From e0d9d405459c72706d8a7c1d6cf902be70295ae6 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 18 Jul 2023 16:29:55 +0200 Subject: [PATCH 01/25] algebra/zkevm: prevent pool exclusion and prefer lighter rpc fallback --- src/dex/algebra/algebra.ts | 6 +----- src/dex/algebra/config.ts | 2 +- src/dex/uniswap-v3/config.ts | 2 +- src/dex/uniswap-v3/uniswap-v3.ts | 6 +----- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 67f4441bd..2cf8d0f1a 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -183,11 +183,7 @@ export class Algebra extends SimpleExchange implements IDex { }, }); } catch (e) { - if ( - // most zkEVM rpcs fails with "cannot execute unsigned transaction" issue. Prefer to flag pool as non existing instaed of trying to generateState on earch round - this.network === Network.ZKEVM || - (e instanceof Error && e.message.endsWith('Pool does not exist')) - ) { + if (e instanceof Error && e.message.endsWith('Pool does not exist')) { // no need to await we want the set to have the pool key but it's not blocking this.dexHelper.cache.zadd( this.notExistingPoolSetKey, diff --git a/src/dex/algebra/config.ts b/src/dex/algebra/config.ts index 24c55704b..add0b935e 100644 --- a/src/dex/algebra/config.ts +++ b/src/dex/algebra/config.ts @@ -23,7 +23,7 @@ export const AlgebraConfig: DexConfigMap = { quoter: '0x55BeE1bD3Eb9986f6d2d963278de09eE92a3eF1D', initHash: '0x6ec6c9c8091d160c0aa74b2b14ba9c1717e95093bd3ac085cee99a49aab294a4', - chunksCount: 10, + chunksCount: 5, algebraStateMulticall: '0xa6bc273A238867dD74F2bBbD5fBbA3c941C939B9', subgraphURL: 'https://api.studio.thegraph.com/query/44554/quickswap-v3-02/0.0.7', diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index a93fd5877..d03723524 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -106,7 +106,7 @@ export const UniswapV3Config: DexConfigMap = { supportedFees: SUPPORTED_FEES, stateMulticall: '0x983ab0171159b7e17835cc6aec70c72b8aadb133', uniswapMulticall: '0x61530d6E1c7A47BBB3e48e8b8EdF7569DcFeE121', - chunksCount: 10, + chunksCount: 5, initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, subgraphURL: 'https://api.studio.thegraph.com/query/44554/uniswap-v3/version/latest', diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index f43c4679d..6358b1d94 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -237,11 +237,7 @@ export class UniswapV3 }, }); } catch (e) { - // most zkEVM rpcs fails with "cannot execute unsigned transaction" issue. Prefer to flag pool as non existing instaed of trying to generateState on earch round - if ( - this.network === Network.ZKEVM || - (e instanceof Error && e.message.endsWith('Pool does not exist')) - ) { + if (e instanceof Error && e.message.endsWith('Pool does not exist')) { // no need to await we want the set to have the pool key but it's not blocking this.dexHelper.cache.zadd( this.notExistingPoolSetKey, From a23027f8a1bb1005a85570308e90b72058e77f36 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 18 Jul 2023 16:31:12 +0200 Subject: [PATCH 02/25] 2.25.2-algebra-z-rpc.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e82c995d9..942468250 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.25.1", + "version": "2.25.2-algebra-z-rpc.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1ab4825b483b76f93aec53edce7b3204f4c638e2 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 18 Jul 2023 18:18:36 +0200 Subject: [PATCH 03/25] alegebra implement retry init mecanism --- src/dex/algebra/algebra-pool.ts | 3 +++ src/dex/algebra/algebra.ts | 20 +++++++++++++++++--- src/dex/algebra/config.ts | 4 +++- src/dex/algebra/types.ts | 1 + 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/dex/algebra/algebra-pool.ts b/src/dex/algebra/algebra-pool.ts index 9b02a50f2..f42509b1e 100644 --- a/src/dex/algebra/algebra-pool.ts +++ b/src/dex/algebra/algebra-pool.ts @@ -49,6 +49,9 @@ export class AlgebraEventPool extends StatefulEventSubscriber { public readonly poolIface = new Interface(AlgebraABI); + public initFailed = false; + public initRetryCount = 0; + constructor( readonly dexHelper: IDexHelper, parentName: string, diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 2cf8d0f1a..9d98ca35d 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -133,6 +133,15 @@ export class Algebra extends SimpleExchange implements IDex { ): Promise { let pool = this.eventPools[this.getPoolIdentifier(srcAddress, destAddress)]; + if ( + pool && + pool.initFailed && + pool.initRetryCount % this.config.initRetryFrequency === 0 + ) { + // if init failed then prefer to early return pool with empty state to fallback to rpc call + return pool; + } + if (pool === undefined) { const [token0, token1] = this._sortTokens(srcAddress, destAddress); @@ -180,6 +189,8 @@ export class Algebra extends SimpleExchange implements IDex { //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber pool!.addressesSubscribed[0] = state.pool; pool!.poolAddress = state.pool; + pool!.initFailed = false; + pool!.initRetryCount = 0; }, }); } catch (e) { @@ -200,11 +211,13 @@ export class Algebra extends SimpleExchange implements IDex { ); } else { // Unexpected Error. Break execution. Do not save the pool in this.eventPools - this.logger.error( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}pool`, + // note: state would be null by default which allows to fallback + this.logger.warn( + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}pool fallback to rpc and retry every ${this.config.initRetryFrequency} times`, e, ); - throw new Error('Cannot generate pool state'); + pool.initFailed = true; + pool.initRetryCount++; } } @@ -687,6 +700,7 @@ export class Algebra extends SimpleExchange implements IDex { factory: this.config.factory.toLowerCase(), algebraStateMulticall: this.config.algebraStateMulticall.toLowerCase(), chunksCount: this.config.chunksCount, + initRetryFrequency: this.config.initRetryFrequency, uniswapMulticall: this.config.uniswapMulticall, deployer: this.config.deployer?.toLowerCase(), initHash: this.config.initHash, diff --git a/src/dex/algebra/config.ts b/src/dex/algebra/config.ts index add0b935e..20bf174f2 100644 --- a/src/dex/algebra/config.ts +++ b/src/dex/algebra/config.ts @@ -11,6 +11,7 @@ export const AlgebraConfig: DexConfigMap = { initHash: '0x6ec6c9c8091d160c0aa74b2b14ba9c1717e95093bd3ac085cee99a49aab294a4', chunksCount: 10, + initRetryFrequency: 10, algebraStateMulticall: '0xfb948e6e23eb58ec7320ddb60df9115de07141ec', subgraphURL: 'https://api.thegraph.com/subgraphs/name/sameepsi/quickswap-v3', @@ -23,7 +24,8 @@ export const AlgebraConfig: DexConfigMap = { quoter: '0x55BeE1bD3Eb9986f6d2d963278de09eE92a3eF1D', initHash: '0x6ec6c9c8091d160c0aa74b2b14ba9c1717e95093bd3ac085cee99a49aab294a4', - chunksCount: 5, + chunksCount: 3, + initRetryFrequency: 10, algebraStateMulticall: '0xa6bc273A238867dD74F2bBbD5fBbA3c941C939B9', subgraphURL: 'https://api.studio.thegraph.com/query/44554/quickswap-v3-02/0.0.7', diff --git a/src/dex/algebra/types.ts b/src/dex/algebra/types.ts index da6643faa..abc9c699f 100644 --- a/src/dex/algebra/types.ts +++ b/src/dex/algebra/types.ts @@ -40,6 +40,7 @@ export type DexParams = { algebraStateMulticall: Address; uniswapMulticall: Address; chunksCount: number; + initRetryFrequency: number; deployer: Address; subgraphURL: string; initHash: string; From c70aaf2c7b0f2a0697836f5bcedffedb4f7bba86 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 18 Jul 2023 18:20:16 +0200 Subject: [PATCH 04/25] replicate initRetry for univ3 and panv3 --- src/dex/pancakeswap-v3/config.ts | 2 ++ src/dex/pancakeswap-v3/pancakeswap-v3-pool.ts | 3 +++ src/dex/pancakeswap-v3/pancakeswap-v3.ts | 10 ++++++++++ src/dex/uniswap-v3/config.ts | 7 +++++++ src/dex/uniswap-v3/types.ts | 1 + src/dex/uniswap-v3/uniswap-v3-pool.ts | 3 +++ src/dex/uniswap-v3/uniswap-v3.ts | 10 ++++++++++ 7 files changed, 36 insertions(+) diff --git a/src/dex/pancakeswap-v3/config.ts b/src/dex/pancakeswap-v3/config.ts index 805ef917e..098cc6329 100644 --- a/src/dex/pancakeswap-v3/config.ts +++ b/src/dex/pancakeswap-v3/config.ts @@ -17,6 +17,7 @@ export const PancakeswapV3Config: DexConfigMap = { stateMulticall: '0x80898f80cFA3Fa3AbF410d90e69aDc432AE5D4c2', uniswapMulticall: '0xac1cE734566f390A94b00eb9bf561c2625BF44ea', chunksCount: 10, + initRetryFrequency: 10, initHash: '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', subgraphURL: @@ -31,6 +32,7 @@ export const PancakeswapV3Config: DexConfigMap = { stateMulticall: '0x9DAd2ED7ADc6eaacf81589Cd043579c9684E5C81', uniswapMulticall: '0xac1cE734566f390A94b00eb9bf561c2625BF44ea', chunksCount: 10, + initRetryFrequency: 10, initHash: '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', subgraphURL: diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3-pool.ts b/src/dex/pancakeswap-v3/pancakeswap-v3-pool.ts index a49e207d9..8662805e8 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3-pool.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3-pool.ts @@ -54,6 +54,9 @@ export class PancakeSwapV3EventPool extends StatefulEventSubscriber { public readonly poolIface = new Interface(PancakeswapV3PoolABI); + public initFailed = false; + public initRetryCount = 0; + public readonly feeCodeAsString; constructor( diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index c7b3a8c42..d46069e78 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -160,6 +160,15 @@ export class PancakeswapV3 let pool = this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)]; + if ( + pool && + pool.initFailed && + pool.initRetryCount % this.config.initRetryFrequency === 0 + ) { + // if init failed then prefer to early return pool with empty state to fallback to rpc call + return pool; + } + if (pool === undefined) { const [token0, token1] = this._sortTokens(srcAddress, destAddress); @@ -873,6 +882,7 @@ export class PancakeswapV3 supportedFees: this.config.supportedFees, stateMulticall: this.config.stateMulticall.toLowerCase(), chunksCount: this.config.chunksCount, + initRetryFrequency: this.config.initRetryFrequency, uniswapMulticall: this.config.uniswapMulticall, deployer: this.config.deployer?.toLowerCase(), initHash: this.config.initHash, diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index d03723524..2321f7b74 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -34,6 +34,7 @@ export const UniswapV3Config: DexConfigMap = { stateMulticall: '0x9c764D2e92dA68E4CDfD784B902283A095ff8b63', uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', chunksCount: 10, + initRetryFrequency: 10, initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, subgraphURL: 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3', }, @@ -45,6 +46,7 @@ export const UniswapV3Config: DexConfigMap = { stateMulticall: '0x593F39A4Ba26A9c8ed2128ac95D109E8e403C485', uniswapMulticall: '0x963Df249eD09c358A4819E39d9Cd5736c3087184', chunksCount: 10, + initRetryFrequency: 10, initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, subgraphURL: 'https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-v3-bsc', @@ -57,6 +59,7 @@ export const UniswapV3Config: DexConfigMap = { stateMulticall: '0x6Dc993Fe1e945A640576B4Dca81281d8e998DF71', uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', chunksCount: 10, + initRetryFrequency: 10, initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, subgraphURL: 'https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-v3-polygon', @@ -69,6 +72,7 @@ export const UniswapV3Config: DexConfigMap = { stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', chunksCount: 10, + initRetryFrequency: 10, initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, subgraphURL: 'https://api.thegraph.com/subgraphs/name/ianlapham/arbitrum-minimal', @@ -81,6 +85,7 @@ export const UniswapV3Config: DexConfigMap = { stateMulticall: '0x4FF0dEC5f9a763Aa1E5C2a962aa6f4eDFeE4f9eA', uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', chunksCount: 10, + initRetryFrequency: 10, initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, subgraphURL: 'https://api.thegraph.com/subgraphs/name/ianlapham/optimism-post-regenesis', @@ -93,6 +98,7 @@ export const UniswapV3Config: DexConfigMap = { stateMulticall: '0x30F6B9b6485ff0B67E881f5ac80D3F1c70A4B23d', uniswapMulticall: '0x0139141Cd4Ee88dF3Cdb65881D411bAE271Ef0C2', chunksCount: 10, + initRetryFrequency: 10, initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, subgraphURL: 'https://api.thegraph.com/subgraphs/name/lynnshaoyu/uniswap-v3-avax', @@ -107,6 +113,7 @@ export const UniswapV3Config: DexConfigMap = { stateMulticall: '0x983ab0171159b7e17835cc6aec70c72b8aadb133', uniswapMulticall: '0x61530d6E1c7A47BBB3e48e8b8EdF7569DcFeE121', chunksCount: 5, + initRetryFrequency: 10, initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, subgraphURL: 'https://api.studio.thegraph.com/query/44554/uniswap-v3/version/latest', diff --git a/src/dex/uniswap-v3/types.ts b/src/dex/uniswap-v3/types.ts index de2053eec..c3fd7890c 100644 --- a/src/dex/uniswap-v3/types.ts +++ b/src/dex/uniswap-v3/types.ts @@ -68,6 +68,7 @@ export type DexParams = { uniswapMulticall: Address; supportedFees: bigint[]; chunksCount: number; + initRetryFrequency: number; deployer?: Address; subgraphURL: string; initHash: string; diff --git a/src/dex/uniswap-v3/uniswap-v3-pool.ts b/src/dex/uniswap-v3/uniswap-v3-pool.ts index 8b0a1a7f4..baa2dcce2 100644 --- a/src/dex/uniswap-v3/uniswap-v3-pool.ts +++ b/src/dex/uniswap-v3/uniswap-v3-pool.ts @@ -51,6 +51,9 @@ export class UniswapV3EventPool extends StatefulEventSubscriber { public readonly poolIface = new Interface(UniswapV3PoolABI); + public initFailed = false; + public initRetryCount = 0; + public readonly feeCodeAsString; constructor( diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 6358b1d94..ff59f0fd5 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -185,6 +185,15 @@ export class UniswapV3 let pool = this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)]; + if ( + pool && + pool.initFailed && + pool.initRetryCount % this.config.initRetryFrequency === 0 + ) { + // if init failed then prefer to early return pool with empty state to fallback to rpc call + return pool; + } + if (pool === undefined) { const [token0, token1] = this._sortTokens(srcAddress, destAddress); @@ -1022,6 +1031,7 @@ export class UniswapV3 supportedFees: this.config.supportedFees, stateMulticall: this.config.stateMulticall.toLowerCase(), chunksCount: this.config.chunksCount, + initRetryFrequency: this.config.initRetryFrequency, uniswapMulticall: this.config.uniswapMulticall, deployer: this.config.deployer?.toLowerCase(), initHash: this.config.initHash, From e8151ef1966ea304e703a5f152647b6f6ea205f8 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 18 Jul 2023 18:21:18 +0200 Subject: [PATCH 05/25] 2.25.2-algebra-z-rpc.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 942468250..4747022de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.25.2-algebra-z-rpc.0", + "version": "2.25.2-algebra-z-rpc.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 310d646440a85a7b9e368d953915fc618179cecc Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 18 Jul 2023 19:05:34 +0200 Subject: [PATCH 06/25] stop fallbacking on z due to resp time --- src/dex/algebra/algebra.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 9d98ca35d..59d288132 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -409,6 +409,8 @@ export class Algebra extends SimpleExchange implements IDex { const state = pool.getState(blockNumber); + if (state === null && this.network === Network.ZKEVM) return null; // never fallback as takes more time + if (state === null) { const rpcPrice = await this.getPricingFromRpc( _srcToken, From 6f24320df4a05014fa88297ad55cc218c17e8e4e Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 18 Jul 2023 19:08:07 +0200 Subject: [PATCH 07/25] 2.25.2-algebra-z-rpc.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4747022de..f5adb5651 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.25.2-algebra-z-rpc.1", + "version": "2.25.2-algebra-z-rpc.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From eeb22b052d8fbfc4026a7a0aedb7c2cf1382426b Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 18 Jul 2023 19:15:05 +0200 Subject: [PATCH 08/25] prevent making rpc calls for univ3 and panv3 --- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 2 +- src/dex/uniswap-v3/uniswap-v3.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index d46069e78..f56302a5f 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -559,7 +559,7 @@ export class PancakeswapV3 _destToken, amounts, side, - poolsToUse.poolWithoutState, + this.network === Network.ZKEVM ? [] : poolsToUse.poolWithoutState, ); const states = poolsToUse.poolWithState.map( diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index ff59f0fd5..467ec60ba 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -584,7 +584,7 @@ export class UniswapV3 _destToken, amounts, side, - poolsToUse.poolWithoutState, + this.network === Network.ZKEVM ? [] : poolsToUse.poolWithoutState, ); const states = poolsToUse.poolWithState.map( From 116c01b9625a15e1dbf4f44c7c52e2151190d01b Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 18 Jul 2023 19:16:16 +0200 Subject: [PATCH 09/25] 2.25.2-algebra-z-rpc.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f5adb5651..a72c76772 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.25.2-algebra-z-rpc.2", + "version": "2.25.2-algebra-z-rpc.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 215780ee0013fb6041f9d46d9930c9288175905f Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 18 Jul 2023 19:30:36 +0200 Subject: [PATCH 10/25] fix univ3 and panv3 and enrich logs with retry count --- package.json | 2 +- src/dex/algebra/algebra.ts | 4 ++-- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 10 ++++++---- src/dex/uniswap-v3/uniswap-v3.ts | 10 ++++++---- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index a72c76772..80ac9e29c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.25.2-algebra-z-rpc.3", + "version": "2.25.2-algebra-z-rpc.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 59d288132..a2bef551d 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -210,10 +210,10 @@ export class Algebra extends SimpleExchange implements IDex { e, ); } else { - // Unexpected Error. Break execution. Do not save the pool in this.eventPools + // on unkown error mark as failed and increase retryCount for retry init strategy // note: state would be null by default which allows to fallback this.logger.warn( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}pool fallback to rpc and retry every ${this.config.initRetryFrequency} times`, + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryCount=${pool.initRetryCount}`, e, ); pool.initFailed = true; diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index f56302a5f..9755eb110 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -238,12 +238,14 @@ export class PancakeswapV3 e, ); } else { - // Unexpected Error. Break execution. Do not save the pool in this.eventPools - this.logger.error( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool`, + // on unkown error mark as failed and increase retryCount for retry init strategy + // note: state would be null by default which allows to fallback + this.logger.warn( + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryCount=${pool.initRetryCount}`, e, ); - throw new Error('Cannot generate pool state'); + pool.initFailed = true; + pool.initRetryCount++; } } diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 467ec60ba..00ceef9c6 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -262,12 +262,14 @@ export class UniswapV3 e, ); } else { - // Unexpected Error. Break execution. Do not save the pool in this.eventPools - this.logger.error( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool`, + // on unkown error mark as failed and increase retryCount for retry init strategy + // note: state would be null by default which allows to fallback + this.logger.warn( + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryCount=${pool.initRetryCount}`, e, ); - throw new Error('Cannot generate pool state'); + pool.initFailed = true; + pool.initRetryCount++; } } From a63f8cf9bb173315aeb4baaf1eb24ddf0283d54d Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 18 Jul 2023 19:57:21 +0200 Subject: [PATCH 11/25] fix missing reset --- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 2 ++ src/dex/uniswap-v3/uniswap-v3.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index 9755eb110..93d45462e 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -219,6 +219,8 @@ export class PancakeswapV3 //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber pool!.addressesSubscribed[0] = state.pool; pool!.poolAddress = state.pool; + pool!.initFailed = false; + pool!.initRetryCount = 0; }, }); } catch (e) { diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 00ceef9c6..c33542566 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -243,6 +243,8 @@ export class UniswapV3 //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber pool!.addressesSubscribed[0] = state.pool; pool!.poolAddress = state.pool; + pool!.initFailed = false; + pool!.initRetryCount = 0; }, }); } catch (e) { From 737affe18c27e427f151a6a6ecd65f79bb88cd68 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 18 Jul 2023 20:00:42 +0200 Subject: [PATCH 12/25] fix implem to actually try to regen state --- src/dex/algebra/algebra.ts | 140 +++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 69 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index a2bef551d..bd352dcc3 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -142,34 +142,37 @@ export class Algebra extends SimpleExchange implements IDex { return pool; } - if (pool === undefined) { - const [token0, token1] = this._sortTokens(srcAddress, destAddress); + if (pool === null) return null; - const key = `${token0}_${token1}`.toLowerCase(); + const [token0, token1] = this._sortTokens(srcAddress, destAddress); - const notExistingPoolScore = await this.dexHelper.cache.zscore( - this.notExistingPoolSetKey, - key, - ); + const key = `${token0}_${token1}`.toLowerCase(); - const poolDoesNotExist = notExistingPoolScore !== null; + const notExistingPoolScore = await this.dexHelper.cache.zscore( + this.notExistingPoolSetKey, + key, + ); - if (poolDoesNotExist) { - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress)] = null; - return null; - } + const poolDoesNotExist = notExistingPoolScore !== null; - await this.dexHelper.cache.hset( - this.dexmapKey, - key, - JSON.stringify({ - token0, - token1, - }), - ); + if (poolDoesNotExist) { + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress)] = null; + return null; + } + + await this.dexHelper.cache.hset( + this.dexmapKey, + key, + JSON.stringify({ + token0, + token1, + }), + ); - this.logger.trace(`starting to listen to new pool: ${key}`); - pool = new AlgebraEventPool( + this.logger.trace(`starting to listen to new pool: ${key}`); + pool = + pool || + new AlgebraEventPool( this.dexHelper, this.dexKey, this.stateMultiContract, @@ -183,58 +186,57 @@ export class Algebra extends SimpleExchange implements IDex { this.config.deployer, ); - try { - await pool.initialize(blockNumber, { - initCallback: (state: DeepReadonly) => { - //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber - pool!.addressesSubscribed[0] = state.pool; - pool!.poolAddress = state.pool; - pool!.initFailed = false; - pool!.initRetryCount = 0; - }, - }); - } catch (e) { - if (e instanceof Error && e.message.endsWith('Pool does not exist')) { - // no need to await we want the set to have the pool key but it's not blocking - this.dexHelper.cache.zadd( - this.notExistingPoolSetKey, - [Date.now(), key], - 'NX', - ); - - // Pool does not exist for this pair, so we can set it to null - // to prevent more requests for this pool - pool = null; - this.logger.trace( - `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress} not found`, - e, - ); - } else { - // on unkown error mark as failed and increase retryCount for retry init strategy - // note: state would be null by default which allows to fallback - this.logger.warn( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryCount=${pool.initRetryCount}`, - e, - ); - pool.initFailed = true; - pool.initRetryCount++; - } - } + try { + await pool.initialize(blockNumber, { + initCallback: (state: DeepReadonly) => { + //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber + pool!.addressesSubscribed[0] = state.pool; + pool!.poolAddress = state.pool; + pool!.initFailed = false; + pool!.initRetryCount = 0; + }, + }); + } catch (e) { + if (e instanceof Error && e.message.endsWith('Pool does not exist')) { + // no need to await we want the set to have the pool key but it's not blocking + this.dexHelper.cache.zadd( + this.notExistingPoolSetKey, + [Date.now(), key], + 'NX', + ); - if (pool !== null) { - const allEventPools = Object.values(this.eventPools); - this.logger.info( - `starting to listen to new non-null pool: ${key}. Already following ${allEventPools - // Not that I like this reduce, but since it is done only on initialization, expect this to be ok - .reduce( - (acc, curr) => (curr !== null ? ++acc : acc), - 0, - )} non-null pools or ${allEventPools.length} total pools`, + // Pool does not exist for this pair, so we can set it to null + // to prevent more requests for this pool + pool = null; + this.logger.trace( + `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress} not found`, + e, + ); + } else { + // on unkown error mark as failed and increase retryCount for retry init strategy + // note: state would be null by default which allows to fallback + this.logger.warn( + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryCount=${pool.initRetryCount}`, + e, ); + pool.initFailed = true; + pool.initRetryCount++; } + } - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress)] = pool; + if (pool !== null) { + const allEventPools = Object.values(this.eventPools); + this.logger.info( + `starting to listen to new non-null pool: ${key}. Already following ${allEventPools + // Not that I like this reduce, but since it is done only on initialization, expect this to be ok + .reduce( + (acc, curr) => (curr !== null ? ++acc : acc), + 0, + )} non-null pools or ${allEventPools.length} total pools`, + ); } + + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress)] = pool; return pool; } From 139542972bb3a3a5445ab65d8356fa1ee350a1c0 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 18 Jul 2023 20:02:43 +0200 Subject: [PATCH 13/25] bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 80ac9e29c..c7357b47c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.25.2-algebra-z-rpc.4", + "version": "2.25.2-algebra-z-rpc.5", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1b0bcfb79f08523f1dec9c5a3f8608e63c977634 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 19 Jul 2023 11:42:42 +0200 Subject: [PATCH 14/25] fix retry init --- src/dex/algebra/algebra.ts | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index bd352dcc3..680412339 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -133,17 +133,20 @@ export class Algebra extends SimpleExchange implements IDex { ): Promise { let pool = this.eventPools[this.getPoolIdentifier(srcAddress, destAddress)]; - if ( - pool && - pool.initFailed && - pool.initRetryCount % this.config.initRetryFrequency === 0 - ) { - // if init failed then prefer to early return pool with empty state to fallback to rpc call - return pool; - } - if (pool === null) return null; + if (pool) { + if (!pool.initFailed) { + return pool; + } else { + // if init failed then prefer to early return pool with empty state to fallback to rpc call + if (++pool.initRetryCount % this.config.initRetryFrequency === 0) { + return pool; + } + // else pursue with re-try initialization + } + } + const [token0, token1] = this._sortTokens(srcAddress, destAddress); const key = `${token0}_${token1}`.toLowerCase(); @@ -220,7 +223,6 @@ export class Algebra extends SimpleExchange implements IDex { e, ); pool.initFailed = true; - pool.initRetryCount++; } } From fcc38d2ed252fdd1ec24ffd289301eadda8f6d6d Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 19 Jul 2023 11:45:11 +0200 Subject: [PATCH 15/25] 2.25.2-algebra-z-rpc.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c7357b47c..9490176df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.25.2-algebra-z-rpc.5", + "version": "2.25.2-algebra-z-rpc.6", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 2a82d34c60370b07fc32e374b144c9db1f7deea5 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 19 Jul 2023 12:04:23 +0200 Subject: [PATCH 16/25] better types --- src/dex/algebra/algebra.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 680412339..3ea965b19 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -131,7 +131,9 @@ export class Algebra extends SimpleExchange implements IDex { destAddress: Address, blockNumber: number, ): Promise { - let pool = this.eventPools[this.getPoolIdentifier(srcAddress, destAddress)]; + let pool = this.eventPools[ + this.getPoolIdentifier(srcAddress, destAddress) + ] as AlgebraEventPool | null | undefined; if (pool === null) return null; @@ -163,14 +165,16 @@ export class Algebra extends SimpleExchange implements IDex { return null; } - await this.dexHelper.cache.hset( - this.dexmapKey, - key, - JSON.stringify({ - token0, - token1, - }), - ); + if (!pool) { + await this.dexHelper.cache.hset( + this.dexmapKey, + key, + JSON.stringify({ + token0, + token1, + }), + ); + } this.logger.trace(`starting to listen to new pool: ${key}`); pool = From cd45d442ccc9091339a32a428a9a23f79292cba1 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 19 Jul 2023 12:08:02 +0200 Subject: [PATCH 17/25] more micro opt --- src/dex/algebra/algebra.ts | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 3ea965b19..827ace72e 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -153,19 +153,20 @@ export class Algebra extends SimpleExchange implements IDex { const key = `${token0}_${token1}`.toLowerCase(); - const notExistingPoolScore = await this.dexHelper.cache.zscore( - this.notExistingPoolSetKey, - key, - ); + // no need to run this logic on retry initialisation scenario + if (!pool) { + const notExistingPoolScore = await this.dexHelper.cache.zscore( + this.notExistingPoolSetKey, + key, + ); - const poolDoesNotExist = notExistingPoolScore !== null; + const poolDoesNotExist = notExistingPoolScore !== null; - if (poolDoesNotExist) { - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress)] = null; - return null; - } + if (poolDoesNotExist) { + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress)] = null; + return null; + } - if (!pool) { await this.dexHelper.cache.hset( this.dexmapKey, key, From f4ecb8ccb3c94d5fdf88c60a1a61a88f820627f2 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 19 Jul 2023 12:09:54 +0200 Subject: [PATCH 18/25] replicate fix of retry logic on univ3 and panv3 --- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 134 ++++++++++++----------- src/dex/uniswap-v3/uniswap-v3.ts | 131 +++++++++++----------- 2 files changed, 140 insertions(+), 125 deletions(-) diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index 93d45462e..3436b6e1a 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -157,23 +157,30 @@ export class PancakeswapV3 fee: bigint, blockNumber: number, ): Promise { - let pool = - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)]; - - if ( - pool && - pool.initFailed && - pool.initRetryCount % this.config.initRetryFrequency === 0 - ) { - // if init failed then prefer to early return pool with empty state to fallback to rpc call - return pool; + let pool = this.eventPools[ + this.getPoolIdentifier(srcAddress, destAddress, fee) + ] as PancakeSwapV3EventPool | null | undefined; + + if (pool === null) return null; + + if (pool) { + if (!pool.initFailed) { + return pool; + } else { + // if init failed then prefer to early return pool with empty state to fallback to rpc call + if (++pool.initRetryCount % this.config.initRetryFrequency === 0) { + return pool; + } + // else pursue with re-try initialization + } } - if (pool === undefined) { - const [token0, token1] = this._sortTokens(srcAddress, destAddress); + const [token0, token1] = this._sortTokens(srcAddress, destAddress); - const key = `${token0}_${token1}_${fee}`.toLowerCase(); + const key = `${token0}_${token1}_${fee}`.toLowerCase(); + // no need to run this logic on retry initialisation scenario + if (!pool) { const notExistingPoolScore = await this.dexHelper.cache.zscore( this.notExistingPoolSetKey, key, @@ -196,9 +203,12 @@ export class PancakeswapV3 fee: fee.toString(), }), ); + } - this.logger.trace(`starting to listen to new pool: ${key}`); - pool = new PancakeSwapV3EventPool( + this.logger.trace(`starting to listen to new pool: ${key}`); + pool = + pool || + new PancakeSwapV3EventPool( this.dexHelper, this.dexKey, this.stateMultiContract, @@ -213,59 +223,57 @@ export class PancakeswapV3 this.config.deployer, ); - try { - await pool.initialize(blockNumber, { - initCallback: (state: DeepReadonly) => { - //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber - pool!.addressesSubscribed[0] = state.pool; - pool!.poolAddress = state.pool; - pool!.initFailed = false; - pool!.initRetryCount = 0; - }, - }); - } catch (e) { - if (e instanceof Error && e.message.endsWith('Pool does not exist')) { - // no need to await we want the set to have the pool key but it's not blocking - this.dexHelper.cache.zadd( - this.notExistingPoolSetKey, - [Date.now(), key], - 'NX', - ); - - // Pool does not exist for this feeCode, so we can set it to null - // to prevent more requests for this pool - pool = null; - this.logger.trace( - `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} not found`, - e, - ); - } else { - // on unkown error mark as failed and increase retryCount for retry init strategy - // note: state would be null by default which allows to fallback - this.logger.warn( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryCount=${pool.initRetryCount}`, - e, - ); - pool.initFailed = true; - pool.initRetryCount++; - } - } + try { + await pool.initialize(blockNumber, { + initCallback: (state: DeepReadonly) => { + //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber + pool!.addressesSubscribed[0] = state.pool; + pool!.poolAddress = state.pool; + pool!.initFailed = false; + pool!.initRetryCount = 0; + }, + }); + } catch (e) { + if (e instanceof Error && e.message.endsWith('Pool does not exist')) { + // no need to await we want the set to have the pool key but it's not blocking + this.dexHelper.cache.zadd( + this.notExistingPoolSetKey, + [Date.now(), key], + 'NX', + ); - if (pool !== null) { - const allEventPools = Object.values(this.eventPools); - this.logger.info( - `starting to listen to new non-null pool: ${key}. Already following ${allEventPools - // Not that I like this reduce, but since it is done only on initialization, expect this to be ok - .reduce( - (acc, curr) => (curr !== null ? ++acc : acc), - 0, - )} non-null pools or ${allEventPools.length} total pools`, + // Pool does not exist for this feeCode, so we can set it to null + // to prevent more requests for this pool + pool = null; + this.logger.trace( + `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} not found`, + e, ); + } else { + // on unkown error mark as failed and increase retryCount for retry init strategy + // note: state would be null by default which allows to fallback + this.logger.warn( + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryCount=${pool.initRetryCount}`, + e, + ); + pool.initFailed = true; } + } - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = - pool; + if (pool !== null) { + const allEventPools = Object.values(this.eventPools); + this.logger.info( + `starting to listen to new non-null pool: ${key}. Already following ${allEventPools + // Not that I like this reduce, but since it is done only on initialization, expect this to be ok + .reduce( + (acc, curr) => (curr !== null ? ++acc : acc), + 0, + )} non-null pools or ${allEventPools.length} total pools`, + ); } + + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = + pool; return pool; } diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index c33542566..7d283c5ee 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -182,23 +182,29 @@ export class UniswapV3 fee: bigint, blockNumber: number, ): Promise { - let pool = - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)]; + let pool = this.eventPools[ + this.getPoolIdentifier(srcAddress, destAddress, fee) + ] as UniswapV3EventPool | null | undefined; - if ( - pool && - pool.initFailed && - pool.initRetryCount % this.config.initRetryFrequency === 0 - ) { - // if init failed then prefer to early return pool with empty state to fallback to rpc call - return pool; + if (pool === null) return null; + + if (pool) { + if (!pool.initFailed) { + return pool; + } else { + // if init failed then prefer to early return pool with empty state to fallback to rpc call + if (++pool.initRetryCount % this.config.initRetryFrequency === 0) { + return pool; + } + // else pursue with re-try initialization + } } - if (pool === undefined) { - const [token0, token1] = this._sortTokens(srcAddress, destAddress); + const [token0, token1] = this._sortTokens(srcAddress, destAddress); - const key = `${token0}_${token1}_${fee}`.toLowerCase(); + const key = `${token0}_${token1}_${fee}`.toLowerCase(); + if (!pool) { const notExistingPoolScore = await this.dexHelper.cache.zscore( this.notExistingPoolSetKey, key, @@ -221,9 +227,12 @@ export class UniswapV3 fee: fee.toString(), }), ); + } - this.logger.trace(`starting to listen to new pool: ${key}`); - pool = new UniswapV3EventPool( + this.logger.trace(`starting to listen to new pool: ${key}`); + pool = + pool || + new UniswapV3EventPool( this.dexHelper, this.dexKey, this.stateMultiContract, @@ -237,59 +246,57 @@ export class UniswapV3 this.config.initHash, ); - try { - await pool.initialize(blockNumber, { - initCallback: (state: DeepReadonly) => { - //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber - pool!.addressesSubscribed[0] = state.pool; - pool!.poolAddress = state.pool; - pool!.initFailed = false; - pool!.initRetryCount = 0; - }, - }); - } catch (e) { - if (e instanceof Error && e.message.endsWith('Pool does not exist')) { - // no need to await we want the set to have the pool key but it's not blocking - this.dexHelper.cache.zadd( - this.notExistingPoolSetKey, - [Date.now(), key], - 'NX', - ); - - // Pool does not exist for this feeCode, so we can set it to null - // to prevent more requests for this pool - pool = null; - this.logger.trace( - `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} not found`, - e, - ); - } else { - // on unkown error mark as failed and increase retryCount for retry init strategy - // note: state would be null by default which allows to fallback - this.logger.warn( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryCount=${pool.initRetryCount}`, - e, - ); - pool.initFailed = true; - pool.initRetryCount++; - } - } + try { + await pool.initialize(blockNumber, { + initCallback: (state: DeepReadonly) => { + //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber + pool!.addressesSubscribed[0] = state.pool; + pool!.poolAddress = state.pool; + pool!.initFailed = false; + pool!.initRetryCount = 0; + }, + }); + } catch (e) { + if (e instanceof Error && e.message.endsWith('Pool does not exist')) { + // no need to await we want the set to have the pool key but it's not blocking + this.dexHelper.cache.zadd( + this.notExistingPoolSetKey, + [Date.now(), key], + 'NX', + ); - if (pool !== null) { - const allEventPools = Object.values(this.eventPools); - this.logger.info( - `starting to listen to new non-null pool: ${key}. Already following ${allEventPools - // Not that I like this reduce, but since it is done only on initialization, expect this to be ok - .reduce( - (acc, curr) => (curr !== null ? ++acc : acc), - 0, - )} non-null pools or ${allEventPools.length} total pools`, + // Pool does not exist for this feeCode, so we can set it to null + // to prevent more requests for this pool + pool = null; + this.logger.trace( + `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} not found`, + e, + ); + } else { + // on unkown error mark as failed and increase retryCount for retry init strategy + // note: state would be null by default which allows to fallback + this.logger.warn( + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryCount=${pool.initRetryCount}`, + e, ); + pool.initFailed = true; } + } - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = - pool; + if (pool !== null) { + const allEventPools = Object.values(this.eventPools); + this.logger.info( + `starting to listen to new non-null pool: ${key}. Already following ${allEventPools + // Not that I like this reduce, but since it is done only on initialization, expect this to be ok + .reduce( + (acc, curr) => (curr !== null ? ++acc : acc), + 0, + )} non-null pools or ${allEventPools.length} total pools`, + ); } + + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = + pool; return pool; } From c4a86a6b8065aaa6db00f82c5bf814f2e18758e2 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 19 Jul 2023 12:11:22 +0200 Subject: [PATCH 19/25] 2.25.2-algebra-z-rpc.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9490176df..7009e6765 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.25.2-algebra-z-rpc.6", + "version": "2.25.2-algebra-z-rpc.7", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From ed41f6477912b4fcfe325f4d25a13de61203a293 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 19 Jul 2023 12:50:30 +0200 Subject: [PATCH 20/25] fix wrong cond --- src/dex/algebra/algebra.ts | 2 +- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 2 +- src/dex/uniswap-v3/uniswap-v3.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 827ace72e..bfbeed760 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -142,7 +142,7 @@ export class Algebra extends SimpleExchange implements IDex { return pool; } else { // if init failed then prefer to early return pool with empty state to fallback to rpc call - if (++pool.initRetryCount % this.config.initRetryFrequency === 0) { + if (++pool.initRetryCount % this.config.initRetryFrequency !== 0) { return pool; } // else pursue with re-try initialization diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index 3436b6e1a..b9faa381d 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -168,7 +168,7 @@ export class PancakeswapV3 return pool; } else { // if init failed then prefer to early return pool with empty state to fallback to rpc call - if (++pool.initRetryCount % this.config.initRetryFrequency === 0) { + if (++pool.initRetryCount % this.config.initRetryFrequency !== 0) { return pool; } // else pursue with re-try initialization diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 7d283c5ee..9348e1883 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -193,7 +193,7 @@ export class UniswapV3 return pool; } else { // if init failed then prefer to early return pool with empty state to fallback to rpc call - if (++pool.initRetryCount % this.config.initRetryFrequency === 0) { + if (++pool.initRetryCount % this.config.initRetryFrequency !== 0) { return pool; } // else pursue with re-try initialization From 0e8f11bda152c11853296e0bf7464d59bd74eefb Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 19 Jul 2023 12:59:10 +0200 Subject: [PATCH 21/25] 2.25.2-algebra-z-rpc.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7009e6765..074979f0a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.25.2-algebra-z-rpc.7", + "version": "2.25.2-algebra-z-rpc.8", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 5ae3330ab8bbb2ea5a9cc6994566df1d9d618ddf Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 19 Jul 2023 17:07:43 +0200 Subject: [PATCH 22/25] decrease retry frequency on zkevm --- src/dex/algebra/config.ts | 2 +- src/dex/pancakeswap-v3/config.ts | 2 +- src/dex/uniswap-v3/config.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/algebra/config.ts b/src/dex/algebra/config.ts index 20bf174f2..402609e29 100644 --- a/src/dex/algebra/config.ts +++ b/src/dex/algebra/config.ts @@ -25,7 +25,7 @@ export const AlgebraConfig: DexConfigMap = { initHash: '0x6ec6c9c8091d160c0aa74b2b14ba9c1717e95093bd3ac085cee99a49aab294a4', chunksCount: 3, - initRetryFrequency: 10, + initRetryFrequency: 30, algebraStateMulticall: '0xa6bc273A238867dD74F2bBbD5fBbA3c941C939B9', subgraphURL: 'https://api.studio.thegraph.com/query/44554/quickswap-v3-02/0.0.7', diff --git a/src/dex/pancakeswap-v3/config.ts b/src/dex/pancakeswap-v3/config.ts index 098cc6329..b4ca340ff 100644 --- a/src/dex/pancakeswap-v3/config.ts +++ b/src/dex/pancakeswap-v3/config.ts @@ -32,7 +32,7 @@ export const PancakeswapV3Config: DexConfigMap = { stateMulticall: '0x9DAd2ED7ADc6eaacf81589Cd043579c9684E5C81', uniswapMulticall: '0xac1cE734566f390A94b00eb9bf561c2625BF44ea', chunksCount: 10, - initRetryFrequency: 10, + initRetryFrequency: 30, initHash: '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', subgraphURL: diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index 2321f7b74..c1c74165f 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -113,7 +113,7 @@ export const UniswapV3Config: DexConfigMap = { stateMulticall: '0x983ab0171159b7e17835cc6aec70c72b8aadb133', uniswapMulticall: '0x61530d6E1c7A47BBB3e48e8b8EdF7569DcFeE121', chunksCount: 5, - initRetryFrequency: 10, + initRetryFrequency: 30, initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, subgraphURL: 'https://api.studio.thegraph.com/query/44554/uniswap-v3/version/latest', From 44be3bdfb64bce37bd517447fbfadc21cc149bf5 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 19 Jul 2023 17:09:47 +0200 Subject: [PATCH 23/25] 2.25.2-algebra-z-rpc.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 074979f0a..7de830502 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.25.2-algebra-z-rpc.8", + "version": "2.25.2-algebra-z-rpc.9", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From a8c8f0ba481570f31bc52604559021ebcc347619 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Thu, 20 Jul 2023 13:28:18 +0200 Subject: [PATCH 24/25] rename initRetryCount -> initRetryAttemptCount --- src/dex/algebra/algebra-pool.ts | 2 +- src/dex/algebra/algebra.ts | 9 ++++++--- src/dex/pancakeswap-v3/pancakeswap-v3-pool.ts | 2 +- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 9 ++++++--- src/dex/uniswap-v3/uniswap-v3-pool.ts | 2 +- src/dex/uniswap-v3/uniswap-v3.ts | 9 ++++++--- 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/dex/algebra/algebra-pool.ts b/src/dex/algebra/algebra-pool.ts index f42509b1e..7350784b4 100644 --- a/src/dex/algebra/algebra-pool.ts +++ b/src/dex/algebra/algebra-pool.ts @@ -50,7 +50,7 @@ export class AlgebraEventPool extends StatefulEventSubscriber { public readonly poolIface = new Interface(AlgebraABI); public initFailed = false; - public initRetryCount = 0; + public initRetryAttemptCount = 0; constructor( readonly dexHelper: IDexHelper, diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index bfbeed760..5ddc8f948 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -142,7 +142,10 @@ export class Algebra extends SimpleExchange implements IDex { return pool; } else { // if init failed then prefer to early return pool with empty state to fallback to rpc call - if (++pool.initRetryCount % this.config.initRetryFrequency !== 0) { + if ( + ++pool.initRetryAttemptCount % this.config.initRetryFrequency !== + 0 + ) { return pool; } // else pursue with re-try initialization @@ -201,7 +204,7 @@ export class Algebra extends SimpleExchange implements IDex { pool!.addressesSubscribed[0] = state.pool; pool!.poolAddress = state.pool; pool!.initFailed = false; - pool!.initRetryCount = 0; + pool!.initRetryAttemptCount = 0; }, }); } catch (e) { @@ -224,7 +227,7 @@ export class Algebra extends SimpleExchange implements IDex { // on unkown error mark as failed and increase retryCount for retry init strategy // note: state would be null by default which allows to fallback this.logger.warn( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryCount=${pool.initRetryCount}`, + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, e, ); pool.initFailed = true; diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3-pool.ts b/src/dex/pancakeswap-v3/pancakeswap-v3-pool.ts index 8662805e8..94e613c61 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3-pool.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3-pool.ts @@ -55,7 +55,7 @@ export class PancakeSwapV3EventPool extends StatefulEventSubscriber { public readonly poolIface = new Interface(PancakeswapV3PoolABI); public initFailed = false; - public initRetryCount = 0; + public initRetryAttemptCount = 0; public readonly feeCodeAsString; diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index b9faa381d..c38f5089a 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -168,7 +168,10 @@ export class PancakeswapV3 return pool; } else { // if init failed then prefer to early return pool with empty state to fallback to rpc call - if (++pool.initRetryCount % this.config.initRetryFrequency !== 0) { + if ( + ++pool.initRetryAttemptCount % this.config.initRetryFrequency !== + 0 + ) { return pool; } // else pursue with re-try initialization @@ -230,7 +233,7 @@ export class PancakeswapV3 pool!.addressesSubscribed[0] = state.pool; pool!.poolAddress = state.pool; pool!.initFailed = false; - pool!.initRetryCount = 0; + pool!.initRetryAttemptCount = 0; }, }); } catch (e) { @@ -253,7 +256,7 @@ export class PancakeswapV3 // on unkown error mark as failed and increase retryCount for retry init strategy // note: state would be null by default which allows to fallback this.logger.warn( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryCount=${pool.initRetryCount}`, + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, e, ); pool.initFailed = true; diff --git a/src/dex/uniswap-v3/uniswap-v3-pool.ts b/src/dex/uniswap-v3/uniswap-v3-pool.ts index baa2dcce2..82342ce24 100644 --- a/src/dex/uniswap-v3/uniswap-v3-pool.ts +++ b/src/dex/uniswap-v3/uniswap-v3-pool.ts @@ -52,7 +52,7 @@ export class UniswapV3EventPool extends StatefulEventSubscriber { public readonly poolIface = new Interface(UniswapV3PoolABI); public initFailed = false; - public initRetryCount = 0; + public initRetryAttemptCount = 0; public readonly feeCodeAsString; diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 9348e1883..347fad846 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -193,7 +193,10 @@ export class UniswapV3 return pool; } else { // if init failed then prefer to early return pool with empty state to fallback to rpc call - if (++pool.initRetryCount % this.config.initRetryFrequency !== 0) { + if ( + ++pool.initRetryAttemptCount % this.config.initRetryFrequency !== + 0 + ) { return pool; } // else pursue with re-try initialization @@ -253,7 +256,7 @@ export class UniswapV3 pool!.addressesSubscribed[0] = state.pool; pool!.poolAddress = state.pool; pool!.initFailed = false; - pool!.initRetryCount = 0; + pool!.initRetryAttemptCount = 0; }, }); } catch (e) { @@ -276,7 +279,7 @@ export class UniswapV3 // on unkown error mark as failed and increase retryCount for retry init strategy // note: state would be null by default which allows to fallback this.logger.warn( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryCount=${pool.initRetryCount}`, + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, e, ); pool.initFailed = true; From 8cdb7228932d3ab668c0a591ba56cc043cdb9189 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Thu, 20 Jul 2023 13:41:30 +0200 Subject: [PATCH 25/25] 2.26.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7de830502..094d3168f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.25.2-algebra-z-rpc.9", + "version": "2.26.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib",