@gearbox-protocol/sdk 16.0.0-next.41 → 16.0.0-next.43

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.
Files changed (62) hide show
  1. package/dist/cjs/model/errors.js +1 -0
  2. package/dist/cjs/model/index.js +5 -0
  3. package/dist/cjs/model/result.js +27 -0
  4. package/dist/cjs/onchain/accounts/intents/open-strategy.js +1 -1
  5. package/dist/cjs/onchain/accounts/intents/tail.js +1 -1
  6. package/dist/cjs/onchain/accounts/withdrawal-compressor/errors.js +14 -14
  7. package/dist/cjs/onchain/index.js +0 -1
  8. package/dist/cjs/onchain/market/zapper/errors.js +13 -12
  9. package/dist/cjs/onchain/validation/index.js +0 -1
  10. package/dist/cjs/preview/index.js +4 -1
  11. package/dist/cjs/preview/parse/errors.js +25 -22
  12. package/dist/cjs/preview/preview/errors.js +12 -11
  13. package/dist/cjs/preview/preview/previewOperation.js +41 -10
  14. package/dist/cjs/preview/simulate/errors.js +18 -17
  15. package/dist/cjs/sdk/execute/ExecuteApi.js +3 -3
  16. package/dist/cjs/sdk/index.js +5 -0
  17. package/dist/cjs/sdk/prepare/PrepareApi.js +254 -101
  18. package/dist/cjs/sdk/prepare/errors.js +93 -0
  19. package/dist/cjs/sdk/prepare/index.js +5 -0
  20. package/dist/esm/model/errors.js +1 -0
  21. package/dist/esm/model/index.js +3 -1
  22. package/dist/esm/model/result.js +24 -0
  23. package/dist/esm/onchain/accounts/intents/open-strategy.js +1 -1
  24. package/dist/esm/onchain/accounts/intents/tail.js +1 -1
  25. package/dist/esm/onchain/accounts/withdrawal-compressor/errors.js +14 -14
  26. package/dist/esm/onchain/index.js +2 -2
  27. package/dist/esm/onchain/market/zapper/errors.js +13 -12
  28. package/dist/esm/onchain/validation/index.js +2 -2
  29. package/dist/esm/preview/index.js +4 -2
  30. package/dist/esm/preview/parse/errors.js +25 -22
  31. package/dist/esm/preview/preview/errors.js +12 -11
  32. package/dist/esm/preview/preview/previewOperation.js +41 -10
  33. package/dist/esm/preview/simulate/errors.js +18 -17
  34. package/dist/esm/sdk/execute/ExecuteApi.js +3 -3
  35. package/dist/esm/sdk/index.js +2 -1
  36. package/dist/esm/sdk/prepare/PrepareApi.js +255 -102
  37. package/dist/esm/sdk/prepare/errors.js +89 -0
  38. package/dist/esm/sdk/prepare/index.js +2 -1
  39. package/dist/types/model/errors.d.ts +46 -0
  40. package/dist/types/model/index.d.ts +3 -1
  41. package/dist/types/model/result.d.ts +48 -0
  42. package/dist/types/onchain/accounts/intents/open-strategy.d.ts +3 -3
  43. package/dist/types/onchain/accounts/intents/types.d.ts +13 -14
  44. package/dist/types/onchain/accounts/withdrawal-compressor/errors.d.ts +18 -5
  45. package/dist/types/onchain/index.d.ts +2 -2
  46. package/dist/types/onchain/market/zapper/errors.d.ts +20 -6
  47. package/dist/types/onchain/validation/index.d.ts +2 -2
  48. package/dist/types/preview/index.d.ts +5 -3
  49. package/dist/types/preview/parse/errors.d.ts +36 -11
  50. package/dist/types/preview/preview/errors.d.ts +17 -5
  51. package/dist/types/preview/preview/index.d.ts +2 -2
  52. package/dist/types/preview/preview/previewOperation.d.ts +21 -2
  53. package/dist/types/preview/simulate/errors.d.ts +21 -8
  54. package/dist/types/sdk/execute/types.d.ts +9 -14
  55. package/dist/types/sdk/index.d.ts +3 -2
  56. package/dist/types/sdk/prepare/PrepareApi.d.ts +30 -22
  57. package/dist/types/sdk/prepare/errors.d.ts +317 -0
  58. package/dist/types/sdk/prepare/index.d.ts +3 -2
  59. package/dist/types/sdk/prepare/types.d.ts +88 -62
  60. package/dist/types/sdk/preview/PreviewNamespace.d.ts +4 -1
  61. package/dist/types/sdk/preview/types.d.ts +7 -3
  62. package/package.json +11 -2
@@ -1,11 +1,13 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_onchain_utils_hex = require("../../onchain/utils/hex.js");
3
3
  const require_onchain_base_MultichainConstruct = require("../../onchain/base/MultichainConstruct.js");
4
- const require_onchain_validation_refusal = require("../../onchain/validation/refusal.js");
4
+ const require_model_result = require("../../model/result.js");
5
+ require("../../model/index.js");
5
6
  const require_onchain_validation_token = require("../../onchain/validation/token.js");
6
7
  const require_onchain_accounts_intents_utils_credit_account_slice = require("../../onchain/accounts/intents/utils/credit-account-slice.js");
7
8
  const require_onchain_accounts_intents_index = require("../../onchain/accounts/intents/index.js");
8
9
  require("../../onchain/index.js");
10
+ const require_sdk_prepare_errors = require("./errors.js");
9
11
  const require_sdk_prepare_withdrawable_collaterals = require("./withdrawable-collaterals.js");
10
12
  //#region src/sdk/prepare/PrepareApi.ts
11
13
  /**
@@ -16,10 +18,18 @@ const require_sdk_prepare_withdrawable_collaterals = require("./withdrawable-col
16
18
  * protocol knowledge stays in `CreditAccountOperationsService` and
17
19
  * `PoolService`.
18
20
  *
19
- * A prepared operation names one chain, so it reads through
20
- * {@link MultichainConstruct.queryChain}: there is no second source to fall back
21
- * to, hence a chain the SDK does not cover, or one that fails the read, throws
22
- * rather than answering with empty metadata.
21
+ * A prepared operation names one chain and reads it directly: there is no
22
+ * second source to fall back to, so a chain the SDK does not cover, or one
23
+ * that fails the read, is a failure of the whole request rather than a thinner
24
+ * answer.
25
+ *
26
+ * No refusable async method here throws. Every way such a preparation can
27
+ * fail — the market's own refusals, the ones the namespace decides itself, and
28
+ * anything the chain or the engine raises — comes back in the failure half of
29
+ * its `SDKReturn`, under the codes that method's signature names. A caller
30
+ * writes one branch, not a branch and a `try`. The synchronous LP methods and
31
+ * the bare `max*` reads throw on bugs and lifecycle errors instead, see
32
+ * {@link IOpportunitiesPrepare}.
23
33
  **/
24
34
  var PrepareApi = class extends require_onchain_base_MultichainConstruct.MultichainConstruct {
25
35
  #ensureFresh;
@@ -27,29 +37,39 @@ var PrepareApi = class extends require_onchain_base_MultichainConstruct.Multicha
27
37
  super(sdk);
28
38
  this.#ensureFresh = ensureFresh;
29
39
  }
30
- async queryChain(props) {
31
- await this.#ensureFresh?.([this.sdk.chain(props.network).chainId]);
32
- return super.queryChain(props);
40
+ /**
41
+ * The chain an async method reads, revalidated first so the state it is
42
+ * about to weigh is no older than the SDK's freshness bar.
43
+ **/
44
+ async #chain(chainId) {
45
+ await this.#ensureFresh?.([this.sdk.chain(chainId).chainId]);
46
+ return this.sdk.chain(chainId);
33
47
  }
34
48
  /**
35
49
  * {@inheritDoc IOpportunitiesPrepare.finalize}
36
50
  **/
37
51
  async finalize(position, params) {
38
- return this.queryChain({
39
- network: position.chainId,
40
- run: async (sdk) => {
41
- const intent = resumable(params.intent ?? params.claimable.intent);
42
- if (!intent) return require_onchain_validation_refusal.refuse("noRecordedIntent", void 0);
43
- return service(sdk).finishIntent({
44
- intent,
45
- claimable: toClaimableWithdrawal(params.claimable),
46
- creditAccount: await slice(sdk, position.creditAccount),
47
- sdk,
48
- slippage: params.slippage,
49
- quotaReserve: params.quotaReserve
50
- });
51
- }
52
- });
52
+ try {
53
+ const sdk = await this.#chain(position.chainId);
54
+ const at = stateBlock(sdk);
55
+ const intent = resumable(params.intent ?? params.claimable.intent);
56
+ if (!intent) return require_model_result.sdkErr(require_sdk_prepare_errors.toRefusalError({
57
+ reason: "noRecordedIntent",
58
+ detail: void 0
59
+ }));
60
+ const creditAccount = await slice(sdk, position.creditAccount);
61
+ if (!creditAccount) return require_model_result.sdkErr(require_sdk_prepare_errors.creditAccountNotFound(position.creditAccount));
62
+ return planned(await service(sdk).finishIntent({
63
+ intent,
64
+ claimable: toClaimableWithdrawal(params.claimable),
65
+ creditAccount,
66
+ sdk,
67
+ slippage: params.slippage,
68
+ quotaReserve: params.quotaReserve
69
+ }), at);
70
+ } catch (e) {
71
+ return require_model_result.sdkErr(require_sdk_prepare_errors.unexpectedFailure(e));
72
+ }
53
73
  }
54
74
  /**
55
75
  * {@inheritDoc IOpportunitiesPrepare.deposit}
@@ -76,12 +96,12 @@ var PrepareApi = class extends require_onchain_base_MultichainConstruct.Multicha
76
96
  meta: pools.getDepositMetadata(pool.pool, tokenIn, tokenOut)
77
97
  });
78
98
  if (!call) return unroutable(chain, tokenIn, tokenOut);
79
- return {
80
- ok: true,
99
+ return require_model_result.sdkOk({
81
100
  operations: [],
82
101
  state,
83
- calls: call.calls
84
- };
102
+ calls: call.calls,
103
+ ...stateBlock(chain)
104
+ });
85
105
  }
86
106
  /**
87
107
  * {@inheritDoc IOpportunitiesPrepare.withdraw}
@@ -106,12 +126,12 @@ var PrepareApi = class extends require_onchain_base_MultichainConstruct.Multicha
106
126
  meta: pools.getWithdrawalMetadata(pool.pool, tokenIn, tokenOut),
107
127
  mode: "withdraw"
108
128
  });
109
- return {
110
- ok: true,
129
+ return require_model_result.sdkOk({
111
130
  operations: [],
112
131
  state,
113
- calls
114
- };
132
+ calls,
133
+ ...stateBlock(chain)
134
+ });
115
135
  }
116
136
  /**
117
137
  * {@inheritDoc IOpportunitiesPrepare.redeem}
@@ -136,34 +156,35 @@ var PrepareApi = class extends require_onchain_base_MultichainConstruct.Multicha
136
156
  meta: pools.getWithdrawalMetadata(pool.pool, tokenIn, tokenOut),
137
157
  mode: "redeem"
138
158
  });
139
- return {
140
- ok: true,
159
+ return require_model_result.sdkOk({
141
160
  operations: [],
142
161
  state,
143
- calls
144
- };
162
+ calls,
163
+ ...stateBlock(chain)
164
+ });
145
165
  }
146
166
  /**
147
167
  * {@inheritDoc IOpportunitiesPrepare.openNewStrategy}
148
168
  **/
149
169
  async openNewStrategy(strategy, params) {
150
- return this.queryChain({
151
- network: strategy.chainId,
152
- run: (sdk) => {
153
- const targetToken = params.targetToken ?? sdk.marketRegister.findCreditManager(strategy.creditManager).strategyTargetCollateral;
154
- if (!targetToken) throw new Error(`credit manager ${strategy.creditManager} has no strategy target collateral`);
155
- return service(sdk).openStrategyIntent({
156
- sdk,
157
- creditManager: strategy.creditManager,
158
- collateral: params.collateral,
159
- targetToken,
160
- leverage: params.leverage,
161
- leftoverBalances: params.leftoverBalances,
162
- slippage: params.slippage,
163
- quotaReserve: params.quotaReserve
164
- });
165
- }
166
- });
170
+ try {
171
+ const sdk = await this.#chain(strategy.chainId);
172
+ const at = stateBlock(sdk);
173
+ const targetToken = params.targetToken ?? sdk.marketRegister.findCreditManager(strategy.creditManager).strategyTargetCollateral;
174
+ if (!targetToken) return require_model_result.sdkErr(require_sdk_prepare_errors.noStrategyTargetCollateral(strategy.creditManager));
175
+ return opened(await service(sdk).openStrategyIntent({
176
+ sdk,
177
+ creditManager: strategy.creditManager,
178
+ collateral: params.collateral,
179
+ targetToken,
180
+ leverage: params.leverage,
181
+ leftoverBalances: params.leftoverBalances,
182
+ slippage: params.slippage,
183
+ quotaReserve: params.quotaReserve
184
+ }), at);
185
+ } catch (e) {
186
+ return require_model_result.sdkErr(require_sdk_prepare_errors.unexpectedFailure(e));
187
+ }
167
188
  }
168
189
  /**
169
190
  * {@inheritDoc IOpportunitiesPrepare.depositStrategy}
@@ -194,12 +215,11 @@ var PrepareApi = class extends require_onchain_base_MultichainConstruct.Multicha
194
215
  * {@inheritDoc IOpportunitiesPrepare.maxWithdraw}
195
216
  **/
196
217
  async maxWithdraw(position) {
197
- return this.queryChain({
198
- network: position.chainId,
199
- run: async (sdk) => service(sdk).maxWithdraw({
200
- creditAccount: await slice(sdk, position.creditAccount),
201
- sdk
202
- })
218
+ const sdk = await this.#chain(position.chainId);
219
+ const creditAccount = await this.#account(sdk, position);
220
+ return service(sdk).maxWithdraw({
221
+ creditAccount,
222
+ sdk
203
223
  });
204
224
  }
205
225
  /**
@@ -217,12 +237,11 @@ var PrepareApi = class extends require_onchain_base_MultichainConstruct.Multicha
217
237
  * {@inheritDoc IOpportunitiesPrepare.maxRepay}
218
238
  **/
219
239
  async maxRepay(position) {
220
- return this.queryChain({
221
- network: position.chainId,
222
- run: async (sdk) => service(sdk).maxRepay({
223
- creditAccount: await slice(sdk, position.creditAccount),
224
- sdk
225
- })
240
+ const sdk = await this.#chain(position.chainId);
241
+ const creditAccount = await this.#account(sdk, position);
242
+ return service(sdk).maxRepay({
243
+ creditAccount,
244
+ sdk
226
245
  });
227
246
  }
228
247
  /**
@@ -279,57 +298,99 @@ var PrepareApi = class extends require_onchain_base_MultichainConstruct.Multicha
279
298
  * {@inheritDoc IOpportunitiesPrepare.maxWithdrawCollateral}
280
299
  **/
281
300
  async maxWithdrawCollateral(position, token, targetHF) {
282
- return this.queryChain({
283
- network: position.chainId,
284
- run: async (sdk) => service(sdk).maxWithdrawCollateral({
285
- creditAccount: await slice(sdk, position.creditAccount),
286
- sdk,
287
- token,
288
- targetHF
289
- })
301
+ const sdk = await this.#chain(position.chainId);
302
+ const creditAccount = await this.#account(sdk, position);
303
+ return service(sdk).maxWithdrawCollateral({
304
+ creditAccount,
305
+ sdk,
306
+ token,
307
+ targetHF
290
308
  });
291
309
  }
292
310
  /**
293
- * Shared path of the two flows that sell a position asset, and therefore have
294
- * two routes to offer: one account read, one intent, both routes quoted.
311
+ * The account a bare `max*` read weighs. These reads answer a number, not
312
+ * an envelope, so an account the markets do not hold is thrown rather than
313
+ * described, see {@link IOpportunitiesPrepare.maxWithdraw}.
314
+ **/
315
+ async #account(sdk, position) {
316
+ const creditAccount = await slice(sdk, position.creditAccount);
317
+ if (!creditAccount) throw new Error(require_sdk_prepare_errors.creditAccountNotFound(position.creditAccount).message);
318
+ return creditAccount;
319
+ }
320
+ /**
321
+ * Shared path of the two flows that sell a position asset, and therefore
322
+ * have two routes to offer: one account read, one intent, both routes
323
+ * quoted. Every refusal, the crash wrap included, carries `refused` so a
324
+ * form can say which routes were ruled out and why.
325
+ *
326
+ * @typeParam X - The codes the calling flow can raise beyond the shared
327
+ * ones, per the engine trace its signature spells out.
295
328
  **/
296
329
  async #startRoutes(position, options, intent) {
297
- return this.queryChain({
298
- network: position.chainId,
299
- run: async (sdk) => service(sdk).intentRoutes({
330
+ try {
331
+ const sdk = await this.#chain(position.chainId);
332
+ const at = stateBlock(sdk);
333
+ const creditAccount = await slice(sdk, position.creditAccount);
334
+ if (!creditAccount) return neitherRoute(require_sdk_prepare_errors.creditAccountNotFound(position.creditAccount));
335
+ return routed(await service(sdk).intentRoutes({
300
336
  intent,
301
- creditAccount: await slice(sdk, position.creditAccount),
337
+ creditAccount,
302
338
  sdk,
303
339
  slippage: options.slippage,
304
340
  quotaReserve: options.quotaReserve
305
- })
306
- });
341
+ }), at);
342
+ } catch (e) {
343
+ return neitherRoute(require_sdk_prepare_errors.unexpectedFailure(e));
344
+ }
307
345
  }
308
346
  /**
309
347
  * Shared path of the five flows that act on an existing account: read the
310
- * account, then run the intent through the engine.
348
+ * account, then run the intent through the engine. Whatever the chain or
349
+ * the engine throws on the way is described as `unexpectedFailure` instead
350
+ * of escaping, so the flow always answers.
351
+ *
352
+ * @typeParam X - The codes the calling flow can raise beyond the shared
353
+ * ones, per the engine trace its signature spells out.
311
354
  **/
312
355
  async #startIntent(position, options, intent) {
313
- return this.queryChain({
314
- network: position.chainId,
315
- run: async (sdk) => {
316
- const creditAccount = await slice(sdk, position.creditAccount);
317
- return service(sdk).startIntent({
318
- intent,
319
- creditAccount,
320
- sdk,
321
- slippage: options.slippage,
322
- quotaReserve: options.quotaReserve
323
- });
324
- }
325
- });
356
+ try {
357
+ const sdk = await this.#chain(position.chainId);
358
+ const at = stateBlock(sdk);
359
+ const creditAccount = await slice(sdk, position.creditAccount);
360
+ if (!creditAccount) return require_model_result.sdkErr(require_sdk_prepare_errors.creditAccountNotFound(position.creditAccount));
361
+ return planned(await service(sdk).startIntent({
362
+ intent,
363
+ creditAccount,
364
+ sdk,
365
+ slippage: options.slippage,
366
+ quotaReserve: options.quotaReserve
367
+ }), at);
368
+ } catch (e) {
369
+ return require_model_result.sdkErr(require_sdk_prepare_errors.unexpectedFailure(e));
370
+ }
326
371
  }
327
372
  };
328
373
  function service(sdk) {
329
374
  return new require_onchain_accounts_intents_index.CreditAccountOperationsService(sdk);
330
375
  }
331
- function slice(sdk, creditAccount) {
332
- return require_onchain_accounts_intents_utils_credit_account_slice.fetchCreditAccountSlice(sdk, creditAccount);
376
+ /**
377
+ * Reads the block the SDK's loaded state stands at — the same state every
378
+ * preparation below is computed from, so it is the block the result reports.
379
+ **/
380
+ function stateBlock(sdk) {
381
+ return {
382
+ blockNumber: Number(sdk.currentBlock),
383
+ timestamp: Number(sdk.timestamp)
384
+ };
385
+ }
386
+ /**
387
+ * The account the request names, or nothing where the markets this SDK is
388
+ * connected to hold no such account — closed since it was listed, or named on
389
+ * the wrong chain. Read rather than thrown, so the caller gets a code for it.
390
+ **/
391
+ async function slice(sdk, creditAccount) {
392
+ const data = await sdk.accounts.getCreditAccountData(creditAccount);
393
+ return data && require_onchain_accounts_intents_utils_credit_account_slice.toCreditAccountSlice(data);
333
394
  }
334
395
  /**
335
396
  * The operation a claim resumes, or `undefined` when there is none to resume:
@@ -362,6 +423,95 @@ function toClaimableWithdrawal(claimable) {
362
423
  };
363
424
  }
364
425
  /**
426
+ * The engine's refusal as one flow's failure half.
427
+ *
428
+ * The engine answers with the open union of every reason it can raise
429
+ * anywhere; which of them a given flow actually reaches is the engine trace
430
+ * written into the public signatures. This cast is the one place the open
431
+ * union is narrowed onto them — a code added to or removed from a flow has to
432
+ * move its signature, which `types.test-d.ts` pins.
433
+ **/
434
+ function refusal(issue) {
435
+ return require_model_result.sdkErr(require_sdk_prepare_errors.toRefusalError(issue));
436
+ }
437
+ /**
438
+ * A flow with two routes, refused before either could be quoted: the error is
439
+ * the same one any other flow would report, with nothing to say about the
440
+ * routes because neither was reached.
441
+ **/
442
+ function neitherRoute(error) {
443
+ return require_model_result.sdkErr({
444
+ ...error,
445
+ refused: {
446
+ instant: void 0,
447
+ delayed: void 0
448
+ }
449
+ });
450
+ }
451
+ /**
452
+ * The engine's answer, as the envelope the namespace speaks in: what the
453
+ * operation comes to under `data`, stamped with the block it was computed
454
+ * from, or the refusal as an error carrying its own numbers, see
455
+ * {@link refusal}.
456
+ *
457
+ * The engine keeps its `ok` union — it is the shape the planners, the guards
458
+ * and their tests are written against — and the boundary is the one place the
459
+ * two vocabularies meet.
460
+ **/
461
+ function planned(result, at) {
462
+ if (!result.ok) return refusal(result);
463
+ const { operations, state, calls } = result;
464
+ return require_model_result.sdkOk({
465
+ operations,
466
+ state,
467
+ calls,
468
+ ...at
469
+ });
470
+ }
471
+ /**
472
+ * {@inheritDoc planned}
473
+ **/
474
+ function opened(result, at) {
475
+ return result.ok ? require_model_result.sdkOk({
476
+ state: result.state,
477
+ ...at
478
+ }) : refusal(result);
479
+ }
480
+ /**
481
+ * {@inheritDoc planned}
482
+ *
483
+ * Both routes are payload, refusal and all: `refused` says why a missing one is
484
+ * missing, and it stays on the error when neither route answered, since that is
485
+ * the same question asked of a request that has no viable half at all.
486
+ **/
487
+ function routed(result, at) {
488
+ if (!result.ok) {
489
+ const { refused, ...issue } = result;
490
+ return require_model_result.sdkErr({
491
+ ...require_sdk_prepare_errors.toRefusalError(issue),
492
+ refused
493
+ });
494
+ }
495
+ const { instant, delayed, refused } = result;
496
+ return require_model_result.sdkOk({
497
+ instant: instant && {
498
+ operations: instant.operations,
499
+ state: instant.state,
500
+ calls: instant.calls,
501
+ ...at
502
+ },
503
+ delayed: delayed && {
504
+ operations: delayed.operations,
505
+ state: delayed.state,
506
+ calls: delayed.calls,
507
+ delayed: delayed.delayed,
508
+ ...at
509
+ },
510
+ refused,
511
+ ...at
512
+ });
513
+ }
514
+ /**
365
515
  * A pool route the market does not offer, as the refusal a caller reads.
366
516
  *
367
517
  * `to` is absent where {@link lpRoute} found no output to name at all, which
@@ -369,15 +519,18 @@ function toClaimableWithdrawal(claimable) {
369
519
  * ours implements it.
370
520
  **/
371
521
  function unroutable(sdk, from, to) {
372
- return require_onchain_validation_refusal.refuse("unsupportedTokenPair", {
373
- from: require_onchain_validation_token.toToken(sdk, from),
374
- to: to === void 0 ? void 0 : require_onchain_validation_token.toToken(sdk, to)
375
- });
522
+ return require_model_result.sdkErr(require_sdk_prepare_errors.toRefusalError({
523
+ reason: "unsupportedTokenPair",
524
+ detail: {
525
+ from: require_onchain_validation_token.toToken(sdk, from),
526
+ to: to === void 0 ? void 0 : require_onchain_validation_token.toToken(sdk, to)
527
+ }
528
+ }));
376
529
  }
377
530
  /**
378
531
  * Picks the route the operation takes out of `tokenIn`, as a value rather than
379
532
  * an exception: an unroutable or ambiguous pair is a request the caller can
380
- * fix, so it belongs in the `ok: false` half alongside the strategy refusals.
533
+ * fix, so it belongs in the failure half alongside the strategy refusals.
381
534
  *
382
535
  * A pool with no route out of the input reports it by throwing, hence the
383
536
  * catch; a requested output is checked against the list rather than trusted,
@@ -0,0 +1,93 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/sdk/prepare/errors.ts
3
+ /**
4
+ * One sentence per refusal, naming what was ruled out rather than restating the
5
+ * numbers the error already carries.
6
+ *
7
+ * English and loggable, not a string to put on a screen: a form renders the
8
+ * code and the amounts in its own words, see {@link IGearboxError.message}.
9
+ **/
10
+ const MESSAGES = {
11
+ debtOutOfRange: "The debt this request implies is outside the market's band.",
12
+ leverageOutOfRange: "The leverage asked for cannot be expressed as a plan.",
13
+ insufficientSourceBalance: "Neither the account nor the wallet holds enough to fund this request.",
14
+ unsupportedCollateralToken: "This flow does not accept that token.",
15
+ unsupportedTokenPair: "No route exists between these two tokens.",
16
+ noDelayedRoute: "This request cannot be served as a delayed redemption.",
17
+ multipleDelayedWithdrawals: "The source asset has several redemption venues and none was named.",
18
+ withdrawalInProgress: "A redemption of this asset is already in flight on the account.",
19
+ noRecordedIntent: "The claim names no operation to resume.",
20
+ marketPaused: "The market is paused.",
21
+ marketExpired: "The market is past its expiration date.",
22
+ insufficientPoolLiquidity: "The pool cannot lend what this plan draws.",
23
+ quotaLimitReached: "The market takes no more quota for a token this plan holds.",
24
+ forbiddenToken: "This plan would increase the balance of a forbidden token.",
25
+ insufficientCollateral: "The account would end this transaction under-collateralised.",
26
+ poolSunset: "The pool is winding down and takes no more deposits.",
27
+ quotaCountExceeded: "The account would hold more quoted tokens than the facade enables at once.",
28
+ malformedTransaction: "The transaction could not be replayed."
29
+ };
30
+ /**
31
+ * The engine's refusal, as the error the namespace answers with.
32
+ *
33
+ * One place does the lifting, so the two shapes cannot drift: `reason` becomes
34
+ * `code`, the detail is spread onto the error, and the sentence comes from
35
+ * {@link MESSAGES}. A malformed transaction is spelled out rather than spread,
36
+ * because its detail names a `code` and a `message` of its own and they are not
37
+ * the envelope's.
38
+ *
39
+ * Generic over the issue it is handed, so a call site that already knows the
40
+ * reason gets that reason's error back rather than a union to narrow again.
41
+ **/
42
+ function toRefusalError(issue) {
43
+ if (issue.reason === "malformedTransaction") return {
44
+ code: "malformedTransaction",
45
+ message: MESSAGES.malformedTransaction,
46
+ previewCode: issue.detail.code,
47
+ detail: issue.detail.message
48
+ };
49
+ return {
50
+ code: issue.reason,
51
+ message: MESSAGES[issue.reason],
52
+ ...issue.detail
53
+ };
54
+ }
55
+ /**
56
+ * {@inheritDoc NoStrategyTargetCollateralError}
57
+ **/
58
+ function noStrategyTargetCollateral(creditManager) {
59
+ return {
60
+ code: "noStrategyTargetCollateral",
61
+ message: `Credit manager ${creditManager} has no strategy target collateral, and none was named.`,
62
+ creditManager
63
+ };
64
+ }
65
+ /**
66
+ * {@inheritDoc CreditAccountNotFoundError}
67
+ **/
68
+ function creditAccountNotFound(creditAccount) {
69
+ return {
70
+ code: "creditAccountNotFound",
71
+ message: `Credit account not found: ${creditAccount}.`,
72
+ creditAccount
73
+ };
74
+ }
75
+ /**
76
+ * {@inheritDoc UnexpectedFailureError}
77
+ *
78
+ * Takes what was thrown, whatever that is: a `throw` is not obliged to raise an
79
+ * `Error`, and `cause` promises one.
80
+ **/
81
+ function unexpectedFailure(thrown) {
82
+ const cause = thrown instanceof Error ? thrown : new Error(String(thrown));
83
+ return {
84
+ code: "unexpectedFailure",
85
+ message: `The SDK could not prepare this operation: ${cause.message}`,
86
+ cause
87
+ };
88
+ }
89
+ //#endregion
90
+ exports.creditAccountNotFound = creditAccountNotFound;
91
+ exports.noStrategyTargetCollateral = noStrategyTargetCollateral;
92
+ exports.toRefusalError = toRefusalError;
93
+ exports.unexpectedFailure = unexpectedFailure;
@@ -1,8 +1,13 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_onchain_validation_refusal = require("../../onchain/validation/refusal.js");
3
+ const require_sdk_prepare_errors = require("./errors.js");
3
4
  const require_sdk_prepare_PrepareApi = require("./PrepareApi.js");
4
5
  require("./types.js");
5
6
  exports.IntentPreviewError = require_onchain_validation_refusal.IntentPreviewError;
6
7
  exports.PrepareApi = require_sdk_prepare_PrepareApi.PrepareApi;
8
+ exports.creditAccountNotFound = require_sdk_prepare_errors.creditAccountNotFound;
9
+ exports.noStrategyTargetCollateral = require_sdk_prepare_errors.noStrategyTargetCollateral;
7
10
  exports.raise = require_onchain_validation_refusal.raise;
8
11
  exports.refuse = require_onchain_validation_refusal.refuse;
12
+ exports.toRefusalError = require_sdk_prepare_errors.toRefusalError;
13
+ exports.unexpectedFailure = require_sdk_prepare_errors.unexpectedFailure;
@@ -0,0 +1 @@
1
+ export {};
@@ -5,6 +5,7 @@ import { chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chart
5
5
  import "./curators.js";
6
6
  import { curatorNameSchema, curatorSchema } from "./curators.schema.js";
7
7
  import "./delayed-intents.js";
8
+ import "./errors.js";
8
9
  import { FILTER_ALL, isFilterSet } from "./filters.js";
9
10
  import { booleanParamSchema, encodeFlag, filterAllSchema, filterable } from "./filters.schema.js";
10
11
  import { matchesLiquidatableAccountFilter } from "./liquidations.js";
@@ -19,6 +20,7 @@ import { ERROR_ADAPTER_CALL_OUTSIDE_BRACKET, ERROR_INVALID_TRANSACTION_VALUE, ER
19
20
  import "./primitives.js";
20
21
  import "./response.js";
21
22
  import { chainFailedSchema, chainMetadataSchema, chainSucceededSchema, dataSourceSchema, responseMetadataSchema, responseSchema } from "./response.schema.js";
23
+ import { isSDKError, sdkErr, sdkOk } from "./result.js";
22
24
  import "./withdrawals.js";
23
25
  import { positionClaimableWithdrawalSchema, positionPendingWithdrawalSchema, positionWithdrawalsSchema } from "./withdrawals.schema.js";
24
- export { CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, ERROR_ADAPTER_CALL_OUTSIDE_BRACKET, ERROR_INVALID_TRANSACTION_VALUE, ERROR_MALFORMED_BRACKET, ERROR_NON_ADAPTER_CALL_IN_BRACKET, ERROR_UNPREVIEWABLE_ADAPTER_CALL, ERROR_UNPRICEABLE_TOKEN, ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL, FILTER_ALL, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, STRATEGY_POSITION_COLLATERAL_ERROR, amountSchema, apyBreakdownSchema, asEstimated, assetTypeSchema, backendPreferred, booleanParamSchema, borrowRateBreakdownSchema, bpsSchema, chainFailedSchema, chainIdSchema, chainMetadataSchema, chainSucceededSchema, chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, compareTagOf, curatorNameSchema, curatorSchema, dataSourceSchema, delayedReceivedAssetSchema, encodeFlag, filterAllSchema, filterable, instantReceivedAssetSchema, isFilterSet, leverageSchema, liquidatableAccountFilterSchema, liquidatableAccountSchema, liquidationApprovalSchema, liquidationDetailsSchema, liquidationPositionId, liquidationPositionSchema, matchesLiquidatableAccountFilter, matchesOpportunityFilter, matchesPositionFilter, noticeKindSchema, noticeSchema, offchainOnly, onchainOnly, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityId, opportunityKeySchema, opportunityKindSchema, opportunitySchema, opportunityTotalsSchema, pnlBreakdownSchema, pointRewardsSchema, pointsProgramPnLSchema, pointsProgramSchema, pointsRewardsPnLSchema, poolOpportunityChartMetricSchema, poolOpportunityDetailSchema, poolOpportunityId, poolOpportunityKeySchema, poolOpportunitySchema, poolPositionChartMetricSchema, poolPositionId, poolPositionKeySchema, poolPositionSchema, positionClaimableWithdrawalSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionId, positionKeySchema, positionKindSchema, positionPendingWithdrawalSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionWithdrawalsSchema, positionsTotalsSchema, priceFeedDataSchema, priceFeedSummarySchema, quotaAssetSchema, rateCurvePointSchema, rateCurveSchema, receivedAssetSchema, responseMetadataSchema, responseSchema, rewardsPnLSchema, rewardsSchema, strategyOpportunityChartMetricSchema, strategyOpportunityDetailSchema, strategyOpportunityId, strategyOpportunityKeySchema, strategyOpportunitySchema, strategyPositionChartMetricSchema, strategyPositionId, strategyPositionKeySchema, strategyPositionSchema, timestampSchema, tokenAmountSchema, tokenQuotaRateSchema, tokenRewardsPnLSchema, tokenRewardsSchema, tokenSchema, tolerance, txCallSchema, underlyingTokenSchema };
26
+ export { CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, ERROR_ADAPTER_CALL_OUTSIDE_BRACKET, ERROR_INVALID_TRANSACTION_VALUE, ERROR_MALFORMED_BRACKET, ERROR_NON_ADAPTER_CALL_IN_BRACKET, ERROR_UNPREVIEWABLE_ADAPTER_CALL, ERROR_UNPRICEABLE_TOKEN, ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL, FILTER_ALL, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, STRATEGY_POSITION_COLLATERAL_ERROR, amountSchema, apyBreakdownSchema, asEstimated, assetTypeSchema, backendPreferred, booleanParamSchema, borrowRateBreakdownSchema, bpsSchema, chainFailedSchema, chainIdSchema, chainMetadataSchema, chainSucceededSchema, chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, compareTagOf, curatorNameSchema, curatorSchema, dataSourceSchema, delayedReceivedAssetSchema, encodeFlag, filterAllSchema, filterable, instantReceivedAssetSchema, isFilterSet, isSDKError, leverageSchema, liquidatableAccountFilterSchema, liquidatableAccountSchema, liquidationApprovalSchema, liquidationDetailsSchema, liquidationPositionId, liquidationPositionSchema, matchesLiquidatableAccountFilter, matchesOpportunityFilter, matchesPositionFilter, noticeKindSchema, noticeSchema, offchainOnly, onchainOnly, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityId, opportunityKeySchema, opportunityKindSchema, opportunitySchema, opportunityTotalsSchema, pnlBreakdownSchema, pointRewardsSchema, pointsProgramPnLSchema, pointsProgramSchema, pointsRewardsPnLSchema, poolOpportunityChartMetricSchema, poolOpportunityDetailSchema, poolOpportunityId, poolOpportunityKeySchema, poolOpportunitySchema, poolPositionChartMetricSchema, poolPositionId, poolPositionKeySchema, poolPositionSchema, positionClaimableWithdrawalSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionId, positionKeySchema, positionKindSchema, positionPendingWithdrawalSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionWithdrawalsSchema, positionsTotalsSchema, priceFeedDataSchema, priceFeedSummarySchema, quotaAssetSchema, rateCurvePointSchema, rateCurveSchema, receivedAssetSchema, responseMetadataSchema, responseSchema, rewardsPnLSchema, rewardsSchema, sdkErr, sdkOk, strategyOpportunityChartMetricSchema, strategyOpportunityDetailSchema, strategyOpportunityId, strategyOpportunityKeySchema, strategyOpportunitySchema, strategyPositionChartMetricSchema, strategyPositionId, strategyPositionKeySchema, strategyPositionSchema, timestampSchema, tokenAmountSchema, tokenQuotaRateSchema, tokenRewardsPnLSchema, tokenRewardsSchema, tokenSchema, tolerance, txCallSchema, underlyingTokenSchema };
@@ -0,0 +1,24 @@
1
+ //#region src/model/result.ts
2
+ /** The success half, built. */
3
+ function sdkOk(data) {
4
+ return {
5
+ ok: true,
6
+ data
7
+ };
8
+ }
9
+ /** The failure half, built. */
10
+ function sdkErr(error) {
11
+ return {
12
+ ok: false,
13
+ error
14
+ };
15
+ }
16
+ /**
17
+ * Narrows a {@link SDKReturn} to its failure half. Trivial over `ok`, but it
18
+ * names the intent at call sites that would otherwise read `!r.ok`.
19
+ **/
20
+ function isSDKError(answer) {
21
+ return !answer.ok;
22
+ }
23
+ //#endregion
24
+ export { isSDKError, sdkErr, sdkOk };
@@ -10,7 +10,7 @@ import "./utils/index.js";
10
10
  const NO_ACCOUNT = "0x0000000000000000000000000000000000000000";
11
11
  /**
12
12
  * Builds the state opening a leveraged position out of wallet collateral would
13
- * land in.
13
+ * reach.
14
14
  *
15
15
  * Debt follows from the target leverage against the supplied margin
16
16
  * (`debt = margin * (L - 1)`, `totalValue = margin * L`); the collateral and the
@@ -53,7 +53,7 @@ async function projectTail(args) {
53
53
  const { request, delayed, creditAccount, sdk, quotaReserve } = args;
54
54
  const { claim } = delayed;
55
55
  const queued = request.outputs.find((o) => o.isDelayed);
56
- if (!queued || !claim) throw new Error("projectTail: the request queued nothing to claim");
56
+ if (!queued || !claim) throw new IntentPreviewError("noRecordedIntent", void 0, "projectTail: the request queued nothing to claim");
57
57
  const next = sliceAfter(creditAccount, delayed.afterRequest);
58
58
  const steps = planTail({
59
59
  intent: delayed.record,