@gearbox-protocol/sdk 17.1.0-next.2 → 17.1.0-next.3

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 (79) hide show
  1. package/dist/cjs/onchain/MultichainSDK.js +2 -27
  2. package/dist/cjs/onchain/OnchainSDK.js +5 -6
  3. package/dist/cjs/onchain/accounts/intents/borrow.js +47 -20
  4. package/dist/cjs/onchain/accounts/intents/guards.js +6 -4
  5. package/dist/cjs/onchain/accounts/intents/index.js +40 -9
  6. package/dist/cjs/onchain/accounts/intents/open-strategy.js +49 -17
  7. package/dist/cjs/onchain/accounts/intents/realize.js +55 -24
  8. package/dist/cjs/onchain/index.js +0 -5
  9. package/dist/cjs/onchain/market/credit/CreditSuite.js +6 -5
  10. package/dist/cjs/onchain/market/index.js +0 -5
  11. package/dist/cjs/onchain/market/pricefeeds/feeds/RedstonePriceFeed.js +1 -7
  12. package/dist/cjs/onchain/market/pricefeeds/index.js +0 -5
  13. package/dist/cjs/onchain/market/pricefeeds/updates/UpdatablePriceFeedRegistry.js +5 -5
  14. package/dist/cjs/onchain/market/pricefeeds/updates/index.js +0 -5
  15. package/dist/cjs/onchain/options.js +1 -7
  16. package/dist/cjs/permissionless/index.js +1 -5
  17. package/dist/cjs/permissionless/utils/index.js +1 -5
  18. package/dist/cjs/permissionless/utils/price-update/get-price-update-tx.js +5 -0
  19. package/dist/cjs/permissionless/utils/price-update/get-updatable-feeds.js +6 -4
  20. package/dist/cjs/permissionless/utils/price-update/index.js +1 -5
  21. package/dist/cjs/sdk/prepare/PrepareApi.js +83 -32
  22. package/dist/esm/onchain/MultichainSDK.js +2 -27
  23. package/dist/esm/onchain/OnchainSDK.js +5 -6
  24. package/dist/esm/onchain/accounts/intents/borrow.js +47 -20
  25. package/dist/esm/onchain/accounts/intents/guards.js +6 -4
  26. package/dist/esm/onchain/accounts/intents/index.js +40 -9
  27. package/dist/esm/onchain/accounts/intents/open-strategy.js +49 -17
  28. package/dist/esm/onchain/accounts/intents/realize.js +55 -24
  29. package/dist/esm/onchain/index.js +1 -3
  30. package/dist/esm/onchain/market/credit/CreditSuite.js +6 -5
  31. package/dist/esm/onchain/market/index.js +1 -3
  32. package/dist/esm/onchain/market/pricefeeds/feeds/RedstonePriceFeed.js +1 -7
  33. package/dist/esm/onchain/market/pricefeeds/index.js +1 -3
  34. package/dist/esm/onchain/market/pricefeeds/updates/UpdatablePriceFeedRegistry.js +5 -5
  35. package/dist/esm/onchain/market/pricefeeds/updates/index.js +1 -3
  36. package/dist/esm/onchain/options.js +1 -7
  37. package/dist/esm/permissionless/index.js +2 -3
  38. package/dist/esm/permissionless/utils/index.js +2 -3
  39. package/dist/esm/permissionless/utils/price-update/get-price-update-tx.js +5 -0
  40. package/dist/esm/permissionless/utils/price-update/get-updatable-feeds.js +6 -4
  41. package/dist/esm/permissionless/utils/price-update/index.js +2 -3
  42. package/dist/esm/sdk/prepare/PrepareApi.js +83 -32
  43. package/dist/types/onchain/MultichainSDK.d.ts +0 -10
  44. package/dist/types/onchain/OnchainSDK.d.ts +0 -10
  45. package/dist/types/onchain/accounts/index.d.ts +2 -2
  46. package/dist/types/onchain/accounts/intents/borrow.d.ts +5 -0
  47. package/dist/types/onchain/accounts/intents/guards.d.ts +6 -4
  48. package/dist/types/onchain/accounts/intents/index.d.ts +4 -4
  49. package/dist/types/onchain/accounts/intents/open-strategy.d.ts +5 -0
  50. package/dist/types/onchain/accounts/intents/realize.d.ts +5 -0
  51. package/dist/types/onchain/accounts/intents/types.d.ts +49 -6
  52. package/dist/types/onchain/index.d.ts +4 -6
  53. package/dist/types/onchain/market/credit/CreditSuite.d.ts +10 -0
  54. package/dist/types/onchain/market/index.d.ts +3 -5
  55. package/dist/types/onchain/market/pricefeeds/feeds/RedstonePriceFeed.d.ts +1 -4
  56. package/dist/types/onchain/market/pricefeeds/index.d.ts +3 -5
  57. package/dist/types/onchain/market/pricefeeds/updates/UpdatablePriceFeedRegistry.d.ts +4 -4
  58. package/dist/types/onchain/market/pricefeeds/updates/index.d.ts +3 -5
  59. package/dist/types/onchain/market/pricefeeds/updates/types.d.ts +2 -16
  60. package/dist/types/onchain/options.d.ts +0 -7
  61. package/dist/types/permissionless/index.d.ts +2 -3
  62. package/dist/types/permissionless/utils/index.d.ts +2 -3
  63. package/dist/types/permissionless/utils/price-update/get-price-update-tx.d.ts +5 -0
  64. package/dist/types/permissionless/utils/price-update/get-updatable-feeds.d.ts +9 -3
  65. package/dist/types/permissionless/utils/price-update/index.d.ts +2 -3
  66. package/dist/types/sdk/index.d.ts +2 -2
  67. package/dist/types/sdk/prepare/PrepareApi.d.ts +16 -14
  68. package/dist/types/sdk/prepare/index.d.ts +2 -2
  69. package/dist/types/sdk/prepare/types.d.ts +21 -14
  70. package/package.json +1 -5
  71. package/dist/cjs/onchain/market/pricefeeds/updates/RedstoneUpdater.js +0 -193
  72. package/dist/cjs/onchain/market/pricefeeds/updates/fetchRedstonePayloads.js +0 -95
  73. package/dist/cjs/permissionless/utils/price-update/get-price-feeds.js +0 -60
  74. package/dist/esm/onchain/market/pricefeeds/updates/RedstoneUpdater.js +0 -191
  75. package/dist/esm/onchain/market/pricefeeds/updates/fetchRedstonePayloads.js +0 -94
  76. package/dist/esm/permissionless/utils/price-update/get-price-feeds.js +0 -57
  77. package/dist/types/onchain/market/pricefeeds/updates/RedstoneUpdater.d.ts +0 -37
  78. package/dist/types/onchain/market/pricefeeds/updates/fetchRedstonePayloads.d.ts +0 -62
  79. package/dist/types/permissionless/utils/price-update/get-price-feeds.d.ts +0 -22
@@ -1,8 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_onchain_chain_chains = require("./chain/chains.js");
3
3
  const require_onchain_core_errors = require("./core/errors.js");
4
- const require_onchain_market_pricefeeds_updates_PriceUpdatesCache = require("./market/pricefeeds/updates/PriceUpdatesCache.js");
5
- require("./market/pricefeeds/updates/index.js");
6
4
  const require_onchain_accounts_liquidations_MultichainLiquidationsService = require("./accounts/liquidations/MultichainLiquidationsService.js");
7
5
  require("./accounts/index.js");
8
6
  require("./core/index.js");
@@ -19,7 +17,6 @@ const require_onchain_OnchainSDK = require("./OnchainSDK.js");
19
17
  **/
20
18
  var MultichainSDK = class {
21
19
  #chains;
22
- #redstoneCache;
23
20
  #logger;
24
21
  /**
25
22
  * Namespace for liquidatable credit accounts discovery across all
@@ -61,20 +58,9 @@ var MultichainSDK = class {
61
58
  * @param options - Shared and per-chain attach options.
62
59
  */
63
60
  async attach(options) {
64
- if (options?.redstone) this.#redstoneCache = new require_onchain_market_pricefeeds_updates_PriceUpdatesCache.PriceUpdatesCache({
65
- ttl: options.redstone.cacheTTL ?? 225e3,
66
- historical: !!options.redstone.historicTimestamp
67
- });
68
61
  await Promise.all([...this.#chains.entries()].map(([network, sdk]) => {
69
62
  const perChainOpts = options?.perChain?.[network] ?? {};
70
- return sdk.attach({
71
- ...perChainOpts,
72
- redstone: {
73
- ...options?.redstone,
74
- cache: this.#redstoneCache,
75
- ...perChainOpts.redstone
76
- }
77
- });
63
+ return sdk.attach(perChainOpts);
78
64
  }));
79
65
  this.#logger?.info("Attached all chains");
80
66
  }
@@ -89,10 +75,6 @@ var MultichainSDK = class {
89
75
  */
90
76
  hydrate(state, options) {
91
77
  if (state.version !== 2) throw new require_onchain_core_errors.SdkStateVersionMismatchError(2, state.version);
92
- if (options?.redstone) this.#redstoneCache = new require_onchain_market_pricefeeds_updates_PriceUpdatesCache.PriceUpdatesCache({
93
- ttl: options.redstone.cacheTTL ?? 225e3,
94
- historical: !!options.redstone.historicTimestamp
95
- });
96
78
  const stateByNetwork = new Map(state.chains.map((cs) => [cs.network, cs]));
97
79
  for (const [network, sdk] of this.#chains) {
98
80
  const chainState = stateByNetwork.get(network);
@@ -101,14 +83,7 @@ var MultichainSDK = class {
101
83
  throw new require_onchain_core_errors.SdkMissingChainStateError(network);
102
84
  }
103
85
  const perChainOpts = options?.perChain?.[network] ?? {};
104
- sdk.hydrate(chainState, {
105
- ...perChainOpts,
106
- redstone: {
107
- ...options?.redstone,
108
- cache: this.#redstoneCache,
109
- ...perChainOpts.redstone
110
- }
111
- });
86
+ sdk.hydrate(chainState, perChainOpts);
112
87
  }
113
88
  this.#logger?.info("Hydrated all chains");
114
89
  }
@@ -152,7 +152,7 @@ var OnchainSDK = class extends require_onchain_base_ChainContractsRegister.Chain
152
152
  */
153
153
  async attach(options) {
154
154
  if (this.#attached) throw new require_onchain_core_errors.SdkAlreadyAttachedError();
155
- const { addressProvider = require_onchain_constants_address_provider.ADDRESS_PROVIDER_V310, blockNumber, ignoreUpdateablePrices, ignoreMarkets, marketConfigurators: mcs, redstone } = options ?? {};
155
+ const { addressProvider = require_onchain_constants_address_provider.ADDRESS_PROVIDER_V310, blockNumber, ignoreUpdateablePrices, ignoreMarkets, marketConfigurators: mcs } = options ?? {};
156
156
  const marketConfigurators = mcs ?? this.client.chain.defaultMarketConfigurators.keys();
157
157
  const rwaFactories = options?.rwaFactories ?? this.client.chain.rwaFactories;
158
158
  this.logger?.info({
@@ -167,8 +167,7 @@ var OnchainSDK = class extends require_onchain_base_ChainContractsRegister.Chain
167
167
  const block = await this.client.getBlock(blockNumber ? { blockNumber: BigInt(blockNumber) } : { blockTag: "latest" });
168
168
  this.#currentBlock = block.number;
169
169
  this.#timestamp = block.timestamp;
170
- if (blockNumber && !redstone?.historicTimestamp && time - Number(block.timestamp) * 1e3 > 6e4) this.logger?.warn("attaching to fixed block number, but redstone historicTimestamp is not set. price updates might fail");
171
- this.#priceFeeds = new require_onchain_market_pricefeeds_updates_UpdatablePriceFeedRegistry.UpdatablePriceFeedRegistry(this, { redstone });
170
+ this.#priceFeeds = new require_onchain_market_pricefeeds_updates_UpdatablePriceFeedRegistry.UpdatablePriceFeedRegistry(this);
172
171
  this.logger?.debug(`attach block number ${this.currentBlock} timestamp ${this.timestamp}`);
173
172
  this.#addressProvider = await require_onchain_core_createAddressProvider.createAddressProvider(this, addressProvider);
174
173
  this.logger?.debug(`address provider version: ${this.#addressProvider.version}`);
@@ -259,11 +258,11 @@ var OnchainSDK = class extends require_onchain_base_ChainContractsRegister.Chain
259
258
  if (this.#attached) throw new require_onchain_core_errors.SdkAlreadyAttachedError();
260
259
  if (state.version !== 2) throw new require_onchain_core_errors.SdkStateVersionMismatchError(2, state.version);
261
260
  if (state.network !== this.networkType) throw new require_onchain_core_errors.SdkChainMismatchError(this.networkType, state.network);
262
- const { ignoreMarkets, redstone } = options ?? {};
261
+ const { ignoreMarkets } = options ?? {};
263
262
  this.logger?.info({ networkType: this.networkType }, "hydrating sdk state");
264
263
  this.#currentBlock = state.currentBlock;
265
264
  this.#timestamp = state.timestamp;
266
- this.#priceFeeds = new require_onchain_market_pricefeeds_updates_UpdatablePriceFeedRegistry.UpdatablePriceFeedRegistry(this, { redstone });
265
+ this.#priceFeeds = new require_onchain_market_pricefeeds_updates_UpdatablePriceFeedRegistry.UpdatablePriceFeedRegistry(this);
267
266
  this.#addressProvider = require_onchain_core_createAddressProvider.hydrateAddressProvider(this, state.addressProvider);
268
267
  this.logger?.debug(`address provider version: ${this.#addressProvider.version}`);
269
268
  this.#marketRegister = new require_onchain_market_MarketRegister.MarketRegister(this, ignoreMarkets);
@@ -346,7 +345,7 @@ var OnchainSDK = class extends require_onchain_base_ChainContractsRegister.Chain
346
345
  */
347
346
  async syncState(opts) {
348
347
  let { blockNumber, timestamp, ignoreUpdateablePrices } = opts ?? {};
349
- if (this.priceFeeds.historical && !ignoreUpdateablePrices) this.logger?.warn("syncState is not supported with redstone historicTimestamp");
348
+ if (this.priceFeeds.historical && !ignoreUpdateablePrices) this.logger?.warn("syncState is not supported with historical price updates");
350
349
  if (!blockNumber || !timestamp) {
351
350
  const block = await this.client.getBlock({ blockTag: "latest" });
352
351
  blockNumber = block.number;
@@ -30,7 +30,10 @@ async function buildBorrowState(props) {
30
30
  const { sdk, creditManager, collateralAmount, borrowAmount, slippage = 0, quotaReserve, creditAccount: existing } = props;
31
31
  const suite = sdk.marketRegister.findCreditManager(creditManager);
32
32
  const market = sdk.marketRegister.findByCreditManager(creditManager);
33
+ const draft = props.draft ?? {};
34
+ Object.assign(draft, suite.creditOperationMarket(), { slippage });
33
35
  require_onchain_accounts_intents_guards.assertMarketOperable(suite);
36
+ const priced = (token, balance) => market.priceOracle.toTokenAmount(token, balance);
34
37
  const underlying = market.pool.underlying.toLowerCase();
35
38
  const collateralToken = props.collateralToken.toLowerCase();
36
39
  const borrowToken = props.borrowToken.toLowerCase();
@@ -42,8 +45,16 @@ async function buildBorrowState(props) {
42
45
  if (collateralAmount <= 0n) throw new require_onchain_validation_raise.IntentPreviewError(require_model_errors_operation_errors.insufficientBalance(), "borrow: no collateral supplied");
43
46
  if (borrowAmount <= 0n) throw new require_onchain_validation_raise.IntentPreviewError(require_model_errors_operation_errors.insufficientBalance(), "borrow: nothing to borrow");
44
47
  const margin = convert(collateralToken, underlying, collateralAmount);
48
+ Object.assign(draft, {
49
+ collateral: priced(collateralToken, collateralAmount),
50
+ totalValue: market.toUnderlyingAmount(margin)
51
+ });
45
52
  if (margin <= 0n) throw new require_onchain_validation_raise.IntentPreviewError(require_model_errors_operation_errors.insufficientBalance(), "borrow: collateral is worth nothing in underlying");
46
53
  const debt = require_onchain_accounts_intents_utils_common.eq(borrowToken, underlying) ? borrowAmount : unwrapsPayout ? require_onchain_accounts_intents_utils_common.toTargetDecimals(borrowAmount, borrowToken, underlying, sdk) : convert(borrowToken, underlying, borrowAmount);
54
+ Object.assign(draft, {
55
+ totalDebt: market.toUnderlyingAmount(debt),
56
+ netValue: market.toUnderlyingAmount(margin - debt)
57
+ });
47
58
  require_onchain_accounts_intents_math.assertDebtLimits(sdk, debt, suite.creditFacade, underlying);
48
59
  require_onchain_accounts_intents_guards.assertCanBorrow(sdk, suite, debt);
49
60
  const account = existing ?? require_onchain_accounts_intents_utils_credit_account_slice.unopenedAccountSlice({
@@ -73,6 +84,37 @@ async function buildBorrowState(props) {
73
84
  assets,
74
85
  quotaReserve
75
86
  });
87
+ const payout = unwrapsPayout ? require_onchain_accounts_intents_utils_common.toTargetDecimals(debt, underlying, borrowToken, sdk) : leg ? leg.amount : debt;
88
+ /** The two sides of the loan, which the guards below weigh but do not move. */
89
+ const loan = {
90
+ collateral: priced(collateralToken, collateralAmount),
91
+ borrowed: priced(borrowToken, payout),
92
+ minBorrowed: priced(borrowToken, leg ? leg.minAmount : payout),
93
+ slippage,
94
+ quotaIncrease,
95
+ calls: leg ? [...leg.calls] : unwrap ?? [],
96
+ creditAccount: existing?.creditAccount
97
+ };
98
+ Object.assign(draft, loan);
99
+ const snapshot = {
100
+ creditManager,
101
+ assets,
102
+ quotas: quotaIncrease,
103
+ totalDebt: debt,
104
+ totalValue: margin
105
+ };
106
+ const settle = () => ({
107
+ ...sdk.positions.projection(snapshot, { availableLiquidityChange: -debt }),
108
+ currentPrice: sdk.positions.currentPrice(snapshot),
109
+ executionCost: void 0
110
+ });
111
+ let reached;
112
+ try {
113
+ reached = settle();
114
+ Object.assign(draft, reached);
115
+ } catch {
116
+ reached = void 0;
117
+ }
76
118
  require_onchain_accounts_intents_guards.assertGrowthAllowed({
77
119
  sdk,
78
120
  suite,
@@ -81,35 +123,20 @@ async function buildBorrowState(props) {
81
123
  after: assets
82
124
  });
83
125
  require_onchain_accounts_intents_guards.assertQuotaAvailable(sdk, market, quotaIncrease);
84
- const snapshot = {
85
- creditManager,
86
- assets,
87
- quotas: quotaIncrease,
88
- totalDebt: debt,
89
- totalValue: margin
90
- };
91
- const projection = sdk.positions.projection(snapshot, { availableLiquidityChange: -debt });
126
+ const projection = reached ?? settle();
92
127
  require_onchain_accounts_intents_guards.assertCollateralised(projection.safeHealthFactor, true);
93
- const priced = (token, balance) => market.priceOracle.toTokenAmount(token, balance);
94
- const payout = unwrapsPayout ? require_onchain_accounts_intents_utils_common.toTargetDecimals(debt, underlying, borrowToken, sdk) : leg ? leg.amount : debt;
95
- return {
128
+ const state = {
96
129
  ...projection,
97
- currentPrice: sdk.positions.currentPrice(snapshot),
98
- executionCost: void 0,
99
130
  priceImpact: await require_onchain_accounts_intents_utils_price_impact.collectPriceImpact(leg?.probe ? [leg.probe] : [], {
100
131
  totalValue: margin,
101
132
  netValue: margin - debt,
102
133
  toUnderlying: (from, amount) => convert(from, underlying, amount),
103
134
  toUnderlyingAmount: market.toUnderlyingAmount
104
135
  }),
105
- collateral: priced(collateralToken, collateralAmount),
106
- borrowed: priced(borrowToken, payout),
107
- minBorrowed: priced(borrowToken, leg ? leg.minAmount : payout),
108
- slippage,
109
- quotaIncrease,
110
- calls: leg ? [...leg.calls] : unwrap ?? [],
111
- creditAccount: existing?.creditAccount
136
+ ...loan
112
137
  };
138
+ Object.assign(draft, state);
139
+ return state;
113
140
  }
114
141
  /**
115
142
  * Quota a borrow buys for its collateral on an account that holds none yet.
@@ -14,7 +14,8 @@ const require_onchain_accounts_intents_utils_common = require("./utils/common.js
14
14
  const require_onchain_accounts_intents_utils_pick_token = require("./utils/pick-token.js");
15
15
  //#region src/onchain/accounts/intents/guards.ts
16
16
  /**
17
- * What the market itself refuses, checked before anything is quoted.
17
+ * What the market itself refuses, read from its loaded state rather than
18
+ * learned from a revert.
18
19
  *
19
20
  * The planners answer for the arithmetic of an intent and the ledger for the
20
21
  * balances it moves, but neither can see that the facade is paused or that the
@@ -23,9 +24,10 @@ const require_onchain_accounts_intents_utils_pick_token = require("./utils/pick-
23
24
  * loaded market and reported as refusals instead.
24
25
  *
25
26
  * Every guard here refuses something the market decides rather than something
26
- * the arithmetic cannot do, which is why all six of their reasons are
27
- * `blocking`: the walk that hit one still reached an end state, and a caller
28
- * gets that state alongside the refusal.
27
+ * the arithmetic cannot do, so where the account would have landed stays a
28
+ * question the walk can answer. The three that judge that end state — growth,
29
+ * quota limits, collateral — therefore run only once the projection exists,
30
+ * which is what lets them hand it back as `state` when they refuse.
29
31
  */
30
32
  /**
31
33
  * The facade takes no multicall while it is paused or past its expiration, so
@@ -220,7 +220,7 @@ var CreditAccountOperationsService = class extends require_onchain_base_SDKConst
220
220
  delayed
221
221
  };
222
222
  } catch (e) {
223
- return asSDKError(e);
223
+ return asRefused(e, result.state);
224
224
  }
225
225
  }
226
226
  /**
@@ -243,7 +243,13 @@ var CreditAccountOperationsService = class extends require_onchain_base_SDKConst
243
243
  * @returns Whichever routes are viable, or `{ ok: false, error }` when none is
244
244
  */
245
245
  async intentRoutes(props) {
246
- const [instant, delayed] = await Promise.allSettled([this.startIntent(props), this.startDelayedIntent(props)]);
246
+ const [instant, delayed] = await Promise.allSettled([this.startIntent({
247
+ ...props,
248
+ draft: props.draft ?? {}
249
+ }), this.startDelayedIntent({
250
+ ...props,
251
+ draft: {}
252
+ })]);
247
253
  const instantRoute = instant.status === "fulfilled" && instant.value.ok ? instant.value : void 0;
248
254
  const delayedRoute = delayed.status === "fulfilled" && delayed.value.ok ? delayed.value : void 0;
249
255
  const instantError = instant.status === "fulfilled" && !instant.value.ok ? instant.value.error : void 0;
@@ -340,13 +346,17 @@ var CreditAccountOperationsService = class extends require_onchain_base_SDKConst
340
346
  * leverage or the resulting debt is not viable
341
347
  */
342
348
  async openStrategyIntent(props) {
349
+ const draft = props.draft ?? {};
343
350
  try {
344
351
  return {
345
352
  ok: true,
346
- state: await require_onchain_accounts_intents_open_strategy.buildOpenStrategyState(props)
353
+ state: await require_onchain_accounts_intents_open_strategy.buildOpenStrategyState({
354
+ ...props,
355
+ draft
356
+ })
347
357
  };
348
358
  } catch (e) {
349
- return asSDKError(e);
359
+ return asRefused(e, draft);
350
360
  }
351
361
  }
352
362
  /**
@@ -371,24 +381,32 @@ var CreditAccountOperationsService = class extends require_onchain_base_SDKConst
371
381
  * router has no path to
372
382
  */
373
383
  async borrowIntent(props) {
384
+ const draft = props.draft ?? {};
374
385
  try {
375
386
  return {
376
387
  ok: true,
377
- state: await require_onchain_accounts_intents_borrow.buildBorrowState(props)
388
+ state: await require_onchain_accounts_intents_borrow.buildBorrowState({
389
+ ...props,
390
+ draft
391
+ })
378
392
  };
379
393
  } catch (e) {
380
- return asSDKError(e);
394
+ return asRefused(e, draft);
381
395
  }
382
396
  }
383
397
  /** Plan → realise → wrap. Unviable requests become `{ ok: false }`. */
384
398
  async #preview(props, plan) {
399
+ const draft = props.draft ?? {};
385
400
  try {
386
- require_onchain_accounts_intents_guards.assertMarketOperable(props.sdk.marketRegister.findCreditManager(props.creditAccount.creditManager));
401
+ const suite = props.sdk.marketRegister.findCreditManager(props.creditAccount.creditManager);
402
+ Object.assign(draft, suite.creditOperationMarket());
403
+ require_onchain_accounts_intents_guards.assertMarketOperable(suite);
387
404
  const { operations, state, calls, delayed } = await require_onchain_accounts_intents_realize.realize(plan(), {
388
405
  creditAccount: props.creditAccount,
389
406
  sdk: props.sdk,
390
407
  slippage: props.slippage ?? 0,
391
- quotaReserve: props.quotaReserve
408
+ quotaReserve: props.quotaReserve,
409
+ draft
392
410
  });
393
411
  return {
394
412
  ok: true,
@@ -398,7 +416,7 @@ var CreditAccountOperationsService = class extends require_onchain_base_SDKConst
398
416
  delayed
399
417
  };
400
418
  } catch (e) {
401
- return asSDKError(e);
419
+ return asRefused(e, draft);
402
420
  }
403
421
  }
404
422
  };
@@ -420,6 +438,19 @@ function asSDKError(e) {
420
438
  throw e;
421
439
  }
422
440
  /**
441
+ * {@inheritDoc asSDKError}
442
+ *
443
+ * The same verdict with the walk's draft attached, which is what every flow
444
+ * that projects a state answers with — see {@link WithPartialState} for what
445
+ * a caller can expect to find on it.
446
+ */
447
+ function asRefused(e, state) {
448
+ return require_model_result.sdkErr({
449
+ ...asSDKError(e).error,
450
+ state
451
+ });
452
+ }
453
+ /**
423
454
  * How the pathfinder says there is no route: it reverts instead of answering
424
455
  * with an empty path, so viem raises a contract error where the rest of the
425
456
  * engine raises an {@link IntentPreviewError}. Nothing is wrong — the trade
@@ -27,12 +27,19 @@ async function buildOpenStrategyState(props) {
27
27
  require_onchain_accounts_intents_math.assertLeverageAtLeastOne(leverage);
28
28
  const suite = sdk.marketRegister.findCreditManager(creditManager);
29
29
  const market = sdk.marketRegister.findByCreditManager(creditManager);
30
+ const draft = props.draft ?? {};
31
+ Object.assign(draft, suite.creditOperationMarket());
30
32
  require_onchain_accounts_intents_guards.assertMarketOperable(suite);
31
33
  const underlying = market.pool.underlying.toLowerCase();
32
34
  const convert = (from, to, amount) => market.priceOracle.safeConvert(from, to, amount).value;
33
35
  const margin = collateral.reduce((acc, a) => acc + convert(a.token, underlying, a.balance), 0n);
34
- if (margin <= 0n) throw new require_onchain_validation_raise.IntentPreviewError(require_model_errors_operation_errors.insufficientBalance(), "openStrategy: collateral is worth nothing in underlying");
35
36
  const debt = require_onchain_accounts_intents_math.debtForLeverage(margin, leverage);
37
+ Object.assign(draft, {
38
+ totalValue: market.toUnderlyingAmount(margin + debt),
39
+ totalDebt: market.toUnderlyingAmount(debt),
40
+ netValue: market.toUnderlyingAmount(margin)
41
+ });
42
+ if (margin <= 0n) throw new require_onchain_validation_raise.IntentPreviewError(require_model_errors_operation_errors.insufficientBalance(), "openStrategy: collateral is worth nothing in underlying");
36
43
  const account = existing ?? require_onchain_accounts_intents_utils_credit_account_slice.unopenedAccountSlice({
37
44
  creditManager,
38
45
  creditFacade: suite.creditFacade.address,
@@ -67,6 +74,42 @@ async function buildOpenStrategyState(props) {
67
74
  }).quotaIncrease;
68
75
  const averageQuota = quotasFor(averageAssets);
69
76
  const minQuota = quotasFor(minAssets);
77
+ /** What the route came back with, which the guards below weigh but do not move. */
78
+ const routed = {
79
+ averageAssets: averageAssets.map(priced),
80
+ minAssets: minAssets.map(priced),
81
+ averageQuota,
82
+ minQuota,
83
+ calls: [...leg.calls],
84
+ creditAccount: existing?.creditAccount
85
+ };
86
+ Object.assign(draft, routed);
87
+ const snapshot = {
88
+ creditManager,
89
+ assets: averageAssets,
90
+ quotas: averageQuota,
91
+ totalDebt: debt,
92
+ totalValue: margin + debt
93
+ };
94
+ /**
95
+ * The shared builder, as everywhere else — the two branches are what this
96
+ * flow reports instead of `assets` and `quotas`, so those are dropped.
97
+ * Opening borrows the whole debt from the pool.
98
+ */
99
+ const settle = () => {
100
+ const { assets: _assets, quotas: _quotas, ...projection } = sdk.positions.projection(snapshot, { availableLiquidityChange: -debt });
101
+ return {
102
+ ...projection,
103
+ currentPrice: sdk.positions.currentPrice(snapshot)
104
+ };
105
+ };
106
+ let reached;
107
+ try {
108
+ reached = settle();
109
+ Object.assign(draft, reached);
110
+ } catch {
111
+ reached = void 0;
112
+ }
70
113
  require_onchain_accounts_intents_guards.assertGrowthAllowed({
71
114
  sdk,
72
115
  suite,
@@ -75,14 +118,7 @@ async function buildOpenStrategyState(props) {
75
118
  after: averageAssets
76
119
  });
77
120
  require_onchain_accounts_intents_guards.assertQuotaAvailable(sdk, market, averageQuota);
78
- const snapshot = {
79
- creditManager,
80
- assets: averageAssets,
81
- quotas: averageQuota,
82
- totalDebt: debt,
83
- totalValue: margin + debt
84
- };
85
- const { assets: _assets, quotas: _quotas, ...projection } = sdk.positions.projection(snapshot, { availableLiquidityChange: -debt });
121
+ const projection = reached ?? settle();
86
122
  require_onchain_accounts_intents_guards.assertCollateralised(projection.healthFactor, false);
87
123
  const priceImpact = await require_onchain_accounts_intents_utils_price_impact.collectPriceImpact(leg.probe ? [leg.probe] : [], {
88
124
  totalValue: margin + debt,
@@ -90,17 +126,13 @@ async function buildOpenStrategyState(props) {
90
126
  toUnderlying: (from, amount) => convert(from, underlying, amount),
91
127
  toUnderlyingAmount: market.toUnderlyingAmount
92
128
  });
93
- return {
129
+ const state = {
94
130
  ...projection,
95
- currentPrice: sdk.positions.currentPrice(snapshot),
96
131
  priceImpact,
97
- averageAssets: averageAssets.map(priced),
98
- minAssets: minAssets.map(priced),
99
- averageQuota,
100
- minQuota,
101
- calls: [...leg.calls],
102
- creditAccount: existing?.creditAccount
132
+ ...routed
103
133
  };
134
+ Object.assign(draft, state);
135
+ return state;
104
136
  }
105
137
  /** Collateral plus the borrowed underlying, folded into one balance per token. */
106
138
  function mergeExpectedBalances(collateral, underlying, debt) {
@@ -37,6 +37,8 @@ async function realize(steps, props) {
37
37
  const market = sdk.marketRegister.findByCreditManager(creditAccount.creditManager);
38
38
  const price = (from, to, amount) => market.priceOracle.safeConvert(from, to, amount).value;
39
39
  const suite = sdk.marketRegister.findCreditManager(creditAccount.creditManager);
40
+ const draft = props.draft ?? {};
41
+ Object.assign(draft, suite.creditOperationMarket());
40
42
  const start = {
41
43
  initialAssets: creditAccount.tokens,
42
44
  underlying,
@@ -328,13 +330,6 @@ async function realize(steps, props) {
328
330
  const floor = ledger.snapshot();
329
331
  const { assets, debt } = floor;
330
332
  const projected = expected.snapshot();
331
- require_onchain_accounts_intents_guards.assertGrowthAllowed({
332
- sdk,
333
- suite,
334
- market,
335
- before: creditAccount.tokens,
336
- after: projected.assets
337
- });
338
333
  const quotas = cleared ?? require_onchain_accounts_intents_utils_quotas_for_update.getQuotasForUpdate({
339
334
  assetsBefore: creditAccount.tokens,
340
335
  assetsAfter: assets,
@@ -346,14 +341,6 @@ async function realize(steps, props) {
346
341
  maxDebt: suite.creditFacade.maxDebt,
347
342
  convert: price
348
343
  });
349
- if (!cleared && quotas.quotaIncrease.length + quotas.quotaDecrease.length > 0) {
350
- require_onchain_accounts_intents_guards.assertQuotaAvailable(sdk, market, quotas.quotaIncrease);
351
- push(require_onchain_accounts_intents_operations.buildQuotaUpdateOperation({
352
- update: quotas,
353
- creditAccount,
354
- sdk
355
- }));
356
- }
357
344
  const quotasAfter = require_onchain_accounts_intents_utils_quotas_for_update.quotasAfterUpdate(creditAccount.tokens, quotas.desiredQuota);
358
345
  const quoted = Object.values(quotasAfter);
359
346
  const snapshot = {
@@ -363,7 +350,56 @@ async function realize(steps, props) {
363
350
  totalDebt: debt,
364
351
  totalValue: projected.totalValue
365
352
  };
366
- const projection = sdk.positions.projection(snapshot, { availableLiquidityChange: creditAccount.totalDebt - debt });
353
+ const executionCost = traded.priced && traded.spentUnd > 0n ? {
354
+ amount: market.toUnderlyingAmount(traded.returnedUnd - traded.spentUnd),
355
+ rate: require_onchain_constants_math.PERCENTAGE_FACTOR_1KK * (traded.returnedUnd - traded.spentUnd) / traded.spentUnd
356
+ } : void 0;
357
+ /**
358
+ * Everything about where the account lands except how much depth the routes
359
+ * cost, which is a quote of its own and waits until the guards have spoken.
360
+ *
361
+ * The same builder the preview module fills its answers from, so a state
362
+ * this walk plans and the state read back out of the calls it produced are
363
+ * described by one piece of code. Debt taken on leaves the pool, debt repaid
364
+ * returns to it.
365
+ */
366
+ const settle = () => ({
367
+ ...sdk.positions.projection(snapshot, { availableLiquidityChange: creditAccount.totalDebt - debt }),
368
+ executionCost,
369
+ currentPrice: sdk.positions.currentPrice(snapshot)
370
+ });
371
+ /**
372
+ * Read before the guards below rather than after them, so a plan they turn
373
+ * down is still described by the state they turned it down on — which is the
374
+ * question a form asks next, and the reason a guard's verdict is worth more
375
+ * than its code alone.
376
+ *
377
+ * A snapshot the oracle cannot value goes unanswered here and is raised by
378
+ * the success path instead: a guard's verdict is the better answer when
379
+ * there is one.
380
+ */
381
+ let reached;
382
+ try {
383
+ reached = settle();
384
+ Object.assign(draft, reached);
385
+ } catch {
386
+ reached = void 0;
387
+ }
388
+ require_onchain_accounts_intents_guards.assertGrowthAllowed({
389
+ sdk,
390
+ suite,
391
+ market,
392
+ before: creditAccount.tokens,
393
+ after: projected.assets
394
+ });
395
+ if (!cleared && quotas.quotaIncrease.length + quotas.quotaDecrease.length > 0) {
396
+ require_onchain_accounts_intents_guards.assertQuotaAvailable(sdk, market, quotas.quotaIncrease);
397
+ push(require_onchain_accounts_intents_operations.buildQuotaUpdateOperation({
398
+ update: quotas,
399
+ creditAccount,
400
+ sdk
401
+ }));
402
+ }
367
403
  const settled = {
368
404
  ...snapshot,
369
405
  assets,
@@ -382,16 +418,11 @@ async function realize(steps, props) {
382
418
  toUnderlying: (from, amount) => price(from, underlying, amount),
383
419
  toUnderlyingAmount: market.toUnderlyingAmount
384
420
  });
385
- const executionCost = traded.priced && traded.spentUnd > 0n ? {
386
- amount: market.toUnderlyingAmount(traded.returnedUnd - traded.spentUnd),
387
- rate: require_onchain_constants_math.PERCENTAGE_FACTOR_1KK * (traded.returnedUnd - traded.spentUnd) / traded.spentUnd
388
- } : void 0;
389
421
  const state = {
390
- ...projection,
391
- priceImpact,
392
- executionCost,
393
- currentPrice: sdk.positions.currentPrice(snapshot)
422
+ ...reached ?? settle(),
423
+ priceImpact
394
424
  };
425
+ Object.assign(draft, state);
395
426
  return {
396
427
  operations,
397
428
  state,
@@ -171,11 +171,9 @@ const require_onchain_market_pricefeeds_feeds_WstETHPriceFeed = require("./marke
171
171
  const require_onchain_market_pricefeeds_feeds_YearnPriceFeed = require("./market/pricefeeds/feeds/YearnPriceFeed.js");
172
172
  const require_onchain_market_pricefeeds_feeds_ZeroPriceFeed = require("./market/pricefeeds/feeds/ZeroPriceFeed.js");
173
173
  const require_onchain_market_pricefeeds_PriceFeedRegistry = require("./market/pricefeeds/PriceFeedRegistry.js");
174
- const require_onchain_market_pricefeeds_updates_fetchRedstonePayloads = require("./market/pricefeeds/updates/fetchRedstonePayloads.js");
175
174
  const require_onchain_market_pricefeeds_updates_getRawPriceUpdates = require("./market/pricefeeds/updates/getRawPriceUpdates.js");
176
175
  const require_onchain_market_pricefeeds_updates_isUpdatablePriceFeed = require("./market/pricefeeds/updates/isUpdatablePriceFeed.js");
177
176
  const require_onchain_market_pricefeeds_updates_PriceUpdatesCache = require("./market/pricefeeds/updates/PriceUpdatesCache.js");
178
- const require_onchain_market_pricefeeds_updates_RedstoneUpdater = require("./market/pricefeeds/updates/RedstoneUpdater.js");
179
177
  const require_onchain_market_pricefeeds_updates_updatableDependencies = require("./market/pricefeeds/updates/updatableDependencies.js");
180
178
  const require_onchain_market_pricefeeds_updates_UpdatablePriceFeedRegistry = require("./market/pricefeeds/updates/UpdatablePriceFeedRegistry.js");
181
179
  const require_onchain_market_oracle_PriceOracleV310Contract = require("./market/oracle/PriceOracleV310Contract.js");
@@ -489,9 +487,7 @@ exports.RWA_ON_DEMAND_LP_MONOPOLIZED = require_onchain_base_token_types.RWA_ON_D
489
487
  exports.RWA_UNDERLYING_DEFAULT = require_onchain_base_token_types.RWA_UNDERLYING_DEFAULT;
490
488
  exports.RWA_UNDERLYING_ON_DEMAND = require_onchain_base_token_types.RWA_UNDERLYING_ON_DEMAND;
491
489
  exports.RedemptionLoggerV310Contract = require_onchain_accounts_withdrawal_compressor_RedemptionLoggerV310Contract.RedemptionLoggerV310Contract;
492
- exports.RedstoneOptions = require_onchain_market_pricefeeds_updates_RedstoneUpdater.RedstoneOptions;
493
490
  exports.RedstonePriceFeedContract = require_onchain_market_pricefeeds_feeds_RedstonePriceFeed.RedstonePriceFeedContract;
494
- exports.RedstoneUpdater = require_onchain_market_pricefeeds_updates_RedstoneUpdater.RedstoneUpdater;
495
491
  exports.RouterV310Contract = require_onchain_router_RouterV310Contract.RouterV310Contract;
496
492
  exports.SDKConstruct = require_onchain_base_SDKConstruct.SDKConstruct;
497
493
  exports.SECONDS_PER_YEAR = require_onchain_constants_math.SECONDS_PER_YEAR;
@@ -637,7 +633,6 @@ exports.executeDelegatedMulticalls = require_onchain_utils_viem_executeDelegated
637
633
  exports.executeMulticallBatches = require_onchain_utils_viem_executeMulticallBatches.executeMulticallBatches;
638
634
  exports.expectedBalanceDeltas = require_onchain_market_credit_expectedBalanceDeltas.expectedBalanceDeltas;
639
635
  exports.fetchCreditAccountSlice = require_onchain_accounts_intents_utils_credit_account_slice.fetchCreditAccountSlice;
640
- exports.fetchRedstonePayloads = require_onchain_market_pricefeeds_updates_fetchRedstonePayloads.fetchRedstonePayloads;
641
636
  exports.filterDust = require_onchain_utils_filterDust.filterDust;
642
637
  exports.filterDustUSD = require_onchain_utils_filterDust.filterDustUSD;
643
638
  exports.findCallTo = require_onchain_utils_trace.findCallTo;
@@ -397,7 +397,7 @@ var CreditSuite = class extends require_onchain_base_SDKConstruct.SDKConstruct {
397
397
  curator: market.curator,
398
398
  underlyingToken: this.underlyingToken,
399
399
  totalBorrowed: oracle.toAmount(pool.underlying, borrowed),
400
- allowedDepositTokens: this.#allowedDepositTokens(collateral),
400
+ allowedDepositTokens: this.allowedDepositTokens(collateral),
401
401
  paused: this.isPaused,
402
402
  rwa: market.rwa,
403
403
  sunset: market.sunset || require_onchain_chain_chains.isSunsetStrategy(cm.address, this.sdk.networkType),
@@ -471,17 +471,18 @@ var CreditSuite = class extends require_onchain_base_SDKConstruct.SDKConstruct {
471
471
  *
472
472
  * 1. unwrapped underlying (USDC, never dcUSDC)
473
473
  * 2. target collateral
474
- * 3. remaining CM collaterals in manager order, no phantoms
474
+ * 3. remaining CM collaterals in manager order, excluding phantom tokens
475
+ * and tokens without price
475
476
  */
476
- #allowedDepositTokens(targetCollateral) {
477
+ allowedDepositTokens(targetCollateral) {
477
478
  const unwrappedUnderlying = this.market.unwrappedUnderlying;
478
- const skip = (token) => this.market.isUnderlyingLike(token) || (0, viem.isAddressEqual)(token, targetCollateral);
479
+ const { mainPrices, reservePrices } = this.market.priceOracle;
479
480
  return [
480
481
  unwrappedUnderlying,
481
482
  targetCollateral,
482
483
  ...this.creditManager.collateralTokens.filter((token) => {
483
484
  const contractType = this.tokensMeta.mustGet(token).contractType;
484
- return !skip(token) && !contractType?.startsWith("PHANTOM_TOKEN::");
485
+ return !this.market.isUnderlyingLike(token) && !(0, viem.isAddressEqual)(token, targetCollateral) && !contractType?.startsWith("PHANTOM_TOKEN::") && (!!mainPrices.get(token)?.price || !!reservePrices.get(token)?.price);
485
486
  })
486
487
  ].map((token) => this.tokensMeta.mustGetToken(token));
487
488
  }
@@ -120,11 +120,9 @@ const require_onchain_market_pricefeeds_feeds_WstETHPriceFeed = require("./price
120
120
  const require_onchain_market_pricefeeds_feeds_YearnPriceFeed = require("./pricefeeds/feeds/YearnPriceFeed.js");
121
121
  const require_onchain_market_pricefeeds_feeds_ZeroPriceFeed = require("./pricefeeds/feeds/ZeroPriceFeed.js");
122
122
  const require_onchain_market_pricefeeds_PriceFeedRegistry = require("./pricefeeds/PriceFeedRegistry.js");
123
- const require_onchain_market_pricefeeds_updates_fetchRedstonePayloads = require("./pricefeeds/updates/fetchRedstonePayloads.js");
124
123
  const require_onchain_market_pricefeeds_updates_getRawPriceUpdates = require("./pricefeeds/updates/getRawPriceUpdates.js");
125
124
  const require_onchain_market_pricefeeds_updates_isUpdatablePriceFeed = require("./pricefeeds/updates/isUpdatablePriceFeed.js");
126
125
  const require_onchain_market_pricefeeds_updates_PriceUpdatesCache = require("./pricefeeds/updates/PriceUpdatesCache.js");
127
- const require_onchain_market_pricefeeds_updates_RedstoneUpdater = require("./pricefeeds/updates/RedstoneUpdater.js");
128
126
  const require_onchain_market_pricefeeds_updates_updatableDependencies = require("./pricefeeds/updates/updatableDependencies.js");
129
127
  const require_onchain_market_pricefeeds_updates_UpdatablePriceFeedRegistry = require("./pricefeeds/updates/UpdatablePriceFeedRegistry.js");
130
128
  require("./pricefeeds/index.js");
@@ -230,9 +228,7 @@ exports.RWARegistry = require_onchain_market_rwa_RWARegistry.RWARegistry;
230
228
  exports.RWA_COMPRESSOR_ADDRESS = require_onchain_market_rwa_RWARegistry.RWA_COMPRESSOR_ADDRESS;
231
229
  exports.RWA_LIQUIDATOR_MIDAS = require_onchain_market_rwa_midas_constants.RWA_LIQUIDATOR_MIDAS;
232
230
  exports.RWA_LIQUIDATOR_SECURITIZE = require_onchain_market_rwa_securitize_constants.RWA_LIQUIDATOR_SECURITIZE;
233
- exports.RedstoneOptions = require_onchain_market_pricefeeds_updates_RedstoneUpdater.RedstoneOptions;
234
231
  exports.RedstonePriceFeedContract = require_onchain_market_pricefeeds_feeds_RedstonePriceFeed.RedstonePriceFeedContract;
235
- exports.RedstoneUpdater = require_onchain_market_pricefeeds_updates_RedstoneUpdater.RedstoneUpdater;
236
232
  exports.SecuritizeDegenNFT = require_onchain_market_rwa_securitize_SecuritizeDegenNFT.SecuritizeDegenNFT;
237
233
  exports.SecuritizeLiquidatorContract = require_onchain_market_rwa_securitize_SecuritizeLiquidatorContract.SecuritizeLiquidatorContract;
238
234
  exports.SecuritizeOnRampAdapterContract = require_onchain_market_adapters_contracts_SecuritizeOnRampAdapterContract.SecuritizeOnRampAdapterContract;
@@ -277,7 +273,6 @@ exports.curveRemoveLiquidityFromTransfers = require_onchain_market_adapters_tran
277
273
  exports.dominantCollateral = require_onchain_market_credit_collateralUtils.dominantCollateral;
278
274
  exports.erc4626ReferralAdapterAbi = require_onchain_market_adapters_abi_adapters_erc4626ReferralAdapter.erc4626ReferralAdapterAbi;
279
275
  exports.expectedBalanceDeltas = require_onchain_market_credit_expectedBalanceDeltas.expectedBalanceDeltas;
280
- exports.fetchRedstonePayloads = require_onchain_market_pricefeeds_updates_fetchRedstonePayloads.fetchRedstonePayloads;
281
276
  exports.fnSigToName = require_onchain_market_adapters_transferHelpers.fnSigToName;
282
277
  exports.getAdapterActionAbi = require_onchain_market_adapters_abi_utils.getAdapterActionAbi;
283
278
  exports.getAdapterDeployParamsAbi = require_onchain_market_adapters_abi_utils.getAdapterDeployParamsAbi;