@panoptic-eng/sdk 1.0.60 → 1.0.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/{chainDeployments-CmDzAmZ3.js → chainDeployments-BhXMBZ4B.js} +50 -12
  2. package/dist/cow/index.js +1207 -484
  3. package/dist/cow/index.js.map +1 -1
  4. package/dist/{cow-CHb343la.js → cow-DTi3GjQz.js} +1 -1
  5. package/dist/deployments.d.ts +9 -1
  6. package/dist/deployments.d.ts.map +1 -1
  7. package/dist/deployments.js +50 -12
  8. package/dist/deployments.js.map +1 -1
  9. package/dist/index.d.ts +587 -75
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +577 -357
  12. package/dist/index.js.map +1 -1
  13. package/dist/{irm-BIaLQ-0n.js → irm-BDlcUNgJ.js} +2 -2
  14. package/dist/panoptic/v2/index.d.ts +169 -3
  15. package/dist/panoptic/v2/index.d.ts.map +1 -1
  16. package/dist/panoptic/v2/index.js +658 -107
  17. package/dist/panoptic/v2/index.js.map +1 -1
  18. package/dist/panoptic/v2/react-public.d.ts +177 -3
  19. package/dist/panoptic/v2/react-public.d.ts.map +1 -1
  20. package/dist/panoptic/v2/react-public.js +674 -113
  21. package/dist/panoptic/v2/react-public.js.map +1 -1
  22. package/dist/{rates-COAJpKRd.js → rates-BwZnK0tG.js} +498 -482
  23. package/dist/{router-B2fj4_X7.js → router-Y1OxL9Nt.js} +2 -2
  24. package/dist/{router-DliBF9FK.js → router-jMP7fVno.js} +2 -2
  25. package/dist/{transactionFees-CNbjAigT.js → transactionFees-aXQlx-lq.js} +11 -6
  26. package/dist/uniswap/index.js +724 -1
  27. package/dist/uniswap/index.js.map +1 -1
  28. package/dist/{v2-C3n8n1_i.js → v2-B27ILZl4.js} +518 -202
  29. package/dist/vault-transaction-fees.d.ts +1 -0
  30. package/dist/vault-transaction-fees.d.ts.map +1 -1
  31. package/dist/vault-transaction-fees.js +59 -16
  32. package/dist/vault-transaction-fees.js.map +1 -1
  33. package/dist/{writes-BTkqc_rn.js → writes-B8NGXzUG.js} +219 -38
  34. package/package.json +1 -1
@@ -1,9 +1,9 @@
1
- import { StateViewAbi, getAccountCollateral, panopticQueryAbi, readBlockAndAggregate, requireReturnData } from "./irm-BIaLQ-0n.js";
2
- import { AccountInsolventError, ChunkLimitError, DEFAULT_VEGOID, InvalidHistoryRangeError, MulticallResultMissingError, NotEnoughTokensError, PanopticError, PanopticValidationError, SafeModeError, StaleDataError, StorageDataNotFoundError, UnhealthyPoolError, WrongUniswapPoolError, applyMintBufferPerToken, availableToBorrow, collateralTrackerV2Abi, decodeLeftRightSigned, decodeLeftRightUnsigned, decodePositionBalance, getBlockMeta, getClosedPositionsKey, getPendingPositionsKey, getPool, getPoolMetaKey, getPoolMetadata, getPositionMetaKey, getPositionsKey, getTrackedChunksKey, getTrackedPositionIds, isPanopticErrorType, jsonSerializer, mintableAfterBuffer, panopticFactoryV3Abi, panopticFactoryV4Abi, panopticGuardianAbi, panopticLiquidatorAbi, panopticPoolV2Abi, panopticQueryAbi$1, parsePanopticError, riskEngineAbi, semiFungiblePositionManagerV3Abi, semiFungiblePositionManagerV4Abi, stateViewAbi, uniswapV3PoolAbi } from "./rates-COAJpKRd.js";
1
+ import { StateViewAbi, getAccountCollateral, panopticQueryAbi$1 as panopticQueryAbi, readBlockAndAggregate, requireReturnData } from "./irm-BDlcUNgJ.js";
2
+ import { AccountInsolventError, ChunkLimitError, DEFAULT_VEGOID, InvalidHistoryRangeError, MulticallResultMissingError, NotEnoughTokensError, PanopticError, PanopticValidationError, SafeModeError, StaleDataError, StorageDataNotFoundError, UnhealthyPoolError, WrongUniswapPoolError, applyMintBufferPerToken, availableToBorrow, collateralTrackerV2Abi, decodeLeftRightSigned, decodeLeftRightUnsigned, decodePositionBalance, getBlockMeta, getClosedPositionsKey, getPendingPositionsKey, getPool, getPoolMetaKey, getPoolMetadata, getPositionMetaKey, getPositionsKey, getTrackedChunksKey, getTrackedPositionIds, isPanopticErrorType, jsonSerializer, mintableAfterBuffer, panopticFactoryV3Abi, panopticFactoryV4Abi, panopticGuardianAbi, panopticLiquidatorAbi, panopticPoolV2Abi, panopticQueryAbi as panopticQueryAbi$1, parsePanopticError, riskEngineAbi, semiFungiblePositionManagerV3Abi, semiFungiblePositionManagerV4Abi, stateViewAbi, uniswapV3PoolAbi } from "./rates-BwZnK0tG.js";
3
3
  import { MAX_TICK, MAX_TRACKED_CHUNKS, MIN_TICK, NO_LOWER_LIQUIDATION_TICK, NO_UPPER_LIQUIDATION_TICK, WAD, calculatePositionDelta, calculatePositionDeltaDebtOnly, calculatePositionGamma, calculatePositionValue, priceToTick, sqrtPriceX96ToTick, tickLimits, tickToPriceDecimalScaled, tickToSqrtPriceX96, toVaultFrameAtTick } from "./greeks-CNi1-cnp.js";
4
- import { addLegToTokenId, buildBatchDispatchArgs, buildSettleSequenceCalls, buildUniqueCredit, buildUniqueLoan, countLegs, createTokenIdBuilder, decodeAllLegs, decodeTokenId, getPoolTokensForSimulation, loadCheckpoint, resolveTokenIndex, simulateOpenPosition, simulateWithTokenFlow } from "./writes-BTkqc_rn.js";
5
- import { getLpPositionFunding, getMaxLpPositionSize } from "./router-B2fj4_X7.js";
6
- import { BaseError, ContractFunctionExecutionError, ContractFunctionRevertedError, ExecutionRevertedError, decodeFunctionResult, encodeAbiParameters, encodeFunctionData, getAddress, hexToString, keccak256, parseAbi, toHex, trim, zeroAddress } from "viem";
4
+ import { addLegToTokenId, buildBatchDispatchArgs, buildUniqueCredit, buildUniqueLoan, countLegs, createTokenIdBuilder, decodeAllLegs, decodeTokenId, getPoolTokensForSimulation, loadCheckpoint, resolveTokenIndex, simulateDispatch, simulateOpenPosition, simulateWithTokenFlow } from "./writes-B8NGXzUG.js";
5
+ import { getLpPositionFunding, getMaxLpPositionSize } from "./router-Y1OxL9Nt.js";
6
+ import { BaseError, ContractFunctionExecutionError, ContractFunctionRevertedError, ExecutionRevertedError, decodeFunctionResult, encodeAbiParameters, encodeFunctionData, getAddress, hexToString, keccak256, parseAbi, parseEventLogs, toHex, trim, zeroAddress } from "viem";
7
7
  import { multicall } from "viem/actions";
8
8
  import Decimal from "decimal.js";
9
9
 
@@ -539,159 +539,6 @@ async function assertLpPositionFunded(params) {
539
539
  return funding;
540
540
  }
541
541
 
542
- //#endregion
543
- //#region src/panoptic/v2/simulations/simulateDispatch.ts
544
- /**
545
- * Simulate a raw dispatch operation.
546
- *
547
- * Uses PanopticPool.multicall with getAssetsOf-dispatch-getAssetsOf pattern
548
- * to measure exact collateral asset movements.
549
- *
550
- * @param params - Simulation parameters
551
- * @returns Simulation result with dispatch data or error
552
- */
553
- async function simulateDispatch(params) {
554
- const { client, poolAddress, account, positionIdList, finalPositionIdList, positionSizes, tickAndSpreadLimits, usePremiaAsCollateral = false, builderCode = 0n, blockNumber, existingPositionIdList, measurePremia = false } = params;
555
- const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
556
- const metaPromise = getBlockMeta({
557
- client,
558
- blockNumber: targetBlockNumber
559
- });
560
- try {
561
- const callData = encodeFunctionData({
562
- abi: panopticPoolV2Abi,
563
- functionName: "dispatch",
564
- args: [
565
- positionIdList,
566
- finalPositionIdList,
567
- positionSizes,
568
- tickAndSpreadLimits.map((t) => [
569
- Number(t[0]),
570
- Number(t[1]),
571
- Number(t[2])
572
- ]),
573
- usePremiaAsCollateral,
574
- builderCode
575
- ]
576
- });
577
- const preFullPositionsCallData = existingPositionIdList !== void 0 ? encodeFunctionData({
578
- abi: panopticPoolV2Abi,
579
- functionName: "getFullPositionsData",
580
- args: [
581
- account,
582
- false,
583
- existingPositionIdList
584
- ]
585
- }) : void 0;
586
- const prePremiaCallData = measurePremia && existingPositionIdList !== void 0 ? encodeFunctionData({
587
- abi: panopticPoolV2Abi,
588
- functionName: "getFullPositionsData",
589
- args: [
590
- account,
591
- true,
592
- existingPositionIdList
593
- ]
594
- }) : void 0;
595
- const postFullPositionsCallData = encodeFunctionData({
596
- abi: panopticPoolV2Abi,
597
- functionName: "getFullPositionsData",
598
- args: [
599
- account,
600
- false,
601
- finalPositionIdList
602
- ]
603
- });
604
- const postPremiaCallData = measurePremia ? encodeFunctionData({
605
- abi: panopticPoolV2Abi,
606
- functionName: "getFullPositionsData",
607
- args: [
608
- account,
609
- true,
610
- finalPositionIdList
611
- ]
612
- }) : void 0;
613
- const flowResult = await simulateWithTokenFlow({
614
- client,
615
- poolAddress,
616
- user: account,
617
- callData: params.settleSequence?.targets.length ? encodeFunctionData({
618
- abi: panopticPoolV2Abi,
619
- functionName: "multicall",
620
- args: [[...buildSettleSequenceCalls(params.settleSequence), callData]]
621
- }) : callData,
622
- blockNumber: targetBlockNumber,
623
- preCallData: preFullPositionsCallData ? [preFullPositionsCallData, ...prePremiaCallData ? [prePremiaCallData] : []] : void 0,
624
- postCallData: [postFullPositionsCallData, ...postPremiaCallData ? [postPremiaCallData] : []]
625
- });
626
- if (!flowResult.success || !flowResult.tokenFlow) throw flowResult.rawError ?? new PanopticError(flowResult.error || "Token flow simulation failed");
627
- const tokenFlow = flowResult.tokenFlow;
628
- const preSnapshot = existingPositionIdList ?? [];
629
- const positionsCreated = finalPositionIdList.filter((id) => !preSnapshot.includes(id));
630
- const positionsClosed = preSnapshot.filter((id) => !finalPositionIdList.includes(id));
631
- const decodeFullPositions = (data$1) => {
632
- if (!data$1) return null;
633
- try {
634
- const decoded = decodeFunctionResult({
635
- abi: panopticPoolV2Abi,
636
- functionName: "getFullPositionsData",
637
- data: data$1
638
- });
639
- const shortPremium = decodeLeftRightUnsigned(decoded[0]);
640
- const longPremium = decodeLeftRightUnsigned(decoded[1]);
641
- const reqs = decoded[3];
642
- let collateralRequirements0 = 0n;
643
- let collateralRequirements1 = 0n;
644
- for (const packed of reqs) {
645
- const r = decodeLeftRightUnsigned(packed);
646
- collateralRequirements0 += r.right;
647
- collateralRequirements1 += r.left;
648
- }
649
- return {
650
- collateralRequirements0,
651
- collateralRequirements1,
652
- netPremia0: shortPremium.right - longPremium.right,
653
- netPremia1: shortPremium.left - longPremium.left
654
- };
655
- } catch {
656
- return null;
657
- }
658
- };
659
- const prePositions = decodeFullPositions(flowResult.preCallResults?.[0]);
660
- const postPositions = decodeFullPositions(flowResult.postCallResults?.[0]);
661
- const prePremia = decodeFullPositions(flowResult.preCallResults?.[1]);
662
- const postPremia = decodeFullPositions(flowResult.postCallResults?.[1]);
663
- const _meta = await metaPromise;
664
- const data = {
665
- netAmount0: tokenFlow.delta0,
666
- netAmount1: tokenFlow.delta1,
667
- premiaReceived0: prePremia !== null && postPremia !== null ? prePremia.netPremia0 - postPremia.netPremia0 : null,
668
- premiaReceived1: prePremia !== null && postPremia !== null ? prePremia.netPremia1 - postPremia.netPremia1 : null,
669
- positionsCreated,
670
- positionsClosed,
671
- postCollateral0: tokenFlow.balanceAfter0,
672
- postCollateral1: tokenFlow.balanceAfter1,
673
- preMarginExcess0: prePositions === null ? null : tokenFlow.balanceBefore0 - prePositions.collateralRequirements0,
674
- preMarginExcess1: prePositions === null ? null : tokenFlow.balanceBefore1 - prePositions.collateralRequirements1,
675
- postMarginExcess0: postPositions === null ? null : tokenFlow.balanceAfter0 - postPositions.collateralRequirements0,
676
- postMarginExcess1: postPositions === null ? null : tokenFlow.balanceAfter1 - postPositions.collateralRequirements1
677
- };
678
- return {
679
- success: true,
680
- data,
681
- gasEstimate: flowResult.gasEstimate,
682
- tokenFlow,
683
- _meta
684
- };
685
- } catch (error) {
686
- const _meta = await metaPromise;
687
- return {
688
- success: false,
689
- error: error instanceof PanopticError ? error : new PanopticError(error instanceof Error ? error.message : "Simulation failed", error instanceof Error ? error : void 0),
690
- _meta
691
- };
692
- }
693
- }
694
-
695
542
  //#endregion
696
543
  //#region src/panoptic/v2/simulations/creditWrap.ts
697
544
  /**
@@ -3549,6 +3396,73 @@ async function optimizeTokenIdRiskPartners(params) {
3549
3396
  return optimizedTokenId;
3550
3397
  }
3551
3398
 
3399
+ //#endregion
3400
+ //#region src/panoptic/v2/reads/tickNetWindows.ts
3401
+ /**
3402
+ * Wide liquidity distributions from several adjacent `getTickNets*` windows.
3403
+ *
3404
+ * @module v2/reads/tickNetWindows
3405
+ */
3406
+ /** Absolute Uniswap V3/V4 tick bounds. */
3407
+ const TICK_MIN$1 = -887272;
3408
+ const TICK_MAX$1 = 887272;
3409
+ /**
3410
+ * Join ascending, edge-sharing windows into one distribution anchored to `windows[mainIndex]`.
3411
+ *
3412
+ * Each `getTickNets*` window is a running sum of liquidityNet from its own first tick (only the
3413
+ * window holding the current tick is rescaled to the pool's liquidity), so a neighbour's values
3414
+ * are off by a constant. Adjacent windows share their edge tick; the offset that makes that tick
3415
+ * agree is applied to the whole neighbour. Stitching stops at the first window that does not share
3416
+ * an edge with the one before it.
3417
+ */
3418
+ function stitchTickNetWindows(windows, mainIndex) {
3419
+ const main = windows[mainIndex];
3420
+ if (!main) return {
3421
+ ticks: [],
3422
+ liquidityNets: []
3423
+ };
3424
+ const ticks = [...main.ticks];
3425
+ const nets = [...main.liquidityNets];
3426
+ for (let i = mainIndex + 1; i < windows.length; i++) {
3427
+ const window = windows[i];
3428
+ const edge = ticks.length - 1;
3429
+ if (!window.ticks.length || window.ticks[0] !== ticks[edge]) break;
3430
+ const offset = nets[edge] - window.liquidityNets[0];
3431
+ ticks.push(...window.ticks.slice(1));
3432
+ nets.push(...window.liquidityNets.slice(1).map((value) => value + offset));
3433
+ }
3434
+ for (let i = mainIndex - 1; i >= 0; i--) {
3435
+ const window = windows[i];
3436
+ const last = window.ticks.length - 1;
3437
+ if (last < 0 || window.ticks[last] !== ticks[0]) break;
3438
+ const offset = nets[0] - window.liquidityNets[last];
3439
+ ticks.unshift(...window.ticks.slice(0, last));
3440
+ nets.unshift(...window.liquidityNets.slice(0, last).map((value) => value + offset));
3441
+ }
3442
+ return {
3443
+ ticks,
3444
+ liquidityNets: nets
3445
+ };
3446
+ }
3447
+ /**
3448
+ * Read the main window around `startTick` plus up to `windowsPerSide` windows of `nTicks` on each
3449
+ * side, in parallel, and stitch them. Side windows that would cross the tick bounds are skipped.
3450
+ */
3451
+ async function readTickNetWindows({ startTick, mainNTicks, nTicks, tickSpacing, windowsPerSide, read }) {
3452
+ const center = Math.trunc(startTick / tickSpacing) * tickSpacing;
3453
+ const half = Number(nTicks) * tickSpacing;
3454
+ const mainHalf = Number(mainNTicks) * tickSpacing;
3455
+ const sideCenters = (direction) => Array.from({ length: windowsPerSide }, (_, k) => center + direction * (mainHalf + half + 2 * half * k)).filter((side) => side - half >= TICK_MIN$1 && side + half <= TICK_MAX$1);
3456
+ const below = sideCenters(-1).reverse();
3457
+ const above = sideCenters(1);
3458
+ const windows = await Promise.all([
3459
+ ...below.map((side) => read(side, nTicks)),
3460
+ read(startTick, mainNTicks),
3461
+ ...above.map((side) => read(side, nTicks))
3462
+ ]);
3463
+ return stitchTickNetWindows(windows, below.length);
3464
+ }
3465
+
3552
3466
  //#endregion
3553
3467
  //#region src/panoptic/v2/reads/liquidity.ts
3554
3468
  /**
@@ -3566,24 +3480,35 @@ async function optimizeTokenIdRiskPartners(params) {
3566
3480
  async function getPoolLiquidities(params) {
3567
3481
  const { client, poolAddress, queryAddress, startTick, nTicks, blockNumber } = params;
3568
3482
  const targetBlockNumber = blockNumber ?? params._meta?.blockNumber ?? await client.getBlockNumber();
3569
- const [result, _meta] = await Promise.all([client.readContract({
3570
- address: queryAddress,
3571
- abi: panopticQueryAbi,
3572
- functionName: "getTickNets",
3573
- args: [
3574
- poolAddress,
3575
- Number(startTick),
3576
- nTicks
3577
- ],
3578
- blockNumber: targetBlockNumber
3483
+ const windowsPerSide = params.windowsPerSide ?? 0;
3484
+ if (windowsPerSide > 0 && params.tickSpacing === void 0) throw new PanopticValidationError("getPoolLiquidities: tickSpacing is required with windowsPerSide");
3485
+ const [{ ticks, liquidityNets }, _meta] = await Promise.all([readTickNetWindows({
3486
+ startTick: Number(startTick),
3487
+ mainNTicks: nTicks,
3488
+ nTicks,
3489
+ tickSpacing: params.tickSpacing ?? 1,
3490
+ windowsPerSide,
3491
+ read: (centerTick, windowTicks) => client.readContract({
3492
+ address: queryAddress,
3493
+ abi: panopticQueryAbi,
3494
+ functionName: "getTickNets",
3495
+ args: [
3496
+ poolAddress,
3497
+ centerTick,
3498
+ windowTicks
3499
+ ],
3500
+ blockNumber: targetBlockNumber
3501
+ }).then(([tickData, nets]) => ({
3502
+ ticks: tickData,
3503
+ liquidityNets: nets
3504
+ }))
3579
3505
  }), params._meta ?? getBlockMeta({
3580
3506
  client,
3581
3507
  blockNumber: targetBlockNumber
3582
3508
  })]);
3583
- const [tickData, liquidityNets] = result;
3584
3509
  return {
3585
- ticks: [...tickData],
3586
- liquidityNets: [...liquidityNets],
3510
+ ticks,
3511
+ liquidityNets,
3587
3512
  _meta
3588
3513
  };
3589
3514
  }
@@ -4475,6 +4400,32 @@ function computeUniswapFeesForBlock(blockData, legs) {
4475
4400
  total1
4476
4401
  };
4477
4402
  }
4403
+ const MAX_UINT256$1 = 2n ** 256n - 1n;
4404
+ /**
4405
+ * Fee growth per unit of liquidity inside `[lowerTick, upperTick)` at one block,
4406
+ * wrapped to uint256 as the pool computes it. Diff two snapshots with
4407
+ * `feesFromFeeGrowthDelta` to get the fees a constant liquidity earned between them.
4408
+ */
4409
+ function feeGrowthInsideX128(blockData, lowerTick, upperTick) {
4410
+ const lower = blockData.tickData.get(lowerTick);
4411
+ const upper = blockData.tickData.get(upperTick);
4412
+ if (!lower || !upper) return null;
4413
+ const { currentTick } = blockData;
4414
+ const inside = (global, lowerOutside, upperOutside) => {
4415
+ const below = currentTick >= lowerTick ? lowerOutside : global - lowerOutside;
4416
+ const above = currentTick < upperTick ? upperOutside : global - upperOutside;
4417
+ return global - below - above & MAX_UINT256$1;
4418
+ };
4419
+ return {
4420
+ feeGrowthInside0X128: inside(blockData.feeGrowthGlobal0, lower.feeGrowthOutside0, upper.feeGrowthOutside0),
4421
+ feeGrowthInside1X128: inside(blockData.feeGrowthGlobal1, lower.feeGrowthOutside1, upper.feeGrowthOutside1)
4422
+ };
4423
+ }
4424
+ /** Blocks before the chain's Multicall3 deployment need viem's deployless multicall. */
4425
+ function predatesMulticall3(client, blockNumber) {
4426
+ const deployedAt = client.chain?.contracts?.multicall3?.blockCreated;
4427
+ return blockNumber != null && deployedAt != null && blockNumber < BigInt(deployedAt);
4428
+ }
4478
4429
  async function fetchUniswapBlockSnapshot(client, blockNumber, uniqueTicks, poolConfig) {
4479
4430
  if (poolConfig.version === "v3") return fetchV3BlockSnapshot(client, poolConfig.poolAddress, blockNumber, uniqueTicks);
4480
4431
  else return fetchV4BlockSnapshot(client, poolConfig.stateViewAddress, poolConfig.poolId, blockNumber, uniqueTicks);
@@ -4506,7 +4457,8 @@ async function fetchV3BlockSnapshot(client, poolAddress, blockNumber, uniqueTick
4506
4457
  const results = await client.multicall({
4507
4458
  contracts,
4508
4459
  blockNumber,
4509
- allowFailure: false
4460
+ allowFailure: false,
4461
+ deployless: predatesMulticall3(client, blockNumber)
4510
4462
  });
4511
4463
  const slot0Result = results[0];
4512
4464
  const feeGrowthGlobal0 = results[1];
@@ -4515,6 +4467,7 @@ async function fetchV3BlockSnapshot(client, poolAddress, blockNumber, uniqueTick
4515
4467
  for (let i = 0; i < uniqueTicks.length; i++) {
4516
4468
  const tickResult = results[3 + i];
4517
4469
  tickData.set(uniqueTicks[i], {
4470
+ liquidityGross: tickResult[0],
4518
4471
  feeGrowthOutside0: tickResult[2],
4519
4472
  feeGrowthOutside1: tickResult[3]
4520
4473
  });
@@ -4551,7 +4504,8 @@ async function fetchV4BlockSnapshot(client, stateViewAddress, poolId, blockNumbe
4551
4504
  const results = await client.multicall({
4552
4505
  contracts,
4553
4506
  blockNumber,
4554
- allowFailure: false
4507
+ allowFailure: false,
4508
+ deployless: predatesMulticall3(client, blockNumber)
4555
4509
  });
4556
4510
  const slot0Result = results[0];
4557
4511
  const feeGrowthResult = results[1];
@@ -4559,6 +4513,7 @@ async function fetchV4BlockSnapshot(client, stateViewAddress, poolId, blockNumbe
4559
4513
  for (let i = 0; i < uniqueTicks.length; i++) {
4560
4514
  const tickResult = results[2 + i];
4561
4515
  tickData.set(uniqueTicks[i], {
4516
+ liquidityGross: tickResult[0],
4562
4517
  feeGrowthOutside0: tickResult[2],
4563
4518
  feeGrowthOutside1: tickResult[3]
4564
4519
  });
@@ -4861,23 +4816,34 @@ function clampNTicks(startTick, tickSpacing, nTicks) {
4861
4816
  * for the pool — only a deployed PanopticQuery on the chain.
4862
4817
  */
4863
4818
  async function getUniswapV3PoolLiquidities(params) {
4864
- const { client, poolAddress, queryAddress, startTick, nTicks } = params;
4865
- const safeN = clampNTicks(startTick, 1, nTicks);
4819
+ const { client, poolAddress, queryAddress, startTick, nTicks, windowsPerSide = 0 } = params;
4820
+ if (windowsPerSide > 0 && params.tickSpacing === void 0) throw new PanopticValidationError("getUniswapV3PoolLiquidities: tickSpacing is required with windowsPerSide");
4821
+ const safeN = clampNTicks(startTick, params.tickSpacing ?? 1, nTicks);
4866
4822
  const _meta = await getBlockMeta({ client });
4867
- const [ticks, liquidityNets] = await client.readContract({
4868
- address: queryAddress,
4869
- abi: panopticQueryAbi,
4870
- functionName: "getTickNetsV3",
4871
- args: [
4872
- poolAddress,
4873
- startTick,
4874
- safeN
4875
- ],
4876
- blockNumber: _meta.blockNumber
4823
+ const { ticks, liquidityNets } = await readTickNetWindows({
4824
+ startTick,
4825
+ mainNTicks: safeN,
4826
+ nTicks,
4827
+ tickSpacing: params.tickSpacing ?? 1,
4828
+ windowsPerSide,
4829
+ read: (centerTick, windowTicks) => client.readContract({
4830
+ address: queryAddress,
4831
+ abi: panopticQueryAbi,
4832
+ functionName: "getTickNetsV3",
4833
+ args: [
4834
+ poolAddress,
4835
+ centerTick,
4836
+ windowTicks
4837
+ ],
4838
+ blockNumber: _meta.blockNumber
4839
+ }).then(([windowTickData, windowNets]) => ({
4840
+ ticks: windowTickData,
4841
+ liquidityNets: windowNets
4842
+ }))
4877
4843
  });
4878
4844
  return {
4879
- ticks: [...ticks],
4880
- liquidityNets: [...liquidityNets],
4845
+ ticks,
4846
+ liquidityNets,
4881
4847
  _meta
4882
4848
  };
4883
4849
  }
@@ -5050,22 +5016,32 @@ async function getUniswapV4PoolLiquidities(params) {
5050
5016
  const { client, queryAddress, poolManager, poolId, tickSpacing, startTick, nTicks } = params;
5051
5017
  const safeN = clampNTicks(startTick, tickSpacing, nTicks);
5052
5018
  const _meta = await getBlockMeta({ client });
5053
- const [ticks, liquidityNets] = await client.readContract({
5054
- address: queryAddress,
5055
- abi: panopticQueryAbi,
5056
- functionName: "getTickNetsV4",
5057
- args: [
5058
- poolManager,
5059
- poolId,
5060
- tickSpacing,
5061
- startTick,
5062
- safeN
5063
- ],
5064
- blockNumber: _meta.blockNumber
5019
+ const { ticks, liquidityNets } = await readTickNetWindows({
5020
+ startTick,
5021
+ mainNTicks: safeN,
5022
+ nTicks,
5023
+ tickSpacing,
5024
+ windowsPerSide: params.windowsPerSide ?? 0,
5025
+ read: (centerTick, windowTicks) => client.readContract({
5026
+ address: queryAddress,
5027
+ abi: panopticQueryAbi,
5028
+ functionName: "getTickNetsV4",
5029
+ args: [
5030
+ poolManager,
5031
+ poolId,
5032
+ tickSpacing,
5033
+ centerTick,
5034
+ windowTicks
5035
+ ],
5036
+ blockNumber: _meta.blockNumber
5037
+ }).then(([windowTickData, windowNets]) => ({
5038
+ ticks: windowTickData,
5039
+ liquidityNets: windowNets
5040
+ }))
5065
5041
  });
5066
5042
  return {
5067
- ticks: [...ticks],
5068
- liquidityNets: [...liquidityNets],
5043
+ ticks,
5044
+ liquidityNets,
5069
5045
  _meta
5070
5046
  };
5071
5047
  }
@@ -9927,6 +9903,131 @@ function marketRiskFromValues({ lower, current, upper }) {
9927
9903
  };
9928
9904
  }
9929
9905
 
9906
+ //#endregion
9907
+ //#region src/panoptic/v2/greeks/positionVolatility.ts
9908
+ const Precision = Decimal.clone({ precision: 80 });
9909
+ const Q96 = 1n << 96n;
9910
+ const YEAR_SECONDS = new Precision(31536e3);
9911
+ /** The premium-free position curve, expressed in one quote token's human units. */
9912
+ function preparePositionGamma({ tokenId, positionSize, quoteIsToken0, quoteDecimals }) {
9913
+ if (positionSize <= 0n || positionSize >= 1n << 128n) throw new RangeError("Invalid position size");
9914
+ if (!Number.isInteger(quoteDecimals) || quoteDecimals < 0 || quoteDecimals > 255) throw new RangeError("Invalid quote decimals");
9915
+ const decoded = decodeTokenId(tokenId);
9916
+ const chunks = decoded.legs.flatMap((leg) => {
9917
+ if (leg.width === 0n) return [];
9918
+ const width = leg.width * decoded.tickSpacing;
9919
+ const lowerTick = leg.strike - width / 2n;
9920
+ const upperTick = leg.strike + (width + 1n) / 2n;
9921
+ if (lowerTick < -887272n || upperTick > 887272n || lowerTick >= upperTick) throw new RangeError("Invalid position range");
9922
+ const lower = tickToSqrtPriceX96(lowerTick);
9923
+ const upper = tickToSqrtPriceX96(upperTick);
9924
+ const amount = positionSize * leg.optionRatio;
9925
+ const liquidity = leg.asset === 0n ? amount * (lower * upper / Q96) / (upper - lower) : amount * Q96 / (upper - lower);
9926
+ if (liquidity >= 1n << 128n) throw new RangeError("Liquidity exceeds uint128");
9927
+ return [{
9928
+ lowerTick: Number(lowerTick),
9929
+ upperTick: Number(upperTick),
9930
+ liquidity,
9931
+ isLong: leg.isLong
9932
+ }];
9933
+ });
9934
+ const scale = new Precision(10).pow(quoteDecimals);
9935
+ const atTick = (tick) => {
9936
+ const netLiquidity = chunks.reduce((sum$1, chunk) => tick >= BigInt(chunk.lowerTick) && tick < BigInt(chunk.upperTick) ? sum$1 + (chunk.isLong ? -chunk.liquidity : chunk.liquidity) : sum$1, 0n);
9937
+ const sqrt = new Precision(tickToSqrtPriceX96(tick).toString()).div(Q96.toString());
9938
+ const gamma = new Precision(netLiquidity.toString()).neg().div(2).div(scale);
9939
+ return quoteIsToken0 ? gamma.div(sqrt) : gamma.mul(sqrt);
9940
+ };
9941
+ const inRange = (low, high) => {
9942
+ if (low > high) throw new RangeError("Invalid candle range");
9943
+ const ticks = new Set([low, high]);
9944
+ for (const chunk of chunks) for (const boundary of [BigInt(chunk.lowerTick), BigInt(chunk.upperTick)]) {
9945
+ if (boundary >= low && boundary <= high) ticks.add(boundary);
9946
+ if (boundary - 1n >= low && boundary - 1n <= high) ticks.add(boundary - 1n);
9947
+ }
9948
+ return [...ticks].map(atTick);
9949
+ };
9950
+ return {
9951
+ chunks,
9952
+ atTick,
9953
+ inRange
9954
+ };
9955
+ }
9956
+ /** Historical whole-position diagnostics, with signs retained independently of eligibility. */
9957
+ function calculatePositionVolatilityMetrics({ observations, netPremium, baseFees, quoteDecimals }) {
9958
+ if (observations.length < 2) throw new RangeError("At least two price observations are required");
9959
+ if (!Number.isInteger(quoteDecimals) || quoteDecimals < 0 || quoteDecimals > 255) throw new RangeError("Invalid quote decimals");
9960
+ const points = observations.map((point) => ({
9961
+ ...point,
9962
+ price: new Precision(point.price),
9963
+ gamma: new Precision(point.gamma),
9964
+ rangeGammas: (point.rangeGammas ?? []).map((gamma) => new Precision(gamma))
9965
+ }));
9966
+ for (const point of points) if (!point.price.isFinite() || point.price.lte(0) || !point.gamma.isFinite() || point.rangeGammas.some((gamma) => !gamma.isFinite())) throw new RangeError("Invalid price or gamma observation");
9967
+ const quantum = new Precision(10).pow(-quoteDecimals);
9968
+ const gammas = points.flatMap((point) => [point.gamma, ...point.rangeGammas]);
9969
+ const peak = gammas.reduce((max, gamma) => Precision.max(max, gamma.abs()), new Precision(0));
9970
+ const tolerance = Precision.max(quantum, peak.mul("1e-12"));
9971
+ const positive = gammas.some((gamma) => gamma.gt(tolerance));
9972
+ const negative = gammas.some((gamma) => gamma.lt(tolerance.neg()));
9973
+ const gammaSign = positive && negative ? "changing" : positive ? "positive" : negative ? "negative" : "zero";
9974
+ let exposure = new Precision(0);
9975
+ let signedConvexity = new Precision(0);
9976
+ let absoluteConvexity = new Precision(0);
9977
+ let years = new Precision(0);
9978
+ for (let i = 1; i < points.length; i++) {
9979
+ const previous = points[i - 1];
9980
+ const point = points[i];
9981
+ const seconds = point.timestamp - previous.timestamp;
9982
+ if (seconds <= 0n) throw new RangeError("Observations must have increasing timestamps");
9983
+ const elapsed = new Precision(seconds.toString()).div(YEAR_SECONDS);
9984
+ const squaredReturn = point.price.div(previous.price).ln().pow(2);
9985
+ exposure = exposure.plus(previous.gamma.abs().mul(elapsed));
9986
+ signedConvexity = signedConvexity.plus(previous.gamma.mul(squaredReturn).div(2));
9987
+ absoluteConvexity = absoluteConvexity.plus(previous.gamma.abs().mul(squaredReturn).div(2));
9988
+ years = years.plus(elapsed);
9989
+ }
9990
+ const sufficientExposure = exposure.gt(tolerance.mul(years).mul(100));
9991
+ const premium = netPremium === null ? null : new Precision(netPremium);
9992
+ const fees = baseFees == null ? null : new Precision(baseFees);
9993
+ if (premium !== null && !premium.isFinite() || fees !== null && !fees.isFinite()) throw new RangeError("Invalid accounting amount");
9994
+ const consistent = (amount) => gammaSign === "positive" ? amount.lte(quantum) : gammaSign === "negative" && amount.gte(quantum.neg());
9995
+ const reason = !sufficientExposure ? "insufficient-exposure" : gammaSign === "changing" ? "changing-sign" : premium === null ? "premium-unavailable" : !consistent(premium) ? "inconsistent-premium-direction" : null;
9996
+ const equivalent = (amount) => amount.abs().mul(2).div(exposure).sqrt().toString();
9997
+ const coverage = (amount) => absoluteConvexity.gt(quantum) ? amount.abs().div(absoluteConvexity).toString() : null;
9998
+ const eligibleFees = sufficientExposure && fees !== null && consistent(fees);
9999
+ return {
10000
+ gammaSign,
10001
+ exposure: exposure.toString(),
10002
+ signedConvexity: signedConvexity.toString(),
10003
+ absoluteConvexity: absoluteConvexity.toString(),
10004
+ netPremium: premium?.toString() ?? null,
10005
+ estimatedHedgedResult: premium?.plus(signedConvexity).toString() ?? null,
10006
+ weightedRealizedVolatility: sufficientExposure ? equivalent(absoluteConvexity) : null,
10007
+ premiumEquivalentVolatility: reason === null && premium !== null ? equivalent(premium) : null,
10008
+ premiumToConvexity: reason === null && premium !== null ? coverage(premium) : null,
10009
+ baseFees: fees?.toString() ?? null,
10010
+ feeEquivalentVolatility: eligibleFees ? equivalent(fees) : null,
10011
+ feeToConvexity: eligibleFees ? coverage(fees) : null,
10012
+ comparisonReason: reason
10013
+ };
10014
+ }
10015
+ /** Quote-value signed cumulative token increments, excluding revaluation of previous accrual. */
10016
+ function valuePositionAccrual({ snapshots, quoteIsToken0, quoteDecimals }) {
10017
+ let previous0 = 0n;
10018
+ let previous1 = 0n;
10019
+ let total = new Precision(0);
10020
+ for (const snapshot of snapshots) {
10021
+ const amount0 = new Precision((snapshot.token0 - previous0).toString());
10022
+ const amount1 = new Precision((snapshot.token1 - previous1).toString());
10023
+ const price = new Precision("1.0001").pow(snapshot.tick.toString());
10024
+ total = total.plus(quoteIsToken0 ? amount0.plus(amount1.div(price)) : amount1.plus(amount0.mul(price)));
10025
+ previous0 = snapshot.token0;
10026
+ previous1 = snapshot.token1;
10027
+ }
10028
+ return total.div(new Precision(10).pow(quoteDecimals));
10029
+ }
10030
+
9930
10031
  //#endregion
9931
10032
  //#region src/panoptic/v2/reads/collateralCurve.ts
9932
10033
  /** Native-token margin inputs, independent of the tick used to display the curve. */
@@ -10120,4 +10221,219 @@ function preparePositionValueCurve(curve) {
10120
10221
  }
10121
10222
 
10122
10223
  //#endregion
10123
- export { DEFAULT_MIN_SWAP_RATIO_BPS, DEFAULT_RECONNECT_CONFIG, MARKET_INDICATOR_PERIODS, REQUIRED_BASE_ERROR_SENTINEL, STRIKE_LADDER_TARGET_STRIKES, VARIANCE_RATIO_LAG, addPendingPosition, addTrackedChunks, apportion, assertCanBurn, assertCanForceExercise, assertCanLiquidate, assertCanMint, assertFresh, assertHealthy, assertLpPositionFunded, assertTradeable, buildCreditWrappedDispatch, buildSfpmSwapCalldata, buildSfpmSwapPlan, buildTemporaryLoanRecoveryDispatch, buildTokenShortfallRecoveryDispatch, calculateAccountGreeksPure, calculateMarketIndicator, calculateSpreadWad, calculateVarianceProfile, checkCollateralAcrossTicks, classifyStrategyGroups, classifyStrike, cleanupStalePendingPositions, clearPendingPositions, clearTrackedChunks, clearTradeHistory, collateralCurveTicks, collateralRuleKindFor, computeV4PoolId, confirmPendingPosition, convertToAssets, convertToShares, createEventPoller, createEventSubscription, createFlowNeutralTokenId, decodePanopticTokenURI, emptyLiquidateParams, encodePoolKeyBytes, encodeV3PoolKeyBytes, ensureSfpmV3PoolInitialized, estimateBlockNumbers, estimateCollateralBreakdown, estimateCollateralRequired, failPendingPosition, feesFromFeeGrowthDelta, fetchSfpmV3PoolId, getAccountBuyingPower, getAccountGreeks, getAccountHistory, getChunkLiquidities, getChunkSpreads, getClosedPositions, getCollateralCurve, getCollateralCurveInputs, getCollateralRequiredBase, getCollateralSharePrices, getCollateralTotalAssetsBatch, getDeltaHedgeParams, getEnforcedTickLimits, getExecutableLpMaxSize, getFactoryConstructMetadata, getFactoryOwnerOf, getFactoryTokenURI, getGuardianUnlockState, getHedgeLimits, getItmAmounts, getMarginBuffer, getMaxPositionSize, getMaxRedeem, getMaxWithdrawable, getNativeTokenPrice, getNotEnoughTokensError, getOpenPositionPreview, getPanopticPoolAddress, getPanopticPoolFromPoolId, getPendingPositions, getPoolCollateralAddresses, getPoolLiquidities, getPortfolioValue, getPositionChunkData, getPositionEnrichmentData, getPositionValueCurve, getPriceHistory, getRealizedPnL, getRequiredCreditForITM, getSafeMode, getStreamiaHistory, getSyncStatus, getTrackedChunks, getTradeHistory, getUniswapFeeHistory, getUniswapV3LpPositionState, getUniswapV3PoolFromId, getUniswapV3PoolInfo, getUniswapV3PoolLiquidities, getUniswapV4LpPositionState, getUniswapV4PoolBasicState, getUniswapV4PoolInfo, getUniswapV4PoolKeyFromId, getUniswapV4PoolLiquidities, interpolateBlocks, isGasError, isNonceError, isRetryableRpcError, isolateGroupTokenId, ladderStrikeSequence, logReturns, marketPnlInQuote, marketRiskFromValues, marketScenario, minePoolAddress, minePoolAddressLocalAsync, multicallRead, netLiquidationValueInQuote, optimizeTokenIdRiskPartners, parseCollateralLog, parsePoolLog, positionValueKey, positionValueTicks, prepareIndicatorCandles, preparePositionValueCurve, previewDeposit, previewMint, previewRedeem, previewWithdraw, quoteLiquidation, quoteOneTokenFlow, quoteSfpmSwap, quoteTemporaryLoanRecovery, quoteTokenShortfallRecovery, realizedBeta, removeTrackedChunks, resolveBlockNumbers, resolveLadderStrike, resolvePanopticPoolFromPoolId, resolveUniswapV4PoolKey, saveClosedPosition, scaleCollateralRequired, scanChunks, screenAccountExact, simulateBatchDispatch, simulateClosePosition, simulateDeployNewPool, simulateDeposit, simulateDispatch, simulateForceExercise, simulateLiquidate, simulateSFPMBurn, simulateSFPMMint, simulateSwapExactIn, simulateSwapExactOut, simulateWithdraw, slippageBpsToTickDistance, watchEvents };
10224
+ //#region src/panoptic/v2/reads/positionVolatilityHistory.ts
10225
+ const signedSlot = (value) => BigInt.asIntN(128, value);
10226
+ const unpack = (value) => ({
10227
+ token0: signedSlot(value),
10228
+ token1: signedSlot(value >> 128n)
10229
+ });
10230
+ /** RPC accounting for exactly one mint lifecycle; candle prices are supplied by the application. */
10231
+ async function getPositionVolatilityHistory({ client, poolAddress, account, tokenId, mintBlock, endBlock, poolConfig, includeBaseFees = false }) {
10232
+ if (mintBlock <= 0n || endBlock <= mintBlock) throw new RangeError("Insufficient lifecycle history");
10233
+ const [mints, burns] = await Promise.all([client.getContractEvents({
10234
+ address: poolAddress,
10235
+ abi: panopticPoolV2Abi,
10236
+ eventName: "OptionMinted",
10237
+ args: {
10238
+ recipient: account,
10239
+ tokenId
10240
+ },
10241
+ fromBlock: mintBlock,
10242
+ toBlock: mintBlock,
10243
+ strict: true
10244
+ }), client.getContractEvents({
10245
+ address: poolAddress,
10246
+ abi: panopticPoolV2Abi,
10247
+ eventName: "OptionBurnt",
10248
+ args: {
10249
+ recipient: account,
10250
+ tokenId
10251
+ },
10252
+ fromBlock: mintBlock,
10253
+ toBlock: endBlock,
10254
+ strict: true
10255
+ })]);
10256
+ const mint = mints[0];
10257
+ if (mints.length !== 1 || !mint) throw new Error("Opening event is missing or ambiguous");
10258
+ const balance = decodePositionBalance(mint.args.balanceData);
10259
+ const close = burns.filter((burn) => burn.blockNumber > mintBlock || burn.logIndex > mint.logIndex).sort((a, b) => a.blockNumber === b.blockNumber ? a.logIndex - b.logIndex : a.blockNumber < b.blockNumber ? -1 : 1)[0];
10260
+ const finalBlock = close?.blockNumber ?? endBlock;
10261
+ if (finalBlock <= mintBlock) throw new Error("Intrablock lifecycle cannot be reconstructed");
10262
+ if (close && close.args.positionSize !== balance.positionSize) throw new Error("Position size changed");
10263
+ const [start, end, boundaryPrices] = await Promise.all([
10264
+ getBlockMeta({
10265
+ client,
10266
+ blockNumber: mintBlock
10267
+ }),
10268
+ getBlockMeta({
10269
+ client,
10270
+ blockNumber: finalBlock
10271
+ }),
10272
+ getPriceHistory({
10273
+ client,
10274
+ poolConfig,
10275
+ blockNumbers: [mintBlock, finalBlock]
10276
+ })
10277
+ ]);
10278
+ const openingPrice = boundaryPrices.snapshots[0];
10279
+ const endingPrice = boundaryPrices.snapshots[1];
10280
+ if (!openingPrice || !endingPrice) throw new Error("Boundary prices unavailable");
10281
+ const pointCount = Math.min(200, Math.max(2, Number((end.blockTimestamp - start.blockTimestamp) / 900n) + 2));
10282
+ const blockNumbers = [...new Set(interpolateBlocks(mintBlock, finalBlock, pointCount))];
10283
+ const metadata = [];
10284
+ for (let i = 0; i < blockNumbers.length; i += 16) metadata.push(...await Promise.all(blockNumbers.slice(i, i + 16).map((blockNumber) => getBlockMeta({
10285
+ client,
10286
+ blockNumber
10287
+ }))));
10288
+ const timestamps = new Map(metadata.map((meta) => [meta.blockNumber, meta.blockTimestamp]));
10289
+ const chunks = preparePositionGamma({
10290
+ tokenId,
10291
+ positionSize: balance.positionSize,
10292
+ quoteIsToken0: false,
10293
+ quoteDecimals: 0
10294
+ }).chunks.filter((chunk) => chunk.liquidity > 0n);
10295
+ let premiumError = null;
10296
+ let feeError = includeBaseFees ? null : "Base fee history was not requested";
10297
+ let premium = null;
10298
+ let fees = null;
10299
+ try {
10300
+ const settlementLogs = await client.getContractEvents({
10301
+ address: poolAddress,
10302
+ abi: panopticPoolV2Abi,
10303
+ eventName: "PremiumSettled",
10304
+ args: {
10305
+ user: account,
10306
+ tokenId
10307
+ },
10308
+ fromBlock: mintBlock,
10309
+ toBlock: finalBlock,
10310
+ strict: true
10311
+ });
10312
+ const settled = [];
10313
+ const seen = new Set();
10314
+ for (const log of settlementLogs) {
10315
+ if (log.blockNumber === mintBlock && log.logIndex <= mint.logIndex) continue;
10316
+ if (close && log.blockNumber === finalBlock && log.logIndex >= close.logIndex) continue;
10317
+ const key = `${log.transactionHash}:${log.logIndex}`;
10318
+ if (seen.has(key)) continue;
10319
+ seen.add(key);
10320
+ const amounts = unpack(log.args.settledAmounts);
10321
+ settled.push({
10322
+ blockNumber: log.blockNumber,
10323
+ settled0: amounts.token0,
10324
+ settled1: amounts.token1
10325
+ });
10326
+ }
10327
+ if (close) {
10328
+ const receipt = await client.getTransactionReceipt({ hash: close.transactionHash });
10329
+ const liquidations = parseEventLogs({
10330
+ abi: panopticPoolV2Abi,
10331
+ logs: receipt.logs.filter((log) => log.address.toLowerCase() === poolAddress.toLowerCase()),
10332
+ eventName: "AccountLiquidated"
10333
+ });
10334
+ if (liquidations.some((event) => event.args.liquidatee.toLowerCase() === account.toLowerCase())) throw new Error("Liquidation premium requires haircut reconciliation");
10335
+ for (const packed of close.args.premiaByLeg) {
10336
+ const amounts = unpack(packed);
10337
+ settled.push({
10338
+ blockNumber: finalBlock,
10339
+ settled0: amounts.token0,
10340
+ settled1: amounts.token1
10341
+ });
10342
+ }
10343
+ }
10344
+ const readableBlocks = close ? blockNumbers.filter((block) => block < finalBlock) : blockNumbers;
10345
+ premium = [];
10346
+ for (let i = 0; i < readableBlocks.length; i += 16) {
10347
+ const history = await getStreamiaHistory({
10348
+ client,
10349
+ panopticPoolAddress: poolAddress,
10350
+ account,
10351
+ tokenId,
10352
+ blockNumbers: readableBlocks.slice(i, i + 16),
10353
+ legs: [],
10354
+ poolConfig,
10355
+ includeUniswapFees: false,
10356
+ settledEvents: settled,
10357
+ _meta: end
10358
+ });
10359
+ for (const snapshot of history.snapshots) {
10360
+ const timestamp = snapshot.blockNumber === void 0 ? void 0 : timestamps.get(snapshot.blockNumber);
10361
+ if (timestamp === void 0) throw new Error("Accounting timestamp missing");
10362
+ premium.push({
10363
+ timestamp,
10364
+ ...snapshot.cumulativePanopticPremia
10365
+ });
10366
+ }
10367
+ }
10368
+ if (close) premium.push({
10369
+ timestamp: end.blockTimestamp,
10370
+ ...settled.reduce((sum$1, event) => ({
10371
+ token0: sum$1.token0 + event.settled0,
10372
+ token1: sum$1.token1 + event.settled1
10373
+ }), {
10374
+ token0: 0n,
10375
+ token1: 0n
10376
+ })
10377
+ });
10378
+ const openingAccrual = premium[0];
10379
+ if (!openingAccrual || openingAccrual.timestamp !== start.blockTimestamp) throw new Error("Opening premium snapshot missing");
10380
+ premium = premium.map((snapshot) => ({
10381
+ timestamp: snapshot.timestamp,
10382
+ token0: snapshot.token0 - openingAccrual.token0,
10383
+ token1: snapshot.token1 - openingAccrual.token1
10384
+ }));
10385
+ } catch (error) {
10386
+ premium = null;
10387
+ premiumError = error instanceof Error ? error.message : "Premium history unavailable";
10388
+ }
10389
+ if (includeBaseFees) try {
10390
+ const feeBlocks = close ? blockNumbers.filter((block) => block < finalBlock) : blockNumbers;
10391
+ const data = [];
10392
+ for (let i = 0; i < feeBlocks.length; i += 16) data.push(...await fetchUniswapFeeData(client, feeBlocks.slice(i, i + 16), chunks, poolConfig));
10393
+ let total0 = 0n;
10394
+ let total1 = 0n;
10395
+ fees = [];
10396
+ for (let i = 0; i < data.length; i++) {
10397
+ const current = data[i];
10398
+ for (const chunk of chunks) {
10399
+ if ((current.tickData.get(chunk.lowerTick)?.liquidityGross ?? 0n) === 0n || (current.tickData.get(chunk.upperTick)?.liquidityGross ?? 0n) === 0n) throw new Error("LP range was uninitialized; complete base fee history is unavailable");
10400
+ if (i === 0) continue;
10401
+ const previous = feeGrowthInsideX128(data[i - 1], chunk.lowerTick, chunk.upperTick);
10402
+ const next = feeGrowthInsideX128(current, chunk.lowerTick, chunk.upperTick);
10403
+ if (!previous || !next) throw new Error("Range fee growth missing");
10404
+ if (BigInt.asUintN(256, next.feeGrowthInside0X128 - previous.feeGrowthInside0X128) > BigInt.asUintN(256, current.feeGrowthGlobal0 - data[i - 1].feeGrowthGlobal0) || BigInt.asUintN(256, next.feeGrowthInside1X128 - previous.feeGrowthInside1X128) > BigInt.asUintN(256, current.feeGrowthGlobal1 - data[i - 1].feeGrowthGlobal1)) throw new Error("Range fee growth is inconsistent with pool fee growth");
10405
+ const sign = chunk.isLong ? -1n : 1n;
10406
+ total0 += sign * feesFromFeeGrowthDelta(next.feeGrowthInside0X128, previous.feeGrowthInside0X128, chunk.liquidity);
10407
+ total1 += sign * feesFromFeeGrowthDelta(next.feeGrowthInside1X128, previous.feeGrowthInside1X128, chunk.liquidity);
10408
+ }
10409
+ fees.push({
10410
+ timestamp: metadata[i].blockTimestamp,
10411
+ token0: total0,
10412
+ token1: total1
10413
+ });
10414
+ }
10415
+ } catch (error) {
10416
+ fees = null;
10417
+ feeError = error instanceof Error ? error.message : "Base fee history unavailable";
10418
+ }
10419
+ return {
10420
+ start,
10421
+ end,
10422
+ positionSize: balance.positionSize,
10423
+ closed: close !== void 0,
10424
+ openingTick: BigInt(openingPrice.tick),
10425
+ endingTick: BigInt(endingPrice.tick),
10426
+ premium,
10427
+ fees,
10428
+ premiumError,
10429
+ feeError,
10430
+ accountingSamples: blockNumbers.length,
10431
+ maxAccountingIntervalSeconds: metadata.slice(1).reduce((maximum, meta, index) => {
10432
+ const interval = meta.blockTimestamp - metadata[index].blockTimestamp;
10433
+ return interval > maximum ? interval : maximum;
10434
+ }, 0n)
10435
+ };
10436
+ }
10437
+
10438
+ //#endregion
10439
+ export { DEFAULT_MIN_SWAP_RATIO_BPS, DEFAULT_RECONNECT_CONFIG, MARKET_INDICATOR_PERIODS, REQUIRED_BASE_ERROR_SENTINEL, STRIKE_LADDER_TARGET_STRIKES, VARIANCE_RATIO_LAG, addPendingPosition, addTrackedChunks, apportion, assertCanBurn, assertCanForceExercise, assertCanLiquidate, assertCanMint, assertFresh, assertHealthy, assertLpPositionFunded, assertTradeable, buildCreditWrappedDispatch, buildSfpmSwapCalldata, buildSfpmSwapPlan, buildTemporaryLoanRecoveryDispatch, buildTokenShortfallRecoveryDispatch, calculateAccountGreeksPure, calculateMarketIndicator, calculatePositionVolatilityMetrics, calculateSpreadWad, calculateVarianceProfile, checkCollateralAcrossTicks, classifyStrategyGroups, classifyStrike, cleanupStalePendingPositions, clearPendingPositions, clearTrackedChunks, clearTradeHistory, collateralCurveTicks, collateralRuleKindFor, computeV4PoolId, confirmPendingPosition, convertToAssets, convertToShares, createEventPoller, createEventSubscription, createFlowNeutralTokenId, decodePanopticTokenURI, emptyLiquidateParams, encodePoolKeyBytes, encodeV3PoolKeyBytes, ensureSfpmV3PoolInitialized, estimateBlockNumbers, estimateCollateralBreakdown, estimateCollateralRequired, failPendingPosition, feeGrowthInsideX128, feesFromFeeGrowthDelta, fetchSfpmV3PoolId, fetchUniswapFeeData, getAccountBuyingPower, getAccountGreeks, getAccountHistory, getChunkLiquidities, getChunkSpreads, getClosedPositions, getCollateralCurve, getCollateralCurveInputs, getCollateralRequiredBase, getCollateralSharePrices, getCollateralTotalAssetsBatch, getDeltaHedgeParams, getEnforcedTickLimits, getExecutableLpMaxSize, getFactoryConstructMetadata, getFactoryOwnerOf, getFactoryTokenURI, getGuardianUnlockState, getHedgeLimits, getItmAmounts, getMarginBuffer, getMaxPositionSize, getMaxRedeem, getMaxWithdrawable, getNativeTokenPrice, getNotEnoughTokensError, getOpenPositionPreview, getPanopticPoolAddress, getPanopticPoolFromPoolId, getPendingPositions, getPoolCollateralAddresses, getPoolLiquidities, getPortfolioValue, getPositionChunkData, getPositionEnrichmentData, getPositionValueCurve, getPositionVolatilityHistory, getPriceHistory, getRealizedPnL, getRequiredCreditForITM, getSafeMode, getStreamiaHistory, getSyncStatus, getTrackedChunks, getTradeHistory, getUniswapFeeHistory, getUniswapV3LpPositionState, getUniswapV3PoolFromId, getUniswapV3PoolInfo, getUniswapV3PoolLiquidities, getUniswapV4LpPositionState, getUniswapV4PoolBasicState, getUniswapV4PoolInfo, getUniswapV4PoolKeyFromId, getUniswapV4PoolLiquidities, interpolateBlocks, isGasError, isNonceError, isRetryableRpcError, isolateGroupTokenId, ladderStrikeSequence, logReturns, marketPnlInQuote, marketRiskFromValues, marketScenario, minePoolAddress, minePoolAddressLocalAsync, multicallRead, netLiquidationValueInQuote, optimizeTokenIdRiskPartners, parseCollateralLog, parsePoolLog, positionValueKey, positionValueTicks, prepareIndicatorCandles, preparePositionGamma, preparePositionValueCurve, previewDeposit, previewMint, previewRedeem, previewWithdraw, quoteLiquidation, quoteOneTokenFlow, quoteSfpmSwap, quoteTemporaryLoanRecovery, quoteTokenShortfallRecovery, realizedBeta, removeTrackedChunks, resolveBlockNumbers, resolveLadderStrike, resolvePanopticPoolFromPoolId, resolveUniswapV4PoolKey, saveClosedPosition, scaleCollateralRequired, scanChunks, screenAccountExact, simulateBatchDispatch, simulateClosePosition, simulateDeployNewPool, simulateDeposit, simulateForceExercise, simulateLiquidate, simulateSFPMBurn, simulateSFPMMint, simulateSwapExactIn, simulateSwapExactOut, simulateWithdraw, slippageBpsToTickDistance, valuePositionAccrual, watchEvents };