Skip to content

Commit

Permalink
Revert "YB tokens refactor, new Maker on Gnosis source (#480)"
Browse files Browse the repository at this point in the history
This reverts commit 25f070e.
  • Loading branch information
gmbronco authored Oct 18, 2023
1 parent 0b0b7ff commit 5ed75f6
Show file tree
Hide file tree
Showing 19 changed files with 179 additions and 228 deletions.
Original file line number Diff line number Diff line change
@@ -1,113 +1,169 @@
import * as sources from './sources';
import { AaveAprHandler } from './sources/aave-apr-handler';
import { AnkrAprHandler } from './sources/ankr-apr-handler';
import { DefaultAprHandler } from './sources/default-apr-handler';
import { EulerAprHandler } from './sources/euler-apr-handler';
import { GearboxAprHandler } from './sources/gearbox-apr-handler';
import { IdleAprHandler } from './sources/idle-apr-handler';
import { OvixAprHandler } from './sources/ovix-apr-handler';
import { TesseraAprHandler } from './sources/tessera-apr-handler';
import { TetuAprHandler } from './sources/tetu-apr-handler';
import { TranchessAprHandler } from './sources/tranchess-apr-handler';
import { YearnAprHandler } from './sources/yearn-apr-handler';
import { ReaperCryptAprHandler } from './sources/reaper-crypt-apr-handler';
import { BeefyAprHandler } from './sources/beefy-apr-handler';
import { IbAprConfig } from '../../../../network/apr-config-types';
import { Chain } from '@prisma/client';

const sourceToHandler = {
aave: sources.AaveAprHandler,
ankr: sources.AnkrAprHandler,
beefy: sources.BeefyAprHandler,
bloom: sources.BloomAprHandler,
euler: sources.EulerAprHandler,
gearbox: sources.GearboxAprHandler,
idle: sources.IdleAprHandler,
maker: sources.MakerAprHandler,
ovix: sources.OvixAprHandler,
reaper: sources.ReaperCryptAprHandler,
tessera: sources.TesseraAprHandler,
tetu: sources.TetuAprHandler,
tranchess: sources.TranchessAprHandler,
yearn: sources.YearnAprHandler,
defaultHandlers: sources.DefaultAprHandler,
}
import { MakerAprHandler } from './sources/maker-apr-handler';
import { BloomAprHandler } from './sources/bloom-apr-handler';

export class IbLinearAprHandlers {
private handlers: AprHandler[] = [];
fixedAprTokens?: { [tokenName: string]: { address: string; apr: number; group?: string; isIbYield?: boolean } };

constructor(aprConfig: IbAprConfig, private chain?: Chain) {
const { fixedAprHandler, ...config } = aprConfig;
this.handlers = this.buildAprHandlers(config);
this.fixedAprTokens = fixedAprHandler;
constructor(aprConfig: IbAprConfig) {
this.handlers = this.buildAprHandlers(aprConfig);
this.fixedAprTokens = aprConfig.fixedAprHandler;
}

private buildAprHandlers(aprConfig: IbAprConfig) {
buildAprHandlers(aprConfig: IbAprConfig) {
const handlers: AprHandler[] = [];

// Add handlers from global configuration
for (const [source, config] of Object.entries(aprConfig)) {
const Handler = sourceToHandler[source as keyof typeof sourceToHandler];

// Handle nested configs
if (source === 'aave' || source === 'defaultHandlers') {
for (const nestedConfig of Object.values(config)) {
handlers.push(new Handler(nestedConfig as any));
}
} else {
handlers.push(new Handler(config));
if (aprConfig.aave) {
for (const config of Object.values(aprConfig.aave)) {
const aaveHandler = new AaveAprHandler(config);
handlers.push(aaveHandler);
}
}
if (aprConfig.ankr) {
const ankrHandler = new AnkrAprHandler(aprConfig.ankr);
handlers.push(ankrHandler);
}
if (aprConfig.beefy) {
const beefyHandler = new BeefyAprHandler(aprConfig.beefy);
handlers.push(beefyHandler);
}
if (aprConfig.bloom) {
const bloomAprHandler = new BloomAprHandler(aprConfig.bloom);
handlers.push(bloomAprHandler);
}
if (aprConfig.euler) {
const eulerHandler = new EulerAprHandler(aprConfig.euler);
handlers.push(eulerHandler);
}
if (aprConfig.gearbox) {
const gearboxHandler = new GearboxAprHandler(aprConfig.gearbox);
handlers.push(gearboxHandler);
}
if (aprConfig.idle) {
const idleHandler = new IdleAprHandler(aprConfig.idle);
handlers.push(idleHandler);
}
if (aprConfig.maker) {
const makerHandler = new MakerAprHandler(aprConfig.maker);
handlers.push(makerHandler);
}
if (aprConfig.ovix) {
const ovixHandler = new OvixAprHandler({
...aprConfig.ovix,
});
handlers.push(ovixHandler);
}
if (aprConfig.reaper) {
const reaperCryptHandler = new ReaperCryptAprHandler({ ...aprConfig.reaper });
handlers.push(reaperCryptHandler);
}
if (aprConfig.tessera) {
const tesseraHandler = new TesseraAprHandler({
...aprConfig.tessera,
});
handlers.push(tesseraHandler);
}
if (aprConfig.tetu) {
const tetuHandler = new TetuAprHandler(aprConfig.tetu);
handlers.push(tetuHandler);
}
if (aprConfig.tranchess) {
const tranchessHandler = new TranchessAprHandler(aprConfig.tranchess);
handlers.push(tranchessHandler);
}
if (aprConfig.yearn) {
const yearnHandler = new YearnAprHandler(aprConfig.yearn);
handlers.push(yearnHandler);
}
if (aprConfig.defaultHandlers) {
for (const handlerConfig of Object.values(aprConfig.defaultHandlers)) {
const handler = new DefaultAprHandler(handlerConfig);
handlers.push(handler);
}
}

// Add handlers from self-configured sources
Object.values(sources as unknown as any[])
.filter((source): source is { chains: Chain[], Handler: AprHandlerConstructor } => 'chains' in source)
.filter((source) => this.chain && source.chains.includes(this.chain))
.forEach((source) => {
handlers.push(new source.Handler());
});

return handlers;
}

async fetchAprsFromAllHandlers(): Promise<TokenApr[]> {
let aprs: TokenApr[] = this.fixedAprTokens
? Object.values(this.fixedAprTokens).map(({ address, apr, isIbYield, group }) => ({
apr,
address,
isIbYield: isIbYield ?? false,
group
}))
: [];
// Any IB Yield tokens (such as rETH, wstETH) need to be added here. Linear Wrapped Tokens must NOT be added here.
buildIbYieldTokens(aprConfig: IbAprConfig): string[] {
const ibYieldTokenNamesForDefaultHandler = [
'rEth',
'stETH',
'wstETH',
'cbETH',
'sfrxETH',
'USDR',
'swETH',
'wjAURA',
'qETH',
'ankrETH',
'ankrFTM',
'sFTMx',
'stMATIC',
'MATICX',
'wbETH',
'ETHx',
].map((token) => token.toLowerCase());

const results = await Promise.allSettled(this.handlers.map((handler) => handler.getAprs(this.chain)));
return [
...Object.values(aprConfig?.ankr?.tokens || {}).map((token) => token.address),
...Object.keys(aprConfig?.defaultHandlers || {}).filter((handler) =>
ibYieldTokenNamesForDefaultHandler.includes(handler.toLowerCase()),
),
...Object.keys(aprConfig?.fixedAprHandler || {}).filter((handler) =>
ibYieldTokenNamesForDefaultHandler.includes(handler.toLowerCase()),
),
];
}

for (const result of results) {
if (result.status === 'fulfilled') {
aprs = aprs.concat(
Object.entries(result.value).map(([address, { apr, isIbYield, group }]) => ({
apr,
address,
isIbYield,
group
})),
);
} else {
console.error('Failed to fetch APRs from handler', result.reason);
async fetchAprsFromAllHandlers(): Promise<TokenApr[]> {
let aprs: TokenApr[] = [];
for (const handler of this.handlers) {
const fetchedResponse: { [key: string]: { apr: number; isIbYield: boolean } } = await handler.getAprs();
for (const [address, { apr, isIbYield }] of Object.entries(fetchedResponse)) {
aprs.push({
apr,
isIbYield,
group: handler.group,
address,
});
}
}
if (this.fixedAprTokens) {
for (const { address, apr, isIbYield, group } of Object.values(this.fixedAprTokens)) {
aprs.push({
apr,
isIbYield: isIbYield ?? false,
group,
address,
});
}
}

return aprs;
}
}

interface AprHandlerConstructor {
new (config?: any): AprHandler;
}

export interface AprHandler {
group?: string;
getAprs(chain?: Chain): Promise<{
[tokenAddress: string]: {
/** Defined as float, eg: 0.01 is 1% */
apr: number;
isIbYield: boolean
group?: string;
}
}>;
group: string | undefined;
getAprs(): Promise<{ [tokenAddress: string]: { apr: number; isIbYield: boolean } }>;
}

export type TokenApr = {
apr: number;
address: string;
isIbYield: boolean;
group?: string;
isIbYield: boolean;
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export class AaveAprHandler implements AprHandler {
};
};
subgraphUrl: string;
group = 'AAVE';

readonly group = 'AAVE';

readonly query = `query getReserves($aTokens: [String!], $underlyingAssets: [Bytes!]) {
reserves(
Expand Down Expand Up @@ -80,11 +81,7 @@ export class AaveAprHandler implements AprHandler {
.map(({ wrappedTokens, underlyingAssetAddress, isIbYield }) => {
const apr = aprsByUnderlyingAddress[underlyingAssetAddress];
return Object.values(wrappedTokens).map((wrappedTokenAddress) => ({
[wrappedTokenAddress]: {
apr,
isIbYield: isIbYield ?? false,
group: this.group,
},
[wrappedTokenAddress]: { apr, isIbYield: isIbYield ?? false },
}));
})
.flat()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ export class AnkrAprHandler implements AprHandler {
};
};
url: string;
readonly group = undefined;

constructor(config: AnkrAprConfig) {
this.tokens = config.tokens;
this.url = config.sourceUrl;
constructor(aprHandlerConfig: AnkrAprConfig) {
this.tokens = aprHandlerConfig.tokens;
this.url = aprHandlerConfig.sourceUrl;
}

async getAprs() {
async getAprs(): Promise<{ [tokenAddress: string]: { apr: number; isIbYield: boolean } }> {
try {
const { data } = await axios.get(this.url);
const services = (data as { services: { serviceName: string; apy: string }[] }).services;
Expand All @@ -28,10 +29,7 @@ export class AnkrAprHandler implements AprHandler {
if (!service) {
return [address, 0];
}
return [address, {
apr: parseFloat(service.apy) / 1e2,
isIbYield: isIbYield ?? false,
}];
return [address, { apr: parseFloat(service.apy) / 1e2, isIbYield: isIbYield ?? false }];
}),
);
return aprs;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,20 @@ export class BeefyAprHandler implements AprHandler {
};
};
sourceUrl: string;
group = 'BEEFY';
group: string | undefined = 'BEEFY';

constructor(config: BeefyAprConfig) {
this.tokens = config.tokens;
this.sourceUrl = config.sourceUrl;
constructor(aprConfig: BeefyAprConfig) {
this.tokens = aprConfig.tokens;
this.sourceUrl = aprConfig.sourceUrl;
}

async getAprs() {
async getAprs(): Promise<{ [p: string]: { apr: number; isIbYield: boolean } }> {
try {
const { data: aprData } = await axios.get<VaultApr>(this.sourceUrl);
const aprs = Object.values(this.tokens).map(({ address, vaultId, isIbYield }) => {
const apr = aprData[vaultId]?.vaultApr ?? 0;
return {
[address]: {
apr,
isIbYield: isIbYield ?? false,
group: this.group
}
};
});

const aprs: { [tokenAddress: string]: { apr: number; isIbYield: boolean } } = {};
for (const { address, vaultId, isIbYield } of Object.values(this.tokens)) {
aprs[address] = { apr: aprData[vaultId].vaultApr, isIbYield: isIbYield ?? false };
}
return aprs;
} catch (error) {
console.error(`Beefy IB APR hanlder failed: `, error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import { abi as bloomBpsFeed } from './abis/bloom-bps-feed';
import * as Sentry from '@sentry/node';

export class BloomAprHandler implements AprHandler {
group = "BLOOM";
group: string | undefined;

tokens: BloomAprConfig['tokens'];

constructor(config: BloomAprConfig) {
this.tokens = config.tokens;
constructor(aprConfig: BloomAprConfig) {
this.tokens = aprConfig.tokens;
}

async getAprs() {
const aprs: { [p: string]: { apr: number; isIbYield: boolean, group?: string } } = {};
async getAprs(): Promise<{ [p: string]: { apr: number; isIbYield: boolean } }> {
const aprs: { [p: string]: { apr: number; isIbYield: boolean } } = {};
for (const { address, feedAddress, isIbYield } of Object.values(this.tokens)) {
try {
const feedContract = getContractAt(feedAddress, bloomBpsFeed);
Expand All @@ -23,11 +23,7 @@ export class BloomAprHandler implements AprHandler {
continue;
}
const tokenApr = (Number(currentRate) - 10000) / 10000;
aprs[address] = {
apr: tokenApr,
isIbYield: isIbYield ?? false,
group: this.group
};
aprs[address] = { apr: tokenApr, isIbYield: isIbYield ?? false };
} catch (error) {
console.error(`Bloom APR Failed for token ${address}: `, error);
Sentry.captureException(`Bloom APR Failed for token ${address}: ${error}`);
Expand Down
Loading

0 comments on commit 5ed75f6

Please sign in to comment.