@gearbox-protocol/sdk 3.0.0-next.95 → 3.0.0-next.97
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.
|
@@ -52,6 +52,13 @@ export interface CalcAvgQuotaBorrowRateProps {
|
|
|
52
52
|
quotaRates: Record<string, Pick<QuotaInfo, "isActive" | "rate">>;
|
|
53
53
|
totalValue: bigint;
|
|
54
54
|
}
|
|
55
|
+
interface LiquidationPriceProps {
|
|
56
|
+
liquidationThresholds: Record<string, bigint>;
|
|
57
|
+
debt: bigint;
|
|
58
|
+
underlyingToken: string;
|
|
59
|
+
targetToken: string;
|
|
60
|
+
assets: Record<string, Asset>;
|
|
61
|
+
}
|
|
55
62
|
export declare class CreditAccountData {
|
|
56
63
|
readonly isSuccessful: boolean;
|
|
57
64
|
readonly addr: string;
|
|
@@ -100,5 +107,6 @@ export declare class CreditAccountData {
|
|
|
100
107
|
static calcQuotaUpdate({ quotas, initialQuotas, assetsAfterUpdate, allowedToSpend, allowedToObtain, quotaReserve, }: CalcQuotaUpdateProps): CalcQuotaUpdateReturnType;
|
|
101
108
|
static calcQuotaBorrowRate({ quotas, quotaRates }: CalcQuotaBorrowRateProps): bigint;
|
|
102
109
|
static calcRelativeBaseBorrowRate({ debt, baseRateWithFee, assetAmountInUnderlying, totalValue, }: CalcRelativeBaseBorrowRateProps): bigint;
|
|
110
|
+
static liquidationPrice({ liquidationThresholds, debt, underlyingToken, targetToken, assets, }: LiquidationPriceProps): bigint;
|
|
103
111
|
}
|
|
104
112
|
export {};
|
|
@@ -182,24 +182,26 @@ class CreditAccountData {
|
|
|
182
182
|
static calcHealthFactor({ assets, quotas, quotasInfo, liquidationThresholds, underlyingToken, debt, prices, }) {
|
|
183
183
|
const [, underlyingDecimals] = (0, sdk_gov_1.extractTokenData)(underlyingToken);
|
|
184
184
|
const underlyingPrice = prices[underlyingToken] || 0n;
|
|
185
|
-
const
|
|
185
|
+
const assetMoney = assets.reduce((acc, { token: tokenAddress, balance: amount }) => {
|
|
186
186
|
const [, tokenDecimals] = (0, sdk_gov_1.extractTokenData)(tokenAddress);
|
|
187
187
|
const lt = liquidationThresholds[tokenAddress] || 0n;
|
|
188
188
|
const price = prices[tokenAddress] || 0n;
|
|
189
189
|
const tokenMoney = price_1.PriceUtils.calcTotalPrice(price, amount, tokenDecimals);
|
|
190
|
+
const tokenLtMoney = (tokenMoney * lt) / sdk_gov_1.PERCENTAGE_FACTOR;
|
|
190
191
|
const { isActive = false } = quotasInfo?.[tokenAddress] || {};
|
|
191
192
|
const quota = quotas[tokenAddress];
|
|
192
193
|
const quotaBalance = isActive ? quota?.balance || 0n : 0n;
|
|
193
194
|
const quotaMoney = price_1.PriceUtils.calcTotalPrice(underlyingPrice, quotaBalance, underlyingDecimals);
|
|
194
195
|
// if quota is undefined, then it is not a quoted token
|
|
195
196
|
const money = quota
|
|
196
|
-
? math_1.BigIntMath.min(quotaMoney,
|
|
197
|
-
:
|
|
198
|
-
|
|
199
|
-
return acc + ltMoney;
|
|
197
|
+
? math_1.BigIntMath.min(quotaMoney, tokenLtMoney)
|
|
198
|
+
: tokenLtMoney;
|
|
199
|
+
return acc + money;
|
|
200
200
|
}, 0n);
|
|
201
201
|
const borrowedMoney = price_1.PriceUtils.calcTotalPrice(underlyingPrice || sdk_gov_1.PRICE_DECIMALS, debt, underlyingDecimals);
|
|
202
|
-
const hfInPercent = borrowedMoney > 0n
|
|
202
|
+
const hfInPercent = borrowedMoney > 0n
|
|
203
|
+
? (assetMoney * sdk_gov_1.PERCENTAGE_FACTOR) / borrowedMoney
|
|
204
|
+
: 0n;
|
|
203
205
|
return Number(hfInPercent);
|
|
204
206
|
}
|
|
205
207
|
static calcQuotaUpdate({ quotas, initialQuotas, assetsAfterUpdate, allowedToSpend, allowedToObtain, quotaReserve, }) {
|
|
@@ -262,5 +264,21 @@ class CreditAccountData {
|
|
|
262
264
|
return 0n;
|
|
263
265
|
return ((debt * BigInt(baseRateWithFee) * assetAmountInUnderlying) / totalValue);
|
|
264
266
|
}
|
|
267
|
+
static liquidationPrice({ liquidationThresholds, debt, underlyingToken, targetToken, assets, }) {
|
|
268
|
+
const underlyingTokenLC = underlyingToken.toLowerCase();
|
|
269
|
+
const [, underlyingDecimals = 18] = (0, sdk_gov_1.extractTokenData)(underlyingTokenLC);
|
|
270
|
+
const { balance: underlyingBalance = 0n } = assets[underlyingTokenLC] || {};
|
|
271
|
+
const effectiveDebt = ((debt - underlyingBalance) * sdk_gov_1.WAD) / 10n ** BigInt(underlyingDecimals);
|
|
272
|
+
const targetTokenLC = targetToken.toLowerCase();
|
|
273
|
+
const [, targetDecimals = 18] = (0, sdk_gov_1.extractTokenData)(targetTokenLC);
|
|
274
|
+
const { balance: targetBalance = 0n } = assets[targetTokenLC] || {};
|
|
275
|
+
const effectiveTargetBalance = (targetBalance * sdk_gov_1.WAD) / 10n ** BigInt(targetDecimals);
|
|
276
|
+
const lpLT = liquidationThresholds[targetTokenLC] || 0n;
|
|
277
|
+
if (targetBalance <= 0n || lpLT <= 0n)
|
|
278
|
+
return 0n;
|
|
279
|
+
return ((effectiveDebt * sdk_gov_1.PRICE_DECIMALS * sdk_gov_1.PERCENTAGE_FACTOR) /
|
|
280
|
+
effectiveTargetBalance /
|
|
281
|
+
lpLT);
|
|
282
|
+
}
|
|
265
283
|
}
|
|
266
284
|
exports.CreditAccountData = CreditAccountData;
|
package/lib/core/strategy.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Asset } from "./assets";
|
|
2
1
|
import { CreditManagerData } from "./creditManager";
|
|
3
2
|
export interface StrategyPayload {
|
|
4
3
|
apy?: number;
|
|
@@ -9,14 +8,6 @@ export interface StrategyPayload {
|
|
|
9
8
|
unleveragableCollateral: Array<string>;
|
|
10
9
|
leveragableCollateral: Array<string>;
|
|
11
10
|
}
|
|
12
|
-
interface LiquidationPriceProps {
|
|
13
|
-
prices: Record<string, bigint>;
|
|
14
|
-
liquidationThresholds: Record<string, bigint>;
|
|
15
|
-
debt: bigint;
|
|
16
|
-
underlyingToken: string;
|
|
17
|
-
targetToken: string;
|
|
18
|
-
assets: Record<string, Asset>;
|
|
19
|
-
}
|
|
20
11
|
interface CalculateMaxAPYProps {
|
|
21
12
|
apy: number;
|
|
22
13
|
leverage: number;
|
|
@@ -34,7 +25,6 @@ export declare class Strategy {
|
|
|
34
25
|
constructor(payload: StrategyPayload);
|
|
35
26
|
static maxLeverage(lpToken: string, cms: Array<PartialCM>): number;
|
|
36
27
|
static maxAPY({ apy, leverage, baseRateWithFee, quotaRateWithFee, }: CalculateMaxAPYProps): number;
|
|
37
|
-
static liquidationPrice({ prices, liquidationThresholds, debt, underlyingToken, targetToken, assets, }: LiquidationPriceProps): bigint;
|
|
38
28
|
protected static maxLeverageThreshold(lpToken: string, cms: Array<PartialCM>): readonly [bigint, string];
|
|
39
29
|
}
|
|
40
30
|
type PartialCM = Pick<CreditManagerData, "liquidationThresholds" | "address">;
|
package/lib/core/strategy.js
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Strategy = void 0;
|
|
4
4
|
const sdk_gov_1 = require("@gearbox-protocol/sdk-gov");
|
|
5
|
-
const math_1 = require("../utils/math");
|
|
6
|
-
const price_1 = require("../utils/price");
|
|
7
5
|
class Strategy {
|
|
8
6
|
apy;
|
|
9
7
|
name;
|
|
@@ -34,21 +32,6 @@ class Strategy {
|
|
|
34
32
|
Number(sdk_gov_1.LEVERAGE_DECIMALS);
|
|
35
33
|
return collateralTerm + Math.floor(debtTerm);
|
|
36
34
|
}
|
|
37
|
-
static liquidationPrice({ prices, liquidationThresholds, debt, underlyingToken, targetToken, assets, }) {
|
|
38
|
-
const underlyingTokenLC = underlyingToken.toLowerCase();
|
|
39
|
-
const [, underlyingDecimals = 18] = (0, sdk_gov_1.extractTokenData)(underlyingTokenLC);
|
|
40
|
-
const { balance: underlyingBalance = 0n } = assets[underlyingTokenLC] || {};
|
|
41
|
-
const underlyingPrice = prices[underlyingTokenLC] || sdk_gov_1.PRICE_DECIMALS;
|
|
42
|
-
const borrowedMoney = price_1.PriceUtils.calcTotalPrice(underlyingPrice, math_1.BigIntMath.max(0n, debt - underlyingBalance), underlyingDecimals);
|
|
43
|
-
const targetTokenLC = targetToken.toLowerCase();
|
|
44
|
-
const [, targetDecimals = 18] = (0, sdk_gov_1.extractTokenData)(targetTokenLC);
|
|
45
|
-
const { balance: targetBalance = 0n } = assets[targetTokenLC] || {};
|
|
46
|
-
const lpLT = liquidationThresholds[targetTokenLC] || 0n;
|
|
47
|
-
const lpPrice = prices[targetTokenLC] || sdk_gov_1.PRICE_DECIMALS;
|
|
48
|
-
const lpMoney = price_1.PriceUtils.calcTotalPrice(lpPrice, targetBalance, targetDecimals);
|
|
49
|
-
const lpLTMoney = (lpMoney * lpLT) / sdk_gov_1.PERCENTAGE_FACTOR;
|
|
50
|
-
return lpLTMoney > 0n ? (borrowedMoney * sdk_gov_1.WAD) / lpLTMoney : 0n;
|
|
51
|
-
}
|
|
52
35
|
static maxLeverageThreshold(lpToken, cms) {
|
|
53
36
|
const lpTokenLC = lpToken.toLowerCase();
|
|
54
37
|
const ltByCM = cms.map(cm => {
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const sdk_gov_1 = require("@gearbox-protocol/sdk-gov");
|
|
4
|
-
const chai_1 = require("chai");
|
|
5
|
-
const formatter_1 = require("../utils/formatter");
|
|
6
|
-
const strategy_1 = require("./strategy");
|
|
7
|
-
const pools = {
|
|
8
|
-
"0x1": {
|
|
9
|
-
borrowRate: 27543,
|
|
10
|
-
},
|
|
11
|
-
"0x2": {
|
|
12
|
-
borrowRate: 5736,
|
|
13
|
-
},
|
|
14
|
-
};
|
|
15
|
-
const prices = {
|
|
16
|
-
[sdk_gov_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase()]: (0, formatter_1.toBN)("1738.11830000", sdk_gov_1.PRICE_DECIMALS_POW),
|
|
17
|
-
[sdk_gov_1.tokenDataByNetwork.Mainnet.DAI.toLowerCase()]: (0, formatter_1.toBN)("0.99941103", sdk_gov_1.PRICE_DECIMALS_POW),
|
|
18
|
-
[sdk_gov_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase()]: (0, formatter_1.toBN)("1703.87588096", sdk_gov_1.PRICE_DECIMALS_POW),
|
|
19
|
-
};
|
|
20
|
-
const liquidationThresholds = {
|
|
21
|
-
[sdk_gov_1.tokenDataByNetwork.Mainnet.DAI.toLowerCase()]: 9300n,
|
|
22
|
-
[sdk_gov_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase()]: 8500n,
|
|
23
|
-
[sdk_gov_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase()]: 9000n,
|
|
24
|
-
};
|
|
25
|
-
describe("Strategy test", () => {
|
|
26
|
-
it("maxAPY calculation is correct", () => {
|
|
27
|
-
const result = strategy_1.Strategy.maxAPY({
|
|
28
|
-
apy: 53203,
|
|
29
|
-
leverage: 10 * Number(sdk_gov_1.LEVERAGE_DECIMALS),
|
|
30
|
-
baseRateWithFee: pools["0x1"].borrowRate,
|
|
31
|
-
quotaRateWithFee: 0,
|
|
32
|
-
});
|
|
33
|
-
(0, chai_1.expect)(result).to.be.eq(284143);
|
|
34
|
-
});
|
|
35
|
-
it("liquidationPrice: calculation is correct", () => {
|
|
36
|
-
const result = strategy_1.Strategy.liquidationPrice({
|
|
37
|
-
liquidationThresholds,
|
|
38
|
-
prices,
|
|
39
|
-
debt: (0, formatter_1.toBN)("350", sdk_gov_1.decimals.WETH),
|
|
40
|
-
underlyingToken: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
|
|
41
|
-
targetToken: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
|
|
42
|
-
assets: {
|
|
43
|
-
[sdk_gov_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase()]: {
|
|
44
|
-
balance: (0, formatter_1.toBN)("400", sdk_gov_1.decimals.STETH),
|
|
45
|
-
token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
(0, chai_1.expect)(Number((0, formatter_1.toSignificant)(result, sdk_gov_1.WAD_DECIMALS_POW)).toFixed(3)).to.be.eq("0.992");
|
|
50
|
-
});
|
|
51
|
-
it("liquidationPrice: zero result when debt is compensated", () => {
|
|
52
|
-
const result = strategy_1.Strategy.liquidationPrice({
|
|
53
|
-
liquidationThresholds,
|
|
54
|
-
prices,
|
|
55
|
-
debt: (0, formatter_1.toBN)("350", sdk_gov_1.decimals.WETH),
|
|
56
|
-
underlyingToken: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
|
|
57
|
-
targetToken: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
|
|
58
|
-
assets: {
|
|
59
|
-
[sdk_gov_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase()]: {
|
|
60
|
-
balance: (0, formatter_1.toBN)("400", sdk_gov_1.decimals.STETH),
|
|
61
|
-
token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
|
|
62
|
-
},
|
|
63
|
-
[sdk_gov_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase()]: {
|
|
64
|
-
balance: (0, formatter_1.toBN)("350", sdk_gov_1.decimals.WETH),
|
|
65
|
-
token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
|
|
66
|
-
},
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
|
-
(0, chai_1.expect)(Number((0, formatter_1.toSignificant)(result, sdk_gov_1.WAD_DECIMALS_POW)).toFixed(3)).to.be.eq("0.000");
|
|
70
|
-
});
|
|
71
|
-
it("liquidationPrice: zero result when debt is overcompensated", () => {
|
|
72
|
-
const result = strategy_1.Strategy.liquidationPrice({
|
|
73
|
-
liquidationThresholds,
|
|
74
|
-
prices,
|
|
75
|
-
debt: (0, formatter_1.toBN)("350", sdk_gov_1.decimals.WETH),
|
|
76
|
-
underlyingToken: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
|
|
77
|
-
targetToken: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
|
|
78
|
-
assets: {
|
|
79
|
-
[sdk_gov_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase()]: {
|
|
80
|
-
balance: (0, formatter_1.toBN)("400", sdk_gov_1.decimals.STETH),
|
|
81
|
-
token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
|
|
82
|
-
},
|
|
83
|
-
[sdk_gov_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase()]: {
|
|
84
|
-
balance: (0, formatter_1.toBN)("450", sdk_gov_1.decimals.WETH),
|
|
85
|
-
token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
});
|
|
89
|
-
(0, chai_1.expect)(Number((0, formatter_1.toSignificant)(result, sdk_gov_1.WAD_DECIMALS_POW)).toFixed(3)).to.be.eq("0.000");
|
|
90
|
-
});
|
|
91
|
-
it("liquidationPrice: zero result when debt is not compensated", () => {
|
|
92
|
-
const result = strategy_1.Strategy.liquidationPrice({
|
|
93
|
-
liquidationThresholds,
|
|
94
|
-
prices,
|
|
95
|
-
debt: (0, formatter_1.toBN)("450", sdk_gov_1.decimals.WETH),
|
|
96
|
-
underlyingToken: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
|
|
97
|
-
targetToken: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
|
|
98
|
-
assets: {
|
|
99
|
-
[sdk_gov_1.tokenDataByNetwork.Mainnet.STETH.toLowerCase()]: {
|
|
100
|
-
balance: (0, formatter_1.toBN)("400", sdk_gov_1.decimals.STETH),
|
|
101
|
-
token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
|
|
102
|
-
},
|
|
103
|
-
[sdk_gov_1.tokenDataByNetwork.Mainnet.WETH.toLowerCase()]: {
|
|
104
|
-
balance: (0, formatter_1.toBN)("100", sdk_gov_1.decimals.WETH),
|
|
105
|
-
token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
(0, chai_1.expect)(Number((0, formatter_1.toSignificant)(result, sdk_gov_1.WAD_DECIMALS_POW)).toFixed(3)).to.be.eq("0.992");
|
|
110
|
-
});
|
|
111
|
-
it("maxLeverage is correct", () => {
|
|
112
|
-
const result = strategy_1.Strategy.maxLeverage(sdk_gov_1.tokenDataByNetwork.Mainnet.STETH, [
|
|
113
|
-
{ address: "0x1", liquidationThresholds },
|
|
114
|
-
]);
|
|
115
|
-
(0, chai_1.expect)(result).to.be.eq(9 * Number(sdk_gov_1.LEVERAGE_DECIMALS));
|
|
116
|
-
});
|
|
117
|
-
});
|