From 13164fcf56fc6c05002ca5a39b3afda56bf5783c Mon Sep 17 00:00:00 2001 From: Tim Robinson Date: Thu, 29 Sep 2022 18:37:50 +1000 Subject: [PATCH 01/14] Add additional subpool data to PoolToken --- balancer-js/src/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/balancer-js/src/types.ts b/balancer-js/src/types.ts index c25650b83..c9089380d 100644 --- a/balancer-js/src/types.ts +++ b/balancer-js/src/types.ts @@ -174,6 +174,7 @@ export interface PoolToken extends Token { balance: string; priceRate?: string; weight?: string | null; + token?: { pool: { poolType: null | PoolType } | null }; } export interface OnchainTokenData { From 8e81beee91197385a81c7fe444eb31f9ec58c278 Mon Sep 17 00:00:00 2001 From: Tim Robinson Date: Fri, 30 Sep 2022 13:22:48 +1000 Subject: [PATCH 02/14] Make pool optional as well --- balancer-js/src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/balancer-js/src/types.ts b/balancer-js/src/types.ts index c9089380d..17cda1cbd 100644 --- a/balancer-js/src/types.ts +++ b/balancer-js/src/types.ts @@ -174,7 +174,7 @@ export interface PoolToken extends Token { balance: string; priceRate?: string; weight?: string | null; - token?: { pool: { poolType: null | PoolType } | null }; + token?: { pool?: { poolType: null | PoolType } | null }; } export interface OnchainTokenData { From a302ff79b903e395740e422d6b82d10961e24289 Mon Sep 17 00:00:00 2001 From: Tim Robinson Date: Fri, 30 Sep 2022 14:10:11 +1000 Subject: [PATCH 03/14] Also make poolType optional --- balancer-js/src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/balancer-js/src/types.ts b/balancer-js/src/types.ts index 17cda1cbd..6815ae808 100644 --- a/balancer-js/src/types.ts +++ b/balancer-js/src/types.ts @@ -174,7 +174,7 @@ export interface PoolToken extends Token { balance: string; priceRate?: string; weight?: string | null; - token?: { pool?: { poolType: null | PoolType } | null }; + token?: { pool?: { poolType?: null | PoolType } | null }; } export interface OnchainTokenData { From b2ae71d5dffaf51ad2493f0b00661b62ca82c5b5 Mon Sep 17 00:00:00 2001 From: Tim Robinson Date: Fri, 30 Sep 2022 14:40:59 +1000 Subject: [PATCH 04/14] Rebuild subgraph types, add mapToken for poolType - Rebuild subgraph types so that SubgraphPoolTokenFragment contains the sub pool. This was changed in graphQL previously but the interfaces were not rebuilt. - Add mapToken function that formats the token correctly for the PoolToken type and leaves it as null otherwise. --- balancer-js/src/modules/data/pool/subgraph.ts | 22 +++++++++++++++++-- .../generated/balancer-subgraph-types.ts | 21 +++++++++++------- balancer-js/src/types.ts | 2 +- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/balancer-js/src/modules/data/pool/subgraph.ts b/balancer-js/src/modules/data/pool/subgraph.ts index e5e777bae..65fd4ec92 100644 --- a/balancer-js/src/modules/data/pool/subgraph.ts +++ b/balancer-js/src/modules/data/pool/subgraph.ts @@ -5,6 +5,7 @@ import { SubgraphPool, Pool_OrderBy, OrderDirection, + SubgraphPoolTokenFragment, } from '@/modules/subgraph/subgraph'; import { GraphQLArgsBuilder, @@ -12,9 +13,10 @@ import { } from '@/lib/graphql/args-builder'; import { GraphQLArgs } from '@/lib/graphql/types'; import { PoolAttribute, PoolsRepositoryFetchOptions } from './types'; -import { GraphQLQuery, Pool, PoolType } from '@/types'; +import { GraphQLQuery, Pool, PoolType, PoolToken } from '@/types'; import { Network } from '@/lib/constants/network'; import { PoolsQueryVariables } from '../../subgraph/subgraph'; +import { SubgraphToken } from '@balancer-labs/sor'; interface PoolsSubgraphRepositoryOptions { url: string; @@ -153,7 +155,7 @@ export class PoolsSubgraphRepository amp: subgraphPool.amp ?? undefined, owner: subgraphPool.owner ?? undefined, factory: subgraphPool.factory ?? undefined, - tokens: subgraphPool.tokens || [], + tokens: (subgraphPool.tokens || []).map(this.mapToken), tokensList: subgraphPool.tokensList, tokenAddresses: (subgraphPool.tokens || []).map((t) => t.address), totalLiquidity: subgraphPool.totalLiquidity, @@ -174,4 +176,20 @@ export class PoolsSubgraphRepository totalWeight: subgraphPool.totalWeight || '1', }; } + + private mapToken(subgraphToken: SubgraphPoolTokenFragment): PoolToken { + let subgraphTokenPool = null; + if (subgraphToken.token?.pool) { + subgraphTokenPool = { + ...subgraphToken.token.pool, + poolType: subgraphToken.token.pool.poolType as PoolType, + }; + } + return { + ...subgraphToken, + token: { + pool: subgraphTokenPool, + }, + }; + } } diff --git a/balancer-js/src/modules/subgraph/generated/balancer-subgraph-types.ts b/balancer-js/src/modules/subgraph/generated/balancer-subgraph-types.ts index 91fd9765c..dc276ea42 100644 --- a/balancer-js/src/modules/subgraph/generated/balancer-subgraph-types.ts +++ b/balancer-js/src/modules/subgraph/generated/balancer-subgraph-types.ts @@ -3572,7 +3572,7 @@ export type PoolsQueryVariables = Exact<{ }>; -export type PoolsQuery = { __typename?: 'Query', pools: Array<{ __typename?: 'Pool', id: string, address: string, poolType?: string | null, factory?: string | null, strategyType: number, symbol?: string | null, name?: string | null, swapEnabled: boolean, swapFee: string, owner?: string | null, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, createTime: number, principalToken?: string | null, baseToken?: string | null, wrappedIndex?: number | null, mainIndex?: number | null, lowerTarget?: string | null, upperTarget?: string | null, sqrtAlpha?: string | null, sqrtBeta?: string | null, root3Alpha?: string | null, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string }> | null }> }; +export type PoolsQuery = { __typename?: 'Query', pools: Array<{ __typename?: 'Pool', id: string, address: string, poolType?: string | null, factory?: string | null, strategyType: number, symbol?: string | null, name?: string | null, swapEnabled: boolean, swapFee: string, owner?: string | null, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, createTime: number, principalToken?: string | null, baseToken?: string | null, wrappedIndex?: number | null, mainIndex?: number | null, lowerTarget?: string | null, upperTarget?: string | null, sqrtAlpha?: string | null, sqrtBeta?: string | null, root3Alpha?: string | null, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string, token: { __typename?: 'Token', pool?: { __typename?: 'Pool', poolType?: string | null } | null } }> | null }> }; export type AllPoolsQueryVariables = Exact<{ skip?: InputMaybe; @@ -3584,7 +3584,7 @@ export type AllPoolsQueryVariables = Exact<{ }>; -export type AllPoolsQuery = { __typename?: 'Query', pool0: Array<{ __typename?: 'Pool', id: string, address: string, poolType?: string | null, factory?: string | null, strategyType: number, symbol?: string | null, name?: string | null, swapEnabled: boolean, swapFee: string, owner?: string | null, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, createTime: number, principalToken?: string | null, baseToken?: string | null, wrappedIndex?: number | null, mainIndex?: number | null, lowerTarget?: string | null, upperTarget?: string | null, sqrtAlpha?: string | null, sqrtBeta?: string | null, root3Alpha?: string | null, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string }> | null }>, pool1000: Array<{ __typename?: 'Pool', id: string, address: string, poolType?: string | null, factory?: string | null, strategyType: number, symbol?: string | null, name?: string | null, swapEnabled: boolean, swapFee: string, owner?: string | null, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, createTime: number, principalToken?: string | null, baseToken?: string | null, wrappedIndex?: number | null, mainIndex?: number | null, lowerTarget?: string | null, upperTarget?: string | null, sqrtAlpha?: string | null, sqrtBeta?: string | null, root3Alpha?: string | null, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string }> | null }>, pool2000: Array<{ __typename?: 'Pool', id: string, address: string, poolType?: string | null, factory?: string | null, strategyType: number, symbol?: string | null, name?: string | null, swapEnabled: boolean, swapFee: string, owner?: string | null, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, createTime: number, principalToken?: string | null, baseToken?: string | null, wrappedIndex?: number | null, mainIndex?: number | null, lowerTarget?: string | null, upperTarget?: string | null, sqrtAlpha?: string | null, sqrtBeta?: string | null, root3Alpha?: string | null, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string }> | null }> }; +export type AllPoolsQuery = { __typename?: 'Query', pool0: Array<{ __typename?: 'Pool', id: string, address: string, poolType?: string | null, factory?: string | null, strategyType: number, symbol?: string | null, name?: string | null, swapEnabled: boolean, swapFee: string, owner?: string | null, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, createTime: number, principalToken?: string | null, baseToken?: string | null, wrappedIndex?: number | null, mainIndex?: number | null, lowerTarget?: string | null, upperTarget?: string | null, sqrtAlpha?: string | null, sqrtBeta?: string | null, root3Alpha?: string | null, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string, token: { __typename?: 'Token', pool?: { __typename?: 'Pool', poolType?: string | null } | null } }> | null }>, pool1000: Array<{ __typename?: 'Pool', id: string, address: string, poolType?: string | null, factory?: string | null, strategyType: number, symbol?: string | null, name?: string | null, swapEnabled: boolean, swapFee: string, owner?: string | null, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, createTime: number, principalToken?: string | null, baseToken?: string | null, wrappedIndex?: number | null, mainIndex?: number | null, lowerTarget?: string | null, upperTarget?: string | null, sqrtAlpha?: string | null, sqrtBeta?: string | null, root3Alpha?: string | null, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string, token: { __typename?: 'Token', pool?: { __typename?: 'Pool', poolType?: string | null } | null } }> | null }>, pool2000: Array<{ __typename?: 'Pool', id: string, address: string, poolType?: string | null, factory?: string | null, strategyType: number, symbol?: string | null, name?: string | null, swapEnabled: boolean, swapFee: string, owner?: string | null, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, createTime: number, principalToken?: string | null, baseToken?: string | null, wrappedIndex?: number | null, mainIndex?: number | null, lowerTarget?: string | null, upperTarget?: string | null, sqrtAlpha?: string | null, sqrtBeta?: string | null, root3Alpha?: string | null, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string, token: { __typename?: 'Token', pool?: { __typename?: 'Pool', poolType?: string | null } | null } }> | null }> }; export type PoolQueryVariables = Exact<{ id: Scalars['ID']; @@ -3592,7 +3592,7 @@ export type PoolQueryVariables = Exact<{ }>; -export type PoolQuery = { __typename?: 'Query', pool?: { __typename?: 'Pool', id: string, address: string, poolType?: string | null, factory?: string | null, strategyType: number, symbol?: string | null, name?: string | null, swapEnabled: boolean, swapFee: string, owner?: string | null, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, createTime: number, principalToken?: string | null, baseToken?: string | null, wrappedIndex?: number | null, mainIndex?: number | null, lowerTarget?: string | null, upperTarget?: string | null, sqrtAlpha?: string | null, sqrtBeta?: string | null, root3Alpha?: string | null, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string }> | null } | null }; +export type PoolQuery = { __typename?: 'Query', pool?: { __typename?: 'Pool', id: string, address: string, poolType?: string | null, factory?: string | null, strategyType: number, symbol?: string | null, name?: string | null, swapEnabled: boolean, swapFee: string, owner?: string | null, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, createTime: number, principalToken?: string | null, baseToken?: string | null, wrappedIndex?: number | null, mainIndex?: number | null, lowerTarget?: string | null, upperTarget?: string | null, sqrtAlpha?: string | null, sqrtBeta?: string | null, root3Alpha?: string | null, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string, token: { __typename?: 'Token', pool?: { __typename?: 'Pool', poolType?: string | null } | null } }> | null } | null }; export type PoolsWithoutLinearQueryVariables = Exact<{ skip?: InputMaybe; @@ -3604,7 +3604,7 @@ export type PoolsWithoutLinearQueryVariables = Exact<{ }>; -export type PoolsWithoutLinearQuery = { __typename?: 'Query', pools: Array<{ __typename?: 'Pool', id: string, address: string, poolType?: string | null, symbol?: string | null, name?: string | null, swapFee: string, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, principalToken?: string | null, baseToken?: string | null, swapEnabled: boolean, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string }> | null }> }; +export type PoolsWithoutLinearQuery = { __typename?: 'Query', pools: Array<{ __typename?: 'Pool', id: string, address: string, poolType?: string | null, symbol?: string | null, name?: string | null, swapFee: string, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, principalToken?: string | null, baseToken?: string | null, swapEnabled: boolean, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string, token: { __typename?: 'Token', pool?: { __typename?: 'Pool', poolType?: string | null } | null } }> | null }> }; export type PoolWithoutLinearQueryVariables = Exact<{ id: Scalars['ID']; @@ -3612,13 +3612,13 @@ export type PoolWithoutLinearQueryVariables = Exact<{ }>; -export type PoolWithoutLinearQuery = { __typename?: 'Query', pool?: { __typename?: 'Pool', id: string, address: string, poolType?: string | null, symbol?: string | null, name?: string | null, swapFee: string, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, principalToken?: string | null, baseToken?: string | null, swapEnabled: boolean, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string }> | null } | null }; +export type PoolWithoutLinearQuery = { __typename?: 'Query', pool?: { __typename?: 'Pool', id: string, address: string, poolType?: string | null, symbol?: string | null, name?: string | null, swapFee: string, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, principalToken?: string | null, baseToken?: string | null, swapEnabled: boolean, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string, token: { __typename?: 'Token', pool?: { __typename?: 'Pool', poolType?: string | null } | null } }> | null } | null }; -export type SubgraphPoolFragment = { __typename?: 'Pool', id: string, address: string, poolType?: string | null, factory?: string | null, strategyType: number, symbol?: string | null, name?: string | null, swapEnabled: boolean, swapFee: string, owner?: string | null, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, createTime: number, principalToken?: string | null, baseToken?: string | null, wrappedIndex?: number | null, mainIndex?: number | null, lowerTarget?: string | null, upperTarget?: string | null, sqrtAlpha?: string | null, sqrtBeta?: string | null, root3Alpha?: string | null, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string }> | null }; +export type SubgraphPoolFragment = { __typename?: 'Pool', id: string, address: string, poolType?: string | null, factory?: string | null, strategyType: number, symbol?: string | null, name?: string | null, swapEnabled: boolean, swapFee: string, owner?: string | null, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, createTime: number, principalToken?: string | null, baseToken?: string | null, wrappedIndex?: number | null, mainIndex?: number | null, lowerTarget?: string | null, upperTarget?: string | null, sqrtAlpha?: string | null, sqrtBeta?: string | null, root3Alpha?: string | null, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string, token: { __typename?: 'Token', pool?: { __typename?: 'Pool', poolType?: string | null } | null } }> | null }; -export type SubgraphPoolWithoutLinearFragment = { __typename?: 'Pool', id: string, address: string, poolType?: string | null, symbol?: string | null, name?: string | null, swapFee: string, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, principalToken?: string | null, baseToken?: string | null, swapEnabled: boolean, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string }> | null }; +export type SubgraphPoolWithoutLinearFragment = { __typename?: 'Pool', id: string, address: string, poolType?: string | null, symbol?: string | null, name?: string | null, swapFee: string, totalWeight?: string | null, totalSwapVolume: string, totalSwapFee: string, totalLiquidity: string, totalShares: string, swapsCount: string, holdersCount: string, tokensList: Array, amp?: string | null, expiryTime?: string | null, unitSeconds?: string | null, principalToken?: string | null, baseToken?: string | null, swapEnabled: boolean, tokens?: Array<{ __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string, token: { __typename?: 'Token', pool?: { __typename?: 'Pool', poolType?: string | null } | null } }> | null }; -export type SubgraphPoolTokenFragment = { __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string }; +export type SubgraphPoolTokenFragment = { __typename?: 'PoolToken', id: string, symbol: string, name: string, decimals: number, address: string, balance: string, managedBalance: string, weight?: string | null, priceRate: string, token: { __typename?: 'Token', pool?: { __typename?: 'Pool', poolType?: string | null } | null } }; export type PoolHistoricalLiquiditiesQueryVariables = Exact<{ skip?: InputMaybe; @@ -3742,6 +3742,11 @@ export const SubgraphPoolTokenFragmentDoc = gql` managedBalance weight priceRate + token { + pool { + poolType + } + } } `; export const SubgraphPoolFragmentDoc = gql` diff --git a/balancer-js/src/types.ts b/balancer-js/src/types.ts index 6815ae808..c9089380d 100644 --- a/balancer-js/src/types.ts +++ b/balancer-js/src/types.ts @@ -174,7 +174,7 @@ export interface PoolToken extends Token { balance: string; priceRate?: string; weight?: string | null; - token?: { pool?: { poolType?: null | PoolType } | null }; + token?: { pool: { poolType: null | PoolType } | null }; } export interface OnchainTokenData { From 2d6b672b4a83f450233bd2615f5acbbba8710eb1 Mon Sep 17 00:00:00 2001 From: Tim Robinson Date: Fri, 30 Sep 2022 14:44:30 +1000 Subject: [PATCH 05/14] Fix lint issues --- balancer-js/src/modules/data/pool/subgraph.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/balancer-js/src/modules/data/pool/subgraph.ts b/balancer-js/src/modules/data/pool/subgraph.ts index 65fd4ec92..f35e95e43 100644 --- a/balancer-js/src/modules/data/pool/subgraph.ts +++ b/balancer-js/src/modules/data/pool/subgraph.ts @@ -16,7 +16,6 @@ import { PoolAttribute, PoolsRepositoryFetchOptions } from './types'; import { GraphQLQuery, Pool, PoolType, PoolToken } from '@/types'; import { Network } from '@/lib/constants/network'; import { PoolsQueryVariables } from '../../subgraph/subgraph'; -import { SubgraphToken } from '@balancer-labs/sor'; interface PoolsSubgraphRepositoryOptions { url: string; From 82cf1ac1989129fca6ffe9e45768f8e98704877d Mon Sep 17 00:00:00 2001 From: Tim Robinson Date: Wed, 5 Oct 2022 10:07:33 -0400 Subject: [PATCH 06/14] Always find token prices by lower case address --- balancer-js/src/modules/pools/apr/apr.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/balancer-js/src/modules/pools/apr/apr.ts b/balancer-js/src/modules/pools/apr/apr.ts index cf1eca07f..45e96b613 100644 --- a/balancer-js/src/modules/pools/apr/apr.ts +++ b/balancer-js/src/modules/pools/apr/apr.ts @@ -417,9 +417,9 @@ export class PoolApr { }; } else { const yearlyReward = rewardData.rate.mul(86400).mul(365); - const price = await this.tokenPrices.find(tokenAddress); + const price = await this.tokenPrices.find(tokenAddress.toLowerCase()); if (price && price.usd) { - const meta = await this.tokenMeta.find(tokenAddress); + const meta = await this.tokenMeta.find(tokenAddress.toLowerCase()); const decimals = meta?.decimals || 18; const yearlyRewardUsd = parseFloat(formatUnits(yearlyReward, decimals)) * From aa92a34a17e7b2def9c25fb77ac7c000e30a0d8c Mon Sep 17 00:00:00 2001 From: Tim Robinson Date: Wed, 5 Oct 2022 10:12:29 -0400 Subject: [PATCH 07/14] Remove hack for calculating token USD prices --- .../src/modules/data/token-prices/static.ts | 48 +------------------ 1 file changed, 1 insertion(+), 47 deletions(-) diff --git a/balancer-js/src/modules/data/token-prices/static.ts b/balancer-js/src/modules/data/token-prices/static.ts index 221a3475d..3a7915406 100644 --- a/balancer-js/src/modules/data/token-prices/static.ts +++ b/balancer-js/src/modules/data/token-prices/static.ts @@ -1,54 +1,8 @@ -import { BigNumber, formatFixed } from '@ethersproject/bignumber'; -import { parseFixed } from '@/lib/utils/math'; import { Price, TokenPrices } from '@/types'; import { TokenPriceProvider } from './types'; -const SCALING_FACTOR = 18; - export class StaticTokenPriceProvider implements TokenPriceProvider { - constructor(private tokenPrices: TokenPrices) { - this.calculateUSDPrices(); - } - - /** - * Iterates through all tokens and calculates USD prices - * based on data the tokens already have. - */ - calculateUSDPrices(): void { - const USDAssets = [ - '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - '0x6b175474e89094c44da98b954eedeac495271d0f', - '0x6B175474E89094C44Da98b954EedeAC495271d0F', - '0xdac17f958d2ee523a2206206994597c13d831ec7', - '0xdAC17F958D2ee523a2206206994597C13D831ec7', - ]; - let assetsAvailable = 0; - let assetValueSum = BigNumber.from(0); - - USDAssets.forEach((address) => { - const tokenPrice = this.tokenPrices[address]; - if (tokenPrice?.eth) { - const scaledPrice = parseFixed(tokenPrice?.eth, SCALING_FACTOR); - assetValueSum = assetValueSum.add(scaledPrice); - assetsAvailable++; - } - }); - - if (assetsAvailable === 0) return; - const NativeAssetUSDPrice = assetValueSum.div(assetsAvailable); - - for (const token in this.tokenPrices) { - const price = this.tokenPrices[token]; - if (price.eth && !price.usd) { - const usdPrice = parseFixed('1', SCALING_FACTOR) - .mul(parseFixed(price.eth, SCALING_FACTOR)) - .div(NativeAssetUSDPrice) - .toString(); - price.usd = formatFixed(usdPrice, SCALING_FACTOR); - } - } - } + constructor(private tokenPrices: TokenPrices) {} async find(address: string): Promise { const price = this.tokenPrices[address]; From 4c271e1eb2e87091555908a3d0f7abd012ae6ee6 Mon Sep 17 00:00:00 2001 From: Tim Robinson Date: Wed, 5 Oct 2022 10:52:21 -0400 Subject: [PATCH 08/14] Scale reward breakdown correctly --- balancer-js/src/modules/pools/apr/apr.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/balancer-js/src/modules/pools/apr/apr.ts b/balancer-js/src/modules/pools/apr/apr.ts index 45e96b613..c16673972 100644 --- a/balancer-js/src/modules/pools/apr/apr.ts +++ b/balancer-js/src/modules/pools/apr/apr.ts @@ -278,12 +278,13 @@ export class PoolApr { let total = 0; for await (const reward of Object.values(rewards)) { const rewardValue = reward.value / totalSupplyUsd; - total += rewardValue; - rewardTokensBreakdown[reward.address] = reward.value; + const rewardValueScaled = Math.round(10000 * rewardValue); + total += rewardValueScaled; + rewardTokensBreakdown[reward.address] = rewardValueScaled; } return { - total: Math.round(10000 * total), + total, breakdown: rewardTokensBreakdown, }; } From 9c0df6891d2857260b0ea6a98bd4a3728d5be404 Mon Sep 17 00:00:00 2001 From: Tim Robinson Date: Wed, 5 Oct 2022 10:59:50 -0400 Subject: [PATCH 09/14] Add test to reproduce reward breakdown bug --- balancer-js/src/modules/pools/apr/apr.spec.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/balancer-js/src/modules/pools/apr/apr.spec.ts b/balancer-js/src/modules/pools/apr/apr.spec.ts index 3f4046db2..cf073e70e 100644 --- a/balancer-js/src/modules/pools/apr/apr.spec.ts +++ b/balancer-js/src/modules/pools/apr/apr.spec.ts @@ -192,6 +192,13 @@ describe('pool apr', () => { ).rewardAprs(poolData); expect(apr.total).to.eq(20000); + + const aprBreakdownSum = Object.values(apr.breakdown).reduce( + (total, current) => (total += current), + 0 + ); + + expect(aprBreakdownSum).to.eq(apr.total); }); }); }); From 349b267e4deb7edce6656ef9e4e0e570547c5f2e Mon Sep 17 00:00:00 2001 From: bronco Date: Thu, 6 Oct 2022 16:06:18 +0200 Subject: [PATCH 10/14] add test to cover different address casing --- balancer-js/src/modules/data/token-prices/coingecko.spec.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/balancer-js/src/modules/data/token-prices/coingecko.spec.ts b/balancer-js/src/modules/data/token-prices/coingecko.spec.ts index c57c7f0a6..dbaa1e4aa 100644 --- a/balancer-js/src/modules/data/token-prices/coingecko.spec.ts +++ b/balancer-js/src/modules/data/token-prices/coingecko.spec.ts @@ -41,8 +41,9 @@ describe('coingecko repository', () => { }); it('finds prices', async () => { - const [price1, price2, price3, price4, price5] = await Promise.all([ + const [price1, price2, price3, price4, price5, price6] = await Promise.all([ repository.find(addresses[0]), + repository.find(addresses[0].toUpperCase()), repository.find(addresses[1]), repository.find(addresses[2]), repository.find(addresses[3]), @@ -51,7 +52,8 @@ describe('coingecko repository', () => { expect(price1?.usd).to.be.gt(0); expect(price2?.usd).to.be.gt(0); expect(price3?.usd).to.be.gt(0); - expect(price4?.usd).to.be.undefined; + expect(price4?.usd).to.be.gt(0); expect(price5?.usd).to.be.undefined; + expect(price6?.usd).to.be.undefined; }); }); From 7f13b37445f7896704242a6b62dd0a38c2dbb9f6 Mon Sep 17 00:00:00 2001 From: Tim Robinson Date: Thu, 6 Oct 2022 10:28:05 -0400 Subject: [PATCH 11/14] Always use lowercase addresses in static provider - Instead of changing the apr code to pass in addresses in lower case, always store addresses as lower case in the static provider and convert ot lower case when finding. --- .../src/modules/data/token-prices/index.ts | 1 - .../modules/data/token-prices/static.spec.ts | 38 +++++++++++++++++++ .../src/modules/data/token-prices/static.ts | 17 ++++++--- .../src/modules/data/token-prices/types.ts | 5 --- .../src/modules/liquidity/liquidity.module.ts | 5 +-- balancer-js/src/modules/pools/apr/apr.ts | 4 +- 6 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 balancer-js/src/modules/data/token-prices/static.spec.ts delete mode 100644 balancer-js/src/modules/data/token-prices/types.ts diff --git a/balancer-js/src/modules/data/token-prices/index.ts b/balancer-js/src/modules/data/token-prices/index.ts index a70204eb7..6390e116a 100644 --- a/balancer-js/src/modules/data/token-prices/index.ts +++ b/balancer-js/src/modules/data/token-prices/index.ts @@ -1,3 +1,2 @@ -export * from './types'; export * from './static'; export * from './coingecko'; diff --git a/balancer-js/src/modules/data/token-prices/static.spec.ts b/balancer-js/src/modules/data/token-prices/static.spec.ts new file mode 100644 index 000000000..8cab4e643 --- /dev/null +++ b/balancer-js/src/modules/data/token-prices/static.spec.ts @@ -0,0 +1,38 @@ +import { TokenPrices } from '@/types'; +import { expect } from 'chai'; +import { StaticTokenPriceProvider } from './static'; + +const TOKENS = { + BAL: '0x9a71012B13CA4d3D0Cdc72A177DF3ef03b0E76A3', + WMATIC: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', +}; + +let staticTokenPriceProvider: StaticTokenPriceProvider; + +describe('static token prices repository', () => { + it('Should store token addresses as lower case internally', async () => { + const tokenPrices: TokenPrices = { + [TOKENS.BAL]: { + usd: '10', + }, + }; + staticTokenPriceProvider = new StaticTokenPriceProvider(tokenPrices); + expect( + await staticTokenPriceProvider.find(TOKENS.BAL.toLowerCase()) + ).to.deep.eq({ + usd: '10', + }); + }); + + it('When finding by upper case address it converts to lower case', async () => { + const tokenPrices: TokenPrices = { + [TOKENS.BAL.toLowerCase()]: { + usd: '10', + }, + }; + staticTokenPriceProvider = new StaticTokenPriceProvider(tokenPrices); + expect(await staticTokenPriceProvider.find(TOKENS.BAL)).to.deep.eq({ + usd: '10', + }); + }); +}); diff --git a/balancer-js/src/modules/data/token-prices/static.ts b/balancer-js/src/modules/data/token-prices/static.ts index 3a7915406..5898e12f7 100644 --- a/balancer-js/src/modules/data/token-prices/static.ts +++ b/balancer-js/src/modules/data/token-prices/static.ts @@ -1,11 +1,18 @@ -import { Price, TokenPrices } from '@/types'; -import { TokenPriceProvider } from './types'; +import { Findable, Price, TokenPrices } from '@/types'; -export class StaticTokenPriceProvider implements TokenPriceProvider { - constructor(private tokenPrices: TokenPrices) {} +export class StaticTokenPriceProvider implements Findable { + tokenPrices: TokenPrices; + constructor(tokenPrices: TokenPrices) { + this.tokenPrices = Object.fromEntries( + Object.entries(tokenPrices).map(([address, price]) => { + return [address.toLowerCase(), price]; + }) + ); + } async find(address: string): Promise { - const price = this.tokenPrices[address]; + const lowercaseAddress = address.toLowerCase(); + const price = this.tokenPrices[lowercaseAddress]; if (!price) return; return price; } diff --git a/balancer-js/src/modules/data/token-prices/types.ts b/balancer-js/src/modules/data/token-prices/types.ts deleted file mode 100644 index 8e327c3b1..000000000 --- a/balancer-js/src/modules/data/token-prices/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Price } from '@/types'; - -export interface TokenPriceProvider { - find: (address: string) => Promise; -} diff --git a/balancer-js/src/modules/liquidity/liquidity.module.ts b/balancer-js/src/modules/liquidity/liquidity.module.ts index a4d985ab1..39312f27f 100644 --- a/balancer-js/src/modules/liquidity/liquidity.module.ts +++ b/balancer-js/src/modules/liquidity/liquidity.module.ts @@ -1,6 +1,5 @@ -import { Findable, Pool, PoolToken } from '@/types'; +import { Findable, Pool, PoolToken, Price } from '@/types'; import { PoolAttribute } from '../data'; -import { TokenPriceProvider } from '../data'; import { PoolTypeConcerns } from '../pools/pool-type-concerns'; import { BigNumber } from '@ethersproject/bignumber'; import { formatFixed, parseFixed } from '@/lib/utils/math'; @@ -15,7 +14,7 @@ export interface PoolBPTValue { export class Liquidity { constructor( private pools: Findable, - private tokenPrices: TokenPriceProvider + private tokenPrices: Findable ) {} async getLiquidity(pool: Pool): Promise { diff --git a/balancer-js/src/modules/pools/apr/apr.ts b/balancer-js/src/modules/pools/apr/apr.ts index c16673972..6f67be3ff 100644 --- a/balancer-js/src/modules/pools/apr/apr.ts +++ b/balancer-js/src/modules/pools/apr/apr.ts @@ -418,9 +418,9 @@ export class PoolApr { }; } else { const yearlyReward = rewardData.rate.mul(86400).mul(365); - const price = await this.tokenPrices.find(tokenAddress.toLowerCase()); + const price = await this.tokenPrices.find(tokenAddress); if (price && price.usd) { - const meta = await this.tokenMeta.find(tokenAddress.toLowerCase()); + const meta = await this.tokenMeta.find(tokenAddress); const decimals = meta?.decimals || 18; const yearlyRewardUsd = parseFloat(formatUnits(yearlyReward, decimals)) * From 903b0b781464c2d55e216631a0eb832b1ac73051 Mon Sep 17 00:00:00 2001 From: bronco Date: Mon, 3 Oct 2022 18:05:41 +0200 Subject: [PATCH 12/14] fix: wrapped aave tokens rate --- .../examples/pools/calculateLiquidity.ts | 12 ++--- balancer-js/examples/pools/liquidity.ts | 22 +++++++++ balancer-js/src/modules/data/index.ts | 15 ++++++- .../modules/data/token-prices/aave-rates.ts | 45 +++++++++++++++++++ .../src/modules/data/token-prices/index.ts | 2 + .../src/modules/data/token-prices/provider.ts | 31 +++++++++++++ 6 files changed, 117 insertions(+), 10 deletions(-) create mode 100644 balancer-js/examples/pools/liquidity.ts create mode 100644 balancer-js/src/modules/data/token-prices/aave-rates.ts create mode 100644 balancer-js/src/modules/data/token-prices/provider.ts diff --git a/balancer-js/examples/pools/calculateLiquidity.ts b/balancer-js/examples/pools/calculateLiquidity.ts index f26ecf936..4e7068657 100644 --- a/balancer-js/examples/pools/calculateLiquidity.ts +++ b/balancer-js/examples/pools/calculateLiquidity.ts @@ -1,13 +1,12 @@ import { Liquidity, - StaticPoolRepository, StaticTokenPriceProvider, Pool, TokenPrices, } from '../../src'; +import { findable } from '../../src/test/factories/data'; import { formatFixed } from '@ethersproject/bignumber'; import { parseFixed } from '../../src/lib/utils/math'; -import { FallbackPoolRepository } from '../../src/modules/data/pool'; import POOLS from './pools.json'; import DECORATED_POOLS from './decorated-pools.json'; import TOKENS from './tokens.json'; @@ -28,12 +27,9 @@ TOKENS.forEach((token) => { } }); -// const sorPoolProvider = new SORPoolProvider(config); -const staticPoolProvider = new StaticPoolRepository(POOLS as Pool[]); -const poolProvider = new FallbackPoolRepository([ - // sorPoolProvider, - staticPoolProvider, -]); +const pools = new Map(); +POOLS.forEach((pool) => pools.set(pool.id, pool as Pool)); +const poolProvider = findable(pools); const tokenPriceProvider = new StaticTokenPriceProvider(tokenPrices); const liquidity = new Liquidity(poolProvider, tokenPriceProvider); diff --git a/balancer-js/examples/pools/liquidity.ts b/balancer-js/examples/pools/liquidity.ts new file mode 100644 index 000000000..f207e8714 --- /dev/null +++ b/balancer-js/examples/pools/liquidity.ts @@ -0,0 +1,22 @@ +import { BalancerSDK } from '../../src'; + +const sdk = new BalancerSDK({ + network: 1, + rpcUrl: 'https://eth-rpc.gateway.pokt.network', +}); + +const { pools } = sdk; + +const main = async () => { + [ + '0xa13a9247ea42d743238089903570127dda72fe4400000000000000000000035d', + ].forEach(async (poolId) => { + const pool = await pools.find(poolId); + if (pool) { + const liquidity = await pools.liquidity(pool); + console.log(pool.totalShares, pool.totalLiquidity, liquidity); + } + }); +}; + +main(); diff --git a/balancer-js/src/modules/data/index.ts b/balancer-js/src/modules/data/index.ts index f92ccdfc0..ea0de215a 100644 --- a/balancer-js/src/modules/data/index.ts +++ b/balancer-js/src/modules/data/index.ts @@ -13,7 +13,11 @@ export * from './block-number'; import { BalancerNetworkConfig, BalancerDataRepositories } from '@/types'; import { PoolsSubgraphRepository } from './pool/subgraph'; import { BlockNumberRepository } from './block-number'; -import { CoingeckoPriceRepository } from './token-prices/coingecko'; +import { + CoingeckoPriceRepository, + AaveRates, + TokenPriceProvider, +} from './token-prices'; import { StaticTokenProvider } from './token/static'; import { LiquidityGaugeSubgraphRPCProvider } from './liquidity-gauges/provider'; import { FeeDistributorRepository } from './fee-distributor/repository'; @@ -68,11 +72,18 @@ export class Data implements BalancerDataRepositories { .filter((t) => t.chainId == networkConfig.chainId) .map((t) => t.address); - this.tokenPrices = new CoingeckoPriceRepository( + const coingeckoRepository = new CoingeckoPriceRepository( tokenAddresses, networkConfig.chainId ); + const aaveRates = new AaveRates( + networkConfig.addresses.contracts.multicall, + provider + ); + + this.tokenPrices = new TokenPriceProvider(coingeckoRepository, aaveRates); + this.tokenMeta = new StaticTokenProvider([]); if (networkConfig.urls.gaugesSubgraph) { diff --git a/balancer-js/src/modules/data/token-prices/aave-rates.ts b/balancer-js/src/modules/data/token-prices/aave-rates.ts new file mode 100644 index 000000000..bd449ae8f --- /dev/null +++ b/balancer-js/src/modules/data/token-prices/aave-rates.ts @@ -0,0 +1,45 @@ +import { Interface } from '@ethersproject/abi'; +import { Contract } from '@ethersproject/contracts'; +import { Provider } from '@ethersproject/providers'; +import { formatUnits } from '@ethersproject/units'; +import { Multicall } from '@/modules/contracts/multicall'; +import { yieldTokens } from '../token-yields/tokens/aave'; + +const wrappedATokenInterface = new Interface([ + 'function rate() view returns (uint256)', +]); + +export class AaveRates { + multicall: Contract; + rates?: Promise<{ [wrappedATokenAddress: string]: number }>; + + constructor(multicallAddress: string, provider: Provider) { + this.multicall = Multicall(multicallAddress, provider); + } + + private async fetch(): Promise<{ [wrappedATokenAddress: string]: number }> { + console.time('Fetching aave rates'); + const addresses = Object.values(yieldTokens); + const payload = addresses.map((wrappedATokenAddress) => [ + wrappedATokenAddress, + wrappedATokenInterface.encodeFunctionData('rate', []), + ]); + const [, res] = await this.multicall.aggregate(payload); + + const rates = addresses.reduce((p: { [key: string]: number }, a, i) => { + p[a] ||= parseFloat(formatUnits(res[i], 27)); + return p; + }, {}); + console.timeEnd('Fetching aave rates'); + + return rates; + } + + async getRate(wrappedAToken: string): Promise { + if (!this.rates) { + this.rates = this.fetch(); + } + + return (await this.rates)[wrappedAToken]; + } +} diff --git a/balancer-js/src/modules/data/token-prices/index.ts b/balancer-js/src/modules/data/token-prices/index.ts index 6390e116a..61defd9af 100644 --- a/balancer-js/src/modules/data/token-prices/index.ts +++ b/balancer-js/src/modules/data/token-prices/index.ts @@ -1,2 +1,4 @@ export * from './static'; export * from './coingecko'; +export * from './provider'; +export * from './aave-rates'; diff --git a/balancer-js/src/modules/data/token-prices/provider.ts b/balancer-js/src/modules/data/token-prices/provider.ts new file mode 100644 index 000000000..79138f138 --- /dev/null +++ b/balancer-js/src/modules/data/token-prices/provider.ts @@ -0,0 +1,31 @@ +import type { Findable, Price } from '@/types'; +import { AaveRates } from './aave-rates'; +import { CoingeckoPriceRepository } from './coingecko'; + +export class TokenPriceProvider implements Findable { + constructor( + private coingeckoRepository: CoingeckoPriceRepository, + private aaveRates: AaveRates + ) {} + + async find(address: string): Promise { + const price = await this.coingeckoRepository.find(address); + const rate = (await this.aaveRates.getRate(address)) || 1; + if (price && price.usd) { + return { + ...price, + usd: (parseFloat(price.usd) * rate).toString(), + }; + } else { + return price; + } + } + + async findBy(attribute: string, value: string): Promise { + if (attribute === 'address') { + return this.find(value); + } else { + throw `Token price search by ${attribute} not implemented`; + } + } +} From b2cbc1d26a6bc1f91b2c4f5eab7788f2e98c2205 Mon Sep 17 00:00:00 2001 From: bronco Date: Thu, 6 Oct 2022 22:16:56 +0200 Subject: [PATCH 13/14] version bump --- balancer-js/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/balancer-js/package.json b/balancer-js/package.json index bb9aa2923..1691b082e 100644 --- a/balancer-js/package.json +++ b/balancer-js/package.json @@ -1,6 +1,6 @@ { "name": "@balancer-labs/sdk", - "version": "0.1.26", + "version": "0.1.27", "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", From 1f02c346a64d0de8fcb2c0209ca718b7e96b0e2d Mon Sep 17 00:00:00 2001 From: bronco Date: Thu, 6 Oct 2022 22:23:04 +0200 Subject: [PATCH 14/14] aave-rates fix for polygon --- balancer-js/src/modules/data/token-prices/aave-rates.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/balancer-js/src/modules/data/token-prices/aave-rates.ts b/balancer-js/src/modules/data/token-prices/aave-rates.ts index bd449ae8f..25329bae9 100644 --- a/balancer-js/src/modules/data/token-prices/aave-rates.ts +++ b/balancer-js/src/modules/data/token-prices/aave-rates.ts @@ -27,7 +27,7 @@ export class AaveRates { const [, res] = await this.multicall.aggregate(payload); const rates = addresses.reduce((p: { [key: string]: number }, a, i) => { - p[a] ||= parseFloat(formatUnits(res[i], 27)); + p[a] ||= res[i] == '0x' ? 0 : parseFloat(formatUnits(res[i], 27)); return p; }, {}); console.timeEnd('Fetching aave rates');