@gearbox-protocol/sdk 16.3.2 → 16.4.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/dev/midasUtils.js +11 -46
- package/dist/cjs/model/errors/index.js +1 -0
- package/dist/cjs/model/errors/operation-errors.js +9 -0
- package/dist/cjs/model/index.js +1 -0
- package/dist/cjs/onchain/accounts/intents/collateral-money.js +41 -0
- package/dist/cjs/onchain/accounts/intents/guards.js +15 -3
- package/dist/cjs/onchain/accounts/intents/index.js +21 -18
- package/dist/cjs/onchain/accounts/intents/maxWithdrawCollateral.js +12 -38
- package/dist/cjs/onchain/accounts/intents/realize.js +10 -2
- package/dist/cjs/onchain/accounts/intents/tail.js +1 -1
- package/dist/cjs/onchain/accounts/intents/withdraw-limits.js +97 -0
- package/dist/cjs/onchain/index.js +2 -0
- package/dist/cjs/onchain/market/adapters/abi/conctructorAbi.js +1 -1
- package/dist/cjs/onchain/preview/preview/previewOpenStrategyPosition.js +10 -16
- package/dist/cjs/onchain/preview/preview/previewOperation.js +19 -11
- package/dist/cjs/onchain/preview/preview/replayMulticall.js +4 -3
- package/dist/cjs/onchain/validation/bundles/checkCollateralFunding.js +3 -3
- package/dist/cjs/onchain/validation/bundles/checkCreditOperation.js +2 -2
- package/dist/cjs/onchain/validation/bundles/checkRWAOpening.js +1 -2
- package/dist/cjs/onchain/validation/checkOperation.js +0 -1
- package/dist/cjs/onchain/validation/checks/checkReservePriceLimited.js +30 -0
- package/dist/cjs/onchain/validation/checks/index.js +2 -0
- package/dist/cjs/onchain/validation/index.js +2 -0
- package/dist/cjs/sdk/prepare/PrepareApi.js +3 -2
- package/dist/esm/dev/midasUtils.js +12 -47
- package/dist/esm/model/errors/index.js +2 -2
- package/dist/esm/model/errors/operation-errors.js +9 -1
- package/dist/esm/model/index.js +2 -2
- package/dist/esm/onchain/accounts/intents/collateral-money.js +40 -0
- package/dist/esm/onchain/accounts/intents/guards.js +15 -3
- package/dist/esm/onchain/accounts/intents/index.js +21 -18
- package/dist/esm/onchain/accounts/intents/maxWithdrawCollateral.js +12 -38
- package/dist/esm/onchain/accounts/intents/realize.js +10 -2
- package/dist/esm/onchain/accounts/intents/tail.js +1 -1
- package/dist/esm/onchain/accounts/intents/withdraw-limits.js +95 -0
- package/dist/esm/onchain/index.js +2 -1
- package/dist/esm/onchain/market/adapters/abi/conctructorAbi.js +1 -1
- package/dist/esm/onchain/preview/preview/previewOpenStrategyPosition.js +11 -17
- package/dist/esm/onchain/preview/preview/previewOperation.js +19 -11
- package/dist/esm/onchain/preview/preview/replayMulticall.js +4 -3
- package/dist/esm/onchain/validation/bundles/checkCollateralFunding.js +3 -3
- package/dist/esm/onchain/validation/bundles/checkCreditOperation.js +2 -2
- package/dist/esm/onchain/validation/bundles/checkRWAOpening.js +1 -2
- package/dist/esm/onchain/validation/checkOperation.js +0 -1
- package/dist/esm/onchain/validation/checks/checkReservePriceLimited.js +29 -0
- package/dist/esm/onchain/validation/checks/index.js +2 -1
- package/dist/esm/onchain/validation/index.js +2 -1
- package/dist/esm/sdk/prepare/PrepareApi.js +3 -2
- package/dist/types/dev/midasUtils.d.ts +3 -4
- package/dist/types/model/errors/index.d.ts +2 -2
- package/dist/types/model/errors/operation-errors.d.ts +41 -1
- package/dist/types/model/index.d.ts +3 -3
- package/dist/types/model/previews.d.ts +11 -20
- package/dist/types/onchain/accounts/intents/collateral-money.d.ts +42 -0
- package/dist/types/onchain/accounts/intents/guards.d.ts +18 -2
- package/dist/types/onchain/accounts/intents/index.d.ts +23 -14
- package/dist/types/onchain/accounts/intents/maxWithdrawCollateral.d.ts +3 -8
- package/dist/types/onchain/accounts/intents/types.d.ts +26 -4
- package/dist/types/onchain/accounts/intents/withdraw-limits.d.ts +80 -0
- package/dist/types/onchain/index.d.ts +2 -1
- package/dist/types/onchain/preview/preview/previewOpenStrategyPosition.d.ts +5 -3
- package/dist/types/onchain/preview/preview/replayMulticall.d.ts +8 -7
- package/dist/types/onchain/validation/checks/checkReservePriceLimited.d.ts +31 -0
- package/dist/types/onchain/validation/checks/index.d.ts +2 -1
- package/dist/types/onchain/validation/index.d.ts +2 -1
- package/dist/types/onchain/validation/raise.d.ts +2 -2
- package/dist/types/sdk/prepare/PrepareApi.d.ts +1 -1
- package/dist/types/sdk/prepare/types.d.ts +23 -16
- package/package.json +1 -1
|
@@ -34,9 +34,13 @@ async function previewOperation(sdk, input, options, creditAccount) {
|
|
|
34
34
|
if (!parsed.ok) return parsed;
|
|
35
35
|
const operation = parsed.data;
|
|
36
36
|
if (require_onchain_preview_parse_types.isPoolOperation(operation)) return require_onchain_preview_preview_previewPoolPositionOperation.previewPoolPositionOperation(sdk, operation, options);
|
|
37
|
-
if (operation.operation === "OpenCreditAccount" || operation.operation === "RWAOpenCreditAccount")
|
|
37
|
+
if (operation.operation === "OpenCreditAccount" || operation.operation === "RWAOpenCreditAccount") {
|
|
38
|
+
const replayed = require_onchain_preview_preview_replayMulticall.replayMulticall(sdk, operation);
|
|
39
|
+
if (!replayed.ok) return replayed;
|
|
40
|
+
return require_onchain_preview_preview_previewOpenStrategyPosition.previewOpenStrategyPosition(sdk, input, operation, replayed.data);
|
|
41
|
+
}
|
|
38
42
|
if (operation.operation === "CloseCreditAccount") {
|
|
39
|
-
const resolved = await resolveCreditAccount(sdk, operation, options, creditAccount);
|
|
43
|
+
const resolved = await resolveCreditAccount(sdk, operation.creditAccount, options, creditAccount);
|
|
40
44
|
if (!resolved.ok) return resolved;
|
|
41
45
|
const replayed = require_onchain_preview_preview_replayMulticall.replayMulticall(sdk, operation, resolved.data);
|
|
42
46
|
if (!replayed.ok) return replayed;
|
|
@@ -48,7 +52,7 @@ async function previewOperation(sdk, input, options, creditAccount) {
|
|
|
48
52
|
return preview;
|
|
49
53
|
}
|
|
50
54
|
if (operation.operation === "MultiCall" || operation.operation === "BotMulticall" || operation.operation === "RWAMulticall") {
|
|
51
|
-
const resolved = await resolveCreditAccount(sdk, operation, options, creditAccount);
|
|
55
|
+
const resolved = await resolveCreditAccount(sdk, operation.creditAccount, options, creditAccount);
|
|
52
56
|
if (!resolved.ok) return resolved;
|
|
53
57
|
const replayed = require_onchain_preview_preview_replayMulticall.replayMulticall(sdk, operation, resolved.data);
|
|
54
58
|
if (!replayed.ok) return replayed;
|
|
@@ -65,20 +69,24 @@ async function previewOperation(sdk, input, options, creditAccount) {
|
|
|
65
69
|
* injected state when present, otherwise fetches it from the credit account
|
|
66
70
|
* compressor.
|
|
67
71
|
*/
|
|
68
|
-
async function resolveCreditAccount(sdk,
|
|
69
|
-
let resolved =
|
|
70
|
-
if (!resolved) resolved = await sdk.accounts.getCreditAccountData(
|
|
71
|
-
if (!resolved) return require_model_result.sdkErr(require_model_errors_prepare_errors.creditAccountNotFound(
|
|
72
|
+
async function resolveCreditAccount(sdk, address, options, data) {
|
|
73
|
+
let resolved = data;
|
|
74
|
+
if (!resolved) resolved = await sdk.accounts.getCreditAccountData(address, options?.blockNumber);
|
|
75
|
+
if (!resolved) return require_model_result.sdkErr(require_model_errors_prepare_errors.creditAccountNotFound(address));
|
|
72
76
|
return require_model_result.sdkOk(resolved);
|
|
73
77
|
}
|
|
74
78
|
/**
|
|
75
79
|
* Previews a plain/bot/RWA multicall: classifies the instant preview
|
|
76
|
-
* (zero-debt closure/repay
|
|
77
|
-
* delayed withdrawal, wraps the instant
|
|
78
|
-
* `DelayedCreditAccountOperation` together with the
|
|
79
|
-
* the state after the withdrawal is claimed.
|
|
80
|
+
* (reopening a zero-debt account, zero-debt closure/repay, or adjustment)
|
|
81
|
+
* and, when the multicall requests a delayed withdrawal, wraps the instant
|
|
82
|
+
* preview into a `DelayedCreditAccountOperation` together with the
|
|
83
|
+
* best-effort preview of the state after the withdrawal is claimed.
|
|
84
|
+
*
|
|
85
|
+
* A reopening is reported as `OpenCreditAccount` and never as a delayed
|
|
86
|
+
* withdrawal: an opening requests no redemption.
|
|
80
87
|
*/
|
|
81
88
|
async function previewMulticallOperation(sdk, input, operation, replay, blockNumber) {
|
|
89
|
+
if (replay.before.totalDebt === 0n && replay.before.quotas.toAssets(0n).length === 0 && replay.after.account.totalDebt > 0n) return require_onchain_preview_preview_previewOpenStrategyPosition.previewOpenStrategyPosition(sdk, input, operation, replay);
|
|
82
90
|
let instantPreview;
|
|
83
91
|
if (require_onchain_preview_preview_detectCloseOrRepay.isCloseOrRepay(operation.multicall)) {
|
|
84
92
|
const instant = require_onchain_preview_preview_previewExitOrRepayStrategyPosition.previewExitOrRepayStrategyPosition(sdk, input, operation, false, replay);
|
|
@@ -5,11 +5,12 @@ const require_onchain_preview_preview_CreditAccountState = require("./CreditAcco
|
|
|
5
5
|
const require_onchain_preview_preview_replayInnerOperations = require("./replayInnerOperations.js");
|
|
6
6
|
//#region src/onchain/preview/preview/replayMulticall.ts
|
|
7
7
|
/**
|
|
8
|
-
* Replays the operation's multicall
|
|
9
|
-
*
|
|
8
|
+
* Replays the operation's multicall via {@link replayInnerOperations}.
|
|
9
|
+
* When `creditAccount` is omitted, the seed is
|
|
10
|
+
* {@link CreditAccountState.beforeOpen} (a fresh opening).
|
|
10
11
|
*/
|
|
11
12
|
function replayMulticall(sdk, operation, creditAccount) {
|
|
12
|
-
const before = require_onchain_preview_preview_CreditAccountState.CreditAccountState.fromCreditAccountData(creditAccount);
|
|
13
|
+
const before = creditAccount ? require_onchain_preview_preview_CreditAccountState.CreditAccountState.fromCreditAccountData(creditAccount) : require_onchain_preview_preview_CreditAccountState.CreditAccountState.beforeOpen(operation.creditManager, sdk.marketRegister.findByCreditManager(operation.creditManager).underlying);
|
|
13
14
|
const after = require_onchain_preview_preview_replayInnerOperations.makeReplayState(before.clone());
|
|
14
15
|
const error = require_onchain_preview_preview_replayInnerOperations.replayInnerOperations(sdk, operation.multicall, after);
|
|
15
16
|
if (error) return require_model_result.sdkErr(error);
|
|
@@ -23,13 +23,13 @@ async function checkCollateralFunding(input) {
|
|
|
23
23
|
if (held.size === 0) return [];
|
|
24
24
|
let spender;
|
|
25
25
|
try {
|
|
26
|
-
if (preview.
|
|
26
|
+
if (preview.creditAccount) spender = await sdk.accounts.getApprovalAddress({
|
|
27
27
|
creditManager: preview.creditManager,
|
|
28
|
-
|
|
28
|
+
creditAccount: preview.creditAccount
|
|
29
29
|
});
|
|
30
30
|
else spender = await sdk.accounts.getApprovalAddress({
|
|
31
31
|
creditManager: preview.creditManager,
|
|
32
|
-
|
|
32
|
+
borrower: sender
|
|
33
33
|
});
|
|
34
34
|
} catch (cause) {
|
|
35
35
|
return [require_model_errors_prepare_errors.unexpectedFailure(cause, "resolve the approval address")];
|
|
@@ -26,7 +26,7 @@ async function checkCreditOperation(args) {
|
|
|
26
26
|
const suite = sdk.marketRegister.findCreditManager(preview.creditManager);
|
|
27
27
|
const market = suite.market;
|
|
28
28
|
const underlying = require_onchain_validation_helpers_token.toToken(sdk, market.pool.underlying);
|
|
29
|
-
const isOpening = preview.operation === "OpenCreditAccount"
|
|
29
|
+
const isOpening = preview.operation === "OpenCreditAccount";
|
|
30
30
|
const protocol = [
|
|
31
31
|
...require_onchain_validation_bundles_checkMarket.checkMarket(suite),
|
|
32
32
|
...require_onchain_validation_checks_checkDebtLimits.checkDebtLimits({
|
|
@@ -52,7 +52,7 @@ async function checkCreditOperation(args) {
|
|
|
52
52
|
preview,
|
|
53
53
|
sender,
|
|
54
54
|
blockNumber
|
|
55
|
-
}),
|
|
55
|
+
}), isOpening ? require_onchain_validation_bundles_checkRWAOpening.checkRWAOpening({
|
|
56
56
|
sdk,
|
|
57
57
|
preview,
|
|
58
58
|
sender
|
|
@@ -12,13 +12,12 @@ async function checkRWAOpening(input) {
|
|
|
12
12
|
if (!nft) return [];
|
|
13
13
|
const gated = new require_onchain_utils_AddressSet.AddressSet(await nft.getTokens());
|
|
14
14
|
const candidates = new require_onchain_utils_AddressSet.AddressSet([...preview.collateralAdded.map((a) => a.token.address), ...preview.quotas.map((q) => q.token.address)]);
|
|
15
|
-
const providedArgs = preview.operation === "RWAOpenCreditAccount" ? preview.rwaArgs : void 0;
|
|
16
15
|
return (await Promise.all([...candidates].filter((token) => gated.has(token)).map((token) => require_onchain_validation_bundles_checkRWAOpenRequirements.checkRWAOpenRequirements({
|
|
17
16
|
sdk,
|
|
18
17
|
wallet: sender,
|
|
19
18
|
creditManager: preview.creditManager,
|
|
20
19
|
token,
|
|
21
|
-
providedArgs
|
|
20
|
+
providedArgs: preview.rwaArgs
|
|
22
21
|
})))).flat();
|
|
23
22
|
}
|
|
24
23
|
//#endregion
|
|
@@ -43,7 +43,6 @@ async function checkOperation(input, options = {}) {
|
|
|
43
43
|
sender
|
|
44
44
|
}, options);
|
|
45
45
|
case "OpenCreditAccount":
|
|
46
|
-
case "RWAOpenCreditAccount":
|
|
47
46
|
case "AdjustCreditAccount": return require_onchain_validation_bundles_checkCreditOperation.checkCreditOperation({
|
|
48
47
|
sdk,
|
|
49
48
|
preview,
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_model_errors_operation_errors = require("../../../model/errors/operation-errors.js");
|
|
3
|
+
require("../../../model/index.js");
|
|
4
|
+
//#region src/onchain/validation/checks/checkReservePriceLimited.ts
|
|
5
|
+
/**
|
|
6
|
+
* Whether a failed collateral check is the reserve price feed's doing.
|
|
7
|
+
*
|
|
8
|
+
* A call that hands funds over is weighed at safe prices — `min` of a token's
|
|
9
|
+
* two feeds, and nothing at all where governance registered no reserve feed —
|
|
10
|
+
* so an account that covers its debt at the main feed can still be refused.
|
|
11
|
+
* The two are worth telling apart: a position that is genuinely too small is
|
|
12
|
+
* fixed by adding collateral or requesting less, while this one is a valuation
|
|
13
|
+
* the account does not control, and requesting less only helps as far as
|
|
14
|
+
* `withdrawable` says it does.
|
|
15
|
+
*
|
|
16
|
+
* Runs after `checkCollateralised` and answers only when that one refused, so
|
|
17
|
+
* the caller keeps its own threshold rather than restating it here.
|
|
18
|
+
*/
|
|
19
|
+
function checkReservePriceLimited(args) {
|
|
20
|
+
const { healthFactor, atMainPrices, healthFactorThreshold, withdrawable } = args;
|
|
21
|
+
if (healthFactor >= healthFactorThreshold || atMainPrices < healthFactorThreshold) return [];
|
|
22
|
+
return [require_model_errors_operation_errors.reservePriceLimited({
|
|
23
|
+
healthFactor,
|
|
24
|
+
atMainPrices,
|
|
25
|
+
healthFactorThreshold,
|
|
26
|
+
withdrawable
|
|
27
|
+
})];
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
exports.checkReservePriceLimited = checkReservePriceLimited;
|
|
@@ -14,6 +14,7 @@ const require_onchain_validation_checks_checkPoolPaused = require("./checkPoolPa
|
|
|
14
14
|
const require_onchain_validation_checks_checkPoolSunset = require("./checkPoolSunset.js");
|
|
15
15
|
const require_onchain_validation_checks_checkQuotaCount = require("./checkQuotaCount.js");
|
|
16
16
|
const require_onchain_validation_checks_checkQuotaLimit = require("./checkQuotaLimit.js");
|
|
17
|
+
const require_onchain_validation_checks_checkReservePriceLimited = require("./checkReservePriceLimited.js");
|
|
17
18
|
exports.checkBorrowLimit = require_onchain_validation_checks_checkBorrowLimit.checkBorrowLimit;
|
|
18
19
|
exports.checkCollateralised = require_onchain_validation_checks_checkCollateralised.checkCollateralised;
|
|
19
20
|
exports.checkCreditAccountFrozen = require_onchain_validation_checks_checkCreditAccountFrozen.checkCreditAccountFrozen;
|
|
@@ -29,3 +30,4 @@ exports.checkPoolPaused = require_onchain_validation_checks_checkPoolPaused.chec
|
|
|
29
30
|
exports.checkPoolSunset = require_onchain_validation_checks_checkPoolSunset.checkPoolSunset;
|
|
30
31
|
exports.checkQuotaCount = require_onchain_validation_checks_checkQuotaCount.checkQuotaCount;
|
|
31
32
|
exports.checkQuotaLimit = require_onchain_validation_checks_checkQuotaLimit.checkQuotaLimit;
|
|
33
|
+
exports.checkReservePriceLimited = require_onchain_validation_checks_checkReservePriceLimited.checkReservePriceLimited;
|
|
@@ -18,6 +18,7 @@ const require_onchain_validation_checks_checkPoolPaused = require("./checks/chec
|
|
|
18
18
|
const require_onchain_validation_checks_checkPoolSunset = require("./checks/checkPoolSunset.js");
|
|
19
19
|
const require_onchain_validation_checks_checkQuotaCount = require("./checks/checkQuotaCount.js");
|
|
20
20
|
const require_onchain_validation_checks_checkQuotaLimit = require("./checks/checkQuotaLimit.js");
|
|
21
|
+
const require_onchain_validation_checks_checkReservePriceLimited = require("./checks/checkReservePriceLimited.js");
|
|
21
22
|
require("./checks/index.js");
|
|
22
23
|
const require_onchain_validation_bundles_checkAccountQuotas = require("./bundles/checkAccountQuotas.js");
|
|
23
24
|
const require_onchain_validation_bundles_checkWalletAllowance = require("./bundles/checkWalletAllowance.js");
|
|
@@ -77,6 +78,7 @@ exports.checkQuotaCount = require_onchain_validation_checks_checkQuotaCount.chec
|
|
|
77
78
|
exports.checkQuotaLimit = require_onchain_validation_checks_checkQuotaLimit.checkQuotaLimit;
|
|
78
79
|
exports.checkRWAOpenRequirements = require_onchain_validation_bundles_checkRWAOpenRequirements.checkRWAOpenRequirements;
|
|
79
80
|
exports.checkRWAOpening = require_onchain_validation_bundles_checkRWAOpening.checkRWAOpening;
|
|
81
|
+
exports.checkReservePriceLimited = require_onchain_validation_checks_checkReservePriceLimited.checkReservePriceLimited;
|
|
80
82
|
exports.checkSimulation = require_onchain_validation_checkSimulation.checkSimulation;
|
|
81
83
|
exports.checkWallet = require_onchain_validation_bundles_checkWallet.checkWallet;
|
|
82
84
|
exports.checkWalletAllowance = require_onchain_validation_bundles_checkWalletAllowance.checkWalletAllowance;
|
|
@@ -259,12 +259,13 @@ var PrepareApi = class extends require_onchain_base_MultichainConstruct.Multicha
|
|
|
259
259
|
/**
|
|
260
260
|
* {@inheritDoc IOpportunitiesPrepare.maxWithdraw}
|
|
261
261
|
**/
|
|
262
|
-
async maxWithdraw(position) {
|
|
262
|
+
async maxWithdraw(position, sourceToken) {
|
|
263
263
|
const sdk = await this.#chain(position.chainId);
|
|
264
264
|
const creditAccount = await this.#account(sdk, position);
|
|
265
265
|
return service(sdk).maxWithdraw({
|
|
266
266
|
creditAccount,
|
|
267
|
-
sdk
|
|
267
|
+
sdk,
|
|
268
|
+
sourceToken
|
|
268
269
|
});
|
|
269
270
|
}
|
|
270
271
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { writeAndWait } from "./kycUtils.js";
|
|
2
|
-
import { parseAbi, parseEther
|
|
2
|
+
import { parseAbi, parseEther } from "viem";
|
|
3
3
|
//#region src/dev/midasUtils.ts
|
|
4
4
|
/**
|
|
5
5
|
* Midas vaults inherit their own `Pausable`, whose global pause is guarded by
|
|
@@ -9,24 +9,14 @@ const iMidasPausableVaultAbi = parseAbi([
|
|
|
9
9
|
"function paused() external view returns (bool)",
|
|
10
10
|
"function pause() external",
|
|
11
11
|
"function unpause() external",
|
|
12
|
-
"function fnPaused(bytes4 fn) external view returns (bool)",
|
|
13
|
-
"function pauseFn(bytes4 fn) external",
|
|
14
|
-
"function unpauseFn(bytes4 fn) external",
|
|
15
12
|
"function pauseAdminRole() external view returns (bytes32)",
|
|
16
13
|
"function accessControl() external view returns (address)"
|
|
17
14
|
]);
|
|
18
15
|
const iMidasAccessControlAbi = parseAbi(["function hasRole(bytes32 role, address account) external view returns (bool)", "function grantRole(bytes32 role, address account) external"]);
|
|
19
16
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*/
|
|
24
|
-
const DEPOSIT_INSTANT_SELECTOR = toFunctionSelector("depositInstant(address,uint256,uint256,bytes32)");
|
|
25
|
-
/**
|
|
26
|
-
* Unpauses a Midas issuance vault on an anvil fork so that `depositInstant`
|
|
27
|
-
* stops reverting with `Pausable: paused` (global) or `Pausable: fn paused`
|
|
28
|
-
* (per-selector), and returns a callback that restores the original pause
|
|
29
|
-
* state of each layer that was cleared.
|
|
17
|
+
* Unpauses a globally paused Midas issuance vault on an anvil fork, so that
|
|
18
|
+
* `depositInstant` stops reverting with `Pausable: paused`, and returns a
|
|
19
|
+
* callback that restores the original pause state.
|
|
30
20
|
*
|
|
31
21
|
* Impersonates `admin` and grants it `pauseAdminRole()` when missing, same as
|
|
32
22
|
* `greenlistMidasGateway` does with the greenlist roles. The grant is not
|
|
@@ -34,20 +24,11 @@ const DEPOSIT_INSTANT_SELECTOR = toFunctionSelector("depositInstant(address,uint
|
|
|
34
24
|
*/
|
|
35
25
|
async function unpauseMidasIssuanceVault(props) {
|
|
36
26
|
const { anvil, vault, admin, logger } = props;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
functionName: "paused"
|
|
43
|
-
}, {
|
|
44
|
-
address: vault,
|
|
45
|
-
abi: iMidasPausableVaultAbi,
|
|
46
|
-
functionName: "fnPaused",
|
|
47
|
-
args: [DEPOSIT_INSTANT_SELECTOR]
|
|
48
|
-
}]
|
|
49
|
-
});
|
|
50
|
-
if (!paused && !depositInstantPaused) {
|
|
27
|
+
if (!await anvil.readContract({
|
|
28
|
+
address: vault,
|
|
29
|
+
abi: iMidasPausableVaultAbi,
|
|
30
|
+
functionName: "paused"
|
|
31
|
+
})) {
|
|
51
32
|
logger?.debug(`midas: issuance vault ${vault} is not paused`);
|
|
52
33
|
return async () => {};
|
|
53
34
|
}
|
|
@@ -69,7 +50,7 @@ async function unpauseMidasIssuanceVault(props) {
|
|
|
69
50
|
functionName: "hasRole",
|
|
70
51
|
args: [pauseAdminRole, admin]
|
|
71
52
|
});
|
|
72
|
-
logger?.debug(`midas: unpausing issuance vault ${vault} as ${admin}, access control ${accessControl}, pause admin role ${pauseAdminRole}`
|
|
53
|
+
logger?.debug(`midas: unpausing issuance vault ${vault} as ${admin}, access control ${accessControl}, pause admin role ${pauseAdminRole}`);
|
|
73
54
|
await anvil.impersonateAccount({ address: admin });
|
|
74
55
|
try {
|
|
75
56
|
await anvil.setBalance({
|
|
@@ -87,21 +68,13 @@ async function unpauseMidasIssuanceVault(props) {
|
|
|
87
68
|
});
|
|
88
69
|
logger?.debug(`midas: granted pause admin role to ${admin}`);
|
|
89
70
|
}
|
|
90
|
-
|
|
71
|
+
await writeAndWait(anvil, {
|
|
91
72
|
account: admin,
|
|
92
73
|
chain: anvil.chain,
|
|
93
74
|
address: vault,
|
|
94
75
|
abi: iMidasPausableVaultAbi,
|
|
95
76
|
functionName: "unpause"
|
|
96
77
|
});
|
|
97
|
-
if (depositInstantPaused) await writeAndWait(anvil, {
|
|
98
|
-
account: admin,
|
|
99
|
-
chain: anvil.chain,
|
|
100
|
-
address: vault,
|
|
101
|
-
abi: iMidasPausableVaultAbi,
|
|
102
|
-
functionName: "unpauseFn",
|
|
103
|
-
args: [DEPOSIT_INSTANT_SELECTOR]
|
|
104
|
-
});
|
|
105
78
|
} finally {
|
|
106
79
|
await anvil.stopImpersonatingAccount({ address: admin });
|
|
107
80
|
}
|
|
@@ -116,21 +89,13 @@ async function unpauseMidasIssuanceVault(props) {
|
|
|
116
89
|
address: admin,
|
|
117
90
|
value: parseEther("100")
|
|
118
91
|
});
|
|
119
|
-
|
|
92
|
+
await writeAndWait(anvil, {
|
|
120
93
|
account: admin,
|
|
121
94
|
chain: anvil.chain,
|
|
122
95
|
address: vault,
|
|
123
96
|
abi: iMidasPausableVaultAbi,
|
|
124
97
|
functionName: "pause"
|
|
125
98
|
});
|
|
126
|
-
if (depositInstantPaused) await writeAndWait(anvil, {
|
|
127
|
-
account: admin,
|
|
128
|
-
chain: anvil.chain,
|
|
129
|
-
address: vault,
|
|
130
|
-
abi: iMidasPausableVaultAbi,
|
|
131
|
-
functionName: "pauseFn",
|
|
132
|
-
args: [DEPOSIT_INSTANT_SELECTOR]
|
|
133
|
-
});
|
|
134
99
|
} catch (e) {
|
|
135
100
|
logger?.warn(`midas: failed to pause issuance vault ${vault} back: ${e}`);
|
|
136
101
|
} finally {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "./base.js";
|
|
2
2
|
import { creditAccountFrozen, liquidatorNotEligible, notEmergencyLiquidator } from "./liquidation-errors.js";
|
|
3
|
-
import { creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, rwaOpenRequirementsNotMet } from "./operation-errors.js";
|
|
3
|
+
import { creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet } from "./operation-errors.js";
|
|
4
4
|
import { unpriceableTokenError } from "./oracle-errors.js";
|
|
5
5
|
import { creditAccountNotEmpty, creditAccountNotFound, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, unexpectedFailure, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress } from "./prepare-errors.js";
|
|
6
6
|
import { malformedTransaction } from "./preview-errors.js";
|
|
7
|
-
export { creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, liquidatorNotEligible, malformedTransaction, marketExpired, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, rwaOpenRequirementsNotMet, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress };
|
|
7
|
+
export { creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, liquidatorNotEligible, malformedTransaction, marketExpired, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress };
|
|
@@ -66,6 +66,14 @@ function insufficientCollateral(args) {
|
|
|
66
66
|
...args
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
|
+
/** {@inheritDoc ReservePriceLimitedError} */
|
|
70
|
+
function reservePriceLimited(args) {
|
|
71
|
+
return {
|
|
72
|
+
code: "reservePriceLimited",
|
|
73
|
+
message: `The reserve price feed values this collateral below what the operation pays out: the account covers its debt at ${args.atMainPrices} on the main feed and only ${args.healthFactor} at the reserve one, below ${args.healthFactorThreshold}.`,
|
|
74
|
+
...args
|
|
75
|
+
};
|
|
76
|
+
}
|
|
69
77
|
/** {@inheritDoc ForbiddenTokenError} */
|
|
70
78
|
function forbiddenToken(token) {
|
|
71
79
|
return {
|
|
@@ -118,4 +126,4 @@ function rwaOpenRequirementsNotMet(args) {
|
|
|
118
126
|
};
|
|
119
127
|
}
|
|
120
128
|
//#endregion
|
|
121
|
-
export { creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, rwaOpenRequirementsNotMet };
|
|
129
|
+
export { creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet };
|
package/dist/esm/model/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import { ANALYTICS_POSITIONS_DEFAULT_LIMIT, ANALYTICS_POSITIONS_MAX_LIMIT, analy
|
|
|
15
15
|
import "./curators.js";
|
|
16
16
|
import "./delayed-intents.js";
|
|
17
17
|
import { creditAccountFrozen, liquidatorNotEligible, notEmergencyLiquidator } from "./errors/liquidation-errors.js";
|
|
18
|
-
import { creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, rwaOpenRequirementsNotMet } from "./errors/operation-errors.js";
|
|
18
|
+
import { creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet } from "./errors/operation-errors.js";
|
|
19
19
|
import { unpriceableTokenError } from "./errors/oracle-errors.js";
|
|
20
20
|
import { creditAccountNotEmpty, creditAccountNotFound, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, unexpectedFailure, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress } from "./errors/prepare-errors.js";
|
|
21
21
|
import { malformedTransaction } from "./errors/preview-errors.js";
|
|
@@ -32,4 +32,4 @@ import { chainFailedSchema, chainMetadataSchema, chainSucceededSchema, dataSourc
|
|
|
32
32
|
import { safeValue, sdkErr, sdkOk } from "./result.js";
|
|
33
33
|
import "./withdrawals.js";
|
|
34
34
|
import { positionClaimableWithdrawalSchema, positionPendingWithdrawalSchema, positionWithdrawalsSchema, withdrawalOutputAmountSchema } from "./withdrawals.schema.js";
|
|
35
|
-
export { ANALYTICS_POSITIONS_DEFAULT_LIMIT, ANALYTICS_POSITIONS_MAX_LIMIT, CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, FILTER_ALL, KYC_REGISTRATION_LINKS, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, PROTOCOL_CHART_METRICS, RWA_FACTORY_SECURITIZE, RWA_FACTORY_TYPES, RWA_PROTOCOLS, SECURITIZE_REGISTER_VAULT_TYPES, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, STRATEGY_POSITION_COLLATERAL_ERROR, amountSchema, analyticsChartQueryOptionsSchema, analyticsChartQueryParamsSchema, analyticsChartQuerySchema, analyticsPositionListOptionsSchema, analyticsPositionListQueryParamsSchema, analyticsPositionListQuerySchema, analyticsPositionPageSchema, analyticsPositionSchema, analyticsPositionSortFieldSchema, analyticsSortDirectionSchema, apyBreakdownSchema, asEstimated, assetTypeSchema, backendPreferred, booleanParamSchema, borrowRateBreakdownSchema, bpsSchema, chainFailedSchema, chainIdSchema, chainMetadataSchema, chainSucceededSchema, chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, compareTagOf, creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, curatorNameSchema, curatorSchema, dataSourceSchema, debtOutOfRange, delayedReceivedAssetSchema, encodeFlag, filterAllSchema, filterable, forbiddenToken, instantReceivedAssetSchema, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, isFilterSet, kycRequirementSchema, leverageOutOfRange, leverageSchema, liquidatableAccountFilterSchema, liquidatableAccountSchema, liquidationApprovalSchema, liquidationDetailsSchema, liquidationPositionId, liquidationPositionSchema, liquidatorNotEligible, malformedTransaction, marketExpired, matchesLiquidatableAccountFilter, matchesOpportunityFilter, matchesPositionFilter, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, noticeKindSchema, noticeSchema, offchainOnly, onchainOnly, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityId, opportunityKeySchema, opportunityKindSchema, opportunitySchema, opportunityTotalsSchema, pnlBreakdownSchema, pointRewardsSchema, pointsProgramPnLSchema, pointsProgramSchema, pointsRewardsPnLSchema, poolOpportunityChartMetricSchema, poolOpportunityDetailSchema, poolOpportunityId, poolOpportunityKeySchema, poolOpportunitySchema, poolPaused, poolPositionChartMetricSchema, poolPositionId, poolPositionKeySchema, poolPositionSchema, poolSunset, positionClaimableWithdrawalSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionId, positionKeySchema, positionKindSchema, positionPendingWithdrawalSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionWithdrawalsSchema, positionsTotalsSchema, priceFeedDataSchema, priceFeedSummarySchema, protocolChartMetricSchema, quotaAssetSchema, quotaCountExceeded, quotaLimitReached, rateCurvePointSchema, rateCurveSchema, receivedAssetSchema, responseMetadataSchema, responseSchema, rewardsPnLSchema, rewardsSchema, rwaOpenRequirementsNotMet, rwaProtocolSchema, safeValue, sdkErr, sdkOk, strategyOpportunityChartMetricSchema, strategyOpportunityDetailSchema, strategyOpportunityId, strategyOpportunityKeySchema, strategyOpportunitySchema, strategyPositionChartMetricSchema, strategyPositionId, strategyPositionKeySchema, strategyPositionSchema, timestampSchema, tokenAmountSchema, tokenQuotaRateSchema, tokenRewardsPnLSchema, tokenRewardsSchema, tokenSchema, tolerance, txCallSchema, underlyingTokenSchema, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress, withdrawalOutputAmountSchema };
|
|
35
|
+
export { ANALYTICS_POSITIONS_DEFAULT_LIMIT, ANALYTICS_POSITIONS_MAX_LIMIT, CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, FILTER_ALL, KYC_REGISTRATION_LINKS, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, PROTOCOL_CHART_METRICS, RWA_FACTORY_SECURITIZE, RWA_FACTORY_TYPES, RWA_PROTOCOLS, SECURITIZE_REGISTER_VAULT_TYPES, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, STRATEGY_POSITION_COLLATERAL_ERROR, amountSchema, analyticsChartQueryOptionsSchema, analyticsChartQueryParamsSchema, analyticsChartQuerySchema, analyticsPositionListOptionsSchema, analyticsPositionListQueryParamsSchema, analyticsPositionListQuerySchema, analyticsPositionPageSchema, analyticsPositionSchema, analyticsPositionSortFieldSchema, analyticsSortDirectionSchema, apyBreakdownSchema, asEstimated, assetTypeSchema, backendPreferred, booleanParamSchema, borrowRateBreakdownSchema, bpsSchema, chainFailedSchema, chainIdSchema, chainMetadataSchema, chainSucceededSchema, chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, compareTagOf, creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, curatorNameSchema, curatorSchema, dataSourceSchema, debtOutOfRange, delayedReceivedAssetSchema, encodeFlag, filterAllSchema, filterable, forbiddenToken, instantReceivedAssetSchema, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, isFilterSet, kycRequirementSchema, leverageOutOfRange, leverageSchema, liquidatableAccountFilterSchema, liquidatableAccountSchema, liquidationApprovalSchema, liquidationDetailsSchema, liquidationPositionId, liquidationPositionSchema, liquidatorNotEligible, malformedTransaction, marketExpired, matchesLiquidatableAccountFilter, matchesOpportunityFilter, matchesPositionFilter, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, noticeKindSchema, noticeSchema, offchainOnly, onchainOnly, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityId, opportunityKeySchema, opportunityKindSchema, opportunitySchema, opportunityTotalsSchema, pnlBreakdownSchema, pointRewardsSchema, pointsProgramPnLSchema, pointsProgramSchema, pointsRewardsPnLSchema, poolOpportunityChartMetricSchema, poolOpportunityDetailSchema, poolOpportunityId, poolOpportunityKeySchema, poolOpportunitySchema, poolPaused, poolPositionChartMetricSchema, poolPositionId, poolPositionKeySchema, poolPositionSchema, poolSunset, positionClaimableWithdrawalSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionId, positionKeySchema, positionKindSchema, positionPendingWithdrawalSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionWithdrawalsSchema, positionsTotalsSchema, priceFeedDataSchema, priceFeedSummarySchema, protocolChartMetricSchema, quotaAssetSchema, quotaCountExceeded, quotaLimitReached, rateCurvePointSchema, rateCurveSchema, receivedAssetSchema, reservePriceLimited, responseMetadataSchema, responseSchema, rewardsPnLSchema, rewardsSchema, rwaOpenRequirementsNotMet, rwaProtocolSchema, safeValue, sdkErr, sdkOk, strategyOpportunityChartMetricSchema, strategyOpportunityDetailSchema, strategyOpportunityId, strategyOpportunityKeySchema, strategyOpportunitySchema, strategyPositionChartMetricSchema, strategyPositionId, strategyPositionKeySchema, strategyPositionSchema, timestampSchema, tokenAmountSchema, tokenQuotaRateSchema, tokenRewardsPnLSchema, tokenRewardsSchema, tokenSchema, tolerance, txCallSchema, underlyingTokenSchema, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress, withdrawalOutputAmountSchema };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { BigIntMath } from "../../utils/bigint-math.js";
|
|
2
|
+
import { PERCENTAGE_FACTOR } from "../../constants/math.js";
|
|
3
|
+
import "../../utils/index.js";
|
|
4
|
+
import { eq } from "./utils/common.js";
|
|
5
|
+
//#region src/onchain/accounts/intents/collateral-money.ts
|
|
6
|
+
/** {@inheritDoc CollateralMoney} */
|
|
7
|
+
function collateralMoney(creditAccount, sdk) {
|
|
8
|
+
const { market, creditManager } = sdk.marketRegister.findCreditManager(creditAccount.creditManager);
|
|
9
|
+
const { priceOracle } = market;
|
|
10
|
+
const { pqk } = market.pool;
|
|
11
|
+
const underlying = market.pool.underlying;
|
|
12
|
+
const masked = creditAccount.enabledTokensMask !== 0n;
|
|
13
|
+
const mainUsd = (token, amount) => {
|
|
14
|
+
try {
|
|
15
|
+
return priceOracle.convertToUSD(token, amount);
|
|
16
|
+
} catch {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const lt = (token) => BigInt(creditManager.liquidationThresholds.get(token) ?? 0);
|
|
21
|
+
const checkedUsd = (holding) => eq(holding.token, underlying) ? mainUsd(holding.token, holding.balance) ?? 0n : priceOracle.safeConvertMinUSD(holding.token, holding.balance).value;
|
|
22
|
+
/** A quota is underlying-denominated, and a closed market backs nothing. */
|
|
23
|
+
const quotaMoney = (holding) => pqk.hasActiveQuota(holding.token) ? (mainUsd(underlying, holding.quota) ?? 0n) * PERCENTAGE_FACTOR : 0n;
|
|
24
|
+
const weigh = (holding) => {
|
|
25
|
+
const weighted = checkedUsd(holding) * lt(holding.token);
|
|
26
|
+
if (holding.quota === 0n) return weighted;
|
|
27
|
+
return BigIntMath.min(quotaMoney(holding), weighted);
|
|
28
|
+
};
|
|
29
|
+
return {
|
|
30
|
+
underlying,
|
|
31
|
+
counts: (holding) => holding.balance > 10n && (!masked || (holding.mask & creditAccount.enabledTokensMask) !== 0n),
|
|
32
|
+
weigh,
|
|
33
|
+
quotaMoney,
|
|
34
|
+
mainUsd,
|
|
35
|
+
checkedUsd,
|
|
36
|
+
lt
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { collateralMoney };
|
|
@@ -6,6 +6,7 @@ import { checkCreditManagerPaused } from "../../validation/checks/checkCreditMan
|
|
|
6
6
|
import { checkForbiddenToken } from "../../validation/checks/checkForbiddenToken.js";
|
|
7
7
|
import { checkMarketExpired } from "../../validation/checks/checkMarketExpired.js";
|
|
8
8
|
import { checkQuotaLimit } from "../../validation/checks/checkQuotaLimit.js";
|
|
9
|
+
import { checkReservePriceLimited } from "../../validation/checks/checkReservePriceLimited.js";
|
|
9
10
|
import { raise } from "../../validation/raise.js";
|
|
10
11
|
import "../../validation/index.js";
|
|
11
12
|
import { eq } from "./utils/common.js";
|
|
@@ -111,13 +112,24 @@ function assertGrowthAllowed(args) {
|
|
|
111
112
|
* whose reserve feed the SDK cannot read keeps its main price, so a plan can
|
|
112
113
|
* still be refused on-chain after passing here.
|
|
113
114
|
*/
|
|
114
|
-
function assertCollateralised(healthFactorBps, safePrices) {
|
|
115
|
+
function assertCollateralised(healthFactorBps, safePrices, atSafePrices) {
|
|
115
116
|
const healthFactorThreshold = MIN_HEALTH_FACTOR_FACADE;
|
|
116
|
-
|
|
117
|
+
const errors = checkCollateralised({
|
|
117
118
|
healthFactor: healthFactorBps,
|
|
118
119
|
healthFactorThreshold,
|
|
119
120
|
safePrices
|
|
120
|
-
})
|
|
121
|
+
});
|
|
122
|
+
if (errors.length === 0) return;
|
|
123
|
+
if (safePrices && atSafePrices) {
|
|
124
|
+
const { atMainPrices, withdrawable } = atSafePrices();
|
|
125
|
+
raise(checkReservePriceLimited({
|
|
126
|
+
healthFactor: healthFactorBps,
|
|
127
|
+
atMainPrices,
|
|
128
|
+
healthFactorThreshold,
|
|
129
|
+
withdrawable
|
|
130
|
+
}), `the account covers its debt at ${atMainPrices} on the main feed and only ${healthFactorBps} at the reserve one, below ${healthFactorThreshold}`);
|
|
131
|
+
}
|
|
132
|
+
raise(errors, `the account would end at a health factor of ${healthFactorBps}, below ${healthFactorThreshold}`);
|
|
121
133
|
}
|
|
122
134
|
/**
|
|
123
135
|
* A quota can only be raised as far as the market still has room for: past the
|
|
@@ -8,13 +8,13 @@ import "../../validation/index.js";
|
|
|
8
8
|
import { isPhantomToken } from "./utils/pick-token.js";
|
|
9
9
|
import { assertMarketOperable } from "./guards.js";
|
|
10
10
|
import { calcLeverageBand } from "./leverage-band.js";
|
|
11
|
-
import { maxProportionalWithdrawal } from "./math.js";
|
|
12
11
|
import { maxWithdrawCollateral } from "./maxWithdrawCollateral.js";
|
|
13
12
|
import { fetchCreditAccountSlice, toCreditAccountSlice } from "./utils/credit-account-slice.js";
|
|
14
13
|
import { buildOpenStrategyState } from "./open-strategy.js";
|
|
15
14
|
import { planAddCollateral, planAdjustLeverage, planAdjustLeverageDelayed, planDeposit, planRepay, planWithdraw, planWithdrawAsset, planWithdrawDelayed } from "./plan.js";
|
|
16
|
-
import { realize } from "./realize.js";
|
|
17
15
|
import { accountView } from "./view.js";
|
|
16
|
+
import { withdrawLimits } from "./withdraw-limits.js";
|
|
17
|
+
import { realize } from "./realize.js";
|
|
18
18
|
import { planTail, projectTail } from "./tail.js";
|
|
19
19
|
//#region src/onchain/accounts/intents/index.ts
|
|
20
20
|
/**
|
|
@@ -50,26 +50,29 @@ var CreditAccountOperationsService = class extends SDKConstruct {
|
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
52
|
* Both ends of what a `WITHDRAW` can take out, in underlying: the largest
|
|
53
|
-
* partial withdrawal that keeps leverage and
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
53
|
+
* partial withdrawal that keeps leverage, and the net value an exit hands
|
|
54
|
+
* over. They are reported together because a withdraw form needs both — the
|
|
55
|
+
* range it may offer, and the one amount past it that is allowed — and
|
|
56
|
+
* because the distance between them is the account's own, not a constant a
|
|
57
|
+
* caller could assume.
|
|
58
58
|
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
59
|
+
* Two rules bound the partial end and both are reported: the facade's
|
|
60
|
+
* `debtLimits` as `partial`, and the safe-price collateral check on top of
|
|
61
|
+
* it as `safePartial`. The second is the one to offer — see
|
|
62
|
+
* {@link WithdrawCeilings}.
|
|
62
63
|
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
64
|
+
* Takes no target health factor, unlike {@link maxWithdrawCollateral}. A
|
|
65
|
+
* proportional withdrawal leaves the factor where it found it, so there is
|
|
66
|
+
* no room to choose: what these answer to is the facade's own threshold,
|
|
67
|
+
* which is also what {@link startIntent} refuses against.
|
|
68
|
+
*
|
|
69
|
+
* @param props - Account slice, the SDK holding its market, and optionally
|
|
70
|
+
* the collateral the withdrawal would be funded from
|
|
71
|
+
* @returns The three limits, see {@link WithdrawCeilings} for the gap
|
|
72
|
+
* between them
|
|
66
73
|
*/
|
|
67
74
|
maxWithdraw(props) {
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
partial: maxProportionalWithdrawal(view, view.debtLimits),
|
|
71
|
-
exit: view.collateral > 0n ? view.collateral : 0n
|
|
72
|
-
};
|
|
75
|
+
return withdrawLimits(props);
|
|
73
76
|
}
|
|
74
77
|
/**
|
|
75
78
|
* Debt a `REPAY` would have to cover to settle the account, in underlying
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
import { BigIntMath } from "../../utils/bigint-math.js";
|
|
2
|
-
import
|
|
2
|
+
import "../../constants/math.js";
|
|
3
3
|
import "../../utils/index.js";
|
|
4
4
|
import { eq } from "./utils/common.js";
|
|
5
|
+
import { collateralMoney } from "./collateral-money.js";
|
|
5
6
|
//#region src/onchain/accounts/intents/maxWithdrawCollateral.ts
|
|
6
7
|
/**
|
|
7
8
|
* Largest amount of one collateral the account can withdraw while its health
|
|
8
9
|
* factor stays at or above `targetHF`.
|
|
9
10
|
*
|
|
10
11
|
* This is the collateral check solved for one balance, and it counts what that
|
|
11
|
-
* check counts
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* Collateral is valued at the protocol safe price (`min` of the two feeds,
|
|
15
|
-
* 0 when there is no reserve), the way the facade values a call that hands
|
|
16
|
-
* funds over; the underlying is exempt and is valued at the main feed, as
|
|
17
|
-
* `CreditManagerV3._safeConvertToUSD` does. The debt is valued at the main
|
|
18
|
-
* feed, as the check does. Zero debt frees the whole balance.
|
|
12
|
+
* check counts — see {@link collateralMoney} for the valuation, safe prices
|
|
13
|
+
* included. The debt is valued at the main feed, as the check does. Zero debt
|
|
14
|
+
* frees the whole balance.
|
|
19
15
|
*
|
|
20
16
|
* Rounding always favours the account, so the answer clears the check rather
|
|
21
17
|
* than landing a wei short of it.
|
|
@@ -26,49 +22,27 @@ import { eq } from "./utils/common.js";
|
|
|
26
22
|
**/
|
|
27
23
|
function maxWithdrawCollateral(props) {
|
|
28
24
|
const { creditAccount, sdk, token, targetHF } = props;
|
|
29
|
-
const { market, creditManager } = sdk.marketRegister.findCreditManager(creditAccount.creditManager);
|
|
30
|
-
const { priceOracle } = market;
|
|
31
|
-
const { pqk } = market.pool;
|
|
32
|
-
const underlying = market.pool.underlying;
|
|
33
25
|
const target = creditAccount.tokens.find((t) => eq(t.token, token));
|
|
34
26
|
if (!target || target.balance <= 10n) return 0n;
|
|
35
27
|
if (creditAccount.totalDebt === 0n) return target.balance;
|
|
36
|
-
const
|
|
37
|
-
const counts = (t) => t.balance > 10n && (!masked || (t.mask & creditAccount.enabledTokensMask) !== 0n);
|
|
38
|
-
/** What a holding backs, in the check's units: USD × PERCENTAGE_FACTOR. */
|
|
39
|
-
const weigh = (t) => {
|
|
40
|
-
const lt = BigInt(creditManager.liquidationThresholds.get(t.token) ?? 0);
|
|
41
|
-
const weighted = (eq(t.token, underlying) ? usd(priceOracle, t.token, t.balance) ?? 0n : priceOracle.safeConvertMinUSD(t.token, t.balance).value) * lt;
|
|
42
|
-
if (t.quota === 0n) return weighted;
|
|
43
|
-
return BigIntMath.min(quotaUsd(t) * PERCENTAGE_FACTOR, weighted);
|
|
44
|
-
};
|
|
45
|
-
/** A quota is underlying-denominated, and a closed market backs nothing. */
|
|
46
|
-
const quotaUsd = (t) => pqk.hasActiveQuota(t.token) ? usd(priceOracle, underlying, t.quota) ?? 0n : 0n;
|
|
28
|
+
const money = collateralMoney(creditAccount, sdk);
|
|
47
29
|
let otherMoney = 0n;
|
|
48
30
|
for (const t of creditAccount.tokens) {
|
|
49
|
-
if (eq(t.token, token) || !counts(t)) continue;
|
|
50
|
-
otherMoney += weigh(t);
|
|
31
|
+
if (eq(t.token, token) || !money.counts(t)) continue;
|
|
32
|
+
otherMoney += money.weigh(t);
|
|
51
33
|
}
|
|
52
|
-
const borrowed =
|
|
34
|
+
const borrowed = money.mainUsd(money.underlying, creditAccount.totalDebt);
|
|
53
35
|
if (borrowed === void 0 || borrowed <= 0n) return 0n;
|
|
54
36
|
const required = borrowed * targetHF;
|
|
55
37
|
if (required <= otherMoney) return target.balance;
|
|
56
38
|
const shortfall = required - otherMoney;
|
|
57
|
-
if (target.quota > 0n &&
|
|
58
|
-
const targetLt =
|
|
59
|
-
const targetUsd =
|
|
39
|
+
if (target.quota > 0n && money.quotaMoney(target) < shortfall) return 0n;
|
|
40
|
+
const targetLt = money.lt(target.token);
|
|
41
|
+
const targetUsd = money.checkedUsd(target);
|
|
60
42
|
if (targetLt === 0n || targetUsd === 0n) return 0n;
|
|
61
43
|
const keptUsd = BigIntMath.ceilDiv(shortfall, targetLt);
|
|
62
44
|
const kept = BigIntMath.ceilDiv(target.balance * keptUsd, targetUsd);
|
|
63
45
|
return kept >= target.balance ? 0n : target.balance - kept;
|
|
64
46
|
}
|
|
65
|
-
/** USD value at the main feed, or `undefined` when the token has no price. */
|
|
66
|
-
function usd(oracle, token, amount) {
|
|
67
|
-
try {
|
|
68
|
-
return oracle.convertToUSD(token, amount);
|
|
69
|
-
} catch {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
47
|
//#endregion
|
|
74
48
|
export { maxWithdrawCollateral };
|