-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
APR Services - Add some yield tokens APR to linear pools #396
Conversation
What are "Non Reaper Boosted pools"? |
I thought it would be necessary to update boosted pools in the same APR Service that updates the linear pools with "non reaper tokens" yield (Which John called Non Reaper Boosted Pools, because there's another service that updates the APR for pools with wrapped tokens from Reaper Crypt) but there's already a service that updates all boosted pools, so it's not necessary to update the "Non Reaper Boosted Pools", because they're already being updated by the "boosted-pool.apr.service" |
… instead of use the yield-tokens cloudflare service; Removed the boosted pools apr, and let only the yield tokens APR update, boosted pools are updated in another service;
title: `${ token.token.symbol || token.address } APR`, | ||
apr: aprs.get(token.address) ?? 0, | ||
group: null, | ||
type: 'IB_YIELD', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be different, based on the pool. If it's a wrapped asset from a linear pool, it needs to be LINEAR_BOOSTED
, else IB_YIELD
private async fetchYieldTokensApr(): Promise<Map<string, number>> { | ||
const res = await axios.get("https://yield-tokens.balancer.workers.dev/"); | ||
const aprs = new Map<string, number>(Object.entries(res.data as { | ||
[key: string]: number | ||
}).map(([key, apr]) => [key, apr * 0.0001])); | ||
return aprs; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume this will change to be sourced locally from the sources you added?
…er-yield-tokens-apr Grouping APRs by source;
import { tokens } from "./tokens"; | ||
import { TokenApr } from "./types"; | ||
|
||
export const fetchAllAprs = async (): Promise<TokenApr[]> => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please create a proper function for this
|
||
|
||
const jsonRpcProvider = new JsonRpcProvider('https://arb1.arbitrum.io/rpc', 42161 /*ARBITRUM*/) | ||
const provider = MulticallWrapper.wrap(jsonRpcProvider) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this multicall wrapper needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used it so calls performed simultaneously can be automatically batched. Like in this case:
const getAprs = () => {
const calls = Object.keys(strategiesMap).map(async (coin) => {
const contract = new Contract(strategiesMap[coin], abi, provider)
return contract.averageAPRAcrossLastNHarvests(3)
})
return Promise.all(calls)
}
on viem, it was this:
const getAprs = () => {
const contracts = Object.keys(strategiesMap).map((coin) => ({
address: strategiesMap[coin],
abi,
functionName: 'averageAPRAcrossLastNHarvests',
args: [3],
}))
return client.multicall({ contracts })
}
import { TokenApr } from "./types"; | ||
|
||
export const fetchAllAprs = async (): Promise<TokenApr[]> => { | ||
const res = await Promise.all( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any of these fetches can fail for various reasons. I'd rather do that sequential (no need to optimize in the cron) and log proper errors to sentry
tokens.map(async ({ name, group, fetchFn }) => { | ||
const fetchedResponse: {[key:string]:number} = await fetchFn() | ||
return Object.entries(fetchedResponse).map(([address, aprValue]) => ({ | ||
val: aprValue * 0.0001 /*Values come in BPS 10000=>100% */, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe the apr services should already provide values in %
Looked through the thing now. We will need to redesign it a bit and make it multichain aware. Currently, some APR sources are multichain aware and others arent. |
getHandlersAprs = async (): Promise<TokenApr[]> => { | ||
const aprPromises = this.handlers.map(async (handler) => { | ||
const fetchedResponse: { [key: string]: number } = await handler.getAprs() | ||
return Object.entries(fetchedResponse).map(([address, aprValue]) => ({ | ||
val: aprValue, | ||
group: handler.group, | ||
address | ||
})) | ||
}); | ||
const res = Array(this.handlers.length) | ||
for (const [index, aprPromise] of aprPromises.entries()) { | ||
res[index] = await aprPromise | ||
} | ||
return res.flat(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make this a proper function of this class
export const aprHandlers: AprHandler[] = [ | ||
aaveV2MainnetAprHandler, | ||
aaveV2PolygonAprHandler, | ||
aaveV3MainnetAprHandler, | ||
aaveV3PolygonAprHandler, | ||
aaveV3ArbitrumAprHandler, | ||
ankrEthMainnetAprHandler, | ||
stMaticAprHandler, | ||
cbEthAprHandler, | ||
sfrxEthAprHandler, | ||
rETHAprHandler, | ||
USDRAprHandler, | ||
MATICXAprHandler, | ||
wbETHAprHandler, | ||
swETHAprHandler, | ||
wjAURAAprHandler, | ||
eulerMainnetAprHandler, | ||
gearboxMainnetAprHandler, | ||
idleMainnetAprHandler, | ||
overnightMainnetAprHandler, | ||
ovixZkEVMAprHandler, | ||
reaperArbitrumAprHandler, | ||
tesseraApePoolAprHandler, | ||
tetuAprHandler, | ||
tranchessMainnetAprHandler, | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these better be initialized in the ib-yield-apr-handlers.ts instead of an additional file?
} | ||
|
||
export interface AprHandler { | ||
readonly group: string | undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this ever be undefined?
Changing arrow functions to normal functions;
…er-yield-tokens-apr # Conflicts: # yarn.lock
Adding fixed apr tokens; Removing logs
# Conflicts: # modules/network/arbitrum.ts # modules/network/avalanche.ts # modules/network/fantom.ts # modules/network/gnosis.ts # modules/network/mainnet.ts # modules/network/network-config-types.ts # modules/network/optimism.ts # modules/network/polygon.ts # modules/network/zkevm.ts # modules/pool/lib/apr-data-sources/fantom/yearn-vault-apr.service.ts # modules/pool/lib/apr-data-sources/reaper-crypt-apr.service.ts
…oo, because idk what to do with the spooky apr service yet;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, still a few things. Also, I think Optimism is missing reaper single strat configs (maybe also fantom).
Also, there are two reaper apr handlers, I believe only one is needed.
let tokenApr = parseFloat(apr) / APR_PERCENT_DIVISOR; | ||
if (token.isSftmX) { | ||
tokenApr = tokenApr * (1 + sFTMxBaseApr); | ||
} | ||
if (token.isWstETH) { | ||
tokenApr = tokenApr * (1 + this.wstETHBaseApr); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a possibility to make this more general? Like if any of the IB-token-apr handlers for linear pools have an IB token, this needs to apply.
@@ -1,181 +0,0 @@ | |||
import { isSameAddress } from '@balancer-labs/sdk'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove alltogether
@@ -1,59 +0,0 @@ | |||
import { PoolAprService } from '../../../pool-types'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove file
import { Dictionary } from 'lodash' | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still there :)
Fixing default apr handler error; testing on all networks;
I've been testing this out with balancer/frontend-v2#4068 running it all locally, and found a few issues:
Base
Ethereum
For some things (like missing BAL rewards) I'm thinking maybe I haven't run the right jobs to get the data needed? It would be good to get this merged to canary or hosted somewhere where it can continually update with the latest data and anyone compare current Balancer prod with pulling pools from the beets API and report any differences. |
Thanks for testing further! We are in the final phase to test everything locally. Next phase is to merge to canary and have it running there to investigate differences between prod and canary, like you already did. The missing/wrong BAL rewards is something we already noticed and @gmbronco is looking into that separately. |
|
This rETH token included in the APR's is the stafi rETH (0x9559aaa82d9649c7a7b220e7c461d2e74c9a3593), not the rETH you're referring to (0xae78736cd615f374d3085123a210448e74fc6393), that's why this pool(0x1e19cf2d73a72ef1332c882f20534b6519be0276000200000000000000000112) is not getting the rETH APR, thanks for seeing that. |
Adding APR Service to fetch token yields APR on https://yield-tokens.balancer.workers.dev/ and calculate the APR for boosted pools with nested pools that contain the fetched tokens.