@pancakeswap/sdk 3.1.4 → 3.2.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.d.ts +14 -5
- package/dist/index.js +375 -232
- package/dist/index.mjs +288 -154
- package/package.json +13 -6
package/dist/index.mjs
CHANGED
|
@@ -1,23 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import {
|
|
1
|
+
import JSBI from 'jsbi';
|
|
2
|
+
export { default as JSBI } from 'jsbi';
|
|
3
|
+
import { Percent, Token, Price, ZERO, InsufficientReservesError, _9975, _10000, CurrencyAmount, InsufficientInputAmountError, ONE, sqrt, MINIMUM_LIQUIDITY, FIVE, TradeType, computePriceImpact, Fraction, sortedInsert, NativeCurrency } from '@pancakeswap/swap-sdk-core';
|
|
4
|
+
export * from '@pancakeswap/swap-sdk-core';
|
|
5
|
+
import { getAddress, getCreate2Address } from '@ethersproject/address';
|
|
6
|
+
import invariant4 from 'tiny-invariant';
|
|
7
|
+
import warning from 'tiny-warning';
|
|
8
|
+
import { keccak256, pack } from '@ethersproject/solidity';
|
|
9
9
|
|
|
10
|
-
// src/
|
|
11
|
-
import { getAddress } from "@ethersproject/address";
|
|
12
|
-
import invariant from "tiny-invariant";
|
|
13
|
-
import warning from "tiny-warning";
|
|
10
|
+
// src/index.ts
|
|
14
11
|
function validateAndParseAddress(address) {
|
|
15
12
|
try {
|
|
16
13
|
const checksummedAddress = getAddress(address);
|
|
17
14
|
warning(address === checksummedAddress, `${address} is not checksummed.`);
|
|
18
15
|
return checksummedAddress;
|
|
19
16
|
} catch (error) {
|
|
20
|
-
|
|
17
|
+
invariant4(false, `${address} is not a valid address.`);
|
|
21
18
|
}
|
|
22
19
|
}
|
|
23
20
|
|
|
@@ -29,12 +26,12 @@ var ERC20Token = class extends Token {
|
|
|
29
26
|
};
|
|
30
27
|
|
|
31
28
|
// src/constants.ts
|
|
32
|
-
var ChainId = /* @__PURE__ */ ((
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return
|
|
29
|
+
var ChainId = /* @__PURE__ */ ((ChainId3) => {
|
|
30
|
+
ChainId3[ChainId3["ETHEREUM"] = 1] = "ETHEREUM";
|
|
31
|
+
ChainId3[ChainId3["GOERLI"] = 5] = "GOERLI";
|
|
32
|
+
ChainId3[ChainId3["BSC"] = 56] = "BSC";
|
|
33
|
+
ChainId3[ChainId3["BSC_TESTNET"] = 97] = "BSC_TESTNET";
|
|
34
|
+
return ChainId3;
|
|
38
35
|
})(ChainId || {});
|
|
39
36
|
var ZERO_PERCENT = new Percent("0");
|
|
40
37
|
var ONE_HUNDRED_PERCENT = new Percent("1");
|
|
@@ -55,13 +52,48 @@ var INIT_CODE_HASH_MAP = {
|
|
|
55
52
|
[97 /* BSC_TESTNET */]: "0xd0d4c4cd0848c93cb4fd1f498d7013ee6bfb25783ea21593d5834f5d250ece66"
|
|
56
53
|
};
|
|
57
54
|
var WETH9 = {
|
|
58
|
-
[1 /* ETHEREUM */]: new ERC20Token(
|
|
59
|
-
|
|
55
|
+
[1 /* ETHEREUM */]: new ERC20Token(
|
|
56
|
+
1 /* ETHEREUM */,
|
|
57
|
+
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
|
58
|
+
18,
|
|
59
|
+
"WETH",
|
|
60
|
+
"Wrapped Ether",
|
|
61
|
+
"https://weth.io"
|
|
62
|
+
),
|
|
63
|
+
[5 /* GOERLI */]: new ERC20Token(
|
|
64
|
+
5 /* GOERLI */,
|
|
65
|
+
"0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6",
|
|
66
|
+
18,
|
|
67
|
+
"WETH",
|
|
68
|
+
"Wrapped Ether",
|
|
69
|
+
"https://weth.io"
|
|
70
|
+
)
|
|
60
71
|
};
|
|
61
72
|
var WBNB = {
|
|
62
|
-
[1 /* ETHEREUM */]: new ERC20Token(
|
|
63
|
-
|
|
64
|
-
|
|
73
|
+
[1 /* ETHEREUM */]: new ERC20Token(
|
|
74
|
+
1 /* ETHEREUM */,
|
|
75
|
+
"0x418D75f65a02b3D53B2418FB8E1fe493759c7605",
|
|
76
|
+
18,
|
|
77
|
+
"WBNB",
|
|
78
|
+
"Wrapped BNB",
|
|
79
|
+
"https://www.binance.org"
|
|
80
|
+
),
|
|
81
|
+
[56 /* BSC */]: new ERC20Token(
|
|
82
|
+
56 /* BSC */,
|
|
83
|
+
"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
|
|
84
|
+
18,
|
|
85
|
+
"WBNB",
|
|
86
|
+
"Wrapped BNB",
|
|
87
|
+
"https://www.binance.org"
|
|
88
|
+
),
|
|
89
|
+
[97 /* BSC_TESTNET */]: new ERC20Token(
|
|
90
|
+
97 /* BSC_TESTNET */,
|
|
91
|
+
"0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd",
|
|
92
|
+
18,
|
|
93
|
+
"WBNB",
|
|
94
|
+
"Wrapped BNB",
|
|
95
|
+
"https://www.binance.org"
|
|
96
|
+
)
|
|
65
97
|
};
|
|
66
98
|
var WNATIVE = {
|
|
67
99
|
[1 /* ETHEREUM */]: WETH9[1 /* ETHEREUM */],
|
|
@@ -100,25 +132,6 @@ function isTradeBetter(tradeA, tradeB, minimumDelta = ZERO_PERCENT) {
|
|
|
100
132
|
}
|
|
101
133
|
return tradeA.executionPrice.asFraction.multiply(minimumDelta.add(ONE_HUNDRED_PERCENT)).lessThan(tradeB.executionPrice);
|
|
102
134
|
}
|
|
103
|
-
|
|
104
|
-
// src/entities/pair.ts
|
|
105
|
-
import {
|
|
106
|
-
InsufficientInputAmountError,
|
|
107
|
-
InsufficientReservesError,
|
|
108
|
-
sqrt,
|
|
109
|
-
CurrencyAmount,
|
|
110
|
-
Price,
|
|
111
|
-
FIVE,
|
|
112
|
-
ONE,
|
|
113
|
-
ZERO,
|
|
114
|
-
_10000,
|
|
115
|
-
_9975,
|
|
116
|
-
MINIMUM_LIQUIDITY
|
|
117
|
-
} from "@pancakeswap/swap-sdk-core";
|
|
118
|
-
import { getCreate2Address } from "@ethersproject/address";
|
|
119
|
-
import { keccak256, pack } from "@ethersproject/solidity";
|
|
120
|
-
import JSBI from "jsbi";
|
|
121
|
-
import invariant2 from "tiny-invariant";
|
|
122
135
|
var PAIR_ADDRESS_CACHE = {};
|
|
123
136
|
var composeKey = (token0, token1) => `${token0.chainId}-${token0.address}-${token1.address}`;
|
|
124
137
|
var computePairAddress = ({
|
|
@@ -131,7 +144,11 @@ var computePairAddress = ({
|
|
|
131
144
|
if ((PAIR_ADDRESS_CACHE == null ? void 0 : PAIR_ADDRESS_CACHE[key]) === void 0) {
|
|
132
145
|
PAIR_ADDRESS_CACHE = {
|
|
133
146
|
...PAIR_ADDRESS_CACHE,
|
|
134
|
-
[key]: getCreate2Address(
|
|
147
|
+
[key]: getCreate2Address(
|
|
148
|
+
factoryAddress,
|
|
149
|
+
keccak256(["bytes"], [pack(["address", "address"], [token0.address, token1.address])]),
|
|
150
|
+
INIT_CODE_HASH_MAP[token0.chainId]
|
|
151
|
+
)
|
|
135
152
|
};
|
|
136
153
|
}
|
|
137
154
|
return PAIR_ADDRESS_CACHE[key];
|
|
@@ -142,24 +159,47 @@ var Pair = class {
|
|
|
142
159
|
}
|
|
143
160
|
constructor(currencyAmountA, tokenAmountB) {
|
|
144
161
|
const tokenAmounts = currencyAmountA.currency.sortsBefore(tokenAmountB.currency) ? [currencyAmountA, tokenAmountB] : [tokenAmountB, currencyAmountA];
|
|
145
|
-
this.liquidityToken = new ERC20Token(
|
|
162
|
+
this.liquidityToken = new ERC20Token(
|
|
163
|
+
tokenAmounts[0].currency.chainId,
|
|
164
|
+
Pair.getAddress(tokenAmounts[0].currency, tokenAmounts[1].currency),
|
|
165
|
+
18,
|
|
166
|
+
"Cake-LP",
|
|
167
|
+
"Pancake LPs"
|
|
168
|
+
);
|
|
146
169
|
this.tokenAmounts = tokenAmounts;
|
|
147
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Returns true if the token is either token0 or token1
|
|
173
|
+
* @param token to check
|
|
174
|
+
*/
|
|
148
175
|
involvesToken(token) {
|
|
149
176
|
return token.equals(this.token0) || token.equals(this.token1);
|
|
150
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* Returns the current mid price of the pair in terms of token0, i.e. the ratio of reserve1 to reserve0
|
|
180
|
+
*/
|
|
151
181
|
get token0Price() {
|
|
152
182
|
const result = this.tokenAmounts[1].divide(this.tokenAmounts[0]);
|
|
153
183
|
return new Price(this.token0, this.token1, result.denominator, result.numerator);
|
|
154
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* Returns the current mid price of the pair in terms of token1, i.e. the ratio of reserve0 to reserve1
|
|
187
|
+
*/
|
|
155
188
|
get token1Price() {
|
|
156
189
|
const result = this.tokenAmounts[0].divide(this.tokenAmounts[1]);
|
|
157
190
|
return new Price(this.token1, this.token0, result.denominator, result.numerator);
|
|
158
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* Return the price of the given token in terms of the other token in the pair.
|
|
194
|
+
* @param token token to return price of
|
|
195
|
+
*/
|
|
159
196
|
priceOf(token) {
|
|
160
|
-
|
|
197
|
+
invariant4(this.involvesToken(token), "TOKEN");
|
|
161
198
|
return token.equals(this.token0) ? this.token0Price : this.token1Price;
|
|
162
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* Returns the chain ID of the tokens in the pair.
|
|
202
|
+
*/
|
|
163
203
|
get chainId() {
|
|
164
204
|
return this.token0.chainId;
|
|
165
205
|
}
|
|
@@ -176,11 +216,11 @@ var Pair = class {
|
|
|
176
216
|
return this.tokenAmounts[1];
|
|
177
217
|
}
|
|
178
218
|
reserveOf(token) {
|
|
179
|
-
|
|
219
|
+
invariant4(this.involvesToken(token), "TOKEN");
|
|
180
220
|
return token.equals(this.token0) ? this.reserve0 : this.reserve1;
|
|
181
221
|
}
|
|
182
222
|
getOutputAmount(inputAmount) {
|
|
183
|
-
|
|
223
|
+
invariant4(this.involvesToken(inputAmount.currency), "TOKEN");
|
|
184
224
|
if (JSBI.equal(this.reserve0.quotient, ZERO) || JSBI.equal(this.reserve1.quotient, ZERO)) {
|
|
185
225
|
throw new InsufficientReservesError();
|
|
186
226
|
}
|
|
@@ -189,14 +229,17 @@ var Pair = class {
|
|
|
189
229
|
const inputAmountWithFee = JSBI.multiply(inputAmount.quotient, _9975);
|
|
190
230
|
const numerator = JSBI.multiply(inputAmountWithFee, outputReserve.quotient);
|
|
191
231
|
const denominator = JSBI.add(JSBI.multiply(inputReserve.quotient, _10000), inputAmountWithFee);
|
|
192
|
-
const outputAmount = CurrencyAmount.fromRawAmount(
|
|
232
|
+
const outputAmount = CurrencyAmount.fromRawAmount(
|
|
233
|
+
inputAmount.currency.equals(this.token0) ? this.token1 : this.token0,
|
|
234
|
+
JSBI.divide(numerator, denominator)
|
|
235
|
+
);
|
|
193
236
|
if (JSBI.equal(outputAmount.quotient, ZERO)) {
|
|
194
237
|
throw new InsufficientInputAmountError();
|
|
195
238
|
}
|
|
196
239
|
return [outputAmount, new Pair(inputReserve.add(inputAmount), outputReserve.subtract(outputAmount))];
|
|
197
240
|
}
|
|
198
241
|
getInputAmount(outputAmount) {
|
|
199
|
-
|
|
242
|
+
invariant4(this.involvesToken(outputAmount.currency), "TOKEN");
|
|
200
243
|
if (JSBI.equal(this.reserve0.quotient, ZERO) || JSBI.equal(this.reserve1.quotient, ZERO) || JSBI.greaterThanOrEqual(outputAmount.quotient, this.reserveOf(outputAmount.currency).quotient)) {
|
|
201
244
|
throw new InsufficientReservesError();
|
|
202
245
|
}
|
|
@@ -204,16 +247,22 @@ var Pair = class {
|
|
|
204
247
|
const inputReserve = this.reserveOf(outputAmount.currency.equals(this.token0) ? this.token1 : this.token0);
|
|
205
248
|
const numerator = JSBI.multiply(JSBI.multiply(inputReserve.quotient, outputAmount.quotient), _10000);
|
|
206
249
|
const denominator = JSBI.multiply(JSBI.subtract(outputReserve.quotient, outputAmount.quotient), _9975);
|
|
207
|
-
const inputAmount = CurrencyAmount.fromRawAmount(
|
|
250
|
+
const inputAmount = CurrencyAmount.fromRawAmount(
|
|
251
|
+
outputAmount.currency.equals(this.token0) ? this.token1 : this.token0,
|
|
252
|
+
JSBI.add(JSBI.divide(numerator, denominator), ONE)
|
|
253
|
+
);
|
|
208
254
|
return [inputAmount, new Pair(inputReserve.add(inputAmount), outputReserve.subtract(outputAmount))];
|
|
209
255
|
}
|
|
210
256
|
getLiquidityMinted(totalSupply, tokenAmountA, tokenAmountB) {
|
|
211
|
-
|
|
257
|
+
invariant4(totalSupply.currency.equals(this.liquidityToken), "LIQUIDITY");
|
|
212
258
|
const tokenAmounts = tokenAmountA.currency.sortsBefore(tokenAmountB.currency) ? [tokenAmountA, tokenAmountB] : [tokenAmountB, tokenAmountA];
|
|
213
|
-
|
|
259
|
+
invariant4(tokenAmounts[0].currency.equals(this.token0) && tokenAmounts[1].currency.equals(this.token1), "TOKEN");
|
|
214
260
|
let liquidity;
|
|
215
261
|
if (JSBI.equal(totalSupply.quotient, ZERO)) {
|
|
216
|
-
liquidity = JSBI.subtract(
|
|
262
|
+
liquidity = JSBI.subtract(
|
|
263
|
+
sqrt(JSBI.multiply(tokenAmounts[0].quotient, tokenAmounts[1].quotient)),
|
|
264
|
+
MINIMUM_LIQUIDITY
|
|
265
|
+
);
|
|
217
266
|
} else {
|
|
218
267
|
const amount0 = JSBI.divide(JSBI.multiply(tokenAmounts[0].quotient, totalSupply.quotient), this.reserve0.quotient);
|
|
219
268
|
const amount1 = JSBI.divide(JSBI.multiply(tokenAmounts[1].quotient, totalSupply.quotient), this.reserve1.quotient);
|
|
@@ -225,15 +274,15 @@ var Pair = class {
|
|
|
225
274
|
return CurrencyAmount.fromRawAmount(this.liquidityToken, liquidity);
|
|
226
275
|
}
|
|
227
276
|
getLiquidityValue(token, totalSupply, liquidity, feeOn = false, kLast) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
277
|
+
invariant4(this.involvesToken(token), "TOKEN");
|
|
278
|
+
invariant4(totalSupply.currency.equals(this.liquidityToken), "TOTAL_SUPPLY");
|
|
279
|
+
invariant4(liquidity.currency.equals(this.liquidityToken), "LIQUIDITY");
|
|
280
|
+
invariant4(JSBI.lessThanOrEqual(liquidity.quotient, totalSupply.quotient), "LIQUIDITY");
|
|
232
281
|
let totalSupplyAdjusted;
|
|
233
282
|
if (!feeOn) {
|
|
234
283
|
totalSupplyAdjusted = totalSupply;
|
|
235
284
|
} else {
|
|
236
|
-
|
|
285
|
+
invariant4(!!kLast, "K_LAST");
|
|
237
286
|
const kLastParsed = JSBI.BigInt(kLast);
|
|
238
287
|
if (!JSBI.equal(kLastParsed, ZERO)) {
|
|
239
288
|
const rootK = sqrt(JSBI.multiply(this.reserve0.quotient, this.reserve1.quotient));
|
|
@@ -250,26 +299,28 @@ var Pair = class {
|
|
|
250
299
|
totalSupplyAdjusted = totalSupply;
|
|
251
300
|
}
|
|
252
301
|
}
|
|
253
|
-
return CurrencyAmount.fromRawAmount(
|
|
302
|
+
return CurrencyAmount.fromRawAmount(
|
|
303
|
+
token,
|
|
304
|
+
JSBI.divide(JSBI.multiply(liquidity.quotient, this.reserveOf(token).quotient), totalSupplyAdjusted.quotient)
|
|
305
|
+
);
|
|
254
306
|
}
|
|
255
307
|
};
|
|
256
|
-
|
|
257
|
-
// src/entities/route.ts
|
|
258
|
-
import invariant3 from "tiny-invariant";
|
|
259
|
-
import { Price as Price2 } from "@pancakeswap/swap-sdk-core";
|
|
260
308
|
var Route = class {
|
|
261
309
|
constructor(pairs, input, output) {
|
|
262
310
|
this._midPrice = null;
|
|
263
|
-
|
|
311
|
+
invariant4(pairs.length > 0, "PAIRS");
|
|
264
312
|
const chainId = pairs[0].chainId;
|
|
265
|
-
|
|
313
|
+
invariant4(
|
|
314
|
+
pairs.every((pair) => pair.chainId === chainId),
|
|
315
|
+
"CHAIN_IDS"
|
|
316
|
+
);
|
|
266
317
|
const wrappedInput = input.wrapped;
|
|
267
|
-
|
|
268
|
-
|
|
318
|
+
invariant4(pairs[0].involvesToken(wrappedInput), "INPUT");
|
|
319
|
+
invariant4(typeof output === "undefined" || pairs[pairs.length - 1].involvesToken(output.wrapped), "OUTPUT");
|
|
269
320
|
const path = [wrappedInput];
|
|
270
321
|
for (const [i, pair] of pairs.entries()) {
|
|
271
322
|
const currentInput = path[i];
|
|
272
|
-
|
|
323
|
+
invariant4(currentInput.equals(pair.token0) || currentInput.equals(pair.token1), "PATH");
|
|
273
324
|
const output2 = currentInput.equals(pair.token0) ? pair.token1 : pair.token0;
|
|
274
325
|
path.push(output2);
|
|
275
326
|
}
|
|
@@ -283,28 +334,17 @@ var Route = class {
|
|
|
283
334
|
return this._midPrice;
|
|
284
335
|
const prices = [];
|
|
285
336
|
for (const [i, pair] of this.pairs.entries()) {
|
|
286
|
-
prices.push(
|
|
337
|
+
prices.push(
|
|
338
|
+
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)
|
|
339
|
+
);
|
|
287
340
|
}
|
|
288
341
|
const reduced = prices.slice(1).reduce((accumulator, currentValue) => accumulator.multiply(currentValue), prices[0]);
|
|
289
|
-
return this._midPrice = new
|
|
342
|
+
return this._midPrice = new Price(this.input, this.output, reduced.denominator, reduced.numerator);
|
|
290
343
|
}
|
|
291
344
|
get chainId() {
|
|
292
345
|
return this.pairs[0].chainId;
|
|
293
346
|
}
|
|
294
347
|
};
|
|
295
|
-
|
|
296
|
-
// src/entities/trade.ts
|
|
297
|
-
import invariant4 from "tiny-invariant";
|
|
298
|
-
import {
|
|
299
|
-
ONE as ONE2,
|
|
300
|
-
TradeType,
|
|
301
|
-
ZERO as ZERO2,
|
|
302
|
-
CurrencyAmount as CurrencyAmount2,
|
|
303
|
-
Fraction,
|
|
304
|
-
Price as Price3,
|
|
305
|
-
sortedInsert,
|
|
306
|
-
computePriceImpact
|
|
307
|
-
} from "@pancakeswap/swap-sdk-core";
|
|
308
348
|
function inputOutputComparator(a, b) {
|
|
309
349
|
invariant4(a.inputAmount.currency.equals(b.inputAmount.currency), "INPUT_CURRENCY");
|
|
310
350
|
invariant4(a.outputAmount.currency.equals(b.outputAmount.currency), "OUTPUT_CURRENCY");
|
|
@@ -336,9 +376,19 @@ function tradeComparator(a, b) {
|
|
|
336
376
|
return a.route.path.length - b.route.path.length;
|
|
337
377
|
}
|
|
338
378
|
var Trade = class {
|
|
379
|
+
/**
|
|
380
|
+
* Constructs an exact in trade with the given amount in and route
|
|
381
|
+
* @param route route of the exact in trade
|
|
382
|
+
* @param amountIn the amount being passed in
|
|
383
|
+
*/
|
|
339
384
|
static exactIn(route, amountIn) {
|
|
340
385
|
return new Trade(route, amountIn, TradeType.EXACT_INPUT);
|
|
341
386
|
}
|
|
387
|
+
/**
|
|
388
|
+
* Constructs an exact out trade with the given amount out and route
|
|
389
|
+
* @param route route of the exact out trade
|
|
390
|
+
* @param amountOut the amount returned by the trade
|
|
391
|
+
*/
|
|
342
392
|
static exactOut(route, amountOut) {
|
|
343
393
|
return new Trade(route, amountOut, TradeType.EXACT_OUTPUT);
|
|
344
394
|
}
|
|
@@ -354,8 +404,12 @@ var Trade = class {
|
|
|
354
404
|
const [outputAmount] = pair.getOutputAmount(tokenAmounts[i]);
|
|
355
405
|
tokenAmounts[i + 1] = outputAmount;
|
|
356
406
|
}
|
|
357
|
-
this.inputAmount =
|
|
358
|
-
this.outputAmount =
|
|
407
|
+
this.inputAmount = CurrencyAmount.fromFractionalAmount(route.input, amount.numerator, amount.denominator);
|
|
408
|
+
this.outputAmount = CurrencyAmount.fromFractionalAmount(
|
|
409
|
+
route.output,
|
|
410
|
+
tokenAmounts[tokenAmounts.length - 1].numerator,
|
|
411
|
+
tokenAmounts[tokenAmounts.length - 1].denominator
|
|
412
|
+
);
|
|
359
413
|
} else {
|
|
360
414
|
invariant4(amount.currency.equals(route.output), "OUTPUT");
|
|
361
415
|
tokenAmounts[tokenAmounts.length - 1] = amount.wrapped;
|
|
@@ -364,28 +418,59 @@ var Trade = class {
|
|
|
364
418
|
const [inputAmount] = pair.getInputAmount(tokenAmounts[i]);
|
|
365
419
|
tokenAmounts[i - 1] = inputAmount;
|
|
366
420
|
}
|
|
367
|
-
this.inputAmount =
|
|
368
|
-
|
|
421
|
+
this.inputAmount = CurrencyAmount.fromFractionalAmount(
|
|
422
|
+
route.input,
|
|
423
|
+
tokenAmounts[0].numerator,
|
|
424
|
+
tokenAmounts[0].denominator
|
|
425
|
+
);
|
|
426
|
+
this.outputAmount = CurrencyAmount.fromFractionalAmount(route.output, amount.numerator, amount.denominator);
|
|
369
427
|
}
|
|
370
|
-
this.executionPrice = new
|
|
428
|
+
this.executionPrice = new Price(
|
|
429
|
+
this.inputAmount.currency,
|
|
430
|
+
this.outputAmount.currency,
|
|
431
|
+
this.inputAmount.quotient,
|
|
432
|
+
this.outputAmount.quotient
|
|
433
|
+
);
|
|
371
434
|
this.priceImpact = computePriceImpact(route.midPrice, this.inputAmount, this.outputAmount);
|
|
372
435
|
}
|
|
436
|
+
/**
|
|
437
|
+
* Get the minimum amount that must be received from this trade for the given slippage tolerance
|
|
438
|
+
* @param slippageTolerance tolerance of unfavorable slippage from the execution price of this trade
|
|
439
|
+
*/
|
|
373
440
|
minimumAmountOut(slippageTolerance) {
|
|
374
|
-
invariant4(!slippageTolerance.lessThan(
|
|
441
|
+
invariant4(!slippageTolerance.lessThan(ZERO), "SLIPPAGE_TOLERANCE");
|
|
375
442
|
if (this.tradeType === TradeType.EXACT_OUTPUT) {
|
|
376
443
|
return this.outputAmount;
|
|
377
444
|
}
|
|
378
|
-
const slippageAdjustedAmountOut = new Fraction(
|
|
379
|
-
return
|
|
445
|
+
const slippageAdjustedAmountOut = new Fraction(ONE).add(slippageTolerance).invert().multiply(this.outputAmount.quotient).quotient;
|
|
446
|
+
return CurrencyAmount.fromRawAmount(this.outputAmount.currency, slippageAdjustedAmountOut);
|
|
380
447
|
}
|
|
448
|
+
/**
|
|
449
|
+
* Get the maximum amount in that can be spent via this trade for the given slippage tolerance
|
|
450
|
+
* @param slippageTolerance tolerance of unfavorable slippage from the execution price of this trade
|
|
451
|
+
*/
|
|
381
452
|
maximumAmountIn(slippageTolerance) {
|
|
382
|
-
invariant4(!slippageTolerance.lessThan(
|
|
453
|
+
invariant4(!slippageTolerance.lessThan(ZERO), "SLIPPAGE_TOLERANCE");
|
|
383
454
|
if (this.tradeType === TradeType.EXACT_INPUT) {
|
|
384
455
|
return this.inputAmount;
|
|
385
456
|
}
|
|
386
|
-
const slippageAdjustedAmountIn = new Fraction(
|
|
387
|
-
return
|
|
388
|
-
}
|
|
457
|
+
const slippageAdjustedAmountIn = new Fraction(ONE).add(slippageTolerance).multiply(this.inputAmount.quotient).quotient;
|
|
458
|
+
return CurrencyAmount.fromRawAmount(this.inputAmount.currency, slippageAdjustedAmountIn);
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Given a list of pairs, and a fixed amount in, returns the top `maxNumResults` trades that go from an input token
|
|
462
|
+
* amount to an output token, making at most `maxHops` hops.
|
|
463
|
+
* Note this does not consider aggregation, as routes are linear. It's possible a better route exists by splitting
|
|
464
|
+
* the amount in among multiple routes.
|
|
465
|
+
* @param pairs the pairs to consider in finding the best trade
|
|
466
|
+
* @param nextAmountIn exact amount of input currency to spend
|
|
467
|
+
* @param currencyOut the desired currency out
|
|
468
|
+
* @param maxNumResults maximum number of results to return
|
|
469
|
+
* @param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pair
|
|
470
|
+
* @param currentPairs used in recursion; the current list of pairs
|
|
471
|
+
* @param currencyAmountIn used in recursion; the original value of the currencyAmountIn parameter
|
|
472
|
+
* @param bestTrades used in recursion; the current list of best trades
|
|
473
|
+
*/
|
|
389
474
|
static bestTradeExactIn(pairs, currencyAmountIn, currencyOut, { maxNumResults = 3, maxHops = 3 } = {}, currentPairs = [], nextAmountIn = currencyAmountIn, bestTrades = []) {
|
|
390
475
|
invariant4(pairs.length > 0, "PAIRS");
|
|
391
476
|
invariant4(maxHops > 0, "MAX_HOPS");
|
|
@@ -396,7 +481,7 @@ var Trade = class {
|
|
|
396
481
|
const pair = pairs[i];
|
|
397
482
|
if (!pair.token0.equals(amountIn.currency) && !pair.token1.equals(amountIn.currency))
|
|
398
483
|
continue;
|
|
399
|
-
if (pair.reserve0.equalTo(
|
|
484
|
+
if (pair.reserve0.equalTo(ZERO) || pair.reserve1.equalTo(ZERO))
|
|
400
485
|
continue;
|
|
401
486
|
let amountOut;
|
|
402
487
|
try {
|
|
@@ -409,20 +494,61 @@ var Trade = class {
|
|
|
409
494
|
throw error;
|
|
410
495
|
}
|
|
411
496
|
if (amountOut.currency.equals(tokenOut)) {
|
|
412
|
-
sortedInsert(
|
|
497
|
+
sortedInsert(
|
|
498
|
+
bestTrades,
|
|
499
|
+
new Trade(
|
|
500
|
+
new Route([...currentPairs, pair], currencyAmountIn.currency, currencyOut),
|
|
501
|
+
currencyAmountIn,
|
|
502
|
+
TradeType.EXACT_INPUT
|
|
503
|
+
),
|
|
504
|
+
maxNumResults,
|
|
505
|
+
tradeComparator
|
|
506
|
+
);
|
|
413
507
|
} else if (maxHops > 1 && pairs.length > 1) {
|
|
414
508
|
const pairsExcludingThisPair = pairs.slice(0, i).concat(pairs.slice(i + 1, pairs.length));
|
|
415
|
-
Trade.bestTradeExactIn(
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
509
|
+
Trade.bestTradeExactIn(
|
|
510
|
+
pairsExcludingThisPair,
|
|
511
|
+
currencyAmountIn,
|
|
512
|
+
currencyOut,
|
|
513
|
+
{
|
|
514
|
+
maxNumResults,
|
|
515
|
+
maxHops: maxHops - 1
|
|
516
|
+
},
|
|
517
|
+
[...currentPairs, pair],
|
|
518
|
+
amountOut,
|
|
519
|
+
bestTrades
|
|
520
|
+
);
|
|
419
521
|
}
|
|
420
522
|
}
|
|
421
523
|
return bestTrades;
|
|
422
524
|
}
|
|
525
|
+
/**
|
|
526
|
+
* Return the execution price after accounting for slippage tolerance
|
|
527
|
+
* @param slippageTolerance the allowed tolerated slippage
|
|
528
|
+
*/
|
|
423
529
|
worstExecutionPrice(slippageTolerance) {
|
|
424
|
-
return new
|
|
425
|
-
|
|
530
|
+
return new Price(
|
|
531
|
+
this.inputAmount.currency,
|
|
532
|
+
this.outputAmount.currency,
|
|
533
|
+
this.maximumAmountIn(slippageTolerance).quotient,
|
|
534
|
+
this.minimumAmountOut(slippageTolerance).quotient
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* similar to the above method but instead targets a fixed output amount
|
|
539
|
+
* given a list of pairs, and a fixed amount out, returns the top `maxNumResults` trades that go from an input token
|
|
540
|
+
* to an output token amount, making at most `maxHops` hops
|
|
541
|
+
* note this does not consider aggregation, as routes are linear. it's possible a better route exists by splitting
|
|
542
|
+
* the amount in among multiple routes.
|
|
543
|
+
* @param pairs the pairs to consider in finding the best trade
|
|
544
|
+
* @param currencyIn the currency to spend
|
|
545
|
+
* @param nextAmountOut the exact amount of currency out
|
|
546
|
+
* @param maxNumResults maximum number of results to return
|
|
547
|
+
* @param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pair
|
|
548
|
+
* @param currentPairs used in recursion; the current list of pairs
|
|
549
|
+
* @param currencyAmountOut used in recursion; the original value of the currencyAmountOut parameter
|
|
550
|
+
* @param bestTrades used in recursion; the current list of best trades
|
|
551
|
+
*/
|
|
426
552
|
static bestTradeExactOut(pairs, currencyIn, currencyAmountOut, { maxNumResults = 3, maxHops = 3 } = {}, currentPairs = [], nextAmountOut = currencyAmountOut, bestTrades = []) {
|
|
427
553
|
invariant4(pairs.length > 0, "PAIRS");
|
|
428
554
|
invariant4(maxHops > 0, "MAX_HOPS");
|
|
@@ -433,7 +559,7 @@ var Trade = class {
|
|
|
433
559
|
const pair = pairs[i];
|
|
434
560
|
if (!pair.token0.equals(amountOut.currency) && !pair.token1.equals(amountOut.currency))
|
|
435
561
|
continue;
|
|
436
|
-
if (pair.reserve0.equalTo(
|
|
562
|
+
if (pair.reserve0.equalTo(ZERO) || pair.reserve1.equalTo(ZERO))
|
|
437
563
|
continue;
|
|
438
564
|
let amountIn;
|
|
439
565
|
try {
|
|
@@ -446,22 +572,35 @@ var Trade = class {
|
|
|
446
572
|
throw error;
|
|
447
573
|
}
|
|
448
574
|
if (amountIn.currency.equals(tokenIn)) {
|
|
449
|
-
sortedInsert(
|
|
575
|
+
sortedInsert(
|
|
576
|
+
bestTrades,
|
|
577
|
+
new Trade(
|
|
578
|
+
new Route([pair, ...currentPairs], currencyIn, currencyAmountOut.currency),
|
|
579
|
+
currencyAmountOut,
|
|
580
|
+
TradeType.EXACT_OUTPUT
|
|
581
|
+
),
|
|
582
|
+
maxNumResults,
|
|
583
|
+
tradeComparator
|
|
584
|
+
);
|
|
450
585
|
} else if (maxHops > 1 && pairs.length > 1) {
|
|
451
586
|
const pairsExcludingThisPair = pairs.slice(0, i).concat(pairs.slice(i + 1, pairs.length));
|
|
452
|
-
Trade.bestTradeExactOut(
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
587
|
+
Trade.bestTradeExactOut(
|
|
588
|
+
pairsExcludingThisPair,
|
|
589
|
+
currencyIn,
|
|
590
|
+
currencyAmountOut,
|
|
591
|
+
{
|
|
592
|
+
maxNumResults,
|
|
593
|
+
maxHops: maxHops - 1
|
|
594
|
+
},
|
|
595
|
+
[pair, ...currentPairs],
|
|
596
|
+
amountIn,
|
|
597
|
+
bestTrades
|
|
598
|
+
);
|
|
456
599
|
}
|
|
457
600
|
}
|
|
458
601
|
return bestTrades;
|
|
459
602
|
}
|
|
460
603
|
};
|
|
461
|
-
|
|
462
|
-
// src/entities/native.ts
|
|
463
|
-
import invariant5 from "tiny-invariant";
|
|
464
|
-
import { NativeCurrency } from "@pancakeswap/swap-sdk-core";
|
|
465
604
|
var _Native = class extends NativeCurrency {
|
|
466
605
|
constructor({
|
|
467
606
|
chainId,
|
|
@@ -473,14 +612,14 @@ var _Native = class extends NativeCurrency {
|
|
|
473
612
|
}
|
|
474
613
|
get wrapped() {
|
|
475
614
|
const wnative = WNATIVE[this.chainId];
|
|
476
|
-
|
|
615
|
+
invariant4(!!wnative, "WRAPPED");
|
|
477
616
|
return wnative;
|
|
478
617
|
}
|
|
479
618
|
static onChain(chainId) {
|
|
480
619
|
if (chainId in this.cache) {
|
|
481
620
|
return this.cache[chainId];
|
|
482
621
|
}
|
|
483
|
-
|
|
622
|
+
invariant4(!!NATIVE[chainId], "NATIVE_CURRENCY");
|
|
484
623
|
const { decimals, name, symbol } = NATIVE[chainId];
|
|
485
624
|
return this.cache[chainId] = new _Native({ chainId, decimals, symbol, name });
|
|
486
625
|
}
|
|
@@ -490,33 +629,32 @@ var _Native = class extends NativeCurrency {
|
|
|
490
629
|
};
|
|
491
630
|
var Native = _Native;
|
|
492
631
|
Native.cache = {};
|
|
493
|
-
|
|
494
|
-
// src/router.ts
|
|
495
|
-
import { TradeType as TradeType2 } from "@pancakeswap/swap-sdk-core";
|
|
496
|
-
import invariant6 from "tiny-invariant";
|
|
497
632
|
function toHex(currencyAmount) {
|
|
498
633
|
return `0x${currencyAmount.quotient.toString(16)}`;
|
|
499
634
|
}
|
|
500
635
|
var ZERO_HEX = "0x0";
|
|
501
636
|
var Router = class {
|
|
502
|
-
|
|
503
|
-
|
|
637
|
+
/**
|
|
638
|
+
* Produces the on-chain method name to call and the hex encoded parameters to pass as arguments for a given trade.
|
|
639
|
+
* @param trade to produce call parameters for
|
|
640
|
+
* @param options options for the call parameters
|
|
641
|
+
*/
|
|
504
642
|
static swapCallParameters(trade, options) {
|
|
505
643
|
const etherIn = trade.inputAmount.currency.isNative;
|
|
506
644
|
const etherOut = trade.outputAmount.currency.isNative;
|
|
507
|
-
|
|
508
|
-
|
|
645
|
+
invariant4(!(etherIn && etherOut), "ETHER_IN_OUT");
|
|
646
|
+
invariant4(!("ttl" in options) || options.ttl > 0, "TTL");
|
|
509
647
|
const to = validateAndParseAddress(options.recipient);
|
|
510
648
|
const amountIn = toHex(trade.maximumAmountIn(options.allowedSlippage));
|
|
511
649
|
const amountOut = toHex(trade.minimumAmountOut(options.allowedSlippage));
|
|
512
650
|
const path = trade.route.path.map((token) => token.address);
|
|
513
|
-
const deadline = "ttl" in options ? `0x${(Math.floor(new Date().getTime() / 1e3) + options.ttl).toString(16)}` : `0x${options.deadline.toString(16)}`;
|
|
651
|
+
const deadline = "ttl" in options ? `0x${(Math.floor(( new Date()).getTime() / 1e3) + options.ttl).toString(16)}` : `0x${options.deadline.toString(16)}`;
|
|
514
652
|
const useFeeOnTransfer = Boolean(options.feeOnTransfer);
|
|
515
653
|
let methodName;
|
|
516
654
|
let args;
|
|
517
655
|
let value;
|
|
518
656
|
switch (trade.tradeType) {
|
|
519
|
-
case
|
|
657
|
+
case TradeType.EXACT_INPUT:
|
|
520
658
|
if (etherIn) {
|
|
521
659
|
methodName = useFeeOnTransfer ? "swapExactETHForTokensSupportingFeeOnTransferTokens" : "swapExactETHForTokens";
|
|
522
660
|
args = [amountOut, path, to, deadline];
|
|
@@ -531,8 +669,8 @@ var Router = class {
|
|
|
531
669
|
value = ZERO_HEX;
|
|
532
670
|
}
|
|
533
671
|
break;
|
|
534
|
-
case
|
|
535
|
-
|
|
672
|
+
case TradeType.EXACT_OUTPUT:
|
|
673
|
+
invariant4(!useFeeOnTransfer, "EXACT_OUT_FOT");
|
|
536
674
|
if (etherIn) {
|
|
537
675
|
methodName = "swapETHForExactTokens";
|
|
538
676
|
args = [amountOut, path, to, deadline];
|
|
@@ -555,30 +693,26 @@ var Router = class {
|
|
|
555
693
|
};
|
|
556
694
|
}
|
|
557
695
|
};
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
WBNB,
|
|
577
|
-
WETH9,
|
|
578
|
-
WNATIVE,
|
|
579
|
-
ZERO_PERCENT,
|
|
580
|
-
computePairAddress,
|
|
581
|
-
inputOutputComparator,
|
|
582
|
-
isTradeBetter,
|
|
583
|
-
tradeComparator
|
|
696
|
+
var _Ether = class extends NativeCurrency {
|
|
697
|
+
constructor(chainId) {
|
|
698
|
+
super(chainId, 18, "ETH", "Ether");
|
|
699
|
+
}
|
|
700
|
+
get wrapped() {
|
|
701
|
+
const weth9 = WETH9[this.chainId];
|
|
702
|
+
invariant4(!!weth9, "WRAPPED");
|
|
703
|
+
return weth9;
|
|
704
|
+
}
|
|
705
|
+
static onChain(chainId) {
|
|
706
|
+
if (!this._etherCache[chainId]) {
|
|
707
|
+
this._etherCache[chainId] = new _Ether(chainId);
|
|
708
|
+
}
|
|
709
|
+
return this._etherCache[chainId];
|
|
710
|
+
}
|
|
711
|
+
equals(other) {
|
|
712
|
+
return other.isNative && other.chainId === this.chainId;
|
|
713
|
+
}
|
|
584
714
|
};
|
|
715
|
+
var Ether = _Ether;
|
|
716
|
+
Ether._etherCache = {};
|
|
717
|
+
|
|
718
|
+
export { ChainId, ERC20Token, Ether, FACTORY_ADDRESS, FACTORY_ADDRESS_MAP, INIT_CODE_HASH, INIT_CODE_HASH_MAP, NATIVE, Native, ONE_HUNDRED_PERCENT, Pair, Route, Router, Trade, WBNB, WETH9, WNATIVE, ZERO_PERCENT, computePairAddress, inputOutputComparator, isTradeBetter, tradeComparator, validateAndParseAddress };
|