@paraswap/dex-lib 2.21.0 → 2.21.1-chronos

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 (131) hide show
  1. package/build/config.js +2 -4
  2. package/build/config.js.map +1 -1
  3. package/build/dex/balancer-v2/balancer-v2.d.ts +3 -9
  4. package/build/dex/balancer-v2/balancer-v2.js +0 -83
  5. package/build/dex/balancer-v2/balancer-v2.js.map +1 -1
  6. package/build/dex/balancer-v2/constants.d.ts +0 -4
  7. package/build/dex/balancer-v2/constants.js +1 -6
  8. package/build/dex/balancer-v2/constants.js.map +1 -1
  9. package/build/dex/balancer-v2/types.d.ts +1 -20
  10. package/build/dex/balancer-v2/types.js.map +1 -1
  11. package/build/dex/curve-v1/constants.d.ts +0 -1
  12. package/build/dex/curve-v1/constants.js +1 -2
  13. package/build/dex/curve-v1/constants.js.map +1 -1
  14. package/build/dex/curve-v1/curve-v1.d.ts +3 -9
  15. package/build/dex/curve-v1/curve-v1.js +4 -92
  16. package/build/dex/curve-v1/curve-v1.js.map +1 -1
  17. package/build/dex/curve-v1/types.d.ts +0 -24
  18. package/build/dex/curve-v1/types.js +1 -6
  19. package/build/dex/curve-v1/types.js.map +1 -1
  20. package/build/dex/curve-v1-factory/constants.d.ts +0 -1
  21. package/build/dex/curve-v1-factory/constants.js +1 -2
  22. package/build/dex/curve-v1-factory/constants.js.map +1 -1
  23. package/build/dex/curve-v1-factory/curve-v1-factory.d.ts +4 -11
  24. package/build/dex/curve-v1-factory/curve-v1-factory.js +0 -87
  25. package/build/dex/curve-v1-factory/curve-v1-factory.js.map +1 -1
  26. package/build/dex/curve-v1-factory/types.d.ts +0 -24
  27. package/build/dex/curve-v1-factory/types.js +1 -6
  28. package/build/dex/curve-v1-factory/types.js.map +1 -1
  29. package/build/dex/curve-v2.d.ts +7 -29
  30. package/build/dex/curve-v2.js +1 -91
  31. package/build/dex/curve-v2.js.map +1 -1
  32. package/build/dex/idex.d.ts +1 -1
  33. package/build/dex/index.js +2 -4
  34. package/build/dex/index.js.map +1 -1
  35. package/build/dex/pancakeswap-v3/pancakeswap-v3.d.ts +2 -2
  36. package/build/dex/pancakeswap-v3/utils.js.map +1 -1
  37. package/build/dex/quickswap/config.js +0 -8
  38. package/build/dex/quickswap/config.js.map +1 -1
  39. package/build/dex/simple-exchange.d.ts +0 -2
  40. package/build/dex/simple-exchange.js +0 -1
  41. package/build/dex/simple-exchange.js.map +1 -1
  42. package/build/dex/solidly/config.js +13 -0
  43. package/build/dex/solidly/config.js.map +1 -1
  44. package/build/dex/solidly/forks-override/chronos.d.ts +3 -0
  45. package/build/dex/solidly/forks-override/chronos.js +88 -0
  46. package/build/dex/solidly/forks-override/chronos.js.map +1 -1
  47. package/build/dex/solidly/solidly.js +1 -0
  48. package/build/dex/solidly/solidly.js.map +1 -1
  49. package/build/dex/uniswap-v2/uniswap-v2.d.ts +1 -1
  50. package/build/dex/uniswap-v2/uniswap-v2.js +1 -1
  51. package/build/dex/uniswap-v2/uniswap-v2.js.map +1 -1
  52. package/build/dex/uniswap-v3/constants.d.ts +0 -4
  53. package/build/dex/uniswap-v3/constants.js +1 -6
  54. package/build/dex/uniswap-v3/constants.js.map +1 -1
  55. package/build/dex/uniswap-v3/types.d.ts +3 -20
  56. package/build/dex/uniswap-v3/types.js.map +1 -1
  57. package/build/dex/uniswap-v3/uniswap-v3.d.ts +1 -7
  58. package/build/dex/uniswap-v3/uniswap-v3.js +1 -85
  59. package/build/dex/uniswap-v3/uniswap-v3.js.map +1 -1
  60. package/build/dex/woo-fi-v2/config.js +6 -6
  61. package/build/dex/zerox/index.d.ts +1 -1
  62. package/build/dex/zerox/index.js +1 -1
  63. package/build/dex/zerox/index.js.map +1 -1
  64. package/build/implementations/local-paraswap-sdk.js +1 -5
  65. package/build/implementations/local-paraswap-sdk.js.map +1 -1
  66. package/build/router/directswap.js +1 -7
  67. package/build/router/directswap.js.map +1 -1
  68. package/build/router/index.js.map +1 -1
  69. package/build/router/payload-encoder.js +6 -16
  70. package/build/router/payload-encoder.js.map +1 -1
  71. package/build/types.d.ts +0 -2
  72. package/build/utils.d.ts +0 -2
  73. package/build/utils.js +1 -5
  74. package/build/utils.js.map +1 -1
  75. package/package.json +4 -6
  76. package/src/config.ts +2 -5
  77. package/src/dex/balancer-v2/balancer-v2-e2e.test.ts +0 -79
  78. package/src/dex/balancer-v2/balancer-v2.ts +4 -153
  79. package/src/dex/balancer-v2/constants.ts +0 -5
  80. package/src/dex/balancer-v2/types.ts +1 -21
  81. package/src/dex/curve-v1/constants.ts +0 -2
  82. package/src/dex/curve-v1/curve-v1-e2e.test.ts +0 -57
  83. package/src/dex/curve-v1/curve-v1.ts +5 -144
  84. package/src/dex/curve-v1/types.ts +0 -26
  85. package/src/dex/curve-v1-factory/constants.ts +0 -2
  86. package/src/dex/curve-v1-factory/curve-v1-factory-e2e.test.ts +0 -1
  87. package/src/dex/curve-v1-factory/curve-v1-factory.ts +4 -140
  88. package/src/dex/curve-v1-factory/types.ts +0 -26
  89. package/src/dex/curve-v2.ts +8 -169
  90. package/src/dex/idex.ts +0 -6
  91. package/src/dex/index.ts +2 -4
  92. package/src/dex/pancakeswap-v3/pancakeswap-v3-e2e.test.ts +6 -3
  93. package/src/dex/pancakeswap-v3/pancakeswap-v3-integration.test.ts +14 -3
  94. package/src/dex/pancakeswap-v3/pancakeswap-v3.ts +3 -3
  95. package/src/dex/pancakeswap-v3/utils.ts +4 -1
  96. package/src/dex/quickswap/config.ts +0 -9
  97. package/src/dex/quickswap/quickswap-e2e.test.ts +0 -109
  98. package/src/dex/simple-exchange.ts +0 -6
  99. package/src/dex/solidly/config.ts +14 -0
  100. package/src/dex/solidly/forks-override/chronos.ts +206 -0
  101. package/src/dex/solidly/solidly-e2e.test.ts +205 -31
  102. package/src/dex/solidly/solidly-integration.test.ts +141 -0
  103. package/src/dex/solidly/solidly.ts +1 -0
  104. package/src/dex/uniswap-v2/uniswap-v2.ts +0 -6
  105. package/src/dex/uniswap-v3/constants.ts +0 -5
  106. package/src/dex/uniswap-v3/types.ts +3 -23
  107. package/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +2 -100
  108. package/src/dex/uniswap-v3/uniswap-v3.ts +3 -138
  109. package/src/dex/woo-fi-v2/config.ts +6 -6
  110. package/src/dex/zerox/index.ts +0 -7
  111. package/src/implementations/local-paraswap-sdk.ts +1 -8
  112. package/src/router/directswap.ts +0 -23
  113. package/src/router/index.ts +2 -0
  114. package/src/router/payload-encoder.ts +5 -22
  115. package/src/types.ts +0 -2
  116. package/src/utils.ts +0 -5
  117. package/tests/constants-e2e.ts +9 -4
  118. package/tests/utils-e2e.ts +20 -140
  119. package/tests/utils.ts +0 -52
  120. package/src/abi/DirectSwap.json +0 -1018
  121. package/src/abi/swaap-v2/vault.json +0 -918
  122. package/src/dex/quickswap/camelot-v3.ts +0 -15
  123. package/src/dex/swaap-v2/config.ts +0 -19
  124. package/src/dex/swaap-v2/constants.ts +0 -37
  125. package/src/dex/swaap-v2/rate-fetcher.ts +0 -214
  126. package/src/dex/swaap-v2/swaap-v2-e2e.test.ts +0 -172
  127. package/src/dex/swaap-v2/swaap-v2-integration.test.ts +0 -142
  128. package/src/dex/swaap-v2/swaap-v2.ts +0 -901
  129. package/src/dex/swaap-v2/types.ts +0 -95
  130. package/src/dex/swaap-v2/utils.ts +0 -36
  131. package/src/dex/swaap-v2/validators.ts +0 -128
@@ -1,901 +0,0 @@
1
- import {
2
- Token,
3
- Address,
4
- ExchangePrices,
5
- PoolPrices,
6
- AdapterExchangeParam,
7
- SimpleExchangeParam,
8
- PoolLiquidity,
9
- Logger,
10
- ExchangeTxInfo,
11
- OptimalSwapExchange,
12
- PreprocessTransactionOptions,
13
- } from '../../types';
14
- import { SwapSide, Network, MAX_INT, MAX_UINT } from '../../constants';
15
- import * as CALLDATA_GAS_COST from '../../calldata-gas-cost';
16
- import { getDexKeysWithNetwork, isAxiosError } from '../../utils';
17
- import { IDex } from '../idex';
18
- import { IDexHelper } from '../../dex-helper/idex-helper';
19
- import {
20
- SwaapV2Data,
21
- SwaapV2PriceLevel,
22
- SwaapV2PriceLevels,
23
- SwaapV2APIParameters,
24
- SwaapV2QuoteError,
25
- TokensMap,
26
- } from './types';
27
- import { SimpleExchange } from '../simple-exchange';
28
- import { Adapters, SwaapV2Config } from './config';
29
- import { RateFetcher } from './rate-fetcher';
30
- import routerAbi from '../../abi/swaap-v2/vault.json';
31
- import BigNumber from 'bignumber.js';
32
- import { BN_0, BN_1, getBigNumberPow } from '../../bignumber-constants';
33
- import { Interface } from 'ethers/lib/utils';
34
- import { assert } from 'ts-essentials';
35
- import {
36
- SWAAP_RFQ_API_URL,
37
- SWAAP_RFQ_PRICES_ENDPOINT,
38
- SWAAP_RFQ_QUOTE_ENDPOINT,
39
- SWAAP_RFQ_API_PRICES_POLLING_INTERVAL_MS,
40
- SWAAP_RFQ_PRICES_CACHES_TTL_S,
41
- GAS_COST_ESTIMATION,
42
- BATCH_SWAP_SELECTOR,
43
- CALLER_SLOT,
44
- SWAAP_BLACKLIST_TTL_S,
45
- SWAAP_RFQ_TOKENS_ENDPOINT,
46
- SWAAP_RESTRICT_TTL_S,
47
- SWAAP_RESTRICTED_CACHE_KEY,
48
- SWAAP_RFQ_API_TOKENS_POLLING_INTERVAL_MS,
49
- SWAAP_RFQ_TOKENS_CACHES_TTL_S,
50
- SWAAP_PRICES_CACHE_KEY,
51
- SWAAP_TOKENS_CACHE_KEY,
52
- SWAAP_ORDER_TYPE_SELL,
53
- SWAAP_ORDER_TYPE_BUY,
54
- } from './constants';
55
- import { getPoolIdentifier, normalizeTokenAddress, getPairName } from './utils';
56
- import { Method } from '../../dex-helper/irequest-wrapper';
57
- import { SlippageCheckError } from '../generic-rfq/types';
58
- import { BI_MAX_UINT256 } from '../../bigint-constants';
59
-
60
- const BLACKLISTED = 'blacklisted';
61
-
62
- export class SwaapV2 extends SimpleExchange implements IDex<SwaapV2Data> {
63
- readonly isStatePollingDex = true;
64
- readonly hasConstantPriceLargeAmounts = false;
65
- readonly needWrapNative = false;
66
- readonly isFeeOnTransferSupported = false;
67
- private rateFetcher: RateFetcher;
68
- private swaapV2AuthToken: string;
69
- private tokensMap: TokensMap = {};
70
-
71
- public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
72
- getDexKeysWithNetwork(SwaapV2Config);
73
-
74
- logger: Logger;
75
-
76
- constructor(
77
- readonly network: Network,
78
- readonly dexKey: string,
79
- readonly dexHelper: IDexHelper,
80
- protected adapters = Adapters[network] || {},
81
- protected routerInterface = new Interface(routerAbi),
82
- ) {
83
- super(dexHelper, dexKey);
84
- this.logger = dexHelper.getLogger(dexKey);
85
- const token = dexHelper.config.data.swaapV2AuthToken;
86
- assert(
87
- token !== undefined,
88
- 'SwaapV2 auth token is not specified with env variable',
89
- );
90
-
91
- this.swaapV2AuthToken = token;
92
-
93
- this.rateFetcher = new RateFetcher(
94
- this.dexHelper,
95
- this.dexKey,
96
- this.logger,
97
- {
98
- rateConfig: {
99
- pricesIntervalMs: SWAAP_RFQ_API_PRICES_POLLING_INTERVAL_MS,
100
- pricesReqParams: this.getPriceLevelsReqParams(),
101
- pricesCacheTTLSecs: SWAAP_RFQ_PRICES_CACHES_TTL_S,
102
- pricesCacheKey: SWAAP_PRICES_CACHE_KEY,
103
- },
104
- tokensConfig: {
105
- tokensIntervalMs: SWAAP_RFQ_API_TOKENS_POLLING_INTERVAL_MS,
106
- tokensReqParams: this.getTokensReqParams(),
107
- tokensCacheTTLSecs: SWAAP_RFQ_TOKENS_CACHES_TTL_S,
108
- tokensCacheKey: SWAAP_TOKENS_CACHE_KEY,
109
- },
110
- },
111
- );
112
- }
113
-
114
- async initializePricing(blockNumber: number): Promise<void> {
115
- if (!this.dexHelper.config.isSlave) {
116
- await this.rateFetcher.start();
117
- }
118
-
119
- return;
120
- }
121
-
122
- getAdapters(side: SwapSide): { name: string; index: number }[] | null {
123
- return this.adapters[side] ? this.adapters[side] : null;
124
- }
125
-
126
- async getPoolIdentifiers(
127
- srcToken: Token,
128
- destToken: Token,
129
- side: SwapSide,
130
- blockNumber: number,
131
- ): Promise<string[]> {
132
- const normalizedSrcToken = this.normalizeToken(srcToken);
133
- const normalizedDestToken = this.normalizeToken(destToken);
134
-
135
- if (normalizedSrcToken.address === normalizedDestToken.address) {
136
- return [];
137
- }
138
-
139
- const poolIdentifier = getPoolIdentifier(
140
- this.dexKey,
141
- normalizedSrcToken.address,
142
- normalizedDestToken.address,
143
- );
144
-
145
- const levels = await this.getCachedLevels();
146
- if (levels === null) {
147
- return [];
148
- }
149
-
150
- return Object.keys(levels)
151
- .map((pair: string) => {
152
- return getPoolIdentifier(
153
- this.dexKey,
154
- levels[pair].base!,
155
- levels[pair].quote!,
156
- );
157
- })
158
- .filter((pi: string) => pi === poolIdentifier);
159
- }
160
-
161
- computePricesFromLevelsBids(
162
- amounts: BigNumber[],
163
- asksAndBids: SwaapV2PriceLevels,
164
- srcToken: Token,
165
- destToken: Token,
166
- side: SwapSide,
167
- ): bigint[] {
168
- let levels: SwaapV2PriceLevel[] = [];
169
- if (side === SwapSide.BUY) {
170
- if (destToken.address === asksAndBids.base!) {
171
- levels = asksAndBids.asks;
172
- } else {
173
- levels = this.invertPrices(asksAndBids.bids);
174
- }
175
- } else {
176
- if (srcToken.address === asksAndBids.base!) {
177
- levels = asksAndBids.bids;
178
- } else {
179
- levels = this.invertPrices(asksAndBids.asks);
180
- }
181
- }
182
-
183
- const firstLevelRaw = levels[0];
184
- const firstLevelAmountBN = new BigNumber(firstLevelRaw.level);
185
-
186
- if (amounts[amounts.length - 1].lt(firstLevelAmountBN)) {
187
- return [];
188
- }
189
-
190
- return this.computeLevelsQuote(amounts, levels, srcToken, destToken, side);
191
- }
192
-
193
- inversePrice(priceLevel: SwaapV2PriceLevel): SwaapV2PriceLevel {
194
- return {
195
- level: priceLevel.level * priceLevel.price,
196
- price: 1 / priceLevel.price,
197
- };
198
- }
199
-
200
- invertPrices(levels: SwaapV2PriceLevel[]): SwaapV2PriceLevel[] {
201
- return levels.map(pl => this.inversePrice(pl));
202
- }
203
-
204
- computeLevelsQuote(
205
- amounts: BigNumber[],
206
- levels: SwaapV2PriceLevel[],
207
- srcToken: Token,
208
- destToken: Token,
209
- side: SwapSide,
210
- ): bigint[] {
211
- const size = levels.length;
212
- if (size === 0) {
213
- return amounts.map(_ => BigInt(0));
214
- }
215
-
216
- return amounts.map((amount: BigNumber) => {
217
- if (amount.isZero()) {
218
- return BigInt(0);
219
- }
220
-
221
- let i = 0;
222
- let output = BN_0;
223
- let previousLevel = BN_0;
224
- let remaininig = BigNumber(amount);
225
- let enoughLiquidity = false;
226
- while (i < size) {
227
- const levelDelta = BigNumber(levels[i].level).minus(previousLevel);
228
- if (levelDelta.lte(remaininig)) {
229
- output = output.plus(levelDelta.times(levels[i].price));
230
- remaininig = remaininig.minus(levelDelta);
231
- previousLevel = BigNumber(levels[i].level);
232
- i += 1;
233
- } else {
234
- output = output.plus(remaininig.times(levels[i].price));
235
- enoughLiquidity = true;
236
- break;
237
- }
238
- }
239
- if (enoughLiquidity) {
240
- return BigInt(
241
- output
242
- .multipliedBy(
243
- getBigNumberPow(
244
- side === SwapSide.BUY ? srcToken.decimals : destToken.decimals,
245
- ),
246
- )
247
- .toFixed(0),
248
- );
249
- }
250
- return BigInt(0); // not enough liquidity
251
- });
252
- }
253
-
254
- async getCachedTokens(): Promise<TokensMap | null> {
255
- const cachedTokens = await this.dexHelper.cache.get(
256
- this.dexKey,
257
- this.network,
258
- SWAAP_TOKENS_CACHE_KEY,
259
- );
260
-
261
- if (cachedTokens) {
262
- return JSON.parse(cachedTokens) as TokensMap;
263
- }
264
-
265
- return null;
266
- }
267
-
268
- async getCachedLevels(): Promise<Record<string, SwaapV2PriceLevels> | null> {
269
- const cachedLevels = await this.dexHelper.cache.get(
270
- this.dexKey,
271
- this.network,
272
- SWAAP_PRICES_CACHE_KEY,
273
- );
274
-
275
- if (cachedLevels) {
276
- return JSON.parse(cachedLevels) as Record<string, SwaapV2PriceLevels>;
277
- }
278
-
279
- return null;
280
- }
281
-
282
- normalizeToken(token: Token): Token {
283
- return {
284
- address: normalizeTokenAddress(token.address),
285
- decimals: token.decimals,
286
- };
287
- }
288
-
289
- async getPricesVolume(
290
- srcToken: Token,
291
- destToken: Token,
292
- amounts: bigint[],
293
- side: SwapSide,
294
- blockNumber: number,
295
- limitPools?: string[],
296
- ): Promise<null | ExchangePrices<SwaapV2Data>> {
297
- try {
298
- if (await this.isRestricted()) {
299
- return null;
300
- }
301
-
302
- this.tokensMap = (await this.getCachedTokens()) || {};
303
-
304
- const normalizedSrcToken = this.normalizeToken(srcToken);
305
- const normalizedDestToken = this.normalizeToken(destToken);
306
-
307
- const requestedPoolIdentifier: string = getPoolIdentifier(
308
- this.dexKey,
309
- normalizedSrcToken.address,
310
- normalizedDestToken.address,
311
- );
312
-
313
- if (normalizedSrcToken.address === normalizedDestToken.address) {
314
- return null;
315
- }
316
-
317
- const pools = limitPools
318
- ? limitPools.filter(
319
- p =>
320
- p ===
321
- getPoolIdentifier(
322
- this.dexKey,
323
- normalizedSrcToken.address,
324
- normalizedDestToken.address,
325
- ) ||
326
- p ===
327
- getPoolIdentifier(
328
- this.dexKey,
329
- normalizedDestToken.address,
330
- normalizedSrcToken.address,
331
- ),
332
- )
333
- : await this.getPoolIdentifiers(srcToken, destToken, side, blockNumber);
334
-
335
- if (pools.length === 0) {
336
- return null;
337
- }
338
-
339
- const levels = await this.getCachedLevels();
340
- if (levels === null) {
341
- return null;
342
- }
343
-
344
- const levelEntries: SwaapV2PriceLevels[] = Object.keys(levels)
345
- .filter(pair => {
346
- const { base, quote } = levels[pair];
347
- if (
348
- pools.includes(getPoolIdentifier(this.dexKey, quote, base)) ||
349
- pools.includes(getPoolIdentifier(this.dexKey, base, quote))
350
- ) {
351
- return true;
352
- }
353
-
354
- return false;
355
- })
356
- .map(pair => {
357
- return levels[pair];
358
- });
359
-
360
- const unitVolume = getBigNumberPow(
361
- (side === SwapSide.SELL ? normalizedSrcToken : normalizedDestToken)
362
- .decimals,
363
- );
364
-
365
- const amountsFloat = amounts.map(a =>
366
- new BigNumber(a.toString()).dividedBy(unitVolume),
367
- );
368
-
369
- const prices = levelEntries.map((askAndBids: SwaapV2PriceLevels) => {
370
- const unitPrice: bigint | undefined = this.computePricesFromLevelsBids(
371
- [unitVolume],
372
- askAndBids,
373
- normalizedSrcToken,
374
- normalizedDestToken,
375
- side,
376
- )[0];
377
-
378
- const prices = this.computePricesFromLevelsBids(
379
- amountsFloat,
380
- askAndBids,
381
- normalizedSrcToken,
382
- normalizedDestToken,
383
- side,
384
- );
385
-
386
- if (!prices.length) {
387
- return null;
388
- }
389
-
390
- return {
391
- gasCost: GAS_COST_ESTIMATION,
392
- exchange: this.dexKey,
393
- data: {},
394
- prices,
395
- unit: unitPrice === undefined ? 0n : unitPrice,
396
- poolIdentifier: requestedPoolIdentifier,
397
- } as PoolPrices<SwaapV2Data>;
398
- });
399
-
400
- return prices.filter((p): p is PoolPrices<SwaapV2Data> => !!p);
401
- } catch (e) {
402
- this.logger.error(
403
- `Error_getPrices ${srcToken}, ${destToken}, ${side}:`,
404
- e,
405
- );
406
- return null;
407
- }
408
- }
409
-
410
- getBaseToken(poolIdentifier: string): string {
411
- return poolIdentifier.split('_')[1];
412
- }
413
-
414
- async preProcessTransaction(
415
- optimalSwapExchange: OptimalSwapExchange<SwaapV2Data>,
416
- srcToken: Token,
417
- destToken: Token,
418
- side: SwapSide,
419
- options: PreprocessTransactionOptions,
420
- ): Promise<[OptimalSwapExchange<SwaapV2Data>, ExchangeTxInfo]> {
421
- if (await this.isBlacklisted(options.txOrigin)) {
422
- this.logger.warn(
423
- `${this.dexKey}-${this.network}: blacklisted TX Origin address '${options.txOrigin}' trying to build a transaction. Bailing...`,
424
- );
425
- throw new Error(
426
- `${this.dexKey}-${
427
- this.network
428
- }: user=${options.txOrigin.toLowerCase()} is blacklisted`,
429
- );
430
- }
431
-
432
- const isSell = side === SwapSide.SELL;
433
-
434
- const normalizedSrcToken = this.normalizeToken(srcToken);
435
- const normalizedDestToken = this.normalizeToken(destToken);
436
-
437
- const tolerance = (
438
- options.slippageFactor > BN_1
439
- ? options.slippageFactor.minus(BN_1)
440
- : BN_1.minus(options.slippageFactor)
441
- ).toNumber();
442
-
443
- try {
444
- const quote = await this.rateFetcher.getQuote(
445
- this.network,
446
- normalizedSrcToken,
447
- normalizedDestToken,
448
- isSell ? optimalSwapExchange.srcAmount : optimalSwapExchange.destAmount,
449
- isSell ? SWAAP_ORDER_TYPE_SELL : SWAAP_ORDER_TYPE_BUY,
450
- options.txOrigin,
451
- this.augustusAddress,
452
- tolerance,
453
- this.getQuoteReqParams(),
454
- );
455
-
456
- if (!quote.success) {
457
- const message = `${this.dexKey}-${
458
- this.network
459
- }: Failed to fetch RFQ for ${getPairName(
460
- normalizedSrcToken.address,
461
- normalizedDestToken.address,
462
- )}: ${JSON.stringify(quote)}`;
463
- this.logger.warn(message);
464
- throw new SwaapV2QuoteError(message);
465
- } else if (!quote.calldata) {
466
- const message = `${this.dexKey}-${
467
- this.network
468
- }: Failed to fetch RFQ for ${getPairName(
469
- normalizedSrcToken.address,
470
- normalizedDestToken.address,
471
- )}. Missing quote data`;
472
- this.logger.warn(message);
473
- throw new SwaapV2QuoteError(message);
474
- } else if (!quote.router) {
475
- const message = `${this.dexKey}-${
476
- this.network
477
- }: Failed to fetch RFQ for ${getPairName(
478
- normalizedSrcToken.address,
479
- normalizedDestToken.address,
480
- )}. Missing router address`;
481
- this.logger.warn(message);
482
- throw new SwaapV2QuoteError(message);
483
- }
484
-
485
- const srcAmount = BigInt(optimalSwapExchange.srcAmount);
486
- const destAmount = BigInt(optimalSwapExchange.destAmount);
487
- const quoteTokenAmount = BigInt(quote.amount);
488
- const slippageFactor = options.slippageFactor;
489
-
490
- if (side === SwapSide.SELL) {
491
- if (
492
- quoteTokenAmount <
493
- BigInt(
494
- new BigNumber(destAmount.toString())
495
- .times(slippageFactor)
496
- .toFixed(0),
497
- )
498
- ) {
499
- const message = `${this.dexKey}-${this.network}: too much slippage on quote ${side} quoteTokenAmount ${quoteTokenAmount} / destAmount ${destAmount} < ${slippageFactor}`;
500
- this.logger.warn(message);
501
- throw new SlippageCheckError(message);
502
- }
503
- } else {
504
- if (
505
- quoteTokenAmount >
506
- BigInt(slippageFactor.times(srcAmount.toString()).toFixed(0))
507
- ) {
508
- const message = `${this.dexKey}-${
509
- this.network
510
- }: too much slippage on quote ${side} baseTokenAmount ${srcAmount} / srcAmount ${srcAmount} > ${slippageFactor.toFixed()}`;
511
- this.logger.warn(message);
512
- throw new SlippageCheckError(message);
513
- }
514
- }
515
-
516
- const expiryAsBigInt = BigInt(quote.expiration);
517
- const minDeadline = expiryAsBigInt > 0 ? expiryAsBigInt : BI_MAX_UINT256;
518
-
519
- return [
520
- {
521
- ...optimalSwapExchange,
522
- data: {
523
- router: quote.router,
524
- callData: quote.calldata,
525
- },
526
- },
527
- { deadline: minDeadline },
528
- ];
529
- } catch (e) {
530
- if (
531
- isAxiosError(e) &&
532
- (e.response?.status === 403 || e.response?.status === 429)
533
- ) {
534
- await this.setBlacklist(options.txOrigin);
535
- this.logger.warn(
536
- `${this.dexKey}-${this.network}: Encountered restricted user=${options.txOrigin}. Adding to local blacklist cache`,
537
- );
538
- } else {
539
- this.logger.warn(
540
- `${this.dexKey}-${this.network}: protocol is restricted`,
541
- );
542
- await this.restrict();
543
- }
544
-
545
- throw e;
546
- }
547
- }
548
-
549
- async restrict(ttl: number = SWAAP_RESTRICT_TTL_S): Promise<boolean> {
550
- await this.dexHelper.cache.setex(
551
- this.dexKey,
552
- this.network,
553
- SWAAP_RESTRICTED_CACHE_KEY,
554
- ttl,
555
- 'true',
556
- );
557
- return true;
558
- }
559
-
560
- async isRestricted(): Promise<boolean> {
561
- const result = await this.dexHelper.cache.get(
562
- this.dexKey,
563
- this.network,
564
- SWAAP_RESTRICTED_CACHE_KEY,
565
- );
566
-
567
- return result === 'true';
568
- }
569
-
570
- async isBlacklisted(txOrigin: Address): Promise<boolean> {
571
- const result = await this.dexHelper.cache.get(
572
- this.dexKey,
573
- this.network,
574
- this.getBlackListKey(txOrigin),
575
- );
576
- return result === BLACKLISTED;
577
- }
578
-
579
- getBlackListKey(address: Address) {
580
- return `blacklist_${address}`.toLowerCase();
581
- }
582
-
583
- async setBlacklist(
584
- txOrigin: Address,
585
- ttl: number = SWAAP_BLACKLIST_TTL_S,
586
- ): Promise<boolean> {
587
- await this.dexHelper.cache.setex(
588
- this.dexKey,
589
- this.network,
590
- this.getBlackListKey(txOrigin),
591
- ttl,
592
- BLACKLISTED,
593
- );
594
- return true;
595
- }
596
-
597
- // Returns estimated gas cost of calldata for this DEX in multiSwap
598
- getCalldataGasCost(poolPrices: PoolPrices<SwaapV2Data>): number | number[] {
599
- return (
600
- CALLDATA_GAS_COST.DEX_OVERHEAD +
601
- CALLDATA_GAS_COST.LENGTH_LARGE +
602
- // ParentStruct header
603
- CALLDATA_GAS_COST.OFFSET_SMALL +
604
- // ParentStruct -> swaps[] header
605
- CALLDATA_GAS_COST.OFFSET_LARGE +
606
- // ParentStruct -> assets[] header
607
- CALLDATA_GAS_COST.OFFSET_LARGE +
608
- // ParentStruct -> funds
609
- CALLDATA_GAS_COST.ADDRESS +
610
- CALLDATA_GAS_COST.BOOL +
611
- CALLDATA_GAS_COST.ADDRESS +
612
- CALLDATA_GAS_COST.BOOL +
613
- // ParentStruct -> limits[] header
614
- CALLDATA_GAS_COST.OFFSET_LARGE +
615
- // ParentStruct -> deadline
616
- CALLDATA_GAS_COST.TIMESTAMP +
617
- // ParentStruct -> swaps[]
618
- CALLDATA_GAS_COST.LENGTH_SMALL +
619
- // ParentStruct -> swaps[0] header
620
- CALLDATA_GAS_COST.OFFSET_SMALL +
621
- // ParentStruct -> swaps[0] -> poolId
622
- CALLDATA_GAS_COST.FULL_WORD +
623
- // ParentStruct -> swaps[0] -> assetInIndex
624
- CALLDATA_GAS_COST.INDEX +
625
- // ParentStruct -> swaps[0] -> assetOutIndex
626
- CALLDATA_GAS_COST.INDEX +
627
- // ParentStruct -> swaps[0] -> amount
628
- CALLDATA_GAS_COST.AMOUNT +
629
- // ParentStruct -> swaps[0] -> userData header
630
- CALLDATA_GAS_COST.OFFSET_SMALL +
631
- // ParentStruct -> swaps[0] -> userData
632
- CALLDATA_GAS_COST.ZERO +
633
- // ParentStruct -> assets[]
634
- CALLDATA_GAS_COST.LENGTH_SMALL +
635
- // ParentStruct -> assets[0:2]
636
- CALLDATA_GAS_COST.ADDRESS * 2 +
637
- // ParentStruct -> limits[]
638
- CALLDATA_GAS_COST.LENGTH_SMALL +
639
- // ParentStruct -> limits[0:2]
640
- CALLDATA_GAS_COST.FULL_WORD * 2 +
641
- // Bool -> IsBatchSwap
642
- CALLDATA_GAS_COST.BOOL
643
- );
644
- }
645
-
646
- getAdapterParam(
647
- srcToken: string,
648
- destToken: string,
649
- srcAmount: string,
650
- destAmount: string,
651
- data: SwaapV2Data,
652
- side: SwapSide,
653
- ): AdapterExchangeParam {
654
- const { router, callData } = data;
655
-
656
- assert(
657
- router !== undefined,
658
- `${this.dexKey}-${this.network}: router undefined`,
659
- );
660
-
661
- assert(
662
- callData !== undefined,
663
- `${this.dexKey}-${this.network}: callData undefined`,
664
- );
665
-
666
- let payload: string;
667
- const truncatedCalldata = '0x' + callData.slice(10); // droping the function selector
668
- const isBatchSwap = callData.slice(0, 10) === BATCH_SWAP_SELECTOR;
669
-
670
- if (isBatchSwap) {
671
- const batchswapAbi = routerAbi.filter(abi => abi.name === 'batchSwap');
672
-
673
- const callDataStruct = this.abiCoder.decodeParameters(
674
- batchswapAbi[0].inputs!,
675
- truncatedCalldata,
676
- );
677
-
678
- const callerSlots = Array(callDataStruct.swaps.length).fill(160);
679
-
680
- payload = this.abiCoder.encodeParameters(
681
- [
682
- 'bool',
683
- 'uint256[]',
684
- {
685
- ParentStruct: {
686
- 'swaps[]': {
687
- poolId: 'bytes32',
688
- assetInIndex: 'uint256',
689
- assetOutIndex: 'uint256',
690
- amount: 'uint256',
691
- userData: 'bytes',
692
- },
693
- assets: 'address[]',
694
- funds: {
695
- sender: 'address',
696
- fromInternalBalance: 'bool',
697
- recipient: 'address',
698
- toInternalBalance: 'bool',
699
- },
700
- limits: 'int256[]',
701
- },
702
- },
703
- ],
704
- [
705
- isBatchSwap,
706
- callerSlots,
707
- {
708
- swaps: callDataStruct.swaps,
709
- assets: callDataStruct.assets,
710
- funds: callDataStruct.funds,
711
- limits: callDataStruct.limits.map((_: any) => MAX_INT),
712
- },
713
- ],
714
- );
715
- } else {
716
- const swapAbi = routerAbi.filter(abi => abi.name === 'swap');
717
-
718
- const callDataStruct = this.abiCoder.decodeParameters(
719
- swapAbi[0].inputs!,
720
- truncatedCalldata,
721
- );
722
-
723
- const callerSlot = CALLER_SLOT;
724
-
725
- payload = this.abiCoder.encodeParameters(
726
- [
727
- 'bool',
728
- 'uint256',
729
- {
730
- ParentStruct: {
731
- swap: {
732
- poolId: 'bytes32',
733
- kind: 'uint8',
734
- assetIn: 'address',
735
- assetOut: 'address',
736
- amount: 'uint256',
737
- userData: 'bytes',
738
- },
739
- funds: {
740
- sender: 'address',
741
- fromInternalBalance: 'bool',
742
- recipient: 'address',
743
- toInternalBalance: 'bool',
744
- },
745
- limit: 'uint256',
746
- },
747
- },
748
- ],
749
- [
750
- isBatchSwap,
751
- callerSlot,
752
- {
753
- swap: {
754
- poolId: callDataStruct.singleSwap.poolId,
755
- kind: callDataStruct.singleSwap.kind,
756
- assetIn: callDataStruct.singleSwap.assetIn,
757
- assetOut: callDataStruct.singleSwap.assetOut,
758
- amount: callDataStruct.singleSwap.amount,
759
- userData: callDataStruct.singleSwap.userData,
760
- },
761
- funds: {
762
- sender: callDataStruct.funds.sender,
763
- fromInternalBalance: callDataStruct.funds.fromInternalBalance,
764
- recipient: callDataStruct.funds.recipient,
765
- toInternalBalance: callDataStruct.funds.toInternalBalance,
766
- },
767
- limit: side === SwapSide.BUY ? MAX_UINT : '0',
768
- },
769
- ],
770
- );
771
- }
772
-
773
- return {
774
- targetExchange: router,
775
- payload: payload,
776
- networkFee: '0',
777
- };
778
- }
779
-
780
- async getSimpleParam(
781
- srcToken: string,
782
- destToken: string,
783
- srcAmount: string,
784
- destAmount: string,
785
- data: SwaapV2Data,
786
- side: SwapSide,
787
- ): Promise<SimpleExchangeParam> {
788
- const { router, callData } = data;
789
-
790
- assert(
791
- router !== undefined,
792
- `${this.dexKey}-${this.network}: router undefined`,
793
- );
794
-
795
- assert(
796
- callData !== undefined,
797
- `${this.dexKey}-${this.network}: callData undefined`,
798
- );
799
-
800
- return this.buildSimpleParamWithoutWETHConversion(
801
- srcToken,
802
- srcAmount,
803
- destToken,
804
- destAmount,
805
- callData,
806
- router,
807
- );
808
- }
809
-
810
- computeMaxLiquidity = (
811
- levels: SwaapV2PriceLevels,
812
- tokenAddress: string,
813
- ): number => {
814
- if (tokenAddress === levels.base!) {
815
- return (
816
- (levels.asks[levels.asks.length - 1]?.level ?? 0) *
817
- levels.asks[0]?.price
818
- );
819
- }
820
- return (
821
- (levels.asks[levels.bids.length - 1]?.level ?? 0) * levels.asks[0]?.price
822
- );
823
- };
824
-
825
- async getTopPoolsForToken(
826
- tokenAddress: Address,
827
- limit: number,
828
- ): Promise<PoolLiquidity[]> {
829
- if (await this.isRestricted()) {
830
- return [];
831
- }
832
-
833
- this.tokensMap = (await this.getCachedTokens()) || {};
834
- const normalizedTokenAddress = normalizeTokenAddress(tokenAddress);
835
-
836
- const pLevels = await this.getCachedLevels();
837
-
838
- if (pLevels === null) {
839
- return [];
840
- }
841
-
842
- return Object.keys(pLevels)
843
- .filter((pair: string) => {
844
- const { base, quote } = pLevels[pair];
845
-
846
- return (
847
- normalizedTokenAddress === base || normalizedTokenAddress === quote
848
- );
849
- })
850
- .map((pair: string) => {
851
- return {
852
- exchange: this.dexKey,
853
- connectorTokens: [
854
- this.getTokenFromAddress(
855
- normalizedTokenAddress === pLevels[pair].base
856
- ? pLevels[pair].quote
857
- : pLevels[pair].base,
858
- ),
859
- ],
860
- liquidityUSD: this.computeMaxLiquidity(pLevels[pair], tokenAddress),
861
- } as PoolLiquidity;
862
- })
863
- .sort((pl: PoolLiquidity) => {
864
- return -pl.liquidityUSD;
865
- })
866
- .slice(0, limit);
867
- }
868
-
869
- getTokenFromAddress(address: Address): Token {
870
- return this.tokensMap[normalizeTokenAddress(address)];
871
- }
872
-
873
- releaseResources(): void {
874
- if (this.rateFetcher) {
875
- this.rateFetcher.stop();
876
- }
877
- }
878
-
879
- getPriceLevelsReqParams(): SwaapV2APIParameters {
880
- return this.getAPIReqParams(SWAAP_RFQ_PRICES_ENDPOINT, 'GET');
881
- }
882
-
883
- getQuoteReqParams(): SwaapV2APIParameters {
884
- return this.getAPIReqParams(SWAAP_RFQ_QUOTE_ENDPOINT, 'POST');
885
- }
886
-
887
- getTokensReqParams(): SwaapV2APIParameters {
888
- return this.getAPIReqParams(SWAAP_RFQ_TOKENS_ENDPOINT, 'GET');
889
- }
890
-
891
- getAPIReqParams(endpoint: string, method: Method): SwaapV2APIParameters {
892
- return {
893
- url: `${SWAAP_RFQ_API_URL}/${endpoint}`,
894
- params: {
895
- networkId: this.network,
896
- },
897
- headers: { 'x-api-key': this.swaapV2AuthToken },
898
- method: method,
899
- };
900
- }
901
- }