@curvefi/api 2.62.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 +31 -31
  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 +3 -3
  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 +36 -46
  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 -906
  83. package/package.json +1 -1
@@ -0,0 +1,9 @@
1
+ import type { IDict, IRoutePoolData, IRouteStep } from "./interfaces";
2
+ export type IRouterWorkerInput = {
3
+ inputCoinAddress: string;
4
+ outputCoinAddress: string;
5
+ routerGraph: IDict<IDict<IRouteStep[]>>;
6
+ poolData: IDict<IRoutePoolData>;
7
+ };
8
+ export declare function routeFinderWorker(): (({ inputCoinAddress, outputCoinAddress, routerGraph, poolData }: IRouterWorkerInput) => IRouteStep[][]) | undefined;
9
+ export declare const routeFinderWorkerCode: string;
@@ -0,0 +1,112 @@
1
+ export function routeFinderWorker() {
2
+ const MAX_ROUTES_FOR_ONE_COIN = 5;
3
+ const MAX_DEPTH = 4;
4
+ const _removeDuplications = (routesA, routesB) => {
5
+ const routeToStr = (r) => r.route.map((s) => s.poolId).toString();
6
+ const routeIdsA = new Set(routesA.map(routeToStr));
7
+ return routesA.concat(routesB.filter((r) => !routeIdsA.has(routeToStr(r))));
8
+ };
9
+ const _sortByTvl = (a, b) => b.minTvl - a.minTvl || b.totalTvl - a.totalTvl || a.route.length - b.route.length;
10
+ const _sortByLength = (a, b) => a.route.length - b.route.length || b.minTvl - a.minTvl || b.totalTvl - a.totalTvl;
11
+ // 4 --> 6, 5 --> 7 not allowed
12
+ // 4 --> 7, 5 --> 6 allowed
13
+ const _handleSwapType = (swapType) => {
14
+ if (swapType === 6)
15
+ return "4";
16
+ if (swapType === 7)
17
+ return "5";
18
+ return swapType.toString();
19
+ };
20
+ /** Add step to route */
21
+ const _addStep = (route, step) => ({
22
+ route: route.route.concat(step),
23
+ minTvl: Math.min(step.tvl, route.minTvl),
24
+ totalTvl: route.totalTvl + step.tvl,
25
+ });
26
+ /** Check if item fits in a sorted-sized array */
27
+ function _fits(array, item, compareFn, maxSize) {
28
+ if (array.length < maxSize)
29
+ return true;
30
+ const last = array[array.length - 1];
31
+ return compareFn(item, last) < 0;
32
+ }
33
+ /** Add item to sorted-sized array */
34
+ function _sortedPush(array, item, compareFn, maxSize) {
35
+ if (!_fits(array, item, compareFn, maxSize))
36
+ return;
37
+ if (array.length === maxSize) {
38
+ array.pop();
39
+ }
40
+ const position = array.findIndex((existingItem) => compareFn(item, existingItem) < 0);
41
+ if (position === -1) {
42
+ array.push(item);
43
+ }
44
+ else {
45
+ array.splice(position, 0, item);
46
+ }
47
+ }
48
+ const _isVisitedCoin = (coinAddress, route) => route.route.find((r) => r.inputCoinAddress === coinAddress) !== undefined;
49
+ const _findPool = (route, poolId) => route.route.find((r) => r.poolId === poolId);
50
+ const findRoutes = ({ inputCoinAddress, outputCoinAddress, routerGraph, poolData }) => {
51
+ inputCoinAddress = inputCoinAddress.toLowerCase();
52
+ outputCoinAddress = outputCoinAddress.toLowerCase();
53
+ const routes = [{ route: [], minTvl: Infinity, totalTvl: 0 }];
54
+ const targetRoutesByTvl = [];
55
+ const targetRoutesByLength = [];
56
+ while (routes.length) {
57
+ const route = routes.pop();
58
+ const inCoin = route.route.length > 0 ? route.route[route.route.length - 1].outputCoinAddress : inputCoinAddress;
59
+ Object.entries(routerGraph[inCoin]).forEach((leaf) => {
60
+ const outCoin = leaf[0], steps = leaf[1];
61
+ if (_isVisitedCoin(outCoin, route))
62
+ return;
63
+ steps.forEach((step) => {
64
+ const pool = poolData[step.poolId];
65
+ const currentPoolInRoute = _findPool(route, step.poolId);
66
+ if (currentPoolInRoute) {
67
+ if (!(pool === null || pool === void 0 ? void 0 : pool.is_lending))
68
+ return;
69
+ // 4 --> 6, 5 --> 7 not allowed
70
+ // 4 --> 7, 5 --> 6 allowed
71
+ if (_handleSwapType(step.swapParams[2]) === _handleSwapType(currentPoolInRoute.swapParams[2])) {
72
+ return;
73
+ }
74
+ }
75
+ if (step.outputCoinAddress === outputCoinAddress) {
76
+ const newRoute = _addStep(route, step);
77
+ _sortedPush(targetRoutesByTvl, newRoute, _sortByTvl, MAX_ROUTES_FOR_ONE_COIN);
78
+ _sortedPush(targetRoutesByLength, newRoute, _sortByLength, MAX_ROUTES_FOR_ONE_COIN);
79
+ return;
80
+ }
81
+ if ((pool === null || pool === void 0 ? void 0 : pool.wrapped_coin_addresses.includes(outputCoinAddress)) || (pool === null || pool === void 0 ? void 0 : pool.underlying_coin_addresses.includes(outputCoinAddress))) {
82
+ // Exclude such cases as: cvxeth -> tricrypto2 -> tusd -> susd (cvxeth -> tricrypto2 -> tusd instead)
83
+ if (!(pool === null || pool === void 0 ? void 0 : pool.is_lending))
84
+ return;
85
+ // Exclude such cases as: aave -> aave -> 3pool (aave -> aave instead)
86
+ if (outCoin !== (pool === null || pool === void 0 ? void 0 : pool.token_address))
87
+ return;
88
+ }
89
+ if (route.route.length < MAX_DEPTH) {
90
+ const newRoute = _addStep(route, step);
91
+ if (_fits(targetRoutesByTvl, newRoute, _sortByTvl, MAX_ROUTES_FOR_ONE_COIN) ||
92
+ _fits(targetRoutesByLength, newRoute, _sortByLength, MAX_ROUTES_FOR_ONE_COIN)) {
93
+ routes.push(newRoute); // try another step
94
+ }
95
+ }
96
+ });
97
+ });
98
+ }
99
+ return _removeDuplications(targetRoutesByTvl, targetRoutesByLength).map((r) => r.route);
100
+ };
101
+ if (typeof addEventListener === 'undefined') {
102
+ return findRoutes; // for nodejs
103
+ }
104
+ addEventListener('message', (e) => {
105
+ const { type } = e.data;
106
+ if (type === 'findRoutes') {
107
+ postMessage({ type, result: findRoutes(e.data) });
108
+ }
109
+ });
110
+ }
111
+ // this is a workaround to avoid importing web-worker in the main bundle (nextjs will try to inject invalid hot-reloading code)
112
+ export const routeFinderWorkerCode = `${routeFinderWorker.toString()}; ${routeFinderWorker.name}();`;
@@ -0,0 +1,11 @@
1
+ import type { IChainId, IDict, IPoolData, IRouteStep } from "./interfaces";
2
+ import type { curve } from "./curve";
3
+ export type IRouteGraphInput = {
4
+ constants: typeof curve['constants'];
5
+ chainId: IChainId;
6
+ allPools: [string, IPoolData][];
7
+ amplificationCoefficientDict: IDict<number>;
8
+ poolTvlDict: IDict<number>;
9
+ };
10
+ export declare function routeGraphWorker(): (({ constants, chainId, allPools, amplificationCoefficientDict, poolTvlDict }: IRouteGraphInput) => IDict<IDict<IRouteStep[]>>) | undefined;
11
+ export declare const routeGraphWorkerCode: string;
@@ -0,0 +1,334 @@
1
+ export function routeGraphWorker() {
2
+ const GRAPH_MAX_EDGES = 3;
3
+ const SNX = {
4
+ 10: {
5
+ swap: "0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4".toLowerCase(),
6
+ coins: [
7
+ "0x8c6f28f2f1a3c87f0f938b96d27520d9751ec8d9",
8
+ "0xFBc4198702E81aE77c06D58f81b629BDf36f0a71",
9
+ "0xe405de8f52ba7559f9df3c368500b6e6ae6cee49",
10
+ "0x298b9b95708152ff6968aafd889c6586e9169f1d", // sBTC
11
+ ].map((a) => a.toLowerCase()),
12
+ },
13
+ };
14
+ const createRouteGraph = ({ constants, chainId, allPools, amplificationCoefficientDict, poolTvlDict }) => {
15
+ var _a, _b, _c;
16
+ const routerGraph = {};
17
+ // ETH <-> WETH (exclude Celo)
18
+ if (chainId !== 42220) {
19
+ routerGraph[constants.NATIVE_TOKEN.address] = {};
20
+ routerGraph[constants.NATIVE_TOKEN.address][constants.NATIVE_TOKEN.wrappedAddress] = [{
21
+ poolId: "WETH wrapper",
22
+ swapAddress: constants.NATIVE_TOKEN.wrappedAddress,
23
+ inputCoinAddress: constants.NATIVE_TOKEN.address,
24
+ outputCoinAddress: constants.NATIVE_TOKEN.wrappedAddress,
25
+ swapParams: [0, 0, 8, 0, 0],
26
+ poolAddress: constants.ZERO_ADDRESS,
27
+ basePool: constants.ZERO_ADDRESS,
28
+ baseToken: constants.ZERO_ADDRESS,
29
+ secondBasePool: constants.ZERO_ADDRESS,
30
+ secondBaseToken: constants.ZERO_ADDRESS,
31
+ tvl: Infinity,
32
+ }];
33
+ routerGraph[constants.NATIVE_TOKEN.wrappedAddress] = {};
34
+ routerGraph[constants.NATIVE_TOKEN.wrappedAddress][constants.NATIVE_TOKEN.address] = [{
35
+ poolId: "WETH wrapper",
36
+ swapAddress: constants.NATIVE_TOKEN.wrappedAddress,
37
+ inputCoinAddress: constants.NATIVE_TOKEN.wrappedAddress,
38
+ outputCoinAddress: constants.NATIVE_TOKEN.address,
39
+ swapParams: [0, 0, 8, 0, 0],
40
+ poolAddress: constants.ZERO_ADDRESS,
41
+ basePool: constants.ZERO_ADDRESS,
42
+ baseToken: constants.ZERO_ADDRESS,
43
+ secondBasePool: constants.ZERO_ADDRESS,
44
+ secondBaseToken: constants.ZERO_ADDRESS,
45
+ tvl: Infinity,
46
+ }];
47
+ }
48
+ // ETH -> stETH, ETH -> frxETH, ETH -> wBETH (Ethereum only)
49
+ if (chainId == 1) {
50
+ for (const outCoin of ["stETH", "frxETH", "wBETH"]) {
51
+ routerGraph[constants.NATIVE_TOKEN.address][constants.COINS[outCoin.toLowerCase()]] = [{
52
+ poolId: outCoin + " minter",
53
+ swapAddress: outCoin === "frxETH" ? "0xbAFA44EFE7901E04E39Dad13167D089C559c1138".toLowerCase() : constants.COINS[outCoin.toLowerCase()],
54
+ inputCoinAddress: constants.NATIVE_TOKEN.address,
55
+ outputCoinAddress: constants.COINS[outCoin.toLowerCase()],
56
+ swapParams: [0, 0, 8, 0, 0],
57
+ poolAddress: constants.ZERO_ADDRESS,
58
+ basePool: constants.ZERO_ADDRESS,
59
+ baseToken: constants.ZERO_ADDRESS,
60
+ secondBasePool: constants.ZERO_ADDRESS,
61
+ secondBaseToken: constants.ZERO_ADDRESS,
62
+ tvl: Infinity,
63
+ }];
64
+ }
65
+ }
66
+ // stETH <-> wstETH (Ethereum only)
67
+ if (chainId === 1) {
68
+ routerGraph[constants.COINS.steth] = {};
69
+ routerGraph[constants.COINS.steth][constants.COINS.wsteth] = [{
70
+ poolId: "wstETH wrapper",
71
+ swapAddress: constants.COINS.wsteth,
72
+ inputCoinAddress: constants.COINS.steth,
73
+ outputCoinAddress: constants.COINS.wsteth,
74
+ swapParams: [0, 0, 8, 0, 0],
75
+ poolAddress: constants.ZERO_ADDRESS,
76
+ basePool: constants.ZERO_ADDRESS,
77
+ baseToken: constants.ZERO_ADDRESS,
78
+ secondBasePool: constants.ZERO_ADDRESS,
79
+ secondBaseToken: constants.ZERO_ADDRESS,
80
+ tvl: Infinity,
81
+ }];
82
+ routerGraph[constants.COINS.wsteth] = {};
83
+ routerGraph[constants.COINS.wsteth][constants.COINS.steth] = [{
84
+ poolId: "wstETH wrapper",
85
+ swapAddress: constants.COINS.wsteth,
86
+ inputCoinAddress: constants.COINS.wsteth,
87
+ outputCoinAddress: constants.COINS.steth,
88
+ swapParams: [0, 0, 8, 0, 0],
89
+ poolAddress: constants.ZERO_ADDRESS,
90
+ basePool: constants.ZERO_ADDRESS,
91
+ baseToken: constants.ZERO_ADDRESS,
92
+ secondBasePool: constants.ZERO_ADDRESS,
93
+ secondBaseToken: constants.ZERO_ADDRESS,
94
+ tvl: Infinity,
95
+ }];
96
+ }
97
+ // frxETH <-> sfrxETH (Ethereum only)
98
+ if (chainId === 1) {
99
+ routerGraph[constants.COINS.frxeth] = {};
100
+ routerGraph[constants.COINS.frxeth][constants.COINS.sfrxeth] = [{
101
+ poolId: "sfrxETH wrapper",
102
+ swapAddress: constants.COINS.sfrxeth,
103
+ inputCoinAddress: constants.COINS.frxeth,
104
+ outputCoinAddress: constants.COINS.sfrxeth,
105
+ swapParams: [0, 0, 8, 0, 0],
106
+ poolAddress: constants.ZERO_ADDRESS,
107
+ basePool: constants.ZERO_ADDRESS,
108
+ baseToken: constants.ZERO_ADDRESS,
109
+ secondBasePool: constants.ZERO_ADDRESS,
110
+ secondBaseToken: constants.ZERO_ADDRESS,
111
+ tvl: Infinity,
112
+ }];
113
+ routerGraph[constants.COINS.sfrxeth] = {};
114
+ routerGraph[constants.COINS.sfrxeth][constants.COINS.frxeth] = [{
115
+ poolId: "sfrxETH wrapper",
116
+ swapAddress: constants.COINS.sfrxeth,
117
+ inputCoinAddress: constants.COINS.sfrxeth,
118
+ outputCoinAddress: constants.COINS.frxeth,
119
+ swapParams: [0, 0, 8, 0, 0],
120
+ poolAddress: constants.ZERO_ADDRESS,
121
+ basePool: constants.ZERO_ADDRESS,
122
+ baseToken: constants.ZERO_ADDRESS,
123
+ secondBasePool: constants.ZERO_ADDRESS,
124
+ secondBaseToken: constants.ZERO_ADDRESS,
125
+ tvl: Infinity,
126
+ }];
127
+ }
128
+ // SNX swaps
129
+ if (chainId in SNX) {
130
+ // @ts-ignore
131
+ for (const inCoin of SNX[chainId].coins) {
132
+ // @ts-ignore
133
+ for (const outCoin of SNX[chainId].coins) {
134
+ if (inCoin === outCoin)
135
+ continue;
136
+ if (!routerGraph[inCoin])
137
+ routerGraph[inCoin] = {};
138
+ routerGraph[inCoin][outCoin] = [{
139
+ poolId: "SNX exchanger",
140
+ // @ts-ignore
141
+ swapAddress: SNX[chainId].swap,
142
+ inputCoinAddress: inCoin,
143
+ outputCoinAddress: outCoin,
144
+ swapParams: [0, 0, 9, 0, 0],
145
+ poolAddress: constants.ZERO_ADDRESS,
146
+ basePool: constants.ZERO_ADDRESS,
147
+ baseToken: constants.ZERO_ADDRESS,
148
+ secondBasePool: constants.ZERO_ADDRESS,
149
+ secondBaseToken: constants.ZERO_ADDRESS,
150
+ tvl: Infinity,
151
+ }];
152
+ }
153
+ }
154
+ }
155
+ const start = Date.now();
156
+ for (const poolItem of allPools) {
157
+ const poolId = poolItem[0], poolData = poolItem[1];
158
+ const wrappedCoinAddresses = poolData.wrapped_coin_addresses.map((a) => a.toLowerCase());
159
+ const underlyingCoinAddresses = poolData.underlying_coin_addresses.map((a) => a.toLowerCase());
160
+ const poolAddress = poolData.swap_address.toLowerCase();
161
+ const tokenAddress = poolData.token_address.toLowerCase();
162
+ const isAaveLikeLending = poolData.is_lending && wrappedCoinAddresses.length === 3 && !poolData.deposit_address;
163
+ // pool_type: 1 - stable, 2 - twocrypto, 3 - tricrypto, 4 - llamma
164
+ // 10 - stable-ng, 20 - twocrypto-ng, 30 - tricrypto-ng
165
+ let poolType = poolData.is_llamma ? 4 : poolData.is_crypto ? Math.min(poolData.wrapped_coins.length, 3) : 1;
166
+ if (poolData.is_ng)
167
+ poolType *= 10;
168
+ const tvlMultiplier = poolData.is_crypto ? 1 : ((_a = amplificationCoefficientDict[poolData.swap_address]) !== null && _a !== void 0 ? _a : 1);
169
+ const basePool = poolData.is_meta ? Object.assign(Object.assign({}, constants.POOLS_DATA), constants.FACTORY_POOLS_DATA)[poolData.base_pool] : null;
170
+ const basePoolAddress = basePool ? basePool.swap_address.toLowerCase() : constants.ZERO_ADDRESS;
171
+ let baseTokenAddress = basePool ? basePool.token_address.toLowerCase() : constants.ZERO_ADDRESS;
172
+ const secondBasePool = basePool && basePool.base_pool ? Object.assign(Object.assign(Object.assign({}, constants.POOLS_DATA), constants.FACTORY_POOLS_DATA), constants.CRVUSD_FACTORY_POOLS_DATA)[basePool.base_pool] : null;
173
+ const secondBasePoolAddress = secondBasePool ? secondBasePool.swap_address.toLowerCase() : constants.ZERO_ADDRESS;
174
+ // for double meta underlying (crv/tricrypto, wmatic/tricrypto)
175
+ if (basePool && secondBasePoolAddress !== constants.ZERO_ADDRESS)
176
+ baseTokenAddress = (_b = basePool.deposit_address) === null || _b === void 0 ? void 0 : _b.toLowerCase();
177
+ const secondBaseTokenAddress = secondBasePool ? secondBasePool.token_address.toLowerCase() : constants.ZERO_ADDRESS;
178
+ const metaCoinAddresses = basePool ? basePool.underlying_coin_addresses.map((a) => a.toLowerCase()) : [];
179
+ let swapAddress = poolData.is_fake ? (_c = poolData.deposit_address) === null || _c === void 0 ? void 0 : _c.toLowerCase() : poolAddress;
180
+ const tvl = poolTvlDict[poolId] * tvlMultiplier;
181
+ // Skip empty pools
182
+ if (chainId === 1 && tvl < 1000)
183
+ continue;
184
+ if (chainId !== 1 && tvl < 100)
185
+ continue;
186
+ const excludedUnderlyingSwaps = (poolId === 'ib' && chainId === 1) ||
187
+ (poolId === 'geist' && chainId === 250) ||
188
+ (poolId === 'saave' && chainId === 1);
189
+ // Wrapped coin <-> LP "swaps" (actually add_liquidity/remove_liquidity_one_coin)
190
+ if (!poolData.is_fake && !poolData.is_llamma && wrappedCoinAddresses.length < 6) {
191
+ const coins = [tokenAddress].concat(wrappedCoinAddresses);
192
+ for (let k = 0; k < coins.length; k++) {
193
+ for (let l = 0; l < coins.length; l++) {
194
+ if (k > 0 && l > 0)
195
+ continue;
196
+ if (k == 0 && l == 0)
197
+ continue;
198
+ const i = Math.max(k - 1, 0);
199
+ const j = Math.max(l - 1, 0);
200
+ const swapType = k == 0 ? 6 : 4;
201
+ if (!routerGraph[coins[k]])
202
+ routerGraph[coins[k]] = {};
203
+ if (!routerGraph[coins[k]][coins[l]])
204
+ routerGraph[coins[k]][coins[l]] = [];
205
+ routerGraph[coins[k]][coins[l]].push({
206
+ poolId,
207
+ swapAddress,
208
+ inputCoinAddress: coins[k],
209
+ outputCoinAddress: coins[l],
210
+ swapParams: [i, j, swapType, poolType, wrappedCoinAddresses.length],
211
+ poolAddress: constants.ZERO_ADDRESS,
212
+ basePool: constants.ZERO_ADDRESS,
213
+ baseToken: constants.ZERO_ADDRESS,
214
+ secondBasePool: constants.ZERO_ADDRESS,
215
+ secondBaseToken: constants.ZERO_ADDRESS,
216
+ tvl,
217
+ });
218
+ }
219
+ }
220
+ }
221
+ // Underlying coin <-> LP "swaps" (actually add_liquidity/remove_liquidity_one_coin)
222
+ if ((poolData.is_fake || isAaveLikeLending) && underlyingCoinAddresses.length < 6 && !excludedUnderlyingSwaps) {
223
+ const coins = [tokenAddress].concat(underlyingCoinAddresses);
224
+ for (let k = 0; k < coins.length; k++) {
225
+ for (let l = 0; l < coins.length; l++) {
226
+ if (k > 0 && l > 0)
227
+ continue;
228
+ if (k == 0 && l == 0)
229
+ continue;
230
+ const i = Math.max(k - 1, 0);
231
+ const j = Math.max(l - 1, 0);
232
+ let swapType = isAaveLikeLending ? 7 : 6;
233
+ if (k > 0)
234
+ swapType = isAaveLikeLending ? 5 : 4;
235
+ if (!routerGraph[coins[k]])
236
+ routerGraph[coins[k]] = {};
237
+ if (!routerGraph[coins[k]][coins[l]])
238
+ routerGraph[coins[k]][coins[l]] = [];
239
+ routerGraph[coins[k]][coins[l]].push({
240
+ poolId,
241
+ swapAddress,
242
+ inputCoinAddress: coins[k],
243
+ outputCoinAddress: coins[l],
244
+ swapParams: [i, j, swapType, poolType, underlyingCoinAddresses.length],
245
+ poolAddress: constants.ZERO_ADDRESS,
246
+ basePool: constants.ZERO_ADDRESS,
247
+ baseToken: constants.ZERO_ADDRESS,
248
+ secondBasePool: constants.ZERO_ADDRESS,
249
+ secondBaseToken: constants.ZERO_ADDRESS,
250
+ tvl,
251
+ });
252
+ }
253
+ }
254
+ }
255
+ // Wrapped swaps
256
+ if (!poolData.is_fake) {
257
+ for (let i = 0; i < wrappedCoinAddresses.length; i++) {
258
+ for (let j = 0; j < wrappedCoinAddresses.length; j++) {
259
+ if (i == j)
260
+ continue;
261
+ if (!routerGraph[wrappedCoinAddresses[i]])
262
+ routerGraph[wrappedCoinAddresses[i]] = {};
263
+ if (!routerGraph[wrappedCoinAddresses[i]][wrappedCoinAddresses[j]])
264
+ routerGraph[wrappedCoinAddresses[i]][wrappedCoinAddresses[j]] = [];
265
+ routerGraph[wrappedCoinAddresses[i]][wrappedCoinAddresses[j]] = routerGraph[wrappedCoinAddresses[i]][wrappedCoinAddresses[j]].concat({
266
+ poolId,
267
+ swapAddress,
268
+ inputCoinAddress: wrappedCoinAddresses[i],
269
+ outputCoinAddress: wrappedCoinAddresses[j],
270
+ swapParams: [i, j, 1, poolType, wrappedCoinAddresses.length],
271
+ poolAddress,
272
+ basePool: basePoolAddress,
273
+ baseToken: baseTokenAddress,
274
+ secondBasePool: secondBasePoolAddress,
275
+ secondBaseToken: secondBaseTokenAddress,
276
+ tvl,
277
+ }).sort((a, b) => b.tvl - a.tvl).slice(0, GRAPH_MAX_EDGES);
278
+ }
279
+ }
280
+ }
281
+ // Only for underlying swaps
282
+ swapAddress = (poolData.is_crypto && poolData.is_meta) || ((basePool === null || basePool === void 0 ? void 0 : basePool.is_lending) && poolData.is_factory) ?
283
+ poolData.deposit_address : poolData.swap_address;
284
+ // Underlying swaps
285
+ if (!poolData.is_plain && !excludedUnderlyingSwaps) {
286
+ for (let i = 0; i < underlyingCoinAddresses.length; i++) {
287
+ for (let j = 0; j < underlyingCoinAddresses.length; j++) {
288
+ if (i === j)
289
+ continue;
290
+ // Don't swap metacoins since they can be swapped directly in base pool
291
+ if (metaCoinAddresses.includes(underlyingCoinAddresses[i]) && metaCoinAddresses.includes(underlyingCoinAddresses[j]))
292
+ continue;
293
+ // avWBTC is frozen by Aave on Avalanche, deposits are not working
294
+ if (chainId === 43114 && poolId === "atricrypto" && i === 3)
295
+ continue;
296
+ const hasEth = underlyingCoinAddresses.includes(constants.NATIVE_TOKEN.address);
297
+ const swapType = (poolData.is_crypto && poolData.is_meta && poolData.is_factory) || ((basePool === null || basePool === void 0 ? void 0 : basePool.is_lending) && poolData.is_factory) ? 3
298
+ : hasEth && poolId !== 'avaxcrypto' ? 1 : 2;
299
+ if (!routerGraph[underlyingCoinAddresses[i]])
300
+ routerGraph[underlyingCoinAddresses[i]] = {};
301
+ if (!routerGraph[underlyingCoinAddresses[i]][underlyingCoinAddresses[j]])
302
+ routerGraph[underlyingCoinAddresses[i]][underlyingCoinAddresses[j]] = [];
303
+ routerGraph[underlyingCoinAddresses[i]][underlyingCoinAddresses[j]] = routerGraph[underlyingCoinAddresses[i]][underlyingCoinAddresses[j]].concat({
304
+ poolId,
305
+ swapAddress,
306
+ inputCoinAddress: underlyingCoinAddresses[i],
307
+ outputCoinAddress: underlyingCoinAddresses[j],
308
+ swapParams: [i, j, swapType, poolType, underlyingCoinAddresses.length],
309
+ poolAddress,
310
+ basePool: basePoolAddress,
311
+ baseToken: baseTokenAddress,
312
+ secondBasePool: secondBasePoolAddress,
313
+ secondBaseToken: secondBaseTokenAddress,
314
+ tvl,
315
+ }).sort((a, b) => b.tvl - a.tvl).slice(0, GRAPH_MAX_EDGES);
316
+ }
317
+ }
318
+ }
319
+ }
320
+ console.log(`Read ${allPools.length} pools`, `${Date.now() - start}ms, routerGraph: ${Object.keys(routerGraph).length} items`);
321
+ return routerGraph;
322
+ };
323
+ if (typeof addEventListener === 'undefined') {
324
+ return createRouteGraph; // for nodejs
325
+ }
326
+ addEventListener('message', (e) => {
327
+ const { type } = e.data;
328
+ if (type === 'createRouteGraph') {
329
+ postMessage({ type, result: createRouteGraph(e.data) });
330
+ }
331
+ });
332
+ }
333
+ // this is a workaround to avoid importing web-worker in the main bundle (nextjs will try to inject invalid hot-reloading code)
334
+ export const routeGraphWorkerCode = `${routeGraphWorker.toString()}; ${routeGraphWorker.name}();`;