@panoptic-eng/sdk 1.0.40 → 1.0.42

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.
@@ -1,7 +1,7 @@
1
1
  import { StateViewAbi, formatTokenAmount, getAccountCollateral, panopticQueryAbi$1 as panopticQueryAbi, parseTokenAmount, readBlockAndAggregate, requireReturnData } from "./irm-SPC2KxLA.js";
2
- import { AccountInsolventError, ChunkLimitError, DEFAULT_VEGOID, InvalidHistoryRangeError, NotEnoughTokensError, PanopticError, PanopticValidationError, SafeModeError, StaleDataError, StorageDataNotFoundError, UnhealthyPoolError, WrongUniswapPoolError, collateralTrackerV2Abi, decodeLeftRightSigned, decodeLeftRightUnsigned, decodePosition, decodePositionBalance, decodeTickSpacing, getBlockMeta, getClosedPositionsKey, getPendingPositionsKey, getPool, getPoolMetaKey, getPositionMetaKey, getPositionsKey, getTrackedChunksKey, getTrackedPositionIds, jsonSerializer, mintableAfterBuffer, panopticFactoryV3Abi, panopticFactoryV4Abi, panopticGuardianAbi, panopticPoolV2Abi, panopticQueryAbi as panopticQueryAbi$1, parsePanopticError, riskEngineAbi, semiFungiblePositionManagerV3Abi, semiFungiblePositionManagerV4Abi, stateViewAbi, uniswapV3PoolAbi } from "./getTrackedPositionIds-ms3W9dYB.js";
2
+ import { AccountInsolventError, ChunkLimitError, DEFAULT_VEGOID, InvalidHistoryRangeError, LEG_LIMITS, NotEnoughTokensError, PanopticError, PanopticValidationError, SafeModeError, StaleDataError, StorageDataNotFoundError, TOKEN_ID_BITS, UnhealthyPoolError, WrongUniswapPoolError, collateralTrackerV2Abi, decodeLeftRightSigned, decodeLeftRightUnsigned, decodePosition, decodePositionBalance, decodeTickSpacing, getBlockMeta, getClosedPositionsKey, getPendingPositionsKey, getPool, getPoolMetaKey, getPositionMetaKey, getPositionsKey, getTrackedChunksKey, getTrackedPositionIds, jsonSerializer, mintableAfterBuffer, panopticFactoryV3Abi, panopticFactoryV4Abi, panopticGuardianAbi, panopticPoolV2Abi, panopticQueryAbi as panopticQueryAbi$1, parsePanopticError, riskEngineAbi, semiFungiblePositionManagerV3Abi, semiFungiblePositionManagerV4Abi, stateViewAbi, uniswapV3PoolAbi } from "./getTrackedPositionIds-ms3W9dYB.js";
3
3
  import { MAX_TICK, MAX_TRACKED_CHUNKS, MIN_TICK, WAD, calculatePositionDelta, calculatePositionGamma, calculatePositionValue, priceToTick, sqrtPriceX96ToTick, tickLimits, tickToPrice, tickToPriceDecimalScaled, tickToSqrtPriceX96 } from "./greeks-GysWXct-.js";
4
- import { addLegToTokenId, buildBatchDispatchArgs, buildUniqueCredit, countLegs, createTokenIdBuilder, decodeAllLegs, decodeTokenId, getPoolTokensForSimulation, loadCheckpoint, resolveTokenIndex, simulateOpenPosition, simulateWithTokenFlow } from "./writes-Xp9Wa8GQ.js";
4
+ import { addLegToTokenId, buildBatchDispatchArgs, buildUniqueCredit, buildUniqueLoan, countLegs, createTokenIdBuilder, decodeAllLegs, decodeTokenId, getCurrentPositionSizes, getPoolTokensForSimulation, loadCheckpoint, resolveTokenIndex, simulateOpenPosition, simulateWithTokenFlow } from "./writes-_gfkBizf.js";
5
5
  import { BaseError, ContractFunctionExecutionError, ContractFunctionRevertedError, ExecutionRevertedError, decodeFunctionResult, encodeAbiParameters, encodeFunctionData, getAddress, keccak256, toHex, zeroAddress } from "viem";
6
6
  import { multicall } from "viem/actions";
7
7
 
@@ -203,6 +203,165 @@ function interpolateBlocks(startBlock, endBlock, points) {
203
203
  return Array.from({ length: points }, (_, i) => startBlock + range * BigInt(i) / BigInt(points - 1));
204
204
  }
205
205
 
206
+ //#endregion
207
+ //#region src/panoptic/v2/tokenId/deriveUniqueTokenId.ts
208
+ const POOL_ID_MASK$2 = (1n << 64n) - 1n;
209
+ const MAX_LEGS = TOKEN_ID_BITS.MAX_LEGS;
210
+ const MAX_OPTION_RATIO = LEG_LIMITS.MAX_RATIO;
211
+ const Q192$2 = 1n << 192n;
212
+ /**
213
+ * Floor integer square root for bigints (Newton's method). Mirrors the isqrt
214
+ * used in reads/collateralEstimate.ts (buildNeutralLeg).
215
+ */
216
+ function isqrt$1(value) {
217
+ if (value < 0n) throw new PanopticError("isqrt of negative number");
218
+ if (value < 2n) return value;
219
+ let x = value;
220
+ let y = x + 1n >> 1n;
221
+ while (y < x) {
222
+ x = y;
223
+ y = x + value / x >> 1n;
224
+ }
225
+ return x;
226
+ }
227
+ const DEFAULT_TICK_SPACING = 200n;
228
+ /**
229
+ * Target notional (in wei of the tokenType-side asset) for the appended
230
+ * tiny credit leg. Chosen at 10 wei — small enough to be economically
231
+ * meaningless against any real position size, large enough to safely
232
+ * clear rounding on the SFPM's width-2 internal chunk math without any
233
+ * risk of underflowing to zero (which would revert ChunkHasZeroLiquidity).
234
+ */
235
+ const TINY_CREDIT_TARGET_NOTIONAL_WEI = 10n;
236
+ /**
237
+ * Pick a signedStrike for the appended width=0 credit leg such that:
238
+ * 1. positionSize · 1.0001^signedStrike ≈ TINY_CREDIT_TARGET_NOTIONAL_WEI
239
+ * (~10 wei — economically meaningless but comfortably above any
240
+ * SFPM width-2 chunk rounding);
241
+ * 2. the leg's tick range (SFPM internally treats width=0 as width=2, so
242
+ * the range is `strike ± tickSpacing`) stays strictly inside
243
+ * `[MIN_POOL_TICK, MAX_POOL_TICK]` — otherwise the getSqrtRatioAtTick
244
+ * call reverts with `InvalidTick`.
245
+ *
246
+ * Closed form: `1.0001^signedStrike = target/positionSize`, so
247
+ * `sqrtKrawX96 = isqrt(target · 2^192 / positionSize)` and
248
+ * `signedStrike = sqrtPriceX96ToTick(sqrtKrawX96)`. If the notional-optimal
249
+ * strike falls outside the safe range, we clamp inward. Clamping raises the
250
+ * notional but keeps it << position size for any reasonable strike.
251
+ */
252
+ function computeTinyCreditSignedStrike(positionSize, tickSpacing) {
253
+ if (positionSize <= 0n) throw new PanopticError("computeTinyCreditSignedStrike: positionSize must be > 0");
254
+ const minSafe = MIN_TICK + tickSpacing + 1n;
255
+ const maxSafe = MAX_TICK - tickSpacing - 1n;
256
+ let signedStrike;
257
+ try {
258
+ const sqrtKrawX96 = isqrt$1(TINY_CREDIT_TARGET_NOTIONAL_WEI * Q192$2 / positionSize);
259
+ signedStrike = sqrtPriceX96ToTick(sqrtKrawX96);
260
+ } catch {
261
+ signedStrike = minSafe;
262
+ }
263
+ if (signedStrike < minSafe) return minSafe;
264
+ if (signedStrike > maxSafe) return maxSafe;
265
+ return signedStrike;
266
+ }
267
+ /**
268
+ * Assemble the tiny credit leg struct, picking a strike that avoids
269
+ * colliding with any existing width=0 credit leg on the same (asset,
270
+ * tokenType) pair.
271
+ *
272
+ * The encoded strike stored in the tokenId is
273
+ * `asset === 0 ? signedStrike : -signedStrike` (mirrors
274
+ * {@link buildNeutralLeg} in reads/collateralEstimate.ts).
275
+ */
276
+ function pickUniqueTinyCreditLeg(baseTokenId, legIndex, positionSize, tickSpacing) {
277
+ const asset = 1n;
278
+ const tokenType = 0n;
279
+ const existingLegs = decodeAllLegs(baseTokenId);
280
+ const maxSafe = MAX_TICK - tickSpacing - 1n;
281
+ let signedStrike = computeTinyCreditSignedStrike(positionSize, tickSpacing);
282
+ while (signedStrike <= maxSafe) {
283
+ const candidate = asset === 0n ? signedStrike : -signedStrike;
284
+ let collides = false;
285
+ for (const leg of existingLegs) if (leg.width === 0n && leg.isLong && leg.asset === asset && leg.tokenType === tokenType && leg.strike === candidate) {
286
+ collides = true;
287
+ break;
288
+ }
289
+ if (!collides) break;
290
+ signedStrike += 1n;
291
+ }
292
+ if (signedStrike > maxSafe) throw new PanopticError("deriveUniqueTokenId: exhausted strike space picking a unique tiny credit leg");
293
+ const encodedStrike = asset === 0n ? signedStrike : -signedStrike;
294
+ return {
295
+ index: legIndex,
296
+ asset,
297
+ tokenType,
298
+ optionRatio: 1n,
299
+ isLong: 1n,
300
+ riskPartner: legIndex,
301
+ strike: encodedStrike,
302
+ width: 0n
303
+ };
304
+ }
305
+ function appendTinyCreditLeg(baseTokenId, baseLegCount, positionSize, tickSpacing) {
306
+ const newLeg = pickUniqueTinyCreditLeg(baseTokenId, baseLegCount, positionSize, tickSpacing);
307
+ return addLegToTokenId(baseTokenId, newLeg);
308
+ }
309
+ function scaleRatios(baseTokenId, targetPositionSize) {
310
+ const legs = decodeAllLegs(baseTokenId);
311
+ const maxRatio = legs.reduce((m, leg) => leg.optionRatio > m ? leg.optionRatio : m, 0n);
312
+ const N = MAX_OPTION_RATIO / maxRatio;
313
+ if (N < 2n) throw new PanopticError("deriveUniqueTokenId: cannot derive a unique tokenId — all 4 leg slots used and optionRatios already near the 127 ceiling");
314
+ const newPositionSize = (targetPositionSize + N - 1n) / N;
315
+ const poolId = baseTokenId & POOL_ID_MASK$2;
316
+ let out = poolId;
317
+ for (const leg of legs) out = addLegToTokenId(out, {
318
+ index: leg.index,
319
+ asset: leg.asset,
320
+ tokenType: leg.tokenType,
321
+ optionRatio: leg.optionRatio * N,
322
+ isLong: leg.isLong ? 1n : 0n,
323
+ riskPartner: leg.riskPartner,
324
+ strike: leg.strike,
325
+ width: leg.width
326
+ });
327
+ return {
328
+ newTokenId: out,
329
+ newPositionSize,
330
+ effectivePositionSize: newPositionSize * N,
331
+ strategy: "ratio-scale"
332
+ };
333
+ }
334
+ /**
335
+ * Derive a tokenId unique from `baseTokenId` for a partial reduction.
336
+ *
337
+ * Prefers a tiny-credit-leg extension (arbitrary new size). Falls back to
338
+ * optionRatio scaling only when the base tokenId already occupies all 4 leg
339
+ * slots.
340
+ */
341
+ function deriveUniqueTokenId(params) {
342
+ const { baseTokenId, targetPositionSize, tickSpacing = DEFAULT_TICK_SPACING } = params;
343
+ if (targetPositionSize <= 0n) throw new PanopticError("deriveUniqueTokenId: targetPositionSize must be > 0");
344
+ const legCount = countLegs(baseTokenId);
345
+ if (legCount === 0n) throw new PanopticError("deriveUniqueTokenId: baseTokenId has no legs");
346
+ if (legCount < MAX_LEGS) {
347
+ const newTokenId = appendTinyCreditLeg(baseTokenId, legCount, targetPositionSize, tickSpacing);
348
+ return {
349
+ newTokenId,
350
+ newPositionSize: targetPositionSize,
351
+ effectivePositionSize: targetPositionSize,
352
+ strategy: "tiny-credit"
353
+ };
354
+ }
355
+ return scaleRatios(baseTokenId, targetPositionSize);
356
+ }
357
+ /**
358
+ * Re-export decoded leg count so callers can gate UI on the strategy that
359
+ * would be chosen (e.g. show a divisibility hint on ratio-scale positions).
360
+ */
361
+ function planDeriveStrategy(baseTokenId) {
362
+ return countLegs(baseTokenId) < MAX_LEGS ? "tiny-credit" : "ratio-scale";
363
+ }
364
+
206
365
  //#endregion
207
366
  //#region src/panoptic/v2/sfpmSwap/calldata.ts
208
367
  /**
@@ -1474,7 +1633,7 @@ async function simulateDispatch(params) {
1474
1633
 
1475
1634
  //#endregion
1476
1635
  //#region src/panoptic/v2/simulations/tokenShortfallRecovery.ts
1477
- const BPS_DENOMINATOR$1 = 10000n;
1636
+ const BPS_DENOMINATOR$2 = 10000n;
1478
1637
  const MAX_RECOVERY_QUOTE_ATTEMPTS = 8;
1479
1638
  /**
1480
1639
  * Wrap a dispatch with a temporary credit leg that sources the shortfall.
@@ -1524,7 +1683,7 @@ function getNotEnoughTokensError(error) {
1524
1683
  }
1525
1684
  function maximumAmountIn(estimatedAmountIn, slippageBps) {
1526
1685
  if (slippageBps < 0n) throw new PanopticError("slippageBps must be non-negative");
1527
- return (estimatedAmountIn * (BPS_DENOMINATOR$1 + slippageBps) + BPS_DENOMINATOR$1 - 1n) / BPS_DENOMINATOR$1;
1686
+ return (estimatedAmountIn * (BPS_DENOMINATOR$2 + slippageBps) + BPS_DENOMINATOR$2 - 1n) / BPS_DENOMINATOR$2;
1528
1687
  }
1529
1688
  function ceilDiv(numerator, denominator) {
1530
1689
  return (numerator + denominator - 1n) / denominator;
@@ -1552,10 +1711,10 @@ async function quoteTokenShortfallRecovery(params) {
1552
1711
  reason: "invalid-shortfall",
1553
1712
  detail: `requested=${shortfallError.assetsRequested} <= balance=${shortfallError.assetBalance}`
1554
1713
  };
1555
- if (params.slippageBps < 0n || params.slippageBps > BPS_DENOMINATOR$1) return {
1714
+ if (params.slippageBps < 0n || params.slippageBps > BPS_DENOMINATOR$2) return {
1556
1715
  available: false,
1557
1716
  reason: "invalid-slippage",
1558
- detail: `slippageBps=${params.slippageBps} is outside [0, ${BPS_DENOMINATOR$1}]`
1717
+ detail: `slippageBps=${params.slippageBps} is outside [0, ${BPS_DENOMINATOR$2}]`
1559
1718
  };
1560
1719
  const targetBlockNumber = params.blockNumber ?? await params.client.getBlockNumber();
1561
1720
  const pool = await getPool({
@@ -1703,8 +1862,9 @@ async function quoteTokenShortfallRecovery(params) {
1703
1862
  error: new PanopticError("Could not size the prefixed recovery swap")
1704
1863
  };
1705
1864
  };
1865
+ let creditOutSize = amountOut;
1706
1866
  for (let attempt = 0; attempt < MAX_RECOVERY_QUOTE_ATTEMPTS; attempt++) {
1707
- const credit = buildUniqueCredit(pool.poolId, tokenOutIndex, tokenOutIndex, pool.currentTick, pool.tickSpacing, collisionIds, amountOut);
1867
+ const credit = buildUniqueCredit(pool.poolId, tokenOutIndex, tokenOutIndex, pool.currentTick, pool.tickSpacing, collisionIds, creditOutSize);
1708
1868
  const recoveredDispatch = buildTokenShortfallRecoveryDispatch({
1709
1869
  dispatch: params.dispatch,
1710
1870
  creditTokenId: credit.tokenId,
@@ -1748,10 +1908,14 @@ async function quoteTokenShortfallRecovery(params) {
1748
1908
  const maxAmountIn = maximumAmountIn(estimatedAmountIn, params.slippageBps);
1749
1909
  const swapOutput = getOutputAmount(swapSimulation.tokenFlow, tokenOutIndex);
1750
1910
  const sourceBalance = getBalanceBefore(swapSimulation.tokenFlow, tokenInIndex);
1751
- if (swapOutput < amountOut || sourceBalance < maxAmountIn) return {
1911
+ if (swapOutput < amountOut) {
1912
+ creditOutSize = swapOutput > 0n ? ceilDiv(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
1913
+ continue;
1914
+ }
1915
+ if (sourceBalance < maxAmountIn) return {
1752
1916
  available: false,
1753
1917
  reason: "swap-unavailable",
1754
- detail: swapOutput < amountOut ? `swap output ${swapOutput} < required ${amountOut}` : `source balance ${sourceBalance} < maximumAmountIn ${maxAmountIn} (estimated ${estimatedAmountIn}, slippageBps ${params.slippageBps})`,
1918
+ detail: `source balance ${sourceBalance} < maximumAmountIn ${maxAmountIn} (estimated ${estimatedAmountIn}, slippageBps ${params.slippageBps})`,
1755
1919
  error: new PanopticError("Insufficient source collateral for the recovery swap")
1756
1920
  };
1757
1921
  const recoverySimulation = await simulateDispatch({
@@ -1803,6 +1967,7 @@ async function quoteTokenShortfallRecovery(params) {
1803
1967
  const decodedShortfall = remainingShortfall.assetsRequested - remainingShortfall.assetBalance;
1804
1968
  const additionalAmountOut = decodedShortfall > 0n ? decodedShortfall : amountOut;
1805
1969
  amountOut += additionalAmountOut;
1970
+ creditOutSize = swapOutput > 0n ? ceilDiv(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
1806
1971
  }
1807
1972
  return {
1808
1973
  available: false,
@@ -1829,6 +1994,7 @@ const MAX_EFFECTIVE_LIQUIDITY_LIMIT = 8388607;
1829
1994
  * returned value must be scaled down to the caller's actual `positionSize`.
1830
1995
  */
1831
1996
  const MAX_UINT64$1 = 2n ** 64n - 1n;
1997
+ const FP96$1 = 1n << 96n;
1832
1998
  /**
1833
1999
  * `getRequiredBase` returns `type(uint128).max` as an error sentinel (invalid
1834
2000
  * tokenId or reverting `getMargin`). Detect it so we don't scale a garbage value.
@@ -1841,7 +2007,9 @@ const REQUIRED_BASE_ERROR_SENTINEL = 2n ** 128n - 1n;
1841
2007
  * computes the requirement at `type(uint64).max` size and 0% utilization. Since
1842
2008
  * the requirement is linear in size, the raw result is scaled by
1843
2009
  * `positionSize / type(uint64).max` to yield the requirement for the requested
1844
- * size. Returns collateral requirement in terms of token0.
2010
+ * size. `PanopticQuery.getRequiredBase` returns the cross-margin requirement in
2011
+ * the higher-precision raw token at `atTick`; this function places that amount
2012
+ * in the matching `required0` or `required1` field.
1845
2013
  *
1846
2014
  * @param params - The parameters
1847
2015
  * @returns Estimated collateral requirements with block metadata
@@ -1860,7 +2028,7 @@ async function estimateCollateralRequired(params) {
1860
2028
  });
1861
2029
  effectiveTick = BigInt(currentTickResult);
1862
2030
  }
1863
- const [required0, _meta] = await Promise.all([client.readContract({
2031
+ const [requiredBase, _meta] = await Promise.all([client.readContract({
1864
2032
  address: queryAddress,
1865
2033
  abi: panopticQueryAbi,
1866
2034
  functionName: "getRequiredBase",
@@ -1874,10 +2042,11 @@ async function estimateCollateralRequired(params) {
1874
2042
  client,
1875
2043
  blockNumber: targetBlockNumber
1876
2044
  })]);
1877
- const scaled0 = required0 >= REQUIRED_BASE_ERROR_SENTINEL ? required0 : required0 * positionSize / MAX_UINT64$1;
2045
+ const scaledRequirement = requiredBase >= REQUIRED_BASE_ERROR_SENTINEL ? requiredBase : requiredBase * positionSize / MAX_UINT64$1;
2046
+ const denominatedInToken0 = tickToSqrtPriceX96(effectiveTick) < FP96$1;
1878
2047
  return {
1879
- required0: scaled0,
1880
- required1: 0n,
2048
+ required0: denominatedInToken0 ? scaledRequirement : 0n,
2049
+ required1: denominatedInToken0 ? 0n : scaledRequirement,
1881
2050
  _meta
1882
2051
  };
1883
2052
  }
@@ -5089,7 +5258,9 @@ async function getStreamiaHistory(params) {
5089
5258
  _meta: _meta$1
5090
5259
  };
5091
5260
  }
5092
- const premiaRequests = blockNumbers.map((bn) => client.readContract({
5261
+ const _meta = params._meta ?? await getBlockMeta({ client });
5262
+ const resolvedBlockNumbers = blockNumbers.map((blockNumber) => blockNumber ?? _meta.blockNumber);
5263
+ const premiaRequests = resolvedBlockNumbers.map((blockNumber) => client.readContract({
5093
5264
  address: panopticPoolAddress,
5094
5265
  abi: panopticPoolV2Abi,
5095
5266
  functionName: "getFullPositionsData",
@@ -5098,18 +5269,36 @@ async function getStreamiaHistory(params) {
5098
5269
  true,
5099
5270
  [tokenId]
5100
5271
  ],
5101
- blockNumber: bn
5272
+ blockNumber
5102
5273
  }));
5103
- const uniswapDataPromise = includeUniswapFees && legs.length > 0 ? fetchUniswapFeeData(client, blockNumbers, legs, poolConfig) : void 0;
5104
- const [premiaResults, uniswapData, _meta] = await Promise.all([
5105
- Promise.all(premiaRequests),
5106
- uniswapDataPromise ?? Promise.resolve(void 0),
5107
- params._meta ? Promise.resolve(params._meta) : getBlockMeta({ client })
5108
- ]);
5109
- const sortedSettled = settledEvents ? [...settledEvents].sort((a, b) => a.blockNumber < b.blockNumber ? -1 : 1) : [];
5274
+ const uniswapDataPromise = includeUniswapFees && legs.length > 0 ? fetchUniswapFeeData(client, resolvedBlockNumbers, legs, poolConfig) : void 0;
5275
+ const [premiaResults, uniswapData] = await Promise.all([Promise.all(premiaRequests), uniswapDataPromise ?? Promise.resolve(void 0)]);
5276
+ const sortedSettled = settledEvents ? [...settledEvents].sort((a, b) => a.blockNumber === b.blockNumber ? 0 : a.blockNumber < b.blockNumber ? -1 : 1) : [];
5110
5277
  let settledIdx = 0;
5111
5278
  let accSettled0 = 0n;
5112
5279
  let accSettled1 = 0n;
5280
+ const cumulativePremiaByInputIndex = Array.from({ length: blockNumbers.length }, () => ({
5281
+ token0: 0n,
5282
+ token1: 0n
5283
+ }));
5284
+ const chronologicalInputs = resolvedBlockNumbers.map((blockNumber, inputIndex) => ({
5285
+ blockNumber,
5286
+ inputIndex
5287
+ })).sort((a, b) => a.blockNumber === b.blockNumber ? a.inputIndex - b.inputIndex : a.blockNumber < b.blockNumber ? -1 : 1);
5288
+ for (const { blockNumber, inputIndex } of chronologicalInputs) {
5289
+ while (settledIdx < sortedSettled.length && sortedSettled[settledIdx].blockNumber <= blockNumber) {
5290
+ accSettled0 += sortedSettled[settledIdx].settled0;
5291
+ accSettled1 += sortedSettled[settledIdx].settled1;
5292
+ settledIdx++;
5293
+ }
5294
+ const result = premiaResults[inputIndex];
5295
+ const premia0 = (result[0] & MASK_128) - (result[1] & MASK_128);
5296
+ const premia1 = (result[0] >> 128n) - (result[1] >> 128n);
5297
+ cumulativePremiaByInputIndex[inputIndex] = {
5298
+ token0: premia0 + accSettled0,
5299
+ token1: premia1 + accSettled1
5300
+ };
5301
+ }
5113
5302
  let initialUniswapFees0 = null;
5114
5303
  let initialUniswapFees1 = null;
5115
5304
  const snapshots = premiaResults.map((result, i) => {
@@ -5120,14 +5309,8 @@ async function getStreamiaHistory(params) {
5120
5309
  const short1 = shortPacked >> 128n;
5121
5310
  const long0 = longPacked & MASK_128;
5122
5311
  const long1 = longPacked >> 128n;
5123
- const effectiveBn = bn ?? BigInt(Number.MAX_SAFE_INTEGER);
5124
- while (settledIdx < sortedSettled.length && sortedSettled[settledIdx].blockNumber <= effectiveBn) {
5125
- accSettled0 += sortedSettled[settledIdx].settled0;
5126
- accSettled1 += sortedSettled[settledIdx].settled1;
5127
- settledIdx++;
5128
- }
5129
- const premia0 = short0 - long0 - accSettled0;
5130
- const premia1 = short1 - long1 - accSettled1;
5312
+ const premia0 = short0 - long0;
5313
+ const premia1 = short1 - long1;
5131
5314
  let uniswapFees0 = 0n;
5132
5315
  let uniswapFees1 = 0n;
5133
5316
  if (uniswapData) {
@@ -5146,6 +5329,7 @@ async function getStreamiaHistory(params) {
5146
5329
  token0: premia0,
5147
5330
  token1: premia1
5148
5331
  },
5332
+ cumulativePanopticPremia: cumulativePremiaByInputIndex[i],
5149
5333
  uniswapFees: {
5150
5334
  token0: uniswapFees0,
5151
5335
  token1: uniswapFees1
@@ -5612,7 +5796,7 @@ const nfpmAbi = [{
5612
5796
  }],
5613
5797
  stateMutability: "payable"
5614
5798
  }];
5615
- const MAX_UINT128 = 2n ** 128n - 1n;
5799
+ const MAX_UINT128$1 = 2n ** 128n - 1n;
5616
5800
  const MAX_UINT256 = 2n ** 256n - 1n;
5617
5801
  const Q128 = 2n ** 128n;
5618
5802
  /**
@@ -5654,8 +5838,8 @@ async function getUniswapV3LpPositionState(params) {
5654
5838
  args: [{
5655
5839
  tokenId,
5656
5840
  recipient: owner,
5657
- amount0Max: MAX_UINT128,
5658
- amount1Max: MAX_UINT128
5841
+ amount0Max: MAX_UINT128$1,
5842
+ amount1Max: MAX_UINT128$1
5659
5843
  }],
5660
5844
  account: owner,
5661
5845
  blockNumber: _meta.blockNumber
@@ -6932,14 +7116,21 @@ const multicallAbi = [{
6932
7116
  * @returns Simulation result with settlement data or error
6933
7117
  */
6934
7118
  async function simulateSettle(params) {
6935
- const { client, poolAddress, account, positionIdList, tokenId, blockNumber } = params;
7119
+ const { client, poolAddress, account, positionIdList, finalPositionIdList, positionSizes: providedSizes, tokenId, blockNumber } = params;
6936
7120
  const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
6937
7121
  const metaPromise = getBlockMeta({
6938
7122
  client,
6939
7123
  blockNumber: targetBlockNumber
6940
7124
  });
6941
7125
  try {
6942
- const positionSizes = positionIdList.map(() => 0n);
7126
+ if (providedSizes && providedSizes.length !== positionIdList.length) throw new PanopticError("simulateSettle: positionSizes length must match positionIdList");
7127
+ const positionSizes = providedSizes ?? await getCurrentPositionSizes({
7128
+ client,
7129
+ poolAddress,
7130
+ account,
7131
+ positionIdList,
7132
+ blockNumber: targetBlockNumber
7133
+ });
6943
7134
  const tickAndSpreadLimits = positionIdList.map(() => [
6944
7135
  -887272n,
6945
7136
  887272n,
@@ -6950,7 +7141,7 @@ async function simulateSettle(params) {
6950
7141
  functionName: "dispatch",
6951
7142
  args: [
6952
7143
  positionIdList,
6953
- positionIdList,
7144
+ finalPositionIdList ?? positionIdList,
6954
7145
  positionSizes.map((s) => BigInt(s)),
6955
7146
  tickAndSpreadLimits.map((t) => [
6956
7147
  Number(t[0]),
@@ -6982,8 +7173,8 @@ async function simulateSettle(params) {
6982
7173
  });
6983
7174
  const _meta = await metaPromise;
6984
7175
  const data = {
6985
- premiaReceived0: tokenFlow.delta0 > 0n ? tokenFlow.delta0 : 0n,
6986
- premiaReceived1: tokenFlow.delta1 > 0n ? tokenFlow.delta1 : 0n,
7176
+ premiaReceived0: tokenFlow.delta0,
7177
+ premiaReceived1: tokenFlow.delta1,
6987
7178
  postCollateral0: tokenFlow.balanceAfter0,
6988
7179
  postCollateral1: tokenFlow.balanceAfter1,
6989
7180
  forfeitAmounts
@@ -7495,7 +7686,7 @@ async function simulateSwapExactIn(params) {
7495
7686
 
7496
7687
  //#endregion
7497
7688
  //#region src/panoptic/v2/simulations/oneTokenFlow.ts
7498
- const BPS_DENOMINATOR = 10000n;
7689
+ const BPS_DENOMINATOR$1 = 10000n;
7499
7690
  /**
7500
7691
  * Default {@link OneTokenFlowQuoteParams.minSwapRatioBps}: 0.5%.
7501
7692
  *
@@ -7515,7 +7706,7 @@ function abs(value) {
7515
7706
  return value < 0n ? -value : value;
7516
7707
  }
7517
7708
  function padForSlippage(amount, slippageBps) {
7518
- return (amount * (BPS_DENOMINATOR + slippageBps) + BPS_DENOMINATOR - 1n) / BPS_DENOMINATOR;
7709
+ return (amount * (BPS_DENOMINATOR$1 + slippageBps) + BPS_DENOMINATOR$1 - 1n) / BPS_DENOMINATOR$1;
7519
7710
  }
7520
7711
  /**
7521
7712
  * Quote a dispatch wrapped so its net flow lands in `targetTokenIndex` only.
@@ -7535,10 +7726,10 @@ async function quoteOneTokenFlow(params) {
7535
7726
  reason: "invalid-target-token",
7536
7727
  detail: `targetTokenIndex=${targetTokenIndex} is neither 0 nor 1`
7537
7728
  };
7538
- if (params.slippageBps < 0n || params.slippageBps > BPS_DENOMINATOR) return {
7729
+ if (params.slippageBps < 0n || params.slippageBps > BPS_DENOMINATOR$1) return {
7539
7730
  available: false,
7540
7731
  reason: "invalid-slippage",
7541
- detail: `slippageBps=${params.slippageBps} is outside [0, ${BPS_DENOMINATOR}]`
7732
+ detail: `slippageBps=${params.slippageBps} is outside [0, ${BPS_DENOMINATOR$1}]`
7542
7733
  };
7543
7734
  const tickLimitLow = params.tickLimitLow ?? MIN_TICK;
7544
7735
  const tickLimitHigh = params.tickLimitHigh ?? MAX_TICK;
@@ -7646,7 +7837,7 @@ async function quoteOneTokenFlow(params) {
7646
7837
  }
7647
7838
  if (baseTargetDelta !== null && minSwapRatioBps > 0n) {
7648
7839
  const swapInTargetTerms = convertToTokenIndex(swapAmount, otherTokenIndex, targetTokenIndex, pool.sqrtPriceX96);
7649
- if (swapInTargetTerms * BPS_DENOMINATOR < minSwapRatioBps * abs(baseTargetDelta)) return {
7840
+ if (swapInTargetTerms * BPS_DENOMINATOR$1 < minSwapRatioBps * abs(baseTargetDelta)) return {
7650
7841
  available: false,
7651
7842
  reason: "below-threshold",
7652
7843
  detail: `non-target flow ${swapInTargetTerms} (in target token terms) is below ${minSwapRatioBps}bps of the target flow ${abs(baseTargetDelta)}`
@@ -7738,6 +7929,200 @@ async function quoteOneTokenFlow(params) {
7738
7929
  };
7739
7930
  }
7740
7931
 
7932
+ //#endregion
7933
+ //#region src/panoptic/v2/simulations/temporaryLoanRecovery.ts
7934
+ const BPS_DENOMINATOR = 10000n;
7935
+ const MAX_RECOVERY_ATTEMPTS = 8n;
7936
+ const MAX_UINT128 = (1n << 128n) - 1n;
7937
+ const LOAN_GROWTH_DENOMINATOR = 20n;
7938
+ /**
7939
+ * Wrap a dispatch with `loan mint -> user operations -> swapped loan burn`.
7940
+ * The repeated tokenId is intentional: the first occurrence mints it and the
7941
+ * last occurrence burns it after the user's operations have settled.
7942
+ */
7943
+ function buildTemporaryLoanRecoveryDispatch(params) {
7944
+ const low = params.tickLimitLow <= params.tickLimitHigh ? params.tickLimitLow : params.tickLimitHigh;
7945
+ const high = params.tickLimitLow <= params.tickLimitHigh ? params.tickLimitHigh : params.tickLimitLow;
7946
+ return {
7947
+ positionIdList: [
7948
+ params.loanTokenId,
7949
+ ...params.dispatch.positionIdList,
7950
+ params.loanTokenId
7951
+ ],
7952
+ finalPositionIdList: [...params.dispatch.finalPositionIdList],
7953
+ positionSizes: [
7954
+ params.loanPositionSize,
7955
+ ...params.dispatch.positionSizes,
7956
+ 0n
7957
+ ],
7958
+ tickAndSpreadLimits: [
7959
+ [
7960
+ low,
7961
+ high,
7962
+ 0n
7963
+ ],
7964
+ ...params.dispatch.tickAndSpreadLimits,
7965
+ [
7966
+ high,
7967
+ low,
7968
+ 0n
7969
+ ]
7970
+ ],
7971
+ usePremiaAsCollateral: params.dispatch.usePremiaAsCollateral,
7972
+ builderCode: params.dispatch.builderCode
7973
+ };
7974
+ }
7975
+ /**
7976
+ * Quotes and simulates an atomic temporary loan around a full-close dispatch.
7977
+ *
7978
+ * @param params - Chain client, account, failed dispatch, shortfall error, and quote limits.
7979
+ * @returns An executable quote when recovery succeeds, otherwise a categorized unavailable result.
7980
+ * @throws {PanopticError} When the dispatch is not a full close or required RPC reads fail.
7981
+ */
7982
+ async function quoteTemporaryLoanRecovery(params) {
7983
+ const initialShortfall = getNotEnoughTokensError(params.error);
7984
+ if (initialShortfall === null) return {
7985
+ available: false,
7986
+ reason: "not-token-shortfall"
7987
+ };
7988
+ let loanAmount = initialShortfall.assetsRequested - initialShortfall.assetBalance;
7989
+ if (loanAmount <= 0n) return {
7990
+ available: false,
7991
+ reason: "invalid-shortfall",
7992
+ detail: `requested=${initialShortfall.assetsRequested} <= balance=${initialShortfall.assetBalance}`
7993
+ };
7994
+ if (params.slippageBps <= 0n || params.slippageBps > BPS_DENOMINATOR) return {
7995
+ available: false,
7996
+ reason: "invalid-slippage",
7997
+ detail: `slippageBps=${params.slippageBps} is outside (0, ${BPS_DENOMINATOR}]`
7998
+ };
7999
+ if (params.dispatch.finalPositionIdList.length !== 0) throw new PanopticError("Temporary-loan recovery requires a full-close dispatch with an empty finalPositionIdList");
8000
+ let targetBlockNumber;
8001
+ try {
8002
+ targetBlockNumber = params.blockNumber ?? await params.client.getBlockNumber();
8003
+ } catch (error) {
8004
+ if (error instanceof PanopticError) throw error;
8005
+ throw new PanopticError("Failed to resolve the block for temporary-loan recovery", error instanceof Error ? error : new Error(String(error)));
8006
+ }
8007
+ let pool;
8008
+ try {
8009
+ pool = await getPool({
8010
+ client: params.client,
8011
+ poolAddress: params.poolAddress,
8012
+ chainId: params.chainId,
8013
+ blockNumber: targetBlockNumber
8014
+ });
8015
+ } catch (error) {
8016
+ if (error instanceof PanopticError) throw error;
8017
+ throw new PanopticError("Failed to load the pool for temporary-loan recovery", error instanceof Error ? error : new Error(String(error)));
8018
+ }
8019
+ const defaultLimits = tickLimits(pool.currentTick, params.slippageBps);
8020
+ const tickLimitLow = params.tickLimitLow ?? defaultLimits.low;
8021
+ const tickLimitHigh = params.tickLimitHigh ?? defaultLimits.high;
8022
+ if (tickLimitLow >= tickLimitHigh) return {
8023
+ available: false,
8024
+ reason: "invalid-tick-limits",
8025
+ detail: `tickLimitLow=${tickLimitLow} >= tickLimitHigh=${tickLimitHigh}`
8026
+ };
8027
+ const token0 = pool.collateralTracker0.token;
8028
+ const token1 = pool.collateralTracker1.token;
8029
+ const tokenIndexFor = (address) => {
8030
+ const normalized = address.toLowerCase();
8031
+ if (normalized === token0.toLowerCase() || normalized === pool.collateralTracker0.address.toLowerCase()) return 0n;
8032
+ if (normalized === token1.toLowerCase() || normalized === pool.collateralTracker1.address.toLowerCase()) return 1n;
8033
+ return null;
8034
+ };
8035
+ const loanTokenIndex = tokenIndexFor(initialShortfall.tokenAddress);
8036
+ if (loanTokenIndex === null) return {
8037
+ available: false,
8038
+ reason: "unsupported-token",
8039
+ detail: `${initialShortfall.tokenAddress} is neither collateral token of ${params.poolAddress}`
8040
+ };
8041
+ const repaymentTokenIndex = loanTokenIndex === 0n ? 1n : 0n;
8042
+ const loanToken = loanTokenIndex === 0n ? token0 : token1;
8043
+ const repaymentToken = repaymentTokenIndex === 0n ? token0 : token1;
8044
+ const collisionIds = Array.from(new Set([
8045
+ ...params.existingPositionIds,
8046
+ ...params.dispatch.positionIdList,
8047
+ ...params.dispatch.finalPositionIdList
8048
+ ]));
8049
+ for (let attempt = 0n; attempt < MAX_RECOVERY_ATTEMPTS; attempt += 1n) {
8050
+ if (loanAmount > MAX_UINT128) return {
8051
+ available: false,
8052
+ reason: "recovery-unavailable",
8053
+ detail: `required loan amount ${loanAmount} exceeds uint128`
8054
+ };
8055
+ const loan = buildUniqueLoan(pool.poolId, loanTokenIndex, loanTokenIndex, pool.currentTick, pool.tickSpacing, collisionIds, loanAmount);
8056
+ const recoveredDispatch = buildTemporaryLoanRecoveryDispatch({
8057
+ dispatch: params.dispatch,
8058
+ loanTokenId: loan.tokenId,
8059
+ loanPositionSize: loan.adjustedSize,
8060
+ tickLimitLow,
8061
+ tickLimitHigh
8062
+ });
8063
+ const simulation = await simulateDispatch({
8064
+ client: params.client,
8065
+ poolAddress: params.poolAddress,
8066
+ account: params.account,
8067
+ existingPositionIdList: params.existingPositionIds,
8068
+ ...recoveredDispatch,
8069
+ blockNumber: targetBlockNumber
8070
+ });
8071
+ if (simulation.success && simulation.tokenFlow !== void 0) {
8072
+ const tokenFlow = simulation.tokenFlow;
8073
+ return {
8074
+ available: true,
8075
+ quote: {
8076
+ loanToken,
8077
+ repaymentToken,
8078
+ loanTokenIndex,
8079
+ loanAmount,
8080
+ loanPositionSize: loan.adjustedSize,
8081
+ loanTokenId: loan.tokenId,
8082
+ slippageBps: params.slippageBps,
8083
+ netLoanTokenChange: loanTokenIndex === 0n ? tokenFlow.delta0 : tokenFlow.delta1,
8084
+ netRepaymentTokenChange: repaymentTokenIndex === 0n ? tokenFlow.delta0 : tokenFlow.delta1,
8085
+ dispatch: recoveredDispatch,
8086
+ simulation: {
8087
+ ...simulation,
8088
+ tokenFlow
8089
+ },
8090
+ tokenFlow,
8091
+ _meta: simulation._meta
8092
+ }
8093
+ };
8094
+ }
8095
+ if (simulation.success) return {
8096
+ available: false,
8097
+ reason: "recovery-unavailable",
8098
+ detail: "temporary-loan simulation returned no token flow"
8099
+ };
8100
+ const shortfall = getNotEnoughTokensError(simulation.error);
8101
+ if (shortfall === null) return {
8102
+ available: false,
8103
+ reason: "recovery-unavailable",
8104
+ detail: `temporary-loan dispatch reverted: ${simulation.error.message}`,
8105
+ error: simulation.error
8106
+ };
8107
+ const shortfallIndex = tokenIndexFor(shortfall.tokenAddress);
8108
+ if (shortfallIndex !== loanTokenIndex) return {
8109
+ available: false,
8110
+ reason: "repayment-token-shortfall",
8111
+ detail: `repayment token ${shortfall.tokenAddress} requested ${shortfall.assetsRequested}, balance ${shortfall.assetBalance}`,
8112
+ error: simulation.error
8113
+ };
8114
+ const residual = shortfall.assetsRequested - shortfall.assetBalance;
8115
+ const geometricGrowth = (loanAmount + LOAN_GROWTH_DENOMINATOR - 1n) / LOAN_GROWTH_DENOMINATOR;
8116
+ loanAmount += residual > geometricGrowth ? residual : geometricGrowth;
8117
+ }
8118
+ return {
8119
+ available: false,
8120
+ reason: "recovery-unavailable",
8121
+ detail: `temporary-loan recovery remained short after ${MAX_RECOVERY_ATTEMPTS} attempts`,
8122
+ error: new PanopticError("Could not size the temporary loan within the quote attempt limit")
8123
+ };
8124
+ }
8125
+
7741
8126
  //#endregion
7742
8127
  //#region src/panoptic/v2/abis/poolManager.ts
7743
8128
  /**
@@ -9100,4 +9485,4 @@ function isGasError(error) {
9100
9485
  }
9101
9486
 
9102
9487
  //#endregion
9103
- export { DEFAULT_MIN_SWAP_RATIO_BPS, DEFAULT_RECONNECT_CONFIG, REQUIRED_BASE_ERROR_SENTINEL, addPendingPosition, addTrackedChunks, apportion, assertCanBurn, assertCanForceExercise, assertCanLiquidate, assertCanMint, assertFresh, assertHealthy, assertTradeable, buildCreditWrappedDispatch, buildSfpmSwapCalldata, buildSfpmSwapPlan, buildTokenShortfallRecoveryDispatch, calculateAccountGreeksPure, calculateSpreadWad, checkCollateralAcrossTicks, classifyStrategyGroups, cleanupStalePendingPositions, clearPendingPositions, clearTrackedChunks, clearTradeHistory, collateralRuleKindFor, computeV4PoolId, confirmPendingPosition, convertToAssets, convertToShares, createEventPoller, createEventSubscription, createFlowNeutralTokenId, createPoolFormatters, decodePanopticTokenURI, encodePoolKeyBytes, encodeV3PoolKeyBytes, ensureSfpmV3PoolInitialized, estimateBlockNumbers, estimateCollateralBreakdown, estimateCollateralRequired, failPendingPosition, feesFromFeeGrowthDelta, fetchSfpmV3PoolId, formatBlockNumber, formatBps, formatCompact, formatDatetime, formatDuration, formatDurationSeconds, formatFeeTier, formatGas, formatGwei, formatPoolIdHex, formatRatioPercent, formatTimestamp, formatTimestampLocale, formatTokenIdHex, formatTokenIdShort, formatTxHash, formatUtilization, formatWei, getAccountBuyingPower, getAccountGreeks, getAccountHistory, getAccountPremia, getChunkLiquidities, getChunkSpreads, getClosedPositions, getCollateralSharePrices, getCollateralTotalAssetsBatch, getDeltaHedgeParams, getEnforcedTickLimits, getFactoryConstructMetadata, getFactoryOwnerOf, getFactoryTokenURI, getGuardianUnlockState, getItmAmounts, getMarginBuffer, getMaxPositionSize, getMaxRedeem, getMaxWithdrawable, getNativeTokenPrice, getNotEnoughTokensError, getOpenPositionPreview, getPanopticPoolAddress, getPanopticPoolFromPoolId, getPendingPositions, getPoolDisplayId, getPoolLiquidities, getPortfolioValue, getPositionChunkData, getPositionEnrichmentData, getPositionsWithPremia, getPriceHistory, getRealizedPnL, getRequiredCreditForITM, getSafeMode, getStreamiaHistory, getSyncStatus, getTokenListId, getTrackedChunks, getTradeHistory, getUniswapFeeHistory, getUniswapV3LpPositionState, getUniswapV3PoolFromId, getUniswapV3PoolInfo, getUniswapV3PoolLiquidities, getUniswapV4LpPositionState, getUniswapV4PoolBasicState, getUniswapV4PoolInfo, getUniswapV4PoolKeyFromId, getUniswapV4PoolLiquidities, interpolateBlocks, isGasError, isNonceError, isRetryableRpcError, isolateGroupTokenId, minePoolAddress, minePoolAddressLocalAsync, multicallRead, optimizeTokenIdRiskPartners, parseBps, parseCollateralLog, parsePoolLog, parseTokenListId, previewDeposit, previewMint, previewRedeem, previewWithdraw, quoteOneTokenFlow, quoteSfpmSwap, quoteTokenShortfallRecovery, removeTrackedChunks, resolveBlockNumbers, resolvePanopticPoolFromPoolId, resolveUniswapV4PoolKey, saveClosedPosition, scanChunks, simulateBatchDispatch, simulateClosePosition, simulateDeployNewPool, simulateDeposit, simulateDispatch, simulateForceExercise, simulateLiquidate, simulateSFPMBurn, simulateSFPMMint, simulateSettle, simulateSwapExactIn, simulateSwapExactOut, simulateWithdraw, slippageBpsToTickDistance, truncateAddress, watchEvents };
9488
+ export { DEFAULT_MIN_SWAP_RATIO_BPS, DEFAULT_RECONNECT_CONFIG, REQUIRED_BASE_ERROR_SENTINEL, addPendingPosition, addTrackedChunks, apportion, assertCanBurn, assertCanForceExercise, assertCanLiquidate, assertCanMint, assertFresh, assertHealthy, assertTradeable, buildCreditWrappedDispatch, buildSfpmSwapCalldata, buildSfpmSwapPlan, buildTemporaryLoanRecoveryDispatch, buildTokenShortfallRecoveryDispatch, calculateAccountGreeksPure, calculateSpreadWad, checkCollateralAcrossTicks, classifyStrategyGroups, cleanupStalePendingPositions, clearPendingPositions, clearTrackedChunks, clearTradeHistory, collateralRuleKindFor, computeV4PoolId, confirmPendingPosition, convertToAssets, convertToShares, createEventPoller, createEventSubscription, createFlowNeutralTokenId, createPoolFormatters, decodePanopticTokenURI, deriveUniqueTokenId, encodePoolKeyBytes, encodeV3PoolKeyBytes, ensureSfpmV3PoolInitialized, estimateBlockNumbers, estimateCollateralBreakdown, estimateCollateralRequired, failPendingPosition, feesFromFeeGrowthDelta, fetchSfpmV3PoolId, formatBlockNumber, formatBps, formatCompact, formatDatetime, formatDuration, formatDurationSeconds, formatFeeTier, formatGas, formatGwei, formatPoolIdHex, formatRatioPercent, formatTimestamp, formatTimestampLocale, formatTokenIdHex, formatTokenIdShort, formatTxHash, formatUtilization, formatWei, getAccountBuyingPower, getAccountGreeks, getAccountHistory, getAccountPremia, getChunkLiquidities, getChunkSpreads, getClosedPositions, getCollateralSharePrices, getCollateralTotalAssetsBatch, getDeltaHedgeParams, getEnforcedTickLimits, getFactoryConstructMetadata, getFactoryOwnerOf, getFactoryTokenURI, getGuardianUnlockState, getItmAmounts, getMarginBuffer, getMaxPositionSize, getMaxRedeem, getMaxWithdrawable, getNativeTokenPrice, getNotEnoughTokensError, getOpenPositionPreview, getPanopticPoolAddress, getPanopticPoolFromPoolId, getPendingPositions, getPoolDisplayId, getPoolLiquidities, getPortfolioValue, getPositionChunkData, getPositionEnrichmentData, getPositionsWithPremia, getPriceHistory, getRealizedPnL, getRequiredCreditForITM, getSafeMode, getStreamiaHistory, getSyncStatus, getTokenListId, getTrackedChunks, getTradeHistory, getUniswapFeeHistory, getUniswapV3LpPositionState, getUniswapV3PoolFromId, getUniswapV3PoolInfo, getUniswapV3PoolLiquidities, getUniswapV4LpPositionState, getUniswapV4PoolBasicState, getUniswapV4PoolInfo, getUniswapV4PoolKeyFromId, getUniswapV4PoolLiquidities, interpolateBlocks, isGasError, isNonceError, isRetryableRpcError, isolateGroupTokenId, minePoolAddress, minePoolAddressLocalAsync, multicallRead, optimizeTokenIdRiskPartners, parseBps, parseCollateralLog, parsePoolLog, parseTokenListId, planDeriveStrategy, previewDeposit, previewMint, previewRedeem, previewWithdraw, quoteOneTokenFlow, quoteSfpmSwap, quoteTemporaryLoanRecovery, quoteTokenShortfallRecovery, removeTrackedChunks, resolveBlockNumbers, resolvePanopticPoolFromPoolId, resolveUniswapV4PoolKey, saveClosedPosition, scanChunks, simulateBatchDispatch, simulateClosePosition, simulateDeployNewPool, simulateDeposit, simulateDispatch, simulateForceExercise, simulateLiquidate, simulateSFPMBurn, simulateSFPMMint, simulateSettle, simulateSwapExactIn, simulateSwapExactOut, simulateWithdraw, slippageBpsToTickDistance, truncateAddress, watchEvents };