From 10c888b9f5bd85fbc9447363297598c317e37852 Mon Sep 17 00:00:00 2001 From: Peiman Date: Thu, 3 Oct 2024 04:08:40 +0330 Subject: [PATCH] feat: toros pool card --- liquidity/lib/usePoolsList/usePoolsList.ts | 12 +- .../src/components/Pools/CollateralFilter.tsx | 10 +- .../components/Pools/PoolCards/Specifics.tsx | 107 +++++++----------- .../Pools/PoolCards/TorosPoolCard.tsx | 51 ++++++--- .../ui/src/components/Pools/PoolsList.tsx | 61 ++++++---- yarn.lock | 6 +- 6 files changed, 123 insertions(+), 124 deletions(-) diff --git a/liquidity/lib/usePoolsList/usePoolsList.ts b/liquidity/lib/usePoolsList/usePoolsList.ts index 6b7973e4..6d53b446 100644 --- a/liquidity/lib/usePoolsList/usePoolsList.ts +++ b/liquidity/lib/usePoolsList/usePoolsList.ts @@ -9,18 +9,14 @@ export function usePoolsList() { queryKey: ['poolsList'], queryFn: async () => { try { - const [pools, aprs, toros] = await Promise.all([ - fetchPoolsList(), - fetchAprs(), - fetchTorosPool(), - ]); + const [pools, aprs] = await Promise.all([fetchPoolsList(), fetchAprs()]); const synthetixPools = pools.map((p, i) => ({ ...p, apr: aprs[i], })); - return { synthetixPools, toros }; + return { synthetixPools }; } catch (error) { throw error; } @@ -43,7 +39,7 @@ export function usePool(networkId: number, poolId: string) { const supportedNetworks = [MAINNET.id, BASE_ANDROMEDA.id, ARBITRUM.id]; -async function fetchTorosPool() { +export async function fetchTorosPool(address: string) { return fetch('https://api-v2.dhedge.org/graphql', { method: 'POST', headers: { @@ -60,7 +56,7 @@ async function fetchTorosPool() { } } }`, - variables: { address: '0xc1e02884af4a283ca25ab63c45360d220d69da52' }, + variables: { address }, }), }) .then((response) => response.json()) diff --git a/liquidity/ui/src/components/Pools/CollateralFilter.tsx b/liquidity/ui/src/components/Pools/CollateralFilter.tsx index 8f38a9b1..fa8429ef 100644 --- a/liquidity/ui/src/components/Pools/CollateralFilter.tsx +++ b/liquidity/ui/src/components/Pools/CollateralFilter.tsx @@ -3,15 +3,15 @@ import { Flex, Button } from '@chakra-ui/react'; import { TokenIcon } from '../TokenIcon'; import { PoolsFilterAction } from './PoolsList'; -const supportedCollateralTypes = ['WETH', 'SNX', 'USDC', 'ARB']; +const supportedCollateralTypes = ['WETH', 'SNX', 'USDC', 'ARB', 'wstETH']; interface CollateralFilterProps { - activeCollateral: string[]; + activeCollaterals: string[]; dispatch: Dispatch; } -export const CollateralFilter = ({ activeCollateral, dispatch }: CollateralFilterProps) => { - const isAllActive = activeCollateral.length === 0; +export const CollateralFilter = ({ activeCollaterals, dispatch }: CollateralFilterProps) => { + const isAllActive = activeCollaterals.length === 0; return ( @@ -31,7 +31,7 @@ export const CollateralFilter = ({ activeCollateral, dispatch }: CollateralFilte All Collaterals {supportedCollateralTypes.map((collateral) => { - const isActive = activeCollateral.includes(collateral); + const isActive = activeCollaterals.includes(collateral); const toggle = () => { if (isActive) { diff --git a/liquidity/ui/src/components/Pools/PoolCards/Specifics.tsx b/liquidity/ui/src/components/Pools/PoolCards/Specifics.tsx index c215f256..fafb9213 100644 --- a/liquidity/ui/src/components/Pools/PoolCards/Specifics.tsx +++ b/liquidity/ui/src/components/Pools/PoolCards/Specifics.tsx @@ -1,4 +1,4 @@ -import { Flex, Text, Tooltip } from '@chakra-ui/react'; +import { Text, Tooltip } from '@chakra-ui/react'; import { isBaseAndromeda } from '@snx-v3/isBaseAndromeda'; import { Network } from '@snx-v3/useBlockchain'; import { CollateralType } from '@snx-v3/useCollateralTypes'; @@ -12,72 +12,45 @@ export const Specifics: React.FC<{ if (isToros) { return ( - - - - - - - - - - - - - - - - + + + + + + + + ); } diff --git a/liquidity/ui/src/components/Pools/PoolCards/TorosPoolCard.tsx b/liquidity/ui/src/components/Pools/PoolCards/TorosPoolCard.tsx index f60b10d4..d00c10d7 100644 --- a/liquidity/ui/src/components/Pools/PoolCards/TorosPoolCard.tsx +++ b/liquidity/ui/src/components/Pools/PoolCards/TorosPoolCard.tsx @@ -1,21 +1,40 @@ import { Flex, Text, Button, Link, Fade, Icon, IconProps } from '@chakra-ui/react'; -import { BASE_ANDROMEDA, NetworkIcon } from '@snx-v3/useBlockchain'; +import { ARBITRUM, BASE_ANDROMEDA, NetworkIcon } from '@snx-v3/useBlockchain'; import { TokenIcon } from '../../TokenIcon'; -import { useGetWrapperToken } from '@snx-v3/useGetUSDTokens'; -import { getSpotMarketId } from '@snx-v3/isBaseAndromeda'; import { useTokenBalance } from '@snx-v3/useTokenBalance'; import { formatNumberToUsd } from '@snx-v3/formatters'; import { formatNumber } from 'humanize-plus'; import { Specifics } from './Specifics'; +import { useQuery } from '@tanstack/react-query'; +import { fetchTorosPool } from '@snx-v3/usePoolsList'; interface TorosPoolCardProps { - tvl: string; - apy: number; + token: 'USDC' | 'wstETH'; } -export function TorosPoolCard({ tvl, apy }: TorosPoolCardProps) { - const { data: wrapperToken } = useGetWrapperToken(getSpotMarketId('USDC'), BASE_ANDROMEDA); - const { data: balance } = useTokenBalance(wrapperToken, BASE_ANDROMEDA); +const vaults = { + USDC: { + pool: '0xc1e02884af4a283ca25ab63c45360d220d69da52', + address: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913', + network: BASE_ANDROMEDA, + link: 'https://toros.finance/synthetix-usdc-andromeda-yield', + }, + wstETH: { + pool: '0xe9b5260d99d283ff887859c569baf8ad1bd12aac', + address: '0x5979d7b546e38e414f7e9822514be443a4800529', + network: ARBITRUM, + link: 'https://toros.finance/synthetix-eth-yield', + }, +}; + +export function TorosPoolCard({ token }: TorosPoolCardProps) { + const vault = vaults[token]; + + const { data: balance } = useTokenBalance(vault.address, vault.network); + const { data } = useQuery({ + queryKey: ['toros-pool', token], + queryFn: () => fetchTorosPool(vault.pool), + }); return ( @@ -32,12 +51,12 @@ export function TorosPoolCard({ tvl, apy }: TorosPoolCardProps) { > - + @@ -49,7 +68,7 @@ export function TorosPoolCard({ tvl, apy }: TorosPoolCardProps) { lineHeight="1.25rem" fontFamily="heading" > - USDC + {token} - Base Network + {vault.network.name} Network @@ -73,7 +92,7 @@ export function TorosPoolCard({ tvl, apy }: TorosPoolCardProps) { {balance ? formatNumberToUsd(balance.toNumber()) : '-'} - {balance ? formatNumber(balance.toNumber()) : ''} USDC + {balance ? formatNumber(balance.toNumber()) : ''} {token} @@ -99,7 +118,7 @@ export function TorosPoolCard({ tvl, apy }: TorosPoolCardProps) { color="white" textAlign="right" > - ${tvl} + ${data?.tvl} @@ -110,7 +129,7 @@ export function TorosPoolCard({ tvl, apy }: TorosPoolCardProps) { fontWeight={500} color="white" > - {apy}% + {data?.apy}% @@ -118,7 +137,7 @@ export function TorosPoolCard({ tvl, apy }: TorosPoolCardProps) { { - const [state, dispatch] = useReducer(poolsReducer, { collateral: [], chain: [] }); + const [state, dispatch] = useReducer(poolsReducer, { collaterals: [], chains: [] }); const { data, isLoading: isPoolsListLoading } = usePoolsList(); const { data: BaseCollateralTypes, isLoading: isBaseCollateralLoading } = useCollateralTypes( @@ -70,11 +70,7 @@ export const PoolsList = () => { // Mainnet Rewards const { data: MainRewards, isLoading: isMainRewardsLoading } = useRewardsDistributors(MAINNET); - const { collateral, chain } = state; - - const showToros = - (chain.length === 0 || chain.includes(BASE_ANDROMEDA.id)) && - (collateral.length === 0 || collateral.includes('USDC')); + const { collaterals, chains } = state; const isLoading = isPoolsListLoading || @@ -129,13 +125,13 @@ export const PoolsList = () => { }) .filter((pool) => { const { network, collateralTypes } = pool; - if (chain.length > 0 && !chain.includes(network.id)) { + if (chains.length > 0 && !chains.includes(network.id)) { return false; } const isCollateralFiltered = collateralTypes?.some((collateralType) => - collateral.length - ? !!collateral.find((collateral) => { + collaterals.length + ? !!collaterals.find((collateral) => { if ( isBaseAndromeda(network.id, network.preset) && collateralType.symbol.toUpperCase() === 'SUSDC' @@ -162,8 +158,8 @@ export const PoolsList = () => { BaseRewards, MainnetCollateralTypes, MainRewards, - chain, - collateral, + chains, + collaterals, ]); const allCollateralPrices = useMemo(() => { @@ -178,8 +174,8 @@ export const PoolsList = () => { Pools - - + + @@ -262,12 +258,27 @@ export const PoolsList = () => { {isLoading && !filteredPools?.length ? : null} - {showToros ? : null} + {(!chains.length || chains.includes(BASE_ANDROMEDA.id)) && + (!collaterals.length || collaterals.includes('USDC')) ? ( + + ) : null} + {(!chains.length || chains.includes(ARBITRUM.id)) && + (!collaterals.length || collaterals.includes('wstETH')) ? ( + + ) : null} {filteredPools?.length > 0 ? filteredPools.map( ({ network, poolInfo, apr, collateralTypes, rewardsDistributors }) => { const { pool } = poolInfo[0]; + const filteredCollateralTypes = collateralTypes?.filter((collateralType) => { + if (!collaterals.length) { + return true; + } + + return collaterals.includes(collateralType.symbol); + }); + const rewardsPayoutTokens = [ ...new Set( rewardsDistributors?.map(({ payoutToken }: any) => @@ -279,7 +290,7 @@ export const PoolsList = () => { return ( { }; interface PoolsFilterState { - collateral: string[]; - chain: number[]; + collaterals: string[]; + chains: number[]; } export interface PoolsFilterAction { @@ -342,14 +353,14 @@ function poolsReducer(state: PoolsFilterState, action: PoolsFilterAction): Pools return { ...state, // Only one collateral active at once - collateral: [action.payload.collateral], + collaterals: [action.payload.collateral], }; } case 'REMOVE_COLLATERAL': return { ...state, - collateral: state.collateral.filter((item) => item !== action.payload?.collateral), + collaterals: state.collaterals.filter((item) => item !== action.payload?.collateral), }; case 'ADD_CHAIN': @@ -357,26 +368,26 @@ function poolsReducer(state: PoolsFilterState, action: PoolsFilterAction): Pools // Only one chain active at once return { ...state, - chain: [action.payload.chain], + chains: [action.payload.chain], }; } case 'REMOVE_CHAIN': return { ...state, - chain: state.chain.filter((item) => item !== action.payload?.chain), + chains: state.chains.filter((item) => item !== action.payload?.chain), }; case 'RESET_COLLATERAL': return { - collateral: [], - chain: state.chain, + collaterals: [], + chains: state.chains, }; case 'RESET_CHAIN': return { - collateral: state.collateral, - chain: [], + collaterals: state.collaterals, + chains: [], }; default: diff --git a/yarn.lock b/yarn.lock index 31f46318..ebb57de9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6614,9 +6614,9 @@ __metadata: linkType: soft "@synthetixio/v3-contracts@npm:^6.10.0": - version: 6.12.0 - resolution: "@synthetixio/v3-contracts@npm:6.12.0" - checksum: 10/2bf320ff9a56ae6716476c77aaa95f7ca1a2ab00e3eb29d2ba942083b787f6ddd693e1bf982b9d37c69c13a716f747571874cf042b7adc899c8491a2b4a7049b + version: 6.13.0 + resolution: "@synthetixio/v3-contracts@npm:6.13.0" + checksum: 10/30375af354ced5904c335c4bcb2e4649ea9c01c7bdc0ecd776dc0f84847e189c73264b4872e006748ec01635df1122938be9fe61a1557fb70ef193e28c610cd2 languageName: node linkType: hard