@pancakeswap/v2-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,1409 @@
1
+ import { ChainId } from '@pancakeswap/chains';
2
+ import { Price, ZERO, InsufficientReservesError, _9975, _10000, CurrencyAmount, InsufficientInputAmountError, ONE, sqrt, MINIMUM_LIQUIDITY, TradeType, computePriceImpact, Fraction, sortedInsert, Token, FIVE } from '@pancakeswap/swap-sdk-core';
3
+ import { createPublicClient, http, keccak256, encodePacked, getContract, toBytes, getAddress, pad, isBytes, slice, concat } from 'viem';
4
+ import invariant3 from 'tiny-invariant';
5
+ import { ERC20Token, validateAndParseAddress, erc20Abi, ZERO_PERCENT, ONE_HUNDRED_PERCENT } from '@pancakeswap/swap-sdk-evm';
6
+ import { mainnet, bsc, bscTestnet, goerli } from 'viem/chains';
7
+
8
+ // src/constants.ts
9
+ var FACTORY_ADDRESS = "0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73";
10
+ var FACTORY_ADDRESS_ETH = "0x1097053Fd2ea711dad45caCcc45EfF7548fCB362";
11
+ var FACTORY_ADDRESS_MAP = {
12
+ [ChainId.ETHEREUM]: FACTORY_ADDRESS_ETH,
13
+ [ChainId.GOERLI]: FACTORY_ADDRESS_ETH,
14
+ [ChainId.BSC]: FACTORY_ADDRESS,
15
+ [ChainId.BSC_TESTNET]: "0x6725F303b657a9451d8BA641348b6761A6CC7a17",
16
+ [ChainId.ARBITRUM_ONE]: "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E",
17
+ [ChainId.ARBITRUM_GOERLI]: "0x333EAE459075b1d7dE8eb57997b5d4eee5F1070a",
18
+ [ChainId.POLYGON_ZKEVM]: "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E",
19
+ [ChainId.POLYGON_ZKEVM_TESTNET]: "0xBA40c83026213F9cbc79998752721a0312bdB74a",
20
+ [ChainId.ZKSYNC]: "0xd03D8D566183F0086d8D09A84E1e30b58Dd5619d",
21
+ [ChainId.ZKSYNC_TESTNET]: "0x48a33610Cd0E130af2024D55F67aE72a8C51aC27",
22
+ [ChainId.LINEA]: "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E",
23
+ [ChainId.LINEA_TESTNET]: "0xB6FAfd4ADbCd21cF665909767e0eD0D05709abfB",
24
+ [ChainId.OPBNB]: "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E",
25
+ [ChainId.OPBNB_TESTNET]: "0x776e4bD2f72de2176A59465e316335aaf8ed4E8F",
26
+ [ChainId.BASE]: "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E",
27
+ [ChainId.BASE_TESTNET]: "0x715303D2eF7dA7FFAbF637651D71FD11d41fAf7F",
28
+ [ChainId.SCROLL_SEPOLIA]: "0x2B3C5df29F73dbF028BA82C33e0A5A6e5800F75e",
29
+ [ChainId.SEPOLIA]: "0x1bdc540dEB9Ed1fA29964DeEcCc524A8f5e2198e",
30
+ [ChainId.ARBITRUM_SEPOLIA]: "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E",
31
+ [ChainId.BASE_SEPOLIA]: "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E"
32
+ };
33
+ var INIT_CODE_HASH = "0x00fb7f630766e6a796048ea87d01acd3068e8ff67d078148a3fa3f4a84f69bd5";
34
+ var INIT_CODE_HASH_ETH = "0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d";
35
+ var INIT_CODE_HASH_MAP = {
36
+ [ChainId.ETHEREUM]: INIT_CODE_HASH_ETH,
37
+ [ChainId.GOERLI]: INIT_CODE_HASH_ETH,
38
+ [ChainId.BSC]: INIT_CODE_HASH,
39
+ [ChainId.BSC_TESTNET]: "0xd0d4c4cd0848c93cb4fd1f498d7013ee6bfb25783ea21593d5834f5d250ece66",
40
+ [ChainId.ARBITRUM_ONE]: INIT_CODE_HASH_ETH,
41
+ [ChainId.ARBITRUM_GOERLI]: INIT_CODE_HASH_ETH,
42
+ [ChainId.POLYGON_ZKEVM]: INIT_CODE_HASH_ETH,
43
+ [ChainId.POLYGON_ZKEVM_TESTNET]: INIT_CODE_HASH_ETH,
44
+ [ChainId.ZKSYNC]: "0x0100045707a42494392b3558029b9869f865ff9df8f375dc1bf20b0555093f43",
45
+ [ChainId.ZKSYNC_TESTNET]: "0x0100045707a42494392b3558029b9869f865ff9df8f375dc1bf20b0555093f43",
46
+ [ChainId.LINEA]: INIT_CODE_HASH_ETH,
47
+ [ChainId.LINEA_TESTNET]: INIT_CODE_HASH_ETH,
48
+ [ChainId.OPBNB]: INIT_CODE_HASH_ETH,
49
+ [ChainId.OPBNB_TESTNET]: INIT_CODE_HASH_ETH,
50
+ [ChainId.BASE]: INIT_CODE_HASH_ETH,
51
+ [ChainId.BASE_TESTNET]: "0xa5934690703a592a07e841ca29d5e5c79b5e22ed4749057bb216dc31100be1c0",
52
+ [ChainId.SCROLL_SEPOLIA]: INIT_CODE_HASH_ETH,
53
+ [ChainId.SEPOLIA]: INIT_CODE_HASH_ETH,
54
+ [ChainId.ARBITRUM_SEPOLIA]: INIT_CODE_HASH_ETH,
55
+ [ChainId.BASE_SEPOLIA]: INIT_CODE_HASH_ETH
56
+ };
57
+ var PAIR_ADDRESS_CACHE = {};
58
+ var composeKey = (token0, token1) => `${token0.chainId}-${token0.address}-${token1.address}`;
59
+ function getCreate2Address(from_, salt_, initCodeHash) {
60
+ const from = toBytes(getAddress(from_));
61
+ const salt = pad(isBytes(salt_) ? salt_ : toBytes(salt_), {
62
+ size: 32
63
+ });
64
+ return getAddress(slice(keccak256(concat([toBytes("0xff"), from, salt, toBytes(initCodeHash)])), 12));
65
+ }
66
+ var EMPTY_INPU_HASH = "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470";
67
+ var ZKSYNC_PREFIX = "0x2020dba91b30cc0006188af794c2fb30dd8520db7e2c088b7fc7c103c00ca494";
68
+ function getCreate2AddressZkSync(from, salt, initCodeHash) {
69
+ return getAddress(
70
+ `0x${keccak256(concat([ZKSYNC_PREFIX, pad(from, { size: 32 }), salt, initCodeHash, EMPTY_INPU_HASH])).slice(26)}`
71
+ );
72
+ }
73
+ var computePairAddress = ({
74
+ factoryAddress,
75
+ tokenA,
76
+ tokenB
77
+ }) => {
78
+ const [token0, token1] = tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA];
79
+ const key = composeKey(token0, token1);
80
+ if (PAIR_ADDRESS_CACHE?.[key] === void 0) {
81
+ const getCreate2Address_ = token0.chainId === ChainId.ZKSYNC_TESTNET || token1.chainId === ChainId.ZKSYNC ? getCreate2AddressZkSync : getCreate2Address;
82
+ PAIR_ADDRESS_CACHE = {
83
+ ...PAIR_ADDRESS_CACHE,
84
+ [key]: getCreate2Address_(
85
+ factoryAddress,
86
+ keccak256(encodePacked(["address", "address"], [token0.address, token1.address])),
87
+ INIT_CODE_HASH_MAP[token0.chainId]
88
+ )
89
+ };
90
+ }
91
+ return PAIR_ADDRESS_CACHE[key];
92
+ };
93
+ var Pair = class {
94
+ static getAddress(tokenA, tokenB) {
95
+ return computePairAddress({
96
+ factoryAddress: FACTORY_ADDRESS_MAP[tokenA.chainId],
97
+ tokenA,
98
+ tokenB
99
+ });
100
+ }
101
+ constructor(currencyAmountA, tokenAmountB) {
102
+ const tokenAmounts = currencyAmountA.currency.sortsBefore(tokenAmountB.currency) ? [currencyAmountA, tokenAmountB] : [tokenAmountB, currencyAmountA];
103
+ this.liquidityToken = new ERC20Token(
104
+ tokenAmounts[0].currency.chainId,
105
+ Pair.getAddress(tokenAmounts[0].currency, tokenAmounts[1].currency),
106
+ 18,
107
+ "Cake-LP",
108
+ "Pancake LPs"
109
+ );
110
+ this.tokenAmounts = tokenAmounts;
111
+ }
112
+ /**
113
+ * Returns true if the token is either token0 or token1
114
+ * @param token to check
115
+ */
116
+ involvesToken(token) {
117
+ return token.equals(this.token0) || token.equals(this.token1);
118
+ }
119
+ /**
120
+ * Returns the current mid price of the pair in terms of token0, i.e. the ratio of reserve1 to reserve0
121
+ */
122
+ get token0Price() {
123
+ const result = this.tokenAmounts[1].divide(this.tokenAmounts[0]);
124
+ return new Price(this.token0, this.token1, result.denominator, result.numerator);
125
+ }
126
+ /**
127
+ * Returns the current mid price of the pair in terms of token1, i.e. the ratio of reserve0 to reserve1
128
+ */
129
+ get token1Price() {
130
+ const result = this.tokenAmounts[0].divide(this.tokenAmounts[1]);
131
+ return new Price(this.token1, this.token0, result.denominator, result.numerator);
132
+ }
133
+ /**
134
+ * Return the price of the given token in terms of the other token in the pair.
135
+ * @param token token to return price of
136
+ */
137
+ priceOf(token) {
138
+ invariant3(this.involvesToken(token), "TOKEN");
139
+ return token.equals(this.token0) ? this.token0Price : this.token1Price;
140
+ }
141
+ /**
142
+ * Returns the chain ID of the tokens in the pair.
143
+ */
144
+ get chainId() {
145
+ return this.token0.chainId;
146
+ }
147
+ get token0() {
148
+ return this.tokenAmounts[0].currency;
149
+ }
150
+ get token1() {
151
+ return this.tokenAmounts[1].currency;
152
+ }
153
+ get reserve0() {
154
+ return this.tokenAmounts[0];
155
+ }
156
+ get reserve1() {
157
+ return this.tokenAmounts[1];
158
+ }
159
+ reserveOf(token) {
160
+ invariant3(this.involvesToken(token), "TOKEN");
161
+ return token.equals(this.token0) ? this.reserve0 : this.reserve1;
162
+ }
163
+ getOutputAmount(inputAmount) {
164
+ invariant3(this.involvesToken(inputAmount.currency), "TOKEN");
165
+ if (this.reserve0.quotient === ZERO || this.reserve1.quotient === ZERO) {
166
+ throw new InsufficientReservesError();
167
+ }
168
+ const inputReserve = this.reserveOf(inputAmount.currency);
169
+ const outputReserve = this.reserveOf(inputAmount.currency.equals(this.token0) ? this.token1 : this.token0);
170
+ const inputAmountWithFee = inputAmount.quotient * _9975;
171
+ const numerator = inputAmountWithFee * outputReserve.quotient;
172
+ const denominator = inputReserve.quotient * _10000 + inputAmountWithFee;
173
+ const outputAmount = CurrencyAmount.fromRawAmount(
174
+ inputAmount.currency.equals(this.token0) ? this.token1 : this.token0,
175
+ numerator / denominator
176
+ );
177
+ if (outputAmount.quotient === ZERO) {
178
+ throw new InsufficientInputAmountError();
179
+ }
180
+ return [outputAmount, new Pair(inputReserve.add(inputAmount), outputReserve.subtract(outputAmount))];
181
+ }
182
+ getInputAmount(outputAmount) {
183
+ invariant3(this.involvesToken(outputAmount.currency), "TOKEN");
184
+ if (this.reserve0.quotient === ZERO || this.reserve1.quotient === ZERO || outputAmount.quotient >= this.reserveOf(outputAmount.currency).quotient) {
185
+ throw new InsufficientReservesError();
186
+ }
187
+ const outputReserve = this.reserveOf(outputAmount.currency);
188
+ const inputReserve = this.reserveOf(outputAmount.currency.equals(this.token0) ? this.token1 : this.token0);
189
+ const numerator = inputReserve.quotient * outputAmount.quotient * _10000;
190
+ const denominator = (outputReserve.quotient - outputAmount.quotient) * _9975;
191
+ const inputAmount = CurrencyAmount.fromRawAmount(
192
+ outputAmount.currency.equals(this.token0) ? this.token1 : this.token0,
193
+ numerator / denominator + ONE
194
+ );
195
+ return [inputAmount, new Pair(inputReserve.add(inputAmount), outputReserve.subtract(outputAmount))];
196
+ }
197
+ getLiquidityMinted(totalSupply, tokenAmountA, tokenAmountB) {
198
+ invariant3(totalSupply.currency.equals(this.liquidityToken), "LIQUIDITY");
199
+ const tokenAmounts = tokenAmountA.currency.sortsBefore(tokenAmountB.currency) ? [tokenAmountA, tokenAmountB] : [tokenAmountB, tokenAmountA];
200
+ invariant3(tokenAmounts[0].currency.equals(this.token0) && tokenAmounts[1].currency.equals(this.token1), "TOKEN");
201
+ let liquidity;
202
+ if (totalSupply.quotient === ZERO) {
203
+ liquidity = sqrt(tokenAmounts[0].quotient * tokenAmounts[1].quotient) - MINIMUM_LIQUIDITY;
204
+ } else {
205
+ const amount0 = tokenAmounts[0].quotient * totalSupply.quotient / this.reserve0.quotient;
206
+ const amount1 = tokenAmounts[1].quotient * totalSupply.quotient / this.reserve1.quotient;
207
+ liquidity = amount0 <= amount1 ? amount0 : amount1;
208
+ }
209
+ if (!(liquidity > ZERO)) {
210
+ throw new InsufficientInputAmountError();
211
+ }
212
+ return CurrencyAmount.fromRawAmount(this.liquidityToken, liquidity);
213
+ }
214
+ getLiquidityValue(token, totalSupply, liquidity, feeOn = false, kLast) {
215
+ invariant3(this.involvesToken(token), "TOKEN");
216
+ invariant3(totalSupply.currency.equals(this.liquidityToken), "TOTAL_SUPPLY");
217
+ invariant3(liquidity.currency.equals(this.liquidityToken), "LIQUIDITY");
218
+ invariant3(liquidity.quotient <= totalSupply.quotient, "LIQUIDITY");
219
+ let totalSupplyAdjusted;
220
+ if (!feeOn) {
221
+ totalSupplyAdjusted = totalSupply;
222
+ } else {
223
+ invariant3(!!kLast, "K_LAST");
224
+ const kLastParsed = BigInt(kLast);
225
+ if (!(kLastParsed === ZERO)) {
226
+ const rootK = sqrt(this.reserve0.quotient * this.reserve1.quotient);
227
+ const rootKLast = sqrt(kLastParsed);
228
+ if (rootK > rootKLast) {
229
+ const numerator = totalSupply.quotient * (rootK - rootKLast);
230
+ const denominator = rootK * FIVE + rootKLast;
231
+ const feeLiquidity = numerator / denominator;
232
+ totalSupplyAdjusted = totalSupply.add(CurrencyAmount.fromRawAmount(this.liquidityToken, feeLiquidity));
233
+ } else {
234
+ totalSupplyAdjusted = totalSupply;
235
+ }
236
+ } else {
237
+ totalSupplyAdjusted = totalSupply;
238
+ }
239
+ }
240
+ return CurrencyAmount.fromRawAmount(
241
+ token,
242
+ liquidity.quotient * this.reserveOf(token).quotient / totalSupplyAdjusted.quotient
243
+ );
244
+ }
245
+ };
246
+ var Route = class {
247
+ constructor(pairs, input, output) {
248
+ this._midPrice = null;
249
+ invariant3(pairs.length > 0, "PAIRS");
250
+ const { chainId } = pairs[0];
251
+ invariant3(
252
+ pairs.every((pair) => pair.chainId === chainId),
253
+ "CHAIN_IDS"
254
+ );
255
+ const wrappedInput = input.wrapped;
256
+ invariant3(pairs[0].involvesToken(wrappedInput), "INPUT");
257
+ invariant3(typeof output === "undefined" || pairs[pairs.length - 1].involvesToken(output.wrapped), "OUTPUT");
258
+ const path = [wrappedInput];
259
+ for (const [i, pair] of pairs.entries()) {
260
+ const currentInput = path[i];
261
+ invariant3(currentInput.equals(pair.token0) || currentInput.equals(pair.token1), "PATH");
262
+ const output2 = currentInput.equals(pair.token0) ? pair.token1 : pair.token0;
263
+ path.push(output2);
264
+ }
265
+ this.pairs = pairs;
266
+ this.path = path;
267
+ this.input = input;
268
+ this.output = output;
269
+ }
270
+ get midPrice() {
271
+ if (this._midPrice !== null)
272
+ return this._midPrice;
273
+ const prices = [];
274
+ for (const [i, pair] of this.pairs.entries()) {
275
+ prices.push(
276
+ this.path[i].equals(pair.token0) ? new Price(pair.reserve0.currency, pair.reserve1.currency, pair.reserve0.quotient, pair.reserve1.quotient) : new Price(pair.reserve1.currency, pair.reserve0.currency, pair.reserve1.quotient, pair.reserve0.quotient)
277
+ );
278
+ }
279
+ const reduced = prices.slice(1).reduce((accumulator, currentValue) => accumulator.multiply(currentValue), prices[0]);
280
+ return this._midPrice = new Price(this.input, this.output, reduced.denominator, reduced.numerator);
281
+ }
282
+ get chainId() {
283
+ return this.pairs[0].chainId;
284
+ }
285
+ };
286
+ function inputOutputComparator(a, b) {
287
+ invariant3(a.inputAmount.currency.equals(b.inputAmount.currency), "INPUT_CURRENCY");
288
+ invariant3(a.outputAmount.currency.equals(b.outputAmount.currency), "OUTPUT_CURRENCY");
289
+ if (a.outputAmount.equalTo(b.outputAmount)) {
290
+ if (a.inputAmount.equalTo(b.inputAmount)) {
291
+ return 0;
292
+ }
293
+ if (a.inputAmount.lessThan(b.inputAmount)) {
294
+ return -1;
295
+ }
296
+ return 1;
297
+ }
298
+ if (a.outputAmount.lessThan(b.outputAmount)) {
299
+ return 1;
300
+ }
301
+ return -1;
302
+ }
303
+ function tradeComparator(a, b) {
304
+ const ioComp = inputOutputComparator(a, b);
305
+ if (ioComp !== 0) {
306
+ return ioComp;
307
+ }
308
+ if (a.priceImpact.lessThan(b.priceImpact)) {
309
+ return -1;
310
+ }
311
+ if (a.priceImpact.greaterThan(b.priceImpact)) {
312
+ return 1;
313
+ }
314
+ return a.route.path.length - b.route.path.length;
315
+ }
316
+ var Trade = class {
317
+ /**
318
+ * Constructs an exact in trade with the given amount in and route
319
+ * @param route route of the exact in trade
320
+ * @param amountIn the amount being passed in
321
+ */
322
+ static exactIn(route, amountIn) {
323
+ return new Trade(route, amountIn, TradeType.EXACT_INPUT);
324
+ }
325
+ /**
326
+ * Constructs an exact out trade with the given amount out and route
327
+ * @param route route of the exact out trade
328
+ * @param amountOut the amount returned by the trade
329
+ */
330
+ static exactOut(route, amountOut) {
331
+ return new Trade(route, amountOut, TradeType.EXACT_OUTPUT);
332
+ }
333
+ constructor(route, amount, tradeType) {
334
+ this.route = route;
335
+ this.tradeType = tradeType;
336
+ const tokenAmounts = new Array(route.path.length);
337
+ if (tradeType === TradeType.EXACT_INPUT) {
338
+ invariant3(amount.currency.equals(route.input), "INPUT");
339
+ tokenAmounts[0] = amount.wrapped;
340
+ for (let i = 0; i < route.path.length - 1; i++) {
341
+ const pair = route.pairs[i];
342
+ const [outputAmount] = pair.getOutputAmount(tokenAmounts[i]);
343
+ tokenAmounts[i + 1] = outputAmount;
344
+ }
345
+ this.inputAmount = CurrencyAmount.fromFractionalAmount(route.input, amount.numerator, amount.denominator);
346
+ this.outputAmount = CurrencyAmount.fromFractionalAmount(
347
+ route.output,
348
+ tokenAmounts[tokenAmounts.length - 1].numerator,
349
+ tokenAmounts[tokenAmounts.length - 1].denominator
350
+ );
351
+ } else {
352
+ invariant3(amount.currency.equals(route.output), "OUTPUT");
353
+ tokenAmounts[tokenAmounts.length - 1] = amount.wrapped;
354
+ for (let i = route.path.length - 1; i > 0; i--) {
355
+ const pair = route.pairs[i - 1];
356
+ const [inputAmount] = pair.getInputAmount(tokenAmounts[i]);
357
+ tokenAmounts[i - 1] = inputAmount;
358
+ }
359
+ this.inputAmount = CurrencyAmount.fromFractionalAmount(
360
+ route.input,
361
+ tokenAmounts[0].numerator,
362
+ tokenAmounts[0].denominator
363
+ );
364
+ this.outputAmount = CurrencyAmount.fromFractionalAmount(route.output, amount.numerator, amount.denominator);
365
+ }
366
+ this.executionPrice = new Price(
367
+ this.inputAmount.currency,
368
+ this.outputAmount.currency,
369
+ this.inputAmount.quotient,
370
+ this.outputAmount.quotient
371
+ );
372
+ this.priceImpact = computePriceImpact(route.midPrice, this.inputAmount, this.outputAmount);
373
+ }
374
+ /**
375
+ * Get the minimum amount that must be received from this trade for the given slippage tolerance
376
+ * @param slippageTolerance tolerance of unfavorable slippage from the execution price of this trade
377
+ */
378
+ minimumAmountOut(slippageTolerance) {
379
+ invariant3(!slippageTolerance.lessThan(ZERO), "SLIPPAGE_TOLERANCE");
380
+ if (this.tradeType === TradeType.EXACT_OUTPUT) {
381
+ return this.outputAmount;
382
+ }
383
+ const slippageAdjustedAmountOut = new Fraction(ONE).add(slippageTolerance).invert().multiply(this.outputAmount.quotient).quotient;
384
+ return CurrencyAmount.fromRawAmount(this.outputAmount.currency, slippageAdjustedAmountOut);
385
+ }
386
+ /**
387
+ * Get the maximum amount in that can be spent via this trade for the given slippage tolerance
388
+ * @param slippageTolerance tolerance of unfavorable slippage from the execution price of this trade
389
+ */
390
+ maximumAmountIn(slippageTolerance) {
391
+ invariant3(!slippageTolerance.lessThan(ZERO), "SLIPPAGE_TOLERANCE");
392
+ if (this.tradeType === TradeType.EXACT_INPUT) {
393
+ return this.inputAmount;
394
+ }
395
+ const slippageAdjustedAmountIn = new Fraction(ONE).add(slippageTolerance).multiply(this.inputAmount.quotient).quotient;
396
+ return CurrencyAmount.fromRawAmount(this.inputAmount.currency, slippageAdjustedAmountIn);
397
+ }
398
+ /**
399
+ * Given a list of pairs, and a fixed amount in, returns the top `maxNumResults` trades that go from an input token
400
+ * amount to an output token, making at most `maxHops` hops.
401
+ * Note this does not consider aggregation, as routes are linear. It's possible a better route exists by splitting
402
+ * the amount in among multiple routes.
403
+ * @param pairs the pairs to consider in finding the best trade
404
+ * @param nextAmountIn exact amount of input currency to spend
405
+ * @param currencyOut the desired currency out
406
+ * @param maxNumResults maximum number of results to return
407
+ * @param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pair
408
+ * @param currentPairs used in recursion; the current list of pairs
409
+ * @param currencyAmountIn used in recursion; the original value of the currencyAmountIn parameter
410
+ * @param bestTrades used in recursion; the current list of best trades
411
+ */
412
+ static bestTradeExactIn(pairs, currencyAmountIn, currencyOut, { maxNumResults = 3, maxHops = 3 } = {}, currentPairs = [], nextAmountIn = currencyAmountIn, bestTrades = []) {
413
+ invariant3(pairs.length > 0, "PAIRS");
414
+ invariant3(maxHops > 0, "MAX_HOPS");
415
+ invariant3(currencyAmountIn === nextAmountIn || currentPairs.length > 0, "INVALID_RECURSION");
416
+ const amountIn = nextAmountIn.wrapped;
417
+ const tokenOut = currencyOut.wrapped;
418
+ for (let i = 0; i < pairs.length; i++) {
419
+ const pair = pairs[i];
420
+ if (!pair.token0.equals(amountIn.currency) && !pair.token1.equals(amountIn.currency))
421
+ continue;
422
+ if (pair.reserve0.equalTo(ZERO) || pair.reserve1.equalTo(ZERO))
423
+ continue;
424
+ let amountOut;
425
+ try {
426
+ ;
427
+ [amountOut] = pair.getOutputAmount(amountIn);
428
+ } catch (error) {
429
+ if (error.isInsufficientInputAmountError) {
430
+ continue;
431
+ }
432
+ throw error;
433
+ }
434
+ if (amountOut.currency.equals(tokenOut)) {
435
+ sortedInsert(
436
+ bestTrades,
437
+ new Trade(
438
+ new Route([...currentPairs, pair], currencyAmountIn.currency, currencyOut),
439
+ currencyAmountIn,
440
+ TradeType.EXACT_INPUT
441
+ ),
442
+ maxNumResults,
443
+ tradeComparator
444
+ );
445
+ } else if (maxHops > 1 && pairs.length > 1) {
446
+ const pairsExcludingThisPair = pairs.slice(0, i).concat(pairs.slice(i + 1, pairs.length));
447
+ Trade.bestTradeExactIn(
448
+ pairsExcludingThisPair,
449
+ currencyAmountIn,
450
+ currencyOut,
451
+ {
452
+ maxNumResults,
453
+ maxHops: maxHops - 1
454
+ },
455
+ [...currentPairs, pair],
456
+ amountOut,
457
+ bestTrades
458
+ );
459
+ }
460
+ }
461
+ return bestTrades;
462
+ }
463
+ /**
464
+ * Return the execution price after accounting for slippage tolerance
465
+ * @param slippageTolerance the allowed tolerated slippage
466
+ */
467
+ worstExecutionPrice(slippageTolerance) {
468
+ return new Price(
469
+ this.inputAmount.currency,
470
+ this.outputAmount.currency,
471
+ this.maximumAmountIn(slippageTolerance).quotient,
472
+ this.minimumAmountOut(slippageTolerance).quotient
473
+ );
474
+ }
475
+ /**
476
+ * similar to the above method but instead targets a fixed output amount
477
+ * given a list of pairs, and a fixed amount out, returns the top `maxNumResults` trades that go from an input token
478
+ * to an output token amount, making at most `maxHops` hops
479
+ * note this does not consider aggregation, as routes are linear. it's possible a better route exists by splitting
480
+ * the amount in among multiple routes.
481
+ * @param pairs the pairs to consider in finding the best trade
482
+ * @param currencyIn the currency to spend
483
+ * @param nextAmountOut the exact amount of currency out
484
+ * @param maxNumResults maximum number of results to return
485
+ * @param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pair
486
+ * @param currentPairs used in recursion; the current list of pairs
487
+ * @param currencyAmountOut used in recursion; the original value of the currencyAmountOut parameter
488
+ * @param bestTrades used in recursion; the current list of best trades
489
+ */
490
+ static bestTradeExactOut(pairs, currencyIn, currencyAmountOut, { maxNumResults = 3, maxHops = 3 } = {}, currentPairs = [], nextAmountOut = currencyAmountOut, bestTrades = []) {
491
+ invariant3(pairs.length > 0, "PAIRS");
492
+ invariant3(maxHops > 0, "MAX_HOPS");
493
+ invariant3(currencyAmountOut === nextAmountOut || currentPairs.length > 0, "INVALID_RECURSION");
494
+ const amountOut = nextAmountOut.wrapped;
495
+ const tokenIn = currencyIn.wrapped;
496
+ for (let i = 0; i < pairs.length; i++) {
497
+ const pair = pairs[i];
498
+ if (!pair.token0.equals(amountOut.currency) && !pair.token1.equals(amountOut.currency))
499
+ continue;
500
+ if (pair.reserve0.equalTo(ZERO) || pair.reserve1.equalTo(ZERO))
501
+ continue;
502
+ let amountIn;
503
+ try {
504
+ ;
505
+ [amountIn] = pair.getInputAmount(amountOut);
506
+ } catch (error) {
507
+ if (error.isInsufficientReservesError) {
508
+ continue;
509
+ }
510
+ throw error;
511
+ }
512
+ if (amountIn.currency.equals(tokenIn)) {
513
+ sortedInsert(
514
+ bestTrades,
515
+ new Trade(
516
+ new Route([pair, ...currentPairs], currencyIn, currencyAmountOut.currency),
517
+ currencyAmountOut,
518
+ TradeType.EXACT_OUTPUT
519
+ ),
520
+ maxNumResults,
521
+ tradeComparator
522
+ );
523
+ } else if (maxHops > 1 && pairs.length > 1) {
524
+ const pairsExcludingThisPair = pairs.slice(0, i).concat(pairs.slice(i + 1, pairs.length));
525
+ Trade.bestTradeExactOut(
526
+ pairsExcludingThisPair,
527
+ currencyIn,
528
+ currencyAmountOut,
529
+ {
530
+ maxNumResults,
531
+ maxHops: maxHops - 1
532
+ },
533
+ [pair, ...currentPairs],
534
+ amountIn,
535
+ bestTrades
536
+ );
537
+ }
538
+ }
539
+ return bestTrades;
540
+ }
541
+ };
542
+
543
+ // src/abis/IPancakePair.ts
544
+ var pancakePairV2ABI = [
545
+ {
546
+ anonymous: false,
547
+ inputs: [
548
+ {
549
+ indexed: true,
550
+ internalType: "address",
551
+ name: "owner",
552
+ type: "address"
553
+ },
554
+ {
555
+ indexed: true,
556
+ internalType: "address",
557
+ name: "spender",
558
+ type: "address"
559
+ },
560
+ {
561
+ indexed: false,
562
+ internalType: "uint256",
563
+ name: "value",
564
+ type: "uint256"
565
+ }
566
+ ],
567
+ name: "Approval",
568
+ type: "event"
569
+ },
570
+ {
571
+ anonymous: false,
572
+ inputs: [
573
+ {
574
+ indexed: true,
575
+ internalType: "address",
576
+ name: "sender",
577
+ type: "address"
578
+ },
579
+ {
580
+ indexed: false,
581
+ internalType: "uint256",
582
+ name: "amount0",
583
+ type: "uint256"
584
+ },
585
+ {
586
+ indexed: false,
587
+ internalType: "uint256",
588
+ name: "amount1",
589
+ type: "uint256"
590
+ },
591
+ {
592
+ indexed: true,
593
+ internalType: "address",
594
+ name: "to",
595
+ type: "address"
596
+ }
597
+ ],
598
+ name: "Burn",
599
+ type: "event"
600
+ },
601
+ {
602
+ anonymous: false,
603
+ inputs: [
604
+ {
605
+ indexed: true,
606
+ internalType: "address",
607
+ name: "sender",
608
+ type: "address"
609
+ },
610
+ {
611
+ indexed: false,
612
+ internalType: "uint256",
613
+ name: "amount0",
614
+ type: "uint256"
615
+ },
616
+ {
617
+ indexed: false,
618
+ internalType: "uint256",
619
+ name: "amount1",
620
+ type: "uint256"
621
+ }
622
+ ],
623
+ name: "Mint",
624
+ type: "event"
625
+ },
626
+ {
627
+ anonymous: false,
628
+ inputs: [
629
+ {
630
+ indexed: true,
631
+ internalType: "address",
632
+ name: "sender",
633
+ type: "address"
634
+ },
635
+ {
636
+ indexed: false,
637
+ internalType: "uint256",
638
+ name: "amount0In",
639
+ type: "uint256"
640
+ },
641
+ {
642
+ indexed: false,
643
+ internalType: "uint256",
644
+ name: "amount1In",
645
+ type: "uint256"
646
+ },
647
+ {
648
+ indexed: false,
649
+ internalType: "uint256",
650
+ name: "amount0Out",
651
+ type: "uint256"
652
+ },
653
+ {
654
+ indexed: false,
655
+ internalType: "uint256",
656
+ name: "amount1Out",
657
+ type: "uint256"
658
+ },
659
+ {
660
+ indexed: true,
661
+ internalType: "address",
662
+ name: "to",
663
+ type: "address"
664
+ }
665
+ ],
666
+ name: "Swap",
667
+ type: "event"
668
+ },
669
+ {
670
+ anonymous: false,
671
+ inputs: [
672
+ {
673
+ indexed: false,
674
+ internalType: "uint112",
675
+ name: "reserve0",
676
+ type: "uint112"
677
+ },
678
+ {
679
+ indexed: false,
680
+ internalType: "uint112",
681
+ name: "reserve1",
682
+ type: "uint112"
683
+ }
684
+ ],
685
+ name: "Sync",
686
+ type: "event"
687
+ },
688
+ {
689
+ anonymous: false,
690
+ inputs: [
691
+ {
692
+ indexed: true,
693
+ internalType: "address",
694
+ name: "from",
695
+ type: "address"
696
+ },
697
+ {
698
+ indexed: true,
699
+ internalType: "address",
700
+ name: "to",
701
+ type: "address"
702
+ },
703
+ {
704
+ indexed: false,
705
+ internalType: "uint256",
706
+ name: "value",
707
+ type: "uint256"
708
+ }
709
+ ],
710
+ name: "Transfer",
711
+ type: "event"
712
+ },
713
+ {
714
+ constant: true,
715
+ inputs: [],
716
+ name: "DOMAIN_SEPARATOR",
717
+ outputs: [
718
+ {
719
+ internalType: "bytes32",
720
+ name: "",
721
+ type: "bytes32"
722
+ }
723
+ ],
724
+ payable: false,
725
+ stateMutability: "view",
726
+ type: "function"
727
+ },
728
+ {
729
+ constant: true,
730
+ inputs: [],
731
+ name: "MINIMUM_LIQUIDITY",
732
+ outputs: [
733
+ {
734
+ internalType: "uint256",
735
+ name: "",
736
+ type: "uint256"
737
+ }
738
+ ],
739
+ payable: false,
740
+ stateMutability: "pure",
741
+ type: "function"
742
+ },
743
+ {
744
+ constant: true,
745
+ inputs: [],
746
+ name: "PERMIT_TYPEHASH",
747
+ outputs: [
748
+ {
749
+ internalType: "bytes32",
750
+ name: "",
751
+ type: "bytes32"
752
+ }
753
+ ],
754
+ payable: false,
755
+ stateMutability: "pure",
756
+ type: "function"
757
+ },
758
+ {
759
+ constant: true,
760
+ inputs: [
761
+ {
762
+ internalType: "address",
763
+ name: "owner",
764
+ type: "address"
765
+ },
766
+ {
767
+ internalType: "address",
768
+ name: "spender",
769
+ type: "address"
770
+ }
771
+ ],
772
+ name: "allowance",
773
+ outputs: [
774
+ {
775
+ internalType: "uint256",
776
+ name: "",
777
+ type: "uint256"
778
+ }
779
+ ],
780
+ payable: false,
781
+ stateMutability: "view",
782
+ type: "function"
783
+ },
784
+ {
785
+ constant: false,
786
+ inputs: [
787
+ {
788
+ internalType: "address",
789
+ name: "spender",
790
+ type: "address"
791
+ },
792
+ {
793
+ internalType: "uint256",
794
+ name: "value",
795
+ type: "uint256"
796
+ }
797
+ ],
798
+ name: "approve",
799
+ outputs: [
800
+ {
801
+ internalType: "bool",
802
+ name: "",
803
+ type: "bool"
804
+ }
805
+ ],
806
+ payable: false,
807
+ stateMutability: "nonpayable",
808
+ type: "function"
809
+ },
810
+ {
811
+ constant: true,
812
+ inputs: [
813
+ {
814
+ internalType: "address",
815
+ name: "owner",
816
+ type: "address"
817
+ }
818
+ ],
819
+ name: "balanceOf",
820
+ outputs: [
821
+ {
822
+ internalType: "uint256",
823
+ name: "",
824
+ type: "uint256"
825
+ }
826
+ ],
827
+ payable: false,
828
+ stateMutability: "view",
829
+ type: "function"
830
+ },
831
+ {
832
+ constant: false,
833
+ inputs: [
834
+ {
835
+ internalType: "address",
836
+ name: "to",
837
+ type: "address"
838
+ }
839
+ ],
840
+ name: "burn",
841
+ outputs: [
842
+ {
843
+ internalType: "uint256",
844
+ name: "amount0",
845
+ type: "uint256"
846
+ },
847
+ {
848
+ internalType: "uint256",
849
+ name: "amount1",
850
+ type: "uint256"
851
+ }
852
+ ],
853
+ payable: false,
854
+ stateMutability: "nonpayable",
855
+ type: "function"
856
+ },
857
+ {
858
+ constant: true,
859
+ inputs: [],
860
+ name: "decimals",
861
+ outputs: [
862
+ {
863
+ internalType: "uint8",
864
+ name: "",
865
+ type: "uint8"
866
+ }
867
+ ],
868
+ payable: false,
869
+ stateMutability: "pure",
870
+ type: "function"
871
+ },
872
+ {
873
+ constant: true,
874
+ inputs: [],
875
+ name: "factory",
876
+ outputs: [
877
+ {
878
+ internalType: "address",
879
+ name: "",
880
+ type: "address"
881
+ }
882
+ ],
883
+ payable: false,
884
+ stateMutability: "view",
885
+ type: "function"
886
+ },
887
+ {
888
+ constant: true,
889
+ inputs: [],
890
+ name: "getReserves",
891
+ outputs: [
892
+ {
893
+ internalType: "uint112",
894
+ name: "reserve0",
895
+ type: "uint112"
896
+ },
897
+ {
898
+ internalType: "uint112",
899
+ name: "reserve1",
900
+ type: "uint112"
901
+ },
902
+ {
903
+ internalType: "uint32",
904
+ name: "blockTimestampLast",
905
+ type: "uint32"
906
+ }
907
+ ],
908
+ payable: false,
909
+ stateMutability: "view",
910
+ type: "function"
911
+ },
912
+ {
913
+ constant: false,
914
+ inputs: [
915
+ {
916
+ internalType: "address",
917
+ name: "",
918
+ type: "address"
919
+ },
920
+ {
921
+ internalType: "address",
922
+ name: "",
923
+ type: "address"
924
+ }
925
+ ],
926
+ name: "initialize",
927
+ outputs: [],
928
+ payable: false,
929
+ stateMutability: "nonpayable",
930
+ type: "function"
931
+ },
932
+ {
933
+ constant: true,
934
+ inputs: [],
935
+ name: "kLast",
936
+ outputs: [
937
+ {
938
+ internalType: "uint256",
939
+ name: "",
940
+ type: "uint256"
941
+ }
942
+ ],
943
+ payable: false,
944
+ stateMutability: "view",
945
+ type: "function"
946
+ },
947
+ {
948
+ constant: false,
949
+ inputs: [
950
+ {
951
+ internalType: "address",
952
+ name: "to",
953
+ type: "address"
954
+ }
955
+ ],
956
+ name: "mint",
957
+ outputs: [
958
+ {
959
+ internalType: "uint256",
960
+ name: "liquidity",
961
+ type: "uint256"
962
+ }
963
+ ],
964
+ payable: false,
965
+ stateMutability: "nonpayable",
966
+ type: "function"
967
+ },
968
+ {
969
+ constant: true,
970
+ inputs: [],
971
+ name: "name",
972
+ outputs: [
973
+ {
974
+ internalType: "string",
975
+ name: "",
976
+ type: "string"
977
+ }
978
+ ],
979
+ payable: false,
980
+ stateMutability: "pure",
981
+ type: "function"
982
+ },
983
+ {
984
+ constant: true,
985
+ inputs: [
986
+ {
987
+ internalType: "address",
988
+ name: "owner",
989
+ type: "address"
990
+ }
991
+ ],
992
+ name: "nonces",
993
+ outputs: [
994
+ {
995
+ internalType: "uint256",
996
+ name: "",
997
+ type: "uint256"
998
+ }
999
+ ],
1000
+ payable: false,
1001
+ stateMutability: "view",
1002
+ type: "function"
1003
+ },
1004
+ {
1005
+ constant: false,
1006
+ inputs: [
1007
+ {
1008
+ internalType: "address",
1009
+ name: "owner",
1010
+ type: "address"
1011
+ },
1012
+ {
1013
+ internalType: "address",
1014
+ name: "spender",
1015
+ type: "address"
1016
+ },
1017
+ {
1018
+ internalType: "uint256",
1019
+ name: "value",
1020
+ type: "uint256"
1021
+ },
1022
+ {
1023
+ internalType: "uint256",
1024
+ name: "deadline",
1025
+ type: "uint256"
1026
+ },
1027
+ {
1028
+ internalType: "uint8",
1029
+ name: "v",
1030
+ type: "uint8"
1031
+ },
1032
+ {
1033
+ internalType: "bytes32",
1034
+ name: "r",
1035
+ type: "bytes32"
1036
+ },
1037
+ {
1038
+ internalType: "bytes32",
1039
+ name: "s",
1040
+ type: "bytes32"
1041
+ }
1042
+ ],
1043
+ name: "permit",
1044
+ outputs: [],
1045
+ payable: false,
1046
+ stateMutability: "nonpayable",
1047
+ type: "function"
1048
+ },
1049
+ {
1050
+ constant: true,
1051
+ inputs: [],
1052
+ name: "price0CumulativeLast",
1053
+ outputs: [
1054
+ {
1055
+ internalType: "uint256",
1056
+ name: "",
1057
+ type: "uint256"
1058
+ }
1059
+ ],
1060
+ payable: false,
1061
+ stateMutability: "view",
1062
+ type: "function"
1063
+ },
1064
+ {
1065
+ constant: true,
1066
+ inputs: [],
1067
+ name: "price1CumulativeLast",
1068
+ outputs: [
1069
+ {
1070
+ internalType: "uint256",
1071
+ name: "",
1072
+ type: "uint256"
1073
+ }
1074
+ ],
1075
+ payable: false,
1076
+ stateMutability: "view",
1077
+ type: "function"
1078
+ },
1079
+ {
1080
+ constant: false,
1081
+ inputs: [
1082
+ {
1083
+ internalType: "address",
1084
+ name: "to",
1085
+ type: "address"
1086
+ }
1087
+ ],
1088
+ name: "skim",
1089
+ outputs: [],
1090
+ payable: false,
1091
+ stateMutability: "nonpayable",
1092
+ type: "function"
1093
+ },
1094
+ {
1095
+ constant: false,
1096
+ inputs: [
1097
+ {
1098
+ internalType: "uint256",
1099
+ name: "amount0Out",
1100
+ type: "uint256"
1101
+ },
1102
+ {
1103
+ internalType: "uint256",
1104
+ name: "amount1Out",
1105
+ type: "uint256"
1106
+ },
1107
+ {
1108
+ internalType: "address",
1109
+ name: "to",
1110
+ type: "address"
1111
+ },
1112
+ {
1113
+ internalType: "bytes",
1114
+ name: "data",
1115
+ type: "bytes"
1116
+ }
1117
+ ],
1118
+ name: "swap",
1119
+ outputs: [],
1120
+ payable: false,
1121
+ stateMutability: "nonpayable",
1122
+ type: "function"
1123
+ },
1124
+ {
1125
+ constant: true,
1126
+ inputs: [],
1127
+ name: "symbol",
1128
+ outputs: [
1129
+ {
1130
+ internalType: "string",
1131
+ name: "",
1132
+ type: "string"
1133
+ }
1134
+ ],
1135
+ payable: false,
1136
+ stateMutability: "pure",
1137
+ type: "function"
1138
+ },
1139
+ {
1140
+ constant: false,
1141
+ inputs: [],
1142
+ name: "sync",
1143
+ outputs: [],
1144
+ payable: false,
1145
+ stateMutability: "nonpayable",
1146
+ type: "function"
1147
+ },
1148
+ {
1149
+ constant: true,
1150
+ inputs: [],
1151
+ name: "token0",
1152
+ outputs: [
1153
+ {
1154
+ internalType: "address",
1155
+ name: "",
1156
+ type: "address"
1157
+ }
1158
+ ],
1159
+ payable: false,
1160
+ stateMutability: "view",
1161
+ type: "function"
1162
+ },
1163
+ {
1164
+ constant: true,
1165
+ inputs: [],
1166
+ name: "token1",
1167
+ outputs: [
1168
+ {
1169
+ internalType: "address",
1170
+ name: "",
1171
+ type: "address"
1172
+ }
1173
+ ],
1174
+ payable: false,
1175
+ stateMutability: "view",
1176
+ type: "function"
1177
+ },
1178
+ {
1179
+ constant: true,
1180
+ inputs: [],
1181
+ name: "totalSupply",
1182
+ outputs: [
1183
+ {
1184
+ internalType: "uint256",
1185
+ name: "",
1186
+ type: "uint256"
1187
+ }
1188
+ ],
1189
+ payable: false,
1190
+ stateMutability: "view",
1191
+ type: "function"
1192
+ },
1193
+ {
1194
+ constant: false,
1195
+ inputs: [
1196
+ {
1197
+ internalType: "address",
1198
+ name: "to",
1199
+ type: "address"
1200
+ },
1201
+ {
1202
+ internalType: "uint256",
1203
+ name: "value",
1204
+ type: "uint256"
1205
+ }
1206
+ ],
1207
+ name: "transfer",
1208
+ outputs: [
1209
+ {
1210
+ internalType: "bool",
1211
+ name: "",
1212
+ type: "bool"
1213
+ }
1214
+ ],
1215
+ payable: false,
1216
+ stateMutability: "nonpayable",
1217
+ type: "function"
1218
+ },
1219
+ {
1220
+ constant: false,
1221
+ inputs: [
1222
+ {
1223
+ internalType: "address",
1224
+ name: "from",
1225
+ type: "address"
1226
+ },
1227
+ {
1228
+ internalType: "address",
1229
+ name: "to",
1230
+ type: "address"
1231
+ },
1232
+ {
1233
+ internalType: "uint256",
1234
+ name: "value",
1235
+ type: "uint256"
1236
+ }
1237
+ ],
1238
+ name: "transferFrom",
1239
+ outputs: [
1240
+ {
1241
+ internalType: "bool",
1242
+ name: "",
1243
+ type: "bool"
1244
+ }
1245
+ ],
1246
+ payable: false,
1247
+ stateMutability: "nonpayable",
1248
+ type: "function"
1249
+ }
1250
+ ];
1251
+ function toHex(currencyAmount) {
1252
+ return `0x${currencyAmount.quotient.toString(16)}`;
1253
+ }
1254
+ var ZERO_HEX = "0x0";
1255
+ var Router = class {
1256
+ /**
1257
+ * Produces the on-chain method name to call and the hex encoded parameters to pass as arguments for a given trade.
1258
+ * @param trade to produce call parameters for
1259
+ * @param options options for the call parameters
1260
+ */
1261
+ static swapCallParameters(trade, options) {
1262
+ const etherIn = trade.inputAmount.currency.isNative;
1263
+ const etherOut = trade.outputAmount.currency.isNative;
1264
+ invariant3(!(etherIn && etherOut), "ETHER_IN_OUT");
1265
+ invariant3(!("ttl" in options) || options.ttl > 0, "TTL");
1266
+ const to = validateAndParseAddress(options.recipient);
1267
+ const amountIn = toHex(trade.maximumAmountIn(options.allowedSlippage));
1268
+ const amountOut = toHex(trade.minimumAmountOut(options.allowedSlippage));
1269
+ const path = trade.route.path.map((token) => token.address);
1270
+ const deadline = "ttl" in options ? `0x${(Math.floor(( new Date()).getTime() / 1e3) + options.ttl).toString(16)}` : `0x${options.deadline.toString(16)}`;
1271
+ const useFeeOnTransfer = Boolean(options.feeOnTransfer);
1272
+ let methodName;
1273
+ let args;
1274
+ let value;
1275
+ switch (trade.tradeType) {
1276
+ case TradeType.EXACT_INPUT:
1277
+ if (etherIn) {
1278
+ methodName = useFeeOnTransfer ? "swapExactETHForTokensSupportingFeeOnTransferTokens" : "swapExactETHForTokens";
1279
+ args = [amountOut, path, to, deadline];
1280
+ value = amountIn;
1281
+ } else if (etherOut) {
1282
+ methodName = useFeeOnTransfer ? "swapExactTokensForETHSupportingFeeOnTransferTokens" : "swapExactTokensForETH";
1283
+ args = [amountIn, amountOut, path, to, deadline];
1284
+ value = ZERO_HEX;
1285
+ } else {
1286
+ methodName = useFeeOnTransfer ? "swapExactTokensForTokensSupportingFeeOnTransferTokens" : "swapExactTokensForTokens";
1287
+ args = [amountIn, amountOut, path, to, deadline];
1288
+ value = ZERO_HEX;
1289
+ }
1290
+ break;
1291
+ case TradeType.EXACT_OUTPUT:
1292
+ invariant3(!useFeeOnTransfer, "EXACT_OUT_FOT");
1293
+ if (etherIn) {
1294
+ methodName = "swapETHForExactTokens";
1295
+ args = [amountOut, path, to, deadline];
1296
+ value = amountIn;
1297
+ } else if (etherOut) {
1298
+ methodName = "swapTokensForExactETH";
1299
+ args = [amountOut, amountIn, path, to, deadline];
1300
+ value = ZERO_HEX;
1301
+ } else {
1302
+ methodName = "swapTokensForExactTokens";
1303
+ args = [amountOut, amountIn, path, to, deadline];
1304
+ value = ZERO_HEX;
1305
+ }
1306
+ break;
1307
+ }
1308
+ return {
1309
+ methodName,
1310
+ args,
1311
+ value
1312
+ };
1313
+ }
1314
+ };
1315
+ var TOKEN_DECIMALS_CACHE = {
1316
+ [ChainId.BSC]: {}
1317
+ };
1318
+ var ethClient = createPublicClient({ chain: mainnet, transport: http() });
1319
+ var bscClient = createPublicClient({ chain: bsc, transport: http() });
1320
+ var bscTestnetClient = createPublicClient({ chain: bscTestnet, transport: http() });
1321
+ var goerliClient = createPublicClient({ chain: goerli, transport: http() });
1322
+ var getDefaultClient = (chainId) => {
1323
+ switch (chainId) {
1324
+ case ChainId.ETHEREUM:
1325
+ return ethClient;
1326
+ case ChainId.BSC:
1327
+ return bscClient;
1328
+ case ChainId.BSC_TESTNET:
1329
+ return bscTestnetClient;
1330
+ case ChainId.GOERLI:
1331
+ return goerliClient;
1332
+ default:
1333
+ return bscClient;
1334
+ }
1335
+ };
1336
+ var Fetcher = class {
1337
+ /**
1338
+ * Cannot be constructed.
1339
+ */
1340
+ // eslint-disable-next-line no-useless-constructor,@typescript-eslint/no-empty-function
1341
+ constructor() {
1342
+ }
1343
+ /**
1344
+ * Fetch information for a given token on the given chain, using the given viem provider.
1345
+ * @param chainId chain of the token
1346
+ * @param address address of the token on the chain
1347
+ * @param provider provider used to fetch the token
1348
+ * @param symbol symbol of the token
1349
+ * @param name optional name of the token
1350
+ */
1351
+ static async fetchTokenData(chainId, address, publicClient = getDefaultClient(chainId), symbol, name) {
1352
+ const erc20 = getContract({
1353
+ abi: erc20Abi,
1354
+ address,
1355
+ client: publicClient
1356
+ });
1357
+ const parsedDecimals = typeof TOKEN_DECIMALS_CACHE?.[chainId]?.[address] === "number" ? TOKEN_DECIMALS_CACHE[chainId][address] : await erc20.read.decimals().then((decimals) => {
1358
+ TOKEN_DECIMALS_CACHE = {
1359
+ ...TOKEN_DECIMALS_CACHE,
1360
+ [chainId]: {
1361
+ ...TOKEN_DECIMALS_CACHE?.[chainId],
1362
+ [address]: decimals
1363
+ }
1364
+ };
1365
+ return decimals;
1366
+ });
1367
+ return new Token(chainId, address, parsedDecimals, symbol, name);
1368
+ }
1369
+ /**
1370
+ * Fetches information about a pair and constructs a pair from the given two tokens.
1371
+ * @param tokenA first token
1372
+ * @param tokenB second token
1373
+ * @param provider the provider to use to fetch the data
1374
+ */
1375
+ static async fetchPairData(tokenA, tokenB, publicClient = getDefaultClient(tokenA.chainId)) {
1376
+ invariant3(tokenA.chainId === tokenB.chainId, "CHAIN_ID");
1377
+ const address = Pair.getAddress(tokenA, tokenB);
1378
+ const pairContract = getContract({
1379
+ abi: pancakePairV2ABI,
1380
+ address,
1381
+ client: publicClient
1382
+ });
1383
+ const [reserves0, reserves1] = await pairContract.read.getReserves();
1384
+ const balances = tokenA.sortsBefore(tokenB) ? [reserves0, reserves1] : [reserves1, reserves0];
1385
+ return new Pair(
1386
+ CurrencyAmount.fromRawAmount(tokenA, balances[0]),
1387
+ CurrencyAmount.fromRawAmount(tokenB, balances[1])
1388
+ );
1389
+ }
1390
+ };
1391
+ function isTradeBetter(tradeA, tradeB, minimumDelta = ZERO_PERCENT) {
1392
+ if (tradeA && !tradeB)
1393
+ return false;
1394
+ if (tradeB && !tradeA)
1395
+ return true;
1396
+ if (!tradeA || !tradeB)
1397
+ return void 0;
1398
+ if (tradeA.tradeType !== tradeB.tradeType || !tradeA.inputAmount.currency.equals(tradeB.inputAmount.currency) || !tradeA.outputAmount.currency.equals(tradeB.outputAmount.currency)) {
1399
+ throw new Error("Trades are not comparable");
1400
+ }
1401
+ if (minimumDelta.equalTo(ZERO_PERCENT)) {
1402
+ return tradeA.executionPrice.lessThan(tradeB.executionPrice);
1403
+ }
1404
+ return tradeA.executionPrice.asFraction.multiply(minimumDelta.add(ONE_HUNDRED_PERCENT)).lessThan(tradeB.executionPrice);
1405
+ }
1406
+
1407
+ export { FACTORY_ADDRESS, FACTORY_ADDRESS_MAP, Fetcher, INIT_CODE_HASH, INIT_CODE_HASH_MAP, Pair, Route, Router, Trade, computePairAddress, inputOutputComparator, isTradeBetter, pancakePairV2ABI, tradeComparator };
1408
+ //# sourceMappingURL=out.js.map
1409
+ //# sourceMappingURL=index.mjs.map