@curvefi/api 1.22.0 → 1.24.1

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.
package/README.md CHANGED
@@ -161,13 +161,12 @@ import curve from "@curvefi/api";
161
161
  console.log(await curve.getBalances(['aDAI', 'aSUSD']));
162
162
  // OR console.log(await curve.getBalances(['0x028171bCA77440897B824Ca71D1c56caC55b68A3', '0x6c5024cd4f8a59110119c56f8933403a539555eb']));
163
163
 
164
- // [ '10000.000211315200513239', '10000.0' ]
164
+ // [ '10000.00017727177059715', '10000.000080108429034461' ]
165
+
165
166
 
166
-
167
167
  // --- Pool ---
168
168
 
169
169
  const saave = new curve.Pool('saave');
170
-
171
170
 
172
171
  // 1. Current address balances (signer balances)
173
172
 
@@ -175,40 +174,46 @@ import curve from "@curvefi/api";
175
174
  // {
176
175
  // lpToken: '0.0',
177
176
  // gauge: '0.0',
178
- // DAI: '10000.0',
179
- // sUSD: '10000.0',
180
- // aDAI: '10000.000211315200513239',
181
- // aSUSD: '10000.0'
177
+ // '0x6B175474E89094C44Da98b954EedeAC495271d0F': '10000.0',
178
+ // '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51': '10000.0',
179
+ // '0x028171bCA77440897B824Ca71D1c56caC55b68A3': '10000.00017727177059715',
180
+ // '0x6c5024cd4f8a59110119c56f8933403a539555eb': '10000.000080108429034461'
182
181
  // }
183
182
 
184
183
  console.log(await saave.lpTokenBalances());
185
184
  // { lpToken: '0.0', gauge: '0.0' }
186
185
 
187
186
  console.log(await saave.underlyingCoinBalances());
188
- // { DAI: '10000.0', sUSD: '10000.0' }
189
-
187
+ // {
188
+ // '0x6B175474E89094C44Da98b954EedeAC495271d0F': '10000.0',
189
+ // '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51': '10000.0'
190
+ // }
191
+
190
192
  console.log(await saave.coinBalances());
191
- // { aDAI: '10000.000211315200513239', aSUSD: '10000.0' }
193
+ // {
194
+ // '0x028171bCA77440897B824Ca71D1c56caC55b68A3': '10000.00017727177059715',
195
+ // '0x6c5024cd4f8a59110119c56f8933403a539555eb': '10000.000080108429034461'
196
+ // }
192
197
 
193
198
  console.log(await saave.allCoinBalances());
194
199
  // {
195
- // DAI: '10000.0',
196
- // sUSD: '10000.0',
197
- // aDAI: '10000.000211315200513239',
198
- // aSUSD: '10000.0'
200
+ // '0x6B175474E89094C44Da98b954EedeAC495271d0F': '10000.0',
201
+ // '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51': '10000.0',
202
+ // '0x028171bCA77440897B824Ca71D1c56caC55b68A3': '10000.00017727177059715',
203
+ // '0x6c5024cd4f8a59110119c56f8933403a539555eb': '10000.000080108429034461'
199
204
  // }
200
205
 
201
-
206
+
202
207
  // 2. For every method above you can specify the address
203
208
 
204
209
  console.log(await saave.balances("0x0063046686E46Dc6F15918b61AE2B121458534a5"));
205
210
  // {
206
211
  // lpToken: '0.0',
207
212
  // gauge: '0.0',
208
- // DAI: '0.0',
209
- // sUSD: '0.0',
210
- // aDAI: '0.0',
211
- // aSUSD: '0.0'
213
+ // '0x6B175474E89094C44Da98b954EedeAC495271d0F': '0.0',
214
+ // '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51': '0.0',
215
+ // '0x028171bCA77440897B824Ca71D1c56caC55b68A3': '0.0',
216
+ // '0x6c5024cd4f8a59110119c56f8933403a539555eb': '0.0'
212
217
  // }
213
218
 
214
219
  // Or several addresses
@@ -217,21 +222,22 @@ import curve from "@curvefi/api";
217
222
  // '0x0063046686E46Dc6F15918b61AE2B121458534a5': {
218
223
  // lpToken: '0.0',
219
224
  // gauge: '0.0',
220
- // DAI: '0.0',
221
- // sUSD: '0.0',
222
- // aDAI: '0.0',
223
- // aSUSD: '0.0'
225
+ // '0x6B175474E89094C44Da98b954EedeAC495271d0F': '0.0',
226
+ // '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51': '0.0',
227
+ // '0x028171bCA77440897B824Ca71D1c56caC55b68A3': '0.0',
228
+ // '0x6c5024cd4f8a59110119c56f8933403a539555eb': '0.0'
224
229
  // },
225
230
  // '0x66aB6D9362d4F35596279692F0251Db635165871': {
226
231
  // lpToken: '0.0',
227
232
  // gauge: '0.0',
228
- // DAI: '10000.0',
229
- // sUSD: '10000.0',
230
- // aDAI: '10000.000211315200513239',
231
- // aSUSD: '10000.0'
233
+ // '0x6B175474E89094C44Da98b954EedeAC495271d0F': '10000.0',
234
+ // '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51': '10000.0',
235
+ // '0x028171bCA77440897B824Ca71D1c56caC55b68A3': '10000.00017727177059715',
236
+ // '0x6c5024cd4f8a59110119c56f8933403a539555eb': '10000.000080108429034461'
232
237
  // }
233
238
  // }
234
239
 
240
+
235
241
  })()
236
242
  ```
237
243
 
@@ -494,7 +500,66 @@ import curve from "@curvefi/api";
494
500
  })()
495
501
  ```
496
502
 
497
- ## Exchange using all pools
503
+ ## Exchange
504
+
505
+ ### Router exchange
506
+
507
+ ```ts
508
+ import curve from "@curvefi/api";
509
+
510
+ (async () => {
511
+ await curve.init('JsonRpc', {}, { gasPrice: 0, chainId: 1 });
512
+
513
+ console.log(await curve.getBalances(['DAI', 'CRV']));
514
+ // [ '9900.0', '100049.744832225238317557' ]
515
+
516
+ const { route, output } = await curve.getBestRouteAndOutput('DAI', 'CRV', '1000');
517
+ // OR await curve.getBestPoolAndOutput('0x6B175474E89094C44Da98b954EedeAC495271d0F', '0xD533a949740bb3306d119CC777fa900bA034cd52', '10000');
518
+ const expected = await curve.routerExchangeExpected('DAI', 'CRV', '1000');
519
+ // OR await curve.exchangeExpected('0x6B175474E89094C44Da98b954EedeAC495271d0F', '0xD533a949740bb3306d119CC777fa900bA034cd52', '10000');
520
+
521
+ console.log(route, output, expected);
522
+ // route = [
523
+ // {
524
+ // poolId: '3pool',
525
+ // poolAddress: '0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7',
526
+ // outputCoinAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',
527
+ // i: 0,
528
+ // j: 2,
529
+ // swapType: 1,
530
+ // swapAddress: '0x0000000000000000000000000000000000000000'
531
+ // },
532
+ // {
533
+ // poolId: 'tricrypto2',
534
+ // poolAddress: '0xD51a44d3FaE010294C616388b506AcdA1bfAAE46',
535
+ // outputCoinAddress: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
536
+ // i: 0,
537
+ // j: 2,
538
+ // swapType: 3,
539
+ // swapAddress: '0x0000000000000000000000000000000000000000'
540
+ // },
541
+ // {
542
+ // poolId: 'crveth',
543
+ // poolAddress: '0x8301AE4fc9c624d1D396cbDAa1ed877821D7C511',
544
+ // outputCoinAddress: '0xd533a949740bb3306d119cc777fa900ba034cd52',
545
+ // i: 0,
546
+ // j: 1,
547
+ // swapType: 3,
548
+ // swapAddress: '0x0000000000000000000000000000000000000000'
549
+ // }
550
+ // ]
551
+ //
552
+ // output = expected = 378.881631202862354937
553
+
554
+ await curve.routerExchange('DAI', 'CRV', '1000')
555
+ // OR await curve.exchange('0x6B175474E89094C44Da98b954EedeAC495271d0F', '0xD533a949740bb3306d119CC777fa900bA034cd52', '10000');
556
+
557
+ console.log(await curve.getBalances(['DAI', 'CRV']));
558
+ // [ '8900.0', '100428.626463428100672494' ]
559
+ })()
560
+ ```
561
+
562
+ ### Single-pool exchange
498
563
 
499
564
  ```ts
500
565
  import curve from "@curvefi/api";
@@ -521,7 +586,7 @@ import curve from "@curvefi/api";
521
586
  })()
522
587
  ```
523
588
 
524
- ## Cross-Asset Exchange
589
+ ### Cross-Asset Exchange
525
590
 
526
591
  ```ts
527
592
  import curve from "@curvefi/api";
@@ -668,6 +733,10 @@ await pool.exchangeWrappedApprove("0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490",
668
733
 
669
734
  ### Exchange
670
735
  ```ts
736
+ // Router
737
+ await curve.routerExchangeisApproved("DAI", "0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3", "1000"); // DAI -> MIM
738
+ await curve.routerExchangeApprove("DAI", "0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3", "1000"); // DAI -> MIM
739
+
671
740
  // Straight
672
741
  await curve.exchangeisApproved("DAI", "0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3", "1000"); // DAI -> MIM
673
742
  await curve.exchangeApprove("DAI", "0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3", "1000"); // DAI -> MIM
@@ -385,6 +385,36 @@
385
385
  "stateMutability": "view",
386
386
  "type": "function"
387
387
  },
388
+ {
389
+ "gas": "278915",
390
+ "inputs": [
391
+ {
392
+ "name": "_route",
393
+ "type": "address[9]"
394
+ },
395
+ {
396
+ "name": "_swap_params",
397
+ "type": "uint256[3][4]"
398
+ },
399
+ {
400
+ "name": "_amount",
401
+ "type": "uint256"
402
+ },
403
+ {
404
+ "name": "_pools",
405
+ "type": "address[4]"
406
+ }
407
+ ],
408
+ "name": "get_exchange_multiple_amount",
409
+ "outputs": [
410
+ {
411
+ "name": "",
412
+ "type": "uint256"
413
+ }
414
+ ],
415
+ "stateMutability": "view",
416
+ "type": "function"
417
+ },
388
418
  {
389
419
  "gas": "2654",
390
420
  "inputs": [
package/lib/curve.js CHANGED
@@ -115,9 +115,9 @@ var Curve = /** @class */ (function () {
115
115
  ) {
116
116
  if (options === void 0) { options = {}; }
117
117
  return __awaiter(this, void 0, void 0, function () {
118
- var cTokens, yTokens, ycTokens, aTokens, network, _a, customAbiTokens, _b, _i, _c, pool, _d, _e, coinAddr, _f, _g, coinAddr, _h, _j, coinAddr, _k, _l, rewardTokenAddr, addressProviderContract, _m;
119
- return __generator(this, function (_o) {
120
- switch (_o.label) {
118
+ var cTokens, yTokens, ycTokens, aTokens, network, _a, customAbiTokens, _b, _i, _c, pool, _d, _e, coinAddr, _f, _g, coinAddr, _h, _j, coinAddr, _k, _l, rewardTokenAddr, _m, _o, _p, _q, _r, addressProviderContract, _s;
119
+ return __generator(this, function (_t) {
120
+ switch (_t.label) {
121
121
  case 0:
122
122
  // JsonRpc provider
123
123
  if (providerType.toLowerCase() === 'JsonRpc'.toLowerCase()) {
@@ -160,8 +160,8 @@ var Curve = /** @class */ (function () {
160
160
  if (_a) return [3 /*break*/, 2];
161
161
  return [4 /*yield*/, this.provider._networkPromise];
162
162
  case 1:
163
- _a = (_o.sent());
164
- _o.label = 2;
163
+ _a = (_t.sent());
164
+ _t.label = 2;
165
165
  case 2:
166
166
  network = _a;
167
167
  console.log("CURVE-JS IS CONNECTED TO NETWORK:", network);
@@ -217,75 +217,100 @@ var Curve = /** @class */ (function () {
217
217
  this.multicallProvider = new ethcall_1.Provider();
218
218
  return [4 /*yield*/, this.multicallProvider.init(this.provider)];
219
219
  case 3:
220
- _o.sent();
220
+ _t.sent();
221
221
  if (!this.signer) return [3 /*break*/, 5];
222
222
  _b = this;
223
223
  return [4 /*yield*/, this.signer.getAddress()];
224
224
  case 4:
225
- _b.signerAddress = _o.sent();
225
+ _b.signerAddress = _t.sent();
226
226
  return [3 /*break*/, 6];
227
227
  case 5:
228
228
  this.signerAddress = '';
229
- _o.label = 6;
229
+ _t.label = 6;
230
230
  case 6:
231
231
  this.feeData = { gasPrice: options.gasPrice, maxFeePerGas: options.maxFeePerGas, maxPriorityFeePerGas: options.maxPriorityFeePerGas };
232
232
  return [4 /*yield*/, this.updateFeeData()];
233
233
  case 7:
234
- _o.sent();
235
- // TODO delete toLowerCase()
236
- for (_i = 0, _c = Object.values(exports.POOLS_DATA); _i < _c.length; _i++) {
237
- pool = _c[_i];
238
- this.contracts[pool.swap_address] = {
239
- contract: new ethers_1.Contract(pool.swap_address, pool.swap_abi, this.signer || this.provider),
240
- multicallContract: new ethcall_1.Contract(pool.swap_address, pool.swap_abi),
234
+ _t.sent();
235
+ _i = 0, _c = Object.values(exports.POOLS_DATA);
236
+ _t.label = 8;
237
+ case 8:
238
+ if (!(_i < _c.length)) return [3 /*break*/, 13];
239
+ pool = _c[_i];
240
+ this.contracts[pool.swap_address] = {
241
+ contract: new ethers_1.Contract(pool.swap_address, pool.swap_abi, this.signer || this.provider),
242
+ multicallContract: new ethcall_1.Contract(pool.swap_address, pool.swap_abi),
243
+ };
244
+ this.contracts[pool.swap_address.toLowerCase()] = {
245
+ contract: new ethers_1.Contract(pool.swap_address, pool.swap_abi, this.signer || this.provider),
246
+ multicallContract: new ethcall_1.Contract(pool.swap_address, pool.swap_abi),
247
+ };
248
+ if (pool.token_address !== pool.swap_address) {
249
+ this.contracts[pool.token_address] = {
250
+ contract: new ethers_1.Contract(pool.token_address, ERC20_json_1.default, this.signer || this.provider),
251
+ multicallContract: new ethcall_1.Contract(pool.token_address, ERC20_json_1.default),
241
252
  };
242
- this.contracts[pool.swap_address.toLowerCase()] = {
243
- contract: new ethers_1.Contract(pool.swap_address, pool.swap_abi, this.signer || this.provider),
244
- multicallContract: new ethcall_1.Contract(pool.swap_address, pool.swap_abi),
253
+ this.contracts[pool.token_address.toLowerCase()] = {
254
+ contract: new ethers_1.Contract(pool.token_address, ERC20_json_1.default, this.signer || this.provider),
255
+ multicallContract: new ethcall_1.Contract(pool.token_address, ERC20_json_1.default),
245
256
  };
246
- if (pool.token_address !== pool.swap_address) {
247
- this.contracts[pool.token_address] = {
248
- contract: new ethers_1.Contract(pool.token_address, ERC20_json_1.default, this.signer || this.provider),
249
- multicallContract: new ethcall_1.Contract(pool.token_address, ERC20_json_1.default),
250
- };
251
- this.contracts[pool.token_address.toLowerCase()] = {
252
- contract: new ethers_1.Contract(pool.token_address, ERC20_json_1.default, this.signer || this.provider),
253
- multicallContract: new ethcall_1.Contract(pool.token_address, ERC20_json_1.default),
254
- };
255
- }
256
- this.contracts[pool.gauge_address] = {
257
- contract: new ethers_1.Contract(pool.gauge_address, pool.gauge_abi, this.signer || this.provider),
258
- multicallContract: new ethcall_1.Contract(pool.gauge_address, pool.gauge_abi),
257
+ }
258
+ this.contracts[pool.gauge_address] = {
259
+ contract: new ethers_1.Contract(pool.gauge_address, pool.gauge_abi, this.signer || this.provider),
260
+ multicallContract: new ethcall_1.Contract(pool.gauge_address, pool.gauge_abi),
261
+ };
262
+ this.contracts[pool.gauge_address.toLowerCase()] = {
263
+ contract: new ethers_1.Contract(pool.gauge_address, pool.gauge_abi, this.signer || this.provider),
264
+ multicallContract: new ethcall_1.Contract(pool.gauge_address, pool.gauge_abi),
265
+ };
266
+ if (pool.deposit_address && this.contracts[pool.deposit_address] === undefined) {
267
+ this.contracts[pool.deposit_address] = {
268
+ contract: new ethers_1.Contract(pool.deposit_address, pool.deposit_abi, this.signer || this.provider),
269
+ multicallContract: new ethcall_1.Contract(pool.deposit_address, pool.deposit_abi),
259
270
  };
260
- this.contracts[pool.gauge_address.toLowerCase()] = {
261
- contract: new ethers_1.Contract(pool.gauge_address, pool.gauge_abi, this.signer || this.provider),
262
- multicallContract: new ethcall_1.Contract(pool.gauge_address, pool.gauge_abi),
271
+ this.contracts[pool.deposit_address.toLowerCase()] = {
272
+ contract: new ethers_1.Contract(pool.deposit_address, pool.deposit_abi, this.signer || this.provider),
273
+ multicallContract: new ethcall_1.Contract(pool.deposit_address, pool.deposit_abi),
263
274
  };
264
- if (pool.deposit_address && this.contracts[pool.deposit_address] === undefined) {
265
- this.contracts[pool.deposit_address] = {
266
- contract: new ethers_1.Contract(pool.deposit_address, pool.deposit_abi, this.signer || this.provider),
267
- multicallContract: new ethcall_1.Contract(pool.deposit_address, pool.deposit_abi),
268
- };
269
- this.contracts[pool.deposit_address.toLowerCase()] = {
270
- contract: new ethers_1.Contract(pool.deposit_address, pool.deposit_abi, this.signer || this.provider),
271
- multicallContract: new ethcall_1.Contract(pool.deposit_address, pool.deposit_abi),
272
- };
273
- }
274
- for (_d = 0, _e = pool.underlying_coin_addresses; _d < _e.length; _d++) {
275
- coinAddr = _e[_d];
275
+ }
276
+ for (_d = 0, _e = pool.underlying_coin_addresses; _d < _e.length; _d++) {
277
+ coinAddr = _e[_d];
278
+ this.contracts[coinAddr] = {
279
+ contract: new ethers_1.Contract(coinAddr, ERC20_json_1.default, this.signer || this.provider),
280
+ multicallContract: new ethcall_1.Contract(coinAddr, ERC20_json_1.default),
281
+ };
282
+ this.contracts[coinAddr.toLowerCase()] = {
283
+ contract: new ethers_1.Contract(coinAddr, ERC20_json_1.default, this.signer || this.provider),
284
+ multicallContract: new ethcall_1.Contract(coinAddr, ERC20_json_1.default),
285
+ };
286
+ }
287
+ for (_f = 0, _g = pool.coin_addresses; _f < _g.length; _f++) {
288
+ coinAddr = _g[_f];
289
+ if (customAbiTokens.includes(coinAddr))
290
+ continue;
291
+ this.contracts[coinAddr] = {
292
+ contract: new ethers_1.Contract(coinAddr, ERC20_json_1.default, this.signer || this.provider),
293
+ multicallContract: new ethcall_1.Contract(coinAddr, ERC20_json_1.default),
294
+ };
295
+ this.contracts[coinAddr.toLowerCase()] = {
296
+ contract: new ethers_1.Contract(coinAddr, ERC20_json_1.default, this.signer || this.provider),
297
+ multicallContract: new ethcall_1.Contract(coinAddr, ERC20_json_1.default),
298
+ };
299
+ }
300
+ // TODO add all coins
301
+ for (_h = 0, _j = pool.coin_addresses; _h < _j.length; _h++) {
302
+ coinAddr = _j[_h];
303
+ if (cTokens.includes(coinAddr)) {
276
304
  this.contracts[coinAddr] = {
277
- contract: new ethers_1.Contract(coinAddr, ERC20_json_1.default, this.signer || this.provider),
278
- multicallContract: new ethcall_1.Contract(coinAddr, ERC20_json_1.default),
305
+ contract: new ethers_1.Contract(coinAddr, cERC20_json_1.default, this.signer || this.provider),
306
+ multicallContract: new ethcall_1.Contract(coinAddr, cERC20_json_1.default),
279
307
  };
280
308
  this.contracts[coinAddr.toLowerCase()] = {
281
- contract: new ethers_1.Contract(coinAddr, ERC20_json_1.default, this.signer || this.provider),
282
- multicallContract: new ethcall_1.Contract(coinAddr, ERC20_json_1.default),
309
+ contract: new ethers_1.Contract(coinAddr, cERC20_json_1.default, this.signer || this.provider),
310
+ multicallContract: new ethcall_1.Contract(coinAddr, cERC20_json_1.default),
283
311
  };
284
312
  }
285
- for (_f = 0, _g = pool.coin_addresses; _f < _g.length; _f++) {
286
- coinAddr = _g[_f];
287
- if (customAbiTokens.includes(coinAddr))
288
- continue;
313
+ if (aTokens.includes(coinAddr)) {
289
314
  this.contracts[coinAddr] = {
290
315
  contract: new ethers_1.Contract(coinAddr, ERC20_json_1.default, this.signer || this.provider),
291
316
  multicallContract: new ethcall_1.Contract(coinAddr, ERC20_json_1.default),
@@ -295,62 +320,56 @@ var Curve = /** @class */ (function () {
295
320
  multicallContract: new ethcall_1.Contract(coinAddr, ERC20_json_1.default),
296
321
  };
297
322
  }
298
- // TODO add all coins
299
- for (_h = 0, _j = pool.coin_addresses; _h < _j.length; _h++) {
300
- coinAddr = _j[_h];
301
- if (cTokens.includes(coinAddr)) {
302
- this.contracts[coinAddr] = {
303
- contract: new ethers_1.Contract(coinAddr, cERC20_json_1.default, this.signer || this.provider),
304
- multicallContract: new ethcall_1.Contract(coinAddr, cERC20_json_1.default),
305
- };
306
- this.contracts[coinAddr.toLowerCase()] = {
307
- contract: new ethers_1.Contract(coinAddr, cERC20_json_1.default, this.signer || this.provider),
308
- multicallContract: new ethcall_1.Contract(coinAddr, cERC20_json_1.default),
309
- };
310
- }
311
- if (aTokens.includes(coinAddr)) {
312
- this.contracts[coinAddr] = {
313
- contract: new ethers_1.Contract(coinAddr, ERC20_json_1.default, this.signer || this.provider),
314
- multicallContract: new ethcall_1.Contract(coinAddr, ERC20_json_1.default),
315
- };
316
- this.contracts[coinAddr.toLowerCase()] = {
317
- contract: new ethers_1.Contract(coinAddr, ERC20_json_1.default, this.signer || this.provider),
318
- multicallContract: new ethcall_1.Contract(coinAddr, ERC20_json_1.default),
319
- };
320
- }
321
- if (yTokens.includes(coinAddr) || ycTokens.includes(coinAddr)) {
322
- this.contracts[coinAddr] = {
323
- contract: new ethers_1.Contract(coinAddr, yERC20_json_1.default, this.signer || this.provider),
324
- multicallContract: new ethcall_1.Contract(coinAddr, yERC20_json_1.default),
325
- };
326
- this.contracts[coinAddr.toLowerCase()] = {
327
- contract: new ethers_1.Contract(coinAddr, yERC20_json_1.default, this.signer || this.provider),
328
- multicallContract: new ethcall_1.Contract(coinAddr, yERC20_json_1.default),
329
- };
330
- }
331
- }
332
- if (pool.reward_contract) {
333
- this.contracts[pool.reward_contract] = {
334
- contract: new ethers_1.Contract(pool.reward_contract, streamer_json_1.default, this.signer || this.provider),
335
- multicallContract: new ethcall_1.Contract(pool.reward_contract, streamer_json_1.default),
336
- };
337
- this.contracts[pool.reward_contract.toLowerCase()] = {
338
- contract: new ethers_1.Contract(pool.reward_contract, streamer_json_1.default, this.signer || this.provider),
339
- multicallContract: new ethcall_1.Contract(pool.reward_contract, streamer_json_1.default),
340
- };
341
- }
342
- for (_k = 0, _l = pool.reward_tokens || []; _k < _l.length; _k++) {
343
- rewardTokenAddr = _l[_k];
344
- this.contracts[rewardTokenAddr] = {
345
- contract: new ethers_1.Contract(rewardTokenAddr, ERC20_json_1.default, this.signer || this.provider),
346
- multicallContract: new ethcall_1.Contract(rewardTokenAddr, ERC20_json_1.default),
323
+ if (yTokens.includes(coinAddr) || ycTokens.includes(coinAddr)) {
324
+ this.contracts[coinAddr] = {
325
+ contract: new ethers_1.Contract(coinAddr, yERC20_json_1.default, this.signer || this.provider),
326
+ multicallContract: new ethcall_1.Contract(coinAddr, yERC20_json_1.default),
347
327
  };
348
- this.contracts[rewardTokenAddr.toLowerCase()] = {
349
- contract: new ethers_1.Contract(rewardTokenAddr, ERC20_json_1.default, this.signer || this.provider),
350
- multicallContract: new ethcall_1.Contract(rewardTokenAddr, ERC20_json_1.default),
328
+ this.contracts[coinAddr.toLowerCase()] = {
329
+ contract: new ethers_1.Contract(coinAddr, yERC20_json_1.default, this.signer || this.provider),
330
+ multicallContract: new ethcall_1.Contract(coinAddr, yERC20_json_1.default),
351
331
  };
352
332
  }
353
333
  }
334
+ if (pool.reward_contract) {
335
+ this.contracts[pool.reward_contract] = {
336
+ contract: new ethers_1.Contract(pool.reward_contract, streamer_json_1.default, this.signer || this.provider),
337
+ multicallContract: new ethcall_1.Contract(pool.reward_contract, streamer_json_1.default),
338
+ };
339
+ this.contracts[pool.reward_contract.toLowerCase()] = {
340
+ contract: new ethers_1.Contract(pool.reward_contract, streamer_json_1.default, this.signer || this.provider),
341
+ multicallContract: new ethcall_1.Contract(pool.reward_contract, streamer_json_1.default),
342
+ };
343
+ }
344
+ _k = 0, _l = pool.reward_tokens || [];
345
+ _t.label = 9;
346
+ case 9:
347
+ if (!(_k < _l.length)) return [3 /*break*/, 12];
348
+ rewardTokenAddr = _l[_k];
349
+ this.contracts[rewardTokenAddr] = {
350
+ contract: new ethers_1.Contract(rewardTokenAddr, ERC20_json_1.default, this.signer || this.provider),
351
+ multicallContract: new ethcall_1.Contract(rewardTokenAddr, ERC20_json_1.default),
352
+ };
353
+ this.contracts[rewardTokenAddr.toLowerCase()] = {
354
+ contract: new ethers_1.Contract(rewardTokenAddr, ERC20_json_1.default, this.signer || this.provider),
355
+ multicallContract: new ethcall_1.Contract(rewardTokenAddr, ERC20_json_1.default),
356
+ };
357
+ _m = exports.DECIMALS_LOWER_CASE;
358
+ _o = rewardTokenAddr.toLowerCase();
359
+ _p = Number;
360
+ _r = (_q = ethers_1.ethers.utils).formatUnits;
361
+ return [4 /*yield*/, this.contracts[rewardTokenAddr].contract.decimals()];
362
+ case 10:
363
+ _m[_o] =
364
+ _p.apply(void 0, [_r.apply(_q, [_t.sent(), 0])]);
365
+ _t.label = 11;
366
+ case 11:
367
+ _k++;
368
+ return [3 /*break*/, 9];
369
+ case 12:
370
+ _i++;
371
+ return [3 /*break*/, 8];
372
+ case 13:
354
373
  this.contracts[exports.ALIASES.crv] = {
355
374
  contract: new ethers_1.Contract(exports.ALIASES.crv, ERC20_json_1.default, this.signer || this.provider),
356
375
  multicallContract: new ethcall_1.Contract(exports.ALIASES.crv, ERC20_json_1.default),
@@ -384,10 +403,10 @@ var Curve = /** @class */ (function () {
384
403
  multicallContract: new ethcall_1.Contract(exports.ALIASES.address_provider, address_provider_json_1.default),
385
404
  };
386
405
  addressProviderContract = this.contracts[exports.ALIASES.address_provider].contract;
387
- _m = exports.ALIASES;
406
+ _s = exports.ALIASES;
388
407
  return [4 /*yield*/, addressProviderContract.get_address(2, this.constantOptions)];
389
- case 8:
390
- _m.registry_exchange = _o.sent();
408
+ case 14:
409
+ _s.registry_exchange = _t.sent();
391
410
  this.contracts[exports.ALIASES.registry_exchange] = {
392
411
  contract: new ethers_1.Contract(exports.ALIASES.registry_exchange, registry_exchange_json_1.default, this.signer || this.provider),
393
412
  multicallContract: new ethcall_1.Contract(exports.ALIASES.registry_exchange, registry_exchange_json_1.default),
package/lib/index.d.ts CHANGED
@@ -58,12 +58,22 @@ declare const curve: {
58
58
  crossAssetExchangeApprove: (inputCoin: string, amount: string) => Promise<string[]>;
59
59
  crossAssetExchange: (inputCoin: string, outputCoin: string, amount: string, maxSlippage?: number) => Promise<string>;
60
60
  getUserPoolList: (address?: string | undefined) => Promise<string[]>;
61
+ getBestRouteAndOutput: (inputCoin: string, outputCoin: string, amount: string) => Promise<{
62
+ route: import("./interfaces").IRouteStep[];
63
+ output: string;
64
+ }>;
65
+ routerExchangeExpected: (inputCoin: string, outputCoin: string, amount: string) => Promise<string>;
66
+ routerExchangeIsApproved: (inputCoin: string, amount: string) => Promise<boolean>;
67
+ routerExchangeApprove: (inputCoin: string, amount: string) => Promise<string[]>;
68
+ routerExchange: (inputCoin: string, outputCoin: string, amount: string, maxSlippage?: number) => Promise<string>;
61
69
  estimateGas: {
62
70
  ensureAllowance: (coins: string[], amounts: string[], spender: string) => Promise<number>;
63
71
  exchangeApprove: (inputCoin: string, outputCoin: string, amount: string) => Promise<number>;
64
72
  exchange: (inputCoin: string, outputCoin: string, amount: string, maxSlippage?: number) => Promise<number>;
65
73
  crossAssetExchangeApprove: (inputCoin: string, amount: string) => Promise<number>;
66
74
  crossAssetExchange: (inputCoin: string, outputCoin: string, amount: string, maxSlippage?: number) => Promise<number>;
75
+ routerExchangeApprove: (inputCoin: string, amount: string) => Promise<number>;
76
+ routerExchange: (inputCoin: string, outputCoin: string, amount: string) => Promise<number>;
67
77
  };
68
78
  boosting: {
69
79
  getCrv: (...addresses: string[] | string[][]) => Promise<string | import("./interfaces").DictInterface<string>>;
package/lib/index.js CHANGED
@@ -115,12 +115,19 @@ var curve = {
115
115
  crossAssetExchangeApprove: pools_1.crossAssetExchangeApprove,
116
116
  crossAssetExchange: pools_1.crossAssetExchange,
117
117
  getUserPoolList: pools_1.getUserPoolList,
118
+ getBestRouteAndOutput: pools_1.getBestRouteAndOutput,
119
+ routerExchangeExpected: pools_1.routerExchangeExpected,
120
+ routerExchangeIsApproved: pools_1.routerExchangeIsApproved,
121
+ routerExchangeApprove: pools_1.routerExchangeApprove,
122
+ routerExchange: pools_1.routerExchange,
118
123
  estimateGas: {
119
124
  ensureAllowance: utils_1.ensureAllowanceEstimateGas,
120
125
  exchangeApprove: pools_1.exchangeApproveEstimateGas,
121
126
  exchange: pools_1.exchangeEstimateGas,
122
127
  crossAssetExchangeApprove: pools_1.crossAssetExchangeApproveEstimateGas,
123
128
  crossAssetExchange: pools_1.crossAssetExchangeEstimateGas,
129
+ routerExchangeApprove: pools_1.routerExchangeApproveEstimateGas,
130
+ routerExchange: pools_1.routerExchangeEstimateGas,
124
131
  },
125
132
  boosting: {
126
133
  getCrv: boosting_1.getCrv,
@@ -134,9 +134,24 @@ export interface ISinglePoolSwapData {
134
134
  poolAddress: string;
135
135
  i: number;
136
136
  j: number;
137
- swapType: 1 | 2 | 3 | 4;
137
+ swapType: 1 | 2 | 3 | 4 | 5;
138
138
  swapAddress: string;
139
139
  }
140
140
  export interface ISinglePoolSwapDataAndOutput extends ISinglePoolSwapData {
141
141
  _output: ethers.BigNumber;
142
142
  }
143
+ export interface IRouteStep {
144
+ poolId: string;
145
+ poolAddress: string;
146
+ outputCoinAddress: string;
147
+ i: number;
148
+ j: number;
149
+ swapType: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
150
+ swapAddress: string;
151
+ }
152
+ export interface IRoute {
153
+ steps: IRouteStep[];
154
+ _output: ethers.BigNumber;
155
+ outputUsd: number;
156
+ txCostUsd: number;
157
+ }
package/lib/pools.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ethers } from "ethers";
2
2
  import BigNumber from 'bignumber.js';
3
- import { DictInterface, RewardsApyInterface } from './interfaces';
3
+ import { DictInterface, IRouteStep, RewardsApyInterface } from './interfaces';
4
4
  export declare class Pool {
5
5
  id: string;
6
6
  name: string;
@@ -254,3 +254,14 @@ export declare const crossAssetExchangeApprove: (inputCoin: string, amount: stri
254
254
  export declare const crossAssetExchangeEstimateGas: (inputCoin: string, outputCoin: string, amount: string, maxSlippage?: number) => Promise<number>;
255
255
  export declare const crossAssetExchange: (inputCoin: string, outputCoin: string, amount: string, maxSlippage?: number) => Promise<string>;
256
256
  export declare const getUserPoolList: (address?: string | undefined) => Promise<string[]>;
257
+ export declare const _findAllRoutes: (inputCoinAddress: string, outputCoinAddress: string) => Promise<IRouteStep[][]>;
258
+ export declare const getBestRouteAndOutput: (inputCoin: string, outputCoin: string, amount: string) => Promise<{
259
+ route: IRouteStep[];
260
+ output: string;
261
+ }>;
262
+ export declare const routerExchangeExpected: (inputCoin: string, outputCoin: string, amount: string) => Promise<string>;
263
+ export declare const routerExchangeIsApproved: (inputCoin: string, amount: string) => Promise<boolean>;
264
+ export declare const routerExchangeApproveEstimateGas: (inputCoin: string, amount: string) => Promise<number>;
265
+ export declare const routerExchangeApprove: (inputCoin: string, amount: string) => Promise<string[]>;
266
+ export declare const routerExchangeEstimateGas: (inputCoin: string, outputCoin: string, amount: string) => Promise<number>;
267
+ export declare const routerExchange: (inputCoin: string, outputCoin: string, amount: string, maxSlippage?: number) => Promise<string>;
package/lib/pools.js CHANGED
@@ -59,9 +59,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
59
59
  return (mod && mod.__esModule) ? mod : { "default": mod };
60
60
  };
61
61
  Object.defineProperty(exports, "__esModule", { value: true });
62
- exports.getUserPoolList = exports.crossAssetExchange = exports.crossAssetExchangeEstimateGas = exports.crossAssetExchangeApprove = exports.crossAssetExchangeApproveEstimateGas = exports.crossAssetExchangeIsApproved = exports.crossAssetExchangeExpected = exports.crossAssetExchangeOutputAndSlippage = exports._crossAssetExchangeInfo = exports._getSmallAmountForCoin = exports.crossAssetExchangeAvailable = exports.exchange = exports.exchangeEstimateGas = exports.exchangeApprove = exports.exchangeApproveEstimateGas = exports.exchangeIsApproved = exports.exchangeExpected = exports.getBestPoolAndOutput = exports.Pool = void 0;
62
+ exports.routerExchange = exports.routerExchangeEstimateGas = exports.routerExchangeApprove = exports.routerExchangeApproveEstimateGas = exports.routerExchangeIsApproved = exports.routerExchangeExpected = exports.getBestRouteAndOutput = exports._findAllRoutes = exports.getUserPoolList = exports.crossAssetExchange = exports.crossAssetExchangeEstimateGas = exports.crossAssetExchangeApprove = exports.crossAssetExchangeApproveEstimateGas = exports.crossAssetExchangeIsApproved = exports.crossAssetExchangeExpected = exports.crossAssetExchangeOutputAndSlippage = exports._crossAssetExchangeInfo = exports._getSmallAmountForCoin = exports.crossAssetExchangeAvailable = exports.exchange = exports.exchangeEstimateGas = exports.exchangeApprove = exports.exchangeApproveEstimateGas = exports.exchangeIsApproved = exports.exchangeExpected = exports.getBestPoolAndOutput = exports.Pool = void 0;
63
63
  var axios_1 = __importDefault(require("axios"));
64
64
  var ethers_1 = require("ethers");
65
+ var memoizee_1 = __importDefault(require("memoizee"));
65
66
  var external_api_1 = require("./external-api");
66
67
  var utils_1 = require("./utils");
67
68
  var curve_1 = require("./curve");
@@ -2025,9 +2026,9 @@ var Pool = /** @class */ (function () {
2025
2026
  switch (_a.label) {
2026
2027
  case 0:
2027
2028
  if (!(this.gauge === ethers_1.ethers.constants.AddressZero)) return [3 /*break*/, 2];
2028
- return [4 /*yield*/, this._balances.apply(this, __spreadArray([__spreadArray(__spreadArray(['lpToken'], this.underlyingCoins, true), this.coins, true), __spreadArray(__spreadArray([this.lpToken], this.underlyingCoinAddresses, true), this.coinAddresses, true)], addresses, false))];
2029
+ return [4 /*yield*/, this._balances.apply(this, __spreadArray([__spreadArray(__spreadArray(['lpToken'], this.underlyingCoinAddresses, true), this.coinAddresses, true), __spreadArray(__spreadArray([this.lpToken], this.underlyingCoinAddresses, true), this.coinAddresses, true)], addresses, false))];
2029
2030
  case 1: return [2 /*return*/, _a.sent()];
2030
- case 2: return [4 /*yield*/, this._balances.apply(this, __spreadArray([__spreadArray(__spreadArray(['lpToken', 'gauge'], this.underlyingCoins, true), this.coins, true), __spreadArray(__spreadArray([this.lpToken, this.gauge], this.underlyingCoinAddresses, true), this.coinAddresses, true)], addresses, false))];
2031
+ case 2: return [4 /*yield*/, this._balances.apply(this, __spreadArray([__spreadArray(__spreadArray(['lpToken', 'gauge'], this.underlyingCoinAddresses, true), this.coinAddresses, true), __spreadArray(__spreadArray([this.lpToken, this.gauge], this.underlyingCoinAddresses, true), this.coinAddresses, true)], addresses, false))];
2031
2032
  case 3: return [2 /*return*/, _a.sent()];
2032
2033
  }
2033
2034
  });
@@ -2059,7 +2060,7 @@ var Pool = /** @class */ (function () {
2059
2060
  return __awaiter(_this, void 0, void 0, function () {
2060
2061
  return __generator(this, function (_a) {
2061
2062
  switch (_a.label) {
2062
- case 0: return [4 /*yield*/, this._balances.apply(this, __spreadArray([this.underlyingCoins, this.underlyingCoinAddresses], addresses, false))];
2063
+ case 0: return [4 /*yield*/, this._balances.apply(this, __spreadArray([this.underlyingCoinAddresses, this.underlyingCoinAddresses], addresses, false))];
2063
2064
  case 1: return [2 /*return*/, _a.sent()];
2064
2065
  }
2065
2066
  });
@@ -2073,7 +2074,7 @@ var Pool = /** @class */ (function () {
2073
2074
  return __awaiter(_this, void 0, void 0, function () {
2074
2075
  return __generator(this, function (_a) {
2075
2076
  switch (_a.label) {
2076
- case 0: return [4 /*yield*/, this._balances.apply(this, __spreadArray([this.coins, this.coinAddresses], addresses, false))];
2077
+ case 0: return [4 /*yield*/, this._balances.apply(this, __spreadArray([this.coinAddresses, this.coinAddresses], addresses, false))];
2077
2078
  case 1: return [2 /*return*/, _a.sent()];
2078
2079
  }
2079
2080
  });
@@ -2087,7 +2088,7 @@ var Pool = /** @class */ (function () {
2087
2088
  return __awaiter(_this, void 0, void 0, function () {
2088
2089
  return __generator(this, function (_a) {
2089
2090
  switch (_a.label) {
2090
- case 0: return [4 /*yield*/, this._balances.apply(this, __spreadArray([__spreadArray(__spreadArray([], this.underlyingCoins, true), this.coins, true), __spreadArray(__spreadArray([], this.underlyingCoinAddresses, true), this.coinAddresses, true)], addresses, false))];
2091
+ case 0: return [4 /*yield*/, this._balances.apply(this, __spreadArray([__spreadArray(__spreadArray([], this.underlyingCoinAddresses, true), this.coinAddresses, true), __spreadArray(__spreadArray([], this.underlyingCoinAddresses, true), this.coinAddresses, true)], addresses, false))];
2091
2092
  case 1: return [2 /*return*/, _a.sent()];
2092
2093
  }
2093
2094
  });
@@ -4180,3 +4181,560 @@ var getUserPoolList = function (address) { return __awaiter(void 0, void 0, void
4180
4181
  });
4181
4182
  }); };
4182
4183
  exports.getUserPoolList = getUserPoolList;
4184
+ // --------- Multi-Pool Exchange ---------
4185
+ // TODO make working or remove
4186
+ var IMBALANCED_POOLS = [];
4187
+ // Inspired by Dijkstra's algorithm
4188
+ var _findAllRoutes = function (inputCoinAddress, outputCoinAddress) { return __awaiter(void 0, void 0, void 0, function () {
4189
+ var ALL_POOLS, basePoolsSet, _i, ALL_POOLS_1, pool, basePoolIds, markedCoins, curCoins, nextCoins, routes, step, _a, curCoins_1, inCoin, _c, ALL_POOLS_2, _d, poolId, poolData, coin_addresses, underlying_coin_addresses, meta_coin_addresses, token_address, is_lending, inCoinIndexes, j, swapType, _e, _f, inCoinRoute, swapType, _h, _j, inCoinRoute, j, tvl, _k, swapType, _l, _m, inCoinRoute, poolAddress, j, tvl, _o, swapType, _p, _q, inCoinRoute, j, tvl, _r, swapType, _s, _t, inCoinRoute, tvl, _u, swapType, _v, _w, inCoinRoute;
4190
+ var _x;
4191
+ var _y, _z, _0, _1, _2, _3, _4, _5;
4192
+ return __generator(this, function (_6) {
4193
+ switch (_6.label) {
4194
+ case 0:
4195
+ inputCoinAddress = inputCoinAddress.toLowerCase();
4196
+ outputCoinAddress = outputCoinAddress.toLowerCase();
4197
+ ALL_POOLS = Object.entries(__assign(__assign(__assign({}, curve_1.POOLS_DATA), curve_1.curve.constants.FACTORY_POOLS_DATA), curve_1.curve.constants.CRYPTO_FACTORY_POOLS_DATA));
4198
+ basePoolsSet = new Set();
4199
+ for (_i = 0, ALL_POOLS_1 = ALL_POOLS; _i < ALL_POOLS_1.length; _i++) {
4200
+ pool = ALL_POOLS_1[_i];
4201
+ if (pool[1].base_pool)
4202
+ basePoolsSet.add(pool[1].base_pool);
4203
+ }
4204
+ basePoolIds = Array.from(basePoolsSet);
4205
+ markedCoins = [];
4206
+ curCoins = [inputCoinAddress];
4207
+ nextCoins = new Set();
4208
+ routes = (_x = {},
4209
+ _x[inputCoinAddress] = [[]],
4210
+ _x);
4211
+ step = 0;
4212
+ _6.label = 1;
4213
+ case 1:
4214
+ if (!(step < 4)) return [3 /*break*/, 21];
4215
+ _a = 0, curCoins_1 = curCoins;
4216
+ _6.label = 2;
4217
+ case 2:
4218
+ if (!(_a < curCoins_1.length)) return [3 /*break*/, 19];
4219
+ inCoin = curCoins_1[_a];
4220
+ _c = 0, ALL_POOLS_2 = ALL_POOLS;
4221
+ _6.label = 3;
4222
+ case 3:
4223
+ if (!(_c < ALL_POOLS_2.length)) return [3 /*break*/, 18];
4224
+ _d = ALL_POOLS_2[_c], poolId = _d[0], poolData = _d[1];
4225
+ coin_addresses = poolData.coin_addresses.map(function (a) { return a.toLowerCase(); });
4226
+ underlying_coin_addresses = poolData.underlying_coin_addresses.map(function (a) { return a.toLowerCase(); });
4227
+ meta_coin_addresses = ((_y = poolData.meta_coin_addresses) === null || _y === void 0 ? void 0 : _y.map(function (a) { return a.toLowerCase(); })) || [];
4228
+ token_address = poolData.token_address.toLowerCase();
4229
+ is_lending = poolData.use_lending.includes(true);
4230
+ inCoinIndexes = {
4231
+ coin: coin_addresses.indexOf(inCoin),
4232
+ underlying_coin: underlying_coin_addresses.indexOf(inCoin),
4233
+ meta_coin: meta_coin_addresses ? meta_coin_addresses.indexOf(inCoin) : -1,
4234
+ };
4235
+ // Find all LP -> underlying coin "swaps" (actually remove_liquidity_one_coin)
4236
+ if (basePoolIds.includes(poolId) && inCoin === token_address) {
4237
+ for (j = 0; j < underlying_coin_addresses.length; j++) {
4238
+ // If this coin already marked or will be marked on the current step, no need to consider it on the next step
4239
+ if (markedCoins.includes(underlying_coin_addresses[j]) || curCoins.includes(underlying_coin_addresses[j]))
4240
+ continue;
4241
+ // Looking for outputCoinAddress only on the final step
4242
+ if (step === 3 && underlying_coin_addresses[j] !== outputCoinAddress)
4243
+ continue;
4244
+ swapType = poolId === 'aave' ? 10 : 9;
4245
+ for (_e = 0, _f = routes[inCoin]; _e < _f.length; _e++) {
4246
+ inCoinRoute = _f[_e];
4247
+ routes[underlying_coin_addresses[j]] = ((_z = routes[underlying_coin_addresses[j]]) !== null && _z !== void 0 ? _z : []).concat([__spreadArray(__spreadArray([], inCoinRoute, true), [
4248
+ {
4249
+ poolId: poolId,
4250
+ poolAddress: poolData.swap_address,
4251
+ outputCoinAddress: underlying_coin_addresses[j],
4252
+ i: 0,
4253
+ j: j,
4254
+ swapType: swapType,
4255
+ swapAddress: ethers_1.ethers.constants.AddressZero,
4256
+ },
4257
+ ], false)]);
4258
+ }
4259
+ nextCoins.add(underlying_coin_addresses[j]);
4260
+ }
4261
+ }
4262
+ // Find all underlying coin -> LP "swaps" (actually add_liquidity)
4263
+ if (basePoolIds.includes(poolId) && underlying_coin_addresses.includes(inCoin)) {
4264
+ // If this coin already marked or will be marked on the current step, no need to consider it on the next step
4265
+ if (markedCoins.includes(token_address) || curCoins.includes(token_address))
4266
+ return [3 /*break*/, 17];
4267
+ // Looking for outputCoinAddress only on the final step
4268
+ if (step === 3 && token_address !== outputCoinAddress)
4269
+ return [3 /*break*/, 17];
4270
+ swapType = is_lending ? 8 : underlying_coin_addresses.length === 2 ? 6 : 7;
4271
+ for (_h = 0, _j = routes[inCoin]; _h < _j.length; _h++) {
4272
+ inCoinRoute = _j[_h];
4273
+ routes[token_address] = ((_0 = routes[token_address]) !== null && _0 !== void 0 ? _0 : []).concat([__spreadArray(__spreadArray([], inCoinRoute, true), [
4274
+ {
4275
+ poolId: poolId,
4276
+ poolAddress: poolData.swap_address,
4277
+ outputCoinAddress: token_address,
4278
+ i: underlying_coin_addresses.indexOf(inCoin),
4279
+ j: 0,
4280
+ swapType: swapType,
4281
+ swapAddress: ethers_1.ethers.constants.AddressZero,
4282
+ },
4283
+ ], false)]);
4284
+ }
4285
+ nextCoins.add(token_address);
4286
+ }
4287
+ // No input coin in this pool --> skip
4288
+ if (inCoinIndexes.coin === -1 && inCoinIndexes.underlying_coin === -1 && inCoinIndexes.meta_coin === -1)
4289
+ return [3 /*break*/, 17];
4290
+ if (!(inCoinIndexes.coin >= 0 && poolId !== "atricrypto3")) return [3 /*break*/, 7];
4291
+ j = 0;
4292
+ _6.label = 4;
4293
+ case 4:
4294
+ if (!(j < coin_addresses.length)) return [3 /*break*/, 7];
4295
+ // If this coin already marked or will be marked on the current step, no need to consider it on the next step
4296
+ if (markedCoins.includes(coin_addresses[j]) || curCoins.includes(coin_addresses[j]))
4297
+ return [3 /*break*/, 6];
4298
+ // Looking for outputCoinAddress only on the final step
4299
+ if (step === 3 && coin_addresses[j] !== outputCoinAddress)
4300
+ return [3 /*break*/, 6];
4301
+ _k = Number;
4302
+ return [4 /*yield*/, (new Pool(poolId)).stats.getTotalLiquidity()];
4303
+ case 5:
4304
+ tvl = _k.apply(void 0, [_6.sent()]);
4305
+ if (tvl === 0)
4306
+ return [3 /*break*/, 6];
4307
+ // Skip imbalanced pools
4308
+ if (IMBALANCED_POOLS.includes(poolId))
4309
+ return [3 /*break*/, 6];
4310
+ swapType = poolData.is_crypto ? 3 : 1;
4311
+ for (_l = 0, _m = routes[inCoin]; _l < _m.length; _l++) {
4312
+ inCoinRoute = _m[_l];
4313
+ routes[coin_addresses[j]] = ((_1 = routes[coin_addresses[j]]) !== null && _1 !== void 0 ? _1 : []).concat([__spreadArray(__spreadArray([], inCoinRoute, true), [
4314
+ {
4315
+ poolId: poolId,
4316
+ poolAddress: poolData.swap_address,
4317
+ outputCoinAddress: coin_addresses[j],
4318
+ i: inCoinIndexes.coin,
4319
+ j: j,
4320
+ swapType: swapType,
4321
+ swapAddress: ethers_1.ethers.constants.AddressZero,
4322
+ },
4323
+ ], false)]);
4324
+ }
4325
+ nextCoins.add(coin_addresses[j]);
4326
+ _6.label = 6;
4327
+ case 6:
4328
+ j++;
4329
+ return [3 /*break*/, 4];
4330
+ case 7:
4331
+ poolAddress = ["eurtusd", "xautusd", "atricrypto3"].includes(poolId) ||
4332
+ (curve_1.curve.chainId === 137 && poolData.is_factory) ? poolData.deposit_address : poolData.swap_address;
4333
+ if (!(coin_addresses.join("|") !== underlying_coin_addresses.join("|") && inCoinIndexes.underlying_coin >= 0)) return [3 /*break*/, 11];
4334
+ j = 0;
4335
+ _6.label = 8;
4336
+ case 8:
4337
+ if (!(j < underlying_coin_addresses.length)) return [3 /*break*/, 11];
4338
+ if (poolId === "atricrypto3" && inCoinIndexes.meta_coin >= 0 && meta_coin_addresses.includes(underlying_coin_addresses[j]))
4339
+ return [3 /*break*/, 10];
4340
+ // If this coin already marked or will be marked on the current step, no need to consider it on the next step
4341
+ if (markedCoins.includes(underlying_coin_addresses[j]) || curCoins.includes(underlying_coin_addresses[j]))
4342
+ return [3 /*break*/, 10];
4343
+ // Looking for outputCoinAddress only on the final step
4344
+ if (step === 3 && underlying_coin_addresses[j] !== outputCoinAddress)
4345
+ return [3 /*break*/, 10];
4346
+ _o = Number;
4347
+ return [4 /*yield*/, (new Pool(poolId)).stats.getTotalLiquidity()];
4348
+ case 9:
4349
+ tvl = _o.apply(void 0, [_6.sent()]);
4350
+ if (tvl === 0)
4351
+ return [3 /*break*/, 10];
4352
+ // Skip imbalanced pools
4353
+ if (IMBALANCED_POOLS.includes(poolId))
4354
+ return [3 /*break*/, 10];
4355
+ swapType = poolData.is_crypto && (poolData.is_fake || poolData.is_meta) ? 4 : poolData.is_crypto ? 3 : 2;
4356
+ for (_p = 0, _q = routes[inCoin]; _p < _q.length; _p++) {
4357
+ inCoinRoute = _q[_p];
4358
+ routes[underlying_coin_addresses[j]] = ((_2 = routes[underlying_coin_addresses[j]]) !== null && _2 !== void 0 ? _2 : []).concat([__spreadArray(__spreadArray([], inCoinRoute, true), [
4359
+ {
4360
+ poolId: poolId,
4361
+ poolAddress: poolAddress,
4362
+ outputCoinAddress: underlying_coin_addresses[j],
4363
+ i: inCoinIndexes.underlying_coin,
4364
+ j: j,
4365
+ swapType: swapType,
4366
+ swapAddress: ethers_1.ethers.constants.AddressZero,
4367
+ },
4368
+ ], false)]);
4369
+ }
4370
+ nextCoins.add(underlying_coin_addresses[j]);
4371
+ _6.label = 10;
4372
+ case 10:
4373
+ j++;
4374
+ return [3 /*break*/, 8];
4375
+ case 11:
4376
+ if (!(inCoinIndexes.coin === 0 && meta_coin_addresses.length > 0 && poolId !== "atricrypto3")) return [3 /*break*/, 15];
4377
+ j = 0;
4378
+ _6.label = 12;
4379
+ case 12:
4380
+ if (!(j < meta_coin_addresses.length)) return [3 /*break*/, 15];
4381
+ // If this coin already marked or will be marked on the current step, no need to consider it on the next step
4382
+ if (markedCoins.includes(meta_coin_addresses[j]) || curCoins.includes(meta_coin_addresses[j]))
4383
+ return [3 /*break*/, 14];
4384
+ // Looking for outputCoinAddress only on the final step
4385
+ if (step === 3 && meta_coin_addresses[j] !== outputCoinAddress)
4386
+ return [3 /*break*/, 14];
4387
+ _r = Number;
4388
+ return [4 /*yield*/, (new Pool(poolId)).stats.getTotalLiquidity()];
4389
+ case 13:
4390
+ tvl = _r.apply(void 0, [_6.sent()]);
4391
+ if (tvl === 0)
4392
+ return [3 /*break*/, 14];
4393
+ // Skip imbalanced pools
4394
+ if (IMBALANCED_POOLS.includes(poolId))
4395
+ return [3 /*break*/, 14];
4396
+ swapType = (curve_1.curve.chainId === 137 && poolData.is_factory) ? 5 : poolData.is_crypto ? 4 : 2;
4397
+ for (_s = 0, _t = routes[inCoin]; _s < _t.length; _s++) {
4398
+ inCoinRoute = _t[_s];
4399
+ routes[meta_coin_addresses[j]] = ((_3 = routes[meta_coin_addresses[j]]) !== null && _3 !== void 0 ? _3 : []).concat([__spreadArray(__spreadArray([], inCoinRoute, true), [
4400
+ {
4401
+ poolId: poolId,
4402
+ poolAddress: poolAddress,
4403
+ outputCoinAddress: meta_coin_addresses[j],
4404
+ i: inCoinIndexes.coin,
4405
+ j: j + 1,
4406
+ swapType: swapType,
4407
+ swapAddress: swapType === 5 ? poolData.swap_address : ethers_1.ethers.constants.AddressZero,
4408
+ },
4409
+ ], false)]);
4410
+ }
4411
+ nextCoins.add(meta_coin_addresses[j]);
4412
+ _6.label = 14;
4413
+ case 14:
4414
+ j++;
4415
+ return [3 /*break*/, 12];
4416
+ case 15:
4417
+ if (!(inCoinIndexes.meta_coin >= 0 && poolId !== "atricrypto3")) return [3 /*break*/, 17];
4418
+ // If this coin already marked or will be marked on the current step, no need to consider it on the next step
4419
+ if (markedCoins.includes(coin_addresses[0]) || curCoins.includes(coin_addresses[0]))
4420
+ return [3 /*break*/, 17];
4421
+ // Looking for outputCoinAddress only on the final step
4422
+ if (step === 3 && coin_addresses[0] !== outputCoinAddress)
4423
+ return [3 /*break*/, 17];
4424
+ _u = Number;
4425
+ return [4 /*yield*/, (new Pool(poolId)).stats.getTotalLiquidity()];
4426
+ case 16:
4427
+ tvl = _u.apply(void 0, [_6.sent()]);
4428
+ if (tvl === 0)
4429
+ return [3 /*break*/, 17];
4430
+ // Skip imbalanced pools
4431
+ if (IMBALANCED_POOLS.includes(poolId))
4432
+ return [3 /*break*/, 17];
4433
+ swapType = (curve_1.curve.chainId === 137 && poolData.is_factory) ? 5 : poolData.is_crypto ? 4 : 2;
4434
+ for (_v = 0, _w = routes[inCoin]; _v < _w.length; _v++) {
4435
+ inCoinRoute = _w[_v];
4436
+ routes[coin_addresses[0]] = ((_4 = routes[coin_addresses[0]]) !== null && _4 !== void 0 ? _4 : []).concat([__spreadArray(__spreadArray([], inCoinRoute, true), [
4437
+ {
4438
+ poolId: poolId,
4439
+ poolAddress: poolAddress,
4440
+ outputCoinAddress: coin_addresses[0],
4441
+ i: inCoinIndexes.meta_coin + 1,
4442
+ j: 0,
4443
+ swapType: swapType,
4444
+ swapAddress: swapType === 5 ? poolData.swap_address : ethers_1.ethers.constants.AddressZero,
4445
+ },
4446
+ ], false)]);
4447
+ nextCoins.add(coin_addresses[0]);
4448
+ }
4449
+ _6.label = 17;
4450
+ case 17:
4451
+ _c++;
4452
+ return [3 /*break*/, 3];
4453
+ case 18:
4454
+ _a++;
4455
+ return [3 /*break*/, 2];
4456
+ case 19:
4457
+ // If target output coin is reached, search is finished. Assumption: the shorter route, the better.
4458
+ if (outputCoinAddress in routes)
4459
+ return [3 /*break*/, 21];
4460
+ markedCoins.push.apply(markedCoins, curCoins);
4461
+ curCoins = Array.from(nextCoins);
4462
+ nextCoins = new Set();
4463
+ _6.label = 20;
4464
+ case 20:
4465
+ step++;
4466
+ return [3 /*break*/, 1];
4467
+ case 21: return [2 /*return*/, (_5 = routes[outputCoinAddress]) !== null && _5 !== void 0 ? _5 : []];
4468
+ }
4469
+ });
4470
+ }); };
4471
+ exports._findAllRoutes = _findAllRoutes;
4472
+ var _getRouteKey = function (route, inputCoinAddress, outputCoinAddress) {
4473
+ var sortedCoins = [inputCoinAddress, outputCoinAddress].sort();
4474
+ var key = "".concat(sortedCoins[0], "-->");
4475
+ for (var _i = 0, _a = route.steps; _i < _a.length; _i++) {
4476
+ var routeStep = _a[_i];
4477
+ key += "".concat(routeStep.poolId, "-->");
4478
+ }
4479
+ key += sortedCoins[1];
4480
+ return key;
4481
+ };
4482
+ var _getExchangeMultipleArgs = function (inputCoinAddress, route) {
4483
+ var _route = [inputCoinAddress];
4484
+ var _swapParams = [];
4485
+ var _factorySwapAddresses = [];
4486
+ for (var _i = 0, _a = route.steps; _i < _a.length; _i++) {
4487
+ var routeStep = _a[_i];
4488
+ _route.push(routeStep.poolAddress, routeStep.outputCoinAddress);
4489
+ _swapParams.push([routeStep.i, routeStep.j, routeStep.swapType]);
4490
+ _factorySwapAddresses.push(routeStep.swapAddress);
4491
+ }
4492
+ _route = _route.concat(Array(9 - _route.length).fill(ethers_1.ethers.constants.AddressZero));
4493
+ _swapParams = _swapParams.concat(Array(4 - _swapParams.length).fill([0, 0, 0]));
4494
+ _factorySwapAddresses = _factorySwapAddresses.concat(Array(4 - _factorySwapAddresses.length).fill(ethers_1.ethers.constants.AddressZero));
4495
+ return { _route: _route, _swapParams: _swapParams, _factorySwapAddresses: _factorySwapAddresses };
4496
+ };
4497
+ var _estimatedGasForDifferentRoutesCache = {};
4498
+ var _estimateGasForDifferentRoutes = function (routes, inputCoinAddress, outputCoinAddress, _amount) { return __awaiter(void 0, void 0, void 0, function () {
4499
+ var contract, gasPromises, value, _i, routes_1, route, routeKey, gasPromise, _a, _route, _swapParams, _factorySwapAddresses, _gasAmounts_2, err_3;
4500
+ var _c;
4501
+ return __generator(this, function (_d) {
4502
+ switch (_d.label) {
4503
+ case 0:
4504
+ inputCoinAddress = inputCoinAddress.toLowerCase();
4505
+ outputCoinAddress = outputCoinAddress.toLowerCase();
4506
+ contract = curve_1.curve.contracts[curve_1.ALIASES.registry_exchange].contract;
4507
+ gasPromises = [];
4508
+ value = (0, utils_1.isEth)(inputCoinAddress) ? _amount : ethers_1.ethers.BigNumber.from(0);
4509
+ for (_i = 0, routes_1 = routes; _i < routes_1.length; _i++) {
4510
+ route = routes_1[_i];
4511
+ routeKey = _getRouteKey(route, inputCoinAddress, outputCoinAddress);
4512
+ gasPromise = void 0;
4513
+ _a = _getExchangeMultipleArgs(inputCoinAddress, route), _route = _a._route, _swapParams = _a._swapParams, _factorySwapAddresses = _a._factorySwapAddresses;
4514
+ if ((((_c = _estimatedGasForDifferentRoutesCache[routeKey]) === null || _c === void 0 ? void 0 : _c.time) || 0) + 3600000 < Date.now()) {
4515
+ gasPromise = contract.estimateGas.exchange_multiple(_route, _swapParams, _amount, 0, _factorySwapAddresses, __assign(__assign({}, curve_1.curve.constantOptions), { value: value }));
4516
+ }
4517
+ else {
4518
+ gasPromise = Promise.resolve(_estimatedGasForDifferentRoutesCache[routeKey].gas);
4519
+ }
4520
+ gasPromises.push(gasPromise);
4521
+ }
4522
+ _d.label = 1;
4523
+ case 1:
4524
+ _d.trys.push([1, 3, , 4]);
4525
+ return [4 /*yield*/, Promise.all(gasPromises)];
4526
+ case 2:
4527
+ _gasAmounts_2 = _d.sent();
4528
+ routes.forEach(function (route, i) {
4529
+ var routeKey = _getRouteKey(route, inputCoinAddress, outputCoinAddress);
4530
+ _estimatedGasForDifferentRoutesCache[routeKey] = { 'gas': _gasAmounts_2[i], 'time': Date.now() };
4531
+ });
4532
+ return [2 /*return*/, _gasAmounts_2.map(function (_g) { return Number(ethers_1.ethers.utils.formatUnits(_g, 0)); })];
4533
+ case 3:
4534
+ err_3 = _d.sent();
4535
+ return [2 /*return*/, routes.map(function () { return 0; })];
4536
+ case 4: return [2 /*return*/];
4537
+ }
4538
+ });
4539
+ }); };
4540
+ var _getBestRouteAndOutput = (0, memoizee_1.default)(function (inputCoinAddress, outputCoinAddress, amount) { return __awaiter(void 0, void 0, void 0, function () {
4541
+ var _a, inputCoinDecimals, outputCoinDecimals, _amount, routesRaw, routes, calls, promises, multicallContract, contract, _i, routesRaw_1, route, _c, _route, _swapParams, _factorySwapAddresses, calls_1, multicallContract_1, _d, routesRaw_2, route, _e, _route, _swapParams, _factorySwapAddresses, _outputAmounts, i, err_4, promises_1, contract_1, _f, routesRaw_3, route, _h, _route, _swapParams, _factorySwapAddresses, res, i, _j, gasAmounts, outputCoinUsdRate, gasData, ethUsdRate, gasPrice, expectedAmounts, expectedAmountsUsd, txCostsUsd;
4542
+ return __generator(this, function (_k) {
4543
+ switch (_k.label) {
4544
+ case 0:
4545
+ _a = (0, utils_1._getCoinDecimals)(inputCoinAddress, outputCoinAddress), inputCoinDecimals = _a[0], outputCoinDecimals = _a[1];
4546
+ _amount = ethers_1.ethers.utils.parseUnits(amount.toString(), inputCoinDecimals);
4547
+ return [4 /*yield*/, (0, exports._findAllRoutes)(inputCoinAddress, outputCoinAddress)];
4548
+ case 1:
4549
+ routesRaw = (_k.sent()).map(function (steps) { return ({ steps: steps, _output: ethers_1.ethers.BigNumber.from(0), outputUsd: 0, txCostUsd: 0 }); });
4550
+ routes = [];
4551
+ calls = [];
4552
+ promises = [];
4553
+ multicallContract = curve_1.curve.contracts[curve_1.ALIASES.registry_exchange].multicallContract;
4554
+ contract = curve_1.curve.contracts[curve_1.ALIASES.registry_exchange].contract;
4555
+ for (_i = 0, routesRaw_1 = routesRaw; _i < routesRaw_1.length; _i++) {
4556
+ route = routesRaw_1[_i];
4557
+ _c = _getExchangeMultipleArgs(inputCoinAddress, route), _route = _c._route, _swapParams = _c._swapParams, _factorySwapAddresses = _c._factorySwapAddresses;
4558
+ calls.push(multicallContract.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses));
4559
+ promises.push(contract.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses, curve_1.curve.constantOptions));
4560
+ }
4561
+ _k.label = 2;
4562
+ case 2:
4563
+ _k.trys.push([2, 4, , 6]);
4564
+ calls_1 = [];
4565
+ multicallContract_1 = curve_1.curve.contracts[curve_1.ALIASES.registry_exchange].multicallContract;
4566
+ for (_d = 0, routesRaw_2 = routesRaw; _d < routesRaw_2.length; _d++) {
4567
+ route = routesRaw_2[_d];
4568
+ _e = _getExchangeMultipleArgs(inputCoinAddress, route), _route = _e._route, _swapParams = _e._swapParams, _factorySwapAddresses = _e._factorySwapAddresses;
4569
+ calls_1.push(multicallContract_1.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses));
4570
+ }
4571
+ return [4 /*yield*/, curve_1.curve.multicallProvider.all(calls_1)];
4572
+ case 3:
4573
+ _outputAmounts = _k.sent();
4574
+ for (i = 0; i < _outputAmounts.length; i++) {
4575
+ routesRaw[i]._output = _outputAmounts[i];
4576
+ routes.push(routesRaw[i]);
4577
+ }
4578
+ return [3 /*break*/, 6];
4579
+ case 4:
4580
+ err_4 = _k.sent();
4581
+ promises_1 = [];
4582
+ contract_1 = curve_1.curve.contracts[curve_1.ALIASES.registry_exchange].contract;
4583
+ for (_f = 0, routesRaw_3 = routesRaw; _f < routesRaw_3.length; _f++) {
4584
+ route = routesRaw_3[_f];
4585
+ _h = _getExchangeMultipleArgs(inputCoinAddress, route), _route = _h._route, _swapParams = _h._swapParams, _factorySwapAddresses = _h._factorySwapAddresses;
4586
+ promises_1.push(contract_1.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses, curve_1.curve.constantOptions));
4587
+ }
4588
+ return [4 /*yield*/, Promise.allSettled(promises_1)];
4589
+ case 5:
4590
+ res = _k.sent();
4591
+ for (i = 0; i < res.length; i++) {
4592
+ if (res[i].status === 'rejected') {
4593
+ console.log("Route ".concat((routesRaw[i].steps.map(function (s) { return s.poolId; })).join(" --> "), " is anavailable"));
4594
+ continue;
4595
+ }
4596
+ routesRaw[i]._output = res[i].value;
4597
+ routes.push(routesRaw[i]);
4598
+ }
4599
+ return [3 /*break*/, 6];
4600
+ case 6:
4601
+ if (routes.length === 0) {
4602
+ return [2 /*return*/, {
4603
+ steps: [],
4604
+ _output: ethers_1.ethers.BigNumber.from(0),
4605
+ outputUsd: 0,
4606
+ txCostUsd: 0,
4607
+ }];
4608
+ }
4609
+ if (routes.length === 1)
4610
+ return [2 /*return*/, routes[0]];
4611
+ return [4 /*yield*/, Promise.all([
4612
+ _estimateGasForDifferentRoutes(routes, inputCoinAddress, outputCoinAddress, _amount),
4613
+ (0, utils_1._getUsdRate)(outputCoinAddress),
4614
+ axios_1.default.get("https://api.curve.fi/api/getGas"),
4615
+ (0, utils_1._getUsdRate)(curve_1.curve.chainId === 137 ? curve_1.COINS.matic : curve_1.COINS.eth),
4616
+ ])];
4617
+ case 7:
4618
+ _j = _k.sent(), gasAmounts = _j[0], outputCoinUsdRate = _j[1], gasData = _j[2], ethUsdRate = _j[3];
4619
+ gasPrice = gasData.data.data.gas.standard;
4620
+ expectedAmounts = (routes).map(function (route) { return Number(ethers_1.ethers.utils.formatUnits(route._output, outputCoinDecimals)); });
4621
+ expectedAmountsUsd = expectedAmounts.map(function (a) { return a * outputCoinUsdRate; });
4622
+ txCostsUsd = gasAmounts.map(function (a) { return ethUsdRate * a * gasPrice / 1e18; });
4623
+ routes.forEach(function (route, i) {
4624
+ route.outputUsd = expectedAmountsUsd[i];
4625
+ route.txCostUsd = txCostsUsd[i];
4626
+ });
4627
+ return [2 /*return*/, routes.reduce(function (route1, route2) { return (route1.outputUsd - route1.txCostUsd) - (route2.outputUsd - route2.txCostUsd) >= 0 ? route1 : route2; })];
4628
+ }
4629
+ });
4630
+ }); }, {
4631
+ promise: true,
4632
+ maxAge: 5 * 60 * 1000, // 5m
4633
+ });
4634
+ var getBestRouteAndOutput = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
4635
+ var _a, inputCoinAddress, outputCoinAddress, outputCoinDecimals, _c, steps, _output;
4636
+ return __generator(this, function (_d) {
4637
+ switch (_d.label) {
4638
+ case 0:
4639
+ _a = (0, utils_1._getCoinAddresses)(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
4640
+ outputCoinDecimals = (0, utils_1._getCoinDecimals)(outputCoinAddress)[0];
4641
+ return [4 /*yield*/, _getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount)];
4642
+ case 1:
4643
+ _c = _d.sent(), steps = _c.steps, _output = _c._output;
4644
+ return [2 /*return*/, { route: steps, output: ethers_1.ethers.utils.formatUnits(_output, outputCoinDecimals) }];
4645
+ }
4646
+ });
4647
+ }); };
4648
+ exports.getBestRouteAndOutput = getBestRouteAndOutput;
4649
+ var routerExchangeExpected = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
4650
+ return __generator(this, function (_a) {
4651
+ switch (_a.label) {
4652
+ case 0: return [4 /*yield*/, (0, exports.getBestRouteAndOutput)(inputCoin, outputCoin, amount)];
4653
+ case 1: return [2 /*return*/, (_a.sent())['output']];
4654
+ }
4655
+ });
4656
+ }); };
4657
+ exports.routerExchangeExpected = routerExchangeExpected;
4658
+ var routerExchangeIsApproved = function (inputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
4659
+ return __generator(this, function (_a) {
4660
+ switch (_a.label) {
4661
+ case 0: return [4 /*yield*/, (0, utils_1.hasAllowance)([inputCoin], [amount], curve_1.curve.signerAddress, curve_1.ALIASES.registry_exchange)];
4662
+ case 1: return [2 /*return*/, _a.sent()];
4663
+ }
4664
+ });
4665
+ }); };
4666
+ exports.routerExchangeIsApproved = routerExchangeIsApproved;
4667
+ var routerExchangeApproveEstimateGas = function (inputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
4668
+ return __generator(this, function (_a) {
4669
+ switch (_a.label) {
4670
+ case 0: return [4 /*yield*/, (0, utils_1.ensureAllowanceEstimateGas)([inputCoin], [amount], curve_1.ALIASES.registry_exchange)];
4671
+ case 1: return [2 /*return*/, _a.sent()];
4672
+ }
4673
+ });
4674
+ }); };
4675
+ exports.routerExchangeApproveEstimateGas = routerExchangeApproveEstimateGas;
4676
+ var routerExchangeApprove = function (inputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
4677
+ return __generator(this, function (_a) {
4678
+ switch (_a.label) {
4679
+ case 0: return [4 /*yield*/, (0, utils_1.ensureAllowance)([inputCoin], [amount], curve_1.ALIASES.registry_exchange)];
4680
+ case 1: return [2 /*return*/, _a.sent()];
4681
+ }
4682
+ });
4683
+ }); };
4684
+ exports.routerExchangeApprove = routerExchangeApprove;
4685
+ var routerExchangeEstimateGas = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
4686
+ var _a, inputCoinAddress, outputCoinAddress, inputCoinDecimals, route, _amount, gas;
4687
+ return __generator(this, function (_c) {
4688
+ switch (_c.label) {
4689
+ case 0:
4690
+ _a = (0, utils_1._getCoinAddresses)(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
4691
+ inputCoinDecimals = (0, utils_1._getCoinDecimals)(inputCoinAddress, outputCoinAddress)[0];
4692
+ return [4 /*yield*/, _getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount)];
4693
+ case 1:
4694
+ route = _c.sent();
4695
+ _amount = ethers_1.ethers.utils.parseUnits(amount, inputCoinDecimals);
4696
+ return [4 /*yield*/, _estimateGasForDifferentRoutes([route], inputCoinAddress, outputCoinAddress, _amount)];
4697
+ case 2:
4698
+ gas = (_c.sent())[0];
4699
+ return [2 /*return*/, gas];
4700
+ }
4701
+ });
4702
+ }); };
4703
+ exports.routerExchangeEstimateGas = routerExchangeEstimateGas;
4704
+ var routerExchange = function (inputCoin, outputCoin, amount, maxSlippage) {
4705
+ if (maxSlippage === void 0) { maxSlippage = 0.01; }
4706
+ return __awaiter(void 0, void 0, void 0, function () {
4707
+ var _a, inputCoinAddress, outputCoinAddress, _c, inputCoinDecimals, outputCoinDecimals, route, _d, _route, _swapParams, _factorySwapAddresses, _amount, minRecvAmountBN, _minRecvAmount, contract, value, gasLimit;
4708
+ return __generator(this, function (_e) {
4709
+ switch (_e.label) {
4710
+ case 0:
4711
+ _a = (0, utils_1._getCoinAddresses)(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
4712
+ _c = (0, utils_1._getCoinDecimals)(inputCoinAddress, outputCoinAddress), inputCoinDecimals = _c[0], outputCoinDecimals = _c[1];
4713
+ return [4 /*yield*/, (0, exports.routerExchangeApprove)(inputCoin, amount)];
4714
+ case 1:
4715
+ _e.sent();
4716
+ return [4 /*yield*/, _getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount)];
4717
+ case 2:
4718
+ route = _e.sent();
4719
+ if (route.steps.length === 0) {
4720
+ throw new Error("This pair can't be exchanged");
4721
+ }
4722
+ _d = _getExchangeMultipleArgs(inputCoinAddress, route), _route = _d._route, _swapParams = _d._swapParams, _factorySwapAddresses = _d._factorySwapAddresses;
4723
+ _amount = ethers_1.ethers.utils.parseUnits(amount, inputCoinDecimals);
4724
+ minRecvAmountBN = (0, utils_1.toBN)(route._output, outputCoinDecimals).times(1 - maxSlippage);
4725
+ _minRecvAmount = (0, utils_1.fromBN)(minRecvAmountBN, outputCoinDecimals);
4726
+ contract = curve_1.curve.contracts[curve_1.ALIASES.registry_exchange].contract;
4727
+ value = (0, utils_1.isEth)(inputCoinAddress) ? _amount : ethers_1.ethers.BigNumber.from(0);
4728
+ return [4 /*yield*/, curve_1.curve.updateFeeData()];
4729
+ case 3:
4730
+ _e.sent();
4731
+ return [4 /*yield*/, contract.estimateGas.exchange_multiple(_route, _swapParams, _amount, _minRecvAmount, _factorySwapAddresses, __assign(__assign({}, curve_1.curve.constantOptions), { value: value }))];
4732
+ case 4:
4733
+ gasLimit = (_e.sent()).mul(curve_1.curve.chainId === 1 ? 130 : 160).div(100);
4734
+ return [4 /*yield*/, contract.exchange_multiple(_route, _swapParams, _amount, _minRecvAmount, _factorySwapAddresses, __assign(__assign({}, curve_1.curve.options), { value: value, gasLimit: gasLimit }))];
4735
+ case 5: return [2 /*return*/, (_e.sent()).hash];
4736
+ }
4737
+ });
4738
+ });
4739
+ };
4740
+ exports.routerExchange = routerExchange;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curvefi/api",
3
- "version": "1.22.0",
3
+ "version": "1.24.1",
4
4
  "description": "JavaScript library for curve.fi",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {