diff --git a/components/account/HealthContributions.tsx b/components/account/HealthContributions.tsx index 95ecf040..4261cc70 100644 --- a/components/account/HealthContributions.tsx +++ b/components/account/HealthContributions.tsx @@ -5,19 +5,15 @@ import { useMemo, useState } from 'react' import { HealthType } from '@blockworks-foundation/mango-v4' import { ArrowLeftIcon, - ChevronDownIcon, QuestionMarkCircleIcon, } from '@heroicons/react/20/solid' -import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements' import Tooltip from '@components/shared/Tooltip' import TokenLogo from '@components/shared/TokenLogo' import { useTranslation } from 'next-i18next' import MarketLogos from '@components/trade/MarketLogos' -import FormatNumericValue from '@components/shared/FormatNumericValue' import mangoStore from '@store/mangoStore' -import { useViewport } from 'hooks/useViewport' -import { breakpoints } from 'utils/theme' -import { Disclosure, Transition } from '@headlessui/react' +import TokensHealthTable from './TokensHealthTable' +import MarketsHealthTable from './MarketsHealthTable' export interface HealthContribution { asset: string @@ -35,8 +31,6 @@ const HealthContributions = ({ hideView }: { hideView: () => void }) => { const [maintActiveIndex, setMaintActiveIndex] = useState( undefined ) - const { width } = useViewport() - const isMobile = width ? width < breakpoints.sm : false const [initHealthContributions, maintHealthContributions] = useMemo(() => { if (!group || !mangoAccount) return [[], []] @@ -228,547 +222,25 @@ const HealthContributions = ({ hideView }: { hideView: () => void }) => { {maintHealthTokens.length ? (

{t('tokens')}

- {!isMobile ? ( - - - - - - - - - - - {maintHealthTokens - .sort((a, b) => b.contribution - a.contribution) - .map((cont) => { - const { asset, contribution, isAsset } = cont - const bank = group.banksMapByName.get(asset)?.[0] - - let initAssetWeight = 0 - let initLiabWeight = 0 - let maintAssetWeight = 0 - let maintLiabWeight = 0 - - let balance = 0 - - if (bank) { - initAssetWeight = bank - .scaledInitAssetWeight(bank.price) - .toNumber() - initLiabWeight = bank - .scaledInitLiabWeight(bank.price) - .toNumber() - maintAssetWeight = bank.maintAssetWeight.toNumber() - maintLiabWeight = bank.maintLiabWeight.toNumber() - - balance = mangoAccount.getTokenBalanceUi(bank) - } - - const assetOrLiabMultiplier = isAsset ? 1 : -1 - - const initContribution = - (initHealthTokens.find((cont) => cont.asset === asset) - ?.contribution || 0) * assetOrLiabMultiplier - - const maintContribution = - contribution * assetOrLiabMultiplier - - return ( - handleLegendClick(cont)} - onMouseEnter={() => handleLegendMouseEnter(cont)} - onMouseLeave={handleLegendMouseLeave} - > - - - - - - ) - })} - -
{t('token')}{t('trade:notional')} -
- - - {t('account:init-health-contributions')} - - -
-
-
- - - {t('account:maint-health-contributions')} - - -
-
-
-
- -
-

{asset}

-
-
- {bank ? ( -

- {' '} - - - -

- ) : ( - '–' - )} -
-
-

- -

-

- {initContribution > 0 - ? initAssetWeight.toFixed(2) - : initContribution < 0 - ? initLiabWeight.toFixed(2) - : 0} - x -

-
-
-
-

- -

-

- {maintContribution > 0 - ? maintAssetWeight.toFixed(2) - : maintContribution < 0 - ? maintLiabWeight.toFixed(2) - : 0} - x -

-
-
- ) : ( -
- {maintHealthTokens - .sort((a, b) => b.contribution - a.contribution) - .map((cont) => { - const { asset, contribution, isAsset } = cont - const bank = group.banksMapByName.get(asset)?.[0] - - let initAssetWeight = 0 - let initLiabWeight = 0 - let maintAssetWeight = 0 - let maintLiabWeight = 0 - - let balance = 0 - - if (bank) { - initAssetWeight = bank - .scaledInitAssetWeight(bank.price) - .toNumber() - initLiabWeight = bank - .scaledInitLiabWeight(bank.price) - .toNumber() - maintAssetWeight = bank.maintAssetWeight.toNumber() - maintLiabWeight = bank.maintLiabWeight.toNumber() - - balance = mangoAccount.getTokenBalanceUi(bank) - } - - const assetOrLiabMultiplier = isAsset ? 1 : -1 - - const initContribution = - (initHealthTokens.find((cont) => cont.asset === asset) - ?.contribution || 0) * assetOrLiabMultiplier - - const maintContribution = contribution * assetOrLiabMultiplier - - return ( - - {({ open }) => ( - <> - -
-
-
- -
-
-

{asset}

-
-
- -
-
- - -
-
-

- {t('trade:notional')} -

-

- {bank ? ( - - {' '} - - - - - ) : ( - '–' - )} -

-
-
-

- - - {t('account:init-health-contributions')} - - -

-

- -

-

- {initContribution > 0 - ? initAssetWeight.toFixed(2) - : initContribution < 0 - ? initLiabWeight.toFixed(2) - : 0} - x -

-
-
-

- - - {t( - 'account:maint-health-contributions' - )} - - -

-

- -

-

- {maintContribution > 0 - ? maintAssetWeight.toFixed(2) - : maintContribution < 0 - ? maintLiabWeight.toFixed(2) - : 0} - x -

-
-
-
-
- - )} -
- ) - })} -
- )} +
) : null} {maintHealthMarkets.length ? (

{t('markets')}

- {!isMobile ? ( - - - - - - - - - - {maintHealthMarkets - .sort((a, b) => b.contribution - a.contribution) - .map((cont) => { - const { asset, contribution, isAsset } = cont - const market = group.getSerum3MarketByName(asset) - const bank = group.banksMapByTokenIndex.get( - market.baseTokenIndex - )?.[0] - - let initAssetWeight = 0 - let initLiabWeight = 0 - let maintAssetWeight = 0 - let maintLiabWeight = 0 - - if (bank) { - initAssetWeight = bank - .scaledInitAssetWeight(bank.price) - .toNumber() - initLiabWeight = bank - .scaledInitLiabWeight(bank.price) - .toNumber() - maintAssetWeight = bank.maintAssetWeight.toNumber() - maintLiabWeight = bank.maintLiabWeight.toNumber() - } - - const assetOrLiabMultiplier = isAsset ? 1 : -1 - - const initContribution = - (initHealthMarkets.find((cont) => cont.asset === asset) - ?.contribution || 0) * assetOrLiabMultiplier - - const maintContribution = - contribution * assetOrLiabMultiplier - - return ( - - - - - - ) - })} - -
{t('market')} -
- - - {t('account:init-health-contributions')} - - -
-
-
- - - {t('account:maint-health-contributions')} - - -
-
-
- -

{asset}

-
-
-
-

- -

-

- {initContribution > 0 - ? initAssetWeight.toFixed(2) - : initContribution < 0 - ? initLiabWeight.toFixed(2) - : 0} - x -

-
-
-
-

- -

-

- {maintContribution > 0 - ? maintAssetWeight.toFixed(2) - : maintContribution < 0 - ? maintLiabWeight.toFixed(2) - : 0} - x -

-
-
- ) : ( -
- {maintHealthMarkets - .sort((a, b) => b.contribution - a.contribution) - .map((cont) => { - const { asset, contribution, isAsset } = cont - const market = group.getSerum3MarketByName(asset) - const bank = group.banksMapByTokenIndex.get( - market.baseTokenIndex - )?.[0] - - let initAssetWeight = 0 - let initLiabWeight = 0 - let maintAssetWeight = 0 - let maintLiabWeight = 0 - - if (bank) { - initAssetWeight = bank - .scaledInitAssetWeight(bank.price) - .toNumber() - initLiabWeight = bank - .scaledInitLiabWeight(bank.price) - .toNumber() - maintAssetWeight = bank.maintAssetWeight.toNumber() - maintLiabWeight = bank.maintLiabWeight.toNumber() - } - - const assetOrLiabMultiplier = isAsset ? 1 : -1 - - const initContribution = - (initHealthMarkets.find((cont) => cont.asset === asset) - ?.contribution || 0) * assetOrLiabMultiplier - - const maintContribution = contribution * assetOrLiabMultiplier - - return ( - - {({ open }) => ( - <> - -
-
- -
-

{asset}

-
-
- -
-
- - -
-
-

- - - {t('account:init-health-contributions')} - - -

-

- -

-

- {initContribution > 0 - ? initAssetWeight.toFixed(2) - : initContribution < 0 - ? initLiabWeight.toFixed(2) - : 0} - x -

-
-
-

- - - {t( - 'account:maint-health-contributions' - )} - - -

-

- -

-

- {maintContribution > 0 - ? maintAssetWeight.toFixed(2) - : maintContribution < 0 - ? maintLiabWeight.toFixed(2) - : 0} - x -

-
-
-
-
- - )} -
- ) - })} -
- )} +
) : null} diff --git a/components/account/MarketsHealthTable.tsx b/components/account/MarketsHealthTable.tsx new file mode 100644 index 00000000..b0f13c79 --- /dev/null +++ b/components/account/MarketsHealthTable.tsx @@ -0,0 +1,276 @@ +import FormatNumericValue from '@components/shared/FormatNumericValue' +import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements' +import Tooltip from '@components/shared/Tooltip' +import { Disclosure, Transition } from '@headlessui/react' +import { ChevronDownIcon } from '@heroicons/react/20/solid' +import { useTranslation } from 'next-i18next' +import { HealthContribution } from './HealthContributions' +import useMangoGroup from 'hooks/useMangoGroup' +import useMangoAccount from 'hooks/useMangoAccount' +import { useViewport } from 'hooks/useViewport' +import { breakpoints } from 'utils/theme' +import { MouseEventHandler } from 'react' +import MarketLogos from '@components/trade/MarketLogos' + +const MarketsHealthTable = ({ + initMarkets, + maintMarkets, + handleLegendClick, + handleLegendMouseEnter, + handleLegendMouseLeave, +}: { + initMarkets: HealthContribution[] + maintMarkets: HealthContribution[] + handleLegendClick: (cont: HealthContribution) => void + handleLegendMouseEnter: (cont: HealthContribution) => void + handleLegendMouseLeave: MouseEventHandler +}) => { + const { t } = useTranslation(['common', 'account', 'trade']) + const { group } = useMangoGroup() + const { mangoAccount } = useMangoAccount() + const { width } = useViewport() + const isMobile = width ? width < breakpoints.sm : false + return group && mangoAccount ? ( + !isMobile ? ( + + + + + + + + + + {maintMarkets + .sort((a, b) => b.contribution - a.contribution) + .map((cont) => { + const { asset, contribution, isAsset } = cont + const market = group.getSerum3MarketByName(asset) + const bank = group.banksMapByTokenIndex.get( + market.baseTokenIndex + )?.[0] + + let initAssetWeight = 0 + let initLiabWeight = 0 + let maintAssetWeight = 0 + let maintLiabWeight = 0 + + if (bank) { + initAssetWeight = bank + .scaledInitAssetWeight(bank.price) + .toNumber() + initLiabWeight = bank + .scaledInitLiabWeight(bank.price) + .toNumber() + maintAssetWeight = bank.maintAssetWeight.toNumber() + maintLiabWeight = bank.maintLiabWeight.toNumber() + } + + const assetOrLiabMultiplier = isAsset ? 1 : -1 + + const initContribution = + (initMarkets.find((cont) => cont.asset === asset) + ?.contribution || 0) * assetOrLiabMultiplier + + const maintContribution = contribution * assetOrLiabMultiplier + + return ( + handleLegendClick(cont)} + onMouseEnter={() => handleLegendMouseEnter(cont)} + onMouseLeave={handleLegendMouseLeave} + > + + + + + ) + })} + +
{t('market')} +
+ + + {t('account:init-health-contribution')} + + +
+
+
+ + + {t('account:maint-health-contribution')} + + +
+
+
+ +

{asset}

+
+
+
+

+ +

+

+ {initContribution > 0 + ? initAssetWeight.toFixed(2) + : initContribution < 0 + ? initLiabWeight.toFixed(2) + : 0} + x +

+
+
+
+

+ +

+

+ {maintContribution > 0 + ? maintAssetWeight.toFixed(2) + : maintContribution < 0 + ? maintLiabWeight.toFixed(2) + : 0} + x +

+
+
+ ) : ( +
+ {maintMarkets + .sort((a, b) => b.contribution - a.contribution) + .map((cont) => { + const { asset, contribution, isAsset } = cont + const market = group.getSerum3MarketByName(asset) + const bank = group.banksMapByTokenIndex.get( + market.baseTokenIndex + )?.[0] + + let initAssetWeight = 0 + let initLiabWeight = 0 + let maintAssetWeight = 0 + let maintLiabWeight = 0 + + if (bank) { + initAssetWeight = bank + .scaledInitAssetWeight(bank.price) + .toNumber() + initLiabWeight = bank.scaledInitLiabWeight(bank.price).toNumber() + maintAssetWeight = bank.maintAssetWeight.toNumber() + maintLiabWeight = bank.maintLiabWeight.toNumber() + } + + const assetOrLiabMultiplier = isAsset ? 1 : -1 + + const initContribution = + (initMarkets.find((cont) => cont.asset === asset)?.contribution || + 0) * assetOrLiabMultiplier + + const maintContribution = contribution * assetOrLiabMultiplier + + return ( + + {({ open }) => ( + <> + +
+
+ +
+

{asset}

+
+
+ +
+
+ + +
+
+

+ + + {t('account:init-health-contribution')} + + +

+

+ +

+

+ {initContribution > 0 + ? initAssetWeight.toFixed(2) + : initContribution < 0 + ? initLiabWeight.toFixed(2) + : 0} + x +

+
+
+

+ + + {t('account:maint-health-contribution')} + + +

+

+ +

+

+ {maintContribution > 0 + ? maintAssetWeight.toFixed(2) + : maintContribution < 0 + ? maintLiabWeight.toFixed(2) + : 0} + x +

+
+
+
+
+ + )} +
+ ) + })} +
+ ) + ) : null +} + +export default MarketsHealthTable diff --git a/components/account/TokensHealthTable.tsx b/components/account/TokensHealthTable.tsx new file mode 100644 index 00000000..9ba0b7cd --- /dev/null +++ b/components/account/TokensHealthTable.tsx @@ -0,0 +1,326 @@ +import FormatNumericValue from '@components/shared/FormatNumericValue' +import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements' +import TokenLogo from '@components/shared/TokenLogo' +import Tooltip from '@components/shared/Tooltip' +import { Disclosure, Transition } from '@headlessui/react' +import { ChevronDownIcon } from '@heroicons/react/20/solid' +import { useTranslation } from 'next-i18next' +import { HealthContribution } from './HealthContributions' +import useMangoGroup from 'hooks/useMangoGroup' +import useMangoAccount from 'hooks/useMangoAccount' +import { useViewport } from 'hooks/useViewport' +import { breakpoints } from 'utils/theme' +import { MouseEventHandler } from 'react' + +const TokensHealthTable = ({ + initTokens, + maintTokens, + handleLegendClick, + handleLegendMouseEnter, + handleLegendMouseLeave, +}: { + initTokens: HealthContribution[] + maintTokens: HealthContribution[] + handleLegendClick: (cont: HealthContribution) => void + handleLegendMouseEnter: (cont: HealthContribution) => void + handleLegendMouseLeave: MouseEventHandler +}) => { + const { t } = useTranslation(['common', 'account', 'trade']) + const { group } = useMangoGroup() + const { mangoAccount } = useMangoAccount() + const { width } = useViewport() + const isMobile = width ? width < breakpoints.sm : false + return group && mangoAccount ? ( + !isMobile ? ( + + + + + + + + + + + {maintTokens + .sort((a, b) => b.contribution - a.contribution) + .map((cont) => { + const { asset, contribution, isAsset } = cont + const bank = group.banksMapByName.get(asset)?.[0] + + let initAssetWeight = 0 + let initLiabWeight = 0 + let maintAssetWeight = 0 + let maintLiabWeight = 0 + + let balance = 0 + + if (bank) { + initAssetWeight = bank + .scaledInitAssetWeight(bank.price) + .toNumber() + initLiabWeight = bank + .scaledInitLiabWeight(bank.price) + .toNumber() + maintAssetWeight = bank.maintAssetWeight.toNumber() + maintLiabWeight = bank.maintLiabWeight.toNumber() + + balance = mangoAccount.getTokenBalanceUi(bank) + } + + const assetOrLiabMultiplier = isAsset ? 1 : -1 + + const initContribution = + (initTokens.find((cont) => cont.asset === asset) + ?.contribution || 0) * assetOrLiabMultiplier + + const maintContribution = contribution * assetOrLiabMultiplier + + return ( + handleLegendClick(cont)} + onMouseEnter={() => handleLegendMouseEnter(cont)} + onMouseLeave={handleLegendMouseLeave} + > + + + + + + ) + })} + +
{t('token')}{t('trade:notional')} +
+ + + {t('account:init-health-contribution')} + + +
+
+
+ + + {t('account:maint-health-contribution')} + + +
+
+
+
+ +
+

{asset}

+
+
+ {bank ? ( +

+ {' '} + + + +

+ ) : ( + '–' + )} +
+
+

+ +

+

+ {initContribution > 0 + ? initAssetWeight.toFixed(2) + : initContribution < 0 + ? initLiabWeight.toFixed(2) + : 0} + x +

+
+
+
+

+ +

+

+ {maintContribution > 0 + ? maintAssetWeight.toFixed(2) + : maintContribution < 0 + ? maintLiabWeight.toFixed(2) + : 0} + x +

+
+
+ ) : ( +
+ {maintTokens + .sort((a, b) => b.contribution - a.contribution) + .map((cont) => { + const { asset, contribution, isAsset } = cont + const bank = group.banksMapByName.get(asset)?.[0] + + let initAssetWeight = 0 + let initLiabWeight = 0 + let maintAssetWeight = 0 + let maintLiabWeight = 0 + + let balance = 0 + + if (bank) { + initAssetWeight = bank + .scaledInitAssetWeight(bank.price) + .toNumber() + initLiabWeight = bank.scaledInitLiabWeight(bank.price).toNumber() + maintAssetWeight = bank.maintAssetWeight.toNumber() + maintLiabWeight = bank.maintLiabWeight.toNumber() + + balance = mangoAccount.getTokenBalanceUi(bank) + } + + const assetOrLiabMultiplier = isAsset ? 1 : -1 + + const initContribution = + (initTokens.find((cont) => cont.asset === asset)?.contribution || + 0) * assetOrLiabMultiplier + + const maintContribution = contribution * assetOrLiabMultiplier + + return ( + + {({ open }) => ( + <> + +
+
+
+ +
+
+

{asset}

+
+
+ +
+
+ + +
+
+

+ {t('trade:notional')} +

+

+ {bank ? ( + + {' '} + + + + + ) : ( + '–' + )} +

+
+
+

+ + + {t('account:init-health-contribution')} + + +

+

+ +

+

+ {initContribution > 0 + ? initAssetWeight.toFixed(2) + : initContribution < 0 + ? initLiabWeight.toFixed(2) + : 0} + x +

+
+
+

+ + + {t('account:maint-health-contribution')} + + +

+

+ +

+

+ {maintContribution > 0 + ? maintAssetWeight.toFixed(2) + : maintContribution < 0 + ? maintLiabWeight.toFixed(2) + : 0} + x +

+
+
+
+
+ + )} +
+ ) + })} +
+ ) + ) : null +} + +export default TokensHealthTable diff --git a/public/locales/en/account.json b/public/locales/en/account.json index e3d187ba..8fb3b404 100644 --- a/public/locales/en/account.json +++ b/public/locales/en/account.json @@ -6,9 +6,11 @@ "export": "Export {{dataType}}", "funding-chart": "Funding Chart", "health-contributions": "Health Contributions", + "init-health-contribution": "Init Health Contribution", "init-health-contributions": "Init Health Contributions", "liabilities": "Liabilities", "lifetime-volume": "Lifetime Trade Volume", + "maint-health-contribution": "Maint Health Contribution", "maint-health-contributions": "Maint Health Contributions", "no-data": "No data to display", "no-pnl-history": "No PnL History", diff --git a/public/locales/es/account.json b/public/locales/es/account.json index e3d187ba..8fb3b404 100644 --- a/public/locales/es/account.json +++ b/public/locales/es/account.json @@ -6,9 +6,11 @@ "export": "Export {{dataType}}", "funding-chart": "Funding Chart", "health-contributions": "Health Contributions", + "init-health-contribution": "Init Health Contribution", "init-health-contributions": "Init Health Contributions", "liabilities": "Liabilities", "lifetime-volume": "Lifetime Trade Volume", + "maint-health-contribution": "Maint Health Contribution", "maint-health-contributions": "Maint Health Contributions", "no-data": "No data to display", "no-pnl-history": "No PnL History", diff --git a/public/locales/ru/account.json b/public/locales/ru/account.json index e3d187ba..8fb3b404 100644 --- a/public/locales/ru/account.json +++ b/public/locales/ru/account.json @@ -6,9 +6,11 @@ "export": "Export {{dataType}}", "funding-chart": "Funding Chart", "health-contributions": "Health Contributions", + "init-health-contribution": "Init Health Contribution", "init-health-contributions": "Init Health Contributions", "liabilities": "Liabilities", "lifetime-volume": "Lifetime Trade Volume", + "maint-health-contribution": "Maint Health Contribution", "maint-health-contributions": "Maint Health Contributions", "no-data": "No data to display", "no-pnl-history": "No PnL History", diff --git a/public/locales/zh/account.json b/public/locales/zh/account.json index e3d187ba..8fb3b404 100644 --- a/public/locales/zh/account.json +++ b/public/locales/zh/account.json @@ -6,9 +6,11 @@ "export": "Export {{dataType}}", "funding-chart": "Funding Chart", "health-contributions": "Health Contributions", + "init-health-contribution": "Init Health Contribution", "init-health-contributions": "Init Health Contributions", "liabilities": "Liabilities", "lifetime-volume": "Lifetime Trade Volume", + "maint-health-contribution": "Maint Health Contribution", "maint-health-contributions": "Maint Health Contributions", "no-data": "No data to display", "no-pnl-history": "No PnL History", diff --git a/public/locales/zh_tw/account.json b/public/locales/zh_tw/account.json index e3d187ba..8fb3b404 100644 --- a/public/locales/zh_tw/account.json +++ b/public/locales/zh_tw/account.json @@ -6,9 +6,11 @@ "export": "Export {{dataType}}", "funding-chart": "Funding Chart", "health-contributions": "Health Contributions", + "init-health-contribution": "Init Health Contribution", "init-health-contributions": "Init Health Contributions", "liabilities": "Liabilities", "lifetime-volume": "Lifetime Trade Volume", + "maint-health-contribution": "Maint Health Contribution", "maint-health-contributions": "Maint Health Contributions", "no-data": "No data to display", "no-pnl-history": "No PnL History",