mango-ui-v3/components/AccountInfo.tsx

358 lines
12 KiB
TypeScript
Raw Normal View History

2021-08-04 11:31:32 -07:00
import {
2021-08-16 14:35:40 -07:00
I80F48,
nativeI80F48ToUi,
2021-08-04 11:31:32 -07:00
nativeToUi,
2021-08-20 05:50:48 -07:00
QUOTE_INDEX,
2021-08-04 11:31:32 -07:00
ZERO_BN,
ZERO_I80F48,
} from '@blockworks-foundation/mango-client'
2021-09-04 15:20:49 -07:00
import { useCallback, useState } from 'react'
2021-10-27 13:31:45 -07:00
import {
ExclamationIcon,
ExternalLinkIcon,
HeartIcon,
} from '@heroicons/react/solid'
2021-09-13 14:14:59 -07:00
import useMangoStore, { MNGO_INDEX } from '../stores/useMangoStore'
2021-10-27 13:31:45 -07:00
import { abbreviateAddress, formatUsdValue, usdFormatter } from '../utils'
2021-08-04 11:31:32 -07:00
import { notify } from '../utils/notifications'
2021-08-05 11:55:18 -07:00
import { LinkButton } from './Button'
import { ElementTitle } from './styles'
2021-04-16 11:16:31 -07:00
import Tooltip from './Tooltip'
2021-08-16 06:31:25 -07:00
import DepositModal from './DepositModal'
import WithdrawModal from './WithdrawModal'
import Button from './Button'
2021-08-21 06:02:51 -07:00
import { DataLoader } from './MarketPosition'
import { useViewport } from '../hooks/useViewport'
import { breakpoints } from './TradePageGrid'
import { useTranslation } from 'next-i18next'
import useMangoAccount from '../hooks/useMangoAccount'
2021-07-05 08:03:57 -07:00
2021-08-16 14:35:40 -07:00
const I80F48_100 = I80F48.fromString('100')
export default function AccountInfo() {
const { t } = useTranslation('common')
2021-07-22 04:34:03 -07:00
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)
2021-09-13 14:14:59 -07:00
const mangoClient = useMangoStore((s) => s.connection.client)
2021-08-04 11:31:32 -07:00
const actions = useMangoStore((s) => s.actions)
const { width } = useViewport()
const isMobile = width ? width < breakpoints.sm : false
2021-08-16 06:31:25 -07:00
const [showDepositModal, setShowDepositModal] = useState(false)
const [showWithdrawModal, setShowWithdrawModal] = useState(false)
const handleCloseDeposit = useCallback(() => {
setShowDepositModal(false)
}, [])
const handleCloseWithdraw = useCallback(() => {
setShowWithdrawModal(false)
}, [])
2021-07-07 13:38:04 -07:00
const equity = mangoAccount
? mangoAccount.computeValue(mangoGroup, mangoCache)
: ZERO_I80F48
2021-08-05 11:55:18 -07:00
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())
2021-08-04 11:31:32 -07:00
const handleRedeemMngo = async () => {
const wallet = useMangoStore.getState().wallet.current
const mngoNodeBank =
mangoGroup.rootBankAccounts[MNGO_INDEX].nodeBankAccounts[0]
try {
const txid = await mangoClient.redeemAllMngo(
mangoGroup,
mangoAccount,
wallet,
mangoGroup.tokens[MNGO_INDEX].rootBank,
mngoNodeBank.publicKey,
mngoNodeBank.vault
)
notify({
title: t('redeem-success'),
2021-08-04 11:31:32 -07:00
description: '',
txid,
})
} catch (e) {
notify({
title: t('redeem-failure'),
2021-08-04 11:31:32 -07:00
description: e.message,
txid: e.txid,
type: 'error',
})
} finally {
actions.reloadMangoAccount()
2021-08-04 11:31:32 -07:00
}
}
2021-09-04 15:20:49 -07:00
const maintHealthRatio = mangoAccount
? mangoAccount.getHealthRatio(mangoGroup, mangoCache, 'Maint')
: I80F48_100
2021-09-04 15:20:49 -07:00
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
2021-07-05 08:03:57 -07:00
return (
<>
2021-10-31 04:21:22 -07:00
<div
className={!connected && !isMobile ? 'filter blur-sm' : undefined}
2021-11-04 05:25:11 -07:00
id="account-details-tip"
2021-10-31 04:21:22 -07:00
>
{!isMobile ? (
<ElementTitle>
<Tooltip
content={
mangoAccount ? (
<div>
{t('init-health')}: {initHealth.toFixed(4)}
<br />
2021-10-27 13:31:45 -07:00
{t('maint-health')}: {maintHealth.toFixed(4)}
</div>
) : (
''
)
}
>
{t('account')}
</Tooltip>
</ElementTitle>
) : null}
2021-07-22 04:34:03 -07:00
<div>
2021-10-27 13:31:45 -07:00
{mangoAccount ? (
<div className="flex justify-center text-xs -mt-2">
<a
className="flex items-center text-th-fgd-4 hover:text-th-primary"
href={`https://explorer.solana.com/address/${mangoAccount?.publicKey}`}
target="_blank"
rel="noopener noreferrer"
>
{abbreviateAddress(mangoAccount.publicKey, 6)}
<ExternalLinkIcon className={`h-4 w-4 ml-1.5`} />
</a>
</div>
) : null}
2021-07-05 08:03:57 -07:00
<div>
2021-08-20 18:42:59 -07:00
<div className="flex justify-between pb-3">
<div className="font-normal text-th-fgd-3 leading-4">
{t('equity')}
</div>
2021-08-20 06:17:02 -07:00
<div className="text-th-fgd-1">
{initialLoad ? <DataLoader /> : formatUsdValue(+equity)}
2021-08-20 06:17:02 -07:00
</div>
2021-07-06 21:34:21 -07:00
</div>
2021-08-20 18:42:59 -07:00
<div className="flex justify-between pb-3">
<div className="font-normal text-th-fgd-3 leading-4">
{t('leverage')}
</div>
2021-08-14 14:14:43 -07:00
<div className="text-th-fgd-1">
{initialLoad ? (
2021-08-21 06:02:51 -07:00
<DataLoader />
2021-08-20 06:17:02 -07:00
) : mangoAccount ? (
`${mangoAccount
.getLeverage(mangoGroup, mangoCache)
.toFixed(2)}x`
) : (
'0.00x'
)}
2021-08-14 14:14:43 -07:00
</div>
</div>
2021-08-20 18:42:59 -07:00
<div className={`flex justify-between pb-3`}>
2021-08-20 05:50:48 -07:00
<div className="font-normal text-th-fgd-3 leading-4">
{t('collateral-available')}
2021-08-20 05:50:48 -07:00
</div>
<div className={`text-th-fgd-1`}>
{initialLoad ? (
2021-08-21 06:02:51 -07:00
<DataLoader />
) : mangoAccount ? (
usdFormatter(
nativeI80F48ToUi(
initHealth,
mangoGroup.tokens[QUOTE_INDEX].decimals
).toFixed()
)
2021-08-21 06:02:51 -07:00
) : (
'--'
)}
2021-08-20 05:50:48 -07:00
</div>
</div>
<div className={`flex justify-between pb-3`}>
<div className="font-normal text-th-fgd-3 leading-4">
{`${marketConfig.name} ${t('margin-available')}`}
</div>
<div className={`text-th-fgd-1`}>
{mangoAccount
? usdFormatter(
nativeI80F48ToUi(
mangoAccount.getMarketMarginAvailable(
mangoGroup,
mangoCache,
marketConfig.marketIndex,
marketConfig.kind
),
mangoGroup.tokens[QUOTE_INDEX].decimals
).toFixed()
)
: '0.00'}
</div>
</div>
2021-11-14 14:02:30 -08:00
{liquidationPrice && liquidationPrice.gt(ZERO_I80F48) ? (
<div className={`flex justify-between pb-3`}>
<div className="font-normal text-th-fgd-3 leading-4">
{t('estimated-liq-price')}
</div>
<div className={`text-th-fgd-1`}>
{usdFormatter(liquidationPrice)}
</div>
</div>
) : null}
2021-08-20 18:42:59 -07:00
<div className={`flex justify-between pb-3`}>
2021-08-04 12:25:56 -07:00
<Tooltip
content={
<div>
{t('tooltip-earn-mngo')}{' '}
2021-08-04 12:25:56 -07:00
<a
href="https://docs.mango.markets/mango-v3/liquidity-incentives"
target="_blank"
rel="noopener noreferrer"
>
{t('learn-more')}
2021-08-04 12:25:56 -07:00
</a>
</div>
}
>
<div className="cursor-help font-normal text-th-fgd-3 leading-4 border-b border-th-fgd-3 border-dashed border-opacity-20 default-transition hover:border-th-bkg-2">
{t('mngo-rewards')}
2021-08-04 12:25:56 -07:00
</div>
</Tooltip>
2021-08-05 07:07:29 -07:00
<div className={`flex items-center text-th-fgd-1`}>
{initialLoad ? (
2021-08-21 06:02:51 -07:00
<DataLoader />
2021-08-20 06:17:02 -07:00
) : mangoGroup ? (
nativeToUi(
mngoAccrued.toNumber(),
mangoGroup.tokens[MNGO_INDEX].decimals
)
) : (
0
)}
2021-08-05 07:07:29 -07:00
<LinkButton
onClick={handleRedeemMngo}
2021-08-16 06:31:25 -07:00
className="ml-2 text-th-primary text-xs disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:underline"
2021-08-05 07:07:29 -07:00
disabled={mngoAccrued.eq(ZERO_BN)}
>
{t('claim')}
2021-08-05 07:07:29 -07:00
</LinkButton>
2021-08-04 11:31:32 -07:00
</div>
</div>
2021-07-05 08:03:57 -07:00
</div>
<div className="border border-th-bkg-4 rounded flex items-center my-2 sm:my-3 p-2.5">
2021-08-16 06:31:25 -07:00
<div className="flex items-center pr-2">
<HeartIcon
className="h-5 mr-1.5 w-5 text-th-primary"
aria-hidden="true"
/>
<span>
<Tooltip
content={
<div>
{t('tooltip-account-liquidated')}{' '}
2021-08-16 06:31:25 -07:00
<a
href="https://docs.mango.markets/mango-v3/overview#health"
target="_blank"
rel="noopener noreferrer"
>
{t('learn-more')}
2021-08-16 06:31:25 -07:00
</a>
</div>
}
>
<div className="cursor-help font-normal text-th-fgd-3 leading-4 border-b border-th-fgd-3 border-dashed border-opacity-20 default-transition hover:border-th-bkg-2">
{t('health')}
2021-08-16 06:31:25 -07:00
</div>
</Tooltip>
</span>
2021-07-01 07:12:42 -07:00
</div>
2021-08-16 06:31:25 -07:00
<div className="h-1.5 flex flex-grow rounded bg-th-bkg-4">
<div
style={{
width: `${maintHealthRatio}%`,
}}
className={`flex rounded ${
2021-08-16 14:35:40 -07:00
maintHealthRatio.toNumber() > 30
2021-08-16 06:31:25 -07:00
? 'bg-th-green'
2021-08-16 14:35:40 -07:00
: initHealthRatio.toNumber() > 0
2021-08-16 06:31:25 -07:00
? 'bg-th-orange'
: 'bg-th-red'
}`}
></div>
</div>
<div className="pl-2 text-right">
2021-08-16 14:35:40 -07:00
{maintHealthRatio.gt(I80F48_100)
? '>100'
: maintHealthRatio.toFixed(2)}
%
2021-08-16 06:31:25 -07:00
</div>
</div>
2021-10-04 19:14:07 -07:00
{mangoAccount && mangoAccount.beingLiquidated ? (
<div className="pt-0.5 text-xs sm:text-sm flex items-center justify-center">
<ExclamationIcon className="flex-shrink-0 h-5 w-5 mr-1.5 text-th-red" />
<span className="text-th-red">{t('being-liquidated')}</span>
</div>
) : null}
<div className={`grid grid-cols-2 grid-rows-1 gap-4 pt-2 sm:pt-4`}>
2021-08-16 06:31:25 -07:00
<Button
onClick={() => setShowDepositModal(true)}
2021-08-16 06:31:25 -07:00
className="w-full"
disabled={!connected}
>
<span>{t('deposit')}</span>
2021-08-16 06:31:25 -07:00
</Button>
<Button
onClick={() => setShowWithdrawModal(true)}
className="w-full"
disabled={!connected || !mangoAccount}
2021-08-16 06:31:25 -07:00
>
<span>{t('withdraw')}</span>
2021-08-16 06:31:25 -07:00
</Button>
2021-07-05 08:03:57 -07:00
</div>
</div>
</div>
2021-08-16 06:31:25 -07:00
{showDepositModal && (
<DepositModal isOpen={showDepositModal} onClose={handleCloseDeposit} />
)}
{showWithdrawModal && (
<WithdrawModal
isOpen={showWithdrawModal}
onClose={handleCloseWithdraw}
/>
)}
</>
)
}