@panoptic-eng/sdk 1.0.68 → 1.0.70

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 (34) hide show
  1. package/dist/cow/index.js +47 -2
  2. package/dist/cow/index.js.map +1 -1
  3. package/dist/{cow-CGgPXhY6.js → cow-sGuN0eas.js} +1 -1
  4. package/dist/{greeks-CGtgLUyh.js → greeks-DNPP24KL.js} +115 -9
  5. package/dist/index.d.ts +67 -25
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +161 -62
  8. package/dist/index.js.map +1 -1
  9. package/dist/{irm-BDxwCFDm.js → irm-6RzXXa1_.js} +927 -3
  10. package/dist/panoptic/v2/greeks/index.d.ts +7 -4
  11. package/dist/panoptic/v2/greeks/index.d.ts.map +1 -1
  12. package/dist/panoptic/v2/greeks/index.js +74 -7
  13. package/dist/panoptic/v2/greeks/index.js.map +1 -1
  14. package/dist/panoptic/v2/index.d.ts +244 -6
  15. package/dist/panoptic/v2/index.d.ts.map +1 -1
  16. package/dist/panoptic/v2/index.js +2554 -464
  17. package/dist/panoptic/v2/index.js.map +1 -1
  18. package/dist/panoptic/v2/react-public.d.ts +258 -9
  19. package/dist/panoptic/v2/react-public.d.ts.map +1 -1
  20. package/dist/panoptic/v2/react-public.js +4655 -2909
  21. package/dist/panoptic/v2/react-public.js.map +1 -1
  22. package/dist/{providers-DubVMHWU.js → providers-CbcNt27n.js} +2 -1
  23. package/dist/{rates-BHS-Qiu7.js → rates-DDK4ZimJ.js} +40 -4
  24. package/dist/{router-BW6TqwOO.js → router-njWsLvZc.js} +969 -39
  25. package/dist/rpc/index.d.ts +12 -1
  26. package/dist/rpc/index.d.ts.map +1 -1
  27. package/dist/rpc/index.js +65 -5
  28. package/dist/rpc/index.js.map +1 -1
  29. package/dist/uniswap/index.js +53 -13
  30. package/dist/uniswap/index.js.map +1 -1
  31. package/dist/{v2-Dgh6JxG_.js → v2-BrG4T_Gh.js} +681 -32
  32. package/dist/{writes-CG612Vuk.js → writes-CI6Haer-.js} +34 -3
  33. package/package.json +1 -1
  34. package/dist/router-IDtCENST.js +0 -942
@@ -1,4 +1,4 @@
1
- import { BaseError, ContractFunctionExecutionError, ContractFunctionRevertedError, ExecutionRevertedError, decodeAbiParameters, decodeErrorResult, decodeEventLog, decodeFunctionData, decodeFunctionResult, encodeAbiParameters, encodeFunctionData, erc20Abi, getAbiItem, getAddress, hexToString, keccak256, parseAbi, parseEventLogs, toFunctionSelector, toHex, trim, zeroAddress } from "viem";
1
+ import { BaseError, ContractFunctionExecutionError, ContractFunctionRevertedError, ExecutionRevertedError, decodeAbiParameters, decodeErrorResult, decodeEventLog, decodeFunctionData, decodeFunctionResult, encodeAbiParameters, encodeFunctionData, erc20Abi, getAbiItem, getAddress, hexToString, isAddress, isAddressEqual, isHex, keccak256, parseAbi, parseEventLogs, toFunctionSelector, toHex, trim, zeroAddress } from "viem";
2
2
  import { call, multicall } from "viem/actions";
3
3
  import Decimal from "decimal.js";
4
4
 
@@ -94,7 +94,7 @@ const UTILIZATION_DENOMINATOR = 10000n;
94
94
 
95
95
  //#endregion
96
96
  //#region src/panoptic/v2/formatters/tick.ts
97
- const Q192$6 = 1n << 192n;
97
+ const Q192$8 = 1n << 192n;
98
98
  const RAW_PRICE_PRECISION = 40n;
99
99
  function pow10$2(exponent) {
100
100
  if (exponent < 0n) throw new RangeError("Exponent must be non-negative");
@@ -184,7 +184,7 @@ const MAX_SQRT_PRICE_X96 = tickToSqrtPriceX96(MAX_TICK);
184
184
  function getPriceRatioFromSqrtPriceX96(sqrtPriceX96) {
185
185
  return {
186
186
  numerator: sqrtPriceX96 * sqrtPriceX96,
187
- denominator: Q192$6
187
+ denominator: Q192$8
188
188
  };
189
189
  }
190
190
  function getRawPriceRatio(tick) {
@@ -586,6 +586,9 @@ var NotMarginCalledError = class extends PanopticError {
586
586
  */
587
587
  var NotEnoughTokensError = class extends PanopticError {
588
588
  name = "NotEnoughTokensError";
589
+ get deficit() {
590
+ return this.assetsRequested > this.assetBalance ? this.assetsRequested - this.assetBalance : 0n;
591
+ }
589
592
  constructor(tokenAddress, assetsRequested, assetBalance, cause) {
590
593
  super(`Not enough tokens: requested=${assetsRequested}, balance=${assetBalance}, token=${tokenAddress}`, cause);
591
594
  this.tokenAddress = tokenAddress;
@@ -9079,6 +9082,39 @@ const panopticErrorsAbi = [
9079
9082
  }
9080
9083
  ]
9081
9084
  },
9085
+ {
9086
+ type: "error",
9087
+ name: "NotEnoughTokens",
9088
+ inputs: [
9089
+ {
9090
+ name: "tokenAddress",
9091
+ type: "address"
9092
+ },
9093
+ {
9094
+ name: "account",
9095
+ type: "address"
9096
+ },
9097
+ {
9098
+ name: "assetsRequested",
9099
+ type: "uint256"
9100
+ },
9101
+ {
9102
+ name: "assetBalance",
9103
+ type: "uint256"
9104
+ }
9105
+ ]
9106
+ },
9107
+ {
9108
+ type: "error",
9109
+ name: "ExecuteError",
9110
+ inputs: [{
9111
+ name: "callIndex",
9112
+ type: "uint256"
9113
+ }, {
9114
+ name: "revertData",
9115
+ type: "bytes"
9116
+ }]
9117
+ },
9082
9118
  {
9083
9119
  type: "error",
9084
9120
  name: "NotGuardian",
@@ -9220,7 +9256,7 @@ const errorConstructors = {
9220
9256
  AccountInsolvent: (args, cause) => new AccountInsolventError(args[0], args[1], cause),
9221
9257
  NotMarginCalled: (_args, cause) => new NotMarginCalledError(cause),
9222
9258
  CreateFail: (_args, cause) => new CreateFailError(cause),
9223
- NotEnoughTokens: (args, cause) => new NotEnoughTokensError(args[0], args[1], args[2], cause),
9259
+ NotEnoughTokens: (args, cause) => new NotEnoughTokensError(args[0], args[args.length === 4 ? 2 : 1], args[args.length === 4 ? 3 : 2], cause),
9224
9260
  NotEnoughLiquidityInChunk: (_args, cause) => new NotEnoughLiquidityInChunkError(cause),
9225
9261
  InsufficientCreditLiquidity: (_args, cause) => new InsufficientCreditLiquidityError(cause),
9226
9262
  DepositTooLarge: (_args, cause) => new DepositTooLargeError(cause),
@@ -10032,7 +10068,7 @@ function hasLoanOrCredit(tokenId) {
10032
10068
  const POOL_ID_MASK$4 = (1n << 64n) - 1n;
10033
10069
  const MAX_LEGS = TOKEN_ID_BITS.MAX_LEGS;
10034
10070
  const MAX_OPTION_RATIO = LEG_LIMITS.MAX_RATIO;
10035
- const Q192$5 = 1n << 192n;
10071
+ const Q192$7 = 1n << 192n;
10036
10072
  /**
10037
10073
  * Floor integer square root for bigints (Newton's method). Mirrors the isqrt
10038
10074
  * used in reads/collateralEstimate.ts (buildNeutralLeg).
@@ -10079,7 +10115,7 @@ function computeTinyCreditSignedStrike(positionSize, tickSpacing) {
10079
10115
  const maxSafe = MAX_TICK - tickSpacing - 1n;
10080
10116
  let signedStrike;
10081
10117
  try {
10082
- const sqrtKrawX96 = isqrt$1(TINY_CREDIT_TARGET_NOTIONAL_WEI * Q192$5 / positionSize);
10118
+ const sqrtKrawX96 = isqrt$1(TINY_CREDIT_TARGET_NOTIONAL_WEI * Q192$7 / positionSize);
10083
10119
  signedStrike = sqrtPriceX96ToTick(sqrtKrawX96);
10084
10120
  } catch {
10085
10121
  signedStrike = minSafe;
@@ -10951,7 +10987,7 @@ function formatGwei(wei, precision) {
10951
10987
  //#region src/panoptic/v2/tokenId/generateOverlapping.ts
10952
10988
  const MAX_UINT64$2 = (1n << 64n) - 1n;
10953
10989
  const MAX_UINT128$4 = (1n << 128n) - 1n;
10954
- const Q192$4 = 1n << 192n;
10990
+ const Q192$6 = 1n << 192n;
10955
10991
  const MAX_TOKEN_DECIMALS = 255n;
10956
10992
  const MAX_DECIMAL_EXPONENT = 512n;
10957
10993
  function invalid$1(message) {
@@ -10997,7 +11033,7 @@ function quotePriceAtTick(tick, asset, assetDecimals, quoteDecimals) {
10997
11033
  const orientedTick = asset === 0n ? tick : -tick;
10998
11034
  const sqrtPriceX96 = tickToSqrtPriceX96(orientedTick);
10999
11035
  let numerator = sqrtPriceX96 * sqrtPriceX96;
11000
- let denominator = Q192$4;
11036
+ let denominator = Q192$6;
11001
11037
  const decimalDifference = assetDecimals - quoteDecimals;
11002
11038
  if (decimalDifference > 0n) numerator *= pow10$1(decimalDifference);
11003
11039
  else if (decimalDifference < 0n) denominator *= pow10$1(-decimalDifference);
@@ -11017,7 +11053,7 @@ function isPriceGridStrike(strike, params, spacing, tickSpacing) {
11017
11053
  }
11018
11054
  return false;
11019
11055
  }
11020
- function ceilDiv$5(value, divisor) {
11056
+ function ceilDiv$6(value, divisor) {
11021
11057
  const quotient = value / divisor;
11022
11058
  const remainder = value % divisor;
11023
11059
  return remainder > 0n ? quotient + 1n : quotient;
@@ -11050,7 +11086,7 @@ function resolveLegs(legs) {
11050
11086
  function getCandidateStrikes(params, spacing, tickSpacing, halfWidth) {
11051
11087
  const lower = MIN_TICK + halfWidth > params.currentTick - halfWidth + 1n ? MIN_TICK + halfWidth : params.currentTick - halfWidth + 1n;
11052
11088
  const upper = MAX_TICK - halfWidth < params.currentTick + halfWidth - 1n ? MAX_TICK - halfWidth : params.currentTick + halfWidth - 1n;
11053
- const firstStrike = ceilDiv$5(lower, tickSpacing) * tickSpacing;
11089
+ const firstStrike = ceilDiv$6(lower, tickSpacing) * tickSpacing;
11054
11090
  const lastStrike = floorDiv$1(upper, tickSpacing) * tickSpacing;
11055
11091
  const strikes = [];
11056
11092
  for (let strike = firstStrike; strike <= lastStrike; strike += tickSpacing) if (isPriceGridStrike(strike, params, spacing, tickSpacing)) strikes.push(strike);
@@ -11272,10 +11308,41 @@ function splitTokenIdByTimescale(tokenId, positionSize, targetTimescale) {
11272
11308
  };
11273
11309
  }
11274
11310
 
11311
+ //#endregion
11312
+ //#region src/panoptic/v2/tokenId/validate.ts
11313
+ /**
11314
+ * Validate a TokenId's structure using the rules of TokenId.validate.
11315
+ * This does not check pool registration, available liquidity, or account collateral.
11316
+ */
11317
+ function getTokenIdValidationError(tokenId) {
11318
+ if (tokenId < 0n || tokenId >= 1n << 256n) return "Token ID must fit in uint256.";
11319
+ const legs = [];
11320
+ for (let index = 0n; index < TOKEN_ID_BITS.MAX_LEGS; index++) {
11321
+ const leg = decodeLeg(tokenId, index);
11322
+ if (leg.optionRatio === 0n) {
11323
+ const offset = TOKEN_ID_BITS.POOL_ID_SIZE + index * TOKEN_ID_BITS.LEG_SIZE;
11324
+ if (tokenId >> offset !== 0n) return "Position contains empty or non-contiguous legs.";
11325
+ break;
11326
+ }
11327
+ legs.push(leg);
11328
+ }
11329
+ if (legs.length === 0) return "Position must contain at least one leg.";
11330
+ const chunks = new Set();
11331
+ for (const leg of legs) {
11332
+ const chunk = `${leg.strike}:${leg.width}:${leg.tokenType}`;
11333
+ if (chunks.has(chunk)) return "Position contains duplicate legs sharing the same liquidity chunk.";
11334
+ chunks.add(chunk);
11335
+ if (leg.strike <= -887272n || leg.strike >= 887272n) return "Position strike must be inside the pool tick bounds.";
11336
+ const partner = legs[Number(leg.riskPartner)];
11337
+ if (!partner || partner.riskPartner !== leg.index) return "Position risk partners must reference existing legs and be mutual.";
11338
+ }
11339
+ return null;
11340
+ }
11341
+
11275
11342
  //#endregion
11276
11343
  //#region src/uniswap/lpDeposit.ts
11277
- const Q96$3 = 1n << 96n;
11278
- const ceilDiv$4 = (n, d) => (n + d - 1n) / d;
11344
+ const Q96$6 = 1n << 96n;
11345
+ const ceilDiv$5 = (n, d) => (n + d - 1n) / d;
11279
11346
  /** Principal and separately identified funding headroom, in native token units. */
11280
11347
  function getLpDepositBreakdown(ranges, sqrtPriceX96) {
11281
11348
  if (sqrtPriceX96 <= 0n) throw new Error("Invalid pool price");
@@ -11286,12 +11353,12 @@ function getLpDepositBreakdown(ranges, sqrtPriceX96) {
11286
11353
  const lower = tickToSqrtPriceX96(BigInt(tickLower));
11287
11354
  const upper = tickToSqrtPriceX96(BigInt(tickUpper));
11288
11355
  const price = sqrtPriceX96 < lower ? lower : sqrtPriceX96 > upper ? upper : sqrtPriceX96;
11289
- amount0 += ceilDiv$4(liquidity * Q96$3 * (upper - price), upper * price);
11290
- amount1 += ceilDiv$4(liquidity * (price - lower), Q96$3);
11356
+ amount0 += ceilDiv$5(liquidity * Q96$6 * (upper - price), upper * price);
11357
+ amount1 += ceilDiv$5(liquidity * (price - lower), Q96$6);
11291
11358
  }
11292
11359
  const buffer = {
11293
- amount0: ceilDiv$4(amount0 * 5n, 100n),
11294
- amount1: ceilDiv$4(amount1 * 5n, 100n)
11360
+ amount0: ceilDiv$5(amount0 * 5n, 100n),
11361
+ amount1: ceilDiv$5(amount1 * 5n, 100n)
11295
11362
  };
11296
11363
  return {
11297
11364
  principal: {
@@ -11315,7 +11382,7 @@ function getUnhedgedLpRanges({ tokenId, positionSize, tickSpacing }) {
11315
11382
  const lower = tickToSqrtPriceX96(tickLower);
11316
11383
  const upper = tickToSqrtPriceX96(tickUpper);
11317
11384
  const amount = positionSize * leg.optionRatio;
11318
- const liquidity = leg.asset === 0n ? amount * (lower * upper / Q96$3) / (upper - lower) : amount * Q96$3 / (upper - lower);
11385
+ const liquidity = leg.asset === 0n ? amount * (lower * upper / Q96$6) / (upper - lower) : amount * Q96$6 / (upper - lower);
11319
11386
  return liquidity <= 0n ? [] : [{
11320
11387
  tickLower: Number(tickLower),
11321
11388
  tickUpper: Number(tickUpper),
@@ -11336,7 +11403,7 @@ function getLpPositionFunding(params) {
11336
11403
  });
11337
11404
  const breakdown = getLpDepositBreakdown(ranges, sqrtPriceX96);
11338
11405
  const priceSquared = valuationSqrtPriceX96 * valuationSqrtPriceX96;
11339
- const value = ({ amount0, amount1 }) => quoteTokenIndex === 0 ? amount0 + ceilDiv$4(amount1 * Q96$3 * Q96$3, priceSquared) : amount1 + ceilDiv$4(amount0 * priceSquared, Q96$3 * Q96$3);
11406
+ const value = ({ amount0, amount1 }) => quoteTokenIndex === 0 ? amount0 + ceilDiv$5(amount1 * Q96$6 * Q96$6, priceSquared) : amount1 + ceilDiv$5(amount0 * priceSquared, Q96$6 * Q96$6);
11340
11407
  const principalInQuote = value(breakdown.principal);
11341
11408
  const totalInQuote = value(breakdown.total);
11342
11409
  return {
@@ -11358,7 +11425,7 @@ function getMaxLpPositionSize(params) {
11358
11425
  ...params,
11359
11426
  positionSize: mid
11360
11427
  });
11361
- const minimum = params.minimumRequirement ? ceilDiv$4(params.minimumRequirement.requiredInQuote * mid, params.minimumRequirement.referenceSize) : 0n;
11428
+ const minimum = params.minimumRequirement ? ceilDiv$5(params.minimumRequirement.requiredInQuote * mid, params.minimumRequirement.referenceSize) : 0n;
11362
11429
  if (funding.totalInQuote <= params.availableInQuote && minimum <= params.availableInQuote) low = mid;
11363
11430
  else high = mid - 1n;
11364
11431
  }
@@ -12818,7 +12885,7 @@ async function submitWriteRequest(params) {
12818
12885
  * Exported so callers can display the constant; prefer {@link applyMintBuffer}
12819
12886
  * over multiplying by it directly, which is how the rounding bug reappears.
12820
12887
  */
12821
- const MINT_BUFFER = 10666667n;
12888
+ const MINT_BUFFER = 10750000n;
12822
12889
  /** `RiskEngine.DECIMALS` — the denominator {@link MINT_BUFFER} is taken over. */
12823
12890
  const MINT_BUFFER_DENOMINATOR = 10000000n;
12824
12891
  /** The compiled-in default, matching the deployed RiskEngine. */
@@ -14547,11 +14614,76 @@ async function assertLpPositionFunded(params) {
14547
14614
  return funding;
14548
14615
  }
14549
14616
 
14617
+ //#endregion
14618
+ //#region src/uniswap/lpGreeks.ts
14619
+ const Q96$5 = 1n << 96n;
14620
+ const Q192$5 = 1n << 192n;
14621
+ /**
14622
+ * Compute the token0/token1 amounts backing `liquidity` over `[sqrtA, sqrtB]`
14623
+ * at the current price `sqrtP`, mirroring Uniswap's `LiquidityAmounts`
14624
+ * (`getAmountsForLiquidity`). All sqrt prices are X96. The current price is
14625
+ * clamped into the range, so out-of-range positions collapse to a single token.
14626
+ */
14627
+ function getAmountsForLiquidity(sqrtPriceX96, sqrtRatioAX96, sqrtRatioBX96, liquidity) {
14628
+ const [sqrtA, sqrtB] = sqrtRatioAX96 <= sqrtRatioBX96 ? [sqrtRatioAX96, sqrtRatioBX96] : [sqrtRatioBX96, sqrtRatioAX96];
14629
+ const sqrtC = sqrtPriceX96 < sqrtA ? sqrtA : sqrtPriceX96 > sqrtB ? sqrtB : sqrtPriceX96;
14630
+ const amount0 = sqrtC < sqrtB ? liquidity * (sqrtB - sqrtC) * Q96$5 / (sqrtC * sqrtB) : 0n;
14631
+ const amount1 = sqrtC > sqrtA ? liquidity * (sqrtC - sqrtA) / Q96$5 : 0n;
14632
+ return {
14633
+ amount0,
14634
+ amount1
14635
+ };
14636
+ }
14637
+
14638
+ //#endregion
14639
+ //#region src/panoptic/v2/greeks/legLiquidity.ts
14640
+ const Q96$4 = 1n << 96n;
14641
+ function divCeil(numerator, denominator) {
14642
+ return (numerator + denominator - 1n) / denominator;
14643
+ }
14644
+ /** The Uniswap range and liquidity backing one option leg, with the contract's rounding. */
14645
+ function getLegLiquidityRange(leg, positionSize, tickSpacing) {
14646
+ const width = leg.width * tickSpacing;
14647
+ const lowerTick = leg.strike - width / 2n;
14648
+ const upperTick = leg.strike + (width + 1n) / 2n;
14649
+ if (lowerTick < -887272n || upperTick > 887272n || lowerTick >= upperTick) throw new RangeError("Invalid position range");
14650
+ const sqrtLower = tickToSqrtPriceX96(lowerTick);
14651
+ const sqrtUpper = tickToSqrtPriceX96(upperTick);
14652
+ const amount = positionSize * leg.optionRatio;
14653
+ const liquidity = leg.asset === 0n ? amount * (sqrtLower * sqrtUpper / Q96$4) / (sqrtUpper - sqrtLower) : amount * Q96$4 / (sqrtUpper - sqrtLower);
14654
+ return {
14655
+ lowerTick,
14656
+ upperTick,
14657
+ sqrtLower,
14658
+ sqrtUpper,
14659
+ liquidity
14660
+ };
14661
+ }
14662
+ /**
14663
+ * One option leg's signed holding of `tokenIndex` at `currentTick`: the amount
14664
+ * its liquidity holds minus the amount the leg moved, positive for short legs.
14665
+ */
14666
+ function getLegTokenInventory(leg, currentTick, positionSize, tickSpacing, tokenIndex) {
14667
+ const { sqrtLower, sqrtUpper, liquidity } = getLegLiquidityRange(leg, positionSize, tickSpacing);
14668
+ const held = getAmountsForLiquidity(tickToSqrtPriceX96(currentTick), sqrtLower, sqrtUpper, liquidity);
14669
+ const heldAmount = tokenIndex === 0n ? held.amount0 : held.amount1;
14670
+ let movedAmount = 0n;
14671
+ if (leg.tokenType === tokenIndex) {
14672
+ const span = sqrtUpper - sqrtLower;
14673
+ if (tokenIndex === 0n) {
14674
+ const scaled = (liquidity << 96n) * span;
14675
+ movedAmount = leg.isLong ? scaled / sqrtUpper / sqrtLower : divCeil(divCeil(scaled, sqrtUpper), sqrtLower);
14676
+ } else movedAmount = leg.isLong ? liquidity * span / Q96$4 : divCeil(liquidity * span, Q96$4);
14677
+ }
14678
+ const net = heldAmount - movedAmount;
14679
+ return leg.isLong ? -net : net;
14680
+ }
14681
+
14550
14682
  //#endregion
14551
14683
  //#region src/panoptic/v2/greeks/index.ts
14552
14684
  /** Fixed-point scale constants for sqrtPriceX96 arithmetic */
14553
- const Q96$2 = 1n << 96n;
14554
- const Q192$3 = 1n << 192n;
14685
+ const Q96$3 = 1n << 96n;
14686
+ const Q192$4 = 1n << 192n;
14555
14687
  /**
14556
14688
  * Convert tick to quote-denominated tick based on asset direction.
14557
14689
  *
@@ -14605,7 +14737,7 @@ function computeWidth0Notional(leg, m) {
14605
14737
  const signedStrike = leg.asset === 0n ? leg.strike : -leg.strike;
14606
14738
  const sqrtKraw = tickToSqrtPriceX96(signedStrike);
14607
14739
  const KrawX192 = sqrtKraw * sqrtKraw;
14608
- return divTrunc(m * KrawX192, Q192$3);
14740
+ return divTrunc(m * KrawX192, Q192$4);
14609
14741
  }
14610
14742
  /**
14611
14743
  * Calculate value for a width=0 (loan/credit) leg.
@@ -14625,7 +14757,7 @@ function getLegValueWidth0(leg, m, qCurrentTick, qStrikeTick, qMintTick, isAsset
14625
14757
  const sqrtPm = tickToSqrtPriceX96(qMintTick);
14626
14758
  const PX192 = sqrtP * sqrtP;
14627
14759
  const PmX192 = sqrtPm * sqrtPm;
14628
- return divTrunc(-notional * (PX192 - PmX192), Q192$3);
14760
+ return divTrunc(-notional * (PX192 - PmX192), Q192$4);
14629
14761
  } else return 0n;
14630
14762
  }
14631
14763
  /**
@@ -14654,7 +14786,7 @@ function getLegNetValueWidth0(leg, m, qCurrentTick, qMintTick, isAssetToken0, sw
14654
14786
  const sqrtPm = tickToSqrtPriceX96(qMintTick);
14655
14787
  const PX192 = sqrtP * sqrtP;
14656
14788
  const PmX192 = sqrtPm * sqrtPm;
14657
- if (borrowsAsset) return divTrunc(-notional * (PX192 - PmX192), Q192$3);
14789
+ if (borrowsAsset) return divTrunc(-notional * (PX192 - PmX192), Q192$4);
14658
14790
  return divTrunc(notional * PX192, PmX192) - notional;
14659
14791
  }
14660
14792
  /**
@@ -14676,7 +14808,7 @@ function computeOptionItm(m, qStrikeTick, qMintTick, halfWidthTick, isPut) {
14676
14808
  const sqrtPm$2 = tickToSqrtPriceX96(qMintTick);
14677
14809
  const KX192 = sqrtK$1 * sqrtK$1;
14678
14810
  const PmX192 = sqrtPm$2 * sqrtPm$2;
14679
- return divTrunc(m * (KX192 - PmX192), Q192$3);
14811
+ return divTrunc(m * (KX192 - PmX192), Q192$4);
14680
14812
  } else if (qMintTick > qStrikeTick + halfWidthTick) return 0n;
14681
14813
  const sqrtKR = tickToSqrtPriceX96(qStrikeTick + halfWidthTick);
14682
14814
  const sqrtPm$1 = tickToSqrtPriceX96(qMintTick);
@@ -14684,7 +14816,7 @@ function computeOptionItm(m, qStrikeTick, qMintTick, halfWidthTick, isPut) {
14684
14816
  const rX192$1 = sqrtR$1 * sqrtR$1;
14685
14817
  const diff$1 = sqrtKR - sqrtPm$1;
14686
14818
  const diffSqX192$1 = diff$1 * diff$1;
14687
- return divTrunc(m * diffSqX192$1, rX192$1 - Q192$3);
14819
+ return divTrunc(m * diffSqX192$1, rX192$1 - Q192$4);
14688
14820
  }
14689
14821
  if (qMintTick < qStrikeTick - halfWidthTick) return 0n;
14690
14822
  else if (qMintTick > qStrikeTick + halfWidthTick) {
@@ -14698,10 +14830,10 @@ function computeOptionItm(m, qStrikeTick, qMintTick, halfWidthTick, isPut) {
14698
14830
  const sqrtK = tickToSqrtPriceX96(qStrikeTick);
14699
14831
  const sqrtPm = tickToSqrtPriceX96(qMintTick);
14700
14832
  const rX192 = sqrtR * sqrtR;
14701
- const sqrtKPmX96 = divTrunc(sqrtK * Q96$2, sqrtPm);
14833
+ const sqrtKPmX96 = divTrunc(sqrtK * Q96$3, sqrtPm);
14702
14834
  const diff = sqrtR - sqrtKPmX96;
14703
14835
  const diffSqX192 = diff * diff;
14704
- return divTrunc(m * diffSqX192, rX192 - Q192$3);
14836
+ return divTrunc(m * diffSqX192, rX192 - Q192$4);
14705
14837
  }
14706
14838
  /**
14707
14839
  * Check if leg is a call option (vs put).
@@ -14757,11 +14889,11 @@ function getLegValue(leg, currentTick, mintTick, positionSize, poolTickSpacing,
14757
14889
  if (qCurrentTick < qStrikeTick - halfWidthTick) {
14758
14890
  const sqrtP = tickToSqrtPriceX96(qCurrentTick);
14759
14891
  const PX192 = sqrtP * sqrtP;
14760
- v = divTrunc(m * PX192, Q192$3);
14892
+ v = divTrunc(m * PX192, Q192$4);
14761
14893
  } else if (qCurrentTick > qStrikeTick + halfWidthTick) {
14762
14894
  const sqrtK = tickToSqrtPriceX96(qStrikeTick);
14763
14895
  const KX192 = sqrtK * sqrtK;
14764
- v = divTrunc(m * KX192, Q192$3);
14896
+ v = divTrunc(m * KX192, Q192$4);
14765
14897
  } else {
14766
14898
  const sqrtP = tickToSqrtPriceX96(qCurrentTick);
14767
14899
  const sqrtK = tickToSqrtPriceX96(qStrikeTick);
@@ -14770,8 +14902,8 @@ function getLegValue(leg, currentTick, mintTick, positionSize, poolTickSpacing,
14770
14902
  const PX192 = sqrtP * sqrtP;
14771
14903
  const KX192 = sqrtK * sqrtK;
14772
14904
  const rX192 = sqrtR * sqrtR;
14773
- const numerator = m * (2n * sqrtPKR * Q96$2 - PX192 - KX192);
14774
- const denominator = rX192 - Q192$3;
14905
+ const numerator = m * (2n * sqrtPKR * Q96$3 - PX192 - KX192);
14906
+ const denominator = rX192 - Q192$4;
14775
14907
  v = divTrunc(numerator, denominator);
14776
14908
  }
14777
14909
  const debt = -m;
@@ -14780,19 +14912,19 @@ function getLegValue(leg, currentTick, mintTick, positionSize, poolTickSpacing,
14780
14912
  if (isPut) {
14781
14913
  const sqrtK = tickToSqrtPriceX96(qStrikeTick);
14782
14914
  const KX192 = sqrtK * sqrtK;
14783
- const debtK = divTrunc(debt * KX192, Q192$3);
14915
+ const debtK = divTrunc(debt * KX192, Q192$4);
14784
14916
  return debtK + v + itm;
14785
14917
  } else {
14786
14918
  const sqrtP = tickToSqrtPriceX96(qCurrentTick);
14787
14919
  const PX192 = sqrtP * sqrtP;
14788
- const debtP = divTrunc(debt * PX192, Q192$3);
14920
+ const debtP = divTrunc(debt * PX192, Q192$4);
14789
14921
  if (definedRisk) {
14790
14922
  const sqrtPm = tickToSqrtPriceX96(qMintTick);
14791
14923
  const PmX192 = sqrtPm * sqrtPm;
14792
- const itmPm = divTrunc(itm * PmX192, Q192$3);
14924
+ const itmPm = divTrunc(itm * PmX192, Q192$4);
14793
14925
  return debtP + v + itmPm;
14794
14926
  } else {
14795
- const itmP = divTrunc(itm * PX192, Q192$3);
14927
+ const itmP = divTrunc(itm * PX192, Q192$4);
14796
14928
  return debtP + v + itmP;
14797
14929
  }
14798
14930
  }
@@ -14828,7 +14960,7 @@ function getLegDelta(leg, currentTick, positionSize, poolTickSpacing, mintTick,
14828
14960
  const signedStrike = leg.asset === 0n ? leg.strike : -leg.strike;
14829
14961
  const sqrtKraw = tickToSqrtPriceX96(signedStrike);
14830
14962
  const KrawX192 = sqrtKraw * sqrtKraw;
14831
- const notional = divTrunc(m * KrawX192, Q192$3);
14963
+ const notional = divTrunc(m * KrawX192, Q192$4);
14832
14964
  return -notional;
14833
14965
  }
14834
14966
  if (halfWidthTick === 0n) {
@@ -14857,8 +14989,8 @@ function getLegDelta(leg, currentTick, positionSize, poolTickSpacing, mintTick,
14857
14989
  const sqrtKR = tickToSqrtPriceX96(qStrikeTick + halfWidthTick);
14858
14990
  const sqrtR = tickToSqrtPriceX96(halfWidthTick);
14859
14991
  const rX192 = sqrtR * sqrtR;
14860
- const numerator = m * (sqrtKR - sqrtP) * Q192$3;
14861
- const denominator = sqrtP * (rX192 - Q192$3);
14992
+ const numerator = m * (sqrtKR - sqrtP) * Q192$4;
14993
+ const denominator = sqrtP * (rX192 - Q192$4);
14862
14994
  vDelta = divTrunc(numerator, denominator);
14863
14995
  }
14864
14996
  const isPut = !isCall(leg.tokenType, isAssetToken0);
@@ -14878,10 +15010,10 @@ function getLegDelta(leg, currentTick, positionSize, poolTickSpacing, mintTick,
14878
15010
  const sqrtK = tickToSqrtPriceX96(qStrikeTick);
14879
15011
  const sqrtPm = tickToSqrtPriceX96(qMintTick);
14880
15012
  const rX192 = sqrtR * sqrtR;
14881
- const sqrtKPmX96 = sqrtK * Q96$2 / sqrtPm;
15013
+ const sqrtKPmX96 = sqrtK * Q96$3 / sqrtPm;
14882
15014
  const diff = sqrtR - sqrtKPmX96;
14883
15015
  const diffSqX192 = diff * diff;
14884
- return divTrunc(m * diffSqX192, rX192 - Q192$3);
15016
+ return divTrunc(m * diffSqX192, rX192 - Q192$4);
14885
15017
  }
14886
15018
  })();
14887
15019
  return definedRisk ? debtDelta + vDelta : debtDelta + vDelta + itmDelta;
@@ -14890,19 +15022,21 @@ function getLegDelta(leg, currentTick, positionSize, poolTickSpacing, mintTick,
14890
15022
  function toVaultFrameAtTick(delta, fromAsset, vaultAssetIndex, currentTick, flipSignOnAssetInversion = false) {
14891
15023
  if (fromAsset === vaultAssetIndex) return delta;
14892
15024
  const sqrtPriceX96 = tickToSqrtPriceX96(currentTick);
14893
- const converted = vaultAssetIndex === 0n ? delta * Q192$3 / (sqrtPriceX96 * sqrtPriceX96) : delta * sqrtPriceX96 * sqrtPriceX96 / Q192$3;
15025
+ const converted = vaultAssetIndex === 0n ? delta * Q192$4 / (sqrtPriceX96 * sqrtPriceX96) : delta * sqrtPriceX96 * sqrtPriceX96 / Q192$4;
14894
15026
  return flipSignOnAssetInversion ? -converted : converted;
14895
15027
  }
14896
15028
  /**
14897
15029
  * Calculate one leg's wallet-aware delta in the vault asset frame.
14898
15030
  *
14899
15031
  * Width-zero loans and credits must be evaluated directly in the vault frame.
14900
- * Option legs remain in their natural leg frame until converted at the mark tick.
15032
+ * An option leg is measured as its current holding of the vault token, so
15033
+ * `mintTick` and `definedRisk` do not affect it. Tokens swapped at mint belong
15034
+ * to the account's collateral balance, not to the position: a per-position
15035
+ * display omits them by design, and a whole-account delta adds the balance.
14901
15036
  */
14902
15037
  function getLegDeltaInVaultFrame(leg, currentTick, positionSize, poolTickSpacing, mintTick, definedRisk, vaultAssetIndex) {
14903
15038
  if (leg.width === 0n) return getLegDelta(leg, currentTick, positionSize, poolTickSpacing, mintTick, definedRisk, vaultAssetIndex);
14904
- const legDelta = getLegDelta(leg, currentTick, positionSize, poolTickSpacing, mintTick, definedRisk);
14905
- return toVaultFrameAtTick(legDelta, leg.asset, vaultAssetIndex, currentTick, true);
15039
+ return getLegTokenInventory(leg, currentTick, positionSize, poolTickSpacing, vaultAssetIndex);
14906
15040
  }
14907
15041
  /**
14908
15042
  * Calculate the gamma (dollar gamma) of a single leg.
@@ -14937,8 +15071,8 @@ function getLegGamma(leg, currentTick, positionSize, poolTickSpacing, assetIndex
14937
15071
  const sqrtKPR = tickToSqrtPriceX96(qStrikeTick + qCurrentTick + halfWidthTick);
14938
15072
  const sqrtR = tickToSqrtPriceX96(halfWidthTick);
14939
15073
  const rX192 = sqrtR * sqrtR;
14940
- const numerator = m * sqrtKPR * Q96$2;
14941
- const denominator = 2n * (rX192 - Q192$3);
15074
+ const numerator = m * sqrtKPR * Q96$3;
15075
+ const denominator = 2n * (rX192 - Q192$4);
14942
15076
  return divTrunc(numerator, denominator);
14943
15077
  }
14944
15078
  /**
@@ -15001,9 +15135,9 @@ function calculatePositionDelta(input) {
15001
15135
  /**
15002
15136
  * Calculate debt-only position delta in a single target asset frame.
15003
15137
  *
15004
- * Option legs are first valued in their natural `leg.asset` frame, then
15005
- * converted into `assetIndex` using the current pool price. Width-zero legs
15006
- * are evaluated directly in the target frame.
15138
+ * Option legs contribute their current holding of the `assetIndex` token,
15139
+ * without any mint-time adjustment. Width-zero legs are evaluated directly in
15140
+ * the target frame.
15007
15141
  *
15008
15142
  * Width=0 loan/credit legs include only their debt obligation. The held-token
15009
15143
  * side must be added separately from account collateral balances, preventing a
@@ -17515,7 +17649,7 @@ function buildCreditWrappedDispatch(params) {
17515
17649
 
17516
17650
  //#endregion
17517
17651
  //#region src/panoptic/v2/simulations/tokenShortfallRecovery.ts
17518
- const BPS_DENOMINATOR$4 = 10000n;
17652
+ const BPS_DENOMINATOR$5 = 10000n;
17519
17653
  const MAX_RECOVERY_QUOTE_ATTEMPTS = 8;
17520
17654
  /**
17521
17655
  * Wrap a dispatch with a temporary credit leg that sources the shortfall.
@@ -17553,21 +17687,23 @@ function getNotEnoughTokensError(error) {
17553
17687
  let current = error;
17554
17688
  while (current !== void 0 && current !== null && !visited.has(current)) {
17555
17689
  visited.add(current);
17556
- const parsed = current instanceof NotEnoughTokensError ? current : parsePanopticError(current)?.error;
17690
+ const decoded = parsePanopticError(current);
17691
+ const parsed = current instanceof NotEnoughTokensError ? current : decoded?.error;
17557
17692
  const candidate = parsed instanceof NotEnoughTokensError ? parsed : null;
17558
17693
  if (candidate !== null) {
17559
17694
  const args = candidate;
17560
- if (args.tokenAddress !== void 0 && args.assetsRequested !== void 0 && args.assetBalance !== void 0) return candidate;
17695
+ if (typeof args.tokenAddress === "string" && isAddress(args.tokenAddress) && typeof args.assetsRequested === "bigint" && typeof args.assetBalance === "bigint") return candidate;
17561
17696
  }
17562
- current = current instanceof Error && "cause" in current ? current.cause : void 0;
17697
+ const innerData = decoded?.errorName === "ExecuteError" ? decoded.args[1] : void 0;
17698
+ current = typeof innerData === "string" && isHex(innerData) ? { data: innerData } : current instanceof Error && "cause" in current ? current.cause : void 0;
17563
17699
  }
17564
17700
  return null;
17565
17701
  }
17566
17702
  function maximumAmountIn(estimatedAmountIn, slippageBps) {
17567
17703
  if (slippageBps < 0n) throw new PanopticError("slippageBps must be non-negative");
17568
- return (estimatedAmountIn * (BPS_DENOMINATOR$4 + slippageBps) + BPS_DENOMINATOR$4 - 1n) / BPS_DENOMINATOR$4;
17704
+ return (estimatedAmountIn * (BPS_DENOMINATOR$5 + slippageBps) + BPS_DENOMINATOR$5 - 1n) / BPS_DENOMINATOR$5;
17569
17705
  }
17570
- function ceilDiv$3(numerator, denominator) {
17706
+ function ceilDiv$4(numerator, denominator) {
17571
17707
  return (numerator + denominator - 1n) / denominator;
17572
17708
  }
17573
17709
  function getInputAmount(tokenFlow, tokenInIndex) {
@@ -17590,10 +17726,10 @@ async function quoteTokenShortfallRecovery(params) {
17590
17726
  reason: "invalid-shortfall",
17591
17727
  detail: `requested=${shortfallError.assetsRequested} <= balance=${shortfallError.assetBalance}`
17592
17728
  };
17593
- if (params.slippageBps < 0n || params.slippageBps > BPS_DENOMINATOR$4) return {
17729
+ if (params.slippageBps < 0n || params.slippageBps > BPS_DENOMINATOR$5) return {
17594
17730
  available: false,
17595
17731
  reason: "invalid-slippage",
17596
- detail: `slippageBps=${params.slippageBps} is outside [0, ${BPS_DENOMINATOR$4}]`
17732
+ detail: `slippageBps=${params.slippageBps} is outside [0, ${BPS_DENOMINATOR$5}]`
17597
17733
  };
17598
17734
  const targetBlockNumber = params.blockNumber ?? await params.client.getBlockNumber();
17599
17735
  const pool = await getPool({
@@ -17672,7 +17808,7 @@ async function quoteTokenShortfallRecovery(params) {
17672
17808
  const estimatedAmountIn = getInputAmount(swapSimulation.tokenFlow, tokenInIndex);
17673
17809
  const estimatedAmountOut = getOutputAmount(swapSimulation.tokenFlow, tokenOutIndex);
17674
17810
  if (estimatedAmountOut < requiredOutput) {
17675
- creditInput = estimatedAmountOut > 0n ? ceilDiv$3(creditInput * requiredOutput, estimatedAmountOut) + 1n : creditInput * 2n;
17811
+ creditInput = estimatedAmountOut > 0n ? ceilDiv$4(creditInput * requiredOutput, estimatedAmountOut) + 1n : creditInput * 2n;
17676
17812
  continue;
17677
17813
  }
17678
17814
  const recoveredDispatch = buildPrefixedExactInputRecoveryDispatch({
@@ -17727,7 +17863,7 @@ async function quoteTokenShortfallRecovery(params) {
17727
17863
  };
17728
17864
  const residual = remainingShortfall.assetsRequested - remainingShortfall.assetBalance;
17729
17865
  requiredOutput += residual > 0n ? residual : requiredOutput;
17730
- creditInput = ceilDiv$3(creditInput * requiredOutput, estimatedAmountOut) + 1n;
17866
+ creditInput = ceilDiv$4(creditInput * requiredOutput, estimatedAmountOut) + 1n;
17731
17867
  }
17732
17868
  return {
17733
17869
  available: false,
@@ -17782,7 +17918,7 @@ async function quoteTokenShortfallRecovery(params) {
17782
17918
  const maxAmountIn = maximumAmountIn(estimatedAmountIn, params.slippageBps);
17783
17919
  const swapOutput = getOutputAmount(swapSimulation.tokenFlow, tokenOutIndex);
17784
17920
  if (swapOutput < amountOut) {
17785
- creditOutSize = swapOutput > 0n ? ceilDiv$3(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
17921
+ creditOutSize = swapOutput > 0n ? ceilDiv$4(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
17786
17922
  continue;
17787
17923
  }
17788
17924
  const recoverySimulation = await simulateDispatch({
@@ -17837,7 +17973,7 @@ async function quoteTokenShortfallRecovery(params) {
17837
17973
  if (decodedShortfall >= shortfallError.assetsRequested - shortfallError.assetBalance) return quotePrefixedExactInput(amountOut);
17838
17974
  const additionalAmountOut = decodedShortfall > 0n ? decodedShortfall : amountOut;
17839
17975
  amountOut += additionalAmountOut;
17840
- creditOutSize = swapOutput > 0n ? ceilDiv$3(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
17976
+ creditOutSize = swapOutput > 0n ? ceilDiv$4(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
17841
17977
  }
17842
17978
  return quotePrefixedExactInput(shortfallError.assetsRequested - shortfallError.assetBalance);
17843
17979
  }
@@ -18366,10 +18502,32 @@ var UnsupportedChainError = class extends PanopticError {
18366
18502
  this.chainId = chainId;
18367
18503
  }
18368
18504
  };
18505
+ /**
18506
+ * `tokenIn` is neither `currency0` nor `currency1` of the resolved pool.
18507
+ */
18508
+ var InvalidSwapTokenError = class extends PanopticError {
18509
+ name = "InvalidSwapTokenError";
18510
+ constructor(token, currency0, currency1, cause) {
18511
+ super(`Token ${token} is not part of the pool (currency0=${currency0}, currency1=${currency1})`, cause);
18512
+ this.token = token;
18513
+ this.currency0 = currency0;
18514
+ this.currency1 = currency1;
18515
+ }
18516
+ };
18517
+ /**
18518
+ * The V4Quoter is not available for the chain (no fallback in v1).
18519
+ */
18520
+ var QuoterUnavailableError = class extends PanopticError {
18521
+ name = "QuoterUnavailableError";
18522
+ constructor(chainId, cause) {
18523
+ super(`V4Quoter unavailable for chain ${chainId}`, cause);
18524
+ this.chainId = chainId;
18525
+ }
18526
+ };
18369
18527
 
18370
18528
  //#endregion
18371
18529
  //#region src/uniswap/v3/router/encodeSwap.ts
18372
- const UINT128_MAX$1 = (1n << 128n) - 1n;
18530
+ const UINT128_MAX$4 = (1n << 128n) - 1n;
18373
18531
 
18374
18532
  //#endregion
18375
18533
  //#region src/uniswap/v3/abis/quoterV2.ts
@@ -18513,8 +18671,8 @@ function getUniswapV3Addresses(chainId, overrides) {
18513
18671
 
18514
18672
  //#endregion
18515
18673
  //#region src/uniswap/v3/router/quote.ts
18516
- const BPS_DENOMINATOR$3 = 10000n;
18517
- const UINT128_MAX = (1n << 128n) - 1n;
18674
+ const BPS_DENOMINATOR$4 = 10000n;
18675
+ const UINT128_MAX$3 = (1n << 128n) - 1n;
18518
18676
  /**
18519
18677
  * Quote an exact-in v3 swap. Returns `null` when the quote reverts (e.g. the
18520
18678
  * pool does not exist / has no liquidity) so callers can skip that pool when
@@ -18522,8 +18680,8 @@ const UINT128_MAX = (1n << 128n) - 1n;
18522
18680
  */
18523
18681
  async function quoteV3ExactIn(params) {
18524
18682
  const { client, chainId, tokenIn, tokenOut, fee, amountIn, slippageBps, blockNumber } = params;
18525
- if (amountIn < 0n || amountIn > UINT128_MAX) throw new PanopticError(`amountIn ${amountIn} exceeds uint128 maximum`);
18526
- assertSlippageBps(slippageBps);
18683
+ if (amountIn < 0n || amountIn > UINT128_MAX$3) throw new PanopticError(`amountIn ${amountIn} exceeds uint128 maximum`);
18684
+ assertSlippageBps$1(slippageBps);
18527
18685
  const { quoterV2 } = getUniswapV3Addresses(chainId, params.addresses);
18528
18686
  try {
18529
18687
  const { result } = await client.simulateContract({
@@ -18540,7 +18698,7 @@ async function quoteV3ExactIn(params) {
18540
18698
  }]
18541
18699
  });
18542
18700
  const [amountOut, , , gasEstimate] = result;
18543
- const amountOutMinimum = amountOut * (BPS_DENOMINATOR$3 - slippageBps) / BPS_DENOMINATOR$3;
18701
+ const amountOutMinimum = amountOut * (BPS_DENOMINATOR$4 - slippageBps) / BPS_DENOMINATOR$4;
18544
18702
  return {
18545
18703
  amountOut,
18546
18704
  amountOutMinimum,
@@ -18551,13 +18709,172 @@ async function quoteV3ExactIn(params) {
18551
18709
  throw err;
18552
18710
  }
18553
18711
  }
18554
- function assertSlippageBps(slippageBps) {
18555
- if (slippageBps < 0n || slippageBps > BPS_DENOMINATOR$3) throw new PanopticError(`invalid slippageBps ${slippageBps}, must be 0..10000`);
18712
+ /**
18713
+ * Quote an exact-out v3 swap. Returns `null` on revert (no pool / no liquidity).
18714
+ */
18715
+ async function quoteV3ExactOut(params) {
18716
+ const { client, chainId, tokenIn, tokenOut, fee, amountOut, slippageBps, blockNumber } = params;
18717
+ if (amountOut < 0n || amountOut > UINT128_MAX$3) throw new PanopticError(`amountOut ${amountOut} exceeds uint128 maximum`);
18718
+ assertSlippageBps$1(slippageBps);
18719
+ const { quoterV2 } = getUniswapV3Addresses(chainId, params.addresses);
18720
+ try {
18721
+ const { result } = await client.simulateContract({
18722
+ address: quoterV2,
18723
+ abi: quoterV2Abi,
18724
+ functionName: "quoteExactOutputSingle",
18725
+ blockNumber,
18726
+ args: [{
18727
+ tokenIn,
18728
+ tokenOut,
18729
+ amount: amountOut,
18730
+ fee: Number(fee),
18731
+ sqrtPriceLimitX96: 0n
18732
+ }]
18733
+ });
18734
+ const [amountIn, , , gasEstimate] = result;
18735
+ const amountInMaximum = (amountIn * (BPS_DENOMINATOR$4 + slippageBps) + BPS_DENOMINATOR$4 - 1n) / BPS_DENOMINATOR$4;
18736
+ return {
18737
+ amountIn,
18738
+ amountInMaximum,
18739
+ gasEstimate
18740
+ };
18741
+ } catch (err) {
18742
+ if (isRevert(err)) return null;
18743
+ throw err;
18744
+ }
18745
+ }
18746
+ function assertSlippageBps$1(slippageBps) {
18747
+ if (slippageBps < 0n || slippageBps > BPS_DENOMINATOR$4) throw new PanopticError(`invalid slippageBps ${slippageBps}, must be 0..10000`);
18556
18748
  }
18557
18749
  function isRevert(err) {
18558
18750
  return err instanceof BaseError && err.walk((e) => e instanceof ContractFunctionRevertedError) instanceof ContractFunctionRevertedError;
18559
18751
  }
18560
18752
 
18753
+ //#endregion
18754
+ //#region src/uniswap/v3/router/resolveRoute.ts
18755
+ async function resolveV3SwapRoute(params) {
18756
+ const { client, poolAddress, tokenIn } = params;
18757
+ const meta = await getPoolMetadata({
18758
+ client,
18759
+ poolAddress
18760
+ });
18761
+ if (meta.isV4) throw new PanopticError("resolveV3SwapRoute called on a v4 pool");
18762
+ const isToken0 = isAddressEqual(tokenIn, meta.token0Asset);
18763
+ const isToken1 = isAddressEqual(tokenIn, meta.token1Asset);
18764
+ if (!isToken0 && !isToken1) throw new InvalidSwapTokenError(tokenIn, meta.token0Asset, meta.token1Asset);
18765
+ const zeroForOne = isToken0;
18766
+ return {
18767
+ tokenIn,
18768
+ tokenOut: zeroForOne ? meta.token1Asset : meta.token0Asset,
18769
+ fee: meta.fee,
18770
+ zeroForOne
18771
+ };
18772
+ }
18773
+
18774
+ //#endregion
18775
+ //#region src/uniswap/v3/router/quoteViaRouter.ts
18776
+ const FALLBACK_META$1 = {
18777
+ blockNumber: 0n,
18778
+ blockTimestamp: 0n,
18779
+ blockHash: "0x0"
18780
+ };
18781
+ async function quoteSwapExactOutViaV3Router(params) {
18782
+ const { client, poolAddress, chainId, tokenIn, amountOut, slippageBps, blockNumber, addresses } = params;
18783
+ try {
18784
+ const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
18785
+ const metaPromise = getBlockMeta({
18786
+ client,
18787
+ blockNumber: targetBlockNumber
18788
+ });
18789
+ metaPromise.catch(() => void 0);
18790
+ const route = await resolveV3SwapRoute({
18791
+ client,
18792
+ poolAddress,
18793
+ tokenIn
18794
+ });
18795
+ const quote = await quoteV3ExactOut({
18796
+ client,
18797
+ chainId,
18798
+ tokenIn: route.tokenIn,
18799
+ tokenOut: route.tokenOut,
18800
+ fee: route.fee,
18801
+ amountOut,
18802
+ slippageBps,
18803
+ blockNumber: targetBlockNumber,
18804
+ addresses
18805
+ });
18806
+ if (!quote) throw new PanopticError("v3 quote returned no result (pool may have no liquidity)");
18807
+ const _meta = await metaPromise;
18808
+ return {
18809
+ success: true,
18810
+ data: {
18811
+ amountIn: quote.amountIn,
18812
+ amountInMaximum: quote.amountInMaximum,
18813
+ zeroForOne: route.zeroForOne,
18814
+ tokenOut: route.tokenOut,
18815
+ gasEstimate: quote.gasEstimate
18816
+ },
18817
+ gasEstimate: quote.gasEstimate,
18818
+ _meta
18819
+ };
18820
+ } catch (error) {
18821
+ return {
18822
+ success: false,
18823
+ error: error instanceof PanopticError ? error : new PanopticError(error instanceof Error ? error.message : "Quote failed", error instanceof Error ? error : void 0),
18824
+ _meta: FALLBACK_META$1
18825
+ };
18826
+ }
18827
+ }
18828
+
18829
+ //#endregion
18830
+ //#region src/uniswap/v4/addresses.ts
18831
+ /**
18832
+ * Canonical Permit2, identical across all chains.
18833
+ */
18834
+ const PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
18835
+ /**
18836
+ * Verified Uniswap v4 deployment addresses keyed by chainId.
18837
+ *
18838
+ * Sourced from the official Uniswap v4 deployments. Add a chain here only after
18839
+ * verifying each address against the canonical Uniswap deployment listing —
18840
+ * Universal Router in particular is NOT the same address across chains.
18841
+ */
18842
+ const UNISWAP_V4_ADDRESSES = {
18843
+ 1: {
18844
+ universalRouter: "0x66a9893cC07D91D95644AEDD05D03f95e1dBA8Af",
18845
+ v4Quoter: "0x52F0E24D1c21C8A0cB1e5a5dD6198556BD9E1203",
18846
+ poolManager: "0x000000000004444c5dc75cB358380D2e3dE08A90",
18847
+ positionManager: "0xbD216513d74C8cf14cf4747E6AaA6420FF64ee9e",
18848
+ permit2: PERMIT2_ADDRESS
18849
+ },
18850
+ 4663: {
18851
+ universalRouter: "0x8876789976decbfcbbbe364623c63652db8c0904",
18852
+ v4Quoter: "0x8dc178efb8111bb0973dd9d722ebeff267c98f94",
18853
+ poolManager: "0x8366a39cc670b4001a1121b8f6a443a643e40951",
18854
+ positionManager: "0x58daec3116aae6d93017baaea7749052e8a04fa7",
18855
+ permit2: PERMIT2_ADDRESS
18856
+ }
18857
+ };
18858
+ /**
18859
+ * Resolve the Uniswap v4 addresses for a chain, applying optional overrides.
18860
+ *
18861
+ * @param chainId - Target chain ID.
18862
+ * @param overrides - Partial override of any address (e.g. for fork tests).
18863
+ * @returns Fully-resolved {@link UniswapV4Addresses}.
18864
+ * @throws {UnsupportedChainError} when the chain is not listed and the
18865
+ * overrides do not supply every required address.
18866
+ */
18867
+ function getUniswapV4Addresses(chainId, overrides) {
18868
+ const base = UNISWAP_V4_ADDRESSES[Number(chainId)];
18869
+ const merged = {
18870
+ ...base,
18871
+ ...overrides,
18872
+ permit2: overrides?.permit2 ?? base?.permit2 ?? PERMIT2_ADDRESS
18873
+ };
18874
+ if (merged.universalRouter === void 0 || merged.v4Quoter === void 0 || merged.poolManager === void 0 || merged.positionManager === void 0 || merged.permit2 === void 0) throw new UnsupportedChainError(chainId);
18875
+ return merged;
18876
+ }
18877
+
18561
18878
  //#endregion
18562
18879
  //#region src/panoptic/v2/reads/sfpm.ts
18563
18880
  /**
@@ -20578,7 +20895,7 @@ async function getItmAmounts(params) {
20578
20895
  * high-decimal amount can't masquerade as real flow.
20579
20896
  */
20580
20897
  const FLOW_NEUTRAL_DUST_THRESHOLD = 1000n;
20581
- const Q192$2 = 1n << 192n;
20898
+ const Q192$3 = 1n << 192n;
20582
20899
  const POOL_ID_MASK$2 = (1n << 64n) - 1n;
20583
20900
  /**
20584
20901
  * Floor integer square root for bigints (Newton's method). Exact for all
@@ -20614,7 +20931,7 @@ function buildNeutralLeg(tokenIndex, signedAmount, positionSize) {
20614
20931
  const absAmount = signedAmount < 0n ? -signedAmount : signedAmount;
20615
20932
  const legAsset = tokenIndex === 0n ? 1n : 0n;
20616
20933
  const legIsLong = signedAmount < 0n;
20617
- const sqrtKrawX96 = isqrt(absAmount * Q192$2 / positionSize);
20934
+ const sqrtKrawX96 = isqrt(absAmount * Q192$3 / positionSize);
20618
20935
  let signedTick;
20619
20936
  try {
20620
20937
  signedTick = sqrtPriceX96ToTick(sqrtKrawX96);
@@ -20872,7 +21189,7 @@ async function createFlowNeutralTokenId(params) {
20872
21189
  const sqrtPX96 = tickToSqrtPriceX96(tickBefore);
20873
21190
  const valueAbs = (index, amount) => {
20874
21191
  const abs$1 = amount < 0n ? -amount : amount;
20875
- return index === 0n ? abs$1 * sqrtPX96 * sqrtPX96 / Q192$2 : abs$1;
21192
+ return index === 0n ? abs$1 * sqrtPX96 * sqrtPX96 / Q192$3 : abs$1;
20876
21193
  };
20877
21194
  const flowFor = (index) => index === 0n ? credit.creditAmount0 : credit.creditAmount1;
20878
21195
  if (queryAddress !== void 0) {
@@ -21845,7 +22162,7 @@ async function getPoolLiquidities(params) {
21845
22162
 
21846
22163
  //#endregion
21847
22164
  //#region src/panoptic/v2/reads/accountGreeks.ts
21848
- const Q192$1 = 1n << 192n;
22165
+ const Q192$2 = 1n << 192n;
21849
22166
  /**
21850
22167
  * Calculate account-level greeks using stored position data.
21851
22168
  *
@@ -21966,8 +22283,8 @@ async function getAccountGreeks(params) {
21966
22283
  const assetBal = isAssetToken0 ? collateral.token0.assets : collateral.token1.assets;
21967
22284
  const otherBal = isAssetToken0 ? collateral.token1.assets : collateral.token0.assets;
21968
22285
  const sqrtPriceX96 = tickToSqrtPriceX96(BigInt(currentTick));
21969
- if (isAssetToken0) collateralValue = assetBal * sqrtPriceX96 * sqrtPriceX96 / Q192$1 + otherBal;
21970
- else collateralValue = assetBal * Q192$1 / (sqrtPriceX96 * sqrtPriceX96) + otherBal;
22286
+ if (isAssetToken0) collateralValue = assetBal * sqrtPriceX96 * sqrtPriceX96 / Q192$2 + otherBal;
22287
+ else collateralValue = assetBal * Q192$2 / (sqrtPriceX96 * sqrtPriceX96) + otherBal;
21971
22288
  collateralDelta = assetBal;
21972
22289
  }
21973
22290
  return {
@@ -22007,7 +22324,7 @@ function calculateAccountGreeksPure(params) {
22007
22324
  const totalDelta$1 = [];
22008
22325
  for (let i = 0; i < n; i++) {
22009
22326
  const sqrtPriceX96 = tickToSqrtPriceX96(atTicks[i]);
22010
- const assetValueInNumeraire = isAssetToken0 ? assetBal * sqrtPriceX96 * sqrtPriceX96 / Q192$1 : assetBal * Q192$1 / (sqrtPriceX96 * sqrtPriceX96);
22327
+ const assetValueInNumeraire = isAssetToken0 ? assetBal * sqrtPriceX96 * sqrtPriceX96 / Q192$2 : assetBal * Q192$2 / (sqrtPriceX96 * sqrtPriceX96);
22011
22328
  totalValue$1.push(assetValueInNumeraire + otherBal);
22012
22329
  totalDelta$1.push(assetBal);
22013
22330
  }
@@ -22057,7 +22374,7 @@ function calculateAccountGreeksPure(params) {
22057
22374
  }
22058
22375
  for (let i = 0; i < n; i++) {
22059
22376
  const sqrtPriceX96 = tickToSqrtPriceX96(atTicks[i]);
22060
- const assetValueInNumeraire = isAssetToken0 ? assetBal * sqrtPriceX96 * sqrtPriceX96 / Q192$1 : assetBal * Q192$1 / (sqrtPriceX96 * sqrtPriceX96);
22377
+ const assetValueInNumeraire = isAssetToken0 ? assetBal * sqrtPriceX96 * sqrtPriceX96 / Q192$2 : assetBal * Q192$2 / (sqrtPriceX96 * sqrtPriceX96);
22061
22378
  totalValue[i] += assetValueInNumeraire + otherBal;
22062
22379
  totalDelta[i] += assetBal;
22063
22380
  }
@@ -24472,10 +24789,10 @@ async function processClosedPositions(client, queryAddress, positions) {
24472
24789
  //#endregion
24473
24790
  //#region src/panoptic/v2/reads/hedgeCapacity.ts
24474
24791
  const SCALE$1 = 10000000n;
24475
- const FEE_SCALE = 10000n;
24476
- const Q192 = 1n << 192n;
24792
+ const FEE_SCALE$1 = 10000n;
24793
+ const Q192$1 = 1n << 192n;
24477
24794
  const MASK128$1 = (1n << 128n) - 1n;
24478
- const ceilDiv$2 = (value, divisor) => (value + divisor - 1n) / divisor;
24795
+ const ceilDiv$3 = (value, divisor) => (value + divisor - 1n) / divisor;
24479
24796
  function accountHedgeDelta({ positionIds, balances, collateralDelta, tick, tickSpacing, assetIndex }) {
24480
24797
  return positionIds.reduce((sum$1, id, index) => {
24481
24798
  const balance = balances[index];
@@ -24495,8 +24812,8 @@ function accountHedgeDelta({ positionIds, balances, collateralDelta, tick, tickS
24495
24812
  function buildCapacityHedge({ delta, assetIndex, tick, tickSpacing, poolId, notionalFee, swapFee }) {
24496
24813
  const borrowToken = delta >= 0n ? assetIndex : assetIndex === 0n ? 1n : 0n;
24497
24814
  const receiveToken = borrowToken === 0n ? 1n : 0n;
24498
- const amount = delta >= 0n ? delta : ceilDiv$2((toVaultFrameAtTick(-delta, assetIndex, borrowToken, tick) + 1n) * 1000000n * FEE_SCALE, (1000000n - swapFee) * (FEE_SCALE - notionalFee));
24499
- const commission = ceilDiv$2(amount * notionalFee, FEE_SCALE);
24815
+ const amount = delta >= 0n ? delta : ceilDiv$3((toVaultFrameAtTick(-delta, assetIndex, borrowToken, tick) + 1n) * 1000000n * FEE_SCALE$1, (1000000n - swapFee) * (FEE_SCALE$1 - notionalFee));
24816
+ const commission = ceilDiv$3(amount * notionalFee, FEE_SCALE$1);
24500
24817
  const proceeds = toVaultFrameAtTick((amount - commission) * (1000000n - swapFee) / 1000000n, borrowToken, receiveToken, tick);
24501
24818
  const tokenId = addLegToTokenId(poolId, {
24502
24819
  index: 0n,
@@ -24528,7 +24845,7 @@ function hedgeMargin({ tokenData, balanceChanges, crossRatios, tick, buffer }) {
24528
24845
  const surplus1 = balances[1] > required1 ? (balances[1] - required1) * crossRatios[1] / SCALE$1 : 0n;
24529
24846
  const sqrt = tickToSqrtPriceX96(tick);
24530
24847
  const price = sqrt * sqrt;
24531
- const pairs = sqrt < 1n << 96n ? [[balances[0] + surplus1 * Q192 / price, required0], [balances[1] * Q192 / price + surplus0, ceilDiv$2(required1 * Q192, price)]] : [[balances[0] * price / Q192 + surplus1, ceilDiv$2(required0 * price, Q192)], [balances[1] + surplus0 * price / Q192, required1]];
24848
+ const pairs = sqrt < 1n << 96n ? [[balances[0] + surplus1 * Q192$1 / price, required0], [balances[1] * Q192$1 / price + surplus0, ceilDiv$3(required1 * Q192$1, price)]] : [[balances[0] * price / Q192$1 + surplus1, ceilDiv$3(required0 * price, Q192$1)], [balances[1] + surplus0 * price / Q192$1, required1]];
24532
24849
  const headroom = pairs.map(([balance, required]) => balance - required);
24533
24850
  return {
24534
24851
  solvent: balances.every((balance) => balance >= 0n) && headroom.every((value) => value >= 0n),
@@ -24741,7 +25058,7 @@ async function getHedgeLimits({ client, poolAddress, account, positionIds, asset
24741
25058
  if (hedge.amount > 0n && BigInt(legCount) >= maxLegs) return unavailable("leg-limit");
24742
25059
  const totalAssets = hedge.borrowToken === 0n ? total0 : total1;
24743
25060
  if (hedge.amount > 0n && (hedge.amount > MAX_SIZE || hedge.amount > borrowCapacity[Number(hedge.borrowToken)] || totalAssets === 0n)) return unavailable("capacity");
24744
- const projectedUtilization = currentUtilizations.map((util, i) => hedge.amount > 0n && BigInt(i) === hedge.borrowToken ? ceilDiv$2(util * totalAssets + hedge.amount * 10000n, totalAssets) : util);
25061
+ const projectedUtilization = currentUtilizations.map((util, i) => hedge.amount > 0n && BigInt(i) === hedge.borrowToken ? ceilDiv$3(util * totalAssets + hedge.amount * 10000n, totalAssets) : util);
24745
25062
  if (hedge.amount > 0n && projectedUtilization.some((util) => util > 10000n)) return unavailable("capacity");
24746
25063
  const global = projectedUtilization.map((util, i) => util > globalUtilizations[i] ? util : globalUtilizations[i]);
24747
25064
  const syntheticBalance = hedge.amount | projectedUtilization[0] << 128n | projectedUtilization[1] << 144n;
@@ -24833,6 +25150,90 @@ async function getHedgeLimits({ client, poolAddress, account, positionIds, asset
24833
25150
  };
24834
25151
  }
24835
25152
 
25153
+ //#endregion
25154
+ //#region src/panoptic/v2/reads/positionMintFunding.ts
25155
+ const Q96$2 = 1n << 96n;
25156
+ const Q192 = 1n << 192n;
25157
+ const BPS = 10000n;
25158
+ const FEE_SCALE = 1000000n;
25159
+ const max = (a, b) => a > b ? a : b;
25160
+ const ceilDiv$2 = (n, d) => n > 0n ? (n + d - 1n) / d : n / d;
25161
+ /**
25162
+ * Estimate deposit-independent mint funding, including settlement and commission.
25163
+ * Swaps use spot conversion with fees and slippage allowance; execution still needs a live quote.
25164
+ * Received tokens cover post-mint margin but cannot fund the other tracker's upfront payment.
25165
+ * Each requiredValue is the starting balance when funding entirely in that token.
25166
+ */
25167
+ function getPositionMintFunding(params) {
25168
+ const { tokenId, positionSize, sqrtPriceX96, valuationSqrtPriceX96, swapAtMint, commissionRate, swapFee, slippageBps, required0, required1 } = params;
25169
+ if (positionSize < 0n || sqrtPriceX96 <= 0n || valuationSqrtPriceX96 <= 0n || commissionRate < 0n || swapFee < 0n || swapFee >= FEE_SCALE || slippageBps < 0n || slippageBps >= BPS || required0 < 0n || required1 < 0n) throw new RangeError("Invalid mint funding inputs");
25170
+ const { legs, tickSpacing } = decodeTokenId(tokenId);
25171
+ const firstLeg = legs[0];
25172
+ if (!firstLeg || tickSpacing <= 0n) throw new RangeError("Invalid position");
25173
+ let paid0 = 0n;
25174
+ let paid1 = 0n;
25175
+ let itm0 = 0n;
25176
+ let itm1 = 0n;
25177
+ let notional0 = 0n;
25178
+ let notional1 = 0n;
25179
+ for (const leg of legs) {
25180
+ const { sqrtLower, sqrtUpper, liquidity } = getLegLiquidityRange(leg.width === 0n ? {
25181
+ ...leg,
25182
+ width: 2n
25183
+ } : leg, positionSize, tickSpacing);
25184
+ const round = !leg.isLong || leg.width === 0n ? ceilDiv$2 : (n, d) => n / d;
25185
+ const moved0 = round((liquidity << 96n) * (sqrtUpper - sqrtLower), sqrtUpper * sqrtLower);
25186
+ const moved1 = round(liquidity * (sqrtUpper - sqrtLower), Q96$2);
25187
+ const sign = leg.isLong ? -1n : 1n;
25188
+ let amm0 = 0n;
25189
+ let amm1 = 0n;
25190
+ if (leg.width > 0n) {
25191
+ const price = max(sqrtLower, sqrtPriceX96 < sqrtUpper ? sqrtPriceX96 : sqrtUpper);
25192
+ amm0 = sign * round((liquidity << 96n) * (sqrtUpper - price), sqrtUpper * price);
25193
+ amm1 = sign * round(liquidity * (price - sqrtLower), Q96$2);
25194
+ itm0 += leg.tokenType === 1n ? amm0 : 0n;
25195
+ itm1 += leg.tokenType === 0n ? amm1 : 0n;
25196
+ } else {
25197
+ itm0 -= leg.tokenType === 0n ? sign * moved0 : 0n;
25198
+ itm1 -= leg.tokenType === 1n ? sign * moved1 : 0n;
25199
+ }
25200
+ paid0 += amm0 - (leg.tokenType === 0n ? sign * moved0 : 0n);
25201
+ paid1 += amm1 - (leg.tokenType === 1n ? sign * moved1 : 0n);
25202
+ notional0 += leg.tokenType === 0n ? moved0 : 0n;
25203
+ notional1 += leg.tokenType === 1n ? moved1 : 0n;
25204
+ }
25205
+ if (swapAtMint && (itm0 !== 0n || itm1 !== 0n)) {
25206
+ const swapToken0 = itm0 !== 0n && (itm1 === 0n || firstLeg.asset === 0n);
25207
+ const priceSquared$1 = sqrtPriceX96 * sqrtPriceX96;
25208
+ const itm = swapToken0 ? itm0 : itm1;
25209
+ const numerator = swapToken0 ? priceSquared$1 : Q192;
25210
+ const denominator = swapToken0 ? Q192 : priceSquared$1;
25211
+ const retained$1 = (FEE_SCALE - swapFee) * (BPS - slippageBps);
25212
+ const scale$1 = FEE_SCALE * BPS;
25213
+ const payment = itm > 0n ? ceilDiv$2(itm * numerator * scale$1, denominator * retained$1) : itm * numerator * retained$1 / (denominator * scale$1);
25214
+ paid0 += swapToken0 ? -itm : payment;
25215
+ paid1 += swapToken0 ? payment : -itm;
25216
+ }
25217
+ paid0 += ceilDiv$2(notional0 * commissionRate, BPS);
25218
+ paid1 += ceilDiv$2(notional1 * commissionRate, BPS);
25219
+ const priceSquared = valuationSqrtPriceX96 * valuationSqrtPriceX96;
25220
+ const inToken0 = (amount0, amount1) => amount0 + ceilDiv$2(amount1 * Q192, priceSquared);
25221
+ const inToken1 = (amount0, amount1) => amount1 + ceilDiv$2(amount0 * priceSquared, Q192);
25222
+ const retained = (FEE_SCALE - swapFee) * (BPS - slippageBps);
25223
+ const scale = FEE_SCALE * BPS;
25224
+ const spotSquared = sqrtPriceX96 * sqrtPriceX96;
25225
+ const upfront0 = max(paid0, 0n) + ceilDiv$2(max(paid1, 0n) * Q192 * scale, spotSquared * retained);
25226
+ const upfront1 = max(paid1, 0n) + ceilDiv$2(max(paid0, 0n) * spotSquared * scale, Q192 * retained);
25227
+ const requiredValue0 = upfront0 + max(0n, inToken0(required0 - max(-paid0, 0n), required1 - max(-paid1, 0n)));
25228
+ const requiredValue1 = upfront1 + max(0n, inToken1(required0 - max(-paid0, 0n), required1 - max(-paid1, 0n)));
25229
+ return {
25230
+ paid0,
25231
+ paid1,
25232
+ requiredValue0,
25233
+ requiredValue1
25234
+ };
25235
+ }
25236
+
24836
25237
  //#endregion
24837
25238
  //#region src/panoptic/v2/sync/getSyncStatus.ts
24838
25239
  /**
@@ -28406,121 +28807,223 @@ async function simulateClosePosition(params) {
28406
28807
  }
28407
28808
 
28408
28809
  //#endregion
28409
- //#region src/panoptic/v2/simulations/simulateForceExercise.ts
28410
- /**
28411
- * Simulate a force exercise operation.
28412
- *
28413
- * @param params - Simulation parameters
28414
- * @returns Simulation result with exercise data or error
28415
- */
28416
- async function simulateForceExercise(params) {
28417
- const { client, poolAddress, account, user, positionIdListFrom, positionIdListTo, positionIdListToFinal, blockNumber } = params;
28418
- const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
28419
- const metaPromise = getBlockMeta({
28420
- client,
28421
- blockNumber: targetBlockNumber
28422
- });
28423
- const emptyTokenFlow = {
28424
- delta0: 0n,
28425
- delta1: 0n,
28426
- balanceBefore0: 0n,
28427
- balanceBefore1: 0n,
28428
- balanceAfter0: 0n,
28429
- balanceAfter1: 0n,
28430
- tickBefore: null,
28431
- tickAfter: null
28432
- };
28810
+ //#region src/panoptic/v2/simulations/simulateClosePremiumProtection.ts
28811
+ /** Estimate unfunded short premium after buyer settlement and collection of chunk fees. */
28812
+ async function simulateClosePremiumProtection(params) {
28813
+ const { client, poolAddress, account, positionIdList, closingTokenIds, targets } = params;
28814
+ let metaPromise;
28433
28815
  try {
28434
- const callData = encodeFunctionData({
28435
- abi: panopticPoolV2Abi,
28436
- functionName: "dispatchFrom",
28437
- args: [
28438
- positionIdListFrom,
28439
- user,
28440
- positionIdListTo,
28441
- positionIdListToFinal,
28442
- 0n
28443
- ]
28816
+ const blockNumber = params.blockNumber ?? await client.getBlockNumber();
28817
+ metaPromise = getBlockMeta({
28818
+ client,
28819
+ blockNumber
28444
28820
  });
28445
- const flowResult = await simulateWithTokenFlow({
28821
+ metaPromise.catch(() => {});
28822
+ if (closingTokenIds.length === 0 || closingTokenIds.some((id) => !positionIdList.includes(id))) throw new PanopticError("Premium protection requires currently held positions to close");
28823
+ const positionSizes = await getCurrentPositionSizes({
28446
28824
  client,
28447
28825
  poolAddress,
28448
- user: account,
28449
- callData,
28450
- blockNumber: targetBlockNumber
28826
+ account,
28827
+ positionIdList: closingTokenIds,
28828
+ blockNumber
28451
28829
  });
28452
- if (!flowResult.success || !flowResult.tokenFlow) {
28453
- const errorMessage = flowResult.error || "Simulation failed";
28454
- const isNotExercisable = errorMessage.includes("NoLegsExercisable") || errorMessage.includes("NotALongLeg");
28455
- if (isNotExercisable) {
28456
- const _meta$1 = await metaPromise;
28457
- const data$1 = {
28458
- exerciseFee0: 0n,
28459
- exerciseFee1: 0n,
28460
- canExercise: false,
28461
- reason: errorMessage.includes("NoLegsExercisable") ? "No legs are exercisable (not ITM)" : "Position does not have a long leg"
28462
- };
28463
- return {
28464
- success: true,
28465
- data: data$1,
28466
- gasEstimate: 0n,
28467
- tokenFlow: emptyTokenFlow,
28468
- _meta: _meta$1
28469
- };
28470
- }
28471
- throw new PanopticError(errorMessage);
28830
+ const { collectionDispatch } = buildProtectedSettlePlan({
28831
+ positionIdList: closingTokenIds,
28832
+ finalPositionIdList: positionIdList,
28833
+ positionSizes,
28834
+ builderCode: params.builderCode
28835
+ });
28836
+ const calls = (targets.length ? buildSettleSequenceCalls({
28837
+ positionIdListFrom: params.signerPositionIdList,
28838
+ targets
28839
+ }) : []).map((data) => ({
28840
+ to: poolAddress,
28841
+ data,
28842
+ account: params.signerAddress
28843
+ }));
28844
+ if (collectionDispatch !== void 0) {
28845
+ const [dispatchData] = buildSettleSequenceCalls({
28846
+ positionIdListFrom: positionIdList,
28847
+ targets: [],
28848
+ dispatch: collectionDispatch
28849
+ });
28850
+ if (dispatchData === void 0) throw new PanopticError("Premium protection collection dispatch is missing");
28851
+ calls.push({
28852
+ ...params.buildCollectionCall(dispatchData),
28853
+ account: params.signerAddress
28854
+ });
28472
28855
  }
28473
- const _meta = await metaPromise;
28474
- const tokenFlow = flowResult.tokenFlow;
28475
- const data = {
28476
- exerciseFee0: tokenFlow.delta0,
28477
- exerciseFee1: tokenFlow.delta1,
28478
- canExercise: true
28479
- };
28856
+ for (const includePendingPremium of [true, false]) calls.push({
28857
+ to: poolAddress,
28858
+ account: params.signerAddress,
28859
+ data: encodeFunctionData({
28860
+ abi: panopticPoolV2Abi,
28861
+ functionName: "getFullPositionsData",
28862
+ args: [
28863
+ account,
28864
+ includePendingPremium,
28865
+ closingTokenIds
28866
+ ]
28867
+ })
28868
+ });
28869
+ const blocks = await client.simulateBlocks({
28870
+ blocks: [{ calls }],
28871
+ blockNumber
28872
+ });
28873
+ const results = blocks[0]?.calls;
28874
+ if (results === void 0 || results.length !== calls.length) throw new PanopticError("Premium protection simulation returned incomplete results");
28875
+ for (const result$1 of results) if (result$1.status === "failure") throw result$1.error;
28876
+ const result = results.map((call$1) => call$1.data);
28877
+ const owedResult = result[result.length - 2];
28878
+ const availableResult = result[result.length - 1];
28879
+ if (owedResult === void 0 || availableResult === void 0) throw new PanopticError("Premium protection simulation returned incomplete results");
28880
+ const decodeShortPremium$1 = (data) => decodeLeftRightUnsigned(decodeFunctionResult({
28881
+ abi: panopticPoolV2Abi,
28882
+ functionName: "getFullPositionsData",
28883
+ data
28884
+ })[0]);
28885
+ const owed = decodeShortPremium$1(owedResult);
28886
+ const available = decodeShortPremium$1(availableResult);
28480
28887
  return {
28481
28888
  success: true,
28482
- data,
28483
- gasEstimate: flowResult.gasEstimate,
28484
- tokenFlow,
28485
- _meta
28889
+ gasEstimate: 0n,
28890
+ data: {
28891
+ owed0: owed.right,
28892
+ owed1: owed.left,
28893
+ available0: available.right,
28894
+ available1: available.left,
28895
+ forfeit0: owed.right > available.right ? owed.right - available.right : 0n,
28896
+ forfeit1: owed.left > available.left ? owed.left - available.left : 0n
28897
+ },
28898
+ _meta: await metaPromise
28486
28899
  };
28487
28900
  } catch (error) {
28488
- const _meta = await metaPromise;
28489
- const errorMessage = error instanceof Error ? error.message : "Simulation failed";
28490
- const isNotExercisable = errorMessage.includes("NoLegsExercisable") || errorMessage.includes("NotALongLeg");
28491
- if (isNotExercisable) {
28492
- const data = {
28493
- exerciseFee0: 0n,
28494
- exerciseFee1: 0n,
28495
- canExercise: false,
28496
- reason: errorMessage.includes("NoLegsExercisable") ? "No legs are exercisable (not ITM)" : "Position does not have a long leg"
28497
- };
28498
- return {
28499
- success: true,
28500
- data,
28501
- gasEstimate: 0n,
28502
- tokenFlow: emptyTokenFlow,
28503
- _meta
28504
- };
28505
- }
28901
+ const simulationError = error instanceof PanopticError ? error : new PanopticError(String(error));
28902
+ if (metaPromise === void 0) throw simulationError;
28506
28903
  return {
28507
28904
  success: false,
28508
- error: error instanceof PanopticError ? error : new PanopticError(errorMessage, error instanceof Error ? error : void 0),
28509
- _meta
28905
+ error: simulationError,
28906
+ _meta: await metaPromise
28510
28907
  };
28511
28908
  }
28512
28909
  }
28513
28910
 
28514
28911
  //#endregion
28515
- //#region src/panoptic/v2/simulations/simulateLiquidate.ts
28912
+ //#region src/panoptic/v2/simulations/simulateForceExercise.ts
28516
28913
  /**
28517
- * Simulate a liquidation operation.
28914
+ * Simulate a force exercise operation.
28518
28915
  *
28519
28916
  * @param params - Simulation parameters
28520
- * @returns Simulation result with liquidation data or error
28917
+ * @returns Simulation result with exercise data or error
28521
28918
  */
28522
- async function simulateLiquidate(params) {
28523
- const { client, poolAddress, account, liquidatee, positionIdListFrom, positionIdListTo, positionIdListToFinal, blockNumber } = params;
28919
+ async function simulateForceExercise(params) {
28920
+ const { client, poolAddress, account, user, positionIdListFrom, positionIdListTo, positionIdListToFinal, blockNumber } = params;
28921
+ const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
28922
+ const metaPromise = getBlockMeta({
28923
+ client,
28924
+ blockNumber: targetBlockNumber
28925
+ });
28926
+ const emptyTokenFlow = {
28927
+ delta0: 0n,
28928
+ delta1: 0n,
28929
+ balanceBefore0: 0n,
28930
+ balanceBefore1: 0n,
28931
+ balanceAfter0: 0n,
28932
+ balanceAfter1: 0n,
28933
+ tickBefore: null,
28934
+ tickAfter: null
28935
+ };
28936
+ try {
28937
+ const callData = encodeFunctionData({
28938
+ abi: panopticPoolV2Abi,
28939
+ functionName: "dispatchFrom",
28940
+ args: [
28941
+ positionIdListFrom,
28942
+ user,
28943
+ positionIdListTo,
28944
+ positionIdListToFinal,
28945
+ 0n
28946
+ ]
28947
+ });
28948
+ const flowResult = await simulateWithTokenFlow({
28949
+ client,
28950
+ poolAddress,
28951
+ user: account,
28952
+ callData,
28953
+ blockNumber: targetBlockNumber
28954
+ });
28955
+ if (!flowResult.success || !flowResult.tokenFlow) {
28956
+ const errorMessage = flowResult.error || "Simulation failed";
28957
+ const isNotExercisable = errorMessage.includes("NoLegsExercisable") || errorMessage.includes("NotALongLeg");
28958
+ if (isNotExercisable) {
28959
+ const _meta$1 = await metaPromise;
28960
+ const data$1 = {
28961
+ exerciseFee0: 0n,
28962
+ exerciseFee1: 0n,
28963
+ canExercise: false,
28964
+ reason: errorMessage.includes("NoLegsExercisable") ? "No legs are exercisable (not ITM)" : "Position does not have a long leg"
28965
+ };
28966
+ return {
28967
+ success: true,
28968
+ data: data$1,
28969
+ gasEstimate: 0n,
28970
+ tokenFlow: emptyTokenFlow,
28971
+ _meta: _meta$1
28972
+ };
28973
+ }
28974
+ throw new PanopticError(errorMessage);
28975
+ }
28976
+ const _meta = await metaPromise;
28977
+ const tokenFlow = flowResult.tokenFlow;
28978
+ const data = {
28979
+ exerciseFee0: tokenFlow.delta0,
28980
+ exerciseFee1: tokenFlow.delta1,
28981
+ canExercise: true
28982
+ };
28983
+ return {
28984
+ success: true,
28985
+ data,
28986
+ gasEstimate: flowResult.gasEstimate,
28987
+ tokenFlow,
28988
+ _meta
28989
+ };
28990
+ } catch (error) {
28991
+ const _meta = await metaPromise;
28992
+ const errorMessage = error instanceof Error ? error.message : "Simulation failed";
28993
+ const isNotExercisable = errorMessage.includes("NoLegsExercisable") || errorMessage.includes("NotALongLeg");
28994
+ if (isNotExercisable) {
28995
+ const data = {
28996
+ exerciseFee0: 0n,
28997
+ exerciseFee1: 0n,
28998
+ canExercise: false,
28999
+ reason: errorMessage.includes("NoLegsExercisable") ? "No legs are exercisable (not ITM)" : "Position does not have a long leg"
29000
+ };
29001
+ return {
29002
+ success: true,
29003
+ data,
29004
+ gasEstimate: 0n,
29005
+ tokenFlow: emptyTokenFlow,
29006
+ _meta
29007
+ };
29008
+ }
29009
+ return {
29010
+ success: false,
29011
+ error: error instanceof PanopticError ? error : new PanopticError(errorMessage, error instanceof Error ? error : void 0),
29012
+ _meta
29013
+ };
29014
+ }
29015
+ }
29016
+
29017
+ //#endregion
29018
+ //#region src/panoptic/v2/simulations/simulateLiquidate.ts
29019
+ /**
29020
+ * Simulate a liquidation operation.
29021
+ *
29022
+ * @param params - Simulation parameters
29023
+ * @returns Simulation result with liquidation data or error
29024
+ */
29025
+ async function simulateLiquidate(params) {
29026
+ const { client, poolAddress, account, liquidatee, positionIdListFrom, positionIdListTo, positionIdListToFinal, blockNumber } = params;
28524
29027
  const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
28525
29028
  const metaPromise = getBlockMeta({
28526
29029
  client,
@@ -29060,7 +29563,7 @@ async function simulateSwapExactIn(params) {
29060
29563
 
29061
29564
  //#endregion
29062
29565
  //#region src/panoptic/v2/simulations/oneTokenFlow.ts
29063
- const BPS_DENOMINATOR$2 = 10000n;
29566
+ const BPS_DENOMINATOR$3 = 10000n;
29064
29567
  /**
29065
29568
  * Default {@link OneTokenFlowQuoteParams.minSwapRatioBps}: 0.5%.
29066
29569
  *
@@ -29077,7 +29580,7 @@ function abs(value) {
29077
29580
  return value < 0n ? -value : value;
29078
29581
  }
29079
29582
  function padForSlippage(amount, slippageBps) {
29080
- return (amount * (BPS_DENOMINATOR$2 + slippageBps) + BPS_DENOMINATOR$2 - 1n) / BPS_DENOMINATOR$2;
29583
+ return (amount * (BPS_DENOMINATOR$3 + slippageBps) + BPS_DENOMINATOR$3 - 1n) / BPS_DENOMINATOR$3;
29081
29584
  }
29082
29585
  /**
29083
29586
  * Quote a dispatch wrapped so its net flow lands in `targetTokenIndex` only.
@@ -29097,10 +29600,10 @@ async function quoteOneTokenFlow(params) {
29097
29600
  reason: "invalid-target-token",
29098
29601
  detail: `targetTokenIndex=${targetTokenIndex} is neither 0 nor 1`
29099
29602
  };
29100
- if (params.slippageBps < 0n || params.slippageBps > BPS_DENOMINATOR$2) return {
29603
+ if (params.slippageBps < 0n || params.slippageBps > BPS_DENOMINATOR$3) return {
29101
29604
  available: false,
29102
29605
  reason: "invalid-slippage",
29103
- detail: `slippageBps=${params.slippageBps} is outside [0, ${BPS_DENOMINATOR$2}]`
29606
+ detail: `slippageBps=${params.slippageBps} is outside [0, ${BPS_DENOMINATOR$3}]`
29104
29607
  };
29105
29608
  const tickLimitLow = params.tickLimitLow ?? MIN_TICK;
29106
29609
  const tickLimitHigh = params.tickLimitHigh ?? MAX_TICK;
@@ -29190,7 +29693,7 @@ async function quoteOneTokenFlow(params) {
29190
29693
  if (minSwapRatioBps > 0n) {
29191
29694
  const residualInTargetTerms = convertToTokenIndex(abs(recovery.quote.netTokenOutChange), otherTokenIndex, targetTokenIndex, pool.sqrtPriceX96);
29192
29695
  const settledInTargetTerms = abs(recovery.quote.netTokenInChange) + residualInTargetTerms;
29193
- if (residualInTargetTerms * BPS_DENOMINATOR$2 >= minSwapRatioBps * settledInTargetTerms) return {
29696
+ if (residualInTargetTerms * BPS_DENOMINATOR$3 >= minSwapRatioBps * settledInTargetTerms) return {
29194
29697
  available: false,
29195
29698
  reason: "residual-not-single-token",
29196
29699
  detail: `covering the shortfall leaves ${recovery.quote.netTokenOutChange} of the other token (${residualInTargetTerms} in target token terms) against a target flow of ${recovery.quote.netTokenInChange}`
@@ -29219,7 +29722,7 @@ async function quoteOneTokenFlow(params) {
29219
29722
  }
29220
29723
  if (baseTargetDelta !== null && minSwapRatioBps > 0n) {
29221
29724
  const swapInTargetTerms = convertToTokenIndex(swapAmount, otherTokenIndex, targetTokenIndex, pool.sqrtPriceX96);
29222
- if (swapInTargetTerms * BPS_DENOMINATOR$2 < minSwapRatioBps * abs(baseTargetDelta)) return {
29725
+ if (swapInTargetTerms * BPS_DENOMINATOR$3 < minSwapRatioBps * abs(baseTargetDelta)) return {
29223
29726
  available: false,
29224
29727
  reason: "below-threshold",
29225
29728
  detail: `non-target flow ${swapInTargetTerms} (in target token terms) is below ${minSwapRatioBps}bps of the target flow ${abs(baseTargetDelta)}`
@@ -29305,6 +29808,251 @@ async function quoteOneTokenFlow(params) {
29305
29808
  };
29306
29809
  }
29307
29810
 
29811
+ //#endregion
29812
+ //#region src/uniswap/v4/router/encodeSwap.ts
29813
+ const UINT128_MAX$2 = (1n << 128n) - 1n;
29814
+
29815
+ //#endregion
29816
+ //#region src/uniswap/v4/router/permit2.ts
29817
+ /** uint160 max — the largest Permit2 allowance amount. */
29818
+ const UINT160_MAX = (1n << 160n) - 1n;
29819
+ /** uint48 max — the largest Permit2 expiration. */
29820
+ const UINT48_MAX = (1n << 48n) - 1n;
29821
+
29822
+ //#endregion
29823
+ //#region src/uniswap/v4/abis/v4Quoter.ts
29824
+ /**
29825
+ * Minimal V4Quoter ABI (`quoteExactInputSingle`, `quoteExactOutputSingle`).
29826
+ *
29827
+ * Note: neither function is `view` — they mutate state internally and are
29828
+ * intended to be called via `eth_call` / viem `simulateContract`, never
29829
+ * `readContract`.
29830
+ *
29831
+ * @module uniswap/v4/abis/v4Quoter
29832
+ */
29833
+ const quoteExactSingleParams = {
29834
+ name: "params",
29835
+ type: "tuple",
29836
+ components: [
29837
+ {
29838
+ name: "poolKey",
29839
+ type: "tuple",
29840
+ components: [
29841
+ {
29842
+ name: "currency0",
29843
+ type: "address"
29844
+ },
29845
+ {
29846
+ name: "currency1",
29847
+ type: "address"
29848
+ },
29849
+ {
29850
+ name: "fee",
29851
+ type: "uint24"
29852
+ },
29853
+ {
29854
+ name: "tickSpacing",
29855
+ type: "int24"
29856
+ },
29857
+ {
29858
+ name: "hooks",
29859
+ type: "address"
29860
+ }
29861
+ ]
29862
+ },
29863
+ {
29864
+ name: "zeroForOne",
29865
+ type: "bool"
29866
+ },
29867
+ {
29868
+ name: "exactAmount",
29869
+ type: "uint128"
29870
+ },
29871
+ {
29872
+ name: "hookData",
29873
+ type: "bytes"
29874
+ }
29875
+ ]
29876
+ };
29877
+ const v4QuoterAbi = [{
29878
+ type: "function",
29879
+ name: "quoteExactInputSingle",
29880
+ stateMutability: "nonpayable",
29881
+ inputs: [quoteExactSingleParams],
29882
+ outputs: [{
29883
+ name: "amountOut",
29884
+ type: "uint256"
29885
+ }, {
29886
+ name: "gasEstimate",
29887
+ type: "uint256"
29888
+ }]
29889
+ }, {
29890
+ type: "function",
29891
+ name: "quoteExactOutputSingle",
29892
+ stateMutability: "nonpayable",
29893
+ inputs: [quoteExactSingleParams],
29894
+ outputs: [{
29895
+ name: "amountIn",
29896
+ type: "uint256"
29897
+ }, {
29898
+ name: "gasEstimate",
29899
+ type: "uint256"
29900
+ }]
29901
+ }];
29902
+
29903
+ //#endregion
29904
+ //#region src/uniswap/v4/router/resolvePoolKey.ts
29905
+ /**
29906
+ * Resolve the PoolKey, swap direction, and output token metadata for a swap.
29907
+ *
29908
+ * @throws {InvalidSwapTokenError} when `tokenIn` is not part of the pool.
29909
+ */
29910
+ async function resolveSwapRoute(params) {
29911
+ const { client, poolAddress, chainId, tokenIn, blockNumber } = params;
29912
+ const pool = await getPool({
29913
+ client,
29914
+ poolAddress,
29915
+ chainId,
29916
+ blockNumber
29917
+ });
29918
+ const { poolKey } = pool;
29919
+ const isCurrency0 = isAddressEqual(tokenIn, poolKey.currency0);
29920
+ const isCurrency1 = isAddressEqual(tokenIn, poolKey.currency1);
29921
+ if (!isCurrency0 && !isCurrency1) throw new InvalidSwapTokenError(tokenIn, poolKey.currency0, poolKey.currency1);
29922
+ const zeroForOne = isCurrency0;
29923
+ const tokenOut = zeroForOne ? poolKey.currency1 : poolKey.currency0;
29924
+ const outTracker = zeroForOne ? pool.collateralTracker1 : pool.collateralTracker0;
29925
+ return {
29926
+ poolKey,
29927
+ zeroForOne,
29928
+ tokenOut,
29929
+ tokenOutDecimals: outTracker.decimals,
29930
+ tokenOutSymbol: outTracker.symbol
29931
+ };
29932
+ }
29933
+
29934
+ //#endregion
29935
+ //#region src/uniswap/v4/router/quote.ts
29936
+ const BPS_DENOMINATOR$2 = 10000n;
29937
+ const UINT128_MAX$1 = (1n << 128n) - 1n;
29938
+ /** Reject out-of-range slippage so the min/max amount math can't underflow/overflow. */
29939
+ function assertSlippageBps(slippageBps) {
29940
+ if (slippageBps < 0n || slippageBps > BPS_DENOMINATOR$2) throw new PanopticError(`invalid slippageBps ${slippageBps}, must be 0..10000`);
29941
+ }
29942
+ const FALLBACK_META = {
29943
+ blockNumber: 0n,
29944
+ blockTimestamp: 0n,
29945
+ blockHash: "0x0"
29946
+ };
29947
+ /**
29948
+ * Quote an exact-out spot swap against the underlying Uniswap v4 pool.
29949
+ *
29950
+ * Uses the V4Quoter `quoteExactOutputSingle` via `eth_call` (the quoter is
29951
+ * state-mutating / revert-based, so it must be simulated, not read). Returns a
29952
+ * `SimulationResult` so failures carry a structured error rather than throwing.
29953
+ */
29954
+ async function quoteSwapExactOutViaRouter(params) {
29955
+ const { client, poolAddress, chainId, tokenIn, amountOut, slippageBps, blockNumber, addresses } = params;
29956
+ try {
29957
+ if (amountOut < 0n || amountOut > UINT128_MAX$1) throw new PanopticError(`amountOut ${amountOut} exceeds uint128 maximum`);
29958
+ assertSlippageBps(slippageBps);
29959
+ const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
29960
+ const metaPromise = getBlockMeta({
29961
+ client,
29962
+ blockNumber: targetBlockNumber
29963
+ });
29964
+ const { v4Quoter } = getUniswapV4Addresses(chainId, addresses);
29965
+ if (v4Quoter === zeroAddress) throw new QuoterUnavailableError(chainId);
29966
+ const route = await resolveSwapRoute({
29967
+ client,
29968
+ poolAddress,
29969
+ chainId,
29970
+ tokenIn,
29971
+ blockNumber: targetBlockNumber
29972
+ });
29973
+ const { result } = await client.simulateContract({
29974
+ address: v4Quoter,
29975
+ abi: v4QuoterAbi,
29976
+ functionName: "quoteExactOutputSingle",
29977
+ blockNumber: targetBlockNumber,
29978
+ args: [{
29979
+ poolKey: {
29980
+ currency0: route.poolKey.currency0,
29981
+ currency1: route.poolKey.currency1,
29982
+ fee: Number(route.poolKey.fee),
29983
+ tickSpacing: Number(route.poolKey.tickSpacing),
29984
+ hooks: route.poolKey.hooks
29985
+ },
29986
+ zeroForOne: route.zeroForOne,
29987
+ exactAmount: amountOut,
29988
+ hookData: "0x"
29989
+ }]
29990
+ });
29991
+ const [amountIn, gasEstimate] = result;
29992
+ const amountInMaximum = (amountIn * (BPS_DENOMINATOR$2 + slippageBps) + BPS_DENOMINATOR$2 - 1n) / BPS_DENOMINATOR$2;
29993
+ const _meta = await metaPromise;
29994
+ return {
29995
+ success: true,
29996
+ data: {
29997
+ amountIn,
29998
+ amountInMaximum,
29999
+ zeroForOne: route.zeroForOne,
30000
+ tokenOut: route.tokenOut,
30001
+ poolKey: route.poolKey,
30002
+ gasEstimate
30003
+ },
30004
+ gasEstimate,
30005
+ _meta
30006
+ };
30007
+ } catch (error) {
30008
+ return {
30009
+ success: false,
30010
+ error: error instanceof PanopticError ? error : new PanopticError(error instanceof Error ? error.message : "Quote failed", error instanceof Error ? error : void 0),
30011
+ _meta: FALLBACK_META
30012
+ };
30013
+ }
30014
+ }
30015
+
30016
+ //#endregion
30017
+ //#region src/uniswap/v4/router/quoteByPoolKey.ts
30018
+ const UINT128_MAX = (1n << 128n) - 1n;
30019
+
30020
+ //#endregion
30021
+ //#region src/panoptic/v2/simulations/quoteTokenShortfallSwap.ts
30022
+ /** Quote the opposite pool token needed to buy the deficit in a NotEnoughTokens revert. */
30023
+ async function quoteTokenShortfallSwap({ client, chainId, poolAddress, error, slippageBps = 50n }) {
30024
+ const shortfall = getNotEnoughTokensError(error);
30025
+ if (shortfall === null || shortfall.deficit === 0n) return null;
30026
+ const metadata = await getPoolMetadata({
30027
+ client,
30028
+ poolAddress
30029
+ });
30030
+ const matches0 = [metadata.token0Asset, metadata.collateralToken0Address].some((address) => isAddressEqual(address, shortfall.tokenAddress));
30031
+ const matches1 = [metadata.token1Asset, metadata.collateralToken1Address].some((address) => isAddressEqual(address, shortfall.tokenAddress));
30032
+ if (matches0 === matches1) return null;
30033
+ const tokenIn = matches0 ? metadata.token1Asset : metadata.token0Asset;
30034
+ const quote = await (metadata.isV4 ? quoteSwapExactOutViaRouter : quoteSwapExactOutViaV3Router)({
30035
+ client,
30036
+ chainId,
30037
+ poolAddress,
30038
+ tokenIn,
30039
+ amountOut: shortfall.deficit,
30040
+ slippageBps
30041
+ });
30042
+ return {
30043
+ deficit: shortfall.deficit,
30044
+ outputSymbol: matches0 ? metadata.token0Symbol : metadata.token1Symbol,
30045
+ outputDecimals: matches0 ? metadata.token0Decimals : metadata.token1Decimals,
30046
+ inputSymbol: matches0 ? metadata.token1Symbol : metadata.token0Symbol,
30047
+ inputDecimals: matches0 ? metadata.token1Decimals : metadata.token0Decimals,
30048
+ tokenIn,
30049
+ slippageBps,
30050
+ poolFeePips: metadata.fee <= 1000000n ? metadata.fee : null,
30051
+ estimatedPoolFee: quote.success && metadata.fee <= 1000000n ? (quote.data.amountIn * metadata.fee + 999999n) / 1000000n : null,
30052
+ quote: quote.success ? quote.data : null
30053
+ };
30054
+ }
30055
+
29308
30056
  //#endregion
29309
30057
  //#region src/panoptic/v2/simulations/temporaryLoanRecovery.ts
29310
30058
  const BPS_DENOMINATOR$1 = 10000n;
@@ -30407,7 +31155,7 @@ const DEFAULT_INTERVAL_MS = 12000n;
30407
31155
  /**
30408
31156
  * Default maximum block range per poll.
30409
31157
  */
30410
- const DEFAULT_MAX_BLOCK_RANGE = 1000n;
31158
+ const DEFAULT_MAX_BLOCK_RANGE$1 = 1000n;
30411
31159
  /**
30412
31160
  * Create an HTTP polling-based event fetcher.
30413
31161
  *
@@ -30444,7 +31192,7 @@ const DEFAULT_MAX_BLOCK_RANGE = 1000n;
30444
31192
  * ```
30445
31193
  */
30446
31194
  function createEventPoller(params) {
30447
- const { client, poolAddress, collateralTracker0, collateralTracker1, riskEngineAddress, sfpmAddress, poolManagerAddress, eventTypes, onLogs, onError, intervalMs = DEFAULT_INTERVAL_MS, maxBlockRange = DEFAULT_MAX_BLOCK_RANGE, fromBlock } = params;
31195
+ const { client, poolAddress, collateralTracker0, collateralTracker1, riskEngineAddress, sfpmAddress, poolManagerAddress, eventTypes, onLogs, onError, intervalMs = DEFAULT_INTERVAL_MS, maxBlockRange = DEFAULT_MAX_BLOCK_RANGE$1, fromBlock } = params;
30448
31196
  let isRunning = false;
30449
31197
  let lastPolledBlock = fromBlock ?? 0n;
30450
31198
  let pollTimeout = null;
@@ -30633,272 +31381,1621 @@ function createEventPoller(params) {
30633
31381
  }
30634
31382
 
30635
31383
  //#endregion
30636
- //#region src/panoptic/v2/strike/ladder.ts
30637
- /** Target number of rungs across a leg's full range (lower tick → upper tick). */
30638
- const STRIKE_LADDER_TARGET_STRIKES = 16n;
30639
- /** Nice increment mantissas, in tenths (1, 2.5, 5) × 10ⁿ. */
30640
- const NICE_MANTISSAS_TENTHS = [
30641
- 10n,
30642
- 25n,
30643
- 50n
30644
- ];
30645
- /** Upper bound on rung hops when searching for a tick-changing step. */
30646
- const MAX_STEP_ITERATIONS = 512;
30647
- /** Decimal precision used when rendering exact tick prices as strings. */
30648
- const PRICE_PRECISION = 30n;
30649
- function floorDiv(a, b) {
30650
- const q = a / b;
30651
- return a % b !== 0n && a < 0n !== b < 0n ? q - 1n : q;
30652
- }
30653
- function floorMod(a, b) {
30654
- return a - floorDiv(a, b) * b;
30655
- }
30656
- function ceilDiv(a, b) {
30657
- return -floorDiv(-a, b);
30658
- }
30659
- /** round(a / b) to nearest, ties up. */
30660
- function roundDiv(a, b) {
30661
- return floorDiv(2n * a + b, 2n * b);
30662
- }
30663
- function pow10(exp) {
30664
- let result = 1n;
30665
- for (let i = 0n; i < exp; i++) result *= 10n;
30666
- return result;
30667
- }
30668
- function gcd(a, b) {
30669
- a = a < 0n ? -a : a;
30670
- b = b < 0n ? -b : b;
30671
- while (b !== 0n) [a, b] = [b, a % b];
30672
- return a;
30673
- }
30674
- function reduce(f) {
30675
- const g = gcd(f.numerator, f.denominator);
30676
- return g <= 1n ? f : {
30677
- numerator: f.numerator / g,
30678
- denominator: f.denominator / g
30679
- };
30680
- }
30681
- function fromBigint(n) {
30682
- return {
30683
- numerator: n,
30684
- denominator: 1n
30685
- };
30686
- }
30687
- function mul(a, b) {
30688
- return reduce({
30689
- numerator: a.numerator * b.numerator,
30690
- denominator: a.denominator * b.denominator
30691
- });
30692
- }
30693
- function add(a, b) {
30694
- return reduce({
30695
- numerator: a.numerator * b.denominator + b.numerator * a.denominator,
30696
- denominator: a.denominator * b.denominator
30697
- });
30698
- }
30699
- function sub(a, b) {
30700
- return add(a, {
30701
- numerator: -b.numerator,
30702
- denominator: b.denominator
30703
- });
30704
- }
30705
- /** -1 | 0 | 1 comparing a to b. */
30706
- function cmp(a, b) {
30707
- const l = a.numerator * b.denominator;
30708
- const r = b.numerator * a.denominator;
30709
- return l === r ? 0 : l < r ? -1 : 1;
30710
- }
30711
- const LADDER_MIN = fromBigint(1n);
30712
- /** Largest normalised price on the ladder. Prices above are "outside". */
30713
- const LADDER_MAX = fromBigint(1000000n);
30714
- function parseDecimal(value) {
30715
- const trimmed = value.trim();
30716
- const [basePart, exponentPart] = trimmed.toLowerCase().split("e");
30717
- const [integerStr, fractionalStr = ""] = basePart.split(".");
30718
- let numerator = BigInt(`${integerStr === "" ? "0" : integerStr}${fractionalStr}`);
30719
- let denominator = pow10(BigInt(fractionalStr.length));
30720
- if (exponentPart !== void 0 && exponentPart !== "") {
30721
- const exponent = BigInt(exponentPart);
30722
- if (exponent > 0n) numerator *= pow10(exponent);
30723
- else if (exponent < 0n) denominator *= pow10(-exponent);
30724
- }
30725
- if (numerator <= 0n) throw new Error("Price must be positive");
30726
- return reduce({
30727
- numerator,
30728
- denominator
30729
- });
30730
- }
30731
- /** Render a positive fraction as a decimal string with trailing zeros trimmed. */
30732
- function fractionToDecimal(f, precision) {
30733
- const scaled = f.numerator * pow10(precision) / f.denominator;
30734
- const digits = scaled.toString().padStart(Number(precision) + 1, "0");
30735
- const intPart = digits.slice(0, digits.length - Number(precision));
30736
- const fracPart = digits.slice(digits.length - Number(precision)).replace(/0+$/, "");
30737
- return fracPart.length === 0 ? intPart : `${intPart}.${fracPart}`;
30738
- }
30739
- /** 10^k as an exact fraction, k may be negative. */
30740
- function powerOfTen(k) {
30741
- return k >= 0n ? fromBigint(pow10(k)) : {
30742
- numerator: 1n,
30743
- denominator: pow10(-k)
30744
- };
30745
- }
30746
- /** floor(log10(f)) for a positive fraction. */
30747
- function floorLog10(f) {
30748
- let e = BigInt(f.numerator.toString().length - f.denominator.toString().length);
30749
- while (cmp(f, powerOfTen(e)) < 0) e -= 1n;
30750
- while (cmp(f, powerOfTen(e + 1n)) >= 0) e += 1n;
30751
- return e;
30752
- }
30753
- function orientTick(tick, orient) {
30754
- return orient.asset === 0n ? tick : -tick;
30755
- }
30756
- /** Exact-enough price of `tick` in the caller's orientation. */
30757
- function tickToOrientedPrice(tick, orient) {
30758
- const price = tickToPriceDecimalScaled(orientTick(tick, orient), orient.assetDecimals, orient.quoteDecimals, PRICE_PRECISION);
30759
- return parseDecimal(price);
30760
- }
30761
- /** Nearest integer tick for a caller-oriented decimal price. */
30762
- function orientedPriceToTick(price, orient) {
30763
- const t = priceToTick(price, orient.assetDecimals, orient.quoteDecimals);
30764
- return orientTick(t, orient);
30765
- }
30766
- /**
30767
- * Relative rung step for a leg: `1.0001^(round(width·tickSpacing / TARGET)) − 1`.
30768
- * Rungs scale with price (they are multiples of a price-proportional increment), so
30769
- * spacing them by the range's TARGET-th root yields ≈TARGET rungs across the range
30770
- * regardless of how wide it is.
30771
- */
30772
- function relativeStep(width, tickSpacing) {
30773
- validateGeometry(width, tickSpacing);
30774
- const ticks = roundDiv(width * tickSpacing, STRIKE_LADDER_TARGET_STRIKES);
30775
- const ratio = parseDecimal(tickToPriceDecimalScaled(ticks < 1n ? 1n : ticks, 0n, 0n, PRICE_PRECISION));
30776
- return sub(ratio, fromBigint(1n));
30777
- }
30778
- /** Nice increment `m × 10ⁿ` (m ∈ {1, 2.5, 5}) with the smallest log-distance to `raw`. */
30779
- function niceIncrement(raw) {
30780
- const e = floorLog10(raw);
30781
- const scale = (tenths) => mul(fromBigint(tenths), powerOfTen(e - 1n));
30782
- const candidates = [...NICE_MANTISSAS_TENTHS.map(scale), scale(100n)];
30783
- let lo = candidates[0] ?? powerOfTen(e);
30784
- for (const hi of candidates.slice(1)) {
30785
- if (cmp(raw, hi) < 0) return cmp(mul(raw, raw), mul(lo, hi)) <= 0 ? lo : hi;
30786
- lo = hi;
30787
- }
30788
- return lo;
30789
- }
30790
- /** Rung increment at normalised price `p` for the given relative step. */
30791
- function incrementAt(p, rf) {
30792
- return niceIncrement(mul(p, rf));
30793
- }
30794
- /** Normalise a price to `max(p, 1/p)` and remember whether it was inverted. */
30795
- function normalise(price) {
30796
- if (price.numerator >= price.denominator) return {
30797
- value: price,
30798
- reciprocal: false
30799
- };
30800
- return {
30801
- value: {
30802
- numerator: price.denominator,
30803
- denominator: price.numerator
30804
- },
30805
- reciprocal: true
30806
- };
30807
- }
30808
- /** Is `r` a multiple of `inc`? */
30809
- function isMultiple(r, inc) {
30810
- return r.numerator * inc.denominator % (r.denominator * inc.numerator) === 0n;
30811
- }
30812
- /** Smallest multiple of `inc` strictly greater than `x`. */
30813
- function ceilMultipleStrict(x, inc) {
30814
- const k = floorDiv(x.numerator * inc.denominator, x.denominator * inc.numerator) + 1n;
30815
- return mul(fromBigint(k), inc);
30816
- }
30817
- /** Largest multiple of `inc` strictly smaller than `x`. */
30818
- function floorMultipleStrict(x, inc) {
30819
- const k = ceilDiv(x.numerator * inc.denominator, x.denominator * inc.numerator) - 1n;
30820
- return mul(fromBigint(k), inc);
30821
- }
30822
- /**
30823
- * The rung set is `{ r : r is a multiple of incrementAt(r) }`. Because the
30824
- * increment grows with price, a multiple of a finer increment can land inside a
30825
- * coarser band where it is no longer a rung; these helpers push such a candidate
30826
- * up/down until it is a multiple of its own band's increment.
30827
- */
30828
- function isRung(r, rf) {
30829
- return r.numerator > 0n && isMultiple(r, incrementAt(r, rf));
30830
- }
30831
- function fixUp(c, rf) {
30832
- for (let i = 0; i < 64 && !isRung(c, rf); i++) c = ceilMultipleStrict(c, incrementAt(c, rf));
30833
- return c;
30834
- }
30835
- function fixDown(c, rf) {
30836
- for (let i = 0; i < 64 && c.numerator > 0n && !isRung(c, rf); i++) c = floorMultipleStrict(c, incrementAt(c, rf));
30837
- return c;
30838
- }
30839
- /** Smallest rung strictly above `x` (may exceed the ladder top). */
30840
- function nextRungAbove(x, rf) {
30841
- const incHere = incrementAt(x, rf);
30842
- const incs = [incHere, incrementAt(add(x, incHere), rf)];
30843
- let best = null;
30844
- for (const inc of incs) {
30845
- const c = fixUp(ceilMultipleStrict(x, inc), rf);
30846
- if (cmp(c, x) > 0 && (best === null || cmp(c, best) < 0)) best = c;
30847
- }
30848
- if (best === null) throw new PanopticValidationError("No ladder rung above price");
30849
- return best;
30850
- }
30851
- /** Largest rung strictly below `x` (may fall below the ladder floor). */
30852
- function prevRungBelow(x, rf) {
30853
- const incHere = incrementAt(x, rf);
30854
- const finer = incrementAt(sub(x, incHere), rf);
30855
- let best = null;
30856
- for (const inc of [incHere, finer]) {
30857
- const c = fixDown(floorMultipleStrict(x, inc), rf);
30858
- if (c.numerator > 0n && cmp(c, x) < 0 && (best === null || cmp(c, best) > 0)) best = c;
30859
- }
30860
- return best ?? fromBigint(0n);
30861
- }
30862
- /** Nearest rung price to a normalised price, or null when above the ladder. */
30863
- function nearestRungPrice(normalised, rf) {
30864
- let rung;
30865
- if (isRung(normalised, rf)) rung = normalised;
30866
- else {
30867
- const up = nextRungAbove(normalised, rf);
30868
- const down = prevRungBelow(normalised, rf);
30869
- if (down.numerator <= 0n) rung = up;
30870
- else rung = cmp(sub(normalised, down), sub(up, normalised)) <= 0 ? down : up;
30871
- }
30872
- if (cmp(rung, LADDER_MIN) < 0) rung = LADDER_MIN;
30873
- if (cmp(rung, LADDER_MAX) > 0) return null;
30874
- return rung;
30875
- }
30876
- /** Step one rung up (+1) or down (-1) on the normalised ladder. Null when leaving it. */
30877
- function stepRungPrice(rung, direction, rf) {
30878
- const next = direction > 0n ? nextRungAbove(rung, rf) : prevRungBelow(rung, rf);
30879
- if (cmp(next, LADDER_MIN) < 0 || cmp(next, LADDER_MAX) > 0) return null;
30880
- return next;
30881
- }
30882
- /** Nominal caller-oriented price of a rung as an exact fraction. */
30883
- function rungToPrice(rung) {
30884
- return rung.reciprocal ? {
30885
- numerator: rung.price.denominator,
30886
- denominator: rung.price.numerator
30887
- } : rung.price;
30888
- }
30889
- function rungToPriceString(rung) {
30890
- return fractionToDecimal(rungToPrice(rung), PRICE_PRECISION);
30891
- }
30892
- function nearestRung(price, rf) {
30893
- const { value, reciprocal } = normalise(price);
30894
- const p = nearestRungPrice(value, rf);
30895
- return p === null ? null : {
30896
- price: p,
30897
- reciprocal
30898
- };
30899
- }
30900
- /**
30901
- * Step a rung in the caller's price direction. For reciprocal quotes a higher
31384
+ //#region src/abis/UniswapV3Pool.ts
31385
+ const UniswapV3PoolAbi = [
31386
+ {
31387
+ inputs: [],
31388
+ stateMutability: "payable",
31389
+ type: "constructor"
31390
+ },
31391
+ {
31392
+ anonymous: false,
31393
+ inputs: [
31394
+ {
31395
+ indexed: true,
31396
+ internalType: "address",
31397
+ name: "owner",
31398
+ type: "address"
31399
+ },
31400
+ {
31401
+ indexed: true,
31402
+ internalType: "int24",
31403
+ name: "tickLower",
31404
+ type: "int24"
31405
+ },
31406
+ {
31407
+ indexed: true,
31408
+ internalType: "int24",
31409
+ name: "tickUpper",
31410
+ type: "int24"
31411
+ },
31412
+ {
31413
+ indexed: false,
31414
+ internalType: "uint128",
31415
+ name: "amount",
31416
+ type: "uint128"
31417
+ },
31418
+ {
31419
+ indexed: false,
31420
+ internalType: "uint256",
31421
+ name: "amount0",
31422
+ type: "uint256"
31423
+ },
31424
+ {
31425
+ indexed: false,
31426
+ internalType: "uint256",
31427
+ name: "amount1",
31428
+ type: "uint256"
31429
+ }
31430
+ ],
31431
+ name: "Burn",
31432
+ type: "event"
31433
+ },
31434
+ {
31435
+ anonymous: false,
31436
+ inputs: [
31437
+ {
31438
+ indexed: true,
31439
+ internalType: "address",
31440
+ name: "owner",
31441
+ type: "address"
31442
+ },
31443
+ {
31444
+ indexed: false,
31445
+ internalType: "address",
31446
+ name: "recipient",
31447
+ type: "address"
31448
+ },
31449
+ {
31450
+ indexed: true,
31451
+ internalType: "int24",
31452
+ name: "tickLower",
31453
+ type: "int24"
31454
+ },
31455
+ {
31456
+ indexed: true,
31457
+ internalType: "int24",
31458
+ name: "tickUpper",
31459
+ type: "int24"
31460
+ },
31461
+ {
31462
+ indexed: false,
31463
+ internalType: "uint128",
31464
+ name: "amount0",
31465
+ type: "uint128"
31466
+ },
31467
+ {
31468
+ indexed: false,
31469
+ internalType: "uint128",
31470
+ name: "amount1",
31471
+ type: "uint128"
31472
+ }
31473
+ ],
31474
+ name: "Collect",
31475
+ type: "event"
31476
+ },
31477
+ {
31478
+ anonymous: false,
31479
+ inputs: [
31480
+ {
31481
+ indexed: true,
31482
+ internalType: "address",
31483
+ name: "sender",
31484
+ type: "address"
31485
+ },
31486
+ {
31487
+ indexed: true,
31488
+ internalType: "address",
31489
+ name: "recipient",
31490
+ type: "address"
31491
+ },
31492
+ {
31493
+ indexed: false,
31494
+ internalType: "uint128",
31495
+ name: "amount0",
31496
+ type: "uint128"
31497
+ },
31498
+ {
31499
+ indexed: false,
31500
+ internalType: "uint128",
31501
+ name: "amount1",
31502
+ type: "uint128"
31503
+ }
31504
+ ],
31505
+ name: "CollectProtocol",
31506
+ type: "event"
31507
+ },
31508
+ {
31509
+ anonymous: false,
31510
+ inputs: [
31511
+ {
31512
+ indexed: true,
31513
+ internalType: "address",
31514
+ name: "sender",
31515
+ type: "address"
31516
+ },
31517
+ {
31518
+ indexed: true,
31519
+ internalType: "address",
31520
+ name: "recipient",
31521
+ type: "address"
31522
+ },
31523
+ {
31524
+ indexed: false,
31525
+ internalType: "uint256",
31526
+ name: "amount0",
31527
+ type: "uint256"
31528
+ },
31529
+ {
31530
+ indexed: false,
31531
+ internalType: "uint256",
31532
+ name: "amount1",
31533
+ type: "uint256"
31534
+ },
31535
+ {
31536
+ indexed: false,
31537
+ internalType: "uint256",
31538
+ name: "paid0",
31539
+ type: "uint256"
31540
+ },
31541
+ {
31542
+ indexed: false,
31543
+ internalType: "uint256",
31544
+ name: "paid1",
31545
+ type: "uint256"
31546
+ }
31547
+ ],
31548
+ name: "Flash",
31549
+ type: "event"
31550
+ },
31551
+ {
31552
+ anonymous: false,
31553
+ inputs: [{
31554
+ indexed: false,
31555
+ internalType: "uint16",
31556
+ name: "observationCardinalityNextOld",
31557
+ type: "uint16"
31558
+ }, {
31559
+ indexed: false,
31560
+ internalType: "uint16",
31561
+ name: "observationCardinalityNextNew",
31562
+ type: "uint16"
31563
+ }],
31564
+ name: "IncreaseObservationCardinalityNext",
31565
+ type: "event"
31566
+ },
31567
+ {
31568
+ anonymous: false,
31569
+ inputs: [{
31570
+ indexed: false,
31571
+ internalType: "uint160",
31572
+ name: "sqrtPriceX96",
31573
+ type: "uint160"
31574
+ }, {
31575
+ indexed: false,
31576
+ internalType: "int24",
31577
+ name: "tick",
31578
+ type: "int24"
31579
+ }],
31580
+ name: "Initialize",
31581
+ type: "event"
31582
+ },
31583
+ {
31584
+ anonymous: false,
31585
+ inputs: [
31586
+ {
31587
+ indexed: false,
31588
+ internalType: "address",
31589
+ name: "sender",
31590
+ type: "address"
31591
+ },
31592
+ {
31593
+ indexed: true,
31594
+ internalType: "address",
31595
+ name: "owner",
31596
+ type: "address"
31597
+ },
31598
+ {
31599
+ indexed: true,
31600
+ internalType: "int24",
31601
+ name: "tickLower",
31602
+ type: "int24"
31603
+ },
31604
+ {
31605
+ indexed: true,
31606
+ internalType: "int24",
31607
+ name: "tickUpper",
31608
+ type: "int24"
31609
+ },
31610
+ {
31611
+ indexed: false,
31612
+ internalType: "uint128",
31613
+ name: "amount",
31614
+ type: "uint128"
31615
+ },
31616
+ {
31617
+ indexed: false,
31618
+ internalType: "uint256",
31619
+ name: "amount0",
31620
+ type: "uint256"
31621
+ },
31622
+ {
31623
+ indexed: false,
31624
+ internalType: "uint256",
31625
+ name: "amount1",
31626
+ type: "uint256"
31627
+ }
31628
+ ],
31629
+ name: "Mint",
31630
+ type: "event"
31631
+ },
31632
+ {
31633
+ anonymous: false,
31634
+ inputs: [
31635
+ {
31636
+ indexed: false,
31637
+ internalType: "uint8",
31638
+ name: "feeProtocol0Old",
31639
+ type: "uint8"
31640
+ },
31641
+ {
31642
+ indexed: false,
31643
+ internalType: "uint8",
31644
+ name: "feeProtocol1Old",
31645
+ type: "uint8"
31646
+ },
31647
+ {
31648
+ indexed: false,
31649
+ internalType: "uint8",
31650
+ name: "feeProtocol0New",
31651
+ type: "uint8"
31652
+ },
31653
+ {
31654
+ indexed: false,
31655
+ internalType: "uint8",
31656
+ name: "feeProtocol1New",
31657
+ type: "uint8"
31658
+ }
31659
+ ],
31660
+ name: "SetFeeProtocol",
31661
+ type: "event"
31662
+ },
31663
+ {
31664
+ anonymous: false,
31665
+ inputs: [
31666
+ {
31667
+ indexed: true,
31668
+ internalType: "address",
31669
+ name: "sender",
31670
+ type: "address"
31671
+ },
31672
+ {
31673
+ indexed: true,
31674
+ internalType: "address",
31675
+ name: "recipient",
31676
+ type: "address"
31677
+ },
31678
+ {
31679
+ indexed: false,
31680
+ internalType: "int256",
31681
+ name: "amount0",
31682
+ type: "int256"
31683
+ },
31684
+ {
31685
+ indexed: false,
31686
+ internalType: "int256",
31687
+ name: "amount1",
31688
+ type: "int256"
31689
+ },
31690
+ {
31691
+ indexed: false,
31692
+ internalType: "uint160",
31693
+ name: "sqrtPriceX96",
31694
+ type: "uint160"
31695
+ },
31696
+ {
31697
+ indexed: false,
31698
+ internalType: "uint128",
31699
+ name: "liquidity",
31700
+ type: "uint128"
31701
+ },
31702
+ {
31703
+ indexed: false,
31704
+ internalType: "int24",
31705
+ name: "tick",
31706
+ type: "int24"
31707
+ }
31708
+ ],
31709
+ name: "Swap",
31710
+ type: "event"
31711
+ },
31712
+ {
31713
+ inputs: [
31714
+ {
31715
+ internalType: "int24",
31716
+ name: "tickLower",
31717
+ type: "int24"
31718
+ },
31719
+ {
31720
+ internalType: "int24",
31721
+ name: "tickUpper",
31722
+ type: "int24"
31723
+ },
31724
+ {
31725
+ internalType: "uint128",
31726
+ name: "amount",
31727
+ type: "uint128"
31728
+ }
31729
+ ],
31730
+ name: "burn",
31731
+ outputs: [{
31732
+ internalType: "uint256",
31733
+ name: "amount0",
31734
+ type: "uint256"
31735
+ }, {
31736
+ internalType: "uint256",
31737
+ name: "amount1",
31738
+ type: "uint256"
31739
+ }],
31740
+ stateMutability: "payable",
31741
+ type: "function"
31742
+ },
31743
+ {
31744
+ inputs: [
31745
+ {
31746
+ internalType: "address",
31747
+ name: "recipient",
31748
+ type: "address"
31749
+ },
31750
+ {
31751
+ internalType: "int24",
31752
+ name: "tickLower",
31753
+ type: "int24"
31754
+ },
31755
+ {
31756
+ internalType: "int24",
31757
+ name: "tickUpper",
31758
+ type: "int24"
31759
+ },
31760
+ {
31761
+ internalType: "uint128",
31762
+ name: "amount0Requested",
31763
+ type: "uint128"
31764
+ },
31765
+ {
31766
+ internalType: "uint128",
31767
+ name: "amount1Requested",
31768
+ type: "uint128"
31769
+ }
31770
+ ],
31771
+ name: "collect",
31772
+ outputs: [{
31773
+ internalType: "uint128",
31774
+ name: "amount0",
31775
+ type: "uint128"
31776
+ }, {
31777
+ internalType: "uint128",
31778
+ name: "amount1",
31779
+ type: "uint128"
31780
+ }],
31781
+ stateMutability: "payable",
31782
+ type: "function"
31783
+ },
31784
+ {
31785
+ inputs: [
31786
+ {
31787
+ internalType: "address",
31788
+ name: "recipient",
31789
+ type: "address"
31790
+ },
31791
+ {
31792
+ internalType: "uint128",
31793
+ name: "amount0Requested",
31794
+ type: "uint128"
31795
+ },
31796
+ {
31797
+ internalType: "uint128",
31798
+ name: "amount1Requested",
31799
+ type: "uint128"
31800
+ }
31801
+ ],
31802
+ name: "collectProtocol",
31803
+ outputs: [{
31804
+ internalType: "uint128",
31805
+ name: "amount0",
31806
+ type: "uint128"
31807
+ }, {
31808
+ internalType: "uint128",
31809
+ name: "amount1",
31810
+ type: "uint128"
31811
+ }],
31812
+ stateMutability: "payable",
31813
+ type: "function"
31814
+ },
31815
+ {
31816
+ inputs: [],
31817
+ name: "factory",
31818
+ outputs: [{
31819
+ internalType: "address",
31820
+ name: "",
31821
+ type: "address"
31822
+ }],
31823
+ stateMutability: "view",
31824
+ type: "function"
31825
+ },
31826
+ {
31827
+ inputs: [],
31828
+ name: "fee",
31829
+ outputs: [{
31830
+ internalType: "uint24",
31831
+ name: "",
31832
+ type: "uint24"
31833
+ }],
31834
+ stateMutability: "view",
31835
+ type: "function"
31836
+ },
31837
+ {
31838
+ inputs: [],
31839
+ name: "feeGrowthGlobal0X128",
31840
+ outputs: [{
31841
+ internalType: "uint256",
31842
+ name: "",
31843
+ type: "uint256"
31844
+ }],
31845
+ stateMutability: "view",
31846
+ type: "function"
31847
+ },
31848
+ {
31849
+ inputs: [],
31850
+ name: "feeGrowthGlobal1X128",
31851
+ outputs: [{
31852
+ internalType: "uint256",
31853
+ name: "",
31854
+ type: "uint256"
31855
+ }],
31856
+ stateMutability: "view",
31857
+ type: "function"
31858
+ },
31859
+ {
31860
+ inputs: [
31861
+ {
31862
+ internalType: "address",
31863
+ name: "recipient",
31864
+ type: "address"
31865
+ },
31866
+ {
31867
+ internalType: "uint256",
31868
+ name: "amount0",
31869
+ type: "uint256"
31870
+ },
31871
+ {
31872
+ internalType: "uint256",
31873
+ name: "amount1",
31874
+ type: "uint256"
31875
+ },
31876
+ {
31877
+ internalType: "bytes",
31878
+ name: "data",
31879
+ type: "bytes"
31880
+ }
31881
+ ],
31882
+ name: "flash",
31883
+ outputs: [],
31884
+ stateMutability: "payable",
31885
+ type: "function"
31886
+ },
31887
+ {
31888
+ inputs: [{
31889
+ internalType: "uint16",
31890
+ name: "observationCardinalityNext",
31891
+ type: "uint16"
31892
+ }],
31893
+ name: "increaseObservationCardinalityNext",
31894
+ outputs: [],
31895
+ stateMutability: "payable",
31896
+ type: "function"
31897
+ },
31898
+ {
31899
+ inputs: [{
31900
+ internalType: "uint160",
31901
+ name: "sqrtPriceX96",
31902
+ type: "uint160"
31903
+ }],
31904
+ name: "initialize",
31905
+ outputs: [],
31906
+ stateMutability: "payable",
31907
+ type: "function"
31908
+ },
31909
+ {
31910
+ inputs: [],
31911
+ name: "liquidity",
31912
+ outputs: [{
31913
+ internalType: "uint128",
31914
+ name: "",
31915
+ type: "uint128"
31916
+ }],
31917
+ stateMutability: "view",
31918
+ type: "function"
31919
+ },
31920
+ {
31921
+ inputs: [],
31922
+ name: "maxLiquidityPerTick",
31923
+ outputs: [{
31924
+ internalType: "uint128",
31925
+ name: "",
31926
+ type: "uint128"
31927
+ }],
31928
+ stateMutability: "view",
31929
+ type: "function"
31930
+ },
31931
+ {
31932
+ inputs: [
31933
+ {
31934
+ internalType: "address",
31935
+ name: "recipient",
31936
+ type: "address"
31937
+ },
31938
+ {
31939
+ internalType: "int24",
31940
+ name: "tickLower",
31941
+ type: "int24"
31942
+ },
31943
+ {
31944
+ internalType: "int24",
31945
+ name: "tickUpper",
31946
+ type: "int24"
31947
+ },
31948
+ {
31949
+ internalType: "uint128",
31950
+ name: "amount",
31951
+ type: "uint128"
31952
+ },
31953
+ {
31954
+ internalType: "bytes",
31955
+ name: "data",
31956
+ type: "bytes"
31957
+ }
31958
+ ],
31959
+ name: "mint",
31960
+ outputs: [{
31961
+ internalType: "uint256",
31962
+ name: "amount0",
31963
+ type: "uint256"
31964
+ }, {
31965
+ internalType: "uint256",
31966
+ name: "amount1",
31967
+ type: "uint256"
31968
+ }],
31969
+ stateMutability: "payable",
31970
+ type: "function"
31971
+ },
31972
+ {
31973
+ inputs: [{
31974
+ internalType: "uint256",
31975
+ name: "",
31976
+ type: "uint256"
31977
+ }],
31978
+ name: "observations",
31979
+ outputs: [
31980
+ {
31981
+ internalType: "uint32",
31982
+ name: "blockTimestamp",
31983
+ type: "uint32"
31984
+ },
31985
+ {
31986
+ internalType: "int56",
31987
+ name: "tickCumulative",
31988
+ type: "int56"
31989
+ },
31990
+ {
31991
+ internalType: "uint160",
31992
+ name: "secondsPerLiquidityCumulativeX128",
31993
+ type: "uint160"
31994
+ },
31995
+ {
31996
+ internalType: "bool",
31997
+ name: "initialized",
31998
+ type: "bool"
31999
+ }
32000
+ ],
32001
+ stateMutability: "view",
32002
+ type: "function"
32003
+ },
32004
+ {
32005
+ inputs: [{
32006
+ internalType: "uint32[]",
32007
+ name: "secondsAgos",
32008
+ type: "uint32[]"
32009
+ }],
32010
+ name: "observe",
32011
+ outputs: [{
32012
+ internalType: "int56[]",
32013
+ name: "tickCumulatives",
32014
+ type: "int56[]"
32015
+ }, {
32016
+ internalType: "uint160[]",
32017
+ name: "secondsPerLiquidityCumulativeX128s",
32018
+ type: "uint160[]"
32019
+ }],
32020
+ stateMutability: "view",
32021
+ type: "function"
32022
+ },
32023
+ {
32024
+ inputs: [{
32025
+ internalType: "bytes32",
32026
+ name: "",
32027
+ type: "bytes32"
32028
+ }],
32029
+ name: "positions",
32030
+ outputs: [
32031
+ {
32032
+ internalType: "uint128",
32033
+ name: "liquidity",
32034
+ type: "uint128"
32035
+ },
32036
+ {
32037
+ internalType: "uint256",
32038
+ name: "feeGrowthInside0LastX128",
32039
+ type: "uint256"
32040
+ },
32041
+ {
32042
+ internalType: "uint256",
32043
+ name: "feeGrowthInside1LastX128",
32044
+ type: "uint256"
32045
+ },
32046
+ {
32047
+ internalType: "uint128",
32048
+ name: "tokensOwed0",
32049
+ type: "uint128"
32050
+ },
32051
+ {
32052
+ internalType: "uint128",
32053
+ name: "tokensOwed1",
32054
+ type: "uint128"
32055
+ }
32056
+ ],
32057
+ stateMutability: "view",
32058
+ type: "function"
32059
+ },
32060
+ {
32061
+ inputs: [],
32062
+ name: "protocolFees",
32063
+ outputs: [{
32064
+ internalType: "uint128",
32065
+ name: "token0",
32066
+ type: "uint128"
32067
+ }, {
32068
+ internalType: "uint128",
32069
+ name: "token1",
32070
+ type: "uint128"
32071
+ }],
32072
+ stateMutability: "view",
32073
+ type: "function"
32074
+ },
32075
+ {
32076
+ inputs: [{
32077
+ internalType: "uint8",
32078
+ name: "feeProtocol0",
32079
+ type: "uint8"
32080
+ }, {
32081
+ internalType: "uint8",
32082
+ name: "feeProtocol1",
32083
+ type: "uint8"
32084
+ }],
32085
+ name: "setFeeProtocol",
32086
+ outputs: [],
32087
+ stateMutability: "payable",
32088
+ type: "function"
32089
+ },
32090
+ {
32091
+ inputs: [],
32092
+ name: "slot0",
32093
+ outputs: [
32094
+ {
32095
+ internalType: "uint160",
32096
+ name: "sqrtPriceX96",
32097
+ type: "uint160"
32098
+ },
32099
+ {
32100
+ internalType: "int24",
32101
+ name: "tick",
32102
+ type: "int24"
32103
+ },
32104
+ {
32105
+ internalType: "uint16",
32106
+ name: "observationIndex",
32107
+ type: "uint16"
32108
+ },
32109
+ {
32110
+ internalType: "uint16",
32111
+ name: "observationCardinality",
32112
+ type: "uint16"
32113
+ },
32114
+ {
32115
+ internalType: "uint16",
32116
+ name: "observationCardinalityNext",
32117
+ type: "uint16"
32118
+ },
32119
+ {
32120
+ internalType: "uint8",
32121
+ name: "feeProtocol",
32122
+ type: "uint8"
32123
+ },
32124
+ {
32125
+ internalType: "bool",
32126
+ name: "unlocked",
32127
+ type: "bool"
32128
+ }
32129
+ ],
32130
+ stateMutability: "view",
32131
+ type: "function"
32132
+ },
32133
+ {
32134
+ inputs: [{
32135
+ internalType: "int24",
32136
+ name: "tickLower",
32137
+ type: "int24"
32138
+ }, {
32139
+ internalType: "int24",
32140
+ name: "tickUpper",
32141
+ type: "int24"
32142
+ }],
32143
+ name: "snapshotCumulativesInside",
32144
+ outputs: [
32145
+ {
32146
+ internalType: "int56",
32147
+ name: "tickCumulativeInside",
32148
+ type: "int56"
32149
+ },
32150
+ {
32151
+ internalType: "uint160",
32152
+ name: "secondsPerLiquidityInsideX128",
32153
+ type: "uint160"
32154
+ },
32155
+ {
32156
+ internalType: "uint32",
32157
+ name: "secondsInside",
32158
+ type: "uint32"
32159
+ }
32160
+ ],
32161
+ stateMutability: "view",
32162
+ type: "function"
32163
+ },
32164
+ {
32165
+ inputs: [
32166
+ {
32167
+ internalType: "address",
32168
+ name: "recipient",
32169
+ type: "address"
32170
+ },
32171
+ {
32172
+ internalType: "bool",
32173
+ name: "zeroForOne",
32174
+ type: "bool"
32175
+ },
32176
+ {
32177
+ internalType: "int256",
32178
+ name: "amountSpecified",
32179
+ type: "int256"
32180
+ },
32181
+ {
32182
+ internalType: "uint160",
32183
+ name: "sqrtPriceLimitX96",
32184
+ type: "uint160"
32185
+ },
32186
+ {
32187
+ internalType: "bytes",
32188
+ name: "data",
32189
+ type: "bytes"
32190
+ }
32191
+ ],
32192
+ name: "swap",
32193
+ outputs: [{
32194
+ internalType: "int256",
32195
+ name: "amount0",
32196
+ type: "int256"
32197
+ }, {
32198
+ internalType: "int256",
32199
+ name: "amount1",
32200
+ type: "int256"
32201
+ }],
32202
+ stateMutability: "payable",
32203
+ type: "function"
32204
+ },
32205
+ {
32206
+ inputs: [{
32207
+ internalType: "int16",
32208
+ name: "",
32209
+ type: "int16"
32210
+ }],
32211
+ name: "tickBitmap",
32212
+ outputs: [{
32213
+ internalType: "uint256",
32214
+ name: "",
32215
+ type: "uint256"
32216
+ }],
32217
+ stateMutability: "view",
32218
+ type: "function"
32219
+ },
32220
+ {
32221
+ inputs: [],
32222
+ name: "tickSpacing",
32223
+ outputs: [{
32224
+ internalType: "int24",
32225
+ name: "",
32226
+ type: "int24"
32227
+ }],
32228
+ stateMutability: "view",
32229
+ type: "function"
32230
+ },
32231
+ {
32232
+ inputs: [{
32233
+ internalType: "int24",
32234
+ name: "",
32235
+ type: "int24"
32236
+ }],
32237
+ name: "ticks",
32238
+ outputs: [
32239
+ {
32240
+ internalType: "uint128",
32241
+ name: "liquidityGross",
32242
+ type: "uint128"
32243
+ },
32244
+ {
32245
+ internalType: "int128",
32246
+ name: "liquidityNet",
32247
+ type: "int128"
32248
+ },
32249
+ {
32250
+ internalType: "uint256",
32251
+ name: "feeGrowthOutside0X128",
32252
+ type: "uint256"
32253
+ },
32254
+ {
32255
+ internalType: "uint256",
32256
+ name: "feeGrowthOutside1X128",
32257
+ type: "uint256"
32258
+ },
32259
+ {
32260
+ internalType: "int56",
32261
+ name: "tickCumulativeOutside",
32262
+ type: "int56"
32263
+ },
32264
+ {
32265
+ internalType: "uint160",
32266
+ name: "secondsPerLiquidityOutsideX128",
32267
+ type: "uint160"
32268
+ },
32269
+ {
32270
+ internalType: "uint32",
32271
+ name: "secondsOutside",
32272
+ type: "uint32"
32273
+ },
32274
+ {
32275
+ internalType: "bool",
32276
+ name: "initialized",
32277
+ type: "bool"
32278
+ }
32279
+ ],
32280
+ stateMutability: "view",
32281
+ type: "function"
32282
+ },
32283
+ {
32284
+ inputs: [],
32285
+ name: "token0",
32286
+ outputs: [{
32287
+ internalType: "address",
32288
+ name: "",
32289
+ type: "address"
32290
+ }],
32291
+ stateMutability: "view",
32292
+ type: "function"
32293
+ },
32294
+ {
32295
+ inputs: [],
32296
+ name: "token1",
32297
+ outputs: [{
32298
+ internalType: "address",
32299
+ name: "",
32300
+ type: "address"
32301
+ }],
32302
+ stateMutability: "view",
32303
+ type: "function"
32304
+ }
32305
+ ];
32306
+
32307
+ //#endregion
32308
+ //#region src/panoptic/v2/events/poolSwapStream.ts
32309
+ const DEFAULT_POLL_INTERVAL_MS$1 = 3e3;
32310
+ const FAILURE_WINDOW_MS = 3e4;
32311
+ const FAILURES_BEFORE_POLL = 3;
32312
+ const STREAM_RETRY_MIN_MS = 15e3;
32313
+ const STREAM_RETRY_MAX_MS = 3e5;
32314
+ const RESYNC_JITTER_MS = 2e3;
32315
+ const EVENT_SOURCE_CLOSED = 2;
32316
+ function parseRecord(data) {
32317
+ const value = JSON.parse(data);
32318
+ if (typeof value !== "object" || value === null) throw new Error("Malformed stream frame");
32319
+ return value;
32320
+ }
32321
+ function bigintField(record, field) {
32322
+ const value = record[field];
32323
+ if (typeof value !== "string") throw new Error(`Stream frame is missing ${field}`);
32324
+ return BigInt(value);
32325
+ }
32326
+ function numberField(record, field) {
32327
+ const value = record[field];
32328
+ if (typeof value !== "number") throw new Error(`Stream frame is missing ${field}`);
32329
+ return value;
32330
+ }
32331
+ function parseStreamedKey(data) {
32332
+ const record = parseRecord(data);
32333
+ return {
32334
+ blockNumber: bigintField(record, "blockNumber"),
32335
+ logIndex: numberField(record, "logIndex")
32336
+ };
32337
+ }
32338
+ function parseStreamedSwap(data) {
32339
+ const record = parseRecord(data);
32340
+ const transactionHash = record.transactionHash;
32341
+ if (typeof transactionHash !== "string") throw new Error("Stream frame is missing transactionHash");
32342
+ return {
32343
+ ...parseStreamedKey(data),
32344
+ timestamp: bigintField(record, "timestamp"),
32345
+ transactionHash,
32346
+ tick: numberField(record, "tick"),
32347
+ amount0: bigintField(record, "amount0"),
32348
+ amount1: bigintField(record, "amount1"),
32349
+ sqrtPriceX96: bigintField(record, "sqrtPriceX96"),
32350
+ liquidity: bigintField(record, "liquidity")
32351
+ };
32352
+ }
32353
+ function parseHead(data) {
32354
+ return bigintField(parseRecord(data ?? ""), "head");
32355
+ }
32356
+ function defaultEventSource() {
32357
+ const EventSourceCtor = globalThis.EventSource;
32358
+ return EventSourceCtor && ((url) => new EventSourceCtor(url));
32359
+ }
32360
+ function toError$1(error) {
32361
+ return error instanceof Error ? error : new Error(String(error));
32362
+ }
32363
+ /**
32364
+ * Stream a pool's swaps from the relay at `streamUrl`.
32365
+ *
32366
+ * Every `ready`/`resync` frame carries the relay's head; swaps from the cursor up
32367
+ * to that head are fetched over HTTP so nothing is lost across reconnects. A
32368
+ * stream that closes, or errors three times in 30 s, is replaced by HTTP polling
32369
+ * and retried with backoff; one that closes before ever opening is not retried.
32370
+ */
32371
+ function streamPoolSwaps(params) {
32372
+ const { client, pool, fromBlock, pollIntervalMs = DEFAULT_POLL_INTERVAL_MS$1, maxBlockRange = DEFAULT_MAX_BLOCK_RANGE, streamUrl, onSwaps, onError, onRemoved, onTransport, eventSource = defaultEventSource() } = params;
32373
+ let running = true;
32374
+ let cursor = fromBlock === void 0 ? void 0 : fromBlock - 1n;
32375
+ let transport = "off";
32376
+ let failures = [];
32377
+ let source;
32378
+ let poller;
32379
+ let retryTimer;
32380
+ let retryDelayMs = STREAM_RETRY_MIN_MS;
32381
+ let catchUpTimer;
32382
+ let catchUpTarget;
32383
+ let catchingUp = false;
32384
+ let everOpened = false;
32385
+ const setTransport = (next) => {
32386
+ if (next === transport) return;
32387
+ transport = next;
32388
+ onTransport?.(next);
32389
+ };
32390
+ const advance = (block) => {
32391
+ if (block !== void 0 && (cursor === void 0 || block > cursor)) cursor = block;
32392
+ };
32393
+ const report = (error) => {
32394
+ if (running) onError?.(toError$1(error));
32395
+ };
32396
+ const catchUpPending = () => catchingUp || catchUpTarget !== void 0;
32397
+ const runCatchUp = async () => {
32398
+ catchingUp = true;
32399
+ while (running && catchUpTarget !== void 0) {
32400
+ const head = catchUpTarget;
32401
+ catchUpTarget = void 0;
32402
+ if (cursor === void 0) {
32403
+ cursor = head;
32404
+ continue;
32405
+ }
32406
+ try {
32407
+ const { swaps } = await fetchPoolSwaps(client, pool, cursor + 1n, head, maxBlockRange);
32408
+ if (!running) break;
32409
+ const first = swaps[0];
32410
+ const last = swaps[swaps.length - 1];
32411
+ if (first && last) onSwaps(swaps, {
32412
+ fromBlock: first.blockNumber,
32413
+ toBlock: last.blockNumber
32414
+ });
32415
+ advance(head);
32416
+ } catch (error) {
32417
+ report(error);
32418
+ if (catchUpTarget === void 0 || catchUpTarget < head) catchUpTarget = head;
32419
+ catchingUp = false;
32420
+ catchUpTimer = setTimeout(() => void runCatchUp(), pollIntervalMs);
32421
+ return;
32422
+ }
32423
+ }
32424
+ catchingUp = false;
32425
+ };
32426
+ const catchUp = (head, delayMs = 0) => {
32427
+ if (catchUpTarget === void 0 || head > catchUpTarget) catchUpTarget = head;
32428
+ if (catchingUp) return;
32429
+ if (catchUpTimer !== void 0) clearTimeout(catchUpTimer);
32430
+ catchUpTimer = setTimeout(() => {
32431
+ catchUpTimer = void 0;
32432
+ runCatchUp();
32433
+ }, delayMs);
32434
+ };
32435
+ const startPolling = () => {
32436
+ if (poller) return;
32437
+ poller = watchPoolSwaps({
32438
+ client,
32439
+ pool,
32440
+ fromBlock: cursor === void 0 ? void 0 : cursor + 1n,
32441
+ pollIntervalMs,
32442
+ maxBlockRange,
32443
+ onSwaps,
32444
+ onError
32445
+ });
32446
+ setTransport("poll");
32447
+ };
32448
+ const stopPolling = () => {
32449
+ if (!poller) return;
32450
+ advance(poller.lastScannedBlock());
32451
+ poller.stop();
32452
+ poller = void 0;
32453
+ };
32454
+ const closeStream = () => {
32455
+ source?.close();
32456
+ source = void 0;
32457
+ };
32458
+ const scheduleStreamRetry = () => {
32459
+ retryTimer = setTimeout(() => {
32460
+ retryTimer = void 0;
32461
+ if (running) openStream();
32462
+ }, retryDelayMs);
32463
+ retryDelayMs = Math.min(retryDelayMs * 2, STREAM_RETRY_MAX_MS);
32464
+ };
32465
+ const openStream = () => {
32466
+ if (!eventSource) {
32467
+ startPolling();
32468
+ return;
32469
+ }
32470
+ const es = eventSource(streamUrl);
32471
+ source = es;
32472
+ failures = [];
32473
+ let opened = false;
32474
+ const listen = (type, handle) => es.addEventListener(type, (event) => {
32475
+ if (!running || source !== es) return;
32476
+ try {
32477
+ handle(event.data);
32478
+ } catch (error) {
32479
+ report(error);
32480
+ }
32481
+ });
32482
+ listen("open", () => {
32483
+ opened = true;
32484
+ everOpened = true;
32485
+ failures = [];
32486
+ retryDelayMs = STREAM_RETRY_MIN_MS;
32487
+ });
32488
+ listen("ready", (data) => {
32489
+ const head = parseHead(data);
32490
+ stopPolling();
32491
+ setTransport("stream");
32492
+ catchUp(head);
32493
+ });
32494
+ listen("resync", (data) => {
32495
+ catchUp(parseHead(data), Math.random() * RESYNC_JITTER_MS);
32496
+ });
32497
+ listen("swap", (data) => {
32498
+ const swap = parseStreamedSwap(data ?? "");
32499
+ onSwaps([swap], {
32500
+ fromBlock: swap.blockNumber,
32501
+ toBlock: swap.blockNumber
32502
+ });
32503
+ if (!catchUpPending()) advance(swap.blockNumber);
32504
+ });
32505
+ listen("removed", (data) => {
32506
+ onRemoved?.(parseStreamedKey(data ?? ""));
32507
+ });
32508
+ listen("error", () => {
32509
+ const now = Date.now();
32510
+ failures = failures.filter((at) => now - at < FAILURE_WINDOW_MS);
32511
+ failures.push(now);
32512
+ const closed = es.readyState === EVENT_SOURCE_CLOSED;
32513
+ if (!closed && failures.length < FAILURES_BEFORE_POLL) return;
32514
+ closeStream();
32515
+ startPolling();
32516
+ if (closed && !opened && !everOpened) return;
32517
+ scheduleStreamRetry();
32518
+ });
32519
+ };
32520
+ openStream();
32521
+ return {
32522
+ stop() {
32523
+ running = false;
32524
+ closeStream();
32525
+ stopPolling();
32526
+ if (retryTimer !== void 0) clearTimeout(retryTimer);
32527
+ if (catchUpTimer !== void 0) clearTimeout(catchUpTimer);
32528
+ setTransport("off");
32529
+ },
32530
+ lastScannedBlock: () => cursor,
32531
+ transport: () => transport
32532
+ };
32533
+ }
32534
+
32535
+ //#endregion
32536
+ //#region src/panoptic/v2/events/poolSwaps.ts
32537
+ const DEFAULT_POLL_INTERVAL_MS = 3e3;
32538
+ const DEFAULT_MAX_BLOCK_RANGE = 2000n;
32539
+ const SHARED_BUFFER_LIMIT = 4096;
32540
+ /**
32541
+ * Parse a decoded v3 `UniswapV3Pool.Swap` or v4 `PoolManager.Swap` log.
32542
+ */
32543
+ function parseSwapLog(log, timestamp) {
32544
+ if (log.blockNumber === null || log.logIndex === null || log.transactionHash === null) throw new Error("Cannot parse a pending Swap log");
32545
+ const args = log.args;
32546
+ return {
32547
+ blockNumber: log.blockNumber,
32548
+ logIndex: log.logIndex,
32549
+ timestamp,
32550
+ transactionHash: log.transactionHash,
32551
+ tick: Number(args.tick),
32552
+ amount0: args.amount0,
32553
+ amount1: args.amount1,
32554
+ sqrtPriceX96: args.sqrtPriceX96,
32555
+ liquidity: args.liquidity
32556
+ };
32557
+ }
32558
+ function toError(error) {
32559
+ return error instanceof Error ? error : new Error(String(error));
32560
+ }
32561
+ async function fetchSwapLogs(client, pool, fromBlock, toBlock) {
32562
+ if (pool.version === "v3") return client.getContractEvents({
32563
+ address: pool.poolAddress,
32564
+ abi: UniswapV3PoolAbi,
32565
+ eventName: "Swap",
32566
+ fromBlock,
32567
+ toBlock
32568
+ });
32569
+ return client.getContractEvents({
32570
+ address: pool.poolManager,
32571
+ abi: poolManagerAbi,
32572
+ eventName: "Swap",
32573
+ args: { id: pool.poolId },
32574
+ fromBlock,
32575
+ toBlock
32576
+ });
32577
+ }
32578
+ async function fetchSwaps(client, pool, fromBlock, toBlock) {
32579
+ const logs = await fetchSwapLogs(client, pool, fromBlock, toBlock);
32580
+ if (logs.length === 0) return [];
32581
+ const blockNumbers = [...new Set(logs.flatMap((log) => log.blockNumber === null ? [] : [log.blockNumber]))];
32582
+ const blocks = await Promise.all(blockNumbers.map((blockNumber) => client.getBlock({ blockNumber })));
32583
+ const timestamps = new Map(blocks.map((block, i) => [blockNumbers[i], block.timestamp]));
32584
+ return logs.map((log) => parseSwapLog(log, timestamps.get(log.blockNumber ?? -1n) ?? 0n)).sort((a, b) => a.blockNumber === b.blockNumber ? a.logIndex - b.logIndex : a.blockNumber < b.blockNumber ? -1 : 1);
32585
+ }
32586
+ /**
32587
+ * Fetch a pool's swaps in `[fromBlock, toBlock]` (default: the current head), in
32588
+ * chain order. Returns no swaps when `fromBlock > toBlock`.
32589
+ */
32590
+ async function fetchPoolSwaps(client, pool, fromBlock, toBlock, maxBlockRange = DEFAULT_MAX_BLOCK_RANGE) {
32591
+ const end = toBlock ?? await client.getBlockNumber();
32592
+ const swaps = [];
32593
+ for (let from = fromBlock; from <= end; from += maxBlockRange) {
32594
+ const to = from + maxBlockRange - 1n < end ? from + maxBlockRange - 1n : end;
32595
+ swaps.push(...await fetchSwaps(client, pool, from, to));
32596
+ }
32597
+ return {
32598
+ swaps,
32599
+ toBlock: end
32600
+ };
32601
+ }
32602
+ /**
32603
+ * Poll a single pool's `Swap` logs with `eth_getLogs`, timestamped by block.
32604
+ *
32605
+ * Works over plain HTTP (no filters or websockets). A chunk that fails is retried on
32606
+ * the next tick; errors never stop the loop.
32607
+ */
32608
+ function watchPoolSwaps(params) {
32609
+ const { client, pool, fromBlock, pollIntervalMs = DEFAULT_POLL_INTERVAL_MS, maxBlockRange = DEFAULT_MAX_BLOCK_RANGE, onSwaps, onError } = params;
32610
+ let running = true;
32611
+ let lastScanned;
32612
+ let timer;
32613
+ const poll = async () => {
32614
+ try {
32615
+ const head = await client.getBlockNumber();
32616
+ let from = lastScanned !== void 0 ? lastScanned + 1n : fromBlock ?? head;
32617
+ while (running && from <= head) {
32618
+ const to = from + maxBlockRange - 1n < head ? from + maxBlockRange - 1n : head;
32619
+ const swaps = await fetchSwaps(client, pool, from, to);
32620
+ if (!running) return;
32621
+ if (swaps.length > 0) onSwaps(swaps, {
32622
+ fromBlock: from,
32623
+ toBlock: to
32624
+ });
32625
+ lastScanned = to;
32626
+ from = to + 1n;
32627
+ }
32628
+ } catch (error) {
32629
+ if (running) onError?.(toError(error));
32630
+ }
32631
+ if (running) timer = setTimeout(() => void poll(), pollIntervalMs);
32632
+ };
32633
+ poll();
32634
+ return {
32635
+ stop() {
32636
+ running = false;
32637
+ if (timer !== void 0) clearTimeout(timer);
32638
+ },
32639
+ lastScannedBlock: () => lastScanned
32640
+ };
32641
+ }
32642
+ const sharedWatchers = new Map();
32643
+ function swapKey(key) {
32644
+ return `${key.blockNumber}:${key.logIndex}`;
32645
+ }
32646
+ /**
32647
+ * Ref-counted pool swap feed: subscribers with the same `key` share one watcher
32648
+ * (relay stream when `streamUrl` is set, else HTTP polling), duplicates are
32649
+ * dropped, late subscribers first receive the swaps already seen, and the watcher
32650
+ * stops when the last subscriber unsubscribes.
32651
+ */
32652
+ function subscribePoolSwaps(params) {
32653
+ const { key, streamUrl, onSwaps, onError, onRemoved, onTransport,...watchParams } = params;
32654
+ const listener = {
32655
+ onSwaps,
32656
+ onError,
32657
+ onRemoved,
32658
+ onTransport
32659
+ };
32660
+ const existing = sharedWatchers.get(key);
32661
+ if (existing) {
32662
+ existing.listeners.add(listener);
32663
+ const buffered = [...existing.buffer.values()];
32664
+ const first = buffered[0];
32665
+ const last = buffered[buffered.length - 1];
32666
+ if (first && last) onSwaps(buffered, {
32667
+ fromBlock: first.blockNumber,
32668
+ toBlock: last.blockNumber
32669
+ });
32670
+ onTransport?.(existing.transport);
32671
+ } else {
32672
+ const listeners = new Set([listener]);
32673
+ const buffer = new Map();
32674
+ const entry = {
32675
+ watcher: {
32676
+ stop: () => void 0,
32677
+ lastScannedBlock: () => void 0
32678
+ },
32679
+ listeners,
32680
+ buffer,
32681
+ transport: "off"
32682
+ };
32683
+ const setTransport = (transport) => {
32684
+ entry.transport = transport;
32685
+ for (const l of listeners) l.onTransport?.(transport);
32686
+ };
32687
+ const callbacks = {
32688
+ onSwaps: (swaps, range) => {
32689
+ const fresh = swaps.filter((swap) => !buffer.has(swapKey(swap)));
32690
+ if (fresh.length === 0) return;
32691
+ for (const swap of fresh) buffer.set(swapKey(swap), swap);
32692
+ for (const k of buffer.keys()) {
32693
+ if (buffer.size <= SHARED_BUFFER_LIMIT) break;
32694
+ buffer.delete(k);
32695
+ }
32696
+ for (const l of listeners) l.onSwaps(fresh, range);
32697
+ },
32698
+ onError: (error) => {
32699
+ for (const l of listeners) l.onError?.(error);
32700
+ }
32701
+ };
32702
+ sharedWatchers.set(key, entry);
32703
+ if (streamUrl !== void 0) entry.watcher = streamPoolSwaps({
32704
+ ...watchParams,
32705
+ ...callbacks,
32706
+ streamUrl,
32707
+ onRemoved: (removed) => {
32708
+ buffer.delete(swapKey(removed));
32709
+ for (const l of listeners) l.onRemoved?.(removed);
32710
+ },
32711
+ onTransport: setTransport
32712
+ });
32713
+ else {
32714
+ entry.watcher = watchPoolSwaps({
32715
+ ...watchParams,
32716
+ ...callbacks
32717
+ });
32718
+ setTransport("poll");
32719
+ }
32720
+ }
32721
+ return () => {
32722
+ const entry = sharedWatchers.get(key);
32723
+ if (!entry) return;
32724
+ entry.listeners.delete(listener);
32725
+ if (entry.listeners.size === 0) {
32726
+ entry.watcher.stop();
32727
+ sharedWatchers.delete(key);
32728
+ }
32729
+ };
32730
+ }
32731
+
32732
+ //#endregion
32733
+ //#region src/panoptic/v2/strike/ladder.ts
32734
+ /** Target number of rungs across a leg's full range (lower tick → upper tick). */
32735
+ const STRIKE_LADDER_TARGET_STRIKES = 16n;
32736
+ /** Nice increment mantissas, in tenths (1, 2.5, 5) × 10ⁿ. */
32737
+ const NICE_MANTISSAS_TENTHS = [
32738
+ 10n,
32739
+ 25n,
32740
+ 50n
32741
+ ];
32742
+ /** Upper bound on rung hops when searching for a tick-changing step. */
32743
+ const MAX_STEP_ITERATIONS = 512;
32744
+ /** Decimal precision used when rendering exact tick prices as strings. */
32745
+ const PRICE_PRECISION = 30n;
32746
+ function floorDiv(a, b) {
32747
+ const q = a / b;
32748
+ return a % b !== 0n && a < 0n !== b < 0n ? q - 1n : q;
32749
+ }
32750
+ function floorMod(a, b) {
32751
+ return a - floorDiv(a, b) * b;
32752
+ }
32753
+ function ceilDiv(a, b) {
32754
+ return -floorDiv(-a, b);
32755
+ }
32756
+ /** round(a / b) to nearest, ties up. */
32757
+ function roundDiv(a, b) {
32758
+ return floorDiv(2n * a + b, 2n * b);
32759
+ }
32760
+ function pow10(exp) {
32761
+ let result = 1n;
32762
+ for (let i = 0n; i < exp; i++) result *= 10n;
32763
+ return result;
32764
+ }
32765
+ function gcd(a, b) {
32766
+ a = a < 0n ? -a : a;
32767
+ b = b < 0n ? -b : b;
32768
+ while (b !== 0n) [a, b] = [b, a % b];
32769
+ return a;
32770
+ }
32771
+ function reduce(f) {
32772
+ const g = gcd(f.numerator, f.denominator);
32773
+ return g <= 1n ? f : {
32774
+ numerator: f.numerator / g,
32775
+ denominator: f.denominator / g
32776
+ };
32777
+ }
32778
+ function fromBigint(n) {
32779
+ return {
32780
+ numerator: n,
32781
+ denominator: 1n
32782
+ };
32783
+ }
32784
+ function mul(a, b) {
32785
+ return reduce({
32786
+ numerator: a.numerator * b.numerator,
32787
+ denominator: a.denominator * b.denominator
32788
+ });
32789
+ }
32790
+ function add(a, b) {
32791
+ return reduce({
32792
+ numerator: a.numerator * b.denominator + b.numerator * a.denominator,
32793
+ denominator: a.denominator * b.denominator
32794
+ });
32795
+ }
32796
+ function sub(a, b) {
32797
+ return add(a, {
32798
+ numerator: -b.numerator,
32799
+ denominator: b.denominator
32800
+ });
32801
+ }
32802
+ /** -1 | 0 | 1 comparing a to b. */
32803
+ function cmp(a, b) {
32804
+ const l = a.numerator * b.denominator;
32805
+ const r = b.numerator * a.denominator;
32806
+ return l === r ? 0 : l < r ? -1 : 1;
32807
+ }
32808
+ const LADDER_MIN = fromBigint(1n);
32809
+ /** Largest normalised price on the ladder. Prices above are "outside". */
32810
+ const LADDER_MAX = fromBigint(1000000n);
32811
+ function parseDecimal(value) {
32812
+ const trimmed = value.trim();
32813
+ const [basePart, exponentPart] = trimmed.toLowerCase().split("e");
32814
+ const [integerStr, fractionalStr = ""] = basePart.split(".");
32815
+ let numerator = BigInt(`${integerStr === "" ? "0" : integerStr}${fractionalStr}`);
32816
+ let denominator = pow10(BigInt(fractionalStr.length));
32817
+ if (exponentPart !== void 0 && exponentPart !== "") {
32818
+ const exponent = BigInt(exponentPart);
32819
+ if (exponent > 0n) numerator *= pow10(exponent);
32820
+ else if (exponent < 0n) denominator *= pow10(-exponent);
32821
+ }
32822
+ if (numerator <= 0n) throw new Error("Price must be positive");
32823
+ return reduce({
32824
+ numerator,
32825
+ denominator
32826
+ });
32827
+ }
32828
+ /** Render a positive fraction as a decimal string with trailing zeros trimmed. */
32829
+ function fractionToDecimal(f, precision) {
32830
+ const scaled = f.numerator * pow10(precision) / f.denominator;
32831
+ const digits = scaled.toString().padStart(Number(precision) + 1, "0");
32832
+ const intPart = digits.slice(0, digits.length - Number(precision));
32833
+ const fracPart = digits.slice(digits.length - Number(precision)).replace(/0+$/, "");
32834
+ return fracPart.length === 0 ? intPart : `${intPart}.${fracPart}`;
32835
+ }
32836
+ /** 10^k as an exact fraction, k may be negative. */
32837
+ function powerOfTen(k) {
32838
+ return k >= 0n ? fromBigint(pow10(k)) : {
32839
+ numerator: 1n,
32840
+ denominator: pow10(-k)
32841
+ };
32842
+ }
32843
+ /** floor(log10(f)) for a positive fraction. */
32844
+ function floorLog10(f) {
32845
+ let e = BigInt(f.numerator.toString().length - f.denominator.toString().length);
32846
+ while (cmp(f, powerOfTen(e)) < 0) e -= 1n;
32847
+ while (cmp(f, powerOfTen(e + 1n)) >= 0) e += 1n;
32848
+ return e;
32849
+ }
32850
+ function orientTick(tick, orient) {
32851
+ return orient.asset === 0n ? tick : -tick;
32852
+ }
32853
+ /** Exact-enough price of `tick` in the caller's orientation. */
32854
+ function tickToOrientedPrice(tick, orient) {
32855
+ const price = tickToPriceDecimalScaled(orientTick(tick, orient), orient.assetDecimals, orient.quoteDecimals, PRICE_PRECISION);
32856
+ return parseDecimal(price);
32857
+ }
32858
+ /** Nearest integer tick for a caller-oriented decimal price. */
32859
+ function orientedPriceToTick(price, orient) {
32860
+ const t = priceToTick(price, orient.assetDecimals, orient.quoteDecimals);
32861
+ return orientTick(t, orient);
32862
+ }
32863
+ /**
32864
+ * Relative rung step for a leg: `1.0001^(round(width·tickSpacing / TARGET)) − 1`.
32865
+ * Rungs scale with price (they are multiples of a price-proportional increment), so
32866
+ * spacing them by the range's TARGET-th root yields ≈TARGET rungs across the range
32867
+ * regardless of how wide it is.
32868
+ */
32869
+ function relativeStep(width, tickSpacing) {
32870
+ validateGeometry(width, tickSpacing);
32871
+ const ticks = roundDiv(width * tickSpacing, STRIKE_LADDER_TARGET_STRIKES);
32872
+ const ratio = parseDecimal(tickToPriceDecimalScaled(ticks < 1n ? 1n : ticks, 0n, 0n, PRICE_PRECISION));
32873
+ return sub(ratio, fromBigint(1n));
32874
+ }
32875
+ /** Nice increment `m × 10ⁿ` (m ∈ {1, 2.5, 5}) with the smallest log-distance to `raw`. */
32876
+ function niceIncrement(raw) {
32877
+ const e = floorLog10(raw);
32878
+ const scale = (tenths) => mul(fromBigint(tenths), powerOfTen(e - 1n));
32879
+ const candidates = [...NICE_MANTISSAS_TENTHS.map(scale), scale(100n)];
32880
+ let lo = candidates[0] ?? powerOfTen(e);
32881
+ for (const hi of candidates.slice(1)) {
32882
+ if (cmp(raw, hi) < 0) return cmp(mul(raw, raw), mul(lo, hi)) <= 0 ? lo : hi;
32883
+ lo = hi;
32884
+ }
32885
+ return lo;
32886
+ }
32887
+ /** Rung increment at normalised price `p` for the given relative step. */
32888
+ function incrementAt(p, rf) {
32889
+ return niceIncrement(mul(p, rf));
32890
+ }
32891
+ /** Normalise a price to `max(p, 1/p)` and remember whether it was inverted. */
32892
+ function normalise(price) {
32893
+ if (price.numerator >= price.denominator) return {
32894
+ value: price,
32895
+ reciprocal: false
32896
+ };
32897
+ return {
32898
+ value: {
32899
+ numerator: price.denominator,
32900
+ denominator: price.numerator
32901
+ },
32902
+ reciprocal: true
32903
+ };
32904
+ }
32905
+ /** Is `r` a multiple of `inc`? */
32906
+ function isMultiple(r, inc) {
32907
+ return r.numerator * inc.denominator % (r.denominator * inc.numerator) === 0n;
32908
+ }
32909
+ /** Smallest multiple of `inc` strictly greater than `x`. */
32910
+ function ceilMultipleStrict(x, inc) {
32911
+ const k = floorDiv(x.numerator * inc.denominator, x.denominator * inc.numerator) + 1n;
32912
+ return mul(fromBigint(k), inc);
32913
+ }
32914
+ /** Largest multiple of `inc` strictly smaller than `x`. */
32915
+ function floorMultipleStrict(x, inc) {
32916
+ const k = ceilDiv(x.numerator * inc.denominator, x.denominator * inc.numerator) - 1n;
32917
+ return mul(fromBigint(k), inc);
32918
+ }
32919
+ /**
32920
+ * The rung set is `{ r : r is a multiple of incrementAt(r) }`. Because the
32921
+ * increment grows with price, a multiple of a finer increment can land inside a
32922
+ * coarser band where it is no longer a rung; these helpers push such a candidate
32923
+ * up/down until it is a multiple of its own band's increment.
32924
+ */
32925
+ function isRung(r, rf) {
32926
+ return r.numerator > 0n && isMultiple(r, incrementAt(r, rf));
32927
+ }
32928
+ function fixUp(c, rf) {
32929
+ for (let i = 0; i < 64 && !isRung(c, rf); i++) c = ceilMultipleStrict(c, incrementAt(c, rf));
32930
+ return c;
32931
+ }
32932
+ function fixDown(c, rf) {
32933
+ for (let i = 0; i < 64 && c.numerator > 0n && !isRung(c, rf); i++) c = floorMultipleStrict(c, incrementAt(c, rf));
32934
+ return c;
32935
+ }
32936
+ /** Smallest rung strictly above `x` (may exceed the ladder top). */
32937
+ function nextRungAbove(x, rf) {
32938
+ const incHere = incrementAt(x, rf);
32939
+ const incs = [incHere, incrementAt(add(x, incHere), rf)];
32940
+ let best = null;
32941
+ for (const inc of incs) {
32942
+ const c = fixUp(ceilMultipleStrict(x, inc), rf);
32943
+ if (cmp(c, x) > 0 && (best === null || cmp(c, best) < 0)) best = c;
32944
+ }
32945
+ if (best === null) throw new PanopticValidationError("No ladder rung above price");
32946
+ return best;
32947
+ }
32948
+ /** Largest rung strictly below `x` (may fall below the ladder floor). */
32949
+ function prevRungBelow(x, rf) {
32950
+ const incHere = incrementAt(x, rf);
32951
+ const finer = incrementAt(sub(x, incHere), rf);
32952
+ let best = null;
32953
+ for (const inc of [incHere, finer]) {
32954
+ const c = fixDown(floorMultipleStrict(x, inc), rf);
32955
+ if (c.numerator > 0n && cmp(c, x) < 0 && (best === null || cmp(c, best) > 0)) best = c;
32956
+ }
32957
+ return best ?? fromBigint(0n);
32958
+ }
32959
+ /** Nearest rung price to a normalised price, or null when above the ladder. */
32960
+ function nearestRungPrice(normalised, rf) {
32961
+ let rung;
32962
+ if (isRung(normalised, rf)) rung = normalised;
32963
+ else {
32964
+ const up = nextRungAbove(normalised, rf);
32965
+ const down = prevRungBelow(normalised, rf);
32966
+ if (down.numerator <= 0n) rung = up;
32967
+ else rung = cmp(sub(normalised, down), sub(up, normalised)) <= 0 ? down : up;
32968
+ }
32969
+ if (cmp(rung, LADDER_MIN) < 0) rung = LADDER_MIN;
32970
+ if (cmp(rung, LADDER_MAX) > 0) return null;
32971
+ return rung;
32972
+ }
32973
+ /** Step one rung up (+1) or down (-1) on the normalised ladder. Null when leaving it. */
32974
+ function stepRungPrice(rung, direction, rf) {
32975
+ const next = direction > 0n ? nextRungAbove(rung, rf) : prevRungBelow(rung, rf);
32976
+ if (cmp(next, LADDER_MIN) < 0 || cmp(next, LADDER_MAX) > 0) return null;
32977
+ return next;
32978
+ }
32979
+ /** Nominal caller-oriented price of a rung as an exact fraction. */
32980
+ function rungToPrice(rung) {
32981
+ return rung.reciprocal ? {
32982
+ numerator: rung.price.denominator,
32983
+ denominator: rung.price.numerator
32984
+ } : rung.price;
32985
+ }
32986
+ function rungToPriceString(rung) {
32987
+ return fractionToDecimal(rungToPrice(rung), PRICE_PRECISION);
32988
+ }
32989
+ function nearestRung(price, rf) {
32990
+ const { value, reciprocal } = normalise(price);
32991
+ const p = nearestRungPrice(value, rf);
32992
+ return p === null ? null : {
32993
+ price: p,
32994
+ reciprocal
32995
+ };
32996
+ }
32997
+ /**
32998
+ * Step a rung in the caller's price direction. For reciprocal quotes a higher
30902
32999
  * caller price is a lower normalised price, so the direction flips.
30903
33000
  */
30904
33001
  function stepRung(rung, direction, rf) {
@@ -32055,14 +34152,7 @@ function preparePositionGamma({ tokenId, positionSize, quoteIsToken0, quoteDecim
32055
34152
  const decoded = decodeTokenId(tokenId);
32056
34153
  const chunks = decoded.legs.flatMap((leg) => {
32057
34154
  if (leg.width === 0n) return [];
32058
- const width = leg.width * decoded.tickSpacing;
32059
- const lowerTick = leg.strike - width / 2n;
32060
- const upperTick = leg.strike + (width + 1n) / 2n;
32061
- if (lowerTick < -887272n || upperTick > 887272n || lowerTick >= upperTick) throw new RangeError("Invalid position range");
32062
- const lower = tickToSqrtPriceX96(lowerTick);
32063
- const upper = tickToSqrtPriceX96(upperTick);
32064
- const amount = positionSize * leg.optionRatio;
32065
- const liquidity = leg.asset === 0n ? amount * (lower * upper / Q96) / (upper - lower) : amount * Q96 / (upper - lower);
34155
+ const { lowerTick, upperTick, liquidity } = getLegLiquidityRange(leg, positionSize, decoded.tickSpacing);
32066
34156
  if (liquidity >= 1n << 128n) throw new RangeError("Liquidity exceeds uint128");
32067
34157
  return [{
32068
34158
  lowerTick: Number(lowerTick),
@@ -32116,7 +34206,7 @@ function calculatePositionVolatilityMetrics({ observations, netPremium, baseFees
32116
34206
  for (const point of points) if (!point.price.isFinite() || point.price.lte(0) || !point.gamma.isFinite() || point.rangeGammas.some((gamma) => !gamma.isFinite())) throw new RangeError("Invalid price or gamma observation");
32117
34207
  const quantum = new Precision(10).pow(-quoteDecimals);
32118
34208
  const gammas = points.flatMap((point) => [point.gamma, ...point.rangeGammas]);
32119
- const peak = gammas.reduce((max, gamma) => Precision.max(max, gamma.abs()), new Precision(0));
34209
+ const peak = gammas.reduce((max$1, gamma) => Precision.max(max$1, gamma.abs()), new Precision(0));
32120
34210
  const tolerance = Precision.max(quantum, peak.mul("1e-12"));
32121
34211
  const positive = gammas.some((gamma) => gamma.gt(tolerance));
32122
34212
  const negative = gammas.some((gamma) => gamma.lt(tolerance.neg()));
@@ -32587,5 +34677,5 @@ async function getPositionVolatilityHistory({ client, poolAddress, account, toke
32587
34677
  }
32588
34678
 
32589
34679
  //#endregion
32590
- export { AccountInsolventError, AlreadyInitializedError, BORROW_INDEX_BITS, BPS_DENOMINATOR, BPS_SCALE, BatchValidationError, BelowMinimumRedemptionError, CastingError, ChunkHasZeroLiquidityError, ChunkLimitError, CrossPoolError, DEFAULT_MAX_SPREAD, DEFAULT_MINT_BUFFER, DEFAULT_MIN_SWAP_RATIO_BPS, DEFAULT_RECONNECT_CONFIG, DEFAULT_VEGOID, DepositTooLargeError, DuplicateTokenIdError, EffectiveLiquidityAboveThresholdError, ExceedsMaximumRedemptionError, InputListFailError, InsufficientCreditLiquidityError, InvalidBuilderCodeError, InvalidHistoryRangeError, InvalidTickBoundError, InvalidTickError, InvalidTokenIdParameterError, InvalidUniswapCallbackError, LEG_BITS, LEG_LIMITS, LEG_MASKS, LengthMismatchError, LiquidityTooHighError, LoanSlotExhaustedError, MARKET_EPOCH_BITS, MARKET_EPOCH_SHIFT, MARKET_INDICATOR_PERIODS, MAX_TICK, MAX_TRACKED_CHUNKS, MINT_BUFFER, MINT_BUFFER_DENOMINATOR, MIN_TICK, MaxRetriesExceededError, MissingPositionIdsError, NO_LOWER_LIQUIDATION_TICK, NO_UPPER_LIQUIDATION_TICK, NetLiquidityZeroError, NetworkMismatchError, NoLegsExercisableError, NotALongLegError, NotBuilderError, NotEnoughLiquidityInChunkError, NotEnoughTokensError, NotGuardianError, NotMarginCalledError, NotPanopticPoolError, ORACLE_EPOCH_SECONDS, OracleRateLimitedError, PanopticError, PanopticHelperNotDeployedError, PanopticValidationError, PoolNotInitializedError, PositionCountNotZeroError, PositionNotOwnedError, PositionSnapshotNotFoundError, PositionTooLargeError, PriceBoundFailError, PriceImpactTooLargeError, ProviderLagError, RATE_AT_TARGET_BITS, REORG_DEPTH, REQUIRED_BASE_ERROR_SENTINEL, ReentrancyError, RpcError, RpcResponseError, SCHEMA_VERSION, SECONDS_PER_YEAR, STANDARD_TICK_WIDTHS, STORAGE_PREFIX, STRIKE_LADDER_TARGET_STRIKES, SafeModeError, StaleDataError, StaleOracleError, SwapTokenMismatchError, SyncTimeoutError, TOKEN_ID_BITS, TokenIdHasZeroLegsError, TooManyLegsOpenError, TransferFailedError, UNREALIZED_INTEREST_BITS, UTILIZATION_DENOMINATOR, UnauthorizedUniswapCallbackError, UnderOverFlowError, UnhealthyPoolError, UnsafePremiumSettlementError, VARIANCE_RATIO_LAG, WAD, WrongPoolIdError, WrongUniswapPoolError, ZERO_COLLATERAL, ZERO_VALUATION, ZeroAddressError, ZeroCollateralRequirementError, addLegToTokenId, addPendingPosition, addTrackedChunks, annualizePerSecondRateWad, applyMintBuffer, applyMintBufferPerToken, apportion, approve, approveAndWait, approvePool, assertCanBurn, assertCanForceExercise, assertCanLiquidate, assertCanMint, assertFresh, assertHealthy, assertLpPositionFunded, assertTradeable, borrow, borrowAndWait, buildBatchDispatchArgs, buildCreditSwapCall, buildCreditWrappedDispatch, buildOpenPositionCalldata, buildProtectedSettleDispatch, buildProtectedSettlePlan, buildSettleSequenceCalls, buildSfpmSwapCalldata, buildSfpmSwapPlan, buildTemporaryLoanRecoveryDispatch, buildTokenShortfallRecoveryDispatch, buildUniqueCredit, buildUniqueLoan, buildUniqueWidthZeroLeg, calculateAccountGreeksPure, calculateMarketIndicator, calculatePortfolioDelta, calculatePortfolioGamma, calculatePortfolioGreeks, calculatePortfolioValue, calculatePositionDelta, calculatePositionDeltaDebtOnly, calculatePositionDeltaWithSwap, calculatePositionGamma, calculatePositionGreeks, calculatePositionValue, calculatePositionValues, calculatePositionVolatilityMetrics, calculateResyncBlock, calculateSpreadWad, calculateVarianceProfile, cancelTransaction, checkApproval, checkCollateralAcrossTicks, classifyStrategyGroups, classifyStrike, cleanupStalePendingPositions, clearCheckpoint, clearPendingPositions, clearTrackedChunks, clearTrackedPositions, clearTradeHistory, closePosition, closePositionAndWait, collateralCurveTicks, collateralRuleKindFor, collateralTrackerV2Abi, computeV4PoolId, confirmPendingPosition, convertToAssets, convertToShares, countLegs, createEventPoller, createEventSubscription, createFileStorage, createFlowNeutralTokenId, createMemoryStorage, createNonceManager, createPoolFormatters, createTokenIdBuilder, decodeAllDispatchCalldata, decodeAllLegs, decodeDispatchCalldata, decodeLeftRightSigned, decodeLeftRightUnsigned, decodeLeg, decodeOraclePack, decodeOracleRiskParameters, decodeOracleTiming, decodePanopticTokenURI, decodePoolId, decodeTickSpacing, decodeTokenId, decodeVegoid, deployNewPool, deployNewPoolAndWait, deposit, depositAndWait, deriveSupplyRatePerSecWad, deriveUniqueTokenId, detectReorg, diagnoseOracleSafeMode, dispatch, dispatchAndWait, emptyLiquidateParams, encodeLeg, encodePoolId, encodePoolKeyBytes, encodeV3PoolKeyBytes, encodeV4PoolId, ensureSfpmV3PoolInitialized, estimateBlockNumbers, estimateCloseZapSwap, estimateCollateralBreakdown, estimateCollateralRequired, executeBatchDispatch, executeBatchDispatchAndWait, executeSettleSequence, executeSettleSequenceAndWait, failPendingPosition, feeGrowthInsideX128, feesFromFeeGrowthDelta, fetchPoolId, fetchSfpmV3PoolId, fetchUniswapFeeData, forceExercise, forceExerciseAndWait, formatBlockNumber, formatBps, formatCompact, formatDatetime, formatDuration, formatDurationSeconds, formatFeeTier, formatGas, formatGwei, formatPerSecondRateWadAsAprPct, formatPerSecondRateWadAsApyPct, formatPoolIdHex, formatPriceRange, formatRateWad, formatRatioPercent, formatTick, formatTickRange, formatTimestamp, formatTimestampLocale, formatTokenAmount, formatTokenAmountSigned, formatTokenDelta, formatTokenFlow, formatTokenIdHex, formatTokenIdShort, formatTxHash, formatUtilization, formatWad, formatWadPercent, formatWadSigned, formatWei, generateOverlappingTokenIds, getAccountBuyingPower, getAccountCollateral, getAccountGreeks, getAccountHistory, getAccountPremia, getAccountSummaryBasic, getAccountSummaryRisk, getAssetIndex, getBlockMeta, getChainDeployment, getChunkLiquidities, getChunkSpreads, getClosePositionTransferEstimate, getClosedPositions, getClosedPositionsKey, getCollateralAddresses, getCollateralCurve, getCollateralCurveInputs, getCollateralData, getCollateralRequiredBase, getCollateralSharePrices, getCollateralTotalAssetsBatch, getCurrentRates, getDeltaHedgeParams, getEnforcedTickLimits, getExecutableLpMaxSize, getFactoryConstructMetadata, getFactoryOwnerOf, getFactoryTokenURI, getForfeitablePremium, getGuardianUnlockState, getHedgeLimits, getInterestState, getIrmCurrent, getIrmCurve, getItmAmounts, getLegDelta, getLegDeltaInVaultFrame, getLegGamma, getLegNetValueWidth0, getLegValue, getLiquidationPrices, getMarginBuffer, getMaxPositionSize, getMaxRedeem, getMaxWithdrawable, getNativeTokenPrice, getNetLiquidationValue, getNetLiquidationValues, getNotEnoughTokensError, getOpenPositionIds, getOpenPositionPreview, getOracleRiskParameters, getOracleState, getPanopticPoolAddress, getPanopticPoolFromPoolId, getPendingPositions, getPendingPositionsKey, getPool, getPoolCurrentTick, getPoolDeploymentBlock, getPoolDisplayId, getPoolLiquidities, getPoolMetaKey, getPoolMetadata, getPoolPrefix, getPortfolioValue, getPosition, getPositionChunkData, getPositionDeltaMetrics, getPositionEnrichmentData, getPositionGreeks, getPositionMetaKey, getPositionValueCurve, getPositionVolatilityHistory, getPositions, getPositionsKey, getPositionsWithPremia, getPriceHistory, getPricesAtTick, getRealizedPnL, getRequiredCreditForITM, getRiskParameters, getSafeMode, getSchemaVersionKey, getSimpleLoanTokenIndex, getStreamiaHistory, getSyncCheckpointKey, getSyncStatus, getTickSpacing, getTokenListId, getTrackedChunks, getTrackedChunksKey, getTrackedPositionIds, getTradeHistory, getUniswapFeeHistory, getUniswapV3LpPositionState, getUniswapV3PoolFromId, getUniswapV3PoolInfo, getUniswapV3PoolLiquidities, getUniswapV4LpPositionState, getUniswapV4PoolBasicState, getUniswapV4PoolInfo, getUniswapV4PoolKeyFromId, getUniswapV4PoolLiquidities, getUtilization, hasLoanOrCredit, hasLongLeg, interpolateBlocks, isCall, isCredit, isCreditLeg, isDefinedRisk, isGasError, isInputListFailError, isLiquidatable, isLoan, isLoanLeg, isNonceError, isPanopticErrorType, isPositionTracked, isRetryableRpcError, isShortOnly, isSpread, isSupportedChain, isolateGroupTokenId, jsonSerializer, ladderStrikeSequence, liquidate, liquidateAndWait, loadCheckpoint, logReturns, marketPnlInQuote, marketRiskFromValues, marketScenario, minePoolAddress, mint, mintAndWait, mintableAfterBuffer, multicallRead, netLiquidationValueInQuote, openPosition, openPositionAndWait, optimizeTokenIdRiskPartners, oracleEpochAt, orderListForSettle, packMarketState, panopticLiquidatorAbi, panopticPoolV2Abi, panopticQueryAbi, parseBps, parseCollateralLog, parsePanopticError, parsePoolLog, parseTokenAmount, parseTokenListId, parseWad, planDeriveStrategy, pokeOracle, pokeOracleAndWait, positionValueKey, positionValueTicks, prepareIndicatorCandles, prepareLiquidityGamma, preparePositionGamma, preparePositionValue, preparePositionValueCurve, previewBorrow, previewDeposit, previewMint, previewRedeem, previewRepay, previewUnwrap, previewWithdraw, previewWrap, priceToTick, publicBroadcaster, quoteLiquidation, quoteOneTokenFlow, quoteSfpmSwap, quoteTemporaryLoanRecovery, quoteTokenShortfallRecovery, quoteV3ExactIn, ratePerSecWadToAprPct, realizedBeta, reconstructFromEvents, recoverSnapshot, recoverSnapshotFromTx, redeem, redeemAndWait, removeTrackedChunks, repay, repayAndWait, requireChainDeployment, resolveBlockNumbers, resolveLadderStrike, resolvePanopticPoolFromPoolId, resolveTokenIndex, resolveUniswapV4PoolKey, riskEngineAbi, rollPosition, rollPositionAndWait, roundToTickSpacing, saveCheckpoint, saveClosedPosition, scaleCollateralRequired, scanChunks, screenAccountExact, selectDispatchForAccount, settleAccumulatedPremia, settleAccumulatedPremiaAndWait, settlePremiumFrom, settlePremiumFromAndWait, simulateBatchDispatch, simulateClosePosition, simulateDeployNewPool, simulateDeposit, simulateDispatch, simulateForceExercise, simulateLiquidate, simulateOpenPosition, simulateSFPMBurn, simulateSFPMMint, simulateSettle, simulateSettlePremiumBatch, simulateSettlePremiumFrom, simulateSettleSequence, simulateSwapExactIn, simulateSwapExactOut, simulateWithTokenFlow, simulateWithdraw, slippageBpsToTickDistance, smartRepay, smartRepayAndWait, speedUpTransaction, splitTokenIdByTimescale, sqrtPriceX96ToPriceDecimalScaled, sqrtPriceX96ToTick, supply, supplyAndWait, swapExactIn, swapExactInAndWait, swapExactOut, swapExactOutAndWait, syncPositions, tickLimits, tickToPrice, tickToPriceDecimalScaled, tickToSqrtPriceX96, toVaultFrameAtTick, truncateAddress, unsupply, unsupplyAndWait, unwrapWeth, unwrapWethAndWait, unwrapXstock, unwrapXstockAndWait, utilizationBpsToWad, utilizationPctToWad, validateBatch, validateBuilderCode, validatePoolId, valuePositionAccrual, verifyBlockContinuity, watchEvents, wethWrapAbi, withdraw, withdrawAndWait, withdrawWithPositions, withdrawWithPositionsAndWait, wrapEth, wrapEthAndWait, wrapXstock, wrapXstockAndWait, xstockWrapperAbi };
34680
+ export { AccountInsolventError, AlreadyInitializedError, BORROW_INDEX_BITS, BPS_DENOMINATOR, BPS_SCALE, BatchValidationError, BelowMinimumRedemptionError, CastingError, ChunkHasZeroLiquidityError, ChunkLimitError, CrossPoolError, DEFAULT_MAX_SPREAD, DEFAULT_MINT_BUFFER, DEFAULT_MIN_SWAP_RATIO_BPS, DEFAULT_RECONNECT_CONFIG, DEFAULT_VEGOID, DepositTooLargeError, DuplicateTokenIdError, EffectiveLiquidityAboveThresholdError, ExceedsMaximumRedemptionError, InputListFailError, InsufficientCreditLiquidityError, InvalidBuilderCodeError, InvalidHistoryRangeError, InvalidTickBoundError, InvalidTickError, InvalidTokenIdParameterError, InvalidUniswapCallbackError, LEG_BITS, LEG_LIMITS, LEG_MASKS, LengthMismatchError, LiquidityTooHighError, LoanSlotExhaustedError, MARKET_EPOCH_BITS, MARKET_EPOCH_SHIFT, MARKET_INDICATOR_PERIODS, MAX_TICK, MAX_TRACKED_CHUNKS, MINT_BUFFER, MINT_BUFFER_DENOMINATOR, MIN_TICK, MaxRetriesExceededError, MissingPositionIdsError, NO_LOWER_LIQUIDATION_TICK, NO_UPPER_LIQUIDATION_TICK, NetLiquidityZeroError, NetworkMismatchError, NoLegsExercisableError, NotALongLegError, NotBuilderError, NotEnoughLiquidityInChunkError, NotEnoughTokensError, NotGuardianError, NotMarginCalledError, NotPanopticPoolError, ORACLE_EPOCH_SECONDS, OracleRateLimitedError, PanopticError, PanopticHelperNotDeployedError, PanopticValidationError, PoolNotInitializedError, PositionCountNotZeroError, PositionNotOwnedError, PositionSnapshotNotFoundError, PositionTooLargeError, PriceBoundFailError, PriceImpactTooLargeError, ProviderLagError, RATE_AT_TARGET_BITS, REORG_DEPTH, REQUIRED_BASE_ERROR_SENTINEL, ReentrancyError, RpcError, RpcResponseError, SCHEMA_VERSION, SECONDS_PER_YEAR, STANDARD_TICK_WIDTHS, STORAGE_PREFIX, STRIKE_LADDER_TARGET_STRIKES, SafeModeError, StaleDataError, StaleOracleError, SwapTokenMismatchError, SyncTimeoutError, TOKEN_ID_BITS, TokenIdHasZeroLegsError, TooManyLegsOpenError, TransferFailedError, UNREALIZED_INTEREST_BITS, UTILIZATION_DENOMINATOR, UnauthorizedUniswapCallbackError, UnderOverFlowError, UnhealthyPoolError, UnsafePremiumSettlementError, VARIANCE_RATIO_LAG, WAD, WrongPoolIdError, WrongUniswapPoolError, ZERO_COLLATERAL, ZERO_VALUATION, ZeroAddressError, ZeroCollateralRequirementError, addLegToTokenId, addPendingPosition, addTrackedChunks, annualizePerSecondRateWad, applyMintBuffer, applyMintBufferPerToken, apportion, approve, approveAndWait, approvePool, assertCanBurn, assertCanForceExercise, assertCanLiquidate, assertCanMint, assertFresh, assertHealthy, assertLpPositionFunded, assertTradeable, borrow, borrowAndWait, buildBatchDispatchArgs, buildCreditSwapCall, buildCreditWrappedDispatch, buildOpenPositionCalldata, buildProtectedSettleDispatch, buildProtectedSettlePlan, buildSettleSequenceCalls, buildSfpmSwapCalldata, buildSfpmSwapPlan, buildTemporaryLoanRecoveryDispatch, buildTokenShortfallRecoveryDispatch, buildUniqueCredit, buildUniqueLoan, buildUniqueWidthZeroLeg, calculateAccountGreeksPure, calculateMarketIndicator, calculatePortfolioDelta, calculatePortfolioGamma, calculatePortfolioGreeks, calculatePortfolioValue, calculatePositionDelta, calculatePositionDeltaDebtOnly, calculatePositionDeltaWithSwap, calculatePositionGamma, calculatePositionGreeks, calculatePositionValue, calculatePositionValues, calculatePositionVolatilityMetrics, calculateResyncBlock, calculateSpreadWad, calculateVarianceProfile, cancelTransaction, checkApproval, checkCollateralAcrossTicks, classifyStrategyGroups, classifyStrike, cleanupStalePendingPositions, clearCheckpoint, clearPendingPositions, clearTrackedChunks, clearTrackedPositions, clearTradeHistory, closePosition, closePositionAndWait, collateralCurveTicks, collateralRuleKindFor, collateralTrackerV2Abi, computeV4PoolId, confirmPendingPosition, convertToAssets, convertToShares, countLegs, createEventPoller, createEventSubscription, createFileStorage, createFlowNeutralTokenId, createMemoryStorage, createNonceManager, createPoolFormatters, createTokenIdBuilder, decodeAllDispatchCalldata, decodeAllLegs, decodeDispatchCalldata, decodeLeftRightSigned, decodeLeftRightUnsigned, decodeLeg, decodeOraclePack, decodeOracleRiskParameters, decodeOracleTiming, decodePanopticTokenURI, decodePoolId, decodeTickSpacing, decodeTokenId, decodeVegoid, deployNewPool, deployNewPoolAndWait, deposit, depositAndWait, deriveSupplyRatePerSecWad, deriveUniqueTokenId, detectReorg, diagnoseOracleSafeMode, dispatch, dispatchAndWait, emptyLiquidateParams, encodeLeg, encodePoolId, encodePoolKeyBytes, encodeV3PoolKeyBytes, encodeV4PoolId, ensureSfpmV3PoolInitialized, estimateBlockNumbers, estimateCloseZapSwap, estimateCollateralBreakdown, estimateCollateralRequired, executeBatchDispatch, executeBatchDispatchAndWait, executeSettleSequence, executeSettleSequenceAndWait, failPendingPosition, feeGrowthInsideX128, feesFromFeeGrowthDelta, fetchPoolId, fetchPoolSwaps, fetchSfpmV3PoolId, fetchUniswapFeeData, forceExercise, forceExerciseAndWait, formatBlockNumber, formatBps, formatCompact, formatDatetime, formatDuration, formatDurationSeconds, formatFeeTier, formatGas, formatGwei, formatPerSecondRateWadAsAprPct, formatPerSecondRateWadAsApyPct, formatPoolIdHex, formatPriceRange, formatRateWad, formatRatioPercent, formatTick, formatTickRange, formatTimestamp, formatTimestampLocale, formatTokenAmount, formatTokenAmountSigned, formatTokenDelta, formatTokenFlow, formatTokenIdHex, formatTokenIdShort, formatTxHash, formatUtilization, formatWad, formatWadPercent, formatWadSigned, formatWei, generateOverlappingTokenIds, getAccountBuyingPower, getAccountCollateral, getAccountGreeks, getAccountHistory, getAccountPremia, getAccountSummaryBasic, getAccountSummaryRisk, getAssetIndex, getBlockMeta, getChainDeployment, getChunkLiquidities, getChunkSpreads, getClosePositionTransferEstimate, getClosedPositions, getClosedPositionsKey, getCollateralAddresses, getCollateralCurve, getCollateralCurveInputs, getCollateralData, getCollateralRequiredBase, getCollateralSharePrices, getCollateralTotalAssetsBatch, getCurrentRates, getDeltaHedgeParams, getEnforcedTickLimits, getExecutableLpMaxSize, getFactoryConstructMetadata, getFactoryOwnerOf, getFactoryTokenURI, getForfeitablePremium, getGuardianUnlockState, getHedgeLimits, getInterestState, getIrmCurrent, getIrmCurve, getItmAmounts, getLegDelta, getLegDeltaInVaultFrame, getLegGamma, getLegNetValueWidth0, getLegValue, getLiquidationPrices, getMarginBuffer, getMaxPositionSize, getMaxRedeem, getMaxWithdrawable, getNativeTokenPrice, getNetLiquidationValue, getNetLiquidationValues, getNotEnoughTokensError, getOpenPositionIds, getOpenPositionPreview, getOracleRiskParameters, getOracleState, getPanopticPoolAddress, getPanopticPoolFromPoolId, getPendingPositions, getPendingPositionsKey, getPool, getPoolCurrentTick, getPoolDeploymentBlock, getPoolDisplayId, getPoolLiquidities, getPoolMetaKey, getPoolMetadata, getPoolPrefix, getPortfolioValue, getPosition, getPositionChunkData, getPositionDeltaMetrics, getPositionEnrichmentData, getPositionGreeks, getPositionMetaKey, getPositionMintFunding, getPositionValueCurve, getPositionVolatilityHistory, getPositions, getPositionsKey, getPositionsWithPremia, getPriceHistory, getPricesAtTick, getRealizedPnL, getRequiredCreditForITM, getRiskParameters, getSafeMode, getSchemaVersionKey, getSimpleLoanTokenIndex, getStreamiaHistory, getSyncCheckpointKey, getSyncStatus, getTickSpacing, getTokenIdValidationError, getTokenListId, getTrackedChunks, getTrackedChunksKey, getTrackedPositionIds, getTradeHistory, getUniswapFeeHistory, getUniswapV3LpPositionState, getUniswapV3PoolFromId, getUniswapV3PoolInfo, getUniswapV3PoolLiquidities, getUniswapV4LpPositionState, getUniswapV4PoolBasicState, getUniswapV4PoolInfo, getUniswapV4PoolKeyFromId, getUniswapV4PoolLiquidities, getUtilization, hasLoanOrCredit, hasLongLeg, interpolateBlocks, isCall, isCredit, isCreditLeg, isDefinedRisk, isGasError, isInputListFailError, isLiquidatable, isLoan, isLoanLeg, isNonceError, isPanopticErrorType, isPositionTracked, isRetryableRpcError, isShortOnly, isSpread, isSupportedChain, isolateGroupTokenId, jsonSerializer, ladderStrikeSequence, liquidate, liquidateAndWait, loadCheckpoint, logReturns, marketPnlInQuote, marketRiskFromValues, marketScenario, minePoolAddress, mint, mintAndWait, mintableAfterBuffer, multicallRead, netLiquidationValueInQuote, openPosition, openPositionAndWait, optimizeTokenIdRiskPartners, oracleEpochAt, orderListForSettle, packMarketState, panopticLiquidatorAbi, panopticPoolV2Abi, panopticQueryAbi, parseBps, parseCollateralLog, parsePanopticError, parsePoolLog, parseStreamedKey, parseStreamedSwap, parseSwapLog, parseTokenAmount, parseTokenListId, parseWad, planDeriveStrategy, pokeOracle, pokeOracleAndWait, positionValueKey, positionValueTicks, prepareIndicatorCandles, prepareLiquidityGamma, preparePositionGamma, preparePositionValue, preparePositionValueCurve, previewBorrow, previewDeposit, previewMint, previewRedeem, previewRepay, previewUnwrap, previewWithdraw, previewWrap, priceToTick, publicBroadcaster, quoteLiquidation, quoteOneTokenFlow, quoteSfpmSwap, quoteTemporaryLoanRecovery, quoteTokenShortfallRecovery, quoteTokenShortfallSwap, quoteV3ExactIn, ratePerSecWadToAprPct, realizedBeta, reconstructFromEvents, recoverSnapshot, recoverSnapshotFromTx, redeem, redeemAndWait, removeTrackedChunks, repay, repayAndWait, requireChainDeployment, resolveBlockNumbers, resolveLadderStrike, resolvePanopticPoolFromPoolId, resolveTokenIndex, resolveUniswapV4PoolKey, riskEngineAbi, rollPosition, rollPositionAndWait, roundToTickSpacing, saveCheckpoint, saveClosedPosition, scaleCollateralRequired, scanChunks, screenAccountExact, selectDispatchForAccount, settleAccumulatedPremia, settleAccumulatedPremiaAndWait, settlePremiumFrom, settlePremiumFromAndWait, simulateBatchDispatch, simulateClosePosition, simulateClosePremiumProtection, simulateDeployNewPool, simulateDeposit, simulateDispatch, simulateForceExercise, simulateLiquidate, simulateOpenPosition, simulateSFPMBurn, simulateSFPMMint, simulateSettle, simulateSettlePremiumBatch, simulateSettlePremiumFrom, simulateSettleSequence, simulateSwapExactIn, simulateSwapExactOut, simulateWithTokenFlow, simulateWithdraw, slippageBpsToTickDistance, smartRepay, smartRepayAndWait, speedUpTransaction, splitTokenIdByTimescale, sqrtPriceX96ToPriceDecimalScaled, sqrtPriceX96ToTick, streamPoolSwaps, subscribePoolSwaps, supply, supplyAndWait, swapExactIn, swapExactInAndWait, swapExactOut, swapExactOutAndWait, syncPositions, tickLimits, tickToPrice, tickToPriceDecimalScaled, tickToSqrtPriceX96, toVaultFrameAtTick, truncateAddress, unsupply, unsupplyAndWait, unwrapWeth, unwrapWethAndWait, unwrapXstock, unwrapXstockAndWait, utilizationBpsToWad, utilizationPctToWad, validateBatch, validateBuilderCode, validatePoolId, valuePositionAccrual, verifyBlockContinuity, watchEvents, watchPoolSwaps, wethWrapAbi, withdraw, withdrawAndWait, withdrawWithPositions, withdrawWithPositionsAndWait, wrapEth, wrapEthAndWait, wrapXstock, wrapXstockAndWait, xstockWrapperAbi };
32591
34681
  //# sourceMappingURL=index.js.map