Merge pull request #204 from blockworks-foundation/balance-collateral-value

balance collateral value
This commit is contained in:
tlrsssss 2023-07-20 10:49:33 -04:00 committed by GitHub
commit 0605872a56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 322 additions and 129 deletions

View File

@ -32,6 +32,7 @@ import useBanksWithBalances, {
import useUnownedAccount from 'hooks/useUnownedAccount'
import useLocalStorageState from 'hooks/useLocalStorageState'
import TokenLogo from './shared/TokenLogo'
import useHealthContributions from 'hooks/useHealthContributions'
const TokenList = () => {
const { t } = useTranslation(['common', 'token', 'trade'])
@ -40,6 +41,7 @@ const TokenList = () => {
true
)
const { mangoAccount, mangoAccountAddress } = useMangoAccount()
const { initContributions } = useHealthContributions()
const spotBalances = mangoStore((s) => s.mangoAccount.spotBalances)
const totalInterestData = mangoStore(
(s) => s.mangoAccount.interestTotals.data
@ -48,14 +50,26 @@ const TokenList = () => {
const showTableView = width ? width > breakpoints.md : false
const banks = useBanksWithBalances('balance')
// const filteredBanks = useMemo(() => {
// if (banks.length) {
// return showZeroBalances || !mangoAccountAddress
// ? banks
// : banks.filter((b) => Math.abs(b.balance) > 0)
// }
// return []
// }, [banks, mangoAccountAddress, showZeroBalances])
const filteredBanks = useMemo(() => {
if (banks.length) {
return showZeroBalances || !mangoAccountAddress
? banks
: banks.filter((b) => Math.abs(b.balance) > 0)
}
return []
}, [banks, mangoAccountAddress, showZeroBalances])
if (!banks.length) return []
if (showZeroBalances || !mangoAccountAddress) return banks
const filtered = banks.filter((b) => {
const contribution =
initContributions.find((cont) => cont.asset === b.bank.name)
?.contribution || 0
return Math.abs(contribution) > 0
})
return filtered
}, [banks, mangoAccountAddress, showZeroBalances, initContributions])
return (
<ContentBox hideBorder hidePadding>
@ -66,141 +80,181 @@ const TokenList = () => {
disabled={!mangoAccount}
onChange={() => setShowZeroBalances(!showZeroBalances)}
>
{t('show-zero-balances')}
{t('account:zero-collateral')}
</Switch>
</div>
) : null}
{showTableView ? (
<Table>
<thead>
<TrHead>
<Th className="text-left">{t('token')}</Th>
<Th>
<div className="flex justify-end">
<Tooltip content="A negative balance represents a borrow">
<span className="tooltip-underline">{t('balance')}</span>
<div className="thin-scroll overflow-x-auto">
<Table>
<thead>
<TrHead>
<Th className="text-left">{t('token')}</Th>
<Th>
<div className="flex justify-end">
<Tooltip content="A negative balance represents a borrow">
<span className="tooltip-underline">{t('balance')}</span>
</Tooltip>
</div>
</Th>
<Th>
<div className="flex justify-end">
<Tooltip content={t('account:tooltip-collateral-value')}>
<span className="tooltip-underline">
{t('account:collateral-value')}
</span>
</Tooltip>
</div>
</Th>
<Th className="text-right">{t('trade:in-orders')}</Th>
<Th className="text-right">{t('trade:unsettled')}</Th>
<Th className="flex justify-end" id="account-step-nine">
<Tooltip content="The sum of interest earned and interest paid for each token">
<span className="tooltip-underline">
{t('interest-earned-paid')}
</span>
</Tooltip>
</div>
</Th>
<Th className="text-right">{t('trade:in-orders')}</Th>
<Th className="text-right">{t('trade:unsettled')}</Th>
<Th className="flex justify-end" id="account-step-nine">
<Tooltip content="The sum of interest earned and interest paid for each token">
<span className="tooltip-underline">
{t('interest-earned-paid')}
</span>
</Tooltip>
</Th>
<Th id="account-step-ten">
<div className="flex justify-end">
<Tooltip content="The interest rates for depositing (green/left) and borrowing (red/right)">
<span className="tooltip-underline">{t('rates')}</span>
</Tooltip>
</div>
</Th>
<Th className="text-right">
<span>{t('actions')}</span>
</Th>
</TrHead>
</thead>
<tbody>
{filteredBanks.map((b) => {
const bank = b.bank
</Th>
<Th id="account-step-ten">
<div className="flex justify-end">
<Tooltip content="The interest rates for depositing (green/left) and borrowing (red/right)">
<span className="tooltip-underline">{t('rates')}</span>
</Tooltip>
</div>
</Th>
<Th className="text-right">
<span>{t('actions')}</span>
</Th>
</TrHead>
</thead>
<tbody>
{filteredBanks.map((b) => {
const bank = b.bank
const tokenBalance = b.balance
const symbol = bank.name === 'MSOL' ? 'mSOL' : bank.name
const tokenBalance = b.balance
const symbol = bank.name === 'MSOL' ? 'mSOL' : bank.name
const hasInterestEarned = totalInterestData.find(
(d) =>
d.symbol.toLowerCase() === symbol.toLowerCase() ||
(symbol === 'ETH (Portal)' && d.symbol === 'ETH')
)
const hasInterestEarned = totalInterestData.find(
(d) =>
d.symbol.toLowerCase() === symbol.toLowerCase() ||
(symbol === 'ETH (Portal)' && d.symbol === 'ETH')
)
const interestAmount = hasInterestEarned
? hasInterestEarned.borrow_interest * -1 +
hasInterestEarned.deposit_interest
: 0
const interestAmount = hasInterestEarned
? hasInterestEarned.borrow_interest * -1 +
hasInterestEarned.deposit_interest
: 0
const interestValue = hasInterestEarned
? hasInterestEarned.borrow_interest_usd * -1 +
hasInterestEarned.deposit_interest_usd
: 0.0
const interestValue = hasInterestEarned
? hasInterestEarned.borrow_interest_usd * -1 +
hasInterestEarned.deposit_interest_usd
: 0.0
const inOrders = spotBalances[bank.mint.toString()]?.inOrders || 0
const inOrders =
spotBalances[bank.mint.toString()]?.inOrders || 0
const unsettled =
spotBalances[bank.mint.toString()]?.unsettled || 0
const unsettled =
spotBalances[bank.mint.toString()]?.unsettled || 0
return (
<TrBody key={bank.name}>
<Td>
<div className="flex items-center">
<div className="mr-2.5 flex flex-shrink-0 items-center">
<TokenLogo bank={bank} />
const collateralValue =
initContributions.find((val) => val.asset === bank.name)
?.contribution || 0
const assetWeight = bank
.scaledInitAssetWeight(bank.price)
.toFixed(2)
const liabWeight = bank
.scaledInitLiabWeight(bank.price)
.toFixed(2)
return (
<TrBody key={bank.name}>
<Td>
<div className="flex items-center">
<div className="mr-2.5 flex flex-shrink-0 items-center">
<TokenLogo bank={bank} />
</div>
<p className="font-body">{symbol}</p>
</div>
<p className="font-body">{symbol}</p>
</div>
</Td>
<Td className="text-right">
<BankAmountWithValue
amount={tokenBalance}
bank={bank}
stacked
/>
</Td>
<Td className="text-right">
<BankAmountWithValue
amount={inOrders}
bank={bank}
stacked
/>
</Td>
<Td className="text-right">
<BankAmountWithValue
amount={unsettled}
bank={bank}
stacked
/>
</Td>
<Td>
<div className="flex flex-col text-right">
</Td>
<Td className="text-right">
<BankAmountWithValue
amount={interestAmount}
amount={tokenBalance}
bank={bank}
value={interestValue}
stacked
/>
</div>
</Td>
<Td>
<div className="flex justify-end space-x-1.5">
<p className="text-th-up">
</Td>
<Td className="text-right">
<p>
<FormatNumericValue
value={bank.getDepositRateUi()}
value={collateralValue}
decimals={2}
isUsd
/>
%
</p>
<span className="text-th-fgd-4">|</span>
<p className="text-th-down">
<p className="text-sm text-th-fgd-4">
<FormatNumericValue
value={bank.getBorrowRateUi()}
decimals={2}
value={
collateralValue <= -0.01 ? liabWeight : assetWeight
}
/>
%
x
</p>
</div>
</Td>
<Td>
<div className="flex items-center justify-end">
<ActionsMenu bank={bank} mangoAccount={mangoAccount} />
</div>
</Td>
</TrBody>
)
})}
</tbody>
</Table>
</Td>
<Td className="text-right">
<BankAmountWithValue
amount={inOrders}
bank={bank}
stacked
/>
</Td>
<Td className="text-right">
<BankAmountWithValue
amount={unsettled}
bank={bank}
stacked
/>
</Td>
<Td>
<div className="flex flex-col text-right">
<BankAmountWithValue
amount={interestAmount}
bank={bank}
value={interestValue}
stacked
/>
</div>
</Td>
<Td>
<div className="flex justify-end space-x-1.5">
<p className="text-th-up">
<FormatNumericValue
value={bank.getDepositRateUi()}
decimals={2}
/>
%
</p>
<span className="text-th-fgd-4">|</span>
<p className="text-th-down">
<FormatNumericValue
value={bank.getBorrowRateUi()}
decimals={2}
/>
%
</p>
</div>
</Td>
<Td>
<div className="flex items-center justify-end">
<ActionsMenu bank={bank} mangoAccount={mangoAccount} />
</div>
</Td>
</TrBody>
)
})}
</tbody>
</Table>
</div>
) : (
<div className="border-b border-th-bkg-3">
{filteredBanks.map((b) => {
@ -218,6 +272,7 @@ const MobileTokenListItem = ({ bank }: { bank: BankWithBalance }) => {
const { t } = useTranslation(['common', 'token'])
const spotBalances = mangoStore((s) => s.mangoAccount.spotBalances)
const { mangoAccount } = useMangoAccount()
const { initContributions } = useHealthContributions()
const totalInterestData = mangoStore(
(s) => s.mangoAccount.interestTotals.data
)
@ -247,6 +302,15 @@ const MobileTokenListItem = ({ bank }: { bank: BankWithBalance }) => {
const unsettled = spotBalances[mint.toString()]?.unsettled || 0
const collateralValue =
initContributions.find((val) => val.asset === tokenBank.name)
?.contribution || 0
const assetWeight = tokenBank
.scaledInitAssetWeight(tokenBank.price)
.toFixed(2)
const liabWeight = tokenBank.scaledInitLiabWeight(tokenBank.price).toFixed(2)
return (
<Disclosure>
{({ open }) => (
@ -296,6 +360,29 @@ const MobileTokenListItem = ({ bank }: { bank: BankWithBalance }) => {
>
<Disclosure.Panel>
<div className="mx-4 grid grid-cols-2 gap-4 border-t border-th-bkg-3 pt-4 pb-4">
<div className="col-span-1">
<Tooltip content={t('account:tooltip-collateral-value')}>
<p className="tooltip-underline text-xs text-th-fgd-3">
{t('account:collateral-value')}
</p>
</Tooltip>
<p className="font-mono text-th-fgd-2">
<FormatNumericValue
value={collateralValue}
decimals={2}
isUsd
/>
<span className="text-th-fgd-3">
{' '}
<FormatNumericValue
value={
collateralValue <= -0.01 ? liabWeight : assetWeight
}
/>
x
</span>
</p>
</div>
<div className="col-span-1">
<p className="text-xs text-th-fgd-3">
{t('trade:in-orders')}

View File

@ -22,18 +22,21 @@ import useBanksWithBalances, {
import useUnownedAccount from 'hooks/useUnownedAccount'
import { Disclosure, Transition } from '@headlessui/react'
import TokenLogo from './TokenLogo'
import useHealthContributions from 'hooks/useHealthContributions'
import Tooltip from './Tooltip'
import { PublicKey } from '@solana/web3.js'
import { USDC_MINT } from 'utils/constants'
import { WRAPPED_SOL_MINT } from '@project-serum/serum/lib/token-instructions'
const BalancesTable = () => {
const { t } = useTranslation(['common', 'trade'])
const { t } = useTranslation(['common', 'account', 'trade'])
const { mangoAccount, mangoAccountAddress } = useMangoAccount()
const spotBalances = mangoStore((s) => s.mangoAccount.spotBalances)
const { width } = useViewport()
const { connected } = useWallet()
const showTableView = width ? width > breakpoints.md : false
const banks = useBanksWithBalances('balance')
const { initContributions } = useHealthContributions()
const filteredBanks = useMemo(() => {
if (banks.length) {
@ -56,6 +59,15 @@ const BalancesTable = () => {
<TrHead>
<Th className="bg-th-bkg-1 text-left">{t('token')}</Th>
<Th className="bg-th-bkg-1 text-right">{t('balance')}</Th>
<Th>
<div className="flex justify-end">
<Tooltip content={t('account:tooltip-collateral-value')}>
<span className="tooltip-underline">
{t('account:collateral-value')}
</span>
</Tooltip>
</div>
</Th>
<Th className="bg-th-bkg-1 text-right">{t('trade:in-orders')}</Th>
<Th className="bg-th-bkg-1 text-right" id="trade-step-ten">
{t('trade:unsettled')}
@ -70,6 +82,15 @@ const BalancesTable = () => {
const inOrders = spotBalances[bank.mint.toString()]?.inOrders || 0
const unsettled = spotBalances[bank.mint.toString()]?.unsettled || 0
const collateralValue =
initContributions.find((val) => val.asset === bank.name)
?.contribution || 0
const assetWeight = bank
.scaledInitAssetWeight(bank.price)
.toFixed(2)
const liabWeight = bank.scaledInitLiabWeight(bank.price).toFixed(2)
return (
<TrBody key={bank.name} className="text-sm">
<Td>
@ -89,6 +110,23 @@ const BalancesTable = () => {
/>
</p>
</Td>
<Td className="text-right">
<p>
<FormatNumericValue
value={collateralValue}
decimals={2}
isUsd
/>
</p>
<p className="text-sm text-th-fgd-4">
<FormatNumericValue
value={
collateralValue <= -0.01 ? liabWeight : assetWeight
}
/>
x
</p>
</Td>
<Td className="text-right">
<BankAmountWithValue amount={inOrders} bank={bank} stacked />
</Td>
@ -109,6 +147,13 @@ const BalancesTable = () => {
const inOrders = spotBalances[bank.mint.toString()]?.inOrders || 0
const unsettled = spotBalances[bank.mint.toString()]?.unsettled || 0
const collateralValue =
initContributions.find((val) => val.asset === bank.name)
?.contribution || 0
const assetWeight = bank.scaledInitAssetWeight(bank.price).toFixed(2)
const liabWeight = bank.scaledInitLiabWeight(bank.price).toFixed(2)
return (
<Disclosure key={bank.name}>
{({ open }) => (
@ -152,6 +197,33 @@ const BalancesTable = () => {
>
<Disclosure.Panel>
<div className="mx-4 grid grid-cols-2 gap-4 border-t border-th-bkg-3 pt-4 pb-4">
<div className="col-span-1">
<Tooltip
content={t('account:tooltip-collateral-value')}
>
<p className="tooltip-underline text-xs text-th-fgd-3">
{t('account:collateral-value')}
</p>
</Tooltip>
<p className="font-mono text-th-fgd-2">
<FormatNumericValue
value={collateralValue}
decimals={2}
isUsd
/>
<span className="text-th-fgd-3">
{' '}
<FormatNumericValue
value={
collateralValue <= -0.01
? liabWeight
: assetWeight
}
/>
x
</span>
</p>
</div>
<div className="col-span-1">
<p className="text-xs text-th-fgd-3">
{t('trade:in-orders')}

View File

@ -0,0 +1,24 @@
import { HealthType } from '@blockworks-foundation/mango-v4'
import mangoStore from '@store/mangoStore'
import { useMemo } from 'react'
import useMangoAccount from './useMangoAccount'
export default function useHealthContributions() {
const { mangoAccount } = useMangoAccount()
const [initContributions, maintContributions] = useMemo(() => {
const group = mangoStore.getState().group
if (!mangoAccount || !group) return [[], []]
const init = mangoAccount.getHealthContributionPerAssetUi(
group,
HealthType.init
)
const maint = mangoAccount.getHealthContributionPerAssetUi(
group,
HealthType.maint
)
return [init, maint]
}, [mangoAccount])
return { initContributions, maintContributions }
}

View File

@ -1,6 +1,7 @@
{
"assets": "Assets",
"assets-liabilities": "Assets & Liabilities",
"collateral-value": "Collateral Value",
"cumulative-interest-chart": "Cumulative Interst Chart",
"daily-volume": "24h Volume",
"export": "Export {{dataType}}",
@ -16,6 +17,7 @@
"no-pnl-history": "No PnL History",
"pnl-chart": "PnL Chart",
"pnl-history": "PnL History",
"tooltip-collateral-value": "The amount of capital this token gives you to use for trades and loans.",
"tooltip-free-collateral": "The amount of capital you have to use for trades and loans. When your free collateral reaches $0 you won't be able to trade, borrow or withdraw",
"tooltip-init-health": "The contribution an asset gives to your initial account health. Initial health affects your ability to open new positions and withdraw collateral from your account. The sum of these values is equal to your account's free collateral.",
"tooltip-leverage": "Total assets value divided by account equity value",
@ -26,5 +28,6 @@
"tooltip-total-interest": "The value of interest earned (deposits) minus interest paid (borrows)",
"total-funding-earned": "Total Funding Earned",
"volume-chart": "Volume Chart",
"week-starting": "Week starting {{week}}"
"week-starting": "Week starting {{week}}",
"zero-collateral": "Zero Collateral"
}

View File

@ -142,7 +142,6 @@
"sell": "Sell",
"settings": "Settings",
"show-more": "Show More",
"show-zero-balances": "Show Zero Balances",
"solana-tps": "Solana TPS",
"soon": "Soon",
"spot": "Spot",

View File

@ -1,6 +1,7 @@
{
"assets": "Assets",
"assets-liabilities": "Assets & Liabilities",
"collateral-value": "Collateral Value",
"cumulative-interest-chart": "Cumulative Interst Chart",
"daily-volume": "24h Volume",
"export": "Export {{dataType}}",
@ -16,6 +17,7 @@
"no-pnl-history": "No PnL History",
"pnl-chart": "PnL Chart",
"pnl-history": "PnL History",
"tooltip-collateral-value": "The amount of capital this token gives you to use for trades and loans.",
"tooltip-free-collateral": "The amount of capital you have to use for trades and loans. When your free collateral reaches $0 you won't be able to trade, borrow or withdraw",
"tooltip-init-health": "The contribution an asset gives to your initial account health. Initial health affects your ability to open new positions and withdraw collateral from your account. The sum of these values is equal to your account's free collateral.",
"tooltip-leverage": "Total assets value divided by account equity value",
@ -26,5 +28,6 @@
"tooltip-total-interest": "The value of interest earned (deposits) minus interest paid (borrows)",
"total-funding-earned": "Total Funding Earned",
"volume-chart": "Volume Chart",
"week-starting": "Week starting {{week}}"
"week-starting": "Week starting {{week}}",
"zero-collateral": "Zero Collateral"
}

View File

@ -141,7 +141,6 @@
"sell": "Sell",
"settings": "Settings",
"show-more": "Show More",
"show-zero-balances": "Show Zero Balances",
"solana-tps": "Solana TPS",
"soon": "Soon",
"spot": "Spot",

View File

@ -1,6 +1,7 @@
{
"assets": "Assets",
"assets-liabilities": "Assets & Liabilities",
"collateral-value": "Collateral Value",
"cumulative-interest-chart": "Cumulative Interst Chart",
"daily-volume": "24h Volume",
"export": "Export {{dataType}}",
@ -16,6 +17,7 @@
"no-pnl-history": "No PnL History",
"pnl-chart": "PnL Chart",
"pnl-history": "PnL History",
"tooltip-collateral-value": "The amount of capital this token gives you to use for trades and loans.",
"tooltip-free-collateral": "The amount of capital you have to use for trades and loans. When your free collateral reaches $0 you won't be able to trade, borrow or withdraw",
"tooltip-init-health": "The contribution an asset gives to your initial account health. Initial health affects your ability to open new positions and withdraw collateral from your account. The sum of these values is equal to your account's free collateral.",
"tooltip-leverage": "Total assets value divided by account equity value",
@ -26,5 +28,6 @@
"tooltip-total-interest": "The value of interest earned (deposits) minus interest paid (borrows)",
"total-funding-earned": "Total Funding Earned",
"volume-chart": "Volume Chart",
"week-starting": "Week starting {{week}}"
"week-starting": "Week starting {{week}}",
"zero-collateral": "Zero Collateral"
}

View File

@ -141,7 +141,6 @@
"sell": "Sell",
"settings": "Settings",
"show-more": "Show More",
"show-zero-balances": "Show Zero Balances",
"solana-tps": "Solana TPS",
"soon": "Soon",
"spot": "Spot",

View File

@ -1,6 +1,7 @@
{
"assets": "Assets",
"assets-liabilities": "Assets & Liabilities",
"collateral-value": "Collateral Value",
"cumulative-interest-chart": "Cumulative Interst Chart",
"daily-volume": "24h Volume",
"export": "Export {{dataType}}",
@ -16,6 +17,7 @@
"no-pnl-history": "No PnL History",
"pnl-chart": "PnL Chart",
"pnl-history": "PnL History",
"tooltip-collateral-value": "The amount of capital this token gives you to use for trades and loans.",
"tooltip-free-collateral": "The amount of capital you have to use for trades and loans. When your free collateral reaches $0 you won't be able to trade, borrow or withdraw",
"tooltip-init-health": "The contribution an asset gives to your initial account health. Initial health affects your ability to open new positions and withdraw collateral from your account. The sum of these values is equal to your account's free collateral.",
"tooltip-leverage": "Total assets value divided by account equity value",
@ -26,5 +28,6 @@
"tooltip-total-interest": "The value of interest earned (deposits) minus interest paid (borrows)",
"total-funding-earned": "Total Funding Earned",
"volume-chart": "Volume Chart",
"week-starting": "Week starting {{week}}"
"week-starting": "Week starting {{week}}",
"zero-collateral": "Zero Collateral"
}

View File

@ -141,7 +141,6 @@
"sell": "卖",
"settings": "设置",
"show-more": "显示更多",
"show-zero-balances": "显示零余额",
"solana-tps": "Solana TPS",
"soon": "Soon",
"spot": "现货",

View File

@ -1,6 +1,7 @@
{
"assets": "Assets",
"assets-liabilities": "Assets & Liabilities",
"collateral-value": "Collateral Value",
"cumulative-interest-chart": "Cumulative Interst Chart",
"daily-volume": "24h Volume",
"export": "Export {{dataType}}",
@ -16,6 +17,7 @@
"no-pnl-history": "No PnL History",
"pnl-chart": "PnL Chart",
"pnl-history": "PnL History",
"tooltip-collateral-value": "The amount of capital this token gives you to use for trades and loans.",
"tooltip-free-collateral": "The amount of capital you have to use for trades and loans. When your free collateral reaches $0 you won't be able to trade, borrow or withdraw",
"tooltip-init-health": "The contribution an asset gives to your initial account health. Initial health affects your ability to open new positions and withdraw collateral from your account. The sum of these values is equal to your account's free collateral.",
"tooltip-leverage": "Total assets value divided by account equity value",
@ -26,5 +28,6 @@
"tooltip-total-interest": "The value of interest earned (deposits) minus interest paid (borrows)",
"total-funding-earned": "Total Funding Earned",
"volume-chart": "Volume Chart",
"week-starting": "Week starting {{week}}"
"week-starting": "Week starting {{week}}",
"zero-collateral": "Zero Collateral"
}

View File

@ -141,7 +141,6 @@
"sell": "賣",
"settings": "設置",
"show-more": "顯示更多",
"show-zero-balances": "顯示零餘額",
"solana-tps": "Solana TPS",
"soon": "Soon",
"spot": "現貨",