add hook for banks and balances
This commit is contained in:
parent
52e871e566
commit
d8970b02c6
|
@ -1,4 +1,4 @@
|
|||
import { Bank, HealthType } from '@blockworks-foundation/mango-v4'
|
||||
import { HealthType } from '@blockworks-foundation/mango-v4'
|
||||
import {
|
||||
ArrowLeftIcon,
|
||||
ArrowUpLeftIcon,
|
||||
|
@ -42,6 +42,7 @@ import { useEnhancedWallet } from './wallet/EnhancedWalletProvider'
|
|||
import FormatNumericValue from './shared/FormatNumericValue'
|
||||
import { floorToDecimal } from 'utils/numbers'
|
||||
import BankAmountWithValue from './shared/BankAmountWithValue'
|
||||
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||
|
||||
interface BorrowFormProps {
|
||||
onSuccess: () => void
|
||||
|
@ -62,6 +63,7 @@ function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
|||
const { mangoAccount } = useMangoAccount()
|
||||
const { connected, publicKey } = useWallet()
|
||||
const { handleConnect } = useEnhancedWallet()
|
||||
const banks = useBanksWithBalances('maxBorrow')
|
||||
|
||||
const bank = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
|
@ -154,28 +156,6 @@ function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
|||
}
|
||||
}, [bank, inputAmount, onSuccess, publicKey])
|
||||
|
||||
const banks = useMemo(() => {
|
||||
if (mangoAccount) {
|
||||
return group?.banksMapByName
|
||||
? Array.from(group?.banksMapByName, ([key, value]) => {
|
||||
const bank: Bank = value[0]
|
||||
const maxAmount = getMaxWithdrawForBank(
|
||||
group,
|
||||
bank,
|
||||
mangoAccount,
|
||||
true
|
||||
).toNumber()
|
||||
return {
|
||||
key,
|
||||
value,
|
||||
maxAmount,
|
||||
}
|
||||
})
|
||||
: []
|
||||
}
|
||||
return []
|
||||
}, [mangoAccount, group])
|
||||
|
||||
const handleInputChange = (e: NumberFormatValues, info: SourceInfo) => {
|
||||
if (info.source === 'event') {
|
||||
setSizePercentage('')
|
||||
|
@ -221,8 +201,7 @@ function BorrowForm({ onSuccess, token }: BorrowFormProps) {
|
|||
banks={banks}
|
||||
onSelect={handleSelectToken}
|
||||
showBorrowRates
|
||||
sortByKey="maxAmount"
|
||||
valueKey="maxAmount"
|
||||
valueKey="maxBorrow"
|
||||
/>
|
||||
</EnterBottomExitBottom>
|
||||
<FadeInFadeOut show={!showTokenList}>
|
||||
|
|
|
@ -32,13 +32,13 @@ import Tooltip from '@components/shared/Tooltip'
|
|||
import HealthImpactTokenChange from '@components/HealthImpactTokenChange'
|
||||
import SolBalanceWarnings from '@components/shared/SolBalanceWarnings'
|
||||
import useJupiterMints from 'hooks/useJupiterMints'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import { useEnhancedWallet } from './wallet/EnhancedWalletProvider'
|
||||
import useSolBalance from 'hooks/useSolBalance'
|
||||
import FormatNumericValue from './shared/FormatNumericValue'
|
||||
import Decimal from 'decimal.js'
|
||||
import { floorToDecimal } from 'utils/numbers'
|
||||
import BankAmountWithValue from './shared/BankAmountWithValue'
|
||||
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||
|
||||
interface DepositFormProps {
|
||||
onSuccess: () => void
|
||||
|
@ -89,7 +89,6 @@ export const useAlphaMax = (inputAmount: string, bank: Bank | undefined) => {
|
|||
|
||||
function DepositForm({ onSuccess, token }: DepositFormProps) {
|
||||
const { t } = useTranslation('common')
|
||||
const { group } = useMangoGroup()
|
||||
const [inputAmount, setInputAmount] = useState('')
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const [selectedToken, setSelectedToken] = useState(
|
||||
|
@ -100,6 +99,7 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
|
|||
const { mangoTokens } = useJupiterMints()
|
||||
const { handleConnect } = useEnhancedWallet()
|
||||
const { maxSolDeposit } = useSolBalance()
|
||||
const banks = useBanksWithBalances('walletBalance')
|
||||
|
||||
const bank = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
|
@ -185,22 +185,6 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
|
|||
}
|
||||
}, [bank, publicKey, inputAmount])
|
||||
|
||||
// TODO extract into a shared hook for UserSetup.tsx
|
||||
const banks = useMemo(() => {
|
||||
const banks = group?.banksMapByName
|
||||
? Array.from(group?.banksMapByName, ([key, value]) => {
|
||||
const walletBalance = walletBalanceForToken(walletTokens, key)
|
||||
return {
|
||||
key,
|
||||
value,
|
||||
walletBalance: walletBalance.maxAmount,
|
||||
walletBalanceValue: walletBalance.maxAmount * value[0].uiPrice!,
|
||||
}
|
||||
})
|
||||
: []
|
||||
return banks
|
||||
}, [group?.banksMapByName, walletTokens])
|
||||
|
||||
const showInsufficientBalance =
|
||||
tokenMax.maxAmount < Number(inputAmount) ||
|
||||
(selectedToken === 'SOL' && maxSolDeposit <= 0)
|
||||
|
@ -235,7 +219,6 @@ function DepositForm({ onSuccess, token }: DepositFormProps) {
|
|||
banks={banks}
|
||||
onSelect={handleSelectToken}
|
||||
showDepositRates
|
||||
sortByKey="walletBalanceValue"
|
||||
valueKey="walletBalance"
|
||||
/>
|
||||
</EnterBottomExitBottom>
|
||||
|
|
|
@ -27,13 +27,13 @@ import { useAlphaMax, walletBalanceForToken } from './DepositForm'
|
|||
import SolBalanceWarnings from '@components/shared/SolBalanceWarnings'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import useJupiterMints from 'hooks/useJupiterMints'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import {
|
||||
ACCOUNT_ACTION_MODAL_INNER_HEIGHT,
|
||||
INPUT_TOKEN_DEFAULT,
|
||||
} from 'utils/constants'
|
||||
import ConnectEmptyState from './shared/ConnectEmptyState'
|
||||
import BankAmountWithValue from './shared/BankAmountWithValue'
|
||||
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||
|
||||
interface RepayFormProps {
|
||||
onSuccess: () => void
|
||||
|
@ -42,7 +42,6 @@ interface RepayFormProps {
|
|||
|
||||
function RepayForm({ onSuccess, token }: RepayFormProps) {
|
||||
const { t } = useTranslation('common')
|
||||
const { group } = useMangoGroup()
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const [inputAmount, setInputAmount] = useState('')
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
|
@ -52,6 +51,7 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
|||
const [showTokenList, setShowTokenList] = useState(false)
|
||||
const [sizePercentage, setSizePercentage] = useState('')
|
||||
const { mangoTokens } = useJupiterMints()
|
||||
const banks = useBanksWithBalances('borrowedAmount')
|
||||
// const { maxSolDeposit } = useSolBalance()
|
||||
|
||||
const bank = useMemo(() => {
|
||||
|
@ -168,27 +168,9 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
|||
[bank, publicKey?.toBase58(), sizePercentage]
|
||||
)
|
||||
|
||||
const banks = useMemo(() => {
|
||||
const banks =
|
||||
group?.banksMapByName && mangoAccount
|
||||
? Array.from(group?.banksMapByName, ([key, value]) => {
|
||||
return {
|
||||
key,
|
||||
value,
|
||||
borrowAmount: mangoAccount.getTokenBorrowsUi(value[0]),
|
||||
borrowAmountValue:
|
||||
mangoAccount.getTokenBorrowsUi(value[0]) * value[0].uiPrice,
|
||||
}
|
||||
})
|
||||
.filter((b) => b.borrowAmount > 0)
|
||||
.sort((a, b) => a.borrowAmount - b.borrowAmount)
|
||||
: []
|
||||
return banks
|
||||
}, [group?.banksMapByName, mangoAccount])
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedToken && !token && banks.length) {
|
||||
setSelectedToken(banks[0].key)
|
||||
setSelectedToken(banks[0].bank.name)
|
||||
}
|
||||
}, [token, banks, selectedToken])
|
||||
|
||||
|
@ -220,8 +202,7 @@ function RepayForm({ onSuccess, token }: RepayFormProps) {
|
|||
<ActionTokenList
|
||||
banks={banks}
|
||||
onSelect={handleSelectToken}
|
||||
sortByKey="borrowAmountValue"
|
||||
valueKey="borrowAmount"
|
||||
valueKey="borrowedAmount"
|
||||
/>
|
||||
</EnterBottomExitBottom>
|
||||
<FadeInFadeOut show={!showTokenList}>
|
||||
|
|
|
@ -23,7 +23,6 @@ import { formatTokenSymbol } from 'utils/tokens'
|
|||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import useJupiterMints from '../hooks/useJupiterMints'
|
||||
import { Table, Td, Th, TrBody, TrHead } from './shared/TableElements'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import DepositWithdrawModal from './modals/DepositWithdrawModal'
|
||||
import BorrowRepayModal from './modals/BorrowRepayModal'
|
||||
import { WRAPPED_SOL_MINT } from '@project-serum/serum/lib/token-instructions'
|
||||
|
@ -32,6 +31,9 @@ import { PublicKey } from '@solana/web3.js'
|
|||
import ActionsLinkButton from './account/ActionsLinkButton'
|
||||
import FormatNumericValue from './shared/FormatNumericValue'
|
||||
import BankAmountWithValue from './shared/BankAmountWithValue'
|
||||
import useBanksWithBalances, {
|
||||
BankWithBalance,
|
||||
} from 'hooks/useBanksWithBalances'
|
||||
|
||||
const TokenList = () => {
|
||||
const { t } = useTranslation(['common', 'token', 'trade'])
|
||||
|
@ -39,7 +41,6 @@ const TokenList = () => {
|
|||
const [showZeroBalances, setShowZeroBalances] = useState(true)
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const spotBalances = mangoStore((s) => s.mangoAccount.spotBalances)
|
||||
const { group } = useMangoGroup()
|
||||
const { mangoTokens } = useJupiterMints()
|
||||
const totalInterestData = mangoStore(
|
||||
(s) => s.mangoAccount.interestTotals.data
|
||||
|
@ -47,40 +48,16 @@ const TokenList = () => {
|
|||
const { width } = useViewport()
|
||||
const showTableView = width ? width > breakpoints.md : false
|
||||
const router = useRouter()
|
||||
const banks = useBanksWithBalances('balance')
|
||||
|
||||
const banks = useMemo(() => {
|
||||
if (group) {
|
||||
const rawBanks = Array.from(group?.banksMapByName, ([key, value]) => ({
|
||||
key,
|
||||
value,
|
||||
}))
|
||||
const sortedBanks = mangoAccount
|
||||
? rawBanks.sort((a, b) => {
|
||||
const aBalance = Math.abs(
|
||||
mangoAccount.getTokenBalanceUi(a.value[0]) * a.value[0].uiPrice
|
||||
)
|
||||
const bBalance = Math.abs(
|
||||
mangoAccount.getTokenBalanceUi(b.value[0]) * b.value[0].uiPrice
|
||||
)
|
||||
if (aBalance > bBalance) return -1
|
||||
if (aBalance < bBalance) return 1
|
||||
|
||||
const aName = a.value[0].name
|
||||
const bName = b.value[0].name
|
||||
if (aName > bName) return 1
|
||||
if (aName < bName) return -1
|
||||
return 1
|
||||
})
|
||||
: rawBanks.sort((a, b) => a.key.localeCompare(b.key))
|
||||
|
||||
return mangoAccount && !showZeroBalances
|
||||
? sortedBanks.filter(
|
||||
(b) => mangoAccount?.getTokenBalanceUi(b.value[0]) !== 0
|
||||
)
|
||||
: sortedBanks
|
||||
const filteredBanks = useMemo(() => {
|
||||
if (banks.length) {
|
||||
return showZeroBalances
|
||||
? banks
|
||||
: banks.filter((b) => Math.abs(b.balance) > 0)
|
||||
}
|
||||
return []
|
||||
}, [showZeroBalances, group, mangoAccount])
|
||||
}, [banks, showZeroBalances])
|
||||
|
||||
useEffect(() => {
|
||||
if (!connected) {
|
||||
|
@ -88,8 +65,8 @@ const TokenList = () => {
|
|||
}
|
||||
}, [connected])
|
||||
|
||||
const goToTokenPage = (bank: Bank) => {
|
||||
router.push(`/token/${bank.name}`, undefined, { shallow: true })
|
||||
const goToTokenPage = (symbol: string) => {
|
||||
router.push(`/token/${symbol}`, undefined, { shallow: true })
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -135,8 +112,8 @@ const TokenList = () => {
|
|||
</TrHead>
|
||||
</thead>
|
||||
<tbody>
|
||||
{banks.map(({ key, value }) => {
|
||||
const bank = value[0]
|
||||
{filteredBanks.map((b) => {
|
||||
const bank = b.bank
|
||||
|
||||
let logoURI
|
||||
if (mangoTokens?.length) {
|
||||
|
@ -145,9 +122,7 @@ const TokenList = () => {
|
|||
)?.logoURI
|
||||
}
|
||||
|
||||
const tokenBalance = mangoAccount
|
||||
? mangoAccount.getTokenBalanceUi(bank)
|
||||
: 0
|
||||
const tokenBalance = b.balance
|
||||
|
||||
const hasInterestEarned = totalInterestData.find(
|
||||
(d) => d.symbol === bank.name
|
||||
|
@ -169,7 +144,7 @@ const TokenList = () => {
|
|||
spotBalances[bank.mint.toString()]?.unsettled || 0
|
||||
|
||||
return (
|
||||
<TrBody className="last:border-y-0" key={key}>
|
||||
<TrBody className="last:border-y-0" key={bank.name}>
|
||||
<Td>
|
||||
<div className="flex items-center">
|
||||
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
||||
|
@ -237,7 +212,7 @@ const TokenList = () => {
|
|||
<div className="flex justify-end space-x-2">
|
||||
<ActionsMenu bank={bank} mangoAccount={mangoAccount} />
|
||||
<IconButton
|
||||
onClick={() => goToTokenPage(bank)}
|
||||
onClick={() => goToTokenPage(bank.name)}
|
||||
size="small"
|
||||
>
|
||||
<ChevronRightIcon className="h-5 w-5" />
|
||||
|
@ -251,8 +226,8 @@ const TokenList = () => {
|
|||
</Table>
|
||||
) : (
|
||||
<div>
|
||||
{banks.map(({ key, value }) => {
|
||||
return <MobileTokenListItem key={key} bank={value[0]} />
|
||||
{filteredBanks.map((b) => {
|
||||
return <MobileTokenListItem key={b.bank.name} bank={b} />
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
|
@ -262,7 +237,7 @@ const TokenList = () => {
|
|||
|
||||
export default TokenList
|
||||
|
||||
const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
||||
const MobileTokenListItem = ({ bank }: { bank: BankWithBalance }) => {
|
||||
const { t } = useTranslation(['common', 'token'])
|
||||
const [showTokenDetails, setShowTokenDetails] = useState(false)
|
||||
const { mangoTokens } = useJupiterMints()
|
||||
|
@ -271,19 +246,19 @@ const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
|||
const totalInterestData = mangoStore(
|
||||
(s) => s.mangoAccount.interestTotals.data
|
||||
)
|
||||
const symbol = bank.name
|
||||
const tokenBank = bank.bank
|
||||
const mint = tokenBank.mint
|
||||
const symbol = tokenBank.name
|
||||
const router = useRouter()
|
||||
|
||||
let logoURI
|
||||
if (mangoTokens?.length) {
|
||||
logoURI = mangoTokens.find(
|
||||
(t) => t.address === bank.mint.toString()
|
||||
(t) => t.address === tokenBank.mint.toString()
|
||||
)!.logoURI
|
||||
}
|
||||
|
||||
const hasInterestEarned = totalInterestData.find(
|
||||
(d) => d.symbol === bank.name
|
||||
)
|
||||
const hasInterestEarned = totalInterestData.find((d) => d.symbol === symbol)
|
||||
|
||||
const interestAmount = hasInterestEarned
|
||||
? hasInterestEarned.borrow_interest * -1 +
|
||||
|
@ -295,14 +270,14 @@ const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
|||
hasInterestEarned.deposit_interest_usd
|
||||
: 0
|
||||
|
||||
const tokenBalance = mangoAccount ? mangoAccount.getTokenBalanceUi(bank) : 0
|
||||
const tokenBalance = bank.balance
|
||||
|
||||
const inOrders = spotBalances[bank.mint.toString()]?.inOrders || 0
|
||||
const inOrders = spotBalances[mint.toString()]?.inOrders || 0
|
||||
|
||||
const unsettled = spotBalances[bank.mint.toString()]?.unsettled || 0
|
||||
const unsettled = spotBalances[mint.toString()]?.unsettled || 0
|
||||
|
||||
const goToTokenPage = (bank: Bank) => {
|
||||
router.push(`/token/${bank.name}`, undefined, { shallow: true })
|
||||
const goToTokenPage = (symbol: string) => {
|
||||
router.push(`/token/${symbol}`, undefined, { shallow: true })
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -317,20 +292,20 @@ const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
|||
)}
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-th-fgd-1">{bank.name}</p>
|
||||
<p className="text-th-fgd-1">{symbol}</p>
|
||||
<p className="font-mono text-sm text-th-fgd-1">
|
||||
<span className="mr-1 font-body text-th-fgd-4">
|
||||
{t('balance')}:
|
||||
</span>
|
||||
<FormatNumericValue
|
||||
value={tokenBalance}
|
||||
decimals={bank.mintDecimals}
|
||||
decimals={tokenBank.mintDecimals}
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-3">
|
||||
<ActionsMenu bank={bank} mangoAccount={mangoAccount} />
|
||||
<ActionsMenu bank={tokenBank} mangoAccount={mangoAccount} />
|
||||
<IconButton
|
||||
onClick={() => setShowTokenDetails((prev) => !prev)}
|
||||
size="small"
|
||||
|
@ -357,17 +332,17 @@ const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
|||
<div className="mt-4 grid grid-cols-2 gap-4 border-t border-th-bkg-3 pt-4">
|
||||
<div className="col-span-1">
|
||||
<p className="text-xs text-th-fgd-3">{t('trade:in-orders')}</p>
|
||||
<BankAmountWithValue amount={inOrders} bank={bank} />
|
||||
<BankAmountWithValue amount={inOrders} bank={tokenBank} />
|
||||
</div>
|
||||
<div className="col-span-1">
|
||||
<p className="text-xs text-th-fgd-3">{t('trade:unsettled')}</p>
|
||||
<BankAmountWithValue amount={unsettled} bank={bank} />
|
||||
<BankAmountWithValue amount={unsettled} bank={tokenBank} />
|
||||
</div>
|
||||
<div className="col-span-1">
|
||||
<p className="text-xs text-th-fgd-3">{t('interest-earned-paid')}</p>
|
||||
<BankAmountWithValue
|
||||
amount={interestAmount}
|
||||
bank={bank}
|
||||
bank={tokenBank}
|
||||
value={interestValue}
|
||||
/>
|
||||
</div>
|
||||
|
@ -376,7 +351,7 @@ const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
|||
<p className="space-x-2 font-mono">
|
||||
<span className="text-th-up">
|
||||
<FormatNumericValue
|
||||
value={bank.getDepositRateUi()}
|
||||
value={tokenBank.getDepositRateUi()}
|
||||
decimals={2}
|
||||
/>
|
||||
%
|
||||
|
@ -384,7 +359,7 @@ const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
|||
<span className="font-normal text-th-fgd-4">|</span>
|
||||
<span className="text-th-down">
|
||||
<FormatNumericValue
|
||||
value={bank.getBorrowRateUi()}
|
||||
value={tokenBank.getBorrowRateUi()}
|
||||
decimals={2}
|
||||
roundUp
|
||||
/>
|
||||
|
@ -395,7 +370,7 @@ const MobileTokenListItem = ({ bank }: { bank: Bank }) => {
|
|||
<div className="col-span-1">
|
||||
<LinkButton
|
||||
className="flex items-center"
|
||||
onClick={() => goToTokenPage(bank)}
|
||||
onClick={() => goToTokenPage(symbol)}
|
||||
>
|
||||
{t('token:token-details')}
|
||||
<ChevronRightIcon className="ml-1.5 h-5 w-5" />
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Bank, HealthType } from '@blockworks-foundation/mango-v4'
|
||||
import { HealthType } from '@blockworks-foundation/mango-v4'
|
||||
import {
|
||||
ArrowLeftIcon,
|
||||
ArrowUpTrayIcon,
|
||||
|
@ -37,6 +37,7 @@ import { useWallet } from '@solana/wallet-adapter-react'
|
|||
import { useEnhancedWallet } from './wallet/EnhancedWalletProvider'
|
||||
import { floorToDecimal } from 'utils/numbers'
|
||||
import BankAmountWithValue from './shared/BankAmountWithValue'
|
||||
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||
|
||||
interface WithdrawFormProps {
|
||||
onSuccess: () => void
|
||||
|
@ -57,6 +58,7 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
|
|||
const { mangoAccount } = useMangoAccount()
|
||||
const { connected } = useWallet()
|
||||
const { handleConnect } = useEnhancedWallet()
|
||||
const banks = useBanksWithBalances('maxWithdraw')
|
||||
|
||||
const bank = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
|
@ -140,32 +142,6 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
|
|||
setShowTokenList(false)
|
||||
}, [])
|
||||
|
||||
const withdrawBanks = useMemo(() => {
|
||||
if (mangoAccount) {
|
||||
const banks = group?.banksMapByName
|
||||
? Array.from(group?.banksMapByName, ([key, value]) => {
|
||||
const bank: Bank = value[0]
|
||||
const accountBalance = getMaxWithdrawForBank(
|
||||
group,
|
||||
bank,
|
||||
mangoAccount
|
||||
).toNumber()
|
||||
return {
|
||||
key,
|
||||
value,
|
||||
accountBalance,
|
||||
accountBalanceValue:
|
||||
accountBalance && bank.uiPrice
|
||||
? accountBalance * bank.uiPrice
|
||||
: 0,
|
||||
}
|
||||
})
|
||||
: []
|
||||
return banks
|
||||
}
|
||||
return []
|
||||
}, [mangoAccount, group])
|
||||
|
||||
const initHealth = useMemo(() => {
|
||||
return group && mangoAccount
|
||||
? mangoAccount.getHealthRatioUi(group, HealthType.init)
|
||||
|
@ -200,10 +176,9 @@ function WithdrawForm({ onSuccess, token }: WithdrawFormProps) {
|
|||
</div>
|
||||
</div>
|
||||
<ActionTokenList
|
||||
banks={withdrawBanks}
|
||||
banks={banks}
|
||||
onSelect={handleSelectToken}
|
||||
sortByKey="accountBalanceValue"
|
||||
valueKey="accountBalance"
|
||||
valueKey="maxWithdraw"
|
||||
/>
|
||||
</EnterBottomExitBottom>
|
||||
<FadeInFadeOut show={!showTokenList}>
|
||||
|
|
|
@ -3,31 +3,31 @@ import useMangoAccount from 'hooks/useMangoAccount'
|
|||
import ActionTokenItem from './ActionTokenItem'
|
||||
|
||||
type BankParams = {
|
||||
key: string
|
||||
value: Bank[]
|
||||
walletBalance?: number
|
||||
maxAmount?: number
|
||||
accountBalance?: number
|
||||
bank: Bank
|
||||
balance: number
|
||||
borrowedAmount: number
|
||||
walletBalance: number
|
||||
maxBorrow: number
|
||||
maxWithdraw: number
|
||||
}
|
||||
|
||||
const ActionTokenList = ({
|
||||
banks,
|
||||
onSelect,
|
||||
sortByKey,
|
||||
showBorrowRates,
|
||||
showDepositRates,
|
||||
valueKey,
|
||||
}: {
|
||||
banks: BankParams[]
|
||||
onSelect: (x: string) => void
|
||||
sortByKey:
|
||||
| 'maxAmount'
|
||||
| 'walletBalanceValue'
|
||||
| 'accountBalanceValue'
|
||||
| 'borrowAmountValue'
|
||||
showBorrowRates?: boolean
|
||||
showDepositRates?: boolean
|
||||
valueKey: 'maxAmount' | 'walletBalance' | 'accountBalance' | 'borrowAmount'
|
||||
valueKey:
|
||||
| 'balance'
|
||||
| 'borrowedAmount'
|
||||
| 'maxBorrow'
|
||||
| 'maxWithdraw'
|
||||
| 'walletBalance'
|
||||
}) => {
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
|
||||
|
@ -37,15 +37,14 @@ const ActionTokenList = ({
|
|||
{banks?.length ? (
|
||||
banks
|
||||
.filter((b: BankParams) => !!b)
|
||||
.sort((a: any, b: any) => b[sortByKey] - a[sortByKey])
|
||||
.map((bank: any) => {
|
||||
.map((b: any) => {
|
||||
return (
|
||||
<ActionTokenItem
|
||||
bank={bank.value[0]}
|
||||
customValue={bank[valueKey]}
|
||||
key={bank.value[0].name}
|
||||
bank={b.bank}
|
||||
customValue={b[valueKey]}
|
||||
key={b.bank.name}
|
||||
onSelect={onSelect}
|
||||
roundUp={valueKey === 'borrowAmount'}
|
||||
roundUp={valueKey === 'borrowedAmount'}
|
||||
showBorrowRates={showBorrowRates}
|
||||
showDepositRates={showDepositRates}
|
||||
/>
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
} from '@heroicons/react/20/solid'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import Image from 'next/legacy/image'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useViewport } from '../../hooks/useViewport'
|
||||
import { formatNumericValue } from '../../utils/numbers'
|
||||
import { breakpoints } from '../../utils/theme'
|
||||
|
@ -14,10 +14,9 @@ import useJupiterMints from 'hooks/useJupiterMints'
|
|||
import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import { getMaxWithdrawForBank } from '@components/swap/useTokenMax'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import BorrowRepayModal from '@components/modals/BorrowRepayModal'
|
||||
import BankAmountWithValue from '@components/shared/BankAmountWithValue'
|
||||
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||
|
||||
const AssetsBorrowsTable = () => {
|
||||
const { t } = useTranslation(['common', 'token'])
|
||||
|
@ -26,10 +25,10 @@ const AssetsBorrowsTable = () => {
|
|||
const actions = mangoStore.getState().actions
|
||||
const initialStatsLoad = mangoStore((s) => s.tokenStats.initialLoad)
|
||||
const { group } = useMangoGroup()
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const { mangoTokens } = useJupiterMints()
|
||||
const { width } = useViewport()
|
||||
const showTableView = width ? width > breakpoints.md : false
|
||||
const banks = useBanksWithBalances('maxBorrow')
|
||||
|
||||
const handleShowBorrowModal = useCallback((token: string) => {
|
||||
setSelectedToken(token)
|
||||
|
@ -42,17 +41,6 @@ const AssetsBorrowsTable = () => {
|
|||
}
|
||||
}, [group])
|
||||
|
||||
const banks = useMemo(() => {
|
||||
if (group) {
|
||||
const rawBanks = Array.from(group?.banksMapByName, ([key, value]) => ({
|
||||
key,
|
||||
value,
|
||||
}))
|
||||
return rawBanks.sort((a, b) => a.key.localeCompare(b.key))
|
||||
}
|
||||
return []
|
||||
}, [group])
|
||||
|
||||
return (
|
||||
<>
|
||||
{showTableView ? (
|
||||
|
@ -75,8 +63,8 @@ const AssetsBorrowsTable = () => {
|
|||
</TrHead>
|
||||
</thead>
|
||||
<tbody>
|
||||
{banks.map(({ key, value }) => {
|
||||
const bank = value[0]
|
||||
{banks.map((b) => {
|
||||
const bank = b.bank
|
||||
|
||||
let logoURI
|
||||
if (mangoTokens?.length) {
|
||||
|
@ -86,18 +74,8 @@ const AssetsBorrowsTable = () => {
|
|||
}
|
||||
const borrows = bank.uiBorrows()
|
||||
|
||||
const available =
|
||||
group && mangoAccount
|
||||
? getMaxWithdrawForBank(
|
||||
group,
|
||||
bank,
|
||||
mangoAccount,
|
||||
true
|
||||
).toNumber()
|
||||
: 0
|
||||
|
||||
return (
|
||||
<TrBody key={key}>
|
||||
<TrBody key={bank.name}>
|
||||
<Td>
|
||||
<div className="flex items-center">
|
||||
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
||||
|
@ -123,7 +101,7 @@ const AssetsBorrowsTable = () => {
|
|||
<Td>
|
||||
<div className="flex flex-col text-right">
|
||||
<BankAmountWithValue
|
||||
amount={available}
|
||||
amount={b.maxBorrow}
|
||||
bank={bank}
|
||||
stacked
|
||||
/>
|
||||
|
@ -138,7 +116,7 @@ const AssetsBorrowsTable = () => {
|
|||
<div className="flex justify-end">
|
||||
<Tooltip content={`${t('borrow')} ${bank.name}`}>
|
||||
<IconButton
|
||||
disabled={available === 0}
|
||||
disabled={b.maxBorrow === 0}
|
||||
onClick={() => handleShowBorrowModal(bank.name)}
|
||||
size="small"
|
||||
>
|
||||
|
@ -154,8 +132,8 @@ const AssetsBorrowsTable = () => {
|
|||
</Table>
|
||||
) : (
|
||||
<div>
|
||||
{banks.map(({ key, value }) => {
|
||||
const bank = value[0]
|
||||
{banks.map((b) => {
|
||||
const bank = b.bank
|
||||
let logoURI
|
||||
if (mangoTokens?.length) {
|
||||
logoURI = mangoTokens.find(
|
||||
|
@ -163,18 +141,11 @@ const AssetsBorrowsTable = () => {
|
|||
)?.logoURI
|
||||
}
|
||||
|
||||
const available =
|
||||
group && mangoAccount
|
||||
? getMaxWithdrawForBank(
|
||||
group,
|
||||
bank,
|
||||
mangoAccount,
|
||||
true
|
||||
).toNumber()
|
||||
: 0
|
||||
|
||||
return (
|
||||
<div key={key} className="border-b border-th-bkg-3 px-6 py-4">
|
||||
<div
|
||||
key={bank.name}
|
||||
className="border-b border-th-bkg-3 px-6 py-4"
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center">
|
||||
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
||||
|
@ -191,7 +162,7 @@ const AssetsBorrowsTable = () => {
|
|||
<p className="mb-0.5 text-right text-xs">
|
||||
{t('available')}
|
||||
</p>
|
||||
<BankAmountWithValue amount={available} bank={bank} />
|
||||
<BankAmountWithValue amount={b.maxBorrow} bank={bank} />
|
||||
</div>
|
||||
<div>
|
||||
<p className="mb-0.5 text-right text-xs">{t('rate')}</p>
|
||||
|
@ -200,7 +171,7 @@ const AssetsBorrowsTable = () => {
|
|||
</p>
|
||||
</div>
|
||||
<IconButton
|
||||
disabled={available === 0}
|
||||
disabled={b.maxBorrow === 0}
|
||||
onClick={() => handleShowBorrowModal(bank.name)}
|
||||
size="medium"
|
||||
>
|
||||
|
|
|
@ -21,6 +21,7 @@ import TabButtons from '@components/shared/TabButtons'
|
|||
import { useViewport } from 'hooks/useViewport'
|
||||
import { breakpoints } from 'utils/theme'
|
||||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
||||
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||
|
||||
const BorrowPage = () => {
|
||||
const { t } = useTranslation(['common', 'borrow'])
|
||||
|
@ -33,6 +34,7 @@ const BorrowPage = () => {
|
|||
const { connected } = useWallet()
|
||||
const { width } = useViewport()
|
||||
const fullWidthTabs = width ? width < breakpoints.sm : false
|
||||
const banks = useBanksWithBalances('borrowedAmount')
|
||||
|
||||
const handleBorrowModal = () => {
|
||||
if (!connected || mangoAccount) {
|
||||
|
@ -57,35 +59,20 @@ const BorrowPage = () => {
|
|||
}
|
||||
}, [actions, mangoAccountAddress])
|
||||
|
||||
const banks = useMemo(() => {
|
||||
if (group && mangoAccount) {
|
||||
const borrowBanks = Array.from(group?.banksMapByName, ([key, value]) => ({
|
||||
key,
|
||||
value,
|
||||
})).filter((b) => {
|
||||
const bank = b.value[0]
|
||||
return mangoAccount.getTokenBalanceUi(bank) < 0
|
||||
})
|
||||
return borrowBanks
|
||||
.map((b) => {
|
||||
return {
|
||||
balance: mangoAccount.getTokenBalanceUi(b.value[0]),
|
||||
bank: b.value[0],
|
||||
}
|
||||
})
|
||||
.sort((a, b) => {
|
||||
const aBalance = Math.abs(a.balance * a.bank.uiPrice)
|
||||
const bBalance = Math.abs(b.balance * b.bank.uiPrice)
|
||||
return aBalance > bBalance ? -1 : 1
|
||||
})
|
||||
const filteredBanks = useMemo(() => {
|
||||
if (banks.length) {
|
||||
return banks.filter((b) => b.borrowedAmount > 0)
|
||||
}
|
||||
return []
|
||||
}, [group, mangoAccount])
|
||||
}, [banks])
|
||||
|
||||
const borrowValue = useMemo(() => {
|
||||
if (!banks.length) return 0
|
||||
return banks.reduce((a, c) => a + Math.abs(c.balance) * c.bank.uiPrice, 0)
|
||||
}, [banks])
|
||||
if (!filteredBanks.length) return 0
|
||||
return filteredBanks.reduce(
|
||||
(a, c) => a + Math.abs(c.borrowedAmount) * c.bank.uiPrice,
|
||||
0
|
||||
)
|
||||
}, [filteredBanks])
|
||||
|
||||
useEffect(() => {
|
||||
if (mangoAccountAddress && !borrowValue) {
|
||||
|
@ -205,7 +192,7 @@ const BorrowPage = () => {
|
|||
/>
|
||||
</div>
|
||||
{activeTab === 'borrow:your-borrows' ? (
|
||||
<YourBorrowsTable banks={banks} />
|
||||
<YourBorrowsTable banks={filteredBanks} />
|
||||
) : (
|
||||
<AssetsBorrowsTable />
|
||||
)}
|
||||
|
|
|
@ -23,11 +23,7 @@ import { useCallback, useState } from 'react'
|
|||
import BorrowRepayModal from '@components/modals/BorrowRepayModal'
|
||||
import Tooltip from '@components/shared/Tooltip'
|
||||
import BankAmountWithValue from '@components/shared/BankAmountWithValue'
|
||||
|
||||
interface BankWithBalance {
|
||||
balance: number
|
||||
bank: Bank
|
||||
}
|
||||
import { BankWithBalance } from 'hooks/useBanksWithBalances'
|
||||
|
||||
const YourBorrowsTable = ({ banks }: { banks: BankWithBalance[] }) => {
|
||||
const { t } = useTranslation(['common', 'trade'])
|
||||
|
@ -82,14 +78,9 @@ const YourBorrowsTable = ({ banks }: { banks: BankWithBalance[] }) => {
|
|||
)?.logoURI
|
||||
}
|
||||
|
||||
const available =
|
||||
group && mangoAccount
|
||||
? getMaxWithdrawForBank(group, bank, mangoAccount, true)
|
||||
: new Decimal(0)
|
||||
const available = b.maxBorrow
|
||||
|
||||
const borrowedAmount = mangoAccount
|
||||
? Math.abs(mangoAccount.getTokenBalanceUi(bank))
|
||||
: 0
|
||||
const borrowedAmount = b.borrowedAmount
|
||||
|
||||
return (
|
||||
<TrBody key={bank.name} className="text-sm">
|
||||
|
@ -141,7 +132,7 @@ const YourBorrowsTable = ({ banks }: { banks: BankWithBalance[] }) => {
|
|||
</Tooltip>
|
||||
<Tooltip content={`${t('borrow')} ${bank.name}`}>
|
||||
<IconButton
|
||||
disabled={available.eq(0)}
|
||||
disabled={available === 0}
|
||||
onClick={() =>
|
||||
handleShowActionModals(bank.name, 'borrow')
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ import ButtonGroup from '../forms/ButtonGroup'
|
|||
import Input from '../forms/Input'
|
||||
import Label from '../forms/Label'
|
||||
import WalletIcon from '../icons/WalletIcon'
|
||||
import { walletBalanceForToken } from '../DepositForm'
|
||||
import ParticlesBackground from '../ParticlesBackground'
|
||||
// import EditNftProfilePic from '../profile/EditNftProfilePic'
|
||||
// import EditProfileForm from '../profile/EditProfileForm'
|
||||
|
@ -43,7 +42,8 @@ import { useEnhancedWallet } from '../wallet/EnhancedWalletProvider'
|
|||
import Modal from '../shared/Modal'
|
||||
import NumberFormat, { NumberFormatValues } from 'react-number-format'
|
||||
import { withValueLimit } from '@components/swap/SwapForm'
|
||||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
||||
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||
import BankAmountWithValue from '@components/shared/BankAmountWithValue'
|
||||
|
||||
const UserSetupModal = ({
|
||||
isOpen,
|
||||
|
@ -65,9 +65,9 @@ const UserSetupModal = ({
|
|||
const [submitDeposit, setSubmitDeposit] = useState(false)
|
||||
const [sizePercentage, setSizePercentage] = useState('')
|
||||
// const [showEditProfilePic, setShowEditProfilePic] = useState(false)
|
||||
const walletTokens = mangoStore((s) => s.wallet.tokens)
|
||||
const { handleConnect } = useEnhancedWallet()
|
||||
const { maxSolDeposit } = useSolBalance()
|
||||
const banks = useBanksWithBalances('walletBalance')
|
||||
|
||||
useEffect(() => {
|
||||
if (connected) {
|
||||
|
@ -157,24 +157,8 @@ const UserSetupModal = ({
|
|||
}
|
||||
}, [mangoAccount, showSetupStep, onClose])
|
||||
|
||||
const banks = useMemo(() => {
|
||||
const banks = group?.banksMapByName
|
||||
? Array.from(group?.banksMapByName, ([key, value]) => {
|
||||
const walletBalance = walletBalanceForToken(walletTokens, key)
|
||||
return {
|
||||
key,
|
||||
value,
|
||||
tokenDecimals: walletBalance.maxDecimals,
|
||||
walletBalance: walletBalance.maxAmount,
|
||||
walletBalanceValue: walletBalance.maxAmount * value?.[0].uiPrice,
|
||||
}
|
||||
})
|
||||
: []
|
||||
return banks
|
||||
}, [group?.banksMapByName, walletTokens])
|
||||
|
||||
const depositBank = useMemo(() => {
|
||||
return banks.find((b) => b.key === depositToken)?.value[0]
|
||||
return banks.find((b) => b.bank.name === depositToken)?.bank
|
||||
}, [depositToken, banks])
|
||||
|
||||
const exceedsAlphaMax = useMemo(() => {
|
||||
|
@ -195,9 +179,9 @@ const UserSetupModal = ({
|
|||
}, [depositAmount, depositBank, group])
|
||||
|
||||
const tokenMax = useMemo(() => {
|
||||
const bank = banks.find((bank) => bank.key === depositToken)
|
||||
const bank = banks.find((b) => b.bank.name === depositToken)
|
||||
if (bank) {
|
||||
return { amount: bank.walletBalance, decimals: bank.tokenDecimals }
|
||||
return { amount: bank.walletBalance, decimals: bank.bank.mintDecimals }
|
||||
}
|
||||
return { amount: 0, decimals: 0 }
|
||||
}, [banks, depositToken])
|
||||
|
@ -481,7 +465,11 @@ const UserSetupModal = ({
|
|||
<div className="flex justify-between px-2 py-4">
|
||||
<p>{t('deposit-amount')}</p>
|
||||
<p className="font-mono text-th-fgd-2">
|
||||
{depositAmount ? (
|
||||
<BankAmountWithValue
|
||||
amount={depositAmount}
|
||||
bank={depositBank}
|
||||
/>
|
||||
{/* {depositAmount ? (
|
||||
<>
|
||||
<FormatNumericValue
|
||||
value={depositAmount}
|
||||
|
@ -506,7 +494,7 @@ const UserSetupModal = ({
|
|||
($0.00)
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
)} */}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -566,7 +554,6 @@ const UserSetupModal = ({
|
|||
banks={banks}
|
||||
onSelect={setDepositToken}
|
||||
showDepositRates
|
||||
sortByKey="walletBalanceValue"
|
||||
valueKey="walletBalance"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Bank, Serum3Market } from '@blockworks-foundation/mango-v4'
|
||||
import { Serum3Market } from '@blockworks-foundation/mango-v4'
|
||||
import useJupiterMints from 'hooks/useJupiterMints'
|
||||
import { NoSymbolIcon, QuestionMarkCircleIcon } from '@heroicons/react/20/solid'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
|
@ -18,53 +18,40 @@ import { calculateLimitPriceForMarketOrder } from 'utils/tradeForm'
|
|||
import { LinkButton } from './Button'
|
||||
import { Table, Td, Th, TrBody, TrHead } from './TableElements'
|
||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import ConnectEmptyState from './ConnectEmptyState'
|
||||
import { useWallet } from '@solana/wallet-adapter-react'
|
||||
import Decimal from 'decimal.js'
|
||||
import FormatNumericValue from './FormatNumericValue'
|
||||
import BankAmountWithValue from './BankAmountWithValue'
|
||||
import useBanksWithBalances, {
|
||||
BankWithBalance,
|
||||
} from 'hooks/useBanksWithBalances'
|
||||
|
||||
const BalancesTable = () => {
|
||||
const { t } = useTranslation(['common', 'trade'])
|
||||
const { mangoAccount, mangoAccountAddress } = useMangoAccount()
|
||||
const spotBalances = mangoStore((s) => s.mangoAccount.spotBalances)
|
||||
const { group } = useMangoGroup()
|
||||
const { mangoTokens } = useJupiterMints()
|
||||
const { width } = useViewport()
|
||||
const { connected } = useWallet()
|
||||
const showTableView = width ? width > breakpoints.md : false
|
||||
const banks = useBanksWithBalances('balance')
|
||||
|
||||
const banks = useMemo(() => {
|
||||
if (!group || !mangoAccount) return []
|
||||
const filteredBanks = useMemo(() => {
|
||||
if (banks.length) {
|
||||
return banks.filter((b) => {
|
||||
return (
|
||||
Math.abs(floorToDecimal(b.balance, b.bank.mintDecimals).toNumber()) >
|
||||
0 ||
|
||||
spotBalances[b.bank.mint.toString()]?.unsettled > 0 ||
|
||||
spotBalances[b.bank.mint.toString()]?.inOrders > 0
|
||||
)
|
||||
})
|
||||
}
|
||||
return []
|
||||
}, [banks])
|
||||
|
||||
const rawBanks = Array.from(group?.banksMapByName, ([key, value]) => ({
|
||||
key,
|
||||
value,
|
||||
balance: mangoAccount.getTokenBalanceUi(value[0]),
|
||||
}))
|
||||
const sortedBanks = mangoAccount
|
||||
? rawBanks
|
||||
.sort(
|
||||
(a, b) =>
|
||||
Math.abs(b.balance * b.value[0].uiPrice) -
|
||||
Math.abs(a.balance * a.value[0].uiPrice)
|
||||
)
|
||||
.filter((c) => {
|
||||
return (
|
||||
Math.abs(
|
||||
floorToDecimal(c.balance, c.value[0].mintDecimals).toNumber()
|
||||
) > 0 ||
|
||||
spotBalances[c.value[0].mint.toString()]?.unsettled > 0 ||
|
||||
spotBalances[c.value[0].mint.toString()]?.inOrders > 0
|
||||
)
|
||||
})
|
||||
: rawBanks
|
||||
|
||||
return sortedBanks
|
||||
}, [group, mangoAccount, spotBalances])
|
||||
|
||||
return banks?.length ? (
|
||||
return filteredBanks.length ? (
|
||||
showTableView ? (
|
||||
<Table>
|
||||
<thead>
|
||||
|
@ -78,8 +65,8 @@ const BalancesTable = () => {
|
|||
</TrHead>
|
||||
</thead>
|
||||
<tbody>
|
||||
{banks.map(({ key, value }) => {
|
||||
const bank = value[0]
|
||||
{filteredBanks.map((b) => {
|
||||
const bank = b.bank
|
||||
|
||||
let logoURI
|
||||
if (mangoTokens.length) {
|
||||
|
@ -92,7 +79,7 @@ const BalancesTable = () => {
|
|||
const unsettled = spotBalances[bank.mint.toString()]?.unsettled || 0
|
||||
|
||||
return (
|
||||
<TrBody key={key} className="text-sm">
|
||||
<TrBody key={bank.name} className="text-sm">
|
||||
<Td>
|
||||
<div className="flex items-center">
|
||||
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
||||
|
@ -106,14 +93,10 @@ const BalancesTable = () => {
|
|||
</div>
|
||||
</Td>
|
||||
<Td className="text-right">
|
||||
<Balance bank={bank} />
|
||||
<Balance bank={b} />
|
||||
<p className="text-sm text-th-fgd-4">
|
||||
<FormatNumericValue
|
||||
value={
|
||||
mangoAccount
|
||||
? mangoAccount.getTokenBalanceUi(bank) * bank.uiPrice
|
||||
: 0
|
||||
}
|
||||
value={mangoAccount ? b.balance * bank.uiPrice : 0}
|
||||
isUsd
|
||||
/>
|
||||
</p>
|
||||
|
@ -131,8 +114,8 @@ const BalancesTable = () => {
|
|||
</Table>
|
||||
) : (
|
||||
<>
|
||||
{banks.map(({ key, value }) => {
|
||||
const bank = value[0]
|
||||
{filteredBanks.map((b) => {
|
||||
const bank = b.bank
|
||||
|
||||
let logoURI
|
||||
if (mangoTokens.length) {
|
||||
|
@ -147,7 +130,7 @@ const BalancesTable = () => {
|
|||
return (
|
||||
<div
|
||||
className="flex items-center justify-between border-b border-th-bkg-3 p-4"
|
||||
key={key}
|
||||
key={bank.name}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
||||
|
@ -161,14 +144,10 @@ const BalancesTable = () => {
|
|||
</div>
|
||||
<div className="text-right">
|
||||
<div className="mb-0.5 flex justify-end space-x-1.5">
|
||||
<Balance bank={bank} />
|
||||
<Balance bank={b} />
|
||||
<span className="text-sm text-th-fgd-4">
|
||||
<FormatNumericValue
|
||||
value={
|
||||
mangoAccount
|
||||
? mangoAccount.getTokenBalanceUi(bank) * bank.uiPrice
|
||||
: 0
|
||||
}
|
||||
value={mangoAccount ? b.balance * bank.uiPrice : 0}
|
||||
isUsd
|
||||
/>
|
||||
</span>
|
||||
|
@ -213,11 +192,12 @@ const BalancesTable = () => {
|
|||
|
||||
export default BalancesTable
|
||||
|
||||
const Balance = ({ bank }: { bank: Bank }) => {
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const Balance = ({ bank }: { bank: BankWithBalance }) => {
|
||||
const { selectedMarket } = useSelectedMarket()
|
||||
const { asPath } = useRouter()
|
||||
|
||||
const tokenBank = bank.bank
|
||||
|
||||
const handleTradeFormBalanceClick = useCallback(
|
||||
(balance: number, type: 'base' | 'quote') => {
|
||||
const set = mangoStore.getState().set
|
||||
|
@ -279,14 +259,14 @@ const Balance = ({ bank }: { bank: Bank }) => {
|
|||
const set = mangoStore.getState().set
|
||||
if (balance >= 0) {
|
||||
set((s) => {
|
||||
s.swap.inputBank = bank
|
||||
s.swap.inputBank = tokenBank
|
||||
s.swap.amountIn = balance.toString()
|
||||
s.swap.amountOut = ''
|
||||
s.swap.swapMode = 'ExactIn'
|
||||
})
|
||||
} else {
|
||||
set((s) => {
|
||||
s.swap.outputBank = bank
|
||||
s.swap.outputBank = tokenBank
|
||||
s.swap.amountIn = ''
|
||||
s.swap.amountOut = Math.abs(balance).toString()
|
||||
s.swap.swapMode = 'ExactOut'
|
||||
|
@ -296,21 +276,19 @@ const Balance = ({ bank }: { bank: Bank }) => {
|
|||
[bank]
|
||||
)
|
||||
|
||||
const balance = useMemo(() => {
|
||||
return mangoAccount ? mangoAccount.getTokenBalanceUi(bank) : 0
|
||||
}, [bank, mangoAccount])
|
||||
const balance = bank.balance
|
||||
|
||||
const isBaseOrQuote = useMemo(() => {
|
||||
if (selectedMarket instanceof Serum3Market) {
|
||||
if (bank.tokenIndex === selectedMarket.baseTokenIndex) {
|
||||
if (tokenBank.tokenIndex === selectedMarket.baseTokenIndex) {
|
||||
return 'base'
|
||||
} else if (bank.tokenIndex === selectedMarket.quoteTokenIndex) {
|
||||
} else if (tokenBank.tokenIndex === selectedMarket.quoteTokenIndex) {
|
||||
return 'quote'
|
||||
} else return ''
|
||||
}
|
||||
}, [bank, selectedMarket])
|
||||
}, [tokenBank, selectedMarket])
|
||||
|
||||
console.log(bank.name, ' balance', new Decimal(balance).toFixed())
|
||||
console.log(tokenBank.name, ' balance', new Decimal(balance).toFixed())
|
||||
if (!balance) return <p className="flex justify-end">0</p>
|
||||
|
||||
return (
|
||||
|
@ -322,21 +300,27 @@ const Balance = ({ bank }: { bank: Bank }) => {
|
|||
handleTradeFormBalanceClick(Math.abs(balance), isBaseOrQuote)
|
||||
}
|
||||
>
|
||||
<FormatNumericValue value={balance} decimals={bank.mintDecimals} />
|
||||
<FormatNumericValue
|
||||
value={balance}
|
||||
decimals={tokenBank.mintDecimals}
|
||||
/>
|
||||
</LinkButton>
|
||||
) : asPath.includes('/swap') ? (
|
||||
<LinkButton
|
||||
className="font-normal underline-offset-4"
|
||||
onClick={() =>
|
||||
handleSwapFormBalanceClick(
|
||||
Number(formatNumericValue(balance, bank.mintDecimals))
|
||||
Number(formatNumericValue(balance, tokenBank.mintDecimals))
|
||||
)
|
||||
}
|
||||
>
|
||||
<FormatNumericValue value={balance} decimals={bank.mintDecimals} />
|
||||
<FormatNumericValue
|
||||
value={balance}
|
||||
decimals={tokenBank.mintDecimals}
|
||||
/>
|
||||
</LinkButton>
|
||||
) : (
|
||||
<FormatNumericValue value={balance} decimals={bank.mintDecimals} />
|
||||
<FormatNumericValue value={balance} decimals={tokenBank.mintDecimals} />
|
||||
)}
|
||||
</p>
|
||||
)
|
||||
|
|
|
@ -6,7 +6,7 @@ import {
|
|||
} from '@heroicons/react/20/solid'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import Image from 'next/legacy/image'
|
||||
import { Fragment, useEffect, useMemo, useState } from 'react'
|
||||
import { Fragment, useEffect, useState } from 'react'
|
||||
import { useViewport } from '../../hooks/useViewport'
|
||||
import { breakpoints } from '../../utils/theme'
|
||||
import { IconButton, LinkButton } from '../shared/Button'
|
||||
|
@ -20,6 +20,7 @@ import useMangoGroup from 'hooks/useMangoGroup'
|
|||
import mangoStore from '@store/mangoStore'
|
||||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
||||
import BankAmountWithValue from '@components/shared/BankAmountWithValue'
|
||||
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||
|
||||
const TokenStats = () => {
|
||||
const { t } = useTranslation(['common', 'token'])
|
||||
|
@ -31,6 +32,7 @@ const TokenStats = () => {
|
|||
const { width } = useViewport()
|
||||
const showTableView = width ? width > breakpoints.md : false
|
||||
const router = useRouter()
|
||||
const banks = useBanksWithBalances()
|
||||
|
||||
useEffect(() => {
|
||||
if (group && !initialStatsLoad) {
|
||||
|
@ -38,17 +40,6 @@ const TokenStats = () => {
|
|||
}
|
||||
}, [group])
|
||||
|
||||
const banks = useMemo(() => {
|
||||
if (group) {
|
||||
const rawBanks = Array.from(group?.banksMapByName, ([key, value]) => ({
|
||||
key,
|
||||
value,
|
||||
}))
|
||||
return rawBanks.sort((a, b) => a.key.localeCompare(b.key))
|
||||
}
|
||||
return []
|
||||
}, [group])
|
||||
|
||||
const handleShowTokenDetails = (name: string) => {
|
||||
showTokenDetails ? setShowTokenDetails('') : setShowTokenDetails(name)
|
||||
}
|
||||
|
@ -100,8 +91,8 @@ const TokenStats = () => {
|
|||
</TrHead>
|
||||
</thead>
|
||||
<tbody>
|
||||
{banks.map(({ key, value }) => {
|
||||
const bank: Bank = value[0]
|
||||
{banks.map((b) => {
|
||||
const bank: Bank = b.bank
|
||||
|
||||
let logoURI
|
||||
if (mangoTokens?.length) {
|
||||
|
@ -115,7 +106,7 @@ const TokenStats = () => {
|
|||
deposits - deposits * bank.minVaultToDepositsRatio - borrows
|
||||
|
||||
return (
|
||||
<TrBody key={key}>
|
||||
<TrBody key={bank.name}>
|
||||
<Td>
|
||||
<div className="flex items-center">
|
||||
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
||||
|
@ -213,8 +204,8 @@ const TokenStats = () => {
|
|||
</Table>
|
||||
) : (
|
||||
<div>
|
||||
{banks.map(({ key, value }) => {
|
||||
const bank = value[0]
|
||||
{banks.map((b) => {
|
||||
const bank = b.bank
|
||||
let logoURI
|
||||
if (mangoTokens?.length) {
|
||||
logoURI = mangoTokens.find(
|
||||
|
@ -227,7 +218,10 @@ const TokenStats = () => {
|
|||
const available =
|
||||
deposits - deposits * bank.minVaultToDepositsRatio - borrows
|
||||
return (
|
||||
<div key={key} className="border-b border-th-bkg-3 px-6 py-4">
|
||||
<div
|
||||
key={bank.name}
|
||||
className="border-b border-th-bkg-3 px-6 py-4"
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center">
|
||||
<div className="mr-2.5 flex flex-shrink-0 items-center">
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { TokenStatsItem } from '@store/mangoStore'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { useMemo, useState } from 'react'
|
||||
import dayjs from 'dayjs'
|
||||
import { formatYAxis } from 'utils/formatting'
|
||||
import useBanksWithBalances from 'hooks/useBanksWithBalances'
|
||||
const DetailedAreaChart = dynamic(
|
||||
() => import('@components/shared/DetailedAreaChart'),
|
||||
{ ssr: false }
|
||||
|
@ -26,7 +26,7 @@ const TotalDepositBorrowCharts = ({
|
|||
const { t } = useTranslation(['common', 'token', 'trade'])
|
||||
const [borrowDaysToShow, setBorrowDaysToShow] = useState('30')
|
||||
const [depositDaysToShow, setDepositDaysToShow] = useState('30')
|
||||
const { group } = useMangoGroup()
|
||||
const banks = useBanksWithBalances()
|
||||
|
||||
const totalDepositBorrowValues = useMemo(() => {
|
||||
if (!tokenStats) return []
|
||||
|
@ -82,28 +82,11 @@ const TotalDepositBorrowCharts = ({
|
|||
return totalDepositBorrowValues
|
||||
}, [totalDepositBorrowValues, depositDaysToShow])
|
||||
|
||||
const banks = useMemo(() => {
|
||||
if (group) {
|
||||
const rawBanks = Array.from(group?.banksMapByName, ([key, value]) => ({
|
||||
key,
|
||||
value,
|
||||
}))
|
||||
return rawBanks
|
||||
}
|
||||
return []
|
||||
}, [group])
|
||||
|
||||
const [currentTotalDepositValue, currentTotalBorrowValue] = useMemo(() => {
|
||||
if (banks.length) {
|
||||
return [
|
||||
banks.reduce(
|
||||
(a, c) => a + c.value[0].uiPrice * c.value[0].uiDeposits(),
|
||||
0
|
||||
),
|
||||
banks.reduce(
|
||||
(a, c) => a + c.value[0].uiPrice * c.value[0].uiBorrows(),
|
||||
0
|
||||
),
|
||||
banks.reduce((a, c) => a + c.bank.uiPrice * c.bank.uiDeposits(), 0),
|
||||
banks.reduce((a, c) => a + c.bank.uiPrice * c.bank.uiBorrows(), 0),
|
||||
]
|
||||
}
|
||||
return [0, 0]
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
import { Bank } from '@blockworks-foundation/mango-v4'
|
||||
import { walletBalanceForToken } from '@components/DepositForm'
|
||||
import { getMaxWithdrawForBank } from '@components/swap/useTokenMax'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import { useMemo } from 'react'
|
||||
import useMangoAccount from './useMangoAccount'
|
||||
import useMangoGroup from './useMangoGroup'
|
||||
|
||||
export interface BankWithBalance {
|
||||
balance: number
|
||||
bank: Bank
|
||||
borrowedAmount: number
|
||||
maxBorrow: number
|
||||
maxWithdraw: number
|
||||
walletBalance: number
|
||||
}
|
||||
|
||||
export default function useBanksWithBalances(
|
||||
sortByKey?:
|
||||
| 'balance'
|
||||
| 'borrowedAmount'
|
||||
| 'maxBorrow'
|
||||
| 'maxWithdraw'
|
||||
| 'walletBalance'
|
||||
) {
|
||||
const { group } = useMangoGroup()
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const walletTokens = mangoStore((s) => s.wallet.tokens)
|
||||
|
||||
const banks: BankWithBalance[] = useMemo(() => {
|
||||
if (group) {
|
||||
const banksWithBalances = Array.from(
|
||||
group?.banksMapByName,
|
||||
([key, value]) => ({
|
||||
key,
|
||||
value,
|
||||
})
|
||||
).map((b) => {
|
||||
const bank = b.value[0]
|
||||
const balance = mangoAccount ? mangoAccount.getTokenBalanceUi(bank) : 0
|
||||
const maxBorrow = mangoAccount
|
||||
? getMaxWithdrawForBank(group, bank, mangoAccount, true).toNumber()
|
||||
: 0
|
||||
const maxWithdraw = mangoAccount
|
||||
? getMaxWithdrawForBank(group, bank, mangoAccount).toNumber()
|
||||
: 0
|
||||
const borrowedAmount = mangoAccount
|
||||
? mangoAccount.getTokenBorrowsUi(bank)
|
||||
: 0
|
||||
const walletBalance =
|
||||
walletBalanceForToken(walletTokens, bank.name)?.maxAmount || 0
|
||||
return {
|
||||
bank,
|
||||
balance,
|
||||
borrowedAmount,
|
||||
maxBorrow,
|
||||
maxWithdraw,
|
||||
walletBalance,
|
||||
}
|
||||
})
|
||||
|
||||
const sortedBanks = banksWithBalances.sort((a, b) => {
|
||||
if (sortByKey) {
|
||||
const aPrice = a.bank.uiPrice
|
||||
const bPrice = b.bank.uiPrice
|
||||
const aValue = Math.abs(a[sortByKey]) * aPrice
|
||||
const bValue = Math.abs(b[sortByKey]) * bPrice
|
||||
if (aValue > bValue) return -1
|
||||
if (aValue < bValue) return 1
|
||||
}
|
||||
|
||||
const aName = a.bank.name
|
||||
const bName = b.bank.name
|
||||
if (aName > bName) return 1
|
||||
if (aName < bName) return -1
|
||||
return 1
|
||||
})
|
||||
|
||||
return sortedBanks
|
||||
}
|
||||
return []
|
||||
}, [group, mangoAccount])
|
||||
|
||||
return banks
|
||||
}
|
Loading…
Reference in New Issue