perp market close modal
This commit is contained in:
parent
2e664b3dfc
commit
458a70fc9d
|
@ -206,7 +206,6 @@ const AdvancedTradeForm = () => {
|
|||
const minOrderDecimals = getDecimalCount(minOrderSize)
|
||||
return [minOrderDecimals, minOrderSize]
|
||||
}, [selectedMarket])
|
||||
console.log(minOrderDecimals, minOrderSize)
|
||||
|
||||
/*
|
||||
* Updates the limit price on page load
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
import { FunctionComponent, useCallback, useState } from 'react'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import {
|
||||
PerpOrderSide,
|
||||
PerpOrderType,
|
||||
PerpPosition,
|
||||
} from '@blockworks-foundation/mango-v4'
|
||||
import Modal from '@components/shared/Modal'
|
||||
import Button, { LinkButton } from '@components/shared/Button'
|
||||
import { calculateEstPriceForBaseSize } from 'utils/tradeForm'
|
||||
import { notify } from 'utils/notifications'
|
||||
import Loading from '@components/shared/Loading'
|
||||
|
||||
interface MarketCloseModalProps {
|
||||
onClose: () => void
|
||||
isOpen: boolean
|
||||
position: PerpPosition
|
||||
}
|
||||
|
||||
const MarketCloseModal: FunctionComponent<MarketCloseModalProps> = ({
|
||||
onClose,
|
||||
isOpen,
|
||||
position,
|
||||
}) => {
|
||||
const { t } = useTranslation('common')
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const group = mangoStore.getState().group
|
||||
const perpMarket = group?.getPerpMarketByMarketIndex(position.marketIndex)
|
||||
|
||||
const handleMarketClose = useCallback(async () => {
|
||||
const client = mangoStore.getState().client
|
||||
const group = mangoStore.getState().group
|
||||
const mangoAccount = mangoStore.getState().mangoAccount.current
|
||||
const actions = mangoStore.getState().actions
|
||||
|
||||
if (!group || !mangoAccount || !perpMarket) return
|
||||
setSubmitting(true)
|
||||
try {
|
||||
const baseSize = position.getBasePositionUi(perpMarket)
|
||||
const sideToClose = baseSize > 0 ? 'sell' : 'buy'
|
||||
const orderbook = mangoStore.getState().selectedMarket.orderbook
|
||||
const price = calculateEstPriceForBaseSize(
|
||||
orderbook,
|
||||
baseSize,
|
||||
sideToClose
|
||||
)
|
||||
|
||||
const maxSlippage = 0.025
|
||||
// const perpOrderType =
|
||||
// tradeForm.tradeType === 'Market'
|
||||
// ? PerpOrderType.market
|
||||
// : tradeForm.ioc
|
||||
// ? PerpOrderType.immediateOrCancel
|
||||
// : tradeForm.postOnly
|
||||
// ? PerpOrderType.postOnly
|
||||
// : PerpOrderType.limit
|
||||
const tx = await client.perpPlaceOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
perpMarket.perpMarketIndex,
|
||||
sideToClose === 'buy' ? PerpOrderSide.bid : PerpOrderSide.ask,
|
||||
price * (sideToClose === 'buy' ? 1 + maxSlippage : 1 - maxSlippage),
|
||||
Math.abs(baseSize) * 2, // send a larger size to ensure full order is closed
|
||||
undefined, // maxQuoteQuantity
|
||||
Date.now(),
|
||||
PerpOrderType.immediateOrCancel,
|
||||
true, // reduce only
|
||||
undefined,
|
||||
undefined
|
||||
)
|
||||
actions.fetchOpenOrders()
|
||||
notify({
|
||||
type: 'success',
|
||||
title: 'Transaction successful',
|
||||
txid: tx,
|
||||
})
|
||||
} catch (e: any) {
|
||||
notify({
|
||||
title: 'There was an issue.',
|
||||
description: e.message,
|
||||
txid: e?.txid,
|
||||
type: 'error',
|
||||
})
|
||||
console.error('Place trade error:', e)
|
||||
} finally {
|
||||
setSubmitting(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Modal onClose={onClose} isOpen={isOpen}>
|
||||
<h3 className="mb-2">
|
||||
{t('close-confirm', { config_name: perpMarket?.name })}
|
||||
</h3>
|
||||
<div className="pb-6 text-th-fgd-3">{t('price-expect')}</div>
|
||||
<div className="flex items-center justify-center">
|
||||
<Button onClick={handleMarketClose}>
|
||||
{submitting ? <Loading /> : <span>Close Position</span>}
|
||||
</Button>
|
||||
<LinkButton className="ml-4 text-th-fgd-1" onClick={onClose}>
|
||||
{t('cancel')}
|
||||
</LinkButton>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
export default MarketCloseModal
|
|
@ -1,5 +1,5 @@
|
|||
import { PerpMarket } from '@blockworks-foundation/mango-v4'
|
||||
import { LinkButton } from '@components/shared/Button'
|
||||
import { PerpMarket, PerpPosition } from '@blockworks-foundation/mango-v4'
|
||||
import Button, { LinkButton } from '@components/shared/Button'
|
||||
import ConnectEmptyState from '@components/shared/ConnectEmptyState'
|
||||
import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements'
|
||||
import { NoSymbolIcon } from '@heroicons/react/20/solid'
|
||||
|
@ -9,6 +9,7 @@ import useMangoAccount from 'hooks/useMangoAccount'
|
|||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { useCallback, useState } from 'react'
|
||||
import {
|
||||
formatDecimal,
|
||||
formatFixedDecimals,
|
||||
|
@ -17,12 +18,17 @@ import {
|
|||
trimDecimals,
|
||||
} from 'utils/numbers'
|
||||
import { calculateLimitPriceForMarketOrder } from 'utils/tradeForm'
|
||||
import MarketCloseModal from './MarketCloseModal'
|
||||
import PerpSideBadge from './PerpSideBadge'
|
||||
import TableMarketName from './TableMarketName'
|
||||
|
||||
const PerpPositions = () => {
|
||||
const { t } = useTranslation(['common', 'trade'])
|
||||
const { group } = useMangoGroup()
|
||||
const [showMarketCloseModal, setShowMarketCloseModal] = useState(false)
|
||||
const [positionToClose, setPositionToClose] = useState<PerpPosition | null>(
|
||||
null
|
||||
)
|
||||
const perpPositions = mangoStore((s) => s.mangoAccount.perpPositions)
|
||||
const { selectedMarket } = useSelectedMarket()
|
||||
const { connected } = useWallet()
|
||||
|
@ -54,6 +60,16 @@ const PerpPositions = () => {
|
|||
})
|
||||
}
|
||||
|
||||
const showClosePositionModal = useCallback((position: PerpPosition) => {
|
||||
setShowMarketCloseModal(true)
|
||||
setPositionToClose(position)
|
||||
}, [])
|
||||
|
||||
const hideClosePositionModal = useCallback(() => {
|
||||
setShowMarketCloseModal(false)
|
||||
setPositionToClose(null)
|
||||
}, [])
|
||||
|
||||
if (!group) return null
|
||||
|
||||
const openPerpPositions = Object.values(perpPositions).filter((p) =>
|
||||
|
@ -141,11 +157,28 @@ const PerpPositions = () => {
|
|||
>
|
||||
<div>{formatFixedDecimals(cummulativePnl, true)}</div>
|
||||
</Td>
|
||||
<Td className={`text-right`}>
|
||||
<Button
|
||||
className="text-xs"
|
||||
secondary
|
||||
size="small"
|
||||
onClick={() => showClosePositionModal(position)}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
</Td>
|
||||
</TrBody>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</Table>
|
||||
{showMarketCloseModal && positionToClose ? (
|
||||
<MarketCloseModal
|
||||
isOpen={showMarketCloseModal}
|
||||
onClose={hideClosePositionModal}
|
||||
position={positionToClose}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
) : connected ? (
|
||||
<div className="flex flex-col items-center p-8">
|
||||
|
|
|
@ -203,9 +203,13 @@ const TradeHistory = () => {
|
|||
market = selectedMarket
|
||||
}
|
||||
let makerTaker = trade.liquidity
|
||||
|
||||
if ('maker' in trade) {
|
||||
makerTaker = trade.maker ? 'Maker' : 'Taker'
|
||||
if (trade.taker === mangoAccount.publicKey.toString()) {
|
||||
if (
|
||||
trade.taker &&
|
||||
trade.taker.toString() === mangoAccount.publicKey.toString()
|
||||
) {
|
||||
makerTaker = 'Taker'
|
||||
}
|
||||
}
|
||||
|
@ -267,7 +271,7 @@ const TradeHistory = () => {
|
|||
)}
|
||||
</Td>
|
||||
{market.name.includes('PERP') ? (
|
||||
<Td>
|
||||
<Td className="xl:!pl-0">
|
||||
<div className="flex justify-end">
|
||||
<Tooltip content="View Counterparty" delay={250}>
|
||||
<a
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"close-account": "Close Account",
|
||||
"close-account-desc": "Are you sure? Closing your account is irreversible",
|
||||
"closing-account": "Closing your account...",
|
||||
"close-confirm": "Are you sure you want to market close your {{config_name}} position?",
|
||||
"collateral-value": "Collateral Value",
|
||||
"connect": "Connect",
|
||||
"connect-balances": "Connect to view your balances",
|
||||
|
@ -93,6 +94,7 @@
|
|||
"perp": "Perp",
|
||||
"pnl": "PnL",
|
||||
"price": "Price",
|
||||
"price-expect": "The price you receive may be worse than you expect and full execution is not guaranteed. Max slippage is 2.5% for your safety. The part of your position with slippage beyond 2.5% will not be closed.",
|
||||
"quantity": "Quantity",
|
||||
"rate": "Rate (APR)",
|
||||
"rates": "Rates (APR)",
|
||||
|
|
Loading…
Reference in New Issue