From d22c659541161f0d026d26f38ec405db8238263e Mon Sep 17 00:00:00 2001 From: saml33 Date: Tue, 18 Jul 2023 12:58:20 +1000 Subject: [PATCH 1/2] add collateral value to balance tables --- components/TokenList.tsx | 313 +++++++++++++++++----------- components/shared/BalancesTable.tsx | 64 +++++- hooks/useHealthContributions.ts | 24 +++ public/locales/en/account.json | 5 +- public/locales/en/common.json | 1 - public/locales/es/account.json | 5 +- public/locales/es/common.json | 1 - public/locales/ru/account.json | 5 +- public/locales/ru/common.json | 1 - public/locales/zh/account.json | 5 +- public/locales/zh/common.json | 1 - public/locales/zh_tw/account.json | 5 +- public/locales/zh_tw/common.json | 1 - 13 files changed, 300 insertions(+), 131 deletions(-) create mode 100644 hooks/useHealthContributions.ts diff --git a/components/TokenList.tsx b/components/TokenList.tsx index ad7d3bab..df23a32a 100644 --- a/components/TokenList.tsx +++ b/components/TokenList.tsx @@ -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 ( @@ -66,141 +80,174 @@ const TokenList = () => { disabled={!mangoAccount} onChange={() => setShowZeroBalances(!showZeroBalances)} > - {t('show-zero-balances')} + {t('account:zero-collateral')} ) : null} {showTableView ? ( - - - - - + + + ) + })} + +
{t('token')} -
- - {t('balance')} +
+ + + + + + + + + - - - - - - - - - {filteredBanks.map((b) => { - const bank = b.bank + + + + + + + {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 ( - - - - - - + - + + + - - - ) - })} - -
{t('token')} +
+ + {t('balance')} + +
+
+
+ + + {t('account:collateral-value')} + + +
+
{t('trade:in-orders')}{t('trade:unsettled')} + + + {t('interest-earned-paid')} + - - {t('trade:in-orders')}{t('trade:unsettled')} - - - {t('interest-earned-paid')} - - - -
- - {t('rates')} - -
-
- {t('actions')} -
+
+ + {t('rates')} + +
+
+ {t('actions')} +
-
-
- + const collateralValue = + initContributions.find((val) => val.asset === bank.name) + ?.contribution || 0 + + const assetWeight = bank.initAssetWeight.toNumber() + const liabWeight = bank.initLiabWeight.toNumber() + + return ( + +
+
+
+ +
+

{symbol}

-

{symbol}

- -
- - - - - - -
+
- - -
-

+

+

+ +

+

= 0 ? assetWeight : liabWeight + } decimals={2} /> - % + x

- | -

- +

+ + + + +
+ - % -

-
-
-
- -
-
+
+ +
+
+

+ + % +

+ | +

+ + % +

+
+
+
+ +
+
+ ) : (
{filteredBanks.map((b) => { @@ -218,6 +265,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 +295,13 @@ 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.initAssetWeight.toNumber() + const liabWeight = tokenBank.initLiabWeight.toNumber() + return ( {({ open }) => ( @@ -296,6 +351,24 @@ const MobileTokenListItem = ({ bank }: { bank: BankWithBalance }) => { >
+
+ +

+ {t('account:collateral-value')} +

+
+

+ + + {' '} + = 0 ? assetWeight : liabWeight} + decimals={2} + /> + x + +

+

{t('trade:in-orders')} diff --git a/components/shared/BalancesTable.tsx b/components/shared/BalancesTable.tsx index 969e8a85..17f42e80 100644 --- a/components/shared/BalancesTable.tsx +++ b/components/shared/BalancesTable.tsx @@ -26,15 +26,18 @@ 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' 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) { @@ -57,6 +60,15 @@ const BalancesTable = () => { {t('token')} {t('balance')} + +

+ + + {t('account:collateral-value')} + + +
+ {t('trade:in-orders')} {t('trade:unsettled')} @@ -71,6 +83,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.initAssetWeight.toNumber() + const liabWeight = bank.initLiabWeight.toNumber() + return ( @@ -90,6 +109,18 @@ const BalancesTable = () => { />

+ +

+ +

+

+ = 0 ? assetWeight : liabWeight} + decimals={2} + /> + x +

+ @@ -110,6 +141,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.initAssetWeight.toNumber() + const liabWeight = bank.initLiabWeight.toNumber() + return ( {({ open }) => ( @@ -153,6 +191,30 @@ const BalancesTable = () => { >
+
+ +

+ {t('account:collateral-value')} +

+
+

+ + + {' '} + = 0 + ? assetWeight + : liabWeight + } + decimals={2} + /> + x + +

+

{t('trade:in-orders')} diff --git a/hooks/useHealthContributions.ts b/hooks/useHealthContributions.ts new file mode 100644 index 00000000..6845fa78 --- /dev/null +++ b/hooks/useHealthContributions.ts @@ -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 } +} diff --git a/public/locales/en/account.json b/public/locales/en/account.json index 0ac56908..9e25cabf 100644 --- a/public/locales/en/account.json +++ b/public/locales/en/account.json @@ -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}}", @@ -11,6 +12,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-leverage": "Total assets value divided by account equity value", "tooltip-pnl": "The amount your account has profited or lost", @@ -19,5 +21,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" } \ No newline at end of file diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 66a116be..bcc7a73c 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -138,7 +138,6 @@ "sell": "Sell", "settings": "Settings", "show-more": "Show More", - "show-zero-balances": "Show Zero Balances", "solana-tps": "Solana TPS", "soon": "Soon", "spot": "Spot", diff --git a/public/locales/es/account.json b/public/locales/es/account.json index 0ac56908..9e25cabf 100644 --- a/public/locales/es/account.json +++ b/public/locales/es/account.json @@ -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}}", @@ -11,6 +12,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-leverage": "Total assets value divided by account equity value", "tooltip-pnl": "The amount your account has profited or lost", @@ -19,5 +21,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" } \ No newline at end of file diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 66a116be..bcc7a73c 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -138,7 +138,6 @@ "sell": "Sell", "settings": "Settings", "show-more": "Show More", - "show-zero-balances": "Show Zero Balances", "solana-tps": "Solana TPS", "soon": "Soon", "spot": "Spot", diff --git a/public/locales/ru/account.json b/public/locales/ru/account.json index 0ac56908..9e25cabf 100644 --- a/public/locales/ru/account.json +++ b/public/locales/ru/account.json @@ -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}}", @@ -11,6 +12,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-leverage": "Total assets value divided by account equity value", "tooltip-pnl": "The amount your account has profited or lost", @@ -19,5 +21,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" } \ No newline at end of file diff --git a/public/locales/ru/common.json b/public/locales/ru/common.json index 66a116be..bcc7a73c 100644 --- a/public/locales/ru/common.json +++ b/public/locales/ru/common.json @@ -138,7 +138,6 @@ "sell": "Sell", "settings": "Settings", "show-more": "Show More", - "show-zero-balances": "Show Zero Balances", "solana-tps": "Solana TPS", "soon": "Soon", "spot": "Spot", diff --git a/public/locales/zh/account.json b/public/locales/zh/account.json index 0ac56908..9e25cabf 100644 --- a/public/locales/zh/account.json +++ b/public/locales/zh/account.json @@ -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}}", @@ -11,6 +12,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-leverage": "Total assets value divided by account equity value", "tooltip-pnl": "The amount your account has profited or lost", @@ -19,5 +21,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" } \ No newline at end of file diff --git a/public/locales/zh/common.json b/public/locales/zh/common.json index 9b63258f..cd76d608 100644 --- a/public/locales/zh/common.json +++ b/public/locales/zh/common.json @@ -138,7 +138,6 @@ "sell": "卖", "settings": "设置", "show-more": "显示更多", - "show-zero-balances": "显示零余额", "solana-tps": "Solana TPS", "soon": "Soon", "spot": "现货", diff --git a/public/locales/zh_tw/account.json b/public/locales/zh_tw/account.json index 0ac56908..9e25cabf 100644 --- a/public/locales/zh_tw/account.json +++ b/public/locales/zh_tw/account.json @@ -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}}", @@ -11,6 +12,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-leverage": "Total assets value divided by account equity value", "tooltip-pnl": "The amount your account has profited or lost", @@ -19,5 +21,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" } \ No newline at end of file diff --git a/public/locales/zh_tw/common.json b/public/locales/zh_tw/common.json index d9aede3d..2d6b7053 100644 --- a/public/locales/zh_tw/common.json +++ b/public/locales/zh_tw/common.json @@ -138,7 +138,6 @@ "sell": "賣", "settings": "設置", "show-more": "顯示更多", - "show-zero-balances": "顯示零餘額", "solana-tps": "Solana TPS", "soon": "Soon", "spot": "現貨", From 550564752480dc64bc8d90a5f022554191b9556b Mon Sep 17 00:00:00 2001 From: saml33 Date: Tue, 18 Jul 2023 13:09:57 +1000 Subject: [PATCH 2/2] use scaled weight and fix rounding --- components/TokenList.tsx | 34 ++++++++++++++++++++--------- components/shared/BalancesTable.tsx | 34 +++++++++++++++++++---------- 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/components/TokenList.tsx b/components/TokenList.tsx index df23a32a..c1f90be9 100644 --- a/components/TokenList.tsx +++ b/components/TokenList.tsx @@ -160,8 +160,12 @@ const TokenList = () => { initContributions.find((val) => val.asset === bank.name) ?.contribution || 0 - const assetWeight = bank.initAssetWeight.toNumber() - const liabWeight = bank.initLiabWeight.toNumber() + const assetWeight = bank + .scaledInitAssetWeight(bank.price) + .toFixed(2) + const liabWeight = bank + .scaledInitLiabWeight(bank.price) + .toFixed(2) return ( @@ -182,14 +186,17 @@ const TokenList = () => {

- +

= 0 ? assetWeight : liabWeight + collateralValue <= -0.01 ? liabWeight : assetWeight } - decimals={2} /> x

@@ -299,8 +306,10 @@ const MobileTokenListItem = ({ bank }: { bank: BankWithBalance }) => { initContributions.find((val) => val.asset === tokenBank.name) ?.contribution || 0 - const assetWeight = tokenBank.initAssetWeight.toNumber() - const liabWeight = tokenBank.initLiabWeight.toNumber() + const assetWeight = tokenBank + .scaledInitAssetWeight(tokenBank.price) + .toFixed(2) + const liabWeight = tokenBank.scaledInitLiabWeight(tokenBank.price).toFixed(2) return ( @@ -358,12 +367,17 @@ const MobileTokenListItem = ({ bank }: { bank: BankWithBalance }) => {

- + {' '} = 0 ? assetWeight : liabWeight} - decimals={2} + value={ + collateralValue <= -0.01 ? liabWeight : assetWeight + } /> x diff --git a/components/shared/BalancesTable.tsx b/components/shared/BalancesTable.tsx index 17f42e80..df74c192 100644 --- a/components/shared/BalancesTable.tsx +++ b/components/shared/BalancesTable.tsx @@ -87,8 +87,10 @@ const BalancesTable = () => { initContributions.find((val) => val.asset === bank.name) ?.contribution || 0 - const assetWeight = bank.initAssetWeight.toNumber() - const liabWeight = bank.initLiabWeight.toNumber() + const assetWeight = bank + .scaledInitAssetWeight(bank.price) + .toFixed(2) + const liabWeight = bank.scaledInitLiabWeight(bank.price).toFixed(2) return ( @@ -111,12 +113,17 @@ const BalancesTable = () => {

- +

= 0 ? assetWeight : liabWeight} - decimals={2} + value={ + collateralValue <= -0.01 ? liabWeight : assetWeight + } /> x

@@ -145,8 +152,8 @@ const BalancesTable = () => { initContributions.find((val) => val.asset === bank.name) ?.contribution || 0 - const assetWeight = bank.initAssetWeight.toNumber() - const liabWeight = bank.initLiabWeight.toNumber() + const assetWeight = bank.scaledInitAssetWeight(bank.price).toFixed(2) + const liabWeight = bank.scaledInitLiabWeight(bank.price).toFixed(2) return ( @@ -200,16 +207,19 @@ const BalancesTable = () => {

- + {' '} = 0 - ? assetWeight - : liabWeight + collateralValue <= -0.01 + ? liabWeight + : assetWeight } - decimals={2} /> x