@gearbox-protocol/sdk 16.0.0-next.7 → 16.0.0-next.9
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 +3 -2
- package/dist/cjs/onchain/accounts/intents/guards.js +71 -14
- package/dist/cjs/onchain/accounts/intents/index.js +12 -16
- package/dist/cjs/onchain/accounts/intents/math.js +25 -8
- package/dist/cjs/onchain/accounts/intents/maxWithdrawCollateral.js +2 -5
- package/dist/cjs/onchain/accounts/intents/open-strategy.js +5 -6
- package/dist/cjs/onchain/accounts/intents/plan.js +43 -21
- package/dist/cjs/onchain/accounts/intents/realize.js +23 -8
- package/dist/cjs/onchain/accounts/intents/refusal.js +28 -0
- package/dist/cjs/onchain/accounts/intents/tail.js +2 -2
- package/dist/cjs/onchain/accounts/intents/types.js +0 -16
- package/dist/cjs/onchain/index.js +3 -2
- package/dist/cjs/onchain/utils/bigint-math.js +9 -0
- package/dist/cjs/sdk/prepare/PrepareApi.js +19 -20
- package/dist/esm/onchain/accounts/index.js +2 -2
- package/dist/esm/onchain/accounts/intents/guards.js +71 -14
- package/dist/esm/onchain/accounts/intents/index.js +11 -16
- package/dist/esm/onchain/accounts/intents/math.js +25 -8
- package/dist/esm/onchain/accounts/intents/maxWithdrawCollateral.js +2 -5
- package/dist/esm/onchain/accounts/intents/open-strategy.js +6 -7
- package/dist/esm/onchain/accounts/intents/plan.js +43 -21
- package/dist/esm/onchain/accounts/intents/realize.js +23 -8
- package/dist/esm/onchain/accounts/intents/refusal.js +26 -0
- package/dist/esm/onchain/accounts/intents/tail.js +2 -2
- package/dist/esm/onchain/accounts/intents/types.js +1 -16
- package/dist/esm/onchain/index.js +2 -2
- package/dist/esm/onchain/utils/bigint-math.js +9 -0
- package/dist/esm/sdk/GearboxSDK.js +2 -2
- package/dist/esm/sdk/prepare/PrepareApi.js +19 -20
- package/dist/types/onchain/accounts/index.d.ts +3 -2
- package/dist/types/onchain/accounts/intents/guards.d.ts +23 -5
- package/dist/types/onchain/accounts/intents/index.d.ts +4 -6
- package/dist/types/onchain/accounts/intents/math.d.ts +2 -1
- package/dist/types/onchain/accounts/intents/refusal.d.ts +175 -0
- package/dist/types/onchain/accounts/intents/types.d.ts +7 -71
- package/dist/types/onchain/index.d.ts +3 -2
- package/dist/types/onchain/utils/bigint-math.d.ts +9 -0
- package/dist/types/sdk/index.d.ts +3 -1
- package/dist/types/sdk/prepare/index.d.ts +3 -1
- package/dist/types/sdk/prepare/types.d.ts +14 -26
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@ const require_onchain_accounts_credit_account_compressor_CreditAccountCompressor
|
|
|
6
6
|
const require_onchain_accounts_credit_account_compressor_CreditAccountCompressor = require("./credit-account-compressor/CreditAccountCompressor.js");
|
|
7
7
|
require("./credit-account-compressor/index.js");
|
|
8
8
|
const require_onchain_accounts_CreditAccountsServiceV310 = require("./CreditAccountsServiceV310.js");
|
|
9
|
-
const
|
|
9
|
+
const require_onchain_accounts_intents_refusal = require("./intents/refusal.js");
|
|
10
10
|
const require_onchain_accounts_intents_utils_credit_account_slice = require("./intents/utils/credit-account-slice.js");
|
|
11
11
|
const require_onchain_accounts_intents_index = require("./intents/index.js");
|
|
12
12
|
const require_onchain_accounts_liquidations_constants = require("./liquidations/constants.js");
|
|
@@ -34,7 +34,7 @@ exports.CreditAccountOperationsService = require_onchain_accounts_intents_index.
|
|
|
34
34
|
exports.CreditAccountsServiceV310 = require_onchain_accounts_CreditAccountsServiceV310.CreditAccountsServiceV310;
|
|
35
35
|
exports.DELAYED_INTENT_TYPES = require_onchain_accounts_withdrawal_compressor_intent_codec.DELAYED_INTENT_TYPES;
|
|
36
36
|
exports.DELAYED_INTENT_VERSION = require_onchain_accounts_withdrawal_compressor_intent_codec.DELAYED_INTENT_VERSION;
|
|
37
|
-
exports.IntentPreviewError =
|
|
37
|
+
exports.IntentPreviewError = require_onchain_accounts_intents_refusal.IntentPreviewError;
|
|
38
38
|
exports.InvalidDelayedIntentError = require_onchain_accounts_withdrawal_compressor_errors.InvalidDelayedIntentError;
|
|
39
39
|
exports.LIQUIDATION_APPROVAL_BUFFER = require_onchain_accounts_liquidations_constants.LIQUIDATION_APPROVAL_BUFFER;
|
|
40
40
|
exports.LIQUIDATION_COMPRESSOR_V313_ADDRESS = require_onchain_accounts_liquidations_constants.LIQUIDATION_COMPRESSOR_V313_ADDRESS;
|
|
@@ -52,6 +52,7 @@ exports.encodeDelayedIntent = require_onchain_accounts_withdrawal_compressor_int
|
|
|
52
52
|
exports.fetchCreditAccountSlice = require_onchain_accounts_intents_utils_credit_account_slice.fetchCreditAccountSlice;
|
|
53
53
|
exports.getWithdrawalCompressorAddress = require_onchain_accounts_withdrawal_compressor_addresses.getWithdrawalCompressorAddress;
|
|
54
54
|
exports.iCreditAccountAbi = require_onchain_accounts_withdrawal_compressor_AbstractWithdrawalCompressorContract.iCreditAccountAbi;
|
|
55
|
+
exports.refuse = require_onchain_accounts_intents_refusal.refuse;
|
|
55
56
|
exports.toClaimableWithdrawal = require_onchain_accounts_withdrawal_compressor_AbstractWithdrawalCompressorContract.toClaimableWithdrawal;
|
|
56
57
|
exports.toCreditAccountSlice = require_onchain_accounts_intents_utils_credit_account_slice.toCreditAccountSlice;
|
|
57
58
|
exports.toPendingWithdrawal = require_onchain_accounts_withdrawal_compressor_AbstractWithdrawalCompressorContract.toPendingWithdrawal;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
require("../../constants/math.js");
|
|
2
|
+
const require_onchain_constants_math = require("../../constants/math.js");
|
|
3
3
|
require("../../constants/index.js");
|
|
4
|
-
const
|
|
4
|
+
const require_onchain_accounts_intents_refusal = require("./refusal.js");
|
|
5
5
|
const require_onchain_accounts_intents_utils_common = require("./utils/common.js");
|
|
6
6
|
const require_onchain_accounts_intents_utils_pick_token = require("./utils/pick-token.js");
|
|
7
7
|
//#region src/onchain/accounts/intents/guards.ts
|
|
@@ -13,14 +13,23 @@ const require_onchain_accounts_intents_utils_pick_token = require("./utils/pick-
|
|
|
13
13
|
* pool has run out of what it lends. On-chain those come back as a reverted
|
|
14
14
|
* multicall with a selector no form can explain, so they are read from the
|
|
15
15
|
* loaded market and reported as refusals instead.
|
|
16
|
+
*
|
|
17
|
+
* Every guard here refuses something the market decides rather than something
|
|
18
|
+
* the arithmetic cannot do, which is why all six of their reasons are
|
|
19
|
+
* `blocking`: the walk that hit one still reached an end state, and a caller
|
|
20
|
+
* gets that state alongside the refusal.
|
|
16
21
|
*/
|
|
17
22
|
/**
|
|
18
23
|
* The facade takes no multicall while it is paused or past its expiration, so
|
|
19
24
|
* every intent the engine previews would revert on arrival.
|
|
20
25
|
*/
|
|
21
26
|
function assertMarketOperable(suite) {
|
|
22
|
-
|
|
23
|
-
if (suite.
|
|
27
|
+
const creditManager = suite.creditManager.address;
|
|
28
|
+
if (suite.isPaused) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("marketPaused", { creditManager }, `${creditManager} is paused`);
|
|
29
|
+
if (suite.isExpired) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("marketExpired", {
|
|
30
|
+
creditManager,
|
|
31
|
+
expirationDate: suite.creditFacade.expirationDate
|
|
32
|
+
}, `${creditManager} expired at ${suite.creditFacade.expirationDate}`);
|
|
24
33
|
}
|
|
25
34
|
/**
|
|
26
35
|
* What the pool will hand this manager in one transaction: the tightest of its
|
|
@@ -42,7 +51,19 @@ function borrowable(suite) {
|
|
|
42
51
|
/** The pool has to be able to lend what the plan means to draw. */
|
|
43
52
|
function assertCanBorrow(suite, amount) {
|
|
44
53
|
const limit = borrowable(suite);
|
|
45
|
-
if (amount > limit)
|
|
54
|
+
if (amount > limit) {
|
|
55
|
+
const token = suite.market.pool.underlying;
|
|
56
|
+
throw new require_onchain_accounts_intents_refusal.IntentPreviewError("insufficientPoolLiquidity", {
|
|
57
|
+
requested: {
|
|
58
|
+
token,
|
|
59
|
+
balance: amount
|
|
60
|
+
},
|
|
61
|
+
available: {
|
|
62
|
+
token,
|
|
63
|
+
balance: limit
|
|
64
|
+
}
|
|
65
|
+
}, `borrow: ${amount} exceeds what the pool can lend now (${limit})`);
|
|
66
|
+
}
|
|
46
67
|
}
|
|
47
68
|
/**
|
|
48
69
|
* What the account is allowed to end up holding more of than it started with.
|
|
@@ -62,9 +83,16 @@ function assertGrowthAllowed(args) {
|
|
|
62
83
|
const underlying = market.pool.underlying;
|
|
63
84
|
for (const { token, balance } of after) {
|
|
64
85
|
if (balance <= (before.find((a) => require_onchain_accounts_intents_utils_common.eq(a.token, token))?.balance ?? 0n)) continue;
|
|
65
|
-
if (forbidden.some((f) => require_onchain_accounts_intents_utils_common.eq(f, token))) throw new
|
|
86
|
+
if (forbidden.some((f) => require_onchain_accounts_intents_utils_common.eq(f, token))) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("forbiddenToken", { token }, `${token} is forbidden in this market and the plan buys more of it`);
|
|
66
87
|
if (require_onchain_accounts_intents_utils_common.eq(token, underlying) || require_onchain_accounts_intents_utils_pick_token.isPhantomToken(sdk, token)) continue;
|
|
67
|
-
if (!market.pool.pqk.hasActiveQuota(token)) throw new
|
|
88
|
+
if (!market.pool.pqk.hasActiveQuota(token)) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("quotaLimitReached", {
|
|
89
|
+
token,
|
|
90
|
+
requested: void 0,
|
|
91
|
+
available: {
|
|
92
|
+
token: underlying,
|
|
93
|
+
balance: 0n
|
|
94
|
+
}
|
|
95
|
+
}, `${token} takes no quota in this market, so it counts as no collateral`);
|
|
68
96
|
}
|
|
69
97
|
}
|
|
70
98
|
/**
|
|
@@ -72,10 +100,23 @@ function assertGrowthAllowed(args) {
|
|
|
72
100
|
* and reverts if the collateral does not cover it, so a plan that lands the
|
|
73
101
|
* account below water is refused here.
|
|
74
102
|
*
|
|
75
|
-
* The bar is the
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
103
|
+
* The bar is the facade's own `1.0`, because this guard answers one question:
|
|
104
|
+
* would the transaction revert. It is deliberately not `MIN_HF_LIMITED`, and
|
|
105
|
+
* the three bars in this codebase are three different jobs:
|
|
106
|
+
*
|
|
107
|
+
* - here, `1.0` — what the facade enforces, so what a plan must clear to land;
|
|
108
|
+
* - `maxWithdrawCollateral` sizes at `MIN_HF_LIMITED + 2` — a *sizing* helper
|
|
109
|
+
* leaving headroom, which is not the same as a validity check;
|
|
110
|
+
* - `validateHF` refuses at or below `MIN_HF_LIMITED` — a form's own caution.
|
|
111
|
+
*
|
|
112
|
+
* Raising this one to `MIN_HF_LIMITED` was tried and reverted: it made
|
|
113
|
+
* `maxWithdraw` hand back a ceiling this guard then refused, and it blocked
|
|
114
|
+
* small top-ups of an account sitting in `[1.0, 1.01)` — the very operations
|
|
115
|
+
* that rescue it. A form wanting the stricter bar has `validateHF`.
|
|
116
|
+
*
|
|
117
|
+
* Note that a position already underwater cannot be nursed back one step at a
|
|
118
|
+
* time — the check is on where the transaction ends, not on whether it
|
|
119
|
+
* improved things.
|
|
79
120
|
*
|
|
80
121
|
* @remarks
|
|
81
122
|
* The caller decides the pricing the factor was computed at: main prices, or
|
|
@@ -83,20 +124,36 @@ function assertGrowthAllowed(args) {
|
|
|
83
124
|
* whose reserve feed the SDK cannot read keeps its main price, so a plan can
|
|
84
125
|
* still be refused on-chain after passing here.
|
|
85
126
|
*/
|
|
86
|
-
function assertCollateralised(healthFactorBps) {
|
|
87
|
-
|
|
127
|
+
function assertCollateralised(healthFactorBps, safePrices) {
|
|
128
|
+
const required = Number(require_onchain_constants_math.PERCENTAGE_FACTOR);
|
|
129
|
+
if (healthFactorBps < required) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("insufficientCollateral", {
|
|
130
|
+
healthFactor: healthFactorBps,
|
|
131
|
+
required,
|
|
132
|
+
safePrices
|
|
133
|
+
}, `the account would end at a health factor of ${healthFactorBps}, below ${required}`);
|
|
88
134
|
}
|
|
89
135
|
/**
|
|
90
136
|
* A quota can only be raised as far as the market still has room for: past the
|
|
91
137
|
* token's limit the keeper takes nothing more, whoever is asking.
|
|
92
138
|
*/
|
|
93
139
|
function assertQuotaHeadroom(market, increases) {
|
|
140
|
+
const underlying = market.pool.underlying;
|
|
94
141
|
for (const { token, balance } of increases) {
|
|
95
142
|
if (balance <= 0n) continue;
|
|
96
143
|
const quota = market.pool.pqk.quotas.get(token);
|
|
97
144
|
if (!quota) continue;
|
|
98
145
|
const left = quota.limit - quota.totalQuoted;
|
|
99
|
-
if (balance > left) throw new
|
|
146
|
+
if (balance > left) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("quotaLimitReached", {
|
|
147
|
+
token,
|
|
148
|
+
requested: {
|
|
149
|
+
token: underlying,
|
|
150
|
+
balance
|
|
151
|
+
},
|
|
152
|
+
available: {
|
|
153
|
+
token: underlying,
|
|
154
|
+
balance: left
|
|
155
|
+
}
|
|
156
|
+
}, `${token} has ${left} of quota left, the plan needs ${balance}`);
|
|
100
157
|
}
|
|
101
158
|
}
|
|
102
159
|
//#endregion
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_onchain_base_SDKConstruct = require("../../base/SDKConstruct.js");
|
|
3
3
|
const require_common_utils_utils_validation_validate_hf = require("../../../common-utils/utils/validation/validate-hf.js");
|
|
4
|
-
const
|
|
4
|
+
const require_onchain_accounts_intents_refusal = require("./refusal.js");
|
|
5
5
|
const require_onchain_accounts_intents_guards = require("./guards.js");
|
|
6
6
|
const require_onchain_accounts_intents_math = require("./math.js");
|
|
7
7
|
const require_onchain_accounts_intents_maxWithdrawCollateral = require("./maxWithdrawCollateral.js");
|
|
@@ -170,9 +170,11 @@ var CreditAccountOperationsService = class extends require_onchain_base_SDKConst
|
|
|
170
170
|
const [instant, delayed] = await Promise.allSettled([this.startIntent(props), this.startDelayedIntent(props)]);
|
|
171
171
|
const instantRoute = instant.status === "fulfilled" && instant.value.ok ? instant.value : void 0;
|
|
172
172
|
const delayedRoute = delayed.status === "fulfilled" && delayed.value.ok ? delayed.value : void 0;
|
|
173
|
+
const instantRefusal = instant.status === "fulfilled" && !instant.value.ok ? instant.value : void 0;
|
|
174
|
+
const delayedRefusal = delayed.status === "fulfilled" && !delayed.value.ok ? delayed.value : void 0;
|
|
173
175
|
const refused = {
|
|
174
|
-
instant:
|
|
175
|
-
delayed:
|
|
176
|
+
instant: instantRefusal?.reason,
|
|
177
|
+
delayed: delayedRefusal?.reason
|
|
176
178
|
};
|
|
177
179
|
if (instantRoute || delayedRoute) return {
|
|
178
180
|
ok: true,
|
|
@@ -182,11 +184,10 @@ var CreditAccountOperationsService = class extends require_onchain_base_SDKConst
|
|
|
182
184
|
};
|
|
183
185
|
const failed = [instant, delayed].find((s) => s.status === "rejected");
|
|
184
186
|
if (failed?.status === "rejected") throw failed.reason;
|
|
185
|
-
const
|
|
186
|
-
if (
|
|
187
|
+
const chosen = instantRefusal ?? delayedRefusal;
|
|
188
|
+
if (chosen === void 0) throw new Error("intentRoutes: a route neither answered nor refused");
|
|
187
189
|
return {
|
|
188
|
-
|
|
189
|
-
reason,
|
|
190
|
+
...chosen,
|
|
190
191
|
refused
|
|
191
192
|
};
|
|
192
193
|
}
|
|
@@ -268,14 +269,8 @@ function plain(result) {
|
|
|
268
269
|
}
|
|
269
270
|
/** Unviable requests are values; anything else is a genuine failure. */
|
|
270
271
|
function asFailure(e) {
|
|
271
|
-
if (e instanceof
|
|
272
|
-
|
|
273
|
-
reason: e.reason
|
|
274
|
-
};
|
|
275
|
-
if (isUnroutable(e)) return {
|
|
276
|
-
ok: false,
|
|
277
|
-
reason: "unsupportedTokenPair"
|
|
278
|
-
};
|
|
272
|
+
if (e instanceof require_onchain_accounts_intents_refusal.IntentPreviewError) return require_onchain_accounts_intents_refusal.refuse(e.reason, e.detail);
|
|
273
|
+
if (isUnroutable(e)) return require_onchain_accounts_intents_refusal.refuse("unsupportedTokenPair", void 0);
|
|
279
274
|
throw e;
|
|
280
275
|
}
|
|
281
276
|
/**
|
|
@@ -292,6 +287,7 @@ function isUnroutable(e) {
|
|
|
292
287
|
}
|
|
293
288
|
//#endregion
|
|
294
289
|
exports.CreditAccountOperationsService = CreditAccountOperationsService;
|
|
295
|
-
exports.IntentPreviewError =
|
|
290
|
+
exports.IntentPreviewError = require_onchain_accounts_intents_refusal.IntentPreviewError;
|
|
296
291
|
exports.fetchCreditAccountSlice = require_onchain_accounts_intents_utils_credit_account_slice.fetchCreditAccountSlice;
|
|
292
|
+
exports.refuse = require_onchain_accounts_intents_refusal.refuse;
|
|
297
293
|
exports.toCreditAccountSlice = require_onchain_accounts_intents_utils_credit_account_slice.toCreditAccountSlice;
|
|
@@ -1,6 +1,7 @@
|
|
|
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
|
-
const
|
|
4
|
+
const require_onchain_accounts_intents_refusal = require("./refusal.js");
|
|
4
5
|
//#region src/onchain/accounts/intents/math.ts
|
|
5
6
|
/** Debt that realises `leverage` on `collateral`: `D = C · (L − 1)`. */
|
|
6
7
|
function debtForLeverage(collateral, leverage) {
|
|
@@ -14,7 +15,7 @@ function debtForLeverage(collateral, leverage) {
|
|
|
14
15
|
* it, so no rounding is introduced on the way.
|
|
15
16
|
*/
|
|
16
17
|
function proportionalDebt(position, collateralDelta) {
|
|
17
|
-
if (position.collateral <= 0n) throw new
|
|
18
|
+
if (position.collateral <= 0n) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("insufficientSourceBalance", void 0, "cannot preserve leverage on an account with no collateral");
|
|
18
19
|
return position.debt * collateralDelta / position.collateral;
|
|
19
20
|
}
|
|
20
21
|
/**
|
|
@@ -32,21 +33,37 @@ function maxProportionalWithdrawal(position, band) {
|
|
|
32
33
|
if (debt === 0n) return allButLast;
|
|
33
34
|
const repayable = debt - band.minDebt;
|
|
34
35
|
if (repayable < 0n) return 0n;
|
|
35
|
-
const bound = ceilDiv(collateral * (repayable + 1n), debt) - 1n;
|
|
36
|
+
const bound = require_onchain_utils_bigint_math.BigIntMath.ceilDiv(collateral * (repayable + 1n), debt) - 1n;
|
|
36
37
|
return bound < allButLast ? bound : allButLast;
|
|
37
38
|
}
|
|
38
|
-
const ceilDiv = (a, b) => (a + b - 1n) / b;
|
|
39
39
|
/** Total leverage cannot drop below 1x — that would be negative debt. */
|
|
40
40
|
function assertLeverageAtLeastOne(leverage) {
|
|
41
|
-
if (leverage < 100n) throw new
|
|
41
|
+
if (leverage < 100n) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("leverageOutOfRange", {
|
|
42
|
+
requested: leverage,
|
|
43
|
+
min: require_onchain_constants_math.LEVERAGE_DECIMALS
|
|
44
|
+
}, `target leverage ${leverage} is below 1x`);
|
|
42
45
|
}
|
|
43
46
|
/**
|
|
44
47
|
* Rejects a debt the facade would revert on: zero is always fine (no loan at
|
|
45
48
|
* all), anything else has to sit inside `[minDebt, maxDebt]`.
|
|
46
49
|
*/
|
|
47
|
-
function assertDebtInBand(debt, band) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
function assertDebtInBand(debt, band, underlying) {
|
|
51
|
+
const detail = {
|
|
52
|
+
requested: {
|
|
53
|
+
token: underlying,
|
|
54
|
+
balance: debt
|
|
55
|
+
},
|
|
56
|
+
minDebt: {
|
|
57
|
+
token: underlying,
|
|
58
|
+
balance: band.minDebt
|
|
59
|
+
},
|
|
60
|
+
maxDebt: {
|
|
61
|
+
token: underlying,
|
|
62
|
+
balance: band.maxDebt
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
if (debt > band.maxDebt) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("debtOutOfRange", detail, `debt ${debt} exceeds maxDebt ${band.maxDebt}`);
|
|
66
|
+
if (debt > 0n && debt < band.minDebt) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("debtOutOfRange", detail, `debt ${debt} is below minDebt ${band.minDebt}`);
|
|
50
67
|
}
|
|
51
68
|
//#endregion
|
|
52
69
|
exports.assertDebtInBand = assertDebtInBand;
|
|
@@ -57,8 +57,8 @@ function maxWithdrawCollateral(props) {
|
|
|
57
57
|
const targetLt = BigInt(creditManager.liquidationThresholds.get(target.token) ?? 0);
|
|
58
58
|
const targetUsd = safeUsd(priceOracle, target.token, target.balance);
|
|
59
59
|
if (targetLt === 0n || !targetUsd) return 0n;
|
|
60
|
-
const keptUsd = ceilDiv(shortfall, targetLt);
|
|
61
|
-
const kept = ceilDiv(target.balance * keptUsd, targetUsd);
|
|
60
|
+
const keptUsd = require_onchain_utils_bigint_math.BigIntMath.ceilDiv(shortfall, targetLt);
|
|
61
|
+
const kept = require_onchain_utils_bigint_math.BigIntMath.ceilDiv(target.balance * keptUsd, targetUsd);
|
|
62
62
|
return kept >= target.balance ? 0n : target.balance - kept;
|
|
63
63
|
}
|
|
64
64
|
/** USD value at the main feed, or `undefined` when the token has no price. */
|
|
@@ -82,8 +82,5 @@ function safeUsd(oracle, token, amount) {
|
|
|
82
82
|
return main;
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
-
function ceilDiv(a, b) {
|
|
86
|
-
return (a + b - 1n) / b;
|
|
87
|
-
}
|
|
88
85
|
//#endregion
|
|
89
86
|
exports.maxWithdrawCollateral = maxWithdrawCollateral;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
require("
|
|
3
|
-
const require_onchain_accounts_intents_types = require("./types.js");
|
|
2
|
+
const require_onchain_accounts_intents_refusal = require("./refusal.js");
|
|
4
3
|
const require_onchain_accounts_intents_utils_convert_amount = require("./utils/convert-amount.js");
|
|
5
4
|
const require_onchain_accounts_intents_guards = require("./guards.js");
|
|
6
5
|
const require_onchain_accounts_intents_math = require("./math.js");
|
|
@@ -23,14 +22,14 @@ const NO_ACCOUNT = "0x0000000000000000000000000000000000000000";
|
|
|
23
22
|
*/
|
|
24
23
|
async function previewOpenStrategy(props) {
|
|
25
24
|
const { sdk, creditManager, collateral, targetToken, leverage, slippage = 0, quotaReserve, leftoverBalances = [] } = props;
|
|
26
|
-
|
|
25
|
+
require_onchain_accounts_intents_math.assertLeverageAtLeastOne(leverage);
|
|
27
26
|
const suite = sdk.marketRegister.findCreditManager(creditManager);
|
|
28
27
|
const market = sdk.marketRegister.findByCreditManager(creditManager);
|
|
29
28
|
require_onchain_accounts_intents_guards.assertMarketOperable(suite);
|
|
30
29
|
const underlying = market.pool.underlying.toLowerCase();
|
|
31
30
|
const convert = require_onchain_accounts_intents_utils_convert_amount.convertAmount(sdk, creditManager);
|
|
32
31
|
const margin = collateral.reduce((acc, a) => acc + convert(a.token, underlying, a.balance), 0n);
|
|
33
|
-
if (margin <= 0n) throw new
|
|
32
|
+
if (margin <= 0n) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("insufficientSourceBalance", void 0, "openStrategy: collateral is worth nothing in underlying");
|
|
34
33
|
const debt = require_onchain_accounts_intents_math.debtForLeverage(margin, leverage);
|
|
35
34
|
const account = {
|
|
36
35
|
creditAccount: NO_ACCOUNT,
|
|
@@ -42,7 +41,7 @@ async function previewOpenStrategy(props) {
|
|
|
42
41
|
accountDebt: 0n,
|
|
43
42
|
tokens: []
|
|
44
43
|
};
|
|
45
|
-
require_onchain_accounts_intents_math.assertDebtInBand(debt, suite.creditFacade);
|
|
44
|
+
require_onchain_accounts_intents_math.assertDebtInBand(debt, suite.creditFacade, underlying);
|
|
46
45
|
require_onchain_accounts_intents_guards.assertCanBorrow(suite, debt);
|
|
47
46
|
const leg = await require_onchain_accounts_intents_utils_router_path.createRouterPaths({
|
|
48
47
|
sdk,
|
|
@@ -91,7 +90,7 @@ async function previewOpenStrategy(props) {
|
|
|
91
90
|
timeToLiquidation: sdk.positions.timeToLiquidation(snapshot, projectedPool),
|
|
92
91
|
liquidationPrice: sdk.positions.liquidationPrice(snapshot)
|
|
93
92
|
};
|
|
94
|
-
require_onchain_accounts_intents_guards.assertCollateralised(metrics.healthFactor);
|
|
93
|
+
require_onchain_accounts_intents_guards.assertCollateralised(metrics.healthFactor, false);
|
|
95
94
|
return {
|
|
96
95
|
debt,
|
|
97
96
|
collateral: margin,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_onchain_constants_math = require("../../constants/math.js");
|
|
3
3
|
require("../../constants/index.js");
|
|
4
|
-
const
|
|
4
|
+
const require_onchain_accounts_intents_refusal = require("./refusal.js");
|
|
5
5
|
const require_onchain_accounts_intents_utils_common = require("./utils/common.js");
|
|
6
6
|
const require_onchain_accounts_intents_math = require("./math.js");
|
|
7
7
|
//#region src/onchain/accounts/intents/plan.ts
|
|
@@ -24,18 +24,27 @@ function planAdjustLeverage(intent, view) {
|
|
|
24
24
|
const T = intent.token ?? positionToken(view, "adjustLeverage");
|
|
25
25
|
if (delta > 0n) return [borrow(delta), convert(U, T, delta)];
|
|
26
26
|
const shortfall = -delta - view.balanceOf(U);
|
|
27
|
-
if (shortfall > 0n && require_onchain_accounts_intents_utils_common.eq(T, U)) throw new
|
|
27
|
+
if (shortfall > 0n && require_onchain_accounts_intents_utils_common.eq(T, U)) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("insufficientSourceBalance", {
|
|
28
|
+
required: {
|
|
29
|
+
token: U,
|
|
30
|
+
balance: -delta
|
|
31
|
+
},
|
|
32
|
+
held: {
|
|
33
|
+
token: U,
|
|
34
|
+
balance: view.balanceOf(U)
|
|
35
|
+
}
|
|
36
|
+
}, `adjustLeverage: needs ${-delta} underlying, account holds ${view.balanceOf(U)}`);
|
|
28
37
|
return [...shortfall > 0n ? [convert(T, U, view.price(U, T, shortfall))] : [], repay(-delta)];
|
|
29
38
|
}
|
|
30
39
|
/** Intents 1.1 / 1.2: collateral grows by `a`, debt grows to match. */
|
|
31
40
|
function planDeposit(intent, view) {
|
|
32
41
|
assertPositive(intent.amount, "deposit");
|
|
33
42
|
const U = view.underlying;
|
|
34
|
-
if (!require_onchain_accounts_intents_utils_common.eq(intent.token, U) && !(view.rwaAsset && require_onchain_accounts_intents_utils_common.eq(intent.token, view.rwaAsset))) throw new
|
|
43
|
+
if (!require_onchain_accounts_intents_utils_common.eq(intent.token, U) && !(view.rwaAsset && require_onchain_accounts_intents_utils_common.eq(intent.token, view.rwaAsset))) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("unsupportedCollateralToken", { token: intent.token }, `deposit: only ${U}${view.rwaAsset ? ` or ${view.rwaAsset}` : ""} can be deposited, got ${intent.token}`);
|
|
35
44
|
const aU = view.price(intent.token, U, intent.amount);
|
|
36
45
|
const debtDelta = intent.targetLeverage === void 0 ? require_onchain_accounts_intents_math.proportionalDebt(view, aU) : require_onchain_accounts_intents_math.debtForLeverage(view.collateral + aU, intent.targetLeverage) - view.debt;
|
|
37
|
-
if (debtDelta < 0n) throw new
|
|
38
|
-
require_onchain_accounts_intents_math.assertDebtInBand(view.debt + debtDelta, view.band);
|
|
46
|
+
if (debtDelta < 0n) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("leverageOutOfRange", void 0, `deposit: target leverage ${intent.targetLeverage} would require repaying debt`);
|
|
47
|
+
require_onchain_accounts_intents_math.assertDebtInBand(view.debt + debtDelta, view.band, U);
|
|
39
48
|
const T = intent.positionToken ?? positionToken(view, "deposit");
|
|
40
49
|
const depositStays = require_onchain_accounts_intents_utils_common.eq(intent.token, T);
|
|
41
50
|
return [
|
|
@@ -62,11 +71,24 @@ function planRepay(intent, view) {
|
|
|
62
71
|
assertPositive(intent.amount, "repay");
|
|
63
72
|
const U = view.underlying;
|
|
64
73
|
const fundsInU = require_onchain_accounts_intents_utils_common.eq(intent.token, U);
|
|
65
|
-
if (!fundsInU && !(view.rwaAsset && require_onchain_accounts_intents_utils_common.eq(intent.token, view.rwaAsset))) throw new
|
|
66
|
-
if (view.debt <= 0n) throw new
|
|
74
|
+
if (!fundsInU && !(view.rwaAsset && require_onchain_accounts_intents_utils_common.eq(intent.token, view.rwaAsset))) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("unsupportedCollateralToken", { token: intent.token }, `repay: only ${U}${view.rwaAsset ? ` or ${view.rwaAsset}` : ""} can be repaid with, got ${intent.token}`);
|
|
75
|
+
if (view.debt <= 0n) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("debtOutOfRange", {
|
|
76
|
+
requested: {
|
|
77
|
+
token: U,
|
|
78
|
+
balance: view.debt
|
|
79
|
+
},
|
|
80
|
+
minDebt: {
|
|
81
|
+
token: U,
|
|
82
|
+
balance: view.band.minDebt
|
|
83
|
+
},
|
|
84
|
+
maxDebt: {
|
|
85
|
+
token: U,
|
|
86
|
+
balance: view.band.maxDebt
|
|
87
|
+
}
|
|
88
|
+
}, "repay: the account owes nothing");
|
|
67
89
|
const funding = everything(intent.amount) ? view.price(U, intent.token, withMargin(view.debt)) : intent.amount;
|
|
68
90
|
const repaid = min(view.price(intent.token, U, funding), view.debt);
|
|
69
|
-
require_onchain_accounts_intents_math.assertDebtInBand(view.debt - repaid, view.band);
|
|
91
|
+
require_onchain_accounts_intents_math.assertDebtInBand(view.debt - repaid, view.band, U);
|
|
70
92
|
return [
|
|
71
93
|
add(intent.token, funding, intent.value),
|
|
72
94
|
...fundsInU ? [] : [convert(intent.token, U, funding)],
|
|
@@ -122,7 +144,7 @@ function planWithdrawDelayed(intent, view) {
|
|
|
122
144
|
const { U, T, S, WU, dD, all } = withdrawShape(intent, view);
|
|
123
145
|
if (all) {
|
|
124
146
|
const held = view.balanceOf(S);
|
|
125
|
-
if (held <= 0n) throw new
|
|
147
|
+
if (held <= 0n) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("insufficientSourceBalance", void 0, `withdraw: account holds no ${S} to redeem`);
|
|
126
148
|
return [{
|
|
127
149
|
kind: "request",
|
|
128
150
|
token: S,
|
|
@@ -134,7 +156,7 @@ function planWithdrawDelayed(intent, view) {
|
|
|
134
156
|
}
|
|
135
157
|
}];
|
|
136
158
|
}
|
|
137
|
-
if (!require_onchain_accounts_intents_utils_common.eq(T, U) && !(view.rwaAsset && require_onchain_accounts_intents_utils_common.eq(T, view.rwaAsset))) throw new
|
|
159
|
+
if (!require_onchain_accounts_intents_utils_common.eq(T, U) && !(view.rwaAsset && require_onchain_accounts_intents_utils_common.eq(T, view.rwaAsset))) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("noDelayedRoute", { token: T }, `withdraw: a delayed route cannot pay out in ${T}`);
|
|
138
160
|
const payoutIsSource = require_onchain_accounts_intents_utils_common.eq(T, S);
|
|
139
161
|
return [{
|
|
140
162
|
kind: "request",
|
|
@@ -160,9 +182,9 @@ function planWithdrawDelayed(intent, view) {
|
|
|
160
182
|
*/
|
|
161
183
|
function planAdjustLeverageDelayed(intent, view) {
|
|
162
184
|
const { U, delta } = leverageShape(intent, view);
|
|
163
|
-
if (delta >= 0n) throw new
|
|
185
|
+
if (delta >= 0n) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("noDelayedRoute", void 0, "adjustLeverage: only deleveraging can settle with a delay");
|
|
164
186
|
const shortfall = -delta - view.balanceOf(U);
|
|
165
|
-
if (shortfall <= 0n) throw new
|
|
187
|
+
if (shortfall <= 0n) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("noDelayedRoute", void 0, "adjustLeverage: idle underlying covers the repayment, nothing to redeem");
|
|
166
188
|
const T = intent.token ?? positionToken(view, "adjustLeverage");
|
|
167
189
|
return [{
|
|
168
190
|
kind: "request",
|
|
@@ -190,7 +212,7 @@ function planFinishWithdraw(intent, claimable, claimed, view) {
|
|
|
190
212
|
const U = view.underlying;
|
|
191
213
|
const T = intent.withdrawToken;
|
|
192
214
|
const W = intent.withdrawAmount;
|
|
193
|
-
if (!require_onchain_accounts_intents_utils_common.eq(T, U) && !(view.rwaAsset && require_onchain_accounts_intents_utils_common.eq(T, view.rwaAsset))) throw new
|
|
215
|
+
if (!require_onchain_accounts_intents_utils_common.eq(T, U) && !(view.rwaAsset && require_onchain_accounts_intents_utils_common.eq(T, view.rwaAsset))) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("noDelayedRoute", { token: T }, `finishWithdraw: cannot pay out in ${T}`);
|
|
194
216
|
if (intent.debtRepaid === 0n) return [
|
|
195
217
|
claim(claimable),
|
|
196
218
|
convert(claimed.token, T, claimed.amount),
|
|
@@ -282,7 +304,7 @@ function withdrawShape(intent, view) {
|
|
|
282
304
|
};
|
|
283
305
|
}
|
|
284
306
|
const WU = view.price(T, U, intent.amount);
|
|
285
|
-
if (WU <= 0n) throw new
|
|
307
|
+
if (WU <= 0n) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("insufficientSourceBalance", void 0, `withdraw: cannot price ${intent.amount} of ${T}`);
|
|
286
308
|
if (WU >= view.collateral) {
|
|
287
309
|
assertHasValue(view);
|
|
288
310
|
return {
|
|
@@ -295,7 +317,7 @@ function withdrawShape(intent, view) {
|
|
|
295
317
|
};
|
|
296
318
|
}
|
|
297
319
|
const dD = require_onchain_accounts_intents_math.proportionalDebt(view, WU);
|
|
298
|
-
require_onchain_accounts_intents_math.assertDebtInBand(view.debt - dD, view.band);
|
|
320
|
+
require_onchain_accounts_intents_math.assertDebtInBand(view.debt - dD, view.band, U);
|
|
299
321
|
return {
|
|
300
322
|
U,
|
|
301
323
|
T,
|
|
@@ -312,9 +334,9 @@ function withdrawShape(intent, view) {
|
|
|
312
334
|
*/
|
|
313
335
|
function leverageShape(intent, view) {
|
|
314
336
|
require_onchain_accounts_intents_math.assertLeverageAtLeastOne(intent.targetLeverage);
|
|
315
|
-
if (view.collateral <= 0n) throw new
|
|
337
|
+
if (view.collateral <= 0n) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("insufficientSourceBalance", void 0, "adjustLeverage: account has no collateral to lever");
|
|
316
338
|
const target = require_onchain_accounts_intents_math.debtForLeverage(view.collateral, intent.targetLeverage);
|
|
317
|
-
require_onchain_accounts_intents_math.assertDebtInBand(target, view.band);
|
|
339
|
+
require_onchain_accounts_intents_math.assertDebtInBand(target, view.band, view.underlying);
|
|
318
340
|
return {
|
|
319
341
|
U: view.underlying,
|
|
320
342
|
delta: target - view.debt
|
|
@@ -380,20 +402,20 @@ function payout(view, token, amount, to) {
|
|
|
380
402
|
}
|
|
381
403
|
function positionToken(view, flow) {
|
|
382
404
|
const pick = view.fattest([view.underlying]);
|
|
383
|
-
if (!pick) throw new
|
|
405
|
+
if (!pick) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("insufficientSourceBalance", void 0, `${flow}: no position token on the account`);
|
|
384
406
|
return pick;
|
|
385
407
|
}
|
|
386
408
|
function sourceToken(view) {
|
|
387
409
|
const pick = view.fattest();
|
|
388
|
-
if (!pick) throw new
|
|
410
|
+
if (!pick) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("insufficientSourceBalance", void 0, "withdraw: account has no spendable balance");
|
|
389
411
|
return pick;
|
|
390
412
|
}
|
|
391
413
|
/** An account whose debt has eaten its collateral has nothing to hand over. */
|
|
392
414
|
function assertHasValue(view) {
|
|
393
|
-
if (view.collateral <= 0n) throw new
|
|
415
|
+
if (view.collateral <= 0n) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("insufficientSourceBalance", void 0, `withdraw: nothing to withdraw, net value is ${view.collateral}`);
|
|
394
416
|
}
|
|
395
417
|
function assertPositive(amount, flow) {
|
|
396
|
-
if (amount <= 0n) throw new
|
|
418
|
+
if (amount <= 0n) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("insufficientSourceBalance", void 0, `${flow}: amount must be positive`);
|
|
397
419
|
}
|
|
398
420
|
//#endregion
|
|
399
421
|
exports.RAISED = RAISED;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_onchain_market_math = require("../../market/math.js");
|
|
3
|
-
const
|
|
3
|
+
const require_onchain_accounts_intents_refusal = require("./refusal.js");
|
|
4
4
|
const require_onchain_accounts_intents_utils_common = require("./utils/common.js");
|
|
5
5
|
const require_onchain_accounts_intents_utils_convert_amount = require("./utils/convert-amount.js");
|
|
6
6
|
const require_onchain_accounts_intents_utils_pick_token = require("./utils/pick-token.js");
|
|
@@ -60,7 +60,16 @@ async function realize(steps, props) {
|
|
|
60
60
|
const amountOf = (a) => typeof a === "bigint" ? a : min(raised, a.max ?? raised);
|
|
61
61
|
const assertHolds = (token, amount, what) => {
|
|
62
62
|
const held = ledger.balanceOf(token);
|
|
63
|
-
if (amount <= 0n || held < amount) throw new
|
|
63
|
+
if (amount <= 0n || held < amount) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("insufficientSourceBalance", {
|
|
64
|
+
required: {
|
|
65
|
+
token,
|
|
66
|
+
balance: amount
|
|
67
|
+
},
|
|
68
|
+
held: {
|
|
69
|
+
token,
|
|
70
|
+
balance: held
|
|
71
|
+
}
|
|
72
|
+
}, `${what}: needs ${amount} of ${token}, account holds ${held}`);
|
|
64
73
|
};
|
|
65
74
|
for (const step of steps) switch (step.kind) {
|
|
66
75
|
case "add":
|
|
@@ -144,7 +153,7 @@ async function realize(steps, props) {
|
|
|
144
153
|
case "closeAll": {
|
|
145
154
|
const balances = ledger.snapshot().assets.filter((a) => !require_onchain_accounts_intents_utils_common.eq(a.token, underlying) && a.balance > DUST);
|
|
146
155
|
const pending = balances.find((a) => require_onchain_accounts_intents_utils_pick_token.isRedemptionPhantomToken(sdk, a.token));
|
|
147
|
-
if (pending) throw new
|
|
156
|
+
if (pending) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("withdrawalInProgress", { inFlight: pending }, `closeAll: ${pending.token} is a pending withdrawal, claim it first`);
|
|
148
157
|
if (balances.length > 0) {
|
|
149
158
|
const leg = await paths.closeAll({ balances });
|
|
150
159
|
if (leg.calls.length > 0 || leg.minAmount > 0n) push(require_onchain_accounts_intents_operations.buildCloseSwapOperation({
|
|
@@ -172,7 +181,10 @@ async function realize(steps, props) {
|
|
|
172
181
|
}
|
|
173
182
|
case "request": {
|
|
174
183
|
const asset = await delayedConfig(sdk, creditAccount, step.token);
|
|
175
|
-
if (ledger.balanceOf(asset.withdrawalPhantomToken) > 0n) throw new
|
|
184
|
+
if (ledger.balanceOf(asset.withdrawalPhantomToken) > 0n) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("withdrawalInProgress", { inFlight: {
|
|
185
|
+
token: asset.withdrawalPhantomToken,
|
|
186
|
+
balance: ledger.balanceOf(asset.withdrawalPhantomToken)
|
|
187
|
+
} }, `request: ${asset.withdrawalPhantomToken} already holds a pending withdrawal`);
|
|
176
188
|
assertHolds(step.token, step.amount + step.reserve, "request");
|
|
177
189
|
const preview = await sdk.accounts.previewDelayedWithdrawal({
|
|
178
190
|
creditAccount: creditAccount.creditAccount,
|
|
@@ -271,7 +283,7 @@ async function realize(steps, props) {
|
|
|
271
283
|
timeToLiquidation: sdk.positions.timeToLiquidation(snapshot, projectedPool),
|
|
272
284
|
liquidationPrice: sdk.positions.liquidationPrice(snapshot)
|
|
273
285
|
};
|
|
274
|
-
require_onchain_accounts_intents_guards.assertCollateralised(paysOut ? sdk.positions.healthFactor(snapshot, { safePrices: true }) : metrics.healthFactor);
|
|
286
|
+
require_onchain_accounts_intents_guards.assertCollateralised(paysOut ? sdk.positions.healthFactor(snapshot, { safePrices: true }) : metrics.healthFactor, paysOut);
|
|
275
287
|
const state = {
|
|
276
288
|
totalValue,
|
|
277
289
|
accountDebt: debt,
|
|
@@ -298,10 +310,13 @@ async function realize(steps, props) {
|
|
|
298
310
|
*/
|
|
299
311
|
async function delayedConfig(sdk, creditAccount, token) {
|
|
300
312
|
const compressor = sdk.withdrawalCompressor;
|
|
301
|
-
if (!compressor) throw new
|
|
313
|
+
if (!compressor) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("noDelayedRoute", { token }, "request: chain has no withdrawal compressor");
|
|
302
314
|
const assets = await compressor.findWithdrawableAssets(creditAccount.creditManager, token);
|
|
303
|
-
if (assets.length === 0) throw new
|
|
304
|
-
if (assets.length > 1) throw new
|
|
315
|
+
if (assets.length === 0) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("noDelayedRoute", { token }, `request: ${token} has no delayed withdrawal config`);
|
|
316
|
+
if (assets.length > 1) throw new require_onchain_accounts_intents_refusal.IntentPreviewError("multipleDelayedWithdrawals", {
|
|
317
|
+
token,
|
|
318
|
+
venues: assets.length
|
|
319
|
+
}, `request: ${token} has ${assets.length} delayed withdrawal configs`);
|
|
305
320
|
return assets[0];
|
|
306
321
|
}
|
|
307
322
|
const callsOf = (operations) => operations.flatMap((op) => op.calls);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/onchain/accounts/intents/refusal.ts
|
|
3
|
+
/** Builds the refusal a caller sees. */
|
|
4
|
+
function refuse(reason, detail) {
|
|
5
|
+
return {
|
|
6
|
+
ok: false,
|
|
7
|
+
reason,
|
|
8
|
+
detail
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Validation failure that maps onto {@link PreviewErrorReason} rather than
|
|
13
|
+
* crashing the caller: raised by the planners and the guards, turned into
|
|
14
|
+
* `{ ok: false }` by `CreditAccountOperationsService`.
|
|
15
|
+
*/
|
|
16
|
+
var IntentPreviewError = class extends Error {
|
|
17
|
+
reason;
|
|
18
|
+
detail;
|
|
19
|
+
constructor(reason, detail, message) {
|
|
20
|
+
super(message ?? reason);
|
|
21
|
+
this.name = "IntentPreviewError";
|
|
22
|
+
this.reason = reason;
|
|
23
|
+
this.detail = detail;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
//#endregion
|
|
27
|
+
exports.IntentPreviewError = IntentPreviewError;
|
|
28
|
+
exports.refuse = refuse;
|