From ae43c41cb553d900e636df9bba43b25790ed978d Mon Sep 17 00:00:00 2001 From: pavlo-tolok Date: Mon, 2 Dec 2024 14:15:50 +0100 Subject: [PATCH] FEAT(PRIM-6971):Check why Primex is not shown on the Yield page, add it --- src/adaptors/primex-finance/index.js | 166 +++++++++++++++++---------- src/adaptors/primex-finance/utils.js | 102 +++++++++------- 2 files changed, 163 insertions(+), 105 deletions(-) diff --git a/src/adaptors/primex-finance/index.js b/src/adaptors/primex-finance/index.js index 2f143a55a5..bc4051b88e 100644 --- a/src/adaptors/primex-finance/index.js +++ b/src/adaptors/primex-finance/index.js @@ -1,55 +1,66 @@ const sdk = require('@defillama/sdk'); const superagent = require('superagent'); const { abi } = require('./abi'); -const { CHAIN_IDS, DEAD_ADDRESS, ROLES, SECONDS_PER_YEAR, APY_REWARD_BONUS, config, addressEq, getPoolUrl } = require('./utils') +const { + CHAIN_IDS, + DEAD_ADDRESS, + ROLES, + SECONDS_PER_YEAR, + APY_REWARD_BONUS, + config, + configV2, + addressEq, + getPoolUrl, +} = require('./utils'); const formatPool = async (bucket, config, EPMXPrice) => { - const { bucketAddress, asset, supportedAssets, supply, demand, bar, lar, estimatedBar, estimatedLar, miningParams, name } = bucket; - const { chain, activityRewardDistributor, EPMX, USDCE, apyRewardBySymbol } = config - - const [rewardPerTokenLender, rewardPerTokenTrader] = (await Promise.all( - Object.values(ROLES).map((r) => { - return ( - sdk.api.abi.call({ - abi: abi.activityRewardDistributorBuckets, - target: activityRewardDistributor, - chain: chain.toLowerCase(), - params: [bucketAddress, r] - }) - ) - }) - )).map(v => { - return v.output.isFinished ? 0 : v.output.rewardPerToken - }) - - const symbol = addressEq(asset.tokenAddress, USDCE) ? 'USDC.E' : asset.symbol - const underlyingTokens = [asset.tokenAddress] - - const priceKeys = underlyingTokens.map((t) => `${chain.toLowerCase()}:${t}`).join(',') + const { + bucketAddress, + asset, + supportedAssets, + supply, + demand, + bar, + lar, + estimatedBar, + estimatedLar, + miningParams, + name, + } = bucket; + const { chain, EPMX, USDCE, apyRewardBySymbol } = config; + + const symbol = addressEq(asset.tokenAddress, USDCE) ? 'USDC.E' : asset.symbol; + const underlyingTokens = [asset.tokenAddress]; + + const priceKeys = underlyingTokens + .map((t) => `${chain.toLowerCase()}:${t}`) + .join(','); const prices = ( await superagent.get(`https://coins.llama.fi/prices/current/${priceKeys}`) ).body.coins; - const assetPrice = prices[`${chain.toLowerCase()}:${asset.tokenAddress}`] - const totalSupplyUsd = (supply / 10 ** assetPrice.decimals) * assetPrice.price - const totalBorrowUsd = (demand / 10 ** assetPrice.decimals) * assetPrice.price - const tvlUsd = totalSupplyUsd - totalBorrowUsd - - const isMiningPhase = !miningParams.isBucketLaunched && miningParams.deadlineTimestamp * 1000 > Date.now() - - const apyBaseCalculated = (Math.pow(1 + (lar / 10 ** 27) / SECONDS_PER_YEAR, SECONDS_PER_YEAR) - 1) * 100 - const apyBase = isMiningPhase ? 0 : apyBaseCalculated - - const apyBaseBorrowCalculated = (Math.pow(1 + (bar / 10 ** 27) / SECONDS_PER_YEAR, SECONDS_PER_YEAR) - 1) * 100 - const apyBaseBorrow = isMiningPhase ? 0 : apyBaseBorrowCalculated - - // const apyRewardCalculated = (rewardPerTokenLender * 10 ** asset.decimals / 10 ** 18 * SECONDS_PER_YEAR * EPMXPrice / assetPrice.price / 10 ** 18) * 100; - // const apyReward = isMiningPhase ? apyRewardBySymbol[symbol] + APY_REWARD_BONUS : apyRewardCalculated - const apyReward = isMiningPhase ? APY_REWARD_BONUS : 0 - - // const apyRewardBorrowCalculated = (rewardPerTokenTrader * 10 ** asset.decimals / 10 ** 18 * SECONDS_PER_YEAR * EPMXPrice / assetPrice.price / 10 ** 18) * 100; - // const apyRewardBorrow = isMiningPhase ? 0 : apyRewardBorrowCalculated - const apyRewardBorrow = 0 + const assetPrice = prices[`${chain.toLowerCase()}:${asset.tokenAddress}`]; + const totalSupplyUsd = + (supply / 10 ** assetPrice.decimals) * assetPrice.price; + const totalBorrowUsd = + (demand / 10 ** assetPrice.decimals) * assetPrice.price; + const tvlUsd = totalSupplyUsd - totalBorrowUsd; + + const isMiningPhase = + !miningParams.isBucketLaunched && + miningParams.deadlineTimestamp * 1000 > Date.now(); + + const apyBaseCalculated = + (Math.pow(1 + lar / 10 ** 27 / SECONDS_PER_YEAR, SECONDS_PER_YEAR) - 1) * + 100; + const apyBase = isMiningPhase ? 0 : apyBaseCalculated; + + const apyBaseBorrowCalculated = + (Math.pow(1 + bar / 10 ** 27 / SECONDS_PER_YEAR, SECONDS_PER_YEAR) - 1) * + 100; + const apyBaseBorrow = isMiningPhase ? 0 : apyBaseBorrowCalculated; + const apyReward = isMiningPhase ? APY_REWARD_BONUS : 0; + const apyRewardBorrow = 0; return { pool: `${bucketAddress}-${chain}`.toLowerCase(), @@ -66,43 +77,72 @@ const formatPool = async (bucket, config, EPMXPrice) => { apyRewardBorrow, totalSupplyUsd, totalBorrowUsd, - } -} + }; +}; const getPools = async (config) => { - const { chain, lensAddress, bucketsFactory, positionManager, EPMX, EPMXPriceFeed, EPMXPriceFeedDecimals } = config; + const { + chain, + lensAddress, + bucketsFactory, + positionManager, + EPMX, + EPMXPriceFeed, + EPMXPriceFeedDecimals, + } = config; const buckets = ( await sdk.api.abi.call({ abi: abi.getAllBucketsFactory, target: lensAddress, chain: chain.toLowerCase(), - params: [bucketsFactory, DEAD_ADDRESS, positionManager, false] - })).output - - const EPMXPrice = (await sdk.api.abi.call({ - abi: abi.getChainlinkLatestRoundData, - target: lensAddress, - chain: chain.toLowerCase(), - params: [[EPMXPriceFeed]] - })).output[0].answer / 10 ** EPMXPriceFeedDecimals + params: [bucketsFactory, DEAD_ADDRESS, positionManager, false], + }) + ).output; + + const EPMXPrice = + ( + await sdk.api.abi.call({ + abi: abi.getChainlinkLatestRoundData, + target: lensAddress, + chain: chain.toLowerCase(), + params: [[EPMXPriceFeed]], + }) + ).output[0].answer / + 10 ** EPMXPriceFeedDecimals; return await Promise.all( buckets .filter(({ miningParams }) => { - const isMiningFailed = !miningParams.isBucketLaunched && miningParams.deadlineTimestamp * 1000 <= Date.now() - - return !isMiningFailed + const isMiningFailed = + !miningParams.isBucketLaunched && + miningParams.deadlineTimestamp * 1000 <= Date.now(); + + return !isMiningFailed; }) .map((b) => formatPool(b, config, EPMXPrice)) - ) -} + ); +}; + +const getApy = async (conf) => { + return (await Promise.all(conf.map((c) => getPools(c)))).flat(); +}; -const getApy = async () => { - return (await Promise.all(config.map((c) => getPools(c)))).flat() +const getApyCombined = async (config1, config2) => { + try { + const [apy1, apy2] = await Promise.all([getApy(config1), getApy(config2)]); + + return [...apy1, ...apy2]; + } catch (error) { + console.error('Error fetching APY:', error); + return []; + } }; module.exports = { timetravel: false, - apy: getApy, + apy: async () => { + const combinedApy = await getApyCombined(config, configV2); + return combinedApy; + }, }; diff --git a/src/adaptors/primex-finance/utils.js b/src/adaptors/primex-finance/utils.js index 0e7186f870..ec71cba318 100644 --- a/src/adaptors/primex-finance/utils.js +++ b/src/adaptors/primex-finance/utils.js @@ -1,14 +1,15 @@ -const DEAD_ADDRESS = '0x000000000000000000000000000000000000dEaD' +const DEAD_ADDRESS = '0x000000000000000000000000000000000000dEaD'; const SECONDS_PER_YEAR = 31536000; const ROLES = { LENDER: 0, - TRADER: 1 -} + TRADER: 1, +}; const CHAIN_IDS = { Polygon: 'polygon_mainnet', - Arbitrum: 'arbitrum_one' + Arbitrum: 'arbitrum_one', + Ethereum: 'ethereum', }; const APY_REWARD_BONUS = 7; @@ -19,63 +20,80 @@ const config = [ lensAddress: '0xCbaEc4b0683Ed6F2C2C318500962857768Fc1366', bucketsFactory: '0x7E6915D307F434E4171cCee90e180f5021c60089', positionManager: '0x02bcaA4633E466d151b34112608f60A82a4F6035', - activityRewardDistributor: '0x156e2fC8e1906507412BEeEB6640Bf999a1Ea76b', - USDCE: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", - EPMX: "0xDc6D1bd104E1efa4A1bf0BBCf6E0BD093614E31A", - EPMXPriceFeed: "0x103A9FF33c709405DF58f8f209C53f6B5c5eA2BE", + USDCE: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', + EPMX: '0xDc6D1bd104E1efa4A1bf0BBCf6E0BD093614E31A', + EPMXPriceFeed: '0x103A9FF33c709405DF58f8f209C53f6B5c5eA2BE', EPMXPriceFeedDecimals: 8, - apyRewardBySymbol: { - ['WETH']: 18, - ['WBTC']: 1, - ['USDC.E']: 31, - ['USDT']: 20, - ['WMATIC']: 21, - } }, { chain: 'Arbitrum', lensAddress: '0x3a5CAdB5eDF17876fD2518AEC3a4d804964aA89e', bucketsFactory: '0x4e6f7372bCE4083c779c17B240A94dc2EA57AE67', positionManager: '0x86890E30cE9E1e13Db5560BbEb435c55567Af1cd', - activityRewardDistributor: '0x38D94212AAe3f4aB3E4fE801d9021ab0aA371DaB', - USDCE: "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", - EPMX: "0xA533f744B179F2431f5395978e391107DC76e103", - EPMXPriceFeed: "0x053FB5b7c555FC0d9Bc49118023d6B6A4019168f", + USDCE: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', + EPMX: '0xA533f744B179F2431f5395978e391107DC76e103', + EPMXPriceFeed: '0x053FB5b7c555FC0d9Bc49118023d6B6A4019168f', EPMXPriceFeedDecimals: 8, - apyRewardBySymbol: { - ['WETH']: 23.5, - ['WBTC']: 1.25, - ['USDC']: 39.5, - ['USDT']: 41, - ['ARB']: 1, - ['USDC.E']: 39.5, - } }, { chain: 'Ethereum', lensAddress: '0xBF7259d41af428642140C88a10db6921a383FCC1', bucketsFactory: '0x7dE8607157124c894Ba9F18dd6138B5E8AAd5890', positionManager: '0x99d63fEA4b3Ef6ca77941df3C5740dAd1586f0B8', - activityRewardDistributor: '0xA622b8DfC3B5Ec283CEefd37768F5B3b3E316730', - EPMX: "0xA533f744B179F2431f5395978e391107DC76e103", - EPMXPriceFeed: "0xF146a76F3Aa82D4cEa3eaB44932b7eE75737E11a", + EPMX: '0xA533f744B179F2431f5395978e391107DC76e103', + EPMXPriceFeed: '0xF146a76F3Aa82D4cEa3eaB44932b7eE75737E11a', EPMXPriceFeedDecimals: 8, - apyRewardBySymbol: { - ['WETH']: 24, - ['WBTC']: 2.4, - ['USDC']: 44.4, - ['USDT']: 43.2, - ['MATIC']: 21.6, - ['DAI']: 39.6, - } }, -] +]; -const getPoolUrl = (address, chain) => `https://app.primex.finance/#/bucket-details/${address}?network=${CHAIN_IDS[chain]}`; +const configV2 = [ + { + chain: 'Polygon', + lensAddress: '0xe84C7913dec4f1191F0b7ef7fb54c3E60DA2DF0B', + bucketsFactory: '0x9649CfDCfAa9c80907e63dD9Cb161cBA2033F3A0', + positionManager: '0x02bcaA4633E466d151b34112608f60A82a4F6035', + USDCE: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', + EPMX: '0xDc6D1bd104E1efa4A1bf0BBCf6E0BD093614E31A', + EPMXPriceFeed: '0x103A9FF33c709405DF58f8f209C53f6B5c5eA2BE', + EPMXPriceFeedDecimals: 8, + }, + { + chain: 'Arbitrum', + lensAddress: '0x9b3bdb43E43422d789FE4977d63Af76C3159F6C6', + bucketsFactory: '0xB4d3A9f10D3D687FaF3b05b9aa3054856A1d7be8', + positionManager: '0x86890E30cE9E1e13Db5560BbEb435c55567Af1cd', + USDCE: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', + EPMX: '0xA533f744B179F2431f5395978e391107DC76e103', + EPMXPriceFeed: '0x053FB5b7c555FC0d9Bc49118023d6B6A4019168f', + EPMXPriceFeedDecimals: 8, + }, + { + chain: 'Ethereum', + lensAddress: '0xa1690975FBd39dfCdCEf14726cF87662746E91d3', + bucketsFactory: '0x55120da310A0c5fd81Fd3bb8C177F6649bE30ACc', + positionManager: '0x99d63fEA4b3Ef6ca77941df3C5740dAd1586f0B8', + EPMX: '0xA533f744B179F2431f5395978e391107DC76e103', + EPMXPriceFeed: '0xF146a76F3Aa82D4cEa3eaB44932b7eE75737E11a', + EPMXPriceFeedDecimals: 8, + }, +]; + +const getPoolUrl = (address, chain) => + `https://app.primex.finance/#/bucket-details/${address}?network=${CHAIN_IDS[chain]}`; const addressEq = (addressA, addressB) => { if (!addressA || !addressB) return false; return addressA.toLowerCase() === addressB.toLowerCase(); -} +}; -module.exports = { DEAD_ADDRESS, SECONDS_PER_YEAR, ROLES, CHAIN_IDS, APY_REWARD_BONUS, config, getPoolUrl, addressEq } \ No newline at end of file +module.exports = { + DEAD_ADDRESS, + SECONDS_PER_YEAR, + ROLES, + CHAIN_IDS, + APY_REWARD_BONUS, + config, + configV2, + getPoolUrl, + addressEq, +};