Skip to content

Commit

Permalink
Merge pull request #173 from balancer-labs/develop
Browse files Browse the repository at this point in the history
Version 0.1.28
  • Loading branch information
johngrantuk authored Oct 13, 2022
2 parents b6e2abe + 57f47cb commit 7230a5b
Show file tree
Hide file tree
Showing 15 changed files with 261 additions and 295 deletions.
28 changes: 28 additions & 0 deletions balancer-js/examples/pools/aprs.arbitrum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Display APRs for pool ids hardcoded under `const ids`
* Run command: yarn examples:run ./examples/pools/aprs.arbitrum.ts
*/
import dotenv from 'dotenv';
import { BalancerSDK } from '../../src/modules/sdk.module';

dotenv.config();

const sdk = new BalancerSDK({
network: 42161,
rpcUrl: process.env.ARBITRUM_RPC_URL || 'https://rpc.ankr.com/arbitrum', // WARNING: ankr fails for multicall
});

const { pools } = sdk;

const main = async () => {
const pool = await pools.find(
'0xfb5e6d0c1dfed2ba000fbc040ab8df3615ac329c000000000000000000000159'
);

if (pool) {
const apr = await pools.apr(pool);
console.log(pool.id, apr);
}
};

main();
15 changes: 10 additions & 5 deletions balancer-js/examples/pools/liquidity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,21 @@ const sdk = new BalancerSDK({

const { pools } = sdk;

const main = async () => {
(() => {
[
'0xa13a9247ea42d743238089903570127dda72fe4400000000000000000000035d',
// '0x2f4eb100552ef93840d5adc30560e5513dfffacb000000000000000000000334',
].forEach(async (poolId) => {
const pool = await pools.find(poolId);
if (pool) {
const liquidity = await pools.liquidity(pool);
console.log(pool.totalShares, pool.totalLiquidity, liquidity);
console.table([
{
totalShares: pool.totalShares,
liquidity: liquidity,
bptPrice: parseFloat(pool.totalShares) / parseFloat(liquidity),
},
]);
}
});
};

main();
})();
2 changes: 1 addition & 1 deletion balancer-js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@balancer-labs/sdk",
"version": "0.1.27",
"version": "0.1.28",
"description": "JavaScript SDK for interacting with the Balancer Protocol V2",
"license": "GPL-3.0-only",
"homepage": "https://github.com/balancer-labs/balancer-sdk/balancer-js#readme",
Expand Down
5 changes: 3 additions & 2 deletions balancer-js/src/modules/data/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ export class Data implements BalancerDataRepositories {

const aaveRates = new AaveRates(
networkConfig.addresses.contracts.multicall,
provider
provider,
networkConfig.chainId
);

this.tokenPrices = new TokenPriceProvider(coingeckoRepository, aaveRates);
Expand Down Expand Up @@ -125,6 +126,6 @@ export class Data implements BalancerDataRepositories {
);
}

this.tokenYields = new TokenYieldsRepository();
this.tokenYields = new TokenYieldsRepository(networkConfig.chainId);
}
}
18 changes: 14 additions & 4 deletions balancer-js/src/modules/data/token-prices/aave-rates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Provider } from '@ethersproject/providers';
import { formatUnits } from '@ethersproject/units';
import { Multicall } from '@/modules/contracts/multicall';
import { yieldTokens } from '../token-yields/tokens/aave';
import { Network } from '@/types';

const wrappedATokenInterface = new Interface([
'function rate() view returns (uint256)',
Expand All @@ -13,13 +14,19 @@ export class AaveRates {
multicall: Contract;
rates?: Promise<{ [wrappedATokenAddress: string]: number }>;

constructor(multicallAddress: string, provider: Provider) {
constructor(
multicallAddress: string,
provider: Provider,
private network: Network
) {
this.multicall = Multicall(multicallAddress, provider);
}

private async fetch(): Promise<{ [wrappedATokenAddress: string]: number }> {
private async fetch(
network: Network.MAINNET | Network.POLYGON
): Promise<{ [wrappedATokenAddress: string]: number }> {
console.time('Fetching aave rates');
const addresses = Object.values(yieldTokens);
const addresses = Object.values(yieldTokens[network]);
const payload = addresses.map((wrappedATokenAddress) => [
wrappedATokenAddress,
wrappedATokenInterface.encodeFunctionData('rate', []),
Expand All @@ -36,8 +43,11 @@ export class AaveRates {
}

async getRate(wrappedAToken: string): Promise<number> {
if (this.network != Network.MAINNET && this.network != Network.POLYGON) {
return 1;
}
if (!this.rates) {
this.rates = this.fetch();
this.rates = this.fetch(this.network);
}

return (await this.rates)[wrappedAToken];
Expand Down
17 changes: 10 additions & 7 deletions balancer-js/src/modules/data/token-prices/coingecko.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-empty-function */
import { Price, Findable, TokenPrices } from '@/types';
import { Price, Findable, TokenPrices, Network } from '@/types';
import { wrappedTokensMap as aaveWrappedMap } from '../token-yields/tokens/aave';
import axios from 'axios';

Expand Down Expand Up @@ -37,10 +37,10 @@ export class CoingeckoPriceRepository implements Findable<Price> {
timeout?: ReturnType<typeof setTimeout>;
debounceCancel = (): void => {}; // Allow to cancel mid-flight requests

constructor(tokenAddresses: string[], chainId = 1) {
constructor(tokenAddresses: string[], private chainId: Network = 1) {
this.baseTokenAddresses = tokenAddresses
.map((a) => a.toLowerCase())
.map((a) => unwrapToken(a));
.map((a) => unwrapToken(a, this.chainId));
this.urlBase = `https://api.coingecko.com/api/v3/simple/token_price/${this.platform(
chainId
)}?vs_currencies=usd,eth`;
Expand Down Expand Up @@ -97,7 +97,7 @@ export class CoingeckoPriceRepository implements Findable<Price> {

async find(address: string): Promise<Price | undefined> {
const lowercaseAddress = address.toLowerCase();
const unwrapped = unwrapToken(lowercaseAddress);
const unwrapped = unwrapToken(lowercaseAddress, this.chainId);
if (!this.prices[unwrapped]) {
try {
let init = false;
Expand Down Expand Up @@ -154,11 +154,14 @@ export class CoingeckoPriceRepository implements Findable<Price> {
}
}

const unwrapToken = (wrappedAddress: string) => {
const unwrapToken = (wrappedAddress: string, chainId: Network) => {
const lowercase = wrappedAddress.toLocaleLowerCase();

if (Object.keys(aaveWrappedMap).includes(lowercase)) {
return aaveWrappedMap[lowercase as keyof typeof aaveWrappedMap].aToken;
const aaveChain = chainId as keyof typeof aaveWrappedMap;
if (Object.keys(aaveWrappedMap[aaveChain]).includes(lowercase)) {
return aaveWrappedMap[aaveChain][
lowercase as keyof typeof aaveWrappedMap[typeof aaveChain]
].aToken;
} else {
return lowercase;
}
Expand Down
15 changes: 10 additions & 5 deletions balancer-js/src/modules/data/token-yields/repository.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,35 @@
import { lido, yieldTokens as lidoTokens } from './tokens/lido';
import { aave, yieldTokens as aaveTokens } from './tokens/aave';
import {
lidoPolygon,
yieldTokens as lidoPolygonTokens,
} from './tokens/lido-polygon';
import { aave, allYieldTokens as aaveTokens } from './tokens/aave';
import { overnight, yieldTokens as overnightTokens } from './tokens/overnight';
import { Findable } from '../types';
import { Network, Findable } from '@/types';

/**
* Common interface for fetching APR from external sources
*
* @param address is optional, used when same source, eg: aave has multiple tokens and all of them can be fetched in one call.
*/
export interface AprFetcher {
(): Promise<{ [address: string]: number }>;
(network?: Network): Promise<{ [address: string]: number }>;
}

const yieldSourceMap: { [address: string]: AprFetcher } = Object.fromEntries([
...Object.values(lidoTokens).map((k) => [k, lido]),
...Object.values(lidoPolygonTokens).map((k) => [k, lidoPolygon]),
...Object.values(aaveTokens).map((k) => [k, aave]),
...Object.values(overnightTokens).map((k) => [k, overnight]),
]);

export class TokenYieldsRepository implements Findable<number> {
private yields: { [address: string]: number } = {};

constructor(private sources = yieldSourceMap) {}
constructor(private network: Network, private sources = yieldSourceMap) {}

async fetch(address: string): Promise<void> {
const tokenYields = await this.sources[address]();
const tokenYields = await this.sources[address](this.network);
this.yields = {
...this.yields,
...tokenYields,
Expand Down
4 changes: 2 additions & 2 deletions balancer-js/src/modules/data/token-yields/tokens/aave.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const mockedResponse = {
data: {
reserves: [
{
underlyingAsset: wrappedTokensMap[yieldTokens.waUSDT].underlying,
underlyingAsset: wrappedTokensMap[1][yieldTokens[1].waUSDT].underlying,
liquidityRate: '16633720952291480781459657',
},
],
Expand All @@ -29,7 +29,7 @@ describe('aave apr', () => {
});

it('is getting fetched', async () => {
const apr = (await aave())[yieldTokens.waUSDT];
const apr = (await aave(1))[yieldTokens[1].waUSDT];
expect(apr).to.eq(166);
});
});
Expand Down
Loading

0 comments on commit 7230a5b

Please sign in to comment.