From 1cb681192eda118594ebdb7edae9bbd79334af6f Mon Sep 17 00:00:00 2001 From: chefmomota Date: Thu, 21 Dec 2023 14:33:10 +0800 Subject: [PATCH 1/3] feat: Add Alp Fee --- src/pools/service/alpFee.ts | 75 +++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/pools/service/alpFee.ts diff --git a/src/pools/service/alpFee.ts b/src/pools/service/alpFee.ts new file mode 100644 index 0000000..d4e727e --- /dev/null +++ b/src/pools/service/alpFee.ts @@ -0,0 +1,75 @@ +import { ChainId } from "@pancakeswap/sdk"; +import BigNumber from "bignumber.js"; +import { Address } from "viem"; +import { getViemClients } from "../../utils/viem"; + +const WEEK = 7 +const YEAR = 365 +const API_URL = 'https://perp.pancakeswap.finance/bapi/futures/v1/public/future/apx/fee/info?chain=' + +const CONTRACT_ADDRESS: Record = { + [ChainId.OPBNB]: '0x5A5454A6030FB50ceb3eb78977D140198A27be5e', + [ChainId.ARBITRUM_ONE]: '0xB3879E95a4B8e3eE570c232B19d520821F540E48', +} + +const CHAIN_NAME_MAP: Record = { + [ChainId.OPBNB]: 'OPBNB', + [ChainId.ARBITRUM_ONE]: 'ARB', +} + +export const alpFee = async (chainId: ChainId) => { + const client = getViemClients({ chainId }); + try { + const [totalValue] = await client.multicall({ + contracts: [ + { + abi: [ + { + inputs: [], + name: 'totalValue', + outputs: [ + { + components: [ + { internalType: 'address', name: 'tokenAddress', type: 'address' }, + { internalType: 'int256', name: 'value', type: 'int256' }, + { internalType: 'uint8', name: 'decimals', type: 'uint8' }, + { internalType: 'int256', name: 'valueUsd', type: 'int256' }, + { internalType: 'uint16', name: 'targetWeight', type: 'uint16' }, + { internalType: 'uint16', name: 'feeBasisPoints', type: 'uint16' }, + { internalType: 'uint16', name: 'taxBasisPoints', type: 'uint16' }, + { internalType: 'bool', name: 'dynamicFee', type: 'bool' }, + ], + internalType: 'struct IVault.LpItem[]', + name: 'lpItems', + type: 'tuple[]', + }, + ], + stateMutability: 'view', + type: 'function', + }, + ] as const, + address: CONTRACT_ADDRESS?.[chainId], + functionName: 'totalValue', + }, + ], + allowFailure: false, + }) + + const totalValueUsd = totalValue + .map((i) => new BigNumber(i.valueUsd.toString()).div(1e18).toNumber()) + .reduce((a, b) => a + b, 0) + + const response = await fetch(`${API_URL}${CHAIN_NAME_MAP[chainId]}`) + const result = await response.json() + + const { alpFundingFee, alpTradingFee, alpLipFee } = result.data + const apr = new BigNumber(alpFundingFee).plus(alpTradingFee).plus(alpLipFee) + const totalApr = apr.div(totalValueUsd.toString()).div(WEEK) + + const apy = totalApr.plus(1).exponentiatedBy(YEAR).minus(1).times(100) + return apy.toNumber() + } catch (error) { + console.info('Fetch ALP boosted fee error: ', error) + return 0 + } +} \ No newline at end of file From 1d26908aacd350c1efd25928aa1b8650a16f8397 Mon Sep 17 00:00:00 2001 From: chefmomota Date: Thu, 21 Dec 2023 14:39:58 +0800 Subject: [PATCH 2/3] feat: Move in try --- src/pools/service/alpFee.ts | 74 ++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/pools/service/alpFee.ts b/src/pools/service/alpFee.ts index d4e727e..4d9890c 100644 --- a/src/pools/service/alpFee.ts +++ b/src/pools/service/alpFee.ts @@ -3,73 +3,73 @@ import BigNumber from "bignumber.js"; import { Address } from "viem"; import { getViemClients } from "../../utils/viem"; -const WEEK = 7 -const YEAR = 365 -const API_URL = 'https://perp.pancakeswap.finance/bapi/futures/v1/public/future/apx/fee/info?chain=' +const WEEK = 7; +const YEAR = 365; +const API_URL = "https://perp.pancakeswap.finance/bapi/futures/v1/public/future/apx/fee/info?chain="; const CONTRACT_ADDRESS: Record = { - [ChainId.OPBNB]: '0x5A5454A6030FB50ceb3eb78977D140198A27be5e', - [ChainId.ARBITRUM_ONE]: '0xB3879E95a4B8e3eE570c232B19d520821F540E48', -} + [ChainId.OPBNB]: "0x5A5454A6030FB50ceb3eb78977D140198A27be5e", + [ChainId.ARBITRUM_ONE]: "0xB3879E95a4B8e3eE570c232B19d520821F540E48", +}; const CHAIN_NAME_MAP: Record = { - [ChainId.OPBNB]: 'OPBNB', - [ChainId.ARBITRUM_ONE]: 'ARB', -} + [ChainId.OPBNB]: "OPBNB", + [ChainId.ARBITRUM_ONE]: "ARB", +}; export const alpFee = async (chainId: ChainId) => { - const client = getViemClients({ chainId }); try { + const client = getViemClients({ chainId }); const [totalValue] = await client.multicall({ contracts: [ { abi: [ { inputs: [], - name: 'totalValue', + name: "totalValue", outputs: [ { components: [ - { internalType: 'address', name: 'tokenAddress', type: 'address' }, - { internalType: 'int256', name: 'value', type: 'int256' }, - { internalType: 'uint8', name: 'decimals', type: 'uint8' }, - { internalType: 'int256', name: 'valueUsd', type: 'int256' }, - { internalType: 'uint16', name: 'targetWeight', type: 'uint16' }, - { internalType: 'uint16', name: 'feeBasisPoints', type: 'uint16' }, - { internalType: 'uint16', name: 'taxBasisPoints', type: 'uint16' }, - { internalType: 'bool', name: 'dynamicFee', type: 'bool' }, + { internalType: "address", name: "tokenAddress", type: "address" }, + { internalType: "int256", name: "value", type: "int256" }, + { internalType: "uint8", name: "decimals", type: "uint8" }, + { internalType: "int256", name: "valueUsd", type: "int256" }, + { internalType: "uint16", name: "targetWeight", type: "uint16" }, + { internalType: "uint16", name: "feeBasisPoints", type: "uint16" }, + { internalType: "uint16", name: "taxBasisPoints", type: "uint16" }, + { internalType: "bool", name: "dynamicFee", type: "bool" }, ], - internalType: 'struct IVault.LpItem[]', - name: 'lpItems', - type: 'tuple[]', + internalType: "struct IVault.LpItem[]", + name: "lpItems", + type: "tuple[]", }, ], - stateMutability: 'view', - type: 'function', + stateMutability: "view", + type: "function", }, ] as const, address: CONTRACT_ADDRESS?.[chainId], - functionName: 'totalValue', + functionName: "totalValue", }, ], allowFailure: false, - }) + }); const totalValueUsd = totalValue .map((i) => new BigNumber(i.valueUsd.toString()).div(1e18).toNumber()) - .reduce((a, b) => a + b, 0) + .reduce((a, b) => a + b, 0); - const response = await fetch(`${API_URL}${CHAIN_NAME_MAP[chainId]}`) - const result = await response.json() + const response = await fetch(`${API_URL}${CHAIN_NAME_MAP[chainId]}`); + const result = await response.json(); - const { alpFundingFee, alpTradingFee, alpLipFee } = result.data - const apr = new BigNumber(alpFundingFee).plus(alpTradingFee).plus(alpLipFee) - const totalApr = apr.div(totalValueUsd.toString()).div(WEEK) + const { alpFundingFee, alpTradingFee, alpLipFee } = result.data; + const apr = new BigNumber(alpFundingFee).plus(alpTradingFee).plus(alpLipFee); + const totalApr = apr.div(totalValueUsd.toString()).div(WEEK); - const apy = totalApr.plus(1).exponentiatedBy(YEAR).minus(1).times(100) - return apy.toNumber() + const apy = totalApr.plus(1).exponentiatedBy(YEAR).minus(1).times(100); + return apy.toNumber(); } catch (error) { - console.info('Fetch ALP boosted fee error: ', error) - return 0 + console.info("Fetch ALP boosted fee error: ", error); + return 0; } -} \ No newline at end of file +}; From 97b378a55bfcd6b7ae08e1c1090e0cc9759d4d66 Mon Sep 17 00:00:00 2001 From: ChefJoJo <94336009+chef-jojo@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:00:44 +0800 Subject: [PATCH 3/3] add in api --- src/pools/constants/types.ts | 1 + src/pools/service/poolMetrics.ts | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/pools/constants/types.ts b/src/pools/constants/types.ts index e76c542..94c6c95 100644 --- a/src/pools/constants/types.ts +++ b/src/pools/constants/types.ts @@ -17,6 +17,7 @@ interface PoolMetrics { stakingTokenPrice: number; earningTokenPrice: number; apr: number; + alpApr?: number; endTimestamp: number; } diff --git a/src/pools/service/poolMetrics.ts b/src/pools/service/poolMetrics.ts index 2e591cc..b3e2f2b 100644 --- a/src/pools/service/poolMetrics.ts +++ b/src/pools/service/poolMetrics.ts @@ -5,6 +5,7 @@ import { fetchCakeTokenPrice } from "./cakeTokenPrice"; import { fetchEndTimestamp } from "./endTimestamp"; import { fetchTotalStaked } from "./totalStacked"; import { ChainId } from "@pancakeswap/sdk"; +import { alpFee } from "./alpFee"; export const calculatePoolMetrics = async (poolsConfigs: SerializedPool[], chainId: ChainId) => { return await Promise.all(poolsConfigs.map((value) => fillMetric(value, chainId))); @@ -21,11 +22,13 @@ const fillMetric = async (poolConfig: SerializedPool, chainId) => { poolConfig.tokenPerSecond ); const endTimestamp = await fetchEndTimestamp(poolConfig.contractAddress, chainId); + const alpApr = await alpFee(chainId); poolConfig.metrics.totalStaked = totalStaked; poolConfig.metrics.stakingTokenPrice = stakingTokenPrice; poolConfig.metrics.earningTokenPrice = earningTokenPrice; poolConfig.metrics.apr = apr; + poolConfig.metrics.alpApr = alpApr; poolConfig.metrics.endTimestamp = endTimestamp; return poolConfig;