diff --git a/src/components/Portfolio/Account/Summary.tsx b/src/components/Portfolio/Account/Summary.tsx index b0e392b6..18962e72 100644 --- a/src/components/Portfolio/Account/Summary.tsx +++ b/src/components/Portfolio/Account/Summary.tsx @@ -1,26 +1,16 @@ import React, { Suspense, useMemo } from 'react' -import HealthBar from 'components/Account/HealthBar' -import Card from 'components/Card' import DisplayCurrency from 'components/DisplayCurrency' import { FormattedNumber } from 'components/FormattedNumber' -import { Heart } from 'components/Icons' -import Loading from 'components/Loading' -import Text from 'components/Text' -import TitleAndSubCell from 'components/TitleAndSubCell' +import Skeleton from 'components/Portfolio/SummarySkeleton' import { MAX_AMOUNT_DECIMALS } from 'constants/math' -import { ORACLE_DENOM } from 'constants/oracle' import useAccount from 'hooks/useAccount' import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData' import useHealthComputer from 'hooks/useHealthComputer' import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData' import usePrices from 'hooks/usePrices' -import { BNCoin } from 'types/classes/BNCoin' -import { - calculateAccountApr, - calculateAccountLeverage, - getAccountPositionValues, -} from 'utils/accounts' +import { getAccountSummaryStats } from 'utils/accounts' +import { DEFAULT_PORTFOLIO_STATS } from 'utils/constants' interface Props { accountId: string @@ -34,40 +24,27 @@ function Content(props: Props) { const { allAssets: lendingAssets } = useLendingMarketAssetsTableData() const stats = useMemo(() => { - if (!account || !borrowAssets.length || !lendingAssets.length) return STATS + if (!account || !borrowAssets.length || !lendingAssets.length) return DEFAULT_PORTFOLIO_STATS - const [deposits, lends, debts, vaults] = getAccountPositionValues(account, prices) - const positionValue = deposits.plus(lends).plus(vaults) - const apr = calculateAccountApr(account, borrowAssets, lendingAssets, prices) - const leverage = calculateAccountLeverage(account, prices) + const { positionValue, debts, netWorth, apr, leverage } = getAccountSummaryStats( + account, + prices, + borrowAssets, + lendingAssets, + ) return [ { - title: ( - - ), - sub: STATS[0].sub, + title: , + sub: DEFAULT_PORTFOLIO_STATS[0].sub, }, { - title: ( - - ), - sub: STATS[1].sub, + title: , + sub: DEFAULT_PORTFOLIO_STATS[1].sub, }, { - title: ( - - ), - sub: STATS[2].sub, + title: , + sub: DEFAULT_PORTFOLIO_STATS[2].sub, }, { title: ( @@ -81,7 +58,7 @@ function Content(props: Props) { }} /> ), - sub: STATS[3].sub, + sub: DEFAULT_PORTFOLIO_STATS[3].sub, }, { title: ( @@ -91,56 +68,18 @@ function Content(props: Props) { options={{ suffix: 'x' }} /> ), - sub: STATS[4].sub, + sub: DEFAULT_PORTFOLIO_STATS[4].sub, }, ] }, [account, borrowAssets, lendingAssets, prices]) - return + return } export default function Summary(props: Props) { return ( - }> + }> ) } - -interface SkeletonProps extends Props { - stats: { title: React.ReactNode | null; sub: string }[] - health: number -} - -function Skeleton(props: SkeletonProps) { - return ( -
-
- Credit Account {props.accountId} -
- - -
-
-
- {props.stats.map((stat) => ( - - } - sub={stat.sub} - className='mb-1' - /> - - ))} -
-
- ) -} - -const STATS = [ - { title: null, sub: 'Total Balance' }, - { title: null, sub: 'Total Debt' }, - { title: null, sub: 'Net Worth' }, - { title: null, sub: 'APR' }, - { title: null, sub: 'Account Leverage' }, -] diff --git a/src/components/Portfolio/Overview/Summary.tsx b/src/components/Portfolio/Overview/Summary.tsx new file mode 100644 index 00000000..3f45b79f --- /dev/null +++ b/src/components/Portfolio/Overview/Summary.tsx @@ -0,0 +1,93 @@ +import React, { useMemo } from 'react' +import { useParams } from 'react-router-dom' + +import DisplayCurrency from 'components/DisplayCurrency' +import { FormattedNumber } from 'components/FormattedNumber' +import SummarySkeleton from 'components/Portfolio/SummarySkeleton' +import { MAX_AMOUNT_DECIMALS } from 'constants/math' +import useAccounts from 'hooks/useAccounts' +import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData' +import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData' +import usePrices from 'hooks/usePrices' +import useStore from 'store' +import { getAccountSummaryStats } from 'utils/accounts' +import { DEFAULT_PORTFOLIO_STATS } from 'utils/constants' + +export default function PortfolioSummary() { + const { address: urlAddress } = useParams() + const walletAddress = useStore((s) => s.address) + const { data: prices } = usePrices() + const { allAssets: borrowAssets } = useBorrowMarketAssetsTableData() + const { allAssets: lendingAssets } = useLendingMarketAssetsTableData() + const { data: accounts } = useAccounts(urlAddress || walletAddress) + + const stats = useMemo(() => { + if (!accounts?.length) return + const combinedAccount = accounts.reduce( + (combinedAccount, account) => { + combinedAccount.debts = combinedAccount.debts.concat(account.debts) + combinedAccount.deposits = combinedAccount.deposits.concat(account.deposits) + combinedAccount.lends = combinedAccount.lends.concat(account.lends) + combinedAccount.vaults = combinedAccount.vaults.concat(account.vaults) + return combinedAccount + }, + { + id: '1', + deposits: [], + lends: [], + debts: [], + vaults: [], + } as Account, + ) + + const { positionValue, debts, netWorth, apr, leverage } = getAccountSummaryStats( + combinedAccount, + prices, + borrowAssets, + lendingAssets, + ) + + return [ + { + title: , + sub: DEFAULT_PORTFOLIO_STATS[0].sub, + }, + { + title: , + sub: DEFAULT_PORTFOLIO_STATS[1].sub, + }, + { + title: , + sub: DEFAULT_PORTFOLIO_STATS[2].sub, + }, + { + title: ( + + ), + sub: 'Combined APR', + }, + { + title: ( + + ), + sub: 'Combined leverage', + }, + ] + }, [accounts, borrowAssets, lendingAssets, prices]) + + if (!walletAddress && !urlAddress) return null + + return +} diff --git a/src/components/Portfolio/Overview/index.tsx b/src/components/Portfolio/Overview/index.tsx index 2d97b2b2..ec870b08 100644 --- a/src/components/Portfolio/Overview/index.tsx +++ b/src/components/Portfolio/Overview/index.tsx @@ -1,5 +1,5 @@ import classNames from 'classnames' -import { useCallback } from 'react' +import React, { useCallback } from 'react' import { useParams } from 'react-router-dom' import AccountCreateFirst from 'components/Account/AccountCreateFirst' @@ -16,7 +16,7 @@ import useStore from 'store' import { defaultFee } from 'utils/constants' import { BN } from 'utils/helpers' -export default function Content() { +export default function AccountSummary() { const { address: urlAddress } = useParams() const walletAddress = useStore((s) => s.address) const { data: accountIds, isLoading } = useAccountIds(urlAddress) @@ -65,12 +65,17 @@ export default function Content() { } return ( -
- {accountIds.map((accountId: string, index: number) => { - return - })} +
+ + Credit Accounts + +
+ {accountIds.map((accountId: string, index: number) => { + return + })} +
) } diff --git a/src/components/Portfolio/SummarySkeleton.tsx b/src/components/Portfolio/SummarySkeleton.tsx new file mode 100644 index 00000000..5c30862b --- /dev/null +++ b/src/components/Portfolio/SummarySkeleton.tsx @@ -0,0 +1,43 @@ +import React from 'react' + +import HealthBar from 'components/Account/HealthBar' +import Card from 'components/Card' +import { Heart } from 'components/Icons' +import Loading from 'components/Loading' +import Text from 'components/Text' +import TitleAndSubCell from 'components/TitleAndSubCell' +import { DEFAULT_PORTFOLIO_STATS } from 'utils/constants' + +interface Props { + stats?: { title: React.ReactNode | null; sub: string }[] + health?: number + title: string +} + +export default function SummarySkeleton(props: Props) { + const stats = props.stats || DEFAULT_PORTFOLIO_STATS + return ( +
+
+ {props.title} + {props.health !== undefined && ( +
+ + +
+ )} +
+
+ {stats.map((stat) => ( + + } + sub={stat.sub} + className='mb-1' + /> + + ))} +
+
+ ) +} diff --git a/src/pages/PortfolioPage.tsx b/src/pages/PortfolioPage.tsx index d7ddd49f..9c676797 100644 --- a/src/pages/PortfolioPage.tsx +++ b/src/pages/PortfolioPage.tsx @@ -1,5 +1,6 @@ import MigrationBanner from 'components/MigrationBanner' import AccountOverview from 'components/Portfolio/Overview' +import PortfolioSummary from 'components/Portfolio/Overview/Summary' import PortfolioIntro from 'components/Portfolio/PortfolioIntro' export default function PortfolioPage() { @@ -7,6 +8,7 @@ export default function PortfolioPage() {
+
) diff --git a/src/utils/accounts.ts b/src/utils/accounts.ts index 61aa1fea..949f89b7 100644 --- a/src/utils/accounts.ts +++ b/src/utils/accounts.ts @@ -1,6 +1,7 @@ import BigNumber from 'bignumber.js' import { BN_ZERO } from 'constants/math' +import { ORACLE_DENOM } from 'constants/oracle' import { BNCoin } from 'types/classes/BNCoin' import { Positions, @@ -249,3 +250,23 @@ export function computeHealthGaugePercentage(health: number) { return 100 - (health / ATTENTION_CUTOFF) * UNHEALTHY_BAR_SIZE } + +export function getAccountSummaryStats( + account: Account, + prices: BNCoin[], + borrowAssets: BorrowMarketTableData[], + lendingAssets: LendingMarketTableData[], +) { + const [deposits, lends, debts, vaults] = getAccountPositionValues(account, prices) + const positionValue = deposits.plus(lends).plus(vaults) + const apr = calculateAccountApr(account, borrowAssets, lendingAssets, prices) + const leverage = calculateAccountLeverage(account, prices) + + return { + positionValue: BNCoin.fromDenomAndBigNumber(ORACLE_DENOM, positionValue), + debts: BNCoin.fromDenomAndBigNumber(ORACLE_DENOM, debts), + netWorth: BNCoin.fromDenomAndBigNumber(ORACLE_DENOM, positionValue.minus(debts)), + apr, + leverage, + } +} diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 8fe9fe8e..f4e8a264 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -14,3 +14,11 @@ export const LTV_BUFFER = 0.99 export const DEPOSIT_CAP_BUFFER = 0.999 export const VAULT_DEPOSIT_BUFFER = 0.999 + +export const DEFAULT_PORTFOLIO_STATS = [ + { title: null, sub: 'Total Balance' }, + { title: null, sub: 'Total Debt' }, + { title: null, sub: 'Net Worth' }, + { title: null, sub: 'APR' }, + { title: null, sub: 'Account Leverage' }, +]