@pancakeswap/v3-sdk 2.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abi/MasterChefV3.d.ts +1222 -0
- package/dist/abi/MasterChefV3.d.ts.map +1 -0
- package/dist/abi/NonfungiblePositionManager.d.ts +962 -0
- package/dist/abi/NonfungiblePositionManager.d.ts.map +1 -0
- package/dist/abi/PeripheryPaymentsWithFee.d.ts +88 -0
- package/dist/abi/PeripheryPaymentsWithFee.d.ts.map +1 -0
- package/dist/abi/Quoter.d.ts +162 -0
- package/dist/abi/Quoter.d.ts.map +1 -0
- package/dist/abi/QuoterV2.d.ts +220 -0
- package/dist/abi/QuoterV2.d.ts.map +1 -0
- package/dist/abi/SelfPermit.d.ts +122 -0
- package/dist/abi/SelfPermit.d.ts.map +1 -0
- package/dist/abi/SwapRouter.d.ts +453 -0
- package/dist/abi/SwapRouter.d.ts.map +1 -0
- package/dist/abi/V3Staker.d.ts +547 -0
- package/dist/abi/V3Staker.d.ts.map +1 -0
- package/dist/constants.d.ts +36 -3
- package/dist/constants.d.ts.map +1 -1
- package/dist/entities/pool.d.ts +2 -1
- package/dist/entities/pool.d.ts.map +1 -1
- package/dist/entities/tick.d.ts.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1528 -1376
- package/dist/index.mjs +1516 -1371
- package/dist/masterchefV3.d.ts +1228 -9
- package/dist/masterchefV3.d.ts.map +1 -1
- package/dist/multicall.d.ts +16 -3
- package/dist/multicall.d.ts.map +1 -1
- package/dist/nonfungiblePositionManager.d.ts +976 -10
- package/dist/nonfungiblePositionManager.d.ts.map +1 -1
- package/dist/payments.d.ts +95 -6
- package/dist/payments.d.ts.map +1 -1
- package/dist/quoter.d.ts +385 -4
- package/dist/quoter.d.ts.map +1 -1
- package/dist/selfPermit.d.ts +128 -8
- package/dist/selfPermit.d.ts.map +1 -1
- package/dist/staker.d.ts +549 -3
- package/dist/staker.d.ts.map +1 -1
- package/dist/swapRouter.d.ts +452 -2
- package/dist/swapRouter.d.ts.map +1 -1
- package/dist/utils/calldata.d.ts +4 -3
- package/dist/utils/calldata.d.ts.map +1 -1
- package/dist/utils/computePoolAddress.d.ts +4 -3
- package/dist/utils/computePoolAddress.d.ts.map +1 -1
- package/dist/utils/encodeRouteToPath.d.ts +3 -2
- package/dist/utils/encodeRouteToPath.d.ts.map +1 -1
- package/dist/utils/encodeSqrtRatioX96.d.ts +1 -1
- package/dist/utils/encodeSqrtRatioX96.d.ts.map +1 -1
- package/dist/utils/feeCalculator.d.ts +5 -5
- package/dist/utils/feeCalculator.d.ts.map +1 -1
- package/dist/utils/parseProtocolFees.d.ts +1 -1
- package/dist/utils/parseProtocolFees.d.ts.map +1 -1
- package/dist/utils/positionMath.d.ts.map +1 -1
- package/dist/utils/priceTickConversions.d.ts +1 -1
- package/dist/utils/priceTickConversions.d.ts.map +1 -1
- package/package.json +6 -15
package/dist/index.mjs
CHANGED
|
@@ -1,21 +1,55 @@
|
|
|
1
|
-
import { ChainId,
|
|
2
|
-
import
|
|
3
|
-
import { Percent, Price as Price$1, Fraction as Fraction$1 } from '@pancakeswap/swap-sdk-core';
|
|
4
|
-
import {
|
|
5
|
-
import { getCreate2Address } from '@ethersproject/address';
|
|
6
|
-
import { keccak256, pack } from '@ethersproject/solidity';
|
|
1
|
+
import { ChainId, Price, CurrencyAmount, Percent as Percent$1, MaxUint256 as MaxUint256$1, TradeType, Fraction, sortedInsert, validateAndParseAddress, ZERO as ZERO$2, ONE as ONE$1 } from '@pancakeswap/sdk';
|
|
2
|
+
import invariant9 from 'tiny-invariant';
|
|
3
|
+
import { Percent, MaxUint256, sqrt, Price as Price$1, CurrencyAmount as CurrencyAmount$1, Fraction as Fraction$1, ZERO as ZERO$1, TradeType as TradeType$1 } from '@pancakeswap/swap-sdk-core';
|
|
4
|
+
import { keccak256, encodeAbiParameters, parseAbiParameters, encodePacked, encodeFunctionData, toBytes, getAddress, pad, isBytes, slice, concat } from 'viem';
|
|
7
5
|
|
|
8
6
|
// src/entities/pool.ts
|
|
9
7
|
var FACTORY_ADDRESS = "0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865";
|
|
8
|
+
var FACTORY_ADDRESSES = {
|
|
9
|
+
[ChainId.ETHEREUM]: FACTORY_ADDRESS,
|
|
10
|
+
[ChainId.GOERLI]: FACTORY_ADDRESS,
|
|
11
|
+
[ChainId.BSC]: FACTORY_ADDRESS,
|
|
12
|
+
[ChainId.BSC_TESTNET]: FACTORY_ADDRESS,
|
|
13
|
+
// TODO: new chains
|
|
14
|
+
[ChainId.ARBITRUM_ONE]: FACTORY_ADDRESS,
|
|
15
|
+
[ChainId.ARBITRUM_GOERLI]: "0xBA40c83026213F9cbc79998752721a0312bdB74a",
|
|
16
|
+
[ChainId.POLYGON_ZKEVM]: FACTORY_ADDRESS,
|
|
17
|
+
[ChainId.POLYGON_ZKEVM_TESTNET]: "0x2430dbd123BC40f8Be6110065a448C1aA0619Cb1",
|
|
18
|
+
[ChainId.ZKSYNC]: "0x",
|
|
19
|
+
[ChainId.ZKSYNC_TESTNET]: "0x57d01Fbde077C04381a28840A24aCbEeF8314062",
|
|
20
|
+
[ChainId.LINEA_TESTNET]: "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E"
|
|
21
|
+
};
|
|
10
22
|
var DEPLOYER_ADDRESS = "0x41ff9AA7e16B8B1a8a8dc4f0eFacd93D02d071c9";
|
|
11
23
|
var DEPLOYER_ADDRESSES = {
|
|
12
24
|
[ChainId.ETHEREUM]: DEPLOYER_ADDRESS,
|
|
13
25
|
[ChainId.GOERLI]: DEPLOYER_ADDRESS,
|
|
14
26
|
[ChainId.BSC]: DEPLOYER_ADDRESS,
|
|
15
|
-
[ChainId.BSC_TESTNET]: DEPLOYER_ADDRESS
|
|
27
|
+
[ChainId.BSC_TESTNET]: DEPLOYER_ADDRESS,
|
|
28
|
+
// TODO: new chains
|
|
29
|
+
[ChainId.ARBITRUM_ONE]: DEPLOYER_ADDRESS,
|
|
30
|
+
[ChainId.ARBITRUM_GOERLI]: "0xbC465fbf687e4184103b67Ed86557A8155FA4343",
|
|
31
|
+
[ChainId.POLYGON_ZKEVM]: DEPLOYER_ADDRESS,
|
|
32
|
+
[ChainId.POLYGON_ZKEVM_TESTNET]: "0x86808Be3f426C9B4c8C706bCDe29dBC036A1259B",
|
|
33
|
+
[ChainId.ZKSYNC]: "0x",
|
|
34
|
+
[ChainId.ZKSYNC_TESTNET]: "0x71df5b7ea5355180EAb2A54de8aA534016040008",
|
|
35
|
+
[ChainId.LINEA_TESTNET]: "0xdAecee3C08e953Bd5f89A5Cc90ac560413d709E3"
|
|
16
36
|
};
|
|
17
37
|
var ADDRESS_ZERO = "0x0000000000000000000000000000000000000000";
|
|
18
38
|
var POOL_INIT_CODE_HASH = "0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2";
|
|
39
|
+
var POOL_INIT_CODE_HASHES = {
|
|
40
|
+
[ChainId.ETHEREUM]: POOL_INIT_CODE_HASH,
|
|
41
|
+
[ChainId.GOERLI]: POOL_INIT_CODE_HASH,
|
|
42
|
+
[ChainId.BSC]: POOL_INIT_CODE_HASH,
|
|
43
|
+
[ChainId.BSC_TESTNET]: POOL_INIT_CODE_HASH,
|
|
44
|
+
[ChainId.ARBITRUM_ONE]: POOL_INIT_CODE_HASH,
|
|
45
|
+
[ChainId.ARBITRUM_GOERLI]: POOL_INIT_CODE_HASH,
|
|
46
|
+
[ChainId.POLYGON_ZKEVM]: POOL_INIT_CODE_HASH,
|
|
47
|
+
[ChainId.POLYGON_ZKEVM_TESTNET]: POOL_INIT_CODE_HASH,
|
|
48
|
+
// TODO: new chains
|
|
49
|
+
[ChainId.ZKSYNC]: "0x01001487f1c11a662dda518635f8e1f03a41f505cbf7d981c899ba11bf847a8a",
|
|
50
|
+
[ChainId.ZKSYNC_TESTNET]: "0x01001487f1c11a662dda518635f8e1f03a41f505cbf7d981c899ba11bf847a8a",
|
|
51
|
+
[ChainId.LINEA_TESTNET]: POOL_INIT_CODE_HASH
|
|
52
|
+
};
|
|
19
53
|
var FeeAmount = /* @__PURE__ */ ((FeeAmount4) => {
|
|
20
54
|
FeeAmount4[FeeAmount4["LOWEST"] = 100] = "LOWEST";
|
|
21
55
|
FeeAmount4[FeeAmount4["LOW"] = 500] = "LOW";
|
|
@@ -38,6 +72,20 @@ var MAX_FEE = 10n ** 6n;
|
|
|
38
72
|
var ONE_HUNDRED_PERCENT = new Percent("1");
|
|
39
73
|
var ZERO_PERCENT = new Percent("0");
|
|
40
74
|
var Q128 = 2n ** 128n;
|
|
75
|
+
function getCreate2Address(from_, salt_, initCodeHash) {
|
|
76
|
+
const from = toBytes(getAddress(from_));
|
|
77
|
+
const salt = pad(isBytes(salt_) ? salt_ : toBytes(salt_), {
|
|
78
|
+
size: 32
|
|
79
|
+
});
|
|
80
|
+
return getAddress(slice(keccak256(concat([toBytes("0xff"), from, salt, toBytes(initCodeHash)])), 12));
|
|
81
|
+
}
|
|
82
|
+
var EMPTY_INPU_HASH = "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470";
|
|
83
|
+
var ZKSYNC_PREFIX = "0x2020dba91b30cc0006188af794c2fb30dd8520db7e2c088b7fc7c103c00ca494";
|
|
84
|
+
function getCreate2AddressZkSync(from, salt, initCodeHash) {
|
|
85
|
+
return getAddress(
|
|
86
|
+
keccak256(concat([ZKSYNC_PREFIX, pad(from, { size: 32 }), salt, initCodeHash, EMPTY_INPU_HASH])).slice(26)
|
|
87
|
+
);
|
|
88
|
+
}
|
|
41
89
|
function computePoolAddress({
|
|
42
90
|
deployerAddress,
|
|
43
91
|
tokenA,
|
|
@@ -46,13 +94,20 @@ function computePoolAddress({
|
|
|
46
94
|
initCodeHashManualOverride
|
|
47
95
|
}) {
|
|
48
96
|
const [token0, token1] = tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA];
|
|
97
|
+
const salt = keccak256(
|
|
98
|
+
encodeAbiParameters(parseAbiParameters(["address, address, uint24"]), [token0.address, token1.address, fee])
|
|
99
|
+
);
|
|
100
|
+
if (token0.chainId === ChainId.ZKSYNC || token0.chainId === ChainId.ZKSYNC_TESTNET) {
|
|
101
|
+
return getCreate2AddressZkSync(
|
|
102
|
+
deployerAddress,
|
|
103
|
+
salt,
|
|
104
|
+
initCodeHashManualOverride ?? POOL_INIT_CODE_HASHES[token0.chainId]
|
|
105
|
+
);
|
|
106
|
+
}
|
|
49
107
|
return getCreate2Address(
|
|
50
108
|
deployerAddress,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
[defaultAbiCoder.encode(["address", "address", "uint24"], [token0.address, token1.address, fee])]
|
|
54
|
-
),
|
|
55
|
-
initCodeHashManualOverride ?? POOL_INIT_CODE_HASH
|
|
109
|
+
salt,
|
|
110
|
+
initCodeHashManualOverride ?? POOL_INIT_CODE_HASHES[token0.chainId]
|
|
56
111
|
);
|
|
57
112
|
}
|
|
58
113
|
|
|
@@ -118,13 +173,13 @@ var SqrtPriceMath = class {
|
|
|
118
173
|
return roundUp ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, Q96) : liquidity * (sqrtRatioBX96 - sqrtRatioAX96) / Q96;
|
|
119
174
|
}
|
|
120
175
|
static getNextSqrtPriceFromInput(sqrtPX96, liquidity, amountIn, zeroForOne) {
|
|
121
|
-
|
|
122
|
-
|
|
176
|
+
invariant9(sqrtPX96 > ZERO);
|
|
177
|
+
invariant9(liquidity > ZERO);
|
|
123
178
|
return zeroForOne ? this.getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountIn, true) : this.getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountIn, true);
|
|
124
179
|
}
|
|
125
180
|
static getNextSqrtPriceFromOutput(sqrtPX96, liquidity, amountOut, zeroForOne) {
|
|
126
|
-
|
|
127
|
-
|
|
181
|
+
invariant9(sqrtPX96 > ZERO);
|
|
182
|
+
invariant9(liquidity > ZERO);
|
|
128
183
|
return zeroForOne ? this.getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountOut, false) : this.getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountOut, false);
|
|
129
184
|
}
|
|
130
185
|
static getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amount, add) {
|
|
@@ -142,8 +197,8 @@ var SqrtPriceMath = class {
|
|
|
142
197
|
return FullMath.mulDivRoundingUp(numerator1, ONE, numerator1 / sqrtPX96 + amount);
|
|
143
198
|
}
|
|
144
199
|
const product = multiplyIn256(amount, sqrtPX96);
|
|
145
|
-
|
|
146
|
-
|
|
200
|
+
invariant9(product / amount === sqrtPX96);
|
|
201
|
+
invariant9(numerator1 > product);
|
|
147
202
|
const denominator = numerator1 - product;
|
|
148
203
|
return FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator);
|
|
149
204
|
}
|
|
@@ -153,7 +208,7 @@ var SqrtPriceMath = class {
|
|
|
153
208
|
return sqrtPX96 + quotient2;
|
|
154
209
|
}
|
|
155
210
|
const quotient = FullMath.mulDivRoundingUp(amount, Q96, liquidity);
|
|
156
|
-
|
|
211
|
+
invariant9(sqrtPX96 > quotient);
|
|
157
212
|
return sqrtPX96 - quotient;
|
|
158
213
|
}
|
|
159
214
|
};
|
|
@@ -221,8 +276,8 @@ var SwapMath = class {
|
|
|
221
276
|
var TWO = 2n;
|
|
222
277
|
var POWERS_OF_2 = [128, 64, 32, 16, 8, 4, 2, 1].map((pow) => [pow, TWO ** BigInt(pow)]);
|
|
223
278
|
function mostSignificantBit(x) {
|
|
224
|
-
|
|
225
|
-
|
|
279
|
+
invariant9(x > ZERO, "ZERO");
|
|
280
|
+
invariant9(x <= MaxUint256, "MAX");
|
|
226
281
|
let msb = 0;
|
|
227
282
|
for (const [power, min] of POWERS_OF_2) {
|
|
228
283
|
if (x >= min) {
|
|
@@ -249,7 +304,7 @@ var _TickMath = class {
|
|
|
249
304
|
* @param tick the tick for which to compute the sqrt ratio
|
|
250
305
|
*/
|
|
251
306
|
static getSqrtRatioAtTick(tick) {
|
|
252
|
-
|
|
307
|
+
invariant9(tick >= _TickMath.MIN_TICK && tick <= _TickMath.MAX_TICK && Number.isInteger(tick), "TICK");
|
|
253
308
|
const absTick = tick < 0 ? tick * -1 : tick;
|
|
254
309
|
let ratio = (absTick & 1) != 0 ? BigInt("0xfffcb933bd6fad37aa2d162d1a594001") : BigInt("0x100000000000000000000000000000000");
|
|
255
310
|
if ((absTick & 2) != 0)
|
|
@@ -300,7 +355,7 @@ var _TickMath = class {
|
|
|
300
355
|
* @param sqrtRatioX96 the sqrt ratio as a Q64.96 for which to compute the tick
|
|
301
356
|
*/
|
|
302
357
|
static getTickAtSqrtRatio(sqrtRatioX96) {
|
|
303
|
-
|
|
358
|
+
invariant9(sqrtRatioX96 >= _TickMath.MIN_SQRT_RATIO && sqrtRatioX96 < _TickMath.MAX_SQRT_RATIO, "SQRT_RATIO");
|
|
304
359
|
const sqrtRatioX128 = sqrtRatioX96 << 32n;
|
|
305
360
|
const msb = mostSignificantBit(sqrtRatioX128);
|
|
306
361
|
let r;
|
|
@@ -374,25 +429,25 @@ var TickList = class {
|
|
|
374
429
|
constructor() {
|
|
375
430
|
}
|
|
376
431
|
static validateList(ticks, tickSpacing) {
|
|
377
|
-
|
|
378
|
-
|
|
432
|
+
invariant9(tickSpacing > 0, "TICK_SPACING_NONZERO");
|
|
433
|
+
invariant9(
|
|
379
434
|
ticks.every(({ index }) => index % tickSpacing === 0),
|
|
380
435
|
"TICK_SPACING"
|
|
381
436
|
);
|
|
382
|
-
|
|
383
|
-
|
|
437
|
+
invariant9(ticks.reduce((accumulator, { liquidityNet }) => accumulator + liquidityNet, ZERO) === ZERO, "ZERO_NET");
|
|
438
|
+
invariant9(isSorted(ticks, tickComparator), "SORTED");
|
|
384
439
|
}
|
|
385
440
|
static isBelowSmallest(ticks, tick) {
|
|
386
|
-
|
|
441
|
+
invariant9(ticks.length > 0, "LENGTH");
|
|
387
442
|
return tick < ticks[0].index;
|
|
388
443
|
}
|
|
389
444
|
static isAtOrAboveLargest(ticks, tick) {
|
|
390
|
-
|
|
445
|
+
invariant9(ticks.length > 0, "LENGTH");
|
|
391
446
|
return tick >= ticks[ticks.length - 1].index;
|
|
392
447
|
}
|
|
393
448
|
static getTick(ticks, index) {
|
|
394
449
|
const tick = ticks[this.binarySearch(ticks, index)];
|
|
395
|
-
|
|
450
|
+
invariant9(tick.index === index, "NOT_CONTAINED");
|
|
396
451
|
return tick;
|
|
397
452
|
}
|
|
398
453
|
/**
|
|
@@ -402,7 +457,7 @@ var TickList = class {
|
|
|
402
457
|
* @private
|
|
403
458
|
*/
|
|
404
459
|
static binarySearch(ticks, tick) {
|
|
405
|
-
|
|
460
|
+
invariant9(!this.isBelowSmallest(ticks, tick), "BELOW_SMALLEST");
|
|
406
461
|
let l = 0;
|
|
407
462
|
let r = ticks.length - 1;
|
|
408
463
|
let i;
|
|
@@ -420,14 +475,14 @@ var TickList = class {
|
|
|
420
475
|
}
|
|
421
476
|
static nextInitializedTick(ticks, tick, lte) {
|
|
422
477
|
if (lte) {
|
|
423
|
-
|
|
478
|
+
invariant9(!TickList.isBelowSmallest(ticks, tick), "BELOW_SMALLEST");
|
|
424
479
|
if (TickList.isAtOrAboveLargest(ticks, tick)) {
|
|
425
480
|
return ticks[ticks.length - 1];
|
|
426
481
|
}
|
|
427
482
|
const index2 = this.binarySearch(ticks, tick);
|
|
428
483
|
return ticks[index2];
|
|
429
484
|
}
|
|
430
|
-
|
|
485
|
+
invariant9(!this.isAtOrAboveLargest(ticks, tick), "AT_OR_ABOVE_LARGEST");
|
|
431
486
|
if (this.isBelowSmallest(ticks, tick)) {
|
|
432
487
|
return ticks[0];
|
|
433
488
|
}
|
|
@@ -464,44 +519,219 @@ var TickList = class {
|
|
|
464
519
|
return Math.abs(beforeIndex - afterIndex);
|
|
465
520
|
}
|
|
466
521
|
};
|
|
522
|
+
var Tick = class {
|
|
523
|
+
constructor({ index, liquidityGross, liquidityNet }) {
|
|
524
|
+
invariant9(index >= TickMath.MIN_TICK && index <= TickMath.MAX_TICK, "TICK");
|
|
525
|
+
this.index = index;
|
|
526
|
+
this.liquidityGross = BigInt(liquidityGross);
|
|
527
|
+
this.liquidityNet = BigInt(liquidityNet);
|
|
528
|
+
}
|
|
529
|
+
};
|
|
467
530
|
|
|
468
|
-
// src/
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
hex = `0${hex}`;
|
|
531
|
+
// src/entities/tickListDataProvider.ts
|
|
532
|
+
var TickListDataProvider = class {
|
|
533
|
+
constructor(ticks) {
|
|
534
|
+
const ticksMapped = ticks.map((t) => t instanceof Tick ? t : new Tick(t));
|
|
535
|
+
this.ticks = ticksMapped;
|
|
474
536
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
537
|
+
async getTick(tick) {
|
|
538
|
+
return TickList.getTick(this.ticks, tick);
|
|
539
|
+
}
|
|
540
|
+
async nextInitializedTickWithinOneWord(tick, lte, tickSpacing) {
|
|
541
|
+
return TickList.nextInitializedTickWithinOneWord(this.ticks, tick, lte, tickSpacing);
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
// src/entities/pool.ts
|
|
546
|
+
var NO_TICK_DATA_PROVIDER_DEFAULT = new NoTickDataProvider();
|
|
547
|
+
var Pool = class {
|
|
548
|
+
static getAddress(tokenA, tokenB, fee, initCodeHashManualOverride, deployerAddressOverride) {
|
|
549
|
+
return computePoolAddress({
|
|
550
|
+
deployerAddress: deployerAddressOverride ?? DEPLOYER_ADDRESSES[tokenA.chainId],
|
|
551
|
+
fee,
|
|
552
|
+
tokenA,
|
|
553
|
+
tokenB,
|
|
554
|
+
initCodeHashManualOverride
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Construct a pool
|
|
559
|
+
* @param tokenA One of the tokens in the pool
|
|
560
|
+
* @param tokenB The other token in the pool
|
|
561
|
+
* @param fee The fee in hundredths of a bips of the input amount of every swap that is collected by the pool
|
|
562
|
+
* @param sqrtRatioX96 The sqrt of the current ratio of amounts of token1 to token0
|
|
563
|
+
* @param liquidity The current value of in range liquidity
|
|
564
|
+
* @param tickCurrent The current tick of the pool
|
|
565
|
+
* @param ticks The current state of the pool ticks or a data provider that can return tick data
|
|
566
|
+
*/
|
|
567
|
+
constructor(tokenA, tokenB, fee, sqrtRatioX96, liquidity, tickCurrent, ticks = NO_TICK_DATA_PROVIDER_DEFAULT) {
|
|
568
|
+
invariant9(Number.isInteger(fee) && fee < 1e6, "FEE");
|
|
569
|
+
[this.token0, this.token1] = tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA];
|
|
570
|
+
this.fee = fee;
|
|
571
|
+
this.sqrtRatioX96 = BigInt(sqrtRatioX96);
|
|
572
|
+
this.liquidity = BigInt(liquidity);
|
|
573
|
+
this.tickCurrent = tickCurrent;
|
|
574
|
+
this.tickDataProvider = Array.isArray(ticks) ? new TickListDataProvider(ticks) : ticks;
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Returns true if the token is either token0 or token1
|
|
578
|
+
* @param token The token to check
|
|
579
|
+
* @returns True if token is either token0 or token
|
|
580
|
+
*/
|
|
581
|
+
involvesToken(token) {
|
|
582
|
+
return token.equals(this.token0) || token.equals(this.token1);
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Returns the current mid price of the pool in terms of token0, i.e. the ratio of token1 over token0
|
|
586
|
+
*/
|
|
587
|
+
get token0Price() {
|
|
588
|
+
return this._token0Price ?? (this._token0Price = new Price(this.token0, this.token1, Q192, this.sqrtRatioX96 * this.sqrtRatioX96));
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Returns the current mid price of the pool in terms of token1, i.e. the ratio of token0 over token1
|
|
592
|
+
*/
|
|
593
|
+
get token1Price() {
|
|
594
|
+
return this._token1Price ?? (this._token1Price = new Price(this.token1, this.token0, this.sqrtRatioX96 * this.sqrtRatioX96, Q192));
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Return the price of the given token in terms of the other token in the pool.
|
|
598
|
+
* @param token The token to return price of
|
|
599
|
+
* @returns The price of the given token, in terms of the other.
|
|
600
|
+
*/
|
|
601
|
+
priceOf(token) {
|
|
602
|
+
invariant9(this.involvesToken(token), "TOKEN");
|
|
603
|
+
return token.equals(this.token0) ? this.token0Price : this.token1Price;
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Returns the chain ID of the tokens in the pool.
|
|
607
|
+
*/
|
|
608
|
+
get chainId() {
|
|
609
|
+
return this.token0.chainId;
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Given an input amount of a token, return the computed output amount, and a pool with state updated after the trade
|
|
613
|
+
* @param inputAmount The input amount for which to quote the output amount
|
|
614
|
+
* @param sqrtPriceLimitX96 The Q64.96 sqrt price limit
|
|
615
|
+
* @returns The output amount and the pool with updated state
|
|
616
|
+
*/
|
|
617
|
+
async getOutputAmount(inputAmount, sqrtPriceLimitX96) {
|
|
618
|
+
invariant9(this.involvesToken(inputAmount.currency), "TOKEN");
|
|
619
|
+
const zeroForOne = inputAmount.currency.equals(this.token0);
|
|
620
|
+
const {
|
|
621
|
+
amountCalculated: outputAmount,
|
|
622
|
+
sqrtRatioX96,
|
|
623
|
+
liquidity,
|
|
624
|
+
tickCurrent
|
|
625
|
+
} = await this.swap(zeroForOne, inputAmount.quotient, sqrtPriceLimitX96);
|
|
626
|
+
const outputToken = zeroForOne ? this.token1 : this.token0;
|
|
627
|
+
return [
|
|
628
|
+
CurrencyAmount.fromRawAmount(outputToken, outputAmount * NEGATIVE_ONE),
|
|
629
|
+
new Pool(this.token0, this.token1, this.fee, sqrtRatioX96, liquidity, tickCurrent, this.tickDataProvider)
|
|
630
|
+
];
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Given a desired output amount of a token, return the computed input amount and a pool with state updated after the trade
|
|
634
|
+
* @param outputAmount the output amount for which to quote the input amount
|
|
635
|
+
* @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this value after the swap. If one for zero, the price cannot be greater than this value after the swap
|
|
636
|
+
* @returns The input amount and the pool with updated state
|
|
637
|
+
*/
|
|
638
|
+
async getInputAmount(outputAmount, sqrtPriceLimitX96) {
|
|
639
|
+
invariant9(outputAmount.currency.isToken && this.involvesToken(outputAmount.currency), "TOKEN");
|
|
640
|
+
const zeroForOne = outputAmount.currency.equals(this.token1);
|
|
641
|
+
const {
|
|
642
|
+
amountSpecifiedRemaining,
|
|
643
|
+
amountCalculated: inputAmount,
|
|
644
|
+
sqrtRatioX96,
|
|
645
|
+
liquidity,
|
|
646
|
+
tickCurrent
|
|
647
|
+
} = await this.swap(zeroForOne, outputAmount.quotient * NEGATIVE_ONE, sqrtPriceLimitX96);
|
|
648
|
+
invariant9(amountSpecifiedRemaining === ZERO, "INSUFICIENT_LIQUIDITY");
|
|
649
|
+
const inputToken = zeroForOne ? this.token0 : this.token1;
|
|
650
|
+
return [
|
|
651
|
+
CurrencyAmount.fromRawAmount(inputToken, inputAmount),
|
|
652
|
+
new Pool(this.token0, this.token1, this.fee, sqrtRatioX96, liquidity, tickCurrent, this.tickDataProvider)
|
|
653
|
+
];
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Executes a swap
|
|
657
|
+
* @param zeroForOne Whether the amount in is token0 or token1
|
|
658
|
+
* @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)
|
|
659
|
+
* @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this value after the swap. If one for zero, the price cannot be greater than this value after the swap
|
|
660
|
+
* @returns amountCalculated
|
|
661
|
+
* @returns sqrtRatioX96
|
|
662
|
+
* @returns liquidity
|
|
663
|
+
* @returns tickCurrent
|
|
664
|
+
*/
|
|
665
|
+
async swap(zeroForOne, amountSpecified, sqrtPriceLimitX96) {
|
|
666
|
+
if (!sqrtPriceLimitX96)
|
|
667
|
+
sqrtPriceLimitX96 = zeroForOne ? TickMath.MIN_SQRT_RATIO + ONE : TickMath.MAX_SQRT_RATIO - ONE;
|
|
668
|
+
if (zeroForOne) {
|
|
669
|
+
invariant9(sqrtPriceLimitX96 > TickMath.MIN_SQRT_RATIO, "RATIO_MIN");
|
|
670
|
+
invariant9(sqrtPriceLimitX96 < this.sqrtRatioX96, "RATIO_CURRENT");
|
|
671
|
+
} else {
|
|
672
|
+
invariant9(sqrtPriceLimitX96 < TickMath.MAX_SQRT_RATIO, "RATIO_MAX");
|
|
673
|
+
invariant9(sqrtPriceLimitX96 > this.sqrtRatioX96, "RATIO_CURRENT");
|
|
674
|
+
}
|
|
675
|
+
const exactInput = amountSpecified >= ZERO;
|
|
676
|
+
const state = {
|
|
677
|
+
amountSpecifiedRemaining: amountSpecified,
|
|
678
|
+
amountCalculated: ZERO,
|
|
679
|
+
sqrtPriceX96: this.sqrtRatioX96,
|
|
680
|
+
tick: this.tickCurrent,
|
|
681
|
+
liquidity: this.liquidity
|
|
682
|
+
};
|
|
683
|
+
while (state.amountSpecifiedRemaining !== ZERO && state.sqrtPriceX96 != sqrtPriceLimitX96) {
|
|
684
|
+
const step = {};
|
|
685
|
+
step.sqrtPriceStartX96 = state.sqrtPriceX96;
|
|
686
|
+
[step.tickNext, step.initialized] = await this.tickDataProvider.nextInitializedTickWithinOneWord(
|
|
687
|
+
state.tick,
|
|
688
|
+
zeroForOne,
|
|
689
|
+
this.tickSpacing
|
|
690
|
+
);
|
|
691
|
+
if (step.tickNext < TickMath.MIN_TICK) {
|
|
692
|
+
step.tickNext = TickMath.MIN_TICK;
|
|
693
|
+
} else if (step.tickNext > TickMath.MAX_TICK) {
|
|
694
|
+
step.tickNext = TickMath.MAX_TICK;
|
|
488
695
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
696
|
+
step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext);
|
|
697
|
+
[state.sqrtPriceX96, step.amountIn, step.amountOut, step.feeAmount] = SwapMath.computeSwapStep(
|
|
698
|
+
state.sqrtPriceX96,
|
|
699
|
+
(zeroForOne ? step.sqrtPriceNextX96 < sqrtPriceLimitX96 : step.sqrtPriceNextX96 > sqrtPriceLimitX96) ? sqrtPriceLimitX96 : step.sqrtPriceNextX96,
|
|
700
|
+
state.liquidity,
|
|
701
|
+
state.amountSpecifiedRemaining,
|
|
702
|
+
this.fee
|
|
703
|
+
);
|
|
704
|
+
if (exactInput) {
|
|
705
|
+
state.amountSpecifiedRemaining = state.amountSpecifiedRemaining - (step.amountIn + step.feeAmount);
|
|
706
|
+
state.amountCalculated = state.amountCalculated - step.amountOut;
|
|
707
|
+
} else {
|
|
708
|
+
state.amountSpecifiedRemaining = state.amountSpecifiedRemaining + step.amountOut;
|
|
709
|
+
state.amountCalculated = state.amountCalculated + (step.amountIn + step.feeAmount);
|
|
710
|
+
}
|
|
711
|
+
if (state.sqrtPriceX96 === step.sqrtPriceNextX96) {
|
|
712
|
+
if (step.initialized) {
|
|
713
|
+
let liquidityNet = BigInt((await this.tickDataProvider.getTick(step.tickNext)).liquidityNet);
|
|
714
|
+
if (zeroForOne)
|
|
715
|
+
liquidityNet = liquidityNet * NEGATIVE_ONE;
|
|
716
|
+
state.liquidity = LiquidityMath.addDelta(state.liquidity, liquidityNet);
|
|
717
|
+
}
|
|
718
|
+
state.tick = zeroForOne ? step.tickNext - 1 : step.tickNext;
|
|
719
|
+
} else if (state.sqrtPriceX96 !== step.sqrtPriceStartX96) {
|
|
720
|
+
state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
return {
|
|
724
|
+
amountSpecifiedRemaining: state.amountSpecifiedRemaining,
|
|
725
|
+
amountCalculated: state.amountCalculated,
|
|
726
|
+
sqrtRatioX96: state.sqrtPriceX96,
|
|
727
|
+
liquidity: state.liquidity,
|
|
728
|
+
tickCurrent: state.tick
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
get tickSpacing() {
|
|
732
|
+
return TICK_SPACINGS[this.fee];
|
|
733
|
+
}
|
|
734
|
+
};
|
|
505
735
|
|
|
506
736
|
// src/utils/maxLiquidityForAmounts.ts
|
|
507
737
|
function maxLiquidityForAmount0Imprecise(sqrtRatioAX96, sqrtRatioBX96, amount0) {
|
|
@@ -544,36 +774,18 @@ function maxLiquidityForAmounts(sqrtRatioCurrentX96, sqrtRatioAX96, sqrtRatioBX9
|
|
|
544
774
|
}
|
|
545
775
|
return maxLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);
|
|
546
776
|
}
|
|
547
|
-
function
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
if (rounded < TickMath.MIN_TICK)
|
|
553
|
-
return rounded + tickSpacing;
|
|
554
|
-
if (rounded > TickMath.MAX_TICK)
|
|
555
|
-
return rounded - tickSpacing;
|
|
556
|
-
return rounded;
|
|
777
|
+
function encodeSqrtRatioX96(amount1, amount0) {
|
|
778
|
+
const numerator = BigInt(amount1) << 192n;
|
|
779
|
+
const denominator = BigInt(amount0);
|
|
780
|
+
const ratioX192 = numerator / denominator;
|
|
781
|
+
return sqrt(ratioX192);
|
|
557
782
|
}
|
|
558
783
|
|
|
559
|
-
// src/utils/
|
|
560
|
-
var PositionLibrary = class {
|
|
561
|
-
/**
|
|
562
|
-
* Cannot be constructed.
|
|
563
|
-
*/
|
|
564
|
-
constructor() {
|
|
565
|
-
}
|
|
566
|
-
// replicates the portions of Position#update required to compute unaccounted fees
|
|
567
|
-
static getTokensOwed(feeGrowthInside0LastX128, feeGrowthInside1LastX128, liquidity, feeGrowthInside0X128, feeGrowthInside1X128) {
|
|
568
|
-
const tokensOwed0 = subIn256(feeGrowthInside0X128, feeGrowthInside0LastX128) * liquidity / Q128;
|
|
569
|
-
const tokensOwed1 = subIn256(feeGrowthInside1X128, feeGrowthInside1LastX128) * liquidity / Q128;
|
|
570
|
-
return [tokensOwed0, tokensOwed1];
|
|
571
|
-
}
|
|
572
|
-
};
|
|
784
|
+
// src/utils/priceTickConversions.ts
|
|
573
785
|
function tickToPrice(baseToken, quoteToken, tick) {
|
|
574
786
|
const sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);
|
|
575
787
|
const ratioX192 = sqrtRatioX96 * sqrtRatioX96;
|
|
576
|
-
return baseToken.sortsBefore(quoteToken) ? new Price(baseToken, quoteToken, Q192, ratioX192) : new Price(baseToken, quoteToken, ratioX192, Q192);
|
|
788
|
+
return baseToken.sortsBefore(quoteToken) ? new Price$1(baseToken, quoteToken, Q192, ratioX192) : new Price$1(baseToken, quoteToken, ratioX192, Q192);
|
|
577
789
|
}
|
|
578
790
|
function priceToClosestTick(price) {
|
|
579
791
|
const sorted = price.baseCurrency.sortsBefore(price.quoteCurrency);
|
|
@@ -590,47 +802,6 @@ function priceToClosestTick(price) {
|
|
|
590
802
|
return tick;
|
|
591
803
|
}
|
|
592
804
|
|
|
593
|
-
// src/utils/tickLibrary.ts
|
|
594
|
-
var Q256 = 2n ** 256n;
|
|
595
|
-
function subIn256(x, y) {
|
|
596
|
-
const difference = x - y;
|
|
597
|
-
if (difference < ZERO) {
|
|
598
|
-
return Q256 + difference;
|
|
599
|
-
}
|
|
600
|
-
return difference;
|
|
601
|
-
}
|
|
602
|
-
var TickLibrary = class {
|
|
603
|
-
/**
|
|
604
|
-
* Cannot be constructed.
|
|
605
|
-
*/
|
|
606
|
-
constructor() {
|
|
607
|
-
}
|
|
608
|
-
static getFeeGrowthInside(feeGrowthOutsideLower, feeGrowthOutsideUpper, tickLower, tickUpper, tickCurrent, feeGrowthGlobal0X128, feeGrowthGlobal1X128) {
|
|
609
|
-
let feeGrowthBelow0X128;
|
|
610
|
-
let feeGrowthBelow1X128;
|
|
611
|
-
if (tickCurrent >= tickLower) {
|
|
612
|
-
feeGrowthBelow0X128 = feeGrowthOutsideLower.feeGrowthOutside0X128;
|
|
613
|
-
feeGrowthBelow1X128 = feeGrowthOutsideLower.feeGrowthOutside1X128;
|
|
614
|
-
} else {
|
|
615
|
-
feeGrowthBelow0X128 = subIn256(feeGrowthGlobal0X128, feeGrowthOutsideLower.feeGrowthOutside0X128);
|
|
616
|
-
feeGrowthBelow1X128 = subIn256(feeGrowthGlobal1X128, feeGrowthOutsideLower.feeGrowthOutside1X128);
|
|
617
|
-
}
|
|
618
|
-
let feeGrowthAbove0X128;
|
|
619
|
-
let feeGrowthAbove1X128;
|
|
620
|
-
if (tickCurrent < tickUpper) {
|
|
621
|
-
feeGrowthAbove0X128 = feeGrowthOutsideUpper.feeGrowthOutside0X128;
|
|
622
|
-
feeGrowthAbove1X128 = feeGrowthOutsideUpper.feeGrowthOutside1X128;
|
|
623
|
-
} else {
|
|
624
|
-
feeGrowthAbove0X128 = subIn256(feeGrowthGlobal0X128, feeGrowthOutsideUpper.feeGrowthOutside0X128);
|
|
625
|
-
feeGrowthAbove1X128 = subIn256(feeGrowthGlobal1X128, feeGrowthOutsideUpper.feeGrowthOutside1X128);
|
|
626
|
-
}
|
|
627
|
-
return [
|
|
628
|
-
subIn256(subIn256(feeGrowthGlobal0X128, feeGrowthBelow0X128), feeGrowthAbove0X128),
|
|
629
|
-
subIn256(subIn256(feeGrowthGlobal1X128, feeGrowthBelow1X128), feeGrowthAbove1X128)
|
|
630
|
-
];
|
|
631
|
-
}
|
|
632
|
-
};
|
|
633
|
-
|
|
634
805
|
// src/utils/positionMath.ts
|
|
635
806
|
function getToken0Amount(tickCurrent, tickLower, tickUpper, sqrtRatioX96, liquidity) {
|
|
636
807
|
if (tickCurrent < tickLower) {
|
|
@@ -664,914 +835,514 @@ var PositionMath = {
|
|
|
664
835
|
getToken0Amount,
|
|
665
836
|
getToken1Amount
|
|
666
837
|
};
|
|
667
|
-
function parseNumberToFraction(num, precision = 6) {
|
|
668
|
-
const scalar = 10 ** precision;
|
|
669
|
-
return new Fraction$1(BigInt(Math.floor(num * scalar)), BigInt(scalar));
|
|
670
|
-
}
|
|
671
838
|
|
|
672
|
-
// src/
|
|
673
|
-
var
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
return getEstimatedLPFeeByAmounts({
|
|
694
|
-
...rest,
|
|
695
|
-
amountA: amount,
|
|
696
|
-
amountB: CurrencyAmount.fromRawAmount(currency, MaxUint256)
|
|
697
|
-
});
|
|
698
|
-
}
|
|
699
|
-
function getEstimatedLPFeeByAmountsWithProtocolFee(options) {
|
|
700
|
-
try {
|
|
701
|
-
return tryGetEstimatedLPFeeByAmounts(options);
|
|
702
|
-
} catch (e) {
|
|
703
|
-
console.error(e);
|
|
704
|
-
return new Fraction(ZERO$1);
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
function getEstimatedLPFeeByAmounts({ protocolFee = ZERO_PERCENT, ...rest }) {
|
|
708
|
-
try {
|
|
709
|
-
const fee = tryGetEstimatedLPFeeByAmounts(rest);
|
|
710
|
-
return ONE_HUNDRED_PERCENT.subtract(protocolFee).multiply(fee).asFraction;
|
|
711
|
-
} catch (e) {
|
|
712
|
-
console.error(e);
|
|
713
|
-
return new Fraction(ZERO$1);
|
|
839
|
+
// src/entities/position.ts
|
|
840
|
+
var Position = class {
|
|
841
|
+
/**
|
|
842
|
+
* Constructs a position for a given pool with the given liquidity
|
|
843
|
+
* @param pool For which pool the liquidity is assigned
|
|
844
|
+
* @param liquidity The amount of liquidity that is in the position
|
|
845
|
+
* @param tickLower The lower tick of the position
|
|
846
|
+
* @param tickUpper The upper tick of the position
|
|
847
|
+
*/
|
|
848
|
+
constructor({ pool, liquidity, tickLower, tickUpper }) {
|
|
849
|
+
// cached resuts for the getters
|
|
850
|
+
this._token0Amount = null;
|
|
851
|
+
this._token1Amount = null;
|
|
852
|
+
this._mintAmounts = null;
|
|
853
|
+
invariant9(tickLower < tickUpper, "TICK_ORDER");
|
|
854
|
+
invariant9(tickLower >= TickMath.MIN_TICK && tickLower % pool.tickSpacing === 0, "TICK_LOWER");
|
|
855
|
+
invariant9(tickUpper <= TickMath.MAX_TICK && tickUpper % pool.tickSpacing === 0, "TICK_UPPER");
|
|
856
|
+
this.pool = pool;
|
|
857
|
+
this.tickLower = tickLower;
|
|
858
|
+
this.tickUpper = tickUpper;
|
|
859
|
+
this.liquidity = BigInt(liquidity);
|
|
714
860
|
}
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
sqrtRatioX96,
|
|
721
|
-
tickLower,
|
|
722
|
-
tickUpper,
|
|
723
|
-
mostActiveLiquidity,
|
|
724
|
-
fee,
|
|
725
|
-
insidePercentage = ONE_HUNDRED_PERCENT
|
|
726
|
-
}) {
|
|
727
|
-
invariant11(!Number.isNaN(fee) && fee >= 0, "INVALID_FEE");
|
|
728
|
-
const tickCurrent = TickMath.getTickAtSqrtRatio(sqrtRatioX96);
|
|
729
|
-
if (tickCurrent < tickLower || tickCurrent > tickUpper) {
|
|
730
|
-
return new Fraction(ZERO$1);
|
|
861
|
+
/**
|
|
862
|
+
* Returns the price of token0 at the lower tick
|
|
863
|
+
*/
|
|
864
|
+
get token0PriceLower() {
|
|
865
|
+
return tickToPrice(this.pool.token0, this.pool.token1, this.tickLower);
|
|
731
866
|
}
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
sqrtRatioX96
|
|
738
|
-
});
|
|
739
|
-
return insidePercentage.multiply(parseNumberToFraction(volume24H).multiply(BigInt(fee)).multiply(liquidity)).divide(MAX_FEE * (liquidity + mostActiveLiquidity)).asFraction;
|
|
740
|
-
}
|
|
741
|
-
function getDependentAmount(options) {
|
|
742
|
-
const { currency, amount, sqrtRatioX96, tickLower, tickUpper } = options;
|
|
743
|
-
const currentTick = TickMath.getTickAtSqrtRatio(sqrtRatioX96);
|
|
744
|
-
const liquidity = FeeCalculator.getLiquidityBySingleAmount(options);
|
|
745
|
-
const isToken0 = currency.wrapped.sortsBefore(amount.currency.wrapped);
|
|
746
|
-
const getTokenAmount = isToken0 ? PositionMath.getToken0Amount : PositionMath.getToken1Amount;
|
|
747
|
-
return CurrencyAmount.fromRawAmount(
|
|
748
|
-
currency,
|
|
749
|
-
getTokenAmount(currentTick, tickLower, tickUpper, sqrtRatioX96, liquidity)
|
|
750
|
-
);
|
|
751
|
-
}
|
|
752
|
-
function getLiquidityBySingleAmount({ amount, currency, ...rest }) {
|
|
753
|
-
return getLiquidityByAmountsAndPrice({
|
|
754
|
-
amountA: amount,
|
|
755
|
-
amountB: CurrencyAmount.fromRawAmount(currency, MaxUint256),
|
|
756
|
-
...rest
|
|
757
|
-
});
|
|
758
|
-
}
|
|
759
|
-
function getLiquidityByAmountsAndPrice({
|
|
760
|
-
amountA,
|
|
761
|
-
amountB,
|
|
762
|
-
tickUpper,
|
|
763
|
-
tickLower,
|
|
764
|
-
sqrtRatioX96
|
|
765
|
-
}) {
|
|
766
|
-
const isToken0 = amountA.currency.wrapped.sortsBefore(amountB.currency.wrapped);
|
|
767
|
-
const [inputAmount0, inputAmount1] = isToken0 ? [amountA.quotient, amountB.quotient] : [amountB.quotient, amountA.quotient];
|
|
768
|
-
const sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickLower);
|
|
769
|
-
const sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickUpper);
|
|
770
|
-
return maxLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, inputAmount0, inputAmount1, true);
|
|
771
|
-
}
|
|
772
|
-
function getAmountsByLiquidityAndPrice(options) {
|
|
773
|
-
const { currencyA, currencyB, liquidity, sqrtRatioX96, tickLower, tickUpper } = options;
|
|
774
|
-
const currentTick = TickMath.getTickAtSqrtRatio(sqrtRatioX96);
|
|
775
|
-
const isToken0 = currencyA.wrapped.sortsBefore(currencyB.wrapped);
|
|
776
|
-
const adjustedAmount0 = PositionMath.getToken0Amount(currentTick, tickLower, tickUpper, sqrtRatioX96, liquidity);
|
|
777
|
-
const adjustedAmount1 = PositionMath.getToken1Amount(currentTick, tickLower, tickUpper, sqrtRatioX96, liquidity);
|
|
778
|
-
return [
|
|
779
|
-
CurrencyAmount.fromRawAmount(currencyA, isToken0 ? adjustedAmount0 : adjustedAmount1),
|
|
780
|
-
CurrencyAmount.fromRawAmount(currencyB, isToken0 ? adjustedAmount1 : adjustedAmount0)
|
|
781
|
-
];
|
|
782
|
-
}
|
|
783
|
-
function getAmountsAtNewPrice({ newSqrtRatioX96, ...rest }) {
|
|
784
|
-
const { tickLower, tickUpper, amountA, amountB } = rest;
|
|
785
|
-
const liquidity = FeeCalculator.getLiquidityByAmountsAndPrice(rest);
|
|
786
|
-
return FeeCalculator.getAmountsByLiquidityAndPrice({
|
|
787
|
-
liquidity,
|
|
788
|
-
currencyA: amountA.currency,
|
|
789
|
-
currencyB: amountB.currency,
|
|
790
|
-
tickLower,
|
|
791
|
-
tickUpper,
|
|
792
|
-
sqrtRatioX96: newSqrtRatioX96
|
|
793
|
-
});
|
|
794
|
-
}
|
|
795
|
-
function getAverageLiquidity(ticks, tickSpacing, tickLower, tickUpper) {
|
|
796
|
-
invariant11(tickLower <= tickUpper, "INVALID_TICK_RANGE");
|
|
797
|
-
TickList.validateList(ticks, tickSpacing);
|
|
798
|
-
if (tickLower === tickUpper) {
|
|
799
|
-
return FeeCalculator.getLiquidityFromTick(ticks, tickLower);
|
|
867
|
+
/**
|
|
868
|
+
* Returns the price of token0 at the upper tick
|
|
869
|
+
*/
|
|
870
|
+
get token0PriceUpper() {
|
|
871
|
+
return tickToPrice(this.pool.token0, this.pool.token1, this.tickUpper);
|
|
800
872
|
}
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
873
|
+
/**
|
|
874
|
+
* Returns the amount of token0 that this position's liquidity could be burned for at the current pool price
|
|
875
|
+
*/
|
|
876
|
+
get amount0() {
|
|
877
|
+
if (this._token0Amount === null) {
|
|
878
|
+
this._token0Amount = CurrencyAmount.fromRawAmount(
|
|
879
|
+
this.pool.token0,
|
|
880
|
+
PositionMath.getToken0Amount(
|
|
881
|
+
this.pool.tickCurrent,
|
|
882
|
+
this.tickLower,
|
|
883
|
+
this.tickUpper,
|
|
884
|
+
this.pool.sqrtRatioX96,
|
|
885
|
+
this.liquidity
|
|
886
|
+
)
|
|
887
|
+
);
|
|
813
888
|
}
|
|
814
|
-
|
|
889
|
+
return this._token0Amount;
|
|
815
890
|
}
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
891
|
+
/**
|
|
892
|
+
* Returns the amount of token1 that this position's liquidity could be burned for at the current pool price
|
|
893
|
+
*/
|
|
894
|
+
get amount1() {
|
|
895
|
+
if (this._token1Amount === null) {
|
|
896
|
+
this._token1Amount = CurrencyAmount.fromRawAmount(
|
|
897
|
+
this.pool.token1,
|
|
898
|
+
PositionMath.getToken1Amount(
|
|
899
|
+
this.pool.tickCurrent,
|
|
900
|
+
this.tickLower,
|
|
901
|
+
this.tickUpper,
|
|
902
|
+
this.pool.sqrtRatioX96,
|
|
903
|
+
this.liquidity
|
|
904
|
+
)
|
|
905
|
+
);
|
|
906
|
+
}
|
|
907
|
+
return this._token1Amount;
|
|
829
908
|
}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
909
|
+
/**
|
|
910
|
+
* Returns the lower and upper sqrt ratios if the price 'slips' up to slippage tolerance percentage
|
|
911
|
+
* @param slippageTolerance The amount by which the price can 'slip' before the transaction will revert
|
|
912
|
+
* @returns The sqrt ratios after slippage
|
|
913
|
+
*/
|
|
914
|
+
ratiosAfterSlippage(slippageTolerance) {
|
|
915
|
+
const priceLower = this.pool.token0Price.asFraction.multiply(new Percent$1(1).subtract(slippageTolerance));
|
|
916
|
+
const priceUpper = this.pool.token0Price.asFraction.multiply(slippageTolerance.add(1));
|
|
917
|
+
let sqrtRatioX96Lower = encodeSqrtRatioX96(priceLower.numerator, priceLower.denominator);
|
|
918
|
+
if (sqrtRatioX96Lower <= TickMath.MIN_SQRT_RATIO) {
|
|
919
|
+
sqrtRatioX96Lower = TickMath.MIN_SQRT_RATIO + 1n;
|
|
836
920
|
}
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
}
|
|
846
|
-
const token0ProtocolFee = packed % 2 ** 16;
|
|
847
|
-
const token1ProtocolFee = packed >> 16;
|
|
848
|
-
return [new Percent$1(token0ProtocolFee, FEE_BASE), new Percent$1(token1ProtocolFee, FEE_BASE)];
|
|
849
|
-
}
|
|
850
|
-
function sqrtRatioX96ToPrice(sqrtRatioX96, currencyA, currencyB) {
|
|
851
|
-
const ratioX192 = sqrtRatioX96 * sqrtRatioX96;
|
|
852
|
-
return currencyA.wrapped.sortsBefore(currencyB.wrapped) ? new Price$1(currencyA.wrapped, currencyB.wrapped, Q192, ratioX192) : new Price$1(currencyA.wrapped, currencyB.wrapped, ratioX192, Q192);
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
// src/entities/tick.ts
|
|
856
|
-
var Tick = class {
|
|
857
|
-
constructor({ index, liquidityGross, liquidityNet }) {
|
|
858
|
-
invariant11(index >= TickMath.MIN_TICK && index <= TickMath.MAX_TICK, "TICK");
|
|
859
|
-
this.index = index;
|
|
860
|
-
this.liquidityGross = BigInt(liquidityGross);
|
|
861
|
-
this.liquidityNet = BigInt(liquidityNet);
|
|
862
|
-
}
|
|
863
|
-
};
|
|
864
|
-
|
|
865
|
-
// src/entities/tickListDataProvider.ts
|
|
866
|
-
var TickListDataProvider = class {
|
|
867
|
-
constructor(ticks) {
|
|
868
|
-
const ticksMapped = ticks.map((t) => t instanceof Tick ? t : new Tick(t));
|
|
869
|
-
this.ticks = ticksMapped;
|
|
870
|
-
}
|
|
871
|
-
async getTick(tick) {
|
|
872
|
-
return TickList.getTick(this.ticks, tick);
|
|
873
|
-
}
|
|
874
|
-
async nextInitializedTickWithinOneWord(tick, lte, tickSpacing) {
|
|
875
|
-
return TickList.nextInitializedTickWithinOneWord(this.ticks, tick, lte, tickSpacing);
|
|
876
|
-
}
|
|
877
|
-
};
|
|
878
|
-
|
|
879
|
-
// src/entities/pool.ts
|
|
880
|
-
var NO_TICK_DATA_PROVIDER_DEFAULT = new NoTickDataProvider();
|
|
881
|
-
var Pool = class {
|
|
882
|
-
static getAddress(tokenA, tokenB, fee, initCodeHashManualOverride, deployerAddressOverride) {
|
|
883
|
-
return computePoolAddress({
|
|
884
|
-
deployerAddress: deployerAddressOverride ?? DEPLOYER_ADDRESSES[tokenA.chainId],
|
|
885
|
-
fee,
|
|
886
|
-
tokenA,
|
|
887
|
-
tokenB,
|
|
888
|
-
initCodeHashManualOverride
|
|
889
|
-
});
|
|
921
|
+
let sqrtRatioX96Upper = encodeSqrtRatioX96(priceUpper.numerator, priceUpper.denominator);
|
|
922
|
+
if (sqrtRatioX96Upper >= TickMath.MAX_SQRT_RATIO) {
|
|
923
|
+
sqrtRatioX96Upper = TickMath.MAX_SQRT_RATIO - 1n;
|
|
924
|
+
}
|
|
925
|
+
return {
|
|
926
|
+
sqrtRatioX96Lower,
|
|
927
|
+
sqrtRatioX96Upper
|
|
928
|
+
};
|
|
890
929
|
}
|
|
891
930
|
/**
|
|
892
|
-
*
|
|
893
|
-
*
|
|
894
|
-
* @param
|
|
895
|
-
* @
|
|
896
|
-
* @param sqrtRatioX96 The sqrt of the current ratio of amounts of token1 to token0
|
|
897
|
-
* @param liquidity The current value of in range liquidity
|
|
898
|
-
* @param tickCurrent The current tick of the pool
|
|
899
|
-
* @param ticks The current state of the pool ticks or a data provider that can return tick data
|
|
931
|
+
* Returns the minimum amounts that must be sent in order to safely mint the amount of liquidity held by the position
|
|
932
|
+
* with the given slippage tolerance
|
|
933
|
+
* @param slippageTolerance Tolerance of unfavorable slippage from the current price
|
|
934
|
+
* @returns The amounts, with slippage
|
|
900
935
|
*/
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
936
|
+
mintAmountsWithSlippage(slippageTolerance) {
|
|
937
|
+
const { sqrtRatioX96Upper, sqrtRatioX96Lower } = this.ratiosAfterSlippage(slippageTolerance);
|
|
938
|
+
const poolLower = new Pool(
|
|
939
|
+
this.pool.token0,
|
|
940
|
+
this.pool.token1,
|
|
941
|
+
this.pool.fee,
|
|
942
|
+
sqrtRatioX96Lower,
|
|
943
|
+
0,
|
|
944
|
+
TickMath.getTickAtSqrtRatio(sqrtRatioX96Lower)
|
|
945
|
+
);
|
|
946
|
+
const poolUpper = new Pool(
|
|
947
|
+
this.pool.token0,
|
|
948
|
+
this.pool.token1,
|
|
949
|
+
this.pool.fee,
|
|
950
|
+
sqrtRatioX96Upper,
|
|
951
|
+
0,
|
|
952
|
+
TickMath.getTickAtSqrtRatio(sqrtRatioX96Upper)
|
|
953
|
+
);
|
|
954
|
+
const positionThatWillBeCreated = Position.fromAmounts({
|
|
955
|
+
pool: this.pool,
|
|
956
|
+
tickLower: this.tickLower,
|
|
957
|
+
tickUpper: this.tickUpper,
|
|
958
|
+
...this.mintAmounts,
|
|
959
|
+
// the mint amounts are what will be passed as calldata
|
|
960
|
+
useFullPrecision: false
|
|
961
|
+
});
|
|
962
|
+
const { amount0 } = new Position({
|
|
963
|
+
pool: poolUpper,
|
|
964
|
+
liquidity: positionThatWillBeCreated.liquidity,
|
|
965
|
+
tickLower: this.tickLower,
|
|
966
|
+
tickUpper: this.tickUpper
|
|
967
|
+
}).mintAmounts;
|
|
968
|
+
const { amount1 } = new Position({
|
|
969
|
+
pool: poolLower,
|
|
970
|
+
liquidity: positionThatWillBeCreated.liquidity,
|
|
971
|
+
tickLower: this.tickLower,
|
|
972
|
+
tickUpper: this.tickUpper
|
|
973
|
+
}).mintAmounts;
|
|
974
|
+
return { amount0, amount1 };
|
|
909
975
|
}
|
|
910
976
|
/**
|
|
911
|
-
* Returns
|
|
912
|
-
*
|
|
913
|
-
* @
|
|
977
|
+
* Returns the minimum amounts that should be requested in order to safely burn the amount of liquidity held by the
|
|
978
|
+
* position with the given slippage tolerance
|
|
979
|
+
* @param slippageTolerance tolerance of unfavorable slippage from the current price
|
|
980
|
+
* @returns The amounts, with slippage
|
|
914
981
|
*/
|
|
915
|
-
|
|
916
|
-
|
|
982
|
+
burnAmountsWithSlippage(slippageTolerance) {
|
|
983
|
+
const { sqrtRatioX96Upper, sqrtRatioX96Lower } = this.ratiosAfterSlippage(slippageTolerance);
|
|
984
|
+
const poolLower = new Pool(
|
|
985
|
+
this.pool.token0,
|
|
986
|
+
this.pool.token1,
|
|
987
|
+
this.pool.fee,
|
|
988
|
+
sqrtRatioX96Lower,
|
|
989
|
+
0,
|
|
990
|
+
TickMath.getTickAtSqrtRatio(sqrtRatioX96Lower)
|
|
991
|
+
);
|
|
992
|
+
const poolUpper = new Pool(
|
|
993
|
+
this.pool.token0,
|
|
994
|
+
this.pool.token1,
|
|
995
|
+
this.pool.fee,
|
|
996
|
+
sqrtRatioX96Upper,
|
|
997
|
+
0,
|
|
998
|
+
TickMath.getTickAtSqrtRatio(sqrtRatioX96Upper)
|
|
999
|
+
);
|
|
1000
|
+
const { amount0 } = new Position({
|
|
1001
|
+
pool: poolUpper,
|
|
1002
|
+
liquidity: this.liquidity,
|
|
1003
|
+
tickLower: this.tickLower,
|
|
1004
|
+
tickUpper: this.tickUpper
|
|
1005
|
+
});
|
|
1006
|
+
const { amount1 } = new Position({
|
|
1007
|
+
pool: poolLower,
|
|
1008
|
+
liquidity: this.liquidity,
|
|
1009
|
+
tickLower: this.tickLower,
|
|
1010
|
+
tickUpper: this.tickUpper
|
|
1011
|
+
});
|
|
1012
|
+
return { amount0: amount0.quotient, amount1: amount1.quotient };
|
|
917
1013
|
}
|
|
918
1014
|
/**
|
|
919
|
-
* Returns the
|
|
1015
|
+
* Returns the minimum amounts that must be sent in order to mint the amount of liquidity held by the position at
|
|
1016
|
+
* the current price for the pool
|
|
920
1017
|
*/
|
|
921
|
-
get
|
|
922
|
-
|
|
1018
|
+
get mintAmounts() {
|
|
1019
|
+
if (this._mintAmounts === null) {
|
|
1020
|
+
if (this.pool.tickCurrent < this.tickLower) {
|
|
1021
|
+
return {
|
|
1022
|
+
amount0: SqrtPriceMath.getAmount0Delta(
|
|
1023
|
+
TickMath.getSqrtRatioAtTick(this.tickLower),
|
|
1024
|
+
TickMath.getSqrtRatioAtTick(this.tickUpper),
|
|
1025
|
+
this.liquidity,
|
|
1026
|
+
true
|
|
1027
|
+
),
|
|
1028
|
+
amount1: ZERO
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
if (this.pool.tickCurrent < this.tickUpper) {
|
|
1032
|
+
return {
|
|
1033
|
+
amount0: SqrtPriceMath.getAmount0Delta(
|
|
1034
|
+
this.pool.sqrtRatioX96,
|
|
1035
|
+
TickMath.getSqrtRatioAtTick(this.tickUpper),
|
|
1036
|
+
this.liquidity,
|
|
1037
|
+
true
|
|
1038
|
+
),
|
|
1039
|
+
amount1: SqrtPriceMath.getAmount1Delta(
|
|
1040
|
+
TickMath.getSqrtRatioAtTick(this.tickLower),
|
|
1041
|
+
this.pool.sqrtRatioX96,
|
|
1042
|
+
this.liquidity,
|
|
1043
|
+
true
|
|
1044
|
+
)
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
return {
|
|
1048
|
+
amount0: ZERO,
|
|
1049
|
+
amount1: SqrtPriceMath.getAmount1Delta(
|
|
1050
|
+
TickMath.getSqrtRatioAtTick(this.tickLower),
|
|
1051
|
+
TickMath.getSqrtRatioAtTick(this.tickUpper),
|
|
1052
|
+
this.liquidity,
|
|
1053
|
+
true
|
|
1054
|
+
)
|
|
1055
|
+
};
|
|
1056
|
+
}
|
|
1057
|
+
return this._mintAmounts;
|
|
923
1058
|
}
|
|
924
1059
|
/**
|
|
925
|
-
*
|
|
1060
|
+
* Computes the maximum amount of liquidity received for a given amount of token0, token1,
|
|
1061
|
+
* and the prices at the tick boundaries.
|
|
1062
|
+
* @param pool The pool for which the position should be created
|
|
1063
|
+
* @param tickLower The lower tick of the position
|
|
1064
|
+
* @param tickUpper The upper tick of the position
|
|
1065
|
+
* @param amount0 token0 amount
|
|
1066
|
+
* @param amount1 token1 amount
|
|
1067
|
+
* @param useFullPrecision If false, liquidity will be maximized according to what the router can calculate,
|
|
1068
|
+
* not what core can theoretically support
|
|
1069
|
+
* @returns The amount of liquidity for the position
|
|
926
1070
|
*/
|
|
927
|
-
|
|
928
|
-
|
|
1071
|
+
static fromAmounts({
|
|
1072
|
+
pool,
|
|
1073
|
+
tickLower,
|
|
1074
|
+
tickUpper,
|
|
1075
|
+
amount0,
|
|
1076
|
+
amount1,
|
|
1077
|
+
useFullPrecision
|
|
1078
|
+
}) {
|
|
1079
|
+
const sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickLower);
|
|
1080
|
+
const sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickUpper);
|
|
1081
|
+
return new Position({
|
|
1082
|
+
pool,
|
|
1083
|
+
tickLower,
|
|
1084
|
+
tickUpper,
|
|
1085
|
+
liquidity: maxLiquidityForAmounts(
|
|
1086
|
+
pool.sqrtRatioX96,
|
|
1087
|
+
sqrtRatioAX96,
|
|
1088
|
+
sqrtRatioBX96,
|
|
1089
|
+
amount0,
|
|
1090
|
+
amount1,
|
|
1091
|
+
useFullPrecision
|
|
1092
|
+
)
|
|
1093
|
+
});
|
|
929
1094
|
}
|
|
930
1095
|
/**
|
|
931
|
-
*
|
|
932
|
-
* @param
|
|
933
|
-
* @
|
|
1096
|
+
* Computes a position with the maximum amount of liquidity received for a given amount of token0, assuming an unlimited amount of token1
|
|
1097
|
+
* @param pool The pool for which the position is created
|
|
1098
|
+
* @param tickLower The lower tick
|
|
1099
|
+
* @param tickUpper The upper tick
|
|
1100
|
+
* @param amount0 The desired amount of token0
|
|
1101
|
+
* @param useFullPrecision If true, liquidity will be maximized according to what the router can calculate,
|
|
1102
|
+
* not what core can theoretically support
|
|
1103
|
+
* @returns The position
|
|
934
1104
|
*/
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
1105
|
+
static fromAmount0({
|
|
1106
|
+
pool,
|
|
1107
|
+
tickLower,
|
|
1108
|
+
tickUpper,
|
|
1109
|
+
amount0,
|
|
1110
|
+
useFullPrecision
|
|
1111
|
+
}) {
|
|
1112
|
+
return Position.fromAmounts({ pool, tickLower, tickUpper, amount0, amount1: MaxUint256$1, useFullPrecision });
|
|
938
1113
|
}
|
|
939
1114
|
/**
|
|
940
|
-
*
|
|
1115
|
+
* Computes a position with the maximum amount of liquidity received for a given amount of token1, assuming an unlimited amount of token0
|
|
1116
|
+
* @param pool The pool for which the position is created
|
|
1117
|
+
* @param tickLower The lower tick
|
|
1118
|
+
* @param tickUpper The upper tick
|
|
1119
|
+
* @param amount1 The desired amount of token1
|
|
1120
|
+
* @returns The position
|
|
941
1121
|
*/
|
|
942
|
-
|
|
943
|
-
|
|
1122
|
+
static fromAmount1({
|
|
1123
|
+
pool,
|
|
1124
|
+
tickLower,
|
|
1125
|
+
tickUpper,
|
|
1126
|
+
amount1
|
|
1127
|
+
}) {
|
|
1128
|
+
return Position.fromAmounts({ pool, tickLower, tickUpper, amount0: MaxUint256$1, amount1, useFullPrecision: true });
|
|
944
1129
|
}
|
|
1130
|
+
};
|
|
1131
|
+
var Route = class {
|
|
945
1132
|
/**
|
|
946
|
-
*
|
|
947
|
-
* @param
|
|
948
|
-
* @param
|
|
949
|
-
* @
|
|
1133
|
+
* Creates an instance of route.
|
|
1134
|
+
* @param pools An array of `Pool` objects, ordered by the route the swap will take
|
|
1135
|
+
* @param input The input token
|
|
1136
|
+
* @param output The output token
|
|
950
1137
|
*/
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
const {
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
const
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1138
|
+
constructor(pools, input, output) {
|
|
1139
|
+
this._midPrice = null;
|
|
1140
|
+
invariant9(pools.length > 0, "POOLS");
|
|
1141
|
+
const { chainId } = pools[0];
|
|
1142
|
+
const allOnSameChain = pools.every((pool) => pool.chainId === chainId);
|
|
1143
|
+
invariant9(allOnSameChain, "CHAIN_IDS");
|
|
1144
|
+
const wrappedInput = input.wrapped;
|
|
1145
|
+
invariant9(pools[0].involvesToken(wrappedInput), "INPUT");
|
|
1146
|
+
invariant9(pools[pools.length - 1].involvesToken(output.wrapped), "OUTPUT");
|
|
1147
|
+
const tokenPath = [wrappedInput];
|
|
1148
|
+
for (const [i, pool] of pools.entries()) {
|
|
1149
|
+
const currentInputToken = tokenPath[i];
|
|
1150
|
+
invariant9(currentInputToken.equals(pool.token0) || currentInputToken.equals(pool.token1), "PATH");
|
|
1151
|
+
const nextToken = currentInputToken.equals(pool.token0) ? pool.token1 : pool.token0;
|
|
1152
|
+
tokenPath.push(nextToken);
|
|
1153
|
+
}
|
|
1154
|
+
this.pools = pools;
|
|
1155
|
+
this.tokenPath = tokenPath;
|
|
1156
|
+
this.input = input;
|
|
1157
|
+
this.output = output ?? tokenPath[tokenPath.length - 1];
|
|
965
1158
|
}
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
* @param outputAmount the output amount for which to quote the input amount
|
|
969
|
-
* @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this value after the swap. If one for zero, the price cannot be greater than this value after the swap
|
|
970
|
-
* @returns The input amount and the pool with updated state
|
|
971
|
-
*/
|
|
972
|
-
async getInputAmount(outputAmount, sqrtPriceLimitX96) {
|
|
973
|
-
invariant11(outputAmount.currency.isToken && this.involvesToken(outputAmount.currency), "TOKEN");
|
|
974
|
-
const zeroForOne = outputAmount.currency.equals(this.token1);
|
|
975
|
-
const {
|
|
976
|
-
amountSpecifiedRemaining,
|
|
977
|
-
amountCalculated: inputAmount,
|
|
978
|
-
sqrtRatioX96,
|
|
979
|
-
liquidity,
|
|
980
|
-
tickCurrent
|
|
981
|
-
} = await this.swap(zeroForOne, outputAmount.quotient * NEGATIVE_ONE, sqrtPriceLimitX96);
|
|
982
|
-
invariant11(amountSpecifiedRemaining === ZERO, "INSUFICIENT_LIQUIDITY");
|
|
983
|
-
const inputToken = zeroForOne ? this.token0 : this.token1;
|
|
984
|
-
return [
|
|
985
|
-
CurrencyAmount.fromRawAmount(inputToken, inputAmount),
|
|
986
|
-
new Pool(this.token0, this.token1, this.fee, sqrtRatioX96, liquidity, tickCurrent, this.tickDataProvider)
|
|
987
|
-
];
|
|
1159
|
+
get chainId() {
|
|
1160
|
+
return this.pools[0].chainId;
|
|
988
1161
|
}
|
|
989
1162
|
/**
|
|
990
|
-
*
|
|
991
|
-
* @param zeroForOne Whether the amount in is token0 or token1
|
|
992
|
-
* @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)
|
|
993
|
-
* @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this value after the swap. If one for zero, the price cannot be greater than this value after the swap
|
|
994
|
-
* @returns amountCalculated
|
|
995
|
-
* @returns sqrtRatioX96
|
|
996
|
-
* @returns liquidity
|
|
997
|
-
* @returns tickCurrent
|
|
1163
|
+
* Returns the mid price of the route
|
|
998
1164
|
*/
|
|
999
|
-
|
|
1000
|
-
if (
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
const step = {};
|
|
1019
|
-
step.sqrtPriceStartX96 = state.sqrtPriceX96;
|
|
1020
|
-
[step.tickNext, step.initialized] = await this.tickDataProvider.nextInitializedTickWithinOneWord(
|
|
1021
|
-
state.tick,
|
|
1022
|
-
zeroForOne,
|
|
1023
|
-
this.tickSpacing
|
|
1024
|
-
);
|
|
1025
|
-
if (step.tickNext < TickMath.MIN_TICK) {
|
|
1026
|
-
step.tickNext = TickMath.MIN_TICK;
|
|
1027
|
-
} else if (step.tickNext > TickMath.MAX_TICK) {
|
|
1028
|
-
step.tickNext = TickMath.MAX_TICK;
|
|
1029
|
-
}
|
|
1030
|
-
step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext);
|
|
1031
|
-
[state.sqrtPriceX96, step.amountIn, step.amountOut, step.feeAmount] = SwapMath.computeSwapStep(
|
|
1032
|
-
state.sqrtPriceX96,
|
|
1033
|
-
(zeroForOne ? step.sqrtPriceNextX96 < sqrtPriceLimitX96 : step.sqrtPriceNextX96 > sqrtPriceLimitX96) ? sqrtPriceLimitX96 : step.sqrtPriceNextX96,
|
|
1034
|
-
state.liquidity,
|
|
1035
|
-
state.amountSpecifiedRemaining,
|
|
1036
|
-
this.fee
|
|
1037
|
-
);
|
|
1038
|
-
if (exactInput) {
|
|
1039
|
-
state.amountSpecifiedRemaining = state.amountSpecifiedRemaining - (step.amountIn + step.feeAmount);
|
|
1040
|
-
state.amountCalculated = state.amountCalculated - step.amountOut;
|
|
1041
|
-
} else {
|
|
1042
|
-
state.amountSpecifiedRemaining = state.amountSpecifiedRemaining + step.amountOut;
|
|
1043
|
-
state.amountCalculated = state.amountCalculated + (step.amountIn + step.feeAmount);
|
|
1044
|
-
}
|
|
1045
|
-
if (state.sqrtPriceX96 === step.sqrtPriceNextX96) {
|
|
1046
|
-
if (step.initialized) {
|
|
1047
|
-
let liquidityNet = BigInt((await this.tickDataProvider.getTick(step.tickNext)).liquidityNet);
|
|
1048
|
-
if (zeroForOne)
|
|
1049
|
-
liquidityNet = liquidityNet * NEGATIVE_ONE;
|
|
1050
|
-
state.liquidity = LiquidityMath.addDelta(state.liquidity, liquidityNet);
|
|
1051
|
-
}
|
|
1052
|
-
state.tick = zeroForOne ? step.tickNext - 1 : step.tickNext;
|
|
1053
|
-
} else if (state.sqrtPriceX96 !== step.sqrtPriceStartX96) {
|
|
1054
|
-
state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96);
|
|
1165
|
+
get midPrice() {
|
|
1166
|
+
if (this._midPrice !== null)
|
|
1167
|
+
return this._midPrice;
|
|
1168
|
+
const { price } = this.pools.slice(1).reduce(
|
|
1169
|
+
({ nextInput, price: price2 }, pool) => {
|
|
1170
|
+
return nextInput.equals(pool.token0) ? {
|
|
1171
|
+
nextInput: pool.token1,
|
|
1172
|
+
price: price2.multiply(pool.token0Price)
|
|
1173
|
+
} : {
|
|
1174
|
+
nextInput: pool.token0,
|
|
1175
|
+
price: price2.multiply(pool.token1Price)
|
|
1176
|
+
};
|
|
1177
|
+
},
|
|
1178
|
+
this.pools[0].token0.equals(this.input.wrapped) ? {
|
|
1179
|
+
nextInput: this.pools[0].token1,
|
|
1180
|
+
price: this.pools[0].token0Price
|
|
1181
|
+
} : {
|
|
1182
|
+
nextInput: this.pools[0].token0,
|
|
1183
|
+
price: this.pools[0].token1Price
|
|
1055
1184
|
}
|
|
1185
|
+
);
|
|
1186
|
+
return this._midPrice = new Price$1(this.input, this.output, price.denominator, price.numerator);
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
1189
|
+
function tradeComparator(a, b) {
|
|
1190
|
+
invariant9(a.inputAmount.currency.equals(b.inputAmount.currency), "INPUT_CURRENCY");
|
|
1191
|
+
invariant9(a.outputAmount.currency.equals(b.outputAmount.currency), "OUTPUT_CURRENCY");
|
|
1192
|
+
if (a.outputAmount.equalTo(b.outputAmount)) {
|
|
1193
|
+
if (a.inputAmount.equalTo(b.inputAmount)) {
|
|
1194
|
+
const aHops = a.swaps.reduce((total, cur) => total + cur.route.tokenPath.length, 0);
|
|
1195
|
+
const bHops = b.swaps.reduce((total, cur) => total + cur.route.tokenPath.length, 0);
|
|
1196
|
+
return aHops - bHops;
|
|
1056
1197
|
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
liquidity: state.liquidity,
|
|
1062
|
-
tickCurrent: state.tick
|
|
1063
|
-
};
|
|
1198
|
+
if (a.inputAmount.lessThan(b.inputAmount)) {
|
|
1199
|
+
return -1;
|
|
1200
|
+
}
|
|
1201
|
+
return 1;
|
|
1064
1202
|
}
|
|
1065
|
-
|
|
1066
|
-
return
|
|
1203
|
+
if (a.outputAmount.lessThan(b.outputAmount)) {
|
|
1204
|
+
return 1;
|
|
1067
1205
|
}
|
|
1068
|
-
|
|
1069
|
-
|
|
1206
|
+
return -1;
|
|
1207
|
+
}
|
|
1208
|
+
var Trade = class {
|
|
1070
1209
|
/**
|
|
1071
|
-
*
|
|
1072
|
-
*
|
|
1073
|
-
*
|
|
1074
|
-
*
|
|
1075
|
-
*
|
|
1210
|
+
* @deprecated Deprecated in favor of 'swaps' property. If the trade consists of multiple routes
|
|
1211
|
+
* this will return an error.
|
|
1212
|
+
*
|
|
1213
|
+
* When the trade consists of just a single route, this returns the route of the trade,
|
|
1214
|
+
* i.e. which pools the trade goes through.
|
|
1076
1215
|
*/
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
this.
|
|
1080
|
-
this._token1Amount = null;
|
|
1081
|
-
this._mintAmounts = null;
|
|
1082
|
-
invariant11(tickLower < tickUpper, "TICK_ORDER");
|
|
1083
|
-
invariant11(tickLower >= TickMath.MIN_TICK && tickLower % pool.tickSpacing === 0, "TICK_LOWER");
|
|
1084
|
-
invariant11(tickUpper <= TickMath.MAX_TICK && tickUpper % pool.tickSpacing === 0, "TICK_UPPER");
|
|
1085
|
-
this.pool = pool;
|
|
1086
|
-
this.tickLower = tickLower;
|
|
1087
|
-
this.tickUpper = tickUpper;
|
|
1088
|
-
this.liquidity = BigInt(liquidity);
|
|
1216
|
+
get route() {
|
|
1217
|
+
invariant9(this.swaps.length == 1, "MULTIPLE_ROUTES");
|
|
1218
|
+
return this.swaps[0].route;
|
|
1089
1219
|
}
|
|
1090
1220
|
/**
|
|
1091
|
-
*
|
|
1221
|
+
* The input amount for the trade assuming no slippage.
|
|
1092
1222
|
*/
|
|
1093
|
-
get
|
|
1094
|
-
|
|
1223
|
+
get inputAmount() {
|
|
1224
|
+
if (this._inputAmount) {
|
|
1225
|
+
return this._inputAmount;
|
|
1226
|
+
}
|
|
1227
|
+
const inputCurrency = this.swaps[0].inputAmount.currency;
|
|
1228
|
+
const totalInputFromRoutes = this.swaps.map(({ inputAmount }) => inputAmount).reduce((total, cur) => total.add(cur), CurrencyAmount.fromRawAmount(inputCurrency, 0));
|
|
1229
|
+
this._inputAmount = totalInputFromRoutes;
|
|
1230
|
+
return this._inputAmount;
|
|
1095
1231
|
}
|
|
1096
1232
|
/**
|
|
1097
|
-
*
|
|
1233
|
+
* The output amount for the trade assuming no slippage.
|
|
1098
1234
|
*/
|
|
1099
|
-
get
|
|
1100
|
-
|
|
1235
|
+
get outputAmount() {
|
|
1236
|
+
if (this._outputAmount) {
|
|
1237
|
+
return this._outputAmount;
|
|
1238
|
+
}
|
|
1239
|
+
const outputCurrency = this.swaps[0].outputAmount.currency;
|
|
1240
|
+
const totalOutputFromRoutes = this.swaps.map(({ outputAmount }) => outputAmount).reduce((total, cur) => total.add(cur), CurrencyAmount.fromRawAmount(outputCurrency, 0));
|
|
1241
|
+
this._outputAmount = totalOutputFromRoutes;
|
|
1242
|
+
return this._outputAmount;
|
|
1101
1243
|
}
|
|
1102
1244
|
/**
|
|
1103
|
-
*
|
|
1245
|
+
* The price expressed in terms of output amount/input amount.
|
|
1104
1246
|
*/
|
|
1105
|
-
get
|
|
1106
|
-
|
|
1107
|
-
this.
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
this.tickUpper,
|
|
1113
|
-
this.pool.sqrtRatioX96,
|
|
1114
|
-
this.liquidity
|
|
1115
|
-
)
|
|
1116
|
-
);
|
|
1117
|
-
}
|
|
1118
|
-
return this._token0Amount;
|
|
1119
|
-
}
|
|
1120
|
-
/**
|
|
1121
|
-
* Returns the amount of token1 that this position's liquidity could be burned for at the current pool price
|
|
1122
|
-
*/
|
|
1123
|
-
get amount1() {
|
|
1124
|
-
if (this._token1Amount === null) {
|
|
1125
|
-
this._token1Amount = CurrencyAmount.fromRawAmount(
|
|
1126
|
-
this.pool.token1,
|
|
1127
|
-
PositionMath.getToken1Amount(
|
|
1128
|
-
this.pool.tickCurrent,
|
|
1129
|
-
this.tickLower,
|
|
1130
|
-
this.tickUpper,
|
|
1131
|
-
this.pool.sqrtRatioX96,
|
|
1132
|
-
this.liquidity
|
|
1133
|
-
)
|
|
1134
|
-
);
|
|
1135
|
-
}
|
|
1136
|
-
return this._token1Amount;
|
|
1247
|
+
get executionPrice() {
|
|
1248
|
+
return this._executionPrice ?? (this._executionPrice = new Price(
|
|
1249
|
+
this.inputAmount.currency,
|
|
1250
|
+
this.outputAmount.currency,
|
|
1251
|
+
this.inputAmount.quotient,
|
|
1252
|
+
this.outputAmount.quotient
|
|
1253
|
+
));
|
|
1137
1254
|
}
|
|
1138
1255
|
/**
|
|
1139
|
-
* Returns the
|
|
1140
|
-
* @param slippageTolerance The amount by which the price can 'slip' before the transaction will revert
|
|
1141
|
-
* @returns The sqrt ratios after slippage
|
|
1256
|
+
* Returns the percent difference between the route's mid price and the price impact
|
|
1142
1257
|
*/
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
let sqrtRatioX96Lower = encodeSqrtRatioX96(priceLower.numerator, priceLower.denominator);
|
|
1147
|
-
if (sqrtRatioX96Lower <= TickMath.MIN_SQRT_RATIO) {
|
|
1148
|
-
sqrtRatioX96Lower = TickMath.MIN_SQRT_RATIO + 1n;
|
|
1258
|
+
get priceImpact() {
|
|
1259
|
+
if (this._priceImpact) {
|
|
1260
|
+
return this._priceImpact;
|
|
1149
1261
|
}
|
|
1150
|
-
let
|
|
1151
|
-
|
|
1152
|
-
|
|
1262
|
+
let spotOutputAmount = CurrencyAmount.fromRawAmount(this.outputAmount.currency, 0);
|
|
1263
|
+
for (const { route, inputAmount } of this.swaps) {
|
|
1264
|
+
const { midPrice } = route;
|
|
1265
|
+
spotOutputAmount = spotOutputAmount.add(midPrice.quote(inputAmount));
|
|
1153
1266
|
}
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
};
|
|
1267
|
+
const priceImpact = spotOutputAmount.subtract(this.outputAmount).divide(spotOutputAmount);
|
|
1268
|
+
this._priceImpact = new Percent$1(priceImpact.numerator, priceImpact.denominator);
|
|
1269
|
+
return this._priceImpact;
|
|
1158
1270
|
}
|
|
1159
1271
|
/**
|
|
1160
|
-
*
|
|
1161
|
-
*
|
|
1162
|
-
* @
|
|
1163
|
-
* @
|
|
1272
|
+
* Constructs an exact in trade with the given amount in and route
|
|
1273
|
+
* @template TInput The input token, either Ether or an ERC-20
|
|
1274
|
+
* @template TOutput The output token, either Ether or an ERC-20
|
|
1275
|
+
* @param route The route of the exact in trade
|
|
1276
|
+
* @param amountIn The amount being passed in
|
|
1277
|
+
* @returns The exact in trade
|
|
1164
1278
|
*/
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
const poolLower = new Pool(
|
|
1168
|
-
this.pool.token0,
|
|
1169
|
-
this.pool.token1,
|
|
1170
|
-
this.pool.fee,
|
|
1171
|
-
sqrtRatioX96Lower,
|
|
1172
|
-
0,
|
|
1173
|
-
TickMath.getTickAtSqrtRatio(sqrtRatioX96Lower)
|
|
1174
|
-
);
|
|
1175
|
-
const poolUpper = new Pool(
|
|
1176
|
-
this.pool.token0,
|
|
1177
|
-
this.pool.token1,
|
|
1178
|
-
this.pool.fee,
|
|
1179
|
-
sqrtRatioX96Upper,
|
|
1180
|
-
0,
|
|
1181
|
-
TickMath.getTickAtSqrtRatio(sqrtRatioX96Upper)
|
|
1182
|
-
);
|
|
1183
|
-
const positionThatWillBeCreated = Position.fromAmounts({
|
|
1184
|
-
pool: this.pool,
|
|
1185
|
-
tickLower: this.tickLower,
|
|
1186
|
-
tickUpper: this.tickUpper,
|
|
1187
|
-
...this.mintAmounts,
|
|
1188
|
-
// the mint amounts are what will be passed as calldata
|
|
1189
|
-
useFullPrecision: false
|
|
1190
|
-
});
|
|
1191
|
-
const { amount0 } = new Position({
|
|
1192
|
-
pool: poolUpper,
|
|
1193
|
-
liquidity: positionThatWillBeCreated.liquidity,
|
|
1194
|
-
tickLower: this.tickLower,
|
|
1195
|
-
tickUpper: this.tickUpper
|
|
1196
|
-
}).mintAmounts;
|
|
1197
|
-
const { amount1 } = new Position({
|
|
1198
|
-
pool: poolLower,
|
|
1199
|
-
liquidity: positionThatWillBeCreated.liquidity,
|
|
1200
|
-
tickLower: this.tickLower,
|
|
1201
|
-
tickUpper: this.tickUpper
|
|
1202
|
-
}).mintAmounts;
|
|
1203
|
-
return { amount0, amount1 };
|
|
1279
|
+
static async exactIn(route, amountIn) {
|
|
1280
|
+
return Trade.fromRoute(route, amountIn, TradeType.EXACT_INPUT);
|
|
1204
1281
|
}
|
|
1205
1282
|
/**
|
|
1206
|
-
*
|
|
1207
|
-
*
|
|
1208
|
-
* @
|
|
1209
|
-
* @
|
|
1283
|
+
* Constructs an exact out trade with the given amount out and route
|
|
1284
|
+
* @template TInput The input token, either Ether or an ERC-20
|
|
1285
|
+
* @template TOutput The output token, either Ether or an ERC-20
|
|
1286
|
+
* @param route The route of the exact out trade
|
|
1287
|
+
* @param amountOut The amount returned by the trade
|
|
1288
|
+
* @returns The exact out trade
|
|
1210
1289
|
*/
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
const poolLower = new Pool(
|
|
1214
|
-
this.pool.token0,
|
|
1215
|
-
this.pool.token1,
|
|
1216
|
-
this.pool.fee,
|
|
1217
|
-
sqrtRatioX96Lower,
|
|
1218
|
-
0,
|
|
1219
|
-
TickMath.getTickAtSqrtRatio(sqrtRatioX96Lower)
|
|
1220
|
-
);
|
|
1221
|
-
const poolUpper = new Pool(
|
|
1222
|
-
this.pool.token0,
|
|
1223
|
-
this.pool.token1,
|
|
1224
|
-
this.pool.fee,
|
|
1225
|
-
sqrtRatioX96Upper,
|
|
1226
|
-
0,
|
|
1227
|
-
TickMath.getTickAtSqrtRatio(sqrtRatioX96Upper)
|
|
1228
|
-
);
|
|
1229
|
-
const { amount0 } = new Position({
|
|
1230
|
-
pool: poolUpper,
|
|
1231
|
-
liquidity: this.liquidity,
|
|
1232
|
-
tickLower: this.tickLower,
|
|
1233
|
-
tickUpper: this.tickUpper
|
|
1234
|
-
});
|
|
1235
|
-
const { amount1 } = new Position({
|
|
1236
|
-
pool: poolLower,
|
|
1237
|
-
liquidity: this.liquidity,
|
|
1238
|
-
tickLower: this.tickLower,
|
|
1239
|
-
tickUpper: this.tickUpper
|
|
1240
|
-
});
|
|
1241
|
-
return { amount0: amount0.quotient, amount1: amount1.quotient };
|
|
1290
|
+
static async exactOut(route, amountOut) {
|
|
1291
|
+
return Trade.fromRoute(route, amountOut, TradeType.EXACT_OUTPUT);
|
|
1242
1292
|
}
|
|
1243
1293
|
/**
|
|
1244
|
-
*
|
|
1245
|
-
*
|
|
1294
|
+
* Constructs a trade by simulating swaps through the given route
|
|
1295
|
+
* @template TInput The input token, either Ether or an ERC-20.
|
|
1296
|
+
* @template TOutput The output token, either Ether or an ERC-20.
|
|
1297
|
+
* @template TTradeType The type of the trade, either exact in or exact out.
|
|
1298
|
+
* @param route route to swap through
|
|
1299
|
+
* @param amount the amount specified, either input or output, depending on tradeType
|
|
1300
|
+
* @param tradeType whether the trade is an exact input or exact output swap
|
|
1301
|
+
* @returns The route
|
|
1246
1302
|
*/
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
};
|
|
1303
|
+
static async fromRoute(route, amount, tradeType) {
|
|
1304
|
+
const amounts = new Array(route.tokenPath.length);
|
|
1305
|
+
let inputAmount;
|
|
1306
|
+
let outputAmount;
|
|
1307
|
+
if (tradeType === TradeType.EXACT_INPUT) {
|
|
1308
|
+
invariant9(amount.currency.equals(route.input), "INPUT");
|
|
1309
|
+
amounts[0] = amount.wrapped;
|
|
1310
|
+
for (let i = 0; i < route.tokenPath.length - 1; i++) {
|
|
1311
|
+
const pool = route.pools[i];
|
|
1312
|
+
const [outputAmount2] = await pool.getOutputAmount(amounts[i]);
|
|
1313
|
+
amounts[i + 1] = outputAmount2;
|
|
1259
1314
|
}
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
)
|
|
1274
|
-
};
|
|
1315
|
+
inputAmount = CurrencyAmount.fromFractionalAmount(route.input, amount.numerator, amount.denominator);
|
|
1316
|
+
outputAmount = CurrencyAmount.fromFractionalAmount(
|
|
1317
|
+
route.output,
|
|
1318
|
+
amounts[amounts.length - 1].numerator,
|
|
1319
|
+
amounts[amounts.length - 1].denominator
|
|
1320
|
+
);
|
|
1321
|
+
} else {
|
|
1322
|
+
invariant9(amount.currency.equals(route.output), "OUTPUT");
|
|
1323
|
+
amounts[amounts.length - 1] = amount.wrapped;
|
|
1324
|
+
for (let i = route.tokenPath.length - 1; i > 0; i--) {
|
|
1325
|
+
const pool = route.pools[i - 1];
|
|
1326
|
+
const [inputAmount2] = await pool.getInputAmount(amounts[i]);
|
|
1327
|
+
amounts[i - 1] = inputAmount2;
|
|
1275
1328
|
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
amount1: SqrtPriceMath.getAmount1Delta(
|
|
1279
|
-
TickMath.getSqrtRatioAtTick(this.tickLower),
|
|
1280
|
-
TickMath.getSqrtRatioAtTick(this.tickUpper),
|
|
1281
|
-
this.liquidity,
|
|
1282
|
-
true
|
|
1283
|
-
)
|
|
1284
|
-
};
|
|
1329
|
+
inputAmount = CurrencyAmount.fromFractionalAmount(route.input, amounts[0].numerator, amounts[0].denominator);
|
|
1330
|
+
outputAmount = CurrencyAmount.fromFractionalAmount(route.output, amount.numerator, amount.denominator);
|
|
1285
1331
|
}
|
|
1286
|
-
return
|
|
1332
|
+
return new Trade({
|
|
1333
|
+
routes: [{ inputAmount, outputAmount, route }],
|
|
1334
|
+
tradeType
|
|
1335
|
+
});
|
|
1287
1336
|
}
|
|
1288
1337
|
/**
|
|
1289
|
-
*
|
|
1290
|
-
*
|
|
1291
|
-
* @
|
|
1292
|
-
* @
|
|
1293
|
-
* @
|
|
1294
|
-
* @param
|
|
1295
|
-
* @param
|
|
1296
|
-
* @
|
|
1297
|
-
* not what core can theoretically support
|
|
1298
|
-
* @returns The amount of liquidity for the position
|
|
1299
|
-
*/
|
|
1300
|
-
static fromAmounts({
|
|
1301
|
-
pool,
|
|
1302
|
-
tickLower,
|
|
1303
|
-
tickUpper,
|
|
1304
|
-
amount0,
|
|
1305
|
-
amount1,
|
|
1306
|
-
useFullPrecision
|
|
1307
|
-
}) {
|
|
1308
|
-
const sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickLower);
|
|
1309
|
-
const sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickUpper);
|
|
1310
|
-
return new Position({
|
|
1311
|
-
pool,
|
|
1312
|
-
tickLower,
|
|
1313
|
-
tickUpper,
|
|
1314
|
-
liquidity: maxLiquidityForAmounts(
|
|
1315
|
-
pool.sqrtRatioX96,
|
|
1316
|
-
sqrtRatioAX96,
|
|
1317
|
-
sqrtRatioBX96,
|
|
1318
|
-
amount0,
|
|
1319
|
-
amount1,
|
|
1320
|
-
useFullPrecision
|
|
1321
|
-
)
|
|
1322
|
-
});
|
|
1323
|
-
}
|
|
1324
|
-
/**
|
|
1325
|
-
* Computes a position with the maximum amount of liquidity received for a given amount of token0, assuming an unlimited amount of token1
|
|
1326
|
-
* @param pool The pool for which the position is created
|
|
1327
|
-
* @param tickLower The lower tick
|
|
1328
|
-
* @param tickUpper The upper tick
|
|
1329
|
-
* @param amount0 The desired amount of token0
|
|
1330
|
-
* @param useFullPrecision If true, liquidity will be maximized according to what the router can calculate,
|
|
1331
|
-
* not what core can theoretically support
|
|
1332
|
-
* @returns The position
|
|
1333
|
-
*/
|
|
1334
|
-
static fromAmount0({
|
|
1335
|
-
pool,
|
|
1336
|
-
tickLower,
|
|
1337
|
-
tickUpper,
|
|
1338
|
-
amount0,
|
|
1339
|
-
useFullPrecision
|
|
1340
|
-
}) {
|
|
1341
|
-
return Position.fromAmounts({ pool, tickLower, tickUpper, amount0, amount1: MaxUint256, useFullPrecision });
|
|
1342
|
-
}
|
|
1343
|
-
/**
|
|
1344
|
-
* Computes a position with the maximum amount of liquidity received for a given amount of token1, assuming an unlimited amount of token0
|
|
1345
|
-
* @param pool The pool for which the position is created
|
|
1346
|
-
* @param tickLower The lower tick
|
|
1347
|
-
* @param tickUpper The upper tick
|
|
1348
|
-
* @param amount1 The desired amount of token1
|
|
1349
|
-
* @returns The position
|
|
1350
|
-
*/
|
|
1351
|
-
static fromAmount1({
|
|
1352
|
-
pool,
|
|
1353
|
-
tickLower,
|
|
1354
|
-
tickUpper,
|
|
1355
|
-
amount1
|
|
1356
|
-
}) {
|
|
1357
|
-
return Position.fromAmounts({ pool, tickLower, tickUpper, amount0: MaxUint256, amount1, useFullPrecision: true });
|
|
1358
|
-
}
|
|
1359
|
-
};
|
|
1360
|
-
var Route = class {
|
|
1361
|
-
/**
|
|
1362
|
-
* Creates an instance of route.
|
|
1363
|
-
* @param pools An array of `Pool` objects, ordered by the route the swap will take
|
|
1364
|
-
* @param input The input token
|
|
1365
|
-
* @param output The output token
|
|
1366
|
-
*/
|
|
1367
|
-
constructor(pools, input, output) {
|
|
1368
|
-
this._midPrice = null;
|
|
1369
|
-
invariant11(pools.length > 0, "POOLS");
|
|
1370
|
-
const { chainId } = pools[0];
|
|
1371
|
-
const allOnSameChain = pools.every((pool) => pool.chainId === chainId);
|
|
1372
|
-
invariant11(allOnSameChain, "CHAIN_IDS");
|
|
1373
|
-
const wrappedInput = input.wrapped;
|
|
1374
|
-
invariant11(pools[0].involvesToken(wrappedInput), "INPUT");
|
|
1375
|
-
invariant11(pools[pools.length - 1].involvesToken(output.wrapped), "OUTPUT");
|
|
1376
|
-
const tokenPath = [wrappedInput];
|
|
1377
|
-
for (const [i, pool] of pools.entries()) {
|
|
1378
|
-
const currentInputToken = tokenPath[i];
|
|
1379
|
-
invariant11(currentInputToken.equals(pool.token0) || currentInputToken.equals(pool.token1), "PATH");
|
|
1380
|
-
const nextToken = currentInputToken.equals(pool.token0) ? pool.token1 : pool.token0;
|
|
1381
|
-
tokenPath.push(nextToken);
|
|
1382
|
-
}
|
|
1383
|
-
this.pools = pools;
|
|
1384
|
-
this.tokenPath = tokenPath;
|
|
1385
|
-
this.input = input;
|
|
1386
|
-
this.output = output ?? tokenPath[tokenPath.length - 1];
|
|
1387
|
-
}
|
|
1388
|
-
get chainId() {
|
|
1389
|
-
return this.pools[0].chainId;
|
|
1390
|
-
}
|
|
1391
|
-
/**
|
|
1392
|
-
* Returns the mid price of the route
|
|
1393
|
-
*/
|
|
1394
|
-
get midPrice() {
|
|
1395
|
-
if (this._midPrice !== null)
|
|
1396
|
-
return this._midPrice;
|
|
1397
|
-
const { price } = this.pools.slice(1).reduce(
|
|
1398
|
-
({ nextInput, price: price2 }, pool) => {
|
|
1399
|
-
return nextInput.equals(pool.token0) ? {
|
|
1400
|
-
nextInput: pool.token1,
|
|
1401
|
-
price: price2.multiply(pool.token0Price)
|
|
1402
|
-
} : {
|
|
1403
|
-
nextInput: pool.token0,
|
|
1404
|
-
price: price2.multiply(pool.token1Price)
|
|
1405
|
-
};
|
|
1406
|
-
},
|
|
1407
|
-
this.pools[0].token0.equals(this.input.wrapped) ? {
|
|
1408
|
-
nextInput: this.pools[0].token1,
|
|
1409
|
-
price: this.pools[0].token0Price
|
|
1410
|
-
} : {
|
|
1411
|
-
nextInput: this.pools[0].token0,
|
|
1412
|
-
price: this.pools[0].token1Price
|
|
1413
|
-
}
|
|
1414
|
-
);
|
|
1415
|
-
return this._midPrice = new Price$1(this.input, this.output, price.denominator, price.numerator);
|
|
1416
|
-
}
|
|
1417
|
-
};
|
|
1418
|
-
function tradeComparator(a, b) {
|
|
1419
|
-
invariant11(a.inputAmount.currency.equals(b.inputAmount.currency), "INPUT_CURRENCY");
|
|
1420
|
-
invariant11(a.outputAmount.currency.equals(b.outputAmount.currency), "OUTPUT_CURRENCY");
|
|
1421
|
-
if (a.outputAmount.equalTo(b.outputAmount)) {
|
|
1422
|
-
if (a.inputAmount.equalTo(b.inputAmount)) {
|
|
1423
|
-
const aHops = a.swaps.reduce((total, cur) => total + cur.route.tokenPath.length, 0);
|
|
1424
|
-
const bHops = b.swaps.reduce((total, cur) => total + cur.route.tokenPath.length, 0);
|
|
1425
|
-
return aHops - bHops;
|
|
1426
|
-
}
|
|
1427
|
-
if (a.inputAmount.lessThan(b.inputAmount)) {
|
|
1428
|
-
return -1;
|
|
1429
|
-
}
|
|
1430
|
-
return 1;
|
|
1431
|
-
}
|
|
1432
|
-
if (a.outputAmount.lessThan(b.outputAmount)) {
|
|
1433
|
-
return 1;
|
|
1434
|
-
}
|
|
1435
|
-
return -1;
|
|
1436
|
-
}
|
|
1437
|
-
var Trade = class {
|
|
1438
|
-
/**
|
|
1439
|
-
* @deprecated Deprecated in favor of 'swaps' property. If the trade consists of multiple routes
|
|
1440
|
-
* this will return an error.
|
|
1441
|
-
*
|
|
1442
|
-
* When the trade consists of just a single route, this returns the route of the trade,
|
|
1443
|
-
* i.e. which pools the trade goes through.
|
|
1444
|
-
*/
|
|
1445
|
-
get route() {
|
|
1446
|
-
invariant11(this.swaps.length == 1, "MULTIPLE_ROUTES");
|
|
1447
|
-
return this.swaps[0].route;
|
|
1448
|
-
}
|
|
1449
|
-
/**
|
|
1450
|
-
* The input amount for the trade assuming no slippage.
|
|
1451
|
-
*/
|
|
1452
|
-
get inputAmount() {
|
|
1453
|
-
if (this._inputAmount) {
|
|
1454
|
-
return this._inputAmount;
|
|
1455
|
-
}
|
|
1456
|
-
const inputCurrency = this.swaps[0].inputAmount.currency;
|
|
1457
|
-
const totalInputFromRoutes = this.swaps.map(({ inputAmount }) => inputAmount).reduce((total, cur) => total.add(cur), CurrencyAmount.fromRawAmount(inputCurrency, 0));
|
|
1458
|
-
this._inputAmount = totalInputFromRoutes;
|
|
1459
|
-
return this._inputAmount;
|
|
1460
|
-
}
|
|
1461
|
-
/**
|
|
1462
|
-
* The output amount for the trade assuming no slippage.
|
|
1463
|
-
*/
|
|
1464
|
-
get outputAmount() {
|
|
1465
|
-
if (this._outputAmount) {
|
|
1466
|
-
return this._outputAmount;
|
|
1467
|
-
}
|
|
1468
|
-
const outputCurrency = this.swaps[0].outputAmount.currency;
|
|
1469
|
-
const totalOutputFromRoutes = this.swaps.map(({ outputAmount }) => outputAmount).reduce((total, cur) => total.add(cur), CurrencyAmount.fromRawAmount(outputCurrency, 0));
|
|
1470
|
-
this._outputAmount = totalOutputFromRoutes;
|
|
1471
|
-
return this._outputAmount;
|
|
1472
|
-
}
|
|
1473
|
-
/**
|
|
1474
|
-
* The price expressed in terms of output amount/input amount.
|
|
1475
|
-
*/
|
|
1476
|
-
get executionPrice() {
|
|
1477
|
-
return this._executionPrice ?? (this._executionPrice = new Price(
|
|
1478
|
-
this.inputAmount.currency,
|
|
1479
|
-
this.outputAmount.currency,
|
|
1480
|
-
this.inputAmount.quotient,
|
|
1481
|
-
this.outputAmount.quotient
|
|
1482
|
-
));
|
|
1483
|
-
}
|
|
1484
|
-
/**
|
|
1485
|
-
* Returns the percent difference between the route's mid price and the price impact
|
|
1486
|
-
*/
|
|
1487
|
-
get priceImpact() {
|
|
1488
|
-
if (this._priceImpact) {
|
|
1489
|
-
return this._priceImpact;
|
|
1490
|
-
}
|
|
1491
|
-
let spotOutputAmount = CurrencyAmount.fromRawAmount(this.outputAmount.currency, 0);
|
|
1492
|
-
for (const { route, inputAmount } of this.swaps) {
|
|
1493
|
-
const { midPrice } = route;
|
|
1494
|
-
spotOutputAmount = spotOutputAmount.add(midPrice.quote(inputAmount));
|
|
1495
|
-
}
|
|
1496
|
-
const priceImpact = spotOutputAmount.subtract(this.outputAmount).divide(spotOutputAmount);
|
|
1497
|
-
this._priceImpact = new Percent$1(priceImpact.numerator, priceImpact.denominator);
|
|
1498
|
-
return this._priceImpact;
|
|
1499
|
-
}
|
|
1500
|
-
/**
|
|
1501
|
-
* Constructs an exact in trade with the given amount in and route
|
|
1502
|
-
* @template TInput The input token, either Ether or an ERC-20
|
|
1503
|
-
* @template TOutput The output token, either Ether or an ERC-20
|
|
1504
|
-
* @param route The route of the exact in trade
|
|
1505
|
-
* @param amountIn The amount being passed in
|
|
1506
|
-
* @returns The exact in trade
|
|
1507
|
-
*/
|
|
1508
|
-
static async exactIn(route, amountIn) {
|
|
1509
|
-
return Trade.fromRoute(route, amountIn, TradeType.EXACT_INPUT);
|
|
1510
|
-
}
|
|
1511
|
-
/**
|
|
1512
|
-
* Constructs an exact out trade with the given amount out and route
|
|
1513
|
-
* @template TInput The input token, either Ether or an ERC-20
|
|
1514
|
-
* @template TOutput The output token, either Ether or an ERC-20
|
|
1515
|
-
* @param route The route of the exact out trade
|
|
1516
|
-
* @param amountOut The amount returned by the trade
|
|
1517
|
-
* @returns The exact out trade
|
|
1518
|
-
*/
|
|
1519
|
-
static async exactOut(route, amountOut) {
|
|
1520
|
-
return Trade.fromRoute(route, amountOut, TradeType.EXACT_OUTPUT);
|
|
1521
|
-
}
|
|
1522
|
-
/**
|
|
1523
|
-
* Constructs a trade by simulating swaps through the given route
|
|
1524
|
-
* @template TInput The input token, either Ether or an ERC-20.
|
|
1525
|
-
* @template TOutput The output token, either Ether or an ERC-20.
|
|
1526
|
-
* @template TTradeType The type of the trade, either exact in or exact out.
|
|
1527
|
-
* @param route route to swap through
|
|
1528
|
-
* @param amount the amount specified, either input or output, depending on tradeType
|
|
1529
|
-
* @param tradeType whether the trade is an exact input or exact output swap
|
|
1530
|
-
* @returns The route
|
|
1531
|
-
*/
|
|
1532
|
-
static async fromRoute(route, amount, tradeType) {
|
|
1533
|
-
const amounts = new Array(route.tokenPath.length);
|
|
1534
|
-
let inputAmount;
|
|
1535
|
-
let outputAmount;
|
|
1536
|
-
if (tradeType === TradeType.EXACT_INPUT) {
|
|
1537
|
-
invariant11(amount.currency.equals(route.input), "INPUT");
|
|
1538
|
-
amounts[0] = amount.wrapped;
|
|
1539
|
-
for (let i = 0; i < route.tokenPath.length - 1; i++) {
|
|
1540
|
-
const pool = route.pools[i];
|
|
1541
|
-
const [outputAmount2] = await pool.getOutputAmount(amounts[i]);
|
|
1542
|
-
amounts[i + 1] = outputAmount2;
|
|
1543
|
-
}
|
|
1544
|
-
inputAmount = CurrencyAmount.fromFractionalAmount(route.input, amount.numerator, amount.denominator);
|
|
1545
|
-
outputAmount = CurrencyAmount.fromFractionalAmount(
|
|
1546
|
-
route.output,
|
|
1547
|
-
amounts[amounts.length - 1].numerator,
|
|
1548
|
-
amounts[amounts.length - 1].denominator
|
|
1549
|
-
);
|
|
1550
|
-
} else {
|
|
1551
|
-
invariant11(amount.currency.equals(route.output), "OUTPUT");
|
|
1552
|
-
amounts[amounts.length - 1] = amount.wrapped;
|
|
1553
|
-
for (let i = route.tokenPath.length - 1; i > 0; i--) {
|
|
1554
|
-
const pool = route.pools[i - 1];
|
|
1555
|
-
const [inputAmount2] = await pool.getInputAmount(amounts[i]);
|
|
1556
|
-
amounts[i - 1] = inputAmount2;
|
|
1557
|
-
}
|
|
1558
|
-
inputAmount = CurrencyAmount.fromFractionalAmount(route.input, amounts[0].numerator, amounts[0].denominator);
|
|
1559
|
-
outputAmount = CurrencyAmount.fromFractionalAmount(route.output, amount.numerator, amount.denominator);
|
|
1560
|
-
}
|
|
1561
|
-
return new Trade({
|
|
1562
|
-
routes: [{ inputAmount, outputAmount, route }],
|
|
1563
|
-
tradeType
|
|
1564
|
-
});
|
|
1565
|
-
}
|
|
1566
|
-
/**
|
|
1567
|
-
* Constructs a trade from routes by simulating swaps
|
|
1568
|
-
*
|
|
1569
|
-
* @template TInput The input token, either Ether or an ERC-20.
|
|
1570
|
-
* @template TOutput The output token, either Ether or an ERC-20.
|
|
1571
|
-
* @template TTradeType The type of the trade, either exact in or exact out.
|
|
1572
|
-
* @param routes the routes to swap through and how much of the amount should be routed through each
|
|
1573
|
-
* @param tradeType whether the trade is an exact input or exact output swap
|
|
1574
|
-
* @returns The trade
|
|
1338
|
+
* Constructs a trade from routes by simulating swaps
|
|
1339
|
+
*
|
|
1340
|
+
* @template TInput The input token, either Ether or an ERC-20.
|
|
1341
|
+
* @template TOutput The output token, either Ether or an ERC-20.
|
|
1342
|
+
* @template TTradeType The type of the trade, either exact in or exact out.
|
|
1343
|
+
* @param routes the routes to swap through and how much of the amount should be routed through each
|
|
1344
|
+
* @param tradeType whether the trade is an exact input or exact output swap
|
|
1345
|
+
* @returns The trade
|
|
1575
1346
|
*/
|
|
1576
1347
|
static async fromRoutes(routes, tradeType) {
|
|
1577
1348
|
const populatedRoutes = [];
|
|
@@ -1580,7 +1351,7 @@ var Trade = class {
|
|
|
1580
1351
|
let inputAmount;
|
|
1581
1352
|
let outputAmount;
|
|
1582
1353
|
if (tradeType === TradeType.EXACT_INPUT) {
|
|
1583
|
-
|
|
1354
|
+
invariant9(amount.currency.equals(route.input), "INPUT");
|
|
1584
1355
|
inputAmount = CurrencyAmount.fromFractionalAmount(route.input, amount.numerator, amount.denominator);
|
|
1585
1356
|
amounts[0] = CurrencyAmount.fromFractionalAmount(route.input.wrapped, amount.numerator, amount.denominator);
|
|
1586
1357
|
for (let i = 0; i < route.tokenPath.length - 1; i++) {
|
|
@@ -1594,7 +1365,7 @@ var Trade = class {
|
|
|
1594
1365
|
amounts[amounts.length - 1].denominator
|
|
1595
1366
|
);
|
|
1596
1367
|
} else {
|
|
1597
|
-
|
|
1368
|
+
invariant9(amount.currency.equals(route.output), "OUTPUT");
|
|
1598
1369
|
outputAmount = CurrencyAmount.fromFractionalAmount(route.output, amount.numerator, amount.denominator);
|
|
1599
1370
|
amounts[amounts.length - 1] = CurrencyAmount.fromFractionalAmount(
|
|
1600
1371
|
route.output.wrapped,
|
|
@@ -1659,11 +1430,11 @@ var Trade = class {
|
|
|
1659
1430
|
}) {
|
|
1660
1431
|
const inputCurrency = routes[0].inputAmount.currency;
|
|
1661
1432
|
const outputCurrency = routes[0].outputAmount.currency;
|
|
1662
|
-
|
|
1433
|
+
invariant9(
|
|
1663
1434
|
routes.every(({ route }) => inputCurrency.wrapped.equals(route.input.wrapped)),
|
|
1664
1435
|
"INPUT_CURRENCY_MATCH"
|
|
1665
1436
|
);
|
|
1666
|
-
|
|
1437
|
+
invariant9(
|
|
1667
1438
|
routes.every(({ route }) => outputCurrency.wrapped.equals(route.output.wrapped)),
|
|
1668
1439
|
"OUTPUT_CURRENCY_MATCH"
|
|
1669
1440
|
);
|
|
@@ -1674,7 +1445,7 @@ var Trade = class {
|
|
|
1674
1445
|
poolAddressSet.add(Pool.getAddress(pool.token0, pool.token1, pool.fee));
|
|
1675
1446
|
}
|
|
1676
1447
|
}
|
|
1677
|
-
|
|
1448
|
+
invariant9(numPools == poolAddressSet.size, "POOLS_DUPLICATED");
|
|
1678
1449
|
this.swaps = routes;
|
|
1679
1450
|
this.tradeType = tradeType;
|
|
1680
1451
|
}
|
|
@@ -1684,169 +1455,473 @@ var Trade = class {
|
|
|
1684
1455
|
* @returns The amount out
|
|
1685
1456
|
*/
|
|
1686
1457
|
minimumAmountOut(slippageTolerance, amountOut = this.outputAmount) {
|
|
1687
|
-
|
|
1458
|
+
invariant9(!slippageTolerance.lessThan(ZERO), "SLIPPAGE_TOLERANCE");
|
|
1688
1459
|
if (this.tradeType === TradeType.EXACT_OUTPUT) {
|
|
1689
1460
|
return amountOut;
|
|
1690
1461
|
}
|
|
1691
1462
|
const slippageAdjustedAmountOut = new Fraction(ONE).add(slippageTolerance).invert().multiply(amountOut.quotient).quotient;
|
|
1692
1463
|
return CurrencyAmount.fromRawAmount(amountOut.currency, slippageAdjustedAmountOut);
|
|
1693
1464
|
}
|
|
1694
|
-
/**
|
|
1695
|
-
* Get the maximum amount in that can be spent via this trade for the given slippage tolerance
|
|
1696
|
-
* @param slippageTolerance The tolerance of unfavorable slippage from the execution price of this trade
|
|
1697
|
-
* @returns The amount in
|
|
1698
|
-
*/
|
|
1699
|
-
maximumAmountIn(slippageTolerance, amountIn = this.inputAmount) {
|
|
1700
|
-
|
|
1701
|
-
if (this.tradeType === TradeType.EXACT_INPUT) {
|
|
1702
|
-
return amountIn;
|
|
1465
|
+
/**
|
|
1466
|
+
* Get the maximum amount in that can be spent via this trade for the given slippage tolerance
|
|
1467
|
+
* @param slippageTolerance The tolerance of unfavorable slippage from the execution price of this trade
|
|
1468
|
+
* @returns The amount in
|
|
1469
|
+
*/
|
|
1470
|
+
maximumAmountIn(slippageTolerance, amountIn = this.inputAmount) {
|
|
1471
|
+
invariant9(!slippageTolerance.lessThan(ZERO), "SLIPPAGE_TOLERANCE");
|
|
1472
|
+
if (this.tradeType === TradeType.EXACT_INPUT) {
|
|
1473
|
+
return amountIn;
|
|
1474
|
+
}
|
|
1475
|
+
const slippageAdjustedAmountIn = new Fraction(ONE).add(slippageTolerance).multiply(amountIn.quotient).quotient;
|
|
1476
|
+
return CurrencyAmount.fromRawAmount(amountIn.currency, slippageAdjustedAmountIn);
|
|
1477
|
+
}
|
|
1478
|
+
/**
|
|
1479
|
+
* Return the execution price after accounting for slippage tolerance
|
|
1480
|
+
* @param slippageTolerance the allowed tolerated slippage
|
|
1481
|
+
* @returns The execution price
|
|
1482
|
+
*/
|
|
1483
|
+
worstExecutionPrice(slippageTolerance) {
|
|
1484
|
+
return new Price(
|
|
1485
|
+
this.inputAmount.currency,
|
|
1486
|
+
this.outputAmount.currency,
|
|
1487
|
+
this.maximumAmountIn(slippageTolerance).quotient,
|
|
1488
|
+
this.minimumAmountOut(slippageTolerance).quotient
|
|
1489
|
+
);
|
|
1490
|
+
}
|
|
1491
|
+
/**
|
|
1492
|
+
* Given a list of pools, and a fixed amount in, returns the top `maxNumResults` trades that go from an input token
|
|
1493
|
+
* amount to an output token, making at most `maxHops` hops.
|
|
1494
|
+
* Note this does not consider aggregation, as routes are linear. It's possible a better route exists by splitting
|
|
1495
|
+
* the amount in among multiple routes.
|
|
1496
|
+
* @param pools the pools to consider in finding the best trade
|
|
1497
|
+
* @param nextAmountIn exact amount of input currency to spend
|
|
1498
|
+
* @param currencyOut the desired currency out
|
|
1499
|
+
* @param maxNumResults maximum number of results to return
|
|
1500
|
+
* @param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pool
|
|
1501
|
+
* @param currentPools used in recursion; the current list of pools
|
|
1502
|
+
* @param currencyAmountIn used in recursion; the original value of the currencyAmountIn parameter
|
|
1503
|
+
* @param bestTrades used in recursion; the current list of best trades
|
|
1504
|
+
* @returns The exact in trade
|
|
1505
|
+
*/
|
|
1506
|
+
static async bestTradeExactIn(pools, currencyAmountIn, currencyOut, { maxNumResults = 3, maxHops = 3 } = {}, currentPools = [], nextAmountIn = currencyAmountIn, bestTrades = []) {
|
|
1507
|
+
invariant9(pools.length > 0, "POOLS");
|
|
1508
|
+
invariant9(maxHops > 0, "MAX_HOPS");
|
|
1509
|
+
invariant9(currencyAmountIn === nextAmountIn || currentPools.length > 0, "INVALID_RECURSION");
|
|
1510
|
+
const amountIn = nextAmountIn.wrapped;
|
|
1511
|
+
const tokenOut = currencyOut.wrapped;
|
|
1512
|
+
for (let i = 0; i < pools.length; i++) {
|
|
1513
|
+
const pool = pools[i];
|
|
1514
|
+
if (!pool.token0.equals(amountIn.currency) && !pool.token1.equals(amountIn.currency))
|
|
1515
|
+
continue;
|
|
1516
|
+
let amountOut;
|
|
1517
|
+
try {
|
|
1518
|
+
const [result] = await pool.getOutputAmount(amountIn);
|
|
1519
|
+
amountOut = result;
|
|
1520
|
+
} catch (error) {
|
|
1521
|
+
if (error.isInsufficientInputAmountError) {
|
|
1522
|
+
continue;
|
|
1523
|
+
}
|
|
1524
|
+
throw error;
|
|
1525
|
+
}
|
|
1526
|
+
if (amountOut.currency.isToken && amountOut.currency.equals(tokenOut)) {
|
|
1527
|
+
sortedInsert(
|
|
1528
|
+
bestTrades,
|
|
1529
|
+
await Trade.fromRoute(
|
|
1530
|
+
new Route([...currentPools, pool], currencyAmountIn.currency, currencyOut),
|
|
1531
|
+
currencyAmountIn,
|
|
1532
|
+
TradeType.EXACT_INPUT
|
|
1533
|
+
),
|
|
1534
|
+
maxNumResults,
|
|
1535
|
+
tradeComparator
|
|
1536
|
+
);
|
|
1537
|
+
} else if (maxHops > 1 && pools.length > 1) {
|
|
1538
|
+
const poolsExcludingThisPool = pools.slice(0, i).concat(pools.slice(i + 1, pools.length));
|
|
1539
|
+
await Trade.bestTradeExactIn(
|
|
1540
|
+
poolsExcludingThisPool,
|
|
1541
|
+
currencyAmountIn,
|
|
1542
|
+
currencyOut,
|
|
1543
|
+
{
|
|
1544
|
+
maxNumResults,
|
|
1545
|
+
maxHops: maxHops - 1
|
|
1546
|
+
},
|
|
1547
|
+
[...currentPools, pool],
|
|
1548
|
+
amountOut,
|
|
1549
|
+
bestTrades
|
|
1550
|
+
);
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
return bestTrades;
|
|
1554
|
+
}
|
|
1555
|
+
/**
|
|
1556
|
+
* similar to the above method but instead targets a fixed output amount
|
|
1557
|
+
* given a list of pools, and a fixed amount out, returns the top `maxNumResults` trades that go from an input token
|
|
1558
|
+
* to an output token amount, making at most `maxHops` hops
|
|
1559
|
+
* note this does not consider aggregation, as routes are linear. it's possible a better route exists by splitting
|
|
1560
|
+
* the amount in among multiple routes.
|
|
1561
|
+
* @param pools the pools to consider in finding the best trade
|
|
1562
|
+
* @param currencyIn the currency to spend
|
|
1563
|
+
* @param currencyAmountOut the desired currency amount out
|
|
1564
|
+
* @param nextAmountOut the exact amount of currency out
|
|
1565
|
+
* @param maxNumResults maximum number of results to return
|
|
1566
|
+
* @param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pool
|
|
1567
|
+
* @param currentPools used in recursion; the current list of pools
|
|
1568
|
+
* @param bestTrades used in recursion; the current list of best trades
|
|
1569
|
+
* @returns The exact out trade
|
|
1570
|
+
*/
|
|
1571
|
+
static async bestTradeExactOut(pools, currencyIn, currencyAmountOut, { maxNumResults = 3, maxHops = 3 } = {}, currentPools = [], nextAmountOut = currencyAmountOut, bestTrades = []) {
|
|
1572
|
+
invariant9(pools.length > 0, "POOLS");
|
|
1573
|
+
invariant9(maxHops > 0, "MAX_HOPS");
|
|
1574
|
+
invariant9(currencyAmountOut === nextAmountOut || currentPools.length > 0, "INVALID_RECURSION");
|
|
1575
|
+
const amountOut = nextAmountOut.wrapped;
|
|
1576
|
+
const tokenIn = currencyIn.wrapped;
|
|
1577
|
+
for (let i = 0; i < pools.length; i++) {
|
|
1578
|
+
const pool = pools[i];
|
|
1579
|
+
if (!pool.token0.equals(amountOut.currency) && !pool.token1.equals(amountOut.currency))
|
|
1580
|
+
continue;
|
|
1581
|
+
let amountIn;
|
|
1582
|
+
try {
|
|
1583
|
+
const [result] = await pool.getInputAmount(amountOut);
|
|
1584
|
+
amountIn = result;
|
|
1585
|
+
} catch (error) {
|
|
1586
|
+
if (error.isInsufficientReservesError) {
|
|
1587
|
+
continue;
|
|
1588
|
+
}
|
|
1589
|
+
throw error;
|
|
1590
|
+
}
|
|
1591
|
+
if (amountIn.currency.equals(tokenIn)) {
|
|
1592
|
+
sortedInsert(
|
|
1593
|
+
bestTrades,
|
|
1594
|
+
await Trade.fromRoute(
|
|
1595
|
+
new Route([pool, ...currentPools], currencyIn, currencyAmountOut.currency),
|
|
1596
|
+
currencyAmountOut,
|
|
1597
|
+
TradeType.EXACT_OUTPUT
|
|
1598
|
+
),
|
|
1599
|
+
maxNumResults,
|
|
1600
|
+
tradeComparator
|
|
1601
|
+
);
|
|
1602
|
+
} else if (maxHops > 1 && pools.length > 1) {
|
|
1603
|
+
const poolsExcludingThisPool = pools.slice(0, i).concat(pools.slice(i + 1, pools.length));
|
|
1604
|
+
await Trade.bestTradeExactOut(
|
|
1605
|
+
poolsExcludingThisPool,
|
|
1606
|
+
currencyIn,
|
|
1607
|
+
currencyAmountOut,
|
|
1608
|
+
{
|
|
1609
|
+
maxNumResults,
|
|
1610
|
+
maxHops: maxHops - 1
|
|
1611
|
+
},
|
|
1612
|
+
[pool, ...currentPools],
|
|
1613
|
+
amountIn,
|
|
1614
|
+
bestTrades
|
|
1615
|
+
);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
return bestTrades;
|
|
1619
|
+
}
|
|
1620
|
+
};
|
|
1621
|
+
|
|
1622
|
+
// src/utils/calldata.ts
|
|
1623
|
+
function toHex(bigintIsh) {
|
|
1624
|
+
const bigInt = BigInt(bigintIsh);
|
|
1625
|
+
let hex = bigInt.toString(16);
|
|
1626
|
+
if (hex.length % 2 !== 0) {
|
|
1627
|
+
hex = `0${hex}`;
|
|
1628
|
+
}
|
|
1629
|
+
return `0x${hex}`;
|
|
1630
|
+
}
|
|
1631
|
+
function encodeRouteToPath(route, exactOutput) {
|
|
1632
|
+
const firstInputToken = route.input.wrapped;
|
|
1633
|
+
const { path, types } = route.pools.reduce(
|
|
1634
|
+
({ inputToken, path: path2, types: types2 }, pool, index) => {
|
|
1635
|
+
const outputToken = pool.token0.equals(inputToken) ? pool.token1 : pool.token0;
|
|
1636
|
+
if (index === 0) {
|
|
1637
|
+
return {
|
|
1638
|
+
inputToken: outputToken,
|
|
1639
|
+
types: ["address", "uint24", "address"],
|
|
1640
|
+
path: [inputToken.address, pool.fee, outputToken.address]
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
return {
|
|
1644
|
+
inputToken: outputToken,
|
|
1645
|
+
types: [...types2, "uint24", "address"],
|
|
1646
|
+
path: [...path2, pool.fee, outputToken.address]
|
|
1647
|
+
};
|
|
1648
|
+
},
|
|
1649
|
+
{ inputToken: firstInputToken, path: [], types: [] }
|
|
1650
|
+
);
|
|
1651
|
+
return exactOutput ? encodePacked(types.reverse(), path.reverse()) : encodePacked(types, path);
|
|
1652
|
+
}
|
|
1653
|
+
function nearestUsableTick(tick, tickSpacing) {
|
|
1654
|
+
invariant9(Number.isInteger(tick) && Number.isInteger(tickSpacing), "INTEGERS");
|
|
1655
|
+
invariant9(tickSpacing > 0, "TICK_SPACING");
|
|
1656
|
+
invariant9(tick >= TickMath.MIN_TICK && tick <= TickMath.MAX_TICK, "TICK_BOUND");
|
|
1657
|
+
const rounded = Math.round(tick / tickSpacing) * tickSpacing;
|
|
1658
|
+
if (rounded < TickMath.MIN_TICK)
|
|
1659
|
+
return rounded + tickSpacing;
|
|
1660
|
+
if (rounded > TickMath.MAX_TICK)
|
|
1661
|
+
return rounded - tickSpacing;
|
|
1662
|
+
return rounded;
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
// src/utils/position.ts
|
|
1666
|
+
var PositionLibrary = class {
|
|
1667
|
+
/**
|
|
1668
|
+
* Cannot be constructed.
|
|
1669
|
+
*/
|
|
1670
|
+
constructor() {
|
|
1671
|
+
}
|
|
1672
|
+
// replicates the portions of Position#update required to compute unaccounted fees
|
|
1673
|
+
static getTokensOwed(feeGrowthInside0LastX128, feeGrowthInside1LastX128, liquidity, feeGrowthInside0X128, feeGrowthInside1X128) {
|
|
1674
|
+
const tokensOwed0 = subIn256(feeGrowthInside0X128, feeGrowthInside0LastX128) * liquidity / Q128;
|
|
1675
|
+
const tokensOwed1 = subIn256(feeGrowthInside1X128, feeGrowthInside1LastX128) * liquidity / Q128;
|
|
1676
|
+
return [tokensOwed0, tokensOwed1];
|
|
1677
|
+
}
|
|
1678
|
+
};
|
|
1679
|
+
|
|
1680
|
+
// src/utils/tickLibrary.ts
|
|
1681
|
+
var Q256 = 2n ** 256n;
|
|
1682
|
+
function subIn256(x, y) {
|
|
1683
|
+
const difference = x - y;
|
|
1684
|
+
if (difference < ZERO) {
|
|
1685
|
+
return Q256 + difference;
|
|
1686
|
+
}
|
|
1687
|
+
return difference;
|
|
1688
|
+
}
|
|
1689
|
+
var TickLibrary = class {
|
|
1690
|
+
/**
|
|
1691
|
+
* Cannot be constructed.
|
|
1692
|
+
*/
|
|
1693
|
+
constructor() {
|
|
1694
|
+
}
|
|
1695
|
+
static getFeeGrowthInside(feeGrowthOutsideLower, feeGrowthOutsideUpper, tickLower, tickUpper, tickCurrent, feeGrowthGlobal0X128, feeGrowthGlobal1X128) {
|
|
1696
|
+
let feeGrowthBelow0X128;
|
|
1697
|
+
let feeGrowthBelow1X128;
|
|
1698
|
+
if (tickCurrent >= tickLower) {
|
|
1699
|
+
feeGrowthBelow0X128 = feeGrowthOutsideLower.feeGrowthOutside0X128;
|
|
1700
|
+
feeGrowthBelow1X128 = feeGrowthOutsideLower.feeGrowthOutside1X128;
|
|
1701
|
+
} else {
|
|
1702
|
+
feeGrowthBelow0X128 = subIn256(feeGrowthGlobal0X128, feeGrowthOutsideLower.feeGrowthOutside0X128);
|
|
1703
|
+
feeGrowthBelow1X128 = subIn256(feeGrowthGlobal1X128, feeGrowthOutsideLower.feeGrowthOutside1X128);
|
|
1704
|
+
}
|
|
1705
|
+
let feeGrowthAbove0X128;
|
|
1706
|
+
let feeGrowthAbove1X128;
|
|
1707
|
+
if (tickCurrent < tickUpper) {
|
|
1708
|
+
feeGrowthAbove0X128 = feeGrowthOutsideUpper.feeGrowthOutside0X128;
|
|
1709
|
+
feeGrowthAbove1X128 = feeGrowthOutsideUpper.feeGrowthOutside1X128;
|
|
1710
|
+
} else {
|
|
1711
|
+
feeGrowthAbove0X128 = subIn256(feeGrowthGlobal0X128, feeGrowthOutsideUpper.feeGrowthOutside0X128);
|
|
1712
|
+
feeGrowthAbove1X128 = subIn256(feeGrowthGlobal1X128, feeGrowthOutsideUpper.feeGrowthOutside1X128);
|
|
1713
|
+
}
|
|
1714
|
+
return [
|
|
1715
|
+
subIn256(subIn256(feeGrowthGlobal0X128, feeGrowthBelow0X128), feeGrowthAbove0X128),
|
|
1716
|
+
subIn256(subIn256(feeGrowthGlobal1X128, feeGrowthBelow1X128), feeGrowthAbove1X128)
|
|
1717
|
+
];
|
|
1718
|
+
}
|
|
1719
|
+
};
|
|
1720
|
+
function parseNumberToFraction(num, precision = 6) {
|
|
1721
|
+
if (Number.isNaN(num) || !Number.isFinite(num)) {
|
|
1722
|
+
return void 0;
|
|
1723
|
+
}
|
|
1724
|
+
const scalar = 10 ** precision;
|
|
1725
|
+
return new Fraction$1(BigInt(Math.floor(num * scalar)), BigInt(scalar));
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
// src/utils/feeCalculator.ts
|
|
1729
|
+
var FeeCalculator = {
|
|
1730
|
+
getEstimatedLPFee,
|
|
1731
|
+
getEstimatedLPFeeByAmounts,
|
|
1732
|
+
getLiquidityFromTick,
|
|
1733
|
+
getLiquidityFromSqrtRatioX96,
|
|
1734
|
+
getAverageLiquidity,
|
|
1735
|
+
getLiquidityBySingleAmount,
|
|
1736
|
+
getDependentAmount,
|
|
1737
|
+
getLiquidityByAmountsAndPrice,
|
|
1738
|
+
getAmountsByLiquidityAndPrice,
|
|
1739
|
+
getAmountsAtNewPrice
|
|
1740
|
+
};
|
|
1741
|
+
function getEstimatedLPFeeWithProtocolFee({ amount, currency, ...rest }) {
|
|
1742
|
+
return getEstimatedLPFeeByAmountsWithProtocolFee({
|
|
1743
|
+
...rest,
|
|
1744
|
+
amountA: amount,
|
|
1745
|
+
amountB: CurrencyAmount$1.fromRawAmount(currency, MaxUint256)
|
|
1746
|
+
});
|
|
1747
|
+
}
|
|
1748
|
+
function getEstimatedLPFee({ amount, currency, ...rest }) {
|
|
1749
|
+
return getEstimatedLPFeeByAmounts({
|
|
1750
|
+
...rest,
|
|
1751
|
+
amountA: amount,
|
|
1752
|
+
amountB: CurrencyAmount$1.fromRawAmount(currency, MaxUint256)
|
|
1753
|
+
});
|
|
1754
|
+
}
|
|
1755
|
+
function getEstimatedLPFeeByAmountsWithProtocolFee(options) {
|
|
1756
|
+
try {
|
|
1757
|
+
return tryGetEstimatedLPFeeByAmounts(options);
|
|
1758
|
+
} catch (e) {
|
|
1759
|
+
console.error(e);
|
|
1760
|
+
return new Fraction$1(ZERO$1);
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
function getEstimatedLPFeeByAmounts({ protocolFee = ZERO_PERCENT, ...rest }) {
|
|
1764
|
+
try {
|
|
1765
|
+
const fee = tryGetEstimatedLPFeeByAmounts(rest);
|
|
1766
|
+
return ONE_HUNDRED_PERCENT.subtract(protocolFee).multiply(fee).asFraction;
|
|
1767
|
+
} catch (e) {
|
|
1768
|
+
console.error(e);
|
|
1769
|
+
return new Fraction$1(ZERO$1);
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
function tryGetEstimatedLPFeeByAmounts({
|
|
1773
|
+
amountA,
|
|
1774
|
+
amountB,
|
|
1775
|
+
volume24H,
|
|
1776
|
+
sqrtRatioX96,
|
|
1777
|
+
tickLower,
|
|
1778
|
+
tickUpper,
|
|
1779
|
+
mostActiveLiquidity,
|
|
1780
|
+
fee,
|
|
1781
|
+
insidePercentage = ONE_HUNDRED_PERCENT
|
|
1782
|
+
}) {
|
|
1783
|
+
invariant9(!Number.isNaN(fee) && fee >= 0, "INVALID_FEE");
|
|
1784
|
+
const tickCurrent = TickMath.getTickAtSqrtRatio(sqrtRatioX96);
|
|
1785
|
+
if (tickCurrent < tickLower || tickCurrent > tickUpper) {
|
|
1786
|
+
return new Fraction$1(ZERO$1);
|
|
1787
|
+
}
|
|
1788
|
+
const liquidity = FeeCalculator.getLiquidityByAmountsAndPrice({
|
|
1789
|
+
amountA,
|
|
1790
|
+
amountB,
|
|
1791
|
+
tickUpper,
|
|
1792
|
+
tickLower,
|
|
1793
|
+
sqrtRatioX96
|
|
1794
|
+
});
|
|
1795
|
+
if (!liquidity) {
|
|
1796
|
+
return new Fraction$1(ZERO$1);
|
|
1797
|
+
}
|
|
1798
|
+
const volumeInFraction = parseNumberToFraction(volume24H) || new Fraction$1(ZERO$1);
|
|
1799
|
+
return insidePercentage.multiply(volumeInFraction.multiply(BigInt(fee)).multiply(liquidity)).divide(MAX_FEE * (liquidity + mostActiveLiquidity)).asFraction;
|
|
1800
|
+
}
|
|
1801
|
+
function getDependentAmount(options) {
|
|
1802
|
+
const { currency, amount, sqrtRatioX96, tickLower, tickUpper } = options;
|
|
1803
|
+
const currentTick = TickMath.getTickAtSqrtRatio(sqrtRatioX96);
|
|
1804
|
+
const liquidity = FeeCalculator.getLiquidityBySingleAmount(options);
|
|
1805
|
+
const isToken0 = currency.wrapped.sortsBefore(amount.currency.wrapped);
|
|
1806
|
+
const getTokenAmount = isToken0 ? PositionMath.getToken0Amount : PositionMath.getToken1Amount;
|
|
1807
|
+
if (!liquidity) {
|
|
1808
|
+
return void 0;
|
|
1809
|
+
}
|
|
1810
|
+
return CurrencyAmount$1.fromRawAmount(
|
|
1811
|
+
currency,
|
|
1812
|
+
getTokenAmount(currentTick, tickLower, tickUpper, sqrtRatioX96, liquidity)
|
|
1813
|
+
);
|
|
1814
|
+
}
|
|
1815
|
+
function getLiquidityBySingleAmount({ amount, currency, ...rest }) {
|
|
1816
|
+
return getLiquidityByAmountsAndPrice({
|
|
1817
|
+
amountA: amount,
|
|
1818
|
+
amountB: CurrencyAmount$1.fromRawAmount(currency, MaxUint256),
|
|
1819
|
+
...rest
|
|
1820
|
+
});
|
|
1821
|
+
}
|
|
1822
|
+
function getLiquidityByAmountsAndPrice({
|
|
1823
|
+
amountA,
|
|
1824
|
+
amountB,
|
|
1825
|
+
tickUpper,
|
|
1826
|
+
tickLower,
|
|
1827
|
+
sqrtRatioX96
|
|
1828
|
+
}) {
|
|
1829
|
+
const isToken0 = amountA.currency.wrapped.address !== amountB.currency.wrapped.address ? amountA.currency.wrapped.sortsBefore(amountB.currency.wrapped) : true;
|
|
1830
|
+
const [inputAmount0, inputAmount1] = isToken0 ? [amountA.quotient, amountB.quotient] : [amountB.quotient, amountA.quotient];
|
|
1831
|
+
const sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickLower);
|
|
1832
|
+
const sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickUpper);
|
|
1833
|
+
try {
|
|
1834
|
+
return maxLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, inputAmount0, inputAmount1, true);
|
|
1835
|
+
} catch (e) {
|
|
1836
|
+
console.error(e);
|
|
1837
|
+
return void 0;
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
function getAmountsByLiquidityAndPrice(options) {
|
|
1841
|
+
const { currencyA, currencyB, liquidity, sqrtRatioX96, tickLower, tickUpper } = options;
|
|
1842
|
+
const currentTick = TickMath.getTickAtSqrtRatio(sqrtRatioX96);
|
|
1843
|
+
const isToken0 = currencyA.wrapped.sortsBefore(currencyB.wrapped);
|
|
1844
|
+
const adjustedAmount0 = PositionMath.getToken0Amount(currentTick, tickLower, tickUpper, sqrtRatioX96, liquidity);
|
|
1845
|
+
const adjustedAmount1 = PositionMath.getToken1Amount(currentTick, tickLower, tickUpper, sqrtRatioX96, liquidity);
|
|
1846
|
+
return [
|
|
1847
|
+
CurrencyAmount$1.fromRawAmount(currencyA, isToken0 ? adjustedAmount0 : adjustedAmount1),
|
|
1848
|
+
CurrencyAmount$1.fromRawAmount(currencyB, isToken0 ? adjustedAmount1 : adjustedAmount0)
|
|
1849
|
+
];
|
|
1850
|
+
}
|
|
1851
|
+
function getAmountsAtNewPrice({ newSqrtRatioX96, ...rest }) {
|
|
1852
|
+
const { tickLower, tickUpper, amountA, amountB } = rest;
|
|
1853
|
+
const liquidity = FeeCalculator.getLiquidityByAmountsAndPrice(rest);
|
|
1854
|
+
if (!liquidity) {
|
|
1855
|
+
return void 0;
|
|
1856
|
+
}
|
|
1857
|
+
return FeeCalculator.getAmountsByLiquidityAndPrice({
|
|
1858
|
+
liquidity,
|
|
1859
|
+
currencyA: amountA.currency,
|
|
1860
|
+
currencyB: amountB.currency,
|
|
1861
|
+
tickLower,
|
|
1862
|
+
tickUpper,
|
|
1863
|
+
sqrtRatioX96: newSqrtRatioX96
|
|
1864
|
+
});
|
|
1865
|
+
}
|
|
1866
|
+
function getAverageLiquidity(ticks, tickSpacing, tickLower, tickUpper) {
|
|
1867
|
+
invariant9(tickLower <= tickUpper, "INVALID_TICK_RANGE");
|
|
1868
|
+
TickList.validateList(ticks, tickSpacing);
|
|
1869
|
+
if (tickLower === tickUpper) {
|
|
1870
|
+
return FeeCalculator.getLiquidityFromTick(ticks, tickLower);
|
|
1871
|
+
}
|
|
1872
|
+
const lowerOutOfBound = tickLower < ticks[0].index;
|
|
1873
|
+
let lastTick = lowerOutOfBound ? new Tick({ index: TickMath.MIN_TICK, liquidityNet: ZERO$1, liquidityGross: ZERO$1 }) : TickList.nextInitializedTick(ticks, tickLower, true);
|
|
1874
|
+
let currentTick = TickList.nextInitializedTick(ticks, tickLower, false);
|
|
1875
|
+
let currentL = lowerOutOfBound ? ZERO$1 : FeeCalculator.getLiquidityFromTick(ticks, currentTick.index);
|
|
1876
|
+
let weightedL = ZERO$1;
|
|
1877
|
+
const getWeightedLFromLastTickTo = (toTick) => currentL * BigInt(toTick - Math.max(lastTick.index, tickLower));
|
|
1878
|
+
while (currentTick.index < tickUpper) {
|
|
1879
|
+
weightedL += getWeightedLFromLastTickTo(currentTick.index);
|
|
1880
|
+
currentL += currentTick.liquidityNet;
|
|
1881
|
+
lastTick = currentTick;
|
|
1882
|
+
if (currentTick.index === ticks[ticks.length - 1].index) {
|
|
1883
|
+
break;
|
|
1703
1884
|
}
|
|
1704
|
-
|
|
1705
|
-
return CurrencyAmount.fromRawAmount(amountIn.currency, slippageAdjustedAmountIn);
|
|
1885
|
+
currentTick = TickList.nextInitializedTick(ticks, currentTick.index, false);
|
|
1706
1886
|
}
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1887
|
+
weightedL += getWeightedLFromLastTickTo(tickUpper);
|
|
1888
|
+
return weightedL / BigInt(tickUpper - tickLower);
|
|
1889
|
+
}
|
|
1890
|
+
function getLiquidityFromSqrtRatioX96(ticks, sqrtRatioX96) {
|
|
1891
|
+
const tick = TickMath.getTickAtSqrtRatio(sqrtRatioX96);
|
|
1892
|
+
return FeeCalculator.getLiquidityFromTick(ticks, tick);
|
|
1893
|
+
}
|
|
1894
|
+
function getLiquidityFromTick(ticks, tick) {
|
|
1895
|
+
let liquidity = ZERO$1;
|
|
1896
|
+
if (!ticks?.length)
|
|
1897
|
+
return liquidity;
|
|
1898
|
+
if (tick < ticks[0].index || tick > ticks[ticks.length - 1].index) {
|
|
1899
|
+
return liquidity;
|
|
1719
1900
|
}
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
* @param nextAmountIn exact amount of input currency to spend
|
|
1727
|
-
* @param currencyOut the desired currency out
|
|
1728
|
-
* @param maxNumResults maximum number of results to return
|
|
1729
|
-
* @param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pool
|
|
1730
|
-
* @param currentPools used in recursion; the current list of pools
|
|
1731
|
-
* @param currencyAmountIn used in recursion; the original value of the currencyAmountIn parameter
|
|
1732
|
-
* @param bestTrades used in recursion; the current list of best trades
|
|
1733
|
-
* @returns The exact in trade
|
|
1734
|
-
*/
|
|
1735
|
-
static async bestTradeExactIn(pools, currencyAmountIn, currencyOut, { maxNumResults = 3, maxHops = 3 } = {}, currentPools = [], nextAmountIn = currencyAmountIn, bestTrades = []) {
|
|
1736
|
-
invariant11(pools.length > 0, "POOLS");
|
|
1737
|
-
invariant11(maxHops > 0, "MAX_HOPS");
|
|
1738
|
-
invariant11(currencyAmountIn === nextAmountIn || currentPools.length > 0, "INVALID_RECURSION");
|
|
1739
|
-
const amountIn = nextAmountIn.wrapped;
|
|
1740
|
-
const tokenOut = currencyOut.wrapped;
|
|
1741
|
-
for (let i = 0; i < pools.length; i++) {
|
|
1742
|
-
const pool = pools[i];
|
|
1743
|
-
if (!pool.token0.equals(amountIn.currency) && !pool.token1.equals(amountIn.currency))
|
|
1744
|
-
continue;
|
|
1745
|
-
let amountOut;
|
|
1746
|
-
try {
|
|
1747
|
-
const [result] = await pool.getOutputAmount(amountIn);
|
|
1748
|
-
amountOut = result;
|
|
1749
|
-
} catch (error) {
|
|
1750
|
-
if (error.isInsufficientInputAmountError) {
|
|
1751
|
-
continue;
|
|
1752
|
-
}
|
|
1753
|
-
throw error;
|
|
1754
|
-
}
|
|
1755
|
-
if (amountOut.currency.isToken && amountOut.currency.equals(tokenOut)) {
|
|
1756
|
-
sortedInsert(
|
|
1757
|
-
bestTrades,
|
|
1758
|
-
await Trade.fromRoute(
|
|
1759
|
-
new Route([...currentPools, pool], currencyAmountIn.currency, currencyOut),
|
|
1760
|
-
currencyAmountIn,
|
|
1761
|
-
TradeType.EXACT_INPUT
|
|
1762
|
-
),
|
|
1763
|
-
maxNumResults,
|
|
1764
|
-
tradeComparator
|
|
1765
|
-
);
|
|
1766
|
-
} else if (maxHops > 1 && pools.length > 1) {
|
|
1767
|
-
const poolsExcludingThisPool = pools.slice(0, i).concat(pools.slice(i + 1, pools.length));
|
|
1768
|
-
await Trade.bestTradeExactIn(
|
|
1769
|
-
poolsExcludingThisPool,
|
|
1770
|
-
currencyAmountIn,
|
|
1771
|
-
currencyOut,
|
|
1772
|
-
{
|
|
1773
|
-
maxNumResults,
|
|
1774
|
-
maxHops: maxHops - 1
|
|
1775
|
-
},
|
|
1776
|
-
[...currentPools, pool],
|
|
1777
|
-
amountOut,
|
|
1778
|
-
bestTrades
|
|
1779
|
-
);
|
|
1780
|
-
}
|
|
1901
|
+
for (let i = 0; i < ticks.length - 1; ++i) {
|
|
1902
|
+
liquidity += ticks[i].liquidityNet;
|
|
1903
|
+
const lowerTick = ticks[i].index;
|
|
1904
|
+
const upperTick = ticks[i + 1]?.index;
|
|
1905
|
+
if (lowerTick <= tick && tick <= upperTick) {
|
|
1906
|
+
break;
|
|
1781
1907
|
}
|
|
1782
|
-
return bestTrades;
|
|
1783
1908
|
}
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
* @param currencyIn the currency to spend
|
|
1792
|
-
* @param currencyAmountOut the desired currency amount out
|
|
1793
|
-
* @param nextAmountOut the exact amount of currency out
|
|
1794
|
-
* @param maxNumResults maximum number of results to return
|
|
1795
|
-
* @param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pool
|
|
1796
|
-
* @param currentPools used in recursion; the current list of pools
|
|
1797
|
-
* @param bestTrades used in recursion; the current list of best trades
|
|
1798
|
-
* @returns The exact out trade
|
|
1799
|
-
*/
|
|
1800
|
-
static async bestTradeExactOut(pools, currencyIn, currencyAmountOut, { maxNumResults = 3, maxHops = 3 } = {}, currentPools = [], nextAmountOut = currencyAmountOut, bestTrades = []) {
|
|
1801
|
-
invariant11(pools.length > 0, "POOLS");
|
|
1802
|
-
invariant11(maxHops > 0, "MAX_HOPS");
|
|
1803
|
-
invariant11(currencyAmountOut === nextAmountOut || currentPools.length > 0, "INVALID_RECURSION");
|
|
1804
|
-
const amountOut = nextAmountOut.wrapped;
|
|
1805
|
-
const tokenIn = currencyIn.wrapped;
|
|
1806
|
-
for (let i = 0; i < pools.length; i++) {
|
|
1807
|
-
const pool = pools[i];
|
|
1808
|
-
if (!pool.token0.equals(amountOut.currency) && !pool.token1.equals(amountOut.currency))
|
|
1809
|
-
continue;
|
|
1810
|
-
let amountIn;
|
|
1811
|
-
try {
|
|
1812
|
-
const [result] = await pool.getInputAmount(amountOut);
|
|
1813
|
-
amountIn = result;
|
|
1814
|
-
} catch (error) {
|
|
1815
|
-
if (error.isInsufficientReservesError) {
|
|
1816
|
-
continue;
|
|
1817
|
-
}
|
|
1818
|
-
throw error;
|
|
1819
|
-
}
|
|
1820
|
-
if (amountIn.currency.equals(tokenIn)) {
|
|
1821
|
-
sortedInsert(
|
|
1822
|
-
bestTrades,
|
|
1823
|
-
await Trade.fromRoute(
|
|
1824
|
-
new Route([pool, ...currentPools], currencyIn, currencyAmountOut.currency),
|
|
1825
|
-
currencyAmountOut,
|
|
1826
|
-
TradeType.EXACT_OUTPUT
|
|
1827
|
-
),
|
|
1828
|
-
maxNumResults,
|
|
1829
|
-
tradeComparator
|
|
1830
|
-
);
|
|
1831
|
-
} else if (maxHops > 1 && pools.length > 1) {
|
|
1832
|
-
const poolsExcludingThisPool = pools.slice(0, i).concat(pools.slice(i + 1, pools.length));
|
|
1833
|
-
await Trade.bestTradeExactOut(
|
|
1834
|
-
poolsExcludingThisPool,
|
|
1835
|
-
currencyIn,
|
|
1836
|
-
currencyAmountOut,
|
|
1837
|
-
{
|
|
1838
|
-
maxNumResults,
|
|
1839
|
-
maxHops: maxHops - 1
|
|
1840
|
-
},
|
|
1841
|
-
[pool, ...currentPools],
|
|
1842
|
-
amountIn,
|
|
1843
|
-
bestTrades
|
|
1844
|
-
);
|
|
1845
|
-
}
|
|
1846
|
-
}
|
|
1847
|
-
return bestTrades;
|
|
1909
|
+
return liquidity;
|
|
1910
|
+
}
|
|
1911
|
+
var FEE_BASE = 10n ** 4n;
|
|
1912
|
+
function parseProtocolFees(feeProtocol) {
|
|
1913
|
+
const packed = Number(feeProtocol);
|
|
1914
|
+
if (Number.isNaN(packed)) {
|
|
1915
|
+
throw new Error(`Invalid fee protocol ${feeProtocol}`);
|
|
1848
1916
|
}
|
|
1849
|
-
|
|
1917
|
+
const token0ProtocolFee = packed % 2 ** 16;
|
|
1918
|
+
const token1ProtocolFee = packed >> 16;
|
|
1919
|
+
return [new Percent(token0ProtocolFee, FEE_BASE), new Percent(token1ProtocolFee, FEE_BASE)];
|
|
1920
|
+
}
|
|
1921
|
+
function sqrtRatioX96ToPrice(sqrtRatioX96, currencyA, currencyB) {
|
|
1922
|
+
const ratioX192 = sqrtRatioX96 * sqrtRatioX96;
|
|
1923
|
+
return currencyA.wrapped.sortsBefore(currencyB.wrapped) ? new Price$1(currencyA.wrapped, currencyB.wrapped, Q192, ratioX192) : new Price$1(currencyA.wrapped, currencyB.wrapped, ratioX192, Q192);
|
|
1924
|
+
}
|
|
1850
1925
|
var IMulticall = [
|
|
1851
1926
|
{
|
|
1852
1927
|
inputs: [
|
|
@@ -1878,14 +1953,14 @@ var _Multicall = class {
|
|
|
1878
1953
|
if (!Array.isArray(calldatas)) {
|
|
1879
1954
|
calldatas = [calldatas];
|
|
1880
1955
|
}
|
|
1881
|
-
return calldatas.length === 1 ? calldatas[0] : _Multicall.
|
|
1956
|
+
return calldatas.length === 1 ? calldatas[0] : encodeFunctionData({ abi: _Multicall.ABI, functionName: "multicall", args: [calldatas] });
|
|
1882
1957
|
}
|
|
1883
1958
|
};
|
|
1884
1959
|
var Multicall = _Multicall;
|
|
1885
|
-
Multicall.
|
|
1960
|
+
Multicall.ABI = IMulticall;
|
|
1886
1961
|
|
|
1887
|
-
// src/abi/NonfungiblePositionManager.
|
|
1888
|
-
var
|
|
1962
|
+
// src/abi/NonfungiblePositionManager.ts
|
|
1963
|
+
var nonfungiblePositionManagerABI = [
|
|
1889
1964
|
{
|
|
1890
1965
|
inputs: [
|
|
1891
1966
|
{ internalType: "address", name: "_deployer", type: "address" },
|
|
@@ -2391,8 +2466,8 @@ var NonfungiblePositionManager_default = [
|
|
|
2391
2466
|
{ stateMutability: "payable", type: "receive" }
|
|
2392
2467
|
];
|
|
2393
2468
|
|
|
2394
|
-
// src/abi/SelfPermit.
|
|
2395
|
-
var
|
|
2469
|
+
// src/abi/SelfPermit.ts
|
|
2470
|
+
var selfPermitABI = [
|
|
2396
2471
|
{
|
|
2397
2472
|
inputs: [
|
|
2398
2473
|
{
|
|
@@ -2558,28 +2633,22 @@ var _SelfPermit = class {
|
|
|
2558
2633
|
constructor() {
|
|
2559
2634
|
}
|
|
2560
2635
|
static encodePermit(token, options) {
|
|
2561
|
-
return isAllowedPermit(options) ?
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
toHex(options.amount),
|
|
2571
|
-
toHex(options.deadline),
|
|
2572
|
-
options.v,
|
|
2573
|
-
options.r,
|
|
2574
|
-
options.s
|
|
2575
|
-
]);
|
|
2636
|
+
return isAllowedPermit(options) ? encodeFunctionData({
|
|
2637
|
+
abi: _SelfPermit.ABI,
|
|
2638
|
+
functionName: "selfPermitAllowed",
|
|
2639
|
+
args: [token.address, BigInt(options.nonce), BigInt(options.expiry), options.v, options.r, options.s]
|
|
2640
|
+
}) : encodeFunctionData({
|
|
2641
|
+
abi: _SelfPermit.ABI,
|
|
2642
|
+
functionName: "selfPermit",
|
|
2643
|
+
args: [token.address, BigInt(options.amount), BigInt(options.deadline), options.v, options.r, options.s]
|
|
2644
|
+
});
|
|
2576
2645
|
}
|
|
2577
2646
|
};
|
|
2578
2647
|
var SelfPermit = _SelfPermit;
|
|
2579
|
-
SelfPermit.
|
|
2648
|
+
SelfPermit.ABI = selfPermitABI;
|
|
2580
2649
|
|
|
2581
|
-
// src/abi/
|
|
2582
|
-
var
|
|
2650
|
+
// src/abi/PeripheryPaymentsWithFee.ts
|
|
2651
|
+
var peripheryPaymentsWithFeeABI = [
|
|
2583
2652
|
{
|
|
2584
2653
|
inputs: [],
|
|
2585
2654
|
name: "refundETH",
|
|
@@ -2699,46 +2768,47 @@ var _Payments = class {
|
|
|
2699
2768
|
constructor() {
|
|
2700
2769
|
}
|
|
2701
2770
|
static encodeFeeBips(fee) {
|
|
2702
|
-
return
|
|
2771
|
+
return fee.multiply(1e4).quotient;
|
|
2703
2772
|
}
|
|
2704
2773
|
static encodeUnwrapWETH9(amountMinimum, recipient, feeOptions) {
|
|
2705
2774
|
recipient = validateAndParseAddress(recipient);
|
|
2706
2775
|
if (feeOptions) {
|
|
2707
2776
|
const feeBips = this.encodeFeeBips(feeOptions.fee);
|
|
2708
2777
|
const feeRecipient = validateAndParseAddress(feeOptions.recipient);
|
|
2709
|
-
return
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
feeBips,
|
|
2713
|
-
|
|
2714
|
-
]);
|
|
2778
|
+
return encodeFunctionData({
|
|
2779
|
+
abi: _Payments.ABI,
|
|
2780
|
+
functionName: "unwrapWETH9WithFee",
|
|
2781
|
+
args: [amountMinimum, recipient, feeBips, feeRecipient]
|
|
2782
|
+
});
|
|
2715
2783
|
}
|
|
2716
|
-
return _Payments.
|
|
2784
|
+
return encodeFunctionData({ abi: _Payments.ABI, functionName: "unwrapWETH9", args: [amountMinimum, recipient] });
|
|
2717
2785
|
}
|
|
2718
2786
|
static encodeSweepToken(token, amountMinimum, recipient, feeOptions) {
|
|
2719
2787
|
recipient = validateAndParseAddress(recipient);
|
|
2720
2788
|
if (feeOptions) {
|
|
2721
2789
|
const feeBips = this.encodeFeeBips(feeOptions.fee);
|
|
2722
2790
|
const feeRecipient = validateAndParseAddress(feeOptions.recipient);
|
|
2723
|
-
return
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
recipient,
|
|
2727
|
-
|
|
2728
|
-
feeRecipient
|
|
2729
|
-
]);
|
|
2791
|
+
return encodeFunctionData({
|
|
2792
|
+
abi: _Payments.ABI,
|
|
2793
|
+
functionName: "sweepTokenWithFee",
|
|
2794
|
+
args: [token.address, amountMinimum, recipient, feeBips, feeRecipient]
|
|
2795
|
+
});
|
|
2730
2796
|
}
|
|
2731
|
-
return
|
|
2797
|
+
return encodeFunctionData({
|
|
2798
|
+
abi: _Payments.ABI,
|
|
2799
|
+
functionName: "sweepToken",
|
|
2800
|
+
args: [token.address, amountMinimum, recipient]
|
|
2801
|
+
});
|
|
2732
2802
|
}
|
|
2733
2803
|
static encodeRefundETH() {
|
|
2734
|
-
return _Payments.
|
|
2804
|
+
return encodeFunctionData({ abi: _Payments.ABI, functionName: "refundETH" });
|
|
2735
2805
|
}
|
|
2736
2806
|
};
|
|
2737
2807
|
var Payments = _Payments;
|
|
2738
|
-
Payments.
|
|
2808
|
+
Payments.ABI = peripheryPaymentsWithFeeABI;
|
|
2739
2809
|
|
|
2740
2810
|
// src/nonfungiblePositionManager.ts
|
|
2741
|
-
var MaxUint128 =
|
|
2811
|
+
var MaxUint128 = 2n ** 128n - 1n;
|
|
2742
2812
|
function isMint(options) {
|
|
2743
2813
|
return Object.keys(options).some((k) => k === "recipient");
|
|
2744
2814
|
}
|
|
@@ -2750,12 +2820,11 @@ var _NonfungiblePositionManager = class {
|
|
|
2750
2820
|
constructor() {
|
|
2751
2821
|
}
|
|
2752
2822
|
static encodeCreate(pool) {
|
|
2753
|
-
return
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
pool.fee,
|
|
2757
|
-
|
|
2758
|
-
]);
|
|
2823
|
+
return encodeFunctionData({
|
|
2824
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
2825
|
+
functionName: "createAndInitializePoolIfNecessary",
|
|
2826
|
+
args: [pool.token0.address, pool.token1.address, pool.fee, pool.sqrtRatioX96]
|
|
2827
|
+
});
|
|
2759
2828
|
}
|
|
2760
2829
|
static createCallParameters(pool) {
|
|
2761
2830
|
return {
|
|
@@ -2764,13 +2833,13 @@ var _NonfungiblePositionManager = class {
|
|
|
2764
2833
|
};
|
|
2765
2834
|
}
|
|
2766
2835
|
static addCallParameters(position, options) {
|
|
2767
|
-
|
|
2836
|
+
invariant9(position.liquidity > ZERO, "ZERO_LIQUIDITY");
|
|
2768
2837
|
const calldatas = [];
|
|
2769
2838
|
const { amount0: amount0Desired, amount1: amount1Desired } = position.mintAmounts;
|
|
2770
2839
|
const minimumAmounts = position.mintAmountsWithSlippage(options.slippageTolerance);
|
|
2771
|
-
const amount0Min =
|
|
2772
|
-
const amount1Min =
|
|
2773
|
-
const deadline =
|
|
2840
|
+
const amount0Min = minimumAmounts.amount0;
|
|
2841
|
+
const amount1Min = minimumAmounts.amount1;
|
|
2842
|
+
const deadline = BigInt(options.deadline);
|
|
2774
2843
|
if (isMint(options) && options.createPool) {
|
|
2775
2844
|
calldatas.push(this.encodeCreate(position.pool));
|
|
2776
2845
|
}
|
|
@@ -2783,40 +2852,48 @@ var _NonfungiblePositionManager = class {
|
|
|
2783
2852
|
if (isMint(options)) {
|
|
2784
2853
|
const recipient = validateAndParseAddress(options.recipient);
|
|
2785
2854
|
calldatas.push(
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2855
|
+
encodeFunctionData({
|
|
2856
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
2857
|
+
functionName: "mint",
|
|
2858
|
+
args: [
|
|
2859
|
+
{
|
|
2860
|
+
token0: position.pool.token0.address,
|
|
2861
|
+
token1: position.pool.token1.address,
|
|
2862
|
+
fee: position.pool.fee,
|
|
2863
|
+
tickLower: position.tickLower,
|
|
2864
|
+
tickUpper: position.tickUpper,
|
|
2865
|
+
amount0Desired,
|
|
2866
|
+
amount1Desired,
|
|
2867
|
+
amount0Min,
|
|
2868
|
+
amount1Min,
|
|
2869
|
+
recipient,
|
|
2870
|
+
deadline
|
|
2871
|
+
}
|
|
2872
|
+
]
|
|
2873
|
+
})
|
|
2801
2874
|
);
|
|
2802
2875
|
} else {
|
|
2803
2876
|
calldatas.push(
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2877
|
+
encodeFunctionData({
|
|
2878
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
2879
|
+
functionName: "increaseLiquidity",
|
|
2880
|
+
args: [
|
|
2881
|
+
{
|
|
2882
|
+
tokenId: BigInt(options.tokenId),
|
|
2883
|
+
amount0Desired,
|
|
2884
|
+
amount1Desired,
|
|
2885
|
+
amount0Min,
|
|
2886
|
+
amount1Min,
|
|
2887
|
+
deadline
|
|
2888
|
+
}
|
|
2889
|
+
]
|
|
2890
|
+
})
|
|
2814
2891
|
);
|
|
2815
2892
|
}
|
|
2816
2893
|
let value = toHex(0);
|
|
2817
2894
|
if (options.useNative) {
|
|
2818
2895
|
const { wrapped } = options.useNative;
|
|
2819
|
-
|
|
2896
|
+
invariant9(position.pool.token0.equals(wrapped) || position.pool.token1.equals(wrapped), "NO_WETH");
|
|
2820
2897
|
const wrappedValue = position.pool.token0.equals(wrapped) ? amount0Desired : amount1Desired;
|
|
2821
2898
|
if (wrappedValue > ZERO) {
|
|
2822
2899
|
calldatas.push(Payments.encodeRefundETH());
|
|
@@ -2830,18 +2907,22 @@ var _NonfungiblePositionManager = class {
|
|
|
2830
2907
|
}
|
|
2831
2908
|
static encodeCollect(options) {
|
|
2832
2909
|
const calldatas = [];
|
|
2833
|
-
const tokenId =
|
|
2910
|
+
const tokenId = BigInt(options.tokenId);
|
|
2834
2911
|
const involvesETH = options.expectedCurrencyOwed0.currency.isNative || options.expectedCurrencyOwed1.currency.isNative;
|
|
2835
2912
|
const recipient = validateAndParseAddress(options.recipient);
|
|
2836
2913
|
calldatas.push(
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2914
|
+
encodeFunctionData({
|
|
2915
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
2916
|
+
functionName: "collect",
|
|
2917
|
+
args: [
|
|
2918
|
+
{
|
|
2919
|
+
tokenId,
|
|
2920
|
+
recipient: involvesETH ? ADDRESS_ZERO : recipient,
|
|
2921
|
+
amount0Max: MaxUint128,
|
|
2922
|
+
amount1Max: MaxUint128
|
|
2923
|
+
}
|
|
2924
|
+
]
|
|
2925
|
+
})
|
|
2845
2926
|
);
|
|
2846
2927
|
if (involvesETH) {
|
|
2847
2928
|
const ethAmount = options.expectedCurrencyOwed0.currency.isNative ? options.expectedCurrencyOwed0.quotient : options.expectedCurrencyOwed1.quotient;
|
|
@@ -2867,40 +2948,48 @@ var _NonfungiblePositionManager = class {
|
|
|
2867
2948
|
*/
|
|
2868
2949
|
static removeCallParameters(position, options) {
|
|
2869
2950
|
const calldatas = [];
|
|
2870
|
-
const deadline =
|
|
2871
|
-
const tokenId =
|
|
2951
|
+
const deadline = BigInt(options.deadline);
|
|
2952
|
+
const tokenId = BigInt(options.tokenId);
|
|
2872
2953
|
const partialPosition = new Position({
|
|
2873
2954
|
pool: position.pool,
|
|
2874
2955
|
liquidity: options.liquidityPercentage.multiply(position.liquidity).quotient,
|
|
2875
2956
|
tickLower: position.tickLower,
|
|
2876
2957
|
tickUpper: position.tickUpper
|
|
2877
2958
|
});
|
|
2878
|
-
|
|
2959
|
+
invariant9(partialPosition.liquidity > ZERO, "ZERO_LIQUIDITY");
|
|
2879
2960
|
const { amount0: amount0Min, amount1: amount1Min } = partialPosition.burnAmountsWithSlippage(
|
|
2880
2961
|
options.slippageTolerance
|
|
2881
2962
|
);
|
|
2882
2963
|
if (options.permit) {
|
|
2883
2964
|
calldatas.push(
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2965
|
+
encodeFunctionData({
|
|
2966
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
2967
|
+
functionName: "permit",
|
|
2968
|
+
args: [
|
|
2969
|
+
validateAndParseAddress(options.permit.spender),
|
|
2970
|
+
tokenId,
|
|
2971
|
+
BigInt(options.permit.deadline),
|
|
2972
|
+
options.permit.v,
|
|
2973
|
+
options.permit.r,
|
|
2974
|
+
options.permit.s
|
|
2975
|
+
]
|
|
2976
|
+
})
|
|
2892
2977
|
);
|
|
2893
2978
|
}
|
|
2894
2979
|
calldatas.push(
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2980
|
+
encodeFunctionData({
|
|
2981
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
2982
|
+
functionName: "decreaseLiquidity",
|
|
2983
|
+
args: [
|
|
2984
|
+
{
|
|
2985
|
+
tokenId,
|
|
2986
|
+
liquidity: partialPosition.liquidity,
|
|
2987
|
+
amount0Min,
|
|
2988
|
+
amount1Min,
|
|
2989
|
+
deadline
|
|
2990
|
+
}
|
|
2991
|
+
]
|
|
2992
|
+
})
|
|
2904
2993
|
);
|
|
2905
2994
|
const { expectedCurrencyOwed0, expectedCurrencyOwed1, ...rest } = options.collectOptions;
|
|
2906
2995
|
calldatas.push(
|
|
@@ -2918,10 +3007,12 @@ var _NonfungiblePositionManager = class {
|
|
|
2918
3007
|
);
|
|
2919
3008
|
if (options.liquidityPercentage.equalTo(ONE)) {
|
|
2920
3009
|
if (options.burnToken) {
|
|
2921
|
-
calldatas.push(
|
|
3010
|
+
calldatas.push(
|
|
3011
|
+
encodeFunctionData({ abi: _NonfungiblePositionManager.ABI, functionName: "burn", args: [tokenId] })
|
|
3012
|
+
);
|
|
2922
3013
|
}
|
|
2923
3014
|
} else {
|
|
2924
|
-
|
|
3015
|
+
invariant9(options.burnToken !== true, "CANNOT_BURN");
|
|
2925
3016
|
}
|
|
2926
3017
|
return {
|
|
2927
3018
|
calldata: Multicall.encodeMulticall(calldatas),
|
|
@@ -2933,16 +3024,17 @@ var _NonfungiblePositionManager = class {
|
|
|
2933
3024
|
const sender = validateAndParseAddress(options.sender);
|
|
2934
3025
|
let calldata;
|
|
2935
3026
|
if (options.data) {
|
|
2936
|
-
calldata =
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
3027
|
+
calldata = encodeFunctionData({
|
|
3028
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
3029
|
+
functionName: "safeTransferFrom",
|
|
3030
|
+
args: [sender, recipient, BigInt(options.tokenId), options.data]
|
|
3031
|
+
});
|
|
2940
3032
|
} else {
|
|
2941
|
-
calldata =
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
3033
|
+
calldata = encodeFunctionData({
|
|
3034
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
3035
|
+
functionName: "safeTransferFrom",
|
|
3036
|
+
args: [sender, recipient, BigInt(options.tokenId)]
|
|
3037
|
+
});
|
|
2946
3038
|
}
|
|
2947
3039
|
return {
|
|
2948
3040
|
calldata,
|
|
@@ -2951,10 +3043,10 @@ var _NonfungiblePositionManager = class {
|
|
|
2951
3043
|
}
|
|
2952
3044
|
};
|
|
2953
3045
|
var NonfungiblePositionManager = _NonfungiblePositionManager;
|
|
2954
|
-
NonfungiblePositionManager.
|
|
3046
|
+
NonfungiblePositionManager.ABI = nonfungiblePositionManagerABI;
|
|
2955
3047
|
|
|
2956
|
-
// src/abi/Quoter.
|
|
2957
|
-
var
|
|
3048
|
+
// src/abi/Quoter.ts
|
|
3049
|
+
var quoterABI = [
|
|
2958
3050
|
{
|
|
2959
3051
|
inputs: [
|
|
2960
3052
|
{
|
|
@@ -3166,8 +3258,8 @@ var Quoter_default = [
|
|
|
3166
3258
|
}
|
|
3167
3259
|
];
|
|
3168
3260
|
|
|
3169
|
-
// src/abi/QuoterV2.
|
|
3170
|
-
var
|
|
3261
|
+
// src/abi/QuoterV2.ts
|
|
3262
|
+
var quoterV2ABI = [
|
|
3171
3263
|
{
|
|
3172
3264
|
inputs: [
|
|
3173
3265
|
{
|
|
@@ -3468,19 +3560,19 @@ var SwapQuoter = class {
|
|
|
3468
3560
|
*/
|
|
3469
3561
|
static quoteCallParameters(route, amount, tradeType, options = {}) {
|
|
3470
3562
|
const singleHop = route.pools.length === 1;
|
|
3471
|
-
const quoteAmount =
|
|
3563
|
+
const quoteAmount = amount.quotient;
|
|
3472
3564
|
let calldata;
|
|
3473
|
-
const
|
|
3565
|
+
const swapAbi = options.useQuoterV2 ? this.V2ABI : this.V1ABI;
|
|
3474
3566
|
if (singleHop) {
|
|
3475
3567
|
const baseQuoteParams = {
|
|
3476
3568
|
tokenIn: route.tokenPath[0].address,
|
|
3477
3569
|
tokenOut: route.tokenPath[1].address,
|
|
3478
3570
|
fee: route.pools[0].fee,
|
|
3479
|
-
sqrtPriceLimitX96:
|
|
3571
|
+
sqrtPriceLimitX96: BigInt(options?.sqrtPriceLimitX96 ?? 0)
|
|
3480
3572
|
};
|
|
3481
3573
|
const v2QuoteParams = {
|
|
3482
3574
|
...baseQuoteParams,
|
|
3483
|
-
...tradeType
|
|
3575
|
+
...tradeType === TradeType$1.EXACT_INPUT ? { amountIn: quoteAmount } : { amount: quoteAmount }
|
|
3484
3576
|
};
|
|
3485
3577
|
const v1QuoteParams = [
|
|
3486
3578
|
baseQuoteParams.tokenIn,
|
|
@@ -3489,16 +3581,31 @@ var SwapQuoter = class {
|
|
|
3489
3581
|
quoteAmount,
|
|
3490
3582
|
baseQuoteParams.sqrtPriceLimitX96
|
|
3491
3583
|
];
|
|
3492
|
-
const tradeTypeFunctionName = tradeType === TradeType.EXACT_INPUT ? "quoteExactInputSingle" : "quoteExactOutputSingle";
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3584
|
+
const tradeTypeFunctionName = tradeType === TradeType$1.EXACT_INPUT ? "quoteExactInputSingle" : "quoteExactOutputSingle";
|
|
3585
|
+
if (options.useQuoterV2) {
|
|
3586
|
+
calldata = encodeFunctionData({
|
|
3587
|
+
abi: this.V2ABI,
|
|
3588
|
+
functionName: tradeTypeFunctionName,
|
|
3589
|
+
// @ts-ignore // FIXME
|
|
3590
|
+
args: [v2QuoteParams]
|
|
3591
|
+
});
|
|
3592
|
+
} else {
|
|
3593
|
+
calldata = encodeFunctionData({
|
|
3594
|
+
abi: this.V1ABI,
|
|
3595
|
+
functionName: tradeTypeFunctionName,
|
|
3596
|
+
args: v1QuoteParams
|
|
3597
|
+
});
|
|
3598
|
+
}
|
|
3497
3599
|
} else {
|
|
3498
|
-
|
|
3499
|
-
const path = encodeRouteToPath(route, tradeType === TradeType.EXACT_OUTPUT);
|
|
3500
|
-
const tradeTypeFunctionName = tradeType === TradeType.EXACT_INPUT ? "quoteExactInput" : "quoteExactOutput";
|
|
3501
|
-
calldata =
|
|
3600
|
+
invariant9(options?.sqrtPriceLimitX96 === void 0, "MULTIHOP_PRICE_LIMIT");
|
|
3601
|
+
const path = encodeRouteToPath(route, tradeType === TradeType$1.EXACT_OUTPUT);
|
|
3602
|
+
const tradeTypeFunctionName = tradeType === TradeType$1.EXACT_INPUT ? "quoteExactInput" : "quoteExactOutput";
|
|
3603
|
+
calldata = encodeFunctionData({
|
|
3604
|
+
// @ts-ignore
|
|
3605
|
+
abi: swapAbi,
|
|
3606
|
+
functionName: tradeTypeFunctionName,
|
|
3607
|
+
args: [path, quoteAmount]
|
|
3608
|
+
});
|
|
3502
3609
|
}
|
|
3503
3610
|
return {
|
|
3504
3611
|
calldata,
|
|
@@ -3506,11 +3613,11 @@ var SwapQuoter = class {
|
|
|
3506
3613
|
};
|
|
3507
3614
|
}
|
|
3508
3615
|
};
|
|
3509
|
-
SwapQuoter.
|
|
3510
|
-
SwapQuoter.
|
|
3616
|
+
SwapQuoter.V1ABI = quoterABI;
|
|
3617
|
+
SwapQuoter.V2ABI = quoterV2ABI;
|
|
3511
3618
|
|
|
3512
|
-
// src/abi/V3Staker.
|
|
3513
|
-
var
|
|
3619
|
+
// src/abi/V3Staker.ts
|
|
3620
|
+
var v3StakerABI = [
|
|
3514
3621
|
{
|
|
3515
3622
|
inputs: [
|
|
3516
3623
|
{
|
|
@@ -4230,15 +4337,20 @@ var _Staker = class {
|
|
|
4230
4337
|
static encodeClaim(incentiveKey, options) {
|
|
4231
4338
|
const calldatas = [];
|
|
4232
4339
|
calldatas.push(
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4340
|
+
encodeFunctionData({
|
|
4341
|
+
abi: _Staker.ABI,
|
|
4342
|
+
functionName: "unstakeToken",
|
|
4343
|
+
args: [this._encodeIncentiveKey(incentiveKey), BigInt(options.tokenId)]
|
|
4344
|
+
})
|
|
4237
4345
|
);
|
|
4238
4346
|
const recipient = validateAndParseAddress(options.recipient);
|
|
4239
4347
|
const amount = options.amount ?? 0;
|
|
4240
4348
|
calldatas.push(
|
|
4241
|
-
|
|
4349
|
+
encodeFunctionData({
|
|
4350
|
+
abi: _Staker.ABI,
|
|
4351
|
+
functionName: "claimReward",
|
|
4352
|
+
args: [incentiveKey.rewardToken.address, recipient, BigInt(amount)]
|
|
4353
|
+
})
|
|
4242
4354
|
);
|
|
4243
4355
|
return calldatas;
|
|
4244
4356
|
}
|
|
@@ -4258,10 +4370,11 @@ var _Staker = class {
|
|
|
4258
4370
|
const incentiveKey = incentiveKeys[i];
|
|
4259
4371
|
calldatas = calldatas.concat(this.encodeClaim(incentiveKey, options));
|
|
4260
4372
|
calldatas.push(
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4373
|
+
encodeFunctionData({
|
|
4374
|
+
abi: _Staker.ABI,
|
|
4375
|
+
functionName: "stakeToken",
|
|
4376
|
+
args: [this._encodeIncentiveKey(incentiveKey), BigInt(options.tokenId)]
|
|
4377
|
+
})
|
|
4265
4378
|
);
|
|
4266
4379
|
}
|
|
4267
4380
|
return {
|
|
@@ -4289,11 +4402,11 @@ var _Staker = class {
|
|
|
4289
4402
|
}
|
|
4290
4403
|
const owner = validateAndParseAddress(withdrawOptions.owner);
|
|
4291
4404
|
calldatas.push(
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4405
|
+
encodeFunctionData({
|
|
4406
|
+
abi: _Staker.ABI,
|
|
4407
|
+
functionName: "withdrawToken",
|
|
4408
|
+
args: [BigInt(withdrawOptions.tokenId), owner, toHex(0)]
|
|
4409
|
+
})
|
|
4297
4410
|
);
|
|
4298
4411
|
return {
|
|
4299
4412
|
calldata: Multicall.encodeMulticall(calldatas),
|
|
@@ -4314,16 +4427,18 @@ var _Staker = class {
|
|
|
4314
4427
|
const incentiveKey = incentiveKeys[i];
|
|
4315
4428
|
keys.push(this._encodeIncentiveKey(incentiveKey));
|
|
4316
4429
|
}
|
|
4317
|
-
data =
|
|
4430
|
+
data = encodeAbiParameters(parseAbiParameters([`${_Staker.INCENTIVE_KEY_ABI}[]`]), [keys]);
|
|
4318
4431
|
} else {
|
|
4319
|
-
data =
|
|
4432
|
+
data = encodeAbiParameters(parseAbiParameters(_Staker.INCENTIVE_KEY_ABI), [
|
|
4433
|
+
this._encodeIncentiveKey(incentiveKeys[0])
|
|
4434
|
+
]);
|
|
4320
4435
|
}
|
|
4321
4436
|
return data;
|
|
4322
4437
|
}
|
|
4323
4438
|
/**
|
|
4324
4439
|
*
|
|
4325
4440
|
* @param incentiveKey An `IncentiveKey` which represents a unique staking program.
|
|
4326
|
-
* @returns An encoded IncentiveKey to be read by
|
|
4441
|
+
* @returns An encoded IncentiveKey to be read by viem
|
|
4327
4442
|
*/
|
|
4328
4443
|
static _encodeIncentiveKey(incentiveKey) {
|
|
4329
4444
|
const { token0, token1, fee } = incentiveKey.pool;
|
|
@@ -4331,18 +4446,18 @@ var _Staker = class {
|
|
|
4331
4446
|
return {
|
|
4332
4447
|
rewardToken: incentiveKey.rewardToken.address,
|
|
4333
4448
|
pool: Pool.getAddress(token0, token1, fee),
|
|
4334
|
-
startTime:
|
|
4335
|
-
endTime:
|
|
4449
|
+
startTime: BigInt(incentiveKey.startTime),
|
|
4450
|
+
endTime: BigInt(incentiveKey.endTime),
|
|
4336
4451
|
refundee
|
|
4337
4452
|
};
|
|
4338
4453
|
}
|
|
4339
4454
|
};
|
|
4340
4455
|
var Staker = _Staker;
|
|
4341
|
-
Staker.
|
|
4456
|
+
Staker.ABI = v3StakerABI;
|
|
4342
4457
|
Staker.INCENTIVE_KEY_ABI = "tuple(address rewardToken, address pool, uint256 startTime, uint256 endTime, address refundee)";
|
|
4343
4458
|
|
|
4344
|
-
// src/abi/SwapRouter.
|
|
4345
|
-
var
|
|
4459
|
+
// src/abi/SwapRouter.ts
|
|
4460
|
+
var swapRouterABI = [
|
|
4346
4461
|
{
|
|
4347
4462
|
inputs: [
|
|
4348
4463
|
{
|
|
@@ -4945,11 +5060,11 @@ var _SwapRouter = class {
|
|
|
4945
5060
|
const sampleTrade = trades[0];
|
|
4946
5061
|
const tokenIn = sampleTrade.inputAmount.currency.wrapped;
|
|
4947
5062
|
const tokenOut = sampleTrade.outputAmount.currency.wrapped;
|
|
4948
|
-
|
|
5063
|
+
invariant9(
|
|
4949
5064
|
trades.every((trade) => trade.inputAmount.currency.wrapped.equals(tokenIn)),
|
|
4950
5065
|
"TOKEN_IN_DIFF"
|
|
4951
5066
|
);
|
|
4952
|
-
|
|
5067
|
+
invariant9(
|
|
4953
5068
|
trades.every((trade) => trade.outputAmount.currency.wrapped.equals(tokenOut)),
|
|
4954
5069
|
"TOKEN_OUT_DIFF"
|
|
4955
5070
|
);
|
|
@@ -4966,15 +5081,15 @@ var _SwapRouter = class {
|
|
|
4966
5081
|
const routerMustCustody = outputIsNative || !!options.fee;
|
|
4967
5082
|
const totalValue = inputIsNative ? trades.reduce((sum, trade) => sum.add(trade.maximumAmountIn(options.slippageTolerance)), ZERO_IN) : ZERO_IN;
|
|
4968
5083
|
if (options.inputTokenPermit) {
|
|
4969
|
-
|
|
5084
|
+
invariant9(sampleTrade.inputAmount.currency.isToken, "NON_TOKEN_PERMIT");
|
|
4970
5085
|
calldatas.push(SelfPermit.encodePermit(sampleTrade.inputAmount.currency, options.inputTokenPermit));
|
|
4971
5086
|
}
|
|
4972
5087
|
const recipient = validateAndParseAddress(options.recipient);
|
|
4973
|
-
const deadline =
|
|
5088
|
+
const deadline = BigInt(options.deadline);
|
|
4974
5089
|
for (const trade of trades) {
|
|
4975
5090
|
for (const { route, inputAmount, outputAmount } of trade.swaps) {
|
|
4976
|
-
const amountIn =
|
|
4977
|
-
const amountOut =
|
|
5091
|
+
const amountIn = BigInt(trade.maximumAmountIn(options.slippageTolerance, inputAmount).quotient);
|
|
5092
|
+
const amountOut = BigInt(trade.minimumAmountOut(options.slippageTolerance, outputAmount).quotient);
|
|
4978
5093
|
const singleHop = route.pools.length === 1;
|
|
4979
5094
|
if (singleHop) {
|
|
4980
5095
|
if (trade.tradeType === TradeType.EXACT_INPUT) {
|
|
@@ -4986,9 +5101,15 @@ var _SwapRouter = class {
|
|
|
4986
5101
|
deadline,
|
|
4987
5102
|
amountIn,
|
|
4988
5103
|
amountOutMinimum: amountOut,
|
|
4989
|
-
sqrtPriceLimitX96:
|
|
5104
|
+
sqrtPriceLimitX96: BigInt(options.sqrtPriceLimitX96 ?? 0)
|
|
4990
5105
|
};
|
|
4991
|
-
calldatas.push(
|
|
5106
|
+
calldatas.push(
|
|
5107
|
+
encodeFunctionData({
|
|
5108
|
+
abi: _SwapRouter.ABI,
|
|
5109
|
+
functionName: "exactInputSingle",
|
|
5110
|
+
args: [exactInputSingleParams]
|
|
5111
|
+
})
|
|
5112
|
+
);
|
|
4992
5113
|
} else {
|
|
4993
5114
|
const exactOutputSingleParams = {
|
|
4994
5115
|
tokenIn: route.tokenPath[0].address,
|
|
@@ -4998,12 +5119,18 @@ var _SwapRouter = class {
|
|
|
4998
5119
|
deadline,
|
|
4999
5120
|
amountOut,
|
|
5000
5121
|
amountInMaximum: amountIn,
|
|
5001
|
-
sqrtPriceLimitX96:
|
|
5122
|
+
sqrtPriceLimitX96: BigInt(options.sqrtPriceLimitX96 ?? 0)
|
|
5002
5123
|
};
|
|
5003
|
-
calldatas.push(
|
|
5124
|
+
calldatas.push(
|
|
5125
|
+
encodeFunctionData({
|
|
5126
|
+
abi: _SwapRouter.ABI,
|
|
5127
|
+
functionName: "exactOutputSingle",
|
|
5128
|
+
args: [exactOutputSingleParams]
|
|
5129
|
+
})
|
|
5130
|
+
);
|
|
5004
5131
|
}
|
|
5005
5132
|
} else {
|
|
5006
|
-
|
|
5133
|
+
invariant9(options.sqrtPriceLimitX96 === void 0, "MULTIHOP_PRICE_LIMIT");
|
|
5007
5134
|
const path = encodeRouteToPath(route, trade.tradeType === TradeType.EXACT_OUTPUT);
|
|
5008
5135
|
if (trade.tradeType === TradeType.EXACT_INPUT) {
|
|
5009
5136
|
const exactInputParams = {
|
|
@@ -5013,7 +5140,9 @@ var _SwapRouter = class {
|
|
|
5013
5140
|
amountIn,
|
|
5014
5141
|
amountOutMinimum: amountOut
|
|
5015
5142
|
};
|
|
5016
|
-
calldatas.push(
|
|
5143
|
+
calldatas.push(
|
|
5144
|
+
encodeFunctionData({ abi: _SwapRouter.ABI, functionName: "exactInput", args: [exactInputParams] })
|
|
5145
|
+
);
|
|
5017
5146
|
} else {
|
|
5018
5147
|
const exactOutputParams = {
|
|
5019
5148
|
path,
|
|
@@ -5022,7 +5151,9 @@ var _SwapRouter = class {
|
|
|
5022
5151
|
amountOut,
|
|
5023
5152
|
amountInMaximum: amountIn
|
|
5024
5153
|
};
|
|
5025
|
-
calldatas.push(
|
|
5154
|
+
calldatas.push(
|
|
5155
|
+
encodeFunctionData({ abi: _SwapRouter.ABI, functionName: "exactOutput", args: [exactOutputParams] })
|
|
5156
|
+
);
|
|
5026
5157
|
}
|
|
5027
5158
|
}
|
|
5028
5159
|
}
|
|
@@ -5055,10 +5186,11 @@ var _SwapRouter = class {
|
|
|
5055
5186
|
}
|
|
5056
5187
|
};
|
|
5057
5188
|
var SwapRouter = _SwapRouter;
|
|
5058
|
-
|
|
5189
|
+
// public static INTERFACE: Interface = new Interface(ISwapRouter)
|
|
5190
|
+
SwapRouter.ABI = swapRouterABI;
|
|
5059
5191
|
|
|
5060
|
-
// src/abi/MasterChefV3.
|
|
5061
|
-
var
|
|
5192
|
+
// src/abi/MasterChefV3.ts
|
|
5193
|
+
var masterChefV3ABI = [
|
|
5062
5194
|
{
|
|
5063
5195
|
inputs: [
|
|
5064
5196
|
{ internalType: "contract IERC20", name: "_CAKE", type: "address" },
|
|
@@ -5746,14 +5878,14 @@ var _MasterChefV3 = class {
|
|
|
5746
5878
|
// Copy from NonfungiblePositionManager
|
|
5747
5879
|
// Only support increaseLiquidity
|
|
5748
5880
|
static addCallParameters(position, options) {
|
|
5749
|
-
|
|
5881
|
+
invariant9(position.liquidity > ZERO$2, "ZERO_LIQUIDITY");
|
|
5750
5882
|
const calldatas = [];
|
|
5751
5883
|
const { amount0: amount0Desired, amount1: amount1Desired } = position.mintAmounts;
|
|
5752
5884
|
const minimumAmounts = position.mintAmountsWithSlippage(options.slippageTolerance);
|
|
5753
|
-
const amount0Min =
|
|
5754
|
-
const amount1Min =
|
|
5755
|
-
const deadline =
|
|
5756
|
-
|
|
5885
|
+
const amount0Min = BigInt(minimumAmounts.amount0);
|
|
5886
|
+
const amount1Min = BigInt(minimumAmounts.amount1);
|
|
5887
|
+
const deadline = BigInt(options.deadline);
|
|
5888
|
+
invariant9(!isMint(options), "NO_MINT_SUPPORT");
|
|
5757
5889
|
if (options.token0Permit) {
|
|
5758
5890
|
calldatas.push(SelfPermit.encodePermit(position.pool.token0, options.token0Permit));
|
|
5759
5891
|
}
|
|
@@ -5761,21 +5893,25 @@ var _MasterChefV3 = class {
|
|
|
5761
5893
|
calldatas.push(SelfPermit.encodePermit(position.pool.token1, options.token1Permit));
|
|
5762
5894
|
}
|
|
5763
5895
|
calldatas.push(
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5896
|
+
encodeFunctionData({
|
|
5897
|
+
abi: _MasterChefV3.ABI,
|
|
5898
|
+
functionName: "increaseLiquidity",
|
|
5899
|
+
args: [
|
|
5900
|
+
{
|
|
5901
|
+
tokenId: BigInt(options.tokenId),
|
|
5902
|
+
amount0Desired,
|
|
5903
|
+
amount1Desired,
|
|
5904
|
+
amount0Min,
|
|
5905
|
+
amount1Min,
|
|
5906
|
+
deadline
|
|
5907
|
+
}
|
|
5908
|
+
]
|
|
5909
|
+
})
|
|
5774
5910
|
);
|
|
5775
5911
|
let value = toHex(0);
|
|
5776
5912
|
if (options.useNative) {
|
|
5777
5913
|
const { wrapped } = options.useNative;
|
|
5778
|
-
|
|
5914
|
+
invariant9(position.pool.token0.equals(wrapped) || position.pool.token1.equals(wrapped), "NO_WETH");
|
|
5779
5915
|
const wrappedValue = position.pool.token0.equals(wrapped) ? amount0Desired : amount1Desired;
|
|
5780
5916
|
value = toHex(wrappedValue);
|
|
5781
5917
|
}
|
|
@@ -5787,18 +5923,22 @@ var _MasterChefV3 = class {
|
|
|
5787
5923
|
// Copy from NonfungiblePositionManager
|
|
5788
5924
|
static encodeCollect(options) {
|
|
5789
5925
|
const calldatas = [];
|
|
5790
|
-
const tokenId =
|
|
5926
|
+
const tokenId = BigInt(options.tokenId);
|
|
5791
5927
|
const involvesETH = options.expectedCurrencyOwed0.currency.isNative || options.expectedCurrencyOwed1.currency.isNative;
|
|
5792
5928
|
const recipient = validateAndParseAddress(options.recipient);
|
|
5793
5929
|
calldatas.push(
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5930
|
+
encodeFunctionData({
|
|
5931
|
+
abi: _MasterChefV3.ABI,
|
|
5932
|
+
functionName: "collect",
|
|
5933
|
+
args: [
|
|
5934
|
+
{
|
|
5935
|
+
tokenId,
|
|
5936
|
+
recipient: involvesETH ? ADDRESS_ZERO : recipient,
|
|
5937
|
+
amount0Max: MaxUint128,
|
|
5938
|
+
amount1Max: MaxUint128
|
|
5939
|
+
}
|
|
5940
|
+
]
|
|
5941
|
+
})
|
|
5802
5942
|
);
|
|
5803
5943
|
if (involvesETH) {
|
|
5804
5944
|
const ethAmount = options.expectedCurrencyOwed0.currency.isNative ? options.expectedCurrencyOwed0.quotient : options.expectedCurrencyOwed1.quotient;
|
|
@@ -5818,40 +5958,35 @@ var _MasterChefV3 = class {
|
|
|
5818
5958
|
}
|
|
5819
5959
|
static removeCallParameters(position, options) {
|
|
5820
5960
|
const calldatas = [];
|
|
5821
|
-
const deadline =
|
|
5822
|
-
const tokenId =
|
|
5961
|
+
const deadline = BigInt(options.deadline);
|
|
5962
|
+
const tokenId = BigInt(options.tokenId);
|
|
5823
5963
|
const partialPosition = new Position({
|
|
5824
5964
|
pool: position.pool,
|
|
5825
5965
|
liquidity: options.liquidityPercentage.multiply(position.liquidity).quotient,
|
|
5826
5966
|
tickLower: position.tickLower,
|
|
5827
5967
|
tickUpper: position.tickUpper
|
|
5828
5968
|
});
|
|
5829
|
-
|
|
5969
|
+
invariant9(partialPosition.liquidity > ZERO$2, "ZERO_LIQUIDITY");
|
|
5830
5970
|
const { amount0: amount0Min, amount1: amount1Min } = partialPosition.burnAmountsWithSlippage(
|
|
5831
5971
|
options.slippageTolerance
|
|
5832
5972
|
);
|
|
5833
5973
|
if (options.permit) {
|
|
5834
|
-
|
|
5835
|
-
_MasterChefV3.INTERFACE.encodeFunctionData("permit", [
|
|
5836
|
-
validateAndParseAddress(options.permit.spender),
|
|
5837
|
-
tokenId,
|
|
5838
|
-
toHex(options.permit.deadline),
|
|
5839
|
-
options.permit.v,
|
|
5840
|
-
options.permit.r,
|
|
5841
|
-
options.permit.s
|
|
5842
|
-
])
|
|
5843
|
-
);
|
|
5974
|
+
throw new Error("NOT_IMPLEMENTED");
|
|
5844
5975
|
}
|
|
5845
5976
|
calldatas.push(
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5977
|
+
encodeFunctionData({
|
|
5978
|
+
abi: _MasterChefV3.ABI,
|
|
5979
|
+
functionName: "decreaseLiquidity",
|
|
5980
|
+
args: [
|
|
5981
|
+
{
|
|
5982
|
+
tokenId,
|
|
5983
|
+
liquidity: partialPosition.liquidity,
|
|
5984
|
+
amount0Min,
|
|
5985
|
+
amount1Min,
|
|
5986
|
+
deadline
|
|
5987
|
+
}
|
|
5988
|
+
]
|
|
5989
|
+
})
|
|
5855
5990
|
);
|
|
5856
5991
|
const { expectedCurrencyOwed0, expectedCurrencyOwed1, ...rest } = options.collectOptions;
|
|
5857
5992
|
calldatas.push(
|
|
@@ -5870,26 +6005,28 @@ var _MasterChefV3 = class {
|
|
|
5870
6005
|
if (rest?.recipient) {
|
|
5871
6006
|
if (options.liquidityPercentage.equalTo(ONE$1)) {
|
|
5872
6007
|
calldatas.push(
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
6008
|
+
encodeFunctionData({
|
|
6009
|
+
abi: _MasterChefV3.ABI,
|
|
6010
|
+
functionName: "withdraw",
|
|
6011
|
+
args: [tokenId, validateAndParseAddress(rest?.recipient)]
|
|
6012
|
+
})
|
|
5877
6013
|
);
|
|
5878
6014
|
} else {
|
|
5879
6015
|
calldatas.push(
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
6016
|
+
encodeFunctionData({
|
|
6017
|
+
abi: _MasterChefV3.ABI,
|
|
6018
|
+
functionName: "harvest",
|
|
6019
|
+
args: [tokenId, validateAndParseAddress(rest?.recipient)]
|
|
6020
|
+
})
|
|
5884
6021
|
);
|
|
5885
6022
|
}
|
|
5886
6023
|
}
|
|
5887
6024
|
if (options.liquidityPercentage.equalTo(ONE$1)) {
|
|
5888
6025
|
if (options.burnToken) {
|
|
5889
|
-
calldatas.push(_MasterChefV3.
|
|
6026
|
+
calldatas.push(encodeFunctionData({ abi: _MasterChefV3.ABI, functionName: "burn", args: [tokenId] }));
|
|
5890
6027
|
}
|
|
5891
6028
|
} else {
|
|
5892
|
-
|
|
6029
|
+
invariant9(options.burnToken !== true, "CANNOT_BURN");
|
|
5893
6030
|
}
|
|
5894
6031
|
return {
|
|
5895
6032
|
calldata: Multicall.encodeMulticall(calldatas),
|
|
@@ -5915,7 +6052,11 @@ var _MasterChefV3 = class {
|
|
|
5915
6052
|
const { tokenId, to } = options;
|
|
5916
6053
|
const calldatas = [];
|
|
5917
6054
|
calldatas.push(
|
|
5918
|
-
|
|
6055
|
+
encodeFunctionData({
|
|
6056
|
+
abi: _MasterChefV3.ABI,
|
|
6057
|
+
functionName: "harvest",
|
|
6058
|
+
args: [BigInt(tokenId), validateAndParseAddress(to)]
|
|
6059
|
+
})
|
|
5919
6060
|
);
|
|
5920
6061
|
return calldatas;
|
|
5921
6062
|
}
|
|
@@ -5923,7 +6064,11 @@ var _MasterChefV3 = class {
|
|
|
5923
6064
|
const { tokenId, to } = options;
|
|
5924
6065
|
const calldatas = [];
|
|
5925
6066
|
calldatas.push(
|
|
5926
|
-
|
|
6067
|
+
encodeFunctionData({
|
|
6068
|
+
abi: _MasterChefV3.ABI,
|
|
6069
|
+
functionName: "withdraw",
|
|
6070
|
+
args: [BigInt(tokenId), validateAndParseAddress(to)]
|
|
6071
|
+
})
|
|
5927
6072
|
);
|
|
5928
6073
|
return {
|
|
5929
6074
|
calldata: Multicall.encodeMulticall(calldatas),
|
|
@@ -5932,6 +6077,6 @@ var _MasterChefV3 = class {
|
|
|
5932
6077
|
}
|
|
5933
6078
|
};
|
|
5934
6079
|
var MasterChefV3 = _MasterChefV3;
|
|
5935
|
-
MasterChefV3.
|
|
6080
|
+
MasterChefV3.ABI = masterChefV3ABI;
|
|
5936
6081
|
|
|
5937
|
-
export { ADDRESS_ZERO,
|
|
6082
|
+
export { ADDRESS_ZERO, DEPLOYER_ADDRESSES, FACTORY_ADDRESSES, FeeAmount, FeeCalculator, FullMath, LiquidityMath, MasterChefV3, MaxUint128, Multicall, NoTickDataProvider, NonfungiblePositionManager, POOL_INIT_CODE_HASHES, Payments, Pool, Position, PositionLibrary, PositionMath, Route, SelfPermit, SqrtPriceMath, Staker, SwapMath, SwapQuoter, SwapRouter, TICK_SPACINGS, Tick, TickLibrary, TickList, TickListDataProvider, TickMath, Trade, computePoolAddress, encodeRouteToPath, encodeSqrtRatioX96, getAmountsAtNewPrice, getAmountsByLiquidityAndPrice, getAverageLiquidity, getDependentAmount, getEstimatedLPFee, getEstimatedLPFeeByAmounts, getEstimatedLPFeeByAmountsWithProtocolFee, getEstimatedLPFeeWithProtocolFee, getLiquidityByAmountsAndPrice, getLiquidityBySingleAmount, getLiquidityFromSqrtRatioX96, getLiquidityFromTick, isMint, isSorted, masterChefV3ABI, maxLiquidityForAmounts, mostSignificantBit, nearestUsableTick, nonfungiblePositionManagerABI, parseProtocolFees, peripheryPaymentsWithFeeABI, priceToClosestTick, quoterABI, quoterV2ABI, selfPermitABI, sqrtRatioX96ToPrice, subIn256, swapRouterABI, tickToPrice, toHex, tradeComparator, v3StakerABI };
|