forked from Uniswap/v3-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmaxLiquidityForAmounts.ts
91 lines (83 loc) · 4.11 KB
/
maxLiquidityForAmounts.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
import { BigintIsh } from '@uniswap/sdk-core'
import JSBI from 'jsbi'
import { Q96 } from '../internalConstants'
/**
* Returns an imprecise maximum amount of liquidity received for a given amount of token 0.
* This function is available to accommodate LiquidityAmounts#getLiquidityForAmount0 in the v3 periphery,
* which could be more precise by at least 32 bits by dividing by Q64 instead of Q96 in the intermediate step,
* and shifting the subtracted ratio left by 32 bits. This imprecise calculation will likely be replaced in a future
* v3 router contract.
* @param sqrtRatioAX96 The price at the lower boundary
* @param sqrtRatioBX96 The price at the upper boundary
* @param amount0 The token0 amount
* @returns liquidity for amount0, imprecise
*/
function maxLiquidityForAmount0Imprecise(sqrtRatioAX96: JSBI, sqrtRatioBX96: JSBI, amount0: BigintIsh): JSBI {
if (JSBI.greaterThan(sqrtRatioAX96, sqrtRatioBX96)) {
;[sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96]
}
const intermediate = JSBI.divide(JSBI.multiply(sqrtRatioAX96, sqrtRatioBX96), Q96)
return JSBI.divide(JSBI.multiply(JSBI.BigInt(amount0), intermediate), JSBI.subtract(sqrtRatioBX96, sqrtRatioAX96))
}
/**
* Returns a precise maximum amount of liquidity received for a given amount of token 0 by dividing by Q64 instead of Q96 in the intermediate step,
* and shifting the subtracted ratio left by 32 bits.
* @param sqrtRatioAX96 The price at the lower boundary
* @param sqrtRatioBX96 The price at the upper boundary
* @param amount0 The token0 amount
* @returns liquidity for amount0, precise
*/
function maxLiquidityForAmount0Precise(sqrtRatioAX96: JSBI, sqrtRatioBX96: JSBI, amount0: BigintIsh): JSBI {
if (JSBI.greaterThan(sqrtRatioAX96, sqrtRatioBX96)) {
;[sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96]
}
const numerator = JSBI.multiply(JSBI.multiply(JSBI.BigInt(amount0), sqrtRatioAX96), sqrtRatioBX96)
const denominator = JSBI.multiply(Q96, JSBI.subtract(sqrtRatioBX96, sqrtRatioAX96))
return JSBI.divide(numerator, denominator)
}
/**
* Computes the maximum amount of liquidity received for a given amount of token1
* @param sqrtRatioAX96 The price at the lower tick boundary
* @param sqrtRatioBX96 The price at the upper tick boundary
* @param amount1 The token1 amount
* @returns liquidity for amount1
*/
function maxLiquidityForAmount1(sqrtRatioAX96: JSBI, sqrtRatioBX96: JSBI, amount1: BigintIsh): JSBI {
if (JSBI.greaterThan(sqrtRatioAX96, sqrtRatioBX96)) {
;[sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96]
}
return JSBI.divide(JSBI.multiply(JSBI.BigInt(amount1), Q96), JSBI.subtract(sqrtRatioBX96, sqrtRatioAX96))
}
/**
* Computes the maximum amount of liquidity received for a given amount of token0, token1,
* and the prices at the tick boundaries.
* @param sqrtRatioCurrentX96 the current price
* @param sqrtRatioAX96 price at lower boundary
* @param sqrtRatioBX96 price at upper boundary
* @param amount0 token0 amount
* @param amount1 token1 amount
* @param useFullPrecision if false, liquidity will be maximized according to what the router can calculate,
* not what core can theoretically support
*/
export function maxLiquidityForAmounts(
sqrtRatioCurrentX96: JSBI,
sqrtRatioAX96: JSBI,
sqrtRatioBX96: JSBI,
amount0: BigintIsh,
amount1: BigintIsh,
useFullPrecision: boolean
): JSBI {
if (JSBI.greaterThan(sqrtRatioAX96, sqrtRatioBX96)) {
;[sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96]
}
const maxLiquidityForAmount0 = useFullPrecision ? maxLiquidityForAmount0Precise : maxLiquidityForAmount0Imprecise
if (JSBI.lessThanOrEqual(sqrtRatioCurrentX96, sqrtRatioAX96)) {
return maxLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0)
} else if (JSBI.lessThan(sqrtRatioCurrentX96, sqrtRatioBX96)) {
const liquidity0 = maxLiquidityForAmount0(sqrtRatioCurrentX96, sqrtRatioBX96, amount0)
const liquidity1 = maxLiquidityForAmount1(sqrtRatioAX96, sqrtRatioCurrentX96, amount1)
return JSBI.lessThan(liquidity0, liquidity1) ? liquidity0 : liquidity1
} else {
return maxLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1)
}
}