@gearbox-protocol/sdk 16.4.0-next.2 → 16.4.0-next.4

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 (48) hide show
  1. package/dist/cjs/model/errors/index.js +1 -0
  2. package/dist/cjs/model/errors/operation-errors.js +9 -0
  3. package/dist/cjs/model/index.js +1 -0
  4. package/dist/cjs/onchain/accounts/intents/index.js +4 -1
  5. package/dist/cjs/onchain/accounts/intents/realize.js +44 -0
  6. package/dist/cjs/onchain/accounts/intents/utils/price-impact.js +3 -3
  7. package/dist/cjs/onchain/index.js +4 -0
  8. package/dist/cjs/onchain/market/adapters/contracts/MidasGatewayAdapterContract.js +11 -3
  9. package/dist/cjs/onchain/preview/index.js +2 -0
  10. package/dist/cjs/onchain/preview/preview/index.js +2 -0
  11. package/dist/cjs/onchain/preview/preview/midasGreenlistsAccount.js +17 -0
  12. package/dist/cjs/onchain/preview/preview/previewOpenStrategyPosition.js +3 -1
  13. package/dist/cjs/onchain/validation/bundles/checkMidasAccountGreenlist.js +46 -0
  14. package/dist/cjs/onchain/validation/bundles/checkRWAOpening.js +15 -5
  15. package/dist/cjs/onchain/validation/bundles/index.js +2 -0
  16. package/dist/cjs/onchain/validation/index.js +2 -0
  17. package/dist/esm/model/errors/index.js +2 -2
  18. package/dist/esm/model/errors/operation-errors.js +9 -1
  19. package/dist/esm/model/index.js +2 -2
  20. package/dist/esm/onchain/accounts/intents/index.js +4 -1
  21. package/dist/esm/onchain/accounts/intents/realize.js +44 -0
  22. package/dist/esm/onchain/accounts/intents/utils/price-impact.js +3 -3
  23. package/dist/esm/onchain/index.js +3 -1
  24. package/dist/esm/onchain/market/adapters/contracts/MidasGatewayAdapterContract.js +11 -3
  25. package/dist/esm/onchain/preview/index.js +2 -1
  26. package/dist/esm/onchain/preview/preview/index.js +2 -1
  27. package/dist/esm/onchain/preview/preview/midasGreenlistsAccount.js +16 -0
  28. package/dist/esm/onchain/preview/preview/previewOpenStrategyPosition.js +3 -1
  29. package/dist/esm/onchain/validation/bundles/checkMidasAccountGreenlist.js +45 -0
  30. package/dist/esm/onchain/validation/bundles/checkRWAOpening.js +15 -5
  31. package/dist/esm/onchain/validation/bundles/index.js +2 -1
  32. package/dist/esm/onchain/validation/index.js +2 -1
  33. package/dist/types/model/errors/index.d.ts +2 -2
  34. package/dist/types/model/errors/operation-errors.d.ts +14 -1
  35. package/dist/types/model/index.d.ts +2 -2
  36. package/dist/types/model/previews.d.ts +6 -0
  37. package/dist/types/onchain/accounts/intents/types.d.ts +10 -1
  38. package/dist/types/onchain/index.d.ts +4 -2
  39. package/dist/types/onchain/market/adapters/contracts/MidasGatewayAdapterContract.d.ts +8 -2
  40. package/dist/types/onchain/preview/index.d.ts +2 -1
  41. package/dist/types/onchain/preview/preview/index.d.ts +2 -1
  42. package/dist/types/onchain/preview/preview/midasGreenlistsAccount.d.ts +13 -0
  43. package/dist/types/onchain/validation/bundles/checkCreditOperation.d.ts +2 -2
  44. package/dist/types/onchain/validation/bundles/checkMidasAccountGreenlist.d.ts +23 -0
  45. package/dist/types/onchain/validation/bundles/checkRWAOpening.d.ts +6 -4
  46. package/dist/types/onchain/validation/bundles/index.d.ts +3 -2
  47. package/dist/types/onchain/validation/index.d.ts +3 -2
  48. package/package.json +1 -1
@@ -5,6 +5,7 @@ const require_model_errors_operation_errors = require("./operation-errors.js");
5
5
  const require_model_errors_oracle_errors = require("./oracle-errors.js");
6
6
  const require_model_errors_prepare_errors = require("./prepare-errors.js");
7
7
  const require_model_errors_preview_errors = require("./preview-errors.js");
8
+ exports.accountNotMidasGreenlisted = require_model_errors_operation_errors.accountNotMidasGreenlisted;
8
9
  exports.creditAccountFrozen = require_model_errors_liquidation_errors.creditAccountFrozen;
9
10
  exports.creditAccountNotEmpty = require_model_errors_prepare_errors.creditAccountNotEmpty;
10
11
  exports.creditAccountNotFound = require_model_errors_prepare_errors.creditAccountNotFound;
@@ -126,7 +126,16 @@ function rwaOpenRequirementsNotMet(args) {
126
126
  ...args
127
127
  };
128
128
  }
129
+ /** {@inheritDoc AccountNotMidasGreenlistedError} */
130
+ function accountNotMidasGreenlisted(args) {
131
+ return {
132
+ code: "accountNotMidasGreenlisted",
133
+ message: `The credit account is not Midas-greenlisted for ${args.token.symbol}.`,
134
+ ...args
135
+ };
136
+ }
129
137
  //#endregion
138
+ exports.accountNotMidasGreenlisted = accountNotMidasGreenlisted;
130
139
  exports.creditManagerPaused = creditManagerPaused;
131
140
  exports.debtOutOfRange = debtOutOfRange;
132
141
  exports.forbiddenToken = forbiddenToken;
@@ -50,6 +50,7 @@ exports.SECURITIZE_REGISTER_VAULT_TYPES = require_model_rwa.SECURITIZE_REGISTER_
50
50
  exports.STRATEGY_OPPORTUNITY_CHART_METRICS = require_model_charts.STRATEGY_OPPORTUNITY_CHART_METRICS;
51
51
  exports.STRATEGY_POSITION_CHART_METRICS = require_model_charts.STRATEGY_POSITION_CHART_METRICS;
52
52
  exports.STRATEGY_POSITION_COLLATERAL_ERROR = require_model_positions.STRATEGY_POSITION_COLLATERAL_ERROR;
53
+ exports.accountNotMidasGreenlisted = require_model_errors_operation_errors.accountNotMidasGreenlisted;
53
54
  exports.amountSchema = require_model_primitives_schema.amountSchema;
54
55
  exports.analyticsChartQueryOptionsSchema = require_model_analytics_schema.analyticsChartQueryOptionsSchema;
55
56
  exports.analyticsChartQueryParamsSchema = require_model_analytics_schema.analyticsChartQueryParamsSchema;
@@ -183,7 +183,10 @@ var CreditAccountOperationsService = class extends require_onchain_base_SDKConst
183
183
  });
184
184
  return {
185
185
  ...result,
186
- state: tail.state,
186
+ state: {
187
+ ...tail.state,
188
+ executionCost: result.state.executionCost
189
+ },
187
190
  delayed
188
191
  };
189
192
  } catch (e) {
@@ -1,4 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_onchain_constants_math = require("../../constants/math.js");
2
3
  const require_model_errors_operation_errors = require("../../../model/errors/operation-errors.js");
3
4
  const require_model_errors_prepare_errors = require("../../../model/errors/prepare-errors.js");
4
5
  require("../../../model/index.js");
@@ -73,6 +74,26 @@ async function realize(steps, props) {
73
74
  let raised = 0n;
74
75
  /** The request, before the walk's end state can be attached to it. */
75
76
  let delayed;
77
+ /** Oracle value in the underlying of what routed legs and requests spend and return. */
78
+ const traded = {
79
+ spentUnd: 0n,
80
+ returnedUnd: 0n,
81
+ priced: true
82
+ };
83
+ const trade = (spent, returned) => {
84
+ const underlyingValue = (legs) => {
85
+ let sum = 0n;
86
+ for (const { token, amount } of legs) {
87
+ if (amount === 0n) continue;
88
+ const value = price(token, underlying, amount);
89
+ if (value <= 0n) traded.priced = false;
90
+ sum += value;
91
+ }
92
+ return sum;
93
+ };
94
+ traded.spentUnd += underlyingValue(spent);
95
+ traded.returnedUnd += underlyingValue(returned);
96
+ };
76
97
  /**
77
98
  * Set by a `clearQuotas` step, which settles the quotas mid-walk instead of
78
99
  * at the end — and settles them at none, whatever the balances turn out to be.
@@ -174,6 +195,13 @@ async function realize(steps, props) {
174
195
  ...swap,
175
196
  amountOut: leg.amount
176
197
  });
198
+ trade([{
199
+ token: step.from,
200
+ amount
201
+ }], [{
202
+ token: step.to,
203
+ amount: leg.amount
204
+ }]);
177
205
  raised = leg.minAmount;
178
206
  break;
179
207
  }
@@ -199,6 +227,13 @@ async function realize(steps, props) {
199
227
  })),
200
228
  amountOut: leg.amount
201
229
  });
230
+ trade(balances.map((a) => ({
231
+ token: a.token,
232
+ amount: a.balance
233
+ })), [{
234
+ token: underlying,
235
+ amount: leg.amount
236
+ }]);
202
237
  }
203
238
  }
204
239
  raised = ledger.balanceOf(underlying);
@@ -243,6 +278,13 @@ async function realize(steps, props) {
243
278
  amount: require_onchain_accounts_intents_utils_common.toTargetDecimals(queued.amount, queued.token, asset.underlying, sdk)
244
279
  } : void 0
245
280
  };
281
+ trade([{
282
+ token: preview.token,
283
+ amount: preview.amountIn
284
+ }], [...preview.outputs.filter((o) => !o.isDelayed).map((o) => ({
285
+ token: o.token,
286
+ amount: o.amount
287
+ })), ...delayed.claim ? [delayed.claim] : []]);
246
288
  raised = require_onchain_accounts_intents_operations.instantOutput(preview.outputs)?.amount ?? 0n;
247
289
  break;
248
290
  }
@@ -338,9 +380,11 @@ async function realize(steps, props) {
338
380
  netValue: projected.totalValue - debt,
339
381
  toUnderlying: (from, amount) => price(from, underlying, amount)
340
382
  });
383
+ const executionCost = traded.priced && traded.spentUnd > 0n ? require_onchain_constants_math.PERCENTAGE_FACTOR_1KK * (traded.returnedUnd - traded.spentUnd) / traded.spentUnd : void 0;
341
384
  const state = {
342
385
  ...projection,
343
386
  priceImpact,
387
+ executionCost,
344
388
  currentPrice: sdk.positions.currentPrice(snapshot)
345
389
  };
346
390
  return {
@@ -19,12 +19,12 @@ function probeBasket(balances, oracle) {
19
19
  if (usd > 0n) basketWad += usd * require_onchain_constants_math.WAD / require_onchain_constants_math.PRICE_DECIMALS;
20
20
  }
21
21
  if (basketWad <= 0n) return;
22
- const probeWad = PROBE_UNIT_USD_WAD;
23
22
  const scaled = balances.map((asset) => ({
24
23
  token: asset.token,
25
- balance: asset.balance * probeWad / basketWad
24
+ balance: asset.balance * PROBE_UNIT_USD_WAD / basketWad
26
25
  }));
27
- if (!scaled.some((a) => a.balance > 0n)) return;
26
+ const probeWad = scaled.reduce((sum, a) => sum + oracle.safeConvertToUSD(a.token, a.balance).value * require_onchain_constants_math.WAD / require_onchain_constants_math.PRICE_DECIMALS, 0n);
27
+ if (probeWad <= 0n) return;
28
28
  return {
29
29
  balances: scaled,
30
30
  basketWad,
@@ -223,6 +223,7 @@ const require_onchain_validation_bundles_checkIncreaseDebt = require("./validati
223
223
  const require_onchain_validation_bundles_checkIncreaseQuota = require("./validation/bundles/checkIncreaseQuota.js");
224
224
  const require_onchain_validation_bundles_checkMarket = require("./validation/bundles/checkMarket.js");
225
225
  const require_onchain_validation_bundles_checkObtained = require("./validation/bundles/checkObtained.js");
226
+ const require_onchain_validation_bundles_checkMidasAccountGreenlist = require("./validation/bundles/checkMidasAccountGreenlist.js");
226
227
  const require_onchain_validation_bundles_checkRWAOpenRequirements = require("./validation/bundles/checkRWAOpenRequirements.js");
227
228
  const require_onchain_validation_bundles_checkRWAOpening = require("./validation/bundles/checkRWAOpening.js");
228
229
  const require_onchain_validation_bundles_checkCreditOperation = require("./validation/bundles/checkCreditOperation.js");
@@ -293,6 +294,7 @@ const require_onchain_preview_preview_detectCloseOrRepay = require("./preview/pr
293
294
  const require_onchain_preview_preview_detectDelayedClaim = require("./preview/preview/detectDelayedClaim.js");
294
295
  const require_onchain_preview_preview_detectDelayedOperation = require("./preview/preview/detectDelayedOperation.js");
295
296
  const require_onchain_preview_preview_estimateClaimableAt = require("./preview/preview/estimateClaimableAt.js");
297
+ const require_onchain_preview_preview_midasGreenlistsAccount = require("./preview/preview/midasGreenlistsAccount.js");
296
298
  const require_onchain_preview_preview_previewAdjustStrategyPosition = require("./preview/preview/previewAdjustStrategyPosition.js");
297
299
  const require_onchain_preview_preview_previewExitOrRepayStrategyPosition = require("./preview/preview/previewExitOrRepayStrategyPosition.js");
298
300
  const require_onchain_preview_preview_replayInnerOperations = require("./preview/preview/replayInnerOperations.js");
@@ -576,6 +578,7 @@ exports.checkLiquidationFunding = require_onchain_validation_bundles_checkLiquid
576
578
  exports.checkLiquidatorEligible = require_onchain_validation_checks_checkLiquidatorEligible.checkLiquidatorEligible;
577
579
  exports.checkMarket = require_onchain_validation_bundles_checkMarket.checkMarket;
578
580
  exports.checkMarketExpired = require_onchain_validation_checks_checkMarketExpired.checkMarketExpired;
581
+ exports.checkMidasAccountGreenlist = require_onchain_validation_bundles_checkMidasAccountGreenlist.checkMidasAccountGreenlist;
579
582
  exports.checkObtained = require_onchain_validation_bundles_checkObtained.checkObtained;
580
583
  exports.checkOperation = require_onchain_validation_checkOperation.checkOperation;
581
584
  exports.checkPoolFunding = require_onchain_validation_bundles_checkPoolFunding.checkPoolFunding;
@@ -755,6 +758,7 @@ exports.json_stringify = require_onchain_utils_json.json_stringify;
755
758
  exports.lidoV1_WETHGatewayAbi = require_onchain_market_adapters_abi_targetContractAbi.lidoV1_WETHGatewayAbi;
756
759
  exports.makeReplayState = require_onchain_preview_preview_replayInnerOperations.makeReplayState;
757
760
  exports.mellowDvvAdapterAbi = require_onchain_market_adapters_abi_adapters_mellowDvvAdapter.mellowDvvAdapterAbi;
761
+ exports.midasGreenlistsAccount = require_onchain_preview_preview_midasGreenlistsAccount.midasGreenlistsAccount;
758
762
  exports.minSeizedAmount = require_onchain_market_math.minSeizedAmount;
759
763
  exports.numberWithCommas = require_onchain_utils_formatter.numberWithCommas;
760
764
  exports.onchainSDKOptionsSchema = require_onchain_options.onchainSDKOptionsSchema;
@@ -170,13 +170,21 @@ var MidasGatewayAdapterContract = class extends require_onchain_market_adapters_
170
170
  return { redeemer };
171
171
  }
172
172
  /**
173
+ * Whether `calldata` is `receiveGreenlist()`, the call that grants the
174
+ * Midas greenlisted role to the credit account.
175
+ */
176
+ isReceiveGreenlist(calldata) {
177
+ return calldata === receiveGreenlistCalldata;
178
+ }
179
+ /**
173
180
  * `receiveGreenlist()` is prepended by `prependMidasReceiveGreenlist`
174
181
  * before the balance bracket when the multicall mints a permissioned
175
- * mToken: it only greenlists the credit account and is balance-neutral,
176
- * so it is legal outside a bracket and leaves balances untouched.
182
+ * mToken: it only grants the Midas greenlisted role to the credit
183
+ * account and is balance-neutral, so it is legal outside a bracket and
184
+ * leaves balances untouched.
177
185
  */
178
186
  replayOutOfBracketCall(_balances, calldata) {
179
- return calldata === receiveGreenlistCalldata;
187
+ return this.isReceiveGreenlist(calldata);
180
188
  }
181
189
  applyBalanceChanges(balances, decoded) {
182
190
  switch (decoded.functionName) {
@@ -12,6 +12,7 @@ const require_onchain_preview_preview_detectCloseOrRepay = require("./preview/de
12
12
  const require_onchain_preview_preview_detectDelayedClaim = require("./preview/detectDelayedClaim.js");
13
13
  const require_onchain_preview_preview_detectDelayedOperation = require("./preview/detectDelayedOperation.js");
14
14
  const require_onchain_preview_preview_estimateClaimableAt = require("./preview/estimateClaimableAt.js");
15
+ const require_onchain_preview_preview_midasGreenlistsAccount = require("./preview/midasGreenlistsAccount.js");
15
16
  const require_onchain_preview_preview_previewAdjustStrategyPosition = require("./preview/previewAdjustStrategyPosition.js");
16
17
  const require_onchain_preview_preview_previewExitOrRepayStrategyPosition = require("./preview/previewExitOrRepayStrategyPosition.js");
17
18
  const require_onchain_preview_preview_replayInnerOperations = require("./preview/replayInnerOperations.js");
@@ -29,6 +30,7 @@ exports.isCloseOrRepay = require_onchain_preview_preview_detectCloseOrRepay.isCl
29
30
  exports.isPoolOperation = require_onchain_preview_parse_types.isPoolOperation;
30
31
  exports.isRWAOperation = require_onchain_preview_parse_types.isRWAOperation;
31
32
  exports.makeReplayState = require_onchain_preview_preview_replayInnerOperations.makeReplayState;
33
+ exports.midasGreenlistsAccount = require_onchain_preview_preview_midasGreenlistsAccount.midasGreenlistsAccount;
32
34
  exports.parseFacadeOperationCalldata = require_onchain_preview_parse_parseFacadeOperationCalldata.parseFacadeOperationCalldata;
33
35
  exports.parseOperationCalldata = require_onchain_preview_parse_parseOperationCalldata.parseOperationCalldata;
34
36
  exports.parsePoolOperationCalldata = require_onchain_preview_parse_parsePoolOperationCalldata.parsePoolOperationCalldata;
@@ -5,6 +5,7 @@ const require_onchain_preview_preview_detectCloseOrRepay = require("./detectClos
5
5
  const require_onchain_preview_preview_detectDelayedClaim = require("./detectDelayedClaim.js");
6
6
  const require_onchain_preview_preview_detectDelayedOperation = require("./detectDelayedOperation.js");
7
7
  const require_onchain_preview_preview_estimateClaimableAt = require("./estimateClaimableAt.js");
8
+ const require_onchain_preview_preview_midasGreenlistsAccount = require("./midasGreenlistsAccount.js");
8
9
  const require_onchain_preview_preview_previewAdjustStrategyPosition = require("./previewAdjustStrategyPosition.js");
9
10
  const require_onchain_preview_preview_previewExitOrRepayStrategyPosition = require("./previewExitOrRepayStrategyPosition.js");
10
11
  const require_onchain_preview_preview_replayInnerOperations = require("./replayInnerOperations.js");
@@ -18,6 +19,7 @@ exports.detectDelayedOperation = require_onchain_preview_preview_detectDelayedOp
18
19
  exports.estimateClaimableAt = require_onchain_preview_preview_estimateClaimableAt.estimateClaimableAt;
19
20
  exports.isCloseOrRepay = require_onchain_preview_preview_detectCloseOrRepay.isCloseOrRepay;
20
21
  exports.makeReplayState = require_onchain_preview_preview_replayInnerOperations.makeReplayState;
22
+ exports.midasGreenlistsAccount = require_onchain_preview_preview_midasGreenlistsAccount.midasGreenlistsAccount;
21
23
  exports.previewAdjustStrategyPosition = require_onchain_preview_preview_previewAdjustStrategyPosition.previewAdjustStrategyPosition;
22
24
  exports.previewExitOrRepayStrategyPosition = require_onchain_preview_preview_previewExitOrRepayStrategyPosition.previewExitOrRepayStrategyPosition;
23
25
  exports.previewOperation = require_onchain_preview_preview_previewOperation.previewOperation;
@@ -0,0 +1,17 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_onchain_market_adapters_contracts_MidasGatewayAdapterContract = require("../../market/adapters/contracts/MidasGatewayAdapterContract.js");
3
+ //#region src/onchain/preview/preview/midasGreenlistsAccount.ts
4
+ /**
5
+ * Whether the multicall grants the Midas greenlisted role to the credit
6
+ * account via `receiveGreenlist()`.
7
+ */
8
+ function midasGreenlistsAccount(sdk, multicall) {
9
+ for (const op of multicall) {
10
+ if (op.operation !== "Execute") continue;
11
+ const adapter = sdk.getContract(op.adapter);
12
+ if (adapter instanceof require_onchain_market_adapters_contracts_MidasGatewayAdapterContract.MidasGatewayAdapterContract && adapter.isReceiveGreenlist(op.calldata)) return true;
13
+ }
14
+ return false;
15
+ }
16
+ //#endregion
17
+ exports.midasGreenlistsAccount = midasGreenlistsAccount;
@@ -3,6 +3,7 @@ const require_onchain_constants_address_provider = require("../../constants/addr
3
3
  const require_model_previews = require("../../../model/previews.js");
4
4
  const require_model_result = require("../../../model/result.js");
5
5
  require("../../../model/index.js");
6
+ const require_onchain_preview_preview_midasGreenlistsAccount = require("./midasGreenlistsAccount.js");
6
7
  const require_onchain_preview_preview_unwrapNativeCollateral = require("./unwrapNativeCollateral.js");
7
8
  //#region src/onchain/preview/preview/previewOpenStrategyPosition.ts
8
9
  function previewOpenStrategyPosition(sdk, input, operation, replay) {
@@ -33,7 +34,8 @@ function previewOpenStrategyPosition(sdk, input, operation, replay) {
33
34
  ...projection,
34
35
  operation: "OpenCreditAccount",
35
36
  ...operation.operation === "MultiCall" || operation.operation === "BotMulticall" || operation.operation === "RWAMulticall" ? { creditAccount: operation.creditAccount } : {},
36
- ..."args" in operation ? { rwaArgs: operation.args } : {}
37
+ ..."args" in operation ? { rwaArgs: operation.args } : {},
38
+ midasGreenlistsAccount: require_onchain_preview_preview_midasGreenlistsAccount.midasGreenlistsAccount(sdk, operation.multicall)
37
39
  });
38
40
  }
39
41
  /**
@@ -0,0 +1,46 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_model_errors_operation_errors = require("../../../model/errors/operation-errors.js");
3
+ const require_model_errors_prepare_errors = require("../../../model/errors/prepare-errors.js");
4
+ require("../../../model/index.js");
5
+ const require_onchain_validation_helpers_token = require("../helpers/token.js");
6
+ require("../helpers/index.js");
7
+ //#region src/onchain/validation/bundles/checkMidasAccountGreenlist.ts
8
+ /**
9
+ * Whether the credit account already holds the Midas greenlisted role
10
+ * this permissioned mToken requires of its holder, or the transaction
11
+ * grants it via `receiveGreenlist()`.
12
+ */
13
+ async function checkMidasAccountGreenlist(input) {
14
+ const { sdk, preview, nft, tokens } = input;
15
+ if (nft.protocol !== "midas") return [];
16
+ if (preview.midasGreenlistsAccount) return [];
17
+ if (tokens.length === 0) return [];
18
+ const account = preview.creditAccount;
19
+ if (!account) return tokens.map((token) => require_model_errors_operation_errors.accountNotMidasGreenlisted({
20
+ token: require_onchain_validation_helpers_token.toToken(sdk, token),
21
+ creditManager: preview.creditManager
22
+ }));
23
+ return (await Promise.all(tokens.map((token) => checkAccountRole({
24
+ sdk,
25
+ nft,
26
+ account,
27
+ token,
28
+ preview
29
+ })))).flat();
30
+ }
31
+ async function checkAccountRole(input) {
32
+ const { sdk, nft, account, token, preview } = input;
33
+ try {
34
+ const requirements = await nft.getOpenAccountRequirements(account, { tokenOutAddress: token });
35
+ if (nft.isRegistered(requirements)) return [];
36
+ return [require_model_errors_operation_errors.accountNotMidasGreenlisted({
37
+ token: require_onchain_validation_helpers_token.toToken(sdk, token),
38
+ creditManager: preview.creditManager,
39
+ creditAccount: account
40
+ })];
41
+ } catch (cause) {
42
+ return [require_model_errors_prepare_errors.unexpectedFailure(cause, "read the Midas account greenlist")];
43
+ }
44
+ }
45
+ //#endregion
46
+ exports.checkMidasAccountGreenlist = checkMidasAccountGreenlist;
@@ -1,24 +1,34 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_onchain_utils_AddressSet = require("../../utils/AddressSet.js");
3
+ const require_onchain_validation_bundles_checkMidasAccountGreenlist = require("./checkMidasAccountGreenlist.js");
3
4
  const require_onchain_validation_bundles_checkRWAOpenRequirements = require("./checkRWAOpenRequirements.js");
4
5
  //#region src/onchain/validation/bundles/checkRWAOpening.ts
5
6
  /**
6
7
  * Per KYC-gated token among `collateralAdded ∪ quotas`, whether the
7
- * borrower still has to register or sign before this opening can land.
8
+ * borrower still has to register or sign before this opening can land,
9
+ * and whether a Midas credit account may hold the mToken.
8
10
  */
9
11
  async function checkRWAOpening(input) {
10
12
  const { sdk, preview, sender } = input;
11
13
  const nft = await sdk.marketRegister.findCreditManager(preview.creditManager).degenNFT();
12
14
  if (!nft) return [];
13
- const gated = new require_onchain_utils_AddressSet.AddressSet(await nft.getTokens());
14
- const candidates = new require_onchain_utils_AddressSet.AddressSet([...preview.collateralAdded.map((a) => a.token.address), ...preview.quotas.map((q) => q.token.address)]);
15
- return (await Promise.all([...candidates].filter((token) => gated.has(token)).map((token) => require_onchain_validation_bundles_checkRWAOpenRequirements.checkRWAOpenRequirements({
15
+ const nftTokens = new require_onchain_utils_AddressSet.AddressSet(await nft.getTokens());
16
+ let candidates = new require_onchain_utils_AddressSet.AddressSet([...preview.collateralAdded.map((a) => a.token.address), ...preview.quotas.map((q) => q.token.address)]).asArray();
17
+ candidates = candidates.filter((token) => nftTokens.has(token));
18
+ let tokensToCheck = candidates;
19
+ if (tokensToCheck.length === 0 && !preview.creditAccount && nft.protocol === "midas") tokensToCheck = nftTokens.asArray();
20
+ return (await Promise.all([...tokensToCheck.map((token) => require_onchain_validation_bundles_checkRWAOpenRequirements.checkRWAOpenRequirements({
16
21
  sdk,
17
22
  wallet: sender,
18
23
  creditManager: preview.creditManager,
19
24
  token,
20
25
  providedArgs: preview.rwaArgs
21
- })))).flat();
26
+ })), require_onchain_validation_bundles_checkMidasAccountGreenlist.checkMidasAccountGreenlist({
27
+ sdk,
28
+ preview,
29
+ nft,
30
+ tokens: candidates
31
+ })])).flat();
22
32
  }
23
33
  //#endregion
24
34
  exports.checkRWAOpening = checkRWAOpening;
@@ -8,6 +8,7 @@ const require_onchain_validation_bundles_checkIncreaseDebt = require("./checkInc
8
8
  const require_onchain_validation_bundles_checkIncreaseQuota = require("./checkIncreaseQuota.js");
9
9
  const require_onchain_validation_bundles_checkMarket = require("./checkMarket.js");
10
10
  const require_onchain_validation_bundles_checkObtained = require("./checkObtained.js");
11
+ const require_onchain_validation_bundles_checkMidasAccountGreenlist = require("./checkMidasAccountGreenlist.js");
11
12
  const require_onchain_validation_bundles_checkRWAOpenRequirements = require("./checkRWAOpenRequirements.js");
12
13
  const require_onchain_validation_bundles_checkRWAOpening = require("./checkRWAOpening.js");
13
14
  const require_onchain_validation_bundles_checkCreditOperation = require("./checkCreditOperation.js");
@@ -25,6 +26,7 @@ exports.checkIncreaseQuota = require_onchain_validation_bundles_checkIncreaseQuo
25
26
  exports.checkLiquidationEligibility = require_onchain_validation_bundles_checkLiquidationEligibility.checkLiquidationEligibility;
26
27
  exports.checkLiquidationFunding = require_onchain_validation_bundles_checkLiquidationFunding.checkLiquidationFunding;
27
28
  exports.checkMarket = require_onchain_validation_bundles_checkMarket.checkMarket;
29
+ exports.checkMidasAccountGreenlist = require_onchain_validation_bundles_checkMidasAccountGreenlist.checkMidasAccountGreenlist;
28
30
  exports.checkObtained = require_onchain_validation_bundles_checkObtained.checkObtained;
29
31
  exports.checkPoolFunding = require_onchain_validation_bundles_checkPoolFunding.checkPoolFunding;
30
32
  exports.checkPoolOperation = require_onchain_validation_bundles_checkPoolOperation.checkPoolOperation;
@@ -29,6 +29,7 @@ const require_onchain_validation_bundles_checkIncreaseDebt = require("./bundles/
29
29
  const require_onchain_validation_bundles_checkIncreaseQuota = require("./bundles/checkIncreaseQuota.js");
30
30
  const require_onchain_validation_bundles_checkMarket = require("./bundles/checkMarket.js");
31
31
  const require_onchain_validation_bundles_checkObtained = require("./bundles/checkObtained.js");
32
+ const require_onchain_validation_bundles_checkMidasAccountGreenlist = require("./bundles/checkMidasAccountGreenlist.js");
32
33
  const require_onchain_validation_bundles_checkRWAOpenRequirements = require("./bundles/checkRWAOpenRequirements.js");
33
34
  const require_onchain_validation_bundles_checkRWAOpening = require("./bundles/checkRWAOpening.js");
34
35
  const require_onchain_validation_bundles_checkCreditOperation = require("./bundles/checkCreditOperation.js");
@@ -67,6 +68,7 @@ exports.checkLiquidationFunding = require_onchain_validation_bundles_checkLiquid
67
68
  exports.checkLiquidatorEligible = require_onchain_validation_checks_checkLiquidatorEligible.checkLiquidatorEligible;
68
69
  exports.checkMarket = require_onchain_validation_bundles_checkMarket.checkMarket;
69
70
  exports.checkMarketExpired = require_onchain_validation_checks_checkMarketExpired.checkMarketExpired;
71
+ exports.checkMidasAccountGreenlist = require_onchain_validation_bundles_checkMidasAccountGreenlist.checkMidasAccountGreenlist;
70
72
  exports.checkObtained = require_onchain_validation_bundles_checkObtained.checkObtained;
71
73
  exports.checkOperation = require_onchain_validation_checkOperation.checkOperation;
72
74
  exports.checkPoolFunding = require_onchain_validation_bundles_checkPoolFunding.checkPoolFunding;
@@ -1,7 +1,7 @@
1
1
  import "./base.js";
2
2
  import { creditAccountFrozen, liquidatorNotEligible, notEmergencyLiquidator } from "./liquidation-errors.js";
3
- import { creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet } from "./operation-errors.js";
3
+ import { accountNotMidasGreenlisted, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet } from "./operation-errors.js";
4
4
  import { unpriceableTokenError } from "./oracle-errors.js";
5
5
  import { creditAccountNotEmpty, creditAccountNotFound, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, unexpectedFailure, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress } from "./prepare-errors.js";
6
6
  import { malformedTransaction } from "./preview-errors.js";
7
- export { creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, liquidatorNotEligible, malformedTransaction, marketExpired, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress };
7
+ export { accountNotMidasGreenlisted, creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, liquidatorNotEligible, malformedTransaction, marketExpired, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress };
@@ -125,5 +125,13 @@ function rwaOpenRequirementsNotMet(args) {
125
125
  ...args
126
126
  };
127
127
  }
128
+ /** {@inheritDoc AccountNotMidasGreenlistedError} */
129
+ function accountNotMidasGreenlisted(args) {
130
+ return {
131
+ code: "accountNotMidasGreenlisted",
132
+ message: `The credit account is not Midas-greenlisted for ${args.token.symbol}.`,
133
+ ...args
134
+ };
135
+ }
128
136
  //#endregion
129
- export { creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet };
137
+ export { accountNotMidasGreenlisted, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet };
@@ -15,7 +15,7 @@ import { ANALYTICS_POSITIONS_DEFAULT_LIMIT, ANALYTICS_POSITIONS_MAX_LIMIT, analy
15
15
  import "./curators.js";
16
16
  import "./delayed-intents.js";
17
17
  import { creditAccountFrozen, liquidatorNotEligible, notEmergencyLiquidator } from "./errors/liquidation-errors.js";
18
- import { creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet } from "./errors/operation-errors.js";
18
+ import { accountNotMidasGreenlisted, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet } from "./errors/operation-errors.js";
19
19
  import { unpriceableTokenError } from "./errors/oracle-errors.js";
20
20
  import { creditAccountNotEmpty, creditAccountNotFound, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, unexpectedFailure, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress } from "./errors/prepare-errors.js";
21
21
  import { malformedTransaction } from "./errors/preview-errors.js";
@@ -32,4 +32,4 @@ import { chainFailedSchema, chainMetadataSchema, chainSucceededSchema, dataSourc
32
32
  import { safeValue, sdkErr, sdkOk } from "./result.js";
33
33
  import "./withdrawals.js";
34
34
  import { positionClaimableWithdrawalSchema, positionPendingWithdrawalSchema, positionWithdrawalsSchema, withdrawalOutputAmountSchema } from "./withdrawals.schema.js";
35
- export { ANALYTICS_POSITIONS_DEFAULT_LIMIT, ANALYTICS_POSITIONS_MAX_LIMIT, CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, FILTER_ALL, KYC_REGISTRATION_LINKS, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, PROTOCOL_CHART_METRICS, RWA_FACTORY_SECURITIZE, RWA_FACTORY_TYPES, RWA_PROTOCOLS, SECURITIZE_REGISTER_VAULT_TYPES, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, STRATEGY_POSITION_COLLATERAL_ERROR, amountSchema, analyticsChartQueryOptionsSchema, analyticsChartQueryParamsSchema, analyticsChartQuerySchema, analyticsPositionListOptionsSchema, analyticsPositionListQueryParamsSchema, analyticsPositionListQuerySchema, analyticsPositionPageSchema, analyticsPositionSchema, analyticsPositionSortFieldSchema, analyticsSortDirectionSchema, apyBreakdownSchema, asEstimated, assetTypeSchema, backendPreferred, booleanParamSchema, borrowRateBreakdownSchema, bpsSchema, chainFailedSchema, chainIdSchema, chainMetadataSchema, chainSucceededSchema, chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, compareTagOf, creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, curatorNameSchema, curatorSchema, dataSourceSchema, debtOutOfRange, delayedReceivedAssetSchema, encodeFlag, filterAllSchema, filterable, forbiddenToken, instantReceivedAssetSchema, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, isFilterSet, kycRequirementSchema, leverageOutOfRange, leverageSchema, liquidatableAccountFilterSchema, liquidatableAccountSchema, liquidationApprovalSchema, liquidationDetailsSchema, liquidationPositionId, liquidationPositionSchema, liquidatorNotEligible, malformedTransaction, marketExpired, matchesLiquidatableAccountFilter, matchesOpportunityFilter, matchesPositionFilter, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, noticeKindSchema, noticeSchema, offchainOnly, onchainOnly, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityId, opportunityKeySchema, opportunityKindSchema, opportunitySchema, opportunityTotalsSchema, pnlBreakdownSchema, pointRewardsSchema, pointsProgramPnLSchema, pointsProgramSchema, pointsRewardsPnLSchema, poolOpportunityChartMetricSchema, poolOpportunityDetailSchema, poolOpportunityId, poolOpportunityKeySchema, poolOpportunitySchema, poolPaused, poolPositionChartMetricSchema, poolPositionId, poolPositionKeySchema, poolPositionSchema, poolSunset, positionClaimableWithdrawalSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionId, positionKeySchema, positionKindSchema, positionPendingWithdrawalSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionWithdrawalsSchema, positionsTotalsSchema, priceFeedDataSchema, priceFeedSummarySchema, protocolChartMetricSchema, quotaAssetSchema, quotaCountExceeded, quotaLimitReached, rateCurvePointSchema, rateCurveSchema, receivedAssetSchema, reservePriceLimited, responseMetadataSchema, responseSchema, rewardsPnLSchema, rewardsSchema, rwaOpenRequirementsNotMet, rwaProtocolSchema, safeValue, sdkErr, sdkOk, strategyOpportunityChartMetricSchema, strategyOpportunityDetailSchema, strategyOpportunityId, strategyOpportunityKeySchema, strategyOpportunitySchema, strategyPositionChartMetricSchema, strategyPositionId, strategyPositionKeySchema, strategyPositionSchema, timestampSchema, tokenAmountSchema, tokenQuotaRateSchema, tokenRewardsPnLSchema, tokenRewardsSchema, tokenSchema, tolerance, txCallSchema, underlyingTokenSchema, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress, withdrawalOutputAmountSchema };
35
+ export { ANALYTICS_POSITIONS_DEFAULT_LIMIT, ANALYTICS_POSITIONS_MAX_LIMIT, CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, FILTER_ALL, KYC_REGISTRATION_LINKS, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, PROTOCOL_CHART_METRICS, RWA_FACTORY_SECURITIZE, RWA_FACTORY_TYPES, RWA_PROTOCOLS, SECURITIZE_REGISTER_VAULT_TYPES, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, STRATEGY_POSITION_COLLATERAL_ERROR, accountNotMidasGreenlisted, amountSchema, analyticsChartQueryOptionsSchema, analyticsChartQueryParamsSchema, analyticsChartQuerySchema, analyticsPositionListOptionsSchema, analyticsPositionListQueryParamsSchema, analyticsPositionListQuerySchema, analyticsPositionPageSchema, analyticsPositionSchema, analyticsPositionSortFieldSchema, analyticsSortDirectionSchema, apyBreakdownSchema, asEstimated, assetTypeSchema, backendPreferred, booleanParamSchema, borrowRateBreakdownSchema, bpsSchema, chainFailedSchema, chainIdSchema, chainMetadataSchema, chainSucceededSchema, chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, compareTagOf, creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, curatorNameSchema, curatorSchema, dataSourceSchema, debtOutOfRange, delayedReceivedAssetSchema, encodeFlag, filterAllSchema, filterable, forbiddenToken, instantReceivedAssetSchema, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, isFilterSet, kycRequirementSchema, leverageOutOfRange, leverageSchema, liquidatableAccountFilterSchema, liquidatableAccountSchema, liquidationApprovalSchema, liquidationDetailsSchema, liquidationPositionId, liquidationPositionSchema, liquidatorNotEligible, malformedTransaction, marketExpired, matchesLiquidatableAccountFilter, matchesOpportunityFilter, matchesPositionFilter, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, noticeKindSchema, noticeSchema, offchainOnly, onchainOnly, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityId, opportunityKeySchema, opportunityKindSchema, opportunitySchema, opportunityTotalsSchema, pnlBreakdownSchema, pointRewardsSchema, pointsProgramPnLSchema, pointsProgramSchema, pointsRewardsPnLSchema, poolOpportunityChartMetricSchema, poolOpportunityDetailSchema, poolOpportunityId, poolOpportunityKeySchema, poolOpportunitySchema, poolPaused, poolPositionChartMetricSchema, poolPositionId, poolPositionKeySchema, poolPositionSchema, poolSunset, positionClaimableWithdrawalSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionId, positionKeySchema, positionKindSchema, positionPendingWithdrawalSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionWithdrawalsSchema, positionsTotalsSchema, priceFeedDataSchema, priceFeedSummarySchema, protocolChartMetricSchema, quotaAssetSchema, quotaCountExceeded, quotaLimitReached, rateCurvePointSchema, rateCurveSchema, receivedAssetSchema, reservePriceLimited, responseMetadataSchema, responseSchema, rewardsPnLSchema, rewardsSchema, rwaOpenRequirementsNotMet, rwaProtocolSchema, safeValue, sdkErr, sdkOk, strategyOpportunityChartMetricSchema, strategyOpportunityDetailSchema, strategyOpportunityId, strategyOpportunityKeySchema, strategyOpportunitySchema, strategyPositionChartMetricSchema, strategyPositionId, strategyPositionKeySchema, strategyPositionSchema, timestampSchema, tokenAmountSchema, tokenQuotaRateSchema, tokenRewardsPnLSchema, tokenRewardsSchema, tokenSchema, tolerance, txCallSchema, underlyingTokenSchema, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress, withdrawalOutputAmountSchema };
@@ -182,7 +182,10 @@ var CreditAccountOperationsService = class extends SDKConstruct {
182
182
  });
183
183
  return {
184
184
  ...result,
185
- state: tail.state,
185
+ state: {
186
+ ...tail.state,
187
+ executionCost: result.state.executionCost
188
+ },
186
189
  delayed
187
190
  };
188
191
  } catch (e) {
@@ -1,3 +1,4 @@
1
+ import { PERCENTAGE_FACTOR_1KK } from "../../constants/math.js";
1
2
  import { insufficientBalance } from "../../../model/errors/operation-errors.js";
2
3
  import { multipleDelayedWithdrawals, noDelayedRoute, withdrawalInProgress } from "../../../model/errors/prepare-errors.js";
3
4
  import "../../../model/index.js";
@@ -72,6 +73,26 @@ async function realize(steps, props) {
72
73
  let raised = 0n;
73
74
  /** The request, before the walk's end state can be attached to it. */
74
75
  let delayed;
76
+ /** Oracle value in the underlying of what routed legs and requests spend and return. */
77
+ const traded = {
78
+ spentUnd: 0n,
79
+ returnedUnd: 0n,
80
+ priced: true
81
+ };
82
+ const trade = (spent, returned) => {
83
+ const underlyingValue = (legs) => {
84
+ let sum = 0n;
85
+ for (const { token, amount } of legs) {
86
+ if (amount === 0n) continue;
87
+ const value = price(token, underlying, amount);
88
+ if (value <= 0n) traded.priced = false;
89
+ sum += value;
90
+ }
91
+ return sum;
92
+ };
93
+ traded.spentUnd += underlyingValue(spent);
94
+ traded.returnedUnd += underlyingValue(returned);
95
+ };
75
96
  /**
76
97
  * Set by a `clearQuotas` step, which settles the quotas mid-walk instead of
77
98
  * at the end — and settles them at none, whatever the balances turn out to be.
@@ -173,6 +194,13 @@ async function realize(steps, props) {
173
194
  ...swap,
174
195
  amountOut: leg.amount
175
196
  });
197
+ trade([{
198
+ token: step.from,
199
+ amount
200
+ }], [{
201
+ token: step.to,
202
+ amount: leg.amount
203
+ }]);
176
204
  raised = leg.minAmount;
177
205
  break;
178
206
  }
@@ -198,6 +226,13 @@ async function realize(steps, props) {
198
226
  })),
199
227
  amountOut: leg.amount
200
228
  });
229
+ trade(balances.map((a) => ({
230
+ token: a.token,
231
+ amount: a.balance
232
+ })), [{
233
+ token: underlying,
234
+ amount: leg.amount
235
+ }]);
201
236
  }
202
237
  }
203
238
  raised = ledger.balanceOf(underlying);
@@ -242,6 +277,13 @@ async function realize(steps, props) {
242
277
  amount: toTargetDecimals(queued.amount, queued.token, asset.underlying, sdk)
243
278
  } : void 0
244
279
  };
280
+ trade([{
281
+ token: preview.token,
282
+ amount: preview.amountIn
283
+ }], [...preview.outputs.filter((o) => !o.isDelayed).map((o) => ({
284
+ token: o.token,
285
+ amount: o.amount
286
+ })), ...delayed.claim ? [delayed.claim] : []]);
245
287
  raised = instantOutput(preview.outputs)?.amount ?? 0n;
246
288
  break;
247
289
  }
@@ -337,9 +379,11 @@ async function realize(steps, props) {
337
379
  netValue: projected.totalValue - debt,
338
380
  toUnderlying: (from, amount) => price(from, underlying, amount)
339
381
  });
382
+ const executionCost = traded.priced && traded.spentUnd > 0n ? PERCENTAGE_FACTOR_1KK * (traded.returnedUnd - traded.spentUnd) / traded.spentUnd : void 0;
340
383
  const state = {
341
384
  ...projection,
342
385
  priceImpact,
386
+ executionCost,
343
387
  currentPrice: sdk.positions.currentPrice(snapshot)
344
388
  };
345
389
  return {
@@ -18,12 +18,12 @@ function probeBasket(balances, oracle) {
18
18
  if (usd > 0n) basketWad += usd * WAD / PRICE_DECIMALS;
19
19
  }
20
20
  if (basketWad <= 0n) return;
21
- const probeWad = PROBE_UNIT_USD_WAD;
22
21
  const scaled = balances.map((asset) => ({
23
22
  token: asset.token,
24
- balance: asset.balance * probeWad / basketWad
23
+ balance: asset.balance * PROBE_UNIT_USD_WAD / basketWad
25
24
  }));
26
- if (!scaled.some((a) => a.balance > 0n)) return;
25
+ const probeWad = scaled.reduce((sum, a) => sum + oracle.safeConvertToUSD(a.token, a.balance).value * WAD / PRICE_DECIMALS, 0n);
26
+ if (probeWad <= 0n) return;
27
27
  return {
28
28
  balances: scaled,
29
29
  basketWad,