From 5e6bcd496723601e22fe31d1f8ece4d4d7eda456 Mon Sep 17 00:00:00 2001 From: franz Date: Fri, 10 Nov 2023 16:08:17 +0100 Subject: [PATCH 01/44] change fantom rpc --- modules/network/fantom.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/network/fantom.ts b/modules/network/fantom.ts index 38ba6a11c..585731b16 100644 --- a/modules/network/fantom.ts +++ b/modules/network/fantom.ts @@ -94,9 +94,7 @@ const fantomNetworkData: NetworkData = { maxHourlyPriceHistoryNumDays: 100, }, rpcUrl: - (env.DEPLOYMENT_ENV as DeploymentEnv) === 'main' - ? `https://rpc.fantom.gateway.fm` - : `https://rpc.fantom.network`, + (env.DEPLOYMENT_ENV as DeploymentEnv) === 'main' ? `https://rpc.fantom.network` : `https://rpc.fantom.network`, rpcMaxBlockRange: 1000, sanity: { projectId: '1g2ag2hb', From 9e0c6e04377d4e30266ecc6c0d7174ddf1c451d5 Mon Sep 17 00:00:00 2001 From: gmbronco <83549293+gmbronco@users.noreply.github.com> Date: Mon, 20 Nov 2023 05:36:21 +0100 Subject: [PATCH 02/44] fix: beetswars apr --- .../apr-data-sources/fantom/beetswars-gauge-voting-apr.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/pool/lib/apr-data-sources/fantom/beetswars-gauge-voting-apr.ts b/modules/pool/lib/apr-data-sources/fantom/beetswars-gauge-voting-apr.ts index 676bbcc97..93af8076b 100644 --- a/modules/pool/lib/apr-data-sources/fantom/beetswars-gauge-voting-apr.ts +++ b/modules/pool/lib/apr-data-sources/fantom/beetswars-gauge-voting-apr.ts @@ -20,7 +20,10 @@ export class BeetswarsGaugeVotingAprService implements PoolAprService { const response = await axios.get('https://www.beetswars.live/api/trpc/chart.chartdata'); - const votingAprs: number[] = response.data.result.data.json.chartdata.votingApr; + const raw: number[] = response.data.result.data.json.chartdata.votingApr; + + // Filter out non-numbers and infinity values + const votingAprs = raw.filter((apr) => apr && isFinite(apr)); const minApr = 0; const maxApr = votingAprs[votingAprs.length - 1] / 100; From 1757da088ef58a4fe1802569dbd91220e2ef7679 Mon Sep 17 00:00:00 2001 From: franz Date: Mon, 20 Nov 2023 18:31:47 +0100 Subject: [PATCH 03/44] add composable --- modules/pool/pool.gql | 1 + modules/pool/pool.prisma | 1 + .../20231120163312_add_composablestable_pooltype/migration.sql | 2 ++ prisma/schema.prisma | 1 + 4 files changed, 5 insertions(+) create mode 100644 prisma/migrations/20231120163312_add_composablestable_pooltype/migration.sql diff --git a/modules/pool/pool.gql b/modules/pool/pool.gql index 219dea792..fc6aab4ca 100644 --- a/modules/pool/pool.gql +++ b/modules/pool/pool.gql @@ -82,6 +82,7 @@ enum GqlPoolMinimalType { STABLE META_STABLE PHANTOM_STABLE + COMPOSABLE_STABLE ELEMENT LINEAR UNKNOWN diff --git a/modules/pool/pool.prisma b/modules/pool/pool.prisma index 16767b4df..fa2c8bb8c 100644 --- a/modules/pool/pool.prisma +++ b/modules/pool/pool.prisma @@ -47,6 +47,7 @@ enum PrismaPoolType { STABLE META_STABLE PHANTOM_STABLE + COMPOSABLE_STABLE ELEMENT LINEAR UNKNOWN diff --git a/prisma/migrations/20231120163312_add_composablestable_pooltype/migration.sql b/prisma/migrations/20231120163312_add_composablestable_pooltype/migration.sql new file mode 100644 index 000000000..78f3ee0b4 --- /dev/null +++ b/prisma/migrations/20231120163312_add_composablestable_pooltype/migration.sql @@ -0,0 +1,2 @@ +-- AlterEnum +ALTER TYPE "PrismaPoolType" ADD VALUE 'COMPOSABLE_STABLE'; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 9ec3e38d1..2f56c2e23 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -93,6 +93,7 @@ enum PrismaPoolType { STABLE META_STABLE PHANTOM_STABLE + COMPOSABLE_STABLE ELEMENT LINEAR UNKNOWN From f8b4f52c61472595c82429227e2868650bd50861 Mon Sep 17 00:00:00 2001 From: franz Date: Mon, 20 Nov 2023 18:45:29 +0100 Subject: [PATCH 04/44] exlcude tru matic --- modules/network/mainnet.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/modules/network/mainnet.ts b/modules/network/mainnet.ts index 8e77f13ff..986c83a63 100644 --- a/modules/network/mainnet.ts +++ b/modules/network/mainnet.ts @@ -57,7 +57,7 @@ const data: NetworkData = { coingecko: { nativeAssetId: 'ethereum', platformId: 'ethereum', - excludedTokenAddresses: [], + excludedTokenAddresses: ['0xa43a7c62d56df036c187e1966c03e2799d8987ed'], // truMatic, has coingecko entry but no price }, tokenPrices: { maxHourlyPriceHistoryNumDays: 100, @@ -378,10 +378,7 @@ export const mainnetNetworkConfig: NetworkConfig = { data.balancer.yieldProtocolFeePercentage, data.balancer.swapProtocolFeePercentage, ), - new PhantomStableAprService( - data.chain.prismaId, - data.balancer.yieldProtocolFeePercentage, - ), + new PhantomStableAprService(data.chain.prismaId, data.balancer.yieldProtocolFeePercentage), new BoostedPoolAprService(), new SwapFeeAprService(data.balancer.swapProtocolFeePercentage), new GaugeAprService(tokenService, [data.bal!.address]), From 4943f8736827a3147d7ab848d1cbbb49a748c52e Mon Sep 17 00:00:00 2001 From: franz Date: Tue, 21 Nov 2023 10:35:34 +0100 Subject: [PATCH 05/44] only exposing composable stable at query --- modules/pool/lib/pool-gql-loader.service.ts | 35 +++++++++++---------- modules/pool/pool.gql | 25 +++++++-------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/modules/pool/lib/pool-gql-loader.service.ts b/modules/pool/lib/pool-gql-loader.service.ts index 4d965269e..ec211a6d5 100644 --- a/modules/pool/lib/pool-gql-loader.service.ts +++ b/modules/pool/lib/pool-gql-loader.service.ts @@ -20,7 +20,7 @@ import { GqlPoolLinearNested, GqlPoolMinimal, GqlPoolNestingType, - GqlPoolPhantomStableNested, + GqlPoolComposableStableNested, GqlPoolStaking, GqlPoolToken, GqlPoolTokenDisplay, @@ -34,7 +34,7 @@ import { import { isSameAddress } from '@balancer-labs/sdk'; import _ from 'lodash'; import { prisma } from '../../../prisma/prisma-client'; -import { Chain, Prisma, PrismaPoolAprType } from '@prisma/client'; +import { Chain, Prisma, PrismaPoolAprType, PrismaPoolType } from '@prisma/client'; import { isWeightedPoolV2 } from './pool-utils'; import { oldBnum } from '../../big-number/old-big-number'; import { networkContext } from '../../network/network-context.service'; @@ -80,6 +80,7 @@ export class PoolGqlLoaderService { public mapToMinimalGqlPool(pool: PrismaPoolMinimal): GqlPoolMinimal { return { ...pool, + type: pool.type === 'PHANTOM_STABLE' ? PrismaPoolType.COMPOSABLE_STABLE : pool.type, decimals: 18, dynamicData: this.getPoolDynamicData(pool), allTokens: this.mapAllTokens(pool), @@ -380,9 +381,9 @@ export class PoolGqlLoaderService { amp: pool.stableDynamicData?.amp || '0', tokens: mappedData.tokens as GqlPoolToken[], }; - case 'PHANTOM_STABLE': + case 'COMPOSABLE_STABLE': return { - __typename: 'GqlPoolPhantomStable', + __typename: 'GqlPoolComposableStable', ...mappedData, amp: pool.stableDynamicData?.amp || '0', bptPriceRate: bpt?.dynamicData?.priceRate || '1.0', @@ -488,7 +489,7 @@ export class PoolGqlLoaderService { weight: poolToken?.dynamicData?.weight, }; } - } else if (allToken.nestedPool?.type === 'PHANTOM_STABLE') { + } else if (allToken.nestedPool?.type === 'COMPOSABLE_STABLE') { const mainTokens = allToken.nestedPool.allTokens.filter( (nestedToken) => @@ -806,7 +807,7 @@ export class PoolGqlLoaderService { private getPoolInvestConfig(pool: PrismaPoolWithExpandedNesting): GqlPoolInvestConfig { const poolTokens = pool.tokens.filter((token) => token.address !== pool.address); - const supportsNativeAssetDeposit = pool.type !== 'PHANTOM_STABLE'; + const supportsNativeAssetDeposit = pool.type !== 'COMPOSABLE_STABLE'; let options: GqlPoolInvestOption[] = []; for (const poolToken of poolTokens) { @@ -815,7 +816,7 @@ export class PoolGqlLoaderService { return { //TODO could flag these as disabled in sanity - proportionalEnabled: pool.type !== 'PHANTOM_STABLE' && pool.type !== 'META_STABLE', + proportionalEnabled: pool.type !== 'COMPOSABLE_STABLE' && pool.type !== 'META_STABLE', singleAssetEnabled: true, options, }; @@ -871,11 +872,11 @@ export class PoolGqlLoaderService { ] : [this.mapPoolTokenToGql(mainToken)], }); - } else if (nestedPool && nestedPool.type === 'PHANTOM_STABLE') { + } else if (nestedPool && nestedPool.type === 'COMPOSABLE_STABLE') { const nestedTokens = nestedPool.tokens.filter((token) => token.address !== nestedPool.address); - if (pool.type === 'PHANTOM_STABLE' || isWeightedPoolV2(pool)) { - //when nesting a phantom stable inside a phantom stable, all of the underlying tokens can be used when investing + if (pool.type === 'COMPOSABLE_STABLE' || isWeightedPoolV2(pool)) { + //when nesting a composable stable inside a composable stable, all of the underlying tokens can be used when investing //when withdrawing from a v2 weighted pool, we withdraw into all underlying assets. // ie: USDC/DAI/USDT for nested bbaUSD for (const nestedToken of nestedTokens) { @@ -895,7 +896,7 @@ export class PoolGqlLoaderService { }); } } else { - //if the parent pool does not have phantom bpt (ie: weighted), the user can only invest with 1 of the phantom stable tokens + //if the parent pool does not have phantom bpt (ie: weighted), the user can only invest with 1 of the composable stable tokens options.push({ poolTokenIndex: poolToken.index, poolTokenAddress: poolToken.address, @@ -956,7 +957,7 @@ export class PoolGqlLoaderService { ...this.getLinearPoolTokenData(token, nestedPool), pool: this.mapNestedPoolToGqlPoolLinearNested(nestedPool, percentOfSupplyNested), }; - } else if (nestedPool && nestedPool.type === 'PHANTOM_STABLE') { + } else if (nestedPool && nestedPool.type === 'COMPOSABLE_STABLE') { const totalShares = parseFloat(nestedPool.dynamicData?.totalShares || '0'); const percentOfSupplyNested = totalShares > 0 ? parseFloat(token.dynamicData?.balance || '0') / totalShares : 0; @@ -964,8 +965,8 @@ export class PoolGqlLoaderService { //50_000_000_000_000 return { ...this.mapPoolTokenToGql(token), - __typename: 'GqlPoolTokenPhantomStable', - pool: this.mapNestedPoolToGqlPoolPhantomStableNested(nestedPool, percentOfSupplyNested), + __typename: 'GqlPoolTokenComposableStable', + pool: this.mapNestedPoolToGqlPoolComposableStableNested(nestedPool, percentOfSupplyNested), }; } @@ -1019,14 +1020,14 @@ export class PoolGqlLoaderService { }; } - private mapNestedPoolToGqlPoolPhantomStableNested( + private mapNestedPoolToGqlPoolComposableStableNested( pool: PrismaNestedPoolWithSingleLayerNesting, percentOfSupplyNested: number, - ): GqlPoolPhantomStableNested { + ): GqlPoolComposableStableNested { const bpt = pool.tokens.find((token) => token.address === pool.address); return { - __typename: 'GqlPoolPhantomStableNested', + __typename: 'GqlPoolComposableStableNested', ...pool, nestingType: this.getPoolNestingType(pool), tokens: pool.tokens.map((token) => { diff --git a/modules/pool/pool.gql b/modules/pool/pool.gql index fc6aab4ca..87332397f 100644 --- a/modules/pool/pool.gql +++ b/modules/pool/pool.gql @@ -81,7 +81,6 @@ enum GqlPoolMinimalType { WEIGHTED STABLE META_STABLE - PHANTOM_STABLE COMPOSABLE_STABLE ELEMENT LINEAR @@ -177,7 +176,7 @@ type GqlPoolInvestOption { # we use an array here for invest options where there are more than one option, but only one can be selected # - FTM/wFTM or ETH/wETH - # - weighted boosted with nested phantom stable (bb-yv-USD) where you can only invest with DAI or USDC, not both at the same time + # - weighted boosted with nested composable stable (bb-yv-USD) where you can only invest with DAI or USDC, not both at the same time tokenOptions: [GqlPoolToken!]! } @@ -318,7 +317,7 @@ type GqlPoolMetaStable implements GqlPoolBase { version: Int! } -type GqlPoolPhantomStable implements GqlPoolBase { +type GqlPoolComposableStable implements GqlPoolBase { id: ID! chain: GqlChain! name: String! @@ -420,7 +419,7 @@ type GqlPoolLinearNested { version: Int! } -type GqlPoolPhantomStableNested { +type GqlPoolComposableStableNested { id: ID! name: String! symbol: String! @@ -428,7 +427,7 @@ type GqlPoolPhantomStableNested { owner: Bytes! factory: Bytes createTime: Int! - tokens: [GqlPoolTokenPhantomStableNestedUnion!]! + tokens: [GqlPoolTokenComposableStableNestedUnion!]! nestingType: GqlPoolNestingType! totalShares: BigDecimal! @@ -446,14 +445,14 @@ union GqlPoolUnion = | GqlPoolStable | GqlPoolMetaStable | GqlPoolLinear - | GqlPoolPhantomStable + | GqlPoolComposableStable | GqlPoolElement | GqlPoolLiquidityBootstrapping | GqlPoolGyro -union GqlPoolNestedUnion = GqlPoolLinearNested | GqlPoolPhantomStableNested +union GqlPoolNestedUnion = GqlPoolLinearNested | GqlPoolComposableStableNested -union GqlPoolTokenUnion = GqlPoolToken | GqlPoolTokenPhantomStable | GqlPoolTokenLinear -union GqlPoolTokenPhantomStableNestedUnion = GqlPoolToken | GqlPoolTokenLinear +union GqlPoolTokenUnion = GqlPoolToken | GqlPoolTokenComposableStable | GqlPoolTokenLinear +union GqlPoolTokenComposableStableNestedUnion = GqlPoolToken | GqlPoolTokenLinear interface GqlPoolTokenBase { id: ID! @@ -505,7 +504,7 @@ type GqlPoolTokenLinear implements GqlPoolTokenBase { totalBalance: BigDecimal! } -type GqlPoolTokenPhantomStable implements GqlPoolTokenBase { +type GqlPoolTokenComposableStable implements GqlPoolTokenBase { id: ID! address: String! balance: BigDecimal! @@ -518,7 +517,7 @@ type GqlPoolTokenPhantomStable implements GqlPoolTokenBase { #the total balance in the pool, regardless of nesting totalBalance: BigDecimal! - pool: GqlPoolPhantomStableNested! + pool: GqlPoolComposableStableNested! } type GqlPoolLinearPoolData { @@ -535,7 +534,7 @@ type GqlPoolLinearPoolData { mainTokenTotalBalance: String! } -type GqlPoolStablePhantomPoolData { +type GqlPoolStableComposablePoolData { id: ID! address: String! symbol: String! @@ -629,7 +628,7 @@ enum GqlPoolFilterType { WEIGHTED STABLE META_STABLE - PHANTOM_STABLE + COMPOSABLE_STABLE ELEMENT LINEAR UNKNOWN From 1b2d0e7db2a336d566bd18cd80467644e1e765e6 Mon Sep 17 00:00:00 2001 From: franz Date: Tue, 21 Nov 2023 10:50:24 +0100 Subject: [PATCH 06/44] pool creation phantom stable as composable stable v0 --- modules/pool/lib/pool-creator.service.ts | 31 +++++++++++++++--------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/modules/pool/lib/pool-creator.service.ts b/modules/pool/lib/pool-creator.service.ts index fb22dc4fb..46c16d490 100644 --- a/modules/pool/lib/pool-creator.service.ts +++ b/modules/pool/lib/pool-creator.service.ts @@ -88,7 +88,9 @@ export class PoolCreatorService { const nestedPool = subgraphPools.find((nestedPool) => { const poolType = this.mapSubgraphPoolTypeToPoolType(nestedPool.poolType || ''); - return nestedPool.address === token.address && (poolType === 'LINEAR' || poolType === 'PHANTOM_STABLE'); + return ( + nestedPool.address === token.address && (poolType === 'LINEAR' || poolType === 'COMPOSABLE_STABLE') + ); }); if (nestedPool) { @@ -160,7 +162,7 @@ export class PoolCreatorService { const allNestedTypePools = await prisma.prismaPool.findMany({ where: { chain: networkContext.chain, - type: { in: [PrismaPoolType.LINEAR, PrismaPoolType.PHANTOM_STABLE] }, + type: { in: [PrismaPoolType.LINEAR, PrismaPoolType.COMPOSABLE_STABLE] }, }, select: { id: true, address: true }, }); @@ -185,6 +187,12 @@ export class PoolCreatorService { ], }); + // for the old phantom stable pool, we add it to the DB as type COMPOSABLE_STABLE with version 0 + let poolTypeVersion = pool.poolTypeVersion ? pool.poolTypeVersion : 1; + if (pool.poolType === 'PHANTOM_STABLE') { + poolTypeVersion = 0; + } + await prisma.prismaPool.create({ data: { id: pool.id, @@ -195,7 +203,7 @@ export class PoolCreatorService { name: pool.name || '', decimals: 18, type: poolType, - version: pool.poolTypeVersion ? pool.poolTypeVersion : 1, + version: poolTypeVersion, owner: pool.owner || ZERO_ADDRESS, factory: pool.factory, tokens: { @@ -256,7 +264,7 @@ export class PoolCreatorService { } : undefined, stableDynamicData: - poolType === 'STABLE' || poolType === 'PHANTOM_STABLE' || poolType === 'META_STABLE' + poolType === 'STABLE' || poolType === 'COMPOSABLE_STABLE' || poolType === 'META_STABLE' ? { create: { id: pool.id, @@ -364,9 +372,9 @@ export class PoolCreatorService { if (poolType === 'LINEAR') { return 0; - } else if (poolType === 'PHANTOM_STABLE') { - //if the phantom stable has a nested phantom stable, it needs to appear later in the list - const nestedPhantomStableToken = (pool.tokens || []).find((token) => { + } else if (poolType === 'COMPOSABLE_STABLE') { + //if the composable stable has a nested composable stable, it needs to appear later in the list + const nestedComposableStableToken = (pool.tokens || []).find((token) => { if (token.address === pool.address) { return false; } @@ -374,10 +382,10 @@ export class PoolCreatorService { const nestedPool = subgraphPools.find((nestedPool) => nestedPool.address === token.address); const nestedPoolType = this.mapSubgraphPoolTypeToPoolType(nestedPool?.poolType || ''); - return nestedPoolType === 'PHANTOM_STABLE'; + return nestedPoolType === 'COMPOSABLE_STABLE'; }); - return nestedPhantomStableToken ? 2 : 1; + return nestedComposableStableToken ? 2 : 1; } return 3; @@ -394,10 +402,11 @@ export class PoolCreatorService { return 'STABLE'; case 'MetaStable': return 'META_STABLE'; + // for the old phantom stable pool, we add it to the DB as type COMPOSABLE_STABLE with version 0 case 'StablePhantom': - return 'PHANTOM_STABLE'; + return 'COMPOSABLE_STABLE'; case 'ComposableStable': - return 'PHANTOM_STABLE'; + return 'COMPOSABLE_STABLE'; case 'Linear': return 'LINEAR'; case 'Element': From 991e36a2b9a5f5a17526bfb1b8df6e4f637c9e0f Mon Sep 17 00:00:00 2001 From: franz Date: Tue, 21 Nov 2023 10:51:50 +0100 Subject: [PATCH 07/44] add comment --- modules/pool/lib/pool-gql-loader.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/pool/lib/pool-gql-loader.service.ts b/modules/pool/lib/pool-gql-loader.service.ts index ec211a6d5..3440b4168 100644 --- a/modules/pool/lib/pool-gql-loader.service.ts +++ b/modules/pool/lib/pool-gql-loader.service.ts @@ -80,6 +80,7 @@ export class PoolGqlLoaderService { public mapToMinimalGqlPool(pool: PrismaPoolMinimal): GqlPoolMinimal { return { ...pool, + // we need this mapping because we migrated from PHANTOMSTABLE type to COMPOSABLESTABLE in the DB, but now only return COMPOSABLESTABLE type: pool.type === 'PHANTOM_STABLE' ? PrismaPoolType.COMPOSABLE_STABLE : pool.type, decimals: 18, dynamicData: this.getPoolDynamicData(pool), From 84c236e9dba81eb82eecb39dc4bf9c8159b7333b Mon Sep 17 00:00:00 2001 From: franz Date: Tue, 21 Nov 2023 11:03:12 +0100 Subject: [PATCH 08/44] add update mutation --- modules/pool/lib/pool-creator.service.ts | 36 ++++++++++++++++++++++++ modules/pool/pool.gql | 2 +- modules/pool/pool.resolvers.ts | 4 +-- modules/pool/pool.service.ts | 20 ++----------- 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/modules/pool/lib/pool-creator.service.ts b/modules/pool/lib/pool-creator.service.ts index 46c16d490..e9c68111e 100644 --- a/modules/pool/lib/pool-creator.service.ts +++ b/modules/pool/lib/pool-creator.service.ts @@ -366,6 +366,42 @@ export class PoolCreatorService { } } + public async updatePoolTypesAndVersionForAllPools() { + const subgraphPools = await this.balancerSubgraphService.getAllPools({}, false); + + for (const subgraphPool of subgraphPools) { + // for the old phantom stable pool, we add it to the DB as type COMPOSABLE_STABLE with version 0 + let poolTypeVersion = subgraphPool.poolTypeVersion ? subgraphPool.poolTypeVersion : 1; + if (subgraphPool.poolType === 'PHANTOM_STABLE') { + poolTypeVersion = 0; + } + + const poolType = this.mapSubgraphPoolTypeToPoolType(subgraphPool.poolType || ''); + + try { + await prisma.prismaPool.update({ + where: { id_chain: { chain: networkContext.chain, id: subgraphPool.id } }, + data: { + version: poolTypeVersion, + type: poolType, + }, + }); + } catch (e: any) { + // Some pools are filtered from the DB, like test pools, + // so we just ignore them without breaking the loop + const error = e.meta ? e.meta.cause : e; + console.error( + 'Error in updating pool versions: ', + error, + 'Network', + networkContext.chain, + 'Pool ID: ', + subgraphPool.id, + ); + } + } + } + private sortSubgraphPools(subgraphPools: BalancerPoolFragment[]) { return _.sortBy(subgraphPools, (pool) => { const poolType = this.mapSubgraphPoolTypeToPoolType(pool.poolType || ''); diff --git a/modules/pool/pool.gql b/modules/pool/pool.gql index 87332397f..cc3ca9675 100644 --- a/modules/pool/pool.gql +++ b/modules/pool/pool.gql @@ -54,7 +54,7 @@ extend type Mutation { poolBlackListAddPool(poolId: String!): String! poolBlackListRemovePool(poolId: String!): String! poolDeletePool(poolId: String!): String! - poolSyncAllPoolVersions: String! + poolSyncAllPoolTypesVersions: String! poolInitOnChainDataForAllPools: String! } diff --git a/modules/pool/pool.resolvers.ts b/modules/pool/pool.resolvers.ts index e9fe7431b..9edbe1cfd 100644 --- a/modules/pool/pool.resolvers.ts +++ b/modules/pool/pool.resolvers.ts @@ -313,10 +313,10 @@ const balancerResolvers: Resolvers = { return 'success'; }, - poolSyncAllPoolVersions: async (parent, {}, context) => { + poolSyncAllPoolTypesVersions: async (parent, {}, context) => { isAdminRoute(context); - await poolService.syncPoolVersionForAllPools(); + await poolService.syncPoolTypeAndVersionForAllPools(); return 'success'; }, diff --git a/modules/pool/pool.service.ts b/modules/pool/pool.service.ts index ae54c3e2b..5555bdbc4 100644 --- a/modules/pool/pool.service.ts +++ b/modules/pool/pool.service.ts @@ -353,24 +353,8 @@ export class PoolService { await this.poolSyncService.setPoolsWithPreferredGaugesAsIncentivized(); } - public async syncPoolVersionForAllPools() { - const subgraphPools = await this.balancerSubgraphService.getAllPools({}, false); - - for (const subgraphPool of subgraphPools) { - try { - await prisma.prismaPool.update({ - where: { id_chain: { chain: this.chain, id: subgraphPool.id } }, - data: { - version: subgraphPool.poolTypeVersion ? subgraphPool.poolTypeVersion : 1, - }, - }); - } catch (e: any) { - // Some pools are filtered from the DB, like test pools, - // so we just ignore them without breaking the loop - const error = e.meta ? e.meta.cause : e; - console.error(error, 'Network', networkContext.chain, 'Pool ID: ', subgraphPool.id); - } - } + public async syncPoolTypeAndVersionForAllPools() { + await this.poolCreatorService.updatePoolTypesAndVersionForAllPools(); } public async addToBlackList(poolId: string) { From 32f5898da7787a7d61125b6f32484b6d0879c82e Mon Sep 17 00:00:00 2001 From: franz Date: Tue, 21 Nov 2023 11:12:12 +0100 Subject: [PATCH 09/44] get rid of factory tracking --- modules/network/arbitrum.ts | 17 ++++--------- modules/network/avalanche.ts | 13 ++++------ modules/network/base.ts | 7 +++--- modules/network/fantom.ts | 24 ++++--------------- modules/network/gnosis.ts | 16 ++++--------- modules/network/mainnet.ts | 19 +-------------- modules/network/network-config-types.ts | 4 ---- modules/network/optimism.ts | 16 ++++--------- modules/network/polygon.ts | 17 ++++--------- modules/network/zkevm.ts | 11 ++++----- .../pool/lib/pool-on-chain-data.service.ts | 10 ++------ modules/pool/lib/pool-utils.ts | 17 ++----------- 12 files changed, 37 insertions(+), 134 deletions(-) diff --git a/modules/network/arbitrum.ts b/modules/network/arbitrum.ts index 20bb523f5..e4fedf51b 100644 --- a/modules/network/arbitrum.ts +++ b/modules/network/arbitrum.ts @@ -72,18 +72,6 @@ const arbitrumNetworkData: NetworkData = { }, balancer: { vault: '0xba12222222228d8ba445958a75a0704d566bf2c8', - composableStablePoolFactories: [ - '0xaeb406b0e430bf5ea2dc0b9fe62e4e53f74b3a33', - '0x85a80afee867adf27b50bdb7b76da70f1e853062', - '0x1c99324edc771c82a0dccb780cc7dda0045e50e7', - '0x2498a2b0d6462d2260eac50ae1c3e03f4829ba95', - '0xa8920455934da4d853faac1f94fe7bef72943ef1', - ], - weightedPoolV2Factories: [ - '0x8df6efec5547e31b0eb7d1291b511ff8a2bf987c', - '0xf1665e19bc105be4edd3739f88315cc699cc5b65', - '0xc7e5ed1054a24ef31d827e6f86caa58b3bc168d7', - ], swapProtocolFeePercentage: 0.5, yieldProtocolFeePercentage: 0.5, }, @@ -251,7 +239,10 @@ export const arbitrumNetworkConfig: NetworkConfig = { ], userStakedBalanceServices: [new UserSyncGaugeBalanceService()], services: { - balancerSubgraphService: new BalancerSubgraphService(arbitrumNetworkData.subgraphs.balancer, arbitrumNetworkData.chain.id), + balancerSubgraphService: new BalancerSubgraphService( + arbitrumNetworkData.subgraphs.balancer, + arbitrumNetworkData.chain.id, + ), }, /* For sub-minute jobs we set the alarmEvaluationPeriod and alarmDatapointsToAlarm to 1 instead of the default 3. diff --git a/modules/network/avalanche.ts b/modules/network/avalanche.ts index f696e5005..b93ee348b 100644 --- a/modules/network/avalanche.ts +++ b/modules/network/avalanche.ts @@ -70,14 +70,6 @@ const avalancheNetworkData: NetworkData = { }, balancer: { vault: '0xba12222222228d8ba445958a75a0704d566bf2c8', - composableStablePoolFactories: [ - '0x3b1eb8eb7b43882b385ab30533d9a2bef9052a98', - '0xe42ffa682a26ef8f25891db4882932711d42e467', - ], - weightedPoolV2Factories: [ - '0x94f68b54191f62f781fe8298a8a5fa3ed772d227', - '0x230a59f4d9adc147480f03b0d3fffecd56c3289a', - ], swapProtocolFeePercentage: 0.5, yieldProtocolFeePercentage: 0.5, }, @@ -241,7 +233,10 @@ export const avalancheNetworkConfig: NetworkConfig = { ], userStakedBalanceServices: [new UserSyncGaugeBalanceService()], services: { - balancerSubgraphService: new BalancerSubgraphService(avalancheNetworkData.subgraphs.balancer, avalancheNetworkData.chain.id), + balancerSubgraphService: new BalancerSubgraphService( + avalancheNetworkData.subgraphs.balancer, + avalancheNetworkData.chain.id, + ), }, /* For sub-minute jobs we set the alarmEvaluationPeriod and alarmDatapointsToAlarm to 1 instead of the default 3. diff --git a/modules/network/base.ts b/modules/network/base.ts index c25d9b91e..be69466e9 100644 --- a/modules/network/base.ts +++ b/modules/network/base.ts @@ -70,8 +70,6 @@ const baseNetworkData: NetworkData = { }, balancer: { vault: '0xba12222222228d8ba445958a75a0704d566bf2c8', - composableStablePoolFactories: ['0x8df317a729fcaa260306d7de28888932cb579b88'], - weightedPoolV2Factories: ['0x4c32a8a8fda4e24139b51b456b42290f51d6a1c4'], swapProtocolFeePercentage: 0.5, yieldProtocolFeePercentage: 0.5, }, @@ -139,7 +137,10 @@ export const baseNetworkConfig: NetworkConfig = { ], userStakedBalanceServices: [new UserSyncGaugeBalanceService()], services: { - balancerSubgraphService: new BalancerSubgraphService(baseNetworkData.subgraphs.balancer, baseNetworkData.chain.id), + balancerSubgraphService: new BalancerSubgraphService( + baseNetworkData.subgraphs.balancer, + baseNetworkData.chain.id, + ), }, /* For sub-minute jobs we set the alarmEvaluationPeriod and alarmDatapointsToAlarm to 1 instead of the default 3. diff --git a/modules/network/fantom.ts b/modules/network/fantom.ts index a266d331c..0bd2f7bd5 100644 --- a/modules/network/fantom.ts +++ b/modules/network/fantom.ts @@ -116,27 +116,8 @@ const fantomNetworkData: NetworkData = { }, balancer: { vault: '0x20dd72ed959b6147912c2e529f0a0c651c33c9ce', - composableStablePoolFactories: [ - '0x5adaf6509bcec3219455348ac45d6d3261b1a990', - '0xb384a86f2fd7788720db42f9daa60fc07ecbea06', - '0x44814e3a603bb7f1198617995c5696c232f6e8ed', - '0x911566c808bf00acb200b418564440a2af177548', - '0x5c3094982cf3c97a06b7d62a6f7669f14a199b19', - '0x23f03a4fb344d8b98833d2ace093cc305e03474f', - ], - weightedPoolV2Factories: [ - '0xb2ed595afc445b47db7043bec25e772bf0fa1fbb', - '0x8ea1c497c16726e097f62c8c9fbd944143f27090', - '0xea87f3dffc679035653c0fba70e7bfe46e3fb733', - '0xd678b6acd834cc969bb19ce82727f2a541fb7941', - '0xb841df73861e65e6d61a80f503f095a91ce75e15', - ], swapProtocolFeePercentage: 0.25, yieldProtocolFeePercentage: 0.25, - factoriesWithpoolSpecificProtocolFeePercentagesProvider: [ - '0xb841df73861e65e6d61a80f503f095a91ce75e15', - '0x5c3094982cf3c97a06b7d62a6f7669f14a199b19', - ], }, multicall: '0x66335d7ad8011f6aa3f48aadcb523b62b38ed961', multicall3: '0xca11bde05977b3631167028862be2a173976ca11', @@ -347,7 +328,10 @@ export const fantomNetworkConfig: NetworkConfig = { new UserSyncReliquaryFarmBalanceService(fantomNetworkData.reliquary!.address), ], services: { - balancerSubgraphService: new BalancerSubgraphService(fantomNetworkData.subgraphs.balancer, fantomNetworkData.chain.id), + balancerSubgraphService: new BalancerSubgraphService( + fantomNetworkData.subgraphs.balancer, + fantomNetworkData.chain.id, + ), }, /* For sub-minute jobs we set the alarmEvaluationPeriod and alarmDatapointsToAlarm to 1 instead of the default 3. diff --git a/modules/network/gnosis.ts b/modules/network/gnosis.ts index d00aa09f0..57b91773d 100644 --- a/modules/network/gnosis.ts +++ b/modules/network/gnosis.ts @@ -68,17 +68,6 @@ const gnosisNetworkData: NetworkData = { }, balancer: { vault: '0xba12222222228d8ba445958a75a0704d566bf2c8', - composableStablePoolFactories: [ - '0x76578ecf9a141296ec657847fb45b0585bcda3a6', - '0xc128468b7ce63ea702c1f104d55a2566b13d3abd', - '0xd87f44df0159dc78029ab9ca7d7e57e7249f5acd', - '0x4bdcc2fb18aeb9e2d281b0278d946445070eada7', - ], - weightedPoolV2Factories: [ - '0x6cad2ea22bfa7f4c14aae92e47f510cd5c509bc7', - '0xf302f9f50958c5593770fdf4d4812309ff77414f', - '0xc128a9954e6c874ea3d62ce62b468ba073093f25', - ], swapProtocolFeePercentage: 0.5, yieldProtocolFeePercentage: 0.5, }, @@ -168,7 +157,10 @@ export const gnosisNetworkConfig: NetworkConfig = { ], userStakedBalanceServices: [new UserSyncGaugeBalanceService()], services: { - balancerSubgraphService: new BalancerSubgraphService(gnosisNetworkData.subgraphs.balancer, gnosisNetworkData.chain.id), + balancerSubgraphService: new BalancerSubgraphService( + gnosisNetworkData.subgraphs.balancer, + gnosisNetworkData.chain.id, + ), }, /* For sub-minute jobs we set the alarmEvaluationPeriod and alarmDatapointsToAlarm to 1 instead of the default 3. diff --git a/modules/network/mainnet.ts b/modules/network/mainnet.ts index 8e77f13ff..2b1bbdfa7 100644 --- a/modules/network/mainnet.ts +++ b/modules/network/mainnet.ts @@ -83,22 +83,8 @@ const data: NetworkData = { balancer: { vault: '0xba12222222228d8ba445958a75a0704d566bf2c8', tokenAdmin: '0xf302f9f50958c5593770fdf4d4812309ff77414f', - composableStablePoolFactories: [ - '0xf9ac7b9df2b3454e841110cce5550bd5ac6f875f', - '0x85a80afee867adf27b50bdb7b76da70f1e853062', - '0xdba127fbc23fb20f5929c546af220a991b5c6e01', - '0xfada0f4547ab2de89d1304a668c39b3e09aa7c76', - '0xdb8d758bcb971e482b2c45f7f8a7740283a1bd3a', - '0xba1b4a90bad57470a2cba762a32955dc491f76e0', - ], - weightedPoolV2Factories: [ - '0xcc508a455f5b0073973107db6a878ddbdab957bc', - '0x5dd94da3644ddd055fcf6b3e1aa310bb7801eb8b', - '0x897888115ada5773e02aa29f775430bfb5f34c51', - ], swapProtocolFeePercentage: 0.5, yieldProtocolFeePercentage: 0.5, - excludedPoolDataQueryPoolIds: ['0xf71d0774b214c4cf51e33eb3d30ef98132e4dbaa00000000000000000000046e'], }, multicall: '0x5ba1e12693dc8f9c48aad8770482f4739beed696', multicall3: '0xca11bde05977b3631167028862be2a173976ca11', @@ -378,10 +364,7 @@ export const mainnetNetworkConfig: NetworkConfig = { data.balancer.yieldProtocolFeePercentage, data.balancer.swapProtocolFeePercentage, ), - new PhantomStableAprService( - data.chain.prismaId, - data.balancer.yieldProtocolFeePercentage, - ), + new PhantomStableAprService(data.chain.prismaId, data.balancer.yieldProtocolFeePercentage), new BoostedPoolAprService(), new SwapFeeAprService(data.balancer.swapProtocolFeePercentage), new GaugeAprService(tokenService, [data.bal!.address]), diff --git a/modules/network/network-config-types.ts b/modules/network/network-config-types.ts index 10c8e33dd..e921c65b3 100644 --- a/modules/network/network-config-types.ts +++ b/modules/network/network-config-types.ts @@ -104,12 +104,8 @@ export interface NetworkData { balancer: { vault: string; tokenAdmin?: string; - weightedPoolV2Factories: string[]; - composableStablePoolFactories: string[]; yieldProtocolFeePercentage: number; swapProtocolFeePercentage: number; - excludedPoolDataQueryPoolIds?: string[]; - factoriesWithpoolSpecificProtocolFeePercentagesProvider?: string[]; }; multicall: string; multicall3: string; diff --git a/modules/network/optimism.ts b/modules/network/optimism.ts index af9a1a00d..c16361a65 100644 --- a/modules/network/optimism.ts +++ b/modules/network/optimism.ts @@ -81,17 +81,6 @@ const optimismNetworkData: NetworkData = { }, balancer: { vault: '0xba12222222228d8ba445958a75a0704d566bf2c8', - composableStablePoolFactories: [ - '0xf145cafb67081895ee80eb7c04a30cf87f07b745', - '0xe2e901ab09f37884ba31622df3ca7fc19aa443be', - '0x1802953277fd955f9a254b80aa0582f193cf1d77', - '0x043a2dad730d585c44fb79d2614f295d2d625412', - ], - weightedPoolV2Factories: [ - '0xad901309d9e9dbc5df19c84f729f429f0189a633', - '0xa0dabebaad1b243bbb243f933013d560819eb66f', - '0x230a59f4d9adc147480f03b0d3fffecd56c3289a', - ], swapProtocolFeePercentage: 0.5, yieldProtocolFeePercentage: 0.5, }, @@ -296,7 +285,10 @@ export const optimismNetworkConfig: NetworkConfig = { ], userStakedBalanceServices: [new UserSyncGaugeBalanceService()], services: { - balancerSubgraphService: new BalancerSubgraphService(optimismNetworkData.subgraphs.balancer, optimismNetworkData.chain.id), + balancerSubgraphService: new BalancerSubgraphService( + optimismNetworkData.subgraphs.balancer, + optimismNetworkData.chain.id, + ), }, /* For sub-minute jobs we set the alarmEvaluationPeriod and alarmDatapointsToAlarm to 1 instead of the default 3. diff --git a/modules/network/polygon.ts b/modules/network/polygon.ts index 8fd44b1fd..9407a51fa 100644 --- a/modules/network/polygon.ts +++ b/modules/network/polygon.ts @@ -72,18 +72,6 @@ const polygonNetworkData: NetworkData = { }, balancer: { vault: '0xba12222222228d8ba445958a75a0704d566bf2c8', - composableStablePoolFactories: [ - '0x136fd06fa01ecf624c7f2b3cb15742c1339dc2c4', - '0x85a80afee867adf27b50bdb7b76da70f1e853062', - '0x7bc6c0e73edaa66ef3f6e2f27b0ee8661834c6c9', - '0x6ab5549bbd766a43afb687776ad8466f8b42f777', - '0xe2fa4e1d17725e72dcdafe943ecf45df4b9e285b', - ], - weightedPoolV2Factories: [ - '0x0e39c3d9b2ec765efd9c5c70bb290b1fcd8536e3', - '0x82e4cfaef85b1b6299935340c964c942280327f4', - '0xfc8a407bba312ac761d8bfe04ce1201904842b76', - ], swapProtocolFeePercentage: 0.5, yieldProtocolFeePercentage: 0.5, }, @@ -286,7 +274,10 @@ export const polygonNetworkConfig: NetworkConfig = { ], userStakedBalanceServices: [new UserSyncGaugeBalanceService()], services: { - balancerSubgraphService: new BalancerSubgraphService(polygonNetworkData.subgraphs.balancer, polygonNetworkData.chain.id), + balancerSubgraphService: new BalancerSubgraphService( + polygonNetworkData.subgraphs.balancer, + polygonNetworkData.chain.id, + ), }, /* For sub-minute jobs we set the alarmEvaluationPeriod and alarmDatapointsToAlarm to 1 instead of the default 3. diff --git a/modules/network/zkevm.ts b/modules/network/zkevm.ts index 77ed05875..0a2f93c23 100644 --- a/modules/network/zkevm.ts +++ b/modules/network/zkevm.ts @@ -70,12 +70,6 @@ const zkevmNetworkData: NetworkData = { }, balancer: { vault: '0xba12222222228d8ba445958a75a0704d566bf2c8', - composableStablePoolFactories: [ - '0x8ea89804145c007e7d226001a96955ad53836087', - '0x956ccab09898c0af2aca5e6c229c3ad4e93d9288', - '0x577e5993b9cc480f07f98b5ebd055604bd9071c4' - ], - weightedPoolV2Factories: ['0x03f3fb107e74f2eac9358862e91ad3c692712054'], swapProtocolFeePercentage: 0.5, yieldProtocolFeePercentage: 0.5, }, @@ -187,7 +181,10 @@ export const zkevmNetworkConfig: NetworkConfig = { ], userStakedBalanceServices: [new UserSyncGaugeBalanceService()], services: { - balancerSubgraphService: new BalancerSubgraphService(zkevmNetworkData.subgraphs.balancer, zkevmNetworkData.chain.id), + balancerSubgraphService: new BalancerSubgraphService( + zkevmNetworkData.subgraphs.balancer, + zkevmNetworkData.chain.id, + ), }, /* For sub-minute jobs we set the alarmEvaluationPeriod and alarmDatapointsToAlarm to 1 instead of the default 3. diff --git a/modules/pool/lib/pool-on-chain-data.service.ts b/modules/pool/lib/pool-on-chain-data.service.ts index 72bef5972..c60c15d85 100644 --- a/modules/pool/lib/pool-on-chain-data.service.ts +++ b/modules/pool/lib/pool-on-chain-data.service.ts @@ -1,5 +1,5 @@ import { formatFixed } from '@ethersproject/bignumber'; -import { Chain, PrismaPoolType } from '@prisma/client'; +import { PrismaPoolType } from '@prisma/client'; import { isSameAddress } from '@balancer-labs/sdk'; import { prisma } from '../../../prisma/prisma-client'; import { isComposableStablePool, isStablePool } from './pool-utils'; @@ -33,7 +33,6 @@ export class PoolOnChainDataService { vaultAddress: networkContext.data.balancer.vault, yieldProtocolFeePercentage: networkContext.data.balancer.yieldProtocolFeePercentage, gyroConfig: networkContext.data.gyro?.config, - composableStableFactories: networkContext.data.balancer.composableStablePoolFactories, }; } @@ -95,12 +94,7 @@ export class PoolOnChainDataService { }); const gyroPools = filteredPools.filter((pool) => pool.type.includes('GYRO')); - const poolsWithComposableStableType = filteredPools.map((pool) => ({ - ...pool, - type: (isComposableStablePool(pool) ? 'COMPOSABLE_STABLE' : pool.type) as - | PrismaPoolType - | 'COMPOSABLE_STABLE', - })); + const poolsWithComposableStableType = filteredPools.filter((pool) => isComposableStablePool(pool)); const tokenPrices = await this.tokenService.getTokenPrices(); const onchainResults = await fetchOnChainPoolData( diff --git a/modules/pool/lib/pool-utils.ts b/modules/pool/lib/pool-utils.ts index d1cc25d06..321575fd9 100644 --- a/modules/pool/lib/pool-utils.ts +++ b/modules/pool/lib/pool-utils.ts @@ -1,7 +1,4 @@ import { PrismaPoolDynamicData, PrismaPoolType } from '@prisma/client'; -import { isSameAddress } from '@balancer-labs/sdk'; -import { networkContext } from '../../network/network-context.service'; -import { prisma } from '../../../prisma/prisma-client'; type PoolWithTypeAndFactory = { address: string; @@ -16,21 +13,11 @@ export function isStablePool(poolType: PrismaPoolType) { } export function isWeightedPoolV2(pool: PoolWithTypeAndFactory) { - return ( - pool.type === 'WEIGHTED' && - networkContext.data.balancer.weightedPoolV2Factories.find((factory) => - isSameAddress(pool.factory || '', factory), - ) !== undefined - ); + return pool.type === 'WEIGHTED' && pool.version >= 2; } export function isComposableStablePool(pool: PoolWithTypeAndFactory) { - return ( - pool.type === 'PHANTOM_STABLE' && - networkContext.data.balancer.composableStablePoolFactories.find((factory) => - isSameAddress(pool.factory || '', factory), - ) !== undefined - ); + return pool.type === 'COMPOSABLE_STABLE' && pool.version > 0; } export function collectsYieldFee(pool: PoolWithTypeAndFactory) { From c7e05bbbd25d2db28d29d316b47105e8acfc37a6 Mon Sep 17 00:00:00 2001 From: franz Date: Tue, 21 Nov 2023 11:24:31 +0100 Subject: [PATCH 10/44] add phantomstable to gql schema again --- modules/pool/lib/pool-creator.service.ts | 4 ++-- modules/pool/lib/pool-gql-loader.service.ts | 2 -- modules/pool/pool.gql | 1 + 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/pool/lib/pool-creator.service.ts b/modules/pool/lib/pool-creator.service.ts index e9c68111e..0108cba5a 100644 --- a/modules/pool/lib/pool-creator.service.ts +++ b/modules/pool/lib/pool-creator.service.ts @@ -189,7 +189,7 @@ export class PoolCreatorService { // for the old phantom stable pool, we add it to the DB as type COMPOSABLE_STABLE with version 0 let poolTypeVersion = pool.poolTypeVersion ? pool.poolTypeVersion : 1; - if (pool.poolType === 'PHANTOM_STABLE') { + if (pool.poolType === 'StablePhantom') { poolTypeVersion = 0; } @@ -372,7 +372,7 @@ export class PoolCreatorService { for (const subgraphPool of subgraphPools) { // for the old phantom stable pool, we add it to the DB as type COMPOSABLE_STABLE with version 0 let poolTypeVersion = subgraphPool.poolTypeVersion ? subgraphPool.poolTypeVersion : 1; - if (subgraphPool.poolType === 'PHANTOM_STABLE') { + if (subgraphPool.poolType === 'StablePhantom') { poolTypeVersion = 0; } diff --git a/modules/pool/lib/pool-gql-loader.service.ts b/modules/pool/lib/pool-gql-loader.service.ts index 3440b4168..0e5686456 100644 --- a/modules/pool/lib/pool-gql-loader.service.ts +++ b/modules/pool/lib/pool-gql-loader.service.ts @@ -80,8 +80,6 @@ export class PoolGqlLoaderService { public mapToMinimalGqlPool(pool: PrismaPoolMinimal): GqlPoolMinimal { return { ...pool, - // we need this mapping because we migrated from PHANTOMSTABLE type to COMPOSABLESTABLE in the DB, but now only return COMPOSABLESTABLE - type: pool.type === 'PHANTOM_STABLE' ? PrismaPoolType.COMPOSABLE_STABLE : pool.type, decimals: 18, dynamicData: this.getPoolDynamicData(pool), allTokens: this.mapAllTokens(pool), diff --git a/modules/pool/pool.gql b/modules/pool/pool.gql index cc3ca9675..17599275c 100644 --- a/modules/pool/pool.gql +++ b/modules/pool/pool.gql @@ -81,6 +81,7 @@ enum GqlPoolMinimalType { WEIGHTED STABLE META_STABLE + PHANTOM_STABLE COMPOSABLE_STABLE ELEMENT LINEAR From 0717c07bd75652d9913c578d66aa299d767ad271 Mon Sep 17 00:00:00 2001 From: gmbronco <83549293+gmbronco@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:36:53 +0100 Subject: [PATCH 11/44] Update pool-onchain-data.ts --- modules/pool/lib/pool-onchain-data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/pool/lib/pool-onchain-data.ts b/modules/pool/lib/pool-onchain-data.ts index 189c5f62e..eee9af4ed 100644 --- a/modules/pool/lib/pool-onchain-data.ts +++ b/modules/pool/lib/pool-onchain-data.ts @@ -76,7 +76,7 @@ const getSwapFeeFn = (type: string) => { }; const getTotalSupplyFn = (type: PoolInput['type'], version: number) => { - if (['LINEAR', 'PHANTOM_STABLE'].includes(type)) { + if (['LINEAR'].includes(type) || (type === 'COMPOSABLE_STABLE' && version === 0)) { return 'getVirtualSupply'; } else if ( type === 'COMPOSABLE_STABLE' || From 034549f3c03c460be333e3ecdb500edb94b04c48 Mon Sep 17 00:00:00 2001 From: gmbronco <83549293+gmbronco@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:37:51 +0100 Subject: [PATCH 12/44] Update pool-on-chain-data.service.ts --- modules/pool/lib/pool-on-chain-data.service.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/modules/pool/lib/pool-on-chain-data.service.ts b/modules/pool/lib/pool-on-chain-data.service.ts index c60c15d85..2a0e70d9d 100644 --- a/modules/pool/lib/pool-on-chain-data.service.ts +++ b/modules/pool/lib/pool-on-chain-data.service.ts @@ -94,14 +94,9 @@ export class PoolOnChainDataService { }); const gyroPools = filteredPools.filter((pool) => pool.type.includes('GYRO')); - const poolsWithComposableStableType = filteredPools.filter((pool) => isComposableStablePool(pool)); const tokenPrices = await this.tokenService.getTokenPrices(); - const onchainResults = await fetchOnChainPoolData( - poolsWithComposableStableType, - this.options.vaultAddress, - 1024, - ); + const onchainResults = await fetchOnChainPoolData(filteredPools, this.options.vaultAddress, 1024); const gyroFees = await (this.options.gyroConfig ? fetchOnChainGyroFees(gyroPools, this.options.gyroConfig, 1024) : Promise.resolve({} as { [address: string]: string })); From a74456f6dd9a818d210a5a0927e3f7489342fd53 Mon Sep 17 00:00:00 2001 From: mendesfabio Date: Wed, 29 Nov 2023 08:14:10 -0300 Subject: [PATCH 13/44] fix vebal rank sorting --- modules/vebal/vebal.service.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/vebal/vebal.service.ts b/modules/vebal/vebal.service.ts index 841cd510b..0df5742f7 100644 --- a/modules/vebal/vebal.service.ts +++ b/modules/vebal/vebal.service.ts @@ -31,12 +31,18 @@ export class VeBalService { if (networkContext.data.veBal) { const veBalUsers = await prisma.prismaVeBalUserBalance.findMany({ where: { chain: networkContext.chain }, - orderBy: { balance: 'desc' }, }); - for (const user of veBalUsers) { + const veBalUsersNum = veBalUsers.map(user => ({ + ...user, + balance: parseFloat(user.balance), + })); + + veBalUsersNum.sort((a, b) => b.balance - a.balance); + + for (const user of veBalUsersNum) { if (user.userAddress === userAddress) { - balance = user.balance; + balance = user.balance.toString(); break; } rank++; From 69120bc4e60fdb4d90f1bab0bed226a63230ddc0 Mon Sep 17 00:00:00 2001 From: franz Date: Fri, 1 Dec 2023 11:37:45 +0100 Subject: [PATCH 14/44] unity poolType enum --- modules/pool/pool.gql | 59 ++++++++++++++++++++--------------------- modules/vebal/vebal.gql | 2 +- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/modules/pool/pool.gql b/modules/pool/pool.gql index f6d231cf3..83ee81202 100644 --- a/modules/pool/pool.gql +++ b/modules/pool/pool.gql @@ -73,7 +73,7 @@ type GqlPoolMinimal { allTokens: [GqlPoolTokenExpanded!]! dynamicData: GqlPoolDynamicData! staking: GqlPoolStaking - type: GqlPoolMinimalType! + type: GqlPoolType! version: Int! userBalance: GqlPoolUserBalance } @@ -84,7 +84,7 @@ type GqlPoolUserBalance { stakedBalance: AmountHumanReadable! } -enum GqlPoolMinimalType { +enum GqlPoolType { WEIGHTED STABLE META_STABLE @@ -104,7 +104,7 @@ interface GqlPoolBase { #fields that never change after creation id: ID! chain: GqlChain! - type: String! + type: GqlPoolType! version: Int! name: String! symbol: String! @@ -224,7 +224,7 @@ type GqlPoolWeighted implements GqlPoolBase { tokens: [GqlPoolTokenUnion!]! nestingType: GqlPoolNestingType! staking: GqlPoolStaking - type: String! + type: GqlPoolType! version: Int! } @@ -232,7 +232,7 @@ type GqlPoolGyro implements GqlPoolBase { id: ID! chain: GqlChain! name: String! - type: String! + type: GqlPoolType! symbol: String! address: Bytes! decimals: Int! @@ -251,7 +251,6 @@ type GqlPoolGyro implements GqlPoolBase { tokens: [GqlPoolTokenUnion!]! nestingType: GqlPoolNestingType! staking: GqlPoolStaking - type: String! version: Int! } @@ -274,7 +273,7 @@ type GqlPoolLiquidityBootstrapping implements GqlPoolBase { tokens: [GqlPoolTokenUnion!]! nestingType: GqlPoolNestingType! staking: GqlPoolStaking - type: String! + type: GqlPoolType! version: Int! } @@ -297,7 +296,7 @@ type GqlPoolStable implements GqlPoolBase { tokens: [GqlPoolToken!]! amp: BigInt! staking: GqlPoolStaking - type: String! + type: GqlPoolType! version: Int! } @@ -320,7 +319,7 @@ type GqlPoolMetaStable implements GqlPoolBase { tokens: [GqlPoolToken!]! amp: BigInt! staking: GqlPoolStaking - type: String! + type: GqlPoolType! version: Int! } @@ -344,7 +343,7 @@ type GqlPoolPhantomStable implements GqlPoolBase { amp: BigInt! staking: GqlPoolStaking bptPriceRate: BigDecimal! - type: String! + type: GqlPoolType! version: Int! } @@ -370,7 +369,7 @@ type GqlPoolElement implements GqlPoolBase { principalToken: Bytes! baseToken: Bytes! staking: GqlPoolStaking - type: String! + type: GqlPoolType! version: Int! } @@ -398,7 +397,7 @@ type GqlPoolLinear implements GqlPoolBase { lowerTarget: BigInt! staking: GqlPoolStaking bptPriceRate: BigDecimal! - type: String! + type: GqlPoolType! version: Int! } @@ -422,7 +421,7 @@ type GqlPoolLinearNested { lowerTarget: BigInt! bptPriceRate: BigDecimal! - type: String! + type: GqlPoolType! version: Int! } @@ -443,7 +442,7 @@ type GqlPoolPhantomStableNested { swapFee: BigDecimal! bptPriceRate: BigDecimal! - type: String! + type: GqlPoolType! version: Int! } @@ -614,8 +613,8 @@ input GqlPoolFilter { categoryNotIn: [GqlPoolFilterCategory!] tokensIn: [String!] tokensNotIn: [String!] - poolTypeIn: [GqlPoolFilterType!] - poolTypeNotIn: [GqlPoolFilterType!] + poolTypeIn: [GqlPoolType!] + poolTypeNotIn: [GqlPoolType!] idIn: [String!] idNotIn: [String!] filterIn: [String!] @@ -631,20 +630,20 @@ enum GqlPoolFilterCategory { BLACK_LISTED } -enum GqlPoolFilterType { - WEIGHTED - STABLE - META_STABLE - PHANTOM_STABLE - ELEMENT - LINEAR - UNKNOWN - LIQUIDITY_BOOTSTRAPPING - INVESTMENT - GYRO - GYRO3 - GYROE -} +# enum GqlPoolFilterType { +# WEIGHTED +# STABLE +# META_STABLE +# PHANTOM_STABLE +# ELEMENT +# LINEAR +# UNKNOWN +# LIQUIDITY_BOOTSTRAPPING +# INVESTMENT +# GYRO +# GYRO3 +# GYROE +# } type GqlPoolTokenExpanded { id: ID! diff --git a/modules/vebal/vebal.gql b/modules/vebal/vebal.gql index 3c2d4c68b..a16cd12ce 100644 --- a/modules/vebal/vebal.gql +++ b/modules/vebal/vebal.gql @@ -20,7 +20,7 @@ type GqlVotingPool { chain: GqlChain! symbol: String! address: Bytes! - type: GqlPoolMinimalType! + type: GqlPoolType! tokens: [GqlVotingGaugeToken!]! From d1d4993f9462c277f2fee5b40d77be01a5cd29fe Mon Sep 17 00:00:00 2001 From: gmbronco <83549293+gmbronco@users.noreply.github.com> Date: Mon, 4 Dec 2023 16:39:36 +0100 Subject: [PATCH 15/44] fix onchain call for gyro supply --- modules/pool/lib/pool-onchain-data.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/pool/lib/pool-onchain-data.ts b/modules/pool/lib/pool-onchain-data.ts index ca333d132..7a799a481 100644 --- a/modules/pool/lib/pool-onchain-data.ts +++ b/modules/pool/lib/pool-onchain-data.ts @@ -83,7 +83,6 @@ const getTotalSupplyFn = (type: PoolInput['type'], version: number) => { } else if ( type === 'COMPOSABLE_STABLE' || (type === 'WEIGHTED' && version > 1) || - (type === 'GYROE' && version > 1) || (type === 'UNKNOWN' && version > 1) ) { return 'getActualSupply'; From 6e2b97e8c52973da357c6709d0b023d039cfe75f Mon Sep 17 00:00:00 2001 From: gmbronco <83549293+gmbronco@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:17:16 +0100 Subject: [PATCH 16/44] reduce profile sampling in Sentry (#569) --- worker/worker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/worker.ts b/worker/worker.ts index 45cd2e0ed..c5da70337 100644 --- a/worker/worker.ts +++ b/worker/worker.ts @@ -17,7 +17,7 @@ export async function startWorker() { new ProfilingIntegration(), ], tracesSampleRate: 0.2, - profilesSampleRate: 1.0, + profilesSampleRate: 0.1, }); app.use(Sentry.Handlers.requestHandler()); From eb2a4290a84186265cebaf60fd0aa1219560f24c Mon Sep 17 00:00:00 2001 From: gmbronco <83549293+gmbronco@users.noreply.github.com> Date: Wed, 13 Dec 2023 16:57:31 +0100 Subject: [PATCH 17/44] faster logs fetching for staking --- .../lib/user-sync-gauge-balance.service.ts | 81 ++++++++++++------- .../lib/user-sync-wallet-balance.service.ts | 2 +- 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/modules/user/lib/user-sync-gauge-balance.service.ts b/modules/user/lib/user-sync-gauge-balance.service.ts index 0ee6df2f3..93dd0efb8 100644 --- a/modules/user/lib/user-sync-gauge-balance.service.ts +++ b/modules/user/lib/user-sync-gauge-balance.service.ts @@ -88,20 +88,16 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { include: { staking: true }, where: { chain: networkContext.chain }, }); - console.log(`user-sync-staked-balances-${networkContext.chainId} got data from db.`); const latestBlock = await networkContext.provider.getBlockNumber(); console.log(`user-sync-staked-balances-${networkContext.chainId} got latest block.`); + const gaugeAddresses = await gaugeSubgraphService.getAllGaugeAddresses(); - console.log(`user-sync-staked-balances-${networkContext.chainId} got ${gaugeAddresses.length} gauges.`); // we sync at most 10k blocks at a time const startBlock = status.blockNumber + 1; - const endBlock = - latestBlock - startBlock > networkContext.data.rpcMaxBlockRange - ? startBlock + networkContext.data.rpcMaxBlockRange - : latestBlock; + const endBlock = latestBlock; // no new blocks have been minted, needed for slow networks if (startBlock > endBlock) { @@ -112,32 +108,63 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { we need to figure out which users have a changed balance on any gauge contract and update their balance, therefore we check all transfer events since the last synced block */ - - const events: ethers.providers.Log[] = []; - const logPromises: Promise[] = []; const erc20Interface = new ethers.utils.Interface(ERC20Abi); - console.log(`user-sync-staked-balances-${networkContext.chainId} getLogs of ${gaugeAddresses.length} gauges`); - - for (const gaugeAddress of gaugeAddresses) { - logPromises.push( - networkContext.provider.getLogs({ - //ERC20 Transfer topic - topics: ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'], - fromBlock: startBlock, - toBlock: endBlock, - address: gaugeAddress, - }), - ); - } - const allResponses = await Promise.all(logPromises); + // Split the range into smaller chunks to avoid RPC limits, setting up to 50 times max block range + const maxBlockRange = networkContext.data.rpcMaxBlockRange; + const toBlock = Math.min(startBlock + 50 * maxBlockRange, latestBlock); + const range = toBlock - startBlock; + console.log(`user-sync-staked-balances-${networkContext.chainId} block range from ${startBlock} to ${toBlock}`); console.log( - `user-sync-staked-balances-${networkContext.chainId} getLogs of ${gaugeAddresses.length} gauges done`, + `user-sync-staked-balances-${networkContext.chainId} getLogs for ${_.uniq(gaugeAddresses).length} gauges.`, ); + const events = await Promise.all( + // Getting logs in batches of max blocks allowed by RPC + Array.from({ length: Math.ceil(range / maxBlockRange) }, (_, i) => i).map(async (i) => { + const from = startBlock + i * maxBlockRange; + const to = Math.min(startBlock + (i + 1) * maxBlockRange, toBlock); - for (const response of allResponses) { - events.push(...response); - } + // Usually RPCs are handling any number of addresses, but it here batching just to be on the safe side + const logRequests: Promise[] = _.chunk(gaugeAddresses, 500).map((addresses) => { + // Fetch logs with a raw json request until we support Viem or Ethers6 + const payload = { + jsonrpc: '2.0', + id: 1, + method: 'eth_getLogs', + params: [ + { + address: addresses, + topics: [ethers.utils.id('Transfer(address,address,uint256)')], + fromBlock: '0x' + BigInt(from).toString(16), + toBlock: '0x' + BigInt(to).toString(16), + }, + ], + }; + + return fetch(networkContext.data.rpcUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(payload), + }) + .then((response) => response.json() as Promise<{ result: ethers.providers.Log[] }>) + .then(({ result }) => result) + .catch((error) => { + console.error('Error fetching logs:', error); + return []; + }); + }); + + const events = await Promise.all(logRequests).then((res) => res.flat()); + + return events; + }), + ).then((res) => res.flat().filter((event) => event)); + + console.log( + `user-sync-staked-balances-${networkContext.chainId} getLogs for ${gaugeAddresses.length} gauges done`, + ); const balancesToFetch = _.uniqBy( events diff --git a/modules/user/lib/user-sync-wallet-balance.service.ts b/modules/user/lib/user-sync-wallet-balance.service.ts index 340f39781..7389260aa 100644 --- a/modules/user/lib/user-sync-wallet-balance.service.ts +++ b/modules/user/lib/user-sync-wallet-balance.service.ts @@ -212,7 +212,7 @@ export class UserSyncWalletBalanceService { return events; }), - ).then((res) => res.flat()); + ).then((res) => res.flat().filter((event) => event)); console.log( `user-sync-wallet-balances-for-all-pools-${this.chainId} getLogs of ${poolAddresses.length} pools done`, From 5ce23369588d9d9edcf215405034650796eed6df Mon Sep 17 00:00:00 2001 From: franz Date: Thu, 14 Dec 2023 13:16:16 +0100 Subject: [PATCH 18/44] wip --- modules/pool/lib/pool-gql-loader.service.ts | 46 ++++++++++++++++++--- modules/pool/pool.gql | 4 +- modules/pool/pool.resolvers.ts | 6 +-- modules/pool/pool.service.ts | 5 ++- 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/modules/pool/lib/pool-gql-loader.service.ts b/modules/pool/lib/pool-gql-loader.service.ts index 0f1be6426..c0671a828 100644 --- a/modules/pool/lib/pool-gql-loader.service.ts +++ b/modules/pool/lib/pool-gql-loader.service.ts @@ -30,6 +30,7 @@ import { GqlPoolUserBalance, GqlPoolWithdrawConfig, GqlPoolWithdrawOption, + InputMaybe, QueryPoolGetPoolsArgs, } from '../../../schema'; import { isSameAddress } from '@balancer-labs/sdk'; @@ -42,14 +43,16 @@ import { networkContext } from '../../network/network-context.service'; import { fixedNumber } from '../../view-helpers/fixed-number'; import { parseUnits } from 'ethers/lib/utils'; import { formatFixed } from '@ethersproject/bignumber'; -import { StringDecoder } from 'string_decoder'; -import { SwapKind } from '@balancer/sdk'; export class PoolGqlLoaderService { - public async getPool(id: string, chain: Chain): Promise { - const pool = await prisma.prismaPool.findUnique({ + public async getPool(id: string, chain: Chain, userAddress?: InputMaybe): Promise { + let pool = undefined; + pool = await prisma.prismaPool.findUnique({ where: { id_chain: { id, chain: chain } }, - include: prismaPoolWithExpandedNesting.include, + include: { + ...prismaPoolWithExpandedNesting.include, + ...this.getUserBalancesInclude(userAddress), + }, }); if (!pool) { @@ -423,7 +426,11 @@ export class PoolGqlLoaderService { }; } - private mapPoolToGqlPool(pool: PrismaPoolWithExpandedNesting): GqlPoolUnion { + private mapPoolToGqlPool( + pool: PrismaPoolWithExpandedNesting, + userWalletbalances: PrismaUserWalletBalance[] = [], + userStakedBalances: PrismaUserStakedBalance[] = [], + ): GqlPoolUnion { const bpt = pool.tokens.find((token) => token.address === pool.address); const mappedData = { @@ -437,6 +444,7 @@ export class PoolGqlLoaderService { tokens: pool.tokens.map((token) => this.mapPoolTokenToGqlUnion(token)), allTokens: this.mapAllTokens(pool), displayTokens: this.mapDisplayTokens(pool), + userBalance: this.getUserBalance(pool, userWalletbalances, userStakedBalances), }; //TODO: may need to build out the types here still @@ -1258,4 +1266,30 @@ export class PoolGqlLoaderService { .toFixed(mainToken.token.decimals)}`, }; } + + private getUserBalancesInclude(userAddress?: InputMaybe) { + if (!userAddress) { + return {}; + } + return { + userWalletBalances: { + where: { + userAddress: { + equals: userAddress, + mode: 'insensitive' as const, + }, + balanceNum: { gt: 0 }, + }, + }, + userStakedBalances: { + where: { + userAddress: { + equals: userAddress, + mode: 'insensitive' as const, + }, + balanceNum: { gt: 0 }, + }, + }, + }; + } } diff --git a/modules/pool/pool.gql b/modules/pool/pool.gql index dc601f485..d7046df63 100644 --- a/modules/pool/pool.gql +++ b/modules/pool/pool.gql @@ -1,5 +1,5 @@ extend type Query { - poolGetPool(id: String!, chain: GqlChain): GqlPoolBase! + poolGetPool(id: String!, chain: GqlChain, userAddress: String): GqlPoolBase! poolGetPools( first: Int skip: Int @@ -125,6 +125,8 @@ interface GqlPoolBase { dynamicData: GqlPoolDynamicData! staking: GqlPoolStaking + + userBalance: GqlPoolUserBalance } type GqlPoolDynamicData { diff --git a/modules/pool/pool.resolvers.ts b/modules/pool/pool.resolvers.ts index bb7387b93..8acf48937 100644 --- a/modules/pool/pool.resolvers.ts +++ b/modules/pool/pool.resolvers.ts @@ -7,14 +7,14 @@ import { headerChain } from '../context/header-chain'; const balancerResolvers: Resolvers = { Query: { - poolGetPool: async (parent, { id, chain }, context) => { + poolGetPool: async (parent, { id, chain, userAddress }, context) => { const currentChain = headerChain(); if (!chain && currentChain) { chain = currentChain; } else if (!chain) { throw new Error('poolGetPool error: Provide "chain" param'); } - return poolService.getGqlPool(id, chain); + return poolService.getGqlPool(id, chain, userAddress); }, poolGetPools: async (parent, args, context) => { return poolService.getGqlPools(args); @@ -105,7 +105,7 @@ const balancerResolvers: Resolvers = { }, poolGetGyroPools: async () => { return poolService.getGqlGyroPools(); - } + }, }, Mutation: { poolSyncAllPoolsFromSubgraph: async (parent, {}, context) => { diff --git a/modules/pool/pool.service.ts b/modules/pool/pool.service.ts index 704d56364..1ded9c694 100644 --- a/modules/pool/pool.service.ts +++ b/modules/pool/pool.service.ts @@ -14,6 +14,7 @@ import { GqlPoolSnapshotDataRange, GqlPoolUnion, GqlPoolUserSwapVolume, + InputMaybe, QueryPoolGetBatchSwapsArgs, QueryPoolGetJoinExitsArgs, QueryPoolGetPoolsArgs, @@ -73,8 +74,8 @@ export class PoolService { return networkContext.services.balancerSubgraphService; } - public async getGqlPool(id: string, chain: GqlChain): Promise { - return this.poolGqlLoaderService.getPool(id, chain); + public async getGqlPool(id: string, chain: GqlChain, userAddress?: InputMaybe): Promise { + return this.poolGqlLoaderService.getPool(id, chain, userAddress); } public async getGqlPools(args: QueryPoolGetPoolsArgs): Promise { From d90388139b364201b301db2276c63f41e23f01c5 Mon Sep 17 00:00:00 2001 From: franz Date: Fri, 15 Dec 2023 09:21:05 +0100 Subject: [PATCH 19/44] wip --- modules/balancer/balancer.gql | 39 ------------- modules/balancer/balancer.resolvers.ts | 23 -------- modules/beethoven/balancer-sdk.resolvers.ts | 45 -------------- .../{beethoven => sor}/balancer-sor.test.ts | 0 .../balancer-sdk.gql => sor/sor.gql} | 49 +++++++++------- modules/sor/sor.resolvers.ts | 31 ++++++++++ modules/sor/sor.service.ts | 58 ++++++++++++++----- .../sorV1Beets}/balancer-sor.service.ts | 18 +++--- modules/sor/sorV1Beets/sorV1Beets.service.ts | 2 +- modules/sor/sorV2/sorV2.service.ts | 2 +- modules/sor/utils.ts | 5 +- 11 files changed, 119 insertions(+), 153 deletions(-) delete mode 100644 modules/balancer/balancer.gql delete mode 100644 modules/balancer/balancer.resolvers.ts delete mode 100644 modules/beethoven/balancer-sdk.resolvers.ts rename modules/{beethoven => sor}/balancer-sor.test.ts (100%) rename modules/{beethoven/balancer-sdk.gql => sor/sor.gql} (93%) create mode 100644 modules/sor/sor.resolvers.ts rename modules/{beethoven => sor/sorV1Beets}/balancer-sor.service.ts (96%) diff --git a/modules/balancer/balancer.gql b/modules/balancer/balancer.gql deleted file mode 100644 index 228429a2f..000000000 --- a/modules/balancer/balancer.gql +++ /dev/null @@ -1,39 +0,0 @@ -extend type Mutation { - balancerMutationTest: String! -} - -extend type Query { - sorGetCowSwaps( - chain: GqlChain! - tokenIn: String! - tokenOut: String! - swapType: GqlSorSwapType! - swapAmount: BigDecimal! #expected in raw amount - ): GqlCowSwapApiResponse! -} - -enum GqlSorSwapType { - EXACT_IN - EXACT_OUT -} - -type GqlCowSwapApiResponse { - tokenAddresses: [String!]! - swaps: [GqlSwap!]! - swapAmount: String! - swapAmountForSwaps: String! - returnAmount: String! - returnAmountFromSwaps: String! - returnAmountConsideringFees: String! - tokenIn: String! - tokenOut: String! - marketSp: String! -} - -type GqlSwap { - poolId: String! - assetInIndex: Int! - assetOutIndex: Int! - amount: String! - userData: String! -} diff --git a/modules/balancer/balancer.resolvers.ts b/modules/balancer/balancer.resolvers.ts deleted file mode 100644 index 3369aa1e0..000000000 --- a/modules/balancer/balancer.resolvers.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Resolvers } from '../../schema'; -import { sorService } from '../sor/sor.service'; -import { getTokenAmountRaw } from '../sor/utils'; - -const balancerResolvers: Resolvers = { - Query: { - sorGetCowSwaps: async (parent, args, context) => { - const amountToken = args.swapType === 'EXACT_IN' ? args.tokenIn : args.tokenOut; - // Use TokenAmount to help follow scaling requirements in later logic - // args.swapAmount is RawScale, e.g. 1USDC should be passed as 1000000 - const amount = await getTokenAmountRaw(amountToken, args.swapAmount, args.chain); - const swaps = await sorService.getCowSwaps({ ...args, swapAmount: amount, swapOptions: {} }); - return { ...swaps, __typename: 'GqlCowSwapApiResponse' }; - }, - }, - Mutation: { - balancerMutationTest: async (parent, {}, context) => { - return 'test'; - }, - }, -}; - -export default balancerResolvers; diff --git a/modules/beethoven/balancer-sdk.resolvers.ts b/modules/beethoven/balancer-sdk.resolvers.ts deleted file mode 100644 index a755a1e90..000000000 --- a/modules/beethoven/balancer-sdk.resolvers.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Resolvers } from '../../schema'; -import { balancerSorService } from './balancer-sor.service'; -import { tokenService } from '../token/token.service'; -import { sorService } from '../sor/sor.service'; -import { getTokenAmountHuman } from '../sor/utils'; -import { headerChain } from '../context/header-chain'; - -const balancerSdkResolvers: Resolvers = { - Query: { - sorGetSwaps: async (parent, args, context) => { - console.log('sorGetSwaps args', JSON.stringify(args)); - - const currentChain = headerChain(); - if (!args.chain && currentChain) { - args.chain = currentChain; - } else if (!args.chain) { - throw new Error('sorGetSwaps error: Provide "chain" param'); - } - const chain = args.chain; - const tokenIn = args.tokenIn.toLowerCase(); - const tokenOut = args.tokenOut.toLowerCase(); - const amountToken = args.swapType === 'EXACT_IN' ? tokenIn : tokenOut; - // Use TokenAmount to help follow scaling requirements in later logic - // args.swapAmount is HumanScale - const amount = await getTokenAmountHuman(amountToken, args.swapAmount, args.chain); - - const swaps = await sorService.getBeetsSwaps({ - ...args, - chain, - tokenIn, - tokenOut, - swapAmount: amount, - }); - - return { ...swaps, __typename: 'GqlSorGetSwapsResponse' }; - }, - sorGetBatchSwapForTokensIn: async (parent, args, context) => { - const tokens = await tokenService.getTokens(); - - return balancerSorService.getBatchSwapForTokensIn({ ...args, tokens }); - }, - }, -}; - -export default balancerSdkResolvers; diff --git a/modules/beethoven/balancer-sor.test.ts b/modules/sor/balancer-sor.test.ts similarity index 100% rename from modules/beethoven/balancer-sor.test.ts rename to modules/sor/balancer-sor.test.ts diff --git a/modules/beethoven/balancer-sdk.gql b/modules/sor/sor.gql similarity index 93% rename from modules/beethoven/balancer-sdk.gql rename to modules/sor/sor.gql index 530ab20c2..716cf02d2 100644 --- a/modules/beethoven/balancer-sdk.gql +++ b/modules/sor/sor.gql @@ -7,6 +7,13 @@ extend type Query { swapAmount: BigDecimal! #expected in human readable form swapOptions: GqlSorSwapOptionsInput! ): GqlSorGetSwapsResponse! + sorGetCowSwaps( + chain: GqlChain! + tokenIn: String! + tokenOut: String! + swapType: GqlSorSwapType! + swapAmount: BigDecimal! #expected in raw amount + ): GqlCowSwapApiResponse! sorGetBatchSwapForTokensIn( tokensIn: [GqlTokenAmountHumanReadable!]! tokenOut: String! @@ -14,6 +21,27 @@ extend type Query { ): GqlSorGetBatchSwapForTokensInResponse! } +type GqlCowSwapApiResponse { + tokenAddresses: [String!]! + swaps: [GqlSwap!]! + swapAmount: String! + swapAmountForSwaps: String! + returnAmount: String! + returnAmountFromSwaps: String! + returnAmountConsideringFees: String! + tokenIn: String! + tokenOut: String! + marketSp: String! +} + +type GqlSwap { + poolId: String! + assetInIndex: Int! + assetOutIndex: Int! + amount: String! + userData: String! +} + enum GqlSorSwapType { EXACT_IN EXACT_OUT @@ -109,24 +137,3 @@ type GqlSorGetBatchSwapForTokensInResponse { swaps: [GqlSorSwap!]! assets: [String!]! } - -type GqlCowSwapApiResponse { - tokenAddresses: [String!]! - swaps: [GqlSwap!]! - swapAmount: String! - swapAmountForSwaps: String! - returnAmount: String! - returnAmountFromSwaps: String! - returnAmountConsideringFees: String! - tokenIn: String! - tokenOut: String! - marketSp: String! -} - -type GqlSwap { - poolId: String! - assetInIndex: Int! - assetOutIndex: Int! - amount: String! - userData: String! -} diff --git a/modules/sor/sor.resolvers.ts b/modules/sor/sor.resolvers.ts new file mode 100644 index 000000000..b4da3403d --- /dev/null +++ b/modules/sor/sor.resolvers.ts @@ -0,0 +1,31 @@ +import { Resolvers } from '../../schema'; +import { balancerSorService } from './sorV1Beets/balancer-sor.service'; +import { tokenService } from '../token/token.service'; +import { sorService } from './sor.service'; +import { getTokenAmountHuman } from './utils'; +import { headerChain } from '../context/header-chain'; + +const balancerSdkResolvers: Resolvers = { + Query: { + sorGetSwaps: async (parent, args, context) => { + const currentChain = headerChain(); + if (!args.chain && currentChain) { + args.chain = currentChain; + } else if (!args.chain) { + throw new Error('sorGetSwaps error: Provide "chain" param'); + } + + return sorService.getBeetsSwaps(args); + }, + sorGetBatchSwapForTokensIn: async (parent, args, context) => { + const tokens = await tokenService.getTokens(); + + return balancerSorService.getBatchSwapForTokensIn({ ...args, tokens }); + }, + sorGetCowSwaps: async (parent, args, context) => { + return sorService.getCowSwaps(args); + }, + }, +}; + +export default balancerSdkResolvers; diff --git a/modules/sor/sor.service.ts b/modules/sor/sor.service.ts index 33bd006a7..5019bebbb 100644 --- a/modules/sor/sor.service.ts +++ b/modules/sor/sor.service.ts @@ -1,4 +1,11 @@ -import { GqlCowSwapApiResponse, GqlSorSwapType, GqlSorGetSwapsResponse, GqlSorSwapOptionsInput } from '../../schema'; +import { + GqlCowSwapApiResponse, + GqlSorSwapType, + GqlSorGetSwapsResponse, + GqlSorSwapOptionsInput, + QuerySorGetSwapsArgs, + QuerySorGetCowSwapsArgs, +} from '../../schema'; import { sorV1BalancerService } from './sorV1Balancer/sorV1Balancer.service'; import { sorV1BeetsService } from './sorV1Beets/sorV1Beets.service'; import { sorV2Service } from './sorV2/sorV2.service'; @@ -8,32 +15,57 @@ import { publishMetric } from '../metrics/sor.metric'; import { Chain } from '@prisma/client'; import { parseUnits, formatUnits } from '@ethersproject/units'; import { tokenService } from '../token/token.service'; +import { getTokenAmountHuman, getTokenAmountRaw } from './utils'; export class SorService { - async getCowSwaps(input: GetSwapsInput): Promise { - const swap = await this.getSwap({ ...input, swapOptions: {} }); - const emptyResponse = EMPTY_COWSWAP_RESPONSE(input.tokenIn, input.tokenOut, input.swapAmount); + async getCowSwaps(args: QuerySorGetCowSwapsArgs): Promise { + const amountToken = args.swapType === 'EXACT_IN' ? args.tokenIn : args.tokenOut; + // Use TokenAmount to help follow scaling requirements in later logic + // args.swapAmount is RawScale, e.g. 1USDC should be passed as 1000000 + const amount = await getTokenAmountRaw(amountToken, args.swapAmount, args.chain!); + + const swap = await this.getSwap({ + chain: args.chain!, + swapAmount: amount, + swapType: args.swapType, + tokenIn: args.tokenIn.toLowerCase(), + tokenOut: args.tokenOut.toLowerCase(), + swapOptions: {}, + }); + const emptyResponse = EMPTY_COWSWAP_RESPONSE(args.tokenIn, args.tokenOut, amount); if (!swap) return emptyResponse; try { // Updates with latest onchain data before returning - return await swap.getCowSwapResponse(input.chain, true); + return await swap.getCowSwapResponse(args.chain!, true); } catch (err) { console.log(`Error Retrieving QuerySwap`, err); return emptyResponse; } } - async getBeetsSwaps(input: GetSwapsInput): Promise { - console.log('getBeetsSwaps input', JSON.stringify(input)); - const swap = await this.getSwap(input, sorV1BeetsService); - const emptyResponse = sorV1BeetsService.zeroResponse( - input.swapType, - input.tokenIn, - input.tokenOut, - input.swapAmount, + async getBeetsSwaps(args: QuerySorGetSwapsArgs): Promise { + console.log('getBeetsSwaps args', JSON.stringify(args)); + const tokenIn = args.tokenIn.toLowerCase(); + const tokenOut = args.tokenOut.toLowerCase(); + const amountToken = args.swapType === 'EXACT_IN' ? tokenIn : tokenOut; + // Use TokenAmount to help follow scaling requirements in later logic + // args.swapAmount is HumanScale + const amount = await getTokenAmountHuman(amountToken, args.swapAmount, args.chain!); + + const swap = await this.getSwap( + { + chain: args.chain!, + swapAmount: amount, + swapOptions: args.swapOptions, + swapType: args.swapType, + tokenIn: tokenIn, + tokenOut: tokenOut, + }, + sorV1BeetsService, ); + const emptyResponse = sorV1BeetsService.zeroResponse(args.swapType, args.tokenIn, args.tokenOut, amount); if (!swap) return emptyResponse; diff --git a/modules/beethoven/balancer-sor.service.ts b/modules/sor/sorV1Beets/balancer-sor.service.ts similarity index 96% rename from modules/beethoven/balancer-sor.service.ts rename to modules/sor/sorV1Beets/balancer-sor.service.ts index 7452f5ea0..6cf8fefa7 100644 --- a/modules/beethoven/balancer-sor.service.ts +++ b/modules/sor/sorV1Beets/balancer-sor.service.ts @@ -1,19 +1,19 @@ -import { GqlSorGetSwapsResponse, GqlSorSwapOptionsInput, GqlSorSwapType, GqlPoolMinimal } from '../../schema'; +import { GqlSorGetSwapsResponse, GqlSorSwapOptionsInput, GqlSorSwapType, GqlPoolMinimal } from '../../../schema'; import { formatFixed, parseFixed } from '@ethersproject/bignumber'; import { PrismaToken } from '@prisma/client'; -import { poolService } from '../pool/pool.service'; -import { oldBnum } from '../big-number/old-big-number'; +import { poolService } from '../../pool/pool.service'; +import { oldBnum } from '../../big-number/old-big-number'; import axios from 'axios'; import { FundManagement, SwapInfo, SwapTypes, SwapV2 } from '@balancer-labs/sdk'; -import { replaceEthWithZeroAddress, replaceZeroAddressWithEth } from '../web3/addresses'; +import { replaceEthWithZeroAddress, replaceZeroAddressWithEth } from '../../web3/addresses'; import { BigNumber } from 'ethers'; -import { TokenAmountHumanReadable } from '../common/global-types'; +import { TokenAmountHumanReadable } from '../../common/global-types'; import { AddressZero } from '@ethersproject/constants'; import { Contract } from '@ethersproject/contracts'; -import VaultAbi from '../pool/abi/Vault.json'; -import { env } from '../../app/env'; -import { networkContext } from '../network/network-context.service'; -import { DeploymentEnv } from '../network/network-config-types'; +import VaultAbi from '../../pool/abi/Vault.json'; +import { env } from '../../../app/env'; +import { networkContext } from '../../network/network-context.service'; +import { DeploymentEnv } from '../../network/network-config-types'; import * as Sentry from '@sentry/node'; import _ from 'lodash'; import { Logger } from '@ethersproject/logger'; diff --git a/modules/sor/sorV1Beets/sorV1Beets.service.ts b/modules/sor/sorV1Beets/sorV1Beets.service.ts index 067e5f87c..e91744ec7 100644 --- a/modules/sor/sorV1Beets/sorV1Beets.service.ts +++ b/modules/sor/sorV1Beets/sorV1Beets.service.ts @@ -1,7 +1,7 @@ import { formatEther } from 'viem'; import { GqlSorSwapType, GqlCowSwapApiResponse, GqlSorGetSwapsResponse, GqlSorSwapOptionsInput } from '../../../schema'; import { GetSwapsInput, SwapService, SwapResult } from '../types'; -import { BalancerSorService } from '../../beethoven/balancer-sor.service'; +import { BalancerSorService } from './balancer-sor.service'; import { tokenService } from '../../token/token.service'; import { TokenAmount } from '@balancer/sdk'; diff --git a/modules/sor/sorV2/sorV2.service.ts b/modules/sor/sorV2/sorV2.service.ts index a3b96fc2e..fd442dfae 100644 --- a/modules/sor/sorV2/sorV2.service.ts +++ b/modules/sor/sorV2/sorV2.service.ts @@ -32,7 +32,7 @@ import { prisma } from '../../../prisma/prisma-client'; import { GetSwapsInput, SwapResult, SwapService } from '../types'; import { poolService } from '../../pool/pool.service'; import { tokenService } from '../../token/token.service'; -import { BalancerSorService } from '../../beethoven/balancer-sor.service'; +import { BalancerSorService } from '../sorV1Beets/balancer-sor.service'; import { env } from '../../../app/env'; import { DeploymentEnv } from '../../network/network-config-types'; import { Cache, CacheClass } from 'memory-cache'; diff --git a/modules/sor/utils.ts b/modules/sor/utils.ts index ab47ae2b2..2c53582b9 100644 --- a/modules/sor/utils.ts +++ b/modules/sor/utils.ts @@ -22,7 +22,10 @@ export async function getTokenAmountRaw(tokenAddr: string, rawAmount: string, ch export const getToken = async (tokenAddr: string, chain: Chain): Promise => { const chainId = Number(chainToIdMap[chain]); - if (tokenAddr === NATIVE_ADDRESS && chainId in NATIVE_ASSETS) { + if ( + (tokenAddr === NATIVE_ADDRESS || tokenAddr === '0x0000000000000000000000000000000000001010') && + chainId in NATIVE_ASSETS + ) { return NATIVE_ASSETS[chainId as keyof typeof NATIVE_ASSETS]; } else { const prismaToken = await tokenService.getToken(tokenAddr, chain); From 03f51af83226135885962c1f61c3d0bc22d3a20e Mon Sep 17 00:00:00 2001 From: franz Date: Fri, 15 Dec 2023 11:03:09 +0100 Subject: [PATCH 20/44] rename --- modules/sor/sor.resolvers.ts | 2 +- modules/sor/sor.service.ts | 47 +++--- .../sorV1Balancer/sorV1Balancer.service.ts | 135 ------------------ modules/sor/utils.ts | 1 + 4 files changed, 19 insertions(+), 166 deletions(-) delete mode 100644 modules/sor/sorV1Balancer/sorV1Balancer.service.ts diff --git a/modules/sor/sor.resolvers.ts b/modules/sor/sor.resolvers.ts index b4da3403d..31fb1c044 100644 --- a/modules/sor/sor.resolvers.ts +++ b/modules/sor/sor.resolvers.ts @@ -15,7 +15,7 @@ const balancerSdkResolvers: Resolvers = { throw new Error('sorGetSwaps error: Provide "chain" param'); } - return sorService.getBeetsSwaps(args); + return sorService.getSorSwaps(args); }, sorGetBatchSwapForTokensIn: async (parent, args, context) => { const tokens = await tokenService.getTokens(); diff --git a/modules/sor/sor.service.ts b/modules/sor/sor.service.ts index 5019bebbb..ea1abecfa 100644 --- a/modules/sor/sor.service.ts +++ b/modules/sor/sor.service.ts @@ -2,16 +2,13 @@ import { GqlCowSwapApiResponse, GqlSorSwapType, GqlSorGetSwapsResponse, - GqlSorSwapOptionsInput, QuerySorGetSwapsArgs, QuerySorGetCowSwapsArgs, } from '../../schema'; -import { sorV1BalancerService } from './sorV1Balancer/sorV1Balancer.service'; import { sorV1BeetsService } from './sorV1Beets/sorV1Beets.service'; import { sorV2Service } from './sorV2/sorV2.service'; -import { GetSwapsInput, SwapResult, SwapService } from './types'; +import { GetSwapsInput, SwapResult } from './types'; import { EMPTY_COWSWAP_RESPONSE } from './constants'; -import { publishMetric } from '../metrics/sor.metric'; import { Chain } from '@prisma/client'; import { parseUnits, formatUnits } from '@ethersproject/units'; import { tokenService } from '../token/token.service'; @@ -19,12 +16,13 @@ import { getTokenAmountHuman, getTokenAmountRaw } from './utils'; export class SorService { async getCowSwaps(args: QuerySorGetCowSwapsArgs): Promise { + console.log('getCowSwaps args', JSON.stringify(args)); const amountToken = args.swapType === 'EXACT_IN' ? args.tokenIn : args.tokenOut; // Use TokenAmount to help follow scaling requirements in later logic // args.swapAmount is RawScale, e.g. 1USDC should be passed as 1000000 const amount = await getTokenAmountRaw(amountToken, args.swapAmount, args.chain!); - const swap = await this.getSwap({ + const swap = await sorV2Service.getSwapResult({ chain: args.chain!, swapAmount: amount, swapType: args.swapType, @@ -38,15 +36,15 @@ export class SorService { try { // Updates with latest onchain data before returning - return await swap.getCowSwapResponse(args.chain!, true); + return await swap.getCowSwapResponse(true); } catch (err) { console.log(`Error Retrieving QuerySwap`, err); return emptyResponse; } } - async getBeetsSwaps(args: QuerySorGetSwapsArgs): Promise { - console.log('getBeetsSwaps args', JSON.stringify(args)); + async getSorSwaps(args: QuerySorGetSwapsArgs): Promise { + console.log('getSorSwaps args', JSON.stringify(args)); const tokenIn = args.tokenIn.toLowerCase(); const tokenOut = args.tokenOut.toLowerCase(); const amountToken = args.swapType === 'EXACT_IN' ? tokenIn : tokenOut; @@ -54,34 +52,30 @@ export class SorService { // args.swapAmount is HumanScale const amount = await getTokenAmountHuman(amountToken, args.swapAmount, args.chain!); - const swap = await this.getSwap( - { - chain: args.chain!, - swapAmount: amount, - swapOptions: args.swapOptions, - swapType: args.swapType, - tokenIn: tokenIn, - tokenOut: tokenOut, - }, - sorV1BeetsService, - ); + const swap = await this.getComparingSwap({ + chain: args.chain!, + swapAmount: amount, + swapOptions: args.swapOptions, + swapType: args.swapType, + tokenIn: tokenIn, + tokenOut: tokenOut, + }); const emptyResponse = sorV1BeetsService.zeroResponse(args.swapType, args.tokenIn, args.tokenOut, amount); if (!swap) return emptyResponse; try { // Updates with latest onchain data before returning - return swap.getBeetsSwapResponse(true); + return swap.getSorSwapResponse(true); } catch (err) { console.log(`Error Retrieving QuerySwap`, err); return emptyResponse; } } - private async getSwap(input: GetSwapsInput, v1Service: SwapService = sorV1BalancerService) { - console.log(`Running SOR for ${input.swapAmount} ${input.tokenIn} > ${input.tokenOut}`); + private async getComparingSwap(input: GetSwapsInput) { const v1Start = +new Date(); - const swapV1 = await v1Service.getSwapResult(input); + const swapV1 = await sorV1BeetsService.getSwapResult(input); const v1Time = +new Date() - v1Start; const v2Start = +new Date(); @@ -155,9 +149,6 @@ export class SorService { v1Time: number, v2Time: number, ) { - // await publishMetric(chain, `SOR_VALID_V1`, v1.isValid ? 1 : 0); - // await publishMetric(chain, `SOR_VALID_V2`, v2.isValid ? 1 : 0); - if (!version) return; let v1ResultAmount = v1.inputAmount; @@ -187,10 +178,6 @@ export class SorService { let diff = bn(diffN.toFixed(decimals), decimals); let bestResultAmount = version === 'V1' ? v1ResultAmount : v2ResultAmount; - // await publishMetric(chain, `SOR_TIME_V1`, v1Time); - // await publishMetric(chain, `SOR_TIME_V2`, v2Time); - // await publishMetric(chain, `SOR_V2_PERFORMACE`, v2Perf); - console.log( [ 'SOR_RESULT', diff --git a/modules/sor/sorV1Balancer/sorV1Balancer.service.ts b/modules/sor/sorV1Balancer/sorV1Balancer.service.ts deleted file mode 100644 index f35d98914..000000000 --- a/modules/sor/sorV1Balancer/sorV1Balancer.service.ts +++ /dev/null @@ -1,135 +0,0 @@ -import axios from 'axios'; -import * as Sentry from '@sentry/node'; -import { AddressZero } from '@ethersproject/constants'; -import { Contract } from '@ethersproject/contracts'; -import { GqlSorSwapType, GqlCowSwapApiResponse, GqlSorGetSwapsResponse } from '../../../schema'; -import { GetSwapsInput, SwapService, SwapResult } from '../types'; -import { FundManagement, SwapTypes, SwapV2 } from '@balancer-labs/sdk'; -import { env } from '../../../app/env'; -import { AllNetworkConfigs, AllNetworkConfigsKeyedOnChain, chainToIdMap } from '../../network/network-config'; -import { DeploymentEnv } from '../../network/network-config-types'; - -import VaultAbi from '../../pool/abi/Vault.json'; -import { BigNumber } from 'ethers'; -import { TokenAmount } from '@balancer/sdk'; -import { Chain } from '@prisma/client'; - -type CowSwapSwapType = 'buy' | 'sell'; - -class SwapResultV1 implements SwapResult { - public inputAmount: bigint = BigInt(0); - public outputAmount: bigint = BigInt(0); - public isValid: boolean; - - constructor(private swap: GqlCowSwapApiResponse | null, private swapType: GqlSorSwapType) { - if (swap === null) { - this.isValid = false; - this.swap = null; - } else { - this.inputAmount = swapType === 'EXACT_IN' ? BigInt(swap.swapAmount) : BigInt(swap.returnAmount); - this.outputAmount = swapType === 'EXACT_IN' ? BigInt(swap.returnAmount) : BigInt(swap.swapAmount); - this.isValid = swap.swaps.length === 0 ? false : true; - } - } - - async getCowSwapResponse(chain: Chain, queryFirst = false): Promise { - if (!this.isValid || this.swap === null) throw new Error('No Response - Invalid Swap'); - - if (queryFirst) { - const swapType = this.mapSwapType(this.swapType); - const deltas = await this.queryBatchSwap(swapType, this.swap.swaps, this.swap.tokenAddresses, chain); - const tokenInAmount = deltas[this.swap.tokenAddresses.indexOf(this.swap.tokenIn)].toString(); - const tokenOutAmount = deltas[this.swap.tokenAddresses.indexOf(this.swap.tokenOut)].abs().toString(); - // console.log(`UPDATE:`, this.inputAmount, this.outputAmount, tokenInAmount, tokenOutAmount, deltas.toString()); - return { - ...this.swap, - returnAmount: swapType === SwapTypes.SwapExactIn ? tokenOutAmount : tokenInAmount, - swapAmount: swapType === SwapTypes.SwapExactIn ? tokenInAmount : tokenOutAmount, - }; - } - return this.swap; - } - - async getBeetsSwapResponse(queryFirst: boolean): Promise { - throw new Error('Use Beets service.'); - } - - private queryBatchSwap(swapType: SwapTypes, swaps: SwapV2[], assets: string[], chain: Chain): Promise { - const vault = AllNetworkConfigsKeyedOnChain[chain].data.balancer.vault; - const provider = AllNetworkConfigsKeyedOnChain[chain].provider; - - const vaultContract = new Contract(vault, VaultAbi, provider); - const funds: FundManagement = { - sender: AddressZero, - recipient: AddressZero, - fromInternalBalance: false, - toInternalBalance: false, - }; - - return vaultContract.queryBatchSwap(swapType, swaps, assets, funds); - } - - private mapSwapType(swapType: GqlSorSwapType): SwapTypes { - return swapType === 'EXACT_IN' ? SwapTypes.SwapExactIn : SwapTypes.SwapExactOut; - } -} -export class SorV1BalancerService implements SwapService { - public async getSwapResult({ chain, tokenIn, tokenOut, swapType, swapAmount }: GetSwapsInput): Promise { - try { - const swap = await this.querySorBalancer(chain, swapType, tokenIn, tokenOut, swapAmount); - return new SwapResultV1(swap, swapType); - } catch (err: any) { - console.error( - `SOR_V1_ERROR ${err.message} - tokenIn: ${tokenIn} - tokenOut: ${tokenOut} - swapAmount: ${swapAmount.amount} - swapType: ${swapType} - chain: ${chain}`, - ); - Sentry.captureException(err.message, { - tags: { - service: 'sorV1', - tokenIn, - tokenOut, - swapAmount: swapAmount.amount, - swapType, - chain, - }, - }); - return new SwapResultV1(null, swapType); - } - } - - /** - * Query Balancer API CowSwap/SOR endpoint. - * @param swapType - * @param tokenIn - * @param tokenOut - * @param swapAmountScaled - * @param swapOptions - * @returns - */ - private async querySorBalancer( - chain: Chain, - swapType: GqlSorSwapType, - tokenIn: string, - tokenOut: string, - swapAmount: TokenAmount, - ): Promise { - const chainId = chainToIdMap[chain]; - const endPoint = `https://api.balancer.fi/sor/${chainId}`; - const gasPrice = AllNetworkConfigs[chainId].data.sor[env.DEPLOYMENT_ENV as DeploymentEnv].gasPrice.toString(); - const swapData = { - orderKind: this.mapSwapType(swapType), - sellToken: tokenIn, - buyToken: tokenOut, - amount: swapAmount.amount.toString(), - gasPrice, - }; - - const { data } = await axios.post(endPoint, swapData); - return data; - } - - private mapSwapType(swapType: GqlSorSwapType): CowSwapSwapType { - return swapType === 'EXACT_IN' ? 'sell' : 'buy'; - } -} - -export const sorV1BalancerService = new SorV1BalancerService(); diff --git a/modules/sor/utils.ts b/modules/sor/utils.ts index 2c53582b9..4e10b55c8 100644 --- a/modules/sor/utils.ts +++ b/modules/sor/utils.ts @@ -22,6 +22,7 @@ export async function getTokenAmountRaw(tokenAddr: string, rawAmount: string, ch export const getToken = async (tokenAddr: string, chain: Chain): Promise => { const chainId = Number(chainToIdMap[chain]); + // also check for the polygon native asset if ( (tokenAddr === NATIVE_ADDRESS || tokenAddr === '0x0000000000000000000000000000000000001010') && chainId in NATIVE_ASSETS From 55fd61c234a4f78d72f4d6c5a97b39f40831ca16 Mon Sep 17 00:00:00 2001 From: franz Date: Fri, 15 Dec 2023 11:03:59 +0100 Subject: [PATCH 21/44] query first for v2 --- modules/sor/sorV1Beets/sorV1Beets.service.ts | 8 ++--- modules/sor/sorV2/sorV2.service.ts | 34 +++++++++++++------- modules/sor/types.ts | 4 +-- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/modules/sor/sorV1Beets/sorV1Beets.service.ts b/modules/sor/sorV1Beets/sorV1Beets.service.ts index e91744ec7..3b299996f 100644 --- a/modules/sor/sorV1Beets/sorV1Beets.service.ts +++ b/modules/sor/sorV1Beets/sorV1Beets.service.ts @@ -23,11 +23,11 @@ class SwapResultV1 implements SwapResult { } } - async getCowSwapResponse(chain = 'MAINNET', queryFirst = false): Promise { + async getCowSwapResponse(queryFirst = false): Promise { throw new Error('Use Balancer Service'); } - async getBeetsSwapResponse(queryFirst: boolean): Promise { + async getSorSwapResponse(queryFirst: boolean): Promise { if (!this.isValid || this.swap === null) throw new Error('No Response - Invalid Swap'); // Beets service is already querying onchain return this.swap; @@ -42,7 +42,7 @@ export class SorV1BeetsService implements SwapService { public async getSwapResult(input: GetSwapsInput & { swapOptions: GqlSorSwapOptionsInput }): Promise { try { - const swap = await this.querySorBeets(input); + const swap = await this.querySorV1(input); return new SwapResultV1(swap, input.swapType); } catch (err) { console.log(`sorV1 Service Error`, err); @@ -59,7 +59,7 @@ export class SorV1BeetsService implements SwapService { return this.sorService.zeroResponse(swapType, tokenIn, tokenOut, formatEther(swapAmount.scale18)); } - private async querySorBeets( + private async querySorV1( input: GetSwapsInput & { swapOptions: GqlSorSwapOptionsInput }, ): Promise { const tokens = await tokenService.getTokens(); diff --git a/modules/sor/sorV2/sorV2.service.ts b/modules/sor/sorV2/sorV2.service.ts index fd442dfae..e747531b7 100644 --- a/modules/sor/sorV2/sorV2.service.ts +++ b/modules/sor/sorV2/sorV2.service.ts @@ -49,43 +49,53 @@ const ALL_BASEPOOLS_CACHE_KEY = `basePools:all`; class SwapResultV2 implements SwapResult { private swap: SwapSdk | null; + private chain: Chain; public inputAmount: bigint = BigInt(0); public outputAmount: bigint = BigInt(0); public isValid: boolean; - constructor(swap: SwapSdk | null) { + constructor(swap: SwapSdk | null, chain: Chain) { if (swap === null) { this.isValid = false; this.swap = null; + this.chain = chain; } else { this.isValid = true; this.swap = swap; this.inputAmount = swap.inputAmount.amount; this.outputAmount = swap.outputAmount.amount; + this.chain = chain; } } - async getCowSwapResponse(chain: Chain, queryFirst = false): Promise { + async getCowSwapResponse(queryFirst = false): Promise { if (!this.isValid || this.swap === null) throw new Error('No Response - Invalid Swap'); if (!queryFirst) return this.mapResultToCowSwap(this.swap, this.swap.inputAmount, this.swap.outputAmount); else { - const rpcUrl = AllNetworkConfigsKeyedOnChain[chain].data.rpcUrl; - // Needs node >= 18 (https://github.com/wagmi-dev/viem/discussions/147) + const rpcUrl = AllNetworkConfigsKeyedOnChain[this.chain].data.rpcUrl; const updatedResult = await this.swap.query(rpcUrl); - // console.log(`UPDATE:`, this.swap.quote.amount.toString(), updatedResult.amount.toString()); - const ip = this.swap.swapKind === SwapKind.GivenIn ? this.swap.inputAmount : updatedResult; - const op = this.swap.swapKind === SwapKind.GivenIn ? updatedResult : this.swap.outputAmount; + const inputAmount = this.swap.swapKind === SwapKind.GivenIn ? this.swap.inputAmount : updatedResult; + const outputAmount = this.swap.swapKind === SwapKind.GivenIn ? updatedResult : this.swap.outputAmount; - return this.mapResultToCowSwap(this.swap, ip, op); + return this.mapResultToCowSwap(this.swap, inputAmount, outputAmount); } } - async getBeetsSwapResponse(queryFirst: boolean): Promise { + async getSorSwapResponse(queryFirst = false): Promise { if (!this.isValid || this.swap === null) throw new Error('No Response - Invalid Swap'); - return await this.mapResultToBeetsSwap(this.swap, this.swap.inputAmount, this.swap.outputAmount); + if (!queryFirst) return this.mapResultToBeetsSwap(this.swap, this.swap.inputAmount, this.swap.outputAmount); + else { + const rpcUrl = AllNetworkConfigsKeyedOnChain[this.chain].data.rpcUrl; + const updatedResult = await this.swap.query(rpcUrl); + + const inputAmount = this.swap.swapKind === SwapKind.GivenIn ? this.swap.inputAmount : updatedResult; + const outputAmount = this.swap.swapKind === SwapKind.GivenIn ? updatedResult : this.swap.outputAmount; + + return this.mapResultToBeetsSwap(this.swap, inputAmount, outputAmount); + } } private async mapResultToBeetsSwap( @@ -308,7 +318,7 @@ export class SorV2Service implements SwapService { if (!swap && maxNonBoostedPathDepth < 4) { return this.getSwapResult(arguments[0], maxNonBoostedPathDepth + 1); } - return new SwapResultV2(swap); + return new SwapResultV2(swap, chain); } catch (err: any) { console.error( `SOR_V2_ERROR ${err.message} - tokenIn: ${tokenIn} - tokenOut: ${tokenOut} - swapAmount: ${swapAmount.amount} - swapType: ${swapType} - chain: ${chain}`, @@ -323,7 +333,7 @@ export class SorV2Service implements SwapService { chain, }, }); - return new SwapResultV2(null); + return new SwapResultV2(null, chain); } } diff --git a/modules/sor/types.ts b/modules/sor/types.ts index 564647c84..2059332ec 100644 --- a/modules/sor/types.ts +++ b/modules/sor/types.ts @@ -19,8 +19,8 @@ export interface GraphTraversalConfig { } export interface SwapResult { - getCowSwapResponse(chain: Chain, queryFirst: boolean): Promise; - getBeetsSwapResponse(queryFirst: boolean): Promise; + getCowSwapResponse(queryFirst: boolean): Promise; + getSorSwapResponse(queryFirst: boolean): Promise; isValid: boolean; outputAmount: bigint; inputAmount: bigint; From 1c1e46476e11d080a3229cc7a0ed8f4c31560be5 Mon Sep 17 00:00:00 2001 From: franz Date: Fri, 15 Dec 2023 11:52:18 +0100 Subject: [PATCH 22/44] add polygon native address --- modules/sor/sorV1Beets/balancer-sor.service.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/sor/sorV1Beets/balancer-sor.service.ts b/modules/sor/sorV1Beets/balancer-sor.service.ts index 6cf8fefa7..19d5c2b3a 100644 --- a/modules/sor/sorV1Beets/balancer-sor.service.ts +++ b/modules/sor/sorV1Beets/balancer-sor.service.ts @@ -332,7 +332,11 @@ export class BalancerSorService { } private getTokenDecimals(tokenAddress: string, tokens: PrismaToken[]): number { - if (tokenAddress === ZERO_ADDRESS || tokenAddress === NATIVE_ADDRESS) { + if ( + tokenAddress === ZERO_ADDRESS || + tokenAddress === NATIVE_ADDRESS || + tokenAddress === '0x0000000000000000000000000000000000001010' + ) { return 18; } From 0c9d1989ef819821ec2e5fbf5102479dffc21d7e Mon Sep 17 00:00:00 2001 From: gmbronco <83549293+gmbronco@users.noreply.github.com> Date: Fri, 15 Dec 2023 12:17:08 +0100 Subject: [PATCH 23/44] isolate networkContext in the getters --- .../lib/user-sync-gauge-balance.service.ts | 89 +++++++++++-------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/modules/user/lib/user-sync-gauge-balance.service.ts b/modules/user/lib/user-sync-gauge-balance.service.ts index 93dd0efb8..9c99c4f60 100644 --- a/modules/user/lib/user-sync-gauge-balance.service.ts +++ b/modules/user/lib/user-sync-gauge-balance.service.ts @@ -14,6 +14,30 @@ import { gaugeSubgraphService } from '../../subgraphs/gauge-subgraph/gauge-subgr import { AddressZero } from '@ethersproject/constants'; export class UserSyncGaugeBalanceService implements UserStakedBalanceService { + get chain() { + return networkContext.chain; + } + + get chainId() { + return networkContext.chainId; + } + + get provider() { + return networkContext.provider; + } + + get rpcUrl() { + return networkContext.data.rpcUrl; + } + + get rpcMaxBlockRange() { + return networkContext.data.rpcMaxBlockRange; + } + + get multicallAddress() { + return networkContext.data.multicall; + } + public async initStakedBalances(stakingTypes: PrismaPoolStakingType[]): Promise { if (!stakingTypes.includes('GAUGE')) { return; @@ -25,7 +49,7 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { console.log('initStakedBalances: loading pools...'); const pools = await prisma.prismaPool.findMany({ select: { id: true }, - where: { chain: networkContext.chain }, + where: { chain: this.chain }, }); const filteredGaugeShares = gaugeShares.filter((share) => { @@ -45,14 +69,14 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { data: userAddresses.map((userAddress) => ({ address: userAddress })), skipDuplicates: true, }), - prisma.prismaUserStakedBalance.deleteMany({ where: { chain: networkContext.chain } }), + prisma.prismaUserStakedBalance.deleteMany({ where: { chain: this.chain } }), prisma.prismaUserStakedBalance.createMany({ data: filteredGaugeShares.map((share) => { const pool = pools.find((pool) => pool.id === share.gauge.poolId); return { id: `${share.gauge.id}-${share.user.id}`, - chain: networkContext.chain, + chain: this.chain, balance: share.balance, balanceNum: parseFloat(share.balance), userAddress: share.user.id, @@ -63,8 +87,8 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { }), }), prisma.prismaUserBalanceSyncStatus.upsert({ - where: { type_chain: { type: 'STAKED', chain: networkContext.chain } }, - create: { type: 'STAKED', chain: networkContext.chain, blockNumber: block.number }, + where: { type_chain: { type: 'STAKED', chain: this.chain } }, + create: { type: 'STAKED', chain: this.chain, blockNumber: block.number }, update: { blockNumber: block.number }, }), ], @@ -77,7 +101,7 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { public async syncChangedStakedBalances(): Promise { // we always store the latest synced block const status = await prisma.prismaUserBalanceSyncStatus.findUnique({ - where: { type_chain: { type: 'STAKED', chain: networkContext.chain } }, + where: { type_chain: { type: 'STAKED', chain: this.chain } }, }); if (!status) { @@ -86,12 +110,12 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { const pools = await prisma.prismaPool.findMany({ include: { staking: true }, - where: { chain: networkContext.chain }, + where: { chain: this.chain }, }); - console.log(`user-sync-staked-balances-${networkContext.chainId} got data from db.`); + console.log(`user-sync-staked-balances-${this.chainId} got data from db.`); - const latestBlock = await networkContext.provider.getBlockNumber(); - console.log(`user-sync-staked-balances-${networkContext.chainId} got latest block.`); + const latestBlock = await this.provider.getBlockNumber(); + console.log(`user-sync-staked-balances-${this.chainId} got latest block.`); const gaugeAddresses = await gaugeSubgraphService.getAllGaugeAddresses(); @@ -111,18 +135,15 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { const erc20Interface = new ethers.utils.Interface(ERC20Abi); // Split the range into smaller chunks to avoid RPC limits, setting up to 50 times max block range - const maxBlockRange = networkContext.data.rpcMaxBlockRange; - const toBlock = Math.min(startBlock + 50 * maxBlockRange, latestBlock); + const toBlock = Math.min(startBlock + 50 * this.rpcMaxBlockRange, latestBlock); const range = toBlock - startBlock; - console.log(`user-sync-staked-balances-${networkContext.chainId} block range from ${startBlock} to ${toBlock}`); - console.log( - `user-sync-staked-balances-${networkContext.chainId} getLogs for ${_.uniq(gaugeAddresses).length} gauges.`, - ); + console.log(`user-sync-staked-balances-${this.chainId} block range from ${startBlock} to ${toBlock}`); + console.log(`user-sync-staked-balances-${this.chainId} getLogs for ${_.uniq(gaugeAddresses).length} gauges.`); const events = await Promise.all( // Getting logs in batches of max blocks allowed by RPC - Array.from({ length: Math.ceil(range / maxBlockRange) }, (_, i) => i).map(async (i) => { - const from = startBlock + i * maxBlockRange; - const to = Math.min(startBlock + (i + 1) * maxBlockRange, toBlock); + Array.from({ length: Math.ceil(range / this.rpcMaxBlockRange) }, (_, i) => i).map(async (i) => { + const from = startBlock + i * this.rpcMaxBlockRange; + const to = Math.min(startBlock + (i + 1) * this.rpcMaxBlockRange, toBlock); // Usually RPCs are handling any number of addresses, but it here batching just to be on the safe side const logRequests: Promise[] = _.chunk(gaugeAddresses, 500).map((addresses) => { @@ -141,7 +162,7 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { ], }; - return fetch(networkContext.data.rpcUrl, { + return fetch(this.rpcUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -162,9 +183,7 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { }), ).then((res) => res.flat().filter((event) => event)); - console.log( - `user-sync-staked-balances-${networkContext.chainId} getLogs for ${gaugeAddresses.length} gauges done`, - ); + console.log(`user-sync-staked-balances-${this.chainId} getLogs for ${gaugeAddresses.length} gauges done`); const balancesToFetch = _.uniqBy( events @@ -180,13 +199,11 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { (entry) => entry.erc20Address + entry.userAddress, ); - console.log( - `user-sync-staked-balances-${networkContext.chainId} got ${balancesToFetch.length} balances to fetch.`, - ); + console.log(`user-sync-staked-balances-${this.chainId} got ${balancesToFetch.length} balances to fetch.`); if (balancesToFetch.length === 0) { await prisma.prismaUserBalanceSyncStatus.update({ - where: { type_chain: { type: 'STAKED', chain: networkContext.chain } }, + where: { type_chain: { type: 'STAKED', chain: this.chain } }, data: { blockNumber: endBlock }, }); @@ -194,14 +211,12 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { } const balances = await Multicaller.fetchBalances({ - multicallAddress: networkContext.data.multicall, - provider: networkContext.provider, + multicallAddress: this.multicallAddress, + provider: this.provider, balancesToFetch, }); - console.log( - `user-sync-staked-balances-${networkContext.chainId} got ${balancesToFetch.length} balances to fetch done.`, - ); + console.log(`user-sync-staked-balances-${this.chainId} got ${balancesToFetch.length} balances to fetch done.`); await prismaBulkExecuteOperations( [ @@ -220,7 +235,7 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { where: { id_chain: { id: `${userBalance.erc20Address}-${userBalance.userAddress}`, - chain: networkContext.chain, + chain: this.chain, }, }, update: { @@ -229,7 +244,7 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { }, create: { id: `${userBalance.erc20Address}-${userBalance.userAddress}`, - chain: networkContext.chain, + chain: this.chain, balance: formatFixed(userBalance.balance, 18), balanceNum: parseFloat(formatFixed(userBalance.balance, 18)), userAddress: userBalance.userAddress, @@ -243,7 +258,7 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { where: { type_chain: { type: 'STAKED', - chain: networkContext.chain, + chain: this.chain, }, }, data: { blockNumber: endBlock }, @@ -259,14 +274,14 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { const amount = formatFixed(balance, 18); await prisma.prismaUserStakedBalance.upsert({ - where: { id_chain: { id: `${staking.address}-${userAddress}`, chain: networkContext.chain } }, + where: { id_chain: { id: `${staking.address}-${userAddress}`, chain: this.chain } }, update: { balance: amount, balanceNum: parseFloat(amount), }, create: { id: `${staking.address}-${userAddress}`, - chain: networkContext.chain, + chain: this.chain, balance: amount, balanceNum: parseFloat(amount), userAddress: userAddress, From e475429d1f21b5b7dcc5c585a425ab8073847205 Mon Sep 17 00:00:00 2001 From: franz Date: Fri, 15 Dec 2023 14:15:24 +0100 Subject: [PATCH 24/44] decimals for native asset --- modules/sor/sor.service.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/sor/sor.service.ts b/modules/sor/sor.service.ts index 33bd006a7..dc5ac98ce 100644 --- a/modules/sor/sor.service.ts +++ b/modules/sor/sor.service.ts @@ -47,7 +47,6 @@ export class SorService { } private async getSwap(input: GetSwapsInput, v1Service: SwapService = sorV1BalancerService) { - console.log(`Running SOR for ${input.swapAmount} ${input.tokenIn} > ${input.tokenOut}`); const v1Start = +new Date(); const swapV1 = await v1Service.getSwapResult(input); const v1Time = +new Date() - v1Start; @@ -144,7 +143,7 @@ export class SorService { const fp = (a: bigint, d: number) => Number(formatUnits(String(a), d)); const bn = (a: string, d: number) => BigInt(String(parseUnits(a, d))); const prismaToken = await tokenService.getToken(resultToken, chain); - const decimals = prismaToken!.decimals; + const decimals = prismaToken ? prismaToken.decimals : 18; // most probably native asset let v2Perf = version === 'V1' ? 1 - fp(v1ResultAmount, decimals) / fp(v2ResultAmount, decimals) // negative perf means V1 is better From 05c0e45abc946b7927f310d17040d77e059a5da9 Mon Sep 17 00:00:00 2001 From: franz Date: Fri, 15 Dec 2023 14:22:49 +0100 Subject: [PATCH 25/44] bump bsdk --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 9be908911..ce3785b5f 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "@aws-sdk/client-secrets-manager": "^3.195.0", "@aws-sdk/client-sqs": "^3.137.0", "@balancer-labs/sdk": "github:beethovenxfi/balancer-sdk#beethovenx-master", - "@balancer/sdk": "^0.4.0", + "@balancer/sdk": "^0.5.0", "@ethersproject/address": "^5.6.0", "@ethersproject/bignumber": "^5.6.0", "@ethersproject/constants": "^5.6.0", diff --git a/yarn.lock b/yarn.lock index 3374ba4bd..1f593b651 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2456,10 +2456,10 @@ graphology "^0.24.1" isomorphic-fetch "^2.2.1" -"@balancer/sdk@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@balancer/sdk/-/sdk-0.4.0.tgz#9fe762e1b7f6cad574a1603bdc33e77c6e1ab426" - integrity sha512-g8ilzNSlk2Pdh7PUAyr88sD78GGDTOUJUpAhKBO5dN77Kk70ivyL6mNJBGpJqrjraoBygv6yQukV8yO5m0kiEw== +"@balancer/sdk@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@balancer/sdk/-/sdk-0.5.0.tgz#098b2fd019a0460c2ad13c20f1f6a058573a08d2" + integrity sha512-2ys18xZAfGvwJpQmStmX2O6b/QkIQQWHpm09/qk2oHDg/lhnYYY5otfs14QuEQubdlA3Kth0U0uAxMlc4NxN/w== dependencies: async-retry "^1.3.3" decimal.js-light "^2.5.1" From 52a4c53c01443dc0afb3c605b0e91e235fd03187 Mon Sep 17 00:00:00 2001 From: franz Date: Mon, 18 Dec 2023 13:15:18 +0100 Subject: [PATCH 26/44] change to new balancer subgraph code --- modules/network/fantom.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/network/fantom.ts b/modules/network/fantom.ts index ca6112e98..486301112 100644 --- a/modules/network/fantom.ts +++ b/modules/network/fantom.ts @@ -39,7 +39,7 @@ const fantomNetworkData: NetworkData = { }, subgraphs: { startDate: '2021-10-08', - balancer: 'https://api.thegraph.com/subgraphs/name/beethovenxfi/beethovenx', + balancer: 'https://api.thegraph.com/subgraphs/name/beethovenxfi/beethovenx-v2-fantom', beetsBar: 'https://api.thegraph.com/subgraphs/name/beethovenxfi/beets-bar', blocks: 'https://api.thegraph.com/subgraphs/name/beethovenxfi/fantom-blocks', masterchef: 'https://api.thegraph.com/subgraphs/name/beethovenxfi/masterchefv2', @@ -349,7 +349,10 @@ export const fantomNetworkConfig: NetworkConfig = { new UserSyncReliquaryFarmBalanceService(fantomNetworkData.reliquary!.address), ], services: { - balancerSubgraphService: new BalancerSubgraphService(fantomNetworkData.subgraphs.balancer, fantomNetworkData.chain.id), + balancerSubgraphService: new BalancerSubgraphService( + fantomNetworkData.subgraphs.balancer, + fantomNetworkData.chain.id, + ), }, /* For sub-minute jobs we set the alarmEvaluationPeriod and alarmDatapointsToAlarm to 1 instead of the default 3. From 1612fe7af51cb15fe5423fd3473214f0c14bdd05 Mon Sep 17 00:00:00 2001 From: franz Date: Mon, 18 Dec 2023 15:33:17 +0100 Subject: [PATCH 27/44] add field to all pools, fix error --- modules/pool/lib/pool-gql-loader.service.ts | 26 ++++----------------- modules/pool/pool.gql | 16 +++++++++++++ modules/pool/pool.resolvers.ts | 2 +- modules/pool/pool.service.ts | 4 +--- 4 files changed, 22 insertions(+), 26 deletions(-) diff --git a/modules/pool/lib/pool-gql-loader.service.ts b/modules/pool/lib/pool-gql-loader.service.ts index c0671a828..a2b366265 100644 --- a/modules/pool/lib/pool-gql-loader.service.ts +++ b/modules/pool/lib/pool-gql-loader.service.ts @@ -30,7 +30,6 @@ import { GqlPoolUserBalance, GqlPoolWithdrawConfig, GqlPoolWithdrawOption, - InputMaybe, QueryPoolGetPoolsArgs, } from '../../../schema'; import { isSameAddress } from '@balancer-labs/sdk'; @@ -45,7 +44,7 @@ import { parseUnits } from 'ethers/lib/utils'; import { formatFixed } from '@ethersproject/bignumber'; export class PoolGqlLoaderService { - public async getPool(id: string, chain: Chain, userAddress?: InputMaybe): Promise { + public async getPool(id: string, chain: Chain, userAddress?: string): Promise { let pool = undefined; pool = await prisma.prismaPool.findUnique({ where: { id_chain: { id, chain: chain } }, @@ -63,7 +62,7 @@ export class PoolGqlLoaderService { throw new Error('Pool exists, but has an unknown type'); } - return this.mapPoolToGqlPool(pool); + return this.mapPoolToGqlPool(pool, pool.userWalletBalances, pool.userStakedBalances); } public async getPools(args: QueryPoolGetPoolsArgs): Promise { @@ -82,24 +81,7 @@ export class PoolGqlLoaderService { ...this.mapQueryArgsToPoolQuery(args), include: { ...prismaPoolMinimal.include, - userWalletBalances: { - where: { - userAddress: { - equals: args.where?.userAddress, - mode: 'insensitive' as const, - }, - balanceNum: { gt: 0 }, - }, - }, - userStakedBalances: { - where: { - userAddress: { - equals: args.where?.userAddress, - mode: 'insensitive' as const, - }, - balanceNum: { gt: 0 }, - }, - }, + ...this.getUserBalancesInclude(args.where.userAddress), }, }); @@ -1267,7 +1249,7 @@ export class PoolGqlLoaderService { }; } - private getUserBalancesInclude(userAddress?: InputMaybe) { + private getUserBalancesInclude(userAddress?: string) { if (!userAddress) { return {}; } diff --git a/modules/pool/pool.gql b/modules/pool/pool.gql index d7046df63..f1b047f04 100644 --- a/modules/pool/pool.gql +++ b/modules/pool/pool.gql @@ -232,6 +232,8 @@ type GqlPoolWeighted implements GqlPoolBase { staking: GqlPoolStaking type: String! version: Int! + + userBalance: GqlPoolUserBalance } type GqlPoolGyro implements GqlPoolBase { @@ -274,6 +276,8 @@ type GqlPoolGyro implements GqlPoolBase { staking: GqlPoolStaking type: String! version: Int! + + userBalance: GqlPoolUserBalance } type GqlPoolLiquidityBootstrapping implements GqlPoolBase { @@ -297,6 +301,8 @@ type GqlPoolLiquidityBootstrapping implements GqlPoolBase { staking: GqlPoolStaking type: String! version: Int! + + userBalance: GqlPoolUserBalance } type GqlPoolStable implements GqlPoolBase { @@ -320,6 +326,8 @@ type GqlPoolStable implements GqlPoolBase { staking: GqlPoolStaking type: String! version: Int! + + userBalance: GqlPoolUserBalance } type GqlPoolMetaStable implements GqlPoolBase { @@ -343,6 +351,8 @@ type GqlPoolMetaStable implements GqlPoolBase { staking: GqlPoolStaking type: String! version: Int! + + userBalance: GqlPoolUserBalance } type GqlPoolPhantomStable implements GqlPoolBase { @@ -367,6 +377,8 @@ type GqlPoolPhantomStable implements GqlPoolBase { bptPriceRate: BigDecimal! type: String! version: Int! + + userBalance: GqlPoolUserBalance } type GqlPoolElement implements GqlPoolBase { @@ -393,6 +405,8 @@ type GqlPoolElement implements GqlPoolBase { staking: GqlPoolStaking type: String! version: Int! + + userBalance: GqlPoolUserBalance } type GqlPoolLinear implements GqlPoolBase { @@ -421,6 +435,8 @@ type GqlPoolLinear implements GqlPoolBase { bptPriceRate: BigDecimal! type: String! version: Int! + + userBalance: GqlPoolUserBalance } type GqlPoolLinearNested { diff --git a/modules/pool/pool.resolvers.ts b/modules/pool/pool.resolvers.ts index 8acf48937..c6478733d 100644 --- a/modules/pool/pool.resolvers.ts +++ b/modules/pool/pool.resolvers.ts @@ -14,7 +14,7 @@ const balancerResolvers: Resolvers = { } else if (!chain) { throw new Error('poolGetPool error: Provide "chain" param'); } - return poolService.getGqlPool(id, chain, userAddress); + return poolService.getGqlPool(id, chain, userAddress ? userAddress : undefined); }, poolGetPools: async (parent, args, context) => { return poolService.getGqlPools(args); diff --git a/modules/pool/pool.service.ts b/modules/pool/pool.service.ts index 1ded9c694..7a6d7da27 100644 --- a/modules/pool/pool.service.ts +++ b/modules/pool/pool.service.ts @@ -13,8 +13,6 @@ import { GqlPoolMinimal, GqlPoolSnapshotDataRange, GqlPoolUnion, - GqlPoolUserSwapVolume, - InputMaybe, QueryPoolGetBatchSwapsArgs, QueryPoolGetJoinExitsArgs, QueryPoolGetPoolsArgs, @@ -74,7 +72,7 @@ export class PoolService { return networkContext.services.balancerSubgraphService; } - public async getGqlPool(id: string, chain: GqlChain, userAddress?: InputMaybe): Promise { + public async getGqlPool(id: string, chain: GqlChain, userAddress?: string): Promise { return this.poolGqlLoaderService.getPool(id, chain, userAddress); } From 93125b9a36ee490f0d87b58ccdd816b428e205b4 Mon Sep 17 00:00:00 2001 From: gmbronco <83549293+gmbronco@users.noreply.github.com> Date: Mon, 18 Dec 2023 16:07:53 +0100 Subject: [PATCH 28/44] fix: use DB instead of slow subgraph --- modules/user/lib/user-sync-gauge-balance.service.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/user/lib/user-sync-gauge-balance.service.ts b/modules/user/lib/user-sync-gauge-balance.service.ts index 9c99c4f60..04b79bd9e 100644 --- a/modules/user/lib/user-sync-gauge-balance.service.ts +++ b/modules/user/lib/user-sync-gauge-balance.service.ts @@ -117,7 +117,13 @@ export class UserSyncGaugeBalanceService implements UserStakedBalanceService { const latestBlock = await this.provider.getBlockNumber(); console.log(`user-sync-staked-balances-${this.chainId} got latest block.`); - const gaugeAddresses = await gaugeSubgraphService.getAllGaugeAddresses(); + // Get gauge addresses + const gaugeAddresses = ( + await prisma.prismaPoolStakingGauge.findMany({ + select: { gaugeAddress: true }, + where: { chain: this.chain }, + }) + ).map((gauge) => gauge.gaugeAddress); // we sync at most 10k blocks at a time const startBlock = status.blockNumber + 1; From f029c27a473249af52650feb614eb2d40a320771 Mon Sep 17 00:00:00 2001 From: franz Date: Mon, 18 Dec 2023 16:42:20 +0100 Subject: [PATCH 29/44] change fantom fantom_rpc --- modules/network/fantom.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/network/fantom.ts b/modules/network/fantom.ts index 0a0d6fef5..9d800ae38 100644 --- a/modules/network/fantom.ts +++ b/modules/network/fantom.ts @@ -95,7 +95,7 @@ const fantomNetworkData: NetworkData = { maxHourlyPriceHistoryNumDays: 100, }, rpcUrl: - (env.DEPLOYMENT_ENV as DeploymentEnv) === 'main' ? `https://rpc.fantom.network` : `https://rpc.fantom.network`, + (env.DEPLOYMENT_ENV as DeploymentEnv) === 'main' ? `https://rpc.ankr.com/fantom` : `https://rpc.fantom.network`, rpcMaxBlockRange: 1000, sanity: { projectId: '1g2ag2hb', @@ -347,7 +347,10 @@ export const fantomNetworkConfig: NetworkConfig = { new UserSyncReliquaryFarmBalanceService(fantomNetworkData.reliquary!.address), ], services: { - balancerSubgraphService: new BalancerSubgraphService(fantomNetworkData.subgraphs.balancer, fantomNetworkData.chain.id), + balancerSubgraphService: new BalancerSubgraphService( + fantomNetworkData.subgraphs.balancer, + fantomNetworkData.chain.id, + ), }, /* For sub-minute jobs we set the alarmEvaluationPeriod and alarmDatapointsToAlarm to 1 instead of the default 3. From 99159390053b425dfe1443fef4f09f381865441e Mon Sep 17 00:00:00 2001 From: franz Date: Mon, 18 Dec 2023 17:15:09 +0100 Subject: [PATCH 30/44] change fantom rpc --- modules/network/fantom.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/network/fantom.ts b/modules/network/fantom.ts index 486301112..e0efc4c8b 100644 --- a/modules/network/fantom.ts +++ b/modules/network/fantom.ts @@ -96,8 +96,8 @@ const fantomNetworkData: NetworkData = { }, rpcUrl: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'main' - ? `https://rpc.fantom.gateway.fm` - : `https://rpc.fantom.network`, + ? `https://rpc.ankr.com/fantom` + : `https://rpc.fantom.gateway.fm`, rpcMaxBlockRange: 1000, sanity: { projectId: '1g2ag2hb', From 80c3ea12d1349f06233150250631e86e2567dc71 Mon Sep 17 00:00:00 2001 From: franz Date: Tue, 19 Dec 2023 16:20:37 +0100 Subject: [PATCH 31/44] add composable type to supported types --- modules/pool/lib/pool-on-chain-data.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/pool/lib/pool-on-chain-data.service.ts b/modules/pool/lib/pool-on-chain-data.service.ts index 2a0e70d9d..3957329eb 100644 --- a/modules/pool/lib/pool-on-chain-data.service.ts +++ b/modules/pool/lib/pool-on-chain-data.service.ts @@ -15,6 +15,7 @@ const SUPPORTED_POOL_TYPES: PrismaPoolType[] = [ 'STABLE', 'META_STABLE', 'PHANTOM_STABLE', + 'COMPOSABLE_STABLE', 'LINEAR', 'LIQUIDITY_BOOTSTRAPPING', 'ELEMENT', From a815e8c53dead366eb73ef84f310abfe878873ca Mon Sep 17 00:00:00 2001 From: franz Date: Wed, 20 Dec 2023 14:10:39 +0100 Subject: [PATCH 32/44] add composable type --- modules/sor/sorV2/sorV2.service.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/sor/sorV2/sorV2.service.ts b/modules/sor/sorV2/sorV2.service.ts index e747531b7..b972462b7 100644 --- a/modules/sor/sorV2/sorV2.service.ts +++ b/modules/sor/sorV2/sorV2.service.ts @@ -521,6 +521,8 @@ export class SorV2Service implements SwapService { case PrismaPoolType.PHANTOM_STABLE: // Composablestables are PHANTOM_STABLE in Prisma. b-sdk treats Phantoms as ComposableStable. return 'ComposableStable'; + case PrismaPoolType.COMPOSABLE_STABLE: + return 'ComposableStable'; case PrismaPoolType.GYRO: return 'Gyro2'; case PrismaPoolType.GYRO3: From c812f68659e4b89186307c6aefb3961cb3e076c2 Mon Sep 17 00:00:00 2001 From: franz Date: Wed, 20 Dec 2023 14:16:52 +0100 Subject: [PATCH 33/44] only use pools with more th $50 liquidity --- modules/sor/sorV2/sorV2.service.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/sor/sorV2/sorV2.service.ts b/modules/sor/sorV2/sorV2.service.ts index b972462b7..2c983445d 100644 --- a/modules/sor/sorV2/sorV2.service.ts +++ b/modules/sor/sorV2/sorV2.service.ts @@ -364,6 +364,9 @@ export class SorV2Service implements SwapService { gt: 0.000000000001, }, swapEnabled: true, + totalLiquidity: { + gt: 50, + }, }, id: { notIn: [...poolIdsToExclude, ...poolsToIgnore], From 5a777bb8a613310e9797a617f99fffb519efe064 Mon Sep 17 00:00:00 2001 From: franz Date: Wed, 20 Dec 2023 14:20:12 +0100 Subject: [PATCH 34/44] increase one hop --- modules/sor/sorV2/sorV2.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/sor/sorV2/sorV2.service.ts b/modules/sor/sorV2/sorV2.service.ts index 2c983445d..56caa5bb4 100644 --- a/modules/sor/sorV2/sorV2.service.ts +++ b/modules/sor/sorV2/sorV2.service.ts @@ -290,7 +290,7 @@ export class SorV2Service implements SwapService { public async getSwapResult( { chain, tokenIn, tokenOut, swapType, swapAmount, graphTraversalConfig }: GetSwapsInput, - maxNonBoostedPathDepth = 3, + maxNonBoostedPathDepth = 4, ): Promise { try { const poolsFromDb = await this.getBasePools(chain); From 27ca9aa88e799a781a03b727879985c501879d47 Mon Sep 17 00:00:00 2001 From: franz Date: Wed, 20 Dec 2023 14:51:22 +0100 Subject: [PATCH 35/44] remove unused cowswap fields --- modules/sor/constants.ts | 11 +++++------ modules/sor/sor.gql | 4 ---- modules/sor/sorV2/sorV2.service.ts | 4 ---- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/modules/sor/constants.ts b/modules/sor/constants.ts index 0fa69e5be..8c73cdc23 100644 --- a/modules/sor/constants.ts +++ b/modules/sor/constants.ts @@ -1,14 +1,14 @@ import { TokenAmount } from '@balancer/sdk'; import { GqlCowSwapApiResponse, GqlSorSwapType } from '../../schema'; -export const EMPTY_COWSWAP_RESPONSE = (assetIn: string, assetOut: string, amount: TokenAmount): GqlCowSwapApiResponse => { +export const EMPTY_COWSWAP_RESPONSE = ( + assetIn: string, + assetOut: string, + amount: TokenAmount, +): GqlCowSwapApiResponse => { return { - marketSp: '0', returnAmount: '0', - returnAmountConsideringFees: '0', - returnAmountFromSwaps: '0', swapAmount: amount.amount.toString(), - swapAmountForSwaps: '0', swaps: [], tokenAddresses: [], tokenIn: assetIn, @@ -352,4 +352,3 @@ export const poolsToIgnore = [ '0xbfd65c6160cfd638a85c645e6e6d8acac5dac935000000000000000000000004', '0xe274c9deb6ed34cfe4130f8d0a8a948dea5bb28600000000000000000000000d', ]; - diff --git a/modules/sor/sor.gql b/modules/sor/sor.gql index 716cf02d2..9bee51655 100644 --- a/modules/sor/sor.gql +++ b/modules/sor/sor.gql @@ -25,13 +25,9 @@ type GqlCowSwapApiResponse { tokenAddresses: [String!]! swaps: [GqlSwap!]! swapAmount: String! - swapAmountForSwaps: String! returnAmount: String! - returnAmountFromSwaps: String! - returnAmountConsideringFees: String! tokenIn: String! tokenOut: String! - marketSp: String! } type GqlSwap { diff --git a/modules/sor/sorV2/sorV2.service.ts b/modules/sor/sorV2/sorV2.service.ts index 56caa5bb4..3f0ff71f7 100644 --- a/modules/sor/sorV2/sorV2.service.ts +++ b/modules/sor/sorV2/sorV2.service.ts @@ -267,12 +267,8 @@ class SwapResultV2 implements SwapResult { const swapAmount = swap.swapKind === SwapKind.GivenIn ? inputAmount.amount.toString() : outputAmount.amount.toString(); return { - marketSp: '', // CowSwap is not using this field, confirmed. returnAmount, - returnAmountConsideringFees: returnAmount, // CowSwap is not using this field, confirmed. - returnAmountFromSwaps: returnAmount, // CowSwap is not using this field, confirmed. swapAmount, - swapAmountForSwaps: swapAmount, // CowSwap is not using this field, confirmed. swaps, tokenAddresses: swap.assets, tokenIn: swap.inputAmount.token.address, From 18c0ec9efcc0fc7df72194018d403276aa4b841b Mon Sep 17 00:00:00 2001 From: gmbronco <83549293+gmbronco@users.noreply.github.com> Date: Fri, 15 Dec 2023 17:47:07 +0100 Subject: [PATCH 36/44] sync-latest-fx-prices --- modules/network/avalanche.ts | 4 ++ modules/network/mainnet.ts | 4 ++ modules/network/optimism.ts | 5 +- modules/network/polygon.ts | 4 ++ modules/pool/pool.prisma | 1 + .../balancer-subgraph-queries.graphql | 4 ++ modules/token/latest-fx-price.ts | 49 +++++++++++++++++++ modules/token/token.gql | 1 + modules/token/token.resolvers.ts | 10 ++++ .../migration.sql | 2 + prisma/schema.prisma | 1 + worker/job-handlers.ts | 16 ++++++ 12 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 modules/token/latest-fx-price.ts create mode 100644 prisma/migrations/20231215151625_latest_fx_price/migration.sql diff --git a/modules/network/avalanche.ts b/modules/network/avalanche.ts index 038f2788d..8a543c455 100644 --- a/modules/network/avalanche.ts +++ b/modules/network/avalanche.ts @@ -346,5 +346,9 @@ export const avalancheNetworkConfig: NetworkConfig = { name: 'feed-data-to-datastudio', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(1, 'minutes'), }, + { + name: 'sync-latest-fx-prices', + interval: every(10, 'minutes'), + }, ], }; diff --git a/modules/network/mainnet.ts b/modules/network/mainnet.ts index fe2fd1676..8592b1739 100644 --- a/modules/network/mainnet.ts +++ b/modules/network/mainnet.ts @@ -509,5 +509,9 @@ export const mainnetNetworkConfig: NetworkConfig = { name: 'feed-data-to-datastudio', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(1, 'minutes'), }, + { + name: 'sync-latest-fx-prices', + interval: every(10, 'minutes'), + }, ], }; diff --git a/modules/network/optimism.ts b/modules/network/optimism.ts index c0f3beccb..f104162b8 100644 --- a/modules/network/optimism.ts +++ b/modules/network/optimism.ts @@ -298,7 +298,10 @@ export const optimismNetworkConfig: NetworkConfig = { ], userStakedBalanceServices: [new UserSyncGaugeBalanceService()], services: { - balancerSubgraphService: new BalancerSubgraphService(optimismNetworkData.subgraphs.balancer, optimismNetworkData.chain.id), + balancerSubgraphService: new BalancerSubgraphService( + optimismNetworkData.subgraphs.balancer, + optimismNetworkData.chain.id, + ), }, /* For sub-minute jobs we set the alarmEvaluationPeriod and alarmDatapointsToAlarm to 1 instead of the default 3. diff --git a/modules/network/polygon.ts b/modules/network/polygon.ts index 2420ce629..357f35df8 100644 --- a/modules/network/polygon.ts +++ b/modules/network/polygon.ts @@ -391,5 +391,9 @@ export const polygonNetworkConfig: NetworkConfig = { name: 'feed-data-to-datastudio', interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(1, 'minutes'), }, + { + name: 'sync-latest-fx-prices', + interval: every(10, 'minutes'), + }, ], }; diff --git a/modules/pool/pool.prisma b/modules/pool/pool.prisma index 6781f3727..a03ce9e54 100644 --- a/modules/pool/pool.prisma +++ b/modules/pool/pool.prisma @@ -229,6 +229,7 @@ model PrismaPoolTokenDynamicData { balanceUSD Float weight String? priceRate String + latestFxPrice Float? } model PrismaPoolSwap { diff --git a/modules/subgraphs/balancer-subgraph/balancer-subgraph-queries.graphql b/modules/subgraphs/balancer-subgraph/balancer-subgraph-queries.graphql index f154888d1..bdf1a2171 100644 --- a/modules/subgraphs/balancer-subgraph/balancer-subgraph-queries.graphql +++ b/modules/subgraphs/balancer-subgraph/balancer-subgraph-queries.graphql @@ -141,6 +141,7 @@ fragment BalancerToken on Token { id symbol address + latestFXPrice latestUSDPrice totalVolumeNotional totalVolumeUSD @@ -213,6 +214,9 @@ fragment BalancerPoolToken on PoolToken { weight priceRate index + token { + latestFXPrice + } } query BalancerPools( diff --git a/modules/token/latest-fx-price.ts b/modules/token/latest-fx-price.ts new file mode 100644 index 000000000..2eb090661 --- /dev/null +++ b/modules/token/latest-fx-price.ts @@ -0,0 +1,49 @@ +import { GraphQLClient } from 'graphql-request'; +import { getSdk } from '../subgraphs/balancer-subgraph/generated/balancer-subgraph-types'; +import { prisma } from '../../prisma/prisma-client'; +import { Chain } from '@prisma/client'; + +/** + * 'Latest FX Price' is relevant only to FX pools. It is sourced from offchain platforms, like Chainlink. + * The subgraph actively indexes this price by listening to the 'Answer Updated' events emitted by Chainlink oracles. + * For reference and more details, see the code at: + * https://github.com/balancer/balancer-subgraph-v2/blob/master/src/mappings/pricing.ts#L373 + * + * Note: 'LatestFXPrice' is a dependency of SORv2. + */ +export const syncLatestFXPrices = async (subgraphUrl: string, chain: Chain) => { + const { pools } = await fetchFxPools(subgraphUrl); + + for (const pool of pools) { + const { tokens } = pool; + if (!tokens) continue; + + for (const token of tokens) { + try { + await prisma.prismaPoolTokenDynamicData.update({ + where: { + id_chain: { + id: token.id, + chain, + }, + }, + data: { + latestFxPrice: token.token.latestFXPrice ? parseFloat(token.token.latestFXPrice) : undefined, + }, + }); + } catch (e) { + console.error(`Error updating latest FX price for token ${token.id} on chain ${chain}: ${e}`); + } + } + } + + return true; +}; + +const fetchFxPools = (subgraphUrl: string) => { + const sdk = getSdk(new GraphQLClient(subgraphUrl)); + + return sdk.BalancerPools({ + where: { poolType: 'FX' }, + }); +}; diff --git a/modules/token/token.gql b/modules/token/token.gql index 5481e271b..3adbb8db1 100644 --- a/modules/token/token.gql +++ b/modules/token/token.gql @@ -20,6 +20,7 @@ extend type Mutation { tokenReloadTokenPrices: Boolean tokenSyncTokenDefinitions: String! tokenSyncTokenDynamicData: String! + tokenSyncLatestFxPrices(chain: GqlChain!): String! tokenInitChartData(tokenAddress: String!): String! tokenDeletePrice(tokenAddress: String!, timestamp: Int!): Boolean! tokenDeleteTokenType(tokenAddress: String!, type: GqlTokenType!): String! diff --git a/modules/token/token.resolvers.ts b/modules/token/token.resolvers.ts index 8bc79db4c..7554d5c9c 100644 --- a/modules/token/token.resolvers.ts +++ b/modules/token/token.resolvers.ts @@ -3,6 +3,8 @@ import _ from 'lodash'; import { isAdminRoute } from '../auth/auth-context'; import { tokenService } from './token.service'; import { headerChain } from '../context/header-chain'; +import { syncLatestFXPrices } from './latest-fx-price'; +import { AllNetworkConfigsKeyedOnChain } from '../network/network-config'; const resolvers: Resolvers = { Query: { @@ -137,6 +139,14 @@ const resolvers: Resolvers = { return 'success'; }, + tokenSyncLatestFxPrices: async (parent, { chain }, context) => { + isAdminRoute(context); + const subgraphUrl = AllNetworkConfigsKeyedOnChain[chain].data.subgraphs.balancer; + + await syncLatestFXPrices(subgraphUrl, chain); + + return 'success'; + }, tokenInitChartData: async (parent, { tokenAddress }, context) => { isAdminRoute(context); diff --git a/prisma/migrations/20231215151625_latest_fx_price/migration.sql b/prisma/migrations/20231215151625_latest_fx_price/migration.sql new file mode 100644 index 000000000..3f97ae378 --- /dev/null +++ b/prisma/migrations/20231215151625_latest_fx_price/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "PrismaPoolTokenDynamicData" ADD COLUMN "latestFxPrice" DOUBLE PRECISION; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6e3103627..3dc68f074 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -275,6 +275,7 @@ model PrismaPoolTokenDynamicData { balanceUSD Float weight String? priceRate String + latestFxPrice Float? } model PrismaPoolSwap { diff --git a/worker/job-handlers.ts b/worker/job-handlers.ts index 9b6102541..d2b3d2143 100644 --- a/worker/job-handlers.ts +++ b/worker/job-handlers.ts @@ -14,6 +14,8 @@ import { veBalVotingListService } from '../modules/vebal/vebal-voting-list.servi import { cronsMetricPublisher } from '../modules/metrics/metrics.client'; import moment from 'moment'; import { cronsDurationMetricPublisher } from '../modules/metrics/cron-duration-metrics.client'; +import { syncLatestFXPrices } from '../modules/token/latest-fx-price'; +import { AllNetworkConfigs } from '../modules/network/network-config'; const runningJobs: Set = new Set(); @@ -278,6 +280,20 @@ export function configureWorkerRoutes(app: Express) { next, ); break; + case 'sync-latest-fx-prices': + await runIfNotAlreadyRunning( + job.name, + chainId, + () => { + const config = AllNetworkConfigs[chainId].data; + const subgraphUrl = config.subgraphs.balancer; + const chain = config.chain.prismaId; + return syncLatestFXPrices(subgraphUrl, chain); + }, + res, + next, + ); + break; default: res.sendStatus(400); throw new Error(`Unhandled job type ${job.name}`); From 8ccf9d5d1488c2db1ca74b4916cf844333b00237 Mon Sep 17 00:00:00 2001 From: gmbronco <83549293+gmbronco@users.noreply.github.com> Date: Fri, 15 Dec 2023 17:50:48 +0100 Subject: [PATCH 37/44] include FX pools in the SOR --- modules/sor/sorV2/sorV2.service.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/sor/sorV2/sorV2.service.ts b/modules/sor/sorV2/sorV2.service.ts index a3b96fc2e..733d8f659 100644 --- a/modules/sor/sorV2/sorV2.service.ts +++ b/modules/sor/sorV2/sorV2.service.ts @@ -365,7 +365,6 @@ export class SorV2Service implements SwapService { 'ELEMENT', // not supported by b-sdk 'UNKNOWN', // not supported by b-sdk 'INVESTMENT', // not supported by b-sdk - 'FX', // TODO: FX pool tokens are missing latestFXPrice - needs to be added to the DB ], }, AND: { From 1c38aabadc238fc8bfd08fdd283637b698041dfb Mon Sep 17 00:00:00 2001 From: franz Date: Wed, 20 Dec 2023 16:13:47 +0100 Subject: [PATCH 38/44] can go one level deeper than maxdepth, also retry on no candidate paths --- modules/sor/sorV2/sorV2.service.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/sor/sorV2/sorV2.service.ts b/modules/sor/sorV2/sorV2.service.ts index 0c8f72f6d..d78eeecf1 100644 --- a/modules/sor/sorV2/sorV2.service.ts +++ b/modules/sor/sorV2/sorV2.service.ts @@ -288,6 +288,7 @@ export class SorV2Service implements SwapService { { chain, tokenIn, tokenOut, swapType, swapAmount, graphTraversalConfig }: GetSwapsInput, maxNonBoostedPathDepth = 4, ): Promise { + const MAX_INCREASED_PATH_DEPTH = maxNonBoostedPathDepth + 1; try { const poolsFromDb = await this.getBasePools(chain); const tIn = await getToken(tokenIn as Address, chain); @@ -311,11 +312,17 @@ export class SorV2Service implements SwapService { maxNonBoostedPathDepth, ); const swap = await sorGetSwapsWithPools(tIn, tOut, swapKind, swapAmount, poolsFromDb, config); - if (!swap && maxNonBoostedPathDepth < 4) { + if (!swap && maxNonBoostedPathDepth < MAX_INCREASED_PATH_DEPTH) { return this.getSwapResult(arguments[0], maxNonBoostedPathDepth + 1); } return new SwapResultV2(swap, chain); } catch (err: any) { + if ( + err.message.includes('No potential swap paths provided') && + maxNonBoostedPathDepth < MAX_INCREASED_PATH_DEPTH + ) { + return this.getSwapResult(arguments[0], maxNonBoostedPathDepth + 1); + } console.error( `SOR_V2_ERROR ${err.message} - tokenIn: ${tokenIn} - tokenOut: ${tokenOut} - swapAmount: ${swapAmount.amount} - swapType: ${swapType} - chain: ${chain}`, ); From 349f69ac9004119c319568a4aeb7100f17523ee7 Mon Sep 17 00:00:00 2001 From: franz Date: Wed, 20 Dec 2023 16:26:31 +0100 Subject: [PATCH 39/44] remove 7d metrics --- modules/protocol/protocol.gql | 4 ---- modules/protocol/protocol.service.ts | 17 ----------------- 2 files changed, 21 deletions(-) diff --git a/modules/protocol/protocol.gql b/modules/protocol/protocol.gql index c9af32d44..f1a2f2d8c 100644 --- a/modules/protocol/protocol.gql +++ b/modules/protocol/protocol.gql @@ -16,8 +16,6 @@ type GqlProtocolMetricsAggregated { swapFee24h: BigDecimal! swapVolume24h: BigDecimal! yieldCapture24h: BigDecimal! - swapFee7d: BigDecimal! - swapVolume7d: BigDecimal! numLiquidityProviders: BigInt! chains: [GqlProtocolMetricsChain!]! } @@ -31,8 +29,6 @@ type GqlProtocolMetricsChain { swapFee24h: BigDecimal! swapVolume24h: BigDecimal! yieldCapture24h: BigDecimal! - swapFee7d: BigDecimal! - swapVolume7d: BigDecimal! numLiquidityProviders: BigInt! } diff --git a/modules/protocol/protocol.service.ts b/modules/protocol/protocol.service.ts index 45af70a3f..0dc5cf39a 100644 --- a/modules/protocol/protocol.service.ts +++ b/modules/protocol/protocol.service.ts @@ -40,8 +40,6 @@ export class ProtocolService { const swapVolume24h = _.sumBy(chainMetrics, (metrics) => parseFloat(metrics.swapVolume24h)); const swapFee24h = _.sumBy(chainMetrics, (metrics) => parseFloat(metrics.swapFee24h)); const yieldCapture24h = _.sumBy(chainMetrics, (metrics) => parseFloat(metrics.yieldCapture24h)); - const swapVolume7d = _.sumBy(chainMetrics, (metrics) => parseFloat(metrics.swapVolume7d)); - const swapFee7d = _.sumBy(chainMetrics, (metrics) => parseFloat(metrics.swapFee7d)); const numLiquidityProviders = _.sumBy(chainMetrics, (metrics) => parseInt(metrics.numLiquidityProviders)); return { @@ -52,8 +50,6 @@ export class ProtocolService { swapVolume24h: `${swapVolume24h}`, swapFee24h: `${swapFee24h}`, yieldCapture24h: `${yieldCapture24h}`, - swapVolume7d: `${swapVolume7d}`, - swapFee7d: `${swapFee7d}`, numLiquidityProviders: `${numLiquidityProviders}`, chains: chainMetrics, }; @@ -71,8 +67,6 @@ export class ProtocolService { public async cacheProtocolMetrics(chain: Chain): Promise { const oneDayAgo = moment().subtract(24, 'hours').unix(); - const startOfDay = moment().startOf('day').unix(); - const sevenDayRange = moment().startOf('day').subtract(7, 'days').unix(); const client = new GraphQLClient(AllNetworkConfigsKeyedOnChain[chain].data.subgraphs.balancer); const subgraphClient = getSdk(client); @@ -115,15 +109,6 @@ export class ProtocolService { const yieldCapture24h = _.sumBy(pools, (pool) => (!pool.dynamicData ? 0 : pool.dynamicData.yieldCapture24h)); - //we take the aggregate of the last 7 days previous to today, since today's values grow throughout the day - const snapshotQueryResponse = await prisma.prismaPoolSnapshot.aggregate({ - _sum: { fees24h: true, volume24h: true }, - where: { - chain, - timestamp: { gte: sevenDayRange, lt: startOfDay }, - }, - }); - const balancerV1Tvl = await this.getBalancerV1Tvl(`${AllNetworkConfigsKeyedOnChain[chain].data.chain.id}`); const protocolData = { @@ -135,8 +120,6 @@ export class ProtocolService { swapVolume24h: `${swapVolume24h}`, swapFee24h: `${swapFee24h}`, yieldCapture24h: `${yieldCapture24h}`, - swapVolume7d: `${snapshotQueryResponse._sum.volume24h}`, - swapFee7d: `${snapshotQueryResponse._sum.fees24h}`, numLiquidityProviders: `${holdersQueryResponse._sum.holdersCount || '0'}`, }; From aa95f92042f93d567f3abcb3f3de060b2df30abb Mon Sep 17 00:00:00 2001 From: franz Date: Wed, 20 Dec 2023 16:54:10 +0100 Subject: [PATCH 40/44] return phantom stable pool type for vebal voting list --- modules/vebal/vebal-voting-list.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/vebal/vebal-voting-list.service.ts b/modules/vebal/vebal-voting-list.service.ts index db30f16b9..02338e74d 100644 --- a/modules/vebal/vebal-voting-list.service.ts +++ b/modules/vebal/vebal-voting-list.service.ts @@ -42,7 +42,7 @@ export class VeBalVotingListService { chain: pool.chain, symbol: pool.symbol, address: pool.address, - type: pool.type, + type: pool.type === 'COMPOSABLE_STABLE' ? 'PHANTOM_STABLE' : pool.type, tokens: pool.tokens.map((token) => ({ address: token.address, weight: token.dynamicData?.weight, From 74cbc8feb54c2e736ac8e80025e01a424ccd9fa6 Mon Sep 17 00:00:00 2001 From: franz Date: Wed, 20 Dec 2023 21:11:17 +0100 Subject: [PATCH 41/44] check token addresses before sor run --- modules/sor/sor.service.ts | 14 ++++++++++++-- modules/sor/utils.ts | 31 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/modules/sor/sor.service.ts b/modules/sor/sor.service.ts index 573ab289c..f959b58d1 100644 --- a/modules/sor/sor.service.ts +++ b/modules/sor/sor.service.ts @@ -12,7 +12,7 @@ import { EMPTY_COWSWAP_RESPONSE } from './constants'; import { Chain } from '@prisma/client'; import { parseUnits, formatUnits } from '@ethersproject/units'; import { tokenService } from '../token/token.service'; -import { getTokenAmountHuman, getTokenAmountRaw } from './utils'; +import { getToken, getTokenAmountHuman, getTokenAmountRaw, zeroResponse } from './utils'; export class SorService { async getCowSwaps(args: QuerySorGetCowSwapsArgs): Promise { @@ -48,6 +48,17 @@ export class SorService { const tokenIn = args.tokenIn.toLowerCase(); const tokenOut = args.tokenOut.toLowerCase(); const amountToken = args.swapType === 'EXACT_IN' ? tokenIn : tokenOut; + const emptyResponse = zeroResponse(args.swapType, args.tokenIn, args.tokenOut, args.swapAmount); + + // check if tokens addresses exist + try { + await getToken(tokenIn, args.chain!); + await getToken(tokenOut, args.chain!); + } catch (e) { + console.log(e); + return emptyResponse; + } + // Use TokenAmount to help follow scaling requirements in later logic // args.swapAmount is HumanScale const amount = await getTokenAmountHuman(amountToken, args.swapAmount, args.chain!); @@ -60,7 +71,6 @@ export class SorService { tokenIn: tokenIn, tokenOut: tokenOut, }); - const emptyResponse = sorV1BeetsService.zeroResponse(args.swapType, args.tokenIn, args.tokenOut, amount); if (!swap) return emptyResponse; diff --git a/modules/sor/utils.ts b/modules/sor/utils.ts index 4e10b55c8..ddc3ea77a 100644 --- a/modules/sor/utils.ts +++ b/modules/sor/utils.ts @@ -2,6 +2,8 @@ import { TokenAmount, Token, Address, NATIVE_ADDRESS, NATIVE_ASSETS } from '@bal import { tokenService } from '../token/token.service'; import { Chain } from '@prisma/client'; import { chainToIdMap } from '../network/network-config'; +import { GqlSorGetSwapsResponse, GqlSorSwapType } from '../../schema'; +import { replaceZeroAddressWithEth } from '../web3/addresses'; export async function getTokenAmountHuman(tokenAddr: string, humanAmount: string, chain: Chain): Promise { const token = await getToken(tokenAddr, chain); @@ -34,3 +36,32 @@ export const getToken = async (tokenAddr: string, chain: Chain): Promise return new Token(chainId, prismaToken.address as Address, prismaToken.decimals); } }; + +export const zeroResponse = ( + swapType: GqlSorSwapType, + tokenIn: string, + tokenOut: string, + swapAmount: string, +): GqlSorGetSwapsResponse => { + return { + marketSp: '0', + tokenAddresses: [], + swaps: [], + tokenIn: replaceZeroAddressWithEth(tokenIn), + tokenOut: replaceZeroAddressWithEth(tokenOut), + swapType, + tokenInAmount: swapType === 'EXACT_IN' ? swapAmount : '0', + tokenOutAmount: swapType === 'EXACT_IN' ? '0' : swapAmount, + swapAmount: swapType === 'EXACT_IN' ? '0' : swapAmount, + swapAmountScaled: '0', + swapAmountForSwaps: '0', + returnAmount: '0', + returnAmountScaled: '0', + returnAmountConsideringFees: '0', + returnAmountFromSwaps: '0', + routes: [], + effectivePrice: '0', + effectivePriceReversed: '0', + priceImpact: '0', + }; +}; From f05ba56faf48c9d28b1e2fa189628a40331ed1b6 Mon Sep 17 00:00:00 2001 From: gmbronco <83549293+gmbronco@users.noreply.github.com> Date: Thu, 21 Dec 2023 08:12:01 +0100 Subject: [PATCH 42/44] Temporary FX pools block until we get missing data (#609) --- modules/sor/sorV2/sorV2.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/sor/sorV2/sorV2.service.ts b/modules/sor/sorV2/sorV2.service.ts index d78eeecf1..aed55dfd1 100644 --- a/modules/sor/sorV2/sorV2.service.ts +++ b/modules/sor/sorV2/sorV2.service.ts @@ -381,6 +381,7 @@ export class SorV2Service implements SwapService { 'ELEMENT', // not supported by b-sdk 'UNKNOWN', // not supported by b-sdk 'INVESTMENT', // not supported by b-sdk + 'FX', // needs more data ], }, AND: { From be2779988efbffcd33c1c4b828e32c9f9282f403 Mon Sep 17 00:00:00 2001 From: franz Date: Thu, 21 Dec 2023 08:17:27 +0100 Subject: [PATCH 43/44] increase interval for datastudio job --- modules/network/arbitrum.ts | 2 +- modules/network/avalanche.ts | 2 +- modules/network/base.ts | 2 +- modules/network/fantom.ts | 2 +- modules/network/gnosis.ts | 2 +- modules/network/mainnet.ts | 2 +- modules/network/optimism.ts | 2 +- modules/network/polygon.ts | 2 +- modules/network/zkevm.ts | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/network/arbitrum.ts b/modules/network/arbitrum.ts index 2d15c9593..9b889c240 100644 --- a/modules/network/arbitrum.ts +++ b/modules/network/arbitrum.ts @@ -342,7 +342,7 @@ export const arbitrumNetworkConfig: NetworkConfig = { }, { name: 'feed-data-to-datastudio', - interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(1, 'minutes'), + interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(5, 'minutes'), }, ], }; diff --git a/modules/network/avalanche.ts b/modules/network/avalanche.ts index 50471f778..d633625d5 100644 --- a/modules/network/avalanche.ts +++ b/modules/network/avalanche.ts @@ -336,7 +336,7 @@ export const avalancheNetworkConfig: NetworkConfig = { }, { name: 'feed-data-to-datastudio', - interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(1, 'minutes'), + interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(5, 'minutes'), }, { name: 'sync-latest-fx-prices', diff --git a/modules/network/base.ts b/modules/network/base.ts index 22425b3b7..bd45b9005 100644 --- a/modules/network/base.ts +++ b/modules/network/base.ts @@ -256,7 +256,7 @@ export const baseNetworkConfig: NetworkConfig = { }, { name: 'feed-data-to-datastudio', - interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(1, 'minutes'), + interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(5, 'minutes'), }, ], }; diff --git a/modules/network/fantom.ts b/modules/network/fantom.ts index 41519150e..175e3f2db 100644 --- a/modules/network/fantom.ts +++ b/modules/network/fantom.ts @@ -443,7 +443,7 @@ export const fantomNetworkConfig: NetworkConfig = { }, { name: 'feed-data-to-datastudio', - interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(1, 'minutes'), + interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(5, 'minutes'), }, ], }; diff --git a/modules/network/gnosis.ts b/modules/network/gnosis.ts index 3e1c5e2b3..728bf5a15 100644 --- a/modules/network/gnosis.ts +++ b/modules/network/gnosis.ts @@ -260,7 +260,7 @@ export const gnosisNetworkConfig: NetworkConfig = { }, { name: 'feed-data-to-datastudio', - interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(1, 'minutes'), + interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(5, 'minutes'), }, ], }; diff --git a/modules/network/mainnet.ts b/modules/network/mainnet.ts index 16eec5f0c..016a27a21 100644 --- a/modules/network/mainnet.ts +++ b/modules/network/mainnet.ts @@ -493,7 +493,7 @@ export const mainnetNetworkConfig: NetworkConfig = { }, { name: 'feed-data-to-datastudio', - interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(1, 'minutes'), + interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(5, 'minutes'), }, { name: 'sync-latest-fx-prices', diff --git a/modules/network/optimism.ts b/modules/network/optimism.ts index 2ac99b1c8..ffe2b7a5c 100644 --- a/modules/network/optimism.ts +++ b/modules/network/optimism.ts @@ -396,7 +396,7 @@ export const optimismNetworkConfig: NetworkConfig = { }, { name: 'feed-data-to-datastudio', - interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(1, 'minutes'), + interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(5, 'minutes'), }, ], }; diff --git a/modules/network/polygon.ts b/modules/network/polygon.ts index da4c0f696..398985199 100644 --- a/modules/network/polygon.ts +++ b/modules/network/polygon.ts @@ -377,7 +377,7 @@ export const polygonNetworkConfig: NetworkConfig = { }, { name: 'feed-data-to-datastudio', - interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(1, 'minutes'), + interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(5, 'minutes'), }, { name: 'sync-latest-fx-prices', diff --git a/modules/network/zkevm.ts b/modules/network/zkevm.ts index 951f5646a..09a329daf 100644 --- a/modules/network/zkevm.ts +++ b/modules/network/zkevm.ts @@ -284,7 +284,7 @@ export const zkevmNetworkConfig: NetworkConfig = { }, { name: 'feed-data-to-datastudio', - interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(1, 'minutes'), + interval: (env.DEPLOYMENT_ENV as DeploymentEnv) === 'canary' ? every(5, 'minutes') : every(5, 'minutes'), }, ], }; From c1ab514e3f897a197111546a3a919a75d5b0fee2 Mon Sep 17 00:00:00 2001 From: franz Date: Thu, 21 Dec 2023 08:53:51 +0100 Subject: [PATCH 44/44] fix max depth --- modules/sor/sorV2/sorV2.service.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/modules/sor/sorV2/sorV2.service.ts b/modules/sor/sorV2/sorV2.service.ts index aed55dfd1..279c65459 100644 --- a/modules/sor/sorV2/sorV2.service.ts +++ b/modules/sor/sorV2/sorV2.service.ts @@ -288,7 +288,6 @@ export class SorV2Service implements SwapService { { chain, tokenIn, tokenOut, swapType, swapAmount, graphTraversalConfig }: GetSwapsInput, maxNonBoostedPathDepth = 4, ): Promise { - const MAX_INCREASED_PATH_DEPTH = maxNonBoostedPathDepth + 1; try { const poolsFromDb = await this.getBasePools(chain); const tIn = await getToken(tokenIn as Address, chain); @@ -312,15 +311,12 @@ export class SorV2Service implements SwapService { maxNonBoostedPathDepth, ); const swap = await sorGetSwapsWithPools(tIn, tOut, swapKind, swapAmount, poolsFromDb, config); - if (!swap && maxNonBoostedPathDepth < MAX_INCREASED_PATH_DEPTH) { + if (!swap && maxNonBoostedPathDepth < 5) { return this.getSwapResult(arguments[0], maxNonBoostedPathDepth + 1); } return new SwapResultV2(swap, chain); } catch (err: any) { - if ( - err.message.includes('No potential swap paths provided') && - maxNonBoostedPathDepth < MAX_INCREASED_PATH_DEPTH - ) { + if (err.message.includes('No potential swap paths provided') && maxNonBoostedPathDepth < 5) { return this.getSwapResult(arguments[0], maxNonBoostedPathDepth + 1); } console.error(