@paraswap/dex-lib 2.33.2 → 2.33.4-balancer-v2-multihop.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.
@@ -0,0 +1,226 @@
1
+ // import _ from 'lodash';
2
+ // import { balancerV2Merge, AllBalancerV2Forks } from './optimizer';
3
+ // import { UnoptimizedRate } from '../../types';
4
+ // import { SwapSide } from '@paraswap/core';
5
+ //
6
+ // describe('BalancerV2 optimizer', () => {
7
+ // These values are random and are not important. The only invariant here we need to make sure,
8
+ // that the optimizer does not change these values
9
+ // const baseUnoptimizedRate: UnoptimizedRate = {
10
+ // blockNumber: 99,
11
+ // network: 1,
12
+ // srcToken: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
13
+ // srcDecimals: 18,
14
+ // srcAmount: '1',
15
+ // destToken: '0xcafe001067cdef266afb7eb5a286dcfd277f3de5',
16
+ // destDecimals: 18,
17
+ // destAmount: '2',
18
+ // gasCostUSD: '12.178524',
19
+ // gasCost: '747300',
20
+ // side: SwapSide.SELL,
21
+ // tokenTransferProxy: '0x216b4b4ba9f3e719726886d34a177484278bfcae',
22
+ // contractAddress: '0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57',
23
+ // bestRoute: [],
24
+ // };
25
+ // it('balancerV2Merge swapExchanges: BalancerV2-BalancerV2Fork', () => {
26
+ // const testRate: UnoptimizedRate = _.cloneDeep(baseUnoptimizedRate);
27
+ // testRate.bestRoute = [
28
+ // {
29
+ // percent: 92,
30
+ // swaps: [
31
+ // {
32
+ // srcToken: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
33
+ // srcDecimals: 18,
34
+ // destToken: '0xcafe001067cdef266afb7eb5a286dcfd277f3de5',
35
+ // destDecimals: 18,
36
+ // swapExchanges: [
37
+ // {
38
+ // exchange: 'BalancerV2',
39
+ // srcAmount: '27001080000000000000',
40
+ // destAmount: '1663710383246524230443584',
41
+ // percent: 97.83,
42
+ // poolAddresses: ['0xcb0e14e96f2cefa8550ad8e4aea344f211e5061d'],
43
+ // data: {
44
+ // poolId:
45
+ // '0xcb0e14e96f2cefa8550ad8e4aea344f211e5061d00020000000000000000011a',
46
+ // gasUSD: '2.395615',
47
+ // },
48
+ // },
49
+ // {
50
+ // exchange: 'BeetsFi',
51
+ // srcAmount: '598920000000000000',
52
+ // destAmount: '36257151080030344235259',
53
+ // percent: 2.17,
54
+ // poolAddresses: ['0x458ae80894A0924Ac763C034977e330c565F1687'],
55
+ // data: {
56
+ // poolId:
57
+ // '0x87a867f5d240a782d43d90b6b06dea470f3f8f22000200000000000000000516',
58
+ // gasUSD: '2.395615',
59
+ // },
60
+ // },
61
+ // ],
62
+ // },
63
+ // ],
64
+ // },
65
+ // {
66
+ // percent: 8,
67
+ // swaps: [
68
+ // {
69
+ // srcToken: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
70
+ // srcDecimals: 18,
71
+ // destToken: '0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c',
72
+ // destDecimals: 18,
73
+ // swapExchanges: [
74
+ // {
75
+ // exchange: 'Bancor',
76
+ // srcAmount: '2400000000000000000',
77
+ // destAmount: '9235411862479221870019',
78
+ // percent: 100,
79
+ // poolAddresses: ['0x4c9a2bD661D640dA3634A4988a9Bd2Bc0f18e5a9'],
80
+ // data: {
81
+ // path: [
82
+ // '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
83
+ // '0xb1CD6e4153B2a390Cf00A6556b0fC1458C4A5533',
84
+ // '0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c',
85
+ // ],
86
+ // gasUSD: '3.259340',
87
+ // },
88
+ // },
89
+ // ],
90
+ // },
91
+ // {
92
+ // srcToken: '0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c',
93
+ // srcDecimals: 18,
94
+ // destToken: '0xcafe001067cdef266afb7eb5a286dcfd277f3de5',
95
+ // destDecimals: 18,
96
+ // swapExchanges: [
97
+ // {
98
+ // exchange: 'Bancor',
99
+ // srcAmount: '9235411862479221870019',
100
+ // destAmount: '144326625204595711989170',
101
+ // percent: 100,
102
+ // poolAddresses: ['0xe950137942F446a93C8309B3a7c1407ef1975856'],
103
+ // data: {
104
+ // path: [
105
+ // '0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c',
106
+ // '0xdD17F899D4Fa66249bfdba45F0c70817052559Ac',
107
+ // '0xcafe001067cdef266afb7eb5a286dcfd277f3de5',
108
+ // ],
109
+ // gasUSD: '3.259340',
110
+ // },
111
+ // },
112
+ // ],
113
+ // },
114
+ // ],
115
+ // },
116
+ // ];
117
+ //
118
+ // const optimizedRate = balancerV2Merge(testRate);
119
+ //
120
+ // const expectedRate: UnoptimizedRate = _.cloneDeep(baseUnoptimizedRate);
121
+ // expectedRate.bestRoute = [
122
+ // {
123
+ // percent: 92,
124
+ // swaps: [
125
+ // {
126
+ // srcToken: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
127
+ // srcDecimals: 18,
128
+ // destToken: '0xcafe001067cdef266afb7eb5a286dcfd277f3de5',
129
+ // destDecimals: 18,
130
+ // swapExchanges: [
131
+ // {
132
+ // exchange: 'BalancerV2',
133
+ // srcAmount: '27001080000000000000',
134
+ // destAmount: '1663710383246524230443584',
135
+ // percent: 97.83,
136
+ // poolAddresses: ['0xcb0e14e96f2cefa8550ad8e4aea344f211e5061d'],
137
+ // data: {
138
+ // poolId:
139
+ // '0xcb0e14e96f2cefa8550ad8e4aea344f211e5061d00020000000000000000011a',
140
+ // gasUSD: '2.395615',
141
+ // },
142
+ // },
143
+ // {
144
+ // exchange: 'BeetsFi',
145
+ // srcAmount: '598920000000000000',
146
+ // destAmount: '36257151080030344235259',
147
+ // percent: 2.17,
148
+ // poolAddresses: ['0x458ae80894A0924Ac763C034977e330c565F1687'],
149
+ // data: {
150
+ // poolId:
151
+ // '0x87a867f5d240a782d43d90b6b06dea470f3f8f22000200000000000000000516',
152
+ // gasUSD: '2.395615',
153
+ // },
154
+ // },
155
+ // ],
156
+ // },
157
+ // ],
158
+ // },
159
+ // {
160
+ // percent: 8,
161
+ // swaps: [
162
+ // {
163
+ // srcToken: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
164
+ // srcDecimals: 18,
165
+ // destToken: '0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c',
166
+ // destDecimals: 18,
167
+ // swapExchanges: [
168
+ // {
169
+ // exchange: 'Bancor',
170
+ // srcAmount: '2400000000000000000',
171
+ // destAmount: '9235411862479221870019',
172
+ // percent: 100,
173
+ // poolAddresses: ['0x4c9a2bD661D640dA3634A4988a9Bd2Bc0f18e5a9'],
174
+ // data: {
175
+ // path: [
176
+ // '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
177
+ // '0xb1CD6e4153B2a390Cf00A6556b0fC1458C4A5533',
178
+ // '0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c',
179
+ // ],
180
+ // gasUSD: '3.259340',
181
+ // },
182
+ // },
183
+ // ],
184
+ // },
185
+ // {
186
+ // srcToken: '0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c',
187
+ // srcDecimals: 18,
188
+ // destToken: '0xcafe001067cdef266afb7eb5a286dcfd277f3de5',
189
+ // destDecimals: 18,
190
+ // swapExchanges: [
191
+ // {
192
+ // exchange: 'Bancor',
193
+ // srcAmount: '9235411862479221870019',
194
+ // destAmount: '144326625204595711989170',
195
+ // percent: 100,
196
+ // poolAddresses: ['0xe950137942F446a93C8309B3a7c1407ef1975856'],
197
+ // data: {
198
+ // path: [
199
+ // '0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c',
200
+ // '0xdD17F899D4Fa66249bfdba45F0c70817052559Ac',
201
+ // '0xcafe001067cdef266afb7eb5a286dcfd277f3de5',
202
+ // ],
203
+ // gasUSD: '3.259340',
204
+ // },
205
+ // },
206
+ // ],
207
+ // },
208
+ // ],
209
+ // },
210
+ // ];
211
+ //
212
+ // expect(optimizedRate).toStrictEqual(expectedRate);
213
+ // });
214
+ //
215
+ // it('balancerV2Merge swapExchanges: No BalancerV2', () => {
216
+ // expect(true).toBe(true);
217
+ // });
218
+ //
219
+ // it('balancerV2Merge swaps: BalancerV2-BalancerV2Fork', () => {
220
+ // expect(true).toBe(true);
221
+ // });
222
+ //
223
+ // it('balancerV2Merge only one BalancerV2Fork in route', () => {
224
+ // expect(true).toBe(true);
225
+ // });
226
+ // });
@@ -3,17 +3,14 @@ import { BalancerSwapV2 } from './types';
3
3
  import { SwapSide } from '../../constants';
4
4
  import { BalancerConfig } from './config';
5
5
 
6
- const MAX_UINT256 =
7
- '115792089237316195423570985008687907853269984665640564039457584007913129639935';
8
-
9
- const AllBalancerV2Forks = Object.keys(BalancerConfig);
6
+ export const AllBalancerV2Forks = Object.keys(BalancerConfig);
10
7
 
11
8
  export function balancerV2Merge(or: UnoptimizedRate): UnoptimizedRate {
12
9
  const fixSwap = (
13
10
  rawSwap: OptimalSwapExchange<any>[],
11
+ newBalancers: { [key: string]: OptimalSwapExchange<any> },
14
12
  side: SwapSide,
15
13
  ): OptimalSwapExchange<any>[] => {
16
- const newBalancers: { [key: string]: OptimalSwapExchange<any> } = {};
17
14
  let optimizedSwap = new Array<OptimalSwapExchange<any>>();
18
15
  rawSwap.forEach((s: OptimalSwapExchange<any>) => {
19
16
  const exchangeKey = s.exchange.toLowerCase();
@@ -59,12 +56,17 @@ export function balancerV2Merge(or: UnoptimizedRate): UnoptimizedRate {
59
56
  return optimizedSwap;
60
57
  };
61
58
 
62
- or.bestRoute = or.bestRoute.map(r => ({
63
- ...r,
64
- swaps: r.swaps.map(s => ({
65
- ...s,
66
- swapExchanges: fixSwap(s.swapExchanges, or.side),
67
- })),
68
- }));
59
+ or.bestRoute = or.bestRoute.map(r => {
60
+ const newBalancers: {
61
+ [key: string]: OptimalSwapExchange<any>;
62
+ } = {};
63
+ return {
64
+ ...r,
65
+ swaps: r.swaps.map(s => ({
66
+ ...s,
67
+ swapExchanges: fixSwap(s.swapExchanges, newBalancers, or.side),
68
+ })),
69
+ };
70
+ });
69
71
  return or;
70
72
  }
package/src/dex/index.ts CHANGED
@@ -73,6 +73,7 @@ import { SpiritSwapV3 } from './quickswap/spiritswap-v3';
73
73
  import { TraderJoeV21 } from './trader-joe-v2.1';
74
74
  import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3';
75
75
  import { Algebra } from './algebra/algebra';
76
+ import { NomiswapV2 } from './uniswap-v2/nomiswap-v2';
76
77
 
77
78
  const LegacyDexes = [
78
79
  CurveV2,
@@ -143,6 +144,7 @@ const Dexes = [
143
144
  MaverickV1,
144
145
  Camelot,
145
146
  SwaapV2,
147
+ NomiswapV2,
146
148
  ];
147
149
 
148
150
  export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder<
@@ -2,7 +2,11 @@ import dotenv from 'dotenv';
2
2
  dotenv.config();
3
3
 
4
4
  import { testE2E } from '../../../tests/utils-e2e';
5
- import { Tokens, Holders, NativeTokenSymbols } from '../../../tests/constants-e2e';
5
+ import {
6
+ Tokens,
7
+ Holders,
8
+ NativeTokenSymbols,
9
+ } from '../../../tests/constants-e2e';
6
10
  import { Network, ContractMethod, SwapSide } from '../../constants';
7
11
  import { StaticJsonRpcProvider } from '@ethersproject/providers';
8
12
  import { generateConfig } from '../../config';
@@ -410,7 +414,6 @@ describe('Solidly E2E', () => {
410
414
  tokenBAmount,
411
415
  nativeTokenAmount,
412
416
  );
413
-
414
417
  });
415
418
  });
416
419
 
@@ -1401,5 +1404,4 @@ describe('Solidly E2E', () => {
1401
1404
  );
1402
1405
  });
1403
1406
  });
1404
-
1405
1407
  });
@@ -0,0 +1,62 @@
1
+ import { Network } from '../../constants';
2
+ import { getDexKeysWithNetwork } from '../../utils';
3
+ import { IDexHelper } from '../../dex-helper/idex-helper';
4
+ import { UniswapV2, UniswapV2Pair } from '../uniswap-v2/uniswap-v2';
5
+ import { Interface } from '@ethersproject/abi';
6
+ import NomiswapPoolABI from '../../abi/nomiswap-v2/nomiswap-v2-pool.json';
7
+ import { DexParams } from './types';
8
+ import { DexConfigMap } from '../../types';
9
+
10
+ export const NomiswapV2Config: DexConfigMap<DexParams> = {
11
+ NomiswapV2: {
12
+ [Network.BSC]: {
13
+ factoryAddress: '0xd6715A8be3944ec72738F0BFDC739d48C3c29349',
14
+ initCode:
15
+ '0x83eb759f5ea0525124f03d4ac741bb4af0bb1c703d5f694bd42a8bd72e495a01',
16
+ poolGasCost: 120 * 1000,
17
+ feeCode: 0, // this is ignored as Nomiswap uses dynamic fees,
18
+ subgraphURL: 'https://api.thegraph.com/subgraphs/name/nominex/nomiswap-exchange-subgraph',
19
+ },
20
+ },
21
+ };
22
+
23
+ export class NomiswapV2 extends UniswapV2 {
24
+ nomiswapPool: Interface;
25
+
26
+ public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
27
+ getDexKeysWithNetwork(NomiswapV2Config);
28
+
29
+ constructor(
30
+ protected network: Network,
31
+ dexKey: string,
32
+ protected dexHelper: IDexHelper,
33
+ ) {
34
+ super(
35
+ network,
36
+ dexKey,
37
+ dexHelper,
38
+ true,
39
+ NomiswapV2Config[dexKey][network].factoryAddress,
40
+ NomiswapV2Config[dexKey][network].subgraphURL,
41
+ NomiswapV2Config[dexKey][network].initCode,
42
+ NomiswapV2Config[dexKey][network].feeCode,
43
+ NomiswapV2Config[dexKey][network].poolGasCost,
44
+ );
45
+ this.nomiswapPool = new Interface(NomiswapPoolABI);
46
+ }
47
+
48
+ protected getFeesMultiCallData(pair: UniswapV2Pair) {
49
+ const callEntry = {
50
+ target: pair.exchange!,
51
+ callData: this.nomiswapPool.encodeFunctionData('swapFee', []),
52
+ };
53
+ const callDecoder = (values: any[]) =>
54
+ parseInt(
55
+ this.nomiswapPool.decodeFunctionResult('swapFee', values)[0].toString(),
56
+ ) * 10;
57
+ return {
58
+ callEntry,
59
+ callDecoder,
60
+ };
61
+ }
62
+ }
@@ -2,11 +2,110 @@ import dotenv from 'dotenv';
2
2
  dotenv.config();
3
3
 
4
4
  import { testE2E } from '../../../tests/utils-e2e';
5
- import { Tokens, Holders } from '../../../tests/constants-e2e';
5
+ import { Tokens, Holders, NativeTokenSymbols } from '../../../tests/constants-e2e';
6
6
  import { Network, ContractMethod, SwapSide } from '../../constants';
7
7
  import { StaticJsonRpcProvider } from '@ethersproject/providers';
8
8
  import { generateConfig } from '../../config';
9
9
 
10
+ function testForNetwork(
11
+ network: Network,
12
+ dexKey: string,
13
+ tokenASymbol: string,
14
+ tokenBSymbol: string,
15
+ tokenAAmount: string,
16
+ tokenBAmount: string,
17
+ nativeTokenAmount: string,
18
+ slippage?: number | undefined,
19
+ ) {
20
+ const provider = new StaticJsonRpcProvider(
21
+ generateConfig(network).privateHttpProvider,
22
+ network,
23
+ );
24
+ const tokens = Tokens[network];
25
+ const holders = Holders[network];
26
+ const nativeTokenSymbol = NativeTokenSymbols[network];
27
+
28
+ const sideToContractMethods = new Map([
29
+ [
30
+ SwapSide.SELL,
31
+ [
32
+ ContractMethod.simpleSwap,
33
+ ContractMethod.multiSwap,
34
+ ContractMethod.megaSwap,
35
+ ],
36
+ ],
37
+ [
38
+ SwapSide.BUY,
39
+ [
40
+ ContractMethod.simpleBuy,
41
+ ContractMethod.buy,
42
+ ],
43
+ ],
44
+ ]);
45
+
46
+ describe(`${network}`, () => {
47
+ sideToContractMethods.forEach((contractMethods, side) =>
48
+ describe(`${side}`, () => {
49
+ contractMethods.forEach((contractMethod: ContractMethod) => {
50
+ describe(`${contractMethod}`, () => {
51
+ it(`${nativeTokenSymbol} -> ${tokenASymbol}`, async () => {
52
+ await testE2E(
53
+ tokens[nativeTokenSymbol],
54
+ tokens[tokenASymbol],
55
+ holders[nativeTokenSymbol],
56
+ side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount,
57
+ side,
58
+ dexKey,
59
+ contractMethod,
60
+ network,
61
+ provider,
62
+ undefined,
63
+ undefined,
64
+ undefined,
65
+ slippage,
66
+ );
67
+ });
68
+ it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => {
69
+ await testE2E(
70
+ tokens[tokenASymbol],
71
+ tokens[nativeTokenSymbol],
72
+ holders[tokenASymbol],
73
+ side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount,
74
+ side,
75
+ dexKey,
76
+ contractMethod,
77
+ network,
78
+ provider,
79
+ undefined,
80
+ undefined,
81
+ undefined,
82
+ slippage,
83
+ );
84
+ });
85
+ it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => {
86
+ await testE2E(
87
+ tokens[tokenASymbol],
88
+ tokens[tokenBSymbol],
89
+ holders[tokenASymbol],
90
+ side === SwapSide.SELL ? tokenAAmount : tokenBAmount,
91
+ side,
92
+ dexKey,
93
+ contractMethod,
94
+ network,
95
+ provider,
96
+ undefined,
97
+ undefined,
98
+ undefined,
99
+ slippage,
100
+ );
101
+ });
102
+ });
103
+ });
104
+ }),
105
+ );
106
+ });
107
+ }
108
+
10
109
  describe('UniswapV2 E2E BSC', () => {
11
110
  const network = Network.BSC;
12
111
  const tokens = Tokens[network];
@@ -1407,6 +1506,28 @@ describe('UniswapV2 E2E BSC', () => {
1407
1506
  });
1408
1507
  });
1409
1508
 
1509
+ describe('NomiswapV2', () => {
1510
+ const dexKey = 'NomiswapV2';
1511
+ const network = Network.BSC;
1512
+
1513
+ const tokenASymbol: string = 'USDC';
1514
+ const tokenBSymbol: string = 'USDT';
1515
+
1516
+ const tokenAAmount: string = '1111100000';
1517
+ const tokenBAmount: string = '1000000000';
1518
+ const nativeTokenAmount = '11000000000000';
1519
+
1520
+ testForNetwork(
1521
+ network,
1522
+ dexKey,
1523
+ tokenASymbol,
1524
+ tokenBSymbol,
1525
+ tokenAAmount,
1526
+ tokenBAmount,
1527
+ nativeTokenAmount,
1528
+ );
1529
+ });
1530
+
1410
1531
  describe(`Swapsicle`, () => {
1411
1532
  const dexKey = 'Swapsicle';
1412
1533
 
@@ -112,7 +112,6 @@ function testForNetwork(
112
112
  });
113
113
  }
114
114
 
115
-
116
115
  describe('UniswapV3 E2E', () => {
117
116
 
118
117
  describe('UniswapV3', () => {
@@ -462,7 +462,7 @@ export const Tokens: {
462
462
  },
463
463
  EQUAL: {
464
464
  address: '0x3fd3a0c85b70754efc07ac9ac0cbbdce664865a6',
465
- decimals: 18
465
+ decimals: 18,
466
466
  },
467
467
  POPS: {
468
468
  address: '0x9dE4b40bDcE50Ec6a1A668bF85997BbBD324069a',