mango-ui-v3/components/account_page/AccountBorrows.tsx

545 lines
24 KiB
TypeScript
Raw Normal View History

import { useCallback, useState } from 'react'
2021-07-05 08:03:57 -07:00
import {
getTokenBySymbol,
ZERO_I80F48,
2021-09-08 05:47:15 -07:00
I80F48,
2021-07-05 08:03:57 -07:00
} from '@blockworks-foundation/mango-client'
import useMangoStore from '../../stores/useMangoStore'
import { useBalances } from '../../hooks/useBalances'
2021-09-01 09:39:17 -07:00
import {
formatUsdValue,
i80f48ToPercent,
tokenPrecision,
} from '../../utils/index'
2021-07-05 11:21:57 -07:00
import WithdrawModal from '../WithdrawModal'
import Button from '../Button'
import DepositModal from '../DepositModal'
2021-09-08 05:47:15 -07:00
import { useViewport } from '../../hooks/useViewport'
import { breakpoints } from '../TradePageGrid'
import { Table, Td, Th, TrBody, TrHead } from '../TableElements'
import { ExpandableRow } from '../TableElements'
import MobileTableHeader from '../mobile/MobileTableHeader'
import { useTranslation } from 'next-i18next'
import { walletSelector } from '../../stores/selectors'
2022-02-23 14:49:02 -08:00
import Tooltip from '../Tooltip'
export default function AccountBorrows() {
const { t } = useTranslation('common')
const balances = useBalances()
2021-07-05 08:03:57 -07:00
const mangoGroup = useMangoStore((s) => s.selectedMangoGroup.current)
const mangoCache = useMangoStore((s) => s.selectedMangoGroup.cache)
const mangoConfig = useMangoStore((s) => s.selectedMangoGroup.config)
2021-09-08 05:47:15 -07:00
const mangoAccount = useMangoStore((s) => s.selectedMangoAccount.current)
const wallet = useMangoStore(walletSelector)
2021-06-23 08:32:33 -07:00
const loadingMangoAccount = useMangoStore(
(s) => s.selectedMangoAccount.initialLoad
)
const connected = useMangoStore((s) => s.wallet.connected)
const [borrowSymbol, setBorrowSymbol] = useState('')
const [depositToSettle, setDepositToSettle] = useState(null)
const [showBorrowModal, setShowBorrowModal] = useState(false)
const [showDepositModal, setShowDepositModal] = useState(false)
2021-09-08 05:47:15 -07:00
const { width } = useViewport()
const isMobile = width ? width < breakpoints.sm : false
2022-02-09 07:48:05 -08:00
const canWithdraw = mangoAccount?.owner.equals(wallet.publicKey)
const handleCloseWithdraw = useCallback(() => {
setShowBorrowModal(false)
}, [])
const handleCloseDeposit = useCallback(() => {
setShowDepositModal(false)
2021-06-07 14:56:56 -07:00
setDepositToSettle(null)
}, [])
const handleShowBorrow = (symbol) => {
setBorrowSymbol(symbol)
setShowBorrowModal(true)
}
2021-11-09 16:34:03 -08:00
const handleShowDeposit = (symbol, amount) => {
setDepositToSettle({ symbol: symbol, amount: amount })
2021-09-08 05:47:15 -07:00
setShowDepositModal(true)
}
return (
<>
2022-02-23 14:49:02 -08:00
{mangoGroup && mangoAccount ? (
<>
<h2 className="mb-2">{t('your-borrows')}</h2>
{/* TODO: calculate LiabsVal without perp markets
<div className="border border-th-red flex items-center justify-between p-2 rounded">
<div className="pr-4 text-xs text-th-fgd-3">{t('total-borrow-value')}:</div>
<span>
2021-08-15 06:31:59 -07:00
{formatUsdValue(+mangoAccount.getLiabsVal(mangoGroup, mangoCache))}
</span>
2021-08-20 03:07:51 -07:00
</div> */}
2022-02-23 14:49:02 -08:00
<div className="flex flex-col pb-8 pt-4">
<div className="overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="align-middle inline-block min-w-full sm:px-6 lg:px-8">
{balances.find((b) => b.borrows.gt(ZERO_I80F48)) ? (
!isMobile ? (
<Table>
<thead>
<TrHead>
<Th>{t('asset')}</Th>
<Th>{t('balance')}</Th>
<Th>{t('value')}</Th>
<Th>{t('borrow-rate')} (APR)</Th>
</TrHead>
</thead>
<tbody>
{balances
.filter((assets) => assets.borrows.gt(ZERO_I80F48))
.map((asset) => {
const token = getTokenBySymbol(
mangoConfig,
asset.symbol
)
const tokenIndex = mangoGroup.getTokenIndex(
token.mintKey
)
return (
<TrBody key={tokenIndex}>
<Td>
<div className="flex items-center">
<img
alt=""
width="20"
height="20"
src={`/assets/icons/${asset.symbol.toLowerCase()}.svg`}
className={`mr-2.5`}
/>
<div>{asset.symbol}</div>
</div>
</Td>
<Td>{asset.borrows.toFixed()}</Td>
<Td>
{formatUsdValue(
asset.borrows
.mul(
mangoGroup.getPrice(
tokenIndex,
mangoCache
)
)
.toNumber()
)}
</Td>
<Td>
<span className={`text-th-red`}>
{(
mangoGroup
.getBorrowRate(tokenIndex)
.toNumber() * 100
).toFixed(2)}
%
</span>
</Td>
<Td>
<div className={`flex justify-end`}>
<Button
onClick={() =>
handleShowDeposit(
asset.symbol,
asset.borrows.toFixed()
)
}
className="ml-3 text-xs pt-0 pb-0 h-8 pl-3 pr-3"
disabled={
!connected || loadingMangoAccount
}
>
{t('repay')}
</Button>
<Button
onClick={() =>
handleShowBorrow(asset.symbol)
}
className="ml-3 text-xs pt-0 pb-0 h-8 pl-3 pr-3"
disabled={
!connected ||
loadingMangoAccount ||
!canWithdraw
}
>
{t('borrow')}
</Button>
</div>
</Td>
</TrBody>
)
})}
</tbody>
</Table>
) : (
<>
<MobileTableHeader
colOneHeader={t('asset')}
colTwoHeader={t('balance')}
/>
2021-09-08 05:47:15 -07:00
{balances
.filter((assets) => assets.borrows.gt(ZERO_I80F48))
2022-02-23 14:49:02 -08:00
.map((asset, i) => {
2021-09-08 05:47:15 -07:00
const token = getTokenBySymbol(
mangoConfig,
asset.symbol
)
const tokenIndex = mangoGroup.getTokenIndex(
token.mintKey
)
return (
2022-02-23 14:49:02 -08:00
<ExpandableRow
buttonTemplate={
<div className="flex items-center justify-between text-fgd-1 w-full">
<div className="flex items-center text-fgd-1">
<img
alt=""
width="20"
height="20"
src={`/assets/icons/${asset.symbol.toLowerCase()}.svg`}
className={`mr-2.5`}
/>
2021-09-08 05:47:15 -07:00
2022-02-23 14:49:02 -08:00
{asset.symbol}
</div>
<div className="text-fgd-1 text-right">
{asset.borrows.toFixed(
tokenPrecision[asset.symbol]
)}
</div>
2022-02-23 14:49:02 -08:00
</div>
}
key={`${asset.symbol}${i}`}
index={i}
panelTemplate={
<>
<div className="grid grid-cols-2 grid-flow-row gap-4 pb-4">
<div className="text-left">
<div className="pb-0.5 text-th-fgd-3 text-xs">
{t('value')}
</div>
{formatUsdValue(
asset.borrows
.mul(
mangoGroup.getPrice(
tokenIndex,
mangoCache
)
)
.toNumber()
)}
</div>
<div className="text-left">
<div className="pb-0.5 text-th-fgd-3 text-xs">
{t('borrow-rate')} (APR)
</div>
<span className={`text-th-red`}>
{(
mangoGroup
.getBorrowRate(tokenIndex)
.toNumber() * 100
).toFixed(2)}
%
</span>
</div>
2021-09-08 05:47:15 -07:00
</div>
2022-02-23 14:49:02 -08:00
<div className="flex space-x-4">
<Button
onClick={() =>
handleShowDeposit(
asset.symbol,
asset.borrows.toFixed()
)
}
className="text-xs pt-0 pb-0 h-8 w-full"
disabled={
!connected || loadingMangoAccount
}
>
{t('repay')}
</Button>
<Button
onClick={() =>
handleShowBorrow(asset.symbol)
}
className="text-xs pt-0 pb-0 h-8 w-full"
disabled={
!connected ||
loadingMangoAccount ||
!canWithdraw
}
>
{t('borrow')}
</Button>
</div>
</>
}
/>
)
})}
</>
)
) : (
<div
className={`w-full text-center py-6 bg-th-bkg-1 text-th-fgd-3 rounded-md`}
>
{t('no-borrows')}
</div>
)}
</div>
</div>
2021-09-08 05:47:15 -07:00
</div>
2022-02-23 14:49:02 -08:00
</>
) : null}
<h2 className="mb-2">{t('all-assets')}</h2>
2021-09-08 05:47:15 -07:00
<div className="flex flex-col pb-2 pt-4">
2021-12-07 20:00:02 -08:00
<div className="overflow-x-auto sm:-mx-6 lg:-mx-8">
2021-09-08 05:47:15 -07:00
<div className="align-middle inline-block min-w-full sm:px-6 lg:px-8">
{!isMobile ? (
<Table>
<thead>
<TrHead>
<Th>{t('asset')}</Th>
<Th>{t('price')}</Th>
<Th>Deposit APR</Th>
<Th>Borrow APR</Th>
{mangoAccount ? <Th>{t('max-borrow')}</Th> : null}
<Th>{t('liquidity')}</Th>
2021-09-08 05:47:15 -07:00
</TrHead>
</thead>
<tbody>
{mangoConfig.tokens.map((token, i) => {
const tokenIndex = mangoGroup.getTokenIndex(token.mintKey)
return (
2022-02-10 15:48:14 -08:00
<TrBody key={`${token.symbol}${i}`}>
2021-09-08 05:47:15 -07:00
<Td>
<div className="flex items-center">
<img
alt=""
width="20"
height="20"
src={`/assets/icons/${token.symbol.toLowerCase()}.svg`}
className={`mr-2.5`}
/>
<div>{token.symbol}</div>
</div>
</Td>
<Td>
{formatUsdValue(
mangoGroup
.getPrice(tokenIndex, mangoCache)
.toNumber()
2021-09-08 05:47:15 -07:00
)}
</Td>
<Td>
<span className={`text-th-green`}>
2021-09-08 05:47:15 -07:00
{i80f48ToPercent(
mangoGroup.getDepositRate(tokenIndex)
2021-09-08 05:47:15 -07:00
).toFixed(2)}
%
</span>
</Td>
<Td>
<span className={`text-th-red`}>
{i80f48ToPercent(
mangoGroup.getBorrowRate(tokenIndex)
).toFixed(2)}
%
</span>
2021-09-08 05:47:15 -07:00
</Td>
{mangoAccount ? (
<Td>
{mangoAccount
.getMaxWithBorrowForToken(
mangoGroup,
mangoCache,
tokenIndex
)
.mul(I80F48.fromString('0.995'))
.toNumber() > 0
? mangoAccount
.getMaxWithBorrowForToken(
mangoGroup,
mangoCache,
tokenIndex
)
.mul(I80F48.fromString('0.995'))
.toNumber()
.toLocaleString(undefined, {
minimumFractionDigits:
tokenPrecision[token.symbol],
maximumFractionDigits:
tokenPrecision[token.symbol],
})
: 0}
</Td>
) : null}
2021-09-08 05:47:15 -07:00
<Td>
{mangoGroup
.getUiTotalDeposit(tokenIndex)
.sub(mangoGroup.getUiTotalBorrow(tokenIndex))
.toNumber()
.toLocaleString(undefined, {
minimumFractionDigits:
tokenPrecision[token.symbol],
maximumFractionDigits:
tokenPrecision[token.symbol],
})}
</Td>
<Td>
<div className={`flex justify-end`}>
2022-02-23 14:49:02 -08:00
<Tooltip
content={connected ? '' : t('connect-wallet')}
2021-09-08 05:47:15 -07:00
>
2022-02-23 14:49:02 -08:00
<Button
onClick={() => handleShowBorrow(token.symbol)}
className="text-xs pt-0 pb-0 h-8 pl-3 pr-3 ml-3"
disabled={
!connected ||
loadingMangoAccount ||
!canWithdraw
}
>
{t('borrow')}
</Button>
</Tooltip>
2021-09-08 05:47:15 -07:00
</div>
</Td>
</TrBody>
)
})}
</tbody>
</Table>
) : (
<>
<MobileTableHeader
colOneHeader={t('asset')}
2022-02-23 14:49:02 -08:00
colTwoHeader={`${t('deposit')}/${t('borrow-rate')}`}
2021-09-08 05:47:15 -07:00
/>
{mangoConfig.tokens.map((token, i) => {
2021-07-05 08:03:57 -07:00
const tokenIndex = mangoGroup.getTokenIndex(token.mintKey)
return (
2021-09-08 05:47:15 -07:00
<ExpandableRow
buttonTemplate={
<div className="flex items-center justify-between text-fgd-1 w-full">
<div className="flex items-center">
2021-09-08 05:47:15 -07:00
<img
alt=""
width="20"
height="20"
src={`/assets/icons/${token.symbol.toLowerCase()}.svg`}
className={`mr-2.5`}
/>
{token.symbol}
</div>
2022-02-23 14:49:02 -08:00
<div className="flex">
<span className="text-th-green">
{i80f48ToPercent(
mangoGroup.getDepositRate(tokenIndex)
).toFixed(2)}
%
</span>
2022-02-23 14:49:02 -08:00
<span className="px-0.5 text-th-fgd-4">/</span>
<span className="text-th-red">
2021-09-08 05:47:15 -07:00
{i80f48ToPercent(
mangoGroup.getBorrowRate(tokenIndex)
).toFixed(2)}
%
</span>
</div>
</div>
2021-09-08 05:47:15 -07:00
}
key={`${token.symbol}${i}`}
index={i}
panelTemplate={
<div className="grid grid-cols-2 grid-flow-row gap-4">
<div className="text-left">
2021-09-08 05:47:15 -07:00
<div className="pb-0.5 text-th-fgd-3 text-xs">
{t('price')}
2021-09-08 05:47:15 -07:00
</div>
{formatUsdValue(
mangoGroup
.getPrice(tokenIndex, mangoCache)
.toNumber()
2021-09-08 05:47:15 -07:00
)}
</div>
<div className="text-left">
2021-09-08 05:47:15 -07:00
<div className="pb-0.5 text-th-fgd-3 text-xs">
{t('max-borrow')}
2021-09-08 05:47:15 -07:00
</div>
{mangoAccount
? mangoAccount
.getMaxWithBorrowForToken(
mangoGroup,
mangoCache,
tokenIndex
)
.mul(I80F48.fromString('0.995'))
.toNumber()
.toLocaleString(undefined, {
minimumFractionDigits:
tokenPrecision[token.symbol],
maximumFractionDigits:
tokenPrecision[token.symbol],
})
: null}
2021-09-08 05:47:15 -07:00
</div>
<div className="text-left">
2021-09-08 05:47:15 -07:00
<div className="pb-0.5 text-th-fgd-3 text-xs">
{t('liquidity')}
2021-09-08 05:47:15 -07:00
</div>
{mangoGroup
.getUiTotalDeposit(tokenIndex)
.sub(mangoGroup.getUiTotalBorrow(tokenIndex))
.toNumber()
.toLocaleString(undefined, {
minimumFractionDigits:
tokenPrecision[token.symbol],
maximumFractionDigits:
tokenPrecision[token.symbol],
})}
</div>
2022-02-23 14:49:02 -08:00
<Button
onClick={() => handleShowBorrow(token.symbol)}
className="text-xs pt-0 pb-0 h-8 w-full"
disabled={
!connected || loadingMangoAccount || !canWithdraw
}
>
{t('borrow')}
</Button>
</div>
2021-09-08 05:47:15 -07:00
}
/>
2021-07-05 08:03:57 -07:00
)
})}
2021-09-08 05:47:15 -07:00
</>
)}
</div>
2021-09-08 05:47:15 -07:00
</div>
</div>
{showBorrowModal && (
2021-07-05 11:21:57 -07:00
<WithdrawModal
isOpen={showBorrowModal}
onClose={handleCloseWithdraw}
tokenSymbol={borrowSymbol}
title={t('borrow-withdraw')}
2021-07-05 11:21:57 -07:00
borrow
/>
)}
{showDepositModal && (
<DepositModal
isOpen={showDepositModal}
onClose={handleCloseDeposit}
2021-11-09 16:34:03 -08:00
repayAmount={depositToSettle.amount}
tokenSymbol={depositToSettle.symbol}
/>
)}
</>
)
}