@curvefi/api 2.32.0 → 2.33.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/lib/boosting.js +385 -135
  2. package/lib/constants/aliases.js +22 -11
  3. package/lib/constants/coins/arbitrum.js +5 -5
  4. package/lib/constants/coins/aurora.js +5 -5
  5. package/lib/constants/coins/avalanche.js +6 -6
  6. package/lib/constants/coins/celo.js +5 -5
  7. package/lib/constants/coins/ethereum.js +10 -9
  8. package/lib/constants/coins/fantom.js +7 -7
  9. package/lib/constants/coins/kava.js +5 -5
  10. package/lib/constants/coins/moonbeam.js +5 -5
  11. package/lib/constants/coins/optimism.js +5 -5
  12. package/lib/constants/coins/polygon.js +6 -6
  13. package/lib/constants/coins/xdai.js +5 -5
  14. package/lib/constants/pools/arbitrum.js +1 -1
  15. package/lib/constants/pools/aurora.js +1 -1
  16. package/lib/constants/pools/avalanche.js +1 -1
  17. package/lib/constants/pools/celo.js +1 -1
  18. package/lib/constants/pools/ethereum.js +1 -1
  19. package/lib/constants/pools/fantom.js +1 -1
  20. package/lib/constants/pools/kava.js +1 -1
  21. package/lib/constants/pools/moonbeam.js +1 -1
  22. package/lib/constants/pools/optimism.js +1 -1
  23. package/lib/constants/pools/polygon.js +1 -1
  24. package/lib/constants/pools/xdai.js +1 -1
  25. package/lib/constants/utils.js +19 -18
  26. package/lib/curve.js +506 -282
  27. package/lib/external-api.js +132 -45
  28. package/lib/factory/common.js +3 -3
  29. package/lib/factory/constants-crypto.js +21 -21
  30. package/lib/factory/constants.js +32 -31
  31. package/lib/factory/deploy.js +336 -176
  32. package/lib/factory/factory-api.js +256 -180
  33. package/lib/factory/factory-crypto.js +309 -163
  34. package/lib/factory/factory.d.ts +1 -1
  35. package/lib/factory/factory.js +336 -186
  36. package/lib/index.js +98 -44
  37. package/lib/interfaces.d.ts +5 -0
  38. package/lib/pools/PoolTemplate.js +2879 -1468
  39. package/lib/pools/mixins/common.js +106 -22
  40. package/lib/pools/mixins/depositBalancedAmountsMixins.js +131 -48
  41. package/lib/pools/mixins/depositMixins.js +413 -144
  42. package/lib/pools/mixins/depositWrappedMixins.js +223 -72
  43. package/lib/pools/mixins/poolBalancesMixin.js +98 -22
  44. package/lib/pools/mixins/swapMixins.js +347 -125
  45. package/lib/pools/mixins/swapWrappedMixins.js +270 -88
  46. package/lib/pools/mixins/withdrawExpectedMixins.js +104 -23
  47. package/lib/pools/mixins/withdrawImbalanceMixins.js +316 -97
  48. package/lib/pools/mixins/withdrawImbalanceWrappedMixins.js +187 -51
  49. package/lib/pools/mixins/withdrawMixins.js +385 -122
  50. package/lib/pools/mixins/withdrawOneCoinExpectedMixins.js +88 -16
  51. package/lib/pools/mixins/withdrawOneCoinMixins.js +386 -123
  52. package/lib/pools/mixins/withdrawOneCoinWrappedExpectedMixins.js +62 -8
  53. package/lib/pools/mixins/withdrawOneCoinWrappedMixins.js +185 -53
  54. package/lib/pools/mixins/withdrawWrappedMixins.js +185 -50
  55. package/lib/pools/poolConstructor.js +25 -5
  56. package/lib/pools/utils.js +488 -299
  57. package/lib/router.js +675 -212
  58. package/lib/utils.js +675 -354
  59. package/package.json +1 -2
package/lib/router.js CHANGED
@@ -1,27 +1,382 @@
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
- import { findAllRoutes } from "@curvefi/router";
4
59
  import { ethers } from "ethers";
5
60
  import { curve } from "./curve.js";
6
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";
7
62
  import { getPool } from "./pools/index.js";
8
63
  import { _getAmplificationCoefficientsFromApi } from "./pools/utils.js";
9
- const _getRouteKey = (route, inputCoinAddress, outputCoinAddress) => {
10
- const sortedCoins = [inputCoinAddress, outputCoinAddress].sort();
11
- let key = `${sortedCoins[0]}-->`;
12
- for (const routeStep of route) {
13
- key += `${routeStep.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; });
66
+ // Steps <= 4
67
+ if (routePoolIds.length >= 4)
68
+ return { route: [], minTvl: Infinity, totalTvl: 0 };
69
+ // Exclude such cases as cvxeth -> tricrypto2 -> tricrypto2 -> susd
70
+ if (routePoolIds.includes(poolId))
71
+ return { route: [], minTvl: Infinity, totalTvl: 0 };
72
+ return {
73
+ route: __spreadArray(__spreadArray([], routeTvl.route, true), [{ poolId: poolId, poolAddress: poolAddress, inputCoinAddress: inputCoinAddress, outputCoinAddress: outputCoinAddress, i: i, j: j, swapType: swapType, swapAddress: swapAddress }], false),
74
+ minTvl: Math.min(tvl, routeTvl.minTvl),
75
+ totalTvl: routeTvl.totalTvl + tvl,
76
+ };
77
+ };
78
+ // TODO REMOVE IT!!!
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];
83
+ if (step.poolId === "factory-crypto-83" && step.inputCoinAddress === curve.constants.NATIVE_TOKEN.address)
84
+ return false;
85
+ }
86
+ return true;
87
+ });
88
+ };
89
+ // TODO REMOVE IT!!!
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];
94
+ if (step.poolId == 'avaxcrypto' && step.swapType == 4 && (step.i === 3 || step.j === 3))
95
+ return false;
96
+ }
97
+ return true;
98
+ });
99
+ };
100
+ var MAX_ROUTES_FOR_ONE_COIN = 3;
101
+ var filterRoutes = function (routes, inputCoinAddress, sortFn) {
102
+ // TODO REMOVE IT!!!
103
+ if (curve.chainId === 137)
104
+ routes = filterMaticFactory83Route(routes);
105
+ if (curve.chainId === 43114)
106
+ routes = filterAvax(routes);
107
+ return routes
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;
113
+ }) // Route duplications
114
+ .sort(sortFn).slice(0, MAX_ROUTES_FOR_ONE_COIN);
115
+ };
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; };
118
+ // Inspired by Dijkstra's algorithm
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
+ });
336
+ };
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; })];
359
+ }
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, "-->");
14
368
  }
15
369
  key += sortedCoins[1];
16
370
  return key;
17
371
  };
18
- const _getExchangeMultipleArgs = (route) => {
19
- let _route = [];
372
+ var _getExchangeMultipleArgs = function (route) {
373
+ var _route = [];
20
374
  if (route.length > 0)
21
375
  _route.push(route[0].inputCoinAddress);
22
- let _swapParams = [];
23
- let _factorySwapAddresses = [];
24
- 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];
25
380
  _route.push(routeStep.poolAddress, routeStep.outputCoinAddress);
26
381
  _swapParams.push([routeStep.i, routeStep.j, routeStep.swapType]);
27
382
  _factorySwapAddresses.push(routeStep.swapAddress);
@@ -29,214 +384,322 @@ const _getExchangeMultipleArgs = (route) => {
29
384
  _route = _route.concat(Array(9 - _route.length).fill(curve.constants.ZERO_ADDRESS));
30
385
  _swapParams = _swapParams.concat(Array(4 - _swapParams.length).fill([0, 0, 0]));
31
386
  _factorySwapAddresses = _factorySwapAddresses.concat(Array(4 - _factorySwapAddresses.length).fill(curve.constants.ZERO_ADDRESS));
32
- return { _route, _swapParams, _factorySwapAddresses };
387
+ return { _route: _route, _swapParams: _swapParams, _factorySwapAddresses: _factorySwapAddresses };
33
388
  };
34
- const _estimatedGasForDifferentRoutesCache = {};
35
- const _estimateGasForDifferentRoutes = async (routes, inputCoinAddress, outputCoinAddress, _amount) => {
36
- inputCoinAddress = inputCoinAddress.toLowerCase();
37
- outputCoinAddress = outputCoinAddress.toLowerCase();
38
- const contract = curve.contracts[curve.constants.ALIASES.registry_exchange].contract;
39
- const gasPromises = [];
40
- const value = isEth(inputCoinAddress) ? _amount : 0n;
41
- for (const route of routes) {
42
- const routeKey = _getRouteKey(route, inputCoinAddress, outputCoinAddress);
43
- let gasPromise;
44
- const { _route, _swapParams, _factorySwapAddresses } = _getExchangeMultipleArgs(route);
45
- if ((_estimatedGasForDifferentRoutesCache[routeKey]?.time || 0) + 3600000 < Date.now()) {
46
- gasPromise = contract.exchange_multiple.estimateGas(_route, _swapParams, _amount, 0, _factorySwapAddresses, { ...curve.constantOptions, value });
47
- }
48
- else {
49
- gasPromise = Promise.resolve(_estimatedGasForDifferentRoutesCache[routeKey].gas);
50
- }
51
- gasPromises.push(gasPromise);
52
- }
53
- try {
54
- const _gasAmounts = await Promise.all(gasPromises);
55
- routes.forEach((route, i) => {
56
- const routeKey = _getRouteKey(route, inputCoinAddress, outputCoinAddress);
57
- _estimatedGasForDifferentRoutesCache[routeKey] = { 'gas': _gasAmounts[i], 'time': Date.now() };
58
- });
59
- return _gasAmounts.map((_g) => Number(curve.formatUnits(_g, 0)));
60
- }
61
- catch (err) { // No allowance
62
- return routes.map(() => 0);
63
- }
64
- };
65
- const _getBestRoute = memoize(async (inputCoinAddress, outputCoinAddress, amount) => {
66
- const [inputCoinDecimals, outputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
67
- const _amount = parseUnits(amount, inputCoinDecimals);
68
- if (_amount === 0n)
69
- return [];
70
- const pools = {
71
- ...curve.constants.POOLS_DATA,
72
- ...curve.constants.FACTORY_POOLS_DATA,
73
- ...curve.constants.CRYPTO_FACTORY_POOLS_DATA,
74
- };
75
- const ADict = await _getAmplificationCoefficientsFromApi();
76
- const tvlDict = {};
77
- const poolIds = Object.keys(pools);
78
- for (let i = 0; i < poolIds.length; i++) {
79
- tvlDict[poolIds[i]] = Number(await (getPool(poolIds[i])).stats.totalLiquidity());
80
- }
81
- const routesRaw = (findAllRoutes(inputCoinAddress, outputCoinAddress, pools, ADict, curve.chainId, curve.constants.NATIVE_TOKEN, tvlDict)).map((route) => ({ route, _output: 0n, outputUsd: 0, txCostUsd: 0 }));
82
- const routes = [];
83
- try {
84
- const calls = [];
85
- const multicallContract = curve.contracts[curve.constants.ALIASES.registry_exchange].multicallContract;
86
- for (const r of routesRaw) {
87
- const { _route, _swapParams, _factorySwapAddresses } = _getExchangeMultipleArgs(r.route);
88
- calls.push(multicallContract.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses));
89
- }
90
- const _outputAmounts = await curve.multicallProvider.all(calls);
91
- for (let i = 0; i < _outputAmounts.length; i++) {
92
- routesRaw[i]._output = _outputAmounts[i];
93
- routes.push(routesRaw[i]);
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*/];
94
429
  }
95
- }
96
- catch (err) {
97
- const promises = [];
98
- const contract = curve.contracts[curve.constants.ALIASES.registry_exchange].contract;
99
- for (const r of routesRaw) {
100
- const { _route, _swapParams, _factorySwapAddresses } = _getExchangeMultipleArgs(r.route);
101
- promises.push(contract.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses, curve.constantOptions));
102
- }
103
- const res = await Promise.allSettled(promises);
104
- for (let i = 0; i < res.length; i++) {
105
- if (res[i].status === 'rejected') {
106
- console.log(`Route ${(routesRaw[i].route.map((s) => s.poolId)).join(" --> ")} is unavailable`);
107
- continue;
108
- }
109
- routesRaw[i]._output = res[i].value;
110
- 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];
111
513
  }
112
- }
113
- if (routes.length === 0)
114
- return [];
115
- if (routes.length === 1)
116
- return routes[0].route;
117
- const [gasAmounts, outputCoinUsdRate, gasData, ethUsdRate] = await Promise.all([
118
- _estimateGasForDifferentRoutes(routes.map((r) => r.route), inputCoinAddress, outputCoinAddress, _amount),
119
- _getUsdRate(outputCoinAddress),
120
- axios.get("https://api.curve.fi/api/getGas"),
121
- _getUsdRate(ETH_ADDRESS),
122
- ]);
123
- const gasPrice = gasData.data.data.gas.standard;
124
- const expectedAmounts = (routes).map((route) => Number(curve.formatUnits(route._output, outputCoinDecimals)));
125
- const expectedAmountsUsd = expectedAmounts.map((a) => a * outputCoinUsdRate);
126
- const txCostsUsd = gasAmounts.map((a) => ethUsdRate * a * gasPrice / 1e18);
127
- routes.forEach((route, i) => {
128
- route.outputUsd = expectedAmountsUsd[i];
129
- route.txCostUsd = txCostsUsd[i];
130
- });
131
- return routes.reduce((route1, route2) => {
132
- const diff = (route1.outputUsd - route1.txCostUsd) - (route2.outputUsd - route2.txCostUsd);
133
- if (diff > 0)
134
- return route1;
135
- if (diff === 0 && route1.route.length < route2.route.length)
136
- return route1;
137
- return route2;
138
- }).route;
139
- }, {
514
+ });
515
+ }); }, {
140
516
  promise: true,
141
517
  maxAge: 5 * 60 * 1000, // 5m
142
518
  });
143
- const _getOutputForRoute = memoize(async (route, _amount) => {
144
- const contract = curve.contracts[curve.constants.ALIASES.registry_exchange].contract;
145
- const { _route, _swapParams, _factorySwapAddresses } = _getExchangeMultipleArgs(route);
146
- return await contract.get_exchange_multiple_amount(_route, _swapParams, _amount, _factorySwapAddresses, curve.constantOptions);
147
- }, {
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
+ }); }, {
148
531
  promise: true,
149
532
  maxAge: 15 * 1000, // 15s
150
533
  });
151
- export const getBestRouteAndOutput = async (inputCoin, outputCoin, amount) => {
152
- const [inputCoinAddress, outputCoinAddress] = _getCoinAddresses(inputCoin, outputCoin);
153
- const [inputCoinDecimals, outputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
154
- const route = await _getBestRoute(inputCoinAddress, outputCoinAddress, amount); // 5 minutes cache
155
- if (route.length === 0)
156
- return { route, output: '0.0' };
157
- const _output = await _getOutputForRoute(route, parseUnits(amount, inputCoinDecimals)); // 15 seconds cache, so we call it to get fresh output estimation
158
- return { route, output: curve.formatUnits(_output, outputCoinDecimals) };
159
- };
160
- export const swapExpected = async (inputCoin, outputCoin, amount) => {
161
- return (await getBestRouteAndOutput(inputCoin, outputCoin, amount))['output'];
162
- };
163
- export const swapPriceImpact = async (inputCoin, outputCoin, amount) => {
164
- const [inputCoinAddress, outputCoinAddress] = _getCoinAddresses(inputCoin, outputCoin);
165
- const [inputCoinDecimals, outputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
166
- const { route, output } = await getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount);
167
- const _amount = parseUnits(amount, inputCoinDecimals);
168
- const _output = parseUnits(output, outputCoinDecimals);
169
- const smallAmountIntBN = _get_small_x(_amount, _output, inputCoinDecimals, outputCoinDecimals);
170
- const amountIntBN = toBN(_amount, 0);
171
- if (smallAmountIntBN.gte(amountIntBN))
172
- return 0;
173
- const contract = curve.contracts[curve.constants.ALIASES.registry_exchange].contract;
174
- let _smallAmount = fromBN(smallAmountIntBN.div(10 ** inputCoinDecimals), inputCoinDecimals);
175
- const { _route, _swapParams, _factorySwapAddresses } = _getExchangeMultipleArgs(route);
176
- let _smallOutput;
177
- try {
178
- _smallOutput = await contract.get_exchange_multiple_amount(_route, _swapParams, _smallAmount, _factorySwapAddresses, curve.constantOptions);
179
- }
180
- catch (e) {
181
- _smallAmount = curve.parseUnits("1", inputCoinDecimals); // Dirty hack
182
- _smallOutput = await contract.get_exchange_multiple_amount(_route, _swapParams, _smallAmount, _factorySwapAddresses, curve.constantOptions);
183
- }
184
- const priceImpactBN = _get_price_impact(_amount, _output, _smallAmount, _smallOutput, inputCoinDecimals, outputCoinDecimals);
185
- return Number(_cutZeros(priceImpactBN.toFixed(4)));
186
- };
187
- export const swapIsApproved = async (inputCoin, amount) => {
188
- return await hasAllowance([inputCoin], [amount], curve.signerAddress, curve.constants.ALIASES.registry_exchange);
189
- };
190
- export const swapApproveEstimateGas = async (inputCoin, amount) => {
191
- return await ensureAllowanceEstimateGas([inputCoin], [amount], curve.constants.ALIASES.registry_exchange);
192
- };
193
- export const swapApprove = async (inputCoin, amount) => {
194
- return await ensureAllowance([inputCoin], [amount], curve.constants.ALIASES.registry_exchange);
195
- };
196
- export const swapEstimateGas = async (inputCoin, outputCoin, amount) => {
197
- const [inputCoinAddress, outputCoinAddress] = _getCoinAddresses(inputCoin, outputCoin);
198
- const [inputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
199
- const { route } = await getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount);
200
- if (route.length === 0)
201
- return 0;
202
- const _amount = parseUnits(amount, inputCoinDecimals);
203
- const [gas] = await _estimateGasForDifferentRoutes([route], inputCoinAddress, outputCoinAddress, _amount);
204
- return gas;
205
- };
206
- export const swap = async (inputCoin, outputCoin, amount, slippage = 0.5) => {
207
- const [inputCoinAddress, outputCoinAddress] = _getCoinAddresses(inputCoin, outputCoin);
208
- const [inputCoinDecimals, outputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
209
- await swapApprove(inputCoin, amount);
210
- const { route, output } = await getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount);
211
- if (route.length === 0) {
212
- throw new Error("This pair can't be exchanged");
213
- }
214
- const { _route, _swapParams, _factorySwapAddresses } = _getExchangeMultipleArgs(route);
215
- const _amount = parseUnits(amount, inputCoinDecimals);
216
- const minRecvAmountBN = BN(output).times(100 - slippage).div(100);
217
- const _minRecvAmount = fromBN(minRecvAmountBN, outputCoinDecimals);
218
- const contract = curve.contracts[curve.constants.ALIASES.registry_exchange].contract;
219
- const value = isEth(inputCoinAddress) ? _amount : 0n;
220
- await curve.updateFeeData();
221
- const gasLimit = (await contract.exchange_multiple.estimateGas(_route, _swapParams, _amount, _minRecvAmount, _factorySwapAddresses, { ...curve.constantOptions, value })) * (curve.chainId === 1 ? 130n : 160n) / 100n;
222
- return await contract.exchange_multiple(_route, _swapParams, _amount, _minRecvAmount, _factorySwapAddresses, { ...curve.options, value, gasLimit });
223
- };
224
- export const getSwappedAmount = async (tx, outputCoin) => {
225
- const [outputCoinAddress] = _getCoinAddresses(outputCoin);
226
- const [outputCoinDecimals] = _getCoinDecimals(outputCoinAddress);
227
- const txInfo = await tx.wait();
228
- if (txInfo === null)
229
- return '0.0';
230
- let res;
231
- for (let i = 1; i <= txInfo.logs.length; i++) {
232
- try {
233
- const abiCoder = ethers.AbiCoder.defaultAbiCoder();
234
- res = abiCoder.decode(['address[9]', 'uint256[3][4]', 'address[4]', 'uint256', 'uint256'], ethers.dataSlice(txInfo.logs[txInfo.logs.length - i].data, 0));
235
- break;
236
- }
237
- catch (err) { }
238
- }
239
- if (res === undefined)
240
- return '0.0';
241
- return curve.formatUnits(res[res.length - 1], outputCoinDecimals);
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) }];
550
+ }
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
+ });
242
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
+ }); };