2021-12-03 10:03:42 -08:00
|
|
|
import { FunctionComponent, useState } from 'react'
|
2021-09-13 14:14:59 -07:00
|
|
|
import useMangoStore from '../stores/useMangoStore'
|
2021-08-25 11:30:16 -07:00
|
|
|
import { PerpMarket, ZERO_BN } from '@blockworks-foundation/mango-client'
|
2021-08-24 20:15:57 -07:00
|
|
|
import Button, { LinkButton } from './Button'
|
|
|
|
import { notify } from '../utils/notifications'
|
|
|
|
import Loading from './Loading'
|
2021-10-05 17:46:15 -07:00
|
|
|
import { sleep } from '../utils'
|
2021-08-24 20:15:57 -07:00
|
|
|
import Modal from './Modal'
|
2021-10-20 05:42:40 -07:00
|
|
|
import { useTranslation } from 'next-i18next'
|
2021-08-24 20:15:57 -07:00
|
|
|
|
|
|
|
interface MarketCloseModalProps {
|
|
|
|
onClose: () => void
|
|
|
|
isOpen: boolean
|
|
|
|
market: PerpMarket
|
2021-08-25 11:30:16 -07:00
|
|
|
marketIndex: number
|
2021-08-24 20:15:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
const MarketCloseModal: FunctionComponent<MarketCloseModalProps> = ({
|
|
|
|
onClose,
|
|
|
|
isOpen,
|
|
|
|
market,
|
2021-08-25 11:30:16 -07:00
|
|
|
marketIndex,
|
2021-08-24 20:15:57 -07:00
|
|
|
}) => {
|
2021-10-20 05:42:40 -07:00
|
|
|
const { t } = useTranslation('common')
|
2021-08-24 20:15:57 -07:00
|
|
|
const [submitting, setSubmitting] = useState(false)
|
|
|
|
const actions = useMangoStore((s) => s.actions)
|
2021-09-13 14:14:59 -07:00
|
|
|
const mangoClient = useMangoStore((s) => s.connection.client)
|
2021-08-25 11:30:16 -07:00
|
|
|
const config = useMangoStore.getState().selectedMarket.config
|
|
|
|
|
|
|
|
async function handleMarketClose() {
|
2021-08-24 20:15:57 -07:00
|
|
|
const mangoAccount = useMangoStore.getState().selectedMangoAccount.current
|
|
|
|
const mangoGroup = useMangoStore.getState().selectedMangoGroup.current
|
2021-11-30 09:27:27 -08:00
|
|
|
const marketConfig = useMangoStore.getState().selectedMarket.config
|
|
|
|
const askInfo =
|
|
|
|
useMangoStore.getState().accountInfos[marketConfig.asksKey.toString()]
|
|
|
|
const bidInfo =
|
|
|
|
useMangoStore.getState().accountInfos[marketConfig.bidsKey.toString()]
|
2021-08-24 20:15:57 -07:00
|
|
|
const wallet = useMangoStore.getState().wallet.current
|
|
|
|
|
2021-12-03 10:03:42 -08:00
|
|
|
const orderbook = useMangoStore.getState().selectedMarket.orderBook
|
|
|
|
const markPrice = useMangoStore.getState().selectedMarket.markPrice
|
2022-02-14 18:32:31 -08:00
|
|
|
const referrerPk = useMangoStore.getState().referrerPk
|
2021-12-03 10:03:42 -08:00
|
|
|
|
|
|
|
// The reference price is the book mid if book is double sided; else mark price
|
|
|
|
const bb = orderbook?.bids?.length > 0 && Number(orderbook.bids[0][0])
|
|
|
|
const ba = orderbook?.asks?.length > 0 && Number(orderbook.asks[0][0])
|
|
|
|
const referencePrice = bb && ba ? (bb + ba) / 2 : markPrice
|
|
|
|
|
2021-08-24 20:15:57 -07:00
|
|
|
if (!wallet || !mangoGroup || !mangoAccount) return
|
|
|
|
setSubmitting(true)
|
|
|
|
|
|
|
|
try {
|
2021-10-05 16:30:10 -07:00
|
|
|
const perpAccount = mangoAccount.perpAccounts[marketIndex]
|
2021-09-04 09:40:43 -07:00
|
|
|
const side = perpAccount.basePosition.gt(ZERO_BN) ? 'sell' : 'buy'
|
2021-10-05 16:30:10 -07:00
|
|
|
// send a large size to ensure we are reducing the entire position
|
|
|
|
const size =
|
|
|
|
Math.abs(market.baseLotsToNumber(perpAccount.basePosition)) * 2
|
2021-09-04 09:40:43 -07:00
|
|
|
|
2021-12-02 21:15:03 -08:00
|
|
|
// hard coded for now; market orders are very dangerous and fault prone
|
|
|
|
const maxSlippage: number | undefined = 0.025
|
|
|
|
|
2022-02-20 09:52:37 -08:00
|
|
|
const txid = await mangoClient.placePerpOrder2(
|
2021-08-24 20:15:57 -07:00
|
|
|
mangoGroup,
|
|
|
|
mangoAccount,
|
|
|
|
market,
|
|
|
|
wallet,
|
|
|
|
side,
|
2021-12-02 21:15:03 -08:00
|
|
|
referencePrice * (1 + (side === 'buy' ? 1 : -1) * maxSlippage),
|
2021-08-24 20:15:57 -07:00
|
|
|
size,
|
2022-02-20 09:52:37 -08:00
|
|
|
{
|
|
|
|
orderType: 'ioc',
|
|
|
|
bookSideInfo: side === 'buy' ? askInfo : bidInfo,
|
|
|
|
reduceOnly: true,
|
|
|
|
referrerMangoAccountPk: referrerPk ? referrerPk : undefined,
|
|
|
|
}
|
2021-08-24 20:15:57 -07:00
|
|
|
)
|
2021-09-04 09:40:43 -07:00
|
|
|
await sleep(500)
|
|
|
|
actions.reloadMangoAccount()
|
2021-10-20 05:42:40 -07:00
|
|
|
notify({ title: t('transaction-sent'), txid })
|
2021-08-24 20:15:57 -07:00
|
|
|
} catch (e) {
|
|
|
|
notify({
|
2021-10-20 05:42:40 -07:00
|
|
|
title: t('order-error'),
|
2021-08-24 20:15:57 -07:00
|
|
|
description: e.message,
|
|
|
|
txid: e.txid,
|
|
|
|
type: 'error',
|
|
|
|
})
|
|
|
|
} finally {
|
|
|
|
setSubmitting(false)
|
|
|
|
onClose()
|
|
|
|
}
|
|
|
|
}
|
2021-09-04 14:59:53 -07:00
|
|
|
|
2021-08-24 20:15:57 -07:00
|
|
|
return (
|
|
|
|
<Modal onClose={onClose} isOpen={isOpen}>
|
|
|
|
<div className="pb-2 text-th-fgd-1 text-lg">
|
2021-10-20 05:42:40 -07:00
|
|
|
{t('close-confirm', { config_name: config.name })}
|
2021-08-24 20:15:57 -07:00
|
|
|
</div>
|
2021-10-20 05:42:40 -07:00
|
|
|
<div className="pb-6 text-th-fgd-3">{t('price-expect')}</div>
|
2021-08-24 20:15:57 -07:00
|
|
|
<div className="flex items-center">
|
2021-08-25 11:30:16 -07:00
|
|
|
<Button onClick={handleMarketClose}>
|
2021-10-20 05:42:40 -07:00
|
|
|
{submitting ? <Loading /> : <span>{t('close-position')}</span>}
|
2021-08-24 20:15:57 -07:00
|
|
|
</Button>
|
|
|
|
<LinkButton className="ml-4 text-th-fgd-1" onClick={onClose}>
|
2021-10-20 05:42:40 -07:00
|
|
|
{t('cancel')}
|
2021-08-24 20:15:57 -07:00
|
|
|
</LinkButton>
|
|
|
|
</div>
|
|
|
|
</Modal>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
export default MarketCloseModal
|