@gearbox-protocol/sdk 16.0.0-next.27 → 16.0.0-next.29

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 (75) hide show
  1. package/dist/cjs/model/index.js +1 -0
  2. package/dist/cjs/model/previews.js +23 -0
  3. package/dist/cjs/onchain/accounts/intents/open-strategy.js +5 -18
  4. package/dist/cjs/onchain/accounts/intents/realize.js +77 -49
  5. package/dist/cjs/onchain/accounts/intents/testing/market.js +1 -0
  6. package/dist/cjs/onchain/accounts/intents/testing/sdk-mock.js +28 -5
  7. package/dist/cjs/onchain/index.js +6 -0
  8. package/dist/cjs/onchain/market/credit/creditOperationMarket.js +32 -0
  9. package/dist/cjs/onchain/market/credit/index.js +3 -0
  10. package/dist/cjs/onchain/market/index.js +5 -0
  11. package/dist/cjs/onchain/market/oracle/collateralPriceInUnderlying.js +27 -0
  12. package/dist/cjs/onchain/market/oracle/index.js +2 -0
  13. package/dist/cjs/onchain/positions/PositionsService.js +94 -0
  14. package/dist/cjs/onchain/positions/calcLiquidationPrice.js +14 -4
  15. package/dist/cjs/onchain/positions/index.js +1 -0
  16. package/dist/cjs/preview/index.js +6 -6
  17. package/dist/cjs/preview/preview/{buildDelayedPreview.js → buildDelayedStrategyVerify.js} +8 -27
  18. package/dist/cjs/preview/preview/index.js +6 -6
  19. package/dist/cjs/preview/preview/{previewAdjustCreditAccount.js → previewAdjustStrategyVerify.js} +6 -24
  20. package/dist/cjs/preview/preview/{previewCloseOrRepayCreditAccount.js → previewExitOrRepayStrategyVerify.js} +6 -7
  21. package/dist/cjs/preview/preview/{previewPoolOperation.js → previewLpVerify.js} +3 -3
  22. package/dist/cjs/preview/preview/{previewOpenCreditAccount.js → previewOpenStrategyVerify.js} +6 -26
  23. package/dist/cjs/preview/preview/previewOperation.js +13 -12
  24. package/dist/cjs/preview/validate/checkOperation.js +13 -9
  25. package/dist/esm/model/index.js +2 -2
  26. package/dist/esm/model/previews.js +23 -1
  27. package/dist/esm/onchain/accounts/intents/open-strategy.js +5 -18
  28. package/dist/esm/onchain/accounts/intents/realize.js +77 -49
  29. package/dist/esm/onchain/accounts/intents/testing/market.js +1 -0
  30. package/dist/esm/onchain/accounts/intents/testing/sdk-mock.js +27 -6
  31. package/dist/esm/onchain/index.js +4 -2
  32. package/dist/esm/onchain/market/credit/creditOperationMarket.js +30 -0
  33. package/dist/esm/onchain/market/credit/index.js +2 -1
  34. package/dist/esm/onchain/market/index.js +3 -1
  35. package/dist/esm/onchain/market/oracle/collateralPriceInUnderlying.js +26 -0
  36. package/dist/esm/onchain/market/oracle/index.js +2 -1
  37. package/dist/esm/onchain/positions/PositionsService.js +95 -1
  38. package/dist/esm/onchain/positions/calcLiquidationPrice.js +14 -5
  39. package/dist/esm/onchain/positions/index.js +2 -2
  40. package/dist/esm/preview/index.js +4 -4
  41. package/dist/esm/preview/preview/{buildDelayedPreview.js → buildDelayedStrategyVerify.js} +9 -28
  42. package/dist/esm/preview/preview/index.js +4 -4
  43. package/dist/esm/preview/preview/{previewAdjustCreditAccount.js → previewAdjustStrategyVerify.js} +7 -25
  44. package/dist/esm/preview/preview/{previewCloseOrRepayCreditAccount.js → previewExitOrRepayStrategyVerify.js} +6 -7
  45. package/dist/esm/preview/preview/{previewPoolOperation.js → previewLpVerify.js} +3 -3
  46. package/dist/esm/preview/preview/{previewOpenCreditAccount.js → previewOpenStrategyVerify.js} +7 -27
  47. package/dist/esm/preview/preview/previewOperation.js +13 -12
  48. package/dist/esm/preview/validate/checkOperation.js +13 -9
  49. package/dist/types/model/index.d.ts +2 -2
  50. package/dist/types/model/previews.d.ts +222 -97
  51. package/dist/types/onchain/accounts/intents/open-strategy.d.ts +13 -7
  52. package/dist/types/onchain/accounts/intents/testing/market.d.ts +1 -0
  53. package/dist/types/onchain/accounts/intents/testing/sdk-mock.d.ts +18 -0
  54. package/dist/types/onchain/accounts/intents/types.d.ts +12 -0
  55. package/dist/types/onchain/index.d.ts +4 -2
  56. package/dist/types/onchain/market/credit/creditOperationMarket.d.ts +23 -0
  57. package/dist/types/onchain/market/credit/index.d.ts +2 -1
  58. package/dist/types/onchain/market/index.d.ts +3 -1
  59. package/dist/types/onchain/market/oracle/collateralPriceInUnderlying.d.ts +19 -0
  60. package/dist/types/onchain/market/oracle/index.d.ts +2 -1
  61. package/dist/types/onchain/positions/PositionsService.d.ts +38 -0
  62. package/dist/types/onchain/positions/calcLiquidationPrice.d.ts +10 -1
  63. package/dist/types/onchain/positions/index.d.ts +2 -2
  64. package/dist/types/preview/index.d.ts +5 -5
  65. package/dist/types/preview/preview/{buildDelayedPreview.d.ts → buildDelayedStrategyVerify.d.ts} +4 -4
  66. package/dist/types/preview/preview/index.d.ts +4 -4
  67. package/dist/types/preview/preview/{previewAdjustCreditAccount.d.ts → previewAdjustStrategyVerify.d.ts} +4 -4
  68. package/dist/types/preview/preview/{previewCloseOrRepayCreditAccount.d.ts → previewExitOrRepayStrategyVerify.d.ts} +4 -4
  69. package/dist/types/preview/preview/previewLpVerify.d.ts +11 -0
  70. package/dist/types/preview/preview/previewOpenStrategyVerify.d.ts +12 -0
  71. package/dist/types/preview/validate/checkOperation.d.ts +12 -4
  72. package/dist/types/preview/validate/index.d.ts +2 -2
  73. package/package.json +1 -1
  74. package/dist/types/preview/preview/previewOpenCreditAccount.d.ts +0 -12
  75. package/dist/types/preview/preview/previewPoolOperation.d.ts +0 -11
@@ -38,6 +38,7 @@ exports.STRATEGY_POSITION_CHART_METRICS = require_model_charts.STRATEGY_POSITION
38
38
  exports.STRATEGY_POSITION_COLLATERAL_ERROR = require_model_positions.STRATEGY_POSITION_COLLATERAL_ERROR;
39
39
  exports.amountSchema = require_model_primitives_schema.amountSchema;
40
40
  exports.apyBreakdownSchema = require_model_opportunities_schema.apyBreakdownSchema;
41
+ exports.asEstimated = require_model_previews.asEstimated;
41
42
  exports.assetTypeSchema = require_model_primitives_schema.assetTypeSchema;
42
43
  exports.backendPreferred = require_model_compare_schema.backendPreferred;
43
44
  exports.booleanParamSchema = require_model_filters_schema.booleanParamSchema;
@@ -33,6 +33,28 @@ const ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL = 1005;
33
33
  const ERROR_INVALID_TRANSACTION_VALUE = 1006;
34
34
  /** A token in the preview could not be priced by the oracle */
35
35
  const ERROR_UNPRICEABLE_TOKEN = 2001;
36
+ /**
37
+ * Renames a projection's routed fields, for a caller that built one from floor
38
+ * balances.
39
+ *
40
+ * Lives beside the type so the two cannot drift: a field added to
41
+ * {@link RoutedField} fails to compile until it is renamed here too.
42
+ **/
43
+ function asEstimated(p) {
44
+ const { totalValue, netValue, assets, healthFactor, safeHealthFactor, borrowRate, timeToLiquidation, liquidationPrice, leverage, ...settled } = p;
45
+ return {
46
+ ...settled,
47
+ estTotalValue: totalValue,
48
+ estNetValue: netValue,
49
+ estAssets: assets,
50
+ estHealthFactor: healthFactor,
51
+ estSafeHealthFactor: safeHealthFactor,
52
+ estBorrowRate: borrowRate,
53
+ estTimeToLiquidation: timeToLiquidation,
54
+ estLiquidationPrice: liquidationPrice,
55
+ estLeverage: leverage
56
+ };
57
+ }
36
58
  //#endregion
37
59
  exports.ERROR_ADAPTER_CALL_OUTSIDE_BRACKET = ERROR_ADAPTER_CALL_OUTSIDE_BRACKET;
38
60
  exports.ERROR_INVALID_TRANSACTION_VALUE = ERROR_INVALID_TRANSACTION_VALUE;
@@ -41,3 +63,4 @@ exports.ERROR_NON_ADAPTER_CALL_IN_BRACKET = ERROR_NON_ADAPTER_CALL_IN_BRACKET;
41
63
  exports.ERROR_UNPREVIEWABLE_ADAPTER_CALL = ERROR_UNPREVIEWABLE_ADAPTER_CALL;
42
64
  exports.ERROR_UNPRICEABLE_TOKEN = ERROR_UNPRICEABLE_TOKEN;
43
65
  exports.ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL = ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL;
66
+ exports.asEstimated = asEstimated;
@@ -1,5 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_onchain_market_math = require("../../market/math.js");
3
2
  const require_onchain_validation_refusal = require("../../validation/refusal.js");
4
3
  const require_onchain_accounts_intents_guards = require("./guards.js");
5
4
  const require_onchain_accounts_intents_math = require("./math.js");
@@ -86,34 +85,22 @@ async function previewOpenStrategy(props) {
86
85
  totalDebt: debt,
87
86
  totalValue: margin + debt
88
87
  };
89
- const projectedPool = { availableLiquidityChange: -debt };
90
- const metrics = {
91
- healthFactor: sdk.positions.healthFactor(snapshot),
92
- safeHealthFactor: sdk.positions.healthFactor(snapshot, { safePrices: true }),
93
- borrowRate: sdk.positions.borrowRate(snapshot, projectedPool),
94
- timeToLiquidation: sdk.positions.timeToLiquidation(snapshot, projectedPool),
95
- liquidationPrice: sdk.positions.liquidationPrice(snapshot)
96
- };
97
- require_onchain_accounts_intents_guards.assertCollateralised(metrics.healthFactor, false);
88
+ const { assets: _assets, quotas: _quotas, ...projection } = sdk.positions.projection(snapshot, { availableLiquidityChange: -debt });
89
+ require_onchain_accounts_intents_guards.assertCollateralised(projection.healthFactor, false);
98
90
  const priceImpact = await require_onchain_accounts_intents_utils_price_impact.collectPriceImpact(leg.probe ? [leg.probe] : [], {
99
91
  totalValue: margin + debt,
100
92
  netValue: margin,
101
93
  toUnderlying: (from, amount) => convert(from, underlying, amount)
102
94
  });
103
95
  return {
104
- creditManager,
105
- name: suite.name,
106
- totalDebt: market.toUnderlyingAmount(debt),
107
- netValue: market.toUnderlyingAmount(margin),
108
- totalValue: market.toUnderlyingAmount(margin + debt),
109
- leverage: require_onchain_market_math.calcPositionLeverage(margin + debt, debt),
96
+ ...projection,
97
+ currentPrice: sdk.positions.currentPrice(snapshot),
110
98
  priceImpact,
111
99
  averageAssets: averageAssets.map(priced),
112
100
  minAssets: minAssets.map(priced),
113
101
  averageQuota,
114
102
  minQuota,
115
- calls: [...leg.calls],
116
- ...metrics
103
+ calls: [...leg.calls]
117
104
  };
118
105
  }
119
106
  /** Collateral plus the borrowed underlying, folded into one balance per token. */
@@ -1,5 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_onchain_market_math = require("../../market/math.js");
3
2
  const require_onchain_validation_refusal = require("../../validation/refusal.js");
4
3
  const require_onchain_validation_token = require("../../validation/token.js");
5
4
  const require_onchain_accounts_intents_utils_common = require("./utils/common.js");
@@ -33,16 +32,36 @@ async function realize(steps, props) {
33
32
  const market = sdk.marketRegister.findByCreditManager(creditAccount.creditManager);
34
33
  const price = (from, to, amount) => market.priceOracle.safeConvert(from, to, amount) ?? 0n;
35
34
  const suite = sdk.marketRegister.findCreditManager(creditAccount.creditManager);
36
- const ledger = new require_onchain_accounts_intents_utils_ledger.OperationLedger({
35
+ const start = {
37
36
  initialAssets: creditAccount.tokens,
38
37
  underlying,
39
38
  debt: creditAccount.totalDebt,
40
39
  convert: price
41
- });
40
+ };
41
+ /**
42
+ * The floor: every routed leg counted at the amount it guarantees. This is
43
+ * what the calls are built from — a repayment may only spend underlying the
44
+ * route promises to have raised — and what the guards are answered on, since
45
+ * a floor that does not clear the facade's bar is a transaction that can
46
+ * revert.
47
+ */
48
+ const ledger = new require_onchain_accounts_intents_utils_ledger.OperationLedger(start);
49
+ /**
50
+ * The same walk with every routed leg counted at the amount the pathfinder
51
+ * expects to return. Nothing is built from it: it is where the position
52
+ * actually lands, so it is what the reported state is read off.
53
+ */
54
+ const expected = new require_onchain_accounts_intents_utils_ledger.OperationLedger(start);
42
55
  const operations = [];
43
- const push = (op) => {
56
+ /**
57
+ * @param asExpected - The operation as the expected branch sees it, for the
58
+ * legs where the two differ. Defaults to the operation itself, which is the
59
+ * case for everything whose amount the calldata fixes.
60
+ */
61
+ const push = (op, asExpected = op) => {
44
62
  operations.push(op);
45
63
  ledger.apply(op);
64
+ expected.apply(asExpected);
46
65
  };
47
66
  /** One per routed leg, each already awaiting its quote; folded after the guards. */
48
67
  const probes = [];
@@ -138,13 +157,17 @@ async function realize(steps, props) {
138
157
  keep: held - amount
139
158
  });
140
159
  if (leg.probe) probes.push(leg.probe);
141
- push(require_onchain_accounts_intents_operations.buildSwapOperation({
160
+ const swap = require_onchain_accounts_intents_operations.buildSwapOperation({
142
161
  tokenIn: step.from,
143
162
  amountIn: amount,
144
163
  tokenOut: step.to,
145
164
  amountOut: leg.minAmount,
146
165
  calls: leg.calls
147
- }));
166
+ });
167
+ push(swap, {
168
+ ...swap,
169
+ amountOut: leg.amount
170
+ });
148
171
  raised = leg.minAmount;
149
172
  break;
150
173
  }
@@ -155,12 +178,22 @@ async function realize(steps, props) {
155
178
  if (balances.length > 0) {
156
179
  const leg = await paths.closeAll({ balances });
157
180
  if (leg.probe) probes.push(leg.probe);
158
- if (leg.calls.length > 0 || leg.minAmount > 0n) push(require_onchain_accounts_intents_operations.buildCloseSwapOperation({
159
- from: balances,
160
- tokenOut: underlying,
161
- amountOut: leg.minAmount,
162
- calls: leg.calls
163
- }));
181
+ if (leg.calls.length > 0 || leg.minAmount > 0n) {
182
+ const sale = require_onchain_accounts_intents_operations.buildCloseSwapOperation({
183
+ from: balances,
184
+ tokenOut: underlying,
185
+ amountOut: leg.minAmount,
186
+ calls: leg.calls
187
+ });
188
+ push(sale, {
189
+ ...sale,
190
+ from: balances.map((a) => ({
191
+ token: a.token,
192
+ balance: expected.balanceOf(a.token)
193
+ })),
194
+ amountOut: leg.amount
195
+ });
196
+ }
164
197
  }
165
198
  raised = ledger.balanceOf(underlying);
166
199
  break;
@@ -226,24 +259,32 @@ async function realize(steps, props) {
226
259
  creditAccount,
227
260
  sdk
228
261
  }));
229
- for (const { token, balance } of ledger.snapshot().assets) push(require_onchain_accounts_intents_operations.buildWithdrawCollateralOperation({
230
- token,
231
- amount: balance,
232
- to: step.to,
233
- all: true,
234
- creditAccount,
235
- sdk
236
- }));
262
+ for (const { token, balance } of ledger.snapshot().assets) {
263
+ const payout = require_onchain_accounts_intents_operations.buildWithdrawCollateralOperation({
264
+ token,
265
+ amount: balance,
266
+ to: step.to,
267
+ all: true,
268
+ creditAccount,
269
+ sdk
270
+ });
271
+ push(payout, {
272
+ ...payout,
273
+ amount: expected.balanceOf(token)
274
+ });
275
+ }
237
276
  break;
238
277
  }
239
278
  }
240
- const { assets, totalValue, debt } = ledger.snapshot();
279
+ const floor = ledger.snapshot();
280
+ const { assets, debt } = floor;
281
+ const projected = expected.snapshot();
241
282
  require_onchain_accounts_intents_guards.assertGrowthAllowed({
242
283
  sdk,
243
284
  suite,
244
285
  market,
245
286
  before: creditAccount.tokens,
246
- after: assets
287
+ after: projected.assets
247
288
  });
248
289
  const quotas = cleared ?? require_onchain_accounts_intents_utils_quotas_for_update.getQuotasForUpdate({
249
290
  assetsBefore: creditAccount.tokens,
@@ -265,42 +306,29 @@ async function realize(steps, props) {
265
306
  }));
266
307
  }
267
308
  const quotasAfter = require_onchain_accounts_intents_utils_quotas_for_update.quotasAfterUpdate(creditAccount.tokens, quotas.desiredQuota);
309
+ const quoted = Object.values(quotasAfter);
268
310
  const snapshot = {
269
311
  creditManager: creditAccount.creditManager,
270
- assets,
271
- quotas: Object.values(quotasAfter),
312
+ assets: projected.assets,
313
+ quotas: quoted,
272
314
  totalDebt: debt,
273
- totalValue
274
- };
275
- const projectedPool = { availableLiquidityChange: creditAccount.totalDebt - debt };
276
- const metrics = {
277
- healthFactor: sdk.positions.healthFactor(snapshot),
278
- safeHealthFactor: paysOut ? sdk.positions.healthFactor(snapshot, { safePrices: true }) : void 0,
279
- borrowRate: sdk.positions.borrowRate(snapshot, projectedPool),
280
- timeToLiquidation: sdk.positions.timeToLiquidation(snapshot, projectedPool),
281
- liquidationPrice: sdk.positions.liquidationPrice(snapshot)
315
+ totalValue: projected.totalValue
282
316
  };
283
- require_onchain_accounts_intents_guards.assertCollateralised(paysOut ? sdk.positions.healthFactor(snapshot, { safePrices: true }) : metrics.healthFactor, paysOut);
317
+ const projection = sdk.positions.projection(snapshot, { availableLiquidityChange: creditAccount.totalDebt - debt });
318
+ require_onchain_accounts_intents_guards.assertCollateralised(sdk.positions.healthFactor({
319
+ ...snapshot,
320
+ assets,
321
+ totalValue: floor.totalValue
322
+ }, { safePrices: paysOut }), paysOut);
284
323
  const priceImpact = await require_onchain_accounts_intents_utils_price_impact.collectPriceImpact(probes, {
285
- totalValue,
286
- netValue: totalValue - debt,
324
+ totalValue: projected.totalValue,
325
+ netValue: projected.totalValue - debt,
287
326
  toUnderlying: (from, amount) => price(from, underlying, amount)
288
327
  });
289
- const oracle = market.priceOracle;
290
328
  const state = {
291
- creditManager: creditAccount.creditManager,
292
- name: suite.name,
293
- totalValue: market.toUnderlyingAmount(totalValue),
294
- totalDebt: market.toUnderlyingAmount(debt),
295
- netValue: market.toUnderlyingAmount(totalValue - debt),
296
- leverage: require_onchain_market_math.calcPositionLeverage(totalValue, debt),
297
- assets: assets.map((a) => oracle.toTokenAmount(a.token, a.balance)),
298
- quotas: Object.values(quotasAfter).map((q) => ({
299
- token: sdk.tokensMeta.mustGetToken(q.token),
300
- ...oracle.toAmount(underlying, q.balance)
301
- })),
329
+ ...projection,
302
330
  priceImpact,
303
- ...metrics
331
+ currentPrice: sdk.positions.currentPrice(snapshot)
304
332
  };
305
333
  return {
306
334
  operations,
@@ -96,6 +96,7 @@ function buildMarketSdk(extras) {
96
96
  creditFacade: CREDIT_FACADE,
97
97
  underlying: UND,
98
98
  routeQuote: extras?.routeQuote,
99
+ routeFloor: extras?.routeFloor,
99
100
  rwaAssets: extras?.rwaAssets,
100
101
  phantoms: extras?.phantoms,
101
102
  creditAccounts: extras?.creditAccounts,
@@ -13,6 +13,17 @@ let vitest = require("vitest");
13
13
  * from their inputs, so `result.calls` pins down which ops reached the
14
14
  * assembler and in which order.
15
15
  */
16
+ /** Market configurator the mock market is governed by — the curator's address. */
17
+ const MOCK_MARKET_CONFIGURATOR = "0x00000000000000000000000000000000000c0f16";
18
+ /**
19
+ * Liquidation fees of the mock suite: a 3% premium (the manager reports its
20
+ * complement) on top of a 1.5% protocol fee, so the discount a screen shows is
21
+ * 450bps.
22
+ */
23
+ const MOCK_LIQUIDATION_FEES = {
24
+ feeLiquidation: 150,
25
+ liquidationDiscount: 9700
26
+ };
16
27
  /** Recognizable router call embedded in routed leg results. */
17
28
  const MOCK_ROUTER_CALL = {
18
29
  target: "0x9999999999999999999999999999999999999999",
@@ -155,6 +166,8 @@ function buildMockSdk(args) {
155
166
  };
156
167
  const market = {
157
168
  toUnderlyingAmount,
169
+ /** {@inheritDoc MarketSuite.underlying} */
170
+ underlying: args.underlying,
158
171
  priceOracle: {
159
172
  convert,
160
173
  safeConvert,
@@ -204,6 +217,8 @@ function buildMockSdk(args) {
204
217
  const expirationDate = args.expirationDate ?? 0;
205
218
  const creditManagerSuite = {
206
219
  name: "TestCreditManager",
220
+ marketConfigurator: { address: MOCK_MARKET_CONFIGURATOR },
221
+ liquidationFees: () => MOCK_LIQUIDATION_FEES,
207
222
  creditManager: {
208
223
  address: args.creditManager,
209
224
  liquidationThresholds,
@@ -238,10 +253,12 @@ function buildMockSdk(args) {
238
253
  };
239
254
  /** Linear unless the case says otherwise — see `routeQuote`. */
240
255
  const quote = args.routeQuote ?? ((amount) => amount);
256
+ /** Slippage-free unless the case says otherwise — see `routeFloor`. */
257
+ const floor = args.routeFloor ?? ((amount) => amount);
241
258
  const router = {
242
259
  findOneTokenPath: vitest.vi.fn(async ({ amount, tokenIn, tokenOut }) => ({
243
260
  amount: quote(amount),
244
- minAmount: quote(amount),
261
+ minAmount: floor(quote(amount)),
245
262
  calls: routeCalls(tokenIn, tokenOut)
246
263
  })),
247
264
  findManyToOnePath: vitest.vi.fn(async ({ expectedBalances, leftoverBalances, target }) => {
@@ -249,7 +266,7 @@ function buildMockSdk(args) {
249
266
  const tokenIn = expectedBalances[0]?.token ?? target;
250
267
  return {
251
268
  amount: quote(spent),
252
- minAmount: quote(spent),
269
+ minAmount: floor(quote(spent)),
253
270
  calls: routeCalls(tokenIn, target)
254
271
  };
255
272
  }),
@@ -270,11 +287,15 @@ function buildMockSdk(args) {
270
287
  amount += convert(token, targetLc, spend);
271
288
  }
272
289
  balances[targetLc] = (balances[targetLc] ?? 0n) + amount;
290
+ const untouched = (balances[targetLc] ?? 0n) - amount;
273
291
  return {
274
292
  amount,
275
- minAmount: amount,
293
+ minAmount: floor(amount),
276
294
  balances,
277
- minBalances: { ...balances },
295
+ minBalances: {
296
+ ...balances,
297
+ [targetLc]: untouched + floor(amount)
298
+ },
278
299
  calls: [MOCK_ROUTER_CALL]
279
300
  };
280
301
  }),
@@ -284,7 +305,7 @@ function buildMockSdk(args) {
284
305
  const amount = sold.reduce((acc, a) => acc + convert(a.token, underlying, a.balance), 0n);
285
306
  return {
286
307
  amount,
287
- minAmount: amount,
308
+ minAmount: floor(amount),
288
309
  underlyingBalance: amount,
289
310
  calls: sold.length === 0 ? [] : [MOCK_CLOSE_CALL]
290
311
  };
@@ -383,6 +404,8 @@ function payloadOf(slice) {
383
404
  exports.CA_OP_CALLS = CA_OP_CALLS;
384
405
  exports.MOCK_CLAIM_CALL = MOCK_CLAIM_CALL;
385
406
  exports.MOCK_CLOSE_CALL = MOCK_CLOSE_CALL;
407
+ exports.MOCK_LIQUIDATION_FEES = MOCK_LIQUIDATION_FEES;
408
+ exports.MOCK_MARKET_CONFIGURATOR = MOCK_MARKET_CONFIGURATOR;
386
409
  exports.MOCK_REQUEST_CALL = MOCK_REQUEST_CALL;
387
410
  exports.MOCK_ROUTER_CALL = MOCK_ROUTER_CALL;
388
411
  exports.MOCK_RWA_UNWRAP_CALL = MOCK_RWA_UNWRAP_CALL;
@@ -139,6 +139,7 @@ const require_onchain_market_credit_CreditManagerV310Contract = require("./marke
139
139
  const require_onchain_market_strategyName = require("./market/strategyName.js");
140
140
  const require_onchain_market_credit_collateralUtils = require("./market/credit/collateralUtils.js");
141
141
  const require_onchain_market_credit_CreditSuite = require("./market/credit/CreditSuite.js");
142
+ const require_onchain_market_credit_creditOperationMarket = require("./market/credit/creditOperationMarket.js");
142
143
  const require_onchain_market_credit_expectedBalanceDeltas = require("./market/credit/expectedBalanceDeltas.js");
143
144
  const require_onchain_utils_viem_simulateMulticall = require("./utils/viem/simulateMulticall.js");
144
145
  const require_onchain_utils_viem_simulateWithPriceUpdates = require("./utils/viem/simulateWithPriceUpdates.js");
@@ -146,6 +147,7 @@ const require_onchain_utils_viem_executeDelegatedMulticalls = require("./utils/v
146
147
  const require_onchain_utils_viem_sendRawTx = require("./utils/viem/sendRawTx.js");
147
148
  const require_onchain_utils_viem_watchBlocksAsync = require("./utils/viem/watchBlocksAsync.js");
148
149
  require("./utils/viem/index.js");
150
+ const require_onchain_market_oracle_collateralPriceInUnderlying = require("./market/oracle/collateralPriceInUnderlying.js");
149
151
  const require_onchain_market_pricefeeds_isUpdatablePriceFeed = require("./market/pricefeeds/isUpdatablePriceFeed.js");
150
152
  const require_onchain_market_pricefeeds_PriceFeedRef = require("./market/pricefeeds/PriceFeedRef.js");
151
153
  const require_onchain_market_pricefeeds_AbstractPriceFeed = require("./market/pricefeeds/AbstractPriceFeed.js");
@@ -519,6 +521,7 @@ exports.checkQuotaCount = require_onchain_validation_checks.checkQuotaCount;
519
521
  exports.checkQuotaLimit = require_onchain_validation_checks.checkQuotaLimit;
520
522
  exports.childLogger = require_onchain_utils_childLogger.childLogger;
521
523
  exports.classifyCurveOperation = require_onchain_market_adapters_transferHelpers.classifyCurveOperation;
524
+ exports.collateralPriceInUnderlying = require_onchain_market_oracle_collateralPriceInUnderlying.collateralPriceInUnderlying;
522
525
  exports.collectTraces = require_onchain_utils_trace.collectTraces;
523
526
  exports.createAdapter = require_onchain_market_adapters_createAdapter.createAdapter;
524
527
  exports.createAddressProvider = require_onchain_core_createAddressProvider.createAddressProvider;
@@ -529,6 +532,7 @@ exports.createRouter = require_onchain_router_createRouter.createRouter;
529
532
  exports.createWithdrawalCompressor = require_onchain_accounts_withdrawal_compressor_createWithdrawalCompressor.createWithdrawalCompressor;
530
533
  exports.createZapper = require_onchain_market_zapper_createZapper.createZapper;
531
534
  exports.creditFacadeV310Abi = require_onchain_market_credit_CreditFacadeV310BaseContract.creditFacadeV310Abi;
535
+ exports.creditOperationMarket = require_onchain_market_credit_creditOperationMarket.creditOperationMarket;
532
536
  exports.curveAddLiquidityFromTransfers = require_onchain_market_adapters_transferHelpers.curveAddLiquidityFromTransfers;
533
537
  exports.curveRemoveLiquidityFromTransfers = require_onchain_market_adapters_transferHelpers.curveRemoveLiquidityFromTransfers;
534
538
  exports.decodeDelayedIntent = require_onchain_accounts_withdrawal_compressor_intent_codec.decodeDelayedIntent;
@@ -695,6 +699,7 @@ exports.shortHash = require_onchain_utils_formatter.shortHash;
695
699
  exports.simulateCall = require_onchain_utils_viem_simulateCall.simulateCall;
696
700
  exports.simulateMulticall = require_onchain_utils_viem_simulateMulticall.simulateMulticall;
697
701
  exports.simulateWithPriceUpdates = require_onchain_utils_viem_simulateWithPriceUpdates.simulateWithPriceUpdates;
702
+ exports.soleNonUnderlyingCollateral = require_onchain_positions_calcLiquidationPrice.soleNonUnderlyingCollateral;
698
703
  exports.strategyName = require_onchain_market_strategyName.strategyName;
699
704
  exports.swapFromTransfers = require_onchain_market_adapters_transferHelpers.swapFromTransfers;
700
705
  exports.toAddress = require_onchain_utils_toAddress.toAddress;
@@ -712,5 +717,6 @@ exports.toSignificant = require_onchain_utils_formatter.toSignificant;
712
717
  exports.toToken = require_onchain_validation_token.toToken;
713
718
  exports.toTokenAmount = require_onchain_validation_token.toTokenAmount;
714
719
  exports.toWithdrawalStatus = require_onchain_accounts_withdrawal_compressor_types.toWithdrawalStatus;
720
+ exports.totalLiquidationDiscount = require_onchain_market_credit_creditOperationMarket.totalLiquidationDiscount;
715
721
  exports.usdToNumber = require_onchain_market_math.usdToNumber;
716
722
  exports.watchBlocksAsync = require_onchain_utils_viem_watchBlocksAsync.watchBlocksAsync;
@@ -0,0 +1,32 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_onchain_constants_math = require("../../constants/math.js");
3
+ //#region src/onchain/market/credit/creditOperationMarket.ts
4
+ /**
5
+ * What a liquidation takes off an account, in basis points: the premium the
6
+ * liquidator keeps plus the protocol's own fee, with the suite's expiration
7
+ * already resolved.
8
+ *
9
+ * Not {@link LiquidationFees.liquidationDiscount}, which is the complement of
10
+ * the premium alone (`100% - liquidationPremium`) and says what share of the
11
+ * seized collateral repays the debt.
12
+ **/
13
+ function totalLiquidationDiscount(suite) {
14
+ const { feeLiquidation, liquidationDiscount } = suite.liquidationFees();
15
+ return Number(require_onchain_constants_math.PERCENTAGE_FACTOR) - liquidationDiscount + feeLiquidation;
16
+ }
17
+ /**
18
+ * The market half of every credit operation result, read off the suite that
19
+ * serves it. Spread into a preview or a projection so the four fields are
20
+ * filled in one place and cannot drift apart between the two halves of the SDK.
21
+ **/
22
+ function creditOperationMarket(suite) {
23
+ return {
24
+ creditManager: suite.creditManager.address,
25
+ name: suite.name,
26
+ curator: suite.marketConfigurator.address,
27
+ liquidationDiscount: totalLiquidationDiscount(suite)
28
+ };
29
+ }
30
+ //#endregion
31
+ exports.creditOperationMarket = creditOperationMarket;
32
+ exports.totalLiquidationDiscount = totalLiquidationDiscount;
@@ -5,6 +5,7 @@ const require_onchain_market_credit_CreditFacadeV310Contract = require("./Credit
5
5
  const require_onchain_market_credit_CreditManagerV310Contract = require("./CreditManagerV310Contract.js");
6
6
  const require_onchain_market_credit_collateralUtils = require("./collateralUtils.js");
7
7
  const require_onchain_market_credit_CreditSuite = require("./CreditSuite.js");
8
+ const require_onchain_market_credit_creditOperationMarket = require("./creditOperationMarket.js");
8
9
  const require_onchain_market_credit_expectedBalanceDeltas = require("./expectedBalanceDeltas.js");
9
10
  require("./types.js");
10
11
  exports.CreditConfiguratorV310Contract = require_onchain_market_credit_CreditConfiguratorV310Contract.CreditConfiguratorV310Contract;
@@ -13,7 +14,9 @@ exports.CreditFacadeV310Contract = require_onchain_market_credit_CreditFacadeV31
13
14
  exports.CreditManagerV310Contract = require_onchain_market_credit_CreditManagerV310Contract.CreditManagerV310Contract;
14
15
  exports.CreditSuite = require_onchain_market_credit_CreditSuite.CreditSuite;
15
16
  exports.creditFacadeV310Abi = require_onchain_market_credit_CreditFacadeV310BaseContract.creditFacadeV310Abi;
17
+ exports.creditOperationMarket = require_onchain_market_credit_creditOperationMarket.creditOperationMarket;
16
18
  exports.dominantCollateral = require_onchain_market_credit_collateralUtils.dominantCollateral;
17
19
  exports.expectedBalanceDeltas = require_onchain_market_credit_expectedBalanceDeltas.expectedBalanceDeltas;
18
20
  exports.isStrategyCollateral = require_onchain_market_credit_collateralUtils.isStrategyCollateral;
19
21
  exports.pickStrategyTargetCollateral = require_onchain_market_credit_collateralUtils.pickStrategyTargetCollateral;
22
+ exports.totalLiquidationDiscount = require_onchain_market_credit_creditOperationMarket.totalLiquidationDiscount;
@@ -93,8 +93,10 @@ const require_onchain_market_credit_CreditManagerV310Contract = require("./credi
93
93
  const require_onchain_market_strategyName = require("./strategyName.js");
94
94
  const require_onchain_market_credit_collateralUtils = require("./credit/collateralUtils.js");
95
95
  const require_onchain_market_credit_CreditSuite = require("./credit/CreditSuite.js");
96
+ const require_onchain_market_credit_creditOperationMarket = require("./credit/creditOperationMarket.js");
96
97
  const require_onchain_market_credit_expectedBalanceDeltas = require("./credit/expectedBalanceDeltas.js");
97
98
  require("./credit/index.js");
99
+ const require_onchain_market_oracle_collateralPriceInUnderlying = require("./oracle/collateralPriceInUnderlying.js");
98
100
  const require_onchain_market_pricefeeds_isUpdatablePriceFeed = require("./pricefeeds/isUpdatablePriceFeed.js");
99
101
  const require_onchain_market_pricefeeds_PriceFeedRef = require("./pricefeeds/PriceFeedRef.js");
100
102
  const require_onchain_market_pricefeeds_AbstractPriceFeed = require("./pricefeeds/AbstractPriceFeed.js");
@@ -255,10 +257,12 @@ exports.calcQuotaRate = require_onchain_market_math.calcQuotaRate;
255
257
  exports.calcUtilization = require_onchain_market_math.calcUtilization;
256
258
  exports.calcUtilizationRaw = require_onchain_market_math.calcUtilizationRaw;
257
259
  exports.classifyCurveOperation = require_onchain_market_adapters_transferHelpers.classifyCurveOperation;
260
+ exports.collateralPriceInUnderlying = require_onchain_market_oracle_collateralPriceInUnderlying.collateralPriceInUnderlying;
258
261
  exports.createAdapter = require_onchain_market_adapters_createAdapter.createAdapter;
259
262
  exports.createPriceOracle = require_onchain_market_oracle_createPriceOracle.createPriceOracle;
260
263
  exports.createZapper = require_onchain_market_zapper_createZapper.createZapper;
261
264
  exports.creditFacadeV310Abi = require_onchain_market_credit_CreditFacadeV310BaseContract.creditFacadeV310Abi;
265
+ exports.creditOperationMarket = require_onchain_market_credit_creditOperationMarket.creditOperationMarket;
262
266
  exports.curveAddLiquidityFromTransfers = require_onchain_market_adapters_transferHelpers.curveAddLiquidityFromTransfers;
263
267
  exports.curveRemoveLiquidityFromTransfers = require_onchain_market_adapters_transferHelpers.curveRemoveLiquidityFromTransfers;
264
268
  exports.dominantCollateral = require_onchain_market_credit_collateralUtils.dominantCollateral;
@@ -360,4 +364,5 @@ exports.rewardsFromTransfers = require_onchain_market_adapters_transferHelpers.r
360
364
  exports.strategyName = require_onchain_market_strategyName.strategyName;
361
365
  exports.swapFromTransfers = require_onchain_market_adapters_transferHelpers.swapFromTransfers;
362
366
  exports.toNetTransfers = require_onchain_market_adapters_transferHelpers.toNetTransfers;
367
+ exports.totalLiquidationDiscount = require_onchain_market_credit_creditOperationMarket.totalLiquidationDiscount;
363
368
  exports.usdToNumber = require_onchain_market_math.usdToNumber;
@@ -0,0 +1,27 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_onchain_constants_math = require("../../constants/math.js");
3
+ //#region src/onchain/market/oracle/collateralPriceInUnderlying.ts
4
+ /**
5
+ * What one unit of `collateral` costs in `underlying` right now, in the
6
+ * oracle's 8-decimal (`PRICE_DECIMALS`) fixed point — the scale and the
7
+ * denomination `calcLiquidationPrice` answers in, so the two figures are read
8
+ * as a pair.
9
+ *
10
+ * Both sides come from the oracle's **main** feeds: this is the price the
11
+ * market quotes, not the conservative one a hand-over is weighed at.
12
+ *
13
+ * `null` when the oracle cannot answer for either token, or prices the
14
+ * underlying at zero — a screen shows a gap rather than a number derived from
15
+ * a missing feed.
16
+ **/
17
+ function collateralPriceInUnderlying(oracle, collateral, underlying) {
18
+ try {
19
+ const underlyingPrice = oracle.mainPrice(underlying);
20
+ if (underlyingPrice <= 0n) return null;
21
+ return oracle.mainPrice(collateral) * require_onchain_constants_math.PRICE_DECIMALS / underlyingPrice;
22
+ } catch {
23
+ return null;
24
+ }
25
+ }
26
+ //#endregion
27
+ exports.collateralPriceInUnderlying = collateralPriceInUnderlying;
@@ -1,6 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_onchain_market_oracle_collateralPriceInUnderlying = require("./collateralPriceInUnderlying.js");
2
3
  const require_onchain_market_oracle_PriceOracleV310Contract = require("./PriceOracleV310Contract.js");
3
4
  const require_onchain_market_oracle_createPriceOracle = require("./createPriceOracle.js");
4
5
  require("./types.js");
5
6
  exports.PriceOracleV310Contract = require_onchain_market_oracle_PriceOracleV310Contract.PriceOracleV310Contract;
7
+ exports.collateralPriceInUnderlying = require_onchain_market_oracle_collateralPriceInUnderlying.collateralPriceInUnderlying;
6
8
  exports.createPriceOracle = require_onchain_market_oracle_createPriceOracle.createPriceOracle;