diff --git a/centrifuge-app/src/components/Charts/TotalValueLocked.tsx b/centrifuge-app/src/components/Charts/TotalValueLocked.tsx index 95956963ff..9c8da88cc3 100644 --- a/centrifuge-app/src/components/Charts/TotalValueLocked.tsx +++ b/centrifuge-app/src/components/Charts/TotalValueLocked.tsx @@ -1,8 +1,6 @@ import Decimal from 'decimal.js-light' import * as React from 'react' -import { useQuery } from 'react-query' import { Area, AreaChart, ResponsiveContainer, Tooltip } from 'recharts' -import { getTinlakeSubgraphTVL } from '../../utils/tinlake/getTinlakeSubgraphTVL' import { useDailyTVL } from '../../utils/usePools' export type DataPoint = { @@ -17,11 +15,10 @@ type TotalValueLockedProps = { export default function TotalValueLocked({ chainTVL, setHovered }: TotalValueLockedProps) { const centrifugeTVL = useDailyTVL() - const tinlakeTVL = useDailyTinlakeTVL() const chartColor = '#ff8c00' const chartData = React.useMemo(() => { - if (!tinlakeTVL || !centrifugeTVL) { + if (!centrifugeTVL) { return [] } @@ -32,8 +29,10 @@ export default function TotalValueLocked({ chainTVL, setHovered }: TotalValueLoc } : undefined - return getMergedData([...tinlakeTVL, ...centrifugeTVL], currentTVL) - }, [tinlakeTVL, centrifugeTVL, chainTVL]) + const tvlSnapshots = centrifugeTVL.map((entry) => ({ ...entry, tvl: entry.tvl.toNumber() })) + + return [...tvlSnapshots, currentTVL] + }, [centrifugeTVL, chainTVL]) return ( @@ -69,36 +68,3 @@ export default function TotalValueLocked({ chainTVL, setHovered }: TotalValueLoc ) } - -function useDailyTinlakeTVL() { - const { data } = useQuery('use daily tinlake tvl', getTinlakeSubgraphTVL, { - staleTime: Infinity, - suspense: true, - }) - - return data -} - -function getMergedData(combined: DataPoint[], current?: DataPoint) { - const mergedMap = new Map() - - combined.forEach((entry) => { - const { dateInMilliseconds, tvl } = entry - - if (mergedMap.has(dateInMilliseconds)) { - mergedMap.set(dateInMilliseconds, mergedMap.get(dateInMilliseconds).add(tvl)) - } else { - mergedMap.set(dateInMilliseconds, tvl) - } - }) - - if (current) { - mergedMap.set(current.dateInMilliseconds, current.tvl) - } - - const merged = Array.from(mergedMap, ([dateInMilliseconds, tvl]) => ({ dateInMilliseconds, tvl })) - .sort((a, b) => a.dateInMilliseconds - b.dateInMilliseconds) - .map((entry) => ({ ...entry, tvl: entry.tvl.toNumber() })) - - return merged -} diff --git a/centrifuge-app/src/utils/tinlake/getTinlakeSubgraphTVL.ts b/centrifuge-app/src/utils/tinlake/getTinlakeSubgraphTVL.ts deleted file mode 100644 index 5846c797a3..0000000000 --- a/centrifuge-app/src/utils/tinlake/getTinlakeSubgraphTVL.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { CurrencyBalance } from '@centrifuge/centrifuge-js' -import BN from 'bn.js' -import { fetchFromTinlakeSubgraph } from './fetchFromTinlakeSubgraph' - -export async function getTinlakeSubgraphTVL() { - const query = ` - query ($first: Int!, $skip: Int!) { - days(orderBy: id, orderDirection: asc, first: $first, skip: $skip) { - id - assetValue - reserve - } - } - ` - let skip = 0 - const limit = 1000 - - const data: { - id: string - assetValue: string - reserve: string - }[] = [] - - // subgraph only returns 1000 entries, fetch until no more entries are returned - while (true) { - const response: any = await fetchFromTinlakeSubgraph(query, { first: 1000, skip: skip }) - data.push(...response.days) - if (response.days.length < limit) { - break - } - skip += limit - } - - const poolsDailyData = data.map(({ id, assetValue, reserve }) => ({ - dateInMilliseconds: new Date(Number(id) * 1000).setHours(0, 0, 0, 0), - tvl: new CurrencyBalance(new BN(assetValue || '0').add(new BN(reserve || '0')), 18).toDecimal(), - })) - - return poolsDailyData -} diff --git a/centrifuge-js/src/modules/pools.ts b/centrifuge-js/src/modules/pools.ts index 76b9855073..78777fade8 100644 --- a/centrifuge-js/src/modules/pools.ts +++ b/centrifuge-js/src/modules/pools.ts @@ -2090,13 +2090,17 @@ export function getPoolsModule(inst: Centrifuge) { ) } - function getPoolSnapshotsWithCursor(poolId: string, endCursor: string | null, from?: Date, to?: Date) { + function getPoolSnapshotsWithCursor( + poolId: string, + endCursor: string | null, + options?: { from?: Date; to?: Date; orderBy?: 'BLOCK_NUMBER_ASC' | 'PERIOD_START_ASC' } + ) { return inst.getSubqueryObservable<{ poolSnapshots: { nodes: SubqueryPoolSnapshot[]; pageInfo: { hasNextPage: boolean; endCursor: string } } }>( - `query($poolId: String!, $from: Datetime!, $to: Datetime!, $poolCursor: Cursor) { + `query($poolId: String!, $from: Datetime!, $to: Datetime!, $poolCursor: Cursor, $orderBy: [PoolSnapshotsOrderBy!]) { poolSnapshots( - orderBy: BLOCK_NUMBER_ASC, + orderBy: $orderBy, filter: { id: { startsWith: $poolId }, timestamp: { greaterThan: $from, lessThan: $to } @@ -2114,6 +2118,12 @@ export function getPoolsModule(inst: Centrifuge) { sumInvestedAmountByPeriod sumRedeemedAmountByPeriod sumInterestRepaidAmountByPeriod + periodStart + pool { + currency { + decimals + } + } } pageInfo { hasNextPage @@ -2124,9 +2134,10 @@ export function getPoolsModule(inst: Centrifuge) { `, { poolId, - from: from ? from.toISOString() : getDateYearsFromNow(-10).toISOString(), - to: to ? to.toISOString() : getDateYearsFromNow(10).toISOString(), + from: options?.from ? options.from.toISOString() : getDateYearsFromNow(-10).toISOString(), + to: options?.to ? options.to.toISOString() : getDateYearsFromNow(10).toISOString(), poolCursor: endCursor, + orderBy: options?.orderBy || null, } ) } @@ -2178,7 +2189,7 @@ export function getPoolsModule(inst: Centrifuge) { of({ poolSnapshots: [], endCursor: null, hasNextPage: true }).pipe( expand(({ poolSnapshots, endCursor, hasNextPage }) => { if (!hasNextPage) return EMPTY - return getPoolSnapshotsWithCursor(poolId, endCursor, from, to).pipe( + return getPoolSnapshotsWithCursor(poolId, endCursor, { from, to, orderBy: 'BLOCK_NUMBER_ASC' }).pipe( map( ( response: { @@ -2294,64 +2305,61 @@ export function getPoolsModule(inst: Centrifuge) { } function getDailyTVL() { - const $query = inst.getSubqueryObservable<{ - poolSnapshots: { - nodes: { - portfolioValuation: string - totalReserve: string - periodStart: string - pool: { - currency: { - decimals: number - } - } - }[] - } - }>( - `query { - poolSnapshots(first: 1000, orderBy: PERIOD_START_ASC) { - nodes { - portfolioValuation - totalReserve - periodStart - pool { - currency { - decimals + return of({ poolSnapshots: [], endCursor: null, hasNextPage: true }) + .pipe( + expand(({ poolSnapshots, endCursor, hasNextPage }) => { + if (!hasNextPage) return EMPTY + return getPoolSnapshotsWithCursor('', endCursor, { orderBy: 'PERIOD_START_ASC' }).pipe( + map( + ( + response: { + poolSnapshots: { + nodes: SubqueryPoolSnapshot[] + pageInfo: { hasNextPage: boolean; endCursor: string } + } + } | null + ) => { + if (response?.poolSnapshots) { + const { endCursor, hasNextPage } = response.poolSnapshots.pageInfo + + return { + endCursor, + hasNextPage, + poolSnapshots: [...poolSnapshots, ...response.poolSnapshots.nodes], + } + } + return {} } - } + ) + ) + }) + ) + .pipe( + map(({ poolSnapshots }) => { + if (!poolSnapshots) { + return [] } - } - }` - ) - return $query.pipe( - map((data) => { - if (!data) { - return [] - } - - const mergedMap = new Map() - const formatted = data.poolSnapshots.nodes.map(({ portfolioValuation, totalReserve, periodStart, pool }) => ({ - dateInMilliseconds: new Date(periodStart).getTime(), - tvl: new CurrencyBalance( - new BN(portfolioValuation || '0').add(new BN(totalReserve || '0')), - pool.currency.decimals - ).toDecimal(), - })) - - formatted.forEach((entry) => { - const { dateInMilliseconds, tvl } = entry + const mergedMap = new Map() + const formatted = poolSnapshots.map(({ portfolioValuation, totalReserve, periodStart, pool }) => ({ + dateInMilliseconds: new Date(periodStart).getTime(), + tvl: new CurrencyBalance( + new BN(portfolioValuation || '0').add(new BN(totalReserve || '0')), + pool.currency.decimals + ).toDecimal(), + })) + formatted.forEach((entry) => { + const { dateInMilliseconds, tvl } = entry - if (mergedMap.has(dateInMilliseconds)) { - mergedMap.set(dateInMilliseconds, mergedMap.get(dateInMilliseconds).add(tvl)) - } else { - mergedMap.set(dateInMilliseconds, tvl) - } + if (mergedMap.has(dateInMilliseconds)) { + mergedMap.set(dateInMilliseconds, mergedMap.get(dateInMilliseconds).add(tvl)) + } else { + mergedMap.set(dateInMilliseconds, tvl) + } + }) + return Array.from(mergedMap, ([dateInMilliseconds, tvl]) => ({ dateInMilliseconds, tvl })) }) - - return Array.from(mergedMap, ([dateInMilliseconds, tvl]) => ({ dateInMilliseconds, tvl })) - }) - ) + ) } function getDailyTrancheStates(args: [trancheId: string]) { diff --git a/centrifuge-js/src/types/subquery.ts b/centrifuge-js/src/types/subquery.ts index 12e8563371..29dec91a57 100644 --- a/centrifuge-js/src/types/subquery.ts +++ b/centrifuge-js/src/types/subquery.ts @@ -20,6 +20,12 @@ export type SubqueryPoolSnapshot = { sumInvestedAmountByPeriod?: number | null sumRedeemedAmountByPeriod?: number | null blockNumber: number + periodStart: string + pool: { + currency: { + decimals: number + } + } } export type SubqueryTrancheSnapshot = {