diff --git a/centrifuge-app/src/components/PoolCard/index.tsx b/centrifuge-app/src/components/PoolCard/index.tsx index 58696ae6c..998556856 100644 --- a/centrifuge-app/src/components/PoolCard/index.tsx +++ b/centrifuge-app/src/components/PoolCard/index.tsx @@ -1,18 +1,13 @@ -import { CurrencyBalance, Rate } from '@centrifuge/centrifuge-js' +import { CurrencyBalance, Rate, Token } from '@centrifuge/centrifuge-js' import { Box, Card, Divider, Stack, Text, Thumbnail } from '@centrifuge/fabric' import Decimal from 'decimal.js-light' import styled from 'styled-components' +import { daysBetween } from '../../utils/date' import { formatBalance, formatBalanceAbbreviated, formatPercentage } from '../../utils/formatting' import { CardHeader } from '../ListItemCardStyles' import { RouterTextLink } from '../TextLink' import { PoolStatus, PoolStatusKey } from './PoolStatus' -type TrancheData = { - name: string - apr: string - minInvestment: string -} - export type InnerMetadata = { minInitialInvestment?: CurrencyBalance } @@ -29,19 +24,6 @@ export type MetaData = { } } -export type Tranche = { - id: string - currency: { - name: string - decimals: number - } - interestRatePerSec: { - toAprPercent: () => Decimal - } | null - capacity?: CurrencyBalance | number - metadata?: MetaData -} - const StyledRouterTextLink = styled(RouterTextLink)` font-size: 12px; margin-top: 8px; @@ -77,8 +59,9 @@ export type PoolCardProps = { apr?: Rate | null | undefined status?: PoolStatusKey iconUri?: string - tranches?: Tranche[] + tranches?: Pick[] metaData?: MetaData + createdAt?: string } export function PoolCard({ @@ -91,6 +74,7 @@ export function PoolCard({ iconUri, tranches, metaData, + createdAt, }: PoolCardProps) { const isOneTranche = tranches && tranches?.length === 1 const renderText = (text: string) => ( @@ -99,7 +83,7 @@ export function PoolCard({ ) - const tranchesData: TrancheData[] = tranches?.map((tranche: Tranche) => { + const tranchesData = tranches?.map((tranche) => { const words = tranche.currency.name.trim().split(' ') const metadata = metaData?.tranches[tranche.id] ?? null const trancheName = words[words.length - 1] @@ -108,18 +92,24 @@ export function PoolCard({ tranche.currency.decimals ).toDecimal() + const daysSinceCreation = createdAt ? daysBetween(createdAt, new Date()) : 0 + + function calculateApy() { + if (poolId === '4139607887') return formatPercentage(5, true, {}, 1) + if (poolId === '1655476167') return formatPercentage(15, true, {}, 1) + if (daysSinceCreation > 30 && tranche.yield30DaysAnnualized) + return formatPercentage(tranche.yield30DaysAnnualized, true, {}, 1) + if (tranche.interestRatePerSec) return formatPercentage(tranche.interestRatePerSec.toAprPercent(), true, {}, 1) + return '-' + } + return { name: trancheName, - apr: tranche.interestRatePerSec - ? formatPercentage(tranche.interestRatePerSec.toAprPercent(), true, { - minimumFractionDigits: 1, - maximumFractionDigits: 1, - }) - : '-', + apr: calculateApy(), minInvestment: metadata && metadata.minInitialInvestment ? formatBalanceAbbreviated(investmentBalance, '', 0) : '-', } - }) as TrancheData[] + }) return ( diff --git a/centrifuge-app/src/components/PoolList.tsx b/centrifuge-app/src/components/PoolList.tsx index 25c4db63a..1b17fcc62 100644 --- a/centrifuge-app/src/components/PoolList.tsx +++ b/centrifuge-app/src/components/PoolList.tsx @@ -9,7 +9,7 @@ import { TinlakePool } from '../utils/tinlake/useTinlakePools' import { useIsAboveBreakpoint } from '../utils/useIsAboveBreakpoint' import { useListedPools } from '../utils/useListedPools' import { useMetadataMulti } from '../utils/useMetadata' -import { MetaData, PoolCard, PoolCardProps, Tranche } from './PoolCard' +import { MetaData, PoolCard, PoolCardProps } from './PoolCard' import { PoolStatusKey } from './PoolCard/PoolStatus' import { filterPools } from './PoolFilter/utils' @@ -154,7 +154,7 @@ export function poolsToPoolCardProps( ? 'Open for investments' : ('Closed' as PoolStatusKey), iconUri: metaData?.pool?.icon?.uri ? cent.metadata.parseMetadataUrl(metaData?.pool?.icon?.uri) : undefined, - tranches: pool.tranches as Tranche[], + tranches: pool.tranches, metaData: metaData as MetaData, } }) diff --git a/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx b/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx index 3056e66e0..9867c68f4 100644 --- a/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx +++ b/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx @@ -1,4 +1,3 @@ -import { Perquintill } from '@centrifuge/centrifuge-js' import { Box, Shelf, Stack, Text } from '@centrifuge/fabric' import { InvestButton, Token } from '../../pages/Pool/Overview' import { daysBetween } from '../../utils/date' @@ -74,7 +73,7 @@ const TrancheTokenCard = ({ if (poolId === '1655476167') return formatPercentage(15) if (isTinlakePool && trancheText === 'senior') return formatPercentage(trancheToken.apy) if (daysSinceCreation < 30 || !trancheToken.yield30DaysAnnualized) return 'N/A' - return formatPercentage(new Perquintill(trancheToken.yield30DaysAnnualized)) + return formatPercentage(trancheToken.yield30DaysAnnualized) } return ( diff --git a/centrifuge-app/src/utils/tinlake/useTinlakePools.ts b/centrifuge-app/src/utils/tinlake/useTinlakePools.ts index 13071a205..c8961c07e 100644 --- a/centrifuge-app/src/utils/tinlake/useTinlakePools.ts +++ b/centrifuge-app/src/utils/tinlake/useTinlakePools.ts @@ -198,8 +198,7 @@ export function useTinlakeLoans(poolId: string) { export type TinlakePool = Omit & { metadata: PoolMetadata tinlakeMetadata: PoolMetadataDetails - tranches: (Omit & { - yield30DaysAnnualized?: string | null + tranches: (Omit & { poolMetadata: PoolMetadata pendingInvestments: CurrencyBalance pendingRedemptions: TokenBalance diff --git a/centrifuge-js/src/modules/pools.ts b/centrifuge-js/src/modules/pools.ts index d75242634..50f26af4a 100644 --- a/centrifuge-js/src/modules/pools.ts +++ b/centrifuge-js/src/modules/pools.ts @@ -317,7 +317,7 @@ export type Tranche = { minRiskBuffer: Perquintill | null currentRiskBuffer: Perquintill interestRatePerSec: Rate | null - yield30DaysAnnualized?: string | null + yield30DaysAnnualized: Perquintill | null lastUpdatedInterest: string ratio: Perquintill } @@ -2054,13 +2054,6 @@ export function getPoolsModule(inst: Centrifuge) { }) .flat() - const $yield30DaysAnnualized = combineLatest( - keys.map((key) => { - const poolIdTrancheId = `${key[0]}-${key[1].toLowerCase()}` - return getLatestTrancheSnapshot(poolIdTrancheId).pipe(map((snapshot) => snapshot?.trancheSnapshots.nodes)) - }) - ) as Observable<{ yield30DaysAnnualized: string | null; trancheId: string }[][]> - const trancheIdToIndex: Record = {} keys.forEach(([, tid], i) => { trancheIdToIndex[tid] = i @@ -2080,11 +2073,11 @@ export function getPoolsModule(inst: Centrifuge) { const $block = inst.getBlocks().pipe(take(1)) - return combineLatest([$issuance, $block, $prices, $navs, $yield30DaysAnnualized]).pipe( - map(([rawIssuances, { block }, rawPrices, rawNavs, [rawYield30DaysAnnualized]]) => { + return combineLatest([$issuance, $block, $prices, $navs, getLatestTrancheSnapshots()]).pipe( + map(([rawIssuances, { block }, rawPrices, rawNavs, rawYield30DaysAnnualized]) => { const blockNumber = block.header.number.toNumber() - const yield30DaysAnnualizedByPoolIdTrancheId = rawYield30DaysAnnualized?.reduce( + const yield30DaysTrancheId = rawYield30DaysAnnualized?.trancheSnapshots.nodes.reduce( (acc, { yield30DaysAnnualized, trancheId }) => { acc[trancheId] = yield30DaysAnnualized return acc @@ -2168,7 +2161,9 @@ export function getPoolsModule(inst: Centrifuge) { poolId, poolMetadata: (metadata ?? undefined) as string | undefined, interestRatePerSec, - yield30DaysAnnualized: yield30DaysAnnualizedByPoolIdTrancheId?.[`${poolId}-${trancheId}`], + yield30DaysAnnualized: yield30DaysTrancheId?.[`${poolId}-${trancheId}`] + ? new Perquintill(yield30DaysTrancheId[`${poolId}-${trancheId}`]!) + : null, minRiskBuffer, currentRiskBuffer, capacity: CurrencyBalance.fromFloat(capacity, currency.decimals), @@ -2301,21 +2296,18 @@ export function getPoolsModule(inst: Centrifuge) { ) } - function getLatestTrancheSnapshot(poolIdTrancheId: string) { + function getLatestTrancheSnapshots() { return inst.getSubqueryObservable<{ trancheSnapshots: { nodes: { yield30DaysAnnualized: string | null; trancheId: string }[] } }>( - `query ($poolIdTrancheId: String!) { - trancheSnapshots(filter: { trancheId: { equalTo: $poolIdTrancheId } }, last: 1) { + `{ + trancheSnapshots(distinct: TRANCHE_ID, orderBy: TIMESTAMP_DESC) { nodes { trancheId yield30DaysAnnualized } } - }`, - { - poolIdTrancheId, - } + }` ) } function getPoolSnapshotsWithCursor(poolId: string, endCursor: string | null, from?: Date, to?: Date) {