import { I80F48, nativeI80F48ToUi, nativeToUi, QUOTE_INDEX, ZERO_BN, ZERO_I80F48, } from '@blockworks-foundation/mango-client' import { useCallback, useState } from 'react' import { ExclamationIcon, ExternalLinkIcon, HeartIcon, } from '@heroicons/react/solid' import { BellIcon } from '@heroicons/react/outline' import useMangoStore, { MNGO_INDEX } from '../stores/useMangoStore' import { abbreviateAddress, formatUsdValue, usdFormatter } from '../utils' import { notify } from '../utils/notifications' import { IconButton, LinkButton } from './Button' import { ElementTitle } from './styles' import Tooltip from './Tooltip' import DepositModal from './DepositModal' import WithdrawModal from './WithdrawModal' import Button from './Button' import { DataLoader } from './MarketPosition' import { useViewport } from '../hooks/useViewport' import { breakpoints } from './TradePageGrid' import { useTranslation } from 'next-i18next' import useMangoAccount from '../hooks/useMangoAccount' import Loading from './Loading' import CreateAlertModal from './CreateAlertModal' const I80F48_100 = I80F48.fromString('100') export default function AccountInfo() { const { t } = useTranslation('common') const connected = useMangoStore((s) => s.wallet.connected) const mangoGroup = useMangoStore((s) => s.selectedMangoGroup.current) const mangoCache = useMangoStore((s) => s.selectedMangoGroup.cache) const { mangoAccount, initialLoad } = useMangoAccount() const marketConfig = useMangoStore((s) => s.selectedMarket.config) const mangoClient = useMangoStore((s) => s.connection.client) const wallet = useMangoStore((s) => s.wallet.current) const actions = useMangoStore((s) => s.actions) const { width } = useViewport() const isMobile = width ? width < breakpoints.sm : false const [redeeming, setRedeeming] = useState(false) const [showDepositModal, setShowDepositModal] = useState(false) const [showWithdrawModal, setShowWithdrawModal] = useState(false) const [showAlertsModal, setShowAlertsModal] = useState(false) const canWithdraw = mangoAccount?.owner.equals(wallet.publicKey) const handleCloseDeposit = useCallback(() => { setShowDepositModal(false) }, []) const handleCloseWithdraw = useCallback(() => { setShowWithdrawModal(false) }, []) const handleCloseAlerts = useCallback(() => { setShowAlertsModal(false) }, []) const equity = mangoAccount ? mangoAccount.computeValue(mangoGroup, mangoCache) : ZERO_I80F48 const mngoAccrued = mangoAccount ? mangoAccount.perpAccounts.reduce((acc, perpAcct) => { return perpAcct.mngoAccrued.add(acc) }, ZERO_BN) : ZERO_BN // console.log('rerendering account info', mangoAccount, mngoAccrued.toNumber()) const handleRedeemMngo = async () => { const wallet = useMangoStore.getState().wallet.current const mngoNodeBank = mangoGroup.rootBankAccounts[MNGO_INDEX].nodeBankAccounts[0] try { setRedeeming(true) const txid = await mangoClient.redeemAllMngo( mangoGroup, mangoAccount, wallet, mangoGroup.tokens[MNGO_INDEX].rootBank, mngoNodeBank.publicKey, mngoNodeBank.vault ) notify({ title: t('redeem-success'), description: '', txid, }) } catch (e) { notify({ title: t('redeem-failure'), description: e.message, txid: e.txid, type: 'error', }) } finally { actions.reloadMangoAccount() setRedeeming(false) } } const maintHealthRatio = mangoAccount ? mangoAccount.getHealthRatio(mangoGroup, mangoCache, 'Maint') : I80F48_100 const initHealthRatio = mangoAccount ? mangoAccount.getHealthRatio(mangoGroup, mangoCache, 'Init') : I80F48_100 const maintHealth = mangoAccount ? mangoAccount.getHealth(mangoGroup, mangoCache, 'Maint') : I80F48_100 const initHealth = mangoAccount ? mangoAccount.getHealth(mangoGroup, mangoCache, 'Init') : I80F48_100 const liquidationPrice = mangoGroup && mangoAccount && marketConfig ? mangoAccount.getLiquidationPrice( mangoGroup, mangoCache, marketConfig.marketIndex ) : undefined return ( <>
{!isMobile ? ( mangoAccount ? (
{t('init-health')}: {initHealth.toFixed(4)}
{t('maint-health')}: {maintHealth.toFixed(4)}
) : ( '' ) } > {t('account')} setShowAlertsModal(true)}>
) : ( {t('account')} ) ) : null}
{mangoAccount ? (
{abbreviateAddress(mangoAccount.publicKey, 6)}
) : null}
{t('equity')}
{initialLoad ? : formatUsdValue(+equity)}
{t('leverage')}
{initialLoad ? ( ) : mangoAccount ? ( `${mangoAccount .getLeverage(mangoGroup, mangoCache) .toFixed(2)}x` ) : ( '0.00x' )}
{t('collateral-available')}
{initialLoad ? ( ) : mangoAccount ? ( usdFormatter( nativeI80F48ToUi( initHealth, mangoGroup.tokens[QUOTE_INDEX].decimals ).toFixed() ) ) : ( '--' )}
{marketConfig.name} {t('margin-available')}
{mangoAccount ? usdFormatter( nativeI80F48ToUi( mangoAccount.getMarketMarginAvailable( mangoGroup, mangoCache, marketConfig.marketIndex, marketConfig.kind ), mangoGroup.tokens[QUOTE_INDEX].decimals ).toFixed() ) : '0.00'}
{marketConfig.name} {t('estimated-liq-price')}
{liquidationPrice && liquidationPrice.gt(ZERO_I80F48) ? usdFormatter(liquidationPrice) : 'N/A'}
{t('tooltip-earn-mngo')}{' '} {t('learn-more')}
} >
{t('mngo-rewards')}
{initialLoad ? ( ) : mangoGroup ? ( nativeToUi( mngoAccrued.toNumber(), mangoGroup.tokens[MNGO_INDEX].decimals ) ) : ( 0 )} {redeeming ? ( ) : ( {t('claim')} )}
} >
{t('health')}
30 ? 'bg-th-green' : initHealthRatio.toNumber() > 0 ? 'bg-th-orange' : 'bg-th-red' }`} >
{maintHealthRatio.gt(I80F48_100) ? '>100' : maintHealthRatio.toFixed(2)} %
{mangoAccount && mangoAccount.beingLiquidated ? (
{t('being-liquidated')}
) : null}
{showDepositModal && ( )} {showWithdrawModal && ( )} {showAlertsModal && ( )} ) }