@curvefi/api 2.31.1 → 2.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/lib/boosting.js +385 -135
  2. package/lib/constants/abis/stable_calc.json +151 -0
  3. package/lib/constants/abis/wbeth/swap.json +1086 -0
  4. package/lib/constants/aliases.js +33 -11
  5. package/lib/constants/coins/arbitrum.js +5 -5
  6. package/lib/constants/coins/aurora.js +5 -5
  7. package/lib/constants/coins/avalanche.js +6 -6
  8. package/lib/constants/coins/celo.js +5 -5
  9. package/lib/constants/coins/ethereum.js +10 -9
  10. package/lib/constants/coins/fantom.js +7 -7
  11. package/lib/constants/coins/kava.js +5 -5
  12. package/lib/constants/coins/moonbeam.js +5 -5
  13. package/lib/constants/coins/optimism.js +5 -5
  14. package/lib/constants/coins/polygon.js +6 -6
  15. package/lib/constants/coins/xdai.js +5 -5
  16. package/lib/constants/pools/arbitrum.js +1 -1
  17. package/lib/constants/pools/aurora.js +1 -1
  18. package/lib/constants/pools/avalanche.js +1 -1
  19. package/lib/constants/pools/celo.js +1 -1
  20. package/lib/constants/pools/ethereum.js +26 -1
  21. package/lib/constants/pools/fantom.js +1 -1
  22. package/lib/constants/pools/kava.js +1 -1
  23. package/lib/constants/pools/moonbeam.js +1 -1
  24. package/lib/constants/pools/optimism.js +1 -1
  25. package/lib/constants/pools/polygon.js +1 -1
  26. package/lib/constants/pools/xdai.js +1 -1
  27. package/lib/constants/utils.d.ts +1 -1
  28. package/lib/constants/utils.js +19 -18
  29. package/lib/curve.js +507 -281
  30. package/lib/external-api.js +132 -45
  31. package/lib/factory/common.js +3 -3
  32. package/lib/factory/constants-crypto.js +21 -21
  33. package/lib/factory/constants.js +32 -31
  34. package/lib/factory/deploy.js +336 -176
  35. package/lib/factory/factory-api.js +256 -180
  36. package/lib/factory/factory-crypto.js +309 -163
  37. package/lib/factory/factory.d.ts +1 -1
  38. package/lib/factory/factory.js +336 -186
  39. package/lib/index.js +98 -44
  40. package/lib/interfaces.d.ts +1 -1
  41. package/lib/pools/PoolTemplate.js +2882 -1511
  42. package/lib/pools/mixins/common.js +106 -22
  43. package/lib/pools/mixins/depositBalancedAmountsMixins.js +131 -48
  44. package/lib/pools/mixins/depositMixins.js +413 -144
  45. package/lib/pools/mixins/depositWrappedMixins.js +223 -72
  46. package/lib/pools/mixins/poolBalancesMixin.js +98 -22
  47. package/lib/pools/mixins/swapMixins.js +347 -125
  48. package/lib/pools/mixins/swapWrappedMixins.js +270 -88
  49. package/lib/pools/mixins/withdrawExpectedMixins.js +104 -23
  50. package/lib/pools/mixins/withdrawImbalanceMixins.js +316 -97
  51. package/lib/pools/mixins/withdrawImbalanceWrappedMixins.js +187 -51
  52. package/lib/pools/mixins/withdrawMixins.js +385 -122
  53. package/lib/pools/mixins/withdrawOneCoinExpectedMixins.js +88 -16
  54. package/lib/pools/mixins/withdrawOneCoinMixins.js +386 -123
  55. package/lib/pools/mixins/withdrawOneCoinWrappedExpectedMixins.js +62 -8
  56. package/lib/pools/mixins/withdrawOneCoinWrappedMixins.js +185 -53
  57. package/lib/pools/mixins/withdrawWrappedMixins.js +185 -50
  58. package/lib/pools/poolConstructor.js +25 -5
  59. package/lib/pools/utils.js +488 -298
  60. package/lib/router.js +636 -378
  61. package/lib/utils.js +675 -354
  62. package/package.json +1 -1
package/lib/router.js CHANGED
@@ -1,3 +1,59 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
+ return new (P || (P = Promise))(function (resolve, reject) {
15
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
19
+ });
20
+ };
21
+ var __generator = (this && this.__generator) || function (thisArg, body) {
22
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
23
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
24
+ function verb(n) { return function (v) { return step([n, v]); }; }
25
+ function step(op) {
26
+ if (f) throw new TypeError("Generator is already executing.");
27
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
28
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
29
+ if (y = 0, t) op = [op[0] & 2, t.value];
30
+ switch (op[0]) {
31
+ case 0: case 1: t = op; break;
32
+ case 4: _.label++; return { value: op[1], done: false };
33
+ case 5: _.label++; y = op[1]; op = [0]; continue;
34
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
35
+ default:
36
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
37
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
38
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
39
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
40
+ if (t[2]) _.ops.pop();
41
+ _.trys.pop(); continue;
42
+ }
43
+ op = body.call(thisArg, _);
44
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
45
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
+ }
47
+ };
48
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
49
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
50
+ if (ar || !(i in from)) {
51
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
52
+ ar[i] = from[i];
53
+ }
54
+ }
55
+ return to.concat(ar || Array.prototype.slice.call(from));
56
+ };
1
57
  import axios from "axios";
2
58
  import memoize from "memoizee";
3
59
  import { ethers } from "ethers";
@@ -5,8 +61,8 @@ import { curve } from "./curve.js";
5
61
  import { _getCoinAddresses, _getCoinDecimals, _getUsdRate, ensureAllowance, ensureAllowanceEstimateGas, fromBN, hasAllowance, isEth, toBN, BN, parseUnits, _cutZeros, ETH_ADDRESS, _get_small_x, _get_price_impact, } from "./utils.js";
6
62
  import { getPool } from "./pools/index.js";
7
63
  import { _getAmplificationCoefficientsFromApi } from "./pools/utils.js";
8
- const getNewRoute = (routeTvl, poolId, poolAddress, inputCoinAddress, outputCoinAddress, i, j, swapType, swapAddress, tvl) => {
9
- const routePoolIds = routeTvl.route.map((s) => s.poolId);
64
+ var getNewRoute = function (routeTvl, poolId, poolAddress, inputCoinAddress, outputCoinAddress, i, j, swapType, swapAddress, tvl) {
65
+ var routePoolIds = routeTvl.route.map(function (s) { return s.poolId; });
10
66
  // Steps <= 4
11
67
  if (routePoolIds.length >= 4)
12
68
  return { route: [], minTvl: Infinity, totalTvl: 0 };
@@ -14,15 +70,16 @@ const getNewRoute = (routeTvl, poolId, poolAddress, inputCoinAddress, outputCoin
14
70
  if (routePoolIds.includes(poolId))
15
71
  return { route: [], minTvl: Infinity, totalTvl: 0 };
16
72
  return {
17
- route: [...routeTvl.route, { poolId, poolAddress, inputCoinAddress, outputCoinAddress, i, j, swapType, swapAddress }],
73
+ route: __spreadArray(__spreadArray([], routeTvl.route, true), [{ poolId: poolId, poolAddress: poolAddress, inputCoinAddress: inputCoinAddress, outputCoinAddress: outputCoinAddress, i: i, j: j, swapType: swapType, swapAddress: swapAddress }], false),
18
74
  minTvl: Math.min(tvl, routeTvl.minTvl),
19
75
  totalTvl: routeTvl.totalTvl + tvl,
20
76
  };
21
77
  };
22
78
  // TODO REMOVE IT!!!
23
- const filterMaticFactory83Route = (routes) => {
24
- return routes.filter((r) => {
25
- for (const step of r.route) {
79
+ var filterMaticFactory83Route = function (routes) {
80
+ return routes.filter(function (r) {
81
+ for (var _i = 0, _a = r.route; _i < _a.length; _i++) {
82
+ var step = _a[_i];
26
83
  if (step.poolId === "factory-crypto-83" && step.inputCoinAddress === curve.constants.NATIVE_TOKEN.address)
27
84
  return false;
28
85
  }
@@ -30,213 +87,296 @@ const filterMaticFactory83Route = (routes) => {
30
87
  });
31
88
  };
32
89
  // TODO REMOVE IT!!!
33
- const filterAvax = (routes) => {
34
- return routes.filter((r) => {
35
- for (const step of r.route) {
90
+ var filterAvax = function (routes) {
91
+ return routes.filter(function (r) {
92
+ for (var _i = 0, _a = r.route; _i < _a.length; _i++) {
93
+ var step = _a[_i];
36
94
  if (step.poolId == 'avaxcrypto' && step.swapType == 4 && (step.i === 3 || step.j === 3))
37
95
  return false;
38
96
  }
39
97
  return true;
40
98
  });
41
99
  };
42
- const MAX_ROUTES_FOR_ONE_COIN = 3;
43
- const filterRoutes = (routes, inputCoinAddress, sortFn) => {
100
+ var MAX_ROUTES_FOR_ONE_COIN = 3;
101
+ var filterRoutes = function (routes, inputCoinAddress, sortFn) {
44
102
  // TODO REMOVE IT!!!
45
103
  if (curve.chainId === 137)
46
104
  routes = filterMaticFactory83Route(routes);
47
105
  if (curve.chainId === 43114)
48
106
  routes = filterAvax(routes);
49
107
  return routes
50
- .filter((r) => r.route.length > 0)
51
- .filter((r) => r.route[0].inputCoinAddress === inputCoinAddress) // Truncated routes
52
- .filter((r, i, _routes) => {
53
- const routesByPoolIds = _routes.map((r) => r.route.map((s) => s.poolId).toString());
54
- return routesByPoolIds.indexOf(r.route.map((s) => s.poolId).toString()) === i;
108
+ .filter(function (r) { return r.route.length > 0; })
109
+ .filter(function (r) { return r.route[0].inputCoinAddress === inputCoinAddress; }) // Truncated routes
110
+ .filter(function (r, i, _routes) {
111
+ var routesByPoolIds = _routes.map(function (r) { return r.route.map(function (s) { return s.poolId; }).toString(); });
112
+ return routesByPoolIds.indexOf(r.route.map(function (s) { return s.poolId; }).toString()) === i;
55
113
  }) // Route duplications
56
114
  .sort(sortFn).slice(0, MAX_ROUTES_FOR_ONE_COIN);
57
115
  };
58
- const sortByTvl = (a, b) => b.minTvl - a.minTvl || b.totalTvl - a.totalTvl || a.route.length - b.route.length;
59
- const sortByLength = (a, b) => a.route.length - b.route.length || b.minTvl - a.minTvl || b.totalTvl - a.totalTvl;
116
+ var sortByTvl = function (a, b) { return b.minTvl - a.minTvl || b.totalTvl - a.totalTvl || a.route.length - b.route.length; };
117
+ var sortByLength = function (a, b) { return a.route.length - b.route.length || b.minTvl - a.minTvl || b.totalTvl - a.totalTvl; };
60
118
  // Inspired by Dijkstra's algorithm
61
- const _findAllRoutes = async (inputCoinAddress, outputCoinAddress) => {
62
- inputCoinAddress = inputCoinAddress.toLowerCase();
63
- outputCoinAddress = outputCoinAddress.toLowerCase();
64
- const ALL_POOLS = Object.entries({
65
- ...curve.constants.POOLS_DATA,
66
- ...curve.constants.FACTORY_POOLS_DATA,
67
- ...curve.constants.CRYPTO_FACTORY_POOLS_DATA,
68
- });
69
- const amplificationCoefficientDict = await _getAmplificationCoefficientsFromApi();
70
- // Coins we are searching routes for on the current step
71
- let curCoins = [inputCoinAddress];
72
- // Coins we will search routes for on the next step
73
- let nextCoins = new Set();
74
- // Routes for all coins found
75
- const routesByTvl = {
76
- [inputCoinAddress]: [{ route: [], minTvl: Infinity, totalTvl: 0 }],
77
- };
78
- const routesByLength = {
79
- [inputCoinAddress]: [{ route: [], minTvl: Infinity, totalTvl: 0 }],
80
- };
81
- // No more than 4 steps (swaps)
82
- for (let step = 0; step < 4; step++) {
83
- for (const inCoin of curCoins) {
84
- if (curve.chainId !== 42220 && [curve.constants.NATIVE_TOKEN.address, curve.constants.NATIVE_TOKEN.wrappedAddress].includes(inCoin)) { // Exclude Celo
85
- const outCoin = inCoin === curve.constants.NATIVE_TOKEN.address ? curve.constants.NATIVE_TOKEN.wrappedAddress : curve.constants.NATIVE_TOKEN.address;
86
- const newRoutesByTvl = routesByTvl[inCoin].map((route) => getNewRoute(route, "wrapper", curve.constants.NATIVE_TOKEN.wrappedAddress, inCoin, outCoin, 0, 0, 15, curve.constants.ZERO_ADDRESS, Infinity));
87
- const newRoutesByLength = routesByLength[inCoin].map((route) => getNewRoute(route, "wrapper", curve.constants.NATIVE_TOKEN.wrappedAddress, inCoin, outCoin, 0, 0, 15, curve.constants.ZERO_ADDRESS, Infinity));
88
- routesByTvl[outCoin] = [...(routesByTvl[outCoin] ?? []), ...newRoutesByTvl];
89
- routesByTvl[outCoin] = filterRoutes(routesByTvl[outCoin], inputCoinAddress, sortByTvl);
90
- routesByLength[outCoin] = [...(routesByLength[outCoin] ?? []), ...newRoutesByLength];
91
- routesByLength[outCoin] = filterRoutes(routesByLength[outCoin], inputCoinAddress, sortByLength);
92
- nextCoins.add(outCoin);
93
- }
94
- for (const [poolId, poolData] of ALL_POOLS) {
95
- const wrapped_coin_addresses = poolData.wrapped_coin_addresses.map((a) => a.toLowerCase());
96
- const underlying_coin_addresses = poolData.underlying_coin_addresses.map((a) => a.toLowerCase());
97
- const base_pool = poolData.is_meta ? curve.constants.POOLS_DATA[poolData.base_pool] : null;
98
- const meta_coin_addresses = base_pool ? base_pool.underlying_coin_addresses.map((a) => a.toLowerCase()) : [];
99
- const token_address = poolData.token_address.toLowerCase();
100
- const is_aave_like_lending = poolData.is_lending && wrapped_coin_addresses.length === 3 && !poolData.deposit_address;
101
- const tvlMultiplier = poolData.is_crypto ? 1 : (amplificationCoefficientDict[poolData.swap_address] ?? 1);
102
- const inCoinIndexes = {
103
- wrapped_coin: wrapped_coin_addresses.indexOf(inCoin),
104
- underlying_coin: underlying_coin_addresses.indexOf(inCoin),
105
- meta_coin: meta_coin_addresses ? meta_coin_addresses.indexOf(inCoin) : -1,
119
+ var _findAllRoutes = function (inputCoinAddress, outputCoinAddress) { return __awaiter(void 0, void 0, void 0, function () {
120
+ var ALL_POOLS, amplificationCoefficientDict, curCoins, nextCoins, routesByTvl, routesByLength, step, _loop_1, _i, curCoins_1, inCoin, routes;
121
+ var _a, _b;
122
+ var _c, _d, _e, _f, _h, _j, _k, _l, _m, _o, _p, _q, _r;
123
+ return __generator(this, function (_s) {
124
+ switch (_s.label) {
125
+ case 0:
126
+ inputCoinAddress = inputCoinAddress.toLowerCase();
127
+ outputCoinAddress = outputCoinAddress.toLowerCase();
128
+ ALL_POOLS = Object.entries(__assign(__assign(__assign({}, curve.constants.POOLS_DATA), curve.constants.FACTORY_POOLS_DATA), curve.constants.CRYPTO_FACTORY_POOLS_DATA));
129
+ return [4 /*yield*/, _getAmplificationCoefficientsFromApi()];
130
+ case 1:
131
+ amplificationCoefficientDict = _s.sent();
132
+ curCoins = [inputCoinAddress];
133
+ nextCoins = new Set();
134
+ routesByTvl = (_a = {},
135
+ _a[inputCoinAddress] = [{ route: [], minTvl: Infinity, totalTvl: 0 }],
136
+ _a);
137
+ routesByLength = (_b = {},
138
+ _b[inputCoinAddress] = [{ route: [], minTvl: Infinity, totalTvl: 0 }],
139
+ _b);
140
+ step = 0;
141
+ _s.label = 2;
142
+ case 2:
143
+ if (!(step < 4)) return [3 /*break*/, 8];
144
+ _loop_1 = function (inCoin) {
145
+ var outCoin_1, newRoutesByTvl, newRoutesByLength, _loop_2, _t, ALL_POOLS_1, _u, poolId, poolData;
146
+ return __generator(this, function (_v) {
147
+ switch (_v.label) {
148
+ case 0:
149
+ if (curve.chainId !== 42220 && [curve.constants.NATIVE_TOKEN.address, curve.constants.NATIVE_TOKEN.wrappedAddress].includes(inCoin)) { // Exclude Celo
150
+ outCoin_1 = inCoin === curve.constants.NATIVE_TOKEN.address ? curve.constants.NATIVE_TOKEN.wrappedAddress : curve.constants.NATIVE_TOKEN.address;
151
+ newRoutesByTvl = routesByTvl[inCoin].map(function (route) { return getNewRoute(route, "wrapper", curve.constants.NATIVE_TOKEN.wrappedAddress, inCoin, outCoin_1, 0, 0, 15, curve.constants.ZERO_ADDRESS, Infinity); });
152
+ newRoutesByLength = routesByLength[inCoin].map(function (route) { return getNewRoute(route, "wrapper", curve.constants.NATIVE_TOKEN.wrappedAddress, inCoin, outCoin_1, 0, 0, 15, curve.constants.ZERO_ADDRESS, Infinity); });
153
+ routesByTvl[outCoin_1] = __spreadArray(__spreadArray([], ((_c = routesByTvl[outCoin_1]) !== null && _c !== void 0 ? _c : []), true), newRoutesByTvl, true);
154
+ routesByTvl[outCoin_1] = filterRoutes(routesByTvl[outCoin_1], inputCoinAddress, sortByTvl);
155
+ routesByLength[outCoin_1] = __spreadArray(__spreadArray([], ((_d = routesByLength[outCoin_1]) !== null && _d !== void 0 ? _d : []), true), newRoutesByLength, true);
156
+ routesByLength[outCoin_1] = filterRoutes(routesByLength[outCoin_1], inputCoinAddress, sortByLength);
157
+ nextCoins.add(outCoin_1);
158
+ }
159
+ _loop_2 = function (poolId, poolData) {
160
+ var wrapped_coin_addresses, underlying_coin_addresses, base_pool, meta_coin_addresses, token_address, is_aave_like_lending, tvlMultiplier, inCoinIndexes, tvl, _w, _x, poolAddress, coin_addresses, _loop_3, j, inCoinIndex, swapType_1, newRoutesByTvl, newRoutesByLength, _loop_4, j, _loop_5, j;
161
+ return __generator(this, function (_y) {
162
+ switch (_y.label) {
163
+ case 0:
164
+ wrapped_coin_addresses = poolData.wrapped_coin_addresses.map(function (a) { return a.toLowerCase(); });
165
+ underlying_coin_addresses = poolData.underlying_coin_addresses.map(function (a) { return a.toLowerCase(); });
166
+ base_pool = poolData.is_meta ? curve.constants.POOLS_DATA[poolData.base_pool] : null;
167
+ meta_coin_addresses = base_pool ? base_pool.underlying_coin_addresses.map(function (a) { return a.toLowerCase(); }) : [];
168
+ token_address = poolData.token_address.toLowerCase();
169
+ is_aave_like_lending = poolData.is_lending && wrapped_coin_addresses.length === 3 && !poolData.deposit_address;
170
+ tvlMultiplier = poolData.is_crypto ? 1 : ((_e = amplificationCoefficientDict[poolData.swap_address]) !== null && _e !== void 0 ? _e : 1);
171
+ inCoinIndexes = {
172
+ wrapped_coin: wrapped_coin_addresses.indexOf(inCoin),
173
+ underlying_coin: underlying_coin_addresses.indexOf(inCoin),
174
+ meta_coin: meta_coin_addresses ? meta_coin_addresses.indexOf(inCoin) : -1,
175
+ };
176
+ // Skip pools which don't contain inCoin
177
+ if (inCoinIndexes.wrapped_coin === -1 && inCoinIndexes.underlying_coin === -1 && inCoinIndexes.meta_coin === -1 && inCoin !== token_address)
178
+ return [2 /*return*/, "continue"];
179
+ if (!poolId.startsWith('factory-crvusd-')) return [3 /*break*/, 1];
180
+ _w = 500000 * 100;
181
+ return [3 /*break*/, 3];
182
+ case 1:
183
+ _x = Number;
184
+ return [4 /*yield*/, (getPool(poolId)).stats.totalLiquidity()];
185
+ case 2:
186
+ _w = _x.apply(void 0, [_y.sent()]) * tvlMultiplier;
187
+ _y.label = 3;
188
+ case 3:
189
+ tvl = _w;
190
+ // Skip empty pools
191
+ if (tvl === 0)
192
+ return [2 /*return*/, "continue"];
193
+ poolAddress = poolData.is_fake ? poolData.deposit_address : poolData.swap_address;
194
+ coin_addresses = (is_aave_like_lending || poolData.is_fake) ? underlying_coin_addresses : wrapped_coin_addresses;
195
+ // LP -> wrapped coin (underlying for lending or fake pool) "swaps" (actually remove_liquidity_one_coin)
196
+ if (coin_addresses.length < 6 && inCoin === token_address) {
197
+ _loop_3 = function (j) {
198
+ // Looking for outputCoinAddress only on the final step
199
+ if (step === 3 && coin_addresses[j] !== outputCoinAddress)
200
+ return "continue";
201
+ // Exclude such cases as cvxeth -> tricrypto2 -> tusd -> susd or cvxeth -> tricrypto2 -> susd -> susd
202
+ var outputCoinIdx = coin_addresses.indexOf(outputCoinAddress);
203
+ if (outputCoinIdx >= 0 && j !== outputCoinIdx)
204
+ return "continue";
205
+ var swapType = poolData.is_crypto ? 14 : is_aave_like_lending ? 13 : 12;
206
+ var newRoutesByTvl = routesByTvl[inCoin].map(function (route) { return getNewRoute(route, poolId, poolAddress, inCoin, coin_addresses[j], 0, j, swapType, curve.constants.ZERO_ADDRESS, tvl); });
207
+ var newRoutesByLength = routesByLength[inCoin].map(function (route) { return getNewRoute(route, poolId, poolAddress, inCoin, coin_addresses[j], 0, j, swapType, curve.constants.ZERO_ADDRESS, tvl); });
208
+ routesByTvl[coin_addresses[j]] = __spreadArray(__spreadArray([], ((_f = routesByTvl[coin_addresses[j]]) !== null && _f !== void 0 ? _f : []), true), newRoutesByTvl, true);
209
+ routesByTvl[coin_addresses[j]] = filterRoutes(routesByTvl[coin_addresses[j]], inputCoinAddress, sortByTvl);
210
+ routesByLength[coin_addresses[j]] = __spreadArray(__spreadArray([], ((_h = routesByLength[coin_addresses[j]]) !== null && _h !== void 0 ? _h : []), true), newRoutesByLength, true);
211
+ routesByLength[coin_addresses[j]] = filterRoutes(routesByLength[coin_addresses[j]], inputCoinAddress, sortByLength);
212
+ nextCoins.add(coin_addresses[j]);
213
+ };
214
+ for (j = 0; j < coin_addresses.length; j++) {
215
+ _loop_3(j);
216
+ }
217
+ }
218
+ inCoinIndex = (is_aave_like_lending || poolData.is_fake) ? inCoinIndexes.underlying_coin : inCoinIndexes.wrapped_coin;
219
+ if (coin_addresses.length < 6 && inCoinIndex >= 0) {
220
+ // Looking for outputCoinAddress only on the final step
221
+ if (!(step === 3 && token_address !== outputCoinAddress)) {
222
+ swapType_1 = is_aave_like_lending ? 9
223
+ : coin_addresses.length === 2 ? 7
224
+ : coin_addresses.length === 3 ? 8
225
+ : coin_addresses.length === 4 ? 10 : 11;
226
+ newRoutesByTvl = routesByTvl[inCoin].map(function (route) { return getNewRoute(route, poolId, poolAddress, inCoin, token_address, coin_addresses.indexOf(inCoin), 0, swapType_1, curve.constants.ZERO_ADDRESS, tvl); });
227
+ newRoutesByLength = routesByLength[inCoin].map(function (route) { return getNewRoute(route, poolId, poolAddress, inCoin, token_address, coin_addresses.indexOf(inCoin), 0, swapType_1, curve.constants.ZERO_ADDRESS, tvl); });
228
+ routesByTvl[token_address] = __spreadArray(__spreadArray([], ((_j = routesByTvl[token_address]) !== null && _j !== void 0 ? _j : []), true), newRoutesByTvl, true);
229
+ routesByTvl[token_address] = filterRoutes(routesByTvl[token_address], inputCoinAddress, sortByTvl);
230
+ routesByLength[token_address] = __spreadArray(__spreadArray([], ((_k = routesByLength[token_address]) !== null && _k !== void 0 ? _k : []), true), newRoutesByLength, true);
231
+ routesByLength[token_address] = filterRoutes(routesByLength[token_address], inputCoinAddress, sortByLength);
232
+ nextCoins.add(token_address);
233
+ }
234
+ }
235
+ // Wrapped swaps
236
+ if (inCoinIndexes.wrapped_coin >= 0 && !poolData.is_fake) {
237
+ _loop_4 = function (j) {
238
+ if (j === inCoinIndexes.wrapped_coin)
239
+ return "continue";
240
+ // Native swaps spend less gas
241
+ // TODO uncomment
242
+ // if (wrapped_coin_addresses[j] !== outputCoinAddress && wrapped_coin_addresses[j] === curve.constants.NATIVE_TOKEN.wrappedAddress) continue;
243
+ // Looking for outputCoinAddress only on the final step
244
+ if (step === 3 && wrapped_coin_addresses[j] !== outputCoinAddress)
245
+ return "continue";
246
+ // Exclude such cases as cvxeth -> tricrypto2 -> tusd -> susd or cvxeth -> tricrypto2 -> susd -> susd
247
+ var outputCoinIdx = wrapped_coin_addresses.indexOf(outputCoinAddress);
248
+ if (outputCoinIdx >= 0 && j !== outputCoinIdx)
249
+ return "continue";
250
+ var swapType = poolData.is_crypto ? 3 : 1;
251
+ var newRoutesByTvl = routesByTvl[inCoin].map(function (route) { return getNewRoute(route, poolId, poolData.swap_address, inCoin, wrapped_coin_addresses[j], inCoinIndexes.wrapped_coin, j, swapType, curve.constants.ZERO_ADDRESS, tvl); });
252
+ var newRoutesByLength = routesByLength[inCoin].map(function (route) { return getNewRoute(route, poolId, poolData.swap_address, inCoin, wrapped_coin_addresses[j], inCoinIndexes.wrapped_coin, j, swapType, curve.constants.ZERO_ADDRESS, tvl); });
253
+ routesByTvl[wrapped_coin_addresses[j]] = __spreadArray(__spreadArray([], ((_l = routesByTvl[wrapped_coin_addresses[j]]) !== null && _l !== void 0 ? _l : []), true), newRoutesByTvl, true);
254
+ routesByTvl[wrapped_coin_addresses[j]] = filterRoutes(routesByTvl[wrapped_coin_addresses[j]], inputCoinAddress, sortByTvl);
255
+ routesByLength[wrapped_coin_addresses[j]] = __spreadArray(__spreadArray([], ((_m = routesByLength[wrapped_coin_addresses[j]]) !== null && _m !== void 0 ? _m : []), true), newRoutesByLength, true);
256
+ routesByLength[wrapped_coin_addresses[j]] = filterRoutes(routesByLength[wrapped_coin_addresses[j]], inputCoinAddress, sortByLength);
257
+ nextCoins.add(wrapped_coin_addresses[j]);
258
+ };
259
+ for (j = 0; j < wrapped_coin_addresses.length; j++) {
260
+ _loop_4(j);
261
+ }
262
+ }
263
+ // Only for underlying swaps
264
+ poolAddress = (poolData.is_crypto && poolData.is_meta) || ((base_pool === null || base_pool === void 0 ? void 0 : base_pool.is_lending) && poolData.is_factory) ?
265
+ poolData.deposit_address : poolData.swap_address;
266
+ if (!(!poolData.is_plain && inCoinIndexes.underlying_coin >= 0)) return [3 /*break*/, 7];
267
+ _loop_5 = function (j) {
268
+ var outputCoinIdx, tvl_1, _z, hasEth, swapType, newRoutesByTvl, newRoutesByLength;
269
+ return __generator(this, function (_0) {
270
+ switch (_0.label) {
271
+ case 0:
272
+ if (j === inCoinIndexes.underlying_coin)
273
+ return [2 /*return*/, "continue"];
274
+ // Don't swap metacoins since they can be swapped directly in base pool
275
+ if (inCoinIndexes.meta_coin >= 0 && meta_coin_addresses.includes(underlying_coin_addresses[j]))
276
+ return [2 /*return*/, "continue"];
277
+ // Looking for outputCoinAddress only on the final step
278
+ if (step === 3 && underlying_coin_addresses[j] !== outputCoinAddress)
279
+ return [2 /*return*/, "continue"];
280
+ outputCoinIdx = underlying_coin_addresses.indexOf(outputCoinAddress);
281
+ if (outputCoinIdx >= 0 && j !== outputCoinIdx)
282
+ return [2 /*return*/, "continue"];
283
+ _z = Number;
284
+ return [4 /*yield*/, (getPool(poolId)).stats.totalLiquidity()];
285
+ case 1:
286
+ tvl_1 = _z.apply(void 0, [_0.sent()]);
287
+ if (tvl_1 === 0)
288
+ return [2 /*return*/, "continue"];
289
+ hasEth = (inCoin === curve.constants.NATIVE_TOKEN.address || underlying_coin_addresses[j] === curve.constants.NATIVE_TOKEN.address);
290
+ swapType = (poolData.is_crypto && poolData.is_meta && poolData.is_factory) ? 6
291
+ : ((base_pool === null || base_pool === void 0 ? void 0 : base_pool.is_lending) && poolData.is_factory) ? 5
292
+ : hasEth && poolId !== 'avaxcrypto' ? 3
293
+ : poolData.is_crypto ? 4
294
+ : 2;
295
+ 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 : curve.constants.ZERO_ADDRESS, tvl_1); });
296
+ 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 : curve.constants.ZERO_ADDRESS, tvl_1); });
297
+ routesByTvl[underlying_coin_addresses[j]] = __spreadArray(__spreadArray([], ((_o = routesByTvl[underlying_coin_addresses[j]]) !== null && _o !== void 0 ? _o : []), true), newRoutesByTvl, true);
298
+ routesByTvl[underlying_coin_addresses[j]] = filterRoutes(routesByTvl[underlying_coin_addresses[j]], inputCoinAddress, sortByTvl);
299
+ routesByLength[underlying_coin_addresses[j]] = __spreadArray(__spreadArray([], ((_p = routesByLength[underlying_coin_addresses[j]]) !== null && _p !== void 0 ? _p : []), true), newRoutesByLength, true);
300
+ routesByLength[underlying_coin_addresses[j]] = filterRoutes(routesByLength[underlying_coin_addresses[j]], inputCoinAddress, sortByLength);
301
+ nextCoins.add(underlying_coin_addresses[j]);
302
+ return [2 /*return*/];
303
+ }
304
+ });
305
+ };
306
+ j = 0;
307
+ _y.label = 4;
308
+ case 4:
309
+ if (!(j < underlying_coin_addresses.length)) return [3 /*break*/, 7];
310
+ return [5 /*yield**/, _loop_5(j)];
311
+ case 5:
312
+ _y.sent();
313
+ _y.label = 6;
314
+ case 6:
315
+ j++;
316
+ return [3 /*break*/, 4];
317
+ case 7: return [2 /*return*/];
318
+ }
319
+ });
320
+ };
321
+ _t = 0, ALL_POOLS_1 = ALL_POOLS;
322
+ _v.label = 1;
323
+ case 1:
324
+ if (!(_t < ALL_POOLS_1.length)) return [3 /*break*/, 4];
325
+ _u = ALL_POOLS_1[_t], poolId = _u[0], poolData = _u[1];
326
+ return [5 /*yield**/, _loop_2(poolId, poolData)];
327
+ case 2:
328
+ _v.sent();
329
+ _v.label = 3;
330
+ case 3:
331
+ _t++;
332
+ return [3 /*break*/, 1];
333
+ case 4: return [2 /*return*/];
334
+ }
335
+ });
106
336
  };
107
- // Skip pools which don't contain inCoin
108
- if (inCoinIndexes.wrapped_coin === -1 && inCoinIndexes.underlying_coin === -1 && inCoinIndexes.meta_coin === -1 && inCoin !== token_address)
109
- continue;
110
- const tvl = Number(await (getPool(poolId)).stats.totalLiquidity()) * tvlMultiplier;
111
- // Skip empty pools
112
- if (tvl === 0)
113
- continue;
114
- let poolAddress = poolData.is_fake ? poolData.deposit_address : poolData.swap_address;
115
- const coin_addresses = (is_aave_like_lending || poolData.is_fake) ? underlying_coin_addresses : wrapped_coin_addresses;
116
- // LP -> wrapped coin (underlying for lending or fake pool) "swaps" (actually remove_liquidity_one_coin)
117
- if (coin_addresses.length < 6 && inCoin === token_address) {
118
- for (let j = 0; j < coin_addresses.length; j++) {
119
- // Looking for outputCoinAddress only on the final step
120
- if (step === 3 && coin_addresses[j] !== outputCoinAddress)
121
- continue;
122
- // Exclude such cases as cvxeth -> tricrypto2 -> tusd -> susd or cvxeth -> tricrypto2 -> susd -> susd
123
- const outputCoinIdx = coin_addresses.indexOf(outputCoinAddress);
124
- if (outputCoinIdx >= 0 && j !== outputCoinIdx)
125
- continue;
126
- const swapType = poolData.is_crypto ? 14 : is_aave_like_lending ? 13 : 12;
127
- const newRoutesByTvl = routesByTvl[inCoin].map((route) => getNewRoute(route, poolId, poolAddress, inCoin, coin_addresses[j], 0, j, swapType, curve.constants.ZERO_ADDRESS, tvl));
128
- const newRoutesByLength = routesByLength[inCoin].map((route) => getNewRoute(route, poolId, poolAddress, inCoin, coin_addresses[j], 0, j, swapType, curve.constants.ZERO_ADDRESS, tvl));
129
- routesByTvl[coin_addresses[j]] = [...(routesByTvl[coin_addresses[j]] ?? []), ...newRoutesByTvl];
130
- routesByTvl[coin_addresses[j]] = filterRoutes(routesByTvl[coin_addresses[j]], inputCoinAddress, sortByTvl);
131
- routesByLength[coin_addresses[j]] = [...(routesByLength[coin_addresses[j]] ?? []), ...newRoutesByLength];
132
- routesByLength[coin_addresses[j]] = filterRoutes(routesByLength[coin_addresses[j]], inputCoinAddress, sortByLength);
133
- nextCoins.add(coin_addresses[j]);
134
- }
135
- }
136
- // Wrapped coin (underlying for lending or fake pool) -> LP "swaps" (actually add_liquidity)
137
- const inCoinIndex = (is_aave_like_lending || poolData.is_fake) ? inCoinIndexes.underlying_coin : inCoinIndexes.wrapped_coin;
138
- if (coin_addresses.length < 6 && inCoinIndex >= 0) {
139
- // Looking for outputCoinAddress only on the final step
140
- if (!(step === 3 && token_address !== outputCoinAddress)) {
141
- const swapType = is_aave_like_lending ? 9
142
- : coin_addresses.length === 2 ? 7
143
- : coin_addresses.length === 3 ? 8
144
- : coin_addresses.length === 4 ? 10 : 11;
145
- const newRoutesByTvl = routesByTvl[inCoin].map((route) => getNewRoute(route, poolId, poolAddress, inCoin, token_address, coin_addresses.indexOf(inCoin), 0, swapType, curve.constants.ZERO_ADDRESS, tvl));
146
- const newRoutesByLength = routesByLength[inCoin].map((route) => getNewRoute(route, poolId, poolAddress, inCoin, token_address, coin_addresses.indexOf(inCoin), 0, swapType, curve.constants.ZERO_ADDRESS, tvl));
147
- routesByTvl[token_address] = [...(routesByTvl[token_address] ?? []), ...newRoutesByTvl];
148
- routesByTvl[token_address] = filterRoutes(routesByTvl[token_address], inputCoinAddress, sortByTvl);
149
- routesByLength[token_address] = [...(routesByLength[token_address] ?? []), ...newRoutesByLength];
150
- routesByLength[token_address] = filterRoutes(routesByLength[token_address], inputCoinAddress, sortByLength);
151
- nextCoins.add(token_address);
152
- }
153
- }
154
- // Wrapped swaps
155
- if (inCoinIndexes.wrapped_coin >= 0 && !poolData.is_fake) {
156
- for (let j = 0; j < wrapped_coin_addresses.length; j++) {
157
- if (j === inCoinIndexes.wrapped_coin)
158
- continue;
159
- // Native swaps spend less gas
160
- // TODO uncomment
161
- // if (wrapped_coin_addresses[j] !== outputCoinAddress && wrapped_coin_addresses[j] === curve.constants.NATIVE_TOKEN.wrappedAddress) continue;
162
- // Looking for outputCoinAddress only on the final step
163
- if (step === 3 && wrapped_coin_addresses[j] !== outputCoinAddress)
164
- continue;
165
- // Exclude such cases as cvxeth -> tricrypto2 -> tusd -> susd or cvxeth -> tricrypto2 -> susd -> susd
166
- const outputCoinIdx = wrapped_coin_addresses.indexOf(outputCoinAddress);
167
- if (outputCoinIdx >= 0 && j !== outputCoinIdx)
168
- continue;
169
- const swapType = poolData.is_crypto ? 3 : 1;
170
- const newRoutesByTvl = routesByTvl[inCoin].map((route) => getNewRoute(route, poolId, poolData.swap_address, inCoin, wrapped_coin_addresses[j], inCoinIndexes.wrapped_coin, j, swapType, curve.constants.ZERO_ADDRESS, tvl));
171
- const newRoutesByLength = routesByLength[inCoin].map((route) => getNewRoute(route, poolId, poolData.swap_address, inCoin, wrapped_coin_addresses[j], inCoinIndexes.wrapped_coin, j, swapType, curve.constants.ZERO_ADDRESS, tvl));
172
- routesByTvl[wrapped_coin_addresses[j]] = [...(routesByTvl[wrapped_coin_addresses[j]] ?? []), ...newRoutesByTvl];
173
- routesByTvl[wrapped_coin_addresses[j]] = filterRoutes(routesByTvl[wrapped_coin_addresses[j]], inputCoinAddress, sortByTvl);
174
- routesByLength[wrapped_coin_addresses[j]] = [...(routesByLength[wrapped_coin_addresses[j]] ?? []), ...newRoutesByLength];
175
- routesByLength[wrapped_coin_addresses[j]] = filterRoutes(routesByLength[wrapped_coin_addresses[j]], inputCoinAddress, sortByLength);
176
- nextCoins.add(wrapped_coin_addresses[j]);
177
- }
178
- }
179
- // Only for underlying swaps
180
- poolAddress = (poolData.is_crypto && poolData.is_meta) || (base_pool?.is_lending && poolData.is_factory) ?
181
- poolData.deposit_address : poolData.swap_address;
182
- // Underlying swaps
183
- if (!poolData.is_plain && inCoinIndexes.underlying_coin >= 0) {
184
- for (let j = 0; j < underlying_coin_addresses.length; j++) {
185
- if (j === inCoinIndexes.underlying_coin)
186
- continue;
187
- // Don't swap metacoins since they can be swapped directly in base pool
188
- if (inCoinIndexes.meta_coin >= 0 && meta_coin_addresses.includes(underlying_coin_addresses[j]))
189
- continue;
190
- // Looking for outputCoinAddress only on the final step
191
- if (step === 3 && underlying_coin_addresses[j] !== outputCoinAddress)
192
- continue;
193
- // Exclude such cases as cvxeth -> tricrypto2 -> tusd -> susd or cvxeth -> tricrypto2 -> susd -> susd
194
- const outputCoinIdx = underlying_coin_addresses.indexOf(outputCoinAddress);
195
- if (outputCoinIdx >= 0 && j !== outputCoinIdx)
196
- continue;
197
- // Skip empty pools
198
- const tvl = Number(await (getPool(poolId)).stats.totalLiquidity());
199
- if (tvl === 0)
200
- continue;
201
- const hasEth = (inCoin === curve.constants.NATIVE_TOKEN.address || underlying_coin_addresses[j] === curve.constants.NATIVE_TOKEN.address);
202
- const swapType = (poolData.is_crypto && poolData.is_meta && poolData.is_factory) ? 6
203
- : (base_pool?.is_lending && poolData.is_factory) ? 5
204
- : hasEth && poolId !== 'avaxcrypto' ? 3
205
- : poolData.is_crypto ? 4
206
- : 2;
207
- const newRoutesByTvl = routesByTvl[inCoin].map((route) => getNewRoute(route, poolId, poolAddress, inCoin, underlying_coin_addresses[j], inCoinIndexes.underlying_coin, j, swapType, (swapType === 5 || swapType === 6) ? poolData.swap_address : curve.constants.ZERO_ADDRESS, tvl));
208
- const newRoutesByLength = routesByLength[inCoin].map((route) => getNewRoute(route, poolId, poolAddress, inCoin, underlying_coin_addresses[j], inCoinIndexes.underlying_coin, j, swapType, (swapType === 5 || swapType === 6) ? poolData.swap_address : curve.constants.ZERO_ADDRESS, tvl));
209
- routesByTvl[underlying_coin_addresses[j]] = [...(routesByTvl[underlying_coin_addresses[j]] ?? []), ...newRoutesByTvl];
210
- routesByTvl[underlying_coin_addresses[j]] = filterRoutes(routesByTvl[underlying_coin_addresses[j]], inputCoinAddress, sortByTvl);
211
- routesByLength[underlying_coin_addresses[j]] = [...(routesByLength[underlying_coin_addresses[j]] ?? []), ...newRoutesByLength];
212
- routesByLength[underlying_coin_addresses[j]] = filterRoutes(routesByLength[underlying_coin_addresses[j]], inputCoinAddress, sortByLength);
213
- nextCoins.add(underlying_coin_addresses[j]);
214
- }
215
- }
216
- }
337
+ _i = 0, curCoins_1 = curCoins;
338
+ _s.label = 3;
339
+ case 3:
340
+ if (!(_i < curCoins_1.length)) return [3 /*break*/, 6];
341
+ inCoin = curCoins_1[_i];
342
+ return [5 /*yield**/, _loop_1(inCoin)];
343
+ case 4:
344
+ _s.sent();
345
+ _s.label = 5;
346
+ case 5:
347
+ _i++;
348
+ return [3 /*break*/, 3];
349
+ case 6:
350
+ curCoins = Array.from(nextCoins);
351
+ nextCoins = new Set();
352
+ _s.label = 7;
353
+ case 7:
354
+ step++;
355
+ return [3 /*break*/, 2];
356
+ case 8:
357
+ routes = __spreadArray(__spreadArray([], ((_q = routesByTvl[outputCoinAddress]) !== null && _q !== void 0 ? _q : []), true), ((_r = routesByLength[outputCoinAddress]) !== null && _r !== void 0 ? _r : []), true);
358
+ return [2 /*return*/, routes.map(function (r) { return r.route; })];
217
359
  }
218
- curCoins = Array.from(nextCoins);
219
- nextCoins = new Set();
220
- }
221
- const routes = [...(routesByTvl[outputCoinAddress] ?? []), ...(routesByLength[outputCoinAddress] ?? [])];
222
- return routes.map((r) => r.route);
223
- };
224
- const _getRouteKey = (route, inputCoinAddress, outputCoinAddress) => {
225
- const sortedCoins = [inputCoinAddress, outputCoinAddress].sort();
226
- let key = `${sortedCoins[0]}-->`;
227
- for (const routeStep of route) {
228
- key += `${routeStep.poolId}-->`;
360
+ });
361
+ }); };
362
+ var _getRouteKey = function (route, inputCoinAddress, outputCoinAddress) {
363
+ var sortedCoins = [inputCoinAddress, outputCoinAddress].sort();
364
+ var key = "".concat(sortedCoins[0], "-->");
365
+ for (var _i = 0, route_1 = route; _i < route_1.length; _i++) {
366
+ var routeStep = route_1[_i];
367
+ key += "".concat(routeStep.poolId, "-->");
229
368
  }
230
369
  key += sortedCoins[1];
231
370
  return key;
232
371
  };
233
- const _getExchangeMultipleArgs = (route) => {
234
- let _route = [];
372
+ var _getExchangeMultipleArgs = function (route) {
373
+ var _route = [];
235
374
  if (route.length > 0)
236
375
  _route.push(route[0].inputCoinAddress);
237
- let _swapParams = [];
238
- let _factorySwapAddresses = [];
239
- for (const routeStep of route) {
376
+ var _swapParams = [];
377
+ var _factorySwapAddresses = [];
378
+ for (var _i = 0, route_2 = route; _i < route_2.length; _i++) {
379
+ var routeStep = route_2[_i];
240
380
  _route.push(routeStep.poolAddress, routeStep.outputCoinAddress);
241
381
  _swapParams.push([routeStep.i, routeStep.j, routeStep.swapType]);
242
382
  _factorySwapAddresses.push(routeStep.swapAddress);
@@ -244,204 +384,322 @@ const _getExchangeMultipleArgs = (route) => {
244
384
  _route = _route.concat(Array(9 - _route.length).fill(curve.constants.ZERO_ADDRESS));
245
385
  _swapParams = _swapParams.concat(Array(4 - _swapParams.length).fill([0, 0, 0]));
246
386
  _factorySwapAddresses = _factorySwapAddresses.concat(Array(4 - _factorySwapAddresses.length).fill(curve.constants.ZERO_ADDRESS));
247
- return { _route, _swapParams, _factorySwapAddresses };
387
+ return { _route: _route, _swapParams: _swapParams, _factorySwapAddresses: _factorySwapAddresses };
248
388
  };
249
- const _estimatedGasForDifferentRoutesCache = {};
250
- const _estimateGasForDifferentRoutes = async (routes, inputCoinAddress, outputCoinAddress, _amount) => {
251
- inputCoinAddress = inputCoinAddress.toLowerCase();
252
- outputCoinAddress = outputCoinAddress.toLowerCase();
253
- const contract = curve.contracts[curve.constants.ALIASES.registry_exchange].contract;
254
- const gasPromises = [];
255
- const value = isEth(inputCoinAddress) ? _amount : 0n;
256
- for (const route of routes) {
257
- const routeKey = _getRouteKey(route, inputCoinAddress, outputCoinAddress);
258
- let gasPromise;
259
- const { _route, _swapParams, _factorySwapAddresses } = _getExchangeMultipleArgs(route);
260
- if ((_estimatedGasForDifferentRoutesCache[routeKey]?.time || 0) + 3600000 < Date.now()) {
261
- gasPromise = contract.exchange_multiple.estimateGas(_route, _swapParams, _amount, 0, _factorySwapAddresses, { ...curve.constantOptions, value });
262
- }
263
- else {
264
- gasPromise = Promise.resolve(_estimatedGasForDifferentRoutesCache[routeKey].gas);
265
- }
266
- gasPromises.push(gasPromise);
267
- }
268
- try {
269
- const _gasAmounts = await Promise.all(gasPromises);
270
- routes.forEach((route, i) => {
271
- const routeKey = _getRouteKey(route, inputCoinAddress, outputCoinAddress);
272
- _estimatedGasForDifferentRoutesCache[routeKey] = { 'gas': _gasAmounts[i], 'time': Date.now() };
273
- });
274
- return _gasAmounts.map((_g) => Number(curve.formatUnits(_g, 0)));
275
- }
276
- catch (err) { // No allowance
277
- return routes.map(() => 0);
278
- }
279
- };
280
- const _getBestRoute = memoize(async (inputCoinAddress, outputCoinAddress, amount) => {
281
- const [inputCoinDecimals, outputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
282
- const _amount = parseUnits(amount, inputCoinDecimals);
283
- if (_amount === 0n)
284
- return [];
285
- const routesRaw = (await _findAllRoutes(inputCoinAddress, outputCoinAddress)).map((route) => ({ route, _output: 0n, outputUsd: 0, txCostUsd: 0 }));
286
- const routes = [];
287
- try {
288
- const calls = [];
289
- const multicallContract = curve.contracts[curve.constants.ALIASES.registry_exchange].multicallContract;
290
- for (const r of routesRaw) {
291
- const { _route, _swapParams, _factorySwapAddresses } = _getExchangeMultipleArgs(r.route);
292
- calls.push(multicallContract.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses));
293
- }
294
- const _outputAmounts = await curve.multicallProvider.all(calls);
295
- for (let i = 0; i < _outputAmounts.length; i++) {
296
- routesRaw[i]._output = _outputAmounts[i];
297
- routes.push(routesRaw[i]);
298
- }
299
- }
300
- catch (err) {
301
- const promises = [];
302
- const contract = curve.contracts[curve.constants.ALIASES.registry_exchange].contract;
303
- for (const r of routesRaw) {
304
- const { _route, _swapParams, _factorySwapAddresses } = _getExchangeMultipleArgs(r.route);
305
- promises.push(contract.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses, curve.constantOptions));
389
+ var _estimatedGasForDifferentRoutesCache = {};
390
+ var _estimateGasForDifferentRoutes = function (routes, inputCoinAddress, outputCoinAddress, _amount) { return __awaiter(void 0, void 0, void 0, function () {
391
+ var contract, gasPromises, value, _i, routes_1, route, routeKey, gasPromise, _a, _route, _swapParams, _factorySwapAddresses, _gasAmounts_1, err_1;
392
+ var _b;
393
+ return __generator(this, function (_c) {
394
+ switch (_c.label) {
395
+ case 0:
396
+ inputCoinAddress = inputCoinAddress.toLowerCase();
397
+ outputCoinAddress = outputCoinAddress.toLowerCase();
398
+ contract = curve.contracts[curve.constants.ALIASES.registry_exchange].contract;
399
+ gasPromises = [];
400
+ value = isEth(inputCoinAddress) ? _amount : curve.parseUnits("0");
401
+ for (_i = 0, routes_1 = routes; _i < routes_1.length; _i++) {
402
+ route = routes_1[_i];
403
+ routeKey = _getRouteKey(route, inputCoinAddress, outputCoinAddress);
404
+ gasPromise = void 0;
405
+ _a = _getExchangeMultipleArgs(route), _route = _a._route, _swapParams = _a._swapParams, _factorySwapAddresses = _a._factorySwapAddresses;
406
+ if ((((_b = _estimatedGasForDifferentRoutesCache[routeKey]) === null || _b === void 0 ? void 0 : _b.time) || 0) + 3600000 < Date.now()) {
407
+ gasPromise = contract.exchange_multiple.estimateGas(_route, _swapParams, _amount, 0, _factorySwapAddresses, __assign(__assign({}, curve.constantOptions), { value: value }));
408
+ }
409
+ else {
410
+ gasPromise = Promise.resolve(_estimatedGasForDifferentRoutesCache[routeKey].gas);
411
+ }
412
+ gasPromises.push(gasPromise);
413
+ }
414
+ _c.label = 1;
415
+ case 1:
416
+ _c.trys.push([1, 3, , 4]);
417
+ return [4 /*yield*/, Promise.all(gasPromises)];
418
+ case 2:
419
+ _gasAmounts_1 = _c.sent();
420
+ routes.forEach(function (route, i) {
421
+ var routeKey = _getRouteKey(route, inputCoinAddress, outputCoinAddress);
422
+ _estimatedGasForDifferentRoutesCache[routeKey] = { 'gas': _gasAmounts_1[i], 'time': Date.now() };
423
+ });
424
+ return [2 /*return*/, _gasAmounts_1.map(function (_g) { return Number(curve.formatUnits(_g, 0)); })];
425
+ case 3:
426
+ err_1 = _c.sent();
427
+ return [2 /*return*/, routes.map(function () { return 0; })];
428
+ case 4: return [2 /*return*/];
306
429
  }
307
- // @ts-ignore
308
- const res = await Promise.allSettled(promises);
309
- for (let i = 0; i < res.length; i++) {
310
- if (res[i].status === 'rejected') {
311
- console.log(`Route ${(routesRaw[i].route.map((s) => s.poolId)).join(" --> ")} is unavailable`);
312
- continue;
313
- }
314
- routesRaw[i]._output = res[i].value;
315
- routes.push(routesRaw[i]);
430
+ });
431
+ }); };
432
+ var _getBestRoute = memoize(function (inputCoinAddress, outputCoinAddress, amount) { return __awaiter(void 0, void 0, void 0, function () {
433
+ var _a, inputCoinDecimals, outputCoinDecimals, _amount, routesRaw, routes, calls, multicallContract, _i, routesRaw_1, r, _b, _route, _swapParams, _factorySwapAddresses, _outputAmounts, i, err_2, promises, contract, _c, routesRaw_2, r, _d, _route, _swapParams, _factorySwapAddresses, res, i, _e, gasAmounts, outputCoinUsdRate, gasData, ethUsdRate, gasPrice, expectedAmounts, expectedAmountsUsd, txCostsUsd;
434
+ return __generator(this, function (_f) {
435
+ switch (_f.label) {
436
+ case 0:
437
+ _a = _getCoinDecimals(inputCoinAddress, outputCoinAddress), inputCoinDecimals = _a[0], outputCoinDecimals = _a[1];
438
+ _amount = parseUnits(amount, inputCoinDecimals);
439
+ if (_amount === curve.parseUnits("0"))
440
+ return [2 /*return*/, []];
441
+ return [4 /*yield*/, _findAllRoutes(inputCoinAddress, outputCoinAddress)];
442
+ case 1:
443
+ routesRaw = (_f.sent()).map(function (route) { return ({ route: route, _output: curve.parseUnits("0"), outputUsd: 0, txCostUsd: 0 }); });
444
+ routes = [];
445
+ _f.label = 2;
446
+ case 2:
447
+ _f.trys.push([2, 4, , 6]);
448
+ calls = [];
449
+ multicallContract = curve.contracts[curve.constants.ALIASES.registry_exchange].multicallContract;
450
+ for (_i = 0, routesRaw_1 = routesRaw; _i < routesRaw_1.length; _i++) {
451
+ r = routesRaw_1[_i];
452
+ _b = _getExchangeMultipleArgs(r.route), _route = _b._route, _swapParams = _b._swapParams, _factorySwapAddresses = _b._factorySwapAddresses;
453
+ calls.push(multicallContract.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses));
454
+ }
455
+ return [4 /*yield*/, curve.multicallProvider.all(calls)];
456
+ case 3:
457
+ _outputAmounts = _f.sent();
458
+ for (i = 0; i < _outputAmounts.length; i++) {
459
+ routesRaw[i]._output = _outputAmounts[i];
460
+ routes.push(routesRaw[i]);
461
+ }
462
+ return [3 /*break*/, 6];
463
+ case 4:
464
+ err_2 = _f.sent();
465
+ promises = [];
466
+ contract = curve.contracts[curve.constants.ALIASES.registry_exchange].contract;
467
+ for (_c = 0, routesRaw_2 = routesRaw; _c < routesRaw_2.length; _c++) {
468
+ r = routesRaw_2[_c];
469
+ _d = _getExchangeMultipleArgs(r.route), _route = _d._route, _swapParams = _d._swapParams, _factorySwapAddresses = _d._factorySwapAddresses;
470
+ promises.push(contract.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses, curve.constantOptions));
471
+ }
472
+ return [4 /*yield*/, Promise.allSettled(promises)];
473
+ case 5:
474
+ res = _f.sent();
475
+ for (i = 0; i < res.length; i++) {
476
+ if (res[i].status === 'rejected') {
477
+ console.log("Route ".concat((routesRaw[i].route.map(function (s) { return s.poolId; })).join(" --> "), " is unavailable"));
478
+ continue;
479
+ }
480
+ routesRaw[i]._output = res[i].value;
481
+ routes.push(routesRaw[i]);
482
+ }
483
+ return [3 /*break*/, 6];
484
+ case 6:
485
+ if (routes.length === 0)
486
+ return [2 /*return*/, []];
487
+ if (routes.length === 1)
488
+ return [2 /*return*/, routes[0].route];
489
+ return [4 /*yield*/, Promise.all([
490
+ _estimateGasForDifferentRoutes(routes.map(function (r) { return r.route; }), inputCoinAddress, outputCoinAddress, _amount),
491
+ _getUsdRate(outputCoinAddress),
492
+ axios.get("https://api.curve.fi/api/getGas"),
493
+ _getUsdRate(ETH_ADDRESS),
494
+ ])];
495
+ case 7:
496
+ _e = _f.sent(), gasAmounts = _e[0], outputCoinUsdRate = _e[1], gasData = _e[2], ethUsdRate = _e[3];
497
+ gasPrice = gasData.data.data.gas.standard;
498
+ expectedAmounts = (routes).map(function (route) { return Number(curve.formatUnits(route._output, outputCoinDecimals)); });
499
+ expectedAmountsUsd = expectedAmounts.map(function (a) { return a * outputCoinUsdRate; });
500
+ txCostsUsd = gasAmounts.map(function (a) { return ethUsdRate * a * gasPrice / 1e18; });
501
+ routes.forEach(function (route, i) {
502
+ route.outputUsd = expectedAmountsUsd[i];
503
+ route.txCostUsd = txCostsUsd[i];
504
+ });
505
+ return [2 /*return*/, routes.reduce(function (route1, route2) {
506
+ var diff = (route1.outputUsd - route1.txCostUsd) - (route2.outputUsd - route2.txCostUsd);
507
+ if (diff > 0)
508
+ return route1;
509
+ if (diff === 0 && route1.route.length < route2.route.length)
510
+ return route1;
511
+ return route2;
512
+ }).route];
316
513
  }
317
- }
318
- if (routes.length === 0)
319
- return [];
320
- if (routes.length === 1)
321
- return routes[0].route;
322
- const [gasAmounts, outputCoinUsdRate, gasData, ethUsdRate] = await Promise.all([
323
- _estimateGasForDifferentRoutes(routes.map((r) => r.route), inputCoinAddress, outputCoinAddress, _amount),
324
- _getUsdRate(outputCoinAddress),
325
- axios.get("https://api.curve.fi/api/getGas"),
326
- _getUsdRate(ETH_ADDRESS),
327
- ]);
328
- const gasPrice = gasData.data.data.gas.standard;
329
- const expectedAmounts = (routes).map((route) => Number(curve.formatUnits(route._output, outputCoinDecimals)));
330
- const expectedAmountsUsd = expectedAmounts.map((a) => a * outputCoinUsdRate);
331
- const txCostsUsd = gasAmounts.map((a) => ethUsdRate * a * gasPrice / 1e18);
332
- routes.forEach((route, i) => {
333
- route.outputUsd = expectedAmountsUsd[i];
334
- route.txCostUsd = txCostsUsd[i];
335
514
  });
336
- return routes.reduce((route1, route2) => {
337
- const diff = (route1.outputUsd - route1.txCostUsd) - (route2.outputUsd - route2.txCostUsd);
338
- if (diff > 0)
339
- return route1;
340
- if (diff === 0 && route1.route.length < route2.route.length)
341
- return route1;
342
- return route2;
343
- }).route;
344
- }, {
515
+ }); }, {
345
516
  promise: true,
346
517
  maxAge: 5 * 60 * 1000, // 5m
347
518
  });
348
- const _getOutputForRoute = memoize(async (route, _amount) => {
349
- const contract = curve.contracts[curve.constants.ALIASES.registry_exchange].contract;
350
- const { _route, _swapParams, _factorySwapAddresses } = _getExchangeMultipleArgs(route);
351
- return await contract.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses, curve.constantOptions);
352
- }, {
519
+ var _getOutputForRoute = memoize(function (route, _amount) { return __awaiter(void 0, void 0, void 0, function () {
520
+ var contract, _a, _route, _swapParams, _factorySwapAddresses;
521
+ return __generator(this, function (_b) {
522
+ switch (_b.label) {
523
+ case 0:
524
+ contract = curve.contracts[curve.constants.ALIASES.registry_exchange].contract;
525
+ _a = _getExchangeMultipleArgs(route), _route = _a._route, _swapParams = _a._swapParams, _factorySwapAddresses = _a._factorySwapAddresses;
526
+ return [4 /*yield*/, contract.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses, curve.constantOptions)];
527
+ case 1: return [2 /*return*/, _b.sent()];
528
+ }
529
+ });
530
+ }); }, {
353
531
  promise: true,
354
532
  maxAge: 15 * 1000, // 15s
355
533
  });
356
- export const getBestRouteAndOutput = async (inputCoin, outputCoin, amount) => {
357
- const [inputCoinAddress, outputCoinAddress] = _getCoinAddresses(inputCoin, outputCoin);
358
- const [inputCoinDecimals, outputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
359
- const route = await _getBestRoute(inputCoinAddress, outputCoinAddress, amount); // 5 minutes cache
360
- if (route.length === 0)
361
- return { route, output: '0.0' };
362
- const _output = await _getOutputForRoute(route, parseUnits(amount, inputCoinDecimals)); // 15 seconds cache, so we call it to get fresh output estimation
363
- return { route, output: curve.formatUnits(_output, outputCoinDecimals) };
364
- };
365
- export const swapExpected = async (inputCoin, outputCoin, amount) => {
366
- return (await getBestRouteAndOutput(inputCoin, outputCoin, amount))['output'];
367
- };
368
- export const swapPriceImpact = async (inputCoin, outputCoin, amount) => {
369
- const [inputCoinAddress, outputCoinAddress] = _getCoinAddresses(inputCoin, outputCoin);
370
- const [inputCoinDecimals, outputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
371
- const { route, output } = await getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount);
372
- const _amount = parseUnits(amount, inputCoinDecimals);
373
- const _output = parseUnits(output, outputCoinDecimals);
374
- const smallAmountIntBN = _get_small_x(_amount, _output, inputCoinDecimals, outputCoinDecimals);
375
- const amountIntBN = toBN(_amount, 0);
376
- if (smallAmountIntBN.gte(amountIntBN))
377
- return 0;
378
- const contract = curve.contracts[curve.constants.ALIASES.registry_exchange].contract;
379
- let _smallAmount = fromBN(smallAmountIntBN.div(10 ** inputCoinDecimals), inputCoinDecimals);
380
- const { _route, _swapParams, _factorySwapAddresses } = _getExchangeMultipleArgs(route);
381
- let _smallOutput;
382
- try {
383
- _smallOutput = await contract.get_exchange_multiple_amount(_route, _swapParams, _smallAmount, _factorySwapAddresses, curve.constantOptions);
384
- }
385
- catch (e) {
386
- _smallAmount = curve.parseUnits("1", inputCoinDecimals); // Dirty hack
387
- _smallOutput = await contract.get_exchange_multiple_amount(_route, _swapParams, _smallAmount, _factorySwapAddresses, curve.constantOptions);
388
- }
389
- const priceImpactBN = _get_price_impact(_amount, _output, _smallAmount, _smallOutput, inputCoinDecimals, outputCoinDecimals);
390
- return Number(_cutZeros(priceImpactBN.toFixed(4)));
391
- };
392
- export const swapIsApproved = async (inputCoin, amount) => {
393
- return await hasAllowance([inputCoin], [amount], curve.signerAddress, curve.constants.ALIASES.registry_exchange);
394
- };
395
- export const swapApproveEstimateGas = async (inputCoin, amount) => {
396
- return await ensureAllowanceEstimateGas([inputCoin], [amount], curve.constants.ALIASES.registry_exchange);
397
- };
398
- export const swapApprove = async (inputCoin, amount) => {
399
- return await ensureAllowance([inputCoin], [amount], curve.constants.ALIASES.registry_exchange);
400
- };
401
- export const swapEstimateGas = async (inputCoin, outputCoin, amount) => {
402
- const [inputCoinAddress, outputCoinAddress] = _getCoinAddresses(inputCoin, outputCoin);
403
- const [inputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
404
- const { route } = await getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount);
405
- if (route.length === 0)
406
- return 0;
407
- const _amount = parseUnits(amount, inputCoinDecimals);
408
- const [gas] = await _estimateGasForDifferentRoutes([route], inputCoinAddress, outputCoinAddress, _amount);
409
- return gas;
410
- };
411
- export const swap = async (inputCoin, outputCoin, amount, slippage = 0.5) => {
412
- const [inputCoinAddress, outputCoinAddress] = _getCoinAddresses(inputCoin, outputCoin);
413
- const [inputCoinDecimals, outputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
414
- await swapApprove(inputCoin, amount);
415
- const { route, output } = await getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount);
416
- if (route.length === 0) {
417
- throw new Error("This pair can't be exchanged");
418
- }
419
- const { _route, _swapParams, _factorySwapAddresses } = _getExchangeMultipleArgs(route);
420
- const _amount = parseUnits(amount, inputCoinDecimals);
421
- const minRecvAmountBN = BN(output).times(100 - slippage).div(100);
422
- const _minRecvAmount = fromBN(minRecvAmountBN, outputCoinDecimals);
423
- const contract = curve.contracts[curve.constants.ALIASES.registry_exchange].contract;
424
- const value = isEth(inputCoinAddress) ? _amount : 0n;
425
- await curve.updateFeeData();
426
- const gasLimit = (await contract.exchange_multiple.estimateGas(_route, _swapParams, _amount, _minRecvAmount, _factorySwapAddresses, { ...curve.constantOptions, value })) * (curve.chainId === 1 ? 130n : 160n) / 100n;
427
- return await contract.exchange_multiple(_route, _swapParams, _amount, _minRecvAmount, _factorySwapAddresses, { ...curve.options, value, gasLimit });
428
- };
429
- export const getSwappedAmount = async (tx, outputCoin) => {
430
- const [outputCoinAddress] = _getCoinAddresses(outputCoin);
431
- const [outputCoinDecimals] = _getCoinDecimals(outputCoinAddress);
432
- const txInfo = await tx.wait();
433
- if (txInfo === null)
434
- return '0.0';
435
- let res;
436
- for (let i = 1; i <= txInfo.logs.length; i++) {
437
- try {
438
- const abiCoder = ethers.AbiCoder.defaultAbiCoder();
439
- res = abiCoder.decode(['address[9]', 'uint256[3][4]', 'address[4]', 'uint256', 'uint256'], ethers.dataSlice(txInfo.logs[txInfo.logs.length - i].data, 0));
440
- break;
534
+ export var getBestRouteAndOutput = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
535
+ var _a, inputCoinAddress, outputCoinAddress, _b, inputCoinDecimals, outputCoinDecimals, route, _output;
536
+ return __generator(this, function (_c) {
537
+ switch (_c.label) {
538
+ case 0:
539
+ _a = _getCoinAddresses(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
540
+ _b = _getCoinDecimals(inputCoinAddress, outputCoinAddress), inputCoinDecimals = _b[0], outputCoinDecimals = _b[1];
541
+ return [4 /*yield*/, _getBestRoute(inputCoinAddress, outputCoinAddress, amount)];
542
+ case 1:
543
+ route = _c.sent();
544
+ if (route.length === 0)
545
+ return [2 /*return*/, { route: route, output: '0.0' }];
546
+ return [4 /*yield*/, _getOutputForRoute(route, parseUnits(amount, inputCoinDecimals))];
547
+ case 2:
548
+ _output = _c.sent();
549
+ return [2 /*return*/, { route: route, output: curve.formatUnits(_output, outputCoinDecimals) }];
441
550
  }
442
- catch (err) { }
443
- }
444
- if (res === undefined)
445
- return '0.0';
446
- return curve.formatUnits(res[res.length - 1], outputCoinDecimals);
551
+ });
552
+ }); };
553
+ export var swapExpected = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
554
+ return __generator(this, function (_a) {
555
+ switch (_a.label) {
556
+ case 0: return [4 /*yield*/, getBestRouteAndOutput(inputCoin, outputCoin, amount)];
557
+ case 1: return [2 /*return*/, (_a.sent())['output']];
558
+ }
559
+ });
560
+ }); };
561
+ export var swapPriceImpact = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
562
+ var _a, inputCoinAddress, outputCoinAddress, _b, inputCoinDecimals, outputCoinDecimals, _c, route, output, _amount, _output, smallAmountIntBN, amountIntBN, contract, _smallAmount, _d, _route, _swapParams, _factorySwapAddresses, _smallOutput, e_1, priceImpactBN;
563
+ return __generator(this, function (_e) {
564
+ switch (_e.label) {
565
+ case 0:
566
+ _a = _getCoinAddresses(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
567
+ _b = _getCoinDecimals(inputCoinAddress, outputCoinAddress), inputCoinDecimals = _b[0], outputCoinDecimals = _b[1];
568
+ return [4 /*yield*/, getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount)];
569
+ case 1:
570
+ _c = _e.sent(), route = _c.route, output = _c.output;
571
+ _amount = parseUnits(amount, inputCoinDecimals);
572
+ _output = parseUnits(output, outputCoinDecimals);
573
+ smallAmountIntBN = _get_small_x(_amount, _output, inputCoinDecimals, outputCoinDecimals);
574
+ amountIntBN = toBN(_amount, 0);
575
+ if (smallAmountIntBN.gte(amountIntBN))
576
+ return [2 /*return*/, 0];
577
+ contract = curve.contracts[curve.constants.ALIASES.registry_exchange].contract;
578
+ _smallAmount = fromBN(smallAmountIntBN.div(Math.pow(10, inputCoinDecimals)), inputCoinDecimals);
579
+ _d = _getExchangeMultipleArgs(route), _route = _d._route, _swapParams = _d._swapParams, _factorySwapAddresses = _d._factorySwapAddresses;
580
+ _e.label = 2;
581
+ case 2:
582
+ _e.trys.push([2, 4, , 6]);
583
+ return [4 /*yield*/, contract.get_exchange_multiple_amount(_route, _swapParams, _smallAmount, _factorySwapAddresses, curve.constantOptions)];
584
+ case 3:
585
+ _smallOutput = _e.sent();
586
+ return [3 /*break*/, 6];
587
+ case 4:
588
+ e_1 = _e.sent();
589
+ _smallAmount = curve.parseUnits("1", inputCoinDecimals); // Dirty hack
590
+ return [4 /*yield*/, contract.get_exchange_multiple_amount(_route, _swapParams, _smallAmount, _factorySwapAddresses, curve.constantOptions)];
591
+ case 5:
592
+ _smallOutput = _e.sent();
593
+ return [3 /*break*/, 6];
594
+ case 6:
595
+ priceImpactBN = _get_price_impact(_amount, _output, _smallAmount, _smallOutput, inputCoinDecimals, outputCoinDecimals);
596
+ return [2 /*return*/, Number(_cutZeros(priceImpactBN.toFixed(4)))];
597
+ }
598
+ });
599
+ }); };
600
+ export var swapIsApproved = function (inputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
601
+ return __generator(this, function (_a) {
602
+ switch (_a.label) {
603
+ case 0: return [4 /*yield*/, hasAllowance([inputCoin], [amount], curve.signerAddress, curve.constants.ALIASES.registry_exchange)];
604
+ case 1: return [2 /*return*/, _a.sent()];
605
+ }
606
+ });
607
+ }); };
608
+ export var swapApproveEstimateGas = function (inputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
609
+ return __generator(this, function (_a) {
610
+ switch (_a.label) {
611
+ case 0: return [4 /*yield*/, ensureAllowanceEstimateGas([inputCoin], [amount], curve.constants.ALIASES.registry_exchange)];
612
+ case 1: return [2 /*return*/, _a.sent()];
613
+ }
614
+ });
615
+ }); };
616
+ export var swapApprove = function (inputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
617
+ return __generator(this, function (_a) {
618
+ switch (_a.label) {
619
+ case 0: return [4 /*yield*/, ensureAllowance([inputCoin], [amount], curve.constants.ALIASES.registry_exchange)];
620
+ case 1: return [2 /*return*/, _a.sent()];
621
+ }
622
+ });
623
+ }); };
624
+ export var swapEstimateGas = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
625
+ var _a, inputCoinAddress, outputCoinAddress, inputCoinDecimals, route, _amount, gas;
626
+ return __generator(this, function (_b) {
627
+ switch (_b.label) {
628
+ case 0:
629
+ _a = _getCoinAddresses(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
630
+ inputCoinDecimals = _getCoinDecimals(inputCoinAddress, outputCoinAddress)[0];
631
+ return [4 /*yield*/, getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount)];
632
+ case 1:
633
+ route = (_b.sent()).route;
634
+ if (route.length === 0)
635
+ return [2 /*return*/, 0];
636
+ _amount = parseUnits(amount, inputCoinDecimals);
637
+ return [4 /*yield*/, _estimateGasForDifferentRoutes([route], inputCoinAddress, outputCoinAddress, _amount)];
638
+ case 2:
639
+ gas = (_b.sent())[0];
640
+ return [2 /*return*/, gas];
641
+ }
642
+ });
643
+ }); };
644
+ export var swap = function (inputCoin, outputCoin, amount, slippage) {
645
+ if (slippage === void 0) { slippage = 0.5; }
646
+ return __awaiter(void 0, void 0, void 0, function () {
647
+ var _a, inputCoinAddress, outputCoinAddress, _b, inputCoinDecimals, outputCoinDecimals, _c, route, output, _d, _route, _swapParams, _factorySwapAddresses, _amount, minRecvAmountBN, _minRecvAmount, contract, value, gasLimit;
648
+ return __generator(this, function (_e) {
649
+ switch (_e.label) {
650
+ case 0:
651
+ _a = _getCoinAddresses(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
652
+ _b = _getCoinDecimals(inputCoinAddress, outputCoinAddress), inputCoinDecimals = _b[0], outputCoinDecimals = _b[1];
653
+ return [4 /*yield*/, swapApprove(inputCoin, amount)];
654
+ case 1:
655
+ _e.sent();
656
+ return [4 /*yield*/, getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount)];
657
+ case 2:
658
+ _c = _e.sent(), route = _c.route, output = _c.output;
659
+ if (route.length === 0) {
660
+ throw new Error("This pair can't be exchanged");
661
+ }
662
+ _d = _getExchangeMultipleArgs(route), _route = _d._route, _swapParams = _d._swapParams, _factorySwapAddresses = _d._factorySwapAddresses;
663
+ _amount = parseUnits(amount, inputCoinDecimals);
664
+ minRecvAmountBN = BN(output).times(100 - slippage).div(100);
665
+ _minRecvAmount = fromBN(minRecvAmountBN, outputCoinDecimals);
666
+ contract = curve.contracts[curve.constants.ALIASES.registry_exchange].contract;
667
+ value = isEth(inputCoinAddress) ? _amount : curve.parseUnits("0");
668
+ return [4 /*yield*/, curve.updateFeeData()];
669
+ case 3:
670
+ _e.sent();
671
+ return [4 /*yield*/, contract.exchange_multiple.estimateGas(_route, _swapParams, _amount, _minRecvAmount, _factorySwapAddresses, __assign(__assign({}, curve.constantOptions), { value: value }))];
672
+ case 4:
673
+ gasLimit = (_e.sent()) * (curve.chainId === 1 ? curve.parseUnits("130", 0) : curve.parseUnits("160", 0)) / curve.parseUnits("100", 0);
674
+ return [4 /*yield*/, contract.exchange_multiple(_route, _swapParams, _amount, _minRecvAmount, _factorySwapAddresses, __assign(__assign({}, curve.options), { value: value, gasLimit: gasLimit }))];
675
+ case 5: return [2 /*return*/, _e.sent()];
676
+ }
677
+ });
678
+ });
447
679
  };
680
+ export var getSwappedAmount = function (tx, outputCoin) { return __awaiter(void 0, void 0, void 0, function () {
681
+ var outputCoinAddress, outputCoinDecimals, txInfo, res, i, abiCoder;
682
+ return __generator(this, function (_a) {
683
+ switch (_a.label) {
684
+ case 0:
685
+ outputCoinAddress = _getCoinAddresses(outputCoin)[0];
686
+ outputCoinDecimals = _getCoinDecimals(outputCoinAddress)[0];
687
+ return [4 /*yield*/, tx.wait()];
688
+ case 1:
689
+ txInfo = _a.sent();
690
+ if (txInfo === null)
691
+ return [2 /*return*/, '0.0'];
692
+ for (i = 1; i <= txInfo.logs.length; i++) {
693
+ try {
694
+ abiCoder = ethers.AbiCoder.defaultAbiCoder();
695
+ res = abiCoder.decode(['address[9]', 'uint256[3][4]', 'address[4]', 'uint256', 'uint256'], ethers.dataSlice(txInfo.logs[txInfo.logs.length - i].data, 0));
696
+ break;
697
+ }
698
+ catch (err) { }
699
+ }
700
+ if (res === undefined)
701
+ return [2 /*return*/, '0.0'];
702
+ return [2 /*return*/, curve.formatUnits(res[res.length - 1], outputCoinDecimals)];
703
+ }
704
+ });
705
+ }); };