mango-ui-v3/components/CloseAccountModal.tsx

232 lines
7.2 KiB
TypeScript
Raw Normal View History

2021-11-09 07:58:29 -08:00
import {
2021-11-08 08:42:55 -08:00
FunctionComponent,
useCallback,
useEffect,
useMemo,
useState,
} from 'react'
2021-11-09 11:19:07 -08:00
import useMangoStore, { MNGO_INDEX } from '../stores/useMangoStore'
2022-01-17 15:56:23 -08:00
import {
CheckCircleIcon,
ExclamationCircleIcon,
} from '@heroicons/react/outline'
2021-11-08 08:42:55 -08:00
import Button from './Button'
import Modal from './Modal'
import { ElementTitle } from './styles'
import { notify } from '../utils/notifications'
2022-01-18 10:16:18 -08:00
import { useTranslation } from 'next-i18next'
2021-11-08 08:42:55 -08:00
import {
getMultipleAccounts,
nativeToUi,
zeroKey,
ZERO_BN,
ZERO_I80F48,
} from '@blockworks-foundation/mango-client'
2021-12-20 06:05:35 -08:00
import { formatUsdValue } from '../utils'
2021-11-08 08:42:55 -08:00
interface CloseAccountModalProps {
lamports?: number
isOpen: boolean
onClose?: (x?) => void
}
const CloseAccountModal: FunctionComponent<CloseAccountModalProps> = ({
isOpen,
onClose,
}) => {
2022-01-18 10:16:18 -08:00
const { t } = useTranslation(['common', 'close-account'])
2021-11-08 08:42:55 -08:00
const mangoGroup = useMangoStore((s) => s.selectedMangoGroup.current)
const mangoAccount = useMangoStore((s) => s.selectedMangoAccount.current)
const mangoCache = useMangoStore((s) => s.selectedMangoGroup.cache)
2022-01-27 19:57:18 -08:00
const openPositions = useMangoStore(
(s) => s.selectedMangoAccount.openPerpPositions
)
const unsettledPositions = useMangoStore(
(s) => s.selectedMangoAccount.unsettledPerpPositions
)
2021-11-08 08:42:55 -08:00
const [hasBorrows, setHasBorrows] = useState(false)
const [hasOpenPositions, setHasOpenPositions] = useState(false)
const [totalAccountSOL, setTotalAccountSOL] = useState(0)
const actions = useMangoStore((s) => s.actions)
const connection = useMangoStore((s) => s.connection.current)
const client = useMangoStore((s) => s.connection.client)
2022-01-27 08:57:36 -08:00
const openOrders = useMangoStore((s) => s.selectedMangoAccount.openOrders)
2021-11-09 07:58:29 -08:00
const setMangoStore = useMangoStore((s) => s.set)
2021-11-08 08:42:55 -08:00
const fetchTotalAccountSOL = useCallback(async () => {
if (!mangoAccount) {
return
}
const accountKeys = [
mangoAccount.publicKey,
...mangoAccount.spotOpenOrders.filter((oo) => !oo.equals(zeroKey)),
...(!mangoAccount.advancedOrdersKey.equals(zeroKey)
? [mangoAccount.advancedOrdersKey]
: []),
]
const accounts = await getMultipleAccounts(connection, accountKeys)
const lamports =
accounts.reduce((total, account) => {
return total + account.accountInfo.lamports
}, 0) * 0.000000001
setTotalAccountSOL(lamports)
}, [mangoAccount])
useEffect(() => {
if (mangoAccount) {
if (mangoAccount.borrows.some((b) => b.gt(ZERO_I80F48))) {
setHasBorrows(true)
}
if (openPositions.length || unsettledPositions.length) {
setHasOpenPositions(true)
}
}
fetchTotalAccountSOL()
}, [mangoAccount])
const mngoAccrued = useMemo(() => {
return mangoAccount
? mangoAccount.perpAccounts.reduce((acc, perpAcct) => {
return perpAcct.mngoAccrued.add(acc)
}, ZERO_BN)
: ZERO_BN
}, [mangoAccount])
const closeAccount = async () => {
const wallet = useMangoStore.getState().wallet.current
try {
const txids = await client.emptyAndCloseMangoAccount(
2021-11-09 11:19:07 -08:00
mangoGroup,
mangoAccount,
mangoCache,
2021-11-10 09:33:15 -08:00
MNGO_INDEX,
2021-11-09 11:19:07 -08:00
wallet
2021-11-08 08:42:55 -08:00
)
await actions.fetchAllMangoAccounts()
const mangoAccounts = useMangoStore.getState().mangoAccounts
2021-11-09 07:58:29 -08:00
setMangoStore((state) => {
state.selectedMangoAccount.current = mangoAccounts.length
? mangoAccounts[0]
: null
2021-11-09 07:58:29 -08:00
})
2021-11-08 08:42:55 -08:00
onClose()
for (const txid of txids) {
notify({
title: t('close-account:transaction-confirmed'),
txid,
})
}
2021-11-08 08:42:55 -08:00
} catch (err) {
console.warn('Error deleting account:', err)
notify({
title: t('close-account:error-deleting-account'),
description: `${err.message}`,
2021-11-08 08:42:55 -08:00
txid: err.txid,
type: 'error',
})
}
}
2022-01-17 15:56:23 -08:00
const isDisabled =
(openOrders && openOrders.length > 0) || hasBorrows || hasOpenPositions
2021-11-08 08:42:55 -08:00
return (
<Modal onClose={onClose} isOpen={isOpen && mangoAccount !== undefined}>
2022-02-20 19:55:13 -08:00
<Modal.Header>
<ElementTitle noMarginBottom>
{t('close-account:are-you-sure')}
</ElementTitle>
<p className="mt-1 text-center">
{t('close-account:closing-account-will')}
</p>
</Modal.Header>
2022-01-17 15:56:23 -08:00
<div className="bg-th-bkg-4 overflow-wrap p-2 sm:p-4 rounded-md space-y-2">
2021-11-08 08:42:55 -08:00
<div className="flex items-center text-th-fgd-2">
<CheckCircleIcon className="h-4 w-4 mr-1.5 text-th-green" />
{t('close-account:delete-your-account')}
2021-11-08 08:42:55 -08:00
</div>
{mangoAccount &&
mangoAccount.getAssetsVal(mangoGroup, mangoCache).gt(ZERO_I80F48) ? (
2022-01-17 15:56:23 -08:00
<div className="flex items-center text-th-fgd-2">
2021-11-08 08:42:55 -08:00
<CheckCircleIcon className="h-4 w-4 mr-1.5 text-th-green" />
2022-01-18 10:16:18 -08:00
{t('close-account:withdraw-assets-worth', {
2022-01-18 12:55:11 -08:00
value: formatUsdValue(
+mangoAccount.computeValue(mangoGroup, mangoCache)
),
2022-01-18 10:16:18 -08:00
})}
2021-11-08 08:42:55 -08:00
</div>
) : (
''
)}
2022-01-17 15:56:23 -08:00
<div className="flex items-center text-th-fgd-2">
2021-11-08 08:42:55 -08:00
<CheckCircleIcon className="h-4 w-4 mr-1.5 text-th-green" />
{t('close-account:recover-x-sol', {
amount: totalAccountSOL.toFixed(3),
})}
2021-11-08 08:42:55 -08:00
</div>
{!mngoAccrued.isZero() ? (
2022-01-17 15:56:23 -08:00
<div className="flex items-center text-th-fgd-2">
2021-11-08 08:42:55 -08:00
<CheckCircleIcon className="h-4 w-4 mr-1.5 text-th-green" />
{t('close-account:claim-x-mngo', {
amount: mangoGroup
? nativeToUi(
mngoAccrued.toNumber(),
mangoGroup.tokens[MNGO_INDEX].decimals
).toFixed(3)
: 0,
})}
2021-11-08 08:42:55 -08:00
</div>
) : (
''
)}
</div>
2022-01-17 15:56:23 -08:00
{isDisabled ? (
<>
<h3 className="text-center my-3">
{t('close-account:before-you-continue')}
</h3>
2022-01-17 15:56:23 -08:00
<div className="bg-th-bkg-4 overflow-none p-2 sm:p-4 rounded-md space-y-2">
{hasBorrows ? (
<div className="flex items-center text-th-fgd-2">
<ExclamationCircleIcon className="h-4 w-4 mr-1.5 text-th-red" />
{t('close-account:close-all-borrows')}
2022-01-17 15:56:23 -08:00
</div>
) : null}
{hasOpenPositions ? (
<div className="flex items-center text-th-fgd-2">
<ExclamationCircleIcon className="h-4 w-4 mr-1.5 text-th-red" />
{t('close-account:close-perp-positions')}
2022-01-17 15:56:23 -08:00
</div>
) : null}
{openOrders && openOrders.length ? (
<div className="flex items-center text-th-fgd-2">
<ExclamationCircleIcon className="h-4 w-4 mr-1.5 text-th-red" />
{t('close-account:close-open-orders')}
2022-01-17 15:56:23 -08:00
</div>
) : null}
</div>
</>
) : null}
{!isDisabled ? (
<div className="text-th-fgd-2 text-center mt-4">
{t('close-account:goodbye')}
</div>
2022-01-17 15:56:23 -08:00
) : null}
2021-11-08 08:42:55 -08:00
<Button
onClick={() => closeAccount()}
2022-01-17 15:56:23 -08:00
disabled={isDisabled}
className="mt-6 w-full"
2021-11-08 08:42:55 -08:00
>
2022-01-18 10:16:18 -08:00
{t('close-account:close-account')}
2021-11-08 08:42:55 -08:00
</Button>
</Modal>
)
}
export default CloseAccountModal