@paraswap/dex-lib 2.19.1 → 2.20.0

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 (131) hide show
  1. package/build/abi/DirectSwap.json +1018 -0
  2. package/build/dex/balancer-v2/balancer-v2.d.ts +9 -3
  3. package/build/dex/balancer-v2/balancer-v2.js +83 -0
  4. package/build/dex/balancer-v2/balancer-v2.js.map +1 -1
  5. package/build/dex/balancer-v2/constants.d.ts +4 -0
  6. package/build/dex/balancer-v2/constants.js +6 -1
  7. package/build/dex/balancer-v2/constants.js.map +1 -1
  8. package/build/dex/balancer-v2/types.d.ts +20 -1
  9. package/build/dex/balancer-v2/types.js.map +1 -1
  10. package/build/dex/curve-v1/constants.d.ts +1 -0
  11. package/build/dex/curve-v1/constants.js +2 -1
  12. package/build/dex/curve-v1/constants.js.map +1 -1
  13. package/build/dex/curve-v1/curve-v1.d.ts +9 -3
  14. package/build/dex/curve-v1/curve-v1.js +92 -4
  15. package/build/dex/curve-v1/curve-v1.js.map +1 -1
  16. package/build/dex/curve-v1/types.d.ts +24 -0
  17. package/build/dex/curve-v1/types.js +6 -1
  18. package/build/dex/curve-v1/types.js.map +1 -1
  19. package/build/dex/curve-v1-factory/constants.d.ts +1 -0
  20. package/build/dex/curve-v1-factory/constants.js +2 -1
  21. package/build/dex/curve-v1-factory/constants.js.map +1 -1
  22. package/build/dex/curve-v1-factory/curve-v1-factory.d.ts +11 -4
  23. package/build/dex/curve-v1-factory/curve-v1-factory.js +87 -0
  24. package/build/dex/curve-v1-factory/curve-v1-factory.js.map +1 -1
  25. package/build/dex/curve-v1-factory/types.d.ts +24 -0
  26. package/build/dex/curve-v1-factory/types.js +6 -1
  27. package/build/dex/curve-v1-factory/types.js.map +1 -1
  28. package/build/dex/curve-v2.d.ts +29 -7
  29. package/build/dex/curve-v2.js +91 -1
  30. package/build/dex/curve-v2.js.map +1 -1
  31. package/build/dex/idex.d.ts +1 -1
  32. package/build/dex/pancakeswap-v3/pancakeswap-v3.d.ts +2 -2
  33. package/build/dex/pancakeswap-v3/utils.js.map +1 -1
  34. package/build/dex/simple-exchange.d.ts +2 -0
  35. package/build/dex/simple-exchange.js +1 -0
  36. package/build/dex/simple-exchange.js.map +1 -1
  37. package/build/dex/swaap-v2/swaap-v2.js +5 -1
  38. package/build/dex/swaap-v2/swaap-v2.js.map +1 -1
  39. package/build/dex/swaap-v2/utils.js.map +1 -1
  40. package/build/dex/swaap-v2/validators.js +1 -2
  41. package/build/dex/swaap-v2/validators.js.map +1 -1
  42. package/build/dex/test-dex/config.d.ts +4 -0
  43. package/build/dex/test-dex/config.js +15 -0
  44. package/build/dex/test-dex/config.js.map +1 -0
  45. package/build/dex/test-dex/test-dex-pool.d.ts +39 -0
  46. package/build/dex/test-dex/test-dex-pool.js +63 -0
  47. package/build/dex/test-dex/test-dex-pool.js.map +1 -0
  48. package/build/dex/test-dex/test-dex.d.ts +37 -0
  49. package/build/dex/test-dex/test-dex.js +126 -0
  50. package/build/dex/test-dex/test-dex.js.map +1 -0
  51. package/build/dex/test-dex/types.d.ts +6 -0
  52. package/build/dex/{pancakeswap-v3 → test-dex}/types.js.map +1 -1
  53. package/build/dex/uniswap-v2/uniswap-v2.d.ts +1 -1
  54. package/build/dex/uniswap-v2/uniswap-v2.js +1 -1
  55. package/build/dex/uniswap-v2/uniswap-v2.js.map +1 -1
  56. package/build/dex/uniswap-v3/constants.d.ts +4 -0
  57. package/build/dex/uniswap-v3/constants.js +6 -1
  58. package/build/dex/uniswap-v3/constants.js.map +1 -1
  59. package/build/dex/uniswap-v3/types.d.ts +20 -3
  60. package/build/dex/uniswap-v3/types.js.map +1 -1
  61. package/build/dex/uniswap-v3/uniswap-v3.d.ts +7 -1
  62. package/build/dex/uniswap-v3/uniswap-v3.js +85 -1
  63. package/build/dex/uniswap-v3/uniswap-v3.js.map +1 -1
  64. package/build/dex/woo-fi-v2/woo-fi-math.d.ts +16 -0
  65. package/build/dex/woo-fi-v2/woo-fi-math.js +137 -0
  66. package/build/dex/woo-fi-v2/woo-fi-math.js.map +1 -0
  67. package/build/dex/zerox/index.d.ts +1 -1
  68. package/build/dex/zerox/index.js +1 -1
  69. package/build/dex/zerox/index.js.map +1 -1
  70. package/build/implementations/local-paraswap-sdk.js +5 -1
  71. package/build/implementations/local-paraswap-sdk.js.map +1 -1
  72. package/build/router/directswap.js +7 -1
  73. package/build/router/directswap.js.map +1 -1
  74. package/build/router/index.js.map +1 -1
  75. package/build/router/payload-encoder.js +14 -3
  76. package/build/router/payload-encoder.js.map +1 -1
  77. package/build/types.d.ts +1 -0
  78. package/build/utils.js.map +1 -1
  79. package/package.json +5 -3
  80. package/src/abi/DirectSwap.json +1018 -0
  81. package/src/dex/balancer-v2/balancer-v2-e2e.test.ts +79 -0
  82. package/src/dex/balancer-v2/balancer-v2.ts +153 -4
  83. package/src/dex/balancer-v2/constants.ts +5 -0
  84. package/src/dex/balancer-v2/types.ts +21 -1
  85. package/src/dex/curve-v1/constants.ts +2 -0
  86. package/src/dex/curve-v1/curve-v1-e2e.test.ts +57 -0
  87. package/src/dex/curve-v1/curve-v1.ts +144 -5
  88. package/src/dex/curve-v1/types.ts +26 -0
  89. package/src/dex/curve-v1-factory/constants.ts +2 -0
  90. package/src/dex/curve-v1-factory/curve-v1-factory-e2e.test.ts +1 -0
  91. package/src/dex/curve-v1-factory/curve-v1-factory.ts +140 -4
  92. package/src/dex/curve-v1-factory/types.ts +26 -0
  93. package/src/dex/curve-v2.ts +169 -8
  94. package/src/dex/idex.ts +6 -0
  95. package/src/dex/pancakeswap-v3/pancakeswap-v3-e2e.test.ts +3 -6
  96. package/src/dex/pancakeswap-v3/pancakeswap-v3-integration.test.ts +3 -14
  97. package/src/dex/pancakeswap-v3/pancakeswap-v3.ts +3 -3
  98. package/src/dex/pancakeswap-v3/utils.ts +1 -4
  99. package/src/dex/simple-exchange.ts +6 -0
  100. package/src/dex/solidly/solidly-e2e.test.ts +31 -32
  101. package/src/dex/swaap-v2/swaap-v2.ts +19 -11
  102. package/src/dex/swaap-v2/types.ts +4 -4
  103. package/src/dex/swaap-v2/utils.ts +4 -4
  104. package/src/dex/swaap-v2/validators.ts +4 -7
  105. package/src/dex/uniswap-v2/uniswap-v2.ts +6 -0
  106. package/src/dex/uniswap-v3/constants.ts +5 -0
  107. package/src/dex/uniswap-v3/types.ts +23 -3
  108. package/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +100 -2
  109. package/src/dex/uniswap-v3/uniswap-v3.ts +138 -3
  110. package/src/dex/zerox/index.ts +7 -0
  111. package/src/implementations/local-paraswap-sdk.ts +8 -1
  112. package/src/router/directswap.ts +23 -0
  113. package/src/router/index.ts +0 -2
  114. package/src/router/payload-encoder.ts +19 -3
  115. package/src/types.ts +1 -0
  116. package/src/utils.ts +1 -1
  117. package/tests/constants-e2e.ts +3 -3
  118. package/tests/utils-e2e.ts +136 -21
  119. package/tests/utils.ts +52 -0
  120. package/.idea/aws.xml +0 -17
  121. package/.idea/codeStyles/Project.xml +0 -19
  122. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  123. package/.idea/misc.xml +0 -6
  124. package/.idea/modules.xml +0 -8
  125. package/.idea/paraswap-dex-lib.iml +0 -9
  126. package/.idea/vcs.xml +0 -6
  127. package/build/dex/pancakeswap-v3/types.d.ts +0 -14
  128. package/build/dex/solidly/forks-override/chronos.d.ts +0 -20
  129. package/build/dex/solidly/forks-override/chronos.js +0 -44
  130. package/build/dex/solidly/forks-override/chronos.js.map +0 -1
  131. /package/build/dex/{pancakeswap-v3 → test-dex}/types.js +0 -0
@@ -905,39 +905,38 @@ describe('Solidly E2E', () => {
905
905
  ],
906
906
  ]);
907
907
 
908
- const pairs: { name: string; sellAmount: string; }[][] =
908
+ const pairs: { name: string; sellAmount: string }[][] = [
909
909
  [
910
- [
911
- {
912
- name: 'BNB',
913
- sellAmount: '1000000000000000000',
914
- },
915
- {
916
- name: 'USDT',
917
- sellAmount: '10000000000000000000',
918
- },
919
- ],
920
- [
921
- {
922
- name: 'USDT',
923
- sellAmount: '10000000000000000000',
924
- },
925
- {
926
- name: 'USDC',
927
- sellAmount: '10000000000000000000',
928
- },
929
- ],
930
- [
931
- {
932
- name: 'ETH',
933
- sellAmount: '5000000000000000000',
934
- },
935
- {
936
- name: 'BNB',
937
- sellAmount: '1000000000000000000',
938
- },
939
- ]
940
- ];
910
+ {
911
+ name: 'BNB',
912
+ sellAmount: '1000000000000000000',
913
+ },
914
+ {
915
+ name: 'USDT',
916
+ sellAmount: '10000000000000000000',
917
+ },
918
+ ],
919
+ [
920
+ {
921
+ name: 'USDT',
922
+ sellAmount: '10000000000000000000',
923
+ },
924
+ {
925
+ name: 'USDC',
926
+ sellAmount: '10000000000000000000',
927
+ },
928
+ ],
929
+ [
930
+ {
931
+ name: 'ETH',
932
+ sellAmount: '5000000000000000000',
933
+ },
934
+ {
935
+ name: 'BNB',
936
+ sellAmount: '1000000000000000000',
937
+ },
938
+ ],
939
+ ];
941
940
 
942
941
  sideToContractMethods.forEach((contractMethods, side) =>
943
942
  describe(`${side}`, () => {
@@ -116,10 +116,13 @@ export class SwaapV2 extends SimpleExchange implements IDex<SwaapV2Data> {
116
116
  getTokensResponseValidator,
117
117
  );
118
118
 
119
- this.tokensMap = Object.keys(tokensResp.tokens).reduce((acc, key: string) => {
120
- acc[key.toLowerCase()] = tokensResp.tokens[key];
121
- return acc;
122
- }, {} as TokensMap);
119
+ this.tokensMap = Object.keys(tokensResp.tokens).reduce(
120
+ (acc, key: string) => {
121
+ acc[key.toLowerCase()] = tokensResp.tokens[key];
122
+ return acc;
123
+ },
124
+ {} as TokensMap,
125
+ );
123
126
 
124
127
  if (!this.dexHelper.config.isSlave) {
125
128
  await this.rateFetcher.start();
@@ -281,7 +284,7 @@ export class SwaapV2 extends SimpleExchange implements IDex<SwaapV2Data> {
281
284
  limitPools?: string[],
282
285
  ): Promise<null | ExchangePrices<SwaapV2Data>> {
283
286
  try {
284
- if(await this.isRestricted()) {
287
+ if (await this.isRestricted()) {
285
288
  return null;
286
289
  }
287
290
 
@@ -332,7 +335,6 @@ export class SwaapV2 extends SimpleExchange implements IDex<SwaapV2Data> {
332
335
  );
333
336
 
334
337
  const prices = levelEntries.map((askAndBids: SwaapV2PriceLevels) => {
335
-
336
338
  const unitPrice = this.computePricesFromLevelsBids(
337
339
  [unitVolume],
338
340
  askAndBids,
@@ -361,7 +363,8 @@ export class SwaapV2 extends SimpleExchange implements IDex<SwaapV2Data> {
361
363
  return prices;
362
364
  } catch (e) {
363
365
  this.logger.error(
364
- `Error_getPrices ${srcToken}, ${destToken}, ${side}:`, e,
366
+ `Error_getPrices ${srcToken}, ${destToken}, ${side}:`,
367
+ e,
365
368
  );
366
369
  return null;
367
370
  }
@@ -459,7 +462,7 @@ export class SwaapV2 extends SimpleExchange implements IDex<SwaapV2Data> {
459
462
  const quoteTokenAmount = BigInt(quote.amount);
460
463
  const slippageFactor = options.slippageFactor;
461
464
 
462
- if(side === SwapSide.SELL) {
465
+ if (side === SwapSide.SELL) {
463
466
  if (
464
467
  quoteTokenAmount <
465
468
  BigInt(
@@ -798,8 +801,7 @@ export class SwaapV2 extends SimpleExchange implements IDex<SwaapV2Data> {
798
801
  tokenAddress: Address,
799
802
  limit: number,
800
803
  ): Promise<PoolLiquidity[]> {
801
-
802
- if(await this.isRestricted()) {
804
+ if (await this.isRestricted()) {
803
805
  return [];
804
806
  }
805
807
 
@@ -821,7 +823,13 @@ export class SwaapV2 extends SimpleExchange implements IDex<SwaapV2Data> {
821
823
  .map((pair: string) => {
822
824
  return {
823
825
  exchange: this.dexKey,
824
- connectorTokens: [this.getTokenFromAddress(normalizedTokenAddress === pLevels[pair].base ? pLevels[pair].quote : pLevels[pair].base)],
826
+ connectorTokens: [
827
+ this.getTokenFromAddress(
828
+ normalizedTokenAddress === pLevels[pair].base
829
+ ? pLevels[pair].quote
830
+ : pLevels[pair].base,
831
+ ),
832
+ ],
825
833
  liquidityUSD: this.computeMaxLiquidity(pLevels[pair], tokenAddress),
826
834
  } as PoolLiquidity;
827
835
  })
@@ -42,10 +42,10 @@ export type SwaapV2TokensResponse = {
42
42
  symbol: string;
43
43
  address: string;
44
44
  decimals: number;
45
- },
46
- },
45
+ };
46
+ };
47
47
  success: boolean;
48
- }
48
+ };
49
49
 
50
50
  export type SwaapV2QuoteResponse = {
51
51
  id: string;
@@ -84,5 +84,5 @@ export type SwaapV2APIParameters = {
84
84
  };
85
85
 
86
86
  export type TokensMap = {
87
- [address: string]: Token,
87
+ [address: string]: Token;
88
88
  };
@@ -11,11 +11,11 @@ export const getIdentifierPrefix = (
11
11
 
12
12
  export const getPairName = (srcAddress: Address, destAddress: Address) => {
13
13
  const sortedAddresses =
14
- srcAddress < destAddress
15
- ? [srcAddress, destAddress]
16
- : [destAddress, srcAddress];
14
+ srcAddress < destAddress
15
+ ? [srcAddress, destAddress]
16
+ : [destAddress, srcAddress];
17
17
  return `${sortedAddresses[0]}_${sortedAddresses[1]}`.toLowerCase();
18
- }
18
+ };
19
19
 
20
20
  export const getCacheKey = (dexKey: string, cacheType: string) => {
21
21
  return `${CACHE_PREFIX}_${dexKey}_${cacheType}`.toLowerCase();
@@ -3,7 +3,6 @@ import joi, { CustomHelpers, ErrorReport } from 'joi';
3
3
  import * as ethers from 'ethers';
4
4
  import { SwaapV2PriceLevel } from './types';
5
5
 
6
-
7
6
  const priceLevelsValidator = joi.array().items(
8
7
  joi.object({
9
8
  level: joi.number().required(),
@@ -107,12 +106,10 @@ const mustBeAugustusSwapper = (
107
106
  });
108
107
  };
109
108
 
110
- export const getTokensResponseValidator = joi
111
- .object({
112
- tokens: joi.object().required(),
113
- success: joi.boolean().required(),
114
- });
115
-
109
+ export const getTokensResponseValidator = joi.object({
110
+ tokens: joi.object().required(),
111
+ success: joi.boolean().required(),
112
+ });
116
113
 
117
114
  export const getQuoteResponseValidator = joi
118
115
  .object({
@@ -788,9 +788,15 @@ export class UniswapV2
788
788
  destToken: Address,
789
789
  srcAmount: NumberAsString,
790
790
  destAmount: NumberAsString,
791
+ expectedAmount: NumberAsString,
791
792
  _data: UniswapData,
792
793
  side: SwapSide,
793
794
  permit: string,
795
+ uuid: string,
796
+ feePercent: NumberAsString,
797
+ deadline: NumberAsString,
798
+ partner: string,
799
+ beneficiary: string,
794
800
  contractMethod?: string,
795
801
  ): TxInfo<UniswapParam> {
796
802
  if (!contractMethod) throw new Error(`contractMethod need to be passed`);
@@ -34,3 +34,8 @@ export const ZERO_ORACLE_OBSERVATION = {
34
34
  export const OUT_OF_RANGE_ERROR_POSTFIX = `INVALID_TICK_BIT_MAP_RANGES`;
35
35
 
36
36
  export const DEFAULT_POOL_INIT_CODE_HASH = `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`;
37
+
38
+ export enum DirectMethods {
39
+ directSell = 'directUniV3Swap',
40
+ directBuy = 'directUniV3Buy',
41
+ }
@@ -57,6 +57,7 @@ export type UniswapV3Data = {
57
57
  tokenOut: Address;
58
58
  fee: NumberAsString;
59
59
  }[];
60
+ isApproved?: boolean;
60
61
  };
61
62
 
62
63
  export type DexParams = {
@@ -72,7 +73,7 @@ export type DexParams = {
72
73
  initHash: string;
73
74
  };
74
75
 
75
- export type UniswapV3SellParam = {
76
+ export type UniswapV3SimpleSwapSellParam = {
76
77
  path: string;
77
78
  recipient: Address;
78
79
  deadline: string;
@@ -80,7 +81,7 @@ export type UniswapV3SellParam = {
80
81
  amountOutMinimum: NumberAsString;
81
82
  };
82
83
 
83
- export type UniswapV3BuyParam = {
84
+ export type UniswapV3SimpleSwapBuyParam = {
84
85
  path: string;
85
86
  recipient: Address;
86
87
  deadline: string;
@@ -88,7 +89,26 @@ export type UniswapV3BuyParam = {
88
89
  amountInMaximum: NumberAsString;
89
90
  };
90
91
 
91
- export type UniswapV3Param = UniswapV3SellParam | UniswapV3BuyParam;
92
+ export type UniswapV3SimpleSwapParams =
93
+ | UniswapV3SimpleSwapSellParam
94
+ | UniswapV3SimpleSwapBuyParam;
95
+
96
+ export type UniswapV3Param = [
97
+ fromToken: Address,
98
+ toToken: Address,
99
+ exchange: Address,
100
+ fromAmount: NumberAsString,
101
+ toAmount: NumberAsString,
102
+ expectedAmount: NumberAsString,
103
+ feePercent: NumberAsString,
104
+ deadline: NumberAsString,
105
+ partner: Address,
106
+ isApproved: boolean,
107
+ beneficiary: Address,
108
+ path: string,
109
+ permit: string,
110
+ uuid: string,
111
+ ];
92
112
 
93
113
  export enum UniswapV3Functions {
94
114
  exactInput = 'exactInput',
@@ -49,6 +49,20 @@ describe('UniswapV3 E2E', () => {
49
49
  provider,
50
50
  );
51
51
  });
52
+
53
+ it('directSwap SELL WETH -> USDC', async () => {
54
+ await testE2E(
55
+ tokens['WETH'],
56
+ tokens['USDC'],
57
+ holders['WETH'],
58
+ '1000000000000000000',
59
+ SwapSide.SELL,
60
+ dexKey,
61
+ ContractMethod.directUniV3Swap,
62
+ network,
63
+ provider,
64
+ );
65
+ });
52
66
  });
53
67
 
54
68
  describe('UniswapV3 POLYGON', () => {
@@ -64,7 +78,7 @@ describe('UniswapV3 E2E', () => {
64
78
  const tokenBSymbol: string = 'WETH';
65
79
  const nativeTokenSymbol = NativeTokenSymbols[network];
66
80
 
67
- const tokenAAmount: string = '11111000000';
81
+ const tokenAAmount: string = '11000000';
68
82
  const tokenBAmount: string = '11000000000000000000';
69
83
  const nativeTokenAmount = '11000000000000000000';
70
84
 
@@ -75,9 +89,17 @@ describe('UniswapV3 E2E', () => {
75
89
  ContractMethod.simpleSwap,
76
90
  ContractMethod.multiSwap,
77
91
  ContractMethod.megaSwap,
92
+ ContractMethod.directUniV3Swap,
93
+ ],
94
+ ],
95
+ [
96
+ SwapSide.BUY,
97
+ [
98
+ ContractMethod.simpleBuy,
99
+ ContractMethod.buy,
100
+ ContractMethod.directUniV3Buy,
78
101
  ],
79
102
  ],
80
- [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]],
81
103
  ]);
82
104
 
83
105
  sideToContractMethods.forEach((contractMethods, side) =>
@@ -202,4 +224,80 @@ describe('UniswapV3 E2E', () => {
202
224
  }),
203
225
  );
204
226
  });
227
+
228
+ describe('UniswapV3 Optimism', () => {
229
+ const network = Network.OPTIMISM;
230
+ const tokens = Tokens[network];
231
+ const holders = Holders[network];
232
+ const provider = new StaticJsonRpcProvider(
233
+ generateConfig(network).privateHttpProvider,
234
+ network,
235
+ );
236
+
237
+ const tokenASymbol: string = 'OP';
238
+ const tokenBSymbol: string = 'ETH';
239
+ const nativeTokenSymbol = NativeTokenSymbols[network];
240
+
241
+ const tokenAAmount: string = '1000000000000000000';
242
+ const tokenBAmount: string = '1000000000000000000';
243
+ const nativeTokenAmount = '1000000000000000000';
244
+
245
+ const sideToContractMethods = new Map([
246
+ [
247
+ SwapSide.SELL,
248
+ [
249
+ ContractMethod.simpleSwap,
250
+ ContractMethod.multiSwap,
251
+ ContractMethod.megaSwap,
252
+ ],
253
+ ],
254
+ [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]],
255
+ ]);
256
+
257
+ sideToContractMethods.forEach((contractMethods, side) =>
258
+ contractMethods.forEach((contractMethod: ContractMethod) => {
259
+ describe(`${contractMethod}`, () => {
260
+ it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => {
261
+ await testE2E(
262
+ tokens[nativeTokenSymbol],
263
+ tokens[tokenASymbol],
264
+ holders[nativeTokenSymbol],
265
+ side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount,
266
+ side,
267
+ dexKey,
268
+ contractMethod,
269
+ network,
270
+ provider,
271
+ );
272
+ });
273
+ it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => {
274
+ await testE2E(
275
+ tokens[tokenASymbol],
276
+ tokens[nativeTokenSymbol],
277
+ holders[tokenASymbol],
278
+ side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount,
279
+ side,
280
+ dexKey,
281
+ contractMethod,
282
+ network,
283
+ provider,
284
+ );
285
+ });
286
+ it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => {
287
+ await testE2E(
288
+ tokens[tokenASymbol],
289
+ tokens[tokenBSymbol],
290
+ holders[tokenASymbol],
291
+ side === SwapSide.SELL ? tokenAAmount : tokenBAmount,
292
+ side,
293
+ dexKey,
294
+ contractMethod,
295
+ network,
296
+ provider,
297
+ );
298
+ });
299
+ });
300
+ }),
301
+ );
302
+ });
205
303
  });
@@ -11,6 +11,9 @@ import {
11
11
  Logger,
12
12
  NumberAsString,
13
13
  PoolPrices,
14
+ TxInfo,
15
+ PreprocessTransactionOptions,
16
+ ExchangeTxInfo,
14
17
  } from '../../types';
15
18
  import { SwapSide, Network, CACHE_PREFIX } from '../../constants';
16
19
  import * as CALLDATA_GAS_COST from '../../calldata-gas-cost';
@@ -19,6 +22,7 @@ import {
19
22
  getDexKeysWithNetwork,
20
23
  interpolate,
21
24
  isTruthy,
25
+ uuidToBytes16,
22
26
  } from '../../utils';
23
27
  import { IDex } from '../../dex/idex';
24
28
  import { IDexHelper } from '../../dex-helper/idex-helper';
@@ -29,6 +33,7 @@ import {
29
33
  UniswapV3Data,
30
34
  UniswapV3Functions,
31
35
  UniswapV3Param,
36
+ UniswapV3SimpleSwapParams,
32
37
  } from './types';
33
38
  import {
34
39
  getLocalDeadlineAsFriendlyPlaceholder,
@@ -39,14 +44,16 @@ import { UniswapV3EventPool } from './uniswap-v3-pool';
39
44
  import UniswapV3RouterABI from '../../abi/uniswap-v3/UniswapV3Router.abi.json';
40
45
  import UniswapV3QuoterABI from '../../abi/uniswap-v3/UniswapV3Quoter.abi.json';
41
46
  import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json';
47
+ import DirectSwapABI from '../../abi/DirectSwap.json';
42
48
  import UniswapV3StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json';
43
49
  import {
50
+ DirectMethods,
44
51
  UNISWAPV3_EFFICIENCY_FACTOR,
45
52
  UNISWAPV3_POOL_SEARCH_OVERHEAD,
46
53
  UNISWAPV3_TICK_BASE_OVERHEAD,
47
54
  UNISWAPV3_TICK_GAS_COST,
48
55
  } from './constants';
49
- import { DeepReadonly } from 'ts-essentials';
56
+ import { assert, DeepReadonly } from 'ts-essentials';
50
57
  import { uniswapV3Math } from './contract-math/uniswap-v3-math';
51
58
  import { Contract } from 'web3-eth-contract';
52
59
  import { AbiItem } from 'web3-utils';
@@ -56,6 +63,7 @@ import {
56
63
  DEFAULT_ID_ERC20,
57
64
  DEFAULT_ID_ERC20_AS_STRING,
58
65
  } from '../../lib/tokens/types';
66
+ import { OptimalSwapExchange } from '@paraswap/core';
59
67
 
60
68
  type PoolPairsInfo = {
61
69
  token0: Address;
@@ -77,6 +85,8 @@ export class UniswapV3
77
85
  readonly hasConstantPriceLargeAmounts = false;
78
86
  readonly needWrapNative = true;
79
87
 
88
+ readonly directSwapIface = new Interface(DirectSwapABI);
89
+
80
90
  intervalTask?: NodeJS.Timeout;
81
91
 
82
92
  public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
@@ -113,7 +123,7 @@ export class UniswapV3
113
123
  // To receive revert reasons
114
124
  this.dexHelper.web3Provider.eth.handleRevert = false;
115
125
 
116
- // Normalise once all config addresses and use across all scenarios
126
+ // Normalize once all config addresses and use across all scenarios
117
127
  this.config = this._toLowerForAllConfigAddresses();
118
128
 
119
129
  this.notExistingPoolSetKey =
@@ -449,6 +459,7 @@ export class UniswapV3
449
459
  fee: pool.feeCodeAsString,
450
460
  },
451
461
  ],
462
+ exchange: pool.poolAddress,
452
463
  },
453
464
  poolIdentifier: this.getPoolIdentifier(
454
465
  pool.token0,
@@ -731,6 +742,130 @@ export class UniswapV3
731
742
  return arr;
732
743
  }
733
744
 
745
+ getTokenFromAddress(address: Address): Token {
746
+ // In this Dex decimals are not used
747
+ return { address, decimals: 0 };
748
+ }
749
+
750
+ async preProcessTransaction(
751
+ optimalSwapExchange: OptimalSwapExchange<UniswapV3Data>,
752
+ srcToken: Token,
753
+ _0: Token,
754
+ _1: SwapSide,
755
+ options: PreprocessTransactionOptions,
756
+ ): Promise<[OptimalSwapExchange<UniswapV3Data>, ExchangeTxInfo]> {
757
+ if (!options.isDirectMethod) {
758
+ return [
759
+ optimalSwapExchange,
760
+ {
761
+ deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()),
762
+ },
763
+ ];
764
+ }
765
+
766
+ assert(
767
+ optimalSwapExchange.data !== undefined,
768
+ `preProcessTransaction: data field is missing`,
769
+ );
770
+
771
+ let isApproved: boolean | undefined;
772
+
773
+ try {
774
+ this.erc20Contract.options.address =
775
+ this.dexHelper.config.wrapETH(srcToken).address;
776
+ const allowance = await this.erc20Contract.methods
777
+ .allowance(this.augustusAddress, this.config.router)
778
+ .call(undefined, 'latest');
779
+ isApproved =
780
+ BigInt(allowance.toString()) >= BigInt(optimalSwapExchange.srcAmount);
781
+ } catch (e) {
782
+ this.logger.error(
783
+ `preProcessTransaction failed to retrieve allowance info: `,
784
+ e,
785
+ );
786
+ }
787
+
788
+ return [
789
+ {
790
+ ...optimalSwapExchange,
791
+ data: {
792
+ ...optimalSwapExchange.data,
793
+ isApproved,
794
+ },
795
+ },
796
+ {
797
+ deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()),
798
+ },
799
+ ];
800
+ }
801
+
802
+ getDirectParam(
803
+ srcToken: Address,
804
+ destToken: Address,
805
+ srcAmount: NumberAsString,
806
+ destAmount: NumberAsString,
807
+ expectedAmount: NumberAsString,
808
+ data: UniswapV3Data,
809
+ side: SwapSide,
810
+ permit: string,
811
+ uuid: string,
812
+ feePercent: NumberAsString,
813
+ deadline: NumberAsString,
814
+ partner: string,
815
+ beneficiary: string,
816
+ contractMethod?: string,
817
+ ): TxInfo<UniswapV3Param> {
818
+ if (
819
+ contractMethod !== DirectMethods.directSell &&
820
+ contractMethod !== DirectMethods.directBuy
821
+ ) {
822
+ throw new Error(`Invalid contract method ${contractMethod}`);
823
+ }
824
+
825
+ let isApproved: boolean = !!data.isApproved;
826
+ if (data.isApproved === undefined) {
827
+ this.logger.warn(`isApproved is undefined, defaulting to false`);
828
+ }
829
+
830
+ const path = this._encodePath(data.path, side);
831
+
832
+ const swapParams: UniswapV3Param = [
833
+ srcToken,
834
+ destToken,
835
+ this.config.router,
836
+ srcAmount,
837
+ destAmount,
838
+ expectedAmount,
839
+ feePercent,
840
+ deadline,
841
+ partner,
842
+ isApproved,
843
+ beneficiary,
844
+ path,
845
+ permit,
846
+ uuidToBytes16(uuid),
847
+ ];
848
+
849
+ const encoder = (...params: UniswapV3Param) => {
850
+ return this.directSwapIface.encodeFunctionData(
851
+ side === SwapSide.SELL
852
+ ? DirectMethods.directSell
853
+ : DirectMethods.directBuy,
854
+ [params],
855
+ );
856
+ };
857
+
858
+ return {
859
+ params: swapParams,
860
+ encoder,
861
+ networkFee: '0',
862
+ };
863
+ }
864
+
865
+ static getDirectFunctionName(): string[] {
866
+ return [DirectMethods.directSell, DirectMethods.directBuy];
867
+ }
868
+
734
869
  async getSimpleParam(
735
870
  srcToken: string,
736
871
  destToken: string,
@@ -745,7 +880,7 @@ export class UniswapV3
745
880
  : UniswapV3Functions.exactOutput;
746
881
 
747
882
  const path = this._encodePath(data.path, side);
748
- const swapFunctionParams: UniswapV3Param =
883
+ const swapFunctionParams: UniswapV3SimpleSwapParams =
749
884
  side === SwapSide.SELL
750
885
  ? {
751
886
  recipient: this.augustusAddress,
@@ -269,9 +269,16 @@ export class ZeroX
269
269
  destToken: Address,
270
270
  srcAmount: NumberAsString,
271
271
  destAmount: NumberAsString,
272
+ expectedAmount: NumberAsString,
272
273
  data: ZeroXData,
273
274
  side: SwapSide,
274
275
  permit: string,
276
+ uuid: string,
277
+ feePercent: NumberAsString,
278
+ deadline: NumberAsString,
279
+ partner: string,
280
+ beneficiary: string,
281
+ contractMethod?: string,
275
282
  ): TxInfo<ZeroXParam> {
276
283
  const usePermit = permit !== '0x';
277
284
  const encoder = (...params: ZeroXParam) => {
@@ -17,6 +17,8 @@ import {
17
17
  } from '../types';
18
18
  import { SwapSide, NULL_ADDRESS, ContractMethod } from '../constants';
19
19
  import { LimitOrderExchange } from '../dex/limit-order-exchange';
20
+ import { v4 as uuid } from 'uuid';
21
+ import { DirectContractMethods } from '@paraswap/core/build/constants';
20
22
 
21
23
  export interface IParaSwapSDK {
22
24
  getPrices(
@@ -205,6 +207,8 @@ export class LocalParaswapSDK implements IParaSwapSDK {
205
207
  : priceRoute.srcAmount,
206
208
  );
207
209
 
210
+ const contractMethod = priceRoute.contractMethod;
211
+
208
212
  // Call preprocessTransaction for each exchange before we build transaction
209
213
  try {
210
214
  priceRoute.bestRoute = await Promise.all(
@@ -234,6 +238,9 @@ export class LocalParaswapSDK implements IParaSwapSDK {
234
238
  {
235
239
  slippageFactor,
236
240
  txOrigin: userAddress,
241
+ isDirectMethod: DirectContractMethods.includes(
242
+ contractMethod as ContractMethod,
243
+ ),
237
244
  },
238
245
  );
239
246
 
@@ -264,7 +271,7 @@ export class LocalParaswapSDK implements IParaSwapSDK {
264
271
  partnerAddress: NULL_ADDRESS,
265
272
  partnerFeePercent: '0',
266
273
  deadline: deadline.toString(),
267
- uuid: '00000000-0000-0000-0000-000000000000',
274
+ uuid: uuid(),
268
275
  });
269
276
  }
270
277
  }