@pancakeswap/v3-sdk 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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.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 +1447 -1359
- package/dist/index.mjs +1447 -1367
- 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 +1 -1
- 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.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var sdk = require('@pancakeswap/sdk');
|
|
4
|
-
var
|
|
4
|
+
var invariant9 = require('tiny-invariant');
|
|
5
5
|
var swapSdkCore = require('@pancakeswap/swap-sdk-core');
|
|
6
|
-
var
|
|
7
|
-
var address = require('@ethersproject/address');
|
|
8
|
-
var solidity = require('@ethersproject/solidity');
|
|
6
|
+
var viem = require('viem');
|
|
9
7
|
|
|
10
8
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
9
|
|
|
12
|
-
var
|
|
10
|
+
var invariant9__default = /*#__PURE__*/_interopDefault(invariant9);
|
|
13
11
|
|
|
14
12
|
// src/entities/pool.ts
|
|
15
13
|
var FACTORY_ADDRESS = "0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865";
|
|
@@ -44,6 +42,13 @@ var MAX_FEE = 10n ** 6n;
|
|
|
44
42
|
var ONE_HUNDRED_PERCENT = new swapSdkCore.Percent("1");
|
|
45
43
|
var ZERO_PERCENT = new swapSdkCore.Percent("0");
|
|
46
44
|
var Q128 = 2n ** 128n;
|
|
45
|
+
function getCreate2Address(from_, salt_, initCodeHash) {
|
|
46
|
+
const from = viem.toBytes(viem.getAddress(from_));
|
|
47
|
+
const salt = viem.pad(viem.isBytes(salt_) ? salt_ : viem.toBytes(salt_), {
|
|
48
|
+
size: 32
|
|
49
|
+
});
|
|
50
|
+
return viem.getAddress(viem.slice(viem.keccak256(viem.concat([viem.toBytes("0xff"), from, salt, viem.toBytes(initCodeHash)])), 12));
|
|
51
|
+
}
|
|
47
52
|
function computePoolAddress({
|
|
48
53
|
deployerAddress,
|
|
49
54
|
tokenA,
|
|
@@ -52,11 +57,10 @@ function computePoolAddress({
|
|
|
52
57
|
initCodeHashManualOverride
|
|
53
58
|
}) {
|
|
54
59
|
const [token0, token1] = tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA];
|
|
55
|
-
return
|
|
60
|
+
return getCreate2Address(
|
|
56
61
|
deployerAddress,
|
|
57
|
-
|
|
58
|
-
["
|
|
59
|
-
[abi.defaultAbiCoder.encode(["address", "address", "uint24"], [token0.address, token1.address, fee])]
|
|
62
|
+
viem.keccak256(
|
|
63
|
+
viem.encodeAbiParameters(viem.parseAbiParameters(["address, address, uint24"]), [token0.address, token1.address, fee])
|
|
60
64
|
),
|
|
61
65
|
initCodeHashManualOverride ?? POOL_INIT_CODE_HASH
|
|
62
66
|
);
|
|
@@ -95,11 +99,11 @@ var FullMath = class {
|
|
|
95
99
|
var MaxUint160 = 2n ** 160n - ONE;
|
|
96
100
|
function multiplyIn256(x, y) {
|
|
97
101
|
const product = x * y;
|
|
98
|
-
return product &
|
|
102
|
+
return product & swapSdkCore.MaxUint256;
|
|
99
103
|
}
|
|
100
104
|
function addIn256(x, y) {
|
|
101
105
|
const sum = x + y;
|
|
102
|
-
return sum &
|
|
106
|
+
return sum & swapSdkCore.MaxUint256;
|
|
103
107
|
}
|
|
104
108
|
var SqrtPriceMath = class {
|
|
105
109
|
/**
|
|
@@ -124,13 +128,13 @@ var SqrtPriceMath = class {
|
|
|
124
128
|
return roundUp ? FullMath.mulDivRoundingUp(liquidity, sqrtRatioBX96 - sqrtRatioAX96, Q96) : liquidity * (sqrtRatioBX96 - sqrtRatioAX96) / Q96;
|
|
125
129
|
}
|
|
126
130
|
static getNextSqrtPriceFromInput(sqrtPX96, liquidity, amountIn, zeroForOne) {
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
invariant9__default.default(sqrtPX96 > ZERO);
|
|
132
|
+
invariant9__default.default(liquidity > ZERO);
|
|
129
133
|
return zeroForOne ? this.getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountIn, true) : this.getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountIn, true);
|
|
130
134
|
}
|
|
131
135
|
static getNextSqrtPriceFromOutput(sqrtPX96, liquidity, amountOut, zeroForOne) {
|
|
132
|
-
|
|
133
|
-
|
|
136
|
+
invariant9__default.default(sqrtPX96 > ZERO);
|
|
137
|
+
invariant9__default.default(liquidity > ZERO);
|
|
134
138
|
return zeroForOne ? this.getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountOut, false) : this.getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountOut, false);
|
|
135
139
|
}
|
|
136
140
|
static getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amount, add) {
|
|
@@ -148,8 +152,8 @@ var SqrtPriceMath = class {
|
|
|
148
152
|
return FullMath.mulDivRoundingUp(numerator1, ONE, numerator1 / sqrtPX96 + amount);
|
|
149
153
|
}
|
|
150
154
|
const product = multiplyIn256(amount, sqrtPX96);
|
|
151
|
-
|
|
152
|
-
|
|
155
|
+
invariant9__default.default(product / amount === sqrtPX96);
|
|
156
|
+
invariant9__default.default(numerator1 > product);
|
|
153
157
|
const denominator = numerator1 - product;
|
|
154
158
|
return FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator);
|
|
155
159
|
}
|
|
@@ -159,7 +163,7 @@ var SqrtPriceMath = class {
|
|
|
159
163
|
return sqrtPX96 + quotient2;
|
|
160
164
|
}
|
|
161
165
|
const quotient = FullMath.mulDivRoundingUp(amount, Q96, liquidity);
|
|
162
|
-
|
|
166
|
+
invariant9__default.default(sqrtPX96 > quotient);
|
|
163
167
|
return sqrtPX96 - quotient;
|
|
164
168
|
}
|
|
165
169
|
};
|
|
@@ -227,8 +231,8 @@ var SwapMath = class {
|
|
|
227
231
|
var TWO = 2n;
|
|
228
232
|
var POWERS_OF_2 = [128, 64, 32, 16, 8, 4, 2, 1].map((pow) => [pow, TWO ** BigInt(pow)]);
|
|
229
233
|
function mostSignificantBit(x) {
|
|
230
|
-
|
|
231
|
-
|
|
234
|
+
invariant9__default.default(x > ZERO, "ZERO");
|
|
235
|
+
invariant9__default.default(x <= swapSdkCore.MaxUint256, "MAX");
|
|
232
236
|
let msb = 0;
|
|
233
237
|
for (const [power, min] of POWERS_OF_2) {
|
|
234
238
|
if (x >= min) {
|
|
@@ -255,7 +259,7 @@ var _TickMath = class {
|
|
|
255
259
|
* @param tick the tick for which to compute the sqrt ratio
|
|
256
260
|
*/
|
|
257
261
|
static getSqrtRatioAtTick(tick) {
|
|
258
|
-
|
|
262
|
+
invariant9__default.default(tick >= _TickMath.MIN_TICK && tick <= _TickMath.MAX_TICK && Number.isInteger(tick), "TICK");
|
|
259
263
|
const absTick = tick < 0 ? tick * -1 : tick;
|
|
260
264
|
let ratio = (absTick & 1) != 0 ? BigInt("0xfffcb933bd6fad37aa2d162d1a594001") : BigInt("0x100000000000000000000000000000000");
|
|
261
265
|
if ((absTick & 2) != 0)
|
|
@@ -297,7 +301,7 @@ var _TickMath = class {
|
|
|
297
301
|
if ((absTick & 524288) != 0)
|
|
298
302
|
ratio = mulShift(ratio, "0x48a170391f7dc42444e8fa2");
|
|
299
303
|
if (tick > 0)
|
|
300
|
-
ratio =
|
|
304
|
+
ratio = swapSdkCore.MaxUint256 / ratio;
|
|
301
305
|
return ratio % Q32 > ZERO ? ratio / Q32 + ONE : ratio / Q32;
|
|
302
306
|
}
|
|
303
307
|
/**
|
|
@@ -306,7 +310,7 @@ var _TickMath = class {
|
|
|
306
310
|
* @param sqrtRatioX96 the sqrt ratio as a Q64.96 for which to compute the tick
|
|
307
311
|
*/
|
|
308
312
|
static getTickAtSqrtRatio(sqrtRatioX96) {
|
|
309
|
-
|
|
313
|
+
invariant9__default.default(sqrtRatioX96 >= _TickMath.MIN_SQRT_RATIO && sqrtRatioX96 < _TickMath.MAX_SQRT_RATIO, "SQRT_RATIO");
|
|
310
314
|
const sqrtRatioX128 = sqrtRatioX96 << 32n;
|
|
311
315
|
const msb = mostSignificantBit(sqrtRatioX128);
|
|
312
316
|
let r;
|
|
@@ -380,25 +384,25 @@ var TickList = class {
|
|
|
380
384
|
constructor() {
|
|
381
385
|
}
|
|
382
386
|
static validateList(ticks, tickSpacing) {
|
|
383
|
-
|
|
384
|
-
|
|
387
|
+
invariant9__default.default(tickSpacing > 0, "TICK_SPACING_NONZERO");
|
|
388
|
+
invariant9__default.default(
|
|
385
389
|
ticks.every(({ index }) => index % tickSpacing === 0),
|
|
386
390
|
"TICK_SPACING"
|
|
387
391
|
);
|
|
388
|
-
|
|
389
|
-
|
|
392
|
+
invariant9__default.default(ticks.reduce((accumulator, { liquidityNet }) => accumulator + liquidityNet, ZERO) === ZERO, "ZERO_NET");
|
|
393
|
+
invariant9__default.default(isSorted(ticks, tickComparator), "SORTED");
|
|
390
394
|
}
|
|
391
395
|
static isBelowSmallest(ticks, tick) {
|
|
392
|
-
|
|
396
|
+
invariant9__default.default(ticks.length > 0, "LENGTH");
|
|
393
397
|
return tick < ticks[0].index;
|
|
394
398
|
}
|
|
395
399
|
static isAtOrAboveLargest(ticks, tick) {
|
|
396
|
-
|
|
400
|
+
invariant9__default.default(ticks.length > 0, "LENGTH");
|
|
397
401
|
return tick >= ticks[ticks.length - 1].index;
|
|
398
402
|
}
|
|
399
403
|
static getTick(ticks, index) {
|
|
400
404
|
const tick = ticks[this.binarySearch(ticks, index)];
|
|
401
|
-
|
|
405
|
+
invariant9__default.default(tick.index === index, "NOT_CONTAINED");
|
|
402
406
|
return tick;
|
|
403
407
|
}
|
|
404
408
|
/**
|
|
@@ -408,7 +412,7 @@ var TickList = class {
|
|
|
408
412
|
* @private
|
|
409
413
|
*/
|
|
410
414
|
static binarySearch(ticks, tick) {
|
|
411
|
-
|
|
415
|
+
invariant9__default.default(!this.isBelowSmallest(ticks, tick), "BELOW_SMALLEST");
|
|
412
416
|
let l = 0;
|
|
413
417
|
let r = ticks.length - 1;
|
|
414
418
|
let i;
|
|
@@ -426,14 +430,14 @@ var TickList = class {
|
|
|
426
430
|
}
|
|
427
431
|
static nextInitializedTick(ticks, tick, lte) {
|
|
428
432
|
if (lte) {
|
|
429
|
-
|
|
433
|
+
invariant9__default.default(!TickList.isBelowSmallest(ticks, tick), "BELOW_SMALLEST");
|
|
430
434
|
if (TickList.isAtOrAboveLargest(ticks, tick)) {
|
|
431
435
|
return ticks[ticks.length - 1];
|
|
432
436
|
}
|
|
433
437
|
const index2 = this.binarySearch(ticks, tick);
|
|
434
438
|
return ticks[index2];
|
|
435
439
|
}
|
|
436
|
-
|
|
440
|
+
invariant9__default.default(!this.isAtOrAboveLargest(ticks, tick), "AT_OR_ABOVE_LARGEST");
|
|
437
441
|
if (this.isBelowSmallest(ticks, tick)) {
|
|
438
442
|
return ticks[0];
|
|
439
443
|
}
|
|
@@ -470,44 +474,219 @@ var TickList = class {
|
|
|
470
474
|
return Math.abs(beforeIndex - afterIndex);
|
|
471
475
|
}
|
|
472
476
|
};
|
|
477
|
+
var Tick = class {
|
|
478
|
+
constructor({ index, liquidityGross, liquidityNet }) {
|
|
479
|
+
invariant9__default.default(index >= TickMath.MIN_TICK && index <= TickMath.MAX_TICK, "TICK");
|
|
480
|
+
this.index = index;
|
|
481
|
+
this.liquidityGross = BigInt(liquidityGross);
|
|
482
|
+
this.liquidityNet = BigInt(liquidityNet);
|
|
483
|
+
}
|
|
484
|
+
};
|
|
473
485
|
|
|
474
|
-
// src/
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
hex = `0${hex}`;
|
|
486
|
+
// src/entities/tickListDataProvider.ts
|
|
487
|
+
var TickListDataProvider = class {
|
|
488
|
+
constructor(ticks) {
|
|
489
|
+
const ticksMapped = ticks.map((t) => t instanceof Tick ? t : new Tick(t));
|
|
490
|
+
this.ticks = ticksMapped;
|
|
480
491
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
492
|
+
async getTick(tick) {
|
|
493
|
+
return TickList.getTick(this.ticks, tick);
|
|
494
|
+
}
|
|
495
|
+
async nextInitializedTickWithinOneWord(tick, lte, tickSpacing) {
|
|
496
|
+
return TickList.nextInitializedTickWithinOneWord(this.ticks, tick, lte, tickSpacing);
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
// src/entities/pool.ts
|
|
501
|
+
var NO_TICK_DATA_PROVIDER_DEFAULT = new NoTickDataProvider();
|
|
502
|
+
var Pool = class {
|
|
503
|
+
static getAddress(tokenA, tokenB, fee, initCodeHashManualOverride, deployerAddressOverride) {
|
|
504
|
+
return computePoolAddress({
|
|
505
|
+
deployerAddress: deployerAddressOverride ?? DEPLOYER_ADDRESSES[tokenA.chainId],
|
|
506
|
+
fee,
|
|
507
|
+
tokenA,
|
|
508
|
+
tokenB,
|
|
509
|
+
initCodeHashManualOverride
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Construct a pool
|
|
514
|
+
* @param tokenA One of the tokens in the pool
|
|
515
|
+
* @param tokenB The other token in the pool
|
|
516
|
+
* @param fee The fee in hundredths of a bips of the input amount of every swap that is collected by the pool
|
|
517
|
+
* @param sqrtRatioX96 The sqrt of the current ratio of amounts of token1 to token0
|
|
518
|
+
* @param liquidity The current value of in range liquidity
|
|
519
|
+
* @param tickCurrent The current tick of the pool
|
|
520
|
+
* @param ticks The current state of the pool ticks or a data provider that can return tick data
|
|
521
|
+
*/
|
|
522
|
+
constructor(tokenA, tokenB, fee, sqrtRatioX96, liquidity, tickCurrent, ticks = NO_TICK_DATA_PROVIDER_DEFAULT) {
|
|
523
|
+
invariant9__default.default(Number.isInteger(fee) && fee < 1e6, "FEE");
|
|
524
|
+
[this.token0, this.token1] = tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA];
|
|
525
|
+
this.fee = fee;
|
|
526
|
+
this.sqrtRatioX96 = BigInt(sqrtRatioX96);
|
|
527
|
+
this.liquidity = BigInt(liquidity);
|
|
528
|
+
this.tickCurrent = tickCurrent;
|
|
529
|
+
this.tickDataProvider = Array.isArray(ticks) ? new TickListDataProvider(ticks) : ticks;
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Returns true if the token is either token0 or token1
|
|
533
|
+
* @param token The token to check
|
|
534
|
+
* @returns True if token is either token0 or token
|
|
535
|
+
*/
|
|
536
|
+
involvesToken(token) {
|
|
537
|
+
return token.equals(this.token0) || token.equals(this.token1);
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Returns the current mid price of the pool in terms of token0, i.e. the ratio of token1 over token0
|
|
541
|
+
*/
|
|
542
|
+
get token0Price() {
|
|
543
|
+
return this._token0Price ?? (this._token0Price = new sdk.Price(this.token0, this.token1, Q192, this.sqrtRatioX96 * this.sqrtRatioX96));
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Returns the current mid price of the pool in terms of token1, i.e. the ratio of token0 over token1
|
|
547
|
+
*/
|
|
548
|
+
get token1Price() {
|
|
549
|
+
return this._token1Price ?? (this._token1Price = new sdk.Price(this.token1, this.token0, this.sqrtRatioX96 * this.sqrtRatioX96, Q192));
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Return the price of the given token in terms of the other token in the pool.
|
|
553
|
+
* @param token The token to return price of
|
|
554
|
+
* @returns The price of the given token, in terms of the other.
|
|
555
|
+
*/
|
|
556
|
+
priceOf(token) {
|
|
557
|
+
invariant9__default.default(this.involvesToken(token), "TOKEN");
|
|
558
|
+
return token.equals(this.token0) ? this.token0Price : this.token1Price;
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Returns the chain ID of the tokens in the pool.
|
|
562
|
+
*/
|
|
563
|
+
get chainId() {
|
|
564
|
+
return this.token0.chainId;
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* Given an input amount of a token, return the computed output amount, and a pool with state updated after the trade
|
|
568
|
+
* @param inputAmount The input amount for which to quote the output amount
|
|
569
|
+
* @param sqrtPriceLimitX96 The Q64.96 sqrt price limit
|
|
570
|
+
* @returns The output amount and the pool with updated state
|
|
571
|
+
*/
|
|
572
|
+
async getOutputAmount(inputAmount, sqrtPriceLimitX96) {
|
|
573
|
+
invariant9__default.default(this.involvesToken(inputAmount.currency), "TOKEN");
|
|
574
|
+
const zeroForOne = inputAmount.currency.equals(this.token0);
|
|
575
|
+
const {
|
|
576
|
+
amountCalculated: outputAmount,
|
|
577
|
+
sqrtRatioX96,
|
|
578
|
+
liquidity,
|
|
579
|
+
tickCurrent
|
|
580
|
+
} = await this.swap(zeroForOne, inputAmount.quotient, sqrtPriceLimitX96);
|
|
581
|
+
const outputToken = zeroForOne ? this.token1 : this.token0;
|
|
582
|
+
return [
|
|
583
|
+
sdk.CurrencyAmount.fromRawAmount(outputToken, outputAmount * NEGATIVE_ONE),
|
|
584
|
+
new Pool(this.token0, this.token1, this.fee, sqrtRatioX96, liquidity, tickCurrent, this.tickDataProvider)
|
|
585
|
+
];
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Given a desired output amount of a token, return the computed input amount and a pool with state updated after the trade
|
|
589
|
+
* @param outputAmount the output amount for which to quote the input amount
|
|
590
|
+
* @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
|
|
591
|
+
* @returns The input amount and the pool with updated state
|
|
592
|
+
*/
|
|
593
|
+
async getInputAmount(outputAmount, sqrtPriceLimitX96) {
|
|
594
|
+
invariant9__default.default(outputAmount.currency.isToken && this.involvesToken(outputAmount.currency), "TOKEN");
|
|
595
|
+
const zeroForOne = outputAmount.currency.equals(this.token1);
|
|
596
|
+
const {
|
|
597
|
+
amountSpecifiedRemaining,
|
|
598
|
+
amountCalculated: inputAmount,
|
|
599
|
+
sqrtRatioX96,
|
|
600
|
+
liquidity,
|
|
601
|
+
tickCurrent
|
|
602
|
+
} = await this.swap(zeroForOne, outputAmount.quotient * NEGATIVE_ONE, sqrtPriceLimitX96);
|
|
603
|
+
invariant9__default.default(amountSpecifiedRemaining === ZERO, "INSUFICIENT_LIQUIDITY");
|
|
604
|
+
const inputToken = zeroForOne ? this.token0 : this.token1;
|
|
605
|
+
return [
|
|
606
|
+
sdk.CurrencyAmount.fromRawAmount(inputToken, inputAmount),
|
|
607
|
+
new Pool(this.token0, this.token1, this.fee, sqrtRatioX96, liquidity, tickCurrent, this.tickDataProvider)
|
|
608
|
+
];
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Executes a swap
|
|
612
|
+
* @param zeroForOne Whether the amount in is token0 or token1
|
|
613
|
+
* @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)
|
|
614
|
+
* @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
|
|
615
|
+
* @returns amountCalculated
|
|
616
|
+
* @returns sqrtRatioX96
|
|
617
|
+
* @returns liquidity
|
|
618
|
+
* @returns tickCurrent
|
|
619
|
+
*/
|
|
620
|
+
async swap(zeroForOne, amountSpecified, sqrtPriceLimitX96) {
|
|
621
|
+
if (!sqrtPriceLimitX96)
|
|
622
|
+
sqrtPriceLimitX96 = zeroForOne ? TickMath.MIN_SQRT_RATIO + ONE : TickMath.MAX_SQRT_RATIO - ONE;
|
|
623
|
+
if (zeroForOne) {
|
|
624
|
+
invariant9__default.default(sqrtPriceLimitX96 > TickMath.MIN_SQRT_RATIO, "RATIO_MIN");
|
|
625
|
+
invariant9__default.default(sqrtPriceLimitX96 < this.sqrtRatioX96, "RATIO_CURRENT");
|
|
626
|
+
} else {
|
|
627
|
+
invariant9__default.default(sqrtPriceLimitX96 < TickMath.MAX_SQRT_RATIO, "RATIO_MAX");
|
|
628
|
+
invariant9__default.default(sqrtPriceLimitX96 > this.sqrtRatioX96, "RATIO_CURRENT");
|
|
629
|
+
}
|
|
630
|
+
const exactInput = amountSpecified >= ZERO;
|
|
631
|
+
const state = {
|
|
632
|
+
amountSpecifiedRemaining: amountSpecified,
|
|
633
|
+
amountCalculated: ZERO,
|
|
634
|
+
sqrtPriceX96: this.sqrtRatioX96,
|
|
635
|
+
tick: this.tickCurrent,
|
|
636
|
+
liquidity: this.liquidity
|
|
637
|
+
};
|
|
638
|
+
while (state.amountSpecifiedRemaining !== ZERO && state.sqrtPriceX96 != sqrtPriceLimitX96) {
|
|
639
|
+
const step = {};
|
|
640
|
+
step.sqrtPriceStartX96 = state.sqrtPriceX96;
|
|
641
|
+
[step.tickNext, step.initialized] = await this.tickDataProvider.nextInitializedTickWithinOneWord(
|
|
642
|
+
state.tick,
|
|
643
|
+
zeroForOne,
|
|
644
|
+
this.tickSpacing
|
|
645
|
+
);
|
|
646
|
+
if (step.tickNext < TickMath.MIN_TICK) {
|
|
647
|
+
step.tickNext = TickMath.MIN_TICK;
|
|
648
|
+
} else if (step.tickNext > TickMath.MAX_TICK) {
|
|
649
|
+
step.tickNext = TickMath.MAX_TICK;
|
|
494
650
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
651
|
+
step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext);
|
|
652
|
+
[state.sqrtPriceX96, step.amountIn, step.amountOut, step.feeAmount] = SwapMath.computeSwapStep(
|
|
653
|
+
state.sqrtPriceX96,
|
|
654
|
+
(zeroForOne ? step.sqrtPriceNextX96 < sqrtPriceLimitX96 : step.sqrtPriceNextX96 > sqrtPriceLimitX96) ? sqrtPriceLimitX96 : step.sqrtPriceNextX96,
|
|
655
|
+
state.liquidity,
|
|
656
|
+
state.amountSpecifiedRemaining,
|
|
657
|
+
this.fee
|
|
658
|
+
);
|
|
659
|
+
if (exactInput) {
|
|
660
|
+
state.amountSpecifiedRemaining = state.amountSpecifiedRemaining - (step.amountIn + step.feeAmount);
|
|
661
|
+
state.amountCalculated = state.amountCalculated - step.amountOut;
|
|
662
|
+
} else {
|
|
663
|
+
state.amountSpecifiedRemaining = state.amountSpecifiedRemaining + step.amountOut;
|
|
664
|
+
state.amountCalculated = state.amountCalculated + (step.amountIn + step.feeAmount);
|
|
665
|
+
}
|
|
666
|
+
if (state.sqrtPriceX96 === step.sqrtPriceNextX96) {
|
|
667
|
+
if (step.initialized) {
|
|
668
|
+
let liquidityNet = BigInt((await this.tickDataProvider.getTick(step.tickNext)).liquidityNet);
|
|
669
|
+
if (zeroForOne)
|
|
670
|
+
liquidityNet = liquidityNet * NEGATIVE_ONE;
|
|
671
|
+
state.liquidity = LiquidityMath.addDelta(state.liquidity, liquidityNet);
|
|
672
|
+
}
|
|
673
|
+
state.tick = zeroForOne ? step.tickNext - 1 : step.tickNext;
|
|
674
|
+
} else if (state.sqrtPriceX96 !== step.sqrtPriceStartX96) {
|
|
675
|
+
state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
return {
|
|
679
|
+
amountSpecifiedRemaining: state.amountSpecifiedRemaining,
|
|
680
|
+
amountCalculated: state.amountCalculated,
|
|
681
|
+
sqrtRatioX96: state.sqrtPriceX96,
|
|
682
|
+
liquidity: state.liquidity,
|
|
683
|
+
tickCurrent: state.tick
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
get tickSpacing() {
|
|
687
|
+
return TICK_SPACINGS[this.fee];
|
|
688
|
+
}
|
|
689
|
+
};
|
|
511
690
|
|
|
512
691
|
// src/utils/maxLiquidityForAmounts.ts
|
|
513
692
|
function maxLiquidityForAmount0Imprecise(sqrtRatioAX96, sqrtRatioBX96, amount0) {
|
|
@@ -550,36 +729,18 @@ function maxLiquidityForAmounts(sqrtRatioCurrentX96, sqrtRatioAX96, sqrtRatioBX9
|
|
|
550
729
|
}
|
|
551
730
|
return maxLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);
|
|
552
731
|
}
|
|
553
|
-
function
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
if (rounded < TickMath.MIN_TICK)
|
|
559
|
-
return rounded + tickSpacing;
|
|
560
|
-
if (rounded > TickMath.MAX_TICK)
|
|
561
|
-
return rounded - tickSpacing;
|
|
562
|
-
return rounded;
|
|
732
|
+
function encodeSqrtRatioX96(amount1, amount0) {
|
|
733
|
+
const numerator = BigInt(amount1) << 192n;
|
|
734
|
+
const denominator = BigInt(amount0);
|
|
735
|
+
const ratioX192 = numerator / denominator;
|
|
736
|
+
return swapSdkCore.sqrt(ratioX192);
|
|
563
737
|
}
|
|
564
738
|
|
|
565
|
-
// src/utils/
|
|
566
|
-
var PositionLibrary = class {
|
|
567
|
-
/**
|
|
568
|
-
* Cannot be constructed.
|
|
569
|
-
*/
|
|
570
|
-
constructor() {
|
|
571
|
-
}
|
|
572
|
-
// replicates the portions of Position#update required to compute unaccounted fees
|
|
573
|
-
static getTokensOwed(feeGrowthInside0LastX128, feeGrowthInside1LastX128, liquidity, feeGrowthInside0X128, feeGrowthInside1X128) {
|
|
574
|
-
const tokensOwed0 = subIn256(feeGrowthInside0X128, feeGrowthInside0LastX128) * liquidity / Q128;
|
|
575
|
-
const tokensOwed1 = subIn256(feeGrowthInside1X128, feeGrowthInside1LastX128) * liquidity / Q128;
|
|
576
|
-
return [tokensOwed0, tokensOwed1];
|
|
577
|
-
}
|
|
578
|
-
};
|
|
739
|
+
// src/utils/priceTickConversions.ts
|
|
579
740
|
function tickToPrice(baseToken, quoteToken, tick) {
|
|
580
741
|
const sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);
|
|
581
742
|
const ratioX192 = sqrtRatioX96 * sqrtRatioX96;
|
|
582
|
-
return baseToken.sortsBefore(quoteToken) ? new
|
|
743
|
+
return baseToken.sortsBefore(quoteToken) ? new swapSdkCore.Price(baseToken, quoteToken, Q192, ratioX192) : new swapSdkCore.Price(baseToken, quoteToken, ratioX192, Q192);
|
|
583
744
|
}
|
|
584
745
|
function priceToClosestTick(price) {
|
|
585
746
|
const sorted = price.baseCurrency.sortsBefore(price.quoteCurrency);
|
|
@@ -596,47 +757,6 @@ function priceToClosestTick(price) {
|
|
|
596
757
|
return tick;
|
|
597
758
|
}
|
|
598
759
|
|
|
599
|
-
// src/utils/tickLibrary.ts
|
|
600
|
-
var Q256 = 2n ** 256n;
|
|
601
|
-
function subIn256(x, y) {
|
|
602
|
-
const difference = x - y;
|
|
603
|
-
if (difference < ZERO) {
|
|
604
|
-
return Q256 + difference;
|
|
605
|
-
}
|
|
606
|
-
return difference;
|
|
607
|
-
}
|
|
608
|
-
var TickLibrary = class {
|
|
609
|
-
/**
|
|
610
|
-
* Cannot be constructed.
|
|
611
|
-
*/
|
|
612
|
-
constructor() {
|
|
613
|
-
}
|
|
614
|
-
static getFeeGrowthInside(feeGrowthOutsideLower, feeGrowthOutsideUpper, tickLower, tickUpper, tickCurrent, feeGrowthGlobal0X128, feeGrowthGlobal1X128) {
|
|
615
|
-
let feeGrowthBelow0X128;
|
|
616
|
-
let feeGrowthBelow1X128;
|
|
617
|
-
if (tickCurrent >= tickLower) {
|
|
618
|
-
feeGrowthBelow0X128 = feeGrowthOutsideLower.feeGrowthOutside0X128;
|
|
619
|
-
feeGrowthBelow1X128 = feeGrowthOutsideLower.feeGrowthOutside1X128;
|
|
620
|
-
} else {
|
|
621
|
-
feeGrowthBelow0X128 = subIn256(feeGrowthGlobal0X128, feeGrowthOutsideLower.feeGrowthOutside0X128);
|
|
622
|
-
feeGrowthBelow1X128 = subIn256(feeGrowthGlobal1X128, feeGrowthOutsideLower.feeGrowthOutside1X128);
|
|
623
|
-
}
|
|
624
|
-
let feeGrowthAbove0X128;
|
|
625
|
-
let feeGrowthAbove1X128;
|
|
626
|
-
if (tickCurrent < tickUpper) {
|
|
627
|
-
feeGrowthAbove0X128 = feeGrowthOutsideUpper.feeGrowthOutside0X128;
|
|
628
|
-
feeGrowthAbove1X128 = feeGrowthOutsideUpper.feeGrowthOutside1X128;
|
|
629
|
-
} else {
|
|
630
|
-
feeGrowthAbove0X128 = subIn256(feeGrowthGlobal0X128, feeGrowthOutsideUpper.feeGrowthOutside0X128);
|
|
631
|
-
feeGrowthAbove1X128 = subIn256(feeGrowthGlobal1X128, feeGrowthOutsideUpper.feeGrowthOutside1X128);
|
|
632
|
-
}
|
|
633
|
-
return [
|
|
634
|
-
subIn256(subIn256(feeGrowthGlobal0X128, feeGrowthBelow0X128), feeGrowthAbove0X128),
|
|
635
|
-
subIn256(subIn256(feeGrowthGlobal1X128, feeGrowthBelow1X128), feeGrowthAbove1X128)
|
|
636
|
-
];
|
|
637
|
-
}
|
|
638
|
-
};
|
|
639
|
-
|
|
640
760
|
// src/utils/positionMath.ts
|
|
641
761
|
function getToken0Amount(tickCurrent, tickLower, tickUpper, sqrtRatioX96, liquidity) {
|
|
642
762
|
if (tickCurrent < tickLower) {
|
|
@@ -670,903 +790,503 @@ var PositionMath = {
|
|
|
670
790
|
getToken0Amount,
|
|
671
791
|
getToken1Amount
|
|
672
792
|
};
|
|
673
|
-
function parseNumberToFraction(num, precision = 6) {
|
|
674
|
-
const scalar = 10 ** precision;
|
|
675
|
-
return new swapSdkCore.Fraction(BigInt(Math.floor(num * scalar)), BigInt(scalar));
|
|
676
|
-
}
|
|
677
793
|
|
|
678
|
-
// src/
|
|
679
|
-
var
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
return getEstimatedLPFeeByAmounts({
|
|
700
|
-
...rest,
|
|
701
|
-
amountA: amount,
|
|
702
|
-
amountB: sdk.CurrencyAmount.fromRawAmount(currency, sdk.MaxUint256)
|
|
703
|
-
});
|
|
704
|
-
}
|
|
705
|
-
function getEstimatedLPFeeByAmountsWithProtocolFee(options) {
|
|
706
|
-
try {
|
|
707
|
-
return tryGetEstimatedLPFeeByAmounts(options);
|
|
708
|
-
} catch (e) {
|
|
709
|
-
console.error(e);
|
|
710
|
-
return new sdk.Fraction(sdk.ZERO);
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
function getEstimatedLPFeeByAmounts({ protocolFee = ZERO_PERCENT, ...rest }) {
|
|
714
|
-
try {
|
|
715
|
-
const fee = tryGetEstimatedLPFeeByAmounts(rest);
|
|
716
|
-
return ONE_HUNDRED_PERCENT.subtract(protocolFee).multiply(fee).asFraction;
|
|
717
|
-
} catch (e) {
|
|
718
|
-
console.error(e);
|
|
719
|
-
return new sdk.Fraction(sdk.ZERO);
|
|
794
|
+
// src/entities/position.ts
|
|
795
|
+
var Position = class {
|
|
796
|
+
/**
|
|
797
|
+
* Constructs a position for a given pool with the given liquidity
|
|
798
|
+
* @param pool For which pool the liquidity is assigned
|
|
799
|
+
* @param liquidity The amount of liquidity that is in the position
|
|
800
|
+
* @param tickLower The lower tick of the position
|
|
801
|
+
* @param tickUpper The upper tick of the position
|
|
802
|
+
*/
|
|
803
|
+
constructor({ pool, liquidity, tickLower, tickUpper }) {
|
|
804
|
+
// cached resuts for the getters
|
|
805
|
+
this._token0Amount = null;
|
|
806
|
+
this._token1Amount = null;
|
|
807
|
+
this._mintAmounts = null;
|
|
808
|
+
invariant9__default.default(tickLower < tickUpper, "TICK_ORDER");
|
|
809
|
+
invariant9__default.default(tickLower >= TickMath.MIN_TICK && tickLower % pool.tickSpacing === 0, "TICK_LOWER");
|
|
810
|
+
invariant9__default.default(tickUpper <= TickMath.MAX_TICK && tickUpper % pool.tickSpacing === 0, "TICK_UPPER");
|
|
811
|
+
this.pool = pool;
|
|
812
|
+
this.tickLower = tickLower;
|
|
813
|
+
this.tickUpper = tickUpper;
|
|
814
|
+
this.liquidity = BigInt(liquidity);
|
|
720
815
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
sqrtRatioX96,
|
|
727
|
-
tickLower,
|
|
728
|
-
tickUpper,
|
|
729
|
-
mostActiveLiquidity,
|
|
730
|
-
fee,
|
|
731
|
-
insidePercentage = ONE_HUNDRED_PERCENT
|
|
732
|
-
}) {
|
|
733
|
-
invariant11__default.default(!Number.isNaN(fee) && fee >= 0, "INVALID_FEE");
|
|
734
|
-
const tickCurrent = TickMath.getTickAtSqrtRatio(sqrtRatioX96);
|
|
735
|
-
if (tickCurrent < tickLower || tickCurrent > tickUpper) {
|
|
736
|
-
return new sdk.Fraction(sdk.ZERO);
|
|
816
|
+
/**
|
|
817
|
+
* Returns the price of token0 at the lower tick
|
|
818
|
+
*/
|
|
819
|
+
get token0PriceLower() {
|
|
820
|
+
return tickToPrice(this.pool.token0, this.pool.token1, this.tickLower);
|
|
737
821
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
sqrtRatioX96
|
|
744
|
-
});
|
|
745
|
-
return insidePercentage.multiply(parseNumberToFraction(volume24H).multiply(BigInt(fee)).multiply(liquidity)).divide(MAX_FEE * (liquidity + mostActiveLiquidity)).asFraction;
|
|
746
|
-
}
|
|
747
|
-
function getDependentAmount(options) {
|
|
748
|
-
const { currency, amount, sqrtRatioX96, tickLower, tickUpper } = options;
|
|
749
|
-
const currentTick = TickMath.getTickAtSqrtRatio(sqrtRatioX96);
|
|
750
|
-
const liquidity = FeeCalculator.getLiquidityBySingleAmount(options);
|
|
751
|
-
const isToken0 = currency.wrapped.sortsBefore(amount.currency.wrapped);
|
|
752
|
-
const getTokenAmount = isToken0 ? PositionMath.getToken0Amount : PositionMath.getToken1Amount;
|
|
753
|
-
return sdk.CurrencyAmount.fromRawAmount(
|
|
754
|
-
currency,
|
|
755
|
-
getTokenAmount(currentTick, tickLower, tickUpper, sqrtRatioX96, liquidity)
|
|
756
|
-
);
|
|
757
|
-
}
|
|
758
|
-
function getLiquidityBySingleAmount({ amount, currency, ...rest }) {
|
|
759
|
-
return getLiquidityByAmountsAndPrice({
|
|
760
|
-
amountA: amount,
|
|
761
|
-
amountB: sdk.CurrencyAmount.fromRawAmount(currency, sdk.MaxUint256),
|
|
762
|
-
...rest
|
|
763
|
-
});
|
|
764
|
-
}
|
|
765
|
-
function getLiquidityByAmountsAndPrice({
|
|
766
|
-
amountA,
|
|
767
|
-
amountB,
|
|
768
|
-
tickUpper,
|
|
769
|
-
tickLower,
|
|
770
|
-
sqrtRatioX96
|
|
771
|
-
}) {
|
|
772
|
-
const isToken0 = amountA.currency.wrapped.sortsBefore(amountB.currency.wrapped);
|
|
773
|
-
const [inputAmount0, inputAmount1] = isToken0 ? [amountA.quotient, amountB.quotient] : [amountB.quotient, amountA.quotient];
|
|
774
|
-
const sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickLower);
|
|
775
|
-
const sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickUpper);
|
|
776
|
-
return maxLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, inputAmount0, inputAmount1, true);
|
|
777
|
-
}
|
|
778
|
-
function getAmountsByLiquidityAndPrice(options) {
|
|
779
|
-
const { currencyA, currencyB, liquidity, sqrtRatioX96, tickLower, tickUpper } = options;
|
|
780
|
-
const currentTick = TickMath.getTickAtSqrtRatio(sqrtRatioX96);
|
|
781
|
-
const isToken0 = currencyA.wrapped.sortsBefore(currencyB.wrapped);
|
|
782
|
-
const adjustedAmount0 = PositionMath.getToken0Amount(currentTick, tickLower, tickUpper, sqrtRatioX96, liquidity);
|
|
783
|
-
const adjustedAmount1 = PositionMath.getToken1Amount(currentTick, tickLower, tickUpper, sqrtRatioX96, liquidity);
|
|
784
|
-
return [
|
|
785
|
-
sdk.CurrencyAmount.fromRawAmount(currencyA, isToken0 ? adjustedAmount0 : adjustedAmount1),
|
|
786
|
-
sdk.CurrencyAmount.fromRawAmount(currencyB, isToken0 ? adjustedAmount1 : adjustedAmount0)
|
|
787
|
-
];
|
|
788
|
-
}
|
|
789
|
-
function getAmountsAtNewPrice({ newSqrtRatioX96, ...rest }) {
|
|
790
|
-
const { tickLower, tickUpper, amountA, amountB } = rest;
|
|
791
|
-
const liquidity = FeeCalculator.getLiquidityByAmountsAndPrice(rest);
|
|
792
|
-
return FeeCalculator.getAmountsByLiquidityAndPrice({
|
|
793
|
-
liquidity,
|
|
794
|
-
currencyA: amountA.currency,
|
|
795
|
-
currencyB: amountB.currency,
|
|
796
|
-
tickLower,
|
|
797
|
-
tickUpper,
|
|
798
|
-
sqrtRatioX96: newSqrtRatioX96
|
|
799
|
-
});
|
|
800
|
-
}
|
|
801
|
-
function getAverageLiquidity(ticks, tickSpacing, tickLower, tickUpper) {
|
|
802
|
-
invariant11__default.default(tickLower <= tickUpper, "INVALID_TICK_RANGE");
|
|
803
|
-
TickList.validateList(ticks, tickSpacing);
|
|
804
|
-
if (tickLower === tickUpper) {
|
|
805
|
-
return FeeCalculator.getLiquidityFromTick(ticks, tickLower);
|
|
822
|
+
/**
|
|
823
|
+
* Returns the price of token0 at the upper tick
|
|
824
|
+
*/
|
|
825
|
+
get token0PriceUpper() {
|
|
826
|
+
return tickToPrice(this.pool.token0, this.pool.token1, this.tickUpper);
|
|
806
827
|
}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
828
|
+
/**
|
|
829
|
+
* Returns the amount of token0 that this position's liquidity could be burned for at the current pool price
|
|
830
|
+
*/
|
|
831
|
+
get amount0() {
|
|
832
|
+
if (this._token0Amount === null) {
|
|
833
|
+
this._token0Amount = sdk.CurrencyAmount.fromRawAmount(
|
|
834
|
+
this.pool.token0,
|
|
835
|
+
PositionMath.getToken0Amount(
|
|
836
|
+
this.pool.tickCurrent,
|
|
837
|
+
this.tickLower,
|
|
838
|
+
this.tickUpper,
|
|
839
|
+
this.pool.sqrtRatioX96,
|
|
840
|
+
this.liquidity
|
|
841
|
+
)
|
|
842
|
+
);
|
|
819
843
|
}
|
|
820
|
-
|
|
821
|
-
}
|
|
822
|
-
weightedL += getWeightedLFromLastTickTo(tickUpper);
|
|
823
|
-
return weightedL / BigInt(tickUpper - tickLower);
|
|
824
|
-
}
|
|
825
|
-
function getLiquidityFromSqrtRatioX96(ticks, sqrtRatioX96) {
|
|
826
|
-
const tick = TickMath.getTickAtSqrtRatio(sqrtRatioX96);
|
|
827
|
-
return FeeCalculator.getLiquidityFromTick(ticks, tick);
|
|
828
|
-
}
|
|
829
|
-
function getLiquidityFromTick(ticks, tick) {
|
|
830
|
-
let liquidity = sdk.ZERO;
|
|
831
|
-
if (!ticks?.length)
|
|
832
|
-
return liquidity;
|
|
833
|
-
if (tick < ticks[0].index || tick > ticks[ticks.length - 1].index) {
|
|
834
|
-
return liquidity;
|
|
844
|
+
return this._token0Amount;
|
|
835
845
|
}
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
if (
|
|
841
|
-
|
|
846
|
+
/**
|
|
847
|
+
* Returns the amount of token1 that this position's liquidity could be burned for at the current pool price
|
|
848
|
+
*/
|
|
849
|
+
get amount1() {
|
|
850
|
+
if (this._token1Amount === null) {
|
|
851
|
+
this._token1Amount = sdk.CurrencyAmount.fromRawAmount(
|
|
852
|
+
this.pool.token1,
|
|
853
|
+
PositionMath.getToken1Amount(
|
|
854
|
+
this.pool.tickCurrent,
|
|
855
|
+
this.tickLower,
|
|
856
|
+
this.tickUpper,
|
|
857
|
+
this.pool.sqrtRatioX96,
|
|
858
|
+
this.liquidity
|
|
859
|
+
)
|
|
860
|
+
);
|
|
842
861
|
}
|
|
843
|
-
|
|
844
|
-
return liquidity;
|
|
845
|
-
}
|
|
846
|
-
var FEE_BASE = 10n ** 4n;
|
|
847
|
-
function parseProtocolFees(feeProtocol) {
|
|
848
|
-
const packed = Number(feeProtocol);
|
|
849
|
-
if (Number.isNaN(packed)) {
|
|
850
|
-
throw new Error(`Invalid fee protocol ${feeProtocol}`);
|
|
851
|
-
}
|
|
852
|
-
const token0ProtocolFee = packed % 2 ** 16;
|
|
853
|
-
const token1ProtocolFee = packed >> 16;
|
|
854
|
-
return [new sdk.Percent(token0ProtocolFee, FEE_BASE), new sdk.Percent(token1ProtocolFee, FEE_BASE)];
|
|
855
|
-
}
|
|
856
|
-
function sqrtRatioX96ToPrice(sqrtRatioX96, currencyA, currencyB) {
|
|
857
|
-
const ratioX192 = sqrtRatioX96 * sqrtRatioX96;
|
|
858
|
-
return currencyA.wrapped.sortsBefore(currencyB.wrapped) ? new swapSdkCore.Price(currencyA.wrapped, currencyB.wrapped, Q192, ratioX192) : new swapSdkCore.Price(currencyA.wrapped, currencyB.wrapped, ratioX192, Q192);
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
// src/entities/tick.ts
|
|
862
|
-
var Tick = class {
|
|
863
|
-
constructor({ index, liquidityGross, liquidityNet }) {
|
|
864
|
-
invariant11__default.default(index >= TickMath.MIN_TICK && index <= TickMath.MAX_TICK, "TICK");
|
|
865
|
-
this.index = index;
|
|
866
|
-
this.liquidityGross = BigInt(liquidityGross);
|
|
867
|
-
this.liquidityNet = BigInt(liquidityNet);
|
|
868
|
-
}
|
|
869
|
-
};
|
|
870
|
-
|
|
871
|
-
// src/entities/tickListDataProvider.ts
|
|
872
|
-
var TickListDataProvider = class {
|
|
873
|
-
constructor(ticks) {
|
|
874
|
-
const ticksMapped = ticks.map((t) => t instanceof Tick ? t : new Tick(t));
|
|
875
|
-
this.ticks = ticksMapped;
|
|
876
|
-
}
|
|
877
|
-
async getTick(tick) {
|
|
878
|
-
return TickList.getTick(this.ticks, tick);
|
|
879
|
-
}
|
|
880
|
-
async nextInitializedTickWithinOneWord(tick, lte, tickSpacing) {
|
|
881
|
-
return TickList.nextInitializedTickWithinOneWord(this.ticks, tick, lte, tickSpacing);
|
|
882
|
-
}
|
|
883
|
-
};
|
|
884
|
-
|
|
885
|
-
// src/entities/pool.ts
|
|
886
|
-
var NO_TICK_DATA_PROVIDER_DEFAULT = new NoTickDataProvider();
|
|
887
|
-
var Pool = class {
|
|
888
|
-
static getAddress(tokenA, tokenB, fee, initCodeHashManualOverride, deployerAddressOverride) {
|
|
889
|
-
return computePoolAddress({
|
|
890
|
-
deployerAddress: deployerAddressOverride ?? DEPLOYER_ADDRESSES[tokenA.chainId],
|
|
891
|
-
fee,
|
|
892
|
-
tokenA,
|
|
893
|
-
tokenB,
|
|
894
|
-
initCodeHashManualOverride
|
|
895
|
-
});
|
|
862
|
+
return this._token1Amount;
|
|
896
863
|
}
|
|
897
864
|
/**
|
|
898
|
-
*
|
|
899
|
-
* @param
|
|
900
|
-
* @
|
|
901
|
-
* @param fee The fee in hundredths of a bips of the input amount of every swap that is collected by the pool
|
|
902
|
-
* @param sqrtRatioX96 The sqrt of the current ratio of amounts of token1 to token0
|
|
903
|
-
* @param liquidity The current value of in range liquidity
|
|
904
|
-
* @param tickCurrent The current tick of the pool
|
|
905
|
-
* @param ticks The current state of the pool ticks or a data provider that can return tick data
|
|
865
|
+
* Returns the lower and upper sqrt ratios if the price 'slips' up to slippage tolerance percentage
|
|
866
|
+
* @param slippageTolerance The amount by which the price can 'slip' before the transaction will revert
|
|
867
|
+
* @returns The sqrt ratios after slippage
|
|
906
868
|
*/
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
869
|
+
ratiosAfterSlippage(slippageTolerance) {
|
|
870
|
+
const priceLower = this.pool.token0Price.asFraction.multiply(new sdk.Percent(1).subtract(slippageTolerance));
|
|
871
|
+
const priceUpper = this.pool.token0Price.asFraction.multiply(slippageTolerance.add(1));
|
|
872
|
+
let sqrtRatioX96Lower = encodeSqrtRatioX96(priceLower.numerator, priceLower.denominator);
|
|
873
|
+
if (sqrtRatioX96Lower <= TickMath.MIN_SQRT_RATIO) {
|
|
874
|
+
sqrtRatioX96Lower = TickMath.MIN_SQRT_RATIO + 1n;
|
|
875
|
+
}
|
|
876
|
+
let sqrtRatioX96Upper = encodeSqrtRatioX96(priceUpper.numerator, priceUpper.denominator);
|
|
877
|
+
if (sqrtRatioX96Upper >= TickMath.MAX_SQRT_RATIO) {
|
|
878
|
+
sqrtRatioX96Upper = TickMath.MAX_SQRT_RATIO - 1n;
|
|
879
|
+
}
|
|
880
|
+
return {
|
|
881
|
+
sqrtRatioX96Lower,
|
|
882
|
+
sqrtRatioX96Upper
|
|
883
|
+
};
|
|
915
884
|
}
|
|
916
885
|
/**
|
|
917
|
-
* Returns
|
|
918
|
-
*
|
|
919
|
-
* @
|
|
886
|
+
* Returns the minimum amounts that must be sent in order to safely mint the amount of liquidity held by the position
|
|
887
|
+
* with the given slippage tolerance
|
|
888
|
+
* @param slippageTolerance Tolerance of unfavorable slippage from the current price
|
|
889
|
+
* @returns The amounts, with slippage
|
|
920
890
|
*/
|
|
921
|
-
|
|
922
|
-
|
|
891
|
+
mintAmountsWithSlippage(slippageTolerance) {
|
|
892
|
+
const { sqrtRatioX96Upper, sqrtRatioX96Lower } = this.ratiosAfterSlippage(slippageTolerance);
|
|
893
|
+
const poolLower = new Pool(
|
|
894
|
+
this.pool.token0,
|
|
895
|
+
this.pool.token1,
|
|
896
|
+
this.pool.fee,
|
|
897
|
+
sqrtRatioX96Lower,
|
|
898
|
+
0,
|
|
899
|
+
TickMath.getTickAtSqrtRatio(sqrtRatioX96Lower)
|
|
900
|
+
);
|
|
901
|
+
const poolUpper = new Pool(
|
|
902
|
+
this.pool.token0,
|
|
903
|
+
this.pool.token1,
|
|
904
|
+
this.pool.fee,
|
|
905
|
+
sqrtRatioX96Upper,
|
|
906
|
+
0,
|
|
907
|
+
TickMath.getTickAtSqrtRatio(sqrtRatioX96Upper)
|
|
908
|
+
);
|
|
909
|
+
const positionThatWillBeCreated = Position.fromAmounts({
|
|
910
|
+
pool: this.pool,
|
|
911
|
+
tickLower: this.tickLower,
|
|
912
|
+
tickUpper: this.tickUpper,
|
|
913
|
+
...this.mintAmounts,
|
|
914
|
+
// the mint amounts are what will be passed as calldata
|
|
915
|
+
useFullPrecision: false
|
|
916
|
+
});
|
|
917
|
+
const { amount0 } = new Position({
|
|
918
|
+
pool: poolUpper,
|
|
919
|
+
liquidity: positionThatWillBeCreated.liquidity,
|
|
920
|
+
tickLower: this.tickLower,
|
|
921
|
+
tickUpper: this.tickUpper
|
|
922
|
+
}).mintAmounts;
|
|
923
|
+
const { amount1 } = new Position({
|
|
924
|
+
pool: poolLower,
|
|
925
|
+
liquidity: positionThatWillBeCreated.liquidity,
|
|
926
|
+
tickLower: this.tickLower,
|
|
927
|
+
tickUpper: this.tickUpper
|
|
928
|
+
}).mintAmounts;
|
|
929
|
+
return { amount0, amount1 };
|
|
923
930
|
}
|
|
924
931
|
/**
|
|
925
|
-
* Returns the
|
|
932
|
+
* Returns the minimum amounts that should be requested in order to safely burn the amount of liquidity held by the
|
|
933
|
+
* position with the given slippage tolerance
|
|
934
|
+
* @param slippageTolerance tolerance of unfavorable slippage from the current price
|
|
935
|
+
* @returns The amounts, with slippage
|
|
926
936
|
*/
|
|
927
|
-
|
|
928
|
-
|
|
937
|
+
burnAmountsWithSlippage(slippageTolerance) {
|
|
938
|
+
const { sqrtRatioX96Upper, sqrtRatioX96Lower } = this.ratiosAfterSlippage(slippageTolerance);
|
|
939
|
+
const poolLower = new Pool(
|
|
940
|
+
this.pool.token0,
|
|
941
|
+
this.pool.token1,
|
|
942
|
+
this.pool.fee,
|
|
943
|
+
sqrtRatioX96Lower,
|
|
944
|
+
0,
|
|
945
|
+
TickMath.getTickAtSqrtRatio(sqrtRatioX96Lower)
|
|
946
|
+
);
|
|
947
|
+
const poolUpper = new Pool(
|
|
948
|
+
this.pool.token0,
|
|
949
|
+
this.pool.token1,
|
|
950
|
+
this.pool.fee,
|
|
951
|
+
sqrtRatioX96Upper,
|
|
952
|
+
0,
|
|
953
|
+
TickMath.getTickAtSqrtRatio(sqrtRatioX96Upper)
|
|
954
|
+
);
|
|
955
|
+
const { amount0 } = new Position({
|
|
956
|
+
pool: poolUpper,
|
|
957
|
+
liquidity: this.liquidity,
|
|
958
|
+
tickLower: this.tickLower,
|
|
959
|
+
tickUpper: this.tickUpper
|
|
960
|
+
});
|
|
961
|
+
const { amount1 } = new Position({
|
|
962
|
+
pool: poolLower,
|
|
963
|
+
liquidity: this.liquidity,
|
|
964
|
+
tickLower: this.tickLower,
|
|
965
|
+
tickUpper: this.tickUpper
|
|
966
|
+
});
|
|
967
|
+
return { amount0: amount0.quotient, amount1: amount1.quotient };
|
|
929
968
|
}
|
|
930
969
|
/**
|
|
931
|
-
* Returns the
|
|
970
|
+
* Returns the minimum amounts that must be sent in order to mint the amount of liquidity held by the position at
|
|
971
|
+
* the current price for the pool
|
|
932
972
|
*/
|
|
933
|
-
get
|
|
934
|
-
|
|
973
|
+
get mintAmounts() {
|
|
974
|
+
if (this._mintAmounts === null) {
|
|
975
|
+
if (this.pool.tickCurrent < this.tickLower) {
|
|
976
|
+
return {
|
|
977
|
+
amount0: SqrtPriceMath.getAmount0Delta(
|
|
978
|
+
TickMath.getSqrtRatioAtTick(this.tickLower),
|
|
979
|
+
TickMath.getSqrtRatioAtTick(this.tickUpper),
|
|
980
|
+
this.liquidity,
|
|
981
|
+
true
|
|
982
|
+
),
|
|
983
|
+
amount1: ZERO
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
if (this.pool.tickCurrent < this.tickUpper) {
|
|
987
|
+
return {
|
|
988
|
+
amount0: SqrtPriceMath.getAmount0Delta(
|
|
989
|
+
this.pool.sqrtRatioX96,
|
|
990
|
+
TickMath.getSqrtRatioAtTick(this.tickUpper),
|
|
991
|
+
this.liquidity,
|
|
992
|
+
true
|
|
993
|
+
),
|
|
994
|
+
amount1: SqrtPriceMath.getAmount1Delta(
|
|
995
|
+
TickMath.getSqrtRatioAtTick(this.tickLower),
|
|
996
|
+
this.pool.sqrtRatioX96,
|
|
997
|
+
this.liquidity,
|
|
998
|
+
true
|
|
999
|
+
)
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
1002
|
+
return {
|
|
1003
|
+
amount0: ZERO,
|
|
1004
|
+
amount1: SqrtPriceMath.getAmount1Delta(
|
|
1005
|
+
TickMath.getSqrtRatioAtTick(this.tickLower),
|
|
1006
|
+
TickMath.getSqrtRatioAtTick(this.tickUpper),
|
|
1007
|
+
this.liquidity,
|
|
1008
|
+
true
|
|
1009
|
+
)
|
|
1010
|
+
};
|
|
1011
|
+
}
|
|
1012
|
+
return this._mintAmounts;
|
|
935
1013
|
}
|
|
936
1014
|
/**
|
|
937
|
-
*
|
|
938
|
-
*
|
|
939
|
-
* @
|
|
1015
|
+
* Computes the maximum amount of liquidity received for a given amount of token0, token1,
|
|
1016
|
+
* and the prices at the tick boundaries.
|
|
1017
|
+
* @param pool The pool for which the position should be created
|
|
1018
|
+
* @param tickLower The lower tick of the position
|
|
1019
|
+
* @param tickUpper The upper tick of the position
|
|
1020
|
+
* @param amount0 token0 amount
|
|
1021
|
+
* @param amount1 token1 amount
|
|
1022
|
+
* @param useFullPrecision If false, liquidity will be maximized according to what the router can calculate,
|
|
1023
|
+
* not what core can theoretically support
|
|
1024
|
+
* @returns The amount of liquidity for the position
|
|
940
1025
|
*/
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
1026
|
+
static fromAmounts({
|
|
1027
|
+
pool,
|
|
1028
|
+
tickLower,
|
|
1029
|
+
tickUpper,
|
|
1030
|
+
amount0,
|
|
1031
|
+
amount1,
|
|
1032
|
+
useFullPrecision
|
|
1033
|
+
}) {
|
|
1034
|
+
const sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickLower);
|
|
1035
|
+
const sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickUpper);
|
|
1036
|
+
return new Position({
|
|
1037
|
+
pool,
|
|
1038
|
+
tickLower,
|
|
1039
|
+
tickUpper,
|
|
1040
|
+
liquidity: maxLiquidityForAmounts(
|
|
1041
|
+
pool.sqrtRatioX96,
|
|
1042
|
+
sqrtRatioAX96,
|
|
1043
|
+
sqrtRatioBX96,
|
|
1044
|
+
amount0,
|
|
1045
|
+
amount1,
|
|
1046
|
+
useFullPrecision
|
|
1047
|
+
)
|
|
1048
|
+
});
|
|
944
1049
|
}
|
|
945
1050
|
/**
|
|
946
|
-
*
|
|
1051
|
+
* Computes a position with the maximum amount of liquidity received for a given amount of token0, assuming an unlimited amount of token1
|
|
1052
|
+
* @param pool The pool for which the position is created
|
|
1053
|
+
* @param tickLower The lower tick
|
|
1054
|
+
* @param tickUpper The upper tick
|
|
1055
|
+
* @param amount0 The desired amount of token0
|
|
1056
|
+
* @param useFullPrecision If true, liquidity will be maximized according to what the router can calculate,
|
|
1057
|
+
* not what core can theoretically support
|
|
1058
|
+
* @returns The position
|
|
947
1059
|
*/
|
|
948
|
-
|
|
949
|
-
|
|
1060
|
+
static fromAmount0({
|
|
1061
|
+
pool,
|
|
1062
|
+
tickLower,
|
|
1063
|
+
tickUpper,
|
|
1064
|
+
amount0,
|
|
1065
|
+
useFullPrecision
|
|
1066
|
+
}) {
|
|
1067
|
+
return Position.fromAmounts({ pool, tickLower, tickUpper, amount0, amount1: sdk.MaxUint256, useFullPrecision });
|
|
950
1068
|
}
|
|
951
1069
|
/**
|
|
952
|
-
*
|
|
953
|
-
* @param
|
|
954
|
-
* @param
|
|
955
|
-
* @
|
|
1070
|
+
* Computes a position with the maximum amount of liquidity received for a given amount of token1, assuming an unlimited amount of token0
|
|
1071
|
+
* @param pool The pool for which the position is created
|
|
1072
|
+
* @param tickLower The lower tick
|
|
1073
|
+
* @param tickUpper The upper tick
|
|
1074
|
+
* @param amount1 The desired amount of token1
|
|
1075
|
+
* @returns The position
|
|
956
1076
|
*/
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
tickCurrent
|
|
965
|
-
} = await this.swap(zeroForOne, inputAmount.quotient, sqrtPriceLimitX96);
|
|
966
|
-
const outputToken = zeroForOne ? this.token1 : this.token0;
|
|
967
|
-
return [
|
|
968
|
-
sdk.CurrencyAmount.fromRawAmount(outputToken, outputAmount * NEGATIVE_ONE),
|
|
969
|
-
new Pool(this.token0, this.token1, this.fee, sqrtRatioX96, liquidity, tickCurrent, this.tickDataProvider)
|
|
970
|
-
];
|
|
1077
|
+
static fromAmount1({
|
|
1078
|
+
pool,
|
|
1079
|
+
tickLower,
|
|
1080
|
+
tickUpper,
|
|
1081
|
+
amount1
|
|
1082
|
+
}) {
|
|
1083
|
+
return Position.fromAmounts({ pool, tickLower, tickUpper, amount0: sdk.MaxUint256, amount1, useFullPrecision: true });
|
|
971
1084
|
}
|
|
1085
|
+
};
|
|
1086
|
+
var Route = class {
|
|
972
1087
|
/**
|
|
973
|
-
*
|
|
974
|
-
* @param
|
|
975
|
-
* @param
|
|
976
|
-
* @
|
|
1088
|
+
* Creates an instance of route.
|
|
1089
|
+
* @param pools An array of `Pool` objects, ordered by the route the swap will take
|
|
1090
|
+
* @param input The input token
|
|
1091
|
+
* @param output The output token
|
|
977
1092
|
*/
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
const {
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
1093
|
+
constructor(pools, input, output) {
|
|
1094
|
+
this._midPrice = null;
|
|
1095
|
+
invariant9__default.default(pools.length > 0, "POOLS");
|
|
1096
|
+
const { chainId } = pools[0];
|
|
1097
|
+
const allOnSameChain = pools.every((pool) => pool.chainId === chainId);
|
|
1098
|
+
invariant9__default.default(allOnSameChain, "CHAIN_IDS");
|
|
1099
|
+
const wrappedInput = input.wrapped;
|
|
1100
|
+
invariant9__default.default(pools[0].involvesToken(wrappedInput), "INPUT");
|
|
1101
|
+
invariant9__default.default(pools[pools.length - 1].involvesToken(output.wrapped), "OUTPUT");
|
|
1102
|
+
const tokenPath = [wrappedInput];
|
|
1103
|
+
for (const [i, pool] of pools.entries()) {
|
|
1104
|
+
const currentInputToken = tokenPath[i];
|
|
1105
|
+
invariant9__default.default(currentInputToken.equals(pool.token0) || currentInputToken.equals(pool.token1), "PATH");
|
|
1106
|
+
const nextToken = currentInputToken.equals(pool.token0) ? pool.token1 : pool.token0;
|
|
1107
|
+
tokenPath.push(nextToken);
|
|
1108
|
+
}
|
|
1109
|
+
this.pools = pools;
|
|
1110
|
+
this.tokenPath = tokenPath;
|
|
1111
|
+
this.input = input;
|
|
1112
|
+
this.output = output ?? tokenPath[tokenPath.length - 1];
|
|
1113
|
+
}
|
|
1114
|
+
get chainId() {
|
|
1115
|
+
return this.pools[0].chainId;
|
|
994
1116
|
}
|
|
995
1117
|
/**
|
|
996
|
-
*
|
|
997
|
-
* @param zeroForOne Whether the amount in is token0 or token1
|
|
998
|
-
* @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)
|
|
999
|
-
* @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
|
|
1000
|
-
* @returns amountCalculated
|
|
1001
|
-
* @returns sqrtRatioX96
|
|
1002
|
-
* @returns liquidity
|
|
1003
|
-
* @returns tickCurrent
|
|
1118
|
+
* Returns the mid price of the route
|
|
1004
1119
|
*/
|
|
1005
|
-
|
|
1006
|
-
if (
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
const step = {};
|
|
1025
|
-
step.sqrtPriceStartX96 = state.sqrtPriceX96;
|
|
1026
|
-
[step.tickNext, step.initialized] = await this.tickDataProvider.nextInitializedTickWithinOneWord(
|
|
1027
|
-
state.tick,
|
|
1028
|
-
zeroForOne,
|
|
1029
|
-
this.tickSpacing
|
|
1030
|
-
);
|
|
1031
|
-
if (step.tickNext < TickMath.MIN_TICK) {
|
|
1032
|
-
step.tickNext = TickMath.MIN_TICK;
|
|
1033
|
-
} else if (step.tickNext > TickMath.MAX_TICK) {
|
|
1034
|
-
step.tickNext = TickMath.MAX_TICK;
|
|
1035
|
-
}
|
|
1036
|
-
step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext);
|
|
1037
|
-
[state.sqrtPriceX96, step.amountIn, step.amountOut, step.feeAmount] = SwapMath.computeSwapStep(
|
|
1038
|
-
state.sqrtPriceX96,
|
|
1039
|
-
(zeroForOne ? step.sqrtPriceNextX96 < sqrtPriceLimitX96 : step.sqrtPriceNextX96 > sqrtPriceLimitX96) ? sqrtPriceLimitX96 : step.sqrtPriceNextX96,
|
|
1040
|
-
state.liquidity,
|
|
1041
|
-
state.amountSpecifiedRemaining,
|
|
1042
|
-
this.fee
|
|
1043
|
-
);
|
|
1044
|
-
if (exactInput) {
|
|
1045
|
-
state.amountSpecifiedRemaining = state.amountSpecifiedRemaining - (step.amountIn + step.feeAmount);
|
|
1046
|
-
state.amountCalculated = state.amountCalculated - step.amountOut;
|
|
1047
|
-
} else {
|
|
1048
|
-
state.amountSpecifiedRemaining = state.amountSpecifiedRemaining + step.amountOut;
|
|
1049
|
-
state.amountCalculated = state.amountCalculated + (step.amountIn + step.feeAmount);
|
|
1050
|
-
}
|
|
1051
|
-
if (state.sqrtPriceX96 === step.sqrtPriceNextX96) {
|
|
1052
|
-
if (step.initialized) {
|
|
1053
|
-
let liquidityNet = BigInt((await this.tickDataProvider.getTick(step.tickNext)).liquidityNet);
|
|
1054
|
-
if (zeroForOne)
|
|
1055
|
-
liquidityNet = liquidityNet * NEGATIVE_ONE;
|
|
1056
|
-
state.liquidity = LiquidityMath.addDelta(state.liquidity, liquidityNet);
|
|
1057
|
-
}
|
|
1058
|
-
state.tick = zeroForOne ? step.tickNext - 1 : step.tickNext;
|
|
1059
|
-
} else if (state.sqrtPriceX96 !== step.sqrtPriceStartX96) {
|
|
1060
|
-
state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96);
|
|
1120
|
+
get midPrice() {
|
|
1121
|
+
if (this._midPrice !== null)
|
|
1122
|
+
return this._midPrice;
|
|
1123
|
+
const { price } = this.pools.slice(1).reduce(
|
|
1124
|
+
({ nextInput, price: price2 }, pool) => {
|
|
1125
|
+
return nextInput.equals(pool.token0) ? {
|
|
1126
|
+
nextInput: pool.token1,
|
|
1127
|
+
price: price2.multiply(pool.token0Price)
|
|
1128
|
+
} : {
|
|
1129
|
+
nextInput: pool.token0,
|
|
1130
|
+
price: price2.multiply(pool.token1Price)
|
|
1131
|
+
};
|
|
1132
|
+
},
|
|
1133
|
+
this.pools[0].token0.equals(this.input.wrapped) ? {
|
|
1134
|
+
nextInput: this.pools[0].token1,
|
|
1135
|
+
price: this.pools[0].token0Price
|
|
1136
|
+
} : {
|
|
1137
|
+
nextInput: this.pools[0].token0,
|
|
1138
|
+
price: this.pools[0].token1Price
|
|
1061
1139
|
}
|
|
1062
|
-
|
|
1063
|
-
return
|
|
1064
|
-
amountSpecifiedRemaining: state.amountSpecifiedRemaining,
|
|
1065
|
-
amountCalculated: state.amountCalculated,
|
|
1066
|
-
sqrtRatioX96: state.sqrtPriceX96,
|
|
1067
|
-
liquidity: state.liquidity,
|
|
1068
|
-
tickCurrent: state.tick
|
|
1069
|
-
};
|
|
1070
|
-
}
|
|
1071
|
-
get tickSpacing() {
|
|
1072
|
-
return TICK_SPACINGS[this.fee];
|
|
1140
|
+
);
|
|
1141
|
+
return this._midPrice = new swapSdkCore.Price(this.input, this.output, price.denominator, price.numerator);
|
|
1073
1142
|
}
|
|
1074
1143
|
};
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
this.pool = pool;
|
|
1092
|
-
this.tickLower = tickLower;
|
|
1093
|
-
this.tickUpper = tickUpper;
|
|
1094
|
-
this.liquidity = BigInt(liquidity);
|
|
1144
|
+
function tradeComparator(a, b) {
|
|
1145
|
+
invariant9__default.default(a.inputAmount.currency.equals(b.inputAmount.currency), "INPUT_CURRENCY");
|
|
1146
|
+
invariant9__default.default(a.outputAmount.currency.equals(b.outputAmount.currency), "OUTPUT_CURRENCY");
|
|
1147
|
+
if (a.outputAmount.equalTo(b.outputAmount)) {
|
|
1148
|
+
if (a.inputAmount.equalTo(b.inputAmount)) {
|
|
1149
|
+
const aHops = a.swaps.reduce((total, cur) => total + cur.route.tokenPath.length, 0);
|
|
1150
|
+
const bHops = b.swaps.reduce((total, cur) => total + cur.route.tokenPath.length, 0);
|
|
1151
|
+
return aHops - bHops;
|
|
1152
|
+
}
|
|
1153
|
+
if (a.inputAmount.lessThan(b.inputAmount)) {
|
|
1154
|
+
return -1;
|
|
1155
|
+
}
|
|
1156
|
+
return 1;
|
|
1157
|
+
}
|
|
1158
|
+
if (a.outputAmount.lessThan(b.outputAmount)) {
|
|
1159
|
+
return 1;
|
|
1095
1160
|
}
|
|
1161
|
+
return -1;
|
|
1162
|
+
}
|
|
1163
|
+
var Trade = class {
|
|
1096
1164
|
/**
|
|
1097
|
-
*
|
|
1165
|
+
* @deprecated Deprecated in favor of 'swaps' property. If the trade consists of multiple routes
|
|
1166
|
+
* this will return an error.
|
|
1167
|
+
*
|
|
1168
|
+
* When the trade consists of just a single route, this returns the route of the trade,
|
|
1169
|
+
* i.e. which pools the trade goes through.
|
|
1098
1170
|
*/
|
|
1099
|
-
get
|
|
1100
|
-
|
|
1171
|
+
get route() {
|
|
1172
|
+
invariant9__default.default(this.swaps.length == 1, "MULTIPLE_ROUTES");
|
|
1173
|
+
return this.swaps[0].route;
|
|
1101
1174
|
}
|
|
1102
1175
|
/**
|
|
1103
|
-
*
|
|
1176
|
+
* The input amount for the trade assuming no slippage.
|
|
1104
1177
|
*/
|
|
1105
|
-
get
|
|
1106
|
-
|
|
1178
|
+
get inputAmount() {
|
|
1179
|
+
if (this._inputAmount) {
|
|
1180
|
+
return this._inputAmount;
|
|
1181
|
+
}
|
|
1182
|
+
const inputCurrency = this.swaps[0].inputAmount.currency;
|
|
1183
|
+
const totalInputFromRoutes = this.swaps.map(({ inputAmount }) => inputAmount).reduce((total, cur) => total.add(cur), sdk.CurrencyAmount.fromRawAmount(inputCurrency, 0));
|
|
1184
|
+
this._inputAmount = totalInputFromRoutes;
|
|
1185
|
+
return this._inputAmount;
|
|
1107
1186
|
}
|
|
1108
1187
|
/**
|
|
1109
|
-
*
|
|
1188
|
+
* The output amount for the trade assuming no slippage.
|
|
1110
1189
|
*/
|
|
1111
|
-
get
|
|
1112
|
-
if (this.
|
|
1113
|
-
this.
|
|
1114
|
-
this.pool.token0,
|
|
1115
|
-
PositionMath.getToken0Amount(
|
|
1116
|
-
this.pool.tickCurrent,
|
|
1117
|
-
this.tickLower,
|
|
1118
|
-
this.tickUpper,
|
|
1119
|
-
this.pool.sqrtRatioX96,
|
|
1120
|
-
this.liquidity
|
|
1121
|
-
)
|
|
1122
|
-
);
|
|
1190
|
+
get outputAmount() {
|
|
1191
|
+
if (this._outputAmount) {
|
|
1192
|
+
return this._outputAmount;
|
|
1123
1193
|
}
|
|
1124
|
-
|
|
1194
|
+
const outputCurrency = this.swaps[0].outputAmount.currency;
|
|
1195
|
+
const totalOutputFromRoutes = this.swaps.map(({ outputAmount }) => outputAmount).reduce((total, cur) => total.add(cur), sdk.CurrencyAmount.fromRawAmount(outputCurrency, 0));
|
|
1196
|
+
this._outputAmount = totalOutputFromRoutes;
|
|
1197
|
+
return this._outputAmount;
|
|
1125
1198
|
}
|
|
1126
1199
|
/**
|
|
1127
|
-
*
|
|
1200
|
+
* The price expressed in terms of output amount/input amount.
|
|
1128
1201
|
*/
|
|
1129
|
-
get
|
|
1130
|
-
|
|
1131
|
-
this.
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
this.tickUpper,
|
|
1137
|
-
this.pool.sqrtRatioX96,
|
|
1138
|
-
this.liquidity
|
|
1139
|
-
)
|
|
1140
|
-
);
|
|
1141
|
-
}
|
|
1142
|
-
return this._token1Amount;
|
|
1202
|
+
get executionPrice() {
|
|
1203
|
+
return this._executionPrice ?? (this._executionPrice = new sdk.Price(
|
|
1204
|
+
this.inputAmount.currency,
|
|
1205
|
+
this.outputAmount.currency,
|
|
1206
|
+
this.inputAmount.quotient,
|
|
1207
|
+
this.outputAmount.quotient
|
|
1208
|
+
));
|
|
1143
1209
|
}
|
|
1144
1210
|
/**
|
|
1145
|
-
* Returns the
|
|
1146
|
-
* @param slippageTolerance The amount by which the price can 'slip' before the transaction will revert
|
|
1147
|
-
* @returns The sqrt ratios after slippage
|
|
1211
|
+
* Returns the percent difference between the route's mid price and the price impact
|
|
1148
1212
|
*/
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
let sqrtRatioX96Lower = encodeSqrtRatioX96(priceLower.numerator, priceLower.denominator);
|
|
1153
|
-
if (sqrtRatioX96Lower <= TickMath.MIN_SQRT_RATIO) {
|
|
1154
|
-
sqrtRatioX96Lower = TickMath.MIN_SQRT_RATIO + 1n;
|
|
1213
|
+
get priceImpact() {
|
|
1214
|
+
if (this._priceImpact) {
|
|
1215
|
+
return this._priceImpact;
|
|
1155
1216
|
}
|
|
1156
|
-
let
|
|
1157
|
-
|
|
1158
|
-
|
|
1217
|
+
let spotOutputAmount = sdk.CurrencyAmount.fromRawAmount(this.outputAmount.currency, 0);
|
|
1218
|
+
for (const { route, inputAmount } of this.swaps) {
|
|
1219
|
+
const { midPrice } = route;
|
|
1220
|
+
spotOutputAmount = spotOutputAmount.add(midPrice.quote(inputAmount));
|
|
1159
1221
|
}
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
};
|
|
1222
|
+
const priceImpact = spotOutputAmount.subtract(this.outputAmount).divide(spotOutputAmount);
|
|
1223
|
+
this._priceImpact = new sdk.Percent(priceImpact.numerator, priceImpact.denominator);
|
|
1224
|
+
return this._priceImpact;
|
|
1164
1225
|
}
|
|
1165
1226
|
/**
|
|
1166
|
-
*
|
|
1167
|
-
*
|
|
1168
|
-
* @
|
|
1169
|
-
* @
|
|
1227
|
+
* Constructs an exact in trade with the given amount in and route
|
|
1228
|
+
* @template TInput The input token, either Ether or an ERC-20
|
|
1229
|
+
* @template TOutput The output token, either Ether or an ERC-20
|
|
1230
|
+
* @param route The route of the exact in trade
|
|
1231
|
+
* @param amountIn The amount being passed in
|
|
1232
|
+
* @returns The exact in trade
|
|
1170
1233
|
*/
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
const poolLower = new Pool(
|
|
1174
|
-
this.pool.token0,
|
|
1175
|
-
this.pool.token1,
|
|
1176
|
-
this.pool.fee,
|
|
1177
|
-
sqrtRatioX96Lower,
|
|
1178
|
-
0,
|
|
1179
|
-
TickMath.getTickAtSqrtRatio(sqrtRatioX96Lower)
|
|
1180
|
-
);
|
|
1181
|
-
const poolUpper = new Pool(
|
|
1182
|
-
this.pool.token0,
|
|
1183
|
-
this.pool.token1,
|
|
1184
|
-
this.pool.fee,
|
|
1185
|
-
sqrtRatioX96Upper,
|
|
1186
|
-
0,
|
|
1187
|
-
TickMath.getTickAtSqrtRatio(sqrtRatioX96Upper)
|
|
1188
|
-
);
|
|
1189
|
-
const positionThatWillBeCreated = Position.fromAmounts({
|
|
1190
|
-
pool: this.pool,
|
|
1191
|
-
tickLower: this.tickLower,
|
|
1192
|
-
tickUpper: this.tickUpper,
|
|
1193
|
-
...this.mintAmounts,
|
|
1194
|
-
// the mint amounts are what will be passed as calldata
|
|
1195
|
-
useFullPrecision: false
|
|
1196
|
-
});
|
|
1197
|
-
const { amount0 } = new Position({
|
|
1198
|
-
pool: poolUpper,
|
|
1199
|
-
liquidity: positionThatWillBeCreated.liquidity,
|
|
1200
|
-
tickLower: this.tickLower,
|
|
1201
|
-
tickUpper: this.tickUpper
|
|
1202
|
-
}).mintAmounts;
|
|
1203
|
-
const { amount1 } = new Position({
|
|
1204
|
-
pool: poolLower,
|
|
1205
|
-
liquidity: positionThatWillBeCreated.liquidity,
|
|
1206
|
-
tickLower: this.tickLower,
|
|
1207
|
-
tickUpper: this.tickUpper
|
|
1208
|
-
}).mintAmounts;
|
|
1209
|
-
return { amount0, amount1 };
|
|
1234
|
+
static async exactIn(route, amountIn) {
|
|
1235
|
+
return Trade.fromRoute(route, amountIn, sdk.TradeType.EXACT_INPUT);
|
|
1210
1236
|
}
|
|
1211
1237
|
/**
|
|
1212
|
-
*
|
|
1213
|
-
*
|
|
1214
|
-
* @
|
|
1215
|
-
* @
|
|
1238
|
+
* Constructs an exact out trade with the given amount out and route
|
|
1239
|
+
* @template TInput The input token, either Ether or an ERC-20
|
|
1240
|
+
* @template TOutput The output token, either Ether or an ERC-20
|
|
1241
|
+
* @param route The route of the exact out trade
|
|
1242
|
+
* @param amountOut The amount returned by the trade
|
|
1243
|
+
* @returns The exact out trade
|
|
1216
1244
|
*/
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
const poolLower = new Pool(
|
|
1220
|
-
this.pool.token0,
|
|
1221
|
-
this.pool.token1,
|
|
1222
|
-
this.pool.fee,
|
|
1223
|
-
sqrtRatioX96Lower,
|
|
1224
|
-
0,
|
|
1225
|
-
TickMath.getTickAtSqrtRatio(sqrtRatioX96Lower)
|
|
1226
|
-
);
|
|
1227
|
-
const poolUpper = new Pool(
|
|
1228
|
-
this.pool.token0,
|
|
1229
|
-
this.pool.token1,
|
|
1230
|
-
this.pool.fee,
|
|
1231
|
-
sqrtRatioX96Upper,
|
|
1232
|
-
0,
|
|
1233
|
-
TickMath.getTickAtSqrtRatio(sqrtRatioX96Upper)
|
|
1234
|
-
);
|
|
1235
|
-
const { amount0 } = new Position({
|
|
1236
|
-
pool: poolUpper,
|
|
1237
|
-
liquidity: this.liquidity,
|
|
1238
|
-
tickLower: this.tickLower,
|
|
1239
|
-
tickUpper: this.tickUpper
|
|
1240
|
-
});
|
|
1241
|
-
const { amount1 } = new Position({
|
|
1242
|
-
pool: poolLower,
|
|
1243
|
-
liquidity: this.liquidity,
|
|
1244
|
-
tickLower: this.tickLower,
|
|
1245
|
-
tickUpper: this.tickUpper
|
|
1246
|
-
});
|
|
1247
|
-
return { amount0: amount0.quotient, amount1: amount1.quotient };
|
|
1245
|
+
static async exactOut(route, amountOut) {
|
|
1246
|
+
return Trade.fromRoute(route, amountOut, sdk.TradeType.EXACT_OUTPUT);
|
|
1248
1247
|
}
|
|
1249
1248
|
/**
|
|
1250
|
-
*
|
|
1251
|
-
*
|
|
1249
|
+
* Constructs a trade by simulating swaps through the given route
|
|
1250
|
+
* @template TInput The input token, either Ether or an ERC-20.
|
|
1251
|
+
* @template TOutput The output token, either Ether or an ERC-20.
|
|
1252
|
+
* @template TTradeType The type of the trade, either exact in or exact out.
|
|
1253
|
+
* @param route route to swap through
|
|
1254
|
+
* @param amount the amount specified, either input or output, depending on tradeType
|
|
1255
|
+
* @param tradeType whether the trade is an exact input or exact output swap
|
|
1256
|
+
* @returns The route
|
|
1252
1257
|
*/
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
};
|
|
1258
|
+
static async fromRoute(route, amount, tradeType) {
|
|
1259
|
+
const amounts = new Array(route.tokenPath.length);
|
|
1260
|
+
let inputAmount;
|
|
1261
|
+
let outputAmount;
|
|
1262
|
+
if (tradeType === sdk.TradeType.EXACT_INPUT) {
|
|
1263
|
+
invariant9__default.default(amount.currency.equals(route.input), "INPUT");
|
|
1264
|
+
amounts[0] = amount.wrapped;
|
|
1265
|
+
for (let i = 0; i < route.tokenPath.length - 1; i++) {
|
|
1266
|
+
const pool = route.pools[i];
|
|
1267
|
+
const [outputAmount2] = await pool.getOutputAmount(amounts[i]);
|
|
1268
|
+
amounts[i + 1] = outputAmount2;
|
|
1265
1269
|
}
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
)
|
|
1280
|
-
};
|
|
1270
|
+
inputAmount = sdk.CurrencyAmount.fromFractionalAmount(route.input, amount.numerator, amount.denominator);
|
|
1271
|
+
outputAmount = sdk.CurrencyAmount.fromFractionalAmount(
|
|
1272
|
+
route.output,
|
|
1273
|
+
amounts[amounts.length - 1].numerator,
|
|
1274
|
+
amounts[amounts.length - 1].denominator
|
|
1275
|
+
);
|
|
1276
|
+
} else {
|
|
1277
|
+
invariant9__default.default(amount.currency.equals(route.output), "OUTPUT");
|
|
1278
|
+
amounts[amounts.length - 1] = amount.wrapped;
|
|
1279
|
+
for (let i = route.tokenPath.length - 1; i > 0; i--) {
|
|
1280
|
+
const pool = route.pools[i - 1];
|
|
1281
|
+
const [inputAmount2] = await pool.getInputAmount(amounts[i]);
|
|
1282
|
+
amounts[i - 1] = inputAmount2;
|
|
1281
1283
|
}
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
amount1: SqrtPriceMath.getAmount1Delta(
|
|
1285
|
-
TickMath.getSqrtRatioAtTick(this.tickLower),
|
|
1286
|
-
TickMath.getSqrtRatioAtTick(this.tickUpper),
|
|
1287
|
-
this.liquidity,
|
|
1288
|
-
true
|
|
1289
|
-
)
|
|
1290
|
-
};
|
|
1284
|
+
inputAmount = sdk.CurrencyAmount.fromFractionalAmount(route.input, amounts[0].numerator, amounts[0].denominator);
|
|
1285
|
+
outputAmount = sdk.CurrencyAmount.fromFractionalAmount(route.output, amount.numerator, amount.denominator);
|
|
1291
1286
|
}
|
|
1292
|
-
return
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
* Computes the maximum amount of liquidity received for a given amount of token0, token1,
|
|
1296
|
-
* and the prices at the tick boundaries.
|
|
1297
|
-
* @param pool The pool for which the position should be created
|
|
1298
|
-
* @param tickLower The lower tick of the position
|
|
1299
|
-
* @param tickUpper The upper tick of the position
|
|
1300
|
-
* @param amount0 token0 amount
|
|
1301
|
-
* @param amount1 token1 amount
|
|
1302
|
-
* @param useFullPrecision If false, liquidity will be maximized according to what the router can calculate,
|
|
1303
|
-
* not what core can theoretically support
|
|
1304
|
-
* @returns The amount of liquidity for the position
|
|
1305
|
-
*/
|
|
1306
|
-
static fromAmounts({
|
|
1307
|
-
pool,
|
|
1308
|
-
tickLower,
|
|
1309
|
-
tickUpper,
|
|
1310
|
-
amount0,
|
|
1311
|
-
amount1,
|
|
1312
|
-
useFullPrecision
|
|
1313
|
-
}) {
|
|
1314
|
-
const sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickLower);
|
|
1315
|
-
const sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickUpper);
|
|
1316
|
-
return new Position({
|
|
1317
|
-
pool,
|
|
1318
|
-
tickLower,
|
|
1319
|
-
tickUpper,
|
|
1320
|
-
liquidity: maxLiquidityForAmounts(
|
|
1321
|
-
pool.sqrtRatioX96,
|
|
1322
|
-
sqrtRatioAX96,
|
|
1323
|
-
sqrtRatioBX96,
|
|
1324
|
-
amount0,
|
|
1325
|
-
amount1,
|
|
1326
|
-
useFullPrecision
|
|
1327
|
-
)
|
|
1328
|
-
});
|
|
1329
|
-
}
|
|
1330
|
-
/**
|
|
1331
|
-
* Computes a position with the maximum amount of liquidity received for a given amount of token0, assuming an unlimited amount of token1
|
|
1332
|
-
* @param pool The pool for which the position is created
|
|
1333
|
-
* @param tickLower The lower tick
|
|
1334
|
-
* @param tickUpper The upper tick
|
|
1335
|
-
* @param amount0 The desired amount of token0
|
|
1336
|
-
* @param useFullPrecision If true, liquidity will be maximized according to what the router can calculate,
|
|
1337
|
-
* not what core can theoretically support
|
|
1338
|
-
* @returns The position
|
|
1339
|
-
*/
|
|
1340
|
-
static fromAmount0({
|
|
1341
|
-
pool,
|
|
1342
|
-
tickLower,
|
|
1343
|
-
tickUpper,
|
|
1344
|
-
amount0,
|
|
1345
|
-
useFullPrecision
|
|
1346
|
-
}) {
|
|
1347
|
-
return Position.fromAmounts({ pool, tickLower, tickUpper, amount0, amount1: sdk.MaxUint256, useFullPrecision });
|
|
1348
|
-
}
|
|
1349
|
-
/**
|
|
1350
|
-
* Computes a position with the maximum amount of liquidity received for a given amount of token1, assuming an unlimited amount of token0
|
|
1351
|
-
* @param pool The pool for which the position is created
|
|
1352
|
-
* @param tickLower The lower tick
|
|
1353
|
-
* @param tickUpper The upper tick
|
|
1354
|
-
* @param amount1 The desired amount of token1
|
|
1355
|
-
* @returns The position
|
|
1356
|
-
*/
|
|
1357
|
-
static fromAmount1({
|
|
1358
|
-
pool,
|
|
1359
|
-
tickLower,
|
|
1360
|
-
tickUpper,
|
|
1361
|
-
amount1
|
|
1362
|
-
}) {
|
|
1363
|
-
return Position.fromAmounts({ pool, tickLower, tickUpper, amount0: sdk.MaxUint256, amount1, useFullPrecision: true });
|
|
1364
|
-
}
|
|
1365
|
-
};
|
|
1366
|
-
var Route = class {
|
|
1367
|
-
/**
|
|
1368
|
-
* Creates an instance of route.
|
|
1369
|
-
* @param pools An array of `Pool` objects, ordered by the route the swap will take
|
|
1370
|
-
* @param input The input token
|
|
1371
|
-
* @param output The output token
|
|
1372
|
-
*/
|
|
1373
|
-
constructor(pools, input, output) {
|
|
1374
|
-
this._midPrice = null;
|
|
1375
|
-
invariant11__default.default(pools.length > 0, "POOLS");
|
|
1376
|
-
const { chainId } = pools[0];
|
|
1377
|
-
const allOnSameChain = pools.every((pool) => pool.chainId === chainId);
|
|
1378
|
-
invariant11__default.default(allOnSameChain, "CHAIN_IDS");
|
|
1379
|
-
const wrappedInput = input.wrapped;
|
|
1380
|
-
invariant11__default.default(pools[0].involvesToken(wrappedInput), "INPUT");
|
|
1381
|
-
invariant11__default.default(pools[pools.length - 1].involvesToken(output.wrapped), "OUTPUT");
|
|
1382
|
-
const tokenPath = [wrappedInput];
|
|
1383
|
-
for (const [i, pool] of pools.entries()) {
|
|
1384
|
-
const currentInputToken = tokenPath[i];
|
|
1385
|
-
invariant11__default.default(currentInputToken.equals(pool.token0) || currentInputToken.equals(pool.token1), "PATH");
|
|
1386
|
-
const nextToken = currentInputToken.equals(pool.token0) ? pool.token1 : pool.token0;
|
|
1387
|
-
tokenPath.push(nextToken);
|
|
1388
|
-
}
|
|
1389
|
-
this.pools = pools;
|
|
1390
|
-
this.tokenPath = tokenPath;
|
|
1391
|
-
this.input = input;
|
|
1392
|
-
this.output = output ?? tokenPath[tokenPath.length - 1];
|
|
1393
|
-
}
|
|
1394
|
-
get chainId() {
|
|
1395
|
-
return this.pools[0].chainId;
|
|
1396
|
-
}
|
|
1397
|
-
/**
|
|
1398
|
-
* Returns the mid price of the route
|
|
1399
|
-
*/
|
|
1400
|
-
get midPrice() {
|
|
1401
|
-
if (this._midPrice !== null)
|
|
1402
|
-
return this._midPrice;
|
|
1403
|
-
const { price } = this.pools.slice(1).reduce(
|
|
1404
|
-
({ nextInput, price: price2 }, pool) => {
|
|
1405
|
-
return nextInput.equals(pool.token0) ? {
|
|
1406
|
-
nextInput: pool.token1,
|
|
1407
|
-
price: price2.multiply(pool.token0Price)
|
|
1408
|
-
} : {
|
|
1409
|
-
nextInput: pool.token0,
|
|
1410
|
-
price: price2.multiply(pool.token1Price)
|
|
1411
|
-
};
|
|
1412
|
-
},
|
|
1413
|
-
this.pools[0].token0.equals(this.input.wrapped) ? {
|
|
1414
|
-
nextInput: this.pools[0].token1,
|
|
1415
|
-
price: this.pools[0].token0Price
|
|
1416
|
-
} : {
|
|
1417
|
-
nextInput: this.pools[0].token0,
|
|
1418
|
-
price: this.pools[0].token1Price
|
|
1419
|
-
}
|
|
1420
|
-
);
|
|
1421
|
-
return this._midPrice = new swapSdkCore.Price(this.input, this.output, price.denominator, price.numerator);
|
|
1422
|
-
}
|
|
1423
|
-
};
|
|
1424
|
-
function tradeComparator(a, b) {
|
|
1425
|
-
invariant11__default.default(a.inputAmount.currency.equals(b.inputAmount.currency), "INPUT_CURRENCY");
|
|
1426
|
-
invariant11__default.default(a.outputAmount.currency.equals(b.outputAmount.currency), "OUTPUT_CURRENCY");
|
|
1427
|
-
if (a.outputAmount.equalTo(b.outputAmount)) {
|
|
1428
|
-
if (a.inputAmount.equalTo(b.inputAmount)) {
|
|
1429
|
-
const aHops = a.swaps.reduce((total, cur) => total + cur.route.tokenPath.length, 0);
|
|
1430
|
-
const bHops = b.swaps.reduce((total, cur) => total + cur.route.tokenPath.length, 0);
|
|
1431
|
-
return aHops - bHops;
|
|
1432
|
-
}
|
|
1433
|
-
if (a.inputAmount.lessThan(b.inputAmount)) {
|
|
1434
|
-
return -1;
|
|
1435
|
-
}
|
|
1436
|
-
return 1;
|
|
1437
|
-
}
|
|
1438
|
-
if (a.outputAmount.lessThan(b.outputAmount)) {
|
|
1439
|
-
return 1;
|
|
1440
|
-
}
|
|
1441
|
-
return -1;
|
|
1442
|
-
}
|
|
1443
|
-
var Trade = class {
|
|
1444
|
-
/**
|
|
1445
|
-
* @deprecated Deprecated in favor of 'swaps' property. If the trade consists of multiple routes
|
|
1446
|
-
* this will return an error.
|
|
1447
|
-
*
|
|
1448
|
-
* When the trade consists of just a single route, this returns the route of the trade,
|
|
1449
|
-
* i.e. which pools the trade goes through.
|
|
1450
|
-
*/
|
|
1451
|
-
get route() {
|
|
1452
|
-
invariant11__default.default(this.swaps.length == 1, "MULTIPLE_ROUTES");
|
|
1453
|
-
return this.swaps[0].route;
|
|
1454
|
-
}
|
|
1455
|
-
/**
|
|
1456
|
-
* The input amount for the trade assuming no slippage.
|
|
1457
|
-
*/
|
|
1458
|
-
get inputAmount() {
|
|
1459
|
-
if (this._inputAmount) {
|
|
1460
|
-
return this._inputAmount;
|
|
1461
|
-
}
|
|
1462
|
-
const inputCurrency = this.swaps[0].inputAmount.currency;
|
|
1463
|
-
const totalInputFromRoutes = this.swaps.map(({ inputAmount }) => inputAmount).reduce((total, cur) => total.add(cur), sdk.CurrencyAmount.fromRawAmount(inputCurrency, 0));
|
|
1464
|
-
this._inputAmount = totalInputFromRoutes;
|
|
1465
|
-
return this._inputAmount;
|
|
1466
|
-
}
|
|
1467
|
-
/**
|
|
1468
|
-
* The output amount for the trade assuming no slippage.
|
|
1469
|
-
*/
|
|
1470
|
-
get outputAmount() {
|
|
1471
|
-
if (this._outputAmount) {
|
|
1472
|
-
return this._outputAmount;
|
|
1473
|
-
}
|
|
1474
|
-
const outputCurrency = this.swaps[0].outputAmount.currency;
|
|
1475
|
-
const totalOutputFromRoutes = this.swaps.map(({ outputAmount }) => outputAmount).reduce((total, cur) => total.add(cur), sdk.CurrencyAmount.fromRawAmount(outputCurrency, 0));
|
|
1476
|
-
this._outputAmount = totalOutputFromRoutes;
|
|
1477
|
-
return this._outputAmount;
|
|
1478
|
-
}
|
|
1479
|
-
/**
|
|
1480
|
-
* The price expressed in terms of output amount/input amount.
|
|
1481
|
-
*/
|
|
1482
|
-
get executionPrice() {
|
|
1483
|
-
return this._executionPrice ?? (this._executionPrice = new sdk.Price(
|
|
1484
|
-
this.inputAmount.currency,
|
|
1485
|
-
this.outputAmount.currency,
|
|
1486
|
-
this.inputAmount.quotient,
|
|
1487
|
-
this.outputAmount.quotient
|
|
1488
|
-
));
|
|
1489
|
-
}
|
|
1490
|
-
/**
|
|
1491
|
-
* Returns the percent difference between the route's mid price and the price impact
|
|
1492
|
-
*/
|
|
1493
|
-
get priceImpact() {
|
|
1494
|
-
if (this._priceImpact) {
|
|
1495
|
-
return this._priceImpact;
|
|
1496
|
-
}
|
|
1497
|
-
let spotOutputAmount = sdk.CurrencyAmount.fromRawAmount(this.outputAmount.currency, 0);
|
|
1498
|
-
for (const { route, inputAmount } of this.swaps) {
|
|
1499
|
-
const { midPrice } = route;
|
|
1500
|
-
spotOutputAmount = spotOutputAmount.add(midPrice.quote(inputAmount));
|
|
1501
|
-
}
|
|
1502
|
-
const priceImpact = spotOutputAmount.subtract(this.outputAmount).divide(spotOutputAmount);
|
|
1503
|
-
this._priceImpact = new sdk.Percent(priceImpact.numerator, priceImpact.denominator);
|
|
1504
|
-
return this._priceImpact;
|
|
1505
|
-
}
|
|
1506
|
-
/**
|
|
1507
|
-
* Constructs an exact in trade with the given amount in and route
|
|
1508
|
-
* @template TInput The input token, either Ether or an ERC-20
|
|
1509
|
-
* @template TOutput The output token, either Ether or an ERC-20
|
|
1510
|
-
* @param route The route of the exact in trade
|
|
1511
|
-
* @param amountIn The amount being passed in
|
|
1512
|
-
* @returns The exact in trade
|
|
1513
|
-
*/
|
|
1514
|
-
static async exactIn(route, amountIn) {
|
|
1515
|
-
return Trade.fromRoute(route, amountIn, sdk.TradeType.EXACT_INPUT);
|
|
1516
|
-
}
|
|
1517
|
-
/**
|
|
1518
|
-
* Constructs an exact out trade with the given amount out and route
|
|
1519
|
-
* @template TInput The input token, either Ether or an ERC-20
|
|
1520
|
-
* @template TOutput The output token, either Ether or an ERC-20
|
|
1521
|
-
* @param route The route of the exact out trade
|
|
1522
|
-
* @param amountOut The amount returned by the trade
|
|
1523
|
-
* @returns The exact out trade
|
|
1524
|
-
*/
|
|
1525
|
-
static async exactOut(route, amountOut) {
|
|
1526
|
-
return Trade.fromRoute(route, amountOut, sdk.TradeType.EXACT_OUTPUT);
|
|
1527
|
-
}
|
|
1528
|
-
/**
|
|
1529
|
-
* Constructs a trade by simulating swaps through the given route
|
|
1530
|
-
* @template TInput The input token, either Ether or an ERC-20.
|
|
1531
|
-
* @template TOutput The output token, either Ether or an ERC-20.
|
|
1532
|
-
* @template TTradeType The type of the trade, either exact in or exact out.
|
|
1533
|
-
* @param route route to swap through
|
|
1534
|
-
* @param amount the amount specified, either input or output, depending on tradeType
|
|
1535
|
-
* @param tradeType whether the trade is an exact input or exact output swap
|
|
1536
|
-
* @returns The route
|
|
1537
|
-
*/
|
|
1538
|
-
static async fromRoute(route, amount, tradeType) {
|
|
1539
|
-
const amounts = new Array(route.tokenPath.length);
|
|
1540
|
-
let inputAmount;
|
|
1541
|
-
let outputAmount;
|
|
1542
|
-
if (tradeType === sdk.TradeType.EXACT_INPUT) {
|
|
1543
|
-
invariant11__default.default(amount.currency.equals(route.input), "INPUT");
|
|
1544
|
-
amounts[0] = amount.wrapped;
|
|
1545
|
-
for (let i = 0; i < route.tokenPath.length - 1; i++) {
|
|
1546
|
-
const pool = route.pools[i];
|
|
1547
|
-
const [outputAmount2] = await pool.getOutputAmount(amounts[i]);
|
|
1548
|
-
amounts[i + 1] = outputAmount2;
|
|
1549
|
-
}
|
|
1550
|
-
inputAmount = sdk.CurrencyAmount.fromFractionalAmount(route.input, amount.numerator, amount.denominator);
|
|
1551
|
-
outputAmount = sdk.CurrencyAmount.fromFractionalAmount(
|
|
1552
|
-
route.output,
|
|
1553
|
-
amounts[amounts.length - 1].numerator,
|
|
1554
|
-
amounts[amounts.length - 1].denominator
|
|
1555
|
-
);
|
|
1556
|
-
} else {
|
|
1557
|
-
invariant11__default.default(amount.currency.equals(route.output), "OUTPUT");
|
|
1558
|
-
amounts[amounts.length - 1] = amount.wrapped;
|
|
1559
|
-
for (let i = route.tokenPath.length - 1; i > 0; i--) {
|
|
1560
|
-
const pool = route.pools[i - 1];
|
|
1561
|
-
const [inputAmount2] = await pool.getInputAmount(amounts[i]);
|
|
1562
|
-
amounts[i - 1] = inputAmount2;
|
|
1563
|
-
}
|
|
1564
|
-
inputAmount = sdk.CurrencyAmount.fromFractionalAmount(route.input, amounts[0].numerator, amounts[0].denominator);
|
|
1565
|
-
outputAmount = sdk.CurrencyAmount.fromFractionalAmount(route.output, amount.numerator, amount.denominator);
|
|
1566
|
-
}
|
|
1567
|
-
return new Trade({
|
|
1568
|
-
routes: [{ inputAmount, outputAmount, route }],
|
|
1569
|
-
tradeType
|
|
1287
|
+
return new Trade({
|
|
1288
|
+
routes: [{ inputAmount, outputAmount, route }],
|
|
1289
|
+
tradeType
|
|
1570
1290
|
});
|
|
1571
1291
|
}
|
|
1572
1292
|
/**
|
|
@@ -1586,7 +1306,7 @@ var Trade = class {
|
|
|
1586
1306
|
let inputAmount;
|
|
1587
1307
|
let outputAmount;
|
|
1588
1308
|
if (tradeType === sdk.TradeType.EXACT_INPUT) {
|
|
1589
|
-
|
|
1309
|
+
invariant9__default.default(amount.currency.equals(route.input), "INPUT");
|
|
1590
1310
|
inputAmount = sdk.CurrencyAmount.fromFractionalAmount(route.input, amount.numerator, amount.denominator);
|
|
1591
1311
|
amounts[0] = sdk.CurrencyAmount.fromFractionalAmount(route.input.wrapped, amount.numerator, amount.denominator);
|
|
1592
1312
|
for (let i = 0; i < route.tokenPath.length - 1; i++) {
|
|
@@ -1600,7 +1320,7 @@ var Trade = class {
|
|
|
1600
1320
|
amounts[amounts.length - 1].denominator
|
|
1601
1321
|
);
|
|
1602
1322
|
} else {
|
|
1603
|
-
|
|
1323
|
+
invariant9__default.default(amount.currency.equals(route.output), "OUTPUT");
|
|
1604
1324
|
outputAmount = sdk.CurrencyAmount.fromFractionalAmount(route.output, amount.numerator, amount.denominator);
|
|
1605
1325
|
amounts[amounts.length - 1] = sdk.CurrencyAmount.fromFractionalAmount(
|
|
1606
1326
|
route.output.wrapped,
|
|
@@ -1665,11 +1385,11 @@ var Trade = class {
|
|
|
1665
1385
|
}) {
|
|
1666
1386
|
const inputCurrency = routes[0].inputAmount.currency;
|
|
1667
1387
|
const outputCurrency = routes[0].outputAmount.currency;
|
|
1668
|
-
|
|
1388
|
+
invariant9__default.default(
|
|
1669
1389
|
routes.every(({ route }) => inputCurrency.wrapped.equals(route.input.wrapped)),
|
|
1670
1390
|
"INPUT_CURRENCY_MATCH"
|
|
1671
1391
|
);
|
|
1672
|
-
|
|
1392
|
+
invariant9__default.default(
|
|
1673
1393
|
routes.every(({ route }) => outputCurrency.wrapped.equals(route.output.wrapped)),
|
|
1674
1394
|
"OUTPUT_CURRENCY_MATCH"
|
|
1675
1395
|
);
|
|
@@ -1680,7 +1400,7 @@ var Trade = class {
|
|
|
1680
1400
|
poolAddressSet.add(Pool.getAddress(pool.token0, pool.token1, pool.fee));
|
|
1681
1401
|
}
|
|
1682
1402
|
}
|
|
1683
|
-
|
|
1403
|
+
invariant9__default.default(numPools == poolAddressSet.size, "POOLS_DUPLICATED");
|
|
1684
1404
|
this.swaps = routes;
|
|
1685
1405
|
this.tradeType = tradeType;
|
|
1686
1406
|
}
|
|
@@ -1690,169 +1410,459 @@ var Trade = class {
|
|
|
1690
1410
|
* @returns The amount out
|
|
1691
1411
|
*/
|
|
1692
1412
|
minimumAmountOut(slippageTolerance, amountOut = this.outputAmount) {
|
|
1693
|
-
|
|
1413
|
+
invariant9__default.default(!slippageTolerance.lessThan(ZERO), "SLIPPAGE_TOLERANCE");
|
|
1694
1414
|
if (this.tradeType === sdk.TradeType.EXACT_OUTPUT) {
|
|
1695
1415
|
return amountOut;
|
|
1696
1416
|
}
|
|
1697
1417
|
const slippageAdjustedAmountOut = new sdk.Fraction(ONE).add(slippageTolerance).invert().multiply(amountOut.quotient).quotient;
|
|
1698
1418
|
return sdk.CurrencyAmount.fromRawAmount(amountOut.currency, slippageAdjustedAmountOut);
|
|
1699
1419
|
}
|
|
1700
|
-
/**
|
|
1701
|
-
* Get the maximum amount in that can be spent via this trade for the given slippage tolerance
|
|
1702
|
-
* @param slippageTolerance The tolerance of unfavorable slippage from the execution price of this trade
|
|
1703
|
-
* @returns The amount in
|
|
1704
|
-
*/
|
|
1705
|
-
maximumAmountIn(slippageTolerance, amountIn = this.inputAmount) {
|
|
1706
|
-
|
|
1707
|
-
if (this.tradeType === sdk.TradeType.EXACT_INPUT) {
|
|
1708
|
-
return amountIn;
|
|
1420
|
+
/**
|
|
1421
|
+
* Get the maximum amount in that can be spent via this trade for the given slippage tolerance
|
|
1422
|
+
* @param slippageTolerance The tolerance of unfavorable slippage from the execution price of this trade
|
|
1423
|
+
* @returns The amount in
|
|
1424
|
+
*/
|
|
1425
|
+
maximumAmountIn(slippageTolerance, amountIn = this.inputAmount) {
|
|
1426
|
+
invariant9__default.default(!slippageTolerance.lessThan(ZERO), "SLIPPAGE_TOLERANCE");
|
|
1427
|
+
if (this.tradeType === sdk.TradeType.EXACT_INPUT) {
|
|
1428
|
+
return amountIn;
|
|
1429
|
+
}
|
|
1430
|
+
const slippageAdjustedAmountIn = new sdk.Fraction(ONE).add(slippageTolerance).multiply(amountIn.quotient).quotient;
|
|
1431
|
+
return sdk.CurrencyAmount.fromRawAmount(amountIn.currency, slippageAdjustedAmountIn);
|
|
1432
|
+
}
|
|
1433
|
+
/**
|
|
1434
|
+
* Return the execution price after accounting for slippage tolerance
|
|
1435
|
+
* @param slippageTolerance the allowed tolerated slippage
|
|
1436
|
+
* @returns The execution price
|
|
1437
|
+
*/
|
|
1438
|
+
worstExecutionPrice(slippageTolerance) {
|
|
1439
|
+
return new sdk.Price(
|
|
1440
|
+
this.inputAmount.currency,
|
|
1441
|
+
this.outputAmount.currency,
|
|
1442
|
+
this.maximumAmountIn(slippageTolerance).quotient,
|
|
1443
|
+
this.minimumAmountOut(slippageTolerance).quotient
|
|
1444
|
+
);
|
|
1445
|
+
}
|
|
1446
|
+
/**
|
|
1447
|
+
* Given a list of pools, and a fixed amount in, returns the top `maxNumResults` trades that go from an input token
|
|
1448
|
+
* amount to an output token, making at most `maxHops` hops.
|
|
1449
|
+
* Note this does not consider aggregation, as routes are linear. It's possible a better route exists by splitting
|
|
1450
|
+
* the amount in among multiple routes.
|
|
1451
|
+
* @param pools the pools to consider in finding the best trade
|
|
1452
|
+
* @param nextAmountIn exact amount of input currency to spend
|
|
1453
|
+
* @param currencyOut the desired currency out
|
|
1454
|
+
* @param maxNumResults maximum number of results to return
|
|
1455
|
+
* @param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pool
|
|
1456
|
+
* @param currentPools used in recursion; the current list of pools
|
|
1457
|
+
* @param currencyAmountIn used in recursion; the original value of the currencyAmountIn parameter
|
|
1458
|
+
* @param bestTrades used in recursion; the current list of best trades
|
|
1459
|
+
* @returns The exact in trade
|
|
1460
|
+
*/
|
|
1461
|
+
static async bestTradeExactIn(pools, currencyAmountIn, currencyOut, { maxNumResults = 3, maxHops = 3 } = {}, currentPools = [], nextAmountIn = currencyAmountIn, bestTrades = []) {
|
|
1462
|
+
invariant9__default.default(pools.length > 0, "POOLS");
|
|
1463
|
+
invariant9__default.default(maxHops > 0, "MAX_HOPS");
|
|
1464
|
+
invariant9__default.default(currencyAmountIn === nextAmountIn || currentPools.length > 0, "INVALID_RECURSION");
|
|
1465
|
+
const amountIn = nextAmountIn.wrapped;
|
|
1466
|
+
const tokenOut = currencyOut.wrapped;
|
|
1467
|
+
for (let i = 0; i < pools.length; i++) {
|
|
1468
|
+
const pool = pools[i];
|
|
1469
|
+
if (!pool.token0.equals(amountIn.currency) && !pool.token1.equals(amountIn.currency))
|
|
1470
|
+
continue;
|
|
1471
|
+
let amountOut;
|
|
1472
|
+
try {
|
|
1473
|
+
const [result] = await pool.getOutputAmount(amountIn);
|
|
1474
|
+
amountOut = result;
|
|
1475
|
+
} catch (error) {
|
|
1476
|
+
if (error.isInsufficientInputAmountError) {
|
|
1477
|
+
continue;
|
|
1478
|
+
}
|
|
1479
|
+
throw error;
|
|
1480
|
+
}
|
|
1481
|
+
if (amountOut.currency.isToken && amountOut.currency.equals(tokenOut)) {
|
|
1482
|
+
sdk.sortedInsert(
|
|
1483
|
+
bestTrades,
|
|
1484
|
+
await Trade.fromRoute(
|
|
1485
|
+
new Route([...currentPools, pool], currencyAmountIn.currency, currencyOut),
|
|
1486
|
+
currencyAmountIn,
|
|
1487
|
+
sdk.TradeType.EXACT_INPUT
|
|
1488
|
+
),
|
|
1489
|
+
maxNumResults,
|
|
1490
|
+
tradeComparator
|
|
1491
|
+
);
|
|
1492
|
+
} else if (maxHops > 1 && pools.length > 1) {
|
|
1493
|
+
const poolsExcludingThisPool = pools.slice(0, i).concat(pools.slice(i + 1, pools.length));
|
|
1494
|
+
await Trade.bestTradeExactIn(
|
|
1495
|
+
poolsExcludingThisPool,
|
|
1496
|
+
currencyAmountIn,
|
|
1497
|
+
currencyOut,
|
|
1498
|
+
{
|
|
1499
|
+
maxNumResults,
|
|
1500
|
+
maxHops: maxHops - 1
|
|
1501
|
+
},
|
|
1502
|
+
[...currentPools, pool],
|
|
1503
|
+
amountOut,
|
|
1504
|
+
bestTrades
|
|
1505
|
+
);
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
return bestTrades;
|
|
1509
|
+
}
|
|
1510
|
+
/**
|
|
1511
|
+
* similar to the above method but instead targets a fixed output amount
|
|
1512
|
+
* given a list of pools, and a fixed amount out, returns the top `maxNumResults` trades that go from an input token
|
|
1513
|
+
* to an output token amount, making at most `maxHops` hops
|
|
1514
|
+
* note this does not consider aggregation, as routes are linear. it's possible a better route exists by splitting
|
|
1515
|
+
* the amount in among multiple routes.
|
|
1516
|
+
* @param pools the pools to consider in finding the best trade
|
|
1517
|
+
* @param currencyIn the currency to spend
|
|
1518
|
+
* @param currencyAmountOut the desired currency amount out
|
|
1519
|
+
* @param nextAmountOut the exact amount of currency out
|
|
1520
|
+
* @param maxNumResults maximum number of results to return
|
|
1521
|
+
* @param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pool
|
|
1522
|
+
* @param currentPools used in recursion; the current list of pools
|
|
1523
|
+
* @param bestTrades used in recursion; the current list of best trades
|
|
1524
|
+
* @returns The exact out trade
|
|
1525
|
+
*/
|
|
1526
|
+
static async bestTradeExactOut(pools, currencyIn, currencyAmountOut, { maxNumResults = 3, maxHops = 3 } = {}, currentPools = [], nextAmountOut = currencyAmountOut, bestTrades = []) {
|
|
1527
|
+
invariant9__default.default(pools.length > 0, "POOLS");
|
|
1528
|
+
invariant9__default.default(maxHops > 0, "MAX_HOPS");
|
|
1529
|
+
invariant9__default.default(currencyAmountOut === nextAmountOut || currentPools.length > 0, "INVALID_RECURSION");
|
|
1530
|
+
const amountOut = nextAmountOut.wrapped;
|
|
1531
|
+
const tokenIn = currencyIn.wrapped;
|
|
1532
|
+
for (let i = 0; i < pools.length; i++) {
|
|
1533
|
+
const pool = pools[i];
|
|
1534
|
+
if (!pool.token0.equals(amountOut.currency) && !pool.token1.equals(amountOut.currency))
|
|
1535
|
+
continue;
|
|
1536
|
+
let amountIn;
|
|
1537
|
+
try {
|
|
1538
|
+
const [result] = await pool.getInputAmount(amountOut);
|
|
1539
|
+
amountIn = result;
|
|
1540
|
+
} catch (error) {
|
|
1541
|
+
if (error.isInsufficientReservesError) {
|
|
1542
|
+
continue;
|
|
1543
|
+
}
|
|
1544
|
+
throw error;
|
|
1545
|
+
}
|
|
1546
|
+
if (amountIn.currency.equals(tokenIn)) {
|
|
1547
|
+
sdk.sortedInsert(
|
|
1548
|
+
bestTrades,
|
|
1549
|
+
await Trade.fromRoute(
|
|
1550
|
+
new Route([pool, ...currentPools], currencyIn, currencyAmountOut.currency),
|
|
1551
|
+
currencyAmountOut,
|
|
1552
|
+
sdk.TradeType.EXACT_OUTPUT
|
|
1553
|
+
),
|
|
1554
|
+
maxNumResults,
|
|
1555
|
+
tradeComparator
|
|
1556
|
+
);
|
|
1557
|
+
} else if (maxHops > 1 && pools.length > 1) {
|
|
1558
|
+
const poolsExcludingThisPool = pools.slice(0, i).concat(pools.slice(i + 1, pools.length));
|
|
1559
|
+
await Trade.bestTradeExactOut(
|
|
1560
|
+
poolsExcludingThisPool,
|
|
1561
|
+
currencyIn,
|
|
1562
|
+
currencyAmountOut,
|
|
1563
|
+
{
|
|
1564
|
+
maxNumResults,
|
|
1565
|
+
maxHops: maxHops - 1
|
|
1566
|
+
},
|
|
1567
|
+
[pool, ...currentPools],
|
|
1568
|
+
amountIn,
|
|
1569
|
+
bestTrades
|
|
1570
|
+
);
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
return bestTrades;
|
|
1574
|
+
}
|
|
1575
|
+
};
|
|
1576
|
+
|
|
1577
|
+
// src/utils/calldata.ts
|
|
1578
|
+
function toHex(bigintIsh) {
|
|
1579
|
+
const bigInt = BigInt(bigintIsh);
|
|
1580
|
+
let hex = bigInt.toString(16);
|
|
1581
|
+
if (hex.length % 2 !== 0) {
|
|
1582
|
+
hex = `0${hex}`;
|
|
1583
|
+
}
|
|
1584
|
+
return `0x${hex}`;
|
|
1585
|
+
}
|
|
1586
|
+
function encodeRouteToPath(route, exactOutput) {
|
|
1587
|
+
const firstInputToken = route.input.wrapped;
|
|
1588
|
+
const { path, types } = route.pools.reduce(
|
|
1589
|
+
({ inputToken, path: path2, types: types2 }, pool, index) => {
|
|
1590
|
+
const outputToken = pool.token0.equals(inputToken) ? pool.token1 : pool.token0;
|
|
1591
|
+
if (index === 0) {
|
|
1592
|
+
return {
|
|
1593
|
+
inputToken: outputToken,
|
|
1594
|
+
types: ["address", "uint24", "address"],
|
|
1595
|
+
path: [inputToken.address, pool.fee, outputToken.address]
|
|
1596
|
+
};
|
|
1597
|
+
}
|
|
1598
|
+
return {
|
|
1599
|
+
inputToken: outputToken,
|
|
1600
|
+
types: [...types2, "uint24", "address"],
|
|
1601
|
+
path: [...path2, pool.fee, outputToken.address]
|
|
1602
|
+
};
|
|
1603
|
+
},
|
|
1604
|
+
{ inputToken: firstInputToken, path: [], types: [] }
|
|
1605
|
+
);
|
|
1606
|
+
return exactOutput ? viem.encodePacked(types.reverse(), path.reverse()) : viem.encodePacked(types, path);
|
|
1607
|
+
}
|
|
1608
|
+
function nearestUsableTick(tick, tickSpacing) {
|
|
1609
|
+
invariant9__default.default(Number.isInteger(tick) && Number.isInteger(tickSpacing), "INTEGERS");
|
|
1610
|
+
invariant9__default.default(tickSpacing > 0, "TICK_SPACING");
|
|
1611
|
+
invariant9__default.default(tick >= TickMath.MIN_TICK && tick <= TickMath.MAX_TICK, "TICK_BOUND");
|
|
1612
|
+
const rounded = Math.round(tick / tickSpacing) * tickSpacing;
|
|
1613
|
+
if (rounded < TickMath.MIN_TICK)
|
|
1614
|
+
return rounded + tickSpacing;
|
|
1615
|
+
if (rounded > TickMath.MAX_TICK)
|
|
1616
|
+
return rounded - tickSpacing;
|
|
1617
|
+
return rounded;
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
// src/utils/position.ts
|
|
1621
|
+
var PositionLibrary = class {
|
|
1622
|
+
/**
|
|
1623
|
+
* Cannot be constructed.
|
|
1624
|
+
*/
|
|
1625
|
+
constructor() {
|
|
1626
|
+
}
|
|
1627
|
+
// replicates the portions of Position#update required to compute unaccounted fees
|
|
1628
|
+
static getTokensOwed(feeGrowthInside0LastX128, feeGrowthInside1LastX128, liquidity, feeGrowthInside0X128, feeGrowthInside1X128) {
|
|
1629
|
+
const tokensOwed0 = subIn256(feeGrowthInside0X128, feeGrowthInside0LastX128) * liquidity / Q128;
|
|
1630
|
+
const tokensOwed1 = subIn256(feeGrowthInside1X128, feeGrowthInside1LastX128) * liquidity / Q128;
|
|
1631
|
+
return [tokensOwed0, tokensOwed1];
|
|
1632
|
+
}
|
|
1633
|
+
};
|
|
1634
|
+
|
|
1635
|
+
// src/utils/tickLibrary.ts
|
|
1636
|
+
var Q256 = 2n ** 256n;
|
|
1637
|
+
function subIn256(x, y) {
|
|
1638
|
+
const difference = x - y;
|
|
1639
|
+
if (difference < ZERO) {
|
|
1640
|
+
return Q256 + difference;
|
|
1641
|
+
}
|
|
1642
|
+
return difference;
|
|
1643
|
+
}
|
|
1644
|
+
var TickLibrary = class {
|
|
1645
|
+
/**
|
|
1646
|
+
* Cannot be constructed.
|
|
1647
|
+
*/
|
|
1648
|
+
constructor() {
|
|
1649
|
+
}
|
|
1650
|
+
static getFeeGrowthInside(feeGrowthOutsideLower, feeGrowthOutsideUpper, tickLower, tickUpper, tickCurrent, feeGrowthGlobal0X128, feeGrowthGlobal1X128) {
|
|
1651
|
+
let feeGrowthBelow0X128;
|
|
1652
|
+
let feeGrowthBelow1X128;
|
|
1653
|
+
if (tickCurrent >= tickLower) {
|
|
1654
|
+
feeGrowthBelow0X128 = feeGrowthOutsideLower.feeGrowthOutside0X128;
|
|
1655
|
+
feeGrowthBelow1X128 = feeGrowthOutsideLower.feeGrowthOutside1X128;
|
|
1656
|
+
} else {
|
|
1657
|
+
feeGrowthBelow0X128 = subIn256(feeGrowthGlobal0X128, feeGrowthOutsideLower.feeGrowthOutside0X128);
|
|
1658
|
+
feeGrowthBelow1X128 = subIn256(feeGrowthGlobal1X128, feeGrowthOutsideLower.feeGrowthOutside1X128);
|
|
1659
|
+
}
|
|
1660
|
+
let feeGrowthAbove0X128;
|
|
1661
|
+
let feeGrowthAbove1X128;
|
|
1662
|
+
if (tickCurrent < tickUpper) {
|
|
1663
|
+
feeGrowthAbove0X128 = feeGrowthOutsideUpper.feeGrowthOutside0X128;
|
|
1664
|
+
feeGrowthAbove1X128 = feeGrowthOutsideUpper.feeGrowthOutside1X128;
|
|
1665
|
+
} else {
|
|
1666
|
+
feeGrowthAbove0X128 = subIn256(feeGrowthGlobal0X128, feeGrowthOutsideUpper.feeGrowthOutside0X128);
|
|
1667
|
+
feeGrowthAbove1X128 = subIn256(feeGrowthGlobal1X128, feeGrowthOutsideUpper.feeGrowthOutside1X128);
|
|
1668
|
+
}
|
|
1669
|
+
return [
|
|
1670
|
+
subIn256(subIn256(feeGrowthGlobal0X128, feeGrowthBelow0X128), feeGrowthAbove0X128),
|
|
1671
|
+
subIn256(subIn256(feeGrowthGlobal1X128, feeGrowthBelow1X128), feeGrowthAbove1X128)
|
|
1672
|
+
];
|
|
1673
|
+
}
|
|
1674
|
+
};
|
|
1675
|
+
function parseNumberToFraction(num, precision = 6) {
|
|
1676
|
+
if (Number.isNaN(num) || !Number.isFinite(num)) {
|
|
1677
|
+
return void 0;
|
|
1678
|
+
}
|
|
1679
|
+
const scalar = 10 ** precision;
|
|
1680
|
+
return new swapSdkCore.Fraction(BigInt(Math.floor(num * scalar)), BigInt(scalar));
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
// src/utils/feeCalculator.ts
|
|
1684
|
+
var FeeCalculator = {
|
|
1685
|
+
getEstimatedLPFee,
|
|
1686
|
+
getEstimatedLPFeeByAmounts,
|
|
1687
|
+
getLiquidityFromTick,
|
|
1688
|
+
getLiquidityFromSqrtRatioX96,
|
|
1689
|
+
getAverageLiquidity,
|
|
1690
|
+
getLiquidityBySingleAmount,
|
|
1691
|
+
getDependentAmount,
|
|
1692
|
+
getLiquidityByAmountsAndPrice,
|
|
1693
|
+
getAmountsByLiquidityAndPrice,
|
|
1694
|
+
getAmountsAtNewPrice
|
|
1695
|
+
};
|
|
1696
|
+
function getEstimatedLPFeeWithProtocolFee({ amount, currency, ...rest }) {
|
|
1697
|
+
return getEstimatedLPFeeByAmountsWithProtocolFee({
|
|
1698
|
+
...rest,
|
|
1699
|
+
amountA: amount,
|
|
1700
|
+
amountB: swapSdkCore.CurrencyAmount.fromRawAmount(currency, swapSdkCore.MaxUint256)
|
|
1701
|
+
});
|
|
1702
|
+
}
|
|
1703
|
+
function getEstimatedLPFee({ amount, currency, ...rest }) {
|
|
1704
|
+
return getEstimatedLPFeeByAmounts({
|
|
1705
|
+
...rest,
|
|
1706
|
+
amountA: amount,
|
|
1707
|
+
amountB: swapSdkCore.CurrencyAmount.fromRawAmount(currency, swapSdkCore.MaxUint256)
|
|
1708
|
+
});
|
|
1709
|
+
}
|
|
1710
|
+
function getEstimatedLPFeeByAmountsWithProtocolFee(options) {
|
|
1711
|
+
try {
|
|
1712
|
+
return tryGetEstimatedLPFeeByAmounts(options);
|
|
1713
|
+
} catch (e) {
|
|
1714
|
+
console.error(e);
|
|
1715
|
+
return new swapSdkCore.Fraction(swapSdkCore.ZERO);
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
function getEstimatedLPFeeByAmounts({ protocolFee = ZERO_PERCENT, ...rest }) {
|
|
1719
|
+
try {
|
|
1720
|
+
const fee = tryGetEstimatedLPFeeByAmounts(rest);
|
|
1721
|
+
return ONE_HUNDRED_PERCENT.subtract(protocolFee).multiply(fee).asFraction;
|
|
1722
|
+
} catch (e) {
|
|
1723
|
+
console.error(e);
|
|
1724
|
+
return new swapSdkCore.Fraction(swapSdkCore.ZERO);
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
function tryGetEstimatedLPFeeByAmounts({
|
|
1728
|
+
amountA,
|
|
1729
|
+
amountB,
|
|
1730
|
+
volume24H,
|
|
1731
|
+
sqrtRatioX96,
|
|
1732
|
+
tickLower,
|
|
1733
|
+
tickUpper,
|
|
1734
|
+
mostActiveLiquidity,
|
|
1735
|
+
fee,
|
|
1736
|
+
insidePercentage = ONE_HUNDRED_PERCENT
|
|
1737
|
+
}) {
|
|
1738
|
+
invariant9__default.default(!Number.isNaN(fee) && fee >= 0, "INVALID_FEE");
|
|
1739
|
+
const tickCurrent = TickMath.getTickAtSqrtRatio(sqrtRatioX96);
|
|
1740
|
+
if (tickCurrent < tickLower || tickCurrent > tickUpper) {
|
|
1741
|
+
return new swapSdkCore.Fraction(swapSdkCore.ZERO);
|
|
1742
|
+
}
|
|
1743
|
+
const liquidity = FeeCalculator.getLiquidityByAmountsAndPrice({
|
|
1744
|
+
amountA,
|
|
1745
|
+
amountB,
|
|
1746
|
+
tickUpper,
|
|
1747
|
+
tickLower,
|
|
1748
|
+
sqrtRatioX96
|
|
1749
|
+
});
|
|
1750
|
+
const volumeInFraction = parseNumberToFraction(volume24H) || new swapSdkCore.Fraction(swapSdkCore.ZERO);
|
|
1751
|
+
return insidePercentage.multiply(volumeInFraction.multiply(BigInt(fee)).multiply(liquidity)).divide(MAX_FEE * (liquidity + mostActiveLiquidity)).asFraction;
|
|
1752
|
+
}
|
|
1753
|
+
function getDependentAmount(options) {
|
|
1754
|
+
const { currency, amount, sqrtRatioX96, tickLower, tickUpper } = options;
|
|
1755
|
+
const currentTick = TickMath.getTickAtSqrtRatio(sqrtRatioX96);
|
|
1756
|
+
const liquidity = FeeCalculator.getLiquidityBySingleAmount(options);
|
|
1757
|
+
const isToken0 = currency.wrapped.sortsBefore(amount.currency.wrapped);
|
|
1758
|
+
const getTokenAmount = isToken0 ? PositionMath.getToken0Amount : PositionMath.getToken1Amount;
|
|
1759
|
+
return swapSdkCore.CurrencyAmount.fromRawAmount(
|
|
1760
|
+
currency,
|
|
1761
|
+
getTokenAmount(currentTick, tickLower, tickUpper, sqrtRatioX96, liquidity)
|
|
1762
|
+
);
|
|
1763
|
+
}
|
|
1764
|
+
function getLiquidityBySingleAmount({ amount, currency, ...rest }) {
|
|
1765
|
+
return getLiquidityByAmountsAndPrice({
|
|
1766
|
+
amountA: amount,
|
|
1767
|
+
amountB: swapSdkCore.CurrencyAmount.fromRawAmount(currency, swapSdkCore.MaxUint256),
|
|
1768
|
+
...rest
|
|
1769
|
+
});
|
|
1770
|
+
}
|
|
1771
|
+
function getLiquidityByAmountsAndPrice({
|
|
1772
|
+
amountA,
|
|
1773
|
+
amountB,
|
|
1774
|
+
tickUpper,
|
|
1775
|
+
tickLower,
|
|
1776
|
+
sqrtRatioX96
|
|
1777
|
+
}) {
|
|
1778
|
+
const isToken0 = amountA.currency.wrapped.address !== amountB.currency.wrapped.address ? amountA.currency.wrapped.sortsBefore(amountB.currency.wrapped) : true;
|
|
1779
|
+
const [inputAmount0, inputAmount1] = isToken0 ? [amountA.quotient, amountB.quotient] : [amountB.quotient, amountA.quotient];
|
|
1780
|
+
const sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickLower);
|
|
1781
|
+
const sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickUpper);
|
|
1782
|
+
return maxLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, inputAmount0, inputAmount1, true);
|
|
1783
|
+
}
|
|
1784
|
+
function getAmountsByLiquidityAndPrice(options) {
|
|
1785
|
+
const { currencyA, currencyB, liquidity, sqrtRatioX96, tickLower, tickUpper } = options;
|
|
1786
|
+
const currentTick = TickMath.getTickAtSqrtRatio(sqrtRatioX96);
|
|
1787
|
+
const isToken0 = currencyA.wrapped.sortsBefore(currencyB.wrapped);
|
|
1788
|
+
const adjustedAmount0 = PositionMath.getToken0Amount(currentTick, tickLower, tickUpper, sqrtRatioX96, liquidity);
|
|
1789
|
+
const adjustedAmount1 = PositionMath.getToken1Amount(currentTick, tickLower, tickUpper, sqrtRatioX96, liquidity);
|
|
1790
|
+
return [
|
|
1791
|
+
swapSdkCore.CurrencyAmount.fromRawAmount(currencyA, isToken0 ? adjustedAmount0 : adjustedAmount1),
|
|
1792
|
+
swapSdkCore.CurrencyAmount.fromRawAmount(currencyB, isToken0 ? adjustedAmount1 : adjustedAmount0)
|
|
1793
|
+
];
|
|
1794
|
+
}
|
|
1795
|
+
function getAmountsAtNewPrice({ newSqrtRatioX96, ...rest }) {
|
|
1796
|
+
const { tickLower, tickUpper, amountA, amountB } = rest;
|
|
1797
|
+
const liquidity = FeeCalculator.getLiquidityByAmountsAndPrice(rest);
|
|
1798
|
+
return FeeCalculator.getAmountsByLiquidityAndPrice({
|
|
1799
|
+
liquidity,
|
|
1800
|
+
currencyA: amountA.currency,
|
|
1801
|
+
currencyB: amountB.currency,
|
|
1802
|
+
tickLower,
|
|
1803
|
+
tickUpper,
|
|
1804
|
+
sqrtRatioX96: newSqrtRatioX96
|
|
1805
|
+
});
|
|
1806
|
+
}
|
|
1807
|
+
function getAverageLiquidity(ticks, tickSpacing, tickLower, tickUpper) {
|
|
1808
|
+
invariant9__default.default(tickLower <= tickUpper, "INVALID_TICK_RANGE");
|
|
1809
|
+
TickList.validateList(ticks, tickSpacing);
|
|
1810
|
+
if (tickLower === tickUpper) {
|
|
1811
|
+
return FeeCalculator.getLiquidityFromTick(ticks, tickLower);
|
|
1812
|
+
}
|
|
1813
|
+
const lowerOutOfBound = tickLower < ticks[0].index;
|
|
1814
|
+
let lastTick = lowerOutOfBound ? new Tick({ index: TickMath.MIN_TICK, liquidityNet: swapSdkCore.ZERO, liquidityGross: swapSdkCore.ZERO }) : TickList.nextInitializedTick(ticks, tickLower, true);
|
|
1815
|
+
let currentTick = TickList.nextInitializedTick(ticks, tickLower, false);
|
|
1816
|
+
let currentL = lowerOutOfBound ? swapSdkCore.ZERO : FeeCalculator.getLiquidityFromTick(ticks, currentTick.index);
|
|
1817
|
+
let weightedL = swapSdkCore.ZERO;
|
|
1818
|
+
const getWeightedLFromLastTickTo = (toTick) => currentL * BigInt(toTick - Math.max(lastTick.index, tickLower));
|
|
1819
|
+
while (currentTick.index < tickUpper) {
|
|
1820
|
+
weightedL += getWeightedLFromLastTickTo(currentTick.index);
|
|
1821
|
+
currentL += currentTick.liquidityNet;
|
|
1822
|
+
lastTick = currentTick;
|
|
1823
|
+
if (currentTick.index === ticks[ticks.length - 1].index) {
|
|
1824
|
+
break;
|
|
1709
1825
|
}
|
|
1710
|
-
|
|
1711
|
-
return sdk.CurrencyAmount.fromRawAmount(amountIn.currency, slippageAdjustedAmountIn);
|
|
1826
|
+
currentTick = TickList.nextInitializedTick(ticks, currentTick.index, false);
|
|
1712
1827
|
}
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1828
|
+
weightedL += getWeightedLFromLastTickTo(tickUpper);
|
|
1829
|
+
return weightedL / BigInt(tickUpper - tickLower);
|
|
1830
|
+
}
|
|
1831
|
+
function getLiquidityFromSqrtRatioX96(ticks, sqrtRatioX96) {
|
|
1832
|
+
const tick = TickMath.getTickAtSqrtRatio(sqrtRatioX96);
|
|
1833
|
+
return FeeCalculator.getLiquidityFromTick(ticks, tick);
|
|
1834
|
+
}
|
|
1835
|
+
function getLiquidityFromTick(ticks, tick) {
|
|
1836
|
+
let liquidity = swapSdkCore.ZERO;
|
|
1837
|
+
if (!ticks?.length)
|
|
1838
|
+
return liquidity;
|
|
1839
|
+
if (tick < ticks[0].index || tick > ticks[ticks.length - 1].index) {
|
|
1840
|
+
return liquidity;
|
|
1725
1841
|
}
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
* @param nextAmountIn exact amount of input currency to spend
|
|
1733
|
-
* @param currencyOut the desired currency out
|
|
1734
|
-
* @param maxNumResults maximum number of results to return
|
|
1735
|
-
* @param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pool
|
|
1736
|
-
* @param currentPools used in recursion; the current list of pools
|
|
1737
|
-
* @param currencyAmountIn used in recursion; the original value of the currencyAmountIn parameter
|
|
1738
|
-
* @param bestTrades used in recursion; the current list of best trades
|
|
1739
|
-
* @returns The exact in trade
|
|
1740
|
-
*/
|
|
1741
|
-
static async bestTradeExactIn(pools, currencyAmountIn, currencyOut, { maxNumResults = 3, maxHops = 3 } = {}, currentPools = [], nextAmountIn = currencyAmountIn, bestTrades = []) {
|
|
1742
|
-
invariant11__default.default(pools.length > 0, "POOLS");
|
|
1743
|
-
invariant11__default.default(maxHops > 0, "MAX_HOPS");
|
|
1744
|
-
invariant11__default.default(currencyAmountIn === nextAmountIn || currentPools.length > 0, "INVALID_RECURSION");
|
|
1745
|
-
const amountIn = nextAmountIn.wrapped;
|
|
1746
|
-
const tokenOut = currencyOut.wrapped;
|
|
1747
|
-
for (let i = 0; i < pools.length; i++) {
|
|
1748
|
-
const pool = pools[i];
|
|
1749
|
-
if (!pool.token0.equals(amountIn.currency) && !pool.token1.equals(amountIn.currency))
|
|
1750
|
-
continue;
|
|
1751
|
-
let amountOut;
|
|
1752
|
-
try {
|
|
1753
|
-
const [result] = await pool.getOutputAmount(amountIn);
|
|
1754
|
-
amountOut = result;
|
|
1755
|
-
} catch (error) {
|
|
1756
|
-
if (error.isInsufficientInputAmountError) {
|
|
1757
|
-
continue;
|
|
1758
|
-
}
|
|
1759
|
-
throw error;
|
|
1760
|
-
}
|
|
1761
|
-
if (amountOut.currency.isToken && amountOut.currency.equals(tokenOut)) {
|
|
1762
|
-
sdk.sortedInsert(
|
|
1763
|
-
bestTrades,
|
|
1764
|
-
await Trade.fromRoute(
|
|
1765
|
-
new Route([...currentPools, pool], currencyAmountIn.currency, currencyOut),
|
|
1766
|
-
currencyAmountIn,
|
|
1767
|
-
sdk.TradeType.EXACT_INPUT
|
|
1768
|
-
),
|
|
1769
|
-
maxNumResults,
|
|
1770
|
-
tradeComparator
|
|
1771
|
-
);
|
|
1772
|
-
} else if (maxHops > 1 && pools.length > 1) {
|
|
1773
|
-
const poolsExcludingThisPool = pools.slice(0, i).concat(pools.slice(i + 1, pools.length));
|
|
1774
|
-
await Trade.bestTradeExactIn(
|
|
1775
|
-
poolsExcludingThisPool,
|
|
1776
|
-
currencyAmountIn,
|
|
1777
|
-
currencyOut,
|
|
1778
|
-
{
|
|
1779
|
-
maxNumResults,
|
|
1780
|
-
maxHops: maxHops - 1
|
|
1781
|
-
},
|
|
1782
|
-
[...currentPools, pool],
|
|
1783
|
-
amountOut,
|
|
1784
|
-
bestTrades
|
|
1785
|
-
);
|
|
1786
|
-
}
|
|
1842
|
+
for (let i = 0; i < ticks.length - 1; ++i) {
|
|
1843
|
+
liquidity += ticks[i].liquidityNet;
|
|
1844
|
+
const lowerTick = ticks[i].index;
|
|
1845
|
+
const upperTick = ticks[i + 1]?.index;
|
|
1846
|
+
if (lowerTick <= tick && tick <= upperTick) {
|
|
1847
|
+
break;
|
|
1787
1848
|
}
|
|
1788
|
-
return bestTrades;
|
|
1789
1849
|
}
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
* @param currencyIn the currency to spend
|
|
1798
|
-
* @param currencyAmountOut the desired currency amount out
|
|
1799
|
-
* @param nextAmountOut the exact amount of currency out
|
|
1800
|
-
* @param maxNumResults maximum number of results to return
|
|
1801
|
-
* @param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pool
|
|
1802
|
-
* @param currentPools used in recursion; the current list of pools
|
|
1803
|
-
* @param bestTrades used in recursion; the current list of best trades
|
|
1804
|
-
* @returns The exact out trade
|
|
1805
|
-
*/
|
|
1806
|
-
static async bestTradeExactOut(pools, currencyIn, currencyAmountOut, { maxNumResults = 3, maxHops = 3 } = {}, currentPools = [], nextAmountOut = currencyAmountOut, bestTrades = []) {
|
|
1807
|
-
invariant11__default.default(pools.length > 0, "POOLS");
|
|
1808
|
-
invariant11__default.default(maxHops > 0, "MAX_HOPS");
|
|
1809
|
-
invariant11__default.default(currencyAmountOut === nextAmountOut || currentPools.length > 0, "INVALID_RECURSION");
|
|
1810
|
-
const amountOut = nextAmountOut.wrapped;
|
|
1811
|
-
const tokenIn = currencyIn.wrapped;
|
|
1812
|
-
for (let i = 0; i < pools.length; i++) {
|
|
1813
|
-
const pool = pools[i];
|
|
1814
|
-
if (!pool.token0.equals(amountOut.currency) && !pool.token1.equals(amountOut.currency))
|
|
1815
|
-
continue;
|
|
1816
|
-
let amountIn;
|
|
1817
|
-
try {
|
|
1818
|
-
const [result] = await pool.getInputAmount(amountOut);
|
|
1819
|
-
amountIn = result;
|
|
1820
|
-
} catch (error) {
|
|
1821
|
-
if (error.isInsufficientReservesError) {
|
|
1822
|
-
continue;
|
|
1823
|
-
}
|
|
1824
|
-
throw error;
|
|
1825
|
-
}
|
|
1826
|
-
if (amountIn.currency.equals(tokenIn)) {
|
|
1827
|
-
sdk.sortedInsert(
|
|
1828
|
-
bestTrades,
|
|
1829
|
-
await Trade.fromRoute(
|
|
1830
|
-
new Route([pool, ...currentPools], currencyIn, currencyAmountOut.currency),
|
|
1831
|
-
currencyAmountOut,
|
|
1832
|
-
sdk.TradeType.EXACT_OUTPUT
|
|
1833
|
-
),
|
|
1834
|
-
maxNumResults,
|
|
1835
|
-
tradeComparator
|
|
1836
|
-
);
|
|
1837
|
-
} else if (maxHops > 1 && pools.length > 1) {
|
|
1838
|
-
const poolsExcludingThisPool = pools.slice(0, i).concat(pools.slice(i + 1, pools.length));
|
|
1839
|
-
await Trade.bestTradeExactOut(
|
|
1840
|
-
poolsExcludingThisPool,
|
|
1841
|
-
currencyIn,
|
|
1842
|
-
currencyAmountOut,
|
|
1843
|
-
{
|
|
1844
|
-
maxNumResults,
|
|
1845
|
-
maxHops: maxHops - 1
|
|
1846
|
-
},
|
|
1847
|
-
[pool, ...currentPools],
|
|
1848
|
-
amountIn,
|
|
1849
|
-
bestTrades
|
|
1850
|
-
);
|
|
1851
|
-
}
|
|
1852
|
-
}
|
|
1853
|
-
return bestTrades;
|
|
1850
|
+
return liquidity;
|
|
1851
|
+
}
|
|
1852
|
+
var FEE_BASE = 10n ** 4n;
|
|
1853
|
+
function parseProtocolFees(feeProtocol) {
|
|
1854
|
+
const packed = Number(feeProtocol);
|
|
1855
|
+
if (Number.isNaN(packed)) {
|
|
1856
|
+
throw new Error(`Invalid fee protocol ${feeProtocol}`);
|
|
1854
1857
|
}
|
|
1855
|
-
|
|
1858
|
+
const token0ProtocolFee = packed % 2 ** 16;
|
|
1859
|
+
const token1ProtocolFee = packed >> 16;
|
|
1860
|
+
return [new swapSdkCore.Percent(token0ProtocolFee, FEE_BASE), new swapSdkCore.Percent(token1ProtocolFee, FEE_BASE)];
|
|
1861
|
+
}
|
|
1862
|
+
function sqrtRatioX96ToPrice(sqrtRatioX96, currencyA, currencyB) {
|
|
1863
|
+
const ratioX192 = sqrtRatioX96 * sqrtRatioX96;
|
|
1864
|
+
return currencyA.wrapped.sortsBefore(currencyB.wrapped) ? new swapSdkCore.Price(currencyA.wrapped, currencyB.wrapped, Q192, ratioX192) : new swapSdkCore.Price(currencyA.wrapped, currencyB.wrapped, ratioX192, Q192);
|
|
1865
|
+
}
|
|
1856
1866
|
var IMulticall = [
|
|
1857
1867
|
{
|
|
1858
1868
|
inputs: [
|
|
@@ -1884,14 +1894,14 @@ var _Multicall = class {
|
|
|
1884
1894
|
if (!Array.isArray(calldatas)) {
|
|
1885
1895
|
calldatas = [calldatas];
|
|
1886
1896
|
}
|
|
1887
|
-
return calldatas.length === 1 ? calldatas[0] :
|
|
1897
|
+
return calldatas.length === 1 ? calldatas[0] : viem.encodeFunctionData({ abi: _Multicall.ABI, functionName: "multicall", args: [calldatas] });
|
|
1888
1898
|
}
|
|
1889
1899
|
};
|
|
1890
1900
|
var Multicall = _Multicall;
|
|
1891
|
-
Multicall.
|
|
1901
|
+
Multicall.ABI = IMulticall;
|
|
1892
1902
|
|
|
1893
|
-
// src/abi/NonfungiblePositionManager.
|
|
1894
|
-
var
|
|
1903
|
+
// src/abi/NonfungiblePositionManager.ts
|
|
1904
|
+
var nonfungiblePositionManagerABI = [
|
|
1895
1905
|
{
|
|
1896
1906
|
inputs: [
|
|
1897
1907
|
{ internalType: "address", name: "_deployer", type: "address" },
|
|
@@ -2397,8 +2407,8 @@ var NonfungiblePositionManager_default = [
|
|
|
2397
2407
|
{ stateMutability: "payable", type: "receive" }
|
|
2398
2408
|
];
|
|
2399
2409
|
|
|
2400
|
-
// src/abi/SelfPermit.
|
|
2401
|
-
var
|
|
2410
|
+
// src/abi/SelfPermit.ts
|
|
2411
|
+
var selfPermitABI = [
|
|
2402
2412
|
{
|
|
2403
2413
|
inputs: [
|
|
2404
2414
|
{
|
|
@@ -2564,28 +2574,22 @@ var _SelfPermit = class {
|
|
|
2564
2574
|
constructor() {
|
|
2565
2575
|
}
|
|
2566
2576
|
static encodePermit(token, options) {
|
|
2567
|
-
return isAllowedPermit(options) ?
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
toHex(options.amount),
|
|
2577
|
-
toHex(options.deadline),
|
|
2578
|
-
options.v,
|
|
2579
|
-
options.r,
|
|
2580
|
-
options.s
|
|
2581
|
-
]);
|
|
2577
|
+
return isAllowedPermit(options) ? viem.encodeFunctionData({
|
|
2578
|
+
abi: _SelfPermit.ABI,
|
|
2579
|
+
functionName: "selfPermitAllowed",
|
|
2580
|
+
args: [token.address, BigInt(options.nonce), BigInt(options.expiry), options.v, options.r, options.s]
|
|
2581
|
+
}) : viem.encodeFunctionData({
|
|
2582
|
+
abi: _SelfPermit.ABI,
|
|
2583
|
+
functionName: "selfPermit",
|
|
2584
|
+
args: [token.address, BigInt(options.amount), BigInt(options.deadline), options.v, options.r, options.s]
|
|
2585
|
+
});
|
|
2582
2586
|
}
|
|
2583
2587
|
};
|
|
2584
2588
|
var SelfPermit = _SelfPermit;
|
|
2585
|
-
SelfPermit.
|
|
2589
|
+
SelfPermit.ABI = selfPermitABI;
|
|
2586
2590
|
|
|
2587
|
-
// src/abi/
|
|
2588
|
-
var
|
|
2591
|
+
// src/abi/PeripheryPaymentsWithFee.ts
|
|
2592
|
+
var peripheryPaymentsWithFeeABI = [
|
|
2589
2593
|
{
|
|
2590
2594
|
inputs: [],
|
|
2591
2595
|
name: "refundETH",
|
|
@@ -2705,46 +2709,47 @@ var _Payments = class {
|
|
|
2705
2709
|
constructor() {
|
|
2706
2710
|
}
|
|
2707
2711
|
static encodeFeeBips(fee) {
|
|
2708
|
-
return
|
|
2712
|
+
return fee.multiply(1e4).quotient;
|
|
2709
2713
|
}
|
|
2710
2714
|
static encodeUnwrapWETH9(amountMinimum, recipient, feeOptions) {
|
|
2711
2715
|
recipient = sdk.validateAndParseAddress(recipient);
|
|
2712
2716
|
if (feeOptions) {
|
|
2713
2717
|
const feeBips = this.encodeFeeBips(feeOptions.fee);
|
|
2714
2718
|
const feeRecipient = sdk.validateAndParseAddress(feeOptions.recipient);
|
|
2715
|
-
return
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
feeBips,
|
|
2719
|
-
|
|
2720
|
-
]);
|
|
2719
|
+
return viem.encodeFunctionData({
|
|
2720
|
+
abi: _Payments.ABI,
|
|
2721
|
+
functionName: "unwrapWETH9WithFee",
|
|
2722
|
+
args: [amountMinimum, recipient, feeBips, feeRecipient]
|
|
2723
|
+
});
|
|
2721
2724
|
}
|
|
2722
|
-
return
|
|
2725
|
+
return viem.encodeFunctionData({ abi: _Payments.ABI, functionName: "unwrapWETH9", args: [amountMinimum, recipient] });
|
|
2723
2726
|
}
|
|
2724
2727
|
static encodeSweepToken(token, amountMinimum, recipient, feeOptions) {
|
|
2725
2728
|
recipient = sdk.validateAndParseAddress(recipient);
|
|
2726
2729
|
if (feeOptions) {
|
|
2727
2730
|
const feeBips = this.encodeFeeBips(feeOptions.fee);
|
|
2728
2731
|
const feeRecipient = sdk.validateAndParseAddress(feeOptions.recipient);
|
|
2729
|
-
return
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
recipient,
|
|
2733
|
-
|
|
2734
|
-
feeRecipient
|
|
2735
|
-
]);
|
|
2732
|
+
return viem.encodeFunctionData({
|
|
2733
|
+
abi: _Payments.ABI,
|
|
2734
|
+
functionName: "sweepTokenWithFee",
|
|
2735
|
+
args: [token.address, amountMinimum, recipient, feeBips, feeRecipient]
|
|
2736
|
+
});
|
|
2736
2737
|
}
|
|
2737
|
-
return
|
|
2738
|
+
return viem.encodeFunctionData({
|
|
2739
|
+
abi: _Payments.ABI,
|
|
2740
|
+
functionName: "sweepToken",
|
|
2741
|
+
args: [token.address, amountMinimum, recipient]
|
|
2742
|
+
});
|
|
2738
2743
|
}
|
|
2739
2744
|
static encodeRefundETH() {
|
|
2740
|
-
return
|
|
2745
|
+
return viem.encodeFunctionData({ abi: _Payments.ABI, functionName: "refundETH" });
|
|
2741
2746
|
}
|
|
2742
2747
|
};
|
|
2743
2748
|
var Payments = _Payments;
|
|
2744
|
-
Payments.
|
|
2749
|
+
Payments.ABI = peripheryPaymentsWithFeeABI;
|
|
2745
2750
|
|
|
2746
2751
|
// src/nonfungiblePositionManager.ts
|
|
2747
|
-
var MaxUint128 =
|
|
2752
|
+
var MaxUint128 = 2n ** 128n - 1n;
|
|
2748
2753
|
function isMint(options) {
|
|
2749
2754
|
return Object.keys(options).some((k) => k === "recipient");
|
|
2750
2755
|
}
|
|
@@ -2756,12 +2761,11 @@ var _NonfungiblePositionManager = class {
|
|
|
2756
2761
|
constructor() {
|
|
2757
2762
|
}
|
|
2758
2763
|
static encodeCreate(pool) {
|
|
2759
|
-
return
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
pool.fee,
|
|
2763
|
-
|
|
2764
|
-
]);
|
|
2764
|
+
return viem.encodeFunctionData({
|
|
2765
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
2766
|
+
functionName: "createAndInitializePoolIfNecessary",
|
|
2767
|
+
args: [pool.token0.address, pool.token1.address, pool.fee, pool.sqrtRatioX96]
|
|
2768
|
+
});
|
|
2765
2769
|
}
|
|
2766
2770
|
static createCallParameters(pool) {
|
|
2767
2771
|
return {
|
|
@@ -2770,13 +2774,13 @@ var _NonfungiblePositionManager = class {
|
|
|
2770
2774
|
};
|
|
2771
2775
|
}
|
|
2772
2776
|
static addCallParameters(position, options) {
|
|
2773
|
-
|
|
2777
|
+
invariant9__default.default(position.liquidity > ZERO, "ZERO_LIQUIDITY");
|
|
2774
2778
|
const calldatas = [];
|
|
2775
2779
|
const { amount0: amount0Desired, amount1: amount1Desired } = position.mintAmounts;
|
|
2776
2780
|
const minimumAmounts = position.mintAmountsWithSlippage(options.slippageTolerance);
|
|
2777
|
-
const amount0Min =
|
|
2778
|
-
const amount1Min =
|
|
2779
|
-
const deadline =
|
|
2781
|
+
const amount0Min = minimumAmounts.amount0;
|
|
2782
|
+
const amount1Min = minimumAmounts.amount1;
|
|
2783
|
+
const deadline = BigInt(options.deadline);
|
|
2780
2784
|
if (isMint(options) && options.createPool) {
|
|
2781
2785
|
calldatas.push(this.encodeCreate(position.pool));
|
|
2782
2786
|
}
|
|
@@ -2789,40 +2793,48 @@ var _NonfungiblePositionManager = class {
|
|
|
2789
2793
|
if (isMint(options)) {
|
|
2790
2794
|
const recipient = sdk.validateAndParseAddress(options.recipient);
|
|
2791
2795
|
calldatas.push(
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2796
|
+
viem.encodeFunctionData({
|
|
2797
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
2798
|
+
functionName: "mint",
|
|
2799
|
+
args: [
|
|
2800
|
+
{
|
|
2801
|
+
token0: position.pool.token0.address,
|
|
2802
|
+
token1: position.pool.token1.address,
|
|
2803
|
+
fee: position.pool.fee,
|
|
2804
|
+
tickLower: position.tickLower,
|
|
2805
|
+
tickUpper: position.tickUpper,
|
|
2806
|
+
amount0Desired,
|
|
2807
|
+
amount1Desired,
|
|
2808
|
+
amount0Min,
|
|
2809
|
+
amount1Min,
|
|
2810
|
+
recipient,
|
|
2811
|
+
deadline
|
|
2812
|
+
}
|
|
2813
|
+
]
|
|
2814
|
+
})
|
|
2807
2815
|
);
|
|
2808
2816
|
} else {
|
|
2809
2817
|
calldatas.push(
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2818
|
+
viem.encodeFunctionData({
|
|
2819
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
2820
|
+
functionName: "increaseLiquidity",
|
|
2821
|
+
args: [
|
|
2822
|
+
{
|
|
2823
|
+
tokenId: BigInt(options.tokenId),
|
|
2824
|
+
amount0Desired,
|
|
2825
|
+
amount1Desired,
|
|
2826
|
+
amount0Min,
|
|
2827
|
+
amount1Min,
|
|
2828
|
+
deadline
|
|
2829
|
+
}
|
|
2830
|
+
]
|
|
2831
|
+
})
|
|
2820
2832
|
);
|
|
2821
2833
|
}
|
|
2822
2834
|
let value = toHex(0);
|
|
2823
2835
|
if (options.useNative) {
|
|
2824
2836
|
const { wrapped } = options.useNative;
|
|
2825
|
-
|
|
2837
|
+
invariant9__default.default(position.pool.token0.equals(wrapped) || position.pool.token1.equals(wrapped), "NO_WETH");
|
|
2826
2838
|
const wrappedValue = position.pool.token0.equals(wrapped) ? amount0Desired : amount1Desired;
|
|
2827
2839
|
if (wrappedValue > ZERO) {
|
|
2828
2840
|
calldatas.push(Payments.encodeRefundETH());
|
|
@@ -2836,18 +2848,22 @@ var _NonfungiblePositionManager = class {
|
|
|
2836
2848
|
}
|
|
2837
2849
|
static encodeCollect(options) {
|
|
2838
2850
|
const calldatas = [];
|
|
2839
|
-
const tokenId =
|
|
2851
|
+
const tokenId = BigInt(options.tokenId);
|
|
2840
2852
|
const involvesETH = options.expectedCurrencyOwed0.currency.isNative || options.expectedCurrencyOwed1.currency.isNative;
|
|
2841
2853
|
const recipient = sdk.validateAndParseAddress(options.recipient);
|
|
2842
2854
|
calldatas.push(
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2855
|
+
viem.encodeFunctionData({
|
|
2856
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
2857
|
+
functionName: "collect",
|
|
2858
|
+
args: [
|
|
2859
|
+
{
|
|
2860
|
+
tokenId,
|
|
2861
|
+
recipient: involvesETH ? ADDRESS_ZERO : recipient,
|
|
2862
|
+
amount0Max: MaxUint128,
|
|
2863
|
+
amount1Max: MaxUint128
|
|
2864
|
+
}
|
|
2865
|
+
]
|
|
2866
|
+
})
|
|
2851
2867
|
);
|
|
2852
2868
|
if (involvesETH) {
|
|
2853
2869
|
const ethAmount = options.expectedCurrencyOwed0.currency.isNative ? options.expectedCurrencyOwed0.quotient : options.expectedCurrencyOwed1.quotient;
|
|
@@ -2873,40 +2889,48 @@ var _NonfungiblePositionManager = class {
|
|
|
2873
2889
|
*/
|
|
2874
2890
|
static removeCallParameters(position, options) {
|
|
2875
2891
|
const calldatas = [];
|
|
2876
|
-
const deadline =
|
|
2877
|
-
const tokenId =
|
|
2892
|
+
const deadline = BigInt(options.deadline);
|
|
2893
|
+
const tokenId = BigInt(options.tokenId);
|
|
2878
2894
|
const partialPosition = new Position({
|
|
2879
2895
|
pool: position.pool,
|
|
2880
2896
|
liquidity: options.liquidityPercentage.multiply(position.liquidity).quotient,
|
|
2881
2897
|
tickLower: position.tickLower,
|
|
2882
2898
|
tickUpper: position.tickUpper
|
|
2883
2899
|
});
|
|
2884
|
-
|
|
2900
|
+
invariant9__default.default(partialPosition.liquidity > ZERO, "ZERO_LIQUIDITY");
|
|
2885
2901
|
const { amount0: amount0Min, amount1: amount1Min } = partialPosition.burnAmountsWithSlippage(
|
|
2886
2902
|
options.slippageTolerance
|
|
2887
2903
|
);
|
|
2888
2904
|
if (options.permit) {
|
|
2889
2905
|
calldatas.push(
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2906
|
+
viem.encodeFunctionData({
|
|
2907
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
2908
|
+
functionName: "permit",
|
|
2909
|
+
args: [
|
|
2910
|
+
sdk.validateAndParseAddress(options.permit.spender),
|
|
2911
|
+
tokenId,
|
|
2912
|
+
BigInt(options.permit.deadline),
|
|
2913
|
+
options.permit.v,
|
|
2914
|
+
options.permit.r,
|
|
2915
|
+
options.permit.s
|
|
2916
|
+
]
|
|
2917
|
+
})
|
|
2898
2918
|
);
|
|
2899
2919
|
}
|
|
2900
2920
|
calldatas.push(
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2921
|
+
viem.encodeFunctionData({
|
|
2922
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
2923
|
+
functionName: "decreaseLiquidity",
|
|
2924
|
+
args: [
|
|
2925
|
+
{
|
|
2926
|
+
tokenId,
|
|
2927
|
+
liquidity: partialPosition.liquidity,
|
|
2928
|
+
amount0Min,
|
|
2929
|
+
amount1Min,
|
|
2930
|
+
deadline
|
|
2931
|
+
}
|
|
2932
|
+
]
|
|
2933
|
+
})
|
|
2910
2934
|
);
|
|
2911
2935
|
const { expectedCurrencyOwed0, expectedCurrencyOwed1, ...rest } = options.collectOptions;
|
|
2912
2936
|
calldatas.push(
|
|
@@ -2924,10 +2948,12 @@ var _NonfungiblePositionManager = class {
|
|
|
2924
2948
|
);
|
|
2925
2949
|
if (options.liquidityPercentage.equalTo(ONE)) {
|
|
2926
2950
|
if (options.burnToken) {
|
|
2927
|
-
calldatas.push(
|
|
2951
|
+
calldatas.push(
|
|
2952
|
+
viem.encodeFunctionData({ abi: _NonfungiblePositionManager.ABI, functionName: "burn", args: [tokenId] })
|
|
2953
|
+
);
|
|
2928
2954
|
}
|
|
2929
2955
|
} else {
|
|
2930
|
-
|
|
2956
|
+
invariant9__default.default(options.burnToken !== true, "CANNOT_BURN");
|
|
2931
2957
|
}
|
|
2932
2958
|
return {
|
|
2933
2959
|
calldata: Multicall.encodeMulticall(calldatas),
|
|
@@ -2939,16 +2965,17 @@ var _NonfungiblePositionManager = class {
|
|
|
2939
2965
|
const sender = sdk.validateAndParseAddress(options.sender);
|
|
2940
2966
|
let calldata;
|
|
2941
2967
|
if (options.data) {
|
|
2942
|
-
calldata =
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2968
|
+
calldata = viem.encodeFunctionData({
|
|
2969
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
2970
|
+
functionName: "safeTransferFrom",
|
|
2971
|
+
args: [sender, recipient, BigInt(options.tokenId), options.data]
|
|
2972
|
+
});
|
|
2946
2973
|
} else {
|
|
2947
|
-
calldata =
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2974
|
+
calldata = viem.encodeFunctionData({
|
|
2975
|
+
abi: _NonfungiblePositionManager.ABI,
|
|
2976
|
+
functionName: "safeTransferFrom",
|
|
2977
|
+
args: [sender, recipient, BigInt(options.tokenId)]
|
|
2978
|
+
});
|
|
2952
2979
|
}
|
|
2953
2980
|
return {
|
|
2954
2981
|
calldata,
|
|
@@ -2957,10 +2984,10 @@ var _NonfungiblePositionManager = class {
|
|
|
2957
2984
|
}
|
|
2958
2985
|
};
|
|
2959
2986
|
var NonfungiblePositionManager = _NonfungiblePositionManager;
|
|
2960
|
-
NonfungiblePositionManager.
|
|
2987
|
+
NonfungiblePositionManager.ABI = nonfungiblePositionManagerABI;
|
|
2961
2988
|
|
|
2962
|
-
// src/abi/Quoter.
|
|
2963
|
-
var
|
|
2989
|
+
// src/abi/Quoter.ts
|
|
2990
|
+
var quoterABI = [
|
|
2964
2991
|
{
|
|
2965
2992
|
inputs: [
|
|
2966
2993
|
{
|
|
@@ -3172,8 +3199,8 @@ var Quoter_default = [
|
|
|
3172
3199
|
}
|
|
3173
3200
|
];
|
|
3174
3201
|
|
|
3175
|
-
// src/abi/QuoterV2.
|
|
3176
|
-
var
|
|
3202
|
+
// src/abi/QuoterV2.ts
|
|
3203
|
+
var quoterV2ABI = [
|
|
3177
3204
|
{
|
|
3178
3205
|
inputs: [
|
|
3179
3206
|
{
|
|
@@ -3474,19 +3501,19 @@ var SwapQuoter = class {
|
|
|
3474
3501
|
*/
|
|
3475
3502
|
static quoteCallParameters(route, amount, tradeType, options = {}) {
|
|
3476
3503
|
const singleHop = route.pools.length === 1;
|
|
3477
|
-
const quoteAmount =
|
|
3504
|
+
const quoteAmount = amount.quotient;
|
|
3478
3505
|
let calldata;
|
|
3479
|
-
const
|
|
3506
|
+
const swapAbi = options.useQuoterV2 ? this.V2ABI : this.V1ABI;
|
|
3480
3507
|
if (singleHop) {
|
|
3481
3508
|
const baseQuoteParams = {
|
|
3482
3509
|
tokenIn: route.tokenPath[0].address,
|
|
3483
3510
|
tokenOut: route.tokenPath[1].address,
|
|
3484
3511
|
fee: route.pools[0].fee,
|
|
3485
|
-
sqrtPriceLimitX96:
|
|
3512
|
+
sqrtPriceLimitX96: BigInt(options?.sqrtPriceLimitX96 ?? 0)
|
|
3486
3513
|
};
|
|
3487
3514
|
const v2QuoteParams = {
|
|
3488
3515
|
...baseQuoteParams,
|
|
3489
|
-
...tradeType
|
|
3516
|
+
...tradeType === swapSdkCore.TradeType.EXACT_INPUT ? { amountIn: quoteAmount } : { amount: quoteAmount }
|
|
3490
3517
|
};
|
|
3491
3518
|
const v1QuoteParams = [
|
|
3492
3519
|
baseQuoteParams.tokenIn,
|
|
@@ -3495,16 +3522,31 @@ var SwapQuoter = class {
|
|
|
3495
3522
|
quoteAmount,
|
|
3496
3523
|
baseQuoteParams.sqrtPriceLimitX96
|
|
3497
3524
|
];
|
|
3498
|
-
const tradeTypeFunctionName = tradeType ===
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3525
|
+
const tradeTypeFunctionName = tradeType === swapSdkCore.TradeType.EXACT_INPUT ? "quoteExactInputSingle" : "quoteExactOutputSingle";
|
|
3526
|
+
if (options.useQuoterV2) {
|
|
3527
|
+
calldata = viem.encodeFunctionData({
|
|
3528
|
+
abi: this.V2ABI,
|
|
3529
|
+
functionName: tradeTypeFunctionName,
|
|
3530
|
+
// @ts-ignore // FIXME
|
|
3531
|
+
args: [v2QuoteParams]
|
|
3532
|
+
});
|
|
3533
|
+
} else {
|
|
3534
|
+
calldata = viem.encodeFunctionData({
|
|
3535
|
+
abi: this.V1ABI,
|
|
3536
|
+
functionName: tradeTypeFunctionName,
|
|
3537
|
+
args: v1QuoteParams
|
|
3538
|
+
});
|
|
3539
|
+
}
|
|
3503
3540
|
} else {
|
|
3504
|
-
|
|
3505
|
-
const path = encodeRouteToPath(route, tradeType ===
|
|
3506
|
-
const tradeTypeFunctionName = tradeType ===
|
|
3507
|
-
calldata =
|
|
3541
|
+
invariant9__default.default(options?.sqrtPriceLimitX96 === void 0, "MULTIHOP_PRICE_LIMIT");
|
|
3542
|
+
const path = encodeRouteToPath(route, tradeType === swapSdkCore.TradeType.EXACT_OUTPUT);
|
|
3543
|
+
const tradeTypeFunctionName = tradeType === swapSdkCore.TradeType.EXACT_INPUT ? "quoteExactInput" : "quoteExactOutput";
|
|
3544
|
+
calldata = viem.encodeFunctionData({
|
|
3545
|
+
// @ts-ignore
|
|
3546
|
+
abi: swapAbi,
|
|
3547
|
+
functionName: tradeTypeFunctionName,
|
|
3548
|
+
args: [path, quoteAmount]
|
|
3549
|
+
});
|
|
3508
3550
|
}
|
|
3509
3551
|
return {
|
|
3510
3552
|
calldata,
|
|
@@ -3512,11 +3554,11 @@ var SwapQuoter = class {
|
|
|
3512
3554
|
};
|
|
3513
3555
|
}
|
|
3514
3556
|
};
|
|
3515
|
-
SwapQuoter.
|
|
3516
|
-
SwapQuoter.
|
|
3557
|
+
SwapQuoter.V1ABI = quoterABI;
|
|
3558
|
+
SwapQuoter.V2ABI = quoterV2ABI;
|
|
3517
3559
|
|
|
3518
|
-
// src/abi/V3Staker.
|
|
3519
|
-
var
|
|
3560
|
+
// src/abi/V3Staker.ts
|
|
3561
|
+
var v3StakerABI = [
|
|
3520
3562
|
{
|
|
3521
3563
|
inputs: [
|
|
3522
3564
|
{
|
|
@@ -4236,15 +4278,20 @@ var _Staker = class {
|
|
|
4236
4278
|
static encodeClaim(incentiveKey, options) {
|
|
4237
4279
|
const calldatas = [];
|
|
4238
4280
|
calldatas.push(
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4281
|
+
viem.encodeFunctionData({
|
|
4282
|
+
abi: _Staker.ABI,
|
|
4283
|
+
functionName: "unstakeToken",
|
|
4284
|
+
args: [this._encodeIncentiveKey(incentiveKey), BigInt(options.tokenId)]
|
|
4285
|
+
})
|
|
4243
4286
|
);
|
|
4244
4287
|
const recipient = sdk.validateAndParseAddress(options.recipient);
|
|
4245
4288
|
const amount = options.amount ?? 0;
|
|
4246
4289
|
calldatas.push(
|
|
4247
|
-
|
|
4290
|
+
viem.encodeFunctionData({
|
|
4291
|
+
abi: _Staker.ABI,
|
|
4292
|
+
functionName: "claimReward",
|
|
4293
|
+
args: [incentiveKey.rewardToken.address, recipient, BigInt(amount)]
|
|
4294
|
+
})
|
|
4248
4295
|
);
|
|
4249
4296
|
return calldatas;
|
|
4250
4297
|
}
|
|
@@ -4264,10 +4311,11 @@ var _Staker = class {
|
|
|
4264
4311
|
const incentiveKey = incentiveKeys[i];
|
|
4265
4312
|
calldatas = calldatas.concat(this.encodeClaim(incentiveKey, options));
|
|
4266
4313
|
calldatas.push(
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4314
|
+
viem.encodeFunctionData({
|
|
4315
|
+
abi: _Staker.ABI,
|
|
4316
|
+
functionName: "stakeToken",
|
|
4317
|
+
args: [this._encodeIncentiveKey(incentiveKey), BigInt(options.tokenId)]
|
|
4318
|
+
})
|
|
4271
4319
|
);
|
|
4272
4320
|
}
|
|
4273
4321
|
return {
|
|
@@ -4295,11 +4343,11 @@ var _Staker = class {
|
|
|
4295
4343
|
}
|
|
4296
4344
|
const owner = sdk.validateAndParseAddress(withdrawOptions.owner);
|
|
4297
4345
|
calldatas.push(
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4346
|
+
viem.encodeFunctionData({
|
|
4347
|
+
abi: _Staker.ABI,
|
|
4348
|
+
functionName: "withdrawToken",
|
|
4349
|
+
args: [BigInt(withdrawOptions.tokenId), owner, toHex(0)]
|
|
4350
|
+
})
|
|
4303
4351
|
);
|
|
4304
4352
|
return {
|
|
4305
4353
|
calldata: Multicall.encodeMulticall(calldatas),
|
|
@@ -4320,16 +4368,18 @@ var _Staker = class {
|
|
|
4320
4368
|
const incentiveKey = incentiveKeys[i];
|
|
4321
4369
|
keys.push(this._encodeIncentiveKey(incentiveKey));
|
|
4322
4370
|
}
|
|
4323
|
-
data =
|
|
4371
|
+
data = viem.encodeAbiParameters(viem.parseAbiParameters([`${_Staker.INCENTIVE_KEY_ABI}[]`]), [keys]);
|
|
4324
4372
|
} else {
|
|
4325
|
-
data =
|
|
4373
|
+
data = viem.encodeAbiParameters(viem.parseAbiParameters(_Staker.INCENTIVE_KEY_ABI), [
|
|
4374
|
+
this._encodeIncentiveKey(incentiveKeys[0])
|
|
4375
|
+
]);
|
|
4326
4376
|
}
|
|
4327
4377
|
return data;
|
|
4328
4378
|
}
|
|
4329
4379
|
/**
|
|
4330
4380
|
*
|
|
4331
4381
|
* @param incentiveKey An `IncentiveKey` which represents a unique staking program.
|
|
4332
|
-
* @returns An encoded IncentiveKey to be read by
|
|
4382
|
+
* @returns An encoded IncentiveKey to be read by viem
|
|
4333
4383
|
*/
|
|
4334
4384
|
static _encodeIncentiveKey(incentiveKey) {
|
|
4335
4385
|
const { token0, token1, fee } = incentiveKey.pool;
|
|
@@ -4337,18 +4387,18 @@ var _Staker = class {
|
|
|
4337
4387
|
return {
|
|
4338
4388
|
rewardToken: incentiveKey.rewardToken.address,
|
|
4339
4389
|
pool: Pool.getAddress(token0, token1, fee),
|
|
4340
|
-
startTime:
|
|
4341
|
-
endTime:
|
|
4390
|
+
startTime: BigInt(incentiveKey.startTime),
|
|
4391
|
+
endTime: BigInt(incentiveKey.endTime),
|
|
4342
4392
|
refundee
|
|
4343
4393
|
};
|
|
4344
4394
|
}
|
|
4345
4395
|
};
|
|
4346
4396
|
var Staker = _Staker;
|
|
4347
|
-
Staker.
|
|
4397
|
+
Staker.ABI = v3StakerABI;
|
|
4348
4398
|
Staker.INCENTIVE_KEY_ABI = "tuple(address rewardToken, address pool, uint256 startTime, uint256 endTime, address refundee)";
|
|
4349
4399
|
|
|
4350
|
-
// src/abi/SwapRouter.
|
|
4351
|
-
var
|
|
4400
|
+
// src/abi/SwapRouter.ts
|
|
4401
|
+
var swapRouterABI = [
|
|
4352
4402
|
{
|
|
4353
4403
|
inputs: [
|
|
4354
4404
|
{
|
|
@@ -4951,11 +5001,11 @@ var _SwapRouter = class {
|
|
|
4951
5001
|
const sampleTrade = trades[0];
|
|
4952
5002
|
const tokenIn = sampleTrade.inputAmount.currency.wrapped;
|
|
4953
5003
|
const tokenOut = sampleTrade.outputAmount.currency.wrapped;
|
|
4954
|
-
|
|
5004
|
+
invariant9__default.default(
|
|
4955
5005
|
trades.every((trade) => trade.inputAmount.currency.wrapped.equals(tokenIn)),
|
|
4956
5006
|
"TOKEN_IN_DIFF"
|
|
4957
5007
|
);
|
|
4958
|
-
|
|
5008
|
+
invariant9__default.default(
|
|
4959
5009
|
trades.every((trade) => trade.outputAmount.currency.wrapped.equals(tokenOut)),
|
|
4960
5010
|
"TOKEN_OUT_DIFF"
|
|
4961
5011
|
);
|
|
@@ -4972,15 +5022,15 @@ var _SwapRouter = class {
|
|
|
4972
5022
|
const routerMustCustody = outputIsNative || !!options.fee;
|
|
4973
5023
|
const totalValue = inputIsNative ? trades.reduce((sum, trade) => sum.add(trade.maximumAmountIn(options.slippageTolerance)), ZERO_IN) : ZERO_IN;
|
|
4974
5024
|
if (options.inputTokenPermit) {
|
|
4975
|
-
|
|
5025
|
+
invariant9__default.default(sampleTrade.inputAmount.currency.isToken, "NON_TOKEN_PERMIT");
|
|
4976
5026
|
calldatas.push(SelfPermit.encodePermit(sampleTrade.inputAmount.currency, options.inputTokenPermit));
|
|
4977
5027
|
}
|
|
4978
5028
|
const recipient = sdk.validateAndParseAddress(options.recipient);
|
|
4979
|
-
const deadline =
|
|
5029
|
+
const deadline = BigInt(options.deadline);
|
|
4980
5030
|
for (const trade of trades) {
|
|
4981
5031
|
for (const { route, inputAmount, outputAmount } of trade.swaps) {
|
|
4982
|
-
const amountIn =
|
|
4983
|
-
const amountOut =
|
|
5032
|
+
const amountIn = BigInt(trade.maximumAmountIn(options.slippageTolerance, inputAmount).quotient);
|
|
5033
|
+
const amountOut = BigInt(trade.minimumAmountOut(options.slippageTolerance, outputAmount).quotient);
|
|
4984
5034
|
const singleHop = route.pools.length === 1;
|
|
4985
5035
|
if (singleHop) {
|
|
4986
5036
|
if (trade.tradeType === sdk.TradeType.EXACT_INPUT) {
|
|
@@ -4992,9 +5042,15 @@ var _SwapRouter = class {
|
|
|
4992
5042
|
deadline,
|
|
4993
5043
|
amountIn,
|
|
4994
5044
|
amountOutMinimum: amountOut,
|
|
4995
|
-
sqrtPriceLimitX96:
|
|
5045
|
+
sqrtPriceLimitX96: BigInt(options.sqrtPriceLimitX96 ?? 0)
|
|
4996
5046
|
};
|
|
4997
|
-
calldatas.push(
|
|
5047
|
+
calldatas.push(
|
|
5048
|
+
viem.encodeFunctionData({
|
|
5049
|
+
abi: _SwapRouter.ABI,
|
|
5050
|
+
functionName: "exactInputSingle",
|
|
5051
|
+
args: [exactInputSingleParams]
|
|
5052
|
+
})
|
|
5053
|
+
);
|
|
4998
5054
|
} else {
|
|
4999
5055
|
const exactOutputSingleParams = {
|
|
5000
5056
|
tokenIn: route.tokenPath[0].address,
|
|
@@ -5004,12 +5060,18 @@ var _SwapRouter = class {
|
|
|
5004
5060
|
deadline,
|
|
5005
5061
|
amountOut,
|
|
5006
5062
|
amountInMaximum: amountIn,
|
|
5007
|
-
sqrtPriceLimitX96:
|
|
5063
|
+
sqrtPriceLimitX96: BigInt(options.sqrtPriceLimitX96 ?? 0)
|
|
5008
5064
|
};
|
|
5009
|
-
calldatas.push(
|
|
5065
|
+
calldatas.push(
|
|
5066
|
+
viem.encodeFunctionData({
|
|
5067
|
+
abi: _SwapRouter.ABI,
|
|
5068
|
+
functionName: "exactOutputSingle",
|
|
5069
|
+
args: [exactOutputSingleParams]
|
|
5070
|
+
})
|
|
5071
|
+
);
|
|
5010
5072
|
}
|
|
5011
5073
|
} else {
|
|
5012
|
-
|
|
5074
|
+
invariant9__default.default(options.sqrtPriceLimitX96 === void 0, "MULTIHOP_PRICE_LIMIT");
|
|
5013
5075
|
const path = encodeRouteToPath(route, trade.tradeType === sdk.TradeType.EXACT_OUTPUT);
|
|
5014
5076
|
if (trade.tradeType === sdk.TradeType.EXACT_INPUT) {
|
|
5015
5077
|
const exactInputParams = {
|
|
@@ -5019,7 +5081,9 @@ var _SwapRouter = class {
|
|
|
5019
5081
|
amountIn,
|
|
5020
5082
|
amountOutMinimum: amountOut
|
|
5021
5083
|
};
|
|
5022
|
-
calldatas.push(
|
|
5084
|
+
calldatas.push(
|
|
5085
|
+
viem.encodeFunctionData({ abi: _SwapRouter.ABI, functionName: "exactInput", args: [exactInputParams] })
|
|
5086
|
+
);
|
|
5023
5087
|
} else {
|
|
5024
5088
|
const exactOutputParams = {
|
|
5025
5089
|
path,
|
|
@@ -5028,7 +5092,9 @@ var _SwapRouter = class {
|
|
|
5028
5092
|
amountOut,
|
|
5029
5093
|
amountInMaximum: amountIn
|
|
5030
5094
|
};
|
|
5031
|
-
calldatas.push(
|
|
5095
|
+
calldatas.push(
|
|
5096
|
+
viem.encodeFunctionData({ abi: _SwapRouter.ABI, functionName: "exactOutput", args: [exactOutputParams] })
|
|
5097
|
+
);
|
|
5032
5098
|
}
|
|
5033
5099
|
}
|
|
5034
5100
|
}
|
|
@@ -5061,10 +5127,11 @@ var _SwapRouter = class {
|
|
|
5061
5127
|
}
|
|
5062
5128
|
};
|
|
5063
5129
|
var SwapRouter = _SwapRouter;
|
|
5064
|
-
|
|
5130
|
+
// public static INTERFACE: Interface = new Interface(ISwapRouter)
|
|
5131
|
+
SwapRouter.ABI = swapRouterABI;
|
|
5065
5132
|
|
|
5066
|
-
// src/abi/MasterChefV3.
|
|
5067
|
-
var
|
|
5133
|
+
// src/abi/MasterChefV3.ts
|
|
5134
|
+
var masterChefV3ABI = [
|
|
5068
5135
|
{
|
|
5069
5136
|
inputs: [
|
|
5070
5137
|
{ internalType: "contract IERC20", name: "_CAKE", type: "address" },
|
|
@@ -5752,14 +5819,14 @@ var _MasterChefV3 = class {
|
|
|
5752
5819
|
// Copy from NonfungiblePositionManager
|
|
5753
5820
|
// Only support increaseLiquidity
|
|
5754
5821
|
static addCallParameters(position, options) {
|
|
5755
|
-
|
|
5822
|
+
invariant9__default.default(position.liquidity > sdk.ZERO, "ZERO_LIQUIDITY");
|
|
5756
5823
|
const calldatas = [];
|
|
5757
5824
|
const { amount0: amount0Desired, amount1: amount1Desired } = position.mintAmounts;
|
|
5758
5825
|
const minimumAmounts = position.mintAmountsWithSlippage(options.slippageTolerance);
|
|
5759
|
-
const amount0Min =
|
|
5760
|
-
const amount1Min =
|
|
5761
|
-
const deadline =
|
|
5762
|
-
|
|
5826
|
+
const amount0Min = BigInt(minimumAmounts.amount0);
|
|
5827
|
+
const amount1Min = BigInt(minimumAmounts.amount1);
|
|
5828
|
+
const deadline = BigInt(options.deadline);
|
|
5829
|
+
invariant9__default.default(!isMint(options), "NO_MINT_SUPPORT");
|
|
5763
5830
|
if (options.token0Permit) {
|
|
5764
5831
|
calldatas.push(SelfPermit.encodePermit(position.pool.token0, options.token0Permit));
|
|
5765
5832
|
}
|
|
@@ -5767,21 +5834,25 @@ var _MasterChefV3 = class {
|
|
|
5767
5834
|
calldatas.push(SelfPermit.encodePermit(position.pool.token1, options.token1Permit));
|
|
5768
5835
|
}
|
|
5769
5836
|
calldatas.push(
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5837
|
+
viem.encodeFunctionData({
|
|
5838
|
+
abi: _MasterChefV3.ABI,
|
|
5839
|
+
functionName: "increaseLiquidity",
|
|
5840
|
+
args: [
|
|
5841
|
+
{
|
|
5842
|
+
tokenId: BigInt(options.tokenId),
|
|
5843
|
+
amount0Desired,
|
|
5844
|
+
amount1Desired,
|
|
5845
|
+
amount0Min,
|
|
5846
|
+
amount1Min,
|
|
5847
|
+
deadline
|
|
5848
|
+
}
|
|
5849
|
+
]
|
|
5850
|
+
})
|
|
5780
5851
|
);
|
|
5781
5852
|
let value = toHex(0);
|
|
5782
5853
|
if (options.useNative) {
|
|
5783
5854
|
const { wrapped } = options.useNative;
|
|
5784
|
-
|
|
5855
|
+
invariant9__default.default(position.pool.token0.equals(wrapped) || position.pool.token1.equals(wrapped), "NO_WETH");
|
|
5785
5856
|
const wrappedValue = position.pool.token0.equals(wrapped) ? amount0Desired : amount1Desired;
|
|
5786
5857
|
value = toHex(wrappedValue);
|
|
5787
5858
|
}
|
|
@@ -5793,18 +5864,22 @@ var _MasterChefV3 = class {
|
|
|
5793
5864
|
// Copy from NonfungiblePositionManager
|
|
5794
5865
|
static encodeCollect(options) {
|
|
5795
5866
|
const calldatas = [];
|
|
5796
|
-
const tokenId =
|
|
5867
|
+
const tokenId = BigInt(options.tokenId);
|
|
5797
5868
|
const involvesETH = options.expectedCurrencyOwed0.currency.isNative || options.expectedCurrencyOwed1.currency.isNative;
|
|
5798
5869
|
const recipient = sdk.validateAndParseAddress(options.recipient);
|
|
5799
5870
|
calldatas.push(
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5871
|
+
viem.encodeFunctionData({
|
|
5872
|
+
abi: _MasterChefV3.ABI,
|
|
5873
|
+
functionName: "collect",
|
|
5874
|
+
args: [
|
|
5875
|
+
{
|
|
5876
|
+
tokenId,
|
|
5877
|
+
recipient: involvesETH ? ADDRESS_ZERO : recipient,
|
|
5878
|
+
amount0Max: MaxUint128,
|
|
5879
|
+
amount1Max: MaxUint128
|
|
5880
|
+
}
|
|
5881
|
+
]
|
|
5882
|
+
})
|
|
5808
5883
|
);
|
|
5809
5884
|
if (involvesETH) {
|
|
5810
5885
|
const ethAmount = options.expectedCurrencyOwed0.currency.isNative ? options.expectedCurrencyOwed0.quotient : options.expectedCurrencyOwed1.quotient;
|
|
@@ -5824,40 +5899,35 @@ var _MasterChefV3 = class {
|
|
|
5824
5899
|
}
|
|
5825
5900
|
static removeCallParameters(position, options) {
|
|
5826
5901
|
const calldatas = [];
|
|
5827
|
-
const deadline =
|
|
5828
|
-
const tokenId =
|
|
5902
|
+
const deadline = BigInt(options.deadline);
|
|
5903
|
+
const tokenId = BigInt(options.tokenId);
|
|
5829
5904
|
const partialPosition = new Position({
|
|
5830
5905
|
pool: position.pool,
|
|
5831
5906
|
liquidity: options.liquidityPercentage.multiply(position.liquidity).quotient,
|
|
5832
5907
|
tickLower: position.tickLower,
|
|
5833
5908
|
tickUpper: position.tickUpper
|
|
5834
5909
|
});
|
|
5835
|
-
|
|
5910
|
+
invariant9__default.default(partialPosition.liquidity > sdk.ZERO, "ZERO_LIQUIDITY");
|
|
5836
5911
|
const { amount0: amount0Min, amount1: amount1Min } = partialPosition.burnAmountsWithSlippage(
|
|
5837
5912
|
options.slippageTolerance
|
|
5838
5913
|
);
|
|
5839
5914
|
if (options.permit) {
|
|
5840
|
-
|
|
5841
|
-
_MasterChefV3.INTERFACE.encodeFunctionData("permit", [
|
|
5842
|
-
sdk.validateAndParseAddress(options.permit.spender),
|
|
5843
|
-
tokenId,
|
|
5844
|
-
toHex(options.permit.deadline),
|
|
5845
|
-
options.permit.v,
|
|
5846
|
-
options.permit.r,
|
|
5847
|
-
options.permit.s
|
|
5848
|
-
])
|
|
5849
|
-
);
|
|
5915
|
+
throw new Error("NOT_IMPLEMENTED");
|
|
5850
5916
|
}
|
|
5851
5917
|
calldatas.push(
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5918
|
+
viem.encodeFunctionData({
|
|
5919
|
+
abi: _MasterChefV3.ABI,
|
|
5920
|
+
functionName: "decreaseLiquidity",
|
|
5921
|
+
args: [
|
|
5922
|
+
{
|
|
5923
|
+
tokenId,
|
|
5924
|
+
liquidity: partialPosition.liquidity,
|
|
5925
|
+
amount0Min,
|
|
5926
|
+
amount1Min,
|
|
5927
|
+
deadline
|
|
5928
|
+
}
|
|
5929
|
+
]
|
|
5930
|
+
})
|
|
5861
5931
|
);
|
|
5862
5932
|
const { expectedCurrencyOwed0, expectedCurrencyOwed1, ...rest } = options.collectOptions;
|
|
5863
5933
|
calldatas.push(
|
|
@@ -5876,26 +5946,28 @@ var _MasterChefV3 = class {
|
|
|
5876
5946
|
if (rest?.recipient) {
|
|
5877
5947
|
if (options.liquidityPercentage.equalTo(sdk.ONE)) {
|
|
5878
5948
|
calldatas.push(
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5949
|
+
viem.encodeFunctionData({
|
|
5950
|
+
abi: _MasterChefV3.ABI,
|
|
5951
|
+
functionName: "withdraw",
|
|
5952
|
+
args: [tokenId, sdk.validateAndParseAddress(rest?.recipient)]
|
|
5953
|
+
})
|
|
5883
5954
|
);
|
|
5884
5955
|
} else {
|
|
5885
5956
|
calldatas.push(
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5957
|
+
viem.encodeFunctionData({
|
|
5958
|
+
abi: _MasterChefV3.ABI,
|
|
5959
|
+
functionName: "harvest",
|
|
5960
|
+
args: [tokenId, sdk.validateAndParseAddress(rest?.recipient)]
|
|
5961
|
+
})
|
|
5890
5962
|
);
|
|
5891
5963
|
}
|
|
5892
5964
|
}
|
|
5893
5965
|
if (options.liquidityPercentage.equalTo(sdk.ONE)) {
|
|
5894
5966
|
if (options.burnToken) {
|
|
5895
|
-
calldatas.push(
|
|
5967
|
+
calldatas.push(viem.encodeFunctionData({ abi: _MasterChefV3.ABI, functionName: "burn", args: [tokenId] }));
|
|
5896
5968
|
}
|
|
5897
5969
|
} else {
|
|
5898
|
-
|
|
5970
|
+
invariant9__default.default(options.burnToken !== true, "CANNOT_BURN");
|
|
5899
5971
|
}
|
|
5900
5972
|
return {
|
|
5901
5973
|
calldata: Multicall.encodeMulticall(calldatas),
|
|
@@ -5921,7 +5993,11 @@ var _MasterChefV3 = class {
|
|
|
5921
5993
|
const { tokenId, to } = options;
|
|
5922
5994
|
const calldatas = [];
|
|
5923
5995
|
calldatas.push(
|
|
5924
|
-
|
|
5996
|
+
viem.encodeFunctionData({
|
|
5997
|
+
abi: _MasterChefV3.ABI,
|
|
5998
|
+
functionName: "harvest",
|
|
5999
|
+
args: [BigInt(tokenId), sdk.validateAndParseAddress(to)]
|
|
6000
|
+
})
|
|
5925
6001
|
);
|
|
5926
6002
|
return calldatas;
|
|
5927
6003
|
}
|
|
@@ -5929,7 +6005,11 @@ var _MasterChefV3 = class {
|
|
|
5929
6005
|
const { tokenId, to } = options;
|
|
5930
6006
|
const calldatas = [];
|
|
5931
6007
|
calldatas.push(
|
|
5932
|
-
|
|
6008
|
+
viem.encodeFunctionData({
|
|
6009
|
+
abi: _MasterChefV3.ABI,
|
|
6010
|
+
functionName: "withdraw",
|
|
6011
|
+
args: [BigInt(tokenId), sdk.validateAndParseAddress(to)]
|
|
6012
|
+
})
|
|
5933
6013
|
);
|
|
5934
6014
|
return {
|
|
5935
6015
|
calldata: Multicall.encodeMulticall(calldatas),
|
|
@@ -5938,7 +6018,7 @@ var _MasterChefV3 = class {
|
|
|
5938
6018
|
}
|
|
5939
6019
|
};
|
|
5940
6020
|
var MasterChefV3 = _MasterChefV3;
|
|
5941
|
-
MasterChefV3.
|
|
6021
|
+
MasterChefV3.ABI = masterChefV3ABI;
|
|
5942
6022
|
|
|
5943
6023
|
exports.ADDRESS_ZERO = ADDRESS_ZERO;
|
|
5944
6024
|
exports.DEPLOYER_ADDRESS = DEPLOYER_ADDRESS;
|
|
@@ -5990,13 +6070,21 @@ exports.getLiquidityFromSqrtRatioX96 = getLiquidityFromSqrtRatioX96;
|
|
|
5990
6070
|
exports.getLiquidityFromTick = getLiquidityFromTick;
|
|
5991
6071
|
exports.isMint = isMint;
|
|
5992
6072
|
exports.isSorted = isSorted;
|
|
6073
|
+
exports.masterChefV3ABI = masterChefV3ABI;
|
|
5993
6074
|
exports.maxLiquidityForAmounts = maxLiquidityForAmounts;
|
|
5994
6075
|
exports.mostSignificantBit = mostSignificantBit;
|
|
5995
6076
|
exports.nearestUsableTick = nearestUsableTick;
|
|
6077
|
+
exports.nonfungiblePositionManagerABI = nonfungiblePositionManagerABI;
|
|
5996
6078
|
exports.parseProtocolFees = parseProtocolFees;
|
|
6079
|
+
exports.peripheryPaymentsWithFeeABI = peripheryPaymentsWithFeeABI;
|
|
5997
6080
|
exports.priceToClosestTick = priceToClosestTick;
|
|
6081
|
+
exports.quoterABI = quoterABI;
|
|
6082
|
+
exports.quoterV2ABI = quoterV2ABI;
|
|
6083
|
+
exports.selfPermitABI = selfPermitABI;
|
|
5998
6084
|
exports.sqrtRatioX96ToPrice = sqrtRatioX96ToPrice;
|
|
5999
6085
|
exports.subIn256 = subIn256;
|
|
6086
|
+
exports.swapRouterABI = swapRouterABI;
|
|
6000
6087
|
exports.tickToPrice = tickToPrice;
|
|
6001
6088
|
exports.toHex = toHex;
|
|
6002
6089
|
exports.tradeComparator = tradeComparator;
|
|
6090
|
+
exports.v3StakerABI = v3StakerABI;
|