diff --git a/src/components/client/StatsPage.tsx b/src/components/client/StatsPage.tsx index a4166bc3..21ba1c9e 100644 --- a/src/components/client/StatsPage.tsx +++ b/src/components/client/StatsPage.tsx @@ -13,8 +13,6 @@ import { } from '@chakra-ui/react' import React from 'react' import * as Humanize from 'humanize-plus' -import { PolygonFrax } from '@/components/icons/polygon-frax' -import { USDCIQ } from '@/components/icons/usdc-iq' import { Twitter } from '@/components/icons/twitter' import { Reddit } from '@/components/icons/reddit' import { Ethereum } from '@/components/icons/ethereum' @@ -25,6 +23,8 @@ import { SushiSwap } from '../icons/sushiswap' import PageHeader from '../dashboard/PageHeader' import { Fraxswap } from '../icons/fraxswap' import { useTranslations } from 'next-intl' +import FraxtalCurveIcon from '../icons/fraxswap-fraxtal' +import CurveFraxtalIcon from '../icons/curve-fraxtal' type Stat = { label: string @@ -96,12 +96,12 @@ const StatsPage = () => { [ t('labels.lpLiquidityFraxswap'), t('labels.lpLiquiditySushiswap'), - t('labels.lpLiquidityFraxSwapPolygon'), - t('labels.lpLiquidityQuickSwap'), + 'LP Liquidity BAMM', + 'LP Liquidity Curve Fraxtal', ], 'lp', - ['fraxSwap', 'sushiSwap', 'polygonSwap', 'quickSwap'], - [Fraxswap, SushiSwap, PolygonFrax, USDCIQ], + ['fraxSwap', 'sushiSwap', 'bammLiquidity', 'curveFraxtal'], + [Fraxswap, SushiSwap, FraxtalCurveIcon, CurveFraxtalIcon], ) const IQ = generateArray2( diff --git a/src/components/icons/curve-fraxtal.tsx b/src/components/icons/curve-fraxtal.tsx new file mode 100644 index 00000000..a69c573e --- /dev/null +++ b/src/components/icons/curve-fraxtal.tsx @@ -0,0 +1,6111 @@ +import { Icon, IconProps } from '@chakra-ui/react' + +export default function CurveFraxtalIcon(props: IconProps) { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} diff --git a/src/components/icons/fraxswap-fraxtal.tsx b/src/components/icons/fraxswap-fraxtal.tsx new file mode 100644 index 00000000..aa71e4df --- /dev/null +++ b/src/components/icons/fraxswap-fraxtal.tsx @@ -0,0 +1,38 @@ +import { Icon, IconProps } from '@chakra-ui/react' + +export default function FraxtalCurveIcon(props: IconProps) { + return ( + + + + + + + + + + + + + + ) +} diff --git a/src/pages/api/chain-balance.tsx b/src/pages/api/chain-balance.tsx new file mode 100644 index 00000000..427cc67f --- /dev/null +++ b/src/pages/api/chain-balance.tsx @@ -0,0 +1,47 @@ +import config from '@/config' +import { ResponseData } from '@/types/TreasuryTokenType' +import { setCacheHeaders } from '@/utils/cache' +import type { NextApiRequest, NextApiResponse } from 'next' + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse, +) { + if (req.method !== 'GET') { + return res + .status(405) + .json({ status: false, message: 'Method not allowed' }) + } + try { + const { chainId, id } = req.query + if (!chainId || !id) { + return res.status(400).json({ + status: false, + message: 'chain id and wallet address are needed', + }) + } + const url = `https://pro-openapi.debank.com/v1/user/chain_balance?chain_id=${chainId}&id=${id}` + const result = await fetch(url, { + headers: { + Accept: 'application/json', + Accesskey: `${config.debankApiKey}`, + }, + }) + setCacheHeaders(res) + return res.status(200).json({ + response: await result.json(), + status: true, + message: 'Balance details successfully fetched', + }) + } catch (error) { + console.error('Fetch balance details error:', error) + + return res.status(500).json({ + status: false, + message: + error instanceof Error + ? error.message + : 'Failed to fetch protocol details', + }) + } +} diff --git a/src/pages/api/liquidity-pool.ts b/src/pages/api/liquidity-pool.ts new file mode 100644 index 00000000..332bf395 --- /dev/null +++ b/src/pages/api/liquidity-pool.ts @@ -0,0 +1,47 @@ +import config from '@/config' +import { ResponseData } from '@/types/TreasuryTokenType' +import { setCacheHeaders } from '@/utils/cache' +import type { NextApiRequest, NextApiResponse } from 'next' + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse, +) { + if (req.method !== 'GET') { + return res + .status(405) + .json({ status: false, message: 'Method not allowed' }) + } + try { + const { chainId, id } = req.query + if (!chainId || !id) { + return res.status(400).json({ + status: false, + message: 'chain id and wallet address are needed', + }) + } + const url = `https://pro-openapi.debank.com/v1/pool?chain_id=${chainId}&id=${id}&is_all=true` + const result = await fetch(url, { + headers: { + Accept: 'application/json', + Accesskey: `${config.debankApiKey}`, + }, + }) + setCacheHeaders(res) + return res.status(200).json({ + response: await result.json(), + status: true, + message: 'pool details successfully fetched', + }) + } catch (error) { + console.error('Fetch pool details error:', error) + + return res.status(500).json({ + status: false, + message: + error instanceof Error + ? error.message + : 'Failed to fetch protocol details', + }) + } +} diff --git a/src/utils/stats-data.ts b/src/utils/stats-data.ts index b3c7b27f..8d6b5ae7 100644 --- a/src/utils/stats-data.ts +++ b/src/utils/stats-data.ts @@ -1,13 +1,11 @@ import config from '@/config' -import { ethAlchemy, polygonAlchemy } from '@/config/alchemy-sdk' +import { ethAlchemy } from '@/config/alchemy-sdk' import { NORMALIZE_VALUE } from '@/data/LockConstants' import { bscHolders, ETHPLORER_CONTRACT_ADDRESS, ETHPLORER_TOKEN_ADDRESSES, maticHolders, - POLYGON_CONTRACT_ADDRESS, - POLYGON_TOKEN_ADDRESSES, } from '@/data/StatsData' import { Alchemy } from 'alchemy-sdk' import axios from 'axios' @@ -21,6 +19,13 @@ import { readContract } from '@wagmi/core' import hiIQABI from '@/abis/hiIQABI.abi' import IQABI from '@/abis/IQABI.abi' import { useGetHIIQHoldersCountQuery } from '@/services/holders' +import { store } from '@/store/store' +import { getProtocolDetails } from '@/services/treasury/restApi' + +const CURVE_LIQUIDITY_POOL_ADDRESS = + '0xfb8b95fb2296a0ad4b6b1419fdaa5aa5f13e4009' +const BAMM_WALLET_ADDRESS = '0xc0780420d79e1eef7a597b3af6663d79bdbf13ae' +const BAMM_FRAXSWAP_POOL_ADDRESS = '0xdf1c16eabc74afe18ddc81f2e0b0cf16582d92a8' const getEosSupplyUsingGreymassAPI = async () => { try { @@ -218,6 +223,62 @@ const getIQ = async () => { } } +const _getFraxConvexData = async (assetTokenLength: number) => { + const { data } = await store.dispatch( + getProtocolDetails.initiate({ + protocolId: 'frax_convex', + id: '0x5493f3dbe06accd1f51568213de839498a2a3b83', + }), + ) + return data + .filter((item: any) => item.asset_token_list.length > assetTokenLength) + .reduce((total: number, item: any) => total + item.stats.asset_usd_value, 0) +} + +const getSushiSwapData = async () => { + const data = await fetchEndpointData( + { protocolId: 'sushiswap', id: config.treasuryAddress as string }, + '/api/protocols', + ) + return data.portfolio_item_list[0].stats.asset_usd_value +} + +const getCurveFraxtalData = async () => { + const data = await fetchEndpointData( + { + chainId: 'frax', + id: CURVE_LIQUIDITY_POOL_ADDRESS, + }, + '/api/liquidity-pool', + ) + + return data?.stats.deposit_usd_value || 0 +} + +const getBAMMFraxswapPoolData = async () => { + const data = await fetchEndpointData( + { + chainId: 'frax', + id: BAMM_FRAXSWAP_POOL_ADDRESS, + }, + '/api/liquidity-pool', + ) + + return data?.stats.deposit_usd_value || 0 +} + +const getBAMMTotalChainBalance = async () => { + const data = await fetchEndpointData( + { + chainId: 'frax', + id: BAMM_WALLET_ADDRESS, + }, + '/api/chain-balance', + ) + + return data?.usd_value || 0 +} + const getLPs = async () => { const fetchData = async (promise: Promise) => { try { @@ -229,35 +290,32 @@ const getLPs = async () => { } const promises = [ - fetch('/api/quickswap-details') - .then((response) => response.json()) - .then((data) => data.data), calculateLPBalance( ethAlchemy, ETHPLORER_CONTRACT_ADDRESS, ETHPLORER_TOKEN_ADDRESSES, ), - calculateLPBalance( - polygonAlchemy, - POLYGON_CONTRACT_ADDRESS, - POLYGON_TOKEN_ADDRESSES, - ), - fetchEndpointData( - { protocolId: 'sushiswap', id: config.treasuryAddress as string }, - '/api/protocols', - ).then((data) => data.portfolio_item_list[0].stats.asset_usd_value), + fetchData(getSushiSwapData()), + fetchData(getCurveFraxtalData()), + fetchData(getBAMMTotalChainBalance()), + fetchData(getBAMMFraxswapPoolData()), ] - const [quickSwap, fraxSwap, polygonSwap, sushiSwap] = await Promise.all( - promises.map(fetchData), - ) + const [ + fraxSwap, + sushiSwap, + curveFraxtal, + bammTotalChainBalance, + bammFraxswapLiquidity, + ] = await Promise.all(promises.map(fetchData)) + const bammLiquidity = bammTotalChainBalance - bammFraxswapLiquidity return { lp: { fraxSwap, - quickSwap, - polygonSwap, + bammLiquidity, sushiSwap, + curveFraxtal, }, } } diff --git a/src/utils/use-stats-data.ts b/src/utils/use-stats-data.ts index 5859badf..2d4e4aa1 100644 --- a/src/utils/use-stats-data.ts +++ b/src/utils/use-stats-data.ts @@ -22,7 +22,12 @@ const initialDataForIQ = { } const initialDataForLPs = { - lp: { fraxSwap: 0, quickSwap: 0, polygonSwap: 0, sushiSwap: 0 }, + lp: { + fraxSwap: 0, + bammLiquidity: 0, + sushiSwap: 0, + curveFraxtal: 0, + }, } const initialDataForSocialData = {