impermax-sdk 2.1.214 → 2.1.216

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.
@@ -27,8 +27,8 @@ class OffchainAccountCollateralV2 extends offchainAccountPoolToken_1.default {
27
27
  return parseFloat(collateralPosition.balance);
28
28
  }
29
29
  async getLiquidity() {
30
- // todo check if growth factor works
31
30
  console.log("Offchain `getAmount`: %s", await this.getAmount());
31
+ console.log("Offchain `getGrowthFactor`: %s", await this.getCollateral().getGrowthFactor());
32
32
  return await this.getAmount() * await this.getCollateral().getGrowthFactor();
33
33
  }
34
34
  // Notice: createNewPositionObject is not needed for V2
@@ -45,6 +45,11 @@ class OffchainCollateralV2 extends offchainPoolToken_1.default {
45
45
  const reserve1 = parseFloat(lendingPoolData.pair.reserve1);
46
46
  const totalSupply = parseFloat(lendingPoolData.pair.totalSupply);
47
47
  const exchangeRate = await this.getExchangeRate();
48
+ console.log("offchain exchangeRate", exchangeRate);
49
+ console.log("offchain reserve0", reserve0);
50
+ console.log("offchain reserve1", reserve1);
51
+ console.log("offchain totalSupply", totalSupply);
52
+ console.log("offchain k", Math.sqrt(reserve0 * reserve1) / totalSupply);
48
53
  return Math.sqrt(reserve0 * reserve1) / totalSupply * exchangeRate;
49
54
  }
50
55
  //
@@ -31,9 +31,9 @@ class OnchainAccountCollateralV2 extends onchainAccountPoolToken_1.default {
31
31
  this.collateralCache = {};
32
32
  }
33
33
  async getLiquidity() {
34
- console.log("Onchain `getLiquidity`: %s", await this.getDeposited());
35
- // todo check if growth factor works
36
- return await this.getDeposited() * await this.getCollateral().getGrowthFactor();
34
+ console.log("Onchain `getTokens`: %s", await this.getTokens());
35
+ console.log("Offchain `getGrowthFactor`: %s", await this.getCollateral().getGrowthFactor());
36
+ return await this.getTokens() * await this.getCollateral().getGrowthFactor();
37
37
  }
38
38
  // Notice: createNewPositionObject is not needed for V2
39
39
  async createPositionObject(lockStateChange = false) {
@@ -6,7 +6,8 @@ export default abstract class OnchainAccountPoolToken {
6
6
  protected poolToken: OnchainPoolToken;
7
7
  protected cache: {
8
8
  availableBalance?: Promise<number>;
9
- deposited?: Promise<number>;
9
+ tokens?: Promise<number>;
10
+ amount?: Promise<number>;
10
11
  };
11
12
  getPoolToken: () => OnchainPoolToken;
12
13
  abstract getAccount(): OnchainAccount;
@@ -23,8 +24,11 @@ export default abstract class OnchainAccountPoolToken {
23
24
  private initializeAvailableBalance;
24
25
  getAvailableBalance(): Promise<number>;
25
26
  getAvailableBalanceUSD(): Promise<number>;
26
- private initializeDeposited;
27
- getDeposited(): Promise<number>;
27
+ private initializeTokens;
28
+ getTokens(): Promise<number>;
29
+ private initializeAmount;
30
+ getAmount(): Promise<number>;
31
+ getDeposited: () => Promise<number>;
28
32
  getDepositedUSD(): Promise<number>;
29
33
  getMaxWithdrawable(): Promise<number>;
30
34
  }
@@ -13,6 +13,7 @@ class OnchainAccountPoolToken {
13
13
  this.getLiquidityBuffer = () => this.getAccount().getOnchain().liquidityBuffer;
14
14
  this.getUiMargin = () => this.getAccount().getOnchain().uiMargin;
15
15
  this.getTokenPriceAccurate = async () => (await this.poolToken.getOffchainPoolToken()).getTokenPriceAccurate();
16
+ this.getDeposited = this.getAmount;
16
17
  }
17
18
  cleanCache() {
18
19
  this.cache = {};
@@ -36,17 +37,27 @@ class OnchainAccountPoolToken {
36
37
  const tokenPrice = await this.getTokenPriceAccurate();
37
38
  return availableBalance * tokenPrice;
38
39
  }
39
- // Deposited
40
- async initializeDeposited() {
40
+ // Tokens
41
+ async initializeTokens() {
41
42
  const poolToken = await this.poolToken.getPoolToken();
42
- const exchangeRate = await this.poolToken.getExchangeRate();
43
43
  const balance = await poolToken.methods.balanceOf(this.getAccountAddress()).call();
44
- return (await this.poolToken.normalize(balance)) * exchangeRate;
44
+ return (await this.poolToken.normalize(balance));
45
+ }
46
+ async getTokens() {
47
+ if (!this.cache.tokens)
48
+ this.cache.tokens = this.initializeTokens();
49
+ return this.cache.tokens;
50
+ }
51
+ // Deposited
52
+ async initializeAmount() {
53
+ const exchangeRate = await this.poolToken.getExchangeRate();
54
+ const tokens = await this.getTokens();
55
+ return (await this.poolToken.normalize(tokens)) * exchangeRate;
45
56
  }
46
- async getDeposited() {
47
- if (!this.cache.deposited)
48
- this.cache.deposited = this.initializeDeposited();
49
- return this.cache.deposited;
57
+ async getAmount() {
58
+ if (!this.cache.amount)
59
+ this.cache.amount = this.initializeAmount();
60
+ return this.cache.amount;
50
61
  }
51
62
  async getDepositedUSD() {
52
63
  const deposited = await this.getDeposited();
@@ -37,9 +37,13 @@ class OnchainCollateralV2 extends onchainPoolToken_1.default {
37
37
  async getGrowthFactor() {
38
38
  const [reserve0, reserve1] = await this.getLendingPool().getReserves();
39
39
  const totalSupply = await this.getLendingPool().getLPTotalSupply();
40
- const stakedLPExchangeRate = await this.getLendingPool().getStakedLPExchangeRate();
41
40
  const exchangeRate = await this.getExchangeRate();
42
- return Math.sqrt(reserve0 * reserve1) / totalSupply * stakedLPExchangeRate * exchangeRate;
41
+ console.log("onchain exchangeRate", exchangeRate);
42
+ console.log("onchain reserve0", reserve0);
43
+ console.log("onchain reserve1", reserve1);
44
+ console.log("onchain totalSupply", totalSupply);
45
+ console.log("onchain k", Math.sqrt(reserve0 * reserve1) / totalSupply);
46
+ return Math.sqrt(reserve0 * reserve1) / totalSupply * exchangeRate;
43
47
  }
44
48
  }
45
49
  exports.default = OnchainCollateralV2;
@@ -1,4 +1,7 @@
1
1
  import type { Position } from "../interface";
2
+ /**
3
+ * TODO: Cache for initialRealX, intialCollateralValue, etc...
4
+ */
2
5
  export declare class UniswapV3Position implements Position {
3
6
  lockStateChange: boolean;
4
7
  state: number;
@@ -106,10 +109,14 @@ export declare class UniswapV3Position implements Position {
106
109
  amountX: number;
107
110
  amountY: number;
108
111
  };
109
- getOptimalWithdraw(minAmountX: number, minAmountY: number): {
112
+ getOptimalWithdraw(amountX: number, amountY: number, withdrawAtLeast?: boolean): {
110
113
  amountX: number;
111
114
  amountY: number;
112
115
  };
116
+ getOptimalWithdrawForDeleverage(targetLeverage: number): {
117
+ amountX: number;
118
+ amountY: number;
119
+ } | null;
113
120
  getMaxLeverage(): number;
114
121
  getMinLeverage(): number;
115
122
  getMaxWithdrawable(): {
@@ -20,6 +20,9 @@ function getRealY(liquidity, price, priceA, priceB) {
20
20
  const LOWEST_PRICE = 1 / 1e18;
21
21
  const HIGHEST_PRICE = 1e18;
22
22
  const FEE_COLLECTED_WEIGHT = 0.95;
23
+ /**
24
+ * TODO: Cache for initialRealX, intialCollateralValue, etc...
25
+ */
23
26
  class UniswapV3Position {
24
27
  constructor(_liquidity, _unclaimedFeesX, _unclaimedFeesY, _debtX, _debtY, _marketPrice, _oraclePrice, _priceA, _priceB, _safetyMargin, _liquidationPenalty, _lockStateChange) {
25
28
  this.liquidity = _liquidity;
@@ -361,16 +364,60 @@ class UniswapV3Position {
361
364
  amountY: Number.isNaN(maxAmountY) ? 0 : maxAmountY ?? 0,
362
365
  };
363
366
  }
364
- getOptimalWithdraw(minAmountX, minAmountY) {
365
- const percentageToRemoveX = minAmountX / this.getInitialDepositedX();
366
- const percentageToRemoveY = minAmountY / this.getInitialDepositedY();
367
- let percentageToRemove = Math.min(Math.max(percentageToRemoveX, percentageToRemoveY), 1);
367
+ getOptimalWithdraw(amountX, amountY, withdrawAtLeast = true) {
368
+ let percentageToRemove;
369
+ const percentageToRemoveX = amountX / this.getInitialDepositedX();
370
+ const percentageToRemoveY = amountY / this.getInitialDepositedY();
371
+ // Withdraw at least amountX and amountY
372
+ if (withdrawAtLeast)
373
+ percentageToRemove = Math.min(Math.max(percentageToRemoveX, percentageToRemoveY), 1);
374
+ // Withdraw at most amountX and amountY
375
+ else
376
+ percentageToRemove = Math.min(Math.min(percentageToRemoveX, percentageToRemoveY), 1);
368
377
  percentageToRemove = percentageToRemove && !Number.isNaN(percentageToRemove) ? percentageToRemove : 0;
369
378
  return {
370
379
  amountX: this.getInitialDepositedX() * percentageToRemove,
371
380
  amountY: this.getInitialDepositedY() * percentageToRemove,
372
381
  };
373
382
  }
383
+ getOptimalWithdrawForDeleverage(targetLeverage) {
384
+ // 1. If target leverage out of range
385
+ if (!(targetLeverage >= 1 && targetLeverage < this.getInitialLeverage())) {
386
+ return null;
387
+ }
388
+ // 2. If target leverage is achievable through a straight deleverage
389
+ const maxStraightDeleverage = this.getOptimalWithdraw(this.initialDebtX, this.initialDebtY, false);
390
+ const maxStraightDeleverageValue = this.getValueGivenAmounts(maxStraightDeleverage.amountX, maxStraightDeleverage.amountY);
391
+ const minStraightLeverage = (this.getInitialCollateralValue() - maxStraightDeleverageValue) / this.getInitialEquityValue();
392
+ if (targetLeverage >= minStraightLeverage) {
393
+ const desiredCollateralValue = targetLeverage * this.getEquityValue();
394
+ const desiredValue = this.getInitialCollateralValue() - desiredCollateralValue;
395
+ const ratio = desiredValue / maxStraightDeleverageValue;
396
+ return {
397
+ amountX: maxStraightDeleverage.amountX * ratio,
398
+ amountY: maxStraightDeleverage.amountY * ratio,
399
+ };
400
+ }
401
+ // 3. Deleveraging will result in withdrawing
402
+ const debtValue = this.getInitialDebtValue() - maxStraightDeleverageValue;
403
+ const collateralValue = this.getInitialCollateralValue() - maxStraightDeleverageValue;
404
+ let repayRatio;
405
+ if (this.initialDebtX == maxStraightDeleverage.amountX) {
406
+ repayRatio = this.getValueGivenAmounts(0, this.getInitialDepositedY()) / this.getInitialCollateralValue();
407
+ }
408
+ else {
409
+ repayRatio = this.getValueGivenAmounts(this.getInitialDepositedX(), 0) / this.getInitialCollateralValue();
410
+ }
411
+ const deltaValue = (collateralValue * (targetLeverage - 1) - debtValue * targetLeverage) / (targetLeverage * (1 - repayRatio) - 1);
412
+ // 4. Return amounts if the leverage is achievable
413
+ if (deltaValue < 0 || deltaValue > collateralValue)
414
+ return null;
415
+ const percentageToRemove = (deltaValue + maxStraightDeleverageValue) / this.getInitialCollateralValue();
416
+ return {
417
+ amountX: this.getInitialDepositedX() * percentageToRemove,
418
+ amountY: this.getInitialDepositedY() * percentageToRemove,
419
+ };
420
+ }
374
421
  getMaxLeverage() {
375
422
  const currentLeverage = this.getLeverage();
376
423
  if (this.isLiquidatable())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "impermax-sdk",
3
- "version": "2.1.214",
3
+ "version": "2.1.216",
4
4
  "description": "",
5
5
  "main": "./lib/index.js",
6
6
  "module": "./lib/index.js",