@curvefi/api 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.
@@ -133,6 +133,7 @@ export interface IRouteStep {
133
133
  export interface IRoute_ {
134
134
  steps: IRouteStep[];
135
135
  minTvl: number;
136
+ totalTvl: number;
136
137
  }
137
138
  export interface IRoute {
138
139
  steps: IRouteStep[];
package/lib/router.js CHANGED
@@ -67,11 +67,10 @@ var curve_1 = require("./curve");
67
67
  var utils_1 = require("./utils");
68
68
  var pools_1 = require("./pools");
69
69
  var utils_2 = require("./pools/utils");
70
- var MAX_ROUTES_FOR_ONE_COIN = 3;
71
- var MIN_TVL_THRESHOLD = 5000000;
70
+ // --------------------------- LEGACY ROUTER ---------------------------
72
71
  // Inspired by Dijkstra's algorithm
73
72
  var _findAllRoutesTheShorterTheBetter = function (inputCoinAddress, outputCoinAddress) { return __awaiter(void 0, void 0, void 0, function () {
74
- var ALL_POOLS, basePoolsSet, _i, ALL_POOLS_1, pool, basePoolIds, markedCoins, curCoins, nextCoins, routes, step, _a, curCoins_1, inCoin, _b, ALL_POOLS_2, _c, poolId, poolData, wrapped_coin_addresses, underlying_coin_addresses, base_pool, meta_coin_addresses, token_address, is_lending, inCoinIndexes, j, swapType, _d, _e, inCoinRoute, swapType, _f, _h, inCoinRoute, j, tvl, _j, swapType, _k, _l, inCoinRoute, poolAddress, j, tvl, _m, hasEth, swapType, _o, _p, inCoinRoute;
73
+ var ALL_POOLS, basePoolsSet, _i, ALL_POOLS_1, pool, basePoolIds, markedCoins, curCoins, nextCoins, routes, step, _a, curCoins_1, inCoin, _b, ALL_POOLS_2, _c, poolId, poolData, wrapped_coin_addresses, underlying_coin_addresses, base_pool, meta_coin_addresses, token_address, is_lending, inCoinIndexes, j, swapType, _d, _e, inCoinRoute, flag, swapType, _f, _h, inCoinRoute, j, tvl, _j, swapType, _k, _l, inCoinRoute, poolAddress, j, tvl, _m, hasEth, swapType, _o, _p, inCoinRoute;
75
74
  var _q;
76
75
  var _r, _s, _t, _u, _v, _w;
77
76
  return __generator(this, function (_x) {
@@ -148,29 +147,32 @@ var _findAllRoutesTheShorterTheBetter = function (inputCoinAddress, outputCoinAd
148
147
  }
149
148
  // Wrapped coin -> LP "swaps" (actually add_liquidity)
150
149
  if (basePoolIds.includes(poolId) && wrapped_coin_addresses.includes(inCoin)) {
150
+ flag = true;
151
151
  // If this coin already marked or will be marked on the current step, no need to consider it on the next step
152
152
  if (markedCoins.includes(token_address) || curCoins.includes(token_address))
153
- return [3 /*break*/, 11];
153
+ flag = false;
154
154
  // Looking for outputCoinAddress only on the final step
155
155
  if (step === 3 && token_address !== outputCoinAddress)
156
- return [3 /*break*/, 11];
157
- swapType = is_lending ? 9 : wrapped_coin_addresses.length === 2 ? 7 : 8;
158
- for (_f = 0, _h = routes[inCoin]; _f < _h.length; _f++) {
159
- inCoinRoute = _h[_f];
160
- routes[token_address] = ((_t = routes[token_address]) !== null && _t !== void 0 ? _t : []).concat([__spreadArray(__spreadArray([], inCoinRoute, true), [
161
- {
162
- poolId: poolId,
163
- poolAddress: poolData.swap_address,
164
- inputCoinAddress: inCoin,
165
- outputCoinAddress: token_address,
166
- i: wrapped_coin_addresses.indexOf(inCoin),
167
- j: 0,
168
- swapType: swapType,
169
- swapAddress: ethers_1.ethers.constants.AddressZero,
170
- },
171
- ], false)]);
156
+ flag = false;
157
+ if (flag) {
158
+ swapType = is_lending ? 9 : wrapped_coin_addresses.length === 2 ? 7 : 8;
159
+ for (_f = 0, _h = routes[inCoin]; _f < _h.length; _f++) {
160
+ inCoinRoute = _h[_f];
161
+ routes[token_address] = ((_t = routes[token_address]) !== null && _t !== void 0 ? _t : []).concat([__spreadArray(__spreadArray([], inCoinRoute, true), [
162
+ {
163
+ poolId: poolId,
164
+ poolAddress: poolData.swap_address,
165
+ inputCoinAddress: inCoin,
166
+ outputCoinAddress: token_address,
167
+ i: wrapped_coin_addresses.indexOf(inCoin),
168
+ j: 0,
169
+ swapType: swapType,
170
+ swapAddress: ethers_1.ethers.constants.AddressZero,
171
+ },
172
+ ], false)]);
173
+ }
174
+ nextCoins.add(token_address);
172
175
  }
173
- nextCoins.add(token_address);
174
176
  }
175
177
  // No input coin in this pool --> skip
176
178
  if (inCoinIndexes.wrapped_coin === -1 && inCoinIndexes.underlying_coin === -1 && inCoinIndexes.meta_coin === -1)
@@ -287,249 +289,169 @@ var _findAllRoutesTheShorterTheBetter = function (inputCoinAddress, outputCoinAd
287
289
  });
288
290
  }); };
289
291
  exports._findAllRoutesTheShorterTheBetter = _findAllRoutesTheShorterTheBetter;
292
+ var getNewRoute = function (route, poolId, poolAddress, inputCoinAddress, outputCoinAddress, i, j, swapType, swapAddress, tvl) {
293
+ var routePoolIds = route.steps.map(function (s) { return s.poolId; });
294
+ // Steps <= 4
295
+ if (routePoolIds.length >= 4)
296
+ return { steps: [], minTvl: Infinity, totalTvl: 0 };
297
+ // Exclude such cases as cvxeth -> tricrypto2 -> tricrypto2 -> susd
298
+ if (routePoolIds.includes(poolId))
299
+ return { steps: [], minTvl: Infinity, totalTvl: 0 };
300
+ return {
301
+ steps: __spreadArray(__spreadArray([], route.steps, true), [{ poolId: poolId, poolAddress: poolAddress, inputCoinAddress: inputCoinAddress, outputCoinAddress: outputCoinAddress, i: i, j: j, swapType: swapType, swapAddress: swapAddress }], false),
302
+ minTvl: Math.min(tvl, route.minTvl),
303
+ totalTvl: route.totalTvl + tvl,
304
+ };
305
+ };
306
+ // --------------------------- MAIN ROUTER ---------------------------
307
+ var MAX_ROUTES_FOR_ONE_COIN = 3;
308
+ var filterRoutes = function (routes, inputCoinAddress, sortFn) {
309
+ var routesByPoolIds = routes.map(function (r) { return r.steps.map(function (s) { return s.poolId; }).toString(); });
310
+ return routes
311
+ .filter(function (r) { return r.steps.length > 0; })
312
+ .filter(function (r) { return r.steps[0].inputCoinAddress === inputCoinAddress; }) // Truncated routes
313
+ .filter(function (r, i) { return routesByPoolIds.indexOf(r.steps.map(function (s) { return s.poolId; }).toString()) === i; }) // Route duplications
314
+ .sort(sortFn).slice(0, MAX_ROUTES_FOR_ONE_COIN);
315
+ };
316
+ var sortByTvl = function (a, b) { return b.minTvl - a.minTvl || b.totalTvl - a.totalTvl || a.steps.length - b.steps.length; };
317
+ var sortByLength = function (a, b) { return a.steps.length - b.steps.length || b.minTvl - a.minTvl || b.totalTvl - a.totalTvl; };
290
318
  // Inspired by Dijkstra's algorithm
291
319
  var _findAllRoutesTvl = function (inputCoinAddress, outputCoinAddress) { return __awaiter(void 0, void 0, void 0, function () {
292
- var ALL_POOLS, amplificationCoefficientDict, basePoolsSet, _i, ALL_POOLS_3, pool, basePoolIds, curCoins, nextCoins, routes, step, _loop_1, _a, curCoins_2, inCoin;
293
- var _b;
294
- var _c, _d, _e, _f, _h, _j;
295
- return __generator(this, function (_k) {
296
- switch (_k.label) {
320
+ var ALL_POOLS, amplificationCoefficientDict, basePoolsSet, _i, ALL_POOLS_3, pool, basePoolIds, curCoins, nextCoins, routesByTvl, routesByLength, step, _loop_1, _a, curCoins_2, inCoin, routes;
321
+ var _b, _c;
322
+ var _d, _e, _f, _h, _j, _k, _l, _m, _o, _p, _q, _r;
323
+ return __generator(this, function (_s) {
324
+ switch (_s.label) {
297
325
  case 0:
298
326
  inputCoinAddress = inputCoinAddress.toLowerCase();
299
327
  outputCoinAddress = outputCoinAddress.toLowerCase();
300
328
  ALL_POOLS = Object.entries(__assign(__assign(__assign({}, curve_1.curve.constants.POOLS_DATA), curve_1.curve.constants.FACTORY_POOLS_DATA), curve_1.curve.constants.CRYPTO_FACTORY_POOLS_DATA));
301
329
  return [4 /*yield*/, (0, utils_2._getAmplificationCoefficientsFromApi)()];
302
330
  case 1:
303
- amplificationCoefficientDict = _k.sent();
331
+ amplificationCoefficientDict = _s.sent();
304
332
  basePoolsSet = new Set();
305
333
  for (_i = 0, ALL_POOLS_3 = ALL_POOLS; _i < ALL_POOLS_3.length; _i++) {
306
334
  pool = ALL_POOLS_3[_i];
307
- if (pool[1].base_pool)
308
- basePoolsSet.add(pool[1].base_pool);
335
+ if (pool[1].wrapped_coin_addresses.length < 4)
336
+ basePoolsSet.add(pool[0]);
309
337
  }
310
338
  basePoolIds = Array.from(basePoolsSet);
311
339
  curCoins = [inputCoinAddress];
312
340
  nextCoins = new Set();
313
- routes = (_b = {},
314
- _b[inputCoinAddress] = [{ steps: [], minTvl: Infinity }],
341
+ routesByTvl = (_b = {},
342
+ _b[inputCoinAddress] = [{ steps: [], minTvl: Infinity, totalTvl: 0 }],
315
343
  _b);
344
+ routesByLength = (_c = {},
345
+ _c[inputCoinAddress] = [{ steps: [], minTvl: Infinity, totalTvl: 0 }],
346
+ _c);
316
347
  step = 0;
317
- _k.label = 2;
348
+ _s.label = 2;
318
349
  case 2:
319
350
  if (!(step < 4)) return [3 /*break*/, 8];
320
351
  _loop_1 = function (inCoin) {
321
- var _loop_2, _l, ALL_POOLS_4, _m, poolId, poolData;
322
- return __generator(this, function (_o) {
323
- switch (_o.label) {
352
+ var _loop_2, _t, ALL_POOLS_4, _u, poolId, poolData;
353
+ return __generator(this, function (_v) {
354
+ switch (_v.label) {
324
355
  case 0:
325
356
  _loop_2 = function (poolId, poolData) {
326
- var wrapped_coin_addresses, underlying_coin_addresses, base_pool, meta_coin_addresses, token_address, is_lending, minTvlMultiplier, inCoinIndexes, _loop_3, j, tvl_1, _p, swapType_1, newRoutes, routesByPoolIds_1, _loop_4, j, poolAddress, _loop_5, j;
327
- return __generator(this, function (_q) {
328
- switch (_q.label) {
357
+ var wrapped_coin_addresses, underlying_coin_addresses, base_pool, meta_coin_addresses, token_address, is_lending, tvlMultiplier, inCoinIndexes, tvl, _w, _loop_3, j, swapType_1, newRoutesByTvl, newRoutesByLength, _loop_4, j, poolAddress, _loop_5, j;
358
+ return __generator(this, function (_x) {
359
+ switch (_x.label) {
329
360
  case 0:
330
361
  wrapped_coin_addresses = poolData.wrapped_coin_addresses.map(function (a) { return a.toLowerCase(); });
331
362
  underlying_coin_addresses = poolData.underlying_coin_addresses.map(function (a) { return a.toLowerCase(); });
332
363
  base_pool = poolData.is_meta ? curve_1.curve.constants.POOLS_DATA[poolData.base_pool] : null;
333
364
  meta_coin_addresses = base_pool ? base_pool.underlying_coin_addresses.map(function (a) { return a.toLowerCase(); }) : [];
334
365
  token_address = poolData.token_address.toLowerCase();
335
- is_lending = (_c = poolData.is_lending) !== null && _c !== void 0 ? _c : false;
336
- minTvlMultiplier = poolData.is_crypto ? 1 : ((_d = amplificationCoefficientDict[poolData.swap_address]) !== null && _d !== void 0 ? _d : 1);
366
+ is_lending = (_d = poolData.is_lending) !== null && _d !== void 0 ? _d : false;
367
+ tvlMultiplier = poolData.is_crypto ? 1 : ((_e = amplificationCoefficientDict[poolData.swap_address]) !== null && _e !== void 0 ? _e : 1);
337
368
  inCoinIndexes = {
338
369
  wrapped_coin: wrapped_coin_addresses.indexOf(inCoin),
339
370
  underlying_coin: underlying_coin_addresses.indexOf(inCoin),
340
371
  meta_coin: meta_coin_addresses ? meta_coin_addresses.indexOf(inCoin) : -1,
341
372
  };
342
- // No input coin in this pool --> skip
373
+ // Skip pools which don't contain inCoin
343
374
  if (inCoinIndexes.wrapped_coin === -1 && inCoinIndexes.underlying_coin === -1 && inCoinIndexes.meta_coin === -1 && inCoin !== token_address)
344
375
  return [2 /*return*/, "continue"];
345
- if (!(basePoolIds.includes(poolId) && inCoin === token_address)) return [3 /*break*/, 4];
346
- _loop_3 = function (j) {
347
- var outputCoinIdx, tvl, _r, swapType, newRoutes, routesByPoolIds;
348
- return __generator(this, function (_s) {
349
- switch (_s.label) {
350
- case 0:
351
- // Looking for outputCoinAddress only on the final step
352
- if (step === 3 && underlying_coin_addresses[j] !== outputCoinAddress)
353
- return [2 /*return*/, "continue"];
354
- outputCoinIdx = underlying_coin_addresses.indexOf(outputCoinAddress);
355
- if (outputCoinIdx >= 0 && j !== outputCoinIdx)
356
- return [2 /*return*/, "continue"];
357
- _r = Number;
358
- return [4 /*yield*/, ((0, pools_1.getPool)(poolId)).stats.totalLiquidity()];
359
- case 1:
360
- tvl = _r.apply(void 0, [_s.sent()]);
361
- swapType = poolId === 'aave' ? 11 : 10;
362
- newRoutes = routes[inCoin].map(function (route) {
363
- var routePoolIds = route.steps.map(function (s) { return s.poolId; });
364
- // Steps <= 4
365
- if (routePoolIds.length >= 4)
366
- return { steps: [], minTvl: -1 };
367
- // Exclude such cases as cvxeth -> tricrypto2 -> tricrypto2 -> susd
368
- if (routePoolIds.includes(poolId))
369
- return { steps: [], minTvl: -1 };
370
- return {
371
- steps: __spreadArray(__spreadArray([], route.steps, true), [
372
- {
373
- poolId: poolId,
374
- poolAddress: poolData.swap_address,
375
- inputCoinAddress: inCoin,
376
- outputCoinAddress: underlying_coin_addresses[j],
377
- i: 0,
378
- j: j,
379
- swapType: swapType,
380
- swapAddress: ethers_1.ethers.constants.AddressZero,
381
- },
382
- ], false),
383
- minTvl: Math.min(tvl, route.minTvl * minTvlMultiplier),
384
- };
385
- });
386
- routes[underlying_coin_addresses[j]] = __spreadArray(__spreadArray([], ((_e = routes[underlying_coin_addresses[j]]) !== null && _e !== void 0 ? _e : []), true), newRoutes, true);
387
- routesByPoolIds = routes[underlying_coin_addresses[j]].map(function (r) { return r.steps.map(function (s) { return s.poolId; }).toString(); });
388
- routes[underlying_coin_addresses[j]] = routes[underlying_coin_addresses[j]]
389
- .filter(function (r) { return r.steps.length > 0; })
390
- .filter(function (r) { return r.steps[0].inputCoinAddress === inputCoinAddress; }) // Truncated routes
391
- .filter(function (r, i) { return routesByPoolIds.indexOf(r.steps.map(function (s) { return s.poolId; }).toString()) === i; }) // Route duplications
392
- .sort(function (a, b) { return Math.min(b.minTvl, MIN_TVL_THRESHOLD) - Math.min(a.minTvl, MIN_TVL_THRESHOLD) || a.steps.length - b.steps.length; }).slice(0, MAX_ROUTES_FOR_ONE_COIN);
393
- nextCoins.add(underlying_coin_addresses[j]);
394
- return [2 /*return*/];
395
- }
396
- });
397
- };
398
- j = 0;
399
- _q.label = 1;
376
+ _w = Number;
377
+ return [4 /*yield*/, ((0, pools_1.getPool)(poolId)).stats.totalLiquidity()];
400
378
  case 1:
401
- if (!(j < underlying_coin_addresses.length)) return [3 /*break*/, 4];
402
- return [5 /*yield**/, _loop_3(j)];
403
- case 2:
404
- _q.sent();
405
- _q.label = 3;
406
- case 3:
407
- j++;
408
- return [3 /*break*/, 1];
409
- case 4:
410
- if (!(basePoolIds.includes(poolId) && inCoinIndexes.underlying_coin >= 0)) return [3 /*break*/, 6];
411
- // Looking for outputCoinAddress only on the final step
412
- if (step === 3 && token_address !== outputCoinAddress)
379
+ tvl = _w.apply(void 0, [_x.sent()]) * tvlMultiplier;
380
+ // Skip empty pools
381
+ if (tvl === 0)
413
382
  return [2 /*return*/, "continue"];
414
- _p = Number;
415
- return [4 /*yield*/, ((0, pools_1.getPool)(poolId)).stats.totalLiquidity()];
416
- case 5:
417
- tvl_1 = _p.apply(void 0, [_q.sent()]);
418
- swapType_1 = is_lending ? 9 : underlying_coin_addresses.length === 2 ? 7 : 8;
419
- newRoutes = routes[inCoin].map(function (route) {
420
- var routePoolIds = route.steps.map(function (s) { return s.poolId; });
421
- // Steps <= 4
422
- if (routePoolIds.length >= 4)
423
- return { steps: [], minTvl: -1 };
424
- // Exclude such cases as cvxeth -> tricrypto2 -> tricrypto2 -> susd
425
- if (routePoolIds.includes(poolId))
426
- return { steps: [], minTvl: -1 };
427
- return {
428
- steps: __spreadArray(__spreadArray([], route.steps, true), [
429
- {
430
- poolId: poolId,
431
- poolAddress: poolData.swap_address,
432
- inputCoinAddress: inCoin,
433
- outputCoinAddress: token_address,
434
- i: underlying_coin_addresses.indexOf(inCoin),
435
- j: 0,
436
- swapType: swapType_1,
437
- swapAddress: ethers_1.ethers.constants.AddressZero,
438
- },
439
- ], false),
440
- minTvl: Math.min(tvl_1, route.minTvl * minTvlMultiplier),
383
+ // LP -> wrapped coin "swaps" (actually remove_liquidity_one_coin)
384
+ if (basePoolIds.includes(poolId) && inCoin === token_address) {
385
+ _loop_3 = function (j) {
386
+ // Looking for outputCoinAddress only on the final step
387
+ if (step === 3 && wrapped_coin_addresses[j] !== outputCoinAddress)
388
+ return "continue";
389
+ // Exclude such cases as cvxeth -> tricrypto2 -> tusd -> susd or cvxeth -> tricrypto2 -> susd -> susd
390
+ var outputCoinIdx = wrapped_coin_addresses.indexOf(outputCoinAddress);
391
+ if (outputCoinIdx >= 0 && j !== outputCoinIdx)
392
+ return "continue";
393
+ var swapType = poolId === 'aave' ? 11 : 10;
394
+ var newRoutesByTvl = routesByTvl[inCoin].map(function (route) { return getNewRoute(route, poolId, poolData.swap_address, inCoin, wrapped_coin_addresses[j], 0, j, swapType, ethers_1.ethers.constants.AddressZero, tvl); });
395
+ var newRoutesByLength = routesByLength[inCoin].map(function (route) { return getNewRoute(route, poolId, poolData.swap_address, inCoin, wrapped_coin_addresses[j], 0, j, swapType, ethers_1.ethers.constants.AddressZero, tvl); });
396
+ routesByTvl[wrapped_coin_addresses[j]] = __spreadArray(__spreadArray([], ((_f = routesByTvl[wrapped_coin_addresses[j]]) !== null && _f !== void 0 ? _f : []), true), newRoutesByTvl, true);
397
+ routesByTvl[wrapped_coin_addresses[j]] = filterRoutes(routesByTvl[wrapped_coin_addresses[j]], inputCoinAddress, sortByTvl);
398
+ routesByLength[wrapped_coin_addresses[j]] = __spreadArray(__spreadArray([], ((_h = routesByLength[wrapped_coin_addresses[j]]) !== null && _h !== void 0 ? _h : []), true), newRoutesByLength, true);
399
+ routesByLength[wrapped_coin_addresses[j]] = filterRoutes(routesByLength[wrapped_coin_addresses[j]], inputCoinAddress, sortByLength);
400
+ nextCoins.add(wrapped_coin_addresses[j]);
441
401
  };
442
- });
443
- routes[token_address] = __spreadArray(__spreadArray([], ((_f = routes[token_address]) !== null && _f !== void 0 ? _f : []), true), newRoutes, true);
444
- routesByPoolIds_1 = routes[token_address].map(function (r) { return r.steps.map(function (s) { return s.poolId; }).toString(); });
445
- routes[token_address] = routes[token_address]
446
- .filter(function (r) { return r.steps.length > 0; })
447
- .filter(function (r) { return r.steps[0].inputCoinAddress === inputCoinAddress; }) // Truncated routes
448
- .filter(function (r, i) { return routesByPoolIds_1.indexOf(r.steps.map(function (s) { return s.poolId; }).toString()) === i; }) // Route duplications
449
- .sort(function (a, b) { return Math.min(b.minTvl, MIN_TVL_THRESHOLD) - Math.min(a.minTvl, MIN_TVL_THRESHOLD) || a.steps.length - b.steps.length; }).slice(0, MAX_ROUTES_FOR_ONE_COIN);
450
- nextCoins.add(token_address);
451
- _q.label = 6;
452
- case 6:
453
- if (!(inCoinIndexes.wrapped_coin >= 0 && !poolData.is_fake)) return [3 /*break*/, 10];
454
- _loop_4 = function (j) {
455
- var outputCoinIdx, tvl, _t, swapType, newRoutes, routesByPoolIds;
456
- return __generator(this, function (_u) {
457
- switch (_u.label) {
458
- case 0:
459
- if (j === inCoinIndexes.wrapped_coin)
460
- return [2 /*return*/, "continue"];
461
- // Native swaps spend less gas
462
- if (wrapped_coin_addresses[j] !== outputCoinAddress && wrapped_coin_addresses[j] === curve_1.curve.constants.NATIVE_TOKEN.wrappedAddress)
463
- return [2 /*return*/, "continue"];
464
- // Looking for outputCoinAddress only on the final step
465
- if (step === 3 && wrapped_coin_addresses[j] !== outputCoinAddress)
466
- return [2 /*return*/, "continue"];
467
- outputCoinIdx = wrapped_coin_addresses.indexOf(outputCoinAddress);
468
- if (outputCoinIdx >= 0 && j !== outputCoinIdx)
469
- return [2 /*return*/, "continue"];
470
- _t = Number;
471
- return [4 /*yield*/, ((0, pools_1.getPool)(poolId)).stats.totalLiquidity()];
472
- case 1:
473
- tvl = _t.apply(void 0, [_u.sent()]);
474
- // Skip empty pools
475
- if (tvl === 0)
476
- return [2 /*return*/, "continue"];
477
- swapType = poolData.is_crypto ? 3 : 1;
478
- newRoutes = routes[inCoin].map(function (route) {
479
- var routePoolIds = route.steps.map(function (s) { return s.poolId; });
480
- // Steps <= 4
481
- if (routePoolIds.length >= 4)
482
- return { steps: [], minTvl: -1 };
483
- // Exclude such cases as cvxeth -> tricrypto2 -> tricrypto2 -> susd
484
- if (routePoolIds.includes(poolId))
485
- return { steps: [], minTvl: -1 };
486
- return {
487
- steps: __spreadArray(__spreadArray([], route.steps, true), [
488
- {
489
- poolId: poolId,
490
- poolAddress: poolData.swap_address,
491
- inputCoinAddress: inCoin,
492
- outputCoinAddress: wrapped_coin_addresses[j],
493
- i: inCoinIndexes.wrapped_coin,
494
- j: j,
495
- swapType: swapType,
496
- swapAddress: ethers_1.ethers.constants.AddressZero,
497
- },
498
- ], false),
499
- minTvl: Math.min(tvl, route.minTvl * minTvlMultiplier),
500
- };
501
- });
502
- routes[wrapped_coin_addresses[j]] = __spreadArray(__spreadArray([], ((_h = routes[wrapped_coin_addresses[j]]) !== null && _h !== void 0 ? _h : []), true), newRoutes, true);
503
- routesByPoolIds = routes[wrapped_coin_addresses[j]].map(function (r) { return r.steps.map(function (s) { return s.poolId; }).toString(); });
504
- routes[wrapped_coin_addresses[j]] = routes[wrapped_coin_addresses[j]]
505
- .filter(function (r) { return r.steps.length > 0; })
506
- .filter(function (r) { return r.steps[0].inputCoinAddress === inputCoinAddress; }) // Truncated routes
507
- .filter(function (r, i) { return routesByPoolIds.indexOf(r.steps.map(function (s) { return s.poolId; }).toString()) === i; }) // Route duplications
508
- .sort(function (a, b) { return Math.min(b.minTvl, MIN_TVL_THRESHOLD) - Math.min(a.minTvl, MIN_TVL_THRESHOLD) || a.steps.length - b.steps.length; }).slice(0, MAX_ROUTES_FOR_ONE_COIN);
509
- nextCoins.add(wrapped_coin_addresses[j]);
510
- return [2 /*return*/];
511
- }
512
- });
513
- };
514
- j = 0;
515
- _q.label = 7;
516
- case 7:
517
- if (!(j < wrapped_coin_addresses.length)) return [3 /*break*/, 10];
518
- return [5 /*yield**/, _loop_4(j)];
519
- case 8:
520
- _q.sent();
521
- _q.label = 9;
522
- case 9:
523
- j++;
524
- return [3 /*break*/, 7];
525
- case 10:
402
+ for (j = 0; j < wrapped_coin_addresses.length; j++) {
403
+ _loop_3(j);
404
+ }
405
+ }
406
+ // Wrapped coin -> LP "swaps" (actually add_liquidity)
407
+ if (basePoolIds.includes(poolId) && inCoinIndexes.wrapped_coin >= 0) {
408
+ // Looking for outputCoinAddress only on the final step
409
+ if (!(step === 3 && token_address !== outputCoinAddress)) {
410
+ swapType_1 = is_lending ? 9 : wrapped_coin_addresses.length === 2 ? 7 : 8;
411
+ newRoutesByTvl = routesByTvl[inCoin].map(function (route) { return getNewRoute(route, poolId, poolData.swap_address, inCoin, token_address, wrapped_coin_addresses.indexOf(inCoin), 0, swapType_1, ethers_1.ethers.constants.AddressZero, tvl); });
412
+ newRoutesByLength = routesByLength[inCoin].map(function (route) { return getNewRoute(route, poolId, poolData.swap_address, inCoin, token_address, wrapped_coin_addresses.indexOf(inCoin), 0, swapType_1, ethers_1.ethers.constants.AddressZero, tvl); });
413
+ routesByTvl[token_address] = __spreadArray(__spreadArray([], ((_j = routesByTvl[token_address]) !== null && _j !== void 0 ? _j : []), true), newRoutesByTvl, true);
414
+ routesByTvl[token_address] = filterRoutes(routesByTvl[token_address], inputCoinAddress, sortByTvl);
415
+ routesByLength[token_address] = __spreadArray(__spreadArray([], ((_k = routesByLength[token_address]) !== null && _k !== void 0 ? _k : []), true), newRoutesByLength, true);
416
+ routesByLength[token_address] = filterRoutes(routesByLength[token_address], inputCoinAddress, sortByLength);
417
+ nextCoins.add(token_address);
418
+ }
419
+ }
420
+ // Wrapped swaps
421
+ if (inCoinIndexes.wrapped_coin >= 0 && !poolData.is_fake) {
422
+ _loop_4 = function (j) {
423
+ if (j === inCoinIndexes.wrapped_coin)
424
+ return "continue";
425
+ // Native swaps spend less gas
426
+ if (wrapped_coin_addresses[j] !== outputCoinAddress && wrapped_coin_addresses[j] === curve_1.curve.constants.NATIVE_TOKEN.wrappedAddress)
427
+ return "continue";
428
+ // Looking for outputCoinAddress only on the final step
429
+ if (step === 3 && wrapped_coin_addresses[j] !== outputCoinAddress)
430
+ return "continue";
431
+ // Exclude such cases as cvxeth -> tricrypto2 -> tusd -> susd or cvxeth -> tricrypto2 -> susd -> susd
432
+ var outputCoinIdx = wrapped_coin_addresses.indexOf(outputCoinAddress);
433
+ if (outputCoinIdx >= 0 && j !== outputCoinIdx)
434
+ return "continue";
435
+ var swapType = poolData.is_crypto ? 3 : 1;
436
+ var newRoutesByTvl = routesByTvl[inCoin].map(function (route) { return getNewRoute(route, poolId, poolData.swap_address, inCoin, wrapped_coin_addresses[j], inCoinIndexes.wrapped_coin, j, swapType, ethers_1.ethers.constants.AddressZero, tvl); });
437
+ var newRoutesByLength = routesByLength[inCoin].map(function (route) { return getNewRoute(route, poolId, poolData.swap_address, inCoin, wrapped_coin_addresses[j], inCoinIndexes.wrapped_coin, j, swapType, ethers_1.ethers.constants.AddressZero, tvl); });
438
+ routesByTvl[wrapped_coin_addresses[j]] = __spreadArray(__spreadArray([], ((_l = routesByTvl[wrapped_coin_addresses[j]]) !== null && _l !== void 0 ? _l : []), true), newRoutesByTvl, true);
439
+ routesByTvl[wrapped_coin_addresses[j]] = filterRoutes(routesByTvl[wrapped_coin_addresses[j]], inputCoinAddress, sortByTvl);
440
+ routesByLength[wrapped_coin_addresses[j]] = __spreadArray(__spreadArray([], ((_m = routesByLength[wrapped_coin_addresses[j]]) !== null && _m !== void 0 ? _m : []), true), newRoutesByLength, true);
441
+ routesByLength[wrapped_coin_addresses[j]] = filterRoutes(routesByLength[wrapped_coin_addresses[j]], inputCoinAddress, sortByLength);
442
+ nextCoins.add(wrapped_coin_addresses[j]);
443
+ };
444
+ for (j = 0; j < wrapped_coin_addresses.length; j++) {
445
+ _loop_4(j);
446
+ }
447
+ }
526
448
  poolAddress = (poolData.is_crypto && poolData.is_meta) || ((base_pool === null || base_pool === void 0 ? void 0 : base_pool.is_lending) && poolData.is_factory) ?
527
449
  poolData.deposit_address : poolData.swap_address;
528
- if (!(!poolData.is_plain && inCoinIndexes.underlying_coin >= 0)) return [3 /*break*/, 14];
450
+ if (!(!poolData.is_plain && inCoinIndexes.underlying_coin >= 0)) return [3 /*break*/, 5];
529
451
  _loop_5 = function (j) {
530
- var outputCoinIdx, tvl, _v, hasEth, swapType, newRoutes, routesByPoolIds;
531
- return __generator(this, function (_w) {
532
- switch (_w.label) {
452
+ var outputCoinIdx, tvl_1, _y, hasEth, swapType, newRoutesByTvl, newRoutesByLength;
453
+ return __generator(this, function (_z) {
454
+ switch (_z.label) {
533
455
  case 0:
534
456
  if (j === inCoinIndexes.underlying_coin)
535
457
  return [2 /*return*/, "continue"];
@@ -542,11 +464,11 @@ var _findAllRoutesTvl = function (inputCoinAddress, outputCoinAddress) { return
542
464
  outputCoinIdx = underlying_coin_addresses.indexOf(outputCoinAddress);
543
465
  if (outputCoinIdx >= 0 && j !== outputCoinIdx)
544
466
  return [2 /*return*/, "continue"];
545
- _v = Number;
467
+ _y = Number;
546
468
  return [4 /*yield*/, ((0, pools_1.getPool)(poolId)).stats.totalLiquidity()];
547
469
  case 1:
548
- tvl = _v.apply(void 0, [_w.sent()]);
549
- if (tvl === 0)
470
+ tvl_1 = _y.apply(void 0, [_z.sent()]);
471
+ if (tvl_1 === 0)
550
472
  return [2 /*return*/, "continue"];
551
473
  hasEth = (inCoin === curve_1.curve.constants.NATIVE_TOKEN.address || underlying_coin_addresses[j] === curve_1.curve.constants.NATIVE_TOKEN.address);
552
474
  swapType = (poolData.is_crypto && poolData.is_meta && poolData.is_factory) ? 6
@@ -554,93 +476,70 @@ var _findAllRoutesTvl = function (inputCoinAddress, outputCoinAddress) { return
554
476
  : hasEth ? 3
555
477
  : poolData.is_crypto ? 4
556
478
  : 2;
557
- newRoutes = routes[inCoin].map(function (route) {
558
- var routePoolIds = route.steps.map(function (s) { return s.poolId; });
559
- // Steps <= 4
560
- if (routePoolIds.length >= 4)
561
- return { steps: [], minTvl: -1 };
562
- // Exclude such cases as cvxeth -> tricrypto2 -> tricrypto2 -> susd
563
- if (routePoolIds.includes(poolId))
564
- return { steps: [], minTvl: -1 };
565
- return {
566
- steps: __spreadArray(__spreadArray([], route.steps, true), [
567
- {
568
- poolId: poolId,
569
- poolAddress: poolAddress,
570
- inputCoinAddress: inCoin,
571
- outputCoinAddress: underlying_coin_addresses[j],
572
- i: inCoinIndexes.underlying_coin,
573
- j: j,
574
- swapType: swapType,
575
- swapAddress: (swapType === 5 || swapType === 6) ? poolData.swap_address : ethers_1.ethers.constants.AddressZero,
576
- },
577
- ], false),
578
- minTvl: Math.min(tvl, route.minTvl * minTvlMultiplier),
579
- };
580
- });
581
- routes[underlying_coin_addresses[j]] = __spreadArray(__spreadArray([], ((_j = routes[underlying_coin_addresses[j]]) !== null && _j !== void 0 ? _j : []), true), newRoutes, true);
582
- routesByPoolIds = routes[underlying_coin_addresses[j]].map(function (r) { return r.steps.map(function (s) { return s.poolId; }).toString(); });
583
- routes[underlying_coin_addresses[j]] = routes[underlying_coin_addresses[j]]
584
- .filter(function (r) { return r.steps.length > 0; })
585
- .filter(function (r) { return r.steps[0].inputCoinAddress === inputCoinAddress; }) // Truncated routes
586
- .filter(function (r, i) { return routesByPoolIds.indexOf(r.steps.map(function (s) { return s.poolId; }).toString()) === i; }) // Route duplications
587
- .sort(function (a, b) { return Math.min(b.minTvl, MIN_TVL_THRESHOLD) - Math.min(a.minTvl, MIN_TVL_THRESHOLD) || a.steps.length - b.steps.length; }).slice(0, MAX_ROUTES_FOR_ONE_COIN);
479
+ newRoutesByTvl = routesByTvl[inCoin].map(function (route) { return getNewRoute(route, poolId, poolAddress, inCoin, underlying_coin_addresses[j], inCoinIndexes.underlying_coin, j, swapType, (swapType === 5 || swapType === 6) ? poolData.swap_address : ethers_1.ethers.constants.AddressZero, tvl_1); });
480
+ newRoutesByLength = routesByLength[inCoin].map(function (route) { return getNewRoute(route, poolId, poolAddress, inCoin, underlying_coin_addresses[j], inCoinIndexes.underlying_coin, j, swapType, (swapType === 5 || swapType === 6) ? poolData.swap_address : ethers_1.ethers.constants.AddressZero, tvl_1); });
481
+ routesByTvl[underlying_coin_addresses[j]] = __spreadArray(__spreadArray([], ((_o = routesByTvl[underlying_coin_addresses[j]]) !== null && _o !== void 0 ? _o : []), true), newRoutesByTvl, true);
482
+ routesByTvl[underlying_coin_addresses[j]] = filterRoutes(routesByTvl[underlying_coin_addresses[j]], inputCoinAddress, sortByTvl);
483
+ routesByLength[underlying_coin_addresses[j]] = __spreadArray(__spreadArray([], ((_p = routesByLength[underlying_coin_addresses[j]]) !== null && _p !== void 0 ? _p : []), true), newRoutesByLength, true);
484
+ routesByLength[underlying_coin_addresses[j]] = filterRoutes(routesByLength[underlying_coin_addresses[j]], inputCoinAddress, sortByLength);
588
485
  nextCoins.add(underlying_coin_addresses[j]);
589
486
  return [2 /*return*/];
590
487
  }
591
488
  });
592
489
  };
593
490
  j = 0;
594
- _q.label = 11;
595
- case 11:
596
- if (!(j < underlying_coin_addresses.length)) return [3 /*break*/, 14];
491
+ _x.label = 2;
492
+ case 2:
493
+ if (!(j < underlying_coin_addresses.length)) return [3 /*break*/, 5];
597
494
  return [5 /*yield**/, _loop_5(j)];
598
- case 12:
599
- _q.sent();
600
- _q.label = 13;
601
- case 13:
495
+ case 3:
496
+ _x.sent();
497
+ _x.label = 4;
498
+ case 4:
602
499
  j++;
603
- return [3 /*break*/, 11];
604
- case 14: return [2 /*return*/];
500
+ return [3 /*break*/, 2];
501
+ case 5: return [2 /*return*/];
605
502
  }
606
503
  });
607
504
  };
608
- _l = 0, ALL_POOLS_4 = ALL_POOLS;
609
- _o.label = 1;
505
+ _t = 0, ALL_POOLS_4 = ALL_POOLS;
506
+ _v.label = 1;
610
507
  case 1:
611
- if (!(_l < ALL_POOLS_4.length)) return [3 /*break*/, 4];
612
- _m = ALL_POOLS_4[_l], poolId = _m[0], poolData = _m[1];
508
+ if (!(_t < ALL_POOLS_4.length)) return [3 /*break*/, 4];
509
+ _u = ALL_POOLS_4[_t], poolId = _u[0], poolData = _u[1];
613
510
  return [5 /*yield**/, _loop_2(poolId, poolData)];
614
511
  case 2:
615
- _o.sent();
616
- _o.label = 3;
512
+ _v.sent();
513
+ _v.label = 3;
617
514
  case 3:
618
- _l++;
515
+ _t++;
619
516
  return [3 /*break*/, 1];
620
517
  case 4: return [2 /*return*/];
621
518
  }
622
519
  });
623
520
  };
624
521
  _a = 0, curCoins_2 = curCoins;
625
- _k.label = 3;
522
+ _s.label = 3;
626
523
  case 3:
627
524
  if (!(_a < curCoins_2.length)) return [3 /*break*/, 6];
628
525
  inCoin = curCoins_2[_a];
629
526
  return [5 /*yield**/, _loop_1(inCoin)];
630
527
  case 4:
631
- _k.sent();
632
- _k.label = 5;
528
+ _s.sent();
529
+ _s.label = 5;
633
530
  case 5:
634
531
  _a++;
635
532
  return [3 /*break*/, 3];
636
533
  case 6:
637
534
  curCoins = Array.from(nextCoins);
638
535
  nextCoins = new Set();
639
- _k.label = 7;
536
+ _s.label = 7;
640
537
  case 7:
641
538
  step++;
642
539
  return [3 /*break*/, 2];
643
- case 8: return [2 /*return*/, routes[outputCoinAddress] ? routes[outputCoinAddress].map(function (r) { return r.steps; }) : []];
540
+ case 8:
541
+ routes = __spreadArray(__spreadArray([], ((_q = routesByTvl[outputCoinAddress]) !== null && _q !== void 0 ? _q : []), true), ((_r = routesByLength[outputCoinAddress]) !== null && _r !== void 0 ? _r : []), true);
542
+ return [2 /*return*/, routes.map(function (r) { return r.steps; })];
644
543
  }
645
544
  });
646
545
  }); };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curvefi/api",
3
- "version": "2.19.1",
3
+ "version": "2.20.0",
4
4
  "description": "JavaScript library for curve.fi",
5
5
  "main": "lib/index.js",
6
6
  "author": "Macket",