@gearbox-protocol/sdk 17.10.0 → 17.10.1-next.2
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 +44 -11
- package/dist/cjs/onchain/accounts/intents/leverage-band.js +49 -8
- 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 +6 -2
- 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/intents/withdraw-limits.js +1 -1
- 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/cjs/sdk/prepare/PrepareApi.js +3 -2
- 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 +44 -11
- package/dist/esm/onchain/accounts/intents/leverage-band.js +50 -9
- 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 +6 -2
- 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/intents/withdraw-limits.js +1 -1
- 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/esm/sdk/prepare/PrepareApi.js +3 -2
- 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/index.d.ts +2 -3
- package/dist/types/onchain/accounts/intents/leverage-band.d.ts +8 -6
- 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/dist/types/sdk/prepare/PrepareApi.d.ts +1 -1
- package/dist/types/sdk/prepare/types.d.ts +3 -4
- package/package.json +1 -1
|
@@ -24,6 +24,7 @@ exports.isPhantomToken = require_onchain_accounts_intents_utils_pick_token.isPha
|
|
|
24
24
|
exports.isRedemptionPhantomToken = require_onchain_accounts_intents_utils_pick_token.isRedemptionPhantomToken;
|
|
25
25
|
exports.lossRate = require_onchain_accounts_intents_utils_price_impact.lossRate;
|
|
26
26
|
exports.pickFattestNonPhantomToken = require_onchain_accounts_intents_utils_pick_token.pickFattestNonPhantomToken;
|
|
27
|
+
exports.quotaIncreaseLimit = require_onchain_accounts_intents_utils_quotas_for_update.quotaIncreaseLimit;
|
|
27
28
|
exports.quotasAfterUpdate = require_onchain_accounts_intents_utils_quotas_for_update.quotasAfterUpdate;
|
|
28
29
|
exports.rankAccountTokens = require_onchain_accounts_intents_utils_pick_token.rankAccountTokens;
|
|
29
30
|
exports.resolveCreditManager = require_onchain_accounts_intents_utils_common.resolveCreditManager;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_onchain_utils_bigint_math = require("../../../utils/bigint-math.js");
|
|
2
3
|
const require_onchain_constants_math = require("../../../constants/math.js");
|
|
3
4
|
const require_onchain_utils_mappers = require("../../../utils/mappers.js");
|
|
5
|
+
require("../../../constants/index.js");
|
|
4
6
|
const require_onchain_accounts_quota_utils = require("../../quota-utils.js");
|
|
5
7
|
//#region src/onchain/accounts/intents/utils/quotas-for-update.ts
|
|
6
8
|
function getQuotasForUpdate({ assetsBefore, assetsAfter, initialQuotas, quotaReserve = 0, liquidationThresholds: liquidationThresholdsMap, quotas: quotasMap, maxDebt, underlyingToken, convert }) {
|
|
@@ -195,8 +197,45 @@ function constructAssetRecord(a) {
|
|
|
195
197
|
return acc;
|
|
196
198
|
}, {});
|
|
197
199
|
}
|
|
200
|
+
/** Largest additional underlying amount whose purchase fits this token's quota. */
|
|
201
|
+
function quotaIncreaseLimit({ suite, token, balance, initialQuotas, quotaReserve = 0, rwaAsset }) {
|
|
202
|
+
const { market } = suite;
|
|
203
|
+
if (market.isUnderlyingLike(token)) return { value: void 0 };
|
|
204
|
+
const oracle = market.priceOracle;
|
|
205
|
+
const purchaseResult = oracle.safeConvert(market.pool.underlying, token, require_onchain_constants_math.MAX_UINT256);
|
|
206
|
+
if (purchaseResult.error) return purchaseResult;
|
|
207
|
+
const valuationResult = oracle.safeConvert(token, market.pool.underlying, require_onchain_constants_math.MAX_UINT256);
|
|
208
|
+
if (valuationResult.error) return valuationResult;
|
|
209
|
+
if (purchaseResult.value === 0n || valuationResult.value === 0n) return { value: void 0 };
|
|
210
|
+
const maxQuotaValue = require_onchain_accounts_quota_utils.maxAmountForQuota({
|
|
211
|
+
available: market.pool.pqk.quotaAvailable(token),
|
|
212
|
+
initialQuota: initialQuotas.find((q) => q.token.toLowerCase() === token.toLowerCase())?.quota ?? 0n,
|
|
213
|
+
totalInitialQuota: initialQuotas.reduce((sum, q) => sum + require_onchain_accounts_quota_utils.roundUpQuota(q.quota), 0n),
|
|
214
|
+
maxDebt: suite.creditFacade.maxDebt,
|
|
215
|
+
lt: BigInt(suite.creditManager.liquidationThresholds.get(token) ?? 0),
|
|
216
|
+
quotaReserve: BigInt(quotaReserve)
|
|
217
|
+
});
|
|
218
|
+
if (maxQuotaValue === void 0) return { value: void 0 };
|
|
219
|
+
const quotaBalanceResult = oracle.safeConvert(market.pool.underlying, token, maxQuotaValue);
|
|
220
|
+
if (quotaBalanceResult.error) return quotaBalanceResult;
|
|
221
|
+
const quotaValueResult = oracle.safeConvert(token, market.pool.underlying, quotaBalanceResult.value);
|
|
222
|
+
if (quotaValueResult.error) return quotaValueResult;
|
|
223
|
+
const availableTokenIncrease = quotaBalanceResult.value - (quotaValueResult.value > maxQuotaValue ? 1n : 0n) - balance;
|
|
224
|
+
const excessTokenIncrease = require_onchain_utils_bigint_math.BigIntMath.max(availableTokenIncrease, 0n) + 1n;
|
|
225
|
+
if (rwaAsset?.toLowerCase() === token.toLowerCase()) {
|
|
226
|
+
const underlyingScale = 10n ** BigInt(suite.sdk.tokensMeta.decimals(market.pool.underlying));
|
|
227
|
+
const tokenScale = 10n ** BigInt(suite.sdk.tokensMeta.decimals(token));
|
|
228
|
+
return { value: require_onchain_utils_bigint_math.BigIntMath.ceilDiv(excessTokenIncrease * underlyingScale, tokenScale) - 1n };
|
|
229
|
+
}
|
|
230
|
+
const increaseResult = oracle.safeConvert(token, market.pool.underlying, excessTokenIncrease - 1n);
|
|
231
|
+
if (increaseResult.error) return increaseResult;
|
|
232
|
+
const purchaseValue = oracle.safeConvert(market.pool.underlying, token, increaseResult.value);
|
|
233
|
+
if (purchaseValue.error) return purchaseValue;
|
|
234
|
+
return { value: increaseResult.value - (purchaseValue.value >= excessTokenIncrease ? 1n : 0n) };
|
|
235
|
+
}
|
|
198
236
|
//#endregion
|
|
199
237
|
exports.clearedQuotas = clearedQuotas;
|
|
200
238
|
exports.getQuotasForUpdate = getQuotasForUpdate;
|
|
239
|
+
exports.quotaIncreaseLimit = quotaIncreaseLimit;
|
|
201
240
|
exports.quotasAfterUpdate = quotasAfterUpdate;
|
|
202
241
|
exports.withDirectTransferQuota = withDirectTransferQuota;
|
|
@@ -5,8 +5,8 @@ require("../../validation/helpers/health-factor-limits.js");
|
|
|
5
5
|
require("../../validation/index.js");
|
|
6
6
|
const require_onchain_accounts_intents_utils_common = require("./utils/common.js");
|
|
7
7
|
const require_onchain_accounts_intents_math = require("./math.js");
|
|
8
|
-
const require_onchain_accounts_intents_collateral_valuation = require("./collateral-valuation.js");
|
|
9
8
|
const require_onchain_accounts_intents_view = require("./view.js");
|
|
9
|
+
const require_onchain_accounts_intents_collateral_valuation = require("./collateral-valuation.js");
|
|
10
10
|
//#region src/onchain/accounts/intents/withdraw-limits.ts
|
|
11
11
|
/**
|
|
12
12
|
* Every limit a `WITHDRAW` answers to, in underlying units.
|
|
@@ -43,6 +43,14 @@ function calcRecommendedQuota({ amount, debt, lt, quotaReserve }) {
|
|
|
43
43
|
function calcDefaultQuota({ amount, lt, quotaReserve }) {
|
|
44
44
|
return roundUpQuota(amount * lt / require_onchain_constants_math.PERCENTAGE_FACTOR * (require_onchain_constants_math.PERCENTAGE_FACTOR + quotaReserve) / require_onchain_constants_math.PERCENTAGE_FACTOR);
|
|
45
45
|
}
|
|
46
|
+
/** Inverse of default quota rounding, including the account-wide increase cap. */
|
|
47
|
+
function maxAmountForQuota({ available, initialQuota, totalInitialQuota, maxDebt, lt, quotaReserve }) {
|
|
48
|
+
const increaseCap = roundUpQuota(require_onchain_utils_bigint_math.BigIntMath.max(roundUpQuota(maxDebt * 2n) - totalInitialQuota, 0n));
|
|
49
|
+
if (lt === 0n || increaseCap <= available) return void 0;
|
|
50
|
+
const desired = roundUpQuota(initialQuota) + roundUpQuota(available) + require_onchain_constants_math.PERCENTAGE_FACTOR - 1n;
|
|
51
|
+
const base = require_onchain_utils_bigint_math.BigIntMath.ceilDiv((desired + 1n) * require_onchain_constants_math.PERCENTAGE_FACTOR, require_onchain_constants_math.PERCENTAGE_FACTOR + quotaReserve) - 1n;
|
|
52
|
+
return require_onchain_utils_bigint_math.BigIntMath.ceilDiv((base + 1n) * require_onchain_constants_math.PERCENTAGE_FACTOR, lt) - 1n;
|
|
53
|
+
}
|
|
46
54
|
/**
|
|
47
55
|
* Produces desired quota state and explicit increase/decrease actions.
|
|
48
56
|
*
|
|
@@ -147,4 +155,5 @@ exports.DIRECT_TRANSFERS_QUOTA = DIRECT_TRANSFERS_QUOTA;
|
|
|
147
155
|
exports.calcDefaultQuota = calcDefaultQuota;
|
|
148
156
|
exports.calcQuotaUpdate = calcQuotaUpdate;
|
|
149
157
|
exports.calcRecommendedQuota = calcRecommendedQuota;
|
|
158
|
+
exports.maxAmountForQuota = maxAmountForQuota;
|
|
150
159
|
exports.roundUpQuota = roundUpQuota;
|
|
@@ -766,6 +766,7 @@ exports.json_parse = require_onchain_utils_json.json_parse;
|
|
|
766
766
|
exports.json_stringify = require_onchain_utils_json.json_stringify;
|
|
767
767
|
exports.lidoV1_WETHGatewayAbi = require_onchain_market_adapters_abi_targetContractAbi.lidoV1_WETHGatewayAbi;
|
|
768
768
|
exports.makeReplayState = require_onchain_preview_preview_replayInnerOperations.makeReplayState;
|
|
769
|
+
exports.maxAmountForQuota = require_onchain_accounts_quota_utils.maxAmountForQuota;
|
|
769
770
|
exports.mellowDvvAdapterAbi = require_onchain_market_adapters_abi_adapters_mellowDvvAdapter.mellowDvvAdapterAbi;
|
|
770
771
|
exports.midasGreenlistsAccount = require_onchain_preview_preview_midasGreenlistsAccount.midasGreenlistsAccount;
|
|
771
772
|
exports.minSeizedAmount = require_onchain_market_math.minSeizedAmount;
|
|
@@ -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)
|
|
@@ -374,13 +374,14 @@ var PrepareApi = class extends require_onchain_base_MultichainConstruct.Multicha
|
|
|
374
374
|
/**
|
|
375
375
|
* {@inheritDoc IOpportunitiesPrepare.leverageBand}
|
|
376
376
|
**/
|
|
377
|
-
leverageBand(strategy, collateral, targetHF) {
|
|
377
|
+
leverageBand(strategy, collateral, targetHF, position) {
|
|
378
378
|
const sdk = this.sdk.chain(strategy.chainId);
|
|
379
379
|
return service(sdk).leverageBand({
|
|
380
380
|
sdk,
|
|
381
381
|
creditManager: strategy.creditManager,
|
|
382
382
|
collateral,
|
|
383
|
-
targetHF
|
|
383
|
+
targetHF,
|
|
384
|
+
position
|
|
384
385
|
});
|
|
385
386
|
}
|
|
386
387
|
/**
|
|
@@ -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";
|
|
@@ -9,12 +10,13 @@ import { isPhantomToken } from "./utils/pick-token.js";
|
|
|
9
10
|
import { assertMarketOperable } from "./guards.js";
|
|
10
11
|
import { fetchCreditAccountSlice, toCreditAccountSlice } from "./utils/credit-account-slice.js";
|
|
11
12
|
import { buildBorrowState } from "./borrow.js";
|
|
13
|
+
import { strategyLimits } from "./strategyLimits.js";
|
|
14
|
+
import { accountView } from "./view.js";
|
|
12
15
|
import { calcLeverageBand } from "./leverage-band.js";
|
|
13
16
|
import { maxBorrow } from "./maxBorrow.js";
|
|
14
17
|
import { maxWithdrawCollateral } from "./maxWithdrawCollateral.js";
|
|
15
18
|
import { buildOpenStrategyState } from "./open-strategy.js";
|
|
16
19
|
import { planAddCollateral, planAdjustLeverage, planAdjustLeverageDelayed, planDeposit, planRepay, planWithdraw, planWithdrawAsset, planWithdrawDelayed } from "./plan.js";
|
|
17
|
-
import { accountView } from "./view.js";
|
|
18
20
|
import { withdrawLimits } from "./withdraw-limits.js";
|
|
19
21
|
import { realize } from "./realize.js";
|
|
20
22
|
import { planTail, projectTail } from "./tail.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
|
|
@@ -105,9 +123,8 @@ var CreditAccountOperationsService = class extends SDKConstruct {
|
|
|
105
123
|
* given deposit reaches is decided by the debt it implies and by the
|
|
106
124
|
* `debtLimits` the market puts that debt in — the range a leverage slider should offer.
|
|
107
125
|
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
* holds. Nothing is fetched, so a form can ask on every keystroke.
|
|
126
|
+
* Nothing is fetched: opening uses the supplied collateral, while adjust
|
|
127
|
+
* uses a supplied account slice, so a form can ask on every keystroke.
|
|
111
128
|
*
|
|
112
129
|
* @param props - The manager, the SDK holding its market, what stands
|
|
113
130
|
* behind the position, and optionally the health factor the ceiling should
|
|
@@ -190,14 +207,28 @@ var CreditAccountOperationsService = class extends SDKConstruct {
|
|
|
190
207
|
*/
|
|
191
208
|
async startDelayedIntent(props) {
|
|
192
209
|
const { intent } = props;
|
|
210
|
+
const current = accountView(props.creditAccount, props.sdk);
|
|
211
|
+
const repayFromSource = current.debt - current.balanceOf(current.underlying);
|
|
212
|
+
const maximum = intent.type === "ADJUST_LEVERAGE" && current.collateral > 0n && repayFromSource > 0n ? LEVERAGE_DECIMALS + (repayFromSource * LEVERAGE_DECIMALS - 1n) / current.collateral : void 0;
|
|
213
|
+
const limits = intent.type === "ADJUST_LEVERAGE" && maximum !== void 0 ? strategyLimits({
|
|
214
|
+
...intent,
|
|
215
|
+
suite: props.sdk.marketRegister.findCreditManager(props.creditAccount.creditManager),
|
|
216
|
+
view: current,
|
|
217
|
+
initialQuotas: props.creditAccount.tokens,
|
|
218
|
+
quotaReserve: props.quotaReserve,
|
|
219
|
+
maxLeverage: maximum
|
|
220
|
+
}) : {};
|
|
193
221
|
const result = await this.#preview(props, () => {
|
|
194
|
-
const view =
|
|
222
|
+
const view = {
|
|
223
|
+
...current,
|
|
224
|
+
limits
|
|
225
|
+
};
|
|
195
226
|
switch (intent.type) {
|
|
196
227
|
case "ADJUST_LEVERAGE": return planAdjustLeverageDelayed(intent, view);
|
|
197
228
|
case "WITHDRAW": return planWithdrawDelayed(intent, view);
|
|
198
229
|
default: throw new Error(`${intent.type} - cannot be delayed`);
|
|
199
230
|
}
|
|
200
|
-
});
|
|
231
|
+
}, limits);
|
|
201
232
|
if (!result.ok) return result;
|
|
202
233
|
const { delayed } = result;
|
|
203
234
|
if (!delayed) throw new Error("startDelayedIntent: plan started no withdrawal");
|
|
@@ -213,7 +244,8 @@ var CreditAccountOperationsService = class extends SDKConstruct {
|
|
|
213
244
|
delayed,
|
|
214
245
|
creditAccount: props.creditAccount,
|
|
215
246
|
sdk: props.sdk,
|
|
216
|
-
quotaReserve: props.quotaReserve
|
|
247
|
+
quotaReserve: props.quotaReserve,
|
|
248
|
+
limits
|
|
217
249
|
});
|
|
218
250
|
return {
|
|
219
251
|
...result,
|
|
@@ -399,7 +431,7 @@ var CreditAccountOperationsService = class extends SDKConstruct {
|
|
|
399
431
|
}
|
|
400
432
|
}
|
|
401
433
|
/** Plan → realise → wrap. Unviable requests become `{ ok: false }`. */
|
|
402
|
-
async #preview(props, plan) {
|
|
434
|
+
async #preview(props, plan, limits = {}) {
|
|
403
435
|
const draft = props.draft ?? {};
|
|
404
436
|
try {
|
|
405
437
|
const suite = props.sdk.marketRegister.findCreditManager(props.creditAccount.creditManager);
|
|
@@ -410,7 +442,8 @@ var CreditAccountOperationsService = class extends SDKConstruct {
|
|
|
410
442
|
sdk: props.sdk,
|
|
411
443
|
slippage: props.slippage ?? 0,
|
|
412
444
|
quotaReserve: props.quotaReserve,
|
|
413
|
-
draft
|
|
445
|
+
draft,
|
|
446
|
+
limits
|
|
414
447
|
});
|
|
415
448
|
return {
|
|
416
449
|
ok: true,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { BigIntMath } from "../../utils/bigint-math.js";
|
|
2
2
|
import { LEVERAGE_DECIMALS } from "../../constants/math.js";
|
|
3
|
-
import { resolveCreditManager } from "./utils/common.js";
|
|
3
|
+
import { eq, resolveCreditManager } from "./utils/common.js";
|
|
4
|
+
import { strategyLimits } from "./strategyLimits.js";
|
|
5
|
+
import { accountView } from "./view.js";
|
|
4
6
|
//#region src/onchain/accounts/intents/leverage-band.ts
|
|
5
7
|
/**
|
|
6
8
|
* The leverages this market will actually fund for a position of this size.
|
|
@@ -15,8 +17,8 @@ import { resolveCreditManager } from "./utils/common.js";
|
|
|
15
17
|
* rounds **up** so the leverage it names really does clear `minDebt`, and the
|
|
16
18
|
* ceiling rounds **down** so it really does stay under the borrow limit.
|
|
17
19
|
*
|
|
18
|
-
* Nothing here is fetched or simulated —
|
|
19
|
-
* so a form can call this on each keystroke.
|
|
20
|
+
* Nothing here is fetched or simulated — adjust state comes from the supplied
|
|
21
|
+
* position and the attached market, so a form can call this on each keystroke.
|
|
20
22
|
*
|
|
21
23
|
* @param props - {@link LeverageBandProps}
|
|
22
24
|
* @returns The band, or `undefined` when there is nothing to offer: an
|
|
@@ -29,13 +31,53 @@ import { resolveCreditManager } from "./utils/common.js";
|
|
|
29
31
|
* calcLeverageBand({ sdk, creditManager, collateral }) // { min: 1.1, max: 9 }
|
|
30
32
|
* ```
|
|
31
33
|
**/
|
|
32
|
-
function calcLeverageBand({ sdk, creditManager, collateral, targetHF }) {
|
|
34
|
+
function calcLeverageBand({ sdk, creditManager, collateral, targetHF, position }) {
|
|
33
35
|
const found = resolveCreditManager(sdk, creditManager);
|
|
34
36
|
if (!found) return;
|
|
35
37
|
const { suite, market } = found;
|
|
36
|
-
const
|
|
37
|
-
if (!
|
|
38
|
+
const strategy = suite.strategy;
|
|
39
|
+
if (!strategy) return;
|
|
40
|
+
const target = strategy.targetCollateral;
|
|
38
41
|
const ceiling = suite.creditManager.maxLeverage(target, targetHF);
|
|
42
|
+
if (position) {
|
|
43
|
+
if (!eq(position.creditManager, creditManager)) throw new Error("credit account belongs to a different credit manager");
|
|
44
|
+
const creditAccount = {
|
|
45
|
+
creditAccount: position.creditAccount,
|
|
46
|
+
creditManager: position.creditManager,
|
|
47
|
+
creditFacade: suite.creditFacade.address,
|
|
48
|
+
underlying: position.underlyingToken.address,
|
|
49
|
+
enabledTokensMask: 0n,
|
|
50
|
+
totalDebtUSD: 0n,
|
|
51
|
+
totalDebt: position.totalDebt.value,
|
|
52
|
+
tokens: position.collaterals.map(({ collateral, quota }) => ({
|
|
53
|
+
token: collateral.token.address,
|
|
54
|
+
mask: 0n,
|
|
55
|
+
balance: collateral.value,
|
|
56
|
+
quota: quota.value,
|
|
57
|
+
success: true
|
|
58
|
+
}))
|
|
59
|
+
};
|
|
60
|
+
const view = {
|
|
61
|
+
...accountView(creditAccount, sdk),
|
|
62
|
+
collateral: position.totalValue.value - position.totalDebt.value
|
|
63
|
+
};
|
|
64
|
+
const { leverageLimits, quotaLimits } = strategyLimits({
|
|
65
|
+
type: "ADJUST_LEVERAGE",
|
|
66
|
+
suite,
|
|
67
|
+
view,
|
|
68
|
+
initialQuotas: creditAccount.tokens,
|
|
69
|
+
token: target,
|
|
70
|
+
targetLeverage: LEVERAGE_DECIMALS,
|
|
71
|
+
quotaReserve: void 0
|
|
72
|
+
});
|
|
73
|
+
if (!leverageLimits) return void 0;
|
|
74
|
+
const min = Number(leverageLimits.min) / Number(LEVERAGE_DECIMALS);
|
|
75
|
+
const max = Math.min(ceiling, Number(BigIntMath.min(leverageLimits.max, quotaLimits?.leverageMax ?? leverageLimits.max)) / Number(LEVERAGE_DECIMALS));
|
|
76
|
+
return min > max ? void 0 : {
|
|
77
|
+
min,
|
|
78
|
+
max
|
|
79
|
+
};
|
|
80
|
+
}
|
|
39
81
|
const underlying = market.pool.underlying;
|
|
40
82
|
const convert = (from, to, amount) => market.priceOracle.safeConvert(from, to, amount).value;
|
|
41
83
|
const netValue = collateral.reduce((acc, a) => acc + convert(a.token, underlying, a.balance), 0n);
|
|
@@ -43,9 +85,8 @@ function calcLeverageBand({ sdk, creditManager, collateral, targetHF }) {
|
|
|
43
85
|
min: 1,
|
|
44
86
|
max: ceiling
|
|
45
87
|
};
|
|
46
|
-
const { minDebt
|
|
47
|
-
const
|
|
48
|
-
const borrowLimit = available === void 0 ? maxDebt : BigIntMath.min(maxDebt, available);
|
|
88
|
+
const { minDebt } = suite.creditFacade;
|
|
89
|
+
const borrowLimit = strategy.maxBorrowAmount().amount.value;
|
|
49
90
|
const floor = BigIntMath.ceilDiv(LEVERAGE_DECIMALS * minDebt, netValue);
|
|
50
91
|
const roof = BigIntMath.ceilDiv(LEVERAGE_DECIMALS * (borrowLimit + 1n), netValue) - 1n;
|
|
51
92
|
const min = 1 + Number(floor) / Number(LEVERAGE_DECIMALS);
|
|
@@ -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 };
|