@gearbox-protocol/sdk 17.10.0 → 17.10.1-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/onchain/accounts/index.js +1 -0
- package/dist/cjs/onchain/accounts/intents/guards.js +4 -2
- package/dist/cjs/onchain/accounts/intents/index.js +41 -7
- package/dist/cjs/onchain/accounts/intents/math.js +3 -44
- package/dist/cjs/onchain/accounts/intents/maxBorrow.js +7 -1
- package/dist/cjs/onchain/accounts/intents/open-strategy.js +12 -7
- package/dist/cjs/onchain/accounts/intents/plan.js +4 -4
- package/dist/cjs/onchain/accounts/intents/realize.js +4 -3
- package/dist/cjs/onchain/accounts/intents/strategyLimits.js +159 -0
- package/dist/cjs/onchain/accounts/intents/tail.js +5 -1
- package/dist/cjs/onchain/accounts/intents/testing/sdk-mock.js +4 -0
- package/dist/cjs/onchain/accounts/intents/utils/index.js +1 -0
- package/dist/cjs/onchain/accounts/intents/utils/quotas-for-update.js +39 -0
- package/dist/cjs/onchain/accounts/quota-utils.js +9 -0
- package/dist/cjs/onchain/index.js +1 -0
- package/dist/cjs/onchain/market/oracle/PriceOracleBaseContract.js +8 -6
- package/dist/cjs/onchain/validation/checks/checkBorrowLimit.js +2 -3
- package/dist/cjs/onchain/validation/checks/checkDebtLimits.js +3 -4
- package/dist/cjs/onchain/validation/checks/checkQuotaLimit.js +2 -1
- package/dist/esm/dev/AccountOpener.js +1 -1
- package/dist/esm/dev/withdrawalUtils.js +1 -1
- package/dist/esm/history/trace/extractTransfers.js +1 -1
- package/dist/esm/onchain/accounts/CreditAccountsServiceV310.js +2 -2
- package/dist/esm/onchain/accounts/index.js +2 -2
- package/dist/esm/onchain/accounts/intents/guards.js +4 -2
- package/dist/esm/onchain/accounts/intents/index.js +41 -7
- package/dist/esm/onchain/accounts/intents/math.js +5 -45
- package/dist/esm/onchain/accounts/intents/maxBorrow.js +7 -1
- package/dist/esm/onchain/accounts/intents/open-strategy.js +13 -8
- package/dist/esm/onchain/accounts/intents/plan.js +4 -4
- package/dist/esm/onchain/accounts/intents/realize.js +4 -3
- package/dist/esm/onchain/accounts/intents/strategyLimits.js +158 -0
- package/dist/esm/onchain/accounts/intents/tail.js +5 -1
- package/dist/esm/onchain/accounts/intents/testing/sdk-mock.js +4 -0
- package/dist/esm/onchain/accounts/intents/utils/index.js +2 -2
- package/dist/esm/onchain/accounts/intents/utils/quotas-for-update.js +41 -3
- package/dist/esm/onchain/accounts/liquidations/LiquidationsService.js +1 -1
- package/dist/esm/onchain/accounts/quota-utils.js +9 -1
- package/dist/esm/onchain/accounts/withdrawal-compressor/RedemptionLoggerV310Contract.js +1 -1
- package/dist/esm/onchain/accounts/withdrawal-compressor/WithdrawalCompressorV310Contract.js +1 -1
- package/dist/esm/onchain/accounts/withdrawal-compressor/WithdrawalCompressorV311Contract.js +1 -1
- package/dist/esm/onchain/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.js +1 -1
- package/dist/esm/onchain/base/TokensMeta.js +3 -3
- package/dist/esm/onchain/core/createAddressProvider.js +1 -1
- package/dist/esm/onchain/index.js +2 -2
- package/dist/esm/onchain/market/adapters/contracts/AccountMigratorAdapterContract.js +1 -1
- package/dist/esm/onchain/market/adapters/contracts/ERC4626AdapterContract.js +1 -1
- package/dist/esm/onchain/market/credit/CreditFacadeV310BaseContract.js +1 -1
- package/dist/esm/onchain/market/oracle/PriceOracleBaseContract.js +8 -6
- package/dist/esm/onchain/market/pool/PoolV310Contract.js +1 -1
- package/dist/esm/onchain/market/rwa/createDegenNFT.js +1 -1
- package/dist/esm/onchain/market/zapper/IETHZapperContract.js +1 -1
- package/dist/esm/onchain/market/zapper/ZapperContract.js +1 -1
- package/dist/esm/onchain/preview/preview/previewPoolPositionOperation.js +2 -2
- package/dist/esm/onchain/utils/viem/simulateWithPriceUpdates.js +1 -1
- package/dist/esm/onchain/validation/checks/checkBorrowLimit.js +2 -3
- package/dist/esm/onchain/validation/checks/checkDebtLimits.js +3 -4
- package/dist/esm/onchain/validation/checks/checkQuotaLimit.js +2 -1
- package/dist/types/model/errors/index.d.ts +2 -2
- package/dist/types/model/errors/operation-errors.d.ts +28 -14
- package/dist/types/model/index.d.ts +2 -2
- package/dist/types/onchain/accounts/index.d.ts +2 -2
- package/dist/types/onchain/accounts/intents/guards.d.ts +12 -12
- package/dist/types/onchain/accounts/intents/math.d.ts +7 -16
- package/dist/types/onchain/accounts/intents/plan.d.ts +2 -0
- package/dist/types/onchain/accounts/intents/realize.d.ts +3 -0
- package/dist/types/onchain/accounts/intents/strategyLimits.d.ts +33 -0
- package/dist/types/onchain/accounts/intents/tail.d.ts +13 -9
- package/dist/types/onchain/accounts/intents/utils/index.d.ts +2 -2
- package/dist/types/onchain/accounts/intents/utils/quotas-for-update.d.ts +15 -1
- package/dist/types/onchain/accounts/quota-utils.d.ts +11 -1
- package/dist/types/onchain/index.d.ts +2 -2
- package/dist/types/onchain/market/oracle/PriceOracleBaseContract.d.ts +0 -3
- package/dist/types/onchain/market/oracle/types.d.ts +4 -3
- package/dist/types/onchain/validation/checks/checkBorrowLimit.d.ts +2 -3
- package/dist/types/onchain/validation/checks/checkDebtLimits.d.ts +2 -3
- package/dist/types/onchain/validation/checks/checkQuotaLimit.d.ts +2 -2
- package/package.json +1 -1
|
@@ -113,6 +113,9 @@ var PriceOracleBaseContract = class extends require_onchain_base_BaseContract.Ba
|
|
|
113
113
|
* {@inheritDoc IPriceOracleContract.convert}
|
|
114
114
|
**/
|
|
115
115
|
convert(from, to, amount, reserve = false) {
|
|
116
|
+
return this.#convert(from, to, amount, reserve, false);
|
|
117
|
+
}
|
|
118
|
+
#convert(from, to, amount, reserve, roundUp) {
|
|
116
119
|
if ((0, viem.isAddressEqual)(from, to)) return amount;
|
|
117
120
|
const fromToken = this.#priceableToken(from);
|
|
118
121
|
const toToken = this.#priceableToken(to);
|
|
@@ -120,7 +123,9 @@ var PriceOracleBaseContract = class extends require_onchain_base_BaseContract.Ba
|
|
|
120
123
|
const fromScale = 10n ** BigInt(this.tokensMeta.decimals(fromToken));
|
|
121
124
|
const toPrice = reserve ? this.reservePrice(toToken) : this.mainPrice(toToken);
|
|
122
125
|
const toScale = 10n ** BigInt(this.tokensMeta.decimals(toToken));
|
|
123
|
-
|
|
126
|
+
const numerator = amount * fromPrice * toScale;
|
|
127
|
+
const denominator = toPrice * fromScale;
|
|
128
|
+
return roundUp ? require_onchain_utils_bigint_math.BigIntMath.ceilDiv(numerator, denominator) : numerator / denominator;
|
|
124
129
|
}
|
|
125
130
|
/**
|
|
126
131
|
* {@inheritDoc IPriceOracleContract.convertToUSD}
|
|
@@ -141,15 +146,12 @@ var PriceOracleBaseContract = class extends require_onchain_base_BaseContract.Ba
|
|
|
141
146
|
const price = reserve ? this.reservePrice(token) : this.mainPrice(token);
|
|
142
147
|
return amount * 10n ** BigInt(this.tokensMeta.decimals(token)) / price;
|
|
143
148
|
}
|
|
144
|
-
/**
|
|
145
|
-
* {@inheritDoc IPriceOracleContract.safeConvert}
|
|
146
|
-
**/
|
|
147
149
|
safeConvert(from, to, amount) {
|
|
148
150
|
try {
|
|
149
|
-
return { value: this
|
|
151
|
+
return { value: this.#convert(from, to, amount, false, true) };
|
|
150
152
|
} catch {
|
|
151
153
|
try {
|
|
152
|
-
return { value: this
|
|
154
|
+
return { value: this.#convert(from, to, amount, true, true) };
|
|
153
155
|
} catch {
|
|
154
156
|
return require_model_result.safeValue(0n, require_model_errors_oracle_errors.unpriceableTokenError(from));
|
|
155
157
|
}
|
|
@@ -12,13 +12,12 @@ require("../helpers/index.js");
|
|
|
12
12
|
* takeable, left out when none is.
|
|
13
13
|
*/
|
|
14
14
|
function checkBorrowLimit(args) {
|
|
15
|
-
const { requested, available,
|
|
15
|
+
const { requested, available, underlying, maxBorrowAmount, ...rest } = args;
|
|
16
16
|
if (requested <= available) return [];
|
|
17
17
|
return [require_model_errors_operation_errors.insufficientPoolLiquidity({
|
|
18
|
-
|
|
18
|
+
...rest,
|
|
19
19
|
requested: require_onchain_validation_helpers_amount.amountOf(underlying, requested),
|
|
20
20
|
available: require_onchain_validation_helpers_amount.amountOf(underlying, available),
|
|
21
|
-
limit,
|
|
22
21
|
...maxBorrowAmount === void 0 ? {} : { maxBorrowAmount: require_onchain_validation_helpers_amount.amountOf(underlying, maxBorrowAmount) }
|
|
23
22
|
})];
|
|
24
23
|
}
|
|
@@ -6,14 +6,13 @@ require("../helpers/index.js");
|
|
|
6
6
|
//#region src/onchain/validation/checks/checkDebtLimits.ts
|
|
7
7
|
/** A debt the facade would revert on. */
|
|
8
8
|
function checkDebtLimits(args) {
|
|
9
|
-
const { debt, minDebt, maxDebt, underlying, allowZero,
|
|
9
|
+
const { debt, minDebt, maxDebt, underlying, allowZero, ...rest } = args;
|
|
10
10
|
if (!(debt > maxDebt || debt < minDebt && !(allowZero && debt === 0n))) return [];
|
|
11
11
|
return [require_model_errors_operation_errors.debtOutOfRange({
|
|
12
|
-
|
|
12
|
+
...rest,
|
|
13
13
|
requested: require_onchain_validation_helpers_amount.amountOf(underlying, debt),
|
|
14
14
|
minDebt: require_onchain_validation_helpers_amount.amountOf(underlying, minDebt),
|
|
15
|
-
maxDebt: require_onchain_validation_helpers_amount.amountOf(underlying, maxDebt)
|
|
16
|
-
maxBorrowAmount
|
|
15
|
+
maxDebt: require_onchain_validation_helpers_amount.amountOf(underlying, maxDebt)
|
|
17
16
|
})];
|
|
18
17
|
}
|
|
19
18
|
//#endregion
|
|
@@ -6,9 +6,10 @@ require("../helpers/index.js");
|
|
|
6
6
|
//#region src/onchain/validation/checks/checkQuotaLimit.ts
|
|
7
7
|
/** The room the keeper still has for a token's quota, in the underlying. */
|
|
8
8
|
function checkQuotaLimit(args) {
|
|
9
|
-
const { token, requested, available, underlying } = args;
|
|
9
|
+
const { token, requested, available, underlying, ...rest } = args;
|
|
10
10
|
if (requested !== void 0 && requested <= available) return [];
|
|
11
11
|
return [require_model_errors_operation_errors.quotaLimitReached({
|
|
12
|
+
...rest,
|
|
12
13
|
token,
|
|
13
14
|
requested: requested === void 0 ? void 0 : require_onchain_validation_helpers_amount.amountOf(underlying, requested),
|
|
14
15
|
available: require_onchain_validation_helpers_amount.amountOf(underlying, available)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iCreditFacadeV310Abi } from "../abi/310/generated.js";
|
|
2
1
|
import { ierc20Abi } from "../abi/iERC20.js";
|
|
2
|
+
import { iCreditFacadeV310Abi } from "../abi/310/generated.js";
|
|
3
3
|
import { AddressMap } from "../onchain/utils/AddressMap.js";
|
|
4
4
|
import { AddressSet } from "../onchain/utils/AddressSet.js";
|
|
5
5
|
import { AssetsMap } from "../onchain/utils/AssetsMap.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { iWithdrawalCompressorV313Abi } from "../abi/IWithdrawalCompressorV313.js";
|
|
1
2
|
import { getNetworkType } from "../onchain/chain/chains.js";
|
|
2
3
|
import { getWithdrawalCompressorAddress } from "../onchain/accounts/withdrawal-compressor/addresses.js";
|
|
3
|
-
import { iWithdrawalCompressorV313Abi } from "../abi/IWithdrawalCompressorV313.js";
|
|
4
4
|
import "../onchain/index.js";
|
|
5
5
|
import { iMidasDataFeedAbi, iMidasRedemptionVaultAbi, midasGatewayAbi, midasRedeemerAbi, midasRedemptionVaultPhantomTokenAbi, securitizeRedeemerAbi, securitizeRedemptionGatewayAbi, securitizeRedemptionPhantomTokenAbi } from "./withdrawalAbi.js";
|
|
6
6
|
import { erc20Abi, hexToString, parseAbi, parseEther } from "viem";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { iCreditFacadeV310Abi } from "../../abi/310/generated.js";
|
|
2
1
|
import { ierc20Abi } from "../../abi/iERC20.js";
|
|
2
|
+
import { iCreditFacadeV310Abi } from "../../abi/310/generated.js";
|
|
3
3
|
import { AddressMap } from "../../onchain/utils/AddressMap.js";
|
|
4
4
|
import "../../onchain/index.js";
|
|
5
5
|
import { UnexpectedFacadeEventOrderError } from "./errors.js";
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { iBaseRewardPoolAbi } from "../../abi/iBaseRewardPool.js";
|
|
2
|
+
import { ierc4626AdapterAbi } from "../../abi/ierc4626Adapter.js";
|
|
1
3
|
import { AP_REWARDS_COMPRESSOR } from "../constants/address-provider.js";
|
|
2
4
|
import { ADDRESS_0X0 } from "../constants/addresses.js";
|
|
3
5
|
import { MAX_UINT256 } from "../constants/math.js";
|
|
@@ -8,8 +10,6 @@ import "../base/index.js";
|
|
|
8
10
|
import { AccountBotsService } from "./bots/AccountBotsService.js";
|
|
9
11
|
import "./bots/index.js";
|
|
10
12
|
import { rewardsCompressorAbi } from "../../abi/compressors/rewardsCompressor.js";
|
|
11
|
-
import { iBaseRewardPoolAbi } from "../../abi/iBaseRewardPool.js";
|
|
12
|
-
import { ierc4626AdapterAbi } from "../../abi/ierc4626Adapter.js";
|
|
13
13
|
import { expectedBalanceDeltas } from "../market/credit/expectedBalanceDeltas.js";
|
|
14
14
|
import "../market/index.js";
|
|
15
15
|
import { CreditAccountCompressor } from "./credit-account-compressor/CreditAccountCompressor.js";
|
|
@@ -7,7 +7,7 @@ import "./credit-account-compressor/index.js";
|
|
|
7
7
|
import { CreditAccountsServiceV310 } from "./CreditAccountsServiceV310.js";
|
|
8
8
|
import { isPhantomToken } from "./intents/utils/pick-token.js";
|
|
9
9
|
import { fetchCreditAccountSlice, toCreditAccountSlice } from "./intents/utils/credit-account-slice.js";
|
|
10
|
-
import { DIRECT_TRANSFERS_QUOTA, calcDefaultQuota, calcQuotaUpdate, calcRecommendedQuota, roundUpQuota } from "./quota-utils.js";
|
|
10
|
+
import { DIRECT_TRANSFERS_QUOTA, calcDefaultQuota, calcQuotaUpdate, calcRecommendedQuota, maxAmountForQuota, roundUpQuota } from "./quota-utils.js";
|
|
11
11
|
import { CreditAccountOperationsService } from "./intents/index.js";
|
|
12
12
|
import { LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS } from "./liquidations/constants.js";
|
|
13
13
|
import { LiquidationsService } from "./liquidations/LiquidationsService.js";
|
|
@@ -25,4 +25,4 @@ import { toWithdrawalStatus } from "./withdrawal-compressor/types.js";
|
|
|
25
25
|
import { WithdrawalCompressorV313Contract } from "./withdrawal-compressor/WithdrawalCompressorV313Contract.js";
|
|
26
26
|
import { createWithdrawalCompressor } from "./withdrawal-compressor/createWithdrawalCompressor.js";
|
|
27
27
|
import "./withdrawal-compressor/index.js";
|
|
28
|
-
export { AbstractWithdrawalCompressorContract, AccountBotsService, CreditAccountCompressor, CreditAccountCompressorV310Contract, CreditAccountOperationsService, CreditAccountsServiceV310, DELAYED_INTENT_TYPES, DELAYED_INTENT_VERSION, DIRECT_TRANSFERS_QUOTA, LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS, LiquidationsService, MultichainLiquidationsService, PeripheryCompressorV310Contract, RedemptionLoggerV310Contract, WithdrawalCompressorV310Contract, WithdrawalCompressorV311Contract, WithdrawalCompressorV313Contract, calcDefaultQuota, calcQuotaUpdate, calcRecommendedQuota, createRedemptionLogger, createWithdrawalCompressor, decodeDelayedIntent, encodeDelayedIntent, fetchCreditAccountSlice, getWithdrawalCompressorAddress, iCreditAccountAbi, isPhantomToken, roundUpQuota, toClaimableWithdrawal, toCreditAccountSlice, toPendingWithdrawal, toRequestableWithdrawal, toWithdrawalStatus };
|
|
28
|
+
export { AbstractWithdrawalCompressorContract, AccountBotsService, CreditAccountCompressor, CreditAccountCompressorV310Contract, CreditAccountOperationsService, CreditAccountsServiceV310, DELAYED_INTENT_TYPES, DELAYED_INTENT_VERSION, DIRECT_TRANSFERS_QUOTA, LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS, LiquidationsService, MultichainLiquidationsService, PeripheryCompressorV310Contract, RedemptionLoggerV310Contract, WithdrawalCompressorV310Contract, WithdrawalCompressorV311Contract, WithdrawalCompressorV313Contract, calcDefaultQuota, calcQuotaUpdate, calcRecommendedQuota, createRedemptionLogger, createWithdrawalCompressor, decodeDelayedIntent, encodeDelayedIntent, fetchCreditAccountSlice, getWithdrawalCompressorAddress, iCreditAccountAbi, isPhantomToken, maxAmountForQuota, roundUpQuota, toClaimableWithdrawal, toCreditAccountSlice, toPendingWithdrawal, toRequestableWithdrawal, toWithdrawalStatus };
|
|
@@ -52,7 +52,7 @@ function assertCanBorrow(sdk, suite, amount, options = {}) {
|
|
|
52
52
|
available: maxBorrowAmount.amount.value,
|
|
53
53
|
limit: maxBorrowAmount.limit,
|
|
54
54
|
underlying: toToken(sdk, suite.market.pool.underlying),
|
|
55
|
-
|
|
55
|
+
...options
|
|
56
56
|
}), `borrow: ${amount} exceeds what the pool can lend now (${maxBorrowAmount.amount.value})`);
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
@@ -81,6 +81,7 @@ function assertGrowthAllowed(args) {
|
|
|
81
81
|
token: toToken(sdk, token),
|
|
82
82
|
requested: void 0,
|
|
83
83
|
available: 0n,
|
|
84
|
+
...args.limits,
|
|
84
85
|
underlying: toToken(sdk, underlying)
|
|
85
86
|
}), `${token} takes no quota in this market, so it counts as no collateral`);
|
|
86
87
|
}
|
|
@@ -138,7 +139,7 @@ function assertCollateralised(healthFactorBps, safePrices, atSafePrices) {
|
|
|
138
139
|
* A quota can only be raised as far as the market still has room for: past the
|
|
139
140
|
* token's limit the keeper takes nothing more, whoever is asking.
|
|
140
141
|
*/
|
|
141
|
-
function assertQuotaAvailable(sdk, market, increases) {
|
|
142
|
+
function assertQuotaAvailable(sdk, market, increases, options = {}) {
|
|
142
143
|
const underlying = market.pool.underlying;
|
|
143
144
|
const { pqk } = market.pool;
|
|
144
145
|
for (const { token, balance } of increases) {
|
|
@@ -148,6 +149,7 @@ function assertQuotaAvailable(sdk, market, increases) {
|
|
|
148
149
|
token: toToken(sdk, token),
|
|
149
150
|
requested: balance,
|
|
150
151
|
available: left,
|
|
152
|
+
...options,
|
|
151
153
|
underlying: toToken(sdk, underlying)
|
|
152
154
|
}), `${token} has ${left} of quota left, the plan needs ${balance}`);
|
|
153
155
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LEVERAGE_DECIMALS } from "../../constants/math.js";
|
|
1
2
|
import { SDKConstruct } from "../../base/SDKConstruct.js";
|
|
2
3
|
import { unsupportedTokenPair } from "../../../model/errors/prepare-errors.js";
|
|
3
4
|
import { sdkErr } from "../../../model/result.js";
|
|
@@ -12,6 +13,7 @@ import { buildBorrowState } from "./borrow.js";
|
|
|
12
13
|
import { calcLeverageBand } from "./leverage-band.js";
|
|
13
14
|
import { maxBorrow } from "./maxBorrow.js";
|
|
14
15
|
import { maxWithdrawCollateral } from "./maxWithdrawCollateral.js";
|
|
16
|
+
import { strategyLimits } from "./strategyLimits.js";
|
|
15
17
|
import { buildOpenStrategyState } from "./open-strategy.js";
|
|
16
18
|
import { planAddCollateral, planAdjustLeverage, planAdjustLeverageDelayed, planDeposit, planRepay, planWithdraw, planWithdrawAsset, planWithdrawDelayed } from "./plan.js";
|
|
17
19
|
import { accountView } from "./view.js";
|
|
@@ -36,9 +38,25 @@ var CreditAccountOperationsService = class extends SDKConstruct {
|
|
|
36
38
|
* balance)
|
|
37
39
|
*/
|
|
38
40
|
async startIntent(props) {
|
|
41
|
+
const { intent, sdk, creditAccount, quotaReserve } = props;
|
|
42
|
+
let current;
|
|
43
|
+
let limits = {};
|
|
44
|
+
if (intent.type === "DEPOSIT" || intent.type === "ADJUST_LEVERAGE") {
|
|
45
|
+
current = accountView(creditAccount, sdk);
|
|
46
|
+
limits = strategyLimits({
|
|
47
|
+
...intent,
|
|
48
|
+
suite: sdk.marketRegister.findCreditManager(creditAccount.creditManager),
|
|
49
|
+
view: current,
|
|
50
|
+
initialQuotas: creditAccount.tokens,
|
|
51
|
+
quotaReserve
|
|
52
|
+
});
|
|
53
|
+
}
|
|
39
54
|
return plain(await this.#preview(props, () => {
|
|
40
55
|
const { intent } = props;
|
|
41
|
-
const view =
|
|
56
|
+
const view = {
|
|
57
|
+
...current ?? accountView(props.creditAccount, props.sdk),
|
|
58
|
+
limits
|
|
59
|
+
};
|
|
42
60
|
switch (intent.type) {
|
|
43
61
|
case "ADD_COLLATERAL": return planAddCollateral(intent);
|
|
44
62
|
case "WITHDRAW_ASSET": return planWithdrawAsset(intent, view);
|
|
@@ -48,7 +66,7 @@ var CreditAccountOperationsService = class extends SDKConstruct {
|
|
|
48
66
|
case "WITHDRAW": return planWithdraw(intent, view);
|
|
49
67
|
default: throw new Error(`${intent.type} - not implemented`);
|
|
50
68
|
}
|
|
51
|
-
}));
|
|
69
|
+
}, limits));
|
|
52
70
|
}
|
|
53
71
|
/**
|
|
54
72
|
* Both ends of what a `WITHDRAW` can take out, in underlying: the largest
|
|
@@ -190,14 +208,28 @@ var CreditAccountOperationsService = class extends SDKConstruct {
|
|
|
190
208
|
*/
|
|
191
209
|
async startDelayedIntent(props) {
|
|
192
210
|
const { intent } = props;
|
|
211
|
+
const current = accountView(props.creditAccount, props.sdk);
|
|
212
|
+
const repayFromSource = current.debt - current.balanceOf(current.underlying);
|
|
213
|
+
const maximum = intent.type === "ADJUST_LEVERAGE" && current.collateral > 0n && repayFromSource > 0n ? LEVERAGE_DECIMALS + (repayFromSource * LEVERAGE_DECIMALS - 1n) / current.collateral : void 0;
|
|
214
|
+
const limits = intent.type === "ADJUST_LEVERAGE" && maximum !== void 0 ? strategyLimits({
|
|
215
|
+
...intent,
|
|
216
|
+
suite: props.sdk.marketRegister.findCreditManager(props.creditAccount.creditManager),
|
|
217
|
+
view: current,
|
|
218
|
+
initialQuotas: props.creditAccount.tokens,
|
|
219
|
+
quotaReserve: props.quotaReserve,
|
|
220
|
+
maxLeverage: maximum
|
|
221
|
+
}) : {};
|
|
193
222
|
const result = await this.#preview(props, () => {
|
|
194
|
-
const view =
|
|
223
|
+
const view = {
|
|
224
|
+
...current,
|
|
225
|
+
limits
|
|
226
|
+
};
|
|
195
227
|
switch (intent.type) {
|
|
196
228
|
case "ADJUST_LEVERAGE": return planAdjustLeverageDelayed(intent, view);
|
|
197
229
|
case "WITHDRAW": return planWithdrawDelayed(intent, view);
|
|
198
230
|
default: throw new Error(`${intent.type} - cannot be delayed`);
|
|
199
231
|
}
|
|
200
|
-
});
|
|
232
|
+
}, limits);
|
|
201
233
|
if (!result.ok) return result;
|
|
202
234
|
const { delayed } = result;
|
|
203
235
|
if (!delayed) throw new Error("startDelayedIntent: plan started no withdrawal");
|
|
@@ -213,7 +245,8 @@ var CreditAccountOperationsService = class extends SDKConstruct {
|
|
|
213
245
|
delayed,
|
|
214
246
|
creditAccount: props.creditAccount,
|
|
215
247
|
sdk: props.sdk,
|
|
216
|
-
quotaReserve: props.quotaReserve
|
|
248
|
+
quotaReserve: props.quotaReserve,
|
|
249
|
+
limits
|
|
217
250
|
});
|
|
218
251
|
return {
|
|
219
252
|
...result,
|
|
@@ -399,7 +432,7 @@ var CreditAccountOperationsService = class extends SDKConstruct {
|
|
|
399
432
|
}
|
|
400
433
|
}
|
|
401
434
|
/** Plan → realise → wrap. Unviable requests become `{ ok: false }`. */
|
|
402
|
-
async #preview(props, plan) {
|
|
435
|
+
async #preview(props, plan, limits = {}) {
|
|
403
436
|
const draft = props.draft ?? {};
|
|
404
437
|
try {
|
|
405
438
|
const suite = props.sdk.marketRegister.findCreditManager(props.creditAccount.creditManager);
|
|
@@ -410,7 +443,8 @@ var CreditAccountOperationsService = class extends SDKConstruct {
|
|
|
410
443
|
sdk: props.sdk,
|
|
411
444
|
slippage: props.slippage ?? 0,
|
|
412
445
|
quotaReserve: props.quotaReserve,
|
|
413
|
-
draft
|
|
446
|
+
draft,
|
|
447
|
+
limits
|
|
414
448
|
});
|
|
415
449
|
return {
|
|
416
450
|
ok: true,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { BigIntMath } from "../../utils/bigint-math.js";
|
|
2
|
-
import { LEVERAGE_DECIMALS,
|
|
3
|
-
import "../../constants/index.js";
|
|
2
|
+
import { LEVERAGE_DECIMALS, PERCENTAGE_FACTOR } from "../../constants/math.js";
|
|
4
3
|
import { insufficientBalance } from "../../../model/errors/operation-errors.js";
|
|
5
4
|
import "../../../model/index.js";
|
|
6
5
|
import { toToken } from "../../validation/helpers/token.js";
|
|
@@ -58,53 +57,14 @@ function assertLeverageAtLeastOne(leverage) {
|
|
|
58
57
|
* may end owing nothing, an opening may not.
|
|
59
58
|
*/
|
|
60
59
|
function assertDebtLimits(sdk, debt, debtLimits, underlying, options = {}) {
|
|
61
|
-
const { allowZero = true,
|
|
60
|
+
const { allowZero = true, ...rest } = options;
|
|
62
61
|
raise(checkDebtLimits({
|
|
63
62
|
debt,
|
|
64
|
-
|
|
65
|
-
maxDebt: debtLimits.maxDebt,
|
|
63
|
+
...debtLimits,
|
|
66
64
|
underlying: toToken(sdk, underlying),
|
|
67
65
|
allowZero,
|
|
68
|
-
|
|
69
|
-
maxBorrowAmount
|
|
66
|
+
...rest
|
|
70
67
|
}), debt > debtLimits.maxDebt ? `debt ${debt} exceeds maxDebt ${debtLimits.maxDebt}` : `debt ${debt} is below minDebt ${debtLimits.minDebt}`);
|
|
71
68
|
}
|
|
72
|
-
/** Finds single-token Open amounts whose projected debt fits the market limits. */
|
|
73
|
-
function openCollateralForDebtLimits({ suite, collateral, leverage }) {
|
|
74
|
-
if (collateral.length !== 1 || leverage <= 100n) return void 0;
|
|
75
|
-
const [{ token }] = collateral;
|
|
76
|
-
const { market } = suite;
|
|
77
|
-
const limits = {
|
|
78
|
-
minDebt: suite.creditFacade.minDebt,
|
|
79
|
-
maxDebt: suite.maxBorrowAmount().amount.value
|
|
80
|
-
};
|
|
81
|
-
if (limits.maxDebt < limits.minDebt) return void 0;
|
|
82
|
-
const debtAt = (amount) => {
|
|
83
|
-
const converted = market.priceOracle.safeConvert(token, market.pool.underlying, amount);
|
|
84
|
-
return converted.error ? void 0 : debtForLeverage(converted.value, leverage);
|
|
85
|
-
};
|
|
86
|
-
const lastDebt = debtAt(MAX_UINT256);
|
|
87
|
-
if (lastDebt === void 0 || lastDebt < limits.minDebt) return void 0;
|
|
88
|
-
const firstAtLeast = (threshold) => {
|
|
89
|
-
let low = 0n;
|
|
90
|
-
let high = MAX_UINT256;
|
|
91
|
-
while (low < high) {
|
|
92
|
-
const middle = (low + high) / 2n;
|
|
93
|
-
const debt = debtAt(middle);
|
|
94
|
-
if (debt === void 0) return void 0;
|
|
95
|
-
if (debt < threshold) low = middle + 1n;
|
|
96
|
-
else high = middle;
|
|
97
|
-
}
|
|
98
|
-
return low;
|
|
99
|
-
};
|
|
100
|
-
const min = firstAtLeast(limits.minDebt > 0n ? limits.minDebt : 1n);
|
|
101
|
-
const above = lastDebt > limits.maxDebt ? firstAtLeast(limits.maxDebt + 1n) : void 0;
|
|
102
|
-
if (min === void 0 || lastDebt > limits.maxDebt && above === void 0) return void 0;
|
|
103
|
-
const max = above === void 0 ? MAX_UINT256 : above - 1n;
|
|
104
|
-
return min <= max ? {
|
|
105
|
-
min: market.priceOracle.toTokenAmount(token, min),
|
|
106
|
-
max: market.priceOracle.toTokenAmount(token, max)
|
|
107
|
-
} : void 0;
|
|
108
|
-
}
|
|
109
69
|
//#endregion
|
|
110
|
-
export { assertDebtLimits, assertLeverageAtLeastOne, debtForLeverage, maxProportionalWithdrawal,
|
|
70
|
+
export { assertDebtLimits, assertLeverageAtLeastOne, debtForLeverage, maxProportionalWithdrawal, proportionalDebt };
|
|
@@ -85,7 +85,13 @@ function maxBorrow(props) {
|
|
|
85
85
|
if (lends < suite.creditFacade.minDebt) return 0n;
|
|
86
86
|
const ceiling = BigIntMath.min(priceOracle.safeConvertFromUSD(underlying, backed / targetHF).value, lends);
|
|
87
87
|
const unwrapsPayout = !!rwaAsset && eq(borrowToken, rwaAsset);
|
|
88
|
-
|
|
88
|
+
if (eq(borrowToken, underlying)) return ceiling;
|
|
89
|
+
if (unwrapsPayout) return toTargetDecimals(ceiling, underlying, borrowToken, sdk);
|
|
90
|
+
const payout = priceOracle.safeConvert(underlying, borrowToken, ceiling);
|
|
91
|
+
if (payout.error) return 0n;
|
|
92
|
+
const debt = priceOracle.safeConvert(borrowToken, underlying, payout.value);
|
|
93
|
+
if (debt.error) return 0n;
|
|
94
|
+
return BigIntMath.max(payout.value - (debt.value > ceiling ? 1n : 0n), 0n);
|
|
89
95
|
}
|
|
90
96
|
//#endregion
|
|
91
97
|
export { maxBorrow };
|
|
@@ -2,12 +2,13 @@ import { insufficientBalance } from "../../../model/errors/operation-errors.js";
|
|
|
2
2
|
import "../../../model/index.js";
|
|
3
3
|
import { IntentPreviewError } from "../../validation/raise.js";
|
|
4
4
|
import { assertCanBorrow, assertCollateralised, assertGrowthAllowed, assertMarketOperable, assertQuotaAvailable } from "./guards.js";
|
|
5
|
-
import { assertDebtLimits, assertLeverageAtLeastOne, debtForLeverage
|
|
5
|
+
import { assertDebtLimits, assertLeverageAtLeastOne, debtForLeverage } from "./math.js";
|
|
6
6
|
import { unopenedAccountSlice } from "./utils/credit-account-slice.js";
|
|
7
7
|
import { collectPriceImpact } from "./utils/price-impact.js";
|
|
8
8
|
import { getQuotasForUpdate } from "./utils/quotas-for-update.js";
|
|
9
9
|
import { createRouterPaths } from "./utils/router-path.js";
|
|
10
10
|
import "./utils/index.js";
|
|
11
|
+
import { strategyLimits } from "./strategyLimits.js";
|
|
11
12
|
//#region src/onchain/accounts/intents/open-strategy.ts
|
|
12
13
|
/**
|
|
13
14
|
* Builds the state opening a leveraged position out of wallet collateral would
|
|
@@ -44,17 +45,20 @@ async function buildOpenStrategyState(props) {
|
|
|
44
45
|
creditFacade: suite.creditFacade.address,
|
|
45
46
|
underlying
|
|
46
47
|
});
|
|
47
|
-
const
|
|
48
|
+
const options = leftoverBalances.length || existing?.tokens.some((t) => t.balance > 0n) ? void 0 : strategyLimits({
|
|
49
|
+
type: "OPEN",
|
|
48
50
|
suite,
|
|
49
51
|
collateral,
|
|
50
|
-
leverage
|
|
52
|
+
leverage,
|
|
53
|
+
targetToken,
|
|
54
|
+
quotaReserve
|
|
51
55
|
});
|
|
52
56
|
assertDebtLimits(sdk, debt, suite.creditFacade, underlying, {
|
|
57
|
+
...options,
|
|
53
58
|
allowZero: false,
|
|
54
|
-
maxBorrowAmount: suite.maxBorrowAmount()
|
|
55
|
-
getCollateralLimits
|
|
59
|
+
maxBorrowAmount: suite.maxBorrowAmount()
|
|
56
60
|
});
|
|
57
|
-
assertCanBorrow(sdk, suite, debt,
|
|
61
|
+
assertCanBorrow(sdk, suite, debt, options);
|
|
58
62
|
const paths = createRouterPaths({
|
|
59
63
|
sdk,
|
|
60
64
|
creditAccount: account,
|
|
@@ -123,9 +127,10 @@ async function buildOpenStrategyState(props) {
|
|
|
123
127
|
suite,
|
|
124
128
|
market,
|
|
125
129
|
before: [],
|
|
126
|
-
after: averageAssets
|
|
130
|
+
after: averageAssets,
|
|
131
|
+
limits: options
|
|
127
132
|
});
|
|
128
|
-
assertQuotaAvailable(sdk, market, averageQuota);
|
|
133
|
+
assertQuotaAvailable(sdk, market, averageQuota, options);
|
|
129
134
|
const projection = reached ?? settle();
|
|
130
135
|
assertCollateralised(projection.healthFactor, false);
|
|
131
136
|
const priceImpact = await collectPriceImpact(leg.probe ? [leg.probe] : [], {
|
|
@@ -42,7 +42,7 @@ function planDeposit(intent, view) {
|
|
|
42
42
|
const aU = view.price(intent.token, U, intent.amount);
|
|
43
43
|
const debtDelta = intent.targetLeverage === void 0 ? proportionalDebt(view, aU) : debtForLeverage(view.collateral + aU, intent.targetLeverage) - view.debt;
|
|
44
44
|
if (debtDelta < 0n) throw new IntentPreviewError(leverageOutOfRange(), `deposit: target leverage ${intent.targetLeverage} would require repaying debt`);
|
|
45
|
-
assertDebtLimits(view.sdk, view.debt + debtDelta, view.debtLimits, U);
|
|
45
|
+
assertDebtLimits(view.sdk, view.debt + debtDelta, view.debtLimits, U, view.limits);
|
|
46
46
|
const T = intent.positionToken ?? positionToken(view, "deposit");
|
|
47
47
|
const depositStays = eq(intent.token, T);
|
|
48
48
|
return [
|
|
@@ -77,7 +77,7 @@ function planRepay(intent, view) {
|
|
|
77
77
|
}), "repay: the account owes nothing");
|
|
78
78
|
const funding = everything(intent.amount) ? view.price(U, intent.token, withMargin(view.debt)) : intent.amount;
|
|
79
79
|
const repaid = min(view.price(intent.token, U, funding), view.debt);
|
|
80
|
-
assertDebtLimits(view.sdk, view.debt - repaid, view.debtLimits, view.underlying);
|
|
80
|
+
assertDebtLimits(view.sdk, view.debt - repaid, view.debtLimits, view.underlying, view.limits);
|
|
81
81
|
return [
|
|
82
82
|
add(intent.token, funding, intent.value),
|
|
83
83
|
...fundsInU ? [] : [convert(intent.token, U, funding)],
|
|
@@ -306,7 +306,7 @@ function withdrawShape(intent, view) {
|
|
|
306
306
|
};
|
|
307
307
|
}
|
|
308
308
|
const dD = proportionalDebt(view, WU);
|
|
309
|
-
assertDebtLimits(view.sdk, view.debt - dD, view.debtLimits, view.underlying);
|
|
309
|
+
assertDebtLimits(view.sdk, view.debt - dD, view.debtLimits, view.underlying, view.limits);
|
|
310
310
|
return {
|
|
311
311
|
U,
|
|
312
312
|
T,
|
|
@@ -325,7 +325,7 @@ function leverageShape(intent, view) {
|
|
|
325
325
|
assertLeverageAtLeastOne(intent.targetLeverage);
|
|
326
326
|
if (view.collateral <= 0n) throw new IntentPreviewError(insufficientBalance(), "adjustLeverage: account has no collateral to lever");
|
|
327
327
|
const target = debtForLeverage(view.collateral, intent.targetLeverage);
|
|
328
|
-
assertDebtLimits(view.sdk, target, view.debtLimits, view.underlying);
|
|
328
|
+
assertDebtLimits(view.sdk, target, view.debtLimits, view.underlying, view.limits);
|
|
329
329
|
return {
|
|
330
330
|
U: view.underlying,
|
|
331
331
|
delta: target - view.debt
|
|
@@ -130,7 +130,7 @@ async function realize(steps, props) {
|
|
|
130
130
|
}));
|
|
131
131
|
break;
|
|
132
132
|
case "borrow":
|
|
133
|
-
assertCanBorrow(sdk, suite, step.amount);
|
|
133
|
+
assertCanBorrow(sdk, suite, step.amount, props.limits);
|
|
134
134
|
push(buildIncreaseDebtOperation({
|
|
135
135
|
amount: step.amount,
|
|
136
136
|
creditAccount,
|
|
@@ -394,10 +394,11 @@ async function realize(steps, props) {
|
|
|
394
394
|
suite,
|
|
395
395
|
market,
|
|
396
396
|
before: creditAccount.tokens,
|
|
397
|
-
after: projected.assets
|
|
397
|
+
after: projected.assets,
|
|
398
|
+
limits: props.limits
|
|
398
399
|
});
|
|
399
400
|
if (!cleared && quotas.quotaIncrease.length + quotas.quotaDecrease.length > 0) {
|
|
400
|
-
assertQuotaAvailable(sdk, market, quotas.quotaIncrease);
|
|
401
|
+
assertQuotaAvailable(sdk, market, quotas.quotaIncrease, props.limits);
|
|
401
402
|
push(buildQuotaUpdateOperation({
|
|
402
403
|
update: quotas,
|
|
403
404
|
creditAccount,
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { BigIntMath } from "../../utils/bigint-math.js";
|
|
2
|
+
import { LEVERAGE_DECIMALS, MAX_UINT256 } from "../../constants/math.js";
|
|
3
|
+
import "../../constants/index.js";
|
|
4
|
+
import { quotaIncreaseLimit } from "./utils/quotas-for-update.js";
|
|
5
|
+
//#region src/onchain/accounts/intents/strategyLimits.ts
|
|
6
|
+
/** Independent input bounds supplied to debt, liquidity and quota errors. */
|
|
7
|
+
function strategyLimits(props) {
|
|
8
|
+
const { suite, quotaReserve } = props;
|
|
9
|
+
const { market } = suite;
|
|
10
|
+
const { priceOracle: oracle } = market;
|
|
11
|
+
switch (props.type) {
|
|
12
|
+
case "OPEN": {
|
|
13
|
+
const { collateral, leverage, targetToken } = props;
|
|
14
|
+
if (collateral.length !== 1 || leverage <= 100n) return {};
|
|
15
|
+
const [{ token }] = collateral;
|
|
16
|
+
const minDebt = suite.creditFacade.minDebt;
|
|
17
|
+
const maxDebt = suite.maxBorrowAmount().amount.value;
|
|
18
|
+
if (maxDebt < minDebt) return {};
|
|
19
|
+
const minCollateralForDebt = (debt) => {
|
|
20
|
+
const collateralUnderlying = BigIntMath.ceilDiv(debt * LEVERAGE_DECIMALS, leverage - LEVERAGE_DECIMALS);
|
|
21
|
+
const result = oracle.safeConvert(market.pool.underlying, token, collateralUnderlying - 1n);
|
|
22
|
+
if (result.error) return void 0;
|
|
23
|
+
const valuation = oracle.safeConvert(token, market.pool.underlying, result.value);
|
|
24
|
+
if (valuation.error) return void 0;
|
|
25
|
+
const collateral = result.value + (valuation.value < collateralUnderlying ? 1n : 0n);
|
|
26
|
+
const checked = oracle.safeConvert(token, market.pool.underlying, collateral);
|
|
27
|
+
return checked.error || checked.value < collateralUnderlying ? void 0 : collateral;
|
|
28
|
+
};
|
|
29
|
+
if (oracle.safeConvert(token, market.pool.underlying, 1n).error) return {};
|
|
30
|
+
const minCollateral = minCollateralForDebt(BigIntMath.max(minDebt, 1n));
|
|
31
|
+
const excessCollateral = minCollateralForDebt(maxDebt + 1n);
|
|
32
|
+
if (minCollateral === void 0 || excessCollateral === void 0 || minCollateral > 115792089237316195423570985008687907853269984665640564039457584007913129639935n) return {};
|
|
33
|
+
const maxCollateral = BigIntMath.min(MAX_UINT256, excessCollateral - 1n);
|
|
34
|
+
let maxCollateralByQuota;
|
|
35
|
+
if (!market.isUnderlyingLike(targetToken) && !market.pool.pqk.hasActiveQuota(targetToken)) maxCollateralByQuota = 0n;
|
|
36
|
+
else {
|
|
37
|
+
const quotaResult = quotaIncreaseLimit({
|
|
38
|
+
suite,
|
|
39
|
+
token: targetToken,
|
|
40
|
+
balance: 0n,
|
|
41
|
+
initialQuotas: [],
|
|
42
|
+
quotaReserve
|
|
43
|
+
});
|
|
44
|
+
if (!quotaResult.error && quotaResult.value !== void 0) {
|
|
45
|
+
const excessUnderlying = BigIntMath.ceilDiv((BigIntMath.max(quotaResult.value, 0n) + 1n) * LEVERAGE_DECIMALS, leverage);
|
|
46
|
+
const result = oracle.safeConvert(market.pool.underlying, token, excessUnderlying - 1n);
|
|
47
|
+
if (!result.error) {
|
|
48
|
+
const valuation = oracle.safeConvert(token, market.pool.underlying, result.value);
|
|
49
|
+
if (!valuation.error) {
|
|
50
|
+
const collateral = result.value - (valuation.value >= excessUnderlying ? 1n : 0n);
|
|
51
|
+
maxCollateralByQuota = BigIntMath.min(MAX_UINT256, BigIntMath.max(collateral, 0n));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
collateralLimits: minCollateral <= maxCollateral ? {
|
|
58
|
+
min: oracle.toTokenAmount(token, minCollateral),
|
|
59
|
+
max: oracle.toTokenAmount(token, maxCollateral)
|
|
60
|
+
} : void 0,
|
|
61
|
+
quotaLimits: maxCollateralByQuota === void 0 ? void 0 : { collateralMax: oracle.toTokenAmount(token, maxCollateralByQuota) }
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
case "DEPOSIT": {
|
|
65
|
+
const { view, token, positionToken, initialQuotas, targetLeverage } = props;
|
|
66
|
+
if (targetLeverage !== void 0 || view.collateral <= 0n) return {};
|
|
67
|
+
const minDebt = BigIntMath.max(view.debt, suite.creditFacade.minDebt);
|
|
68
|
+
const maxDebt = BigIntMath.min(suite.creditFacade.maxDebt, view.debt + suite.maxBorrowAmount().amount.value);
|
|
69
|
+
const minCollateralForDebt = (debt) => {
|
|
70
|
+
if (debt <= view.debt) return 0n;
|
|
71
|
+
if (view.debt === 0n) return void 0;
|
|
72
|
+
const collateralUnderlying = BigIntMath.ceilDiv((debt - view.debt) * view.collateral, view.debt);
|
|
73
|
+
const result = oracle.safeConvert(view.underlying, token, collateralUnderlying - 1n);
|
|
74
|
+
if (result.error) return void 0;
|
|
75
|
+
const valuation = oracle.safeConvert(token, view.underlying, result.value);
|
|
76
|
+
if (valuation.error) return void 0;
|
|
77
|
+
const collateral = result.value + (valuation.value < collateralUnderlying ? 1n : 0n);
|
|
78
|
+
const checked = oracle.safeConvert(token, view.underlying, collateral);
|
|
79
|
+
return checked.error || checked.value < collateralUnderlying ? void 0 : collateral;
|
|
80
|
+
};
|
|
81
|
+
const debtFloorCollateral = minCollateralForDebt(minDebt);
|
|
82
|
+
const minCollateral = debtFloorCollateral === void 0 ? void 0 : BigIntMath.max(1n, debtFloorCollateral);
|
|
83
|
+
const excessCollateral = debtFloorCollateral === void 0 ? void 0 : minCollateralForDebt(maxDebt + 1n);
|
|
84
|
+
const maxCollateral = excessCollateral === void 0 ? MAX_UINT256 : BigIntMath.min(MAX_UINT256, excessCollateral - 1n);
|
|
85
|
+
const position = positionToken ?? view.fattest([view.underlying]);
|
|
86
|
+
let maxCollateralByQuota;
|
|
87
|
+
if (position) {
|
|
88
|
+
if (!market.isUnderlyingLike(position) && !market.pool.pqk.hasActiveQuota(position)) maxCollateralByQuota = 0n;
|
|
89
|
+
else {
|
|
90
|
+
const quotaResult = quotaIncreaseLimit({
|
|
91
|
+
suite,
|
|
92
|
+
token: position,
|
|
93
|
+
balance: view.balanceOf(position),
|
|
94
|
+
initialQuotas,
|
|
95
|
+
quotaReserve,
|
|
96
|
+
rwaAsset: view.rwaAsset
|
|
97
|
+
});
|
|
98
|
+
maxCollateralByQuota = MAX_UINT256;
|
|
99
|
+
if (!quotaResult.error && quotaResult.value !== void 0) {
|
|
100
|
+
const excessUnderlying = BigIntMath.ceilDiv((quotaResult.value + 1n) * view.collateral, view.collateral + view.debt);
|
|
101
|
+
const result = oracle.safeConvert(view.underlying, token, BigIntMath.max(excessUnderlying - 1n, 0n));
|
|
102
|
+
maxCollateralByQuota = void 0;
|
|
103
|
+
if (!result.error) {
|
|
104
|
+
const valuation = oracle.safeConvert(token, view.underlying, result.value);
|
|
105
|
+
if (!valuation.error) {
|
|
106
|
+
const collateral = result.value - (valuation.value >= excessUnderlying ? 1n : 0n);
|
|
107
|
+
maxCollateralByQuota = BigIntMath.min(MAX_UINT256, BigIntMath.max(collateral, 0n));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
collateralLimits: minCollateral !== void 0 && minCollateral <= maxCollateral ? {
|
|
115
|
+
min: oracle.toTokenAmount(token, minCollateral),
|
|
116
|
+
max: oracle.toTokenAmount(token, maxCollateral)
|
|
117
|
+
} : void 0,
|
|
118
|
+
quotaLimits: maxCollateralByQuota === void 0 ? void 0 : { collateralMax: oracle.toTokenAmount(token, maxCollateralByQuota) }
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
case "ADJUST_LEVERAGE": {
|
|
122
|
+
const { view, token, initialQuotas, targetLeverage, maxLeverage = MAX_UINT256 } = props;
|
|
123
|
+
if (view.collateral <= 0n || targetLeverage < 100n) return {};
|
|
124
|
+
const maxDebt = BigIntMath.min(suite.creditFacade.maxDebt, view.debt + suite.maxBorrowAmount().amount.value);
|
|
125
|
+
const minLeverage = BigIntMath.max(LEVERAGE_DECIMALS + 1n, LEVERAGE_DECIMALS + BigIntMath.ceilDiv(suite.creditFacade.minDebt * LEVERAGE_DECIMALS, view.collateral));
|
|
126
|
+
const debtMaxLeverage = BigIntMath.min(maxLeverage, LEVERAGE_DECIMALS + BigIntMath.ceilDiv((maxDebt + 1n) * LEVERAGE_DECIMALS, view.collateral) - 1n);
|
|
127
|
+
const position = token ?? view.fattest([view.underlying]);
|
|
128
|
+
let maxLeverageByQuota;
|
|
129
|
+
if (position) {
|
|
130
|
+
if (!market.isUnderlyingLike(position) && !market.pool.pqk.hasActiveQuota(position)) maxLeverageByQuota = LEVERAGE_DECIMALS;
|
|
131
|
+
else {
|
|
132
|
+
const quotaResult = quotaIncreaseLimit({
|
|
133
|
+
suite,
|
|
134
|
+
token: position,
|
|
135
|
+
balance: view.balanceOf(position),
|
|
136
|
+
initialQuotas,
|
|
137
|
+
quotaReserve,
|
|
138
|
+
rwaAsset: view.rwaAsset
|
|
139
|
+
});
|
|
140
|
+
maxLeverageByQuota = maxLeverage;
|
|
141
|
+
if (!quotaResult.error && quotaResult.value !== void 0) {
|
|
142
|
+
const quotaMaxDebt = view.debt + quotaResult.value;
|
|
143
|
+
maxLeverageByQuota = BigIntMath.min(maxLeverage, LEVERAGE_DECIMALS + BigIntMath.ceilDiv((quotaMaxDebt + 1n) * LEVERAGE_DECIMALS, view.collateral) - 1n);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
leverageLimits: minLeverage <= debtMaxLeverage ? {
|
|
149
|
+
min: minLeverage,
|
|
150
|
+
max: debtMaxLeverage
|
|
151
|
+
} : void 0,
|
|
152
|
+
quotaLimits: maxLeverageByQuota === void 0 ? void 0 : { leverageMax: maxLeverageByQuota }
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
//#endregion
|
|
158
|
+
export { strategyLimits };
|