impermax-sdk 2.1.261 → 2.1.262
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/lib/utils/position/genericPosition.d.ts +131 -0
- package/lib/utils/position/genericPosition.js +456 -0
- package/lib/utils/position/uniswapV2/index.d.ts +8 -104
- package/lib/utils/position/uniswapV2/index.js +11 -445
- package/lib/utils/position/uniswapV3/index.d.ts +23 -111
- package/lib/utils/position/uniswapV3/index.js +22 -416
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import GenericPosition from "../genericPosition";
|
|
2
2
|
export interface UniswapV2PositionParams {
|
|
3
3
|
liquidity: number;
|
|
4
4
|
debtX: number;
|
|
@@ -11,121 +11,25 @@ export interface UniswapV2PositionParams {
|
|
|
11
11
|
availableToBorrowY?: number;
|
|
12
12
|
lockStateChange?: boolean;
|
|
13
13
|
}
|
|
14
|
-
export declare class UniswapV2Position
|
|
15
|
-
lockStateChange: boolean;
|
|
16
|
-
state: number;
|
|
17
|
-
/**
|
|
18
|
-
* NOTICE all values inside this class are normalized (no decimals or mantissa to take into account)
|
|
19
|
-
*/
|
|
20
|
-
liquidity: number;
|
|
21
|
-
debtX: number;
|
|
22
|
-
debtY: number;
|
|
23
|
-
initialLiquidity: number;
|
|
24
|
-
initialDebtX: number;
|
|
25
|
-
initialDebtY: number;
|
|
26
|
-
marketPrice: number;
|
|
27
|
-
oraclePrice: number;
|
|
28
|
-
safetyMargin: number;
|
|
29
|
-
liquidationPenalty: number;
|
|
30
|
-
availableToBorrowX: number;
|
|
31
|
-
availableToBorrowY: number;
|
|
14
|
+
export declare class UniswapV2Position extends GenericPosition {
|
|
32
15
|
constructor(params: UniswapV2PositionParams);
|
|
33
|
-
|
|
16
|
+
protected checkLock(): void;
|
|
34
17
|
/**
|
|
35
|
-
*
|
|
18
|
+
* protected SETTERS
|
|
36
19
|
*/
|
|
37
|
-
|
|
38
|
-
private setRealX;
|
|
39
|
-
private setRealY;
|
|
40
|
-
private setDebtX;
|
|
41
|
-
private setDebtY;
|
|
20
|
+
protected setLiquidity(liquidity: number): void;
|
|
42
21
|
/**
|
|
43
|
-
*
|
|
22
|
+
* protected GETTERS
|
|
44
23
|
*/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
private getRealXGivenLiquidity;
|
|
48
|
-
private getRealYGivenLiquidity;
|
|
49
|
-
private getRealXGivenPrice;
|
|
50
|
-
private getRealYGivenPrice;
|
|
51
|
-
private getRealX;
|
|
52
|
-
private getRealY;
|
|
53
|
-
private getInitialRealX;
|
|
54
|
-
private getInitialRealY;
|
|
55
|
-
private getValueGivenPriceAndAmounts;
|
|
56
|
-
private getValueGivenAmounts;
|
|
57
|
-
private getAmountXGivenValue;
|
|
58
|
-
private getAmountYGivenValue;
|
|
59
|
-
private getInitialDebtValue;
|
|
60
|
-
private getDebtValueGivenPrice;
|
|
61
|
-
private getInitialCollateralValue;
|
|
62
|
-
private getCollateralValueGivenPrice;
|
|
63
|
-
private getCollateralValueGivenPriceAndDeltaLeverage;
|
|
64
|
-
private getInitialEquityValue;
|
|
65
|
-
private getEquityValueGivenPrice;
|
|
66
|
-
private getDebtValue;
|
|
67
|
-
private getCollateralValue;
|
|
68
|
-
private getEquityValue;
|
|
69
|
-
private getLiquidityPostLiquidationValueGivenPriceAndDebt;
|
|
70
|
-
private getLiquidityPostLiquidationValueGivenPriceAndDeltaLeverage;
|
|
71
|
-
private isLiquidatableGivenPriceAndDebt;
|
|
72
|
-
private isLiquidatableGivenPriceAndDeltaLeverage;
|
|
73
|
-
private isLiquidatableGivenDebt;
|
|
74
|
-
private isLiquidatableGivenDeltaLeverage;
|
|
75
|
-
private isLiquidatableGivenPrice;
|
|
76
|
-
private isUnderwaterGivenPrice;
|
|
77
|
-
private getLiquidationPriceInRange;
|
|
78
|
-
private getMaxDeltaDebtInRange;
|
|
79
|
-
private getMaxDeltaLeverageInRange;
|
|
80
|
-
private getMinLeverageInRange;
|
|
81
|
-
/**
|
|
82
|
-
* PUBLIC SETTERS
|
|
83
|
-
*/
|
|
84
|
-
depositX(amount: number): void;
|
|
85
|
-
depositY(amount: number): void;
|
|
86
|
-
withdrawX(amount: number): void;
|
|
87
|
-
withdrawY(amount: number): void;
|
|
88
|
-
borrowX(amount: number): void;
|
|
89
|
-
borrowY(amount: number): void;
|
|
90
|
-
repayX(amount: number): void;
|
|
91
|
-
repayY(amount: number): void;
|
|
24
|
+
protected getRealXGivenLiquidityAndPrice(liquidity: number, price: number): number;
|
|
25
|
+
protected getRealYGivenLiquidityAndPrice(liquidity: number, price: number): number;
|
|
92
26
|
/**
|
|
93
27
|
* PUBLIC GETTERS
|
|
94
28
|
*/
|
|
95
|
-
getInitialDepositedX(): number;
|
|
96
|
-
getInitialDepositedY(): number;
|
|
97
|
-
getDepositedX(): number;
|
|
98
|
-
getDepositedY(): number;
|
|
99
|
-
getNetX(): number;
|
|
100
|
-
getNetY(): number;
|
|
101
|
-
isLiquidatable(): boolean;
|
|
102
|
-
isUnderwater(): boolean;
|
|
103
|
-
getLiquidationRange(): {
|
|
104
|
-
priceA: number;
|
|
105
|
-
priceB: number;
|
|
106
|
-
} | undefined;
|
|
107
|
-
getInitialLeverage(): number;
|
|
108
|
-
getLeverage(): number;
|
|
109
29
|
getOptimalLiquidity(amountX: number, amountY: number): {
|
|
110
30
|
liquidity: number;
|
|
111
31
|
amountX: number;
|
|
112
32
|
amountY: number;
|
|
113
33
|
};
|
|
114
|
-
getOptimalWithdraw(amountX: number, amountY: number, withdrawAtLeast?: boolean): {
|
|
115
|
-
amountX: number;
|
|
116
|
-
amountY: number;
|
|
117
|
-
};
|
|
118
|
-
getOptimalWithdrawForDeleverage(targetLeverage: number): {
|
|
119
|
-
amountX: number;
|
|
120
|
-
amountY: number;
|
|
121
|
-
} | null;
|
|
122
|
-
getMaxLeverage(): number;
|
|
123
|
-
getMinLeverage(): number;
|
|
124
|
-
getMaxWithdrawable(): {
|
|
125
|
-
amountX: number;
|
|
126
|
-
amountY: number;
|
|
127
|
-
};
|
|
128
|
-
getMaxBorrowableX(): number;
|
|
129
|
-
getMaxBorrowableY(): number;
|
|
130
34
|
}
|
|
131
35
|
export default UniswapV2Position;
|
|
@@ -1,30 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.UniswapV2Position = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
function getRealY(liquidity, price) {
|
|
8
|
-
return liquidity * Math.sqrt(price);
|
|
9
|
-
}
|
|
10
|
-
const LOWEST_PRICE = 1 / 1e18;
|
|
11
|
-
const HIGHEST_PRICE = 1e18;
|
|
12
|
-
class UniswapV2Position {
|
|
7
|
+
const genericPosition_1 = __importDefault(require("../genericPosition"));
|
|
8
|
+
class UniswapV2Position extends genericPosition_1.default {
|
|
13
9
|
constructor(params) {
|
|
14
|
-
|
|
15
|
-
this.debtX = params.debtX;
|
|
16
|
-
this.debtY = params.debtY;
|
|
17
|
-
this.initialLiquidity = params.liquidity;
|
|
18
|
-
this.initialDebtX = params.debtX;
|
|
19
|
-
this.initialDebtY = params.debtY;
|
|
20
|
-
this.marketPrice = params.marketPrice;
|
|
21
|
-
this.oraclePrice = params.oraclePrice;
|
|
22
|
-
this.safetyMargin = params.safetyMargin;
|
|
23
|
-
this.liquidationPenalty = params.liquidationPenalty;
|
|
24
|
-
this.availableToBorrowX = params.availableToBorrowX ?? 0;
|
|
25
|
-
this.availableToBorrowY = params.availableToBorrowY ?? 0;
|
|
26
|
-
this.lockStateChange = params.lockStateChange ?? true;
|
|
27
|
-
this.state = 0;
|
|
10
|
+
super(params);
|
|
28
11
|
}
|
|
29
12
|
checkLock() {
|
|
30
13
|
if (this.lockStateChange)
|
|
@@ -33,297 +16,23 @@ class UniswapV2Position {
|
|
|
33
16
|
this.state++;
|
|
34
17
|
}
|
|
35
18
|
/**
|
|
36
|
-
*
|
|
19
|
+
* protected SETTERS
|
|
37
20
|
*/
|
|
38
|
-
|
|
39
|
-
if (Number.isNaN(amountX))
|
|
40
|
-
return;
|
|
41
|
-
if (Number.isNaN(amountY))
|
|
42
|
-
return;
|
|
43
|
-
this.checkLock();
|
|
44
|
-
const { liquidity } = this.getOptimalLiquidity(amountX, amountY);
|
|
45
|
-
this.liquidity = liquidity;
|
|
46
|
-
}
|
|
47
|
-
setRealX(amountX) {
|
|
48
|
-
if (Number.isNaN(amountX))
|
|
49
|
-
return;
|
|
50
|
-
this.checkLock();
|
|
51
|
-
const { liquidity } = this.getOptimalLiquidity(amountX, Infinity);
|
|
52
|
-
this.liquidity = liquidity;
|
|
53
|
-
}
|
|
54
|
-
setRealY(amountY) {
|
|
55
|
-
if (Number.isNaN(amountY))
|
|
56
|
-
return;
|
|
57
|
-
this.checkLock();
|
|
58
|
-
const { liquidity } = this.getOptimalLiquidity(Infinity, amountY);
|
|
21
|
+
setLiquidity(liquidity) {
|
|
59
22
|
this.liquidity = liquidity;
|
|
60
23
|
}
|
|
61
|
-
setDebtX(_debtX) {
|
|
62
|
-
if (Number.isNaN(_debtX))
|
|
63
|
-
return;
|
|
64
|
-
this.checkLock();
|
|
65
|
-
this.debtX = _debtX;
|
|
66
|
-
}
|
|
67
|
-
setDebtY(_debtY) {
|
|
68
|
-
if (Number.isNaN(_debtY))
|
|
69
|
-
return;
|
|
70
|
-
this.checkLock();
|
|
71
|
-
this.debtY = _debtY;
|
|
72
|
-
}
|
|
73
24
|
/**
|
|
74
|
-
*
|
|
25
|
+
* protected GETTERS
|
|
75
26
|
*/
|
|
76
27
|
getRealXGivenLiquidityAndPrice(liquidity, price) {
|
|
77
|
-
return
|
|
28
|
+
return liquidity / Math.sqrt(price);
|
|
78
29
|
}
|
|
79
30
|
getRealYGivenLiquidityAndPrice(liquidity, price) {
|
|
80
|
-
return
|
|
81
|
-
}
|
|
82
|
-
getRealXGivenLiquidity(liquidity) {
|
|
83
|
-
return this.getRealXGivenLiquidityAndPrice(liquidity, this.marketPrice);
|
|
84
|
-
}
|
|
85
|
-
getRealYGivenLiquidity(liquidity) {
|
|
86
|
-
return this.getRealYGivenLiquidityAndPrice(liquidity, this.marketPrice);
|
|
87
|
-
}
|
|
88
|
-
getRealXGivenPrice(price) {
|
|
89
|
-
return this.getRealXGivenLiquidityAndPrice(this.liquidity, price);
|
|
90
|
-
}
|
|
91
|
-
getRealYGivenPrice(price) {
|
|
92
|
-
return this.getRealYGivenLiquidityAndPrice(this.liquidity, price);
|
|
93
|
-
}
|
|
94
|
-
getRealX() {
|
|
95
|
-
return this.getRealXGivenLiquidityAndPrice(this.liquidity, this.marketPrice);
|
|
96
|
-
}
|
|
97
|
-
getRealY() {
|
|
98
|
-
return this.getRealYGivenLiquidityAndPrice(this.liquidity, this.marketPrice);
|
|
99
|
-
}
|
|
100
|
-
getInitialRealX() {
|
|
101
|
-
return this.getRealXGivenLiquidityAndPrice(this.initialLiquidity, this.marketPrice);
|
|
102
|
-
}
|
|
103
|
-
getInitialRealY() {
|
|
104
|
-
return this.getRealYGivenLiquidityAndPrice(this.initialLiquidity, this.marketPrice);
|
|
105
|
-
}
|
|
106
|
-
getValueGivenPriceAndAmounts(price, amountX, amountY) {
|
|
107
|
-
return amountX * price + amountY;
|
|
108
|
-
}
|
|
109
|
-
getValueGivenAmounts(amountX, amountY) {
|
|
110
|
-
return amountX * this.marketPrice + amountY;
|
|
111
|
-
}
|
|
112
|
-
getAmountXGivenValue(value) {
|
|
113
|
-
return value / this.marketPrice;
|
|
114
|
-
}
|
|
115
|
-
getAmountYGivenValue(value) {
|
|
116
|
-
return value;
|
|
117
|
-
}
|
|
118
|
-
getInitialDebtValue() {
|
|
119
|
-
return this.getValueGivenAmounts(this.initialDebtX, this.initialDebtY);
|
|
120
|
-
}
|
|
121
|
-
getDebtValueGivenPrice(price) {
|
|
122
|
-
return this.getValueGivenPriceAndAmounts(price, this.debtX, this.debtY);
|
|
123
|
-
}
|
|
124
|
-
getInitialCollateralValue() {
|
|
125
|
-
return this.getValueGivenAmounts(this.getInitialRealX(), this.getInitialRealY());
|
|
126
|
-
}
|
|
127
|
-
getCollateralValueGivenPrice(price) {
|
|
128
|
-
return this.getValueGivenPriceAndAmounts(price, this.getRealXGivenPrice(price), this.getRealYGivenPrice(price));
|
|
129
|
-
}
|
|
130
|
-
getCollateralValueGivenPriceAndDeltaLeverage(price, deltaX, deltaY) {
|
|
131
|
-
const { liquidity } = this.getOptimalLiquidity(deltaX, deltaY);
|
|
132
|
-
return this.getValueGivenPriceAndAmounts(price, this.getRealXGivenLiquidityAndPrice(this.liquidity + liquidity, price), this.getRealYGivenLiquidityAndPrice(this.liquidity + liquidity, price));
|
|
133
|
-
}
|
|
134
|
-
getInitialEquityValue() {
|
|
135
|
-
return this.getInitialCollateralValue() - this.getInitialDebtValue();
|
|
136
|
-
}
|
|
137
|
-
getEquityValueGivenPrice(price) {
|
|
138
|
-
return this.getCollateralValueGivenPrice(price) - this.getDebtValueGivenPrice(price);
|
|
139
|
-
}
|
|
140
|
-
getDebtValue() {
|
|
141
|
-
return this.getDebtValueGivenPrice(this.marketPrice);
|
|
142
|
-
}
|
|
143
|
-
getCollateralValue() {
|
|
144
|
-
return this.getCollateralValueGivenPrice(this.marketPrice);
|
|
145
|
-
}
|
|
146
|
-
getEquityValue() {
|
|
147
|
-
return this.getEquityValueGivenPrice(this.marketPrice);
|
|
148
|
-
}
|
|
149
|
-
getLiquidityPostLiquidationValueGivenPriceAndDebt(price, debtX, debtY) {
|
|
150
|
-
const debtValue = this.getValueGivenPriceAndAmounts(price, debtX, debtY);
|
|
151
|
-
const collateralValue = this.getCollateralValueGivenPrice(price);
|
|
152
|
-
const collateralNeeded = debtValue * this.liquidationPenalty;
|
|
153
|
-
return collateralValue - collateralNeeded;
|
|
154
|
-
}
|
|
155
|
-
getLiquidityPostLiquidationValueGivenPriceAndDeltaLeverage(price, deltaX, deltaY) {
|
|
156
|
-
const debtValue = this.getDebtValueGivenPrice(price) + this.getValueGivenPriceAndAmounts(price, deltaX, deltaY);
|
|
157
|
-
const collateralValue = this.getCollateralValueGivenPriceAndDeltaLeverage(price, deltaX, deltaY);
|
|
158
|
-
const collateralNeeded = debtValue * this.liquidationPenalty;
|
|
159
|
-
return collateralValue - collateralNeeded;
|
|
160
|
-
}
|
|
161
|
-
isLiquidatableGivenPriceAndDebt(price, debtX, debtY) {
|
|
162
|
-
return this.getLiquidityPostLiquidationValueGivenPriceAndDebt(price / this.safetyMargin, debtX, debtY) < 0
|
|
163
|
-
|| this.getLiquidityPostLiquidationValueGivenPriceAndDebt(price * this.safetyMargin, debtX, debtY) < 0;
|
|
164
|
-
}
|
|
165
|
-
isLiquidatableGivenPriceAndDeltaLeverage(price, deltaX, deltaY) {
|
|
166
|
-
return this.getLiquidityPostLiquidationValueGivenPriceAndDeltaLeverage(price / this.safetyMargin, deltaX, deltaY) < 0
|
|
167
|
-
|| this.getLiquidityPostLiquidationValueGivenPriceAndDeltaLeverage(price * this.safetyMargin, deltaX, deltaY) < 0;
|
|
168
|
-
}
|
|
169
|
-
isLiquidatableGivenDebt(debtX, debtY) {
|
|
170
|
-
return this.isLiquidatableGivenPriceAndDebt(this.marketPrice, debtX, debtY);
|
|
171
|
-
}
|
|
172
|
-
isLiquidatableGivenDeltaLeverage(deltaX, deltaY) {
|
|
173
|
-
return this.isLiquidatableGivenPriceAndDeltaLeverage(this.marketPrice, deltaX, deltaY);
|
|
174
|
-
}
|
|
175
|
-
isLiquidatableGivenPrice(price) {
|
|
176
|
-
return this.isLiquidatableGivenPriceAndDebt(price, this.debtX, this.debtY);
|
|
177
|
-
}
|
|
178
|
-
isUnderwaterGivenPrice(price) {
|
|
179
|
-
return this.getLiquidityPostLiquidationValueGivenPriceAndDebt(price, this.debtX, this.debtY) < 0;
|
|
180
|
-
}
|
|
181
|
-
getLiquidationPriceInRange(lowPrice, highPrice, lowIsLiquidatable, highIsLiquidatable) {
|
|
182
|
-
if (lowIsLiquidatable == highIsLiquidatable)
|
|
183
|
-
return undefined;
|
|
184
|
-
const avgPrice = Math.sqrt(lowPrice * highPrice);
|
|
185
|
-
if (lowPrice / highPrice > 0.9999)
|
|
186
|
-
return avgPrice;
|
|
187
|
-
const avgIsLiquidatable = this.isLiquidatableGivenPrice(avgPrice);
|
|
188
|
-
return this.getLiquidationPriceInRange(lowPrice, avgPrice, lowIsLiquidatable, avgIsLiquidatable)
|
|
189
|
-
?? this.getLiquidationPriceInRange(avgPrice, highPrice, avgIsLiquidatable, highIsLiquidatable);
|
|
190
|
-
}
|
|
191
|
-
getMaxDeltaDebtInRange(lowDeltaX, lowDeltaY, highDeltaX, highDeltaY) {
|
|
192
|
-
if (Number.isNaN(lowDeltaX) || Number.isNaN(lowDeltaY) || Number.isNaN(highDeltaX) || Number.isNaN(highDeltaY))
|
|
193
|
-
return [0, 0];
|
|
194
|
-
if (highDeltaX == 0 && highDeltaY == 0)
|
|
195
|
-
return [0, 0];
|
|
196
|
-
if (Math.abs(highDeltaX / lowDeltaX) < 1.001 || Math.abs(highDeltaY / lowDeltaY) < 1.001)
|
|
197
|
-
return [lowDeltaX, lowDeltaY];
|
|
198
|
-
const avgDeltaX = (lowDeltaX + highDeltaX) / 2;
|
|
199
|
-
const avgDeltaY = (lowDeltaY + highDeltaY) / 2;
|
|
200
|
-
if (this.isLiquidatableGivenDebt(this.debtX + avgDeltaX, this.debtY + avgDeltaY))
|
|
201
|
-
return this.getMaxDeltaDebtInRange(lowDeltaX, lowDeltaY, avgDeltaX, avgDeltaY);
|
|
202
|
-
else
|
|
203
|
-
return this.getMaxDeltaDebtInRange(avgDeltaX, avgDeltaY, highDeltaX, highDeltaY);
|
|
204
|
-
}
|
|
205
|
-
getMaxDeltaLeverageInRange(lowDeltaX, lowDeltaY, highDeltaX, highDeltaY) {
|
|
206
|
-
if (Number.isNaN(lowDeltaX) || Number.isNaN(lowDeltaY) || Number.isNaN(highDeltaX) || Number.isNaN(highDeltaY))
|
|
207
|
-
return [0, 0];
|
|
208
|
-
if (highDeltaX == 0 && highDeltaY == 0)
|
|
209
|
-
return [0, 0];
|
|
210
|
-
if (Math.abs(highDeltaX / lowDeltaX) < 1.001 || Math.abs(highDeltaY / lowDeltaY) < 1.001)
|
|
211
|
-
return [lowDeltaX, lowDeltaY];
|
|
212
|
-
const avgDeltaX = (lowDeltaX + highDeltaX) / 2;
|
|
213
|
-
const avgDeltaY = (lowDeltaY + highDeltaY) / 2;
|
|
214
|
-
if (this.isLiquidatableGivenDeltaLeverage(avgDeltaX, avgDeltaY))
|
|
215
|
-
return this.getMaxDeltaLeverageInRange(lowDeltaX, lowDeltaY, avgDeltaX, avgDeltaY);
|
|
216
|
-
else
|
|
217
|
-
return this.getMaxDeltaLeverageInRange(avgDeltaX, avgDeltaY, highDeltaX, highDeltaY);
|
|
218
|
-
}
|
|
219
|
-
getMinLeverageInRange(lowLeverage, highLeverage) {
|
|
220
|
-
if (highLeverage / lowLeverage < 1.001)
|
|
221
|
-
return highLeverage;
|
|
222
|
-
const avgLeverage = (lowLeverage + highLeverage) / 2;
|
|
223
|
-
if (this.getOptimalWithdrawForDeleverage(avgLeverage) !== null)
|
|
224
|
-
return this.getMinLeverageInRange(lowLeverage, avgLeverage);
|
|
225
|
-
else
|
|
226
|
-
return this.getMinLeverageInRange(avgLeverage, highLeverage);
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* PUBLIC SETTERS
|
|
230
|
-
*/
|
|
231
|
-
depositX(amount) {
|
|
232
|
-
this.setRealX(this.getInitialRealX() + amount);
|
|
233
|
-
}
|
|
234
|
-
depositY(amount) {
|
|
235
|
-
this.setRealY(this.getInitialRealY() + amount);
|
|
236
|
-
}
|
|
237
|
-
withdrawX(amount) {
|
|
238
|
-
this.setRealX(Math.max(this.getInitialRealX() - amount, 0));
|
|
239
|
-
}
|
|
240
|
-
withdrawY(amount) {
|
|
241
|
-
this.setRealY(Math.max(this.getInitialRealY() - amount, 0));
|
|
242
|
-
}
|
|
243
|
-
borrowX(amount) {
|
|
244
|
-
if (amount > this.availableToBorrowX) {
|
|
245
|
-
throw new Error("Trying to borrow more than available liquidity");
|
|
246
|
-
}
|
|
247
|
-
else {
|
|
248
|
-
this.setDebtX(this.initialDebtX + amount);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
borrowY(amount) {
|
|
252
|
-
if (amount > this.availableToBorrowY) {
|
|
253
|
-
throw new Error("Trying to borrow more than available liquidity");
|
|
254
|
-
}
|
|
255
|
-
else {
|
|
256
|
-
this.setDebtY(this.initialDebtY + amount);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
repayX(amount) {
|
|
260
|
-
this.setDebtX(Math.max(this.initialDebtX - amount, 0));
|
|
261
|
-
}
|
|
262
|
-
repayY(amount) {
|
|
263
|
-
this.setDebtY(Math.max(this.initialDebtY - amount, 0));
|
|
31
|
+
return liquidity * Math.sqrt(price);
|
|
264
32
|
}
|
|
265
33
|
/**
|
|
266
34
|
* PUBLIC GETTERS
|
|
267
35
|
*/
|
|
268
|
-
getInitialDepositedX() {
|
|
269
|
-
return this.getInitialRealX();
|
|
270
|
-
}
|
|
271
|
-
getInitialDepositedY() {
|
|
272
|
-
return this.getInitialRealY();
|
|
273
|
-
}
|
|
274
|
-
getDepositedX() {
|
|
275
|
-
return this.getRealX();
|
|
276
|
-
}
|
|
277
|
-
getDepositedY() {
|
|
278
|
-
return this.getRealY();
|
|
279
|
-
}
|
|
280
|
-
getNetX() {
|
|
281
|
-
return this.getDepositedX() - this.debtX;
|
|
282
|
-
}
|
|
283
|
-
getNetY() {
|
|
284
|
-
return this.getDepositedY() - this.debtY;
|
|
285
|
-
}
|
|
286
|
-
isLiquidatable() {
|
|
287
|
-
return this.isLiquidatableGivenPrice(this.oraclePrice);
|
|
288
|
-
}
|
|
289
|
-
isUnderwater() {
|
|
290
|
-
return this.isUnderwaterGivenPrice(this.marketPrice);
|
|
291
|
-
}
|
|
292
|
-
getLiquidationRange() {
|
|
293
|
-
const isLiquidatable = this.isLiquidatable();
|
|
294
|
-
if (isLiquidatable)
|
|
295
|
-
return undefined;
|
|
296
|
-
if (this.marketPrice < LOWEST_PRICE || this.marketPrice > HIGHEST_PRICE)
|
|
297
|
-
return undefined;
|
|
298
|
-
const lowIsLiquidatable = this.isLiquidatableGivenPrice(LOWEST_PRICE);
|
|
299
|
-
const highIsLiquidatable = this.isLiquidatableGivenPrice(HIGHEST_PRICE);
|
|
300
|
-
const priceA = this.getLiquidationPriceInRange(LOWEST_PRICE, this.marketPrice, lowIsLiquidatable, isLiquidatable);
|
|
301
|
-
const priceB = this.getLiquidationPriceInRange(this.marketPrice, HIGHEST_PRICE, isLiquidatable, highIsLiquidatable);
|
|
302
|
-
return {
|
|
303
|
-
priceA: priceA && priceA > LOWEST_PRICE ? priceA : 0,
|
|
304
|
-
priceB: priceB && priceB < HIGHEST_PRICE ? priceB : Infinity,
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
getInitialLeverage() {
|
|
308
|
-
const leverage = this.getInitialCollateralValue() / this.getInitialEquityValue();
|
|
309
|
-
if (!leverage)
|
|
310
|
-
return 1;
|
|
311
|
-
if (Number.isNaN(leverage))
|
|
312
|
-
return 1;
|
|
313
|
-
if (leverage < 1)
|
|
314
|
-
return 1;
|
|
315
|
-
return leverage;
|
|
316
|
-
}
|
|
317
|
-
getLeverage() {
|
|
318
|
-
const leverage = this.getCollateralValue() / this.getEquityValue();
|
|
319
|
-
if (!leverage)
|
|
320
|
-
return 1;
|
|
321
|
-
if (Number.isNaN(leverage))
|
|
322
|
-
return 1;
|
|
323
|
-
if (leverage < 1)
|
|
324
|
-
return 1;
|
|
325
|
-
return leverage;
|
|
326
|
-
}
|
|
327
36
|
// amountX and amountY are expected to have the same sign
|
|
328
37
|
getOptimalLiquidity(amountX, amountY) {
|
|
329
38
|
amountX = Number.isNaN(amountX) ? 0 : amountX ?? 0;
|
|
@@ -337,149 +46,6 @@ class UniswapV2Position {
|
|
|
337
46
|
amountY: this.getRealYGivenLiquidity(liquidity),
|
|
338
47
|
};
|
|
339
48
|
}
|
|
340
|
-
getOptimalWithdraw(amountX, amountY, withdrawAtLeast = true) {
|
|
341
|
-
let percentageToRemove;
|
|
342
|
-
const percentageToRemoveX = amountX / this.getInitialDepositedX();
|
|
343
|
-
const percentageToRemoveY = amountY / this.getInitialDepositedY();
|
|
344
|
-
// Withdraw at least amountX and amountY
|
|
345
|
-
if (withdrawAtLeast)
|
|
346
|
-
percentageToRemove = Math.min(Math.max(percentageToRemoveX, percentageToRemoveY), 1);
|
|
347
|
-
// Withdraw at most amountX and amountY
|
|
348
|
-
else
|
|
349
|
-
percentageToRemove = Math.min(Math.min(percentageToRemoveX, percentageToRemoveY), 1);
|
|
350
|
-
percentageToRemove = percentageToRemove && !Number.isNaN(percentageToRemove) ? percentageToRemove : 0;
|
|
351
|
-
return {
|
|
352
|
-
amountX: this.getInitialDepositedX() * percentageToRemove,
|
|
353
|
-
amountY: this.getInitialDepositedY() * percentageToRemove,
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
getOptimalWithdrawForDeleverage(targetLeverage) {
|
|
357
|
-
// 1. If target leverage out of range
|
|
358
|
-
if (!(targetLeverage >= 1 && targetLeverage < this.getInitialLeverage())) {
|
|
359
|
-
return null;
|
|
360
|
-
}
|
|
361
|
-
// 2. If target leverage is achievable through a straight deleverage
|
|
362
|
-
const maxStraightDeleverage = this.getOptimalWithdraw(this.initialDebtX, this.initialDebtY, false);
|
|
363
|
-
const maxStraightDeleverageValue = this.getValueGivenAmounts(maxStraightDeleverage.amountX, maxStraightDeleverage.amountY);
|
|
364
|
-
const minStraightLeverage = (this.getInitialCollateralValue() - maxStraightDeleverageValue) / this.getInitialEquityValue();
|
|
365
|
-
if (targetLeverage >= minStraightLeverage) {
|
|
366
|
-
const desiredCollateralValue = targetLeverage * this.getInitialEquityValue();
|
|
367
|
-
const desiredValue = this.getInitialCollateralValue() - desiredCollateralValue;
|
|
368
|
-
const ratio = desiredValue / maxStraightDeleverageValue;
|
|
369
|
-
return {
|
|
370
|
-
amountX: maxStraightDeleverage.amountX * ratio,
|
|
371
|
-
amountY: maxStraightDeleverage.amountY * ratio,
|
|
372
|
-
};
|
|
373
|
-
}
|
|
374
|
-
// 3. Deleveraging will result in withdrawing
|
|
375
|
-
const debtValue = this.getInitialDebtValue() - maxStraightDeleverageValue;
|
|
376
|
-
const collateralValue = this.getInitialCollateralValue() - maxStraightDeleverageValue;
|
|
377
|
-
let repayRatio;
|
|
378
|
-
if (this.initialDebtX == maxStraightDeleverage.amountX) {
|
|
379
|
-
repayRatio = this.getValueGivenAmounts(0, this.getInitialDepositedY()) / this.getInitialCollateralValue();
|
|
380
|
-
}
|
|
381
|
-
else {
|
|
382
|
-
repayRatio = this.getValueGivenAmounts(this.getInitialDepositedX(), 0) / this.getInitialCollateralValue();
|
|
383
|
-
}
|
|
384
|
-
const deltaValue = (collateralValue * (targetLeverage - 1) - debtValue * targetLeverage) / (targetLeverage * (1 - repayRatio) - 1);
|
|
385
|
-
// Proof:
|
|
386
|
-
// leverage = newCollateral / (newCollateral - newDebt)
|
|
387
|
-
// newCollateral = collateral - delta
|
|
388
|
-
// newDebt = debt - delta * repayRatio;
|
|
389
|
-
// ((collateral - delta) - (debt - delta * repayRatio)) * leverage = (collateral - delta)
|
|
390
|
-
// (collateral - delta - debt + delta * repayRatio) * leverage - collateral = - delta
|
|
391
|
-
// collateral * leverage - delta * leverage - debt * leverage + delta * repayRatio * leverage - collateral = - delta
|
|
392
|
-
// collateral * leverage - debt * leverage - collateral = - delta + delta * leverage - delta * repayRatio * leverage
|
|
393
|
-
// collateral * (leverage-1) - debt * leverage = delta * (leverage - repayRatio * leverage - 1)
|
|
394
|
-
// collateral * (leverage-1) - debt * leverage = delta * (leverage * (1-repayRatio) - 1)
|
|
395
|
-
// (collateral * (leverage-1) - debt * leverage) / (leverage * (1-repayRatio) - 1) = delta
|
|
396
|
-
// 4. Return amounts if the leverage is achievable
|
|
397
|
-
if (deltaValue < 0 || deltaValue > collateralValue)
|
|
398
|
-
return null;
|
|
399
|
-
const percentageToRemove = (deltaValue + maxStraightDeleverageValue) / this.getInitialCollateralValue();
|
|
400
|
-
return {
|
|
401
|
-
amountX: this.getInitialDepositedX() * percentageToRemove,
|
|
402
|
-
amountY: this.getInitialDepositedY() * percentageToRemove,
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
getMaxLeverage() {
|
|
406
|
-
const currentLeverage = this.getLeverage();
|
|
407
|
-
if (this.isLiquidatable())
|
|
408
|
-
return currentLeverage;
|
|
409
|
-
const highLeverage = 100; // we assume the position is liquidatable with this leverage
|
|
410
|
-
let setLiquidityToZero = false;
|
|
411
|
-
if (this.liquidity === 0) {
|
|
412
|
-
this.liquidity = 0.000001;
|
|
413
|
-
setLiquidityToZero = true;
|
|
414
|
-
}
|
|
415
|
-
const realX = this.getRealX();
|
|
416
|
-
const realY = this.getRealY();
|
|
417
|
-
let maxDeltaX = realX * highLeverage / currentLeverage;
|
|
418
|
-
let maxDeltaY = realY * highLeverage / currentLeverage;
|
|
419
|
-
const actualAvailableToBorrowX = this.availableToBorrowX - (this.debtX - this.initialDebtX);
|
|
420
|
-
const actualAvailableToBorrowY = this.availableToBorrowY - (this.debtY - this.initialDebtY);
|
|
421
|
-
if (maxDeltaX > actualAvailableToBorrowX) {
|
|
422
|
-
maxDeltaY *= actualAvailableToBorrowX / maxDeltaX;
|
|
423
|
-
maxDeltaX = actualAvailableToBorrowX;
|
|
424
|
-
}
|
|
425
|
-
if (maxDeltaY > actualAvailableToBorrowY) {
|
|
426
|
-
maxDeltaX *= actualAvailableToBorrowY / maxDeltaY;
|
|
427
|
-
maxDeltaY = actualAvailableToBorrowY;
|
|
428
|
-
}
|
|
429
|
-
const [deltaX, deltaY] = this.getMaxDeltaLeverageInRange(0, 0, maxDeltaX, maxDeltaY);
|
|
430
|
-
const collateralValue = this.getCollateralValue();
|
|
431
|
-
const additionalValue = this.getValueGivenAmounts(deltaX, deltaY);
|
|
432
|
-
if (setLiquidityToZero)
|
|
433
|
-
this.liquidity = 0;
|
|
434
|
-
return (collateralValue + additionalValue) / collateralValue * currentLeverage;
|
|
435
|
-
}
|
|
436
|
-
getMinLeverage() {
|
|
437
|
-
const depositedX = this.getDepositedX();
|
|
438
|
-
const depositedY = this.getDepositedY();
|
|
439
|
-
const ratioX = this.debtX === 0 ? Infinity : depositedX / this.debtX;
|
|
440
|
-
const ratioY = this.debtY === 0 ? Infinity : depositedY / this.debtY;
|
|
441
|
-
if (ratioX >= 1 && ratioY >= 1)
|
|
442
|
-
return 0;
|
|
443
|
-
return this.getMinLeverageInRange(1, this.getInitialLeverage());
|
|
444
|
-
}
|
|
445
|
-
getMaxWithdrawable() {
|
|
446
|
-
const depositedX = this.getDepositedX();
|
|
447
|
-
const depositedY = this.getDepositedY();
|
|
448
|
-
const additionalDepositX = this.getRealX() - this.getInitialRealX();
|
|
449
|
-
const additionalDepositY = this.getRealY() - this.getInitialRealY();
|
|
450
|
-
let percentage = 0;
|
|
451
|
-
if (!this.isLiquidatable()) {
|
|
452
|
-
if (this.debtX == 0 && this.debtY == 0) {
|
|
453
|
-
percentage = 1;
|
|
454
|
-
}
|
|
455
|
-
else {
|
|
456
|
-
const highRatio = this.getEquityValue() / this.getDebtValue();
|
|
457
|
-
const [deltaDebtX, deltaDebtY] = this.getMaxDeltaDebtInRange(0, 0, this.debtX * highRatio, this.debtY * highRatio);
|
|
458
|
-
const ratio = this.debtX > 0 ? deltaDebtX / this.debtX : deltaDebtY / this.debtY;
|
|
459
|
-
percentage = 1 / (1 / ratio + 1);
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
return {
|
|
463
|
-
amountX: depositedX * percentage - additionalDepositX,
|
|
464
|
-
amountY: depositedY * percentage - additionalDepositY,
|
|
465
|
-
};
|
|
466
|
-
}
|
|
467
|
-
getMaxBorrowableX() {
|
|
468
|
-
if (this.isLiquidatable())
|
|
469
|
-
return 0;
|
|
470
|
-
const equityValue = this.getEquityValue();
|
|
471
|
-
const highDebtX = this.getAmountXGivenValue(equityValue);
|
|
472
|
-
const [debtX,] = this.getMaxDeltaDebtInRange(0, 0, highDebtX, 0);
|
|
473
|
-
return Math.min(debtX + this.debtX - this.initialDebtX, this.availableToBorrowX);
|
|
474
|
-
}
|
|
475
|
-
getMaxBorrowableY() {
|
|
476
|
-
if (this.isLiquidatable())
|
|
477
|
-
return 0;
|
|
478
|
-
const equityValue = this.getEquityValue();
|
|
479
|
-
const highDebtY = this.getAmountYGivenValue(equityValue);
|
|
480
|
-
const [, debtY] = this.getMaxDeltaDebtInRange(0, 0, 0, highDebtY);
|
|
481
|
-
return Math.min(debtY + this.debtY - this.initialDebtY, this.availableToBorrowY);
|
|
482
|
-
}
|
|
483
49
|
}
|
|
484
50
|
exports.UniswapV2Position = UniswapV2Position;
|
|
485
51
|
exports.default = UniswapV2Position;
|