import { FunctionComponent, useCallback, useEffect, useMemo, useState, } from 'react' import useMangoStore, { MNGO_INDEX } from '../stores/useMangoStore' import { CheckCircleIcon, ExclamationCircleIcon, } from '@heroicons/react/outline' import Button from './Button' import Modal from './Modal' import { ElementTitle } from './styles' import { notify } from '../utils/notifications' import { useTranslation } from 'next-i18next' import { getMultipleAccounts, nativeToUi, zeroKey, ZERO_BN, ZERO_I80F48, } from '@blockworks-foundation/mango-client' import { formatUsdValue } from '../utils' import { useWallet } from '@solana/wallet-adapter-react' interface CloseAccountModalProps { lamports?: number isOpen: boolean onClose?: (x?) => void } const CloseAccountModal: FunctionComponent = ({ isOpen, onClose, }) => { const { t } = useTranslation(['common', 'close-account']) const { wallet } = useWallet() const mangoGroup = useMangoStore((s) => s.selectedMangoGroup.current) const mangoAccount = useMangoStore((s) => s.selectedMangoAccount.current) const mangoCache = useMangoStore((s) => s.selectedMangoGroup.cache) const openPositions = useMangoStore( (s) => s.selectedMangoAccount.openPerpPositions ) const unsettledPositions = useMangoStore( (s) => s.selectedMangoAccount.unsettledPerpPositions ) 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 openOrders = useMangoStore((s) => s.selectedMangoAccount.openOrders) const setMangoStore = useMangoStore((s) => s.set) const activeAlerts = useMangoStore((s) => s.alerts.activeAlerts) const spotBalances = useMangoStore((s) => s.selectedMangoAccount.spotBalances) const unsettledBalances = spotBalances.filter( (bal) => bal.unsettled && bal.unsettled > 0 ) 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 deleteAlerts = () => { try { for (const alert of activeAlerts) { actions.deleteAlert(alert._id) } } catch (err) { console.warn('Error deleting active alerts:', err) } } const closeAccount = async () => { const mangoClient = useMangoStore.getState().connection.client if (!mangoGroup || !mangoAccount || !mangoCache || !wallet) { return } if (activeAlerts.length > 0) { deleteAlerts() } try { const txids = await mangoClient.emptyAndCloseMangoAccount( mangoGroup, mangoAccount, mangoCache, MNGO_INDEX, wallet.adapter ) await actions.fetchAllMangoAccounts(wallet) const mangoAccounts = useMangoStore.getState().mangoAccounts setMangoStore((state) => { state.selectedMangoAccount.current = mangoAccounts.length ? mangoAccounts[0] : null }) onClose?.() if (txids) { for (const txid of txids) { notify({ title: t('close-account:transaction-confirmed'), txid, }) } } else { notify({ title: t('close-account:error-deleting-account'), description: t('transaction-failed'), type: 'error', }) } } catch (err) { console.warn('Error deleting account:', err) notify({ title: t('close-account:error-deleting-account'), description: `${err.message}`, txid: err.txid, type: 'error', }) } } const isDisabled = (openOrders && openOrders.length > 0) || hasBorrows || hasOpenPositions || !!unsettledBalances.length return ( {t('close-account:are-you-sure')}

{t('close-account:closing-account-will')}

{t('close-account:delete-your-account')}
{mangoAccount && mangoGroup && mangoCache && mangoAccount.getAssetsVal(mangoGroup, mangoCache).gt(ZERO_I80F48) ? (
{t('close-account:withdraw-assets-worth', { value: formatUsdValue( +mangoAccount.computeValue(mangoGroup, mangoCache) ), })}
) : ( '' )}
{t('close-account:recover-x-sol', { amount: totalAccountSOL.toFixed(3), })}
{!mngoAccrued.isZero() ? (
{t('close-account:claim-x-mngo-rewards', { amount: mangoGroup ? nativeToUi( mngoAccrued.toNumber(), mangoGroup.tokens[MNGO_INDEX].decimals ).toFixed(3) : 0, })}
) : ( '' )}
{isDisabled ? ( <>

{t('close-account:before-you-continue')}

{hasBorrows ? (
{t('close-account:close-all-borrows')}
) : null} {hasOpenPositions ? (
{t('close-account:close-perp-positions')}
) : null} {openOrders && openOrders.length ? (
{t('close-account:close-open-orders')}
) : null} {unsettledBalances.length ? (
{t('close-account:settle-balances')}
) : null}
) : null} {!isDisabled ? (
{t('close-account:goodbye')}
) : null}
) } export default CloseAccountModal