-
Notifications
You must be signed in to change notification settings - Fork 833
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add factor-v2 * fix mux * add glp, mux, vela * boilerplate(factor-v2): add strategy adapter * chore(factor-v2): separate utils * fix(factor-v2): circular import of utils * feat(factor-v2): glp strategy adapter * feat(factor-v2): lodestar strategy-adapter * feat(factor-v2): mux strategy-adapter * feat(factor-v2): vela strategy-adapter:wq * feat(factor-v2): add sjoe strategy-adapter * fix(factor-v2): sjoe apr * 100 * feat(factor-v2): silo strategy-adapter * chore(factor-v2): refactor * feat(factor-v2): add pendle strategy-adapter * feat(factor-v2): add penpie strategy-adapter * feat(factor-v2): add olive strategy-adapter * feat(factor-v2): add redacted strategy-adapter * feat(factor-v2): add tender strategy-adapter * chore(factor-v2): disable redacted * feat(factor-v2): add getDefiLLamaPools * feat(factor-v2): glp adapter use defillama api * feat(factor-v2): add pendle adapter * feat(factor-v2): add tender adapter * feat(factor-v2): add olive adapter * feat(factor-v2): add vela adapter
- Loading branch information
Showing
16 changed files
with
726 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
const vaults = require('./vaults'); | ||
const { getTvl, getApr } = require('./shared'); | ||
|
||
async function getSingleYieldVaultAPY() { | ||
const poolData = await Promise.all( | ||
vaults.map(async (vault) => { | ||
const project = 'factor-v2'; | ||
const chain = 'arbitrum'; | ||
const pool = `${vault.poolAddress}-${chain}`.toLowerCase(); | ||
const url = `https://app.factor.fi/vault/${vault.poolAddress}`; | ||
const symbol = vault.symbol; | ||
|
||
const [tvlUsd, apyBase] = await Promise.all([ | ||
getTvl(vault.poolAddress, vault.underlyingToken, vault.strategy), | ||
getApr(vault.poolAddress, vault.underlyingToken, vault.strategy), | ||
]); | ||
|
||
const data = { | ||
pool, | ||
chain, | ||
project, | ||
symbol, | ||
tvlUsd, | ||
apyBase, | ||
underlyingTokens: [vault.underlyingToken], | ||
url, | ||
}; | ||
|
||
return data; | ||
}) | ||
); | ||
|
||
return poolData; | ||
} | ||
|
||
module.exports = { | ||
timetravel: false, | ||
apy: getSingleYieldVaultAPY, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
const sdk = require('@defillama/sdk3'); | ||
const utils = require('../utils'); | ||
|
||
const { | ||
getMuxLpApr, | ||
getGlpApr, | ||
getVlpApr, | ||
getLodestarApr, | ||
getLodestarTokenPriceInUSD, | ||
getPendleApr, | ||
getSJoeApr, | ||
getSiloApr, | ||
getTenderApr, | ||
getOliveApr, | ||
getPxGMXApr, | ||
getPenpieApr | ||
} = require('./strategy-adapter'); | ||
const { getCoinDataFromDefillamaAPI } = require('./strategy-adapter/utils'); | ||
|
||
async function getApr(poolAddress, underlyingTokenAddress, strategy) { | ||
let apr = 0; | ||
switch (strategy) { | ||
case 'GLPStrategy': | ||
apr = await getGlpApr(); | ||
break; | ||
case 'MuxStrategy': | ||
apr = await getMuxLpApr(); | ||
break; | ||
case 'VelaStrategy': | ||
apr = await getVlpApr(); | ||
break; | ||
case 'LodestarStrategy': | ||
apr = await getLodestarApr(underlyingTokenAddress); | ||
break; | ||
case 'PenpieStrategy': | ||
apr = await getPenpieApr(underlyingTokenAddress); | ||
break; | ||
case 'PendleStrategy': | ||
apr = await getPendleApr(underlyingTokenAddress); | ||
break; | ||
case 'TraderJoeStrategy': | ||
apr = await getSJoeApr(underlyingTokenAddress); | ||
break; | ||
case 'SiloStrategy': | ||
apr = await getSiloApr(underlyingTokenAddress); | ||
break; | ||
case 'TenderStrategy': | ||
apr = await getTenderApr(underlyingTokenAddress); | ||
break; | ||
case 'OliveStrategy': | ||
apr = await getOliveApr(); | ||
break; | ||
case 'RedactedStrategy': | ||
apr = await getPxGMXApr(); | ||
break; | ||
default: | ||
apr = 0; | ||
} | ||
|
||
const harvestCountPerDay = 3; | ||
const apyBase = utils.aprToApy(apr, harvestCountPerDay * 365); | ||
|
||
return apyBase; | ||
} | ||
|
||
async function getTvl(poolAddress, underlyingTokenAddress, strategy) { | ||
let underlyingTokenPrice = 0; | ||
|
||
if (strategy == 'LodestarStrategy') { | ||
underlyingTokenPrice = await getLodestarTokenPriceInUSD( | ||
underlyingTokenAddress | ||
); | ||
} else if (strategy == "RedactedStrategy") { | ||
const gmxCoin = await getCoinDataFromDefillamaAPI('arbitrum','0xfc5a1a6eb076a2c7ad06ed22c90d7e710e35ad0a') | ||
underlyingTokenPrice = gmxCoin.price; | ||
} else { | ||
underlyingTokenPrice = ( | ||
await utils.getPrices([underlyingTokenAddress], 'arbitrum') | ||
).pricesByAddress[underlyingTokenAddress.toLowerCase()]; | ||
} | ||
|
||
const [{ output: assetBalance }, { output: assetDecimals }] = | ||
await Promise.all([ | ||
sdk.api.abi.call({ | ||
target: poolAddress, | ||
abi: 'uint256:assetBalance', | ||
chain: 'arbitrum', | ||
}), | ||
sdk.api.abi.call({ | ||
target: underlyingTokenAddress, | ||
abi: 'erc20:decimals', | ||
chain: 'arbitrum', | ||
}), | ||
]); | ||
|
||
const tvlUsd = (assetBalance / 10 ** assetDecimals) * underlyingTokenPrice; | ||
|
||
return tvlUsd; | ||
} | ||
|
||
module.exports = { getTvl, getApr }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
const { getDefiLLamaPools } = require('./utils'); | ||
|
||
/*////////////////////////////////////////////////////////////////////////////// | ||
GLP APR | ||
//////////////////////////////////////////////////////////////////////////////*/ | ||
|
||
async function getGlpApr() { | ||
const pool = await getDefiLLamaPools( | ||
'825688c0-c694-4a6b-8497-177e425b7348' | ||
); | ||
const apr = pool.apyBase + pool.apyReward; | ||
|
||
return apr; | ||
} | ||
|
||
module.exports = { getGlpApr }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
module.exports = { | ||
...require('./lodestar-adapter'), | ||
...require('./mux-adapter'), | ||
...require('./glp-adapter'), | ||
...require('./vela-adapter'), | ||
...require('./pendle-adapter'), | ||
...require('./sjoe-adapter'), | ||
...require('./silo-adapter'), | ||
...require('./tender-adapter'), | ||
...require('./olive-adapter'), | ||
...require('./redacted-adapter'), | ||
...require('./penpie-adapter'), | ||
}; |
59 changes: 59 additions & 0 deletions
59
src/adaptors/factor-v2/strategy-adapter/lodestar-adapter.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
const sdk = require('@defillama/sdk3'); | ||
const utils = require('../../utils'); | ||
const { makeReadable } = require('./utils'); | ||
|
||
async function getSupplyRatePerBlock(assetAddress) { | ||
const { output } = await sdk.api.abi.call({ | ||
target: assetAddress, | ||
abi: 'uint256:supplyRatePerBlock', | ||
chain: 'arbitrum', | ||
}); | ||
return { | ||
supplyRatePerBlock: makeReadable(output), | ||
}; | ||
} | ||
|
||
async function getLodestarApr(assetAddress) { | ||
const { supplyRatePerBlock } = await getSupplyRatePerBlock(assetAddress); | ||
const blocksPerYear = 7200 * 365; | ||
const apr = (1 + supplyRatePerBlock) ** blocksPerYear - 1; | ||
return apr * 100; | ||
} | ||
|
||
async function getExchangeRateStored(assetAddress) { | ||
const { output } = await sdk.api.abi.call({ | ||
target: assetAddress, | ||
abi: 'uint256:exchangeRateStored', | ||
chain: 'arbitrum', | ||
}); | ||
return { | ||
exchangeRateStored: makeReadable(output, 16), | ||
}; | ||
} | ||
|
||
async function getLodestarUnderlyingTokenPriceInUSD(lToken) { | ||
const { output: underlyingTokenAddress } = await sdk.api.abi.call({ | ||
target: lToken, | ||
abi: 'address:underlying', | ||
chain: 'arbitrum', | ||
}); | ||
const underlyingLodestarTokenPriceInUSD = ( | ||
await utils.getPrices([underlyingTokenAddress], 'arbitrum') | ||
).pricesByAddress[underlyingTokenAddress.toLowerCase()]; | ||
|
||
return { underlyingLodestarTokenPriceInUSD }; | ||
} | ||
|
||
async function getLodestarTokenPriceInUSD(lToken) { | ||
const [{ exchangeRateStored }, { underlyingLodestarTokenPriceInUSD }] = | ||
await Promise.all([ | ||
getExchangeRateStored(lToken), | ||
getLodestarUnderlyingTokenPriceInUSD(lToken), | ||
]); | ||
|
||
const lTokenPriceInUSD = | ||
underlyingLodestarTokenPriceInUSD * exchangeRateStored; | ||
return lTokenPriceInUSD; | ||
} | ||
|
||
module.exports = { getLodestarApr, getLodestarTokenPriceInUSD }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
const sdk = require('@defillama/sdk3'); | ||
const utils = require('../../utils'); | ||
const { makeReadable } = require('./utils'); | ||
|
||
/*////////////////////////////////////////////////////////////////////////////// | ||
Mux Reward Router | ||
//////////////////////////////////////////////////////////////////////////////*/ | ||
|
||
async function getDataFromRewardRouter() { | ||
const REWARD_ROUTER_ADDRESS = '0xaf9C4F6A0ceB02d4217Ff73f3C95BbC8c7320ceE'; | ||
|
||
const rewardRouterABIs = [ | ||
'uint256:feeRewardRate', | ||
'uint256:muxRewardRate', | ||
'uint256:poolOwnedRate', | ||
'uint256:votingEscrowedRate', | ||
]; | ||
|
||
const [feeRewardRate, muxRewardRate, poolOwnedRate, votingEscrowedRate] = | ||
await Promise.all( | ||
rewardRouterABIs.map(async (abi) => { | ||
const { output } = await sdk.api.abi.call({ | ||
target: REWARD_ROUTER_ADDRESS, | ||
abi: abi, | ||
chain: 'arbitrum', | ||
}); | ||
return output; | ||
}) | ||
); | ||
return { | ||
feeRewardRate: makeReadable(feeRewardRate), | ||
muxRewardRate: makeReadable(muxRewardRate), | ||
poolOwnedRate: makeReadable(poolOwnedRate), | ||
votingEscrowedRate: makeReadable(votingEscrowedRate), | ||
}; | ||
} | ||
|
||
/*////////////////////////////////////////////////////////////////////////////// | ||
Mux Pool Owned Liquidity | ||
//////////////////////////////////////////////////////////////////////////////*/ | ||
|
||
async function getDataFromPOL() { | ||
const MLP_ADDRESS = '0x7CbaF5a14D953fF896E5B3312031515c858737C8'; | ||
const POL_ADDRESS = '0x18891480b9dd2aC5eF03220C45713d780b5CFdeF'; | ||
|
||
const { output: mlpPolBalance } = await sdk.api.abi.call({ | ||
target: MLP_ADDRESS, | ||
abi: 'erc20:balanceOf', | ||
params: [POL_ADDRESS], | ||
chain: 'arbitrum', | ||
}); | ||
|
||
return { | ||
mlpPolBalance: makeReadable(mlpPolBalance), | ||
}; | ||
} | ||
|
||
/*////////////////////////////////////////////////////////////////////////////// | ||
Token Prices | ||
//////////////////////////////////////////////////////////////////////////////*/ | ||
|
||
async function getTokenPrices() { | ||
const tokenAddresses = [ | ||
'0x7CbaF5a14D953fF896E5B3312031515c858737C8', // MuxLP | ||
'0x4e352cf164e64adcbad318c3a1e222e9eba4ce42', // MCB | ||
'0x82af49447d8a07e3bd95bd0d56f35241523fbab1', // WETH | ||
]; | ||
|
||
const tokenPrices = await utils.getPrices(tokenAddresses, 'arbitrum'); | ||
|
||
const mlpPrice = tokenPrices.pricesByAddress[tokenAddresses[0].toLowerCase()]; | ||
const mcbPrice = tokenPrices.pricesByAddress[tokenAddresses[1].toLowerCase()]; | ||
const ethPrice = tokenPrices.pricesByAddress[tokenAddresses[2].toLowerCase()]; | ||
|
||
return { mlpPrice, mcbPrice, ethPrice }; | ||
} | ||
|
||
/*////////////////////////////////////////////////////////////////////////////// | ||
Mux LP APR | ||
//////////////////////////////////////////////////////////////////////////////*/ | ||
|
||
async function getMuxLpApr() { | ||
const [ | ||
{ mlpPolBalance }, | ||
{ feeRewardRate, muxRewardRate, poolOwnedRate, votingEscrowedRate }, | ||
{ mlpPrice, mcbPrice, ethPrice }, | ||
] = await Promise.all([ | ||
getDataFromPOL(), | ||
getDataFromRewardRouter(), | ||
getTokenPrices(), | ||
]); | ||
|
||
const mlpCirculatingSupply = mlpPolBalance / poolOwnedRate; | ||
|
||
const muxAPR = | ||
(muxRewardRate * mcbPrice * 86400 * 365 * (1 - votingEscrowedRate)) / | ||
(mlpCirculatingSupply * mlpPrice); | ||
|
||
const ethAPR = | ||
(feeRewardRate * ethPrice * 86400 * 365 * 0.7) / | ||
(mlpCirculatingSupply * mlpPrice); | ||
|
||
const totalAPR = (muxAPR + ethAPR) * 100; | ||
|
||
return totalAPR; | ||
} | ||
|
||
module.exports = { getMuxLpApr }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
const { getDefiLLamaPools } = require('./utils'); | ||
|
||
async function getOliveApr() { | ||
const pool = await getDefiLLamaPools( | ||
'79587734-a461-4f4c-b9e2-c85c70484cf8' | ||
); | ||
|
||
const beefyApr = | ||
pool.apyBase + (isNaN(pool.apyReward) ? 0 : pool.apyReward); | ||
|
||
const ampFactor = 1.33; | ||
const weeksPerYear = 365 / 7; | ||
const oliveBoost = 0.05; | ||
const apr = | ||
(1 + (beefyApr * ampFactor) / weeksPerYear) ** weeksPerYear - | ||
1 + | ||
oliveBoost; | ||
|
||
return apr * 100; | ||
} | ||
|
||
module.exports = { getOliveApr }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
const { getDefiLLamaPools } = require('./utils'); | ||
|
||
async function getPendleApr(poolAddress) { | ||
const poolAddressToIdMap = { | ||
// wstETH | ||
'0x08a152834de126d2ef83d612ff36e4523fd0017f': | ||
'f05aa688-f627-4438-89c6-2fef135510c7', | ||
|
||
// rETH | ||
'0x14fbc760efaf36781cb0eb3cb255ad976117b9bd': | ||
'35fe5f76-3b7d-42c8-9e54-3da70fbcb3a9', | ||
}; | ||
|
||
const pool = await getDefiLLamaPools( | ||
poolAddressToIdMap[poolAddress.toLowerCase()] | ||
); | ||
|
||
const apr = pool.apyBase + pool.apyReward; | ||
|
||
return apr; | ||
} | ||
|
||
module.exports = { getPendleApr }; |
Oops, something went wrong.