diff --git a/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx b/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx index bcf720fb4..d806c5c52 100644 --- a/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx +++ b/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx @@ -1,4 +1,5 @@ import { AnchorButton, Box, IconDownload, Select, Shelf, Stack, Tabs, TabsItem, Text } from '@centrifuge/fabric' +import Decimal from 'decimal.js-light' import * as React from 'react' import { useParams } from 'react-router' import { Bar, CartesianGrid, ComposedChart, Line, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts' @@ -8,7 +9,7 @@ import { daysBetween, formatDate } from '../../utils/date' import { formatBalance, formatBalanceAbbreviated } from '../../utils/formatting' import { useLoans } from '../../utils/useLoans' import { useDailyPoolStates, usePool } from '../../utils/usePools' -import { Tooltips } from '../Tooltips' +import { Tooltips, tooltipText } from '../Tooltips' import { TooltipContainer, TooltipTitle } from './Tooltip' import { getRangeNumber } from './utils' @@ -18,6 +19,7 @@ type ChartData = { juniorTokenPrice: number | null seniorTokenPrice?: number | null currency?: string + totalAPY: Decimal } type Tranche = { @@ -44,6 +46,21 @@ function calculateTranchePrices(pool: any) { return { juniorTokenPrice, seniorTokenPrice } } +function getYieldFieldForFilter(tranche: any, filter: string) { + switch (filter) { + case '30d': + return tranche.yield30DaysAnnualized || 0 + case '90d': + return tranche.yield90DaysAnnualized || 0 + case 'ytd': + return tranche.yieldYTD || 0 + case 'all': + return tranche.yieldSinceInception || 0 + default: + return 0 + } +} + function PoolPerformanceChart() { const theme = useTheme() const [selectedTabIndex, setSelectedTabIndex] = React.useState(0) @@ -94,11 +111,16 @@ function PoolPerformanceChart() { const juniorTrancheKey = trancheKeys[0] const seniorTrancheKey = trancheKeys[1] || null - const juniorTokenPrice = (day.tranches[juniorTrancheKey]?.price as any)?.toFloat() || null + const juniorTokenPrice = (day.tranches[juniorTrancheKey]?.price as any)?.toFloat() || 0 const seniorTokenPrice = seniorTrancheKey - ? (day.tranches[seniorTrancheKey]?.price as any)?.toFloat() || null + ? (day.tranches[seniorTrancheKey]?.price as any)?.toFloat() || 0 : null + const juniorAPY = getYieldFieldForFilter(day.tranches[juniorTrancheKey], range.value) + const seniorAPY = seniorTrancheKey ? getYieldFieldForFilter(day.tranches[seniorTrancheKey], range.value) : 0 + + console.log(juniorAPY, seniorAPY) + if (day.timestamp && new Date(day.timestamp).toDateString() === new Date().toDateString()) { const tranchePrices = calculateTranchePrices(pool) @@ -107,6 +129,8 @@ function PoolPerformanceChart() { nav: todayAssetValue, juniorTokenPrice: tranchePrices.juniorTokenPrice ?? null, seniorTokenPrice: tranchePrices.seniorTokenPrice ?? null, + juniorAPY, + seniorAPY, } } @@ -115,9 +139,11 @@ function PoolPerformanceChart() { nav: Number(nav), juniorTokenPrice, seniorTokenPrice, + juniorAPY, + seniorAPY, } }) || [], - [isSingleTranche, truncatedPoolStates, todayAssetValue, todayPrice, pool] + [isSingleTranche, truncatedPoolStates, todayAssetValue, todayPrice, pool, range] ) const today = { @@ -266,6 +292,7 @@ function PoolPerformanceChart() { if (name === 'nav') label = 'NAV' else if (name === 'juniorTokenPrice') label = 'Junior Token Price' else if (name === 'seniorTokenPrice') label = 'Senior Token Price' + else if (name === 'totalAPY') label = 'Total APY' else label = 'Cash' return ( @@ -274,7 +301,7 @@ function PoolPerformanceChart() { {label} - {typeof value === 'number' + {typeof value === 'number' && name !== 'totalAPY' ? formatBalance( value, name === 'nav' ? pool.currency.symbol ?? 'USD' : '', @@ -299,24 +326,38 @@ function PoolPerformanceChart() { fill={theme.colors.backgroundTertiary} yAxisId="left" /> - - {chartData.some((d) => d.seniorTokenPrice !== null) && ( + {selectedTabIndex === 0 ? ( + <> + + {chartData.some((d) => d.seniorTokenPrice !== null) && ( + + )} + + ) : ( )} @@ -332,6 +373,7 @@ function PoolPerformanceChart() { function CustomLegend({ data, setRange, + selectedTabIndex, }: { data: { currency: string @@ -340,19 +382,22 @@ function CustomLegend({ seniorTokenPrice?: number | null } setRange: (value: { value: string; label: string }) => void + selectedTabIndex: number }) { const Dot = ({ color }: { color: string }) => ( ) - const buildData = [ - { - color: 'backgroundTertiary', - label: `NAV ${data.currency}`, - value: formatBalance(data.nav), - type: 'nav', - show: true, - }, + const navObj = { + color: 'backgroundTertiary', + label: `NAV ${data.currency}`, + value: formatBalance(data.nav), + type: 'nav', + show: true, + } + + const tokenData = [ + navObj, { color: 'textGold', label: 'Junior token price', @@ -369,6 +414,19 @@ function CustomLegend({ }, ] + const apyData = [ + navObj, + { + color: 'textGold', + label: 'APY', + value: data.juniorTokenPrice ?? 0, + type: 'singleTrancheTokenPrice', + show: true, + }, + ] + + const graphData = selectedTabIndex === 0 ? tokenData : apyData + const toggleRange = (e: any) => { const value = e.target.value const range = rangeFilters.find((range) => range.value === value) @@ -378,18 +436,29 @@ function CustomLegend({ return ( - {buildData.map((item, index) => { - if (!item.show) return - return ( - - - - - - {item.value} - - ) - })} + {graphData.map( + ( + item: { + show: boolean + color: string + type: keyof typeof tooltipText + label: string + value: Number | Decimal + }, + index: number + ) => { + if (!item.show) return + return ( + + + + + + {item.value} + + ) + } + )}