impermax-sdk 2.1.149 → 2.1.151
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.
|
@@ -31,16 +31,22 @@ export declare class UniswapV3Position implements Position {
|
|
|
31
31
|
private getInitialRealY;
|
|
32
32
|
private getValueGivenPriceAndAmounts;
|
|
33
33
|
private getValueGivenAmounts;
|
|
34
|
+
private getAmountXGivenValue;
|
|
35
|
+
private getAmountYGivenValue;
|
|
34
36
|
private getDebtValueGivenPrice;
|
|
35
37
|
private getCollateralValueGivenPrice;
|
|
36
38
|
private getEquityValueGivenPrice;
|
|
37
39
|
private getDebtValue;
|
|
38
40
|
private getCollateralValue;
|
|
39
41
|
private getEquityValue;
|
|
42
|
+
private getLiquidityPostLiquidationValueGivenPriceAndDebt;
|
|
43
|
+
private isLiquidatableGivenPriceAndDebt;
|
|
44
|
+
private isLiquidatableGivenDebt;
|
|
40
45
|
private isLiquidatableGivenPrice;
|
|
41
46
|
private isUnderwaterGivenPrice;
|
|
42
47
|
private getLiquidityGivenAmounts;
|
|
43
48
|
private getLiquidationPriceInRange;
|
|
49
|
+
private getMaxDeltaDebtInRange;
|
|
44
50
|
/**
|
|
45
51
|
* PUBLIC SETTERS
|
|
46
52
|
*/
|
|
@@ -73,6 +73,12 @@ class UniswapV3Position {
|
|
|
73
73
|
getValueGivenAmounts(amountX, amountY) {
|
|
74
74
|
return amountX * this.marketPrice + amountY;
|
|
75
75
|
}
|
|
76
|
+
getAmountXGivenValue(value) {
|
|
77
|
+
return value / this.marketPrice;
|
|
78
|
+
}
|
|
79
|
+
getAmountYGivenValue(value) {
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
76
82
|
getDebtValueGivenPrice(price) {
|
|
77
83
|
return this.getValueGivenPriceAndAmounts(price, this.debtX, this.debtY);
|
|
78
84
|
}
|
|
@@ -91,11 +97,24 @@ class UniswapV3Position {
|
|
|
91
97
|
getEquityValue() {
|
|
92
98
|
return this.getEquityValueGivenPrice(this.marketPrice);
|
|
93
99
|
}
|
|
100
|
+
getLiquidityPostLiquidationValueGivenPriceAndDebt(price, debtX, debtY) {
|
|
101
|
+
const debtValue = this.getValueGivenPriceAndAmounts(price, debtX, debtY);
|
|
102
|
+
const collateralValue = this.getCollateralValueGivenPrice(price);
|
|
103
|
+
const collateralNeeded = debtValue * this.liquidationPenalty;
|
|
104
|
+
return collateralValue - collateralNeeded;
|
|
105
|
+
}
|
|
106
|
+
isLiquidatableGivenPriceAndDebt(price, debtX, debtY) {
|
|
107
|
+
return this.getLiquidityPostLiquidationValueGivenPriceAndDebt(price / this.safetyMargin, debtX, debtY) < 0
|
|
108
|
+
|| this.getLiquidityPostLiquidationValueGivenPriceAndDebt(price * this.safetyMargin, debtX, debtY) < 0;
|
|
109
|
+
}
|
|
110
|
+
isLiquidatableGivenDebt(debtX, debtY) {
|
|
111
|
+
return this.isLiquidatableGivenPriceAndDebt(this.marketPrice, debtX, debtY);
|
|
112
|
+
}
|
|
94
113
|
isLiquidatableGivenPrice(price) {
|
|
95
|
-
return this.
|
|
114
|
+
return this.isLiquidatableGivenPriceAndDebt(price, this.debtX, this.debtY);
|
|
96
115
|
}
|
|
97
116
|
isUnderwaterGivenPrice(price) {
|
|
98
|
-
return this.
|
|
117
|
+
return this.getLiquidityPostLiquidationValueGivenPriceAndDebt(price, this.debtX, this.debtY) < 0;
|
|
99
118
|
}
|
|
100
119
|
getLiquidityGivenAmounts(amountX, amountY) {
|
|
101
120
|
if (amountX == 0) {
|
|
@@ -116,6 +135,17 @@ class UniswapV3Position {
|
|
|
116
135
|
return this.getLiquidationPriceInRange(lowPrice, avgPrice, lowIsLiquidatable, avgIsLiquidatable)
|
|
117
136
|
?? this.getLiquidationPriceInRange(avgPrice, highPrice, avgIsLiquidatable, highIsLiquidatable);
|
|
118
137
|
}
|
|
138
|
+
// divide and conquer implementation
|
|
139
|
+
getMaxDeltaDebtInRange(lowDeltaX, lowDeltaY, highDeltaX, highDeltaY) {
|
|
140
|
+
if (Math.abs(highDeltaX / lowDeltaX) < 1.001 || Math.abs(highDeltaY / lowDeltaY) < 1.001)
|
|
141
|
+
return [lowDeltaX, lowDeltaY];
|
|
142
|
+
const avgDeltaX = (lowDeltaX + highDeltaX) / 2;
|
|
143
|
+
const avgDeltaY = (lowDeltaY + highDeltaY) / 2;
|
|
144
|
+
if (this.isLiquidatableGivenDebt(this.debtX + avgDeltaX, this.debtY + avgDeltaY))
|
|
145
|
+
return this.getMaxDeltaDebtInRange(lowDeltaX, lowDeltaY, avgDeltaX, avgDeltaY);
|
|
146
|
+
else
|
|
147
|
+
return this.getMaxDeltaDebtInRange(avgDeltaX, avgDeltaY, highDeltaX, highDeltaY);
|
|
148
|
+
}
|
|
119
149
|
/**
|
|
120
150
|
* PUBLIC SETTERS
|
|
121
151
|
*/
|
|
@@ -229,8 +259,21 @@ class UniswapV3Position {
|
|
|
229
259
|
return { liquidity, amountX, amountY };
|
|
230
260
|
}
|
|
231
261
|
getMaxLeverage() {
|
|
232
|
-
|
|
233
|
-
|
|
262
|
+
const currentLeverage = this.getLeverage();
|
|
263
|
+
if (this.isLiquidatable())
|
|
264
|
+
return currentLeverage;
|
|
265
|
+
const highLeverage = 100; // we assume the position is liquidatable with this leverage
|
|
266
|
+
const realX = this.getRealX();
|
|
267
|
+
const realY = this.getRealY();
|
|
268
|
+
const projectedRealX = realX * highLeverage / currentLeverage;
|
|
269
|
+
const projectedRealY = realY * highLeverage / currentLeverage;
|
|
270
|
+
const projectedDebtX = this.debtX + projectedRealX - realX;
|
|
271
|
+
const projectedDebtY = this.debtY + projectedRealY - realY;
|
|
272
|
+
const normalizedDeltaDebtX = projectedDebtX * currentLeverage / highLeverage - this.debtX;
|
|
273
|
+
const normalizedDeltaDebtY = projectedDebtY * currentLeverage / highLeverage - this.debtY;
|
|
274
|
+
const [deltaDebtX, deltaDebtY] = this.getMaxDeltaDebtInRange(0, 0, normalizedDeltaDebtX, normalizedDeltaDebtY);
|
|
275
|
+
const ratio = realX > 0 ? deltaDebtX / normalizedDeltaDebtX : deltaDebtY / normalizedDeltaDebtY;
|
|
276
|
+
return currentLeverage + (highLeverage - currentLeverage) * ratio;
|
|
234
277
|
}
|
|
235
278
|
getMinLeverage() {
|
|
236
279
|
const realX = this.getRealX();
|
|
@@ -241,17 +284,40 @@ class UniswapV3Position {
|
|
|
241
284
|
return 0;
|
|
242
285
|
}
|
|
243
286
|
getMaxWithdrawable() {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
287
|
+
const realX = this.getRealX();
|
|
288
|
+
const realY = this.getRealY();
|
|
289
|
+
let percentage = 0;
|
|
290
|
+
if (!this.isLiquidatable()) {
|
|
291
|
+
if (this.debtX == 0 && this.debtY == 0) {
|
|
292
|
+
percentage = 1;
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
const highRatio = this.getEquityValue() / this.getDebtValue();
|
|
296
|
+
const [deltaDebtX, deltaDebtY] = this.getMaxDeltaDebtInRange(0, 0, this.debtX * highRatio, this.debtY * highRatio);
|
|
297
|
+
const ratio = this.debtX > 0 ? deltaDebtX / this.debtX : deltaDebtY / this.debtY;
|
|
298
|
+
percentage = 1 / (1 / ratio + 1);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return {
|
|
302
|
+
amountX: realX * percentage,
|
|
303
|
+
amountY: realY * percentage,
|
|
304
|
+
};
|
|
247
305
|
}
|
|
248
306
|
getMaxBorrowableX() {
|
|
249
|
-
|
|
250
|
-
|
|
307
|
+
if (this.isLiquidatable())
|
|
308
|
+
return 0;
|
|
309
|
+
const equityValue = this.getEquityValue();
|
|
310
|
+
const highDebtX = this.getAmountXGivenValue(equityValue);
|
|
311
|
+
const [debtX,] = this.getMaxDeltaDebtInRange(0, 0, highDebtX, 0);
|
|
312
|
+
return debtX;
|
|
251
313
|
}
|
|
252
314
|
getMaxBorrowableY() {
|
|
253
|
-
|
|
254
|
-
|
|
315
|
+
if (this.isLiquidatable())
|
|
316
|
+
return 0;
|
|
317
|
+
const equityValue = this.getEquityValue();
|
|
318
|
+
const highDebtY = this.getAmountYGivenValue(equityValue);
|
|
319
|
+
const [, debtY] = this.getMaxDeltaDebtInRange(0, 0, 0, highDebtY);
|
|
320
|
+
return debtY;
|
|
255
321
|
}
|
|
256
322
|
}
|
|
257
323
|
exports.UniswapV3Position = UniswapV3Position;
|
package/package.json
CHANGED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
export default class UniswapV3Position {
|
|
2
|
-
lockStateChange: boolean;
|
|
3
|
-
/**
|
|
4
|
-
* NOTICE all values inside this class are normalized (no decimals or mantissa to take into account)
|
|
5
|
-
*/
|
|
6
|
-
liquidity: number;
|
|
7
|
-
debtX: number;
|
|
8
|
-
debtY: number;
|
|
9
|
-
initialLiquidity: number;
|
|
10
|
-
initialDebtX: number;
|
|
11
|
-
initialDebtY: number;
|
|
12
|
-
marketPrice: number;
|
|
13
|
-
oraclePrice: number;
|
|
14
|
-
priceA: number;
|
|
15
|
-
priceB: number;
|
|
16
|
-
safetyMargin: number;
|
|
17
|
-
liquidationPenalty: number;
|
|
18
|
-
constructor(_liquidity: number, _debtX: number, _debtY: number, _marketPrice: number, _oraclePrice: number, _priceA: number, _priceB: number, _safetyMargin: number, _liquidationPenalty: number, _lockStateChange: boolean);
|
|
19
|
-
private checkLock;
|
|
20
|
-
/**
|
|
21
|
-
* PRIVATE
|
|
22
|
-
*/
|
|
23
|
-
private getRealXGivenLiquidityAndPrice;
|
|
24
|
-
private getRealYGivenLiquidityAndPrice;
|
|
25
|
-
private getRealXGivenLiquidity;
|
|
26
|
-
private getRealYGivenLiquidity;
|
|
27
|
-
private getRealXGivenPrice;
|
|
28
|
-
private getRealYGivenPrice;
|
|
29
|
-
private getInitialRealX;
|
|
30
|
-
private getInitialRealY;
|
|
31
|
-
private getValueGivenPriceAndAmounts;
|
|
32
|
-
private getValueGivenAmounts;
|
|
33
|
-
private getAmountXGivenValue;
|
|
34
|
-
private getAmountYGivenValue;
|
|
35
|
-
private getDebtValueGivenPrice;
|
|
36
|
-
private getCollateralValueGivenPrice;
|
|
37
|
-
private getEquityValueGivenPrice;
|
|
38
|
-
private getDebtValue;
|
|
39
|
-
private getCollateralValue;
|
|
40
|
-
private getEquityValue;
|
|
41
|
-
private getLiquidityPostLiquidationValueGivenPriceAndDebt;
|
|
42
|
-
private isLiquidatableGivenPriceAndDebt;
|
|
43
|
-
private isLiquidatableGivenDebt;
|
|
44
|
-
private isLiquidatableGivenPrice;
|
|
45
|
-
private isUnderwaterGivenPrice;
|
|
46
|
-
private getLiquidityGivenAmounts;
|
|
47
|
-
private getLiquidationPriceInRange;
|
|
48
|
-
private getMaxDeltaDebtInRange;
|
|
49
|
-
/**
|
|
50
|
-
* PUBLIC SETTERS
|
|
51
|
-
*/
|
|
52
|
-
setLiquidity(_liquidity: number): void;
|
|
53
|
-
setRealXRealY(amountX: number, amountY: number): void;
|
|
54
|
-
setRealX(amountX: number): void;
|
|
55
|
-
setRealY(amountY: number): void;
|
|
56
|
-
setDebtX(_debtX: number): void;
|
|
57
|
-
setDebtY(_debtY: number): void;
|
|
58
|
-
depositX(amount: number): void;
|
|
59
|
-
depositY(amount: number): void;
|
|
60
|
-
withdrawX(amount: number): void;
|
|
61
|
-
withdrawY(amount: number): void;
|
|
62
|
-
borrowX(amount: number): void;
|
|
63
|
-
borrowY(amount: number): void;
|
|
64
|
-
repayX(amount: number): void;
|
|
65
|
-
repayY(amount: number): void;
|
|
66
|
-
/**
|
|
67
|
-
* PUBLIC GETTERS
|
|
68
|
-
*/
|
|
69
|
-
getRealX(): number;
|
|
70
|
-
getRealY(): number;
|
|
71
|
-
getNetX(): number;
|
|
72
|
-
getNetY(): number;
|
|
73
|
-
isLiquidatable(): boolean;
|
|
74
|
-
isUnderwater(): boolean;
|
|
75
|
-
getLiquidationRange(): {
|
|
76
|
-
priceA: number;
|
|
77
|
-
priceB: number;
|
|
78
|
-
} | undefined;
|
|
79
|
-
getLeverage(): number;
|
|
80
|
-
getOptimalLiquidity(amountX: number, amountY: number): {
|
|
81
|
-
liquidity: number;
|
|
82
|
-
amountX: number;
|
|
83
|
-
amountY: number;
|
|
84
|
-
};
|
|
85
|
-
getMaxLeverage(): number;
|
|
86
|
-
getMinLeverage(): number;
|
|
87
|
-
getMaxWithdrawable(): {
|
|
88
|
-
amountX: number;
|
|
89
|
-
amountY: number;
|
|
90
|
-
};
|
|
91
|
-
getMaxBorrowableX(): number;
|
|
92
|
-
getMaxBorrowableY(): number;
|
|
93
|
-
}
|
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
function getVirtualX(liquidity, price) {
|
|
4
|
-
return liquidity / Math.sqrt(price);
|
|
5
|
-
}
|
|
6
|
-
function getVirtualY(liquidity, price) {
|
|
7
|
-
return liquidity * Math.sqrt(price);
|
|
8
|
-
}
|
|
9
|
-
function getRealX(liquidity, price, priceA, priceB) {
|
|
10
|
-
const surplusX = getVirtualX(liquidity, priceB);
|
|
11
|
-
const virtualX = getVirtualX(liquidity, Math.max(price, priceA));
|
|
12
|
-
return Math.max(virtualX - surplusX, 0);
|
|
13
|
-
}
|
|
14
|
-
function getRealY(liquidity, price, priceA, priceB) {
|
|
15
|
-
const surplusY = getVirtualY(liquidity, priceA);
|
|
16
|
-
const virtualY = getVirtualY(liquidity, Math.min(price, priceB));
|
|
17
|
-
return Math.max(virtualY - surplusY, 0);
|
|
18
|
-
}
|
|
19
|
-
const LOWEST_PRICE = 1 / 1e18;
|
|
20
|
-
const HIGHEST_PRICE = 1e18;
|
|
21
|
-
class UniswapV3Position {
|
|
22
|
-
// TODO add fee logic
|
|
23
|
-
constructor(_liquidity, _debtX, _debtY, _marketPrice, _oraclePrice, _priceA, _priceB, _safetyMargin, _liquidationPenalty, _lockStateChange) {
|
|
24
|
-
this.liquidity = _liquidity;
|
|
25
|
-
this.debtX = _debtX;
|
|
26
|
-
this.debtY = _debtY;
|
|
27
|
-
this.initialLiquidity = _liquidity;
|
|
28
|
-
this.initialDebtX = _debtX;
|
|
29
|
-
this.initialDebtY = _debtY;
|
|
30
|
-
this.marketPrice = _marketPrice;
|
|
31
|
-
this.oraclePrice = _oraclePrice;
|
|
32
|
-
this.priceA = _priceA;
|
|
33
|
-
this.priceB = _priceB;
|
|
34
|
-
this.safetyMargin = _safetyMargin;
|
|
35
|
-
this.liquidationPenalty = _liquidationPenalty;
|
|
36
|
-
this.lockStateChange = _lockStateChange;
|
|
37
|
-
}
|
|
38
|
-
checkLock() {
|
|
39
|
-
if (this.lockStateChange)
|
|
40
|
-
throw Error("Can't change state of original position object");
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* PRIVATE
|
|
44
|
-
*/
|
|
45
|
-
getRealXGivenLiquidityAndPrice(liquidity, price) {
|
|
46
|
-
return getRealX(liquidity, price, this.priceA, this.priceB);
|
|
47
|
-
}
|
|
48
|
-
getRealYGivenLiquidityAndPrice(liquidity, price) {
|
|
49
|
-
return getRealY(liquidity, price, this.priceA, this.priceB);
|
|
50
|
-
}
|
|
51
|
-
getRealXGivenLiquidity(liquidity) {
|
|
52
|
-
return this.getRealXGivenLiquidityAndPrice(liquidity, this.marketPrice);
|
|
53
|
-
}
|
|
54
|
-
getRealYGivenLiquidity(liquidity) {
|
|
55
|
-
return this.getRealYGivenLiquidityAndPrice(liquidity, this.marketPrice);
|
|
56
|
-
}
|
|
57
|
-
getRealXGivenPrice(price) {
|
|
58
|
-
return this.getRealXGivenLiquidityAndPrice(this.liquidity, price);
|
|
59
|
-
}
|
|
60
|
-
getRealYGivenPrice(price) {
|
|
61
|
-
return this.getRealYGivenLiquidityAndPrice(this.liquidity, price);
|
|
62
|
-
}
|
|
63
|
-
getInitialRealX() {
|
|
64
|
-
return this.getRealXGivenLiquidityAndPrice(this.initialLiquidity, this.marketPrice);
|
|
65
|
-
}
|
|
66
|
-
getInitialRealY() {
|
|
67
|
-
return this.getRealYGivenLiquidityAndPrice(this.initialLiquidity, this.marketPrice);
|
|
68
|
-
}
|
|
69
|
-
getValueGivenPriceAndAmounts(price, amountX, amountY) {
|
|
70
|
-
return amountX * price + amountY;
|
|
71
|
-
}
|
|
72
|
-
getValueGivenAmounts(amountX, amountY) {
|
|
73
|
-
return amountX * this.marketPrice + amountY;
|
|
74
|
-
}
|
|
75
|
-
getAmountXGivenValue(value) {
|
|
76
|
-
return value / this.marketPrice;
|
|
77
|
-
}
|
|
78
|
-
getAmountYGivenValue(value) {
|
|
79
|
-
return value;
|
|
80
|
-
}
|
|
81
|
-
getDebtValueGivenPrice(price) {
|
|
82
|
-
return this.getValueGivenPriceAndAmounts(price, this.debtX, this.debtY);
|
|
83
|
-
}
|
|
84
|
-
getCollateralValueGivenPrice(price) {
|
|
85
|
-
return this.getValueGivenPriceAndAmounts(price, this.getRealXGivenPrice(price), this.getRealYGivenPrice(price));
|
|
86
|
-
}
|
|
87
|
-
getEquityValueGivenPrice(price) {
|
|
88
|
-
return this.getCollateralValueGivenPrice(price) - this.getDebtValueGivenPrice(price);
|
|
89
|
-
}
|
|
90
|
-
getDebtValue() {
|
|
91
|
-
return this.getDebtValueGivenPrice(this.marketPrice);
|
|
92
|
-
}
|
|
93
|
-
getCollateralValue() {
|
|
94
|
-
return this.getCollateralValueGivenPrice(this.marketPrice);
|
|
95
|
-
}
|
|
96
|
-
getEquityValue() {
|
|
97
|
-
return this.getEquityValueGivenPrice(this.marketPrice);
|
|
98
|
-
}
|
|
99
|
-
getLiquidityPostLiquidationValueGivenPriceAndDebt(price, debtX, debtY) {
|
|
100
|
-
const debtValue = this.getValueGivenPriceAndAmounts(price, debtX, debtY);
|
|
101
|
-
const collateralValue = this.getCollateralValueGivenPrice(price);
|
|
102
|
-
const collateralNeeded = debtValue * this.liquidationPenalty;
|
|
103
|
-
return collateralValue - collateralNeeded;
|
|
104
|
-
}
|
|
105
|
-
isLiquidatableGivenPriceAndDebt(price, debtX, debtY) {
|
|
106
|
-
return this.getLiquidityPostLiquidationValueGivenPriceAndDebt(price / this.safetyMargin, debtX, debtY) < 0
|
|
107
|
-
|| this.getLiquidityPostLiquidationValueGivenPriceAndDebt(price * this.safetyMargin, debtX, debtY) < 0;
|
|
108
|
-
}
|
|
109
|
-
isLiquidatableGivenDebt(debtX, debtY) {
|
|
110
|
-
return this.isLiquidatableGivenPriceAndDebt(this.marketPrice, debtX, debtY);
|
|
111
|
-
}
|
|
112
|
-
isLiquidatableGivenPrice(price) {
|
|
113
|
-
return this.isLiquidatableGivenPriceAndDebt(price, this.debtX, this.debtY);
|
|
114
|
-
}
|
|
115
|
-
isUnderwaterGivenPrice(price) {
|
|
116
|
-
return this.getLiquidityPostLiquidationValueGivenPriceAndDebt(price, this.debtX, this.debtY) < 0;
|
|
117
|
-
}
|
|
118
|
-
getLiquidityGivenAmounts(amountX, amountY) {
|
|
119
|
-
if (amountX == 0) {
|
|
120
|
-
return amountY / Math.sqrt(this.marketPrice);
|
|
121
|
-
}
|
|
122
|
-
if (amountY == 0) {
|
|
123
|
-
return amountX * Math.sqrt(this.marketPrice);
|
|
124
|
-
}
|
|
125
|
-
return amountX / (1 / Math.sqrt(this.marketPrice) - 1 / Math.sqrt(this.priceB));
|
|
126
|
-
}
|
|
127
|
-
// divide and conquer implementation
|
|
128
|
-
getLiquidationPriceInRange(lowPrice, highPrice, lowIsLiquidatable, highIsLiquidatable) {
|
|
129
|
-
if (lowIsLiquidatable == highIsLiquidatable)
|
|
130
|
-
return undefined;
|
|
131
|
-
const avgPrice = Math.sqrt(lowPrice * highPrice);
|
|
132
|
-
if (lowPrice / highPrice > 0.9999)
|
|
133
|
-
return avgPrice;
|
|
134
|
-
const avgIsLiquidatable = this.isLiquidatableGivenPrice(avgPrice);
|
|
135
|
-
return this.getLiquidationPriceInRange(lowPrice, avgPrice, lowIsLiquidatable, avgIsLiquidatable)
|
|
136
|
-
?? this.getLiquidationPriceInRange(avgPrice, highPrice, avgIsLiquidatable, highIsLiquidatable);
|
|
137
|
-
}
|
|
138
|
-
// divide and conquer implementation
|
|
139
|
-
getMaxDeltaDebtInRange(lowDeltaX, lowDeltaY, highDeltaX, highDeltaY) {
|
|
140
|
-
if (Math.abs(highDeltaX / lowDeltaX) < 1.001 || Math.abs(highDeltaY / lowDeltaY) < 1.001)
|
|
141
|
-
return [lowDeltaX, lowDeltaY];
|
|
142
|
-
const avgDeltaX = (lowDeltaX + highDeltaX) / 2;
|
|
143
|
-
const avgDeltaY = (lowDeltaY + highDeltaY) / 2;
|
|
144
|
-
if (this.isLiquidatableGivenDebt(this.debtX + avgDeltaX, this.debtY + avgDeltaY))
|
|
145
|
-
return this.getMaxDeltaDebtInRange(lowDeltaX, lowDeltaY, avgDeltaX, avgDeltaY);
|
|
146
|
-
else
|
|
147
|
-
return this.getMaxDeltaDebtInRange(avgDeltaX, avgDeltaY, highDeltaX, highDeltaY);
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* PUBLIC SETTERS
|
|
151
|
-
*/
|
|
152
|
-
// Setters
|
|
153
|
-
setLiquidity(_liquidity) {
|
|
154
|
-
this.checkLock();
|
|
155
|
-
this.liquidity = _liquidity;
|
|
156
|
-
}
|
|
157
|
-
setRealXRealY(amountX, amountY) {
|
|
158
|
-
this.checkLock();
|
|
159
|
-
const { liquidity } = this.getOptimalLiquidity(amountX, amountY);
|
|
160
|
-
this.liquidity = liquidity;
|
|
161
|
-
}
|
|
162
|
-
setRealX(amountX) {
|
|
163
|
-
this.checkLock();
|
|
164
|
-
const { liquidity } = this.getOptimalLiquidity(amountX, Infinity);
|
|
165
|
-
this.liquidity = liquidity;
|
|
166
|
-
}
|
|
167
|
-
setRealY(amountY) {
|
|
168
|
-
this.checkLock();
|
|
169
|
-
const { liquidity } = this.getOptimalLiquidity(Infinity, amountY);
|
|
170
|
-
this.liquidity = liquidity;
|
|
171
|
-
}
|
|
172
|
-
setDebtX(_debtX) {
|
|
173
|
-
this.checkLock();
|
|
174
|
-
this.debtX = _debtX;
|
|
175
|
-
}
|
|
176
|
-
setDebtY(_debtY) {
|
|
177
|
-
this.checkLock();
|
|
178
|
-
this.debtY = _debtY;
|
|
179
|
-
}
|
|
180
|
-
// Actions
|
|
181
|
-
depositX(amount) {
|
|
182
|
-
this.setRealX(this.getInitialRealX() + amount);
|
|
183
|
-
}
|
|
184
|
-
depositY(amount) {
|
|
185
|
-
this.setRealY(this.getInitialRealY() + amount);
|
|
186
|
-
}
|
|
187
|
-
withdrawX(amount) {
|
|
188
|
-
this.setRealX(Math.max(this.getInitialRealX() - amount, 0));
|
|
189
|
-
}
|
|
190
|
-
withdrawY(amount) {
|
|
191
|
-
this.setRealY(Math.max(this.getInitialRealY() - amount, 0));
|
|
192
|
-
}
|
|
193
|
-
borrowX(amount) {
|
|
194
|
-
this.setDebtX(this.initialDebtX + amount);
|
|
195
|
-
}
|
|
196
|
-
borrowY(amount) {
|
|
197
|
-
this.setDebtY(this.initialDebtY + amount);
|
|
198
|
-
}
|
|
199
|
-
repayX(amount) {
|
|
200
|
-
this.setDebtX(Math.max(this.initialDebtX - amount, 0));
|
|
201
|
-
}
|
|
202
|
-
repayY(amount) {
|
|
203
|
-
this.setDebtY(Math.max(this.initialDebtY - amount, 0));
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* PUBLIC GETTERS
|
|
207
|
-
*/
|
|
208
|
-
getRealX() {
|
|
209
|
-
return this.getRealXGivenLiquidityAndPrice(this.liquidity, this.marketPrice);
|
|
210
|
-
}
|
|
211
|
-
getRealY() {
|
|
212
|
-
return this.getRealYGivenLiquidityAndPrice(this.liquidity, this.marketPrice);
|
|
213
|
-
}
|
|
214
|
-
getNetX() {
|
|
215
|
-
return this.getRealX() - this.debtX;
|
|
216
|
-
}
|
|
217
|
-
getNetY() {
|
|
218
|
-
return this.getRealY() - this.debtY;
|
|
219
|
-
}
|
|
220
|
-
isLiquidatable() {
|
|
221
|
-
return this.isLiquidatableGivenPrice(this.oraclePrice);
|
|
222
|
-
}
|
|
223
|
-
isUnderwater() {
|
|
224
|
-
return this.isUnderwaterGivenPrice(this.marketPrice);
|
|
225
|
-
}
|
|
226
|
-
getLiquidationRange() {
|
|
227
|
-
const isLiquidatable = this.isLiquidatable();
|
|
228
|
-
if (isLiquidatable)
|
|
229
|
-
return undefined;
|
|
230
|
-
const lowIsLiquidatable = this.isLiquidatableGivenPrice(LOWEST_PRICE);
|
|
231
|
-
const highIsLiquidatable = this.isLiquidatableGivenPrice(HIGHEST_PRICE);
|
|
232
|
-
const priceA = this.getLiquidationPriceInRange(LOWEST_PRICE, this.marketPrice, lowIsLiquidatable, isLiquidatable);
|
|
233
|
-
const priceB = this.getLiquidationPriceInRange(this.marketPrice, HIGHEST_PRICE, isLiquidatable, highIsLiquidatable);
|
|
234
|
-
return {
|
|
235
|
-
priceA: priceA ? priceA : 0,
|
|
236
|
-
priceB: priceB ? priceB : Infinity,
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
getLeverage() {
|
|
240
|
-
return this.getCollateralValue() / this.getEquityValue();
|
|
241
|
-
}
|
|
242
|
-
// amountX and amountY are expected to have the same sign
|
|
243
|
-
getOptimalLiquidity(amountX, amountY) {
|
|
244
|
-
if (amountX != 0 && amountY != 0) {
|
|
245
|
-
const sampleX = this.getRealXGivenLiquidity(1);
|
|
246
|
-
const sampleY = this.getRealYGivenLiquidity(1);
|
|
247
|
-
if (sampleX == 0)
|
|
248
|
-
amountX = 0;
|
|
249
|
-
else if (sampleY == 0)
|
|
250
|
-
amountY = 0;
|
|
251
|
-
else {
|
|
252
|
-
if (Math.abs(amountX) / sampleX > Math.abs(amountY) / sampleY)
|
|
253
|
-
amountX = amountY / sampleY * sampleX;
|
|
254
|
-
else
|
|
255
|
-
amountY = amountX / sampleX * sampleY;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
const liquidity = this.getLiquidityGivenAmounts(amountX, amountY);
|
|
259
|
-
return { liquidity, amountX, amountY };
|
|
260
|
-
}
|
|
261
|
-
getMaxLeverage() {
|
|
262
|
-
const currentLeverage = this.getLeverage();
|
|
263
|
-
if (this.isLiquidatable())
|
|
264
|
-
return currentLeverage;
|
|
265
|
-
const highLeverage = 100; // we assume the position is liquidatable with this leverage
|
|
266
|
-
const realX = this.getRealX();
|
|
267
|
-
const realY = this.getRealY();
|
|
268
|
-
const projectedRealX = realX * highLeverage / currentLeverage;
|
|
269
|
-
const projectedRealY = realY * highLeverage / currentLeverage;
|
|
270
|
-
const projectedDebtX = this.debtX + projectedRealX - realX;
|
|
271
|
-
const projectedDebtY = this.debtY + projectedRealY - realY;
|
|
272
|
-
const normalizedDeltaDebtX = projectedDebtX * currentLeverage / highLeverage - this.debtX;
|
|
273
|
-
const normalizedDeltaDebtY = projectedDebtY * currentLeverage / highLeverage - this.debtY;
|
|
274
|
-
const [deltaDebtX, deltaDebtY] = this.getMaxDeltaDebtInRange(0, 0, normalizedDeltaDebtX, normalizedDeltaDebtY);
|
|
275
|
-
const ratio = realX > 0 ? deltaDebtX / normalizedDeltaDebtX : deltaDebtY / normalizedDeltaDebtY;
|
|
276
|
-
return currentLeverage + (highLeverage - currentLeverage) * ratio;
|
|
277
|
-
}
|
|
278
|
-
getMinLeverage() {
|
|
279
|
-
const realX = this.getRealX();
|
|
280
|
-
const realY = this.getRealY();
|
|
281
|
-
if (realX > this.debtX && realY > this.debtY)
|
|
282
|
-
return 0;
|
|
283
|
-
// TODO binary search
|
|
284
|
-
return 0;
|
|
285
|
-
}
|
|
286
|
-
getMaxWithdrawable() {
|
|
287
|
-
const realX = this.getRealX();
|
|
288
|
-
const realY = this.getRealY();
|
|
289
|
-
let percentage = 0;
|
|
290
|
-
if (!this.isLiquidatable()) {
|
|
291
|
-
if (this.debtX == 0 && this.debtY == 0) {
|
|
292
|
-
percentage = 1;
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
const highRatio = this.getEquityValue() / this.getDebtValue();
|
|
296
|
-
const [deltaDebtX, deltaDebtY] = this.getMaxDeltaDebtInRange(0, 0, this.debtX * highRatio, this.debtY * highRatio);
|
|
297
|
-
const ratio = this.debtX > 0 ? deltaDebtX / this.debtX : deltaDebtY / this.debtY;
|
|
298
|
-
percentage = 1 / (1 / ratio + 1);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
return {
|
|
302
|
-
amountX: realX * percentage,
|
|
303
|
-
amountY: realY * percentage,
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
getMaxBorrowableX() {
|
|
307
|
-
if (this.isLiquidatable())
|
|
308
|
-
return 0;
|
|
309
|
-
const equityValue = this.getEquityValue();
|
|
310
|
-
const highDebtX = this.getAmountXGivenValue(equityValue);
|
|
311
|
-
const [debtX,] = this.getMaxDeltaDebtInRange(0, 0, highDebtX, 0);
|
|
312
|
-
return debtX;
|
|
313
|
-
}
|
|
314
|
-
getMaxBorrowableY() {
|
|
315
|
-
if (this.isLiquidatable())
|
|
316
|
-
return 0;
|
|
317
|
-
const equityValue = this.getEquityValue();
|
|
318
|
-
const highDebtY = this.getAmountYGivenValue(equityValue);
|
|
319
|
-
const [, debtY] = this.getMaxDeltaDebtInRange(0, 0, 0, highDebtY);
|
|
320
|
-
return debtY;
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
exports.default = UniswapV3Position;
|