/
decrease-liquidity-quote.ts
163 lines (143 loc) · 5.87 KB
/
decrease-liquidity-quote.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import { BN } from "@coral-xyz/anchor";
import { Percentage, ZERO } from "@orca-so/common-sdk";
import invariant from "tiny-invariant";
import { DecreaseLiquidityInput } from "../../instructions";
import {
adjustForSlippage,
getTokenAFromLiquidity,
getTokenBFromLiquidity,
PositionStatus,
PositionUtil,
} from "../../utils/position-util";
import { PriceMath, TickUtil } from "../../utils/public";
import { Position, Whirlpool } from "../../whirlpool-client";
/**
* @category Quotes
* @param liquidity - The desired liquidity to withdraw from the Whirlpool
* @param tickCurrentIndex - The Whirlpool's current tickIndex
* @param sqrtPrice - The Whirlpool's current sqrtPrice
* @param tickLowerIndex - The lower index of the position that we are withdrawing from.
* @param tickUpperIndex - The upper index of the position that we are withdrawing from.
* @param slippageTolerance - The maximum slippage allowed when calculating the minimum tokens received.
*/
export type DecreaseLiquidityQuoteParam = {
liquidity: BN;
tickCurrentIndex: number;
sqrtPrice: BN;
tickLowerIndex: number;
tickUpperIndex: number;
slippageTolerance: Percentage;
};
/**
* Return object from decrease liquidity quote functions.
* @category Quotes
*/
export type DecreaseLiquidityQuote = DecreaseLiquidityInput & { tokenEstA: BN; tokenEstB: BN };
/**
* Get an estimated quote on the minimum tokens receivable based on the desired withdraw liquidity value.
*
* @category Quotes
* @param liquidity - The desired liquidity to withdraw from the Whirlpool
* @param slippageTolerance - The maximum slippage allowed when calculating the minimum tokens received.
* @param position - A Position helper class to help interact with the Position account.
* @param whirlpool - A Whirlpool helper class to help interact with the Whirlpool account.
* @returns An DecreaseLiquidityQuote object detailing the tokenMin & liquidity values to use when calling decrease-liquidity-ix.
*/
export function decreaseLiquidityQuoteByLiquidity(
liquidity: BN,
slippageTolerance: Percentage,
position: Position,
whirlpool: Whirlpool
) {
const positionData = position.getData();
const whirlpoolData = whirlpool.getData();
invariant(
liquidity.lte(positionData.liquidity),
"Quote liquidity is more than the position liquidity."
);
return decreaseLiquidityQuoteByLiquidityWithParams({
liquidity,
slippageTolerance,
tickLowerIndex: positionData.tickLowerIndex,
tickUpperIndex: positionData.tickUpperIndex,
sqrtPrice: whirlpoolData.sqrtPrice,
tickCurrentIndex: whirlpoolData.tickCurrentIndex,
});
}
/**
* Get an estimated quote on the minimum tokens receivable based on the desired withdraw liquidity value.
*
* @category Quotes
* @param param DecreaseLiquidityQuoteParam
* @returns An DecreaseLiquidityInput object detailing the tokenMin & liquidity values to use when calling decrease-liquidity-ix.
*/
export function decreaseLiquidityQuoteByLiquidityWithParams(
param: DecreaseLiquidityQuoteParam
): DecreaseLiquidityQuote {
invariant(TickUtil.checkTickInBounds(param.tickLowerIndex), "tickLowerIndex is out of bounds.");
invariant(TickUtil.checkTickInBounds(param.tickUpperIndex), "tickUpperIndex is out of bounds.");
invariant(
TickUtil.checkTickInBounds(param.tickCurrentIndex),
"tickCurrentIndex is out of bounds."
);
const positionStatus = PositionUtil.getStrictPositionStatus(
param.sqrtPrice,
param.tickLowerIndex,
param.tickUpperIndex
);
switch (positionStatus) {
case PositionStatus.BelowRange:
return quotePositionBelowRange(param);
case PositionStatus.InRange:
return quotePositionInRange(param);
case PositionStatus.AboveRange:
return quotePositionAboveRange(param);
default:
throw new Error(`type ${positionStatus} is an unknown PositionStatus`);
}
}
function quotePositionBelowRange(param: DecreaseLiquidityQuoteParam): DecreaseLiquidityQuote {
const { tickLowerIndex, tickUpperIndex, liquidity, slippageTolerance } = param;
const sqrtPriceLowerX64 = PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex);
const sqrtPriceUpperX64 = PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex);
const tokenEstA = getTokenAFromLiquidity(liquidity, sqrtPriceLowerX64, sqrtPriceUpperX64, false);
const tokenMinA = adjustForSlippage(tokenEstA, slippageTolerance, false);
return {
tokenMinA,
tokenMinB: ZERO,
tokenEstA,
tokenEstB: ZERO,
liquidityAmount: liquidity,
};
}
function quotePositionInRange(param: DecreaseLiquidityQuoteParam): DecreaseLiquidityQuote {
const { sqrtPrice, tickLowerIndex, tickUpperIndex, liquidity, slippageTolerance } = param;
const sqrtPriceX64 = sqrtPrice;
const sqrtPriceLowerX64 = PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex);
const sqrtPriceUpperX64 = PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex);
const tokenEstA = getTokenAFromLiquidity(liquidity, sqrtPriceX64, sqrtPriceUpperX64, false);
const tokenMinA = adjustForSlippage(tokenEstA, slippageTolerance, false);
const tokenEstB = getTokenBFromLiquidity(liquidity, sqrtPriceLowerX64, sqrtPriceX64, false);
const tokenMinB = adjustForSlippage(tokenEstB, slippageTolerance, false);
return {
tokenMinA,
tokenMinB,
tokenEstA,
tokenEstB,
liquidityAmount: liquidity,
};
}
function quotePositionAboveRange(param: DecreaseLiquidityQuoteParam): DecreaseLiquidityQuote {
const { tickLowerIndex, tickUpperIndex, liquidity, slippageTolerance: slippageTolerance } = param;
const sqrtPriceLowerX64 = PriceMath.tickIndexToSqrtPriceX64(tickLowerIndex);
const sqrtPriceUpperX64 = PriceMath.tickIndexToSqrtPriceX64(tickUpperIndex);
const tokenEstB = getTokenBFromLiquidity(liquidity, sqrtPriceLowerX64, sqrtPriceUpperX64, false);
const tokenMinB = adjustForSlippage(tokenEstB, slippageTolerance, false);
return {
tokenMinA: ZERO,
tokenMinB,
tokenEstA: ZERO,
tokenEstB,
liquidityAmount: liquidity,
};
}