Skip to content
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

Merged
merged 48 commits into from
Sep 6, 2023

Conversation

lgahdl
Copy link
Contributor

@lgahdl lgahdl commented Jul 3, 2023

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.

@lgahdl lgahdl requested a review from gmbronco July 3, 2023 13:04
@lgahdl lgahdl self-assigned this Jul 3, 2023
@lgahdl lgahdl marked this pull request as draft July 3, 2023 13:04
@gmbronco
Copy link
Contributor

gmbronco commented Jul 6, 2023

What are "Non Reaper Boosted pools"?

@lgahdl
Copy link
Contributor Author

lgahdl commented Jul 6, 2023

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',
Copy link
Contributor

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

Comment on lines 44 to 50
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;
}
Copy link
Contributor

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?

@lgahdl lgahdl changed the title APR Services - Non Reaper Boosted pools APR Services - Add some yield tokens APR to linear pools Jul 8, 2023
@lgahdl lgahdl requested a review from franzns July 8, 2023 02:08
Luiz Gustavo Abou Hatem De Liz added 3 commits July 7, 2023 23:15
import { tokens } from "./tokens";
import { TokenApr } from "./types";

export const fetchAllAprs = async (): Promise<TokenApr[]> => {
Copy link
Contributor

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)
Copy link
Contributor

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?

Copy link
Contributor Author

@lgahdl lgahdl Jul 21, 2023

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(
Copy link
Contributor

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% */,
Copy link
Contributor

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 %

@franzns
Copy link
Contributor

franzns commented Jul 21, 2023

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.
I would even redesign the whole thing, introducing interfaces for the APR sources, similar to what we did for the other APR services.
In addition, that thing should live in the pools module with the other APR code and not in the token module.

Comment on lines 11 to 26
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();
}
}
Copy link
Contributor

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

Comment on lines 25 to 50
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,
]
Copy link
Contributor

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;
Copy link
Contributor

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?

Luiz Gustavo Abou Hatem De Liz added 3 commits August 1, 2023 19:25
Luiz Gustavo Abou Hatem De Liz added 8 commits August 29, 2023 00:00
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;
@franzns franzns marked this pull request as ready for review August 30, 2023 11:11
@franzns franzns self-requested a review August 30, 2023 11:11
Copy link
Contributor

@franzns franzns left a 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.

modules/pool/lib/apr-data-sources/ib-tokens-apr.service.ts Outdated Show resolved Hide resolved
modules/pool/lib/apr-data-sources/ib-tokens-apr.service.ts Outdated Show resolved Hide resolved
Comment on lines 92 to 98
let tokenApr = parseFloat(apr) / APR_PERCENT_DIVISOR;
if (token.isSftmX) {
tokenApr = tokenApr * (1 + sFTMxBaseApr);
}
if (token.isWstETH) {
tokenApr = tokenApr * (1 + this.wstETHBaseApr);
}
Copy link
Contributor

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';
Copy link
Contributor

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';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove file

Comment on lines 1 to 2
import { Dictionary } from 'lodash'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still there :)

@timjrobinson
Copy link
Contributor

timjrobinson commented Sep 5, 2023

I've been testing this out with balancer/frontend-v2#4068 running it all locally, and found a few issues:

  • All pools are missing BAL rewards

Base

  • USDbC rewards on cbETH/WETH (0xfb4c2e6e6e27b5b4a07a36360c89ede29bb3c9b6000000000000000000000026) and USDbC/axlUSDC (0xe58ca65f418d4121d6c70d4c133e60cf6fda363c000000000000000000000013) pools on base are way too low (like orders of magnitude lower than expected, seems like a scaling issue maybe because the reward token has 6 decimals rather than 18)
  • Pool liquidity values are incorrect (different to prod)
  • GOLD rewards APR are much lower than prod (40% vs 60%)
  • There's no APR on 0x18f150c43598cd822d39711c55bd90407a8b8ad700020000000000000000003b when in prod it has 12% APR - rewards from the subpool 0x2db50a0e0310723ef0c2a165cb9a9f80d772ba2f00020000000000000000000d

Ethereum

  • 0x1e19cf2d73a72ef1332c882f20534b6519be0276000200000000000000000112 is missing rETH APR while 0x42ed016f826165c2e5976fe5bc3df540c5ad0af700000000000000000000058b has the token APR's including rETH

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.

@franzns
Copy link
Contributor

franzns commented Sep 5, 2023

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.

@lgahdl
Copy link
Contributor Author

lgahdl commented Sep 5, 2023

  • 0x1e19cf2d73a72ef1332c882f20534b6519be0276000200000000000000000112
    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 is not getting the rETH APR, thanks for seeing that.
    I'm not sure if the source we're using for the stafi rETH could be used for the rETH, but I can add it

@lgahdl
Copy link
Contributor Author

lgahdl commented Sep 5, 2023

I've been testing this out with balancer/frontend-v2#4068 running it all locally, and found a few issues:

  • All pools are missing BAL rewards

Base

  • USDbC rewards on cbETH/WETH (0xfb4c2e6e6e27b5b4a07a36360c89ede29bb3c9b6000000000000000000000026) and USDbC/axlUSDC (0xe58ca65f418d4121d6c70d4c133e60cf6fda363c000000000000000000000013) pools on base are way too low (like orders of magnitude lower than expected, seems like a scaling issue maybe because the reward token has 6 decimals rather than 18)
  • Pool liquidity values are incorrect (different to prod)
  • GOLD rewards APR are much lower than prod (40% vs 60%)
  • There's no APR on 0x18f150c43598cd822d39711c55bd90407a8b8ad700020000000000000000003b when in prod it has 12% APR - rewards from the subpool 0x2db50a0e0310723ef0c2a165cb9a9f80d772ba2f00020000000000000000000d

Ethereum

  • 0x1e19cf2d73a72ef1332c882f20534b6519be0276000200000000000000000112 is missing rETH APR while 0x42ed016f826165c2e5976fe5bc3df540c5ad0af700000000000000000000058b has the token APR's including rETH

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.

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.
I'm not sure if the source we're using for the stafi rETH could be used for the rETH, but I can add it
Note.: The rETH APR of the pool 0x42ed016f826165c2e5976fe5bc3df540c5ad0af700000000000000000000058b is probably not from this service

@franzns franzns merged commit 4b000ae into v3-canary Sep 6, 2023
@franzns franzns deleted the non-reaper-yield-tokens-apr branch September 6, 2023 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants