Skip to content

Commit

Permalink
Calculate YoY
Browse files Browse the repository at this point in the history
  • Loading branch information
kattylucy committed Aug 28, 2024
1 parent 8b5680e commit ddb4160
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 9 deletions.
23 changes: 15 additions & 8 deletions centrifuge-app/src/pages/Pools.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { formatBalance } from '@centrifuge/centrifuge-react'
import { Box, IconArrowUpRight, Stack, StatusChip, Text } from '@centrifuge/fabric'
import { Box, IconArrowDown, IconArrowUpRight, Stack, StatusChip, Text } from '@centrifuge/fabric'
import * as React from 'react'
import { useListedPools } from '../../src/utils/useListedPools'
import { getYearOverYearGrowth, useListedPools } from '../../src/utils/useListedPools'
import { LayoutSection } from '../components/LayoutBase/LayoutSection'
import { PoolList } from '../components/PoolList'
import { prefetchRoute } from '../components/Root'
Expand All @@ -10,6 +10,9 @@ import { Dec } from '../utils/Decimal'

export default function PoolsPage() {
const [, listedTokens] = useListedPools()
const { totalValueLockedGrowth, isLoading } = getYearOverYearGrowth()
const isPositiveYoy = totalValueLockedGrowth > 0
const IconComponent = isPositiveYoy ? IconArrowUpRight : IconArrowDown

const totalValueLocked = React.useMemo(() => {
return (
Expand Down Expand Up @@ -41,12 +44,16 @@ export default function PoolsPage() {
<Text color="textDisabled" variant="body2" style={{ marginRight: 8 }}>
Total value locked (TVL)
</Text>
<StatusChip status="ok">
<IconArrowUpRight size={16} color="ok" />
<Text variant="body3" color="ok">
24% YoY
</Text>
</StatusChip>
{!isLoading && (
<StatusChip status={isPositiveYoy ? 'ok' : 'critical'}>
<Box display="flex" alignItems="center" pt="2px">
<IconComponent size={16} color="ok" />
<Text variant="body3" color={isPositiveYoy ? 'ok' : 'warning'}>
{formatBalance(totalValueLockedGrowth ?? 0, '', 2)} YoY
</Text>
</Box>
</StatusChip>
)}
</Box>
<Text as="h1" variant="heading1" color="textBlack" style={{ fontSize: 36 }}>
{formatBalance(totalValueLocked ?? 0, config.baseCurrency)}
Expand Down
91 changes: 90 additions & 1 deletion centrifuge-app/src/utils/useListedPools.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import { PoolMetadata } from '@centrifuge/centrifuge-js'
import { CurrencyBalance, PoolMetadata } from '@centrifuge/centrifuge-js'
import BN from 'bn.js'
import * as React from 'react'
import { useMemo } from 'react'
import { useAddress } from '../utils/useAddress'
import { useMetadataMulti } from '../utils/useMetadata'
import { usePermissions } from '../utils/usePermissions'
import { usePools } from '../utils/usePools'
import { Dec } from './Decimal'
import { getPoolTVL } from './getPoolTVL'
import { useTinlakePools } from './tinlake/useTinlakePools'
import { useSubquery } from './useSubquery'

type FlattenedDataItem = {
netAssetValue: string
decimals: number
}

const sign = (n: BN) => (n.isZero() ? 0 : n.isNeg() ? -1 : 1)

Expand Down Expand Up @@ -40,3 +48,84 @@ export function useListedPools() {

return [listedPools, listedTokens, isLoading] as const
}

export function getYearOverYearGrowth() {
const [listedPools] = useListedPools()

Check failure on line 53 in centrifuge-app/src/utils/useListedPools.ts

View workflow job for this annotation

GitHub Actions / build-app

React Hook "useListedPools" is called in function "getYearOverYearGrowth" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use"

Check failure on line 53 in centrifuge-app/src/utils/useListedPools.ts

View workflow job for this annotation

GitHub Actions / ff-prod / build-app

React Hook "useListedPools" is called in function "getYearOverYearGrowth" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use"

const { oneDayAgoFromOneYearAgo, nextDay } = useMemo(() => {

Check failure on line 55 in centrifuge-app/src/utils/useListedPools.ts

View workflow job for this annotation

GitHub Actions / build-app

React Hook "useMemo" is called in function "getYearOverYearGrowth" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use"

Check failure on line 55 in centrifuge-app/src/utils/useListedPools.ts

View workflow job for this annotation

GitHub Actions / ff-prod / build-app

React Hook "useMemo" is called in function "getYearOverYearGrowth" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use"
const today = new Date()
const oneYearAgo = new Date(Date.UTC(today.getUTCFullYear() - 1, today.getUTCMonth(), today.getUTCDate(), 0, 0, 0))

const addOneDay = (date: Date): Date => {
const newDate = new Date(date)
newDate.setDate(date.getDate() + 1)
return newDate
}

return {
oneDayAgoFromOneYearAgo: oneYearAgo,
nextDay: addOneDay(oneYearAgo),
}
}, [])

const { data, isLoading } = useSubquery(

Check failure on line 71 in centrifuge-app/src/utils/useListedPools.ts

View workflow job for this annotation

GitHub Actions / build-app

React Hook "useSubquery" is called in function "getYearOverYearGrowth" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use"

Check failure on line 71 in centrifuge-app/src/utils/useListedPools.ts

View workflow job for this annotation

GitHub Actions / ff-prod / build-app

React Hook "useSubquery" is called in function "getYearOverYearGrowth" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use"
`query ($oneDayAgoFromOneYearAgo: Datetime!, $nextDay: Datetime!) {
pools {
nodes {
currency {
decimals
}
poolSnapshots(
filter: {
timestamp: {
greaterThan: $oneDayAgoFromOneYearAgo,
lessThan: $nextDay
}
},
) {
nodes {
netAssetValue
timestamp
}
}
}
}
}`,
{
oneDayAgoFromOneYearAgo,
nextDay,
},
{
enabled: !!oneDayAgoFromOneYearAgo,
}
)

const flattenedData =
data?.pools?.nodes.flatMap((pool: any) =>
pool.poolSnapshots.nodes.map((snapshot: any) => ({
netAssetValue: snapshot.netAssetValue,
decimals: pool.currency.decimals,
}))
) || []

// Aggregate NAV from last year
const aggregatedNetAssetValue = flattenedData.reduce((accumulator: any, item: FlattenedDataItem) => {
const netAssetValue = new CurrencyBalance(item.netAssetValue, item.decimals)
return accumulator.add(netAssetValue.toDecimal())
}, Dec(0))

const aggregatedListedPoolsNav = listedPools.reduce((accumulator, pool) => {
const decimal = pool.currency?.decimals ?? 0
const navTotal = new CurrencyBalance(pool.nav.total, decimal)
return accumulator.add(navTotal.toDecimal())
}, Dec(0))

const lastYearNAV = aggregatedNetAssetValue.toNumber()
const currentYearNAV = aggregatedListedPoolsNav.toNumber()

// YoY growth
const totalValueLockedGrowth =
lastYearNAV && currentYearNAV ? ((currentYearNAV - lastYearNAV) / lastYearNAV) * 100 : 0

return { totalValueLockedGrowth, isLoading }
}

0 comments on commit ddb4160

Please sign in to comment.