@alcorexchange/alcor-swap-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +2 -0
- package/.eslintrc +12 -0
- package/LICENSE +21 -0
- package/build/entities/baseCurrency.js +27 -0
- package/build/entities/currency.js +2 -0
- package/build/entities/fractions/currencyAmount.js +80 -0
- package/build/entities/fractions/fraction.js +117 -0
- package/build/entities/fractions/index.js +11 -0
- package/build/entities/fractions/percent.js +46 -0
- package/build/entities/fractions/price.js +73 -0
- package/build/entities/index.js +26 -0
- package/build/entities/pool.js +248 -0
- package/build/entities/position.js +364 -0
- package/build/entities/route.js +70 -0
- package/build/entities/tick.js +23 -0
- package/build/entities/tickDataProvider.js +30 -0
- package/build/entities/tickListDataProvider.js +35 -0
- package/build/entities/token.js +53 -0
- package/build/entities/trade.js +464 -0
- package/build/index.js +19 -0
- package/build/internalConstants.js +54 -0
- package/build/utils/computeAllRoutes.js +39 -0
- package/build/utils/encodeSqrtRatioX64.js +21 -0
- package/build/utils/fullMath.js +22 -0
- package/build/utils/index.js +30 -0
- package/build/utils/isSorted.js +18 -0
- package/build/utils/liquidityMath.js +23 -0
- package/build/utils/maxLiquidityForAmounts.js +86 -0
- package/build/utils/mostSignificantBit.js +27 -0
- package/build/utils/nearestUsableTick.js +26 -0
- package/build/utils/positionLibrary.js +22 -0
- package/build/utils/priceTickConversions.js +51 -0
- package/build/utils/sortedInsert.js +39 -0
- package/build/utils/sqrt.js +33 -0
- package/build/utils/sqrtPriceMath.js +92 -0
- package/build/utils/swapMath.js +86 -0
- package/build/utils/tickLibrary.js +61 -0
- package/build/utils/tickList.js +110 -0
- package/build/utils/tickMath.js +122 -0
- package/jest.config.js +40 -0
- package/nodemon.json +6 -0
- package/package.json +51 -0
- package/src/entities/baseCurrency.ts +53 -0
- package/src/entities/currency.ts +3 -0
- package/src/entities/fractions/currencyAmount.ts +129 -0
- package/src/entities/fractions/fraction.ts +190 -0
- package/src/entities/fractions/index.ts +4 -0
- package/src/entities/fractions/percent.ts +54 -0
- package/src/entities/fractions/price.ts +127 -0
- package/src/entities/index.ts +11 -0
- package/src/entities/pool.ts +399 -0
- package/src/entities/position.ts +591 -0
- package/src/entities/route.ts +84 -0
- package/src/entities/tick.ts +48 -0
- package/src/entities/tickDataProvider.ts +43 -0
- package/src/entities/tickListDataProvider.ts +37 -0
- package/src/entities/token.ts +56 -0
- package/src/entities/trade.ts +650 -0
- package/src/index.ts +3 -0
- package/src/internalConstants.ts +58 -0
- package/src/utils/computeAllRoutes.ts +64 -0
- package/src/utils/encodeSqrtRatioX64.ts +20 -0
- package/src/utils/fullMath.ts +17 -0
- package/src/utils/index.ts +14 -0
- package/src/utils/isSorted.ts +17 -0
- package/src/utils/liquidityMath.ts +17 -0
- package/src/utils/maxLiquidityForAmounts.ts +127 -0
- package/src/utils/mostSignificantBit.ts +25 -0
- package/src/utils/nearestUsableTick.ts +23 -0
- package/src/utils/positionLibrary.ts +37 -0
- package/src/utils/priceTickConversions.ts +57 -0
- package/src/utils/sortedInsert.ts +35 -0
- package/src/utils/sqrt.ts +31 -0
- package/src/utils/sqrtPriceMath.ts +169 -0
- package/src/utils/swapMath.ts +175 -0
- package/src/utils/tickLibrary.ts +88 -0
- package/src/utils/tickList.ts +147 -0
- package/src/utils/tickMath.ts +166 -0
- package/test/bestTradeExactOut.test.ts +266 -0
- package/test/currencyAmount.test.js +92 -0
- package/test/currencyAmount.test.ts +114 -0
- package/test/encodeSqrtRatioX64.test.ts +33 -0
- package/test/fixtures/pools.json +276 -0
- package/test/fixtures/ticks.json +608 -0
- package/test/fraction.test.js +87 -0
- package/test/fraction.test.ts +176 -0
- package/test/isSorted.test.ts +52 -0
- package/test/maxLiquidityForAmounts.test copy.ts +256 -0
- package/test/mostSignificantBit.test.ts +32 -0
- package/test/nearestUsableTick.test.ts +54 -0
- package/test/percent.test.js +52 -0
- package/test/percent.test.ts +68 -0
- package/test/pool.test.ts +377 -0
- package/test/position.test.ts +579 -0
- package/test/positionLibrary.test.ts +31 -0
- package/test/price.test.js +57 -0
- package/test/price.test.ts +62 -0
- package/test/priceTickConversions.test.ts +137 -0
- package/test/sqrtPriceMath.test.ts +113 -0
- package/test/tick.test.js +22 -0
- package/test/tick.test.ts +28 -0
- package/test/tickDataProvider.test.ts +17 -0
- package/test/tickLibrary.test.ts +111 -0
- package/test/tickList.test.ts +215 -0
- package/test/tickListDataProvider.test.ts +64 -0
- package/test/tickMath.test.ts +66 -0
- package/test/token.test.ts +58 -0
- package/test/trade.test.ts +210 -0
- package/test2.ts +73 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.Pool = void 0;
|
|
16
|
+
const fractions_1 = require("./fractions");
|
|
17
|
+
const internalConstants_1 = require("../internalConstants");
|
|
18
|
+
const jsbi_1 = __importDefault(require("jsbi"));
|
|
19
|
+
const tiny_invariant_1 = __importDefault(require("tiny-invariant"));
|
|
20
|
+
const internalConstants_2 = require("../internalConstants");
|
|
21
|
+
const liquidityMath_1 = require("../utils/liquidityMath");
|
|
22
|
+
const swapMath_1 = require("../utils/swapMath");
|
|
23
|
+
const tickMath_1 = require("../utils/tickMath");
|
|
24
|
+
const tickDataProvider_1 = require("./tickDataProvider");
|
|
25
|
+
const tickListDataProvider_1 = require("./tickListDataProvider");
|
|
26
|
+
/**
|
|
27
|
+
* By default, pools will not allow operations that require ticks.
|
|
28
|
+
*/
|
|
29
|
+
const NO_TICK_DATA_PROVIDER_DEFAULT = new tickDataProvider_1.NoTickDataProvider();
|
|
30
|
+
/**
|
|
31
|
+
* Represents a V3 pool
|
|
32
|
+
*/
|
|
33
|
+
class Pool {
|
|
34
|
+
/**
|
|
35
|
+
* Construct a pool
|
|
36
|
+
* @param tokenA One of the tokens in the pool
|
|
37
|
+
* @param tokenB The other token in the pool
|
|
38
|
+
* @param fee The fee in hundredths of a bips of the input amount of every swap that is collected by the pool
|
|
39
|
+
* @param sqrtPriceX64 The sqrt of the current ratio of amounts of tokenB to tokenA
|
|
40
|
+
* @param liquidity The current value of in range liquidity
|
|
41
|
+
* @param tickCurrent The current tick of the pool
|
|
42
|
+
* @param ticks The current state of the pool ticks or a data provider that can return tick data
|
|
43
|
+
*/
|
|
44
|
+
constructor({ id, tokenA, tokenB, fee, sqrtPriceX64, liquidity, tickCurrent, ticks = NO_TICK_DATA_PROVIDER_DEFAULT, feeGrowthGlobalAX64 = 0, feeGrowthGlobalBX64 = 0, }) {
|
|
45
|
+
(0, tiny_invariant_1.default)(Number.isInteger(fee) && fee < 1000000, "FEE");
|
|
46
|
+
const tickCurrentSqrtRatioX64 = tickMath_1.TickMath.getSqrtRatioAtTick(tickCurrent);
|
|
47
|
+
const nextTickSqrtRatioX64 = tickMath_1.TickMath.getSqrtRatioAtTick(tickCurrent + 1);
|
|
48
|
+
(0, tiny_invariant_1.default)(jsbi_1.default.greaterThanOrEqual(jsbi_1.default.BigInt(sqrtPriceX64), tickCurrentSqrtRatioX64) &&
|
|
49
|
+
jsbi_1.default.lessThanOrEqual(jsbi_1.default.BigInt(sqrtPriceX64), nextTickSqrtRatioX64), "PRICE_BOUNDS");
|
|
50
|
+
// always create a copy of the list since we want the pool's tick list to be immutable
|
|
51
|
+
this.id = id;
|
|
52
|
+
this.fee = fee;
|
|
53
|
+
this.sqrtPriceX64 = jsbi_1.default.BigInt(sqrtPriceX64);
|
|
54
|
+
this.liquidity = jsbi_1.default.BigInt(liquidity);
|
|
55
|
+
this.tickCurrent = tickCurrent;
|
|
56
|
+
this.feeGrowthGlobalAX64 = jsbi_1.default.BigInt(feeGrowthGlobalAX64);
|
|
57
|
+
this.feeGrowthGlobalBX64 = jsbi_1.default.BigInt(feeGrowthGlobalBX64);
|
|
58
|
+
this.tickDataProvider = Array.isArray(ticks)
|
|
59
|
+
? new tickListDataProvider_1.TickListDataProvider(ticks, internalConstants_1.TICK_SPACINGS[fee])
|
|
60
|
+
: ticks;
|
|
61
|
+
[this.tokenA, this.tokenB] = tokenA.sortsBefore(tokenB)
|
|
62
|
+
? [tokenA, tokenB]
|
|
63
|
+
: [tokenB, tokenA];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Returns true if the token is either tokenA or tokenB
|
|
67
|
+
* @param token The token to check
|
|
68
|
+
* @returns True if token is either tokenA or token
|
|
69
|
+
*/
|
|
70
|
+
involvesToken(token) {
|
|
71
|
+
return token.equals(this.tokenA) || token.equals(this.tokenB);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Returns the current mid price of the pool in terms of tokenA, i.e. the ratio of tokenB over tokenA
|
|
75
|
+
*/
|
|
76
|
+
get tokenAPrice() {
|
|
77
|
+
var _a;
|
|
78
|
+
return ((_a = this._tokenAPrice) !== null && _a !== void 0 ? _a : (this._tokenAPrice = new fractions_1.Price(this.tokenA, this.tokenB, internalConstants_2.Q128, jsbi_1.default.multiply(this.sqrtPriceX64, this.sqrtPriceX64))));
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Returns the current mid price of the pool in terms of tokenB, i.e. the ratio of tokenA over tokenB
|
|
82
|
+
*/
|
|
83
|
+
get tokenBPrice() {
|
|
84
|
+
var _a;
|
|
85
|
+
return ((_a = this._tokenBPrice) !== null && _a !== void 0 ? _a : (this._tokenBPrice = new fractions_1.Price(this.tokenB, this.tokenA, jsbi_1.default.multiply(this.sqrtPriceX64, this.sqrtPriceX64), internalConstants_2.Q128)));
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Return the price of the given token in terms of the other token in the pool.
|
|
89
|
+
* @param token The token to return price of
|
|
90
|
+
* @returns The price of the given token, in terms of the other.
|
|
91
|
+
*/
|
|
92
|
+
priceOf(token) {
|
|
93
|
+
(0, tiny_invariant_1.default)(this.involvesToken(token), "TOKEN");
|
|
94
|
+
return token.equals(this.tokenA) ? this.tokenAPrice : this.tokenBPrice;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Given an input amount of a token, return the computed output amount, and a pool with state updated after the trade
|
|
98
|
+
* @param inputAmount The input amount for which to quote the output amount
|
|
99
|
+
* @param sqrtPriceLimitX64 The Q64.96 sqrt price limit
|
|
100
|
+
* @returns The output amount and the pool with updated state
|
|
101
|
+
*/
|
|
102
|
+
getOutputAmount(inputAmount, sqrtPriceLimitX64) {
|
|
103
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
104
|
+
(0, tiny_invariant_1.default)(this.involvesToken(inputAmount.currency), "TOKEN");
|
|
105
|
+
const zeroForOne = inputAmount.currency.equals(this.tokenA);
|
|
106
|
+
const { amountCalculated: outputAmount, sqrtPriceX64, liquidity, tickCurrent, } = yield this.swap(zeroForOne, inputAmount.quotient, sqrtPriceLimitX64);
|
|
107
|
+
const outputToken = zeroForOne ? this.tokenB : this.tokenA;
|
|
108
|
+
return [
|
|
109
|
+
fractions_1.CurrencyAmount.fromRawAmount(outputToken, jsbi_1.default.multiply(outputAmount, internalConstants_2.NEGATIVE_ONE)),
|
|
110
|
+
new Pool({
|
|
111
|
+
id: this.id,
|
|
112
|
+
tokenA: this.tokenA,
|
|
113
|
+
tokenB: this.tokenB,
|
|
114
|
+
fee: this.fee,
|
|
115
|
+
sqrtPriceX64,
|
|
116
|
+
liquidity,
|
|
117
|
+
tickCurrent,
|
|
118
|
+
ticks: this.tickDataProvider,
|
|
119
|
+
feeGrowthGlobalAX64: this.feeGrowthGlobalAX64,
|
|
120
|
+
feeGrowthGlobalBX64: this.feeGrowthGlobalBX64,
|
|
121
|
+
})
|
|
122
|
+
];
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Given a desired output amount of a token, return the computed input amount and a pool with state updated after the trade
|
|
127
|
+
* @param outputAmount the output amount for which to quote the input amount
|
|
128
|
+
* @param sqrtPriceLimitX64 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
|
|
129
|
+
* @returns The input amount and the pool with updated state
|
|
130
|
+
*/
|
|
131
|
+
getInputAmount(outputAmount, sqrtPriceLimitX64) {
|
|
132
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
133
|
+
const zeroForOne = outputAmount.currency.equals(this.tokenB);
|
|
134
|
+
const { amountCalculated: inputAmount, sqrtPriceX64, liquidity, tickCurrent, } = yield this.swap(zeroForOne, jsbi_1.default.multiply(outputAmount.quotient, internalConstants_2.NEGATIVE_ONE), sqrtPriceLimitX64);
|
|
135
|
+
const inputToken = zeroForOne ? this.tokenA : this.tokenB;
|
|
136
|
+
return [
|
|
137
|
+
fractions_1.CurrencyAmount.fromRawAmount(inputToken, inputAmount),
|
|
138
|
+
new Pool({
|
|
139
|
+
id: this.id,
|
|
140
|
+
tokenA: this.tokenA,
|
|
141
|
+
tokenB: this.tokenB,
|
|
142
|
+
fee: this.fee,
|
|
143
|
+
sqrtPriceX64,
|
|
144
|
+
liquidity,
|
|
145
|
+
tickCurrent,
|
|
146
|
+
ticks: this.tickDataProvider,
|
|
147
|
+
feeGrowthGlobalAX64: this.feeGrowthGlobalAX64,
|
|
148
|
+
feeGrowthGlobalBX64: this.feeGrowthGlobalBX64,
|
|
149
|
+
}),
|
|
150
|
+
];
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Executes a swap
|
|
155
|
+
* @param zeroForOne Whether the amount in is tokenA or tokenB
|
|
156
|
+
* @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)
|
|
157
|
+
* @param sqrtPriceLimitX64 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
|
|
158
|
+
* @returns amountCalculated
|
|
159
|
+
* @returns sqrtPriceX64
|
|
160
|
+
* @returns liquidity
|
|
161
|
+
* @returns tickCurrent
|
|
162
|
+
*/
|
|
163
|
+
swap(zeroForOne, amountSpecified, sqrtPriceLimitX64) {
|
|
164
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
165
|
+
if (!sqrtPriceLimitX64)
|
|
166
|
+
sqrtPriceLimitX64 = zeroForOne
|
|
167
|
+
? jsbi_1.default.add(tickMath_1.TickMath.MIN_SQRT_RATIO, internalConstants_2.ONE)
|
|
168
|
+
: jsbi_1.default.subtract(tickMath_1.TickMath.MAX_SQRT_RATIO, internalConstants_2.ONE);
|
|
169
|
+
if (zeroForOne) {
|
|
170
|
+
(0, tiny_invariant_1.default)(jsbi_1.default.greaterThan(sqrtPriceLimitX64, tickMath_1.TickMath.MIN_SQRT_RATIO), "RATIO_MIN");
|
|
171
|
+
(0, tiny_invariant_1.default)(jsbi_1.default.lessThan(sqrtPriceLimitX64, this.sqrtPriceX64), "RATIO_CURRENT");
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
(0, tiny_invariant_1.default)(jsbi_1.default.lessThan(sqrtPriceLimitX64, tickMath_1.TickMath.MAX_SQRT_RATIO), "RATIO_MAX");
|
|
175
|
+
(0, tiny_invariant_1.default)(jsbi_1.default.greaterThan(sqrtPriceLimitX64, this.sqrtPriceX64), "RATIO_CURRENT");
|
|
176
|
+
}
|
|
177
|
+
const exactInput = jsbi_1.default.greaterThanOrEqual(amountSpecified, internalConstants_2.ZERO);
|
|
178
|
+
// keep track of swap state
|
|
179
|
+
const state = {
|
|
180
|
+
amountSpecifiedRemaining: amountSpecified,
|
|
181
|
+
amountCalculated: internalConstants_2.ZERO,
|
|
182
|
+
sqrtPriceX64: this.sqrtPriceX64,
|
|
183
|
+
tick: this.tickCurrent,
|
|
184
|
+
liquidity: this.liquidity,
|
|
185
|
+
};
|
|
186
|
+
// start swap while loop
|
|
187
|
+
while (jsbi_1.default.notEqual(state.amountSpecifiedRemaining, internalConstants_2.ZERO) &&
|
|
188
|
+
state.sqrtPriceX64 != sqrtPriceLimitX64) {
|
|
189
|
+
const step = {};
|
|
190
|
+
step.sqrtPriceStartX64 = state.sqrtPriceX64;
|
|
191
|
+
// because each iteration of the while loop rounds, we can't optimize this code (relative to the smart contract)
|
|
192
|
+
// by simply traversing to the next available tick, we instead need to exactly replicate
|
|
193
|
+
// tickBitmap.nextInitializedTickWithinOneWord
|
|
194
|
+
[step.tickNext, step.initialized] =
|
|
195
|
+
yield this.tickDataProvider.nextInitializedTickWithinOneWord(state.tick, zeroForOne, this.tickSpacing);
|
|
196
|
+
if (step.tickNext < tickMath_1.TickMath.MIN_TICK) {
|
|
197
|
+
step.tickNext = tickMath_1.TickMath.MIN_TICK;
|
|
198
|
+
}
|
|
199
|
+
else if (step.tickNext > tickMath_1.TickMath.MAX_TICK) {
|
|
200
|
+
step.tickNext = tickMath_1.TickMath.MAX_TICK;
|
|
201
|
+
}
|
|
202
|
+
step.sqrtPriceNextX64 = tickMath_1.TickMath.getSqrtRatioAtTick(step.tickNext);
|
|
203
|
+
[state.sqrtPriceX64, step.amountIn, step.amountOut, step.feeAmount] =
|
|
204
|
+
swapMath_1.SwapMath.computeSwapStep(state.sqrtPriceX64, (zeroForOne
|
|
205
|
+
? jsbi_1.default.lessThan(step.sqrtPriceNextX64, sqrtPriceLimitX64)
|
|
206
|
+
: jsbi_1.default.greaterThan(step.sqrtPriceNextX64, sqrtPriceLimitX64))
|
|
207
|
+
? sqrtPriceLimitX64
|
|
208
|
+
: step.sqrtPriceNextX64, state.liquidity, state.amountSpecifiedRemaining, this.fee);
|
|
209
|
+
if (exactInput) {
|
|
210
|
+
state.amountSpecifiedRemaining = jsbi_1.default.subtract(state.amountSpecifiedRemaining, jsbi_1.default.add(step.amountIn, step.feeAmount));
|
|
211
|
+
state.amountCalculated = jsbi_1.default.subtract(state.amountCalculated, step.amountOut);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
state.amountSpecifiedRemaining = jsbi_1.default.add(state.amountSpecifiedRemaining, step.amountOut);
|
|
215
|
+
state.amountCalculated = jsbi_1.default.add(state.amountCalculated, jsbi_1.default.add(step.amountIn, step.feeAmount));
|
|
216
|
+
}
|
|
217
|
+
// TODO
|
|
218
|
+
if (jsbi_1.default.equal(state.sqrtPriceX64, step.sqrtPriceNextX64)) {
|
|
219
|
+
// if the tick is initialized, run the tick transition
|
|
220
|
+
if (step.initialized) {
|
|
221
|
+
let liquidityNet = jsbi_1.default.BigInt((yield this.tickDataProvider.getTick(step.tickNext)).liquidityNet);
|
|
222
|
+
// if we're moving leftward, we interpret liquidityNet as the opposite sign
|
|
223
|
+
// safe because liquidityNet cannot be type(int128).min
|
|
224
|
+
if (zeroForOne)
|
|
225
|
+
liquidityNet = jsbi_1.default.multiply(liquidityNet, internalConstants_2.NEGATIVE_ONE);
|
|
226
|
+
state.liquidity = liquidityMath_1.LiquidityMath.addDelta(state.liquidity, liquidityNet);
|
|
227
|
+
}
|
|
228
|
+
state.tick = zeroForOne ? step.tickNext - 1 : step.tickNext;
|
|
229
|
+
}
|
|
230
|
+
else if (jsbi_1.default.notEqual(state.sqrtPriceX64, step.sqrtPriceStartX64)) {
|
|
231
|
+
// updated comparison function
|
|
232
|
+
// recompute unless we're on a lower tick boundary (i.e. already transitioned ticks), and haven't moved
|
|
233
|
+
state.tick = tickMath_1.TickMath.getTickAtSqrtRatio(state.sqrtPriceX64);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
amountCalculated: state.amountCalculated,
|
|
238
|
+
sqrtPriceX64: state.sqrtPriceX64,
|
|
239
|
+
liquidity: state.liquidity,
|
|
240
|
+
tickCurrent: state.tick,
|
|
241
|
+
};
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
get tickSpacing() {
|
|
245
|
+
return internalConstants_1.TICK_SPACINGS[this.fee];
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
exports.Pool = Pool;
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.Position = void 0;
|
|
16
|
+
const fractions_1 = require("./fractions");
|
|
17
|
+
const internalConstants_1 = require("../internalConstants");
|
|
18
|
+
const jsbi_1 = __importDefault(require("jsbi"));
|
|
19
|
+
const tiny_invariant_1 = __importDefault(require("tiny-invariant"));
|
|
20
|
+
const internalConstants_2 = require("../internalConstants");
|
|
21
|
+
const maxLiquidityForAmounts_1 = require("../utils/maxLiquidityForAmounts");
|
|
22
|
+
const priceTickConversions_1 = require("../utils/priceTickConversions");
|
|
23
|
+
const sqrtPriceMath_1 = require("../utils/sqrtPriceMath");
|
|
24
|
+
const tickMath_1 = require("../utils/tickMath");
|
|
25
|
+
const encodeSqrtRatioX64_1 = require("../utils/encodeSqrtRatioX64");
|
|
26
|
+
const pool_1 = require("./pool");
|
|
27
|
+
const utils_1 = require("../utils");
|
|
28
|
+
class Position {
|
|
29
|
+
/**
|
|
30
|
+
* Constructs a position for a given pool with the given liquidity
|
|
31
|
+
* @param pool For which pool the liquidity is assigned
|
|
32
|
+
* @param liquidity The amount of liquidity that is in the position
|
|
33
|
+
* @param lower The lower tick of the position
|
|
34
|
+
* @param upper The upper tick of the position
|
|
35
|
+
*/
|
|
36
|
+
constructor({ id, owner, pool, liquidity, tickLower, tickUpper, feeGrowthInsideALastX64 = 0, feeGrowthInsideBLastX64 = 0, }) {
|
|
37
|
+
// cached resuts for the getters
|
|
38
|
+
this._tokenAAmount = null;
|
|
39
|
+
this._tokenBAmount = null;
|
|
40
|
+
this._mintAmounts = null;
|
|
41
|
+
(0, tiny_invariant_1.default)(tickLower < tickUpper, "TICK_ORDER");
|
|
42
|
+
(0, tiny_invariant_1.default)(tickLower >= tickMath_1.TickMath.MIN_TICK && tickLower % pool.tickSpacing === 0, "TICK_LOWER");
|
|
43
|
+
(0, tiny_invariant_1.default)(tickUpper <= tickMath_1.TickMath.MAX_TICK && tickUpper % pool.tickSpacing === 0, "TICK_UPPER");
|
|
44
|
+
this.id = id;
|
|
45
|
+
this.owner = owner;
|
|
46
|
+
this.pool = pool;
|
|
47
|
+
this.tickLower = tickLower;
|
|
48
|
+
this.tickUpper = tickUpper;
|
|
49
|
+
this.liquidity = jsbi_1.default.BigInt(liquidity);
|
|
50
|
+
this.feeGrowthInsideALastX64 = jsbi_1.default.BigInt(feeGrowthInsideALastX64);
|
|
51
|
+
this.feeGrowthInsideBLastX64 = jsbi_1.default.BigInt(feeGrowthInsideBLastX64);
|
|
52
|
+
}
|
|
53
|
+
get inRange() {
|
|
54
|
+
return (this.tickLower < this.pool.tickCurrent &&
|
|
55
|
+
this.pool.tickCurrent < this.tickUpper);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Returns the price of tokenA at the lower tick
|
|
59
|
+
*/
|
|
60
|
+
get tokenAPriceLower() {
|
|
61
|
+
return (0, priceTickConversions_1.tickToPrice)(this.pool.tokenA, this.pool.tokenB, this.tickLower);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Returns the price of tokenA at the upper tick
|
|
65
|
+
*/
|
|
66
|
+
get tokenAPriceUpper() {
|
|
67
|
+
return (0, priceTickConversions_1.tickToPrice)(this.pool.tokenA, this.pool.tokenB, this.tickUpper);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Returns the amount of tokenA that this position's liquidity could be burned for at the current pool price
|
|
71
|
+
*/
|
|
72
|
+
get amountA() {
|
|
73
|
+
if (this._tokenAAmount === null) {
|
|
74
|
+
if (this.pool.tickCurrent < this.tickLower) {
|
|
75
|
+
this._tokenAAmount = fractions_1.CurrencyAmount.fromRawAmount(this.pool.tokenA, sqrtPriceMath_1.SqrtPriceMath.getAmountADelta(tickMath_1.TickMath.getSqrtRatioAtTick(this.tickLower), tickMath_1.TickMath.getSqrtRatioAtTick(this.tickUpper), this.liquidity, false));
|
|
76
|
+
}
|
|
77
|
+
else if (this.pool.tickCurrent < this.tickUpper) {
|
|
78
|
+
this._tokenAAmount = fractions_1.CurrencyAmount.fromRawAmount(this.pool.tokenA, sqrtPriceMath_1.SqrtPriceMath.getAmountADelta(this.pool.sqrtPriceX64, tickMath_1.TickMath.getSqrtRatioAtTick(this.tickUpper), this.liquidity, false));
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
this._tokenAAmount = fractions_1.CurrencyAmount.fromRawAmount(this.pool.tokenA, internalConstants_2.ZERO);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return this._tokenAAmount;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Returns the amount of tokenB that this position's liquidity could be burned for at the current pool price
|
|
88
|
+
*/
|
|
89
|
+
get amountB() {
|
|
90
|
+
if (this._tokenBAmount === null) {
|
|
91
|
+
if (this.pool.tickCurrent < this.tickLower) {
|
|
92
|
+
this._tokenBAmount = fractions_1.CurrencyAmount.fromRawAmount(this.pool.tokenB, internalConstants_2.ZERO);
|
|
93
|
+
}
|
|
94
|
+
else if (this.pool.tickCurrent < this.tickUpper) {
|
|
95
|
+
this._tokenBAmount = fractions_1.CurrencyAmount.fromRawAmount(this.pool.tokenB, sqrtPriceMath_1.SqrtPriceMath.getAmountBDelta(tickMath_1.TickMath.getSqrtRatioAtTick(this.tickLower), this.pool.sqrtPriceX64, this.liquidity, false));
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
this._tokenBAmount = fractions_1.CurrencyAmount.fromRawAmount(this.pool.tokenB, sqrtPriceMath_1.SqrtPriceMath.getAmountBDelta(tickMath_1.TickMath.getSqrtRatioAtTick(this.tickLower), tickMath_1.TickMath.getSqrtRatioAtTick(this.tickUpper), this.liquidity, false));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return this._tokenBAmount;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Returns the lower and upper sqrt ratios if the price 'slips' up to slippage tolerance percentage
|
|
105
|
+
* @param slippageTolerance The amount by which the price can 'slip' before the transaction will revert
|
|
106
|
+
* @returns The sqrt ratios after slippage
|
|
107
|
+
*/
|
|
108
|
+
ratiosAfterSlippage(slippageTolerance) {
|
|
109
|
+
const priceLower = this.pool.tokenAPrice.asFraction.multiply(new fractions_1.Percent(1).subtract(slippageTolerance));
|
|
110
|
+
const priceUpper = this.pool.tokenAPrice.asFraction.multiply(slippageTolerance.add(1));
|
|
111
|
+
let sqrtPriceX64Lower = (0, encodeSqrtRatioX64_1.encodeSqrtRatioX64)(priceLower.numerator, priceLower.denominator);
|
|
112
|
+
if (jsbi_1.default.lessThanOrEqual(sqrtPriceX64Lower, tickMath_1.TickMath.MIN_SQRT_RATIO)) {
|
|
113
|
+
sqrtPriceX64Lower = jsbi_1.default.add(tickMath_1.TickMath.MIN_SQRT_RATIO, jsbi_1.default.BigInt(1));
|
|
114
|
+
}
|
|
115
|
+
let sqrtPriceX64Upper = (0, encodeSqrtRatioX64_1.encodeSqrtRatioX64)(priceUpper.numerator, priceUpper.denominator);
|
|
116
|
+
if (jsbi_1.default.greaterThanOrEqual(sqrtPriceX64Upper, tickMath_1.TickMath.MAX_SQRT_RATIO)) {
|
|
117
|
+
sqrtPriceX64Upper = jsbi_1.default.subtract(tickMath_1.TickMath.MAX_SQRT_RATIO, jsbi_1.default.BigInt(1));
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
sqrtPriceX64Lower,
|
|
121
|
+
sqrtPriceX64Upper,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Returns the minimum amounts that must be sent in order to safely mint the amount of liquidity held by the position
|
|
126
|
+
* with the given slippage tolerance
|
|
127
|
+
* @param slippageTolerance Tolerance of unfavorable slippage from the current price
|
|
128
|
+
* @returns The amounts, with slippage
|
|
129
|
+
*/
|
|
130
|
+
mintAmountsWithSlippage(slippageTolerance) {
|
|
131
|
+
// get lower/upper prices
|
|
132
|
+
const { sqrtPriceX64Upper, sqrtPriceX64Lower } = this.ratiosAfterSlippage(slippageTolerance);
|
|
133
|
+
// construct counterfactual pools
|
|
134
|
+
const poolLower = new pool_1.Pool({
|
|
135
|
+
id: this.pool.id,
|
|
136
|
+
tokenA: this.pool.tokenA,
|
|
137
|
+
tokenB: this.pool.tokenB,
|
|
138
|
+
fee: this.pool.fee,
|
|
139
|
+
sqrtPriceX64: sqrtPriceX64Lower,
|
|
140
|
+
liquidity: 0 /* liquidity doesn't matter */,
|
|
141
|
+
tickCurrent: tickMath_1.TickMath.getTickAtSqrtRatio(sqrtPriceX64Lower),
|
|
142
|
+
feeGrowthGlobalAX64: this.feeGrowthInsideALastX64,
|
|
143
|
+
feeGrowthGlobalBX64: this.feeGrowthInsideBLastX64,
|
|
144
|
+
ticks: this.pool.tickDataProvider
|
|
145
|
+
});
|
|
146
|
+
const poolUpper = new pool_1.Pool({
|
|
147
|
+
id: this.pool.id,
|
|
148
|
+
tokenA: this.pool.tokenA,
|
|
149
|
+
tokenB: this.pool.tokenB,
|
|
150
|
+
fee: this.pool.fee,
|
|
151
|
+
sqrtPriceX64: sqrtPriceX64Upper,
|
|
152
|
+
liquidity: 0 /* liquidity doesn't matter */,
|
|
153
|
+
tickCurrent: tickMath_1.TickMath.getTickAtSqrtRatio(sqrtPriceX64Upper),
|
|
154
|
+
feeGrowthGlobalAX64: this.feeGrowthInsideALastX64,
|
|
155
|
+
feeGrowthGlobalBX64: this.feeGrowthInsideBLastX64,
|
|
156
|
+
ticks: this.pool.tickDataProvider
|
|
157
|
+
});
|
|
158
|
+
// because the router is imprecise, we need to calculate the position that will be created (assuming no slippage)
|
|
159
|
+
const positionThatWillBeCreated = Position.fromAmounts(Object.assign(Object.assign({ id: this.id, owner: this.owner, pool: this.pool, tickLower: this.tickLower, tickUpper: this.tickUpper }, this.mintAmounts), { useFullPrecision: false, feeGrowthInsideALastX64: this.feeGrowthInsideALastX64, feeGrowthInsideBLastX64: this.feeGrowthInsideBLastX64 }));
|
|
160
|
+
// we want the smaller amounts...
|
|
161
|
+
// ...which occurs at the upper price for amountA...
|
|
162
|
+
const { amountA } = new Position({
|
|
163
|
+
id: this.id,
|
|
164
|
+
owner: this.owner,
|
|
165
|
+
pool: poolUpper,
|
|
166
|
+
liquidity: positionThatWillBeCreated.liquidity,
|
|
167
|
+
tickLower: this.tickLower,
|
|
168
|
+
tickUpper: this.tickUpper,
|
|
169
|
+
feeGrowthInsideALastX64: this.feeGrowthInsideALastX64,
|
|
170
|
+
feeGrowthInsideBLastX64: this.feeGrowthInsideBLastX64,
|
|
171
|
+
}).mintAmounts;
|
|
172
|
+
// ...and the lower for amountB
|
|
173
|
+
const { amountB } = new Position({
|
|
174
|
+
id: this.id,
|
|
175
|
+
owner: this.owner,
|
|
176
|
+
pool: poolLower,
|
|
177
|
+
liquidity: positionThatWillBeCreated.liquidity,
|
|
178
|
+
tickLower: this.tickLower,
|
|
179
|
+
tickUpper: this.tickUpper,
|
|
180
|
+
feeGrowthInsideALastX64: this.feeGrowthInsideALastX64,
|
|
181
|
+
feeGrowthInsideBLastX64: this.feeGrowthInsideBLastX64,
|
|
182
|
+
}).mintAmounts;
|
|
183
|
+
return { amountA, amountB };
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Returns the minimum amounts that should be requested in order to safely burn the amount of liquidity held by the
|
|
187
|
+
* position with the given slippage tolerance
|
|
188
|
+
* @param slippageTolerance tolerance of unfavorable slippage from the current price
|
|
189
|
+
* @returns The amounts, with slippage
|
|
190
|
+
*/
|
|
191
|
+
burnAmountsWithSlippage(slippageTolerance) {
|
|
192
|
+
// get lower/upper prices
|
|
193
|
+
const { sqrtPriceX64Upper, sqrtPriceX64Lower } = this.ratiosAfterSlippage(slippageTolerance);
|
|
194
|
+
// construct counterfactual pools
|
|
195
|
+
const poolLower = new pool_1.Pool({
|
|
196
|
+
id: this.pool.id,
|
|
197
|
+
tokenA: this.pool.tokenA,
|
|
198
|
+
tokenB: this.pool.tokenB,
|
|
199
|
+
fee: this.pool.fee,
|
|
200
|
+
sqrtPriceX64: sqrtPriceX64Lower,
|
|
201
|
+
liquidity: 0 /* liquidity doesn't matter */,
|
|
202
|
+
tickCurrent: tickMath_1.TickMath.getTickAtSqrtRatio(sqrtPriceX64Lower),
|
|
203
|
+
feeGrowthGlobalAX64: this.feeGrowthInsideALastX64,
|
|
204
|
+
feeGrowthGlobalBX64: this.feeGrowthInsideBLastX64,
|
|
205
|
+
ticks: this.pool.tickDataProvider
|
|
206
|
+
});
|
|
207
|
+
const poolUpper = new pool_1.Pool({
|
|
208
|
+
id: this.pool.id,
|
|
209
|
+
tokenA: this.pool.tokenA,
|
|
210
|
+
tokenB: this.pool.tokenB,
|
|
211
|
+
fee: this.pool.fee,
|
|
212
|
+
sqrtPriceX64: sqrtPriceX64Upper,
|
|
213
|
+
liquidity: 0 /* liquidity doesn't matter */,
|
|
214
|
+
tickCurrent: tickMath_1.TickMath.getTickAtSqrtRatio(sqrtPriceX64Upper),
|
|
215
|
+
feeGrowthGlobalAX64: this.feeGrowthInsideALastX64,
|
|
216
|
+
feeGrowthGlobalBX64: this.feeGrowthInsideBLastX64,
|
|
217
|
+
ticks: this.pool.tickDataProvider
|
|
218
|
+
});
|
|
219
|
+
// we want the smaller amounts...
|
|
220
|
+
// ...which occurs at the upper price for amountA...
|
|
221
|
+
const amountA = new Position({
|
|
222
|
+
id: this.id,
|
|
223
|
+
owner: this.owner,
|
|
224
|
+
pool: poolUpper,
|
|
225
|
+
liquidity: this.liquidity,
|
|
226
|
+
tickLower: this.tickLower,
|
|
227
|
+
tickUpper: this.tickUpper,
|
|
228
|
+
feeGrowthInsideALastX64: this.feeGrowthInsideALastX64,
|
|
229
|
+
feeGrowthInsideBLastX64: this.feeGrowthInsideBLastX64,
|
|
230
|
+
}).amountA;
|
|
231
|
+
// ...and the lower for amountB
|
|
232
|
+
const amountB = new Position({
|
|
233
|
+
id: this.id,
|
|
234
|
+
owner: this.owner,
|
|
235
|
+
pool: poolLower,
|
|
236
|
+
liquidity: this.liquidity,
|
|
237
|
+
tickLower: this.tickLower,
|
|
238
|
+
tickUpper: this.tickUpper,
|
|
239
|
+
feeGrowthInsideALastX64: this.feeGrowthInsideALastX64,
|
|
240
|
+
feeGrowthInsideBLastX64: this.feeGrowthInsideBLastX64,
|
|
241
|
+
}).amountB;
|
|
242
|
+
return { amountA: amountA, amountB: amountB };
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Returns the minimum amounts that must be sent in order to mint the amount of liquidity held by the position at
|
|
246
|
+
* the current price for the pool
|
|
247
|
+
*/
|
|
248
|
+
get mintAmounts() {
|
|
249
|
+
if (this._mintAmounts === null) {
|
|
250
|
+
if (this.pool.tickCurrent < this.tickLower) {
|
|
251
|
+
return {
|
|
252
|
+
amountA: sqrtPriceMath_1.SqrtPriceMath.getAmountADelta(tickMath_1.TickMath.getSqrtRatioAtTick(this.tickLower), tickMath_1.TickMath.getSqrtRatioAtTick(this.tickUpper), this.liquidity, true),
|
|
253
|
+
amountB: internalConstants_2.ZERO,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
else if (this.pool.tickCurrent < this.tickUpper) {
|
|
257
|
+
return {
|
|
258
|
+
amountA: sqrtPriceMath_1.SqrtPriceMath.getAmountADelta(this.pool.sqrtPriceX64, tickMath_1.TickMath.getSqrtRatioAtTick(this.tickUpper), this.liquidity, true),
|
|
259
|
+
amountB: sqrtPriceMath_1.SqrtPriceMath.getAmountBDelta(tickMath_1.TickMath.getSqrtRatioAtTick(this.tickLower), this.pool.sqrtPriceX64, this.liquidity, true),
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
return {
|
|
264
|
+
amountA: internalConstants_2.ZERO,
|
|
265
|
+
amountB: sqrtPriceMath_1.SqrtPriceMath.getAmountBDelta(tickMath_1.TickMath.getSqrtRatioAtTick(this.tickLower), tickMath_1.TickMath.getSqrtRatioAtTick(this.tickUpper), this.liquidity, true),
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return this._mintAmounts;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Computes the maximum amount of liquidity received for a given amount of tokenA, tokenB,
|
|
273
|
+
* and the prices at the tick boundaries.
|
|
274
|
+
* @param pool The pool for which the position should be created
|
|
275
|
+
* @param lower The lower tick of the position
|
|
276
|
+
* @param upper The upper tick of the position
|
|
277
|
+
* @param amountA tokenA amount
|
|
278
|
+
* @param amountB tokenB amount
|
|
279
|
+
* @param useFullPrecision If false, liquidity will be maximized according to what the router can calculate,
|
|
280
|
+
* not what core can theoretically support
|
|
281
|
+
* @returns The amount of liquidity for the position
|
|
282
|
+
*/
|
|
283
|
+
static fromAmounts({ id, owner, pool, tickLower, tickUpper, amountA, amountB, useFullPrecision, feeGrowthInsideALastX64, feeGrowthInsideBLastX64, }) {
|
|
284
|
+
const sqrtRatioLX64 = tickMath_1.TickMath.getSqrtRatioAtTick(tickLower);
|
|
285
|
+
const sqrtRatioUX64 = tickMath_1.TickMath.getSqrtRatioAtTick(tickUpper);
|
|
286
|
+
return new Position({
|
|
287
|
+
id,
|
|
288
|
+
owner,
|
|
289
|
+
pool,
|
|
290
|
+
tickLower,
|
|
291
|
+
tickUpper,
|
|
292
|
+
liquidity: (0, maxLiquidityForAmounts_1.maxLiquidityForAmounts)(pool.sqrtPriceX64, sqrtRatioLX64, sqrtRatioUX64, amountA, amountB, useFullPrecision),
|
|
293
|
+
feeGrowthInsideALastX64,
|
|
294
|
+
feeGrowthInsideBLastX64
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Computes a position with the maximum amount of liquidity received for a given amount of tokenA, assuming an unlimited amount of tokenB
|
|
299
|
+
* @param pool The pool for which the position is created
|
|
300
|
+
* @param lower The lower tick
|
|
301
|
+
* @param upper The upper tick
|
|
302
|
+
* @param amountA The desired amount of tokenA
|
|
303
|
+
* @param useFullPrecision If true, liquidity will be maximized according to what the router can calculate,
|
|
304
|
+
* not what core can theoretically support
|
|
305
|
+
* @returns The position
|
|
306
|
+
*/
|
|
307
|
+
static fromAmountA({ id, owner, pool, tickLower, tickUpper, amountA, useFullPrecision, feeGrowthInsideALastX64, feeGrowthInsideBLastX64 }) {
|
|
308
|
+
return Position.fromAmounts({
|
|
309
|
+
id,
|
|
310
|
+
owner,
|
|
311
|
+
pool,
|
|
312
|
+
tickLower,
|
|
313
|
+
tickUpper,
|
|
314
|
+
amountA,
|
|
315
|
+
amountB: internalConstants_1.MaxUint64,
|
|
316
|
+
useFullPrecision,
|
|
317
|
+
feeGrowthInsideALastX64,
|
|
318
|
+
feeGrowthInsideBLastX64
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Computes a position with the maximum amount of liquidity received for a given amount of tokenB, assuming an unlimited amount of tokenA
|
|
323
|
+
* @param pool The pool for which the position is created
|
|
324
|
+
* @param lower The lower tick
|
|
325
|
+
* @param upper The upper tick
|
|
326
|
+
* @param amountB The desired amount of tokenB
|
|
327
|
+
* @returns The position
|
|
328
|
+
*/
|
|
329
|
+
static fromAmountB({ id, owner, pool, tickLower, tickUpper, amountB, feeGrowthInsideALastX64, feeGrowthInsideBLastX64, }) {
|
|
330
|
+
// this function always uses full precision,
|
|
331
|
+
return Position.fromAmounts({
|
|
332
|
+
id,
|
|
333
|
+
owner,
|
|
334
|
+
pool,
|
|
335
|
+
tickLower,
|
|
336
|
+
tickUpper,
|
|
337
|
+
amountA: internalConstants_1.MaxUint64,
|
|
338
|
+
amountB,
|
|
339
|
+
useFullPrecision: true,
|
|
340
|
+
feeGrowthInsideALastX64,
|
|
341
|
+
feeGrowthInsideBLastX64,
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Computes a position fees
|
|
346
|
+
* @returns The position
|
|
347
|
+
*/
|
|
348
|
+
getFees() {
|
|
349
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
350
|
+
const { liquidity, tickLower, tickUpper, feeGrowthInsideALastX64, feeGrowthInsideBLastX64, pool } = this;
|
|
351
|
+
const lower = yield this.pool.tickDataProvider.getTick(tickLower);
|
|
352
|
+
const upper = yield this.pool.tickDataProvider.getTick(tickUpper);
|
|
353
|
+
const { feeGrowthGlobalAX64, feeGrowthGlobalBX64 } = pool;
|
|
354
|
+
const [feeGrowthInsideAX64, feeGrowthInsideBX64] = utils_1.TickLibrary.getFeeGrowthInside(lower, upper, tickLower, tickUpper, pool.tickCurrent, feeGrowthGlobalAX64, feeGrowthGlobalBX64);
|
|
355
|
+
const tokensOwedA = jsbi_1.default.divide(jsbi_1.default.multiply((0, utils_1.subIn128)(feeGrowthInsideAX64, feeGrowthInsideALastX64), liquidity), internalConstants_1.Q64);
|
|
356
|
+
const tokensOwedB = jsbi_1.default.divide(jsbi_1.default.multiply((0, utils_1.subIn128)(feeGrowthInsideBX64, feeGrowthInsideBLastX64), liquidity), internalConstants_1.Q64);
|
|
357
|
+
return {
|
|
358
|
+
feesA: fractions_1.CurrencyAmount.fromRawAmount(this.pool.tokenA, tokensOwedA),
|
|
359
|
+
feesB: fractions_1.CurrencyAmount.fromRawAmount(this.pool.tokenB, tokensOwedB),
|
|
360
|
+
};
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
exports.Position = Position;
|