@panoptic-eng/sdk 1.0.47 → 1.0.49

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.
@@ -435,6 +435,19 @@ var SwapTokenMismatchError = class extends PanopticError {
435
435
  this.token1 = token1;
436
436
  }
437
437
  };
438
+ /**
439
+ * A premium settlement would advance the seller checkpoint while some
440
+ * displayed premium is still unavailable, or a required buyer cannot settle.
441
+ */
442
+ var UnsafePremiumSettlementError = class extends PanopticError {
443
+ name = "UnsafePremiumSettlementError";
444
+ constructor(remainingForfeit, failedBuyerCount, cause) {
445
+ const [token0, token1] = remainingForfeit;
446
+ super(failedBuyerCount > 0 ? `Premium settlement blocked: ${failedBuyerCount} buyer settlement${failedBuyerCount === 1 ? "" : "s"} would fail` : `Premium settlement blocked: uncollectable premium remains (${token0}, ${token1})`, cause);
447
+ this.remainingForfeit = remainingForfeit;
448
+ this.failedBuyerCount = failedBuyerCount;
449
+ }
450
+ };
438
451
 
439
452
  //#endregion
440
453
  //#region src/panoptic/v2/utils/interpolateBlocks.ts
@@ -10037,7 +10050,7 @@ function hasLoanOrCredit(tokenId) {
10037
10050
  //#region src/panoptic/v2/formatters/tick.ts
10038
10051
  const Q192$5 = 1n << 192n;
10039
10052
  const RAW_PRICE_PRECISION = 40n;
10040
- function pow10$1(exponent) {
10053
+ function pow10$2(exponent) {
10041
10054
  if (exponent < 0n) throw new RangeError("Exponent must be non-negative");
10042
10055
  return 10n ** exponent;
10043
10056
  }
@@ -10056,7 +10069,7 @@ function formatRatio$3(numerator, denominator, precision) {
10056
10069
  if (precision < 0n) throw new RangeError("Precision must be non-negative");
10057
10070
  const sign = numerator < 0n ? "-" : "";
10058
10071
  const absNumerator = numerator < 0n ? -numerator : numerator;
10059
- const scale = pow10$1(precision);
10072
+ const scale = pow10$2(precision);
10060
10073
  const scaled = (absNumerator * scale + denominator / 2n) / denominator;
10061
10074
  const integerPart = scaled / scale;
10062
10075
  const fractionalPart = scaled % scale;
@@ -10074,11 +10087,11 @@ function parseDecimalToFraction(value) {
10074
10087
  const integerDigits = integerStr === "" ? "0" : integerStr;
10075
10088
  const digits = `${integerDigits}${fractionalStr}`;
10076
10089
  let numerator = BigInt(digits === "" ? "0" : digits);
10077
- let denominator = pow10$1(BigInt(fractionalStr.length));
10090
+ let denominator = pow10$2(BigInt(fractionalStr.length));
10078
10091
  if (exponentPart !== void 0 && exponentPart !== "") {
10079
10092
  const exponent = BigInt(exponentPart);
10080
- if (exponent > 0n) numerator *= pow10$1(exponent);
10081
- else if (exponent < 0n) denominator *= pow10$1(-exponent);
10093
+ if (exponent > 0n) numerator *= pow10$2(exponent);
10094
+ else if (exponent < 0n) denominator *= pow10$2(-exponent);
10082
10095
  }
10083
10096
  if (isNegative) numerator = -numerator;
10084
10097
  return {
@@ -10138,12 +10151,12 @@ function adjustRatioForDecimals(numerator, denominator, decimals0, decimals1) {
10138
10151
  denominator
10139
10152
  };
10140
10153
  if (diff > 0n) return {
10141
- numerator: numerator * pow10$1(diff),
10154
+ numerator: numerator * pow10$2(diff),
10142
10155
  denominator
10143
10156
  };
10144
10157
  return {
10145
10158
  numerator,
10146
- denominator: denominator * pow10$1(-diff)
10159
+ denominator: denominator * pow10$2(-diff)
10147
10160
  };
10148
10161
  }
10149
10162
  /**
@@ -10240,16 +10253,16 @@ function priceToTick(price, decimals0, decimals1) {
10240
10253
  let targetNumerator = parsed.numerator;
10241
10254
  let targetDenominator = parsed.denominator;
10242
10255
  const diff = decimals0 - decimals1;
10243
- if (diff > 0n) targetDenominator *= pow10$1(diff);
10244
- else if (diff < 0n) targetNumerator *= pow10$1(-diff);
10256
+ if (diff > 0n) targetDenominator *= pow10$2(diff);
10257
+ else if (diff < 0n) targetNumerator *= pow10$2(-diff);
10245
10258
  let low = MIN_TICK;
10246
10259
  let high = MAX_TICK;
10247
10260
  while (low <= high) {
10248
10261
  const mid = (low + high) / 2n;
10249
10262
  const { numerator, denominator } = getRawPriceRatio(mid);
10250
- const cmp = compareRatios(numerator, denominator, targetNumerator, targetDenominator);
10251
- if (cmp === 0) return mid;
10252
- if (cmp < 0) low = mid + 1n;
10263
+ const cmp$1 = compareRatios(numerator, denominator, targetNumerator, targetDenominator);
10264
+ if (cmp$1 === 0) return mid;
10265
+ if (cmp$1 < 0) low = mid + 1n;
10253
10266
  else high = mid - 1n;
10254
10267
  }
10255
10268
  const floorTick = high;
@@ -10459,7 +10472,7 @@ function tickLimits(currentTick, toleranceBps) {
10459
10472
 
10460
10473
  //#endregion
10461
10474
  //#region src/panoptic/v2/tokenId/deriveUniqueTokenId.ts
10462
- const POOL_ID_MASK$3 = (1n << 64n) - 1n;
10475
+ const POOL_ID_MASK$4 = (1n << 64n) - 1n;
10463
10476
  const MAX_LEGS = TOKEN_ID_BITS.MAX_LEGS;
10464
10477
  const MAX_OPTION_RATIO = LEG_LIMITS.MAX_RATIO;
10465
10478
  const Q192$4 = 1n << 192n;
@@ -10566,7 +10579,7 @@ function scaleRatios(baseTokenId, targetPositionSize) {
10566
10579
  const N = MAX_OPTION_RATIO / maxRatio;
10567
10580
  if (N < 2n) throw new PanopticError("deriveUniqueTokenId: cannot derive a unique tokenId — all 4 leg slots used and optionRatios already near the 127 ceiling");
10568
10581
  const newPositionSize = (targetPositionSize + N - 1n) / N;
10569
- const poolId = baseTokenId & POOL_ID_MASK$3;
10582
+ const poolId = baseTokenId & POOL_ID_MASK$4;
10570
10583
  let out = poolId;
10571
10584
  for (const leg of legs) out = addLegToTokenId(out, {
10572
10585
  index: leg.index,
@@ -11380,14 +11393,14 @@ function formatGwei(wei, precision) {
11380
11393
  //#endregion
11381
11394
  //#region src/panoptic/v2/tokenId/generateOverlapping.ts
11382
11395
  const MAX_UINT64$2 = (1n << 64n) - 1n;
11383
- const MAX_UINT128$3 = (1n << 128n) - 1n;
11396
+ const MAX_UINT128$4 = (1n << 128n) - 1n;
11384
11397
  const Q192$3 = 1n << 192n;
11385
11398
  const MAX_TOKEN_DECIMALS = 255n;
11386
11399
  const MAX_DECIMAL_EXPONENT = 512n;
11387
11400
  function invalid$1(message) {
11388
11401
  throw new PanopticValidationError(`generateOverlappingTokenIds: ${message}`);
11389
11402
  }
11390
- function pow10(exponent) {
11403
+ function pow10$1(exponent) {
11391
11404
  return 10n ** exponent;
11392
11405
  }
11393
11406
  function parsePriceSpacing(value, quoteDecimals) {
@@ -11400,7 +11413,7 @@ function parsePriceSpacing(value, quoteDecimals) {
11400
11413
  let units = BigInt(`${integerPart}${fractionalPart}`);
11401
11414
  let scale = BigInt(fractionalPart.length) - exponent;
11402
11415
  if (scale < 0n) {
11403
- units *= pow10(-scale);
11416
+ units *= pow10$1(-scale);
11404
11417
  scale = 0n;
11405
11418
  }
11406
11419
  while (scale > 0n && units % 10n === 0n) {
@@ -11412,7 +11425,7 @@ function parsePriceSpacing(value, quoteDecimals) {
11412
11425
  return {
11413
11426
  units,
11414
11427
  scale,
11415
- denominator: pow10(scale)
11428
+ denominator: pow10$1(scale)
11416
11429
  };
11417
11430
  }
11418
11431
  function formatGridPrice(multiple, spacing) {
@@ -11429,8 +11442,8 @@ function quotePriceAtTick(tick, asset, assetDecimals, quoteDecimals) {
11429
11442
  let numerator = sqrtPriceX96 * sqrtPriceX96;
11430
11443
  let denominator = Q192$3;
11431
11444
  const decimalDifference = assetDecimals - quoteDecimals;
11432
- if (decimalDifference > 0n) numerator *= pow10(decimalDifference);
11433
- else if (decimalDifference < 0n) denominator *= pow10(-decimalDifference);
11445
+ if (decimalDifference > 0n) numerator *= pow10$1(decimalDifference);
11446
+ else if (decimalDifference < 0n) denominator *= pow10$1(-decimalDifference);
11434
11447
  return {
11435
11448
  numerator,
11436
11449
  denominator
@@ -11447,12 +11460,12 @@ function isPriceGridStrike(strike, params, spacing, tickSpacing) {
11447
11460
  }
11448
11461
  return false;
11449
11462
  }
11450
- function ceilDiv$1(value, divisor) {
11463
+ function ceilDiv$3(value, divisor) {
11451
11464
  const quotient = value / divisor;
11452
11465
  const remainder = value % divisor;
11453
11466
  return remainder > 0n ? quotient + 1n : quotient;
11454
11467
  }
11455
- function floorDiv(value, divisor) {
11468
+ function floorDiv$1(value, divisor) {
11456
11469
  const quotient = value / divisor;
11457
11470
  const remainder = value % divisor;
11458
11471
  return remainder < 0n ? quotient - 1n : quotient;
@@ -11480,8 +11493,8 @@ function resolveLegs(legs) {
11480
11493
  function getCandidateStrikes(params, spacing, tickSpacing, halfWidth) {
11481
11494
  const lower = MIN_TICK + halfWidth > params.currentTick - halfWidth + 1n ? MIN_TICK + halfWidth : params.currentTick - halfWidth + 1n;
11482
11495
  const upper = MAX_TICK - halfWidth < params.currentTick + halfWidth - 1n ? MAX_TICK - halfWidth : params.currentTick + halfWidth - 1n;
11483
- const firstStrike = ceilDiv$1(lower, tickSpacing) * tickSpacing;
11484
- const lastStrike = floorDiv(upper, tickSpacing) * tickSpacing;
11496
+ const firstStrike = ceilDiv$3(lower, tickSpacing) * tickSpacing;
11497
+ const lastStrike = floorDiv$1(upper, tickSpacing) * tickSpacing;
11485
11498
  const strikes = [];
11486
11499
  for (let strike = firstStrike; strike <= lastStrike; strike += tickSpacing) if (isPriceGridStrike(strike, params, spacing, tickSpacing)) strikes.push(strike);
11487
11500
  if (params.asset === 1n) strikes.reverse();
@@ -11521,7 +11534,7 @@ function generateOverlappingTokenIds(params) {
11521
11534
  if (params.currentTick < MIN_TICK || params.currentTick > MAX_TICK) invalid$1(`currentTick must be between ${MIN_TICK} and ${MAX_TICK}`);
11522
11535
  if (params.asset !== 0n && params.asset !== 1n) invalid$1("asset must be 0 or 1");
11523
11536
  if (params.assetDecimals < 0n || params.assetDecimals > MAX_TOKEN_DECIMALS || params.quoteDecimals < 0n || params.quoteDecimals > MAX_TOKEN_DECIMALS) invalid$1("assetDecimals and quoteDecimals must be between 0 and 255");
11524
- if (params.positionSize <= 0n || params.positionSize > MAX_UINT128$3) invalid$1("positionSize must be between 1 and uint128.max");
11537
+ if (params.positionSize <= 0n || params.positionSize > MAX_UINT128$4) invalid$1("positionSize must be between 1 and uint128.max");
11525
11538
  const tickSpacing = decodeTickSpacing(params.poolId);
11526
11539
  if (tickSpacing <= 0n) invalid$1("poolId tick spacing must be positive");
11527
11540
  const standardTickWidth = STANDARD_TICK_WIDTHS[params.timescale];
@@ -11542,15 +11555,15 @@ function generateOverlappingTokenIds(params) {
11542
11555
 
11543
11556
  //#endregion
11544
11557
  //#region src/panoptic/v2/tokenId/split.ts
11545
- const POOL_ID_MASK$2 = (1n << TOKEN_ID_BITS.POOL_ID_SIZE) - 1n;
11546
- const MAX_UINT128$2 = (1n << 128n) - 1n;
11558
+ const POOL_ID_MASK$3 = (1n << TOKEN_ID_BITS.POOL_ID_SIZE) - 1n;
11559
+ const MAX_UINT128$3 = (1n << 128n) - 1n;
11547
11560
  const MAX_UINT256$1 = (1n << 256n) - 1n;
11548
11561
  function invalid(message) {
11549
11562
  throw new PanopticValidationError(`splitTokenIdByTimescale: ${message}`);
11550
11563
  }
11551
11564
  function validateInput(tokenId, positionSize) {
11552
11565
  if (tokenId < 0n || tokenId > MAX_UINT256$1) invalid("tokenId must fit in uint256");
11553
- if (positionSize <= 0n || positionSize > MAX_UINT128$2) invalid("positionSize must be between 1 and uint128.max");
11566
+ if (positionSize <= 0n || positionSize > MAX_UINT128$3) invalid("positionSize must be between 1 and uint128.max");
11554
11567
  const legs = decodeAllLegs(tokenId);
11555
11568
  if (legs.length === 0) invalid("tokenId must contain at least one active leg");
11556
11569
  for (const [index, leg] of legs.entries()) if (leg.index !== BigInt(index)) invalid("active legs must be contiguous from index 0");
@@ -11679,7 +11692,7 @@ function splitTokenIdByTimescale(tokenId, positionSize, targetTimescale) {
11679
11692
  const targetTickWidth = STANDARD_TICK_WIDTHS[targetTimescale];
11680
11693
  if (targetTickWidth === void 0) invalid(`unknown target timescale ${String(targetTimescale)}`);
11681
11694
  const targetWidth = (targetTickWidth + tickSpacing - 1n) / tickSpacing;
11682
- const poolId = tokenId & POOL_ID_MASK$2;
11695
+ const poolId = tokenId & POOL_ID_MASK$3;
11683
11696
  const optionLegs = legs.filter((leg) => leg.width > 0n);
11684
11697
  const fundingLegs = legs.filter((leg) => leg.width === 0n);
11685
11698
  const positionIdList = [];
@@ -13562,7 +13575,7 @@ async function fetchPoolId(params) {
13562
13575
  //#endregion
13563
13576
  //#region src/panoptic/v2/greeks/index.ts
13564
13577
  /** Fixed-point scale constants for sqrtPriceX96 arithmetic */
13565
- const Q96 = 1n << 96n;
13578
+ const Q96$1 = 1n << 96n;
13566
13579
  const Q192$2 = 1n << 192n;
13567
13580
  /**
13568
13581
  * Convert tick to quote-denominated tick based on asset direction.
@@ -13710,7 +13723,7 @@ function computeOptionItm(m, qStrikeTick, qMintTick, halfWidthTick, isPut) {
13710
13723
  const sqrtK = tickToSqrtPriceX96(qStrikeTick);
13711
13724
  const sqrtPm = tickToSqrtPriceX96(qMintTick);
13712
13725
  const rX192 = sqrtR * sqrtR;
13713
- const sqrtKPmX96 = divTrunc(sqrtK * Q96, sqrtPm);
13726
+ const sqrtKPmX96 = divTrunc(sqrtK * Q96$1, sqrtPm);
13714
13727
  const diff = sqrtR - sqrtKPmX96;
13715
13728
  const diffSqX192 = diff * diff;
13716
13729
  return divTrunc(m * diffSqX192, rX192 - Q192$2);
@@ -13782,7 +13795,7 @@ function getLegValue(leg, currentTick, mintTick, positionSize, poolTickSpacing,
13782
13795
  const PX192 = sqrtP * sqrtP;
13783
13796
  const KX192 = sqrtK * sqrtK;
13784
13797
  const rX192 = sqrtR * sqrtR;
13785
- const numerator = m * (2n * sqrtPKR * Q96 - PX192 - KX192);
13798
+ const numerator = m * (2n * sqrtPKR * Q96$1 - PX192 - KX192);
13786
13799
  const denominator = rX192 - Q192$2;
13787
13800
  v = divTrunc(numerator, denominator);
13788
13801
  }
@@ -13890,7 +13903,7 @@ function getLegDelta(leg, currentTick, positionSize, poolTickSpacing, mintTick,
13890
13903
  const sqrtK = tickToSqrtPriceX96(qStrikeTick);
13891
13904
  const sqrtPm = tickToSqrtPriceX96(qMintTick);
13892
13905
  const rX192 = sqrtR * sqrtR;
13893
- const sqrtKPmX96 = sqrtK * Q96 / sqrtPm;
13906
+ const sqrtKPmX96 = sqrtK * Q96$1 / sqrtPm;
13894
13907
  const diff = sqrtR - sqrtKPmX96;
13895
13908
  const diffSqX192 = diff * diff;
13896
13909
  return divTrunc(m * diffSqX192, rX192 - Q192$2);
@@ -13949,7 +13962,7 @@ function getLegGamma(leg, currentTick, positionSize, poolTickSpacing, assetIndex
13949
13962
  const sqrtKPR = tickToSqrtPriceX96(qStrikeTick + qCurrentTick + halfWidthTick);
13950
13963
  const sqrtR = tickToSqrtPriceX96(halfWidthTick);
13951
13964
  const rX192 = sqrtR * sqrtR;
13952
- const numerator = m * sqrtKPR * Q96;
13965
+ const numerator = m * sqrtKPR * Q96$1;
13953
13966
  const denominator = 2n * (rX192 - Q192$2);
13954
13967
  return divTrunc(numerator, denominator);
13955
13968
  }
@@ -18070,7 +18083,7 @@ function maximumAmountIn(estimatedAmountIn, slippageBps) {
18070
18083
  if (slippageBps < 0n) throw new PanopticError("slippageBps must be non-negative");
18071
18084
  return (estimatedAmountIn * (BPS_DENOMINATOR$3 + slippageBps) + BPS_DENOMINATOR$3 - 1n) / BPS_DENOMINATOR$3;
18072
18085
  }
18073
- function ceilDiv(numerator, denominator) {
18086
+ function ceilDiv$2(numerator, denominator) {
18074
18087
  return (numerator + denominator - 1n) / denominator;
18075
18088
  }
18076
18089
  function getInputAmount(tokenFlow, tokenInIndex) {
@@ -18185,7 +18198,7 @@ async function quoteTokenShortfallRecovery(params) {
18185
18198
  error: new PanopticError("Insufficient source collateral for the recovery swap")
18186
18199
  };
18187
18200
  if (estimatedAmountOut < requiredOutput) {
18188
- creditInput = estimatedAmountOut > 0n ? ceilDiv(creditInput * requiredOutput, estimatedAmountOut) + 1n : creditInput * 2n;
18201
+ creditInput = estimatedAmountOut > 0n ? ceilDiv$2(creditInput * requiredOutput, estimatedAmountOut) + 1n : creditInput * 2n;
18189
18202
  continue;
18190
18203
  }
18191
18204
  const recoveredDispatch = buildPrefixedExactInputRecoveryDispatch({
@@ -18239,7 +18252,7 @@ async function quoteTokenShortfallRecovery(params) {
18239
18252
  };
18240
18253
  const residual = remainingShortfall.assetsRequested - remainingShortfall.assetBalance;
18241
18254
  requiredOutput += residual > 0n ? residual : requiredOutput;
18242
- creditInput = ceilDiv(creditInput * requiredOutput, estimatedAmountOut) + 1n;
18255
+ creditInput = ceilDiv$2(creditInput * requiredOutput, estimatedAmountOut) + 1n;
18243
18256
  }
18244
18257
  return {
18245
18258
  available: false,
@@ -18295,7 +18308,7 @@ async function quoteTokenShortfallRecovery(params) {
18295
18308
  const swapOutput = getOutputAmount(swapSimulation.tokenFlow, tokenOutIndex);
18296
18309
  const sourceBalance = getBalanceBefore(swapSimulation.tokenFlow, tokenInIndex);
18297
18310
  if (swapOutput < amountOut) {
18298
- creditOutSize = swapOutput > 0n ? ceilDiv(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
18311
+ creditOutSize = swapOutput > 0n ? ceilDiv$2(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
18299
18312
  continue;
18300
18313
  }
18301
18314
  if (sourceBalance < maxAmountIn) return {
@@ -18354,7 +18367,7 @@ async function quoteTokenShortfallRecovery(params) {
18354
18367
  const decodedShortfall = remainingShortfall.assetsRequested - remainingShortfall.assetBalance;
18355
18368
  const additionalAmountOut = decodedShortfall > 0n ? decodedShortfall : amountOut;
18356
18369
  amountOut += additionalAmountOut;
18357
- creditOutSize = swapOutput > 0n ? ceilDiv(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
18370
+ creditOutSize = swapOutput > 0n ? ceilDiv$2(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
18358
18371
  }
18359
18372
  return {
18360
18373
  available: false,
@@ -18703,7 +18716,7 @@ async function getItmAmounts(params) {
18703
18716
  */
18704
18717
  const FLOW_NEUTRAL_DUST_THRESHOLD = 1000n;
18705
18718
  const Q192$1 = 1n << 192n;
18706
- const POOL_ID_MASK$1 = (1n << 64n) - 1n;
18719
+ const POOL_ID_MASK$2 = (1n << 64n) - 1n;
18707
18720
  /**
18708
18721
  * Floor integer square root for bigints (Newton's method). Exact for all
18709
18722
  * non-negative inputs — no float precision loss for values above 2^53.
@@ -18863,7 +18876,7 @@ async function createFlowNeutralTokenId(params) {
18863
18876
  const measureSize = referenceSize !== void 0 && referenceSize > 0n && referenceSize < positionSize ? referenceSize : positionSize;
18864
18877
  const legCount = countLegs(tokenId);
18865
18878
  if (legCount >= 4n) throw new PanopticError("Cannot append neutralizing leg: tokenId already has 4 legs");
18866
- const poolId = tokenId & POOL_ID_MASK$1;
18879
+ const poolId = tokenId & POOL_ID_MASK$2;
18867
18880
  const baseLegs = decodeAllLegs(tokenId);
18868
18881
  const prependNeutral = baseLegs.length === 1 && baseLegs[0].tokenType === baseLegs[0].asset;
18869
18882
  let credit;
@@ -19170,7 +19183,7 @@ async function tryWithdrawSimulation(params) {
19170
19183
  //#endregion
19171
19184
  //#region src/panoptic/v2/reads/collateralBreakdown.ts
19172
19185
  /** Mask selecting the poolId (low 64 bits) of a tokenId. */
19173
- const POOL_ID_MASK = (1n << 64n) - 1n;
19186
+ const POOL_ID_MASK$1 = (1n << 64n) - 1n;
19174
19187
  /** `getRequiredBase` prices at `type(uint64).max`; results scale linearly in size. */
19175
19188
  const MAX_UINT64 = 2n ** 64n - 1n;
19176
19189
  /** Kinds whose collateral rule is identical on-chain and must share one explanation. */
@@ -19295,7 +19308,7 @@ function isolateGroupTokenId(tokenId, legIndices) {
19295
19308
  const byIndex = new Map(legs.map((leg) => [leg.index, leg]));
19296
19309
  const ordered = [...legIndices].sort((x, y) => x < y ? -1 : x > y ? 1 : 0);
19297
19310
  const remapped = new Map(ordered.map((old, i) => [old, BigInt(i)]));
19298
- let out = tokenId & POOL_ID_MASK;
19311
+ let out = tokenId & POOL_ID_MASK$1;
19299
19312
  for (const [index, oldIndex] of ordered.entries()) {
19300
19313
  const leg = byIndex.get(oldIndex);
19301
19314
  if (leg === void 0) throw new PanopticError(`isolateGroupTokenId: leg ${oldIndex} is not present in the tokenId`);
@@ -22166,7 +22179,7 @@ const nfpmAbi = [{
22166
22179
  }],
22167
22180
  stateMutability: "payable"
22168
22181
  }];
22169
- const MAX_UINT128$1 = 2n ** 128n - 1n;
22182
+ const MAX_UINT128$2 = 2n ** 128n - 1n;
22170
22183
  const MAX_UINT256 = 2n ** 256n - 1n;
22171
22184
  const Q128 = 2n ** 128n;
22172
22185
  /**
@@ -22208,8 +22221,8 @@ async function getUniswapV3LpPositionState(params) {
22208
22221
  args: [{
22209
22222
  tokenId,
22210
22223
  recipient: owner,
22211
- amount0Max: MAX_UINT128$1,
22212
- amount1Max: MAX_UINT128$1
22224
+ amount0Max: MAX_UINT128$2,
22225
+ amount1Max: MAX_UINT128$2
22213
22226
  }],
22214
22227
  account: owner,
22215
22228
  blockNumber: _meta.blockNumber
@@ -24586,214 +24599,864 @@ async function executeSettleSequenceAndWait(params) {
24586
24599
  }
24587
24600
 
24588
24601
  //#endregion
24589
- //#region src/panoptic/v2/writes/settle.ts
24590
- /**
24591
- * Settle accumulated premia on existing positions.
24592
- *
24593
- * This function triggers premium collection without changing position size.
24594
- * It calls dispatch with unchanged position lists.
24595
- *
24596
- * @param params - Settlement parameters
24597
- * @returns TxResult
24598
- *
24599
- * @example
24600
- * ```typescript
24601
- * const result = await settleAccumulatedPremia({
24602
- * client,
24603
- * walletClient,
24604
- * account,
24605
- * poolAddress,
24606
- * positionIdList: existingPositions,
24607
- * })
24608
- * const receipt = await result.wait()
24609
- * ```
24610
- */
24611
- async function settleAccumulatedPremia(params) {
24612
- const { client, walletClient, account, poolAddress, positionIdList, finalPositionIdList, positionSizes: providedSizes, usePremiaAsCollateral = false, builderCode = 0n, txOverrides } = params;
24613
- if (providedSizes && providedSizes.length !== positionIdList.length) throw new PanopticError("settleAccumulatedPremia: positionSizes length must match positionIdList");
24614
- const positionSizes = providedSizes ?? await getCurrentPositionSizes({
24615
- client,
24616
- poolAddress,
24617
- account,
24618
- positionIdList
24602
+ //#region src/panoptic/v2/writes/protectedSettle.ts
24603
+ const POOL_ID_MASK = (1n << 64n) - 1n;
24604
+ const Q96 = 1n << 96n;
24605
+ const MAX_UINT128$1 = (1n << 128n) - 1n;
24606
+ const SETTLE_LIMITS = [
24607
+ -887272n,
24608
+ 887272n,
24609
+ 0n
24610
+ ];
24611
+ function ceilDiv$1(numerator, denominator) {
24612
+ return (numerator + denominator - 1n) / denominator;
24613
+ }
24614
+ /** Smallest position size that creates non-zero liquidity on every poke leg. */
24615
+ function minimumPokeSize(legs, tickSpacing) {
24616
+ let requiredSize = 1n;
24617
+ for (const leg of legs) {
24618
+ const widthInTicks = leg.width * tickSpacing;
24619
+ const lowerTick = leg.strike - widthInTicks / 2n;
24620
+ const upperTick = leg.strike + (widthInTicks + 1n) / 2n;
24621
+ const sqrtLower = tickToSqrtPriceX96(lowerTick);
24622
+ const sqrtUpper = tickToSqrtPriceX96(upperTick);
24623
+ const delta = sqrtUpper - sqrtLower;
24624
+ const liquidityFactor = leg.asset === 0n ? sqrtLower * sqrtUpper / Q96 : Q96;
24625
+ if (liquidityFactor === 0n) return void 0;
24626
+ const requiredAmount = ceilDiv$1(delta, liquidityFactor);
24627
+ const legSize = ceilDiv$1(requiredAmount, leg.optionRatio);
24628
+ if (legSize > requiredSize) requiredSize = legSize;
24629
+ }
24630
+ if (requiredSize > MAX_UINT128$1) return void 0;
24631
+ return requiredSize;
24632
+ }
24633
+ function encodePokeToken(sourceTokenId, legs, firstRatio, assetMask) {
24634
+ let tokenId = sourceTokenId & POOL_ID_MASK;
24635
+ legs.forEach((leg, index) => {
24636
+ const encodedIndex = BigInt(index);
24637
+ tokenId = addLegToTokenId(tokenId, {
24638
+ index: encodedIndex,
24639
+ asset: assetMask >> encodedIndex & 1n,
24640
+ optionRatio: index === 0 ? firstRatio : leg.optionRatio,
24641
+ isLong: 0n,
24642
+ tokenType: leg.tokenType,
24643
+ riskPartner: encodedIndex,
24644
+ strike: leg.strike,
24645
+ width: leg.width
24646
+ });
24619
24647
  });
24620
- const tickAndSpreadLimits = positionIdList.map(() => [
24621
- -887272n,
24622
- 887272n,
24623
- 0n
24624
- ]);
24625
- return submitWrite({
24626
- client,
24627
- walletClient,
24628
- account,
24629
- address: poolAddress,
24630
- abi: panopticPoolV2Abi,
24631
- functionName: "dispatch",
24632
- args: [
24633
- positionIdList,
24634
- finalPositionIdList ?? positionIdList,
24635
- positionSizes.map((s) => BigInt(s)),
24636
- tickAndSpreadLimits.map((t) => [
24637
- Number(t[0]),
24638
- Number(t[1]),
24639
- Number(t[2])
24640
- ]),
24641
- usePremiaAsCollateral,
24642
- builderCode
24643
- ],
24644
- txOverrides
24648
+ return tokenId;
24649
+ }
24650
+ function buildUniquePoke(sourceTokenId, occupied) {
24651
+ const seenChunks = new Set();
24652
+ const shortChunkLegs = decodeAllLegs(sourceTokenId).filter((leg) => {
24653
+ if (leg.isLong || leg.width === 0n) return false;
24654
+ const chunkKey = `${leg.strike}:${leg.width}:${leg.tokenType}`;
24655
+ if (seenChunks.has(chunkKey)) return false;
24656
+ seenChunks.add(chunkKey);
24657
+ return true;
24645
24658
  });
24646
- }
24647
- /**
24648
- * Settle premia and wait for confirmation.
24649
- */
24650
- async function settleAccumulatedPremiaAndWait(params) {
24651
- const result = await settleAccumulatedPremia(params);
24652
- return result.wait();
24653
- }
24654
-
24655
- //#endregion
24656
- //#region src/panoptic/v2/writes/pokeOracle.ts
24657
- /**
24658
- * Poke the oracle to update its state.
24659
- *
24660
- * This function can be called to advance the oracle epoch.
24661
- * Note: The oracle can only be poked once per epoch (64 seconds).
24662
- *
24663
- * @param params - Poke oracle parameters
24664
- * @returns TxResult
24665
- * @throws OracleRateLimitedError if checkRateLimit is true and oracle was recently poked
24666
- *
24667
- * @example
24668
- * ```typescript
24669
- * const result = await pokeOracle({
24670
- * client,
24671
- * walletClient,
24672
- * account,
24673
- * poolAddress,
24674
- * })
24675
- * const receipt = await result.wait()
24676
- * ```
24677
- */
24678
- async function pokeOracle(params) {
24679
- const { client, walletClient, account, poolAddress, checkRateLimit = false, txOverrides } = params;
24680
- if (checkRateLimit) {
24681
- const [oracleData, block] = await Promise.all([client.readContract({
24682
- address: poolAddress,
24683
- abi: panopticPoolV2Abi,
24684
- functionName: "getOracleTicks"
24685
- }), client.getBlock()]);
24686
- const oraclePack = oracleData[4];
24687
- const { epoch } = decodeOracleTiming(oraclePack, block.timestamp);
24688
- const currentEpoch = oracleEpochAt(block.timestamp);
24689
- if (currentEpoch === epoch) {
24690
- const lastUpdate = epoch << 6n;
24691
- throw new OracleRateLimitedError(lastUpdate, block.timestamp);
24659
+ if (shortChunkLegs.length === 0) return void 0;
24660
+ const originalRatio = shortChunkLegs[0].optionRatio;
24661
+ for (let ratioOffset = 0n; ratioOffset < 127n; ratioOffset += 1n) {
24662
+ const firstRatio = (originalRatio - 1n + ratioOffset) % 127n + 1n;
24663
+ const assetVariants = 1n << BigInt(shortChunkLegs.length);
24664
+ for (let assetMask = 0n; assetMask < assetVariants; assetMask += 1n) {
24665
+ const tokenId = encodePokeToken(sourceTokenId, shortChunkLegs, firstRatio, assetMask);
24666
+ if (!occupied.has(tokenId)) {
24667
+ const size = minimumPokeSize(decodeAllLegs(tokenId), decodeTickSpacing(sourceTokenId));
24668
+ if (size !== void 0) return {
24669
+ tokenId,
24670
+ size
24671
+ };
24672
+ }
24692
24673
  }
24693
24674
  }
24694
- return submitWrite({
24695
- client,
24696
- walletClient,
24697
- account,
24698
- address: poolAddress,
24699
- abi: panopticPoolV2Abi,
24700
- functionName: "pokeOracle",
24701
- args: [],
24702
- txOverrides
24675
+ throw new PanopticError("Unable to derive a collision-free protected settlement poke");
24676
+ }
24677
+ /**
24678
+ * Build `[poke, settle, poke]` for every target containing a width>0 short.
24679
+ * Pure-long and width-zero positions are settled directly.
24680
+ */
24681
+ function buildProtectedSettlePlan(params) {
24682
+ const { positionIdList, finalPositionIdList, positionSizes, usePremiaAsCollateral = false, builderCode = 0n } = params;
24683
+ if (positionIdList.length !== positionSizes.length) throw new PanopticError("Protected settlement: positionSizes length must match positionIdList");
24684
+ const occupied = new Set(finalPositionIdList);
24685
+ const actionIds = [];
24686
+ const actionSizes = [];
24687
+ const actionLimits = [];
24688
+ const collectionIds = [];
24689
+ const collectionSizes = [];
24690
+ const collectionLimits = [];
24691
+ const pokingTokenIds = [];
24692
+ positionIdList.forEach((tokenId, index) => {
24693
+ const poke = buildUniquePoke(tokenId, occupied);
24694
+ if (poke === void 0) {
24695
+ actionIds.push(tokenId);
24696
+ actionSizes.push(positionSizes[index]);
24697
+ actionLimits.push(SETTLE_LIMITS);
24698
+ return;
24699
+ }
24700
+ occupied.add(poke.tokenId);
24701
+ pokingTokenIds.push(poke.tokenId);
24702
+ actionIds.push(poke.tokenId, tokenId, poke.tokenId);
24703
+ actionSizes.push(poke.size, positionSizes[index], 0n);
24704
+ actionLimits.push(SETTLE_LIMITS, SETTLE_LIMITS, SETTLE_LIMITS);
24705
+ collectionIds.push(poke.tokenId, poke.tokenId);
24706
+ collectionSizes.push(poke.size, 0n);
24707
+ collectionLimits.push(SETTLE_LIMITS, SETTLE_LIMITS);
24703
24708
  });
24709
+ const base = {
24710
+ finalPositionIdList: [...finalPositionIdList],
24711
+ usePremiaAsCollateral,
24712
+ builderCode
24713
+ };
24714
+ return {
24715
+ dispatch: {
24716
+ ...base,
24717
+ positionIdList: actionIds,
24718
+ positionSizes: actionSizes,
24719
+ tickAndSpreadLimits: actionLimits
24720
+ },
24721
+ collectionDispatch: collectionIds.length === 0 ? void 0 : {
24722
+ ...base,
24723
+ positionIdList: collectionIds,
24724
+ positionSizes: collectionSizes,
24725
+ tickAndSpreadLimits: collectionLimits
24726
+ },
24727
+ pokingTokenIds
24728
+ };
24704
24729
  }
24705
24730
  /**
24706
- * Poke oracle and wait for confirmation.
24731
+ * Build the atomic self-settlement dispatch that temporarily pokes each
24732
+ * affected short chunk before settling its source position.
24733
+ *
24734
+ * @param params - Positions, current sizes, and complete held-position list.
24735
+ * @returns A dispatch intent ready for simulation or submission.
24707
24736
  */
24708
- async function pokeOracleAndWait(params) {
24709
- const result = await pokeOracle(params);
24710
- return result.wait();
24737
+ function buildProtectedSettleDispatch(params) {
24738
+ return buildProtectedSettlePlan(params).dispatch;
24711
24739
  }
24712
24740
 
24713
24741
  //#endregion
24714
- //#region src/panoptic/v2/writes/factory.ts
24742
+ //#region src/panoptic/v2/simulations/simulateSettlePremiumFrom.ts
24743
+ /** Soft-failure revert markers for settle premium (target-state issues, not caller errors). */
24744
+ const SOFT_FAILURES = [
24745
+ {
24746
+ marker: "AccountInsolvent",
24747
+ reason: "Target account is insolvent; premium cannot be settled"
24748
+ },
24749
+ {
24750
+ marker: "PositionNotOwned",
24751
+ reason: "Target account no longer owns the position"
24752
+ },
24753
+ {
24754
+ marker: "StaleOracle",
24755
+ reason: "Oracle price is stale; settlement temporarily unavailable"
24756
+ },
24757
+ {
24758
+ marker: "InputListFail",
24759
+ reason: "Position list is stale (target positions changed)"
24760
+ }
24761
+ ];
24715
24762
  /**
24716
- * Deploy a new Panoptic pool via the factory.
24763
+ * Simulate settling another account's accumulated long premium via `dispatchFrom`
24764
+ * (equal-length `positionIdListTo`/`positionIdListToFinal` selects the settle mode).
24717
24765
  *
24718
- * @param params - Deployment parameters (versioned: 'v3' or 'v4')
24719
- * @returns Transaction result with hash and wait function
24766
+ * The measured token flow is the CALLER's collateral delta — i.e. the premium
24767
+ * the caller receives from the settlement (for chunks they sold).
24768
+ *
24769
+ * @param params - Simulation parameters
24770
+ * @returns Simulation result with settled premium data or error
24720
24771
  */
24721
- async function deployNewPool(params) {
24722
- const { client, walletClient, account, factoryAddress, riskEngine, salt, txOverrides } = params;
24723
- if (params.version === "v3") return submitWrite({
24724
- client,
24725
- walletClient,
24726
- account,
24727
- address: factoryAddress,
24728
- abi: panopticFactoryV3Abi,
24729
- functionName: "deployNewPool",
24730
- args: [
24731
- params.token0,
24732
- params.token1,
24733
- params.fee,
24734
- riskEngine,
24735
- salt
24736
- ],
24737
- txOverrides
24738
- });
24739
- return submitWrite({
24772
+ async function simulateSettlePremiumFrom(params) {
24773
+ const { client, poolAddress, account, user, positionIdListFrom, positionIdList, tokenId, blockNumber } = params;
24774
+ const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
24775
+ const metaPromise = getBlockMeta({
24740
24776
  client,
24741
- walletClient,
24742
- account,
24743
- address: factoryAddress,
24744
- abi: panopticFactoryV4Abi,
24745
- functionName: "deployNewPool",
24746
- args: [
24747
- {
24748
- currency0: params.poolKey.currency0,
24749
- currency1: params.poolKey.currency1,
24750
- fee: Number(params.poolKey.fee),
24751
- tickSpacing: Number(params.poolKey.tickSpacing),
24752
- hooks: params.poolKey.hooks
24753
- },
24754
- riskEngine,
24755
- salt
24756
- ],
24757
- txOverrides
24777
+ blockNumber: targetBlockNumber
24758
24778
  });
24759
- }
24760
- /**
24761
- * Deploy a new Panoptic pool and wait for confirmation.
24762
- */
24763
- async function deployNewPoolAndWait(params) {
24764
- const result = await deployNewPool(params);
24765
- return result.wait();
24766
- }
24767
-
24768
- //#endregion
24769
- //#region src/panoptic/v2/writes/txManagement.ts
24770
- /** Default gas price multiplier for replacement (12.5% bump = minimum for replacement) */
24771
- const DEFAULT_GAS_PRICE_MULTIPLIER = 1.125;
24772
- /**
24773
- * Apply a multiplier to a bigint gas value.
24774
- * Uses integer arithmetic to avoid floating point issues.
24775
- */
24776
- function applyMultiplier(value, multiplier) {
24777
- const bps = BigInt(Math.ceil(multiplier * 1e4));
24778
- return value * bps / 10000n;
24779
- }
24780
- /**
24781
- * Compute bumped gas parameters from the original transaction.
24782
- */
24783
- function computeBumpedGas(originalMaxFeePerGas, originalMaxPriorityFeePerGas, explicitMaxFeePerGas, explicitMaxPriorityFeePerGas, multiplier) {
24784
- const maxFeePerGas = explicitMaxFeePerGas ?? applyMultiplier(originalMaxFeePerGas ?? 0n, multiplier);
24785
- const maxPriorityFeePerGas = explicitMaxPriorityFeePerGas ?? applyMultiplier(originalMaxPriorityFeePerGas ?? 0n, multiplier);
24786
- return {
24787
- maxFeePerGas,
24788
- maxPriorityFeePerGas
24789
- };
24790
- }
24791
- /**
24792
- * Speed up a pending transaction by resubmitting with higher gas.
24793
- *
24794
- * Fetches the original transaction, extracts its parameters,
24795
- * bumps the gas price, and resubmits with the same nonce.
24796
- *
24779
+ const emptyTokenFlow = {
24780
+ delta0: 0n,
24781
+ delta1: 0n,
24782
+ balanceBefore0: 0n,
24783
+ balanceBefore1: 0n,
24784
+ balanceAfter0: 0n,
24785
+ balanceAfter1: 0n,
24786
+ tickBefore: null,
24787
+ tickAfter: null
24788
+ };
24789
+ const softFailure = (errorMessage) => {
24790
+ const match = SOFT_FAILURES.find(({ marker }) => errorMessage.includes(marker));
24791
+ return match ? {
24792
+ premium0: 0n,
24793
+ premium1: 0n,
24794
+ settled0: 0n,
24795
+ settled1: 0n,
24796
+ canSettle: false,
24797
+ reason: match.reason
24798
+ } : null;
24799
+ };
24800
+ try {
24801
+ const orderedList = tokenId !== void 0 ? orderListForSettle(positionIdList, tokenId) : positionIdList;
24802
+ const callData = encodeFunctionData({
24803
+ abi: panopticPoolV2Abi,
24804
+ functionName: "dispatchFrom",
24805
+ args: [
24806
+ positionIdListFrom,
24807
+ user,
24808
+ orderedList,
24809
+ orderedList,
24810
+ 0n
24811
+ ]
24812
+ });
24813
+ const availablePremiumCallData = encodeFunctionData({
24814
+ abi: panopticPoolV2Abi,
24815
+ functionName: "getFullPositionsData",
24816
+ args: [
24817
+ account,
24818
+ false,
24819
+ positionIdListFrom
24820
+ ]
24821
+ });
24822
+ const buyerOwedCallData = encodeFunctionData({
24823
+ abi: panopticPoolV2Abi,
24824
+ functionName: "getFullPositionsData",
24825
+ args: [
24826
+ user,
24827
+ true,
24828
+ orderedList
24829
+ ]
24830
+ });
24831
+ const flowResult = await simulateWithTokenFlow({
24832
+ client,
24833
+ poolAddress,
24834
+ user: account,
24835
+ callData,
24836
+ blockNumber: targetBlockNumber,
24837
+ preCallData: [availablePremiumCallData, buyerOwedCallData],
24838
+ postCallData: [availablePremiumCallData, buyerOwedCallData]
24839
+ });
24840
+ if (!flowResult.success || !flowResult.tokenFlow) {
24841
+ const errorMessage = flowResult.error || "Simulation failed";
24842
+ const soft = softFailure(errorMessage);
24843
+ if (soft) {
24844
+ const _meta$1 = await metaPromise;
24845
+ return {
24846
+ success: true,
24847
+ data: soft,
24848
+ gasEstimate: 0n,
24849
+ tokenFlow: emptyTokenFlow,
24850
+ _meta: _meta$1
24851
+ };
24852
+ }
24853
+ throw new PanopticError(errorMessage);
24854
+ }
24855
+ const _meta = await metaPromise;
24856
+ const tokenFlow = flowResult.tokenFlow;
24857
+ const decodePremia = (raw) => {
24858
+ const [shortPremiumPacked, longPremiumPacked] = decodeFunctionResult({
24859
+ abi: panopticPoolV2Abi,
24860
+ functionName: "getFullPositionsData",
24861
+ data: raw
24862
+ });
24863
+ const short = decodeLeftRightUnsigned(shortPremiumPacked);
24864
+ const long = decodeLeftRightUnsigned(longPremiumPacked);
24865
+ return {
24866
+ short0: short.right,
24867
+ short1: short.left,
24868
+ long0: long.right,
24869
+ long1: long.left
24870
+ };
24871
+ };
24872
+ let premium0 = 0n;
24873
+ let premium1 = 0n;
24874
+ const preRaw = flowResult.preCallResults?.[0];
24875
+ const postRaw = flowResult.postCallResults?.[0];
24876
+ if (preRaw !== void 0 && postRaw !== void 0) {
24877
+ const pre = decodePremia(preRaw);
24878
+ const post = decodePremia(postRaw);
24879
+ premium0 = post.short0 > pre.short0 ? post.short0 - pre.short0 : 0n;
24880
+ premium1 = post.short1 > pre.short1 ? post.short1 - pre.short1 : 0n;
24881
+ }
24882
+ let settled0 = 0n;
24883
+ let settled1 = 0n;
24884
+ const preBuyerRaw = flowResult.preCallResults?.[1];
24885
+ const postBuyerRaw = flowResult.postCallResults?.[1];
24886
+ if (preBuyerRaw !== void 0 && postBuyerRaw !== void 0) {
24887
+ const pre = decodePremia(preBuyerRaw);
24888
+ const post = decodePremia(postBuyerRaw);
24889
+ settled0 = pre.long0 > post.long0 ? pre.long0 - post.long0 : 0n;
24890
+ settled1 = pre.long1 > post.long1 ? pre.long1 - post.long1 : 0n;
24891
+ }
24892
+ const data = {
24893
+ premium0,
24894
+ premium1,
24895
+ settled0,
24896
+ settled1,
24897
+ canSettle: true
24898
+ };
24899
+ return {
24900
+ success: true,
24901
+ data,
24902
+ gasEstimate: flowResult.gasEstimate,
24903
+ tokenFlow,
24904
+ _meta
24905
+ };
24906
+ } catch (error) {
24907
+ const _meta = await metaPromise;
24908
+ const errorMessage = error instanceof Error ? error.message : "Simulation failed";
24909
+ const soft = softFailure(errorMessage);
24910
+ if (soft) return {
24911
+ success: true,
24912
+ data: soft,
24913
+ gasEstimate: 0n,
24914
+ tokenFlow: emptyTokenFlow,
24915
+ _meta
24916
+ };
24917
+ return {
24918
+ success: false,
24919
+ error: error instanceof PanopticError ? error : new PanopticError(errorMessage, error instanceof Error ? error : void 0),
24920
+ _meta
24921
+ };
24922
+ }
24923
+ }
24924
+
24925
+ //#endregion
24926
+ //#region src/panoptic/v2/simulations/simulateSettlePremiumBatch.ts
24927
+ /**
24928
+ * Simulate settling each target buyer's owed long premium, all at one block.
24929
+ *
24930
+ * Individual failures (insolvent buyer, stale list, …) are soft: the target
24931
+ * lands in the unsettleable partition instead of failing the batch. Only
24932
+ * unexpected errors reject.
24933
+ *
24934
+ * @param params - Simulation parameters
24935
+ * @returns Partitioned targets with per-target premium and totals
24936
+ */
24937
+ async function simulateSettlePremiumBatch(params) {
24938
+ const { client, poolAddress, account, positionIdListFrom, targets, blockNumber } = params;
24939
+ const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
24940
+ const metaPromise = getBlockMeta({
24941
+ client,
24942
+ blockNumber: targetBlockNumber
24943
+ });
24944
+ const simulations = await Promise.all(targets.map((target) => simulateSettlePremiumFrom({
24945
+ client,
24946
+ poolAddress,
24947
+ account,
24948
+ user: target.user,
24949
+ positionIdListFrom,
24950
+ positionIdList: target.positionIdList,
24951
+ tokenId: target.tokenId,
24952
+ blockNumber: targetBlockNumber
24953
+ })));
24954
+ const results = [];
24955
+ const settleable = [];
24956
+ let unsettleableCount = 0;
24957
+ let premium0 = 0n;
24958
+ let premium1 = 0n;
24959
+ simulations.forEach((sim, i) => {
24960
+ const simulation = sim.success ? sim.data : {
24961
+ premium0: 0n,
24962
+ premium1: 0n,
24963
+ settled0: 0n,
24964
+ settled1: 0n,
24965
+ canSettle: false,
24966
+ reason: sim.error.message
24967
+ };
24968
+ results.push({
24969
+ target: targets[i],
24970
+ simulation
24971
+ });
24972
+ if (simulation.canSettle) {
24973
+ settleable.push(targets[i]);
24974
+ premium0 += simulation.premium0;
24975
+ premium1 += simulation.premium1;
24976
+ } else unsettleableCount += 1;
24977
+ });
24978
+ const _meta = await metaPromise;
24979
+ return {
24980
+ results,
24981
+ settleable,
24982
+ unsettleableCount,
24983
+ premium0,
24984
+ premium1,
24985
+ _meta
24986
+ };
24987
+ }
24988
+ /**
24989
+ * Simulate a full settle sequence (all settles + optional close) as the one
24990
+ * multicall that `executeSettleSequence` submits, measuring the caller's
24991
+ * total token flow and gas.
24992
+ *
24993
+ * @param params - Simulation parameters
24994
+ * @returns Simulation result with the caller's net flow, or error
24995
+ */
24996
+ async function simulateSettleSequence(params) {
24997
+ const { client, poolAddress, account, blockNumber } = params;
24998
+ const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
24999
+ const metaPromise = getBlockMeta({
25000
+ client,
25001
+ blockNumber: targetBlockNumber
25002
+ });
25003
+ try {
25004
+ const calls = buildSettleSequenceCalls(params);
25005
+ const callData = encodeFunctionData({
25006
+ abi: panopticPoolV2Abi,
25007
+ functionName: "multicall",
25008
+ args: [calls]
25009
+ });
25010
+ const flowResult = await simulateWithTokenFlow({
25011
+ client,
25012
+ poolAddress,
25013
+ user: account,
25014
+ callData,
25015
+ blockNumber: targetBlockNumber
25016
+ });
25017
+ if (!flowResult.success || !flowResult.tokenFlow) throw new PanopticError(flowResult.error || "Simulation failed");
25018
+ const _meta = await metaPromise;
25019
+ const tokenFlow = flowResult.tokenFlow;
25020
+ return {
25021
+ success: true,
25022
+ data: {
25023
+ delta0: tokenFlow.delta0,
25024
+ delta1: tokenFlow.delta1
25025
+ },
25026
+ gasEstimate: flowResult.gasEstimate,
25027
+ tokenFlow,
25028
+ _meta
25029
+ };
25030
+ } catch (error) {
25031
+ const _meta = await metaPromise;
25032
+ const errorMessage = error instanceof Error ? error.message : "Simulation failed";
25033
+ return {
25034
+ success: false,
25035
+ error: error instanceof PanopticError ? error : new PanopticError(errorMessage, error instanceof Error ? error : void 0),
25036
+ _meta
25037
+ };
25038
+ }
25039
+ }
25040
+
25041
+ //#endregion
25042
+ //#region src/panoptic/v2/simulations/simulateSettle.ts
25043
+ const BIT_MASK_128 = (1n << 128n) - 1n;
25044
+ const multicallAbi = [{
25045
+ type: "function",
25046
+ name: "multicall",
25047
+ inputs: [{
25048
+ name: "data",
25049
+ type: "bytes[]"
25050
+ }],
25051
+ outputs: [{
25052
+ name: "results",
25053
+ type: "bytes[]"
25054
+ }],
25055
+ stateMutability: "nonpayable"
25056
+ }];
25057
+ function encodeDispatch(plan) {
25058
+ const dispatch$1 = plan.dispatch;
25059
+ return encodeFunctionData({
25060
+ abi: panopticPoolV2Abi,
25061
+ functionName: "dispatch",
25062
+ args: [
25063
+ dispatch$1.positionIdList,
25064
+ dispatch$1.finalPositionIdList,
25065
+ dispatch$1.positionSizes,
25066
+ dispatch$1.tickAndSpreadLimits.map((limits) => [
25067
+ Number(limits[0]),
25068
+ Number(limits[1]),
25069
+ Number(limits[2])
25070
+ ]),
25071
+ dispatch$1.usePremiaAsCollateral,
25072
+ dispatch$1.builderCode
25073
+ ]
25074
+ });
25075
+ }
25076
+ function decodeShortPremium(data) {
25077
+ const packed = decodeFunctionResult({
25078
+ abi: panopticPoolV2Abi,
25079
+ functionName: "getFullPositionsData",
25080
+ data
25081
+ })[0];
25082
+ return [packed & BIT_MASK_128, packed >> 128n];
25083
+ }
25084
+ async function remainingForfeitAfterProtection(params) {
25085
+ const { client, poolAddress, account, positionIdList, targets, plan, blockNumber, initial } = params;
25086
+ if (targets.length === 0 && plan.collectionDispatch === void 0) return [...initial];
25087
+ const protectionCalls = buildSettleSequenceCalls({
25088
+ positionIdListFrom: params.finalPositionIdList,
25089
+ targets,
25090
+ dispatch: plan.collectionDispatch
25091
+ });
25092
+ const availableCall = encodeFunctionData({
25093
+ abi: panopticPoolV2Abi,
25094
+ functionName: "getFullPositionsData",
25095
+ args: [
25096
+ account,
25097
+ false,
25098
+ positionIdList
25099
+ ]
25100
+ });
25101
+ const totalCall = encodeFunctionData({
25102
+ abi: panopticPoolV2Abi,
25103
+ functionName: "getFullPositionsData",
25104
+ args: [
25105
+ account,
25106
+ true,
25107
+ positionIdList
25108
+ ]
25109
+ });
25110
+ const { result } = await client.simulateContract({
25111
+ address: poolAddress,
25112
+ abi: multicallAbi,
25113
+ functionName: "multicall",
25114
+ args: [[
25115
+ ...protectionCalls,
25116
+ availableCall,
25117
+ totalCall
25118
+ ]],
25119
+ account,
25120
+ blockNumber
25121
+ });
25122
+ const available = decodeShortPremium(result[result.length - 2]);
25123
+ const total = decodeShortPremium(result[result.length - 1]);
25124
+ return [total[0] > available[0] ? total[0] - available[0] : 0n, total[1] > available[1] ? total[1] - available[1] : 0n];
25125
+ }
25126
+ async function simulateSettle(params) {
25127
+ const { client, poolAddress, account, positionIdList, finalPositionIdList = positionIdList, positionSizes: providedSizes, targets = [], usePremiaAsCollateral = false, builderCode = 0n, allowForfeit = false, blockNumber } = params;
25128
+ const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
25129
+ const metaPromise = getBlockMeta({
25130
+ client,
25131
+ blockNumber: targetBlockNumber
25132
+ });
25133
+ try {
25134
+ if (providedSizes && providedSizes.length !== positionIdList.length) throw new PanopticError("simulateSettle: positionSizes length must match positionIdList");
25135
+ const positionSizes = providedSizes ?? await getCurrentPositionSizes({
25136
+ client,
25137
+ poolAddress,
25138
+ account,
25139
+ positionIdList,
25140
+ blockNumber: targetBlockNumber
25141
+ });
25142
+ const plan = buildProtectedSettlePlan({
25143
+ positionIdList,
25144
+ finalPositionIdList,
25145
+ positionSizes,
25146
+ usePremiaAsCollateral,
25147
+ builderCode
25148
+ });
25149
+ const initialForfeit = await getForfeitablePremium({
25150
+ client,
25151
+ poolAddress,
25152
+ account,
25153
+ tokenIds: positionIdList,
25154
+ blockNumber: targetBlockNumber
25155
+ });
25156
+ const initial = [initialForfeit.forfeit0, initialForfeit.forfeit1];
25157
+ if (targets.length > 0) {
25158
+ const buyers = await simulateSettlePremiumBatch({
25159
+ client,
25160
+ poolAddress,
25161
+ account,
25162
+ positionIdListFrom: finalPositionIdList,
25163
+ targets,
25164
+ blockNumber: targetBlockNumber
25165
+ });
25166
+ if (buyers.unsettleableCount > 0) throw new UnsafePremiumSettlementError(initial, buyers.unsettleableCount);
25167
+ }
25168
+ const remainingForfeit = await remainingForfeitAfterProtection({
25169
+ client,
25170
+ poolAddress,
25171
+ account,
25172
+ positionIdList,
25173
+ finalPositionIdList,
25174
+ targets,
25175
+ plan,
25176
+ blockNumber: targetBlockNumber,
25177
+ initial
25178
+ });
25179
+ if ((remainingForfeit[0] > 0n || remainingForfeit[1] > 0n) && !allowForfeit) throw new UnsafePremiumSettlementError(remainingForfeit, 0);
25180
+ const callData = targets.length === 0 ? encodeDispatch(plan) : encodeFunctionData({
25181
+ abi: panopticPoolV2Abi,
25182
+ functionName: "multicall",
25183
+ args: [buildSettleSequenceCalls({
25184
+ positionIdListFrom: finalPositionIdList,
25185
+ targets,
25186
+ dispatch: plan.dispatch
25187
+ })]
25188
+ });
25189
+ const flowResult = await simulateWithTokenFlow({
25190
+ client,
25191
+ poolAddress,
25192
+ user: account,
25193
+ callData,
25194
+ blockNumber: targetBlockNumber
25195
+ });
25196
+ if (!flowResult.success || !flowResult.tokenFlow) throw flowResult.rawError ?? new PanopticError(flowResult.error || "Simulation failed");
25197
+ const tokenFlow = flowResult.tokenFlow;
25198
+ return {
25199
+ success: true,
25200
+ data: {
25201
+ premiaReceived0: tokenFlow.delta0,
25202
+ premiaReceived1: tokenFlow.delta1,
25203
+ postCollateral0: tokenFlow.balanceAfter0,
25204
+ postCollateral1: tokenFlow.balanceAfter1,
25205
+ premiumProtected: [initial[0] - remainingForfeit[0], initial[1] - remainingForfeit[1]],
25206
+ remainingForfeit,
25207
+ usesPoke: plan.pokingTokenIds.length > 0,
25208
+ settledBuyerCount: targets.length
25209
+ },
25210
+ gasEstimate: flowResult.gasEstimate,
25211
+ tokenFlow,
25212
+ _meta: await metaPromise
25213
+ };
25214
+ } catch (error) {
25215
+ return {
25216
+ success: false,
25217
+ error: error instanceof PanopticError ? error : new PanopticError(error instanceof Error ? error.message : "Simulation failed", error instanceof Error ? error : void 0),
25218
+ _meta: await metaPromise
25219
+ };
25220
+ }
25221
+ }
25222
+
25223
+ //#endregion
25224
+ //#region src/panoptic/v2/writes/settle.ts
25225
+ /**
25226
+ * Settle accumulated premia on existing positions.
25227
+ *
25228
+ * This function triggers premium collection without changing position size.
25229
+ * It calls dispatch with unchanged position lists.
25230
+ *
25231
+ * @param params - Settlement parameters
25232
+ * @returns TxResult
25233
+ *
25234
+ * @example
25235
+ * ```typescript
25236
+ * const result = await settleAccumulatedPremia({
25237
+ * client,
25238
+ * walletClient,
25239
+ * account,
25240
+ * poolAddress,
25241
+ * positionIdList: existingPositions,
25242
+ * })
25243
+ * const receipt = await result.wait()
25244
+ * ```
25245
+ */
25246
+ async function settleAccumulatedPremia(params) {
25247
+ const { client, walletClient, account, poolAddress, positionIdList, finalPositionIdList, positionSizes: providedSizes, targets = [], skipPreflight = false, allowForfeit = false, usePremiaAsCollateral = false, builderCode = 0n, txOverrides } = params;
25248
+ if (providedSizes && providedSizes.length !== positionIdList.length) throw new PanopticError("settleAccumulatedPremia: positionSizes length must match positionIdList");
25249
+ const positionSizes = providedSizes ?? await getCurrentPositionSizes({
25250
+ client,
25251
+ poolAddress,
25252
+ account,
25253
+ positionIdList
25254
+ });
25255
+ const heldPositions = finalPositionIdList ?? positionIdList;
25256
+ if (!skipPreflight) {
25257
+ const simulation = await simulateSettle({
25258
+ client,
25259
+ poolAddress,
25260
+ account,
25261
+ positionIdList,
25262
+ finalPositionIdList: heldPositions,
25263
+ positionSizes,
25264
+ targets,
25265
+ usePremiaAsCollateral,
25266
+ builderCode,
25267
+ allowForfeit
25268
+ });
25269
+ if (!simulation.success) throw simulation.error;
25270
+ }
25271
+ const { dispatch: dispatch$1 } = buildProtectedSettlePlan({
25272
+ positionIdList,
25273
+ finalPositionIdList: heldPositions,
25274
+ positionSizes,
25275
+ usePremiaAsCollateral,
25276
+ builderCode
25277
+ });
25278
+ if (targets.length > 0) return executeSettleSequence({
25279
+ client,
25280
+ walletClient,
25281
+ account,
25282
+ poolAddress,
25283
+ positionIdListFrom: heldPositions,
25284
+ targets,
25285
+ dispatch: dispatch$1,
25286
+ txOverrides
25287
+ });
25288
+ return submitWrite({
25289
+ client,
25290
+ walletClient,
25291
+ account,
25292
+ address: poolAddress,
25293
+ abi: panopticPoolV2Abi,
25294
+ functionName: "dispatch",
25295
+ args: [
25296
+ dispatch$1.positionIdList,
25297
+ dispatch$1.finalPositionIdList,
25298
+ dispatch$1.positionSizes,
25299
+ dispatch$1.tickAndSpreadLimits.map((t) => [
25300
+ Number(t[0]),
25301
+ Number(t[1]),
25302
+ Number(t[2])
25303
+ ]),
25304
+ dispatch$1.usePremiaAsCollateral,
25305
+ dispatch$1.builderCode
25306
+ ],
25307
+ txOverrides
25308
+ });
25309
+ }
25310
+ /**
25311
+ * Settle premia and wait for confirmation.
25312
+ */
25313
+ async function settleAccumulatedPremiaAndWait(params) {
25314
+ const result = await settleAccumulatedPremia(params);
25315
+ return result.wait();
25316
+ }
25317
+
25318
+ //#endregion
25319
+ //#region src/panoptic/v2/writes/pokeOracle.ts
25320
+ /**
25321
+ * Poke the oracle to update its state.
25322
+ *
25323
+ * This function can be called to advance the oracle epoch.
25324
+ * Note: The oracle can only be poked once per epoch (64 seconds).
25325
+ *
25326
+ * @param params - Poke oracle parameters
25327
+ * @returns TxResult
25328
+ * @throws OracleRateLimitedError if checkRateLimit is true and oracle was recently poked
25329
+ *
25330
+ * @example
25331
+ * ```typescript
25332
+ * const result = await pokeOracle({
25333
+ * client,
25334
+ * walletClient,
25335
+ * account,
25336
+ * poolAddress,
25337
+ * })
25338
+ * const receipt = await result.wait()
25339
+ * ```
25340
+ */
25341
+ async function pokeOracle(params) {
25342
+ const { client, walletClient, account, poolAddress, checkRateLimit = false, txOverrides } = params;
25343
+ if (checkRateLimit) {
25344
+ const [oracleData, block] = await Promise.all([client.readContract({
25345
+ address: poolAddress,
25346
+ abi: panopticPoolV2Abi,
25347
+ functionName: "getOracleTicks"
25348
+ }), client.getBlock()]);
25349
+ const oraclePack = oracleData[4];
25350
+ const { epoch } = decodeOracleTiming(oraclePack, block.timestamp);
25351
+ const currentEpoch = oracleEpochAt(block.timestamp);
25352
+ if (currentEpoch === epoch) {
25353
+ const lastUpdate = epoch << 6n;
25354
+ throw new OracleRateLimitedError(lastUpdate, block.timestamp);
25355
+ }
25356
+ }
25357
+ return submitWrite({
25358
+ client,
25359
+ walletClient,
25360
+ account,
25361
+ address: poolAddress,
25362
+ abi: panopticPoolV2Abi,
25363
+ functionName: "pokeOracle",
25364
+ args: [],
25365
+ txOverrides
25366
+ });
25367
+ }
25368
+ /**
25369
+ * Poke oracle and wait for confirmation.
25370
+ */
25371
+ async function pokeOracleAndWait(params) {
25372
+ const result = await pokeOracle(params);
25373
+ return result.wait();
25374
+ }
25375
+
25376
+ //#endregion
25377
+ //#region src/panoptic/v2/writes/factory.ts
25378
+ /**
25379
+ * Deploy a new Panoptic pool via the factory.
25380
+ *
25381
+ * @param params - Deployment parameters (versioned: 'v3' or 'v4')
25382
+ * @returns Transaction result with hash and wait function
25383
+ */
25384
+ async function deployNewPool(params) {
25385
+ const { client, walletClient, account, factoryAddress, riskEngine, salt, txOverrides } = params;
25386
+ if (params.version === "v3") return submitWrite({
25387
+ client,
25388
+ walletClient,
25389
+ account,
25390
+ address: factoryAddress,
25391
+ abi: panopticFactoryV3Abi,
25392
+ functionName: "deployNewPool",
25393
+ args: [
25394
+ params.token0,
25395
+ params.token1,
25396
+ params.fee,
25397
+ riskEngine,
25398
+ salt
25399
+ ],
25400
+ txOverrides
25401
+ });
25402
+ return submitWrite({
25403
+ client,
25404
+ walletClient,
25405
+ account,
25406
+ address: factoryAddress,
25407
+ abi: panopticFactoryV4Abi,
25408
+ functionName: "deployNewPool",
25409
+ args: [
25410
+ {
25411
+ currency0: params.poolKey.currency0,
25412
+ currency1: params.poolKey.currency1,
25413
+ fee: Number(params.poolKey.fee),
25414
+ tickSpacing: Number(params.poolKey.tickSpacing),
25415
+ hooks: params.poolKey.hooks
25416
+ },
25417
+ riskEngine,
25418
+ salt
25419
+ ],
25420
+ txOverrides
25421
+ });
25422
+ }
25423
+ /**
25424
+ * Deploy a new Panoptic pool and wait for confirmation.
25425
+ */
25426
+ async function deployNewPoolAndWait(params) {
25427
+ const result = await deployNewPool(params);
25428
+ return result.wait();
25429
+ }
25430
+
25431
+ //#endregion
25432
+ //#region src/panoptic/v2/writes/txManagement.ts
25433
+ /** Default gas price multiplier for replacement (12.5% bump = minimum for replacement) */
25434
+ const DEFAULT_GAS_PRICE_MULTIPLIER = 1.125;
25435
+ /**
25436
+ * Apply a multiplier to a bigint gas value.
25437
+ * Uses integer arithmetic to avoid floating point issues.
25438
+ */
25439
+ function applyMultiplier(value, multiplier) {
25440
+ const bps = BigInt(Math.ceil(multiplier * 1e4));
25441
+ return value * bps / 10000n;
25442
+ }
25443
+ /**
25444
+ * Compute bumped gas parameters from the original transaction.
25445
+ */
25446
+ function computeBumpedGas(originalMaxFeePerGas, originalMaxPriorityFeePerGas, explicitMaxFeePerGas, explicitMaxPriorityFeePerGas, multiplier) {
25447
+ const maxFeePerGas = explicitMaxFeePerGas ?? applyMultiplier(originalMaxFeePerGas ?? 0n, multiplier);
25448
+ const maxPriorityFeePerGas = explicitMaxPriorityFeePerGas ?? applyMultiplier(originalMaxPriorityFeePerGas ?? 0n, multiplier);
25449
+ return {
25450
+ maxFeePerGas,
25451
+ maxPriorityFeePerGas
25452
+ };
25453
+ }
25454
+ /**
25455
+ * Speed up a pending transaction by resubmitting with higher gas.
25456
+ *
25457
+ * Fetches the original transaction, extracts its parameters,
25458
+ * bumps the gas price, and resubmits with the same nonce.
25459
+ *
24797
25460
  * @param params - Speed up parameters
24798
25461
  * @returns TxResult for the replacement transaction
24799
25462
  * @throws Error if the original transaction is not found
@@ -25783,469 +26446,145 @@ async function smartRepay(params) {
25783
26446
  client,
25784
26447
  walletClient,
25785
26448
  account,
25786
- address: poolAddress,
25787
- abi: panopticPoolV2Abi,
25788
- functionName: "dispatch",
25789
- args: [
25790
- opsPositionIds,
25791
- finalPositionIdList,
25792
- opsSizes,
25793
- opsLimits,
25794
- false,
25795
- builderCode
25796
- ],
25797
- txOverrides
25798
- });
25799
- } catch (error) {
25800
- if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) continue;
25801
- throw error;
25802
- }
25803
- }
25804
- throw new MaxRetriesExceededError("smartRepay");
25805
- }
25806
- /**
25807
- * Smart repay and wait for confirmation.
25808
- */
25809
- async function smartRepayAndWait(params) {
25810
- const result = await smartRepay(params);
25811
- const receipt = await result.wait();
25812
- if (params.storage && params.chainId !== void 0) {
25813
- const { client, account, poolAddress, chainId, token, amount, storage, existingPositionIds } = params;
25814
- const pool = await getPool({
25815
- client,
25816
- poolAddress,
25817
- chainId
25818
- });
25819
- const tokenIndex = resolveTokenIndex(token, pool.collateralTracker0.token, pool.collateralTracker1.token);
25820
- const loans = await getLoanPositionsForToken(client, poolAddress, account, existingPositionIds, tokenIndex);
25821
- const loanIds = loans.map((l) => l.tokenId);
25822
- const totalDebt = loans.reduce((sum, l) => sum + l.tokenAmount, 0n);
25823
- const remainder = totalDebt > amount ? totalDebt - amount : 0n;
25824
- const positionIds = existingPositionIds ?? await getTrackedPositionIds({
25825
- chainId,
25826
- poolAddress,
25827
- account,
25828
- storage
25829
- });
25830
- let updatedIds = positionIds.filter((id) => !loanIds.includes(id));
25831
- if (remainder > 0n) {
25832
- const nonLoanIds = existingPositionIds.filter((id) => !loanIds.includes(id));
25833
- const newLoan = buildUniqueLoan(pool.poolId, tokenIndex, tokenIndex, pool.currentTick, pool.tickSpacing, nonLoanIds, remainder);
25834
- updatedIds = [...updatedIds, newLoan.tokenId];
25835
- }
25836
- await savePositionIds(storage, chainId, poolAddress, account, updatedIds);
25837
- }
25838
- return receipt;
25839
- }
25840
-
25841
- //#endregion
25842
- //#region src/panoptic/v2/simulations/simulateBatchDispatch.ts
25843
- /**
25844
- * Simulate a batch dispatch built from `items` + the current on-chain
25845
- * positionIdList. Returns batch diagnostics OR a real simulation result.
25846
- */
25847
- async function simulateBatchDispatch(params) {
25848
- const { client, poolAddress, account, items, existingPositionIds, usePremiaAsCollateral = false, builderCode = 0n, blockNumber } = params;
25849
- const { args, diagnostics } = buildBatchDispatchArgs({
25850
- items,
25851
- existingPositionIds,
25852
- usePremiaAsCollateral,
25853
- builderCode
25854
- });
25855
- if (args === null) {
25856
- const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
25857
- const meta = await getBlockMeta({
25858
- client,
25859
- blockNumber: targetBlockNumber
25860
- });
25861
- return {
25862
- success: false,
25863
- diagnostics,
25864
- _meta: meta
25865
- };
25866
- }
25867
- const sim = await simulateDispatch({
25868
- client,
25869
- poolAddress,
25870
- account,
25871
- positionIdList: args.positionIdList,
25872
- finalPositionIdList: args.finalPositionIdList,
25873
- existingPositionIdList: existingPositionIds,
25874
- positionSizes: args.positionSizes,
25875
- tickAndSpreadLimits: args.tickAndSpreadLimits,
25876
- usePremiaAsCollateral: args.usePremiaAsCollateral,
25877
- builderCode: args.builderCode,
25878
- blockNumber
25879
- });
25880
- return {
25881
- ...sim,
25882
- diagnostics: []
25883
- };
25884
- }
25885
-
25886
- //#endregion
25887
- //#region src/panoptic/v2/simulations/simulateClosePosition.ts
25888
- /**
25889
- * Simulate closing a position.
25890
- *
25891
- * Uses PanopticPool.multicall with getAssetsOf-dispatch-getAssetsOf pattern
25892
- * to measure exact collateral asset movements from the burn.
25893
- *
25894
- * @param params - Simulation parameters
25895
- * @returns Simulation result with close data or error
25896
- */
25897
- async function simulateClosePosition(params) {
25898
- const { client, poolAddress, account, positionIdList, tokenId, tickLimitLow, tickLimitHigh, spreadLimit = 0n, swapAtMint = false, usePremiaAsCollateral = false, builderCode = 0n, blockNumber } = params;
25899
- const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
25900
- const metaPromise = getBlockMeta({
25901
- client,
25902
- blockNumber: targetBlockNumber
25903
- });
25904
- const tickLimits$1 = swapAtMint ? [
25905
- Number(tickLimitHigh),
25906
- Number(tickLimitLow),
25907
- Number(spreadLimit)
25908
- ] : [
25909
- Number(tickLimitLow),
25910
- Number(tickLimitHigh),
25911
- Number(spreadLimit)
25912
- ];
25913
- try {
25914
- const finalPositionIdList = positionIdList.filter((id) => id !== tokenId);
25915
- const callData = encodeFunctionData({
25916
- abi: panopticPoolV2Abi,
25917
- functionName: "dispatch",
25918
- args: [
25919
- [tokenId],
25920
- finalPositionIdList,
25921
- [0n],
25922
- [tickLimits$1],
25923
- usePremiaAsCollateral,
25924
- builderCode
25925
- ]
25926
- });
25927
- const flowResult = await simulateWithTokenFlow({
25928
- client,
25929
- poolAddress,
25930
- user: account,
25931
- callData,
25932
- blockNumber: targetBlockNumber
25933
- });
25934
- if (!flowResult.success || !flowResult.tokenFlow) throw flowResult.rawError ?? new PanopticError(flowResult.error || "Token flow simulation failed");
25935
- const tokenFlow = flowResult.tokenFlow;
25936
- const _meta = await metaPromise;
25937
- const data = {
25938
- amount0Received: tokenFlow.delta0,
25939
- amount1Received: tokenFlow.delta1,
25940
- premiaCollected0: null,
25941
- premiaCollected1: null,
25942
- postCollateral0: tokenFlow.balanceAfter0,
25943
- postCollateral1: tokenFlow.balanceAfter1,
25944
- realizedPnL0: null,
25945
- realizedPnL1: null
25946
- };
25947
- return {
25948
- success: true,
25949
- data,
25950
- gasEstimate: flowResult.gasEstimate,
25951
- tokenFlow,
25952
- _meta
25953
- };
25954
- } catch (error) {
25955
- const _meta = await metaPromise;
25956
- return {
25957
- success: false,
25958
- error: error instanceof PanopticError ? error : new PanopticError(error instanceof Error ? error.message : "Simulation failed", error instanceof Error ? error : void 0),
25959
- _meta
25960
- };
26449
+ address: poolAddress,
26450
+ abi: panopticPoolV2Abi,
26451
+ functionName: "dispatch",
26452
+ args: [
26453
+ opsPositionIds,
26454
+ finalPositionIdList,
26455
+ opsSizes,
26456
+ opsLimits,
26457
+ false,
26458
+ builderCode
26459
+ ],
26460
+ txOverrides
26461
+ });
26462
+ } catch (error) {
26463
+ if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) continue;
26464
+ throw error;
26465
+ }
25961
26466
  }
26467
+ throw new MaxRetriesExceededError("smartRepay");
25962
26468
  }
25963
-
25964
- //#endregion
25965
- //#region src/panoptic/v2/simulations/simulateForceExercise.ts
25966
26469
  /**
25967
- * Simulate a force exercise operation.
25968
- *
25969
- * @param params - Simulation parameters
25970
- * @returns Simulation result with exercise data or error
26470
+ * Smart repay and wait for confirmation.
25971
26471
  */
25972
- async function simulateForceExercise(params) {
25973
- const { client, poolAddress, account, user, positionIdListFrom, positionIdListTo, positionIdListToFinal, blockNumber } = params;
25974
- const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
25975
- const metaPromise = getBlockMeta({
25976
- client,
25977
- blockNumber: targetBlockNumber
25978
- });
25979
- const emptyTokenFlow = {
25980
- delta0: 0n,
25981
- delta1: 0n,
25982
- balanceBefore0: 0n,
25983
- balanceBefore1: 0n,
25984
- balanceAfter0: 0n,
25985
- balanceAfter1: 0n,
25986
- tickBefore: null,
25987
- tickAfter: null
25988
- };
25989
- try {
25990
- const callData = encodeFunctionData({
25991
- abi: panopticPoolV2Abi,
25992
- functionName: "dispatchFrom",
25993
- args: [
25994
- positionIdListFrom,
25995
- user,
25996
- positionIdListTo,
25997
- positionIdListToFinal,
25998
- 0n
25999
- ]
26000
- });
26001
- const flowResult = await simulateWithTokenFlow({
26472
+ async function smartRepayAndWait(params) {
26473
+ const result = await smartRepay(params);
26474
+ const receipt = await result.wait();
26475
+ if (params.storage && params.chainId !== void 0) {
26476
+ const { client, account, poolAddress, chainId, token, amount, storage, existingPositionIds } = params;
26477
+ const pool = await getPool({
26002
26478
  client,
26003
26479
  poolAddress,
26004
- user: account,
26005
- callData,
26006
- blockNumber: targetBlockNumber
26480
+ chainId
26007
26481
  });
26008
- if (!flowResult.success || !flowResult.tokenFlow) {
26009
- const errorMessage = flowResult.error || "Simulation failed";
26010
- const isNotExercisable = errorMessage.includes("NoLegsExercisable") || errorMessage.includes("NotALongLeg");
26011
- if (isNotExercisable) {
26012
- const _meta$1 = await metaPromise;
26013
- const data$1 = {
26014
- exerciseFee0: 0n,
26015
- exerciseFee1: 0n,
26016
- canExercise: false,
26017
- reason: errorMessage.includes("NoLegsExercisable") ? "No legs are exercisable (not ITM)" : "Position does not have a long leg"
26018
- };
26019
- return {
26020
- success: true,
26021
- data: data$1,
26022
- gasEstimate: 0n,
26023
- tokenFlow: emptyTokenFlow,
26024
- _meta: _meta$1
26025
- };
26026
- }
26027
- throw new PanopticError(errorMessage);
26028
- }
26029
- const _meta = await metaPromise;
26030
- const tokenFlow = flowResult.tokenFlow;
26031
- const data = {
26032
- exerciseFee0: tokenFlow.delta0,
26033
- exerciseFee1: tokenFlow.delta1,
26034
- canExercise: true
26035
- };
26036
- return {
26037
- success: true,
26038
- data,
26039
- gasEstimate: flowResult.gasEstimate,
26040
- tokenFlow,
26041
- _meta
26042
- };
26043
- } catch (error) {
26044
- const _meta = await metaPromise;
26045
- const errorMessage = error instanceof Error ? error.message : "Simulation failed";
26046
- const isNotExercisable = errorMessage.includes("NoLegsExercisable") || errorMessage.includes("NotALongLeg");
26047
- if (isNotExercisable) {
26048
- const data = {
26049
- exerciseFee0: 0n,
26050
- exerciseFee1: 0n,
26051
- canExercise: false,
26052
- reason: errorMessage.includes("NoLegsExercisable") ? "No legs are exercisable (not ITM)" : "Position does not have a long leg"
26053
- };
26054
- return {
26055
- success: true,
26056
- data,
26057
- gasEstimate: 0n,
26058
- tokenFlow: emptyTokenFlow,
26059
- _meta
26060
- };
26482
+ const tokenIndex = resolveTokenIndex(token, pool.collateralTracker0.token, pool.collateralTracker1.token);
26483
+ const loans = await getLoanPositionsForToken(client, poolAddress, account, existingPositionIds, tokenIndex);
26484
+ const loanIds = loans.map((l) => l.tokenId);
26485
+ const totalDebt = loans.reduce((sum, l) => sum + l.tokenAmount, 0n);
26486
+ const remainder = totalDebt > amount ? totalDebt - amount : 0n;
26487
+ const positionIds = existingPositionIds ?? await getTrackedPositionIds({
26488
+ chainId,
26489
+ poolAddress,
26490
+ account,
26491
+ storage
26492
+ });
26493
+ let updatedIds = positionIds.filter((id) => !loanIds.includes(id));
26494
+ if (remainder > 0n) {
26495
+ const nonLoanIds = existingPositionIds.filter((id) => !loanIds.includes(id));
26496
+ const newLoan = buildUniqueLoan(pool.poolId, tokenIndex, tokenIndex, pool.currentTick, pool.tickSpacing, nonLoanIds, remainder);
26497
+ updatedIds = [...updatedIds, newLoan.tokenId];
26061
26498
  }
26062
- return {
26063
- success: false,
26064
- error: error instanceof PanopticError ? error : new PanopticError(errorMessage, error instanceof Error ? error : void 0),
26065
- _meta
26066
- };
26499
+ await savePositionIds(storage, chainId, poolAddress, account, updatedIds);
26067
26500
  }
26501
+ return receipt;
26068
26502
  }
26069
26503
 
26070
26504
  //#endregion
26071
- //#region src/panoptic/v2/simulations/simulateLiquidate.ts
26505
+ //#region src/panoptic/v2/simulations/simulateBatchDispatch.ts
26072
26506
  /**
26073
- * Simulate a liquidation operation.
26074
- *
26075
- * @param params - Simulation parameters
26076
- * @returns Simulation result with liquidation data or error
26507
+ * Simulate a batch dispatch built from `items` + the current on-chain
26508
+ * positionIdList. Returns batch diagnostics OR a real simulation result.
26077
26509
  */
26078
- async function simulateLiquidate(params) {
26079
- const { client, poolAddress, account, liquidatee, positionIdListFrom, positionIdListTo, positionIdListToFinal, blockNumber } = params;
26080
- const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
26081
- const metaPromise = getBlockMeta({
26082
- client,
26083
- blockNumber: targetBlockNumber
26510
+ async function simulateBatchDispatch(params) {
26511
+ const { client, poolAddress, account, items, existingPositionIds, usePremiaAsCollateral = false, builderCode = 0n, blockNumber } = params;
26512
+ const { args, diagnostics } = buildBatchDispatchArgs({
26513
+ items,
26514
+ existingPositionIds,
26515
+ usePremiaAsCollateral,
26516
+ builderCode
26084
26517
  });
26085
- const emptyTokenFlow = {
26086
- delta0: 0n,
26087
- delta1: 0n,
26088
- balanceBefore0: 0n,
26089
- balanceBefore1: 0n,
26090
- balanceAfter0: 0n,
26091
- balanceAfter1: 0n,
26092
- tickBefore: null,
26093
- tickAfter: null
26094
- };
26095
- try {
26096
- const callData = encodeFunctionData({
26097
- abi: panopticPoolV2Abi,
26098
- functionName: "dispatchFrom",
26099
- args: [
26100
- positionIdListFrom,
26101
- liquidatee,
26102
- positionIdListTo,
26103
- positionIdListToFinal,
26104
- 0n
26105
- ]
26106
- });
26107
- const flowResult = await simulateWithTokenFlow({
26108
- client,
26109
- poolAddress,
26110
- user: account,
26111
- callData,
26112
- blockNumber: targetBlockNumber
26113
- });
26114
- if (!flowResult.success || !flowResult.tokenFlow) {
26115
- const errorMessage = flowResult.error || "Simulation failed";
26116
- const isNotLiquidatable = errorMessage.includes("NotMarginCalled") || errorMessage.includes("AccountInsolvent");
26117
- if (isNotLiquidatable) {
26118
- const _meta$1 = await metaPromise;
26119
- const data$1 = {
26120
- bonus0: 0n,
26121
- bonus1: 0n,
26122
- positionsClosed: [],
26123
- isLiquidatable: false,
26124
- shortfall0: 0n,
26125
- shortfall1: 0n
26126
- };
26127
- return {
26128
- success: true,
26129
- data: data$1,
26130
- gasEstimate: 0n,
26131
- tokenFlow: emptyTokenFlow,
26132
- _meta: _meta$1
26133
- };
26134
- }
26135
- throw new PanopticError(errorMessage);
26136
- }
26137
- const _meta = await metaPromise;
26138
- const tokenFlow = flowResult.tokenFlow;
26139
- const positionsClosed = positionIdListTo.filter((id) => !positionIdListToFinal.includes(id));
26140
- const data = {
26141
- bonus0: tokenFlow.delta0 > 0n ? tokenFlow.delta0 : 0n,
26142
- bonus1: tokenFlow.delta1 > 0n ? tokenFlow.delta1 : 0n,
26143
- positionsClosed,
26144
- isLiquidatable: true,
26145
- shortfall0: 0n,
26146
- shortfall1: 0n
26147
- };
26148
- return {
26149
- success: true,
26150
- data,
26151
- gasEstimate: flowResult.gasEstimate,
26152
- tokenFlow,
26153
- _meta
26154
- };
26155
- } catch (error) {
26156
- const _meta = await metaPromise;
26157
- const errorMessage = error instanceof Error ? error.message : "Simulation failed";
26158
- const isNotLiquidatable = errorMessage.includes("NotMarginCalled") || errorMessage.includes("AccountInsolvent");
26159
- if (isNotLiquidatable) {
26160
- const data = {
26161
- bonus0: 0n,
26162
- bonus1: 0n,
26163
- positionsClosed: [],
26164
- isLiquidatable: false,
26165
- shortfall0: 0n,
26166
- shortfall1: 0n
26167
- };
26168
- return {
26169
- success: true,
26170
- data,
26171
- gasEstimate: 0n,
26172
- tokenFlow: emptyTokenFlow,
26173
- _meta
26174
- };
26175
- }
26518
+ if (args === null) {
26519
+ const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
26520
+ const meta = await getBlockMeta({
26521
+ client,
26522
+ blockNumber: targetBlockNumber
26523
+ });
26176
26524
  return {
26177
26525
  success: false,
26178
- error: error instanceof PanopticError ? error : new PanopticError(errorMessage, error instanceof Error ? error : void 0),
26179
- _meta
26526
+ diagnostics,
26527
+ _meta: meta
26180
26528
  };
26181
26529
  }
26530
+ const sim = await simulateDispatch({
26531
+ client,
26532
+ poolAddress,
26533
+ account,
26534
+ positionIdList: args.positionIdList,
26535
+ finalPositionIdList: args.finalPositionIdList,
26536
+ existingPositionIdList: existingPositionIds,
26537
+ positionSizes: args.positionSizes,
26538
+ tickAndSpreadLimits: args.tickAndSpreadLimits,
26539
+ usePremiaAsCollateral: args.usePremiaAsCollateral,
26540
+ builderCode: args.builderCode,
26541
+ blockNumber
26542
+ });
26543
+ return {
26544
+ ...sim,
26545
+ diagnostics: []
26546
+ };
26182
26547
  }
26183
26548
 
26184
26549
  //#endregion
26185
- //#region src/panoptic/v2/simulations/simulateSettle.ts
26186
- /** BIT_MASK_128 = (1n << 128n) - 1n */
26187
- const BIT_MASK_128 = (1n << 128n) - 1n;
26188
- /**
26189
- * PanopticPool multicall ABI (inherited from Uniswap).
26190
- */
26191
- const multicallAbi = [{
26192
- type: "function",
26193
- name: "multicall",
26194
- inputs: [{
26195
- name: "data",
26196
- type: "bytes[]"
26197
- }],
26198
- outputs: [{
26199
- name: "results",
26200
- type: "bytes[]"
26201
- }],
26202
- stateMutability: "nonpayable"
26203
- }];
26550
+ //#region src/panoptic/v2/simulations/simulateClosePosition.ts
26204
26551
  /**
26205
- * Simulate premium settlement.
26552
+ * Simulate closing a position.
26206
26553
  *
26207
- * When `tokenId` is provided, the simulation also computes forfeit amounts
26208
- * by chaining the dispatch with `getFullPositionsData` reads
26209
- * in a single multicall.
26554
+ * Uses PanopticPool.multicall with getAssetsOf-dispatch-getAssetsOf pattern
26555
+ * to measure exact collateral asset movements from the burn.
26210
26556
  *
26211
26557
  * @param params - Simulation parameters
26212
- * @returns Simulation result with settlement data or error
26558
+ * @returns Simulation result with close data or error
26213
26559
  */
26214
- async function simulateSettle(params) {
26215
- const { client, poolAddress, account, positionIdList, finalPositionIdList, positionSizes: providedSizes, tokenId, blockNumber } = params;
26560
+ async function simulateClosePosition(params) {
26561
+ const { client, poolAddress, account, positionIdList, tokenId, tickLimitLow, tickLimitHigh, spreadLimit = 0n, swapAtMint = false, usePremiaAsCollateral = false, builderCode = 0n, blockNumber } = params;
26216
26562
  const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
26217
26563
  const metaPromise = getBlockMeta({
26218
26564
  client,
26219
26565
  blockNumber: targetBlockNumber
26220
26566
  });
26567
+ const tickLimits$1 = swapAtMint ? [
26568
+ Number(tickLimitHigh),
26569
+ Number(tickLimitLow),
26570
+ Number(spreadLimit)
26571
+ ] : [
26572
+ Number(tickLimitLow),
26573
+ Number(tickLimitHigh),
26574
+ Number(spreadLimit)
26575
+ ];
26221
26576
  try {
26222
- if (providedSizes && providedSizes.length !== positionIdList.length) throw new PanopticError("simulateSettle: positionSizes length must match positionIdList");
26223
- const positionSizes = providedSizes ?? await getCurrentPositionSizes({
26224
- client,
26225
- poolAddress,
26226
- account,
26227
- positionIdList,
26228
- blockNumber: targetBlockNumber
26229
- });
26230
- const tickAndSpreadLimits = positionIdList.map(() => [
26231
- -887272n,
26232
- 887272n,
26233
- 0n
26234
- ]);
26577
+ const finalPositionIdList = positionIdList.filter((id) => id !== tokenId);
26235
26578
  const callData = encodeFunctionData({
26236
26579
  abi: panopticPoolV2Abi,
26237
26580
  functionName: "dispatch",
26238
26581
  args: [
26239
- positionIdList,
26240
- finalPositionIdList ?? positionIdList,
26241
- positionSizes.map((s) => BigInt(s)),
26242
- tickAndSpreadLimits.map((t) => [
26243
- Number(t[0]),
26244
- Number(t[1]),
26245
- Number(t[2])
26246
- ]),
26247
- false,
26248
- 0n
26582
+ [tokenId],
26583
+ finalPositionIdList,
26584
+ [0n],
26585
+ [tickLimits$1],
26586
+ usePremiaAsCollateral,
26587
+ builderCode
26249
26588
  ]
26250
26589
  });
26251
26590
  const flowResult = await simulateWithTokenFlow({
@@ -26257,23 +26596,16 @@ async function simulateSettle(params) {
26257
26596
  });
26258
26597
  if (!flowResult.success || !flowResult.tokenFlow) throw flowResult.rawError ?? new PanopticError(flowResult.error || "Token flow simulation failed");
26259
26598
  const tokenFlow = flowResult.tokenFlow;
26260
- let forfeitAmounts;
26261
- if (tokenId !== void 0) forfeitAmounts = await computeForfeitAmounts({
26262
- client,
26263
- poolAddress,
26264
- account,
26265
- positionIdList,
26266
- tokenId,
26267
- dispatchCallData: callData,
26268
- blockNumber: targetBlockNumber
26269
- });
26270
26599
  const _meta = await metaPromise;
26271
26600
  const data = {
26272
- premiaReceived0: tokenFlow.delta0,
26273
- premiaReceived1: tokenFlow.delta1,
26601
+ amount0Received: tokenFlow.delta0,
26602
+ amount1Received: tokenFlow.delta1,
26603
+ premiaCollected0: null,
26604
+ premiaCollected1: null,
26274
26605
  postCollateral0: tokenFlow.balanceAfter0,
26275
26606
  postCollateral1: tokenFlow.balanceAfter1,
26276
- forfeitAmounts
26607
+ realizedPnL0: null,
26608
+ realizedPnL1: null
26277
26609
  };
26278
26610
  return {
26279
26611
  success: true,
@@ -26291,95 +26623,17 @@ async function simulateSettle(params) {
26291
26623
  };
26292
26624
  }
26293
26625
  }
26294
- /**
26295
- * Compute forfeit amounts by chaining dispatch + getFullPositionsData
26296
- * in a single PanopticPool.multicall.
26297
- */
26298
- async function computeForfeitAmounts(params) {
26299
- const { client, poolAddress, account, tokenId, dispatchCallData, blockNumber } = params;
26300
- const feesCallAvailable = encodeFunctionData({
26301
- abi: panopticPoolV2Abi,
26302
- functionName: "getFullPositionsData",
26303
- args: [
26304
- account,
26305
- false,
26306
- [tokenId]
26307
- ]
26308
- });
26309
- const feesCallTotal = encodeFunctionData({
26310
- abi: panopticPoolV2Abi,
26311
- functionName: "getFullPositionsData",
26312
- args: [
26313
- account,
26314
- true,
26315
- [tokenId]
26316
- ]
26317
- });
26318
- try {
26319
- const { result } = await client.simulateContract({
26320
- address: poolAddress,
26321
- abi: multicallAbi,
26322
- functionName: "multicall",
26323
- args: [[
26324
- dispatchCallData,
26325
- feesCallAvailable,
26326
- feesCallTotal
26327
- ]],
26328
- account,
26329
- blockNumber
26330
- });
26331
- const decodeFeesResult = (data) => {
26332
- return decodeFunctionResult({
26333
- abi: panopticPoolV2Abi,
26334
- functionName: "getFullPositionsData",
26335
- data
26336
- })[0];
26337
- };
26338
- const availablePremium = decodeFeesResult(result[1]);
26339
- const totalPremium = decodeFeesResult(result[2]);
26340
- const available0 = availablePremium & BIT_MASK_128;
26341
- const available1 = availablePremium >> 128n;
26342
- const total0 = totalPremium & BIT_MASK_128;
26343
- const total1 = totalPremium >> 128n;
26344
- return [total0 - available0, total1 - available1];
26345
- } catch (error) {
26346
- throw new PanopticError("Forfeit amount computation failed", error instanceof Error ? error : void 0);
26347
- }
26348
- }
26349
26626
 
26350
26627
  //#endregion
26351
- //#region src/panoptic/v2/simulations/simulateSettlePremiumFrom.ts
26352
- /** Soft-failure revert markers for settle premium (target-state issues, not caller errors). */
26353
- const SOFT_FAILURES = [
26354
- {
26355
- marker: "AccountInsolvent",
26356
- reason: "Target account is insolvent; premium cannot be settled"
26357
- },
26358
- {
26359
- marker: "PositionNotOwned",
26360
- reason: "Target account no longer owns the position"
26361
- },
26362
- {
26363
- marker: "StaleOracle",
26364
- reason: "Oracle price is stale; settlement temporarily unavailable"
26365
- },
26366
- {
26367
- marker: "InputListFail",
26368
- reason: "Position list is stale (target positions changed)"
26369
- }
26370
- ];
26628
+ //#region src/panoptic/v2/simulations/simulateForceExercise.ts
26371
26629
  /**
26372
- * Simulate settling another account's accumulated long premium via `dispatchFrom`
26373
- * (equal-length `positionIdListTo`/`positionIdListToFinal` selects the settle mode).
26374
- *
26375
- * The measured token flow is the CALLER's collateral delta — i.e. the premium
26376
- * the caller receives from the settlement (for chunks they sold).
26630
+ * Simulate a force exercise operation.
26377
26631
  *
26378
26632
  * @param params - Simulation parameters
26379
- * @returns Simulation result with settled premium data or error
26633
+ * @returns Simulation result with exercise data or error
26380
26634
  */
26381
- async function simulateSettlePremiumFrom(params) {
26382
- const { client, poolAddress, account, user, positionIdListFrom, positionIdList, tokenId, blockNumber } = params;
26635
+ async function simulateForceExercise(params) {
26636
+ const { client, poolAddress, account, user, positionIdListFrom, positionIdListTo, positionIdListToFinal, blockNumber } = params;
26383
26637
  const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
26384
26638
  const metaPromise = getBlockMeta({
26385
26639
  client,
@@ -26395,115 +26649,52 @@ async function simulateSettlePremiumFrom(params) {
26395
26649
  tickBefore: null,
26396
26650
  tickAfter: null
26397
26651
  };
26398
- const softFailure = (errorMessage) => {
26399
- const match = SOFT_FAILURES.find(({ marker }) => errorMessage.includes(marker));
26400
- return match ? {
26401
- premium0: 0n,
26402
- premium1: 0n,
26403
- settled0: 0n,
26404
- settled1: 0n,
26405
- canSettle: false,
26406
- reason: match.reason
26407
- } : null;
26408
- };
26409
26652
  try {
26410
- const orderedList = tokenId !== void 0 ? orderListForSettle(positionIdList, tokenId) : positionIdList;
26411
26653
  const callData = encodeFunctionData({
26412
26654
  abi: panopticPoolV2Abi,
26413
26655
  functionName: "dispatchFrom",
26414
26656
  args: [
26415
26657
  positionIdListFrom,
26416
26658
  user,
26417
- orderedList,
26418
- orderedList,
26659
+ positionIdListTo,
26660
+ positionIdListToFinal,
26419
26661
  0n
26420
26662
  ]
26421
26663
  });
26422
- const availablePremiumCallData = encodeFunctionData({
26423
- abi: panopticPoolV2Abi,
26424
- functionName: "getFullPositionsData",
26425
- args: [
26426
- account,
26427
- false,
26428
- positionIdListFrom
26429
- ]
26430
- });
26431
- const buyerOwedCallData = encodeFunctionData({
26432
- abi: panopticPoolV2Abi,
26433
- functionName: "getFullPositionsData",
26434
- args: [
26435
- user,
26436
- true,
26437
- orderedList
26438
- ]
26439
- });
26440
26664
  const flowResult = await simulateWithTokenFlow({
26441
26665
  client,
26442
26666
  poolAddress,
26443
26667
  user: account,
26444
26668
  callData,
26445
- blockNumber: targetBlockNumber,
26446
- preCallData: [availablePremiumCallData, buyerOwedCallData],
26447
- postCallData: [availablePremiumCallData, buyerOwedCallData]
26669
+ blockNumber: targetBlockNumber
26448
26670
  });
26449
26671
  if (!flowResult.success || !flowResult.tokenFlow) {
26450
26672
  const errorMessage = flowResult.error || "Simulation failed";
26451
- const soft = softFailure(errorMessage);
26452
- if (soft) {
26673
+ const isNotExercisable = errorMessage.includes("NoLegsExercisable") || errorMessage.includes("NotALongLeg");
26674
+ if (isNotExercisable) {
26453
26675
  const _meta$1 = await metaPromise;
26676
+ const data$1 = {
26677
+ exerciseFee0: 0n,
26678
+ exerciseFee1: 0n,
26679
+ canExercise: false,
26680
+ reason: errorMessage.includes("NoLegsExercisable") ? "No legs are exercisable (not ITM)" : "Position does not have a long leg"
26681
+ };
26454
26682
  return {
26455
26683
  success: true,
26456
- data: soft,
26457
- gasEstimate: 0n,
26458
- tokenFlow: emptyTokenFlow,
26459
- _meta: _meta$1
26460
- };
26461
- }
26462
- throw new PanopticError(errorMessage);
26463
- }
26464
- const _meta = await metaPromise;
26465
- const tokenFlow = flowResult.tokenFlow;
26466
- const decodePremia = (raw) => {
26467
- const [shortPremiumPacked, longPremiumPacked] = decodeFunctionResult({
26468
- abi: panopticPoolV2Abi,
26469
- functionName: "getFullPositionsData",
26470
- data: raw
26471
- });
26472
- const short = decodeLeftRightUnsigned(shortPremiumPacked);
26473
- const long = decodeLeftRightUnsigned(longPremiumPacked);
26474
- return {
26475
- short0: short.right,
26476
- short1: short.left,
26477
- long0: long.right,
26478
- long1: long.left
26479
- };
26480
- };
26481
- let premium0 = 0n;
26482
- let premium1 = 0n;
26483
- const preRaw = flowResult.preCallResults?.[0];
26484
- const postRaw = flowResult.postCallResults?.[0];
26485
- if (preRaw !== void 0 && postRaw !== void 0) {
26486
- const pre = decodePremia(preRaw);
26487
- const post = decodePremia(postRaw);
26488
- premium0 = post.short0 > pre.short0 ? post.short0 - pre.short0 : 0n;
26489
- premium1 = post.short1 > pre.short1 ? post.short1 - pre.short1 : 0n;
26490
- }
26491
- let settled0 = 0n;
26492
- let settled1 = 0n;
26493
- const preBuyerRaw = flowResult.preCallResults?.[1];
26494
- const postBuyerRaw = flowResult.postCallResults?.[1];
26495
- if (preBuyerRaw !== void 0 && postBuyerRaw !== void 0) {
26496
- const pre = decodePremia(preBuyerRaw);
26497
- const post = decodePremia(postBuyerRaw);
26498
- settled0 = pre.long0 > post.long0 ? pre.long0 - post.long0 : 0n;
26499
- settled1 = pre.long1 > post.long1 ? pre.long1 - post.long1 : 0n;
26684
+ data: data$1,
26685
+ gasEstimate: 0n,
26686
+ tokenFlow: emptyTokenFlow,
26687
+ _meta: _meta$1
26688
+ };
26689
+ }
26690
+ throw new PanopticError(errorMessage);
26500
26691
  }
26692
+ const _meta = await metaPromise;
26693
+ const tokenFlow = flowResult.tokenFlow;
26501
26694
  const data = {
26502
- premium0,
26503
- premium1,
26504
- settled0,
26505
- settled1,
26506
- canSettle: true
26695
+ exerciseFee0: tokenFlow.delta0,
26696
+ exerciseFee1: tokenFlow.delta1,
26697
+ canExercise: true
26507
26698
  };
26508
26699
  return {
26509
26700
  success: true,
@@ -26515,14 +26706,22 @@ async function simulateSettlePremiumFrom(params) {
26515
26706
  } catch (error) {
26516
26707
  const _meta = await metaPromise;
26517
26708
  const errorMessage = error instanceof Error ? error.message : "Simulation failed";
26518
- const soft = softFailure(errorMessage);
26519
- if (soft) return {
26520
- success: true,
26521
- data: soft,
26522
- gasEstimate: 0n,
26523
- tokenFlow: emptyTokenFlow,
26524
- _meta
26525
- };
26709
+ const isNotExercisable = errorMessage.includes("NoLegsExercisable") || errorMessage.includes("NotALongLeg");
26710
+ if (isNotExercisable) {
26711
+ const data = {
26712
+ exerciseFee0: 0n,
26713
+ exerciseFee1: 0n,
26714
+ canExercise: false,
26715
+ reason: errorMessage.includes("NoLegsExercisable") ? "No legs are exercisable (not ITM)" : "Position does not have a long leg"
26716
+ };
26717
+ return {
26718
+ success: true,
26719
+ data,
26720
+ gasEstimate: 0n,
26721
+ tokenFlow: emptyTokenFlow,
26722
+ _meta
26723
+ };
26724
+ }
26526
26725
  return {
26527
26726
  success: false,
26528
26727
  error: error instanceof PanopticError ? error : new PanopticError(errorMessage, error instanceof Error ? error : void 0),
@@ -26532,89 +26731,41 @@ async function simulateSettlePremiumFrom(params) {
26532
26731
  }
26533
26732
 
26534
26733
  //#endregion
26535
- //#region src/panoptic/v2/simulations/simulateSettlePremiumBatch.ts
26734
+ //#region src/panoptic/v2/simulations/simulateLiquidate.ts
26536
26735
  /**
26537
- * Simulate settling each target buyer's owed long premium, all at one block.
26538
- *
26539
- * Individual failures (insolvent buyer, stale list, …) are soft: the target
26540
- * lands in the unsettleable partition instead of failing the batch. Only
26541
- * unexpected errors reject.
26736
+ * Simulate a liquidation operation.
26542
26737
  *
26543
26738
  * @param params - Simulation parameters
26544
- * @returns Partitioned targets with per-target premium and totals
26739
+ * @returns Simulation result with liquidation data or error
26545
26740
  */
26546
- async function simulateSettlePremiumBatch(params) {
26547
- const { client, poolAddress, account, positionIdListFrom, targets, blockNumber } = params;
26741
+ async function simulateLiquidate(params) {
26742
+ const { client, poolAddress, account, liquidatee, positionIdListFrom, positionIdListTo, positionIdListToFinal, blockNumber } = params;
26548
26743
  const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
26549
26744
  const metaPromise = getBlockMeta({
26550
26745
  client,
26551
26746
  blockNumber: targetBlockNumber
26552
26747
  });
26553
- const simulations = await Promise.all(targets.map((target) => simulateSettlePremiumFrom({
26554
- client,
26555
- poolAddress,
26556
- account,
26557
- user: target.user,
26558
- positionIdListFrom,
26559
- positionIdList: target.positionIdList,
26560
- tokenId: target.tokenId,
26561
- blockNumber: targetBlockNumber
26562
- })));
26563
- const results = [];
26564
- const settleable = [];
26565
- let unsettleableCount = 0;
26566
- let premium0 = 0n;
26567
- let premium1 = 0n;
26568
- simulations.forEach((sim, i) => {
26569
- const simulation = sim.success ? sim.data : {
26570
- premium0: 0n,
26571
- premium1: 0n,
26572
- settled0: 0n,
26573
- settled1: 0n,
26574
- canSettle: false,
26575
- reason: sim.error.message
26576
- };
26577
- results.push({
26578
- target: targets[i],
26579
- simulation
26580
- });
26581
- if (simulation.canSettle) {
26582
- settleable.push(targets[i]);
26583
- premium0 += simulation.premium0;
26584
- premium1 += simulation.premium1;
26585
- } else unsettleableCount += 1;
26586
- });
26587
- const _meta = await metaPromise;
26588
- return {
26589
- results,
26590
- settleable,
26591
- unsettleableCount,
26592
- premium0,
26593
- premium1,
26594
- _meta
26748
+ const emptyTokenFlow = {
26749
+ delta0: 0n,
26750
+ delta1: 0n,
26751
+ balanceBefore0: 0n,
26752
+ balanceBefore1: 0n,
26753
+ balanceAfter0: 0n,
26754
+ balanceAfter1: 0n,
26755
+ tickBefore: null,
26756
+ tickAfter: null
26595
26757
  };
26596
- }
26597
- /**
26598
- * Simulate a full settle sequence (all settles + optional close) as the one
26599
- * multicall that `executeSettleSequence` submits, measuring the caller's
26600
- * total token flow and gas.
26601
- *
26602
- * @param params - Simulation parameters
26603
- * @returns Simulation result with the caller's net flow, or error
26604
- */
26605
- async function simulateSettleSequence(params) {
26606
- const { client, poolAddress, account, blockNumber } = params;
26607
- const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
26608
- const metaPromise = getBlockMeta({
26609
- client,
26610
- blockNumber: targetBlockNumber
26611
- });
26612
26758
  try {
26613
- const calls = buildSettleSequenceCalls(params);
26614
26759
  const callData = encodeFunctionData({
26615
26760
  abi: panopticPoolV2Abi,
26616
- functionName: "multicall",
26617
- args: [calls]
26761
+ functionName: "dispatchFrom",
26762
+ args: [
26763
+ positionIdListFrom,
26764
+ liquidatee,
26765
+ positionIdListTo,
26766
+ positionIdListToFinal,
26767
+ 0n
26768
+ ]
26618
26769
  });
26619
26770
  const flowResult = await simulateWithTokenFlow({
26620
26771
  client,
@@ -26623,15 +26774,43 @@ async function simulateSettleSequence(params) {
26623
26774
  callData,
26624
26775
  blockNumber: targetBlockNumber
26625
26776
  });
26626
- if (!flowResult.success || !flowResult.tokenFlow) throw new PanopticError(flowResult.error || "Simulation failed");
26777
+ if (!flowResult.success || !flowResult.tokenFlow) {
26778
+ const errorMessage = flowResult.error || "Simulation failed";
26779
+ const isNotLiquidatable = errorMessage.includes("NotMarginCalled") || errorMessage.includes("AccountInsolvent");
26780
+ if (isNotLiquidatable) {
26781
+ const _meta$1 = await metaPromise;
26782
+ const data$1 = {
26783
+ bonus0: 0n,
26784
+ bonus1: 0n,
26785
+ positionsClosed: [],
26786
+ isLiquidatable: false,
26787
+ shortfall0: 0n,
26788
+ shortfall1: 0n
26789
+ };
26790
+ return {
26791
+ success: true,
26792
+ data: data$1,
26793
+ gasEstimate: 0n,
26794
+ tokenFlow: emptyTokenFlow,
26795
+ _meta: _meta$1
26796
+ };
26797
+ }
26798
+ throw new PanopticError(errorMessage);
26799
+ }
26627
26800
  const _meta = await metaPromise;
26628
26801
  const tokenFlow = flowResult.tokenFlow;
26802
+ const positionsClosed = positionIdListTo.filter((id) => !positionIdListToFinal.includes(id));
26803
+ const data = {
26804
+ bonus0: tokenFlow.delta0 > 0n ? tokenFlow.delta0 : 0n,
26805
+ bonus1: tokenFlow.delta1 > 0n ? tokenFlow.delta1 : 0n,
26806
+ positionsClosed,
26807
+ isLiquidatable: true,
26808
+ shortfall0: 0n,
26809
+ shortfall1: 0n
26810
+ };
26629
26811
  return {
26630
26812
  success: true,
26631
- data: {
26632
- delta0: tokenFlow.delta0,
26633
- delta1: tokenFlow.delta1
26634
- },
26813
+ data,
26635
26814
  gasEstimate: flowResult.gasEstimate,
26636
26815
  tokenFlow,
26637
26816
  _meta
@@ -26639,6 +26818,24 @@ async function simulateSettleSequence(params) {
26639
26818
  } catch (error) {
26640
26819
  const _meta = await metaPromise;
26641
26820
  const errorMessage = error instanceof Error ? error.message : "Simulation failed";
26821
+ const isNotLiquidatable = errorMessage.includes("NotMarginCalled") || errorMessage.includes("AccountInsolvent");
26822
+ if (isNotLiquidatable) {
26823
+ const data = {
26824
+ bonus0: 0n,
26825
+ bonus1: 0n,
26826
+ positionsClosed: [],
26827
+ isLiquidatable: false,
26828
+ shortfall0: 0n,
26829
+ shortfall1: 0n
26830
+ };
26831
+ return {
26832
+ success: true,
26833
+ data,
26834
+ gasEstimate: 0n,
26835
+ tokenFlow: emptyTokenFlow,
26836
+ _meta
26837
+ };
26838
+ }
26642
26839
  return {
26643
26840
  success: false,
26644
26841
  error: error instanceof PanopticError ? error : new PanopticError(errorMessage, error instanceof Error ? error : void 0),
@@ -28652,6 +28849,441 @@ function createEventPoller(params) {
28652
28849
  };
28653
28850
  }
28654
28851
 
28852
+ //#endregion
28853
+ //#region src/panoptic/v2/strike/ladder.ts
28854
+ /** Target number of rungs across a leg's full range (lower tick → upper tick). */
28855
+ const STRIKE_LADDER_TARGET_STRIKES = 16n;
28856
+ /** Nice increment mantissas, in tenths (1, 2.5, 5) × 10ⁿ. */
28857
+ const NICE_MANTISSAS_TENTHS = [
28858
+ 10n,
28859
+ 25n,
28860
+ 50n
28861
+ ];
28862
+ /** Upper bound on rung hops when searching for a tick-changing step. */
28863
+ const MAX_STEP_ITERATIONS = 512;
28864
+ /** Decimal precision used when rendering exact tick prices as strings. */
28865
+ const PRICE_PRECISION = 30n;
28866
+ function floorDiv(a, b) {
28867
+ const q = a / b;
28868
+ return a % b !== 0n && a < 0n !== b < 0n ? q - 1n : q;
28869
+ }
28870
+ function floorMod(a, b) {
28871
+ return a - floorDiv(a, b) * b;
28872
+ }
28873
+ function ceilDiv(a, b) {
28874
+ return -floorDiv(-a, b);
28875
+ }
28876
+ /** round(a / b) to nearest, ties up. */
28877
+ function roundDiv(a, b) {
28878
+ return floorDiv(2n * a + b, 2n * b);
28879
+ }
28880
+ function pow10(exp) {
28881
+ let result = 1n;
28882
+ for (let i = 0n; i < exp; i++) result *= 10n;
28883
+ return result;
28884
+ }
28885
+ function gcd(a, b) {
28886
+ a = a < 0n ? -a : a;
28887
+ b = b < 0n ? -b : b;
28888
+ while (b !== 0n) [a, b] = [b, a % b];
28889
+ return a;
28890
+ }
28891
+ function reduce(f) {
28892
+ const g = gcd(f.numerator, f.denominator);
28893
+ return g <= 1n ? f : {
28894
+ numerator: f.numerator / g,
28895
+ denominator: f.denominator / g
28896
+ };
28897
+ }
28898
+ function fromBigint(n) {
28899
+ return {
28900
+ numerator: n,
28901
+ denominator: 1n
28902
+ };
28903
+ }
28904
+ function mul(a, b) {
28905
+ return reduce({
28906
+ numerator: a.numerator * b.numerator,
28907
+ denominator: a.denominator * b.denominator
28908
+ });
28909
+ }
28910
+ function add(a, b) {
28911
+ return reduce({
28912
+ numerator: a.numerator * b.denominator + b.numerator * a.denominator,
28913
+ denominator: a.denominator * b.denominator
28914
+ });
28915
+ }
28916
+ function sub(a, b) {
28917
+ return add(a, {
28918
+ numerator: -b.numerator,
28919
+ denominator: b.denominator
28920
+ });
28921
+ }
28922
+ /** -1 | 0 | 1 comparing a to b. */
28923
+ function cmp(a, b) {
28924
+ const l = a.numerator * b.denominator;
28925
+ const r = b.numerator * a.denominator;
28926
+ return l === r ? 0 : l < r ? -1 : 1;
28927
+ }
28928
+ const LADDER_MIN = fromBigint(1n);
28929
+ /** Largest normalised price on the ladder. Prices above are "outside". */
28930
+ const LADDER_MAX = fromBigint(1000000n);
28931
+ function parseDecimal(value) {
28932
+ const trimmed = value.trim();
28933
+ const [basePart, exponentPart] = trimmed.toLowerCase().split("e");
28934
+ const [integerStr, fractionalStr = ""] = basePart.split(".");
28935
+ let numerator = BigInt(`${integerStr === "" ? "0" : integerStr}${fractionalStr}`);
28936
+ let denominator = pow10(BigInt(fractionalStr.length));
28937
+ if (exponentPart !== void 0 && exponentPart !== "") {
28938
+ const exponent = BigInt(exponentPart);
28939
+ if (exponent > 0n) numerator *= pow10(exponent);
28940
+ else if (exponent < 0n) denominator *= pow10(-exponent);
28941
+ }
28942
+ if (numerator <= 0n) throw new Error("Price must be positive");
28943
+ return reduce({
28944
+ numerator,
28945
+ denominator
28946
+ });
28947
+ }
28948
+ /** Render a positive fraction as a decimal string with trailing zeros trimmed. */
28949
+ function fractionToDecimal(f, precision) {
28950
+ const scaled = f.numerator * pow10(precision) / f.denominator;
28951
+ const digits = scaled.toString().padStart(Number(precision) + 1, "0");
28952
+ const intPart = digits.slice(0, digits.length - Number(precision));
28953
+ const fracPart = digits.slice(digits.length - Number(precision)).replace(/0+$/, "");
28954
+ return fracPart.length === 0 ? intPart : `${intPart}.${fracPart}`;
28955
+ }
28956
+ /** 10^k as an exact fraction, k may be negative. */
28957
+ function powerOfTen(k) {
28958
+ return k >= 0n ? fromBigint(pow10(k)) : {
28959
+ numerator: 1n,
28960
+ denominator: pow10(-k)
28961
+ };
28962
+ }
28963
+ /** floor(log10(f)) for a positive fraction. */
28964
+ function floorLog10(f) {
28965
+ let e = BigInt(f.numerator.toString().length - f.denominator.toString().length);
28966
+ while (cmp(f, powerOfTen(e)) < 0) e -= 1n;
28967
+ while (cmp(f, powerOfTen(e + 1n)) >= 0) e += 1n;
28968
+ return e;
28969
+ }
28970
+ function orientTick(tick, orient) {
28971
+ return orient.asset === 0n ? tick : -tick;
28972
+ }
28973
+ /** Exact-enough price of `tick` in the caller's orientation. */
28974
+ function tickToOrientedPrice(tick, orient) {
28975
+ const price = tickToPriceDecimalScaled(orientTick(tick, orient), orient.assetDecimals, orient.quoteDecimals, PRICE_PRECISION);
28976
+ return parseDecimal(price);
28977
+ }
28978
+ /** Nearest integer tick for a caller-oriented decimal price. */
28979
+ function orientedPriceToTick(price, orient) {
28980
+ const t = priceToTick(price, orient.assetDecimals, orient.quoteDecimals);
28981
+ return orientTick(t, orient);
28982
+ }
28983
+ /**
28984
+ * Relative rung step for a leg: `1.0001^(round(width·tickSpacing / TARGET)) − 1`.
28985
+ * Rungs scale with price (they are multiples of a price-proportional increment), so
28986
+ * spacing them by the range's TARGET-th root yields ≈TARGET rungs across the range
28987
+ * regardless of how wide it is.
28988
+ */
28989
+ function relativeStep(width, tickSpacing) {
28990
+ validateGeometry(width, tickSpacing);
28991
+ const ticks = roundDiv(width * tickSpacing, STRIKE_LADDER_TARGET_STRIKES);
28992
+ const ratio = parseDecimal(tickToPriceDecimalScaled(ticks < 1n ? 1n : ticks, 0n, 0n, PRICE_PRECISION));
28993
+ return sub(ratio, fromBigint(1n));
28994
+ }
28995
+ /** Nice increment `m × 10ⁿ` (m ∈ {1, 2.5, 5}) with the smallest log-distance to `raw`. */
28996
+ function niceIncrement(raw) {
28997
+ const e = floorLog10(raw);
28998
+ const scale = (tenths) => mul(fromBigint(tenths), powerOfTen(e - 1n));
28999
+ const candidates = [...NICE_MANTISSAS_TENTHS.map(scale), scale(100n)];
29000
+ let lo = candidates[0] ?? powerOfTen(e);
29001
+ for (const hi of candidates.slice(1)) {
29002
+ if (cmp(raw, hi) < 0) return cmp(mul(raw, raw), mul(lo, hi)) <= 0 ? lo : hi;
29003
+ lo = hi;
29004
+ }
29005
+ return lo;
29006
+ }
29007
+ /** Rung increment at normalised price `p` for the given relative step. */
29008
+ function incrementAt(p, rf) {
29009
+ return niceIncrement(mul(p, rf));
29010
+ }
29011
+ /** Normalise a price to `max(p, 1/p)` and remember whether it was inverted. */
29012
+ function normalise(price) {
29013
+ if (price.numerator >= price.denominator) return {
29014
+ value: price,
29015
+ reciprocal: false
29016
+ };
29017
+ return {
29018
+ value: {
29019
+ numerator: price.denominator,
29020
+ denominator: price.numerator
29021
+ },
29022
+ reciprocal: true
29023
+ };
29024
+ }
29025
+ /** Is `r` a multiple of `inc`? */
29026
+ function isMultiple(r, inc) {
29027
+ return r.numerator * inc.denominator % (r.denominator * inc.numerator) === 0n;
29028
+ }
29029
+ /** Smallest multiple of `inc` strictly greater than `x`. */
29030
+ function ceilMultipleStrict(x, inc) {
29031
+ const k = floorDiv(x.numerator * inc.denominator, x.denominator * inc.numerator) + 1n;
29032
+ return mul(fromBigint(k), inc);
29033
+ }
29034
+ /** Largest multiple of `inc` strictly smaller than `x`. */
29035
+ function floorMultipleStrict(x, inc) {
29036
+ const k = ceilDiv(x.numerator * inc.denominator, x.denominator * inc.numerator) - 1n;
29037
+ return mul(fromBigint(k), inc);
29038
+ }
29039
+ /**
29040
+ * The rung set is `{ r : r is a multiple of incrementAt(r) }`. Because the
29041
+ * increment grows with price, a multiple of a finer increment can land inside a
29042
+ * coarser band where it is no longer a rung; these helpers push such a candidate
29043
+ * up/down until it is a multiple of its own band's increment.
29044
+ */
29045
+ function isRung(r, rf) {
29046
+ return r.numerator > 0n && isMultiple(r, incrementAt(r, rf));
29047
+ }
29048
+ function fixUp(c, rf) {
29049
+ for (let i = 0; i < 64 && !isRung(c, rf); i++) c = ceilMultipleStrict(c, incrementAt(c, rf));
29050
+ return c;
29051
+ }
29052
+ function fixDown(c, rf) {
29053
+ for (let i = 0; i < 64 && c.numerator > 0n && !isRung(c, rf); i++) c = floorMultipleStrict(c, incrementAt(c, rf));
29054
+ return c;
29055
+ }
29056
+ /** Smallest rung strictly above `x` (may exceed the ladder top). */
29057
+ function nextRungAbove(x, rf) {
29058
+ const incHere = incrementAt(x, rf);
29059
+ const incs = [incHere, incrementAt(add(x, incHere), rf)];
29060
+ let best = null;
29061
+ for (const inc of incs) {
29062
+ const c = fixUp(ceilMultipleStrict(x, inc), rf);
29063
+ if (cmp(c, x) > 0 && (best === null || cmp(c, best) < 0)) best = c;
29064
+ }
29065
+ if (best === null) throw new PanopticValidationError("No ladder rung above price");
29066
+ return best;
29067
+ }
29068
+ /** Largest rung strictly below `x` (may fall below the ladder floor). */
29069
+ function prevRungBelow(x, rf) {
29070
+ const incHere = incrementAt(x, rf);
29071
+ const finer = incrementAt(sub(x, incHere), rf);
29072
+ let best = null;
29073
+ for (const inc of [incHere, finer]) {
29074
+ const c = fixDown(floorMultipleStrict(x, inc), rf);
29075
+ if (c.numerator > 0n && cmp(c, x) < 0 && (best === null || cmp(c, best) > 0)) best = c;
29076
+ }
29077
+ return best ?? fromBigint(0n);
29078
+ }
29079
+ /** Nearest rung price to a normalised price, or null when above the ladder. */
29080
+ function nearestRungPrice(normalised, rf) {
29081
+ let rung;
29082
+ if (isRung(normalised, rf)) rung = normalised;
29083
+ else {
29084
+ const up = nextRungAbove(normalised, rf);
29085
+ const down = prevRungBelow(normalised, rf);
29086
+ if (down.numerator <= 0n) rung = up;
29087
+ else rung = cmp(sub(normalised, down), sub(up, normalised)) <= 0 ? down : up;
29088
+ }
29089
+ if (cmp(rung, LADDER_MIN) < 0) rung = LADDER_MIN;
29090
+ if (cmp(rung, LADDER_MAX) > 0) return null;
29091
+ return rung;
29092
+ }
29093
+ /** Step one rung up (+1) or down (-1) on the normalised ladder. Null when leaving it. */
29094
+ function stepRungPrice(rung, direction, rf) {
29095
+ const next = direction > 0n ? nextRungAbove(rung, rf) : prevRungBelow(rung, rf);
29096
+ if (cmp(next, LADDER_MIN) < 0 || cmp(next, LADDER_MAX) > 0) return null;
29097
+ return next;
29098
+ }
29099
+ /** Nominal caller-oriented price of a rung as an exact fraction. */
29100
+ function rungToPrice(rung) {
29101
+ return rung.reciprocal ? {
29102
+ numerator: rung.price.denominator,
29103
+ denominator: rung.price.numerator
29104
+ } : rung.price;
29105
+ }
29106
+ function rungToPriceString(rung) {
29107
+ return fractionToDecimal(rungToPrice(rung), PRICE_PRECISION);
29108
+ }
29109
+ function nearestRung(price, rf) {
29110
+ const { value, reciprocal } = normalise(price);
29111
+ const p = nearestRungPrice(value, rf);
29112
+ return p === null ? null : {
29113
+ price: p,
29114
+ reciprocal
29115
+ };
29116
+ }
29117
+ /**
29118
+ * Step a rung in the caller's price direction. For reciprocal quotes a higher
29119
+ * caller price is a lower normalised price, so the direction flips.
29120
+ */
29121
+ function stepRung(rung, direction, rf) {
29122
+ const normalisedDir = rung.reciprocal ? direction > 0n ? -1n : 1n : direction;
29123
+ const p = stepRungPrice(rung.price, normalisedDir, rf);
29124
+ return p === null ? null : {
29125
+ price: p,
29126
+ reciprocal: rung.reciprocal
29127
+ };
29128
+ }
29129
+ /** Reject geometry the ladder cannot place: non-positive inputs or a span wider than the tick domain. */
29130
+ function validateGeometry(width, tickSpacing) {
29131
+ if (width <= 0n) throw new PanopticValidationError("width must be positive");
29132
+ if (tickSpacing <= 0n) throw new PanopticValidationError("tickSpacing must be positive");
29133
+ if (width * tickSpacing > MAX_TICK - MIN_TICK) throw new PanopticValidationError("width * tickSpacing exceeds the tick domain");
29134
+ }
29135
+ /** `rangeDown`/`rangeUp` exactly as `PanopticMath.getRangesFromStrike`. */
29136
+ function rangesFromStrike(width, tickSpacing) {
29137
+ const span = width * tickSpacing;
29138
+ return {
29139
+ rangeDown: span / 2n,
29140
+ rangeUp: ceilDiv(span, 2n)
29141
+ };
29142
+ }
29143
+ /**
29144
+ * Nearest valid strike tick to `exactTick` for `width`/`tickSpacing`.
29145
+ * Valid strikes satisfy `strike ≡ rangeDown (mod tickSpacing)`; the result is
29146
+ * shifted in whole tick spacings so the leg's ticks stay within `[MIN_TICK, MAX_TICK]`.
29147
+ */
29148
+ function canonicalStrikeForWidth(exactTick, width, tickSpacing) {
29149
+ validateGeometry(width, tickSpacing);
29150
+ const { rangeDown, rangeUp } = rangesFromStrike(width, tickSpacing);
29151
+ const offset = floorMod(rangeDown, tickSpacing);
29152
+ let strike = roundDiv(exactTick - offset, tickSpacing) * tickSpacing + offset;
29153
+ while (strike - rangeDown < MIN_TICK) strike += tickSpacing;
29154
+ while (strike + rangeUp > MAX_TICK) strike -= tickSpacing;
29155
+ return strike;
29156
+ }
29157
+ function rungToStrike(rung, geom) {
29158
+ const nominalPrice = rungToPriceString(rung);
29159
+ const exactTick = orientedPriceToTick(nominalPrice, geom.orient);
29160
+ return {
29161
+ tick: canonicalStrikeForWidth(exactTick, geom.width, geom.tickSpacing),
29162
+ nominalPrice
29163
+ };
29164
+ }
29165
+ function classifyTick(tick, geom, rf) {
29166
+ const rung = nearestRung(tickToOrientedPrice(tick, geom.orient), rf);
29167
+ if (rung === null) return { kind: "outside-ladder" };
29168
+ const canonical = rungToStrike(rung, geom);
29169
+ return canonical.tick === tick ? {
29170
+ kind: "ladder",
29171
+ nominalPrice: canonical.nominalPrice
29172
+ } : { kind: "off-ladder" };
29173
+ }
29174
+ /**
29175
+ * A rung's canonical tick is only usable when that tick classifies back to the
29176
+ * same rung (`classifyStrike` → 'ladder'). When rungs are finer than the tick
29177
+ * grid two rungs can share a tick and only one of them "owns" it; return the
29178
+ * owner's strike, or null when this rung does not own its tick.
29179
+ */
29180
+ function ownedStrike(rung, geom, rf) {
29181
+ const strike = rungToStrike(rung, geom);
29182
+ const cls = classifyTick(strike.tick, geom, rf);
29183
+ return cls.kind === "ladder" ? {
29184
+ tick: strike.tick,
29185
+ nominalPrice: cls.nominalPrice
29186
+ } : null;
29187
+ }
29188
+ /**
29189
+ * Classify a strike tick against the ladder for its width.
29190
+ *
29191
+ * - `ladder`: the tick is the canonical tick of its nearest rung → show `nominalPrice`.
29192
+ * - `off-ladder`: an in-range tick that is not a rung's canonical tick (e.g. real AMM
29193
+ * liquidity at an arbitrary strike) → show the exact price.
29194
+ * - `outside-ladder`: the normalised price exceeds 1,000,000 → legacy behaviour.
29195
+ */
29196
+ function classifyStrike(params) {
29197
+ return classifyTick(params.tick, params, relativeStep(params.width, params.tickSpacing));
29198
+ }
29199
+ /**
29200
+ * Resolve a tick to a ladder strike.
29201
+ *
29202
+ * - `step` 0 (default): the ladder tick nearest to `tick` (the tick's own rung when
29203
+ * it owns one, otherwise the closest owned neighbour).
29204
+ * - `step` ±1: the nearest ladder tick strictly beyond `tick` in that price direction
29205
+ * (rungs finer than the tick grid can collapse onto one tick, so a single rung hop
29206
+ * may not move the strike).
29207
+ *
29208
+ * Returns null when the target lies outside the ladder (normalised price > 1e6).
29209
+ */
29210
+ function resolveLadderStrike(params) {
29211
+ const step = params.step ?? 0n;
29212
+ const rf = relativeStep(params.width, params.tickSpacing);
29213
+ const start = nearestRung(tickToOrientedPrice(params.tick, params.orient), rf);
29214
+ if (start === null) return null;
29215
+ const startOriented = orientTick(params.tick, params.orient);
29216
+ if (step === 0n) {
29217
+ const own = ownedStrike(start, params, rf);
29218
+ if (own !== null) return own;
29219
+ let lo = start;
29220
+ let hi = start;
29221
+ for (let i = 0; i < MAX_STEP_ITERATIONS; i++) {
29222
+ lo = lo === null ? null : stepRung(lo, -1n, rf);
29223
+ hi = hi === null ? null : stepRung(hi, 1n, rf);
29224
+ const a = lo === null ? null : ownedStrike(lo, params, rf);
29225
+ const b = hi === null ? null : ownedStrike(hi, params, rf);
29226
+ if (a !== null && b !== null) {
29227
+ const da = startOriented - orientTick(a.tick, params.orient);
29228
+ const db = orientTick(b.tick, params.orient) - startOriented;
29229
+ return da <= db ? a : b;
29230
+ }
29231
+ if (a !== null) return a;
29232
+ if (b !== null) return b;
29233
+ if (lo === null && hi === null) return null;
29234
+ }
29235
+ return null;
29236
+ }
29237
+ let rung = start;
29238
+ for (let i = 0; i < MAX_STEP_ITERATIONS && rung !== null; i++) {
29239
+ const own = ownedStrike(rung, params, rf);
29240
+ if (own !== null) {
29241
+ const oriented = orientTick(own.tick, params.orient);
29242
+ if (step > 0n ? oriented > startOriented : oriented < startOriented) return own;
29243
+ }
29244
+ rung = stepRung(rung, step, rf);
29245
+ }
29246
+ return null;
29247
+ }
29248
+ /**
29249
+ * Generate up to `count` ladder strikes centred on `centerTick`, sorted by
29250
+ * ascending caller price and deduplicated by tick. Rungs beyond the ladder are
29251
+ * omitted (the result may be shorter than `count`). Returns null when the
29252
+ * centre itself lies outside the ladder and `[]` when `count` is 0.
29253
+ */
29254
+ function ladderStrikeSequence(params) {
29255
+ const rf = relativeStep(params.width, params.tickSpacing);
29256
+ if (params.count <= 0) return [];
29257
+ const center = nearestRung(tickToOrientedPrice(params.centerTick, params.orient), rf);
29258
+ if (center === null) return null;
29259
+ const half = Math.floor(params.count / 2);
29260
+ const below = [];
29261
+ const above = [];
29262
+ let r = center;
29263
+ for (let i = 0; i < half && r !== null; i++) {
29264
+ r = stepRung(r, -1n, rf);
29265
+ if (r !== null) below.push(r);
29266
+ }
29267
+ r = center;
29268
+ for (let i = 0; i < params.count - half - 1 && r !== null; i++) {
29269
+ r = stepRung(r, 1n, rf);
29270
+ if (r !== null) above.push(r);
29271
+ }
29272
+ const seen = new Set();
29273
+ const out = [];
29274
+ for (const rung of [
29275
+ ...below.reverse(),
29276
+ center,
29277
+ ...above
29278
+ ]) {
29279
+ const strike = ownedStrike(rung, params, rf);
29280
+ if (strike === null || seen.has(strike.tick)) continue;
29281
+ seen.add(strike.tick);
29282
+ out.push(strike);
29283
+ }
29284
+ return out;
29285
+ }
29286
+
28655
29287
  //#endregion
28656
29288
  //#region src/panoptic/v2/bot/index.ts
28657
29289
  /**
@@ -29186,5 +29818,5 @@ const VAULT_DISPLAY_NAME_RESOLVERS_PER_CHAIN = {
29186
29818
  };
29187
29819
 
29188
29820
  //#endregion
29189
- 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, 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, SafeModeError, StaleDataError, StaleOracleError, SwapTokenMismatchError, SyncTimeoutError, TOKEN_ID_BITS, TokenIdHasZeroLegsError, TooManyLegsOpenError, TransferFailedError, UNREALIZED_INTEREST_BITS, UTILIZATION_DENOMINATOR, UnauthorizedUniswapCallbackError, UnderOverFlowError, UnhealthyPoolError, 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, assertTradeable, borrow, borrowAndWait, buildBatchDispatchArgs, buildCreditSwapCall, buildCreditWrappedDispatch, buildOpenPositionCalldata, buildSettleSequenceCalls, buildSfpmSwapCalldata, buildSfpmSwapPlan, buildTemporaryLoanRecoveryDispatch, buildTokenShortfallRecoveryDispatch, buildUniqueCredit, buildUniqueLoan, buildUniqueWidthZeroLeg, calculateAccountGreeksPure, calculatePortfolioDelta, calculatePortfolioGamma, calculatePortfolioGreeks, calculatePortfolioValue, calculatePositionDelta, calculatePositionDeltaDebtOnly, calculatePositionDeltaWithSwap, calculatePositionGamma, calculatePositionGreeks, calculatePositionValue, calculateResyncBlock, calculateSpreadWad, cancelTransaction, checkApproval, checkCollateralAcrossTicks, classifyStrategyGroups, cleanupStalePendingPositions, clearCheckpoint, clearPendingPositions, clearTrackedChunks, clearTrackedPositions, clearTradeHistory, closePosition, closePositionAndWait, 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, encodeLeg, encodePoolId, encodePoolKeyBytes, encodeV3PoolKeyBytes, encodeV4PoolId, ensureSfpmV3PoolInitialized, estimateBlockNumbers, estimateCollateralBreakdown, estimateCollateralRequired, executeBatchDispatch, executeBatchDispatchAndWait, executeSettleSequence, executeSettleSequenceAndWait, failPendingPosition, feesFromFeeGrowthDelta, fetchPoolId, fetchSfpmV3PoolId, 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, getClosedPositions, getClosedPositionsKey, getCollateralAddresses, getCollateralData, getCollateralSharePrices, getCollateralTotalAssetsBatch, getCurrentRates, getDeltaHedgeParams, getEnforcedTickLimits, getFactoryConstructMetadata, getFactoryOwnerOf, getFactoryTokenURI, getForfeitablePremium, getGuardianUnlockState, 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, getPoolDeploymentBlock, getPoolDisplayId, getPoolLiquidities, getPoolMetaKey, getPoolMetadata, getPoolPrefix, getPortfolioValue, getPosition, getPositionChunkData, getPositionEnrichmentData, getPositionGreeks, getPositionMetaKey, getPositions, getPositionsKey, getPositionsWithPremia, getPriceHistory, getPricesAtTick, getRealizedPnL, getRequiredCreditForITM, getRiskParameters, getSafeMode, getSchemaVersionKey, 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, liquidate, liquidateAndWait, loadCheckpoint, minePoolAddress, mint, mintAndWait, mintableAfterBuffer, multicallRead, openPosition, openPositionAndWait, optimizeTokenIdRiskPartners, oracleEpochAt, orderListForSettle, packMarketState, panopticPoolV2Abi, parseBps, parseCollateralLog, parsePanopticError, parsePoolLog, parseTokenAmount, parseTokenListId, parseWad, planDeriveStrategy, pokeOracle, pokeOracleAndWait, previewBorrow, previewDeposit, previewMint, previewRedeem, previewUnwrap, previewWithdraw, previewWrap, priceToTick, publicBroadcaster, quoteOneTokenFlow, quoteSfpmSwap, quoteTemporaryLoanRecovery, quoteTokenShortfallRecovery, quoteV3ExactIn, ratePerSecWadToAprPct, reconstructFromEvents, recoverSnapshot, recoverSnapshotFromTx, redeem, redeemAndWait, removeTrackedChunks, repay, repayAndWait, requireChainDeployment, resolveBlockNumbers, resolvePanopticPoolFromPoolId, resolveTokenIndex, resolveUniswapV4PoolKey, riskEngineAbi, rollPosition, rollPositionAndWait, roundToTickSpacing, saveCheckpoint, saveClosedPosition, scanChunks, 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, verifyBlockContinuity, watchEvents, wethWrapAbi, withdraw, withdrawAndWait, withdrawWithPositions, withdrawWithPositionsAndWait, wrapEth, wrapEthAndWait, wrapXstock, wrapXstockAndWait, xstockWrapperAbi };
29821
+ 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, 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, 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, assertTradeable, borrow, borrowAndWait, buildBatchDispatchArgs, buildCreditSwapCall, buildCreditWrappedDispatch, buildOpenPositionCalldata, buildProtectedSettleDispatch, buildProtectedSettlePlan, buildSettleSequenceCalls, buildSfpmSwapCalldata, buildSfpmSwapPlan, buildTemporaryLoanRecoveryDispatch, buildTokenShortfallRecoveryDispatch, buildUniqueCredit, buildUniqueLoan, buildUniqueWidthZeroLeg, calculateAccountGreeksPure, calculatePortfolioDelta, calculatePortfolioGamma, calculatePortfolioGreeks, calculatePortfolioValue, calculatePositionDelta, calculatePositionDeltaDebtOnly, calculatePositionDeltaWithSwap, calculatePositionGamma, calculatePositionGreeks, calculatePositionValue, calculateResyncBlock, calculateSpreadWad, cancelTransaction, checkApproval, checkCollateralAcrossTicks, classifyStrategyGroups, classifyStrike, cleanupStalePendingPositions, clearCheckpoint, clearPendingPositions, clearTrackedChunks, clearTrackedPositions, clearTradeHistory, closePosition, closePositionAndWait, 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, encodeLeg, encodePoolId, encodePoolKeyBytes, encodeV3PoolKeyBytes, encodeV4PoolId, ensureSfpmV3PoolInitialized, estimateBlockNumbers, estimateCollateralBreakdown, estimateCollateralRequired, executeBatchDispatch, executeBatchDispatchAndWait, executeSettleSequence, executeSettleSequenceAndWait, failPendingPosition, feesFromFeeGrowthDelta, fetchPoolId, fetchSfpmV3PoolId, 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, getClosedPositions, getClosedPositionsKey, getCollateralAddresses, getCollateralData, getCollateralSharePrices, getCollateralTotalAssetsBatch, getCurrentRates, getDeltaHedgeParams, getEnforcedTickLimits, getFactoryConstructMetadata, getFactoryOwnerOf, getFactoryTokenURI, getForfeitablePremium, getGuardianUnlockState, 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, getPoolDeploymentBlock, getPoolDisplayId, getPoolLiquidities, getPoolMetaKey, getPoolMetadata, getPoolPrefix, getPortfolioValue, getPosition, getPositionChunkData, getPositionEnrichmentData, getPositionGreeks, getPositionMetaKey, getPositions, getPositionsKey, getPositionsWithPremia, getPriceHistory, getPricesAtTick, getRealizedPnL, getRequiredCreditForITM, getRiskParameters, getSafeMode, getSchemaVersionKey, 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, minePoolAddress, mint, mintAndWait, mintableAfterBuffer, multicallRead, openPosition, openPositionAndWait, optimizeTokenIdRiskPartners, oracleEpochAt, orderListForSettle, packMarketState, panopticPoolV2Abi, parseBps, parseCollateralLog, parsePanopticError, parsePoolLog, parseTokenAmount, parseTokenListId, parseWad, planDeriveStrategy, pokeOracle, pokeOracleAndWait, previewBorrow, previewDeposit, previewMint, previewRedeem, previewUnwrap, previewWithdraw, previewWrap, priceToTick, publicBroadcaster, quoteOneTokenFlow, quoteSfpmSwap, quoteTemporaryLoanRecovery, quoteTokenShortfallRecovery, quoteV3ExactIn, ratePerSecWadToAprPct, reconstructFromEvents, recoverSnapshot, recoverSnapshotFromTx, redeem, redeemAndWait, removeTrackedChunks, repay, repayAndWait, requireChainDeployment, resolveBlockNumbers, resolveLadderStrike, resolvePanopticPoolFromPoolId, resolveTokenIndex, resolveUniswapV4PoolKey, riskEngineAbi, rollPosition, rollPositionAndWait, roundToTickSpacing, saveCheckpoint, saveClosedPosition, scanChunks, 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, verifyBlockContinuity, watchEvents, wethWrapAbi, withdraw, withdrawAndWait, withdrawWithPositions, withdrawWithPositionsAndWait, wrapEth, wrapEthAndWait, wrapXstock, wrapXstockAndWait, xstockWrapperAbi };
29190
29822
  //# sourceMappingURL=index.js.map