@curvefi/api 2.63.0 → 2.63.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 (83) hide show
  1. package/lib/boosting.js +247 -645
  2. package/lib/constants/L2Networks.js +1 -1
  3. package/lib/constants/aliases.js +19 -19
  4. package/lib/constants/coins/arbitrum.js +5 -5
  5. package/lib/constants/coins/aurora.js +5 -5
  6. package/lib/constants/coins/avalanche.js +6 -6
  7. package/lib/constants/coins/base.js +5 -5
  8. package/lib/constants/coins/bsc.js +5 -5
  9. package/lib/constants/coins/celo.js +5 -5
  10. package/lib/constants/coins/ethereum.js +9 -9
  11. package/lib/constants/coins/fantom.js +7 -7
  12. package/lib/constants/coins/fraxtal.js +5 -5
  13. package/lib/constants/coins/kava.js +5 -5
  14. package/lib/constants/coins/mantle.js +5 -5
  15. package/lib/constants/coins/moonbeam.js +5 -5
  16. package/lib/constants/coins/optimism.js +5 -5
  17. package/lib/constants/coins/polygon.js +6 -6
  18. package/lib/constants/coins/xdai.js +5 -5
  19. package/lib/constants/coins/xlayer.js +5 -5
  20. package/lib/constants/coins/zksync.js +5 -5
  21. package/lib/constants/pools/arbitrum.js +1 -1
  22. package/lib/constants/pools/aurora.js +1 -1
  23. package/lib/constants/pools/avalanche.js +1 -1
  24. package/lib/constants/pools/base.js +1 -1
  25. package/lib/constants/pools/bsc.js +1 -1
  26. package/lib/constants/pools/celo.js +1 -1
  27. package/lib/constants/pools/ethereum.js +2 -2
  28. package/lib/constants/pools/fantom.js +1 -1
  29. package/lib/constants/pools/fraxtal.js +1 -1
  30. package/lib/constants/pools/kava.js +1 -1
  31. package/lib/constants/pools/mantle.js +1 -1
  32. package/lib/constants/pools/moonbeam.js +1 -1
  33. package/lib/constants/pools/optimism.js +1 -1
  34. package/lib/constants/pools/polygon.js +1 -1
  35. package/lib/constants/pools/xdai.js +1 -1
  36. package/lib/constants/pools/xlayer.js +1 -1
  37. package/lib/constants/pools/zksync.js +1 -1
  38. package/lib/constants/tricryptoDeployImplementations.js +1 -1
  39. package/lib/constants/utils.js +18 -19
  40. package/lib/constants/volumeNetworks.js +1 -1
  41. package/lib/curve.d.ts +3 -1
  42. package/lib/curve.js +534 -909
  43. package/lib/dao.js +351 -705
  44. package/lib/external-api.js +127 -256
  45. package/lib/factory/common.js +4 -4
  46. package/lib/factory/constants-crypto.js +33 -33
  47. package/lib/factory/constants.js +34 -34
  48. package/lib/factory/deploy.js +542 -907
  49. package/lib/factory/factory-api.js +205 -269
  50. package/lib/factory/factory-crypto.js +202 -342
  51. package/lib/factory/factory-tricrypto.js +164 -286
  52. package/lib/factory/factory-twocrypto.js +151 -269
  53. package/lib/factory/factory.js +245 -385
  54. package/lib/index.js +109 -198
  55. package/lib/interfaces.d.ts +1 -6
  56. package/lib/pools/PoolTemplate.js +1773 -3025
  57. package/lib/pools/gaugePool.js +112 -251
  58. package/lib/pools/mixins/common.js +22 -93
  59. package/lib/pools/mixins/depositBalancedAmountsMixins.js +52 -118
  60. package/lib/pools/mixins/depositMixins.js +160 -386
  61. package/lib/pools/mixins/depositWrappedMixins.js +79 -205
  62. package/lib/pools/mixins/poolBalancesMixin.js +24 -87
  63. package/lib/pools/mixins/swapMixins.js +139 -324
  64. package/lib/pools/mixins/swapWrappedMixins.js +111 -265
  65. package/lib/pools/mixins/withdrawExpectedMixins.js +27 -91
  66. package/lib/pools/mixins/withdrawImbalanceMixins.js +111 -293
  67. package/lib/pools/mixins/withdrawImbalanceWrappedMixins.js +58 -169
  68. package/lib/pools/mixins/withdrawMixins.js +139 -359
  69. package/lib/pools/mixins/withdrawOneCoinExpectedMixins.js +20 -75
  70. package/lib/pools/mixins/withdrawOneCoinMixins.js +140 -360
  71. package/lib/pools/mixins/withdrawOneCoinWrappedExpectedMixins.js +10 -51
  72. package/lib/pools/mixins/withdrawOneCoinWrappedMixins.js +60 -167
  73. package/lib/pools/mixins/withdrawWrappedMixins.js +57 -167
  74. package/lib/pools/poolConstructor.js +5 -25
  75. package/lib/pools/utils.js +301 -469
  76. package/lib/route-finder.worker.d.ts +9 -0
  77. package/lib/route-finder.worker.js +112 -0
  78. package/lib/route-graph.worker.d.ts +11 -0
  79. package/lib/route-graph.worker.js +334 -0
  80. package/lib/router.js +323 -912
  81. package/lib/utils.d.ts +5 -4
  82. package/lib/utils.js +539 -918
  83. package/package.json +1 -1
package/lib/router.js CHANGED
@@ -1,14 +1,3 @@
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
1
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
2
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
3
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -18,510 +7,75 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
18
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
19
8
  });
20
9
  };
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
- };
57
10
  import axios from "axios";
58
11
  import memoize from "memoizee";
59
12
  import { ethers } from "ethers";
60
13
  import { curve } from "./curve.js";
61
- import { _getCoinAddresses, _getCoinDecimals, _getUsdRate, ensureAllowance, ensureAllowanceEstimateGas, fromBN, hasAllowance, isEth, toBN, BN, parseUnits, _cutZeros, ETH_ADDRESS, _get_small_x, _get_price_impact, DIGas, smartNumber, getTxCostsUsd, getGasPriceFromL1, } from "./utils.js";
14
+ import { _cutZeros, _get_price_impact, _get_small_x, _getCoinAddresses, _getCoinDecimals, _getUsdRate, BN, DIGas, ensureAllowance, ensureAllowanceEstimateGas, ETH_ADDRESS, fromBN, getGasPriceFromL1, getTxCostsUsd, hasAllowance, isEth, parseUnits, runWorker, smartNumber, toBN, } from "./utils.js";
62
15
  import { getPool } from "./pools/index.js";
63
16
  import { _getAmplificationCoefficientsFromApi } from "./pools/utils.js";
64
17
  import { L2Networks } from "./constants/L2Networks.js";
65
- var MAX_STEPS = 5;
66
- var ROUTE_LENGTH = (MAX_STEPS * 2) + 1;
67
- var GRAPH_MAX_EDGES = 3;
68
- var MAX_ROUTES_FOR_ONE_COIN = 5;
69
- var OLD_CHAINS = [1, 10, 56, 100, 137, 250, 1284, 2222, 8453, 42161, 42220, 43114, 1313161554]; // these chains have non-ng pools
70
- var _removeDuplications = function (routes) {
71
- return routes.filter(function (r, i, _routes) {
72
- var routesByPoolIds = _routes.map(function (r) { return r.route.map(function (s) { return s.poolId; }).toString(); });
73
- return routesByPoolIds.indexOf(r.route.map(function (s) { return s.poolId; }).toString()) === i;
74
- });
75
- };
76
- var _sortByTvl = function (a, b) { return b.minTvl - a.minTvl || b.totalTvl - a.totalTvl || a.route.length - b.route.length; };
77
- var _sortByLength = function (a, b) { return a.route.length - b.route.length || b.minTvl - a.minTvl || b.totalTvl - a.totalTvl; };
78
- var _getTVL = memoize(function (poolId) { return __awaiter(void 0, void 0, void 0, function () { var _a; return __generator(this, function (_b) {
79
- switch (_b.label) {
80
- case 0:
81
- _a = Number;
82
- return [4 /*yield*/, (getPool(poolId)).stats.totalLiquidity()];
83
- case 1: return [2 /*return*/, _a.apply(void 0, [_b.sent()])];
84
- }
85
- }); }); }, {
18
+ import { routeFinderWorker, routeFinderWorkerCode } from "./route-finder.worker.js";
19
+ import { routeGraphWorker, routeGraphWorkerCode } from "./route-graph.worker.js";
20
+ const MAX_STEPS = 5;
21
+ const ROUTE_LENGTH = (MAX_STEPS * 2) + 1;
22
+ const OLD_CHAINS = [1, 10, 56, 100, 137, 250, 1284, 2222, 8453, 42161, 42220, 43114, 1313161554]; // these chains have non-ng pools
23
+ const _getTVL = memoize((poolId) => __awaiter(void 0, void 0, void 0, function* () { return Number(yield (getPool(poolId)).stats.totalLiquidity()); }), {
86
24
  promise: true,
87
25
  maxAge: 5 * 60 * 1000, // 5m
88
26
  });
89
- // 4 --> 6, 5 --> 7 not allowed
90
- // 4 --> 7, 5 --> 6 allowed
91
- var _handleSwapType = function (swapType) {
92
- if (swapType === 6)
93
- return "4";
94
- if (swapType === 7)
95
- return "5";
96
- return swapType.toString();
97
- };
98
- var SNX = {
99
- 10: {
100
- swap: "0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4".toLowerCase(),
101
- coins: [
102
- "0x8c6f28f2f1a3c87f0f938b96d27520d9751ec8d9",
103
- "0xFBc4198702E81aE77c06D58f81b629BDf36f0a71",
104
- "0xe405de8f52ba7559f9df3c368500b6e6ae6cee49",
105
- "0x298b9b95708152ff6968aafd889c6586e9169f1d", // sBTC
106
- ].map(function (a) { return a.toLowerCase(); }),
107
- },
108
- };
109
- var _buildRouteGraph = memoize(function () { return __awaiter(void 0, void 0, void 0, function () {
110
- var routerGraph, _i, _a, outCoin, _b, _c, inCoin, _d, _e, outCoin, ALL_POOLS, amplificationCoefficientDict, _f, ALL_POOLS_1, _h, poolId, poolData, wrappedCoinAddresses, underlyingCoinAddresses, poolAddress, tokenAddress, isAaveLikeLending, poolType, tvlMultiplier, basePool, basePoolAddress, baseTokenAddress, secondBasePool, secondBasePoolAddress, secondBaseTokenAddress, metaCoinAddresses, swapAddress, tvl, excludedUnderlyingSwaps, coins, k, l, i, j, swapType, coins, k, l, i, j, swapType, i, j, i, j, hasEth, swapType;
111
- var _j, _k, _l;
112
- return __generator(this, function (_m) {
113
- switch (_m.label) {
114
- case 0:
115
- routerGraph = {};
116
- // ETH <-> WETH (exclude Celo)
117
- if (curve.chainId !== 42220) {
118
- routerGraph[curve.constants.NATIVE_TOKEN.address] = {};
119
- routerGraph[curve.constants.NATIVE_TOKEN.address][curve.constants.NATIVE_TOKEN.wrappedAddress] = [{
120
- poolId: "WETH wrapper",
121
- swapAddress: curve.constants.NATIVE_TOKEN.wrappedAddress,
122
- inputCoinAddress: curve.constants.NATIVE_TOKEN.address,
123
- outputCoinAddress: curve.constants.NATIVE_TOKEN.wrappedAddress,
124
- swapParams: [0, 0, 8, 0, 0],
125
- poolAddress: curve.constants.ZERO_ADDRESS,
126
- basePool: curve.constants.ZERO_ADDRESS,
127
- baseToken: curve.constants.ZERO_ADDRESS,
128
- secondBasePool: curve.constants.ZERO_ADDRESS,
129
- secondBaseToken: curve.constants.ZERO_ADDRESS,
130
- tvl: Infinity,
131
- }];
132
- routerGraph[curve.constants.NATIVE_TOKEN.wrappedAddress] = {};
133
- routerGraph[curve.constants.NATIVE_TOKEN.wrappedAddress][curve.constants.NATIVE_TOKEN.address] = [{
134
- poolId: "WETH wrapper",
135
- swapAddress: curve.constants.NATIVE_TOKEN.wrappedAddress,
136
- inputCoinAddress: curve.constants.NATIVE_TOKEN.wrappedAddress,
137
- outputCoinAddress: curve.constants.NATIVE_TOKEN.address,
138
- swapParams: [0, 0, 8, 0, 0],
139
- poolAddress: curve.constants.ZERO_ADDRESS,
140
- basePool: curve.constants.ZERO_ADDRESS,
141
- baseToken: curve.constants.ZERO_ADDRESS,
142
- secondBasePool: curve.constants.ZERO_ADDRESS,
143
- secondBaseToken: curve.constants.ZERO_ADDRESS,
144
- tvl: Infinity,
145
- }];
146
- }
147
- // ETH -> stETH, ETH -> frxETH, ETH -> wBETH (Ethereum only)
148
- if (curve.chainId == 1) {
149
- for (_i = 0, _a = ["stETH", "frxETH", "wBETH"]; _i < _a.length; _i++) {
150
- outCoin = _a[_i];
151
- routerGraph[curve.constants.NATIVE_TOKEN.address][curve.constants.COINS[outCoin.toLowerCase()]] = [{
152
- poolId: outCoin + " minter",
153
- swapAddress: outCoin === "frxETH" ? "0xbAFA44EFE7901E04E39Dad13167D089C559c1138".toLowerCase() : curve.constants.COINS[outCoin.toLowerCase()],
154
- inputCoinAddress: curve.constants.NATIVE_TOKEN.address,
155
- outputCoinAddress: curve.constants.COINS[outCoin.toLowerCase()],
156
- swapParams: [0, 0, 8, 0, 0],
157
- poolAddress: curve.constants.ZERO_ADDRESS,
158
- basePool: curve.constants.ZERO_ADDRESS,
159
- baseToken: curve.constants.ZERO_ADDRESS,
160
- secondBasePool: curve.constants.ZERO_ADDRESS,
161
- secondBaseToken: curve.constants.ZERO_ADDRESS,
162
- tvl: Infinity,
163
- }];
164
- }
165
- }
166
- // stETH <-> wstETH (Ethereum only)
167
- if (curve.chainId === 1) {
168
- routerGraph[curve.constants.COINS.steth] = {};
169
- routerGraph[curve.constants.COINS.steth][curve.constants.COINS.wsteth] = [{
170
- poolId: "wstETH wrapper",
171
- swapAddress: curve.constants.COINS.wsteth,
172
- inputCoinAddress: curve.constants.COINS.steth,
173
- outputCoinAddress: curve.constants.COINS.wsteth,
174
- swapParams: [0, 0, 8, 0, 0],
175
- poolAddress: curve.constants.ZERO_ADDRESS,
176
- basePool: curve.constants.ZERO_ADDRESS,
177
- baseToken: curve.constants.ZERO_ADDRESS,
178
- secondBasePool: curve.constants.ZERO_ADDRESS,
179
- secondBaseToken: curve.constants.ZERO_ADDRESS,
180
- tvl: Infinity,
181
- }];
182
- routerGraph[curve.constants.COINS.wsteth] = {};
183
- routerGraph[curve.constants.COINS.wsteth][curve.constants.COINS.steth] = [{
184
- poolId: "wstETH wrapper",
185
- swapAddress: curve.constants.COINS.wsteth,
186
- inputCoinAddress: curve.constants.COINS.wsteth,
187
- outputCoinAddress: curve.constants.COINS.steth,
188
- swapParams: [0, 0, 8, 0, 0],
189
- poolAddress: curve.constants.ZERO_ADDRESS,
190
- basePool: curve.constants.ZERO_ADDRESS,
191
- baseToken: curve.constants.ZERO_ADDRESS,
192
- secondBasePool: curve.constants.ZERO_ADDRESS,
193
- secondBaseToken: curve.constants.ZERO_ADDRESS,
194
- tvl: Infinity,
195
- }];
196
- }
197
- // frxETH <-> sfrxETH (Ethereum only)
198
- if (curve.chainId === 1) {
199
- routerGraph[curve.constants.COINS.frxeth] = {};
200
- routerGraph[curve.constants.COINS.frxeth][curve.constants.COINS.sfrxeth] = [{
201
- poolId: "sfrxETH wrapper",
202
- swapAddress: curve.constants.COINS.sfrxeth,
203
- inputCoinAddress: curve.constants.COINS.frxeth,
204
- outputCoinAddress: curve.constants.COINS.sfrxeth,
205
- swapParams: [0, 0, 8, 0, 0],
206
- poolAddress: curve.constants.ZERO_ADDRESS,
207
- basePool: curve.constants.ZERO_ADDRESS,
208
- baseToken: curve.constants.ZERO_ADDRESS,
209
- secondBasePool: curve.constants.ZERO_ADDRESS,
210
- secondBaseToken: curve.constants.ZERO_ADDRESS,
211
- tvl: Infinity,
212
- }];
213
- routerGraph[curve.constants.COINS.sfrxeth] = {};
214
- routerGraph[curve.constants.COINS.sfrxeth][curve.constants.COINS.frxeth] = [{
215
- poolId: "sfrxETH wrapper",
216
- swapAddress: curve.constants.COINS.sfrxeth,
217
- inputCoinAddress: curve.constants.COINS.sfrxeth,
218
- outputCoinAddress: curve.constants.COINS.frxeth,
219
- swapParams: [0, 0, 8, 0, 0],
220
- poolAddress: curve.constants.ZERO_ADDRESS,
221
- basePool: curve.constants.ZERO_ADDRESS,
222
- baseToken: curve.constants.ZERO_ADDRESS,
223
- secondBasePool: curve.constants.ZERO_ADDRESS,
224
- secondBaseToken: curve.constants.ZERO_ADDRESS,
225
- tvl: Infinity,
226
- }];
227
- }
228
- // SNX swaps
229
- if (curve.chainId in SNX) {
230
- // @ts-ignore
231
- for (_b = 0, _c = SNX[curve.chainId].coins; _b < _c.length; _b++) {
232
- inCoin = _c[_b];
233
- // @ts-ignore
234
- for (_d = 0, _e = SNX[curve.chainId].coins; _d < _e.length; _d++) {
235
- outCoin = _e[_d];
236
- if (inCoin === outCoin)
237
- continue;
238
- if (!routerGraph[inCoin])
239
- routerGraph[inCoin] = {};
240
- routerGraph[inCoin][outCoin] = [{
241
- poolId: "SNX exchanger",
242
- // @ts-ignore
243
- swapAddress: SNX[curve.chainId].swap,
244
- inputCoinAddress: inCoin,
245
- outputCoinAddress: outCoin,
246
- swapParams: [0, 0, 9, 0, 0],
247
- poolAddress: curve.constants.ZERO_ADDRESS,
248
- basePool: curve.constants.ZERO_ADDRESS,
249
- baseToken: curve.constants.ZERO_ADDRESS,
250
- secondBasePool: curve.constants.ZERO_ADDRESS,
251
- secondBaseToken: curve.constants.ZERO_ADDRESS,
252
- tvl: Infinity,
253
- }];
254
- }
255
- }
256
- }
257
- ALL_POOLS = Object.entries(curve.getPoolsData()).filter(function (_a) {
258
- var id = _a[0], _ = _a[1];
259
- return !["crveth", "y", "busd", "pax"].includes(id);
260
- });
261
- return [4 /*yield*/, _getAmplificationCoefficientsFromApi()];
262
- case 1:
263
- amplificationCoefficientDict = _m.sent();
264
- _f = 0, ALL_POOLS_1 = ALL_POOLS;
265
- _m.label = 2;
266
- case 2:
267
- if (!(_f < ALL_POOLS_1.length)) return [3 /*break*/, 5];
268
- _h = ALL_POOLS_1[_f], poolId = _h[0], poolData = _h[1];
269
- wrappedCoinAddresses = poolData.wrapped_coin_addresses.map(function (a) { return a.toLowerCase(); });
270
- underlyingCoinAddresses = poolData.underlying_coin_addresses.map(function (a) { return a.toLowerCase(); });
271
- poolAddress = poolData.swap_address.toLowerCase();
272
- tokenAddress = poolData.token_address.toLowerCase();
273
- isAaveLikeLending = poolData.is_lending && wrappedCoinAddresses.length === 3 && !poolData.deposit_address;
274
- poolType = poolData.is_llamma ? 4 : poolData.is_crypto ? Math.min(poolData.wrapped_coins.length, 3) : 1;
275
- if (poolData.is_ng)
276
- poolType *= 10;
277
- tvlMultiplier = poolData.is_crypto ? 1 : ((_j = amplificationCoefficientDict[poolData.swap_address]) !== null && _j !== void 0 ? _j : 1);
278
- basePool = poolData.is_meta ? __assign(__assign({}, curve.constants.POOLS_DATA), curve.constants.FACTORY_POOLS_DATA)[poolData.base_pool] : null;
279
- basePoolAddress = basePool ? basePool.swap_address.toLowerCase() : curve.constants.ZERO_ADDRESS;
280
- baseTokenAddress = basePool ? basePool.token_address.toLowerCase() : curve.constants.ZERO_ADDRESS;
281
- secondBasePool = basePool && basePool.base_pool ? __assign(__assign(__assign({}, curve.constants.POOLS_DATA), curve.constants.FACTORY_POOLS_DATA), curve.constants.CRVUSD_FACTORY_POOLS_DATA)[basePool.base_pool] : null;
282
- secondBasePoolAddress = secondBasePool ? secondBasePool.swap_address.toLowerCase() : curve.constants.ZERO_ADDRESS;
283
- // for double meta underlying (crv/tricrypto, wmatic/tricrypto)
284
- if (basePool && secondBasePoolAddress !== curve.constants.ZERO_ADDRESS)
285
- baseTokenAddress = (_k = basePool.deposit_address) === null || _k === void 0 ? void 0 : _k.toLowerCase();
286
- secondBaseTokenAddress = secondBasePool ? secondBasePool.token_address.toLowerCase() : curve.constants.ZERO_ADDRESS;
287
- metaCoinAddresses = basePool ? basePool.underlying_coin_addresses.map(function (a) { return a.toLowerCase(); }) : [];
288
- swapAddress = poolData.is_fake ? (_l = poolData.deposit_address) === null || _l === void 0 ? void 0 : _l.toLowerCase() : poolAddress;
289
- return [4 /*yield*/, _getTVL(poolId)];
290
- case 3:
291
- tvl = (_m.sent()) * tvlMultiplier;
292
- // Skip empty pools
293
- if (curve.chainId === 1 && tvl < 1000)
294
- return [3 /*break*/, 4];
295
- if (curve.chainId !== 1 && tvl < 100)
296
- return [3 /*break*/, 4];
297
- excludedUnderlyingSwaps = (poolId === 'ib' && curve.chainId === 1) ||
298
- (poolId === 'geist' && curve.chainId === 250) ||
299
- (poolId === 'saave' && curve.chainId === 1);
300
- // Wrapped coin <-> LP "swaps" (actually add_liquidity/remove_liquidity_one_coin)
301
- if (!poolData.is_fake && !poolData.is_llamma && wrappedCoinAddresses.length < 6) {
302
- coins = __spreadArray([tokenAddress], wrappedCoinAddresses, true);
303
- for (k = 0; k < coins.length; k++) {
304
- for (l = 0; l < coins.length; l++) {
305
- if (k > 0 && l > 0)
306
- continue;
307
- if (k == 0 && l == 0)
308
- continue;
309
- i = Math.max(k - 1, 0);
310
- j = Math.max(l - 1, 0);
311
- swapType = k == 0 ? 6 : 4;
312
- if (!routerGraph[coins[k]])
313
- routerGraph[coins[k]] = {};
314
- if (!routerGraph[coins[k]][coins[l]])
315
- routerGraph[coins[k]][coins[l]] = [];
316
- routerGraph[coins[k]][coins[l]].push({
317
- poolId: poolId,
318
- swapAddress: swapAddress,
319
- inputCoinAddress: coins[k],
320
- outputCoinAddress: coins[l],
321
- swapParams: [i, j, swapType, poolType, wrappedCoinAddresses.length],
322
- poolAddress: curve.constants.ZERO_ADDRESS,
323
- basePool: curve.constants.ZERO_ADDRESS,
324
- baseToken: curve.constants.ZERO_ADDRESS,
325
- secondBasePool: curve.constants.ZERO_ADDRESS,
326
- secondBaseToken: curve.constants.ZERO_ADDRESS,
327
- tvl: tvl,
328
- });
329
- }
330
- }
331
- }
332
- // Underlying coin <-> LP "swaps" (actually add_liquidity/remove_liquidity_one_coin)
333
- if ((poolData.is_fake || isAaveLikeLending) && underlyingCoinAddresses.length < 6 && !excludedUnderlyingSwaps) {
334
- coins = __spreadArray([tokenAddress], underlyingCoinAddresses, true);
335
- for (k = 0; k < coins.length; k++) {
336
- for (l = 0; l < coins.length; l++) {
337
- if (k > 0 && l > 0)
338
- continue;
339
- if (k == 0 && l == 0)
340
- continue;
341
- i = Math.max(k - 1, 0);
342
- j = Math.max(l - 1, 0);
343
- swapType = isAaveLikeLending ? 7 : 6;
344
- if (k > 0)
345
- swapType = isAaveLikeLending ? 5 : 4;
346
- if (!routerGraph[coins[k]])
347
- routerGraph[coins[k]] = {};
348
- if (!routerGraph[coins[k]][coins[l]])
349
- routerGraph[coins[k]][coins[l]] = [];
350
- routerGraph[coins[k]][coins[l]].push({
351
- poolId: poolId,
352
- swapAddress: swapAddress,
353
- inputCoinAddress: coins[k],
354
- outputCoinAddress: coins[l],
355
- swapParams: [i, j, swapType, poolType, underlyingCoinAddresses.length],
356
- poolAddress: curve.constants.ZERO_ADDRESS,
357
- basePool: curve.constants.ZERO_ADDRESS,
358
- baseToken: curve.constants.ZERO_ADDRESS,
359
- secondBasePool: curve.constants.ZERO_ADDRESS,
360
- secondBaseToken: curve.constants.ZERO_ADDRESS,
361
- tvl: tvl,
362
- });
363
- }
364
- }
365
- }
366
- // Wrapped swaps
367
- if (!poolData.is_fake) {
368
- for (i = 0; i < wrappedCoinAddresses.length; i++) {
369
- for (j = 0; j < wrappedCoinAddresses.length; j++) {
370
- if (i == j)
371
- continue;
372
- if (!routerGraph[wrappedCoinAddresses[i]])
373
- routerGraph[wrappedCoinAddresses[i]] = {};
374
- if (!routerGraph[wrappedCoinAddresses[i]][wrappedCoinAddresses[j]])
375
- routerGraph[wrappedCoinAddresses[i]][wrappedCoinAddresses[j]] = [];
376
- routerGraph[wrappedCoinAddresses[i]][wrappedCoinAddresses[j]] = routerGraph[wrappedCoinAddresses[i]][wrappedCoinAddresses[j]].concat({
377
- poolId: poolId,
378
- swapAddress: swapAddress,
379
- inputCoinAddress: wrappedCoinAddresses[i],
380
- outputCoinAddress: wrappedCoinAddresses[j],
381
- swapParams: [i, j, 1, poolType, wrappedCoinAddresses.length],
382
- poolAddress: poolAddress,
383
- basePool: basePoolAddress,
384
- baseToken: baseTokenAddress,
385
- secondBasePool: secondBasePoolAddress,
386
- secondBaseToken: secondBaseTokenAddress,
387
- tvl: tvl,
388
- }).sort(function (a, b) { return b.tvl - a.tvl; }).slice(0, GRAPH_MAX_EDGES);
389
- }
390
- }
391
- }
392
- // Only for underlying swaps
393
- swapAddress = (poolData.is_crypto && poolData.is_meta) || ((basePool === null || basePool === void 0 ? void 0 : basePool.is_lending) && poolData.is_factory) ?
394
- poolData.deposit_address : poolData.swap_address;
395
- // Underlying swaps
396
- if (!poolData.is_plain && !excludedUnderlyingSwaps) {
397
- for (i = 0; i < underlyingCoinAddresses.length; i++) {
398
- for (j = 0; j < underlyingCoinAddresses.length; j++) {
399
- if (i === j)
400
- continue;
401
- // Don't swap metacoins since they can be swapped directly in base pool
402
- if (metaCoinAddresses.includes(underlyingCoinAddresses[i]) && metaCoinAddresses.includes(underlyingCoinAddresses[j]))
403
- continue;
404
- // avWBTC is frozen by Aave on Avalanche, deposits are not working
405
- if (curve.chainId === 43114 && poolId === "atricrypto" && i === 3)
406
- continue;
407
- hasEth = underlyingCoinAddresses.includes(curve.constants.NATIVE_TOKEN.address);
408
- swapType = (poolData.is_crypto && poolData.is_meta && poolData.is_factory) || ((basePool === null || basePool === void 0 ? void 0 : basePool.is_lending) && poolData.is_factory) ? 3
409
- : hasEth && poolId !== 'avaxcrypto' ? 1 : 2;
410
- if (!routerGraph[underlyingCoinAddresses[i]])
411
- routerGraph[underlyingCoinAddresses[i]] = {};
412
- if (!routerGraph[underlyingCoinAddresses[i]][underlyingCoinAddresses[j]])
413
- routerGraph[underlyingCoinAddresses[i]][underlyingCoinAddresses[j]] = [];
414
- routerGraph[underlyingCoinAddresses[i]][underlyingCoinAddresses[j]] = routerGraph[underlyingCoinAddresses[i]][underlyingCoinAddresses[j]].concat({
415
- poolId: poolId,
416
- swapAddress: swapAddress,
417
- inputCoinAddress: underlyingCoinAddresses[i],
418
- outputCoinAddress: underlyingCoinAddresses[j],
419
- swapParams: [i, j, swapType, poolType, underlyingCoinAddresses.length],
420
- poolAddress: poolAddress,
421
- basePool: basePoolAddress,
422
- baseToken: baseTokenAddress,
423
- secondBasePool: secondBasePoolAddress,
424
- secondBaseToken: secondBaseTokenAddress,
425
- tvl: tvl,
426
- }).sort(function (a, b) { return b.tvl - a.tvl; }).slice(0, GRAPH_MAX_EDGES);
427
- }
428
- }
429
- }
430
- _m.label = 4;
431
- case 4:
432
- _f++;
433
- return [3 /*break*/, 2];
434
- case 5: return [2 /*return*/, routerGraph];
435
- }
27
+ function entriesToDictAsync(entries, mapper) {
28
+ return __awaiter(this, void 0, void 0, function* () {
29
+ const result = {};
30
+ yield Promise.all(entries.map(([key, value]) => __awaiter(this, void 0, void 0, function* () { return result[key] = yield mapper(key, value); })));
31
+ return result;
436
32
  });
437
- }); }, {
33
+ }
34
+ function mapDict(dict, mapper) {
35
+ const result = {};
36
+ Object.entries(dict).forEach(([key, value]) => result[key] = mapper(key, value));
37
+ return result;
38
+ }
39
+ const _buildRouteGraph = memoize(() => __awaiter(void 0, void 0, void 0, function* () {
40
+ const constants = curve.constants;
41
+ const chainId = curve.chainId;
42
+ const allPools = Object.entries(curve.getPoolsData()).filter(([id]) => !["crveth", "y", "busd", "pax"].includes(id));
43
+ const amplificationCoefficientDict = yield _getAmplificationCoefficientsFromApi();
44
+ const poolTvlDict = yield entriesToDictAsync(allPools, _getTVL);
45
+ const input = { constants, chainId, allPools, amplificationCoefficientDict, poolTvlDict };
46
+ return runWorker(routeGraphWorkerCode, routeGraphWorker, Object.assign({ type: 'createRouteGraph' }, input));
47
+ }), {
438
48
  promise: true,
439
49
  maxAge: 5 * 1000, // 5m
440
50
  });
441
- var _isVisitedCoin = function (coinAddress, route) {
442
- return route.route.map(function (r) { return r.inputCoinAddress; }).includes(coinAddress);
443
- };
444
- var _isVisitedPool = function (poolId, route) {
445
- return route.route.map(function (r) { return r.poolId; }).includes(poolId);
446
- };
447
- // Breadth-first search
448
- var _findRoutes = function (inputCoinAddress, outputCoinAddress) { return __awaiter(void 0, void 0, void 0, function () {
449
- var routes, targetRoutes, routerGraph, ALL_POOLS, route, inCoin, outCoin, _i, _a, step, poolData, routePoolIdsPlusSwapType, poolCoins;
450
- return __generator(this, function (_b) {
451
- switch (_b.label) {
452
- case 0:
453
- inputCoinAddress = inputCoinAddress.toLowerCase();
454
- outputCoinAddress = outputCoinAddress.toLowerCase();
455
- routes = [{ route: [], minTvl: Infinity, totalTvl: 0 }];
456
- targetRoutes = [];
457
- return [4 /*yield*/, _buildRouteGraph()];
458
- case 1:
459
- routerGraph = _b.sent();
460
- ALL_POOLS = curve.getPoolsData();
461
- while (routes.length > 0) {
462
- route = routes.pop();
463
- inCoin = route.route.length > 0 ? route.route[route.route.length - 1].outputCoinAddress : inputCoinAddress;
464
- if (inCoin === outputCoinAddress) {
465
- targetRoutes.push(route);
466
- }
467
- else if (route.route.length < 5) {
468
- for (outCoin in routerGraph[inCoin]) {
469
- if (_isVisitedCoin(outCoin, route))
470
- continue;
471
- for (_i = 0, _a = routerGraph[inCoin][outCoin]; _i < _a.length; _i++) {
472
- step = _a[_i];
473
- poolData = ALL_POOLS[step.poolId];
474
- if (!(poolData === null || poolData === void 0 ? void 0 : poolData.is_lending) && _isVisitedPool(step.poolId, route))
475
- continue;
476
- routePoolIdsPlusSwapType = route.route.map(function (s) { return s.poolId + "+" + _handleSwapType(s.swapParams[2]); });
477
- if (routePoolIdsPlusSwapType.includes(step.poolId + "+" + _handleSwapType(step.swapParams[2])))
478
- continue;
479
- poolCoins = poolData ? poolData.wrapped_coin_addresses.concat(poolData.underlying_coin_addresses) : [];
480
- // Exclude such cases as:
481
- // cvxeth -> tricrypto2 -> tusd -> susd (cvxeth -> tricrypto2 -> tusd instead)
482
- if (!(poolData === null || poolData === void 0 ? void 0 : poolData.is_lending) && poolCoins.includes(outputCoinAddress) && outCoin !== outputCoinAddress)
483
- continue;
484
- // Exclude such cases as:
485
- // aave -> aave -> 3pool (aave -> aave instead)
486
- if ((poolData === null || poolData === void 0 ? void 0 : poolData.is_lending) && poolCoins.includes(outputCoinAddress) && outCoin !== outputCoinAddress && outCoin !== poolData.token_address)
487
- continue;
488
- routes.push({
489
- route: __spreadArray(__spreadArray([], route.route, true), [step], false),
490
- minTvl: Math.min(step.tvl, route.minTvl),
491
- totalTvl: route.totalTvl + step.tvl,
492
- });
493
- }
494
- }
495
- }
496
- }
497
- targetRoutes = _removeDuplications(__spreadArray(__spreadArray([], targetRoutes.sort(_sortByTvl).slice(0, MAX_ROUTES_FOR_ONE_COIN), true), targetRoutes.sort(_sortByLength).slice(0, MAX_ROUTES_FOR_ONE_COIN), true));
498
- return [2 /*return*/, targetRoutes.map(function (r) { return r.route; })];
499
- }
500
- });
501
- }); };
502
- var _getRouteKey = function (route, inputCoinAddress, outputCoinAddress) {
503
- var sortedCoins = [inputCoinAddress, outputCoinAddress].sort();
504
- var key = "".concat(sortedCoins[0], "-->");
505
- for (var _i = 0, route_1 = route; _i < route_1.length; _i++) {
506
- var routeStep = route_1[_i];
507
- key += "".concat(routeStep.poolId, "-->");
51
+ const _findRoutes = (inputCoinAddress, outputCoinAddress) => __awaiter(void 0, void 0, void 0, function* () {
52
+ const routerGraph = yield _buildRouteGraph();
53
+ // extract only the fields we need for the worker
54
+ const poolData = mapDict(curve.getPoolsData(), (_, { is_lending, wrapped_coin_addresses, underlying_coin_addresses, token_address }) => ({ is_lending, wrapped_coin_addresses, underlying_coin_addresses, token_address }));
55
+ const input = { inputCoinAddress, outputCoinAddress, routerGraph, poolData };
56
+ return runWorker(routeFinderWorkerCode, routeFinderWorker, Object.assign({ type: 'findRoutes' }, input));
57
+ });
58
+ const _getRouteKey = (route, inputCoinAddress, outputCoinAddress) => {
59
+ const sortedCoins = [inputCoinAddress, outputCoinAddress].sort();
60
+ let key = `${sortedCoins[0]}-->`;
61
+ for (const routeStep of route) {
62
+ key += `${routeStep.poolId}-->`;
508
63
  }
509
64
  key += sortedCoins[1];
510
65
  return key;
511
66
  };
512
- var _getExchangeArgs = function (route) {
67
+ const _getExchangeArgs = (route) => {
513
68
  if (OLD_CHAINS.includes(curve.chainId)) {
514
- var _route = [];
69
+ let _route = [];
515
70
  if (route.length > 0)
516
71
  _route.push(route[0].inputCoinAddress);
517
- var _swapParams = [];
518
- var _pools = [];
519
- var _basePools = [];
520
- var _baseTokens = [];
521
- var _secondBasePools = [];
522
- var _secondBaseTokens = [];
523
- for (var _i = 0, route_2 = route; _i < route_2.length; _i++) {
524
- var routeStep = route_2[_i];
72
+ let _swapParams = [];
73
+ let _pools = [];
74
+ let _basePools = [];
75
+ let _baseTokens = [];
76
+ let _secondBasePools = [];
77
+ let _secondBaseTokens = [];
78
+ for (const routeStep of route) {
525
79
  _route.push(routeStep.swapAddress, routeStep.outputCoinAddress);
526
80
  _swapParams.push(routeStep.swapParams);
527
81
  _pools.push(routeStep.poolAddress);
@@ -537,453 +91,310 @@ var _getExchangeArgs = function (route) {
537
91
  _baseTokens = _baseTokens.concat(Array(MAX_STEPS - _baseTokens.length).fill(curve.constants.ZERO_ADDRESS));
538
92
  _secondBasePools = _secondBasePools.concat(Array(MAX_STEPS - _secondBasePools.length).fill(curve.constants.ZERO_ADDRESS));
539
93
  _secondBaseTokens = _secondBaseTokens.concat(Array(MAX_STEPS - _secondBaseTokens.length).fill(curve.constants.ZERO_ADDRESS));
540
- return { _route: _route, _swapParams: _swapParams, _pools: _pools, _basePools: _basePools, _baseTokens: _baseTokens, _secondBasePools: _secondBasePools, _secondBaseTokens: _secondBaseTokens };
94
+ return { _route, _swapParams, _pools, _basePools, _baseTokens, _secondBasePools, _secondBaseTokens };
541
95
  }
542
96
  else { // RouterNgPoolsOnly
543
- var _route = [];
97
+ let _route = [];
544
98
  if (route.length > 0)
545
99
  _route.push(route[0].inputCoinAddress);
546
- var _swapParams = [];
547
- for (var _a = 0, route_3 = route; _a < route_3.length; _a++) {
548
- var routeStep = route_3[_a];
100
+ let _swapParams = [];
101
+ for (const routeStep of route) {
549
102
  _route.push(routeStep.swapAddress, routeStep.outputCoinAddress);
550
103
  _swapParams.push(routeStep.swapParams.slice(0, 4));
551
104
  }
552
105
  _route = _route.concat(Array(ROUTE_LENGTH - _route.length).fill(curve.constants.ZERO_ADDRESS));
553
106
  _swapParams = _swapParams.concat(Array(MAX_STEPS - _swapParams.length).fill([0, 0, 0, 0]));
554
- return { _route: _route, _swapParams: _swapParams };
107
+ return { _route, _swapParams };
555
108
  }
556
109
  };
557
- var _estimatedGasForDifferentRoutesCache = {};
558
- var _estimateGasForDifferentRoutes = function (routes, inputCoinAddress, outputCoinAddress, _amount) { return __awaiter(void 0, void 0, void 0, function () {
559
- var contract, gasPromises, value, _i, routes_1, route, routeKey, gasPromise, _a, _route, _swapParams, _pools, _gasAmounts_1, err_1;
560
- var _b;
561
- return __generator(this, function (_c) {
562
- switch (_c.label) {
563
- case 0:
564
- inputCoinAddress = inputCoinAddress.toLowerCase();
565
- outputCoinAddress = outputCoinAddress.toLowerCase();
566
- contract = curve.contracts[curve.constants.ALIASES.router].contract;
567
- gasPromises = [];
568
- value = isEth(inputCoinAddress) ? _amount : curve.parseUnits("0");
569
- for (_i = 0, routes_1 = routes; _i < routes_1.length; _i++) {
570
- route = routes_1[_i];
571
- routeKey = _getRouteKey(route, inputCoinAddress, outputCoinAddress);
572
- gasPromise = void 0;
573
- _a = _getExchangeArgs(route), _route = _a._route, _swapParams = _a._swapParams, _pools = _a._pools;
574
- if ((((_b = _estimatedGasForDifferentRoutesCache[routeKey]) === null || _b === void 0 ? void 0 : _b.time) || 0) + 3600000 < Date.now()) {
575
- if (_pools) {
576
- gasPromise = contract.exchange.estimateGas(_route, _swapParams, _amount, 0, _pools, __assign(__assign({}, curve.constantOptions), { value: value }));
577
- }
578
- else {
579
- gasPromise = contract.exchange.estimateGas(_route, _swapParams, _amount, 0, __assign(__assign({}, curve.constantOptions), { value: value }));
580
- }
581
- }
582
- else {
583
- gasPromise = Promise.resolve(_estimatedGasForDifferentRoutesCache[routeKey].gas);
584
- }
585
- gasPromises.push(gasPromise);
586
- }
587
- _c.label = 1;
588
- case 1:
589
- _c.trys.push([1, 3, , 4]);
590
- return [4 /*yield*/, Promise.all(gasPromises)];
591
- case 2:
592
- _gasAmounts_1 = _c.sent();
593
- routes.forEach(function (route, i) {
594
- var routeKey = _getRouteKey(route, inputCoinAddress, outputCoinAddress);
595
- _estimatedGasForDifferentRoutesCache[routeKey] = { 'gas': _gasAmounts_1[i], 'time': Date.now() };
596
- });
597
- return [2 /*return*/, _gasAmounts_1.map(function (_g) { return smartNumber(_g); })];
598
- case 3:
599
- err_1 = _c.sent();
600
- return [2 /*return*/, routes.map(function () { return 0; })];
601
- case 4: return [2 /*return*/];
110
+ const _estimatedGasForDifferentRoutesCache = {};
111
+ const _estimateGasForDifferentRoutes = (routes, inputCoinAddress, outputCoinAddress, _amount) => __awaiter(void 0, void 0, void 0, function* () {
112
+ var _a;
113
+ inputCoinAddress = inputCoinAddress.toLowerCase();
114
+ outputCoinAddress = outputCoinAddress.toLowerCase();
115
+ const contract = curve.contracts[curve.constants.ALIASES.router].contract;
116
+ const gasPromises = [];
117
+ const value = isEth(inputCoinAddress) ? _amount : curve.parseUnits("0");
118
+ for (const route of routes) {
119
+ const routeKey = _getRouteKey(route, inputCoinAddress, outputCoinAddress);
120
+ let gasPromise;
121
+ const { _route, _swapParams, _pools } = _getExchangeArgs(route);
122
+ if ((((_a = _estimatedGasForDifferentRoutesCache[routeKey]) === null || _a === void 0 ? void 0 : _a.time) || 0) + 3600000 < Date.now()) {
123
+ if (_pools) {
124
+ gasPromise = contract.exchange.estimateGas(_route, _swapParams, _amount, 0, _pools, Object.assign(Object.assign({}, curve.constantOptions), { value }));
125
+ }
126
+ else {
127
+ gasPromise = contract.exchange.estimateGas(_route, _swapParams, _amount, 0, Object.assign(Object.assign({}, curve.constantOptions), { value }));
128
+ }
602
129
  }
603
- });
604
- }); };
605
- var _getBestRoute = memoize(function (inputCoinAddress, outputCoinAddress, amount) { return __awaiter(void 0, void 0, void 0, function () {
606
- var _a, inputCoinDecimals, outputCoinDecimals, _amount, routesRaw, routes, calls, multicallContract, _i, routesRaw_1, r, _b, _route, _swapParams, _pools, _outputAmounts, i, err_2, contract, _outputs, _c, routesRaw_2, r, _d, _route, _swapParams, _pools, _e, _f, _h, _j, e_1, i, _k, gasAmounts, outputCoinUsdRate, gasData, ethUsdRate, gasPrice, expectedAmounts, expectedAmountsUsd, L1GasPrice, _l, txCostsUsd;
607
- return __generator(this, function (_m) {
608
- switch (_m.label) {
609
- case 0:
610
- _a = _getCoinDecimals(inputCoinAddress, outputCoinAddress), inputCoinDecimals = _a[0], outputCoinDecimals = _a[1];
611
- _amount = parseUnits(amount, inputCoinDecimals);
612
- if (_amount === curve.parseUnits("0"))
613
- return [2 /*return*/, []];
614
- return [4 /*yield*/, _findRoutes(inputCoinAddress, outputCoinAddress)];
615
- case 1:
616
- routesRaw = (_m.sent()).map(function (route) { return ({ route: route, _output: curve.parseUnits("0"), outputUsd: 0, txCostUsd: 0 }); });
617
- routes = [];
618
- _m.label = 2;
619
- case 2:
620
- _m.trys.push([2, 4, , 14]);
621
- calls = [];
622
- multicallContract = curve.contracts[curve.constants.ALIASES.router].multicallContract;
623
- for (_i = 0, routesRaw_1 = routesRaw; _i < routesRaw_1.length; _i++) {
624
- r = routesRaw_1[_i];
625
- _b = _getExchangeArgs(r.route), _route = _b._route, _swapParams = _b._swapParams, _pools = _b._pools;
626
- if (_pools) {
627
- calls.push(multicallContract.get_dy(_route, _swapParams, _amount, _pools));
628
- }
629
- else {
630
- calls.push(multicallContract.get_dy(_route, _swapParams, _amount));
631
- }
130
+ else {
131
+ gasPromise = Promise.resolve(_estimatedGasForDifferentRoutesCache[routeKey].gas);
132
+ }
133
+ gasPromises.push(gasPromise);
134
+ }
135
+ try {
136
+ const _gasAmounts = yield Promise.all(gasPromises);
137
+ routes.forEach((route, i) => {
138
+ const routeKey = _getRouteKey(route, inputCoinAddress, outputCoinAddress);
139
+ _estimatedGasForDifferentRoutesCache[routeKey] = { 'gas': _gasAmounts[i], 'time': Date.now() };
140
+ });
141
+ return _gasAmounts.map((_g) => smartNumber(_g));
142
+ }
143
+ catch (err) { // No allowance
144
+ return routes.map(() => 0);
145
+ }
146
+ });
147
+ const _getBestRoute = memoize((inputCoinAddress, outputCoinAddress, amount) => __awaiter(void 0, void 0, void 0, function* () {
148
+ const [inputCoinDecimals, outputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
149
+ const _amount = parseUnits(amount, inputCoinDecimals);
150
+ if (_amount === curve.parseUnits("0"))
151
+ return [];
152
+ const routesRaw = (yield _findRoutes(inputCoinAddress, outputCoinAddress)).map((route) => ({ route, _output: curve.parseUnits("0"), outputUsd: 0, txCostUsd: 0 }));
153
+ const routes = [];
154
+ try {
155
+ const calls = [];
156
+ const multicallContract = curve.contracts[curve.constants.ALIASES.router].multicallContract;
157
+ for (const r of routesRaw) {
158
+ const { _route, _swapParams, _pools } = _getExchangeArgs(r.route);
159
+ if (_pools) {
160
+ calls.push(multicallContract.get_dy(_route, _swapParams, _amount, _pools));
161
+ }
162
+ else {
163
+ calls.push(multicallContract.get_dy(_route, _swapParams, _amount));
164
+ }
165
+ }
166
+ const _outputAmounts = yield curve.multicallProvider.all(calls);
167
+ for (let i = 0; i < _outputAmounts.length; i++) {
168
+ routesRaw[i]._output = _outputAmounts[i];
169
+ routes.push(routesRaw[i]);
170
+ }
171
+ }
172
+ catch (err) {
173
+ // const promises = [];
174
+ // const contract = curve.contracts[curve.constants.ALIASES.router].contract;
175
+ // for (const r of routesRaw) {
176
+ // const { _route, _swapParams, _pools } = _getExchangeArgs(r.route);
177
+ // promises.push(contract.get_dy(_route, _swapParams, _amount, _pools, curve.constantOptions));
178
+ // }
179
+ //
180
+ // const res = await Promise.allSettled(promises);
181
+ //
182
+ // for (let i = 0; i < res.length; i++) {
183
+ // if (res[i].status === 'rejected') {
184
+ // console.log(`Route ${(routesRaw[i].route.map((s) => s.poolId)).join(" --> ")} is unavailable`);
185
+ // continue;
186
+ // }
187
+ // routesRaw[i]._output = (res[i] as PromiseFulfilledResult<bigint>).value;
188
+ // routes.push(routesRaw[i]);
189
+ // }
190
+ const contract = curve.contracts[curve.constants.ALIASES.router].contract;
191
+ const _outputs = [];
192
+ for (const r of routesRaw) {
193
+ const { _route, _swapParams, _pools } = _getExchangeArgs(r.route);
194
+ try {
195
+ if (_pools) {
196
+ _outputs.push(yield contract.get_dy(_route, _swapParams, _amount, _pools, curve.constantOptions));
632
197
  }
633
- return [4 /*yield*/, curve.multicallProvider.all(calls)];
634
- case 3:
635
- _outputAmounts = _m.sent();
636
- for (i = 0; i < _outputAmounts.length; i++) {
637
- routesRaw[i]._output = _outputAmounts[i];
638
- routes.push(routesRaw[i]);
198
+ else {
199
+ _outputs.push(yield contract.get_dy(_route, _swapParams, _amount, curve.constantOptions));
639
200
  }
640
- return [3 /*break*/, 14];
641
- case 4:
642
- err_2 = _m.sent();
643
- contract = curve.contracts[curve.constants.ALIASES.router].contract;
644
- _outputs = [];
645
- _c = 0, routesRaw_2 = routesRaw;
646
- _m.label = 5;
647
- case 5:
648
- if (!(_c < routesRaw_2.length)) return [3 /*break*/, 13];
649
- r = routesRaw_2[_c];
650
- _d = _getExchangeArgs(r.route), _route = _d._route, _swapParams = _d._swapParams, _pools = _d._pools;
651
- _m.label = 6;
652
- case 6:
653
- _m.trys.push([6, 11, , 12]);
654
- if (!_pools) return [3 /*break*/, 8];
655
- _f = (_e = _outputs).push;
656
- return [4 /*yield*/, contract.get_dy(_route, _swapParams, _amount, _pools, curve.constantOptions)];
657
- case 7:
658
- _f.apply(_e, [_m.sent()]);
659
- return [3 /*break*/, 10];
660
- case 8:
661
- _j = (_h = _outputs).push;
662
- return [4 /*yield*/, contract.get_dy(_route, _swapParams, _amount, curve.constantOptions)];
663
- case 9:
664
- _j.apply(_h, [_m.sent()]);
665
- _m.label = 10;
666
- case 10: return [3 /*break*/, 12];
667
- case 11:
668
- e_1 = _m.sent();
201
+ }
202
+ catch (e) {
669
203
  _outputs.push(curve.parseUnits('-1', 0));
670
- return [3 /*break*/, 12];
671
- case 12:
672
- _c++;
673
- return [3 /*break*/, 5];
674
- case 13:
675
- for (i = 0; i < _outputs.length; i++) {
676
- if (_outputs[i] < 0) {
677
- console.log("Route ".concat((routesRaw[i].route.map(function (s) { return s.poolId; })).join(" --> "), " is unavailable"));
678
- continue;
679
- }
680
- routesRaw[i]._output = _outputs[i];
681
- routes.push(routesRaw[i]);
682
- }
683
- return [3 /*break*/, 14];
684
- case 14:
685
- if (routes.length === 0)
686
- return [2 /*return*/, []];
687
- if (routes.length === 1)
688
- return [2 /*return*/, routes[0].route];
689
- return [4 /*yield*/, Promise.all([
690
- _estimateGasForDifferentRoutes(routes.map(function (r) { return r.route; }), inputCoinAddress, outputCoinAddress, _amount),
691
- _getUsdRate(outputCoinAddress),
692
- axios.get("https://api.curve.fi/api/getGas"),
693
- _getUsdRate(ETH_ADDRESS),
694
- ])];
695
- case 15:
696
- _k = _m.sent(), gasAmounts = _k[0], outputCoinUsdRate = _k[1], gasData = _k[2], ethUsdRate = _k[3];
697
- gasPrice = gasData.data.data.gas.standard;
698
- expectedAmounts = (routes).map(function (route) { return Number(curve.formatUnits(route._output, outputCoinDecimals)); });
699
- expectedAmountsUsd = expectedAmounts.map(function (a) { return a * outputCoinUsdRate; });
700
- if (!L2Networks.includes(curve.chainId)) return [3 /*break*/, 17];
701
- return [4 /*yield*/, getGasPriceFromL1()];
702
- case 16:
703
- _l = _m.sent();
704
- return [3 /*break*/, 18];
705
- case 17:
706
- _l = 0;
707
- _m.label = 18;
708
- case 18:
709
- L1GasPrice = _l;
710
- txCostsUsd = gasAmounts.map(function (a) { return getTxCostsUsd(ethUsdRate, gasPrice, a, L1GasPrice); });
711
- routes.forEach(function (route, i) {
712
- route.outputUsd = expectedAmountsUsd[i];
713
- route.txCostUsd = txCostsUsd[i];
714
- });
715
- return [2 /*return*/, routes.reduce(function (route1, route2) {
716
- var diff = (route1.outputUsd - route1.txCostUsd) - (route2.outputUsd - route2.txCostUsd);
717
- if (diff > 0)
718
- return route1;
719
- if (diff === 0 && route1.route.length < route2.route.length)
720
- return route1;
721
- return route2;
722
- }).route];
204
+ }
205
+ }
206
+ for (let i = 0; i < _outputs.length; i++) {
207
+ if (_outputs[i] < 0) {
208
+ console.log(`Route ${(routesRaw[i].route.map((s) => s.poolId)).join(" --> ")} is unavailable`);
209
+ continue;
210
+ }
211
+ routesRaw[i]._output = _outputs[i];
212
+ routes.push(routesRaw[i]);
723
213
  }
214
+ }
215
+ if (routes.length === 0)
216
+ return [];
217
+ if (routes.length === 1)
218
+ return routes[0].route;
219
+ const [gasAmounts, outputCoinUsdRate, gasData, ethUsdRate] = yield Promise.all([
220
+ _estimateGasForDifferentRoutes(routes.map((r) => r.route), inputCoinAddress, outputCoinAddress, _amount),
221
+ _getUsdRate(outputCoinAddress),
222
+ axios.get("https://api.curve.fi/api/getGas"),
223
+ _getUsdRate(ETH_ADDRESS),
224
+ ]);
225
+ const gasPrice = gasData.data.data.gas.standard;
226
+ const expectedAmounts = (routes).map((route) => Number(curve.formatUnits(route._output, outputCoinDecimals)));
227
+ const expectedAmountsUsd = expectedAmounts.map((a) => a * outputCoinUsdRate);
228
+ const L1GasPrice = L2Networks.includes(curve.chainId) ? yield getGasPriceFromL1() : 0;
229
+ const txCostsUsd = gasAmounts.map((a) => getTxCostsUsd(ethUsdRate, gasPrice, a, L1GasPrice));
230
+ routes.forEach((route, i) => {
231
+ route.outputUsd = expectedAmountsUsd[i];
232
+ route.txCostUsd = txCostsUsd[i];
724
233
  });
725
- }); }, {
234
+ return routes.reduce((route1, route2) => {
235
+ const diff = (route1.outputUsd - route1.txCostUsd) - (route2.outputUsd - route2.txCostUsd);
236
+ if (diff > 0)
237
+ return route1;
238
+ if (diff === 0 && route1.route.length < route2.route.length)
239
+ return route1;
240
+ return route2;
241
+ }).route;
242
+ }), {
726
243
  promise: true,
727
244
  maxAge: 5 * 60 * 1000, // 5m
728
245
  });
729
- var _getOutputForRoute = memoize(function (route, _amount) { return __awaiter(void 0, void 0, void 0, function () {
730
- var contract, _a, _route, _swapParams, _pools;
731
- return __generator(this, function (_b) {
732
- switch (_b.label) {
733
- case 0:
734
- contract = curve.contracts[curve.constants.ALIASES.router].contract;
735
- _a = _getExchangeArgs(route), _route = _a._route, _swapParams = _a._swapParams, _pools = _a._pools;
736
- if (!_pools) return [3 /*break*/, 2];
737
- return [4 /*yield*/, contract.get_dy(_route, _swapParams, _amount, _pools, curve.constantOptions)];
738
- case 1: return [2 /*return*/, _b.sent()];
739
- case 2: return [4 /*yield*/, contract.get_dy(_route, _swapParams, _amount, curve.constantOptions)];
740
- case 3: return [2 /*return*/, _b.sent()];
741
- }
742
- });
743
- }); }, {
246
+ const _getOutputForRoute = memoize((route, _amount) => __awaiter(void 0, void 0, void 0, function* () {
247
+ const contract = curve.contracts[curve.constants.ALIASES.router].contract;
248
+ const { _route, _swapParams, _pools } = _getExchangeArgs(route);
249
+ if (_pools) {
250
+ return yield contract.get_dy(_route, _swapParams, _amount, _pools, curve.constantOptions);
251
+ }
252
+ else {
253
+ return yield contract.get_dy(_route, _swapParams, _amount, curve.constantOptions);
254
+ }
255
+ }), {
744
256
  promise: true,
745
257
  maxAge: 15 * 1000, // 15s
746
258
  });
747
- var _routesCache = {};
748
- var _getBestRouteAndOutput = function (inputCoin, outputCoin, amount) {
749
- var _a = _getCoinAddresses(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
750
- var key = "".concat(inputCoinAddress, "-").concat(outputCoinAddress, "-").concat(amount);
259
+ const _routesCache = {};
260
+ const _getBestRouteAndOutput = (inputCoin, outputCoin, amount) => {
261
+ const [inputCoinAddress, outputCoinAddress] = _getCoinAddresses(inputCoin, outputCoin);
262
+ const key = `${inputCoinAddress}-${outputCoinAddress}-${amount}`;
751
263
  if (!(key in _routesCache))
752
264
  throw Error("You must call getBestRouteAndOutput first");
753
265
  return _routesCache[key];
754
266
  };
755
- export var getBestRouteAndOutput = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
756
- var _a, inputCoinAddress, outputCoinAddress, _b, inputCoinDecimals, outputCoinDecimals, route, _output;
757
- return __generator(this, function (_c) {
758
- switch (_c.label) {
759
- case 0:
760
- _a = _getCoinAddresses(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
761
- _b = _getCoinDecimals(inputCoinAddress, outputCoinAddress), inputCoinDecimals = _b[0], outputCoinDecimals = _b[1];
762
- return [4 /*yield*/, _getBestRoute(inputCoinAddress, outputCoinAddress, amount)];
763
- case 1:
764
- route = _c.sent();
765
- if (route.length === 0)
766
- return [2 /*return*/, { route: route, output: '0.0' }];
767
- return [4 /*yield*/, _getOutputForRoute(route, parseUnits(amount, inputCoinDecimals))];
768
- case 2:
769
- _output = _c.sent();
770
- _routesCache["".concat(inputCoinAddress, "-").concat(outputCoinAddress, "-").concat(amount)] = {
771
- route: route,
772
- output: curve.formatUnits(_output + BigInt(1), outputCoinDecimals),
773
- timestamp: Date.now(),
774
- };
775
- return [2 /*return*/, { route: route, output: curve.formatUnits(_output + BigInt(1), outputCoinDecimals) }];
776
- }
777
- });
778
- }); };
779
- export var getArgs = function (route) {
780
- return _getExchangeArgs(route);
781
- };
782
- export var swapExpected = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
783
- return __generator(this, function (_a) {
784
- switch (_a.label) {
785
- case 0: return [4 /*yield*/, getBestRouteAndOutput(inputCoin, outputCoin, amount)];
786
- case 1: return [2 /*return*/, (_a.sent())['output']];
787
- }
788
- });
789
- }); };
790
- export var swapRequired = function (inputCoin, outputCoin, outAmount) { return __awaiter(void 0, void 0, void 0, function () {
791
- var _a, inputCoinAddress, outputCoinAddress, _b, inputCoinDecimals, outputCoinDecimals, _outAmount, p1, p2, approximateRequiredAmount, route, contract, _c, _route, _swapParams, _pools, _basePools, _baseTokens, _secondBasePools, _secondBaseTokens, _required;
792
- return __generator(this, function (_d) {
793
- switch (_d.label) {
794
- case 0:
795
- _a = _getCoinAddresses(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
796
- _b = _getCoinDecimals(inputCoinAddress, outputCoinAddress), inputCoinDecimals = _b[0], outputCoinDecimals = _b[1];
797
- _outAmount = parseUnits(outAmount, outputCoinDecimals);
798
- return [4 /*yield*/, _getUsdRate(inputCoinAddress)];
799
- case 1:
800
- p1 = (_d.sent()) || 1;
801
- return [4 /*yield*/, _getUsdRate(outputCoinAddress)];
802
- case 2:
803
- p2 = (_d.sent()) || 1;
804
- approximateRequiredAmount = Number(outAmount) * p2 / p1;
805
- return [4 /*yield*/, _getBestRoute(inputCoinAddress, outputCoinAddress, approximateRequiredAmount)];
806
- case 3:
807
- route = _d.sent();
808
- contract = curve.contracts[curve.constants.ALIASES.router].contract;
809
- _c = _getExchangeArgs(route), _route = _c._route, _swapParams = _c._swapParams, _pools = _c._pools, _basePools = _c._basePools, _baseTokens = _c._baseTokens, _secondBasePools = _c._secondBasePools, _secondBaseTokens = _c._secondBaseTokens;
810
- _required = 0;
811
- if (!("get_dx(address[11],uint256[5][5],uint256,address[5],address[5],address[5],address[5],address[5])" in contract)) return [3 /*break*/, 5];
812
- return [4 /*yield*/, contract.get_dx(_route, _swapParams, _outAmount, _pools, _basePools, _baseTokens, _secondBasePools, _secondBaseTokens, curve.constantOptions)];
813
- case 4:
814
- _required = _d.sent();
815
- return [3 /*break*/, 9];
816
- case 5:
817
- if (!_pools) return [3 /*break*/, 7];
818
- return [4 /*yield*/, contract.get_dx(_route, _swapParams, _outAmount, _pools, _basePools, _baseTokens, curve.constantOptions)];
819
- case 6:
820
- _required = _d.sent();
821
- return [3 /*break*/, 9];
822
- case 7: return [4 /*yield*/, contract.get_dx(_route, _swapParams, _outAmount, curve.constantOptions)];
823
- case 8:
824
- _required = _d.sent();
825
- _d.label = 9;
826
- case 9: return [2 /*return*/, curve.formatUnits(_required, inputCoinDecimals)];
827
- }
828
- });
829
- }); };
830
- export var swapPriceImpact = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
831
- var _a, inputCoinAddress, outputCoinAddress, _b, inputCoinDecimals, outputCoinDecimals, _c, route, output, _amount, _output, smallAmountIntBN, amountIntBN, contract, _smallAmount, _d, _route, _swapParams, _pools, _smallOutput, e_2, priceImpactBN;
832
- return __generator(this, function (_e) {
833
- switch (_e.label) {
834
- case 0:
835
- _a = _getCoinAddresses(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
836
- _b = _getCoinDecimals(inputCoinAddress, outputCoinAddress), inputCoinDecimals = _b[0], outputCoinDecimals = _b[1];
837
- _c = _getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount), route = _c.route, output = _c.output;
838
- _amount = parseUnits(amount, inputCoinDecimals);
839
- _output = parseUnits(output, outputCoinDecimals);
840
- smallAmountIntBN = _get_small_x(_amount, _output, inputCoinDecimals, outputCoinDecimals);
841
- amountIntBN = toBN(_amount, 0);
842
- if (smallAmountIntBN.gte(amountIntBN))
843
- return [2 /*return*/, 0];
844
- contract = curve.contracts[curve.constants.ALIASES.router].contract;
845
- _smallAmount = fromBN(smallAmountIntBN.div(Math.pow(10, inputCoinDecimals)), inputCoinDecimals);
846
- _d = _getExchangeArgs(route), _route = _d._route, _swapParams = _d._swapParams, _pools = _d._pools;
847
- _e.label = 1;
848
- case 1:
849
- _e.trys.push([1, 6, , 11]);
850
- if (!_pools) return [3 /*break*/, 3];
851
- return [4 /*yield*/, contract.get_dy(_route, _swapParams, _smallAmount, _pools, curve.constantOptions)];
852
- case 2:
853
- _smallOutput = _e.sent();
854
- return [3 /*break*/, 5];
855
- case 3: return [4 /*yield*/, contract.get_dy(_route, _swapParams, _smallAmount, curve.constantOptions)];
856
- case 4:
857
- _smallOutput = _e.sent();
858
- _e.label = 5;
859
- case 5: return [3 /*break*/, 11];
860
- case 6:
861
- e_2 = _e.sent();
862
- _smallAmount = curve.parseUnits("1", inputCoinDecimals); // Dirty hack
863
- if (!_pools) return [3 /*break*/, 8];
864
- return [4 /*yield*/, contract.get_dy(_route, _swapParams, _smallAmount, _pools, curve.constantOptions)];
865
- case 7:
866
- _smallOutput = _e.sent();
867
- return [3 /*break*/, 10];
868
- case 8: return [4 /*yield*/, contract.get_dy(_route, _swapParams, _smallAmount, curve.constantOptions)];
869
- case 9:
870
- _smallOutput = _e.sent();
871
- _e.label = 10;
872
- case 10: return [3 /*break*/, 11];
873
- case 11:
874
- priceImpactBN = _get_price_impact(_amount, _output, _smallAmount, _smallOutput, inputCoinDecimals, outputCoinDecimals);
875
- return [2 /*return*/, Number(_cutZeros(priceImpactBN.toFixed(4)))];
876
- }
877
- });
878
- }); };
879
- export var swapIsApproved = function (inputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
880
- return __generator(this, function (_a) {
881
- switch (_a.label) {
882
- case 0: return [4 /*yield*/, hasAllowance([inputCoin], [amount], curve.signerAddress, curve.constants.ALIASES.router)];
883
- case 1: return [2 /*return*/, _a.sent()];
267
+ export const getBestRouteAndOutput = (inputCoin, outputCoin, amount) => __awaiter(void 0, void 0, void 0, function* () {
268
+ const [inputCoinAddress, outputCoinAddress] = _getCoinAddresses(inputCoin, outputCoin);
269
+ const [inputCoinDecimals, outputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
270
+ const route = yield _getBestRoute(inputCoinAddress, outputCoinAddress, amount); // 5 minutes cache
271
+ if (route.length === 0)
272
+ return { route, output: '0.0' };
273
+ const _output = yield _getOutputForRoute(route, parseUnits(amount, inputCoinDecimals)); // 15 seconds cache, so we call it to get fresh output estimation
274
+ _routesCache[`${inputCoinAddress}-${outputCoinAddress}-${amount}`] = {
275
+ route,
276
+ output: curve.formatUnits(_output + BigInt(1), outputCoinDecimals),
277
+ timestamp: Date.now(),
278
+ };
279
+ return { route, output: curve.formatUnits(_output + BigInt(1), outputCoinDecimals) };
280
+ });
281
+ export const getArgs = (route) => _getExchangeArgs(route);
282
+ export const swapExpected = (inputCoin, outputCoin, amount) => __awaiter(void 0, void 0, void 0, function* () { return (yield getBestRouteAndOutput(inputCoin, outputCoin, amount))['output']; });
283
+ export const swapRequired = (inputCoin, outputCoin, outAmount) => __awaiter(void 0, void 0, void 0, function* () {
284
+ const [inputCoinAddress, outputCoinAddress] = _getCoinAddresses(inputCoin, outputCoin);
285
+ const [inputCoinDecimals, outputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
286
+ const _outAmount = parseUnits(outAmount, outputCoinDecimals);
287
+ const p1 = (yield _getUsdRate(inputCoinAddress)) || 1;
288
+ const p2 = (yield _getUsdRate(outputCoinAddress)) || 1;
289
+ const approximateRequiredAmount = Number(outAmount) * p2 / p1;
290
+ const route = yield _getBestRoute(inputCoinAddress, outputCoinAddress, approximateRequiredAmount);
291
+ const contract = curve.contracts[curve.constants.ALIASES.router].contract;
292
+ const { _route, _swapParams, _pools, _basePools, _baseTokens, _secondBasePools, _secondBaseTokens } = _getExchangeArgs(route);
293
+ let _required;
294
+ if ("get_dx(address[11],uint256[5][5],uint256,address[5],address[5],address[5],address[5],address[5])" in contract) {
295
+ _required = yield contract.get_dx(_route, _swapParams, _outAmount, _pools, _basePools, _baseTokens, _secondBasePools, _secondBaseTokens, curve.constantOptions);
296
+ }
297
+ else if (_pools) {
298
+ _required = yield contract.get_dx(_route, _swapParams, _outAmount, _pools, _basePools, _baseTokens, curve.constantOptions);
299
+ }
300
+ else {
301
+ _required = yield contract.get_dx(_route, _swapParams, _outAmount, curve.constantOptions);
302
+ }
303
+ return curve.formatUnits(_required, inputCoinDecimals);
304
+ });
305
+ export const swapPriceImpact = (inputCoin, outputCoin, amount) => __awaiter(void 0, void 0, void 0, function* () {
306
+ const [inputCoinAddress, outputCoinAddress] = _getCoinAddresses(inputCoin, outputCoin);
307
+ const [inputCoinDecimals, outputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
308
+ const { route, output } = _getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount);
309
+ const _amount = parseUnits(amount, inputCoinDecimals);
310
+ const _output = parseUnits(output, outputCoinDecimals);
311
+ const smallAmountIntBN = _get_small_x(_amount, _output, inputCoinDecimals, outputCoinDecimals);
312
+ const amountIntBN = toBN(_amount, 0);
313
+ if (smallAmountIntBN.gte(amountIntBN))
314
+ return 0;
315
+ const contract = curve.contracts[curve.constants.ALIASES.router].contract;
316
+ let _smallAmount = fromBN(smallAmountIntBN.div(Math.pow(10, inputCoinDecimals)), inputCoinDecimals);
317
+ const { _route, _swapParams, _pools } = _getExchangeArgs(route);
318
+ let _smallOutput;
319
+ try {
320
+ if (_pools) {
321
+ _smallOutput = yield contract.get_dy(_route, _swapParams, _smallAmount, _pools, curve.constantOptions);
884
322
  }
885
- });
886
- }); };
887
- export var swapApproveEstimateGas = function (inputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
888
- return __generator(this, function (_a) {
889
- switch (_a.label) {
890
- case 0: return [4 /*yield*/, ensureAllowanceEstimateGas([inputCoin], [amount], curve.constants.ALIASES.router)];
891
- case 1: return [2 /*return*/, _a.sent()];
323
+ else {
324
+ _smallOutput = yield contract.get_dy(_route, _swapParams, _smallAmount, curve.constantOptions);
892
325
  }
893
- });
894
- }); };
895
- export var swapApprove = function (inputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
896
- return __generator(this, function (_a) {
897
- switch (_a.label) {
898
- case 0: return [4 /*yield*/, ensureAllowance([inputCoin], [amount], curve.constants.ALIASES.router)];
899
- case 1: return [2 /*return*/, _a.sent()];
326
+ }
327
+ catch (e) {
328
+ _smallAmount = curve.parseUnits("1", inputCoinDecimals); // Dirty hack
329
+ if (_pools) {
330
+ _smallOutput = yield contract.get_dy(_route, _swapParams, _smallAmount, _pools, curve.constantOptions);
900
331
  }
901
- });
902
- }); };
903
- export var swapEstimateGas = function (inputCoin, outputCoin, amount) { return __awaiter(void 0, void 0, void 0, function () {
904
- var _a, inputCoinAddress, outputCoinAddress, inputCoinDecimals, route, _amount, gas;
905
- return __generator(this, function (_b) {
906
- switch (_b.label) {
907
- case 0:
908
- _a = _getCoinAddresses(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
909
- inputCoinDecimals = _getCoinDecimals(inputCoinAddress, outputCoinAddress)[0];
910
- route = _getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount).route;
911
- if (route.length === 0)
912
- return [2 /*return*/, 0];
913
- _amount = parseUnits(amount, inputCoinDecimals);
914
- return [4 /*yield*/, _estimateGasForDifferentRoutes([route], inputCoinAddress, outputCoinAddress, _amount)];
915
- case 1:
916
- gas = (_b.sent())[0];
917
- return [2 /*return*/, gas];
332
+ else {
333
+ _smallOutput = yield contract.get_dy(_route, _swapParams, _smallAmount, curve.constantOptions);
918
334
  }
919
- });
920
- }); };
921
- export var swap = function (inputCoin, outputCoin, amount, slippage) {
922
- if (slippage === void 0) { slippage = 0.5; }
923
- return __awaiter(void 0, void 0, void 0, function () {
924
- var _a, inputCoinAddress, outputCoinAddress, _b, inputCoinDecimals, outputCoinDecimals, _c, route, output, _d, _route, _swapParams, _pools, _amount, minRecvAmountBN, _minRecvAmount, contract, value, gasLimit, _e, gasLimit, _f;
925
- return __generator(this, function (_h) {
926
- switch (_h.label) {
927
- case 0:
928
- _a = _getCoinAddresses(inputCoin, outputCoin), inputCoinAddress = _a[0], outputCoinAddress = _a[1];
929
- _b = _getCoinDecimals(inputCoinAddress, outputCoinAddress), inputCoinDecimals = _b[0], outputCoinDecimals = _b[1];
930
- return [4 /*yield*/, swapApprove(inputCoin, amount)];
931
- case 1:
932
- _h.sent();
933
- _c = _getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount), route = _c.route, output = _c.output;
934
- if (route.length === 0) {
935
- throw new Error("This pair can't be exchanged");
936
- }
937
- _d = _getExchangeArgs(route), _route = _d._route, _swapParams = _d._swapParams, _pools = _d._pools;
938
- _amount = parseUnits(amount, inputCoinDecimals);
939
- minRecvAmountBN = BN(output).times(100 - slippage).div(100);
940
- _minRecvAmount = fromBN(minRecvAmountBN, outputCoinDecimals);
941
- contract = curve.contracts[curve.constants.ALIASES.router].contract;
942
- value = isEth(inputCoinAddress) ? _amount : curve.parseUnits("0");
943
- return [4 /*yield*/, curve.updateFeeData()];
944
- case 2:
945
- _h.sent();
946
- if (!_pools) return [3 /*break*/, 5];
947
- _e = DIGas;
948
- return [4 /*yield*/, contract.exchange.estimateGas(_route, _swapParams, _amount, _minRecvAmount, _pools, __assign(__assign({}, curve.constantOptions), { value: value }))];
949
- case 3:
950
- gasLimit = (_e.apply(void 0, [_h.sent()])) * (curve.chainId === 1 ? curve.parseUnits("130", 0) : curve.parseUnits("160", 0)) / curve.parseUnits("100", 0);
951
- return [4 /*yield*/, contract.exchange(_route, _swapParams, _amount, _minRecvAmount, _pools, __assign(__assign({}, curve.options), { value: value, gasLimit: gasLimit }))];
952
- case 4: return [2 /*return*/, _h.sent()];
953
- case 5:
954
- _f = DIGas;
955
- return [4 /*yield*/, contract.exchange.estimateGas(_route, _swapParams, _amount, _minRecvAmount, __assign(__assign({}, curve.constantOptions), { value: value }))];
956
- case 6:
957
- gasLimit = (_f.apply(void 0, [_h.sent()])) * curve.parseUnits("160", 0) / curve.parseUnits("100", 0);
958
- return [4 /*yield*/, contract.exchange(_route, _swapParams, _amount, _minRecvAmount, __assign(__assign({}, curve.options), { value: value, gasLimit: gasLimit }))];
959
- case 7: return [2 /*return*/, _h.sent()];
960
- }
961
- });
962
- });
963
- };
964
- export var getSwappedAmount = function (tx, outputCoin) { return __awaiter(void 0, void 0, void 0, function () {
965
- var outputCoinAddress, outputCoinDecimals, txInfo, res, i, abiCoder;
966
- return __generator(this, function (_a) {
967
- switch (_a.label) {
968
- case 0:
969
- outputCoinAddress = _getCoinAddresses(outputCoin)[0];
970
- outputCoinDecimals = _getCoinDecimals(outputCoinAddress)[0];
971
- return [4 /*yield*/, tx.wait()];
972
- case 1:
973
- txInfo = _a.sent();
974
- if (txInfo === null)
975
- return [2 /*return*/, '0.0'];
976
- for (i = 1; i <= txInfo.logs.length; i++) {
977
- try {
978
- abiCoder = ethers.AbiCoder.defaultAbiCoder();
979
- res = abiCoder.decode(["address[".concat(ROUTE_LENGTH, "]"), "uint256[".concat(MAX_STEPS, "][").concat(MAX_STEPS, "]"), "address[".concat(MAX_STEPS, "]"), 'uint256', 'uint256'], ethers.dataSlice(txInfo.logs[txInfo.logs.length - i].data, 0));
980
- break;
981
- }
982
- catch (err) { }
983
- }
984
- if (res === undefined)
985
- return [2 /*return*/, '0.0'];
986
- return [2 /*return*/, curve.formatUnits(res[res.length - 1], outputCoinDecimals)];
335
+ }
336
+ const priceImpactBN = _get_price_impact(_amount, _output, _smallAmount, _smallOutput, inputCoinDecimals, outputCoinDecimals);
337
+ return Number(_cutZeros(priceImpactBN.toFixed(4)));
338
+ });
339
+ export const swapIsApproved = (inputCoin, amount) => __awaiter(void 0, void 0, void 0, function* () {
340
+ return yield hasAllowance([inputCoin], [amount], curve.signerAddress, curve.constants.ALIASES.router);
341
+ });
342
+ export const swapApproveEstimateGas = (inputCoin, amount) => __awaiter(void 0, void 0, void 0, function* () {
343
+ return yield ensureAllowanceEstimateGas([inputCoin], [amount], curve.constants.ALIASES.router);
344
+ });
345
+ export const swapApprove = (inputCoin, amount) => __awaiter(void 0, void 0, void 0, function* () {
346
+ return yield ensureAllowance([inputCoin], [amount], curve.constants.ALIASES.router);
347
+ });
348
+ export const swapEstimateGas = (inputCoin, outputCoin, amount) => __awaiter(void 0, void 0, void 0, function* () {
349
+ const [inputCoinAddress, outputCoinAddress] = _getCoinAddresses(inputCoin, outputCoin);
350
+ const [inputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
351
+ const { route } = _getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount);
352
+ if (route.length === 0)
353
+ return 0;
354
+ const _amount = parseUnits(amount, inputCoinDecimals);
355
+ const [gas] = yield _estimateGasForDifferentRoutes([route], inputCoinAddress, outputCoinAddress, _amount);
356
+ return gas;
357
+ });
358
+ export const swap = (inputCoin, outputCoin, amount, slippage = 0.5) => __awaiter(void 0, void 0, void 0, function* () {
359
+ const [inputCoinAddress, outputCoinAddress] = _getCoinAddresses(inputCoin, outputCoin);
360
+ const [inputCoinDecimals, outputCoinDecimals] = _getCoinDecimals(inputCoinAddress, outputCoinAddress);
361
+ yield swapApprove(inputCoin, amount);
362
+ const { route, output } = _getBestRouteAndOutput(inputCoinAddress, outputCoinAddress, amount);
363
+ if (route.length === 0) {
364
+ throw new Error("This pair can't be exchanged");
365
+ }
366
+ const { _route, _swapParams, _pools } = _getExchangeArgs(route);
367
+ const _amount = parseUnits(amount, inputCoinDecimals);
368
+ const minRecvAmountBN = BN(output).times(100 - slippage).div(100);
369
+ const _minRecvAmount = fromBN(minRecvAmountBN, outputCoinDecimals);
370
+ const contract = curve.contracts[curve.constants.ALIASES.router].contract;
371
+ const value = isEth(inputCoinAddress) ? _amount : curve.parseUnits("0");
372
+ yield curve.updateFeeData();
373
+ if (_pools) {
374
+ const gasLimit = (DIGas(yield contract.exchange.estimateGas(_route, _swapParams, _amount, _minRecvAmount, _pools, Object.assign(Object.assign({}, curve.constantOptions), { value })))) * (curve.chainId === 1 ? curve.parseUnits("130", 0) : curve.parseUnits("160", 0)) / curve.parseUnits("100", 0);
375
+ return yield contract.exchange(_route, _swapParams, _amount, _minRecvAmount, _pools, Object.assign(Object.assign({}, curve.options), { value, gasLimit }));
376
+ }
377
+ else {
378
+ const gasLimit = (DIGas(yield contract.exchange.estimateGas(_route, _swapParams, _amount, _minRecvAmount, Object.assign(Object.assign({}, curve.constantOptions), { value })))) * curve.parseUnits("160", 0) / curve.parseUnits("100", 0);
379
+ return yield contract.exchange(_route, _swapParams, _amount, _minRecvAmount, Object.assign(Object.assign({}, curve.options), { value, gasLimit }));
380
+ }
381
+ });
382
+ export const getSwappedAmount = (tx, outputCoin) => __awaiter(void 0, void 0, void 0, function* () {
383
+ const [outputCoinAddress] = _getCoinAddresses(outputCoin);
384
+ const [outputCoinDecimals] = _getCoinDecimals(outputCoinAddress);
385
+ const txInfo = yield tx.wait();
386
+ if (txInfo === null)
387
+ return '0.0';
388
+ let res;
389
+ for (let i = 1; i <= txInfo.logs.length; i++) {
390
+ try {
391
+ const abiCoder = ethers.AbiCoder.defaultAbiCoder();
392
+ res = abiCoder.decode([`address[${ROUTE_LENGTH}]`, `uint256[${MAX_STEPS}][${MAX_STEPS}]`, `address[${MAX_STEPS}]`, 'uint256', 'uint256'], ethers.dataSlice(txInfo.logs[txInfo.logs.length - i].data, 0));
393
+ break;
987
394
  }
988
- });
989
- }); };
395
+ catch (err) { }
396
+ }
397
+ if (res === undefined)
398
+ return '0.0';
399
+ return curve.formatUnits(res[res.length - 1], outputCoinDecimals);
400
+ });