@gearbox-protocol/sdk 14.5.10 → 14.6.0-next.1
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/dist/cjs/common-utils/utils/apy/bonus-apy-from-points.js +28 -0
- package/dist/cjs/common-utils/utils/apy/calculate-effective-borrow-rate.js +35 -0
- package/dist/cjs/common-utils/utils/apy/get-complex-apy-list.js +45 -0
- package/dist/cjs/common-utils/utils/apy/get-rate-with-fee.js +31 -0
- package/dist/cjs/common-utils/utils/apy/get-single-quota-borrow-rate.js +33 -0
- package/dist/cjs/common-utils/utils/apy/index.js +32 -0
- package/dist/cjs/common-utils/utils/apy/max-apy-formula.js +40 -0
- package/dist/cjs/common-utils/utils/index.js +5 -1
- package/dist/cjs/common-utils/utils/strategies/__test-utils.js +95 -0
- package/dist/cjs/common-utils/utils/strategies/availability/check-boolean.js +33 -0
- package/dist/cjs/common-utils/utils/strategies/availability/check-degen-nft.js +35 -0
- package/dist/cjs/common-utils/utils/strategies/availability/index.js +28 -0
- package/dist/cjs/common-utils/utils/strategies/availability/validate-open-account-pool-quota-status.js +40 -0
- package/dist/cjs/common-utils/utils/strategies/availability/validate-open-account-pool-status.js +76 -0
- package/dist/cjs/common-utils/utils/strategies/index.js +28 -0
- package/dist/cjs/common-utils/utils/strategies/leverage/calculate-loss-coefficient.js +31 -0
- package/dist/cjs/common-utils/utils/strategies/leverage/calculate-max-leverage-factor.js +45 -0
- package/dist/cjs/common-utils/utils/strategies/leverage/get-factor-from-leverage.js +31 -0
- package/dist/cjs/common-utils/utils/strategies/leverage/get-leverage-from-factor.js +31 -0
- package/dist/cjs/common-utils/utils/strategies/leverage/index.js +32 -0
- package/dist/cjs/common-utils/utils/strategies/leverage/max-leverage-threshold.js +42 -0
- package/dist/cjs/common-utils/utils/strategies/leverage/max-leverage.js +35 -0
- package/dist/cjs/common-utils/utils/strategies/sort-strategy-cms-by-availability/index.js +22 -0
- package/dist/cjs/common-utils/utils/strategies/sort-strategy-cms-by-availability/sort-strategy-cms-by-availability.js +64 -0
- package/dist/cjs/common-utils/utils/strategies/strategy-info/cm-availability-condition.js +63 -0
- package/dist/cjs/common-utils/utils/strategies/strategy-info/get-strategy-info.js +98 -0
- package/dist/cjs/common-utils/utils/strategies/strategy-info/get-strategy-max-apy.js +102 -0
- package/dist/cjs/common-utils/utils/strategies/strategy-info/index.js +30 -0
- package/dist/cjs/common-utils/utils/strategies/strategy-info/is-strategy-cm-disabled.js +33 -0
- package/dist/cjs/common-utils/utils/strategies/strategy-info/types.js +16 -0
- package/dist/esm/common-utils/utils/apy/bonus-apy-from-points.js +4 -0
- package/dist/esm/common-utils/utils/apy/calculate-effective-borrow-rate.js +11 -0
- package/dist/esm/common-utils/utils/apy/get-complex-apy-list.js +21 -0
- package/dist/esm/common-utils/utils/apy/get-rate-with-fee.js +7 -0
- package/dist/esm/common-utils/utils/apy/get-single-quota-borrow-rate.js +9 -0
- package/dist/esm/common-utils/utils/apy/index.js +6 -0
- package/dist/esm/common-utils/utils/apy/max-apy-formula.js +16 -0
- package/dist/esm/common-utils/utils/index.js +2 -0
- package/dist/esm/common-utils/utils/strategies/__test-utils.js +65 -0
- package/dist/esm/common-utils/utils/strategies/availability/check-boolean.js +9 -0
- package/dist/esm/common-utils/utils/strategies/availability/check-degen-nft.js +11 -0
- package/dist/esm/common-utils/utils/strategies/availability/index.js +4 -0
- package/dist/esm/common-utils/utils/strategies/availability/validate-open-account-pool-quota-status.js +16 -0
- package/dist/esm/common-utils/utils/strategies/availability/validate-open-account-pool-status.js +52 -0
- package/dist/esm/common-utils/utils/strategies/index.js +4 -0
- package/dist/esm/common-utils/utils/strategies/leverage/calculate-loss-coefficient.js +7 -0
- package/dist/esm/common-utils/utils/strategies/leverage/calculate-max-leverage-factor.js +21 -0
- package/dist/esm/common-utils/utils/strategies/leverage/get-factor-from-leverage.js +7 -0
- package/dist/esm/common-utils/utils/strategies/leverage/get-leverage-from-factor.js +7 -0
- package/dist/esm/common-utils/utils/strategies/leverage/index.js +6 -0
- package/dist/esm/common-utils/utils/strategies/leverage/max-leverage-threshold.js +18 -0
- package/dist/esm/common-utils/utils/strategies/leverage/max-leverage.js +11 -0
- package/dist/esm/common-utils/utils/strategies/sort-strategy-cms-by-availability/index.js +1 -0
- package/dist/esm/common-utils/utils/strategies/sort-strategy-cms-by-availability/sort-strategy-cms-by-availability.js +43 -0
- package/dist/esm/common-utils/utils/strategies/strategy-info/cm-availability-condition.js +43 -0
- package/dist/esm/common-utils/utils/strategies/strategy-info/get-strategy-info.js +74 -0
- package/dist/esm/common-utils/utils/strategies/strategy-info/get-strategy-max-apy.js +85 -0
- package/dist/esm/common-utils/utils/strategies/strategy-info/index.js +5 -0
- package/dist/esm/common-utils/utils/strategies/strategy-info/is-strategy-cm-disabled.js +9 -0
- package/dist/esm/common-utils/utils/strategies/strategy-info/types.js +0 -0
- package/dist/types/common-utils/utils/apy/bonus-apy-from-points.d.ts +4 -0
- package/dist/types/common-utils/utils/apy/calculate-effective-borrow-rate.d.ts +6 -0
- package/dist/types/common-utils/utils/apy/get-complex-apy-list.d.ts +5 -0
- package/dist/types/common-utils/utils/apy/get-rate-with-fee.d.ts +7 -0
- package/dist/types/common-utils/utils/apy/get-single-quota-borrow-rate.d.ts +9 -0
- package/dist/types/common-utils/utils/apy/index.d.ts +6 -0
- package/dist/types/common-utils/utils/apy/max-apy-formula.d.ts +6 -0
- package/dist/types/common-utils/utils/index.d.ts +2 -0
- package/dist/types/common-utils/utils/strategies/__test-utils.d.ts +11 -0
- package/dist/types/common-utils/utils/strategies/availability/check-boolean.d.ts +1 -0
- package/dist/types/common-utils/utils/strategies/availability/check-degen-nft.d.ts +5 -0
- package/dist/types/common-utils/utils/strategies/availability/index.d.ts +4 -0
- package/dist/types/common-utils/utils/strategies/availability/validate-open-account-pool-quota-status.d.ts +6 -0
- package/dist/types/common-utils/utils/strategies/availability/validate-open-account-pool-status.d.ts +24 -0
- package/dist/types/common-utils/utils/strategies/index.d.ts +4 -0
- package/dist/types/common-utils/utils/strategies/leverage/calculate-loss-coefficient.d.ts +1 -0
- package/dist/types/common-utils/utils/strategies/leverage/calculate-max-leverage-factor.d.ts +12 -0
- package/dist/types/common-utils/utils/strategies/leverage/get-factor-from-leverage.d.ts +4 -0
- package/dist/types/common-utils/utils/strategies/leverage/get-leverage-from-factor.d.ts +2 -0
- package/dist/types/common-utils/utils/strategies/leverage/index.d.ts +6 -0
- package/dist/types/common-utils/utils/strategies/leverage/max-leverage-threshold.d.ts +5 -0
- package/dist/types/common-utils/utils/strategies/leverage/max-leverage.d.ts +9 -0
- package/dist/types/common-utils/utils/strategies/sort-strategy-cms-by-availability/index.d.ts +1 -0
- package/dist/types/common-utils/utils/strategies/sort-strategy-cms-by-availability/sort-strategy-cms-by-availability.d.ts +13 -0
- package/dist/types/common-utils/utils/strategies/strategy-info/cm-availability-condition.d.ts +3 -0
- package/dist/types/common-utils/utils/strategies/strategy-info/get-strategy-info.d.ts +2 -0
- package/dist/types/common-utils/utils/strategies/strategy-info/get-strategy-max-apy.d.ts +13 -0
- package/dist/types/common-utils/utils/strategies/strategy-info/index.d.ts +5 -0
- package/dist/types/common-utils/utils/strategies/strategy-info/is-strategy-cm-disabled.d.ts +2 -0
- package/dist/types/common-utils/utils/strategies/strategy-info/types.d.ts +80 -0
- package/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
function calculateEffectiveBorrowRate({
|
|
2
|
+
underlyingTokenAddress,
|
|
3
|
+
baseRateWithFee = 0,
|
|
4
|
+
apyList
|
|
5
|
+
}) {
|
|
6
|
+
const apy = underlyingTokenAddress ? apyList?.[underlyingTokenAddress] || 0 : 0;
|
|
7
|
+
return apy > 0 ? baseRateWithFee + apy : baseRateWithFee;
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
calculateEffectiveBorrowRate
|
|
11
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { TypedObjectUtils } from "../../../sdk/index.js";
|
|
2
|
+
function getComplexAPYList(baseAPYList, extraCollateralAPYList, pool) {
|
|
3
|
+
if (!pool) return baseAPYList;
|
|
4
|
+
const poolExtraCollateralAPY = extraCollateralAPYList?.[pool];
|
|
5
|
+
if (!poolExtraCollateralAPY) return baseAPYList;
|
|
6
|
+
const baseCopy = { ...baseAPYList };
|
|
7
|
+
TypedObjectUtils.entries(poolExtraCollateralAPY).forEach(
|
|
8
|
+
([token, extraAPY]) => {
|
|
9
|
+
const baseAPY = baseCopy[token];
|
|
10
|
+
if (extraAPY.type === "relative" && baseAPY !== void 0) {
|
|
11
|
+
baseCopy[token] = baseAPY + extraAPY.value;
|
|
12
|
+
} else if (extraAPY.type === "absolute") {
|
|
13
|
+
baseCopy[token] = extraAPY.value;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
);
|
|
17
|
+
return baseCopy;
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
getComplexAPYList
|
|
21
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { calcQuotaBorrowRate } from "../creditAccount/calc-quota-borrow-rate.js";
|
|
2
|
+
import { getRateWithFee } from "./get-rate-with-fee.js";
|
|
3
|
+
function getSingleQuotaBorrowRate(props) {
|
|
4
|
+
const qr = calcQuotaBorrowRate(props);
|
|
5
|
+
return getRateWithFee(qr, props.feeInterest);
|
|
6
|
+
}
|
|
7
|
+
export {
|
|
8
|
+
getSingleQuotaBorrowRate
|
|
9
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from "./bonus-apy-from-points.js";
|
|
2
|
+
export * from "./calculate-effective-borrow-rate.js";
|
|
3
|
+
export * from "./get-complex-apy-list.js";
|
|
4
|
+
export * from "./get-rate-with-fee.js";
|
|
5
|
+
export * from "./get-single-quota-borrow-rate.js";
|
|
6
|
+
export * from "./max-apy-formula.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { LEVERAGE_DECIMALS } from "../../../sdk/index.js";
|
|
2
|
+
import { getFactorFromLeverage } from "../strategies/leverage/index.js";
|
|
3
|
+
function maxAPYFormula({
|
|
4
|
+
apy,
|
|
5
|
+
leverage,
|
|
6
|
+
baseRateWithFee,
|
|
7
|
+
quotaRateWithFee
|
|
8
|
+
}) {
|
|
9
|
+
const collateralTerm = apy - quotaRateWithFee;
|
|
10
|
+
const leverageFactor = getFactorFromLeverage(leverage);
|
|
11
|
+
const debtTerm = (apy - baseRateWithFee - quotaRateWithFee) * Number(leverageFactor) / Number(LEVERAGE_DECIMALS);
|
|
12
|
+
return collateralTerm + Math.floor(debtTerm);
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
maxAPYFormula
|
|
16
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const mockToken1 = "0x1111111111111111111111111111111111111111";
|
|
2
|
+
const mockToken2 = "0x2222222222222222222222222222222222222222";
|
|
3
|
+
const mockUnderlyingToken = "0x9999999999999999999999999999999999999999";
|
|
4
|
+
const mockTokenData = {
|
|
5
|
+
[mockToken1]: { address: mockToken1, decimals: 18, title: "T1" },
|
|
6
|
+
[mockToken2]: { address: mockToken2, decimals: 18, title: "T2" },
|
|
7
|
+
[mockUnderlyingToken]: {
|
|
8
|
+
address: mockUnderlyingToken,
|
|
9
|
+
decimals: 18,
|
|
10
|
+
title: "UNDER"
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
function buildQuota(overrides) {
|
|
14
|
+
return {
|
|
15
|
+
rate: 0n,
|
|
16
|
+
quotaIncreaseFee: 0n,
|
|
17
|
+
totalQuoted: 0n,
|
|
18
|
+
limit: 0n,
|
|
19
|
+
isActive: true,
|
|
20
|
+
...overrides
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function buildPool(overrides = {}) {
|
|
24
|
+
const address = overrides.address ?? "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
|
25
|
+
return {
|
|
26
|
+
address,
|
|
27
|
+
totalDebtLimit: 0n,
|
|
28
|
+
totalBorrowed: 0n,
|
|
29
|
+
...overrides
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function buildCreditManager(overrides = {}) {
|
|
33
|
+
const address = overrides.address ?? "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
|
|
34
|
+
const pool = overrides.pool ?? "0xcccccccccccccccccccccccccccccccccccccccc";
|
|
35
|
+
const underlyingToken = overrides.underlyingToken ?? mockUnderlyingToken;
|
|
36
|
+
const quotas = overrides.quotas ?? {};
|
|
37
|
+
return {
|
|
38
|
+
address,
|
|
39
|
+
underlyingToken,
|
|
40
|
+
pool,
|
|
41
|
+
chainId: 1,
|
|
42
|
+
baseBorrowRate: 0,
|
|
43
|
+
feeInterest: 0,
|
|
44
|
+
availableToBorrow: 0n,
|
|
45
|
+
minDebt: 0n,
|
|
46
|
+
maxDebt: 0n,
|
|
47
|
+
totalDebt: 0n,
|
|
48
|
+
totalDebtLimit: 0n,
|
|
49
|
+
isDegenMode: false,
|
|
50
|
+
degenNFT: "0x0000000000000000000000000000000000000000",
|
|
51
|
+
liquidationThresholds: {},
|
|
52
|
+
quotas,
|
|
53
|
+
collateralTokens: [],
|
|
54
|
+
...overrides
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
buildCreditManager,
|
|
59
|
+
buildPool,
|
|
60
|
+
buildQuota,
|
|
61
|
+
mockToken1,
|
|
62
|
+
mockToken2,
|
|
63
|
+
mockTokenData,
|
|
64
|
+
mockUnderlyingToken
|
|
65
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ADDRESS_0X0 } from "../../../../sdk/index.js";
|
|
2
|
+
function checkDegenNFT(creditManager) {
|
|
3
|
+
const nftAddress = creditManager.isDegenMode ? creditManager.degenNFT : ADDRESS_0X0;
|
|
4
|
+
return {
|
|
5
|
+
nftAddress,
|
|
6
|
+
freeOfNFT: nftAddress === ADDRESS_0X0
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
checkDegenNFT
|
|
11
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
function validateOpenAccountPoolQuotaStatus(targetToken, creditManager, amountToBorrow) {
|
|
2
|
+
const quota = creditManager.quotas[targetToken];
|
|
3
|
+
if (quota) {
|
|
4
|
+
const realLimit = quota.isActive ? quota.limit : 0n;
|
|
5
|
+
const quotaLeft = realLimit - quota.totalQuoted;
|
|
6
|
+
if (quotaLeft < amountToBorrow)
|
|
7
|
+
return {
|
|
8
|
+
message: "insufficientQuota",
|
|
9
|
+
token: targetToken
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
validateOpenAccountPoolQuotaStatus
|
|
16
|
+
};
|
package/dist/esm/common-utils/utils/strategies/availability/validate-open-account-pool-status.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { BigIntMath } from "../../bigint-math.js";
|
|
2
|
+
import { validateOpenAccountPoolQuotaStatus } from "./validate-open-account-pool-quota-status.js";
|
|
3
|
+
function validateOpenAccountPoolStatus(props) {
|
|
4
|
+
const { debt, creditManager, pool, targetToken } = props;
|
|
5
|
+
const effectiveDebt = BigIntMath.max(creditManager.minDebt, debt);
|
|
6
|
+
const hasDebtLimit = creditManager.totalDebtLimit >= 0n;
|
|
7
|
+
const debtLimitLeft = BigIntMath.max(
|
|
8
|
+
creditManager.totalDebtLimit - creditManager.totalDebt,
|
|
9
|
+
0n
|
|
10
|
+
);
|
|
11
|
+
const { totalDebtLimit = 0n, totalBorrowed = 0n } = pool || {};
|
|
12
|
+
const hasPoolDebtLimit = totalDebtLimit > 0n;
|
|
13
|
+
const poolDebtLimitLeft = totalDebtLimit - totalBorrowed;
|
|
14
|
+
const canOpenMinDebt = creditManager.minDebt <= debtLimitLeft && creditManager.minDebt <= poolDebtLimitLeft && creditManager.minDebt <= creditManager.availableToBorrow;
|
|
15
|
+
const minPositionSize = BigIntMath.min(
|
|
16
|
+
BigIntMath.min(debtLimitLeft, poolDebtLimitLeft),
|
|
17
|
+
creditManager.availableToBorrow
|
|
18
|
+
);
|
|
19
|
+
if (hasDebtLimit && effectiveDebt > debtLimitLeft) {
|
|
20
|
+
return {
|
|
21
|
+
message: "insufficientDebtLimit",
|
|
22
|
+
amount: debtLimitLeft,
|
|
23
|
+
solutionAmount: canOpenMinDebt ? minPositionSize : void 0
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
if (hasPoolDebtLimit && effectiveDebt > poolDebtLimitLeft) {
|
|
27
|
+
return {
|
|
28
|
+
message: "insufficientPoolDebtLimit",
|
|
29
|
+
amount: poolDebtLimitLeft,
|
|
30
|
+
solutionAmount: canOpenMinDebt ? minPositionSize : void 0
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (effectiveDebt > creditManager.availableToBorrow) {
|
|
34
|
+
return {
|
|
35
|
+
message: "insufficientPoolLiquidity",
|
|
36
|
+
amount: creditManager.availableToBorrow,
|
|
37
|
+
solutionAmount: canOpenMinDebt ? minPositionSize : void 0
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (targetToken !== null) {
|
|
41
|
+
const quotaError = validateOpenAccountPoolQuotaStatus(
|
|
42
|
+
targetToken,
|
|
43
|
+
creditManager,
|
|
44
|
+
effectiveDebt
|
|
45
|
+
);
|
|
46
|
+
if (quotaError) return quotaError;
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
validateOpenAccountPoolStatus
|
|
52
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { PERCENTAGE_FACTOR } from "../../../../sdk/index.js";
|
|
2
|
+
import { BigIntMath } from "../../bigint-math.js";
|
|
3
|
+
import { calculateLossCoefficient } from "./calculate-loss-coefficient.js";
|
|
4
|
+
import { maxLeverage } from "./max-leverage.js";
|
|
5
|
+
const DEFAULT_LEVERAGE_CONSTANT_LOSS = 500n;
|
|
6
|
+
function calculateMaxLeverageFactor({
|
|
7
|
+
targetToken,
|
|
8
|
+
slippage,
|
|
9
|
+
creditManagers,
|
|
10
|
+
constantLoss = DEFAULT_LEVERAGE_CONSTANT_LOSS,
|
|
11
|
+
leverageLimit
|
|
12
|
+
}) {
|
|
13
|
+
const maxPossibleLeverage = maxLeverage(targetToken, creditManagers);
|
|
14
|
+
const coefficient = calculateLossCoefficient(slippage, constantLoss);
|
|
15
|
+
const maxLeverageValue = BigInt(maxPossibleLeverage) * coefficient / PERCENTAGE_FACTOR;
|
|
16
|
+
const r = leverageLimit !== void 0 ? BigIntMath.min(BigInt(leverageLimit), maxLeverageValue) : maxLeverageValue;
|
|
17
|
+
return r;
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
calculateMaxLeverageFactor
|
|
21
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from "./calculate-loss-coefficient.js";
|
|
2
|
+
export * from "./calculate-max-leverage-factor.js";
|
|
3
|
+
export * from "./get-factor-from-leverage.js";
|
|
4
|
+
export * from "./get-leverage-from-factor.js";
|
|
5
|
+
export * from "./max-leverage.js";
|
|
6
|
+
export * from "./max-leverage-threshold.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const EMPTY_ADDRESS = "";
|
|
2
|
+
function maxLeverageThreshold(lpToken, cms) {
|
|
3
|
+
const lpTokenLC = lpToken.toLowerCase();
|
|
4
|
+
const ltByCM = cms.map((cm2) => {
|
|
5
|
+
const lt2 = cm2.liquidationThresholds[lpTokenLC] || 0n;
|
|
6
|
+
return [cm2.address, lt2];
|
|
7
|
+
});
|
|
8
|
+
const sorted = ltByCM.sort(([, ltA], [, ltB]) => {
|
|
9
|
+
if (ltA > ltB) return -1;
|
|
10
|
+
if (ltB > ltA) return 1;
|
|
11
|
+
return 0;
|
|
12
|
+
});
|
|
13
|
+
const [cm = EMPTY_ADDRESS, lt = 0n] = sorted[0] || [];
|
|
14
|
+
return [lt, cm];
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
maxLeverageThreshold
|
|
18
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { LEVERAGE_DECIMALS, PERCENTAGE_FACTOR } from "../../../../sdk/index.js";
|
|
2
|
+
import { getFactorFromLeverage } from "./get-factor-from-leverage.js";
|
|
3
|
+
import { maxLeverageThreshold } from "./max-leverage-threshold.js";
|
|
4
|
+
function maxLeverage(lpToken, cms, targetHF = PERCENTAGE_FACTOR) {
|
|
5
|
+
const [maxThreshold] = maxLeverageThreshold(lpToken, cms);
|
|
6
|
+
const maxLeverageValue = targetHF * LEVERAGE_DECIMALS / (targetHF - maxThreshold);
|
|
7
|
+
return getFactorFromLeverage(maxLeverageValue);
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
maxLeverage
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./sort-strategy-cms-by-availability.js";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { amountAbcComparator } from "../../creditAccount/sort.js";
|
|
2
|
+
import {
|
|
3
|
+
cmAvailabilityCondition,
|
|
4
|
+
getStrategyMaxAPY
|
|
5
|
+
} from "../strategy-info/index.js";
|
|
6
|
+
function sortStrategyCMsByAvailability({
|
|
7
|
+
targetToken,
|
|
8
|
+
allCreditManagers,
|
|
9
|
+
apyListByNetwork,
|
|
10
|
+
pools,
|
|
11
|
+
slippage,
|
|
12
|
+
quotaReserve,
|
|
13
|
+
leverageLimit,
|
|
14
|
+
isStrategy
|
|
15
|
+
}) {
|
|
16
|
+
const list = [...allCreditManagers].sort((cmA, cmB) => {
|
|
17
|
+
const sort = cmAvailabilityCondition(targetToken, cmA, cmB, pools);
|
|
18
|
+
if (sort !== 0) return sort;
|
|
19
|
+
const apyA = getStrategyMaxAPY(
|
|
20
|
+
targetToken,
|
|
21
|
+
cmA,
|
|
22
|
+
apyListByNetwork,
|
|
23
|
+
slippage,
|
|
24
|
+
quotaReserve,
|
|
25
|
+
leverageLimit
|
|
26
|
+
);
|
|
27
|
+
const apyB = getStrategyMaxAPY(
|
|
28
|
+
targetToken,
|
|
29
|
+
cmB,
|
|
30
|
+
apyListByNetwork,
|
|
31
|
+
slippage,
|
|
32
|
+
quotaReserve,
|
|
33
|
+
leverageLimit
|
|
34
|
+
);
|
|
35
|
+
const sortAPY = isStrategy ? (apyB?.totalMaxApy || 0) - (apyA?.totalMaxApy || 0) : (apyA?.totalBorrowRate || 0) - (apyB?.totalBorrowRate || 0);
|
|
36
|
+
if (sortAPY !== 0) return sortAPY;
|
|
37
|
+
return amountAbcComparator(cmA.maxDebt, cmB.maxDebt);
|
|
38
|
+
});
|
|
39
|
+
return list;
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
sortStrategyCMsByAvailability
|
|
43
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
checkBoolean,
|
|
3
|
+
checkDegenNFT,
|
|
4
|
+
validateOpenAccountPoolStatus
|
|
5
|
+
} from "../availability/index.js";
|
|
6
|
+
function cmAvailabilityCondition(targetToken, cmA, cmB, pools) {
|
|
7
|
+
const aHasMinError = validateOpenAccountPoolStatus({
|
|
8
|
+
pool: pools?.[cmA.pool],
|
|
9
|
+
debt: cmA.minDebt,
|
|
10
|
+
creditManager: cmA,
|
|
11
|
+
targetToken
|
|
12
|
+
});
|
|
13
|
+
const bHasMinError = validateOpenAccountPoolStatus({
|
|
14
|
+
pool: pools?.[cmB.pool],
|
|
15
|
+
debt: cmB.minDebt,
|
|
16
|
+
creditManager: cmB,
|
|
17
|
+
targetToken
|
|
18
|
+
});
|
|
19
|
+
const minSort = checkBoolean(!aHasMinError, !bHasMinError);
|
|
20
|
+
if (minSort !== 0) return minSort;
|
|
21
|
+
const { freeOfNFT: aFreeOfNFT } = checkDegenNFT(cmA);
|
|
22
|
+
const { freeOfNFT: bFreeOfNFT } = checkDegenNFT(cmB);
|
|
23
|
+
const nftSort = checkBoolean(aFreeOfNFT, bFreeOfNFT);
|
|
24
|
+
if (nftSort !== 0) return nftSort;
|
|
25
|
+
const aHasMaxError = validateOpenAccountPoolStatus({
|
|
26
|
+
pool: pools?.[cmA.pool],
|
|
27
|
+
debt: cmA.maxDebt,
|
|
28
|
+
creditManager: cmA,
|
|
29
|
+
targetToken
|
|
30
|
+
});
|
|
31
|
+
const bHasMaxError = validateOpenAccountPoolStatus({
|
|
32
|
+
pool: pools?.[cmB.pool],
|
|
33
|
+
debt: cmB.maxDebt,
|
|
34
|
+
creditManager: cmB,
|
|
35
|
+
targetToken
|
|
36
|
+
});
|
|
37
|
+
const maxSort = checkBoolean(!aHasMaxError, !bHasMaxError);
|
|
38
|
+
if (maxSort !== 0) return maxSort;
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
cmAvailabilityCondition
|
|
43
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { PriceUtils } from "../../price-math.js";
|
|
2
|
+
import { getFactorFromLeverage } from "../leverage/index.js";
|
|
3
|
+
import { sortStrategyCMsByAvailability } from "../sort-strategy-cms-by-availability/index.js";
|
|
4
|
+
import { getStrategyMaxAPY } from "./get-strategy-max-apy.js";
|
|
5
|
+
import { isStrategyCMDisabled } from "./is-strategy-cm-disabled.js";
|
|
6
|
+
const EMPTY_ADDRESS = "";
|
|
7
|
+
const EMPTY_CHAIN_ID = 0;
|
|
8
|
+
function getStrategyInfo({
|
|
9
|
+
strategy,
|
|
10
|
+
creditManagers,
|
|
11
|
+
sdkStateByChain,
|
|
12
|
+
apyListByNetwork,
|
|
13
|
+
quotaReserve,
|
|
14
|
+
slippage,
|
|
15
|
+
allPricesByChain
|
|
16
|
+
}) {
|
|
17
|
+
const strategyCMs = creditManagers?.[strategy.chainId]?.[strategy.id] || {};
|
|
18
|
+
const strategyCMsList = Object.values(strategyCMs);
|
|
19
|
+
if (strategyCMsList.length === 0) return void 0;
|
|
20
|
+
const openableCMsList = strategyCMsList.filter(
|
|
21
|
+
(cm) => !isStrategyCMDisabled(cm, cm.quotas[strategy.tokenOutAddress])
|
|
22
|
+
);
|
|
23
|
+
const currentSdkState = sdkStateByChain?.[strategy.chainId];
|
|
24
|
+
const pools = currentSdkState?.pools;
|
|
25
|
+
const tokensList = currentSdkState?.tokens?.tokenDataList;
|
|
26
|
+
const targetTokenAddress = strategy.tokenOutAddress;
|
|
27
|
+
const minCreditManager = sortStrategyCMsByAvailability({
|
|
28
|
+
targetToken: targetTokenAddress,
|
|
29
|
+
allCreditManagers: openableCMsList.length > 0 ? openableCMsList : strategyCMsList,
|
|
30
|
+
apyListByNetwork,
|
|
31
|
+
slippage,
|
|
32
|
+
quotaReserve,
|
|
33
|
+
pools,
|
|
34
|
+
leverageLimit: strategy.maxLeverage,
|
|
35
|
+
isStrategy: true
|
|
36
|
+
})?.[0] || strategyCMsList[0];
|
|
37
|
+
const { underlyingToken = EMPTY_ADDRESS, availableToBorrow = 0n } = minCreditManager || {};
|
|
38
|
+
const {
|
|
39
|
+
bonusAPY,
|
|
40
|
+
totalMaxApy = 0,
|
|
41
|
+
maxLeverage = 0n,
|
|
42
|
+
baseBorrowRate = 0,
|
|
43
|
+
quotaRateMin = 0n
|
|
44
|
+
} = getStrategyMaxAPY(
|
|
45
|
+
targetTokenAddress,
|
|
46
|
+
minCreditManager,
|
|
47
|
+
apyListByNetwork,
|
|
48
|
+
slippage,
|
|
49
|
+
quotaReserve,
|
|
50
|
+
strategy.maxLeverage
|
|
51
|
+
) || {};
|
|
52
|
+
const prices = allPricesByChain?.[minCreditManager?.chainId ?? EMPTY_CHAIN_ID]?.prices?.[minCreditManager?.pool || EMPTY_ADDRESS];
|
|
53
|
+
const underlyingPrice = prices?.[underlyingToken] || 0n;
|
|
54
|
+
const underlyingDecimals = tokensList?.[underlyingToken]?.decimals || 18;
|
|
55
|
+
const availableToBorrowMoney = PriceUtils.calcTotalPrice(
|
|
56
|
+
underlyingPrice,
|
|
57
|
+
availableToBorrow,
|
|
58
|
+
underlyingDecimals
|
|
59
|
+
);
|
|
60
|
+
const r = BigInt(baseBorrowRate) * getFactorFromLeverage(maxLeverage) / maxLeverage;
|
|
61
|
+
const qr = quotaRateMin;
|
|
62
|
+
const totalBorrowRate = Number(r + qr);
|
|
63
|
+
return {
|
|
64
|
+
maxLeverage,
|
|
65
|
+
maxAPY: totalMaxApy,
|
|
66
|
+
bonusAPY,
|
|
67
|
+
totalBorrowRate,
|
|
68
|
+
availableToBorrowMoney,
|
|
69
|
+
minCreditManager
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export {
|
|
73
|
+
getStrategyInfo
|
|
74
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LEVERAGE_DECIMALS,
|
|
3
|
+
PERCENTAGE_FACTOR,
|
|
4
|
+
toBigInt
|
|
5
|
+
} from "../../../../sdk/index.js";
|
|
6
|
+
import { BONUS_APY_FROM_POINTS } from "../../apy/bonus-apy-from-points.js";
|
|
7
|
+
import { calculateEffectiveBorrowRate } from "../../apy/calculate-effective-borrow-rate.js";
|
|
8
|
+
import { getComplexAPYList } from "../../apy/get-complex-apy-list.js";
|
|
9
|
+
import { getSingleQuotaBorrowRate } from "../../apy/get-single-quota-borrow-rate.js";
|
|
10
|
+
import { maxAPYFormula } from "../../apy/max-apy-formula.js";
|
|
11
|
+
import {
|
|
12
|
+
calculateMaxLeverageFactor,
|
|
13
|
+
getLeverageFromFactor
|
|
14
|
+
} from "../leverage/index.js";
|
|
15
|
+
function getStrategyMaxAPY(targetToken, cm, apyListByNetwork, slippage, quotaReserve, leverageLimit) {
|
|
16
|
+
if (!cm) return void 0;
|
|
17
|
+
const apyRecord = getComplexAPYList(
|
|
18
|
+
apyListByNetwork?.[cm.chainId]?.apyList,
|
|
19
|
+
apyListByNetwork?.[cm.chainId]?.extraCollateralAPYList,
|
|
20
|
+
cm.pool
|
|
21
|
+
);
|
|
22
|
+
const baseRateWithFee = calculateEffectiveBorrowRate({
|
|
23
|
+
underlyingTokenAddress: cm.underlyingToken,
|
|
24
|
+
baseRateWithFee: cm.baseBorrowRate,
|
|
25
|
+
apyList: apyRecord
|
|
26
|
+
});
|
|
27
|
+
const lt = cm.liquidationThresholds[targetToken] || 0n;
|
|
28
|
+
const feeInterest = cm.feeInterest;
|
|
29
|
+
const tokenQuota = cm.quotas[targetToken] || {
|
|
30
|
+
token: targetToken,
|
|
31
|
+
rate: 0n,
|
|
32
|
+
quotaIncreaseFee: 0n,
|
|
33
|
+
totalQuoted: 0n,
|
|
34
|
+
limit: 0n,
|
|
35
|
+
isActive: true
|
|
36
|
+
};
|
|
37
|
+
const qRate = (tokenQuota?.rate || 0n) * lt / PERCENTAGE_FACTOR;
|
|
38
|
+
const qRate_reserve = qRate * (PERCENTAGE_FACTOR + toBigInt(quotaReserve)) / PERCENTAGE_FACTOR;
|
|
39
|
+
const quotaRateWithFee = getSingleQuotaBorrowRate({
|
|
40
|
+
quotaRates: {
|
|
41
|
+
[targetToken]: {
|
|
42
|
+
...tokenQuota,
|
|
43
|
+
rate: qRate_reserve
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
feeInterest,
|
|
47
|
+
quotas: {
|
|
48
|
+
[targetToken]: {
|
|
49
|
+
token: targetToken,
|
|
50
|
+
balance: 1n
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
const leverage = getLeverageFromFactor(
|
|
55
|
+
calculateMaxLeverageFactor({
|
|
56
|
+
targetToken,
|
|
57
|
+
creditManagers: [cm],
|
|
58
|
+
slippage,
|
|
59
|
+
leverageLimit
|
|
60
|
+
})
|
|
61
|
+
);
|
|
62
|
+
const apy = apyRecord?.[targetToken] || 0;
|
|
63
|
+
const maxAPY = apyRecord ? maxAPYFormula({
|
|
64
|
+
apy,
|
|
65
|
+
leverage,
|
|
66
|
+
baseRateWithFee,
|
|
67
|
+
quotaRateWithFee: Number(quotaRateWithFee)
|
|
68
|
+
}) : void 0;
|
|
69
|
+
const bonusAPY = BONUS_APY_FROM_POINTS[targetToken];
|
|
70
|
+
const bonusAPYTotal = BigInt(bonusAPY?.value || 0) * leverage / LEVERAGE_DECIMALS;
|
|
71
|
+
const totalMaxApy = (maxAPY || 0) + Number(bonusAPYTotal);
|
|
72
|
+
const totalBorrowRate = baseRateWithFee + Number(quotaRateWithFee);
|
|
73
|
+
return {
|
|
74
|
+
totalMaxApy,
|
|
75
|
+
bonusAPY,
|
|
76
|
+
maxAPY: maxAPY || 0,
|
|
77
|
+
maxLeverage: leverage,
|
|
78
|
+
quotaRateMin: quotaRateWithFee,
|
|
79
|
+
baseBorrowRate: baseRateWithFee,
|
|
80
|
+
totalBorrowRate
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export {
|
|
84
|
+
getStrategyMaxAPY
|
|
85
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
function isStrategyCMDisabled(cm, quota) {
|
|
2
|
+
if (!quota) return true;
|
|
3
|
+
const realLimit = quota.isActive ? quota.limit : 0n;
|
|
4
|
+
const quotaLeft = realLimit - quota.totalQuoted;
|
|
5
|
+
return cm.availableToBorrow < cm.minDebt || quotaLeft < cm.minDebt;
|
|
6
|
+
}
|
|
7
|
+
export {
|
|
8
|
+
isStrategyCMDisabled
|
|
9
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Address } from "viem";
|
|
2
|
+
export declare function calculateEffectiveBorrowRate({ underlyingTokenAddress, baseRateWithFee, apyList, }: {
|
|
3
|
+
underlyingTokenAddress: Address | undefined;
|
|
4
|
+
baseRateWithFee?: number;
|
|
5
|
+
apyList: Record<Address, number> | undefined;
|
|
6
|
+
}): number;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Address } from "viem";
|
|
2
|
+
export declare function getComplexAPYList<T extends Address | undefined = undefined>(baseAPYList: Record<Address, number> | undefined, extraCollateralAPYList: Record<Address, Record<Address, {
|
|
3
|
+
type: "relative" | "absolute";
|
|
4
|
+
value: number;
|
|
5
|
+
}>> | undefined, pool: T | undefined): Record<Address, number> | undefined;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CalcQuotaBorrowRateProps } from "../creditAccount/calc-quota-borrow-rate.js";
|
|
2
|
+
export interface GetSingleQuotaBorrowRateRate extends CalcQuotaBorrowRateProps {
|
|
3
|
+
feeInterest: number;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Under the hood sums up rates for all given quotas and then multiplies them by 1+feeInterest,
|
|
7
|
+
* but it is expected that the ONLY quota will be passed
|
|
8
|
+
*/
|
|
9
|
+
export declare function getSingleQuotaBorrowRate(props: GetSingleQuotaBorrowRateRate): bigint;
|