@gearbox-protocol/sdk 16.0.0-next.12 → 16.0.0-next.14

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 (51) hide show
  1. package/dist/cjs/model/charts.js +5 -1
  2. package/dist/cjs/model/index.js +3 -1
  3. package/dist/cjs/model/opportunities.schema.js +9 -0
  4. package/dist/cjs/model/positions.js +6 -0
  5. package/dist/cjs/model/positions.schema.js +2 -1
  6. package/dist/cjs/model/previews.js +4 -3
  7. package/dist/cjs/offchain/opportunities/OffchainOpportunities.js +9 -0
  8. package/dist/cjs/offchain/positions/OffchainPositions.js +9 -0
  9. package/dist/cjs/onchain/market/adapters/contracts/AbstractAdapter.js +14 -0
  10. package/dist/cjs/onchain/market/adapters/contracts/ERC4626AdapterContract.js +54 -0
  11. package/dist/cjs/onchain/market/adapters/contracts/MidasGatewayAdapterContract.js +13 -0
  12. package/dist/cjs/onchain/positions/PositionsService.js +20 -17
  13. package/dist/cjs/preview/preview/replayInnerOperations.js +10 -25
  14. package/dist/cjs/sdk/opportunities/OpportunitiesNamespace.js +6 -0
  15. package/dist/cjs/sdk/positions/PositionsNamespace.js +6 -0
  16. package/dist/esm/model/charts.js +5 -1
  17. package/dist/esm/model/index.js +4 -4
  18. package/dist/esm/model/opportunities.schema.js +9 -1
  19. package/dist/esm/model/positions.js +6 -1
  20. package/dist/esm/model/positions.schema.js +2 -1
  21. package/dist/esm/model/previews.js +4 -3
  22. package/dist/esm/offchain/opportunities/OffchainOpportunities.js +10 -1
  23. package/dist/esm/offchain/positions/OffchainPositions.js +10 -1
  24. package/dist/esm/onchain/market/adapters/contracts/AbstractAdapter.js +14 -0
  25. package/dist/esm/onchain/market/adapters/contracts/ERC4626AdapterContract.js +55 -1
  26. package/dist/esm/onchain/market/adapters/contracts/MidasGatewayAdapterContract.js +14 -1
  27. package/dist/esm/onchain/positions/PositionsService.js +21 -18
  28. package/dist/esm/preview/preview/replayInnerOperations.js +11 -26
  29. package/dist/esm/sdk/opportunities/OpportunitiesNamespace.js +6 -0
  30. package/dist/esm/sdk/positions/PositionsNamespace.js +6 -0
  31. package/dist/types/model/charts.d.ts +4 -2
  32. package/dist/types/model/charts.schema.d.ts +8 -0
  33. package/dist/types/model/index.d.ts +5 -5
  34. package/dist/types/model/opportunities.d.ts +19 -1
  35. package/dist/types/model/opportunities.schema.d.ts +9 -1
  36. package/dist/types/model/positions.d.ts +13 -1
  37. package/dist/types/model/positions.schema.d.ts +2 -0
  38. package/dist/types/model/previews.d.ts +4 -3
  39. package/dist/types/offchain/opportunities/OffchainOpportunities.d.ts +5 -1
  40. package/dist/types/offchain/positions/OffchainPositions.d.ts +6 -1
  41. package/dist/types/onchain/market/adapters/contracts/AbstractAdapter.d.ts +12 -0
  42. package/dist/types/onchain/market/adapters/contracts/ERC4626AdapterContract.d.ts +8 -1
  43. package/dist/types/onchain/market/adapters/contracts/MidasGatewayAdapterContract.d.ts +7 -0
  44. package/dist/types/sdk/opportunities/OpportunitiesNamespace.d.ts +5 -1
  45. package/dist/types/sdk/opportunities/types.d.ts +9 -1
  46. package/dist/types/sdk/positions/PositionsNamespace.d.ts +5 -1
  47. package/dist/types/sdk/positions/types.d.ts +9 -1
  48. package/package.json +1 -1
  49. package/dist/cjs/preview/preview/applyRWAWrapUnwrap.js +0 -67
  50. package/dist/esm/preview/preview/applyRWAWrapUnwrap.js +0 -66
  51. package/dist/types/preview/preview/applyRWAWrapUnwrap.d.ts +0 -17
@@ -32,7 +32,8 @@ const POOL_OPPORTUNITY_CHART_METRICS = [
32
32
  "depositApyAvg7d",
33
33
  "dieselRate",
34
34
  "supplied",
35
- "borrowed"
35
+ "borrowed",
36
+ "utilization"
36
37
  ];
37
38
  /**
38
39
  * Every metric a strategy opportunity can chart.
@@ -62,6 +63,7 @@ const STRATEGY_OPPORTUNITY_CHART_METRICS = [
62
63
  **/
63
64
  const POOL_POSITION_CHART_METRICS = [
64
65
  "apy",
66
+ "apyAvg7d",
65
67
  "pnl",
66
68
  "mwr"
67
69
  ];
@@ -100,11 +102,13 @@ const CHART_METRIC_UNITS = {
100
102
  supplied: "token",
101
103
  borrowed: "token",
102
104
  tvl: "token",
105
+ utilization: "bps",
103
106
  dieselRate: "ratio",
104
107
  collateralPrice: "ratio",
105
108
  collateralUsdPrice: "usd",
106
109
  underlyingUsdPrice: "usd",
107
110
  apy: "bps",
111
+ apyAvg7d: "bps",
108
112
  pnl: "token",
109
113
  mwr: "bps",
110
114
  totalValueUnderlying: "token",
@@ -28,13 +28,14 @@ exports.ERROR_INVALID_TRANSACTION_VALUE = require_model_previews.ERROR_INVALID_T
28
28
  exports.ERROR_MALFORMED_BRACKET = require_model_previews.ERROR_MALFORMED_BRACKET;
29
29
  exports.ERROR_NON_ADAPTER_CALL_IN_BRACKET = require_model_previews.ERROR_NON_ADAPTER_CALL_IN_BRACKET;
30
30
  exports.ERROR_UNPREVIEWABLE_ADAPTER_CALL = require_model_previews.ERROR_UNPREVIEWABLE_ADAPTER_CALL;
31
- exports.ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP = require_model_previews.ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP;
32
31
  exports.ERROR_UNPRICEABLE_TOKEN = require_model_previews.ERROR_UNPRICEABLE_TOKEN;
32
+ exports.ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL = require_model_previews.ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL;
33
33
  exports.FILTER_ALL = require_model_filters.FILTER_ALL;
34
34
  exports.POOL_OPPORTUNITY_CHART_METRICS = require_model_charts.POOL_OPPORTUNITY_CHART_METRICS;
35
35
  exports.POOL_POSITION_CHART_METRICS = require_model_charts.POOL_POSITION_CHART_METRICS;
36
36
  exports.STRATEGY_OPPORTUNITY_CHART_METRICS = require_model_charts.STRATEGY_OPPORTUNITY_CHART_METRICS;
37
37
  exports.STRATEGY_POSITION_CHART_METRICS = require_model_charts.STRATEGY_POSITION_CHART_METRICS;
38
+ exports.STRATEGY_POSITION_COLLATERAL_ERROR = require_model_positions.STRATEGY_POSITION_COLLATERAL_ERROR;
38
39
  exports.amountSchema = require_model_primitives_schema.amountSchema;
39
40
  exports.apyBreakdownSchema = require_model_opportunities_schema.apyBreakdownSchema;
40
41
  exports.assetTypeSchema = require_model_primitives_schema.assetTypeSchema;
@@ -89,6 +90,7 @@ exports.opportunityId = require_model_opportunities.opportunityId;
89
90
  exports.opportunityKeySchema = require_model_opportunities_schema.opportunityKeySchema;
90
91
  exports.opportunityKindSchema = require_model_opportunities_schema.opportunityKindSchema;
91
92
  exports.opportunitySchema = require_model_opportunities_schema.opportunitySchema;
93
+ exports.opportunityTotalsSchema = require_model_opportunities_schema.opportunityTotalsSchema;
92
94
  exports.pnlBreakdownSchema = require_model_positions_schema.pnlBreakdownSchema;
93
95
  exports.pointRewardsSchema = require_model_opportunities_schema.pointRewardsSchema;
94
96
  exports.pointsProgramPnLSchema = require_model_positions_schema.pointsProgramPnLSchema;
@@ -245,6 +245,14 @@ const opportunityKeySchema = zod_v4.z.discriminatedUnion("kind", [zod_v4.z.objec
245
245
  kind: zod_v4.z.literal("strategy"),
246
246
  ...strategyOpportunityKeySchema.shape
247
247
  })]);
248
+ /**
249
+ * {@link OpportunityTotals}
250
+ **/
251
+ const opportunityTotalsSchema = zod_v4.z.object({
252
+ tvl: zod_v4.z.number(),
253
+ totalBorrowed: zod_v4.z.number(),
254
+ totalSupply: zod_v4.z.number()
255
+ });
248
256
  //#endregion
249
257
  exports.apyBreakdownSchema = apyBreakdownSchema;
250
258
  exports.opportunityBaseSchema = opportunityBaseSchema;
@@ -255,6 +263,7 @@ exports.opportunityFilterSchema = opportunityFilterSchema;
255
263
  exports.opportunityKeySchema = opportunityKeySchema;
256
264
  exports.opportunityKindSchema = opportunityKindSchema;
257
265
  exports.opportunitySchema = opportunitySchema;
266
+ exports.opportunityTotalsSchema = opportunityTotalsSchema;
258
267
  exports.pointRewardsSchema = pointRewardsSchema;
259
268
  exports.pointsProgramSchema = pointsProgramSchema;
260
269
  exports.poolOpportunityDetailSchema = poolOpportunityDetailSchema;
@@ -2,6 +2,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_model_filters = require("./filters.js");
3
3
  //#region src/model/positions.ts
4
4
  /**
5
+ * Set on {@link StrategyPosition.error} when the account could not be fully
6
+ * valued (e.g. a dead price feed).
7
+ **/
8
+ const STRATEGY_POSITION_COLLATERAL_ERROR = "collateral computation failed";
9
+ /**
5
10
  * Builds the canonical id of a pool position.
6
11
  *
7
12
  * @example
@@ -85,6 +90,7 @@ function positionUnderlying(position) {
85
90
  }
86
91
  }
87
92
  //#endregion
93
+ exports.STRATEGY_POSITION_COLLATERAL_ERROR = STRATEGY_POSITION_COLLATERAL_ERROR;
88
94
  exports.liquidationPositionId = liquidationPositionId;
89
95
  exports.matchesPositionFilter = matchesPositionFilter;
90
96
  exports.poolPositionId = poolPositionId;
@@ -115,7 +115,8 @@ const strategyPositionSchema = zod_v4.z.object({
115
115
  timeToLiquidation: require_model_compare_schema.onchainOnly(require_onchain_utils_zod.ZodBigInt().nullable()).optional(),
116
116
  liquidationPrice: require_model_compare_schema.onchainOnly(require_onchain_utils_zod.ZodBigInt().nullable()).optional(),
117
117
  pnl: require_model_compare_schema.offchainOnly(pnlBreakdownSchema).optional(),
118
- collaterals: zod_v4.z.array(positionCollateralSchema)
118
+ collaterals: zod_v4.z.array(positionCollateralSchema),
119
+ error: zod_v4.z.string().optional()
119
120
  });
120
121
  /**
121
122
  * {@link Position}
@@ -21,9 +21,10 @@ const ERROR_NON_ADAPTER_CALL_IN_BRACKET = 1003;
21
21
  **/
22
22
  const ERROR_UNPREVIEWABLE_ADAPTER_CALL = 1004;
23
23
  /**
24
- * Out-of-bracket RWA wrap/unwrap calldata cannot be decoded
24
+ * An out-of-bracket adapter call that is allowed there (e.g. RWA wrap/unwrap)
25
+ * could not be decoded or replayed
25
26
  **/
26
- const ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP = 1005;
27
+ const ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL = 1005;
27
28
  /**
28
29
  * `msg.value` does not fit into the declared WETH collateral
29
30
  * Transactions can have arbitrary value, but the ones that we create
@@ -38,5 +39,5 @@ exports.ERROR_INVALID_TRANSACTION_VALUE = ERROR_INVALID_TRANSACTION_VALUE;
38
39
  exports.ERROR_MALFORMED_BRACKET = ERROR_MALFORMED_BRACKET;
39
40
  exports.ERROR_NON_ADAPTER_CALL_IN_BRACKET = ERROR_NON_ADAPTER_CALL_IN_BRACKET;
40
41
  exports.ERROR_UNPREVIEWABLE_ADAPTER_CALL = ERROR_UNPREVIEWABLE_ADAPTER_CALL;
41
- exports.ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP = ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP;
42
42
  exports.ERROR_UNPRICEABLE_TOKEN = ERROR_UNPRICEABLE_TOKEN;
43
+ exports.ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL = ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL;
@@ -44,6 +44,15 @@ var OffchainOpportunities = class extends require_offchain_AbstractOffchainNames
44
44
  });
45
45
  }
46
46
  /**
47
+ * Protocol-wide totals across every opportunity the backend serves.
48
+ **/
49
+ async getTotals() {
50
+ return this.get({
51
+ path: `${this.#root}/totals`,
52
+ schema: require_model_opportunities_schema.opportunityTotalsSchema
53
+ });
54
+ }
55
+ /**
47
56
  * Charts of one opportunity: one series per metric, on a shared grid.
48
57
  **/
49
58
  async getCharts(key, metrics, range) {
@@ -25,6 +25,15 @@ var OffchainPositions = class extends require_offchain_AbstractOffchainNamespace
25
25
  });
26
26
  }
27
27
  /**
28
+ * Aggregate over everything a wallet holds, see {@link PositionsTotals}.
29
+ **/
30
+ async getTotals(wallet) {
31
+ return this.get({
32
+ path: `${this.#root}/${wallet}/totals`,
33
+ schema: require_model_positions_schema.positionsTotalsSchema
34
+ });
35
+ }
36
+ /**
28
37
  * Charts of one position: one series per metric, on a shared grid.
29
38
  **/
30
39
  async getCharts(key, metrics, range) {
@@ -115,6 +115,20 @@ var AbstractAdapterContract = class extends require_onchain_base_BaseContract.Ba
115
115
  await this.applyBalanceChanges(balances, decoded);
116
116
  }
117
117
  /**
118
+ * Replays this adapter call when it appears outside a
119
+ * storeExpectedBalances/compareBalances bracket, mutating `balances` in
120
+ * place, and returns `true` when the call is legal there.
121
+ *
122
+ * Base implementation returns `false`: nothing enforces the outcome of an
123
+ * out-of-bracket adapter call on-chain, so it cannot be previewed.
124
+ *
125
+ * @throws when the call is allowed outside a bracket but its calldata
126
+ * cannot be decoded
127
+ */
128
+ replayOutOfBracketCall(_balances, _calldata) {
129
+ return false;
130
+ }
131
+ /**
118
132
  * Applies the balance changes of a decoded adapter call to the running
119
133
  * balances, mutating them in place. Overrides should express changes via
120
134
  * {@link setLeftover} (diff-style calls) and {@link spendExact}
@@ -98,6 +98,60 @@ var ERC4626AdapterContract = class extends require_onchain_market_adapters_contr
98
98
  };
99
99
  return super.classifyLegacyOperation(parsed, transfers);
100
100
  }
101
+ /**
102
+ * Out-of-bracket calls are legal only on the RWA wrap/unwrap adapter (the
103
+ * share converts 1:1 with the vault asset, so no on-chain preview or
104
+ * slippage bracket is needed); a regular vault-strategy ERC4626 adapter
105
+ * keeps the base behavior and returns false.
106
+ */
107
+ replayOutOfBracketCall(balances, calldata) {
108
+ const meta = this.sdk.tokensMeta.get(this.share);
109
+ if (!meta || !this.sdk.tokensMeta.isRWAUnderlying(meta)) return false;
110
+ const resolved = this.#resolveWrapUnwrap(calldata, balances);
111
+ if (resolved && resolved.amountIn > 0n) {
112
+ balances.dec(resolved.tokenIn, resolved.amountIn);
113
+ balances.inc(resolved.tokenOut, resolved.amountIn);
114
+ }
115
+ return true;
116
+ }
117
+ #resolveWrapUnwrap(calldata, balances) {
118
+ const decoded = (0, viem.decodeFunctionData)({
119
+ abi,
120
+ data: calldata
121
+ });
122
+ const { asset, share } = this;
123
+ switch (decoded.functionName) {
124
+ case "deposit": return {
125
+ tokenIn: asset,
126
+ tokenOut: share,
127
+ amountIn: decoded.args[0]
128
+ };
129
+ case "depositDiff": {
130
+ const [leftoverAmount] = decoded.args;
131
+ const running = balances.getOrZero(asset);
132
+ return {
133
+ tokenIn: asset,
134
+ tokenOut: share,
135
+ amountIn: running > leftoverAmount ? running - leftoverAmount : 0n
136
+ };
137
+ }
138
+ case "redeem": return {
139
+ tokenIn: share,
140
+ tokenOut: asset,
141
+ amountIn: decoded.args[0]
142
+ };
143
+ case "redeemDiff": {
144
+ const [leftoverAmount] = decoded.args;
145
+ const running = balances.getOrZero(share);
146
+ return {
147
+ tokenIn: share,
148
+ tokenOut: asset,
149
+ amountIn: running > leftoverAmount ? running - leftoverAmount : 0n
150
+ };
151
+ }
152
+ default: return;
153
+ }
154
+ }
101
155
  async applyBalanceChanges(balances, decoded) {
102
156
  switch (decoded.functionName) {
103
157
  case "depositDiff": {
@@ -10,6 +10,10 @@ let viem = require("viem");
10
10
  //#region src/onchain/market/adapters/contracts/MidasGatewayAdapterContract.ts
11
11
  const abi = require_onchain_market_adapters_abi_adapters_iMidasGatewayAdapterV311.iMidasGatewayAdapterV311Abi;
12
12
  const protocolAbi = require_onchain_market_adapters_abi_midas_iMidasGatewayV311.iMidasGatewayV311Abi;
13
+ const receiveGreenlistCalldata = (0, viem.encodeFunctionData)({
14
+ abi,
15
+ functionName: "receiveGreenlist"
16
+ });
13
17
  var MidasGatewayAdapterContract = class extends require_onchain_market_adapters_contracts_AbstractAdapter.AbstractAdapterContract {
14
18
  #version;
15
19
  #gateway;
@@ -165,6 +169,15 @@ var MidasGatewayAdapterContract = class extends require_onchain_market_adapters_
165
169
  const [redeemer] = decoded.args;
166
170
  return { redeemer };
167
171
  }
172
+ /**
173
+ * `receiveGreenlist()` is prepended by `prependMidasReceiveGreenlist`
174
+ * 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.
177
+ */
178
+ replayOutOfBracketCall(_balances, calldata) {
179
+ return calldata === receiveGreenlistCalldata;
180
+ }
168
181
  async applyBalanceChanges(balances, decoded) {
169
182
  switch (decoded.functionName) {
170
183
  case "depositInstantDiff": {
@@ -64,12 +64,9 @@ var PositionsService = class extends require_onchain_base_SDKConstruct.SDKConstr
64
64
  **/
65
65
  async listStrategyPositions(props) {
66
66
  const { owner, includeZeroDebt, blockNumber } = props;
67
- const describable = (await this.sdk.accounts.getBorrowerCreditAccounts(owner, { includeZeroDebt }, blockNumber)).filter((ca) => {
68
- if (!ca.success) this.logger?.warn(`cannot describe position of ${this.labelAddress(ca.creditAccount)}: collateral computation failed`);
69
- return ca.success;
70
- });
71
- const withdrawals = await Promise.all(describable.map((ca) => this.#accountWithdrawals(ca, blockNumber)));
72
- return describable.map((ca, i) => this.#toStrategyPosition(ca, withdrawals[i] ?? new require_onchain_utils_AddressMap.AddressMap()));
67
+ const accounts = await this.sdk.accounts.getBorrowerCreditAccounts(owner, { includeZeroDebt }, blockNumber);
68
+ const withdrawals = await Promise.all(accounts.map((ca) => this.#accountWithdrawals(ca, blockNumber)));
69
+ return accounts.map((ca, i) => this.#toStrategyPosition(ca, withdrawals[i] ?? new require_onchain_utils_AddressMap.AddressMap()));
73
70
  }
74
71
  /**
75
72
  * Health factor of an account state, in basis points (`10000` = 1.0).
@@ -180,14 +177,11 @@ var PositionsService = class extends require_onchain_base_SDKConstruct.SDKConstr
180
177
  const token = market.underlyingToken;
181
178
  const totalDebtValue = ca.debt + ca.accruedInterest + ca.accruedFees;
182
179
  const target = require_onchain_chain_chains.getAccountTargetCollateral(ca.creditAccount, this.sdk.chainId) ?? suite.strategyTargetCollateral;
183
- const snapshot = require_onchain_positions_types.accountSnapshotFromCreditAccountData(ca);
184
- const borrowRate = this.borrowRate(snapshot);
185
- const timeToLiquidation = this.timeToLiquidation(snapshot);
186
- const liquidationPrice = this.liquidationPrice(snapshot);
187
- const zeroDebt = ca.debt === 0n;
180
+ const priceFailed = !ca.success;
181
+ const recomputeTotals = ca.debt === 0n || priceFailed;
188
182
  const collaterals = [];
189
- let totalValue = zeroDebt ? 0n : ca.totalValue;
190
- let totalValueUSD = zeroDebt ? 0n : ca.totalValueUSD;
183
+ let totalValue = recomputeTotals ? 0n : ca.totalValue;
184
+ let totalValueUSD = recomputeTotals ? 0n : ca.totalValueUSD;
191
185
  for (const t of ca.tokens) {
192
186
  if (t.balance <= 10n) continue;
193
187
  collaterals.push({
@@ -195,13 +189,21 @@ var PositionsService = class extends require_onchain_base_SDKConstruct.SDKConstr
195
189
  quota: priceOracle.toTokenAmount(market.underlying, t.quota),
196
190
  withdrawals: withdrawals.get(t.token) ?? []
197
191
  });
198
- if (zeroDebt) {
192
+ if (recomputeTotals) {
199
193
  const value = priceOracle.safeConvert(t.token, market.underlying, t.balance) || 0n;
200
194
  totalValue += value;
201
195
  const usd = priceOracle.safeConvertToUSD(t.token, t.balance) || 0n;
202
196
  totalValueUSD += usd;
203
197
  }
204
198
  }
199
+ const snapshot = {
200
+ ...require_onchain_positions_types.accountSnapshotFromCreditAccountData(ca),
201
+ totalValue
202
+ };
203
+ const borrowRate = this.borrowRate(snapshot);
204
+ const timeToLiquidation = this.timeToLiquidation(snapshot);
205
+ const liquidationPrice = this.liquidationPrice(snapshot);
206
+ const totalDebtUSD = priceFailed ? priceOracle.safeConvertToUSD(market.underlying, totalDebtValue) ?? 0n : ca.totalDebtUSD;
205
207
  return {
206
208
  kind: "strategy",
207
209
  chainId: this.sdk.chainId,
@@ -215,18 +217,19 @@ var PositionsService = class extends require_onchain_base_SDKConstruct.SDKConstr
215
217
  totalDebt: {
216
218
  token,
217
219
  value: totalDebtValue,
218
- valueUsd: require_onchain_market_math.usdToNumber(ca.totalDebtUSD)
220
+ valueUsd: require_onchain_market_math.usdToNumber(totalDebtUSD)
219
221
  },
220
222
  totalValue: {
221
223
  token,
222
224
  value: totalValue,
223
225
  valueUsd: require_onchain_market_math.usdToNumber(totalValueUSD)
224
226
  },
225
- healthFactor: require_onchain_market_math.healthFactorBps(ca.healthFactor),
227
+ healthFactor: priceFailed ? this.healthFactor(snapshot) : require_onchain_market_math.healthFactorBps(ca.healthFactor),
226
228
  borrowRate,
227
229
  timeToLiquidation,
228
230
  liquidationPrice,
229
- collaterals
231
+ collaterals,
232
+ ...priceFailed ? { error: require_model_positions.STRATEGY_POSITION_COLLATERAL_ERROR } : {}
230
233
  };
231
234
  }
232
235
  /**
@@ -2,11 +2,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_onchain_utils_AssetsMap = require("../../onchain/utils/AssetsMap.js");
3
3
  require("../../onchain/constants/math.js");
4
4
  const require_onchain_market_adapters_contracts_AbstractAdapter = require("../../onchain/market/adapters/contracts/AbstractAdapter.js");
5
- const require_onchain_market_adapters_contracts_ERC4626AdapterContract = require("../../onchain/market/adapters/contracts/ERC4626AdapterContract.js");
6
5
  const require_model_previews = require("../../model/previews.js");
7
6
  require("../../model/index.js");
8
7
  require("../../onchain/index.js");
9
- const require_preview_preview_applyRWAWrapUnwrap = require("./applyRWAWrapUnwrap.js");
10
8
  //#region src/preview/preview/replayInnerOperations.ts
11
9
  /**
12
10
  * Creates a {@link ReplayState} around the given account seed, with empty
@@ -94,26 +92,25 @@ function applyWithdrawCollateral(state, op) {
94
92
  *
95
93
  * Inside a bracket, the adapter's balance changes are previewed via
96
94
  * {@link AbstractAdapterContract.previewBalanceChanges}. Outside a bracket,
97
- * only RWA wrap/unwrap calls are allowed (see {@link applyRWAWrapUnwrap});
98
- * nothing enforces the outcome of any other out-of-bracket adapter call
99
- * on-chain, so its effect on balances cannot be previewed.
95
+ * only calls that {@link AbstractAdapterContract.replayOutOfBracketCall}
96
+ * accepts are allowed; nothing enforces the outcome of any other out-of-bracket
97
+ * adapter call on-chain, so its effect on balances cannot be previewed.
100
98
  */
101
99
  async function applyExecute(sdk, op, inBracket, balances) {
102
100
  const adapter = sdk.getContract(op.adapter);
103
101
  if (!inBracket) {
104
- if (!isRWAShare(sdk, adapter)) return {
105
- code: require_model_previews.ERROR_ADAPTER_CALL_OUTSIDE_BRACKET,
106
- message: `call to ${op.adapter} outside of a storeExpectedBalances/compareBalances bracket`
107
- };
108
- try {
109
- require_preview_preview_applyRWAWrapUnwrap.applyRWAWrapUnwrap(adapter, op.calldata, balances);
110
- return;
102
+ if (adapter instanceof require_onchain_market_adapters_contracts_AbstractAdapter.AbstractAdapterContract) try {
103
+ if (adapter.replayOutOfBracketCall(balances, op.calldata)) return;
111
104
  } catch (e) {
112
105
  return {
113
- code: require_model_previews.ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP,
106
+ code: require_model_previews.ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL,
114
107
  message: e instanceof Error ? e.message : String(e)
115
108
  };
116
109
  }
110
+ return {
111
+ code: require_model_previews.ERROR_ADAPTER_CALL_OUTSIDE_BRACKET,
112
+ message: `call to ${op.adapter} outside of a storeExpectedBalances/compareBalances bracket`
113
+ };
117
114
  }
118
115
  if (!(adapter instanceof require_onchain_market_adapters_contracts_AbstractAdapter.AbstractAdapterContract)) return {
119
116
  code: require_model_previews.ERROR_NON_ADAPTER_CALL_IN_BRACKET,
@@ -129,18 +126,6 @@ async function applyExecute(sdk, op, inBracket, balances) {
129
126
  };
130
127
  }
131
128
  }
132
- /**
133
- * True when the ERC4626 adapter converts an RWA underlying, i.e. it is the
134
- * wrap/unwrap adapter of an RWA market rather than a regular vault strategy
135
- * adapter.
136
- */
137
- function isRWAShare(sdk, adapter) {
138
- if (adapter instanceof require_onchain_market_adapters_contracts_ERC4626AdapterContract.ERC4626AdapterContract) {
139
- const meta = sdk.tokensMeta.get(adapter.share);
140
- return !!meta && sdk.tokensMeta.isRWAUnderlying(meta);
141
- }
142
- return false;
143
- }
144
129
  //#endregion
145
130
  exports.makeReplayState = makeReplayState;
146
131
  exports.replayInnerOperations = replayInnerOperations;
@@ -85,6 +85,12 @@ var OpportunitiesNamespace = class extends require_sdk_AbstractNamespace.Abstrac
85
85
  filter(response, filter) {
86
86
  return require_sdk_utils_filterResponse.filterResponse(response, filter, require_model_opportunities.matchesOpportunityFilter);
87
87
  }
88
+ /**
89
+ * {@inheritDoc OpportunitiesOffchainOnly.totals}
90
+ **/
91
+ async totals() {
92
+ return this.offchain.getTotals();
93
+ }
88
94
  async charts(key, metrics, range) {
89
95
  return this.offchain.getCharts(key, metrics, range);
90
96
  }
@@ -41,6 +41,12 @@ var PositionsNamespace = class extends require_sdk_AbstractNamespace.AbstractNam
41
41
  filter(response, filter) {
42
42
  return require_sdk_utils_filterResponse.filterResponse(response, filter, require_model_positions.matchesPositionFilter);
43
43
  }
44
+ /**
45
+ * {@inheritDoc PositionsOffchainOnly.totals}
46
+ **/
47
+ async totals(wallet) {
48
+ return this.offchain.getTotals(wallet);
49
+ }
44
50
  async charts(key, metrics, range) {
45
51
  return this.offchain.getCharts(key, metrics, range);
46
52
  }
@@ -31,7 +31,8 @@ const POOL_OPPORTUNITY_CHART_METRICS = [
31
31
  "depositApyAvg7d",
32
32
  "dieselRate",
33
33
  "supplied",
34
- "borrowed"
34
+ "borrowed",
35
+ "utilization"
35
36
  ];
36
37
  /**
37
38
  * Every metric a strategy opportunity can chart.
@@ -61,6 +62,7 @@ const STRATEGY_OPPORTUNITY_CHART_METRICS = [
61
62
  **/
62
63
  const POOL_POSITION_CHART_METRICS = [
63
64
  "apy",
65
+ "apyAvg7d",
64
66
  "pnl",
65
67
  "mwr"
66
68
  ];
@@ -99,11 +101,13 @@ const CHART_METRIC_UNITS = {
99
101
  supplied: "token",
100
102
  borrowed: "token",
101
103
  tvl: "token",
104
+ utilization: "bps",
102
105
  dieselRate: "ratio",
103
106
  collateralPrice: "ratio",
104
107
  collateralUsdPrice: "usd",
105
108
  underlyingUsdPrice: "usd",
106
109
  apy: "bps",
110
+ apyAvg7d: "bps",
107
111
  pnl: "token",
108
112
  mwr: "bps",
109
113
  totalValueUnderlying: "token",
@@ -12,11 +12,11 @@ import { delayedReceivedAssetSchema, instantReceivedAssetSchema, liquidatableAcc
12
12
  import "./notices.js";
13
13
  import { noticeKindSchema, noticeSchema } from "./notices.schema.js";
14
14
  import { matchesOpportunityFilter, opportunityId, poolOpportunityId, strategyOpportunityId } from "./opportunities.js";
15
- import { apyBreakdownSchema, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityKeySchema, opportunityKindSchema, opportunitySchema, pointRewardsSchema, pointsProgramSchema, poolOpportunityDetailSchema, poolOpportunityKeySchema, poolOpportunitySchema, priceFeedDataSchema, priceFeedSummarySchema, quotaAssetSchema, rateCurvePointSchema, rateCurveSchema, rewardsSchema, strategyOpportunityDetailSchema, strategyOpportunityKeySchema, strategyOpportunitySchema, tokenRewardsSchema } from "./opportunities.schema.js";
16
- import { liquidationPositionId, matchesPositionFilter, poolPositionId, positionId, strategyPositionId } from "./positions.js";
15
+ import { apyBreakdownSchema, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityKeySchema, opportunityKindSchema, opportunitySchema, opportunityTotalsSchema, pointRewardsSchema, pointsProgramSchema, poolOpportunityDetailSchema, poolOpportunityKeySchema, poolOpportunitySchema, priceFeedDataSchema, priceFeedSummarySchema, quotaAssetSchema, rateCurvePointSchema, rateCurveSchema, rewardsSchema, strategyOpportunityDetailSchema, strategyOpportunityKeySchema, strategyOpportunitySchema, tokenRewardsSchema } from "./opportunities.schema.js";
16
+ import { STRATEGY_POSITION_COLLATERAL_ERROR, liquidationPositionId, matchesPositionFilter, poolPositionId, positionId, strategyPositionId } from "./positions.js";
17
17
  import { borrowRateBreakdownSchema, pnlBreakdownSchema, pointsProgramPnLSchema, pointsRewardsPnLSchema, poolPositionKeySchema, poolPositionSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionKeySchema, positionKindSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionsTotalsSchema, rewardsPnLSchema, strategyPositionKeySchema, strategyPositionSchema, tokenQuotaRateSchema, tokenRewardsPnLSchema } from "./positions.schema.js";
18
- import { ERROR_ADAPTER_CALL_OUTSIDE_BRACKET, ERROR_INVALID_TRANSACTION_VALUE, ERROR_MALFORMED_BRACKET, ERROR_NON_ADAPTER_CALL_IN_BRACKET, ERROR_UNPREVIEWABLE_ADAPTER_CALL, ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP, ERROR_UNPRICEABLE_TOKEN } from "./previews.js";
18
+ import { ERROR_ADAPTER_CALL_OUTSIDE_BRACKET, ERROR_INVALID_TRANSACTION_VALUE, ERROR_MALFORMED_BRACKET, ERROR_NON_ADAPTER_CALL_IN_BRACKET, ERROR_UNPREVIEWABLE_ADAPTER_CALL, ERROR_UNPRICEABLE_TOKEN, ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL } from "./previews.js";
19
19
  import "./primitives.js";
20
20
  import "./response.js";
21
21
  import { chainFailedSchema, chainMetadataSchema, chainSucceededSchema, dataSourceSchema, responseMetadataSchema, responseSchema } from "./response.schema.js";
22
- export { CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, ERROR_ADAPTER_CALL_OUTSIDE_BRACKET, ERROR_INVALID_TRANSACTION_VALUE, ERROR_MALFORMED_BRACKET, ERROR_NON_ADAPTER_CALL_IN_BRACKET, ERROR_UNPREVIEWABLE_ADAPTER_CALL, ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP, ERROR_UNPRICEABLE_TOKEN, FILTER_ALL, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, amountSchema, apyBreakdownSchema, assetTypeSchema, backendPreferred, booleanParamSchema, borrowRateBreakdownSchema, bpsSchema, chainFailedSchema, chainIdSchema, chainMetadataSchema, chainSucceededSchema, chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, compareTagOf, curatorNameSchema, curatorSchema, dataSourceSchema, delayedReceivedAssetSchema, encodeFlag, filterAllSchema, filterable, instantReceivedAssetSchema, isFilterSet, leverageSchema, liquidatableAccountFilterSchema, liquidatableAccountSchema, liquidationApprovalSchema, liquidationDetailsSchema, liquidationPositionId, liquidationPositionSchema, matchesLiquidatableAccountFilter, matchesOpportunityFilter, matchesPositionFilter, noticeKindSchema, noticeSchema, offchainOnly, onchainOnly, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityId, opportunityKeySchema, opportunityKindSchema, opportunitySchema, pnlBreakdownSchema, pointRewardsSchema, pointsProgramPnLSchema, pointsProgramSchema, pointsRewardsPnLSchema, poolOpportunityChartMetricSchema, poolOpportunityDetailSchema, poolOpportunityId, poolOpportunityKeySchema, poolOpportunitySchema, poolPositionChartMetricSchema, poolPositionId, poolPositionKeySchema, poolPositionSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionId, positionKeySchema, positionKindSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionsTotalsSchema, priceFeedDataSchema, priceFeedSummarySchema, quotaAssetSchema, rateCurvePointSchema, rateCurveSchema, receivedAssetSchema, responseMetadataSchema, responseSchema, rewardsPnLSchema, rewardsSchema, strategyOpportunityChartMetricSchema, strategyOpportunityDetailSchema, strategyOpportunityId, strategyOpportunityKeySchema, strategyOpportunitySchema, strategyPositionChartMetricSchema, strategyPositionId, strategyPositionKeySchema, strategyPositionSchema, timestampSchema, tokenAmountSchema, tokenQuotaRateSchema, tokenRewardsPnLSchema, tokenRewardsSchema, tokenSchema, tolerance, txCallSchema, underlyingTokenSchema };
22
+ export { CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, ERROR_ADAPTER_CALL_OUTSIDE_BRACKET, ERROR_INVALID_TRANSACTION_VALUE, ERROR_MALFORMED_BRACKET, ERROR_NON_ADAPTER_CALL_IN_BRACKET, ERROR_UNPREVIEWABLE_ADAPTER_CALL, ERROR_UNPRICEABLE_TOKEN, ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL, FILTER_ALL, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, STRATEGY_POSITION_COLLATERAL_ERROR, amountSchema, apyBreakdownSchema, assetTypeSchema, backendPreferred, booleanParamSchema, borrowRateBreakdownSchema, bpsSchema, chainFailedSchema, chainIdSchema, chainMetadataSchema, chainSucceededSchema, chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, compareTagOf, curatorNameSchema, curatorSchema, dataSourceSchema, delayedReceivedAssetSchema, encodeFlag, filterAllSchema, filterable, instantReceivedAssetSchema, isFilterSet, leverageSchema, liquidatableAccountFilterSchema, liquidatableAccountSchema, liquidationApprovalSchema, liquidationDetailsSchema, liquidationPositionId, liquidationPositionSchema, matchesLiquidatableAccountFilter, matchesOpportunityFilter, matchesPositionFilter, noticeKindSchema, noticeSchema, offchainOnly, onchainOnly, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityId, opportunityKeySchema, opportunityKindSchema, opportunitySchema, opportunityTotalsSchema, pnlBreakdownSchema, pointRewardsSchema, pointsProgramPnLSchema, pointsProgramSchema, pointsRewardsPnLSchema, poolOpportunityChartMetricSchema, poolOpportunityDetailSchema, poolOpportunityId, poolOpportunityKeySchema, poolOpportunitySchema, poolPositionChartMetricSchema, poolPositionId, poolPositionKeySchema, poolPositionSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionId, positionKeySchema, positionKindSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionsTotalsSchema, priceFeedDataSchema, priceFeedSummarySchema, quotaAssetSchema, rateCurvePointSchema, rateCurveSchema, receivedAssetSchema, responseMetadataSchema, responseSchema, rewardsPnLSchema, rewardsSchema, strategyOpportunityChartMetricSchema, strategyOpportunityDetailSchema, strategyOpportunityId, strategyOpportunityKeySchema, strategyOpportunitySchema, strategyPositionChartMetricSchema, strategyPositionId, strategyPositionKeySchema, strategyPositionSchema, timestampSchema, tokenAmountSchema, tokenQuotaRateSchema, tokenRewardsPnLSchema, tokenRewardsSchema, tokenSchema, tolerance, txCallSchema, underlyingTokenSchema };
@@ -244,5 +244,13 @@ const opportunityKeySchema = z.discriminatedUnion("kind", [z.object({
244
244
  kind: z.literal("strategy"),
245
245
  ...strategyOpportunityKeySchema.shape
246
246
  })]);
247
+ /**
248
+ * {@link OpportunityTotals}
249
+ **/
250
+ const opportunityTotalsSchema = z.object({
251
+ tvl: z.number(),
252
+ totalBorrowed: z.number(),
253
+ totalSupply: z.number()
254
+ });
247
255
  //#endregion
248
- export { apyBreakdownSchema, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityKeySchema, opportunityKindSchema, opportunitySchema, pointRewardsSchema, pointsProgramSchema, poolOpportunityDetailSchema, poolOpportunityKeySchema, poolOpportunitySchema, priceFeedDataSchema, priceFeedSummarySchema, quotaAssetSchema, rateCurvePointSchema, rateCurveSchema, rewardsSchema, strategyOpportunityDetailSchema, strategyOpportunityKeySchema, strategyOpportunitySchema, tokenRewardsSchema };
256
+ export { apyBreakdownSchema, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityKeySchema, opportunityKindSchema, opportunitySchema, opportunityTotalsSchema, pointRewardsSchema, pointsProgramSchema, poolOpportunityDetailSchema, poolOpportunityKeySchema, poolOpportunitySchema, priceFeedDataSchema, priceFeedSummarySchema, quotaAssetSchema, rateCurvePointSchema, rateCurveSchema, rewardsSchema, strategyOpportunityDetailSchema, strategyOpportunityKeySchema, strategyOpportunitySchema, tokenRewardsSchema };
@@ -1,6 +1,11 @@
1
1
  import { isFilterSet } from "./filters.js";
2
2
  //#region src/model/positions.ts
3
3
  /**
4
+ * Set on {@link StrategyPosition.error} when the account could not be fully
5
+ * valued (e.g. a dead price feed).
6
+ **/
7
+ const STRATEGY_POSITION_COLLATERAL_ERROR = "collateral computation failed";
8
+ /**
4
9
  * Builds the canonical id of a pool position.
5
10
  *
6
11
  * @example
@@ -84,4 +89,4 @@ function positionUnderlying(position) {
84
89
  }
85
90
  }
86
91
  //#endregion
87
- export { liquidationPositionId, matchesPositionFilter, poolPositionId, positionId, strategyPositionId };
92
+ export { STRATEGY_POSITION_COLLATERAL_ERROR, liquidationPositionId, matchesPositionFilter, poolPositionId, positionId, strategyPositionId };
@@ -114,7 +114,8 @@ const strategyPositionSchema = z.object({
114
114
  timeToLiquidation: onchainOnly(ZodBigInt().nullable()).optional(),
115
115
  liquidationPrice: onchainOnly(ZodBigInt().nullable()).optional(),
116
116
  pnl: offchainOnly(pnlBreakdownSchema).optional(),
117
- collaterals: z.array(positionCollateralSchema)
117
+ collaterals: z.array(positionCollateralSchema),
118
+ error: z.string().optional()
118
119
  });
119
120
  /**
120
121
  * {@link Position}
@@ -20,9 +20,10 @@ const ERROR_NON_ADAPTER_CALL_IN_BRACKET = 1003;
20
20
  **/
21
21
  const ERROR_UNPREVIEWABLE_ADAPTER_CALL = 1004;
22
22
  /**
23
- * Out-of-bracket RWA wrap/unwrap calldata cannot be decoded
23
+ * An out-of-bracket adapter call that is allowed there (e.g. RWA wrap/unwrap)
24
+ * could not be decoded or replayed
24
25
  **/
25
- const ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP = 1005;
26
+ const ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL = 1005;
26
27
  /**
27
28
  * `msg.value` does not fit into the declared WETH collateral
28
29
  * Transactions can have arbitrary value, but the ones that we create
@@ -32,4 +33,4 @@ const ERROR_INVALID_TRANSACTION_VALUE = 1006;
32
33
  /** A token in the preview could not be priced by the oracle */
33
34
  const ERROR_UNPRICEABLE_TOKEN = 2001;
34
35
  //#endregion
35
- export { ERROR_ADAPTER_CALL_OUTSIDE_BRACKET, ERROR_INVALID_TRANSACTION_VALUE, ERROR_MALFORMED_BRACKET, ERROR_NON_ADAPTER_CALL_IN_BRACKET, ERROR_UNPREVIEWABLE_ADAPTER_CALL, ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP, ERROR_UNPRICEABLE_TOKEN };
36
+ export { ERROR_ADAPTER_CALL_OUTSIDE_BRACKET, ERROR_INVALID_TRANSACTION_VALUE, ERROR_MALFORMED_BRACKET, ERROR_NON_ADAPTER_CALL_IN_BRACKET, ERROR_UNPREVIEWABLE_ADAPTER_CALL, ERROR_UNPRICEABLE_TOKEN, ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL };
@@ -1,4 +1,4 @@
1
- import { opportunityFilterQuerySchema, opportunitySchema, poolOpportunityDetailSchema, strategyOpportunityDetailSchema } from "../../model/opportunities.schema.js";
1
+ import { opportunityFilterQuerySchema, opportunitySchema, opportunityTotalsSchema, poolOpportunityDetailSchema, strategyOpportunityDetailSchema } from "../../model/opportunities.schema.js";
2
2
  import { AbstractOffchainNamespace } from "../AbstractOffchainNamespace.js";
3
3
  import { z } from "zod/v4";
4
4
  //#region src/offchain/opportunities/OffchainOpportunities.ts
@@ -43,6 +43,15 @@ var OffchainOpportunities = class extends AbstractOffchainNamespace {
43
43
  });
44
44
  }
45
45
  /**
46
+ * Protocol-wide totals across every opportunity the backend serves.
47
+ **/
48
+ async getTotals() {
49
+ return this.get({
50
+ path: `${this.#root}/totals`,
51
+ schema: opportunityTotalsSchema
52
+ });
53
+ }
54
+ /**
46
55
  * Charts of one opportunity: one series per metric, on a shared grid.
47
56
  **/
48
57
  async getCharts(key, metrics, range) {
@@ -1,4 +1,4 @@
1
- import { positionFilterQuerySchema, positionSchema } from "../../model/positions.schema.js";
1
+ import { positionFilterQuerySchema, positionSchema, positionsTotalsSchema } from "../../model/positions.schema.js";
2
2
  import { AbstractOffchainNamespace } from "../AbstractOffchainNamespace.js";
3
3
  import { z } from "zod/v4";
4
4
  //#region src/offchain/positions/OffchainPositions.ts
@@ -24,6 +24,15 @@ var OffchainPositions = class extends AbstractOffchainNamespace {
24
24
  });
25
25
  }
26
26
  /**
27
+ * Aggregate over everything a wallet holds, see {@link PositionsTotals}.
28
+ **/
29
+ async getTotals(wallet) {
30
+ return this.get({
31
+ path: `${this.#root}/${wallet}/totals`,
32
+ schema: positionsTotalsSchema
33
+ });
34
+ }
35
+ /**
27
36
  * Charts of one position: one series per metric, on a shared grid.
28
37
  **/
29
38
  async getCharts(key, metrics, range) {
@@ -114,6 +114,20 @@ var AbstractAdapterContract = class extends BaseContract {
114
114
  await this.applyBalanceChanges(balances, decoded);
115
115
  }
116
116
  /**
117
+ * Replays this adapter call when it appears outside a
118
+ * storeExpectedBalances/compareBalances bracket, mutating `balances` in
119
+ * place, and returns `true` when the call is legal there.
120
+ *
121
+ * Base implementation returns `false`: nothing enforces the outcome of an
122
+ * out-of-bracket adapter call on-chain, so it cannot be previewed.
123
+ *
124
+ * @throws when the call is allowed outside a bracket but its calldata
125
+ * cannot be decoded
126
+ */
127
+ replayOutOfBracketCall(_balances, _calldata) {
128
+ return false;
129
+ }
130
+ /**
117
131
  * Applies the balance changes of a decoded adapter call to the running
118
132
  * balances, mutating them in place. Overrides should express changes via
119
133
  * {@link setLeftover} (diff-style calls) and {@link spendExact}