From 55d3be69e4b6ee81a73d3f93a64e80d10e42e74e Mon Sep 17 00:00:00 2001 From: katty barroso Date: Fri, 10 Jan 2025 12:04:34 +0100 Subject: [PATCH] Investment position table changes --- .../src/components/Portfolio/Holdings.tsx | 64 +++++++++- .../src/components/Portfolio/usePortfolio.ts | 110 ++++++------------ centrifuge-app/src/pages/Prime/Detail.tsx | 3 +- centrifuge-app/src/pages/Prime/index.tsx | 2 +- 4 files changed, 98 insertions(+), 81 deletions(-) diff --git a/centrifuge-app/src/components/Portfolio/Holdings.tsx b/centrifuge-app/src/components/Portfolio/Holdings.tsx index b8c054c1d5..174acf2627 100644 --- a/centrifuge-app/src/components/Portfolio/Holdings.tsx +++ b/centrifuge-app/src/components/Portfolio/Holdings.tsx @@ -1,10 +1,11 @@ -import { Token, evmToSubstrateAddress } from '@centrifuge/centrifuge-js' -import { formatBalance, useBalances, useCentrifuge, useWallet } from '@centrifuge/centrifuge-react' +import { CurrencyBalance, Token, evmToSubstrateAddress } from '@centrifuge/centrifuge-js' +import { NetworkIcon, formatBalance, useBalances, useCentrifuge, useWallet } from '@centrifuge/centrifuge-react' import { Box, Grid, IconDownload, IconMinus, IconPlus, IconSend, Shelf, Text, Thumbnail } from '@centrifuge/fabric' import Decimal from 'decimal.js-light' import { useMatch, useNavigate } from 'react-router' import { useLocation } from 'react-router-dom' import { useTheme } from 'styled-components' +import { evmChains } from '../../../src/config' import daiLogo from '../../assets/images/dai-logo.svg' import ethLogo from '../../assets/images/ethereum.svg' import centLogo from '../../assets/images/logoCentrifuge.svg' @@ -22,7 +23,6 @@ import { Column, DataTable, SortableTableHeader } from '../DataTable' import { Eththumbnail } from '../EthThumbnail' import { InvestRedeemDrawer } from '../InvestRedeem/InvestRedeemDrawer' import { RouterLinkButton } from '../RouterLinkButton' -import { Tooltips } from '../Tooltips' import { TransferTokensDrawer } from './TransferTokensDrawer' import { usePortfolioTokens } from './usePortfolio' @@ -35,7 +35,9 @@ export type Holding = { tokenPrice: Decimal showActions?: boolean address?: string - connectedNetwork?: string | null + connectedNetwork?: any + realizedProfit?: CurrencyBalance + unrealizedProfit?: CurrencyBalance } const columns: Column[] = [ @@ -45,9 +47,23 @@ const columns: Column[] = [ cell: (token: Holding) => { return }, + width: '300px', }, { - header: , + align: 'left', + header: 'Network', + cell: ({ connectedNetwork }: Holding) => { + if (!connectedNetwork) return + return ( + + + {(evmChains as any)[connectedNetwork]?.name || 'Centrifuge'} + + ) + }, + }, + { + header: , cell: ({ tokenPrice }: Holding) => { return ( @@ -81,6 +97,30 @@ const columns: Column[] = [ sortKey: 'marketValue', align: 'left', }, + { + header: , + cell: ({ realizedProfit }: Holding) => { + return ( + + {formatBalance(realizedProfit || 0, 'USD', 2)} + + ) + }, + sortKey: 'realizedProfit', + align: 'left', + }, + { + header: , + cell: ({ unrealizedProfit }: Holding) => { + return ( + + {formatBalance(unrealizedProfit || 0, 'USD', 2)} + + ) + }, + sortKey: 'unrealizedProfit', + align: 'left', + }, { align: 'right', header: '', // invest redeem buttons @@ -139,6 +179,7 @@ export function useHoldings(address?: string, chainId?: number, showActions = tr ...token, tokenPrice: token.tokenPrice.toDecimal() || Dec(0), showActions, + connectedNetwork: wallet.connectedNetwork, })), ...(tinlakeBalances?.tranches.filter((tranche) => !tranche.balancePending.isZero()) || []).map((balance) => { const pool = tinlakePools.data?.pools?.find((pool) => pool.id === balance.poolId) @@ -223,6 +264,7 @@ export function Holdings({ address?: string chainId?: number }) { + const theme = useTheme() const { search, pathname } = useLocation() const navigate = useNavigate() const params = new URLSearchParams(search) @@ -251,7 +293,17 @@ export function Holdings({ isOpen={!!(openSendDrawer || openReceiveDrawer)} onClose={() => navigate(pathname, { replace: true })} /> - + ) : ( diff --git a/centrifuge-app/src/components/Portfolio/usePortfolio.ts b/centrifuge-app/src/components/Portfolio/usePortfolio.ts index 95fb6cc102..30e1ebc913 100644 --- a/centrifuge-app/src/components/Portfolio/usePortfolio.ts +++ b/centrifuge-app/src/components/Portfolio/usePortfolio.ts @@ -126,11 +126,6 @@ const getPriceAtDate = ( } export function usePortfolio(substrateAddress?: string) { - // const [result] = useCentrifugeQuery(['accountPortfolio', substrateAddress], (cent) => cent.pools.getPortfolio([substrateAddress!]), { - // enabled: !!substrateAddress, - // }) - // return result - const pools = usePools() const { data: subData } = useSubquery( `query ($account: String!) { @@ -174,6 +169,12 @@ export function usePortfolio(substrateAddress?: string) { purchasePrice timestamp trancheId + tranche { + pool { + sumUnrealizedProfitAtMarketPrice + sumRealizedProfitFifoByPeriod + } + } } } } @@ -187,7 +188,15 @@ export function usePortfolio(substrateAddress?: string) { ) const data = useMemo(() => { - const trancheBalances: Record = {} + const trancheBalances: Record< + string, + { + totalTrancheTokens: TokenBalance + tokenPrice: Price + unrealizedProfit: CurrencyBalance + realizedProfit: CurrencyBalance + } + > = {} subData?.account?.investorPositions.nodes.forEach((position: any) => { const pool = pools?.find((p) => p.id === position.poolId) @@ -199,72 +208,14 @@ export function usePortfolio(substrateAddress?: string) { if (existing) { existing.totalTrancheTokens.iadd(balance) } else { - trancheBalances[trancheId] = { totalTrancheTokens: balance, tokenPrice } + trancheBalances[trancheId] = { + totalTrancheTokens: balance, + tokenPrice, + realizedProfit: new CurrencyBalance(position.tranche.pool.sumRealizedProfitFifoByPeriod, decimals), + unrealizedProfit: new CurrencyBalance(position.tranche.pool.sumUnrealizedProfitAtMarketPrice, decimals), + } } }) - // return ( - // (subData?.account as undefined | {}) && - // (Object.fromEntries( - // subData.account.trancheBalances.nodes.map((tranche: any) => { - // const decimals = tranche.pool.currency.decimals - // const tokenPrice = new Price(tranche.tranche.tokenPrice) - // let freeTrancheTokens = new CurrencyBalance(0, decimals) - - // const claimableCurrency = new CurrencyBalance(tranche.claimableCurrency, decimals) - // const claimableTrancheTokens = new TokenBalance(tranche.claimableTrancheTokens, decimals) - // const pendingInvestCurrency = new CurrencyBalance(tranche.pendingInvestCurrency, decimals) - // const pendingRedeemTrancheTokens = new TokenBalance(tranche.pendingRedeemTrancheTokens, decimals) - // const sumClaimedCurrency = new CurrencyBalance(tranche.sumClaimedCurrency, decimals) - // const sumClaimedTrancheTokens = new TokenBalance(tranche.sumClaimedTrancheTokens, decimals) - - // const currencyAmounts = subData.account.currencyBalances.nodes.filter( - // (b: any) => b.currency.trancheId && b.currency.trancheId === tranche.trancheId - // ) - // if (currencyAmounts.length) { - // freeTrancheTokens = new CurrencyBalance( - // currencyAmounts.reduce((acc: BN, cur: any) => acc.add(new BN(cur.amount)), new BN(0)), - // decimals - // ) - // } - - // const totalTrancheTokens = new CurrencyBalance( - // new BN(tranche.claimableTrancheTokens) - // .add(new BN(tranche.pendingRedeemTrancheTokens)) - // .add(freeTrancheTokens), - // decimals - // ) - - // return [ - // tranche.trancheId.split('-')[1], - // { - // claimableCurrency, - // claimableTrancheTokens, - // pendingInvestCurrency, - // pendingRedeemTrancheTokens, - // sumClaimedCurrency, - // sumClaimedTrancheTokens, - // totalTrancheTokens, - // freeTrancheTokens, - // tokenPrice, - // }, - // ] - // }) - // ) satisfies Record< - // string, - // { - // claimableCurrency: CurrencyBalance - // claimableTrancheTokens: TokenBalance - // pendingInvestCurrency: CurrencyBalance - // pendingRedeemTrancheTokens: TokenBalance - // sumClaimedCurrency: CurrencyBalance - // sumClaimedTrancheTokens: TokenBalance - // totalTrancheTokens: TokenBalance - // freeTrancheTokens: TokenBalance - // tokenPrice: Price - // // TODO: add reservedTrancheTokens - // } - // >) - // ) return trancheBalances }, [subData, pools]) @@ -278,14 +229,14 @@ type PortfolioToken = { trancheId: string poolId: string currency: Token['currency'] + realizedProfit: CurrencyBalance + unrealizedProfit: CurrencyBalance } export function usePortfolioTokens(address?: string) { const pools = usePools() const portfolioData = usePortfolio(address) - console.log(pools) - const trancheTokenPrices = pools?.reduce( (tranches, pool) => pool.tranches.reduce((tranches, tranche) => { @@ -293,10 +244,21 @@ export function usePortfolioTokens(address?: string) { currency: tranche.currency, tokenPrice: tranche.tokenPrice, poolId: tranche.poolId, + realizedProfit: portfolioData[tranche.id]?.realizedProfit, + unrealizedProfit: portfolioData[tranche.id]?.unrealizedProfit, } return tranches }, tranches), - {} as Record + {} as Record< + string, + { + tokenPrice: Price | null + poolId: string + currency: CurrencyMetadata + realizedProfit: CurrencyBalance + unrealizedProfit: CurrencyBalance + } + > ) if (portfolioData && trancheTokenPrices) { @@ -312,6 +274,8 @@ export function usePortfolioTokens(address?: string) { trancheId: trancheId, poolId: trancheTokenPrices[trancheId].poolId, currency: trancheTokenPrices[trancheId].currency, + realizedProfit: trancheTokenPrices[trancheId].realizedProfit, + unrealizedProfit: trancheTokenPrices[trancheId].unrealizedProfit, } }, [] as PortfolioToken[]) } diff --git a/centrifuge-app/src/pages/Prime/Detail.tsx b/centrifuge-app/src/pages/Prime/Detail.tsx index f18a413147..8c419d17c4 100644 --- a/centrifuge-app/src/pages/Prime/Detail.tsx +++ b/centrifuge-app/src/pages/Prime/Detail.tsx @@ -68,7 +68,8 @@ const PrimeDetail = () => { - + + Investment positions {/* diff --git a/centrifuge-app/src/pages/Prime/index.tsx b/centrifuge-app/src/pages/Prime/index.tsx index f55b7f0f02..fb1a9149ac 100644 --- a/centrifuge-app/src/pages/Prime/index.tsx +++ b/centrifuge-app/src/pages/Prime/index.tsx @@ -22,7 +22,7 @@ function Prime() { return ( <> - +