add market close to positions table (#365)
* add market close to positions table * fix variable reference * use secondary buttons
This commit is contained in:
parent
dd1c0fab1d
commit
f226e210ce
|
@ -1,6 +1,10 @@
|
|||
import { FunctionComponent, useState } from 'react'
|
||||
import useMangoStore from '../stores/useMangoStore'
|
||||
import { PerpMarket, ZERO_BN } from '@blockworks-foundation/mango-client'
|
||||
import {
|
||||
MarketConfig,
|
||||
PerpMarket,
|
||||
ZERO_BN,
|
||||
} from '@blockworks-foundation/mango-client'
|
||||
import Button, { LinkButton } from './Button'
|
||||
import { notify } from '../utils/notifications'
|
||||
import Loading from './Loading'
|
||||
|
@ -12,26 +16,26 @@ import { useWallet } from '@solana/wallet-adapter-react'
|
|||
interface MarketCloseModalProps {
|
||||
onClose: () => void
|
||||
isOpen: boolean
|
||||
market: PerpMarket
|
||||
marketIndex: number
|
||||
position: {
|
||||
marketConfig: MarketConfig
|
||||
perpMarket: PerpMarket
|
||||
}
|
||||
}
|
||||
|
||||
const MarketCloseModal: FunctionComponent<MarketCloseModalProps> = ({
|
||||
onClose,
|
||||
isOpen,
|
||||
market,
|
||||
marketIndex,
|
||||
position,
|
||||
}) => {
|
||||
const { t } = useTranslation('common')
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const { wallet } = useWallet()
|
||||
const actions = useMangoStore((s) => s.actions)
|
||||
const config = useMangoStore.getState().selectedMarket.config
|
||||
const { marketConfig, perpMarket } = position
|
||||
|
||||
async function handleMarketClose() {
|
||||
const mangoAccount = useMangoStore.getState().selectedMangoAccount.current
|
||||
const mangoGroup = useMangoStore.getState().selectedMangoGroup.current
|
||||
const marketConfig = useMangoStore.getState().selectedMarket.config
|
||||
const mangoClient = useMangoStore.getState().connection.client
|
||||
const askInfo =
|
||||
useMangoStore.getState().accountInfos[marketConfig.asksKey.toString()]
|
||||
|
@ -51,11 +55,11 @@ const MarketCloseModal: FunctionComponent<MarketCloseModalProps> = ({
|
|||
setSubmitting(true)
|
||||
|
||||
try {
|
||||
const perpAccount = mangoAccount.perpAccounts[marketIndex]
|
||||
const perpAccount = mangoAccount.perpAccounts[marketConfig.marketIndex]
|
||||
const side = perpAccount.basePosition.gt(ZERO_BN) ? 'sell' : 'buy'
|
||||
// send a large size to ensure we are reducing the entire position
|
||||
const size =
|
||||
Math.abs(market.baseLotsToNumber(perpAccount.basePosition)) * 2
|
||||
Math.abs(perpMarket.baseLotsToNumber(perpAccount.basePosition)) * 2
|
||||
|
||||
// hard coded for now; market orders are very dangerous and fault prone
|
||||
const maxSlippage: number | undefined = 0.025
|
||||
|
@ -63,7 +67,7 @@ const MarketCloseModal: FunctionComponent<MarketCloseModalProps> = ({
|
|||
const txid = await mangoClient.placePerpOrder2(
|
||||
mangoGroup,
|
||||
mangoAccount,
|
||||
market,
|
||||
perpMarket,
|
||||
wallet?.adapter,
|
||||
side,
|
||||
referencePrice * (1 + (side === 'buy' ? 1 : -1) * maxSlippage),
|
||||
|
@ -93,9 +97,9 @@ const MarketCloseModal: FunctionComponent<MarketCloseModalProps> = ({
|
|||
|
||||
return (
|
||||
<Modal onClose={onClose} isOpen={isOpen}>
|
||||
<div className="pb-2 text-lg text-th-fgd-1">
|
||||
{t('close-confirm', { config_name: config.name })}
|
||||
</div>
|
||||
<h2 className="mb-2">
|
||||
{t('close-confirm', { config_name: marketConfig.name })}
|
||||
</h2>
|
||||
<div className="pb-6 text-th-fgd-3">{t('price-expect')}</div>
|
||||
<div className="flex items-center">
|
||||
<Button onClick={handleMarketClose}>
|
||||
|
|
|
@ -390,6 +390,7 @@ export default function MarketPosition() {
|
|||
<Button
|
||||
onClick={() => setShowMarketCloseModal(true)}
|
||||
className="mt-2.5 w-full"
|
||||
primary={false}
|
||||
>
|
||||
<span>{t('market-close')}</span>
|
||||
</Button>
|
||||
|
@ -399,8 +400,7 @@ export default function MarketPosition() {
|
|||
<MarketCloseModal
|
||||
isOpen={showMarketCloseModal}
|
||||
onClose={handleCloseWarning}
|
||||
market={selectedMarket}
|
||||
marketIndex={marketIndex}
|
||||
position={{ marketConfig: marketConfig, perpMarket: selectedMarket }}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
|
|
|
@ -143,7 +143,7 @@ const DesktopTable = ({
|
|||
)} $${order.triggerPrice.toFixed(2)}`}
|
||||
</Td>
|
||||
<Td className="w-[14.286%]">
|
||||
<div className={`flex justify-end space-x-3`}>
|
||||
<div className={`flex justify-end space-x-2`}>
|
||||
{editOrderIndex !== index ? (
|
||||
<>
|
||||
{!order.perpTrigger ? (
|
||||
|
@ -157,6 +157,7 @@ const DesktopTable = ({
|
|||
<Button
|
||||
onClick={() => handleCancelOrder(order, market.account)}
|
||||
className="-my-1 h-7 pt-0 pb-0 pl-3 pr-3 text-xs"
|
||||
primary={false}
|
||||
>
|
||||
{cancelledOrderId + '' === order.orderId + '' ? (
|
||||
<Loading />
|
||||
|
@ -170,6 +171,7 @@ const DesktopTable = ({
|
|||
<Button
|
||||
onClick={() => handleCancelAllOrders(market.account)}
|
||||
className="-my-1 h-7 pt-0 pb-0 pl-3 pr-3 text-xs text-th-red"
|
||||
primary={false}
|
||||
>
|
||||
{t('cancel-all') + ' ' + market.config.name}
|
||||
</Button>
|
||||
|
@ -335,9 +337,7 @@ const MobileTable = ({
|
|||
/>
|
||||
</div>
|
||||
<Button
|
||||
className={`${
|
||||
index % 2 === 0 ? 'bg-th-bkg-4' : 'bg-th-bkg-3'
|
||||
} mt-4 h-8 pt-0 pb-0 pl-3 pr-3 text-xs`}
|
||||
className={`mt-4 h-8 pt-0 pb-0 pl-3 pr-3 text-xs`}
|
||||
onClick={() =>
|
||||
handleModifyOrder(
|
||||
order,
|
||||
|
|
|
@ -5,7 +5,7 @@ import { useTranslation } from 'next-i18next'
|
|||
import { ExclamationIcon } from '@heroicons/react/solid'
|
||||
import { ZERO_I80F48 } from '@blockworks-foundation/mango-client'
|
||||
import useMangoStore from '../stores/useMangoStore'
|
||||
import { LinkButton } from '../components/Button'
|
||||
import Button, { LinkButton } from '../components/Button'
|
||||
import { useViewport } from '../hooks/useViewport'
|
||||
import { breakpoints } from './TradePageGrid'
|
||||
import { ExpandableRow, Table, Td, Th, TrBody, TrHead } from './TableElements'
|
||||
|
@ -33,6 +33,7 @@ const PositionsTable: React.FC = () => {
|
|||
const { t } = useTranslation('common')
|
||||
const [showShareModal, setShowShareModal] = useState(false)
|
||||
const [showMarketCloseModal, setShowMarketCloseModal] = useState(false)
|
||||
const [positionToClose, setPositionToClose] = useState<any>(null)
|
||||
const [positionToShare, setPositionToShare] = useState<any>(null)
|
||||
const [settleSinglePos, setSettleSinglePos] = useState(null)
|
||||
|
||||
|
@ -61,8 +62,20 @@ const PositionsTable: React.FC = () => {
|
|||
}
|
||||
}, [openPositions])
|
||||
|
||||
useEffect(() => {
|
||||
if (positionToClose) {
|
||||
const updatedPosition = openPositions.find(
|
||||
(p) => p.marketConfig === positionToClose.marketConfig
|
||||
)
|
||||
if (updatedPosition) {
|
||||
setPositionToClose(updatedPosition)
|
||||
}
|
||||
}
|
||||
}, [openPositions])
|
||||
|
||||
const handleCloseWarning = useCallback(() => {
|
||||
setShowMarketCloseModal(false)
|
||||
setPositionToClose(null)
|
||||
}, [])
|
||||
|
||||
const handleSizeClick = (size, indexPrice) => {
|
||||
|
@ -87,6 +100,11 @@ const PositionsTable: React.FC = () => {
|
|||
setShowShareModal(true)
|
||||
}
|
||||
|
||||
const handleShowMarketCloseModal = (position) => {
|
||||
setPositionToClose(position)
|
||||
setShowMarketCloseModal(true)
|
||||
}
|
||||
|
||||
const handleSettlePnl = async (perpMarket, perpAccount, index) => {
|
||||
if (wallet) {
|
||||
setSettleSinglePos(index)
|
||||
|
@ -177,7 +195,6 @@ const PositionsTable: React.FC = () => {
|
|||
<Th>{t('market')}</Th>
|
||||
<Th>{t('side')}</Th>
|
||||
<Th>{t('position-size')}</Th>
|
||||
<Th>{t('notional-size')}</Th>
|
||||
<Th>{t('average-entry')}</Th>
|
||||
<Th>{t('break-even')}</Th>
|
||||
<Th>{t('estimated-liq-price')}</Th>
|
||||
|
@ -260,15 +277,18 @@ const PositionsTable: React.FC = () => {
|
|||
handleSizeClick(basePosition, indexPrice)
|
||||
}
|
||||
>
|
||||
{`${basePositionUi} ${marketConfig.baseSymbol}`}
|
||||
{`${basePositionUi} (${formatUsdValue(
|
||||
Math.abs(notionalSize)
|
||||
)})`}
|
||||
</span>
|
||||
) : (
|
||||
<span>
|
||||
{`${basePositionUi} ${marketConfig.baseSymbol}`}
|
||||
{`${basePositionUi} (${formatUsdValue(
|
||||
Math.abs(notionalSize)
|
||||
)})`}
|
||||
</span>
|
||||
)}
|
||||
</Td>
|
||||
<Td>{formatUsdValue(Math.abs(notionalSize))}</Td>
|
||||
<Td>
|
||||
{avgEntryPrice
|
||||
? formatUsdValue(avgEntryPrice)
|
||||
|
@ -322,23 +342,28 @@ const PositionsTable: React.FC = () => {
|
|||
)}
|
||||
</Td>
|
||||
<Td>
|
||||
<LinkButton
|
||||
onClick={() =>
|
||||
handleShowShare(openPositions[index])
|
||||
}
|
||||
disabled={!avgEntryPrice ? true : false}
|
||||
>
|
||||
<TwitterIcon className="h-4 w-4" />
|
||||
</LinkButton>
|
||||
<div className="flex items-center space-x-3">
|
||||
<Button
|
||||
className="h-8 pt-0 pb-0 pl-3 pr-3 text-xs"
|
||||
primary={false}
|
||||
onClick={() =>
|
||||
handleShowMarketCloseModal(
|
||||
openPositions[index]
|
||||
)
|
||||
}
|
||||
>
|
||||
{t('market-close')}
|
||||
</Button>
|
||||
<LinkButton
|
||||
onClick={() =>
|
||||
handleShowShare(openPositions[index])
|
||||
}
|
||||
disabled={!avgEntryPrice ? true : false}
|
||||
>
|
||||
<TwitterIcon className="h-4 w-4" />
|
||||
</LinkButton>
|
||||
</div>
|
||||
</Td>
|
||||
{showMarketCloseModal ? (
|
||||
<MarketCloseModal
|
||||
isOpen={showMarketCloseModal}
|
||||
onClose={handleCloseWarning}
|
||||
market={perpMarket}
|
||||
marketIndex={marketConfig.marketIndex}
|
||||
/>
|
||||
) : null}
|
||||
</TrBody>
|
||||
)
|
||||
}
|
||||
|
@ -489,6 +514,19 @@ const PositionsTable: React.FC = () => {
|
|||
? usdFormatter(liquidationPrice)
|
||||
: 'N/A'}
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Button
|
||||
className="w-full"
|
||||
primary={false}
|
||||
onClick={() =>
|
||||
handleShowMarketCloseModal(
|
||||
openPositions[index]
|
||||
)
|
||||
}
|
||||
>
|
||||
{t('market-close')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
@ -513,6 +551,13 @@ const PositionsTable: React.FC = () => {
|
|||
position={positionToShare!}
|
||||
/>
|
||||
) : null}
|
||||
{showMarketCloseModal ? (
|
||||
<MarketCloseModal
|
||||
isOpen={showMarketCloseModal}
|
||||
onClose={handleCloseWarning}
|
||||
position={positionToClose!}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ const RedeemButtons: React.FC = () => {
|
|||
<Button
|
||||
className="flex h-7 items-center justify-center pt-0 pb-0 pl-3 pr-3 text-xs"
|
||||
onClick={handleSettleAll}
|
||||
primary={false}
|
||||
>
|
||||
{settling ? <Loading /> : t('redeem-all')}
|
||||
</Button>
|
||||
|
|
|
@ -5,7 +5,6 @@ import {
|
|||
createRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
// import { getWeights, MarketConfig } from '@blockworks-foundation/mango-client'
|
||||
import { MarketConfig } from '@blockworks-foundation/mango-client'
|
||||
|
||||
import useMangoStore from '../stores/useMangoStore'
|
||||
|
|
Loading…
Reference in New Issue