@paraswap/dex-lib 2.18.5 → 2.18.6-swaap-v2

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 (69) hide show
  1. package/.idea/aws.xml +17 -0
  2. package/.idea/codeStyles/Project.xml +19 -0
  3. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  4. package/.idea/misc.xml +6 -0
  5. package/.idea/modules.xml +8 -0
  6. package/.idea/paraswap-dex-lib.iml +9 -0
  7. package/.idea/vcs.xml +6 -0
  8. package/build/abi/swaap-v2/vault.json +918 -0
  9. package/build/config.js +4 -2
  10. package/build/config.js.map +1 -1
  11. package/build/dex/hashflow/hashflow.js +52 -68
  12. package/build/dex/hashflow/hashflow.js.map +1 -1
  13. package/build/dex/index.js +2 -0
  14. package/build/dex/index.js.map +1 -1
  15. package/build/dex/pancakeswap-v3/types.d.ts +14 -0
  16. package/build/dex/{test-dex → pancakeswap-v3}/types.js.map +1 -1
  17. package/build/dex/{test-dex → swaap-v2}/config.d.ts +1 -1
  18. package/build/dex/swaap-v2/config.js +25 -0
  19. package/build/dex/swaap-v2/config.js.map +1 -0
  20. package/build/dex/swaap-v2/constants.d.ts +9 -0
  21. package/build/dex/swaap-v2/constants.js +13 -0
  22. package/build/dex/swaap-v2/constants.js.map +1 -0
  23. package/build/dex/swaap-v2/rate-fetcher.d.ts +16 -0
  24. package/build/dex/swaap-v2/rate-fetcher.js +100 -0
  25. package/build/dex/swaap-v2/rate-fetcher.js.map +1 -0
  26. package/build/dex/swaap-v2/swaap-v2.d.ts +55 -0
  27. package/build/dex/swaap-v2/swaap-v2.js +465 -0
  28. package/build/dex/swaap-v2/swaap-v2.js.map +1 -0
  29. package/build/dex/swaap-v2/types.d.ts +64 -0
  30. package/build/dex/swaap-v2/types.js +7 -0
  31. package/build/dex/swaap-v2/types.js.map +1 -0
  32. package/build/dex/swaap-v2/utils.d.ts +7 -0
  33. package/build/dex/swaap-v2/utils.js +34 -0
  34. package/build/dex/swaap-v2/utils.js.map +1 -0
  35. package/build/dex/swaap-v2/validators.d.ts +5 -0
  36. package/build/dex/swaap-v2/validators.js +120 -0
  37. package/build/dex/swaap-v2/validators.js.map +1 -0
  38. package/build/types.d.ts +1 -0
  39. package/package.json +1 -1
  40. package/src/abi/swaap-v2/vault.json +918 -0
  41. package/src/config.ts +5 -2
  42. package/src/dex/hashflow/hashflow.ts +85 -110
  43. package/src/dex/index.ts +2 -0
  44. package/src/dex/swaap-v2/config.ts +25 -0
  45. package/src/dex/swaap-v2/constants.ts +14 -0
  46. package/src/dex/swaap-v2/rate-fetcher.ts +164 -0
  47. package/src/dex/swaap-v2/swaap-v2-e2e.test.ts +199 -0
  48. package/src/dex/swaap-v2/swaap-v2-integration.test.ts +142 -0
  49. package/src/dex/swaap-v2/swaap-v2.ts +714 -0
  50. package/src/dex/swaap-v2/types.ts +74 -0
  51. package/src/dex/swaap-v2/utils.ts +44 -0
  52. package/src/dex/swaap-v2/validators.ts +123 -0
  53. package/src/types.ts +1 -0
  54. package/tests/constants-e2e.ts +1 -1
  55. package/tests/utils-e2e.ts +5 -0
  56. package/build/abi/DirectSwap.json +0 -1018
  57. package/build/dex/test-dex/config.js +0 -15
  58. package/build/dex/test-dex/config.js.map +0 -1
  59. package/build/dex/test-dex/test-dex-pool.d.ts +0 -39
  60. package/build/dex/test-dex/test-dex-pool.js +0 -63
  61. package/build/dex/test-dex/test-dex-pool.js.map +0 -1
  62. package/build/dex/test-dex/test-dex.d.ts +0 -37
  63. package/build/dex/test-dex/test-dex.js +0 -126
  64. package/build/dex/test-dex/test-dex.js.map +0 -1
  65. package/build/dex/test-dex/types.d.ts +0 -6
  66. package/build/dex/woo-fi-v2/woo-fi-math.d.ts +0 -16
  67. package/build/dex/woo-fi-v2/woo-fi-math.js +0 -137
  68. package/build/dex/woo-fi-v2/woo-fi-math.js.map +0 -1
  69. /package/build/dex/{test-dex → pancakeswap-v3}/types.js +0 -0
package/src/config.ts CHANGED
@@ -29,6 +29,7 @@ type BaseConfig = {
29
29
  rpcPollingBlocksBackToTriggerUpdate: number;
30
30
  hashFlowAuthToken?: string;
31
31
  hashFlowDisabledMMs: string[];
32
+ swaapV2AuthToken?: string;
32
33
  };
33
34
 
34
35
  const baseConfigs: { [network: number]: BaseConfig } = {
@@ -185,8 +186,8 @@ const baseConfigs: { [network: number]: BaseConfig } = {
185
186
  process.env[`HASHFLOW_DISABLED_MMS_137`]?.split(',') || [],
186
187
  adapterAddresses: {
187
188
  PolygonAdapter01: '0xE44769f42E1e9592f86B82f206407a8f7C84b4ed',
188
- PolygonAdapter02: '0xfb2a3de6c7B8c77b520E3da16021f3D8A4E93168',
189
- PolygonBuyAdapter: '0xb2634B3CBc1E401AB3C2743DB44d459C5c9aA662',
189
+ PolygonAdapter02: '0xa05d8C3F278fC7b20b39Ea7A3035E3aD8D808c78',
190
+ PolygonBuyAdapter: '0xB11bCA7B01b425afD0743A4D77B4f593883f94C0',
190
191
  },
191
192
  uniswapV2ExchangeRouterAddress:
192
193
  '0xf3938337F7294fEf84e9B2c6D548A93F956Cc281',
@@ -194,6 +195,7 @@ const baseConfigs: { [network: number]: BaseConfig } = {
194
195
  rfqConfigs: {},
195
196
  rpcPollingMaxAllowedStateDelayInBlocks: 2,
196
197
  rpcPollingBlocksBackToTriggerUpdate: 1,
198
+ swaapV2AuthToken: process.env.API_KEY_SWAAP_V2_AUTH_TOKEN || '',
197
199
  },
198
200
  [Network.AVALANCHE]: {
199
201
  network: Network.AVALANCHE,
@@ -345,6 +347,7 @@ export function generateConfig(network: number): Config {
345
347
  rpcPollingBlocksBackToTriggerUpdate:
346
348
  baseConfig.rpcPollingBlocksBackToTriggerUpdate,
347
349
  hashFlowAuthToken: baseConfig.hashFlowAuthToken,
350
+ swaapV2AuthToken: baseConfig.swaapV2AuthToken,
348
351
  hashFlowDisabledMMs: baseConfig.hashFlowDisabledMMs,
349
352
  };
350
353
  }
@@ -279,14 +279,15 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
279
279
  destToken: Token,
280
280
  side: SwapSide,
281
281
  ): bigint[] {
282
- assert(levels.length > 0, 'Levels should not be empty');
282
+ if (levels.length > 0) {
283
+ const firstLevel = levels[0];
284
+ if (new BigNumber(firstLevel.level).gt(0)) {
285
+ // Add zero level for price computation
286
+ levels.unshift({ level: '0', price: firstLevel.price });
287
+ }
288
+ }
283
289
 
284
290
  const outputs = new Array<BigNumber>(amounts.length).fill(BN_0);
285
- // FIXME: There is still case when last amount is fillable, but in between
286
- // we may have splits that are less than min. amount. I assume that case is very
287
- // and not addressing in current fix. If someone will look into that case, just be aware
288
- // that it is not addressed
289
-
290
291
  for (const [i, amount] of amounts.entries()) {
291
292
  if (amount.isZero()) {
292
293
  outputs[i] = BN_0;
@@ -418,124 +419,98 @@ export class Hashflow extends SimpleExchange implements IDex<HashflowData> {
418
419
  blockNumber: number,
419
420
  limitPools?: string[],
420
421
  ): Promise<null | ExchangePrices<HashflowData>> {
421
- try {
422
- const normalizedSrcToken = this.normalizeToken(srcToken);
423
- const normalizedDestToken = this.normalizeToken(destToken);
424
-
425
- if (normalizedSrcToken.address === normalizedDestToken.address) {
426
- return null;
427
- }
428
-
429
- const prefix = this.getIdentifierPrefix(
430
- normalizedSrcToken.address,
431
- normalizedDestToken.address,
432
- );
433
-
434
- const pools =
435
- limitPools ??
436
- (await this.getPoolIdentifiers(srcToken, destToken, side, blockNumber));
437
-
438
- const marketMakersToUse = pools.map(p => p.split(`${prefix}_`).pop());
422
+ const normalizedSrcToken = this.normalizeToken(srcToken);
423
+ const normalizedDestToken = this.normalizeToken(destToken);
439
424
 
440
- const levelsMap = (await this.getCachedLevels()) || {};
425
+ if (normalizedSrcToken.address === normalizedDestToken.address) {
426
+ return null;
427
+ }
441
428
 
442
- Object.keys(levelsMap).forEach(mmKey => {
443
- if (!marketMakersToUse.includes(mmKey)) {
444
- delete levelsMap[mmKey];
445
- }
446
- });
429
+ const prefix = this.getIdentifierPrefix(
430
+ normalizedSrcToken.address,
431
+ normalizedDestToken.address,
432
+ );
447
433
 
448
- const levelEntries: {
449
- mm: string;
450
- levels: PriceLevel[];
451
- }[] = Object.keys(levelsMap)
452
- .map(mm => {
453
- const entry = levelsMap[mm]?.find(
454
- e =>
455
- `${e.pair.baseToken}_${e.pair.quoteToken}` ===
456
- this.getPairName(
457
- normalizedSrcToken.address,
458
- normalizedDestToken.address,
459
- ),
460
- );
461
- if (entry === undefined) {
462
- return undefined;
463
- } else {
464
- return { mm, levels: entry.levels };
465
- }
466
- })
467
- .filter(o => o !== undefined)
468
- .map(o => o!);
434
+ const pools =
435
+ limitPools ??
436
+ (await this.getPoolIdentifiers(srcToken, destToken, side, blockNumber));
469
437
 
470
- const prices = levelEntries.map(lEntry => {
471
- const { mm, levels } = lEntry;
438
+ const marketMakersToUse = pools.map(p => p.split(`${prefix}_`).pop());
472
439
 
473
- if (levels.length === 0) {
474
- return null;
475
- }
440
+ const levelsMap = (await this.getCachedLevels()) || {};
476
441
 
477
- const divider = getBigNumberPow(
478
- side === SwapSide.SELL
479
- ? normalizedSrcToken.decimals
480
- : normalizedDestToken.decimals,
481
- );
442
+ Object.keys(levelsMap).forEach(mmKey => {
443
+ if (!marketMakersToUse.includes(mmKey)) {
444
+ delete levelsMap[mmKey];
445
+ }
446
+ });
482
447
 
483
- const amountsRaw = amounts.map(a =>
484
- new BigNumber(a.toString()).dividedBy(divider),
448
+ const levelEntries: {
449
+ mm: string;
450
+ levels: PriceLevel[];
451
+ }[] = Object.keys(levelsMap)
452
+ .map(mm => {
453
+ const entry = levelsMap[mm]?.find(
454
+ e =>
455
+ `${e.pair.baseToken}_${e.pair.quoteToken}` ===
456
+ this.getPairName(
457
+ normalizedSrcToken.address,
458
+ normalizedDestToken.address,
459
+ ),
485
460
  );
486
- const firstLevelRaw = levels[0];
487
- const firstLevelAmountBN = new BigNumber(firstLevelRaw.level);
488
-
489
- if (amountsRaw[amountsRaw.length - 1].lt(firstLevelAmountBN)) {
490
- return null;
461
+ if (entry === undefined) {
462
+ return undefined;
463
+ } else {
464
+ return { mm, levels: entry.levels };
491
465
  }
466
+ })
467
+ .filter(o => o !== undefined)
468
+ .map(o => o!);
492
469
 
493
- if (firstLevelAmountBN.gt(0)) {
494
- // Add zero level for price computation
495
- levels.unshift({ level: '0', price: firstLevelRaw.price });
496
- }
470
+ const prices = levelEntries.map(lEntry => {
471
+ const { mm, levels } = lEntry;
497
472
 
498
- const unitPrice = this.computePricesFromLevels(
499
- [BN_1],
500
- levels,
501
- normalizedSrcToken,
502
- normalizedDestToken,
503
- side,
504
- )[0];
505
-
506
- const prices = this.computePricesFromLevels(
507
- amountsRaw,
508
- levels,
509
- normalizedSrcToken,
510
- normalizedDestToken,
511
- side,
512
- );
473
+ const divider = getBigNumberPow(
474
+ side === SwapSide.SELL
475
+ ? normalizedSrcToken.decimals
476
+ : normalizedDestToken.decimals,
477
+ );
513
478
 
514
- return {
515
- gasCost: 100_000,
516
- exchange: this.dexKey,
517
- data: { mm },
518
- prices,
519
- unit: unitPrice,
520
- poolIdentifier: this.getPoolIdentifier(
521
- normalizedSrcToken.address,
522
- normalizedDestToken.address,
523
- mm,
524
- ),
525
- poolAddresses: [this.routerAddress],
526
- } as PoolPrices<HashflowData>;
527
- });
479
+ const amountsRaw = amounts.map(a =>
480
+ new BigNumber(a.toString()).dividedBy(divider),
481
+ );
528
482
 
529
- return prices.filter((p): p is PoolPrices<HashflowData> => !!p);
530
- } catch (e: unknown) {
531
- this.logger.error(
532
- `Error_getPricesVolume ${srcToken.symbol || srcToken.address}, ${
533
- destToken.symbol || destToken.address
534
- }, ${side}:`,
535
- e,
483
+ const unitPrice = this.computePricesFromLevels(
484
+ [BN_1],
485
+ levels,
486
+ normalizedSrcToken,
487
+ normalizedDestToken,
488
+ side,
489
+ )[0];
490
+ const prices = this.computePricesFromLevels(
491
+ amountsRaw,
492
+ levels,
493
+ normalizedSrcToken,
494
+ normalizedDestToken,
495
+ side,
536
496
  );
537
- return null;
538
- }
497
+
498
+ return {
499
+ gasCost: 100_000,
500
+ exchange: this.dexKey,
501
+ data: { mm },
502
+ prices,
503
+ unit: unitPrice,
504
+ poolIdentifier: this.getPoolIdentifier(
505
+ normalizedSrcToken.address,
506
+ normalizedDestToken.address,
507
+ mm,
508
+ ),
509
+ poolAddresses: [this.routerAddress],
510
+ } as PoolPrices<HashflowData>;
511
+ });
512
+
513
+ return prices;
539
514
  }
540
515
 
541
516
  async preProcessTransaction(
package/src/dex/index.ts CHANGED
@@ -63,6 +63,7 @@ import { MaverickV1 } from './maverick-v1/maverick-v1';
63
63
  import { QuickSwapV3 } from './quickswap/quickswap-v3';
64
64
  import { ZyberSwapV3 } from './quickswap/zyberswap-v3';
65
65
  import { TraderJoeV2 } from './trader-joe-v2';
66
+ import { SwaapV2 } from './swaap-v2/swaap-v2';
66
67
  import { SpiritSwapV3 } from './quickswap/spiritswap-v3';
67
68
  import { TraderJoeV21 } from './trader-joe-v2.1';
68
69
  import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3';
@@ -129,6 +130,7 @@ const Dexes = [
129
130
  Hashflow,
130
131
  MaverickV1,
131
132
  Camelot,
133
+ SwaapV2,
132
134
  ];
133
135
 
134
136
  export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder<
@@ -0,0 +1,25 @@
1
+ import { DexParams } from './types';
2
+ import { DexConfigMap, AdapterMappings } from '../../types';
3
+ import { Network, SwapSide } from '../../constants';
4
+
5
+ export const SwaapV2Config: DexConfigMap<DexParams> = {
6
+ SwaapV2: {
7
+ // Mainnet and Arbitrum will be supported later
8
+ // [Network.MAINNET]: {
9
+ // routerAddress: '0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa',
10
+ // },
11
+ // [Network.ARBITRUM]: {
12
+ // routerAddress: '0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa',
13
+ // },
14
+ [Network.POLYGON]: {
15
+ routerAddress: '0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa',
16
+ },
17
+ },
18
+ };
19
+
20
+ export const Adapters: Record<number, AdapterMappings> = {
21
+ [Network.POLYGON]: {
22
+ [SwapSide.SELL]: [{ name: 'PolygonAdapter02', index: 8 }],
23
+ [SwapSide.BUY]: [{ name: 'PolygonBuyAdapter', index: 7 }],
24
+ },
25
+ };
@@ -0,0 +1,14 @@
1
+ export const SWAAP_RFQ_PRICES_CACHES_TTL_S = 3;
2
+ export const SWAAP_RFQ_QUOTE_TIMEOUT_MS = 2000;
3
+
4
+ export const SWAAP_RFQ_API_PRICES_POLLING_INTERVAL_MS = 1000;
5
+
6
+ export const SWAAP_RFQ_API_URL = 'https://api.swaap.finance/v1/rfq';
7
+ export const SWAAP_RFQ_PRICES_ENDPOINT = 'prices';
8
+ export const SWAAP_RFQ_QUOTE_ENDPOINT = 'quote';
9
+
10
+ export const GAS_COST_ESTIMATION = 142_000;
11
+
12
+ export const BATCH_SWAP_SELECTOR = '0x945bcec9';
13
+
14
+ export const CALLER_SLOT = 160;
@@ -0,0 +1,164 @@
1
+ import { IDexHelper } from '../../dex-helper';
2
+ import { Fetcher } from '../../lib/fetcher/fetcher';
3
+ import { validateAndCast } from '../../lib/validators';
4
+ import { Logger, Token, Address } from '../../types';
5
+ import {
6
+ SwaapV2RateFetcherConfig,
7
+ SwaapV2PriceLevelsResponse,
8
+ SwaapV2QuoteResponse,
9
+ SwaapV2PriceLevels,
10
+ SwaapV2QuoteRequest,
11
+ SwaapV2OrderType,
12
+ } from './types';
13
+ import {
14
+ priceLevelsResponseValidator,
15
+ getQuoteResponseValidator,
16
+ } from './validators';
17
+ import { getPriceLevelsCacheKey, normalizeTokenAddress } from './utils';
18
+ import { SWAAP_RFQ_QUOTE_TIMEOUT_MS } from './constants';
19
+ import BigNumber from 'bignumber.js';
20
+ import { RequestConfig } from '../../dex-helper/irequest-wrapper';
21
+
22
+ export class RateFetcher {
23
+ private rateFetcher: Fetcher<SwaapV2PriceLevelsResponse>;
24
+ private pricesCacheTTL: number;
25
+
26
+ constructor(
27
+ private dexHelper: IDexHelper,
28
+ private dexKey: string,
29
+ private logger: Logger,
30
+ config: SwaapV2RateFetcherConfig,
31
+ ) {
32
+ this.pricesCacheTTL = config.rateConfig.pricesCacheTTLSecs;
33
+
34
+ this.rateFetcher = new Fetcher<SwaapV2PriceLevelsResponse>(
35
+ dexHelper.httpRequest,
36
+ {
37
+ info: {
38
+ requestOptions: config.rateConfig.pricesReqParams,
39
+ caster: (data: unknown) => {
40
+ return validateAndCast<SwaapV2PriceLevelsResponse>(
41
+ data,
42
+ priceLevelsResponseValidator,
43
+ );
44
+ },
45
+ },
46
+ handler: this.handleRatesResponse.bind(this),
47
+ },
48
+ config.rateConfig.pricesIntervalMs,
49
+ logger,
50
+ );
51
+ }
52
+
53
+ start() {
54
+ this.rateFetcher.startPolling();
55
+ }
56
+
57
+ stop() {
58
+ this.rateFetcher.stopPolling();
59
+ }
60
+
61
+ private handleRatesResponse(resp: SwaapV2PriceLevelsResponse): void {
62
+ if (resp.success) {
63
+ const levels = Object.keys(resp.levels)
64
+ .map(pairName => {
65
+ const pair = resp.levels[pairName];
66
+ if (!pair) {
67
+ return;
68
+ }
69
+ const levels = resp.levels[pairName];
70
+
71
+ if (!levels.asks || !levels.bids) {
72
+ return;
73
+ }
74
+
75
+ const pairSplit = pairName.split('/');
76
+
77
+ const baseAddress = pairSplit[0];
78
+ const quoteAddress = pairSplit[1];
79
+ pair.base = normalizeTokenAddress(baseAddress);
80
+ pair.quote = normalizeTokenAddress(quoteAddress);
81
+ return pair;
82
+ })
83
+ .filter((p: SwaapV2PriceLevels | undefined) => p != null);
84
+
85
+ this.dexHelper.cache.setex(
86
+ this.dexKey,
87
+ this.dexHelper.config.data.network,
88
+ `${getPriceLevelsCacheKey(this.dexKey)}`,
89
+ this.pricesCacheTTL,
90
+ JSON.stringify(levels),
91
+ );
92
+ }
93
+ }
94
+
95
+ async getQuote(
96
+ networkId: number,
97
+ _srcToken: Token,
98
+ _destToken: Token,
99
+ srcAmount: string,
100
+ side: SwaapV2OrderType,
101
+ userAddress: Address,
102
+ aggregatorRecipient: Address,
103
+ tolerance: number,
104
+ requestParameters: RequestConfig,
105
+ ): Promise<SwaapV2QuoteResponse> {
106
+ const srcToken = this.dexHelper.config.wrapETH(_srcToken);
107
+ const destToken = this.dexHelper.config.wrapETH(_destToken);
108
+
109
+ if (BigInt(srcAmount) === 0n) {
110
+ throw new Error('geQuote failed with srcAmount == 0');
111
+ }
112
+
113
+ const _payload: SwaapV2QuoteRequest = {
114
+ network_id: networkId,
115
+ origin: userAddress,
116
+ sender: aggregatorRecipient,
117
+ recipient: aggregatorRecipient,
118
+ timestamp: Math.round(Date.now() / 1000),
119
+ order_type: side,
120
+ token_in: srcToken.address,
121
+ token_out: destToken.address,
122
+ amount: srcAmount,
123
+ tolerance: tolerance,
124
+ };
125
+
126
+ try {
127
+ let payload: RequestConfig = {
128
+ data: _payload,
129
+ ...requestParameters,
130
+ timeout: SWAAP_RFQ_QUOTE_TIMEOUT_MS,
131
+ };
132
+
133
+ this.logger.info(
134
+ 'GetQuote Request:',
135
+ JSON.stringify(payload).replace(/(?:\r\n|\r|\n)/g, ' '),
136
+ );
137
+ const { data } = await this.dexHelper.httpRequest.request<unknown>(
138
+ payload,
139
+ );
140
+ this.logger.info(
141
+ 'GetQuote Response: ',
142
+ JSON.stringify(data).replace(/(?:\r\n|\r|\n)/g, ' '),
143
+ );
144
+ const quoteResp = validateAndCast<SwaapV2QuoteResponse>(
145
+ data,
146
+ getQuoteResponseValidator,
147
+ );
148
+
149
+ return {
150
+ id: quoteResp.id,
151
+ calldata: quoteResp.calldata,
152
+ router: quoteResp.router,
153
+ expiration: quoteResp.expiration,
154
+ amount: quoteResp.amount,
155
+ guaranteed_price: quoteResp.guaranteed_price,
156
+ success: quoteResp.success,
157
+ recipient: quoteResp.recipient,
158
+ };
159
+ } catch (e) {
160
+ this.logger.error(e);
161
+ throw e;
162
+ }
163
+ }
164
+ }
@@ -0,0 +1,199 @@
1
+ import dotenv from 'dotenv';
2
+ dotenv.config();
3
+
4
+ import { testE2E } from '../../../tests/utils-e2e';
5
+ import {
6
+ Tokens,
7
+ Holders,
8
+ NativeTokenSymbols,
9
+ } from '../../../tests/constants-e2e';
10
+ import { Network, ContractMethod, SwapSide } from '../../constants';
11
+ import { StaticJsonRpcProvider } from '@ethersproject/providers';
12
+ import { generateConfig } from '../../config';
13
+
14
+ const sleepMs: number = 5000;
15
+
16
+ function testForNetwork(
17
+ network: Network,
18
+ dexKey: string,
19
+ tokenASymbol: string,
20
+ tokenBSymbol: string,
21
+ tokenAAmount: string,
22
+ tokenBAmount: string,
23
+ nativeTokenAmount: string,
24
+ excludeNativeTokenTests: boolean = true,
25
+ ) {
26
+ const provider = new StaticJsonRpcProvider(
27
+ generateConfig(network).privateHttpProvider,
28
+ network,
29
+ );
30
+ const tokens = Tokens[network];
31
+ const holders = Holders[network];
32
+ const nativeTokenSymbol = NativeTokenSymbols[network];
33
+
34
+ const sideToContractMethods = new Map([
35
+ [
36
+ SwapSide.SELL,
37
+ [
38
+ ContractMethod.simpleSwap,
39
+ ContractMethod.multiSwap,
40
+ ContractMethod.megaSwap,
41
+ ],
42
+ ],
43
+ [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]],
44
+ ]);
45
+
46
+ describe(`${network}`, () => {
47
+ sideToContractMethods.forEach((contractMethods, side) =>
48
+ describe(`${side}`, () => {
49
+ contractMethods.forEach((contractMethod: ContractMethod) => {
50
+ describe(`${contractMethod}`, () => {
51
+ if (excludeNativeTokenTests) {
52
+ it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => {
53
+ await testE2E(
54
+ tokens[tokenASymbol],
55
+ tokens[tokenBSymbol],
56
+ holders[tokenASymbol],
57
+ side === SwapSide.SELL ? tokenAAmount : tokenBAmount,
58
+ side,
59
+ dexKey,
60
+ contractMethod,
61
+ network,
62
+ provider,
63
+ undefined,
64
+ undefined,
65
+ undefined,
66
+ undefined,
67
+ sleepMs,
68
+ );
69
+ });
70
+ it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => {
71
+ await testE2E(
72
+ tokens[tokenBSymbol],
73
+ tokens[tokenASymbol],
74
+ holders[tokenBSymbol],
75
+ side === SwapSide.SELL ? tokenBAmount : tokenAAmount,
76
+ side,
77
+ dexKey,
78
+ contractMethod,
79
+ network,
80
+ provider,
81
+ undefined,
82
+ undefined,
83
+ undefined,
84
+ undefined,
85
+ sleepMs,
86
+ );
87
+ });
88
+ } else {
89
+ it(`${nativeTokenSymbol} -> ${tokenASymbol}`, async () => {
90
+ await testE2E(
91
+ tokens[nativeTokenSymbol],
92
+ tokens[tokenASymbol],
93
+ holders[nativeTokenSymbol],
94
+ side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount,
95
+ side,
96
+ dexKey,
97
+ contractMethod,
98
+ network,
99
+ provider,
100
+ undefined,
101
+ undefined,
102
+ undefined,
103
+ undefined,
104
+ sleepMs,
105
+ );
106
+ });
107
+ it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => {
108
+ await testE2E(
109
+ tokens[tokenASymbol],
110
+ tokens[nativeTokenSymbol],
111
+ holders[tokenASymbol],
112
+ side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount,
113
+ side,
114
+ dexKey,
115
+ contractMethod,
116
+ network,
117
+ provider,
118
+ undefined,
119
+ undefined,
120
+ undefined,
121
+ undefined,
122
+ sleepMs,
123
+ );
124
+ });
125
+ }
126
+ });
127
+ });
128
+ }),
129
+ );
130
+ });
131
+ }
132
+
133
+ describe('SwaapV2 E2E', () => {
134
+ const dexKey = 'SwaapV2';
135
+
136
+ describe('Polygon', () => {
137
+ const network = Network.POLYGON;
138
+
139
+ const tokenASymbol: string = 'USDC';
140
+ const tokenBSymbol: string = 'WETH';
141
+
142
+ const tokenAAmount: string = '100000000';
143
+ const tokenBAmount: string = '10000000000000000';
144
+ const nativeTokenAmount = '1000000000000000000';
145
+
146
+ testForNetwork(
147
+ network,
148
+ dexKey,
149
+ tokenASymbol,
150
+ tokenBSymbol,
151
+ tokenAAmount,
152
+ tokenBAmount,
153
+ nativeTokenAmount,
154
+ );
155
+ });
156
+
157
+ // Arbitrum will be supported later
158
+ // describe('Arbitrum', () => {
159
+ // const network = Network.ARBITRUM;
160
+ //
161
+ // const tokenASymbol: string = 'ETH';
162
+ // const tokenBSymbol: string = 'DAI';
163
+ //
164
+ // const tokenAAmount: string = '100000000';
165
+ // const tokenBAmount: string = '1000000000000000000';
166
+ // const nativeTokenAmount = '1000000000000000000';
167
+ //
168
+ // testForNetwork(
169
+ // network,
170
+ // dexKey,
171
+ // tokenASymbol,
172
+ // tokenBSymbol,
173
+ // tokenAAmount,
174
+ // tokenBAmount,
175
+ // nativeTokenAmount,
176
+ // );
177
+ // });
178
+
179
+ // Mainnet will be supported later
180
+ // describe('Mainnet', () => {
181
+ // const network = Network.MAINNET;
182
+ // const tokenASymbol: string = 'USDC';
183
+ // const tokenBSymbol: string = 'USDT';
184
+ //
185
+ // const tokenAAmount: string = '100000000';
186
+ // const tokenBAmount: string = '1000000000000000000';
187
+ // const nativeTokenAmount = '1000000000000000000';
188
+ //
189
+ // testForNetwork(
190
+ // network,
191
+ // dexKey,
192
+ // tokenASymbol,
193
+ // tokenBSymbol,
194
+ // tokenAAmount,
195
+ // tokenBAmount,
196
+ // nativeTokenAmount,
197
+ // );
198
+ // });
199
+ });