@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,10 +1,12 @@
1
1
  import { hexEq } from "../../onchain/utils/hex.js";
2
2
  import { MultichainConstruct } from "../../onchain/base/MultichainConstruct.js";
3
- import { refuse } from "../../onchain/validation/refusal.js";
3
+ import { sdkErr, sdkOk } from "../../model/result.js";
4
+ import "../../model/index.js";
4
5
  import { toToken } from "../../onchain/validation/token.js";
5
- import { fetchCreditAccountSlice } from "../../onchain/accounts/intents/utils/credit-account-slice.js";
6
+ import { toCreditAccountSlice } from "../../onchain/accounts/intents/utils/credit-account-slice.js";
6
7
  import { CreditAccountOperationsService } from "../../onchain/accounts/intents/index.js";
7
8
  import "../../onchain/index.js";
9
+ import { creditAccountNotFound, noStrategyTargetCollateral, toRefusalError, unexpectedFailure } from "./errors.js";
8
10
  import { withdrawableCollaterals } from "./withdrawable-collaterals.js";
9
11
  //#region src/sdk/prepare/PrepareApi.ts
10
12
  /**
@@ -15,10 +17,18 @@ import { withdrawableCollaterals } from "./withdrawable-collaterals.js";
15
17
  * protocol knowledge stays in `CreditAccountOperationsService` and
16
18
  * `PoolService`.
17
19
  *
18
- * A prepared operation names one chain, so it reads through
19
- * {@link MultichainConstruct.queryChain}: there is no second source to fall back
20
- * to, hence a chain the SDK does not cover, or one that fails the read, throws
21
- * rather than answering with empty metadata.
20
+ * A prepared operation names one chain and reads it directly: there is no
21
+ * second source to fall back to, so a chain the SDK does not cover, or one
22
+ * that fails the read, is a failure of the whole request rather than a thinner
23
+ * answer.
24
+ *
25
+ * No refusable async method here throws. Every way such a preparation can
26
+ * fail — the market's own refusals, the ones the namespace decides itself, and
27
+ * anything the chain or the engine raises — comes back in the failure half of
28
+ * its `SDKReturn`, under the codes that method's signature names. A caller
29
+ * writes one branch, not a branch and a `try`. The synchronous LP methods and
30
+ * the bare `max*` reads throw on bugs and lifecycle errors instead, see
31
+ * {@link IOpportunitiesPrepare}.
22
32
  **/
23
33
  var PrepareApi = class extends MultichainConstruct {
24
34
  #ensureFresh;
@@ -26,29 +36,39 @@ var PrepareApi = class extends MultichainConstruct {
26
36
  super(sdk);
27
37
  this.#ensureFresh = ensureFresh;
28
38
  }
29
- async queryChain(props) {
30
- await this.#ensureFresh?.([this.sdk.chain(props.network).chainId]);
31
- return super.queryChain(props);
39
+ /**
40
+ * The chain an async method reads, revalidated first so the state it is
41
+ * about to weigh is no older than the SDK's freshness bar.
42
+ **/
43
+ async #chain(chainId) {
44
+ await this.#ensureFresh?.([this.sdk.chain(chainId).chainId]);
45
+ return this.sdk.chain(chainId);
32
46
  }
33
47
  /**
34
48
  * {@inheritDoc IOpportunitiesPrepare.finalize}
35
49
  **/
36
50
  async finalize(position, params) {
37
- return this.queryChain({
38
- network: position.chainId,
39
- run: async (sdk) => {
40
- const intent = resumable(params.intent ?? params.claimable.intent);
41
- if (!intent) return refuse("noRecordedIntent", void 0);
42
- return service(sdk).finishIntent({
43
- intent,
44
- claimable: toClaimableWithdrawal(params.claimable),
45
- creditAccount: await slice(sdk, position.creditAccount),
46
- sdk,
47
- slippage: params.slippage,
48
- quotaReserve: params.quotaReserve
49
- });
50
- }
51
- });
51
+ try {
52
+ const sdk = await this.#chain(position.chainId);
53
+ const at = stateBlock(sdk);
54
+ const intent = resumable(params.intent ?? params.claimable.intent);
55
+ if (!intent) return sdkErr(toRefusalError({
56
+ reason: "noRecordedIntent",
57
+ detail: void 0
58
+ }));
59
+ const creditAccount = await slice(sdk, position.creditAccount);
60
+ if (!creditAccount) return sdkErr(creditAccountNotFound(position.creditAccount));
61
+ return planned(await service(sdk).finishIntent({
62
+ intent,
63
+ claimable: toClaimableWithdrawal(params.claimable),
64
+ creditAccount,
65
+ sdk,
66
+ slippage: params.slippage,
67
+ quotaReserve: params.quotaReserve
68
+ }), at);
69
+ } catch (e) {
70
+ return sdkErr(unexpectedFailure(e));
71
+ }
52
72
  }
53
73
  /**
54
74
  * {@inheritDoc IOpportunitiesPrepare.deposit}
@@ -75,12 +95,12 @@ var PrepareApi = class extends MultichainConstruct {
75
95
  meta: pools.getDepositMetadata(pool.pool, tokenIn, tokenOut)
76
96
  });
77
97
  if (!call) return unroutable(chain, tokenIn, tokenOut);
78
- return {
79
- ok: true,
98
+ return sdkOk({
80
99
  operations: [],
81
100
  state,
82
- calls: call.calls
83
- };
101
+ calls: call.calls,
102
+ ...stateBlock(chain)
103
+ });
84
104
  }
85
105
  /**
86
106
  * {@inheritDoc IOpportunitiesPrepare.withdraw}
@@ -105,12 +125,12 @@ var PrepareApi = class extends MultichainConstruct {
105
125
  meta: pools.getWithdrawalMetadata(pool.pool, tokenIn, tokenOut),
106
126
  mode: "withdraw"
107
127
  });
108
- return {
109
- ok: true,
128
+ return sdkOk({
110
129
  operations: [],
111
130
  state,
112
- calls
113
- };
131
+ calls,
132
+ ...stateBlock(chain)
133
+ });
114
134
  }
115
135
  /**
116
136
  * {@inheritDoc IOpportunitiesPrepare.redeem}
@@ -135,34 +155,35 @@ var PrepareApi = class extends MultichainConstruct {
135
155
  meta: pools.getWithdrawalMetadata(pool.pool, tokenIn, tokenOut),
136
156
  mode: "redeem"
137
157
  });
138
- return {
139
- ok: true,
158
+ return sdkOk({
140
159
  operations: [],
141
160
  state,
142
- calls
143
- };
161
+ calls,
162
+ ...stateBlock(chain)
163
+ });
144
164
  }
145
165
  /**
146
166
  * {@inheritDoc IOpportunitiesPrepare.openNewStrategy}
147
167
  **/
148
168
  async openNewStrategy(strategy, params) {
149
- return this.queryChain({
150
- network: strategy.chainId,
151
- run: (sdk) => {
152
- const targetToken = params.targetToken ?? sdk.marketRegister.findCreditManager(strategy.creditManager).strategyTargetCollateral;
153
- if (!targetToken) throw new Error(`credit manager ${strategy.creditManager} has no strategy target collateral`);
154
- return service(sdk).openStrategyIntent({
155
- sdk,
156
- creditManager: strategy.creditManager,
157
- collateral: params.collateral,
158
- targetToken,
159
- leverage: params.leverage,
160
- leftoverBalances: params.leftoverBalances,
161
- slippage: params.slippage,
162
- quotaReserve: params.quotaReserve
163
- });
164
- }
165
- });
169
+ try {
170
+ const sdk = await this.#chain(strategy.chainId);
171
+ const at = stateBlock(sdk);
172
+ const targetToken = params.targetToken ?? sdk.marketRegister.findCreditManager(strategy.creditManager).strategyTargetCollateral;
173
+ if (!targetToken) return sdkErr(noStrategyTargetCollateral(strategy.creditManager));
174
+ return opened(await service(sdk).openStrategyIntent({
175
+ sdk,
176
+ creditManager: strategy.creditManager,
177
+ collateral: params.collateral,
178
+ targetToken,
179
+ leverage: params.leverage,
180
+ leftoverBalances: params.leftoverBalances,
181
+ slippage: params.slippage,
182
+ quotaReserve: params.quotaReserve
183
+ }), at);
184
+ } catch (e) {
185
+ return sdkErr(unexpectedFailure(e));
186
+ }
166
187
  }
167
188
  /**
168
189
  * {@inheritDoc IOpportunitiesPrepare.depositStrategy}
@@ -193,12 +214,11 @@ var PrepareApi = class extends MultichainConstruct {
193
214
  * {@inheritDoc IOpportunitiesPrepare.maxWithdraw}
194
215
  **/
195
216
  async maxWithdraw(position) {
196
- return this.queryChain({
197
- network: position.chainId,
198
- run: async (sdk) => service(sdk).maxWithdraw({
199
- creditAccount: await slice(sdk, position.creditAccount),
200
- sdk
201
- })
217
+ const sdk = await this.#chain(position.chainId);
218
+ const creditAccount = await this.#account(sdk, position);
219
+ return service(sdk).maxWithdraw({
220
+ creditAccount,
221
+ sdk
202
222
  });
203
223
  }
204
224
  /**
@@ -216,12 +236,11 @@ var PrepareApi = class extends MultichainConstruct {
216
236
  * {@inheritDoc IOpportunitiesPrepare.maxRepay}
217
237
  **/
218
238
  async maxRepay(position) {
219
- return this.queryChain({
220
- network: position.chainId,
221
- run: async (sdk) => service(sdk).maxRepay({
222
- creditAccount: await slice(sdk, position.creditAccount),
223
- sdk
224
- })
239
+ const sdk = await this.#chain(position.chainId);
240
+ const creditAccount = await this.#account(sdk, position);
241
+ return service(sdk).maxRepay({
242
+ creditAccount,
243
+ sdk
225
244
  });
226
245
  }
227
246
  /**
@@ -278,57 +297,99 @@ var PrepareApi = class extends MultichainConstruct {
278
297
  * {@inheritDoc IOpportunitiesPrepare.maxWithdrawCollateral}
279
298
  **/
280
299
  async maxWithdrawCollateral(position, token, targetHF) {
281
- return this.queryChain({
282
- network: position.chainId,
283
- run: async (sdk) => service(sdk).maxWithdrawCollateral({
284
- creditAccount: await slice(sdk, position.creditAccount),
285
- sdk,
286
- token,
287
- targetHF
288
- })
300
+ const sdk = await this.#chain(position.chainId);
301
+ const creditAccount = await this.#account(sdk, position);
302
+ return service(sdk).maxWithdrawCollateral({
303
+ creditAccount,
304
+ sdk,
305
+ token,
306
+ targetHF
289
307
  });
290
308
  }
291
309
  /**
292
- * Shared path of the two flows that sell a position asset, and therefore have
293
- * two routes to offer: one account read, one intent, both routes quoted.
310
+ * The account a bare `max*` read weighs. These reads answer a number, not
311
+ * an envelope, so an account the markets do not hold is thrown rather than
312
+ * described, see {@link IOpportunitiesPrepare.maxWithdraw}.
313
+ **/
314
+ async #account(sdk, position) {
315
+ const creditAccount = await slice(sdk, position.creditAccount);
316
+ if (!creditAccount) throw new Error(creditAccountNotFound(position.creditAccount).message);
317
+ return creditAccount;
318
+ }
319
+ /**
320
+ * Shared path of the two flows that sell a position asset, and therefore
321
+ * have two routes to offer: one account read, one intent, both routes
322
+ * quoted. Every refusal, the crash wrap included, carries `refused` so a
323
+ * form can say which routes were ruled out and why.
324
+ *
325
+ * @typeParam X - The codes the calling flow can raise beyond the shared
326
+ * ones, per the engine trace its signature spells out.
294
327
  **/
295
328
  async #startRoutes(position, options, intent) {
296
- return this.queryChain({
297
- network: position.chainId,
298
- run: async (sdk) => service(sdk).intentRoutes({
329
+ try {
330
+ const sdk = await this.#chain(position.chainId);
331
+ const at = stateBlock(sdk);
332
+ const creditAccount = await slice(sdk, position.creditAccount);
333
+ if (!creditAccount) return neitherRoute(creditAccountNotFound(position.creditAccount));
334
+ return routed(await service(sdk).intentRoutes({
299
335
  intent,
300
- creditAccount: await slice(sdk, position.creditAccount),
336
+ creditAccount,
301
337
  sdk,
302
338
  slippage: options.slippage,
303
339
  quotaReserve: options.quotaReserve
304
- })
305
- });
340
+ }), at);
341
+ } catch (e) {
342
+ return neitherRoute(unexpectedFailure(e));
343
+ }
306
344
  }
307
345
  /**
308
346
  * Shared path of the five flows that act on an existing account: read the
309
- * account, then run the intent through the engine.
347
+ * account, then run the intent through the engine. Whatever the chain or
348
+ * the engine throws on the way is described as `unexpectedFailure` instead
349
+ * of escaping, so the flow always answers.
350
+ *
351
+ * @typeParam X - The codes the calling flow can raise beyond the shared
352
+ * ones, per the engine trace its signature spells out.
310
353
  **/
311
354
  async #startIntent(position, options, intent) {
312
- return this.queryChain({
313
- network: position.chainId,
314
- run: async (sdk) => {
315
- const creditAccount = await slice(sdk, position.creditAccount);
316
- return service(sdk).startIntent({
317
- intent,
318
- creditAccount,
319
- sdk,
320
- slippage: options.slippage,
321
- quotaReserve: options.quotaReserve
322
- });
323
- }
324
- });
355
+ try {
356
+ const sdk = await this.#chain(position.chainId);
357
+ const at = stateBlock(sdk);
358
+ const creditAccount = await slice(sdk, position.creditAccount);
359
+ if (!creditAccount) return sdkErr(creditAccountNotFound(position.creditAccount));
360
+ return planned(await service(sdk).startIntent({
361
+ intent,
362
+ creditAccount,
363
+ sdk,
364
+ slippage: options.slippage,
365
+ quotaReserve: options.quotaReserve
366
+ }), at);
367
+ } catch (e) {
368
+ return sdkErr(unexpectedFailure(e));
369
+ }
325
370
  }
326
371
  };
327
372
  function service(sdk) {
328
373
  return new CreditAccountOperationsService(sdk);
329
374
  }
330
- function slice(sdk, creditAccount) {
331
- return fetchCreditAccountSlice(sdk, creditAccount);
375
+ /**
376
+ * Reads the block the SDK's loaded state stands at — the same state every
377
+ * preparation below is computed from, so it is the block the result reports.
378
+ **/
379
+ function stateBlock(sdk) {
380
+ return {
381
+ blockNumber: Number(sdk.currentBlock),
382
+ timestamp: Number(sdk.timestamp)
383
+ };
384
+ }
385
+ /**
386
+ * The account the request names, or nothing where the markets this SDK is
387
+ * connected to hold no such account — closed since it was listed, or named on
388
+ * the wrong chain. Read rather than thrown, so the caller gets a code for it.
389
+ **/
390
+ async function slice(sdk, creditAccount) {
391
+ const data = await sdk.accounts.getCreditAccountData(creditAccount);
392
+ return data && toCreditAccountSlice(data);
332
393
  }
333
394
  /**
334
395
  * The operation a claim resumes, or `undefined` when there is none to resume:
@@ -361,6 +422,95 @@ function toClaimableWithdrawal(claimable) {
361
422
  };
362
423
  }
363
424
  /**
425
+ * The engine's refusal as one flow's failure half.
426
+ *
427
+ * The engine answers with the open union of every reason it can raise
428
+ * anywhere; which of them a given flow actually reaches is the engine trace
429
+ * written into the public signatures. This cast is the one place the open
430
+ * union is narrowed onto them — a code added to or removed from a flow has to
431
+ * move its signature, which `types.test-d.ts` pins.
432
+ **/
433
+ function refusal(issue) {
434
+ return sdkErr(toRefusalError(issue));
435
+ }
436
+ /**
437
+ * A flow with two routes, refused before either could be quoted: the error is
438
+ * the same one any other flow would report, with nothing to say about the
439
+ * routes because neither was reached.
440
+ **/
441
+ function neitherRoute(error) {
442
+ return sdkErr({
443
+ ...error,
444
+ refused: {
445
+ instant: void 0,
446
+ delayed: void 0
447
+ }
448
+ });
449
+ }
450
+ /**
451
+ * The engine's answer, as the envelope the namespace speaks in: what the
452
+ * operation comes to under `data`, stamped with the block it was computed
453
+ * from, or the refusal as an error carrying its own numbers, see
454
+ * {@link refusal}.
455
+ *
456
+ * The engine keeps its `ok` union — it is the shape the planners, the guards
457
+ * and their tests are written against — and the boundary is the one place the
458
+ * two vocabularies meet.
459
+ **/
460
+ function planned(result, at) {
461
+ if (!result.ok) return refusal(result);
462
+ const { operations, state, calls } = result;
463
+ return sdkOk({
464
+ operations,
465
+ state,
466
+ calls,
467
+ ...at
468
+ });
469
+ }
470
+ /**
471
+ * {@inheritDoc planned}
472
+ **/
473
+ function opened(result, at) {
474
+ return result.ok ? sdkOk({
475
+ state: result.state,
476
+ ...at
477
+ }) : refusal(result);
478
+ }
479
+ /**
480
+ * {@inheritDoc planned}
481
+ *
482
+ * Both routes are payload, refusal and all: `refused` says why a missing one is
483
+ * missing, and it stays on the error when neither route answered, since that is
484
+ * the same question asked of a request that has no viable half at all.
485
+ **/
486
+ function routed(result, at) {
487
+ if (!result.ok) {
488
+ const { refused, ...issue } = result;
489
+ return sdkErr({
490
+ ...toRefusalError(issue),
491
+ refused
492
+ });
493
+ }
494
+ const { instant, delayed, refused } = result;
495
+ return sdkOk({
496
+ instant: instant && {
497
+ operations: instant.operations,
498
+ state: instant.state,
499
+ calls: instant.calls,
500
+ ...at
501
+ },
502
+ delayed: delayed && {
503
+ operations: delayed.operations,
504
+ state: delayed.state,
505
+ calls: delayed.calls,
506
+ delayed: delayed.delayed,
507
+ ...at
508
+ },
509
+ refused,
510
+ ...at
511
+ });
512
+ }
513
+ /**
364
514
  * A pool route the market does not offer, as the refusal a caller reads.
365
515
  *
366
516
  * `to` is absent where {@link lpRoute} found no output to name at all, which
@@ -368,15 +518,18 @@ function toClaimableWithdrawal(claimable) {
368
518
  * ours implements it.
369
519
  **/
370
520
  function unroutable(sdk, from, to) {
371
- return refuse("unsupportedTokenPair", {
372
- from: toToken(sdk, from),
373
- to: to === void 0 ? void 0 : toToken(sdk, to)
374
- });
521
+ return sdkErr(toRefusalError({
522
+ reason: "unsupportedTokenPair",
523
+ detail: {
524
+ from: toToken(sdk, from),
525
+ to: to === void 0 ? void 0 : toToken(sdk, to)
526
+ }
527
+ }));
375
528
  }
376
529
  /**
377
530
  * Picks the route the operation takes out of `tokenIn`, as a value rather than
378
531
  * an exception: an unroutable or ambiguous pair is a request the caller can
379
- * fix, so it belongs in the `ok: false` half alongside the strategy refusals.
532
+ * fix, so it belongs in the failure half alongside the strategy refusals.
380
533
  *
381
534
  * A pool with no route out of the input reports it by throwing, hence the
382
535
  * catch; a requested output is checked against the list rather than trusted,
@@ -0,0 +1,89 @@
1
+ //#region src/sdk/prepare/errors.ts
2
+ /**
3
+ * One sentence per refusal, naming what was ruled out rather than restating the
4
+ * numbers the error already carries.
5
+ *
6
+ * English and loggable, not a string to put on a screen: a form renders the
7
+ * code and the amounts in its own words, see {@link IGearboxError.message}.
8
+ **/
9
+ const MESSAGES = {
10
+ debtOutOfRange: "The debt this request implies is outside the market's band.",
11
+ leverageOutOfRange: "The leverage asked for cannot be expressed as a plan.",
12
+ insufficientSourceBalance: "Neither the account nor the wallet holds enough to fund this request.",
13
+ unsupportedCollateralToken: "This flow does not accept that token.",
14
+ unsupportedTokenPair: "No route exists between these two tokens.",
15
+ noDelayedRoute: "This request cannot be served as a delayed redemption.",
16
+ multipleDelayedWithdrawals: "The source asset has several redemption venues and none was named.",
17
+ withdrawalInProgress: "A redemption of this asset is already in flight on the account.",
18
+ noRecordedIntent: "The claim names no operation to resume.",
19
+ marketPaused: "The market is paused.",
20
+ marketExpired: "The market is past its expiration date.",
21
+ insufficientPoolLiquidity: "The pool cannot lend what this plan draws.",
22
+ quotaLimitReached: "The market takes no more quota for a token this plan holds.",
23
+ forbiddenToken: "This plan would increase the balance of a forbidden token.",
24
+ insufficientCollateral: "The account would end this transaction under-collateralised.",
25
+ poolSunset: "The pool is winding down and takes no more deposits.",
26
+ quotaCountExceeded: "The account would hold more quoted tokens than the facade enables at once.",
27
+ malformedTransaction: "The transaction could not be replayed."
28
+ };
29
+ /**
30
+ * The engine's refusal, as the error the namespace answers with.
31
+ *
32
+ * One place does the lifting, so the two shapes cannot drift: `reason` becomes
33
+ * `code`, the detail is spread onto the error, and the sentence comes from
34
+ * {@link MESSAGES}. A malformed transaction is spelled out rather than spread,
35
+ * because its detail names a `code` and a `message` of its own and they are not
36
+ * the envelope's.
37
+ *
38
+ * Generic over the issue it is handed, so a call site that already knows the
39
+ * reason gets that reason's error back rather than a union to narrow again.
40
+ **/
41
+ function toRefusalError(issue) {
42
+ if (issue.reason === "malformedTransaction") return {
43
+ code: "malformedTransaction",
44
+ message: MESSAGES.malformedTransaction,
45
+ previewCode: issue.detail.code,
46
+ detail: issue.detail.message
47
+ };
48
+ return {
49
+ code: issue.reason,
50
+ message: MESSAGES[issue.reason],
51
+ ...issue.detail
52
+ };
53
+ }
54
+ /**
55
+ * {@inheritDoc NoStrategyTargetCollateralError}
56
+ **/
57
+ function noStrategyTargetCollateral(creditManager) {
58
+ return {
59
+ code: "noStrategyTargetCollateral",
60
+ message: `Credit manager ${creditManager} has no strategy target collateral, and none was named.`,
61
+ creditManager
62
+ };
63
+ }
64
+ /**
65
+ * {@inheritDoc CreditAccountNotFoundError}
66
+ **/
67
+ function creditAccountNotFound(creditAccount) {
68
+ return {
69
+ code: "creditAccountNotFound",
70
+ message: `Credit account not found: ${creditAccount}.`,
71
+ creditAccount
72
+ };
73
+ }
74
+ /**
75
+ * {@inheritDoc UnexpectedFailureError}
76
+ *
77
+ * Takes what was thrown, whatever that is: a `throw` is not obliged to raise an
78
+ * `Error`, and `cause` promises one.
79
+ **/
80
+ function unexpectedFailure(thrown) {
81
+ const cause = thrown instanceof Error ? thrown : new Error(String(thrown));
82
+ return {
83
+ code: "unexpectedFailure",
84
+ message: `The SDK could not prepare this operation: ${cause.message}`,
85
+ cause
86
+ };
87
+ }
88
+ //#endregion
89
+ export { creditAccountNotFound, noStrategyTargetCollateral, toRefusalError, unexpectedFailure };
@@ -1,4 +1,5 @@
1
1
  import { IntentPreviewError, raise, refuse } from "../../onchain/validation/refusal.js";
2
+ import { creditAccountNotFound, noStrategyTargetCollateral, toRefusalError, unexpectedFailure } from "./errors.js";
2
3
  import { PrepareApi } from "./PrepareApi.js";
3
4
  import "./types.js";
4
- export { IntentPreviewError, PrepareApi, raise, refuse };
5
+ export { IntentPreviewError, PrepareApi, creditAccountNotFound, noStrategyTargetCollateral, raise, refuse, toRefusalError, unexpectedFailure };
@@ -0,0 +1,46 @@
1
+ //#region src/model/errors.d.ts
2
+ /**
3
+ * The failure vocabulary the SDK answers in.
4
+ *
5
+ * A request that the protocol, the market or the request's own numbers rule out
6
+ * is not an exception: it is an answer, and a screen shows it the way it shows
7
+ * any other. So a method that can be refused returns an {@link SDKReturn}
8
+ * envelope rather than throwing, and what it puts in the failure half is one of
9
+ * these — never a bare string, never a boolean the caller has to interpret.
10
+ *
11
+ * A thrown exception still means what it always did: the SDK could not do its
12
+ * job (a read failed, a contract reverted unexpectedly, an argument is wrong).
13
+ * Those are bugs and outages, not verdicts on the request.
14
+ **/
15
+ /**
16
+ * What every error the SDK reports has.
17
+ *
18
+ * `code` is the discriminant: switch on it and the error narrows to the shape
19
+ * carrying that failure's own numbers, so a caller reads `available` and
20
+ * `required` off the error rather than re-deriving them from the request.
21
+ *
22
+ * The codes themselves are per namespace — there is no SDK-wide enumeration of
23
+ * them, because the set a method can answer with is part of that method's
24
+ * contract, see the `E` of {@link SDKReturn}.
25
+ **/
26
+ interface IGearboxError {
27
+ /**
28
+ * Machine-readable identity of the failure, and the discriminant of the
29
+ * union a method returns.
30
+ **/
31
+ code: string;
32
+ /**
33
+ * One sentence naming what was refused, in English, safe to log. Not a
34
+ * message to show a user as-is: a screen renders the code and the numbers
35
+ * beside it in its own words and its own language.
36
+ **/
37
+ message: string;
38
+ /**
39
+ * The failure this one was raised for, where one error stands in front of
40
+ * another. Absent for a refusal that is its own reason, which is most of
41
+ * them.
42
+ **/
43
+ cause?: IGearboxError | Error;
44
+ }
45
+ //#endregion
46
+ export { IGearboxError };
@@ -5,6 +5,7 @@ import { CompareTag, CompareTolerance, ToleranceCompareTag, backendPreferred, co
5
5
  import { Curator, CuratorName } from "./curators.js";
6
6
  import { curatorNameSchema, curatorSchema } from "./curators.schema.js";
7
7
  import { DelayedAddCollateralIntent, DelayedCloseAccountIntent, DelayedDecreaseLeverageIntent, DelayedDepositAndIncreaseLeverageIntent, DelayedDepositIntent, DelayedIncreaseLeverageIntent, DelayedIntent, DelayedWithdrawCollateralIntent } from "./delayed-intents.js";
8
+ import { IGearboxError } from "./errors.js";
8
9
  import { ChainScopedFilter, FILTER_ALL, FilterAll, Filterable, isFilterSet } from "./filters.js";
9
10
  import { booleanParamSchema, encodeFlag, filterAllSchema, filterable } from "./filters.schema.js";
10
11
  import { ApyBreakdown, Opportunity, OpportunityBase, OpportunityDetail, OpportunityFilter, OpportunityId, OpportunityKey, OpportunityKind, OpportunityTotals, PointRewards, PointsProgram, PoolOpportunity, PoolOpportunityDetail, PoolOpportunityKey, PoolOpportunityRef, PriceFeedData, PriceFeedSummary, QuotaAsset, RateCurve, RateCurvePoint, Rewards, StrategyOpportunity, StrategyOpportunityDetail, StrategyOpportunityKey, StrategyOpportunityRef, TokenRewards, matchesOpportunityFilter, opportunityId, poolOpportunityId, strategyOpportunityId } from "./opportunities.js";
@@ -19,6 +20,7 @@ import { borrowRateBreakdownSchema, pnlBreakdownSchema, pointsProgramPnLSchema,
19
20
  import { amountSchema, assetTypeSchema, bpsSchema, chainIdSchema, leverageSchema, timestampSchema, tokenAmountSchema, tokenSchema, txCallSchema, underlyingTokenSchema } from "./primitives.schema.js";
20
21
  import { ChainFailed, ChainMetadata, ChainScoped, ChainSucceeded, DataResponse, DataSource, ResponseMetadata } from "./response.js";
21
22
  import { chainFailedSchema, chainMetadataSchema, chainSucceededSchema, dataSourceSchema, responseMetadataSchema, responseSchema } from "./response.schema.js";
23
+ import { SDKError, SDKResult, SDKReturn, isSDKError, sdkErr, sdkOk } from "./result.js";
22
24
  import { PositionClaimableWithdrawal, PositionPendingWithdrawal, PositionWithdrawals } from "./withdrawals.js";
23
25
  import { positionClaimableWithdrawalSchema, positionPendingWithdrawalSchema, positionWithdrawalsSchema } from "./withdrawals.schema.js";
24
- export { AccountHoldings, AccountMetrics, AccountProjection, AccountStateChange, AdjustStrategyPositionPreview, Amount, ApyBreakdown, Asset, AssetType, BorrowRateBreakdown, Bps, CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, ChainFailed, ChainId, ChainMetadata, ChainScoped, ChainScopedFilter, ChainSucceeded, ChartBundle, ChartDenomination, ChartMetric, ChartQuery, ChartRange, ChartSeries, ChartSeriesOk, ChartSeriesUnavailable, ChartUnavailableCode, ChartUnit, ChartValue, ChartWindow, CompareTag, CompareTolerance, CreditOperationMarket, Curator, CuratorName, DataResponse, DataSource, DelayedAddCollateralIntent, DelayedCloseAccountIntent, DelayedDecreaseLeverageIntent, DelayedDepositAndIncreaseLeverageIntent, DelayedDepositIntent, DelayedIncreaseLeverageIntent, DelayedIntent, DelayedReceivedAsset, DelayedStrategyPositionOperationPreview, DelayedWithdrawCollateralIntent, 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, Estimated, EstimatedProjection, ExitStrategyPositionPreview, FILTER_ALL, FilterAll, Filterable, GridSampling, InstantReceivedAsset, InstantStrategyPositionOperationPreview, Leverage, LiquidatableAccount, LiquidatableAccountFilter, LiquidationApproval, LiquidationDetails, LiquidationPosition, Notice, NoticeKind, NoticeSubject, OpenStrategyPositionPreview, OperationPreview, OperationPreviewError, Opportunity, OpportunityBase, OpportunityChartMetric, OpportunityDetail, OpportunityFilter, OpportunityId, OpportunityKey, OpportunityKind, OpportunityTotals, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, PnlBreakdown, PointRewards, PointsProgram, PointsProgramPnL, PointsRewardsPnL, PoolOperationType, PoolOpportunity, PoolOpportunityChartMetric, PoolOpportunityDetail, PoolOpportunityKey, PoolOpportunityRef, PoolPosition, PoolPositionChartMetric, PoolPositionKey, PoolPositionOperationPreview, PoolPositionRef, Position, PositionChartMetric, PositionClaimableWithdrawal, PositionCollateral, PositionFilter, PositionId, PositionKey, PositionKind, PositionPendingWithdrawal, PositionTransaction, PositionTransactionKind, PositionWithdrawals, PositionsTotals, PreviewOperationInput, PreviewOperationOptions, PriceFeedData, PriceFeedSummary, QuotaAsset, RateCurve, RateCurvePoint, ReceivedAsset, RepayStrategyPositionPreview, ResponseMetadata, Rewards, RewardsPnL, RoutedField, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, STRATEGY_POSITION_COLLATERAL_ERROR, StrategyOpportunity, StrategyOpportunityChartMetric, StrategyOpportunityDetail, StrategyOpportunityKey, StrategyOpportunityRef, StrategyPosition, StrategyPositionChartMetric, StrategyPositionKey, StrategyPositionRef, Timestamp, Token, TokenAmount, TokenQuotaRate, TokenRewards, TokenRewardsPnL, ToleranceCompareTag, TxCall, UnderlyingToken, 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 { AccountHoldings, AccountMetrics, AccountProjection, AccountStateChange, AdjustStrategyPositionPreview, Amount, ApyBreakdown, Asset, AssetType, BorrowRateBreakdown, Bps, CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, ChainFailed, ChainId, ChainMetadata, ChainScoped, ChainScopedFilter, ChainSucceeded, ChartBundle, ChartDenomination, ChartMetric, ChartQuery, ChartRange, ChartSeries, ChartSeriesOk, ChartSeriesUnavailable, ChartUnavailableCode, ChartUnit, ChartValue, ChartWindow, CompareTag, CompareTolerance, CreditOperationMarket, Curator, CuratorName, DataResponse, DataSource, DelayedAddCollateralIntent, DelayedCloseAccountIntent, DelayedDecreaseLeverageIntent, DelayedDepositAndIncreaseLeverageIntent, DelayedDepositIntent, DelayedIncreaseLeverageIntent, DelayedIntent, DelayedReceivedAsset, DelayedStrategyPositionOperationPreview, DelayedWithdrawCollateralIntent, 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, Estimated, EstimatedProjection, ExitStrategyPositionPreview, FILTER_ALL, FilterAll, Filterable, GridSampling, IGearboxError, InstantReceivedAsset, InstantStrategyPositionOperationPreview, Leverage, LiquidatableAccount, LiquidatableAccountFilter, LiquidationApproval, LiquidationDetails, LiquidationPosition, Notice, NoticeKind, NoticeSubject, OpenStrategyPositionPreview, OperationPreview, OperationPreviewError, Opportunity, OpportunityBase, OpportunityChartMetric, OpportunityDetail, OpportunityFilter, OpportunityId, OpportunityKey, OpportunityKind, OpportunityTotals, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, PnlBreakdown, PointRewards, PointsProgram, PointsProgramPnL, PointsRewardsPnL, PoolOperationType, PoolOpportunity, PoolOpportunityChartMetric, PoolOpportunityDetail, PoolOpportunityKey, PoolOpportunityRef, PoolPosition, PoolPositionChartMetric, PoolPositionKey, PoolPositionOperationPreview, PoolPositionRef, Position, PositionChartMetric, PositionClaimableWithdrawal, PositionCollateral, PositionFilter, PositionId, PositionKey, PositionKind, PositionPendingWithdrawal, PositionTransaction, PositionTransactionKind, PositionWithdrawals, PositionsTotals, PreviewOperationInput, PreviewOperationOptions, PriceFeedData, PriceFeedSummary, QuotaAsset, RateCurve, RateCurvePoint, ReceivedAsset, RepayStrategyPositionPreview, ResponseMetadata, Rewards, RewardsPnL, RoutedField, SDKError, SDKResult, SDKReturn, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, STRATEGY_POSITION_COLLATERAL_ERROR, StrategyOpportunity, StrategyOpportunityChartMetric, StrategyOpportunityDetail, StrategyOpportunityKey, StrategyOpportunityRef, StrategyPosition, StrategyPositionChartMetric, StrategyPositionKey, StrategyPositionRef, Timestamp, Token, TokenAmount, TokenQuotaRate, TokenRewards, TokenRewardsPnL, ToleranceCompareTag, TxCall, UnderlyingToken, 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 };