@paraswap/dex-lib 4.1.7-pub-sub.2 → 4.1.7-pub-sub.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/build/dex/angle-staked-stable/angle-staked-stable.js +2 -1
  2. package/build/dex/angle-staked-stable/angle-staked-stable.js.map +1 -1
  3. package/build/dex/angle-transmuter/angle-transmuter.js.map +1 -1
  4. package/build/dex/balancer-v1/config.js +2 -1
  5. package/build/dex/balancer-v1/config.js.map +1 -1
  6. package/build/dex/dexalot/dexalot.d.ts +2 -9
  7. package/build/dex/dexalot/dexalot.js +18 -62
  8. package/build/dex/dexalot/dexalot.js.map +1 -1
  9. package/build/dex/dexalot/rate-fetcher.d.ts +19 -4
  10. package/build/dex/dexalot/rate-fetcher.js +112 -8
  11. package/build/dex/dexalot/rate-fetcher.js.map +1 -1
  12. package/build/dex/dexalot/types.d.ts +0 -1
  13. package/build/dex/generic-rfq/rate-fetcher.js +0 -12
  14. package/build/dex/generic-rfq/rate-fetcher.js.map +1 -1
  15. package/build/dex/hashflow/constants.d.ts +2 -2
  16. package/build/dex/hashflow/constants.js +2 -2
  17. package/build/dex/hashflow/hashflow.d.ts +1 -6
  18. package/build/dex/hashflow/hashflow.js +9 -34
  19. package/build/dex/hashflow/hashflow.js.map +1 -1
  20. package/build/dex/hashflow/rate-fetcher.d.ts +12 -2
  21. package/build/dex/hashflow/rate-fetcher.js +54 -6
  22. package/build/dex/hashflow/rate-fetcher.js.map +1 -1
  23. package/build/dex/hashflow/types.d.ts +0 -1
  24. package/build/dex/weth/weth.js +2 -1
  25. package/build/dex/weth/weth.js.map +1 -1
  26. package/build/lib/pub-sub.d.ts +0 -2
  27. package/build/lib/pub-sub.js +0 -12
  28. package/build/lib/pub-sub.js.map +1 -1
  29. package/build/pricing-helper.d.ts +1 -1
  30. package/build/pricing-helper.js +13 -9
  31. package/build/pricing-helper.js.map +1 -1
  32. package/build/types.d.ts +1 -0
  33. package/package.json +1 -1
  34. package/src/dex/aave-gsm/aave-gsm-gas-estimation.test.ts +32 -0
  35. package/src/dex/aave-v2/aave-v2-gas-estimation.test.ts +28 -0
  36. package/src/dex/aave-v3/aave-v3-gas-estimation.test.ts +66 -0
  37. package/src/dex/aave-v3-stata/aave-v3-stata-gas-estimation.test.ts +41 -0
  38. package/src/dex/aave-v3-stata-v2/aave-v3-stata-v2-gas-estimation.test.ts +41 -0
  39. package/src/dex/angle-staked-stable/angle-staked-stable-gas-estimation.test.ts +29 -0
  40. package/src/dex/angle-staked-stable/angle-staked-stable.ts +2 -1
  41. package/src/dex/angle-transmuter/angle-transmuter-gas-estimation.test.ts +41 -0
  42. package/src/dex/angle-transmuter/angle-transmuter.ts +0 -1
  43. package/src/dex/balancer-v1/balancer-v1-gas-estimation.test.ts +29 -0
  44. package/src/dex/balancer-v1/config.ts +2 -1
  45. package/src/dex/balancer-v2/balancer-v2-gas-estimation.test.ts +98 -0
  46. package/src/dex/balancer-v3/balancer-v3-gas-estimation.test.ts +30 -0
  47. package/src/dex/bancor/bancor-gas-estimation.test.ts +30 -0
  48. package/src/dex/bebop/bebop-gas-estimation.test.ts +30 -0
  49. package/src/dex/concentrator-arusd/concentrator-arusd-gas-estimation.test.ts +29 -0
  50. package/src/dex/curve-v1/curve-v1-gas-estimation.test.ts +29 -0
  51. package/src/dex/curve-v2/curve-v2-gas-estimation.test.ts +29 -0
  52. package/src/dex/dexalot/dexalot.ts +27 -127
  53. package/src/dex/dexalot/rate-fetcher.ts +219 -9
  54. package/src/dex/dexalot/types.ts +0 -1
  55. package/src/dex/fluid-dex/fluid-dex-gas-estimation.test.ts +29 -0
  56. package/src/dex/fx-protocol-rusd/fx-protocol-rusd-gas-estimation.test.ts +29 -0
  57. package/src/dex/generic-rfq/rate-fetcher.ts +0 -30
  58. package/src/dex/hashflow/constants.ts +2 -2
  59. package/src/dex/hashflow/hashflow-gas-estimation.test.ts +30 -0
  60. package/src/dex/hashflow/hashflow.ts +11 -67
  61. package/src/dex/hashflow/rate-fetcher.ts +106 -8
  62. package/src/dex/hashflow/types.ts +0 -1
  63. package/src/dex/idle-dao/idle-dao--gas-estimation.test.ts +30 -0
  64. package/src/dex/lido/lido-gas-estimation.test.ts +29 -0
  65. package/src/dex/lite-psm/lite-psm-gas-estimation.test.ts +34 -0
  66. package/src/dex/maker-psm/maker-psm-gas-estimation.test.ts +34 -0
  67. package/src/dex/maverick-v1/maverick-v1-gas-estimation.test.ts +29 -0
  68. package/src/dex/maverick-v2/maverick-v2-gas-estimation.test.ts +29 -0
  69. package/src/dex/pancakeswap-v3/pancakeswap-v3-gas-estimation.test.ts +29 -0
  70. package/src/dex/polygon-migrator/polygon-migrator-gas-estimation.test.ts +41 -0
  71. package/src/dex/sky-converter/sky-converter-gas-estimation.test.ts +78 -0
  72. package/src/dex/solidly/solidly-gas-estimation.test.ts +29 -0
  73. package/src/dex/solidly-v3/solidly-v3-gas-estimation.test.ts +29 -0
  74. package/src/dex/spark/spark-gas-estimation.test.ts +29 -0
  75. package/src/dex/stader/stader-gas-estimation.test.ts +29 -0
  76. package/src/dex/stkgho/stkgho-gas-estimation.test.ts +29 -0
  77. package/src/dex/swaap-v2/swaap-v2-estimation.test.ts +29 -0
  78. package/src/dex/swell/swell-estimation.test.ts +29 -0
  79. package/src/dex/trader-joe-v2.1/trader-joe-v2.1-gas-estimation.test.ts +29 -0
  80. package/src/dex/uniswap-v2/uniswap-v2-gas-estimation.test.ts +98 -0
  81. package/src/dex/uniswap-v3/uniswap-v3-gas-estimation.test.ts +98 -0
  82. package/src/dex/usual/usual-gas-estimation.test.ts +54 -0
  83. package/src/dex/usual-pp/usual-pp-gas-estimation.test.ts +29 -0
  84. package/src/dex/weth/weth-gas-estimation.test.ts +42 -0
  85. package/src/dex/weth/weth.ts +3 -1
  86. package/src/dex/wombat/wombat-gas-estimation.test.ts +29 -0
  87. package/src/dex/wsteth/wsteth-gas-estimation.test.ts +41 -0
  88. package/src/dex/wusdm/wusdm-gas-estimation.test.ts +41 -0
  89. package/src/lib/pub-sub.ts +0 -27
  90. package/src/pricing-helper.ts +19 -11
  91. package/src/types.ts +1 -0
  92. package/tests/constants-e2e.ts +8 -0
  93. package/tests/tenderly-simulation-new.test.ts +151 -0
  94. package/tests/tenderly-simulation-new.ts +698 -0
  95. package/tests/token-storage-slots.json +532 -0
  96. package/tests/utils-e2e.ts +137 -1
@@ -28,14 +28,14 @@ import {
28
28
  ClobSide,
29
29
  DexalotData,
30
30
  PairData,
31
- PairDataMap,
32
- PriceDataMap,
33
31
  DexalotRfqError,
34
32
  DexalotAPIParameters,
35
33
  RFQResponse,
36
34
  RFQResponseError,
37
- TokenAddrDataMap,
38
35
  TokenDataMap,
36
+ PairDataMap,
37
+ TokenAddrDataMap,
38
+ PriceDataMap,
39
39
  } from './types';
40
40
  import {
41
41
  SlippageCheckError,
@@ -52,15 +52,10 @@ import {
52
52
  DEXALOT_API_PRICES_POLLING_INTERVAL_MS,
53
53
  DEXALOT_PRICES_CACHES_TTL_S,
54
54
  DEXALOT_GAS_COST,
55
- DEXALOT_PAIRS_CACHES_TTL_S,
56
55
  DEXALOT_API_PAIRS_POLLING_INTERVAL_MS,
57
56
  DEXALOT_TOKENS_CACHES_TTL_S,
58
57
  DEXALOT_API_BLACKLIST_POLLING_INTERVAL_MS,
59
- DEXALOT_RATE_LIMITED_TTL_S,
60
58
  DEXALOT_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION,
61
- DEXALOT_RESTRICTED_CACHE_KEY,
62
- DEXALOT_RESTRICT_TTL_S,
63
- DEXALOT_RATELIMIT_CACHE_VALUE,
64
59
  DEXALOT_BLACKLIST_CACHES_TTL_S,
65
60
  DEXALOT_FIRM_QUOTE_TIMEOUT_MS,
66
61
  } from './constants';
@@ -130,7 +125,6 @@ export class Dexalot extends SimpleExchange implements IDex<DexalotData> {
130
125
  pricesReqParams: this.getAPIReqParams('api/rfq/prices', 'GET'),
131
126
  blacklistReqParams: this.getAPIReqParams('api/rfq/blacklist', 'GET'),
132
127
  pairsCacheKey: this.pairsCacheKey,
133
- pairsCacheTTLSecs: DEXALOT_PAIRS_CACHES_TTL_S,
134
128
  pricesCacheKey: this.pricesCacheKey,
135
129
  pricesCacheTTLSecs: DEXALOT_PRICES_CACHES_TTL_S,
136
130
  tokensAddrCacheKey: this.tokensAddrCacheKey,
@@ -144,10 +138,7 @@ export class Dexalot extends SimpleExchange implements IDex<DexalotData> {
144
138
  }
145
139
 
146
140
  async initializePricing(blockNumber: number): Promise<void> {
147
- if (!this.dexHelper.config.isSlave) {
148
- this.rateFetcher.start();
149
- }
150
-
141
+ this.rateFetcher.start();
151
142
  return;
152
143
  }
153
144
 
@@ -169,7 +160,7 @@ export class Dexalot extends SimpleExchange implements IDex<DexalotData> {
169
160
  return null;
170
161
  }
171
162
 
172
- const cachedTokens = (await this.getCachedTokens()) || {};
163
+ const cachedTokens = (await this.rateFetcher.getCachedTokens()) || {};
173
164
  if (
174
165
  !(normalizedSrcToken.address in cachedTokens) ||
175
166
  !(normalizedDestToken.address in cachedTokens)
@@ -180,7 +171,7 @@ export class Dexalot extends SimpleExchange implements IDex<DexalotData> {
180
171
  normalizedDestToken.symbol =
181
172
  cachedTokens[normalizedDestToken.address].symbol;
182
173
 
183
- const cachedPairs = (await this.getCachedPairs()) || {};
174
+ const cachedPairs = (await this.rateFetcher.getCachedPairs()) || {};
184
175
 
185
176
  const potentialPairs = [
186
177
  {
@@ -228,7 +219,7 @@ export class Dexalot extends SimpleExchange implements IDex<DexalotData> {
228
219
  return [];
229
220
  }
230
221
 
231
- const tokensAddr = (await this.getCachedTokensAddr()) || {};
222
+ const tokensAddr = (await this.rateFetcher.getCachedTokensAddr()) || {};
232
223
 
233
224
  return [
234
225
  this.getIdentifier(
@@ -446,7 +437,7 @@ export class Dexalot extends SimpleExchange implements IDex<DexalotData> {
446
437
  const normalizedSrcToken = this.normalizeToken(srcToken);
447
438
  const normalizedDestToken = this.normalizeToken(destToken);
448
439
 
449
- this.tokensMap = (await this.getCachedTokens()) || {};
440
+ this.tokensMap = (await this.rateFetcher.getCachedTokens()) || {};
450
441
  if (normalizedSrcToken.address === normalizedDestToken.address) {
451
442
  return null;
452
443
  }
@@ -463,7 +454,7 @@ export class Dexalot extends SimpleExchange implements IDex<DexalotData> {
463
454
  : await this.getPoolIdentifiers(srcToken, destToken, side, blockNumber);
464
455
 
465
456
  pools = await Promise.all(
466
- pools.map(async p => !(await this.isRestrictedPool(p))),
457
+ pools.map(async p => !(await this.rateFetcher.isRestrictedPool(p))),
467
458
  ).then(res => pools.filter((_v, i) => res[i]));
468
459
  if (pools.length === 0) {
469
460
  return null;
@@ -477,12 +468,12 @@ export class Dexalot extends SimpleExchange implements IDex<DexalotData> {
477
468
  return null;
478
469
  }
479
470
 
480
- const priceMap = await this.getCachedPrices();
471
+ const priceMap = await this.rateFetcher.getCachedPrices();
481
472
  if (!priceMap) {
482
473
  return null;
483
474
  }
484
475
 
485
- const tokensAddr = (await this.getCachedTokensAddr()) || {};
476
+ const tokensAddr = (await this.rateFetcher.getCachedTokensAddr()) || {};
486
477
  const pairKey = `${pairData.base}/${pairData.quote}`.toLowerCase();
487
478
  if (
488
479
  !(pairKey in priceMap) ||
@@ -565,7 +556,7 @@ export class Dexalot extends SimpleExchange implements IDex<DexalotData> {
565
556
  side: SwapSide,
566
557
  options: PreprocessTransactionOptions,
567
558
  ): Promise<[OptimalSwapExchange<DexalotData>, ExchangeTxInfo]> {
568
- if (await this.isBlacklisted(options.txOrigin)) {
559
+ if (await this.rateFetcher.isBlacklisted(options.txOrigin)) {
569
560
  this.logger.warn(
570
561
  `${this.dexKey}-${this.network}: blacklisted TX Origin address '${options.txOrigin}' trying to build a transaction. Bailing...`,
571
562
  );
@@ -735,9 +726,12 @@ export class Dexalot extends SimpleExchange implements IDex<DexalotData> {
735
726
  this.logger.warn(
736
727
  `${this.dexKey}-${this.network}: Encountered rate limited user=${options.userAddress}. Adding to local rate limit cache`,
737
728
  );
738
- await this.setRateLimited(options.userAddress, errorData.RetryAfter);
729
+ await this.rateFetcher.setRateLimited(
730
+ options.userAddress,
731
+ errorData.RetryAfter,
732
+ );
739
733
  } else {
740
- await this.setBlacklist(options.userAddress);
734
+ await this.rateFetcher.setBlacklist(options.userAddress);
741
735
  this.logger.error(
742
736
  `${this.dexKey}-${this.network}: Failed to fetch RFQ for ${swapIdentifier}: ${errorData.Reason}`,
743
737
  );
@@ -758,7 +752,9 @@ export class Dexalot extends SimpleExchange implements IDex<DexalotData> {
758
752
  `${this.dexKey}-${this.network}: protocol is restricted for pools ${poolIdentifiers} due to swap: ${swapIdentifier}`,
759
753
  );
760
754
  await Promise.all(
761
- poolIdentifiers.map(async p => await this.restrictPool(p)),
755
+ poolIdentifiers.map(
756
+ async p => await this.rateFetcher.restrictPool(p),
757
+ ),
762
758
  );
763
759
  }
764
760
  }
@@ -844,106 +840,6 @@ export class Dexalot extends SimpleExchange implements IDex<DexalotData> {
844
840
  };
845
841
  }
846
842
 
847
- getRestrictedPoolKey(poolIdentifier: string): string {
848
- return `${DEXALOT_RESTRICTED_CACHE_KEY}-${poolIdentifier}`;
849
- }
850
-
851
- async restrictPool(
852
- poolIdentifier: string,
853
- ttl: number = DEXALOT_RESTRICT_TTL_S,
854
- ): Promise<boolean> {
855
- await this.dexHelper.cache.setex(
856
- this.dexKey,
857
- this.network,
858
- this.getRestrictedPoolKey(poolIdentifier),
859
- ttl,
860
- 'true',
861
- );
862
- return true;
863
- }
864
-
865
- async isRestrictedPool(poolIdentifier: string): Promise<boolean> {
866
- const result = await this.dexHelper.cache.get(
867
- this.dexKey,
868
- this.network,
869
- this.getRestrictedPoolKey(poolIdentifier),
870
- );
871
-
872
- return result === 'true';
873
- }
874
-
875
- async setBlacklist(
876
- txOrigin: Address,
877
- ttl: number = DEXALOT_BLACKLIST_CACHES_TTL_S,
878
- ): Promise<boolean> {
879
- const cachedBlacklist = await this.dexHelper.cache.get(
880
- this.dexKey,
881
- this.network,
882
- this.blacklistCacheKey,
883
- );
884
-
885
- let blacklist: string[] = [];
886
- if (cachedBlacklist) {
887
- blacklist = JSON.parse(cachedBlacklist);
888
- }
889
-
890
- blacklist.push(txOrigin.toLowerCase());
891
-
892
- this.dexHelper.cache.setex(
893
- this.dexKey,
894
- this.network,
895
- this.blacklistCacheKey,
896
- ttl,
897
- JSON.stringify(blacklist),
898
- );
899
-
900
- return true;
901
- }
902
-
903
- async isBlacklisted(txOrigin: Address): Promise<boolean> {
904
- const cachedBlacklist = await this.dexHelper.cache.get(
905
- this.dexKey,
906
- this.network,
907
- this.blacklistCacheKey,
908
- );
909
-
910
- if (cachedBlacklist) {
911
- const blacklist = JSON.parse(cachedBlacklist) as string[];
912
- return blacklist.includes(txOrigin.toLowerCase());
913
- }
914
-
915
- // To not show pricing for rate limited users
916
- if (await this.isRateLimited(txOrigin)) {
917
- return true;
918
- }
919
-
920
- return false;
921
- }
922
-
923
- getRateLimitedKey(address: Address) {
924
- return `rate_limited_${address}`.toLowerCase();
925
- }
926
-
927
- async isRateLimited(txOrigin: Address): Promise<boolean> {
928
- const result = await this.dexHelper.cache.get(
929
- this.dexKey,
930
- this.network,
931
- this.getRateLimitedKey(txOrigin),
932
- );
933
- return result === DEXALOT_RATELIMIT_CACHE_VALUE;
934
- }
935
-
936
- async setRateLimited(txOrigin: Address, ttl = DEXALOT_RATE_LIMITED_TTL_S) {
937
- await this.dexHelper.cache.setex(
938
- this.dexKey,
939
- this.network,
940
- this.getRateLimitedKey(txOrigin),
941
- ttl,
942
- DEXALOT_RATELIMIT_CACHE_VALUE,
943
- );
944
- return true;
945
- }
946
-
947
843
  async getSimpleParam(
948
844
  srcToken: string,
949
845
  destToken: string,
@@ -1044,9 +940,9 @@ export class Dexalot extends SimpleExchange implements IDex<DexalotData> {
1044
940
  limit: number,
1045
941
  ): Promise<PoolLiquidity[]> {
1046
942
  const normalizedTokenAddress = this.normalizeAddress(tokenAddress);
1047
- const pairs = (await this.getCachedPairs()) || {};
1048
- this.tokensMap = (await this.getCachedTokens()) || {};
1049
- const tokensAddr = (await this.getCachedTokensAddr()) || {};
943
+ const pairs = (await this.rateFetcher.getCachedPairs()) || {};
944
+ this.tokensMap = (await this.rateFetcher.getCachedTokens()) || {};
945
+ const tokensAddr = (await this.rateFetcher.getCachedTokensAddr()) || {};
1050
946
  const token = this.getTokenFromAddress(normalizedTokenAddress);
1051
947
  if (!token) {
1052
948
  return [];
@@ -1111,4 +1007,8 @@ export class Dexalot extends SimpleExchange implements IDex<DexalotData> {
1111
1007
  this.rateFetcher.stop();
1112
1008
  }
1113
1009
  }
1010
+
1011
+ async isBlacklisted(userAddress: string): Promise<boolean> {
1012
+ return this.rateFetcher.isBlacklisted(userAddress);
1013
+ }
1114
1014
  }
@@ -2,9 +2,11 @@ import { Network } from '../../constants';
2
2
  import { IDexHelper } from '../../dex-helper';
3
3
  import { Fetcher } from '../../lib/fetcher/fetcher';
4
4
  import { validateAndCast } from '../../lib/validators';
5
- import { Logger, Token } from '../../types';
5
+ import { Address, Logger, Token } from '../../types';
6
6
  import {
7
7
  DexalotBlacklistResponse,
8
+ TokenDataMap,
9
+ TokenAddrDataMap,
8
10
  DexalotPairsResponse,
9
11
  DexalotPricesResponse,
10
12
  DexalotRateFetcherConfig,
@@ -16,13 +18,21 @@ import {
16
18
  pairsResponseValidator,
17
19
  pricesResponseValidator,
18
20
  } from './validators';
21
+ import {
22
+ DEXALOT_BLACKLIST_CACHES_TTL_S,
23
+ DEXALOT_RATE_LIMITED_TTL_S,
24
+ DEXALOT_RATELIMIT_CACHE_VALUE,
25
+ DEXALOT_RESTRICT_TTL_S,
26
+ DEXALOT_RESTRICTED_CACHE_KEY,
27
+ } from './constants';
28
+ import { ExpKeyValuePubSub, NonExpSetPubSub } from '../../lib/pub-sub';
19
29
 
20
30
  export class RateFetcher {
21
31
  private pairsFetcher: Fetcher<DexalotPairsResponse>;
22
32
  private pairsCacheKey: string;
23
- private pairsCacheTTL: number;
24
33
 
25
34
  private rateFetcher: Fetcher<DexalotPricesResponse>;
35
+ private rateTokensPubSub: ExpKeyValuePubSub;
26
36
  private pricesCacheKey: string;
27
37
  private pricesCacheTTL: number;
28
38
 
@@ -31,9 +41,12 @@ export class RateFetcher {
31
41
  private tokensCacheTTL: number;
32
42
 
33
43
  private blacklistFetcher: Fetcher<DexalotBlacklistResponse>;
44
+ private blacklistPubSub: NonExpSetPubSub;
34
45
  private blacklistCacheKey: string;
35
46
  private blacklistCacheTTL: number;
36
47
 
48
+ private restrictedPoolPubSub: ExpKeyValuePubSub;
49
+
37
50
  constructor(
38
51
  private dexHelper: IDexHelper,
39
52
  private dexKey: string,
@@ -42,7 +55,6 @@ export class RateFetcher {
42
55
  config: DexalotRateFetcherConfig,
43
56
  ) {
44
57
  this.pairsCacheKey = config.rateConfig.pairsCacheKey;
45
- this.pairsCacheTTL = config.rateConfig.pairsCacheTTLSecs;
46
58
  this.pricesCacheKey = config.rateConfig.pricesCacheKey;
47
59
  this.pricesCacheTTL = config.rateConfig.pricesCacheTTLSecs;
48
60
  this.tokensAddrCacheKey = config.rateConfig.tokensAddrCacheKey;
@@ -51,6 +63,12 @@ export class RateFetcher {
51
63
  this.blacklistCacheKey = config.rateConfig.blacklistCacheKey;
52
64
  this.blacklistCacheTTL = config.rateConfig.blacklistCacheTTLSecs;
53
65
 
66
+ this.rateTokensPubSub = new ExpKeyValuePubSub(
67
+ dexHelper,
68
+ dexKey,
69
+ 'rateTokens',
70
+ );
71
+
54
72
  this.pairsFetcher = new Fetcher<DexalotPairsResponse>(
55
73
  dexHelper.httpRequest,
56
74
  {
@@ -87,6 +105,7 @@ export class RateFetcher {
87
105
  logger,
88
106
  );
89
107
 
108
+ this.blacklistPubSub = new NonExpSetPubSub(dexHelper, dexKey, 'blacklist');
90
109
  this.blacklistFetcher = new Fetcher<DexalotBlacklistResponse>(
91
110
  dexHelper.httpRequest,
92
111
  {
@@ -104,12 +123,30 @@ export class RateFetcher {
104
123
  config.rateConfig.blacklistIntervalMs,
105
124
  logger,
106
125
  );
126
+
127
+ this.restrictedPoolPubSub = new ExpKeyValuePubSub(
128
+ dexHelper,
129
+ dexKey,
130
+ 'restricted-pool',
131
+ // using default value, we can lazy load non-restricted pools
132
+ // and restrict them by subscribing to this channel
133
+ 'false',
134
+ DEXALOT_RESTRICT_TTL_S,
135
+ );
107
136
  }
108
137
 
109
- start() {
110
- this.pairsFetcher.startPolling();
111
- this.rateFetcher.startPolling();
112
- this.blacklistFetcher.startPolling();
138
+ async start() {
139
+ if (!this.dexHelper.config.isSlave) {
140
+ this.pairsFetcher.startPolling();
141
+ this.rateFetcher.startPolling();
142
+ this.blacklistFetcher.startPolling();
143
+ } else {
144
+ this.rateTokensPubSub.subscribe();
145
+ this.restrictedPoolPubSub.subscribe();
146
+
147
+ const initSet = await this.getAllBlacklisted();
148
+ this.blacklistPubSub.initializeAndSubscribe(initSet);
149
+ }
113
150
  }
114
151
 
115
152
  stop() {
@@ -145,7 +182,7 @@ export class RateFetcher {
145
182
  this.dexKey,
146
183
  this.network,
147
184
  this.pairsCacheKey,
148
- this.pairsCacheTTL,
185
+ this.tokensCacheTTL,
149
186
  JSON.stringify(dexPairs),
150
187
  );
151
188
 
@@ -164,6 +201,15 @@ export class RateFetcher {
164
201
  this.tokensCacheTTL,
165
202
  JSON.stringify(tokenAddrMap),
166
203
  );
204
+
205
+ this.rateTokensPubSub.publish(
206
+ {
207
+ [this.pairsCacheKey]: dexPairs,
208
+ [this.tokensCacheKey]: tokenMap,
209
+ [this.tokensAddrCacheKey]: tokenAddrMap,
210
+ },
211
+ this.tokensCacheTTL,
212
+ );
167
213
  }
168
214
 
169
215
  private handleRatesResponse(resp: DexalotPricesResponse): void {
@@ -180,18 +226,182 @@ export class RateFetcher {
180
226
  this.pricesCacheTTL,
181
227
  JSON.stringify(dexPrices),
182
228
  );
229
+
230
+ this.rateTokensPubSub.publish(
231
+ { [this.pricesCacheKey]: dexPrices },
232
+ this.pricesCacheTTL,
233
+ );
183
234
  }
184
235
 
185
236
  private async handleBlacklistResponse(
186
237
  resp: DexalotBlacklistResponse,
187
238
  ): Promise<void> {
188
239
  const { blacklist } = resp;
240
+ const data = blacklist.map(item => item.toLowerCase());
189
241
  this.dexHelper.cache.setex(
190
242
  this.dexKey,
191
243
  this.network,
192
244
  this.blacklistCacheKey,
193
245
  this.blacklistCacheTTL,
194
- JSON.stringify(blacklist.map(item => item.toLowerCase())),
246
+ JSON.stringify(data),
247
+ );
248
+
249
+ this.blacklistPubSub.publish(data);
250
+ }
251
+
252
+ async getCachedTokens(): Promise<TokenDataMap | null> {
253
+ const cachedTokens = await this.rateTokensPubSub.getAndCache(
254
+ this.tokensCacheKey,
255
+ );
256
+
257
+ if (cachedTokens) {
258
+ return cachedTokens as TokenDataMap;
259
+ }
260
+
261
+ return null;
262
+ }
263
+
264
+ async getCachedPairs(): Promise<PairDataMap | null> {
265
+ const cachedPairs = await this.rateTokensPubSub.getAndCache(
266
+ this.pairsCacheKey,
267
+ );
268
+
269
+ if (cachedPairs) {
270
+ return cachedPairs as PairDataMap;
271
+ }
272
+
273
+ return null;
274
+ }
275
+
276
+ async getCachedTokensAddr(): Promise<TokenAddrDataMap | null> {
277
+ const cachedTokensAddr = await this.rateTokensPubSub.getAndCache(
278
+ this.tokensAddrCacheKey,
279
+ );
280
+
281
+ if (cachedTokensAddr) {
282
+ return cachedTokensAddr as TokenAddrDataMap;
283
+ }
284
+
285
+ return null;
286
+ }
287
+
288
+ async setBlacklist(
289
+ txOrigin: Address,
290
+ ttl: number = DEXALOT_BLACKLIST_CACHES_TTL_S,
291
+ ): Promise<boolean> {
292
+ const blacklist = await this.getAllBlacklisted();
293
+
294
+ blacklist.push(txOrigin.toLowerCase());
295
+
296
+ this.dexHelper.cache.setex(
297
+ this.dexKey,
298
+ this.network,
299
+ this.blacklistCacheKey,
300
+ ttl,
301
+ JSON.stringify(blacklist),
302
+ );
303
+
304
+ this.blacklistPubSub.publish([txOrigin.toLowerCase()]);
305
+
306
+ return true;
307
+ }
308
+
309
+ async getAllBlacklisted(): Promise<string[]> {
310
+ const cachedBlacklist = await this.dexHelper.cache.get(
311
+ this.dexKey,
312
+ this.network,
313
+ this.blacklistCacheKey,
195
314
  );
315
+
316
+ if (cachedBlacklist) {
317
+ return JSON.parse(cachedBlacklist);
318
+ }
319
+
320
+ return [];
321
+ }
322
+
323
+ async isBlacklisted(txOrigin: Address): Promise<boolean> {
324
+ const blacklisted = await this.blacklistPubSub.has(txOrigin.toLowerCase());
325
+
326
+ return blacklisted;
327
+
328
+ /*
329
+ rate-limit check was only if blacklist data set was not available,
330
+ in the current implementation it should not be the case,
331
+ so skip next check
332
+ */
333
+ // To not show pricing for rate limited users
334
+ if (await this.isRateLimited(txOrigin)) {
335
+ return true;
336
+ }
337
+
338
+ return false;
339
+ }
340
+
341
+ async setRateLimited(txOrigin: Address, ttl = DEXALOT_RATE_LIMITED_TTL_S) {
342
+ await this.dexHelper.cache.setex(
343
+ this.dexKey,
344
+ this.network,
345
+ this.getRateLimitedKey(txOrigin),
346
+ ttl,
347
+ DEXALOT_RATELIMIT_CACHE_VALUE,
348
+ );
349
+ return true;
350
+ }
351
+
352
+ async isRateLimited(txOrigin: Address): Promise<boolean> {
353
+ const result = await this.dexHelper.cache.get(
354
+ this.dexKey,
355
+ this.network,
356
+ this.getRateLimitedKey(txOrigin),
357
+ );
358
+ return result === DEXALOT_RATELIMIT_CACHE_VALUE;
359
+ }
360
+
361
+ getRateLimitedKey(address: Address) {
362
+ return `rate_limited_${address}`.toLowerCase();
363
+ }
364
+
365
+ async getCachedPrices(): Promise<PriceDataMap | null> {
366
+ const cachedPrices = await this.rateTokensPubSub.getAndCache(
367
+ this.pricesCacheKey,
368
+ );
369
+
370
+ if (cachedPrices) {
371
+ return cachedPrices as PriceDataMap;
372
+ }
373
+
374
+ return null;
375
+ }
376
+
377
+ async restrictPool(
378
+ poolIdentifier: string,
379
+ ttl: number = DEXALOT_RESTRICT_TTL_S,
380
+ ): Promise<boolean> {
381
+ await this.dexHelper.cache.setex(
382
+ this.dexKey,
383
+ this.network,
384
+ this.getRestrictedPoolKey(poolIdentifier),
385
+ ttl,
386
+ 'true',
387
+ );
388
+
389
+ await this.restrictedPoolPubSub.publish(
390
+ { [this.getRestrictedPoolKey(poolIdentifier)]: 'true' },
391
+ ttl,
392
+ );
393
+ return true;
394
+ }
395
+
396
+ async isRestrictedPool(poolIdentifier: string): Promise<boolean> {
397
+ const result = await this.restrictedPoolPubSub.getAndCache(
398
+ this.getRestrictedPoolKey(poolIdentifier),
399
+ );
400
+
401
+ return result === 'true';
402
+ }
403
+
404
+ getRestrictedPoolKey(poolIdentifier: string): string {
405
+ return `${DEXALOT_RESTRICTED_CACHE_KEY}-${poolIdentifier}`;
196
406
  }
197
407
  }
@@ -117,7 +117,6 @@ export type DexalotRateFetcherConfig = {
117
117
  tokensCacheKey: string;
118
118
  blacklistCacheKey: string;
119
119
  blacklistCacheTTLSecs: number;
120
- pairsCacheTTLSecs: number;
121
120
  pricesCacheTTLSecs: number;
122
121
  tokensCacheTTLSecs: number;
123
122
  };
@@ -0,0 +1,29 @@
1
+ /* eslint-disable no-console */
2
+ import 'dotenv/config';
3
+ import { testGasEstimation } from '../../../tests/utils-e2e';
4
+ import { Tokens } from '../../../tests/constants-e2e';
5
+ import { Network, SwapSide } from '../../constants';
6
+ import { ContractMethodV6 } from '@paraswap/core';
7
+
8
+ describe('FluidDex Gas Estimation', () => {
9
+ const dexKey = 'FluidDex';
10
+ const network = Network.MAINNET;
11
+
12
+ describe('swapExactAmountIn', () => {
13
+ const USDC = Tokens[network]['USDC'];
14
+ const USDT = Tokens[network]['USDT'];
15
+ const amount = 10000n;
16
+
17
+ it('swapIn', async () => {
18
+ await testGasEstimation(
19
+ network,
20
+ USDC,
21
+ USDT,
22
+ amount,
23
+ SwapSide.SELL,
24
+ dexKey,
25
+ ContractMethodV6.swapExactAmountIn,
26
+ );
27
+ });
28
+ });
29
+ });
@@ -0,0 +1,29 @@
1
+ /* eslint-disable no-console */
2
+ import 'dotenv/config';
3
+ import { testGasEstimation } from '../../../tests/utils-e2e';
4
+ import { Tokens } from '../../../tests/constants-e2e';
5
+ import { Network, SwapSide } from '../../constants';
6
+ import { ContractMethodV6 } from '@paraswap/core';
7
+
8
+ describe('FxProtocolRusd Gas Estimation', () => {
9
+ const dexKey = 'FxProtocolRusd';
10
+ const network = Network.MAINNET;
11
+
12
+ describe('swapExactAmountIn', () => {
13
+ const weETH = Tokens[network]['weETH'];
14
+ const rUSD = Tokens[network]['rUSD'];
15
+ const amount = 1000000000000000000n;
16
+
17
+ it('mint', async () => {
18
+ await testGasEstimation(
19
+ network,
20
+ weETH,
21
+ rUSD,
22
+ amount,
23
+ SwapSide.SELL,
24
+ dexKey,
25
+ ContractMethodV6.swapExactAmountIn,
26
+ );
27
+ });
28
+ });
29
+ });