@panoptic-eng/sdk 1.0.14 → 1.0.15
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.
- package/dist/cow/index.js +3 -3
- package/dist/{cow-CS9QNWLv.js → cow-GmGNOlyp.js} +2 -2
- package/dist/{cow-CS9QNWLv.js.map → cow-GmGNOlyp.js.map} +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/{irm-CzzPOxhR.js → irm-psiA-OZ-.js} +3 -3
- package/dist/{irm-CzzPOxhR.js.map → irm-psiA-OZ-.js.map} +1 -1
- package/dist/panoptic/v2/index.d.ts +2 -2
- package/dist/panoptic/v2/index.d.ts.map +1 -1
- package/dist/panoptic/v2/index.js +8 -7
- package/dist/panoptic/v2/index.js.map +1 -1
- package/dist/{position-DiqNO8a0.js → position-C3Ca4itE.js} +2 -2
- package/dist/{position-DiqNO8a0.js.map → position-C3Ca4itE.js.map} +1 -1
- package/dist/{router-CS84DV2k.js → router-Dd4tGu9L.js} +2 -2
- package/dist/{router-CS84DV2k.js.map → router-Dd4tGu9L.js.map} +1 -1
- package/dist/uniswap/index.js +3 -3
- package/dist/{writes-BjhsHNh-.js → writes-BlCi23qF.js} +39 -2
- package/dist/writes-BlCi23qF.js.map +1 -0
- package/package.json +1 -1
- package/dist/writes-BjhsHNh-.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["params: ResolveBlockNumbersParams","blockNumber: bigint","targetTimestamp: number","low: bigint","high: bigint","params: EstimateBlockNumbersParams","params: MulticallReadParams<TContracts>","results: MulticallResult<unknown>[]","tokenURI: string","startBlock: bigint","endBlock: bigint","points: number","params: GetUniswapV3PoolFromIdParams","params: GetUniswapV4PoolKeyFromIdParams","params: GetEnforcedTickLimitsParams","params: GetChunkLiquiditiesParams","params: GetFactoryTokenURIParams","params: GetFactoryOwnerOfParams","params: GetFactoryConstructMetadataParams","params: GetPanopticPoolAddressParams","params: MinePoolAddressParams","result: readonly [bigint, bigint]","params: SimulateDeployNewPoolParams","result","params: GetPanopticPoolFromPoolIdParams","params: ResolvePanopticPoolFromPoolIdParams","err: unknown","value: bigint","byteLength: number","addr: Address","hex: Hex","factory: Address","salt: bigint","addrInt: bigint","deployerAddress: Address","v3Pool: Address","riskEngine: Address","poolKey: PoolKey","params: MinePoolAddressLocalParams","params: GetAccountPremiaParams","_meta","params: GetPositionsWithPremiaParams","positions: PositionWithPremia[]","legs: TokenIdLeg[]","params: EstimateCollateralRequiredParams","effectiveTick: bigint","params: GetMaxPositionSizeParams","positionIds: bigint[]","params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n tokenId: bigint\n existingPositionIds: bigint[]\n low: bigint\n high: bigint\n precisionDivisor: bigint\n swapAtMint: boolean\n}","positionSize: bigint","params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n tokenId: bigint\n existingPositionIds: bigint[]\n positionSize: bigint\n swapAtMint: boolean\n}","tickLimits: readonly [number, number, number]","tickLimits","params: GetRequiredCreditForITMParams","params: GetMaxWithdrawableParams","params: {\n client: PublicClient\n collateralTrackerAddress: Address\n account: Address\n assets: bigint\n positionIdList: bigint[]\n usePremiaAsCollateral: boolean\n}","client: PublicClient","poolAddress: Address","tokenIndex: 0 | 1","providedAddress?: Address","params: ERC4626PreviewParams","params: GetGuardianUnlockStateParams","params: GetSafeModeParams","params: GetPortfolioValueParams","params: CheckCollateralAcrossTicksParams","MIN_TICK","MAX_TICK","dataPoints: CollateralDataPoint[]","params: OptimizeTokenIdRiskPartnersParams","effectiveTick: bigint","params: GetPoolLiquiditiesParams","TEN","formatRatio","numerator: bigint","denominator: bigint","precision: bigint","bps: bigint","util: bigint","percent: string","config: PoolFormatterConfig","tick: bigint","precision: bigint","price: string","amount: bigint","amount: string","TEN","formatRatio","numerator: bigint","denominator: bigint","precision: bigint","chainId: bigint","address: Address","tokenListId: string","token0Symbol: string","token1Symbol: string","feeBps: bigint","numerator: bigint","denominator: bigint","precision: bigint","address: string","timestamp: bigint","locale?: string","options?: Intl.DateTimeFormatOptions","ms: bigint","minutes","seconds: bigint","blockNumber: bigint","gas: bigint","hash: string","value: bigint","tokenId: bigint","poolId: bigint","formatted: string","wei: bigint","params: GetAccountGreeksParams","targetBlock","_meta","positions: AccountGreeksResult['positions']","params: CalculateAccountGreeksPureParams","totalValue: bigint[]","totalDelta: bigint[]","positionResults: AccountGreeksCurveResult['positions']","posValues: bigint[]","posDeltas: bigint[]","posGammas: bigint[]","MIN_TICK","MAX_TICK","Q128","convert0to1","amount: bigint","sqrtPriceX96: bigint","convert1to0","params: GetMarginBufferParams","collateralToken0: Address","collateralToken1: Address","calls: MulticallBlockCall[]","denominatedInToken: 0 | 1","lowerLiquidationTick: bigint | null","upperLiquidationTick: bigint | null","liquidationDistance: bigint | null","params: GetDeltaHedgeParamsInput","currentTick: bigint","tickSpacing: bigint","poolMeta: BlockMeta","primaryAsset: bigint","currentDelta: bigint","hedgeLeg: LegConfig","simulatedTickAfter: bigint | undefined","collateralAddresses: [Address, Address]","blockNumber: bigint","client: Client","e: unknown","client: Client","collateralTrackerAddresses: Address[]","chainId: number","blockNumber?: bigint","amount: bigint","sqrtPriceX96: bigint","params: GetAccountBuyingPowerParams","collateralToken0: Address","collateralToken1: Address","calls: MulticallBlockCall[]","params: GetOpenPositionPreviewParams","params: GetNativeTokenPriceParams","params: GetAccountHistoryParams","trades: AccountTrade[]","params: GetUniswapFeeHistoryParams","_meta","initialFees0: bigint | null","initialFees1: bigint | null","snapshots: UniswapFeeSnapshot[]","client: PublicClient","blockNumbers: (bigint | undefined)[]","legs: StreamiaLeg[]","poolConfig: PoolVersionConfig","blockData: UniswapBlockData","blockNumber: bigint | undefined","uniqueTicks: number[]","poolAddress: Address","stateViewAddress: Address","poolId: `0x${string}`","params: GetStreamiaHistoryParams","_meta","initialUniswapFees0: bigint | null","initialUniswapFees1: bigint | null","snapshots: StreamiaSnapshot[]","params: GetUniswapV3PoolInfoParams","startTick: number","tickSpacing: number","nTicks: bigint","params: GetUniswapV3PoolLiquiditiesParams","poolKey: UniswapV4PoolKey","_params: ResolveUniswapV4PoolKeyParams","params: GetUniswapV4PoolBasicStateParams","client: PublicClient","address: Address","blockNumber?: bigint","params: GetUniswapV4PoolInfoParams","params: GetUniswapV4PoolLiquiditiesParams","params: GetPriceHistoryParams","_meta","snapshots: PriceSnapshot[]","client: PublicClient","blockNumber: bigint | undefined","poolConfig: PoolVersionConfig","tokenId: bigint","callName: string","cause?: unknown","params: GetPositionEnrichmentDataParams","client: PublicClient","queryAddress: Address","positions: PositionInput[]","currentTick: number","blockNumber: bigint | undefined","_meta: BlockMeta","panopticQueryAbi","entries: [string, PositionEnrichmentResult][]","params: GetSyncStatusParams","params: SaveClosedPositionParams","history: ClosedPosition[]","params: GetTradeHistoryParams","params: GetRealizedPnLParams","params: Omit<\n GetTradeHistoryParams,\n 'limit' | 'offset' | 'closureReason' | 'fromBlock' | 'toBlock'\n >","chunk: LiquidityChunkKey","key: string","params: AddTrackedChunksParams","trackedKeys: Set<string>","params: RemoveTrackedChunksParams","params: GetTrackedChunksParams","params: GetChunkSpreadsParams","netLiquidity: bigint","removedLiquidity: bigint","vegoid: bigint","params: ScanChunksParams","chunks: ScannedChunk[]","params: GetPositionChunkDataParams","_meta","positions: PositionChunkData[]","legs: LegChunkData[]","params: AddPendingPositionParams","pending: PendingPosition[]","params: GetPendingPositionsParams","params: ConfirmPendingPositionParams","params: FailPendingPositionParams","currentBlock: bigint","maxAgeBlocks: bigint","params: EventReconstructionParams","mintEvents: MintEvent[]","burnEvents: BurnEvent[]","mint","openPositions: bigint[]","closedPositions: bigint[]","client: PublicClient","poolAddress: Address","foundBlock: bigint | null","scope?: string","client: unknown","storage: unknown","atTick?: bigint","chainId: bigint","poolAddress: Address","tokenId: bigint","account: Address","atTick: bigint","collateralTrackerAddress: Address","positionIdList: bigint[]","totalAssets: bigint","token: Address","owner: Address","spender: Address","tracker: Address","operation: string","amount: bigint","poolAddress: string","timestampsHash: string","rangeHash: string","poolAddress: Address","options?: QueryOptions","tokenIndex: 0 | 1","params: { queryAddress: Address; startTick: bigint; nTicks: bigint }","params: { sfpmAddress: Address }","owner: Address","tokenId: bigint","tokenIds: bigint[]","owner?: Address","account?: Address","queryAddress: Address","options?: QueryOptions & { atTick?: bigint; includePendingPremium?: boolean }","options?: QueryOptions & { atTick?: bigint }","atTicks: bigint[]","amount: bigint","positionSize: bigint","options?: QueryOptions & {\n existingPositionIds?: bigint[]\n swapAtMint?: boolean\n precisionPct?: number\n }","atTick?: bigint","collateralTrackerAddress: Address","positionIdList: bigint[]","totalAssets: bigint","options?: QueryOptions & { client?: PublicClient }","account: Address | undefined","existingPositionIds: bigint[]","tickLimitLow: bigint","tickLimitHigh: bigint","options?: QueryOptions & {\n spreadLimit?: bigint\n swapAtMint?: boolean\n usePremiaAsCollateral?: boolean\n blockNumber?: bigint\n }","params?: OmitFactoryClient<GetPanopticPoolAddressParams>","params?: OmitFactoryClient<GetFactoryTokenURIParams>","params?: OmitFactoryClient<GetFactoryOwnerOfParams>","params: MinePoolAddressLocalParams","params?: OmitFactoryClient<GetFactoryConstructMetadataParams>","params?: OmitMineClient<SimulateDeployNewPoolParams>","timeRange: PriceHistoryTimeRange","client: PublicClient","poolConfig: PoolVersionConfig","panopticPoolAddress: Address","account: Address","legs: StreamiaLeg[]","options?: QueryOptions & {\n includeUniswapFees?: boolean\n settledEvents?: Array<{ blockNumber: bigint; settled0: bigint; settled1: bigint }>\n }","poolAddress: Address | undefined","queryAddress: Address | undefined","args: { startTick: number; nTicks: bigint } | undefined","poolManager: Address | undefined","poolId: `0x${string}` | undefined","args?: { fromBlock?: bigint; chunkSize?: bigint }","stateViewAddress: Address | undefined","poolKey: UniswapV4PoolKey | undefined","args: { tickSpacing: number; startTick: number; nTicks: bigint } | undefined","panopticPoolAddress: Address | undefined","token0Decimals: bigint","token1Decimals: bigint","nativeIsToken0: boolean","params?: {\n account: Address\n token: Address\n amount: bigint\n slippageBps: bigint\n existingPositionIds: bigint[]\n }","builderCode: bigint | undefined","params: MutationEffectParams","keys: (readonly string[])[]","chainId: bigint","token: Address","owner: Address","spender: Address","params: Pick<MutationEffectParams, 'chainId' | 'poolAddress'>","requireWallet","inputs: WalletInputs","queryClient: QueryClient","keysToInvalidate: readonly (readonly string[])[]","params: OmitInjected<ApproveParams>","poolAddress: Address","params: OmitInjectedWithPool<ApprovePoolParams>","params: OmitInjected<DepositParams>","params: OmitInjected<WithdrawParams>","params: OmitInjected<WrapXstockParams>","params: OmitInjected<UnwrapXstockParams>","params: OmitInjected<WrapEthParams>","params: OmitInjected<UnwrapWethParams>","params: OmitInjected<MintParams>","params: OmitInjected<RedeemParams>","params: OmitInjected<WithdrawWithPositionsParams>","params: OmitInjectedWithPool<OpenPositionParams>","params: OmitInjectedWithPool<ClosePositionParams>","params: OmitInjectedWithPool<RollPositionParams>","params: OmitInjectedWithPool<LiquidateParams>","params: Omit<\n ForceExerciseParams,\n 'client' | 'walletClient' | 'account' | 'poolAddress' | 'chainId' | 'storage'\n >","params: OmitInjectedWithPool<SettleParams>","params?: OmitInjectedWithPool<PokeOracleParams>","params: OmitInjectedWithPool<DispatchParams>","params: OmitInjectedWithPool<ExecuteBatchDispatchParams>","params: OmitInjected<DeployNewPoolParams>","params: OmitInjectedWithPoolAndChain<SwapExactOutParams>","params: OmitInjectedWithPoolAndChain<SupplyParams>","params: OmitInjectedWithPoolAndChain<UnsupplyParams>","params: OmitInjectedWithPoolAndChain<BorrowParams>","params: OmitInjectedWithPoolAndChain<RepayParams>","params: OmitInjectedWithPoolAndChain<SmartRepayParams>","params: OmitInjectedWithPoolAndChain<SwapExactInParams>","params: SimulateDispatchParams","tokenFlow: TokenFlow","data: Hex | undefined","data","data: DispatchSimulation","params: SimulateBatchDispatchParams","params: SimulateClosePositionParams","tickLimits: readonly [number, number, number]","tickLimits","data: ClosePositionSimulation","params: SimulateForceExerciseParams","emptyTokenFlow: TokenFlow","_meta","data: ForceExerciseSimulation","tokenFlow: TokenFlow","params: SimulateLiquidateParams","emptyTokenFlow: TokenFlow","_meta","data: LiquidateSimulation","tokenFlow: TokenFlow","params: SimulateSettleParams","tokenFlow: TokenFlow","forfeitAmounts: [bigint, bigint] | undefined","data: SettleSimulation","params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n positionIdList: bigint[]\n tokenId: bigint\n dispatchCallData: Hex\n blockNumber: bigint\n}","data: Hex","params: SimulateDepositParams","data: DepositSimulation","params: SimulateWithdrawParams","data: WithdrawSimulation","poolKey: PoolKey","v3PoolAddress: Address","params: SimulateSFPMParams","resolveTokenIndex","tokenAddress: Address","token0: Address","token1: Address","buildUniqueLoan","poolId: bigint","asset: bigint","tokenType: bigint","currentTick: bigint","tickSpacing: bigint","existingPositionIds: bigint[]","loanTokenId: bigint","amount: bigint","mintTickLimits: readonly [number, number, number]","burnTickLimits: readonly [number, number, number]","tokenFlow: TokenFlow","tokenOutIndex: bigint","params: SimulateSwapExactOutParams","params: SimulateSwapExactInParams","poolAddress: Address","params?: OmitClientAndPool<SimulateOpenPositionParams>","params?: OmitClientAndPool<SimulateClosePositionParams>","params?: OmitClient<SimulateDepositParams>","params?: OmitClient<SimulateWithdrawParams>","params?: OmitClientAndPool<SimulateLiquidateParams>","params?: OmitClientAndPool<SimulateForceExerciseParams>","params?: OmitClientAndPool<SimulateSettleParams>","params?: OmitClientAndPool<SimulateBatchDispatchParams>","params?: OmitClientAndPool<SimulateDispatchParams>","params?: OmitClient<SimulateSFPMParams>","params?: OmitClientAndPool<SimulateSwapExactOutParams>","params?: OmitClientAndPool<SimulateSwapExactInParams>","requireWallet","walletClient?: WalletClient","account?: Address","poolAddress: Address","params?: OmitClientPoolAndChain<QuoteSwapExactInViaRouterParams>","params?: OmitClientPoolAndChain<QuoteSwapExactOutViaRouterParams>","params?: OmitInjectedWithChain<CheckRouterApprovalParams>","params: OmitInjectedWithPoolAndChain<SwapExactInViaRouterParams>","params: OmitInjectedWithPoolAndChain<SwapExactOutViaRouterParams>","params: OmitInjectedWithChain<ApproveErc20ForPermit2Params>","params: OmitInjectedWithChain<ApproveRouterViaPermit2Params>","walletClient?: WalletClient","account?: Address","params?: OmitChainAndFrom<QuoteCowSwapParams>","params?: OmitClientOnly<CheckCowApprovalParams>","params: OmitInjectedWithChain<ApproveErc20ForCowParams>","params: Omit<SignAndSubmitCowOrderParams, 'walletClient' | 'account' | 'chainId'>","orderUid?: Hex","params: Omit<CancelCowOrderParams, 'walletClient' | 'account' | 'chainId'>","poolAddress: Address","params?: { fromBlock?: bigint; toBlock?: bigint }","position: PendingPosition","tokenId: bigint","txHash: Hash","POOL_EVENT_NAMES: Record<string, PanopticEventType>","COLLATERAL_EVENT_NAMES: Record<string, PanopticEventType>","RISK_ENGINE_EVENT_NAMES: Record<string, PanopticEventType>","SFPM_EVENT_NAMES: Record<string, PanopticEventType>","POOL_MANAGER_EVENT_NAMES: Record<string, PanopticEventType>","log: DecodedLog","eventName: string","params: WatchEventsParams","unwatchFns: (() => void)[]","events: PanopticEvent[]","DEFAULT_RECONNECT_CONFIG: ReconnectConfig","params: CreateEventSubscriptionParams","config: ReconnectConfig","unwatchFns: (() => void)[]","reconnectTimeout: ReturnType<typeof setTimeout> | null","a: PanopticEvent","b: PanopticEvent","event: PanopticEvent","poolEventTypes: PanopticEventType[]","collateralEventTypes: PanopticEventType[]","riskEngineEventTypes: PanopticEventType[]","sfpmEventTypes: PanopticEventType[]","poolManagerEventTypes: PanopticEventType[]","fromBlock: bigint","toBlock: bigint","allEvents: PanopticEvent[]","parseLog: (log: DecodedLog) => PanopticEvent | null","events: PanopticEvent[]","eventType: PanopticEventType","error: Error","params: CreateEventPollerParams","pollTimeout: ReturnType<typeof setTimeout> | null","poolEventTypes: PanopticEventType[]","collateralEventTypes: PanopticEventType[]","riskEngineEventTypes: PanopticEventType[]","sfpmEventTypes: PanopticEventType[]","poolManagerEventTypes: PanopticEventType[]","from: bigint","to: bigint","allEvents: PanopticEvent[]","poolAddress: Address","eventTypes: PanopticEventType[] | undefined","onEvent: (events: PanopticEvent[]) => void","options?: {\n enabled?: boolean\n collateralTracker0?: Address\n collateralTracker1?: Address\n riskEngineAddress?: Address\n sfpmAddress?: Address\n poolManagerAddress?: Address\n onError?: (error: Error) => void\n }","options?: {\n enabled?: boolean\n collateralTracker0?: Address\n collateralTracker1?: Address\n riskEngineAddress?: Address\n sfpmAddress?: Address\n poolManagerAddress?: Address\n onError?: (error: Error) => void\n onReconnect?: (attempt: bigint, nextDelayMs: bigint) => void\n onConnected?: () => void\n }","handle: EventSubscriptionHandle","options?: {\n enabled?: boolean\n intervalMs?: bigint\n collateralTracker0?: Address\n collateralTracker1?: Address\n riskEngineAddress?: Address\n sfpmAddress?: Address\n poolManagerAddress?: Address\n onError?: (error: Error) => void\n }","poller: EventPoller"],"sources":["../../../src/panoptic/v2/clients/blocksByTimestamp.ts","../../../src/panoptic/v2/clients/multicall.ts","../../../src/panoptic/v2/utils/factory.ts","../../../src/panoptic/v2/utils/interpolateBlocks.ts","../../../src/panoptic/v2/reads/sfpm.ts","../../../src/panoptic/v2/reads/factory.ts","../../../src/panoptic/v2/reads/minePoolAddressLocal.ts","../../../src/panoptic/v2/reads/premia.ts","../../../src/panoptic/v2/reads/collateralEstimate.ts","../../../src/panoptic/v2/reads/erc4626.ts","../../../src/panoptic/v2/reads/guardian.ts","../../../src/panoptic/v2/reads/safeMode.ts","../../../src/panoptic/v2/reads/queryUtils.ts","../../../src/panoptic/v2/reads/liquidity.ts","../../../src/panoptic/v2/formatters/percentage.ts","../../../src/panoptic/v2/formatters/poolFormatters.ts","../../../src/panoptic/v2/formatters/tokenList.ts","../../../src/panoptic/v2/formatters/display.ts","../../../src/panoptic/v2/reads/accountGreeks.ts","../../../src/panoptic/v2/reads/margin.ts","../../../src/panoptic/v2/reads/hedge.ts","../../../src/panoptic/v2/reads/collateralSharePrice.ts","../../../src/panoptic/v2/reads/collateralTotalAssets.ts","../../../src/panoptic/v2/reads/buyingPower.ts","../../../src/panoptic/v2/reads/openPositionPreview.ts","../../../src/panoptic/v2/reads/nativeTokenPrice.ts","../../../src/panoptic/v2/reads/history.ts","../../../src/panoptic/v2/reads/uniswapFeeHistory.ts","../../../src/panoptic/v2/reads/streamiaHistory.ts","../../../src/panoptic/v2/reads/uniswapPool.ts","../../../src/panoptic/v2/reads/priceHistory.ts","../../../src/panoptic/v2/reads/enrichment.ts","../../../src/panoptic/v2/sync/getSyncStatus.ts","../../../src/panoptic/v2/sync/tradeHistory.ts","../../../src/panoptic/v2/sync/chunkTracking.ts","../../../src/panoptic/v2/sync/pendingPositions.ts","../../../src/panoptic/v2/sync/eventReconstruction.ts","../../../src/panoptic/v2/react/cacheScopes.ts","../../../src/panoptic/v2/react/provider.tsx","../../../src/panoptic/v2/react/queryKeys.ts","../../../src/panoptic/v2/react/hooks/reads.ts","../../../src/panoptic/v2/react/mutationEffects.ts","../../../src/panoptic/v2/react/hooks/writes.ts","../../../src/panoptic/v2/simulations/simulateDispatch.ts","../../../src/panoptic/v2/simulations/simulateBatchDispatch.ts","../../../src/panoptic/v2/simulations/simulateClosePosition.ts","../../../src/panoptic/v2/simulations/simulateForceExercise.ts","../../../src/panoptic/v2/simulations/simulateLiquidate.ts","../../../src/panoptic/v2/simulations/simulateSettle.ts","../../../src/panoptic/v2/simulations/simulateVault.ts","../../../src/panoptic/v2/simulations/sfpm.ts","../../../src/panoptic/v2/simulations/simulateSwap.ts","../../../src/panoptic/v2/react/hooks/simulations.ts","../../../src/panoptic/v2/react/hooks/uniswapRouter.ts","../../../src/panoptic/v2/react/hooks/cowSwap.ts","../../../src/panoptic/v2/react/hooks/sync.ts","../../../src/panoptic/v2/abis/poolManager.ts","../../../src/panoptic/v2/events/watchEvents.ts","../../../src/panoptic/v2/events/subscription.ts","../../../src/panoptic/v2/events/poller.ts","../../../src/panoptic/v2/react/hooks/events.ts"],"sourcesContent":["/**\n * Timestamp-to-block resolution via RPC binary search.\n * No subgraph dependency — uses only eth_getBlockByNumber.\n * @module v2/clients/blocksByTimestamp\n */\n\nimport type { PublicClient } from 'viem'\n\n/**\n * Parameters for resolveBlockNumbers.\n */\nexport interface ResolveBlockNumbersParams {\n /** viem PublicClient */\n client: PublicClient\n /** Array of Unix timestamps (seconds) to resolve to block numbers */\n timestamps: number[]\n}\n\n/**\n * Resolve an array of Unix timestamps to the closest block numbers via RPC binary search.\n *\n * All binary searches run in parallel, sharing an in-flight-deduped block cache\n * so concurrent searches for nearby timestamps avoid redundant RPC calls.\n *\n * @param params - The parameters\n * @returns Array of block numbers in the same order as the input timestamps\n *\n * @example\n * ```typescript\n * const blocks = await resolveBlockNumbers({\n * client,\n * timestamps: [1700000000, 1700003600, 1700007200],\n * })\n * // blocks: [18500000n, 18500300n, 18500600n]\n * ```\n */\nexport async function resolveBlockNumbers(params: ResolveBlockNumbersParams): Promise<bigint[]> {\n const { client, timestamps } = params\n\n if (timestamps.length === 0) return []\n\n const latestBlock = await client.getBlock({ blockTag: 'latest', includeTransactions: false })\n const latestNumber = latestBlock.number\n const latestTimestamp = Number(latestBlock.timestamp)\n\n // Cache + in-flight dedup: avoids redundant RPC calls across parallel searches\n const cache = new Map<bigint, number>()\n cache.set(latestNumber, latestTimestamp)\n cache.set(0n, 0) // genesis is always timestamp 0 (close enough)\n\n const inflight = new Map<bigint, Promise<number>>()\n\n function getTimestamp(blockNumber: bigint): Promise<number> {\n const cached = cache.get(blockNumber)\n if (cached !== undefined) return Promise.resolve(cached)\n\n const existing = inflight.get(blockNumber)\n if (existing) return existing\n\n const promise = client.getBlock({ blockNumber, includeTransactions: false }).then((block) => {\n const ts = Number(block.timestamp)\n cache.set(blockNumber, ts)\n inflight.delete(blockNumber)\n return ts\n })\n inflight.set(blockNumber, promise)\n return promise\n }\n\n /**\n * Binary search for the last block whose timestamp <= targetTimestamp.\n */\n async function searchBlock(targetTimestamp: number, low: bigint, high: bigint): Promise<bigint> {\n // Clamp: if target is beyond latest, return latest\n if (targetTimestamp >= latestTimestamp) return latestNumber\n\n while (high - low > 1n) {\n const mid = (low + high) / 2n\n const midTs = await getTimestamp(mid)\n\n if (midTs <= targetTimestamp) {\n low = mid\n } else {\n high = mid\n }\n }\n\n return low\n }\n\n // Run all binary searches in parallel — shared cache deduplicates common midpoints\n const results = await Promise.all(timestamps.map((ts) => searchBlock(ts, 0n, latestNumber)))\n\n return results\n}\n\n/**\n * Parameters for estimateBlockNumbers.\n */\nexport interface EstimateBlockNumbersParams {\n /** viem PublicClient */\n client: PublicClient\n /** Array of Unix timestamps (seconds) to resolve to block numbers */\n timestamps: number[]\n /**\n * Bootstrap block-time used only to pick the anchor block (seconds).\n * The final estimate uses the *measured* rate between latest and anchor,\n * so this only affects which sample point we draw — not accuracy on the\n * sampled window. Default 12 (Ethereum L1).\n */\n fallbackBlockTimeSec?: number\n}\n\n/**\n * Estimate block numbers for the given Unix timestamps using a 2-RPC linear\n * extrapolation. Trades binary-search accuracy (~25 RPCs) for ~2 RPCs.\n *\n * Suitable for chart-style use cases where the consumer plots tens-to-hundreds\n * of evenly-spaced points and a ±N-block error is invisible. Not suitable when\n * exact block correspondence is required (e.g. event log ranges).\n *\n * Algorithm:\n * 1. Fetch `latest` block.\n * 2. Use `fallbackBlockTimeSec` to estimate an anchor block roughly co-temporal\n * with the *earliest* requested timestamp.\n * 3. Fetch the anchor block.\n * 4. Compute the measured average block time over [anchor, latest].\n * 5. Linearly extrapolate every requested timestamp from `latest`.\n *\n * If the sampled window is degenerate (e.g. anchor too close to latest, or\n * timestamps near genesis), falls back to {@link resolveBlockNumbers}.\n */\nexport async function estimateBlockNumbers(params: EstimateBlockNumbersParams): Promise<bigint[]> {\n const { client, timestamps, fallbackBlockTimeSec = 12 } = params\n\n if (timestamps.length === 0) return []\n\n const latest = await client.getBlock({ blockTag: 'latest', includeTransactions: false })\n const latestNum = latest.number\n const latestTs = Number(latest.timestamp)\n\n const earliest = Math.min(...timestamps)\n const secAgoMax = Math.max(0, latestTs - earliest)\n\n // All requested timestamps are now-or-future\n if (secAgoMax === 0) return timestamps.map(() => latestNum)\n\n const blocksBackEst = BigInt(Math.floor(secAgoMax / fallbackBlockTimeSec))\n const anchorNum = blocksBackEst >= latestNum ? 1n : latestNum - blocksBackEst\n const anchor = await client.getBlock({\n blockNumber: anchorNum,\n includeTransactions: false,\n })\n\n const numDelta = latestNum - anchor.number\n const tsDelta = latestTs - Number(anchor.timestamp)\n\n // Degenerate sample window — fall back to exact resolution.\n if (numDelta <= 0n || tsDelta <= 0) {\n return resolveBlockNumbers({ client, timestamps })\n }\n\n const avgBlockTimeSec = tsDelta / Number(numDelta)\n\n return timestamps.map((ts) => {\n const secAgo = latestTs - ts\n if (secAgo <= 0) return latestNum\n const blocksAgo = BigInt(Math.round(secAgo / avgBlockTimeSec))\n return blocksAgo >= latestNum ? 1n : latestNum - blocksAgo\n })\n}\n","/**\n * Multicall utilities for the Panoptic v2 SDK.\n * Uses viem's built-in multicall for same-block consistency.\n * @module v2/clients/multicall\n */\n\nimport type { Abi, Address, ContractFunctionArgs, ContractFunctionName, PublicClient } from 'viem'\n\nimport type { BlockMeta } from '../types'\nimport { getBlockMeta } from './blockMeta'\n\n/**\n * A contract call to include in a multicall batch.\n */\nexport interface MulticallContract<\n TAbi extends Abi = Abi,\n TFunctionName extends ContractFunctionName<TAbi, 'pure' | 'view'> = ContractFunctionName<\n TAbi,\n 'pure' | 'view'\n >,\n> {\n /** Contract address */\n address: Address\n /** Contract ABI */\n abi: TAbi\n /** Function name to call */\n functionName: TFunctionName\n /** Function arguments */\n args?: ContractFunctionArgs<TAbi, 'pure' | 'view', TFunctionName>\n}\n\n/**\n * Parameters for multicallRead.\n */\nexport interface MulticallReadParams<TContracts extends readonly MulticallContract[]> {\n /** viem PublicClient */\n client: PublicClient\n /** Array of contract calls to batch */\n contracts: TContracts\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Whether to allow failures (default: false) */\n allowFailure?: boolean\n}\n\n/**\n * Result type for a single multicall contract result.\n */\nexport type MulticallResult<T> =\n | { status: 'success'; result: T }\n | { status: 'failure'; error: Error }\n\n/**\n * Perform a batched multicall read with block metadata.\n * All calls are executed at the same block for consistency.\n *\n * @param params - The multicall parameters\n * @returns Results array with block metadata\n */\nexport async function multicallRead<TContracts extends readonly MulticallContract[]>(\n params: MulticallReadParams<TContracts>,\n): Promise<{\n results: MulticallResult<unknown>[]\n _meta: BlockMeta\n}> {\n const { client, contracts, blockNumber, allowFailure = false } = params\n\n // Get the block number to use (latest if not specified)\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n\n // Execute multicall and get block meta in parallel\n const [multicallResults, _meta] = await Promise.all([\n client.multicall({\n contracts: contracts as unknown as Parameters<typeof client.multicall>['0']['contracts'],\n blockNumber: targetBlockNumber,\n allowFailure: true, // Always allow failure internally to handle gracefully\n }),\n getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // Map results to our format\n const results: MulticallResult<unknown>[] = multicallResults.map((result) => {\n if (result.status === 'success') {\n return { status: 'success' as const, result: result.result }\n } else {\n // If allowFailure is false and we have a failure, throw\n if (!allowFailure) {\n throw result.error\n }\n return { status: 'failure' as const, error: result.error }\n }\n })\n\n return { results, _meta }\n}\n","/**\n * Factory utility functions for the Panoptic v2 SDK.\n * @module v2/utils/factory\n */\n\n/**\n * Decoded Panoptic NFT metadata from a base64-encoded token URI.\n */\nexport type PanopticNFTMetadata = {\n name: string\n description: string\n attributes: [\n {\n trait_type: 'Rarity'\n value: string\n },\n {\n trait_type: 'Strategy'\n value: string\n },\n {\n trait_type: 'ChainId'\n value: string\n },\n ]\n image: string\n}\n\n/**\n * Decode a base64-encoded Panoptic NFT token URI into metadata.\n *\n * @param tokenURI - The base64-encoded data URI string\n * @returns Parsed NFT metadata object, or undefined if input is invalid\n */\nexport function decodePanopticTokenURI(tokenURI: string): PanopticNFTMetadata | undefined {\n if (tokenURI === undefined || tokenURI === '') {\n return undefined\n }\n const parts = tokenURI.split('data:application/json;base64,')\n if (parts.length < 2 || parts[1] === '') {\n return undefined\n }\n try {\n const decoded = atob(parts[1])\n return JSON.parse(decoded) as PanopticNFTMetadata\n } catch {\n return undefined\n }\n}\n","/**\n * Evenly-spaced block number interpolation utility.\n * @module v2/utils/interpolateBlocks\n */\n\nimport { InvalidHistoryRangeError } from '../errors/sdk'\n\n/**\n * Generate evenly-spaced block numbers between start and end (pure math, no RPC).\n *\n * @param startBlock - First block in the range\n * @param endBlock - Last block in the range\n * @param points - Number of evenly-spaced data points to generate\n * @returns Array of interpolated block numbers\n *\n * @throws {InvalidHistoryRangeError} if startBlock > endBlock or points < 0\n */\nexport function interpolateBlocks(startBlock: bigint, endBlock: bigint, points: number): bigint[] {\n if (!Number.isFinite(points) || !Number.isSafeInteger(points)) {\n throw new InvalidHistoryRangeError(`points must be a finite safe integer, got ${points}`)\n }\n if (points < 0) {\n throw new InvalidHistoryRangeError(`points must be >= 0, got ${points}`)\n }\n if (startBlock > endBlock) {\n throw new InvalidHistoryRangeError(\n `startBlock (${startBlock}) must be <= endBlock (${endBlock})`,\n )\n }\n if (points === 0) return []\n if (points === 1) return [endBlock]\n const range = endBlock - startBlock\n return Array.from(\n { length: points },\n (_, i) => startBlock + (range * BigInt(i)) / BigInt(points - 1),\n )\n}\n","/**\n * SFPM read functions — poolId resolution, enforced tick limits, chunk liquidity.\n *\n * @module v2/reads/sfpm\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport {\n semiFungiblePositionManagerV3Abi,\n semiFungiblePositionManagerV4Abi,\n} from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { ChunkLimitError } from '../errors'\nimport type { BlockMeta, PoolKey } from '../types'\nimport { MAX_TRACKED_CHUNKS } from '../utils/constants'\n\n// ---------------------------------------------------------------------------\n// getUniswapV3PoolFromId\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for {@link getUniswapV3PoolFromId}.\n */\nexport interface GetUniswapV3PoolFromIdParams {\n /** Public client */\n client: PublicClient\n /** SemiFungiblePositionManagerV3 address */\n sfpmAddress: Address\n /** The SFPM pool identifier (uint64) */\n poolId: bigint\n}\n\n/**\n * Resolve an SFPM poolId to its corresponding Uniswap V3 pool address.\n *\n * Calls `SemiFungiblePositionManagerV3.getUniswapV3PoolFromId(poolId)`.\n */\nexport async function getUniswapV3PoolFromId(\n params: GetUniswapV3PoolFromIdParams,\n): Promise<Address> {\n const { client, sfpmAddress, poolId } = params\n return client.readContract({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV3Abi,\n functionName: 'getUniswapV3PoolFromId',\n args: [poolId],\n })\n}\n\n// ---------------------------------------------------------------------------\n// getUniswapV4PoolKeyFromId\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for {@link getUniswapV4PoolKeyFromId}.\n */\nexport interface GetUniswapV4PoolKeyFromIdParams {\n /** Public client */\n client: PublicClient\n /** SemiFungiblePositionManagerV4 address */\n sfpmAddress: Address\n /** The SFPM pool identifier (uint64) */\n poolId: bigint\n}\n\n/**\n * Resolve an SFPM poolId to its corresponding Uniswap V4 pool key.\n *\n * Calls `SemiFungiblePositionManagerV4.getUniswapV4PoolKeyFromId(poolId)`.\n */\nexport async function getUniswapV4PoolKeyFromId(\n params: GetUniswapV4PoolKeyFromIdParams,\n): Promise<PoolKey> {\n const { client, sfpmAddress, poolId } = params\n const raw = await client.readContract({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n functionName: 'getUniswapV4PoolKeyFromId',\n args: [poolId],\n })\n return {\n currency0: raw.currency0,\n currency1: raw.currency1,\n fee: BigInt(raw.fee),\n tickSpacing: BigInt(raw.tickSpacing),\n hooks: raw.hooks,\n }\n}\n\n// ---------------------------------------------------------------------------\n// getEnforcedTickLimits\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for getEnforcedTickLimits.\n */\nexport interface GetEnforcedTickLimitsParams {\n /** viem PublicClient */\n client: PublicClient\n /** SFPM address (from getPool().metadata.sfpmAddress) */\n sfpmAddress: Address\n /** Encoded pool ID (from getPool().poolId) */\n poolId: bigint\n}\n\n/**\n * Result from getEnforcedTickLimits.\n */\nexport interface EnforcedTickLimits {\n minEnforcedTick: number\n maxEnforcedTick: number\n}\n\n/**\n * Get the enforced tick limits for a pool from the SFPM.\n *\n * @param params - The parameters\n * @returns The min and max enforced ticks\n */\nexport async function getEnforcedTickLimits(\n params: GetEnforcedTickLimitsParams,\n): Promise<EnforcedTickLimits> {\n const { client, sfpmAddress, poolId } = params\n\n const [minTick, maxTick] = await client.readContract({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n functionName: 'getEnforcedTickLimits',\n args: [poolId],\n })\n\n return {\n minEnforcedTick: minTick,\n maxEnforcedTick: maxTick,\n }\n}\n\n// ---------------------------------------------------------------------------\n// getChunkLiquidities\n// ---------------------------------------------------------------------------\n\nexport interface ChunkInput {\n /** Owner address (panopticPool address for Panoptic chunks) */\n owner: Address\n /** 0 or 1 */\n tokenType: bigint\n tickLower: bigint\n tickUpper: bigint\n}\n\nexport interface ChunkLiquidityResult {\n /** Liquidity currently deployed in Uniswap */\n netLiquidity: bigint\n /** Liquidity removed by long holders */\n removedLiquidity: bigint\n /** Total liquidity deposited by shorts (net + removed) */\n totalLiquidity: bigint\n /** Alias for totalLiquidity (shorts deposited all of it) */\n shortLiquidity: bigint\n /** Alias for removedLiquidity (longs removed this much) */\n longLiquidity: bigint\n}\n\nexport interface GetChunkLiquiditiesParams {\n client: PublicClient\n /** SFPM address */\n sfpmAddress: Address\n /** Pool key bytes (from getPool().metadata.poolKeyBytes) */\n poolKeyBytes: `0x${string}`\n /** Chunks to query */\n chunks: ChunkInput[]\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\nexport interface GetChunkLiquiditiesResult {\n /** One result per input chunk */\n results: ChunkLiquidityResult[]\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Fetch liquidity breakdown for a batch of chunks via SFPM.getAccountLiquidity().\n *\n * Uses multicall for efficiency. Returns one result per input chunk,\n * along with block metadata for freshness tracking.\n */\nexport async function getChunkLiquidities(\n params: GetChunkLiquiditiesParams,\n): Promise<GetChunkLiquiditiesResult> {\n const { client, sfpmAddress, poolKeyBytes, chunks } = params\n\n if (chunks.length > MAX_TRACKED_CHUNKS) {\n throw new ChunkLimitError(BigInt(chunks.length), 0n)\n }\n\n const _meta = params._meta ?? (await getBlockMeta({ client }))\n\n if (chunks.length === 0) return { results: [], _meta }\n\n // Batch all getAccountLiquidity calls\n const multicallResults = await client.multicall({\n contracts: chunks.map((chunk) => ({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n functionName: 'getAccountLiquidity' as const,\n args: [\n poolKeyBytes,\n chunk.owner,\n chunk.tokenType,\n Number(chunk.tickLower),\n Number(chunk.tickUpper),\n ],\n })),\n allowFailure: true,\n })\n\n const results = multicallResults.map((result) => {\n if (result.status === 'failure') {\n return {\n netLiquidity: 0n,\n removedLiquidity: 0n,\n totalLiquidity: 0n,\n shortLiquidity: 0n,\n longLiquidity: 0n,\n }\n }\n\n const packed = result.result as bigint\n // LeftRightUnsigned: right 128 bits = netLiquidity, left 128 bits = removedLiquidity\n const netLiquidity = packed & ((1n << 128n) - 1n)\n const removedLiquidity = packed >> 128n\n const totalLiquidity = netLiquidity + removedLiquidity\n\n return {\n netLiquidity,\n removedLiquidity,\n totalLiquidity,\n shortLiquidity: totalLiquidity,\n longLiquidity: removedLiquidity,\n }\n })\n\n return { results, _meta }\n}\n","/**\n * Factory read functions for the Panoptic v2 SDK.\n *\n * Supports both PanopticFactoryV3 (Uniswap V3) and PanopticFactoryV4 (Uniswap V4).\n *\n * @module v2/reads/factory\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { zeroAddress } from 'viem'\n\nimport { panopticFactoryV3Abi, panopticFactoryV4Abi } from '../../../generated'\nimport type { PoolKey } from '../types'\nimport { getUniswapV3PoolFromId, getUniswapV4PoolKeyFromId } from './sfpm'\n\n// ---------------------------------------------------------------------------\n// Shared reads (identical signature on both V3 and V4)\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for getFactoryTokenURI.\n */\nexport interface GetFactoryTokenURIParams {\n /** Public client */\n client: PublicClient\n /** PanopticFactory address */\n factoryAddress: Address\n /** Factory version */\n version: 'v3' | 'v4'\n /** Token ID (encoded pool address) */\n tokenId: bigint\n}\n\n/**\n * Get the token URI from a PanopticFactory NFT.\n */\nexport async function getFactoryTokenURI(params: GetFactoryTokenURIParams): Promise<string> {\n const { client, factoryAddress, version, tokenId } = params\n const abi = version === 'v3' ? panopticFactoryV3Abi : panopticFactoryV4Abi\n\n return client.readContract({\n address: factoryAddress,\n abi,\n functionName: 'tokenURI',\n args: [tokenId],\n })\n}\n\n/**\n * Parameters for getFactoryOwnerOf.\n */\nexport interface GetFactoryOwnerOfParams {\n /** Public client */\n client: PublicClient\n /** PanopticFactory address */\n factoryAddress: Address\n /** Factory version */\n version: 'v3' | 'v4'\n /** Token ID (encoded pool address) */\n tokenId: bigint\n}\n\n/**\n * Get the owner of a PanopticFactory NFT.\n */\nexport async function getFactoryOwnerOf(params: GetFactoryOwnerOfParams): Promise<Address> {\n const { client, factoryAddress, version, tokenId } = params\n const abi = version === 'v3' ? panopticFactoryV3Abi : panopticFactoryV4Abi\n\n return client.readContract({\n address: factoryAddress,\n abi,\n functionName: 'ownerOf',\n args: [tokenId],\n })\n}\n\n/**\n * Parameters for getFactoryConstructMetadata.\n */\nexport interface GetFactoryConstructMetadataParams {\n /** Public client */\n client: PublicClient\n /** PanopticFactory address */\n factoryAddress: Address\n /** Factory version */\n version: 'v3' | 'v4'\n /** PanopticPool address (or predicted address) */\n panopticPoolAddress: Address\n /** Token 0 symbol */\n symbol0: string\n /** Token 1 symbol */\n symbol1: string\n /** Fee tier */\n fee: bigint\n}\n\n/**\n * Construct NFT metadata for a pool via the factory contract.\n */\nexport async function getFactoryConstructMetadata(\n params: GetFactoryConstructMetadataParams,\n): Promise<string> {\n const { client, factoryAddress, version, panopticPoolAddress, symbol0, symbol1, fee } = params\n const abi = version === 'v3' ? panopticFactoryV3Abi : panopticFactoryV4Abi\n\n return client.readContract({\n address: factoryAddress,\n abi,\n functionName: 'constructMetadata',\n args: [panopticPoolAddress, symbol0, symbol1, fee],\n })\n}\n\n// ---------------------------------------------------------------------------\n// V3-specific reads\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for getPanopticPoolAddress on a V3 factory.\n */\nexport interface GetPanopticPoolAddressV3Params {\n /** Public client */\n client: PublicClient\n /** PanopticFactoryV3 address */\n factoryAddress: Address\n /** Uniswap V3 pool address */\n univ3pool: Address\n /** Risk engine address */\n riskEngine: Address\n}\n\n/**\n * Parameters for getPanopticPoolAddress on a V4 factory.\n */\nexport interface GetPanopticPoolAddressV4Params {\n /** Public client */\n client: PublicClient\n /** PanopticFactoryV4 address */\n factoryAddress: Address\n /** V4 pool key */\n poolKey: PoolKey\n /** Risk engine address */\n riskEngine: Address\n}\n\n/** Versioned params for {@link getPanopticPoolAddress}. Use `version` to select V3 or V4. */\nexport type GetPanopticPoolAddressParams =\n | ({ version: 'v3' } & GetPanopticPoolAddressV3Params)\n | ({ version: 'v4' } & GetPanopticPoolAddressV4Params)\n\n/**\n * Get the PanopticPool address for a given pool and risk engine.\n */\nexport async function getPanopticPoolAddress(\n params: GetPanopticPoolAddressParams,\n): Promise<Address> {\n const { client, factoryAddress, riskEngine } = params\n\n if (params.version === 'v3') {\n return client.readContract({\n address: factoryAddress,\n abi: panopticFactoryV3Abi,\n functionName: 'getPanopticPool',\n args: [params.univ3pool, riskEngine],\n })\n }\n\n return client.readContract({\n address: factoryAddress,\n abi: panopticFactoryV4Abi,\n functionName: 'getPanopticPool',\n args: [\n {\n currency0: params.poolKey.currency0,\n currency1: params.poolKey.currency1,\n fee: Number(params.poolKey.fee),\n tickSpacing: Number(params.poolKey.tickSpacing),\n hooks: params.poolKey.hooks,\n },\n riskEngine,\n ],\n })\n}\n\n// ---------------------------------------------------------------------------\n// minePoolAddress\n// ---------------------------------------------------------------------------\n\n/**\n * Common mining parameters shared between V3 and V4.\n */\ninterface MinePoolAddressCommon {\n /** Public client */\n client: PublicClient\n /** PanopticFactory address */\n factoryAddress: Address\n /** Deployer address (msg.sender for deployment) */\n deployerAddress: Address\n /** Risk engine address */\n riskEngine: Address\n /** Starting salt (uint96) */\n salt: bigint\n /** Number of mining iterations */\n loops: bigint\n /** Minimum rarity target */\n minTargetRarity: bigint\n}\n\nexport interface MinePoolAddressV3Params extends MinePoolAddressCommon {\n /** Uniswap V3 pool address */\n v3Pool: Address\n}\n\nexport interface MinePoolAddressV4Params extends MinePoolAddressCommon {\n /** V4 pool key */\n poolKey: PoolKey\n}\n\n/** Versioned params for {@link minePoolAddress}. Use `version` to select V3 or V4. */\nexport type MinePoolAddressParams =\n | ({ version: 'v3' } & MinePoolAddressV3Params)\n | ({ version: 'v4' } & MinePoolAddressV4Params)\n\n/**\n * Result of pool address mining.\n */\nexport interface MinePoolAddressResult {\n /** Best salt found */\n bestSalt: bigint\n /** Highest rarity achieved */\n highestRarity: bigint\n}\n\n/**\n * Mine for an optimal pool address salt with high rarity.\n */\nexport async function minePoolAddress(\n params: MinePoolAddressParams,\n): Promise<MinePoolAddressResult> {\n const { client, factoryAddress, deployerAddress, riskEngine, salt, loops, minTargetRarity } =\n params\n\n let result: readonly [bigint, bigint]\n\n if (params.version === 'v3') {\n result = await client.readContract({\n address: factoryAddress,\n abi: panopticFactoryV3Abi,\n functionName: 'minePoolAddress',\n args: [deployerAddress, params.v3Pool, riskEngine, salt, loops, minTargetRarity],\n })\n } else {\n result = await client.readContract({\n address: factoryAddress,\n abi: panopticFactoryV4Abi,\n functionName: 'minePoolAddress',\n args: [\n deployerAddress,\n {\n currency0: params.poolKey.currency0,\n currency1: params.poolKey.currency1,\n fee: Number(params.poolKey.fee),\n tickSpacing: Number(params.poolKey.tickSpacing),\n hooks: params.poolKey.hooks,\n },\n riskEngine,\n salt,\n loops,\n minTargetRarity,\n ],\n })\n }\n\n return { bestSalt: BigInt(result[0]), highestRarity: result[1] }\n}\n\n// ---------------------------------------------------------------------------\n// simulateDeployNewPool\n// ---------------------------------------------------------------------------\n\ninterface SimulateDeployNewPoolCommon {\n /** Public client */\n client: PublicClient\n /** PanopticFactory address */\n factoryAddress: Address\n /** Account address (deployer) */\n account: Address\n /** Risk engine address */\n riskEngine: Address\n /** Salt (uint96) */\n salt: bigint\n}\n\nexport interface SimulateDeployNewPoolV3Params extends SimulateDeployNewPoolCommon {\n /** Token 0 address */\n token0: Address\n /** Token 1 address */\n token1: Address\n /** Fee tier (uint24) */\n fee: bigint\n}\n\nexport interface SimulateDeployNewPoolV4Params extends SimulateDeployNewPoolCommon {\n /** V4 pool key */\n poolKey: PoolKey\n}\n\nexport type SimulateDeployNewPoolParams =\n | ({ version: 'v3' } & SimulateDeployNewPoolV3Params)\n | ({ version: 'v4' } & SimulateDeployNewPoolV4Params)\n\n/**\n * Simulate a pool deployment to get the predicted pool address.\n *\n * Uses `simulateContract` on `deployNewPool` — the return value is the new pool address\n * without actually executing the transaction.\n */\nexport async function simulateDeployNewPool(params: SimulateDeployNewPoolParams): Promise<Address> {\n const { client, factoryAddress, account, riskEngine, salt } = params\n\n if (params.version === 'v3') {\n const { result } = await client.simulateContract({\n address: factoryAddress,\n abi: panopticFactoryV3Abi,\n functionName: 'deployNewPool',\n args: [params.token0, params.token1, Number(params.fee), riskEngine, salt],\n account,\n })\n return result\n }\n\n const { result } = await client.simulateContract({\n address: factoryAddress,\n abi: panopticFactoryV4Abi,\n functionName: 'deployNewPool',\n args: [\n {\n currency0: params.poolKey.currency0,\n currency1: params.poolKey.currency1,\n fee: Number(params.poolKey.fee),\n tickSpacing: Number(params.poolKey.tickSpacing),\n hooks: params.poolKey.hooks,\n },\n riskEngine,\n salt,\n ],\n account,\n })\n return result\n}\n\n// ---------------------------------------------------------------------------\n// getPanopticPoolFromPoolId\n// ---------------------------------------------------------------------------\n\n/**\n * Common parameters for {@link getPanopticPoolFromPoolId}.\n */\ninterface GetPanopticPoolFromPoolIdCommon {\n /** Public client */\n client: PublicClient\n /** SFPM address */\n sfpmAddress: Address\n /** PanopticFactory address */\n factoryAddress: Address\n /** Risk engine address */\n riskEngine: Address\n /** The SFPM pool identifier (uint64) */\n poolId: bigint\n}\n\n/** Versioned params for {@link getPanopticPoolFromPoolId}. */\nexport type GetPanopticPoolFromPoolIdParams =\n | ({ version: 'v3' } & GetPanopticPoolFromPoolIdCommon)\n | ({ version: 'v4' } & GetPanopticPoolFromPoolIdCommon)\n\n/**\n * Resolve an SFPM poolId to its PanopticPool address.\n *\n * Chains two on-chain lookups:\n * 1. SFPM: poolId → Uniswap pool address (V3) or pool key (V4)\n * 2. Factory: Uniswap pool + riskEngine → PanopticPool address\n */\nexport async function getPanopticPoolFromPoolId(\n params: GetPanopticPoolFromPoolIdParams,\n): Promise<Address> {\n const { client, sfpmAddress, factoryAddress, riskEngine, poolId, version } = params\n\n if (version === 'v3') {\n const univ3pool = await getUniswapV3PoolFromId({ client, sfpmAddress, poolId })\n return getPanopticPoolAddress({\n version: 'v3',\n client,\n factoryAddress,\n univ3pool,\n riskEngine,\n })\n }\n\n const poolKey = await getUniswapV4PoolKeyFromId({ client, sfpmAddress, poolId })\n return getPanopticPoolAddress({\n version: 'v4',\n client,\n factoryAddress,\n poolKey,\n riskEngine,\n })\n}\n\n// ---------------------------------------------------------------------------\n// resolvePanopticPoolFromPoolId (version-agnostic)\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for {@link resolvePanopticPoolFromPoolId}.\n */\nexport interface ResolvePanopticPoolFromPoolIdParams {\n /** Public client */\n client: PublicClient\n /** The SFPM pool identifier (uint64) */\n poolId: bigint\n /** Risk engine address */\n riskEngine: Address\n /** V3 SFPM + Factory addresses (omit if V3 is not deployed) */\n v3?: {\n sfpmAddress: Address\n factoryAddress: Address\n }\n /** V4 SFPM + Factory addresses (omit if V4 is not deployed) */\n v4?: {\n sfpmAddress: Address\n factoryAddress: Address\n }\n}\n\n/**\n * Result of {@link resolvePanopticPoolFromPoolId}.\n */\nexport interface ResolvePanopticPoolFromPoolIdResult {\n /** The resolved PanopticPool address */\n panopticPoolAddress: Address\n /** Which version matched */\n version: 'v3' | 'v4'\n}\n\n/**\n * Resolve an SFPM poolId to its PanopticPool address without knowing the version.\n *\n * Tries both V3 and V4 lookups in parallel. The factory returns `address(0)` for\n * non-existent pools, so the non-zero result identifies the correct version.\n *\n * At least one of `v3` or `v4` must be provided.\n *\n * @throws {PanopticValidationError} If no version config is provided or neither resolves.\n */\nexport async function resolvePanopticPoolFromPoolId(\n params: ResolvePanopticPoolFromPoolIdParams,\n): Promise<ResolvePanopticPoolFromPoolIdResult> {\n const { client, poolId, riskEngine, v3, v4 } = params\n\n if (!v3 && !v4) {\n throw new Error('At least one of v3 or v4 must be provided')\n }\n\n const isNotFoundError = (err: unknown): boolean => {\n // Contract reverts (e.g. pool not registered) are \"not found\".\n // RPC / ABI / network errors should propagate.\n if (typeof err === 'object' && err !== null && 'name' in err) {\n const name = (err as { name: string }).name\n return name === 'ContractFunctionExecutionError' || name === 'ContractFunctionRevertedError'\n }\n return false\n }\n\n const results = await Promise.all([\n v3\n ? getPanopticPoolFromPoolId({\n version: 'v3',\n client,\n sfpmAddress: v3.sfpmAddress,\n factoryAddress: v3.factoryAddress,\n riskEngine,\n poolId,\n }).catch((err) => {\n if (isNotFoundError(err)) return zeroAddress\n throw err\n })\n : Promise.resolve(zeroAddress),\n v4\n ? getPanopticPoolFromPoolId({\n version: 'v4',\n client,\n sfpmAddress: v4.sfpmAddress,\n factoryAddress: v4.factoryAddress,\n riskEngine,\n poolId,\n }).catch((err) => {\n if (isNotFoundError(err)) return zeroAddress\n throw err\n })\n : Promise.resolve(zeroAddress),\n ])\n\n const [v3Result, v4Result] = results\n\n if (v3Result !== zeroAddress) {\n return { panopticPoolAddress: v3Result, version: 'v3' }\n }\n if (v4Result !== zeroAddress) {\n return { panopticPoolAddress: v4Result, version: 'v4' }\n }\n\n throw new Error(`No PanopticPool found for poolId ${poolId}`)\n}\n","/**\n * Client-side (off-chain) implementation of minePoolAddress.\n *\n * Replicates the on-chain PanopticFactory mining loop entirely in TypeScript,\n * eliminating RPC round-trips. The result is identical to the on-chain computation.\n *\n * Algorithm:\n * For each candidate salt (uint96):\n * 1. Pack a bytes32 salt from deployer, pool identifier, riskEngine, and iteration salt\n * 2. Predict the CREATE3 deployed address (via proxy)\n * 3. Score by leading hex zeros (\"rarity\")\n * 4. Track the best salt; stop early if minTargetRarity is reached\n *\n * @module v2/reads/minePoolAddressLocal\n */\n\nimport type { Address, Hex } from 'viem'\nimport { encodeAbiParameters, keccak256 } from 'viem'\n\nimport { PanopticValidationError } from '../errors'\nimport type { PoolKey } from '../types'\nimport type {\n MinePoolAddressResult,\n MinePoolAddressV3Params,\n MinePoolAddressV4Params,\n} from './factory'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Mining params for PanopticFactoryV3 — no RPC client needed. */\nexport type MinePoolAddressLocalV3Params = Omit<MinePoolAddressV3Params, 'client'>\n\n/** Mining params for PanopticFactoryV4 — no RPC client needed. */\nexport type MinePoolAddressLocalV4Params = Omit<MinePoolAddressV4Params, 'client'>\n\nexport type MinePoolAddressLocalParams =\n | ({ version: 'v3' } & MinePoolAddressLocalV3Params)\n | ({ version: 'v4' } & MinePoolAddressLocalV4Params)\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/**\n * keccak256 of the CREATE3 proxy initcode used by ClonesWithImmutableArgs.\n * Source: packages/panoptic-v2-core/lib/clones-with-immutable-args/src/ClonesWithImmutableArgs.sol\n */\nconst CREATE3_PROXY_BYTECODE_HASH =\n '0x21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f' as Hex\n\nconst MASK_80 = (1n << 80n) - 1n\nconst MASK_40 = (1n << 40n) - 1n\nconst MASK_96 = (1n << 96n) - 1n\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\n/** Encode a BigInt as a big-endian fixed-length byte array. */\nfunction bigintToBytes(value: bigint, byteLength: number): Uint8Array {\n const bytes = new Uint8Array(byteLength)\n let v = value\n for (let i = byteLength - 1; i >= 0; i--) {\n bytes[i] = Number(v & 0xffn)\n v >>= 8n\n }\n return bytes\n}\n\n/** Parse a 0x-prefixed address into 20 bytes. */\nfunction addressToBytes(addr: Address): Uint8Array {\n const hex = addr.slice(2).padStart(40, '0')\n const bytes = new Uint8Array(20)\n for (let i = 0; i < 20; i++) {\n bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16)\n }\n return bytes\n}\n\n/** Parse a 0x-prefixed 32-byte hex string into bytes. */\nfunction hex32ToBytes(hex: Hex): Uint8Array {\n const h = hex.slice(2).padStart(64, '0')\n const bytes = new Uint8Array(32)\n for (let i = 0; i < 32; i++) {\n bytes[i] = parseInt(h.slice(i * 2, i * 2 + 2), 16)\n }\n return bytes\n}\n\n/**\n * Compute the CREATE3 deployed address for a given factory and packed salt.\n *\n * Mirrors `ClonesWithImmutableArgs.addressOfClone3(salt)` (with `address(this)` = factory):\n * proxy = CREATE2(factory, salt, PROXY_BYTECODE_HASH)\n * deployed = CREATE1(proxy, nonce=1)\n *\n * Returns the deployed address as a uint160 BigInt.\n */\nfunction addressOfClone3(factory: Address, salt: bigint): bigint {\n const saltBytes = bigintToBytes(salt, 32)\n\n // CREATE2: keccak256(0xff ++ factory ++ salt ++ proxyBytecodeHash) — 85 bytes total\n const create2Input = new Uint8Array(85)\n create2Input[0] = 0xff\n create2Input.set(addressToBytes(factory), 1) // bytes 1–20\n create2Input.set(saltBytes, 21) // bytes 21–52\n create2Input.set(hex32ToBytes(CREATE3_PROXY_BYTECODE_HASH), 53) // bytes 53–84\n\n const proxyHash = keccak256(create2Input, 'bytes')\n const proxyAddress = proxyHash.slice(12) // rightmost 20 bytes\n\n // CREATE1 nonce=1: keccak256(0xd694 ++ proxy ++ 0x01) — 23 bytes total\n const create1Input = new Uint8Array(23)\n create1Input[0] = 0xd6\n create1Input[1] = 0x94\n create1Input.set(proxyAddress, 2) // bytes 2–21\n create1Input[22] = 0x01\n\n const deployedHash = keccak256(create1Input, 'bytes')\n\n // Convert rightmost 20 bytes to uint160 BigInt\n let addr = 0n\n for (let i = 12; i < 32; i++) {\n addr = (addr << 8n) | BigInt(deployedHash[i])\n }\n return addr\n}\n\n/**\n * Count leading hex-zero characters in a 160-bit address value.\n *\n * Mirrors `PanopticMath.numberOfLeadingHexZeros(addr)`.\n * Returns 40 for the zero address.\n */\nexport function numberOfLeadingHexZeros(addrInt: bigint): number {\n if (addrInt === 0n) return 40\n let x = addrInt\n let r = 0\n if (x >= 0x100000000000000000000000000000000n) {\n x >>= 128n\n r += 32\n }\n if (x >= 0x10000000000000000n) {\n x >>= 64n\n r += 16\n }\n if (x >= 0x100000000n) {\n x >>= 32n\n r += 8\n }\n if (x >= 0x10000n) {\n x >>= 16n\n r += 4\n }\n if (x >= 0x100n) {\n x >>= 8n\n r += 2\n }\n if (x >= 0x10n) {\n r += 1\n }\n return 39 - r\n}\n\n/**\n * Construct the bytes32 CREATE3 salt for PanopticFactoryV3.\n *\n * Mirrors:\n * bytes32(abi.encodePacked(\n * uint80(uint160(deployerAddress) >> 80), // bits [159:80] of deployer → 10 bytes\n * uint40(uint160(v3Pool) >> 120), // bits [159:120] of v3Pool → 5 bytes\n * uint40(uint160(riskEngine) >> 120), // bits [159:120] of riskEngine→ 5 bytes\n * salt // uint96 → 12 bytes\n * ))\n */\nfunction computeSaltPrefixV3(\n deployerAddress: Address,\n v3Pool: Address,\n riskEngine: Address,\n): bigint {\n const deployer80 = (BigInt(deployerAddress) >> 80n) & MASK_80\n const pool40 = (BigInt(v3Pool) >> 120n) & MASK_40\n const risk40 = (BigInt(riskEngine) >> 120n) & MASK_40\n return (deployer80 << 176n) | (pool40 << 136n) | (risk40 << 96n)\n}\n\n/**\n * Compute the Uniswap V4 PoolId for a PoolKey.\n *\n * Mirrors `PoolId.toId(key)` = keccak256 of the ABI-encoded PoolKey struct\n * (5 fields × 32 bytes = 160 bytes).\n */\nexport function computePoolIdV4(poolKey: PoolKey): bigint {\n const fee = Number(poolKey.fee)\n if (!Number.isInteger(fee) || fee < 0 || fee >= 2 ** 24) {\n throw new PanopticValidationError(`fee out of uint24 range: ${fee}`)\n }\n const tickSpacing = Number(poolKey.tickSpacing)\n if (!Number.isInteger(tickSpacing) || tickSpacing < -(2 ** 23) || tickSpacing > 2 ** 23 - 1) {\n throw new PanopticValidationError(`tickSpacing out of int24 range: ${tickSpacing}`)\n }\n const encoded = encodeAbiParameters(\n [\n { type: 'address' },\n { type: 'address' },\n { type: 'uint24' },\n { type: 'int24' },\n { type: 'address' },\n ],\n [\n poolKey.currency0,\n poolKey.currency1,\n Number(poolKey.fee),\n Number(poolKey.tickSpacing),\n poolKey.hooks,\n ],\n )\n return BigInt(keccak256(encoded))\n}\n\n/**\n * Construct the bytes32 CREATE3 salt for PanopticFactoryV4.\n *\n * Mirrors:\n * bytes32(abi.encodePacked(\n * uint80(uint160(deployerAddress) >> 80),\n * uint40(uint256(PoolId.unwrap(key.toId())) >> 120), // bits [159:120] of poolId\n * uint40(uint160(riskEngine) >> 120),\n * salt\n * ))\n */\nfunction computeSaltPrefixV4(\n deployerAddress: Address,\n poolKey: PoolKey,\n riskEngine: Address,\n): bigint {\n const deployer80 = (BigInt(deployerAddress) >> 80n) & MASK_80\n const poolId40 = (computePoolIdV4(poolKey) >> 120n) & MASK_40\n const risk40 = (BigInt(riskEngine) >> 120n) & MASK_40\n return (deployer80 << 176n) | (poolId40 << 136n) | (risk40 << 96n)\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Mine for an optimal Panoptic pool address salt, running entirely off-chain.\n *\n * Equivalent to calling `minePoolAddress` on the factory contract but with zero\n * RPC round-trips. The result is identical to the on-chain computation.\n *\n * Iterates `loops` times starting from `salt`, tracking the highest-rarity address\n * found. Stops early when `minTargetRarity` is reached.\n *\n * @param params - Mining parameters (versioned: 'v3' or 'v4'). No `client` required.\n * @returns The best salt found and its rarity (number of leading hex zeros).\n */\nexport function minePoolAddressLocal(params: MinePoolAddressLocalParams): MinePoolAddressResult {\n const { factoryAddress, deployerAddress, riskEngine, salt, loops, minTargetRarity } = params\n\n if (salt < 0n || loops < 0n || minTargetRarity < 0n) {\n throw new PanopticValidationError('salt, loops, and minTargetRarity must be non-negative')\n }\n if (salt + loops > (1n << 96n) - 1n) {\n throw new PanopticValidationError('salt + loops exceeds uint96 range')\n }\n\n let bestSalt = salt\n let highestRarity = 0n\n const maxSalt = salt + loops\n\n // Precompute the invariant high-bit prefix once outside the loop\n const saltPrefix =\n params.version === 'v3'\n ? computeSaltPrefixV3(deployerAddress, params.v3Pool, riskEngine)\n : computeSaltPrefixV4(deployerAddress, params.poolKey, riskEngine)\n\n for (let currentSalt = salt; currentSalt < maxSalt; currentSalt++) {\n const newSalt = saltPrefix | (currentSalt & MASK_96)\n\n const addrInt = addressOfClone3(factoryAddress, newSalt)\n const rarity = BigInt(numberOfLeadingHexZeros(addrInt))\n\n if (rarity > highestRarity) {\n highestRarity = rarity\n bestSalt = currentSalt\n }\n\n if (rarity >= minTargetRarity) {\n highestRarity = rarity\n bestSalt = currentSalt\n break\n }\n }\n\n return { bestSalt, highestRarity }\n}\n\n// ---------------------------------------------------------------------------\n// Async variant (yields to the event loop between chunks)\n// ---------------------------------------------------------------------------\n\n/** Number of iterations per chunk before yielding back to the event loop. */\nconst CHUNK_SIZE = 5000n\n\n/**\n * Async version of {@link minePoolAddressLocal} that yields to the event loop\n * between chunks of iterations, preventing the browser UI from freezing.\n *\n * @param params - Mining parameters (versioned: 'v3' or 'v4'). No `client` required.\n * @returns The best salt found and its rarity (number of leading hex zeros).\n */\nexport async function minePoolAddressLocalAsync(\n params: MinePoolAddressLocalParams,\n): Promise<MinePoolAddressResult> {\n const { factoryAddress, deployerAddress, riskEngine, salt, loops, minTargetRarity } = params\n\n let bestSalt = salt\n let highestRarity = 0n\n const maxSalt = salt + loops\n\n const saltPrefix =\n params.version === 'v3'\n ? computeSaltPrefixV3(deployerAddress, params.v3Pool, riskEngine)\n : computeSaltPrefixV4(deployerAddress, params.poolKey, riskEngine)\n\n let currentSalt = salt\n while (currentSalt < maxSalt) {\n const chunkEnd = currentSalt + CHUNK_SIZE < maxSalt ? currentSalt + CHUNK_SIZE : maxSalt\n let done = false\n\n for (; currentSalt < chunkEnd; currentSalt++) {\n const newSalt = saltPrefix | (currentSalt & MASK_96)\n const addrInt = addressOfClone3(factoryAddress, newSalt)\n const rarity = BigInt(numberOfLeadingHexZeros(addrInt))\n\n if (rarity > highestRarity) {\n highestRarity = rarity\n bestSalt = currentSalt\n }\n\n if (rarity >= minTargetRarity) {\n highestRarity = rarity\n bestSalt = currentSalt\n done = true\n break\n }\n }\n\n if (done) break\n\n // Yield to the event loop so the UI stays responsive\n await new Promise<void>((resolve) => setTimeout(resolve, 0))\n }\n\n return { bestSalt, highestRarity }\n}\n","/**\n * Premia read functions for the Panoptic v2 SDK.\n * @module v2/reads/premia\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport type { BlockMeta, Position, TokenIdLeg } from '../types'\nimport { decodePosition, decodeTickSpacing } from '../utils/option-encoding-v2'\nimport { decodeLeftRightUnsigned } from '../writes/utils'\n\n/**\n * Premia data for an account.\n */\nexport interface AccountPremia {\n /** Total short premium owed to the account for token 0 */\n shortPremium0: bigint\n /** Total short premium owed to the account for token 1 */\n shortPremium1: bigint\n /** Total long premium owed by the account for token 0 */\n longPremium0: bigint\n /** Total long premium owed by the account for token 1 */\n longPremium1: bigint\n /** Whether pending (unsettled) premium was included */\n includePendingPremium: boolean\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for getAccountPremia.\n */\nexport interface GetAccountPremiaParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenIds held by the account */\n tokenIds: bigint[]\n /** Whether to include pending (unsettled) premium (default: true) */\n includePendingPremium?: boolean\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get premia totals for an account.\n *\n * Returns the total short and long premium across all positions.\n * Short premium is owed TO the account (earned from selling options).\n * Long premium is owed BY the account (paid for buying options).\n *\n * @param params - The parameters\n * @returns Premia totals with block metadata\n *\n * @example\n * ```typescript\n * const premia = await getAccountPremia({\n * client,\n * poolAddress,\n * account,\n * tokenIds: [tokenId1, tokenId2],\n * includePendingPremium: true,\n * })\n *\n * console.log('Short premium earned:', premia.shortPremium0, premia.shortPremium1)\n * console.log('Long premium owed:', premia.longPremium0, premia.longPremium1)\n * ```\n */\nexport async function getAccountPremia(params: GetAccountPremiaParams): Promise<AccountPremia> {\n const {\n client,\n poolAddress,\n account,\n tokenIds,\n includePendingPremium = true,\n blockNumber,\n } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Handle empty position list\n if (tokenIds.length === 0) {\n const _meta = params._meta ?? (await getBlockMeta({ client, blockNumber: targetBlockNumber }))\n return {\n shortPremium0: 0n,\n shortPremium1: 0n,\n longPremium0: 0n,\n longPremium1: 0n,\n includePendingPremium,\n _meta,\n }\n }\n\n const [[shortPremiumPacked, longPremiumPacked], _meta] = await Promise.all([\n client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, includePendingPremium, tokenIds],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // Decode LeftRightUnsigned values (right = token0, left = token1)\n const shortPremium = decodeLeftRightUnsigned(shortPremiumPacked)\n const longPremium = decodeLeftRightUnsigned(longPremiumPacked)\n\n return {\n shortPremium0: shortPremium.right,\n shortPremium1: shortPremium.left,\n longPremium0: longPremium.right,\n longPremium1: longPremium.left,\n includePendingPremium,\n _meta,\n }\n}\n\n/**\n * Position with premia data.\n */\nexport interface PositionWithPremia extends Position {\n // Position already has all fields from the base Position interface\n}\n\n/**\n * Result from getPositionsWithPremia.\n */\nexport interface PositionsWithPremiaResult {\n /** Positions with full data */\n positions: PositionWithPremia[]\n /** Total short premium owed to the account for token 0 */\n shortPremium0: bigint\n /** Total short premium owed to the account for token 1 */\n shortPremium1: bigint\n /** Total long premium owed by the account for token 0 */\n longPremium0: bigint\n /** Total long premium owed by the account for token 1 */\n longPremium1: bigint\n /** Whether pending (unsettled) premium was included */\n includePendingPremium: boolean\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for getPositionsWithPremia.\n */\nexport interface GetPositionsWithPremiaParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenIds held by the account */\n tokenIds: bigint[]\n /** Whether to include pending (unsettled) premium (default: true) */\n includePendingPremium?: boolean\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get positions with per-position premia data.\n *\n * Uses multicall to batch individual getFullPositionsData calls\n * for each position, giving us per-position premia in a single RPC request.\n *\n * @param params - The parameters\n * @returns Positions with premia and totals with block metadata\n *\n * @example\n * ```typescript\n * const result = await getPositionsWithPremia({\n * client,\n * poolAddress,\n * account,\n * tokenIds: [tokenId1, tokenId2],\n * })\n *\n * for (const position of result.positions) {\n * console.log('Position:', position.tokenId)\n * console.log('Premia:', position.premiaOwed0, position.premiaOwed1)\n * }\n * console.log('Total short premium:', result.shortPremium0, result.shortPremium1)\n * ```\n */\nexport async function getPositionsWithPremia(\n params: GetPositionsWithPremiaParams,\n): Promise<PositionsWithPremiaResult> {\n const {\n client,\n poolAddress,\n account,\n tokenIds,\n includePendingPremium = true,\n blockNumber,\n } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Handle empty position list\n if (tokenIds.length === 0) {\n const _meta = params._meta ?? (await getBlockMeta({ client, blockNumber: targetBlockNumber }))\n return {\n positions: [],\n shortPremium0: 0n,\n shortPremium1: 0n,\n longPremium0: 0n,\n longPremium1: 0n,\n includePendingPremium,\n _meta,\n }\n }\n\n // Build multicall contracts - one getFullPositionsData call per tokenId\n // This gives us per-position premia\n const contracts = tokenIds.map((tokenId) => ({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData' as const,\n args: [account, includePendingPremium, [tokenId]] as const,\n }))\n\n // Execute multicall and get block metadata\n const [multicallResults, _meta] = await Promise.all([\n client.multicall({\n contracts,\n blockNumber: targetBlockNumber,\n allowFailure: true,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // Build positions and accumulate totals\n const positions: PositionWithPremia[] = []\n let totalShortPremium0 = 0n\n let totalShortPremium1 = 0n\n let totalLongPremium0 = 0n\n let totalLongPremium1 = 0n\n\n for (let i = 0; i < tokenIds.length; i++) {\n const tokenId = tokenIds[i]\n const result = multicallResults[i]\n\n // Skip failed calls\n if (result.status !== 'success') {\n continue\n }\n\n const [shortPremiumPacked, longPremiumPacked, balances] = result.result\n\n // Decode per-position premia\n const shortPremium = decodeLeftRightUnsigned(shortPremiumPacked)\n const longPremium = decodeLeftRightUnsigned(longPremiumPacked)\n\n // Accumulate totals\n totalShortPremium0 += shortPremium.right\n totalShortPremium1 += shortPremium.left\n totalLongPremium0 += longPremium.right\n totalLongPremium1 += longPremium.left\n\n // Get balance data (should be single element array)\n const balanceData = balances[0]\n if (balanceData === undefined) {\n continue\n }\n\n // Decode the PositionBalance\n const positionSize = balanceData & ((1n << 128n) - 1n)\n\n // Skip positions with zero size\n if (positionSize === 0n) {\n continue\n }\n\n const poolUtilization0 = (balanceData >> 128n) & 0xffffn\n const poolUtilization1 = (balanceData >> 144n) & 0xffffn\n\n // tickAtMint is int24 at bits 160-183\n let tickAtMint = (balanceData >> 160n) & 0xffffffn\n if (tickAtMint > 0x7fffffn) {\n tickAtMint = tickAtMint - 0x1000000n\n }\n\n const timestampAtMint = (balanceData >> 184n) & 0xffffffffn\n const blockAtMint = (balanceData >> 216n) & ((1n << 39n) - 1n)\n const swapAtMint = balanceData >> 255n === 1n\n\n // Decode the tokenId to get legs\n const decoded = decodePosition(tokenId)\n const tickSpacing = decodeTickSpacing(tokenId)\n\n // Convert decoded legs to TokenIdLeg format\n const legs: TokenIdLeg[] = decoded.legs.map((leg) => {\n const width = leg.width\n const strike = leg.strike\n const tickLower = strike - (width * tickSpacing) / 2n\n const tickUpper = strike + (width * tickSpacing) / 2n\n\n return {\n index: BigInt(leg.index),\n asset: leg.asset,\n optionRatio: leg.optionRatio,\n isLong: leg.isLong === 1n,\n tokenType: leg.tokenType,\n riskPartner: leg.riskPartner,\n strike,\n width,\n tickLower,\n tickUpper,\n }\n })\n\n // Calculate net premia for this position\n // Positive = position has earned premium (short), Negative = position owes premium (long)\n const premiaOwed0 = shortPremium.right - longPremium.right\n const premiaOwed1 = shortPremium.left - longPremium.left\n\n positions.push({\n tokenId,\n positionSize,\n owner: account,\n poolAddress,\n legs,\n poolUtilization0AtMint: poolUtilization0,\n poolUtilization1AtMint: poolUtilization1,\n tickAtMint,\n timestampAtMint,\n blockNumberAtMint: blockAtMint,\n swapAtMint,\n premiaOwed0,\n premiaOwed1,\n assetIndex: legs.length > 0 ? legs[0].asset : 0n,\n _meta,\n })\n }\n\n return {\n positions,\n shortPremium0: totalShortPremium0,\n shortPremium1: totalShortPremium1,\n longPremium0: totalLongPremium0,\n longPremium1: totalLongPremium1,\n includePendingPremium,\n _meta,\n }\n}\n","/**\n * Collateral estimation functions for the Panoptic v2 SDK.\n *\n * These functions require the PanopticQuery contract which provides\n * on-chain calculation capabilities for collateral requirements.\n *\n * @module v2/reads/collateralEstimate\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { encodeFunctionData } from 'viem'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi } from '../../../generated'\nimport { panopticQueryAbi } from '../abis/panopticQuery'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { PanopticError } from '../errors'\nimport { type TokenFlow, simulateWithTokenFlow } from '../simulations/tokenFlow'\nimport type { StorageAdapter } from '../storage'\nimport { getTrackedPositionIds } from '../sync/getTrackedPositionIds'\nimport type { BlockMeta } from '../types'\nimport { MAX_TICK, MIN_TICK } from '../utils/constants'\n\n/**\n * Collateral estimate result.\n */\nexport interface CollateralEstimate {\n /** Required collateral for token 0 */\n required0: bigint\n /** Required collateral for token 1 */\n required1: bigint\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for estimateCollateralRequired.\n */\nexport interface EstimateCollateralRequiredParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenId to estimate collateral for */\n tokenId: bigint\n /** Position size (number of contracts) */\n positionSize: bigint\n /** Optional: Tick to calculate collateral at (defaults to current tick) */\n atTick?: bigint\n /** PanopticQuery address */\n queryAddress: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Estimate the collateral required to open a position.\n *\n * Note: This function uses PanopticQuery.getRequiredBase for estimation.\n * Returns collateral requirement in terms of token0.\n *\n * @param params - The parameters\n * @returns Estimated collateral requirements with block metadata\n */\nexport async function estimateCollateralRequired(\n params: EstimateCollateralRequiredParams,\n): Promise<CollateralEstimate> {\n const { client, poolAddress, tokenId, atTick, queryAddress, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Get current tick if not provided\n let effectiveTick: bigint\n if (atTick !== undefined) {\n effectiveTick = atTick\n } else {\n const currentTickResult = await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n blockNumber: targetBlockNumber,\n })\n // Bridge type from panopticPoolV2Abi (number | bigint) to bigint\n effectiveTick = BigInt(currentTickResult)\n }\n\n const [required0, _meta] = await Promise.all([\n client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getRequiredBase',\n args: [poolAddress, tokenId, Number(effectiveTick)],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // PanopticQuery.getRequiredBase returns collateral requirement in terms of token0\n // For token1 requirement, would need additional conversion or separate call\n return {\n required0,\n required1: 0n, // Not available from getRequiredBase (token0-denominated only)\n _meta,\n }\n}\n\n/**\n * Max position size result.\n */\nexport interface MaxPositionSize {\n /** Refined maximum position size at current market conditions */\n maxSize: bigint\n /** Maximum position size at 0% utilization (best case / upper bound) */\n maxSizeAtMinUtil: bigint\n /** Maximum position size at 100% utilization (worst case / lower bound) */\n maxSizeAtMaxUtil: bigint\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for getMaxPositionSize.\n */\nexport interface GetMaxPositionSizeParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenId to check max size for */\n tokenId: bigint\n /** PanopticQuery address (required for this function) */\n queryAddress: Address\n /**\n * Existing position IDs held by the account.\n * - If provided, uses these directly\n * - If not provided but storage + chainId given, fetches from getTrackedPositionIds()\n * - If neither provided, assumes empty array (new account with no positions)\n */\n existingPositionIds?: bigint[]\n /** Storage adapter for auto-fetching positions (requires chainId) */\n storage?: StorageAdapter\n /** Chain ID (required if using storage) */\n chainId?: bigint\n /** Whether to refine with dispatch simulation (default: true) */\n refine?: boolean\n /** Precision for binary search as percentage (default: 1 = 1%) */\n precisionPct?: number\n /** Whether to swap tokens at mint (affects collateral requirements, default: false) */\n swapAtMint?: boolean\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get the maximum position size an account can open given their current collateral.\n *\n * Uses PanopticQuery.getMaxPositionSizeBounds to get bounds at 0% and 100% utilization,\n * then refines with dispatch simulations to find the exact max at current conditions.\n *\n * @param params - The parameters\n * @returns Maximum position size with bounds and block metadata\n */\nexport async function getMaxPositionSize(\n params: GetMaxPositionSizeParams,\n): Promise<MaxPositionSize> {\n const {\n client,\n poolAddress,\n account,\n tokenId,\n queryAddress,\n existingPositionIds,\n storage,\n chainId,\n refine = true,\n precisionPct = 1,\n swapAtMint = false,\n blockNumber,\n } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Get existing position IDs\n let positionIds: bigint[]\n if (existingPositionIds !== undefined) {\n // Use explicitly provided position IDs\n positionIds = existingPositionIds\n } else if (storage && chainId !== undefined) {\n // Fetch from local cache via getTrackedPositionIds\n positionIds = await getTrackedPositionIds({\n chainId,\n poolAddress,\n account,\n storage,\n })\n } else {\n // Assume new account with no existing positions\n positionIds = []\n }\n // Get bounds and block meta in parallel\n const [boundsResult, _meta] = await Promise.all([\n client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getMaxPositionSizeBounds',\n args: [poolAddress, positionIds, account, tokenId],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const [maxSizeAtMinUtil, maxSizeAtMaxUtil] = boundsResult\n\n // If bounds are equal or very close, or refinement disabled, return conservative estimate\n const precisionDivisor = BigInt(Math.floor(100 / precisionPct))\n if (\n !refine ||\n maxSizeAtMinUtil === maxSizeAtMaxUtil ||\n maxSizeAtMinUtil - maxSizeAtMaxUtil <= maxSizeAtMaxUtil / precisionDivisor\n ) {\n return {\n maxSize: maxSizeAtMaxUtil,\n maxSizeAtMinUtil,\n maxSizeAtMaxUtil,\n _meta,\n }\n }\n\n // Binary search between widened bounds using dispatch simulation\n // Widen by 2x in each direction to account for swapAtMint price impact\n const maxSize = await binarySearchMaxSize({\n client,\n poolAddress,\n account,\n tokenId,\n existingPositionIds: positionIds,\n low: maxSizeAtMaxUtil / 2n,\n high: maxSizeAtMinUtil * 2n,\n precisionDivisor,\n swapAtMint,\n })\n\n return {\n maxSize,\n maxSizeAtMinUtil,\n maxSizeAtMaxUtil,\n _meta,\n }\n}\n\n/**\n * Parallel search to find max position size using dispatch simulation.\n * Tests 5 points per round (sextiles), narrowing the range by 6x each iteration.\n */\nasync function binarySearchMaxSize(params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n tokenId: bigint\n existingPositionIds: bigint[]\n low: bigint\n high: bigint\n precisionDivisor: bigint\n swapAtMint: boolean\n}): Promise<bigint> {\n const {\n client,\n poolAddress,\n account,\n tokenId,\n existingPositionIds,\n precisionDivisor,\n swapAtMint,\n } = params\n let { low, high } = params\n\n const trySize = (positionSize: bigint) =>\n tryDispatchSimulation({\n client,\n poolAddress,\n account,\n tokenId,\n existingPositionIds,\n positionSize,\n swapAtMint,\n })\n\n while (high - low > 1n && high - low > low / precisionDivisor) {\n const range = high - low\n const p1 = low + range / 6n\n const p2 = low + (range * 2n) / 6n\n const p3 = low + (range * 3n) / 6n\n const p4 = low + (range * 4n) / 6n\n const p5 = low + (range * 5n) / 6n\n\n const [s1, s2, s3, s4, s5] = await Promise.all([\n trySize(p1),\n trySize(p2),\n trySize(p3),\n trySize(p4),\n trySize(p5),\n ])\n\n if (s5) {\n low = p5\n } else if (s4) {\n low = p4\n high = p5\n } else if (s3) {\n low = p3\n high = p4\n } else if (s2) {\n low = p2\n high = p3\n } else if (s1) {\n low = p1\n high = p2\n } else {\n high = p1\n }\n }\n\n return low\n}\n\n/**\n * Try to simulate opening a position with the given size.\n */\nasync function tryDispatchSimulation(params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n tokenId: bigint\n existingPositionIds: bigint[]\n positionSize: bigint\n swapAtMint: boolean\n}): Promise<boolean> {\n const { client, poolAddress, account, tokenId, existingPositionIds, positionSize, swapAtMint } =\n params\n\n try {\n // Build final position list (existing + new position)\n const finalPositionIdList = [...existingPositionIds, tokenId]\n\n // Build tick limits based on swapAtMint flag:\n // - swapAtMint=true: descending order (high, low) triggers SFPM swap\n // - swapAtMint=false: ascending order (low, high) no swap\n const tickLimits: readonly [number, number, number] = swapAtMint\n ? [887272, -887272, 0]\n : [-887272, 887272, 0]\n\n // Encode dispatch call\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n [tokenId],\n finalPositionIdList,\n [positionSize as unknown as bigint & { readonly __uint128: true }],\n [tickLimits],\n true, // usePremiaAsCollateral\n 0n, // builderCode\n ],\n })\n\n // Use PanopticPool.multicall to simulate\n await client.simulateContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'multicall',\n args: [[callData]],\n account,\n })\n\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Parameters for getRequiredCreditForITM.\n */\nexport interface GetRequiredCreditForITMParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenId to check */\n tokenId: bigint\n /** Position size (number of contracts) */\n positionSize: bigint\n /** Existing position IDs held by the account (defaults to empty) */\n existingPositionIds?: bigint[]\n /** Optional block number for simulation */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Result for getRequiredCreditForITM.\n */\nexport interface RequiredCreditForITM {\n /**\n * Required credit in token0 to neutralize ITM exposure.\n * Positive = credit needed (deposit), negative = loan proceeds (receive).\n */\n creditAmount0: bigint\n /**\n * Required credit in token1 to neutralize ITM exposure.\n * Positive = credit needed (deposit), negative = loan proceeds (receive).\n */\n creditAmount1: bigint\n /** The raw token flow from simulation */\n tokenFlow: TokenFlow\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Get the required credit (or loan) amount for an ITM position.\n *\n * Simulates opening the position with swapAtMint=true (descending tickLimits)\n * to get single-sided token flow. The token flow represents the ITM amount\n * that would need to be neutralized with a credit (or loan if negative).\n *\n * @param params - The parameters\n * @returns Required credit amounts with token flow and block metadata\n * @throws PanopticError - If simulation fails\n *\n * @example\n * ```typescript\n * const result = await getRequiredCreditForITM({\n * client,\n * poolAddress,\n * account,\n * tokenId,\n * positionSize: 1n,\n * })\n *\n * if (result.creditAmount0 > 0n) {\n * console.log('Need credit of', result.creditAmount0, 'token0')\n * } else if (result.creditAmount0 < 0n) {\n * console.log('Position yields loan of', -result.creditAmount0, 'token0')\n * }\n * ```\n */\nexport async function getRequiredCreditForITM(\n params: GetRequiredCreditForITMParams,\n): Promise<RequiredCreditForITM> {\n const {\n client,\n poolAddress,\n account,\n tokenId,\n positionSize,\n existingPositionIds = [],\n blockNumber,\n } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Build final position list (existing + new position)\n const finalPositionIdList = [...existingPositionIds, tokenId]\n\n // Encode dispatch call with swapAtMint=true (descending tickLimits)\n // Descending order (MAX_TICK > MIN_TICK) triggers SFPM swap, giving single-sided token flow\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n [tokenId], // positionIdList: positions being minted\n finalPositionIdList,\n [positionSize as unknown as bigint & { readonly __uint128: true }],\n [[Number(MAX_TICK), Number(MIN_TICK), 0] as readonly [number, number, number]], // Descending = swapAtMint\n false, // usePremiaAsCollateral\n 0n, // builderCode\n ],\n })\n\n // Simulate with token flow measurement and get block meta in parallel\n const [result, _meta] = await Promise.all([\n simulateWithTokenFlow({\n client,\n poolAddress,\n user: account,\n callData,\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n if (!result.success || !result.tokenFlow) {\n throw new PanopticError(result.error ?? 'Token flow simulation failed')\n }\n\n // The token flow deltas represent the ITM amount:\n // - Negative delta = user deposits (credit needed)\n // - Positive delta = user receives (loan proceeds)\n // We invert the sign so positive = credit needed, negative = loan\n return {\n creditAmount0: -result.tokenFlow.delta0,\n creditAmount1: -result.tokenFlow.delta1,\n tokenFlow: result.tokenFlow,\n _meta,\n }\n}\n\n/**\n * Parameters for getMaxWithdrawable.\n */\nexport interface GetMaxWithdrawableParams {\n /** viem PublicClient */\n client: PublicClient\n /** CollateralTracker address */\n collateralTrackerAddress: Address\n /** Account address */\n account: Address\n /** Position IDs held by the account (required for solvency-checked withdraw) */\n positionIdList: bigint[]\n /** Upper bound for the binary search (e.g. user's total assets in this tracker) */\n totalAssets: bigint\n /** Whether to use premia as collateral (default: false) */\n usePremiaAsCollateral?: boolean\n /** Precision for binary search as percentage (default: 1 = 1%) */\n precisionPct?: number\n}\n\n/**\n * Find the maximum withdrawable amount from a CollateralTracker using binary search.\n *\n * When a user has open positions, the standard `maxWithdraw()` returns 0 because\n * the basic ERC4626 withdraw doesn't check solvency. The overloaded\n * `withdraw(assets, receiver, owner, positionIdList, usePremiaAsCollateral)` does\n * check solvency, so we binary search for the largest amount that doesn't revert.\n *\n * @param params - The parameters\n * @returns Maximum withdrawable amount in underlying asset units\n */\nexport async function getMaxWithdrawable(\n params: GetMaxWithdrawableParams,\n): Promise<{ maxWithdrawable: bigint; _meta: BlockMeta }> {\n const {\n client,\n collateralTrackerAddress,\n account,\n positionIdList,\n totalAssets,\n usePremiaAsCollateral = false,\n precisionPct = 1,\n } = params\n\n const _meta = await getBlockMeta({ client })\n\n if (totalAssets <= 0n || positionIdList.length === 0) {\n // No positions: use the standard maxWithdraw\n const maxWithdraw = await client.readContract({\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'maxWithdraw',\n args: [account],\n })\n return { maxWithdrawable: maxWithdraw, _meta }\n }\n\n const precisionDivisor = BigInt(Math.floor(100 / precisionPct))\n let low = 0n\n let high = totalAssets\n\n while (high - low > 1n && high - low > low / precisionDivisor) {\n const mid = low + (high - low) / 2n\n\n const success = await tryWithdrawSimulation({\n client,\n collateralTrackerAddress,\n account,\n assets: mid,\n positionIdList,\n usePremiaAsCollateral,\n })\n\n if (success) {\n low = mid\n } else {\n high = mid\n }\n }\n\n return { maxWithdrawable: low, _meta }\n}\n\n/**\n * Try to simulate a solvency-checked withdraw with the given amount.\n */\nasync function tryWithdrawSimulation(params: {\n client: PublicClient\n collateralTrackerAddress: Address\n account: Address\n assets: bigint\n positionIdList: bigint[]\n usePremiaAsCollateral: boolean\n}): Promise<boolean> {\n const {\n client,\n collateralTrackerAddress,\n account,\n assets,\n positionIdList,\n usePremiaAsCollateral,\n } = params\n\n try {\n await client.estimateContractGas({\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'withdraw',\n args: [assets, account, account, positionIdList, usePremiaAsCollateral],\n account,\n })\n return true\n } catch {\n return false\n }\n}\n","/**\n * ERC4626 vault preview functions for the Panoptic v2 SDK.\n *\n * The CollateralTracker contract implements ERC4626, providing standard\n * vault functionality for depositing/withdrawing collateral.\n *\n * @module v2/reads/erc4626\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport type { BlockMeta } from '../types'\n\n/**\n * Parameters for ERC4626 preview functions.\n */\nexport interface ERC4626PreviewParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Which token's collateral tracker to query (0 or 1) */\n tokenIndex: 0 | 1\n /** Amount to preview */\n amount: bigint\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched collateral tracker address */\n collateralTrackerAddress?: Address\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * ERC4626 preview result.\n */\nexport interface ERC4626PreviewResult {\n /** The resulting amount (shares or assets depending on function) */\n result: bigint\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Helper to get collateral tracker address.\n */\nasync function getCollateralTrackerAddress(\n client: PublicClient,\n poolAddress: Address,\n tokenIndex: 0 | 1,\n providedAddress?: Address,\n): Promise<Address> {\n if (providedAddress) return providedAddress\n\n return client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: tokenIndex === 0 ? 'collateralToken0' : 'collateralToken1',\n })\n}\n\n/**\n * Preview the amount of shares that would be minted for a deposit.\n *\n * @param params - The parameters\n * @returns Preview result with block metadata\n */\nexport async function previewDeposit(params: ERC4626PreviewParams): Promise<ERC4626PreviewResult> {\n const { client, poolAddress, tokenIndex, amount, blockNumber, collateralTrackerAddress } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n const trackerAddress = await getCollateralTrackerAddress(\n client,\n poolAddress,\n tokenIndex,\n collateralTrackerAddress,\n )\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'previewDeposit',\n args: [amount],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n return { result, _meta }\n}\n\n/**\n * Preview the amount of assets that would be returned for a withdrawal.\n *\n * @param params - The parameters\n * @returns Preview result with block metadata\n */\nexport async function previewWithdraw(params: ERC4626PreviewParams): Promise<ERC4626PreviewResult> {\n const { client, poolAddress, tokenIndex, amount, blockNumber, collateralTrackerAddress } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n const trackerAddress = await getCollateralTrackerAddress(\n client,\n poolAddress,\n tokenIndex,\n collateralTrackerAddress,\n )\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'previewWithdraw',\n args: [amount],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n return { result, _meta }\n}\n\n/**\n * Preview the amount of assets required for a mint.\n *\n * @param params - The parameters\n * @returns Preview result with block metadata\n */\nexport async function previewMint(params: ERC4626PreviewParams): Promise<ERC4626PreviewResult> {\n const { client, poolAddress, tokenIndex, amount, blockNumber, collateralTrackerAddress } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n const trackerAddress = await getCollateralTrackerAddress(\n client,\n poolAddress,\n tokenIndex,\n collateralTrackerAddress,\n )\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'previewMint',\n args: [amount],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n return { result, _meta }\n}\n\n/**\n * Preview the amount of shares that would be burned for a redeem.\n *\n * @param params - The parameters\n * @returns Preview result with block metadata\n */\nexport async function previewRedeem(params: ERC4626PreviewParams): Promise<ERC4626PreviewResult> {\n const { client, poolAddress, tokenIndex, amount, blockNumber, collateralTrackerAddress } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n const trackerAddress = await getCollateralTrackerAddress(\n client,\n poolAddress,\n tokenIndex,\n collateralTrackerAddress,\n )\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'previewRedeem',\n args: [amount],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n return { result, _meta }\n}\n\n/**\n * Convert an amount of assets to shares.\n *\n * @param params - The parameters\n * @returns Conversion result with block metadata\n */\nexport async function convertToShares(params: ERC4626PreviewParams): Promise<ERC4626PreviewResult> {\n const { client, poolAddress, tokenIndex, amount, blockNumber, collateralTrackerAddress } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n const trackerAddress = await getCollateralTrackerAddress(\n client,\n poolAddress,\n tokenIndex,\n collateralTrackerAddress,\n )\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'convertToShares',\n args: [amount],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n return { result, _meta }\n}\n\n/**\n * Convert an amount of shares to assets.\n *\n * @param params - The parameters\n * @returns Conversion result with block metadata\n */\nexport async function convertToAssets(params: ERC4626PreviewParams): Promise<ERC4626PreviewResult> {\n const { client, poolAddress, tokenIndex, amount, blockNumber, collateralTrackerAddress } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n const trackerAddress = await getCollateralTrackerAddress(\n client,\n poolAddress,\n tokenIndex,\n collateralTrackerAddress,\n )\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'convertToAssets',\n args: [amount],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n return { result, _meta }\n}\n","/**\n * PanopticGuardian read functions for the Panoptic v2 SDK.\n *\n * The Guardian can lock a pool into close-only mode. Unlocking is a two-step\n * timelocked flow: `requestUnlock(pool)` schedules an unlock ETA, and after the\n * ETA matures `executeUnlock(pool)` clears the lock. This module reads the\n * pending-unlock state so the UI can surface a countdown while a pool is locked.\n *\n * @module v2/reads/guardian\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticGuardianAbi, panopticPoolV2Abi, riskEngineAbi } from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport type { BlockMeta } from '../types'\n\n/**\n * Parameters for getGuardianUnlockState.\n */\nexport interface GetGuardianUnlockStateParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Optional RiskEngine address (skips the pool.riskEngine() read) */\n riskEngineAddress?: Address\n /** Optional PanopticGuardian address (skips the riskEngine.GUARDIAN() read) */\n guardianAddress?: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Guardian pool-unlock state.\n */\nexport interface GuardianUnlockState {\n /** Resolved PanopticGuardian contract address */\n guardianAddress: Address\n /** Unlock ETA as a Unix timestamp (seconds); 0n when no unlock is pending */\n unlockEta: bigint\n /** True when an unlock has been requested but not yet executed */\n hasPendingUnlock: boolean\n /** True when the pending unlock's timelock has elapsed and it can be executed */\n isReady: boolean\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Read the Guardian pending-unlock state for a pool.\n *\n * Resolves the Guardian address from the pool's RiskEngine when not provided,\n * then reads `unlockEta` and `isPoolUnlockReady` from the PanopticGuardian in a\n * single multicall pinned to the same block.\n *\n * @param params - The parameters\n * @returns Guardian unlock state with block metadata\n */\nexport async function getGuardianUnlockState(\n params: GetGuardianUnlockStateParams,\n): Promise<GuardianUnlockState> {\n const { client, poolAddress, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Only reuse caller-supplied metadata when it matches the block we read at,\n // otherwise data and metadata would come from different blocks.\n const reusableMeta =\n params._meta && params._meta.blockNumber === targetBlockNumber ? params._meta : undefined\n\n // Resolve the RiskEngine (immutable) unless caller supplied it.\n const riskEngineAddress =\n params.riskEngineAddress ??\n (await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'riskEngine',\n blockNumber: targetBlockNumber,\n }))\n\n // Resolve the Guardian (immutable) unless caller supplied it.\n const guardianAddress =\n params.guardianAddress ??\n (await client.readContract({\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'GUARDIAN',\n blockNumber: targetBlockNumber,\n }))\n\n const [results, _meta] = await Promise.all([\n client.multicall({\n contracts: [\n {\n address: guardianAddress,\n abi: panopticGuardianAbi,\n functionName: 'unlockEta',\n args: [poolAddress],\n },\n {\n address: guardianAddress,\n abi: panopticGuardianAbi,\n functionName: 'isPoolUnlockReady',\n args: [poolAddress],\n },\n ],\n blockNumber: targetBlockNumber,\n allowFailure: false,\n }),\n reusableMeta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const [unlockEta, isReady] = results\n\n return {\n guardianAddress,\n unlockEta,\n hasPendingUnlock: unlockEta > 0n,\n isReady,\n _meta,\n }\n}\n","/**\n * Safe mode check functions for the Panoptic v2 SDK.\n *\n * Safe mode is a protective mechanism that activates when pool conditions\n * become dangerous (e.g., extreme price movements or liquidity issues).\n *\n * @module v2/reads/safeMode\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport type { BlockMeta, SafeModeState as OracleSafeModeState } from '../types'\n\n/**\n * Safe mode status values.\n */\nexport const SafeModeStatus = {\n /** Pool is operating normally */\n NORMAL: 0n,\n /** No new leveraged positions allowed */\n NO_LEVERAGE: 1n,\n /** No swaps allowed */\n NO_SWAP: 2n,\n /** Close-only mode */\n CLOSE_ONLY: 3n,\n} as const\n\nexport type SafeModeStatusValue = (typeof SafeModeStatus)[keyof typeof SafeModeStatus]\n\n/**\n * Safe mode state for bot preflight and operation guards.\n */\nexport type SafeModeState = OracleSafeModeState\n\n/**\n * Parameters for getSafeMode.\n */\nexport interface GetSafeModeParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get the current safe mode status of a pool.\n *\n * Safe mode is activated when:\n * - Pool liquidity drops below safe thresholds\n * - Price volatility exceeds safe limits\n * - Administrative pause is triggered\n *\n * @param params - The parameters\n * @returns Safe mode state with block metadata\n */\nexport async function getSafeMode(params: GetSafeModeParams): Promise<SafeModeState> {\n const { client, poolAddress, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n const [safeModeRaw, _meta] = await Promise.all([\n client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'isSafeMode',\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // isSafeMode returns uint8:\n // 0 = normal, 1 = no leverage, 2 = no swap, 3 = close only\n const status = BigInt(safeModeRaw) as SafeModeStatusValue\n\n switch (status) {\n case SafeModeStatus.NO_LEVERAGE:\n return {\n mode: 'restricted',\n canMint: true,\n canBurn: true,\n canForceExercise: true,\n canLiquidate: true,\n canSwapAtMint: true,\n reason: 'All positions require 100% collateral',\n _meta,\n }\n case SafeModeStatus.NO_SWAP:\n return {\n mode: 'restricted',\n canMint: true,\n canBurn: true,\n canForceExercise: true,\n canLiquidate: true,\n canSwapAtMint: false,\n reason: 'Swaps are disabled',\n _meta,\n }\n case SafeModeStatus.CLOSE_ONLY:\n return {\n mode: 'emergency',\n canMint: false,\n canBurn: true,\n canForceExercise: true,\n canLiquidate: true,\n canSwapAtMint: false,\n reason: 'Pool is in close-only mode',\n _meta,\n }\n default:\n return {\n mode: 'normal',\n canMint: true,\n canBurn: true,\n canForceExercise: true,\n canLiquidate: true,\n canSwapAtMint: true,\n _meta,\n }\n }\n}\n","/**\n * Additional utility functions using PanopticQuery contract.\n *\n * These functions provide enhanced analysis capabilities for portfolio management,\n * risk visualization, and TokenId optimization.\n *\n * @module v2/reads/queryUtils\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { panopticQueryAbi } from '../abis/panopticQuery'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport type { BlockMeta } from '../types'\n\n/**\n * Portfolio value result (without premia).\n */\nexport interface PortfolioValue {\n /** Value in token 0 */\n value0: bigint\n /** Value in token 1 */\n value1: bigint\n /** Tick at which value was calculated */\n atTick: bigint\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for getPortfolioValue.\n */\nexport interface GetPortfolioValueParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenIds of open positions */\n tokenIds: bigint[]\n /** Optional: Tick to calculate value at (defaults to current tick) */\n atTick?: bigint\n /** PanopticQuery address (required for this function) */\n queryAddress: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get portfolio value (NAV) without premia.\n *\n * This calculates the net asset value of the portfolio based on Uniswap liquidity\n * at a given tick, excluding accumulated premia. Useful for PnL tracking separate\n * from liquidation value.\n *\n * ## Same-Block Guarantee\n * All data is fetched at a single block.\n *\n * @param params - The parameters\n * @returns Portfolio value with block metadata\n */\nexport async function getPortfolioValue(params: GetPortfolioValueParams): Promise<PortfolioValue> {\n const { client, poolAddress, account, tokenIds, atTick, queryAddress, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Skip getCurrentTick RPC call when atTick is provided\n const [currentTickResult, _meta] = await Promise.all([\n atTick != null\n ? Promise.resolve(atTick)\n : client\n .readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n blockNumber: targetBlockNumber,\n })\n .then((r) => BigInt(r)),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const effectiveTick = currentTickResult\n\n const result = await client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getPortfolioValue',\n args: [poolAddress, account, Number(effectiveTick), tokenIds],\n blockNumber: targetBlockNumber,\n })\n\n const [value0, value1] = result\n\n return {\n value0,\n value1,\n atTick: effectiveTick,\n _meta,\n }\n}\n\n/**\n * Collateral data point across tick range.\n */\nexport interface CollateralDataPoint {\n /** Tick value */\n tick: bigint\n /** Collateral balance at this tick */\n balance: bigint\n /** Required collateral at this tick */\n required: bigint\n}\n\n/**\n * Collateral analysis across tick range result.\n */\nexport interface CollateralAcrossTicks {\n /** Array of data points (301 points from liquidation range) */\n dataPoints: CollateralDataPoint[]\n /** Liquidation price below current (null if none) */\n liquidationPriceDown: bigint | null\n /** Liquidation price above current (null if none) */\n liquidationPriceUp: bigint | null\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for checkCollateralAcrossTicks.\n */\nexport interface CheckCollateralAcrossTicksParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenIds of open positions */\n tokenIds: bigint[]\n /** PanopticQuery address (required for this function) */\n queryAddress: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Check collateral balance vs requirement across a range of ticks.\n *\n * This function returns 301 data points spanning a range around the current price,\n * including liquidation prices. Perfect for charting liquidation risk in a UI.\n *\n * ## Same-Block Guarantee\n * All data is fetched at a single block.\n *\n * @param params - The parameters\n * @returns Collateral analysis across ticks with block metadata\n */\nexport async function checkCollateralAcrossTicks(\n params: CheckCollateralAcrossTicksParams,\n): Promise<CollateralAcrossTicks> {\n const { client, poolAddress, account, tokenIds, queryAddress, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'checkCollateralListOutput',\n args: [poolAddress, account, tokenIds],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const [balanceRequired, tickData, liquidationPrices] = result\n\n // MIN_TICK and MAX_TICK indicate no liquidation at that boundary\n const MIN_TICK = -887272n\n const MAX_TICK = 887272n\n\n // Convert to data points\n const dataPoints: CollateralDataPoint[] = balanceRequired.map((point, index) => ({\n tick: BigInt(tickData[index]),\n balance: point[0],\n required: point[1],\n }))\n\n // Convert from number (abitype default for int24) to bigint (viem runtime type)\n const liqPriceDown = BigInt(liquidationPrices[0])\n const liqPriceUp = BigInt(liquidationPrices[1])\n\n return {\n dataPoints,\n liquidationPriceDown: liqPriceDown === MIN_TICK ? null : liqPriceDown,\n liquidationPriceUp: liqPriceUp === MAX_TICK ? null : liqPriceUp,\n _meta,\n }\n}\n\n/**\n * Parameters for optimizeTokenIdRiskPartners.\n */\nexport interface OptimizeTokenIdRiskPartnersParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** TokenId to optimize */\n tokenId: bigint\n /** Optional: Tick to optimize at (defaults to current tick) */\n atTick?: bigint\n /** PanopticQuery address (required for this function) */\n queryAddress: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Optimize risk partner assignments for a TokenId.\n *\n * Tests all valid risk partner permutations and returns the TokenId with\n * the lowest collateral requirement. Useful when building positions to\n * maximize capital efficiency.\n *\n * ## Same-Block Guarantee\n * Optimization is performed at a single block.\n *\n * Note: Only works for tokenIds with 2+ legs. Single-leg positions return unchanged.\n *\n * @param params - The parameters\n * @returns Optimized TokenId\n */\nexport async function optimizeTokenIdRiskPartners(\n params: OptimizeTokenIdRiskPartnersParams,\n): Promise<bigint> {\n const { client, poolAddress, tokenId, atTick, queryAddress, blockNumber } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n\n // Get current tick if not provided\n let effectiveTick: bigint\n if (atTick !== undefined) {\n effectiveTick = atTick\n } else {\n const currentTickResult = await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n blockNumber: targetBlockNumber,\n })\n // Bridge type from panopticPoolV2Abi (number | bigint) to bigint\n effectiveTick = BigInt(currentTickResult)\n }\n\n const optimizedTokenId = await client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'optimizeRiskPartners',\n args: [poolAddress, Number(effectiveTick), tokenId],\n blockNumber: targetBlockNumber,\n })\n\n return optimizedTokenId\n}\n","/**\n * Pool liquidity distribution read function using PanopticQuery.\n *\n * @module v2/reads/liquidity\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticQueryAbi } from '../abis/panopticQuery'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport type { BlockMeta } from '../types'\n\n/**\n * Result of getPoolLiquidities.\n */\nexport interface PoolLiquidities {\n /** Tick values for each data point */\n ticks: bigint[]\n /** Net liquidity at each tick */\n liquidityNets: bigint[]\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for getPoolLiquidities.\n */\nexport interface GetPoolLiquiditiesParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** PanopticQuery address */\n queryAddress: Address\n /** Starting tick of the range */\n startTick: bigint\n /** Number of ticks to query */\n nTicks: bigint\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get cumulative liquidity distribution across a tick range.\n *\n * Wraps `PanopticQuery.getTickNets()` to return tick data and net liquidity\n * for each tick in the specified range.\n *\n * ## Same-Block Guarantee\n * All data is fetched at a single block.\n *\n * @param params - The parameters\n * @returns Tick data and liquidity nets with block metadata\n */\nexport async function getPoolLiquidities(\n params: GetPoolLiquiditiesParams,\n): Promise<PoolLiquidities> {\n const { client, poolAddress, queryAddress, startTick, nTicks, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getTickNets',\n args: [poolAddress, Number(startTick), nTicks],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const [tickData, liquidityNets] = result\n\n return {\n ticks: [...tickData],\n liquidityNets: [...liquidityNets],\n _meta,\n }\n}\n","/**\n * Percentage and ratio formatters.\n *\n * All formatters require explicit precision - no hidden defaults.\n *\n * @module v2/formatters/percentage\n */\n\nconst TEN = 10n\n\nfunction formatRatio(numerator: bigint, denominator: bigint, precision: bigint): string {\n if (precision < 0n) {\n throw new RangeError('Precision must be non-negative')\n }\n\n if (denominator === 0n) {\n return '0'\n }\n\n const isNegative = numerator < 0n !== denominator < 0n\n const absNumerator = numerator < 0n ? -numerator : numerator\n const absDenominator = denominator < 0n ? -denominator : denominator\n\n const scale = TEN ** precision\n const scaled = (absNumerator * scale + absDenominator / 2n) / absDenominator\n const integerPart = scaled / scale\n const fractionalPart = scaled % scale\n const sign = isNegative ? '-' : ''\n\n if (precision === 0n) {\n return `${sign}${integerPart}`\n }\n\n return `${sign}${integerPart}.${fractionalPart.toString().padStart(Number(precision), '0')}`\n}\n\n/**\n * Format basis points as a percentage string.\n * 100 bps = 1%\n *\n * @param bps - Basis points value\n * @param precision - Number of decimal places to display\n * @returns Formatted percentage string\n *\n * @example\n * ```typescript\n * formatBps(50n, 2n) // \"0.50%\"\n * formatBps(50n, 1n) // \"0.5%\"\n * formatBps(100n, 2n) // \"1.00%\"\n * formatBps(1500n, 2n) // \"15.00%\"\n * formatBps(-50n, 2n) // \"-0.50%\"\n * ```\n */\nexport function formatBps(bps: bigint, precision: bigint): string {\n const isNegative = bps < 0n\n const absBps = isNegative ? -bps : bps\n\n // bps to percentage: divide by 100\n // Scale up for precision, then divide\n const scaleFactor = 10n ** precision\n const scaled = (absBps * scaleFactor) / 100n\n const integerPart = scaled / scaleFactor\n const fractionalPart = scaled % scaleFactor\n\n const fractionalStr = fractionalPart.toString().padStart(Number(precision), '0')\n const sign = isNegative ? '-' : ''\n\n return precision > 0n ? `${sign}${integerPart}.${fractionalStr}%` : `${sign}${integerPart}%`\n}\n\n/**\n * Format utilization as a percentage string.\n * Utilization is stored as 0n-10000n, where 10000n = 100%.\n *\n * @param util - Utilization value (0-10000)\n * @param precision - Number of decimal places to display\n * @returns Formatted percentage string\n *\n * @example\n * ```typescript\n * formatUtilization(7500n, 2n) // \"75.00%\"\n * formatUtilization(7500n, 0n) // \"75%\"\n * formatUtilization(10000n, 2n) // \"100.00%\"\n * formatUtilization(123n, 2n) // \"1.23%\"\n * ```\n */\nexport function formatUtilization(util: bigint, precision: bigint): string {\n // util is in basis points (10000 = 100%)\n return formatBps(util, precision)\n}\n\n/**\n * Parse a percentage string to basis points.\n *\n * @param percent - Percentage string (e.g., \"1.5%\" or \"1.5\")\n * @returns Basis points value\n *\n * @example\n * ```typescript\n * parseBps(\"1.5%\") // 150n\n * parseBps(\"1.5\") // 150n\n * parseBps(\"100%\") // 10000n\n * parseBps(\"0.5%\") // 50n\n * ```\n */\nexport function parseBps(percent: string): bigint {\n // Remove % suffix if present\n const cleaned = percent.trim().replace(/%$/, '')\n const isNegative = cleaned.startsWith('-')\n const absValue = isNegative ? cleaned.slice(1) : cleaned\n\n const [integerStr, fractionalStr = ''] = absValue.split('.')\n\n // Convert to basis points: multiply by 100\n // Handle up to 2 decimal places in the percentage\n const paddedFractional = fractionalStr.padEnd(2, '0').slice(0, 2)\n\n const integerPart = BigInt(integerStr || '0') * 100n\n const fractionalPart = BigInt(paddedFractional || '0')\n\n const result = integerPart + fractionalPart\n return isNegative ? -result : result\n}\n\n/**\n * Format a ratio as a percentage string.\n *\n * @param numerator - Numerator of the ratio\n * @param denominator - Denominator of the ratio\n * @param precision - Number of decimal places to display\n * @returns Formatted percentage string\n *\n * @example\n * ```typescript\n * formatRatioPercent(1n, 4n, 1n) // \"25.0%\"\n * formatRatioPercent(3n, 4n, 2n) // \"75.00%\"\n * ```\n */\nexport function formatRatioPercent(\n numerator: bigint,\n denominator: bigint,\n precision: bigint,\n): string {\n const scaledNumerator = numerator * 100n\n return `${formatRatio(scaledNumerator, denominator, precision)}%`\n}\n","/**\n * Pool-bound formatters factory.\n *\n * Creates formatter functions that capture pool context (token decimals)\n * for less verbose call sites in single-pool UI components.\n *\n * @module v2/formatters/poolFormatters\n */\n\nimport { formatTokenAmount, parseTokenAmount } from './amount'\nimport { priceToTick, tickToPrice, tickToPriceDecimalScaled } from './tick'\n\n/**\n * Pool-bound formatters interface.\n *\n * These formatters capture the pool's token decimals, so you don't need\n * to pass them at every call site.\n */\nexport interface PoolFormatters {\n /** Token0 decimals */\n readonly decimals0: bigint\n /** Token1 decimals */\n readonly decimals1: bigint\n\n /**\n * Convert tick to raw price (1.0001^tick).\n */\n tickToPrice(tick: bigint): string\n\n /**\n * Convert tick to decimal-scaled price (token1 per token0).\n */\n tickToPriceScaled(tick: bigint, precision: bigint): string\n\n /**\n * Convert tick to decimal-scaled inverse price (token0 per token1).\n */\n tickToInversePriceScaled(tick: bigint, precision: bigint): string\n\n /**\n * Convert a price (token1 per token0) to tick.\n */\n priceToTick(price: string): bigint\n\n /**\n * Format token0 amount with specified precision.\n */\n formatAmount0(amount: bigint, precision: bigint): string\n\n /**\n * Format token1 amount with specified precision.\n */\n formatAmount1(amount: bigint, precision: bigint): string\n\n /**\n * Parse token0 amount string to raw units.\n */\n parseAmount0(amount: string): bigint\n\n /**\n * Parse token1 amount string to raw units.\n */\n parseAmount1(amount: string): bigint\n}\n\n/**\n * Pool metadata required to create pool-bound formatters.\n */\nexport interface PoolFormatterConfig {\n /** Token0 decimals */\n decimals0: bigint\n /** Token1 decimals */\n decimals1: bigint\n}\n\n/**\n * Create pool-bound formatters that capture token decimals.\n *\n * Use this factory when working with a single pool to avoid passing\n * decimals at every call site.\n *\n * @param config - Pool configuration with token decimals\n * @returns Pool-bound formatter functions\n *\n * @example\n * ```typescript\n * // Get pool data\n * const pool = await getPool({ client, poolAddress })\n *\n * // Create formatters bound to this pool\n * const fmt = createPoolFormatters({\n * decimals0: pool.token0Decimals,\n * decimals1: pool.token1Decimals,\n * })\n *\n * // Now use without passing decimals each time\n * const priceStr = fmt.tickToPriceScaled(position.currentTick, 4n)\n * const amount0Str = fmt.formatAmount0(collateral.assets, 4n)\n * const amount1Str = fmt.formatAmount1(premia.token1, 2n)\n *\n * // Parse user input\n * const rawAmount0 = fmt.parseAmount0(\"1.5\")\n * const rawAmount1 = fmt.parseAmount1(\"3000\")\n * ```\n */\nexport function createPoolFormatters(config: PoolFormatterConfig): PoolFormatters {\n const { decimals0, decimals1 } = config\n\n return {\n decimals0,\n decimals1,\n\n tickToPrice(tick: bigint): string {\n return tickToPrice(tick)\n },\n\n tickToPriceScaled(tick: bigint, precision: bigint): string {\n return tickToPriceDecimalScaled(tick, decimals0, decimals1, precision)\n },\n\n tickToInversePriceScaled(tick: bigint, precision: bigint): string {\n // Swap decimals for inverse price\n return tickToPriceDecimalScaled(tick, decimals1, decimals0, precision)\n },\n\n priceToTick(price: string): bigint {\n return priceToTick(price, decimals0, decimals1)\n },\n\n formatAmount0(amount: bigint, precision: bigint): string {\n return formatTokenAmount(amount, decimals0, precision)\n },\n\n formatAmount1(amount: bigint, precision: bigint): string {\n return formatTokenAmount(amount, decimals1, precision)\n },\n\n parseAmount0(amount: string): bigint {\n return parseTokenAmount(amount, decimals0)\n },\n\n parseAmount1(amount: string): bigint {\n return parseTokenAmount(amount, decimals1)\n },\n }\n}\n","/**\n * Token list integration utilities.\n *\n * Provides helpers for integrating with standard token lists\n * (e.g., Uniswap token list, CoinGecko token list).\n *\n * @module v2/formatters/tokenList\n */\n\nimport type { Address } from 'viem'\n\nconst TEN = 10n\n\nfunction formatRatio(numerator: bigint, denominator: bigint, precision: bigint): string {\n if (precision < 0n) {\n throw new RangeError('Precision must be non-negative')\n }\n\n const scale = TEN ** precision\n const scaled = (numerator * scale + denominator / 2n) / denominator\n const integerPart = scaled / scale\n const fractionalPart = scaled % scale\n\n if (precision === 0n) {\n return integerPart.toString()\n }\n\n return `${integerPart}.${fractionalPart.toString().padStart(Number(precision), '0')}`\n}\n\n/**\n * Generate a token list ID for external token list integration.\n *\n * Token lists use a standardized format: `chainId:address`\n * This is compatible with most token list standards.\n *\n * @param chainId - The chain ID\n * @param address - The token address\n * @returns Token list ID string\n *\n * @example\n * ```typescript\n * getTokenListId(1n, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2')\n * // \"1:0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\"\n *\n * getTokenListId(11155111n, '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14')\n * // \"11155111:0xfff9976782d46cc05630d1f6ebab18b2324d6b14\"\n * ```\n */\nexport function getTokenListId(chainId: bigint, address: Address): string {\n return `${chainId}:${address.toLowerCase()}`\n}\n\n/**\n * Parse a token list ID back to chain ID and address.\n *\n * @param tokenListId - The token list ID string\n * @returns Object with chainId and address\n *\n * @example\n * ```typescript\n * parseTokenListId(\"1:0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\")\n * // { chainId: 1n, address: \"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\" }\n * ```\n */\nexport function parseTokenListId(tokenListId: string): {\n chainId: bigint\n address: Address\n} {\n const [chainIdStr, address] = tokenListId.split(':')\n if (!chainIdStr || !address) {\n throw new Error(`Invalid token list ID: ${tokenListId}`)\n }\n return {\n chainId: BigInt(chainIdStr),\n address: address as Address,\n }\n}\n\n/**\n * Generate a pool ID string for display purposes.\n *\n * @param token0Symbol - Symbol of token0\n * @param token1Symbol - Symbol of token1\n * @param feeBps - Fee in basis points (e.g., 500n for 0.05%)\n * @returns Pool ID string\n *\n * @example\n * ```typescript\n * getPoolDisplayId('WETH', 'USDC', 500n)\n * // \"WETH/USDC 0.05%\"\n *\n * getPoolDisplayId('WBTC', 'ETH', 3000n)\n * // \"WBTC/ETH 0.30%\"\n * ```\n */\nexport function getPoolDisplayId(\n token0Symbol: string,\n token1Symbol: string,\n feeBps: bigint,\n): string {\n return `${token0Symbol}/${token1Symbol} ${formatFeeTier(feeBps)}`\n}\n\n/**\n * Format a fee tier for display.\n *\n * @param feeBps - Fee in basis points (e.g., 500n for 0.05%)\n * @returns Fee tier string\n *\n * @example\n * ```typescript\n * formatFeeTier(500n) // \"0.05%\"\n * formatFeeTier(3000n) // \"0.30%\"\n * formatFeeTier(10000n) // \"1.0%\"\n * ```\n */\nexport function formatFeeTier(feeBps: bigint): string {\n const precision = feeBps < 10000n ? 2n : 1n\n const feeStr = formatRatio(feeBps, 10_000n, precision)\n return `${feeStr}%`\n}\n","/**\n * General display formatters for UI components.\n *\n * These are utility formatters for common display needs like\n * addresses, timestamps, and durations.\n *\n * @module v2/formatters/display\n */\n\nimport { formatTokenAmount } from './amount'\n\nconst TEN = 10n\n\nfunction formatRatio(numerator: bigint, denominator: bigint, precision: bigint): string {\n if (precision < 0n) {\n throw new RangeError('Precision must be non-negative')\n }\n\n const scale = TEN ** precision\n const scaled = (numerator * scale + denominator / 2n) / denominator\n const integerPart = scaled / scale\n const fractionalPart = scaled % scale\n\n if (precision === 0n) {\n return integerPart.toString()\n }\n\n return `${integerPart}.${fractionalPart.toString().padStart(Number(precision), '0')}`\n}\n\n/**\n * Truncate an address for display.\n *\n * @param address - Full address\n * @param chars - Characters to show on each side (default: 4)\n * @returns Truncated address like \"0x1234...5678\"\n *\n * @example\n * ```typescript\n * truncateAddress('0x1234567890abcdef1234567890abcdef12345678')\n * // \"0x1234...5678\"\n *\n * truncateAddress('0x1234567890abcdef1234567890abcdef12345678', 6)\n * // \"0x123456...345678\"\n * ```\n */\nexport function truncateAddress(address: string, chars = 4): string {\n const charsBig = BigInt(chars)\n const minLength = charsBig * 2n + 4n\n if (BigInt(address.length) <= minLength) return address\n return `${address.slice(0, Number(charsBig + 2n))}...${address.slice(-Number(charsBig))}`\n}\n\n/**\n * Format a Unix timestamp as an ISO date string (YYYY-MM-DD).\n *\n * @param timestamp - Unix timestamp in seconds\n * @returns ISO date string\n *\n * @example\n * ```typescript\n * formatTimestamp(1700000000n) // \"2023-11-14\"\n * ```\n */\nexport function formatTimestamp(timestamp: bigint): string {\n const ms = timestamp * 1000n\n return new Date(Number(ms)).toISOString().split('T')[0]\n}\n\n/**\n * Format a Unix timestamp as an ISO datetime string.\n *\n * @param timestamp - Unix timestamp in seconds\n * @returns ISO datetime string\n *\n * @example\n * ```typescript\n * formatDatetime(1700000000n) // \"2023-11-14T22:13:20.000Z\"\n * ```\n */\nexport function formatDatetime(timestamp: bigint): string {\n const ms = timestamp * 1000n\n return new Date(Number(ms)).toISOString()\n}\n\n/**\n * Format a Unix timestamp as a locale-aware date string.\n *\n * @param timestamp - Unix timestamp in seconds\n * @param locale - Locale string (default: system locale)\n * @param options - Intl.DateTimeFormat options\n * @returns Formatted date string\n *\n * @example\n * ```typescript\n * formatTimestampLocale(1700000000n)\n * // \"11/14/2023\" (US locale)\n *\n * formatTimestampLocale(1700000000n, 'de-DE')\n * // \"14.11.2023\" (German locale)\n * ```\n */\nexport function formatTimestampLocale(\n timestamp: bigint,\n locale?: string,\n options?: Intl.DateTimeFormatOptions,\n): string {\n const ms = timestamp * 1000n\n return new Date(Number(ms)).toLocaleDateString(locale, options)\n}\n\n/**\n * Format a duration in milliseconds as a human-readable string.\n *\n * @param ms - Duration in milliseconds\n * @returns Formatted duration string\n *\n * @example\n * ```typescript\n * formatDuration(1500n) // \"1.5s\"\n * formatDuration(150n) // \"150ms\"\n * formatDuration(90000n) // \"1m 30s\"\n * formatDuration(3661000n) // \"1h 1m\"\n * ```\n */\nexport function formatDuration(ms: bigint): string {\n const isNegative = ms < 0n\n const absMs = isNegative ? -ms : ms\n const sign = isNegative ? '-' : ''\n\n if (absMs < 1000n) {\n return `${sign}${absMs}ms`\n }\n\n if (absMs < 60000n) {\n const tenthsTotal = (absMs + 50n) / 100n\n const seconds = tenthsTotal / 10n\n const tenths = tenthsTotal % 10n\n return `${sign}${seconds}.${tenths}s`\n }\n\n if (absMs < 3600000n) {\n const minutes = absMs / 60000n\n const seconds = ((absMs % 60000n) + 500n) / 1000n\n return seconds > 0n ? `${sign}${minutes}m ${seconds}s` : `${sign}${minutes}m`\n }\n\n const hours = absMs / 3600000n\n const minutes = ((absMs % 3600000n) + 30000n) / 60000n\n return minutes > 0n ? `${sign}${hours}h ${minutes}m` : `${sign}${hours}h`\n}\n\n/**\n * Format a duration in seconds as a human-readable string.\n *\n * @param seconds - Duration in seconds\n * @returns Formatted duration string\n */\nexport function formatDurationSeconds(seconds: bigint): string {\n return formatDuration(seconds * 1000n)\n}\n\n/**\n * Format a block number for display.\n *\n * @param blockNumber - The block number\n * @returns Formatted block number with commas\n *\n * @example\n * ```typescript\n * formatBlockNumber(18000000n) // \"18,000,000\"\n * ```\n */\nexport function formatBlockNumber(blockNumber: bigint): string {\n return blockNumber.toLocaleString()\n}\n\n/**\n * Format a gas amount for display.\n *\n * @param gas - Gas units\n * @returns Formatted gas string\n */\nexport function formatGas(gas: bigint): string {\n return gas.toLocaleString()\n}\n\n/**\n * Format a transaction hash for display (truncated).\n *\n * @param hash - Full transaction hash\n * @param chars - Characters to show on each side (default: 6)\n * @returns Truncated hash like \"0x123456...abcdef\"\n *\n * @example\n * ```typescript\n * formatTxHash('0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef')\n * // \"0x123456...abcdef\"\n * ```\n */\nexport function formatTxHash(hash: string, chars = 6): string {\n const charsBig = BigInt(chars)\n const minLength = charsBig * 2n + 4n\n if (BigInt(hash.length) <= minLength) return hash\n return `${hash.slice(0, Number(charsBig + 2n))}...${hash.slice(-Number(charsBig))}`\n}\n\nfunction formatHex(value: bigint): string {\n return `0x${value.toString(16)}`\n}\n\n/**\n * Format a TokenId as a hex string.\n *\n * @param tokenId - TokenId value\n * @returns Hex string representation\n */\nexport function formatTokenIdHex(tokenId: bigint): string {\n return formatHex(tokenId)\n}\n\n/**\n * Format a PoolId as a hex string.\n *\n * @param poolId - PoolId value\n * @returns Hex string representation\n */\nexport function formatPoolIdHex(poolId: bigint): string {\n return formatHex(poolId)\n}\n\n/**\n * Format a TokenId as a shortened hex string.\n *\n * @param tokenId - TokenId value\n * @param chars - Characters to show on each side (default: 4)\n * @returns Truncated hex string like \"0x1234...abcd\"\n */\nexport function formatTokenIdShort(tokenId: bigint, chars = 4): string {\n const hex = formatHex(tokenId)\n const charsBig = BigInt(chars)\n const minLength = charsBig * 2n + 4n\n if (BigInt(hex.length) <= minLength) return hex\n return `${hex.slice(0, Number(charsBig + 2n))}...${hex.slice(-Number(charsBig))}`\n}\n\n/**\n * Format a large number with K/M/B suffixes.\n *\n * @param value - The numeric value\n * @param precision - Number of decimal places (default: 1n)\n * @returns Formatted string with suffix\n *\n * @example\n * ```typescript\n * formatCompact(1234n) // \"1.2K\"\n * formatCompact(1234567n) // \"1.2M\"\n * formatCompact(1234567890n) // \"1.2B\"\n * formatCompact(999n) // \"999\"\n * ```\n */\nexport function formatCompact(value: bigint, precision: bigint = 1n): string {\n const isNegative = value < 0n\n const absValue = isNegative ? -value : value\n\n let formatted: string\n\n if (absValue < 1000n) {\n formatted = absValue.toString()\n } else if (absValue < 1_000_000n) {\n formatted = `${formatRatio(absValue, 1000n, precision)}K`\n } else if (absValue < 1_000_000_000n) {\n formatted = `${formatRatio(absValue, 1_000_000n, precision)}M`\n } else {\n formatted = `${formatRatio(absValue, 1_000_000_000n, precision)}B`\n }\n\n return isNegative ? `-${formatted}` : formatted\n}\n\n/**\n * Format a wei amount as a display string.\n *\n * @param wei - Amount in wei\n * @returns Formatted string with unit\n */\nexport function formatWei(wei: bigint): string {\n return `${wei} wei`\n}\n\n/**\n * Format a wei amount as gwei.\n *\n * @param wei - Amount in wei\n * @param precision - Number of decimal places to display\n * @returns Formatted string with unit\n */\nexport function formatGwei(wei: bigint, precision: bigint): string {\n return `${formatTokenAmount(wei, 9n, precision)} gwei`\n}\n","/**\n * Account greeks calculation using stored position data.\n *\n * This module provides functions to calculate account-level greeks\n * using position data stored by syncPositions(). Only the current tick\n * is fetched via RPC - all other data comes from storage.\n *\n * @module v2/reads/accountGreeks\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { PanopticError, StorageDataNotFoundError } from '../errors'\nimport { tickToSqrtPriceX96 } from '../formatters'\nimport {\n type PositionGreeksResult,\n calculatePositionDelta,\n calculatePositionGamma,\n calculatePositionValue,\n} from '../greeks'\nimport type { StorageAdapter } from '../storage'\nimport { getPoolMetaKey, getPositionMetaKey, getPositionsKey, jsonSerializer } from '../storage'\nimport type { BlockMeta, StoredPoolMeta, StoredPositionData } from '../types'\nimport { type CollateralAddresses, getAccountCollateral } from './account'\n\nconst Q192 = 1n << 192n\n\n/**\n * Parameters for getAccountGreeks.\n */\nexport interface GetAccountGreeksParams {\n /** viem PublicClient (only used to fetch current tick) */\n client: PublicClient\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** Storage adapter containing synced position data */\n storage: StorageAdapter\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /**\n * When true, include collateral token balance as linear delta.\n * Requires `assetIndex` to specify which token is the asset.\n */\n includeCollateral?: boolean\n /**\n * Which token is the \"asset\" (the directional exposure token).\n * 0n = token0 is asset, 1n = token1 is asset.\n * Required when `includeCollateral` is true.\n */\n assetIndex?: 0n | 1n\n /** Optional pre-fetched collateral addresses (used when includeCollateral is true) */\n collateralAddresses?: CollateralAddresses\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Result of getAccountGreeks.\n *\n * Returns both granular breakdown (positions vs collateral) and computed totals.\n * - `positionsDelta` / `positionsValue`: Options exposure only\n * - `collateralDelta` / `collateralValue`: Collateral in the pool\n * - `totalDelta` / `totalValue`: Sum of both (use for net portfolio greeks)\n *\n * All values are in natural token smallest units (no WAD scaling).\n * - Value/gamma: numeraire token smallest units\n * - Delta: asset token smallest units\n */\nexport interface AccountGreeksResult {\n // --- Position greeks (options only) ---\n /** Sum of position values (numeraire smallest units, options only) */\n positionsValue: bigint\n /** Sum of position deltas (asset smallest units, options only) */\n positionsDelta: bigint\n /** Sum of position gammas (numeraire smallest units) */\n positionsGamma: bigint\n\n // --- Collateral greeks ---\n /**\n * Value of collateral holdings: asset balance × price + numeraire balance.\n * In numeraire smallest units. 0n when includeCollateral is not set.\n */\n collateralValue: bigint\n /**\n * Linear delta from the asset token's collateral balance (asset smallest units).\n * 0n when includeCollateral is not set.\n */\n collateralDelta: bigint\n\n // --- Computed totals ---\n /** Total portfolio value = positionsValue + collateralValue */\n totalValue: bigint\n /** Total portfolio delta = positionsDelta + collateralDelta */\n totalDelta: bigint\n\n // --- Metadata ---\n /** Number of positions included */\n positionCount: bigint\n /** Per-position greeks breakdown */\n positions: Array<{\n tokenId: bigint\n greeks: PositionGreeksResult\n }>\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Calculate account-level greeks using stored position data.\n *\n * This function reads position data from storage (populated by syncPositions)\n * and calculates greeks client-side. Only the current tick is fetched via RPC.\n *\n * @param params - The parameters\n * @returns Account greeks with per-position breakdown\n * @throws StorageDataNotFoundError if required data is not in storage\n * @throws PanopticError if includeCollateral is true but assetIndex is not provided\n *\n * @example\n * ```typescript\n * // First sync positions to populate storage\n * await syncPositions({ client, chainId, poolAddress, account, storage })\n *\n * // Then calculate greeks from stored data\n * const greeks = await getAccountGreeks({\n * client,\n * chainId,\n * poolAddress,\n * account,\n * storage,\n * })\n *\n * console.log('Positions delta:', greeks.positionsDelta)\n * ```\n */\nexport async function getAccountGreeks(\n params: GetAccountGreeksParams,\n): Promise<AccountGreeksResult> {\n const {\n client,\n chainId,\n poolAddress,\n account,\n storage,\n blockNumber,\n includeCollateral,\n assetIndex,\n collateralAddresses,\n } = params\n\n // 0. Validate: includeCollateral requires assetIndex\n if (includeCollateral && assetIndex === undefined) {\n throw new PanopticError('assetIndex is required when includeCollateral is true')\n }\n\n // 1. Read pool metadata from storage\n const poolMetaKey = getPoolMetaKey(chainId, poolAddress)\n const poolMetaRaw = await storage.get(poolMetaKey)\n if (!poolMetaRaw) {\n throw new StorageDataNotFoundError('poolMeta', poolMetaKey)\n }\n const poolMeta = jsonSerializer.parse(poolMetaRaw) as StoredPoolMeta\n\n // 2. Read position IDs from storage\n const positionsKey = getPositionsKey(chainId, poolAddress, account)\n const positionsRaw = await storage.get(positionsKey)\n if (!positionsRaw) {\n throw new StorageDataNotFoundError('positions', positionsKey)\n }\n const positionIds = jsonSerializer.parse(positionsRaw) as bigint[]\n\n // 3. If no positions and no collateral requested, return zeros\n if (positionIds.length === 0 && !includeCollateral) {\n const targetBlock = blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n const _meta = params._meta ?? (await getBlockMeta({ client, blockNumber: targetBlock }))\n\n return {\n positionsValue: 0n,\n positionsDelta: 0n,\n positionsGamma: 0n,\n collateralValue: 0n,\n collateralDelta: 0n,\n totalValue: 0n,\n totalDelta: 0n,\n positionCount: 0n,\n positions: [],\n _meta,\n }\n }\n\n // 4. Read position metadata for each position from storage\n const storedPositions = await Promise.all(\n positionIds.map(async (tokenId) => {\n const posMetaKey = getPositionMetaKey(chainId, poolAddress, tokenId)\n const posMetaRaw = await storage.get(posMetaKey)\n if (!posMetaRaw) {\n throw new StorageDataNotFoundError('positionMeta', posMetaKey)\n }\n return jsonSerializer.parse(posMetaRaw) as StoredPositionData\n }),\n )\n\n // 5. Fetch current tick (+ collateral if requested) from RPC\n const targetBlock = blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n const [currentTick, _meta, collateral] = await Promise.all([\n client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n blockNumber: targetBlock,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlock }),\n includeCollateral\n ? getAccountCollateral({\n client,\n poolAddress,\n account,\n blockNumber: targetBlock,\n collateralAddresses,\n _meta: params._meta,\n })\n : undefined,\n ])\n\n // 6. Calculate greeks for each position\n let positionsValue = 0n\n let positionsDelta = 0n\n let positionsGamma = 0n\n const positions: AccountGreeksResult['positions'] = []\n\n for (const pos of storedPositions) {\n const input = {\n legs: pos.legs,\n currentTick: BigInt(currentTick),\n mintTick: pos.tickAtMint,\n positionSize: pos.positionSize,\n poolTickSpacing: poolMeta.tickSpacing,\n assetIndex,\n }\n\n const value = calculatePositionValue(input)\n const delta = calculatePositionDelta(input)\n const gamma = calculatePositionGamma(input)\n\n positionsValue += value\n positionsDelta += delta\n positionsGamma += gamma\n\n positions.push({\n tokenId: pos.tokenId,\n greeks: { value, delta, gamma },\n })\n }\n\n // 7. Collateral value and delta\n let collateralValue = 0n\n let collateralDelta = 0n\n\n if (collateral) {\n const isAssetToken0 = assetIndex === 0n\n const assetBal = isAssetToken0 ? collateral.token0.assets : collateral.token1.assets\n const otherBal = isAssetToken0 ? collateral.token1.assets : collateral.token0.assets\n const sqrtPriceX96 = tickToSqrtPriceX96(BigInt(currentTick))\n\n // assetBal * price converts asset smallest units to numeraire smallest units\n // otherBal is already in numeraire smallest units\n if (isAssetToken0) {\n // price = token1/token0 = sqrtPriceX96² / 2¹⁹²\n collateralValue = (assetBal * sqrtPriceX96 * sqrtPriceX96) / Q192 + otherBal\n } else {\n // price = token0/token1 = 2¹⁹² / sqrtPriceX96²\n collateralValue = (assetBal * Q192) / (sqrtPriceX96 * sqrtPriceX96) + otherBal\n }\n collateralDelta = assetBal\n }\n\n return {\n positionsValue,\n positionsDelta,\n positionsGamma,\n collateralValue,\n collateralDelta,\n totalValue: positionsValue + collateralValue,\n totalDelta: positionsDelta + collateralDelta,\n positionCount: BigInt(positionIds.length),\n positions,\n _meta,\n }\n}\n\n/**\n * Parameters for calculateAccountGreeksPure.\n */\nexport interface CalculateAccountGreeksPureParams {\n /** Stored position data */\n positions: StoredPositionData[]\n /** Pool tick spacing */\n tickSpacing: bigint\n /** Ticks at which to evaluate greeks (one or more) */\n atTicks: bigint[]\n /**\n * Collateral balances [token0Assets, token1Assets] in token smallest units.\n * When provided, both tokens are included in totalValue and the\n * asset token's balance is added to totalDelta.\n */\n collateralAssets?: [bigint, bigint]\n /** Override for leg.asset on all legs (0n = token0 is asset, 1n = token1). Defaults to 0n. */\n assetIndex?: bigint\n}\n\n/**\n * Result of calculateAccountGreeksPure.\n *\n * Arrays are parallel to the input `atTicks` — index i corresponds to `atTicks[i]`.\n * Totals include both position greeks and collateral contributions.\n * All values in natural token smallest units (no WAD scaling).\n */\nexport interface AccountGreeksCurveResult {\n /** Total value at each tick: positions + collateral (numeraire smallest units) */\n totalValue: bigint[]\n /** Total delta at each tick: positions + asset collateral (asset smallest units) */\n totalDelta: bigint[]\n /** Total gamma at each tick: positions only (numeraire smallest units, collateral has zero gamma) */\n totalGamma: bigint[]\n /** Number of positions included */\n positionCount: bigint\n /** Per-position greeks curves (arrays parallel to atTicks) */\n positions: Array<{\n tokenId: bigint\n greeks: {\n value: bigint[]\n delta: bigint[]\n gamma: bigint[]\n }\n }>\n}\n\n/**\n * Pure function to calculate portfolio greeks across a range of ticks.\n *\n * No RPC calls — useful for plotting value/delta/gamma curves on a chart.\n * All returned arrays are parallel to the input `atTicks`.\n *\n * When `collateralAssets` is provided, both token balances are included in\n * `totalValue` (asset balance × price + numeraire balance) and\n * the asset token's balance is added to `totalDelta`.\n *\n * @param params - The parameters\n * @returns Portfolio greeks curves and per-position breakdown\n */\nexport function calculateAccountGreeksPure(\n params: CalculateAccountGreeksPureParams,\n): AccountGreeksCurveResult {\n const { positions, tickSpacing, atTicks, collateralAssets, assetIndex } = params\n const n = atTicks.length\n const isAssetToken0 = assetIndex === undefined || assetIndex === 0n\n\n // Collateral balances (already in token smallest units)\n const assetBal = collateralAssets ? collateralAssets[isAssetToken0 ? 0 : 1] : 0n\n const otherBal = collateralAssets ? collateralAssets[isAssetToken0 ? 1 : 0] : 0n\n\n if (positions.length === 0) {\n const totalValue: bigint[] = []\n const totalDelta: bigint[] = []\n for (let i = 0; i < n; i++) {\n const sqrtPriceX96 = tickToSqrtPriceX96(atTicks[i])\n const assetValueInNumeraire = isAssetToken0\n ? (assetBal * sqrtPriceX96 * sqrtPriceX96) / Q192\n : (assetBal * Q192) / (sqrtPriceX96 * sqrtPriceX96)\n totalValue.push(assetValueInNumeraire + otherBal)\n totalDelta.push(assetBal)\n }\n return {\n totalValue,\n totalDelta,\n totalGamma: new Array<bigint>(n).fill(0n),\n positionCount: 0n,\n positions: [],\n }\n }\n\n const totalValue = new Array<bigint>(n).fill(0n)\n const totalDelta = new Array<bigint>(n).fill(0n)\n const totalGamma = new Array<bigint>(n).fill(0n)\n const positionResults: AccountGreeksCurveResult['positions'] = []\n\n for (const pos of positions) {\n const posValues: bigint[] = []\n const posDeltas: bigint[] = []\n const posGammas: bigint[] = []\n\n for (let i = 0; i < n; i++) {\n const input = {\n legs: pos.legs,\n currentTick: atTicks[i],\n mintTick: pos.tickAtMint,\n positionSize: pos.positionSize,\n poolTickSpacing: tickSpacing,\n assetIndex,\n }\n\n const v = calculatePositionValue(input)\n const d = calculatePositionDelta(input)\n const g = calculatePositionGamma(input)\n\n posValues.push(v)\n posDeltas.push(d)\n posGammas.push(g)\n\n totalValue[i] += v\n totalDelta[i] += d\n totalGamma[i] += g\n }\n\n positionResults.push({\n tokenId: pos.tokenId,\n greeks: { value: posValues, delta: posDeltas, gamma: posGammas },\n })\n }\n\n // Add collateral contributions at each tick\n for (let i = 0; i < n; i++) {\n const sqrtPriceX96 = tickToSqrtPriceX96(atTicks[i])\n const assetValueInNumeraire = isAssetToken0\n ? (assetBal * sqrtPriceX96 * sqrtPriceX96) / Q192\n : (assetBal * Q192) / (sqrtPriceX96 * sqrtPriceX96)\n totalValue[i] += assetValueInNumeraire + otherBal\n totalDelta[i] += assetBal\n }\n\n return {\n totalValue,\n totalDelta,\n totalGamma,\n positionCount: BigInt(positions.length),\n positions: positionResults,\n }\n}\n","/**\n * Margin buffer and distance-to-liquidation convenience function.\n *\n * Sources current and required margin directly from\n * `PanopticPool.getFullPositionsData` + `CollateralTracker.assetsOf`,\n * rather than `PanopticQuery.checkCollateral`.\n *\n * Why: `checkCollateral` returns a `currentMargin` already netted of the\n * borrowing obligation of width=0 short (\"loan\") tokenIds, and a\n * `requiredMargin` that does NOT include the loan's collateral requirement.\n * That makes buying-power usage read 0% for accounts whose collateral\n * comes mostly from a loan, and double-subtracts the loan from Net Liq\n * when downstream callers add the position MtM (which already values the\n * loan at `-notional`).\n *\n * `getFullPositionsData.collateralRequirements[]` attributes the loan as\n * a margin requirement (the accurate primitive), and `assetsOf` returns\n * the gross collateral (deposits + borrowed shares) — pairing them yields\n * a consistent gross-collateral / gross-requirement view.\n *\n * @module v2/reads/margin\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { decodeFunctionResult, encodeFunctionData } from 'viem'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi } from '../../../generated'\nimport { panopticQueryAbi } from '../abis/panopticQuery'\nimport { tickToSqrtPriceX96 } from '../formatters/tick'\nimport type { BlockMeta } from '../types'\nimport { decodeLeftRightUnsigned } from '../writes/utils'\nimport { type MulticallBlockCall, readBlockAndAggregate, requireReturnData } from './multicallBlock'\n\n// Sentinel ticks used by PanopticQuery to indicate \"no liquidation at this boundary\"\nconst MIN_TICK = -887272n\nconst MAX_TICK = 887272n\n\nconst FP96 = 1n << 96n\nconst Q128 = 1n << 128n\n\n/**\n * Convert a token0 amount to its token1-equivalent at the given sqrtPriceX96.\n *\n * Matches the on-chain `PanopticMath.convert0to1` truncation, with an\n * overflow-safe branch when `sqrtPriceX96^2` would not fit in uint256.\n */\nfunction convert0to1(amount: bigint, sqrtPriceX96: bigint): bigint {\n if (sqrtPriceX96 < Q128) {\n return (amount * sqrtPriceX96 * sqrtPriceX96) >> 192n\n }\n // amount * (sqrtPriceX96 * sqrtPriceX96 >> 64n) >> 128n\n const sp2Hi = (sqrtPriceX96 * sqrtPriceX96) >> 64n\n return (amount * sp2Hi) >> 128n\n}\n\n/**\n * Convert a token1 amount to its token0-equivalent at the given sqrtPriceX96.\n */\nfunction convert1to0(amount: bigint, sqrtPriceX96: bigint): bigint {\n if (sqrtPriceX96 < Q128) {\n const denom = sqrtPriceX96 * sqrtPriceX96\n return (amount * (1n << 192n)) / denom\n }\n const sp2Hi = (sqrtPriceX96 * sqrtPriceX96) >> 64n\n return (amount * (1n << 128n)) / sp2Hi\n}\n\n/**\n * Parameters for {@link getMarginBuffer}.\n */\nexport interface GetMarginBufferParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenIds of open positions (loan/credit width=0 legs included) */\n tokenIds: bigint[]\n /** PanopticQuery address (required for liquidation prices) */\n queryAddress: Address\n /**\n * Optional pre-fetched collateral tracker addresses (saves an RPC).\n * If omitted, they are fetched from the pool.\n */\n collateralAddresses?: { collateralToken0: Address; collateralToken1: Address }\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Margin buffer result with distance-to-liquidation.\n *\n * **Denomination**: Both slots are populated with the account total\n * cross-converted into a single token denomination so they can be\n * compared directly.\n *\n * - `currentMargin0` / `requiredMargin0` / `buffer0` are denominated in **token0**.\n * - `currentMargin1` / `requiredMargin1` / `buffer1` are denominated in **token1**.\n *\n * `denominatedInToken` indicates which of the two pairs is \"preferred\":\n * 0 when `currentTick < 0`, 1 otherwise — matching the historical\n * `checkCollateral` convention so downstream consumers keep working\n * without changes.\n */\nexport interface MarginBuffer {\n /** Excess margin in token0 units (positive = safe, negative = shortfall) */\n buffer0: bigint\n /** Excess margin in token1 units (positive = safe, negative = shortfall) */\n buffer1: bigint\n /** Buffer as percentage of required margin in bps (slot 0). null if no requirement. */\n bufferPercent0: bigint | null\n /** Buffer as percentage of required margin in bps (slot 1). null if no requirement. */\n bufferPercent1: bigint | null\n /** Current (gross) account collateral, denominated in token0 */\n currentMargin0: bigint\n /** Current (gross) account collateral, denominated in token1 */\n currentMargin1: bigint\n /**\n * Sum of per-position collateral requirements from\n * `getFullPositionsData.collateralRequirements[]`, denominated in token0.\n * Loans/credits (width=0) contribute correctly.\n */\n requiredMargin0: bigint\n /** Same, denominated in token1 */\n requiredMargin1: bigint\n /**\n * Which token the \"preferred\" margin values are denominated in.\n * 0 = token0 (when currentTick < 0), 1 = token1 (when currentTick >= 0).\n */\n denominatedInToken: 0 | 1\n /** Tick distance to nearest liquidation boundary (null if no liquidation boundaries) */\n liquidationDistance: bigint | null\n /** Lower liquidation tick (null if safe at MIN_TICK) */\n lowerLiquidationTick: bigint | null\n /** Upper liquidation tick (null if safe at MAX_TICK) */\n upperLiquidationTick: bigint | null\n /** Current tick */\n currentTick: bigint\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Get margin buffer and distance-to-liquidation for an account.\n *\n * Reads, all pinned to the same block:\n * - `getCurrentTick` (sequencing dependency for sqrtPrice conversion)\n * - `getFullPositionsData(account, true, tokenIds)` → collateralRequirements\n * - `CollateralTracker.assetsOf(account)` on both trackers → gross collateral\n * - `PanopticQuery.getLiquidationPrices(...)` → liquidation boundaries\n *\n * @param params - The parameters\n * @returns Margin buffer with liquidation distance and block metadata\n */\nexport async function getMarginBuffer(params: GetMarginBufferParams): Promise<MarginBuffer> {\n const { client, poolAddress, account, tokenIds, queryAddress, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Resolve collateral tracker addresses (immutable; cache-friendly).\n let collateralToken0: Address\n let collateralToken1: Address\n if (params.collateralAddresses) {\n collateralToken0 = params.collateralAddresses.collateralToken0\n collateralToken1 = params.collateralAddresses.collateralToken1\n } else {\n const addrs = await client.multicall({\n contracts: [\n { address: poolAddress, abi: panopticPoolV2Abi, functionName: 'collateralToken0' },\n { address: poolAddress, abi: panopticPoolV2Abi, functionName: 'collateralToken1' },\n ],\n blockNumber: targetBlockNumber,\n allowFailure: false,\n })\n collateralToken0 = addrs[0]\n collateralToken1 = addrs[1]\n }\n\n const hasPositions = tokenIds.length > 0\n const calls: MulticallBlockCall[] = [\n {\n target: poolAddress,\n callData: encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n }),\n },\n {\n target: collateralToken0,\n callData: encodeFunctionData({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n args: [account],\n }),\n },\n {\n target: collateralToken1,\n callData: encodeFunctionData({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n args: [account],\n }),\n },\n ]\n\n const positionDataIndex = hasPositions ? calls.length : null\n if (positionDataIndex !== null) {\n calls.push({\n target: poolAddress,\n callData: encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, true, tokenIds],\n }),\n })\n }\n\n const liqPricesIndex = hasPositions ? calls.length : null\n if (liqPricesIndex !== null) {\n calls.push({\n target: queryAddress,\n callData: encodeFunctionData({\n abi: panopticQueryAbi,\n functionName: 'getLiquidationPrices',\n args: [poolAddress, account, tokenIds],\n }),\n })\n }\n\n const { _meta, results } = await readBlockAndAggregate({\n client,\n calls,\n blockNumber: targetBlockNumber,\n })\n\n const currentTickResult = decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n data: requireReturnData(results, 0, 'PanopticPool.getCurrentTick'),\n })\n const currentTick = BigInt(currentTickResult)\n const assets0 = decodeFunctionResult({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n data: requireReturnData(results, 1, 'CollateralTracker.assetsOf token0'),\n })\n const assets1 = decodeFunctionResult({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n data: requireReturnData(results, 2, 'CollateralTracker.assetsOf token1'),\n })\n const positionDataResult =\n positionDataIndex === null\n ? null\n : (decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n data: requireReturnData(results, positionDataIndex, 'PanopticPool.getFullPositionsData'),\n }) as readonly [bigint, bigint, readonly bigint[], readonly bigint[], readonly bigint[]])\n const liqPricesResult =\n liqPricesIndex === null\n ? null\n : (decodeFunctionResult({\n abi: panopticQueryAbi,\n functionName: 'getLiquidationPrices',\n data: requireReturnData(results, liqPricesIndex, 'PanopticQuery.getLiquidationPrices'),\n }) as readonly [number, number])\n\n // Sum collateral requirements across all positions, per token.\n let required0Native = 0n\n let required1Native = 0n\n if (positionDataResult) {\n const collateralRequirements = positionDataResult[3]\n for (const packed of collateralRequirements) {\n const decoded = decodeLeftRightUnsigned(packed)\n required0Native += decoded.right // token0\n required1Native += decoded.left // token1\n }\n }\n\n // Cross-convert into a single denomination at current tick.\n // The conversion mirrors PanopticQuery.checkCollateral's effective-balance\n // shape so downstream callers keep their existing per-slot interpretation.\n const sqrtPriceX96 = tickToSqrtPriceX96(currentTick)\n const denominatedInToken: 0 | 1 = sqrtPriceX96 < FP96 ? 0 : 1\n\n // Token0-denominated totals\n const currentMargin0 = assets0 + convert1to0(assets1, sqrtPriceX96)\n const requiredMargin0 = required0Native + convert1to0(required1Native, sqrtPriceX96)\n // Token1-denominated totals\n const currentMargin1 = assets1 + convert0to1(assets0, sqrtPriceX96)\n const requiredMargin1 = required1Native + convert0to1(required0Native, sqrtPriceX96)\n\n const buffer0 = currentMargin0 - requiredMargin0\n const buffer1 = currentMargin1 - requiredMargin1\n const bufferPercent0 = requiredMargin0 === 0n ? null : (buffer0 * 10000n) / requiredMargin0\n const bufferPercent1 = requiredMargin1 === 0n ? null : (buffer1 * 10000n) / requiredMargin1\n\n // Liquidation prices: present only when the account has positions.\n let lowerLiquidationTick: bigint | null = null\n let upperLiquidationTick: bigint | null = null\n let liquidationDistance: bigint | null = null\n if (liqPricesResult) {\n const liqPriceDown = BigInt(liqPricesResult[0])\n const liqPriceUp = BigInt(liqPricesResult[1])\n lowerLiquidationTick = liqPriceDown === MIN_TICK ? null : liqPriceDown\n upperLiquidationTick = liqPriceUp === MAX_TICK ? null : liqPriceUp\n if (lowerLiquidationTick !== null && upperLiquidationTick !== null) {\n const distLower = currentTick - lowerLiquidationTick\n const distUpper = upperLiquidationTick - currentTick\n liquidationDistance = distLower < distUpper ? distLower : distUpper\n } else if (lowerLiquidationTick !== null) {\n liquidationDistance = currentTick - lowerLiquidationTick\n } else if (upperLiquidationTick !== null) {\n liquidationDistance = upperLiquidationTick - currentTick\n }\n }\n\n return {\n buffer0,\n buffer1,\n bufferPercent0,\n bufferPercent1,\n currentMargin0,\n currentMargin1,\n requiredMargin0,\n requiredMargin1,\n denominatedInToken,\n liquidationDistance,\n lowerLiquidationTick,\n upperLiquidationTick,\n currentTick,\n _meta,\n }\n}\n","/**\n * Delta hedging utilities for the Panoptic v2 SDK.\n *\n * Provides functions to calculate loan parameters needed\n * to achieve a target delta for option positions.\n *\n * @module v2/reads/hedge\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { PanopticValidationError } from '../errors/sdk'\nimport { calculatePositionDelta } from '../greeks'\nimport { decodeTokenId } from '../tokenId'\nimport type { LegConfig } from '../tokenId/builder'\nimport type { BlockMeta } from '../types'\nimport { getPool } from './pool'\n\n/**\n * Parameters for getDeltaHedgeParams.\n */\nexport interface GetDeltaHedgeParamsInput {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID */\n chainId: bigint\n /**\n * TokenId of the option position to hedge.\n * Optional when both `currentDelta` and `asset` are provided (whole-portfolio hedging).\n */\n tokenId?: bigint\n /**\n * Position size in contracts.\n * Optional when both `currentDelta` and `asset` are provided.\n */\n positionSize?: bigint\n /** Target delta (WAD-scaled, 0n for delta-neutral) */\n targetDelta: bigint\n /** Optional: current delta if adjusting existing position (WAD-scaled) */\n currentDelta?: bigint\n /**\n * Primary asset index (0n or 1n). Used to determine hedge direction.\n * Required when `tokenId` is not provided; ignored when `tokenId` is provided.\n */\n asset?: bigint\n /** Optional: tick at mint (defaults to current tick if not provided) */\n mintTick?: bigint\n /** Optional: block number for historical queries */\n blockNumber?: bigint\n /** Optional: current tick (skips getPool() when both currentTick and tickSpacing are provided) */\n currentTick?: bigint\n /** Optional: pool tick spacing (skips getPool() when both currentTick and tickSpacing are provided) */\n tickSpacing?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n\n // --- Simulation convergence options ---\n\n /**\n * Simulate the hedge swap and return the post-swap tick.\n * When provided (along with `computeDeltaAtTick`), an iterative loop refines\n * the hedge size to account for AMM price impact.\n */\n simulateSwap?: (hedgeAmount: bigint, hedgeLeg: LegConfig) => Promise<{ tickAfter: bigint } | null>\n\n /**\n * Recompute portfolio delta at a given tick.\n * Required when `simulateSwap` is provided.\n */\n computeDeltaAtTick?: (tick: bigint) => bigint\n\n /** Total position size — used for convergence check (sizeDelta * 10000 / totalPositionSize) */\n totalPositionSize?: bigint\n\n /** Max simulation iterations (default 5) */\n maxSimIterations?: number\n\n /** Convergence threshold in bps (default 10). Loop stops when size change < this. */\n convergenceThresholdBps?: bigint\n}\n\n/**\n * Result of getDeltaHedgeParams.\n */\nexport interface DeltaHedgeResult {\n /** LegConfig to add to the position for hedging */\n hedgeLeg: LegConfig\n /** The hedge amount (in position size units) */\n hedgeAmount: bigint\n /** Always 'loan' — the tokenType determines the delta direction */\n hedgeType: 'loan' | 'credit'\n /** Whether the hedge position should be opened with swapAtMint */\n swapAtMint: boolean\n /** Current position delta (WAD-scaled) */\n currentDelta: bigint\n /** Target delta (WAD-scaled) */\n targetDelta: bigint\n /** Delta adjustment needed (WAD-scaled) */\n deltaAdjustment: bigint\n /** Block metadata */\n _meta: BlockMeta\n /** Number of simulation iterations used (0 if no simulateSwap) */\n simulationIterations: number\n /** Post-swap tick from final simulation (undefined if no simulation) */\n simulatedTickAfter?: bigint\n /** Whether the convergence loop converged within threshold */\n converged: boolean\n}\n\n/**\n * Calculate loan parameters to achieve target delta via swapAtMint.\n *\n * Both delta directions use loans with swapAtMint — the tokenType\n * determines whether delta is added or removed:\n *\n * - **Need positive delta** (e.g. hedging a short call):\n * Loan with tokenType = numeraire + swapAtMint.\n * Borrows numeraire (e.g. USDC), swaps to asset (e.g. ETH).\n * Net: +asset exposure → positive delta.\n *\n * - **Need negative delta** (e.g. hedging a short put):\n * Loan with tokenType = asset + swapAtMint.\n * Borrows asset (e.g. ETH), swaps to numeraire (e.g. USDC).\n * Net: −asset exposure → negative delta.\n *\n * ## Example: Delta-neutral short call\n * ```typescript\n * const hedge = await getDeltaHedgeParams({\n * client, poolAddress, chainId,\n * tokenId: shortCallTokenId,\n * positionSize: 1000000000000000n,\n * targetDelta: 0n,\n * })\n *\n * // Open the hedge as a separate position with swapAtMint\n * const hedgeTokenId = builder\n * .addLoan({ tokenType: hedge.hedgeLeg.tokenType, strike: hedge.hedgeLeg.strike })\n * .build()\n *\n * await openPosition({ ..., tokenId: hedgeTokenId,\n * positionSize: hedge.hedgeAmount, swapAtMint: hedge.swapAtMint })\n * ```\n *\n * @param params - The parameters\n * @returns Delta hedge result with LegConfig (always a loan)\n */\nexport async function getDeltaHedgeParams(\n params: GetDeltaHedgeParamsInput,\n): Promise<DeltaHedgeResult> {\n const {\n client,\n poolAddress,\n chainId,\n tokenId,\n positionSize,\n targetDelta,\n currentDelta: providedCurrentDelta,\n asset: providedAsset,\n mintTick: providedMintTick,\n blockNumber,\n currentTick: providedCurrentTick,\n tickSpacing: providedTickSpacing,\n } = params\n\n // Validate: need either tokenId or (currentDelta + asset)\n const hasTokenId = tokenId !== undefined\n const hasDirectDelta = providedCurrentDelta !== undefined && providedAsset !== undefined\n\n if (!hasTokenId && !hasDirectDelta) {\n throw new PanopticValidationError(\n 'getDeltaHedgeParams requires either `tokenId` or both `currentDelta` and `asset`',\n )\n }\n\n // Validate simulateSwap and computeDeltaAtTick are provided together\n if ((params.simulateSwap !== undefined) !== (params.computeDeltaAtTick !== undefined)) {\n throw new PanopticValidationError(\n 'getDeltaHedgeParams: simulateSwap and computeDeltaAtTick must be provided together',\n )\n }\n\n // If both currentTick and tickSpacing are provided, skip the full getPool() call\n let currentTick: bigint\n let tickSpacing: bigint\n let poolMeta: BlockMeta\n\n if (providedCurrentTick !== undefined && providedTickSpacing !== undefined) {\n currentTick = providedCurrentTick\n tickSpacing = providedTickSpacing\n poolMeta =\n params._meta ??\n (await getBlockMeta({ client, blockNumber: blockNumber ?? (await client.getBlockNumber()) }))\n } else {\n const pool = await getPool({\n client,\n poolAddress,\n chainId,\n blockNumber,\n })\n currentTick = pool.currentTick\n tickSpacing = pool.tickSpacing\n poolMeta = pool._meta\n }\n\n // Determine primary asset and current delta\n let primaryAsset: bigint\n let currentDelta: bigint\n\n if (hasTokenId) {\n // Decode the tokenId to get legs\n const decoded = decodeTokenId(tokenId)\n primaryAsset = decoded.legs.length > 0 ? decoded.legs[0].asset : 0n\n\n // Use provided mintTick or default to currentTick\n const mintTick = providedMintTick ?? currentTick\n\n // Calculate position delta if not provided\n currentDelta =\n providedCurrentDelta ??\n calculatePositionDelta({\n legs: decoded.legs,\n currentTick,\n mintTick,\n positionSize: positionSize!,\n poolTickSpacing: tickSpacing,\n })\n } else {\n // Direct delta + asset mode (whole-portfolio hedging)\n if (providedAsset !== 0n && providedAsset !== 1n) {\n throw new PanopticValidationError(\n `getDeltaHedgeParams: asset must be 0n or 1n, got ${providedAsset}`,\n )\n }\n primaryAsset = providedAsset\n currentDelta = providedCurrentDelta!\n }\n\n // deltaAdjustment = targetDelta - currentDelta\n // Positive → need to add positive delta; Negative → need to add negative delta.\n const deltaAdjustment = targetDelta - currentDelta\n\n // Delta is in asset smallest units. A loan+swapAtMint of size X gives\n // effective delta ≈ ±X (in asset smallest units). So hedgeAmount = |deltaAdjustment|.\n const absDeltaAdjustment = deltaAdjustment < 0n ? -deltaAdjustment : deltaAdjustment\n let hedgeAmount = absDeltaAdjustment\n\n const numeraire = primaryAsset === 0n ? 1n : 0n\n\n // Both directions use a loan + swapAtMint. The tokenType determines direction:\n // deltaAdjustment > 0 (need +delta): loan numeraire → swap to asset → +asset exposure\n // deltaAdjustment < 0 (need −delta): loan asset → swap to numeraire → −asset exposure\n const needPositiveDelta = deltaAdjustment > 0n\n const hedgeTokenType = needPositiveDelta ? numeraire : primaryAsset\n\n const hedgeLeg: LegConfig = {\n asset: primaryAsset,\n optionRatio: 1n,\n isLong: false, // Always a loan\n tokenType: hedgeTokenType,\n strike: (currentTick / tickSpacing) * tickSpacing, // Round to tick spacing\n width: 0n, // Loan/credit indicator\n }\n\n // --- Simulation convergence loop ---\n const {\n simulateSwap,\n computeDeltaAtTick,\n totalPositionSize,\n maxSimIterations = 5,\n convergenceThresholdBps = 10n,\n } = params\n\n let simulationIterations = 0\n let simulatedTickAfter: bigint | undefined\n let converged = true\n\n if (simulateSwap && computeDeltaAtTick) {\n if (totalPositionSize === undefined || totalPositionSize === 0n) {\n throw new PanopticValidationError(\n 'getDeltaHedgeParams: totalPositionSize is required and must be > 0 when simulateSwap is provided',\n )\n }\n\n converged = false\n\n for (let i = 0; i < maxSimIterations; i++) {\n simulationIterations = i + 1\n\n const simResult = await simulateSwap(hedgeAmount, hedgeLeg)\n if (simResult == null) break\n\n simulatedTickAfter = simResult.tickAfter\n\n // Recompute portfolio delta at the post-swap tick\n const adjustedDelta = computeDeltaAtTick(simResult.tickAfter)\n const newAdjustment = targetDelta - adjustedDelta\n const newAmount = newAdjustment < 0n ? -newAdjustment : newAdjustment\n\n // Convergence check\n const sizeDelta = newAmount > hedgeAmount ? newAmount - hedgeAmount : hedgeAmount - newAmount\n const sizeChangeBps = (sizeDelta * 10000n) / totalPositionSize\n\n hedgeAmount = newAmount\n\n if (sizeChangeBps <= convergenceThresholdBps || sizeDelta === 0n) {\n converged = true\n break\n }\n }\n }\n\n return {\n hedgeLeg,\n hedgeAmount,\n hedgeType: 'loan',\n swapAtMint: true,\n currentDelta,\n targetDelta,\n deltaAdjustment,\n _meta: poolMeta,\n simulationIterations,\n simulatedTickAfter,\n converged,\n }\n}\n","/**\n * Collateral share price read for the Panoptic v2 SDK.\n *\n * Reads totalAssets and totalSupply from two CollateralTracker contracts\n * to compute share prices. Designed for APY calculations at historical blocks.\n *\n * @module v2/reads/collateralSharePrice\n */\n\nimport type { Address, Client } from 'viem'\nimport { ContractFunctionExecutionError } from 'viem'\nimport { multicall } from 'viem/actions'\n\nimport { collateralTrackerV2Abi } from '../../../generated'\n\n/**\n * Raw share price data for a single collateral tracker.\n */\nexport interface CollateralSharePriceData {\n totalAssets: bigint\n totalSupply: bigint\n}\n\n/**\n * Get totalAssets and totalSupply for two CollateralTracker contracts in a single multicall.\n *\n * Consumers can compute share price as `totalAssets / totalSupply` using their\n * preferred precision library (e.g. Decimal.js).\n *\n * If the collateral tracker reverts (e.g. uninitialized), returns zeros.\n *\n * @param collateralAddresses - Tuple of [token0 tracker, token1 tracker] addresses\n * @param blockNumber - Block number to query at\n * @param client - viem Client\n * @returns Tuple of raw share price data\n */\nexport async function getCollateralSharePrices(\n collateralAddresses: [Address, Address],\n blockNumber: bigint,\n client: Client,\n): Promise<[CollateralSharePriceData, CollateralSharePriceData]> {\n try {\n const results = await multicall(client, {\n contracts: [\n {\n address: collateralAddresses[0],\n abi: collateralTrackerV2Abi,\n functionName: 'totalAssets',\n },\n {\n address: collateralAddresses[0],\n abi: collateralTrackerV2Abi,\n functionName: 'totalSupply',\n },\n {\n address: collateralAddresses[1],\n abi: collateralTrackerV2Abi,\n functionName: 'totalAssets',\n },\n {\n address: collateralAddresses[1],\n abi: collateralTrackerV2Abi,\n functionName: 'totalSupply',\n },\n ],\n blockNumber,\n allowFailure: false,\n })\n\n const [assets0, supply0, assets1, supply1] = results\n\n return [\n { totalAssets: assets0, totalSupply: supply0 },\n { totalAssets: assets1, totalSupply: supply1 },\n ]\n } catch (e: unknown) {\n if (e instanceof ContractFunctionExecutionError) {\n return [\n { totalAssets: 0n, totalSupply: 0n },\n { totalAssets: 0n, totalSupply: 0n },\n ]\n }\n throw e\n }\n}\n","/**\n * Batch read of CollateralTracker.totalAssets() for multiple trackers.\n *\n * @module v2/reads/collateralTotalAssets\n */\n\nimport type { Address, Client } from 'viem'\nimport { getAddress, zeroAddress } from 'viem'\nimport { multicall } from 'viem/actions'\n\nimport { collateralTrackerV2Abi } from '../../../generated'\n\n/**\n * Get totalAssets for multiple CollateralTracker contracts in a single multicall.\n *\n * @param client - viem Client\n * @param collateralTrackerAddresses - Array of CollateralTracker addresses\n * @param chainId - Chain ID (for multicall routing)\n * @param blockNumber - Optional block number for historical queries\n * @returns Array of totalAssets (bigint) in the same order as input addresses\n */\nexport async function getCollateralTotalAssetsBatch(\n client: Client,\n collateralTrackerAddresses: Address[],\n chainId: number,\n blockNumber?: bigint,\n): Promise<bigint[]> {\n if (collateralTrackerAddresses.length === 0) return []\n\n try {\n const contracts = collateralTrackerAddresses.map((address) => ({\n address: getAddress(address ?? zeroAddress),\n abi: collateralTrackerV2Abi,\n functionName: 'totalAssets' as const,\n chainId,\n }))\n\n const results = await multicall(client, {\n contracts,\n blockNumber,\n allowFailure: false,\n })\n\n return results.map((result) => BigInt(result ?? 0))\n } catch (error) {\n console.error('Error reading collateral total assets:', error)\n return collateralTrackerAddresses.map(() => 0n)\n }\n}\n","/**\n * Account buying power read function for the Panoptic v2 SDK.\n *\n * Sources gross collateral from `CollateralTracker.assetsOf` and per-position\n * required margin from `PanopticPool.getFullPositionsData.collateralRequirements[]`,\n * cross-converted to both token denominations at the current tick.\n *\n * This replaces the prior `PanopticQuery.checkCollateral` (3-arg, oracle-ticks\n * overload) implementation that netted loan tokenId debt out of the balance\n * and excluded loans from required-collateral, causing buying-power readouts\n * to be wildly wrong for any account that had borrowed.\n *\n * @module v2/reads/buyingPower\n */\n\nimport type { Address, Client } from 'viem'\nimport { decodeFunctionResult, encodeFunctionData } from 'viem'\nimport { multicall } from 'viem/actions'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi } from '../../../generated'\nimport { tickToSqrtPriceX96 } from '../formatters/tick'\nimport type { BlockMeta } from '../types'\nimport { decodeLeftRightUnsigned } from '../writes/utils'\nimport { type MulticallBlockCall, readBlockAndAggregate, requireReturnData } from './multicallBlock'\n\nconst Q128 = 1n << 128n\n\nfunction convert0to1(amount: bigint, sqrtPriceX96: bigint): bigint {\n if (sqrtPriceX96 < Q128) {\n return (amount * sqrtPriceX96 * sqrtPriceX96) >> 192n\n }\n const sp2Hi = (sqrtPriceX96 * sqrtPriceX96) >> 64n\n return (amount * sp2Hi) >> 128n\n}\n\nfunction convert1to0(amount: bigint, sqrtPriceX96: bigint): bigint {\n if (sqrtPriceX96 < Q128) {\n const denom = sqrtPriceX96 * sqrtPriceX96\n return (amount * (1n << 192n)) / denom\n }\n const sp2Hi = (sqrtPriceX96 * sqrtPriceX96) >> 64n\n return (amount * (1n << 128n)) / sp2Hi\n}\n\n/**\n * Parameters for getAccountBuyingPower.\n */\nexport interface GetAccountBuyingPowerParams {\n /** viem Client (PublicClient or basic Client with transport) */\n client: Client\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenIds of open positions */\n tokenIds: bigint[]\n /** PanopticQuery address (kept for backwards compatibility; unused). */\n queryAddress?: Address\n /**\n * Optional pre-fetched collateral tracker addresses (saves an RPC).\n * If omitted, they are fetched from the pool.\n */\n collateralAddresses?: { collateralToken0: Address; collateralToken1: Address }\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips block metadata fetch) */\n _meta?: BlockMeta\n}\n\n/**\n * Result of getAccountBuyingPower.\n *\n * Both per-token values are the **gross** account total cross-converted\n * into the respective single-token denomination at the current tick:\n * - `collateralBalance0` / `requiredCollateral0` are in token0 units\n * - `collateralBalance1` / `requiredCollateral1` are in token1 units\n */\nexport interface AccountBuyingPower {\n /** Gross collateral (deposits + borrowed shares), denominated in token0 */\n collateralBalance0: bigint\n /** Sum of per-position collateral requirements, denominated in token0 */\n requiredCollateral0: bigint\n /** Gross collateral (deposits + borrowed shares), denominated in token1 */\n collateralBalance1: bigint\n /** Sum of per-position collateral requirements, denominated in token1 */\n requiredCollateral1: bigint\n /** Block metadata for the Multicall3 aggregate read */\n _meta: BlockMeta\n}\n\n/**\n * Get account-level buying power.\n *\n * Uses {@link https://github.com/panoptic-xyz CollateralTracker.assetsOf} for\n * gross collateral and `PanopticPool.getFullPositionsData.collateralRequirements[]`\n * for the per-position required margin — so loan tokenIds (width=0 shorts)\n * contribute to the requirement instead of being netted out of the balance.\n *\n * Accepts a plain viem `Client` (not just `PublicClient`) so it works with wagmi's\n * `useClient()` without needing a cast.\n *\n * @param params - The parameters\n * @returns Account buying power data with optional block metadata\n */\nexport async function getAccountBuyingPower(\n params: GetAccountBuyingPowerParams,\n): Promise<AccountBuyingPower> {\n const { client, poolAddress, account, tokenIds } = params\n const blockNumber = params.blockNumber ?? params._meta?.blockNumber\n\n // Resolve collateral tracker addresses (immutable; cache-friendly).\n let collateralToken0: Address\n let collateralToken1: Address\n if (params.collateralAddresses) {\n collateralToken0 = params.collateralAddresses.collateralToken0\n collateralToken1 = params.collateralAddresses.collateralToken1\n } else {\n const addrs = await multicall(client, {\n contracts: [\n { address: poolAddress, abi: panopticPoolV2Abi, functionName: 'collateralToken0' },\n { address: poolAddress, abi: panopticPoolV2Abi, functionName: 'collateralToken1' },\n ],\n blockNumber,\n allowFailure: false,\n })\n collateralToken0 = addrs[0]\n collateralToken1 = addrs[1]\n }\n\n const calls: MulticallBlockCall[] = [\n {\n target: poolAddress,\n callData: encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n }),\n },\n {\n target: collateralToken0,\n callData: encodeFunctionData({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n args: [account],\n }),\n },\n {\n target: collateralToken1,\n callData: encodeFunctionData({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n args: [account],\n }),\n },\n ]\n\n const positionDataIndex = tokenIds.length > 0 ? calls.length : null\n if (positionDataIndex !== null) {\n calls.push({\n target: poolAddress,\n callData: encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, true, tokenIds],\n }),\n })\n }\n\n const { _meta, results } = await readBlockAndAggregate({ client, calls, blockNumber })\n\n const currentTickResult = decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n data: requireReturnData(results, 0, 'PanopticPool.getCurrentTick'),\n })\n const assets0 = decodeFunctionResult({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n data: requireReturnData(results, 1, 'CollateralTracker.assetsOf token0'),\n })\n const assets1 = decodeFunctionResult({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n data: requireReturnData(results, 2, 'CollateralTracker.assetsOf token1'),\n })\n const currentTick = BigInt(currentTickResult)\n const positionDataResult =\n positionDataIndex === null\n ? null\n : (decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n data: requireReturnData(results, positionDataIndex, 'PanopticPool.getFullPositionsData'),\n }) as readonly [bigint, bigint, readonly bigint[], readonly bigint[], readonly bigint[]])\n\n // Sum collateral requirements across positions, per token.\n let required0Native = 0n\n let required1Native = 0n\n if (positionDataResult) {\n const collateralRequirements = positionDataResult[3]\n for (const packed of collateralRequirements) {\n const decoded = decodeLeftRightUnsigned(packed)\n required0Native += decoded.right // token0\n required1Native += decoded.left // token1\n }\n }\n\n // Cross-convert into each single-token denomination at current tick.\n const sqrtPriceX96 = tickToSqrtPriceX96(currentTick)\n const collateralBalance0 = assets0 + convert1to0(assets1, sqrtPriceX96)\n const requiredCollateral0 = required0Native + convert1to0(required1Native, sqrtPriceX96)\n const collateralBalance1 = assets1 + convert0to1(assets0, sqrtPriceX96)\n const requiredCollateral1 = required1Native + convert0to1(required0Native, sqrtPriceX96)\n\n return {\n collateralBalance0,\n requiredCollateral0,\n collateralBalance1,\n requiredCollateral1,\n _meta,\n }\n}\n","/**\n * Open position preview — combines buying power check with open position simulation.\n *\n * @module v2/reads/openPositionPreview\n */\n\nimport type { Address, Client, PublicClient } from 'viem'\n\nimport { AccountInsolventError, NotEnoughTokensError } from '../errors'\nimport { parsePanopticError } from '../errors/parser'\nimport type { SimulateOpenPositionParams } from '../simulations/simulateOpenPosition'\nimport { simulateOpenPosition } from '../simulations/simulateOpenPosition'\nimport type { OpenPositionSimulation, SimulationResult } from '../types'\nimport type { AccountBuyingPower } from './buyingPower'\nimport { getAccountBuyingPower } from './buyingPower'\n\n/**\n * Parameters for getOpenPositionPreview.\n */\nexport interface GetOpenPositionPreviewParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** Existing position IDs held by the account (before this mint) */\n existingPositionIds: bigint[]\n /** TokenId of position to open */\n tokenId: bigint\n /** Position size */\n positionSize: bigint\n /** PanopticQuery address */\n queryAddress: Address\n /** Lower tick limit */\n tickLimitLow: bigint\n /** Upper tick limit */\n tickLimitHigh: bigint\n /** Spread limit (default 0n) */\n spreadLimit?: bigint\n /** Whether to swap at mint */\n swapAtMint?: boolean\n /** Whether to use premia as collateral */\n usePremiaAsCollateral?: boolean\n /** Chain ID (for greeks calculation) */\n chainId?: bigint\n /** Optional block number */\n blockNumber?: bigint\n}\n\n/**\n * Result of getOpenPositionPreview.\n */\nexport interface OpenPositionPreview {\n /** Current buying power (from checkCollateral on existing positions) */\n currentBuyingPower: AccountBuyingPower\n /** Simulation result (from dry-run dispatch) */\n simulation: SimulationResult<OpenPositionSimulation>\n /** Whether the simulated mint succeeded (position is solvent post-mint) */\n isSolvent: boolean\n /** Token 0 amount required (negative delta = deposit). Null if simulation failed. */\n amount0Required: bigint | null\n /** Token 1 amount required. Null if simulation failed. */\n amount1Required: bigint | null\n /** Collateral balance in token 0 after mint. Null if simulation failed. */\n postCollateral0: bigint | null\n /** Collateral balance in token 1 after mint. Null if simulation failed. */\n postCollateral1: bigint | null\n /** Post-mint collateral requirement in token0 (per-token, not cross-margined). Null if sim failed. */\n postMintCollateralReqToken0: bigint | null\n /** Post-mint collateral requirement in token1 (per-token, not cross-margined). Null if sim failed. */\n postMintCollateralReqToken1: bigint | null\n /**\n * Collateral requirement for the new position only (last entry of perPositionCollateralReqs).\n * Use this for \"Margin Used\" display — postMintCollateralReqToken0/1 includes existing positions too.\n * Null if simulation failed or perPositionCollateralReqs is empty.\n */\n newPositionCollateralReqToken0: bigint | null\n /** Collateral requirement for the new position only, token1. Null if sim failed. */\n newPositionCollateralReqToken1: bigint | null\n}\n\n/**\n * Get a preview of opening a position.\n *\n * Composes two calls:\n * 1. `getAccountBuyingPower` — current margin state for existing positions\n * 2. `simulateOpenPosition` — dry-run dispatch to check feasibility & token flows\n *\n * @param params - Preview parameters\n * @returns Preview with buying power, simulation result, and derived convenience fields\n */\nexport async function getOpenPositionPreview(\n params: GetOpenPositionPreviewParams,\n): Promise<OpenPositionPreview> {\n const {\n client,\n poolAddress,\n account,\n existingPositionIds,\n tokenId,\n positionSize,\n queryAddress,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit,\n swapAtMint,\n usePremiaAsCollateral,\n chainId,\n blockNumber,\n } = params\n\n // Run both calls in parallel\n const [currentBuyingPower, simulation] = await Promise.all([\n getAccountBuyingPower({\n client: client as Client,\n poolAddress,\n account,\n tokenIds: existingPositionIds,\n queryAddress,\n blockNumber,\n }),\n simulateOpenPosition({\n client,\n poolAddress,\n account,\n existingPositionIds,\n tokenId,\n positionSize,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit,\n swapAtMint,\n usePremiaAsCollateral,\n chainId,\n blockNumber,\n } satisfies SimulateOpenPositionParams),\n ])\n\n // isSolvent should only be false for actual solvency errors (AccountInsolvent, NotEnoughTokens).\n // Other simulation failures (PriceBoundFail, EffectiveLiquidityAboveThreshold, etc.) are not\n // solvency issues and should not trigger the \"buying power exceeded\" message.\n let isSolvent = true\n if (!simulation.success) {\n const parsed = parsePanopticError(simulation.error)\n const err = parsed?.error ?? simulation.error\n isSolvent = !(err instanceof AccountInsolventError || err instanceof NotEnoughTokensError)\n }\n const data = simulation.success ? simulation.data : null\n\n return {\n currentBuyingPower,\n simulation,\n isSolvent,\n amount0Required: data?.amount0Required ?? null,\n amount1Required: data?.amount1Required ?? null,\n postCollateral0: data?.postCollateral0 ?? null,\n postCollateral1: data?.postCollateral1 ?? null,\n postMintCollateralReqToken0: data?.postMintCollateralReqToken0 ?? null,\n postMintCollateralReqToken1: data?.postMintCollateralReqToken1 ?? null,\n newPositionCollateralReqToken0:\n data?.perPositionCollateralReqs && data.perPositionCollateralReqs.length > 0\n ? (data.perPositionCollateralReqs[data.perPositionCollateralReqs.length - 1]?.token0 ??\n null)\n : null,\n newPositionCollateralReqToken1:\n data?.perPositionCollateralReqs && data.perPositionCollateralReqs.length > 0\n ? (data.perPositionCollateralReqs[data.perPositionCollateralReqs.length - 1]?.token1 ??\n null)\n : null,\n }\n}\n","/**\n * Read the native token (e.g. ETH) price in USD from a PanopticPool's on-chain tick.\n *\n * @module v2/reads/nativeTokenPrice\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { tickToPriceDecimalScaled } from '../formatters/tick'\n\nexport interface GetNativeTokenPriceParams {\n client: PublicClient\n /** Address of a PanopticPool deployed on a native/USD stablecoin underlying pool */\n panopticPoolAddress: Address\n /** Decimals of token0 in the underlying pool */\n token0Decimals: bigint\n /** Decimals of token1 in the underlying pool */\n token1Decimals: bigint\n /** Whether the native asset is token0 (true) or token1 (false) */\n nativeIsToken0: boolean\n}\n\n/**\n * Fetch the native token price in USD by reading `getCurrentTick()` from a\n * PanopticPool deployed on a native/stablecoin pair.\n *\n * @returns The price as a decimal string (e.g. \"2000.00\")\n */\nexport async function getNativeTokenPrice(params: GetNativeTokenPriceParams): Promise<string> {\n const { client, panopticPoolAddress, token0Decimals, token1Decimals, nativeIsToken0 } = params\n\n const currentTick = await client.readContract({\n address: panopticPoolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n })\n\n // tickToPriceDecimalScaled returns token0/token1 price (price of token0 denominated in token1).\n // If nativeIsToken0: price = USD per native (what we want)\n // If !nativeIsToken0: price = native per USD → invert by swapping decimals\n if (nativeIsToken0) {\n return tickToPriceDecimalScaled(BigInt(currentTick), token0Decimals, token1Decimals, 2n)\n } else {\n // Swap decimals to get the inverse price\n return tickToPriceDecimalScaled(BigInt(currentTick), token1Decimals, token0Decimals, 2n)\n }\n}\n","/**\n * Account trade history for the Panoptic v2 SDK.\n *\n * Fetches OptionMinted and OptionBurnt events filtered by account address\n * using indexed topic filtering for RPC efficiency (2 calls total).\n *\n * @module v2/reads/history\n */\n\nimport type { Address, Hash, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport type { BlockMeta } from '../types'\nimport { decodePositionBalance } from '../writes/utils'\n\n/**\n * A single trade (mint or burn) in the account's history.\n */\nexport interface AccountTrade {\n /** Whether this was a mint or burn */\n action: 'mint' | 'burn'\n /** TokenId of the position */\n tokenId: bigint\n /** Position size */\n positionSize: bigint\n /** Block number of the trade */\n blockNumber: bigint\n /** Transaction hash */\n transactionHash: Hash\n /** Log index within the block */\n logIndex: bigint\n /** Tick at mint (only for mints) */\n tickAtMint?: bigint\n /** Timestamp at mint in Unix seconds (only for mints) */\n timestampAtMint?: bigint\n /** Whether a swap occurred at mint (only for mints) */\n swapAtMint?: boolean\n /** Pool utilization for token 0 at mint (only for mints) */\n poolUtilization0?: bigint\n /** Pool utilization for token 1 at mint (only for mints) */\n poolUtilization1?: bigint\n /** Premia settled per leg on burn (only for burns) */\n premiaByLeg?: readonly [bigint, bigint, bigint, bigint]\n}\n\n/**\n * Account history result.\n */\nexport interface AccountHistory {\n /** All trades sorted by block number ascending, then log index */\n trades: AccountTrade[]\n /** Block metadata at query time */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for getAccountHistory.\n */\nexport interface GetAccountHistoryParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address to fetch history for */\n account: Address\n /** Start block (default: 0n) */\n fromBlock?: bigint\n /** End block (default: latest) */\n toBlock?: bigint\n /** Optional block number for _meta (default: toBlock or latest) */\n blockNumber?: bigint\n}\n\n/**\n * Fetch trade history for an account on a specific pool.\n *\n * Uses indexed topic filtering on the `recipient` field of OptionMinted\n * and OptionBurnt events, resulting in exactly 2 RPC calls regardless\n * of the number of trades.\n *\n * @param params - Query parameters\n * @returns Account trade history sorted chronologically\n *\n * @example\n * ```typescript\n * const history = await getAccountHistory({\n * client,\n * poolAddress,\n * account: '0x...',\n * fromBlock: 18_000_000n,\n * })\n *\n * for (const trade of history.trades) {\n * console.log(`${trade.action} tokenId=${trade.tokenId} size=${trade.positionSize}`)\n * }\n * ```\n */\nexport async function getAccountHistory(params: GetAccountHistoryParams): Promise<AccountHistory> {\n const { client, poolAddress, account, fromBlock = 0n, toBlock, blockNumber } = params\n\n const effectiveToBlock = toBlock ?? blockNumber ?? (await client.getBlockNumber())\n const metaBlockNumber = blockNumber ?? effectiveToBlock\n\n // Fetch mints and burns in parallel — 2 RPC calls total.\n // Both events have `recipient` as indexed topic[1], so the RPC node\n // filters server-side via the topic hash.\n const [mintLogs, burnLogs, _meta] = await Promise.all([\n client.getContractEvents({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n eventName: 'OptionMinted',\n args: { recipient: account },\n fromBlock,\n toBlock: effectiveToBlock,\n }),\n client.getContractEvents({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n eventName: 'OptionBurnt',\n args: { recipient: account },\n fromBlock,\n toBlock: effectiveToBlock,\n }),\n getBlockMeta({ client, blockNumber: metaBlockNumber }),\n ])\n\n const trades: AccountTrade[] = []\n\n // Parse mints\n for (const log of mintLogs) {\n const args = log.args as {\n recipient: Address\n tokenId: bigint\n balanceData: bigint\n }\n const balance = decodePositionBalance(args.balanceData)\n trades.push({\n action: 'mint',\n tokenId: args.tokenId,\n positionSize: balance.positionSize,\n blockNumber: log.blockNumber!,\n transactionHash: log.transactionHash!,\n logIndex: BigInt(log.logIndex!),\n tickAtMint: balance.tickAtMint,\n timestampAtMint: balance.timestampAtMint,\n swapAtMint: balance.swapAtMint,\n poolUtilization0: balance.poolUtilization0,\n poolUtilization1: balance.poolUtilization1,\n })\n }\n\n // Parse burns\n for (const log of burnLogs) {\n const args = log.args as {\n recipient: Address\n tokenId: bigint\n positionSize: bigint\n premiaByLeg: readonly [bigint, bigint, bigint, bigint]\n }\n trades.push({\n action: 'burn',\n tokenId: args.tokenId,\n positionSize: args.positionSize,\n blockNumber: log.blockNumber!,\n transactionHash: log.transactionHash!,\n logIndex: BigInt(log.logIndex!),\n premiaByLeg: args.premiaByLeg,\n })\n }\n\n // Sort chronologically: by block number, then log index\n trades.sort((a, b) => {\n if (a.blockNumber !== b.blockNumber) {\n return a.blockNumber < b.blockNumber ? -1 : 1\n }\n return a.logIndex < b.logIndex ? -1 : 1\n })\n\n return { trades, _meta }\n}\n","/**\n * Historical Uniswap fee reads for the Panoptic v2 SDK.\n *\n * Standalone function for fetching Uniswap fee accrual across historical blocks.\n * Works with any Uniswap V3/V4 pool — no Panoptic pool required.\n *\n * Also used internally by getStreamiaHistory for the Uniswap fee component.\n *\n * @module v2/reads/uniswapFeeHistory\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { stateViewAbi } from '../abis/stateView'\nimport { uniswapV3PoolAbi } from '../abis/uniswapV3Pool'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { InvalidHistoryRangeError } from '../errors/sdk'\nimport type { BlockMeta } from '../types'\nimport type { PoolVersionConfig } from '../types/poolConfig'\nimport type { StreamiaLeg } from '../types/streamia'\n\n// ── Types ──────────────────────────────────────────────────────────────\n\n/** A single snapshot of Uniswap fee data at a particular block. */\nexport interface UniswapFeeSnapshot {\n /** Block number (undefined if queried as latest) */\n blockNumber: bigint | undefined\n /** Uniswap fee delta from the first block in the series */\n fees: { token0: bigint; token1: bigint }\n}\n\n/** Result from getUniswapFeeHistory. */\nexport interface UniswapFeeHistoryResult {\n /** Snapshots in the same order as input blockNumbers */\n snapshots: UniswapFeeSnapshot[]\n /** Block metadata for the latest block used */\n _meta: BlockMeta\n}\n\n/** Parameters for getUniswapFeeHistory. */\nexport interface GetUniswapFeeHistoryParams {\n /** viem PublicClient */\n client: PublicClient\n /** Block numbers to query; undefined entries resolve to latest */\n blockNumbers: (bigint | undefined)[]\n /** Decoded legs with pre-computed liquidity */\n legs: StreamiaLeg[]\n /** Pool version config (carries pool address / StateView + poolId) */\n poolConfig: PoolVersionConfig\n /** Pre-fetched block metadata (skips an extra eth_getBlockByNumber if provided) */\n _meta?: BlockMeta\n}\n\n// ── Public function ────────────────────────────────────────────────────\n\n/**\n * Get historical Uniswap fee accrual for a set of liquidity legs across multiple blocks.\n *\n * Works with any Uniswap V3/V4 pool — no Panoptic pool required.\n * Returns fee deltas relative to the first block in the series.\n *\n * @param params - The parameters\n * @returns Fee snapshots at each block\n */\nexport async function getUniswapFeeHistory(\n params: GetUniswapFeeHistoryParams,\n): Promise<UniswapFeeHistoryResult> {\n const { client, blockNumbers, legs, poolConfig } = params\n\n // Validate legs\n for (const leg of legs) {\n if (leg.lowerTick >= leg.upperTick) {\n throw new InvalidHistoryRangeError(\n `Leg lowerTick (${leg.lowerTick}) must be < upperTick (${leg.upperTick})`,\n )\n }\n if (leg.liquidity <= 0n) {\n throw new InvalidHistoryRangeError(`Leg liquidity must be > 0, got ${leg.liquidity}`)\n }\n }\n\n if (blockNumbers.length === 0 || legs.length === 0) {\n const _meta = params._meta ?? (await getBlockMeta({ client }))\n return { snapshots: [], _meta }\n }\n\n const [blockData, _meta] = await Promise.all([\n fetchUniswapFeeData(client, blockNumbers, legs, poolConfig),\n params._meta ? Promise.resolve(params._meta) : getBlockMeta({ client }),\n ])\n\n let initialFees0: bigint | null = null\n let initialFees1: bigint | null = null\n\n const snapshots: UniswapFeeSnapshot[] = blockData.map((bd, i) => {\n const { total0, total1 } = computeUniswapFeesForBlock(bd, legs)\n\n if (initialFees0 === null) {\n initialFees0 = total0\n initialFees1 = total1\n }\n\n return {\n blockNumber: blockNumbers[i],\n fees: {\n token0: total0 - initialFees0,\n token1: total1 - (initialFees1 as bigint),\n },\n }\n })\n\n return { snapshots, _meta }\n}\n\n// ── Internals (also used by streamiaHistory) ─────────────────────────\n\n/** Raw Uniswap data fetched for a single block. */\nexport interface UniswapBlockData {\n currentTick: number\n feeGrowthGlobal0: bigint\n feeGrowthGlobal1: bigint\n /** Map from tick number → { feeGrowthOutside0, feeGrowthOutside1 } */\n tickData: Map<number, { feeGrowthOutside0: bigint; feeGrowthOutside1: bigint }>\n}\n\n/**\n * Fetch Uniswap pool data for all blocks in parallel.\n * Globals (slot0, feeGrowthGlobal) are fetched ONCE per block, not per-leg.\n * Tick data is fetched for each unique tick across all legs.\n */\nexport async function fetchUniswapFeeData(\n client: PublicClient,\n blockNumbers: (bigint | undefined)[],\n legs: StreamiaLeg[],\n poolConfig: PoolVersionConfig,\n): Promise<UniswapBlockData[]> {\n const uniqueTickSet = new Set<number>()\n for (const leg of legs) {\n uniqueTickSet.add(leg.lowerTick)\n uniqueTickSet.add(leg.upperTick)\n }\n const uniqueTicks = [...uniqueTickSet].sort((a, b) => a - b)\n\n const blockPromises = blockNumbers.map((bn) =>\n fetchUniswapBlockSnapshot(client, bn, uniqueTicks, poolConfig),\n )\n\n return Promise.all(blockPromises)\n}\n\n/**\n * Compute total Uniswap fees for all legs at a single block, using the\n * standard Uniswap V3 fee accumulation formula.\n */\nexport function computeUniswapFeesForBlock(\n blockData: UniswapBlockData,\n legs: StreamiaLeg[],\n): { total0: bigint; total1: bigint } {\n let total0 = 0n\n let total1 = 0n\n\n for (const leg of legs) {\n const lower = blockData.tickData.get(leg.lowerTick)\n const upper = blockData.tickData.get(leg.upperTick)\n if (!lower || !upper) continue\n\n const { feeGrowthGlobal0, feeGrowthGlobal1, currentTick } = blockData\n\n const feesBelow0 =\n currentTick >= leg.lowerTick\n ? lower.feeGrowthOutside0\n : feeGrowthGlobal0 - lower.feeGrowthOutside0\n const feesBelow1 =\n currentTick >= leg.lowerTick\n ? lower.feeGrowthOutside1\n : feeGrowthGlobal1 - lower.feeGrowthOutside1\n\n const feesAbove0 =\n currentTick < leg.upperTick\n ? upper.feeGrowthOutside0\n : feeGrowthGlobal0 - upper.feeGrowthOutside0\n const feesAbove1 =\n currentTick < leg.upperTick\n ? upper.feeGrowthOutside1\n : feeGrowthGlobal1 - upper.feeGrowthOutside1\n\n const fees0 = ((feeGrowthGlobal0 - feesBelow0 - feesAbove0) * leg.liquidity) / (1n << 128n)\n const fees1 = ((feeGrowthGlobal1 - feesBelow1 - feesAbove1) * leg.liquidity) / (1n << 128n)\n\n total0 += fees0\n total1 += fees1\n }\n\n return { total0, total1 }\n}\n\n// ── Block snapshot fetchers ──────────────────────────────────────────\n\nasync function fetchUniswapBlockSnapshot(\n client: PublicClient,\n blockNumber: bigint | undefined,\n uniqueTicks: number[],\n poolConfig: PoolVersionConfig,\n): Promise<UniswapBlockData> {\n if (poolConfig.version === 'v3') {\n return fetchV3BlockSnapshot(client, poolConfig.poolAddress, blockNumber, uniqueTicks)\n } else {\n return fetchV4BlockSnapshot(\n client,\n poolConfig.stateViewAddress,\n poolConfig.poolId,\n blockNumber,\n uniqueTicks,\n )\n }\n}\n\nasync function fetchV3BlockSnapshot(\n client: PublicClient,\n poolAddress: Address,\n blockNumber: bigint | undefined,\n uniqueTicks: number[],\n): Promise<UniswapBlockData> {\n const contracts = [\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'slot0' as const },\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'feeGrowthGlobal0X128' as const },\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'feeGrowthGlobal1X128' as const },\n ...uniqueTicks.map((tick) => ({\n address: poolAddress,\n abi: uniswapV3PoolAbi,\n functionName: 'ticks' as const,\n args: [tick] as const,\n })),\n ]\n\n const results = await client.multicall({ contracts, blockNumber, allowFailure: false })\n\n const slot0Result = results[0] as readonly [\n bigint,\n number,\n number,\n number,\n number,\n number,\n boolean,\n ]\n const feeGrowthGlobal0 = results[1] as bigint\n const feeGrowthGlobal1 = results[2] as bigint\n\n const tickData = new Map<number, { feeGrowthOutside0: bigint; feeGrowthOutside1: bigint }>()\n for (let i = 0; i < uniqueTicks.length; i++) {\n const tickResult = results[3 + i] as readonly [\n bigint,\n bigint,\n bigint,\n bigint,\n bigint,\n bigint,\n number,\n boolean,\n ]\n tickData.set(uniqueTicks[i], {\n feeGrowthOutside0: tickResult[2],\n feeGrowthOutside1: tickResult[3],\n })\n }\n\n return { currentTick: slot0Result[1], feeGrowthGlobal0, feeGrowthGlobal1, tickData }\n}\n\nasync function fetchV4BlockSnapshot(\n client: PublicClient,\n stateViewAddress: Address,\n poolId: `0x${string}`,\n blockNumber: bigint | undefined,\n uniqueTicks: number[],\n): Promise<UniswapBlockData> {\n const contracts = [\n {\n address: stateViewAddress,\n abi: stateViewAbi,\n functionName: 'getSlot0' as const,\n args: [poolId] as const,\n },\n {\n address: stateViewAddress,\n abi: stateViewAbi,\n functionName: 'getFeeGrowthGlobals' as const,\n args: [poolId] as const,\n },\n ...uniqueTicks.map((tick) => ({\n address: stateViewAddress,\n abi: stateViewAbi,\n functionName: 'getTickInfo' as const,\n args: [poolId, tick] as const,\n })),\n ]\n\n const results = await client.multicall({ contracts, blockNumber, allowFailure: false })\n\n const slot0Result = results[0] as readonly [bigint, number, number, number]\n const feeGrowthResult = results[1] as readonly [bigint, bigint]\n\n const tickData = new Map<number, { feeGrowthOutside0: bigint; feeGrowthOutside1: bigint }>()\n for (let i = 0; i < uniqueTicks.length; i++) {\n const tickResult = results[2 + i] as readonly [bigint, bigint, bigint, bigint]\n tickData.set(uniqueTicks[i], {\n feeGrowthOutside0: tickResult[2],\n feeGrowthOutside1: tickResult[3],\n })\n }\n\n return {\n currentTick: slot0Result[1],\n feeGrowthGlobal0: feeGrowthResult[0],\n feeGrowthGlobal1: feeGrowthResult[1],\n tickData,\n }\n}\n","/**\n * Historical streamia (streaming premia) reads for the Panoptic v2 SDK.\n *\n * Fetches Panoptic premia and optionally Uniswap fee accrual across a series\n * of historical block numbers for a single position. Composes\n * getUniswapFeeHistory internally for the Uniswap fee component.\n *\n * @module v2/reads/streamiaHistory\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { InvalidHistoryRangeError } from '../errors/sdk'\nimport type { BlockMeta } from '../types'\nimport type { PoolVersionConfig } from '../types/poolConfig'\nimport type { StreamiaLeg } from '../types/streamia'\nimport { computeUniswapFeesForBlock, fetchUniswapFeeData } from './uniswapFeeHistory'\n\n// Re-export types that were originally defined here for backward compatibility\nexport type { PoolVersionConfig, V3PoolConfig, V4PoolConfig } from '../types/poolConfig'\nexport type { StreamiaLeg } from '../types/streamia'\n\n// ── Types ──────────────────────────────────────────────────────────────\n\n/** A settled premia event, used to subtract already-settled amounts. */\nexport interface SettledEvent {\n /** Block at which settlement occurred */\n blockNumber: bigint\n /** Amount settled for token 0 */\n settled0: bigint\n /** Amount settled for token 1 */\n settled1: bigint\n}\n\n/** Parameters for getStreamiaHistory. */\nexport interface GetStreamiaHistoryParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool contract address */\n panopticPoolAddress: Address\n /** Account whose position to query */\n account: Address\n /** The encoded tokenId */\n tokenId: bigint\n /** Block numbers to query; undefined entries resolve to latest */\n blockNumbers: (bigint | undefined)[]\n /** Decoded legs with pre-computed liquidity */\n legs: StreamiaLeg[]\n /** Pool version config (carries pool address / StateView + poolId) */\n poolConfig: PoolVersionConfig\n /** Whether to include Uniswap fee data (default: true) */\n includeUniswapFees?: boolean\n /** Settled premia events to subtract from Panoptic premia (optional) */\n settledEvents?: SettledEvent[]\n /** Pre-fetched block metadata (skips an extra eth_getBlockByNumber if provided) */\n _meta?: BlockMeta\n}\n\n/** A single snapshot of streamia data at a particular block. */\nexport interface StreamiaSnapshot {\n /** Block number (undefined if queried as latest) */\n blockNumber: bigint | undefined\n /** Net Panoptic premia (short - long), after subtracting settled amounts */\n panopticPremia: { token0: bigint; token1: bigint }\n /** Uniswap fee delta from the first block in the series */\n uniswapFees: { token0: bigint; token1: bigint }\n}\n\n/** Result from getStreamiaHistory. */\nexport interface StreamiaHistoryResult {\n /** Snapshots in the same order as input blockNumbers */\n snapshots: StreamiaSnapshot[]\n /** Block metadata for the latest block used */\n _meta: BlockMeta\n}\n\n// 128-bit mask for LeftRight decoding\nconst MASK_128 = (1n << 128n) - 1n\n\n// ── Main function ──────────────────────────────────────────────────────\n\n/**\n * Get historical streamia data for a position across multiple blocks.\n *\n * @param params - The parameters\n * @returns Snapshots of Panoptic premia and Uniswap fee deltas at each block\n */\nexport async function getStreamiaHistory(\n params: GetStreamiaHistoryParams,\n): Promise<StreamiaHistoryResult> {\n const {\n client,\n panopticPoolAddress,\n account,\n tokenId,\n blockNumbers,\n legs,\n poolConfig,\n includeUniswapFees = true,\n settledEvents,\n } = params\n\n // Validate legs\n for (const leg of legs) {\n if (leg.lowerTick >= leg.upperTick) {\n throw new InvalidHistoryRangeError(\n `Leg lowerTick (${leg.lowerTick}) must be < upperTick (${leg.upperTick})`,\n )\n }\n if (leg.liquidity <= 0n) {\n throw new InvalidHistoryRangeError(`Leg liquidity must be > 0, got ${leg.liquidity}`)\n }\n }\n\n if (blockNumbers.length === 0) {\n const _meta = params._meta ?? (await getBlockMeta({ client }))\n return { snapshots: [], _meta }\n }\n\n // ── 1. Panoptic premia: one readContract per block ─────────────────\n const premiaRequests = blockNumbers.map((bn) =>\n client.readContract({\n address: panopticPoolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, true, [tokenId]],\n blockNumber: bn,\n }),\n )\n\n // ── 2. Uniswap fees (delegated to uniswapFeeHistory internals) ────\n const uniswapDataPromise =\n includeUniswapFees && legs.length > 0\n ? fetchUniswapFeeData(client, blockNumbers, legs, poolConfig)\n : undefined\n\n // ── 3. Fire all in parallel ────────────────────────────────────────\n const [premiaResults, uniswapData, _meta] = await Promise.all([\n Promise.all(premiaRequests),\n uniswapDataPromise ?? Promise.resolve(undefined),\n params._meta ? Promise.resolve(params._meta) : getBlockMeta({ client }),\n ])\n\n // ── 4. Pre-sort settled events for O(n+m) accumulation ─────────────\n const sortedSettled = settledEvents\n ? [...settledEvents].sort((a, b) => (a.blockNumber < b.blockNumber ? -1 : 1))\n : []\n\n // ── 5. Build snapshots ─────────────────────────────────────────────\n let settledIdx = 0\n let accSettled0 = 0n\n let accSettled1 = 0n\n\n let initialUniswapFees0: bigint | null = null\n let initialUniswapFees1: bigint | null = null\n\n const snapshots: StreamiaSnapshot[] = premiaResults.map((result, i) => {\n const bn = blockNumbers[i]\n\n const shortPacked = result[0]\n const longPacked = result[1]\n\n const short0 = shortPacked & MASK_128\n const short1 = shortPacked >> 128n\n const long0 = longPacked & MASK_128\n const long1 = longPacked >> 128n\n\n // Advance settled accumulator\n const effectiveBn = bn ?? BigInt(Number.MAX_SAFE_INTEGER)\n while (\n settledIdx < sortedSettled.length &&\n sortedSettled[settledIdx].blockNumber <= effectiveBn\n ) {\n accSettled0 += sortedSettled[settledIdx].settled0\n accSettled1 += sortedSettled[settledIdx].settled1\n settledIdx++\n }\n\n const premia0 = short0 - long0 - accSettled0\n const premia1 = short1 - long1 - accSettled1\n\n let uniswapFees0 = 0n\n let uniswapFees1 = 0n\n\n if (uniswapData) {\n const blockData = uniswapData[i]\n const { total0, total1 } = computeUniswapFeesForBlock(blockData, legs)\n\n if (initialUniswapFees0 === null) {\n initialUniswapFees0 = total0\n initialUniswapFees1 = total1\n }\n uniswapFees0 = total0 - initialUniswapFees0\n uniswapFees1 = total1 - (initialUniswapFees1 as bigint)\n }\n\n return {\n blockNumber: bn,\n panopticPremia: { token0: premia0, token1: premia1 },\n uniswapFees: { token0: uniswapFees0, token1: uniswapFees1 },\n }\n })\n\n return { snapshots, _meta }\n}\n","/**\n * Direct Uniswap V3 pool read — no Panoptic deployment required.\n *\n * @module v2/reads/uniswapPool\n */\n\nimport type { Address, Hex, PublicClient } from 'viem'\nimport { encodeAbiParameters, keccak256, zeroAddress } from 'viem'\n\nimport { panopticQueryAbi } from '../abis/panopticQuery'\nimport { stateViewAbi } from '../abis/stateView'\nimport { uniswapV3PoolAbi } from '../abis/uniswapV3Pool'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { PanopticValidationError } from '../errors'\nimport type { BlockMeta } from '../types'\n\nconst erc20MetaAbi = [\n {\n type: 'function',\n name: 'symbol',\n inputs: [],\n outputs: [{ type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'name',\n inputs: [],\n outputs: [{ type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'decimals',\n inputs: [],\n outputs: [{ type: 'uint8' }],\n stateMutability: 'view',\n },\n] as const\n\nexport interface UniswapV3PoolToken {\n address: Address\n symbol: string\n name: string\n decimals: number\n}\n\nexport interface UniswapV3PoolInfo {\n poolAddress: Address\n token0: UniswapV3PoolToken\n token1: UniswapV3PoolToken\n /** Fee tier in hundredths of a bip (e.g. 500 = 0.05%) */\n fee: number\n tickSpacing: number\n currentTick: number\n sqrtPriceX96: bigint\n liquidity: bigint\n /**\n * Packed protocol fee from slot0: `feeProtocol1 << 4 | feeProtocol0`. Each\n * nibble `n` denotes a protocol fee of `1/n` of the swap fee (`0` = off).\n */\n feeProtocol: bigint\n _meta: BlockMeta\n}\n\nexport interface GetUniswapV3PoolInfoParams {\n client: PublicClient\n poolAddress: Address\n}\n\n/**\n * Fetch core data for a Uniswap V3 pool directly from chain.\n *\n * Does NOT require a Panoptic deployment — works for any V3 pool address.\n */\nexport async function getUniswapV3PoolInfo(\n params: GetUniswapV3PoolInfoParams,\n): Promise<UniswapV3PoolInfo> {\n const { client, poolAddress } = params\n\n // Pin every read to the same block so pool state + token metadata are\n // self-consistent. Pool reads run first because token0/token1 are needed to\n // address the ERC20 metadata calls; the second multicall is pinned to the\n // same block as the first.\n const _meta = await getBlockMeta({ client })\n\n const [slot0, fee, tickSpacing, token0Addr, token1Addr, liquidity] = await client.multicall({\n allowFailure: false,\n blockNumber: _meta.blockNumber,\n contracts: [\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'slot0' },\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'fee' },\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'tickSpacing' },\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'token0' },\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'token1' },\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'liquidity' },\n ],\n })\n\n const [t0Symbol, t0Name, t0Decimals, t1Symbol, t1Name, t1Decimals] = await client.multicall({\n allowFailure: false,\n blockNumber: _meta.blockNumber,\n contracts: [\n { address: token0Addr, abi: erc20MetaAbi, functionName: 'symbol' },\n { address: token0Addr, abi: erc20MetaAbi, functionName: 'name' },\n { address: token0Addr, abi: erc20MetaAbi, functionName: 'decimals' },\n { address: token1Addr, abi: erc20MetaAbi, functionName: 'symbol' },\n { address: token1Addr, abi: erc20MetaAbi, functionName: 'name' },\n { address: token1Addr, abi: erc20MetaAbi, functionName: 'decimals' },\n ],\n })\n\n return {\n poolAddress,\n token0: {\n address: token0Addr,\n symbol: t0Symbol,\n name: t0Name,\n decimals: Number(t0Decimals),\n },\n token1: {\n address: token1Addr,\n symbol: t1Symbol,\n name: t1Name,\n decimals: Number(t1Decimals),\n },\n fee: Number(fee),\n tickSpacing: Number(tickSpacing),\n currentTick: Number(slot0[1]),\n sqrtPriceX96: slot0[0],\n liquidity,\n feeProtocol: BigInt(slot0[5]),\n _meta,\n }\n}\n\nexport interface UniswapV3Liquidities {\n ticks: bigint[]\n liquidityNets: bigint[]\n _meta: BlockMeta\n}\n\nexport interface GetUniswapV3PoolLiquiditiesParams {\n client: PublicClient\n /** Uniswap V3 pool address */\n poolAddress: Address\n /** PanopticQuery address — must expose the public `getTickNetsV3` overload */\n queryAddress: Address\n /** Center tick of the range to scan */\n startTick: number\n /** Number of ticks on each side of startTick to scan */\n nTicks: bigint\n}\n\n/** Absolute Uniswap V3/V4 tick bounds. */\nconst TICK_MIN = -887272\nconst TICK_MAX = 887272\n\n/**\n * Clamp `nTicks` so the scan range\n * [scaled(startTick) − nTicks·tickSpacing, scaled(startTick) + nTicks·tickSpacing]\n * stays within [TICK_MIN, TICK_MAX]. Required because PanopticQuery's\n * getTickNetsV3/V4 revert with \"Tick out of bounds\" otherwise.\n */\nfunction clampNTicks(startTick: number, tickSpacing: number, nTicks: bigint): bigint {\n if (!Number.isInteger(tickSpacing) || tickSpacing <= 0) {\n throw new PanopticValidationError(\n `clampNTicks: tickSpacing must be a positive integer, got ${tickSpacing}`,\n )\n }\n const scaled = Math.trunc(startTick / tickSpacing) * tickSpacing\n const maxUp = Math.floor((TICK_MAX - scaled) / tickSpacing)\n const maxDown = Math.floor((scaled - TICK_MIN) / tickSpacing)\n const safe = BigInt(Math.max(0, Math.min(maxUp, maxDown)))\n return nTicks < safe ? nTicks : safe\n}\n\n/**\n * Fetch cumulative liquidity distribution for a Uniswap V3 pool via\n * `PanopticQuery.getTickNetsV3`. Does NOT require a Panoptic market to exist\n * for the pool — only a deployed PanopticQuery on the chain.\n */\nexport async function getUniswapV3PoolLiquidities(\n params: GetUniswapV3PoolLiquiditiesParams,\n): Promise<UniswapV3Liquidities> {\n const { client, poolAddress, queryAddress, startTick, nTicks } = params\n\n // We don't know tickSpacing here; PanopticQuery reads it from the pool.\n // For safety, clamp against the worst case (tickSpacing = 1).\n const safeN = clampNTicks(startTick, 1, nTicks)\n\n // Pin the read to a specific block so the returned ticks/liquidityNets\n // are consistent with the _meta we hand back.\n const _meta = await getBlockMeta({ client })\n const [ticks, liquidityNets] = await client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getTickNetsV3',\n args: [poolAddress, startTick, safeN],\n blockNumber: _meta.blockNumber,\n })\n\n return {\n ticks: [...ticks],\n liquidityNets: [...liquidityNets],\n _meta,\n }\n}\n\n// ============================================================================\n// V4\n// ============================================================================\n\nexport interface UniswapV4PoolKey {\n currency0: Address\n currency1: Address\n /** Fee in hundredths of a bip (e.g. 500 = 0.05%) */\n fee: number\n tickSpacing: number\n hooks: Address\n}\n\nconst POOL_KEY_ABI_PARAMS = [\n {\n type: 'tuple',\n components: [\n { name: 'currency0', type: 'address' },\n { name: 'currency1', type: 'address' },\n { name: 'fee', type: 'uint24' },\n { name: 'tickSpacing', type: 'int24' },\n { name: 'hooks', type: 'address' },\n ],\n },\n] as const\n\n/** Compute the v4 poolId from a PoolKey: `keccak256(abi.encode(poolKey))`. */\nexport function computeV4PoolId(poolKey: UniswapV4PoolKey): Hex {\n return keccak256(\n encodeAbiParameters(POOL_KEY_ABI_PARAMS, [\n {\n currency0: poolKey.currency0,\n currency1: poolKey.currency1,\n fee: poolKey.fee,\n tickSpacing: poolKey.tickSpacing,\n hooks: poolKey.hooks,\n },\n ]),\n )\n}\n\nexport interface ResolveUniswapV4PoolKeyParams {\n client: PublicClient\n /** Uniswap V4 PoolManager address */\n poolManager: Address\n /** The bytes32 poolId hash */\n poolId: Hex\n /** Lower bound block for the scan (defaults to 0n) */\n fromBlock?: bigint\n /**\n * Per-request block range. Many RPCs cap getLogs at 10k/50k blocks;\n * defaults to 9_500 to stay under common limits.\n */\n chunkSize?: bigint\n /**\n * Number of chunked getLogs requests fired in parallel per batch.\n * Higher = faster but more likely to trip RPC rate limits. Default 8.\n */\n concurrency?: number\n}\n\n/**\n * Resolve a V4 PoolKey from its poolId by scanning `Initialize` event logs\n * on the PoolManager, filtered on the indexed `id` topic.\n *\n * Walks backwards from the latest block in `chunkSize` increments to\n * accommodate RPCs that cap getLogs ranges. Chunks are fired in parallel\n * batches of `concurrency` to keep wall-clock time low; returns as soon as\n * any batch produces a match. Throws if no event is found or if the\n * recomputed poolId does not match the queried one.\n */\nexport async function resolveUniswapV4PoolKey(\n _params: ResolveUniswapV4PoolKeyParams,\n): Promise<UniswapV4PoolKey> {\n // Disabled to save on RPC costs — the Initialize-event scan over the full\n // PoolManager history can issue dozens of eth_getLogs requests per\n // first-load resolution. Re-enable by uncommenting the body below.\n throw new PanopticValidationError(\n 'resolveUniswapV4PoolKey is disabled. ' +\n 'Resolve the V4 PoolKey via your indexer (e.g. Ponder) and pass it to getUniswapV4PoolInfo directly.',\n )\n\n /*\n const {\n client,\n poolManager,\n poolId,\n fromBlock = 0n,\n chunkSize = 9_500n,\n concurrency = 8,\n } = _params\n\n const latest = await client.getBlockNumber()\n\n // Pre-compute all chunk ranges, walking backwards.\n const ranges: Array<{ from: bigint; to: bigint }> = []\n let to = latest\n while (to >= fromBlock) {\n const from = to - chunkSize + 1n > fromBlock ? to - chunkSize + 1n : fromBlock\n ranges.push({ from, to })\n if (from === fromBlock) break\n to = from - 1n\n }\n\n let foundLogs: Awaited<ReturnType<PublicClient['getLogs']>> = []\n\n for (let i = 0; i < ranges.length; i += concurrency) {\n const batch = ranges.slice(i, i + concurrency)\n const results = await Promise.all(\n batch.map((r) =>\n client.getLogs({\n address: poolManager,\n event: uniswapV4PoolManagerAbi[0],\n args: { id: poolId },\n fromBlock: r.from,\n toBlock: r.to,\n }),\n ),\n )\n const hit = results.find((logs) => logs.length > 0)\n if (hit) {\n foundLogs = hit\n break\n }\n }\n\n if (foundLogs.length === 0) {\n throw new Error(`No Initialize event found for poolId ${poolId} on PoolManager ${poolManager}`)\n }\n\n const args = (foundLogs[0] as { args: Record<string, unknown> }).args as {\n id: Hex\n currency0: Address\n currency1: Address\n fee: number\n tickSpacing: number\n hooks: Address\n }\n\n const key: UniswapV4PoolKey = {\n currency0: args.currency0,\n currency1: args.currency1,\n fee: Number(args.fee),\n tickSpacing: Number(args.tickSpacing),\n hooks: args.hooks,\n }\n\n const recomputed = computeV4PoolId(key)\n if (recomputed.toLowerCase() !== poolId.toLowerCase()) {\n throw new Error(\n `Recomputed poolId ${recomputed} does not match queried ${poolId} — PoolKey encoding mismatch`,\n )\n }\n\n return key\n */\n}\n\n/**\n * Slot0 + liquidity for a V4 pool by poolId — does NOT require the PoolKey.\n * Used to render basic info (currentTick, sqrtPriceX96, liquidity) when the\n * PoolKey is unknown.\n */\nexport interface UniswapV4PoolBasicState {\n poolId: Hex\n sqrtPriceX96: bigint\n currentTick: number\n /** Dynamic LP fee from slot0 (NOT necessarily the static PoolKey.fee). */\n lpFee: number\n liquidity: bigint\n _meta: BlockMeta\n}\n\nexport interface GetUniswapV4PoolBasicStateParams {\n client: PublicClient\n stateViewAddress: Address\n poolId: Hex\n}\n\nexport async function getUniswapV4PoolBasicState(\n params: GetUniswapV4PoolBasicStateParams,\n): Promise<UniswapV4PoolBasicState> {\n const { client, stateViewAddress, poolId } = params\n // Pin slot0 + liquidity to the same block as the returned _meta.\n const _meta = await getBlockMeta({ client })\n const [slot0, liquidity] = await client.multicall({\n allowFailure: false,\n blockNumber: _meta.blockNumber,\n contracts: [\n { address: stateViewAddress, abi: stateViewAbi, functionName: 'getSlot0', args: [poolId] },\n {\n address: stateViewAddress,\n abi: stateViewAbi,\n functionName: 'getLiquidity',\n args: [poolId],\n },\n ],\n })\n return {\n poolId,\n sqrtPriceX96: slot0[0],\n currentTick: Number(slot0[1]),\n lpFee: Number(slot0[3]),\n liquidity,\n _meta,\n }\n}\n\nexport interface UniswapV4PoolInfo {\n poolId: Hex\n poolKey: UniswapV4PoolKey\n token0: UniswapV3PoolToken\n token1: UniswapV3PoolToken\n fee: number\n tickSpacing: number\n hooks: Address\n currentTick: number\n sqrtPriceX96: bigint\n liquidity: bigint\n _meta: BlockMeta\n}\n\nexport interface GetUniswapV4PoolInfoParams {\n client: PublicClient\n stateViewAddress: Address\n poolKey: UniswapV4PoolKey\n}\n\n/** Synthetic token metadata for native ETH (currency address `0x0`). */\nconst NATIVE_ETH_META = { symbol: 'ETH', name: 'Ether', decimals: 18 } as const\n\nasync function readErc20Meta(\n client: PublicClient,\n address: Address,\n blockNumber?: bigint,\n): Promise<{ symbol: string; name: string; decimals: number }> {\n const [symbol, name, decimals] = await client.multicall({\n allowFailure: false,\n blockNumber,\n contracts: [\n { address, abi: erc20MetaAbi, functionName: 'symbol' },\n { address, abi: erc20MetaAbi, functionName: 'name' },\n { address, abi: erc20MetaAbi, functionName: 'decimals' },\n ],\n })\n return { symbol, name, decimals: Number(decimals) }\n}\n\n/**\n * Fetch core data for a Uniswap V4 pool directly from chain.\n *\n * Does NOT require a Panoptic deployment — only StateView + (for non-native\n * currencies) ERC20s. Caller must supply a resolved PoolKey (see\n * `resolveUniswapV4PoolKey`).\n */\nexport async function getUniswapV4PoolInfo(\n params: GetUniswapV4PoolInfoParams,\n): Promise<UniswapV4PoolInfo> {\n const { client, stateViewAddress, poolKey } = params\n const poolId = computeV4PoolId(poolKey)\n\n // Skip ERC20 metadata reads for native ETH (currency `0x0`) so the\n // multicall doesn't revert, and substitute synthetic metadata.\n const c0IsNative = poolKey.currency0 === zeroAddress\n const c1IsNative = poolKey.currency1 === zeroAddress\n\n const _meta = await getBlockMeta({ client })\n\n // State reads (slot0 + liquidity) batched in one multicall.\n const [slot0, liquidity] = await client.multicall({\n allowFailure: false,\n blockNumber: _meta.blockNumber,\n contracts: [\n { address: stateViewAddress, abi: stateViewAbi, functionName: 'getSlot0', args: [poolId] },\n {\n address: stateViewAddress,\n abi: stateViewAbi,\n functionName: 'getLiquidity',\n args: [poolId],\n },\n ],\n })\n\n // ERC20 metadata (skipped for native ETH) batched in a second multicall,\n // pinned to the same block as the state reads above for consistency.\n const token0Meta = c0IsNative\n ? { ...NATIVE_ETH_META }\n : await readErc20Meta(client, poolKey.currency0, _meta.blockNumber)\n const token1Meta = c1IsNative\n ? { ...NATIVE_ETH_META }\n : await readErc20Meta(client, poolKey.currency1, _meta.blockNumber)\n\n return {\n poolId,\n poolKey,\n token0: { address: poolKey.currency0, ...token0Meta },\n token1: { address: poolKey.currency1, ...token1Meta },\n fee: poolKey.fee,\n tickSpacing: poolKey.tickSpacing,\n hooks: poolKey.hooks,\n currentTick: Number(slot0[1]),\n sqrtPriceX96: slot0[0],\n liquidity,\n _meta,\n }\n}\n\nexport interface GetUniswapV4PoolLiquiditiesParams {\n client: PublicClient\n queryAddress: Address\n poolManager: Address\n poolId: Hex\n tickSpacing: number\n startTick: number\n nTicks: bigint\n}\n\n/**\n * Fetch cumulative liquidity distribution for a Uniswap V4 pool via\n * `PanopticQuery.getTickNetsV4`. Does NOT require a Panoptic market for the pool.\n */\nexport async function getUniswapV4PoolLiquidities(\n params: GetUniswapV4PoolLiquiditiesParams,\n): Promise<UniswapV3Liquidities> {\n const { client, queryAddress, poolManager, poolId, tickSpacing, startTick, nTicks } = params\n\n const safeN = clampNTicks(startTick, tickSpacing, nTicks)\n\n // Pin to a specific block so the returned ticks/liquidityNets match _meta.\n const _meta = await getBlockMeta({ client })\n const [ticks, liquidityNets] = await client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getTickNetsV4',\n args: [poolManager, poolId, tickSpacing, startTick, safeN],\n blockNumber: _meta.blockNumber,\n })\n\n return {\n ticks: [...ticks],\n liquidityNets: [...liquidityNets],\n _meta,\n }\n}\n","/**\n * Historical price reads for the Panoptic v2 SDK.\n *\n * Fetches slot0 (tick + sqrtPriceX96) across a series of historical blocks\n * for price-over-time charting. All block reads are parallelized via\n * Promise.all (viem auto-batches into multicall).\n *\n * @module v2/reads/priceHistory\n */\n\nimport type { PublicClient } from 'viem'\n\nimport { stateViewAbi } from '../abis/stateView'\nimport { uniswapV3PoolAbi } from '../abis/uniswapV3Pool'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport type { BlockMeta } from '../types'\nimport type { PoolVersionConfig } from '../types/poolConfig'\n\n// ── Types ──────────────────────────────────────────────────────────────\n\n/** A single price snapshot at a particular block. */\nexport interface PriceSnapshot {\n /** Block number (undefined if queried as latest) */\n blockNumber: bigint | undefined\n /** Current tick of the pool at this block */\n tick: number\n /** sqrtPriceX96 at this block */\n sqrtPriceX96: bigint\n}\n\n/** Result from getPriceHistory. */\nexport interface PriceHistoryResult {\n /** Snapshots in the same order as input blockNumbers */\n snapshots: PriceSnapshot[]\n /** Block metadata for the latest block used */\n _meta: BlockMeta\n}\n\n/** Parameters for getPriceHistory. */\nexport interface GetPriceHistoryParams {\n /** viem PublicClient */\n client: PublicClient\n /** Block numbers to query; undefined entries resolve to latest */\n blockNumbers: (bigint | undefined)[]\n /** Pool version config (carries pool address / StateView + poolId) */\n poolConfig: PoolVersionConfig\n /** Pre-fetched block metadata (skips an extra eth_getBlockByNumber if provided) */\n _meta?: BlockMeta\n}\n\n// ── Main function ──────────────────────────────────────────────────────\n\n/**\n * Get historical price data (tick + sqrtPriceX96) for a pool across multiple blocks.\n *\n * @param params - The parameters\n * @returns Price snapshots at each block\n *\n * @example\n * ```typescript\n * const { snapshots } = await getPriceHistory({\n * client,\n * blockNumbers: [18000000n, 18000100n, 18000200n],\n * poolConfig: { version: 'v3', poolAddress: '0x...' },\n * })\n *\n * for (const snap of snapshots) {\n * console.log(`Block ${snap.blockNumber}: tick=${snap.tick}`)\n * }\n * ```\n */\nexport async function getPriceHistory(params: GetPriceHistoryParams): Promise<PriceHistoryResult> {\n const { client, blockNumbers, poolConfig } = params\n\n if (blockNumbers.length === 0) {\n const _meta = params._meta ?? (await getBlockMeta({ client }))\n return { snapshots: [], _meta }\n }\n\n // Fire one slot0 read per block. Calls at different historical blocks cannot\n // be coalesced into one multicall, so callers should not poll this path.\n const slot0Requests = blockNumbers.map((bn) => fetchSlot0(client, bn, poolConfig))\n\n const [slot0Results, _meta] = await Promise.all([\n Promise.all(slot0Requests),\n params._meta ? Promise.resolve(params._meta) : getBlockMeta({ client }),\n ])\n\n const snapshots: PriceSnapshot[] = slot0Results.map((result, i) => ({\n blockNumber: blockNumbers[i],\n tick: result.tick,\n sqrtPriceX96: result.sqrtPriceX96,\n }))\n\n return { snapshots, _meta }\n}\n\n// ── Internals ──────────────────────────────────────────────────────────\n\ninterface Slot0Data {\n tick: number\n sqrtPriceX96: bigint\n}\n\nasync function fetchSlot0(\n client: PublicClient,\n blockNumber: bigint | undefined,\n poolConfig: PoolVersionConfig,\n): Promise<Slot0Data> {\n if (poolConfig.version === 'v3') {\n const result = await client.readContract({\n address: poolConfig.poolAddress,\n abi: uniswapV3PoolAbi,\n functionName: 'slot0',\n blockNumber,\n })\n return {\n sqrtPriceX96: result[0],\n tick: result[1],\n }\n } else {\n const result = await client.readContract({\n address: poolConfig.stateViewAddress,\n abi: stateViewAbi,\n functionName: 'getSlot0',\n args: [poolConfig.poolId],\n blockNumber,\n })\n return {\n sqrtPriceX96: result[0],\n tick: result[1],\n }\n }\n}\n","/**\n * Position enrichment data for UI display.\n *\n * Batches all contract reads needed to enrich subgraph position data with\n * on-chain premia, portfolio values, and collateral requirements.\n *\n * @module v2/reads/enrichment\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi, panopticQueryAbi } from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { PanopticError } from '../errors'\nimport type { BlockMeta } from '../types'\nimport { decodeLeftRightUnsigned } from '../writes/utils'\n\n/**\n * Error thrown when an enrichment contract call fails for a specific position.\n */\nexport class EnrichmentCallError extends PanopticError {\n /** The tokenId of the position that failed */\n readonly tokenId: bigint\n /** The name of the failing call */\n readonly callName: string\n\n constructor(tokenId: bigint, callName: string, cause?: unknown) {\n super(\n `Enrichment call \"${callName}\" failed for tokenId ${tokenId}`,\n cause instanceof Error ? cause : undefined,\n )\n this.tokenId = tokenId\n this.callName = callName\n }\n}\n\n/**\n * Input describing a position for enrichment.\n */\nexport interface PositionInput {\n /** The tokenId (256-bit identifier) */\n tokenId: bigint\n /** Whether the position is currently open */\n isOpen: boolean\n /** Tick at time of mint */\n tickAtMint: number\n /** Account address that owns the position */\n account: Address\n /** Pool address the position belongs to */\n poolAddress: Address\n /** Tick at burn (closed positions only) */\n tickAtBurn?: number\n /** Block number of the burn tx (closed positions only) */\n burnBlockNumber?: bigint\n /** Premium in token0 from subgraph (closed positions only) */\n burnPremium0?: bigint\n /** Premium in token1 from subgraph (closed positions only) */\n burnPremium1?: bigint\n}\n\n/**\n * Enrichment result for a single position.\n *\n * Values are in raw token units (token0 and token1), not asset/quote.\n * The UI maps these to asset/quote based on isAssetToken0.\n */\nexport interface PositionEnrichmentResult {\n /** Net premia owed: shortPremium - longPremium for token0 (open); burnPremium0 for closed */\n premiaOwed0: bigint\n /** Net premia owed: shortPremium - longPremium for token1 (open); burnPremium1 for closed */\n premiaOwed1: bigint\n /** Portfolio value in token0 at current tick (open) or burn tick (closed) */\n portfolioValue0: bigint\n /** Portfolio value in token1 at current tick (open) or burn tick (closed) */\n portfolioValue1: bigint\n /** Portfolio value in token0 at mint tick */\n portfolioValueAtMint0: bigint\n /** Portfolio value in token1 at mint tick */\n portfolioValueAtMint1: bigint\n /**\n * Per-token collateral requirement from `getFullPositionsData.collateralRequirements[]`.\n * These are NOT cross-margined — each is in its own token denomination.\n * For closed positions these are 0n (collateral is moot).\n */\n collateralReqToken0: bigint\n collateralReqToken1: bigint\n}\n\n/**\n * Parameters for getPositionEnrichmentData.\n */\nexport interface GetPositionEnrichmentDataParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticQuery helper contract address */\n queryAddress: Address\n /** Positions to enrich */\n positions: PositionInput[]\n /** Current pool tick (used for open position portfolio values) */\n currentTick: number\n /** Optional block number for open position reads */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata */\n _meta?: BlockMeta\n}\n\n/**\n * Result from getPositionEnrichmentData.\n */\nexport interface GetPositionEnrichmentDataResult {\n /** Enrichment data keyed by tokenId string */\n byTokenId: Map<string, PositionEnrichmentResult>\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Fetch enrichment data (premia, portfolio values, collateral requirements) for a set of positions.\n *\n * Batches all needed contract reads into efficient multicalls:\n * - **Open positions**: 3 calls per position in a single multicall at current block:\n * 1. `getFullPositionsData` → premia + collateral requirements\n * 2. `getPortfolioValue` at currentTick → current portfolio value\n * 3. `getPortfolioValue` at mintTick → portfolio value at mint\n * - **Closed positions**: 2 calls per position at `burnBlockNumber - 1`:\n * 1. `getPortfolioValue` at burnTick → portfolio value at close\n * 2. `getPortfolioValue` at mintTick → portfolio value at mint\n * (premia come from subgraph `burnPremium0/1`)\n *\n * ## Same-Block Guarantee\n * Open position data is fetched at a single block number.\n * Closed position data is fetched at `burnBlockNumber - 1` (per position).\n *\n * @param params - The parameters\n * @returns Map of tokenId → enrichment data, with block metadata\n */\nexport async function getPositionEnrichmentData(\n params: GetPositionEnrichmentDataParams,\n): Promise<GetPositionEnrichmentDataResult> {\n const { client, queryAddress, positions, currentTick, blockNumber } = params\n\n // Fetch a single block metadata for the entire enrichment result\n const _meta = params._meta ?? (await getBlockMeta({ client, blockNumber }))\n\n if (positions.length === 0) {\n return { byTokenId: new Map(), _meta }\n }\n\n const openPositions = positions.filter((p) => p.isOpen)\n const closedPositions = positions.filter((p) => !p.isOpen)\n\n const byTokenId = new Map<string, PositionEnrichmentResult>()\n\n // Process open and closed positions in parallel\n await Promise.all([\n processOpenPositions(client, queryAddress, openPositions, currentTick, blockNumber, _meta),\n processClosedPositions(client, queryAddress, closedPositions),\n ]).then(([openResults, closedResults]) => {\n // Merge results into byTokenId map\n for (const [key, value] of openResults.entries) {\n byTokenId.set(key, value)\n }\n for (const [key, value] of closedResults) {\n byTokenId.set(key, value)\n }\n })\n\n return { byTokenId, _meta }\n}\n\n/** Number of multicall contracts per open position */\nconst OPEN_CALLS_PER_POSITION = 3\n/** Number of multicall contracts per closed position */\nconst CLOSED_CALLS_PER_POSITION = 2\n\n/**\n * Process open positions: single multicall with 5 calls per position.\n */\nasync function processOpenPositions(\n client: PublicClient,\n queryAddress: Address,\n positions: PositionInput[],\n currentTick: number,\n blockNumber: bigint | undefined,\n _meta: BlockMeta,\n): Promise<{ entries: [string, PositionEnrichmentResult][] }> {\n if (positions.length === 0) {\n return { entries: [] }\n }\n\n const targetBlockNumber = blockNumber ?? _meta.blockNumber\n\n // Build multicall contracts: 3 calls per position\n const contracts = positions.flatMap((p) => [\n // 1. getFullPositionsData → premia + collateral requirements\n {\n address: p.poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData' as const,\n args: [p.account, true, [p.tokenId]] as const,\n },\n // 2. getPortfolioValue at currentTick\n {\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getPortfolioValue' as const,\n args: [p.poolAddress, p.account, currentTick, [p.tokenId]] as const,\n },\n // 3. getPortfolioValue at mintTick\n {\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getPortfolioValue' as const,\n args: [p.poolAddress, p.account, p.tickAtMint, [p.tokenId]] as const,\n },\n ])\n\n const multicallResults = await client.multicall({\n contracts,\n blockNumber: targetBlockNumber,\n allowFailure: true,\n })\n\n const entries: [string, PositionEnrichmentResult][] = []\n\n for (let i = 0; i < positions.length; i++) {\n const position = positions[i]\n const baseIdx = i * OPEN_CALLS_PER_POSITION\n\n const premiaResult = multicallResults[baseIdx]\n const portfolioResult = multicallResults[baseIdx + 1]\n const portfolioAtMintResult = multicallResults[baseIdx + 2]\n\n if (premiaResult.status !== 'success') {\n throw new EnrichmentCallError(position.tokenId, 'getFullPositionsData', premiaResult.error)\n }\n if (portfolioResult.status !== 'success') {\n throw new EnrichmentCallError(\n position.tokenId,\n 'getPortfolioValue (currentTick)',\n portfolioResult.error,\n )\n }\n if (portfolioAtMintResult.status !== 'success') {\n throw new EnrichmentCallError(\n position.tokenId,\n 'getPortfolioValue (mintTick)',\n portfolioAtMintResult.error,\n )\n }\n\n // Decode getFullPositionsData: [shortPremium, longPremium, balances[], collateralReqs[], netPremia[]]\n const [shortPremiumPacked, longPremiumPacked, , collateralReqsPacked] = premiaResult.result as [\n bigint,\n bigint,\n bigint[],\n bigint[],\n bigint[],\n ]\n const shortPremium = decodeLeftRightUnsigned(shortPremiumPacked)\n const longPremium = decodeLeftRightUnsigned(longPremiumPacked)\n\n const premiaOwed0 = shortPremium.right - longPremium.right // token0\n const premiaOwed1 = shortPremium.left - longPremium.left // token1\n\n // Decode per-token collateral requirements from collateralReqs[0] (LeftRightUnsigned)\n const collateralReq = decodeLeftRightUnsigned(collateralReqsPacked[0] ?? 0n)\n\n // Decode portfolio values\n const [portfolioValue0, portfolioValue1] = portfolioResult.result as [bigint, bigint]\n const [portfolioValueAtMint0, portfolioValueAtMint1] = portfolioAtMintResult.result as [\n bigint,\n bigint,\n ]\n\n entries.push([\n position.tokenId.toString(),\n {\n premiaOwed0,\n premiaOwed1,\n portfolioValue0,\n portfolioValue1,\n portfolioValueAtMint0,\n portfolioValueAtMint1,\n collateralReqToken0: collateralReq.right,\n collateralReqToken1: collateralReq.left,\n },\n ])\n }\n\n return { entries }\n}\n\n/**\n * Process closed positions: per-position calls at burnBlockNumber - 1.\n *\n * Returns entries array (not a map) to merge into the final result.\n */\nasync function processClosedPositions(\n client: PublicClient,\n queryAddress: Address,\n positions: PositionInput[],\n): Promise<[string, PositionEnrichmentResult][]> {\n if (positions.length === 0) return []\n\n // Group positions by burnBlockNumber for batch efficiency\n const byBlock = new Map<bigint, PositionInput[]>()\n for (const p of positions) {\n if (p.burnBlockNumber == null) continue\n const readBlock = p.burnBlockNumber - 1n\n const group = byBlock.get(readBlock) ?? []\n group.push(p)\n byBlock.set(readBlock, group)\n }\n\n const entries: [string, PositionEnrichmentResult][] = []\n\n // Process each block group\n await Promise.all(\n Array.from(byBlock.entries()).map(async ([readBlock, blockPositions]) => {\n // Build multicall contracts: 2 calls per position\n const contracts = blockPositions.flatMap((p) => [\n // 1. getPortfolioValue at burnTick\n {\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getPortfolioValue' as const,\n args: [p.poolAddress, p.account, p.tickAtBurn ?? 0, [p.tokenId]] as const,\n },\n // 2. getPortfolioValue at mintTick\n {\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getPortfolioValue' as const,\n args: [p.poolAddress, p.account, p.tickAtMint, [p.tokenId]] as const,\n },\n ])\n\n const multicallResults = await client.multicall({\n contracts,\n blockNumber: readBlock,\n allowFailure: true,\n })\n\n for (let i = 0; i < blockPositions.length; i++) {\n const position = blockPositions[i]\n const baseIdx = i * CLOSED_CALLS_PER_POSITION\n\n const portfolioAtBurnResult = multicallResults[baseIdx]\n const portfolioAtMintResult = multicallResults[baseIdx + 1]\n\n // Closed position reads can fail legitimately (e.g. position minted and burned\n // in the same block — at burnBlock-1 it doesn't exist yet). Fall back to zeros.\n const [portfolioValue0, portfolioValue1] =\n portfolioAtBurnResult.status === 'success'\n ? (portfolioAtBurnResult.result as [bigint, bigint])\n : [0n, 0n]\n const [portfolioValueAtMint0, portfolioValueAtMint1] =\n portfolioAtMintResult.status === 'success'\n ? (portfolioAtMintResult.result as [bigint, bigint])\n : [0n, 0n]\n\n entries.push([\n position.tokenId.toString(),\n {\n premiaOwed0: position.burnPremium0 ?? 0n,\n premiaOwed1: position.burnPremium1 ?? 0n,\n portfolioValue0,\n portfolioValue1,\n portfolioValueAtMint0,\n portfolioValueAtMint1,\n collateralReqToken0: 0n,\n collateralReqToken1: 0n,\n },\n ])\n }\n }),\n )\n\n return entries\n}\n","/**\n * Get synchronization status for an account.\n * @module v2/sync/getSyncStatus\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport type { StorageAdapter } from '../storage'\nimport { loadCheckpoint } from './reorgHandling'\n\n/**\n * Parameters for getSyncStatus.\n */\nexport interface GetSyncStatusParams {\n /** viem public client */\n client: PublicClient\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account to check */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n}\n\n/**\n * Sync status result.\n */\nexport interface SyncStatusResult {\n /** Last synced block number (0n if never synced) */\n lastSyncedBlock: bigint\n /** Whether the account is fully synced to current block */\n isSynced: boolean\n /** Number of blocks behind (0n if synced) */\n blocksBehind: bigint\n /** Number of positions tracked */\n positionCount: bigint\n /** Whether a checkpoint exists */\n hasCheckpoint: boolean\n}\n\n/**\n * Get the synchronization status for an account.\n *\n * This function checks the stored checkpoint and compares against\n * the current chain head to determine sync status.\n *\n * @param params - Status parameters\n * @returns Sync status information\n */\nexport async function getSyncStatus(params: GetSyncStatusParams): Promise<SyncStatusResult> {\n const { client, chainId, poolAddress, account, storage } = params\n\n // Get current block\n const currentBlock = await client.getBlockNumber()\n\n // Load checkpoint\n const checkpoint = await loadCheckpoint(storage, chainId, poolAddress, account)\n\n if (!checkpoint) {\n return {\n lastSyncedBlock: 0n,\n isSynced: false,\n blocksBehind: currentBlock,\n positionCount: 0n,\n hasCheckpoint: false,\n }\n }\n\n const blocksBehind = currentBlock - checkpoint.lastBlock\n const isSynced = blocksBehind <= 0n\n\n return {\n lastSyncedBlock: checkpoint.lastBlock,\n isSynced,\n blocksBehind: blocksBehind > 0n ? blocksBehind : 0n,\n positionCount: BigInt(checkpoint.positionIds.length),\n hasCheckpoint: true,\n }\n}\n","/**\n * Trade history tracking for closed positions.\n * @module v2/sync/tradeHistory\n */\n\nimport type { Address } from 'viem'\n\nimport type { StorageAdapter } from '../storage'\nimport { getClosedPositionsKey, jsonSerializer } from '../storage'\nimport type { ClosedPosition, RealizedPnL } from '../types'\n\n/**\n * Parameters for saving a closed position.\n */\nexport interface SaveClosedPositionParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account that owned the position */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** The closed position data */\n closedPosition: ClosedPosition\n}\n\n/**\n * Save a closed position to trade history.\n *\n * @param params - Save parameters\n */\nexport async function saveClosedPosition(params: SaveClosedPositionParams): Promise<void> {\n const { chainId, poolAddress, account, storage, closedPosition } = params\n\n const key = getClosedPositionsKey(chainId, poolAddress, account)\n const existingData = await storage.get(key)\n\n let history: ClosedPosition[]\n if (existingData) {\n try {\n history = jsonSerializer.parse(existingData) as ClosedPosition[]\n } catch {\n history = []\n }\n } else {\n history = []\n }\n\n // Add new closed position\n history.push(closedPosition)\n\n // Sort by close block (most recent first)\n history.sort((a, b) => Number(b.closeBlock - a.closeBlock))\n\n await storage.set(key, jsonSerializer.stringify(history))\n}\n\n/**\n * Parameters for getting trade history.\n */\nexport interface GetTradeHistoryParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account to get history for */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Maximum number of positions to return (default: 100) */\n limit?: bigint\n /** Offset for pagination */\n offset?: bigint\n /** Filter by closure reason */\n closureReason?: 'closed' | 'liquidated' | 'force_exercised'\n /** Filter by block range (from) */\n fromBlock?: bigint\n /** Filter by block range (to) */\n toBlock?: bigint\n}\n\n/**\n * Get trade history (closed positions) for an account.\n *\n * This function reads from local storage, no RPC calls.\n * Positions are returned in reverse chronological order (most recent first).\n *\n * @param params - Query parameters\n * @returns Array of closed positions\n */\nexport async function getTradeHistory(params: GetTradeHistoryParams): Promise<ClosedPosition[]> {\n const {\n chainId,\n poolAddress,\n account,\n storage,\n limit = 100n,\n offset = 0n,\n closureReason,\n fromBlock,\n toBlock,\n } = params\n\n const key = getClosedPositionsKey(chainId, poolAddress, account)\n const data = await storage.get(key)\n\n if (!data) {\n return []\n }\n\n let history: ClosedPosition[]\n try {\n history = jsonSerializer.parse(data) as ClosedPosition[]\n } catch {\n return []\n }\n\n // Apply filters\n if (closureReason) {\n history = history.filter((p) => p.closureReason === closureReason)\n }\n\n if (fromBlock !== undefined) {\n history = history.filter((p) => p.closeBlock >= fromBlock)\n }\n\n if (toBlock !== undefined) {\n history = history.filter((p) => p.closeBlock <= toBlock)\n }\n\n // Apply pagination\n const start = Number(offset)\n const end = start + Number(limit)\n return history.slice(start, end)\n}\n\n/**\n * Get closed positions (alias for getTradeHistory with specific closure reason).\n *\n * @param params - Query parameters\n * @returns Array of closed positions\n */\nexport async function getClosedPositions(params: GetTradeHistoryParams): Promise<ClosedPosition[]> {\n return getTradeHistory(params)\n}\n\n/**\n * Parameters for getting realized PnL.\n */\nexport interface GetRealizedPnLParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account to get PnL for */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Filter by block range (from) */\n fromBlock?: bigint\n /** Filter by block range (to) */\n toBlock?: bigint\n}\n\n/**\n * Get realized PnL summary for an account.\n *\n * Calculates totals from all closed positions in storage.\n *\n * @param params - Query parameters\n * @returns Realized PnL summary\n */\nexport async function getRealizedPnL(params: GetRealizedPnLParams): Promise<RealizedPnL> {\n const { chainId, poolAddress, account, storage, fromBlock, toBlock } = params\n\n const history = await getTradeHistory({\n chainId,\n poolAddress,\n account,\n storage,\n limit: BigInt(Number.MAX_SAFE_INTEGER), // Get all\n fromBlock,\n toBlock,\n })\n\n let total0 = 0n\n let total1 = 0n\n let winCount = 0n\n let lossCount = 0n\n\n for (const position of history) {\n total0 += position.realizedPnL0\n total1 += position.realizedPnL1\n\n // Consider it a win if either token had positive PnL\n // (in practice, one will usually dominate)\n const isWin = position.realizedPnL0 > 0n || position.realizedPnL1 > 0n\n const isLoss = position.realizedPnL0 < 0n || position.realizedPnL1 < 0n\n\n if (isWin && !isLoss) {\n winCount++\n } else if (isLoss && !isWin) {\n lossCount++\n }\n // Mixed results (win on one, loss on other) don't count as either\n }\n\n return {\n total0,\n total1,\n positionCount: BigInt(history.length),\n winCount,\n lossCount,\n }\n}\n\n/**\n * Clear all trade history for an account.\n *\n * @param params - Query parameters\n */\nexport async function clearTradeHistory(\n params: Omit<\n GetTradeHistoryParams,\n 'limit' | 'offset' | 'closureReason' | 'fromBlock' | 'toBlock'\n >,\n): Promise<void> {\n const { chainId, poolAddress, account, storage } = params\n\n const key = getClosedPositionsKey(chainId, poolAddress, account)\n await storage.delete(key)\n}\n","/**\n * Chunk spread tracking for volatility surface data.\n * @module v2/sync/chunkTracking\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticQueryAbi } from '../abis/panopticQuery'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { ChunkLimitError } from '../errors'\nimport type { StorageAdapter } from '../storage'\nimport { getTrackedChunksKey, jsonSerializer } from '../storage'\nimport { DEFAULT_VEGOID } from '../tokenId/constants'\nimport type { BlockMeta } from '../types'\nimport { MAX_TRACKED_CHUNKS, WAD } from '../utils/constants'\n\n/**\n * Key for identifying a liquidity chunk.\n * A chunk is a unique combination of (tokenType, tickLower, tickUpper).\n */\nexport interface LiquidityChunkKey {\n /** Token type: 0n = token0 (put), 1n = token1 (call) */\n tokenType: 0n | 1n\n /** Lower tick bound */\n tickLower: bigint\n /** Upper tick bound */\n tickUpper: bigint\n}\n\n/**\n * Full chunk data with spread calculation.\n */\nexport interface LiquidityChunkSpread extends LiquidityChunkKey {\n /** Liquidity currently deployed in Uniswap */\n netLiquidity: bigint\n /** Liquidity borrowed by option buyers */\n removedLiquidity: bigint\n /** Computed spread: (1 + (1/VEGOID) * removed/net) * 1e18 */\n spreadWad: bigint\n}\n\n/**\n * Parameters for adding tracked chunks.\n */\nexport interface AddTrackedChunksParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Chunks to add */\n chunks: LiquidityChunkKey[]\n}\n\n/**\n * Serialize a chunk key to a string for storage/comparison.\n */\nfunction serializeChunkKey(chunk: LiquidityChunkKey): string {\n return `${chunk.tokenType}:${chunk.tickLower}:${chunk.tickUpper}`\n}\n\n/**\n * Deserialize a chunk key from a string.\n */\nfunction deserializeChunkKey(key: string): LiquidityChunkKey {\n const [tokenType, tickLower, tickUpper] = key.split(':')\n return {\n tokenType: BigInt(tokenType) as 0n | 1n,\n tickLower: BigInt(tickLower),\n tickUpper: BigInt(tickUpper),\n }\n}\n\n/**\n * Add chunks to tracking.\n *\n * @param params - Parameters\n * @throws ChunkLimitError if adding would exceed 1000 chunks\n */\nexport async function addTrackedChunks(params: AddTrackedChunksParams): Promise<void> {\n const { chainId, poolAddress, storage, chunks } = params\n\n const key = getTrackedChunksKey(chainId, poolAddress)\n const existingData = await storage.get(key)\n\n let trackedKeys: Set<string>\n if (existingData) {\n try {\n const keys = jsonSerializer.parse(existingData) as string[]\n trackedKeys = new Set(keys)\n } catch {\n trackedKeys = new Set()\n }\n } else {\n trackedKeys = new Set()\n }\n\n // Add new chunks\n for (const chunk of chunks) {\n const serialized = serializeChunkKey(chunk)\n trackedKeys.add(serialized)\n }\n\n // Check limit\n if (trackedKeys.size > MAX_TRACKED_CHUNKS) {\n const attemptedAdd = BigInt(chunks.length)\n throw new ChunkLimitError(BigInt(trackedKeys.size - chunks.length), attemptedAdd)\n }\n\n await storage.set(key, jsonSerializer.stringify([...trackedKeys]))\n}\n\n/**\n * Parameters for removing tracked chunks.\n */\nexport interface RemoveTrackedChunksParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Chunks to remove */\n chunks: LiquidityChunkKey[]\n}\n\n/**\n * Remove chunks from tracking.\n *\n * @param params - Parameters\n */\nexport async function removeTrackedChunks(params: RemoveTrackedChunksParams): Promise<void> {\n const { chainId, poolAddress, storage, chunks } = params\n\n const key = getTrackedChunksKey(chainId, poolAddress)\n const existingData = await storage.get(key)\n\n if (!existingData) {\n return\n }\n\n let trackedKeys: Set<string>\n try {\n const keys = jsonSerializer.parse(existingData) as string[]\n trackedKeys = new Set(keys)\n } catch {\n return\n }\n\n // Remove chunks\n for (const chunk of chunks) {\n const serialized = serializeChunkKey(chunk)\n trackedKeys.delete(serialized)\n }\n\n if (trackedKeys.size === 0) {\n await storage.delete(key)\n } else {\n await storage.set(key, jsonSerializer.stringify([...trackedKeys]))\n }\n}\n\n/**\n * Parameters for getting tracked chunks.\n */\nexport interface GetTrackedChunksParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Storage adapter */\n storage: StorageAdapter\n}\n\n/**\n * Get all tracked chunk keys.\n *\n * @param params - Parameters\n * @returns Array of tracked chunk keys\n */\nexport async function getTrackedChunks(\n params: GetTrackedChunksParams,\n): Promise<LiquidityChunkKey[]> {\n const { chainId, poolAddress, storage } = params\n\n const key = getTrackedChunksKey(chainId, poolAddress)\n const data = await storage.get(key)\n\n if (!data) {\n return []\n }\n\n try {\n const keys = jsonSerializer.parse(data) as string[]\n return keys.map(deserializeChunkKey)\n } catch {\n return []\n }\n}\n\n/**\n * Parameters for getting chunk spreads (legacy manual tracking).\n * @deprecated Use scanChunks() for automatic chunk discovery\n */\nexport interface GetChunkSpreadsParams {\n /** viem public client */\n client: PublicClient\n /** Chain ID */\n chainId: bigint\n /** Pool address (PanopticPool) */\n poolAddress: Address\n /** SFPM address */\n sfpmAddress: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Optional filter by token type */\n tokenType?: 0n | 1n\n /** VEGOID constant (default: 4n) */\n vegoid?: bigint\n}\n\n/**\n * Get spread data for all tracked chunks (legacy).\n *\n * @deprecated Use scanChunks() for automatic chunk discovery with on-chain data.\n * This function only returns manually tracked chunks.\n *\n * @param params - Parameters\n * @returns Array of chunk spreads with liquidity data\n */\nexport async function getChunkSpreads(\n params: GetChunkSpreadsParams,\n): Promise<LiquidityChunkSpread[]> {\n const { chainId, poolAddress, storage, tokenType } = params\n\n // Get tracked chunks\n let chunks = await getTrackedChunks({ chainId, poolAddress, storage })\n\n // Apply filter\n if (tokenType !== undefined) {\n chunks = chunks.filter((c) => c.tokenType === tokenType)\n }\n\n if (chunks.length === 0) {\n return []\n }\n\n // Return tracked chunks without liquidity data\n // Use scanChunks() for on-chain liquidity data\n return chunks.map((chunk) => ({\n ...chunk,\n netLiquidity: 0n,\n removedLiquidity: 0n,\n spreadWad: WAD,\n }))\n}\n\n/**\n * Calculate spread from liquidity values.\n *\n * spread = 1 + (1/VEGOID) * removedLiquidity / netLiquidity\n *\n * @param netLiquidity - Liquidity in Uniswap\n * @param removedLiquidity - Liquidity borrowed by buyers\n * @param vegoid - VEGOID constant (default: 4n)\n * @returns Spread in WAD (1e18 = 1.0x)\n */\nexport function calculateSpreadWad(\n netLiquidity: bigint,\n removedLiquidity: bigint,\n vegoid: bigint = DEFAULT_VEGOID,\n): bigint {\n if (netLiquidity === 0n) {\n return WAD // 1.0x spread if no liquidity\n }\n\n // spread = WAD + (WAD / vegoid) * removedLiquidity / netLiquidity\n // = WAD + (WAD * removedLiquidity) / (vegoid * netLiquidity)\n const bonus = (WAD * removedLiquidity) / (vegoid * netLiquidity)\n return WAD + bonus\n}\n\n/**\n * Clear all tracked chunks for a pool.\n *\n * @param params - Parameters\n */\nexport async function clearTrackedChunks(params: GetTrackedChunksParams): Promise<void> {\n const { chainId, poolAddress, storage } = params\n\n const key = getTrackedChunksKey(chainId, poolAddress)\n await storage.delete(key)\n}\n\n// ============================================================================\n// PanopticQuery-based chunk functions (recommended)\n// ============================================================================\n\n/**\n * Scanned chunk with liquidity data from PanopticQuery.scanChunks().\n */\nexport interface ScannedChunk {\n /** Strike tick (center of the chunk) */\n strike: bigint\n /** Token type 0 net liquidity */\n netLiquidity0: bigint\n /** Token type 1 net liquidity */\n netLiquidity1: bigint\n /** Token type 0 removed liquidity */\n removedLiquidity0: bigint\n /** Token type 1 removed liquidity */\n removedLiquidity1: bigint\n /** Computed spread for token type 0 */\n spreadWad0: bigint\n /** Computed spread for token type 1 */\n spreadWad1: bigint\n /** Token type 0 settled tokens (LeftRightUnsigned: left=token1, right=token0) */\n settledTokens0: bigint\n /** Token type 1 settled tokens (LeftRightUnsigned: left=token1, right=token0) */\n settledTokens1: bigint\n}\n\n/**\n * Result of scanning chunks in a tick range.\n */\nexport interface ScanChunksResult {\n /** Array of scanned chunks with liquidity data */\n chunks: ScannedChunk[]\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for scanChunks().\n */\nexport interface ScanChunksParams {\n /** viem public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** PanopticQuery contract address */\n queryAddress: Address\n /** Lower tick bound of range to scan */\n tickLower: bigint\n /** Upper tick bound of range to scan */\n tickUpper: bigint\n /** Width of chunks to scan (tickUpper - tickLower for each chunk) */\n width: bigint\n /** VEGOID constant for spread calculation (default: 4n) */\n vegoid?: bigint\n /** Optional block number for historical queries */\n blockNumber?: bigint\n}\n\n/**\n * Scan for non-empty liquidity chunks in a tick range.\n *\n * Uses PanopticQuery.scanChunks() to discover chunks with liquidity.\n * Returns only non-empty chunks, making it efficient for large ranges.\n *\n * ## Same-Block Guarantee\n * All data is fetched at a single block.\n *\n * @param params - Parameters\n * @returns Scanned chunks with liquidity data and block metadata\n *\n * @example\n * ```typescript\n * const result = await scanChunks({\n * client,\n * poolAddress: '0x...',\n * queryAddress: '0x...',\n * tickLower: -1000n,\n * tickUpper: 1000n,\n * width: 100n, // 100 tick wide chunks\n * })\n *\n * for (const chunk of result.chunks) {\n * console.log(`Strike ${chunk.strike}: spread0=${chunk.spreadWad0}, spread1=${chunk.spreadWad1}`)\n * }\n * ```\n */\nexport async function scanChunks(params: ScanChunksParams): Promise<ScanChunksResult> {\n const {\n client,\n poolAddress,\n queryAddress,\n tickLower,\n tickUpper,\n width,\n vegoid = 4n,\n blockNumber,\n } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'scanChunks',\n args: [poolAddress, Number(tickLower), Number(tickUpper), Number(width)],\n blockNumber: targetBlockNumber,\n }),\n getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const [strikes, netLiquidities, removedLiquidities, settledTokens] = result\n\n const chunks: ScannedChunk[] = strikes.map((strike, i) => {\n const net0 = netLiquidities[i][0]\n const net1 = netLiquidities[i][1]\n const removed0 = removedLiquidities[i][0]\n const removed1 = removedLiquidities[i][1]\n\n return {\n strike: BigInt(strike),\n netLiquidity0: net0,\n netLiquidity1: net1,\n removedLiquidity0: removed0,\n removedLiquidity1: removed1,\n spreadWad0: calculateSpreadWad(net0, removed0, vegoid),\n spreadWad1: calculateSpreadWad(net1, removed1, vegoid),\n settledTokens0: settledTokens[i][0],\n settledTokens1: settledTokens[i][1],\n }\n })\n\n return { chunks, _meta }\n}\n\n/**\n * Chunk data for a single leg of a position.\n */\nexport interface LegChunkData {\n /** Leg index (0-3) */\n legIndex: number\n /** Net liquidity (liquidity in Uniswap) */\n netLiquidity: bigint\n /** Removed liquidity (borrowed by option buyers) */\n removedLiquidity: bigint\n /** Computed spread */\n spreadWad: bigint\n}\n\n/**\n * Chunk data for a position (all legs).\n */\nexport interface PositionChunkData {\n /** TokenId of the position */\n tokenId: bigint\n /** Chunk data for each leg */\n legs: LegChunkData[]\n}\n\n/**\n * Result of getting position chunk data.\n */\nexport interface GetPositionChunkDataResult {\n /** Array of position chunk data */\n positions: PositionChunkData[]\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for getPositionChunkData().\n */\nexport interface GetPositionChunkDataParams {\n /** viem public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** PanopticQuery contract address */\n queryAddress: Address\n /** Array of tokenIds to query */\n tokenIds: bigint[]\n /** VEGOID constant for spread calculation (default: 4n) */\n vegoid?: bigint\n /** Optional block number for historical queries */\n blockNumber?: bigint\n}\n\n/**\n * Get chunk data (liquidity) for specific positions.\n *\n * Uses PanopticQuery.getChunkData() to fetch net and removed liquidity\n * for each leg of the given positions.\n *\n * ## Same-Block Guarantee\n * All data is fetched at a single block.\n *\n * @param params - Parameters\n * @returns Position chunk data with liquidity for each leg\n *\n * @example\n * ```typescript\n * const result = await getPositionChunkData({\n * client,\n * poolAddress: '0x...',\n * queryAddress: '0x...',\n * tokenIds: [tokenId1, tokenId2],\n * })\n *\n * for (const pos of result.positions) {\n * console.log(`Position ${pos.tokenId}:`)\n * for (const leg of pos.legs) {\n * console.log(` Leg ${leg.legIndex}: net=${leg.netLiquidity}, removed=${leg.removedLiquidity}`)\n * }\n * }\n * ```\n */\nexport async function getPositionChunkData(\n params: GetPositionChunkDataParams,\n): Promise<GetPositionChunkDataResult> {\n const {\n client,\n poolAddress,\n queryAddress,\n tokenIds,\n vegoid = DEFAULT_VEGOID,\n blockNumber,\n } = params\n\n if (tokenIds.length === 0) {\n const _meta = await getBlockMeta({ client, blockNumber })\n return { positions: [], _meta }\n }\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n\n const [chunkData, _meta] = await Promise.all([\n client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getChunkData',\n args: [poolAddress, tokenIds],\n blockNumber: targetBlockNumber,\n }),\n getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // chunkData is uint256[2][4][] - [positionIndex][legIndex][0=net, 1=removed]\n const positions: PositionChunkData[] = tokenIds.map((tokenId, posIndex) => {\n const positionData = chunkData[posIndex]\n const legs: LegChunkData[] = []\n\n // Each position has up to 4 legs\n for (let legIndex = 0; legIndex < 4; legIndex++) {\n const legData = positionData[legIndex]\n const netLiquidity = legData[0]\n const removedLiquidity = legData[1]\n\n // Only include legs with data (non-zero liquidity indicates active leg)\n if (netLiquidity > 0n || removedLiquidity > 0n) {\n legs.push({\n legIndex,\n netLiquidity,\n removedLiquidity,\n spreadWad: calculateSpreadWad(netLiquidity, removedLiquidity, vegoid),\n })\n }\n }\n\n return { tokenId, legs }\n })\n\n return { positions, _meta }\n}\n","/**\n * Pending position tracking for optimistic updates.\n * @module v2/sync/pendingPositions\n */\n\nimport type { Address, Hash } from 'viem'\n\nimport type { StorageAdapter } from '../storage'\nimport { getPendingPositionsKey, jsonSerializer } from '../storage'\nimport type { TokenIdLeg } from '../types'\n\n/**\n * A pending position that has been submitted but not yet confirmed.\n */\nexport interface PendingPosition {\n /** The TokenId */\n tokenId: bigint\n /** Owner address */\n owner: Address\n /** Pool address */\n poolAddress: Address\n /** Position size (from simulation) */\n positionSize: bigint\n /** Decoded legs */\n legs: TokenIdLeg[]\n /** Transaction hash */\n txHash: Hash\n /** Block number when submitted */\n submittedAtBlock: bigint\n /** Timestamp when submitted */\n submittedAt: bigint\n /** Status */\n status: 'pending' | 'confirmed' | 'failed'\n}\n\n/**\n * Parameters for adding a pending position.\n */\nexport interface AddPendingPositionParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account (owner) */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Pending position data */\n position: PendingPosition\n}\n\n/**\n * Add a pending position for optimistic updates.\n *\n * Called when openPosition() submits a transaction.\n *\n * @param params - Parameters\n */\nexport async function addPendingPosition(params: AddPendingPositionParams): Promise<void> {\n const { chainId, poolAddress, account, storage, position } = params\n\n const key = getPendingPositionsKey(chainId, poolAddress, account)\n const existingData = await storage.get(key)\n\n let pending: PendingPosition[]\n if (existingData) {\n try {\n pending = jsonSerializer.parse(existingData) as PendingPosition[]\n } catch {\n pending = []\n }\n } else {\n pending = []\n }\n\n // Add new pending position\n pending.push(position)\n\n await storage.set(key, jsonSerializer.stringify(pending))\n}\n\n/**\n * Parameters for getting pending positions.\n */\nexport interface GetPendingPositionsParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account (owner) */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n}\n\n/**\n * Get all pending positions for an account.\n *\n * @param params - Parameters\n * @returns Array of pending positions\n */\nexport async function getPendingPositions(\n params: GetPendingPositionsParams,\n): Promise<PendingPosition[]> {\n const { chainId, poolAddress, account, storage } = params\n\n const key = getPendingPositionsKey(chainId, poolAddress, account)\n const data = await storage.get(key)\n\n if (!data) {\n return []\n }\n\n try {\n const pending = jsonSerializer.parse(data) as PendingPosition[]\n // Only return pending status\n return pending.filter((p) => p.status === 'pending')\n } catch {\n return []\n }\n}\n\n/**\n * Parameters for confirming a pending position.\n */\nexport interface ConfirmPendingPositionParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account (owner) */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Token ID to confirm */\n tokenId: bigint\n}\n\n/**\n * Mark a pending position as confirmed.\n *\n * Called when syncPositions() finds the OptionMinted event.\n *\n * @param params - Parameters\n */\nexport async function confirmPendingPosition(params: ConfirmPendingPositionParams): Promise<void> {\n const { chainId, poolAddress, account, storage, tokenId } = params\n\n const key = getPendingPositionsKey(chainId, poolAddress, account)\n const existingData = await storage.get(key)\n\n if (!existingData) {\n return\n }\n\n let pending: PendingPosition[]\n try {\n pending = jsonSerializer.parse(existingData) as PendingPosition[]\n } catch {\n return\n }\n\n // Find and update the position\n const updated = pending.map((p) =>\n p.tokenId === tokenId ? { ...p, status: 'confirmed' as const } : p,\n )\n\n // Remove confirmed positions (they're now in the main position list)\n const remaining = updated.filter((p) => p.status === 'pending')\n\n if (remaining.length === 0) {\n await storage.delete(key)\n } else {\n await storage.set(key, jsonSerializer.stringify(remaining))\n }\n}\n\n/**\n * Parameters for failing a pending position.\n */\nexport interface FailPendingPositionParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account (owner) */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Transaction hash that failed */\n txHash: Hash\n}\n\n/**\n * Mark a pending position as failed (transaction reverted).\n *\n * @param params - Parameters\n */\nexport async function failPendingPosition(params: FailPendingPositionParams): Promise<void> {\n const { chainId, poolAddress, account, storage, txHash } = params\n\n const key = getPendingPositionsKey(chainId, poolAddress, account)\n const existingData = await storage.get(key)\n\n if (!existingData) {\n return\n }\n\n let pending: PendingPosition[]\n try {\n pending = jsonSerializer.parse(existingData) as PendingPosition[]\n } catch {\n return\n }\n\n // Remove the failed position\n const remaining = pending.filter((p) => p.txHash !== txHash)\n\n if (remaining.length === 0) {\n await storage.delete(key)\n } else {\n await storage.set(key, jsonSerializer.stringify(remaining))\n }\n}\n\n/**\n * Clear all pending positions for an account.\n *\n * @param params - Parameters\n */\nexport async function clearPendingPositions(params: GetPendingPositionsParams): Promise<void> {\n const { chainId, poolAddress, account, storage } = params\n\n const key = getPendingPositionsKey(chainId, poolAddress, account)\n await storage.delete(key)\n}\n\n/**\n * Clean up stale pending positions.\n *\n * Removes pending positions older than the specified block threshold.\n * This handles cases where transactions were dropped from the mempool.\n *\n * @param params - Parameters\n * @param maxAgeBlocks - Maximum age in blocks (default: 100)\n * @param currentBlock - Current block number\n */\nexport async function cleanupStalePendingPositions(\n params: GetPendingPositionsParams,\n currentBlock: bigint,\n maxAgeBlocks: bigint = 100n,\n): Promise<void> {\n const { chainId, poolAddress, account, storage } = params\n\n const key = getPendingPositionsKey(chainId, poolAddress, account)\n const existingData = await storage.get(key)\n\n if (!existingData) {\n return\n }\n\n let pending: PendingPosition[]\n try {\n pending = jsonSerializer.parse(existingData) as PendingPosition[]\n } catch {\n return\n }\n\n // Filter out stale positions\n const threshold = currentBlock - maxAgeBlocks\n const remaining = pending.filter((p) => p.status === 'pending' && p.submittedAtBlock > threshold)\n\n if (remaining.length === 0) {\n await storage.delete(key)\n } else if (remaining.length !== pending.length) {\n await storage.set(key, jsonSerializer.stringify(remaining))\n }\n}\n","/**\n * Event reconstruction for full position history scan.\n * @module v2/sync/eventReconstruction\n */\n\nimport type { Address, Hash, PublicClient } from 'viem'\n\nimport type { SyncEvent } from '../types'\n\n/**\n * Parameters for event reconstruction.\n */\nexport interface EventReconstructionParams {\n /** viem public client */\n client: PublicClient\n /** Pool address */\n poolAddress: Address\n /** Account to reconstruct positions for */\n account: Address\n /** Starting block for event scan */\n fromBlock: bigint\n /** Ending block for event scan */\n toBlock: bigint\n /** Batch size for log queries (default: 10000) */\n batchSize?: bigint\n /** Progress callback */\n onProgress?: (event: SyncEvent) => void\n}\n\n/**\n * Event reconstruction result.\n */\nexport interface EventReconstructionResult {\n /** Position IDs that are currently open */\n openPositions: bigint[]\n /** Position IDs that have been closed */\n closedPositions: bigint[]\n /** Number of blocks scanned */\n blocksScanned: bigint\n /** Last scanned block number */\n lastBlock: bigint\n /** Last scanned block hash */\n lastBlockHash: Hash\n}\n\n/**\n * Mint event from reconstruction.\n */\ninterface MintEvent {\n tokenId: bigint\n positionSize: bigint\n blockNumber: bigint\n blockHash: Hash\n transactionHash: Hash\n logIndex: number\n}\n\n/**\n * Burn event from reconstruction.\n */\ninterface BurnEvent {\n tokenId: bigint\n positionSize: bigint\n blockNumber: bigint\n blockHash: Hash\n transactionHash: Hash\n logIndex: number\n}\n\n/**\n * Reconstruct position history from events.\n * This is the fallback method when snapshot recovery fails.\n * It scans all OptionMinted and OptionBurnt events to build the position set.\n *\n * @param params - Reconstruction parameters\n * @returns Reconstruction result with open and closed positions\n */\nexport async function reconstructFromEvents(\n params: EventReconstructionParams,\n): Promise<EventReconstructionResult> {\n const {\n client,\n poolAddress,\n account,\n fromBlock,\n toBlock,\n batchSize = 10000n,\n onProgress,\n } = params\n\n const mintEvents: MintEvent[] = []\n const burnEvents: BurnEvent[] = []\n\n let currentBlock = fromBlock\n const totalBlocks = toBlock - fromBlock\n\n // Scan in batches\n while (currentBlock <= toBlock) {\n const endBlock =\n currentBlock + batchSize - 1n > toBlock ? toBlock : currentBlock + batchSize - 1n\n\n // Fetch mint events for this batch\n const [mints, burns] = await Promise.all([\n client.getLogs({\n address: poolAddress,\n event: {\n type: 'event',\n name: 'OptionMinted',\n inputs: [\n { type: 'address', name: 'recipient', indexed: true },\n { type: 'uint256', name: 'tokenId', indexed: true },\n { type: 'uint256', name: 'balanceData', indexed: false },\n ],\n },\n args: {\n recipient: account,\n },\n fromBlock: currentBlock,\n toBlock: endBlock,\n }),\n client.getLogs({\n address: poolAddress,\n event: {\n type: 'event',\n name: 'OptionBurnt',\n inputs: [\n { type: 'address', name: 'recipient', indexed: true },\n { type: 'uint256', name: 'tokenId', indexed: true },\n { type: 'uint256', name: 'positionSize', indexed: false },\n { type: 'int256[4]', name: 'premiaByLeg', indexed: false },\n ],\n },\n args: {\n recipient: account,\n },\n fromBlock: currentBlock,\n toBlock: endBlock,\n }),\n ])\n\n // Process mint events\n for (const mint of mints) {\n // Decode position size from balanceData (first 128 bits)\n const balanceData = mint.args.balanceData as bigint\n const positionSize = balanceData & ((1n << 128n) - 1n)\n\n mintEvents.push({\n tokenId: mint.args.tokenId as bigint,\n positionSize,\n blockNumber: mint.blockNumber,\n blockHash: mint.blockHash,\n transactionHash: mint.transactionHash,\n logIndex: mint.logIndex,\n })\n }\n\n // Process burn events\n for (const burn of burns) {\n burnEvents.push({\n tokenId: burn.args.tokenId as bigint,\n positionSize: burn.args.positionSize as bigint,\n blockNumber: burn.blockNumber,\n blockHash: burn.blockHash,\n transactionHash: burn.transactionHash,\n logIndex: burn.logIndex,\n })\n }\n\n // Report progress\n if (onProgress) {\n const blocksProcessed = endBlock - fromBlock + 1n\n const progress = totalBlocks > 0n ? (blocksProcessed * 100n) / totalBlocks : 100n\n\n onProgress({\n currentBlock: endBlock,\n targetBlock: toBlock,\n positionsFound: BigInt(mintEvents.length),\n progress,\n })\n }\n\n currentBlock = endBlock + 1n\n }\n\n // Build position map: tokenId -> net position size\n const positionMap = new Map<bigint, bigint>()\n\n // Sort all events by block and log index\n const allEvents = [\n ...mintEvents.map((e) => ({ ...e, type: 'mint' as const })),\n ...burnEvents.map((e) => ({ ...e, type: 'burn' as const })),\n ].sort((a, b) => {\n const blockDiff = Number(a.blockNumber - b.blockNumber)\n if (blockDiff !== 0) return blockDiff\n return a.logIndex - b.logIndex\n })\n\n // Process events in order\n for (const event of allEvents) {\n const current = positionMap.get(event.tokenId) ?? 0n\n\n if (event.type === 'mint') {\n positionMap.set(event.tokenId, current + event.positionSize)\n } else {\n positionMap.set(event.tokenId, current - event.positionSize)\n }\n }\n\n // Separate open and closed positions\n const openPositions: bigint[] = []\n const closedPositions: bigint[] = []\n\n for (const [tokenId, size] of positionMap) {\n if (size > 0n) {\n openPositions.push(tokenId)\n } else {\n closedPositions.push(tokenId)\n }\n }\n\n // Get the last block hash\n const lastBlock = await client.getBlock({ blockNumber: toBlock })\n\n return {\n openPositions,\n closedPositions,\n blocksScanned: toBlock - fromBlock + 1n,\n lastBlock: toBlock,\n lastBlockHash: lastBlock.hash,\n }\n}\n\n/**\n * Get the deployment block for a pool.\n * This searches for the first PoolInitialized event.\n *\n * @param client - viem public client\n * @param poolAddress - Pool address\n * @returns Deployment block number or null if not found\n */\nexport async function getPoolDeploymentBlock(\n client: PublicClient,\n poolAddress: Address,\n): Promise<bigint | null> {\n // Search for the first event from this pool\n // We use a binary search approach to find the deployment block\n\n const currentBlock = await client.getBlockNumber()\n let low = 0n\n let high = currentBlock\n let foundBlock: bigint | null = null\n\n // Binary search with scan windows to find the deployment block.\n // Each iteration checks [mid, mid + scanRange] for logs.\n const scanRange = 10000n\n\n while (low <= high) {\n const mid = (low + high) / 2n\n const rangeEnd = mid + scanRange > high ? high : mid + scanRange\n\n try {\n const logs = await client.getLogs({\n address: poolAddress,\n fromBlock: mid,\n toBlock: rangeEnd,\n })\n\n if (logs.length > 0) {\n // Found logs — record earliest and search before it\n const earliest = logs[0].blockNumber\n if (foundBlock === null || earliest < foundBlock) {\n foundBlock = earliest\n }\n high = earliest - 1n\n } else {\n // No logs in [mid, rangeEnd] — skip the entire checked range\n low = rangeEnd + 1n\n }\n } catch {\n // Range too large for RPC — halve the search space\n high = mid + (rangeEnd - mid) / 2n\n }\n }\n\n return foundBlock\n}\n","/**\n * Stable cache-scope helpers for React query keys.\n * @module v2/react/cacheScopes\n */\n\nconst DEFAULT_CLIENT_CACHE_SCOPE = 'default-client'\nconst DEFAULT_STORAGE_CACHE_SCOPE = 'default-storage'\n\nexport function getClientCacheScope(scope?: string): string {\n return scope ?? DEFAULT_CLIENT_CACHE_SCOPE\n}\n\nexport function getStorageCacheScope(scope?: string): string {\n return scope ?? DEFAULT_STORAGE_CACHE_SCOPE\n}\n\nexport function getClientCacheScopeKey(client: unknown, scope?: string): string {\n // Keep client in the queryKey expression for exhaustive-deps while keying by stable scope.\n void client\n return getClientCacheScope(scope)\n}\n\nexport function getStorageCacheScopeKey(storage: unknown, scope?: string): string {\n // Keep storage in the queryKey expression for exhaustive-deps while keying by stable scope.\n void storage\n return getStorageCacheScope(scope)\n}\n\nexport function getAtTickCacheKey(atTick?: bigint): string {\n return atTick === undefined ? 'latest' : atTick.toString()\n}\n","/**\n * React context provider for the Panoptic v2 SDK.\n * @module v2/react/provider\n */\n\nimport { type ReactNode, createContext, useContext } from 'react'\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport type { StorageAdapter } from '../storage'\n\n/**\n * Panoptic SDK context value.\n */\nexport interface PanopticContextValue {\n /** viem PublicClient for reading chain state */\n publicClient: PublicClient\n /**\n * Optional cache scope for read/simulation query keys.\n * Use this when multiple environments share the same QueryClient.\n */\n clientScope?: string\n /** Optional viem WalletClient for write operations */\n walletClient?: WalletClient\n /** Optional account address for write operations */\n account?: Address\n /** Chain ID */\n chainId: bigint\n /** Optional StateView address for V4 Uniswap pool reads (per-chain singleton) */\n stateViewAddress?: Address\n /** Optional storage adapter for position tracking */\n storage?: StorageAdapter\n /**\n * Optional cache scope for storage-backed query keys.\n * Set this when swapping storage adapters at runtime.\n */\n storageScope?: string\n}\n\nconst PanopticContext = createContext<PanopticContextValue | null>(null)\n\n/**\n * Props for PanopticProvider.\n */\nexport interface PanopticProviderProps extends PanopticContextValue {\n children: ReactNode\n}\n\n/**\n * Context provider for Panoptic v2 SDK hooks.\n *\n * Wraps children with shared publicClient, walletClient, account, chainId, and storage.\n * Does NOT include QueryClientProvider — you must provide your own.\n *\n * @example\n * ```tsx\n * <QueryClientProvider client={queryClient}>\n * <PanopticProvider\n * publicClient={publicClient}\n * walletClient={walletClient}\n * account={address}\n * chainId={1n}\n * >\n * <App />\n * </PanopticProvider>\n * </QueryClientProvider>\n * ```\n */\nexport function PanopticProvider({ children, ...value }: PanopticProviderProps) {\n return <PanopticContext.Provider value={value}>{children}</PanopticContext.Provider>\n}\n\n/**\n * Access the Panoptic SDK context.\n *\n * @throws Error if used outside PanopticProvider\n * @returns PanopticContextValue\n */\nexport function usePanopticContext(): PanopticContextValue {\n const ctx = useContext(PanopticContext)\n if (!ctx) {\n throw new Error('usePanopticContext must be used within a PanopticProvider')\n }\n return ctx\n}\n\n/**\n * Internal hook that requires walletClient and account.\n *\n * @throws Error if walletClient or account not provided in context\n * @returns { walletClient, account } guaranteed non-undefined\n */\nexport function useRequireWallet(): { walletClient: WalletClient; account: Address } {\n const { walletClient, account } = usePanopticContext()\n if (!walletClient || !account) {\n throw new Error('walletClient and account are required. Provide them via PanopticProvider.')\n }\n return { walletClient, account }\n}\n\n/**\n * Internal hook that requires storage adapter.\n *\n * @throws Error if storage not provided in context\n * @returns StorageAdapter guaranteed non-undefined\n */\nexport function useRequireStorage(): StorageAdapter {\n const { storage } = usePanopticContext()\n if (!storage) {\n throw new Error('storage is required. Provide a StorageAdapter via PanopticProvider.')\n }\n return storage\n}\n","/**\n * Query key factory for TanStack Query / SWR integration.\n * @module v2/react/queryKeys\n */\n\nimport type { Address } from 'viem'\n\n/**\n * Query key factory for Panoptic v2 SDK data.\n *\n * Use with TanStack Query or SWR for cache key consistency.\n * All keys are arrays for proper cache matching and invalidation.\n *\n * @example\n * ```typescript\n * import { useQuery } from '@tanstack/react-query'\n * import { queryKeys, getPool } from 'panoptic-v2-sdk'\n *\n * function usePool(config: PanopticConfig) {\n * return useQuery({\n * queryKey: queryKeys.pool(config.chainId, config.poolAddress),\n * queryFn: () => getPool(config),\n * })\n * }\n * ```\n */\nexport const queryKeys = {\n /**\n * Base key for all Panoptic v2 queries.\n */\n all: ['panoptic-v2'] as const,\n\n /**\n * Key for pool data.\n */\n pool: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'pool', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for pool utilization.\n */\n utilization: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'utilization', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for oracle state.\n */\n oracle: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'oracle', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for safe mode state.\n */\n safeMode: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'safeMode', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for Guardian pool-unlock state.\n */\n guardianUnlock: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'guardianUnlock', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for risk parameters.\n */\n riskParameters: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'riskParameters', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for current rates.\n */\n rates: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'rates', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for a single position.\n */\n position: (chainId: bigint, poolAddress: Address, tokenId: bigint) =>\n [...queryKeys.all, 'position', chainId.toString(), poolAddress, tokenId.toString()] as const,\n\n /**\n * Key for all positions of an account.\n */\n positions: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'positions', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for tracked position IDs.\n */\n trackedPositionIds: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'trackedPositionIds', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for sync status.\n */\n syncStatus: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'syncStatus', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for account collateral.\n */\n accountCollateral: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'accountCollateral', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for base account summary (aggregate dashboard data).\n */\n accountSummaryBasic: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'accountSummaryBasic', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for risk-focused account summary.\n */\n accountSummaryRisk: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'accountSummaryRisk', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for liquidation check.\n */\n isLiquidatable: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'isLiquidatable', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for liquidation prices.\n */\n liquidationPrices: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'liquidationPrices', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for net liquidation value.\n */\n netLiquidationValue: (chainId: bigint, poolAddress: Address, account: Address, atTick: bigint) =>\n [\n ...queryKeys.all,\n 'netLiquidationValue',\n chainId.toString(),\n poolAddress,\n account,\n atTick.toString(),\n ] as const,\n\n /**\n * Key for chunk spreads.\n */\n chunkSpreads: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'chunkSpreads', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for closed positions.\n */\n closedPositions: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'closedPositions', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for trade history.\n */\n tradeHistory: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'tradeHistory', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for realized PnL.\n */\n realizedPnL: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'realizedPnL', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for position greeks.\n */\n positionGreeks: (chainId: bigint, poolAddress: Address, tokenId: bigint) =>\n [\n ...queryKeys.all,\n 'positionGreeks',\n chainId.toString(),\n poolAddress,\n tokenId.toString(),\n ] as const,\n\n /**\n * Key for account greeks.\n */\n accountGreeks: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'accountGreeks', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for collateral estimate.\n */\n collateralEstimate: (chainId: bigint, poolAddress: Address, account: Address, tokenId: bigint) =>\n [\n ...queryKeys.all,\n 'collateralEstimate',\n chainId.toString(),\n poolAddress,\n account,\n tokenId.toString(),\n ] as const,\n\n /**\n * Key for max position size.\n */\n maxPositionSize: (chainId: bigint, poolAddress: Address, account: Address, tokenId: bigint) =>\n [\n ...queryKeys.all,\n 'maxPositionSize',\n chainId.toString(),\n poolAddress,\n account,\n tokenId.toString(),\n ] as const,\n\n /**\n * Key for max withdrawable assets from a collateral tracker.\n */\n maxWithdrawable: (\n chainId: bigint,\n collateralTrackerAddress: Address,\n positionIdList: bigint[],\n totalAssets: bigint,\n account: Address,\n ) =>\n [\n ...queryKeys.all,\n chainId.toString(),\n 'maxWithdrawable',\n collateralTrackerAddress,\n positionIdList.map(String).join(','),\n totalAssets.toString(),\n account,\n ] as const,\n\n /**\n * Key for approval check.\n */\n approval: (chainId: bigint, token: Address, owner: Address, spender: Address) =>\n [...queryKeys.all, 'approval', chainId.toString(), token, owner, spender] as const,\n\n /**\n * Key for ERC4626 preview operations.\n */\n erc4626Preview: (chainId: bigint, tracker: Address, operation: string, amount: bigint) =>\n [\n ...queryKeys.all,\n 'erc4626Preview',\n chainId.toString(),\n tracker,\n operation,\n amount.toString(),\n ] as const,\n\n /**\n * Key for margin buffer.\n */\n marginBuffer: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'marginBuffer', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for account premia.\n */\n accountPremia: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'accountPremia', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for positions with premia.\n */\n positionsWithPremia: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'positionsWithPremia', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for collateral data.\n */\n collateralData: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'collateralData', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for pool liquidities.\n */\n poolLiquidities: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'poolLiquidities', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for optimized risk partners.\n */\n optimizeRiskPartners: (chainId: bigint, poolAddress: Address, tokenId: bigint) =>\n [\n ...queryKeys.all,\n 'optimizeRiskPartners',\n chainId.toString(),\n poolAddress,\n tokenId.toString(),\n ] as const,\n /**\n * Key for price history.\n * Uses a hash of timestamps for cache busting when the time range changes.\n */\n priceHistory: (chainId: bigint, poolAddress: string, timestampsHash: string) =>\n [...queryKeys.all, 'priceHistory', chainId.toString(), poolAddress, timestampsHash] as const,\n\n /**\n * Key for streamia history.\n */\n streamiaHistory: (chainId: bigint, poolAddress: string, rangeHash: string) =>\n [...queryKeys.all, 'streamiaHistory', chainId.toString(), poolAddress, rangeHash] as const,\n\n /**\n * Key for Uniswap fee history.\n */\n uniswapFeeHistory: (chainId: bigint, poolAddress: string, rangeHash: string) =>\n [...queryKeys.all, 'uniswapFeeHistory', chainId.toString(), poolAddress, rangeHash] as const,\n\n /**\n * Key for required credit for ITM position.\n */\n requiredCreditForITM: (\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n tokenId: bigint,\n ) =>\n [\n ...queryKeys.all,\n 'requiredCreditForITM',\n chainId.toString(),\n poolAddress,\n account,\n tokenId.toString(),\n ] as const,\n /**\n * Key for interest state (per-user borrows).\n */\n interestState: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'interestState', chainId.toString(), poolAddress, account] as const,\n} as const\n","/**\n * TanStack Query v5 read hooks for the Panoptic v2 SDK.\n * @module v2/react/hooks/reads\n */\n\nimport { keepPreviousData, useMutation, useQuery } from '@tanstack/react-query'\nimport type { Address, PublicClient } from 'viem'\n\nimport { estimateBlockNumbers, resolveBlockNumbers } from '../../clients/blocksByTimestamp'\nimport { PanopticValidationError } from '../../errors'\nimport {\n type GetEnforcedTickLimitsParams,\n type GetFactoryConstructMetadataParams,\n type GetFactoryOwnerOfParams,\n type GetFactoryTokenURIParams,\n type GetPanopticPoolAddressParams,\n type GetPanopticPoolFromPoolIdParams,\n type GetUniswapV3PoolFromIdParams,\n type GetUniswapV4PoolKeyFromIdParams,\n type MinePoolAddressLocalParams,\n type ResolvePanopticPoolFromPoolIdParams,\n type SimulateDeployNewPoolParams,\n type UniswapV4PoolKey,\n estimateCollateralRequired,\n getAccountCollateral,\n getAccountGreeks,\n getAccountPremia,\n getAccountSummaryBasic,\n getAccountSummaryRisk,\n getCollateralData,\n getCurrentRates,\n getEnforcedTickLimits,\n getFactoryConstructMetadata,\n getFactoryOwnerOf,\n getFactoryTokenURI,\n getGuardianUnlockState,\n getInterestState,\n getLiquidationPrices,\n getMarginBuffer,\n getMaxPositionSize,\n getMaxWithdrawable,\n getNativeTokenPrice,\n getNetLiquidationValue,\n getNetLiquidationValues,\n getOpenPositionPreview,\n getOracleState,\n getPanopticPoolAddress,\n getPanopticPoolFromPoolId,\n getPool,\n getPoolLiquidities,\n getPosition,\n getPositionGreeks,\n getPositions,\n getPositionsWithPremia,\n getRequiredCreditForITM,\n getRiskParameters,\n getSafeMode,\n getUniswapV3PoolFromId,\n getUniswapV3PoolInfo,\n getUniswapV3PoolLiquidities,\n getUniswapV4PoolBasicState,\n getUniswapV4PoolInfo,\n getUniswapV4PoolKeyFromId,\n getUniswapV4PoolLiquidities,\n getUtilization,\n isLiquidatable,\n minePoolAddressLocalAsync,\n previewDeposit,\n previewMint,\n previewRedeem,\n previewWithdraw,\n resolvePanopticPoolFromPoolId,\n resolveUniswapV4PoolKey,\n simulateDeployNewPool,\n validateBuilderCode,\n} from '../../reads'\nimport { getPriceHistory } from '../../reads/priceHistory'\nimport { optimizeTokenIdRiskPartners } from '../../reads/queryUtils'\nimport type { StreamiaLeg } from '../../reads/streamiaHistory'\nimport { getStreamiaHistory } from '../../reads/streamiaHistory'\nimport { getUniswapFeeHistory } from '../../reads/uniswapFeeHistory'\nimport {\n getChunkSpreads,\n getClosedPositions,\n getRealizedPnL,\n getSyncStatus,\n getTrackedPositionIds,\n getTradeHistory,\n scanChunks,\n} from '../../sync'\nimport type { PoolVersionConfig } from '../../types/poolConfig'\nimport { interpolateBlocks } from '../../utils/interpolateBlocks'\nimport { previewBorrow } from '../../writes/lending'\nimport { getAtTickCacheKey, getClientCacheScopeKey, getStorageCacheScopeKey } from '../cacheScopes'\nimport { usePanopticContext, useRequireStorage } from '../provider'\nimport { queryKeys } from '../queryKeys'\n\n/**\n * Common query options exposed to consumers.\n */\nexport interface QueryOptions {\n /** Whether the query is enabled */\n enabled?: boolean\n /** Refetch interval in milliseconds */\n refetchInterval?: number | false\n /** Time in milliseconds that data is considered fresh */\n staleTime?: number\n /** Time in milliseconds that unused data is kept in cache */\n gcTime?: number\n}\n\n// --- Pool reads ---\n\nexport function usePool(poolAddress: Address, options?: QueryOptions) {\n const { publicClient, chainId, clientScope, stateViewAddress } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.pool(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n stateViewAddress,\n ],\n queryFn: () => getPool({ client: publicClient, poolAddress, chainId, stateViewAddress }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n // Caching is opt-in per consumer: per the SDK's \"no memoization of dynamic RPC\n // data\" constraint, we never default a staleTime here. App code can set one\n // explicitly when it knows the consumer can tolerate cached pool state.\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useUtilization(poolAddress: Address, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.utilization(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => getUtilization({ client: publicClient, poolAddress }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useOracleState(poolAddress: Address, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.oracle(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => getOracleState({ client: publicClient, poolAddress }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useRiskParameters(poolAddress: Address, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.riskParameters(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => getRiskParameters({ client: publicClient, poolAddress }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useCurrentRates(poolAddress: Address, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.rates(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => getCurrentRates({ client: publicClient, poolAddress }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useSafeMode(poolAddress: Address, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.safeMode(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => getSafeMode({ client: publicClient, poolAddress }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n/**\n * React hook for the Guardian pending-unlock state of a pool.\n *\n * Reads `unlockEta` + `isPoolUnlockReady` from the PanopticGuardian so the UI\n * can surface the unlock timelock while a pool is locked (close-only). Gate it\n * via `options.enabled` so it only runs when the pool is actually locked.\n *\n * @param poolAddress - The PanopticPool address\n * @param options - Optional react-query settings (enabled, refetchInterval, staleTime, gcTime)\n * @returns A react-query result whose `data` is a `GuardianUnlockState`\n */\nexport function useGuardianUnlockState(poolAddress: Address, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.guardianUnlock(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => getGuardianUnlockState({ client: publicClient, poolAddress }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useCollateralData(poolAddress: Address, tokenIndex: 0 | 1, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.collateralData(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n tokenIndex,\n ],\n queryFn: () => getCollateralData({ client: publicClient, poolAddress, tokenIndex }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function usePoolLiquidities(\n poolAddress: Address,\n params: { queryAddress: Address; startTick: bigint; nTicks: bigint },\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.poolLiquidities(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n params.queryAddress,\n params.startTick,\n params.nTicks,\n ],\n queryFn: () =>\n getPoolLiquidities({\n client: publicClient,\n poolAddress,\n queryAddress: params.queryAddress,\n startTick: params.startTick,\n nTicks: params.nTicks,\n }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useScanChunks(\n poolAddress: Address,\n params: { queryAddress: Address; tickLower: bigint; tickUpper: bigint; width: bigint },\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.chunkSpreads(chainId, poolAddress),\n 'scanChunks',\n getClientCacheScopeKey(publicClient, clientScope),\n params.queryAddress,\n params.tickLower,\n params.tickUpper,\n params.width,\n ],\n queryFn: () =>\n scanChunks({\n client: publicClient,\n poolAddress,\n queryAddress: params.queryAddress,\n tickLower: params.tickLower,\n tickUpper: params.tickUpper,\n width: params.width,\n }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useChunkSpreads(\n poolAddress: Address,\n params: { sfpmAddress: Address },\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope, storageScope } = usePanopticContext()\n const storage = useRequireStorage()\n return useQuery({\n queryKey: [\n ...queryKeys.chunkSpreads(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n params.sfpmAddress,\n getStorageCacheScopeKey(storage, storageScope),\n ],\n queryFn: () =>\n getChunkSpreads({\n client: publicClient,\n chainId,\n poolAddress,\n sfpmAddress: params.sfpmAddress,\n storage,\n }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Position reads ---\n\nexport function usePosition(\n poolAddress: Address,\n owner: Address,\n tokenId: bigint,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.position(chainId, poolAddress, tokenId),\n getClientCacheScopeKey(publicClient, clientScope),\n owner,\n ],\n queryFn: () => getPosition({ client: publicClient, poolAddress, owner, tokenId }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function usePositions(\n poolAddress: Address,\n tokenIds: bigint[],\n owner?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedOwner = owner ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.positions(ctx.chainId, poolAddress, resolvedOwner ?? ('' as Address)),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n ],\n queryFn: () => {\n if (!resolvedOwner) throw new Error('owner required for getPositions')\n return getPositions({ client: ctx.publicClient, poolAddress, owner: resolvedOwner, tokenIds })\n },\n enabled: (options?.enabled ?? true) && !!resolvedOwner,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function usePositionGreeks(\n poolAddress: Address,\n tokenId: bigint,\n owner: Address,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.positionGreeks(chainId, poolAddress, tokenId),\n getClientCacheScopeKey(publicClient, clientScope),\n owner,\n ],\n queryFn: () => getPositionGreeks({ client: publicClient, poolAddress, tokenId, owner }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Account reads ---\n\nexport function useAccountCollateral(\n poolAddress: Address,\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.accountCollateral(ctx.chainId, poolAddress, resolvedAccount ?? ('' as Address)),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n ],\n queryFn: () => {\n if (!resolvedAccount) throw new Error('account required for getAccountCollateral')\n return getAccountCollateral({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount,\n })\n },\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useInterestState(poolAddress: Address, account?: Address, options?: QueryOptions) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.interestState(ctx.chainId, poolAddress, resolvedAccount ?? ('' as Address)),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n ],\n queryFn: () => {\n if (!resolvedAccount) throw new Error('account required for getInterestState')\n return getInterestState({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount,\n })\n },\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useAccountSummaryBasic(\n poolAddress: Address,\n tokenIds: bigint[],\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.accountSummaryBasic(\n ctx.chainId,\n poolAddress,\n resolvedAccount ?? ('' as Address),\n ),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n ],\n queryFn: () => {\n if (!resolvedAccount) throw new Error('account required for getAccountSummaryBasic')\n return getAccountSummaryBasic({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount,\n chainId: ctx.chainId,\n tokenIds,\n })\n },\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useAccountSummaryRisk(\n poolAddress: Address,\n tokenIds: bigint[],\n queryAddress: Address,\n account?: Address,\n options?: QueryOptions & { atTick?: bigint; includePendingPremium?: boolean },\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.accountSummaryRisk(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n queryAddress,\n options?.atTick,\n options?.includePendingPremium,\n ],\n queryFn: () =>\n getAccountSummaryRisk({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n chainId: ctx.chainId,\n tokenIds,\n queryAddress,\n atTick: options?.atTick,\n includePendingPremium: options?.includePendingPremium,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useNetLiquidationValue(\n poolAddress: Address,\n tokenIds: bigint[],\n queryAddress: Address,\n account?: Address,\n options?: QueryOptions & { atTick?: bigint },\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'netLiquidationValue',\n ctx.chainId.toString(),\n poolAddress,\n resolvedAccount!,\n getAtTickCacheKey(options?.atTick),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n queryAddress,\n ],\n queryFn: () =>\n getNetLiquidationValue({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenIds,\n atTick: options?.atTick,\n queryAddress,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useNetLiquidationValues(\n poolAddress: Address,\n tokenIds: bigint[],\n queryAddress: Address,\n atTicks: bigint[],\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'netLiquidationValues',\n ctx.chainId.toString(),\n poolAddress,\n resolvedAccount!,\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n queryAddress,\n atTicks,\n ],\n queryFn: () =>\n getNetLiquidationValues({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenIds,\n atTicks,\n queryAddress,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount && atTicks.length > 0,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useLiquidationPrices(\n poolAddress: Address,\n tokenIds: bigint[],\n queryAddress: Address,\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.liquidationPrices(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n queryAddress,\n ],\n queryFn: () =>\n getLiquidationPrices({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenIds,\n queryAddress,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useAccountGreeks(poolAddress: Address, account?: Address, options?: QueryOptions) {\n const ctx = usePanopticContext()\n const storage = useRequireStorage()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.accountGreeks(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n getStorageCacheScopeKey(storage, ctx.storageScope),\n ],\n queryFn: () =>\n getAccountGreeks({\n client: ctx.publicClient,\n chainId: ctx.chainId,\n poolAddress,\n account: resolvedAccount!,\n storage,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useMarginBuffer(\n poolAddress: Address,\n tokenIds: bigint[],\n queryAddress: Address,\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.marginBuffer(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n queryAddress,\n ],\n queryFn: () =>\n getMarginBuffer({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenIds,\n queryAddress,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useIsLiquidatable(\n poolAddress: Address,\n tokenIds: bigint[],\n queryAddress: Address,\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.isLiquidatable(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n queryAddress,\n ],\n queryFn: () =>\n isLiquidatable({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenIds,\n queryAddress,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useAccountPremia(\n poolAddress: Address,\n tokenIds: bigint[],\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.accountPremia(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n ],\n queryFn: () =>\n getAccountPremia({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenIds,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function usePositionsWithPremia(\n poolAddress: Address,\n tokenIds: bigint[],\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.positionsWithPremia(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n ],\n queryFn: () =>\n getPositionsWithPremia({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenIds,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- ERC4626 previews ---\n\nexport function usePreviewDeposit(\n poolAddress: Address,\n tokenIndex: 0 | 1,\n amount: bigint,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.erc4626Preview(chainId, poolAddress, 'deposit', amount),\n getClientCacheScopeKey(publicClient, clientScope),\n tokenIndex,\n ],\n queryFn: () => previewDeposit({ client: publicClient, poolAddress, tokenIndex, amount }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function usePreviewWithdraw(\n poolAddress: Address,\n tokenIndex: 0 | 1,\n amount: bigint,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.erc4626Preview(chainId, poolAddress, 'withdraw', amount),\n getClientCacheScopeKey(publicClient, clientScope),\n tokenIndex,\n ],\n queryFn: () => previewWithdraw({ client: publicClient, poolAddress, tokenIndex, amount }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function usePreviewMint(\n poolAddress: Address,\n tokenIndex: 0 | 1,\n amount: bigint,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.erc4626Preview(chainId, poolAddress, 'mint', amount),\n getClientCacheScopeKey(publicClient, clientScope),\n tokenIndex,\n ],\n queryFn: () => previewMint({ client: publicClient, poolAddress, tokenIndex, amount }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function usePreviewRedeem(\n poolAddress: Address,\n tokenIndex: 0 | 1,\n amount: bigint,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.erc4626Preview(chainId, poolAddress, 'redeem', amount),\n getClientCacheScopeKey(publicClient, clientScope),\n tokenIndex,\n ],\n queryFn: () => previewRedeem({ client: publicClient, poolAddress, tokenIndex, amount }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Collateral estimation ---\n\nexport function useEstimateCollateralRequired(\n poolAddress: Address,\n tokenId: bigint,\n positionSize: bigint,\n queryAddress: Address,\n account?: Address,\n options?: QueryOptions & { atTick?: bigint },\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.collateralEstimate(ctx.chainId, poolAddress, resolvedAccount!, tokenId),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n positionSize,\n queryAddress,\n options?.atTick,\n ],\n queryFn: () =>\n estimateCollateralRequired({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenId,\n positionSize,\n queryAddress,\n atTick: options?.atTick,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useRequiredCreditForITM(\n poolAddress: Address,\n tokenId: bigint,\n positionSize: bigint,\n account?: Address,\n options?: QueryOptions & { existingPositionIds?: bigint[] },\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.requiredCreditForITM(\n ctx.chainId,\n poolAddress,\n resolvedAccount ?? ('' as Address),\n tokenId,\n ),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n positionSize,\n options?.existingPositionIds,\n ],\n queryFn: () => {\n if (!resolvedAccount) throw new Error('account required for getRequiredCreditForITM')\n return getRequiredCreditForITM({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount,\n tokenId,\n positionSize,\n existingPositionIds: options?.existingPositionIds,\n })\n },\n enabled: (options?.enabled ?? true) && !!resolvedAccount && tokenId !== 0n && positionSize > 0n,\n refetchInterval: options?.refetchInterval,\n placeholderData: keepPreviousData,\n })\n}\n\nexport function useMaxPositionSize(\n poolAddress: Address,\n tokenId: bigint,\n queryAddress: Address,\n account?: Address,\n options?: QueryOptions & {\n existingPositionIds?: bigint[]\n swapAtMint?: boolean\n precisionPct?: number\n },\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.maxPositionSize(\n ctx.chainId,\n poolAddress,\n resolvedAccount ?? ('' as Address),\n tokenId,\n ),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n queryAddress,\n options?.existingPositionIds?.map(String).join(',') ?? '',\n options?.existingPositionIds,\n options?.swapAtMint ?? false,\n options?.precisionPct ?? 1,\n ],\n queryFn: () => {\n if (!resolvedAccount) throw new Error('account required for getMaxPositionSize')\n return getMaxPositionSize({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount,\n tokenId,\n queryAddress,\n existingPositionIds: options?.existingPositionIds,\n swapAtMint: options?.swapAtMint,\n precisionPct: options?.precisionPct,\n })\n },\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n placeholderData: keepPreviousData,\n })\n}\n\nexport function useOptimizeRiskPartners(\n poolAddress: Address,\n tokenId: bigint,\n queryAddress: Address,\n atTick?: bigint,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.optimizeRiskPartners(chainId, poolAddress, tokenId),\n getClientCacheScopeKey(publicClient, clientScope),\n queryAddress,\n getAtTickCacheKey(atTick),\n ],\n queryFn: () =>\n optimizeTokenIdRiskPartners({\n client: publicClient,\n poolAddress,\n tokenId,\n queryAddress,\n atTick,\n }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n placeholderData: keepPreviousData,\n })\n}\n\nexport function useMaxWithdrawable(\n collateralTrackerAddress: Address,\n positionIdList: bigint[],\n totalAssets: bigint,\n account?: Address,\n options?: QueryOptions & { client?: PublicClient },\n) {\n const ctx = usePanopticContext()\n const client = options?.client ?? ctx.publicClient\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.maxWithdrawable(\n ctx.chainId,\n collateralTrackerAddress,\n positionIdList,\n totalAssets,\n resolvedAccount ?? ('' as Address),\n ),\n getClientCacheScopeKey(client, ctx.clientScope),\n ],\n queryFn: () => {\n if (!resolvedAccount) throw new Error('account required for getMaxWithdrawable')\n return getMaxWithdrawable({\n client,\n collateralTrackerAddress,\n account: resolvedAccount,\n positionIdList,\n totalAssets,\n })\n },\n enabled: (options?.enabled ?? true) && !!resolvedAccount && totalAssets > 0n,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Open position preview ---\n\nexport function useOpenPositionPreview(\n poolAddress: Address,\n account: Address | undefined,\n existingPositionIds: bigint[],\n tokenId: bigint,\n positionSize: bigint,\n queryAddress: Address,\n tickLimitLow: bigint,\n tickLimitHigh: bigint,\n options?: QueryOptions & {\n spreadLimit?: bigint\n swapAtMint?: boolean\n usePremiaAsCollateral?: boolean\n blockNumber?: bigint\n },\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n // eslint-disable-next-line @tanstack/query/exhaustive-deps -- deps serialized as strings\n queryKey: [\n ...queryKeys.all,\n 'openPositionPreview',\n ctx.chainId.toString(),\n poolAddress,\n resolvedAccount!,\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenId.toString(),\n positionSize.toString(),\n existingPositionIds.map(String).join(','),\n queryAddress,\n tickLimitLow.toString(),\n tickLimitHigh.toString(),\n options?.spreadLimit?.toString(),\n options?.swapAtMint,\n options?.usePremiaAsCollateral,\n options?.blockNumber?.toString(),\n ],\n queryFn: () =>\n getOpenPositionPreview({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n existingPositionIds,\n tokenId,\n positionSize,\n queryAddress,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit: options?.spreadLimit,\n swapAtMint: options?.swapAtMint,\n usePremiaAsCollateral: options?.usePremiaAsCollateral,\n chainId: ctx.chainId,\n blockNumber: options?.blockNumber,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount && tokenId !== 0n,\n staleTime: options?.staleTime ?? 0,\n })\n}\n\n// --- Storage-backed reads ---\n\nexport function useTrackedPositionIds(\n poolAddress: Address,\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const storage = useRequireStorage()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.trackedPositionIds(ctx.chainId, poolAddress, resolvedAccount!),\n getStorageCacheScopeKey(storage, ctx.storageScope),\n ],\n queryFn: () =>\n getTrackedPositionIds({\n chainId: ctx.chainId,\n poolAddress,\n account: resolvedAccount!,\n storage,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useTradeHistory(poolAddress: Address, account?: Address, options?: QueryOptions) {\n const ctx = usePanopticContext()\n const storage = useRequireStorage()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.tradeHistory(ctx.chainId, poolAddress, resolvedAccount!),\n getStorageCacheScopeKey(storage, ctx.storageScope),\n ],\n queryFn: () =>\n getTradeHistory({ chainId: ctx.chainId, poolAddress, account: resolvedAccount!, storage }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useRealizedPnL(poolAddress: Address, account?: Address, options?: QueryOptions) {\n const ctx = usePanopticContext()\n const storage = useRequireStorage()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.realizedPnL(ctx.chainId, poolAddress, resolvedAccount!),\n getStorageCacheScopeKey(storage, ctx.storageScope),\n ],\n queryFn: () =>\n getRealizedPnL({ chainId: ctx.chainId, poolAddress, account: resolvedAccount!, storage }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useClosedPositions(\n poolAddress: Address,\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const storage = useRequireStorage()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.closedPositions(ctx.chainId, poolAddress, resolvedAccount!),\n getStorageCacheScopeKey(storage, ctx.storageScope),\n ],\n queryFn: () =>\n getClosedPositions({ chainId: ctx.chainId, poolAddress, account: resolvedAccount!, storage }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useSyncStatus(poolAddress: Address, account?: Address, options?: QueryOptions) {\n const ctx = usePanopticContext()\n const storage = useRequireStorage()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.syncStatus(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n getStorageCacheScopeKey(storage, ctx.storageScope),\n ],\n queryFn: () =>\n getSyncStatus({\n client: ctx.publicClient,\n chainId: ctx.chainId,\n poolAddress,\n account: resolvedAccount!,\n storage,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Factory reads ---\n\ntype OmitFactoryClient<T> = T extends unknown ? Omit<T, 'client'> : never\n\nexport function usePanopticPoolAddress(\n params?: OmitFactoryClient<GetPanopticPoolAddressParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'factory',\n 'getPanopticPool',\n params?.factoryAddress,\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getPanopticPoolAddress({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useFactoryTokenURI(\n params?: OmitFactoryClient<GetFactoryTokenURIParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'factory',\n 'tokenURI',\n params?.factoryAddress,\n params?.tokenId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getFactoryTokenURI({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useFactoryOwnerOf(\n params?: OmitFactoryClient<GetFactoryOwnerOfParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'factory',\n 'ownerOf',\n params?.factoryAddress,\n params?.tokenId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getFactoryOwnerOf({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useMinePoolAddress() {\n return useMutation({\n mutationFn: (params: MinePoolAddressLocalParams) => minePoolAddressLocalAsync(params),\n })\n}\n\nexport function useFactoryConstructMetadata(\n params?: OmitFactoryClient<GetFactoryConstructMetadataParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'factory',\n 'constructMetadata',\n params?.factoryAddress,\n params?.panopticPoolAddress,\n params?.symbol0,\n params?.symbol1,\n params?.fee?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getFactoryConstructMetadata({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\ntype OmitMineClient<T> = T extends unknown ? Omit<T, 'client'> : never\n\nexport function useSimulateDeployNewPool(\n params?: OmitMineClient<SimulateDeployNewPoolParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'factory',\n 'simulateDeployNewPool',\n params?.factoryAddress,\n params?.account,\n params?.salt?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return simulateDeployNewPool({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Price history ---\n\n/** Timestamp-based time range. Start/end resolved to blocks via RPC binary search or estimation. */\nexport interface TimestampTimeRange {\n mode: 'timestamps'\n /** Start of the range (Unix seconds) */\n startTimestamp: number\n /** End of the range (Unix seconds). Defaults to now if omitted. */\n endTimestamp?: number\n /** Number of evenly-spaced data points to fetch */\n points: number\n /** Extra block numbers to include in the fetched set (e.g. blockAtMint) */\n pinnedBlocks?: bigint[]\n /**\n * Block resolution strategy.\n * - 'exact': RPC binary search (~25 sequential getBlock calls). Default.\n * - 'estimate': 2-RPC linear extrapolation. Suitable for charts where\n * ±N-block error is invisible. Saves ~23 RPCs per call.\n */\n resolution?: 'exact' | 'estimate'\n}\n\n/** Block-based time range. No RPC resolution needed. */\nexport interface BlockTimeRange {\n mode: 'blocks'\n /** Start block number */\n startBlock: bigint\n /** End block number. Defaults to latest if omitted. */\n endBlock?: bigint\n /** Number of evenly-spaced data points to fetch */\n points: number\n /** Extra block numbers to include in the fetched set (e.g. blockAtMint) */\n pinnedBlocks?: bigint[]\n}\n\nexport type PriceHistoryTimeRange = TimestampTimeRange | BlockTimeRange\n\n/**\n * Build a stable string cache key from time range params (no object references).\n */\nfunction buildRangeHash(timeRange: PriceHistoryTimeRange): string {\n const pinnedSuffix = timeRange.pinnedBlocks?.length\n ? `-pin:${timeRange.pinnedBlocks.join(',')}`\n : ''\n return timeRange.mode === 'timestamps'\n ? `ts:${timeRange.startTimestamp}-${timeRange.endTimestamp ?? 'now'}-${timeRange.points}-${timeRange.resolution ?? 'exact'}${pinnedSuffix}`\n : `blk:${timeRange.startBlock}-${timeRange.endBlock ?? 'latest'}-${timeRange.points}${pinnedSuffix}`\n}\n\n/**\n * Resolve a PriceHistoryTimeRange to start/end block numbers.\n */\nasync function resolveTimeRange(\n client: PublicClient,\n timeRange: PriceHistoryTimeRange,\n): Promise<{ startBlock: bigint; endBlock: bigint }> {\n if (timeRange.mode === 'timestamps') {\n const resolver =\n timeRange.resolution === 'estimate' ? estimateBlockNumbers : resolveBlockNumbers\n if (timeRange.endTimestamp !== undefined) {\n const resolved = await resolver({\n client,\n timestamps: [timeRange.startTimestamp, timeRange.endTimestamp],\n })\n return { startBlock: resolved[0], endBlock: resolved[1] }\n } else {\n const [resolved, latest] = await Promise.all([\n resolver({ client, timestamps: [timeRange.startTimestamp] }),\n client.getBlockNumber(),\n ])\n return { startBlock: resolved[0], endBlock: latest }\n }\n } else {\n return {\n startBlock: timeRange.startBlock,\n endBlock: timeRange.endBlock ?? (await client.getBlockNumber()),\n }\n }\n}\n\n/**\n * Hook to fetch historical price data (tick + sqrtPriceX96) for a pool.\n *\n * Supports two modes:\n * - **timestamps**: Resolves start/end timestamps to blocks (2 RPC binary searches),\n * then interpolates the blocks in between (pure math).\n * - **blocks**: Uses start/end blocks directly, interpolates in between.\n * Zero resolution overhead.\n *\n * In both cases, the actual price reads are O(points) slot0 calls.\n * Reads at different historical blocks cannot be coalesced into one multicall.\n *\n * @param poolConfig - Pool version config (V3 pool address or V4 StateView + poolId)\n * @param timeRange - Time range specification (timestamps or blocks)\n * @param options - Query options (enabled, refetchInterval, staleTime, gcTime)\n */\nexport function usePriceHistory(\n poolConfig: PoolVersionConfig,\n timeRange: PriceHistoryTimeRange,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n\n const poolKey = poolConfig.version === 'v3' ? poolConfig.poolAddress : poolConfig.poolId\n const rangeHash = buildRangeHash(timeRange)\n\n return useQuery({\n // rangeHash serializes timeRange; poolKey serializes poolConfig\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.priceHistory(chainId, poolKey, rangeHash),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: async () => {\n const { startBlock, endBlock } = await resolveTimeRange(publicClient, timeRange)\n let blockNumbers = interpolateBlocks(startBlock, endBlock, timeRange.points)\n\n // Merge pinned blocks (e.g. blockAtMint) into the sorted array\n if (timeRange.pinnedBlocks?.length) {\n const blockSet = new Set(blockNumbers.map(String))\n const extras = timeRange.pinnedBlocks.filter(\n (b) => b >= startBlock && b <= endBlock && !blockSet.has(String(b)),\n )\n if (extras.length > 0) {\n blockNumbers = [...blockNumbers, ...extras].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n }\n }\n\n return getPriceHistory({ client: publicClient, blockNumbers, poolConfig })\n },\n enabled: (options?.enabled ?? true) && timeRange.points > 0,\n staleTime: options?.staleTime ?? Infinity,\n gcTime: options?.gcTime ?? 60 * 60_000,\n refetchInterval: options?.refetchInterval ?? false,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n })\n}\n\n/**\n * Hook to fetch historical streamia (streaming premia + Uniswap fee) data for a position.\n *\n * @param panopticPoolAddress - PanopticPool contract address\n * @param account - Account whose position to query\n * @param tokenId - The encoded tokenId\n * @param legs - Decoded legs with pre-computed liquidity\n * @param poolConfig - Pool version config (V3 pool address or V4 StateView + poolId)\n * @param timeRange - Time range specification (timestamps or blocks)\n * @param options - Query options + optional includeUniswapFees and settledEvents\n */\nexport function useStreamiaHistory(\n panopticPoolAddress: Address,\n account: Address,\n tokenId: bigint,\n legs: StreamiaLeg[],\n poolConfig: PoolVersionConfig,\n timeRange: PriceHistoryTimeRange,\n options?: QueryOptions & {\n includeUniswapFees?: boolean\n settledEvents?: Array<{ blockNumber: bigint; settled0: bigint; settled1: bigint }>\n },\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n\n const poolKey = poolConfig.version === 'v3' ? poolConfig.poolAddress : poolConfig.poolId\n const rangeHash = buildRangeHash(timeRange)\n\n const legsKey = legs.map((l) => `${l.lowerTick}:${l.upperTick}:${l.liquidity}`).join(',')\n const includeUniswapFees = options?.includeUniswapFees ?? true\n const settledEventsKey = options?.settledEvents\n ? options.settledEvents.map((e) => `${e.blockNumber}:${e.settled0}:${e.settled1}`).join(',')\n : ''\n\n return useQuery({\n // rangeHash serializes timeRange; poolKey serializes poolConfig; legsKey serializes legs\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.streamiaHistory(chainId, poolKey, rangeHash),\n getClientCacheScopeKey(publicClient, clientScope),\n panopticPoolAddress,\n account,\n tokenId.toString(),\n legsKey,\n includeUniswapFees,\n settledEventsKey,\n ],\n queryFn: async () => {\n const { startBlock, endBlock } = await resolveTimeRange(publicClient, timeRange)\n let blockNumbers = interpolateBlocks(startBlock, endBlock, timeRange.points)\n if (timeRange.pinnedBlocks?.length) {\n const pinSet = new Set(blockNumbers.map(String))\n const pins = timeRange.pinnedBlocks.filter(\n (b) => b >= startBlock && b <= endBlock && !pinSet.has(String(b)),\n )\n if (pins.length) {\n blockNumbers = [...blockNumbers, ...pins].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n }\n }\n return getStreamiaHistory({\n client: publicClient,\n panopticPoolAddress,\n account,\n tokenId,\n blockNumbers,\n legs,\n poolConfig,\n includeUniswapFees: options?.includeUniswapFees,\n settledEvents: options?.settledEvents,\n })\n },\n enabled: (options?.enabled ?? true) && timeRange.points > 0,\n staleTime: options?.staleTime ?? Infinity,\n gcTime: options?.gcTime ?? 60 * 60_000,\n refetchInterval: options?.refetchInterval ?? false,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n })\n}\n\n/**\n * Hook to fetch historical Uniswap fee data for a set of liquidity legs.\n *\n * @param legs - Decoded legs with pre-computed liquidity\n * @param poolConfig - Pool version config (V3 pool address or V4 StateView + poolId)\n * @param timeRange - Time range specification (timestamps or blocks)\n * @param options - Query options (enabled, refetchInterval, staleTime, gcTime)\n */\nexport function useUniswapFeeHistory(\n legs: StreamiaLeg[],\n poolConfig: PoolVersionConfig,\n timeRange: PriceHistoryTimeRange,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n\n const poolKey = poolConfig.version === 'v3' ? poolConfig.poolAddress : poolConfig.poolId\n const rangeHash = buildRangeHash(timeRange)\n\n const legsKey = legs.map((l) => `${l.lowerTick}:${l.upperTick}:${l.liquidity}`).join(',')\n\n return useQuery({\n // rangeHash serializes timeRange; poolKey serializes poolConfig; legsKey serializes legs\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.uniswapFeeHistory(chainId, poolKey, rangeHash),\n getClientCacheScopeKey(publicClient, clientScope),\n legsKey,\n ],\n queryFn: async () => {\n const { startBlock, endBlock } = await resolveTimeRange(publicClient, timeRange)\n let blockNumbers = interpolateBlocks(startBlock, endBlock, timeRange.points)\n if (timeRange.pinnedBlocks?.length) {\n const pinSet = new Set(blockNumbers.map(String))\n const pins = timeRange.pinnedBlocks.filter(\n (b) => b >= startBlock && b <= endBlock && !pinSet.has(String(b)),\n )\n if (pins.length) {\n blockNumbers = [...blockNumbers, ...pins].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n }\n }\n return getUniswapFeeHistory({ client: publicClient, blockNumbers, legs, poolConfig })\n },\n enabled: (options?.enabled ?? true) && timeRange.points > 0 && legs.length > 0,\n staleTime: options?.staleTime ?? Infinity,\n gcTime: options?.gcTime ?? 60 * 60_000,\n refetchInterval: options?.refetchInterval ?? false,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n })\n}\n\n// --- Direct Uniswap V3 pool info (no Panoptic required) ---\n\n/**\n * Reads basic on-chain info (token0, token1, fee, tickSpacing, slot0, liquidity) from a Uniswap V3 pool.\n * @param poolAddress - The Uniswap V3 pool contract address.\n * @param options - Optional React Query options (`enabled`, `staleTime`, `gcTime`, `refetchInterval`).\n * @returns React Query result resolving to the pool info object.\n */\nexport function useUniswapV3PoolInfo(poolAddress: Address | undefined, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'uniswapV3PoolInfo',\n chainId.toString(),\n poolAddress,\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () =>\n getUniswapV3PoolInfo({ client: publicClient, poolAddress: poolAddress as Address }),\n enabled: (options?.enabled ?? true) && !!poolAddress,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n/**\n * Reads per-tick active liquidity from a Uniswap V3 pool via PanopticQuery's `getTickNetsV3`.\n * @param poolAddress - The Uniswap V3 pool contract address.\n * @param queryAddress - The PanopticQuery helper contract address.\n * @param args - Tick window: `startTick` (inclusive) and `nTicks` count to scan.\n * @param options - Optional React Query options (`enabled`, `staleTime`, `gcTime`, `refetchInterval`).\n * @returns React Query result resolving to `{ ticks, liquidityNets }` parallel arrays.\n */\nexport function useUniswapV3PoolLiquidities(\n poolAddress: Address | undefined,\n queryAddress: Address | undefined,\n args: { startTick: number; nTicks: bigint } | undefined,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'uniswapV3PoolLiquidities',\n chainId.toString(),\n poolAddress,\n queryAddress,\n args?.startTick,\n args?.nTicks,\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => {\n if (!poolAddress || !queryAddress || !args) {\n throw new PanopticValidationError('useUniswapV3PoolLiquidities: missing required args')\n }\n const { startTick, nTicks } = args\n return getUniswapV3PoolLiquidities({\n client: publicClient,\n poolAddress,\n queryAddress,\n startTick,\n nTicks,\n })\n },\n enabled: (options?.enabled ?? true) && !!poolAddress && !!queryAddress && !!args,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Uniswap V4 direct reads (no Panoptic required) ---\n\n/**\n * Resolves a Uniswap V4 PoolKey from a poolId hash by scanning `Initialize` event logs on the PoolManager.\n * PoolKey is immutable, so results are cached indefinitely within the session by default.\n * @param poolManager - The Uniswap V4 PoolManager contract address.\n * @param poolId - The 32-byte poolId hash.\n * @param args - Optional `fromBlock` and `chunkSize` for log paging.\n * @param options - Optional React Query options (`enabled`, `staleTime`, `gcTime`, `refetchInterval`).\n * @returns React Query result resolving to the resolved `UniswapV4PoolKey`.\n */\nexport function useResolveUniswapV4PoolKey(\n poolManager: Address | undefined,\n poolId: `0x${string}` | undefined,\n args?: { fromBlock?: bigint; chunkSize?: bigint },\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'uniswapV4PoolKey',\n chainId.toString(),\n poolManager,\n poolId,\n args?.fromBlock?.toString(),\n args?.chunkSize?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () =>\n resolveUniswapV4PoolKey({\n client: publicClient,\n poolManager: poolManager as Address,\n poolId: poolId as `0x${string}`,\n fromBlock: args?.fromBlock,\n chunkSize: args?.chunkSize,\n }),\n enabled: (options?.enabled ?? true) && !!poolManager && !!poolId,\n // PoolKey is immutable — cache forever within the session.\n staleTime: options?.staleTime ?? Infinity,\n gcTime: options?.gcTime,\n refetchInterval: options?.refetchInterval,\n })\n}\n\n/**\n * Reads basic on-chain state (slot0, liquidity) for a Uniswap V4 pool via the StateView contract.\n * @param stateViewAddress - The Uniswap V4 StateView contract address.\n * @param poolId - The 32-byte poolId hash.\n * @param options - Optional React Query options (`enabled`, `staleTime`, `gcTime`, `refetchInterval`).\n * @returns React Query result resolving to the pool's basic state.\n */\nexport function useUniswapV4PoolBasicState(\n stateViewAddress: Address | undefined,\n poolId: `0x${string}` | undefined,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'uniswapV4PoolBasicState',\n chainId.toString(),\n stateViewAddress,\n poolId,\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () =>\n getUniswapV4PoolBasicState({\n client: publicClient,\n stateViewAddress: stateViewAddress as Address,\n poolId: poolId as `0x${string}`,\n }),\n enabled: (options?.enabled ?? true) && !!stateViewAddress && !!poolId,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n/**\n * Reads full pool info (slot0, liquidity, and PoolKey-derived metadata) for a Uniswap V4 pool via the StateView contract.\n * @param stateViewAddress - The Uniswap V4 StateView contract address.\n * @param poolKey - The pool's `UniswapV4PoolKey` (currency0, currency1, fee, tickSpacing, hooks).\n * @param options - Optional React Query options (`enabled`, `staleTime`, `gcTime`, `refetchInterval`).\n * @returns React Query result resolving to the full pool info object.\n */\nexport function useUniswapV4PoolInfo(\n stateViewAddress: Address | undefined,\n poolKey: UniswapV4PoolKey | undefined,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'uniswapV4PoolInfo',\n chainId.toString(),\n stateViewAddress,\n poolKey?.currency0,\n poolKey?.currency1,\n poolKey?.fee,\n poolKey?.tickSpacing,\n poolKey?.hooks,\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () =>\n getUniswapV4PoolInfo({\n client: publicClient,\n stateViewAddress: stateViewAddress as Address,\n poolKey: poolKey as UniswapV4PoolKey,\n }),\n enabled: (options?.enabled ?? true) && !!stateViewAddress && !!poolKey,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n/**\n * Reads per-tick active liquidity from a Uniswap V4 pool via PanopticQuery's `getTickNetsV4`.\n * @param queryAddress - The PanopticQuery helper contract address.\n * @param poolManager - The Uniswap V4 PoolManager contract address.\n * @param poolId - The 32-byte poolId hash.\n * @param args - `tickSpacing`, `startTick` (inclusive), and `nTicks` count to scan.\n * @param options - Optional React Query options (`enabled`, `staleTime`, `gcTime`, `refetchInterval`).\n * @returns React Query result resolving to `{ ticks, liquidityNets }` parallel arrays.\n */\nexport function useUniswapV4PoolLiquidities(\n queryAddress: Address | undefined,\n poolManager: Address | undefined,\n poolId: `0x${string}` | undefined,\n args: { tickSpacing: number; startTick: number; nTicks: bigint } | undefined,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'uniswapV4PoolLiquidities',\n chainId.toString(),\n queryAddress,\n poolManager,\n poolId,\n args?.tickSpacing,\n args?.startTick,\n args?.nTicks,\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => {\n if (!queryAddress || !poolManager || !poolId || !args) {\n throw new PanopticValidationError('useUniswapV4PoolLiquidities: missing required args')\n }\n const { tickSpacing, startTick, nTicks } = args\n return getUniswapV4PoolLiquidities({\n client: publicClient,\n queryAddress,\n poolManager,\n poolId,\n tickSpacing,\n startTick,\n nTicks,\n })\n },\n enabled: (options?.enabled ?? true) && !!queryAddress && !!poolManager && !!poolId && !!args,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Native token price ---\n\nexport function useNativeTokenPrice(\n panopticPoolAddress: Address | undefined,\n token0Decimals: bigint,\n token1Decimals: bigint,\n nativeIsToken0: boolean,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'nativeTokenPrice',\n chainId,\n panopticPoolAddress,\n token0Decimals,\n token1Decimals,\n nativeIsToken0,\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () =>\n getNativeTokenPrice({\n client: publicClient,\n panopticPoolAddress: panopticPoolAddress!,\n token0Decimals,\n token1Decimals,\n nativeIsToken0,\n }),\n enabled: (options?.enabled ?? true) && panopticPoolAddress !== undefined,\n refetchInterval: options?.refetchInterval ?? 30_000,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- SFPM reads ---\n\ntype OmitSfpmClient<T> = Omit<T, 'client'>\n\nexport function useUniswapV3PoolFromId(\n params?: OmitSfpmClient<GetUniswapV3PoolFromIdParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sfpm',\n 'getUniswapV3PoolFromId',\n params?.sfpmAddress,\n params?.poolId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getUniswapV3PoolFromId({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useUniswapV4PoolKeyFromId(\n params?: OmitSfpmClient<GetUniswapV4PoolKeyFromIdParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sfpm',\n 'getUniswapV4PoolKeyFromId',\n params?.sfpmAddress,\n params?.poolId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getUniswapV4PoolKeyFromId({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useEnforcedTickLimits(\n params?: OmitSfpmClient<GetEnforcedTickLimitsParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sfpm',\n 'getEnforcedTickLimits',\n params?.sfpmAddress,\n params?.poolId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getEnforcedTickLimits({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Factory + SFPM composite reads ---\n\nexport function usePanopticPoolFromPoolId(\n params?: OmitFactoryClient<GetPanopticPoolFromPoolIdParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'factory',\n 'getPanopticPoolFromPoolId',\n params?.sfpmAddress,\n params?.factoryAddress,\n params?.riskEngine,\n params?.poolId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getPanopticPoolFromPoolId({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\ntype OmitResolveClient = Omit<ResolvePanopticPoolFromPoolIdParams, 'client'>\n\nexport function useResolvePanopticPoolFromPoolId(\n params?: OmitResolveClient,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'factory',\n 'resolvePanopticPoolFromPoolId',\n params?.poolId?.toString(),\n params?.riskEngine,\n params?.v3?.sfpmAddress,\n params?.v3?.factoryAddress,\n params?.v4?.sfpmAddress,\n params?.v4?.factoryAddress,\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return resolvePanopticPoolFromPoolId({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Borrow preview ---\n\nexport function usePreviewBorrow(\n poolAddress: Address,\n params?: {\n account: Address\n token: Address\n amount: bigint\n slippageBps: bigint\n existingPositionIds: bigint[]\n },\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'previewBorrow',\n ctx.chainId,\n poolAddress,\n params?.account,\n params?.token,\n params?.amount?.toString(),\n params?.slippageBps?.toString(),\n params?.existingPositionIds?.map(String).join(','),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n ],\n queryFn: () =>\n previewBorrow({\n client: ctx.publicClient,\n poolAddress,\n chainId: ctx.chainId,\n account: params!.account,\n token: params!.token,\n amount: params!.amount,\n slippageBps: params!.slippageBps,\n existingPositionIds: params!.existingPositionIds,\n }),\n enabled: (options?.enabled ?? true) && !!params && params.amount > 0n,\n staleTime: options?.staleTime ?? 10_000,\n gcTime: options?.gcTime,\n placeholderData: keepPreviousData,\n })\n}\n\n/**\n * Validate whether a builder code maps to a deployed builder wallet.\n *\n * Returns `{ data: true }` for valid codes, `{ data: false }` for invalid.\n * Disabled when `builderCode` is `undefined` or `0n`.\n */\nexport function useValidateBuilderCode(\n poolAddress: Address,\n builderCode: bigint | undefined,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n 'validateBuilderCode',\n poolAddress,\n String(builderCode),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => {\n if (builderCode === undefined) throw new Error('builderCode is undefined')\n return validateBuilderCode({\n client: publicClient,\n poolAddress,\n builderCode,\n })\n },\n enabled: (options?.enabled ?? true) && builderCode !== undefined && builderCode !== 0n,\n staleTime: options?.staleTime ?? 60_000,\n gcTime: options?.gcTime,\n })\n}\n","/**\n * Mutation effects for cache invalidation with TanStack Query / SWR.\n * @module v2/react/mutationEffects\n */\n\nimport type { Address } from 'viem'\n\nimport { queryKeys } from './queryKeys'\n\n/**\n * Mutation type identifiers.\n */\nexport type MutationType =\n | 'openPosition'\n | 'closePosition'\n | 'forceExercise'\n | 'liquidate'\n | 'settleAccumulatedPremia'\n | 'deposit'\n | 'withdraw'\n | 'mint'\n | 'redeem'\n | 'approve'\n | 'pokeOracle'\n\n/**\n * Parameters for determining which queries to invalidate.\n */\nexport interface MutationEffectParams {\n chainId: bigint\n poolAddress: Address\n account: Address\n tokenId?: bigint\n}\n\n/**\n * Returns query keys that should be invalidated after a mutation.\n *\n * Use with TanStack Query's `queryClient.invalidateQueries()` or SWR's `mutate()`.\n *\n * @example\n * ```typescript\n * import { useMutation, useQueryClient } from '@tanstack/react-query'\n * import { mutationEffects, openPosition } from 'panoptic-v2-sdk'\n *\n * function useOpenPosition(config: WriteConfig) {\n * const queryClient = useQueryClient()\n *\n * return useMutation({\n * mutationFn: (params) => openPosition(config, params),\n * onSuccess: () => {\n * const keysToInvalidate = mutationEffects.openPosition({\n * chainId: config.chainId,\n * poolAddress: config.poolAddress,\n * account: config.walletClient.account.address,\n * })\n *\n * for (const key of keysToInvalidate) {\n * queryClient.invalidateQueries({ queryKey: key })\n * }\n * },\n * })\n * }\n * ```\n */\nexport const mutationEffects = {\n /**\n * Queries to invalidate after opening a position.\n */\n openPosition: (params: MutationEffectParams): readonly (readonly string[])[] => {\n const { chainId, poolAddress, account } = params\n return [\n queryKeys.pool(chainId, poolAddress),\n queryKeys.utilization(chainId, poolAddress),\n queryKeys.positions(chainId, poolAddress, account),\n queryKeys.trackedPositionIds(chainId, poolAddress, account),\n queryKeys.accountCollateral(chainId, poolAddress, account),\n queryKeys.accountSummaryBasic(chainId, poolAddress, account),\n queryKeys.accountSummaryRisk(chainId, poolAddress, account),\n queryKeys.isLiquidatable(chainId, poolAddress, account),\n queryKeys.liquidationPrices(chainId, poolAddress, account),\n queryKeys.accountGreeks(chainId, poolAddress, account),\n queryKeys.chunkSpreads(chainId, poolAddress),\n ]\n },\n\n /**\n * Queries to invalidate after closing a position.\n */\n closePosition: (params: MutationEffectParams): readonly (readonly string[])[] => {\n const { chainId, poolAddress, account, tokenId } = params\n const keys: (readonly string[])[] = [\n queryKeys.pool(chainId, poolAddress),\n queryKeys.utilization(chainId, poolAddress),\n queryKeys.positions(chainId, poolAddress, account),\n queryKeys.trackedPositionIds(chainId, poolAddress, account),\n queryKeys.accountCollateral(chainId, poolAddress, account),\n queryKeys.accountSummaryBasic(chainId, poolAddress, account),\n queryKeys.accountSummaryRisk(chainId, poolAddress, account),\n queryKeys.isLiquidatable(chainId, poolAddress, account),\n queryKeys.liquidationPrices(chainId, poolAddress, account),\n queryKeys.accountGreeks(chainId, poolAddress, account),\n queryKeys.closedPositions(chainId, poolAddress, account),\n queryKeys.tradeHistory(chainId, poolAddress, account),\n queryKeys.realizedPnL(chainId, poolAddress, account),\n queryKeys.chunkSpreads(chainId, poolAddress),\n ]\n\n if (tokenId !== undefined) {\n keys.push(queryKeys.position(chainId, poolAddress, tokenId))\n keys.push(queryKeys.positionGreeks(chainId, poolAddress, tokenId))\n }\n\n return keys\n },\n\n /**\n * Queries to invalidate after force exercising a position.\n */\n forceExercise: (params: MutationEffectParams): readonly (readonly string[])[] => {\n const { chainId, poolAddress, account, tokenId } = params\n const keys: (readonly string[])[] = [\n queryKeys.pool(chainId, poolAddress),\n queryKeys.utilization(chainId, poolAddress),\n queryKeys.accountCollateral(chainId, poolAddress, account),\n queryKeys.accountSummaryBasic(chainId, poolAddress, account),\n queryKeys.accountSummaryRisk(chainId, poolAddress, account),\n queryKeys.chunkSpreads(chainId, poolAddress),\n ]\n\n if (tokenId !== undefined) {\n keys.push(queryKeys.position(chainId, poolAddress, tokenId))\n }\n\n return keys\n },\n\n /**\n * Queries to invalidate after liquidating an account.\n */\n liquidate: (params: MutationEffectParams): readonly (readonly string[])[] => {\n const { chainId, poolAddress, account } = params\n return [\n queryKeys.pool(chainId, poolAddress),\n queryKeys.utilization(chainId, poolAddress),\n queryKeys.positions(chainId, poolAddress, account),\n queryKeys.trackedPositionIds(chainId, poolAddress, account),\n queryKeys.accountCollateral(chainId, poolAddress, account),\n queryKeys.accountSummaryBasic(chainId, poolAddress, account),\n queryKeys.accountSummaryRisk(chainId, poolAddress, account),\n queryKeys.isLiquidatable(chainId, poolAddress, account),\n queryKeys.liquidationPrices(chainId, poolAddress, account),\n queryKeys.accountGreeks(chainId, poolAddress, account),\n queryKeys.closedPositions(chainId, poolAddress, account),\n queryKeys.chunkSpreads(chainId, poolAddress),\n ]\n },\n\n /**\n * Queries to invalidate after settling accumulated premia.\n */\n settleAccumulatedPremia: (params: MutationEffectParams): readonly (readonly string[])[] => {\n const { chainId, poolAddress, account, tokenId } = params\n const keys: (readonly string[])[] = [\n queryKeys.accountCollateral(chainId, poolAddress, account),\n queryKeys.accountSummaryBasic(chainId, poolAddress, account),\n queryKeys.accountSummaryRisk(chainId, poolAddress, account),\n ]\n\n if (tokenId !== undefined) {\n keys.push(queryKeys.position(chainId, poolAddress, tokenId))\n }\n\n return keys\n },\n\n /**\n * Queries to invalidate after depositing to collateral tracker.\n */\n deposit: (params: MutationEffectParams): readonly (readonly string[])[] => {\n const { chainId, poolAddress, account } = params\n return [\n queryKeys.accountCollateral(chainId, poolAddress, account),\n queryKeys.accountSummaryBasic(chainId, poolAddress, account),\n queryKeys.accountSummaryRisk(chainId, poolAddress, account),\n queryKeys.isLiquidatable(chainId, poolAddress, account),\n queryKeys.liquidationPrices(chainId, poolAddress, account),\n ]\n },\n\n /**\n * Queries to invalidate after withdrawing from collateral tracker.\n */\n withdraw: (params: MutationEffectParams): readonly (readonly string[])[] => {\n const { chainId, poolAddress, account } = params\n return [\n queryKeys.accountCollateral(chainId, poolAddress, account),\n queryKeys.accountSummaryBasic(chainId, poolAddress, account),\n queryKeys.accountSummaryRisk(chainId, poolAddress, account),\n queryKeys.isLiquidatable(chainId, poolAddress, account),\n queryKeys.liquidationPrices(chainId, poolAddress, account),\n ]\n },\n\n /**\n * Queries to invalidate after minting collateral shares.\n */\n mint: (params: MutationEffectParams): readonly (readonly string[])[] => {\n return mutationEffects.deposit(params)\n },\n\n /**\n * Queries to invalidate after redeeming collateral shares.\n */\n redeem: (params: MutationEffectParams): readonly (readonly string[])[] => {\n return mutationEffects.withdraw(params)\n },\n\n /**\n * Queries to invalidate after approving token spending.\n */\n approve: (\n chainId: bigint,\n token: Address,\n owner: Address,\n spender: Address,\n ): readonly (readonly string[])[] => {\n return [queryKeys.approval(chainId, token, owner, spender)]\n },\n\n /**\n * Queries to invalidate after poking the oracle.\n */\n pokeOracle: (\n params: Pick<MutationEffectParams, 'chainId' | 'poolAddress'>,\n ): readonly (readonly string[])[] => {\n const { chainId, poolAddress } = params\n return [queryKeys.oracle(chainId, poolAddress), queryKeys.safeMode(chainId, poolAddress)]\n },\n} as const\n","/**\n * TanStack Query v5 mutation hooks for the Panoptic v2 SDK.\n * @module v2/react/hooks/writes\n */\n\nimport { type QueryClient, useMutation, useQueryClient } from '@tanstack/react-query'\nimport type { Address, WalletClient } from 'viem'\n\nimport {\n type ApproveParams,\n type ApprovePoolParams,\n type BorrowParams,\n type ClosePositionParams,\n type DeployNewPoolParams,\n type DepositParams,\n type DispatchParams,\n type ExecuteBatchDispatchParams,\n type ForceExerciseParams,\n type LiquidateParams,\n type MintParams,\n type OpenPositionParams,\n type PokeOracleParams,\n type RedeemParams,\n type RepayParams,\n type RollPositionParams,\n type SettleParams,\n type SmartRepayParams,\n type SupplyParams,\n type SwapExactInParams,\n type SwapExactOutParams,\n type UnsupplyParams,\n type UnwrapWethParams,\n type UnwrapXstockParams,\n type WithdrawParams,\n type WithdrawWithPositionsParams,\n type WrapEthParams,\n type WrapXstockParams,\n approve,\n approvePool,\n borrow,\n closePosition,\n deployNewPool,\n deposit,\n dispatch,\n executeBatchDispatch,\n forceExerciseAndWait,\n liquidate,\n mint,\n openPosition,\n pokeOracle,\n redeem,\n repay,\n rollPosition,\n settleAccumulatedPremia,\n smartRepay,\n supply,\n swapExactIn,\n swapExactOut,\n unsupply,\n unwrapWeth,\n unwrapXstock,\n withdraw,\n withdrawWithPositions,\n wrapEth,\n wrapXstock,\n} from '../../writes'\nimport { mutationEffects } from '../mutationEffects'\nimport { usePanopticContext } from '../provider'\nimport { queryKeys } from '../queryKeys'\n\ntype OmitInjected<T> = T extends unknown ? Omit<T, 'client' | 'walletClient' | 'account'> : never\ntype OmitInjectedWithPool<T> = Omit<T, 'client' | 'walletClient' | 'account' | 'poolAddress'>\ntype OmitInjectedWithPoolAndChain<T> = Omit<\n T,\n 'client' | 'walletClient' | 'account' | 'poolAddress' | 'chainId'\n>\n\ntype WalletInputs = {\n walletClient?: WalletClient\n account?: Address\n}\n\ntype WalletMutationContext = {\n signerAccount: Address\n}\n\nfunction requireWallet(inputs: WalletInputs): { walletClient: WalletClient; account: Address } {\n if (!inputs.walletClient || !inputs.account) {\n throw new Error('walletClient and account are required. Provide them via PanopticProvider.')\n }\n\n return {\n walletClient: inputs.walletClient,\n account: inputs.account,\n }\n}\n\nfunction createWalletMutationContext(inputs: WalletInputs): WalletMutationContext {\n return { signerAccount: requireWallet(inputs).account }\n}\n\nfunction invalidateKeys(\n queryClient: QueryClient,\n keysToInvalidate: readonly (readonly string[])[],\n): void {\n const seen = new Set<string>()\n\n for (const key of keysToInvalidate) {\n const serialized = JSON.stringify(key)\n if (seen.has(serialized)) {\n continue\n }\n\n seen.add(serialized)\n queryClient.invalidateQueries({ queryKey: key })\n }\n}\n\nexport function useApprove() {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<ApproveParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return approve({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: (_data, params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.approve(\n chainId,\n params.tokenAddress,\n context.signerAccount,\n params.spenderAddress,\n ),\n )\n },\n })\n}\n\nexport function useApprovePool(poolAddress: Address) {\n const { publicClient, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<ApprovePoolParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return approvePool({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [...queryKeys.all, 'approval'] })\n },\n })\n}\n\nexport function useDeposit(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<DepositParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return deposit({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.deposit({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useWithdraw(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<WithdrawParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return withdraw({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.withdraw({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\n/**\n * Wrap an underlying xStock into its ERC4626 wrapper (`deposit`). Requires a\n * prior approval of the underlying to the wrapper (use {@link useApprove}).\n * Invalidates SDK queries so balances refetch.\n */\nexport function useWrapXstock() {\n const { publicClient, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<WrapXstockParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return wrapXstock({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [...queryKeys.all] })\n },\n })\n}\n\n/**\n * Unwrap wrapper shares back into the underlying xStock (`redeem`). Burns the\n * owner's own shares — no approval needed.\n */\nexport function useUnwrapXstock() {\n const { publicClient, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<UnwrapXstockParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return unwrapXstock({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [...queryKeys.all] })\n },\n })\n}\n\n/**\n * Wrap native ETH into WETH (`deposit` payable). No approval needed.\n * Invalidates SDK queries so balances refetch.\n */\nexport function useWrapEth() {\n const { publicClient, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<WrapEthParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return wrapEth({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [...queryKeys.all] })\n },\n })\n}\n\n/**\n * Unwrap WETH back into native ETH (`withdraw`). Burns the caller's own WETH —\n * no approval needed. Invalidates SDK queries so balances refetch.\n */\nexport function useUnwrapWeth() {\n const { publicClient, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<UnwrapWethParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return unwrapWeth({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [...queryKeys.all] })\n },\n })\n}\n\nexport function useMintShares(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<MintParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return mint({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.mint({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useRedeem(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<RedeemParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return redeem({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.redeem({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useWithdrawWithPositions(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<WithdrawWithPositionsParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return withdrawWithPositions({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.withdraw({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useOpenPosition(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<OpenPositionParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return openPosition({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.openPosition({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useClosePosition(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<ClosePositionParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return closePosition({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: (_data, params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.closePosition({\n chainId,\n poolAddress,\n account: context.signerAccount,\n tokenId: params.tokenId,\n }),\n )\n },\n })\n}\n\nexport function useRollPosition(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<RollPositionParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return rollPosition({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.openPosition({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useLiquidate(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<LiquidateParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return liquidate({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: (_data, params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(queryClient, [\n ...mutationEffects.liquidate({ chainId, poolAddress, account: context.signerAccount }),\n ...mutationEffects.liquidate({ chainId, poolAddress, account: params.liquidatee }),\n ])\n },\n })\n}\n\nexport function useForceExercise(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account, storage } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (\n params: Omit<\n ForceExerciseParams,\n 'client' | 'walletClient' | 'account' | 'poolAddress' | 'chainId' | 'storage'\n >,\n ) => {\n const wallet = requireWallet({ walletClient, account })\n return forceExerciseAndWait({\n client: publicClient,\n ...wallet,\n poolAddress,\n ...params,\n storage,\n chainId,\n })\n },\n onSuccess: (_data, params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(queryClient, [\n ...mutationEffects.forceExercise({ chainId, poolAddress, account: context.signerAccount }),\n ...mutationEffects.forceExercise({ chainId, poolAddress, account: params.user }),\n ])\n },\n })\n}\n\nexport function useSettleAccumulatedPremia(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<SettleParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return settleAccumulatedPremia({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.settleAccumulatedPremia({\n chainId,\n poolAddress,\n account: context.signerAccount,\n }),\n )\n },\n })\n}\n\nexport function usePokeOracle(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params?: OmitInjectedWithPool<PokeOracleParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return pokeOracle({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: () => {\n invalidateKeys(queryClient, mutationEffects.pokeOracle({ chainId, poolAddress }))\n },\n })\n}\n\nexport function useDispatch(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<DispatchParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return dispatch({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.openPosition({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useBatchDispatch(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<ExecuteBatchDispatchParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return executeBatchDispatch({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: (_data, params, context) => {\n if (!context) {\n return\n }\n\n const closedTokenIds = params.items.filter((i) => i.kind === 'burn').map((i) => i.tokenId)\n\n const keys = [\n ...mutationEffects.openPosition({\n chainId,\n poolAddress,\n account: context.signerAccount,\n }),\n ...closedTokenIds.flatMap((tokenId) =>\n mutationEffects.closePosition({\n chainId,\n poolAddress,\n account: context.signerAccount,\n tokenId,\n }),\n ),\n ]\n invalidateKeys(queryClient, keys)\n },\n })\n}\n\nexport function useDeployNewPool() {\n const { publicClient, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<DeployNewPoolParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return deployNewPool({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [...queryKeys.all, 'factory'] })\n },\n })\n}\n\nexport function useSwapExactOut(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPoolAndChain<SwapExactOutParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return swapExactOut({ client: publicClient, ...wallet, poolAddress, chainId, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) return\n invalidateKeys(\n queryClient,\n mutationEffects.deposit({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useSupply(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPoolAndChain<SupplyParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return supply({ client: publicClient, ...wallet, poolAddress, chainId, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) return\n invalidateKeys(\n queryClient,\n mutationEffects.deposit({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useUnsupply(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPoolAndChain<UnsupplyParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return unsupply({ client: publicClient, ...wallet, poolAddress, chainId, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) return\n invalidateKeys(\n queryClient,\n mutationEffects.withdraw({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useBorrow(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPoolAndChain<BorrowParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return borrow({ client: publicClient, ...wallet, poolAddress, chainId, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) return\n invalidateKeys(\n queryClient,\n mutationEffects.openPosition({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useRepay(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPoolAndChain<RepayParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return repay({ client: publicClient, ...wallet, poolAddress, chainId, ...params })\n },\n onSuccess: (_data, params, context) => {\n if (!context) return\n invalidateKeys(\n queryClient,\n mutationEffects.closePosition({\n chainId,\n poolAddress,\n account: context.signerAccount,\n tokenId: params.loanTokenId,\n }),\n )\n },\n })\n}\n\nexport function useSmartRepay(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPoolAndChain<SmartRepayParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return smartRepay({ client: publicClient, ...wallet, poolAddress, chainId, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) return\n invalidateKeys(\n queryClient,\n mutationEffects.closePosition({\n chainId,\n poolAddress,\n account: context.signerAccount,\n }),\n )\n },\n })\n}\n\nexport function useSwapExactIn(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPoolAndChain<SwapExactInParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return swapExactIn({ client: publicClient, ...wallet, poolAddress, chainId, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) return\n invalidateKeys(\n queryClient,\n mutationEffects.deposit({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n","/**\n * Dispatch simulation for the Panoptic v2 SDK.\n * @module v2/simulations/simulateDispatch\n */\n\nimport type { Address, Hex, PublicClient } from 'viem'\nimport { decodeFunctionResult, encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError } from '../errors'\nimport type { DispatchSimulation, SimulationResult, TokenFlow } from '../types'\nimport type { TickAndSpreadLimits } from '../writes/position'\nimport { decodeLeftRightUnsigned } from '../writes/utils'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\n/**\n * Parameters for simulating dispatch.\n */\nexport interface SimulateDispatchParams {\n /** Public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /**\n * Operation list passed to `dispatch()` — one tokenId per batch item, in\n * operation order. Mints reference NEW tokenIds the user doesn't yet own,\n * so this list is NOT safe to read against pre-dispatch storage.\n */\n positionIdList: bigint[]\n /** Final position ID list after operations */\n finalPositionIdList: bigint[]\n /**\n * The user's actual on-chain `positionIdList` BEFORE dispatch. Required to\n * populate `preMarginExcess0/1` (read via a pre-dispatch\n * `getFullPositionsData` chained in the same multicall). When omitted,\n * `preMarginExcess0/1` are returned as `null`.\n */\n existingPositionIdList?: bigint[]\n /** Position sizes for each operation */\n positionSizes: bigint[]\n /** Tick and spread limits for each operation */\n tickAndSpreadLimits: TickAndSpreadLimits[]\n /** Whether to use premia as collateral */\n usePremiaAsCollateral?: boolean\n /** Builder code */\n builderCode?: bigint\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate a raw dispatch operation.\n *\n * Uses PanopticPool.multicall with getAssetsOf-dispatch-getAssetsOf pattern\n * to measure exact collateral asset movements.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with dispatch data or error\n */\nexport async function simulateDispatch(\n params: SimulateDispatchParams,\n): Promise<SimulationResult<DispatchSimulation>> {\n const {\n client,\n poolAddress,\n account,\n positionIdList,\n finalPositionIdList,\n positionSizes,\n tickAndSpreadLimits,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n blockNumber,\n existingPositionIdList,\n } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n try {\n // Encode dispatch call data\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n positionSizes,\n tickAndSpreadLimits.map(\n (t) => [Number(t[0]), Number(t[1]), Number(t[2])] as readonly [number, number, number],\n ),\n usePremiaAsCollateral,\n builderCode,\n ],\n })\n\n // Encode getFullPositionsData against the pre-dispatch (caller-supplied\n // existing list) and post-dispatch (finalPositionIdList) position lists.\n // Running both in the same multicall — pre-call before dispatch, post-call\n // after — lets the simulation report margin excess (= assets - required\n // collateral) on both sides atomically. Required collateral is summed\n // across the per-position LeftRightUnsigned entries.\n //\n // The pre-call uses `existingPositionIdList` (the user's actual storage\n // list), NOT `positionIdList` (the operation list, which contains\n // not-yet-minted tokenIds and would revert with PositionNotOwned).\n const preFullPositionsCallData =\n existingPositionIdList !== undefined\n ? encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, existingPositionIdList],\n })\n : undefined\n const postFullPositionsCallData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, finalPositionIdList],\n })\n\n // Simulate with token flow measurement using PanopticPool.multicall + getAssetsOf\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account,\n callData,\n blockNumber: targetBlockNumber,\n preCallData: preFullPositionsCallData ? [preFullPositionsCallData] : undefined,\n postCallData: [postFullPositionsCallData],\n })\n\n if (!flowResult.success || !flowResult.tokenFlow) {\n throw (\n flowResult.rawError ?? new PanopticError(flowResult.error || 'Token flow simulation failed')\n )\n }\n\n const tokenFlow: TokenFlow = flowResult.tokenFlow\n\n // Determine which positions were created/closed by diffing the post-dispatch\n // list against the pre-dispatch on-chain snapshot. `positionIdList` is the\n // operation list (which contains not-yet-minted tokenIds and excludes\n // unaffected pre-existing ones), so it can't be used as the \"before\" set.\n const preSnapshot = existingPositionIdList ?? []\n const positionsCreated = finalPositionIdList.filter((id) => !preSnapshot.includes(id))\n const positionsClosed = preSnapshot.filter((id) => !finalPositionIdList.includes(id))\n\n // Sum collateralRequirements across all entries from one\n // getFullPositionsData multicall slot. Each entry is a LeftRightUnsigned\n // packed as right=token0, left=token1. Returns null on decode failure so\n // callers fall back gracefully (the type is bigint | null).\n const sumCollateralReq = (data: Hex | undefined): { token0: bigint; token1: bigint } | null => {\n if (!data) return null\n try {\n const decoded = decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n data,\n })\n const reqs = decoded[3] // collateralRequirements\n let token0 = 0n\n let token1 = 0n\n for (const packed of reqs) {\n const r = decodeLeftRightUnsigned(packed)\n token0 += r.right\n token1 += r.left\n }\n return { token0, token1 }\n } catch {\n return null\n }\n }\n\n const preReq = sumCollateralReq(flowResult.preCallResults?.[0])\n const postReq = sumCollateralReq(flowResult.postCallResults?.[0])\n\n const _meta = await metaPromise\n\n // Build simulation result with actual token flow data\n const data: DispatchSimulation = {\n netAmount0: tokenFlow.delta0,\n netAmount1: tokenFlow.delta1,\n positionsCreated,\n positionsClosed,\n postCollateral0: tokenFlow.balanceAfter0,\n postCollateral1: tokenFlow.balanceAfter1,\n preMarginExcess0: preReq ? tokenFlow.balanceBefore0 - preReq.token0 : null,\n preMarginExcess1: preReq ? tokenFlow.balanceBefore1 - preReq.token1 : null,\n postMarginExcess0: postReq ? tokenFlow.balanceAfter0 - postReq.token0 : null,\n postMarginExcess1: postReq ? tokenFlow.balanceAfter1 - postReq.token1 : null,\n }\n\n return {\n success: true,\n data,\n gasEstimate: flowResult.gasEstimate,\n tokenFlow,\n _meta,\n }\n } catch (error) {\n const _meta = await metaPromise\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Simulation failed',\n error instanceof Error ? error : undefined,\n ),\n _meta,\n }\n }\n}\n","/**\n * Item-based wrapper around simulateDispatch for batched mint/burn ops.\n * @module v2/simulations/simulateBatchDispatch\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { buildBatchDispatchArgs } from '../batch/build'\nimport type { BatchDiagnostic, BatchOp } from '../batch/types'\nimport { getBlockMeta } from '../clients'\nimport type { BlockMeta, DispatchSimulation, SimulationResult } from '../types'\nimport { simulateDispatch } from './simulateDispatch'\n\n/**\n * Parameters for `simulateBatchDispatch`.\n *\n * - `client`: viem PublicClient used for read calls.\n * - `poolAddress`: PanopticPool address the batch targets.\n * - `account`: account whose collateral and positions are simulated against.\n * - `items`: ordered batch ops (mints + burns) — order matters because dispatch\n * applies them sequentially.\n * - `existingPositionIds`: account's current on-chain `positionIdList`. Must\n * reflect FRESH on-chain state (not a cached/optimistic snapshot) — stale\n * data here yields incorrect pre-dispatch margin excess and false\n * burn-not-found diagnostics.\n * - `usePremiaAsCollateral`: applied across the whole dispatch. Defaults to\n * `false`.\n * - `builderCode`: applied across the whole dispatch. Defaults to `0n`.\n * - `blockNumber`: optional pinned block; defaults to the client's latest.\n */\nexport interface SimulateBatchDispatchParams {\n client: PublicClient\n poolAddress: Address\n account: Address\n /** Batch ops in operation order. */\n items: BatchOp[]\n /** Current on-chain positionIdList for the account (fresh). */\n existingPositionIds: bigint[]\n /** Apply across the whole dispatch. Defaults to false. */\n usePremiaAsCollateral?: boolean\n /** Apply across the whole dispatch. Defaults to 0n. */\n builderCode?: bigint\n /** Optional pinned block. */\n blockNumber?: bigint\n}\n\n/**\n * Result returned by `simulateBatchDispatch`.\n *\n * Either delegates to `simulateDispatch` (and therefore matches its\n * `SimulationResult<DispatchSimulation>` shape), or short-circuits with\n * batch-level diagnostics when the items fail validation. In either case the\n * shape includes a `diagnostics` field so callers can render conflicts before\n * deciding what to do — UIs typically gray out the Execute button when\n * `diagnostics.length > 0`.\n */\nexport type SimulateBatchDispatchResult =\n | (SimulationResult<DispatchSimulation> & { diagnostics: BatchDiagnostic[] })\n | { success: false; diagnostics: BatchDiagnostic[]; _meta: BlockMeta }\n\n/**\n * Simulate a batch dispatch built from `items` + the current on-chain\n * positionIdList. Returns batch diagnostics OR a real simulation result.\n */\nexport async function simulateBatchDispatch(\n params: SimulateBatchDispatchParams,\n): Promise<SimulateBatchDispatchResult> {\n const {\n client,\n poolAddress,\n account,\n items,\n existingPositionIds,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n blockNumber,\n } = params\n\n const { args, diagnostics } = buildBatchDispatchArgs({\n items,\n existingPositionIds,\n usePremiaAsCollateral,\n builderCode,\n })\n\n if (args === null) {\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const meta = await getBlockMeta({ client, blockNumber: targetBlockNumber })\n return { success: false, diagnostics, _meta: meta }\n }\n\n const sim = await simulateDispatch({\n client,\n poolAddress,\n account,\n positionIdList: args.positionIdList,\n finalPositionIdList: args.finalPositionIdList,\n existingPositionIdList: existingPositionIds,\n positionSizes: args.positionSizes,\n tickAndSpreadLimits: args.tickAndSpreadLimits,\n usePremiaAsCollateral: args.usePremiaAsCollateral,\n builderCode: args.builderCode,\n blockNumber,\n })\n\n return { ...sim, diagnostics: [] }\n}\n","/**\n * Close position simulation for the Panoptic v2 SDK.\n * @module v2/simulations/simulateClosePosition\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError } from '../errors'\nimport type { ClosePositionSimulation, SimulationResult } from '../types'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\n/**\n * Parameters for simulating position closing.\n */\nexport interface SimulateClosePositionParams {\n /** Public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** Current position ID list */\n positionIdList: bigint[]\n /** TokenId of position to close */\n tokenId: bigint\n /** Position size to close */\n positionSize: bigint\n /**\n * Lower tick limit (always <= tickLimitHigh).\n * Use MIN_TICK (-887272n) to allow any downward price movement.\n */\n tickLimitLow: bigint\n /**\n * Upper tick limit (always >= tickLimitLow).\n * Use MAX_TICK (887272n) to allow any upward price movement.\n */\n tickLimitHigh: bigint\n /** Spread limit tick (use 0n for no spread limit) */\n spreadLimit?: bigint\n /**\n * Whether to swap tokens at burn to achieve single-sided exposure.\n * When true, tickLimits are passed to dispatch in descending order (high, low).\n * When false (default), tickLimits are passed in ascending order (low, high).\n */\n swapAtMint?: boolean\n /** Whether to use premia as collateral */\n usePremiaAsCollateral?: boolean\n /** Builder code */\n builderCode?: bigint\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate closing a position.\n *\n * Uses PanopticPool.multicall with getAssetsOf-dispatch-getAssetsOf pattern\n * to measure exact collateral asset movements from the burn.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with close data or error\n */\nexport async function simulateClosePosition(\n params: SimulateClosePositionParams,\n): Promise<SimulationResult<ClosePositionSimulation>> {\n const {\n client,\n poolAddress,\n account,\n positionIdList,\n tokenId,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit = 0n,\n swapAtMint = false,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n blockNumber,\n } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n // Build tick limits based on swapAtMint flag:\n // - swapAtMint=true: descending order (high, low) triggers SFPM swap\n // - swapAtMint=false: ascending order (low, high) no swap\n const tickLimits: readonly [number, number, number] = swapAtMint\n ? [Number(tickLimitHigh), Number(tickLimitLow), Number(spreadLimit)]\n : [Number(tickLimitLow), Number(tickLimitHigh), Number(spreadLimit)]\n\n try {\n // Prepare final position list (without the closed position)\n const finalPositionIdList = positionIdList.filter((id) => id !== tokenId)\n\n // Encode dispatch call data for burn (positionSize = 0 signals close)\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n [tokenId],\n finalPositionIdList,\n [0n],\n [tickLimits],\n usePremiaAsCollateral,\n builderCode,\n ],\n })\n\n // Simulate with token flow measurement using PanopticPool.multicall + getAssetsOf\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account,\n callData,\n blockNumber: targetBlockNumber,\n })\n\n if (!flowResult.success || !flowResult.tokenFlow) {\n throw (\n flowResult.rawError ?? new PanopticError(flowResult.error || 'Token flow simulation failed')\n )\n }\n\n const tokenFlow = flowResult.tokenFlow\n const _meta = await metaPromise\n\n // Map token flow to simulation fields:\n // Positive delta = user receives collateral back\n const data: ClosePositionSimulation = {\n amount0Received: tokenFlow.delta0,\n amount1Received: tokenFlow.delta1,\n premiaCollected0: null, // Requires pre-close premia snapshot\n premiaCollected1: null,\n postCollateral0: tokenFlow.balanceAfter0,\n postCollateral1: tokenFlow.balanceAfter1,\n realizedPnL0: null, // Requires open position cost basis\n realizedPnL1: null,\n }\n\n return {\n success: true,\n data,\n gasEstimate: flowResult.gasEstimate,\n tokenFlow,\n _meta,\n }\n } catch (error) {\n const _meta = await metaPromise\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Simulation failed',\n error instanceof Error ? error : undefined,\n ),\n _meta,\n }\n }\n}\n","/**\n * Force exercise simulation for the Panoptic v2 SDK.\n * @module v2/simulations/simulateForceExercise\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError } from '../errors'\nimport type { ForceExerciseSimulation, SimulationResult, TokenFlow } from '../types'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\n/**\n * Parameters for simulating force exercise.\n */\nexport interface SimulateForceExerciseParams {\n /** Public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Exercisor account address */\n account: Address\n /** Account whose position is being exercised */\n user: Address\n /** Position IDs from the exercisor's account */\n positionIdListFrom: bigint[]\n /** Position IDs of the target user */\n positionIdListTo: bigint[]\n /** Final position ID list for the user after exercise */\n positionIdListToFinal: bigint[]\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate a force exercise operation.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with exercise data or error\n */\nexport async function simulateForceExercise(\n params: SimulateForceExerciseParams,\n): Promise<SimulationResult<ForceExerciseSimulation>> {\n const {\n client,\n poolAddress,\n account,\n user,\n positionIdListFrom,\n positionIdListTo,\n positionIdListToFinal,\n blockNumber,\n } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n // Default token flow for failure cases\n const emptyTokenFlow: TokenFlow = {\n delta0: 0n,\n delta1: 0n,\n balanceBefore0: 0n,\n balanceBefore1: 0n,\n balanceAfter0: 0n,\n balanceAfter1: 0n,\n tickBefore: null,\n tickAfter: null,\n }\n\n try {\n // Encode dispatchFrom call data\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatchFrom',\n args: [positionIdListFrom, user, positionIdListTo, positionIdListToFinal, 0n],\n })\n\n // Simulate with token flow measurement using PanopticPool.multicall + getAssetsOf\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account, // Measure exercisor's collateral change\n callData,\n blockNumber: targetBlockNumber,\n })\n\n if (!flowResult.success || !flowResult.tokenFlow) {\n // Check for specific exercise-related errors\n const errorMessage = flowResult.error || 'Simulation failed'\n const isNotExercisable =\n errorMessage.includes('NoLegsExercisable') || errorMessage.includes('NotALongLeg')\n\n if (isNotExercisable) {\n const _meta = await metaPromise\n const data: ForceExerciseSimulation = {\n exerciseFee0: 0n,\n exerciseFee1: 0n,\n canExercise: false,\n reason: errorMessage.includes('NoLegsExercisable')\n ? 'No legs are exercisable (not ITM)'\n : 'Position does not have a long leg',\n }\n\n return {\n success: true,\n data,\n gasEstimate: 0n,\n tokenFlow: emptyTokenFlow,\n _meta,\n }\n }\n\n throw new PanopticError(errorMessage)\n }\n\n const _meta = await metaPromise\n const tokenFlow: TokenFlow = flowResult.tokenFlow\n\n // Build simulation result with actual token flow data\n // Exercise fee is what the exercisor receives (positive delta)\n const data: ForceExerciseSimulation = {\n exerciseFee0: tokenFlow.delta0,\n exerciseFee1: tokenFlow.delta1,\n canExercise: true,\n }\n\n return {\n success: true,\n data,\n gasEstimate: flowResult.gasEstimate,\n tokenFlow,\n _meta,\n }\n } catch (error) {\n const _meta = await metaPromise\n // If simulation fails, check the reason\n const errorMessage = error instanceof Error ? error.message : 'Simulation failed'\n\n // Check for specific exercise-related errors\n const isNotExercisable =\n errorMessage.includes('NoLegsExercisable') || errorMessage.includes('NotALongLeg')\n\n if (isNotExercisable) {\n const data: ForceExerciseSimulation = {\n exerciseFee0: 0n,\n exerciseFee1: 0n,\n canExercise: false,\n reason: errorMessage.includes('NoLegsExercisable')\n ? 'No legs are exercisable (not ITM)'\n : 'Position does not have a long leg',\n }\n\n return {\n success: true,\n data,\n gasEstimate: 0n,\n tokenFlow: emptyTokenFlow,\n _meta,\n }\n }\n\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(errorMessage, error instanceof Error ? error : undefined),\n _meta,\n }\n }\n}\n","/**\n * Liquidation simulation for the Panoptic v2 SDK.\n * @module v2/simulations/simulateLiquidate\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError } from '../errors'\nimport type { LiquidateSimulation, SimulationResult, TokenFlow } from '../types'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\n/**\n * Parameters for simulating liquidation.\n */\nexport interface SimulateLiquidateParams {\n /** Public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Liquidator account address */\n account: Address\n /** Account being liquidated */\n liquidatee: Address\n /** Position IDs from the liquidator's account */\n positionIdListFrom: bigint[]\n /** Position IDs of the liquidatee */\n positionIdListTo: bigint[]\n /** Final position ID list for the liquidatee after liquidation */\n positionIdListToFinal: bigint[]\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate a liquidation operation.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with liquidation data or error\n */\nexport async function simulateLiquidate(\n params: SimulateLiquidateParams,\n): Promise<SimulationResult<LiquidateSimulation>> {\n const {\n client,\n poolAddress,\n account,\n liquidatee,\n positionIdListFrom,\n positionIdListTo,\n positionIdListToFinal,\n blockNumber,\n } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n // Default token flow for failure cases\n const emptyTokenFlow: TokenFlow = {\n delta0: 0n,\n delta1: 0n,\n balanceBefore0: 0n,\n balanceBefore1: 0n,\n balanceAfter0: 0n,\n balanceAfter1: 0n,\n tickBefore: null,\n tickAfter: null,\n }\n\n try {\n // Encode dispatchFrom call data\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatchFrom',\n args: [positionIdListFrom, liquidatee, positionIdListTo, positionIdListToFinal, 0n],\n })\n\n // Simulate with token flow measurement using PanopticPool.multicall + getAssetsOf\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account, // Measure liquidator's collateral change\n callData,\n blockNumber: targetBlockNumber,\n })\n\n if (!flowResult.success || !flowResult.tokenFlow) {\n // Check if it's a specific error indicating not liquidatable\n const errorMessage = flowResult.error || 'Simulation failed'\n const isNotLiquidatable =\n errorMessage.includes('NotMarginCalled') || errorMessage.includes('AccountInsolvent')\n\n if (isNotLiquidatable) {\n const _meta = await metaPromise\n const data: LiquidateSimulation = {\n bonus0: 0n,\n bonus1: 0n,\n positionsClosed: [],\n isLiquidatable: false,\n shortfall0: 0n,\n shortfall1: 0n,\n }\n return {\n success: true,\n data,\n gasEstimate: 0n,\n tokenFlow: emptyTokenFlow,\n _meta,\n }\n }\n\n throw new PanopticError(errorMessage)\n }\n\n const _meta = await metaPromise\n const tokenFlow: TokenFlow = flowResult.tokenFlow\n\n // Positions that would be closed\n const positionsClosed = positionIdListTo.filter((id) => !positionIdListToFinal.includes(id))\n\n // Build simulation result with actual token flow data\n // Positive delta = liquidator receives bonus\n const data: LiquidateSimulation = {\n bonus0: tokenFlow.delta0 > 0n ? tokenFlow.delta0 : 0n,\n bonus1: tokenFlow.delta1 > 0n ? tokenFlow.delta1 : 0n,\n positionsClosed,\n isLiquidatable: true,\n shortfall0: 0n, // Would need additional calculation\n shortfall1: 0n,\n }\n\n return {\n success: true,\n data,\n gasEstimate: flowResult.gasEstimate,\n tokenFlow,\n _meta,\n }\n } catch (error) {\n const _meta = await metaPromise\n // If simulation fails, the account might not be liquidatable\n const errorMessage = error instanceof Error ? error.message : 'Simulation failed'\n const isNotLiquidatable =\n errorMessage.includes('NotMarginCalled') || errorMessage.includes('AccountInsolvent')\n\n if (isNotLiquidatable) {\n const data: LiquidateSimulation = {\n bonus0: 0n,\n bonus1: 0n,\n positionsClosed: [],\n isLiquidatable: false,\n shortfall0: 0n,\n shortfall1: 0n,\n }\n return {\n success: true,\n data,\n gasEstimate: 0n,\n tokenFlow: emptyTokenFlow,\n _meta,\n }\n }\n\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(errorMessage, error instanceof Error ? error : undefined),\n _meta,\n }\n }\n}\n","/**\n * Settle simulation for the Panoptic v2 SDK.\n * @module v2/simulations/simulateSettle\n */\n\nimport type { Address, Hex, PublicClient } from 'viem'\nimport { decodeFunctionResult, encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError } from '../errors'\nimport type { SettleSimulation, SimulationResult, TokenFlow } from '../types'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\n/** BIT_MASK_128 = (1n << 128n) - 1n */\nconst BIT_MASK_128 = (1n << 128n) - 1n\n\n/**\n * PanopticPool multicall ABI (inherited from Uniswap).\n */\nconst multicallAbi = [\n {\n type: 'function',\n name: 'multicall',\n inputs: [{ name: 'data', type: 'bytes[]' }],\n outputs: [{ name: 'results', type: 'bytes[]' }],\n stateMutability: 'nonpayable',\n },\n] as const\n\n/**\n * Parameters for simulating premium settlement.\n */\nexport interface SimulateSettleParams {\n /** Public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** Current position ID list */\n positionIdList: bigint[]\n /** Optional tokenId to compute forfeit amounts for */\n tokenId?: bigint\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate premium settlement.\n *\n * When `tokenId` is provided, the simulation also computes forfeit amounts\n * by chaining the dispatch with `getFullPositionsData` reads\n * in a single multicall.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with settlement data or error\n */\nexport async function simulateSettle(\n params: SimulateSettleParams,\n): Promise<SimulationResult<SettleSimulation>> {\n const { client, poolAddress, account, positionIdList, tokenId, blockNumber } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n try {\n // For settlement, we call dispatch with unchanged position lists\n const positionSizes = positionIdList.map(() => 0n)\n const tickAndSpreadLimits = positionIdList.map(() => [-887272n, 887272n, 0n] as const)\n\n // Encode dispatch call data\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n positionIdList,\n positionSizes.map((s) => BigInt(s) as unknown as bigint & { readonly __uint128: true }),\n tickAndSpreadLimits.map(\n (t) => [Number(t[0]), Number(t[1]), Number(t[2])] as readonly [number, number, number],\n ),\n false,\n 0n,\n ],\n })\n\n // Simulate with token flow measurement using PanopticPool.multicall + getAssetsOf\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account,\n callData,\n blockNumber: targetBlockNumber,\n })\n\n if (!flowResult.success || !flowResult.tokenFlow) {\n throw (\n flowResult.rawError ?? new PanopticError(flowResult.error || 'Token flow simulation failed')\n )\n }\n\n const tokenFlow: TokenFlow = flowResult.tokenFlow\n\n // Compute forfeit amounts if tokenId is provided\n let forfeitAmounts: [bigint, bigint] | undefined\n if (tokenId !== undefined) {\n forfeitAmounts = await computeForfeitAmounts({\n client,\n poolAddress,\n account,\n positionIdList,\n tokenId,\n dispatchCallData: callData,\n blockNumber: targetBlockNumber,\n })\n }\n\n const _meta = await metaPromise\n\n // Build simulation result with actual token flow data\n // Positive delta = premia received\n const data: SettleSimulation = {\n premiaReceived0: tokenFlow.delta0 > 0n ? tokenFlow.delta0 : 0n,\n premiaReceived1: tokenFlow.delta1 > 0n ? tokenFlow.delta1 : 0n,\n postCollateral0: tokenFlow.balanceAfter0,\n postCollateral1: tokenFlow.balanceAfter1,\n forfeitAmounts,\n }\n\n return {\n success: true,\n data,\n gasEstimate: flowResult.gasEstimate,\n tokenFlow,\n _meta,\n }\n } catch (error) {\n const _meta = await metaPromise\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Simulation failed',\n error instanceof Error ? error : undefined,\n ),\n _meta,\n }\n }\n}\n\n/**\n * Compute forfeit amounts by chaining dispatch + getFullPositionsData\n * in a single PanopticPool.multicall.\n */\nasync function computeForfeitAmounts(params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n positionIdList: bigint[]\n tokenId: bigint\n dispatchCallData: Hex\n blockNumber: bigint\n}): Promise<[bigint, bigint]> {\n const { client, poolAddress, account, tokenId, dispatchCallData, blockNumber } = params\n\n // Encode getFullPositionsData calls (available = false, total = true)\n const feesCallAvailable = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, [tokenId]],\n })\n const feesCallTotal = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, true, [tokenId]],\n })\n\n try {\n // Chain: dispatch (settle) + fees(available) + fees(total) in one multicall\n const { result } = await client.simulateContract({\n address: poolAddress,\n abi: multicallAbi,\n functionName: 'multicall',\n args: [[dispatchCallData, feesCallAvailable, feesCallTotal]],\n account,\n blockNumber,\n })\n\n // Decode the two fee reads (result[0] is dispatch, result[1] and result[2] are fees)\n const decodeFeesResult = (data: Hex): bigint => {\n return decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n data,\n })[0]\n }\n\n const availablePremium = decodeFeesResult(result[1])\n const totalPremium = decodeFeesResult(result[2])\n\n const available0 = availablePremium & BIT_MASK_128\n const available1 = availablePremium >> 128n\n const total0 = totalPremium & BIT_MASK_128\n const total1 = totalPremium >> 128n\n\n return [total0 - available0, total1 - available1]\n } catch (error) {\n throw new PanopticError(\n 'Forfeit amount computation failed',\n error instanceof Error ? error : undefined,\n )\n }\n}\n","/**\n * Vault simulation functions for the Panoptic v2 SDK.\n * @module v2/simulations/simulateVault\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { collateralTrackerV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError } from '../errors'\nimport type { DepositSimulation, SimulationResult, WithdrawSimulation } from '../types'\n\n/**\n * Parameters for simulating deposit.\n */\nexport interface SimulateDepositParams {\n /** Public client */\n client: PublicClient\n /** CollateralTracker address */\n collateralTrackerAddress: Address\n /** Account address */\n account: Address\n /** Assets to deposit */\n assets: bigint\n /** Whether the collateral tracker wraps native ETH (requires sending msg.value) */\n isNativeETH?: boolean\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate a deposit operation.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with deposit data or error\n */\nexport async function simulateDeposit(\n params: SimulateDepositParams,\n): Promise<SimulationResult<DepositSimulation>> {\n const { client, collateralTrackerAddress, account, assets, isNativeETH, blockNumber } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n try {\n // Run multicall (historical block), gas estimate (latest), and block meta in parallel\n const [[currentShares, currentAssets, previewedShares], gasEstimate, _meta] = await Promise.all(\n [\n client.multicall({\n contracts: [\n {\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'balanceOf',\n args: [account],\n },\n {\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n args: [account],\n },\n {\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'previewDeposit',\n args: [assets],\n },\n ],\n blockNumber: targetBlockNumber,\n allowFailure: false,\n }),\n client.estimateContractGas({\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'deposit',\n args: [assets, account],\n account,\n ...(isNativeETH && { value: assets }),\n blockNumber: targetBlockNumber,\n }),\n metaPromise,\n ],\n )\n\n const data: DepositSimulation = {\n sharesMinted: previewedShares,\n postAssets: currentAssets + assets,\n postShares: currentShares + previewedShares,\n }\n\n return {\n success: true,\n data,\n gasEstimate,\n _meta,\n }\n } catch (error) {\n const _meta = await metaPromise\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Simulation failed',\n error instanceof Error ? error : undefined,\n ),\n _meta,\n }\n }\n}\n\n/**\n * Parameters for simulating withdrawal.\n */\nexport interface SimulateWithdrawParams {\n /** Public client */\n client: PublicClient\n /** CollateralTracker address */\n collateralTrackerAddress: Address\n /** Account address */\n account: Address\n /** Assets to withdraw */\n assets: bigint\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate a withdrawal operation.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with withdrawal data or error\n */\nexport async function simulateWithdraw(\n params: SimulateWithdrawParams,\n): Promise<SimulationResult<WithdrawSimulation>> {\n const { client, collateralTrackerAddress, account, assets, blockNumber } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n try {\n // Get current state\n const [currentShares, currentAssets, maxWithdrawable, previewedShares] = await client.multicall(\n {\n contracts: [\n {\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'balanceOf',\n args: [account],\n },\n {\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n args: [account],\n },\n {\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'maxWithdraw',\n args: [account],\n },\n {\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'previewWithdraw',\n args: [assets],\n },\n ],\n blockNumber: targetBlockNumber,\n allowFailure: false,\n },\n )\n\n // Check if withdrawal is possible\n const canWithdraw = assets <= maxWithdrawable\n\n const _meta = await metaPromise\n\n if (!canWithdraw) {\n const data: WithdrawSimulation = {\n sharesBurned: 0n,\n assetsReceived: 0n,\n postAssets: currentAssets,\n postShares: currentShares,\n canWithdraw: false,\n reason: `Requested ${assets}, but max withdrawable is ${maxWithdrawable}`,\n }\n\n return {\n success: true,\n data,\n gasEstimate: 0n,\n _meta,\n }\n }\n\n const gasEstimate = await client.estimateContractGas({\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'withdraw',\n args: [assets, account, account],\n account,\n blockNumber: targetBlockNumber,\n })\n\n const data: WithdrawSimulation = {\n sharesBurned: previewedShares,\n assetsReceived: assets,\n postAssets: currentAssets - assets,\n postShares: currentShares - previewedShares,\n canWithdraw: true,\n }\n\n return {\n success: true,\n data,\n gasEstimate,\n _meta,\n }\n } catch (error) {\n const _meta = await metaPromise\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Simulation failed',\n error instanceof Error ? error : undefined,\n ),\n _meta,\n }\n }\n}\n","/**\n * SFPM simulation functions for the Panoptic v2 SDK.\n *\n * These simulate `mintTokenizedPosition` and `burnTokenizedPosition` on the\n * SemiFungiblePositionManager, called with `account: poolAddress` (the pool\n * is the caller in the actual protocol flow).\n *\n * @module v2/simulations/sfpm\n */\n\nimport type { Address, Hex, PublicClient } from 'viem'\nimport { encodeAbiParameters } from 'viem'\n\nimport { semiFungiblePositionManagerV4Abi } from '../../../generated'\nimport type { PoolKey } from '../types'\n\n/**\n * Encode a V4 PoolKey struct as bytes for the SFPM.\n */\nexport function encodePoolKeyBytes(poolKey: PoolKey): Hex {\n return encodeAbiParameters(\n [\n {\n type: 'tuple',\n components: [\n { name: 'currency0', type: 'address' },\n { name: 'currency1', type: 'address' },\n { name: 'fee', type: 'uint24' },\n { name: 'tickSpacing', type: 'int24' },\n { name: 'hooks', type: 'address' },\n ],\n },\n ],\n [\n {\n currency0: poolKey.currency0,\n currency1: poolKey.currency1,\n fee: Number(poolKey.fee),\n tickSpacing: Number(poolKey.tickSpacing),\n hooks: poolKey.hooks,\n },\n ],\n )\n}\n\n/**\n * Encode a V3 pool address as poolKey bytes for the V3 SFPM.\n * V3 SFPM expects `abi.encode(uniswapV3PoolAddress)`.\n */\nexport function encodeV3PoolKeyBytes(v3PoolAddress: Address): Hex {\n return encodeAbiParameters([{ type: 'address' }], [v3PoolAddress])\n}\n\n/**\n * Parameters for simulating an SFPM mint or burn.\n */\nexport interface SimulateSFPMParams {\n /** Public client */\n client: PublicClient\n /** SemiFungiblePositionManager address */\n sfpmAddress: Address\n /** PanopticPool address (used as `account` — the pool is the caller) */\n poolAddress: Address\n /** Encoded pool key (bytes) */\n poolKey: Hex\n /** TokenId to mint/burn */\n tokenId: bigint\n /** Position size (uint128) */\n positionSize: bigint\n /** Lower tick limit */\n tickLimitLow: number\n /** Upper tick limit */\n tickLimitHigh: number\n}\n\n/** Return type from SFPM mintTokenizedPosition / burnTokenizedPosition */\nexport type SFPMSimulationResult = readonly [\n readonly [bigint, bigint, bigint, bigint],\n bigint,\n number,\n]\n\n/**\n * Simulate an SFPM mintTokenizedPosition call.\n *\n * @param params - Simulation parameters\n * @returns The result tuple: [collectedAmounts[4], totalSwapped, newTick]\n */\nexport async function simulateSFPMMint(params: SimulateSFPMParams): Promise<SFPMSimulationResult> {\n const {\n client,\n sfpmAddress,\n poolAddress,\n poolKey,\n tokenId,\n positionSize,\n tickLimitLow,\n tickLimitHigh,\n } = params\n\n const { result } = await client.simulateContract({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n functionName: 'mintTokenizedPosition',\n args: [\n poolKey,\n tokenId,\n BigInt(positionSize) as bigint & { readonly __uint128: true },\n tickLimitLow,\n tickLimitHigh,\n ],\n account: poolAddress,\n })\n\n return result\n}\n\n/**\n * Simulate an SFPM burnTokenizedPosition call.\n *\n * @param params - Simulation parameters\n * @returns The result tuple: [collectedAmounts[4], totalSwapped, newTick]\n */\nexport async function simulateSFPMBurn(params: SimulateSFPMParams): Promise<SFPMSimulationResult> {\n const {\n client,\n sfpmAddress,\n poolAddress,\n poolKey,\n tokenId,\n positionSize,\n tickLimitLow,\n tickLimitHigh,\n } = params\n\n const { result } = await client.simulateContract({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n functionName: 'burnTokenizedPosition',\n args: [\n poolKey,\n tokenId,\n BigInt(positionSize) as bigint & { readonly __uint128: true },\n tickLimitLow,\n tickLimitHigh,\n ],\n account: poolAddress,\n })\n\n return result\n}\n","/**\n * Swap simulation for the Panoptic v2 SDK.\n * @module v2/simulations/simulateSwap\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError, SwapTokenMismatchError } from '../errors'\nimport { tickLimits } from '../formatters/tick'\nimport { getPool } from '../reads/pool'\nimport { createTokenIdBuilder } from '../tokenId/builder'\nimport type { SimulationResult, TokenFlow } from '../types'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\n/**\n * Swap simulation data.\n */\nexport interface SwapSimulation {\n /** Amount of tokenIn spent (positive) */\n amountIn: bigint\n /** Amount of tokenOut received (positive) */\n amountOut: bigint\n /** Raw token flow from the simulation */\n tokenFlow: TokenFlow\n}\n\n/**\n * Parameters for simulateSwapExactOut.\n */\nexport interface SimulateSwapExactOutParams {\n /** Public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** Chain ID */\n chainId: bigint\n /** Token address to receive */\n tokenOut: Address\n /** Exact amount of tokenOut */\n amountOut: bigint\n /** Slippage tolerance in bps */\n slippageBps: bigint\n /** Existing position IDs */\n existingPositionIds: bigint[]\n /** Optional block number */\n blockNumber?: bigint\n}\n\n/**\n * Parameters for simulateSwapExactIn.\n */\nexport interface SimulateSwapExactInParams {\n /** Public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** Chain ID */\n chainId: bigint\n /** Token address to sell */\n tokenIn: Address\n /** Exact amount of tokenIn */\n amountIn: bigint\n /** Slippage tolerance in bps */\n slippageBps: bigint\n /** Existing position IDs */\n existingPositionIds: bigint[]\n /** Optional block number */\n blockNumber?: bigint\n}\n\n/**\n * Resolve token index, throwing SwapTokenMismatchError on mismatch.\n */\nfunction resolveTokenIndex(tokenAddress: Address, token0: Address, token1: Address): bigint {\n const lower = tokenAddress.toLowerCase()\n if (lower === token0.toLowerCase()) return 0n\n if (lower === token1.toLowerCase()) return 1n\n throw new SwapTokenMismatchError(tokenAddress, token0, token1)\n}\n\n/**\n * Build a unique loan tokenId.\n */\nfunction buildUniqueLoan(\n poolId: bigint,\n asset: bigint,\n tokenType: bigint,\n currentTick: bigint,\n tickSpacing: bigint,\n existingPositionIds: bigint[],\n): bigint {\n const mod = currentTick % tickSpacing\n let strike = currentTick - ((mod + tickSpacing) % tickSpacing)\n const step = tickSpacing\n const existingSet = new Set(existingPositionIds)\n\n for (let attempt = 0; attempt < 1000; attempt++) {\n const tokenId = createTokenIdBuilder(poolId).addLoan({ asset, tokenType, strike }).build()\n\n if (!existingSet.has(tokenId)) {\n return tokenId\n }\n strike += step\n }\n\n throw new PanopticError('Could not build unique loan tokenId after 1000 attempts')\n}\n\n/**\n * Build dispatch calldata for swap simulation.\n */\nfunction buildSwapCallData(\n loanTokenId: bigint,\n existingPositionIds: bigint[],\n amount: bigint,\n mintTickLimits: readonly [number, number, number],\n burnTickLimits: readonly [number, number, number],\n): `0x${string}` {\n return encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n [loanTokenId, loanTokenId],\n [...existingPositionIds],\n [amount, 0n],\n [mintTickLimits, burnTickLimits],\n false,\n 0n,\n ],\n })\n}\n\n/**\n * Build SwapSimulation from token flow, given which token index is \"out\".\n */\nfunction buildSwapResult(tokenFlow: TokenFlow, tokenOutIndex: bigint): SwapSimulation {\n // delta is negative when user deposits, positive when user receives\n // For a swap: one delta should be negative (spent) and one positive (received)\n const delta0 = tokenFlow.delta0\n const delta1 = tokenFlow.delta1\n\n if (tokenOutIndex === 0n) {\n return {\n amountOut: delta0 > 0n ? delta0 : -delta0,\n amountIn: delta1 < 0n ? -delta1 : delta1,\n tokenFlow,\n }\n } else {\n return {\n amountOut: delta1 > 0n ? delta1 : -delta1,\n amountIn: delta0 < 0n ? -delta0 : delta0,\n tokenFlow,\n }\n }\n}\n\n/**\n * Simulate an exact-output swap.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with swap data or error\n */\nexport async function simulateSwapExactOut(\n params: SimulateSwapExactOutParams,\n): Promise<SimulationResult<SwapSimulation>> {\n const {\n client,\n poolAddress,\n account,\n chainId,\n tokenOut,\n amountOut,\n slippageBps,\n existingPositionIds,\n blockNumber,\n } = params\n\n try {\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n const pool = await getPool({ client, poolAddress, chainId, blockNumber: targetBlockNumber })\n const token0 = pool.collateralTracker0.token\n const token1 = pool.collateralTracker1.token\n const tokenOutIndex = resolveTokenIndex(tokenOut, token0, token1)\n const tokenType = tokenOutIndex === 0n ? 1n : 0n\n\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n\n const loanTokenId = buildUniqueLoan(\n pool.poolId,\n tokenOutIndex,\n tokenType,\n pool.currentTick,\n pool.tickSpacing,\n existingPositionIds,\n )\n\n // Mint: swapAtMint=true (descending), Burn: swapAtMint=false (ascending)\n const mintTickLimits: readonly [number, number, number] = [\n Number(tickLimitHigh),\n Number(tickLimitLow),\n 0,\n ]\n const burnTickLimits: readonly [number, number, number] = [\n Number(tickLimitLow),\n Number(tickLimitHigh),\n 0,\n ]\n\n const callData = buildSwapCallData(\n loanTokenId,\n existingPositionIds,\n amountOut,\n mintTickLimits,\n burnTickLimits,\n )\n\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account,\n callData,\n blockNumber: targetBlockNumber,\n })\n\n if (!flowResult.success || !flowResult.tokenFlow) {\n throw flowResult.rawError ?? new PanopticError(flowResult.error || 'Swap simulation failed')\n }\n\n const _meta = await metaPromise\n const data = buildSwapResult(flowResult.tokenFlow, tokenOutIndex)\n\n return {\n success: true,\n data,\n gasEstimate: flowResult.gasEstimate,\n tokenFlow: flowResult.tokenFlow,\n _meta,\n }\n } catch (error) {\n // Build a fallback _meta if getBlockMeta also failed\n const fallbackMeta = { blockNumber: 0n, blockTimestamp: 0n, blockHash: '0x0' as `0x${string}` }\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Simulation failed',\n error instanceof Error ? error : undefined,\n ),\n _meta: fallbackMeta,\n }\n }\n}\n\n/**\n * Simulate an exact-input swap.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with swap data or error\n */\nexport async function simulateSwapExactIn(\n params: SimulateSwapExactInParams,\n): Promise<SimulationResult<SwapSimulation>> {\n const {\n client,\n poolAddress,\n account,\n chainId,\n tokenIn,\n amountIn,\n slippageBps,\n existingPositionIds,\n blockNumber,\n } = params\n\n try {\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n const pool = await getPool({ client, poolAddress, chainId, blockNumber: targetBlockNumber })\n const token0 = pool.collateralTracker0.token\n const token1 = pool.collateralTracker1.token\n const tokenInIndex = resolveTokenIndex(tokenIn, token0, token1)\n const tokenType = tokenInIndex\n\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n\n const loanTokenId = buildUniqueLoan(\n pool.poolId,\n tokenInIndex,\n tokenType,\n pool.currentTick,\n pool.tickSpacing,\n existingPositionIds,\n )\n\n // Mint: swapAtMint=false (ascending), Burn: swapAtMint=true (descending)\n const mintTickLimits: readonly [number, number, number] = [\n Number(tickLimitLow),\n Number(tickLimitHigh),\n 0,\n ]\n const burnTickLimits: readonly [number, number, number] = [\n Number(tickLimitHigh),\n Number(tickLimitLow),\n 0,\n ]\n\n // tokenOut is the OTHER token\n const tokenOutIndex = tokenInIndex === 0n ? 1n : 0n\n\n const callData = buildSwapCallData(\n loanTokenId,\n existingPositionIds,\n amountIn,\n mintTickLimits,\n burnTickLimits,\n )\n\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account,\n callData,\n blockNumber: targetBlockNumber,\n })\n\n if (!flowResult.success || !flowResult.tokenFlow) {\n throw flowResult.rawError ?? new PanopticError(flowResult.error || 'Swap simulation failed')\n }\n\n const _meta = await metaPromise\n const data = buildSwapResult(flowResult.tokenFlow, tokenOutIndex)\n\n return {\n success: true,\n data,\n gasEstimate: flowResult.gasEstimate,\n tokenFlow: flowResult.tokenFlow,\n _meta,\n }\n } catch (error) {\n const fallbackMeta = { blockNumber: 0n, blockTimestamp: 0n, blockHash: '0x0' as `0x${string}` }\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Simulation failed',\n error instanceof Error ? error : undefined,\n ),\n _meta: fallbackMeta,\n }\n }\n}\n","/**\n * TanStack Query v5 simulation hooks for the Panoptic v2 SDK.\n * @module v2/react/hooks/simulations\n */\n\nimport { useQuery } from '@tanstack/react-query'\nimport type { Address } from 'viem'\n\nimport {\n type SimulateBatchDispatchParams,\n type SimulateClosePositionParams,\n type SimulateDepositParams,\n type SimulateDispatchParams,\n type SimulateForceExerciseParams,\n type SimulateLiquidateParams,\n type SimulateOpenPositionParams,\n type SimulateSettleParams,\n type SimulateSFPMParams,\n type SimulateSwapExactInParams,\n type SimulateSwapExactOutParams,\n type SimulateWithdrawParams,\n simulateBatchDispatch,\n simulateClosePosition,\n simulateDeposit,\n simulateDispatch,\n simulateForceExercise,\n simulateLiquidate,\n simulateOpenPosition,\n simulateSettle,\n simulateSFPMBurn,\n simulateSFPMMint,\n simulateSwapExactIn,\n simulateSwapExactOut,\n simulateWithdraw,\n} from '../../simulations'\nimport { getClientCacheScopeKey } from '../cacheScopes'\nimport { usePanopticContext } from '../provider'\nimport { queryKeys } from '../queryKeys'\n\ntype OmitClient<T> = Omit<T, 'client'>\ntype OmitClientAndPool<T> = Omit<T, 'client' | 'poolAddress'>\n\nexport function useSimulateOpenPosition(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateOpenPositionParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'openPosition',\n poolAddress,\n params?.tokenId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateOpenPosition({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateClosePosition(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateClosePositionParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'closePosition',\n poolAddress,\n params?.tokenId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateClosePosition({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateDeposit(params?: OmitClient<SimulateDepositParams>) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'deposit',\n params?.collateralTrackerAddress,\n params?.assets?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateDeposit({ client: publicClient, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateWithdraw(params?: OmitClient<SimulateWithdrawParams>) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'withdraw',\n params?.collateralTrackerAddress,\n params?.assets?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateWithdraw({ client: publicClient, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateLiquidate(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateLiquidateParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'liquidate',\n poolAddress,\n params?.liquidatee,\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateLiquidate({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateForceExercise(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateForceExerciseParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'forceExercise',\n poolAddress,\n params?.user,\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateForceExercise({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateSettle(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateSettleParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'settle',\n poolAddress,\n params?.account,\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateSettle({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateBatchDispatch(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateBatchDispatchParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'batchDispatch',\n poolAddress,\n params?.account,\n params?.items?.length,\n JSON.stringify(params?.items?.map((i) => `${i.kind}:${i.tokenId.toString()}`)),\n JSON.stringify(params?.existingPositionIds?.map(String)),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateBatchDispatch({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined && params.items !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateDispatch(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateDispatchParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'dispatch',\n poolAddress,\n JSON.stringify(params?.positionIdList?.map(String)),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateDispatch({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateSFPMMint(params?: OmitClient<SimulateSFPMParams>) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'sfpmMint',\n params?.sfpmAddress,\n params?.tokenId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new Error('params required for simulateSFPMMint')\n return simulateSFPMMint({ client: publicClient, ...params })\n },\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateSFPMBurn(params?: OmitClient<SimulateSFPMParams>) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'sfpmBurn',\n params?.sfpmAddress,\n params?.tokenId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new Error('params required for simulateSFPMBurn')\n return simulateSFPMBurn({ client: publicClient, ...params })\n },\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateSwapExactOut(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateSwapExactOutParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'swapExactOut',\n poolAddress,\n params?.tokenOut,\n params?.amountOut?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateSwapExactOut({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateSwapExactIn(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateSwapExactInParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'swapExactIn',\n poolAddress,\n params?.tokenIn,\n params?.amountIn?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateSwapExactIn({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n","/**\n * TanStack Query v5 hooks for the Uniswap v4 Universal Router swap path.\n *\n * Mirrors the writes/simulations hook ergonomics (usePanopticContext injection,\n * OmitInjected* params, cache invalidation) but targets the generic Uniswap v4\n * router functions in `src/uniswap`.\n *\n * @module v2/react/hooks/uniswapRouter\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { Address, WalletClient } from 'viem'\n\nimport {\n type ApproveErc20ForPermit2Params,\n type ApproveRouterViaPermit2Params,\n type CheckRouterApprovalParams,\n type QuoteSwapExactInViaRouterParams,\n type QuoteSwapExactOutViaRouterParams,\n type SwapExactInViaRouterParams,\n type SwapExactOutViaRouterParams,\n approveErc20ForPermit2,\n approveRouterViaPermit2,\n checkRouterApproval,\n quoteSwapExactInViaRouter,\n quoteSwapExactOutViaRouter,\n swapExactInViaRouter,\n swapExactOutViaRouter,\n} from '../../../../uniswap/v4/router'\nimport { PanopticError } from '../../errors'\nimport { getClientCacheScopeKey } from '../cacheScopes'\nimport { mutationEffects } from '../mutationEffects'\nimport { usePanopticContext } from '../provider'\nimport { queryKeys } from '../queryKeys'\n\ntype OmitInjectedWithPoolAndChain<T> = Omit<\n T,\n 'client' | 'walletClient' | 'account' | 'poolAddress' | 'chainId'\n>\ntype OmitInjectedWithChain<T> = Omit<T, 'client' | 'walletClient' | 'account' | 'chainId'>\ntype OmitClientPoolAndChain<T> = Omit<T, 'client' | 'poolAddress' | 'chainId'>\n\nfunction requireWallet(walletClient?: WalletClient, account?: Address) {\n if (!walletClient || !account) {\n throw new PanopticError(\n 'walletClient and account are required. Provide them via PanopticProvider.',\n )\n }\n return { walletClient, account }\n}\n\n/**\n * Quote an exact-in spot swap via the Universal Router (V4Quoter-backed).\n * Returns a `SimulationResult`, matching `useSimulateSwapExactIn`'s shape.\n */\nexport function useQuoteSwapExactInViaRouter(\n poolAddress: Address,\n params?: OmitClientPoolAndChain<QuoteSwapExactInViaRouterParams>,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // Raw `params` carries bigints that break TanStack v5's JSON key hashing; the\n // stringified scalars below fully capture the query identity.\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'uniswapRouter',\n 'quote',\n chainId,\n poolAddress,\n params?.tokenIn,\n params?.amountIn?.toString(),\n params?.slippageBps?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n ] as const,\n queryFn: () =>\n quoteSwapExactInViaRouter({\n client: publicClient,\n poolAddress,\n chainId,\n ...params!,\n }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\n/**\n * Quote an exact-out spot swap via the Universal Router (V4Quoter-backed).\n * Returns a `SimulationResult` carrying the required input + `amountInMaximum`.\n */\nexport function useQuoteSwapExactOutViaRouter(\n poolAddress: Address,\n params?: OmitClientPoolAndChain<QuoteSwapExactOutViaRouterParams>,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // Raw `params` carries bigints that break TanStack v5's JSON key hashing; the\n // stringified scalars below fully capture the query identity.\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'uniswapRouter',\n 'quoteExactOut',\n chainId,\n poolAddress,\n params?.tokenIn,\n params?.amountOut?.toString(),\n params?.slippageBps?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n ] as const,\n queryFn: () =>\n quoteSwapExactOutViaRouter({\n client: publicClient,\n poolAddress,\n chainId,\n ...params!,\n }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\n/**\n * Check the ERC20 → Permit2 → Universal Router allowance chain.\n */\nexport function useCheckRouterApproval(params?: OmitInjectedWithChain<CheckRouterApprovalParams>) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // Raw `params` carries bigints that break TanStack v5's JSON key hashing; the\n // stringified scalars below fully capture the query identity.\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'uniswapRouter',\n 'approval',\n chainId,\n params?.tokenIn,\n params?.owner,\n params?.amount?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n ] as const,\n queryFn: () => checkRouterApproval({ client: publicClient, chainId, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\n/**\n * Execute an exact-in spot swap via the Universal Router.\n */\nexport function useSwapExactInViaRouter(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: (params: OmitInjectedWithPoolAndChain<SwapExactInViaRouterParams>) => {\n const wallet = requireWallet(walletClient, account)\n return swapExactInViaRouter({\n client: publicClient,\n ...wallet,\n poolAddress,\n chainId,\n ...params,\n })\n },\n onSuccess: () => {\n if (!account) return\n for (const key of mutationEffects.deposit({ chainId, poolAddress, account })) {\n queryClient.invalidateQueries({ queryKey: key })\n }\n },\n })\n}\n\n/**\n * Execute an exact-out spot swap via the Universal Router.\n */\nexport function useSwapExactOutViaRouter(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: (params: OmitInjectedWithPoolAndChain<SwapExactOutViaRouterParams>) => {\n const wallet = requireWallet(walletClient, account)\n return swapExactOutViaRouter({\n client: publicClient,\n ...wallet,\n poolAddress,\n chainId,\n ...params,\n })\n },\n onSuccess: () => {\n if (!account) return\n for (const key of mutationEffects.deposit({ chainId, poolAddress, account })) {\n queryClient.invalidateQueries({ queryKey: key })\n }\n },\n })\n}\n\n/**\n * Step 1 approval mutation: ERC20 → Permit2.\n */\nexport function useApproveErc20ForPermit2() {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n return useMutation({\n mutationFn: (params: OmitInjectedWithChain<ApproveErc20ForPermit2Params>) => {\n const wallet = requireWallet(walletClient, account)\n return approveErc20ForPermit2({ client: publicClient, ...wallet, chainId, ...params })\n },\n })\n}\n\n/**\n * Step 2 approval mutation: Permit2 → Universal Router.\n */\nexport function useApproveRouterViaPermit2() {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n return useMutation({\n mutationFn: (params: OmitInjectedWithChain<ApproveRouterViaPermit2Params>) => {\n const wallet = requireWallet(walletClient, account)\n return approveRouterViaPermit2({ client: publicClient, ...wallet, chainId, ...params })\n },\n })\n}\n","/**\n * TanStack Query v5 hooks for the CoW Protocol swap path.\n *\n * Mirrors the Universal Router hooks (usePanopticContext injection,\n * OmitInjected* params) but targets the order-book functions in `src/cow`.\n * Orders settle asynchronously: submission returns an order UID, and\n * `useCowOrderStatus` polls until the order reaches a terminal state.\n *\n * @module v2/react/hooks/cowSwap\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { Address, Hex, WalletClient } from 'viem'\n\nimport {\n type ApproveErc20ForCowParams,\n type CancelCowOrderParams,\n type CheckCowApprovalParams,\n type QuoteCowSwapParams,\n type SignAndSubmitCowOrderParams,\n approveErc20ForCow,\n cancelCowOrder,\n checkCowApproval,\n getCowOrderStatus,\n isCowSupportedChain,\n quoteCowSwap,\n signAndSubmitCowOrder,\n} from '../../../../cow'\nimport { PanopticError } from '../../errors'\nimport { getClientCacheScopeKey } from '../cacheScopes'\nimport { usePanopticContext } from '../provider'\nimport { queryKeys } from '../queryKeys'\n\ntype OmitChainAndFrom<T> = Omit<T, 'chainId' | 'from'>\ntype OmitInjectedWithChain<T> = Omit<T, 'client' | 'walletClient' | 'account' | 'chainId'>\ntype OmitClientOnly<T> = Omit<T, 'client'>\n\nfunction requireWallet(walletClient?: WalletClient, account?: Address) {\n if (!walletClient || !account) {\n throw new PanopticError(\n 'walletClient and account are required. Provide them via PanopticProvider.',\n )\n }\n return { walletClient, account }\n}\n\n/** How often open-order status is re-polled (ms). */\nconst ORDER_POLL_INTERVAL_MS = 5_000\n/** How often quotes refresh (ms) — CoW quotes go stale quickly. */\nconst QUOTE_REFETCH_INTERVAL_MS = 15_000\n\n/**\n * Placeholder order owner for quotes when no wallet is connected — the order\n * book accepts any non-zero `from` for quoting (verification happens at order\n * submission, which always uses the real account).\n */\nconst QUOTE_STUB_FROM = '0x0000000000000000000000000000000000000001' as const\n\n/**\n * Quote a swap via the CoW order book. The connected account (or a stub when\n * disconnected) is used as the order owner (`from`); disabled while the chain\n * has no order book.\n */\nexport function useQuoteCowSwap(params?: OmitChainAndFrom<QuoteCowSwapParams>) {\n const { publicClient, chainId, account, clientScope } = usePanopticContext()\n return useQuery({\n // Raw `params` carries bigints that break TanStack v5's JSON key hashing; the\n // stringified scalars below fully capture the query identity.\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'cowSwap',\n 'quote',\n chainId,\n params?.sellToken,\n params?.buyToken,\n params?.kind,\n params?.amount?.toString(),\n params?.slippageBps?.toString(),\n account,\n getClientCacheScopeKey(publicClient, clientScope),\n ] as const,\n queryFn: () => quoteCowSwap({ chainId, from: account ?? QUOTE_STUB_FROM, ...params! }),\n enabled: params !== undefined && isCowSupportedChain(chainId),\n staleTime: 0,\n refetchInterval: QUOTE_REFETCH_INTERVAL_MS,\n })\n}\n\n/** Check the ERC20 → GPv2VaultRelayer allowance for the sell token. */\nexport function useCheckCowApproval(params?: OmitClientOnly<CheckCowApprovalParams>) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // Raw `params` carries bigints that break TanStack v5's JSON key hashing; the\n // stringified scalars below fully capture the query identity.\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'cowSwap',\n 'approval',\n chainId,\n params?.sellToken,\n params?.owner,\n params?.amount?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n ] as const,\n queryFn: () => checkCowApproval({ client: publicClient, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\n/** Approval mutation: ERC20 → GPv2VaultRelayer (single step, no Permit2). */\nexport function useApproveErc20ForCow() {\n const { publicClient, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (params: OmitInjectedWithChain<ApproveErc20ForCowParams>) => {\n const wallet = requireWallet(walletClient, account)\n return approveErc20ForCow({ client: publicClient, ...wallet, ...params })\n },\n // Refresh the cached allowance read (useCheckCowApproval) so the swap CTA\n // advances past \"Approve\" once the approval confirms.\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [...queryKeys.all, 'cowSwap', 'approval'] })\n },\n })\n}\n\n/**\n * Sign an order (EIP-712) and post it to the order book. Resolves with the\n * order UID — not a tx hash; settlement is asynchronous.\n */\nexport function useSubmitCowOrder() {\n const { chainId, walletClient, account } = usePanopticContext()\n return useMutation({\n mutationFn: (\n params: Omit<SignAndSubmitCowOrderParams, 'walletClient' | 'account' | 'chainId'>,\n ) => {\n const wallet = requireWallet(walletClient, account)\n return signAndSubmitCowOrder({ ...wallet, chainId, ...params })\n },\n })\n}\n\n/**\n * Poll an order's lifecycle state every few seconds while it is open; polling\n * stops automatically once the order reaches a terminal state.\n */\nexport function useCowOrderStatus(orderUid?: Hex) {\n const { chainId } = usePanopticContext()\n return useQuery({\n queryKey: [...queryKeys.all, 'cowSwap', 'orderStatus', chainId, orderUid] as const,\n queryFn: () => getCowOrderStatus({ chainId, orderUid: orderUid! }),\n enabled: orderUid !== undefined,\n refetchInterval: (query) => {\n const status = query.state.data?.status\n return status === undefined || status === 'open' || status === 'presignaturePending'\n ? ORDER_POLL_INTERVAL_MS\n : false\n },\n })\n}\n\n/** Off-chain (signed, free) order cancellation mutation. */\nexport function useCancelCowOrder() {\n const { chainId, walletClient, account } = usePanopticContext()\n return useMutation({\n mutationFn: (params: Omit<CancelCowOrderParams, 'walletClient' | 'account' | 'chainId'>) => {\n const wallet = requireWallet(walletClient, account)\n return cancelCowOrder({ ...wallet, chainId, ...params })\n },\n })\n}\n\n// Re-export the chain gate so UI code can branch without importing `/cow`.\nexport { isCowSupportedChain }\n","/**\n * TanStack Query v5 sync hooks for the Panoptic v2 SDK.\n * @module v2/react/hooks/sync\n */\n\nimport { useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useState } from 'react'\nimport type { Address, Hash } from 'viem'\n\nimport {\n type PendingPosition,\n type SyncProgressEvent,\n addPendingPosition,\n clearTrackedPositions,\n confirmPendingPosition,\n failPendingPosition,\n syncPositions,\n} from '../../sync'\nimport { usePanopticContext, useRequireStorage } from '../provider'\nimport { queryKeys } from '../queryKeys'\n\n/**\n * Hook for syncing positions with progress tracking.\n */\nexport function useSyncPositions(poolAddress: Address) {\n const { publicClient, chainId } = usePanopticContext()\n const storage = useRequireStorage()\n const account = usePanopticContext().account\n const queryClient = useQueryClient()\n const [progress, setProgress] = useState<SyncProgressEvent | null>(null)\n\n const mutation = useMutation({\n mutationFn: async (params?: { fromBlock?: bigint; toBlock?: bigint }) => {\n if (!account) throw new Error('account is required for sync')\n const result = await syncPositions({\n client: publicClient,\n chainId,\n poolAddress,\n account,\n storage,\n fromBlock: params?.fromBlock,\n toBlock: params?.toBlock,\n onUpdate: setProgress,\n })\n return result\n },\n onSuccess: () => {\n if (!account) return\n queryClient.invalidateQueries({\n queryKey: queryKeys.trackedPositionIds(chainId, poolAddress, account),\n })\n queryClient.invalidateQueries({\n queryKey: queryKeys.syncStatus(chainId, poolAddress, account),\n })\n queryClient.invalidateQueries({\n queryKey: queryKeys.positions(chainId, poolAddress, account),\n })\n queryClient.invalidateQueries({\n queryKey: queryKeys.closedPositions(chainId, poolAddress, account),\n })\n queryClient.invalidateQueries({\n queryKey: queryKeys.tradeHistory(chainId, poolAddress, account),\n })\n },\n })\n\n return { ...mutation, progress }\n}\n\n/**\n * Hook for adding a pending position (optimistic update).\n */\nexport function useAddPendingPosition(poolAddress: Address) {\n const { chainId } = usePanopticContext()\n const storage = useRequireStorage()\n const account = usePanopticContext().account\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: (position: PendingPosition) => {\n if (!account) throw new Error('account is required')\n return addPendingPosition({ chainId, poolAddress, account, storage, position })\n },\n onSuccess: () => {\n if (!account) return\n queryClient.invalidateQueries({\n queryKey: queryKeys.trackedPositionIds(chainId, poolAddress, account),\n })\n },\n })\n}\n\n/**\n * Hook for confirming a pending position.\n */\nexport function useConfirmPendingPosition(poolAddress: Address) {\n const { chainId } = usePanopticContext()\n const storage = useRequireStorage()\n const account = usePanopticContext().account\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: (tokenId: bigint) => {\n if (!account) throw new Error('account is required')\n return confirmPendingPosition({ chainId, poolAddress, account, storage, tokenId })\n },\n onSuccess: () => {\n if (!account) return\n queryClient.invalidateQueries({\n queryKey: queryKeys.trackedPositionIds(chainId, poolAddress, account),\n })\n queryClient.invalidateQueries({\n queryKey: queryKeys.positions(chainId, poolAddress, account),\n })\n },\n })\n}\n\n/**\n * Hook for marking a pending position as failed.\n */\nexport function useFailPendingPosition(poolAddress: Address) {\n const { chainId } = usePanopticContext()\n const storage = useRequireStorage()\n const account = usePanopticContext().account\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: (txHash: Hash) => {\n if (!account) throw new Error('account is required')\n return failPendingPosition({ chainId, poolAddress, account, storage, txHash })\n },\n onSuccess: () => {\n if (!account) return\n queryClient.invalidateQueries({\n queryKey: queryKeys.trackedPositionIds(chainId, poolAddress, account),\n })\n },\n })\n}\n\n/**\n * Hook for clearing all tracked positions.\n */\nexport function useClearTrackedPositions(poolAddress: Address) {\n const { chainId } = usePanopticContext()\n const storage = useRequireStorage()\n const account = usePanopticContext().account\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: () => {\n if (!account) throw new Error('account is required')\n return clearTrackedPositions({ chainId, poolAddress, account, storage })\n },\n onSuccess: () => {\n if (!account) return\n queryClient.invalidateQueries({\n queryKey: queryKeys.trackedPositionIds(chainId, poolAddress, account),\n })\n queryClient.invalidateQueries({\n queryKey: queryKeys.positions(chainId, poolAddress, account),\n })\n },\n })\n}\n","/**\n * Uniswap v4 PoolManager event ABI (subset for event watching).\n * @module abis/poolManager\n */\n\nexport const poolManagerAbi = [\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'id', internalType: 'PoolId', type: 'bytes32', indexed: true },\n { name: 'sender', internalType: 'address', type: 'address', indexed: true },\n { name: 'tickLower', internalType: 'int24', type: 'int24', indexed: false },\n { name: 'tickUpper', internalType: 'int24', type: 'int24', indexed: false },\n { name: 'liquidityDelta', internalType: 'int256', type: 'int256', indexed: false },\n { name: 'salt', internalType: 'bytes32', type: 'bytes32', indexed: false },\n ],\n name: 'ModifyLiquidity',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'id', internalType: 'PoolId', type: 'bytes32', indexed: true },\n { name: 'sender', internalType: 'address', type: 'address', indexed: true },\n { name: 'amount0', internalType: 'int128', type: 'int128', indexed: false },\n { name: 'amount1', internalType: 'int128', type: 'int128', indexed: false },\n { name: 'sqrtPriceX96', internalType: 'uint160', type: 'uint160', indexed: false },\n { name: 'liquidity', internalType: 'uint128', type: 'uint128', indexed: false },\n { name: 'tick', internalType: 'int24', type: 'int24', indexed: false },\n { name: 'fee', internalType: 'uint24', type: 'uint24', indexed: false },\n ],\n name: 'Swap',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'id', internalType: 'PoolId', type: 'bytes32', indexed: true },\n { name: 'sender', internalType: 'address', type: 'address', indexed: true },\n { name: 'amount0', internalType: 'uint256', type: 'uint256', indexed: false },\n { name: 'amount1', internalType: 'uint256', type: 'uint256', indexed: false },\n ],\n name: 'Donate',\n },\n] as const\n","/**\n * Simple WebSocket event watching for the Panoptic v2 SDK.\n * @module v2/events/watchEvents\n */\n\nimport type { Address, Hash, Log, PublicClient } from 'viem'\n\nimport {\n collateralTrackerV2Abi,\n panopticPoolV2Abi,\n riskEngineAbi,\n semiFungiblePositionManagerV4Abi,\n} from '../../../generated'\nimport { poolManagerAbi } from '../abis/poolManager'\nimport type { PanopticEvent, PanopticEventType } from '../types'\nimport { decodeLeftRightSigned, decodePositionBalance } from '../writes/utils'\n\n/**\n * A decoded contract event log that includes both base Log fields and typed args.\n * viem's getContractEvents/watchContractEvent return logs with `.args`,\n * but the generic `Log` type doesn't include it. We use `unknown` for args\n * and narrow to specific types in each parse function's switch cases.\n */\ntype DecodedLog = Log & { args: unknown }\n\n/**\n * Parameters for watching events.\n */\nexport interface WatchEventsParams {\n /** Public client (must have WebSocket transport for real-time watching) */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** CollateralTracker0 address (optional, for Deposit/Withdraw/ProtocolLossRealized events) */\n collateralTracker0?: Address\n /** CollateralTracker1 address (optional, for Deposit/Withdraw/ProtocolLossRealized events) */\n collateralTracker1?: Address\n /** RiskEngine address (optional, for BorrowRateUpdated events) */\n riskEngineAddress?: Address\n /** SemiFungiblePositionManager address (optional, for LiquidityChunkUpdated events) */\n sfpmAddress?: Address\n /** v4 PoolManager address (optional, for ModifyLiquidity/Swap/Donate events) */\n poolManagerAddress?: Address\n /** Event types to filter (omit for all events) */\n eventTypes?: PanopticEventType[]\n /** Callback for received events */\n onLogs: (events: PanopticEvent[]) => void\n /** Callback for errors */\n onError?: (error: Error) => void\n}\n\n/**\n * Event name to ABI event mapping for PanopticPool.\n */\nconst POOL_EVENT_NAMES: Record<string, PanopticEventType> = {\n OptionMinted: 'OptionMinted',\n OptionBurnt: 'OptionBurnt',\n AccountLiquidated: 'AccountLiquidated',\n ForcedExercised: 'ForcedExercised',\n PremiumSettled: 'PremiumSettled',\n}\n\n/**\n * Event name to ABI event mapping for CollateralTracker.\n */\nconst COLLATERAL_EVENT_NAMES: Record<string, PanopticEventType> = {\n Deposit: 'Deposit',\n Withdraw: 'Withdraw',\n ProtocolLossRealized: 'ProtocolLossRealized',\n}\n\n/**\n * Event name to ABI event mapping for RiskEngine.\n */\nconst RISK_ENGINE_EVENT_NAMES: Record<string, PanopticEventType> = {\n BorrowRateUpdated: 'BorrowRateUpdated',\n}\n\n/**\n * Event name to ABI event mapping for SFPM.\n */\nconst SFPM_EVENT_NAMES: Record<string, PanopticEventType> = {\n LiquidityChunkUpdated: 'LiquidityChunkUpdated',\n}\n\n/**\n * Event name to ABI event mapping for v4 PoolManager.\n */\nconst POOL_MANAGER_EVENT_NAMES: Record<string, PanopticEventType> = {\n ModifyLiquidity: 'ModifyLiquidity',\n Swap: 'Swap',\n Donate: 'Donate',\n}\n\n/**\n * Parse a decoded log into a typed PanopticEvent.\n */\nfunction parsePoolLog(log: DecodedLog, eventName: string): PanopticEvent | null {\n const baseEvent = {\n transactionHash: log.transactionHash!,\n blockNumber: log.blockNumber!,\n blockHash: log.blockHash!,\n logIndex: BigInt(log.logIndex!),\n }\n\n // Type narrowing based on event name\n switch (eventName) {\n case 'OptionMinted': {\n const args = log.args as { recipient: Address; tokenId: bigint; balanceData: bigint }\n const balanceData = decodePositionBalance(args.balanceData)\n return {\n type: 'OptionMinted',\n ...baseEvent,\n recipient: args.recipient,\n tokenId: args.tokenId,\n positionSize: balanceData.positionSize,\n poolUtilization0: balanceData.poolUtilization0,\n poolUtilization1: balanceData.poolUtilization1,\n tickAtMint: balanceData.tickAtMint,\n timestampAtMint: balanceData.timestampAtMint,\n blockAtMint: balanceData.blockAtMint,\n swapAtMint: balanceData.swapAtMint,\n }\n }\n\n case 'OptionBurnt': {\n const args = log.args as {\n recipient: Address\n positionSize: bigint\n tokenId: bigint\n premiaByLeg: readonly [bigint, bigint, bigint, bigint]\n }\n return {\n type: 'OptionBurnt',\n ...baseEvent,\n recipient: args.recipient,\n tokenId: args.tokenId,\n positionSize: args.positionSize,\n premiaByLeg: args.premiaByLeg,\n }\n }\n\n case 'AccountLiquidated': {\n const args = log.args as { liquidator: Address; liquidatee: Address; bonusAmounts: bigint }\n const bonus = decodeLeftRightSigned(args.bonusAmounts)\n return {\n type: 'AccountLiquidated',\n ...baseEvent,\n liquidator: args.liquidator,\n liquidatee: args.liquidatee,\n bonusAmount0: bonus.right,\n bonusAmount1: bonus.left,\n }\n }\n\n case 'ForcedExercised': {\n const args = log.args as {\n exercisor: Address\n user: Address\n tokenId: bigint\n exerciseFee: bigint\n }\n const fee = decodeLeftRightSigned(args.exerciseFee)\n return {\n type: 'ForcedExercised',\n ...baseEvent,\n exercisor: args.exercisor,\n user: args.user,\n tokenId: args.tokenId,\n exerciseFee0: fee.right,\n exerciseFee1: fee.left,\n }\n }\n\n case 'PremiumSettled': {\n const args = log.args as {\n user: Address\n tokenId: bigint\n legIndex: bigint\n settledAmounts: bigint\n }\n const settled = decodeLeftRightSigned(args.settledAmounts)\n return {\n type: 'PremiumSettled',\n ...baseEvent,\n user: args.user,\n tokenId: args.tokenId,\n legIndex: args.legIndex,\n settledAmount0: settled.right,\n settledAmount1: settled.left,\n }\n }\n\n default:\n return null\n }\n}\n\n/**\n * Parse a CollateralTracker log into a typed PanopticEvent.\n */\nfunction parseCollateralLog(log: DecodedLog, eventName: string): PanopticEvent | null {\n const baseEvent = {\n transactionHash: log.transactionHash!,\n blockNumber: log.blockNumber!,\n blockHash: log.blockHash!,\n logIndex: BigInt(log.logIndex!),\n }\n\n switch (eventName) {\n case 'Deposit': {\n const args = log.args as { sender: Address; owner: Address; assets: bigint; shares: bigint }\n return {\n type: 'Deposit',\n ...baseEvent,\n sender: args.sender,\n owner: args.owner,\n assets: args.assets,\n shares: args.shares,\n }\n }\n\n case 'Withdraw': {\n const args = log.args as {\n sender: Address\n receiver: Address\n owner: Address\n assets: bigint\n shares: bigint\n }\n return {\n type: 'Withdraw',\n ...baseEvent,\n sender: args.sender,\n receiver: args.receiver,\n owner: args.owner,\n assets: args.assets,\n shares: args.shares,\n }\n }\n\n case 'ProtocolLossRealized': {\n const args = log.args as {\n liquidatee: Address\n liquidator: Address\n protocolLossAssets: bigint\n protocolLossShares: bigint\n }\n return {\n type: 'ProtocolLossRealized',\n ...baseEvent,\n liquidatee: args.liquidatee,\n liquidator: args.liquidator,\n protocolLossAssets: args.protocolLossAssets,\n protocolLossShares: args.protocolLossShares,\n }\n }\n\n default:\n return null\n }\n}\n\n/**\n * Parse a RiskEngine log into a typed PanopticEvent.\n */\nfunction parseRiskEngineLog(log: DecodedLog, eventName: string): PanopticEvent | null {\n const baseEvent = {\n transactionHash: log.transactionHash!,\n blockNumber: log.blockNumber!,\n blockHash: log.blockHash!,\n logIndex: BigInt(log.logIndex!),\n }\n\n switch (eventName) {\n case 'BorrowRateUpdated': {\n const args = log.args as {\n collateralToken: Address\n avgBorrowRate: bigint\n rateAtTarget: bigint\n }\n return {\n type: 'BorrowRateUpdated',\n ...baseEvent,\n collateralToken: args.collateralToken,\n avgBorrowRate: args.avgBorrowRate,\n rateAtTarget: args.rateAtTarget,\n }\n }\n\n default:\n return null\n }\n}\n\n/**\n * Parse an SFPM log into a typed PanopticEvent.\n */\nfunction parseSfpmLog(log: DecodedLog, eventName: string): PanopticEvent | null {\n const baseEvent = {\n transactionHash: log.transactionHash!,\n blockNumber: log.blockNumber!,\n blockHash: log.blockHash!,\n logIndex: BigInt(log.logIndex!),\n }\n\n switch (eventName) {\n case 'LiquidityChunkUpdated': {\n const args = log.args as {\n poolId: Hash\n owner: Address\n tokenType: bigint\n tickLower: number\n tickUpper: number\n liquidityDelta: bigint\n }\n return {\n type: 'LiquidityChunkUpdated',\n ...baseEvent,\n poolId: args.poolId,\n owner: args.owner,\n tokenType: args.tokenType,\n tickLower: args.tickLower,\n tickUpper: args.tickUpper,\n liquidityDelta: args.liquidityDelta,\n }\n }\n\n default:\n return null\n }\n}\n\n/**\n * Parse a v4 PoolManager log into a typed PanopticEvent.\n */\nfunction parsePoolManagerLog(log: DecodedLog, eventName: string): PanopticEvent | null {\n const baseEvent = {\n transactionHash: log.transactionHash!,\n blockNumber: log.blockNumber!,\n blockHash: log.blockHash!,\n logIndex: BigInt(log.logIndex!),\n }\n\n switch (eventName) {\n case 'ModifyLiquidity': {\n const args = log.args as {\n id: Hash\n sender: Address\n tickLower: number\n tickUpper: number\n liquidityDelta: bigint\n salt: Hash\n }\n return {\n type: 'ModifyLiquidity',\n ...baseEvent,\n id: args.id,\n sender: args.sender,\n tickLower: args.tickLower,\n tickUpper: args.tickUpper,\n liquidityDelta: args.liquidityDelta,\n salt: args.salt,\n }\n }\n\n case 'Swap': {\n const args = log.args as {\n id: Hash\n sender: Address\n amount0: bigint\n amount1: bigint\n sqrtPriceX96: bigint\n liquidity: bigint\n tick: number\n fee: number\n }\n return {\n type: 'Swap',\n ...baseEvent,\n id: args.id,\n sender: args.sender,\n amount0: args.amount0,\n amount1: args.amount1,\n sqrtPriceX96: args.sqrtPriceX96,\n liquidity: args.liquidity,\n tick: args.tick,\n fee: args.fee,\n }\n }\n\n case 'Donate': {\n const args = log.args as { id: Hash; sender: Address; amount0: bigint; amount1: bigint }\n return {\n type: 'Donate',\n ...baseEvent,\n id: args.id,\n sender: args.sender,\n amount0: args.amount0,\n amount1: args.amount1,\n }\n }\n\n default:\n return null\n }\n}\n\n/**\n * Watch for Panoptic events in real-time using WebSocket.\n *\n * This is a one-shot watcher - if the WebSocket disconnects, it stops.\n * For production bots that need automatic reconnection, use `createEventSubscription()`.\n *\n * @param params - Watch parameters\n * @returns Unwatch function to stop watching\n *\n * @example\n * ```typescript\n * const unwatch = watchEvents({\n * client,\n * poolAddress,\n * eventTypes: ['OptionMinted', 'OptionBurnt'],\n * onLogs: (events) => {\n * for (const event of events) {\n * console.log(event.type, event)\n * }\n * },\n * onError: (error) => console.error(error),\n * })\n *\n * // Later: stop watching\n * unwatch()\n * ```\n */\nexport function watchEvents(params: WatchEventsParams): () => void {\n const {\n client,\n poolAddress,\n collateralTracker0,\n collateralTracker1,\n riskEngineAddress,\n sfpmAddress,\n poolManagerAddress,\n eventTypes,\n onLogs,\n onError,\n } = params\n\n const unwatchFns: (() => void)[] = []\n\n // Determine which pool events to watch\n const poolEventTypesToWatch = eventTypes\n ? eventTypes.filter((t) => t in POOL_EVENT_NAMES)\n : (Object.keys(POOL_EVENT_NAMES) as PanopticEventType[])\n\n // Watch PanopticPool events\n for (const eventType of poolEventTypesToWatch) {\n try {\n const unwatch = client.watchContractEvent({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n eventName: eventType as\n | 'OptionMinted'\n | 'OptionBurnt'\n | 'AccountLiquidated'\n | 'ForcedExercised'\n | 'PremiumSettled',\n onLogs: (logs) => {\n const events: PanopticEvent[] = []\n for (const log of logs) {\n const parsed = parsePoolLog(log as DecodedLog, eventType)\n if (parsed) {\n events.push(parsed)\n }\n }\n if (events.length > 0) {\n onLogs(events)\n }\n },\n onError: onError,\n })\n unwatchFns.push(unwatch)\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(String(error)))\n }\n }\n\n // Determine which collateral events to watch\n const collateralEventTypesToWatch = eventTypes\n ? eventTypes.filter((t) => t in COLLATERAL_EVENT_NAMES)\n : (Object.keys(COLLATERAL_EVENT_NAMES) as PanopticEventType[])\n\n // Watch CollateralTracker events (if addresses provided)\n const collateralTrackers = [collateralTracker0, collateralTracker1].filter(Boolean) as Address[]\n\n for (const trackerAddress of collateralTrackers) {\n for (const eventType of collateralEventTypesToWatch) {\n try {\n const unwatch = client.watchContractEvent({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n eventName: eventType as 'Deposit' | 'Withdraw' | 'ProtocolLossRealized',\n onLogs: (logs) => {\n const events: PanopticEvent[] = []\n for (const log of logs) {\n const parsed = parseCollateralLog(log as DecodedLog, eventType)\n if (parsed) {\n events.push(parsed)\n }\n }\n if (events.length > 0) {\n onLogs(events)\n }\n },\n onError: onError,\n })\n unwatchFns.push(unwatch)\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(String(error)))\n }\n }\n }\n\n // Watch RiskEngine events (if address provided)\n if (riskEngineAddress) {\n const riskEngineEventTypesToWatch = eventTypes\n ? eventTypes.filter((t) => t in RISK_ENGINE_EVENT_NAMES)\n : (Object.keys(RISK_ENGINE_EVENT_NAMES) as PanopticEventType[])\n\n for (const eventType of riskEngineEventTypesToWatch) {\n try {\n const unwatch = client.watchContractEvent({\n address: riskEngineAddress,\n abi: riskEngineAbi,\n eventName: eventType as 'BorrowRateUpdated',\n onLogs: (logs) => {\n const events: PanopticEvent[] = []\n for (const log of logs) {\n const parsed = parseRiskEngineLog(log as DecodedLog, eventType)\n if (parsed) {\n events.push(parsed)\n }\n }\n if (events.length > 0) {\n onLogs(events)\n }\n },\n onError: onError,\n })\n unwatchFns.push(unwatch)\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(String(error)))\n }\n }\n }\n\n // Watch SFPM events (if address provided)\n if (sfpmAddress) {\n const sfpmEventTypesToWatch = eventTypes\n ? eventTypes.filter((t) => t in SFPM_EVENT_NAMES)\n : (Object.keys(SFPM_EVENT_NAMES) as PanopticEventType[])\n\n for (const eventType of sfpmEventTypesToWatch) {\n try {\n const unwatch = client.watchContractEvent({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n eventName: eventType as 'LiquidityChunkUpdated',\n onLogs: (logs) => {\n const events: PanopticEvent[] = []\n for (const log of logs) {\n const parsed = parseSfpmLog(log as DecodedLog, eventType)\n if (parsed) {\n events.push(parsed)\n }\n }\n if (events.length > 0) {\n onLogs(events)\n }\n },\n onError: onError,\n })\n unwatchFns.push(unwatch)\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(String(error)))\n }\n }\n }\n\n // Watch PoolManager events (if address provided)\n if (poolManagerAddress) {\n const poolManagerEventTypesToWatch = eventTypes\n ? eventTypes.filter((t) => t in POOL_MANAGER_EVENT_NAMES)\n : (Object.keys(POOL_MANAGER_EVENT_NAMES) as PanopticEventType[])\n\n for (const eventType of poolManagerEventTypesToWatch) {\n try {\n const unwatch = client.watchContractEvent({\n address: poolManagerAddress,\n abi: poolManagerAbi,\n eventName: eventType as 'ModifyLiquidity' | 'Swap' | 'Donate',\n onLogs: (logs) => {\n const events: PanopticEvent[] = []\n for (const log of logs) {\n const parsed = parsePoolManagerLog(log as DecodedLog, eventType)\n if (parsed) {\n events.push(parsed)\n }\n }\n if (events.length > 0) {\n onLogs(events)\n }\n },\n onError: onError,\n })\n unwatchFns.push(unwatch)\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(String(error)))\n }\n }\n }\n\n // Return combined unwatch function\n return () => {\n for (const unwatch of unwatchFns) {\n unwatch()\n }\n }\n}\n\nexport type { DecodedLog }\nexport { parseCollateralLog, parsePoolLog, parsePoolManagerLog, parseRiskEngineLog, parseSfpmLog }\n","/**\n * Resilient event subscription with auto-reconnect for the Panoptic v2 SDK.\n * @module v2/events/subscription\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport {\n collateralTrackerV2Abi,\n panopticPoolV2Abi,\n riskEngineAbi,\n semiFungiblePositionManagerV4Abi,\n} from '../../../generated'\nimport { poolManagerAbi } from '../abis/poolManager'\nimport type { EventSubscription, PanopticEvent, PanopticEventType } from '../types'\nimport type { DecodedLog } from './watchEvents'\nimport {\n parseCollateralLog,\n parsePoolLog,\n parsePoolManagerLog,\n parseRiskEngineLog,\n parseSfpmLog,\n} from './watchEvents'\n\n/**\n * Reconnection strategy configuration.\n */\nexport interface ReconnectConfig {\n /** Maximum reconnection attempts (0n = infinite) */\n maxAttempts: bigint\n /** Initial delay before first retry (ms) */\n initialDelayMs: bigint\n /** Maximum delay between retries (ms) */\n maxDelayMs: bigint\n /** Backoff multiplier */\n backoffMultiplier: bigint\n}\n\n/**\n * Default reconnection configuration.\n */\nexport const DEFAULT_RECONNECT_CONFIG: ReconnectConfig = {\n maxAttempts: 10n,\n initialDelayMs: 1000n,\n maxDelayMs: 30000n,\n backoffMultiplier: 2n,\n}\n\n/**\n * Parameters for creating an event subscription.\n */\nexport interface CreateEventSubscriptionParams {\n /** Public client (must have WebSocket transport) */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** CollateralTracker0 address (optional, for Deposit/Withdraw events) */\n collateralTracker0?: Address\n /** CollateralTracker1 address (optional, for Deposit/Withdraw/ProtocolLossRealized events) */\n collateralTracker1?: Address\n /** RiskEngine address (optional, for BorrowRateUpdated events) */\n riskEngineAddress?: Address\n /** SemiFungiblePositionManager address (optional, for LiquidityChunkUpdated events) */\n sfpmAddress?: Address\n /** v4 PoolManager address (optional, for ModifyLiquidity/Swap/Donate events) */\n poolManagerAddress?: Address\n /** Event types to filter (omit for all events) */\n eventTypes?: PanopticEventType[]\n /** Callback for received events */\n onLogs: (events: PanopticEvent[]) => void\n /** Callback for errors (subscription will auto-reconnect) */\n onError?: (error: Error) => void\n /** Callback for reconnection attempts */\n onReconnect?: (attempt: bigint, nextDelayMs: bigint) => void\n /** Callback when connected */\n onConnected?: () => void\n /** Reconnection strategy configuration */\n reconnect?: Partial<ReconnectConfig>\n}\n\n/**\n * Event subscription handle with additional state.\n */\nexport interface EventSubscriptionHandle extends EventSubscription {\n /** Start watching */\n start: () => void\n /** Stop watching (cleans up, no more reconnects) */\n stop: () => void\n /** Number of reconnection attempts */\n reconnectAttempts: bigint\n /** Last processed block number */\n lastProcessedBlock: bigint\n}\n\n/**\n * Create a resilient event subscription with auto-reconnect and gap filling.\n *\n * Unlike `watchEvents()`, this subscription automatically reconnects on\n * disconnection and fills gaps by fetching missed events.\n *\n * @param params - Subscription parameters\n * @returns Event subscription handle\n *\n * @example\n * ```typescript\n * const subscription = createEventSubscription({\n * client,\n * poolAddress,\n * eventTypes: ['OptionMinted', 'OptionBurnt', 'AccountLiquidated'],\n * onLogs: (events) => {\n * for (const event of events) {\n * console.log(event.type, event)\n * }\n * },\n * onError: (error) => console.error('Subscription error:', error),\n * onReconnect: (attempt, nextDelay) => {\n * console.log(`Reconnecting (attempt ${attempt}, next in ${nextDelay}ms)`)\n * },\n * onConnected: () => console.log('Subscription connected'),\n * })\n *\n * // Start watching\n * subscription.start()\n *\n * // Check state\n * console.log('Connected:', subscription.isConnected())\n * console.log('Reconnect attempts:', subscription.reconnectAttempts)\n * console.log('Last processed block:', subscription.lastProcessedBlock)\n *\n * // Stop (cleans up, no more reconnects)\n * subscription.stop()\n * ```\n */\nexport function createEventSubscription(\n params: CreateEventSubscriptionParams,\n): EventSubscriptionHandle {\n const {\n client,\n poolAddress,\n collateralTracker0,\n collateralTracker1,\n riskEngineAddress,\n sfpmAddress,\n poolManagerAddress,\n eventTypes,\n onLogs,\n onError,\n onReconnect,\n onConnected,\n reconnect: reconnectConfig,\n } = params\n\n const config: ReconnectConfig = {\n ...DEFAULT_RECONNECT_CONFIG,\n ...reconnectConfig,\n }\n\n // State\n let isRunning = false\n let connected = false\n let reconnectAttempts = 0n\n let lastProcessedBlock = 0n\n let lastProcessedLogIndex = -1n\n let currentDelay = config.initialDelayMs\n let unwatchFns: (() => void)[] = []\n let reconnectTimeout: ReturnType<typeof setTimeout> | null = null\n\n const compareEvents = (a: PanopticEvent, b: PanopticEvent): number => {\n if (a.blockNumber !== b.blockNumber) {\n return a.blockNumber < b.blockNumber ? -1 : 1\n }\n if (a.logIndex !== b.logIndex) {\n return a.logIndex < b.logIndex ? -1 : 1\n }\n return 0\n }\n\n const isAfterCursor = (event: PanopticEvent): boolean => {\n if (event.blockNumber > lastProcessedBlock) {\n return true\n }\n if (event.blockNumber < lastProcessedBlock) {\n return false\n }\n return event.logIndex > lastProcessedLogIndex\n }\n\n const advanceCursor = (event: PanopticEvent): void => {\n lastProcessedBlock = event.blockNumber\n lastProcessedLogIndex = event.logIndex\n }\n\n // Pool event types\n const poolEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) =>\n [\n 'OptionMinted',\n 'OptionBurnt',\n 'AccountLiquidated',\n 'ForcedExercised',\n 'PremiumSettled',\n ].includes(t),\n )\n : ['OptionMinted', 'OptionBurnt', 'AccountLiquidated', 'ForcedExercised', 'PremiumSettled']\n\n // Collateral event types\n const collateralEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['Deposit', 'Withdraw', 'ProtocolLossRealized'].includes(t))\n : ['Deposit', 'Withdraw', 'ProtocolLossRealized']\n\n // RiskEngine event types\n const riskEngineEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['BorrowRateUpdated'].includes(t))\n : ['BorrowRateUpdated']\n\n // SFPM event types\n const sfpmEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['LiquidityChunkUpdated'].includes(t))\n : ['LiquidityChunkUpdated']\n\n // PoolManager event types\n const poolManagerEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['ModifyLiquidity', 'Swap', 'Donate'].includes(t))\n : ['ModifyLiquidity', 'Swap', 'Donate']\n\n /**\n * Fetch missed events between lastProcessedBlock and currentBlock.\n */\n async function fillGap(fromBlock: bigint, toBlock: bigint): Promise<void> {\n if (fromBlock >= toBlock) return\n\n const allEvents: PanopticEvent[] = []\n\n // Fetch pool events\n for (const eventType of poolEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n eventName: eventType as\n | 'OptionMinted'\n | 'OptionBurnt'\n | 'AccountLiquidated'\n | 'ForcedExercised'\n | 'PremiumSettled',\n fromBlock,\n toBlock,\n })\n for (const log of logs) {\n const parsed = parsePoolLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`))\n }\n }\n\n // Fetch collateral events\n const collateralTrackers = [collateralTracker0, collateralTracker1].filter(Boolean) as Address[]\n for (const trackerAddress of collateralTrackers) {\n for (const eventType of collateralEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n eventName: eventType as 'Deposit' | 'Withdraw' | 'ProtocolLossRealized',\n fromBlock,\n toBlock,\n })\n for (const log of logs) {\n const parsed = parseCollateralLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Fetch RiskEngine events\n if (riskEngineAddress) {\n for (const eventType of riskEngineEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: riskEngineAddress,\n abi: riskEngineAbi,\n eventName: eventType as 'BorrowRateUpdated',\n fromBlock,\n toBlock,\n })\n for (const log of logs) {\n const parsed = parseRiskEngineLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Fetch SFPM events\n if (sfpmAddress) {\n for (const eventType of sfpmEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n eventName: eventType as 'LiquidityChunkUpdated',\n fromBlock,\n toBlock,\n })\n for (const log of logs) {\n const parsed = parseSfpmLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Fetch PoolManager events\n if (poolManagerAddress) {\n for (const eventType of poolManagerEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: poolManagerAddress,\n abi: poolManagerAbi,\n eventName: eventType as 'ModifyLiquidity' | 'Swap' | 'Donate',\n fromBlock,\n toBlock,\n })\n for (const log of logs) {\n const parsed = parsePoolManagerLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Sort by block number and log index, then drop anything at/before cursor.\n const newEvents = allEvents.sort(compareEvents).filter(isAfterCursor)\n\n if (newEvents.length > 0) {\n onLogs(newEvents)\n advanceCursor(newEvents[newEvents.length - 1])\n }\n }\n\n /**\n * Start watching events.\n */\n async function setupWatchers(): Promise<void> {\n // Clean up any existing watchers\n cleanup()\n\n try {\n // Get current block for gap detection\n const currentBlock = await client.getBlockNumber()\n\n // Fill gap if we have a previous position\n if (lastProcessedBlock > 0n && lastProcessedBlock < currentBlock) {\n await fillGap(lastProcessedBlock, currentBlock)\n }\n\n // Set baseline for this subscription start (from \"head\"), unless fillGap\n // already advanced us into this block with a concrete log index.\n if (currentBlock > lastProcessedBlock) {\n lastProcessedBlock = currentBlock\n lastProcessedLogIndex = -1n\n }\n\n const createOnLogsHandler = (\n parseLog: (log: DecodedLog) => PanopticEvent | null,\n ): ((logs: readonly unknown[]) => void) => {\n return (logs) => {\n const events: PanopticEvent[] = []\n for (const log of logs) {\n const parsed = parseLog(log as DecodedLog)\n if (parsed && isAfterCursor(parsed)) {\n events.push(parsed)\n }\n }\n if (events.length > 0) {\n events.sort(compareEvents)\n onLogs(events)\n advanceCursor(events[events.length - 1])\n }\n }\n }\n\n const createPoolOnLogs = (eventType: PanopticEventType) =>\n createOnLogsHandler((log) => parsePoolLog(log, eventType))\n const createCollateralOnLogs = (eventType: PanopticEventType) =>\n createOnLogsHandler((log) => parseCollateralLog(log, eventType))\n const createRiskEngineOnLogs = (eventType: PanopticEventType) =>\n createOnLogsHandler((log) => parseRiskEngineLog(log, eventType))\n const createSfpmOnLogs = (eventType: PanopticEventType) =>\n createOnLogsHandler((log) => parseSfpmLog(log, eventType))\n const createPoolManagerOnLogs = (eventType: PanopticEventType) =>\n createOnLogsHandler((log) => parsePoolManagerLog(log, eventType))\n\n // Watch pool events\n for (const eventType of poolEventTypes) {\n const unwatch = client.watchContractEvent({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n eventName: eventType as\n | 'OptionMinted'\n | 'OptionBurnt'\n | 'AccountLiquidated'\n | 'ForcedExercised'\n | 'PremiumSettled',\n onLogs: createPoolOnLogs(eventType),\n onError: handleError,\n })\n unwatchFns.push(unwatch)\n }\n\n // Watch collateral events\n const collateralTrackers = [collateralTracker0, collateralTracker1].filter(\n Boolean,\n ) as Address[]\n for (const trackerAddress of collateralTrackers) {\n for (const eventType of collateralEventTypes) {\n const unwatch = client.watchContractEvent({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n eventName: eventType as 'Deposit' | 'Withdraw' | 'ProtocolLossRealized',\n onLogs: createCollateralOnLogs(eventType),\n onError: handleError,\n })\n unwatchFns.push(unwatch)\n }\n }\n\n // Watch RiskEngine events\n if (riskEngineAddress) {\n for (const eventType of riskEngineEventTypes) {\n const unwatch = client.watchContractEvent({\n address: riskEngineAddress,\n abi: riskEngineAbi,\n eventName: eventType as 'BorrowRateUpdated',\n onLogs: createRiskEngineOnLogs(eventType),\n onError: handleError,\n })\n unwatchFns.push(unwatch)\n }\n }\n\n // Watch SFPM events\n if (sfpmAddress) {\n for (const eventType of sfpmEventTypes) {\n const unwatch = client.watchContractEvent({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n eventName: eventType as 'LiquidityChunkUpdated',\n onLogs: createSfpmOnLogs(eventType),\n onError: handleError,\n })\n unwatchFns.push(unwatch)\n }\n }\n\n // Watch PoolManager events\n if (poolManagerAddress) {\n for (const eventType of poolManagerEventTypes) {\n const unwatch = client.watchContractEvent({\n address: poolManagerAddress,\n abi: poolManagerAbi,\n eventName: eventType as 'ModifyLiquidity' | 'Swap' | 'Donate',\n onLogs: createPoolManagerOnLogs(eventType),\n onError: handleError,\n })\n unwatchFns.push(unwatch)\n }\n }\n\n // Mark as connected\n connected = true\n reconnectAttempts = 0n\n currentDelay = config.initialDelayMs\n onConnected?.()\n } catch (error) {\n handleError(error instanceof Error ? error : new Error(String(error)))\n }\n }\n\n /**\n * Clean up watchers.\n */\n function cleanup(): void {\n for (const unwatch of unwatchFns) {\n try {\n unwatch()\n } catch {\n // Ignore cleanup errors\n }\n }\n unwatchFns = []\n connected = false\n }\n\n /**\n * Handle errors and schedule reconnection.\n */\n function handleError(error: Error): void {\n connected = false\n onError?.(error)\n\n if (!isRunning) return\n\n // Reconnect already scheduled; avoid duplicate timers.\n if (reconnectTimeout) return\n\n // Check if we've exceeded max attempts\n if (config.maxAttempts > 0n && reconnectAttempts >= config.maxAttempts) {\n onError?.(new Error(`Max reconnection attempts (${config.maxAttempts}) exceeded`))\n return\n }\n\n // Schedule reconnection\n reconnectAttempts++\n onReconnect?.(reconnectAttempts, currentDelay)\n\n reconnectTimeout = setTimeout(() => {\n reconnectTimeout = null\n if (isRunning) {\n setupWatchers()\n }\n }, Number(currentDelay))\n\n // Increase delay for next attempt (exponential backoff)\n currentDelay = currentDelay * config.backoffMultiplier\n if (currentDelay > config.maxDelayMs) {\n currentDelay = config.maxDelayMs\n }\n }\n\n /**\n * Start the subscription.\n */\n function start(): void {\n if (isRunning) return\n isRunning = true\n setupWatchers()\n }\n\n /**\n * Stop the subscription.\n */\n function stop(): void {\n isRunning = false\n if (reconnectTimeout) {\n clearTimeout(reconnectTimeout)\n }\n reconnectTimeout = null\n cleanup()\n }\n\n return {\n start,\n stop,\n unsubscribe: stop,\n isConnected: () => connected,\n get reconnectAttempts() {\n return reconnectAttempts\n },\n get lastProcessedBlock() {\n return lastProcessedBlock\n },\n }\n}\n","/**\n * HTTP polling-based event fetching for the Panoptic v2 SDK.\n * @module v2/events/poller\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport {\n collateralTrackerV2Abi,\n panopticPoolV2Abi,\n riskEngineAbi,\n semiFungiblePositionManagerV4Abi,\n} from '../../../generated'\nimport { poolManagerAbi } from '../abis/poolManager'\nimport type { PanopticEvent, PanopticEventType } from '../types'\nimport type { DecodedLog } from './watchEvents'\nimport {\n parseCollateralLog,\n parsePoolLog,\n parsePoolManagerLog,\n parseRiskEngineLog,\n parseSfpmLog,\n} from './watchEvents'\n\n/**\n * Event poller handle.\n */\nexport interface EventPoller {\n /** Start polling */\n start: () => void\n /** Stop polling */\n stop: () => void\n /** Check if polling is active */\n isPolling: () => boolean\n /** Get last polled block */\n lastPolledBlock: bigint\n}\n\n/**\n * Parameters for creating an event poller.\n */\nexport interface CreateEventPollerParams {\n /** Public client (works with HTTP transport) */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** CollateralTracker0 address (optional, for Deposit/Withdraw events) */\n collateralTracker0?: Address\n /** CollateralTracker1 address (optional, for Deposit/Withdraw/ProtocolLossRealized events) */\n collateralTracker1?: Address\n /** RiskEngine address (optional, for BorrowRateUpdated events) */\n riskEngineAddress?: Address\n /** SemiFungiblePositionManager address (optional, for LiquidityChunkUpdated events) */\n sfpmAddress?: Address\n /** v4 PoolManager address (optional, for ModifyLiquidity/Swap/Donate events) */\n poolManagerAddress?: Address\n /** Event types to filter (omit for all events) */\n eventTypes?: PanopticEventType[]\n /** Callback for received events */\n onLogs: (events: PanopticEvent[]) => void\n /** Callback for errors */\n onError?: (error: Error) => void\n /** Polling interval in milliseconds (default: 12000 = 1 block on mainnet) */\n intervalMs?: bigint\n /** Maximum blocks to query per poll (default: 1000) */\n maxBlockRange?: bigint\n /** Starting block number (default: current block) */\n fromBlock?: bigint\n}\n\n/**\n * Default polling interval (12 seconds = ~1 mainnet block).\n */\nconst DEFAULT_INTERVAL_MS = 12000n\n\n/**\n * Default maximum block range per poll.\n */\nconst DEFAULT_MAX_BLOCK_RANGE = 1000n\n\n/**\n * Create an HTTP polling-based event fetcher.\n *\n * Use this for environments where WebSocket connections are unreliable or unavailable.\n * It polls `eth_getLogs` at regular intervals to fetch new events.\n *\n * @param params - Poller parameters\n * @returns Event poller handle\n *\n * @example\n * ```typescript\n * const poller = createEventPoller({\n * client,\n * poolAddress,\n * onLogs: (events) => {\n * for (const event of events) {\n * console.log(event.type, event)\n * }\n * },\n * onError: (error) => console.error('Polling error:', error),\n * intervalMs: 12000n, // 12 seconds\n * maxBlockRange: 1000n,\n * })\n *\n * // Start polling\n * poller.start()\n *\n * // Check state\n * console.log('Polling:', poller.isPolling())\n * console.log('Last polled block:', poller.lastPolledBlock)\n *\n * // Stop polling\n * poller.stop()\n * ```\n */\nexport function createEventPoller(params: CreateEventPollerParams): EventPoller {\n const {\n client,\n poolAddress,\n collateralTracker0,\n collateralTracker1,\n riskEngineAddress,\n sfpmAddress,\n poolManagerAddress,\n eventTypes,\n onLogs,\n onError,\n intervalMs = DEFAULT_INTERVAL_MS,\n maxBlockRange = DEFAULT_MAX_BLOCK_RANGE,\n fromBlock,\n } = params\n\n // State\n let isRunning = false\n let lastPolledBlock = fromBlock ?? 0n\n let pollTimeout: ReturnType<typeof setTimeout> | null = null\n\n // Pool event types\n const poolEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) =>\n [\n 'OptionMinted',\n 'OptionBurnt',\n 'AccountLiquidated',\n 'ForcedExercised',\n 'PremiumSettled',\n ].includes(t),\n )\n : ['OptionMinted', 'OptionBurnt', 'AccountLiquidated', 'ForcedExercised', 'PremiumSettled']\n\n // Collateral event types\n const collateralEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['Deposit', 'Withdraw', 'ProtocolLossRealized'].includes(t))\n : ['Deposit', 'Withdraw', 'ProtocolLossRealized']\n\n // RiskEngine event types\n const riskEngineEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['BorrowRateUpdated'].includes(t))\n : ['BorrowRateUpdated']\n\n // SFPM event types\n const sfpmEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['LiquidityChunkUpdated'].includes(t))\n : ['LiquidityChunkUpdated']\n\n // PoolManager event types\n const poolManagerEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['ModifyLiquidity', 'Swap', 'Donate'].includes(t))\n : ['ModifyLiquidity', 'Swap', 'Donate']\n\n /**\n * Fetch events for a block range.\n */\n async function fetchEvents(from: bigint, to: bigint): Promise<PanopticEvent[]> {\n const allEvents: PanopticEvent[] = []\n\n // Fetch pool events\n for (const eventType of poolEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n eventName: eventType as\n | 'OptionMinted'\n | 'OptionBurnt'\n | 'AccountLiquidated'\n | 'ForcedExercised'\n | 'PremiumSettled',\n fromBlock: from,\n toBlock: to,\n })\n for (const log of logs) {\n const parsed = parsePoolLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`))\n }\n }\n\n // Fetch collateral events\n const collateralTrackers = [collateralTracker0, collateralTracker1].filter(Boolean) as Address[]\n for (const trackerAddress of collateralTrackers) {\n for (const eventType of collateralEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n eventName: eventType as 'Deposit' | 'Withdraw' | 'ProtocolLossRealized',\n fromBlock: from,\n toBlock: to,\n })\n for (const log of logs) {\n const parsed = parseCollateralLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Fetch RiskEngine events\n if (riskEngineAddress) {\n for (const eventType of riskEngineEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: riskEngineAddress,\n abi: riskEngineAbi,\n eventName: eventType as 'BorrowRateUpdated',\n fromBlock: from,\n toBlock: to,\n })\n for (const log of logs) {\n const parsed = parseRiskEngineLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Fetch SFPM events\n if (sfpmAddress) {\n for (const eventType of sfpmEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n eventName: eventType as 'LiquidityChunkUpdated',\n fromBlock: from,\n toBlock: to,\n })\n for (const log of logs) {\n const parsed = parseSfpmLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Fetch PoolManager events\n if (poolManagerAddress) {\n for (const eventType of poolManagerEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: poolManagerAddress,\n abi: poolManagerAbi,\n eventName: eventType as 'ModifyLiquidity' | 'Swap' | 'Donate',\n fromBlock: from,\n toBlock: to,\n })\n for (const log of logs) {\n const parsed = parsePoolManagerLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Sort by block number and log index\n allEvents.sort((a, b) => {\n if (a.blockNumber !== b.blockNumber) {\n return a.blockNumber < b.blockNumber ? -1 : 1\n }\n return a.logIndex < b.logIndex ? -1 : 1\n })\n\n return allEvents\n }\n\n /**\n * Perform a single poll iteration.\n */\n async function poll(): Promise<void> {\n if (!isRunning) return\n\n try {\n // Get current block\n const currentBlock = await client.getBlockNumber()\n\n // Initialize lastPolledBlock if not set\n if (lastPolledBlock === 0n) {\n lastPolledBlock = currentBlock\n schedulePoll()\n return\n }\n\n // Check if there are new blocks\n if (currentBlock <= lastPolledBlock) {\n schedulePoll()\n return\n }\n\n // Calculate range to query (respect maxBlockRange)\n let toBlock = currentBlock\n const range = toBlock - lastPolledBlock\n if (range > maxBlockRange) {\n toBlock = lastPolledBlock + maxBlockRange\n }\n\n // Fetch events\n const events = await fetchEvents(lastPolledBlock + 1n, toBlock)\n\n // Update last polled block\n lastPolledBlock = toBlock\n\n // Deliver events\n if (events.length > 0) {\n onLogs(events)\n }\n\n // If we didn't catch up to current block, poll again immediately\n if (toBlock < currentBlock && isRunning) {\n // Use setImmediate-like behavior with 0ms timeout\n pollTimeout = setTimeout(poll, 0)\n } else {\n schedulePoll()\n }\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(String(error)))\n schedulePoll()\n }\n }\n\n /**\n * Schedule next poll.\n */\n function schedulePoll(): void {\n if (!isRunning) return\n pollTimeout = setTimeout(poll, Number(intervalMs))\n }\n\n /**\n * Start polling.\n */\n function start(): void {\n if (isRunning) return\n isRunning = true\n poll()\n }\n\n /**\n * Stop polling.\n */\n function stop(): void {\n isRunning = false\n if (pollTimeout) {\n clearTimeout(pollTimeout)\n pollTimeout = null\n }\n }\n\n return {\n start,\n stop,\n isPolling: () => isRunning,\n get lastPolledBlock() {\n return lastPolledBlock\n },\n }\n}\n","/**\n * TanStack Query v5 event hooks for the Panoptic v2 SDK.\n * @module v2/react/hooks/events\n */\n\nimport { useEffect, useRef, useState } from 'react'\nimport type { Address, Hash } from 'viem'\nimport { zeroAddress } from 'viem'\n\nimport { watchEvents } from '../../events'\nimport {\n type EventPoller,\n type EventSubscriptionHandle,\n createEventPoller,\n createEventSubscription,\n} from '../../events'\nimport type { PanopticEvent, PanopticEventType } from '../../types'\nimport { usePanopticContext } from '../provider'\n\n/**\n * Watch events via WebSocket. Returns cleanup automatically on unmount.\n */\nexport function useWatchEvents(\n poolAddress: Address,\n eventTypes: PanopticEventType[] | undefined,\n onEvent: (events: PanopticEvent[]) => void,\n options?: {\n enabled?: boolean\n collateralTracker0?: Address\n collateralTracker1?: Address\n riskEngineAddress?: Address\n sfpmAddress?: Address\n poolManagerAddress?: Address\n onError?: (error: Error) => void\n },\n) {\n const { publicClient } = usePanopticContext()\n const onEventRef = useRef(onEvent)\n onEventRef.current = onEvent\n const onErrorRef = useRef(options?.onError)\n onErrorRef.current = options?.onError\n\n const eventTypesKey = eventTypes?.join(',')\n\n useEffect(() => {\n if (options?.enabled === false) return\n\n const unwatch = watchEvents({\n client: publicClient,\n poolAddress,\n eventTypes,\n collateralTracker0: options?.collateralTracker0,\n collateralTracker1: options?.collateralTracker1,\n riskEngineAddress: options?.riskEngineAddress,\n sfpmAddress: options?.sfpmAddress,\n poolManagerAddress: options?.poolManagerAddress,\n onLogs: (events) => onEventRef.current(events),\n onError: (error) => onErrorRef.current?.(error),\n })\n\n return unwatch\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n publicClient,\n poolAddress,\n options?.enabled,\n options?.collateralTracker0,\n options?.collateralTracker1,\n options?.riskEngineAddress,\n options?.sfpmAddress,\n options?.poolManagerAddress,\n eventTypesKey,\n ])\n}\n\n/**\n * Create a resilient event subscription with auto-reconnect.\n */\nexport function useEventSubscription(\n poolAddress: Address,\n eventTypes: PanopticEventType[] | undefined,\n onEvent: (events: PanopticEvent[]) => void,\n options?: {\n enabled?: boolean\n collateralTracker0?: Address\n collateralTracker1?: Address\n riskEngineAddress?: Address\n sfpmAddress?: Address\n poolManagerAddress?: Address\n onError?: (error: Error) => void\n onReconnect?: (attempt: bigint, nextDelayMs: bigint) => void\n onConnected?: () => void\n },\n) {\n const { publicClient } = usePanopticContext()\n const onEventRef = useRef(onEvent)\n onEventRef.current = onEvent\n const onErrorRef = useRef(options?.onError)\n onErrorRef.current = options?.onError\n const onReconnectRef = useRef(options?.onReconnect)\n onReconnectRef.current = options?.onReconnect\n const onConnectedRef = useRef(options?.onConnected)\n onConnectedRef.current = options?.onConnected\n\n const eventTypesKey = eventTypes?.join(',')\n\n useEffect(() => {\n if (options?.enabled === false) return\n\n const handle: EventSubscriptionHandle = createEventSubscription({\n client: publicClient,\n poolAddress,\n eventTypes,\n collateralTracker0: options?.collateralTracker0,\n collateralTracker1: options?.collateralTracker1,\n riskEngineAddress: options?.riskEngineAddress,\n sfpmAddress: options?.sfpmAddress,\n poolManagerAddress: options?.poolManagerAddress,\n onLogs: (events) => onEventRef.current(events),\n onError: (error) => onErrorRef.current?.(error),\n onReconnect: (attempt, delay) => onReconnectRef.current?.(attempt, delay),\n onConnected: () => onConnectedRef.current?.(),\n })\n\n handle.start()\n return () => handle.stop()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n publicClient,\n poolAddress,\n options?.enabled,\n options?.collateralTracker0,\n options?.collateralTracker1,\n options?.riskEngineAddress,\n options?.sfpmAddress,\n options?.poolManagerAddress,\n eventTypesKey,\n ])\n}\n\n/**\n * Create an HTTP polling event fetcher.\n */\nexport function useEventPoller(\n poolAddress: Address,\n eventTypes: PanopticEventType[] | undefined,\n onEvent: (events: PanopticEvent[]) => void,\n options?: {\n enabled?: boolean\n intervalMs?: bigint\n collateralTracker0?: Address\n collateralTracker1?: Address\n riskEngineAddress?: Address\n sfpmAddress?: Address\n poolManagerAddress?: Address\n onError?: (error: Error) => void\n },\n) {\n const { publicClient } = usePanopticContext()\n const onEventRef = useRef(onEvent)\n onEventRef.current = onEvent\n const onErrorRef = useRef(options?.onError)\n onErrorRef.current = options?.onError\n\n const eventTypesKey = eventTypes?.join(',')\n\n useEffect(() => {\n if (options?.enabled === false) return\n\n const poller: EventPoller = createEventPoller({\n client: publicClient,\n poolAddress,\n eventTypes,\n collateralTracker0: options?.collateralTracker0,\n collateralTracker1: options?.collateralTracker1,\n riskEngineAddress: options?.riskEngineAddress,\n sfpmAddress: options?.sfpmAddress,\n poolManagerAddress: options?.poolManagerAddress,\n intervalMs: options?.intervalMs,\n onLogs: (events) => onEventRef.current(events),\n onError: (error) => onErrorRef.current?.(error),\n })\n\n poller.start()\n return () => poller.stop()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n publicClient,\n poolAddress,\n options?.enabled,\n options?.intervalMs,\n options?.collateralTracker0,\n options?.collateralTracker1,\n options?.riskEngineAddress,\n options?.sfpmAddress,\n options?.poolManagerAddress,\n eventTypesKey,\n ])\n}\n\n/**\n * Confirms a transaction by watching for its corresponding on-chain event.\n *\n * An event log only exists in a confirmed (non-reverted) transaction, so\n * matching on `transactionHash` is sufficient proof of 1-block inclusion.\n * This bypasses the N-block confirmation wait of `useWaitForTransactionReceipt`,\n * making it faster on chains with high confirmation counts (e.g. Base = 150 blocks).\n *\n * Use alongside `useWaitForTransactionReceipt` (confirmations: 1) for revert\n * detection — reverted transactions emit no events.\n *\n * @example\n * ```tsx\n * const confirmation = useTxEventConfirmation({\n * txHash: write.data,\n * poolAddress,\n * eventType: 'OptionMinted',\n * enabled: write.data !== undefined,\n * })\n *\n * useEffect(() => {\n * if (confirmation.isSuccess) onSuccess?.()\n * }, [confirmation.isSuccess])\n * ```\n */\nexport function useTxEventConfirmation({\n txHash,\n poolAddress = zeroAddress,\n collateralTrackerAddress,\n eventType,\n enabled = true,\n intervalMs = 3000n,\n}: {\n /** Transaction hash to confirm. Polling starts when this is defined. */\n txHash: Hash | undefined\n /** PanopticPool address to watch for the event. Optional when watching collateral events only. */\n poolAddress?: Address\n /** CollateralTracker address to watch for Deposit/Withdraw events. */\n collateralTrackerAddress?: Address\n /** The event type expected from this transaction. */\n eventType: PanopticEventType\n /** Set to false to disable polling entirely. Default: true. */\n enabled?: boolean\n /** Polling interval in ms. Default: 3000 (~1 block on L2s). */\n intervalMs?: bigint\n}): {\n /** The matched event, set once the tx is confirmed. */\n data: PanopticEvent | undefined\n /** True while polling and not yet confirmed. */\n isLoading: boolean\n /** True once the matching event has been observed. */\n isSuccess: boolean\n} {\n const { publicClient } = usePanopticContext()\n const [data, setData] = useState<PanopticEvent | undefined>()\n const [isLoading, setIsLoading] = useState(false)\n\n // Refs to avoid stale closures inside the async poller callback\n const txHashRef = useRef(txHash)\n txHashRef.current = txHash\n const confirmedRef = useRef(false)\n const pollerRef = useRef<EventPoller | null>(null)\n\n useEffect(() => {\n // Reset for new tx\n confirmedRef.current = false\n setData(undefined)\n\n if (!txHash || !enabled) {\n pollerRef.current?.stop()\n pollerRef.current = null\n setIsLoading(false)\n return\n }\n\n setIsLoading(true)\n let cancelled = false\n\n // Capture current block before starting so we don't miss an event that\n // lands in the same block as poller initialisation.\n publicClient\n .getBlockNumber()\n .then((currentBlock) => {\n if (cancelled) return\n\n const fromBlock = currentBlock > 0n ? currentBlock - 1n : 0n\n\n const poller = createEventPoller({\n client: publicClient,\n poolAddress,\n collateralTracker0: collateralTrackerAddress,\n eventTypes: [eventType],\n intervalMs,\n fromBlock,\n onLogs: (events) => {\n const hash = txHashRef.current\n if (!hash || confirmedRef.current) return\n const match = events.find((e) => e.transactionHash === hash)\n if (match) {\n confirmedRef.current = true\n pollerRef.current?.stop()\n pollerRef.current = null\n setIsLoading(false)\n setData(match)\n }\n },\n })\n\n pollerRef.current = poller\n poller.start()\n })\n .catch(() => {\n if (cancelled || confirmedRef.current) return\n pollerRef.current?.stop()\n pollerRef.current = null\n setIsLoading(false)\n })\n\n return () => {\n cancelled = true\n pollerRef.current?.stop()\n pollerRef.current = null\n }\n }, [txHash, enabled, publicClient, poolAddress, collateralTrackerAddress, eventType, intervalMs])\n\n return {\n data,\n isLoading: isLoading && data === undefined,\n isSuccess: data !== undefined,\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["params: ResolveBlockNumbersParams","blockNumber: bigint","targetTimestamp: number","low: bigint","high: bigint","params: EstimateBlockNumbersParams","params: MulticallReadParams<TContracts>","results: MulticallResult<unknown>[]","tokenURI: string","startBlock: bigint","endBlock: bigint","points: number","params: GetUniswapV3PoolFromIdParams","params: GetUniswapV4PoolKeyFromIdParams","params: GetEnforcedTickLimitsParams","params: GetChunkLiquiditiesParams","params: GetFactoryTokenURIParams","params: GetFactoryOwnerOfParams","params: GetFactoryConstructMetadataParams","params: GetPanopticPoolAddressParams","params: MinePoolAddressParams","result: readonly [bigint, bigint]","params: SimulateDeployNewPoolParams","result","params: GetPanopticPoolFromPoolIdParams","params: ResolvePanopticPoolFromPoolIdParams","err: unknown","value: bigint","byteLength: number","addr: Address","hex: Hex","factory: Address","salt: bigint","addrInt: bigint","deployerAddress: Address","v3Pool: Address","riskEngine: Address","poolKey: PoolKey","params: MinePoolAddressLocalParams","params: GetAccountPremiaParams","_meta","params: GetPositionsWithPremiaParams","positions: PositionWithPremia[]","legs: TokenIdLeg[]","params: EstimateCollateralRequiredParams","effectiveTick: bigint","params: GetMaxPositionSizeParams","positionIds: bigint[]","params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n tokenId: bigint\n existingPositionIds: bigint[]\n low: bigint\n high: bigint\n precisionDivisor: bigint\n swapAtMint: boolean\n}","positionSize: bigint","params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n tokenId: bigint\n existingPositionIds: bigint[]\n positionSize: bigint\n swapAtMint: boolean\n}","tickLimits: readonly [number, number, number]","tickLimits","params: GetRequiredCreditForITMParams","params: GetMaxWithdrawableParams","params: {\n client: PublicClient\n collateralTrackerAddress: Address\n account: Address\n assets: bigint\n positionIdList: bigint[]\n usePremiaAsCollateral: boolean\n}","client: PublicClient","poolAddress: Address","tokenIndex: 0 | 1","providedAddress?: Address","params: ERC4626PreviewParams","params: GetGuardianUnlockStateParams","params: GetSafeModeParams","params: GetPortfolioValueParams","params: CheckCollateralAcrossTicksParams","MIN_TICK","MAX_TICK","dataPoints: CollateralDataPoint[]","params: OptimizeTokenIdRiskPartnersParams","effectiveTick: bigint","params: GetPoolLiquiditiesParams","TEN","formatRatio","numerator: bigint","denominator: bigint","precision: bigint","bps: bigint","util: bigint","percent: string","config: PoolFormatterConfig","tick: bigint","precision: bigint","price: string","amount: bigint","amount: string","TEN","formatRatio","numerator: bigint","denominator: bigint","precision: bigint","chainId: bigint","address: Address","tokenListId: string","token0Symbol: string","token1Symbol: string","feeBps: bigint","numerator: bigint","denominator: bigint","precision: bigint","address: string","timestamp: bigint","locale?: string","options?: Intl.DateTimeFormatOptions","ms: bigint","minutes","seconds: bigint","blockNumber: bigint","gas: bigint","hash: string","value: bigint","tokenId: bigint","poolId: bigint","formatted: string","wei: bigint","params: GetAccountGreeksParams","targetBlock","_meta","positions: AccountGreeksResult['positions']","params: CalculateAccountGreeksPureParams","totalValue: bigint[]","totalDelta: bigint[]","positionResults: AccountGreeksCurveResult['positions']","posValues: bigint[]","posDeltas: bigint[]","posGammas: bigint[]","MIN_TICK","MAX_TICK","Q128","convert0to1","amount: bigint","sqrtPriceX96: bigint","convert1to0","params: GetMarginBufferParams","collateralToken0: Address","collateralToken1: Address","calls: MulticallBlockCall[]","denominatedInToken: 0 | 1","lowerLiquidationTick: bigint | null","upperLiquidationTick: bigint | null","liquidationDistance: bigint | null","params: GetDeltaHedgeParamsInput","currentTick: bigint","tickSpacing: bigint","poolMeta: BlockMeta","primaryAsset: bigint","currentDelta: bigint","hedgeLeg: LegConfig","simulatedTickAfter: bigint | undefined","collateralAddresses: [Address, Address]","blockNumber: bigint","client: Client","e: unknown","client: Client","collateralTrackerAddresses: Address[]","chainId: number","blockNumber?: bigint","amount: bigint","sqrtPriceX96: bigint","params: GetAccountBuyingPowerParams","collateralToken0: Address","collateralToken1: Address","calls: MulticallBlockCall[]","params: GetOpenPositionPreviewParams","params: GetNativeTokenPriceParams","params: GetAccountHistoryParams","trades: AccountTrade[]","params: GetUniswapFeeHistoryParams","_meta","initialFees0: bigint | null","initialFees1: bigint | null","snapshots: UniswapFeeSnapshot[]","client: PublicClient","blockNumbers: (bigint | undefined)[]","legs: StreamiaLeg[]","poolConfig: PoolVersionConfig","blockData: UniswapBlockData","blockNumber: bigint | undefined","uniqueTicks: number[]","poolAddress: Address","stateViewAddress: Address","poolId: `0x${string}`","params: GetStreamiaHistoryParams","_meta","initialUniswapFees0: bigint | null","initialUniswapFees1: bigint | null","snapshots: StreamiaSnapshot[]","params: GetUniswapV3PoolInfoParams","startTick: number","tickSpacing: number","nTicks: bigint","params: GetUniswapV3PoolLiquiditiesParams","poolKey: UniswapV4PoolKey","_params: ResolveUniswapV4PoolKeyParams","params: GetUniswapV4PoolBasicStateParams","client: PublicClient","address: Address","blockNumber?: bigint","params: GetUniswapV4PoolInfoParams","params: GetUniswapV4PoolLiquiditiesParams","params: GetPriceHistoryParams","_meta","snapshots: PriceSnapshot[]","client: PublicClient","blockNumber: bigint | undefined","poolConfig: PoolVersionConfig","tokenId: bigint","callName: string","cause?: unknown","params: GetPositionEnrichmentDataParams","client: PublicClient","queryAddress: Address","positions: PositionInput[]","currentTick: number","blockNumber: bigint | undefined","_meta: BlockMeta","panopticQueryAbi","entries: [string, PositionEnrichmentResult][]","params: GetSyncStatusParams","params: SaveClosedPositionParams","history: ClosedPosition[]","params: GetTradeHistoryParams","params: GetRealizedPnLParams","params: Omit<\n GetTradeHistoryParams,\n 'limit' | 'offset' | 'closureReason' | 'fromBlock' | 'toBlock'\n >","chunk: LiquidityChunkKey","key: string","params: AddTrackedChunksParams","trackedKeys: Set<string>","params: RemoveTrackedChunksParams","params: GetTrackedChunksParams","params: GetChunkSpreadsParams","netLiquidity: bigint","removedLiquidity: bigint","vegoid: bigint","params: ScanChunksParams","chunks: ScannedChunk[]","params: GetPositionChunkDataParams","_meta","positions: PositionChunkData[]","legs: LegChunkData[]","params: AddPendingPositionParams","pending: PendingPosition[]","params: GetPendingPositionsParams","params: ConfirmPendingPositionParams","params: FailPendingPositionParams","currentBlock: bigint","maxAgeBlocks: bigint","params: EventReconstructionParams","mintEvents: MintEvent[]","burnEvents: BurnEvent[]","mint","openPositions: bigint[]","closedPositions: bigint[]","client: PublicClient","poolAddress: Address","foundBlock: bigint | null","scope?: string","client: unknown","storage: unknown","atTick?: bigint","chainId: bigint","poolAddress: Address","tokenId: bigint","account: Address","atTick: bigint","collateralTrackerAddress: Address","positionIdList: bigint[]","totalAssets: bigint","token: Address","owner: Address","spender: Address","tracker: Address","operation: string","amount: bigint","poolAddress: string","timestampsHash: string","rangeHash: string","poolAddress: Address","options?: QueryOptions","tokenIndex: 0 | 1","params: { queryAddress: Address; startTick: bigint; nTicks: bigint }","params: { sfpmAddress: Address }","owner: Address","tokenId: bigint","tokenIds: bigint[]","owner?: Address","account?: Address","queryAddress: Address","options?: QueryOptions & { atTick?: bigint; includePendingPremium?: boolean }","options?: QueryOptions & { atTick?: bigint }","atTicks: bigint[]","amount: bigint","positionSize: bigint","options?: QueryOptions & {\n existingPositionIds?: bigint[]\n swapAtMint?: boolean\n precisionPct?: number\n }","atTick?: bigint","collateralTrackerAddress: Address","positionIdList: bigint[]","totalAssets: bigint","options?: QueryOptions & { client?: PublicClient }","account: Address | undefined","existingPositionIds: bigint[]","tickLimitLow: bigint","tickLimitHigh: bigint","options?: QueryOptions & {\n spreadLimit?: bigint\n swapAtMint?: boolean\n usePremiaAsCollateral?: boolean\n blockNumber?: bigint\n }","params?: OmitFactoryClient<GetPanopticPoolAddressParams>","params?: OmitFactoryClient<GetFactoryTokenURIParams>","params?: OmitFactoryClient<GetFactoryOwnerOfParams>","params: MinePoolAddressLocalParams","params?: OmitFactoryClient<GetFactoryConstructMetadataParams>","params?: OmitMineClient<SimulateDeployNewPoolParams>","timeRange: PriceHistoryTimeRange","client: PublicClient","poolConfig: PoolVersionConfig","panopticPoolAddress: Address","account: Address","legs: StreamiaLeg[]","options?: QueryOptions & {\n includeUniswapFees?: boolean\n settledEvents?: Array<{ blockNumber: bigint; settled0: bigint; settled1: bigint }>\n }","poolAddress: Address | undefined","queryAddress: Address | undefined","args: { startTick: number; nTicks: bigint } | undefined","poolManager: Address | undefined","poolId: `0x${string}` | undefined","args?: { fromBlock?: bigint; chunkSize?: bigint }","stateViewAddress: Address | undefined","poolKey: UniswapV4PoolKey | undefined","args: { tickSpacing: number; startTick: number; nTicks: bigint } | undefined","panopticPoolAddress: Address | undefined","token0Decimals: bigint","token1Decimals: bigint","nativeIsToken0: boolean","params?: {\n account: Address\n token: Address\n amount: bigint\n slippageBps: bigint\n existingPositionIds: bigint[]\n }","builderCode: bigint | undefined","params: MutationEffectParams","keys: (readonly string[])[]","chainId: bigint","token: Address","owner: Address","spender: Address","params: Pick<MutationEffectParams, 'chainId' | 'poolAddress'>","requireWallet","inputs: WalletInputs","queryClient: QueryClient","keysToInvalidate: readonly (readonly string[])[]","params: OmitInjected<ApproveParams>","poolAddress: Address","params: OmitInjectedWithPool<ApprovePoolParams>","params: OmitInjected<DepositParams>","params: OmitInjected<WithdrawParams>","params: OmitInjected<WrapXstockParams>","params: OmitInjected<UnwrapXstockParams>","params: OmitInjected<WrapEthParams>","params: OmitInjected<UnwrapWethParams>","params: OmitInjected<MintParams>","params: OmitInjected<RedeemParams>","params: OmitInjected<WithdrawWithPositionsParams>","params: OmitInjectedWithPool<OpenPositionParams>","params: OmitInjectedWithPool<ClosePositionParams>","params: OmitInjectedWithPool<RollPositionParams>","params: OmitInjectedWithPool<LiquidateParams>","params: Omit<\n ForceExerciseParams,\n 'client' | 'walletClient' | 'account' | 'poolAddress' | 'chainId' | 'storage'\n >","params: OmitInjectedWithPool<SettleParams>","params?: OmitInjectedWithPool<PokeOracleParams>","params: OmitInjectedWithPool<DispatchParams>","params: OmitInjectedWithPool<ExecuteBatchDispatchParams>","params: OmitInjected<DeployNewPoolParams>","params: OmitInjectedWithPoolAndChain<SwapExactOutParams>","params: OmitInjectedWithPoolAndChain<SupplyParams>","params: OmitInjectedWithPoolAndChain<UnsupplyParams>","params: OmitInjectedWithPoolAndChain<BorrowParams>","params: OmitInjectedWithPoolAndChain<RepayParams>","params: OmitInjectedWithPoolAndChain<SmartRepayParams>","params: OmitInjectedWithPoolAndChain<SwapExactInParams>","params: SimulateDispatchParams","tokenFlow: TokenFlow","data: Hex | undefined","data","data: DispatchSimulation","params: SimulateBatchDispatchParams","params: SimulateClosePositionParams","tickLimits: readonly [number, number, number]","tickLimits","data: ClosePositionSimulation","params: SimulateForceExerciseParams","emptyTokenFlow: TokenFlow","_meta","data: ForceExerciseSimulation","tokenFlow: TokenFlow","params: SimulateLiquidateParams","emptyTokenFlow: TokenFlow","_meta","data: LiquidateSimulation","tokenFlow: TokenFlow","params: SimulateSettleParams","tokenFlow: TokenFlow","forfeitAmounts: [bigint, bigint] | undefined","data: SettleSimulation","params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n positionIdList: bigint[]\n tokenId: bigint\n dispatchCallData: Hex\n blockNumber: bigint\n}","data: Hex","params: SimulateDepositParams","data: DepositSimulation","params: SimulateWithdrawParams","data: WithdrawSimulation","poolKey: PoolKey","v3PoolAddress: Address","params: SimulateSFPMParams","resolveTokenIndex","tokenAddress: Address","token0: Address","token1: Address","buildUniqueLoan","poolId: bigint","asset: bigint","tokenType: bigint","currentTick: bigint","tickSpacing: bigint","existingPositionIds: bigint[]","loanTokenId: bigint","amount: bigint","mintTickLimits: readonly [number, number, number]","burnTickLimits: readonly [number, number, number]","tokenFlow: TokenFlow","tokenOutIndex: bigint","params: SimulateSwapExactOutParams","params: SimulateSwapExactInParams","poolAddress: Address","params?: OmitClientAndPool<SimulateOpenPositionParams>","params?: OmitClientAndPool<SimulateClosePositionParams>","params?: OmitClient<SimulateDepositParams>","params?: OmitClient<SimulateWithdrawParams>","params?: OmitClientAndPool<SimulateLiquidateParams>","params?: OmitClientAndPool<SimulateForceExerciseParams>","params?: OmitClientAndPool<SimulateSettleParams>","params?: OmitClientAndPool<SimulateBatchDispatchParams>","params?: OmitClientAndPool<SimulateDispatchParams>","params?: OmitClient<SimulateSFPMParams>","params?: OmitClientAndPool<SimulateSwapExactOutParams>","params?: OmitClientAndPool<SimulateSwapExactInParams>","requireWallet","walletClient?: WalletClient","account?: Address","poolAddress: Address","params?: OmitClientPoolAndChain<QuoteSwapExactInViaRouterParams>","params?: OmitClientPoolAndChain<QuoteSwapExactOutViaRouterParams>","params?: OmitInjectedWithChain<CheckRouterApprovalParams>","params: OmitInjectedWithPoolAndChain<SwapExactInViaRouterParams>","params: OmitInjectedWithPoolAndChain<SwapExactOutViaRouterParams>","params: OmitInjectedWithChain<ApproveErc20ForPermit2Params>","params: OmitInjectedWithChain<ApproveRouterViaPermit2Params>","walletClient?: WalletClient","account?: Address","params?: OmitChainAndFrom<QuoteCowSwapParams>","params?: OmitClientOnly<CheckCowApprovalParams>","params: OmitInjectedWithChain<ApproveErc20ForCowParams>","params: Omit<SignAndSubmitCowOrderParams, 'walletClient' | 'account' | 'chainId'>","orderUid?: Hex","params: Omit<CancelCowOrderParams, 'walletClient' | 'account' | 'chainId'>","poolAddress: Address","params?: { fromBlock?: bigint; toBlock?: bigint }","position: PendingPosition","tokenId: bigint","txHash: Hash","POOL_EVENT_NAMES: Record<string, PanopticEventType>","COLLATERAL_EVENT_NAMES: Record<string, PanopticEventType>","RISK_ENGINE_EVENT_NAMES: Record<string, PanopticEventType>","SFPM_EVENT_NAMES: Record<string, PanopticEventType>","POOL_MANAGER_EVENT_NAMES: Record<string, PanopticEventType>","log: DecodedLog","eventName: string","params: WatchEventsParams","unwatchFns: (() => void)[]","events: PanopticEvent[]","DEFAULT_RECONNECT_CONFIG: ReconnectConfig","params: CreateEventSubscriptionParams","config: ReconnectConfig","unwatchFns: (() => void)[]","reconnectTimeout: ReturnType<typeof setTimeout> | null","a: PanopticEvent","b: PanopticEvent","event: PanopticEvent","poolEventTypes: PanopticEventType[]","collateralEventTypes: PanopticEventType[]","riskEngineEventTypes: PanopticEventType[]","sfpmEventTypes: PanopticEventType[]","poolManagerEventTypes: PanopticEventType[]","fromBlock: bigint","toBlock: bigint","allEvents: PanopticEvent[]","parseLog: (log: DecodedLog) => PanopticEvent | null","events: PanopticEvent[]","eventType: PanopticEventType","error: Error","params: CreateEventPollerParams","pollTimeout: ReturnType<typeof setTimeout> | null","poolEventTypes: PanopticEventType[]","collateralEventTypes: PanopticEventType[]","riskEngineEventTypes: PanopticEventType[]","sfpmEventTypes: PanopticEventType[]","poolManagerEventTypes: PanopticEventType[]","from: bigint","to: bigint","allEvents: PanopticEvent[]","poolAddress: Address","eventTypes: PanopticEventType[] | undefined","onEvent: (events: PanopticEvent[]) => void","options?: {\n enabled?: boolean\n collateralTracker0?: Address\n collateralTracker1?: Address\n riskEngineAddress?: Address\n sfpmAddress?: Address\n poolManagerAddress?: Address\n onError?: (error: Error) => void\n }","options?: {\n enabled?: boolean\n collateralTracker0?: Address\n collateralTracker1?: Address\n riskEngineAddress?: Address\n sfpmAddress?: Address\n poolManagerAddress?: Address\n onError?: (error: Error) => void\n onReconnect?: (attempt: bigint, nextDelayMs: bigint) => void\n onConnected?: () => void\n }","handle: EventSubscriptionHandle","options?: {\n enabled?: boolean\n intervalMs?: bigint\n collateralTracker0?: Address\n collateralTracker1?: Address\n riskEngineAddress?: Address\n sfpmAddress?: Address\n poolManagerAddress?: Address\n onError?: (error: Error) => void\n }","poller: EventPoller"],"sources":["../../../src/panoptic/v2/clients/blocksByTimestamp.ts","../../../src/panoptic/v2/clients/multicall.ts","../../../src/panoptic/v2/utils/factory.ts","../../../src/panoptic/v2/utils/interpolateBlocks.ts","../../../src/panoptic/v2/reads/sfpm.ts","../../../src/panoptic/v2/reads/factory.ts","../../../src/panoptic/v2/reads/minePoolAddressLocal.ts","../../../src/panoptic/v2/reads/premia.ts","../../../src/panoptic/v2/reads/collateralEstimate.ts","../../../src/panoptic/v2/reads/erc4626.ts","../../../src/panoptic/v2/reads/guardian.ts","../../../src/panoptic/v2/reads/safeMode.ts","../../../src/panoptic/v2/reads/queryUtils.ts","../../../src/panoptic/v2/reads/liquidity.ts","../../../src/panoptic/v2/formatters/percentage.ts","../../../src/panoptic/v2/formatters/poolFormatters.ts","../../../src/panoptic/v2/formatters/tokenList.ts","../../../src/panoptic/v2/formatters/display.ts","../../../src/panoptic/v2/reads/accountGreeks.ts","../../../src/panoptic/v2/reads/margin.ts","../../../src/panoptic/v2/reads/hedge.ts","../../../src/panoptic/v2/reads/collateralSharePrice.ts","../../../src/panoptic/v2/reads/collateralTotalAssets.ts","../../../src/panoptic/v2/reads/buyingPower.ts","../../../src/panoptic/v2/reads/openPositionPreview.ts","../../../src/panoptic/v2/reads/nativeTokenPrice.ts","../../../src/panoptic/v2/reads/history.ts","../../../src/panoptic/v2/reads/uniswapFeeHistory.ts","../../../src/panoptic/v2/reads/streamiaHistory.ts","../../../src/panoptic/v2/reads/uniswapPool.ts","../../../src/panoptic/v2/reads/priceHistory.ts","../../../src/panoptic/v2/reads/enrichment.ts","../../../src/panoptic/v2/sync/getSyncStatus.ts","../../../src/panoptic/v2/sync/tradeHistory.ts","../../../src/panoptic/v2/sync/chunkTracking.ts","../../../src/panoptic/v2/sync/pendingPositions.ts","../../../src/panoptic/v2/sync/eventReconstruction.ts","../../../src/panoptic/v2/react/cacheScopes.ts","../../../src/panoptic/v2/react/provider.tsx","../../../src/panoptic/v2/react/queryKeys.ts","../../../src/panoptic/v2/react/hooks/reads.ts","../../../src/panoptic/v2/react/mutationEffects.ts","../../../src/panoptic/v2/react/hooks/writes.ts","../../../src/panoptic/v2/simulations/simulateDispatch.ts","../../../src/panoptic/v2/simulations/simulateBatchDispatch.ts","../../../src/panoptic/v2/simulations/simulateClosePosition.ts","../../../src/panoptic/v2/simulations/simulateForceExercise.ts","../../../src/panoptic/v2/simulations/simulateLiquidate.ts","../../../src/panoptic/v2/simulations/simulateSettle.ts","../../../src/panoptic/v2/simulations/simulateVault.ts","../../../src/panoptic/v2/simulations/sfpm.ts","../../../src/panoptic/v2/simulations/simulateSwap.ts","../../../src/panoptic/v2/react/hooks/simulations.ts","../../../src/panoptic/v2/react/hooks/uniswapRouter.ts","../../../src/panoptic/v2/react/hooks/cowSwap.ts","../../../src/panoptic/v2/react/hooks/sync.ts","../../../src/panoptic/v2/abis/poolManager.ts","../../../src/panoptic/v2/events/watchEvents.ts","../../../src/panoptic/v2/events/subscription.ts","../../../src/panoptic/v2/events/poller.ts","../../../src/panoptic/v2/react/hooks/events.ts"],"sourcesContent":["/**\n * Timestamp-to-block resolution via RPC binary search.\n * No subgraph dependency — uses only eth_getBlockByNumber.\n * @module v2/clients/blocksByTimestamp\n */\n\nimport type { PublicClient } from 'viem'\n\n/**\n * Parameters for resolveBlockNumbers.\n */\nexport interface ResolveBlockNumbersParams {\n /** viem PublicClient */\n client: PublicClient\n /** Array of Unix timestamps (seconds) to resolve to block numbers */\n timestamps: number[]\n}\n\n/**\n * Resolve an array of Unix timestamps to the closest block numbers via RPC binary search.\n *\n * All binary searches run in parallel, sharing an in-flight-deduped block cache\n * so concurrent searches for nearby timestamps avoid redundant RPC calls.\n *\n * @param params - The parameters\n * @returns Array of block numbers in the same order as the input timestamps\n *\n * @example\n * ```typescript\n * const blocks = await resolveBlockNumbers({\n * client,\n * timestamps: [1700000000, 1700003600, 1700007200],\n * })\n * // blocks: [18500000n, 18500300n, 18500600n]\n * ```\n */\nexport async function resolveBlockNumbers(params: ResolveBlockNumbersParams): Promise<bigint[]> {\n const { client, timestamps } = params\n\n if (timestamps.length === 0) return []\n\n const latestBlock = await client.getBlock({ blockTag: 'latest', includeTransactions: false })\n const latestNumber = latestBlock.number\n const latestTimestamp = Number(latestBlock.timestamp)\n\n // Cache + in-flight dedup: avoids redundant RPC calls across parallel searches\n const cache = new Map<bigint, number>()\n cache.set(latestNumber, latestTimestamp)\n cache.set(0n, 0) // genesis is always timestamp 0 (close enough)\n\n const inflight = new Map<bigint, Promise<number>>()\n\n function getTimestamp(blockNumber: bigint): Promise<number> {\n const cached = cache.get(blockNumber)\n if (cached !== undefined) return Promise.resolve(cached)\n\n const existing = inflight.get(blockNumber)\n if (existing) return existing\n\n const promise = client.getBlock({ blockNumber, includeTransactions: false }).then((block) => {\n const ts = Number(block.timestamp)\n cache.set(blockNumber, ts)\n inflight.delete(blockNumber)\n return ts\n })\n inflight.set(blockNumber, promise)\n return promise\n }\n\n /**\n * Binary search for the last block whose timestamp <= targetTimestamp.\n */\n async function searchBlock(targetTimestamp: number, low: bigint, high: bigint): Promise<bigint> {\n // Clamp: if target is beyond latest, return latest\n if (targetTimestamp >= latestTimestamp) return latestNumber\n\n while (high - low > 1n) {\n const mid = (low + high) / 2n\n const midTs = await getTimestamp(mid)\n\n if (midTs <= targetTimestamp) {\n low = mid\n } else {\n high = mid\n }\n }\n\n return low\n }\n\n // Run all binary searches in parallel — shared cache deduplicates common midpoints\n const results = await Promise.all(timestamps.map((ts) => searchBlock(ts, 0n, latestNumber)))\n\n return results\n}\n\n/**\n * Parameters for estimateBlockNumbers.\n */\nexport interface EstimateBlockNumbersParams {\n /** viem PublicClient */\n client: PublicClient\n /** Array of Unix timestamps (seconds) to resolve to block numbers */\n timestamps: number[]\n /**\n * Bootstrap block-time used only to pick the anchor block (seconds).\n * The final estimate uses the *measured* rate between latest and anchor,\n * so this only affects which sample point we draw — not accuracy on the\n * sampled window. Default 12 (Ethereum L1).\n */\n fallbackBlockTimeSec?: number\n}\n\n/**\n * Estimate block numbers for the given Unix timestamps using a 2-RPC linear\n * extrapolation. Trades binary-search accuracy (~25 RPCs) for ~2 RPCs.\n *\n * Suitable for chart-style use cases where the consumer plots tens-to-hundreds\n * of evenly-spaced points and a ±N-block error is invisible. Not suitable when\n * exact block correspondence is required (e.g. event log ranges).\n *\n * Algorithm:\n * 1. Fetch `latest` block.\n * 2. Use `fallbackBlockTimeSec` to estimate an anchor block roughly co-temporal\n * with the *earliest* requested timestamp.\n * 3. Fetch the anchor block.\n * 4. Compute the measured average block time over [anchor, latest].\n * 5. Linearly extrapolate every requested timestamp from `latest`.\n *\n * If the sampled window is degenerate (e.g. anchor too close to latest, or\n * timestamps near genesis), falls back to {@link resolveBlockNumbers}.\n */\nexport async function estimateBlockNumbers(params: EstimateBlockNumbersParams): Promise<bigint[]> {\n const { client, timestamps, fallbackBlockTimeSec = 12 } = params\n\n if (timestamps.length === 0) return []\n\n const latest = await client.getBlock({ blockTag: 'latest', includeTransactions: false })\n const latestNum = latest.number\n const latestTs = Number(latest.timestamp)\n\n const earliest = Math.min(...timestamps)\n const secAgoMax = Math.max(0, latestTs - earliest)\n\n // All requested timestamps are now-or-future\n if (secAgoMax === 0) return timestamps.map(() => latestNum)\n\n const blocksBackEst = BigInt(Math.floor(secAgoMax / fallbackBlockTimeSec))\n const anchorNum = blocksBackEst >= latestNum ? 1n : latestNum - blocksBackEst\n const anchor = await client.getBlock({\n blockNumber: anchorNum,\n includeTransactions: false,\n })\n\n const numDelta = latestNum - anchor.number\n const tsDelta = latestTs - Number(anchor.timestamp)\n\n // Degenerate sample window — fall back to exact resolution.\n if (numDelta <= 0n || tsDelta <= 0) {\n return resolveBlockNumbers({ client, timestamps })\n }\n\n const avgBlockTimeSec = tsDelta / Number(numDelta)\n\n return timestamps.map((ts) => {\n const secAgo = latestTs - ts\n if (secAgo <= 0) return latestNum\n const blocksAgo = BigInt(Math.round(secAgo / avgBlockTimeSec))\n return blocksAgo >= latestNum ? 1n : latestNum - blocksAgo\n })\n}\n","/**\n * Multicall utilities for the Panoptic v2 SDK.\n * Uses viem's built-in multicall for same-block consistency.\n * @module v2/clients/multicall\n */\n\nimport type { Abi, Address, ContractFunctionArgs, ContractFunctionName, PublicClient } from 'viem'\n\nimport type { BlockMeta } from '../types'\nimport { getBlockMeta } from './blockMeta'\n\n/**\n * A contract call to include in a multicall batch.\n */\nexport interface MulticallContract<\n TAbi extends Abi = Abi,\n TFunctionName extends ContractFunctionName<TAbi, 'pure' | 'view'> = ContractFunctionName<\n TAbi,\n 'pure' | 'view'\n >,\n> {\n /** Contract address */\n address: Address\n /** Contract ABI */\n abi: TAbi\n /** Function name to call */\n functionName: TFunctionName\n /** Function arguments */\n args?: ContractFunctionArgs<TAbi, 'pure' | 'view', TFunctionName>\n}\n\n/**\n * Parameters for multicallRead.\n */\nexport interface MulticallReadParams<TContracts extends readonly MulticallContract[]> {\n /** viem PublicClient */\n client: PublicClient\n /** Array of contract calls to batch */\n contracts: TContracts\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Whether to allow failures (default: false) */\n allowFailure?: boolean\n}\n\n/**\n * Result type for a single multicall contract result.\n */\nexport type MulticallResult<T> =\n | { status: 'success'; result: T }\n | { status: 'failure'; error: Error }\n\n/**\n * Perform a batched multicall read with block metadata.\n * All calls are executed at the same block for consistency.\n *\n * @param params - The multicall parameters\n * @returns Results array with block metadata\n */\nexport async function multicallRead<TContracts extends readonly MulticallContract[]>(\n params: MulticallReadParams<TContracts>,\n): Promise<{\n results: MulticallResult<unknown>[]\n _meta: BlockMeta\n}> {\n const { client, contracts, blockNumber, allowFailure = false } = params\n\n // Get the block number to use (latest if not specified)\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n\n // Execute multicall and get block meta in parallel\n const [multicallResults, _meta] = await Promise.all([\n client.multicall({\n contracts: contracts as unknown as Parameters<typeof client.multicall>['0']['contracts'],\n blockNumber: targetBlockNumber,\n allowFailure: true, // Always allow failure internally to handle gracefully\n }),\n getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // Map results to our format\n const results: MulticallResult<unknown>[] = multicallResults.map((result) => {\n if (result.status === 'success') {\n return { status: 'success' as const, result: result.result }\n } else {\n // If allowFailure is false and we have a failure, throw\n if (!allowFailure) {\n throw result.error\n }\n return { status: 'failure' as const, error: result.error }\n }\n })\n\n return { results, _meta }\n}\n","/**\n * Factory utility functions for the Panoptic v2 SDK.\n * @module v2/utils/factory\n */\n\n/**\n * Decoded Panoptic NFT metadata from a base64-encoded token URI.\n */\nexport type PanopticNFTMetadata = {\n name: string\n description: string\n attributes: [\n {\n trait_type: 'Rarity'\n value: string\n },\n {\n trait_type: 'Strategy'\n value: string\n },\n {\n trait_type: 'ChainId'\n value: string\n },\n ]\n image: string\n}\n\n/**\n * Decode a base64-encoded Panoptic NFT token URI into metadata.\n *\n * @param tokenURI - The base64-encoded data URI string\n * @returns Parsed NFT metadata object, or undefined if input is invalid\n */\nexport function decodePanopticTokenURI(tokenURI: string): PanopticNFTMetadata | undefined {\n if (tokenURI === undefined || tokenURI === '') {\n return undefined\n }\n const parts = tokenURI.split('data:application/json;base64,')\n if (parts.length < 2 || parts[1] === '') {\n return undefined\n }\n try {\n const decoded = atob(parts[1])\n return JSON.parse(decoded) as PanopticNFTMetadata\n } catch {\n return undefined\n }\n}\n","/**\n * Evenly-spaced block number interpolation utility.\n * @module v2/utils/interpolateBlocks\n */\n\nimport { InvalidHistoryRangeError } from '../errors/sdk'\n\n/**\n * Generate evenly-spaced block numbers between start and end (pure math, no RPC).\n *\n * @param startBlock - First block in the range\n * @param endBlock - Last block in the range\n * @param points - Number of evenly-spaced data points to generate\n * @returns Array of interpolated block numbers\n *\n * @throws {InvalidHistoryRangeError} if startBlock > endBlock or points < 0\n */\nexport function interpolateBlocks(startBlock: bigint, endBlock: bigint, points: number): bigint[] {\n if (!Number.isFinite(points) || !Number.isSafeInteger(points)) {\n throw new InvalidHistoryRangeError(`points must be a finite safe integer, got ${points}`)\n }\n if (points < 0) {\n throw new InvalidHistoryRangeError(`points must be >= 0, got ${points}`)\n }\n if (startBlock > endBlock) {\n throw new InvalidHistoryRangeError(\n `startBlock (${startBlock}) must be <= endBlock (${endBlock})`,\n )\n }\n if (points === 0) return []\n if (points === 1) return [endBlock]\n const range = endBlock - startBlock\n return Array.from(\n { length: points },\n (_, i) => startBlock + (range * BigInt(i)) / BigInt(points - 1),\n )\n}\n","/**\n * SFPM read functions — poolId resolution, enforced tick limits, chunk liquidity.\n *\n * @module v2/reads/sfpm\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport {\n semiFungiblePositionManagerV3Abi,\n semiFungiblePositionManagerV4Abi,\n} from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { ChunkLimitError } from '../errors'\nimport type { BlockMeta, PoolKey } from '../types'\nimport { MAX_TRACKED_CHUNKS } from '../utils/constants'\n\n// ---------------------------------------------------------------------------\n// getUniswapV3PoolFromId\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for {@link getUniswapV3PoolFromId}.\n */\nexport interface GetUniswapV3PoolFromIdParams {\n /** Public client */\n client: PublicClient\n /** SemiFungiblePositionManagerV3 address */\n sfpmAddress: Address\n /** The SFPM pool identifier (uint64) */\n poolId: bigint\n}\n\n/**\n * Resolve an SFPM poolId to its corresponding Uniswap V3 pool address.\n *\n * Calls `SemiFungiblePositionManagerV3.getUniswapV3PoolFromId(poolId)`.\n */\nexport async function getUniswapV3PoolFromId(\n params: GetUniswapV3PoolFromIdParams,\n): Promise<Address> {\n const { client, sfpmAddress, poolId } = params\n return client.readContract({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV3Abi,\n functionName: 'getUniswapV3PoolFromId',\n args: [poolId],\n })\n}\n\n// ---------------------------------------------------------------------------\n// getUniswapV4PoolKeyFromId\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for {@link getUniswapV4PoolKeyFromId}.\n */\nexport interface GetUniswapV4PoolKeyFromIdParams {\n /** Public client */\n client: PublicClient\n /** SemiFungiblePositionManagerV4 address */\n sfpmAddress: Address\n /** The SFPM pool identifier (uint64) */\n poolId: bigint\n}\n\n/**\n * Resolve an SFPM poolId to its corresponding Uniswap V4 pool key.\n *\n * Calls `SemiFungiblePositionManagerV4.getUniswapV4PoolKeyFromId(poolId)`.\n */\nexport async function getUniswapV4PoolKeyFromId(\n params: GetUniswapV4PoolKeyFromIdParams,\n): Promise<PoolKey> {\n const { client, sfpmAddress, poolId } = params\n const raw = await client.readContract({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n functionName: 'getUniswapV4PoolKeyFromId',\n args: [poolId],\n })\n return {\n currency0: raw.currency0,\n currency1: raw.currency1,\n fee: BigInt(raw.fee),\n tickSpacing: BigInt(raw.tickSpacing),\n hooks: raw.hooks,\n }\n}\n\n// ---------------------------------------------------------------------------\n// getEnforcedTickLimits\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for getEnforcedTickLimits.\n */\nexport interface GetEnforcedTickLimitsParams {\n /** viem PublicClient */\n client: PublicClient\n /** SFPM address (from getPool().metadata.sfpmAddress) */\n sfpmAddress: Address\n /** Encoded pool ID (from getPool().poolId) */\n poolId: bigint\n}\n\n/**\n * Result from getEnforcedTickLimits.\n */\nexport interface EnforcedTickLimits {\n minEnforcedTick: number\n maxEnforcedTick: number\n}\n\n/**\n * Get the enforced tick limits for a pool from the SFPM.\n *\n * @param params - The parameters\n * @returns The min and max enforced ticks\n */\nexport async function getEnforcedTickLimits(\n params: GetEnforcedTickLimitsParams,\n): Promise<EnforcedTickLimits> {\n const { client, sfpmAddress, poolId } = params\n\n const [minTick, maxTick] = await client.readContract({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n functionName: 'getEnforcedTickLimits',\n args: [poolId],\n })\n\n return {\n minEnforcedTick: minTick,\n maxEnforcedTick: maxTick,\n }\n}\n\n// ---------------------------------------------------------------------------\n// getChunkLiquidities\n// ---------------------------------------------------------------------------\n\nexport interface ChunkInput {\n /** Owner address (panopticPool address for Panoptic chunks) */\n owner: Address\n /** 0 or 1 */\n tokenType: bigint\n tickLower: bigint\n tickUpper: bigint\n}\n\nexport interface ChunkLiquidityResult {\n /** Liquidity currently deployed in Uniswap */\n netLiquidity: bigint\n /** Liquidity removed by long holders */\n removedLiquidity: bigint\n /** Total liquidity deposited by shorts (net + removed) */\n totalLiquidity: bigint\n /** Alias for totalLiquidity (shorts deposited all of it) */\n shortLiquidity: bigint\n /** Alias for removedLiquidity (longs removed this much) */\n longLiquidity: bigint\n}\n\nexport interface GetChunkLiquiditiesParams {\n client: PublicClient\n /** SFPM address */\n sfpmAddress: Address\n /** Pool key bytes (from getPool().metadata.poolKeyBytes) */\n poolKeyBytes: `0x${string}`\n /** Chunks to query */\n chunks: ChunkInput[]\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\nexport interface GetChunkLiquiditiesResult {\n /** One result per input chunk */\n results: ChunkLiquidityResult[]\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Fetch liquidity breakdown for a batch of chunks via SFPM.getAccountLiquidity().\n *\n * Uses multicall for efficiency. Returns one result per input chunk,\n * along with block metadata for freshness tracking.\n */\nexport async function getChunkLiquidities(\n params: GetChunkLiquiditiesParams,\n): Promise<GetChunkLiquiditiesResult> {\n const { client, sfpmAddress, poolKeyBytes, chunks } = params\n\n if (chunks.length > MAX_TRACKED_CHUNKS) {\n throw new ChunkLimitError(BigInt(chunks.length), 0n)\n }\n\n const _meta = params._meta ?? (await getBlockMeta({ client }))\n\n if (chunks.length === 0) return { results: [], _meta }\n\n // Batch all getAccountLiquidity calls\n const multicallResults = await client.multicall({\n contracts: chunks.map((chunk) => ({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n functionName: 'getAccountLiquidity' as const,\n args: [\n poolKeyBytes,\n chunk.owner,\n chunk.tokenType,\n Number(chunk.tickLower),\n Number(chunk.tickUpper),\n ],\n })),\n allowFailure: true,\n })\n\n const results = multicallResults.map((result) => {\n if (result.status === 'failure') {\n return {\n netLiquidity: 0n,\n removedLiquidity: 0n,\n totalLiquidity: 0n,\n shortLiquidity: 0n,\n longLiquidity: 0n,\n }\n }\n\n const packed = result.result as bigint\n // LeftRightUnsigned: right 128 bits = netLiquidity, left 128 bits = removedLiquidity\n const netLiquidity = packed & ((1n << 128n) - 1n)\n const removedLiquidity = packed >> 128n\n const totalLiquidity = netLiquidity + removedLiquidity\n\n return {\n netLiquidity,\n removedLiquidity,\n totalLiquidity,\n shortLiquidity: totalLiquidity,\n longLiquidity: removedLiquidity,\n }\n })\n\n return { results, _meta }\n}\n","/**\n * Factory read functions for the Panoptic v2 SDK.\n *\n * Supports both PanopticFactoryV3 (Uniswap V3) and PanopticFactoryV4 (Uniswap V4).\n *\n * @module v2/reads/factory\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { zeroAddress } from 'viem'\n\nimport { panopticFactoryV3Abi, panopticFactoryV4Abi } from '../../../generated'\nimport type { PoolKey } from '../types'\nimport { getUniswapV3PoolFromId, getUniswapV4PoolKeyFromId } from './sfpm'\n\n// ---------------------------------------------------------------------------\n// Shared reads (identical signature on both V3 and V4)\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for getFactoryTokenURI.\n */\nexport interface GetFactoryTokenURIParams {\n /** Public client */\n client: PublicClient\n /** PanopticFactory address */\n factoryAddress: Address\n /** Factory version */\n version: 'v3' | 'v4'\n /** Token ID (encoded pool address) */\n tokenId: bigint\n}\n\n/**\n * Get the token URI from a PanopticFactory NFT.\n */\nexport async function getFactoryTokenURI(params: GetFactoryTokenURIParams): Promise<string> {\n const { client, factoryAddress, version, tokenId } = params\n const abi = version === 'v3' ? panopticFactoryV3Abi : panopticFactoryV4Abi\n\n return client.readContract({\n address: factoryAddress,\n abi,\n functionName: 'tokenURI',\n args: [tokenId],\n })\n}\n\n/**\n * Parameters for getFactoryOwnerOf.\n */\nexport interface GetFactoryOwnerOfParams {\n /** Public client */\n client: PublicClient\n /** PanopticFactory address */\n factoryAddress: Address\n /** Factory version */\n version: 'v3' | 'v4'\n /** Token ID (encoded pool address) */\n tokenId: bigint\n}\n\n/**\n * Get the owner of a PanopticFactory NFT.\n */\nexport async function getFactoryOwnerOf(params: GetFactoryOwnerOfParams): Promise<Address> {\n const { client, factoryAddress, version, tokenId } = params\n const abi = version === 'v3' ? panopticFactoryV3Abi : panopticFactoryV4Abi\n\n return client.readContract({\n address: factoryAddress,\n abi,\n functionName: 'ownerOf',\n args: [tokenId],\n })\n}\n\n/**\n * Parameters for getFactoryConstructMetadata.\n */\nexport interface GetFactoryConstructMetadataParams {\n /** Public client */\n client: PublicClient\n /** PanopticFactory address */\n factoryAddress: Address\n /** Factory version */\n version: 'v3' | 'v4'\n /** PanopticPool address (or predicted address) */\n panopticPoolAddress: Address\n /** Token 0 symbol */\n symbol0: string\n /** Token 1 symbol */\n symbol1: string\n /** Fee tier */\n fee: bigint\n}\n\n/**\n * Construct NFT metadata for a pool via the factory contract.\n */\nexport async function getFactoryConstructMetadata(\n params: GetFactoryConstructMetadataParams,\n): Promise<string> {\n const { client, factoryAddress, version, panopticPoolAddress, symbol0, symbol1, fee } = params\n const abi = version === 'v3' ? panopticFactoryV3Abi : panopticFactoryV4Abi\n\n return client.readContract({\n address: factoryAddress,\n abi,\n functionName: 'constructMetadata',\n args: [panopticPoolAddress, symbol0, symbol1, fee],\n })\n}\n\n// ---------------------------------------------------------------------------\n// V3-specific reads\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for getPanopticPoolAddress on a V3 factory.\n */\nexport interface GetPanopticPoolAddressV3Params {\n /** Public client */\n client: PublicClient\n /** PanopticFactoryV3 address */\n factoryAddress: Address\n /** Uniswap V3 pool address */\n univ3pool: Address\n /** Risk engine address */\n riskEngine: Address\n}\n\n/**\n * Parameters for getPanopticPoolAddress on a V4 factory.\n */\nexport interface GetPanopticPoolAddressV4Params {\n /** Public client */\n client: PublicClient\n /** PanopticFactoryV4 address */\n factoryAddress: Address\n /** V4 pool key */\n poolKey: PoolKey\n /** Risk engine address */\n riskEngine: Address\n}\n\n/** Versioned params for {@link getPanopticPoolAddress}. Use `version` to select V3 or V4. */\nexport type GetPanopticPoolAddressParams =\n | ({ version: 'v3' } & GetPanopticPoolAddressV3Params)\n | ({ version: 'v4' } & GetPanopticPoolAddressV4Params)\n\n/**\n * Get the PanopticPool address for a given pool and risk engine.\n */\nexport async function getPanopticPoolAddress(\n params: GetPanopticPoolAddressParams,\n): Promise<Address> {\n const { client, factoryAddress, riskEngine } = params\n\n if (params.version === 'v3') {\n return client.readContract({\n address: factoryAddress,\n abi: panopticFactoryV3Abi,\n functionName: 'getPanopticPool',\n args: [params.univ3pool, riskEngine],\n })\n }\n\n return client.readContract({\n address: factoryAddress,\n abi: panopticFactoryV4Abi,\n functionName: 'getPanopticPool',\n args: [\n {\n currency0: params.poolKey.currency0,\n currency1: params.poolKey.currency1,\n fee: Number(params.poolKey.fee),\n tickSpacing: Number(params.poolKey.tickSpacing),\n hooks: params.poolKey.hooks,\n },\n riskEngine,\n ],\n })\n}\n\n// ---------------------------------------------------------------------------\n// minePoolAddress\n// ---------------------------------------------------------------------------\n\n/**\n * Common mining parameters shared between V3 and V4.\n */\ninterface MinePoolAddressCommon {\n /** Public client */\n client: PublicClient\n /** PanopticFactory address */\n factoryAddress: Address\n /** Deployer address (msg.sender for deployment) */\n deployerAddress: Address\n /** Risk engine address */\n riskEngine: Address\n /** Starting salt (uint96) */\n salt: bigint\n /** Number of mining iterations */\n loops: bigint\n /** Minimum rarity target */\n minTargetRarity: bigint\n}\n\nexport interface MinePoolAddressV3Params extends MinePoolAddressCommon {\n /** Uniswap V3 pool address */\n v3Pool: Address\n}\n\nexport interface MinePoolAddressV4Params extends MinePoolAddressCommon {\n /** V4 pool key */\n poolKey: PoolKey\n}\n\n/** Versioned params for {@link minePoolAddress}. Use `version` to select V3 or V4. */\nexport type MinePoolAddressParams =\n | ({ version: 'v3' } & MinePoolAddressV3Params)\n | ({ version: 'v4' } & MinePoolAddressV4Params)\n\n/**\n * Result of pool address mining.\n */\nexport interface MinePoolAddressResult {\n /** Best salt found */\n bestSalt: bigint\n /** Highest rarity achieved */\n highestRarity: bigint\n}\n\n/**\n * Mine for an optimal pool address salt with high rarity.\n */\nexport async function minePoolAddress(\n params: MinePoolAddressParams,\n): Promise<MinePoolAddressResult> {\n const { client, factoryAddress, deployerAddress, riskEngine, salt, loops, minTargetRarity } =\n params\n\n let result: readonly [bigint, bigint]\n\n if (params.version === 'v3') {\n result = await client.readContract({\n address: factoryAddress,\n abi: panopticFactoryV3Abi,\n functionName: 'minePoolAddress',\n args: [deployerAddress, params.v3Pool, riskEngine, salt, loops, minTargetRarity],\n })\n } else {\n result = await client.readContract({\n address: factoryAddress,\n abi: panopticFactoryV4Abi,\n functionName: 'minePoolAddress',\n args: [\n deployerAddress,\n {\n currency0: params.poolKey.currency0,\n currency1: params.poolKey.currency1,\n fee: Number(params.poolKey.fee),\n tickSpacing: Number(params.poolKey.tickSpacing),\n hooks: params.poolKey.hooks,\n },\n riskEngine,\n salt,\n loops,\n minTargetRarity,\n ],\n })\n }\n\n return { bestSalt: BigInt(result[0]), highestRarity: result[1] }\n}\n\n// ---------------------------------------------------------------------------\n// simulateDeployNewPool\n// ---------------------------------------------------------------------------\n\ninterface SimulateDeployNewPoolCommon {\n /** Public client */\n client: PublicClient\n /** PanopticFactory address */\n factoryAddress: Address\n /** Account address (deployer) */\n account: Address\n /** Risk engine address */\n riskEngine: Address\n /** Salt (uint96) */\n salt: bigint\n}\n\nexport interface SimulateDeployNewPoolV3Params extends SimulateDeployNewPoolCommon {\n /** Token 0 address */\n token0: Address\n /** Token 1 address */\n token1: Address\n /** Fee tier (uint24) */\n fee: bigint\n}\n\nexport interface SimulateDeployNewPoolV4Params extends SimulateDeployNewPoolCommon {\n /** V4 pool key */\n poolKey: PoolKey\n}\n\nexport type SimulateDeployNewPoolParams =\n | ({ version: 'v3' } & SimulateDeployNewPoolV3Params)\n | ({ version: 'v4' } & SimulateDeployNewPoolV4Params)\n\n/**\n * Simulate a pool deployment to get the predicted pool address.\n *\n * Uses `simulateContract` on `deployNewPool` — the return value is the new pool address\n * without actually executing the transaction.\n */\nexport async function simulateDeployNewPool(params: SimulateDeployNewPoolParams): Promise<Address> {\n const { client, factoryAddress, account, riskEngine, salt } = params\n\n if (params.version === 'v3') {\n const { result } = await client.simulateContract({\n address: factoryAddress,\n abi: panopticFactoryV3Abi,\n functionName: 'deployNewPool',\n args: [params.token0, params.token1, Number(params.fee), riskEngine, salt],\n account,\n })\n return result\n }\n\n const { result } = await client.simulateContract({\n address: factoryAddress,\n abi: panopticFactoryV4Abi,\n functionName: 'deployNewPool',\n args: [\n {\n currency0: params.poolKey.currency0,\n currency1: params.poolKey.currency1,\n fee: Number(params.poolKey.fee),\n tickSpacing: Number(params.poolKey.tickSpacing),\n hooks: params.poolKey.hooks,\n },\n riskEngine,\n salt,\n ],\n account,\n })\n return result\n}\n\n// ---------------------------------------------------------------------------\n// getPanopticPoolFromPoolId\n// ---------------------------------------------------------------------------\n\n/**\n * Common parameters for {@link getPanopticPoolFromPoolId}.\n */\ninterface GetPanopticPoolFromPoolIdCommon {\n /** Public client */\n client: PublicClient\n /** SFPM address */\n sfpmAddress: Address\n /** PanopticFactory address */\n factoryAddress: Address\n /** Risk engine address */\n riskEngine: Address\n /** The SFPM pool identifier (uint64) */\n poolId: bigint\n}\n\n/** Versioned params for {@link getPanopticPoolFromPoolId}. */\nexport type GetPanopticPoolFromPoolIdParams =\n | ({ version: 'v3' } & GetPanopticPoolFromPoolIdCommon)\n | ({ version: 'v4' } & GetPanopticPoolFromPoolIdCommon)\n\n/**\n * Resolve an SFPM poolId to its PanopticPool address.\n *\n * Chains two on-chain lookups:\n * 1. SFPM: poolId → Uniswap pool address (V3) or pool key (V4)\n * 2. Factory: Uniswap pool + riskEngine → PanopticPool address\n */\nexport async function getPanopticPoolFromPoolId(\n params: GetPanopticPoolFromPoolIdParams,\n): Promise<Address> {\n const { client, sfpmAddress, factoryAddress, riskEngine, poolId, version } = params\n\n if (version === 'v3') {\n const univ3pool = await getUniswapV3PoolFromId({ client, sfpmAddress, poolId })\n return getPanopticPoolAddress({\n version: 'v3',\n client,\n factoryAddress,\n univ3pool,\n riskEngine,\n })\n }\n\n const poolKey = await getUniswapV4PoolKeyFromId({ client, sfpmAddress, poolId })\n return getPanopticPoolAddress({\n version: 'v4',\n client,\n factoryAddress,\n poolKey,\n riskEngine,\n })\n}\n\n// ---------------------------------------------------------------------------\n// resolvePanopticPoolFromPoolId (version-agnostic)\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for {@link resolvePanopticPoolFromPoolId}.\n */\nexport interface ResolvePanopticPoolFromPoolIdParams {\n /** Public client */\n client: PublicClient\n /** The SFPM pool identifier (uint64) */\n poolId: bigint\n /** Risk engine address */\n riskEngine: Address\n /** V3 SFPM + Factory addresses (omit if V3 is not deployed) */\n v3?: {\n sfpmAddress: Address\n factoryAddress: Address\n }\n /** V4 SFPM + Factory addresses (omit if V4 is not deployed) */\n v4?: {\n sfpmAddress: Address\n factoryAddress: Address\n }\n}\n\n/**\n * Result of {@link resolvePanopticPoolFromPoolId}.\n */\nexport interface ResolvePanopticPoolFromPoolIdResult {\n /** The resolved PanopticPool address */\n panopticPoolAddress: Address\n /** Which version matched */\n version: 'v3' | 'v4'\n}\n\n/**\n * Resolve an SFPM poolId to its PanopticPool address without knowing the version.\n *\n * Tries both V3 and V4 lookups in parallel. The factory returns `address(0)` for\n * non-existent pools, so the non-zero result identifies the correct version.\n *\n * At least one of `v3` or `v4` must be provided.\n *\n * @throws {PanopticValidationError} If no version config is provided or neither resolves.\n */\nexport async function resolvePanopticPoolFromPoolId(\n params: ResolvePanopticPoolFromPoolIdParams,\n): Promise<ResolvePanopticPoolFromPoolIdResult> {\n const { client, poolId, riskEngine, v3, v4 } = params\n\n if (!v3 && !v4) {\n throw new Error('At least one of v3 or v4 must be provided')\n }\n\n const isNotFoundError = (err: unknown): boolean => {\n // Contract reverts (e.g. pool not registered) are \"not found\".\n // RPC / ABI / network errors should propagate.\n if (typeof err === 'object' && err !== null && 'name' in err) {\n const name = (err as { name: string }).name\n return name === 'ContractFunctionExecutionError' || name === 'ContractFunctionRevertedError'\n }\n return false\n }\n\n const results = await Promise.all([\n v3\n ? getPanopticPoolFromPoolId({\n version: 'v3',\n client,\n sfpmAddress: v3.sfpmAddress,\n factoryAddress: v3.factoryAddress,\n riskEngine,\n poolId,\n }).catch((err) => {\n if (isNotFoundError(err)) return zeroAddress\n throw err\n })\n : Promise.resolve(zeroAddress),\n v4\n ? getPanopticPoolFromPoolId({\n version: 'v4',\n client,\n sfpmAddress: v4.sfpmAddress,\n factoryAddress: v4.factoryAddress,\n riskEngine,\n poolId,\n }).catch((err) => {\n if (isNotFoundError(err)) return zeroAddress\n throw err\n })\n : Promise.resolve(zeroAddress),\n ])\n\n const [v3Result, v4Result] = results\n\n if (v3Result !== zeroAddress) {\n return { panopticPoolAddress: v3Result, version: 'v3' }\n }\n if (v4Result !== zeroAddress) {\n return { panopticPoolAddress: v4Result, version: 'v4' }\n }\n\n throw new Error(`No PanopticPool found for poolId ${poolId}`)\n}\n","/**\n * Client-side (off-chain) implementation of minePoolAddress.\n *\n * Replicates the on-chain PanopticFactory mining loop entirely in TypeScript,\n * eliminating RPC round-trips. The result is identical to the on-chain computation.\n *\n * Algorithm:\n * For each candidate salt (uint96):\n * 1. Pack a bytes32 salt from deployer, pool identifier, riskEngine, and iteration salt\n * 2. Predict the CREATE3 deployed address (via proxy)\n * 3. Score by leading hex zeros (\"rarity\")\n * 4. Track the best salt; stop early if minTargetRarity is reached\n *\n * @module v2/reads/minePoolAddressLocal\n */\n\nimport type { Address, Hex } from 'viem'\nimport { encodeAbiParameters, keccak256 } from 'viem'\n\nimport { PanopticValidationError } from '../errors'\nimport type { PoolKey } from '../types'\nimport type {\n MinePoolAddressResult,\n MinePoolAddressV3Params,\n MinePoolAddressV4Params,\n} from './factory'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Mining params for PanopticFactoryV3 — no RPC client needed. */\nexport type MinePoolAddressLocalV3Params = Omit<MinePoolAddressV3Params, 'client'>\n\n/** Mining params for PanopticFactoryV4 — no RPC client needed. */\nexport type MinePoolAddressLocalV4Params = Omit<MinePoolAddressV4Params, 'client'>\n\nexport type MinePoolAddressLocalParams =\n | ({ version: 'v3' } & MinePoolAddressLocalV3Params)\n | ({ version: 'v4' } & MinePoolAddressLocalV4Params)\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/**\n * keccak256 of the CREATE3 proxy initcode used by ClonesWithImmutableArgs.\n * Source: packages/panoptic-v2-core/lib/clones-with-immutable-args/src/ClonesWithImmutableArgs.sol\n */\nconst CREATE3_PROXY_BYTECODE_HASH =\n '0x21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f' as Hex\n\nconst MASK_80 = (1n << 80n) - 1n\nconst MASK_40 = (1n << 40n) - 1n\nconst MASK_96 = (1n << 96n) - 1n\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\n/** Encode a BigInt as a big-endian fixed-length byte array. */\nfunction bigintToBytes(value: bigint, byteLength: number): Uint8Array {\n const bytes = new Uint8Array(byteLength)\n let v = value\n for (let i = byteLength - 1; i >= 0; i--) {\n bytes[i] = Number(v & 0xffn)\n v >>= 8n\n }\n return bytes\n}\n\n/** Parse a 0x-prefixed address into 20 bytes. */\nfunction addressToBytes(addr: Address): Uint8Array {\n const hex = addr.slice(2).padStart(40, '0')\n const bytes = new Uint8Array(20)\n for (let i = 0; i < 20; i++) {\n bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16)\n }\n return bytes\n}\n\n/** Parse a 0x-prefixed 32-byte hex string into bytes. */\nfunction hex32ToBytes(hex: Hex): Uint8Array {\n const h = hex.slice(2).padStart(64, '0')\n const bytes = new Uint8Array(32)\n for (let i = 0; i < 32; i++) {\n bytes[i] = parseInt(h.slice(i * 2, i * 2 + 2), 16)\n }\n return bytes\n}\n\n/**\n * Compute the CREATE3 deployed address for a given factory and packed salt.\n *\n * Mirrors `ClonesWithImmutableArgs.addressOfClone3(salt)` (with `address(this)` = factory):\n * proxy = CREATE2(factory, salt, PROXY_BYTECODE_HASH)\n * deployed = CREATE1(proxy, nonce=1)\n *\n * Returns the deployed address as a uint160 BigInt.\n */\nfunction addressOfClone3(factory: Address, salt: bigint): bigint {\n const saltBytes = bigintToBytes(salt, 32)\n\n // CREATE2: keccak256(0xff ++ factory ++ salt ++ proxyBytecodeHash) — 85 bytes total\n const create2Input = new Uint8Array(85)\n create2Input[0] = 0xff\n create2Input.set(addressToBytes(factory), 1) // bytes 1–20\n create2Input.set(saltBytes, 21) // bytes 21–52\n create2Input.set(hex32ToBytes(CREATE3_PROXY_BYTECODE_HASH), 53) // bytes 53–84\n\n const proxyHash = keccak256(create2Input, 'bytes')\n const proxyAddress = proxyHash.slice(12) // rightmost 20 bytes\n\n // CREATE1 nonce=1: keccak256(0xd694 ++ proxy ++ 0x01) — 23 bytes total\n const create1Input = new Uint8Array(23)\n create1Input[0] = 0xd6\n create1Input[1] = 0x94\n create1Input.set(proxyAddress, 2) // bytes 2–21\n create1Input[22] = 0x01\n\n const deployedHash = keccak256(create1Input, 'bytes')\n\n // Convert rightmost 20 bytes to uint160 BigInt\n let addr = 0n\n for (let i = 12; i < 32; i++) {\n addr = (addr << 8n) | BigInt(deployedHash[i])\n }\n return addr\n}\n\n/**\n * Count leading hex-zero characters in a 160-bit address value.\n *\n * Mirrors `PanopticMath.numberOfLeadingHexZeros(addr)`.\n * Returns 40 for the zero address.\n */\nexport function numberOfLeadingHexZeros(addrInt: bigint): number {\n if (addrInt === 0n) return 40\n let x = addrInt\n let r = 0\n if (x >= 0x100000000000000000000000000000000n) {\n x >>= 128n\n r += 32\n }\n if (x >= 0x10000000000000000n) {\n x >>= 64n\n r += 16\n }\n if (x >= 0x100000000n) {\n x >>= 32n\n r += 8\n }\n if (x >= 0x10000n) {\n x >>= 16n\n r += 4\n }\n if (x >= 0x100n) {\n x >>= 8n\n r += 2\n }\n if (x >= 0x10n) {\n r += 1\n }\n return 39 - r\n}\n\n/**\n * Construct the bytes32 CREATE3 salt for PanopticFactoryV3.\n *\n * Mirrors:\n * bytes32(abi.encodePacked(\n * uint80(uint160(deployerAddress) >> 80), // bits [159:80] of deployer → 10 bytes\n * uint40(uint160(v3Pool) >> 120), // bits [159:120] of v3Pool → 5 bytes\n * uint40(uint160(riskEngine) >> 120), // bits [159:120] of riskEngine→ 5 bytes\n * salt // uint96 → 12 bytes\n * ))\n */\nfunction computeSaltPrefixV3(\n deployerAddress: Address,\n v3Pool: Address,\n riskEngine: Address,\n): bigint {\n const deployer80 = (BigInt(deployerAddress) >> 80n) & MASK_80\n const pool40 = (BigInt(v3Pool) >> 120n) & MASK_40\n const risk40 = (BigInt(riskEngine) >> 120n) & MASK_40\n return (deployer80 << 176n) | (pool40 << 136n) | (risk40 << 96n)\n}\n\n/**\n * Compute the Uniswap V4 PoolId for a PoolKey.\n *\n * Mirrors `PoolId.toId(key)` = keccak256 of the ABI-encoded PoolKey struct\n * (5 fields × 32 bytes = 160 bytes).\n */\nexport function computePoolIdV4(poolKey: PoolKey): bigint {\n const fee = Number(poolKey.fee)\n if (!Number.isInteger(fee) || fee < 0 || fee >= 2 ** 24) {\n throw new PanopticValidationError(`fee out of uint24 range: ${fee}`)\n }\n const tickSpacing = Number(poolKey.tickSpacing)\n if (!Number.isInteger(tickSpacing) || tickSpacing < -(2 ** 23) || tickSpacing > 2 ** 23 - 1) {\n throw new PanopticValidationError(`tickSpacing out of int24 range: ${tickSpacing}`)\n }\n const encoded = encodeAbiParameters(\n [\n { type: 'address' },\n { type: 'address' },\n { type: 'uint24' },\n { type: 'int24' },\n { type: 'address' },\n ],\n [\n poolKey.currency0,\n poolKey.currency1,\n Number(poolKey.fee),\n Number(poolKey.tickSpacing),\n poolKey.hooks,\n ],\n )\n return BigInt(keccak256(encoded))\n}\n\n/**\n * Construct the bytes32 CREATE3 salt for PanopticFactoryV4.\n *\n * Mirrors:\n * bytes32(abi.encodePacked(\n * uint80(uint160(deployerAddress) >> 80),\n * uint40(uint256(PoolId.unwrap(key.toId())) >> 120), // bits [159:120] of poolId\n * uint40(uint160(riskEngine) >> 120),\n * salt\n * ))\n */\nfunction computeSaltPrefixV4(\n deployerAddress: Address,\n poolKey: PoolKey,\n riskEngine: Address,\n): bigint {\n const deployer80 = (BigInt(deployerAddress) >> 80n) & MASK_80\n const poolId40 = (computePoolIdV4(poolKey) >> 120n) & MASK_40\n const risk40 = (BigInt(riskEngine) >> 120n) & MASK_40\n return (deployer80 << 176n) | (poolId40 << 136n) | (risk40 << 96n)\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Mine for an optimal Panoptic pool address salt, running entirely off-chain.\n *\n * Equivalent to calling `minePoolAddress` on the factory contract but with zero\n * RPC round-trips. The result is identical to the on-chain computation.\n *\n * Iterates `loops` times starting from `salt`, tracking the highest-rarity address\n * found. Stops early when `minTargetRarity` is reached.\n *\n * @param params - Mining parameters (versioned: 'v3' or 'v4'). No `client` required.\n * @returns The best salt found and its rarity (number of leading hex zeros).\n */\nexport function minePoolAddressLocal(params: MinePoolAddressLocalParams): MinePoolAddressResult {\n const { factoryAddress, deployerAddress, riskEngine, salt, loops, minTargetRarity } = params\n\n if (salt < 0n || loops < 0n || minTargetRarity < 0n) {\n throw new PanopticValidationError('salt, loops, and minTargetRarity must be non-negative')\n }\n if (salt + loops > (1n << 96n) - 1n) {\n throw new PanopticValidationError('salt + loops exceeds uint96 range')\n }\n\n let bestSalt = salt\n let highestRarity = 0n\n const maxSalt = salt + loops\n\n // Precompute the invariant high-bit prefix once outside the loop\n const saltPrefix =\n params.version === 'v3'\n ? computeSaltPrefixV3(deployerAddress, params.v3Pool, riskEngine)\n : computeSaltPrefixV4(deployerAddress, params.poolKey, riskEngine)\n\n for (let currentSalt = salt; currentSalt < maxSalt; currentSalt++) {\n const newSalt = saltPrefix | (currentSalt & MASK_96)\n\n const addrInt = addressOfClone3(factoryAddress, newSalt)\n const rarity = BigInt(numberOfLeadingHexZeros(addrInt))\n\n if (rarity > highestRarity) {\n highestRarity = rarity\n bestSalt = currentSalt\n }\n\n if (rarity >= minTargetRarity) {\n highestRarity = rarity\n bestSalt = currentSalt\n break\n }\n }\n\n return { bestSalt, highestRarity }\n}\n\n// ---------------------------------------------------------------------------\n// Async variant (yields to the event loop between chunks)\n// ---------------------------------------------------------------------------\n\n/** Number of iterations per chunk before yielding back to the event loop. */\nconst CHUNK_SIZE = 5000n\n\n/**\n * Async version of {@link minePoolAddressLocal} that yields to the event loop\n * between chunks of iterations, preventing the browser UI from freezing.\n *\n * @param params - Mining parameters (versioned: 'v3' or 'v4'). No `client` required.\n * @returns The best salt found and its rarity (number of leading hex zeros).\n */\nexport async function minePoolAddressLocalAsync(\n params: MinePoolAddressLocalParams,\n): Promise<MinePoolAddressResult> {\n const { factoryAddress, deployerAddress, riskEngine, salt, loops, minTargetRarity } = params\n\n let bestSalt = salt\n let highestRarity = 0n\n const maxSalt = salt + loops\n\n const saltPrefix =\n params.version === 'v3'\n ? computeSaltPrefixV3(deployerAddress, params.v3Pool, riskEngine)\n : computeSaltPrefixV4(deployerAddress, params.poolKey, riskEngine)\n\n let currentSalt = salt\n while (currentSalt < maxSalt) {\n const chunkEnd = currentSalt + CHUNK_SIZE < maxSalt ? currentSalt + CHUNK_SIZE : maxSalt\n let done = false\n\n for (; currentSalt < chunkEnd; currentSalt++) {\n const newSalt = saltPrefix | (currentSalt & MASK_96)\n const addrInt = addressOfClone3(factoryAddress, newSalt)\n const rarity = BigInt(numberOfLeadingHexZeros(addrInt))\n\n if (rarity > highestRarity) {\n highestRarity = rarity\n bestSalt = currentSalt\n }\n\n if (rarity >= minTargetRarity) {\n highestRarity = rarity\n bestSalt = currentSalt\n done = true\n break\n }\n }\n\n if (done) break\n\n // Yield to the event loop so the UI stays responsive\n await new Promise<void>((resolve) => setTimeout(resolve, 0))\n }\n\n return { bestSalt, highestRarity }\n}\n","/**\n * Premia read functions for the Panoptic v2 SDK.\n * @module v2/reads/premia\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport type { BlockMeta, Position, TokenIdLeg } from '../types'\nimport { decodePosition, decodeTickSpacing } from '../utils/option-encoding-v2'\nimport { decodeLeftRightUnsigned } from '../writes/utils'\n\n/**\n * Premia data for an account.\n */\nexport interface AccountPremia {\n /** Total short premium owed to the account for token 0 */\n shortPremium0: bigint\n /** Total short premium owed to the account for token 1 */\n shortPremium1: bigint\n /** Total long premium owed by the account for token 0 */\n longPremium0: bigint\n /** Total long premium owed by the account for token 1 */\n longPremium1: bigint\n /** Whether pending (unsettled) premium was included */\n includePendingPremium: boolean\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for getAccountPremia.\n */\nexport interface GetAccountPremiaParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenIds held by the account */\n tokenIds: bigint[]\n /** Whether to include pending (unsettled) premium (default: true) */\n includePendingPremium?: boolean\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get premia totals for an account.\n *\n * Returns the total short and long premium across all positions.\n * Short premium is owed TO the account (earned from selling options).\n * Long premium is owed BY the account (paid for buying options).\n *\n * @param params - The parameters\n * @returns Premia totals with block metadata\n *\n * @example\n * ```typescript\n * const premia = await getAccountPremia({\n * client,\n * poolAddress,\n * account,\n * tokenIds: [tokenId1, tokenId2],\n * includePendingPremium: true,\n * })\n *\n * console.log('Short premium earned:', premia.shortPremium0, premia.shortPremium1)\n * console.log('Long premium owed:', premia.longPremium0, premia.longPremium1)\n * ```\n */\nexport async function getAccountPremia(params: GetAccountPremiaParams): Promise<AccountPremia> {\n const {\n client,\n poolAddress,\n account,\n tokenIds,\n includePendingPremium = true,\n blockNumber,\n } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Handle empty position list\n if (tokenIds.length === 0) {\n const _meta = params._meta ?? (await getBlockMeta({ client, blockNumber: targetBlockNumber }))\n return {\n shortPremium0: 0n,\n shortPremium1: 0n,\n longPremium0: 0n,\n longPremium1: 0n,\n includePendingPremium,\n _meta,\n }\n }\n\n const [[shortPremiumPacked, longPremiumPacked], _meta] = await Promise.all([\n client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, includePendingPremium, tokenIds],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // Decode LeftRightUnsigned values (right = token0, left = token1)\n const shortPremium = decodeLeftRightUnsigned(shortPremiumPacked)\n const longPremium = decodeLeftRightUnsigned(longPremiumPacked)\n\n return {\n shortPremium0: shortPremium.right,\n shortPremium1: shortPremium.left,\n longPremium0: longPremium.right,\n longPremium1: longPremium.left,\n includePendingPremium,\n _meta,\n }\n}\n\n/**\n * Position with premia data.\n */\nexport interface PositionWithPremia extends Position {\n // Position already has all fields from the base Position interface\n}\n\n/**\n * Result from getPositionsWithPremia.\n */\nexport interface PositionsWithPremiaResult {\n /** Positions with full data */\n positions: PositionWithPremia[]\n /** Total short premium owed to the account for token 0 */\n shortPremium0: bigint\n /** Total short premium owed to the account for token 1 */\n shortPremium1: bigint\n /** Total long premium owed by the account for token 0 */\n longPremium0: bigint\n /** Total long premium owed by the account for token 1 */\n longPremium1: bigint\n /** Whether pending (unsettled) premium was included */\n includePendingPremium: boolean\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for getPositionsWithPremia.\n */\nexport interface GetPositionsWithPremiaParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenIds held by the account */\n tokenIds: bigint[]\n /** Whether to include pending (unsettled) premium (default: true) */\n includePendingPremium?: boolean\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get positions with per-position premia data.\n *\n * Uses multicall to batch individual getFullPositionsData calls\n * for each position, giving us per-position premia in a single RPC request.\n *\n * @param params - The parameters\n * @returns Positions with premia and totals with block metadata\n *\n * @example\n * ```typescript\n * const result = await getPositionsWithPremia({\n * client,\n * poolAddress,\n * account,\n * tokenIds: [tokenId1, tokenId2],\n * })\n *\n * for (const position of result.positions) {\n * console.log('Position:', position.tokenId)\n * console.log('Premia:', position.premiaOwed0, position.premiaOwed1)\n * }\n * console.log('Total short premium:', result.shortPremium0, result.shortPremium1)\n * ```\n */\nexport async function getPositionsWithPremia(\n params: GetPositionsWithPremiaParams,\n): Promise<PositionsWithPremiaResult> {\n const {\n client,\n poolAddress,\n account,\n tokenIds,\n includePendingPremium = true,\n blockNumber,\n } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Handle empty position list\n if (tokenIds.length === 0) {\n const _meta = params._meta ?? (await getBlockMeta({ client, blockNumber: targetBlockNumber }))\n return {\n positions: [],\n shortPremium0: 0n,\n shortPremium1: 0n,\n longPremium0: 0n,\n longPremium1: 0n,\n includePendingPremium,\n _meta,\n }\n }\n\n // Build multicall contracts - one getFullPositionsData call per tokenId\n // This gives us per-position premia\n const contracts = tokenIds.map((tokenId) => ({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData' as const,\n args: [account, includePendingPremium, [tokenId]] as const,\n }))\n\n // Execute multicall and get block metadata\n const [multicallResults, _meta] = await Promise.all([\n client.multicall({\n contracts,\n blockNumber: targetBlockNumber,\n allowFailure: true,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // Build positions and accumulate totals\n const positions: PositionWithPremia[] = []\n let totalShortPremium0 = 0n\n let totalShortPremium1 = 0n\n let totalLongPremium0 = 0n\n let totalLongPremium1 = 0n\n\n for (let i = 0; i < tokenIds.length; i++) {\n const tokenId = tokenIds[i]\n const result = multicallResults[i]\n\n // Skip failed calls\n if (result.status !== 'success') {\n continue\n }\n\n const [shortPremiumPacked, longPremiumPacked, balances] = result.result\n\n // Decode per-position premia\n const shortPremium = decodeLeftRightUnsigned(shortPremiumPacked)\n const longPremium = decodeLeftRightUnsigned(longPremiumPacked)\n\n // Accumulate totals\n totalShortPremium0 += shortPremium.right\n totalShortPremium1 += shortPremium.left\n totalLongPremium0 += longPremium.right\n totalLongPremium1 += longPremium.left\n\n // Get balance data (should be single element array)\n const balanceData = balances[0]\n if (balanceData === undefined) {\n continue\n }\n\n // Decode the PositionBalance\n const positionSize = balanceData & ((1n << 128n) - 1n)\n\n // Skip positions with zero size\n if (positionSize === 0n) {\n continue\n }\n\n const poolUtilization0 = (balanceData >> 128n) & 0xffffn\n const poolUtilization1 = (balanceData >> 144n) & 0xffffn\n\n // tickAtMint is int24 at bits 160-183\n let tickAtMint = (balanceData >> 160n) & 0xffffffn\n if (tickAtMint > 0x7fffffn) {\n tickAtMint = tickAtMint - 0x1000000n\n }\n\n const timestampAtMint = (balanceData >> 184n) & 0xffffffffn\n const blockAtMint = (balanceData >> 216n) & ((1n << 39n) - 1n)\n const swapAtMint = balanceData >> 255n === 1n\n\n // Decode the tokenId to get legs\n const decoded = decodePosition(tokenId)\n const tickSpacing = decodeTickSpacing(tokenId)\n\n // Convert decoded legs to TokenIdLeg format\n const legs: TokenIdLeg[] = decoded.legs.map((leg) => {\n const width = leg.width\n const strike = leg.strike\n const tickLower = strike - (width * tickSpacing) / 2n\n const tickUpper = strike + (width * tickSpacing) / 2n\n\n return {\n index: BigInt(leg.index),\n asset: leg.asset,\n optionRatio: leg.optionRatio,\n isLong: leg.isLong === 1n,\n tokenType: leg.tokenType,\n riskPartner: leg.riskPartner,\n strike,\n width,\n tickLower,\n tickUpper,\n }\n })\n\n // Calculate net premia for this position\n // Positive = position has earned premium (short), Negative = position owes premium (long)\n const premiaOwed0 = shortPremium.right - longPremium.right\n const premiaOwed1 = shortPremium.left - longPremium.left\n\n positions.push({\n tokenId,\n positionSize,\n owner: account,\n poolAddress,\n legs,\n poolUtilization0AtMint: poolUtilization0,\n poolUtilization1AtMint: poolUtilization1,\n tickAtMint,\n timestampAtMint,\n blockNumberAtMint: blockAtMint,\n swapAtMint,\n premiaOwed0,\n premiaOwed1,\n assetIndex: legs.length > 0 ? legs[0].asset : 0n,\n _meta,\n })\n }\n\n return {\n positions,\n shortPremium0: totalShortPremium0,\n shortPremium1: totalShortPremium1,\n longPremium0: totalLongPremium0,\n longPremium1: totalLongPremium1,\n includePendingPremium,\n _meta,\n }\n}\n","/**\n * Collateral estimation functions for the Panoptic v2 SDK.\n *\n * These functions require the PanopticQuery contract which provides\n * on-chain calculation capabilities for collateral requirements.\n *\n * @module v2/reads/collateralEstimate\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { encodeFunctionData } from 'viem'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi } from '../../../generated'\nimport { panopticQueryAbi } from '../abis/panopticQuery'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { PanopticError } from '../errors'\nimport { type TokenFlow, simulateWithTokenFlow } from '../simulations/tokenFlow'\nimport type { StorageAdapter } from '../storage'\nimport { getTrackedPositionIds } from '../sync/getTrackedPositionIds'\nimport type { BlockMeta } from '../types'\nimport { MAX_TICK, MIN_TICK } from '../utils/constants'\n\n/**\n * Collateral estimate result.\n */\nexport interface CollateralEstimate {\n /** Required collateral for token 0 */\n required0: bigint\n /** Required collateral for token 1 */\n required1: bigint\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for estimateCollateralRequired.\n */\nexport interface EstimateCollateralRequiredParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenId to estimate collateral for */\n tokenId: bigint\n /** Position size (number of contracts) */\n positionSize: bigint\n /** Optional: Tick to calculate collateral at (defaults to current tick) */\n atTick?: bigint\n /** PanopticQuery address */\n queryAddress: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Estimate the collateral required to open a position.\n *\n * Note: This function uses PanopticQuery.getRequiredBase for estimation.\n * Returns collateral requirement in terms of token0.\n *\n * @param params - The parameters\n * @returns Estimated collateral requirements with block metadata\n */\nexport async function estimateCollateralRequired(\n params: EstimateCollateralRequiredParams,\n): Promise<CollateralEstimate> {\n const { client, poolAddress, tokenId, atTick, queryAddress, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Get current tick if not provided\n let effectiveTick: bigint\n if (atTick !== undefined) {\n effectiveTick = atTick\n } else {\n const currentTickResult = await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n blockNumber: targetBlockNumber,\n })\n // Bridge type from panopticPoolV2Abi (number | bigint) to bigint\n effectiveTick = BigInt(currentTickResult)\n }\n\n const [required0, _meta] = await Promise.all([\n client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getRequiredBase',\n args: [poolAddress, tokenId, Number(effectiveTick)],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // PanopticQuery.getRequiredBase returns collateral requirement in terms of token0\n // For token1 requirement, would need additional conversion or separate call\n return {\n required0,\n required1: 0n, // Not available from getRequiredBase (token0-denominated only)\n _meta,\n }\n}\n\n/**\n * Max position size result.\n */\nexport interface MaxPositionSize {\n /** Refined maximum position size at current market conditions */\n maxSize: bigint\n /** Maximum position size at 0% utilization (best case / upper bound) */\n maxSizeAtMinUtil: bigint\n /** Maximum position size at 100% utilization (worst case / lower bound) */\n maxSizeAtMaxUtil: bigint\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for getMaxPositionSize.\n */\nexport interface GetMaxPositionSizeParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenId to check max size for */\n tokenId: bigint\n /** PanopticQuery address (required for this function) */\n queryAddress: Address\n /**\n * Existing position IDs held by the account.\n * - If provided, uses these directly\n * - If not provided but storage + chainId given, fetches from getTrackedPositionIds()\n * - If neither provided, assumes empty array (new account with no positions)\n */\n existingPositionIds?: bigint[]\n /** Storage adapter for auto-fetching positions (requires chainId) */\n storage?: StorageAdapter\n /** Chain ID (required if using storage) */\n chainId?: bigint\n /** Whether to refine with dispatch simulation (default: true) */\n refine?: boolean\n /** Precision for binary search as percentage (default: 1 = 1%) */\n precisionPct?: number\n /** Whether to swap tokens at mint (affects collateral requirements, default: false) */\n swapAtMint?: boolean\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get the maximum position size an account can open given their current collateral.\n *\n * Uses PanopticQuery.getMaxPositionSizeBounds to get bounds at 0% and 100% utilization,\n * then refines with dispatch simulations to find the exact max at current conditions.\n *\n * @param params - The parameters\n * @returns Maximum position size with bounds and block metadata\n */\nexport async function getMaxPositionSize(\n params: GetMaxPositionSizeParams,\n): Promise<MaxPositionSize> {\n const {\n client,\n poolAddress,\n account,\n tokenId,\n queryAddress,\n existingPositionIds,\n storage,\n chainId,\n refine = true,\n precisionPct = 1,\n swapAtMint = false,\n blockNumber,\n } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Get existing position IDs\n let positionIds: bigint[]\n if (existingPositionIds !== undefined) {\n // Use explicitly provided position IDs\n positionIds = existingPositionIds\n } else if (storage && chainId !== undefined) {\n // Fetch from local cache via getTrackedPositionIds\n positionIds = await getTrackedPositionIds({\n chainId,\n poolAddress,\n account,\n storage,\n })\n } else {\n // Assume new account with no existing positions\n positionIds = []\n }\n // Get bounds and block meta in parallel\n const [boundsResult, _meta] = await Promise.all([\n client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getMaxPositionSizeBounds',\n args: [poolAddress, positionIds, account, tokenId],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const [maxSizeAtMinUtil, maxSizeAtMaxUtil] = boundsResult\n\n // If bounds are equal or very close, or refinement disabled, return conservative estimate\n const precisionDivisor = BigInt(Math.floor(100 / precisionPct))\n if (\n !refine ||\n maxSizeAtMinUtil === maxSizeAtMaxUtil ||\n maxSizeAtMinUtil - maxSizeAtMaxUtil <= maxSizeAtMaxUtil / precisionDivisor\n ) {\n return {\n maxSize: maxSizeAtMaxUtil,\n maxSizeAtMinUtil,\n maxSizeAtMaxUtil,\n _meta,\n }\n }\n\n // Binary search between widened bounds using dispatch simulation\n // Widen by 2x in each direction to account for swapAtMint price impact\n const maxSize = await binarySearchMaxSize({\n client,\n poolAddress,\n account,\n tokenId,\n existingPositionIds: positionIds,\n low: maxSizeAtMaxUtil / 2n,\n high: maxSizeAtMinUtil * 2n,\n precisionDivisor,\n swapAtMint,\n })\n\n return {\n maxSize,\n maxSizeAtMinUtil,\n maxSizeAtMaxUtil,\n _meta,\n }\n}\n\n/**\n * Parallel search to find max position size using dispatch simulation.\n * Tests 5 points per round (sextiles), narrowing the range by 6x each iteration.\n */\nasync function binarySearchMaxSize(params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n tokenId: bigint\n existingPositionIds: bigint[]\n low: bigint\n high: bigint\n precisionDivisor: bigint\n swapAtMint: boolean\n}): Promise<bigint> {\n const {\n client,\n poolAddress,\n account,\n tokenId,\n existingPositionIds,\n precisionDivisor,\n swapAtMint,\n } = params\n let { low, high } = params\n\n const trySize = (positionSize: bigint) =>\n tryDispatchSimulation({\n client,\n poolAddress,\n account,\n tokenId,\n existingPositionIds,\n positionSize,\n swapAtMint,\n })\n\n while (high - low > 1n && high - low > low / precisionDivisor) {\n const range = high - low\n const p1 = low + range / 6n\n const p2 = low + (range * 2n) / 6n\n const p3 = low + (range * 3n) / 6n\n const p4 = low + (range * 4n) / 6n\n const p5 = low + (range * 5n) / 6n\n\n const [s1, s2, s3, s4, s5] = await Promise.all([\n trySize(p1),\n trySize(p2),\n trySize(p3),\n trySize(p4),\n trySize(p5),\n ])\n\n if (s5) {\n low = p5\n } else if (s4) {\n low = p4\n high = p5\n } else if (s3) {\n low = p3\n high = p4\n } else if (s2) {\n low = p2\n high = p3\n } else if (s1) {\n low = p1\n high = p2\n } else {\n high = p1\n }\n }\n\n return low\n}\n\n/**\n * Try to simulate opening a position with the given size.\n */\nasync function tryDispatchSimulation(params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n tokenId: bigint\n existingPositionIds: bigint[]\n positionSize: bigint\n swapAtMint: boolean\n}): Promise<boolean> {\n const { client, poolAddress, account, tokenId, existingPositionIds, positionSize, swapAtMint } =\n params\n\n try {\n // Build final position list (existing + new position)\n const finalPositionIdList = [...existingPositionIds, tokenId]\n\n // Build tick limits based on swapAtMint flag:\n // - swapAtMint=true: descending order (high, low) triggers SFPM swap\n // - swapAtMint=false: ascending order (low, high) no swap\n //\n // The third element is the per-position `effectiveLiquidityLimit` (denominated\n // X10_000 = removedLiquidity/netLiquidity ratio). For LONG legs the contract caps\n // the allowed spread at `min(effectiveLiquidityLimit, maxSpread())`\n // (PanopticPool._mintInSFPMAndUpdateCollateral / _checkLiquiditySpread). Passing 0\n // here forces the limit to 0, so ANY long-leg removal reverts with\n // EffectiveLiquidityAboveThreshold — which silently collapsed the max size for\n // multi-leg positions containing a long leg (e.g. spreads). Use the max int24 so the\n // contract clamps to its real on-chain `maxSpread()` ceiling, matching the live trade.\n const MAX_EFFECTIVE_LIQUIDITY_LIMIT = 8388607 // max int24 (2^23 - 1)\n const tickLimits: readonly [number, number, number] = swapAtMint\n ? [887272, -887272, MAX_EFFECTIVE_LIQUIDITY_LIMIT]\n : [-887272, 887272, MAX_EFFECTIVE_LIQUIDITY_LIMIT]\n\n // Encode dispatch call\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n [tokenId],\n finalPositionIdList,\n [positionSize as unknown as bigint & { readonly __uint128: true }],\n [tickLimits],\n true, // usePremiaAsCollateral\n 0n, // builderCode\n ],\n })\n\n // Use PanopticPool.multicall to simulate\n await client.simulateContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'multicall',\n args: [[callData]],\n account,\n })\n\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Parameters for getRequiredCreditForITM.\n */\nexport interface GetRequiredCreditForITMParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenId to check */\n tokenId: bigint\n /** Position size (number of contracts) */\n positionSize: bigint\n /** Existing position IDs held by the account (defaults to empty) */\n existingPositionIds?: bigint[]\n /** Optional block number for simulation */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Result for getRequiredCreditForITM.\n */\nexport interface RequiredCreditForITM {\n /**\n * Required credit in token0 to neutralize ITM exposure.\n * Positive = credit needed (deposit), negative = loan proceeds (receive).\n */\n creditAmount0: bigint\n /**\n * Required credit in token1 to neutralize ITM exposure.\n * Positive = credit needed (deposit), negative = loan proceeds (receive).\n */\n creditAmount1: bigint\n /** The raw token flow from simulation */\n tokenFlow: TokenFlow\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Get the required credit (or loan) amount for an ITM position.\n *\n * Simulates opening the position with swapAtMint=true (descending tickLimits)\n * to get single-sided token flow. The token flow represents the ITM amount\n * that would need to be neutralized with a credit (or loan if negative).\n *\n * @param params - The parameters\n * @returns Required credit amounts with token flow and block metadata\n * @throws PanopticError - If simulation fails\n *\n * @example\n * ```typescript\n * const result = await getRequiredCreditForITM({\n * client,\n * poolAddress,\n * account,\n * tokenId,\n * positionSize: 1n,\n * })\n *\n * if (result.creditAmount0 > 0n) {\n * console.log('Need credit of', result.creditAmount0, 'token0')\n * } else if (result.creditAmount0 < 0n) {\n * console.log('Position yields loan of', -result.creditAmount0, 'token0')\n * }\n * ```\n */\nexport async function getRequiredCreditForITM(\n params: GetRequiredCreditForITMParams,\n): Promise<RequiredCreditForITM> {\n const {\n client,\n poolAddress,\n account,\n tokenId,\n positionSize,\n existingPositionIds = [],\n blockNumber,\n } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Build final position list (existing + new position)\n const finalPositionIdList = [...existingPositionIds, tokenId]\n\n // Encode dispatch call with swapAtMint=true (descending tickLimits)\n // Descending order (MAX_TICK > MIN_TICK) triggers SFPM swap, giving single-sided token flow\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n [tokenId], // positionIdList: positions being minted\n finalPositionIdList,\n [positionSize as unknown as bigint & { readonly __uint128: true }],\n [[Number(MAX_TICK), Number(MIN_TICK), 0] as readonly [number, number, number]], // Descending = swapAtMint\n false, // usePremiaAsCollateral\n 0n, // builderCode\n ],\n })\n\n // Simulate with token flow measurement and get block meta in parallel\n const [result, _meta] = await Promise.all([\n simulateWithTokenFlow({\n client,\n poolAddress,\n user: account,\n callData,\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n if (!result.success || !result.tokenFlow) {\n throw new PanopticError(result.error ?? 'Token flow simulation failed')\n }\n\n // The token flow deltas represent the ITM amount:\n // - Negative delta = user deposits (credit needed)\n // - Positive delta = user receives (loan proceeds)\n // We invert the sign so positive = credit needed, negative = loan\n return {\n creditAmount0: -result.tokenFlow.delta0,\n creditAmount1: -result.tokenFlow.delta1,\n tokenFlow: result.tokenFlow,\n _meta,\n }\n}\n\n/**\n * Parameters for getMaxWithdrawable.\n */\nexport interface GetMaxWithdrawableParams {\n /** viem PublicClient */\n client: PublicClient\n /** CollateralTracker address */\n collateralTrackerAddress: Address\n /** Account address */\n account: Address\n /** Position IDs held by the account (required for solvency-checked withdraw) */\n positionIdList: bigint[]\n /** Upper bound for the binary search (e.g. user's total assets in this tracker) */\n totalAssets: bigint\n /** Whether to use premia as collateral (default: false) */\n usePremiaAsCollateral?: boolean\n /** Precision for binary search as percentage (default: 1 = 1%) */\n precisionPct?: number\n}\n\n/**\n * Find the maximum withdrawable amount from a CollateralTracker using binary search.\n *\n * When a user has open positions, the standard `maxWithdraw()` returns 0 because\n * the basic ERC4626 withdraw doesn't check solvency. The overloaded\n * `withdraw(assets, receiver, owner, positionIdList, usePremiaAsCollateral)` does\n * check solvency, so we binary search for the largest amount that doesn't revert.\n *\n * @param params - The parameters\n * @returns Maximum withdrawable amount in underlying asset units\n */\nexport async function getMaxWithdrawable(\n params: GetMaxWithdrawableParams,\n): Promise<{ maxWithdrawable: bigint; _meta: BlockMeta }> {\n const {\n client,\n collateralTrackerAddress,\n account,\n positionIdList,\n totalAssets,\n usePremiaAsCollateral = false,\n precisionPct = 1,\n } = params\n\n const _meta = await getBlockMeta({ client })\n\n if (totalAssets <= 0n || positionIdList.length === 0) {\n // No positions: use the standard maxWithdraw\n const maxWithdraw = await client.readContract({\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'maxWithdraw',\n args: [account],\n })\n return { maxWithdrawable: maxWithdraw, _meta }\n }\n\n const precisionDivisor = BigInt(Math.floor(100 / precisionPct))\n let low = 0n\n let high = totalAssets\n\n while (high - low > 1n && high - low > low / precisionDivisor) {\n const mid = low + (high - low) / 2n\n\n const success = await tryWithdrawSimulation({\n client,\n collateralTrackerAddress,\n account,\n assets: mid,\n positionIdList,\n usePremiaAsCollateral,\n })\n\n if (success) {\n low = mid\n } else {\n high = mid\n }\n }\n\n return { maxWithdrawable: low, _meta }\n}\n\n/**\n * Try to simulate a solvency-checked withdraw with the given amount.\n */\nasync function tryWithdrawSimulation(params: {\n client: PublicClient\n collateralTrackerAddress: Address\n account: Address\n assets: bigint\n positionIdList: bigint[]\n usePremiaAsCollateral: boolean\n}): Promise<boolean> {\n const {\n client,\n collateralTrackerAddress,\n account,\n assets,\n positionIdList,\n usePremiaAsCollateral,\n } = params\n\n try {\n await client.estimateContractGas({\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'withdraw',\n args: [assets, account, account, positionIdList, usePremiaAsCollateral],\n account,\n })\n return true\n } catch {\n return false\n }\n}\n","/**\n * ERC4626 vault preview functions for the Panoptic v2 SDK.\n *\n * The CollateralTracker contract implements ERC4626, providing standard\n * vault functionality for depositing/withdrawing collateral.\n *\n * @module v2/reads/erc4626\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport type { BlockMeta } from '../types'\n\n/**\n * Parameters for ERC4626 preview functions.\n */\nexport interface ERC4626PreviewParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Which token's collateral tracker to query (0 or 1) */\n tokenIndex: 0 | 1\n /** Amount to preview */\n amount: bigint\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched collateral tracker address */\n collateralTrackerAddress?: Address\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * ERC4626 preview result.\n */\nexport interface ERC4626PreviewResult {\n /** The resulting amount (shares or assets depending on function) */\n result: bigint\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Helper to get collateral tracker address.\n */\nasync function getCollateralTrackerAddress(\n client: PublicClient,\n poolAddress: Address,\n tokenIndex: 0 | 1,\n providedAddress?: Address,\n): Promise<Address> {\n if (providedAddress) return providedAddress\n\n return client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: tokenIndex === 0 ? 'collateralToken0' : 'collateralToken1',\n })\n}\n\n/**\n * Preview the amount of shares that would be minted for a deposit.\n *\n * @param params - The parameters\n * @returns Preview result with block metadata\n */\nexport async function previewDeposit(params: ERC4626PreviewParams): Promise<ERC4626PreviewResult> {\n const { client, poolAddress, tokenIndex, amount, blockNumber, collateralTrackerAddress } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n const trackerAddress = await getCollateralTrackerAddress(\n client,\n poolAddress,\n tokenIndex,\n collateralTrackerAddress,\n )\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'previewDeposit',\n args: [amount],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n return { result, _meta }\n}\n\n/**\n * Preview the amount of assets that would be returned for a withdrawal.\n *\n * @param params - The parameters\n * @returns Preview result with block metadata\n */\nexport async function previewWithdraw(params: ERC4626PreviewParams): Promise<ERC4626PreviewResult> {\n const { client, poolAddress, tokenIndex, amount, blockNumber, collateralTrackerAddress } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n const trackerAddress = await getCollateralTrackerAddress(\n client,\n poolAddress,\n tokenIndex,\n collateralTrackerAddress,\n )\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'previewWithdraw',\n args: [amount],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n return { result, _meta }\n}\n\n/**\n * Preview the amount of assets required for a mint.\n *\n * @param params - The parameters\n * @returns Preview result with block metadata\n */\nexport async function previewMint(params: ERC4626PreviewParams): Promise<ERC4626PreviewResult> {\n const { client, poolAddress, tokenIndex, amount, blockNumber, collateralTrackerAddress } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n const trackerAddress = await getCollateralTrackerAddress(\n client,\n poolAddress,\n tokenIndex,\n collateralTrackerAddress,\n )\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'previewMint',\n args: [amount],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n return { result, _meta }\n}\n\n/**\n * Preview the amount of shares that would be burned for a redeem.\n *\n * @param params - The parameters\n * @returns Preview result with block metadata\n */\nexport async function previewRedeem(params: ERC4626PreviewParams): Promise<ERC4626PreviewResult> {\n const { client, poolAddress, tokenIndex, amount, blockNumber, collateralTrackerAddress } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n const trackerAddress = await getCollateralTrackerAddress(\n client,\n poolAddress,\n tokenIndex,\n collateralTrackerAddress,\n )\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'previewRedeem',\n args: [amount],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n return { result, _meta }\n}\n\n/**\n * Convert an amount of assets to shares.\n *\n * @param params - The parameters\n * @returns Conversion result with block metadata\n */\nexport async function convertToShares(params: ERC4626PreviewParams): Promise<ERC4626PreviewResult> {\n const { client, poolAddress, tokenIndex, amount, blockNumber, collateralTrackerAddress } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n const trackerAddress = await getCollateralTrackerAddress(\n client,\n poolAddress,\n tokenIndex,\n collateralTrackerAddress,\n )\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'convertToShares',\n args: [amount],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n return { result, _meta }\n}\n\n/**\n * Convert an amount of shares to assets.\n *\n * @param params - The parameters\n * @returns Conversion result with block metadata\n */\nexport async function convertToAssets(params: ERC4626PreviewParams): Promise<ERC4626PreviewResult> {\n const { client, poolAddress, tokenIndex, amount, blockNumber, collateralTrackerAddress } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n const trackerAddress = await getCollateralTrackerAddress(\n client,\n poolAddress,\n tokenIndex,\n collateralTrackerAddress,\n )\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'convertToAssets',\n args: [amount],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n return { result, _meta }\n}\n","/**\n * PanopticGuardian read functions for the Panoptic v2 SDK.\n *\n * The Guardian can lock a pool into close-only mode. Unlocking is a two-step\n * timelocked flow: `requestUnlock(pool)` schedules an unlock ETA, and after the\n * ETA matures `executeUnlock(pool)` clears the lock. This module reads the\n * pending-unlock state so the UI can surface a countdown while a pool is locked.\n *\n * @module v2/reads/guardian\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticGuardianAbi, panopticPoolV2Abi, riskEngineAbi } from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport type { BlockMeta } from '../types'\n\n/**\n * Parameters for getGuardianUnlockState.\n */\nexport interface GetGuardianUnlockStateParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Optional RiskEngine address (skips the pool.riskEngine() read) */\n riskEngineAddress?: Address\n /** Optional PanopticGuardian address (skips the riskEngine.GUARDIAN() read) */\n guardianAddress?: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Guardian pool-unlock state.\n */\nexport interface GuardianUnlockState {\n /** Resolved PanopticGuardian contract address */\n guardianAddress: Address\n /** Unlock ETA as a Unix timestamp (seconds); 0n when no unlock is pending */\n unlockEta: bigint\n /** True when an unlock has been requested but not yet executed */\n hasPendingUnlock: boolean\n /** True when the pending unlock's timelock has elapsed and it can be executed */\n isReady: boolean\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Read the Guardian pending-unlock state for a pool.\n *\n * Resolves the Guardian address from the pool's RiskEngine when not provided,\n * then reads `unlockEta` and `isPoolUnlockReady` from the PanopticGuardian in a\n * single multicall pinned to the same block.\n *\n * @param params - The parameters\n * @returns Guardian unlock state with block metadata\n */\nexport async function getGuardianUnlockState(\n params: GetGuardianUnlockStateParams,\n): Promise<GuardianUnlockState> {\n const { client, poolAddress, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Only reuse caller-supplied metadata when it matches the block we read at,\n // otherwise data and metadata would come from different blocks.\n const reusableMeta =\n params._meta && params._meta.blockNumber === targetBlockNumber ? params._meta : undefined\n\n // Resolve the RiskEngine (immutable) unless caller supplied it.\n const riskEngineAddress =\n params.riskEngineAddress ??\n (await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'riskEngine',\n blockNumber: targetBlockNumber,\n }))\n\n // Resolve the Guardian (immutable) unless caller supplied it.\n const guardianAddress =\n params.guardianAddress ??\n (await client.readContract({\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'GUARDIAN',\n blockNumber: targetBlockNumber,\n }))\n\n const [results, _meta] = await Promise.all([\n client.multicall({\n contracts: [\n {\n address: guardianAddress,\n abi: panopticGuardianAbi,\n functionName: 'unlockEta',\n args: [poolAddress],\n },\n {\n address: guardianAddress,\n abi: panopticGuardianAbi,\n functionName: 'isPoolUnlockReady',\n args: [poolAddress],\n },\n ],\n blockNumber: targetBlockNumber,\n allowFailure: false,\n }),\n reusableMeta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const [unlockEta, isReady] = results\n\n return {\n guardianAddress,\n unlockEta,\n hasPendingUnlock: unlockEta > 0n,\n isReady,\n _meta,\n }\n}\n","/**\n * Safe mode check functions for the Panoptic v2 SDK.\n *\n * Safe mode is a protective mechanism that activates when pool conditions\n * become dangerous (e.g., extreme price movements or liquidity issues).\n *\n * @module v2/reads/safeMode\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport type { BlockMeta, SafeModeState as OracleSafeModeState } from '../types'\n\n/**\n * Safe mode status values.\n */\nexport const SafeModeStatus = {\n /** Pool is operating normally */\n NORMAL: 0n,\n /** No new leveraged positions allowed */\n NO_LEVERAGE: 1n,\n /** No swaps allowed */\n NO_SWAP: 2n,\n /** Close-only mode */\n CLOSE_ONLY: 3n,\n} as const\n\nexport type SafeModeStatusValue = (typeof SafeModeStatus)[keyof typeof SafeModeStatus]\n\n/**\n * Safe mode state for bot preflight and operation guards.\n */\nexport type SafeModeState = OracleSafeModeState\n\n/**\n * Parameters for getSafeMode.\n */\nexport interface GetSafeModeParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get the current safe mode status of a pool.\n *\n * Safe mode is activated when:\n * - Pool liquidity drops below safe thresholds\n * - Price volatility exceeds safe limits\n * - Administrative pause is triggered\n *\n * @param params - The parameters\n * @returns Safe mode state with block metadata\n */\nexport async function getSafeMode(params: GetSafeModeParams): Promise<SafeModeState> {\n const { client, poolAddress, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n const [safeModeRaw, _meta] = await Promise.all([\n client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'isSafeMode',\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // isSafeMode returns uint8:\n // 0 = normal, 1 = no leverage, 2 = no swap, 3 = close only\n const status = BigInt(safeModeRaw) as SafeModeStatusValue\n\n switch (status) {\n case SafeModeStatus.NO_LEVERAGE:\n return {\n mode: 'restricted',\n canMint: true,\n canBurn: true,\n canForceExercise: true,\n canLiquidate: true,\n canSwapAtMint: true,\n reason: 'All positions require 100% collateral',\n _meta,\n }\n case SafeModeStatus.NO_SWAP:\n return {\n mode: 'restricted',\n canMint: true,\n canBurn: true,\n canForceExercise: true,\n canLiquidate: true,\n canSwapAtMint: false,\n reason: 'Swaps are disabled',\n _meta,\n }\n case SafeModeStatus.CLOSE_ONLY:\n return {\n mode: 'emergency',\n canMint: false,\n canBurn: true,\n canForceExercise: true,\n canLiquidate: true,\n canSwapAtMint: false,\n reason: 'Pool is in close-only mode',\n _meta,\n }\n default:\n return {\n mode: 'normal',\n canMint: true,\n canBurn: true,\n canForceExercise: true,\n canLiquidate: true,\n canSwapAtMint: true,\n _meta,\n }\n }\n}\n","/**\n * Additional utility functions using PanopticQuery contract.\n *\n * These functions provide enhanced analysis capabilities for portfolio management,\n * risk visualization, and TokenId optimization.\n *\n * @module v2/reads/queryUtils\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { panopticQueryAbi } from '../abis/panopticQuery'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport type { BlockMeta } from '../types'\n\n/**\n * Portfolio value result (without premia).\n */\nexport interface PortfolioValue {\n /** Value in token 0 */\n value0: bigint\n /** Value in token 1 */\n value1: bigint\n /** Tick at which value was calculated */\n atTick: bigint\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for getPortfolioValue.\n */\nexport interface GetPortfolioValueParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenIds of open positions */\n tokenIds: bigint[]\n /** Optional: Tick to calculate value at (defaults to current tick) */\n atTick?: bigint\n /** PanopticQuery address (required for this function) */\n queryAddress: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get portfolio value (NAV) without premia.\n *\n * This calculates the net asset value of the portfolio based on Uniswap liquidity\n * at a given tick, excluding accumulated premia. Useful for PnL tracking separate\n * from liquidation value.\n *\n * ## Same-Block Guarantee\n * All data is fetched at a single block.\n *\n * @param params - The parameters\n * @returns Portfolio value with block metadata\n */\nexport async function getPortfolioValue(params: GetPortfolioValueParams): Promise<PortfolioValue> {\n const { client, poolAddress, account, tokenIds, atTick, queryAddress, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Skip getCurrentTick RPC call when atTick is provided\n const [currentTickResult, _meta] = await Promise.all([\n atTick != null\n ? Promise.resolve(atTick)\n : client\n .readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n blockNumber: targetBlockNumber,\n })\n .then((r) => BigInt(r)),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const effectiveTick = currentTickResult\n\n const result = await client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getPortfolioValue',\n args: [poolAddress, account, Number(effectiveTick), tokenIds],\n blockNumber: targetBlockNumber,\n })\n\n const [value0, value1] = result\n\n return {\n value0,\n value1,\n atTick: effectiveTick,\n _meta,\n }\n}\n\n/**\n * Collateral data point across tick range.\n */\nexport interface CollateralDataPoint {\n /** Tick value */\n tick: bigint\n /** Collateral balance at this tick */\n balance: bigint\n /** Required collateral at this tick */\n required: bigint\n}\n\n/**\n * Collateral analysis across tick range result.\n */\nexport interface CollateralAcrossTicks {\n /** Array of data points (301 points from liquidation range) */\n dataPoints: CollateralDataPoint[]\n /** Liquidation price below current (null if none) */\n liquidationPriceDown: bigint | null\n /** Liquidation price above current (null if none) */\n liquidationPriceUp: bigint | null\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for checkCollateralAcrossTicks.\n */\nexport interface CheckCollateralAcrossTicksParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenIds of open positions */\n tokenIds: bigint[]\n /** PanopticQuery address (required for this function) */\n queryAddress: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Check collateral balance vs requirement across a range of ticks.\n *\n * This function returns 301 data points spanning a range around the current price,\n * including liquidation prices. Perfect for charting liquidation risk in a UI.\n *\n * ## Same-Block Guarantee\n * All data is fetched at a single block.\n *\n * @param params - The parameters\n * @returns Collateral analysis across ticks with block metadata\n */\nexport async function checkCollateralAcrossTicks(\n params: CheckCollateralAcrossTicksParams,\n): Promise<CollateralAcrossTicks> {\n const { client, poolAddress, account, tokenIds, queryAddress, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'checkCollateralListOutput',\n args: [poolAddress, account, tokenIds],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const [balanceRequired, tickData, liquidationPrices] = result\n\n // MIN_TICK and MAX_TICK indicate no liquidation at that boundary\n const MIN_TICK = -887272n\n const MAX_TICK = 887272n\n\n // Convert to data points\n const dataPoints: CollateralDataPoint[] = balanceRequired.map((point, index) => ({\n tick: BigInt(tickData[index]),\n balance: point[0],\n required: point[1],\n }))\n\n // Convert from number (abitype default for int24) to bigint (viem runtime type)\n const liqPriceDown = BigInt(liquidationPrices[0])\n const liqPriceUp = BigInt(liquidationPrices[1])\n\n return {\n dataPoints,\n liquidationPriceDown: liqPriceDown === MIN_TICK ? null : liqPriceDown,\n liquidationPriceUp: liqPriceUp === MAX_TICK ? null : liqPriceUp,\n _meta,\n }\n}\n\n/**\n * Parameters for optimizeTokenIdRiskPartners.\n */\nexport interface OptimizeTokenIdRiskPartnersParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** TokenId to optimize */\n tokenId: bigint\n /** Optional: Tick to optimize at (defaults to current tick) */\n atTick?: bigint\n /** PanopticQuery address (required for this function) */\n queryAddress: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Optimize risk partner assignments for a TokenId.\n *\n * Tests all valid risk partner permutations and returns the TokenId with\n * the lowest collateral requirement. Useful when building positions to\n * maximize capital efficiency.\n *\n * ## Same-Block Guarantee\n * Optimization is performed at a single block.\n *\n * Note: Only works for tokenIds with 2+ legs. Single-leg positions return unchanged.\n *\n * @param params - The parameters\n * @returns Optimized TokenId\n */\nexport async function optimizeTokenIdRiskPartners(\n params: OptimizeTokenIdRiskPartnersParams,\n): Promise<bigint> {\n const { client, poolAddress, tokenId, atTick, queryAddress, blockNumber } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n\n // Get current tick if not provided\n let effectiveTick: bigint\n if (atTick !== undefined) {\n effectiveTick = atTick\n } else {\n const currentTickResult = await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n blockNumber: targetBlockNumber,\n })\n // Bridge type from panopticPoolV2Abi (number | bigint) to bigint\n effectiveTick = BigInt(currentTickResult)\n }\n\n const optimizedTokenId = await client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'optimizeRiskPartners',\n args: [poolAddress, Number(effectiveTick), tokenId],\n blockNumber: targetBlockNumber,\n })\n\n return optimizedTokenId\n}\n","/**\n * Pool liquidity distribution read function using PanopticQuery.\n *\n * @module v2/reads/liquidity\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticQueryAbi } from '../abis/panopticQuery'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport type { BlockMeta } from '../types'\n\n/**\n * Result of getPoolLiquidities.\n */\nexport interface PoolLiquidities {\n /** Tick values for each data point */\n ticks: bigint[]\n /** Net liquidity at each tick */\n liquidityNets: bigint[]\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for getPoolLiquidities.\n */\nexport interface GetPoolLiquiditiesParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** PanopticQuery address */\n queryAddress: Address\n /** Starting tick of the range */\n startTick: bigint\n /** Number of ticks to query */\n nTicks: bigint\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get cumulative liquidity distribution across a tick range.\n *\n * Wraps `PanopticQuery.getTickNets()` to return tick data and net liquidity\n * for each tick in the specified range.\n *\n * ## Same-Block Guarantee\n * All data is fetched at a single block.\n *\n * @param params - The parameters\n * @returns Tick data and liquidity nets with block metadata\n */\nexport async function getPoolLiquidities(\n params: GetPoolLiquiditiesParams,\n): Promise<PoolLiquidities> {\n const { client, poolAddress, queryAddress, startTick, nTicks, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getTickNets',\n args: [poolAddress, Number(startTick), nTicks],\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const [tickData, liquidityNets] = result\n\n return {\n ticks: [...tickData],\n liquidityNets: [...liquidityNets],\n _meta,\n }\n}\n","/**\n * Percentage and ratio formatters.\n *\n * All formatters require explicit precision - no hidden defaults.\n *\n * @module v2/formatters/percentage\n */\n\nconst TEN = 10n\n\nfunction formatRatio(numerator: bigint, denominator: bigint, precision: bigint): string {\n if (precision < 0n) {\n throw new RangeError('Precision must be non-negative')\n }\n\n if (denominator === 0n) {\n return '0'\n }\n\n const isNegative = numerator < 0n !== denominator < 0n\n const absNumerator = numerator < 0n ? -numerator : numerator\n const absDenominator = denominator < 0n ? -denominator : denominator\n\n const scale = TEN ** precision\n const scaled = (absNumerator * scale + absDenominator / 2n) / absDenominator\n const integerPart = scaled / scale\n const fractionalPart = scaled % scale\n const sign = isNegative ? '-' : ''\n\n if (precision === 0n) {\n return `${sign}${integerPart}`\n }\n\n return `${sign}${integerPart}.${fractionalPart.toString().padStart(Number(precision), '0')}`\n}\n\n/**\n * Format basis points as a percentage string.\n * 100 bps = 1%\n *\n * @param bps - Basis points value\n * @param precision - Number of decimal places to display\n * @returns Formatted percentage string\n *\n * @example\n * ```typescript\n * formatBps(50n, 2n) // \"0.50%\"\n * formatBps(50n, 1n) // \"0.5%\"\n * formatBps(100n, 2n) // \"1.00%\"\n * formatBps(1500n, 2n) // \"15.00%\"\n * formatBps(-50n, 2n) // \"-0.50%\"\n * ```\n */\nexport function formatBps(bps: bigint, precision: bigint): string {\n const isNegative = bps < 0n\n const absBps = isNegative ? -bps : bps\n\n // bps to percentage: divide by 100\n // Scale up for precision, then divide\n const scaleFactor = 10n ** precision\n const scaled = (absBps * scaleFactor) / 100n\n const integerPart = scaled / scaleFactor\n const fractionalPart = scaled % scaleFactor\n\n const fractionalStr = fractionalPart.toString().padStart(Number(precision), '0')\n const sign = isNegative ? '-' : ''\n\n return precision > 0n ? `${sign}${integerPart}.${fractionalStr}%` : `${sign}${integerPart}%`\n}\n\n/**\n * Format utilization as a percentage string.\n * Utilization is stored as 0n-10000n, where 10000n = 100%.\n *\n * @param util - Utilization value (0-10000)\n * @param precision - Number of decimal places to display\n * @returns Formatted percentage string\n *\n * @example\n * ```typescript\n * formatUtilization(7500n, 2n) // \"75.00%\"\n * formatUtilization(7500n, 0n) // \"75%\"\n * formatUtilization(10000n, 2n) // \"100.00%\"\n * formatUtilization(123n, 2n) // \"1.23%\"\n * ```\n */\nexport function formatUtilization(util: bigint, precision: bigint): string {\n // util is in basis points (10000 = 100%)\n return formatBps(util, precision)\n}\n\n/**\n * Parse a percentage string to basis points.\n *\n * @param percent - Percentage string (e.g., \"1.5%\" or \"1.5\")\n * @returns Basis points value\n *\n * @example\n * ```typescript\n * parseBps(\"1.5%\") // 150n\n * parseBps(\"1.5\") // 150n\n * parseBps(\"100%\") // 10000n\n * parseBps(\"0.5%\") // 50n\n * ```\n */\nexport function parseBps(percent: string): bigint {\n // Remove % suffix if present\n const cleaned = percent.trim().replace(/%$/, '')\n const isNegative = cleaned.startsWith('-')\n const absValue = isNegative ? cleaned.slice(1) : cleaned\n\n const [integerStr, fractionalStr = ''] = absValue.split('.')\n\n // Convert to basis points: multiply by 100\n // Handle up to 2 decimal places in the percentage\n const paddedFractional = fractionalStr.padEnd(2, '0').slice(0, 2)\n\n const integerPart = BigInt(integerStr || '0') * 100n\n const fractionalPart = BigInt(paddedFractional || '0')\n\n const result = integerPart + fractionalPart\n return isNegative ? -result : result\n}\n\n/**\n * Format a ratio as a percentage string.\n *\n * @param numerator - Numerator of the ratio\n * @param denominator - Denominator of the ratio\n * @param precision - Number of decimal places to display\n * @returns Formatted percentage string\n *\n * @example\n * ```typescript\n * formatRatioPercent(1n, 4n, 1n) // \"25.0%\"\n * formatRatioPercent(3n, 4n, 2n) // \"75.00%\"\n * ```\n */\nexport function formatRatioPercent(\n numerator: bigint,\n denominator: bigint,\n precision: bigint,\n): string {\n const scaledNumerator = numerator * 100n\n return `${formatRatio(scaledNumerator, denominator, precision)}%`\n}\n","/**\n * Pool-bound formatters factory.\n *\n * Creates formatter functions that capture pool context (token decimals)\n * for less verbose call sites in single-pool UI components.\n *\n * @module v2/formatters/poolFormatters\n */\n\nimport { formatTokenAmount, parseTokenAmount } from './amount'\nimport { priceToTick, tickToPrice, tickToPriceDecimalScaled } from './tick'\n\n/**\n * Pool-bound formatters interface.\n *\n * These formatters capture the pool's token decimals, so you don't need\n * to pass them at every call site.\n */\nexport interface PoolFormatters {\n /** Token0 decimals */\n readonly decimals0: bigint\n /** Token1 decimals */\n readonly decimals1: bigint\n\n /**\n * Convert tick to raw price (1.0001^tick).\n */\n tickToPrice(tick: bigint): string\n\n /**\n * Convert tick to decimal-scaled price (token1 per token0).\n */\n tickToPriceScaled(tick: bigint, precision: bigint): string\n\n /**\n * Convert tick to decimal-scaled inverse price (token0 per token1).\n */\n tickToInversePriceScaled(tick: bigint, precision: bigint): string\n\n /**\n * Convert a price (token1 per token0) to tick.\n */\n priceToTick(price: string): bigint\n\n /**\n * Format token0 amount with specified precision.\n */\n formatAmount0(amount: bigint, precision: bigint): string\n\n /**\n * Format token1 amount with specified precision.\n */\n formatAmount1(amount: bigint, precision: bigint): string\n\n /**\n * Parse token0 amount string to raw units.\n */\n parseAmount0(amount: string): bigint\n\n /**\n * Parse token1 amount string to raw units.\n */\n parseAmount1(amount: string): bigint\n}\n\n/**\n * Pool metadata required to create pool-bound formatters.\n */\nexport interface PoolFormatterConfig {\n /** Token0 decimals */\n decimals0: bigint\n /** Token1 decimals */\n decimals1: bigint\n}\n\n/**\n * Create pool-bound formatters that capture token decimals.\n *\n * Use this factory when working with a single pool to avoid passing\n * decimals at every call site.\n *\n * @param config - Pool configuration with token decimals\n * @returns Pool-bound formatter functions\n *\n * @example\n * ```typescript\n * // Get pool data\n * const pool = await getPool({ client, poolAddress })\n *\n * // Create formatters bound to this pool\n * const fmt = createPoolFormatters({\n * decimals0: pool.token0Decimals,\n * decimals1: pool.token1Decimals,\n * })\n *\n * // Now use without passing decimals each time\n * const priceStr = fmt.tickToPriceScaled(position.currentTick, 4n)\n * const amount0Str = fmt.formatAmount0(collateral.assets, 4n)\n * const amount1Str = fmt.formatAmount1(premia.token1, 2n)\n *\n * // Parse user input\n * const rawAmount0 = fmt.parseAmount0(\"1.5\")\n * const rawAmount1 = fmt.parseAmount1(\"3000\")\n * ```\n */\nexport function createPoolFormatters(config: PoolFormatterConfig): PoolFormatters {\n const { decimals0, decimals1 } = config\n\n return {\n decimals0,\n decimals1,\n\n tickToPrice(tick: bigint): string {\n return tickToPrice(tick)\n },\n\n tickToPriceScaled(tick: bigint, precision: bigint): string {\n return tickToPriceDecimalScaled(tick, decimals0, decimals1, precision)\n },\n\n tickToInversePriceScaled(tick: bigint, precision: bigint): string {\n // Swap decimals for inverse price\n return tickToPriceDecimalScaled(tick, decimals1, decimals0, precision)\n },\n\n priceToTick(price: string): bigint {\n return priceToTick(price, decimals0, decimals1)\n },\n\n formatAmount0(amount: bigint, precision: bigint): string {\n return formatTokenAmount(amount, decimals0, precision)\n },\n\n formatAmount1(amount: bigint, precision: bigint): string {\n return formatTokenAmount(amount, decimals1, precision)\n },\n\n parseAmount0(amount: string): bigint {\n return parseTokenAmount(amount, decimals0)\n },\n\n parseAmount1(amount: string): bigint {\n return parseTokenAmount(amount, decimals1)\n },\n }\n}\n","/**\n * Token list integration utilities.\n *\n * Provides helpers for integrating with standard token lists\n * (e.g., Uniswap token list, CoinGecko token list).\n *\n * @module v2/formatters/tokenList\n */\n\nimport type { Address } from 'viem'\n\nconst TEN = 10n\n\nfunction formatRatio(numerator: bigint, denominator: bigint, precision: bigint): string {\n if (precision < 0n) {\n throw new RangeError('Precision must be non-negative')\n }\n\n const scale = TEN ** precision\n const scaled = (numerator * scale + denominator / 2n) / denominator\n const integerPart = scaled / scale\n const fractionalPart = scaled % scale\n\n if (precision === 0n) {\n return integerPart.toString()\n }\n\n return `${integerPart}.${fractionalPart.toString().padStart(Number(precision), '0')}`\n}\n\n/**\n * Generate a token list ID for external token list integration.\n *\n * Token lists use a standardized format: `chainId:address`\n * This is compatible with most token list standards.\n *\n * @param chainId - The chain ID\n * @param address - The token address\n * @returns Token list ID string\n *\n * @example\n * ```typescript\n * getTokenListId(1n, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2')\n * // \"1:0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\"\n *\n * getTokenListId(11155111n, '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14')\n * // \"11155111:0xfff9976782d46cc05630d1f6ebab18b2324d6b14\"\n * ```\n */\nexport function getTokenListId(chainId: bigint, address: Address): string {\n return `${chainId}:${address.toLowerCase()}`\n}\n\n/**\n * Parse a token list ID back to chain ID and address.\n *\n * @param tokenListId - The token list ID string\n * @returns Object with chainId and address\n *\n * @example\n * ```typescript\n * parseTokenListId(\"1:0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\")\n * // { chainId: 1n, address: \"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\" }\n * ```\n */\nexport function parseTokenListId(tokenListId: string): {\n chainId: bigint\n address: Address\n} {\n const [chainIdStr, address] = tokenListId.split(':')\n if (!chainIdStr || !address) {\n throw new Error(`Invalid token list ID: ${tokenListId}`)\n }\n return {\n chainId: BigInt(chainIdStr),\n address: address as Address,\n }\n}\n\n/**\n * Generate a pool ID string for display purposes.\n *\n * @param token0Symbol - Symbol of token0\n * @param token1Symbol - Symbol of token1\n * @param feeBps - Fee in basis points (e.g., 500n for 0.05%)\n * @returns Pool ID string\n *\n * @example\n * ```typescript\n * getPoolDisplayId('WETH', 'USDC', 500n)\n * // \"WETH/USDC 0.05%\"\n *\n * getPoolDisplayId('WBTC', 'ETH', 3000n)\n * // \"WBTC/ETH 0.30%\"\n * ```\n */\nexport function getPoolDisplayId(\n token0Symbol: string,\n token1Symbol: string,\n feeBps: bigint,\n): string {\n return `${token0Symbol}/${token1Symbol} ${formatFeeTier(feeBps)}`\n}\n\n/**\n * Format a fee tier for display.\n *\n * @param feeBps - Fee in basis points (e.g., 500n for 0.05%)\n * @returns Fee tier string\n *\n * @example\n * ```typescript\n * formatFeeTier(500n) // \"0.05%\"\n * formatFeeTier(3000n) // \"0.30%\"\n * formatFeeTier(10000n) // \"1.0%\"\n * ```\n */\nexport function formatFeeTier(feeBps: bigint): string {\n const precision = feeBps < 10000n ? 2n : 1n\n const feeStr = formatRatio(feeBps, 10_000n, precision)\n return `${feeStr}%`\n}\n","/**\n * General display formatters for UI components.\n *\n * These are utility formatters for common display needs like\n * addresses, timestamps, and durations.\n *\n * @module v2/formatters/display\n */\n\nimport { formatTokenAmount } from './amount'\n\nconst TEN = 10n\n\nfunction formatRatio(numerator: bigint, denominator: bigint, precision: bigint): string {\n if (precision < 0n) {\n throw new RangeError('Precision must be non-negative')\n }\n\n const scale = TEN ** precision\n const scaled = (numerator * scale + denominator / 2n) / denominator\n const integerPart = scaled / scale\n const fractionalPart = scaled % scale\n\n if (precision === 0n) {\n return integerPart.toString()\n }\n\n return `${integerPart}.${fractionalPart.toString().padStart(Number(precision), '0')}`\n}\n\n/**\n * Truncate an address for display.\n *\n * @param address - Full address\n * @param chars - Characters to show on each side (default: 4)\n * @returns Truncated address like \"0x1234...5678\"\n *\n * @example\n * ```typescript\n * truncateAddress('0x1234567890abcdef1234567890abcdef12345678')\n * // \"0x1234...5678\"\n *\n * truncateAddress('0x1234567890abcdef1234567890abcdef12345678', 6)\n * // \"0x123456...345678\"\n * ```\n */\nexport function truncateAddress(address: string, chars = 4): string {\n const charsBig = BigInt(chars)\n const minLength = charsBig * 2n + 4n\n if (BigInt(address.length) <= minLength) return address\n return `${address.slice(0, Number(charsBig + 2n))}...${address.slice(-Number(charsBig))}`\n}\n\n/**\n * Format a Unix timestamp as an ISO date string (YYYY-MM-DD).\n *\n * @param timestamp - Unix timestamp in seconds\n * @returns ISO date string\n *\n * @example\n * ```typescript\n * formatTimestamp(1700000000n) // \"2023-11-14\"\n * ```\n */\nexport function formatTimestamp(timestamp: bigint): string {\n const ms = timestamp * 1000n\n return new Date(Number(ms)).toISOString().split('T')[0]\n}\n\n/**\n * Format a Unix timestamp as an ISO datetime string.\n *\n * @param timestamp - Unix timestamp in seconds\n * @returns ISO datetime string\n *\n * @example\n * ```typescript\n * formatDatetime(1700000000n) // \"2023-11-14T22:13:20.000Z\"\n * ```\n */\nexport function formatDatetime(timestamp: bigint): string {\n const ms = timestamp * 1000n\n return new Date(Number(ms)).toISOString()\n}\n\n/**\n * Format a Unix timestamp as a locale-aware date string.\n *\n * @param timestamp - Unix timestamp in seconds\n * @param locale - Locale string (default: system locale)\n * @param options - Intl.DateTimeFormat options\n * @returns Formatted date string\n *\n * @example\n * ```typescript\n * formatTimestampLocale(1700000000n)\n * // \"11/14/2023\" (US locale)\n *\n * formatTimestampLocale(1700000000n, 'de-DE')\n * // \"14.11.2023\" (German locale)\n * ```\n */\nexport function formatTimestampLocale(\n timestamp: bigint,\n locale?: string,\n options?: Intl.DateTimeFormatOptions,\n): string {\n const ms = timestamp * 1000n\n return new Date(Number(ms)).toLocaleDateString(locale, options)\n}\n\n/**\n * Format a duration in milliseconds as a human-readable string.\n *\n * @param ms - Duration in milliseconds\n * @returns Formatted duration string\n *\n * @example\n * ```typescript\n * formatDuration(1500n) // \"1.5s\"\n * formatDuration(150n) // \"150ms\"\n * formatDuration(90000n) // \"1m 30s\"\n * formatDuration(3661000n) // \"1h 1m\"\n * ```\n */\nexport function formatDuration(ms: bigint): string {\n const isNegative = ms < 0n\n const absMs = isNegative ? -ms : ms\n const sign = isNegative ? '-' : ''\n\n if (absMs < 1000n) {\n return `${sign}${absMs}ms`\n }\n\n if (absMs < 60000n) {\n const tenthsTotal = (absMs + 50n) / 100n\n const seconds = tenthsTotal / 10n\n const tenths = tenthsTotal % 10n\n return `${sign}${seconds}.${tenths}s`\n }\n\n if (absMs < 3600000n) {\n const minutes = absMs / 60000n\n const seconds = ((absMs % 60000n) + 500n) / 1000n\n return seconds > 0n ? `${sign}${minutes}m ${seconds}s` : `${sign}${minutes}m`\n }\n\n const hours = absMs / 3600000n\n const minutes = ((absMs % 3600000n) + 30000n) / 60000n\n return minutes > 0n ? `${sign}${hours}h ${minutes}m` : `${sign}${hours}h`\n}\n\n/**\n * Format a duration in seconds as a human-readable string.\n *\n * @param seconds - Duration in seconds\n * @returns Formatted duration string\n */\nexport function formatDurationSeconds(seconds: bigint): string {\n return formatDuration(seconds * 1000n)\n}\n\n/**\n * Format a block number for display.\n *\n * @param blockNumber - The block number\n * @returns Formatted block number with commas\n *\n * @example\n * ```typescript\n * formatBlockNumber(18000000n) // \"18,000,000\"\n * ```\n */\nexport function formatBlockNumber(blockNumber: bigint): string {\n return blockNumber.toLocaleString()\n}\n\n/**\n * Format a gas amount for display.\n *\n * @param gas - Gas units\n * @returns Formatted gas string\n */\nexport function formatGas(gas: bigint): string {\n return gas.toLocaleString()\n}\n\n/**\n * Format a transaction hash for display (truncated).\n *\n * @param hash - Full transaction hash\n * @param chars - Characters to show on each side (default: 6)\n * @returns Truncated hash like \"0x123456...abcdef\"\n *\n * @example\n * ```typescript\n * formatTxHash('0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef')\n * // \"0x123456...abcdef\"\n * ```\n */\nexport function formatTxHash(hash: string, chars = 6): string {\n const charsBig = BigInt(chars)\n const minLength = charsBig * 2n + 4n\n if (BigInt(hash.length) <= minLength) return hash\n return `${hash.slice(0, Number(charsBig + 2n))}...${hash.slice(-Number(charsBig))}`\n}\n\nfunction formatHex(value: bigint): string {\n return `0x${value.toString(16)}`\n}\n\n/**\n * Format a TokenId as a hex string.\n *\n * @param tokenId - TokenId value\n * @returns Hex string representation\n */\nexport function formatTokenIdHex(tokenId: bigint): string {\n return formatHex(tokenId)\n}\n\n/**\n * Format a PoolId as a hex string.\n *\n * @param poolId - PoolId value\n * @returns Hex string representation\n */\nexport function formatPoolIdHex(poolId: bigint): string {\n return formatHex(poolId)\n}\n\n/**\n * Format a TokenId as a shortened hex string.\n *\n * @param tokenId - TokenId value\n * @param chars - Characters to show on each side (default: 4)\n * @returns Truncated hex string like \"0x1234...abcd\"\n */\nexport function formatTokenIdShort(tokenId: bigint, chars = 4): string {\n const hex = formatHex(tokenId)\n const charsBig = BigInt(chars)\n const minLength = charsBig * 2n + 4n\n if (BigInt(hex.length) <= minLength) return hex\n return `${hex.slice(0, Number(charsBig + 2n))}...${hex.slice(-Number(charsBig))}`\n}\n\n/**\n * Format a large number with K/M/B suffixes.\n *\n * @param value - The numeric value\n * @param precision - Number of decimal places (default: 1n)\n * @returns Formatted string with suffix\n *\n * @example\n * ```typescript\n * formatCompact(1234n) // \"1.2K\"\n * formatCompact(1234567n) // \"1.2M\"\n * formatCompact(1234567890n) // \"1.2B\"\n * formatCompact(999n) // \"999\"\n * ```\n */\nexport function formatCompact(value: bigint, precision: bigint = 1n): string {\n const isNegative = value < 0n\n const absValue = isNegative ? -value : value\n\n let formatted: string\n\n if (absValue < 1000n) {\n formatted = absValue.toString()\n } else if (absValue < 1_000_000n) {\n formatted = `${formatRatio(absValue, 1000n, precision)}K`\n } else if (absValue < 1_000_000_000n) {\n formatted = `${formatRatio(absValue, 1_000_000n, precision)}M`\n } else {\n formatted = `${formatRatio(absValue, 1_000_000_000n, precision)}B`\n }\n\n return isNegative ? `-${formatted}` : formatted\n}\n\n/**\n * Format a wei amount as a display string.\n *\n * @param wei - Amount in wei\n * @returns Formatted string with unit\n */\nexport function formatWei(wei: bigint): string {\n return `${wei} wei`\n}\n\n/**\n * Format a wei amount as gwei.\n *\n * @param wei - Amount in wei\n * @param precision - Number of decimal places to display\n * @returns Formatted string with unit\n */\nexport function formatGwei(wei: bigint, precision: bigint): string {\n return `${formatTokenAmount(wei, 9n, precision)} gwei`\n}\n","/**\n * Account greeks calculation using stored position data.\n *\n * This module provides functions to calculate account-level greeks\n * using position data stored by syncPositions(). Only the current tick\n * is fetched via RPC - all other data comes from storage.\n *\n * @module v2/reads/accountGreeks\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { PanopticError, StorageDataNotFoundError } from '../errors'\nimport { tickToSqrtPriceX96 } from '../formatters'\nimport {\n type PositionGreeksResult,\n calculatePositionDelta,\n calculatePositionGamma,\n calculatePositionValue,\n} from '../greeks'\nimport type { StorageAdapter } from '../storage'\nimport { getPoolMetaKey, getPositionMetaKey, getPositionsKey, jsonSerializer } from '../storage'\nimport type { BlockMeta, StoredPoolMeta, StoredPositionData } from '../types'\nimport { type CollateralAddresses, getAccountCollateral } from './account'\n\nconst Q192 = 1n << 192n\n\n/**\n * Parameters for getAccountGreeks.\n */\nexport interface GetAccountGreeksParams {\n /** viem PublicClient (only used to fetch current tick) */\n client: PublicClient\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** Storage adapter containing synced position data */\n storage: StorageAdapter\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /**\n * When true, include collateral token balance as linear delta.\n * Requires `assetIndex` to specify which token is the asset.\n */\n includeCollateral?: boolean\n /**\n * Which token is the \"asset\" (the directional exposure token).\n * 0n = token0 is asset, 1n = token1 is asset.\n * Required when `includeCollateral` is true.\n */\n assetIndex?: 0n | 1n\n /** Optional pre-fetched collateral addresses (used when includeCollateral is true) */\n collateralAddresses?: CollateralAddresses\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Result of getAccountGreeks.\n *\n * Returns both granular breakdown (positions vs collateral) and computed totals.\n * - `positionsDelta` / `positionsValue`: Options exposure only\n * - `collateralDelta` / `collateralValue`: Collateral in the pool\n * - `totalDelta` / `totalValue`: Sum of both (use for net portfolio greeks)\n *\n * All values are in natural token smallest units (no WAD scaling).\n * - Value/gamma: numeraire token smallest units\n * - Delta: asset token smallest units\n */\nexport interface AccountGreeksResult {\n // --- Position greeks (options only) ---\n /** Sum of position values (numeraire smallest units, options only) */\n positionsValue: bigint\n /** Sum of position deltas (asset smallest units, options only) */\n positionsDelta: bigint\n /** Sum of position gammas (numeraire smallest units) */\n positionsGamma: bigint\n\n // --- Collateral greeks ---\n /**\n * Value of collateral holdings: asset balance × price + numeraire balance.\n * In numeraire smallest units. 0n when includeCollateral is not set.\n */\n collateralValue: bigint\n /**\n * Linear delta from the asset token's collateral balance (asset smallest units).\n * 0n when includeCollateral is not set.\n */\n collateralDelta: bigint\n\n // --- Computed totals ---\n /** Total portfolio value = positionsValue + collateralValue */\n totalValue: bigint\n /** Total portfolio delta = positionsDelta + collateralDelta */\n totalDelta: bigint\n\n // --- Metadata ---\n /** Number of positions included */\n positionCount: bigint\n /** Per-position greeks breakdown */\n positions: Array<{\n tokenId: bigint\n greeks: PositionGreeksResult\n }>\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Calculate account-level greeks using stored position data.\n *\n * This function reads position data from storage (populated by syncPositions)\n * and calculates greeks client-side. Only the current tick is fetched via RPC.\n *\n * @param params - The parameters\n * @returns Account greeks with per-position breakdown\n * @throws StorageDataNotFoundError if required data is not in storage\n * @throws PanopticError if includeCollateral is true but assetIndex is not provided\n *\n * @example\n * ```typescript\n * // First sync positions to populate storage\n * await syncPositions({ client, chainId, poolAddress, account, storage })\n *\n * // Then calculate greeks from stored data\n * const greeks = await getAccountGreeks({\n * client,\n * chainId,\n * poolAddress,\n * account,\n * storage,\n * })\n *\n * console.log('Positions delta:', greeks.positionsDelta)\n * ```\n */\nexport async function getAccountGreeks(\n params: GetAccountGreeksParams,\n): Promise<AccountGreeksResult> {\n const {\n client,\n chainId,\n poolAddress,\n account,\n storage,\n blockNumber,\n includeCollateral,\n assetIndex,\n collateralAddresses,\n } = params\n\n // 0. Validate: includeCollateral requires assetIndex\n if (includeCollateral && assetIndex === undefined) {\n throw new PanopticError('assetIndex is required when includeCollateral is true')\n }\n\n // 1. Read pool metadata from storage\n const poolMetaKey = getPoolMetaKey(chainId, poolAddress)\n const poolMetaRaw = await storage.get(poolMetaKey)\n if (!poolMetaRaw) {\n throw new StorageDataNotFoundError('poolMeta', poolMetaKey)\n }\n const poolMeta = jsonSerializer.parse(poolMetaRaw) as StoredPoolMeta\n\n // 2. Read position IDs from storage\n const positionsKey = getPositionsKey(chainId, poolAddress, account)\n const positionsRaw = await storage.get(positionsKey)\n if (!positionsRaw) {\n throw new StorageDataNotFoundError('positions', positionsKey)\n }\n const positionIds = jsonSerializer.parse(positionsRaw) as bigint[]\n\n // 3. If no positions and no collateral requested, return zeros\n if (positionIds.length === 0 && !includeCollateral) {\n const targetBlock = blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n const _meta = params._meta ?? (await getBlockMeta({ client, blockNumber: targetBlock }))\n\n return {\n positionsValue: 0n,\n positionsDelta: 0n,\n positionsGamma: 0n,\n collateralValue: 0n,\n collateralDelta: 0n,\n totalValue: 0n,\n totalDelta: 0n,\n positionCount: 0n,\n positions: [],\n _meta,\n }\n }\n\n // 4. Read position metadata for each position from storage\n const storedPositions = await Promise.all(\n positionIds.map(async (tokenId) => {\n const posMetaKey = getPositionMetaKey(chainId, poolAddress, tokenId)\n const posMetaRaw = await storage.get(posMetaKey)\n if (!posMetaRaw) {\n throw new StorageDataNotFoundError('positionMeta', posMetaKey)\n }\n return jsonSerializer.parse(posMetaRaw) as StoredPositionData\n }),\n )\n\n // 5. Fetch current tick (+ collateral if requested) from RPC\n const targetBlock = blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n const [currentTick, _meta, collateral] = await Promise.all([\n client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n blockNumber: targetBlock,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlock }),\n includeCollateral\n ? getAccountCollateral({\n client,\n poolAddress,\n account,\n blockNumber: targetBlock,\n collateralAddresses,\n _meta: params._meta,\n })\n : undefined,\n ])\n\n // 6. Calculate greeks for each position\n let positionsValue = 0n\n let positionsDelta = 0n\n let positionsGamma = 0n\n const positions: AccountGreeksResult['positions'] = []\n\n for (const pos of storedPositions) {\n const input = {\n legs: pos.legs,\n currentTick: BigInt(currentTick),\n mintTick: pos.tickAtMint,\n positionSize: pos.positionSize,\n poolTickSpacing: poolMeta.tickSpacing,\n assetIndex,\n }\n\n const value = calculatePositionValue(input)\n const delta = calculatePositionDelta(input)\n const gamma = calculatePositionGamma(input)\n\n positionsValue += value\n positionsDelta += delta\n positionsGamma += gamma\n\n positions.push({\n tokenId: pos.tokenId,\n greeks: { value, delta, gamma },\n })\n }\n\n // 7. Collateral value and delta\n let collateralValue = 0n\n let collateralDelta = 0n\n\n if (collateral) {\n const isAssetToken0 = assetIndex === 0n\n const assetBal = isAssetToken0 ? collateral.token0.assets : collateral.token1.assets\n const otherBal = isAssetToken0 ? collateral.token1.assets : collateral.token0.assets\n const sqrtPriceX96 = tickToSqrtPriceX96(BigInt(currentTick))\n\n // assetBal * price converts asset smallest units to numeraire smallest units\n // otherBal is already in numeraire smallest units\n if (isAssetToken0) {\n // price = token1/token0 = sqrtPriceX96² / 2¹⁹²\n collateralValue = (assetBal * sqrtPriceX96 * sqrtPriceX96) / Q192 + otherBal\n } else {\n // price = token0/token1 = 2¹⁹² / sqrtPriceX96²\n collateralValue = (assetBal * Q192) / (sqrtPriceX96 * sqrtPriceX96) + otherBal\n }\n collateralDelta = assetBal\n }\n\n return {\n positionsValue,\n positionsDelta,\n positionsGamma,\n collateralValue,\n collateralDelta,\n totalValue: positionsValue + collateralValue,\n totalDelta: positionsDelta + collateralDelta,\n positionCount: BigInt(positionIds.length),\n positions,\n _meta,\n }\n}\n\n/**\n * Parameters for calculateAccountGreeksPure.\n */\nexport interface CalculateAccountGreeksPureParams {\n /** Stored position data */\n positions: StoredPositionData[]\n /** Pool tick spacing */\n tickSpacing: bigint\n /** Ticks at which to evaluate greeks (one or more) */\n atTicks: bigint[]\n /**\n * Collateral balances [token0Assets, token1Assets] in token smallest units.\n * When provided, both tokens are included in totalValue and the\n * asset token's balance is added to totalDelta.\n */\n collateralAssets?: [bigint, bigint]\n /** Override for leg.asset on all legs (0n = token0 is asset, 1n = token1). Defaults to 0n. */\n assetIndex?: bigint\n}\n\n/**\n * Result of calculateAccountGreeksPure.\n *\n * Arrays are parallel to the input `atTicks` — index i corresponds to `atTicks[i]`.\n * Totals include both position greeks and collateral contributions.\n * All values in natural token smallest units (no WAD scaling).\n */\nexport interface AccountGreeksCurveResult {\n /** Total value at each tick: positions + collateral (numeraire smallest units) */\n totalValue: bigint[]\n /** Total delta at each tick: positions + asset collateral (asset smallest units) */\n totalDelta: bigint[]\n /** Total gamma at each tick: positions only (numeraire smallest units, collateral has zero gamma) */\n totalGamma: bigint[]\n /** Number of positions included */\n positionCount: bigint\n /** Per-position greeks curves (arrays parallel to atTicks) */\n positions: Array<{\n tokenId: bigint\n greeks: {\n value: bigint[]\n delta: bigint[]\n gamma: bigint[]\n }\n }>\n}\n\n/**\n * Pure function to calculate portfolio greeks across a range of ticks.\n *\n * No RPC calls — useful for plotting value/delta/gamma curves on a chart.\n * All returned arrays are parallel to the input `atTicks`.\n *\n * When `collateralAssets` is provided, both token balances are included in\n * `totalValue` (asset balance × price + numeraire balance) and\n * the asset token's balance is added to `totalDelta`.\n *\n * @param params - The parameters\n * @returns Portfolio greeks curves and per-position breakdown\n */\nexport function calculateAccountGreeksPure(\n params: CalculateAccountGreeksPureParams,\n): AccountGreeksCurveResult {\n const { positions, tickSpacing, atTicks, collateralAssets, assetIndex } = params\n const n = atTicks.length\n const isAssetToken0 = assetIndex === undefined || assetIndex === 0n\n\n // Collateral balances (already in token smallest units)\n const assetBal = collateralAssets ? collateralAssets[isAssetToken0 ? 0 : 1] : 0n\n const otherBal = collateralAssets ? collateralAssets[isAssetToken0 ? 1 : 0] : 0n\n\n if (positions.length === 0) {\n const totalValue: bigint[] = []\n const totalDelta: bigint[] = []\n for (let i = 0; i < n; i++) {\n const sqrtPriceX96 = tickToSqrtPriceX96(atTicks[i])\n const assetValueInNumeraire = isAssetToken0\n ? (assetBal * sqrtPriceX96 * sqrtPriceX96) / Q192\n : (assetBal * Q192) / (sqrtPriceX96 * sqrtPriceX96)\n totalValue.push(assetValueInNumeraire + otherBal)\n totalDelta.push(assetBal)\n }\n return {\n totalValue,\n totalDelta,\n totalGamma: new Array<bigint>(n).fill(0n),\n positionCount: 0n,\n positions: [],\n }\n }\n\n const totalValue = new Array<bigint>(n).fill(0n)\n const totalDelta = new Array<bigint>(n).fill(0n)\n const totalGamma = new Array<bigint>(n).fill(0n)\n const positionResults: AccountGreeksCurveResult['positions'] = []\n\n for (const pos of positions) {\n const posValues: bigint[] = []\n const posDeltas: bigint[] = []\n const posGammas: bigint[] = []\n\n for (let i = 0; i < n; i++) {\n const input = {\n legs: pos.legs,\n currentTick: atTicks[i],\n mintTick: pos.tickAtMint,\n positionSize: pos.positionSize,\n poolTickSpacing: tickSpacing,\n assetIndex,\n }\n\n const v = calculatePositionValue(input)\n const d = calculatePositionDelta(input)\n const g = calculatePositionGamma(input)\n\n posValues.push(v)\n posDeltas.push(d)\n posGammas.push(g)\n\n totalValue[i] += v\n totalDelta[i] += d\n totalGamma[i] += g\n }\n\n positionResults.push({\n tokenId: pos.tokenId,\n greeks: { value: posValues, delta: posDeltas, gamma: posGammas },\n })\n }\n\n // Add collateral contributions at each tick\n for (let i = 0; i < n; i++) {\n const sqrtPriceX96 = tickToSqrtPriceX96(atTicks[i])\n const assetValueInNumeraire = isAssetToken0\n ? (assetBal * sqrtPriceX96 * sqrtPriceX96) / Q192\n : (assetBal * Q192) / (sqrtPriceX96 * sqrtPriceX96)\n totalValue[i] += assetValueInNumeraire + otherBal\n totalDelta[i] += assetBal\n }\n\n return {\n totalValue,\n totalDelta,\n totalGamma,\n positionCount: BigInt(positions.length),\n positions: positionResults,\n }\n}\n","/**\n * Margin buffer and distance-to-liquidation convenience function.\n *\n * Sources current and required margin directly from\n * `PanopticPool.getFullPositionsData` + `CollateralTracker.assetsOf`,\n * rather than `PanopticQuery.checkCollateral`.\n *\n * Why: `checkCollateral` returns a `currentMargin` already netted of the\n * borrowing obligation of width=0 short (\"loan\") tokenIds, and a\n * `requiredMargin` that does NOT include the loan's collateral requirement.\n * That makes buying-power usage read 0% for accounts whose collateral\n * comes mostly from a loan, and double-subtracts the loan from Net Liq\n * when downstream callers add the position MtM (which already values the\n * loan at `-notional`).\n *\n * `getFullPositionsData.collateralRequirements[]` attributes the loan as\n * a margin requirement (the accurate primitive), and `assetsOf` returns\n * the gross collateral (deposits + borrowed shares) — pairing them yields\n * a consistent gross-collateral / gross-requirement view.\n *\n * @module v2/reads/margin\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { decodeFunctionResult, encodeFunctionData } from 'viem'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi } from '../../../generated'\nimport { panopticQueryAbi } from '../abis/panopticQuery'\nimport { tickToSqrtPriceX96 } from '../formatters/tick'\nimport type { BlockMeta } from '../types'\nimport { decodeLeftRightUnsigned } from '../writes/utils'\nimport { type MulticallBlockCall, readBlockAndAggregate, requireReturnData } from './multicallBlock'\n\n// Sentinel ticks used by PanopticQuery to indicate \"no liquidation at this boundary\"\nconst MIN_TICK = -887272n\nconst MAX_TICK = 887272n\n\nconst FP96 = 1n << 96n\nconst Q128 = 1n << 128n\n\n/**\n * Convert a token0 amount to its token1-equivalent at the given sqrtPriceX96.\n *\n * Matches the on-chain `PanopticMath.convert0to1` truncation, with an\n * overflow-safe branch when `sqrtPriceX96^2` would not fit in uint256.\n */\nfunction convert0to1(amount: bigint, sqrtPriceX96: bigint): bigint {\n if (sqrtPriceX96 < Q128) {\n return (amount * sqrtPriceX96 * sqrtPriceX96) >> 192n\n }\n // amount * (sqrtPriceX96 * sqrtPriceX96 >> 64n) >> 128n\n const sp2Hi = (sqrtPriceX96 * sqrtPriceX96) >> 64n\n return (amount * sp2Hi) >> 128n\n}\n\n/**\n * Convert a token1 amount to its token0-equivalent at the given sqrtPriceX96.\n */\nfunction convert1to0(amount: bigint, sqrtPriceX96: bigint): bigint {\n if (sqrtPriceX96 < Q128) {\n const denom = sqrtPriceX96 * sqrtPriceX96\n return (amount * (1n << 192n)) / denom\n }\n const sp2Hi = (sqrtPriceX96 * sqrtPriceX96) >> 64n\n return (amount * (1n << 128n)) / sp2Hi\n}\n\n/**\n * Parameters for {@link getMarginBuffer}.\n */\nexport interface GetMarginBufferParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenIds of open positions (loan/credit width=0 legs included) */\n tokenIds: bigint[]\n /** PanopticQuery address (required for liquidation prices) */\n queryAddress: Address\n /**\n * Optional pre-fetched collateral tracker addresses (saves an RPC).\n * If omitted, they are fetched from the pool.\n */\n collateralAddresses?: { collateralToken0: Address; collateralToken1: Address }\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Margin buffer result with distance-to-liquidation.\n *\n * **Denomination**: Both slots are populated with the account total\n * cross-converted into a single token denomination so they can be\n * compared directly.\n *\n * - `currentMargin0` / `requiredMargin0` / `buffer0` are denominated in **token0**.\n * - `currentMargin1` / `requiredMargin1` / `buffer1` are denominated in **token1**.\n *\n * `denominatedInToken` indicates which of the two pairs is \"preferred\":\n * 0 when `currentTick < 0`, 1 otherwise — matching the historical\n * `checkCollateral` convention so downstream consumers keep working\n * without changes.\n */\nexport interface MarginBuffer {\n /** Excess margin in token0 units (positive = safe, negative = shortfall) */\n buffer0: bigint\n /** Excess margin in token1 units (positive = safe, negative = shortfall) */\n buffer1: bigint\n /** Buffer as percentage of required margin in bps (slot 0). null if no requirement. */\n bufferPercent0: bigint | null\n /** Buffer as percentage of required margin in bps (slot 1). null if no requirement. */\n bufferPercent1: bigint | null\n /** Current (gross) account collateral, denominated in token0 */\n currentMargin0: bigint\n /** Current (gross) account collateral, denominated in token1 */\n currentMargin1: bigint\n /**\n * Sum of per-position collateral requirements from\n * `getFullPositionsData.collateralRequirements[]`, denominated in token0.\n * Loans/credits (width=0) contribute correctly.\n */\n requiredMargin0: bigint\n /** Same, denominated in token1 */\n requiredMargin1: bigint\n /**\n * Which token the \"preferred\" margin values are denominated in.\n * 0 = token0 (when currentTick < 0), 1 = token1 (when currentTick >= 0).\n */\n denominatedInToken: 0 | 1\n /** Tick distance to nearest liquidation boundary (null if no liquidation boundaries) */\n liquidationDistance: bigint | null\n /** Lower liquidation tick (null if safe at MIN_TICK) */\n lowerLiquidationTick: bigint | null\n /** Upper liquidation tick (null if safe at MAX_TICK) */\n upperLiquidationTick: bigint | null\n /** Current tick */\n currentTick: bigint\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Get margin buffer and distance-to-liquidation for an account.\n *\n * Reads, all pinned to the same block:\n * - `getCurrentTick` (sequencing dependency for sqrtPrice conversion)\n * - `getFullPositionsData(account, true, tokenIds)` → collateralRequirements\n * - `CollateralTracker.assetsOf(account)` on both trackers → gross collateral\n * - `PanopticQuery.getLiquidationPrices(...)` → liquidation boundaries\n *\n * @param params - The parameters\n * @returns Margin buffer with liquidation distance and block metadata\n */\nexport async function getMarginBuffer(params: GetMarginBufferParams): Promise<MarginBuffer> {\n const { client, poolAddress, account, tokenIds, queryAddress, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Resolve collateral tracker addresses (immutable; cache-friendly).\n let collateralToken0: Address\n let collateralToken1: Address\n if (params.collateralAddresses) {\n collateralToken0 = params.collateralAddresses.collateralToken0\n collateralToken1 = params.collateralAddresses.collateralToken1\n } else {\n const addrs = await client.multicall({\n contracts: [\n { address: poolAddress, abi: panopticPoolV2Abi, functionName: 'collateralToken0' },\n { address: poolAddress, abi: panopticPoolV2Abi, functionName: 'collateralToken1' },\n ],\n blockNumber: targetBlockNumber,\n allowFailure: false,\n })\n collateralToken0 = addrs[0]\n collateralToken1 = addrs[1]\n }\n\n const hasPositions = tokenIds.length > 0\n const calls: MulticallBlockCall[] = [\n {\n target: poolAddress,\n callData: encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n }),\n },\n {\n target: collateralToken0,\n callData: encodeFunctionData({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n args: [account],\n }),\n },\n {\n target: collateralToken1,\n callData: encodeFunctionData({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n args: [account],\n }),\n },\n ]\n\n const positionDataIndex = hasPositions ? calls.length : null\n if (positionDataIndex !== null) {\n calls.push({\n target: poolAddress,\n callData: encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, true, tokenIds],\n }),\n })\n }\n\n const liqPricesIndex = hasPositions ? calls.length : null\n if (liqPricesIndex !== null) {\n calls.push({\n target: queryAddress,\n callData: encodeFunctionData({\n abi: panopticQueryAbi,\n functionName: 'getLiquidationPrices',\n args: [poolAddress, account, tokenIds],\n }),\n })\n }\n\n const { _meta, results } = await readBlockAndAggregate({\n client,\n calls,\n blockNumber: targetBlockNumber,\n })\n\n const currentTickResult = decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n data: requireReturnData(results, 0, 'PanopticPool.getCurrentTick'),\n })\n const currentTick = BigInt(currentTickResult)\n const assets0 = decodeFunctionResult({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n data: requireReturnData(results, 1, 'CollateralTracker.assetsOf token0'),\n })\n const assets1 = decodeFunctionResult({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n data: requireReturnData(results, 2, 'CollateralTracker.assetsOf token1'),\n })\n const positionDataResult =\n positionDataIndex === null\n ? null\n : (decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n data: requireReturnData(results, positionDataIndex, 'PanopticPool.getFullPositionsData'),\n }) as readonly [bigint, bigint, readonly bigint[], readonly bigint[], readonly bigint[]])\n const liqPricesResult =\n liqPricesIndex === null\n ? null\n : (decodeFunctionResult({\n abi: panopticQueryAbi,\n functionName: 'getLiquidationPrices',\n data: requireReturnData(results, liqPricesIndex, 'PanopticQuery.getLiquidationPrices'),\n }) as readonly [number, number])\n\n // Sum collateral requirements across all positions, per token.\n let required0Native = 0n\n let required1Native = 0n\n if (positionDataResult) {\n const collateralRequirements = positionDataResult[3]\n for (const packed of collateralRequirements) {\n const decoded = decodeLeftRightUnsigned(packed)\n required0Native += decoded.right // token0\n required1Native += decoded.left // token1\n }\n }\n\n // Cross-convert into a single denomination at current tick.\n // The conversion mirrors PanopticQuery.checkCollateral's effective-balance\n // shape so downstream callers keep their existing per-slot interpretation.\n const sqrtPriceX96 = tickToSqrtPriceX96(currentTick)\n const denominatedInToken: 0 | 1 = sqrtPriceX96 < FP96 ? 0 : 1\n\n // Token0-denominated totals\n const currentMargin0 = assets0 + convert1to0(assets1, sqrtPriceX96)\n const requiredMargin0 = required0Native + convert1to0(required1Native, sqrtPriceX96)\n // Token1-denominated totals\n const currentMargin1 = assets1 + convert0to1(assets0, sqrtPriceX96)\n const requiredMargin1 = required1Native + convert0to1(required0Native, sqrtPriceX96)\n\n const buffer0 = currentMargin0 - requiredMargin0\n const buffer1 = currentMargin1 - requiredMargin1\n const bufferPercent0 = requiredMargin0 === 0n ? null : (buffer0 * 10000n) / requiredMargin0\n const bufferPercent1 = requiredMargin1 === 0n ? null : (buffer1 * 10000n) / requiredMargin1\n\n // Liquidation prices: present only when the account has positions.\n let lowerLiquidationTick: bigint | null = null\n let upperLiquidationTick: bigint | null = null\n let liquidationDistance: bigint | null = null\n if (liqPricesResult) {\n const liqPriceDown = BigInt(liqPricesResult[0])\n const liqPriceUp = BigInt(liqPricesResult[1])\n lowerLiquidationTick = liqPriceDown === MIN_TICK ? null : liqPriceDown\n upperLiquidationTick = liqPriceUp === MAX_TICK ? null : liqPriceUp\n if (lowerLiquidationTick !== null && upperLiquidationTick !== null) {\n const distLower = currentTick - lowerLiquidationTick\n const distUpper = upperLiquidationTick - currentTick\n liquidationDistance = distLower < distUpper ? distLower : distUpper\n } else if (lowerLiquidationTick !== null) {\n liquidationDistance = currentTick - lowerLiquidationTick\n } else if (upperLiquidationTick !== null) {\n liquidationDistance = upperLiquidationTick - currentTick\n }\n }\n\n return {\n buffer0,\n buffer1,\n bufferPercent0,\n bufferPercent1,\n currentMargin0,\n currentMargin1,\n requiredMargin0,\n requiredMargin1,\n denominatedInToken,\n liquidationDistance,\n lowerLiquidationTick,\n upperLiquidationTick,\n currentTick,\n _meta,\n }\n}\n","/**\n * Delta hedging utilities for the Panoptic v2 SDK.\n *\n * Provides functions to calculate loan parameters needed\n * to achieve a target delta for option positions.\n *\n * @module v2/reads/hedge\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { PanopticValidationError } from '../errors/sdk'\nimport { calculatePositionDelta } from '../greeks'\nimport { decodeTokenId } from '../tokenId'\nimport type { LegConfig } from '../tokenId/builder'\nimport type { BlockMeta } from '../types'\nimport { getPool } from './pool'\n\n/**\n * Parameters for getDeltaHedgeParams.\n */\nexport interface GetDeltaHedgeParamsInput {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID */\n chainId: bigint\n /**\n * TokenId of the option position to hedge.\n * Optional when both `currentDelta` and `asset` are provided (whole-portfolio hedging).\n */\n tokenId?: bigint\n /**\n * Position size in contracts.\n * Optional when both `currentDelta` and `asset` are provided.\n */\n positionSize?: bigint\n /** Target delta (WAD-scaled, 0n for delta-neutral) */\n targetDelta: bigint\n /** Optional: current delta if adjusting existing position (WAD-scaled) */\n currentDelta?: bigint\n /**\n * Primary asset index (0n or 1n). Used to determine hedge direction.\n * Required when `tokenId` is not provided; ignored when `tokenId` is provided.\n */\n asset?: bigint\n /** Optional: tick at mint (defaults to current tick if not provided) */\n mintTick?: bigint\n /** Optional: block number for historical queries */\n blockNumber?: bigint\n /** Optional: current tick (skips getPool() when both currentTick and tickSpacing are provided) */\n currentTick?: bigint\n /** Optional: pool tick spacing (skips getPool() when both currentTick and tickSpacing are provided) */\n tickSpacing?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n\n // --- Simulation convergence options ---\n\n /**\n * Simulate the hedge swap and return the post-swap tick.\n * When provided (along with `computeDeltaAtTick`), an iterative loop refines\n * the hedge size to account for AMM price impact.\n */\n simulateSwap?: (hedgeAmount: bigint, hedgeLeg: LegConfig) => Promise<{ tickAfter: bigint } | null>\n\n /**\n * Recompute portfolio delta at a given tick.\n * Required when `simulateSwap` is provided.\n */\n computeDeltaAtTick?: (tick: bigint) => bigint\n\n /** Total position size — used for convergence check (sizeDelta * 10000 / totalPositionSize) */\n totalPositionSize?: bigint\n\n /** Max simulation iterations (default 5) */\n maxSimIterations?: number\n\n /** Convergence threshold in bps (default 10). Loop stops when size change < this. */\n convergenceThresholdBps?: bigint\n}\n\n/**\n * Result of getDeltaHedgeParams.\n */\nexport interface DeltaHedgeResult {\n /** LegConfig to add to the position for hedging */\n hedgeLeg: LegConfig\n /** The hedge amount (in position size units) */\n hedgeAmount: bigint\n /** Always 'loan' — the tokenType determines the delta direction */\n hedgeType: 'loan' | 'credit'\n /** Whether the hedge position should be opened with swapAtMint */\n swapAtMint: boolean\n /** Current position delta (WAD-scaled) */\n currentDelta: bigint\n /** Target delta (WAD-scaled) */\n targetDelta: bigint\n /** Delta adjustment needed (WAD-scaled) */\n deltaAdjustment: bigint\n /** Block metadata */\n _meta: BlockMeta\n /** Number of simulation iterations used (0 if no simulateSwap) */\n simulationIterations: number\n /** Post-swap tick from final simulation (undefined if no simulation) */\n simulatedTickAfter?: bigint\n /** Whether the convergence loop converged within threshold */\n converged: boolean\n}\n\n/**\n * Calculate loan parameters to achieve target delta via swapAtMint.\n *\n * Both delta directions use loans with swapAtMint — the tokenType\n * determines whether delta is added or removed:\n *\n * - **Need positive delta** (e.g. hedging a short call):\n * Loan with tokenType = numeraire + swapAtMint.\n * Borrows numeraire (e.g. USDC), swaps to asset (e.g. ETH).\n * Net: +asset exposure → positive delta.\n *\n * - **Need negative delta** (e.g. hedging a short put):\n * Loan with tokenType = asset + swapAtMint.\n * Borrows asset (e.g. ETH), swaps to numeraire (e.g. USDC).\n * Net: −asset exposure → negative delta.\n *\n * ## Example: Delta-neutral short call\n * ```typescript\n * const hedge = await getDeltaHedgeParams({\n * client, poolAddress, chainId,\n * tokenId: shortCallTokenId,\n * positionSize: 1000000000000000n,\n * targetDelta: 0n,\n * })\n *\n * // Open the hedge as a separate position with swapAtMint\n * const hedgeTokenId = builder\n * .addLoan({ tokenType: hedge.hedgeLeg.tokenType, strike: hedge.hedgeLeg.strike })\n * .build()\n *\n * await openPosition({ ..., tokenId: hedgeTokenId,\n * positionSize: hedge.hedgeAmount, swapAtMint: hedge.swapAtMint })\n * ```\n *\n * @param params - The parameters\n * @returns Delta hedge result with LegConfig (always a loan)\n */\nexport async function getDeltaHedgeParams(\n params: GetDeltaHedgeParamsInput,\n): Promise<DeltaHedgeResult> {\n const {\n client,\n poolAddress,\n chainId,\n tokenId,\n positionSize,\n targetDelta,\n currentDelta: providedCurrentDelta,\n asset: providedAsset,\n mintTick: providedMintTick,\n blockNumber,\n currentTick: providedCurrentTick,\n tickSpacing: providedTickSpacing,\n } = params\n\n // Validate: need either tokenId or (currentDelta + asset)\n const hasTokenId = tokenId !== undefined\n const hasDirectDelta = providedCurrentDelta !== undefined && providedAsset !== undefined\n\n if (!hasTokenId && !hasDirectDelta) {\n throw new PanopticValidationError(\n 'getDeltaHedgeParams requires either `tokenId` or both `currentDelta` and `asset`',\n )\n }\n\n // Validate simulateSwap and computeDeltaAtTick are provided together\n if ((params.simulateSwap !== undefined) !== (params.computeDeltaAtTick !== undefined)) {\n throw new PanopticValidationError(\n 'getDeltaHedgeParams: simulateSwap and computeDeltaAtTick must be provided together',\n )\n }\n\n // If both currentTick and tickSpacing are provided, skip the full getPool() call\n let currentTick: bigint\n let tickSpacing: bigint\n let poolMeta: BlockMeta\n\n if (providedCurrentTick !== undefined && providedTickSpacing !== undefined) {\n currentTick = providedCurrentTick\n tickSpacing = providedTickSpacing\n poolMeta =\n params._meta ??\n (await getBlockMeta({ client, blockNumber: blockNumber ?? (await client.getBlockNumber()) }))\n } else {\n const pool = await getPool({\n client,\n poolAddress,\n chainId,\n blockNumber,\n })\n currentTick = pool.currentTick\n tickSpacing = pool.tickSpacing\n poolMeta = pool._meta\n }\n\n // Determine primary asset and current delta\n let primaryAsset: bigint\n let currentDelta: bigint\n\n if (hasTokenId) {\n // Decode the tokenId to get legs\n const decoded = decodeTokenId(tokenId)\n primaryAsset = decoded.legs.length > 0 ? decoded.legs[0].asset : 0n\n\n // Use provided mintTick or default to currentTick\n const mintTick = providedMintTick ?? currentTick\n\n // Calculate position delta if not provided\n currentDelta =\n providedCurrentDelta ??\n calculatePositionDelta({\n legs: decoded.legs,\n currentTick,\n mintTick,\n positionSize: positionSize!,\n poolTickSpacing: tickSpacing,\n })\n } else {\n // Direct delta + asset mode (whole-portfolio hedging)\n if (providedAsset !== 0n && providedAsset !== 1n) {\n throw new PanopticValidationError(\n `getDeltaHedgeParams: asset must be 0n or 1n, got ${providedAsset}`,\n )\n }\n primaryAsset = providedAsset\n currentDelta = providedCurrentDelta!\n }\n\n // deltaAdjustment = targetDelta - currentDelta\n // Positive → need to add positive delta; Negative → need to add negative delta.\n const deltaAdjustment = targetDelta - currentDelta\n\n // Delta is in asset smallest units. A loan+swapAtMint of size X gives\n // effective delta ≈ ±X (in asset smallest units). So hedgeAmount = |deltaAdjustment|.\n const absDeltaAdjustment = deltaAdjustment < 0n ? -deltaAdjustment : deltaAdjustment\n let hedgeAmount = absDeltaAdjustment\n\n const numeraire = primaryAsset === 0n ? 1n : 0n\n\n // Both directions use a loan + swapAtMint. The tokenType determines direction:\n // deltaAdjustment > 0 (need +delta): loan numeraire → swap to asset → +asset exposure\n // deltaAdjustment < 0 (need −delta): loan asset → swap to numeraire → −asset exposure\n const needPositiveDelta = deltaAdjustment > 0n\n const hedgeTokenType = needPositiveDelta ? numeraire : primaryAsset\n\n const hedgeLeg: LegConfig = {\n asset: primaryAsset,\n optionRatio: 1n,\n isLong: false, // Always a loan\n tokenType: hedgeTokenType,\n strike: (currentTick / tickSpacing) * tickSpacing, // Round to tick spacing\n width: 0n, // Loan/credit indicator\n }\n\n // --- Simulation convergence loop ---\n const {\n simulateSwap,\n computeDeltaAtTick,\n totalPositionSize,\n maxSimIterations = 5,\n convergenceThresholdBps = 10n,\n } = params\n\n let simulationIterations = 0\n let simulatedTickAfter: bigint | undefined\n let converged = true\n\n if (simulateSwap && computeDeltaAtTick) {\n if (totalPositionSize === undefined || totalPositionSize === 0n) {\n throw new PanopticValidationError(\n 'getDeltaHedgeParams: totalPositionSize is required and must be > 0 when simulateSwap is provided',\n )\n }\n\n converged = false\n\n for (let i = 0; i < maxSimIterations; i++) {\n simulationIterations = i + 1\n\n const simResult = await simulateSwap(hedgeAmount, hedgeLeg)\n if (simResult == null) break\n\n simulatedTickAfter = simResult.tickAfter\n\n // Recompute portfolio delta at the post-swap tick\n const adjustedDelta = computeDeltaAtTick(simResult.tickAfter)\n const newAdjustment = targetDelta - adjustedDelta\n const newAmount = newAdjustment < 0n ? -newAdjustment : newAdjustment\n\n // Convergence check\n const sizeDelta = newAmount > hedgeAmount ? newAmount - hedgeAmount : hedgeAmount - newAmount\n const sizeChangeBps = (sizeDelta * 10000n) / totalPositionSize\n\n hedgeAmount = newAmount\n\n if (sizeChangeBps <= convergenceThresholdBps || sizeDelta === 0n) {\n converged = true\n break\n }\n }\n }\n\n return {\n hedgeLeg,\n hedgeAmount,\n hedgeType: 'loan',\n swapAtMint: true,\n currentDelta,\n targetDelta,\n deltaAdjustment,\n _meta: poolMeta,\n simulationIterations,\n simulatedTickAfter,\n converged,\n }\n}\n","/**\n * Collateral share price read for the Panoptic v2 SDK.\n *\n * Reads totalAssets and totalSupply from two CollateralTracker contracts\n * to compute share prices. Designed for APY calculations at historical blocks.\n *\n * @module v2/reads/collateralSharePrice\n */\n\nimport type { Address, Client } from 'viem'\nimport { ContractFunctionExecutionError } from 'viem'\nimport { multicall } from 'viem/actions'\n\nimport { collateralTrackerV2Abi } from '../../../generated'\n\n/**\n * Raw share price data for a single collateral tracker.\n */\nexport interface CollateralSharePriceData {\n totalAssets: bigint\n totalSupply: bigint\n}\n\n/**\n * Get totalAssets and totalSupply for two CollateralTracker contracts in a single multicall.\n *\n * Consumers can compute share price as `totalAssets / totalSupply` using their\n * preferred precision library (e.g. Decimal.js).\n *\n * If the collateral tracker reverts (e.g. uninitialized), returns zeros.\n *\n * @param collateralAddresses - Tuple of [token0 tracker, token1 tracker] addresses\n * @param blockNumber - Block number to query at\n * @param client - viem Client\n * @returns Tuple of raw share price data\n */\nexport async function getCollateralSharePrices(\n collateralAddresses: [Address, Address],\n blockNumber: bigint,\n client: Client,\n): Promise<[CollateralSharePriceData, CollateralSharePriceData]> {\n try {\n const results = await multicall(client, {\n contracts: [\n {\n address: collateralAddresses[0],\n abi: collateralTrackerV2Abi,\n functionName: 'totalAssets',\n },\n {\n address: collateralAddresses[0],\n abi: collateralTrackerV2Abi,\n functionName: 'totalSupply',\n },\n {\n address: collateralAddresses[1],\n abi: collateralTrackerV2Abi,\n functionName: 'totalAssets',\n },\n {\n address: collateralAddresses[1],\n abi: collateralTrackerV2Abi,\n functionName: 'totalSupply',\n },\n ],\n blockNumber,\n allowFailure: false,\n })\n\n const [assets0, supply0, assets1, supply1] = results\n\n return [\n { totalAssets: assets0, totalSupply: supply0 },\n { totalAssets: assets1, totalSupply: supply1 },\n ]\n } catch (e: unknown) {\n if (e instanceof ContractFunctionExecutionError) {\n return [\n { totalAssets: 0n, totalSupply: 0n },\n { totalAssets: 0n, totalSupply: 0n },\n ]\n }\n throw e\n }\n}\n","/**\n * Batch read of CollateralTracker.totalAssets() for multiple trackers.\n *\n * @module v2/reads/collateralTotalAssets\n */\n\nimport type { Address, Client } from 'viem'\nimport { getAddress, zeroAddress } from 'viem'\nimport { multicall } from 'viem/actions'\n\nimport { collateralTrackerV2Abi } from '../../../generated'\n\n/**\n * Get totalAssets for multiple CollateralTracker contracts in a single multicall.\n *\n * @param client - viem Client\n * @param collateralTrackerAddresses - Array of CollateralTracker addresses\n * @param chainId - Chain ID (for multicall routing)\n * @param blockNumber - Optional block number for historical queries\n * @returns Array of totalAssets (bigint) in the same order as input addresses\n */\nexport async function getCollateralTotalAssetsBatch(\n client: Client,\n collateralTrackerAddresses: Address[],\n chainId: number,\n blockNumber?: bigint,\n): Promise<bigint[]> {\n if (collateralTrackerAddresses.length === 0) return []\n\n try {\n const contracts = collateralTrackerAddresses.map((address) => ({\n address: getAddress(address ?? zeroAddress),\n abi: collateralTrackerV2Abi,\n functionName: 'totalAssets' as const,\n chainId,\n }))\n\n const results = await multicall(client, {\n contracts,\n blockNumber,\n allowFailure: false,\n })\n\n return results.map((result) => BigInt(result ?? 0))\n } catch (error) {\n console.error('Error reading collateral total assets:', error)\n return collateralTrackerAddresses.map(() => 0n)\n }\n}\n","/**\n * Account buying power read function for the Panoptic v2 SDK.\n *\n * Sources gross collateral from `CollateralTracker.assetsOf` and per-position\n * required margin from `PanopticPool.getFullPositionsData.collateralRequirements[]`,\n * cross-converted to both token denominations at the current tick.\n *\n * This replaces the prior `PanopticQuery.checkCollateral` (3-arg, oracle-ticks\n * overload) implementation that netted loan tokenId debt out of the balance\n * and excluded loans from required-collateral, causing buying-power readouts\n * to be wildly wrong for any account that had borrowed.\n *\n * @module v2/reads/buyingPower\n */\n\nimport type { Address, Client } from 'viem'\nimport { decodeFunctionResult, encodeFunctionData } from 'viem'\nimport { multicall } from 'viem/actions'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi } from '../../../generated'\nimport { tickToSqrtPriceX96 } from '../formatters/tick'\nimport type { BlockMeta } from '../types'\nimport { decodeLeftRightUnsigned } from '../writes/utils'\nimport { type MulticallBlockCall, readBlockAndAggregate, requireReturnData } from './multicallBlock'\n\nconst Q128 = 1n << 128n\n\nfunction convert0to1(amount: bigint, sqrtPriceX96: bigint): bigint {\n if (sqrtPriceX96 < Q128) {\n return (amount * sqrtPriceX96 * sqrtPriceX96) >> 192n\n }\n const sp2Hi = (sqrtPriceX96 * sqrtPriceX96) >> 64n\n return (amount * sp2Hi) >> 128n\n}\n\nfunction convert1to0(amount: bigint, sqrtPriceX96: bigint): bigint {\n if (sqrtPriceX96 < Q128) {\n const denom = sqrtPriceX96 * sqrtPriceX96\n return (amount * (1n << 192n)) / denom\n }\n const sp2Hi = (sqrtPriceX96 * sqrtPriceX96) >> 64n\n return (amount * (1n << 128n)) / sp2Hi\n}\n\n/**\n * Parameters for getAccountBuyingPower.\n */\nexport interface GetAccountBuyingPowerParams {\n /** viem Client (PublicClient or basic Client with transport) */\n client: Client\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** TokenIds of open positions */\n tokenIds: bigint[]\n /** PanopticQuery address (kept for backwards compatibility; unused). */\n queryAddress?: Address\n /**\n * Optional pre-fetched collateral tracker addresses (saves an RPC).\n * If omitted, they are fetched from the pool.\n */\n collateralAddresses?: { collateralToken0: Address; collateralToken1: Address }\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips block metadata fetch) */\n _meta?: BlockMeta\n}\n\n/**\n * Result of getAccountBuyingPower.\n *\n * Both per-token values are the **gross** account total cross-converted\n * into the respective single-token denomination at the current tick:\n * - `collateralBalance0` / `requiredCollateral0` are in token0 units\n * - `collateralBalance1` / `requiredCollateral1` are in token1 units\n */\nexport interface AccountBuyingPower {\n /** Gross collateral (deposits + borrowed shares), denominated in token0 */\n collateralBalance0: bigint\n /** Sum of per-position collateral requirements, denominated in token0 */\n requiredCollateral0: bigint\n /** Gross collateral (deposits + borrowed shares), denominated in token1 */\n collateralBalance1: bigint\n /** Sum of per-position collateral requirements, denominated in token1 */\n requiredCollateral1: bigint\n /** Block metadata for the Multicall3 aggregate read */\n _meta: BlockMeta\n}\n\n/**\n * Get account-level buying power.\n *\n * Uses {@link https://github.com/panoptic-xyz CollateralTracker.assetsOf} for\n * gross collateral and `PanopticPool.getFullPositionsData.collateralRequirements[]`\n * for the per-position required margin — so loan tokenIds (width=0 shorts)\n * contribute to the requirement instead of being netted out of the balance.\n *\n * Accepts a plain viem `Client` (not just `PublicClient`) so it works with wagmi's\n * `useClient()` without needing a cast.\n *\n * @param params - The parameters\n * @returns Account buying power data with optional block metadata\n */\nexport async function getAccountBuyingPower(\n params: GetAccountBuyingPowerParams,\n): Promise<AccountBuyingPower> {\n const { client, poolAddress, account, tokenIds } = params\n const blockNumber = params.blockNumber ?? params._meta?.blockNumber\n\n // Resolve collateral tracker addresses (immutable; cache-friendly).\n let collateralToken0: Address\n let collateralToken1: Address\n if (params.collateralAddresses) {\n collateralToken0 = params.collateralAddresses.collateralToken0\n collateralToken1 = params.collateralAddresses.collateralToken1\n } else {\n const addrs = await multicall(client, {\n contracts: [\n { address: poolAddress, abi: panopticPoolV2Abi, functionName: 'collateralToken0' },\n { address: poolAddress, abi: panopticPoolV2Abi, functionName: 'collateralToken1' },\n ],\n blockNumber,\n allowFailure: false,\n })\n collateralToken0 = addrs[0]\n collateralToken1 = addrs[1]\n }\n\n const calls: MulticallBlockCall[] = [\n {\n target: poolAddress,\n callData: encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n }),\n },\n {\n target: collateralToken0,\n callData: encodeFunctionData({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n args: [account],\n }),\n },\n {\n target: collateralToken1,\n callData: encodeFunctionData({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n args: [account],\n }),\n },\n ]\n\n const positionDataIndex = tokenIds.length > 0 ? calls.length : null\n if (positionDataIndex !== null) {\n calls.push({\n target: poolAddress,\n callData: encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, true, tokenIds],\n }),\n })\n }\n\n const { _meta, results } = await readBlockAndAggregate({ client, calls, blockNumber })\n\n const currentTickResult = decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n data: requireReturnData(results, 0, 'PanopticPool.getCurrentTick'),\n })\n const assets0 = decodeFunctionResult({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n data: requireReturnData(results, 1, 'CollateralTracker.assetsOf token0'),\n })\n const assets1 = decodeFunctionResult({\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n data: requireReturnData(results, 2, 'CollateralTracker.assetsOf token1'),\n })\n const currentTick = BigInt(currentTickResult)\n const positionDataResult =\n positionDataIndex === null\n ? null\n : (decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n data: requireReturnData(results, positionDataIndex, 'PanopticPool.getFullPositionsData'),\n }) as readonly [bigint, bigint, readonly bigint[], readonly bigint[], readonly bigint[]])\n\n // Sum collateral requirements across positions, per token.\n let required0Native = 0n\n let required1Native = 0n\n if (positionDataResult) {\n const collateralRequirements = positionDataResult[3]\n for (const packed of collateralRequirements) {\n const decoded = decodeLeftRightUnsigned(packed)\n required0Native += decoded.right // token0\n required1Native += decoded.left // token1\n }\n }\n\n // Cross-convert into each single-token denomination at current tick.\n const sqrtPriceX96 = tickToSqrtPriceX96(currentTick)\n const collateralBalance0 = assets0 + convert1to0(assets1, sqrtPriceX96)\n const requiredCollateral0 = required0Native + convert1to0(required1Native, sqrtPriceX96)\n const collateralBalance1 = assets1 + convert0to1(assets0, sqrtPriceX96)\n const requiredCollateral1 = required1Native + convert0to1(required0Native, sqrtPriceX96)\n\n return {\n collateralBalance0,\n requiredCollateral0,\n collateralBalance1,\n requiredCollateral1,\n _meta,\n }\n}\n","/**\n * Open position preview — combines buying power check with open position simulation.\n *\n * @module v2/reads/openPositionPreview\n */\n\nimport type { Address, Client, PublicClient } from 'viem'\n\nimport { AccountInsolventError, NotEnoughTokensError } from '../errors'\nimport { parsePanopticError } from '../errors/parser'\nimport type { SimulateOpenPositionParams } from '../simulations/simulateOpenPosition'\nimport { simulateOpenPosition } from '../simulations/simulateOpenPosition'\nimport type { OpenPositionSimulation, SimulationResult } from '../types'\nimport type { AccountBuyingPower } from './buyingPower'\nimport { getAccountBuyingPower } from './buyingPower'\n\n/**\n * Parameters for getOpenPositionPreview.\n */\nexport interface GetOpenPositionPreviewParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** Existing position IDs held by the account (before this mint) */\n existingPositionIds: bigint[]\n /** TokenId of position to open */\n tokenId: bigint\n /** Position size */\n positionSize: bigint\n /** PanopticQuery address */\n queryAddress: Address\n /** Lower tick limit */\n tickLimitLow: bigint\n /** Upper tick limit */\n tickLimitHigh: bigint\n /** Spread limit (default 0n) */\n spreadLimit?: bigint\n /** Whether to swap at mint */\n swapAtMint?: boolean\n /** Whether to use premia as collateral */\n usePremiaAsCollateral?: boolean\n /** Chain ID (for greeks calculation) */\n chainId?: bigint\n /** Optional block number */\n blockNumber?: bigint\n}\n\n/**\n * Result of getOpenPositionPreview.\n */\nexport interface OpenPositionPreview {\n /** Current buying power (from checkCollateral on existing positions) */\n currentBuyingPower: AccountBuyingPower\n /** Simulation result (from dry-run dispatch) */\n simulation: SimulationResult<OpenPositionSimulation>\n /** Whether the simulated mint succeeded (position is solvent post-mint) */\n isSolvent: boolean\n /** Token 0 amount required (negative delta = deposit). Null if simulation failed. */\n amount0Required: bigint | null\n /** Token 1 amount required. Null if simulation failed. */\n amount1Required: bigint | null\n /** Collateral balance in token 0 after mint. Null if simulation failed. */\n postCollateral0: bigint | null\n /** Collateral balance in token 1 after mint. Null if simulation failed. */\n postCollateral1: bigint | null\n /** Post-mint collateral requirement in token0 (per-token, not cross-margined). Null if sim failed. */\n postMintCollateralReqToken0: bigint | null\n /** Post-mint collateral requirement in token1 (per-token, not cross-margined). Null if sim failed. */\n postMintCollateralReqToken1: bigint | null\n /**\n * Collateral requirement for the new position only (last entry of perPositionCollateralReqs).\n * Use this for \"Margin Used\" display — postMintCollateralReqToken0/1 includes existing positions too.\n * Null if simulation failed or perPositionCollateralReqs is empty.\n */\n newPositionCollateralReqToken0: bigint | null\n /** Collateral requirement for the new position only, token1. Null if sim failed. */\n newPositionCollateralReqToken1: bigint | null\n}\n\n/**\n * Get a preview of opening a position.\n *\n * Composes two calls:\n * 1. `getAccountBuyingPower` — current margin state for existing positions\n * 2. `simulateOpenPosition` — dry-run dispatch to check feasibility & token flows\n *\n * @param params - Preview parameters\n * @returns Preview with buying power, simulation result, and derived convenience fields\n */\nexport async function getOpenPositionPreview(\n params: GetOpenPositionPreviewParams,\n): Promise<OpenPositionPreview> {\n const {\n client,\n poolAddress,\n account,\n existingPositionIds,\n tokenId,\n positionSize,\n queryAddress,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit,\n swapAtMint,\n usePremiaAsCollateral,\n chainId,\n blockNumber,\n } = params\n\n // Run both calls in parallel\n const [currentBuyingPower, simulation] = await Promise.all([\n getAccountBuyingPower({\n client: client as Client,\n poolAddress,\n account,\n tokenIds: existingPositionIds,\n queryAddress,\n blockNumber,\n }),\n simulateOpenPosition({\n client,\n poolAddress,\n account,\n existingPositionIds,\n tokenId,\n positionSize,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit,\n swapAtMint,\n usePremiaAsCollateral,\n chainId,\n blockNumber,\n } satisfies SimulateOpenPositionParams),\n ])\n\n // isSolvent should only be false for actual solvency errors (AccountInsolvent, NotEnoughTokens).\n // Other simulation failures (PriceBoundFail, EffectiveLiquidityAboveThreshold, etc.) are not\n // solvency issues and should not trigger the \"buying power exceeded\" message.\n let isSolvent = true\n if (!simulation.success) {\n const parsed = parsePanopticError(simulation.error)\n const err = parsed?.error ?? simulation.error\n isSolvent = !(err instanceof AccountInsolventError || err instanceof NotEnoughTokensError)\n }\n const data = simulation.success ? simulation.data : null\n\n return {\n currentBuyingPower,\n simulation,\n isSolvent,\n amount0Required: data?.amount0Required ?? null,\n amount1Required: data?.amount1Required ?? null,\n postCollateral0: data?.postCollateral0 ?? null,\n postCollateral1: data?.postCollateral1 ?? null,\n postMintCollateralReqToken0: data?.postMintCollateralReqToken0 ?? null,\n postMintCollateralReqToken1: data?.postMintCollateralReqToken1 ?? null,\n newPositionCollateralReqToken0:\n data?.perPositionCollateralReqs && data.perPositionCollateralReqs.length > 0\n ? (data.perPositionCollateralReqs[data.perPositionCollateralReqs.length - 1]?.token0 ??\n null)\n : null,\n newPositionCollateralReqToken1:\n data?.perPositionCollateralReqs && data.perPositionCollateralReqs.length > 0\n ? (data.perPositionCollateralReqs[data.perPositionCollateralReqs.length - 1]?.token1 ??\n null)\n : null,\n }\n}\n","/**\n * Read the native token (e.g. ETH) price in USD from a PanopticPool's on-chain tick.\n *\n * @module v2/reads/nativeTokenPrice\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { tickToPriceDecimalScaled } from '../formatters/tick'\n\nexport interface GetNativeTokenPriceParams {\n client: PublicClient\n /** Address of a PanopticPool deployed on a native/USD stablecoin underlying pool */\n panopticPoolAddress: Address\n /** Decimals of token0 in the underlying pool */\n token0Decimals: bigint\n /** Decimals of token1 in the underlying pool */\n token1Decimals: bigint\n /** Whether the native asset is token0 (true) or token1 (false) */\n nativeIsToken0: boolean\n}\n\n/**\n * Fetch the native token price in USD by reading `getCurrentTick()` from a\n * PanopticPool deployed on a native/stablecoin pair.\n *\n * @returns The price as a decimal string (e.g. \"2000.00\")\n */\nexport async function getNativeTokenPrice(params: GetNativeTokenPriceParams): Promise<string> {\n const { client, panopticPoolAddress, token0Decimals, token1Decimals, nativeIsToken0 } = params\n\n const currentTick = await client.readContract({\n address: panopticPoolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n })\n\n // tickToPriceDecimalScaled returns token0/token1 price (price of token0 denominated in token1).\n // If nativeIsToken0: price = USD per native (what we want)\n // If !nativeIsToken0: price = native per USD → invert by swapping decimals\n if (nativeIsToken0) {\n return tickToPriceDecimalScaled(BigInt(currentTick), token0Decimals, token1Decimals, 2n)\n } else {\n // Swap decimals to get the inverse price\n return tickToPriceDecimalScaled(BigInt(currentTick), token1Decimals, token0Decimals, 2n)\n }\n}\n","/**\n * Account trade history for the Panoptic v2 SDK.\n *\n * Fetches OptionMinted and OptionBurnt events filtered by account address\n * using indexed topic filtering for RPC efficiency (2 calls total).\n *\n * @module v2/reads/history\n */\n\nimport type { Address, Hash, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport type { BlockMeta } from '../types'\nimport { decodePositionBalance } from '../writes/utils'\n\n/**\n * A single trade (mint or burn) in the account's history.\n */\nexport interface AccountTrade {\n /** Whether this was a mint or burn */\n action: 'mint' | 'burn'\n /** TokenId of the position */\n tokenId: bigint\n /** Position size */\n positionSize: bigint\n /** Block number of the trade */\n blockNumber: bigint\n /** Transaction hash */\n transactionHash: Hash\n /** Log index within the block */\n logIndex: bigint\n /** Tick at mint (only for mints) */\n tickAtMint?: bigint\n /** Timestamp at mint in Unix seconds (only for mints) */\n timestampAtMint?: bigint\n /** Whether a swap occurred at mint (only for mints) */\n swapAtMint?: boolean\n /** Pool utilization for token 0 at mint (only for mints) */\n poolUtilization0?: bigint\n /** Pool utilization for token 1 at mint (only for mints) */\n poolUtilization1?: bigint\n /** Premia settled per leg on burn (only for burns) */\n premiaByLeg?: readonly [bigint, bigint, bigint, bigint]\n}\n\n/**\n * Account history result.\n */\nexport interface AccountHistory {\n /** All trades sorted by block number ascending, then log index */\n trades: AccountTrade[]\n /** Block metadata at query time */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for getAccountHistory.\n */\nexport interface GetAccountHistoryParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address to fetch history for */\n account: Address\n /** Start block (default: 0n) */\n fromBlock?: bigint\n /** End block (default: latest) */\n toBlock?: bigint\n /** Optional block number for _meta (default: toBlock or latest) */\n blockNumber?: bigint\n}\n\n/**\n * Fetch trade history for an account on a specific pool.\n *\n * Uses indexed topic filtering on the `recipient` field of OptionMinted\n * and OptionBurnt events, resulting in exactly 2 RPC calls regardless\n * of the number of trades.\n *\n * @param params - Query parameters\n * @returns Account trade history sorted chronologically\n *\n * @example\n * ```typescript\n * const history = await getAccountHistory({\n * client,\n * poolAddress,\n * account: '0x...',\n * fromBlock: 18_000_000n,\n * })\n *\n * for (const trade of history.trades) {\n * console.log(`${trade.action} tokenId=${trade.tokenId} size=${trade.positionSize}`)\n * }\n * ```\n */\nexport async function getAccountHistory(params: GetAccountHistoryParams): Promise<AccountHistory> {\n const { client, poolAddress, account, fromBlock = 0n, toBlock, blockNumber } = params\n\n const effectiveToBlock = toBlock ?? blockNumber ?? (await client.getBlockNumber())\n const metaBlockNumber = blockNumber ?? effectiveToBlock\n\n // Fetch mints and burns in parallel — 2 RPC calls total.\n // Both events have `recipient` as indexed topic[1], so the RPC node\n // filters server-side via the topic hash.\n const [mintLogs, burnLogs, _meta] = await Promise.all([\n client.getContractEvents({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n eventName: 'OptionMinted',\n args: { recipient: account },\n fromBlock,\n toBlock: effectiveToBlock,\n }),\n client.getContractEvents({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n eventName: 'OptionBurnt',\n args: { recipient: account },\n fromBlock,\n toBlock: effectiveToBlock,\n }),\n getBlockMeta({ client, blockNumber: metaBlockNumber }),\n ])\n\n const trades: AccountTrade[] = []\n\n // Parse mints\n for (const log of mintLogs) {\n const args = log.args as {\n recipient: Address\n tokenId: bigint\n balanceData: bigint\n }\n const balance = decodePositionBalance(args.balanceData)\n trades.push({\n action: 'mint',\n tokenId: args.tokenId,\n positionSize: balance.positionSize,\n blockNumber: log.blockNumber!,\n transactionHash: log.transactionHash!,\n logIndex: BigInt(log.logIndex!),\n tickAtMint: balance.tickAtMint,\n timestampAtMint: balance.timestampAtMint,\n swapAtMint: balance.swapAtMint,\n poolUtilization0: balance.poolUtilization0,\n poolUtilization1: balance.poolUtilization1,\n })\n }\n\n // Parse burns\n for (const log of burnLogs) {\n const args = log.args as {\n recipient: Address\n tokenId: bigint\n positionSize: bigint\n premiaByLeg: readonly [bigint, bigint, bigint, bigint]\n }\n trades.push({\n action: 'burn',\n tokenId: args.tokenId,\n positionSize: args.positionSize,\n blockNumber: log.blockNumber!,\n transactionHash: log.transactionHash!,\n logIndex: BigInt(log.logIndex!),\n premiaByLeg: args.premiaByLeg,\n })\n }\n\n // Sort chronologically: by block number, then log index\n trades.sort((a, b) => {\n if (a.blockNumber !== b.blockNumber) {\n return a.blockNumber < b.blockNumber ? -1 : 1\n }\n return a.logIndex < b.logIndex ? -1 : 1\n })\n\n return { trades, _meta }\n}\n","/**\n * Historical Uniswap fee reads for the Panoptic v2 SDK.\n *\n * Standalone function for fetching Uniswap fee accrual across historical blocks.\n * Works with any Uniswap V3/V4 pool — no Panoptic pool required.\n *\n * Also used internally by getStreamiaHistory for the Uniswap fee component.\n *\n * @module v2/reads/uniswapFeeHistory\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { stateViewAbi } from '../abis/stateView'\nimport { uniswapV3PoolAbi } from '../abis/uniswapV3Pool'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { InvalidHistoryRangeError } from '../errors/sdk'\nimport type { BlockMeta } from '../types'\nimport type { PoolVersionConfig } from '../types/poolConfig'\nimport type { StreamiaLeg } from '../types/streamia'\n\n// ── Types ──────────────────────────────────────────────────────────────\n\n/** A single snapshot of Uniswap fee data at a particular block. */\nexport interface UniswapFeeSnapshot {\n /** Block number (undefined if queried as latest) */\n blockNumber: bigint | undefined\n /** Uniswap fee delta from the first block in the series */\n fees: { token0: bigint; token1: bigint }\n}\n\n/** Result from getUniswapFeeHistory. */\nexport interface UniswapFeeHistoryResult {\n /** Snapshots in the same order as input blockNumbers */\n snapshots: UniswapFeeSnapshot[]\n /** Block metadata for the latest block used */\n _meta: BlockMeta\n}\n\n/** Parameters for getUniswapFeeHistory. */\nexport interface GetUniswapFeeHistoryParams {\n /** viem PublicClient */\n client: PublicClient\n /** Block numbers to query; undefined entries resolve to latest */\n blockNumbers: (bigint | undefined)[]\n /** Decoded legs with pre-computed liquidity */\n legs: StreamiaLeg[]\n /** Pool version config (carries pool address / StateView + poolId) */\n poolConfig: PoolVersionConfig\n /** Pre-fetched block metadata (skips an extra eth_getBlockByNumber if provided) */\n _meta?: BlockMeta\n}\n\n// ── Public function ────────────────────────────────────────────────────\n\n/**\n * Get historical Uniswap fee accrual for a set of liquidity legs across multiple blocks.\n *\n * Works with any Uniswap V3/V4 pool — no Panoptic pool required.\n * Returns fee deltas relative to the first block in the series.\n *\n * @param params - The parameters\n * @returns Fee snapshots at each block\n */\nexport async function getUniswapFeeHistory(\n params: GetUniswapFeeHistoryParams,\n): Promise<UniswapFeeHistoryResult> {\n const { client, blockNumbers, legs, poolConfig } = params\n\n // Validate legs\n for (const leg of legs) {\n if (leg.lowerTick >= leg.upperTick) {\n throw new InvalidHistoryRangeError(\n `Leg lowerTick (${leg.lowerTick}) must be < upperTick (${leg.upperTick})`,\n )\n }\n if (leg.liquidity <= 0n) {\n throw new InvalidHistoryRangeError(`Leg liquidity must be > 0, got ${leg.liquidity}`)\n }\n }\n\n if (blockNumbers.length === 0 || legs.length === 0) {\n const _meta = params._meta ?? (await getBlockMeta({ client }))\n return { snapshots: [], _meta }\n }\n\n const [blockData, _meta] = await Promise.all([\n fetchUniswapFeeData(client, blockNumbers, legs, poolConfig),\n params._meta ? Promise.resolve(params._meta) : getBlockMeta({ client }),\n ])\n\n let initialFees0: bigint | null = null\n let initialFees1: bigint | null = null\n\n const snapshots: UniswapFeeSnapshot[] = blockData.map((bd, i) => {\n const { total0, total1 } = computeUniswapFeesForBlock(bd, legs)\n\n if (initialFees0 === null) {\n initialFees0 = total0\n initialFees1 = total1\n }\n\n return {\n blockNumber: blockNumbers[i],\n fees: {\n token0: total0 - initialFees0,\n token1: total1 - (initialFees1 as bigint),\n },\n }\n })\n\n return { snapshots, _meta }\n}\n\n// ── Internals (also used by streamiaHistory) ─────────────────────────\n\n/** Raw Uniswap data fetched for a single block. */\nexport interface UniswapBlockData {\n currentTick: number\n feeGrowthGlobal0: bigint\n feeGrowthGlobal1: bigint\n /** Map from tick number → { feeGrowthOutside0, feeGrowthOutside1 } */\n tickData: Map<number, { feeGrowthOutside0: bigint; feeGrowthOutside1: bigint }>\n}\n\n/**\n * Fetch Uniswap pool data for all blocks in parallel.\n * Globals (slot0, feeGrowthGlobal) are fetched ONCE per block, not per-leg.\n * Tick data is fetched for each unique tick across all legs.\n */\nexport async function fetchUniswapFeeData(\n client: PublicClient,\n blockNumbers: (bigint | undefined)[],\n legs: StreamiaLeg[],\n poolConfig: PoolVersionConfig,\n): Promise<UniswapBlockData[]> {\n const uniqueTickSet = new Set<number>()\n for (const leg of legs) {\n uniqueTickSet.add(leg.lowerTick)\n uniqueTickSet.add(leg.upperTick)\n }\n const uniqueTicks = [...uniqueTickSet].sort((a, b) => a - b)\n\n const blockPromises = blockNumbers.map((bn) =>\n fetchUniswapBlockSnapshot(client, bn, uniqueTicks, poolConfig),\n )\n\n return Promise.all(blockPromises)\n}\n\n/**\n * Compute total Uniswap fees for all legs at a single block, using the\n * standard Uniswap V3 fee accumulation formula.\n */\nexport function computeUniswapFeesForBlock(\n blockData: UniswapBlockData,\n legs: StreamiaLeg[],\n): { total0: bigint; total1: bigint } {\n let total0 = 0n\n let total1 = 0n\n\n for (const leg of legs) {\n const lower = blockData.tickData.get(leg.lowerTick)\n const upper = blockData.tickData.get(leg.upperTick)\n if (!lower || !upper) continue\n\n const { feeGrowthGlobal0, feeGrowthGlobal1, currentTick } = blockData\n\n const feesBelow0 =\n currentTick >= leg.lowerTick\n ? lower.feeGrowthOutside0\n : feeGrowthGlobal0 - lower.feeGrowthOutside0\n const feesBelow1 =\n currentTick >= leg.lowerTick\n ? lower.feeGrowthOutside1\n : feeGrowthGlobal1 - lower.feeGrowthOutside1\n\n const feesAbove0 =\n currentTick < leg.upperTick\n ? upper.feeGrowthOutside0\n : feeGrowthGlobal0 - upper.feeGrowthOutside0\n const feesAbove1 =\n currentTick < leg.upperTick\n ? upper.feeGrowthOutside1\n : feeGrowthGlobal1 - upper.feeGrowthOutside1\n\n const fees0 = ((feeGrowthGlobal0 - feesBelow0 - feesAbove0) * leg.liquidity) / (1n << 128n)\n const fees1 = ((feeGrowthGlobal1 - feesBelow1 - feesAbove1) * leg.liquidity) / (1n << 128n)\n\n total0 += fees0\n total1 += fees1\n }\n\n return { total0, total1 }\n}\n\n// ── Block snapshot fetchers ──────────────────────────────────────────\n\nasync function fetchUniswapBlockSnapshot(\n client: PublicClient,\n blockNumber: bigint | undefined,\n uniqueTicks: number[],\n poolConfig: PoolVersionConfig,\n): Promise<UniswapBlockData> {\n if (poolConfig.version === 'v3') {\n return fetchV3BlockSnapshot(client, poolConfig.poolAddress, blockNumber, uniqueTicks)\n } else {\n return fetchV4BlockSnapshot(\n client,\n poolConfig.stateViewAddress,\n poolConfig.poolId,\n blockNumber,\n uniqueTicks,\n )\n }\n}\n\nasync function fetchV3BlockSnapshot(\n client: PublicClient,\n poolAddress: Address,\n blockNumber: bigint | undefined,\n uniqueTicks: number[],\n): Promise<UniswapBlockData> {\n const contracts = [\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'slot0' as const },\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'feeGrowthGlobal0X128' as const },\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'feeGrowthGlobal1X128' as const },\n ...uniqueTicks.map((tick) => ({\n address: poolAddress,\n abi: uniswapV3PoolAbi,\n functionName: 'ticks' as const,\n args: [tick] as const,\n })),\n ]\n\n const results = await client.multicall({ contracts, blockNumber, allowFailure: false })\n\n const slot0Result = results[0] as readonly [\n bigint,\n number,\n number,\n number,\n number,\n number,\n boolean,\n ]\n const feeGrowthGlobal0 = results[1] as bigint\n const feeGrowthGlobal1 = results[2] as bigint\n\n const tickData = new Map<number, { feeGrowthOutside0: bigint; feeGrowthOutside1: bigint }>()\n for (let i = 0; i < uniqueTicks.length; i++) {\n const tickResult = results[3 + i] as readonly [\n bigint,\n bigint,\n bigint,\n bigint,\n bigint,\n bigint,\n number,\n boolean,\n ]\n tickData.set(uniqueTicks[i], {\n feeGrowthOutside0: tickResult[2],\n feeGrowthOutside1: tickResult[3],\n })\n }\n\n return { currentTick: slot0Result[1], feeGrowthGlobal0, feeGrowthGlobal1, tickData }\n}\n\nasync function fetchV4BlockSnapshot(\n client: PublicClient,\n stateViewAddress: Address,\n poolId: `0x${string}`,\n blockNumber: bigint | undefined,\n uniqueTicks: number[],\n): Promise<UniswapBlockData> {\n const contracts = [\n {\n address: stateViewAddress,\n abi: stateViewAbi,\n functionName: 'getSlot0' as const,\n args: [poolId] as const,\n },\n {\n address: stateViewAddress,\n abi: stateViewAbi,\n functionName: 'getFeeGrowthGlobals' as const,\n args: [poolId] as const,\n },\n ...uniqueTicks.map((tick) => ({\n address: stateViewAddress,\n abi: stateViewAbi,\n functionName: 'getTickInfo' as const,\n args: [poolId, tick] as const,\n })),\n ]\n\n const results = await client.multicall({ contracts, blockNumber, allowFailure: false })\n\n const slot0Result = results[0] as readonly [bigint, number, number, number]\n const feeGrowthResult = results[1] as readonly [bigint, bigint]\n\n const tickData = new Map<number, { feeGrowthOutside0: bigint; feeGrowthOutside1: bigint }>()\n for (let i = 0; i < uniqueTicks.length; i++) {\n const tickResult = results[2 + i] as readonly [bigint, bigint, bigint, bigint]\n tickData.set(uniqueTicks[i], {\n feeGrowthOutside0: tickResult[2],\n feeGrowthOutside1: tickResult[3],\n })\n }\n\n return {\n currentTick: slot0Result[1],\n feeGrowthGlobal0: feeGrowthResult[0],\n feeGrowthGlobal1: feeGrowthResult[1],\n tickData,\n }\n}\n","/**\n * Historical streamia (streaming premia) reads for the Panoptic v2 SDK.\n *\n * Fetches Panoptic premia and optionally Uniswap fee accrual across a series\n * of historical block numbers for a single position. Composes\n * getUniswapFeeHistory internally for the Uniswap fee component.\n *\n * @module v2/reads/streamiaHistory\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { InvalidHistoryRangeError } from '../errors/sdk'\nimport type { BlockMeta } from '../types'\nimport type { PoolVersionConfig } from '../types/poolConfig'\nimport type { StreamiaLeg } from '../types/streamia'\nimport { computeUniswapFeesForBlock, fetchUniswapFeeData } from './uniswapFeeHistory'\n\n// Re-export types that were originally defined here for backward compatibility\nexport type { PoolVersionConfig, V3PoolConfig, V4PoolConfig } from '../types/poolConfig'\nexport type { StreamiaLeg } from '../types/streamia'\n\n// ── Types ──────────────────────────────────────────────────────────────\n\n/** A settled premia event, used to subtract already-settled amounts. */\nexport interface SettledEvent {\n /** Block at which settlement occurred */\n blockNumber: bigint\n /** Amount settled for token 0 */\n settled0: bigint\n /** Amount settled for token 1 */\n settled1: bigint\n}\n\n/** Parameters for getStreamiaHistory. */\nexport interface GetStreamiaHistoryParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool contract address */\n panopticPoolAddress: Address\n /** Account whose position to query */\n account: Address\n /** The encoded tokenId */\n tokenId: bigint\n /** Block numbers to query; undefined entries resolve to latest */\n blockNumbers: (bigint | undefined)[]\n /** Decoded legs with pre-computed liquidity */\n legs: StreamiaLeg[]\n /** Pool version config (carries pool address / StateView + poolId) */\n poolConfig: PoolVersionConfig\n /** Whether to include Uniswap fee data (default: true) */\n includeUniswapFees?: boolean\n /** Settled premia events to subtract from Panoptic premia (optional) */\n settledEvents?: SettledEvent[]\n /** Pre-fetched block metadata (skips an extra eth_getBlockByNumber if provided) */\n _meta?: BlockMeta\n}\n\n/** A single snapshot of streamia data at a particular block. */\nexport interface StreamiaSnapshot {\n /** Block number (undefined if queried as latest) */\n blockNumber: bigint | undefined\n /** Net Panoptic premia (short - long), after subtracting settled amounts */\n panopticPremia: { token0: bigint; token1: bigint }\n /** Uniswap fee delta from the first block in the series */\n uniswapFees: { token0: bigint; token1: bigint }\n}\n\n/** Result from getStreamiaHistory. */\nexport interface StreamiaHistoryResult {\n /** Snapshots in the same order as input blockNumbers */\n snapshots: StreamiaSnapshot[]\n /** Block metadata for the latest block used */\n _meta: BlockMeta\n}\n\n// 128-bit mask for LeftRight decoding\nconst MASK_128 = (1n << 128n) - 1n\n\n// ── Main function ──────────────────────────────────────────────────────\n\n/**\n * Get historical streamia data for a position across multiple blocks.\n *\n * @param params - The parameters\n * @returns Snapshots of Panoptic premia and Uniswap fee deltas at each block\n */\nexport async function getStreamiaHistory(\n params: GetStreamiaHistoryParams,\n): Promise<StreamiaHistoryResult> {\n const {\n client,\n panopticPoolAddress,\n account,\n tokenId,\n blockNumbers,\n legs,\n poolConfig,\n includeUniswapFees = true,\n settledEvents,\n } = params\n\n // Validate legs\n for (const leg of legs) {\n if (leg.lowerTick >= leg.upperTick) {\n throw new InvalidHistoryRangeError(\n `Leg lowerTick (${leg.lowerTick}) must be < upperTick (${leg.upperTick})`,\n )\n }\n if (leg.liquidity <= 0n) {\n throw new InvalidHistoryRangeError(`Leg liquidity must be > 0, got ${leg.liquidity}`)\n }\n }\n\n if (blockNumbers.length === 0) {\n const _meta = params._meta ?? (await getBlockMeta({ client }))\n return { snapshots: [], _meta }\n }\n\n // ── 1. Panoptic premia: one readContract per block ─────────────────\n const premiaRequests = blockNumbers.map((bn) =>\n client.readContract({\n address: panopticPoolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, true, [tokenId]],\n blockNumber: bn,\n }),\n )\n\n // ── 2. Uniswap fees (delegated to uniswapFeeHistory internals) ────\n const uniswapDataPromise =\n includeUniswapFees && legs.length > 0\n ? fetchUniswapFeeData(client, blockNumbers, legs, poolConfig)\n : undefined\n\n // ── 3. Fire all in parallel ────────────────────────────────────────\n const [premiaResults, uniswapData, _meta] = await Promise.all([\n Promise.all(premiaRequests),\n uniswapDataPromise ?? Promise.resolve(undefined),\n params._meta ? Promise.resolve(params._meta) : getBlockMeta({ client }),\n ])\n\n // ── 4. Pre-sort settled events for O(n+m) accumulation ─────────────\n const sortedSettled = settledEvents\n ? [...settledEvents].sort((a, b) => (a.blockNumber < b.blockNumber ? -1 : 1))\n : []\n\n // ── 5. Build snapshots ─────────────────────────────────────────────\n let settledIdx = 0\n let accSettled0 = 0n\n let accSettled1 = 0n\n\n let initialUniswapFees0: bigint | null = null\n let initialUniswapFees1: bigint | null = null\n\n const snapshots: StreamiaSnapshot[] = premiaResults.map((result, i) => {\n const bn = blockNumbers[i]\n\n const shortPacked = result[0]\n const longPacked = result[1]\n\n const short0 = shortPacked & MASK_128\n const short1 = shortPacked >> 128n\n const long0 = longPacked & MASK_128\n const long1 = longPacked >> 128n\n\n // Advance settled accumulator\n const effectiveBn = bn ?? BigInt(Number.MAX_SAFE_INTEGER)\n while (\n settledIdx < sortedSettled.length &&\n sortedSettled[settledIdx].blockNumber <= effectiveBn\n ) {\n accSettled0 += sortedSettled[settledIdx].settled0\n accSettled1 += sortedSettled[settledIdx].settled1\n settledIdx++\n }\n\n const premia0 = short0 - long0 - accSettled0\n const premia1 = short1 - long1 - accSettled1\n\n let uniswapFees0 = 0n\n let uniswapFees1 = 0n\n\n if (uniswapData) {\n const blockData = uniswapData[i]\n const { total0, total1 } = computeUniswapFeesForBlock(blockData, legs)\n\n if (initialUniswapFees0 === null) {\n initialUniswapFees0 = total0\n initialUniswapFees1 = total1\n }\n uniswapFees0 = total0 - initialUniswapFees0\n uniswapFees1 = total1 - (initialUniswapFees1 as bigint)\n }\n\n return {\n blockNumber: bn,\n panopticPremia: { token0: premia0, token1: premia1 },\n uniswapFees: { token0: uniswapFees0, token1: uniswapFees1 },\n }\n })\n\n return { snapshots, _meta }\n}\n","/**\n * Direct Uniswap V3 pool read — no Panoptic deployment required.\n *\n * @module v2/reads/uniswapPool\n */\n\nimport type { Address, Hex, PublicClient } from 'viem'\nimport { encodeAbiParameters, keccak256, zeroAddress } from 'viem'\n\nimport { panopticQueryAbi } from '../abis/panopticQuery'\nimport { stateViewAbi } from '../abis/stateView'\nimport { uniswapV3PoolAbi } from '../abis/uniswapV3Pool'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { PanopticValidationError } from '../errors'\nimport type { BlockMeta } from '../types'\n\nconst erc20MetaAbi = [\n {\n type: 'function',\n name: 'symbol',\n inputs: [],\n outputs: [{ type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'name',\n inputs: [],\n outputs: [{ type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'decimals',\n inputs: [],\n outputs: [{ type: 'uint8' }],\n stateMutability: 'view',\n },\n] as const\n\nexport interface UniswapV3PoolToken {\n address: Address\n symbol: string\n name: string\n decimals: number\n}\n\nexport interface UniswapV3PoolInfo {\n poolAddress: Address\n token0: UniswapV3PoolToken\n token1: UniswapV3PoolToken\n /** Fee tier in hundredths of a bip (e.g. 500 = 0.05%) */\n fee: number\n tickSpacing: number\n currentTick: number\n sqrtPriceX96: bigint\n liquidity: bigint\n /**\n * Packed protocol fee from slot0: `feeProtocol1 << 4 | feeProtocol0`. Each\n * nibble `n` denotes a protocol fee of `1/n` of the swap fee (`0` = off).\n */\n feeProtocol: bigint\n _meta: BlockMeta\n}\n\nexport interface GetUniswapV3PoolInfoParams {\n client: PublicClient\n poolAddress: Address\n}\n\n/**\n * Fetch core data for a Uniswap V3 pool directly from chain.\n *\n * Does NOT require a Panoptic deployment — works for any V3 pool address.\n */\nexport async function getUniswapV3PoolInfo(\n params: GetUniswapV3PoolInfoParams,\n): Promise<UniswapV3PoolInfo> {\n const { client, poolAddress } = params\n\n // Pin every read to the same block so pool state + token metadata are\n // self-consistent. Pool reads run first because token0/token1 are needed to\n // address the ERC20 metadata calls; the second multicall is pinned to the\n // same block as the first.\n const _meta = await getBlockMeta({ client })\n\n const [slot0, fee, tickSpacing, token0Addr, token1Addr, liquidity] = await client.multicall({\n allowFailure: false,\n blockNumber: _meta.blockNumber,\n contracts: [\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'slot0' },\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'fee' },\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'tickSpacing' },\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'token0' },\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'token1' },\n { address: poolAddress, abi: uniswapV3PoolAbi, functionName: 'liquidity' },\n ],\n })\n\n const [t0Symbol, t0Name, t0Decimals, t1Symbol, t1Name, t1Decimals] = await client.multicall({\n allowFailure: false,\n blockNumber: _meta.blockNumber,\n contracts: [\n { address: token0Addr, abi: erc20MetaAbi, functionName: 'symbol' },\n { address: token0Addr, abi: erc20MetaAbi, functionName: 'name' },\n { address: token0Addr, abi: erc20MetaAbi, functionName: 'decimals' },\n { address: token1Addr, abi: erc20MetaAbi, functionName: 'symbol' },\n { address: token1Addr, abi: erc20MetaAbi, functionName: 'name' },\n { address: token1Addr, abi: erc20MetaAbi, functionName: 'decimals' },\n ],\n })\n\n return {\n poolAddress,\n token0: {\n address: token0Addr,\n symbol: t0Symbol,\n name: t0Name,\n decimals: Number(t0Decimals),\n },\n token1: {\n address: token1Addr,\n symbol: t1Symbol,\n name: t1Name,\n decimals: Number(t1Decimals),\n },\n fee: Number(fee),\n tickSpacing: Number(tickSpacing),\n currentTick: Number(slot0[1]),\n sqrtPriceX96: slot0[0],\n liquidity,\n feeProtocol: BigInt(slot0[5]),\n _meta,\n }\n}\n\nexport interface UniswapV3Liquidities {\n ticks: bigint[]\n liquidityNets: bigint[]\n _meta: BlockMeta\n}\n\nexport interface GetUniswapV3PoolLiquiditiesParams {\n client: PublicClient\n /** Uniswap V3 pool address */\n poolAddress: Address\n /** PanopticQuery address — must expose the public `getTickNetsV3` overload */\n queryAddress: Address\n /** Center tick of the range to scan */\n startTick: number\n /** Number of ticks on each side of startTick to scan */\n nTicks: bigint\n}\n\n/** Absolute Uniswap V3/V4 tick bounds. */\nconst TICK_MIN = -887272\nconst TICK_MAX = 887272\n\n/**\n * Clamp `nTicks` so the scan range\n * [scaled(startTick) − nTicks·tickSpacing, scaled(startTick) + nTicks·tickSpacing]\n * stays within [TICK_MIN, TICK_MAX]. Required because PanopticQuery's\n * getTickNetsV3/V4 revert with \"Tick out of bounds\" otherwise.\n */\nfunction clampNTicks(startTick: number, tickSpacing: number, nTicks: bigint): bigint {\n if (!Number.isInteger(tickSpacing) || tickSpacing <= 0) {\n throw new PanopticValidationError(\n `clampNTicks: tickSpacing must be a positive integer, got ${tickSpacing}`,\n )\n }\n const scaled = Math.trunc(startTick / tickSpacing) * tickSpacing\n const maxUp = Math.floor((TICK_MAX - scaled) / tickSpacing)\n const maxDown = Math.floor((scaled - TICK_MIN) / tickSpacing)\n const safe = BigInt(Math.max(0, Math.min(maxUp, maxDown)))\n return nTicks < safe ? nTicks : safe\n}\n\n/**\n * Fetch cumulative liquidity distribution for a Uniswap V3 pool via\n * `PanopticQuery.getTickNetsV3`. Does NOT require a Panoptic market to exist\n * for the pool — only a deployed PanopticQuery on the chain.\n */\nexport async function getUniswapV3PoolLiquidities(\n params: GetUniswapV3PoolLiquiditiesParams,\n): Promise<UniswapV3Liquidities> {\n const { client, poolAddress, queryAddress, startTick, nTicks } = params\n\n // We don't know tickSpacing here; PanopticQuery reads it from the pool.\n // For safety, clamp against the worst case (tickSpacing = 1).\n const safeN = clampNTicks(startTick, 1, nTicks)\n\n // Pin the read to a specific block so the returned ticks/liquidityNets\n // are consistent with the _meta we hand back.\n const _meta = await getBlockMeta({ client })\n const [ticks, liquidityNets] = await client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getTickNetsV3',\n args: [poolAddress, startTick, safeN],\n blockNumber: _meta.blockNumber,\n })\n\n return {\n ticks: [...ticks],\n liquidityNets: [...liquidityNets],\n _meta,\n }\n}\n\n// ============================================================================\n// V4\n// ============================================================================\n\nexport interface UniswapV4PoolKey {\n currency0: Address\n currency1: Address\n /** Fee in hundredths of a bip (e.g. 500 = 0.05%) */\n fee: number\n tickSpacing: number\n hooks: Address\n}\n\nconst POOL_KEY_ABI_PARAMS = [\n {\n type: 'tuple',\n components: [\n { name: 'currency0', type: 'address' },\n { name: 'currency1', type: 'address' },\n { name: 'fee', type: 'uint24' },\n { name: 'tickSpacing', type: 'int24' },\n { name: 'hooks', type: 'address' },\n ],\n },\n] as const\n\n/** Compute the v4 poolId from a PoolKey: `keccak256(abi.encode(poolKey))`. */\nexport function computeV4PoolId(poolKey: UniswapV4PoolKey): Hex {\n return keccak256(\n encodeAbiParameters(POOL_KEY_ABI_PARAMS, [\n {\n currency0: poolKey.currency0,\n currency1: poolKey.currency1,\n fee: poolKey.fee,\n tickSpacing: poolKey.tickSpacing,\n hooks: poolKey.hooks,\n },\n ]),\n )\n}\n\nexport interface ResolveUniswapV4PoolKeyParams {\n client: PublicClient\n /** Uniswap V4 PoolManager address */\n poolManager: Address\n /** The bytes32 poolId hash */\n poolId: Hex\n /** Lower bound block for the scan (defaults to 0n) */\n fromBlock?: bigint\n /**\n * Per-request block range. Many RPCs cap getLogs at 10k/50k blocks;\n * defaults to 9_500 to stay under common limits.\n */\n chunkSize?: bigint\n /**\n * Number of chunked getLogs requests fired in parallel per batch.\n * Higher = faster but more likely to trip RPC rate limits. Default 8.\n */\n concurrency?: number\n}\n\n/**\n * Resolve a V4 PoolKey from its poolId by scanning `Initialize` event logs\n * on the PoolManager, filtered on the indexed `id` topic.\n *\n * Walks backwards from the latest block in `chunkSize` increments to\n * accommodate RPCs that cap getLogs ranges. Chunks are fired in parallel\n * batches of `concurrency` to keep wall-clock time low; returns as soon as\n * any batch produces a match. Throws if no event is found or if the\n * recomputed poolId does not match the queried one.\n */\nexport async function resolveUniswapV4PoolKey(\n _params: ResolveUniswapV4PoolKeyParams,\n): Promise<UniswapV4PoolKey> {\n // Disabled to save on RPC costs — the Initialize-event scan over the full\n // PoolManager history can issue dozens of eth_getLogs requests per\n // first-load resolution. Re-enable by uncommenting the body below.\n throw new PanopticValidationError(\n 'resolveUniswapV4PoolKey is disabled. ' +\n 'Resolve the V4 PoolKey via your indexer (e.g. Ponder) and pass it to getUniswapV4PoolInfo directly.',\n )\n\n /*\n const {\n client,\n poolManager,\n poolId,\n fromBlock = 0n,\n chunkSize = 9_500n,\n concurrency = 8,\n } = _params\n\n const latest = await client.getBlockNumber()\n\n // Pre-compute all chunk ranges, walking backwards.\n const ranges: Array<{ from: bigint; to: bigint }> = []\n let to = latest\n while (to >= fromBlock) {\n const from = to - chunkSize + 1n > fromBlock ? to - chunkSize + 1n : fromBlock\n ranges.push({ from, to })\n if (from === fromBlock) break\n to = from - 1n\n }\n\n let foundLogs: Awaited<ReturnType<PublicClient['getLogs']>> = []\n\n for (let i = 0; i < ranges.length; i += concurrency) {\n const batch = ranges.slice(i, i + concurrency)\n const results = await Promise.all(\n batch.map((r) =>\n client.getLogs({\n address: poolManager,\n event: uniswapV4PoolManagerAbi[0],\n args: { id: poolId },\n fromBlock: r.from,\n toBlock: r.to,\n }),\n ),\n )\n const hit = results.find((logs) => logs.length > 0)\n if (hit) {\n foundLogs = hit\n break\n }\n }\n\n if (foundLogs.length === 0) {\n throw new Error(`No Initialize event found for poolId ${poolId} on PoolManager ${poolManager}`)\n }\n\n const args = (foundLogs[0] as { args: Record<string, unknown> }).args as {\n id: Hex\n currency0: Address\n currency1: Address\n fee: number\n tickSpacing: number\n hooks: Address\n }\n\n const key: UniswapV4PoolKey = {\n currency0: args.currency0,\n currency1: args.currency1,\n fee: Number(args.fee),\n tickSpacing: Number(args.tickSpacing),\n hooks: args.hooks,\n }\n\n const recomputed = computeV4PoolId(key)\n if (recomputed.toLowerCase() !== poolId.toLowerCase()) {\n throw new Error(\n `Recomputed poolId ${recomputed} does not match queried ${poolId} — PoolKey encoding mismatch`,\n )\n }\n\n return key\n */\n}\n\n/**\n * Slot0 + liquidity for a V4 pool by poolId — does NOT require the PoolKey.\n * Used to render basic info (currentTick, sqrtPriceX96, liquidity) when the\n * PoolKey is unknown.\n */\nexport interface UniswapV4PoolBasicState {\n poolId: Hex\n sqrtPriceX96: bigint\n currentTick: number\n /** Dynamic LP fee from slot0 (NOT necessarily the static PoolKey.fee). */\n lpFee: number\n liquidity: bigint\n _meta: BlockMeta\n}\n\nexport interface GetUniswapV4PoolBasicStateParams {\n client: PublicClient\n stateViewAddress: Address\n poolId: Hex\n}\n\nexport async function getUniswapV4PoolBasicState(\n params: GetUniswapV4PoolBasicStateParams,\n): Promise<UniswapV4PoolBasicState> {\n const { client, stateViewAddress, poolId } = params\n // Pin slot0 + liquidity to the same block as the returned _meta.\n const _meta = await getBlockMeta({ client })\n const [slot0, liquidity] = await client.multicall({\n allowFailure: false,\n blockNumber: _meta.blockNumber,\n contracts: [\n { address: stateViewAddress, abi: stateViewAbi, functionName: 'getSlot0', args: [poolId] },\n {\n address: stateViewAddress,\n abi: stateViewAbi,\n functionName: 'getLiquidity',\n args: [poolId],\n },\n ],\n })\n return {\n poolId,\n sqrtPriceX96: slot0[0],\n currentTick: Number(slot0[1]),\n lpFee: Number(slot0[3]),\n liquidity,\n _meta,\n }\n}\n\nexport interface UniswapV4PoolInfo {\n poolId: Hex\n poolKey: UniswapV4PoolKey\n token0: UniswapV3PoolToken\n token1: UniswapV3PoolToken\n fee: number\n tickSpacing: number\n hooks: Address\n currentTick: number\n sqrtPriceX96: bigint\n liquidity: bigint\n _meta: BlockMeta\n}\n\nexport interface GetUniswapV4PoolInfoParams {\n client: PublicClient\n stateViewAddress: Address\n poolKey: UniswapV4PoolKey\n}\n\n/** Synthetic token metadata for native ETH (currency address `0x0`). */\nconst NATIVE_ETH_META = { symbol: 'ETH', name: 'Ether', decimals: 18 } as const\n\nasync function readErc20Meta(\n client: PublicClient,\n address: Address,\n blockNumber?: bigint,\n): Promise<{ symbol: string; name: string; decimals: number }> {\n const [symbol, name, decimals] = await client.multicall({\n allowFailure: false,\n blockNumber,\n contracts: [\n { address, abi: erc20MetaAbi, functionName: 'symbol' },\n { address, abi: erc20MetaAbi, functionName: 'name' },\n { address, abi: erc20MetaAbi, functionName: 'decimals' },\n ],\n })\n return { symbol, name, decimals: Number(decimals) }\n}\n\n/**\n * Fetch core data for a Uniswap V4 pool directly from chain.\n *\n * Does NOT require a Panoptic deployment — only StateView + (for non-native\n * currencies) ERC20s. Caller must supply a resolved PoolKey (see\n * `resolveUniswapV4PoolKey`).\n */\nexport async function getUniswapV4PoolInfo(\n params: GetUniswapV4PoolInfoParams,\n): Promise<UniswapV4PoolInfo> {\n const { client, stateViewAddress, poolKey } = params\n const poolId = computeV4PoolId(poolKey)\n\n // Skip ERC20 metadata reads for native ETH (currency `0x0`) so the\n // multicall doesn't revert, and substitute synthetic metadata.\n const c0IsNative = poolKey.currency0 === zeroAddress\n const c1IsNative = poolKey.currency1 === zeroAddress\n\n const _meta = await getBlockMeta({ client })\n\n // State reads (slot0 + liquidity) batched in one multicall.\n const [slot0, liquidity] = await client.multicall({\n allowFailure: false,\n blockNumber: _meta.blockNumber,\n contracts: [\n { address: stateViewAddress, abi: stateViewAbi, functionName: 'getSlot0', args: [poolId] },\n {\n address: stateViewAddress,\n abi: stateViewAbi,\n functionName: 'getLiquidity',\n args: [poolId],\n },\n ],\n })\n\n // ERC20 metadata (skipped for native ETH) batched in a second multicall,\n // pinned to the same block as the state reads above for consistency.\n const token0Meta = c0IsNative\n ? { ...NATIVE_ETH_META }\n : await readErc20Meta(client, poolKey.currency0, _meta.blockNumber)\n const token1Meta = c1IsNative\n ? { ...NATIVE_ETH_META }\n : await readErc20Meta(client, poolKey.currency1, _meta.blockNumber)\n\n return {\n poolId,\n poolKey,\n token0: { address: poolKey.currency0, ...token0Meta },\n token1: { address: poolKey.currency1, ...token1Meta },\n fee: poolKey.fee,\n tickSpacing: poolKey.tickSpacing,\n hooks: poolKey.hooks,\n currentTick: Number(slot0[1]),\n sqrtPriceX96: slot0[0],\n liquidity,\n _meta,\n }\n}\n\nexport interface GetUniswapV4PoolLiquiditiesParams {\n client: PublicClient\n queryAddress: Address\n poolManager: Address\n poolId: Hex\n tickSpacing: number\n startTick: number\n nTicks: bigint\n}\n\n/**\n * Fetch cumulative liquidity distribution for a Uniswap V4 pool via\n * `PanopticQuery.getTickNetsV4`. Does NOT require a Panoptic market for the pool.\n */\nexport async function getUniswapV4PoolLiquidities(\n params: GetUniswapV4PoolLiquiditiesParams,\n): Promise<UniswapV3Liquidities> {\n const { client, queryAddress, poolManager, poolId, tickSpacing, startTick, nTicks } = params\n\n const safeN = clampNTicks(startTick, tickSpacing, nTicks)\n\n // Pin to a specific block so the returned ticks/liquidityNets match _meta.\n const _meta = await getBlockMeta({ client })\n const [ticks, liquidityNets] = await client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getTickNetsV4',\n args: [poolManager, poolId, tickSpacing, startTick, safeN],\n blockNumber: _meta.blockNumber,\n })\n\n return {\n ticks: [...ticks],\n liquidityNets: [...liquidityNets],\n _meta,\n }\n}\n","/**\n * Historical price reads for the Panoptic v2 SDK.\n *\n * Fetches slot0 (tick + sqrtPriceX96) across a series of historical blocks\n * for price-over-time charting. All block reads are parallelized via\n * Promise.all (viem auto-batches into multicall).\n *\n * @module v2/reads/priceHistory\n */\n\nimport type { PublicClient } from 'viem'\n\nimport { stateViewAbi } from '../abis/stateView'\nimport { uniswapV3PoolAbi } from '../abis/uniswapV3Pool'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport type { BlockMeta } from '../types'\nimport type { PoolVersionConfig } from '../types/poolConfig'\n\n// ── Types ──────────────────────────────────────────────────────────────\n\n/** A single price snapshot at a particular block. */\nexport interface PriceSnapshot {\n /** Block number (undefined if queried as latest) */\n blockNumber: bigint | undefined\n /** Current tick of the pool at this block */\n tick: number\n /** sqrtPriceX96 at this block */\n sqrtPriceX96: bigint\n}\n\n/** Result from getPriceHistory. */\nexport interface PriceHistoryResult {\n /** Snapshots in the same order as input blockNumbers */\n snapshots: PriceSnapshot[]\n /** Block metadata for the latest block used */\n _meta: BlockMeta\n}\n\n/** Parameters for getPriceHistory. */\nexport interface GetPriceHistoryParams {\n /** viem PublicClient */\n client: PublicClient\n /** Block numbers to query; undefined entries resolve to latest */\n blockNumbers: (bigint | undefined)[]\n /** Pool version config (carries pool address / StateView + poolId) */\n poolConfig: PoolVersionConfig\n /** Pre-fetched block metadata (skips an extra eth_getBlockByNumber if provided) */\n _meta?: BlockMeta\n}\n\n// ── Main function ──────────────────────────────────────────────────────\n\n/**\n * Get historical price data (tick + sqrtPriceX96) for a pool across multiple blocks.\n *\n * @param params - The parameters\n * @returns Price snapshots at each block\n *\n * @example\n * ```typescript\n * const { snapshots } = await getPriceHistory({\n * client,\n * blockNumbers: [18000000n, 18000100n, 18000200n],\n * poolConfig: { version: 'v3', poolAddress: '0x...' },\n * })\n *\n * for (const snap of snapshots) {\n * console.log(`Block ${snap.blockNumber}: tick=${snap.tick}`)\n * }\n * ```\n */\nexport async function getPriceHistory(params: GetPriceHistoryParams): Promise<PriceHistoryResult> {\n const { client, blockNumbers, poolConfig } = params\n\n if (blockNumbers.length === 0) {\n const _meta = params._meta ?? (await getBlockMeta({ client }))\n return { snapshots: [], _meta }\n }\n\n // Fire one slot0 read per block. Calls at different historical blocks cannot\n // be coalesced into one multicall, so callers should not poll this path.\n const slot0Requests = blockNumbers.map((bn) => fetchSlot0(client, bn, poolConfig))\n\n const [slot0Results, _meta] = await Promise.all([\n Promise.all(slot0Requests),\n params._meta ? Promise.resolve(params._meta) : getBlockMeta({ client }),\n ])\n\n const snapshots: PriceSnapshot[] = slot0Results.map((result, i) => ({\n blockNumber: blockNumbers[i],\n tick: result.tick,\n sqrtPriceX96: result.sqrtPriceX96,\n }))\n\n return { snapshots, _meta }\n}\n\n// ── Internals ──────────────────────────────────────────────────────────\n\ninterface Slot0Data {\n tick: number\n sqrtPriceX96: bigint\n}\n\nasync function fetchSlot0(\n client: PublicClient,\n blockNumber: bigint | undefined,\n poolConfig: PoolVersionConfig,\n): Promise<Slot0Data> {\n if (poolConfig.version === 'v3') {\n const result = await client.readContract({\n address: poolConfig.poolAddress,\n abi: uniswapV3PoolAbi,\n functionName: 'slot0',\n blockNumber,\n })\n return {\n sqrtPriceX96: result[0],\n tick: result[1],\n }\n } else {\n const result = await client.readContract({\n address: poolConfig.stateViewAddress,\n abi: stateViewAbi,\n functionName: 'getSlot0',\n args: [poolConfig.poolId],\n blockNumber,\n })\n return {\n sqrtPriceX96: result[0],\n tick: result[1],\n }\n }\n}\n","/**\n * Position enrichment data for UI display.\n *\n * Batches all contract reads needed to enrich subgraph position data with\n * on-chain premia, portfolio values, and collateral requirements.\n *\n * @module v2/reads/enrichment\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi, panopticQueryAbi } from '../../../generated'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { PanopticError } from '../errors'\nimport type { BlockMeta } from '../types'\nimport { decodeLeftRightUnsigned } from '../writes/utils'\n\n/**\n * Error thrown when an enrichment contract call fails for a specific position.\n */\nexport class EnrichmentCallError extends PanopticError {\n /** The tokenId of the position that failed */\n readonly tokenId: bigint\n /** The name of the failing call */\n readonly callName: string\n\n constructor(tokenId: bigint, callName: string, cause?: unknown) {\n super(\n `Enrichment call \"${callName}\" failed for tokenId ${tokenId}`,\n cause instanceof Error ? cause : undefined,\n )\n this.tokenId = tokenId\n this.callName = callName\n }\n}\n\n/**\n * Input describing a position for enrichment.\n */\nexport interface PositionInput {\n /** The tokenId (256-bit identifier) */\n tokenId: bigint\n /** Whether the position is currently open */\n isOpen: boolean\n /** Tick at time of mint */\n tickAtMint: number\n /** Account address that owns the position */\n account: Address\n /** Pool address the position belongs to */\n poolAddress: Address\n /** Tick at burn (closed positions only) */\n tickAtBurn?: number\n /** Block number of the burn tx (closed positions only) */\n burnBlockNumber?: bigint\n /** Premium in token0 from subgraph (closed positions only) */\n burnPremium0?: bigint\n /** Premium in token1 from subgraph (closed positions only) */\n burnPremium1?: bigint\n}\n\n/**\n * Enrichment result for a single position.\n *\n * Values are in raw token units (token0 and token1), not asset/quote.\n * The UI maps these to asset/quote based on isAssetToken0.\n */\nexport interface PositionEnrichmentResult {\n /** Net premia owed: shortPremium - longPremium for token0 (open); burnPremium0 for closed */\n premiaOwed0: bigint\n /** Net premia owed: shortPremium - longPremium for token1 (open); burnPremium1 for closed */\n premiaOwed1: bigint\n /** Portfolio value in token0 at current tick (open) or burn tick (closed) */\n portfolioValue0: bigint\n /** Portfolio value in token1 at current tick (open) or burn tick (closed) */\n portfolioValue1: bigint\n /** Portfolio value in token0 at mint tick */\n portfolioValueAtMint0: bigint\n /** Portfolio value in token1 at mint tick */\n portfolioValueAtMint1: bigint\n /**\n * Per-token collateral requirement from `getFullPositionsData.collateralRequirements[]`.\n * These are NOT cross-margined — each is in its own token denomination.\n * For closed positions these are 0n (collateral is moot).\n */\n collateralReqToken0: bigint\n collateralReqToken1: bigint\n}\n\n/**\n * Parameters for getPositionEnrichmentData.\n */\nexport interface GetPositionEnrichmentDataParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticQuery helper contract address */\n queryAddress: Address\n /** Positions to enrich */\n positions: PositionInput[]\n /** Current pool tick (used for open position portfolio values) */\n currentTick: number\n /** Optional block number for open position reads */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata */\n _meta?: BlockMeta\n}\n\n/**\n * Result from getPositionEnrichmentData.\n */\nexport interface GetPositionEnrichmentDataResult {\n /** Enrichment data keyed by tokenId string */\n byTokenId: Map<string, PositionEnrichmentResult>\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Fetch enrichment data (premia, portfolio values, collateral requirements) for a set of positions.\n *\n * Batches all needed contract reads into efficient multicalls:\n * - **Open positions**: 3 calls per position in a single multicall at current block:\n * 1. `getFullPositionsData` → premia + collateral requirements\n * 2. `getPortfolioValue` at currentTick → current portfolio value\n * 3. `getPortfolioValue` at mintTick → portfolio value at mint\n * - **Closed positions**: 2 calls per position at `burnBlockNumber - 1`:\n * 1. `getPortfolioValue` at burnTick → portfolio value at close\n * 2. `getPortfolioValue` at mintTick → portfolio value at mint\n * (premia come from subgraph `burnPremium0/1`)\n *\n * ## Same-Block Guarantee\n * Open position data is fetched at a single block number.\n * Closed position data is fetched at `burnBlockNumber - 1` (per position).\n *\n * @param params - The parameters\n * @returns Map of tokenId → enrichment data, with block metadata\n */\nexport async function getPositionEnrichmentData(\n params: GetPositionEnrichmentDataParams,\n): Promise<GetPositionEnrichmentDataResult> {\n const { client, queryAddress, positions, currentTick, blockNumber } = params\n\n // Fetch a single block metadata for the entire enrichment result\n const _meta = params._meta ?? (await getBlockMeta({ client, blockNumber }))\n\n if (positions.length === 0) {\n return { byTokenId: new Map(), _meta }\n }\n\n const openPositions = positions.filter((p) => p.isOpen)\n const closedPositions = positions.filter((p) => !p.isOpen)\n\n const byTokenId = new Map<string, PositionEnrichmentResult>()\n\n // Process open and closed positions in parallel\n await Promise.all([\n processOpenPositions(client, queryAddress, openPositions, currentTick, blockNumber, _meta),\n processClosedPositions(client, queryAddress, closedPositions),\n ]).then(([openResults, closedResults]) => {\n // Merge results into byTokenId map\n for (const [key, value] of openResults.entries) {\n byTokenId.set(key, value)\n }\n for (const [key, value] of closedResults) {\n byTokenId.set(key, value)\n }\n })\n\n return { byTokenId, _meta }\n}\n\n/** Number of multicall contracts per open position */\nconst OPEN_CALLS_PER_POSITION = 3\n/** Number of multicall contracts per closed position */\nconst CLOSED_CALLS_PER_POSITION = 2\n\n/**\n * Process open positions: single multicall with 5 calls per position.\n */\nasync function processOpenPositions(\n client: PublicClient,\n queryAddress: Address,\n positions: PositionInput[],\n currentTick: number,\n blockNumber: bigint | undefined,\n _meta: BlockMeta,\n): Promise<{ entries: [string, PositionEnrichmentResult][] }> {\n if (positions.length === 0) {\n return { entries: [] }\n }\n\n const targetBlockNumber = blockNumber ?? _meta.blockNumber\n\n // Build multicall contracts: 3 calls per position\n const contracts = positions.flatMap((p) => [\n // 1. getFullPositionsData → premia + collateral requirements\n {\n address: p.poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData' as const,\n args: [p.account, true, [p.tokenId]] as const,\n },\n // 2. getPortfolioValue at currentTick\n {\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getPortfolioValue' as const,\n args: [p.poolAddress, p.account, currentTick, [p.tokenId]] as const,\n },\n // 3. getPortfolioValue at mintTick\n {\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getPortfolioValue' as const,\n args: [p.poolAddress, p.account, p.tickAtMint, [p.tokenId]] as const,\n },\n ])\n\n const multicallResults = await client.multicall({\n contracts,\n blockNumber: targetBlockNumber,\n allowFailure: true,\n })\n\n const entries: [string, PositionEnrichmentResult][] = []\n\n for (let i = 0; i < positions.length; i++) {\n const position = positions[i]\n const baseIdx = i * OPEN_CALLS_PER_POSITION\n\n const premiaResult = multicallResults[baseIdx]\n const portfolioResult = multicallResults[baseIdx + 1]\n const portfolioAtMintResult = multicallResults[baseIdx + 2]\n\n if (premiaResult.status !== 'success') {\n throw new EnrichmentCallError(position.tokenId, 'getFullPositionsData', premiaResult.error)\n }\n if (portfolioResult.status !== 'success') {\n throw new EnrichmentCallError(\n position.tokenId,\n 'getPortfolioValue (currentTick)',\n portfolioResult.error,\n )\n }\n if (portfolioAtMintResult.status !== 'success') {\n throw new EnrichmentCallError(\n position.tokenId,\n 'getPortfolioValue (mintTick)',\n portfolioAtMintResult.error,\n )\n }\n\n // Decode getFullPositionsData: [shortPremium, longPremium, balances[], collateralReqs[], netPremia[]]\n const [shortPremiumPacked, longPremiumPacked, , collateralReqsPacked] = premiaResult.result as [\n bigint,\n bigint,\n bigint[],\n bigint[],\n bigint[],\n ]\n const shortPremium = decodeLeftRightUnsigned(shortPremiumPacked)\n const longPremium = decodeLeftRightUnsigned(longPremiumPacked)\n\n const premiaOwed0 = shortPremium.right - longPremium.right // token0\n const premiaOwed1 = shortPremium.left - longPremium.left // token1\n\n // Decode per-token collateral requirements from collateralReqs[0] (LeftRightUnsigned)\n const collateralReq = decodeLeftRightUnsigned(collateralReqsPacked[0] ?? 0n)\n\n // Decode portfolio values\n const [portfolioValue0, portfolioValue1] = portfolioResult.result as [bigint, bigint]\n const [portfolioValueAtMint0, portfolioValueAtMint1] = portfolioAtMintResult.result as [\n bigint,\n bigint,\n ]\n\n entries.push([\n position.tokenId.toString(),\n {\n premiaOwed0,\n premiaOwed1,\n portfolioValue0,\n portfolioValue1,\n portfolioValueAtMint0,\n portfolioValueAtMint1,\n collateralReqToken0: collateralReq.right,\n collateralReqToken1: collateralReq.left,\n },\n ])\n }\n\n return { entries }\n}\n\n/**\n * Process closed positions: per-position calls at burnBlockNumber - 1.\n *\n * Returns entries array (not a map) to merge into the final result.\n */\nasync function processClosedPositions(\n client: PublicClient,\n queryAddress: Address,\n positions: PositionInput[],\n): Promise<[string, PositionEnrichmentResult][]> {\n if (positions.length === 0) return []\n\n // Group positions by burnBlockNumber for batch efficiency\n const byBlock = new Map<bigint, PositionInput[]>()\n for (const p of positions) {\n if (p.burnBlockNumber == null) continue\n const readBlock = p.burnBlockNumber - 1n\n const group = byBlock.get(readBlock) ?? []\n group.push(p)\n byBlock.set(readBlock, group)\n }\n\n const entries: [string, PositionEnrichmentResult][] = []\n\n // Process each block group\n await Promise.all(\n Array.from(byBlock.entries()).map(async ([readBlock, blockPositions]) => {\n // Build multicall contracts: 2 calls per position\n const contracts = blockPositions.flatMap((p) => [\n // 1. getPortfolioValue at burnTick\n {\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getPortfolioValue' as const,\n args: [p.poolAddress, p.account, p.tickAtBurn ?? 0, [p.tokenId]] as const,\n },\n // 2. getPortfolioValue at mintTick\n {\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getPortfolioValue' as const,\n args: [p.poolAddress, p.account, p.tickAtMint, [p.tokenId]] as const,\n },\n ])\n\n const multicallResults = await client.multicall({\n contracts,\n blockNumber: readBlock,\n allowFailure: true,\n })\n\n for (let i = 0; i < blockPositions.length; i++) {\n const position = blockPositions[i]\n const baseIdx = i * CLOSED_CALLS_PER_POSITION\n\n const portfolioAtBurnResult = multicallResults[baseIdx]\n const portfolioAtMintResult = multicallResults[baseIdx + 1]\n\n // Closed position reads can fail legitimately (e.g. position minted and burned\n // in the same block — at burnBlock-1 it doesn't exist yet). Fall back to zeros.\n const [portfolioValue0, portfolioValue1] =\n portfolioAtBurnResult.status === 'success'\n ? (portfolioAtBurnResult.result as [bigint, bigint])\n : [0n, 0n]\n const [portfolioValueAtMint0, portfolioValueAtMint1] =\n portfolioAtMintResult.status === 'success'\n ? (portfolioAtMintResult.result as [bigint, bigint])\n : [0n, 0n]\n\n entries.push([\n position.tokenId.toString(),\n {\n premiaOwed0: position.burnPremium0 ?? 0n,\n premiaOwed1: position.burnPremium1 ?? 0n,\n portfolioValue0,\n portfolioValue1,\n portfolioValueAtMint0,\n portfolioValueAtMint1,\n collateralReqToken0: 0n,\n collateralReqToken1: 0n,\n },\n ])\n }\n }),\n )\n\n return entries\n}\n","/**\n * Get synchronization status for an account.\n * @module v2/sync/getSyncStatus\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport type { StorageAdapter } from '../storage'\nimport { loadCheckpoint } from './reorgHandling'\n\n/**\n * Parameters for getSyncStatus.\n */\nexport interface GetSyncStatusParams {\n /** viem public client */\n client: PublicClient\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account to check */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n}\n\n/**\n * Sync status result.\n */\nexport interface SyncStatusResult {\n /** Last synced block number (0n if never synced) */\n lastSyncedBlock: bigint\n /** Whether the account is fully synced to current block */\n isSynced: boolean\n /** Number of blocks behind (0n if synced) */\n blocksBehind: bigint\n /** Number of positions tracked */\n positionCount: bigint\n /** Whether a checkpoint exists */\n hasCheckpoint: boolean\n}\n\n/**\n * Get the synchronization status for an account.\n *\n * This function checks the stored checkpoint and compares against\n * the current chain head to determine sync status.\n *\n * @param params - Status parameters\n * @returns Sync status information\n */\nexport async function getSyncStatus(params: GetSyncStatusParams): Promise<SyncStatusResult> {\n const { client, chainId, poolAddress, account, storage } = params\n\n // Get current block\n const currentBlock = await client.getBlockNumber()\n\n // Load checkpoint\n const checkpoint = await loadCheckpoint(storage, chainId, poolAddress, account)\n\n if (!checkpoint) {\n return {\n lastSyncedBlock: 0n,\n isSynced: false,\n blocksBehind: currentBlock,\n positionCount: 0n,\n hasCheckpoint: false,\n }\n }\n\n const blocksBehind = currentBlock - checkpoint.lastBlock\n const isSynced = blocksBehind <= 0n\n\n return {\n lastSyncedBlock: checkpoint.lastBlock,\n isSynced,\n blocksBehind: blocksBehind > 0n ? blocksBehind : 0n,\n positionCount: BigInt(checkpoint.positionIds.length),\n hasCheckpoint: true,\n }\n}\n","/**\n * Trade history tracking for closed positions.\n * @module v2/sync/tradeHistory\n */\n\nimport type { Address } from 'viem'\n\nimport type { StorageAdapter } from '../storage'\nimport { getClosedPositionsKey, jsonSerializer } from '../storage'\nimport type { ClosedPosition, RealizedPnL } from '../types'\n\n/**\n * Parameters for saving a closed position.\n */\nexport interface SaveClosedPositionParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account that owned the position */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** The closed position data */\n closedPosition: ClosedPosition\n}\n\n/**\n * Save a closed position to trade history.\n *\n * @param params - Save parameters\n */\nexport async function saveClosedPosition(params: SaveClosedPositionParams): Promise<void> {\n const { chainId, poolAddress, account, storage, closedPosition } = params\n\n const key = getClosedPositionsKey(chainId, poolAddress, account)\n const existingData = await storage.get(key)\n\n let history: ClosedPosition[]\n if (existingData) {\n try {\n history = jsonSerializer.parse(existingData) as ClosedPosition[]\n } catch {\n history = []\n }\n } else {\n history = []\n }\n\n // Add new closed position\n history.push(closedPosition)\n\n // Sort by close block (most recent first)\n history.sort((a, b) => Number(b.closeBlock - a.closeBlock))\n\n await storage.set(key, jsonSerializer.stringify(history))\n}\n\n/**\n * Parameters for getting trade history.\n */\nexport interface GetTradeHistoryParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account to get history for */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Maximum number of positions to return (default: 100) */\n limit?: bigint\n /** Offset for pagination */\n offset?: bigint\n /** Filter by closure reason */\n closureReason?: 'closed' | 'liquidated' | 'force_exercised'\n /** Filter by block range (from) */\n fromBlock?: bigint\n /** Filter by block range (to) */\n toBlock?: bigint\n}\n\n/**\n * Get trade history (closed positions) for an account.\n *\n * This function reads from local storage, no RPC calls.\n * Positions are returned in reverse chronological order (most recent first).\n *\n * @param params - Query parameters\n * @returns Array of closed positions\n */\nexport async function getTradeHistory(params: GetTradeHistoryParams): Promise<ClosedPosition[]> {\n const {\n chainId,\n poolAddress,\n account,\n storage,\n limit = 100n,\n offset = 0n,\n closureReason,\n fromBlock,\n toBlock,\n } = params\n\n const key = getClosedPositionsKey(chainId, poolAddress, account)\n const data = await storage.get(key)\n\n if (!data) {\n return []\n }\n\n let history: ClosedPosition[]\n try {\n history = jsonSerializer.parse(data) as ClosedPosition[]\n } catch {\n return []\n }\n\n // Apply filters\n if (closureReason) {\n history = history.filter((p) => p.closureReason === closureReason)\n }\n\n if (fromBlock !== undefined) {\n history = history.filter((p) => p.closeBlock >= fromBlock)\n }\n\n if (toBlock !== undefined) {\n history = history.filter((p) => p.closeBlock <= toBlock)\n }\n\n // Apply pagination\n const start = Number(offset)\n const end = start + Number(limit)\n return history.slice(start, end)\n}\n\n/**\n * Get closed positions (alias for getTradeHistory with specific closure reason).\n *\n * @param params - Query parameters\n * @returns Array of closed positions\n */\nexport async function getClosedPositions(params: GetTradeHistoryParams): Promise<ClosedPosition[]> {\n return getTradeHistory(params)\n}\n\n/**\n * Parameters for getting realized PnL.\n */\nexport interface GetRealizedPnLParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account to get PnL for */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Filter by block range (from) */\n fromBlock?: bigint\n /** Filter by block range (to) */\n toBlock?: bigint\n}\n\n/**\n * Get realized PnL summary for an account.\n *\n * Calculates totals from all closed positions in storage.\n *\n * @param params - Query parameters\n * @returns Realized PnL summary\n */\nexport async function getRealizedPnL(params: GetRealizedPnLParams): Promise<RealizedPnL> {\n const { chainId, poolAddress, account, storage, fromBlock, toBlock } = params\n\n const history = await getTradeHistory({\n chainId,\n poolAddress,\n account,\n storage,\n limit: BigInt(Number.MAX_SAFE_INTEGER), // Get all\n fromBlock,\n toBlock,\n })\n\n let total0 = 0n\n let total1 = 0n\n let winCount = 0n\n let lossCount = 0n\n\n for (const position of history) {\n total0 += position.realizedPnL0\n total1 += position.realizedPnL1\n\n // Consider it a win if either token had positive PnL\n // (in practice, one will usually dominate)\n const isWin = position.realizedPnL0 > 0n || position.realizedPnL1 > 0n\n const isLoss = position.realizedPnL0 < 0n || position.realizedPnL1 < 0n\n\n if (isWin && !isLoss) {\n winCount++\n } else if (isLoss && !isWin) {\n lossCount++\n }\n // Mixed results (win on one, loss on other) don't count as either\n }\n\n return {\n total0,\n total1,\n positionCount: BigInt(history.length),\n winCount,\n lossCount,\n }\n}\n\n/**\n * Clear all trade history for an account.\n *\n * @param params - Query parameters\n */\nexport async function clearTradeHistory(\n params: Omit<\n GetTradeHistoryParams,\n 'limit' | 'offset' | 'closureReason' | 'fromBlock' | 'toBlock'\n >,\n): Promise<void> {\n const { chainId, poolAddress, account, storage } = params\n\n const key = getClosedPositionsKey(chainId, poolAddress, account)\n await storage.delete(key)\n}\n","/**\n * Chunk spread tracking for volatility surface data.\n * @module v2/sync/chunkTracking\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticQueryAbi } from '../abis/panopticQuery'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { ChunkLimitError } from '../errors'\nimport type { StorageAdapter } from '../storage'\nimport { getTrackedChunksKey, jsonSerializer } from '../storage'\nimport { DEFAULT_VEGOID } from '../tokenId/constants'\nimport type { BlockMeta } from '../types'\nimport { MAX_TRACKED_CHUNKS, WAD } from '../utils/constants'\n\n/**\n * Key for identifying a liquidity chunk.\n * A chunk is a unique combination of (tokenType, tickLower, tickUpper).\n */\nexport interface LiquidityChunkKey {\n /** Token type: 0n = token0 (put), 1n = token1 (call) */\n tokenType: 0n | 1n\n /** Lower tick bound */\n tickLower: bigint\n /** Upper tick bound */\n tickUpper: bigint\n}\n\n/**\n * Full chunk data with spread calculation.\n */\nexport interface LiquidityChunkSpread extends LiquidityChunkKey {\n /** Liquidity currently deployed in Uniswap */\n netLiquidity: bigint\n /** Liquidity borrowed by option buyers */\n removedLiquidity: bigint\n /** Computed spread: (1 + (1/VEGOID) * removed/net) * 1e18 */\n spreadWad: bigint\n}\n\n/**\n * Parameters for adding tracked chunks.\n */\nexport interface AddTrackedChunksParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Chunks to add */\n chunks: LiquidityChunkKey[]\n}\n\n/**\n * Serialize a chunk key to a string for storage/comparison.\n */\nfunction serializeChunkKey(chunk: LiquidityChunkKey): string {\n return `${chunk.tokenType}:${chunk.tickLower}:${chunk.tickUpper}`\n}\n\n/**\n * Deserialize a chunk key from a string.\n */\nfunction deserializeChunkKey(key: string): LiquidityChunkKey {\n const [tokenType, tickLower, tickUpper] = key.split(':')\n return {\n tokenType: BigInt(tokenType) as 0n | 1n,\n tickLower: BigInt(tickLower),\n tickUpper: BigInt(tickUpper),\n }\n}\n\n/**\n * Add chunks to tracking.\n *\n * @param params - Parameters\n * @throws ChunkLimitError if adding would exceed 1000 chunks\n */\nexport async function addTrackedChunks(params: AddTrackedChunksParams): Promise<void> {\n const { chainId, poolAddress, storage, chunks } = params\n\n const key = getTrackedChunksKey(chainId, poolAddress)\n const existingData = await storage.get(key)\n\n let trackedKeys: Set<string>\n if (existingData) {\n try {\n const keys = jsonSerializer.parse(existingData) as string[]\n trackedKeys = new Set(keys)\n } catch {\n trackedKeys = new Set()\n }\n } else {\n trackedKeys = new Set()\n }\n\n // Add new chunks\n for (const chunk of chunks) {\n const serialized = serializeChunkKey(chunk)\n trackedKeys.add(serialized)\n }\n\n // Check limit\n if (trackedKeys.size > MAX_TRACKED_CHUNKS) {\n const attemptedAdd = BigInt(chunks.length)\n throw new ChunkLimitError(BigInt(trackedKeys.size - chunks.length), attemptedAdd)\n }\n\n await storage.set(key, jsonSerializer.stringify([...trackedKeys]))\n}\n\n/**\n * Parameters for removing tracked chunks.\n */\nexport interface RemoveTrackedChunksParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Chunks to remove */\n chunks: LiquidityChunkKey[]\n}\n\n/**\n * Remove chunks from tracking.\n *\n * @param params - Parameters\n */\nexport async function removeTrackedChunks(params: RemoveTrackedChunksParams): Promise<void> {\n const { chainId, poolAddress, storage, chunks } = params\n\n const key = getTrackedChunksKey(chainId, poolAddress)\n const existingData = await storage.get(key)\n\n if (!existingData) {\n return\n }\n\n let trackedKeys: Set<string>\n try {\n const keys = jsonSerializer.parse(existingData) as string[]\n trackedKeys = new Set(keys)\n } catch {\n return\n }\n\n // Remove chunks\n for (const chunk of chunks) {\n const serialized = serializeChunkKey(chunk)\n trackedKeys.delete(serialized)\n }\n\n if (trackedKeys.size === 0) {\n await storage.delete(key)\n } else {\n await storage.set(key, jsonSerializer.stringify([...trackedKeys]))\n }\n}\n\n/**\n * Parameters for getting tracked chunks.\n */\nexport interface GetTrackedChunksParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Storage adapter */\n storage: StorageAdapter\n}\n\n/**\n * Get all tracked chunk keys.\n *\n * @param params - Parameters\n * @returns Array of tracked chunk keys\n */\nexport async function getTrackedChunks(\n params: GetTrackedChunksParams,\n): Promise<LiquidityChunkKey[]> {\n const { chainId, poolAddress, storage } = params\n\n const key = getTrackedChunksKey(chainId, poolAddress)\n const data = await storage.get(key)\n\n if (!data) {\n return []\n }\n\n try {\n const keys = jsonSerializer.parse(data) as string[]\n return keys.map(deserializeChunkKey)\n } catch {\n return []\n }\n}\n\n/**\n * Parameters for getting chunk spreads (legacy manual tracking).\n * @deprecated Use scanChunks() for automatic chunk discovery\n */\nexport interface GetChunkSpreadsParams {\n /** viem public client */\n client: PublicClient\n /** Chain ID */\n chainId: bigint\n /** Pool address (PanopticPool) */\n poolAddress: Address\n /** SFPM address */\n sfpmAddress: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Optional filter by token type */\n tokenType?: 0n | 1n\n /** VEGOID constant (default: 4n) */\n vegoid?: bigint\n}\n\n/**\n * Get spread data for all tracked chunks (legacy).\n *\n * @deprecated Use scanChunks() for automatic chunk discovery with on-chain data.\n * This function only returns manually tracked chunks.\n *\n * @param params - Parameters\n * @returns Array of chunk spreads with liquidity data\n */\nexport async function getChunkSpreads(\n params: GetChunkSpreadsParams,\n): Promise<LiquidityChunkSpread[]> {\n const { chainId, poolAddress, storage, tokenType } = params\n\n // Get tracked chunks\n let chunks = await getTrackedChunks({ chainId, poolAddress, storage })\n\n // Apply filter\n if (tokenType !== undefined) {\n chunks = chunks.filter((c) => c.tokenType === tokenType)\n }\n\n if (chunks.length === 0) {\n return []\n }\n\n // Return tracked chunks without liquidity data\n // Use scanChunks() for on-chain liquidity data\n return chunks.map((chunk) => ({\n ...chunk,\n netLiquidity: 0n,\n removedLiquidity: 0n,\n spreadWad: WAD,\n }))\n}\n\n/**\n * Calculate spread from liquidity values.\n *\n * spread = 1 + (1/VEGOID) * removedLiquidity / netLiquidity\n *\n * @param netLiquidity - Liquidity in Uniswap\n * @param removedLiquidity - Liquidity borrowed by buyers\n * @param vegoid - VEGOID constant (default: 4n)\n * @returns Spread in WAD (1e18 = 1.0x)\n */\nexport function calculateSpreadWad(\n netLiquidity: bigint,\n removedLiquidity: bigint,\n vegoid: bigint = DEFAULT_VEGOID,\n): bigint {\n if (netLiquidity === 0n) {\n return WAD // 1.0x spread if no liquidity\n }\n\n // spread = WAD + (WAD / vegoid) * removedLiquidity / netLiquidity\n // = WAD + (WAD * removedLiquidity) / (vegoid * netLiquidity)\n const bonus = (WAD * removedLiquidity) / (vegoid * netLiquidity)\n return WAD + bonus\n}\n\n/**\n * Clear all tracked chunks for a pool.\n *\n * @param params - Parameters\n */\nexport async function clearTrackedChunks(params: GetTrackedChunksParams): Promise<void> {\n const { chainId, poolAddress, storage } = params\n\n const key = getTrackedChunksKey(chainId, poolAddress)\n await storage.delete(key)\n}\n\n// ============================================================================\n// PanopticQuery-based chunk functions (recommended)\n// ============================================================================\n\n/**\n * Scanned chunk with liquidity data from PanopticQuery.scanChunks().\n */\nexport interface ScannedChunk {\n /** Strike tick (center of the chunk) */\n strike: bigint\n /** Token type 0 net liquidity */\n netLiquidity0: bigint\n /** Token type 1 net liquidity */\n netLiquidity1: bigint\n /** Token type 0 removed liquidity */\n removedLiquidity0: bigint\n /** Token type 1 removed liquidity */\n removedLiquidity1: bigint\n /** Computed spread for token type 0 */\n spreadWad0: bigint\n /** Computed spread for token type 1 */\n spreadWad1: bigint\n /** Token type 0 settled tokens (LeftRightUnsigned: left=token1, right=token0) */\n settledTokens0: bigint\n /** Token type 1 settled tokens (LeftRightUnsigned: left=token1, right=token0) */\n settledTokens1: bigint\n}\n\n/**\n * Result of scanning chunks in a tick range.\n */\nexport interface ScanChunksResult {\n /** Array of scanned chunks with liquidity data */\n chunks: ScannedChunk[]\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for scanChunks().\n */\nexport interface ScanChunksParams {\n /** viem public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** PanopticQuery contract address */\n queryAddress: Address\n /** Lower tick bound of range to scan */\n tickLower: bigint\n /** Upper tick bound of range to scan */\n tickUpper: bigint\n /** Width of chunks to scan (tickUpper - tickLower for each chunk) */\n width: bigint\n /** VEGOID constant for spread calculation (default: 4n) */\n vegoid?: bigint\n /** Optional block number for historical queries */\n blockNumber?: bigint\n}\n\n/**\n * Scan for non-empty liquidity chunks in a tick range.\n *\n * Uses PanopticQuery.scanChunks() to discover chunks with liquidity.\n * Returns only non-empty chunks, making it efficient for large ranges.\n *\n * ## Same-Block Guarantee\n * All data is fetched at a single block.\n *\n * @param params - Parameters\n * @returns Scanned chunks with liquidity data and block metadata\n *\n * @example\n * ```typescript\n * const result = await scanChunks({\n * client,\n * poolAddress: '0x...',\n * queryAddress: '0x...',\n * tickLower: -1000n,\n * tickUpper: 1000n,\n * width: 100n, // 100 tick wide chunks\n * })\n *\n * for (const chunk of result.chunks) {\n * console.log(`Strike ${chunk.strike}: spread0=${chunk.spreadWad0}, spread1=${chunk.spreadWad1}`)\n * }\n * ```\n */\nexport async function scanChunks(params: ScanChunksParams): Promise<ScanChunksResult> {\n const {\n client,\n poolAddress,\n queryAddress,\n tickLower,\n tickUpper,\n width,\n vegoid = 4n,\n blockNumber,\n } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n\n const [result, _meta] = await Promise.all([\n client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'scanChunks',\n args: [poolAddress, Number(tickLower), Number(tickUpper), Number(width)],\n blockNumber: targetBlockNumber,\n }),\n getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const [strikes, netLiquidities, removedLiquidities, settledTokens] = result\n\n const chunks: ScannedChunk[] = strikes.map((strike, i) => {\n const net0 = netLiquidities[i][0]\n const net1 = netLiquidities[i][1]\n const removed0 = removedLiquidities[i][0]\n const removed1 = removedLiquidities[i][1]\n\n return {\n strike: BigInt(strike),\n netLiquidity0: net0,\n netLiquidity1: net1,\n removedLiquidity0: removed0,\n removedLiquidity1: removed1,\n spreadWad0: calculateSpreadWad(net0, removed0, vegoid),\n spreadWad1: calculateSpreadWad(net1, removed1, vegoid),\n settledTokens0: settledTokens[i][0],\n settledTokens1: settledTokens[i][1],\n }\n })\n\n return { chunks, _meta }\n}\n\n/**\n * Chunk data for a single leg of a position.\n */\nexport interface LegChunkData {\n /** Leg index (0-3) */\n legIndex: number\n /** Net liquidity (liquidity in Uniswap) */\n netLiquidity: bigint\n /** Removed liquidity (borrowed by option buyers) */\n removedLiquidity: bigint\n /** Computed spread */\n spreadWad: bigint\n}\n\n/**\n * Chunk data for a position (all legs).\n */\nexport interface PositionChunkData {\n /** TokenId of the position */\n tokenId: bigint\n /** Chunk data for each leg */\n legs: LegChunkData[]\n}\n\n/**\n * Result of getting position chunk data.\n */\nexport interface GetPositionChunkDataResult {\n /** Array of position chunk data */\n positions: PositionChunkData[]\n /** Block metadata */\n _meta: BlockMeta\n}\n\n/**\n * Parameters for getPositionChunkData().\n */\nexport interface GetPositionChunkDataParams {\n /** viem public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** PanopticQuery contract address */\n queryAddress: Address\n /** Array of tokenIds to query */\n tokenIds: bigint[]\n /** VEGOID constant for spread calculation (default: 4n) */\n vegoid?: bigint\n /** Optional block number for historical queries */\n blockNumber?: bigint\n}\n\n/**\n * Get chunk data (liquidity) for specific positions.\n *\n * Uses PanopticQuery.getChunkData() to fetch net and removed liquidity\n * for each leg of the given positions.\n *\n * ## Same-Block Guarantee\n * All data is fetched at a single block.\n *\n * @param params - Parameters\n * @returns Position chunk data with liquidity for each leg\n *\n * @example\n * ```typescript\n * const result = await getPositionChunkData({\n * client,\n * poolAddress: '0x...',\n * queryAddress: '0x...',\n * tokenIds: [tokenId1, tokenId2],\n * })\n *\n * for (const pos of result.positions) {\n * console.log(`Position ${pos.tokenId}:`)\n * for (const leg of pos.legs) {\n * console.log(` Leg ${leg.legIndex}: net=${leg.netLiquidity}, removed=${leg.removedLiquidity}`)\n * }\n * }\n * ```\n */\nexport async function getPositionChunkData(\n params: GetPositionChunkDataParams,\n): Promise<GetPositionChunkDataResult> {\n const {\n client,\n poolAddress,\n queryAddress,\n tokenIds,\n vegoid = DEFAULT_VEGOID,\n blockNumber,\n } = params\n\n if (tokenIds.length === 0) {\n const _meta = await getBlockMeta({ client, blockNumber })\n return { positions: [], _meta }\n }\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n\n const [chunkData, _meta] = await Promise.all([\n client.readContract({\n address: queryAddress,\n abi: panopticQueryAbi,\n functionName: 'getChunkData',\n args: [poolAddress, tokenIds],\n blockNumber: targetBlockNumber,\n }),\n getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // chunkData is uint256[2][4][] - [positionIndex][legIndex][0=net, 1=removed]\n const positions: PositionChunkData[] = tokenIds.map((tokenId, posIndex) => {\n const positionData = chunkData[posIndex]\n const legs: LegChunkData[] = []\n\n // Each position has up to 4 legs\n for (let legIndex = 0; legIndex < 4; legIndex++) {\n const legData = positionData[legIndex]\n const netLiquidity = legData[0]\n const removedLiquidity = legData[1]\n\n // Only include legs with data (non-zero liquidity indicates active leg)\n if (netLiquidity > 0n || removedLiquidity > 0n) {\n legs.push({\n legIndex,\n netLiquidity,\n removedLiquidity,\n spreadWad: calculateSpreadWad(netLiquidity, removedLiquidity, vegoid),\n })\n }\n }\n\n return { tokenId, legs }\n })\n\n return { positions, _meta }\n}\n","/**\n * Pending position tracking for optimistic updates.\n * @module v2/sync/pendingPositions\n */\n\nimport type { Address, Hash } from 'viem'\n\nimport type { StorageAdapter } from '../storage'\nimport { getPendingPositionsKey, jsonSerializer } from '../storage'\nimport type { TokenIdLeg } from '../types'\n\n/**\n * A pending position that has been submitted but not yet confirmed.\n */\nexport interface PendingPosition {\n /** The TokenId */\n tokenId: bigint\n /** Owner address */\n owner: Address\n /** Pool address */\n poolAddress: Address\n /** Position size (from simulation) */\n positionSize: bigint\n /** Decoded legs */\n legs: TokenIdLeg[]\n /** Transaction hash */\n txHash: Hash\n /** Block number when submitted */\n submittedAtBlock: bigint\n /** Timestamp when submitted */\n submittedAt: bigint\n /** Status */\n status: 'pending' | 'confirmed' | 'failed'\n}\n\n/**\n * Parameters for adding a pending position.\n */\nexport interface AddPendingPositionParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account (owner) */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Pending position data */\n position: PendingPosition\n}\n\n/**\n * Add a pending position for optimistic updates.\n *\n * Called when openPosition() submits a transaction.\n *\n * @param params - Parameters\n */\nexport async function addPendingPosition(params: AddPendingPositionParams): Promise<void> {\n const { chainId, poolAddress, account, storage, position } = params\n\n const key = getPendingPositionsKey(chainId, poolAddress, account)\n const existingData = await storage.get(key)\n\n let pending: PendingPosition[]\n if (existingData) {\n try {\n pending = jsonSerializer.parse(existingData) as PendingPosition[]\n } catch {\n pending = []\n }\n } else {\n pending = []\n }\n\n // Add new pending position\n pending.push(position)\n\n await storage.set(key, jsonSerializer.stringify(pending))\n}\n\n/**\n * Parameters for getting pending positions.\n */\nexport interface GetPendingPositionsParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account (owner) */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n}\n\n/**\n * Get all pending positions for an account.\n *\n * @param params - Parameters\n * @returns Array of pending positions\n */\nexport async function getPendingPositions(\n params: GetPendingPositionsParams,\n): Promise<PendingPosition[]> {\n const { chainId, poolAddress, account, storage } = params\n\n const key = getPendingPositionsKey(chainId, poolAddress, account)\n const data = await storage.get(key)\n\n if (!data) {\n return []\n }\n\n try {\n const pending = jsonSerializer.parse(data) as PendingPosition[]\n // Only return pending status\n return pending.filter((p) => p.status === 'pending')\n } catch {\n return []\n }\n}\n\n/**\n * Parameters for confirming a pending position.\n */\nexport interface ConfirmPendingPositionParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account (owner) */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Token ID to confirm */\n tokenId: bigint\n}\n\n/**\n * Mark a pending position as confirmed.\n *\n * Called when syncPositions() finds the OptionMinted event.\n *\n * @param params - Parameters\n */\nexport async function confirmPendingPosition(params: ConfirmPendingPositionParams): Promise<void> {\n const { chainId, poolAddress, account, storage, tokenId } = params\n\n const key = getPendingPositionsKey(chainId, poolAddress, account)\n const existingData = await storage.get(key)\n\n if (!existingData) {\n return\n }\n\n let pending: PendingPosition[]\n try {\n pending = jsonSerializer.parse(existingData) as PendingPosition[]\n } catch {\n return\n }\n\n // Find and update the position\n const updated = pending.map((p) =>\n p.tokenId === tokenId ? { ...p, status: 'confirmed' as const } : p,\n )\n\n // Remove confirmed positions (they're now in the main position list)\n const remaining = updated.filter((p) => p.status === 'pending')\n\n if (remaining.length === 0) {\n await storage.delete(key)\n } else {\n await storage.set(key, jsonSerializer.stringify(remaining))\n }\n}\n\n/**\n * Parameters for failing a pending position.\n */\nexport interface FailPendingPositionParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account (owner) */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n /** Transaction hash that failed */\n txHash: Hash\n}\n\n/**\n * Mark a pending position as failed (transaction reverted).\n *\n * @param params - Parameters\n */\nexport async function failPendingPosition(params: FailPendingPositionParams): Promise<void> {\n const { chainId, poolAddress, account, storage, txHash } = params\n\n const key = getPendingPositionsKey(chainId, poolAddress, account)\n const existingData = await storage.get(key)\n\n if (!existingData) {\n return\n }\n\n let pending: PendingPosition[]\n try {\n pending = jsonSerializer.parse(existingData) as PendingPosition[]\n } catch {\n return\n }\n\n // Remove the failed position\n const remaining = pending.filter((p) => p.txHash !== txHash)\n\n if (remaining.length === 0) {\n await storage.delete(key)\n } else {\n await storage.set(key, jsonSerializer.stringify(remaining))\n }\n}\n\n/**\n * Clear all pending positions for an account.\n *\n * @param params - Parameters\n */\nexport async function clearPendingPositions(params: GetPendingPositionsParams): Promise<void> {\n const { chainId, poolAddress, account, storage } = params\n\n const key = getPendingPositionsKey(chainId, poolAddress, account)\n await storage.delete(key)\n}\n\n/**\n * Clean up stale pending positions.\n *\n * Removes pending positions older than the specified block threshold.\n * This handles cases where transactions were dropped from the mempool.\n *\n * @param params - Parameters\n * @param maxAgeBlocks - Maximum age in blocks (default: 100)\n * @param currentBlock - Current block number\n */\nexport async function cleanupStalePendingPositions(\n params: GetPendingPositionsParams,\n currentBlock: bigint,\n maxAgeBlocks: bigint = 100n,\n): Promise<void> {\n const { chainId, poolAddress, account, storage } = params\n\n const key = getPendingPositionsKey(chainId, poolAddress, account)\n const existingData = await storage.get(key)\n\n if (!existingData) {\n return\n }\n\n let pending: PendingPosition[]\n try {\n pending = jsonSerializer.parse(existingData) as PendingPosition[]\n } catch {\n return\n }\n\n // Filter out stale positions\n const threshold = currentBlock - maxAgeBlocks\n const remaining = pending.filter((p) => p.status === 'pending' && p.submittedAtBlock > threshold)\n\n if (remaining.length === 0) {\n await storage.delete(key)\n } else if (remaining.length !== pending.length) {\n await storage.set(key, jsonSerializer.stringify(remaining))\n }\n}\n","/**\n * Event reconstruction for full position history scan.\n * @module v2/sync/eventReconstruction\n */\n\nimport type { Address, Hash, PublicClient } from 'viem'\n\nimport type { SyncEvent } from '../types'\n\n/**\n * Parameters for event reconstruction.\n */\nexport interface EventReconstructionParams {\n /** viem public client */\n client: PublicClient\n /** Pool address */\n poolAddress: Address\n /** Account to reconstruct positions for */\n account: Address\n /** Starting block for event scan */\n fromBlock: bigint\n /** Ending block for event scan */\n toBlock: bigint\n /** Batch size for log queries (default: 10000) */\n batchSize?: bigint\n /** Progress callback */\n onProgress?: (event: SyncEvent) => void\n}\n\n/**\n * Event reconstruction result.\n */\nexport interface EventReconstructionResult {\n /** Position IDs that are currently open */\n openPositions: bigint[]\n /** Position IDs that have been closed */\n closedPositions: bigint[]\n /** Number of blocks scanned */\n blocksScanned: bigint\n /** Last scanned block number */\n lastBlock: bigint\n /** Last scanned block hash */\n lastBlockHash: Hash\n}\n\n/**\n * Mint event from reconstruction.\n */\ninterface MintEvent {\n tokenId: bigint\n positionSize: bigint\n blockNumber: bigint\n blockHash: Hash\n transactionHash: Hash\n logIndex: number\n}\n\n/**\n * Burn event from reconstruction.\n */\ninterface BurnEvent {\n tokenId: bigint\n positionSize: bigint\n blockNumber: bigint\n blockHash: Hash\n transactionHash: Hash\n logIndex: number\n}\n\n/**\n * Reconstruct position history from events.\n * This is the fallback method when snapshot recovery fails.\n * It scans all OptionMinted and OptionBurnt events to build the position set.\n *\n * @param params - Reconstruction parameters\n * @returns Reconstruction result with open and closed positions\n */\nexport async function reconstructFromEvents(\n params: EventReconstructionParams,\n): Promise<EventReconstructionResult> {\n const {\n client,\n poolAddress,\n account,\n fromBlock,\n toBlock,\n batchSize = 10000n,\n onProgress,\n } = params\n\n const mintEvents: MintEvent[] = []\n const burnEvents: BurnEvent[] = []\n\n let currentBlock = fromBlock\n const totalBlocks = toBlock - fromBlock\n\n // Scan in batches\n while (currentBlock <= toBlock) {\n const endBlock =\n currentBlock + batchSize - 1n > toBlock ? toBlock : currentBlock + batchSize - 1n\n\n // Fetch mint events for this batch\n const [mints, burns] = await Promise.all([\n client.getLogs({\n address: poolAddress,\n event: {\n type: 'event',\n name: 'OptionMinted',\n inputs: [\n { type: 'address', name: 'recipient', indexed: true },\n { type: 'uint256', name: 'tokenId', indexed: true },\n { type: 'uint256', name: 'balanceData', indexed: false },\n ],\n },\n args: {\n recipient: account,\n },\n fromBlock: currentBlock,\n toBlock: endBlock,\n }),\n client.getLogs({\n address: poolAddress,\n event: {\n type: 'event',\n name: 'OptionBurnt',\n inputs: [\n { type: 'address', name: 'recipient', indexed: true },\n { type: 'uint256', name: 'tokenId', indexed: true },\n { type: 'uint256', name: 'positionSize', indexed: false },\n { type: 'int256[4]', name: 'premiaByLeg', indexed: false },\n ],\n },\n args: {\n recipient: account,\n },\n fromBlock: currentBlock,\n toBlock: endBlock,\n }),\n ])\n\n // Process mint events\n for (const mint of mints) {\n // Decode position size from balanceData (first 128 bits)\n const balanceData = mint.args.balanceData as bigint\n const positionSize = balanceData & ((1n << 128n) - 1n)\n\n mintEvents.push({\n tokenId: mint.args.tokenId as bigint,\n positionSize,\n blockNumber: mint.blockNumber,\n blockHash: mint.blockHash,\n transactionHash: mint.transactionHash,\n logIndex: mint.logIndex,\n })\n }\n\n // Process burn events\n for (const burn of burns) {\n burnEvents.push({\n tokenId: burn.args.tokenId as bigint,\n positionSize: burn.args.positionSize as bigint,\n blockNumber: burn.blockNumber,\n blockHash: burn.blockHash,\n transactionHash: burn.transactionHash,\n logIndex: burn.logIndex,\n })\n }\n\n // Report progress\n if (onProgress) {\n const blocksProcessed = endBlock - fromBlock + 1n\n const progress = totalBlocks > 0n ? (blocksProcessed * 100n) / totalBlocks : 100n\n\n onProgress({\n currentBlock: endBlock,\n targetBlock: toBlock,\n positionsFound: BigInt(mintEvents.length),\n progress,\n })\n }\n\n currentBlock = endBlock + 1n\n }\n\n // Build position map: tokenId -> net position size\n const positionMap = new Map<bigint, bigint>()\n\n // Sort all events by block and log index\n const allEvents = [\n ...mintEvents.map((e) => ({ ...e, type: 'mint' as const })),\n ...burnEvents.map((e) => ({ ...e, type: 'burn' as const })),\n ].sort((a, b) => {\n const blockDiff = Number(a.blockNumber - b.blockNumber)\n if (blockDiff !== 0) return blockDiff\n return a.logIndex - b.logIndex\n })\n\n // Process events in order\n for (const event of allEvents) {\n const current = positionMap.get(event.tokenId) ?? 0n\n\n if (event.type === 'mint') {\n positionMap.set(event.tokenId, current + event.positionSize)\n } else {\n positionMap.set(event.tokenId, current - event.positionSize)\n }\n }\n\n // Separate open and closed positions\n const openPositions: bigint[] = []\n const closedPositions: bigint[] = []\n\n for (const [tokenId, size] of positionMap) {\n if (size > 0n) {\n openPositions.push(tokenId)\n } else {\n closedPositions.push(tokenId)\n }\n }\n\n // Get the last block hash\n const lastBlock = await client.getBlock({ blockNumber: toBlock })\n\n return {\n openPositions,\n closedPositions,\n blocksScanned: toBlock - fromBlock + 1n,\n lastBlock: toBlock,\n lastBlockHash: lastBlock.hash,\n }\n}\n\n/**\n * Get the deployment block for a pool.\n * This searches for the first PoolInitialized event.\n *\n * @param client - viem public client\n * @param poolAddress - Pool address\n * @returns Deployment block number or null if not found\n */\nexport async function getPoolDeploymentBlock(\n client: PublicClient,\n poolAddress: Address,\n): Promise<bigint | null> {\n // Search for the first event from this pool\n // We use a binary search approach to find the deployment block\n\n const currentBlock = await client.getBlockNumber()\n let low = 0n\n let high = currentBlock\n let foundBlock: bigint | null = null\n\n // Binary search with scan windows to find the deployment block.\n // Each iteration checks [mid, mid + scanRange] for logs.\n const scanRange = 10000n\n\n while (low <= high) {\n const mid = (low + high) / 2n\n const rangeEnd = mid + scanRange > high ? high : mid + scanRange\n\n try {\n const logs = await client.getLogs({\n address: poolAddress,\n fromBlock: mid,\n toBlock: rangeEnd,\n })\n\n if (logs.length > 0) {\n // Found logs — record earliest and search before it\n const earliest = logs[0].blockNumber\n if (foundBlock === null || earliest < foundBlock) {\n foundBlock = earliest\n }\n high = earliest - 1n\n } else {\n // No logs in [mid, rangeEnd] — skip the entire checked range\n low = rangeEnd + 1n\n }\n } catch {\n // Range too large for RPC — halve the search space\n high = mid + (rangeEnd - mid) / 2n\n }\n }\n\n return foundBlock\n}\n","/**\n * Stable cache-scope helpers for React query keys.\n * @module v2/react/cacheScopes\n */\n\nconst DEFAULT_CLIENT_CACHE_SCOPE = 'default-client'\nconst DEFAULT_STORAGE_CACHE_SCOPE = 'default-storage'\n\nexport function getClientCacheScope(scope?: string): string {\n return scope ?? DEFAULT_CLIENT_CACHE_SCOPE\n}\n\nexport function getStorageCacheScope(scope?: string): string {\n return scope ?? DEFAULT_STORAGE_CACHE_SCOPE\n}\n\nexport function getClientCacheScopeKey(client: unknown, scope?: string): string {\n // Keep client in the queryKey expression for exhaustive-deps while keying by stable scope.\n void client\n return getClientCacheScope(scope)\n}\n\nexport function getStorageCacheScopeKey(storage: unknown, scope?: string): string {\n // Keep storage in the queryKey expression for exhaustive-deps while keying by stable scope.\n void storage\n return getStorageCacheScope(scope)\n}\n\nexport function getAtTickCacheKey(atTick?: bigint): string {\n return atTick === undefined ? 'latest' : atTick.toString()\n}\n","/**\n * React context provider for the Panoptic v2 SDK.\n * @module v2/react/provider\n */\n\nimport { type ReactNode, createContext, useContext } from 'react'\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport type { StorageAdapter } from '../storage'\n\n/**\n * Panoptic SDK context value.\n */\nexport interface PanopticContextValue {\n /** viem PublicClient for reading chain state */\n publicClient: PublicClient\n /**\n * Optional cache scope for read/simulation query keys.\n * Use this when multiple environments share the same QueryClient.\n */\n clientScope?: string\n /** Optional viem WalletClient for write operations */\n walletClient?: WalletClient\n /** Optional account address for write operations */\n account?: Address\n /** Chain ID */\n chainId: bigint\n /** Optional StateView address for V4 Uniswap pool reads (per-chain singleton) */\n stateViewAddress?: Address\n /** Optional storage adapter for position tracking */\n storage?: StorageAdapter\n /**\n * Optional cache scope for storage-backed query keys.\n * Set this when swapping storage adapters at runtime.\n */\n storageScope?: string\n}\n\nconst PanopticContext = createContext<PanopticContextValue | null>(null)\n\n/**\n * Props for PanopticProvider.\n */\nexport interface PanopticProviderProps extends PanopticContextValue {\n children: ReactNode\n}\n\n/**\n * Context provider for Panoptic v2 SDK hooks.\n *\n * Wraps children with shared publicClient, walletClient, account, chainId, and storage.\n * Does NOT include QueryClientProvider — you must provide your own.\n *\n * @example\n * ```tsx\n * <QueryClientProvider client={queryClient}>\n * <PanopticProvider\n * publicClient={publicClient}\n * walletClient={walletClient}\n * account={address}\n * chainId={1n}\n * >\n * <App />\n * </PanopticProvider>\n * </QueryClientProvider>\n * ```\n */\nexport function PanopticProvider({ children, ...value }: PanopticProviderProps) {\n return <PanopticContext.Provider value={value}>{children}</PanopticContext.Provider>\n}\n\n/**\n * Access the Panoptic SDK context.\n *\n * @throws Error if used outside PanopticProvider\n * @returns PanopticContextValue\n */\nexport function usePanopticContext(): PanopticContextValue {\n const ctx = useContext(PanopticContext)\n if (!ctx) {\n throw new Error('usePanopticContext must be used within a PanopticProvider')\n }\n return ctx\n}\n\n/**\n * Internal hook that requires walletClient and account.\n *\n * @throws Error if walletClient or account not provided in context\n * @returns { walletClient, account } guaranteed non-undefined\n */\nexport function useRequireWallet(): { walletClient: WalletClient; account: Address } {\n const { walletClient, account } = usePanopticContext()\n if (!walletClient || !account) {\n throw new Error('walletClient and account are required. Provide them via PanopticProvider.')\n }\n return { walletClient, account }\n}\n\n/**\n * Internal hook that requires storage adapter.\n *\n * @throws Error if storage not provided in context\n * @returns StorageAdapter guaranteed non-undefined\n */\nexport function useRequireStorage(): StorageAdapter {\n const { storage } = usePanopticContext()\n if (!storage) {\n throw new Error('storage is required. Provide a StorageAdapter via PanopticProvider.')\n }\n return storage\n}\n","/**\n * Query key factory for TanStack Query / SWR integration.\n * @module v2/react/queryKeys\n */\n\nimport type { Address } from 'viem'\n\n/**\n * Query key factory for Panoptic v2 SDK data.\n *\n * Use with TanStack Query or SWR for cache key consistency.\n * All keys are arrays for proper cache matching and invalidation.\n *\n * @example\n * ```typescript\n * import { useQuery } from '@tanstack/react-query'\n * import { queryKeys, getPool } from 'panoptic-v2-sdk'\n *\n * function usePool(config: PanopticConfig) {\n * return useQuery({\n * queryKey: queryKeys.pool(config.chainId, config.poolAddress),\n * queryFn: () => getPool(config),\n * })\n * }\n * ```\n */\nexport const queryKeys = {\n /**\n * Base key for all Panoptic v2 queries.\n */\n all: ['panoptic-v2'] as const,\n\n /**\n * Key for pool data.\n */\n pool: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'pool', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for pool utilization.\n */\n utilization: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'utilization', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for oracle state.\n */\n oracle: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'oracle', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for safe mode state.\n */\n safeMode: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'safeMode', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for Guardian pool-unlock state.\n */\n guardianUnlock: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'guardianUnlock', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for risk parameters.\n */\n riskParameters: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'riskParameters', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for current rates.\n */\n rates: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'rates', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for a single position.\n */\n position: (chainId: bigint, poolAddress: Address, tokenId: bigint) =>\n [...queryKeys.all, 'position', chainId.toString(), poolAddress, tokenId.toString()] as const,\n\n /**\n * Key for all positions of an account.\n */\n positions: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'positions', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for tracked position IDs.\n */\n trackedPositionIds: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'trackedPositionIds', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for sync status.\n */\n syncStatus: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'syncStatus', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for account collateral.\n */\n accountCollateral: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'accountCollateral', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for base account summary (aggregate dashboard data).\n */\n accountSummaryBasic: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'accountSummaryBasic', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for risk-focused account summary.\n */\n accountSummaryRisk: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'accountSummaryRisk', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for liquidation check.\n */\n isLiquidatable: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'isLiquidatable', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for liquidation prices.\n */\n liquidationPrices: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'liquidationPrices', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for net liquidation value.\n */\n netLiquidationValue: (chainId: bigint, poolAddress: Address, account: Address, atTick: bigint) =>\n [\n ...queryKeys.all,\n 'netLiquidationValue',\n chainId.toString(),\n poolAddress,\n account,\n atTick.toString(),\n ] as const,\n\n /**\n * Key for chunk spreads.\n */\n chunkSpreads: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'chunkSpreads', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for closed positions.\n */\n closedPositions: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'closedPositions', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for trade history.\n */\n tradeHistory: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'tradeHistory', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for realized PnL.\n */\n realizedPnL: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'realizedPnL', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for position greeks.\n */\n positionGreeks: (chainId: bigint, poolAddress: Address, tokenId: bigint) =>\n [\n ...queryKeys.all,\n 'positionGreeks',\n chainId.toString(),\n poolAddress,\n tokenId.toString(),\n ] as const,\n\n /**\n * Key for account greeks.\n */\n accountGreeks: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'accountGreeks', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for collateral estimate.\n */\n collateralEstimate: (chainId: bigint, poolAddress: Address, account: Address, tokenId: bigint) =>\n [\n ...queryKeys.all,\n 'collateralEstimate',\n chainId.toString(),\n poolAddress,\n account,\n tokenId.toString(),\n ] as const,\n\n /**\n * Key for max position size.\n */\n maxPositionSize: (chainId: bigint, poolAddress: Address, account: Address, tokenId: bigint) =>\n [\n ...queryKeys.all,\n 'maxPositionSize',\n chainId.toString(),\n poolAddress,\n account,\n tokenId.toString(),\n ] as const,\n\n /**\n * Key for max withdrawable assets from a collateral tracker.\n */\n maxWithdrawable: (\n chainId: bigint,\n collateralTrackerAddress: Address,\n positionIdList: bigint[],\n totalAssets: bigint,\n account: Address,\n ) =>\n [\n ...queryKeys.all,\n chainId.toString(),\n 'maxWithdrawable',\n collateralTrackerAddress,\n positionIdList.map(String).join(','),\n totalAssets.toString(),\n account,\n ] as const,\n\n /**\n * Key for approval check.\n */\n approval: (chainId: bigint, token: Address, owner: Address, spender: Address) =>\n [...queryKeys.all, 'approval', chainId.toString(), token, owner, spender] as const,\n\n /**\n * Key for ERC4626 preview operations.\n */\n erc4626Preview: (chainId: bigint, tracker: Address, operation: string, amount: bigint) =>\n [\n ...queryKeys.all,\n 'erc4626Preview',\n chainId.toString(),\n tracker,\n operation,\n amount.toString(),\n ] as const,\n\n /**\n * Key for margin buffer.\n */\n marginBuffer: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'marginBuffer', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for account premia.\n */\n accountPremia: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'accountPremia', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for positions with premia.\n */\n positionsWithPremia: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'positionsWithPremia', chainId.toString(), poolAddress, account] as const,\n\n /**\n * Key for collateral data.\n */\n collateralData: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'collateralData', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for pool liquidities.\n */\n poolLiquidities: (chainId: bigint, poolAddress: Address) =>\n [...queryKeys.all, 'poolLiquidities', chainId.toString(), poolAddress] as const,\n\n /**\n * Key for optimized risk partners.\n */\n optimizeRiskPartners: (chainId: bigint, poolAddress: Address, tokenId: bigint) =>\n [\n ...queryKeys.all,\n 'optimizeRiskPartners',\n chainId.toString(),\n poolAddress,\n tokenId.toString(),\n ] as const,\n /**\n * Key for price history.\n * Uses a hash of timestamps for cache busting when the time range changes.\n */\n priceHistory: (chainId: bigint, poolAddress: string, timestampsHash: string) =>\n [...queryKeys.all, 'priceHistory', chainId.toString(), poolAddress, timestampsHash] as const,\n\n /**\n * Key for streamia history.\n */\n streamiaHistory: (chainId: bigint, poolAddress: string, rangeHash: string) =>\n [...queryKeys.all, 'streamiaHistory', chainId.toString(), poolAddress, rangeHash] as const,\n\n /**\n * Key for Uniswap fee history.\n */\n uniswapFeeHistory: (chainId: bigint, poolAddress: string, rangeHash: string) =>\n [...queryKeys.all, 'uniswapFeeHistory', chainId.toString(), poolAddress, rangeHash] as const,\n\n /**\n * Key for required credit for ITM position.\n */\n requiredCreditForITM: (\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n tokenId: bigint,\n ) =>\n [\n ...queryKeys.all,\n 'requiredCreditForITM',\n chainId.toString(),\n poolAddress,\n account,\n tokenId.toString(),\n ] as const,\n /**\n * Key for interest state (per-user borrows).\n */\n interestState: (chainId: bigint, poolAddress: Address, account: Address) =>\n [...queryKeys.all, 'interestState', chainId.toString(), poolAddress, account] as const,\n} as const\n","/**\n * TanStack Query v5 read hooks for the Panoptic v2 SDK.\n * @module v2/react/hooks/reads\n */\n\nimport { keepPreviousData, useMutation, useQuery } from '@tanstack/react-query'\nimport type { Address, PublicClient } from 'viem'\n\nimport { estimateBlockNumbers, resolveBlockNumbers } from '../../clients/blocksByTimestamp'\nimport { PanopticValidationError } from '../../errors'\nimport {\n type GetEnforcedTickLimitsParams,\n type GetFactoryConstructMetadataParams,\n type GetFactoryOwnerOfParams,\n type GetFactoryTokenURIParams,\n type GetPanopticPoolAddressParams,\n type GetPanopticPoolFromPoolIdParams,\n type GetUniswapV3PoolFromIdParams,\n type GetUniswapV4PoolKeyFromIdParams,\n type MinePoolAddressLocalParams,\n type ResolvePanopticPoolFromPoolIdParams,\n type SimulateDeployNewPoolParams,\n type UniswapV4PoolKey,\n estimateCollateralRequired,\n getAccountCollateral,\n getAccountGreeks,\n getAccountPremia,\n getAccountSummaryBasic,\n getAccountSummaryRisk,\n getCollateralData,\n getCurrentRates,\n getEnforcedTickLimits,\n getFactoryConstructMetadata,\n getFactoryOwnerOf,\n getFactoryTokenURI,\n getGuardianUnlockState,\n getInterestState,\n getLiquidationPrices,\n getMarginBuffer,\n getMaxPositionSize,\n getMaxWithdrawable,\n getNativeTokenPrice,\n getNetLiquidationValue,\n getNetLiquidationValues,\n getOpenPositionPreview,\n getOracleState,\n getPanopticPoolAddress,\n getPanopticPoolFromPoolId,\n getPool,\n getPoolLiquidities,\n getPosition,\n getPositionGreeks,\n getPositions,\n getPositionsWithPremia,\n getRequiredCreditForITM,\n getRiskParameters,\n getSafeMode,\n getUniswapV3PoolFromId,\n getUniswapV3PoolInfo,\n getUniswapV3PoolLiquidities,\n getUniswapV4PoolBasicState,\n getUniswapV4PoolInfo,\n getUniswapV4PoolKeyFromId,\n getUniswapV4PoolLiquidities,\n getUtilization,\n isLiquidatable,\n minePoolAddressLocalAsync,\n previewDeposit,\n previewMint,\n previewRedeem,\n previewWithdraw,\n resolvePanopticPoolFromPoolId,\n resolveUniswapV4PoolKey,\n simulateDeployNewPool,\n validateBuilderCode,\n} from '../../reads'\nimport { getPriceHistory } from '../../reads/priceHistory'\nimport { optimizeTokenIdRiskPartners } from '../../reads/queryUtils'\nimport type { StreamiaLeg } from '../../reads/streamiaHistory'\nimport { getStreamiaHistory } from '../../reads/streamiaHistory'\nimport { getUniswapFeeHistory } from '../../reads/uniswapFeeHistory'\nimport {\n getChunkSpreads,\n getClosedPositions,\n getRealizedPnL,\n getSyncStatus,\n getTrackedPositionIds,\n getTradeHistory,\n scanChunks,\n} from '../../sync'\nimport type { PoolVersionConfig } from '../../types/poolConfig'\nimport { interpolateBlocks } from '../../utils/interpolateBlocks'\nimport { previewBorrow } from '../../writes/lending'\nimport { getAtTickCacheKey, getClientCacheScopeKey, getStorageCacheScopeKey } from '../cacheScopes'\nimport { usePanopticContext, useRequireStorage } from '../provider'\nimport { queryKeys } from '../queryKeys'\n\n/**\n * Common query options exposed to consumers.\n */\nexport interface QueryOptions {\n /** Whether the query is enabled */\n enabled?: boolean\n /** Refetch interval in milliseconds */\n refetchInterval?: number | false\n /** Time in milliseconds that data is considered fresh */\n staleTime?: number\n /** Time in milliseconds that unused data is kept in cache */\n gcTime?: number\n}\n\n// --- Pool reads ---\n\nexport function usePool(poolAddress: Address, options?: QueryOptions) {\n const { publicClient, chainId, clientScope, stateViewAddress } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.pool(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n stateViewAddress,\n ],\n queryFn: () => getPool({ client: publicClient, poolAddress, chainId, stateViewAddress }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n // Caching is opt-in per consumer: per the SDK's \"no memoization of dynamic RPC\n // data\" constraint, we never default a staleTime here. App code can set one\n // explicitly when it knows the consumer can tolerate cached pool state.\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useUtilization(poolAddress: Address, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.utilization(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => getUtilization({ client: publicClient, poolAddress }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useOracleState(poolAddress: Address, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.oracle(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => getOracleState({ client: publicClient, poolAddress }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useRiskParameters(poolAddress: Address, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.riskParameters(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => getRiskParameters({ client: publicClient, poolAddress }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useCurrentRates(poolAddress: Address, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.rates(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => getCurrentRates({ client: publicClient, poolAddress }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useSafeMode(poolAddress: Address, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.safeMode(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => getSafeMode({ client: publicClient, poolAddress }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n/**\n * React hook for the Guardian pending-unlock state of a pool.\n *\n * Reads `unlockEta` + `isPoolUnlockReady` from the PanopticGuardian so the UI\n * can surface the unlock timelock while a pool is locked (close-only). Gate it\n * via `options.enabled` so it only runs when the pool is actually locked.\n *\n * @param poolAddress - The PanopticPool address\n * @param options - Optional react-query settings (enabled, refetchInterval, staleTime, gcTime)\n * @returns A react-query result whose `data` is a `GuardianUnlockState`\n */\nexport function useGuardianUnlockState(poolAddress: Address, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.guardianUnlock(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => getGuardianUnlockState({ client: publicClient, poolAddress }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useCollateralData(poolAddress: Address, tokenIndex: 0 | 1, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.collateralData(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n tokenIndex,\n ],\n queryFn: () => getCollateralData({ client: publicClient, poolAddress, tokenIndex }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function usePoolLiquidities(\n poolAddress: Address,\n params: { queryAddress: Address; startTick: bigint; nTicks: bigint },\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.poolLiquidities(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n params.queryAddress,\n params.startTick,\n params.nTicks,\n ],\n queryFn: () =>\n getPoolLiquidities({\n client: publicClient,\n poolAddress,\n queryAddress: params.queryAddress,\n startTick: params.startTick,\n nTicks: params.nTicks,\n }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useScanChunks(\n poolAddress: Address,\n params: { queryAddress: Address; tickLower: bigint; tickUpper: bigint; width: bigint },\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.chunkSpreads(chainId, poolAddress),\n 'scanChunks',\n getClientCacheScopeKey(publicClient, clientScope),\n params.queryAddress,\n params.tickLower,\n params.tickUpper,\n params.width,\n ],\n queryFn: () =>\n scanChunks({\n client: publicClient,\n poolAddress,\n queryAddress: params.queryAddress,\n tickLower: params.tickLower,\n tickUpper: params.tickUpper,\n width: params.width,\n }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useChunkSpreads(\n poolAddress: Address,\n params: { sfpmAddress: Address },\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope, storageScope } = usePanopticContext()\n const storage = useRequireStorage()\n return useQuery({\n queryKey: [\n ...queryKeys.chunkSpreads(chainId, poolAddress),\n getClientCacheScopeKey(publicClient, clientScope),\n params.sfpmAddress,\n getStorageCacheScopeKey(storage, storageScope),\n ],\n queryFn: () =>\n getChunkSpreads({\n client: publicClient,\n chainId,\n poolAddress,\n sfpmAddress: params.sfpmAddress,\n storage,\n }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Position reads ---\n\nexport function usePosition(\n poolAddress: Address,\n owner: Address,\n tokenId: bigint,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.position(chainId, poolAddress, tokenId),\n getClientCacheScopeKey(publicClient, clientScope),\n owner,\n ],\n queryFn: () => getPosition({ client: publicClient, poolAddress, owner, tokenId }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function usePositions(\n poolAddress: Address,\n tokenIds: bigint[],\n owner?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedOwner = owner ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.positions(ctx.chainId, poolAddress, resolvedOwner ?? ('' as Address)),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n ],\n queryFn: () => {\n if (!resolvedOwner) throw new Error('owner required for getPositions')\n return getPositions({ client: ctx.publicClient, poolAddress, owner: resolvedOwner, tokenIds })\n },\n enabled: (options?.enabled ?? true) && !!resolvedOwner,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function usePositionGreeks(\n poolAddress: Address,\n tokenId: bigint,\n owner: Address,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.positionGreeks(chainId, poolAddress, tokenId),\n getClientCacheScopeKey(publicClient, clientScope),\n owner,\n ],\n queryFn: () => getPositionGreeks({ client: publicClient, poolAddress, tokenId, owner }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Account reads ---\n\nexport function useAccountCollateral(\n poolAddress: Address,\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.accountCollateral(ctx.chainId, poolAddress, resolvedAccount ?? ('' as Address)),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n ],\n queryFn: () => {\n if (!resolvedAccount) throw new Error('account required for getAccountCollateral')\n return getAccountCollateral({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount,\n })\n },\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useInterestState(poolAddress: Address, account?: Address, options?: QueryOptions) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.interestState(ctx.chainId, poolAddress, resolvedAccount ?? ('' as Address)),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n ],\n queryFn: () => {\n if (!resolvedAccount) throw new Error('account required for getInterestState')\n return getInterestState({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount,\n })\n },\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useAccountSummaryBasic(\n poolAddress: Address,\n tokenIds: bigint[],\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.accountSummaryBasic(\n ctx.chainId,\n poolAddress,\n resolvedAccount ?? ('' as Address),\n ),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n ],\n queryFn: () => {\n if (!resolvedAccount) throw new Error('account required for getAccountSummaryBasic')\n return getAccountSummaryBasic({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount,\n chainId: ctx.chainId,\n tokenIds,\n })\n },\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useAccountSummaryRisk(\n poolAddress: Address,\n tokenIds: bigint[],\n queryAddress: Address,\n account?: Address,\n options?: QueryOptions & { atTick?: bigint; includePendingPremium?: boolean },\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.accountSummaryRisk(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n queryAddress,\n options?.atTick,\n options?.includePendingPremium,\n ],\n queryFn: () =>\n getAccountSummaryRisk({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n chainId: ctx.chainId,\n tokenIds,\n queryAddress,\n atTick: options?.atTick,\n includePendingPremium: options?.includePendingPremium,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useNetLiquidationValue(\n poolAddress: Address,\n tokenIds: bigint[],\n queryAddress: Address,\n account?: Address,\n options?: QueryOptions & { atTick?: bigint },\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'netLiquidationValue',\n ctx.chainId.toString(),\n poolAddress,\n resolvedAccount!,\n getAtTickCacheKey(options?.atTick),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n queryAddress,\n ],\n queryFn: () =>\n getNetLiquidationValue({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenIds,\n atTick: options?.atTick,\n queryAddress,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useNetLiquidationValues(\n poolAddress: Address,\n tokenIds: bigint[],\n queryAddress: Address,\n atTicks: bigint[],\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'netLiquidationValues',\n ctx.chainId.toString(),\n poolAddress,\n resolvedAccount!,\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n queryAddress,\n atTicks,\n ],\n queryFn: () =>\n getNetLiquidationValues({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenIds,\n atTicks,\n queryAddress,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount && atTicks.length > 0,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useLiquidationPrices(\n poolAddress: Address,\n tokenIds: bigint[],\n queryAddress: Address,\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.liquidationPrices(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n queryAddress,\n ],\n queryFn: () =>\n getLiquidationPrices({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenIds,\n queryAddress,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useAccountGreeks(poolAddress: Address, account?: Address, options?: QueryOptions) {\n const ctx = usePanopticContext()\n const storage = useRequireStorage()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.accountGreeks(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n getStorageCacheScopeKey(storage, ctx.storageScope),\n ],\n queryFn: () =>\n getAccountGreeks({\n client: ctx.publicClient,\n chainId: ctx.chainId,\n poolAddress,\n account: resolvedAccount!,\n storage,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useMarginBuffer(\n poolAddress: Address,\n tokenIds: bigint[],\n queryAddress: Address,\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.marginBuffer(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n queryAddress,\n ],\n queryFn: () =>\n getMarginBuffer({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenIds,\n queryAddress,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useIsLiquidatable(\n poolAddress: Address,\n tokenIds: bigint[],\n queryAddress: Address,\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.isLiquidatable(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n queryAddress,\n ],\n queryFn: () =>\n isLiquidatable({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenIds,\n queryAddress,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useAccountPremia(\n poolAddress: Address,\n tokenIds: bigint[],\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.accountPremia(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n ],\n queryFn: () =>\n getAccountPremia({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenIds,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function usePositionsWithPremia(\n poolAddress: Address,\n tokenIds: bigint[],\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.positionsWithPremia(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenIds,\n ],\n queryFn: () =>\n getPositionsWithPremia({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenIds,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- ERC4626 previews ---\n\nexport function usePreviewDeposit(\n poolAddress: Address,\n tokenIndex: 0 | 1,\n amount: bigint,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.erc4626Preview(chainId, poolAddress, 'deposit', amount),\n getClientCacheScopeKey(publicClient, clientScope),\n tokenIndex,\n ],\n queryFn: () => previewDeposit({ client: publicClient, poolAddress, tokenIndex, amount }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function usePreviewWithdraw(\n poolAddress: Address,\n tokenIndex: 0 | 1,\n amount: bigint,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.erc4626Preview(chainId, poolAddress, 'withdraw', amount),\n getClientCacheScopeKey(publicClient, clientScope),\n tokenIndex,\n ],\n queryFn: () => previewWithdraw({ client: publicClient, poolAddress, tokenIndex, amount }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function usePreviewMint(\n poolAddress: Address,\n tokenIndex: 0 | 1,\n amount: bigint,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.erc4626Preview(chainId, poolAddress, 'mint', amount),\n getClientCacheScopeKey(publicClient, clientScope),\n tokenIndex,\n ],\n queryFn: () => previewMint({ client: publicClient, poolAddress, tokenIndex, amount }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function usePreviewRedeem(\n poolAddress: Address,\n tokenIndex: 0 | 1,\n amount: bigint,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.erc4626Preview(chainId, poolAddress, 'redeem', amount),\n getClientCacheScopeKey(publicClient, clientScope),\n tokenIndex,\n ],\n queryFn: () => previewRedeem({ client: publicClient, poolAddress, tokenIndex, amount }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Collateral estimation ---\n\nexport function useEstimateCollateralRequired(\n poolAddress: Address,\n tokenId: bigint,\n positionSize: bigint,\n queryAddress: Address,\n account?: Address,\n options?: QueryOptions & { atTick?: bigint },\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.collateralEstimate(ctx.chainId, poolAddress, resolvedAccount!, tokenId),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n positionSize,\n queryAddress,\n options?.atTick,\n ],\n queryFn: () =>\n estimateCollateralRequired({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n tokenId,\n positionSize,\n queryAddress,\n atTick: options?.atTick,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useRequiredCreditForITM(\n poolAddress: Address,\n tokenId: bigint,\n positionSize: bigint,\n account?: Address,\n options?: QueryOptions & { existingPositionIds?: bigint[] },\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.requiredCreditForITM(\n ctx.chainId,\n poolAddress,\n resolvedAccount ?? ('' as Address),\n tokenId,\n ),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n positionSize,\n options?.existingPositionIds,\n ],\n queryFn: () => {\n if (!resolvedAccount) throw new Error('account required for getRequiredCreditForITM')\n return getRequiredCreditForITM({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount,\n tokenId,\n positionSize,\n existingPositionIds: options?.existingPositionIds,\n })\n },\n enabled: (options?.enabled ?? true) && !!resolvedAccount && tokenId !== 0n && positionSize > 0n,\n refetchInterval: options?.refetchInterval,\n placeholderData: keepPreviousData,\n })\n}\n\nexport function useMaxPositionSize(\n poolAddress: Address,\n tokenId: bigint,\n queryAddress: Address,\n account?: Address,\n options?: QueryOptions & {\n existingPositionIds?: bigint[]\n swapAtMint?: boolean\n precisionPct?: number\n },\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.maxPositionSize(\n ctx.chainId,\n poolAddress,\n resolvedAccount ?? ('' as Address),\n tokenId,\n ),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n queryAddress,\n options?.existingPositionIds?.map(String).join(',') ?? '',\n options?.existingPositionIds,\n options?.swapAtMint ?? false,\n options?.precisionPct ?? 1,\n ],\n queryFn: () => {\n if (!resolvedAccount) throw new Error('account required for getMaxPositionSize')\n return getMaxPositionSize({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount,\n tokenId,\n queryAddress,\n existingPositionIds: options?.existingPositionIds,\n swapAtMint: options?.swapAtMint,\n precisionPct: options?.precisionPct,\n })\n },\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n placeholderData: keepPreviousData,\n })\n}\n\nexport function useOptimizeRiskPartners(\n poolAddress: Address,\n tokenId: bigint,\n queryAddress: Address,\n atTick?: bigint,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.optimizeRiskPartners(chainId, poolAddress, tokenId),\n getClientCacheScopeKey(publicClient, clientScope),\n queryAddress,\n getAtTickCacheKey(atTick),\n ],\n queryFn: () =>\n optimizeTokenIdRiskPartners({\n client: publicClient,\n poolAddress,\n tokenId,\n queryAddress,\n atTick,\n }),\n enabled: options?.enabled,\n refetchInterval: options?.refetchInterval,\n placeholderData: keepPreviousData,\n })\n}\n\nexport function useMaxWithdrawable(\n collateralTrackerAddress: Address,\n positionIdList: bigint[],\n totalAssets: bigint,\n account?: Address,\n options?: QueryOptions & { client?: PublicClient },\n) {\n const ctx = usePanopticContext()\n const client = options?.client ?? ctx.publicClient\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.maxWithdrawable(\n ctx.chainId,\n collateralTrackerAddress,\n positionIdList,\n totalAssets,\n resolvedAccount ?? ('' as Address),\n ),\n getClientCacheScopeKey(client, ctx.clientScope),\n ],\n queryFn: () => {\n if (!resolvedAccount) throw new Error('account required for getMaxWithdrawable')\n return getMaxWithdrawable({\n client,\n collateralTrackerAddress,\n account: resolvedAccount,\n positionIdList,\n totalAssets,\n })\n },\n enabled: (options?.enabled ?? true) && !!resolvedAccount && totalAssets > 0n,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Open position preview ---\n\nexport function useOpenPositionPreview(\n poolAddress: Address,\n account: Address | undefined,\n existingPositionIds: bigint[],\n tokenId: bigint,\n positionSize: bigint,\n queryAddress: Address,\n tickLimitLow: bigint,\n tickLimitHigh: bigint,\n options?: QueryOptions & {\n spreadLimit?: bigint\n swapAtMint?: boolean\n usePremiaAsCollateral?: boolean\n blockNumber?: bigint\n },\n) {\n const ctx = usePanopticContext()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n // eslint-disable-next-line @tanstack/query/exhaustive-deps -- deps serialized as strings\n queryKey: [\n ...queryKeys.all,\n 'openPositionPreview',\n ctx.chainId.toString(),\n poolAddress,\n resolvedAccount!,\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n tokenId.toString(),\n positionSize.toString(),\n existingPositionIds.map(String).join(','),\n queryAddress,\n tickLimitLow.toString(),\n tickLimitHigh.toString(),\n options?.spreadLimit?.toString(),\n options?.swapAtMint,\n options?.usePremiaAsCollateral,\n options?.blockNumber?.toString(),\n ],\n queryFn: () =>\n getOpenPositionPreview({\n client: ctx.publicClient,\n poolAddress,\n account: resolvedAccount!,\n existingPositionIds,\n tokenId,\n positionSize,\n queryAddress,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit: options?.spreadLimit,\n swapAtMint: options?.swapAtMint,\n usePremiaAsCollateral: options?.usePremiaAsCollateral,\n chainId: ctx.chainId,\n blockNumber: options?.blockNumber,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount && tokenId !== 0n,\n staleTime: options?.staleTime ?? 0,\n })\n}\n\n// --- Storage-backed reads ---\n\nexport function useTrackedPositionIds(\n poolAddress: Address,\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const storage = useRequireStorage()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.trackedPositionIds(ctx.chainId, poolAddress, resolvedAccount!),\n getStorageCacheScopeKey(storage, ctx.storageScope),\n ],\n queryFn: () =>\n getTrackedPositionIds({\n chainId: ctx.chainId,\n poolAddress,\n account: resolvedAccount!,\n storage,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useTradeHistory(poolAddress: Address, account?: Address, options?: QueryOptions) {\n const ctx = usePanopticContext()\n const storage = useRequireStorage()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.tradeHistory(ctx.chainId, poolAddress, resolvedAccount!),\n getStorageCacheScopeKey(storage, ctx.storageScope),\n ],\n queryFn: () =>\n getTradeHistory({ chainId: ctx.chainId, poolAddress, account: resolvedAccount!, storage }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useRealizedPnL(poolAddress: Address, account?: Address, options?: QueryOptions) {\n const ctx = usePanopticContext()\n const storage = useRequireStorage()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.realizedPnL(ctx.chainId, poolAddress, resolvedAccount!),\n getStorageCacheScopeKey(storage, ctx.storageScope),\n ],\n queryFn: () =>\n getRealizedPnL({ chainId: ctx.chainId, poolAddress, account: resolvedAccount!, storage }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useClosedPositions(\n poolAddress: Address,\n account?: Address,\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n const storage = useRequireStorage()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.closedPositions(ctx.chainId, poolAddress, resolvedAccount!),\n getStorageCacheScopeKey(storage, ctx.storageScope),\n ],\n queryFn: () =>\n getClosedPositions({ chainId: ctx.chainId, poolAddress, account: resolvedAccount!, storage }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useSyncStatus(poolAddress: Address, account?: Address, options?: QueryOptions) {\n const ctx = usePanopticContext()\n const storage = useRequireStorage()\n const resolvedAccount = account ?? ctx.account\n return useQuery({\n queryKey: [\n ...queryKeys.syncStatus(ctx.chainId, poolAddress, resolvedAccount!),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n getStorageCacheScopeKey(storage, ctx.storageScope),\n ],\n queryFn: () =>\n getSyncStatus({\n client: ctx.publicClient,\n chainId: ctx.chainId,\n poolAddress,\n account: resolvedAccount!,\n storage,\n }),\n enabled: (options?.enabled ?? true) && !!resolvedAccount,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Factory reads ---\n\ntype OmitFactoryClient<T> = T extends unknown ? Omit<T, 'client'> : never\n\nexport function usePanopticPoolAddress(\n params?: OmitFactoryClient<GetPanopticPoolAddressParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'factory',\n 'getPanopticPool',\n params?.factoryAddress,\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getPanopticPoolAddress({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useFactoryTokenURI(\n params?: OmitFactoryClient<GetFactoryTokenURIParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'factory',\n 'tokenURI',\n params?.factoryAddress,\n params?.tokenId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getFactoryTokenURI({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useFactoryOwnerOf(\n params?: OmitFactoryClient<GetFactoryOwnerOfParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'factory',\n 'ownerOf',\n params?.factoryAddress,\n params?.tokenId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getFactoryOwnerOf({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useMinePoolAddress() {\n return useMutation({\n mutationFn: (params: MinePoolAddressLocalParams) => minePoolAddressLocalAsync(params),\n })\n}\n\nexport function useFactoryConstructMetadata(\n params?: OmitFactoryClient<GetFactoryConstructMetadataParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'factory',\n 'constructMetadata',\n params?.factoryAddress,\n params?.panopticPoolAddress,\n params?.symbol0,\n params?.symbol1,\n params?.fee?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getFactoryConstructMetadata({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\ntype OmitMineClient<T> = T extends unknown ? Omit<T, 'client'> : never\n\nexport function useSimulateDeployNewPool(\n params?: OmitMineClient<SimulateDeployNewPoolParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'factory',\n 'simulateDeployNewPool',\n params?.factoryAddress,\n params?.account,\n params?.salt?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return simulateDeployNewPool({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Price history ---\n\n/** Timestamp-based time range. Start/end resolved to blocks via RPC binary search or estimation. */\nexport interface TimestampTimeRange {\n mode: 'timestamps'\n /** Start of the range (Unix seconds) */\n startTimestamp: number\n /** End of the range (Unix seconds). Defaults to now if omitted. */\n endTimestamp?: number\n /** Number of evenly-spaced data points to fetch */\n points: number\n /** Extra block numbers to include in the fetched set (e.g. blockAtMint) */\n pinnedBlocks?: bigint[]\n /**\n * Block resolution strategy.\n * - 'exact': RPC binary search (~25 sequential getBlock calls). Default.\n * - 'estimate': 2-RPC linear extrapolation. Suitable for charts where\n * ±N-block error is invisible. Saves ~23 RPCs per call.\n */\n resolution?: 'exact' | 'estimate'\n}\n\n/** Block-based time range. No RPC resolution needed. */\nexport interface BlockTimeRange {\n mode: 'blocks'\n /** Start block number */\n startBlock: bigint\n /** End block number. Defaults to latest if omitted. */\n endBlock?: bigint\n /** Number of evenly-spaced data points to fetch */\n points: number\n /** Extra block numbers to include in the fetched set (e.g. blockAtMint) */\n pinnedBlocks?: bigint[]\n}\n\nexport type PriceHistoryTimeRange = TimestampTimeRange | BlockTimeRange\n\n/**\n * Build a stable string cache key from time range params (no object references).\n */\nfunction buildRangeHash(timeRange: PriceHistoryTimeRange): string {\n const pinnedSuffix = timeRange.pinnedBlocks?.length\n ? `-pin:${timeRange.pinnedBlocks.join(',')}`\n : ''\n return timeRange.mode === 'timestamps'\n ? `ts:${timeRange.startTimestamp}-${timeRange.endTimestamp ?? 'now'}-${timeRange.points}-${timeRange.resolution ?? 'exact'}${pinnedSuffix}`\n : `blk:${timeRange.startBlock}-${timeRange.endBlock ?? 'latest'}-${timeRange.points}${pinnedSuffix}`\n}\n\n/**\n * Resolve a PriceHistoryTimeRange to start/end block numbers.\n */\nasync function resolveTimeRange(\n client: PublicClient,\n timeRange: PriceHistoryTimeRange,\n): Promise<{ startBlock: bigint; endBlock: bigint }> {\n if (timeRange.mode === 'timestamps') {\n const resolver =\n timeRange.resolution === 'estimate' ? estimateBlockNumbers : resolveBlockNumbers\n if (timeRange.endTimestamp !== undefined) {\n const resolved = await resolver({\n client,\n timestamps: [timeRange.startTimestamp, timeRange.endTimestamp],\n })\n return { startBlock: resolved[0], endBlock: resolved[1] }\n } else {\n const [resolved, latest] = await Promise.all([\n resolver({ client, timestamps: [timeRange.startTimestamp] }),\n client.getBlockNumber(),\n ])\n return { startBlock: resolved[0], endBlock: latest }\n }\n } else {\n return {\n startBlock: timeRange.startBlock,\n endBlock: timeRange.endBlock ?? (await client.getBlockNumber()),\n }\n }\n}\n\n/**\n * Hook to fetch historical price data (tick + sqrtPriceX96) for a pool.\n *\n * Supports two modes:\n * - **timestamps**: Resolves start/end timestamps to blocks (2 RPC binary searches),\n * then interpolates the blocks in between (pure math).\n * - **blocks**: Uses start/end blocks directly, interpolates in between.\n * Zero resolution overhead.\n *\n * In both cases, the actual price reads are O(points) slot0 calls.\n * Reads at different historical blocks cannot be coalesced into one multicall.\n *\n * @param poolConfig - Pool version config (V3 pool address or V4 StateView + poolId)\n * @param timeRange - Time range specification (timestamps or blocks)\n * @param options - Query options (enabled, refetchInterval, staleTime, gcTime)\n */\nexport function usePriceHistory(\n poolConfig: PoolVersionConfig,\n timeRange: PriceHistoryTimeRange,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n\n const poolKey = poolConfig.version === 'v3' ? poolConfig.poolAddress : poolConfig.poolId\n const rangeHash = buildRangeHash(timeRange)\n\n return useQuery({\n // rangeHash serializes timeRange; poolKey serializes poolConfig\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.priceHistory(chainId, poolKey, rangeHash),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: async () => {\n const { startBlock, endBlock } = await resolveTimeRange(publicClient, timeRange)\n let blockNumbers = interpolateBlocks(startBlock, endBlock, timeRange.points)\n\n // Merge pinned blocks (e.g. blockAtMint) into the sorted array\n if (timeRange.pinnedBlocks?.length) {\n const blockSet = new Set(blockNumbers.map(String))\n const extras = timeRange.pinnedBlocks.filter(\n (b) => b >= startBlock && b <= endBlock && !blockSet.has(String(b)),\n )\n if (extras.length > 0) {\n blockNumbers = [...blockNumbers, ...extras].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n }\n }\n\n return getPriceHistory({ client: publicClient, blockNumbers, poolConfig })\n },\n enabled: (options?.enabled ?? true) && timeRange.points > 0,\n staleTime: options?.staleTime ?? Infinity,\n gcTime: options?.gcTime ?? 60 * 60_000,\n refetchInterval: options?.refetchInterval ?? false,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n })\n}\n\n/**\n * Hook to fetch historical streamia (streaming premia + Uniswap fee) data for a position.\n *\n * @param panopticPoolAddress - PanopticPool contract address\n * @param account - Account whose position to query\n * @param tokenId - The encoded tokenId\n * @param legs - Decoded legs with pre-computed liquidity\n * @param poolConfig - Pool version config (V3 pool address or V4 StateView + poolId)\n * @param timeRange - Time range specification (timestamps or blocks)\n * @param options - Query options + optional includeUniswapFees and settledEvents\n */\nexport function useStreamiaHistory(\n panopticPoolAddress: Address,\n account: Address,\n tokenId: bigint,\n legs: StreamiaLeg[],\n poolConfig: PoolVersionConfig,\n timeRange: PriceHistoryTimeRange,\n options?: QueryOptions & {\n includeUniswapFees?: boolean\n settledEvents?: Array<{ blockNumber: bigint; settled0: bigint; settled1: bigint }>\n },\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n\n const poolKey = poolConfig.version === 'v3' ? poolConfig.poolAddress : poolConfig.poolId\n const rangeHash = buildRangeHash(timeRange)\n\n const legsKey = legs.map((l) => `${l.lowerTick}:${l.upperTick}:${l.liquidity}`).join(',')\n const includeUniswapFees = options?.includeUniswapFees ?? true\n const settledEventsKey = options?.settledEvents\n ? options.settledEvents.map((e) => `${e.blockNumber}:${e.settled0}:${e.settled1}`).join(',')\n : ''\n\n return useQuery({\n // rangeHash serializes timeRange; poolKey serializes poolConfig; legsKey serializes legs\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.streamiaHistory(chainId, poolKey, rangeHash),\n getClientCacheScopeKey(publicClient, clientScope),\n panopticPoolAddress,\n account,\n tokenId.toString(),\n legsKey,\n includeUniswapFees,\n settledEventsKey,\n ],\n queryFn: async () => {\n const { startBlock, endBlock } = await resolveTimeRange(publicClient, timeRange)\n let blockNumbers = interpolateBlocks(startBlock, endBlock, timeRange.points)\n if (timeRange.pinnedBlocks?.length) {\n const pinSet = new Set(blockNumbers.map(String))\n const pins = timeRange.pinnedBlocks.filter(\n (b) => b >= startBlock && b <= endBlock && !pinSet.has(String(b)),\n )\n if (pins.length) {\n blockNumbers = [...blockNumbers, ...pins].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n }\n }\n return getStreamiaHistory({\n client: publicClient,\n panopticPoolAddress,\n account,\n tokenId,\n blockNumbers,\n legs,\n poolConfig,\n includeUniswapFees: options?.includeUniswapFees,\n settledEvents: options?.settledEvents,\n })\n },\n enabled: (options?.enabled ?? true) && timeRange.points > 0,\n staleTime: options?.staleTime ?? Infinity,\n gcTime: options?.gcTime ?? 60 * 60_000,\n refetchInterval: options?.refetchInterval ?? false,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n })\n}\n\n/**\n * Hook to fetch historical Uniswap fee data for a set of liquidity legs.\n *\n * @param legs - Decoded legs with pre-computed liquidity\n * @param poolConfig - Pool version config (V3 pool address or V4 StateView + poolId)\n * @param timeRange - Time range specification (timestamps or blocks)\n * @param options - Query options (enabled, refetchInterval, staleTime, gcTime)\n */\nexport function useUniswapFeeHistory(\n legs: StreamiaLeg[],\n poolConfig: PoolVersionConfig,\n timeRange: PriceHistoryTimeRange,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n\n const poolKey = poolConfig.version === 'v3' ? poolConfig.poolAddress : poolConfig.poolId\n const rangeHash = buildRangeHash(timeRange)\n\n const legsKey = legs.map((l) => `${l.lowerTick}:${l.upperTick}:${l.liquidity}`).join(',')\n\n return useQuery({\n // rangeHash serializes timeRange; poolKey serializes poolConfig; legsKey serializes legs\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.uniswapFeeHistory(chainId, poolKey, rangeHash),\n getClientCacheScopeKey(publicClient, clientScope),\n legsKey,\n ],\n queryFn: async () => {\n const { startBlock, endBlock } = await resolveTimeRange(publicClient, timeRange)\n let blockNumbers = interpolateBlocks(startBlock, endBlock, timeRange.points)\n if (timeRange.pinnedBlocks?.length) {\n const pinSet = new Set(blockNumbers.map(String))\n const pins = timeRange.pinnedBlocks.filter(\n (b) => b >= startBlock && b <= endBlock && !pinSet.has(String(b)),\n )\n if (pins.length) {\n blockNumbers = [...blockNumbers, ...pins].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n }\n }\n return getUniswapFeeHistory({ client: publicClient, blockNumbers, legs, poolConfig })\n },\n enabled: (options?.enabled ?? true) && timeRange.points > 0 && legs.length > 0,\n staleTime: options?.staleTime ?? Infinity,\n gcTime: options?.gcTime ?? 60 * 60_000,\n refetchInterval: options?.refetchInterval ?? false,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n })\n}\n\n// --- Direct Uniswap V3 pool info (no Panoptic required) ---\n\n/**\n * Reads basic on-chain info (token0, token1, fee, tickSpacing, slot0, liquidity) from a Uniswap V3 pool.\n * @param poolAddress - The Uniswap V3 pool contract address.\n * @param options - Optional React Query options (`enabled`, `staleTime`, `gcTime`, `refetchInterval`).\n * @returns React Query result resolving to the pool info object.\n */\nexport function useUniswapV3PoolInfo(poolAddress: Address | undefined, options?: QueryOptions) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'uniswapV3PoolInfo',\n chainId.toString(),\n poolAddress,\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () =>\n getUniswapV3PoolInfo({ client: publicClient, poolAddress: poolAddress as Address }),\n enabled: (options?.enabled ?? true) && !!poolAddress,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n/**\n * Reads per-tick active liquidity from a Uniswap V3 pool via PanopticQuery's `getTickNetsV3`.\n * @param poolAddress - The Uniswap V3 pool contract address.\n * @param queryAddress - The PanopticQuery helper contract address.\n * @param args - Tick window: `startTick` (inclusive) and `nTicks` count to scan.\n * @param options - Optional React Query options (`enabled`, `staleTime`, `gcTime`, `refetchInterval`).\n * @returns React Query result resolving to `{ ticks, liquidityNets }` parallel arrays.\n */\nexport function useUniswapV3PoolLiquidities(\n poolAddress: Address | undefined,\n queryAddress: Address | undefined,\n args: { startTick: number; nTicks: bigint } | undefined,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'uniswapV3PoolLiquidities',\n chainId.toString(),\n poolAddress,\n queryAddress,\n args?.startTick,\n args?.nTicks,\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => {\n if (!poolAddress || !queryAddress || !args) {\n throw new PanopticValidationError('useUniswapV3PoolLiquidities: missing required args')\n }\n const { startTick, nTicks } = args\n return getUniswapV3PoolLiquidities({\n client: publicClient,\n poolAddress,\n queryAddress,\n startTick,\n nTicks,\n })\n },\n enabled: (options?.enabled ?? true) && !!poolAddress && !!queryAddress && !!args,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Uniswap V4 direct reads (no Panoptic required) ---\n\n/**\n * Resolves a Uniswap V4 PoolKey from a poolId hash by scanning `Initialize` event logs on the PoolManager.\n * PoolKey is immutable, so results are cached indefinitely within the session by default.\n * @param poolManager - The Uniswap V4 PoolManager contract address.\n * @param poolId - The 32-byte poolId hash.\n * @param args - Optional `fromBlock` and `chunkSize` for log paging.\n * @param options - Optional React Query options (`enabled`, `staleTime`, `gcTime`, `refetchInterval`).\n * @returns React Query result resolving to the resolved `UniswapV4PoolKey`.\n */\nexport function useResolveUniswapV4PoolKey(\n poolManager: Address | undefined,\n poolId: `0x${string}` | undefined,\n args?: { fromBlock?: bigint; chunkSize?: bigint },\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'uniswapV4PoolKey',\n chainId.toString(),\n poolManager,\n poolId,\n args?.fromBlock?.toString(),\n args?.chunkSize?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () =>\n resolveUniswapV4PoolKey({\n client: publicClient,\n poolManager: poolManager as Address,\n poolId: poolId as `0x${string}`,\n fromBlock: args?.fromBlock,\n chunkSize: args?.chunkSize,\n }),\n enabled: (options?.enabled ?? true) && !!poolManager && !!poolId,\n // PoolKey is immutable — cache forever within the session.\n staleTime: options?.staleTime ?? Infinity,\n gcTime: options?.gcTime,\n refetchInterval: options?.refetchInterval,\n })\n}\n\n/**\n * Reads basic on-chain state (slot0, liquidity) for a Uniswap V4 pool via the StateView contract.\n * @param stateViewAddress - The Uniswap V4 StateView contract address.\n * @param poolId - The 32-byte poolId hash.\n * @param options - Optional React Query options (`enabled`, `staleTime`, `gcTime`, `refetchInterval`).\n * @returns React Query result resolving to the pool's basic state.\n */\nexport function useUniswapV4PoolBasicState(\n stateViewAddress: Address | undefined,\n poolId: `0x${string}` | undefined,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'uniswapV4PoolBasicState',\n chainId.toString(),\n stateViewAddress,\n poolId,\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () =>\n getUniswapV4PoolBasicState({\n client: publicClient,\n stateViewAddress: stateViewAddress as Address,\n poolId: poolId as `0x${string}`,\n }),\n enabled: (options?.enabled ?? true) && !!stateViewAddress && !!poolId,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n/**\n * Reads full pool info (slot0, liquidity, and PoolKey-derived metadata) for a Uniswap V4 pool via the StateView contract.\n * @param stateViewAddress - The Uniswap V4 StateView contract address.\n * @param poolKey - The pool's `UniswapV4PoolKey` (currency0, currency1, fee, tickSpacing, hooks).\n * @param options - Optional React Query options (`enabled`, `staleTime`, `gcTime`, `refetchInterval`).\n * @returns React Query result resolving to the full pool info object.\n */\nexport function useUniswapV4PoolInfo(\n stateViewAddress: Address | undefined,\n poolKey: UniswapV4PoolKey | undefined,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'uniswapV4PoolInfo',\n chainId.toString(),\n stateViewAddress,\n poolKey?.currency0,\n poolKey?.currency1,\n poolKey?.fee,\n poolKey?.tickSpacing,\n poolKey?.hooks,\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () =>\n getUniswapV4PoolInfo({\n client: publicClient,\n stateViewAddress: stateViewAddress as Address,\n poolKey: poolKey as UniswapV4PoolKey,\n }),\n enabled: (options?.enabled ?? true) && !!stateViewAddress && !!poolKey,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n/**\n * Reads per-tick active liquidity from a Uniswap V4 pool via PanopticQuery's `getTickNetsV4`.\n * @param queryAddress - The PanopticQuery helper contract address.\n * @param poolManager - The Uniswap V4 PoolManager contract address.\n * @param poolId - The 32-byte poolId hash.\n * @param args - `tickSpacing`, `startTick` (inclusive), and `nTicks` count to scan.\n * @param options - Optional React Query options (`enabled`, `staleTime`, `gcTime`, `refetchInterval`).\n * @returns React Query result resolving to `{ ticks, liquidityNets }` parallel arrays.\n */\nexport function useUniswapV4PoolLiquidities(\n queryAddress: Address | undefined,\n poolManager: Address | undefined,\n poolId: `0x${string}` | undefined,\n args: { tickSpacing: number; startTick: number; nTicks: bigint } | undefined,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'uniswapV4PoolLiquidities',\n chainId.toString(),\n queryAddress,\n poolManager,\n poolId,\n args?.tickSpacing,\n args?.startTick,\n args?.nTicks,\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => {\n if (!queryAddress || !poolManager || !poolId || !args) {\n throw new PanopticValidationError('useUniswapV4PoolLiquidities: missing required args')\n }\n const { tickSpacing, startTick, nTicks } = args\n return getUniswapV4PoolLiquidities({\n client: publicClient,\n queryAddress,\n poolManager,\n poolId,\n tickSpacing,\n startTick,\n nTicks,\n })\n },\n enabled: (options?.enabled ?? true) && !!queryAddress && !!poolManager && !!poolId && !!args,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Native token price ---\n\nexport function useNativeTokenPrice(\n panopticPoolAddress: Address | undefined,\n token0Decimals: bigint,\n token1Decimals: bigint,\n nativeIsToken0: boolean,\n options?: QueryOptions,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'nativeTokenPrice',\n chainId,\n panopticPoolAddress,\n token0Decimals,\n token1Decimals,\n nativeIsToken0,\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () =>\n getNativeTokenPrice({\n client: publicClient,\n panopticPoolAddress: panopticPoolAddress!,\n token0Decimals,\n token1Decimals,\n nativeIsToken0,\n }),\n enabled: (options?.enabled ?? true) && panopticPoolAddress !== undefined,\n refetchInterval: options?.refetchInterval ?? 30_000,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- SFPM reads ---\n\ntype OmitSfpmClient<T> = Omit<T, 'client'>\n\nexport function useUniswapV3PoolFromId(\n params?: OmitSfpmClient<GetUniswapV3PoolFromIdParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sfpm',\n 'getUniswapV3PoolFromId',\n params?.sfpmAddress,\n params?.poolId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getUniswapV3PoolFromId({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useUniswapV4PoolKeyFromId(\n params?: OmitSfpmClient<GetUniswapV4PoolKeyFromIdParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sfpm',\n 'getUniswapV4PoolKeyFromId',\n params?.sfpmAddress,\n params?.poolId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getUniswapV4PoolKeyFromId({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\nexport function useEnforcedTickLimits(\n params?: OmitSfpmClient<GetEnforcedTickLimitsParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sfpm',\n 'getEnforcedTickLimits',\n params?.sfpmAddress,\n params?.poolId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getEnforcedTickLimits({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Factory + SFPM composite reads ---\n\nexport function usePanopticPoolFromPoolId(\n params?: OmitFactoryClient<GetPanopticPoolFromPoolIdParams>,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'factory',\n 'getPanopticPoolFromPoolId',\n params?.sfpmAddress,\n params?.factoryAddress,\n params?.riskEngine,\n params?.poolId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return getPanopticPoolFromPoolId({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\ntype OmitResolveClient = Omit<ResolvePanopticPoolFromPoolIdParams, 'client'>\n\nexport function useResolvePanopticPoolFromPoolId(\n params?: OmitResolveClient,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'factory',\n 'resolvePanopticPoolFromPoolId',\n params?.poolId?.toString(),\n params?.riskEngine,\n params?.v3?.sfpmAddress,\n params?.v3?.factoryAddress,\n params?.v4?.sfpmAddress,\n params?.v4?.factoryAddress,\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new PanopticValidationError('params is required')\n return resolvePanopticPoolFromPoolId({ client: publicClient, ...params })\n },\n enabled: (options?.enabled ?? true) && params !== undefined,\n refetchInterval: options?.refetchInterval,\n staleTime: options?.staleTime,\n gcTime: options?.gcTime,\n })\n}\n\n// --- Borrow preview ---\n\nexport function usePreviewBorrow(\n poolAddress: Address,\n params?: {\n account: Address\n token: Address\n amount: bigint\n slippageBps: bigint\n existingPositionIds: bigint[]\n },\n options?: QueryOptions,\n) {\n const ctx = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'previewBorrow',\n ctx.chainId,\n poolAddress,\n params?.account,\n params?.token,\n params?.amount?.toString(),\n params?.slippageBps?.toString(),\n params?.existingPositionIds?.map(String).join(','),\n getClientCacheScopeKey(ctx.publicClient, ctx.clientScope),\n ],\n queryFn: () =>\n previewBorrow({\n client: ctx.publicClient,\n poolAddress,\n chainId: ctx.chainId,\n account: params!.account,\n token: params!.token,\n amount: params!.amount,\n slippageBps: params!.slippageBps,\n existingPositionIds: params!.existingPositionIds,\n }),\n enabled: (options?.enabled ?? true) && !!params && params.amount > 0n,\n staleTime: options?.staleTime ?? 10_000,\n gcTime: options?.gcTime,\n placeholderData: keepPreviousData,\n })\n}\n\n/**\n * Validate whether a builder code maps to a deployed builder wallet.\n *\n * Returns `{ data: true }` for valid codes, `{ data: false }` for invalid.\n * Disabled when `builderCode` is `undefined` or `0n`.\n */\nexport function useValidateBuilderCode(\n poolAddress: Address,\n builderCode: bigint | undefined,\n options?: QueryOptions,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n 'validateBuilderCode',\n poolAddress,\n String(builderCode),\n getClientCacheScopeKey(publicClient, clientScope),\n ],\n queryFn: () => {\n if (builderCode === undefined) throw new Error('builderCode is undefined')\n return validateBuilderCode({\n client: publicClient,\n poolAddress,\n builderCode,\n })\n },\n enabled: (options?.enabled ?? true) && builderCode !== undefined && builderCode !== 0n,\n staleTime: options?.staleTime ?? 60_000,\n gcTime: options?.gcTime,\n })\n}\n","/**\n * Mutation effects for cache invalidation with TanStack Query / SWR.\n * @module v2/react/mutationEffects\n */\n\nimport type { Address } from 'viem'\n\nimport { queryKeys } from './queryKeys'\n\n/**\n * Mutation type identifiers.\n */\nexport type MutationType =\n | 'openPosition'\n | 'closePosition'\n | 'forceExercise'\n | 'liquidate'\n | 'settleAccumulatedPremia'\n | 'deposit'\n | 'withdraw'\n | 'mint'\n | 'redeem'\n | 'approve'\n | 'pokeOracle'\n\n/**\n * Parameters for determining which queries to invalidate.\n */\nexport interface MutationEffectParams {\n chainId: bigint\n poolAddress: Address\n account: Address\n tokenId?: bigint\n}\n\n/**\n * Returns query keys that should be invalidated after a mutation.\n *\n * Use with TanStack Query's `queryClient.invalidateQueries()` or SWR's `mutate()`.\n *\n * @example\n * ```typescript\n * import { useMutation, useQueryClient } from '@tanstack/react-query'\n * import { mutationEffects, openPosition } from 'panoptic-v2-sdk'\n *\n * function useOpenPosition(config: WriteConfig) {\n * const queryClient = useQueryClient()\n *\n * return useMutation({\n * mutationFn: (params) => openPosition(config, params),\n * onSuccess: () => {\n * const keysToInvalidate = mutationEffects.openPosition({\n * chainId: config.chainId,\n * poolAddress: config.poolAddress,\n * account: config.walletClient.account.address,\n * })\n *\n * for (const key of keysToInvalidate) {\n * queryClient.invalidateQueries({ queryKey: key })\n * }\n * },\n * })\n * }\n * ```\n */\nexport const mutationEffects = {\n /**\n * Queries to invalidate after opening a position.\n */\n openPosition: (params: MutationEffectParams): readonly (readonly string[])[] => {\n const { chainId, poolAddress, account } = params\n return [\n queryKeys.pool(chainId, poolAddress),\n queryKeys.utilization(chainId, poolAddress),\n queryKeys.positions(chainId, poolAddress, account),\n queryKeys.trackedPositionIds(chainId, poolAddress, account),\n queryKeys.accountCollateral(chainId, poolAddress, account),\n queryKeys.accountSummaryBasic(chainId, poolAddress, account),\n queryKeys.accountSummaryRisk(chainId, poolAddress, account),\n queryKeys.isLiquidatable(chainId, poolAddress, account),\n queryKeys.liquidationPrices(chainId, poolAddress, account),\n queryKeys.accountGreeks(chainId, poolAddress, account),\n queryKeys.chunkSpreads(chainId, poolAddress),\n ]\n },\n\n /**\n * Queries to invalidate after closing a position.\n */\n closePosition: (params: MutationEffectParams): readonly (readonly string[])[] => {\n const { chainId, poolAddress, account, tokenId } = params\n const keys: (readonly string[])[] = [\n queryKeys.pool(chainId, poolAddress),\n queryKeys.utilization(chainId, poolAddress),\n queryKeys.positions(chainId, poolAddress, account),\n queryKeys.trackedPositionIds(chainId, poolAddress, account),\n queryKeys.accountCollateral(chainId, poolAddress, account),\n queryKeys.accountSummaryBasic(chainId, poolAddress, account),\n queryKeys.accountSummaryRisk(chainId, poolAddress, account),\n queryKeys.isLiquidatable(chainId, poolAddress, account),\n queryKeys.liquidationPrices(chainId, poolAddress, account),\n queryKeys.accountGreeks(chainId, poolAddress, account),\n queryKeys.closedPositions(chainId, poolAddress, account),\n queryKeys.tradeHistory(chainId, poolAddress, account),\n queryKeys.realizedPnL(chainId, poolAddress, account),\n queryKeys.chunkSpreads(chainId, poolAddress),\n ]\n\n if (tokenId !== undefined) {\n keys.push(queryKeys.position(chainId, poolAddress, tokenId))\n keys.push(queryKeys.positionGreeks(chainId, poolAddress, tokenId))\n }\n\n return keys\n },\n\n /**\n * Queries to invalidate after force exercising a position.\n */\n forceExercise: (params: MutationEffectParams): readonly (readonly string[])[] => {\n const { chainId, poolAddress, account, tokenId } = params\n const keys: (readonly string[])[] = [\n queryKeys.pool(chainId, poolAddress),\n queryKeys.utilization(chainId, poolAddress),\n queryKeys.accountCollateral(chainId, poolAddress, account),\n queryKeys.accountSummaryBasic(chainId, poolAddress, account),\n queryKeys.accountSummaryRisk(chainId, poolAddress, account),\n queryKeys.chunkSpreads(chainId, poolAddress),\n ]\n\n if (tokenId !== undefined) {\n keys.push(queryKeys.position(chainId, poolAddress, tokenId))\n }\n\n return keys\n },\n\n /**\n * Queries to invalidate after liquidating an account.\n */\n liquidate: (params: MutationEffectParams): readonly (readonly string[])[] => {\n const { chainId, poolAddress, account } = params\n return [\n queryKeys.pool(chainId, poolAddress),\n queryKeys.utilization(chainId, poolAddress),\n queryKeys.positions(chainId, poolAddress, account),\n queryKeys.trackedPositionIds(chainId, poolAddress, account),\n queryKeys.accountCollateral(chainId, poolAddress, account),\n queryKeys.accountSummaryBasic(chainId, poolAddress, account),\n queryKeys.accountSummaryRisk(chainId, poolAddress, account),\n queryKeys.isLiquidatable(chainId, poolAddress, account),\n queryKeys.liquidationPrices(chainId, poolAddress, account),\n queryKeys.accountGreeks(chainId, poolAddress, account),\n queryKeys.closedPositions(chainId, poolAddress, account),\n queryKeys.chunkSpreads(chainId, poolAddress),\n ]\n },\n\n /**\n * Queries to invalidate after settling accumulated premia.\n */\n settleAccumulatedPremia: (params: MutationEffectParams): readonly (readonly string[])[] => {\n const { chainId, poolAddress, account, tokenId } = params\n const keys: (readonly string[])[] = [\n queryKeys.accountCollateral(chainId, poolAddress, account),\n queryKeys.accountSummaryBasic(chainId, poolAddress, account),\n queryKeys.accountSummaryRisk(chainId, poolAddress, account),\n ]\n\n if (tokenId !== undefined) {\n keys.push(queryKeys.position(chainId, poolAddress, tokenId))\n }\n\n return keys\n },\n\n /**\n * Queries to invalidate after depositing to collateral tracker.\n */\n deposit: (params: MutationEffectParams): readonly (readonly string[])[] => {\n const { chainId, poolAddress, account } = params\n return [\n queryKeys.accountCollateral(chainId, poolAddress, account),\n queryKeys.accountSummaryBasic(chainId, poolAddress, account),\n queryKeys.accountSummaryRisk(chainId, poolAddress, account),\n queryKeys.isLiquidatable(chainId, poolAddress, account),\n queryKeys.liquidationPrices(chainId, poolAddress, account),\n ]\n },\n\n /**\n * Queries to invalidate after withdrawing from collateral tracker.\n */\n withdraw: (params: MutationEffectParams): readonly (readonly string[])[] => {\n const { chainId, poolAddress, account } = params\n return [\n queryKeys.accountCollateral(chainId, poolAddress, account),\n queryKeys.accountSummaryBasic(chainId, poolAddress, account),\n queryKeys.accountSummaryRisk(chainId, poolAddress, account),\n queryKeys.isLiquidatable(chainId, poolAddress, account),\n queryKeys.liquidationPrices(chainId, poolAddress, account),\n ]\n },\n\n /**\n * Queries to invalidate after minting collateral shares.\n */\n mint: (params: MutationEffectParams): readonly (readonly string[])[] => {\n return mutationEffects.deposit(params)\n },\n\n /**\n * Queries to invalidate after redeeming collateral shares.\n */\n redeem: (params: MutationEffectParams): readonly (readonly string[])[] => {\n return mutationEffects.withdraw(params)\n },\n\n /**\n * Queries to invalidate after approving token spending.\n */\n approve: (\n chainId: bigint,\n token: Address,\n owner: Address,\n spender: Address,\n ): readonly (readonly string[])[] => {\n return [queryKeys.approval(chainId, token, owner, spender)]\n },\n\n /**\n * Queries to invalidate after poking the oracle.\n */\n pokeOracle: (\n params: Pick<MutationEffectParams, 'chainId' | 'poolAddress'>,\n ): readonly (readonly string[])[] => {\n const { chainId, poolAddress } = params\n return [queryKeys.oracle(chainId, poolAddress), queryKeys.safeMode(chainId, poolAddress)]\n },\n} as const\n","/**\n * TanStack Query v5 mutation hooks for the Panoptic v2 SDK.\n * @module v2/react/hooks/writes\n */\n\nimport { type QueryClient, useMutation, useQueryClient } from '@tanstack/react-query'\nimport type { Address, WalletClient } from 'viem'\n\nimport {\n type ApproveParams,\n type ApprovePoolParams,\n type BorrowParams,\n type ClosePositionParams,\n type DeployNewPoolParams,\n type DepositParams,\n type DispatchParams,\n type ExecuteBatchDispatchParams,\n type ForceExerciseParams,\n type LiquidateParams,\n type MintParams,\n type OpenPositionParams,\n type PokeOracleParams,\n type RedeemParams,\n type RepayParams,\n type RollPositionParams,\n type SettleParams,\n type SmartRepayParams,\n type SupplyParams,\n type SwapExactInParams,\n type SwapExactOutParams,\n type UnsupplyParams,\n type UnwrapWethParams,\n type UnwrapXstockParams,\n type WithdrawParams,\n type WithdrawWithPositionsParams,\n type WrapEthParams,\n type WrapXstockParams,\n approve,\n approvePool,\n borrow,\n closePosition,\n deployNewPool,\n deposit,\n dispatch,\n executeBatchDispatch,\n forceExerciseAndWait,\n liquidate,\n mint,\n openPosition,\n pokeOracle,\n redeem,\n repay,\n rollPosition,\n settleAccumulatedPremia,\n smartRepay,\n supply,\n swapExactIn,\n swapExactOut,\n unsupply,\n unwrapWeth,\n unwrapXstock,\n withdraw,\n withdrawWithPositions,\n wrapEth,\n wrapXstock,\n} from '../../writes'\nimport { mutationEffects } from '../mutationEffects'\nimport { usePanopticContext } from '../provider'\nimport { queryKeys } from '../queryKeys'\n\ntype OmitInjected<T> = T extends unknown ? Omit<T, 'client' | 'walletClient' | 'account'> : never\ntype OmitInjectedWithPool<T> = Omit<T, 'client' | 'walletClient' | 'account' | 'poolAddress'>\ntype OmitInjectedWithPoolAndChain<T> = Omit<\n T,\n 'client' | 'walletClient' | 'account' | 'poolAddress' | 'chainId'\n>\n\ntype WalletInputs = {\n walletClient?: WalletClient\n account?: Address\n}\n\ntype WalletMutationContext = {\n signerAccount: Address\n}\n\nfunction requireWallet(inputs: WalletInputs): { walletClient: WalletClient; account: Address } {\n if (!inputs.walletClient || !inputs.account) {\n throw new Error('walletClient and account are required. Provide them via PanopticProvider.')\n }\n\n return {\n walletClient: inputs.walletClient,\n account: inputs.account,\n }\n}\n\nfunction createWalletMutationContext(inputs: WalletInputs): WalletMutationContext {\n return { signerAccount: requireWallet(inputs).account }\n}\n\nfunction invalidateKeys(\n queryClient: QueryClient,\n keysToInvalidate: readonly (readonly string[])[],\n): void {\n const seen = new Set<string>()\n\n for (const key of keysToInvalidate) {\n const serialized = JSON.stringify(key)\n if (seen.has(serialized)) {\n continue\n }\n\n seen.add(serialized)\n queryClient.invalidateQueries({ queryKey: key })\n }\n}\n\nexport function useApprove() {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<ApproveParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return approve({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: (_data, params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.approve(\n chainId,\n params.tokenAddress,\n context.signerAccount,\n params.spenderAddress,\n ),\n )\n },\n })\n}\n\nexport function useApprovePool(poolAddress: Address) {\n const { publicClient, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<ApprovePoolParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return approvePool({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [...queryKeys.all, 'approval'] })\n },\n })\n}\n\nexport function useDeposit(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<DepositParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return deposit({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.deposit({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useWithdraw(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<WithdrawParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return withdraw({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.withdraw({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\n/**\n * Wrap an underlying xStock into its ERC4626 wrapper (`deposit`). Requires a\n * prior approval of the underlying to the wrapper (use {@link useApprove}).\n * Invalidates SDK queries so balances refetch.\n */\nexport function useWrapXstock() {\n const { publicClient, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<WrapXstockParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return wrapXstock({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [...queryKeys.all] })\n },\n })\n}\n\n/**\n * Unwrap wrapper shares back into the underlying xStock (`redeem`). Burns the\n * owner's own shares — no approval needed.\n */\nexport function useUnwrapXstock() {\n const { publicClient, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<UnwrapXstockParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return unwrapXstock({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [...queryKeys.all] })\n },\n })\n}\n\n/**\n * Wrap native ETH into WETH (`deposit` payable). No approval needed.\n * Invalidates SDK queries so balances refetch.\n */\nexport function useWrapEth() {\n const { publicClient, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<WrapEthParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return wrapEth({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [...queryKeys.all] })\n },\n })\n}\n\n/**\n * Unwrap WETH back into native ETH (`withdraw`). Burns the caller's own WETH —\n * no approval needed. Invalidates SDK queries so balances refetch.\n */\nexport function useUnwrapWeth() {\n const { publicClient, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<UnwrapWethParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return unwrapWeth({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [...queryKeys.all] })\n },\n })\n}\n\nexport function useMintShares(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<MintParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return mint({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.mint({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useRedeem(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<RedeemParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return redeem({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.redeem({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useWithdrawWithPositions(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<WithdrawWithPositionsParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return withdrawWithPositions({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.withdraw({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useOpenPosition(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<OpenPositionParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return openPosition({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.openPosition({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useClosePosition(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<ClosePositionParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return closePosition({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: (_data, params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.closePosition({\n chainId,\n poolAddress,\n account: context.signerAccount,\n tokenId: params.tokenId,\n }),\n )\n },\n })\n}\n\nexport function useRollPosition(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<RollPositionParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return rollPosition({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.openPosition({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useLiquidate(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<LiquidateParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return liquidate({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: (_data, params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(queryClient, [\n ...mutationEffects.liquidate({ chainId, poolAddress, account: context.signerAccount }),\n ...mutationEffects.liquidate({ chainId, poolAddress, account: params.liquidatee }),\n ])\n },\n })\n}\n\nexport function useForceExercise(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account, storage } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (\n params: Omit<\n ForceExerciseParams,\n 'client' | 'walletClient' | 'account' | 'poolAddress' | 'chainId' | 'storage'\n >,\n ) => {\n const wallet = requireWallet({ walletClient, account })\n return forceExerciseAndWait({\n client: publicClient,\n ...wallet,\n poolAddress,\n ...params,\n storage,\n chainId,\n })\n },\n onSuccess: (_data, params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(queryClient, [\n ...mutationEffects.forceExercise({ chainId, poolAddress, account: context.signerAccount }),\n ...mutationEffects.forceExercise({ chainId, poolAddress, account: params.user }),\n ])\n },\n })\n}\n\nexport function useSettleAccumulatedPremia(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<SettleParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return settleAccumulatedPremia({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.settleAccumulatedPremia({\n chainId,\n poolAddress,\n account: context.signerAccount,\n }),\n )\n },\n })\n}\n\nexport function usePokeOracle(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params?: OmitInjectedWithPool<PokeOracleParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return pokeOracle({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: () => {\n invalidateKeys(queryClient, mutationEffects.pokeOracle({ chainId, poolAddress }))\n },\n })\n}\n\nexport function useDispatch(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<DispatchParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return dispatch({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) {\n return\n }\n\n invalidateKeys(\n queryClient,\n mutationEffects.openPosition({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useBatchDispatch(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPool<ExecuteBatchDispatchParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return executeBatchDispatch({ client: publicClient, ...wallet, poolAddress, ...params })\n },\n onSuccess: (_data, params, context) => {\n if (!context) {\n return\n }\n\n const closedTokenIds = params.items.filter((i) => i.kind === 'burn').map((i) => i.tokenId)\n\n const keys = [\n ...mutationEffects.openPosition({\n chainId,\n poolAddress,\n account: context.signerAccount,\n }),\n ...closedTokenIds.flatMap((tokenId) =>\n mutationEffects.closePosition({\n chainId,\n poolAddress,\n account: context.signerAccount,\n tokenId,\n }),\n ),\n ]\n invalidateKeys(queryClient, keys)\n },\n })\n}\n\nexport function useDeployNewPool() {\n const { publicClient, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjected<DeployNewPoolParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return deployNewPool({ client: publicClient, ...wallet, ...params })\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [...queryKeys.all, 'factory'] })\n },\n })\n}\n\nexport function useSwapExactOut(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPoolAndChain<SwapExactOutParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return swapExactOut({ client: publicClient, ...wallet, poolAddress, chainId, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) return\n invalidateKeys(\n queryClient,\n mutationEffects.deposit({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useSupply(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPoolAndChain<SupplyParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return supply({ client: publicClient, ...wallet, poolAddress, chainId, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) return\n invalidateKeys(\n queryClient,\n mutationEffects.deposit({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useUnsupply(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPoolAndChain<UnsupplyParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return unsupply({ client: publicClient, ...wallet, poolAddress, chainId, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) return\n invalidateKeys(\n queryClient,\n mutationEffects.withdraw({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useBorrow(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPoolAndChain<BorrowParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return borrow({ client: publicClient, ...wallet, poolAddress, chainId, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) return\n invalidateKeys(\n queryClient,\n mutationEffects.openPosition({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n\nexport function useRepay(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPoolAndChain<RepayParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return repay({ client: publicClient, ...wallet, poolAddress, chainId, ...params })\n },\n onSuccess: (_data, params, context) => {\n if (!context) return\n invalidateKeys(\n queryClient,\n mutationEffects.closePosition({\n chainId,\n poolAddress,\n account: context.signerAccount,\n tokenId: params.loanTokenId,\n }),\n )\n },\n })\n}\n\nexport function useSmartRepay(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPoolAndChain<SmartRepayParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return smartRepay({ client: publicClient, ...wallet, poolAddress, chainId, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) return\n invalidateKeys(\n queryClient,\n mutationEffects.closePosition({\n chainId,\n poolAddress,\n account: context.signerAccount,\n }),\n )\n },\n })\n}\n\nexport function useSwapExactIn(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n onMutate: () => createWalletMutationContext({ walletClient, account }),\n mutationFn: (params: OmitInjectedWithPoolAndChain<SwapExactInParams>) => {\n const wallet = requireWallet({ walletClient, account })\n return swapExactIn({ client: publicClient, ...wallet, poolAddress, chainId, ...params })\n },\n onSuccess: (_data, _params, context) => {\n if (!context) return\n invalidateKeys(\n queryClient,\n mutationEffects.deposit({ chainId, poolAddress, account: context.signerAccount }),\n )\n },\n })\n}\n","/**\n * Dispatch simulation for the Panoptic v2 SDK.\n * @module v2/simulations/simulateDispatch\n */\n\nimport type { Address, Hex, PublicClient } from 'viem'\nimport { decodeFunctionResult, encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError } from '../errors'\nimport type { DispatchSimulation, SimulationResult, TokenFlow } from '../types'\nimport type { TickAndSpreadLimits } from '../writes/position'\nimport { decodeLeftRightUnsigned } from '../writes/utils'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\n/**\n * Parameters for simulating dispatch.\n */\nexport interface SimulateDispatchParams {\n /** Public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /**\n * Operation list passed to `dispatch()` — one tokenId per batch item, in\n * operation order. Mints reference NEW tokenIds the user doesn't yet own,\n * so this list is NOT safe to read against pre-dispatch storage.\n */\n positionIdList: bigint[]\n /** Final position ID list after operations */\n finalPositionIdList: bigint[]\n /**\n * The user's actual on-chain `positionIdList` BEFORE dispatch. Required to\n * populate `preMarginExcess0/1` (read via a pre-dispatch\n * `getFullPositionsData` chained in the same multicall). When omitted,\n * `preMarginExcess0/1` are returned as `null`.\n */\n existingPositionIdList?: bigint[]\n /** Position sizes for each operation */\n positionSizes: bigint[]\n /** Tick and spread limits for each operation */\n tickAndSpreadLimits: TickAndSpreadLimits[]\n /** Whether to use premia as collateral */\n usePremiaAsCollateral?: boolean\n /** Builder code */\n builderCode?: bigint\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate a raw dispatch operation.\n *\n * Uses PanopticPool.multicall with getAssetsOf-dispatch-getAssetsOf pattern\n * to measure exact collateral asset movements.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with dispatch data or error\n */\nexport async function simulateDispatch(\n params: SimulateDispatchParams,\n): Promise<SimulationResult<DispatchSimulation>> {\n const {\n client,\n poolAddress,\n account,\n positionIdList,\n finalPositionIdList,\n positionSizes,\n tickAndSpreadLimits,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n blockNumber,\n existingPositionIdList,\n } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n try {\n // Encode dispatch call data\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n positionSizes,\n tickAndSpreadLimits.map(\n (t) => [Number(t[0]), Number(t[1]), Number(t[2])] as readonly [number, number, number],\n ),\n usePremiaAsCollateral,\n builderCode,\n ],\n })\n\n // Encode getFullPositionsData against the pre-dispatch (caller-supplied\n // existing list) and post-dispatch (finalPositionIdList) position lists.\n // Running both in the same multicall — pre-call before dispatch, post-call\n // after — lets the simulation report margin excess (= assets - required\n // collateral) on both sides atomically. Required collateral is summed\n // across the per-position LeftRightUnsigned entries.\n //\n // The pre-call uses `existingPositionIdList` (the user's actual storage\n // list), NOT `positionIdList` (the operation list, which contains\n // not-yet-minted tokenIds and would revert with PositionNotOwned).\n const preFullPositionsCallData =\n existingPositionIdList !== undefined\n ? encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, existingPositionIdList],\n })\n : undefined\n const postFullPositionsCallData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, finalPositionIdList],\n })\n\n // Simulate with token flow measurement using PanopticPool.multicall + getAssetsOf\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account,\n callData,\n blockNumber: targetBlockNumber,\n preCallData: preFullPositionsCallData ? [preFullPositionsCallData] : undefined,\n postCallData: [postFullPositionsCallData],\n })\n\n if (!flowResult.success || !flowResult.tokenFlow) {\n throw (\n flowResult.rawError ?? new PanopticError(flowResult.error || 'Token flow simulation failed')\n )\n }\n\n const tokenFlow: TokenFlow = flowResult.tokenFlow\n\n // Determine which positions were created/closed by diffing the post-dispatch\n // list against the pre-dispatch on-chain snapshot. `positionIdList` is the\n // operation list (which contains not-yet-minted tokenIds and excludes\n // unaffected pre-existing ones), so it can't be used as the \"before\" set.\n const preSnapshot = existingPositionIdList ?? []\n const positionsCreated = finalPositionIdList.filter((id) => !preSnapshot.includes(id))\n const positionsClosed = preSnapshot.filter((id) => !finalPositionIdList.includes(id))\n\n // Sum collateralRequirements across all entries from one\n // getFullPositionsData multicall slot. Each entry is a LeftRightUnsigned\n // packed as right=token0, left=token1. Returns null on decode failure so\n // callers fall back gracefully (the type is bigint | null).\n const sumCollateralReq = (data: Hex | undefined): { token0: bigint; token1: bigint } | null => {\n if (!data) return null\n try {\n const decoded = decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n data,\n })\n const reqs = decoded[3] // collateralRequirements\n let token0 = 0n\n let token1 = 0n\n for (const packed of reqs) {\n const r = decodeLeftRightUnsigned(packed)\n token0 += r.right\n token1 += r.left\n }\n return { token0, token1 }\n } catch {\n return null\n }\n }\n\n const preReq = sumCollateralReq(flowResult.preCallResults?.[0])\n const postReq = sumCollateralReq(flowResult.postCallResults?.[0])\n\n const _meta = await metaPromise\n\n // Build simulation result with actual token flow data\n const data: DispatchSimulation = {\n netAmount0: tokenFlow.delta0,\n netAmount1: tokenFlow.delta1,\n positionsCreated,\n positionsClosed,\n postCollateral0: tokenFlow.balanceAfter0,\n postCollateral1: tokenFlow.balanceAfter1,\n preMarginExcess0: preReq ? tokenFlow.balanceBefore0 - preReq.token0 : null,\n preMarginExcess1: preReq ? tokenFlow.balanceBefore1 - preReq.token1 : null,\n postMarginExcess0: postReq ? tokenFlow.balanceAfter0 - postReq.token0 : null,\n postMarginExcess1: postReq ? tokenFlow.balanceAfter1 - postReq.token1 : null,\n }\n\n return {\n success: true,\n data,\n gasEstimate: flowResult.gasEstimate,\n tokenFlow,\n _meta,\n }\n } catch (error) {\n const _meta = await metaPromise\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Simulation failed',\n error instanceof Error ? error : undefined,\n ),\n _meta,\n }\n }\n}\n","/**\n * Item-based wrapper around simulateDispatch for batched mint/burn ops.\n * @module v2/simulations/simulateBatchDispatch\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { buildBatchDispatchArgs } from '../batch/build'\nimport type { BatchDiagnostic, BatchOp } from '../batch/types'\nimport { getBlockMeta } from '../clients'\nimport type { BlockMeta, DispatchSimulation, SimulationResult } from '../types'\nimport { simulateDispatch } from './simulateDispatch'\n\n/**\n * Parameters for `simulateBatchDispatch`.\n *\n * - `client`: viem PublicClient used for read calls.\n * - `poolAddress`: PanopticPool address the batch targets.\n * - `account`: account whose collateral and positions are simulated against.\n * - `items`: ordered batch ops (mints + burns) — order matters because dispatch\n * applies them sequentially.\n * - `existingPositionIds`: account's current on-chain `positionIdList`. Must\n * reflect FRESH on-chain state (not a cached/optimistic snapshot) — stale\n * data here yields incorrect pre-dispatch margin excess and false\n * burn-not-found diagnostics.\n * - `usePremiaAsCollateral`: applied across the whole dispatch. Defaults to\n * `false`.\n * - `builderCode`: applied across the whole dispatch. Defaults to `0n`.\n * - `blockNumber`: optional pinned block; defaults to the client's latest.\n */\nexport interface SimulateBatchDispatchParams {\n client: PublicClient\n poolAddress: Address\n account: Address\n /** Batch ops in operation order. */\n items: BatchOp[]\n /** Current on-chain positionIdList for the account (fresh). */\n existingPositionIds: bigint[]\n /** Apply across the whole dispatch. Defaults to false. */\n usePremiaAsCollateral?: boolean\n /** Apply across the whole dispatch. Defaults to 0n. */\n builderCode?: bigint\n /** Optional pinned block. */\n blockNumber?: bigint\n}\n\n/**\n * Result returned by `simulateBatchDispatch`.\n *\n * Either delegates to `simulateDispatch` (and therefore matches its\n * `SimulationResult<DispatchSimulation>` shape), or short-circuits with\n * batch-level diagnostics when the items fail validation. In either case the\n * shape includes a `diagnostics` field so callers can render conflicts before\n * deciding what to do — UIs typically gray out the Execute button when\n * `diagnostics.length > 0`.\n */\nexport type SimulateBatchDispatchResult =\n | (SimulationResult<DispatchSimulation> & { diagnostics: BatchDiagnostic[] })\n | { success: false; diagnostics: BatchDiagnostic[]; _meta: BlockMeta }\n\n/**\n * Simulate a batch dispatch built from `items` + the current on-chain\n * positionIdList. Returns batch diagnostics OR a real simulation result.\n */\nexport async function simulateBatchDispatch(\n params: SimulateBatchDispatchParams,\n): Promise<SimulateBatchDispatchResult> {\n const {\n client,\n poolAddress,\n account,\n items,\n existingPositionIds,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n blockNumber,\n } = params\n\n const { args, diagnostics } = buildBatchDispatchArgs({\n items,\n existingPositionIds,\n usePremiaAsCollateral,\n builderCode,\n })\n\n if (args === null) {\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const meta = await getBlockMeta({ client, blockNumber: targetBlockNumber })\n return { success: false, diagnostics, _meta: meta }\n }\n\n const sim = await simulateDispatch({\n client,\n poolAddress,\n account,\n positionIdList: args.positionIdList,\n finalPositionIdList: args.finalPositionIdList,\n existingPositionIdList: existingPositionIds,\n positionSizes: args.positionSizes,\n tickAndSpreadLimits: args.tickAndSpreadLimits,\n usePremiaAsCollateral: args.usePremiaAsCollateral,\n builderCode: args.builderCode,\n blockNumber,\n })\n\n return { ...sim, diagnostics: [] }\n}\n","/**\n * Close position simulation for the Panoptic v2 SDK.\n * @module v2/simulations/simulateClosePosition\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError } from '../errors'\nimport type { ClosePositionSimulation, SimulationResult } from '../types'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\n/**\n * Parameters for simulating position closing.\n */\nexport interface SimulateClosePositionParams {\n /** Public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** Current position ID list */\n positionIdList: bigint[]\n /** TokenId of position to close */\n tokenId: bigint\n /** Position size to close */\n positionSize: bigint\n /**\n * Lower tick limit (always <= tickLimitHigh).\n * Use MIN_TICK (-887272n) to allow any downward price movement.\n */\n tickLimitLow: bigint\n /**\n * Upper tick limit (always >= tickLimitLow).\n * Use MAX_TICK (887272n) to allow any upward price movement.\n */\n tickLimitHigh: bigint\n /** Spread limit tick (use 0n for no spread limit) */\n spreadLimit?: bigint\n /**\n * Whether to swap tokens at burn to achieve single-sided exposure.\n * When true, tickLimits are passed to dispatch in descending order (high, low).\n * When false (default), tickLimits are passed in ascending order (low, high).\n */\n swapAtMint?: boolean\n /** Whether to use premia as collateral */\n usePremiaAsCollateral?: boolean\n /** Builder code */\n builderCode?: bigint\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate closing a position.\n *\n * Uses PanopticPool.multicall with getAssetsOf-dispatch-getAssetsOf pattern\n * to measure exact collateral asset movements from the burn.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with close data or error\n */\nexport async function simulateClosePosition(\n params: SimulateClosePositionParams,\n): Promise<SimulationResult<ClosePositionSimulation>> {\n const {\n client,\n poolAddress,\n account,\n positionIdList,\n tokenId,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit = 0n,\n swapAtMint = false,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n blockNumber,\n } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n // Build tick limits based on swapAtMint flag:\n // - swapAtMint=true: descending order (high, low) triggers SFPM swap\n // - swapAtMint=false: ascending order (low, high) no swap\n const tickLimits: readonly [number, number, number] = swapAtMint\n ? [Number(tickLimitHigh), Number(tickLimitLow), Number(spreadLimit)]\n : [Number(tickLimitLow), Number(tickLimitHigh), Number(spreadLimit)]\n\n try {\n // Prepare final position list (without the closed position)\n const finalPositionIdList = positionIdList.filter((id) => id !== tokenId)\n\n // Encode dispatch call data for burn (positionSize = 0 signals close)\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n [tokenId],\n finalPositionIdList,\n [0n],\n [tickLimits],\n usePremiaAsCollateral,\n builderCode,\n ],\n })\n\n // Simulate with token flow measurement using PanopticPool.multicall + getAssetsOf\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account,\n callData,\n blockNumber: targetBlockNumber,\n })\n\n if (!flowResult.success || !flowResult.tokenFlow) {\n throw (\n flowResult.rawError ?? new PanopticError(flowResult.error || 'Token flow simulation failed')\n )\n }\n\n const tokenFlow = flowResult.tokenFlow\n const _meta = await metaPromise\n\n // Map token flow to simulation fields:\n // Positive delta = user receives collateral back\n const data: ClosePositionSimulation = {\n amount0Received: tokenFlow.delta0,\n amount1Received: tokenFlow.delta1,\n premiaCollected0: null, // Requires pre-close premia snapshot\n premiaCollected1: null,\n postCollateral0: tokenFlow.balanceAfter0,\n postCollateral1: tokenFlow.balanceAfter1,\n realizedPnL0: null, // Requires open position cost basis\n realizedPnL1: null,\n }\n\n return {\n success: true,\n data,\n gasEstimate: flowResult.gasEstimate,\n tokenFlow,\n _meta,\n }\n } catch (error) {\n const _meta = await metaPromise\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Simulation failed',\n error instanceof Error ? error : undefined,\n ),\n _meta,\n }\n }\n}\n","/**\n * Force exercise simulation for the Panoptic v2 SDK.\n * @module v2/simulations/simulateForceExercise\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError } from '../errors'\nimport type { ForceExerciseSimulation, SimulationResult, TokenFlow } from '../types'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\n/**\n * Parameters for simulating force exercise.\n */\nexport interface SimulateForceExerciseParams {\n /** Public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Exercisor account address */\n account: Address\n /** Account whose position is being exercised */\n user: Address\n /** Position IDs from the exercisor's account */\n positionIdListFrom: bigint[]\n /** Position IDs of the target user */\n positionIdListTo: bigint[]\n /** Final position ID list for the user after exercise */\n positionIdListToFinal: bigint[]\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate a force exercise operation.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with exercise data or error\n */\nexport async function simulateForceExercise(\n params: SimulateForceExerciseParams,\n): Promise<SimulationResult<ForceExerciseSimulation>> {\n const {\n client,\n poolAddress,\n account,\n user,\n positionIdListFrom,\n positionIdListTo,\n positionIdListToFinal,\n blockNumber,\n } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n // Default token flow for failure cases\n const emptyTokenFlow: TokenFlow = {\n delta0: 0n,\n delta1: 0n,\n balanceBefore0: 0n,\n balanceBefore1: 0n,\n balanceAfter0: 0n,\n balanceAfter1: 0n,\n tickBefore: null,\n tickAfter: null,\n }\n\n try {\n // Encode dispatchFrom call data\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatchFrom',\n args: [positionIdListFrom, user, positionIdListTo, positionIdListToFinal, 0n],\n })\n\n // Simulate with token flow measurement using PanopticPool.multicall + getAssetsOf\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account, // Measure exercisor's collateral change\n callData,\n blockNumber: targetBlockNumber,\n })\n\n if (!flowResult.success || !flowResult.tokenFlow) {\n // Check for specific exercise-related errors\n const errorMessage = flowResult.error || 'Simulation failed'\n const isNotExercisable =\n errorMessage.includes('NoLegsExercisable') || errorMessage.includes('NotALongLeg')\n\n if (isNotExercisable) {\n const _meta = await metaPromise\n const data: ForceExerciseSimulation = {\n exerciseFee0: 0n,\n exerciseFee1: 0n,\n canExercise: false,\n reason: errorMessage.includes('NoLegsExercisable')\n ? 'No legs are exercisable (not ITM)'\n : 'Position does not have a long leg',\n }\n\n return {\n success: true,\n data,\n gasEstimate: 0n,\n tokenFlow: emptyTokenFlow,\n _meta,\n }\n }\n\n throw new PanopticError(errorMessage)\n }\n\n const _meta = await metaPromise\n const tokenFlow: TokenFlow = flowResult.tokenFlow\n\n // Build simulation result with actual token flow data\n // Exercise fee is what the exercisor receives (positive delta)\n const data: ForceExerciseSimulation = {\n exerciseFee0: tokenFlow.delta0,\n exerciseFee1: tokenFlow.delta1,\n canExercise: true,\n }\n\n return {\n success: true,\n data,\n gasEstimate: flowResult.gasEstimate,\n tokenFlow,\n _meta,\n }\n } catch (error) {\n const _meta = await metaPromise\n // If simulation fails, check the reason\n const errorMessage = error instanceof Error ? error.message : 'Simulation failed'\n\n // Check for specific exercise-related errors\n const isNotExercisable =\n errorMessage.includes('NoLegsExercisable') || errorMessage.includes('NotALongLeg')\n\n if (isNotExercisable) {\n const data: ForceExerciseSimulation = {\n exerciseFee0: 0n,\n exerciseFee1: 0n,\n canExercise: false,\n reason: errorMessage.includes('NoLegsExercisable')\n ? 'No legs are exercisable (not ITM)'\n : 'Position does not have a long leg',\n }\n\n return {\n success: true,\n data,\n gasEstimate: 0n,\n tokenFlow: emptyTokenFlow,\n _meta,\n }\n }\n\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(errorMessage, error instanceof Error ? error : undefined),\n _meta,\n }\n }\n}\n","/**\n * Liquidation simulation for the Panoptic v2 SDK.\n * @module v2/simulations/simulateLiquidate\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError } from '../errors'\nimport type { LiquidateSimulation, SimulationResult, TokenFlow } from '../types'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\n/**\n * Parameters for simulating liquidation.\n */\nexport interface SimulateLiquidateParams {\n /** Public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Liquidator account address */\n account: Address\n /** Account being liquidated */\n liquidatee: Address\n /** Position IDs from the liquidator's account */\n positionIdListFrom: bigint[]\n /** Position IDs of the liquidatee */\n positionIdListTo: bigint[]\n /** Final position ID list for the liquidatee after liquidation */\n positionIdListToFinal: bigint[]\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate a liquidation operation.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with liquidation data or error\n */\nexport async function simulateLiquidate(\n params: SimulateLiquidateParams,\n): Promise<SimulationResult<LiquidateSimulation>> {\n const {\n client,\n poolAddress,\n account,\n liquidatee,\n positionIdListFrom,\n positionIdListTo,\n positionIdListToFinal,\n blockNumber,\n } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n // Default token flow for failure cases\n const emptyTokenFlow: TokenFlow = {\n delta0: 0n,\n delta1: 0n,\n balanceBefore0: 0n,\n balanceBefore1: 0n,\n balanceAfter0: 0n,\n balanceAfter1: 0n,\n tickBefore: null,\n tickAfter: null,\n }\n\n try {\n // Encode dispatchFrom call data\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatchFrom',\n args: [positionIdListFrom, liquidatee, positionIdListTo, positionIdListToFinal, 0n],\n })\n\n // Simulate with token flow measurement using PanopticPool.multicall + getAssetsOf\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account, // Measure liquidator's collateral change\n callData,\n blockNumber: targetBlockNumber,\n })\n\n if (!flowResult.success || !flowResult.tokenFlow) {\n // Check if it's a specific error indicating not liquidatable\n const errorMessage = flowResult.error || 'Simulation failed'\n const isNotLiquidatable =\n errorMessage.includes('NotMarginCalled') || errorMessage.includes('AccountInsolvent')\n\n if (isNotLiquidatable) {\n const _meta = await metaPromise\n const data: LiquidateSimulation = {\n bonus0: 0n,\n bonus1: 0n,\n positionsClosed: [],\n isLiquidatable: false,\n shortfall0: 0n,\n shortfall1: 0n,\n }\n return {\n success: true,\n data,\n gasEstimate: 0n,\n tokenFlow: emptyTokenFlow,\n _meta,\n }\n }\n\n throw new PanopticError(errorMessage)\n }\n\n const _meta = await metaPromise\n const tokenFlow: TokenFlow = flowResult.tokenFlow\n\n // Positions that would be closed\n const positionsClosed = positionIdListTo.filter((id) => !positionIdListToFinal.includes(id))\n\n // Build simulation result with actual token flow data\n // Positive delta = liquidator receives bonus\n const data: LiquidateSimulation = {\n bonus0: tokenFlow.delta0 > 0n ? tokenFlow.delta0 : 0n,\n bonus1: tokenFlow.delta1 > 0n ? tokenFlow.delta1 : 0n,\n positionsClosed,\n isLiquidatable: true,\n shortfall0: 0n, // Would need additional calculation\n shortfall1: 0n,\n }\n\n return {\n success: true,\n data,\n gasEstimate: flowResult.gasEstimate,\n tokenFlow,\n _meta,\n }\n } catch (error) {\n const _meta = await metaPromise\n // If simulation fails, the account might not be liquidatable\n const errorMessage = error instanceof Error ? error.message : 'Simulation failed'\n const isNotLiquidatable =\n errorMessage.includes('NotMarginCalled') || errorMessage.includes('AccountInsolvent')\n\n if (isNotLiquidatable) {\n const data: LiquidateSimulation = {\n bonus0: 0n,\n bonus1: 0n,\n positionsClosed: [],\n isLiquidatable: false,\n shortfall0: 0n,\n shortfall1: 0n,\n }\n return {\n success: true,\n data,\n gasEstimate: 0n,\n tokenFlow: emptyTokenFlow,\n _meta,\n }\n }\n\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(errorMessage, error instanceof Error ? error : undefined),\n _meta,\n }\n }\n}\n","/**\n * Settle simulation for the Panoptic v2 SDK.\n * @module v2/simulations/simulateSettle\n */\n\nimport type { Address, Hex, PublicClient } from 'viem'\nimport { decodeFunctionResult, encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError } from '../errors'\nimport type { SettleSimulation, SimulationResult, TokenFlow } from '../types'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\n/** BIT_MASK_128 = (1n << 128n) - 1n */\nconst BIT_MASK_128 = (1n << 128n) - 1n\n\n/**\n * PanopticPool multicall ABI (inherited from Uniswap).\n */\nconst multicallAbi = [\n {\n type: 'function',\n name: 'multicall',\n inputs: [{ name: 'data', type: 'bytes[]' }],\n outputs: [{ name: 'results', type: 'bytes[]' }],\n stateMutability: 'nonpayable',\n },\n] as const\n\n/**\n * Parameters for simulating premium settlement.\n */\nexport interface SimulateSettleParams {\n /** Public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** Current position ID list */\n positionIdList: bigint[]\n /** Optional tokenId to compute forfeit amounts for */\n tokenId?: bigint\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate premium settlement.\n *\n * When `tokenId` is provided, the simulation also computes forfeit amounts\n * by chaining the dispatch with `getFullPositionsData` reads\n * in a single multicall.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with settlement data or error\n */\nexport async function simulateSettle(\n params: SimulateSettleParams,\n): Promise<SimulationResult<SettleSimulation>> {\n const { client, poolAddress, account, positionIdList, tokenId, blockNumber } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n try {\n // For settlement, we call dispatch with unchanged position lists\n const positionSizes = positionIdList.map(() => 0n)\n const tickAndSpreadLimits = positionIdList.map(() => [-887272n, 887272n, 0n] as const)\n\n // Encode dispatch call data\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n positionIdList,\n positionSizes.map((s) => BigInt(s) as unknown as bigint & { readonly __uint128: true }),\n tickAndSpreadLimits.map(\n (t) => [Number(t[0]), Number(t[1]), Number(t[2])] as readonly [number, number, number],\n ),\n false,\n 0n,\n ],\n })\n\n // Simulate with token flow measurement using PanopticPool.multicall + getAssetsOf\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account,\n callData,\n blockNumber: targetBlockNumber,\n })\n\n if (!flowResult.success || !flowResult.tokenFlow) {\n throw (\n flowResult.rawError ?? new PanopticError(flowResult.error || 'Token flow simulation failed')\n )\n }\n\n const tokenFlow: TokenFlow = flowResult.tokenFlow\n\n // Compute forfeit amounts if tokenId is provided\n let forfeitAmounts: [bigint, bigint] | undefined\n if (tokenId !== undefined) {\n forfeitAmounts = await computeForfeitAmounts({\n client,\n poolAddress,\n account,\n positionIdList,\n tokenId,\n dispatchCallData: callData,\n blockNumber: targetBlockNumber,\n })\n }\n\n const _meta = await metaPromise\n\n // Build simulation result with actual token flow data\n // Positive delta = premia received\n const data: SettleSimulation = {\n premiaReceived0: tokenFlow.delta0 > 0n ? tokenFlow.delta0 : 0n,\n premiaReceived1: tokenFlow.delta1 > 0n ? tokenFlow.delta1 : 0n,\n postCollateral0: tokenFlow.balanceAfter0,\n postCollateral1: tokenFlow.balanceAfter1,\n forfeitAmounts,\n }\n\n return {\n success: true,\n data,\n gasEstimate: flowResult.gasEstimate,\n tokenFlow,\n _meta,\n }\n } catch (error) {\n const _meta = await metaPromise\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Simulation failed',\n error instanceof Error ? error : undefined,\n ),\n _meta,\n }\n }\n}\n\n/**\n * Compute forfeit amounts by chaining dispatch + getFullPositionsData\n * in a single PanopticPool.multicall.\n */\nasync function computeForfeitAmounts(params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n positionIdList: bigint[]\n tokenId: bigint\n dispatchCallData: Hex\n blockNumber: bigint\n}): Promise<[bigint, bigint]> {\n const { client, poolAddress, account, tokenId, dispatchCallData, blockNumber } = params\n\n // Encode getFullPositionsData calls (available = false, total = true)\n const feesCallAvailable = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, [tokenId]],\n })\n const feesCallTotal = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, true, [tokenId]],\n })\n\n try {\n // Chain: dispatch (settle) + fees(available) + fees(total) in one multicall\n const { result } = await client.simulateContract({\n address: poolAddress,\n abi: multicallAbi,\n functionName: 'multicall',\n args: [[dispatchCallData, feesCallAvailable, feesCallTotal]],\n account,\n blockNumber,\n })\n\n // Decode the two fee reads (result[0] is dispatch, result[1] and result[2] are fees)\n const decodeFeesResult = (data: Hex): bigint => {\n return decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n data,\n })[0]\n }\n\n const availablePremium = decodeFeesResult(result[1])\n const totalPremium = decodeFeesResult(result[2])\n\n const available0 = availablePremium & BIT_MASK_128\n const available1 = availablePremium >> 128n\n const total0 = totalPremium & BIT_MASK_128\n const total1 = totalPremium >> 128n\n\n return [total0 - available0, total1 - available1]\n } catch (error) {\n throw new PanopticError(\n 'Forfeit amount computation failed',\n error instanceof Error ? error : undefined,\n )\n }\n}\n","/**\n * Vault simulation functions for the Panoptic v2 SDK.\n * @module v2/simulations/simulateVault\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { collateralTrackerV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError } from '../errors'\nimport type { DepositSimulation, SimulationResult, WithdrawSimulation } from '../types'\n\n/**\n * Parameters for simulating deposit.\n */\nexport interface SimulateDepositParams {\n /** Public client */\n client: PublicClient\n /** CollateralTracker address */\n collateralTrackerAddress: Address\n /** Account address */\n account: Address\n /** Assets to deposit */\n assets: bigint\n /** Whether the collateral tracker wraps native ETH (requires sending msg.value) */\n isNativeETH?: boolean\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate a deposit operation.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with deposit data or error\n */\nexport async function simulateDeposit(\n params: SimulateDepositParams,\n): Promise<SimulationResult<DepositSimulation>> {\n const { client, collateralTrackerAddress, account, assets, isNativeETH, blockNumber } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n try {\n // Run multicall (historical block), gas estimate (latest), and block meta in parallel\n const [[currentShares, currentAssets, previewedShares], gasEstimate, _meta] = await Promise.all(\n [\n client.multicall({\n contracts: [\n {\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'balanceOf',\n args: [account],\n },\n {\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n args: [account],\n },\n {\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'previewDeposit',\n args: [assets],\n },\n ],\n blockNumber: targetBlockNumber,\n allowFailure: false,\n }),\n client.estimateContractGas({\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'deposit',\n args: [assets, account],\n account,\n ...(isNativeETH && { value: assets }),\n blockNumber: targetBlockNumber,\n }),\n metaPromise,\n ],\n )\n\n const data: DepositSimulation = {\n sharesMinted: previewedShares,\n postAssets: currentAssets + assets,\n postShares: currentShares + previewedShares,\n }\n\n return {\n success: true,\n data,\n gasEstimate,\n _meta,\n }\n } catch (error) {\n const _meta = await metaPromise\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Simulation failed',\n error instanceof Error ? error : undefined,\n ),\n _meta,\n }\n }\n}\n\n/**\n * Parameters for simulating withdrawal.\n */\nexport interface SimulateWithdrawParams {\n /** Public client */\n client: PublicClient\n /** CollateralTracker address */\n collateralTrackerAddress: Address\n /** Account address */\n account: Address\n /** Assets to withdraw */\n assets: bigint\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate a withdrawal operation.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with withdrawal data or error\n */\nexport async function simulateWithdraw(\n params: SimulateWithdrawParams,\n): Promise<SimulationResult<WithdrawSimulation>> {\n const { client, collateralTrackerAddress, account, assets, blockNumber } = params\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n try {\n // Get current state\n const [currentShares, currentAssets, maxWithdrawable, previewedShares] = await client.multicall(\n {\n contracts: [\n {\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'balanceOf',\n args: [account],\n },\n {\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'assetsOf',\n args: [account],\n },\n {\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'maxWithdraw',\n args: [account],\n },\n {\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'previewWithdraw',\n args: [assets],\n },\n ],\n blockNumber: targetBlockNumber,\n allowFailure: false,\n },\n )\n\n // Check if withdrawal is possible\n const canWithdraw = assets <= maxWithdrawable\n\n const _meta = await metaPromise\n\n if (!canWithdraw) {\n const data: WithdrawSimulation = {\n sharesBurned: 0n,\n assetsReceived: 0n,\n postAssets: currentAssets,\n postShares: currentShares,\n canWithdraw: false,\n reason: `Requested ${assets}, but max withdrawable is ${maxWithdrawable}`,\n }\n\n return {\n success: true,\n data,\n gasEstimate: 0n,\n _meta,\n }\n }\n\n const gasEstimate = await client.estimateContractGas({\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'withdraw',\n args: [assets, account, account],\n account,\n blockNumber: targetBlockNumber,\n })\n\n const data: WithdrawSimulation = {\n sharesBurned: previewedShares,\n assetsReceived: assets,\n postAssets: currentAssets - assets,\n postShares: currentShares - previewedShares,\n canWithdraw: true,\n }\n\n return {\n success: true,\n data,\n gasEstimate,\n _meta,\n }\n } catch (error) {\n const _meta = await metaPromise\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Simulation failed',\n error instanceof Error ? error : undefined,\n ),\n _meta,\n }\n }\n}\n","/**\n * SFPM simulation functions for the Panoptic v2 SDK.\n *\n * These simulate `mintTokenizedPosition` and `burnTokenizedPosition` on the\n * SemiFungiblePositionManager, called with `account: poolAddress` (the pool\n * is the caller in the actual protocol flow).\n *\n * @module v2/simulations/sfpm\n */\n\nimport type { Address, Hex, PublicClient } from 'viem'\nimport { encodeAbiParameters } from 'viem'\n\nimport { semiFungiblePositionManagerV4Abi } from '../../../generated'\nimport type { PoolKey } from '../types'\n\n/**\n * Encode a V4 PoolKey struct as bytes for the SFPM.\n */\nexport function encodePoolKeyBytes(poolKey: PoolKey): Hex {\n return encodeAbiParameters(\n [\n {\n type: 'tuple',\n components: [\n { name: 'currency0', type: 'address' },\n { name: 'currency1', type: 'address' },\n { name: 'fee', type: 'uint24' },\n { name: 'tickSpacing', type: 'int24' },\n { name: 'hooks', type: 'address' },\n ],\n },\n ],\n [\n {\n currency0: poolKey.currency0,\n currency1: poolKey.currency1,\n fee: Number(poolKey.fee),\n tickSpacing: Number(poolKey.tickSpacing),\n hooks: poolKey.hooks,\n },\n ],\n )\n}\n\n/**\n * Encode a V3 pool address as poolKey bytes for the V3 SFPM.\n * V3 SFPM expects `abi.encode(uniswapV3PoolAddress)`.\n */\nexport function encodeV3PoolKeyBytes(v3PoolAddress: Address): Hex {\n return encodeAbiParameters([{ type: 'address' }], [v3PoolAddress])\n}\n\n/**\n * Parameters for simulating an SFPM mint or burn.\n */\nexport interface SimulateSFPMParams {\n /** Public client */\n client: PublicClient\n /** SemiFungiblePositionManager address */\n sfpmAddress: Address\n /** PanopticPool address (used as `account` — the pool is the caller) */\n poolAddress: Address\n /** Encoded pool key (bytes) */\n poolKey: Hex\n /** TokenId to mint/burn */\n tokenId: bigint\n /** Position size (uint128) */\n positionSize: bigint\n /** Lower tick limit */\n tickLimitLow: number\n /** Upper tick limit */\n tickLimitHigh: number\n}\n\n/** Return type from SFPM mintTokenizedPosition / burnTokenizedPosition */\nexport type SFPMSimulationResult = readonly [\n readonly [bigint, bigint, bigint, bigint],\n bigint,\n number,\n]\n\n/**\n * Simulate an SFPM mintTokenizedPosition call.\n *\n * @param params - Simulation parameters\n * @returns The result tuple: [collectedAmounts[4], totalSwapped, newTick]\n */\nexport async function simulateSFPMMint(params: SimulateSFPMParams): Promise<SFPMSimulationResult> {\n const {\n client,\n sfpmAddress,\n poolAddress,\n poolKey,\n tokenId,\n positionSize,\n tickLimitLow,\n tickLimitHigh,\n } = params\n\n const { result } = await client.simulateContract({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n functionName: 'mintTokenizedPosition',\n args: [\n poolKey,\n tokenId,\n BigInt(positionSize) as bigint & { readonly __uint128: true },\n tickLimitLow,\n tickLimitHigh,\n ],\n account: poolAddress,\n })\n\n return result\n}\n\n/**\n * Simulate an SFPM burnTokenizedPosition call.\n *\n * @param params - Simulation parameters\n * @returns The result tuple: [collectedAmounts[4], totalSwapped, newTick]\n */\nexport async function simulateSFPMBurn(params: SimulateSFPMParams): Promise<SFPMSimulationResult> {\n const {\n client,\n sfpmAddress,\n poolAddress,\n poolKey,\n tokenId,\n positionSize,\n tickLimitLow,\n tickLimitHigh,\n } = params\n\n const { result } = await client.simulateContract({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n functionName: 'burnTokenizedPosition',\n args: [\n poolKey,\n tokenId,\n BigInt(positionSize) as bigint & { readonly __uint128: true },\n tickLimitLow,\n tickLimitHigh,\n ],\n account: poolAddress,\n })\n\n return result\n}\n","/**\n * Swap simulation for the Panoptic v2 SDK.\n * @module v2/simulations/simulateSwap\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError, SwapTokenMismatchError } from '../errors'\nimport { tickLimits } from '../formatters/tick'\nimport { getPool } from '../reads/pool'\nimport { createTokenIdBuilder } from '../tokenId/builder'\nimport type { SimulationResult, TokenFlow } from '../types'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\n/**\n * Swap simulation data.\n */\nexport interface SwapSimulation {\n /** Amount of tokenIn spent (positive) */\n amountIn: bigint\n /** Amount of tokenOut received (positive) */\n amountOut: bigint\n /** Raw token flow from the simulation */\n tokenFlow: TokenFlow\n}\n\n/**\n * Parameters for simulateSwapExactOut.\n */\nexport interface SimulateSwapExactOutParams {\n /** Public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** Chain ID */\n chainId: bigint\n /** Token address to receive */\n tokenOut: Address\n /** Exact amount of tokenOut */\n amountOut: bigint\n /** Slippage tolerance in bps */\n slippageBps: bigint\n /** Existing position IDs */\n existingPositionIds: bigint[]\n /** Optional block number */\n blockNumber?: bigint\n}\n\n/**\n * Parameters for simulateSwapExactIn.\n */\nexport interface SimulateSwapExactInParams {\n /** Public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Account address */\n account: Address\n /** Chain ID */\n chainId: bigint\n /** Token address to sell */\n tokenIn: Address\n /** Exact amount of tokenIn */\n amountIn: bigint\n /** Slippage tolerance in bps */\n slippageBps: bigint\n /** Existing position IDs */\n existingPositionIds: bigint[]\n /** Optional block number */\n blockNumber?: bigint\n}\n\n/**\n * Resolve token index, throwing SwapTokenMismatchError on mismatch.\n */\nfunction resolveTokenIndex(tokenAddress: Address, token0: Address, token1: Address): bigint {\n const lower = tokenAddress.toLowerCase()\n if (lower === token0.toLowerCase()) return 0n\n if (lower === token1.toLowerCase()) return 1n\n throw new SwapTokenMismatchError(tokenAddress, token0, token1)\n}\n\n/**\n * Build a unique loan tokenId.\n */\nfunction buildUniqueLoan(\n poolId: bigint,\n asset: bigint,\n tokenType: bigint,\n currentTick: bigint,\n tickSpacing: bigint,\n existingPositionIds: bigint[],\n): bigint {\n const mod = currentTick % tickSpacing\n let strike = currentTick - ((mod + tickSpacing) % tickSpacing)\n const step = tickSpacing\n const existingSet = new Set(existingPositionIds)\n\n for (let attempt = 0; attempt < 1000; attempt++) {\n const tokenId = createTokenIdBuilder(poolId).addLoan({ asset, tokenType, strike }).build()\n\n if (!existingSet.has(tokenId)) {\n return tokenId\n }\n strike += step\n }\n\n throw new PanopticError('Could not build unique loan tokenId after 1000 attempts')\n}\n\n/**\n * Build dispatch calldata for swap simulation.\n */\nfunction buildSwapCallData(\n loanTokenId: bigint,\n existingPositionIds: bigint[],\n amount: bigint,\n mintTickLimits: readonly [number, number, number],\n burnTickLimits: readonly [number, number, number],\n): `0x${string}` {\n return encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n [loanTokenId, loanTokenId],\n [...existingPositionIds],\n [amount, 0n],\n [mintTickLimits, burnTickLimits],\n false,\n 0n,\n ],\n })\n}\n\n/**\n * Build SwapSimulation from token flow, given which token index is \"out\".\n */\nfunction buildSwapResult(tokenFlow: TokenFlow, tokenOutIndex: bigint): SwapSimulation {\n // delta is negative when user deposits, positive when user receives\n // For a swap: one delta should be negative (spent) and one positive (received)\n const delta0 = tokenFlow.delta0\n const delta1 = tokenFlow.delta1\n\n if (tokenOutIndex === 0n) {\n return {\n amountOut: delta0 > 0n ? delta0 : -delta0,\n amountIn: delta1 < 0n ? -delta1 : delta1,\n tokenFlow,\n }\n } else {\n return {\n amountOut: delta1 > 0n ? delta1 : -delta1,\n amountIn: delta0 < 0n ? -delta0 : delta0,\n tokenFlow,\n }\n }\n}\n\n/**\n * Simulate an exact-output swap.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with swap data or error\n */\nexport async function simulateSwapExactOut(\n params: SimulateSwapExactOutParams,\n): Promise<SimulationResult<SwapSimulation>> {\n const {\n client,\n poolAddress,\n account,\n chainId,\n tokenOut,\n amountOut,\n slippageBps,\n existingPositionIds,\n blockNumber,\n } = params\n\n try {\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n const pool = await getPool({ client, poolAddress, chainId, blockNumber: targetBlockNumber })\n const token0 = pool.collateralTracker0.token\n const token1 = pool.collateralTracker1.token\n const tokenOutIndex = resolveTokenIndex(tokenOut, token0, token1)\n const tokenType = tokenOutIndex === 0n ? 1n : 0n\n\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n\n const loanTokenId = buildUniqueLoan(\n pool.poolId,\n tokenOutIndex,\n tokenType,\n pool.currentTick,\n pool.tickSpacing,\n existingPositionIds,\n )\n\n // Mint: swapAtMint=true (descending), Burn: swapAtMint=false (ascending)\n const mintTickLimits: readonly [number, number, number] = [\n Number(tickLimitHigh),\n Number(tickLimitLow),\n 0,\n ]\n const burnTickLimits: readonly [number, number, number] = [\n Number(tickLimitLow),\n Number(tickLimitHigh),\n 0,\n ]\n\n const callData = buildSwapCallData(\n loanTokenId,\n existingPositionIds,\n amountOut,\n mintTickLimits,\n burnTickLimits,\n )\n\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account,\n callData,\n blockNumber: targetBlockNumber,\n })\n\n if (!flowResult.success || !flowResult.tokenFlow) {\n throw flowResult.rawError ?? new PanopticError(flowResult.error || 'Swap simulation failed')\n }\n\n const _meta = await metaPromise\n const data = buildSwapResult(flowResult.tokenFlow, tokenOutIndex)\n\n return {\n success: true,\n data,\n gasEstimate: flowResult.gasEstimate,\n tokenFlow: flowResult.tokenFlow,\n _meta,\n }\n } catch (error) {\n // Build a fallback _meta if getBlockMeta also failed\n const fallbackMeta = { blockNumber: 0n, blockTimestamp: 0n, blockHash: '0x0' as `0x${string}` }\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Simulation failed',\n error instanceof Error ? error : undefined,\n ),\n _meta: fallbackMeta,\n }\n }\n}\n\n/**\n * Simulate an exact-input swap.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with swap data or error\n */\nexport async function simulateSwapExactIn(\n params: SimulateSwapExactInParams,\n): Promise<SimulationResult<SwapSimulation>> {\n const {\n client,\n poolAddress,\n account,\n chainId,\n tokenIn,\n amountIn,\n slippageBps,\n existingPositionIds,\n blockNumber,\n } = params\n\n try {\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n const pool = await getPool({ client, poolAddress, chainId, blockNumber: targetBlockNumber })\n const token0 = pool.collateralTracker0.token\n const token1 = pool.collateralTracker1.token\n const tokenInIndex = resolveTokenIndex(tokenIn, token0, token1)\n const tokenType = tokenInIndex\n\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n\n const loanTokenId = buildUniqueLoan(\n pool.poolId,\n tokenInIndex,\n tokenType,\n pool.currentTick,\n pool.tickSpacing,\n existingPositionIds,\n )\n\n // Mint: swapAtMint=false (ascending), Burn: swapAtMint=true (descending)\n const mintTickLimits: readonly [number, number, number] = [\n Number(tickLimitLow),\n Number(tickLimitHigh),\n 0,\n ]\n const burnTickLimits: readonly [number, number, number] = [\n Number(tickLimitHigh),\n Number(tickLimitLow),\n 0,\n ]\n\n // tokenOut is the OTHER token\n const tokenOutIndex = tokenInIndex === 0n ? 1n : 0n\n\n const callData = buildSwapCallData(\n loanTokenId,\n existingPositionIds,\n amountIn,\n mintTickLimits,\n burnTickLimits,\n )\n\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account,\n callData,\n blockNumber: targetBlockNumber,\n })\n\n if (!flowResult.success || !flowResult.tokenFlow) {\n throw flowResult.rawError ?? new PanopticError(flowResult.error || 'Swap simulation failed')\n }\n\n const _meta = await metaPromise\n const data = buildSwapResult(flowResult.tokenFlow, tokenOutIndex)\n\n return {\n success: true,\n data,\n gasEstimate: flowResult.gasEstimate,\n tokenFlow: flowResult.tokenFlow,\n _meta,\n }\n } catch (error) {\n const fallbackMeta = { blockNumber: 0n, blockTimestamp: 0n, blockHash: '0x0' as `0x${string}` }\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Simulation failed',\n error instanceof Error ? error : undefined,\n ),\n _meta: fallbackMeta,\n }\n }\n}\n","/**\n * TanStack Query v5 simulation hooks for the Panoptic v2 SDK.\n * @module v2/react/hooks/simulations\n */\n\nimport { useQuery } from '@tanstack/react-query'\nimport type { Address } from 'viem'\n\nimport {\n type SimulateBatchDispatchParams,\n type SimulateClosePositionParams,\n type SimulateDepositParams,\n type SimulateDispatchParams,\n type SimulateForceExerciseParams,\n type SimulateLiquidateParams,\n type SimulateOpenPositionParams,\n type SimulateSettleParams,\n type SimulateSFPMParams,\n type SimulateSwapExactInParams,\n type SimulateSwapExactOutParams,\n type SimulateWithdrawParams,\n simulateBatchDispatch,\n simulateClosePosition,\n simulateDeposit,\n simulateDispatch,\n simulateForceExercise,\n simulateLiquidate,\n simulateOpenPosition,\n simulateSettle,\n simulateSFPMBurn,\n simulateSFPMMint,\n simulateSwapExactIn,\n simulateSwapExactOut,\n simulateWithdraw,\n} from '../../simulations'\nimport { getClientCacheScopeKey } from '../cacheScopes'\nimport { usePanopticContext } from '../provider'\nimport { queryKeys } from '../queryKeys'\n\ntype OmitClient<T> = Omit<T, 'client'>\ntype OmitClientAndPool<T> = Omit<T, 'client' | 'poolAddress'>\n\nexport function useSimulateOpenPosition(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateOpenPositionParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'openPosition',\n poolAddress,\n params?.tokenId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateOpenPosition({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateClosePosition(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateClosePositionParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'closePosition',\n poolAddress,\n params?.tokenId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateClosePosition({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateDeposit(params?: OmitClient<SimulateDepositParams>) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'deposit',\n params?.collateralTrackerAddress,\n params?.assets?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateDeposit({ client: publicClient, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateWithdraw(params?: OmitClient<SimulateWithdrawParams>) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'withdraw',\n params?.collateralTrackerAddress,\n params?.assets?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateWithdraw({ client: publicClient, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateLiquidate(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateLiquidateParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'liquidate',\n poolAddress,\n params?.liquidatee,\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateLiquidate({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateForceExercise(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateForceExerciseParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'forceExercise',\n poolAddress,\n params?.user,\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateForceExercise({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateSettle(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateSettleParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'settle',\n poolAddress,\n params?.account,\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateSettle({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateBatchDispatch(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateBatchDispatchParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'batchDispatch',\n poolAddress,\n params?.account,\n params?.items?.length,\n JSON.stringify(params?.items?.map((i) => `${i.kind}:${i.tokenId.toString()}`)),\n JSON.stringify(params?.existingPositionIds?.map(String)),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateBatchDispatch({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined && params.items !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateDispatch(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateDispatchParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'dispatch',\n poolAddress,\n JSON.stringify(params?.positionIdList?.map(String)),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateDispatch({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateSFPMMint(params?: OmitClient<SimulateSFPMParams>) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'sfpmMint',\n params?.sfpmAddress,\n params?.tokenId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new Error('params required for simulateSFPMMint')\n return simulateSFPMMint({ client: publicClient, ...params })\n },\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateSFPMBurn(params?: OmitClient<SimulateSFPMParams>) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'sfpmBurn',\n params?.sfpmAddress,\n params?.tokenId?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => {\n if (!params) throw new Error('params required for simulateSFPMBurn')\n return simulateSFPMBurn({ client: publicClient, ...params })\n },\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateSwapExactOut(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateSwapExactOutParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'swapExactOut',\n poolAddress,\n params?.tokenOut,\n params?.amountOut?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateSwapExactOut({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\nexport function useSimulateSwapExactIn(\n poolAddress: Address,\n params?: OmitClientAndPool<SimulateSwapExactInParams>,\n) {\n const { publicClient, clientScope } = usePanopticContext()\n return useQuery({\n queryKey: [\n ...queryKeys.all,\n 'sim',\n 'swapExactIn',\n poolAddress,\n params?.tokenIn,\n params?.amountIn?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n params,\n ] as const,\n queryFn: () => simulateSwapExactIn({ client: publicClient, poolAddress, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n","/**\n * TanStack Query v5 hooks for the Uniswap v4 Universal Router swap path.\n *\n * Mirrors the writes/simulations hook ergonomics (usePanopticContext injection,\n * OmitInjected* params, cache invalidation) but targets the generic Uniswap v4\n * router functions in `src/uniswap`.\n *\n * @module v2/react/hooks/uniswapRouter\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { Address, WalletClient } from 'viem'\n\nimport {\n type ApproveErc20ForPermit2Params,\n type ApproveRouterViaPermit2Params,\n type CheckRouterApprovalParams,\n type QuoteSwapExactInViaRouterParams,\n type QuoteSwapExactOutViaRouterParams,\n type SwapExactInViaRouterParams,\n type SwapExactOutViaRouterParams,\n approveErc20ForPermit2,\n approveRouterViaPermit2,\n checkRouterApproval,\n quoteSwapExactInViaRouter,\n quoteSwapExactOutViaRouter,\n swapExactInViaRouter,\n swapExactOutViaRouter,\n} from '../../../../uniswap/v4/router'\nimport { PanopticError } from '../../errors'\nimport { getClientCacheScopeKey } from '../cacheScopes'\nimport { mutationEffects } from '../mutationEffects'\nimport { usePanopticContext } from '../provider'\nimport { queryKeys } from '../queryKeys'\n\ntype OmitInjectedWithPoolAndChain<T> = Omit<\n T,\n 'client' | 'walletClient' | 'account' | 'poolAddress' | 'chainId'\n>\ntype OmitInjectedWithChain<T> = Omit<T, 'client' | 'walletClient' | 'account' | 'chainId'>\ntype OmitClientPoolAndChain<T> = Omit<T, 'client' | 'poolAddress' | 'chainId'>\n\nfunction requireWallet(walletClient?: WalletClient, account?: Address) {\n if (!walletClient || !account) {\n throw new PanopticError(\n 'walletClient and account are required. Provide them via PanopticProvider.',\n )\n }\n return { walletClient, account }\n}\n\n/**\n * Quote an exact-in spot swap via the Universal Router (V4Quoter-backed).\n * Returns a `SimulationResult`, matching `useSimulateSwapExactIn`'s shape.\n */\nexport function useQuoteSwapExactInViaRouter(\n poolAddress: Address,\n params?: OmitClientPoolAndChain<QuoteSwapExactInViaRouterParams>,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // Raw `params` carries bigints that break TanStack v5's JSON key hashing; the\n // stringified scalars below fully capture the query identity.\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'uniswapRouter',\n 'quote',\n chainId,\n poolAddress,\n params?.tokenIn,\n params?.amountIn?.toString(),\n params?.slippageBps?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n ] as const,\n queryFn: () =>\n quoteSwapExactInViaRouter({\n client: publicClient,\n poolAddress,\n chainId,\n ...params!,\n }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\n/**\n * Quote an exact-out spot swap via the Universal Router (V4Quoter-backed).\n * Returns a `SimulationResult` carrying the required input + `amountInMaximum`.\n */\nexport function useQuoteSwapExactOutViaRouter(\n poolAddress: Address,\n params?: OmitClientPoolAndChain<QuoteSwapExactOutViaRouterParams>,\n) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // Raw `params` carries bigints that break TanStack v5's JSON key hashing; the\n // stringified scalars below fully capture the query identity.\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'uniswapRouter',\n 'quoteExactOut',\n chainId,\n poolAddress,\n params?.tokenIn,\n params?.amountOut?.toString(),\n params?.slippageBps?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n ] as const,\n queryFn: () =>\n quoteSwapExactOutViaRouter({\n client: publicClient,\n poolAddress,\n chainId,\n ...params!,\n }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\n/**\n * Check the ERC20 → Permit2 → Universal Router allowance chain.\n */\nexport function useCheckRouterApproval(params?: OmitInjectedWithChain<CheckRouterApprovalParams>) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // Raw `params` carries bigints that break TanStack v5's JSON key hashing; the\n // stringified scalars below fully capture the query identity.\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'uniswapRouter',\n 'approval',\n chainId,\n params?.tokenIn,\n params?.owner,\n params?.amount?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n ] as const,\n queryFn: () => checkRouterApproval({ client: publicClient, chainId, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\n/**\n * Execute an exact-in spot swap via the Universal Router.\n */\nexport function useSwapExactInViaRouter(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: (params: OmitInjectedWithPoolAndChain<SwapExactInViaRouterParams>) => {\n const wallet = requireWallet(walletClient, account)\n return swapExactInViaRouter({\n client: publicClient,\n ...wallet,\n poolAddress,\n chainId,\n ...params,\n })\n },\n onSuccess: () => {\n if (!account) return\n for (const key of mutationEffects.deposit({ chainId, poolAddress, account })) {\n queryClient.invalidateQueries({ queryKey: key })\n }\n },\n })\n}\n\n/**\n * Execute an exact-out spot swap via the Universal Router.\n */\nexport function useSwapExactOutViaRouter(poolAddress: Address) {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: (params: OmitInjectedWithPoolAndChain<SwapExactOutViaRouterParams>) => {\n const wallet = requireWallet(walletClient, account)\n return swapExactOutViaRouter({\n client: publicClient,\n ...wallet,\n poolAddress,\n chainId,\n ...params,\n })\n },\n onSuccess: () => {\n if (!account) return\n for (const key of mutationEffects.deposit({ chainId, poolAddress, account })) {\n queryClient.invalidateQueries({ queryKey: key })\n }\n },\n })\n}\n\n/**\n * Step 1 approval mutation: ERC20 → Permit2.\n */\nexport function useApproveErc20ForPermit2() {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n return useMutation({\n mutationFn: (params: OmitInjectedWithChain<ApproveErc20ForPermit2Params>) => {\n const wallet = requireWallet(walletClient, account)\n return approveErc20ForPermit2({ client: publicClient, ...wallet, chainId, ...params })\n },\n })\n}\n\n/**\n * Step 2 approval mutation: Permit2 → Universal Router.\n */\nexport function useApproveRouterViaPermit2() {\n const { publicClient, chainId, walletClient, account } = usePanopticContext()\n return useMutation({\n mutationFn: (params: OmitInjectedWithChain<ApproveRouterViaPermit2Params>) => {\n const wallet = requireWallet(walletClient, account)\n return approveRouterViaPermit2({ client: publicClient, ...wallet, chainId, ...params })\n },\n })\n}\n","/**\n * TanStack Query v5 hooks for the CoW Protocol swap path.\n *\n * Mirrors the Universal Router hooks (usePanopticContext injection,\n * OmitInjected* params) but targets the order-book functions in `src/cow`.\n * Orders settle asynchronously: submission returns an order UID, and\n * `useCowOrderStatus` polls until the order reaches a terminal state.\n *\n * @module v2/react/hooks/cowSwap\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { Address, Hex, WalletClient } from 'viem'\n\nimport {\n type ApproveErc20ForCowParams,\n type CancelCowOrderParams,\n type CheckCowApprovalParams,\n type QuoteCowSwapParams,\n type SignAndSubmitCowOrderParams,\n approveErc20ForCow,\n cancelCowOrder,\n checkCowApproval,\n getCowOrderStatus,\n isCowSupportedChain,\n quoteCowSwap,\n signAndSubmitCowOrder,\n} from '../../../../cow'\nimport { PanopticError } from '../../errors'\nimport { getClientCacheScopeKey } from '../cacheScopes'\nimport { usePanopticContext } from '../provider'\nimport { queryKeys } from '../queryKeys'\n\ntype OmitChainAndFrom<T> = Omit<T, 'chainId' | 'from'>\ntype OmitInjectedWithChain<T> = Omit<T, 'client' | 'walletClient' | 'account' | 'chainId'>\ntype OmitClientOnly<T> = Omit<T, 'client'>\n\nfunction requireWallet(walletClient?: WalletClient, account?: Address) {\n if (!walletClient || !account) {\n throw new PanopticError(\n 'walletClient and account are required. Provide them via PanopticProvider.',\n )\n }\n return { walletClient, account }\n}\n\n/** How often open-order status is re-polled (ms). */\nconst ORDER_POLL_INTERVAL_MS = 5_000\n/** How often quotes refresh (ms) — CoW quotes go stale quickly. */\nconst QUOTE_REFETCH_INTERVAL_MS = 15_000\n\n/**\n * Placeholder order owner for quotes when no wallet is connected — the order\n * book accepts any non-zero `from` for quoting (verification happens at order\n * submission, which always uses the real account).\n */\nconst QUOTE_STUB_FROM = '0x0000000000000000000000000000000000000001' as const\n\n/**\n * Quote a swap via the CoW order book. The connected account (or a stub when\n * disconnected) is used as the order owner (`from`); disabled while the chain\n * has no order book.\n */\nexport function useQuoteCowSwap(params?: OmitChainAndFrom<QuoteCowSwapParams>) {\n const { publicClient, chainId, account, clientScope } = usePanopticContext()\n return useQuery({\n // Raw `params` carries bigints that break TanStack v5's JSON key hashing; the\n // stringified scalars below fully capture the query identity.\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'cowSwap',\n 'quote',\n chainId,\n params?.sellToken,\n params?.buyToken,\n params?.kind,\n params?.amount?.toString(),\n params?.slippageBps?.toString(),\n account,\n getClientCacheScopeKey(publicClient, clientScope),\n ] as const,\n queryFn: () => quoteCowSwap({ chainId, from: account ?? QUOTE_STUB_FROM, ...params! }),\n enabled: params !== undefined && isCowSupportedChain(chainId),\n staleTime: 0,\n refetchInterval: QUOTE_REFETCH_INTERVAL_MS,\n })\n}\n\n/** Check the ERC20 → GPv2VaultRelayer allowance for the sell token. */\nexport function useCheckCowApproval(params?: OmitClientOnly<CheckCowApprovalParams>) {\n const { publicClient, chainId, clientScope } = usePanopticContext()\n return useQuery({\n // Raw `params` carries bigints that break TanStack v5's JSON key hashing; the\n // stringified scalars below fully capture the query identity.\n // eslint-disable-next-line @tanstack/query/exhaustive-deps\n queryKey: [\n ...queryKeys.all,\n 'cowSwap',\n 'approval',\n chainId,\n params?.sellToken,\n params?.owner,\n params?.amount?.toString(),\n getClientCacheScopeKey(publicClient, clientScope),\n ] as const,\n queryFn: () => checkCowApproval({ client: publicClient, ...params! }),\n enabled: params !== undefined,\n staleTime: 0,\n })\n}\n\n/** Approval mutation: ERC20 → GPv2VaultRelayer (single step, no Permit2). */\nexport function useApproveErc20ForCow() {\n const { publicClient, walletClient, account } = usePanopticContext()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (params: OmitInjectedWithChain<ApproveErc20ForCowParams>) => {\n const wallet = requireWallet(walletClient, account)\n return approveErc20ForCow({ client: publicClient, ...wallet, ...params })\n },\n // Refresh the cached allowance read (useCheckCowApproval) so the swap CTA\n // advances past \"Approve\" once the approval confirms.\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [...queryKeys.all, 'cowSwap', 'approval'] })\n },\n })\n}\n\n/**\n * Sign an order (EIP-712) and post it to the order book. Resolves with the\n * order UID — not a tx hash; settlement is asynchronous.\n */\nexport function useSubmitCowOrder() {\n const { chainId, walletClient, account } = usePanopticContext()\n return useMutation({\n mutationFn: (\n params: Omit<SignAndSubmitCowOrderParams, 'walletClient' | 'account' | 'chainId'>,\n ) => {\n const wallet = requireWallet(walletClient, account)\n return signAndSubmitCowOrder({ ...wallet, chainId, ...params })\n },\n })\n}\n\n/**\n * Poll an order's lifecycle state every few seconds while it is open; polling\n * stops automatically once the order reaches a terminal state.\n */\nexport function useCowOrderStatus(orderUid?: Hex) {\n const { chainId } = usePanopticContext()\n return useQuery({\n queryKey: [...queryKeys.all, 'cowSwap', 'orderStatus', chainId, orderUid] as const,\n queryFn: () => getCowOrderStatus({ chainId, orderUid: orderUid! }),\n enabled: orderUid !== undefined,\n refetchInterval: (query) => {\n const status = query.state.data?.status\n return status === undefined || status === 'open' || status === 'presignaturePending'\n ? ORDER_POLL_INTERVAL_MS\n : false\n },\n })\n}\n\n/** Off-chain (signed, free) order cancellation mutation. */\nexport function useCancelCowOrder() {\n const { chainId, walletClient, account } = usePanopticContext()\n return useMutation({\n mutationFn: (params: Omit<CancelCowOrderParams, 'walletClient' | 'account' | 'chainId'>) => {\n const wallet = requireWallet(walletClient, account)\n return cancelCowOrder({ ...wallet, chainId, ...params })\n },\n })\n}\n\n// Re-export the chain gate so UI code can branch without importing `/cow`.\nexport { isCowSupportedChain }\n","/**\n * TanStack Query v5 sync hooks for the Panoptic v2 SDK.\n * @module v2/react/hooks/sync\n */\n\nimport { useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useState } from 'react'\nimport type { Address, Hash } from 'viem'\n\nimport {\n type PendingPosition,\n type SyncProgressEvent,\n addPendingPosition,\n clearTrackedPositions,\n confirmPendingPosition,\n failPendingPosition,\n syncPositions,\n} from '../../sync'\nimport { usePanopticContext, useRequireStorage } from '../provider'\nimport { queryKeys } from '../queryKeys'\n\n/**\n * Hook for syncing positions with progress tracking.\n */\nexport function useSyncPositions(poolAddress: Address) {\n const { publicClient, chainId } = usePanopticContext()\n const storage = useRequireStorage()\n const account = usePanopticContext().account\n const queryClient = useQueryClient()\n const [progress, setProgress] = useState<SyncProgressEvent | null>(null)\n\n const mutation = useMutation({\n mutationFn: async (params?: { fromBlock?: bigint; toBlock?: bigint }) => {\n if (!account) throw new Error('account is required for sync')\n const result = await syncPositions({\n client: publicClient,\n chainId,\n poolAddress,\n account,\n storage,\n fromBlock: params?.fromBlock,\n toBlock: params?.toBlock,\n onUpdate: setProgress,\n })\n return result\n },\n onSuccess: () => {\n if (!account) return\n queryClient.invalidateQueries({\n queryKey: queryKeys.trackedPositionIds(chainId, poolAddress, account),\n })\n queryClient.invalidateQueries({\n queryKey: queryKeys.syncStatus(chainId, poolAddress, account),\n })\n queryClient.invalidateQueries({\n queryKey: queryKeys.positions(chainId, poolAddress, account),\n })\n queryClient.invalidateQueries({\n queryKey: queryKeys.closedPositions(chainId, poolAddress, account),\n })\n queryClient.invalidateQueries({\n queryKey: queryKeys.tradeHistory(chainId, poolAddress, account),\n })\n },\n })\n\n return { ...mutation, progress }\n}\n\n/**\n * Hook for adding a pending position (optimistic update).\n */\nexport function useAddPendingPosition(poolAddress: Address) {\n const { chainId } = usePanopticContext()\n const storage = useRequireStorage()\n const account = usePanopticContext().account\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: (position: PendingPosition) => {\n if (!account) throw new Error('account is required')\n return addPendingPosition({ chainId, poolAddress, account, storage, position })\n },\n onSuccess: () => {\n if (!account) return\n queryClient.invalidateQueries({\n queryKey: queryKeys.trackedPositionIds(chainId, poolAddress, account),\n })\n },\n })\n}\n\n/**\n * Hook for confirming a pending position.\n */\nexport function useConfirmPendingPosition(poolAddress: Address) {\n const { chainId } = usePanopticContext()\n const storage = useRequireStorage()\n const account = usePanopticContext().account\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: (tokenId: bigint) => {\n if (!account) throw new Error('account is required')\n return confirmPendingPosition({ chainId, poolAddress, account, storage, tokenId })\n },\n onSuccess: () => {\n if (!account) return\n queryClient.invalidateQueries({\n queryKey: queryKeys.trackedPositionIds(chainId, poolAddress, account),\n })\n queryClient.invalidateQueries({\n queryKey: queryKeys.positions(chainId, poolAddress, account),\n })\n },\n })\n}\n\n/**\n * Hook for marking a pending position as failed.\n */\nexport function useFailPendingPosition(poolAddress: Address) {\n const { chainId } = usePanopticContext()\n const storage = useRequireStorage()\n const account = usePanopticContext().account\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: (txHash: Hash) => {\n if (!account) throw new Error('account is required')\n return failPendingPosition({ chainId, poolAddress, account, storage, txHash })\n },\n onSuccess: () => {\n if (!account) return\n queryClient.invalidateQueries({\n queryKey: queryKeys.trackedPositionIds(chainId, poolAddress, account),\n })\n },\n })\n}\n\n/**\n * Hook for clearing all tracked positions.\n */\nexport function useClearTrackedPositions(poolAddress: Address) {\n const { chainId } = usePanopticContext()\n const storage = useRequireStorage()\n const account = usePanopticContext().account\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: () => {\n if (!account) throw new Error('account is required')\n return clearTrackedPositions({ chainId, poolAddress, account, storage })\n },\n onSuccess: () => {\n if (!account) return\n queryClient.invalidateQueries({\n queryKey: queryKeys.trackedPositionIds(chainId, poolAddress, account),\n })\n queryClient.invalidateQueries({\n queryKey: queryKeys.positions(chainId, poolAddress, account),\n })\n },\n })\n}\n","/**\n * Uniswap v4 PoolManager event ABI (subset for event watching).\n * @module abis/poolManager\n */\n\nexport const poolManagerAbi = [\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'id', internalType: 'PoolId', type: 'bytes32', indexed: true },\n { name: 'sender', internalType: 'address', type: 'address', indexed: true },\n { name: 'tickLower', internalType: 'int24', type: 'int24', indexed: false },\n { name: 'tickUpper', internalType: 'int24', type: 'int24', indexed: false },\n { name: 'liquidityDelta', internalType: 'int256', type: 'int256', indexed: false },\n { name: 'salt', internalType: 'bytes32', type: 'bytes32', indexed: false },\n ],\n name: 'ModifyLiquidity',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'id', internalType: 'PoolId', type: 'bytes32', indexed: true },\n { name: 'sender', internalType: 'address', type: 'address', indexed: true },\n { name: 'amount0', internalType: 'int128', type: 'int128', indexed: false },\n { name: 'amount1', internalType: 'int128', type: 'int128', indexed: false },\n { name: 'sqrtPriceX96', internalType: 'uint160', type: 'uint160', indexed: false },\n { name: 'liquidity', internalType: 'uint128', type: 'uint128', indexed: false },\n { name: 'tick', internalType: 'int24', type: 'int24', indexed: false },\n { name: 'fee', internalType: 'uint24', type: 'uint24', indexed: false },\n ],\n name: 'Swap',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'id', internalType: 'PoolId', type: 'bytes32', indexed: true },\n { name: 'sender', internalType: 'address', type: 'address', indexed: true },\n { name: 'amount0', internalType: 'uint256', type: 'uint256', indexed: false },\n { name: 'amount1', internalType: 'uint256', type: 'uint256', indexed: false },\n ],\n name: 'Donate',\n },\n] as const\n","/**\n * Simple WebSocket event watching for the Panoptic v2 SDK.\n * @module v2/events/watchEvents\n */\n\nimport type { Address, Hash, Log, PublicClient } from 'viem'\n\nimport {\n collateralTrackerV2Abi,\n panopticPoolV2Abi,\n riskEngineAbi,\n semiFungiblePositionManagerV4Abi,\n} from '../../../generated'\nimport { poolManagerAbi } from '../abis/poolManager'\nimport type { PanopticEvent, PanopticEventType } from '../types'\nimport { decodeLeftRightSigned, decodePositionBalance } from '../writes/utils'\n\n/**\n * A decoded contract event log that includes both base Log fields and typed args.\n * viem's getContractEvents/watchContractEvent return logs with `.args`,\n * but the generic `Log` type doesn't include it. We use `unknown` for args\n * and narrow to specific types in each parse function's switch cases.\n */\ntype DecodedLog = Log & { args: unknown }\n\n/**\n * Parameters for watching events.\n */\nexport interface WatchEventsParams {\n /** Public client (must have WebSocket transport for real-time watching) */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** CollateralTracker0 address (optional, for Deposit/Withdraw/ProtocolLossRealized events) */\n collateralTracker0?: Address\n /** CollateralTracker1 address (optional, for Deposit/Withdraw/ProtocolLossRealized events) */\n collateralTracker1?: Address\n /** RiskEngine address (optional, for BorrowRateUpdated events) */\n riskEngineAddress?: Address\n /** SemiFungiblePositionManager address (optional, for LiquidityChunkUpdated events) */\n sfpmAddress?: Address\n /** v4 PoolManager address (optional, for ModifyLiquidity/Swap/Donate events) */\n poolManagerAddress?: Address\n /** Event types to filter (omit for all events) */\n eventTypes?: PanopticEventType[]\n /** Callback for received events */\n onLogs: (events: PanopticEvent[]) => void\n /** Callback for errors */\n onError?: (error: Error) => void\n}\n\n/**\n * Event name to ABI event mapping for PanopticPool.\n */\nconst POOL_EVENT_NAMES: Record<string, PanopticEventType> = {\n OptionMinted: 'OptionMinted',\n OptionBurnt: 'OptionBurnt',\n AccountLiquidated: 'AccountLiquidated',\n ForcedExercised: 'ForcedExercised',\n PremiumSettled: 'PremiumSettled',\n}\n\n/**\n * Event name to ABI event mapping for CollateralTracker.\n */\nconst COLLATERAL_EVENT_NAMES: Record<string, PanopticEventType> = {\n Deposit: 'Deposit',\n Withdraw: 'Withdraw',\n ProtocolLossRealized: 'ProtocolLossRealized',\n}\n\n/**\n * Event name to ABI event mapping for RiskEngine.\n */\nconst RISK_ENGINE_EVENT_NAMES: Record<string, PanopticEventType> = {\n BorrowRateUpdated: 'BorrowRateUpdated',\n}\n\n/**\n * Event name to ABI event mapping for SFPM.\n */\nconst SFPM_EVENT_NAMES: Record<string, PanopticEventType> = {\n LiquidityChunkUpdated: 'LiquidityChunkUpdated',\n}\n\n/**\n * Event name to ABI event mapping for v4 PoolManager.\n */\nconst POOL_MANAGER_EVENT_NAMES: Record<string, PanopticEventType> = {\n ModifyLiquidity: 'ModifyLiquidity',\n Swap: 'Swap',\n Donate: 'Donate',\n}\n\n/**\n * Parse a decoded log into a typed PanopticEvent.\n */\nfunction parsePoolLog(log: DecodedLog, eventName: string): PanopticEvent | null {\n const baseEvent = {\n transactionHash: log.transactionHash!,\n blockNumber: log.blockNumber!,\n blockHash: log.blockHash!,\n logIndex: BigInt(log.logIndex!),\n }\n\n // Type narrowing based on event name\n switch (eventName) {\n case 'OptionMinted': {\n const args = log.args as { recipient: Address; tokenId: bigint; balanceData: bigint }\n const balanceData = decodePositionBalance(args.balanceData)\n return {\n type: 'OptionMinted',\n ...baseEvent,\n recipient: args.recipient,\n tokenId: args.tokenId,\n positionSize: balanceData.positionSize,\n poolUtilization0: balanceData.poolUtilization0,\n poolUtilization1: balanceData.poolUtilization1,\n tickAtMint: balanceData.tickAtMint,\n timestampAtMint: balanceData.timestampAtMint,\n blockAtMint: balanceData.blockAtMint,\n swapAtMint: balanceData.swapAtMint,\n }\n }\n\n case 'OptionBurnt': {\n const args = log.args as {\n recipient: Address\n positionSize: bigint\n tokenId: bigint\n premiaByLeg: readonly [bigint, bigint, bigint, bigint]\n }\n return {\n type: 'OptionBurnt',\n ...baseEvent,\n recipient: args.recipient,\n tokenId: args.tokenId,\n positionSize: args.positionSize,\n premiaByLeg: args.premiaByLeg,\n }\n }\n\n case 'AccountLiquidated': {\n const args = log.args as { liquidator: Address; liquidatee: Address; bonusAmounts: bigint }\n const bonus = decodeLeftRightSigned(args.bonusAmounts)\n return {\n type: 'AccountLiquidated',\n ...baseEvent,\n liquidator: args.liquidator,\n liquidatee: args.liquidatee,\n bonusAmount0: bonus.right,\n bonusAmount1: bonus.left,\n }\n }\n\n case 'ForcedExercised': {\n const args = log.args as {\n exercisor: Address\n user: Address\n tokenId: bigint\n exerciseFee: bigint\n }\n const fee = decodeLeftRightSigned(args.exerciseFee)\n return {\n type: 'ForcedExercised',\n ...baseEvent,\n exercisor: args.exercisor,\n user: args.user,\n tokenId: args.tokenId,\n exerciseFee0: fee.right,\n exerciseFee1: fee.left,\n }\n }\n\n case 'PremiumSettled': {\n const args = log.args as {\n user: Address\n tokenId: bigint\n legIndex: bigint\n settledAmounts: bigint\n }\n const settled = decodeLeftRightSigned(args.settledAmounts)\n return {\n type: 'PremiumSettled',\n ...baseEvent,\n user: args.user,\n tokenId: args.tokenId,\n legIndex: args.legIndex,\n settledAmount0: settled.right,\n settledAmount1: settled.left,\n }\n }\n\n default:\n return null\n }\n}\n\n/**\n * Parse a CollateralTracker log into a typed PanopticEvent.\n */\nfunction parseCollateralLog(log: DecodedLog, eventName: string): PanopticEvent | null {\n const baseEvent = {\n transactionHash: log.transactionHash!,\n blockNumber: log.blockNumber!,\n blockHash: log.blockHash!,\n logIndex: BigInt(log.logIndex!),\n }\n\n switch (eventName) {\n case 'Deposit': {\n const args = log.args as { sender: Address; owner: Address; assets: bigint; shares: bigint }\n return {\n type: 'Deposit',\n ...baseEvent,\n sender: args.sender,\n owner: args.owner,\n assets: args.assets,\n shares: args.shares,\n }\n }\n\n case 'Withdraw': {\n const args = log.args as {\n sender: Address\n receiver: Address\n owner: Address\n assets: bigint\n shares: bigint\n }\n return {\n type: 'Withdraw',\n ...baseEvent,\n sender: args.sender,\n receiver: args.receiver,\n owner: args.owner,\n assets: args.assets,\n shares: args.shares,\n }\n }\n\n case 'ProtocolLossRealized': {\n const args = log.args as {\n liquidatee: Address\n liquidator: Address\n protocolLossAssets: bigint\n protocolLossShares: bigint\n }\n return {\n type: 'ProtocolLossRealized',\n ...baseEvent,\n liquidatee: args.liquidatee,\n liquidator: args.liquidator,\n protocolLossAssets: args.protocolLossAssets,\n protocolLossShares: args.protocolLossShares,\n }\n }\n\n default:\n return null\n }\n}\n\n/**\n * Parse a RiskEngine log into a typed PanopticEvent.\n */\nfunction parseRiskEngineLog(log: DecodedLog, eventName: string): PanopticEvent | null {\n const baseEvent = {\n transactionHash: log.transactionHash!,\n blockNumber: log.blockNumber!,\n blockHash: log.blockHash!,\n logIndex: BigInt(log.logIndex!),\n }\n\n switch (eventName) {\n case 'BorrowRateUpdated': {\n const args = log.args as {\n collateralToken: Address\n avgBorrowRate: bigint\n rateAtTarget: bigint\n }\n return {\n type: 'BorrowRateUpdated',\n ...baseEvent,\n collateralToken: args.collateralToken,\n avgBorrowRate: args.avgBorrowRate,\n rateAtTarget: args.rateAtTarget,\n }\n }\n\n default:\n return null\n }\n}\n\n/**\n * Parse an SFPM log into a typed PanopticEvent.\n */\nfunction parseSfpmLog(log: DecodedLog, eventName: string): PanopticEvent | null {\n const baseEvent = {\n transactionHash: log.transactionHash!,\n blockNumber: log.blockNumber!,\n blockHash: log.blockHash!,\n logIndex: BigInt(log.logIndex!),\n }\n\n switch (eventName) {\n case 'LiquidityChunkUpdated': {\n const args = log.args as {\n poolId: Hash\n owner: Address\n tokenType: bigint\n tickLower: number\n tickUpper: number\n liquidityDelta: bigint\n }\n return {\n type: 'LiquidityChunkUpdated',\n ...baseEvent,\n poolId: args.poolId,\n owner: args.owner,\n tokenType: args.tokenType,\n tickLower: args.tickLower,\n tickUpper: args.tickUpper,\n liquidityDelta: args.liquidityDelta,\n }\n }\n\n default:\n return null\n }\n}\n\n/**\n * Parse a v4 PoolManager log into a typed PanopticEvent.\n */\nfunction parsePoolManagerLog(log: DecodedLog, eventName: string): PanopticEvent | null {\n const baseEvent = {\n transactionHash: log.transactionHash!,\n blockNumber: log.blockNumber!,\n blockHash: log.blockHash!,\n logIndex: BigInt(log.logIndex!),\n }\n\n switch (eventName) {\n case 'ModifyLiquidity': {\n const args = log.args as {\n id: Hash\n sender: Address\n tickLower: number\n tickUpper: number\n liquidityDelta: bigint\n salt: Hash\n }\n return {\n type: 'ModifyLiquidity',\n ...baseEvent,\n id: args.id,\n sender: args.sender,\n tickLower: args.tickLower,\n tickUpper: args.tickUpper,\n liquidityDelta: args.liquidityDelta,\n salt: args.salt,\n }\n }\n\n case 'Swap': {\n const args = log.args as {\n id: Hash\n sender: Address\n amount0: bigint\n amount1: bigint\n sqrtPriceX96: bigint\n liquidity: bigint\n tick: number\n fee: number\n }\n return {\n type: 'Swap',\n ...baseEvent,\n id: args.id,\n sender: args.sender,\n amount0: args.amount0,\n amount1: args.amount1,\n sqrtPriceX96: args.sqrtPriceX96,\n liquidity: args.liquidity,\n tick: args.tick,\n fee: args.fee,\n }\n }\n\n case 'Donate': {\n const args = log.args as { id: Hash; sender: Address; amount0: bigint; amount1: bigint }\n return {\n type: 'Donate',\n ...baseEvent,\n id: args.id,\n sender: args.sender,\n amount0: args.amount0,\n amount1: args.amount1,\n }\n }\n\n default:\n return null\n }\n}\n\n/**\n * Watch for Panoptic events in real-time using WebSocket.\n *\n * This is a one-shot watcher - if the WebSocket disconnects, it stops.\n * For production bots that need automatic reconnection, use `createEventSubscription()`.\n *\n * @param params - Watch parameters\n * @returns Unwatch function to stop watching\n *\n * @example\n * ```typescript\n * const unwatch = watchEvents({\n * client,\n * poolAddress,\n * eventTypes: ['OptionMinted', 'OptionBurnt'],\n * onLogs: (events) => {\n * for (const event of events) {\n * console.log(event.type, event)\n * }\n * },\n * onError: (error) => console.error(error),\n * })\n *\n * // Later: stop watching\n * unwatch()\n * ```\n */\nexport function watchEvents(params: WatchEventsParams): () => void {\n const {\n client,\n poolAddress,\n collateralTracker0,\n collateralTracker1,\n riskEngineAddress,\n sfpmAddress,\n poolManagerAddress,\n eventTypes,\n onLogs,\n onError,\n } = params\n\n const unwatchFns: (() => void)[] = []\n\n // Determine which pool events to watch\n const poolEventTypesToWatch = eventTypes\n ? eventTypes.filter((t) => t in POOL_EVENT_NAMES)\n : (Object.keys(POOL_EVENT_NAMES) as PanopticEventType[])\n\n // Watch PanopticPool events\n for (const eventType of poolEventTypesToWatch) {\n try {\n const unwatch = client.watchContractEvent({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n eventName: eventType as\n | 'OptionMinted'\n | 'OptionBurnt'\n | 'AccountLiquidated'\n | 'ForcedExercised'\n | 'PremiumSettled',\n onLogs: (logs) => {\n const events: PanopticEvent[] = []\n for (const log of logs) {\n const parsed = parsePoolLog(log as DecodedLog, eventType)\n if (parsed) {\n events.push(parsed)\n }\n }\n if (events.length > 0) {\n onLogs(events)\n }\n },\n onError: onError,\n })\n unwatchFns.push(unwatch)\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(String(error)))\n }\n }\n\n // Determine which collateral events to watch\n const collateralEventTypesToWatch = eventTypes\n ? eventTypes.filter((t) => t in COLLATERAL_EVENT_NAMES)\n : (Object.keys(COLLATERAL_EVENT_NAMES) as PanopticEventType[])\n\n // Watch CollateralTracker events (if addresses provided)\n const collateralTrackers = [collateralTracker0, collateralTracker1].filter(Boolean) as Address[]\n\n for (const trackerAddress of collateralTrackers) {\n for (const eventType of collateralEventTypesToWatch) {\n try {\n const unwatch = client.watchContractEvent({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n eventName: eventType as 'Deposit' | 'Withdraw' | 'ProtocolLossRealized',\n onLogs: (logs) => {\n const events: PanopticEvent[] = []\n for (const log of logs) {\n const parsed = parseCollateralLog(log as DecodedLog, eventType)\n if (parsed) {\n events.push(parsed)\n }\n }\n if (events.length > 0) {\n onLogs(events)\n }\n },\n onError: onError,\n })\n unwatchFns.push(unwatch)\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(String(error)))\n }\n }\n }\n\n // Watch RiskEngine events (if address provided)\n if (riskEngineAddress) {\n const riskEngineEventTypesToWatch = eventTypes\n ? eventTypes.filter((t) => t in RISK_ENGINE_EVENT_NAMES)\n : (Object.keys(RISK_ENGINE_EVENT_NAMES) as PanopticEventType[])\n\n for (const eventType of riskEngineEventTypesToWatch) {\n try {\n const unwatch = client.watchContractEvent({\n address: riskEngineAddress,\n abi: riskEngineAbi,\n eventName: eventType as 'BorrowRateUpdated',\n onLogs: (logs) => {\n const events: PanopticEvent[] = []\n for (const log of logs) {\n const parsed = parseRiskEngineLog(log as DecodedLog, eventType)\n if (parsed) {\n events.push(parsed)\n }\n }\n if (events.length > 0) {\n onLogs(events)\n }\n },\n onError: onError,\n })\n unwatchFns.push(unwatch)\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(String(error)))\n }\n }\n }\n\n // Watch SFPM events (if address provided)\n if (sfpmAddress) {\n const sfpmEventTypesToWatch = eventTypes\n ? eventTypes.filter((t) => t in SFPM_EVENT_NAMES)\n : (Object.keys(SFPM_EVENT_NAMES) as PanopticEventType[])\n\n for (const eventType of sfpmEventTypesToWatch) {\n try {\n const unwatch = client.watchContractEvent({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n eventName: eventType as 'LiquidityChunkUpdated',\n onLogs: (logs) => {\n const events: PanopticEvent[] = []\n for (const log of logs) {\n const parsed = parseSfpmLog(log as DecodedLog, eventType)\n if (parsed) {\n events.push(parsed)\n }\n }\n if (events.length > 0) {\n onLogs(events)\n }\n },\n onError: onError,\n })\n unwatchFns.push(unwatch)\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(String(error)))\n }\n }\n }\n\n // Watch PoolManager events (if address provided)\n if (poolManagerAddress) {\n const poolManagerEventTypesToWatch = eventTypes\n ? eventTypes.filter((t) => t in POOL_MANAGER_EVENT_NAMES)\n : (Object.keys(POOL_MANAGER_EVENT_NAMES) as PanopticEventType[])\n\n for (const eventType of poolManagerEventTypesToWatch) {\n try {\n const unwatch = client.watchContractEvent({\n address: poolManagerAddress,\n abi: poolManagerAbi,\n eventName: eventType as 'ModifyLiquidity' | 'Swap' | 'Donate',\n onLogs: (logs) => {\n const events: PanopticEvent[] = []\n for (const log of logs) {\n const parsed = parsePoolManagerLog(log as DecodedLog, eventType)\n if (parsed) {\n events.push(parsed)\n }\n }\n if (events.length > 0) {\n onLogs(events)\n }\n },\n onError: onError,\n })\n unwatchFns.push(unwatch)\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(String(error)))\n }\n }\n }\n\n // Return combined unwatch function\n return () => {\n for (const unwatch of unwatchFns) {\n unwatch()\n }\n }\n}\n\nexport type { DecodedLog }\nexport { parseCollateralLog, parsePoolLog, parsePoolManagerLog, parseRiskEngineLog, parseSfpmLog }\n","/**\n * Resilient event subscription with auto-reconnect for the Panoptic v2 SDK.\n * @module v2/events/subscription\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport {\n collateralTrackerV2Abi,\n panopticPoolV2Abi,\n riskEngineAbi,\n semiFungiblePositionManagerV4Abi,\n} from '../../../generated'\nimport { poolManagerAbi } from '../abis/poolManager'\nimport type { EventSubscription, PanopticEvent, PanopticEventType } from '../types'\nimport type { DecodedLog } from './watchEvents'\nimport {\n parseCollateralLog,\n parsePoolLog,\n parsePoolManagerLog,\n parseRiskEngineLog,\n parseSfpmLog,\n} from './watchEvents'\n\n/**\n * Reconnection strategy configuration.\n */\nexport interface ReconnectConfig {\n /** Maximum reconnection attempts (0n = infinite) */\n maxAttempts: bigint\n /** Initial delay before first retry (ms) */\n initialDelayMs: bigint\n /** Maximum delay between retries (ms) */\n maxDelayMs: bigint\n /** Backoff multiplier */\n backoffMultiplier: bigint\n}\n\n/**\n * Default reconnection configuration.\n */\nexport const DEFAULT_RECONNECT_CONFIG: ReconnectConfig = {\n maxAttempts: 10n,\n initialDelayMs: 1000n,\n maxDelayMs: 30000n,\n backoffMultiplier: 2n,\n}\n\n/**\n * Parameters for creating an event subscription.\n */\nexport interface CreateEventSubscriptionParams {\n /** Public client (must have WebSocket transport) */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** CollateralTracker0 address (optional, for Deposit/Withdraw events) */\n collateralTracker0?: Address\n /** CollateralTracker1 address (optional, for Deposit/Withdraw/ProtocolLossRealized events) */\n collateralTracker1?: Address\n /** RiskEngine address (optional, for BorrowRateUpdated events) */\n riskEngineAddress?: Address\n /** SemiFungiblePositionManager address (optional, for LiquidityChunkUpdated events) */\n sfpmAddress?: Address\n /** v4 PoolManager address (optional, for ModifyLiquidity/Swap/Donate events) */\n poolManagerAddress?: Address\n /** Event types to filter (omit for all events) */\n eventTypes?: PanopticEventType[]\n /** Callback for received events */\n onLogs: (events: PanopticEvent[]) => void\n /** Callback for errors (subscription will auto-reconnect) */\n onError?: (error: Error) => void\n /** Callback for reconnection attempts */\n onReconnect?: (attempt: bigint, nextDelayMs: bigint) => void\n /** Callback when connected */\n onConnected?: () => void\n /** Reconnection strategy configuration */\n reconnect?: Partial<ReconnectConfig>\n}\n\n/**\n * Event subscription handle with additional state.\n */\nexport interface EventSubscriptionHandle extends EventSubscription {\n /** Start watching */\n start: () => void\n /** Stop watching (cleans up, no more reconnects) */\n stop: () => void\n /** Number of reconnection attempts */\n reconnectAttempts: bigint\n /** Last processed block number */\n lastProcessedBlock: bigint\n}\n\n/**\n * Create a resilient event subscription with auto-reconnect and gap filling.\n *\n * Unlike `watchEvents()`, this subscription automatically reconnects on\n * disconnection and fills gaps by fetching missed events.\n *\n * @param params - Subscription parameters\n * @returns Event subscription handle\n *\n * @example\n * ```typescript\n * const subscription = createEventSubscription({\n * client,\n * poolAddress,\n * eventTypes: ['OptionMinted', 'OptionBurnt', 'AccountLiquidated'],\n * onLogs: (events) => {\n * for (const event of events) {\n * console.log(event.type, event)\n * }\n * },\n * onError: (error) => console.error('Subscription error:', error),\n * onReconnect: (attempt, nextDelay) => {\n * console.log(`Reconnecting (attempt ${attempt}, next in ${nextDelay}ms)`)\n * },\n * onConnected: () => console.log('Subscription connected'),\n * })\n *\n * // Start watching\n * subscription.start()\n *\n * // Check state\n * console.log('Connected:', subscription.isConnected())\n * console.log('Reconnect attempts:', subscription.reconnectAttempts)\n * console.log('Last processed block:', subscription.lastProcessedBlock)\n *\n * // Stop (cleans up, no more reconnects)\n * subscription.stop()\n * ```\n */\nexport function createEventSubscription(\n params: CreateEventSubscriptionParams,\n): EventSubscriptionHandle {\n const {\n client,\n poolAddress,\n collateralTracker0,\n collateralTracker1,\n riskEngineAddress,\n sfpmAddress,\n poolManagerAddress,\n eventTypes,\n onLogs,\n onError,\n onReconnect,\n onConnected,\n reconnect: reconnectConfig,\n } = params\n\n const config: ReconnectConfig = {\n ...DEFAULT_RECONNECT_CONFIG,\n ...reconnectConfig,\n }\n\n // State\n let isRunning = false\n let connected = false\n let reconnectAttempts = 0n\n let lastProcessedBlock = 0n\n let lastProcessedLogIndex = -1n\n let currentDelay = config.initialDelayMs\n let unwatchFns: (() => void)[] = []\n let reconnectTimeout: ReturnType<typeof setTimeout> | null = null\n\n const compareEvents = (a: PanopticEvent, b: PanopticEvent): number => {\n if (a.blockNumber !== b.blockNumber) {\n return a.blockNumber < b.blockNumber ? -1 : 1\n }\n if (a.logIndex !== b.logIndex) {\n return a.logIndex < b.logIndex ? -1 : 1\n }\n return 0\n }\n\n const isAfterCursor = (event: PanopticEvent): boolean => {\n if (event.blockNumber > lastProcessedBlock) {\n return true\n }\n if (event.blockNumber < lastProcessedBlock) {\n return false\n }\n return event.logIndex > lastProcessedLogIndex\n }\n\n const advanceCursor = (event: PanopticEvent): void => {\n lastProcessedBlock = event.blockNumber\n lastProcessedLogIndex = event.logIndex\n }\n\n // Pool event types\n const poolEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) =>\n [\n 'OptionMinted',\n 'OptionBurnt',\n 'AccountLiquidated',\n 'ForcedExercised',\n 'PremiumSettled',\n ].includes(t),\n )\n : ['OptionMinted', 'OptionBurnt', 'AccountLiquidated', 'ForcedExercised', 'PremiumSettled']\n\n // Collateral event types\n const collateralEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['Deposit', 'Withdraw', 'ProtocolLossRealized'].includes(t))\n : ['Deposit', 'Withdraw', 'ProtocolLossRealized']\n\n // RiskEngine event types\n const riskEngineEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['BorrowRateUpdated'].includes(t))\n : ['BorrowRateUpdated']\n\n // SFPM event types\n const sfpmEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['LiquidityChunkUpdated'].includes(t))\n : ['LiquidityChunkUpdated']\n\n // PoolManager event types\n const poolManagerEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['ModifyLiquidity', 'Swap', 'Donate'].includes(t))\n : ['ModifyLiquidity', 'Swap', 'Donate']\n\n /**\n * Fetch missed events between lastProcessedBlock and currentBlock.\n */\n async function fillGap(fromBlock: bigint, toBlock: bigint): Promise<void> {\n if (fromBlock >= toBlock) return\n\n const allEvents: PanopticEvent[] = []\n\n // Fetch pool events\n for (const eventType of poolEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n eventName: eventType as\n | 'OptionMinted'\n | 'OptionBurnt'\n | 'AccountLiquidated'\n | 'ForcedExercised'\n | 'PremiumSettled',\n fromBlock,\n toBlock,\n })\n for (const log of logs) {\n const parsed = parsePoolLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`))\n }\n }\n\n // Fetch collateral events\n const collateralTrackers = [collateralTracker0, collateralTracker1].filter(Boolean) as Address[]\n for (const trackerAddress of collateralTrackers) {\n for (const eventType of collateralEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n eventName: eventType as 'Deposit' | 'Withdraw' | 'ProtocolLossRealized',\n fromBlock,\n toBlock,\n })\n for (const log of logs) {\n const parsed = parseCollateralLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Fetch RiskEngine events\n if (riskEngineAddress) {\n for (const eventType of riskEngineEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: riskEngineAddress,\n abi: riskEngineAbi,\n eventName: eventType as 'BorrowRateUpdated',\n fromBlock,\n toBlock,\n })\n for (const log of logs) {\n const parsed = parseRiskEngineLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Fetch SFPM events\n if (sfpmAddress) {\n for (const eventType of sfpmEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n eventName: eventType as 'LiquidityChunkUpdated',\n fromBlock,\n toBlock,\n })\n for (const log of logs) {\n const parsed = parseSfpmLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Fetch PoolManager events\n if (poolManagerAddress) {\n for (const eventType of poolManagerEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: poolManagerAddress,\n abi: poolManagerAbi,\n eventName: eventType as 'ModifyLiquidity' | 'Swap' | 'Donate',\n fromBlock,\n toBlock,\n })\n for (const log of logs) {\n const parsed = parsePoolManagerLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Sort by block number and log index, then drop anything at/before cursor.\n const newEvents = allEvents.sort(compareEvents).filter(isAfterCursor)\n\n if (newEvents.length > 0) {\n onLogs(newEvents)\n advanceCursor(newEvents[newEvents.length - 1])\n }\n }\n\n /**\n * Start watching events.\n */\n async function setupWatchers(): Promise<void> {\n // Clean up any existing watchers\n cleanup()\n\n try {\n // Get current block for gap detection\n const currentBlock = await client.getBlockNumber()\n\n // Fill gap if we have a previous position\n if (lastProcessedBlock > 0n && lastProcessedBlock < currentBlock) {\n await fillGap(lastProcessedBlock, currentBlock)\n }\n\n // Set baseline for this subscription start (from \"head\"), unless fillGap\n // already advanced us into this block with a concrete log index.\n if (currentBlock > lastProcessedBlock) {\n lastProcessedBlock = currentBlock\n lastProcessedLogIndex = -1n\n }\n\n const createOnLogsHandler = (\n parseLog: (log: DecodedLog) => PanopticEvent | null,\n ): ((logs: readonly unknown[]) => void) => {\n return (logs) => {\n const events: PanopticEvent[] = []\n for (const log of logs) {\n const parsed = parseLog(log as DecodedLog)\n if (parsed && isAfterCursor(parsed)) {\n events.push(parsed)\n }\n }\n if (events.length > 0) {\n events.sort(compareEvents)\n onLogs(events)\n advanceCursor(events[events.length - 1])\n }\n }\n }\n\n const createPoolOnLogs = (eventType: PanopticEventType) =>\n createOnLogsHandler((log) => parsePoolLog(log, eventType))\n const createCollateralOnLogs = (eventType: PanopticEventType) =>\n createOnLogsHandler((log) => parseCollateralLog(log, eventType))\n const createRiskEngineOnLogs = (eventType: PanopticEventType) =>\n createOnLogsHandler((log) => parseRiskEngineLog(log, eventType))\n const createSfpmOnLogs = (eventType: PanopticEventType) =>\n createOnLogsHandler((log) => parseSfpmLog(log, eventType))\n const createPoolManagerOnLogs = (eventType: PanopticEventType) =>\n createOnLogsHandler((log) => parsePoolManagerLog(log, eventType))\n\n // Watch pool events\n for (const eventType of poolEventTypes) {\n const unwatch = client.watchContractEvent({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n eventName: eventType as\n | 'OptionMinted'\n | 'OptionBurnt'\n | 'AccountLiquidated'\n | 'ForcedExercised'\n | 'PremiumSettled',\n onLogs: createPoolOnLogs(eventType),\n onError: handleError,\n })\n unwatchFns.push(unwatch)\n }\n\n // Watch collateral events\n const collateralTrackers = [collateralTracker0, collateralTracker1].filter(\n Boolean,\n ) as Address[]\n for (const trackerAddress of collateralTrackers) {\n for (const eventType of collateralEventTypes) {\n const unwatch = client.watchContractEvent({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n eventName: eventType as 'Deposit' | 'Withdraw' | 'ProtocolLossRealized',\n onLogs: createCollateralOnLogs(eventType),\n onError: handleError,\n })\n unwatchFns.push(unwatch)\n }\n }\n\n // Watch RiskEngine events\n if (riskEngineAddress) {\n for (const eventType of riskEngineEventTypes) {\n const unwatch = client.watchContractEvent({\n address: riskEngineAddress,\n abi: riskEngineAbi,\n eventName: eventType as 'BorrowRateUpdated',\n onLogs: createRiskEngineOnLogs(eventType),\n onError: handleError,\n })\n unwatchFns.push(unwatch)\n }\n }\n\n // Watch SFPM events\n if (sfpmAddress) {\n for (const eventType of sfpmEventTypes) {\n const unwatch = client.watchContractEvent({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n eventName: eventType as 'LiquidityChunkUpdated',\n onLogs: createSfpmOnLogs(eventType),\n onError: handleError,\n })\n unwatchFns.push(unwatch)\n }\n }\n\n // Watch PoolManager events\n if (poolManagerAddress) {\n for (const eventType of poolManagerEventTypes) {\n const unwatch = client.watchContractEvent({\n address: poolManagerAddress,\n abi: poolManagerAbi,\n eventName: eventType as 'ModifyLiquidity' | 'Swap' | 'Donate',\n onLogs: createPoolManagerOnLogs(eventType),\n onError: handleError,\n })\n unwatchFns.push(unwatch)\n }\n }\n\n // Mark as connected\n connected = true\n reconnectAttempts = 0n\n currentDelay = config.initialDelayMs\n onConnected?.()\n } catch (error) {\n handleError(error instanceof Error ? error : new Error(String(error)))\n }\n }\n\n /**\n * Clean up watchers.\n */\n function cleanup(): void {\n for (const unwatch of unwatchFns) {\n try {\n unwatch()\n } catch {\n // Ignore cleanup errors\n }\n }\n unwatchFns = []\n connected = false\n }\n\n /**\n * Handle errors and schedule reconnection.\n */\n function handleError(error: Error): void {\n connected = false\n onError?.(error)\n\n if (!isRunning) return\n\n // Reconnect already scheduled; avoid duplicate timers.\n if (reconnectTimeout) return\n\n // Check if we've exceeded max attempts\n if (config.maxAttempts > 0n && reconnectAttempts >= config.maxAttempts) {\n onError?.(new Error(`Max reconnection attempts (${config.maxAttempts}) exceeded`))\n return\n }\n\n // Schedule reconnection\n reconnectAttempts++\n onReconnect?.(reconnectAttempts, currentDelay)\n\n reconnectTimeout = setTimeout(() => {\n reconnectTimeout = null\n if (isRunning) {\n setupWatchers()\n }\n }, Number(currentDelay))\n\n // Increase delay for next attempt (exponential backoff)\n currentDelay = currentDelay * config.backoffMultiplier\n if (currentDelay > config.maxDelayMs) {\n currentDelay = config.maxDelayMs\n }\n }\n\n /**\n * Start the subscription.\n */\n function start(): void {\n if (isRunning) return\n isRunning = true\n setupWatchers()\n }\n\n /**\n * Stop the subscription.\n */\n function stop(): void {\n isRunning = false\n if (reconnectTimeout) {\n clearTimeout(reconnectTimeout)\n }\n reconnectTimeout = null\n cleanup()\n }\n\n return {\n start,\n stop,\n unsubscribe: stop,\n isConnected: () => connected,\n get reconnectAttempts() {\n return reconnectAttempts\n },\n get lastProcessedBlock() {\n return lastProcessedBlock\n },\n }\n}\n","/**\n * HTTP polling-based event fetching for the Panoptic v2 SDK.\n * @module v2/events/poller\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport {\n collateralTrackerV2Abi,\n panopticPoolV2Abi,\n riskEngineAbi,\n semiFungiblePositionManagerV4Abi,\n} from '../../../generated'\nimport { poolManagerAbi } from '../abis/poolManager'\nimport type { PanopticEvent, PanopticEventType } from '../types'\nimport type { DecodedLog } from './watchEvents'\nimport {\n parseCollateralLog,\n parsePoolLog,\n parsePoolManagerLog,\n parseRiskEngineLog,\n parseSfpmLog,\n} from './watchEvents'\n\n/**\n * Event poller handle.\n */\nexport interface EventPoller {\n /** Start polling */\n start: () => void\n /** Stop polling */\n stop: () => void\n /** Check if polling is active */\n isPolling: () => boolean\n /** Get last polled block */\n lastPolledBlock: bigint\n}\n\n/**\n * Parameters for creating an event poller.\n */\nexport interface CreateEventPollerParams {\n /** Public client (works with HTTP transport) */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** CollateralTracker0 address (optional, for Deposit/Withdraw events) */\n collateralTracker0?: Address\n /** CollateralTracker1 address (optional, for Deposit/Withdraw/ProtocolLossRealized events) */\n collateralTracker1?: Address\n /** RiskEngine address (optional, for BorrowRateUpdated events) */\n riskEngineAddress?: Address\n /** SemiFungiblePositionManager address (optional, for LiquidityChunkUpdated events) */\n sfpmAddress?: Address\n /** v4 PoolManager address (optional, for ModifyLiquidity/Swap/Donate events) */\n poolManagerAddress?: Address\n /** Event types to filter (omit for all events) */\n eventTypes?: PanopticEventType[]\n /** Callback for received events */\n onLogs: (events: PanopticEvent[]) => void\n /** Callback for errors */\n onError?: (error: Error) => void\n /** Polling interval in milliseconds (default: 12000 = 1 block on mainnet) */\n intervalMs?: bigint\n /** Maximum blocks to query per poll (default: 1000) */\n maxBlockRange?: bigint\n /** Starting block number (default: current block) */\n fromBlock?: bigint\n}\n\n/**\n * Default polling interval (12 seconds = ~1 mainnet block).\n */\nconst DEFAULT_INTERVAL_MS = 12000n\n\n/**\n * Default maximum block range per poll.\n */\nconst DEFAULT_MAX_BLOCK_RANGE = 1000n\n\n/**\n * Create an HTTP polling-based event fetcher.\n *\n * Use this for environments where WebSocket connections are unreliable or unavailable.\n * It polls `eth_getLogs` at regular intervals to fetch new events.\n *\n * @param params - Poller parameters\n * @returns Event poller handle\n *\n * @example\n * ```typescript\n * const poller = createEventPoller({\n * client,\n * poolAddress,\n * onLogs: (events) => {\n * for (const event of events) {\n * console.log(event.type, event)\n * }\n * },\n * onError: (error) => console.error('Polling error:', error),\n * intervalMs: 12000n, // 12 seconds\n * maxBlockRange: 1000n,\n * })\n *\n * // Start polling\n * poller.start()\n *\n * // Check state\n * console.log('Polling:', poller.isPolling())\n * console.log('Last polled block:', poller.lastPolledBlock)\n *\n * // Stop polling\n * poller.stop()\n * ```\n */\nexport function createEventPoller(params: CreateEventPollerParams): EventPoller {\n const {\n client,\n poolAddress,\n collateralTracker0,\n collateralTracker1,\n riskEngineAddress,\n sfpmAddress,\n poolManagerAddress,\n eventTypes,\n onLogs,\n onError,\n intervalMs = DEFAULT_INTERVAL_MS,\n maxBlockRange = DEFAULT_MAX_BLOCK_RANGE,\n fromBlock,\n } = params\n\n // State\n let isRunning = false\n let lastPolledBlock = fromBlock ?? 0n\n let pollTimeout: ReturnType<typeof setTimeout> | null = null\n\n // Pool event types\n const poolEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) =>\n [\n 'OptionMinted',\n 'OptionBurnt',\n 'AccountLiquidated',\n 'ForcedExercised',\n 'PremiumSettled',\n ].includes(t),\n )\n : ['OptionMinted', 'OptionBurnt', 'AccountLiquidated', 'ForcedExercised', 'PremiumSettled']\n\n // Collateral event types\n const collateralEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['Deposit', 'Withdraw', 'ProtocolLossRealized'].includes(t))\n : ['Deposit', 'Withdraw', 'ProtocolLossRealized']\n\n // RiskEngine event types\n const riskEngineEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['BorrowRateUpdated'].includes(t))\n : ['BorrowRateUpdated']\n\n // SFPM event types\n const sfpmEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['LiquidityChunkUpdated'].includes(t))\n : ['LiquidityChunkUpdated']\n\n // PoolManager event types\n const poolManagerEventTypes: PanopticEventType[] = eventTypes\n ? eventTypes.filter((t) => ['ModifyLiquidity', 'Swap', 'Donate'].includes(t))\n : ['ModifyLiquidity', 'Swap', 'Donate']\n\n /**\n * Fetch events for a block range.\n */\n async function fetchEvents(from: bigint, to: bigint): Promise<PanopticEvent[]> {\n const allEvents: PanopticEvent[] = []\n\n // Fetch pool events\n for (const eventType of poolEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n eventName: eventType as\n | 'OptionMinted'\n | 'OptionBurnt'\n | 'AccountLiquidated'\n | 'ForcedExercised'\n | 'PremiumSettled',\n fromBlock: from,\n toBlock: to,\n })\n for (const log of logs) {\n const parsed = parsePoolLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`))\n }\n }\n\n // Fetch collateral events\n const collateralTrackers = [collateralTracker0, collateralTracker1].filter(Boolean) as Address[]\n for (const trackerAddress of collateralTrackers) {\n for (const eventType of collateralEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: trackerAddress,\n abi: collateralTrackerV2Abi,\n eventName: eventType as 'Deposit' | 'Withdraw' | 'ProtocolLossRealized',\n fromBlock: from,\n toBlock: to,\n })\n for (const log of logs) {\n const parsed = parseCollateralLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Fetch RiskEngine events\n if (riskEngineAddress) {\n for (const eventType of riskEngineEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: riskEngineAddress,\n abi: riskEngineAbi,\n eventName: eventType as 'BorrowRateUpdated',\n fromBlock: from,\n toBlock: to,\n })\n for (const log of logs) {\n const parsed = parseRiskEngineLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Fetch SFPM events\n if (sfpmAddress) {\n for (const eventType of sfpmEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: sfpmAddress,\n abi: semiFungiblePositionManagerV4Abi,\n eventName: eventType as 'LiquidityChunkUpdated',\n fromBlock: from,\n toBlock: to,\n })\n for (const log of logs) {\n const parsed = parseSfpmLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Fetch PoolManager events\n if (poolManagerAddress) {\n for (const eventType of poolManagerEventTypes) {\n try {\n const logs = await client.getContractEvents({\n address: poolManagerAddress,\n abi: poolManagerAbi,\n eventName: eventType as 'ModifyLiquidity' | 'Swap' | 'Donate',\n fromBlock: from,\n toBlock: to,\n })\n for (const log of logs) {\n const parsed = parsePoolManagerLog(log as DecodedLog, eventType)\n if (parsed) {\n allEvents.push(parsed)\n }\n }\n } catch (error) {\n onError?.(\n error instanceof Error ? error : new Error(`Failed to fetch ${eventType} events`),\n )\n }\n }\n }\n\n // Sort by block number and log index\n allEvents.sort((a, b) => {\n if (a.blockNumber !== b.blockNumber) {\n return a.blockNumber < b.blockNumber ? -1 : 1\n }\n return a.logIndex < b.logIndex ? -1 : 1\n })\n\n return allEvents\n }\n\n /**\n * Perform a single poll iteration.\n */\n async function poll(): Promise<void> {\n if (!isRunning) return\n\n try {\n // Get current block\n const currentBlock = await client.getBlockNumber()\n\n // Initialize lastPolledBlock if not set\n if (lastPolledBlock === 0n) {\n lastPolledBlock = currentBlock\n schedulePoll()\n return\n }\n\n // Check if there are new blocks\n if (currentBlock <= lastPolledBlock) {\n schedulePoll()\n return\n }\n\n // Calculate range to query (respect maxBlockRange)\n let toBlock = currentBlock\n const range = toBlock - lastPolledBlock\n if (range > maxBlockRange) {\n toBlock = lastPolledBlock + maxBlockRange\n }\n\n // Fetch events\n const events = await fetchEvents(lastPolledBlock + 1n, toBlock)\n\n // Update last polled block\n lastPolledBlock = toBlock\n\n // Deliver events\n if (events.length > 0) {\n onLogs(events)\n }\n\n // If we didn't catch up to current block, poll again immediately\n if (toBlock < currentBlock && isRunning) {\n // Use setImmediate-like behavior with 0ms timeout\n pollTimeout = setTimeout(poll, 0)\n } else {\n schedulePoll()\n }\n } catch (error) {\n onError?.(error instanceof Error ? error : new Error(String(error)))\n schedulePoll()\n }\n }\n\n /**\n * Schedule next poll.\n */\n function schedulePoll(): void {\n if (!isRunning) return\n pollTimeout = setTimeout(poll, Number(intervalMs))\n }\n\n /**\n * Start polling.\n */\n function start(): void {\n if (isRunning) return\n isRunning = true\n poll()\n }\n\n /**\n * Stop polling.\n */\n function stop(): void {\n isRunning = false\n if (pollTimeout) {\n clearTimeout(pollTimeout)\n pollTimeout = null\n }\n }\n\n return {\n start,\n stop,\n isPolling: () => isRunning,\n get lastPolledBlock() {\n return lastPolledBlock\n },\n }\n}\n","/**\n * TanStack Query v5 event hooks for the Panoptic v2 SDK.\n * @module v2/react/hooks/events\n */\n\nimport { useEffect, useRef, useState } from 'react'\nimport type { Address, Hash } from 'viem'\nimport { zeroAddress } from 'viem'\n\nimport { watchEvents } from '../../events'\nimport {\n type EventPoller,\n type EventSubscriptionHandle,\n createEventPoller,\n createEventSubscription,\n} from '../../events'\nimport type { PanopticEvent, PanopticEventType } from '../../types'\nimport { usePanopticContext } from '../provider'\n\n/**\n * Watch events via WebSocket. Returns cleanup automatically on unmount.\n */\nexport function useWatchEvents(\n poolAddress: Address,\n eventTypes: PanopticEventType[] | undefined,\n onEvent: (events: PanopticEvent[]) => void,\n options?: {\n enabled?: boolean\n collateralTracker0?: Address\n collateralTracker1?: Address\n riskEngineAddress?: Address\n sfpmAddress?: Address\n poolManagerAddress?: Address\n onError?: (error: Error) => void\n },\n) {\n const { publicClient } = usePanopticContext()\n const onEventRef = useRef(onEvent)\n onEventRef.current = onEvent\n const onErrorRef = useRef(options?.onError)\n onErrorRef.current = options?.onError\n\n const eventTypesKey = eventTypes?.join(',')\n\n useEffect(() => {\n if (options?.enabled === false) return\n\n const unwatch = watchEvents({\n client: publicClient,\n poolAddress,\n eventTypes,\n collateralTracker0: options?.collateralTracker0,\n collateralTracker1: options?.collateralTracker1,\n riskEngineAddress: options?.riskEngineAddress,\n sfpmAddress: options?.sfpmAddress,\n poolManagerAddress: options?.poolManagerAddress,\n onLogs: (events) => onEventRef.current(events),\n onError: (error) => onErrorRef.current?.(error),\n })\n\n return unwatch\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n publicClient,\n poolAddress,\n options?.enabled,\n options?.collateralTracker0,\n options?.collateralTracker1,\n options?.riskEngineAddress,\n options?.sfpmAddress,\n options?.poolManagerAddress,\n eventTypesKey,\n ])\n}\n\n/**\n * Create a resilient event subscription with auto-reconnect.\n */\nexport function useEventSubscription(\n poolAddress: Address,\n eventTypes: PanopticEventType[] | undefined,\n onEvent: (events: PanopticEvent[]) => void,\n options?: {\n enabled?: boolean\n collateralTracker0?: Address\n collateralTracker1?: Address\n riskEngineAddress?: Address\n sfpmAddress?: Address\n poolManagerAddress?: Address\n onError?: (error: Error) => void\n onReconnect?: (attempt: bigint, nextDelayMs: bigint) => void\n onConnected?: () => void\n },\n) {\n const { publicClient } = usePanopticContext()\n const onEventRef = useRef(onEvent)\n onEventRef.current = onEvent\n const onErrorRef = useRef(options?.onError)\n onErrorRef.current = options?.onError\n const onReconnectRef = useRef(options?.onReconnect)\n onReconnectRef.current = options?.onReconnect\n const onConnectedRef = useRef(options?.onConnected)\n onConnectedRef.current = options?.onConnected\n\n const eventTypesKey = eventTypes?.join(',')\n\n useEffect(() => {\n if (options?.enabled === false) return\n\n const handle: EventSubscriptionHandle = createEventSubscription({\n client: publicClient,\n poolAddress,\n eventTypes,\n collateralTracker0: options?.collateralTracker0,\n collateralTracker1: options?.collateralTracker1,\n riskEngineAddress: options?.riskEngineAddress,\n sfpmAddress: options?.sfpmAddress,\n poolManagerAddress: options?.poolManagerAddress,\n onLogs: (events) => onEventRef.current(events),\n onError: (error) => onErrorRef.current?.(error),\n onReconnect: (attempt, delay) => onReconnectRef.current?.(attempt, delay),\n onConnected: () => onConnectedRef.current?.(),\n })\n\n handle.start()\n return () => handle.stop()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n publicClient,\n poolAddress,\n options?.enabled,\n options?.collateralTracker0,\n options?.collateralTracker1,\n options?.riskEngineAddress,\n options?.sfpmAddress,\n options?.poolManagerAddress,\n eventTypesKey,\n ])\n}\n\n/**\n * Create an HTTP polling event fetcher.\n */\nexport function useEventPoller(\n poolAddress: Address,\n eventTypes: PanopticEventType[] | undefined,\n onEvent: (events: PanopticEvent[]) => void,\n options?: {\n enabled?: boolean\n intervalMs?: bigint\n collateralTracker0?: Address\n collateralTracker1?: Address\n riskEngineAddress?: Address\n sfpmAddress?: Address\n poolManagerAddress?: Address\n onError?: (error: Error) => void\n },\n) {\n const { publicClient } = usePanopticContext()\n const onEventRef = useRef(onEvent)\n onEventRef.current = onEvent\n const onErrorRef = useRef(options?.onError)\n onErrorRef.current = options?.onError\n\n const eventTypesKey = eventTypes?.join(',')\n\n useEffect(() => {\n if (options?.enabled === false) return\n\n const poller: EventPoller = createEventPoller({\n client: publicClient,\n poolAddress,\n eventTypes,\n collateralTracker0: options?.collateralTracker0,\n collateralTracker1: options?.collateralTracker1,\n riskEngineAddress: options?.riskEngineAddress,\n sfpmAddress: options?.sfpmAddress,\n poolManagerAddress: options?.poolManagerAddress,\n intervalMs: options?.intervalMs,\n onLogs: (events) => onEventRef.current(events),\n onError: (error) => onErrorRef.current?.(error),\n })\n\n poller.start()\n return () => poller.stop()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n publicClient,\n poolAddress,\n options?.enabled,\n options?.intervalMs,\n options?.collateralTracker0,\n options?.collateralTracker1,\n options?.riskEngineAddress,\n options?.sfpmAddress,\n options?.poolManagerAddress,\n eventTypesKey,\n ])\n}\n\n/**\n * Confirms a transaction by watching for its corresponding on-chain event.\n *\n * An event log only exists in a confirmed (non-reverted) transaction, so\n * matching on `transactionHash` is sufficient proof of 1-block inclusion.\n * This bypasses the N-block confirmation wait of `useWaitForTransactionReceipt`,\n * making it faster on chains with high confirmation counts (e.g. Base = 150 blocks).\n *\n * Use alongside `useWaitForTransactionReceipt` (confirmations: 1) for revert\n * detection — reverted transactions emit no events.\n *\n * @example\n * ```tsx\n * const confirmation = useTxEventConfirmation({\n * txHash: write.data,\n * poolAddress,\n * eventType: 'OptionMinted',\n * enabled: write.data !== undefined,\n * })\n *\n * useEffect(() => {\n * if (confirmation.isSuccess) onSuccess?.()\n * }, [confirmation.isSuccess])\n * ```\n */\nexport function useTxEventConfirmation({\n txHash,\n poolAddress = zeroAddress,\n collateralTrackerAddress,\n eventType,\n enabled = true,\n intervalMs = 3000n,\n}: {\n /** Transaction hash to confirm. Polling starts when this is defined. */\n txHash: Hash | undefined\n /** PanopticPool address to watch for the event. Optional when watching collateral events only. */\n poolAddress?: Address\n /** CollateralTracker address to watch for Deposit/Withdraw events. */\n collateralTrackerAddress?: Address\n /** The event type expected from this transaction. */\n eventType: PanopticEventType\n /** Set to false to disable polling entirely. Default: true. */\n enabled?: boolean\n /** Polling interval in ms. Default: 3000 (~1 block on L2s). */\n intervalMs?: bigint\n}): {\n /** The matched event, set once the tx is confirmed. */\n data: PanopticEvent | undefined\n /** True while polling and not yet confirmed. */\n isLoading: boolean\n /** True once the matching event has been observed. */\n isSuccess: boolean\n} {\n const { publicClient } = usePanopticContext()\n const [data, setData] = useState<PanopticEvent | undefined>()\n const [isLoading, setIsLoading] = useState(false)\n\n // Refs to avoid stale closures inside the async poller callback\n const txHashRef = useRef(txHash)\n txHashRef.current = txHash\n const confirmedRef = useRef(false)\n const pollerRef = useRef<EventPoller | null>(null)\n\n useEffect(() => {\n // Reset for new tx\n confirmedRef.current = false\n setData(undefined)\n\n if (!txHash || !enabled) {\n pollerRef.current?.stop()\n pollerRef.current = null\n setIsLoading(false)\n return\n }\n\n setIsLoading(true)\n let cancelled = false\n\n // Capture current block before starting so we don't miss an event that\n // lands in the same block as poller initialisation.\n publicClient\n .getBlockNumber()\n .then((currentBlock) => {\n if (cancelled) return\n\n const fromBlock = currentBlock > 0n ? currentBlock - 1n : 0n\n\n const poller = createEventPoller({\n client: publicClient,\n poolAddress,\n collateralTracker0: collateralTrackerAddress,\n eventTypes: [eventType],\n intervalMs,\n fromBlock,\n onLogs: (events) => {\n const hash = txHashRef.current\n if (!hash || confirmedRef.current) return\n const match = events.find((e) => e.transactionHash === hash)\n if (match) {\n confirmedRef.current = true\n pollerRef.current?.stop()\n pollerRef.current = null\n setIsLoading(false)\n setData(match)\n }\n },\n })\n\n pollerRef.current = poller\n poller.start()\n })\n .catch(() => {\n if (cancelled || confirmedRef.current) return\n pollerRef.current?.stop()\n pollerRef.current = null\n setIsLoading(false)\n })\n\n return () => {\n cancelled = true\n pollerRef.current?.stop()\n pollerRef.current = null\n }\n }, [txHash, enabled, publicClient, poolAddress, collateralTrackerAddress, eventType, intervalMs])\n\n return {\n data,\n isLoading: isLoading && data === undefined,\n isSuccess: data !== undefined,\n }\n}\n"],"mappings":"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"}
|