diff --git a/liquidity/lib/Pools/PoolRow.tsx b/liquidity/lib/Pools/PoolRow.tsx index b97bf613b..f708577b0 100644 --- a/liquidity/lib/Pools/PoolRow.tsx +++ b/liquidity/lib/Pools/PoolRow.tsx @@ -1,9 +1,10 @@ import { Button, Fade, Flex, Link, Text } from '@chakra-ui/react'; import { ZEROWEI } from '@snx-v3/constants'; -import { formatApr, formatNumber, formatNumberToUsd } from '@snx-v3/formatters'; +import { formatNumber, formatNumberToUsd } from '@snx-v3/formatters'; import { Sparkles } from '@snx-v3/icons'; import { TokenIcon } from '@snx-v3/TokenIcon'; import { Tooltip } from '@snx-v3/Tooltip'; +import { useApr } from '@snx-v3/useApr'; import { useStataUSDCApr } from '@snx-v3/useApr/useStataUSDCApr'; import { Network, NetworkIcon, useNetwork, useWallet } from '@snx-v3/useBlockchain'; import { CollateralType } from '@snx-v3/useCollateralTypes'; @@ -24,7 +25,6 @@ interface CollateralTypeWithDeposited extends CollateralType { export function PoolRow({ pool: _pool, network, - apr, collateralType, collateralPrices, }: { @@ -38,11 +38,6 @@ export function PoolRow({ symbol: string; price: ethers.BigNumber; }[]; - apr: { - combinedApr: number; - cumulativePnl: number; - collateralAprs: any[]; - }; }) { const [params, setParams] = useParams(); @@ -90,11 +85,14 @@ export function PoolRow({ )?.price ?? 0 ); - const collateralApr = apr.collateralAprs.find( - (apr) => apr.collateralType === collateralType.tokenAddress.toLowerCase() - ) || { apr7d: 0, apr7dRewards: 0, apr7dPnl: 0 }; - - const { apr7d, apr7dRewards, apr7dPnl } = collateralApr; + const { data: apr, isPending: isPendingApr } = useApr(network); + const positionApr = React.useMemo(() => { + if (apr && collateralType) { + return apr.find( + (item) => item.collateralType.toLowerCase() === collateralType.tokenAddress.toLowerCase() + ); + } + }, [apr, collateralType]); const onClick = async (e: React.MouseEvent) => { e.preventDefault(); @@ -236,33 +234,49 @@ export function PoolRow({ fontWeight={500} color="white" > - {isAndromedaStataUSDC && stataUSDCApr - ? formatApr(apr7d * 100 + stataUSDCApr) - : formatApr(apr7d * 100)} - - - - Total APR: - - {formatApr(apr7d * 100)} - - - Performance: - {formatApr(apr7dPnl * 100)} - - - Rewards: - {formatApr(apr7dRewards * 100)} + {isPendingApr ? '~' : null} + {!isPendingApr && positionApr && positionApr.apr28d > 0 + ? ( + positionApr.apr28d * 100 + + (isAndromedaStataUSDC && stataUSDCApr ? stataUSDCApr : 0) + ) + .toFixed(2) + .concat('%') + : '-'} + {!isPendingApr && positionApr && positionApr.apr28d > 0 ? ( + + + + Total APR: + + + {(positionApr.apr28d * 100).toFixed(2).concat('%')} + + + + Performance: + {(positionApr.apr28dPnl * 100).toFixed(2).concat('%')} + + + Rewards: + {(positionApr.apr28dRewards * 100).toFixed(2).concat('%')} + + {isAndromedaStataUSDC && stataUSDCApr ? ( + + AAVE yield: + {stataUSDCApr.toFixed(2).concat('%')} + + ) : null} + } + > + + - } - > - - - - + + ) : null} diff --git a/liquidity/lib/Pools/PoolsList.tsx b/liquidity/lib/Pools/PoolsList.tsx index 4e273400a..e031253a2 100644 --- a/liquidity/lib/Pools/PoolsList.tsx +++ b/liquidity/lib/Pools/PoolsList.tsx @@ -64,11 +64,11 @@ export function PoolsList() { isStataPriceLoading; const filteredPools = React.useMemo(() => { - if (!poolsList?.synthetixPools) { + if (!poolsList) { return []; } - return poolsList.synthetixPools.map(({ network, poolInfo, apr }) => { + return poolsList.map(({ network, poolInfo }) => { const collateralDeposited = poolInfo.map(({ collateral_type }) => ({ collateralDeposited: collateral_type.total_amount_deposited, tokenAddress: collateral_type.id, @@ -93,12 +93,11 @@ export function PoolsList() { return { network, poolInfo, - apr, collateralDeposited, collateralTypes, }; }); - }, [poolsList?.synthetixPools, baseCollateralTypes, mainnetCollateralTypes]); + }, [poolsList, baseCollateralTypes, mainnetCollateralTypes]); const allCollateralPrices = React.useMemo(() => { if (stata && stataPrice) { @@ -122,13 +121,12 @@ export function PoolsList() { {!isPending && filteredPools && allCollateralPrices ? ( {filteredPools.flatMap( - ({ network, poolInfo, apr, collateralTypes }) => + ({ network, poolInfo, collateralTypes }) => collateralTypes?.map((collateralType) => ( diff --git a/liquidity/lib/Positions/PositionTableHeader.tsx b/liquidity/lib/Positions/PositionTableHeader.tsx index e48b940b2..49ff1ae0c 100644 --- a/liquidity/lib/Positions/PositionTableHeader.tsx +++ b/liquidity/lib/Positions/PositionTableHeader.tsx @@ -50,7 +50,7 @@ export function PositionTableHeader() { label={ - APR is averaged over the trailing 7 days and is comprised of both performance + APR is averaged over the trailing 28 days and is comprised of both performance and rewards diff --git a/liquidity/lib/Positions/PositionsList.tsx b/liquidity/lib/Positions/PositionsList.tsx index 1ac0f504b..2662028fb 100644 --- a/liquidity/lib/Positions/PositionsList.tsx +++ b/liquidity/lib/Positions/PositionsList.tsx @@ -1,6 +1,5 @@ import { Flex, Heading, Table, TableContainer, Tbody, Text, Tr } from '@chakra-ui/react'; import { POOL_ID } from '@snx-v3/constants'; -import { useApr } from '@snx-v3/useApr'; import { NetworkIcon, useNetwork, useWallet } from '@snx-v3/useBlockchain'; import { useLiquidityPositions } from '@snx-v3/useLiquidityPositions'; import { useParams } from '@snx-v3/useParams'; @@ -20,7 +19,6 @@ export const PositionsList = () => { const { data: liquidityPositions, isPending: isPendingLiquidityPositions } = useLiquidityPositions({ accountId: params.accountId }); - const { data: apr } = useApr(); const filteredLiquidityPositions = React.useMemo( () => @@ -99,12 +97,6 @@ export const PositionsList = () => { ) : ( <> {filteredLiquidityPositions?.map((liquidityPosition, i) => { - const positionApr = apr?.collateralAprs?.find( - (apr: { collateralType: string }) => - apr.collateralType.toLowerCase() === - liquidityPosition.collateralType.tokenAddress.toLowerCase() - ); - return ( { i === filteredLiquidityPositions.length - 1 ? 'none' : '1px' } > - + ); })} diff --git a/liquidity/lib/Positions/PositionsRow.tsx b/liquidity/lib/Positions/PositionsRow.tsx index e264620de..842b8c60c 100644 --- a/liquidity/lib/Positions/PositionsRow.tsx +++ b/liquidity/lib/Positions/PositionsRow.tsx @@ -22,14 +22,10 @@ import { type LiquidityPositionType } from '@snx-v3/useLiquidityPosition'; import { makeSearch, useParams } from '@snx-v3/useParams'; import { useWithdrawTimer } from '@snx-v3/useWithdrawTimer'; import lockIcon from './lock.svg'; +import React from 'react'; +import { useApr } from '@snx-v3/useApr'; -export function PositionRow({ - liquidityPosition, - apr, -}: { - liquidityPosition: LiquidityPositionType; - apr?: number; -}) { +export function PositionRow({ liquidityPosition }: { liquidityPosition: LiquidityPositionType }) { const [params, setParams] = useParams(); const { network } = useNetwork(); @@ -39,8 +35,7 @@ export function PositionRow({ }); const { minutes, hours, isRunning } = useWithdrawTimer(params.accountId); - const { data: stataUSDCAPR } = useStataUSDCApr(network?.id, network?.preset); - const stataUSDCAPRParsed = stataUSDCAPR || 0; + const { data: stataUSDCApr } = useStataUSDCApr(network?.id, network?.preset); const collateralAmount = liquidityPosition ? liquidityPosition.collateralAmount.add(liquidityPosition.totalLocked) @@ -52,6 +47,17 @@ export function PositionRow({ ) : undefined; + const { data: apr, isPending: isPendingApr } = useApr(network); + const positionApr = React.useMemo( + () => + apr?.find( + (item) => + item.collateralType.toLowerCase() === + liquidityPosition?.collateralType?.tokenAddress.toLowerCase() + ), + [apr, liquidityPosition?.collateralType?.tokenAddress] + ); + return ( <> @@ -190,8 +196,14 @@ export function PositionRow({ - {apr && apr > 0 - ? (isAndromedaStataUSDC ? apr + stataUSDCAPRParsed : apr).toFixed(2).concat('%') + {isPendingApr ? '~' : null} + {!isPendingApr && positionApr && positionApr.apr28d > 0 + ? ( + positionApr.apr28d * 100 + + (isAndromedaStataUSDC && stataUSDCApr ? stataUSDCApr : 0) + ) + .toFixed(2) + .concat('%') : '-'} diff --git a/liquidity/lib/calculations/calculations.test.ts b/liquidity/lib/calculations/calculations.test.ts deleted file mode 100644 index f29dd127b..000000000 --- a/liquidity/lib/calculations/calculations.test.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { wei } from '@synthetixio/wei'; -import { - calculateSevenDaysPnlGrowth, - calculatePoolPerformanceLifetime, - calculatePoolPerformanceSevenDays, -} from './calculations'; - -describe('calculateSevenDaysPnlGrowth', () => { - test('returns undefined when no previous snapshot missing or 0', () => { - expect(calculateSevenDaysPnlGrowth()).toBe(undefined); - expect(calculateSevenDaysPnlGrowth([])).toBe(undefined); - }); - test('return undefined for percentage when the pnl 7days ago is missing or 0', () => { - expect(calculateSevenDaysPnlGrowth([{ pnl: wei(100) }] as any)).toEqual({ - value: wei(100), - percentage: undefined, - }); - - expect(calculateSevenDaysPnlGrowth([{ pnl: wei(100) }, { pnl: wei(0) }] as any)).toEqual({ - value: wei(100), - percentage: undefined, - }); - }); - test('calculate positive growth', () => { - expect(calculateSevenDaysPnlGrowth([{ pnl: wei(100) }, { pnl: wei(50) }] as any)).toEqual({ - value: wei(50), - percentage: wei(1), - }); - }); - test('calculate negative growth', () => { - expect(calculateSevenDaysPnlGrowth([{ pnl: wei(50) }, { pnl: wei(100) }] as any)).toEqual({ - value: wei(-50), - percentage: wei(-0.5), - }); - }); - test('last week negative this week more negative', () => { - expect( - calculateSevenDaysPnlGrowth([{ pnl: wei(-5008.54) }, { pnl: wei(-569.21) }] as any) - ).toEqual({ - value: wei('-4439.330000000000000000'), - percentage: wei('-7.799107535004655575'), - }); - }); -}); - -describe('calculatePoolPerformanceLifetime', () => { - test('returns 0 when there is no configurations', () => { - expect(calculatePoolPerformanceLifetime({ configurations: [] } as any)).toEqual(wei(0)); - }); - test('returns lifetime performance', () => { - expect( - calculatePoolPerformanceLifetime({ - configurations: [{ market: { pnl: wei(60) } }, { market: { pnl: wei(40) } }], - } as any) - ).toEqual(wei(100)); - }); -}); -describe('calculatePoolPerformanceSevenDays', () => { - test('returns 0 when there is no configurations', () => { - expect(calculatePoolPerformanceSevenDays({ configurations: [] } as any)).toEqual({ - value: wei(0), - growthPercentage: undefined, - }); - }); - test('handles market_snapshots_by_week[1] (last week) missing ', () => { - expect( - calculatePoolPerformanceSevenDays({ - configurations: [ - { market: { pnl: wei(100), market_snapshots_by_week: [{ pnl: wei(100) }] } }, - ], - } as any) - ).toEqual({ - value: wei(100), - growthPercentage: undefined, - }); - }); - test('handles market_snapshots_by_week[1] (last week) having 0 pnl', () => { - expect( - calculatePoolPerformanceSevenDays({ - configurations: [ - { - market: { - pnl: wei(100), - market_snapshots_by_week: [{ pnl: wei(100) }, { pnl: wei(0) }], - }, - }, - ], - } as any) - ).toEqual({ - value: wei(100), - growthPercentage: undefined, - }); - }); - test('calculates 7days positive growth', () => { - expect( - calculatePoolPerformanceSevenDays({ - configurations: [ - { - market: { - pnl: wei(100), - market_snapshots_by_week: [{ pnl: wei(100) }, { pnl: wei(50) }], - }, - }, - ], - } as any) - ).toEqual({ - value: wei(50), - growthPercentage: wei(1), - }); - }); - test('calculates 7days negative growth', () => { - expect( - calculatePoolPerformanceSevenDays({ - configurations: [ - { - market: { - pnl: wei(50), - market_snapshots_by_week: [{ pnl: wei(50) }, { pnl: wei(100) }], - }, - }, - ], - } as any) - ).toEqual({ - value: wei(-50), - growthPercentage: wei(-0.5), - }); - }); - test('handles improving pnl that still is negative', () => { - expect( - calculatePoolPerformanceSevenDays({ - configurations: [ - { - market: { - pnl: wei(-50), - market_snapshots_by_week: [{ pnl: wei(-50) }, { pnl: wei(-100) }], - }, - }, - ], - } as any) - ).toEqual({ - value: wei(50), - growthPercentage: wei(0.5), - }); - }); - test('handles 0 growth', () => { - expect( - calculatePoolPerformanceSevenDays({ - configurations: [ - { - market: { - pnl: wei(100), - market_snapshots_by_week: [{ pnl: wei(100) }, { pnl: wei(100) }], - }, - }, - ], - } as any) - ).toEqual({ - value: wei(0), - growthPercentage: wei(0), - }); - }); -}); diff --git a/liquidity/lib/calculations/calculations.ts b/liquidity/lib/calculations/calculations.ts index 819a3a236..9c92c7353 100644 --- a/liquidity/lib/calculations/calculations.ts +++ b/liquidity/lib/calculations/calculations.ts @@ -1,45 +1,5 @@ -import type { MarketSnapshotByWeekSchema, PoolType } from '@snx-v3/usePoolData'; -import { z } from 'zod'; -import { wei, Wei } from '@synthetixio/wei'; import { ZEROWEI } from '@snx-v3/constants'; - -type MarketSnapshotByWeek = z.infer; - -export const calculateSevenDaysPnlGrowth = (marketSnapshots?: MarketSnapshotByWeek[]) => { - if (!marketSnapshots || marketSnapshots.length === 0) return undefined; - const end = marketSnapshots[0].pnl; - const start = marketSnapshots[1]?.pnl || wei(0); - - return { - value: end.sub(start), - percentage: start.eq(0) ? undefined : end.sub(start).div(start.abs()), - }; -}; - -export const calculatePoolPerformanceLifetime = (poolData?: PoolType) => { - return poolData?.configurations.reduce((acc, { market }) => { - return acc.add(market.pnl); - }, wei(0)); -}; - -export const calculatePoolPerformanceSevenDays = (poolData?: PoolType) => { - const total = calculatePoolPerformanceLifetime(poolData); - - const totalSevenDaysAgo = poolData?.configurations.reduce((acc, { market }) => { - return acc.add(market.market_snapshots_by_week[1]?.pnl || wei(0)); - }, wei(0)); - - if (!total || !totalSevenDaysAgo) { - return undefined; - } - - return { - value: total.sub(totalSevenDaysAgo), // Not that this value does not take into account that other pools might have exposure to markets - growthPercentage: totalSevenDaysAgo.eq(0) - ? undefined - : total.sub(totalSevenDaysAgo).div(totalSevenDaysAgo.abs()), - }; -}; +import { Wei } from '@synthetixio/wei'; export function calculateCRatio(debt?: Wei, collateralValue?: Wei) { if (debt && collateralValue && !debt.eq(0) && !collateralValue.eq(0)) { diff --git a/liquidity/lib/calculations/package.json b/liquidity/lib/calculations/package.json index 64ed8a1b5..ea86bf4cd 100644 --- a/liquidity/lib/calculations/package.json +++ b/liquidity/lib/calculations/package.json @@ -5,8 +5,6 @@ "version": "0.0.1", "dependencies": { "@snx-v3/constants": "workspace:*", - "@snx-v3/usePoolData": "workspace:*", - "@synthetixio/wei": "^2.74.4", - "zod": "^3.22.4" + "@synthetixio/wei": "^2.74.4" } } diff --git a/liquidity/lib/formatters/number.ts b/liquidity/lib/formatters/number.ts index 8327c761e..88d76d1ee 100644 --- a/liquidity/lib/formatters/number.ts +++ b/liquidity/lib/formatters/number.ts @@ -29,9 +29,3 @@ export const formatPercent = (value: number, options?: Intl.NumberFormatOptions) ...options, }).format(Number(value)); }; - -export function formatApr(apr?: number) { - if (!apr) return '-'; - - return `${apr.toFixed(2)}%`; -} diff --git a/liquidity/lib/useApr/useApr.ts b/liquidity/lib/useApr/useApr.ts index 2e8338c90..b478563a8 100644 --- a/liquidity/lib/useApr/useApr.ts +++ b/liquidity/lib/useApr/useApr.ts @@ -2,6 +2,33 @@ import { getAprUrl } from '@snx-v3/constants'; import { ARBITRUM, BASE_ANDROMEDA, MAINNET, Network, useNetwork } from '@snx-v3/useBlockchain'; import { useQuery } from '@tanstack/react-query'; +export type PositionAPR = { + poolId: number; + collateralType: string; + apr28d: number; + apr28dPnl: number; + apr28dRewards: number; +}; + +const supportedAprNetworks = [BASE_ANDROMEDA.id, ARBITRUM.id, MAINNET.id]; + +export async function fetchApr(networkId?: number) { + try { + const isSupported = networkId && supportedAprNetworks.includes(networkId); + if (!isSupported) { + throw new Error(`APR endpoint not supported for network ${networkId}`); + } + const response = await fetch(getAprUrl(networkId)); + const data: PositionAPR[] = await response.json(); + + // Math.max(...data.map(({ apr28d }: { apr28d: number }) => apr28d)) * 100 + return data; + } catch (error) { + console.error(error); + return []; + } +} + export function useApr(customNetwork?: Network) { const { network } = useNetwork(); const chain = customNetwork || network; @@ -19,35 +46,3 @@ export function useApr(customNetwork?: Network) { enabled: Boolean(chain?.id), }); } - -const supportedAprNetworks = [BASE_ANDROMEDA.id, ARBITRUM.id, MAINNET.id]; - -export async function fetchApr(networkId?: number) { - try { - const isSupported = networkId && supportedAprNetworks.includes(networkId); - if (!isSupported) { - throw new Error('Apr endpoint not supported for this network'); - } - - const response = await fetch(getAprUrl(networkId)); - - const data = await response.json(); - - const highestAprCollateral = data?.sort( - (a: { apr7d: number }, b: { apr7d: number }) => b.apr7d - a.apr7d - )[0]; - - return { - combinedApr: highestAprCollateral.apr7d * 100, - cumulativePnl: isSupported ? highestAprCollateral.cumulativePnl : 0, - collateralAprs: data, - }; - } catch (error) { - console.error(error); - return { - combinedApr: 0, - cumulativePnl: 0, - collateralAprs: [], - }; - } -} diff --git a/liquidity/lib/useAprHistory/index.ts b/liquidity/lib/useAprHistory/index.ts deleted file mode 100644 index b0fdd698c..000000000 --- a/liquidity/lib/useAprHistory/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './useAprHistory'; diff --git a/liquidity/lib/useAprHistory/package.json b/liquidity/lib/useAprHistory/package.json deleted file mode 100644 index 83c15527c..000000000 --- a/liquidity/lib/useAprHistory/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "@snx-v3/useAprHistory", - "private": true, - "main": "index.ts", - "version": "0.0.2", - "dependencies": { - "@snx-v3/useBlockchain": "workspace:*", - "@tanstack/react-query": "^5.8.3", - "react": "^18.2.0" - } -} diff --git a/liquidity/lib/useAprHistory/useAprHistory.ts b/liquidity/lib/useAprHistory/useAprHistory.ts deleted file mode 100644 index 4df58c016..000000000 --- a/liquidity/lib/useAprHistory/useAprHistory.ts +++ /dev/null @@ -1,177 +0,0 @@ -import { Network, useNetwork } from '@snx-v3/useBlockchain'; -import { useQuery } from '@tanstack/react-query'; - -interface PoolData { - apr7d: number; - apr7dPnl: number; - apr7dRewards: number; - apr24h: number; - apr24hPnl: number; - apr24hRewards: number; - apr28d: number; - apr28dPnl: number; - apr28dRewards: number; - aprCombined: number; - aprPnl: number; - aprRewards: number; - apy7d: number; - apy7dPnl: number; - apy7dRewards: number; - apy24h: number; - apy24hPnl: number; - apy24hRewards: number; - apy28d: number; - apy28dPnl: number; - apy28dRewards: number; - collateralType: string; - collateralValue: number; - cumulativeIssuance: number; - cumulativePnl: number; - debtAmount: number; - hourlyIssuance: number; - hourlyPnl: number; - hourlyPnlPct: number; - hourlyRewardsPct: number; - poolId: number; - rewardsUSD: number; - timestamp: string; -} - -const sevenDays = new Date(); -sevenDays.setDate(sevenDays.getDate() - 7); -const sevenWeeks = new Date(); -sevenWeeks.setDate(sevenWeeks.getDate() - 7 * 7); -const sevenMonth = new Date(); -sevenMonth.setDate(sevenMonth.getDate() - 7 * 4 * 7); -const oneYear = new Date(); -oneYear.setDate(oneYear.getDate() - 365); - -export function useAprHistory(customNetwork?: Network) { - const { network } = useNetwork(); - const chain = customNetwork || network; - - return useQuery({ - queryKey: ['apr-history', chain?.id], - queryFn: async () => { - if (!chain?.id) return {}; - try { - const response = await fetch('https://api.synthetix.io/v3/base/sc-pool-apy-history'); - - const data: PoolData[] = await response.json(); - - const sevenDaysAPR = data - .filter((d) => new Date(d.timestamp).getTime() >= sevenDays.getTime()) - .map((d) => ({ - timestamp: d.timestamp, - value: d.apr24h * 100, - pnl: d.apr24hPnl * 100, - rewards: d.apr24hRewards * 100, - combined: d.aprCombined * 100, - pnlCombined: d.aprPnl * 100, - rewardsCombined: d.aprRewards * 100, - })) - .reverse(); - - const sevenWeeksAPR = data - .filter((d) => new Date(d.timestamp).getTime() >= sevenWeeks.getTime()) - .filter((_, index) => index % 7 === 0) - .map((d) => ({ - timestamp: d.timestamp, - value: d.apr7d * 100, - pnl: d.apr7dPnl * 100, - rewards: d.apr7dRewards * 100, - combined: d.aprCombined * 100, - pnlCombined: d.aprPnl * 100, - rewardsCombined: d.aprRewards * 100, - })) - - .reverse(); - const sevenMonthAPR = data - .filter((d) => new Date(d.timestamp).getTime() >= sevenMonth.getTime()) - .filter((_, index) => index % 30 === 0) - .map((d) => ({ - timestamp: d.timestamp, - value: d.apr28d * 100, - pnl: d.apr28dPnl * 100, - rewards: d.apr28dRewards * 100, - combined: d.aprCombined * 100, - pnlCombined: d.aprPnl * 100, - rewardsCombined: d.aprRewards * 100, - })) - .reverse(); - const oneYearAPR = data - .filter((d) => new Date(d.timestamp).getTime() >= oneYear.getTime()) - .map((d) => ({ - timestamp: d.timestamp, - value: d.apr28d * 100, - pnl: d.apr28dPnl * 100, - rewards: d.apr28dRewards * 100, - combined: d.aprCombined * 100, - pnlCombined: d.aprPnl * 100, - rewardsCombined: d.aprRewards * 100, - })) - .reverse(); - - const sevenDaysTVL = data - .filter((d) => new Date(d.timestamp).getTime() >= sevenDays.getTime()) - .map((d) => ({ - timestamp: d.timestamp, - value: d.collateralValue, - })) - .reverse(); - const sevenWeeksTVL = data - .filter((d) => new Date(d.timestamp).getTime() >= sevenWeeks.getTime()) - .map((d) => ({ - timestamp: d.timestamp, - value: d.collateralValue, - })) - .filter((_, index) => index % 7 === 0) - .reverse(); - const sevenMonthTVL = data - .filter((d) => new Date(d.timestamp).getTime() >= sevenMonth.getTime()) - .filter((_, index) => index % 30 === 0) - .map((d) => ({ - timestamp: d.timestamp, - value: d.collateralValue, - })) - .reverse(); - const oneYearTVL = data - .filter((d) => new Date(d.timestamp).getTime() >= oneYear.getTime()) - .map((d) => ({ - timestamp: d.timestamp, - value: d.collateralValue, - })) - .reverse(); - return { - sevenDaysTVL, - sevenWeeksTVL, - sevenMonthTVL, - oneYearTVL, - allTVL: data - .map((d) => ({ - timestamp: d.timestamp, - value: d.collateralValue, - })) - .reverse(), - allAPR: data - .map((d) => ({ - timestamp: d.timestamp, - value: d.apr24h * 100, - pnl: d.apr24hPnl * 100, - rewards: d.apr24hRewards * 100, - combined: d.aprCombined * 100, - pnlCombined: d.aprPnl * 100, - rewardsCombined: d.aprRewards * 100, - })) - .reverse(), - sevenDaysAPR, - sevenWeeksAPR, - sevenMonthAPR, - oneYearAPR, - }; - } catch (error) { - return; - } - }, - }); -} diff --git a/liquidity/lib/usePoolsList/package.json b/liquidity/lib/usePoolsList/package.json index 636fe15e0..57bb6bfe0 100644 --- a/liquidity/lib/usePoolsList/package.json +++ b/liquidity/lib/usePoolsList/package.json @@ -5,7 +5,6 @@ "version": "0.0.2", "dependencies": { "@snx-v3/constants": "workspace:*", - "@snx-v3/useApr": "workspace:*", "@snx-v3/useBlockchain": "workspace:*", "@tanstack/react-query": "^5.8.3" } diff --git a/liquidity/lib/usePoolsList/usePoolsList.ts b/liquidity/lib/usePoolsList/usePoolsList.ts index cbeee7480..7c845c127 100644 --- a/liquidity/lib/usePoolsList/usePoolsList.ts +++ b/liquidity/lib/usePoolsList/usePoolsList.ts @@ -1,50 +1,13 @@ import { getSubgraphUrl, POOL_ID } from '@snx-v3/constants'; -import { fetchApr } from '@snx-v3/useApr'; import { ARBITRUM, BASE_ANDROMEDA, MAINNET, NETWORKS } from '@snx-v3/useBlockchain'; import { useQuery } from '@tanstack/react-query'; -export function usePoolsList() { - return useQuery({ - queryKey: ['poolsList'], - queryFn: async () => { - try { - const [pools, aprs] = await Promise.all([fetchPoolsList(), fetchAprs()]); - - const synthetixPools = pools.map((p, i) => ({ - ...p, - apr: aprs[i], - })); - - return { synthetixPools }; - } catch (error) { - throw error; - } - }, - staleTime: 60000 * 10, - }); -} - -export function usePool(networkId?: number) { - const { data, isPending } = usePoolsList(); - - return { - data: data?.synthetixPools.find( - (p) => p?.network?.id === networkId && p?.poolInfo?.[0]?.pool?.id === POOL_ID - ), - isPending, - }; -} - const supportedNetworks = [MAINNET.id, BASE_ANDROMEDA.id, ARBITRUM.id]; export const networksOffline = NETWORKS.filter( (n) => supportedNetworks.includes(n.id) && n.isSupported ).map((n) => n); -async function fetchAprs() { - return Promise.all(networksOffline.map((network) => fetchApr(network.id))); -} - async function fetchPoolsList() { const urls = networksOffline.map((network) => getSubgraphUrl(network.name)); @@ -92,3 +55,22 @@ interface PoolInfo { id: string; }; } + +export function usePoolsList() { + return useQuery({ + queryKey: ['poolsList'], + queryFn: async () => { + return fetchPoolsList(); + }, + staleTime: 60000 * 10, + }); +} + +export function usePool(networkId?: number) { + const { data, isPending } = usePoolsList(); + + return { + data: data?.find((p) => p?.network?.id === networkId && p?.poolInfo?.[0]?.pool?.id === POOL_ID), + isPending, + }; +} diff --git a/liquidity/ui/package.json b/liquidity/ui/package.json index 418677449..419345645 100644 --- a/liquidity/ui/package.json +++ b/liquidity/ui/package.json @@ -33,7 +33,6 @@ "@snx-v3/Tooltip": "workspace:*", "@snx-v3/constants": "workspace:*", "@snx-v3/format": "workspace:*", - "@snx-v3/formatters": "workspace:*", "@snx-v3/icons": "workspace:*", "@snx-v3/theme": "workspace:*", "@snx-v3/useAccounts": "workspace:*", @@ -45,7 +44,6 @@ "@snx-v3/useLiquidityPosition": "workspace:*", "@snx-v3/useLocalStorage": "workspace:*", "@snx-v3/useParams": "workspace:*", - "@snx-v3/usePoolsList": "workspace:*", "@synthetixio/safe-import": "workspace:*", "@synthetixio/wei": "^2.74.4", "@tanstack/react-query-devtools": "^5.8.3", diff --git a/liquidity/ui/src/ManagePage.tsx b/liquidity/ui/src/ManagePage.tsx index e73aa4845..48137668b 100644 --- a/liquidity/ui/src/ManagePage.tsx +++ b/liquidity/ui/src/ManagePage.tsx @@ -3,19 +3,18 @@ import { Box, Flex, Text } from '@chakra-ui/react'; import { BorderBox } from '@snx-v3/BorderBox'; import { ClosePosition } from '@snx-v3/ClosePosition'; import { UnsupportedCollateralAlert } from '@snx-v3/CollateralAlert'; -import { formatApr } from '@snx-v3/formatters'; import { ManageStats, PositionTitle, StataDepositBanner } from '@snx-v3/Manage'; import { ManageAction } from '@snx-v3/ManageAction'; import { ManagePositionProvider } from '@snx-v3/ManagePositionContext'; import { LockedCollateral } from '@snx-v3/Positions'; import { Tooltip } from '@snx-v3/Tooltip'; +import { useApr } from '@snx-v3/useApr'; import { useStataUSDCApr } from '@snx-v3/useApr/useStataUSDCApr'; import { useNetwork } from '@snx-v3/useBlockchain'; import { useCollateralType } from '@snx-v3/useCollateralTypes'; import { useIsAndromedaStataUSDC } from '@snx-v3/useIsAndromedaStataUSDC'; import { useLiquidityPosition } from '@snx-v3/useLiquidityPosition'; import { type ManageActionType, type PositionPageSchemaType, useParams } from '@snx-v3/useParams'; -import { usePool } from '@snx-v3/usePoolsList'; import React from 'react'; import { Helmet } from 'react-helmet'; @@ -31,8 +30,7 @@ export const ManagePage = () => { collateralType, }); - const { data: stataUSDCAPR } = useStataUSDCApr(network?.id, network?.preset); - const stataUSDCAPRParsed = stataUSDCAPR || 0; + const { data: stataUSDCApr } = useStataUSDCApr(network?.id, network?.preset); const isAndromedaStataUSDC = useIsAndromedaStataUSDC({ tokenAddress: collateralType?.tokenAddress, @@ -41,10 +39,13 @@ export const ManagePage = () => { const [txnModalOpen, setTxnModalOpen] = React.useState(undefined); - const { data: pool, isPending: isPendingPool } = usePool(Number(network?.id)); - - const positionApr = pool?.apr?.collateralAprs?.find( - (item: any) => item.collateralType.toLowerCase() === collateralType?.tokenAddress.toLowerCase() + const { data: apr, isPending: isPendingApr } = useApr(network); + const positionApr = React.useMemo( + () => + apr?.find( + (item) => item.collateralType.toLowerCase() === collateralType?.tokenAddress.toLowerCase() + ), + [apr, collateralType?.tokenAddress] ); return ( @@ -73,7 +74,7 @@ export const ManagePage = () => { > - + { - {isPendingPool - ? '~' - : formatApr( - positionApr?.apr7d > 0 - ? positionApr.apr7d * 100 + (isAndromedaStataUSDC ? stataUSDCAPRParsed : 0) - : undefined - )} + {isPendingApr ? '~' : null} + {!isPendingApr && positionApr && positionApr.apr28d > 0 + ? ( + positionApr.apr28d * 100 + + (isAndromedaStataUSDC && stataUSDCApr ? stataUSDCApr : 0) + ) + .toFixed(2) + .concat('%') + : '-'} diff --git a/yarn.lock b/yarn.lock index cb0e2968c..4fa81daea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5557,9 +5557,7 @@ __metadata: resolution: "@snx-v3/calculations@workspace:liquidity/lib/calculations" dependencies: "@snx-v3/constants": "workspace:*" - "@snx-v3/usePoolData": "workspace:*" "@synthetixio/wei": "npm:^2.74.4" - zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -5697,7 +5695,6 @@ __metadata: "@snx-v3/Tooltip": "workspace:*" "@snx-v3/constants": "workspace:*" "@snx-v3/format": "workspace:*" - "@snx-v3/formatters": "workspace:*" "@snx-v3/icons": "workspace:*" "@snx-v3/theme": "workspace:*" "@snx-v3/useAccounts": "workspace:*" @@ -5709,7 +5706,6 @@ __metadata: "@snx-v3/useLiquidityPosition": "workspace:*" "@snx-v3/useLocalStorage": "workspace:*" "@snx-v3/useParams": "workspace:*" - "@snx-v3/usePoolsList": "workspace:*" "@synthetixio/safe-import": "workspace:*" "@synthetixio/wei": "npm:^2.74.4" "@tanstack/react-query": "npm:^5.8.3" @@ -5956,16 +5952,6 @@ __metadata: languageName: unknown linkType: soft -"@snx-v3/useAprHistory@workspace:liquidity/lib/useAprHistory": - version: 0.0.0-use.local - resolution: "@snx-v3/useAprHistory@workspace:liquidity/lib/useAprHistory" - dependencies: - "@snx-v3/useBlockchain": "workspace:*" - "@tanstack/react-query": "npm:^5.8.3" - react: "npm:^18.2.0" - languageName: unknown - linkType: soft - "@snx-v3/useBlockNumber@workspace:liquidity/lib/useBlockNumber": version: 0.0.0-use.local resolution: "@snx-v3/useBlockNumber@workspace:liquidity/lib/useBlockNumber" @@ -6400,7 +6386,7 @@ __metadata: languageName: unknown linkType: soft -"@snx-v3/usePoolData@workspace:*, @snx-v3/usePoolData@workspace:liquidity/lib/usePoolData": +"@snx-v3/usePoolData@workspace:liquidity/lib/usePoolData": version: 0.0.0-use.local resolution: "@snx-v3/usePoolData@workspace:liquidity/lib/usePoolData" dependencies: @@ -6432,7 +6418,6 @@ __metadata: resolution: "@snx-v3/usePoolsList@workspace:liquidity/lib/usePoolsList" dependencies: "@snx-v3/constants": "workspace:*" - "@snx-v3/useApr": "workspace:*" "@snx-v3/useBlockchain": "workspace:*" "@tanstack/react-query": "npm:^5.8.3" languageName: unknown