@panoptic-eng/sdk 1.0.20 → 1.0.21
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-Cqw3sako.js → cow-C_SGXoWr.js} +2 -2
- package/dist/{cow-Cqw3sako.js.map → cow-C_SGXoWr.js.map} +1 -1
- package/dist/index.js +2 -2
- package/dist/{irm-DF4NwYIY.js → irm-CfM383Ku.js} +3 -3
- package/dist/{irm-DF4NwYIY.js.map → irm-CfM383Ku.js.map} +1 -1
- package/dist/panoptic/v2/index.d.ts +11 -3
- package/dist/panoptic/v2/index.d.ts.map +1 -1
- package/dist/panoptic/v2/index.js +25 -10
- package/dist/panoptic/v2/index.js.map +1 -1
- package/dist/{position-zqvENVuf.js → position-BK4a-Yyu.js} +2 -2
- package/dist/{position-zqvENVuf.js.map → position-BK4a-Yyu.js.map} +1 -1
- package/dist/{router-d09dxd-F.js → router-CMrp245w.js} +2 -2
- package/dist/{router-d09dxd-F.js.map → router-CMrp245w.js.map} +1 -1
- package/dist/test/index.js +1 -1
- package/dist/uniswap/index.js +3 -3
- package/dist/{writes-CRjVFjMt.js → writes-DymnVbiE.js} +2 -2
- package/dist/{writes-CRjVFjMt.js.map → writes-DymnVbiE.js.map} +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writes-CRjVFjMt.js","names":["publicBroadcaster: TxBroadcaster","signedTx: `0x${string}`","client: PublicClient","account: Address","params: ApproveParams","params: ApprovePoolParams","params: CheckApprovalParams","params: DepositParams","params: WithdrawParams","params: WithdrawWithPositionsParams","params: MintParams","params: RedeemParams","directory: string","fsPromises: typeof FsPromises | null","pathModule: typeof Path | null","key: string","value: string","prefix: string","result: string[]","chainId: bigint","poolAddress: Address","account: Address","tokenId: bigint","key: string","value: string","prefix: string","result: string[]","keysToDelete: string[]","value: unknown","_key: string","space?: string | number","text: string","params: RecoverSnapshotParams","error: unknown","parts: string[]","current: unknown","params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n fromBlock: bigint\n toBlock: bigint\n}","params: {\n client: PublicClient\n account: Address\n events: SnapshotEventLog[]\n}","event: SnapshotEventLog","params: RecoverSnapshotFromTxParams","input: `0x${string}`","candidates: DispatchCalldata[]","account: Address","txFrom: Address","match: DispatchCalldata | null","results: DispatchCalldata[]","params: GetTrackedPositionIdsParams","tokenId: bigint","params: GetOpenPositionIdsParams","snapshot: SnapshotRecoveryResult | null","resolvePositionIds","explicit: bigint[] | undefined","storage: StorageAdapter | undefined","chainId: bigint | undefined","poolAddress: Address","account: Address","savePositionIds","storage: StorageAdapter","chainId: bigint","positionIds: bigint[]","params: OpenPositionParams","tickLimits: readonly [number, number, number]","tickLimits","params: {\n poolAddress: Address\n existingPositionIds: bigint[]\n tokenId: bigint\n positionSize: bigint\n tickLimitLow: bigint\n tickLimitHigh: bigint\n spreadLimit?: bigint\n swapAtMint?: boolean\n usePremiaAsCollateral?: boolean\n builderCode?: bigint\n}","params: ClosePositionParams","params: RollPositionParams","closeLimits: readonly [number, number, number]","openLimits: readonly [number, number, number]","params: DispatchParams","params: ValidateBatchParams","diagnostics: BatchDiagnostic[]","params: BuildBatchDispatchArgsParams","tickAndSpreadLimits: TickAndSpreadLimits[]","params: ExecuteBatchDispatchParams","params: LiquidateParams","data: DataWithMeta","maxAgeSeconds: bigint | number","currentTimestamp?: bigint | number","pool: Pool","safeMode?: SafeModeState","safeMode: SafeModeState","error: unknown","params: DetectReorgParams","reorgBlock: bigint","reorgDepth: bigint","params: SaveCheckpointParams","checkpoint: SyncCheckpoint","storage: StorageAdapter","chainId: bigint","poolAddress: Address","account: Address","client: PublicClient","fromBlock: bigint","toBlock: bigint","previousHash: Hash | null","params: SyncPositionsParams","positionIds: bigint[]","finalBlock","poolMetaKey","existingPoolMeta","positionsKey","storedData: StoredPositionData","params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n fromBlock?: bigint\n toBlock: bigint\n}","client: PublicClient","poolAddress: Address","poolMetaKey: string","storage: StorageAdapter","poolMeta: StoredPoolMeta","fn: () => Promise<T>","lastError: unknown","params: ForceExerciseParams","params: SettleParams","positionSizes: bigint[]","tickAndSpreadLimits: TickAndSpreadLimits[]","params: PokeOracleParams","params: DeployNewPoolParams","value: bigint","multiplier: number","originalMaxFeePerGas: bigint | undefined","originalMaxPriorityFeePerGas: bigint | undefined","explicitMaxFeePerGas: bigint | undefined","explicitMaxPriorityFeePerGas: bigint | undefined","params: SpeedUpParams","replacementHash","params: CancelParams","cancelHash","strike: bigint","encodedStrike: bigint","legIndex: bigint","address: Address","tickSpacing: bigint","vegoid: bigint","bytes: number[]","poolIdHex: Hex","tokenId: bigint","value: bigint","bitPosition: bigint","leg: EncodeLegParams","legs: DecodedLeg[]","poolId: bigint","config: LegConfig","legIndex: bigint","builder: TokenIdBuilder","leg: EncodeLegParams","config: Omit<LegConfig, 'tokenType' | 'asset'> & { asset?: bigint }","config: LoanCreditConfig","tokenAddress: Address","token0: Address","token1: Address","explicit: bigint[] | undefined","storage: StorageAdapter | undefined","chainId: bigint","poolAddress: Address","account: Address","error: unknown","poolId: bigint","asset: bigint","tokenType: bigint","currentTick: bigint","tickSpacing: bigint","existingPositionIds: bigint[]","positionSize: bigint","params: SwapExactOutParams","mintTickLimits: readonly [number, number, number]","burnTickLimits: readonly [number, number, number]","params: SwapExactInParams","params: WrapXstockParams","params: UnwrapXstockParams","params: PreviewWrapParams","params: WrapEthParams","params: UnwrapWethParams","leg: DecodedLeg","tickSpacing: bigint","tokenId: bigint","expectedPoolId: bigint","params: SimulateWithTokenFlowParams","multicallData: Hex[]","data: Hex","params: SimulateOpenPositionParams","tickLimits: readonly [number, number, number]","tickLimits","perPositionCollateralReqs: { token0: bigint; token1: bigint }[]","decoded","data: OpenPositionSimulation","client: PublicClient","poolAddress: Address","chainId: bigint","token: Address","storage: StorageAdapter","account: Address","positionIds: bigint[]","params: SupplyParams","params: UnsupplyParams","params: BorrowParams","mintTickLimits: readonly [number, number, number]","params: PreviewBorrowParams","collateralReqToken0: bigint | null","collateralReqToken1: bigint | null","params: RepayParams","ascendingLimits: readonly [number, number, number]","existingPositionIds: bigint[]","tokenIndex: bigint","params: SmartRepayParams","opsPositionIds: bigint[]","opsSizes: bigint[]","finalPositionIdList: bigint[]"],"sources":["../src/panoptic/v2/writes/broadcaster.ts","../src/panoptic/v2/writes/approve.ts","../src/panoptic/v2/writes/vault.ts","../src/panoptic/v2/storage/fileStorage.ts","../src/panoptic/v2/storage/keys.ts","../src/panoptic/v2/storage/memoryStorage.ts","../src/panoptic/v2/storage/serializer.ts","../src/panoptic/v2/sync/snapshotRecovery.ts","../src/panoptic/v2/sync/getTrackedPositionIds.ts","../src/panoptic/v2/writes/position.ts","../src/panoptic/v2/writes/dispatch.ts","../src/panoptic/v2/batch/validate.ts","../src/panoptic/v2/batch/build.ts","../src/panoptic/v2/writes/executeBatchDispatch.ts","../src/panoptic/v2/writes/liquidate.ts","../src/panoptic/v2/bot/index.ts","../src/panoptic/v2/sync/reorgHandling.ts","../src/panoptic/v2/sync/syncPositions.ts","../src/panoptic/v2/writes/forceExercise.ts","../src/panoptic/v2/writes/settle.ts","../src/panoptic/v2/writes/pokeOracle.ts","../src/panoptic/v2/writes/factory.ts","../src/panoptic/v2/writes/txManagement.ts","../src/panoptic/v2/tokenId/encoding.ts","../src/panoptic/v2/tokenId/builder.ts","../src/panoptic/v2/writes/loanUtils.ts","../src/panoptic/v2/writes/swap.ts","../src/panoptic/v2/writes/wrap.ts","../src/panoptic/v2/tokenId/decode.ts","../src/panoptic/v2/simulations/tokenFlow.ts","../src/panoptic/v2/simulations/simulateOpenPosition.ts","../src/panoptic/v2/writes/lending.ts"],"sourcesContent":["/**\n * Transaction broadcaster utilities for the Panoptic v2 SDK.\n * @module v2/writes/broadcaster\n */\n\nimport type { Address, Hash, PublicClient, WalletClient } from 'viem'\n\nimport type { NonceManager, TxBroadcaster } from '../types'\n\n/**\n * Create a public broadcaster that sends transactions to the standard mempool.\n *\n * Use this factory to create a working broadcaster with a client.\n *\n * @param client - The public client for broadcasting\n * @returns A TxBroadcaster that sends to the public mempool\n *\n * @example\n * ```typescript\n * const broadcaster = createPublicBroadcaster(publicClient)\n * const hash = await broadcaster.broadcast(signedTx)\n * ```\n */\nexport function createPublicBroadcaster(client: PublicClient): TxBroadcaster {\n return {\n async broadcast(signedTx: `0x${string}`): Promise<Hash> {\n return client.sendRawTransaction({ serializedTransaction: signedTx })\n },\n }\n}\n\n/**\n * Default public broadcaster singleton.\n *\n * Note: This singleton requires a client to be provided via the broadcast call's context.\n * For standalone usage, use `createPublicBroadcaster(client)` instead.\n *\n * When used with write functions, the SDK handles client injection automatically.\n */\nexport const publicBroadcaster: TxBroadcaster = {\n async broadcast(signedTx: `0x${string}`): Promise<Hash> {\n // This singleton cannot broadcast without a client.\n // Write functions that use this broadcaster should inject their client.\n throw new Error(\n 'publicBroadcaster requires a client. Use createPublicBroadcaster(client) for standalone usage.',\n )\n },\n}\n\n/**\n * Create a nonce manager for concurrent transaction submission.\n *\n * The nonce manager tracks pending nonces to allow multiple transactions\n * to be submitted without waiting for confirmation.\n *\n * @param client - The public client for querying nonces\n * @returns A NonceManager instance\n *\n * @example\n * ```typescript\n * const nonceManager = createNonceManager(client)\n * const nonce1 = await nonceManager.getNextNonce(account)\n * const nonce2 = await nonceManager.getNextNonce(account) // nonce1 + 1\n * // On failure, reset to re-fetch from chain:\n * nonceManager.reset(account)\n * ```\n */\nexport function createNonceManager(client: PublicClient): NonceManager {\n const pendingNonces = new Map<Address, bigint>()\n\n return {\n async getNextNonce(account: Address): Promise<bigint> {\n const chainNonce = BigInt(\n await client.getTransactionCount({\n address: account,\n blockTag: 'pending',\n }),\n )\n\n const pending = pendingNonces.get(account)\n const localNext = pending !== undefined ? pending + 1n : chainNonce\n const nextNonce = localNext > chainNonce ? localNext : chainNonce\n\n pendingNonces.set(account, nextNonce)\n return nextNonce\n },\n\n reset(account: Address): void {\n pendingNonces.delete(account)\n },\n }\n}\n\n/**\n * Configuration for write operations.\n */\nexport interface WriteConfig {\n /** Wallet client for signing and submitting transactions */\n walletClient: WalletClient\n /** Public client for reading state */\n publicClient: PublicClient\n /** Optional custom broadcaster */\n broadcaster?: TxBroadcaster\n /** Optional nonce manager for concurrent transactions */\n nonceManager?: NonceManager\n /** Gas price multiplier (1.0 = no change, 1.1 = 10% increase) */\n gasPriceMultiplier?: number\n /** Optional gas limit override */\n gasLimit?: bigint\n}\n","/**\n * Approval functions for the Panoptic v2 SDK.\n * @module v2/writes/approve\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\nimport { erc20Abi } from 'viem'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi } from '../../../generated'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for approve function.\n */\nexport interface ApproveParams {\n /** Public client for reading state */\n client: PublicClient\n /** Wallet client for signing transactions */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** Token address to approve */\n tokenAddress: Address\n /** Spender address (collateral tracker) */\n spenderAddress: Address\n /** Amount to approve (use MaxUint256 for unlimited) */\n amount: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Approve token spending for a collateral tracker.\n *\n * @param params - The approval parameters\n * @returns TxResult with hash and wait function\n *\n * @example\n * ```typescript\n * const result = await approve({\n * client,\n * walletClient,\n * account,\n * tokenAddress: WETH,\n * spenderAddress: collateralToken0,\n * amount: MaxUint256,\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function approve(params: ApproveParams): Promise<TxResult> {\n const { client, walletClient, account, tokenAddress, spenderAddress, amount, txOverrides } =\n params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: tokenAddress,\n abi: erc20Abi,\n functionName: 'approve',\n args: [spenderAddress, amount],\n txOverrides,\n })\n}\n\n/**\n * Approve token spending and wait for confirmation.\n *\n * @param params - The approval parameters\n * @returns TxReceipt after confirmation\n */\nexport async function approveAndWait(params: ApproveParams): Promise<TxReceipt> {\n const result = await approve(params)\n return result.wait()\n}\n\n/**\n * Parameters for approving both tokens for a pool.\n */\nexport interface ApprovePoolParams {\n /** Public client for reading state */\n client: PublicClient\n /** Wallet client for signing transactions */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Amount to approve for token 0 */\n amount0: bigint\n /** Amount to approve for token 1 */\n amount1: bigint\n}\n\n/**\n * Approve both tokens for a Panoptic pool.\n * Fetches collateral tracker addresses and underlying tokens, then approves both.\n *\n * @param params - The approval parameters\n * @returns Array of two TxResults\n *\n * @example\n * ```typescript\n * const [result0, result1] = await approvePool({\n * client,\n * walletClient,\n * account,\n * poolAddress,\n * amount0: MaxUint256,\n * amount1: MaxUint256,\n * })\n * await Promise.all([result0.wait(), result1.wait()])\n * ```\n */\nexport async function approvePool(params: ApprovePoolParams): Promise<[TxResult, TxResult]> {\n const { client, walletClient, account, poolAddress, amount0, amount1 } = params\n\n // Get collateral tracker addresses\n const [collateralToken0, collateralToken1] = await client.multicall({\n contracts: [\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'collateralToken0',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'collateralToken1',\n },\n ],\n allowFailure: false,\n })\n\n // Get underlying token addresses\n const [token0, token1] = await client.multicall({\n contracts: [\n {\n address: collateralToken0,\n abi: collateralTrackerV2Abi,\n functionName: 'asset',\n },\n {\n address: collateralToken1,\n abi: collateralTrackerV2Abi,\n functionName: 'asset',\n },\n ],\n allowFailure: false,\n })\n\n // Approve both tokens in parallel\n const [result0, result1] = await Promise.all([\n approve({\n client,\n walletClient,\n account,\n tokenAddress: token0,\n spenderAddress: collateralToken0,\n amount: amount0,\n }),\n approve({\n client,\n walletClient,\n account,\n tokenAddress: token1,\n spenderAddress: collateralToken1,\n amount: amount1,\n }),\n ])\n\n return [result0, result1]\n}\n\n/**\n * Check if an approval is needed for a given amount.\n *\n * @param params - Parameters for checking approval\n * @returns Object with needsApproval flag and current allowance\n */\nexport interface CheckApprovalParams {\n /** Public client */\n client: PublicClient\n /** Token address */\n tokenAddress: Address\n /** Owner address */\n owner: Address\n /** Spender address */\n spender: Address\n /** Amount to check against */\n amount: bigint\n}\n\nexport interface ApprovalStatus {\n /** Whether approval is needed */\n needsApproval: boolean\n /** Current allowance */\n currentAllowance: bigint\n /** Amount that would be approved */\n requiredAmount: bigint\n}\n\n/**\n * Check if approval is needed for a token transfer.\n *\n * @param params - The check parameters\n * @returns Approval status\n */\nexport async function checkApproval(params: CheckApprovalParams): Promise<ApprovalStatus> {\n const { client, tokenAddress, owner, spender, amount } = params\n\n const currentAllowance = await client.readContract({\n address: tokenAddress,\n abi: erc20Abi,\n functionName: 'allowance',\n args: [owner, spender],\n })\n\n return {\n needsApproval: currentAllowance < amount,\n currentAllowance,\n requiredAmount: amount,\n }\n}\n","/**\n * ERC4626 vault operations for the Panoptic v2 SDK.\n * @module v2/writes/vault\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { collateralTrackerV2Abi } from '../../../generated'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for deposit operation.\n */\nexport interface DepositParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** CollateralTracker address */\n collateralTrackerAddress: Address\n /** Amount of assets to deposit */\n assets: bigint\n /** Whether the collateral tracker wraps native ETH (requires sending msg.value) */\n isNativeETH?: boolean\n /** Receiver of shares (defaults to account) */\n receiver?: Address\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Deposit assets into a collateral tracker.\n *\n * @param params - Deposit parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await deposit({\n * client,\n * walletClient,\n * account,\n * collateralTrackerAddress,\n * assets: parseEther('1'),\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function deposit(params: DepositParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n collateralTrackerAddress,\n assets,\n isNativeETH,\n receiver = account,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'deposit',\n args: [assets, receiver],\n value: isNativeETH ? assets : undefined,\n txOverrides,\n })\n}\n\n/**\n * Deposit assets and wait for confirmation.\n */\nexport async function depositAndWait(params: DepositParams): Promise<TxReceipt> {\n const result = await deposit(params)\n return result.wait()\n}\n\n/**\n * Parameters for withdraw operation.\n */\nexport interface WithdrawParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** CollateralTracker address */\n collateralTrackerAddress: Address\n /** Amount of assets to withdraw */\n assets: bigint\n /** Receiver of assets */\n receiver?: Address\n /** Owner of shares (defaults to account) */\n owner?: Address\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Withdraw assets from a collateral tracker.\n *\n * @param params - Withdraw parameters\n * @returns TxResult\n */\nexport async function withdraw(params: WithdrawParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n collateralTrackerAddress,\n assets,\n receiver = account,\n owner = account,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'withdraw',\n args: [assets, receiver, owner],\n txOverrides,\n })\n}\n\n/**\n * Withdraw assets and wait for confirmation.\n */\nexport async function withdrawAndWait(params: WithdrawParams): Promise<TxReceipt> {\n const result = await withdraw(params)\n return result.wait()\n}\n\n/**\n * Parameters for withdraw with position list validation.\n */\nexport interface WithdrawWithPositionsParams extends WithdrawParams {\n /** Position ID list for collateral validation */\n positionIdList: bigint[]\n /** Whether to use premia as collateral */\n usePremiaAsCollateral: boolean\n}\n\n/**\n * Withdraw assets with position list validation.\n * This overload validates that the withdrawal won't make positions undercollateralized.\n *\n * @param params - Withdraw parameters with positions\n * @returns TxResult\n */\nexport async function withdrawWithPositions(\n params: WithdrawWithPositionsParams,\n): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n collateralTrackerAddress,\n assets,\n receiver = account,\n owner = account,\n positionIdList,\n usePremiaAsCollateral,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'withdraw',\n args: [assets, receiver, owner, positionIdList, usePremiaAsCollateral],\n txOverrides,\n })\n}\n\n/**\n * Withdraw with positions and wait for confirmation.\n */\nexport async function withdrawWithPositionsAndWait(\n params: WithdrawWithPositionsParams,\n): Promise<TxReceipt> {\n const result = await withdrawWithPositions(params)\n return result.wait()\n}\n\n/**\n * Parameters for mint operation.\n */\nexport interface MintParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** CollateralTracker address */\n collateralTrackerAddress: Address\n /** Amount of shares to mint */\n shares: bigint\n /** Receiver of shares */\n receiver?: Address\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Mint shares by depositing assets.\n *\n * @param params - Mint parameters\n * @returns TxResult\n */\nexport async function mint(params: MintParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n collateralTrackerAddress,\n shares,\n receiver = account,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'mint',\n args: [shares, receiver],\n txOverrides,\n })\n}\n\n/**\n * Mint shares and wait for confirmation.\n */\nexport async function mintAndWait(params: MintParams): Promise<TxReceipt> {\n const result = await mint(params)\n return result.wait()\n}\n\n/**\n * Parameters for redeem operation.\n */\nexport interface RedeemParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** CollateralTracker address */\n collateralTrackerAddress: Address\n /** Amount of shares to redeem */\n shares: bigint\n /** Receiver of assets */\n receiver?: Address\n /** Owner of shares */\n owner?: Address\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Redeem shares for assets.\n *\n * @param params - Redeem parameters\n * @returns TxResult\n */\nexport async function redeem(params: RedeemParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n collateralTrackerAddress,\n shares,\n receiver = account,\n owner = account,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'redeem',\n args: [shares, receiver, owner],\n txOverrides,\n })\n}\n\n/**\n * Redeem shares and wait for confirmation.\n */\nexport async function redeemAndWait(params: RedeemParams): Promise<TxReceipt> {\n const result = await redeem(params)\n return result.wait()\n}\n","/**\n * File-based storage adapter for Node.js.\n * @module v2/storage/fileStorage\n */\n\nimport type FsPromises from 'node:fs/promises'\nimport type Path from 'node:path'\n\nimport type { StorageAdapter } from './adapter'\n\n/**\n * Creates a file-based storage adapter for Node.js environments.\n * Stores data as JSON files in the specified directory.\n *\n * The directory will be created if it doesn't exist.\n *\n * @param directory - Path to the storage directory\n *\n * @example\n * ```typescript\n * import { createFileStorage, createConfig } from 'panoptic-v2-sdk'\n *\n * // Node.js only\n * const config = createConfig({\n * chainId: 1n,\n * transport: http('...'),\n * poolAddress: '0x...',\n * storage: createFileStorage('./panoptic-cache'),\n * })\n * ```\n */\nexport function createFileStorage(directory: string): StorageAdapter {\n // Lazy import fs/promises to avoid issues in browser environments\n // This function should only be called in Node.js\n let fsPromises: typeof FsPromises | null = null\n let pathModule: typeof Path | null = null\n let initialized = false\n\n const ensureInitialized = async () => {\n if (initialized) return\n\n // Dynamic import for Node.js modules\n fsPromises = await import('node:fs/promises')\n pathModule = await import('node:path')\n\n // Ensure directory exists\n await fsPromises.mkdir(directory, { recursive: true })\n initialized = true\n }\n\n const getFilePath = (key: string): string => {\n if (!pathModule) throw new Error('File storage not initialized')\n // Encode the key to be filesystem-safe\n const safeKey = Buffer.from(key).toString('base64url')\n return pathModule.join(directory, `${safeKey}.json`)\n }\n\n return {\n async get(key: string): Promise<string | null> {\n await ensureInitialized()\n if (!fsPromises) throw new Error('File storage not initialized')\n\n try {\n const filePath = getFilePath(key)\n const content = await fsPromises.readFile(filePath, 'utf-8')\n return content\n } catch (error) {\n // File doesn't exist\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return null\n }\n throw error\n }\n },\n\n async set(key: string, value: string): Promise<void> {\n await ensureInitialized()\n if (!fsPromises) throw new Error('File storage not initialized')\n\n const filePath = getFilePath(key)\n await fsPromises.writeFile(filePath, value, 'utf-8')\n },\n\n async delete(key: string): Promise<void> {\n await ensureInitialized()\n if (!fsPromises) throw new Error('File storage not initialized')\n\n try {\n const filePath = getFilePath(key)\n await fsPromises.unlink(filePath)\n } catch (error) {\n // Ignore if file doesn't exist\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw error\n }\n }\n },\n\n async has(key: string): Promise<boolean> {\n await ensureInitialized()\n if (!fsPromises) throw new Error('File storage not initialized')\n\n try {\n const filePath = getFilePath(key)\n await fsPromises.access(filePath)\n return true\n } catch {\n return false\n }\n },\n\n async keys(prefix: string): Promise<string[]> {\n await ensureInitialized()\n if (!fsPromises || !pathModule) throw new Error('File storage not initialized')\n\n const result: string[] = []\n\n try {\n const files = await fsPromises.readdir(directory)\n for (const file of files) {\n if (file.endsWith('.json')) {\n const safeKey = file.slice(0, -5) // Remove .json\n try {\n const key = Buffer.from(safeKey, 'base64url').toString()\n if (key.startsWith(prefix)) {\n result.push(key)\n }\n } catch {\n // Invalid base64, skip\n }\n }\n }\n } catch (error) {\n // Directory doesn't exist yet\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw error\n }\n }\n\n return result\n },\n\n async clear(prefix: string): Promise<void> {\n await ensureInitialized()\n if (!fsPromises) throw new Error('File storage not initialized')\n\n const keysToDelete = await this.keys(prefix)\n for (const key of keysToDelete) {\n await this.delete(key)\n }\n },\n }\n}\n","/**\n * Storage key generation for the Panoptic v2 SDK.\n * @module v2/storage/keys\n */\n\nimport type { Address } from 'viem'\n\nimport { SCHEMA_VERSION, STORAGE_PREFIX } from '../utils/constants'\n\n/**\n * Get the schema version key.\n */\nexport function getSchemaVersionKey(): string {\n return `${STORAGE_PREFIX}:schemaVersion`\n}\n\n/**\n * Get the base prefix for a specific pool.\n */\nexport function getPoolPrefix(chainId: bigint, poolAddress: Address): string {\n return `${STORAGE_PREFIX}:v${SCHEMA_VERSION}:chain${chainId}:pool${poolAddress.toLowerCase()}`\n}\n\n/**\n * Get the key for tracked position IDs.\n */\nexport function getPositionsKey(chainId: bigint, poolAddress: Address, account: Address): string {\n return `${getPoolPrefix(chainId, poolAddress)}:positions:${account.toLowerCase()}`\n}\n\n/**\n * Get the key for position mint metadata.\n */\nexport function getPositionMetaKey(chainId: bigint, poolAddress: Address, tokenId: bigint): string {\n return `${getPoolPrefix(chainId, poolAddress)}:positionMeta:${tokenId.toString()}`\n}\n\n/**\n * Get the key for sync checkpoint.\n */\nexport function getSyncCheckpointKey(\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n): string {\n return `${getPoolPrefix(chainId, poolAddress)}:sync:${account.toLowerCase()}`\n}\n\n/**\n * Get the key for closed positions.\n */\nexport function getClosedPositionsKey(\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n): string {\n return `${getPoolPrefix(chainId, poolAddress)}:closed:${account.toLowerCase()}`\n}\n\n/**\n * Get the key for tracked chunks.\n */\nexport function getTrackedChunksKey(chainId: bigint, poolAddress: Address): string {\n return `${getPoolPrefix(chainId, poolAddress)}:chunks`\n}\n\n/**\n * Get the key for pending positions.\n */\nexport function getPendingPositionsKey(\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n): string {\n return `${getPoolPrefix(chainId, poolAddress)}:pending:${account.toLowerCase()}`\n}\n\n/**\n * Get the key for pool metadata (tickSpacing, etc.).\n */\nexport function getPoolMetaKey(chainId: bigint, poolAddress: Address): string {\n return `${getPoolPrefix(chainId, poolAddress)}:poolMeta`\n}\n","/**\n * In-memory storage adapter for testing.\n * @module v2/storage/memoryStorage\n */\n\nimport type { StorageAdapter } from './adapter'\n\n/**\n * Creates an in-memory storage adapter.\n * Useful for testing and development.\n *\n * Data is lost when the process exits.\n *\n * @example\n * ```typescript\n * import { createMemoryStorage, createConfig } from 'panoptic-v2-sdk'\n *\n * const config = createConfig({\n * chainId: 1n,\n * transport: http('...'),\n * poolAddress: '0x...',\n * storage: createMemoryStorage(),\n * })\n * ```\n */\nexport function createMemoryStorage(): StorageAdapter {\n const store = new Map<string, string>()\n\n return {\n async get(key: string): Promise<string | null> {\n return store.get(key) ?? null\n },\n\n async set(key: string, value: string): Promise<void> {\n store.set(key, value)\n },\n\n async delete(key: string): Promise<void> {\n store.delete(key)\n },\n\n async has(key: string): Promise<boolean> {\n return store.has(key)\n },\n\n async keys(prefix: string): Promise<string[]> {\n const result: string[] = []\n for (const key of store.keys()) {\n if (key.startsWith(prefix)) {\n result.push(key)\n }\n }\n return result\n },\n\n async clear(prefix: string): Promise<void> {\n const keysToDelete: string[] = []\n for (const key of store.keys()) {\n if (key.startsWith(prefix)) {\n keysToDelete.push(key)\n }\n }\n for (const key of keysToDelete) {\n store.delete(key)\n }\n },\n }\n}\n","/**\n * BigInt-safe JSON serialization for the Panoptic v2 SDK.\n * Compatible with superjson patterns for SSR hydration.\n * @module v2/storage/serializer\n */\n\n/**\n * Tagged value for BigInt serialization.\n * Format compatible with superjson for Next.js/Remix SSR.\n */\ninterface BigIntTagged {\n __type: 'bigint'\n value: string\n}\n\n/**\n * Type guard to check if a value is a tagged BigInt.\n */\nfunction isBigIntTagged(value: unknown): value is BigIntTagged {\n return (\n value !== null &&\n typeof value === 'object' &&\n '__type' in value &&\n (value as BigIntTagged).__type === 'bigint' &&\n 'value' in value &&\n typeof (value as BigIntTagged).value === 'string'\n )\n}\n\n/**\n * Replacer function for JSON.stringify that tags BigInt values.\n */\nfunction replacer(_key: string, value: unknown): unknown {\n if (typeof value === 'bigint') {\n return {\n __type: 'bigint',\n value: value.toString(),\n } satisfies BigIntTagged\n }\n return value\n}\n\n/**\n * Reviver function for JSON.parse that restores tagged BigInt values.\n */\nfunction reviver(_key: string, value: unknown): unknown {\n if (isBigIntTagged(value)) {\n return BigInt(value.value)\n }\n return value\n}\n\n/**\n * BigInt-safe JSON serializer for the Panoptic v2 SDK.\n *\n * This serializer handles BigInt values by tagging them with a special format\n * that can be restored on parse. The format is compatible with superjson\n * patterns used in Next.js and Remix for SSR hydration.\n *\n * @example\n * ```typescript\n * import { jsonSerializer } from 'panoptic-v2-sdk'\n *\n * const data = { amount: 1000000000000000000n, nested: { value: 42n } }\n *\n * // Serialize to JSON string\n * const json = jsonSerializer.stringify(data)\n * // '{\"amount\":{\"__type\":\"bigint\",\"value\":\"1000000000000000000\"},\"nested\":{\"value\":{\"__type\":\"bigint\",\"value\":\"42\"}}}'\n *\n * // Parse back to original types\n * const parsed = jsonSerializer.parse(json)\n * // { amount: 1000000000000000000n, nested: { value: 42n } }\n * ```\n */\nexport const jsonSerializer = {\n /**\n * Serialize a value to a JSON string, handling BigInt values.\n *\n * @param value - The value to serialize\n * @param space - Optional indentation (same as JSON.stringify)\n * @returns JSON string with BigInt values tagged\n */\n stringify(value: unknown, space?: string | number): string {\n return JSON.stringify(value, replacer, space)\n },\n\n /**\n * Parse a JSON string, restoring tagged BigInt values.\n *\n * @param text - The JSON string to parse\n * @returns The parsed value with BigInt values restored\n */\n parse(text: string): unknown {\n return JSON.parse(text, reviver)\n },\n} as const\n","/**\n * Snapshot recovery from dispatch calldata.\n * @module v2/sync/snapshotRecovery\n */\n\nimport type { AbiFunction, Address, Hash, PublicClient } from 'viem'\nimport { decodeFunctionData, toFunctionSelector } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\n\nconst LOG_SCAN_WINDOW = 10_000n\n\ntype SnapshotEventLog = Awaited<ReturnType<PublicClient['getLogs']>>[number]\ntype SnapshotCandidateEvent = SnapshotEventLog & {\n transactionHash: Hash\n blockNumber: bigint\n logIndex: number\n}\n\n/**\n * Parameters for recovering position snapshot from dispatch calldata.\n */\nexport interface RecoverSnapshotParams {\n /** viem public client */\n client: PublicClient\n /** Pool address */\n poolAddress: Address\n /** Account to recover positions for */\n account: Address\n /** Starting block for transaction search (defaults to 0) */\n fromBlock?: bigint\n /** Ending block for transaction search (defaults to latest) */\n toBlock?: bigint\n}\n\n/**\n * Snapshot recovery result.\n */\nexport interface SnapshotRecoveryResult {\n /** Whether recovery was successful */\n success: boolean\n /** Position IDs from the final position list */\n positionIds: bigint[]\n /** Block number of the recovery transaction */\n blockNumber: bigint\n /** Block hash of the recovery transaction */\n blockHash: Hash\n /** Transaction hash used for recovery */\n transactionHash: Hash\n}\n\n/**\n * Recover position snapshot from the last dispatch transaction.\n * This is the primary recovery method - it finds the most recent dispatch()\n * call and extracts the finalPositionIdList from the calldata.\n *\n * @param params - Recovery parameters\n * @returns Snapshot recovery result\n */\nexport async function recoverSnapshot(\n params: RecoverSnapshotParams,\n): Promise<SnapshotRecoveryResult | null> {\n const { client, poolAddress, account, toBlock } = params\n\n // Get the latest block if not specified\n const latestBlock = toBlock ?? (await client.getBlockNumber())\n\n // Search for transactions from the account to the pool\n // We need to find dispatch() or dispatchFrom() calls\n // Note: This requires the account to have sent transactions directly,\n // or we need to look at internal transactions\n\n // Strategy: Look for OptionMinted or OptionBurnt events to find transactions,\n // then decode the transaction input to get the full position list\n\n const searchFromBlock = params.fromBlock ?? 0n\n if (latestBlock < searchFromBlock) return null\n\n // Fast path: a single getLogs per event type over the entire\n // [searchFromBlock, latest] range. The queries are filtered by `address` and\n // an indexed account topic, so providers like Alchemy impose no block-range\n // cap on them (only a result-count cap) — one call per event type is enough\n // and the returned set is already complete, so there are no older windows to\n // scan. This avoids walking the whole chain in 10k-block chunks (4 getLogs\n // per chunk), which for accounts with no history is thousands of empty calls.\n try {\n const events = await getSnapshotEventsForWindow({\n client,\n poolAddress,\n account,\n fromBlock: searchFromBlock,\n toBlock: latestBlock,\n })\n return await recoverSnapshotFromEvents({ client, account, events })\n } catch (error) {\n // Only fall back to windowed scanning when the provider rejected the wide\n // range. Any other error (e.g. transport failure) should propagate.\n if (!isRangeLimitError(error)) throw error\n }\n\n // Fallback for providers that cap getLogs block range: scan newest-to-oldest\n // in 10k-block windows and stop at the first window that yields a snapshot.\n let windowToBlock = latestBlock\n while (true) {\n const windowFromBlock =\n windowToBlock - searchFromBlock + 1n > LOG_SCAN_WINDOW\n ? windowToBlock - LOG_SCAN_WINDOW + 1n\n : searchFromBlock\n\n const events = await getSnapshotEventsForWindow({\n client,\n poolAddress,\n account,\n fromBlock: windowFromBlock,\n toBlock: windowToBlock,\n })\n const snapshot = await recoverSnapshotFromEvents({ client, account, events })\n if (snapshot) return snapshot\n\n if (windowFromBlock === searchFromBlock) break\n windowToBlock = windowFromBlock - 1n\n }\n\n // No snapshot found\n return null\n}\n\n/**\n * Detect provider errors that indicate the requested getLogs block range was\n * too wide (so the caller should retry with smaller windows). Covers the common\n * phrasings used by Alchemy, Infura, and other JSON-RPC providers.\n */\nfunction isRangeLimitError(error: unknown): boolean {\n const parts: string[] = []\n let current: unknown = error\n let depth = 0\n while (current && typeof current === 'object' && depth < 5) {\n const obj = current as Record<string, unknown>\n if (typeof obj.message === 'string') parts.push(obj.message)\n if (typeof obj.details === 'string') parts.push(obj.details)\n current = obj.cause\n depth += 1\n }\n if (typeof error === 'string') parts.push(error)\n\n const message = parts.join(' ').toLowerCase()\n if (!message) return false\n\n return (\n message.includes('block range') ||\n message.includes('range is too large') ||\n message.includes('range too large') ||\n message.includes('query returned more than') ||\n message.includes('too many results') ||\n message.includes('log response size exceeded') ||\n message.includes('exceeds the limit') ||\n (message.includes('range') && message.includes('limit'))\n )\n}\n\nasync function getSnapshotEventsForWindow(params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n fromBlock: bigint\n toBlock: bigint\n}): Promise<SnapshotEventLog[]> {\n const { client, poolAddress, account, fromBlock, toBlock } = params\n\n // OptionMinted/OptionBurnt cover the account's own dispatches.\n // ForcedExercised/AccountLiquidated cover third-party dispatchFrom calls\n // where the tx sender is not the account but calldata contains the final list.\n const [mintEvents, burnEvents, forceExerciseEvents, liquidationEvents] = 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,\n toBlock,\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: 'uint128', name: 'positionSize', indexed: false },\n { type: 'uint256', name: 'tokenId', indexed: true },\n { type: 'int256[4]', name: 'premiaByLeg', indexed: false },\n ],\n },\n args: {\n recipient: account,\n },\n fromBlock,\n toBlock,\n }),\n client.getLogs({\n address: poolAddress,\n event: {\n type: 'event',\n name: 'ForcedExercised',\n inputs: [\n { type: 'address', name: 'exercisor', indexed: true },\n { type: 'address', name: 'user', indexed: true },\n { type: 'uint256', name: 'tokenId', indexed: true },\n { type: 'int256', name: 'exerciseFee', indexed: false },\n ],\n },\n args: {\n user: account,\n },\n fromBlock,\n toBlock,\n }),\n client.getLogs({\n address: poolAddress,\n event: {\n type: 'event',\n name: 'AccountLiquidated',\n inputs: [\n { type: 'address', name: 'liquidator', indexed: true },\n { type: 'address', name: 'liquidatee', indexed: true },\n { type: 'int256', name: 'bonusAmounts', indexed: false },\n ],\n },\n args: {\n liquidatee: account,\n },\n fromBlock,\n toBlock,\n }),\n ])\n\n return [...mintEvents, ...burnEvents, ...forceExerciseEvents, ...liquidationEvents]\n}\n\nasync function recoverSnapshotFromEvents(params: {\n client: PublicClient\n account: Address\n events: SnapshotEventLog[]\n}): Promise<SnapshotRecoveryResult | null> {\n const { client, account, events } = params\n\n // Combine and sort by block number (descending) to get most recent first\n const allEvents = events.filter(isSnapshotCandidateEvent).sort((a, b) => {\n const blockDiff = Number(b.blockNumber - a.blockNumber)\n if (blockDiff !== 0) return blockDiff\n return Number(b.logIndex - a.logIndex)\n })\n\n // Deduplicate by transaction hash — multiple events from the same tx\n // (e.g. OptionMinted for each leg) would produce duplicate entries\n const seen = new Set<string>()\n const uniqueEvents = allEvents.filter((e) => {\n if (seen.has(e.transactionHash)) return false\n seen.add(e.transactionHash)\n return true\n })\n\n // Find the most recent transaction with position data\n for (const event of uniqueEvents) {\n try {\n const [tx, block] = await Promise.all([\n client.getTransaction({ hash: event.transactionHash }),\n client.getBlock({ blockNumber: event.blockNumber }),\n ])\n\n // A single tx (e.g. a force-exercise multicall) can embed several\n // dispatch/dispatchFrom calls — the exercisor's own dispatch alongside the\n // victim's dispatchFrom. Select a strict account match first, then allow a\n // plain dispatch only because this tx came from an account-indexed event.\n const candidates = decodeAllDispatchCalldata(tx.input)\n const decoded =\n selectDispatchForAccount(candidates, account, tx.from) ??\n selectDispatchProvenByAccountEvent(candidates)\n if (!decoded) {\n continue\n }\n\n return {\n success: true,\n positionIds: decoded.positionIds,\n blockNumber: event.blockNumber,\n blockHash: block.hash,\n transactionHash: event.transactionHash,\n }\n } catch {\n // Transaction fetch failed, continue\n }\n }\n\n return null\n}\n\nfunction isSnapshotCandidateEvent(event: SnapshotEventLog): event is SnapshotCandidateEvent {\n return event.transactionHash !== null && event.blockNumber !== null && event.logIndex !== null\n}\n\n/**\n * Parameters for recovering a snapshot from a known transaction hash.\n */\nexport interface RecoverSnapshotFromTxParams {\n /** viem public client */\n client: PublicClient\n /** Transaction hash of a known dispatch() call */\n transactionHash: Hash\n /** Account to verify. When set, rejects transactions not sent by (or targeting) this account. */\n account?: Address\n /** Pool address to validate against. When set, rejects transactions not sent to this pool. */\n pool?: Address\n}\n\n/**\n * Recover position snapshot from a specific dispatch transaction hash.\n *\n * This is an O(1) alternative to {@link recoverSnapshot} when you already\n * know the tx hash of the most recent dispatch. It fetches the transaction,\n * decodes the `finalPositionIdList` from the calldata, and returns the result\n * — no event scanning required.\n *\n * @param params - Recovery parameters including the transaction hash\n * @returns Snapshot recovery result, or null if the tx is not a dispatch call\n *\n * @example\n * ```typescript\n * const snapshot = await recoverSnapshotFromTx({\n * client,\n * transactionHash: '0xabc...',\n * })\n * if (snapshot) {\n * console.log('Open positions:', snapshot.positionIds)\n * }\n * ```\n */\nexport async function recoverSnapshotFromTx(\n params: RecoverSnapshotFromTxParams,\n): Promise<SnapshotRecoveryResult | null> {\n const { client, transactionHash, account, pool } = params\n\n const tx = await client.getTransaction({ hash: transactionHash })\n\n // Pending transactions have no block number — cannot recover snapshot\n if (tx.blockNumber == null) return null\n\n // Validate pool: transaction must have been sent to the expected pool address\n if (pool && tx.to?.toLowerCase() !== pool.toLowerCase()) {\n return null\n }\n\n const candidates = decodeAllDispatchCalldata(tx.input)\n if (candidates.length === 0) return null\n\n // Validate account context:\n // - dispatch: tx.from must be the account (msg.sender is the trader)\n // - dispatchFrom: decoded.targetAccount must be the account (builder sends on behalf of trader)\n // A tx may embed several dispatch calls (e.g. a force-exercise multicall carrying both\n // the exercisor's dispatch and the victim's dispatchFrom); pick the one for `account`.\n const decoded = account\n ? selectDispatchForAccount(candidates, account, tx.from)\n : candidates[candidates.length - 1]\n if (!decoded) return null\n\n const blockNumber = tx.blockNumber\n const block = await client.getBlock({ blockNumber })\n\n return {\n success: true,\n positionIds: decoded.positionIds,\n blockNumber,\n blockHash: block.hash,\n transactionHash,\n }\n}\n\n/**\n * Decoded dispatch calldata result.\n */\nexport interface DispatchCalldata {\n /** Final position ID list after the dispatch */\n positionIds: bigint[]\n /** Target account (only set for dispatchFrom) */\n targetAccount?: Address\n}\n\n/**\n * Decode position IDs from dispatch calldata.\n *\n * When the tx embeds multiple dispatch/dispatchFrom calls (e.g. a force-exercise\n * multicall), this returns the last one — prefer {@link decodeAllDispatchCalldata}\n * plus {@link selectDispatchForAccount} when the account context matters.\n *\n * @param input - Transaction input data\n * @returns Decoded dispatch data or null if not a dispatch call\n */\nexport function decodeDispatchCalldata(input: `0x${string}`): DispatchCalldata | null {\n const all = decodeAllDispatchCalldata(input)\n return all.length > 0 ? all[all.length - 1] : null\n}\n\n/**\n * Decode every dispatch/dispatchFrom call embedded in transaction calldata.\n *\n * A single tx can carry more than one such call — most importantly a force-exercise\n * `multicall` that bundles the exercisor's own `dispatch` together with the victim's\n * `dispatchFrom`. Returning all candidates lets the caller select the one attributable\n * to the relevant account ({@link selectDispatchForAccount}).\n *\n * @param input - Transaction input data\n * @returns All decoded dispatch calls, in calldata order (may be empty)\n */\nexport function decodeAllDispatchCalldata(input: `0x${string}`): DispatchCalldata[] {\n // Try direct dispatch/dispatchFrom first\n const direct = decodeDirectDispatch(input)\n if (direct) return [direct]\n\n // Try unwrapping smart contract wallet wrappers (executeBatch, execute, multicall)\n return decodeWrappedDispatch(input)\n}\n\n/**\n * Select the dispatch call attributable to `account` from a set of candidates.\n *\n * - `dispatchFrom`: matches when `targetAccount === account` (builder/exercisor acting\n * on behalf of the account).\n * - `dispatch` (no `targetAccount`): matches only when the tx sender is the account.\n *\n * Returns the LAST matching candidate (in calldata order), or null when none are\n * attributable to `account`. The last dispatch reflects the final post-transaction\n * state when a single tx contains multiple dispatches for the same account (e.g. a\n * multicall). Matching also prevents accepting a third party's `dispatch` (e.g. the\n * exercisor's own, bundled in a force-exercise multicall) as the account's snapshot.\n *\n * @param candidates - Decoded dispatch calls from a single tx, in calldata order\n * @param account - Account whose position list we are recovering\n * @param txFrom - The transaction sender (`tx.from`)\n */\nexport function selectDispatchForAccount(\n candidates: DispatchCalldata[],\n account: Address,\n txFrom: Address,\n): DispatchCalldata | null {\n const acct = account.toLowerCase()\n let match: DispatchCalldata | null = null\n for (const candidate of candidates) {\n if (candidate.targetAccount) {\n if (candidate.targetAccount.toLowerCase() === acct) match = candidate\n } else if (txFrom.toLowerCase() === acct) {\n match = candidate\n }\n }\n return match\n}\n\nfunction selectDispatchProvenByAccountEvent(\n candidates: DispatchCalldata[],\n): DispatchCalldata | null {\n let match: DispatchCalldata | null = null\n for (const candidate of candidates) {\n if (candidate.targetAccount === undefined) match = candidate\n }\n return match\n}\n\n/**\n * Try to decode input as a direct dispatch or dispatchFrom call.\n */\nfunction decodeDirectDispatch(input: `0x${string}`): DispatchCalldata | null {\n try {\n const decoded = decodeFunctionData({\n abi: panopticPoolV2Abi,\n data: input,\n })\n\n if (decoded.functionName === 'dispatch') {\n const args = decoded.args as readonly [\n bigint[],\n bigint[],\n bigint[],\n readonly [number, number, number][],\n boolean,\n bigint,\n ]\n return { positionIds: [...args[1]] } // finalPositionIdList\n }\n\n if (decoded.functionName === 'dispatchFrom') {\n const args = decoded.args as readonly [bigint[], Address, bigint[], bigint[], bigint]\n return {\n positionIds: [...args[3]], // positionIdListToFinal\n targetAccount: args[1],\n }\n }\n\n return null\n } catch {\n return null\n }\n}\n\n/**\n * 4-byte function selectors for dispatch/dispatchFrom, derived from the generated ABI.\n * Used for scanning raw calldata inside smart contract wallet wrappers.\n */\nconst DISPATCH_SELECTOR = toFunctionSelector(\n panopticPoolV2Abi.find((e) => e.type === 'function' && e.name === 'dispatch') as AbiFunction,\n).slice(2) // strip 0x prefix for hex scanning\n\nconst DISPATCH_FROM_SELECTOR = toFunctionSelector(\n panopticPoolV2Abi.find((e) => e.type === 'function' && e.name === 'dispatchFrom') as AbiFunction,\n).slice(2)\n\n/**\n * Scan raw transaction input for embedded dispatch calldata.\n *\n * Smart contract wallets (Safe, Turnkey, ERC-4337) and vault managers\n * wrap dispatch calls inside executeBatch → manage → dispatch chains.\n * Instead of decoding each wrapper layer, we scan the raw hex for the\n * dispatch function selector and attempt to decode from that offset.\n *\n * This handles arbitrary nesting depth without knowing wrapper ABIs.\n */\nfunction decodeWrappedDispatch(input: `0x${string}`): DispatchCalldata[] {\n const hex = input.slice(2).toLowerCase()\n const selectors = [DISPATCH_SELECTOR, DISPATCH_FROM_SELECTOR]\n\n // Single left-to-right pass: find the earliest selector match at each offset and\n // collect every successful decode, in calldata order. The caller selects the call\n // attributable to the relevant account rather than blindly taking one.\n const results: DispatchCalldata[] = []\n let offset = 0\n\n while (offset < hex.length) {\n // Find the nearest selector match from current offset\n let earliestIdx = -1\n for (const selector of selectors) {\n const idx = hex.indexOf(selector, offset)\n if (idx !== -1 && (earliestIdx === -1 || idx < earliestIdx)) {\n earliestIdx = idx\n }\n }\n if (earliestIdx === -1) break\n\n const candidate = `0x${hex.slice(earliestIdx)}` as `0x${string}`\n const result = decodeDirectDispatch(candidate)\n if (result) results.push(result)\n\n offset = earliestIdx + 8 // Move past this selector\n }\n\n return results\n}\n","/**\n * Get tracked position IDs from local cache.\n * @module v2/sync/getTrackedPositionIds\n */\n\nimport type { Address, Hash, PublicClient } from 'viem'\n\nimport type { StorageAdapter } from '../storage'\nimport { getPositionsKey, jsonSerializer } from '../storage'\nimport {\n type SnapshotRecoveryResult,\n recoverSnapshot,\n recoverSnapshotFromTx,\n} from './snapshotRecovery'\n\n/**\n * Parameters for getTrackedPositionIds.\n */\nexport interface GetTrackedPositionIdsParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account to get positions for */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n}\n\n/**\n * Get all tracked position IDs for an account from local cache.\n *\n * This function reads from the storage adapter without making RPC calls.\n * The positions returned may include closed positions if the cache is stale.\n * Use `getPositions()` for authoritative on-chain data.\n *\n * @param params - Query parameters\n * @returns Array of position token IDs\n */\nexport async function getTrackedPositionIds(\n params: GetTrackedPositionIdsParams,\n): Promise<bigint[]> {\n const { chainId, poolAddress, account, storage } = params\n\n const key = getPositionsKey(chainId, poolAddress, account)\n const data = await storage.get(key)\n\n if (!data) {\n return []\n }\n\n try {\n const positionIds = jsonSerializer.parse(data) as bigint[]\n return positionIds\n } catch {\n // Corrupted data, return empty\n return []\n }\n}\n\n/**\n * Check if a specific position ID is tracked.\n *\n * @param params - Query parameters\n * @param tokenId - Token ID to check\n * @returns Whether the position is tracked\n */\nexport async function isPositionTracked(\n params: GetTrackedPositionIdsParams,\n tokenId: bigint,\n): Promise<boolean> {\n const positionIds = await getTrackedPositionIds(params)\n return positionIds.some((id) => id === tokenId)\n}\n\n/**\n * Clear all tracked positions for an account.\n *\n * @param params - Query parameters\n */\nexport async function clearTrackedPositions(params: GetTrackedPositionIdsParams): Promise<void> {\n const { chainId, poolAddress, account, storage } = params\n\n const key = getPositionsKey(chainId, poolAddress, account)\n await storage.delete(key)\n}\n\n/**\n * Parameters for getOpenPositionIds.\n */\nexport interface GetOpenPositionIdsParams {\n /** viem PublicClient */\n client: PublicClient\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account to get positions for */\n account: Address\n /** Storage adapter (used to update local cache with the authoritative list) */\n storage?: StorageAdapter\n /**\n * Transaction hash of a known dispatch() call. When provided, the position\n * list is decoded directly from this tx's calldata (O(1)) instead of\n * scanning events to find the most recent dispatch.\n */\n lastDispatchTxHash?: Hash\n /**\n * Starting block for event scanning in recoverSnapshot.\n * When set, limits the getLogs window to [fromBlock, latest] instead of\n * scanning from block 0. Use the checkpoint's lastBlock for incremental syncs.\n */\n fromBlock?: bigint\n}\n\n/**\n * Get the authoritative list of open position IDs from the chain.\n *\n * Recovers the `finalPositionIdList` from the account's most recent\n * `dispatch()` transaction calldata. This is the on-chain–validated set of\n * open positions (verified against `s_positionsHash` by the contract) and\n * requires only a few RPC calls regardless of account history length.\n *\n * This is the recommended way to get position IDs for `existingPositionIds`\n * (openPosition) and `positionIdList` (closePosition).\n *\n * If `storage` is provided, the local cache is updated with the result.\n *\n * @param params - Query parameters\n * @returns Array of currently open position token IDs, or null if no snapshot was found\n */\nexport async function getOpenPositionIds(\n params: GetOpenPositionIdsParams,\n): Promise<bigint[] | null> {\n const { client, chainId, poolAddress, account, storage, lastDispatchTxHash, fromBlock } = params\n\n // Fast path: decode directly from a known tx hash (O(1), no event scanning)\n // Falls back to full event-scanning recovery if the fast path returns null or throws\n let snapshot: SnapshotRecoveryResult | null = null\n if (lastDispatchTxHash) {\n try {\n snapshot = await recoverSnapshotFromTx({\n client,\n transactionHash: lastDispatchTxHash,\n account,\n pool: poolAddress,\n })\n } catch {\n // Fast path failed (e.g. RPC error, validation mismatch); fall through to slow-path\n snapshot = null\n }\n }\n\n if (!snapshot) {\n snapshot = await recoverSnapshot({ client, poolAddress, account, fromBlock })\n }\n\n if (!snapshot) {\n return null\n }\n\n // Update local cache if storage provided\n if (storage) {\n const key = getPositionsKey(chainId, poolAddress, account)\n await storage.set(key, jsonSerializer.stringify(snapshot.positionIds))\n }\n\n return snapshot.positionIds\n}\n","/**\n * Position operations for the Panoptic v2 SDK.\n * @module v2/writes/position\n */\n\nimport type { Address, Hex, PublicClient, WalletClient } from 'viem'\nimport { encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { InvalidTickLimitsError, MissingPositionIdsError } from '../errors'\nimport type { StorageAdapter } from '../storage'\nimport { getPositionsKey, jsonSerializer } from '../storage'\nimport { getTrackedPositionIds } from '../sync/getTrackedPositionIds'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\n/**\n * Optional storage parameters for auto-tracking positions.\n * When provided, `*AndWait` variants will automatically update the local\n * position cache after a successful transaction.\n */\nexport interface PositionStorageParams {\n /** Storage adapter for position tracking */\n storage: StorageAdapter\n /** Chain ID (required for storage key construction) */\n chainId: bigint\n}\n\n/**\n * Resolve the position ID list: use the explicit param if provided,\n * otherwise read from storage. Throws if neither is available.\n */\nasync function resolvePositionIds(\n explicit: bigint[] | undefined,\n storage: StorageAdapter | undefined,\n chainId: bigint | undefined,\n poolAddress: Address,\n account: Address,\n): Promise<bigint[]> {\n if (explicit !== undefined) return explicit\n if (storage && chainId !== undefined) {\n return getTrackedPositionIds({ chainId, poolAddress, account, storage })\n }\n throw new MissingPositionIdsError()\n}\n\n/**\n * Save a position ID list to storage.\n */\nasync function savePositionIds(\n storage: StorageAdapter,\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n positionIds: bigint[],\n): Promise<void> {\n const key = getPositionsKey(chainId, poolAddress, account)\n await storage.set(key, jsonSerializer.stringify(positionIds))\n}\n\n/**\n * Tick and spread limits for position operations.\n * [tickLimitLow, tickLimitHigh, spreadLimitTick]\n *\n * SDK uses bigint for all numerics. Converted to number at viem boundary.\n *\n * @deprecated Use individual tickLimitLow, tickLimitHigh, spreadLimit params with swapAtMint flag\n */\nexport type TickAndSpreadLimits = readonly [bigint, bigint, bigint]\n\n/**\n * Parameters for opening a position.\n */\nexport interface OpenPositionParams extends Partial<PositionStorageParams> {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Existing position IDs held by the account (before this mint). Optional if storage + chainId are provided. */\n existingPositionIds?: bigint[]\n /** TokenId of the position to open */\n tokenId: bigint\n /** Position size (number of contracts) */\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 mint 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 (defaults to 0) */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Open a new position using dispatch.\n *\n * @param params - Position parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * import { MIN_TICK, MAX_TICK } from '@panoptic/sdk'\n *\n * const result = await openPosition({\n * client,\n * walletClient,\n * account,\n * poolAddress,\n * existingPositionIds: [], // Existing positions held before this mint\n * tokenId,\n * positionSize: 1n,\n * tickLimitLow: MIN_TICK,\n * tickLimitHigh: MAX_TICK,\n * swapAtMint: false, // true for covered/single-sided exposure\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function openPosition(params: OpenPositionParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n existingPositionIds: explicitIds,\n tokenId,\n positionSize,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit = 0n,\n swapAtMint = false,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n storage,\n chainId,\n txOverrides,\n } = params\n\n // Validate tick limits\n if (tickLimitLow > tickLimitHigh) {\n throw new InvalidTickLimitsError(tickLimitLow, tickLimitHigh)\n }\n\n const existingPositionIds = await resolvePositionIds(\n explicitIds,\n storage,\n chainId,\n poolAddress,\n account,\n )\n\n // Prepare position lists for dispatch:\n // - positionIdList: positions being minted in this call (just the new tokenId)\n // - finalPositionIdList: all positions the user will have after the mint\n const positionIdList = [tokenId]\n const finalPositionIdList = [...existingPositionIds, tokenId]\n\n // Position sizes array contains the size for the new position\n const positionSizes = [positionSize]\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 return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n positionSizes,\n [tickLimits],\n usePremiaAsCollateral,\n builderCode,\n ],\n txOverrides,\n })\n}\n\n/**\n * Build the dispatch calldata for opening a position without executing.\n * Returns the target address and encoded calldata, suitable for manual\n * transaction construction (e.g. RFQ broadcast-reconstruct flow).\n *\n * @param params - Position parameters (existingPositionIds required, no storage resolution)\n * @returns { to, data } — contract address and encoded dispatch calldata\n */\nexport function buildOpenPositionCalldata(params: {\n poolAddress: Address\n existingPositionIds: bigint[]\n tokenId: bigint\n positionSize: bigint\n tickLimitLow: bigint\n tickLimitHigh: bigint\n spreadLimit?: bigint\n swapAtMint?: boolean\n usePremiaAsCollateral?: boolean\n builderCode?: bigint\n}): { to: Address; data: Hex } {\n const {\n poolAddress,\n existingPositionIds,\n tokenId,\n positionSize,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit = 0n,\n swapAtMint = false,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n } = params\n\n if (tickLimitLow > tickLimitHigh) {\n throw new InvalidTickLimitsError(tickLimitLow, tickLimitHigh)\n }\n\n const positionIdList = [tokenId]\n const finalPositionIdList = [...existingPositionIds, tokenId]\n const positionSizes = [positionSize]\n\n const tickLimits: readonly [number, number, number] = swapAtMint\n ? [Number(tickLimitHigh), Number(tickLimitLow), Number(spreadLimit)]\n : [Number(tickLimitLow), Number(tickLimitHigh), Number(spreadLimit)]\n\n const data = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n positionSizes,\n [tickLimits],\n usePremiaAsCollateral,\n builderCode,\n ],\n })\n\n return { to: poolAddress, data }\n}\n\n/**\n * Open position and wait for confirmation.\n */\nexport async function openPositionAndWait(params: OpenPositionParams): Promise<TxReceipt> {\n const result = await openPosition(params)\n const receipt = await result.wait()\n\n // Auto-update storage if provided\n const {\n storage,\n chainId,\n account,\n poolAddress,\n tokenId,\n existingPositionIds: explicitIds,\n } = params\n if (storage && chainId !== undefined) {\n const base =\n explicitIds ?? (await getTrackedPositionIds({ chainId, poolAddress, account, storage }))\n await savePositionIds(storage, chainId, poolAddress, account, [...base, tokenId])\n }\n\n return receipt\n}\n\n/**\n * Parameters for closing a position.\n */\nexport interface ClosePositionParams extends Partial<PositionStorageParams> {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Current position ID list. Optional if storage + chainId are provided. */\n positionIdList?: bigint[]\n /** TokenId of the position to close */\n tokenId: bigint\n /** Position size to close (use full size for complete 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 (defaults to 0) */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Close an existing position using dispatch.\n *\n * @param params - Close parameters\n * @returns TxResult\n */\nexport async function closePosition(params: ClosePositionParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n positionIdList: explicitList,\n tokenId,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit = 0n,\n swapAtMint = false,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n storage,\n chainId,\n txOverrides,\n } = params\n\n // Validate tick limits\n if (tickLimitLow > tickLimitHigh) {\n throw new InvalidTickLimitsError(tickLimitLow, tickLimitHigh)\n }\n\n const positionIdList = await resolvePositionIds(\n explicitList,\n storage,\n chainId,\n poolAddress,\n account,\n )\n\n // For closing, final list excludes the closed position\n const finalPositionIdList = positionIdList.filter((id) => id !== 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 ? [Number(tickLimitHigh), Number(tickLimitLow), Number(spreadLimit)]\n : [Number(tickLimitLow), Number(tickLimitHigh), Number(spreadLimit)]\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [[tokenId], finalPositionIdList, [0n], [tickLimits], usePremiaAsCollateral, builderCode],\n txOverrides,\n })\n}\n\n/**\n * Close position and wait for confirmation.\n */\nexport async function closePositionAndWait(params: ClosePositionParams): Promise<TxReceipt> {\n const result = await closePosition(params)\n const receipt = await result.wait()\n\n // Auto-update storage if provided\n const { storage, chainId, account, poolAddress, tokenId, positionIdList: explicitList } = params\n if (storage && chainId !== undefined) {\n const base =\n explicitList ?? (await getTrackedPositionIds({ chainId, poolAddress, account, storage }))\n await savePositionIds(\n storage,\n chainId,\n poolAddress,\n account,\n base.filter((id) => id !== tokenId),\n )\n }\n\n return receipt\n}\n\n/**\n * Parameters for rolling a position.\n */\nexport interface RollPositionParams extends Partial<PositionStorageParams> {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Current position ID list. Optional if storage + chainId are provided. */\n positionIdList?: bigint[]\n /** TokenId of position to close */\n oldTokenId: bigint\n /** Size of position being closed */\n oldPositionSize: bigint\n /** TokenId of new position to open */\n newTokenId: bigint\n /** Size of new position */\n newPositionSize: bigint\n /** Lower tick limit for close (always <= closeTickLimitHigh) */\n closeTickLimitLow: bigint\n /** Upper tick limit for close (always >= closeTickLimitLow) */\n closeTickLimitHigh: bigint\n /** Spread limit for close (use 0n for no spread limit) */\n closeSpreadLimit?: bigint\n /** Whether to swap tokens when closing */\n closeSwapAtMint?: boolean\n /** Lower tick limit for open (always <= openTickLimitHigh) */\n openTickLimitLow: bigint\n /** Upper tick limit for open (always >= openTickLimitLow) */\n openTickLimitHigh: bigint\n /** Spread limit for open (use 0n for no spread limit) */\n openSpreadLimit?: bigint\n /** Whether to swap tokens when opening */\n openSwapAtMint?: boolean\n /** Whether to use premia as collateral */\n usePremiaAsCollateral?: boolean\n /** Builder code */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Roll a position (close one, open another) in a single transaction.\n *\n * @param params - Roll parameters\n * @returns TxResult\n */\nexport async function rollPosition(params: RollPositionParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n positionIdList: explicitList,\n oldTokenId,\n oldPositionSize,\n newTokenId,\n newPositionSize,\n closeTickLimitLow,\n closeTickLimitHigh,\n closeSpreadLimit = 0n,\n closeSwapAtMint = false,\n openTickLimitLow,\n openTickLimitHigh,\n openSpreadLimit = 0n,\n openSwapAtMint = false,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n storage,\n chainId,\n txOverrides,\n } = params\n\n // Validate tick limits\n if (closeTickLimitLow > closeTickLimitHigh) {\n throw new InvalidTickLimitsError(closeTickLimitLow, closeTickLimitHigh)\n }\n if (openTickLimitLow > openTickLimitHigh) {\n throw new InvalidTickLimitsError(openTickLimitLow, openTickLimitHigh)\n }\n\n const positionIdList = await resolvePositionIds(\n explicitList,\n storage,\n chainId,\n poolAddress,\n account,\n )\n\n // Final list: remove old, add new\n const finalPositionIdList = positionIdList.filter((id) => id !== oldTokenId).concat([newTokenId])\n\n // Position sizes for both operations\n const positionSizes = [oldPositionSize, newPositionSize]\n\n // Build tick limits based on swapAtMint flags\n const closeLimits: readonly [number, number, number] = closeSwapAtMint\n ? [Number(closeTickLimitHigh), Number(closeTickLimitLow), Number(closeSpreadLimit)]\n : [Number(closeTickLimitLow), Number(closeTickLimitHigh), Number(closeSpreadLimit)]\n\n const openLimits: readonly [number, number, number] = openSwapAtMint\n ? [Number(openTickLimitHigh), Number(openTickLimitLow), Number(openSpreadLimit)]\n : [Number(openTickLimitLow), Number(openTickLimitHigh), Number(openSpreadLimit)]\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n positionSizes as bigint[],\n [closeLimits, openLimits],\n usePremiaAsCollateral,\n builderCode,\n ],\n txOverrides,\n })\n}\n\n/**\n * Roll position and wait for confirmation.\n */\nexport async function rollPositionAndWait(params: RollPositionParams): Promise<TxReceipt> {\n const result = await rollPosition(params)\n const receipt = await result.wait()\n\n // Auto-update storage if provided\n const {\n storage,\n chainId,\n account,\n poolAddress,\n oldTokenId,\n newTokenId,\n positionIdList: explicitList,\n } = params\n if (storage && chainId !== undefined) {\n const base =\n explicitList ?? (await getTrackedPositionIds({ chainId, poolAddress, account, storage }))\n const updated = base.filter((id) => id !== oldTokenId).concat([newTokenId])\n await savePositionIds(storage, chainId, poolAddress, account, updated)\n }\n\n return receipt\n}\n","/**\n * Raw dispatch function for the Panoptic v2 SDK.\n * @module v2/writes/dispatch\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport type { TickAndSpreadLimits } from './position'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for dispatch function.\n */\nexport interface DispatchParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Current position ID list */\n positionIdList: bigint[]\n /** Final position ID list after operations */\n finalPositionIdList: 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 /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Execute a raw dispatch operation.\n * This is the low-level function for multi-position operations.\n *\n * @param params - Dispatch parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * // Open multiple positions atomically\n * const result = await dispatch({\n * client,\n * walletClient,\n * account,\n * poolAddress,\n * positionIdList: [],\n * finalPositionIdList: [tokenId1, tokenId2],\n * positionSizes: [size1, size2],\n * tickAndSpreadLimits: [limits1, limits2],\n * })\n * ```\n */\nexport async function dispatch(params: DispatchParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n positionIdList,\n finalPositionIdList,\n positionSizes,\n tickAndSpreadLimits,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\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 usePremiaAsCollateral,\n builderCode,\n ],\n txOverrides,\n })\n}\n\n/**\n * Execute dispatch and wait for confirmation.\n */\nexport async function dispatchAndWait(params: DispatchParams): Promise<TxReceipt> {\n const result = await dispatch(params)\n return result.wait()\n}\n","/**\n * Pure validator for batched mint/burn dispatch operations.\n * @module v2/batch/validate\n */\n\nimport type { BatchDiagnostic, BatchOp } from './types'\n\nexport interface ValidateBatchParams {\n items: BatchOp[]\n /** Current on-chain positionIdList for the account. */\n existingPositionIds: bigint[]\n}\n\n/**\n * Run all batch-level and item-level validations.\n * Pure function; never throws. Empty array means \"ready to build\".\n */\nexport function validateBatch(params: ValidateBatchParams): BatchDiagnostic[] {\n const { items, existingPositionIds } = params\n const diagnostics: BatchDiagnostic[] = []\n\n if (items.length === 0) {\n diagnostics.push({\n itemIndex: -1n,\n tokenId: 0n,\n code: 'empty-batch',\n message: 'Batch is empty.',\n })\n return diagnostics\n }\n\n const head = items[0]\n if (!head) return diagnostics\n const firstPool = head.poolAddress.toLowerCase()\n const existing = new Set(existingPositionIds)\n const seen = new Map<bigint, bigint>()\n\n items.forEach((item, idx) => {\n const itemIndex = BigInt(idx)\n if (item.poolAddress.toLowerCase() !== firstPool) {\n diagnostics.push({\n itemIndex,\n tokenId: item.tokenId,\n code: 'cross-pool',\n message: `Item ${idx} targets pool ${item.poolAddress}, expected ${head.poolAddress}.`,\n })\n }\n\n if (item.tickLimitLow > item.tickLimitHigh) {\n diagnostics.push({\n itemIndex,\n tokenId: item.tokenId,\n code: 'invalid-tick-limits',\n message: `Item ${idx} tickLimitLow (${item.tickLimitLow}) > tickLimitHigh (${item.tickLimitHigh}).`,\n })\n }\n\n if (item.kind === 'mint') {\n if (item.positionSize <= 0n) {\n diagnostics.push({\n itemIndex,\n tokenId: item.tokenId,\n code: 'invalid-position-size',\n message: `Mint at index ${idx} must have positionSize > 0.`,\n })\n }\n if (existing.has(item.tokenId)) {\n diagnostics.push({\n itemIndex,\n tokenId: item.tokenId,\n code: 'mint-already-onchain',\n message: `Mint at index ${idx} targets tokenId ${item.tokenId} which is already open on-chain.`,\n })\n }\n } else if (!existing.has(item.tokenId)) {\n diagnostics.push({\n itemIndex,\n tokenId: item.tokenId,\n code: 'burn-not-found',\n message: `Burn at index ${idx} targets tokenId ${item.tokenId} which is not in the account's positions.`,\n })\n }\n\n const prior = seen.get(item.tokenId)\n if (prior !== undefined) {\n diagnostics.push({\n itemIndex,\n tokenId: item.tokenId,\n code: 'duplicate-tokenid-in-batch',\n message: `Item ${idx} duplicates tokenId ${item.tokenId} also at index ${prior}.`,\n })\n } else {\n seen.set(item.tokenId, itemIndex)\n }\n })\n\n return diagnostics\n}\n","/**\n * Pure builder converting batched mint/burn ops into PanopticPool.dispatch() args.\n * @module v2/batch/build\n */\n\nimport type { TickAndSpreadLimits } from '../writes/position'\nimport type { BatchDiagnostic, BatchDispatchArgs, BatchOp } from './types'\nimport { validateBatch } from './validate'\n\nexport interface BuildBatchDispatchArgsParams {\n items: BatchOp[]\n /** Current on-chain positionIdList for the account. */\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}\n\nexport interface BuildBatchDispatchArgsResult {\n /** Null when diagnostics are non-empty. */\n args: BatchDispatchArgs | null\n diagnostics: BatchDiagnostic[]\n}\n\n/**\n * Build dispatch() args from a list of batch ops + the account's current\n * on-chain positionIdList. Returns diagnostics instead of throwing so callers\n * (UIs, bots) can render conflicts before deciding what to do.\n *\n * The order in `items` is preserved as the operation order in `positionIdList`,\n * `positionSizes`, and `tickAndSpreadLimits`. `finalPositionIdList` is the\n * post-execution state: existing minus burns, plus mints.\n */\nexport function buildBatchDispatchArgs(\n params: BuildBatchDispatchArgsParams,\n): BuildBatchDispatchArgsResult {\n const { items, existingPositionIds, usePremiaAsCollateral = false, builderCode = 0n } = params\n\n const diagnostics = validateBatch({ items, existingPositionIds })\n if (diagnostics.length > 0) {\n return { args: null, diagnostics }\n }\n\n const positionIdList = items.map((i) => i.tokenId)\n const positionSizes = items.map((i) => (i.kind === 'mint' ? i.positionSize : 0n))\n\n const tickAndSpreadLimits: TickAndSpreadLimits[] = items.map((i) => {\n const low = i.tickLimitLow <= i.tickLimitHigh ? i.tickLimitLow : i.tickLimitHigh\n const high = i.tickLimitLow <= i.tickLimitHigh ? i.tickLimitHigh : i.tickLimitLow\n const spread = i.kind === 'mint' ? i.spreadLimit : 0n\n return i.swapAtMint ? ([high, low, spread] as const) : ([low, high, spread] as const)\n })\n\n const mintIds = items.filter((i) => i.kind === 'mint').map((i) => i.tokenId)\n const burnIds = new Set(items.filter((i) => i.kind === 'burn').map((i) => i.tokenId))\n const mintIdSet = new Set(mintIds)\n const finalPositionIdList = [\n ...existingPositionIds.filter((id) => !burnIds.has(id) && !mintIdSet.has(id)),\n ...mintIds,\n ]\n\n return {\n args: {\n positionIdList,\n finalPositionIdList,\n positionSizes,\n tickAndSpreadLimits,\n usePremiaAsCollateral,\n builderCode,\n },\n diagnostics: [],\n }\n}\n","/**\n * Item-based wrapper around dispatch() for batched mint/burn ops.\n * @module v2/writes/executeBatchDispatch\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { buildBatchDispatchArgs } from '../batch/build'\nimport type { BatchOp } from '../batch/types'\nimport { BatchValidationError } from '../errors'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { dispatch } from './dispatch'\n\nexport interface ExecuteBatchDispatchParams {\n client: PublicClient\n walletClient: WalletClient\n account: Address\n poolAddress: 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 txOverrides?: TxOverrides\n}\n\n/**\n * Build dispatch args from a batch and submit them as a single transaction.\n *\n * Throws `BatchValidationError` (with the full diagnostics list) when the batch\n * fails validation. Callers that want to render diagnostics in UI should run\n * `buildBatchDispatchArgs` or `simulateBatchDispatch` first.\n */\nexport async function executeBatchDispatch(params: ExecuteBatchDispatchParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n items,\n existingPositionIds,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n txOverrides,\n } = params\n\n const { args, diagnostics } = buildBatchDispatchArgs({\n items,\n existingPositionIds,\n usePremiaAsCollateral,\n builderCode,\n })\n\n if (args === null) {\n throw new BatchValidationError(diagnostics)\n }\n\n return dispatch({\n client,\n walletClient,\n account,\n poolAddress,\n positionIdList: args.positionIdList,\n finalPositionIdList: args.finalPositionIdList,\n positionSizes: args.positionSizes,\n tickAndSpreadLimits: args.tickAndSpreadLimits,\n usePremiaAsCollateral: args.usePremiaAsCollateral,\n builderCode: args.builderCode,\n txOverrides,\n })\n}\n\n/**\n * Execute a batch dispatch and wait for confirmation.\n */\nexport async function executeBatchDispatchAndWait(\n params: ExecuteBatchDispatchParams,\n): Promise<TxReceipt> {\n const result = await executeBatchDispatch(params)\n return result.wait()\n}\n","/**\n * Liquidation functions for the Panoptic v2 SDK.\n * @module v2/writes/liquidate\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for liquidating an account.\n */\nexport interface LiquidateParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Liquidator account address */\n account: Address\n /** PanopticPool address */\n poolAddress: 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 (positions to liquidate) */\n positionIdListTo: bigint[]\n /** Final position ID list for the liquidatee after liquidation */\n positionIdListToFinal: bigint[]\n /** Packed value for using premia as collateral */\n usePremiaAsCollateral?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Liquidate an undercollateralized account using dispatchFrom.\n *\n * The liquidator calls dispatchFrom to close the liquidatee's positions\n * and receive a bonus.\n *\n * @param params - Liquidation parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await liquidate({\n * client,\n * walletClient,\n * account: liquidatorAddress,\n * poolAddress,\n * liquidatee: undercollateralizedAccount,\n * positionIdListFrom: liquidatorPositions,\n * positionIdListTo: liquidateePositions,\n * positionIdListToFinal: [], // Close all positions\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function liquidate(params: LiquidateParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n liquidatee,\n positionIdListFrom,\n positionIdListTo,\n positionIdListToFinal,\n usePremiaAsCollateral = 0n,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatchFrom',\n args: [\n positionIdListFrom,\n liquidatee,\n positionIdListTo,\n positionIdListToFinal,\n usePremiaAsCollateral,\n ],\n txOverrides,\n })\n}\n\n/**\n * Liquidate and wait for confirmation.\n */\nexport async function liquidateAndWait(params: LiquidateParams): Promise<TxReceipt> {\n const result = await liquidate(params)\n return result.wait()\n}\n","/**\n * Bot utilities for the Panoptic v2 SDK.\n *\n * Assertion functions for validating preconditions before executing operations.\n * These throw typed errors on failure, making bot code cleaner and failures explicit.\n *\n * @module v2/bot\n */\n\nimport { SafeModeError, StaleDataError, UnhealthyPoolError } from '../errors'\nimport type { BlockMeta, Pool, SafeModeState } from '../types'\n\n/**\n * Data with block metadata (anything returned by SDK read functions).\n */\nexport interface DataWithMeta {\n _meta: BlockMeta\n}\n\n/**\n * Assert that data is fresh (not stale).\n *\n * Throws StaleDataError if the data's block timestamp is older than maxAgeSeconds.\n *\n * @param data - Any SDK data with _meta field\n * @param maxAgeSeconds - Maximum allowed age in seconds\n * @param currentTimestamp - Current timestamp (defaults to Date.now() / 1000)\n * @throws StaleDataError if data is stale\n *\n * @example\n * ```typescript\n * const pool = await getPool({ client, poolAddress })\n * assertFresh(pool, 60) // Must be < 60 seconds old\n * ```\n */\nexport function assertFresh(\n data: DataWithMeta,\n maxAgeSeconds: bigint | number,\n currentTimestamp?: bigint | number,\n): void {\n const maxAge = BigInt(maxAgeSeconds)\n const now =\n currentTimestamp !== undefined\n ? BigInt(currentTimestamp)\n : BigInt(Math.floor(Date.now() / 1000))\n const blockTimestamp = data._meta.blockTimestamp\n const age = now - blockTimestamp\n\n if (age > maxAge) {\n throw new StaleDataError(blockTimestamp, now, age)\n }\n}\n\n/**\n * Assert that a pool is healthy.\n *\n * Throws UnhealthyPoolError if the pool health status is not 'active'.\n *\n * @param pool - Pool data from getPool()\n * @throws UnhealthyPoolError if pool is unhealthy (low_liquidity or paused)\n *\n * @example\n * ```typescript\n * const pool = await getPool({ client, poolAddress })\n * assertHealthy(pool) // Throws if pool is paused or has low liquidity\n * ```\n */\nexport function assertHealthy(pool: Pool): void {\n if (pool.healthStatus !== 'active') {\n throw new UnhealthyPoolError(pool.healthStatus)\n }\n}\n\n/**\n * Assert that trading is allowed on a pool.\n *\n * Checks both pool health and safe mode status. Throws appropriate errors\n * if trading is restricted.\n *\n * @param pool - Pool data from getPool()\n * @param safeMode - Optional SafeModeState from getSafeMode()\n * @throws UnhealthyPoolError if pool is unhealthy\n * @throws SafeModeError if pool is in restricted or emergency safe mode\n *\n * @example\n * ```typescript\n * const pool = await getPool({ client, poolAddress })\n * const safeMode = await getSafeMode({ client, poolAddress })\n * assertTradeable(pool, safeMode)\n * ```\n */\nexport function assertTradeable(pool: Pool, safeMode?: SafeModeState): void {\n // First check pool health\n assertHealthy(pool)\n\n // Then check safe mode if provided\n if (safeMode && safeMode.mode !== 'normal') {\n throw new SafeModeError(safeMode.mode, safeMode.reason ?? 'Trading restricted')\n }\n}\n\n/**\n * Assert that minting is allowed.\n *\n * @param safeMode - SafeModeState from getSafeMode()\n * @throws SafeModeError if minting is not allowed\n *\n * @example\n * ```typescript\n * const safeMode = await getSafeMode({ client, poolAddress })\n * assertCanMint(safeMode)\n * await openPosition({ ... })\n * ```\n */\nexport function assertCanMint(safeMode: SafeModeState): void {\n if (!safeMode.canMint) {\n throw new SafeModeError(safeMode.mode, safeMode.reason ?? 'Minting not allowed')\n }\n}\n\n/**\n * Assert that burning is allowed.\n *\n * @param safeMode - SafeModeState from getSafeMode()\n * @throws SafeModeError if burning is not allowed\n */\nexport function assertCanBurn(safeMode: SafeModeState): void {\n if (!safeMode.canBurn) {\n throw new SafeModeError(safeMode.mode, safeMode.reason ?? 'Burning not allowed')\n }\n}\n\n/**\n * Assert that liquidations are allowed.\n *\n * @param safeMode - SafeModeState from getSafeMode()\n * @throws SafeModeError if liquidations are not allowed\n */\nexport function assertCanLiquidate(safeMode: SafeModeState): void {\n if (!safeMode.canLiquidate) {\n throw new SafeModeError(safeMode.mode, safeMode.reason ?? 'Liquidations not allowed')\n }\n}\n\n/**\n * Assert that force exercise is allowed.\n *\n * @param safeMode - SafeModeState from getSafeMode()\n * @throws SafeModeError if force exercise is not allowed\n */\nexport function assertCanForceExercise(safeMode: SafeModeState): void {\n if (!safeMode.canForceExercise) {\n throw new SafeModeError(safeMode.mode, safeMode.reason ?? 'Force exercise not allowed')\n }\n}\n\n// --- RPC Error Classification ---\n\n/**\n * Common retryable RPC error codes.\n */\nconst RETRYABLE_RPC_CODES = new Set([\n -32000, // Server error (generic)\n -32001, // Resource not found (can be transient)\n -32002, // Resource unavailable\n -32003, // Transaction rejected (can retry with new nonce)\n -32005, // Limit exceeded (rate limit)\n -32097, // Rate limit\n -32098, // Request timeout\n -32099, // Internal error\n])\n\n/**\n * Common retryable error message patterns.\n */\nconst RETRYABLE_PATTERNS = [\n /timeout/i,\n /timed out/i,\n /rate limit/i,\n /too many requests/i,\n /429/i,\n /503/i,\n /504/i,\n /502/i,\n /connection refused/i,\n /connection reset/i,\n /network error/i,\n /econnreset/i,\n /econnrefused/i,\n /etimedout/i,\n /socket hang up/i,\n /temporarily unavailable/i,\n /service unavailable/i,\n /server error/i,\n /internal error/i,\n /nonce too low/i, // Can retry with correct nonce\n /replacement transaction underpriced/i, // Can retry with higher gas\n /already known/i, // Transaction already in mempool\n]\n\n/**\n * Check if an error is a retryable RPC error.\n *\n * Returns true for transient errors that may succeed on retry:\n * - Timeouts\n * - Rate limits\n * - Connection errors\n * - Server errors (5xx)\n * - Nonce errors (recoverable with correct nonce)\n *\n * @param error - The error to check\n * @returns True if the error is likely retryable\n *\n * @example\n * ```typescript\n * try {\n * await openPosition({ ... })\n * } catch (error) {\n * if (isRetryableRpcError(error)) {\n * // Wait and retry\n * await sleep(1000)\n * await openPosition({ ... })\n * } else {\n * throw error // Non-retryable, propagate\n * }\n * }\n * ```\n */\nexport function isRetryableRpcError(error: unknown): boolean {\n if (error === null || error === undefined) {\n return false\n }\n\n // Check for RPC error code\n if (typeof error === 'object') {\n const errorObj = error as Record<string, unknown>\n\n // Check code property (standard JSON-RPC error)\n if (typeof errorObj.code === 'number' && RETRYABLE_RPC_CODES.has(errorObj.code)) {\n return true\n }\n\n // Check nested cause\n if (errorObj.cause && isRetryableRpcError(errorObj.cause)) {\n return true\n }\n\n // Check details object (viem style)\n if (errorObj.details && typeof errorObj.details === 'object') {\n const details = errorObj.details as Record<string, unknown>\n if (typeof details.code === 'number' && RETRYABLE_RPC_CODES.has(details.code)) {\n return true\n }\n }\n }\n\n // Check error message patterns\n const message = getErrorMessage(error)\n if (message) {\n for (const pattern of RETRYABLE_PATTERNS) {\n if (pattern.test(message)) {\n return true\n }\n }\n }\n\n return false\n}\n\n/**\n * Extract error message from various error types.\n */\nfunction getErrorMessage(error: unknown): string | undefined {\n if (typeof error === 'string') {\n return error\n }\n if (error instanceof Error) {\n return error.message\n }\n if (typeof error === 'object' && error !== null) {\n const errorObj = error as Record<string, unknown>\n if (typeof errorObj.message === 'string') {\n return errorObj.message\n }\n if (typeof errorObj.shortMessage === 'string') {\n return errorObj.shortMessage\n }\n }\n return undefined\n}\n\n/**\n * Check if an error is a nonce-related error that can be recovered.\n *\n * @param error - The error to check\n * @returns True if this is a nonce error\n */\nexport function isNonceError(error: unknown): boolean {\n const message = getErrorMessage(error)\n if (!message) return false\n\n return (\n /nonce too low/i.test(message) ||\n /nonce too high/i.test(message) ||\n /already known/i.test(message)\n )\n}\n\n/**\n * Check if an error is a gas-related error that can be recovered.\n *\n * @param error - The error to check\n * @returns True if this is a gas error\n */\nexport function isGasError(error: unknown): boolean {\n const message = getErrorMessage(error)\n if (!message) return false\n\n return (\n /replacement transaction underpriced/i.test(message) ||\n /gas too low/i.test(message) ||\n /intrinsic gas too low/i.test(message) ||\n /max fee per gas less than block base fee/i.test(message)\n )\n}\n","/**\n * Reorg detection and handling for position sync.\n * @module v2/sync/reorgHandling\n */\n\nimport type { Address, Hash, PublicClient } from 'viem'\n\nimport type { StorageAdapter } from '../storage'\nimport { getSyncCheckpointKey, jsonSerializer } from '../storage'\nimport type { ReorgDetection, SyncCheckpoint } from '../types'\nimport { REORG_DEPTH } from '../utils/constants'\n\n/**\n * Parameters for reorg detection.\n */\nexport interface DetectReorgParams {\n /** viem public client */\n client: PublicClient\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account being synced */\n account: Address\n /** Storage adapter for checkpoint retrieval */\n storage: StorageAdapter\n}\n\n/**\n * Detect chain reorganization by comparing stored block hash with current chain.\n *\n * @param params - Detection parameters\n * @returns Reorg detection result\n */\nexport async function detectReorg(params: DetectReorgParams): Promise<ReorgDetection> {\n const { client, chainId, poolAddress, account, storage } = params\n\n // Load checkpoint\n const checkpointKey = getSyncCheckpointKey(chainId, poolAddress, account)\n const checkpointData = await storage.get(checkpointKey)\n\n if (!checkpointData) {\n // No checkpoint, no reorg to detect\n return { detected: false }\n }\n\n const checkpoint = jsonSerializer.parse(checkpointData) as SyncCheckpoint\n\n // Get the block at the checkpoint height\n try {\n const block = await client.getBlock({\n blockNumber: checkpoint.lastBlock,\n })\n\n // Compare hashes\n if (block.hash !== checkpoint.lastBlockHash) {\n // Reorg detected!\n return {\n detected: true,\n reorgBlock: checkpoint.lastBlock,\n expectedHash: checkpoint.lastBlockHash,\n actualHash: block.hash,\n blocksToResync: REORG_DEPTH,\n }\n }\n\n // No reorg\n return { detected: false }\n } catch (error) {\n // Block not found - this could mean the block was orphaned\n // Treat as a reorg\n return {\n detected: true,\n reorgBlock: checkpoint.lastBlock,\n expectedHash: checkpoint.lastBlockHash,\n actualHash: '0x0000000000000000000000000000000000000000000000000000000000000000' as Hash,\n blocksToResync: REORG_DEPTH,\n }\n }\n}\n\n/**\n * Calculate the safe resync block after a reorg.\n *\n * @param reorgBlock - Block where reorg was detected\n * @param reorgDepth - Number of blocks to roll back (default: REORG_DEPTH = 128)\n * @returns Safe block to resync from\n */\nexport function calculateResyncBlock(reorgBlock: bigint, reorgDepth: bigint = REORG_DEPTH): bigint {\n // Roll back reorgDepth blocks, but don't go below 0\n if (reorgBlock <= reorgDepth) {\n return 0n\n }\n return reorgBlock - reorgDepth\n}\n\n/**\n * Parameters for checkpoint save.\n */\nexport interface SaveCheckpointParams {\n /** Storage adapter */\n storage: StorageAdapter\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account */\n account: Address\n /** Last synced block */\n lastBlock: bigint\n /** Last synced block hash */\n lastBlockHash: Hash\n /** Position IDs discovered */\n positionIds: bigint[]\n}\n\n/**\n * Save a sync checkpoint.\n *\n * @param params - Checkpoint parameters\n */\nexport async function saveCheckpoint(params: SaveCheckpointParams): Promise<void> {\n const { storage, chainId, poolAddress, account, lastBlock, lastBlockHash, positionIds } = params\n\n const checkpoint: SyncCheckpoint = {\n chainId,\n poolAddress,\n account,\n lastBlock,\n lastBlockHash,\n positionIds,\n createdAt: BigInt(Math.floor(Date.now() / 1000)),\n }\n\n const key = getSyncCheckpointKey(chainId, poolAddress, account)\n await storage.set(key, jsonSerializer.stringify(checkpoint))\n}\n\n/**\n * Load a sync checkpoint.\n *\n * @param storage - Storage adapter\n * @param chainId - Chain ID\n * @param poolAddress - Pool address\n * @param account - Account address\n * @returns Checkpoint or null if not found\n */\nexport async function loadCheckpoint(\n storage: StorageAdapter,\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n): Promise<SyncCheckpoint | null> {\n const key = getSyncCheckpointKey(chainId, poolAddress, account)\n const data = await storage.get(key)\n\n if (!data) {\n return null\n }\n\n return jsonSerializer.parse(data) as SyncCheckpoint\n}\n\n/**\n * Clear a sync checkpoint.\n *\n * @param storage - Storage adapter\n * @param chainId - Chain ID\n * @param poolAddress - Pool address\n * @param account - Account address\n */\nexport async function clearCheckpoint(\n storage: StorageAdapter,\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n): Promise<void> {\n const key = getSyncCheckpointKey(chainId, poolAddress, account)\n await storage.delete(key)\n}\n\n/**\n * Verify block continuity for a range of blocks.\n * This checks that each block's parentHash matches the previous block's hash.\n *\n * @param client - viem public client\n * @param fromBlock - Starting block\n * @param toBlock - Ending block\n * @returns True if blocks form a valid chain\n */\nexport async function verifyBlockContinuity(\n client: PublicClient,\n fromBlock: bigint,\n toBlock: bigint,\n): Promise<boolean> {\n if (fromBlock >= toBlock) {\n return true\n }\n\n // Sample a few blocks to verify continuity\n const sampleSize = Math.min(5, Number(toBlock - fromBlock))\n const step = (toBlock - fromBlock) / BigInt(sampleSize)\n\n let previousHash: Hash | null = null\n\n for (let i = 0; i <= sampleSize; i++) {\n const blockNumber = fromBlock + step * BigInt(i)\n const block = await client.getBlock({ blockNumber })\n\n if (previousHash !== null && i > 0) {\n // For non-consecutive blocks, we can't verify parentHash\n // but we can check that the block exists\n }\n\n previousHash = block.hash\n }\n\n return true\n}\n","/**\n * Main position synchronization function.\n * @module v2/sync/syncPositions\n */\n\nimport type { Address, Hash, PublicClient } from 'viem'\n\nimport { isRetryableRpcError } from '../bot'\nimport { ProviderLagError, SyncTimeoutError } from '../errors'\nimport { getPoolMetadata } from '../reads/pool'\nimport { getPositions } from '../reads/position'\nimport type { StorageAdapter } from '../storage'\nimport { getPoolMetaKey, getPositionMetaKey, getPositionsKey, jsonSerializer } from '../storage'\nimport type { StoredPoolMeta, StoredPositionData } from '../types'\nimport { getOpenPositionIds } from './getTrackedPositionIds'\nimport { detectReorg, loadCheckpoint, saveCheckpoint } from './reorgHandling'\n\n/**\n * Parameters for syncPositions.\n */\nexport interface SyncPositionsParams {\n /** viem public client */\n client: PublicClient\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account to sync */\n account: Address\n /** Storage adapter for persistence */\n storage: StorageAdapter\n /** Starting block for sync (defaults to pool deployment block) */\n fromBlock?: bigint\n /** Ending block for sync (defaults to latest) */\n toBlock?: bigint\n /** Max block range per eth_getLogs call (default: 10000n) */\n maxLogsPerQuery?: bigint\n /** Max sync duration in ms (default: 300000n = 5 min) */\n syncTimeout?: bigint\n /** Optional callback for sync progress */\n onUpdate?: (event: SyncProgressEvent) => void\n /** If provider is behind this block, throw ProviderLagError */\n minBlockNumber?: bigint\n /** Manual snapshot tx hash for recovery when automatic fails */\n snapshotTxHash?: Hash\n}\n\n/**\n * Sync progress event for callbacks.\n */\nexport interface SyncProgressEvent {\n /** Event type */\n type: 'position-opened' | 'position-closed' | 'progress' | 'reorg-detected'\n /** TokenId for position events */\n tokenId?: bigint\n /** Current block being processed */\n blockNumber: bigint\n /** Progress info */\n progress?: {\n /** Current block */\n current: bigint\n /** Total blocks to process */\n total: bigint\n }\n}\n\n/**\n * Result of syncPositions.\n */\nexport interface SyncPositionsResult {\n /** Last synced block number */\n lastSyncedBlock: bigint\n /** Last synced block hash */\n lastSyncedBlockHash: Hash\n /** Number of open positions */\n positionCount: bigint\n /** Position IDs discovered */\n positionIds: bigint[]\n /** Whether this was an incremental sync (vs full) */\n incremental: boolean\n /** Duration in milliseconds */\n durationMs: bigint\n}\n\n/**\n * Synchronize positions for an account.\n *\n * This function:\n * 1. Checks for existing checkpoint\n * 2. If no checkpoint: recovers from dispatch() calldata or falls back to full event scan\n * 3. If checkpoint exists: detects reorgs and syncs incrementally\n * 4. Persists positions and checkpoint to storage\n *\n * @param params - Sync parameters\n * @returns Sync result with position count and sync metadata\n * @throws SyncTimeoutError if sync exceeds timeout\n * @throws ProviderLagError if provider is behind minBlockNumber\n * @throws PositionSnapshotNotFoundError if no positions found and no snapshot available\n */\nexport async function syncPositions(params: SyncPositionsParams): Promise<SyncPositionsResult> {\n const {\n client,\n chainId,\n poolAddress,\n account,\n storage,\n syncTimeout = 300000n, // 5 minutes\n onUpdate,\n minBlockNumber,\n snapshotTxHash,\n } = params\n\n const startTime = Date.now()\n\n const checkTimeout = () => {\n const elapsed = BigInt(Date.now() - startTime)\n if (elapsed > syncTimeout) {\n throw new SyncTimeoutError(elapsed, toBlock, 0n)\n }\n }\n\n // Get latest block\n const latestBlock = await client.getBlockNumber()\n const toBlock = params.toBlock ?? latestBlock\n\n // Check for provider lag\n if (minBlockNumber !== undefined && latestBlock < minBlockNumber) {\n throw new ProviderLagError(minBlockNumber, latestBlock)\n }\n\n // Reorg detection using existing checkpoint\n const checkpoint = await loadCheckpoint(storage, chainId, poolAddress, account)\n if (checkpoint) {\n const reorgResult = await detectReorg({\n client,\n chainId,\n poolAddress,\n account,\n storage,\n })\n\n if (reorgResult.detected) {\n onUpdate?.({\n type: 'reorg-detected',\n blockNumber: reorgResult.reorgBlock ?? 0n,\n })\n }\n }\n\n checkTimeout()\n\n // Get authoritative position IDs from latest dispatch calldata.\n // When resuming from a checkpoint, narrow the event scan window to avoid\n // re-scanning the entire chain history on every incremental sync.\n // Returns null when no dispatch event was found in the scanned range,\n // or [] when a dispatch was found with an empty position list.\n const snapshotResult = await getOpenPositionIds({\n client,\n chainId,\n poolAddress,\n account,\n storage,\n lastDispatchTxHash: snapshotTxHash,\n fromBlock: checkpoint?.lastBlock ?? params.fromBlock,\n })\n\n // If no dispatch events were found in the scanned range (null) but the\n // checkpoint had positions, the user simply hasn't traded since the last\n // sync — keep the cached list. An explicit empty array means a dispatch\n // was found that authoritatively shows zero open positions.\n let positionIds: bigint[]\n if (snapshotResult === null && checkpoint && checkpoint.positionIds.length > 0) {\n positionIds = checkpoint.positionIds\n } else {\n positionIds = snapshotResult ?? []\n }\n\n // If no positions and no history, save empty checkpoint and return early\n if (positionIds.length === 0) {\n const hasAnyEvents = await accountHasPositionEvents({\n client,\n poolAddress,\n account,\n fromBlock: params.fromBlock,\n toBlock,\n })\n\n if (!hasAnyEvents) {\n const finalBlock = await client.getBlock({ blockNumber: toBlock })\n\n const poolMetaKey = getPoolMetaKey(chainId, poolAddress)\n const existingPoolMeta = await storage.get(poolMetaKey)\n if (!existingPoolMeta) {\n await fetchAndStorePoolMeta(client, poolAddress, poolMetaKey, storage)\n }\n\n await saveCheckpoint({\n storage,\n chainId,\n poolAddress,\n account,\n lastBlock: toBlock,\n lastBlockHash: finalBlock.hash,\n positionIds: [],\n })\n\n const positionsKey = getPositionsKey(chainId, poolAddress, account)\n await storage.set(positionsKey, jsonSerializer.stringify([]))\n\n return {\n lastSyncedBlock: toBlock,\n lastSyncedBlockHash: finalBlock.hash,\n positionCount: 0n,\n positionIds: [],\n incremental: false,\n durationMs: BigInt(Date.now() - startTime),\n }\n }\n }\n\n checkTimeout()\n\n // Get final block info\n const finalBlock = await client.getBlock({ blockNumber: toBlock })\n\n // Fetch and store pool metadata if not already stored\n const poolMetaKey = getPoolMetaKey(chainId, poolAddress)\n const existingPoolMeta = await storage.get(poolMetaKey)\n if (!existingPoolMeta) {\n await fetchAndStorePoolMeta(client, poolAddress, poolMetaKey, storage)\n }\n\n // Fetch and store position data for all positions\n if (positionIds.length > 0) {\n const { positions } = await getPositions({\n client,\n poolAddress,\n owner: account,\n tokenIds: positionIds,\n blockNumber: toBlock,\n })\n\n for (const pos of positions) {\n const positionMetaKey = getPositionMetaKey(chainId, poolAddress, pos.tokenId)\n const storedData: StoredPositionData = {\n tokenId: pos.tokenId,\n positionSize: pos.positionSize,\n legs: pos.legs,\n tickAtMint: pos.tickAtMint,\n poolUtilization0AtMint: pos.poolUtilization0AtMint,\n poolUtilization1AtMint: pos.poolUtilization1AtMint,\n timestampAtMint: pos.timestampAtMint,\n blockNumberAtMint: pos.blockNumberAtMint,\n swapAtMint: pos.swapAtMint,\n }\n await storage.set(positionMetaKey, jsonSerializer.stringify(storedData))\n }\n }\n\n // Save checkpoint\n await saveCheckpoint({\n storage,\n chainId,\n poolAddress,\n account,\n lastBlock: toBlock,\n lastBlockHash: finalBlock.hash,\n positionIds,\n })\n\n // Save positions to storage\n const positionsKey = getPositionsKey(chainId, poolAddress, account)\n await storage.set(positionsKey, jsonSerializer.stringify(positionIds))\n\n return {\n lastSyncedBlock: toBlock,\n lastSyncedBlockHash: finalBlock.hash,\n positionCount: BigInt(positionIds.length),\n positionIds,\n incremental: !!checkpoint,\n durationMs: BigInt(Date.now() - startTime),\n }\n}\n\n/**\n * Quick check if an account has ANY position events.\n * Checks OptionMinted, OptionBurnt, ForcedExercised (user), and AccountLiquidated (liquidatee).\n * All checked fields are indexed so this is fast.\n *\n * **Warning:** RPC index lag can cause false negatives for recently minted positions.\n * If the RPC node's event index is behind the chain tip, this function may return\n * `false` even though the account has just minted a position. Callers should either\n * wait a few blocks after minting before calling syncPositions, or skip this\n * optimization (by providing a `snapshotTxHash`) when freshness is critical.\n *\n * @param params - Check parameters\n * @returns true if account has any position events, false otherwise\n */\nasync function accountHasPositionEvents(params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n fromBlock?: bigint\n toBlock: bigint\n}): Promise<boolean> {\n const { client, poolAddress, account, fromBlock = 0n, toBlock } = params\n\n const [mintEvents, burnEvents, forceExerciseEvents, liquidationEvents] = await Promise.all([\n withRetry(() =>\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,\n toBlock,\n }),\n ),\n withRetry(() =>\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,\n toBlock,\n }),\n ),\n withRetry(() =>\n client.getLogs({\n address: poolAddress,\n event: {\n type: 'event',\n name: 'ForcedExercised',\n inputs: [\n { type: 'address', name: 'exercisor', indexed: true },\n { type: 'address', name: 'user', indexed: true },\n { type: 'uint256', name: 'tokenId', indexed: true },\n { type: 'int256', name: 'exerciseFee', indexed: false },\n ],\n },\n args: {\n user: account,\n },\n fromBlock,\n toBlock,\n }),\n ),\n withRetry(() =>\n client.getLogs({\n address: poolAddress,\n event: {\n type: 'event',\n name: 'AccountLiquidated',\n inputs: [\n { type: 'address', name: 'liquidator', indexed: true },\n { type: 'address', name: 'liquidatee', indexed: true },\n { type: 'int256', name: 'bonusAmounts', indexed: false },\n ],\n },\n args: {\n liquidatee: account,\n },\n fromBlock,\n toBlock,\n }),\n ),\n ])\n\n return (\n mintEvents.length > 0 ||\n burnEvents.length > 0 ||\n forceExerciseEvents.length > 0 ||\n liquidationEvents.length > 0\n )\n}\n\n/**\n * Fetch full pool metadata and store it.\n * Uses getPoolMetadata to fetch all immutable pool data in minimal RPC calls.\n */\nasync function fetchAndStorePoolMeta(\n client: PublicClient,\n poolAddress: Address,\n poolMetaKey: string,\n storage: StorageAdapter,\n): Promise<void> {\n const metadata = await getPoolMetadata({ client, poolAddress })\n\n const poolMeta: StoredPoolMeta = {\n tickSpacing: metadata.tickSpacing,\n fee: metadata.fee,\n poolId: metadata.poolId,\n collateralToken0Address: metadata.collateralToken0Address,\n collateralToken1Address: metadata.collateralToken1Address,\n riskEngineAddress: metadata.riskEngineAddress,\n token0Asset: metadata.token0Asset,\n token1Asset: metadata.token1Asset,\n token0Symbol: metadata.token0Symbol,\n token1Symbol: metadata.token1Symbol,\n token0Decimals: metadata.token0Decimals,\n token1Decimals: metadata.token1Decimals,\n }\n\n await storage.set(poolMetaKey, jsonSerializer.stringify(poolMeta))\n}\n\n/**\n * Retry helper with exponential backoff for transient RPC errors.\n *\n * @param fn - Async function to retry\n * @param maxRetries - Maximum number of retries (default: 3)\n * @returns The result of the function\n */\nasync function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {\n let lastError: unknown\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn()\n } catch (error) {\n lastError = error\n if (attempt < maxRetries && isRetryableRpcError(error)) {\n // Exponential backoff: 1s, 2s, 4s\n await new Promise((resolve) => setTimeout(resolve, 1000 * 2 ** attempt))\n continue\n }\n throw error\n }\n }\n throw lastError\n}\n","/**\n * Force exercise functions for the Panoptic v2 SDK.\n * @module v2/writes/forceExercise\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport type { StorageAdapter } from '../storage'\nimport { syncPositions } from '../sync/syncPositions'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for force exercising a position.\n */\nexport interface ForceExerciseParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Exercisor account address */\n account: Address\n /** PanopticPool address */\n poolAddress: 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 /** Packed value for using premia as collateral */\n usePremiaAsCollateral?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n /** Storage adapter for auto-syncing positions after confirmation */\n storage?: StorageAdapter\n /** Chain ID (required when storage is provided) */\n chainId?: bigint\n}\n\n/**\n * Force exercise an ITM (in-the-money) long position.\n *\n * The exercisor calls dispatchFrom to exercise another user's ITM long positions,\n * paying the exercise fee.\n *\n * @param params - Force exercise parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await forceExercise({\n * client,\n * walletClient,\n * account: exercisorAddress,\n * poolAddress,\n * user: targetAccount,\n * positionIdListFrom: exercisorPositions,\n * positionIdListTo: targetPositions,\n * positionIdListToFinal: [], // Exercise all ITM positions\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function forceExercise(params: ForceExerciseParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n user,\n positionIdListFrom,\n positionIdListTo,\n positionIdListToFinal,\n usePremiaAsCollateral = 0n,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatchFrom',\n args: [\n positionIdListFrom,\n user,\n positionIdListTo,\n positionIdListToFinal,\n usePremiaAsCollateral,\n ],\n txOverrides,\n })\n}\n\n/**\n * Force exercise and wait for confirmation.\n *\n * When `storage` and `chainId` are provided, automatically syncs the\n * exercisor's positions after the transaction confirms.\n */\nexport async function forceExerciseAndWait(params: ForceExerciseParams): Promise<TxReceipt> {\n const result = await forceExercise(params)\n const receipt = await result.wait()\n\n const { storage, chainId, client, poolAddress, account } = params\n if (storage && chainId !== undefined) {\n await syncPositions({\n client,\n chainId,\n poolAddress,\n account,\n storage,\n })\n }\n\n return receipt\n}\n","/**\n * Premium settlement functions for the Panoptic v2 SDK.\n * @module v2/writes/settle\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport type { TickAndSpreadLimits } from './position'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for settling accumulated premia.\n */\nexport interface SettleParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Current position ID list */\n positionIdList: bigint[]\n /** Whether to use premia as collateral */\n usePremiaAsCollateral?: boolean\n /** Builder code */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Settle accumulated premia on existing positions.\n *\n * This function triggers premium collection without changing position size.\n * It calls dispatch with unchanged position lists.\n *\n * @param params - Settlement parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await settleAccumulatedPremia({\n * client,\n * walletClient,\n * account,\n * poolAddress,\n * positionIdList: existingPositions,\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function settleAccumulatedPremia(params: SettleParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n positionIdList,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n txOverrides,\n } = params\n\n // For settlement, we call dispatch with:\n // - Same position lists (no change)\n // - Zero position sizes (no size change, just settle)\n // - Wide tick limits\n const positionSizes: bigint[] = positionIdList.map(() => 0n)\n const tickAndSpreadLimits: TickAndSpreadLimits[] = positionIdList.map(\n () => [-887272n, 887272n, 0n] as const,\n )\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n positionIdList, // Same list - no change\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 usePremiaAsCollateral,\n builderCode,\n ],\n txOverrides,\n })\n}\n\n/**\n * Settle premia and wait for confirmation.\n */\nexport async function settleAccumulatedPremiaAndWait(params: SettleParams): Promise<TxReceipt> {\n const result = await settleAccumulatedPremia(params)\n return result.wait()\n}\n","/**\n * Oracle poke function for the Panoptic v2 SDK.\n * @module v2/writes/pokeOracle\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { OracleRateLimitedError } from '../errors'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for poking the oracle.\n */\nexport interface PokeOracleParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Whether to check rate limit before calling (optional) */\n checkRateLimit?: boolean\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Poke the oracle to update its state.\n *\n * This function can be called to advance the oracle epoch.\n * Note: The oracle can only be poked once per epoch (64 seconds).\n *\n * @param params - Poke oracle parameters\n * @returns TxResult\n * @throws OracleRateLimitedError if checkRateLimit is true and oracle was recently poked\n *\n * @example\n * ```typescript\n * const result = await pokeOracle({\n * client,\n * walletClient,\n * account,\n * poolAddress,\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function pokeOracle(params: PokeOracleParams): Promise<TxResult> {\n const { client, walletClient, account, poolAddress, checkRateLimit = false, txOverrides } = params\n\n if (checkRateLimit) {\n // Check current oracle state to see if we can poke\n // Fetch oracle data and block in parallel\n const [oracleData, block] = await Promise.all([\n client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getOracleTicks',\n }),\n client.getBlock(),\n ])\n\n // oracleData[4] is the oraclePack\n const oraclePack = oracleData[4]\n // Epoch is in bits 232-255 (24 bits)\n const epoch = oraclePack >> 232n\n\n const currentEpoch = block.timestamp / 64n\n\n // If current epoch equals oracle epoch, we can't poke yet\n if (currentEpoch <= epoch) {\n const lastUpdate = epoch * 64n\n throw new OracleRateLimitedError(lastUpdate, block.timestamp)\n }\n }\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'pokeOracle',\n args: [],\n txOverrides,\n })\n}\n\n/**\n * Poke oracle and wait for confirmation.\n */\nexport async function pokeOracleAndWait(params: PokeOracleParams): Promise<TxReceipt> {\n const result = await pokeOracle(params)\n return result.wait()\n}\n","/**\n * Factory write functions for the Panoptic v2 SDK.\n * @module v2/writes/factory\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticFactoryV3Abi, panopticFactoryV4Abi } from '../../../generated'\nimport type { PoolKey, TxOverrides, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\ninterface DeployNewPoolCommon {\n /** Public client */\n client: PublicClient\n /** Wallet client for signing */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticFactory address */\n factoryAddress: Address\n /** Risk engine address */\n riskEngine: Address\n /** Salt (uint96) */\n salt: bigint\n /** Optional transaction overrides */\n txOverrides?: TxOverrides\n}\n\nexport interface DeployNewPoolV3Params extends DeployNewPoolCommon {\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 DeployNewPoolV4Params extends DeployNewPoolCommon {\n /** V4 pool key */\n poolKey: PoolKey\n}\n\nexport type DeployNewPoolParams =\n | ({ version: 'v3' } & DeployNewPoolV3Params)\n | ({ version: 'v4' } & DeployNewPoolV4Params)\n\n/**\n * Deploy a new Panoptic pool via the factory.\n *\n * @param params - Deployment parameters (versioned: 'v3' or 'v4')\n * @returns Transaction result with hash and wait function\n */\nexport async function deployNewPool(params: DeployNewPoolParams): Promise<TxResult> {\n const { client, walletClient, account, factoryAddress, riskEngine, salt, txOverrides } = params\n\n if (params.version === 'v3') {\n return submitWrite({\n client,\n walletClient,\n account,\n address: factoryAddress,\n abi: panopticFactoryV3Abi,\n functionName: 'deployNewPool',\n args: [params.token0, params.token1, params.fee, riskEngine, salt],\n txOverrides,\n })\n }\n\n return submitWrite({\n client,\n walletClient,\n account,\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 txOverrides,\n })\n}\n\n/**\n * Deploy a new Panoptic pool and wait for confirmation.\n */\nexport async function deployNewPoolAndWait(params: DeployNewPoolParams) {\n const result = await deployNewPool(params)\n return result.wait()\n}\n","/**\n * Transaction replacement utilities for the Panoptic v2 SDK.\n * Provides speedUp and cancel functionality for pending transactions.\n * @module v2/writes/txManagement\n */\n\nimport type { Address, Hash, PublicClient, WalletClient } from 'viem'\n\nimport type { TxBroadcaster, TxResult } from '../types'\nimport { createTxResult } from './utils'\n\n/** Default gas price multiplier for replacement (12.5% bump = minimum for replacement) */\nconst DEFAULT_GAS_PRICE_MULTIPLIER = 1.125\n\n/**\n * Parameters for speeding up a pending transaction.\n */\nexport interface SpeedUpParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Hash of the pending transaction to speed up */\n hash: Hash\n /** Explicit max fee per gas (overrides multiplier) */\n maxFeePerGas?: bigint\n /** Explicit max priority fee per gas (overrides multiplier) */\n maxPriorityFeePerGas?: bigint\n /** Multiplier for gas price bump (default 1.125 = 12.5%, minimum to replace) */\n gasPriceMultiplier?: number\n /** Custom broadcaster for MEV protection */\n broadcaster?: TxBroadcaster\n}\n\n/**\n * Parameters for cancelling a pending transaction.\n */\nexport interface CancelParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address (for self-transfer) */\n account: Address\n /** Hash of the pending transaction to cancel */\n hash: Hash\n /** Explicit max fee per gas (overrides multiplier) */\n maxFeePerGas?: bigint\n /** Explicit max priority fee per gas (overrides multiplier) */\n maxPriorityFeePerGas?: bigint\n /** Multiplier for gas price bump (default 1.125 = 12.5%, minimum to replace) */\n gasPriceMultiplier?: number\n /** Custom broadcaster for MEV protection */\n broadcaster?: TxBroadcaster\n}\n\n/**\n * Apply a multiplier to a bigint gas value.\n * Uses integer arithmetic to avoid floating point issues.\n */\nfunction applyMultiplier(value: bigint, multiplier: number): bigint {\n // Convert multiplier to basis points (e.g., 1.125 => 11250)\n const bps = BigInt(Math.ceil(multiplier * 10000))\n return (value * bps) / 10000n\n}\n\n/**\n * Compute bumped gas parameters from the original transaction.\n */\nfunction computeBumpedGas(\n originalMaxFeePerGas: bigint | undefined,\n originalMaxPriorityFeePerGas: bigint | undefined,\n explicitMaxFeePerGas: bigint | undefined,\n explicitMaxPriorityFeePerGas: bigint | undefined,\n multiplier: number,\n): { maxFeePerGas: bigint; maxPriorityFeePerGas: bigint } {\n const maxFeePerGas =\n explicitMaxFeePerGas ?? applyMultiplier(originalMaxFeePerGas ?? 0n, multiplier)\n\n const maxPriorityFeePerGas =\n explicitMaxPriorityFeePerGas ?? applyMultiplier(originalMaxPriorityFeePerGas ?? 0n, multiplier)\n\n return { maxFeePerGas, maxPriorityFeePerGas }\n}\n\n/**\n * Speed up a pending transaction by resubmitting with higher gas.\n *\n * Fetches the original transaction, extracts its parameters,\n * bumps the gas price, and resubmits with the same nonce.\n *\n * @param params - Speed up parameters\n * @returns TxResult for the replacement transaction\n * @throws Error if the original transaction is not found\n *\n * @example\n * ```typescript\n * // Speed up with default 12.5% bump\n * const result = await speedUpTransaction({\n * client,\n * walletClient,\n * hash: pendingTxHash,\n * })\n *\n * // Speed up with explicit gas prices\n * const result = await speedUpTransaction({\n * client,\n * walletClient,\n * hash: pendingTxHash,\n * maxFeePerGas: 50_000_000_000n, // 50 gwei\n * maxPriorityFeePerGas: 3_000_000_000n, // 3 gwei\n * })\n * ```\n */\nexport async function speedUpTransaction(params: SpeedUpParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n hash,\n maxFeePerGas: explicitMaxFee,\n maxPriorityFeePerGas: explicitMaxPriority,\n gasPriceMultiplier = DEFAULT_GAS_PRICE_MULTIPLIER,\n broadcaster,\n } = params\n\n const tx = await client.getTransaction({ hash })\n\n const { maxFeePerGas, maxPriorityFeePerGas } = computeBumpedGas(\n tx.maxFeePerGas ?? undefined,\n tx.maxPriorityFeePerGas ?? undefined,\n explicitMaxFee,\n explicitMaxPriority,\n gasPriceMultiplier,\n )\n\n if (broadcaster) {\n const request = await walletClient.prepareTransactionRequest({\n account: tx.from,\n to: tx.to ?? undefined,\n data: tx.input,\n value: tx.value,\n nonce: tx.nonce,\n gas: tx.gas,\n maxFeePerGas,\n maxPriorityFeePerGas,\n chain: walletClient.chain,\n })\n\n const signedTx = await walletClient.signTransaction({\n ...request,\n account: tx.from,\n } as unknown as Parameters<WalletClient['signTransaction']>[0])\n const replacementHash = await broadcaster.broadcast(signedTx)\n return createTxResult(client, replacementHash)\n }\n\n const replacementHash = await walletClient.sendTransaction({\n account: tx.from,\n to: tx.to ?? undefined,\n data: tx.input,\n value: tx.value,\n nonce: tx.nonce,\n gas: tx.gas,\n maxFeePerGas,\n maxPriorityFeePerGas,\n chain: walletClient.chain,\n })\n\n return createTxResult(client, replacementHash)\n}\n\n/**\n * Cancel a pending transaction by sending a 0-value self-transfer\n * with the same nonce and higher gas price.\n *\n * @param params - Cancel parameters\n * @returns TxResult for the cancellation transaction\n * @throws Error if the original transaction is not found\n *\n * @example\n * ```typescript\n * const result = await cancelTransaction({\n * client,\n * walletClient,\n * account,\n * hash: pendingTxHash,\n * })\n * await result.wait()\n * ```\n */\nexport async function cancelTransaction(params: CancelParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n hash,\n maxFeePerGas: explicitMaxFee,\n maxPriorityFeePerGas: explicitMaxPriority,\n gasPriceMultiplier = DEFAULT_GAS_PRICE_MULTIPLIER,\n broadcaster,\n } = params\n\n const tx = await client.getTransaction({ hash })\n\n const { maxFeePerGas, maxPriorityFeePerGas } = computeBumpedGas(\n tx.maxFeePerGas ?? undefined,\n tx.maxPriorityFeePerGas ?? undefined,\n explicitMaxFee,\n explicitMaxPriority,\n gasPriceMultiplier,\n )\n\n if (broadcaster) {\n const request = await walletClient.prepareTransactionRequest({\n account,\n to: account,\n value: 0n,\n nonce: tx.nonce,\n gas: 21000n,\n maxFeePerGas,\n maxPriorityFeePerGas,\n chain: walletClient.chain,\n })\n\n const signedTx = await walletClient.signTransaction({\n ...request,\n account,\n } as unknown as Parameters<WalletClient['signTransaction']>[0])\n const cancelHash = await broadcaster.broadcast(signedTx)\n return createTxResult(client, cancelHash)\n }\n\n const cancelHash = await walletClient.sendTransaction({\n account,\n to: account,\n value: 0n,\n nonce: tx.nonce,\n gas: 21000n,\n maxFeePerGas,\n maxPriorityFeePerGas,\n chain: walletClient.chain,\n })\n\n return createTxResult(client, cancelHash)\n}\n","/**\n * Low-level TokenId encoding utilities for the Panoptic v2 SDK.\n * @module v2/tokenId/encoding\n */\n\nimport type { Address, Hex } from 'viem'\n\nimport {\n DEFAULT_VEGOID,\n LEG_BITS,\n LEG_MASKS,\n STRIKE_CONVERSION_FACTOR,\n TOKEN_ID_BITS,\n} from './constants'\n\n/**\n * Leg parameters for encoding.\n */\nexport interface EncodeLegParams {\n /** Leg index (0-3) */\n index: bigint\n /** Asset index (0 or 1) */\n asset: bigint\n /** Option ratio (1-127) */\n optionRatio: bigint\n /** Whether this is a long position (1n = long, 0n = short) */\n isLong: bigint\n /** Token type (0 or 1) */\n tokenType: bigint\n /** Risk partner leg index (0-3) */\n riskPartner: bigint\n /** Strike tick */\n strike: bigint\n /** Width in tick spacing units */\n width: bigint\n}\n\n/**\n * Convert a signed strike tick to unsigned representation for encoding.\n *\n * @param strike - The signed strike tick\n * @returns The unsigned representation\n */\nexport function convertStrikeToUnsigned(strike: bigint): bigint {\n if (strike < 0n) {\n return STRIKE_CONVERSION_FACTOR + strike\n }\n return strike\n}\n\n/**\n * Convert an unsigned encoded strike back to signed representation.\n *\n * @param encodedStrike - The unsigned encoded strike\n * @returns The signed strike tick\n */\nexport function convertStrikeToSigned(encodedStrike: bigint): bigint {\n // If the value is greater than max positive int24, it's negative\n if (encodedStrike > 2n ** 23n - 1n) {\n return encodedStrike - STRIKE_CONVERSION_FACTOR\n }\n return encodedStrike\n}\n\n/**\n * Get the bit offset for a leg at the given index.\n *\n * @param legIndex - The leg index (0-3)\n * @returns The bit offset from the start of the legs section\n */\nexport function getLegOffset(legIndex: bigint): bigint {\n return legIndex * TOKEN_ID_BITS.LEG_SIZE\n}\n\n/**\n * Encode a pool ID from a Uniswap V3 pool address.\n *\n * The encoded PoolId structure: [16-bit tickSpacing][8-bit vegoid][40-bit pool address]\n *\n * @param address - The Uniswap V3 pool address\n * @param tickSpacing - The tick spacing of the pool\n * @param vegoid - The vegoid value (defaults to 4)\n * @returns The encoded pool ID\n */\nexport function encodePoolId(\n address: Address,\n tickSpacing: bigint,\n vegoid: bigint = DEFAULT_VEGOID,\n): bigint {\n // Remove 0x prefix and get first 10 hex chars (5 bytes = 40 bits)\n const addressHex = address.slice(2, 12).toLowerCase()\n\n // Convert to bytes array (big-endian), then reverse to little-endian\n const bytes: number[] = []\n for (let i = 0; i < 10; i += 2) {\n bytes.push(parseInt(addressHex.slice(i, i + 2), 16))\n }\n bytes.reverse()\n\n // Build poolId: pool address (5 bytes) + vegoid (1 byte) + tickSpacing (2 bytes)\n let poolId = 0n\n for (let i = 0; i < bytes.length; i++) {\n poolId |= BigInt(bytes[i]) << BigInt(i * 8)\n }\n\n // Add vegoid at bit 40\n poolId |= (vegoid & 0xffn) << TOKEN_ID_BITS.VEGOID_STARTING_BIT\n\n // Add tickSpacing at bit 48\n poolId |= (tickSpacing & 0xffffn) << TOKEN_ID_BITS.TICK_SPACING_STARTING_BIT\n\n return poolId\n}\n\n/**\n * Encode a pool ID from a Uniswap V4 pool ID (bytes32).\n *\n * @param poolIdHex - The V4 pool ID (bytes32 hex string)\n * @param tickSpacing - The tick spacing of the pool\n * @param vegoid - The vegoid value (defaults to 4)\n * @returns The encoded pool ID\n */\nexport function encodeV4PoolId(\n poolIdHex: Hex,\n tickSpacing: bigint,\n vegoid: bigint = DEFAULT_VEGOID,\n): bigint {\n // Remove 0x prefix and get last 10 hex chars (5 bytes = 40 bits)\n const hex = poolIdHex.slice(2)\n const last5BytesHex = hex.slice(-10).toLowerCase()\n\n // Convert to bytes array (big-endian), then reverse to little-endian\n const bytes: number[] = []\n for (let i = 0; i < 10; i += 2) {\n bytes.push(parseInt(last5BytesHex.slice(i, i + 2), 16))\n }\n bytes.reverse()\n\n // Build encoded poolId\n let encodedPoolId = 0n\n for (let i = 0; i < bytes.length; i++) {\n encodedPoolId |= BigInt(bytes[i]) << BigInt(i * 8)\n }\n\n // Add vegoid at bit 40\n encodedPoolId |= (vegoid & 0xffn) << TOKEN_ID_BITS.VEGOID_STARTING_BIT\n\n // Add tickSpacing at bit 48\n encodedPoolId |= (tickSpacing & 0xffffn) << TOKEN_ID_BITS.TICK_SPACING_STARTING_BIT\n\n return encodedPoolId\n}\n\n/**\n * Decode the vegoid from a TokenId.\n *\n * @param tokenId - The TokenId to decode\n * @returns The vegoid value\n */\nexport function decodeVegoid(tokenId: bigint): bigint {\n const poolId = tokenId & ((1n << TOKEN_ID_BITS.POOL_ID_SIZE) - 1n)\n return (poolId >> TOKEN_ID_BITS.VEGOID_STARTING_BIT) & ((1n << TOKEN_ID_BITS.VEGOID_SIZE) - 1n)\n}\n\n/**\n * Decode the tick spacing from a TokenId.\n *\n * @param tokenId - The TokenId to decode\n * @returns The tick spacing\n */\nexport function decodeTickSpacing(tokenId: bigint): bigint {\n const poolId = tokenId & ((1n << TOKEN_ID_BITS.POOL_ID_SIZE) - 1n)\n return poolId >> TOKEN_ID_BITS.TICK_SPACING_STARTING_BIT\n}\n\n/**\n * Decode the pool ID portion from a TokenId.\n *\n * @param tokenId - The TokenId to decode\n * @returns The pool ID as a hex string\n */\nexport function decodePoolId(tokenId: bigint): Hex {\n const poolId = tokenId & ((1n << TOKEN_ID_BITS.POOL_ID_SIZE) - 1n)\n let hex = poolId.toString(16)\n // Pad to 16 characters (64 bits)\n while (hex.length < 16) {\n hex = '0' + hex\n }\n return `0x${hex}` as Hex\n}\n\n/**\n * Encode a single leg field.\n *\n * @param value - The value to encode\n * @param bitPosition - The bit position within the leg\n * @param legIndex - The leg index\n * @returns The encoded value shifted to the correct position\n */\nfunction encodeLegField(value: bigint, bitPosition: bigint, legIndex: bigint): bigint {\n return value << (getLegOffset(legIndex) + bitPosition + TOKEN_ID_BITS.POOL_ID_SIZE)\n}\n\n/**\n * Encode a single leg into a TokenId.\n *\n * @param leg - The leg parameters\n * @returns The encoded leg value (to be ORed with existing TokenId)\n */\nexport function encodeLeg(leg: EncodeLegParams): bigint {\n const { index, asset, optionRatio, isLong, tokenType, riskPartner, strike, width } = leg\n\n return (\n encodeLegField(asset & LEG_MASKS.ASSET, LEG_BITS.ASSET_BIT, index) |\n encodeLegField(optionRatio & LEG_MASKS.RATIO, LEG_BITS.RATIO_BIT, index) |\n encodeLegField(isLong & LEG_MASKS.IS_LONG, LEG_BITS.IS_LONG_BIT, index) |\n encodeLegField(tokenType & LEG_MASKS.TOKEN_TYPE, LEG_BITS.TOKEN_TYPE_BIT, index) |\n encodeLegField(riskPartner & LEG_MASKS.RISK_PARTNER, LEG_BITS.RISK_PARTNER_BIT, index) |\n encodeLegField(convertStrikeToUnsigned(strike) & LEG_MASKS.STRIKE, LEG_BITS.STRIKE_BIT, index) |\n encodeLegField(width & LEG_MASKS.WIDTH, LEG_BITS.WIDTH_BIT, index)\n )\n}\n\n/**\n * Add a leg to an existing TokenId.\n *\n * @param tokenId - The existing TokenId (can be just poolId or partial TokenId)\n * @param leg - The leg parameters to add\n * @returns The TokenId with the leg added\n */\nexport function addLegToTokenId(tokenId: bigint, leg: EncodeLegParams): bigint {\n return tokenId | encodeLeg(leg)\n}\n\n/**\n * Decoded leg data.\n */\nexport interface DecodedLeg {\n /** Leg index (0-3) */\n index: bigint\n /** Asset index (0 or 1) */\n asset: bigint\n /** Option ratio (1-127) */\n optionRatio: bigint\n /** Whether this is a long position */\n isLong: boolean\n /** Token type (0 or 1) */\n tokenType: bigint\n /** Risk partner leg index */\n riskPartner: bigint\n /** Strike tick (signed) */\n strike: bigint\n /** Width in tick spacing units */\n width: bigint\n}\n\n/**\n * Decode a single leg from a TokenId.\n *\n * @param tokenId - The TokenId to decode\n * @param legIndex - The leg index (0-3)\n * @returns The decoded leg data\n */\nexport function decodeLeg(tokenId: bigint, legIndex: bigint): DecodedLeg {\n const offset = getLegOffset(legIndex) + TOKEN_ID_BITS.POOL_ID_SIZE\n const leg = (tokenId >> offset) & LEG_MASKS.LEG\n\n const asset = leg & LEG_MASKS.ASSET\n const optionRatio = (leg >> LEG_BITS.RATIO_BIT) & LEG_MASKS.RATIO\n const isLong = ((leg >> LEG_BITS.IS_LONG_BIT) & LEG_MASKS.IS_LONG) === 1n\n const tokenType = (leg >> LEG_BITS.TOKEN_TYPE_BIT) & LEG_MASKS.TOKEN_TYPE\n const riskPartner = (leg >> LEG_BITS.RISK_PARTNER_BIT) & LEG_MASKS.RISK_PARTNER\n const encodedStrike = (leg >> LEG_BITS.STRIKE_BIT) & LEG_MASKS.STRIKE\n const strike = convertStrikeToSigned(encodedStrike)\n const width = (leg >> LEG_BITS.WIDTH_BIT) & LEG_MASKS.WIDTH\n\n return {\n index: legIndex,\n asset,\n optionRatio,\n isLong,\n tokenType,\n riskPartner,\n strike,\n width,\n }\n}\n\n/**\n * Count the number of active legs in a TokenId.\n * A leg is active if its optionRatio > 0.\n *\n * @param tokenId - The TokenId to check\n * @returns The number of active legs\n */\nexport function countLegs(tokenId: bigint): bigint {\n let count = 0n\n for (let i = 0n; i < TOKEN_ID_BITS.MAX_LEGS; i++) {\n const leg = decodeLeg(tokenId, i)\n if (leg.optionRatio > 0n) {\n count++\n }\n }\n return count\n}\n\n/**\n * Decode all active legs from a TokenId.\n *\n * @param tokenId - The TokenId to decode\n * @returns Array of decoded legs (only active legs with optionRatio > 0)\n */\nexport function decodeAllLegs(tokenId: bigint): DecodedLeg[] {\n const legs: DecodedLeg[] = []\n for (let i = 0n; i < TOKEN_ID_BITS.MAX_LEGS; i++) {\n const leg = decodeLeg(tokenId, i)\n if (leg.optionRatio > 0n) {\n legs.push(leg)\n }\n }\n return legs\n}\n","/**\n * TokenId builder for the Panoptic v2 SDK.\n * @module v2/tokenId/builder\n */\n\nimport { InvalidTokenIdParameterError } from '../errors'\nimport { LEG_LIMITS, TOKEN_ID_BITS } from './constants'\nimport { type EncodeLegParams, addLegToTokenId } from './encoding'\n\n/**\n * Leg configuration for the builder.\n */\nexport interface LegConfig {\n /** Asset index (0 or 1) */\n asset: bigint\n /** Option ratio (1-127) */\n optionRatio: bigint\n /** Whether this is a long position */\n isLong: boolean\n /** Token type (0 or 1) */\n tokenType: bigint\n /** Risk partner leg index (defaults to self) */\n riskPartner?: bigint\n /** Strike tick (center of the range) */\n strike: bigint\n /** Width in tick spacing units (0 for loans/credits) */\n width: bigint\n}\n\n/**\n * Loan/credit leg configuration.\n * Uses width=0 encoding to signal the loan/credit branch.\n */\nexport interface LoanCreditConfig {\n /** Asset index (0 or 1) */\n asset: bigint\n /** Token type (0 or 1) - which token to borrow/lend */\n tokenType: bigint\n /** Strike tick (price point for the loan/credit) */\n strike: bigint\n /** Option ratio (1-127, defaults to 1) */\n optionRatio?: bigint\n /** Risk partner leg index (defaults to self) */\n riskPartner?: bigint\n}\n\n/**\n * TokenId builder interface.\n * Provides a fluent API for constructing TokenIds.\n */\nexport interface TokenIdBuilder {\n /**\n * Add a leg to the TokenId.\n * @param config - The leg configuration\n * @returns The builder for chaining\n * @throws InvalidTokenIdParameterError if leg parameters are invalid\n */\n addLeg: (config: LegConfig) => TokenIdBuilder\n\n /**\n * Add a call leg. A call is when tokenType === asset.\n * @param config - Partial leg config (tokenType set automatically based on asset, asset defaults to 0)\n * @returns The builder for chaining\n */\n addCall: (config: Omit<LegConfig, 'tokenType' | 'asset'> & { asset?: bigint }) => TokenIdBuilder\n\n /**\n * Add a put leg. A put is when tokenType !== asset.\n * @param config - Partial leg config (tokenType set automatically based on asset, asset defaults to 0)\n * @returns The builder for chaining\n */\n addPut: (config: Omit<LegConfig, 'tokenType' | 'asset'> & { asset?: bigint }) => TokenIdBuilder\n\n /**\n * Add a loan leg (borrow liquidity). Uses width=0 with isLong=false.\n *\n * A loan borrows liquidity from the pool at a specific strike price.\n * The borrower receives the token and owes interest (streaming premium).\n *\n * @param config - Loan configuration (tokenType, strike, optionRatio)\n * @returns The builder for chaining\n */\n addLoan: (config: LoanCreditConfig) => TokenIdBuilder\n\n /**\n * Add a credit leg (lend liquidity). Uses width=0 with isLong=true.\n *\n * A credit lends liquidity to the pool at a specific strike price.\n * The lender deposits the token and earns interest (streaming premium).\n *\n * @param config - Credit configuration (tokenType, strike, optionRatio)\n * @returns The builder for chaining\n */\n addCredit: (config: LoanCreditConfig) => TokenIdBuilder\n\n /**\n * Build the final TokenId.\n * @returns The constructed TokenId\n * @throws InvalidTokenIdParameterError if the TokenId has no legs\n */\n build: () => bigint\n\n /**\n * Get the current number of legs.\n * @returns The leg count\n */\n legCount: () => bigint\n\n /**\n * Reset the builder to start fresh with just the pool ID.\n * @returns The builder for chaining\n */\n reset: () => TokenIdBuilder\n}\n\n/**\n * Create a TokenId builder from an encoded pool ID.\n *\n * Use the 64-bit poolId from `getPool().poolId` or `fetchPoolId()`.\n * For offline encoding, use `encodePoolId()` or `encodeV4PoolId()` first.\n *\n * @param poolId - The encoded 64-bit pool ID\n * @returns A TokenId builder instance\n *\n * @example\n * ```typescript\n * const pool = await getPool({ client, poolAddress, chainId })\n * const tokenId = createTokenIdBuilder(pool.poolId)\n * .addCall({ strike: 100n, width: 10n, optionRatio: 1n, isLong: false })\n * .addPut({ strike: -100n, width: 10n, optionRatio: 1n, isLong: false })\n * .build()\n * ```\n */\nexport function createTokenIdBuilder(poolId: bigint): TokenIdBuilder {\n let tokenId = poolId\n let currentLegIndex = 0n\n\n const validateLegConfig = (config: LegConfig, legIndex: bigint): void => {\n if (legIndex >= TOKEN_ID_BITS.MAX_LEGS) {\n throw new InvalidTokenIdParameterError(0n) // Too many legs\n }\n\n if (config.optionRatio < 1n || config.optionRatio > LEG_LIMITS.MAX_RATIO) {\n throw new InvalidTokenIdParameterError(1n) // Invalid option ratio\n }\n\n // width == 0 is valid for loans/credits, otherwise must be 1-4095\n if (config.width < 0n || config.width > LEG_LIMITS.MAX_WIDTH) {\n throw new InvalidTokenIdParameterError(2n) // Invalid width\n }\n\n if (config.strike < LEG_LIMITS.MIN_STRIKE || config.strike > LEG_LIMITS.MAX_STRIKE) {\n throw new InvalidTokenIdParameterError(3n) // Invalid strike\n }\n\n if (config.asset !== 0n && config.asset !== 1n) {\n throw new InvalidTokenIdParameterError(4n) // Invalid asset\n }\n\n if (config.tokenType !== 0n && config.tokenType !== 1n) {\n throw new InvalidTokenIdParameterError(5n) // Invalid tokenType\n }\n\n const riskPartner = config.riskPartner ?? legIndex\n if (riskPartner < 0n || riskPartner > 3n) {\n throw new InvalidTokenIdParameterError(6n) // Invalid risk partner\n }\n }\n\n const builder: TokenIdBuilder = {\n addLeg(config: LegConfig): TokenIdBuilder {\n validateLegConfig(config, currentLegIndex)\n\n const leg: EncodeLegParams = {\n index: currentLegIndex,\n asset: config.asset,\n optionRatio: config.optionRatio,\n isLong: config.isLong ? 1n : 0n,\n tokenType: config.tokenType,\n riskPartner: config.riskPartner ?? currentLegIndex,\n strike: config.strike,\n width: config.width,\n }\n\n tokenId = addLegToTokenId(tokenId, leg)\n currentLegIndex++\n\n return builder\n },\n\n addCall(config: Omit<LegConfig, 'tokenType' | 'asset'> & { asset?: bigint }): TokenIdBuilder {\n const asset = config.asset ?? 0n\n return builder.addLeg({\n ...config,\n tokenType: asset, // Call: tokenType === asset\n asset,\n })\n },\n\n addPut(config: Omit<LegConfig, 'tokenType' | 'asset'> & { asset?: bigint }): TokenIdBuilder {\n const asset = config.asset ?? 0n\n return builder.addLeg({\n ...config,\n tokenType: asset === 0n ? 1n : 0n, // Put: tokenType !== asset\n asset,\n })\n },\n\n addLoan(config: LoanCreditConfig): TokenIdBuilder {\n // Loan: width=0, isLong=false (borrowing liquidity)\n // asset is set to same as tokenType for loans\n return builder.addLeg({\n asset: config.asset,\n optionRatio: config.optionRatio ?? 1n,\n isLong: false,\n tokenType: config.tokenType,\n riskPartner: config.riskPartner,\n strike: config.strike,\n width: 0n, // width=0 signals loan/credit branch\n })\n },\n\n addCredit(config: LoanCreditConfig): TokenIdBuilder {\n // Credit: width=0, isLong=true (lending liquidity)\n // asset is set to same as tokenType for credits\n return builder.addLeg({\n asset: config.asset,\n optionRatio: config.optionRatio ?? 1n,\n isLong: true,\n tokenType: config.tokenType,\n riskPartner: config.riskPartner,\n strike: config.strike,\n width: 0n, // width=0 signals loan/credit branch\n })\n },\n\n build(): bigint {\n if (currentLegIndex === 0n) {\n throw new InvalidTokenIdParameterError(7n) // No legs\n }\n return tokenId\n },\n\n legCount(): bigint {\n return currentLegIndex\n },\n\n reset(): TokenIdBuilder {\n tokenId = poolId\n currentLegIndex = 0n\n return builder\n },\n }\n\n return builder\n}\n","/**\n * Shared loan utilities for swap and lending modules.\n * @module v2/writes/loanUtils\n */\n\nimport type { Address } from 'viem'\n\nimport {\n InputListFailError,\n LoanSlotExhaustedError,\n MissingPositionIdsError,\n parsePanopticError,\n SwapTokenMismatchError,\n} from '../errors'\nimport type { StorageAdapter } from '../storage'\nimport { getTrackedPositionIds } from '../sync/getTrackedPositionIds'\nimport { createTokenIdBuilder } from '../tokenId/builder'\n\n/** Maximum retry attempts on InputListFail */\nexport const MAX_RETRIES = 3\n\n/**\n * Resolve token index (0 or 1) for the given token address against the pool.\n * Throws SwapTokenMismatchError if the token isn't in the pool.\n */\nexport function 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 * Resolve existing position IDs from explicit param or storage.\n */\nexport async function resolvePositionIds(\n explicit: bigint[] | undefined,\n storage: StorageAdapter | undefined,\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n): Promise<bigint[]> {\n if (explicit !== undefined) return explicit\n if (storage) {\n return getTrackedPositionIds({ chainId, poolAddress, account, storage })\n }\n throw new MissingPositionIdsError()\n}\n\n/**\n * Check if a caught error is an InputListFail contract revert.\n * Works with both raw viem errors and parsed PanopticError instances.\n */\nexport function isInputListFailError(error: unknown): boolean {\n if (error instanceof InputListFailError) return true\n const parsed = parsePanopticError(error)\n return parsed?.errorName === 'InputListFail'\n}\n\n/**\n * Build a unique loan tokenId that doesn't collide with existing positions.\n * Bumps optionRatio (1-127) and returns adjusted size to maintain equivalent exposure.\n *\n * @param asset - Which token denominates the positionSize (0 or 1).\n */\nexport function buildUniqueLoan(\n poolId: bigint,\n asset: bigint,\n tokenType: bigint,\n currentTick: bigint,\n tickSpacing: bigint,\n existingPositionIds: bigint[],\n positionSize: bigint,\n): { tokenId: bigint; adjustedSize: bigint } {\n // Floor-align to tick spacing (bigint % preserves sign, so handle negatives)\n const mod = currentTick % tickSpacing\n let strike = currentTick - ((mod + tickSpacing) % tickSpacing)\n\n for (let ratio = 1n; ratio <= 127n; ratio++) {\n const tokenId = createTokenIdBuilder(poolId)\n .addLoan({ asset, tokenType, strike, optionRatio: ratio })\n .build()\n\n if (!existingPositionIds.includes(tokenId)) {\n const adjustedSize = positionSize / ratio\n if (adjustedSize === 0n || positionSize % ratio !== 0n) {\n continue\n }\n return { tokenId, adjustedSize }\n }\n }\n\n // Fallback: try different strikes at ratio=1\n const mod2 = currentTick % tickSpacing\n strike = currentTick - ((mod2 + tickSpacing) % tickSpacing) + tickSpacing\n for (let i = 0; i < 100; i++) {\n const tokenId = createTokenIdBuilder(poolId).addLoan({ asset, tokenType, strike }).build()\n\n if (!existingPositionIds.includes(tokenId)) {\n return { tokenId, adjustedSize: positionSize }\n }\n strike += tickSpacing\n }\n\n throw new LoanSlotExhaustedError()\n}\n","/**\n * Swap functions for the Panoptic v2 SDK.\n *\n * Implements token swaps via Panoptic's loan mechanism:\n * open a loan with swapAtMint and immediately close it.\n *\n * @module v2/writes/swap\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { MaxRetriesExceededError } from '../errors'\nimport { tickLimits } from '../formatters/tick'\nimport { getPool } from '../reads/pool'\nimport type { StorageAdapter } from '../storage'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport {\n buildUniqueLoan,\n isInputListFailError,\n MAX_RETRIES,\n resolvePositionIds,\n resolveTokenIndex,\n} from './loanUtils'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for swapExactOut.\n */\nexport interface SwapExactOutParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID (required for pool data fetch) */\n chainId: bigint\n /** Token address you want to receive */\n tokenOut: Address\n /** Exact amount of tokenOut to receive */\n amountOut: bigint\n /** Slippage tolerance in bps (e.g. 500n = 5%) */\n slippageBps: bigint\n /** Existing position IDs. If omitted, resolved from storage. */\n existingPositionIds?: bigint[]\n /** Storage adapter for position ID resolution */\n storage?: StorageAdapter\n /** Builder code for referral fee attribution. Defaults to `0n`. */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Parameters for swapExactIn.\n */\nexport interface SwapExactInParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID (required for pool data fetch) */\n chainId: bigint\n /** Token address you want to sell */\n tokenIn: Address\n /** Exact amount of tokenIn to spend */\n amountIn: bigint\n /** Slippage tolerance in bps (e.g. 500n = 5%) */\n slippageBps: bigint\n /** Existing position IDs. If omitted, resolved from storage. */\n existingPositionIds?: bigint[]\n /** Storage adapter for position ID resolution */\n storage?: StorageAdapter\n /** Builder code for referral fee attribution. Defaults to `0n`. */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Swap tokens using Panoptic's exact-output mechanism.\n *\n * Opens a loan with `swapAtMint=true` and immediately burns it with `swapAtMint=false`.\n * The user receives exactly `amountOut` of `tokenOut`.\n *\n * @param params - Swap parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await swapExactOut({\n * client, walletClient, account, poolAddress,\n * chainId: 11155111n,\n * tokenOut: WETH_ADDRESS,\n * amountOut: 5n * 10n**16n, // 0.05 WETH\n * slippageBps: 500n, // 5% slippage\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function swapExactOut(params: SwapExactOutParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n tokenOut,\n amountOut,\n slippageBps,\n existingPositionIds: explicitIds,\n storage,\n builderCode = 0n,\n txOverrides,\n } = params\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n // Re-fetch pool + positions on each attempt for freshness\n const [pool, positionIds] = await Promise.all([\n getPool({ client, poolAddress, chainId }),\n resolvePositionIds(explicitIds, storage, chainId, poolAddress, account),\n ])\n\n const token0 = pool.collateralTracker0.token\n const token1 = pool.collateralTracker1.token\n const tokenOutIndex = resolveTokenIndex(tokenOut, token0, token1)\n\n // For exact output: borrow the OTHER token, swap it to tokenOut\n const tokenType = tokenOutIndex === 0n ? 1n : 0n\n\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n\n // asset = tokenOutIndex so positionSize is denominated in tokenOut units\n const { tokenId: loanTokenId, adjustedSize } = buildUniqueLoan(\n pool.poolId,\n tokenOutIndex,\n tokenType,\n pool.currentTick,\n pool.tickSpacing,\n positionIds,\n amountOut,\n )\n\n // Op 1 (mint): loan with swapAtMint=true → borrow + swap\n // swapAtMint=true → descending tick limits: [high, low, spread]\n const mintTickLimits: readonly [number, number, number] = [\n Number(tickLimitHigh),\n Number(tickLimitLow),\n 0,\n ]\n\n // Op 2 (burn): same loan with swapAtMint=false → repay without swap\n // swapAtMint=false → ascending tick limits: [low, high, spread]\n const burnTickLimits: readonly [number, number, number] = [\n Number(tickLimitLow),\n Number(tickLimitHigh),\n 0,\n ]\n\n // positionIdList: [mint tokenId, burn tokenId]\n // finalPositionIdList: existing positions (loan opens and closes in same tx, net zero)\n // positionSizes: mint gets the size, burn gets 0n (= burn all)\n const positionIdList = [loanTokenId, loanTokenId]\n const finalPositionIdList = [...positionIds]\n const positionSizes = [adjustedSize, 0n]\n\n try {\n return await submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n positionSizes,\n [mintTickLimits, burnTickLimits],\n false, // usePremiaAsCollateral\n builderCode,\n ],\n txOverrides,\n })\n } catch (error) {\n if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) {\n continue\n }\n throw error\n }\n }\n\n throw new MaxRetriesExceededError('swapExactOut')\n}\n\n/**\n * Swap exact output and wait for confirmation.\n */\nexport async function swapExactOutAndWait(params: SwapExactOutParams): Promise<TxReceipt> {\n const result = await swapExactOut(params)\n return result.wait()\n}\n\n/**\n * Swap tokens using Panoptic's exact-input mechanism.\n *\n * Opens a loan with `swapAtMint=false` (borrows tokenIn to wallet),\n * then burns with `swapAtMint=true` (swaps tokenIn back to repay).\n * The user spends exactly `amountIn` of `tokenIn`.\n *\n * @param params - Swap parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await swapExactIn({\n * client, walletClient, account, poolAddress,\n * chainId: 11155111n,\n * tokenIn: USDC_ADDRESS,\n * amountIn: 1000n * 10n**6n, // 1000 USDC\n * slippageBps: 500n,\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function swapExactIn(params: SwapExactInParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n tokenIn,\n amountIn,\n slippageBps,\n existingPositionIds: explicitIds,\n storage,\n builderCode = 0n,\n txOverrides,\n } = params\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n const [pool, positionIds] = await Promise.all([\n getPool({ client, poolAddress, chainId }),\n resolvePositionIds(explicitIds, storage, chainId, poolAddress, account),\n ])\n\n const token0 = pool.collateralTracker0.token\n const token1 = pool.collateralTracker1.token\n const tokenInIndex = resolveTokenIndex(tokenIn, token0, token1)\n\n // For exact input: borrow tokenIn itself\n const tokenType = tokenInIndex\n\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n\n // asset = tokenInIndex so positionSize is denominated in tokenIn units\n const { tokenId: loanTokenId, adjustedSize } = buildUniqueLoan(\n pool.poolId,\n tokenInIndex,\n tokenType,\n pool.currentTick,\n pool.tickSpacing,\n positionIds,\n amountIn,\n )\n\n // Op 1 (mint): loan with swapAtMint=false → borrow tokenIn to wallet\n // swapAtMint=false → ascending tick limits: [low, high, spread]\n const mintTickLimits: readonly [number, number, number] = [\n Number(tickLimitLow),\n Number(tickLimitHigh),\n 0,\n ]\n\n // Op 2 (burn): same loan with swapAtMint=true → repay with swap\n // swapAtMint=true → descending tick limits: [high, low, spread]\n const burnTickLimits: readonly [number, number, number] = [\n Number(tickLimitHigh),\n Number(tickLimitLow),\n 0,\n ]\n\n // positionSizes: mint gets the size, burn gets 0n (= burn all)\n const positionIdList = [loanTokenId, loanTokenId]\n const finalPositionIdList = [...positionIds]\n const positionSizes = [adjustedSize, 0n]\n\n try {\n return await submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n positionSizes,\n [mintTickLimits, burnTickLimits],\n false,\n builderCode,\n ],\n txOverrides,\n })\n } catch (error) {\n if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) {\n continue\n }\n throw error\n }\n }\n\n throw new MaxRetriesExceededError('swapExactIn')\n}\n\n/**\n * Swap exact input and wait for confirmation.\n */\nexport async function swapExactInAndWait(params: SwapExactInParams): Promise<TxReceipt> {\n const result = await swapExactIn(params)\n return result.wait()\n}\n","/**\n * Wrap / unwrap operations for Backed xStock ERC4626 wrappers.\n *\n * xStocks are rebasing and can't be used in Panoptic/Uniswap pools directly;\n * those trade the non-rebasing **wrapper** (a standard ERC4626 vault whose\n * `asset()` is the underlying xStock). Wrapping is an ERC4626 `deposit`,\n * unwrapping an ERC4626 `redeem`. CoW Swap trades the unwrapped token, so a\n * user who buys an xStock on CoW must wrap it before lending it or selling it\n * through the Uniswap venue.\n *\n * Resolve a token's wrapper with `getXstockWrapper` from `@panoptic-eng/sdk`.\n *\n * @module v2/writes/wrap\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\n/** Minimal ERC4626 surface used by the xStock wrappers. */\nexport const xstockWrapperAbi = [\n {\n type: 'function',\n name: 'deposit',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'assets', type: 'uint256' },\n { name: 'receiver', type: 'address' },\n ],\n outputs: [{ name: 'shares', type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'redeem',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'shares', type: 'uint256' },\n { name: 'receiver', type: 'address' },\n { name: 'owner', type: 'address' },\n ],\n outputs: [{ name: 'assets', type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'asset',\n stateMutability: 'view',\n inputs: [],\n outputs: [{ type: 'address' }],\n },\n {\n type: 'function',\n name: 'previewDeposit',\n stateMutability: 'view',\n inputs: [{ name: 'assets', type: 'uint256' }],\n outputs: [{ name: 'shares', type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'previewRedeem',\n stateMutability: 'view',\n inputs: [{ name: 'shares', type: 'uint256' }],\n outputs: [{ name: 'assets', type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'maxRedeem',\n stateMutability: 'view',\n inputs: [{ name: 'owner', type: 'address' }],\n outputs: [{ name: 'maxShares', type: 'uint256' }],\n },\n] as const\n\n/** Parameters for {@link wrapXstock}. */\nexport interface WrapXstockParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** Wrapper (ERC4626) address — resolve via `getXstockWrapper`. */\n wrapper: Address\n /** Amount of the underlying xStock to wrap. */\n assets: bigint\n /** Receiver of the wrapper shares (defaults to account). */\n receiver?: Address\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Wrap an underlying xStock into its ERC4626 wrapper (`deposit`). Requires a\n * prior ERC20 approval of the underlying to the wrapper address.\n *\n * @returns TxResult with hash and wait function\n */\nexport async function wrapXstock(params: WrapXstockParams): Promise<TxResult> {\n const { client, walletClient, account, wrapper, assets, receiver = account, txOverrides } = params\n return submitWrite({\n client,\n walletClient,\n account,\n address: wrapper,\n abi: xstockWrapperAbi,\n functionName: 'deposit',\n args: [assets, receiver],\n txOverrides,\n })\n}\n\n/** Wrap and wait for confirmation. */\nexport async function wrapXstockAndWait(params: WrapXstockParams): Promise<TxReceipt> {\n const result = await wrapXstock(params)\n return result.wait()\n}\n\n/** Parameters for {@link unwrapXstock}. */\nexport interface UnwrapXstockParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** Wrapper (ERC4626) address — resolve via `getXstockUnderlying`. */\n wrapper: Address\n /** Amount of wrapper shares to unwrap (redeem). */\n shares: bigint\n /** Receiver of the underlying xStock (defaults to account). */\n receiver?: Address\n /** Owner of the shares (defaults to account). */\n owner?: Address\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Unwrap wrapper shares back into the underlying xStock (`redeem`). When\n * `owner` defaults to (or equals) `account` the caller burns their own shares\n * and no approval is needed. Passing a different `owner` redeems on its behalf\n * and requires that owner to have granted the caller an ERC-4626 share\n * allowance (`approve`), or the `redeem` call reverts.\n *\n * @returns TxResult with hash and wait function\n */\nexport async function unwrapXstock(params: UnwrapXstockParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n wrapper,\n shares,\n receiver = account,\n owner = account,\n txOverrides,\n } = params\n return submitWrite({\n client,\n walletClient,\n account,\n address: wrapper,\n abi: xstockWrapperAbi,\n functionName: 'redeem',\n args: [shares, receiver, owner],\n txOverrides,\n })\n}\n\n/** Unwrap and wait for confirmation. */\nexport async function unwrapXstockAndWait(params: UnwrapXstockParams): Promise<TxReceipt> {\n const result = await unwrapXstock(params)\n return result.wait()\n}\n\n/** Parameters for the wrap/unwrap amount previews. */\nexport interface PreviewWrapParams {\n /** Public client */\n client: PublicClient\n /** Wrapper (ERC4626) address. */\n wrapper: Address\n /** Amount to convert: underlying assets for wrap, shares for unwrap. */\n amount: bigint\n}\n\n/**\n * Preview the wrapper shares minted for a given amount of underlying xStock.\n */\nexport async function previewWrap(params: PreviewWrapParams): Promise<bigint> {\n const { client, wrapper, amount } = params\n return client.readContract({\n address: wrapper,\n abi: xstockWrapperAbi,\n functionName: 'previewDeposit',\n args: [amount],\n })\n}\n\n/**\n * Preview the underlying xStock returned for a given amount of wrapper shares.\n */\nexport async function previewUnwrap(params: PreviewWrapParams): Promise<bigint> {\n const { client, wrapper, amount } = params\n return client.readContract({\n address: wrapper,\n abi: xstockWrapperAbi,\n functionName: 'previewRedeem',\n args: [amount],\n })\n}\n\n/**\n * Minimal canonical WETH9 surface used for ETH<->WETH wrapping. Unlike the\n * ERC4626 xStock wrapper, WETH is a 1:1 wrapper: `deposit` is payable and wraps\n * `msg.value`, `withdraw` unwraps an exact amount back to native ETH.\n */\nexport const wethWrapAbi = [\n {\n type: 'function',\n name: 'deposit',\n stateMutability: 'payable',\n inputs: [],\n outputs: [],\n },\n {\n type: 'function',\n name: 'withdraw',\n stateMutability: 'nonpayable',\n inputs: [{ name: 'wad', type: 'uint256' }],\n outputs: [],\n },\n] as const\n\n/** Parameters for {@link wrapEth}. */\nexport interface WrapEthParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** Canonical WETH9 address for the chain. */\n weth: Address\n /** Amount of native ETH to wrap (sent as msg.value). */\n amount: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Wrap native ETH into WETH (`deposit` payable). No approval needed.\n *\n * @returns TxResult with hash and wait function\n */\nexport async function wrapEth(params: WrapEthParams): Promise<TxResult> {\n const { client, walletClient, account, weth, amount, txOverrides } = params\n return submitWrite({\n client,\n walletClient,\n account,\n address: weth,\n abi: wethWrapAbi,\n functionName: 'deposit',\n args: [],\n value: amount,\n txOverrides,\n })\n}\n\n/** Wrap ETH and wait for confirmation. */\nexport async function wrapEthAndWait(params: WrapEthParams): Promise<TxReceipt> {\n const result = await wrapEth(params)\n return result.wait()\n}\n\n/** Parameters for {@link unwrapWeth}. */\nexport interface UnwrapWethParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** Canonical WETH9 address for the chain. */\n weth: Address\n /** Amount of WETH to unwrap back to native ETH. */\n amount: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Unwrap WETH back into native ETH (`withdraw`). Burns the caller's own WETH —\n * no approval needed.\n *\n * @returns TxResult with hash and wait function\n */\nexport async function unwrapWeth(params: UnwrapWethParams): Promise<TxResult> {\n const { client, walletClient, account, weth, amount, txOverrides } = params\n return submitWrite({\n client,\n walletClient,\n account,\n address: weth,\n abi: wethWrapAbi,\n functionName: 'withdraw',\n args: [amount],\n txOverrides,\n })\n}\n\n/** Unwrap WETH and wait for confirmation. */\nexport async function unwrapWethAndWait(params: UnwrapWethParams): Promise<TxReceipt> {\n const result = await unwrapWeth(params)\n return result.wait()\n}\n","/**\n * TokenId decoding for the Panoptic v2 SDK.\n * @module v2/tokenId/decode\n */\n\nimport type { TokenIdLeg } from '../types'\nimport {\n type DecodedLeg,\n countLegs,\n decodeAllLegs,\n decodePoolId,\n decodeTickSpacing,\n decodeVegoid,\n} from './encoding'\n\n/**\n * Decoded TokenId data.\n */\nexport interface DecodedTokenId {\n /** The original TokenId */\n tokenId: bigint\n /** The pool ID portion as hex */\n poolId: `0x${string}`\n /** The vegoid value */\n vegoid: bigint\n /** The tick spacing */\n tickSpacing: bigint\n /** The decoded legs */\n legs: TokenIdLeg[]\n /** Number of active legs */\n legCount: bigint\n}\n\n/**\n * Convert a DecodedLeg to TokenIdLeg format.\n *\n * @param leg - The decoded leg from encoding utils\n * @param tickSpacing - The tick spacing for calculating tick bounds\n * @returns The TokenIdLeg format\n */\nfunction convertToTokenIdLeg(leg: DecodedLeg, tickSpacing: bigint): TokenIdLeg {\n // Calculate tick bounds from strike and width\n // width is in tick spacing units, so actual width = width * tickSpacing\n const halfWidth = (leg.width * tickSpacing) / 2n\n const tickLower = leg.strike - halfWidth\n const tickUpper = leg.strike + halfWidth\n\n return {\n index: leg.index,\n asset: leg.asset,\n optionRatio: leg.optionRatio,\n isLong: leg.isLong,\n tokenType: leg.tokenType,\n riskPartner: leg.riskPartner,\n strike: leg.strike,\n width: leg.width,\n tickLower,\n tickUpper,\n }\n}\n\n/**\n * Decode a TokenId into its component parts.\n *\n * @param tokenId - The TokenId to decode\n * @returns The decoded TokenId data\n *\n * @example\n * ```typescript\n * const decoded = decodeTokenId(tokenId)\n * console.log(decoded.legs) // Array of legs\n * console.log(decoded.tickSpacing) // Tick spacing\n * ```\n */\nexport function decodeTokenId(tokenId: bigint): DecodedTokenId {\n const poolId = decodePoolId(tokenId)\n const vegoid = decodeVegoid(tokenId)\n const tickSpacing = decodeTickSpacing(tokenId)\n const rawLegs = decodeAllLegs(tokenId)\n const numLegs = countLegs(tokenId)\n\n const legs = rawLegs.map((leg) => convertToTokenIdLeg(leg, tickSpacing))\n\n return {\n tokenId,\n poolId,\n vegoid,\n tickSpacing,\n legs,\n legCount: numLegs,\n }\n}\n\n/**\n * Validate that a TokenId has the expected pool ID.\n *\n * @param tokenId - The TokenId to validate\n * @param expectedPoolId - The expected pool ID\n * @returns True if the pool IDs match\n */\nexport function validatePoolId(tokenId: bigint, expectedPoolId: bigint): boolean {\n const actualPoolId = tokenId & ((1n << 64n) - 1n)\n return actualPoolId === expectedPoolId\n}\n\n/**\n * Check if a TokenId represents a long position (any leg is long).\n *\n * @param tokenId - The TokenId to check\n * @returns True if any leg is long\n */\nexport function hasLongLeg(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.some((leg) => leg.isLong)\n}\n\n/**\n * Check if a TokenId represents a short-only position.\n *\n * @param tokenId - The TokenId to check\n * @returns True if all legs are short\n */\nexport function isShortOnly(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.length > 0 && legs.every((leg) => !leg.isLong)\n}\n\n/**\n * Check if a TokenId represents a spread (legs with different risk partners).\n *\n * @param tokenId - The TokenId to check\n * @returns True if any leg has a different risk partner\n */\nexport function isSpread(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.some((leg) => leg.riskPartner !== leg.index)\n}\n\n/**\n * Get the asset index for a TokenId (from the first leg).\n *\n * @param tokenId - The TokenId\n * @returns The asset index (0 or 1), or undefined if no legs\n */\nexport function getAssetIndex(tokenId: bigint): bigint | undefined {\n const legs = decodeAllLegs(tokenId)\n if (legs.length === 0) {\n return undefined\n }\n return legs[0].asset\n}\n\n/**\n * Check if a leg is a loan (width=0 and isLong=false).\n *\n * Loans borrow liquidity from the pool at a specific strike price.\n *\n * @param leg - The decoded leg to check\n * @returns True if the leg is a loan\n */\nexport function isLoanLeg(leg: DecodedLeg): boolean {\n return leg.width === 0n && !leg.isLong\n}\n\n/**\n * Check if a leg is a credit (width=0 and isLong=true).\n *\n * Credits lend liquidity to the pool at a specific strike price.\n *\n * @param leg - The decoded leg to check\n * @returns True if the leg is a credit\n */\nexport function isCreditLeg(leg: DecodedLeg): boolean {\n return leg.width === 0n && leg.isLong\n}\n\n/**\n * Check if a TokenId has any loan legs.\n *\n * @param tokenId - The TokenId to check\n * @returns True if any leg is a loan (width=0, isLong=false)\n */\nexport function hasLoanLeg(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.some(isLoanLeg)\n}\n\n/**\n * Check if a TokenId has any credit legs.\n *\n * @param tokenId - The TokenId to check\n * @returns True if any leg is a credit (width=0, isLong=true)\n */\nexport function hasCreditLeg(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.some(isCreditLeg)\n}\n\n/**\n * Check if a TokenId is a pure loan (all legs are loans).\n *\n * @param tokenId - The TokenId to check\n * @returns True if all legs are loans\n */\nexport function isLoan(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.length > 0 && legs.every(isLoanLeg)\n}\n\n/**\n * Check if a TokenId is a pure credit (all legs are credits).\n *\n * @param tokenId - The TokenId to check\n * @returns True if all legs are credits\n */\nexport function isCredit(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.length > 0 && legs.every(isCreditLeg)\n}\n\n/**\n * Check if a TokenId contains loan or credit legs (width=0).\n *\n * @param tokenId - The TokenId to check\n * @returns True if any leg has width=0 (loan or credit)\n */\nexport function hasLoanOrCredit(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.some((leg) => leg.width === 0n)\n}\n","/**\n * Token flow simulation utility using PanopticPool.multicall.\n *\n * Uses getAssetsOf-dispatch-getAssetsOf pattern within a single eth_call\n * to measure exact collateral asset movements from any dispatch call.\n *\n * @module v2/simulations/tokenFlow\n */\n\nimport {\n type Address,\n type Hex,\n type PublicClient,\n decodeFunctionResult,\n encodeFunctionData,\n} from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { panopticErrorsAbi } from '../errors/errorsAbi'\n\n/**\n * PanopticPool getAssetsOf ABI.\n * Returns collateral assets (shares converted to underlying) for an account.\n */\nconst getAssetsOfAbi = [\n {\n type: 'function',\n name: 'getAssetsOf',\n inputs: [{ name: 'account', type: 'address' }],\n outputs: [\n { name: 'assets0', type: 'uint256' },\n { name: 'assets1', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n] as const\n\n/**\n * PanopticPool multicall ABI (inherited from Uniswap).\n * Uses delegatecall, preserving msg.sender throughout the chain.\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 // Include error definitions so viem can decode revert data with full args\n ...panopticErrorsAbi,\n] as const\n\n/**\n * Token flow result from simulation.\n * Measures collateral asset changes via getAssetsOf-dispatch-getAssetsOf pattern.\n */\nexport interface TokenFlow {\n /** Token 0 collateral change (negative = user deposits, positive = user receives) */\n delta0: bigint\n /** Token 1 collateral change (negative = user deposits, positive = user receives) */\n delta1: bigint\n /** Collateral assets in token 0 before the call */\n balanceBefore0: bigint\n /** Collateral assets in token 1 before the call */\n balanceBefore1: bigint\n /** Collateral assets in token 0 after the call */\n balanceAfter0: bigint\n /** Collateral assets in token 1 after the call */\n balanceAfter1: bigint\n /** Pool tick before the operation */\n tickBefore: bigint | null\n /** Pool tick after the operation */\n tickAfter: bigint | null\n}\n\n/**\n * Parameters for simulateWithTokenFlow.\n */\nexport interface SimulateWithTokenFlowParams {\n /** viem public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** User address whose collateral changes we're measuring */\n user: Address\n /** Encoded call data (typically dispatch) */\n callData: Hex\n /** Optional block number for simulation */\n blockNumber?: bigint\n /**\n * Optional additional encoded calls to append after the 5-call pattern.\n * These execute post-dispatch within the same multicall (same state).\n * Raw encoded bytes are returned in `postCallResults`.\n */\n postCallData?: Hex[]\n /**\n * Optional additional encoded calls to insert between the pre-dispatch\n * `getAssetsOf` / `getCurrentTick` and the target call. These execute\n * pre-dispatch within the same multicall — useful for reading per-position\n * data (e.g. `getFullPositionsData`) against the original `positionIdList`\n * before state mutates. Raw encoded bytes are returned in `preCallResults`.\n */\n preCallData?: Hex[]\n}\n\n/**\n * Result of simulateWithTokenFlow.\n */\nexport interface SimulateWithTokenFlowResult {\n /** Whether the simulation succeeded */\n success: boolean\n /** Token flow data (only if success) */\n tokenFlow?: TokenFlow\n /** Error message (only if failed) */\n error?: string\n /** Raw error object preserving viem cause chain and revert data */\n rawError?: Error\n /** Gas estimate for the inner call */\n gasEstimate: bigint\n /** Raw results from postCallData entries (only if success and postCallData was provided) */\n postCallResults?: Hex[]\n /** Raw results from preCallData entries (only if success and preCallData was provided) */\n preCallResults?: Hex[]\n}\n\n/**\n * Simulate a contract call and measure token flow using PanopticPool.multicall.\n *\n * This function uses PanopticPool's inherited multicall (delegatecall-based) to chain:\n * 1. getAssetsOf(user) - read collateral assets before\n * 2. getCurrentTick() - read pool tick before\n * 3. Execute the target call (e.g., dispatch)\n * 4. getCurrentTick() - read pool tick after\n * 5. getAssetsOf(user) - read collateral assets after\n *\n * ## Why PanopticPool.multicall instead of Multicall3?\n * - Measures **collateral assets** (shares → underlying), not raw wallet balances\n * - Uses **delegatecall**, preserving msg.sender throughout the chain\n * - Single contract interaction with PanopticPool\n * - Correctly reflects what happens during position operations\n *\n * ## Same-Block Guarantee\n * All operations execute within a single eth_call, ensuring atomic consistency.\n *\n * @param params - Simulation parameters\n * @returns Token flow result\n *\n * @example\n * ```typescript\n * const callData = encodeFunctionData({\n * abi: panopticPoolV2Abi,\n * functionName: 'dispatch',\n * args: [positionIdList, finalPositionIdList, positionSizes, tickAndSpreadLimits, false, 0n],\n * })\n *\n * const result = await simulateWithTokenFlow({\n * client,\n * poolAddress,\n * user: userAddress,\n * callData,\n * })\n *\n * if (result.success) {\n * console.log('Token 0 change:', result.tokenFlow.delta0)\n * console.log('Token 1 change:', result.tokenFlow.delta1)\n * }\n * ```\n */\nexport async function simulateWithTokenFlow(\n params: SimulateWithTokenFlowParams,\n): Promise<SimulateWithTokenFlowResult> {\n const { client, poolAddress, user, callData, blockNumber, postCallData, preCallData } = params\n\n // Encode getAssetsOf call\n const getAssetsOfCallData = encodeFunctionData({\n abi: getAssetsOfAbi,\n functionName: 'getAssetsOf',\n args: [user],\n })\n\n // Encode getCurrentTick call\n const getCurrentTickCallData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n })\n\n const preLen = preCallData?.length ?? 0\n\n // Build multicall: [getAssetsOf, getCurrentTick, ...preCallData, targetCall, getCurrentTick, getAssetsOf, ...postCallData]\n const multicallData: Hex[] = [\n getAssetsOfCallData,\n getCurrentTickCallData,\n ...(preCallData ?? []),\n callData,\n getCurrentTickCallData,\n getAssetsOfCallData,\n ...(postCallData ?? []),\n ]\n\n try {\n // Execute via simulateContract on PanopticPool's multicall\n const { result } = await client.simulateContract({\n address: poolAddress,\n abi: multicallAbi,\n functionName: 'multicall',\n args: [multicallData],\n account: user,\n blockNumber,\n })\n\n // Decode getAssetsOf results\n const decodeAssets = (data: Hex): { assets0: bigint; assets1: bigint } => {\n const decoded = decodeFunctionResult({\n abi: getAssetsOfAbi,\n functionName: 'getAssetsOf',\n data,\n })\n return { assets0: decoded[0], assets1: decoded[1] }\n }\n\n // Decode getCurrentTick result (int24 decodes as number, convert to bigint)\n const decodeTick = (data: Hex): bigint => {\n return BigInt(\n decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n data,\n }),\n )\n }\n\n const assetsBefore = decodeAssets(result[0])\n const tickBefore = decodeTick(result[1])\n // result[2..2+preLen-1] are preCallData results\n // result[2+preLen] is the target call result (dispatch)\n const tickAfter = decodeTick(result[3 + preLen])\n const assetsAfter = decodeAssets(result[4 + preLen])\n\n const preCallResults = preLen > 0 ? (result.slice(2, 2 + preLen) as Hex[]) : undefined\n const postCallResults =\n postCallData && postCallData.length > 0 ? (result.slice(5 + preLen) as Hex[]) : undefined\n\n const delta0 = assetsAfter.assets0 - assetsBefore.assets0\n const delta1 = assetsAfter.assets1 - assetsBefore.assets1\n\n // Estimate gas for the target call directly\n let gasEstimate = 0n\n try {\n gasEstimate = await client.estimateGas({\n account: user,\n to: poolAddress,\n data: callData,\n blockNumber,\n })\n } catch {\n // Gas estimation may fail, use 0\n }\n\n return {\n success: true,\n tokenFlow: {\n delta0,\n delta1,\n balanceBefore0: assetsBefore.assets0,\n balanceBefore1: assetsBefore.assets1,\n balanceAfter0: assetsAfter.assets0,\n balanceAfter1: assetsAfter.assets1,\n tickBefore,\n tickAfter,\n },\n gasEstimate,\n postCallResults,\n preCallResults,\n }\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Simulation failed',\n rawError: error instanceof Error ? error : undefined,\n gasEstimate: 0n,\n }\n }\n}\n\n/**\n * Parameters for getting pool tokens.\n */\nexport interface GetPoolTokensParams {\n /** viem public client */\n client: PublicClient\n /** Pool address */\n poolAddress: Address\n /** Optional block number */\n blockNumber?: bigint\n}\n\n/**\n * Pool token addresses result.\n */\nexport interface PoolTokens {\n /** Token 0 address */\n token0: Address\n /** Token 1 address */\n token1: Address\n /** Collateral tracker 0 address */\n collateralTracker0: Address\n /** Collateral tracker 1 address */\n collateralTracker1: Address\n}\n\n/**\n * Get pool token addresses for reference.\n *\n * @param params - Parameters\n * @returns Pool token addresses\n */\nexport async function getPoolTokensForSimulation(params: GetPoolTokensParams): Promise<PoolTokens> {\n const { client, poolAddress, blockNumber } = params\n\n // Minimal ABI for the calls we need\n const poolAbi = [\n {\n type: 'function',\n name: 'collateralToken0',\n inputs: [],\n outputs: [{ type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'collateralToken1',\n inputs: [],\n outputs: [{ type: 'address' }],\n stateMutability: 'view',\n },\n ] as const\n\n const collateralAbi = [\n {\n type: 'function',\n name: 'asset',\n inputs: [],\n outputs: [{ type: 'address' }],\n stateMutability: 'view',\n },\n ] as const\n\n // Get collateral tracker addresses\n const [ct0, ct1] = await client.multicall({\n contracts: [\n { address: poolAddress, abi: poolAbi, functionName: 'collateralToken0' },\n { address: poolAddress, abi: poolAbi, functionName: 'collateralToken1' },\n ],\n blockNumber,\n allowFailure: false,\n })\n\n // Get underlying token addresses from collateral trackers\n const [token0, token1] = await client.multicall({\n contracts: [\n { address: ct0, abi: collateralAbi, functionName: 'asset' },\n { address: ct1, abi: collateralAbi, functionName: 'asset' },\n ],\n blockNumber,\n allowFailure: false,\n })\n\n return {\n token0,\n token1,\n collateralTracker0: ct0,\n collateralTracker1: ct1,\n }\n}\n","/**\n * Open position simulation for the Panoptic v2 SDK.\n * @module v2/simulations/simulateOpenPosition\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { decodeFunctionResult, encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError } from '../errors'\nimport { calculatePositionGreeks } from '../greeks'\nimport { getPool } from '../reads/pool'\nimport { decodeTokenId } from '../tokenId/decode'\nimport type { OpenPositionSimulation, SimulationResult } from '../types'\nimport { decodeLeftRightUnsigned } from '../writes/utils'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\n/**\n * Parameters for simulating position opening.\n */\nexport interface SimulateOpenPositionParams {\n /** Public client */\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 /**\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 mint 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 /** Chain ID (required for pool data fetch used in greeks) */\n chainId?: bigint\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate opening a position.\n *\n * Uses PanopticPool.multicall with getAssetsOf-dispatch-getAssetsOf pattern\n * to measure exact collateral asset movements, then enriches with decoded\n * position data and client-side greeks.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with position data or error\n *\n * @example\n * ```typescript\n * import { MIN_TICK, MAX_TICK } from '@panoptic/sdk'\n *\n * const result = await simulateOpenPosition({\n * client,\n * poolAddress,\n * account,\n * existingPositionIds: [],\n * tokenId,\n * positionSize: 1n,\n * tickLimitLow: MIN_TICK,\n * tickLimitHigh: MAX_TICK,\n * swapAtMint: false,\n * chainId: 11155111n, // Sepolia\n * })\n *\n * if (result.success) {\n * console.log('Gas estimate:', result.gasEstimate)\n * console.log('Token 0 required:', result.data.amount0Required)\n * console.log('Token 1 required:', result.data.amount1Required)\n * console.log('Delta:', result.data.greeks.delta)\n * } else {\n * console.log('Error:', result.error)\n * }\n * ```\n */\nexport async function simulateOpenPosition(\n params: SimulateOpenPositionParams,\n): Promise<SimulationResult<OpenPositionSimulation>> {\n const {\n client,\n poolAddress,\n account,\n existingPositionIds,\n tokenId,\n positionSize,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit = 0n,\n swapAtMint = false,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n chainId,\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 position lists for dispatch:\n // - positionIdList: positions being minted in this call (just the new tokenId)\n // - finalPositionIdList: all positions the user will have after the mint\n const positionIdList = [tokenId]\n const finalPositionIdList = [...existingPositionIds, tokenId]\n\n // Encode dispatch call data\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n // ABI declares uint128 but TS only knows bigint — viem/abitype limitation\n [BigInt(positionSize) as unknown as bigint & { readonly __uint128: true }],\n [tickLimits],\n usePremiaAsCollateral,\n builderCode,\n ],\n })\n\n // Encode getFullPositionsData to run post-dispatch in the same multicall\n const getFullPositionsDataCallData = 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 postCallData: [getFullPositionsDataCallData],\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\n // Decode post-mint collateral requirements from getFullPositionsData result\n let postMintCollateralReqToken0 = 0n\n let postMintCollateralReqToken1 = 0n\n const perPositionCollateralReqs: { token0: bigint; token1: bigint }[] = []\n if (flowResult.postCallResults?.[0]) {\n try {\n const decoded = decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n data: flowResult.postCallResults[0],\n })\n // Result: [shortPremium, longPremium, balances[], collateralReqs[], netPremia[]]\n const collateralReqs = decoded[3]\n if (collateralReqs.length > 0) {\n // Each entry is a LeftRightUnsigned: right=token0, left=token1\n // Sum across all positions in finalPositionIdList\n for (const packed of collateralReqs) {\n const req = decodeLeftRightUnsigned(packed)\n postMintCollateralReqToken0 += req.right\n postMintCollateralReqToken1 += req.left\n perPositionCollateralReqs.push({ token0: req.right, token1: req.left })\n }\n }\n } catch {\n // Decode failure — leave at 0n\n }\n }\n\n // Decode tokenId to get legs and tick spacing\n const decoded = decodeTokenId(tokenId)\n\n // Fetch pool state for greeks (currentTick, tickSpacing) if chainId provided\n let currentTick = 0n\n let poolTickSpacing = decoded.tickSpacing\n let utilization0 = 0n\n let utilization1 = 0n\n\n if (chainId !== undefined) {\n try {\n const pool = await getPool({ client, poolAddress, chainId, blockNumber: targetBlockNumber })\n currentTick = pool.currentTick\n poolTickSpacing = pool.tickSpacing\n utilization0 = pool.collateralTracker0.utilization\n utilization1 = pool.collateralTracker1.utilization\n } catch {\n // Pool fetch failed - use decoded tickSpacing, skip greeks\n }\n }\n\n // Calculate greeks if we have legs and pool data\n const greeks =\n decoded.legs.length > 0 && (chainId !== undefined || currentTick !== 0n)\n ? calculatePositionGreeks({\n legs: decoded.legs,\n currentTick,\n mintTick: currentTick, // At simulation time, mintTick = currentTick\n positionSize,\n poolTickSpacing,\n })\n : { value: 0n, delta: 0n, gamma: 0n }\n\n const _meta = await metaPromise\n\n // Map token flow to simulation fields:\n // Negative delta = user deposits (required), so amount required = -delta\n const amount0Required = -tokenFlow.delta0\n const amount1Required = -tokenFlow.delta1\n\n const data: OpenPositionSimulation = {\n position: {\n tokenId,\n positionSize,\n owner: account,\n poolAddress,\n legs: decoded.legs,\n poolUtilization0AtMint: utilization0,\n poolUtilization1AtMint: utilization1,\n tickAtMint: currentTick,\n timestampAtMint: _meta.blockTimestamp,\n blockNumberAtMint: _meta.blockNumber,\n swapAtMint,\n premiaOwed0: 0n,\n premiaOwed1: 0n,\n assetIndex: 0n,\n _meta,\n },\n greeks,\n amount0Required,\n amount1Required,\n postCollateral0: tokenFlow.balanceAfter0,\n postCollateral1: tokenFlow.balanceAfter1,\n postMintCollateralReqToken0,\n postMintCollateralReqToken1,\n perPositionCollateralReqs,\n commission0: null, // Embedded in contract logic, not extractable from token flow\n commission1: 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 * Lending API for the Panoptic v2 SDK.\n *\n * Provides Aave/Compound-style supply/borrow/repay/unsupply functions\n * that wrap the lower-level vault and position primitives.\n *\n * @module v2/writes/lending\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { MaxRetriesExceededError, NoLoanPositionsError } from '../errors'\nimport { tickLimits } from '../formatters/tick'\nimport { getPool } from '../reads/pool'\nimport { simulateOpenPosition } from '../simulations/simulateOpenPosition'\nimport type { StorageAdapter } from '../storage'\nimport { getPositionsKey, jsonSerializer } from '../storage'\nimport { getTrackedPositionIds } from '../sync/getTrackedPositionIds'\nimport { isLoan } from '../tokenId/decode'\nimport { decodeAllLegs } from '../tokenId/encoding'\nimport type {\n OpenPositionSimulation,\n SimulationResult,\n TxOverrides,\n TxReceipt,\n TxResult,\n} from '../types'\nimport {\n buildUniqueLoan,\n isInputListFailError,\n MAX_RETRIES,\n resolvePositionIds,\n resolveTokenIndex,\n} from './loanUtils'\nimport { submitWrite } from './utils'\nimport { deposit, withdraw } from './vault'\n\n// ---------------------------------------------------------------------------\n// Parameter types\n// ---------------------------------------------------------------------------\n\n/** Parameters for supplying collateral into a pool. */\nexport interface SupplyParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID */\n chainId: bigint\n /** Token address to supply (must be token0 or token1 of the pool) */\n token: Address\n /** Amount of token to supply */\n amount: bigint\n /** Whether the token is native ETH (requires sending msg.value) */\n isNativeETH?: boolean\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/** Parameters for withdrawing (unsupplying) collateral from a pool. */\nexport interface UnsupplyParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID */\n chainId: bigint\n /** Token address to withdraw (must be token0 or token1 of the pool) */\n token: Address\n /** Amount of token to withdraw */\n amount: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/** Parameters for borrowing tokens via a loan position. */\nexport interface BorrowParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID */\n chainId: bigint\n /** Token address to borrow (must be token0 or token1 of the pool) */\n token: Address\n /** Amount of token to borrow */\n amount: bigint\n /** Slippage tolerance in bps (e.g. 500n = 5%) */\n slippageBps: bigint\n /** Existing position IDs. If omitted, resolved from storage. */\n existingPositionIds?: bigint[]\n /** Storage adapter for position ID resolution and tracking */\n storage?: StorageAdapter\n /** Builder code for fee routing (0 = no builder). */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/** Parameters for repaying a loan (full or partial). */\nexport interface RepayParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID */\n chainId: bigint\n /** TokenId of the loan position to repay */\n loanTokenId: bigint\n /** Amount to repay. If >= current position size, does full repay. */\n amount: bigint\n /** Slippage tolerance in bps (e.g. 500n = 5%) */\n slippageBps: bigint\n /** Current position IDs. If omitted, resolved from storage. */\n existingPositionIds?: bigint[]\n /** Storage adapter for position ID resolution and tracking */\n storage?: StorageAdapter\n /** Builder code for fee routing (0 = no builder). */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve collateral tracker address for a given token in the pool.\n */\nasync function resolveCollateralTracker(\n client: PublicClient,\n poolAddress: Address,\n chainId: bigint,\n token: Address,\n): Promise<Address> {\n const pool = await getPool({ client, poolAddress, chainId })\n const tokenIndex = resolveTokenIndex(\n token,\n pool.collateralTracker0.token,\n pool.collateralTracker1.token,\n )\n return tokenIndex === 0n ? pool.collateralTracker0.address : pool.collateralTracker1.address\n}\n\n/**\n * Save a position ID list to storage.\n */\nasync function savePositionIds(\n storage: StorageAdapter,\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n positionIds: bigint[],\n): Promise<void> {\n const key = getPositionsKey(chainId, poolAddress, account)\n await storage.set(key, jsonSerializer.stringify(positionIds))\n}\n\n// ---------------------------------------------------------------------------\n// supply / unsupply\n// ---------------------------------------------------------------------------\n\n/**\n * Supply collateral into a pool.\n *\n * Resolves the correct collateral tracker from the token address,\n * then delegates to the low-level `deposit()`.\n *\n * @param params - Supply parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await supply({\n * client, walletClient, account, poolAddress,\n * chainId: 11155111n,\n * token: WETH_ADDRESS,\n * amount: 1n * 10n**18n,\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function supply(params: SupplyParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n token,\n amount,\n isNativeETH,\n txOverrides,\n } = params\n const collateralTrackerAddress = await resolveCollateralTracker(\n client,\n poolAddress,\n chainId,\n token,\n )\n return deposit({\n client,\n walletClient,\n account,\n collateralTrackerAddress,\n assets: amount,\n isNativeETH,\n txOverrides,\n })\n}\n\n/**\n * Supply collateral and wait for confirmation.\n */\nexport async function supplyAndWait(params: SupplyParams): Promise<TxReceipt> {\n const result = await supply(params)\n return result.wait()\n}\n\n/**\n * Withdraw (unsupply) collateral from a pool.\n *\n * Resolves the correct collateral tracker from the token address,\n * then delegates to the low-level `withdraw()`.\n *\n * @param params - Unsupply parameters\n * @returns TxResult\n */\nexport async function unsupply(params: UnsupplyParams): Promise<TxResult> {\n const { client, walletClient, account, poolAddress, chainId, token, amount, txOverrides } = params\n const collateralTrackerAddress = await resolveCollateralTracker(\n client,\n poolAddress,\n chainId,\n token,\n )\n return withdraw({\n client,\n walletClient,\n account,\n collateralTrackerAddress,\n assets: amount,\n txOverrides,\n })\n}\n\n/**\n * Withdraw collateral and wait for confirmation.\n */\nexport async function unsupplyAndWait(params: UnsupplyParams): Promise<TxReceipt> {\n const result = await unsupply(params)\n return result.wait()\n}\n\n// ---------------------------------------------------------------------------\n// borrow\n// ---------------------------------------------------------------------------\n\n/**\n * Borrow tokens from a pool via a loan position.\n *\n * Creates a loan tokenId and mints it via dispatch. The loan borrows the\n * specified token without swapping (ascending tick limits = no swap).\n *\n * @param params - Borrow parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await borrow({\n * client, walletClient, account, poolAddress,\n * chainId: 11155111n,\n * token: USDC_ADDRESS,\n * amount: 100n * 10n**6n,\n * slippageBps: 500n,\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function borrow(params: BorrowParams): Promise<TxResult & { loanTokenId: bigint }> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n token,\n amount,\n slippageBps,\n existingPositionIds: explicitIds,\n builderCode = 0n,\n storage,\n txOverrides,\n } = params\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n const [pool, positionIds] = await Promise.all([\n getPool({ client, poolAddress, chainId }),\n resolvePositionIds(explicitIds, storage, chainId, poolAddress, account),\n ])\n\n const token0 = pool.collateralTracker0.token\n const token1 = pool.collateralTracker1.token\n const tokenIndex = resolveTokenIndex(token, token0, token1)\n\n // For a loan: both asset and tokenType = the borrowed token index\n const { tokenId: loanTokenId, adjustedSize } = buildUniqueLoan(\n pool.poolId,\n tokenIndex,\n tokenIndex,\n pool.currentTick,\n pool.tickSpacing,\n positionIds,\n amount,\n )\n\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n\n // Ascending tick limits = no swap at mint\n const mintTickLimits: readonly [number, number, number] = [\n Number(tickLimitLow),\n Number(tickLimitHigh),\n 0,\n ]\n\n const positionIdList = [loanTokenId]\n const finalPositionIdList = [...positionIds, loanTokenId]\n const positionSizes = [adjustedSize]\n\n try {\n const txResult = await submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n positionSizes,\n [mintTickLimits],\n false,\n builderCode,\n ],\n txOverrides,\n })\n return { ...txResult, loanTokenId }\n } catch (error) {\n if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) {\n continue\n }\n throw error\n }\n }\n\n throw new MaxRetriesExceededError('borrow')\n}\n\n/**\n * Borrow tokens and wait for confirmation.\n * If storage is provided, auto-tracks the new loan position.\n */\nexport async function borrowAndWait(params: BorrowParams): Promise<TxReceipt> {\n const result = await borrow(params)\n const receipt = await result.wait()\n\n // Auto-update storage if provided\n if (params.storage && params.chainId !== undefined) {\n const { poolAddress, chainId, storage, account, existingPositionIds: explicitIds } = params\n\n const positionIds =\n explicitIds ?? (await getTrackedPositionIds({ chainId, poolAddress, account, storage }))\n\n await savePositionIds(storage, chainId, poolAddress, account, [\n ...positionIds,\n result.loanTokenId,\n ])\n }\n\n return receipt\n}\n\n// ---------------------------------------------------------------------------\n// preview borrow\n// ---------------------------------------------------------------------------\n\n/** Parameters for previewing a borrow (read-only, no wallet required). */\nexport interface PreviewBorrowParams {\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 borrow (must be token0 or token1 of the pool) */\n token: Address\n /** Amount of token to borrow */\n amount: bigint\n /** Slippage tolerance in bps (e.g. 500n = 5%) */\n slippageBps: bigint\n /** Existing position IDs */\n existingPositionIds: bigint[]\n}\n\n/** Result of a borrow preview. */\nexport interface PreviewBorrowResult {\n /** The loan tokenId that would be minted */\n loanTokenId: bigint\n /** Adjusted position size (after optionRatio scaling) */\n adjustedSize: bigint\n /** Simulation result from dry-run dispatch */\n simulation: SimulationResult<OpenPositionSimulation>\n /** Collateral requirement for the new loan position only (token0). Null if simulation failed. */\n collateralReqToken0: bigint | null\n /** Collateral requirement for the new loan position only (token1). Null if simulation failed. */\n collateralReqToken1: bigint | null\n}\n\n/**\n * Preview a borrow without executing it.\n *\n * Builds the loan tokenId (same logic as `borrow`) and runs a\n * dry-run `simulateOpenPosition` to check feasibility and return\n * post-mint collateral requirements.\n *\n * @param params - Preview parameters\n * @returns Preview result with tokenId, size, and simulation data\n */\nexport async function previewBorrow(params: PreviewBorrowParams): Promise<PreviewBorrowResult> {\n const { client, poolAddress, chainId, token, amount, slippageBps, account, existingPositionIds } =\n params\n\n const pool = await getPool({ client, poolAddress, chainId })\n\n const token0 = pool.collateralTracker0.token\n const token1 = pool.collateralTracker1.token\n const tokenIndex = resolveTokenIndex(token, token0, token1)\n\n const { tokenId: loanTokenId, adjustedSize } = buildUniqueLoan(\n pool.poolId,\n tokenIndex,\n tokenIndex,\n pool.currentTick,\n pool.tickSpacing,\n existingPositionIds,\n amount,\n )\n\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n\n const simulation = await simulateOpenPosition({\n client,\n poolAddress,\n account,\n existingPositionIds,\n tokenId: loanTokenId,\n positionSize: adjustedSize,\n tickLimitLow: BigInt(tickLimitLow),\n tickLimitHigh: BigInt(tickLimitHigh),\n chainId,\n })\n\n // Extract the new loan's collateral requirement (last entry in perPositionCollateralReqs)\n let collateralReqToken0: bigint | null = null\n let collateralReqToken1: bigint | null = null\n if (simulation.success) {\n const reqs = simulation.data.perPositionCollateralReqs\n if (reqs.length > 0) {\n const loanReq = reqs[reqs.length - 1]\n collateralReqToken0 = loanReq.token0\n collateralReqToken1 = loanReq.token1\n }\n }\n\n return { loanTokenId, adjustedSize, simulation, collateralReqToken0, collateralReqToken1 }\n}\n\n// ---------------------------------------------------------------------------\n// repay\n// ---------------------------------------------------------------------------\n\n/**\n * Repay a loan position (full or partial).\n *\n * - Full repay (`amount >= currentSize`): Burns the loan position entirely.\n * - Partial repay (`amount < currentSize`): Uses roll-same-tokenId pattern\n * to reduce the position size.\n *\n * @param params - Repay parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * // Full repay\n * await repay({\n * client, walletClient, account, poolAddress,\n * chainId: 11155111n,\n * loanTokenId,\n * amount: MAX_UINT128, // repay all\n * slippageBps: 500n,\n * })\n *\n * // Partial repay\n * await repay({\n * client, walletClient, account, poolAddress,\n * chainId: 11155111n,\n * loanTokenId,\n * amount: 50n * 10n**6n, // repay 50 USDC\n * slippageBps: 500n,\n * })\n * ```\n */\nexport async function repay(params: RepayParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n loanTokenId,\n amount,\n slippageBps,\n existingPositionIds: explicitIds,\n builderCode = 0n,\n storage,\n txOverrides,\n } = params\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n const [positionIds, fullDataResult] = await Promise.all([\n resolvePositionIds(explicitIds, storage, chainId, poolAddress, account),\n client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, [loanTokenId]],\n }),\n ])\n\n // Extract positionSize from the packed PositionBalance\n const balanceRaw = fullDataResult[2][0] // positionBalances[0]\n const currentSize = balanceRaw & ((1n << 128n) - 1n)\n\n const pool = await getPool({ client, poolAddress, chainId })\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n\n // Ascending tick limits = no swap\n const ascendingLimits: readonly [number, number, number] = [\n Number(tickLimitLow),\n Number(tickLimitHigh),\n 0,\n ]\n\n if (amount >= currentSize) {\n // Full repay: burn the entire position\n const finalPositionIdList = positionIds.filter((id) => id !== loanTokenId)\n\n try {\n return await submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n [loanTokenId],\n finalPositionIdList,\n [0n], // 0n = burn all\n [ascendingLimits],\n false,\n builderCode,\n ],\n txOverrides,\n })\n } catch (error) {\n if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) {\n continue\n }\n throw error\n }\n } else {\n // Partial repay: roll-same-tokenId pattern\n // Op 1: burn current position at full size\n // Op 2: re-mint same tokenId at reduced size\n const newSize = currentSize - amount\n const finalPositionIdList = positionIds\n .filter((id) => id !== loanTokenId)\n .concat([loanTokenId])\n\n try {\n return await submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n [loanTokenId, loanTokenId],\n finalPositionIdList,\n [currentSize, newSize],\n [ascendingLimits, ascendingLimits],\n false,\n builderCode,\n ],\n txOverrides,\n })\n } catch (error) {\n if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) {\n continue\n }\n throw error\n }\n }\n }\n\n throw new MaxRetriesExceededError('repay')\n}\n\n/**\n * Repay a loan and wait for confirmation.\n * If storage is provided, auto-updates the tracked positions (removes on full repay).\n */\nexport async function repayAndWait(params: RepayParams): Promise<TxReceipt> {\n const result = await repay(params)\n const receipt = await result.wait()\n\n // Auto-update storage on full repay\n if (params.storage && params.chainId !== undefined) {\n const {\n client,\n account,\n poolAddress,\n chainId,\n loanTokenId,\n storage,\n existingPositionIds: explicitIds,\n } = params\n\n const fullDataResult = await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, [loanTokenId]],\n })\n const balanceRaw = fullDataResult[2][0] // positionBalances[0]\n const currentSize = balanceRaw & ((1n << 128n) - 1n)\n\n // Only remove if the position was fully burned\n if (currentSize === 0n) {\n const positionIds =\n explicitIds ?? (await getTrackedPositionIds({ chainId, poolAddress, account, storage }))\n await savePositionIds(\n storage,\n chainId,\n poolAddress,\n account,\n positionIds.filter((id) => id !== loanTokenId),\n )\n }\n }\n\n return receipt\n}\n\n// ---------------------------------------------------------------------------\n// smart repay\n// ---------------------------------------------------------------------------\n\n/** Parameters for smart repay (burns all loans for a token, optionally re-opens a smaller one). */\nexport interface SmartRepayParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID */\n chainId: bigint\n /** Token address to repay loans for (must be token0 or token1 of the pool) */\n token: Address\n /** Amount of token to repay */\n amount: bigint\n /** Slippage tolerance in bps (e.g. 500n = 5%) */\n slippageBps: bigint\n /** Existing position IDs (all positions, not just loans) */\n existingPositionIds: bigint[]\n /** Builder code for fee routing (0 = no builder). */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n /** Optional storage adapter — when provided, smartRepayAndWait auto-updates tracked positions. */\n storage?: StorageAdapter\n}\n\n/**\n * Identify loan tokenIds for a specific token and return their sizes.\n */\nasync function getLoanPositionsForToken(\n client: PublicClient,\n poolAddress: Address,\n account: Address,\n existingPositionIds: bigint[],\n tokenIndex: bigint,\n): Promise<{ tokenId: bigint; positionSize: bigint; optionRatio: bigint; tokenAmount: bigint }[]> {\n const loanIds = existingPositionIds.filter((id) => {\n if (!isLoan(id)) return false\n const legs = decodeAllLegs(id)\n return legs.length > 0 && legs[0].tokenType === tokenIndex\n })\n\n if (loanIds.length === 0) return []\n\n const fullData = await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, loanIds],\n })\n\n const balances = fullData[2]\n return loanIds.map((tokenId, i) => {\n const positionSize = balances[i] & ((1n << 128n) - 1n)\n const legs = decodeAllLegs(tokenId)\n const optionRatio = legs[0].optionRatio\n // Actual token amount = positionSize * optionRatio\n const tokenAmount = positionSize * optionRatio\n return { tokenId, positionSize, optionRatio, tokenAmount }\n })\n}\n\n/**\n * Smart repay: burns all loan positions for a token and optionally re-opens a smaller one.\n *\n * Unlike `repay()` which targets a single loanTokenId, this function handles\n * multiple loans transparently. The user specifies a repay amount and the SDK:\n * 1. Finds all loan positions for the specified token\n * 2. Burns them all\n * 3. If repayAmount < totalDebt, opens a new loan for the remainder\n *\n * @param params - Smart repay parameters\n * @returns TxResult\n */\nexport async function smartRepay(params: SmartRepayParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n token,\n amount,\n slippageBps,\n existingPositionIds,\n builderCode = 0n,\n txOverrides,\n } = params\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n const pool = await getPool({ client, poolAddress, chainId })\n const tokenIndex = resolveTokenIndex(\n token,\n pool.collateralTracker0.token,\n pool.collateralTracker1.token,\n )\n\n const loans = await getLoanPositionsForToken(\n client,\n poolAddress,\n account,\n existingPositionIds,\n tokenIndex,\n )\n if (loans.length === 0) {\n throw new NoLoanPositionsError(token)\n }\n\n const totalDebt = loans.reduce((sum, l) => sum + l.tokenAmount, 0n)\n const loanIds = loans.map((l) => l.tokenId)\n const remainder = totalDebt > amount ? totalDebt - amount : 0n\n\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n const ascendingLimits: readonly [number, number, number] = [\n Number(tickLimitLow),\n Number(tickLimitHigh),\n 0,\n ]\n\n const nonLoanIds = existingPositionIds.filter((id) => !loanIds.includes(id))\n\n const opsPositionIds: bigint[] = [...loanIds]\n const opsSizes: bigint[] = loanIds.map(() => 0n)\n const opsLimits = loanIds.map(() => ascendingLimits)\n\n let finalPositionIdList: bigint[]\n\n if (remainder > 0n) {\n const { tokenId: newLoanId, adjustedSize } = buildUniqueLoan(\n pool.poolId,\n tokenIndex,\n tokenIndex,\n pool.currentTick,\n pool.tickSpacing,\n nonLoanIds,\n remainder,\n )\n opsPositionIds.push(newLoanId)\n opsSizes.push(adjustedSize)\n opsLimits.push(ascendingLimits)\n finalPositionIdList = [...nonLoanIds, newLoanId]\n } else {\n finalPositionIdList = nonLoanIds\n }\n\n try {\n return await submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [opsPositionIds, finalPositionIdList, opsSizes, opsLimits, false, builderCode],\n txOverrides,\n })\n } catch (error) {\n if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) {\n continue\n }\n throw error\n }\n }\n\n throw new MaxRetriesExceededError('smartRepay')\n}\n\n/**\n * Smart repay and wait for confirmation.\n */\nexport async function smartRepayAndWait(params: SmartRepayParams): Promise<TxReceipt> {\n const result = await smartRepay(params)\n const receipt = await result.wait()\n\n // Auto-update storage: remove fully-repaid loans, insert remainder loan if any\n if (params.storage && params.chainId !== undefined) {\n const { client, account, poolAddress, chainId, token, amount, storage, existingPositionIds } =\n params\n\n const pool = await getPool({ client, poolAddress, chainId })\n const tokenIndex = resolveTokenIndex(\n token,\n pool.collateralTracker0.token,\n pool.collateralTracker1.token,\n )\n\n const loans = await getLoanPositionsForToken(\n client,\n poolAddress,\n account,\n existingPositionIds,\n tokenIndex,\n )\n const loanIds = loans.map((l) => l.tokenId)\n const totalDebt = loans.reduce((sum, l) => sum + l.tokenAmount, 0n)\n const remainder = totalDebt > amount ? totalDebt - amount : 0n\n\n const positionIds =\n existingPositionIds ??\n (await getTrackedPositionIds({ chainId, poolAddress, account, storage }))\n\n // Remove all old loan IDs\n let updatedIds = positionIds.filter((id) => !loanIds.includes(id))\n\n // If there's a remainder, the contract minted a new loan — find it\n if (remainder > 0n) {\n const nonLoanIds = existingPositionIds.filter((id) => !loanIds.includes(id))\n const newLoan = buildUniqueLoan(\n pool.poolId,\n tokenIndex,\n tokenIndex,\n pool.currentTick,\n pool.tickSpacing,\n nonLoanIds,\n remainder,\n )\n updatedIds = [...updatedIds, newLoan.tokenId]\n }\n\n await savePositionIds(storage, chainId, poolAddress, account, updatedIds)\n }\n\n return receipt\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"writes-DymnVbiE.js","names":["publicBroadcaster: TxBroadcaster","signedTx: `0x${string}`","client: PublicClient","account: Address","params: ApproveParams","params: ApprovePoolParams","params: CheckApprovalParams","params: DepositParams","params: WithdrawParams","params: WithdrawWithPositionsParams","params: MintParams","params: RedeemParams","directory: string","fsPromises: typeof FsPromises | null","pathModule: typeof Path | null","key: string","value: string","prefix: string","result: string[]","chainId: bigint","poolAddress: Address","account: Address","tokenId: bigint","key: string","value: string","prefix: string","result: string[]","keysToDelete: string[]","value: unknown","_key: string","space?: string | number","text: string","params: RecoverSnapshotParams","error: unknown","parts: string[]","current: unknown","params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n fromBlock: bigint\n toBlock: bigint\n}","params: {\n client: PublicClient\n account: Address\n events: SnapshotEventLog[]\n}","event: SnapshotEventLog","params: RecoverSnapshotFromTxParams","input: `0x${string}`","candidates: DispatchCalldata[]","account: Address","txFrom: Address","match: DispatchCalldata | null","results: DispatchCalldata[]","params: GetTrackedPositionIdsParams","tokenId: bigint","params: GetOpenPositionIdsParams","snapshot: SnapshotRecoveryResult | null","resolvePositionIds","explicit: bigint[] | undefined","storage: StorageAdapter | undefined","chainId: bigint | undefined","poolAddress: Address","account: Address","savePositionIds","storage: StorageAdapter","chainId: bigint","positionIds: bigint[]","params: OpenPositionParams","tickLimits: readonly [number, number, number]","tickLimits","params: {\n poolAddress: Address\n existingPositionIds: bigint[]\n tokenId: bigint\n positionSize: bigint\n tickLimitLow: bigint\n tickLimitHigh: bigint\n spreadLimit?: bigint\n swapAtMint?: boolean\n usePremiaAsCollateral?: boolean\n builderCode?: bigint\n}","params: ClosePositionParams","params: RollPositionParams","closeLimits: readonly [number, number, number]","openLimits: readonly [number, number, number]","params: DispatchParams","params: ValidateBatchParams","diagnostics: BatchDiagnostic[]","params: BuildBatchDispatchArgsParams","tickAndSpreadLimits: TickAndSpreadLimits[]","params: ExecuteBatchDispatchParams","params: LiquidateParams","data: DataWithMeta","maxAgeSeconds: bigint | number","currentTimestamp?: bigint | number","pool: Pool","safeMode?: SafeModeState","safeMode: SafeModeState","error: unknown","params: DetectReorgParams","reorgBlock: bigint","reorgDepth: bigint","params: SaveCheckpointParams","checkpoint: SyncCheckpoint","storage: StorageAdapter","chainId: bigint","poolAddress: Address","account: Address","client: PublicClient","fromBlock: bigint","toBlock: bigint","previousHash: Hash | null","params: SyncPositionsParams","positionIds: bigint[]","finalBlock","poolMetaKey","existingPoolMeta","positionsKey","storedData: StoredPositionData","params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n fromBlock?: bigint\n toBlock: bigint\n}","client: PublicClient","poolAddress: Address","poolMetaKey: string","storage: StorageAdapter","poolMeta: StoredPoolMeta","fn: () => Promise<T>","lastError: unknown","params: ForceExerciseParams","params: SettleParams","positionSizes: bigint[]","tickAndSpreadLimits: TickAndSpreadLimits[]","params: PokeOracleParams","params: DeployNewPoolParams","value: bigint","multiplier: number","originalMaxFeePerGas: bigint | undefined","originalMaxPriorityFeePerGas: bigint | undefined","explicitMaxFeePerGas: bigint | undefined","explicitMaxPriorityFeePerGas: bigint | undefined","params: SpeedUpParams","replacementHash","params: CancelParams","cancelHash","strike: bigint","encodedStrike: bigint","legIndex: bigint","address: Address","tickSpacing: bigint","vegoid: bigint","bytes: number[]","poolIdHex: Hex","tokenId: bigint","value: bigint","bitPosition: bigint","leg: EncodeLegParams","legs: DecodedLeg[]","poolId: bigint","config: LegConfig","legIndex: bigint","builder: TokenIdBuilder","leg: EncodeLegParams","config: Omit<LegConfig, 'tokenType' | 'asset'> & { asset?: bigint }","config: LoanCreditConfig","tokenAddress: Address","token0: Address","token1: Address","explicit: bigint[] | undefined","storage: StorageAdapter | undefined","chainId: bigint","poolAddress: Address","account: Address","error: unknown","poolId: bigint","asset: bigint","tokenType: bigint","currentTick: bigint","tickSpacing: bigint","existingPositionIds: bigint[]","positionSize: bigint","params: SwapExactOutParams","mintTickLimits: readonly [number, number, number]","burnTickLimits: readonly [number, number, number]","params: SwapExactInParams","params: WrapXstockParams","params: UnwrapXstockParams","params: PreviewWrapParams","params: WrapEthParams","params: UnwrapWethParams","leg: DecodedLeg","tickSpacing: bigint","tokenId: bigint","expectedPoolId: bigint","params: SimulateWithTokenFlowParams","multicallData: Hex[]","data: Hex","params: SimulateOpenPositionParams","tickLimits: readonly [number, number, number]","tickLimits","perPositionCollateralReqs: { token0: bigint; token1: bigint }[]","decoded","data: OpenPositionSimulation","client: PublicClient","poolAddress: Address","chainId: bigint","token: Address","storage: StorageAdapter","account: Address","positionIds: bigint[]","params: SupplyParams","params: UnsupplyParams","params: BorrowParams","mintTickLimits: readonly [number, number, number]","params: PreviewBorrowParams","collateralReqToken0: bigint | null","collateralReqToken1: bigint | null","params: RepayParams","ascendingLimits: readonly [number, number, number]","existingPositionIds: bigint[]","tokenIndex: bigint","params: SmartRepayParams","opsPositionIds: bigint[]","opsSizes: bigint[]","finalPositionIdList: bigint[]"],"sources":["../src/panoptic/v2/writes/broadcaster.ts","../src/panoptic/v2/writes/approve.ts","../src/panoptic/v2/writes/vault.ts","../src/panoptic/v2/storage/fileStorage.ts","../src/panoptic/v2/storage/keys.ts","../src/panoptic/v2/storage/memoryStorage.ts","../src/panoptic/v2/storage/serializer.ts","../src/panoptic/v2/sync/snapshotRecovery.ts","../src/panoptic/v2/sync/getTrackedPositionIds.ts","../src/panoptic/v2/writes/position.ts","../src/panoptic/v2/writes/dispatch.ts","../src/panoptic/v2/batch/validate.ts","../src/panoptic/v2/batch/build.ts","../src/panoptic/v2/writes/executeBatchDispatch.ts","../src/panoptic/v2/writes/liquidate.ts","../src/panoptic/v2/bot/index.ts","../src/panoptic/v2/sync/reorgHandling.ts","../src/panoptic/v2/sync/syncPositions.ts","../src/panoptic/v2/writes/forceExercise.ts","../src/panoptic/v2/writes/settle.ts","../src/panoptic/v2/writes/pokeOracle.ts","../src/panoptic/v2/writes/factory.ts","../src/panoptic/v2/writes/txManagement.ts","../src/panoptic/v2/tokenId/encoding.ts","../src/panoptic/v2/tokenId/builder.ts","../src/panoptic/v2/writes/loanUtils.ts","../src/panoptic/v2/writes/swap.ts","../src/panoptic/v2/writes/wrap.ts","../src/panoptic/v2/tokenId/decode.ts","../src/panoptic/v2/simulations/tokenFlow.ts","../src/panoptic/v2/simulations/simulateOpenPosition.ts","../src/panoptic/v2/writes/lending.ts"],"sourcesContent":["/**\n * Transaction broadcaster utilities for the Panoptic v2 SDK.\n * @module v2/writes/broadcaster\n */\n\nimport type { Address, Hash, PublicClient, WalletClient } from 'viem'\n\nimport type { NonceManager, TxBroadcaster } from '../types'\n\n/**\n * Create a public broadcaster that sends transactions to the standard mempool.\n *\n * Use this factory to create a working broadcaster with a client.\n *\n * @param client - The public client for broadcasting\n * @returns A TxBroadcaster that sends to the public mempool\n *\n * @example\n * ```typescript\n * const broadcaster = createPublicBroadcaster(publicClient)\n * const hash = await broadcaster.broadcast(signedTx)\n * ```\n */\nexport function createPublicBroadcaster(client: PublicClient): TxBroadcaster {\n return {\n async broadcast(signedTx: `0x${string}`): Promise<Hash> {\n return client.sendRawTransaction({ serializedTransaction: signedTx })\n },\n }\n}\n\n/**\n * Default public broadcaster singleton.\n *\n * Note: This singleton requires a client to be provided via the broadcast call's context.\n * For standalone usage, use `createPublicBroadcaster(client)` instead.\n *\n * When used with write functions, the SDK handles client injection automatically.\n */\nexport const publicBroadcaster: TxBroadcaster = {\n async broadcast(signedTx: `0x${string}`): Promise<Hash> {\n // This singleton cannot broadcast without a client.\n // Write functions that use this broadcaster should inject their client.\n throw new Error(\n 'publicBroadcaster requires a client. Use createPublicBroadcaster(client) for standalone usage.',\n )\n },\n}\n\n/**\n * Create a nonce manager for concurrent transaction submission.\n *\n * The nonce manager tracks pending nonces to allow multiple transactions\n * to be submitted without waiting for confirmation.\n *\n * @param client - The public client for querying nonces\n * @returns A NonceManager instance\n *\n * @example\n * ```typescript\n * const nonceManager = createNonceManager(client)\n * const nonce1 = await nonceManager.getNextNonce(account)\n * const nonce2 = await nonceManager.getNextNonce(account) // nonce1 + 1\n * // On failure, reset to re-fetch from chain:\n * nonceManager.reset(account)\n * ```\n */\nexport function createNonceManager(client: PublicClient): NonceManager {\n const pendingNonces = new Map<Address, bigint>()\n\n return {\n async getNextNonce(account: Address): Promise<bigint> {\n const chainNonce = BigInt(\n await client.getTransactionCount({\n address: account,\n blockTag: 'pending',\n }),\n )\n\n const pending = pendingNonces.get(account)\n const localNext = pending !== undefined ? pending + 1n : chainNonce\n const nextNonce = localNext > chainNonce ? localNext : chainNonce\n\n pendingNonces.set(account, nextNonce)\n return nextNonce\n },\n\n reset(account: Address): void {\n pendingNonces.delete(account)\n },\n }\n}\n\n/**\n * Configuration for write operations.\n */\nexport interface WriteConfig {\n /** Wallet client for signing and submitting transactions */\n walletClient: WalletClient\n /** Public client for reading state */\n publicClient: PublicClient\n /** Optional custom broadcaster */\n broadcaster?: TxBroadcaster\n /** Optional nonce manager for concurrent transactions */\n nonceManager?: NonceManager\n /** Gas price multiplier (1.0 = no change, 1.1 = 10% increase) */\n gasPriceMultiplier?: number\n /** Optional gas limit override */\n gasLimit?: bigint\n}\n","/**\n * Approval functions for the Panoptic v2 SDK.\n * @module v2/writes/approve\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\nimport { erc20Abi } from 'viem'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi } from '../../../generated'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for approve function.\n */\nexport interface ApproveParams {\n /** Public client for reading state */\n client: PublicClient\n /** Wallet client for signing transactions */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** Token address to approve */\n tokenAddress: Address\n /** Spender address (collateral tracker) */\n spenderAddress: Address\n /** Amount to approve (use MaxUint256 for unlimited) */\n amount: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Approve token spending for a collateral tracker.\n *\n * @param params - The approval parameters\n * @returns TxResult with hash and wait function\n *\n * @example\n * ```typescript\n * const result = await approve({\n * client,\n * walletClient,\n * account,\n * tokenAddress: WETH,\n * spenderAddress: collateralToken0,\n * amount: MaxUint256,\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function approve(params: ApproveParams): Promise<TxResult> {\n const { client, walletClient, account, tokenAddress, spenderAddress, amount, txOverrides } =\n params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: tokenAddress,\n abi: erc20Abi,\n functionName: 'approve',\n args: [spenderAddress, amount],\n txOverrides,\n })\n}\n\n/**\n * Approve token spending and wait for confirmation.\n *\n * @param params - The approval parameters\n * @returns TxReceipt after confirmation\n */\nexport async function approveAndWait(params: ApproveParams): Promise<TxReceipt> {\n const result = await approve(params)\n return result.wait()\n}\n\n/**\n * Parameters for approving both tokens for a pool.\n */\nexport interface ApprovePoolParams {\n /** Public client for reading state */\n client: PublicClient\n /** Wallet client for signing transactions */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Amount to approve for token 0 */\n amount0: bigint\n /** Amount to approve for token 1 */\n amount1: bigint\n}\n\n/**\n * Approve both tokens for a Panoptic pool.\n * Fetches collateral tracker addresses and underlying tokens, then approves both.\n *\n * @param params - The approval parameters\n * @returns Array of two TxResults\n *\n * @example\n * ```typescript\n * const [result0, result1] = await approvePool({\n * client,\n * walletClient,\n * account,\n * poolAddress,\n * amount0: MaxUint256,\n * amount1: MaxUint256,\n * })\n * await Promise.all([result0.wait(), result1.wait()])\n * ```\n */\nexport async function approvePool(params: ApprovePoolParams): Promise<[TxResult, TxResult]> {\n const { client, walletClient, account, poolAddress, amount0, amount1 } = params\n\n // Get collateral tracker addresses\n const [collateralToken0, collateralToken1] = await client.multicall({\n contracts: [\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'collateralToken0',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'collateralToken1',\n },\n ],\n allowFailure: false,\n })\n\n // Get underlying token addresses\n const [token0, token1] = await client.multicall({\n contracts: [\n {\n address: collateralToken0,\n abi: collateralTrackerV2Abi,\n functionName: 'asset',\n },\n {\n address: collateralToken1,\n abi: collateralTrackerV2Abi,\n functionName: 'asset',\n },\n ],\n allowFailure: false,\n })\n\n // Approve both tokens in parallel\n const [result0, result1] = await Promise.all([\n approve({\n client,\n walletClient,\n account,\n tokenAddress: token0,\n spenderAddress: collateralToken0,\n amount: amount0,\n }),\n approve({\n client,\n walletClient,\n account,\n tokenAddress: token1,\n spenderAddress: collateralToken1,\n amount: amount1,\n }),\n ])\n\n return [result0, result1]\n}\n\n/**\n * Check if an approval is needed for a given amount.\n *\n * @param params - Parameters for checking approval\n * @returns Object with needsApproval flag and current allowance\n */\nexport interface CheckApprovalParams {\n /** Public client */\n client: PublicClient\n /** Token address */\n tokenAddress: Address\n /** Owner address */\n owner: Address\n /** Spender address */\n spender: Address\n /** Amount to check against */\n amount: bigint\n}\n\nexport interface ApprovalStatus {\n /** Whether approval is needed */\n needsApproval: boolean\n /** Current allowance */\n currentAllowance: bigint\n /** Amount that would be approved */\n requiredAmount: bigint\n}\n\n/**\n * Check if approval is needed for a token transfer.\n *\n * @param params - The check parameters\n * @returns Approval status\n */\nexport async function checkApproval(params: CheckApprovalParams): Promise<ApprovalStatus> {\n const { client, tokenAddress, owner, spender, amount } = params\n\n const currentAllowance = await client.readContract({\n address: tokenAddress,\n abi: erc20Abi,\n functionName: 'allowance',\n args: [owner, spender],\n })\n\n return {\n needsApproval: currentAllowance < amount,\n currentAllowance,\n requiredAmount: amount,\n }\n}\n","/**\n * ERC4626 vault operations for the Panoptic v2 SDK.\n * @module v2/writes/vault\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { collateralTrackerV2Abi } from '../../../generated'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for deposit operation.\n */\nexport interface DepositParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** CollateralTracker address */\n collateralTrackerAddress: Address\n /** Amount of assets to deposit */\n assets: bigint\n /** Whether the collateral tracker wraps native ETH (requires sending msg.value) */\n isNativeETH?: boolean\n /** Receiver of shares (defaults to account) */\n receiver?: Address\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Deposit assets into a collateral tracker.\n *\n * @param params - Deposit parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await deposit({\n * client,\n * walletClient,\n * account,\n * collateralTrackerAddress,\n * assets: parseEther('1'),\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function deposit(params: DepositParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n collateralTrackerAddress,\n assets,\n isNativeETH,\n receiver = account,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'deposit',\n args: [assets, receiver],\n value: isNativeETH ? assets : undefined,\n txOverrides,\n })\n}\n\n/**\n * Deposit assets and wait for confirmation.\n */\nexport async function depositAndWait(params: DepositParams): Promise<TxReceipt> {\n const result = await deposit(params)\n return result.wait()\n}\n\n/**\n * Parameters for withdraw operation.\n */\nexport interface WithdrawParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** CollateralTracker address */\n collateralTrackerAddress: Address\n /** Amount of assets to withdraw */\n assets: bigint\n /** Receiver of assets */\n receiver?: Address\n /** Owner of shares (defaults to account) */\n owner?: Address\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Withdraw assets from a collateral tracker.\n *\n * @param params - Withdraw parameters\n * @returns TxResult\n */\nexport async function withdraw(params: WithdrawParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n collateralTrackerAddress,\n assets,\n receiver = account,\n owner = account,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'withdraw',\n args: [assets, receiver, owner],\n txOverrides,\n })\n}\n\n/**\n * Withdraw assets and wait for confirmation.\n */\nexport async function withdrawAndWait(params: WithdrawParams): Promise<TxReceipt> {\n const result = await withdraw(params)\n return result.wait()\n}\n\n/**\n * Parameters for withdraw with position list validation.\n */\nexport interface WithdrawWithPositionsParams extends WithdrawParams {\n /** Position ID list for collateral validation */\n positionIdList: bigint[]\n /** Whether to use premia as collateral */\n usePremiaAsCollateral: boolean\n}\n\n/**\n * Withdraw assets with position list validation.\n * This overload validates that the withdrawal won't make positions undercollateralized.\n *\n * @param params - Withdraw parameters with positions\n * @returns TxResult\n */\nexport async function withdrawWithPositions(\n params: WithdrawWithPositionsParams,\n): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n collateralTrackerAddress,\n assets,\n receiver = account,\n owner = account,\n positionIdList,\n usePremiaAsCollateral,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'withdraw',\n args: [assets, receiver, owner, positionIdList, usePremiaAsCollateral],\n txOverrides,\n })\n}\n\n/**\n * Withdraw with positions and wait for confirmation.\n */\nexport async function withdrawWithPositionsAndWait(\n params: WithdrawWithPositionsParams,\n): Promise<TxReceipt> {\n const result = await withdrawWithPositions(params)\n return result.wait()\n}\n\n/**\n * Parameters for mint operation.\n */\nexport interface MintParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** CollateralTracker address */\n collateralTrackerAddress: Address\n /** Amount of shares to mint */\n shares: bigint\n /** Receiver of shares */\n receiver?: Address\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Mint shares by depositing assets.\n *\n * @param params - Mint parameters\n * @returns TxResult\n */\nexport async function mint(params: MintParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n collateralTrackerAddress,\n shares,\n receiver = account,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'mint',\n args: [shares, receiver],\n txOverrides,\n })\n}\n\n/**\n * Mint shares and wait for confirmation.\n */\nexport async function mintAndWait(params: MintParams): Promise<TxReceipt> {\n const result = await mint(params)\n return result.wait()\n}\n\n/**\n * Parameters for redeem operation.\n */\nexport interface RedeemParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** CollateralTracker address */\n collateralTrackerAddress: Address\n /** Amount of shares to redeem */\n shares: bigint\n /** Receiver of assets */\n receiver?: Address\n /** Owner of shares */\n owner?: Address\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Redeem shares for assets.\n *\n * @param params - Redeem parameters\n * @returns TxResult\n */\nexport async function redeem(params: RedeemParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n collateralTrackerAddress,\n shares,\n receiver = account,\n owner = account,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: collateralTrackerAddress,\n abi: collateralTrackerV2Abi,\n functionName: 'redeem',\n args: [shares, receiver, owner],\n txOverrides,\n })\n}\n\n/**\n * Redeem shares and wait for confirmation.\n */\nexport async function redeemAndWait(params: RedeemParams): Promise<TxReceipt> {\n const result = await redeem(params)\n return result.wait()\n}\n","/**\n * File-based storage adapter for Node.js.\n * @module v2/storage/fileStorage\n */\n\nimport type FsPromises from 'node:fs/promises'\nimport type Path from 'node:path'\n\nimport type { StorageAdapter } from './adapter'\n\n/**\n * Creates a file-based storage adapter for Node.js environments.\n * Stores data as JSON files in the specified directory.\n *\n * The directory will be created if it doesn't exist.\n *\n * @param directory - Path to the storage directory\n *\n * @example\n * ```typescript\n * import { createFileStorage, createConfig } from 'panoptic-v2-sdk'\n *\n * // Node.js only\n * const config = createConfig({\n * chainId: 1n,\n * transport: http('...'),\n * poolAddress: '0x...',\n * storage: createFileStorage('./panoptic-cache'),\n * })\n * ```\n */\nexport function createFileStorage(directory: string): StorageAdapter {\n // Lazy import fs/promises to avoid issues in browser environments\n // This function should only be called in Node.js\n let fsPromises: typeof FsPromises | null = null\n let pathModule: typeof Path | null = null\n let initialized = false\n\n const ensureInitialized = async () => {\n if (initialized) return\n\n // Dynamic import for Node.js modules\n fsPromises = await import('node:fs/promises')\n pathModule = await import('node:path')\n\n // Ensure directory exists\n await fsPromises.mkdir(directory, { recursive: true })\n initialized = true\n }\n\n const getFilePath = (key: string): string => {\n if (!pathModule) throw new Error('File storage not initialized')\n // Encode the key to be filesystem-safe\n const safeKey = Buffer.from(key).toString('base64url')\n return pathModule.join(directory, `${safeKey}.json`)\n }\n\n return {\n async get(key: string): Promise<string | null> {\n await ensureInitialized()\n if (!fsPromises) throw new Error('File storage not initialized')\n\n try {\n const filePath = getFilePath(key)\n const content = await fsPromises.readFile(filePath, 'utf-8')\n return content\n } catch (error) {\n // File doesn't exist\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return null\n }\n throw error\n }\n },\n\n async set(key: string, value: string): Promise<void> {\n await ensureInitialized()\n if (!fsPromises) throw new Error('File storage not initialized')\n\n const filePath = getFilePath(key)\n await fsPromises.writeFile(filePath, value, 'utf-8')\n },\n\n async delete(key: string): Promise<void> {\n await ensureInitialized()\n if (!fsPromises) throw new Error('File storage not initialized')\n\n try {\n const filePath = getFilePath(key)\n await fsPromises.unlink(filePath)\n } catch (error) {\n // Ignore if file doesn't exist\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw error\n }\n }\n },\n\n async has(key: string): Promise<boolean> {\n await ensureInitialized()\n if (!fsPromises) throw new Error('File storage not initialized')\n\n try {\n const filePath = getFilePath(key)\n await fsPromises.access(filePath)\n return true\n } catch {\n return false\n }\n },\n\n async keys(prefix: string): Promise<string[]> {\n await ensureInitialized()\n if (!fsPromises || !pathModule) throw new Error('File storage not initialized')\n\n const result: string[] = []\n\n try {\n const files = await fsPromises.readdir(directory)\n for (const file of files) {\n if (file.endsWith('.json')) {\n const safeKey = file.slice(0, -5) // Remove .json\n try {\n const key = Buffer.from(safeKey, 'base64url').toString()\n if (key.startsWith(prefix)) {\n result.push(key)\n }\n } catch {\n // Invalid base64, skip\n }\n }\n }\n } catch (error) {\n // Directory doesn't exist yet\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw error\n }\n }\n\n return result\n },\n\n async clear(prefix: string): Promise<void> {\n await ensureInitialized()\n if (!fsPromises) throw new Error('File storage not initialized')\n\n const keysToDelete = await this.keys(prefix)\n for (const key of keysToDelete) {\n await this.delete(key)\n }\n },\n }\n}\n","/**\n * Storage key generation for the Panoptic v2 SDK.\n * @module v2/storage/keys\n */\n\nimport type { Address } from 'viem'\n\nimport { SCHEMA_VERSION, STORAGE_PREFIX } from '../utils/constants'\n\n/**\n * Get the schema version key.\n */\nexport function getSchemaVersionKey(): string {\n return `${STORAGE_PREFIX}:schemaVersion`\n}\n\n/**\n * Get the base prefix for a specific pool.\n */\nexport function getPoolPrefix(chainId: bigint, poolAddress: Address): string {\n return `${STORAGE_PREFIX}:v${SCHEMA_VERSION}:chain${chainId}:pool${poolAddress.toLowerCase()}`\n}\n\n/**\n * Get the key for tracked position IDs.\n */\nexport function getPositionsKey(chainId: bigint, poolAddress: Address, account: Address): string {\n return `${getPoolPrefix(chainId, poolAddress)}:positions:${account.toLowerCase()}`\n}\n\n/**\n * Get the key for position mint metadata.\n */\nexport function getPositionMetaKey(chainId: bigint, poolAddress: Address, tokenId: bigint): string {\n return `${getPoolPrefix(chainId, poolAddress)}:positionMeta:${tokenId.toString()}`\n}\n\n/**\n * Get the key for sync checkpoint.\n */\nexport function getSyncCheckpointKey(\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n): string {\n return `${getPoolPrefix(chainId, poolAddress)}:sync:${account.toLowerCase()}`\n}\n\n/**\n * Get the key for closed positions.\n */\nexport function getClosedPositionsKey(\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n): string {\n return `${getPoolPrefix(chainId, poolAddress)}:closed:${account.toLowerCase()}`\n}\n\n/**\n * Get the key for tracked chunks.\n */\nexport function getTrackedChunksKey(chainId: bigint, poolAddress: Address): string {\n return `${getPoolPrefix(chainId, poolAddress)}:chunks`\n}\n\n/**\n * Get the key for pending positions.\n */\nexport function getPendingPositionsKey(\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n): string {\n return `${getPoolPrefix(chainId, poolAddress)}:pending:${account.toLowerCase()}`\n}\n\n/**\n * Get the key for pool metadata (tickSpacing, etc.).\n */\nexport function getPoolMetaKey(chainId: bigint, poolAddress: Address): string {\n return `${getPoolPrefix(chainId, poolAddress)}:poolMeta`\n}\n","/**\n * In-memory storage adapter for testing.\n * @module v2/storage/memoryStorage\n */\n\nimport type { StorageAdapter } from './adapter'\n\n/**\n * Creates an in-memory storage adapter.\n * Useful for testing and development.\n *\n * Data is lost when the process exits.\n *\n * @example\n * ```typescript\n * import { createMemoryStorage, createConfig } from 'panoptic-v2-sdk'\n *\n * const config = createConfig({\n * chainId: 1n,\n * transport: http('...'),\n * poolAddress: '0x...',\n * storage: createMemoryStorage(),\n * })\n * ```\n */\nexport function createMemoryStorage(): StorageAdapter {\n const store = new Map<string, string>()\n\n return {\n async get(key: string): Promise<string | null> {\n return store.get(key) ?? null\n },\n\n async set(key: string, value: string): Promise<void> {\n store.set(key, value)\n },\n\n async delete(key: string): Promise<void> {\n store.delete(key)\n },\n\n async has(key: string): Promise<boolean> {\n return store.has(key)\n },\n\n async keys(prefix: string): Promise<string[]> {\n const result: string[] = []\n for (const key of store.keys()) {\n if (key.startsWith(prefix)) {\n result.push(key)\n }\n }\n return result\n },\n\n async clear(prefix: string): Promise<void> {\n const keysToDelete: string[] = []\n for (const key of store.keys()) {\n if (key.startsWith(prefix)) {\n keysToDelete.push(key)\n }\n }\n for (const key of keysToDelete) {\n store.delete(key)\n }\n },\n }\n}\n","/**\n * BigInt-safe JSON serialization for the Panoptic v2 SDK.\n * Compatible with superjson patterns for SSR hydration.\n * @module v2/storage/serializer\n */\n\n/**\n * Tagged value for BigInt serialization.\n * Format compatible with superjson for Next.js/Remix SSR.\n */\ninterface BigIntTagged {\n __type: 'bigint'\n value: string\n}\n\n/**\n * Type guard to check if a value is a tagged BigInt.\n */\nfunction isBigIntTagged(value: unknown): value is BigIntTagged {\n return (\n value !== null &&\n typeof value === 'object' &&\n '__type' in value &&\n (value as BigIntTagged).__type === 'bigint' &&\n 'value' in value &&\n typeof (value as BigIntTagged).value === 'string'\n )\n}\n\n/**\n * Replacer function for JSON.stringify that tags BigInt values.\n */\nfunction replacer(_key: string, value: unknown): unknown {\n if (typeof value === 'bigint') {\n return {\n __type: 'bigint',\n value: value.toString(),\n } satisfies BigIntTagged\n }\n return value\n}\n\n/**\n * Reviver function for JSON.parse that restores tagged BigInt values.\n */\nfunction reviver(_key: string, value: unknown): unknown {\n if (isBigIntTagged(value)) {\n return BigInt(value.value)\n }\n return value\n}\n\n/**\n * BigInt-safe JSON serializer for the Panoptic v2 SDK.\n *\n * This serializer handles BigInt values by tagging them with a special format\n * that can be restored on parse. The format is compatible with superjson\n * patterns used in Next.js and Remix for SSR hydration.\n *\n * @example\n * ```typescript\n * import { jsonSerializer } from 'panoptic-v2-sdk'\n *\n * const data = { amount: 1000000000000000000n, nested: { value: 42n } }\n *\n * // Serialize to JSON string\n * const json = jsonSerializer.stringify(data)\n * // '{\"amount\":{\"__type\":\"bigint\",\"value\":\"1000000000000000000\"},\"nested\":{\"value\":{\"__type\":\"bigint\",\"value\":\"42\"}}}'\n *\n * // Parse back to original types\n * const parsed = jsonSerializer.parse(json)\n * // { amount: 1000000000000000000n, nested: { value: 42n } }\n * ```\n */\nexport const jsonSerializer = {\n /**\n * Serialize a value to a JSON string, handling BigInt values.\n *\n * @param value - The value to serialize\n * @param space - Optional indentation (same as JSON.stringify)\n * @returns JSON string with BigInt values tagged\n */\n stringify(value: unknown, space?: string | number): string {\n return JSON.stringify(value, replacer, space)\n },\n\n /**\n * Parse a JSON string, restoring tagged BigInt values.\n *\n * @param text - The JSON string to parse\n * @returns The parsed value with BigInt values restored\n */\n parse(text: string): unknown {\n return JSON.parse(text, reviver)\n },\n} as const\n","/**\n * Snapshot recovery from dispatch calldata.\n * @module v2/sync/snapshotRecovery\n */\n\nimport type { AbiFunction, Address, Hash, PublicClient } from 'viem'\nimport { decodeFunctionData, toFunctionSelector } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\n\nconst LOG_SCAN_WINDOW = 10_000n\n\ntype SnapshotEventLog = Awaited<ReturnType<PublicClient['getLogs']>>[number]\ntype SnapshotCandidateEvent = SnapshotEventLog & {\n transactionHash: Hash\n blockNumber: bigint\n logIndex: number\n}\n\n/**\n * Parameters for recovering position snapshot from dispatch calldata.\n */\nexport interface RecoverSnapshotParams {\n /** viem public client */\n client: PublicClient\n /** Pool address */\n poolAddress: Address\n /** Account to recover positions for */\n account: Address\n /** Starting block for transaction search (defaults to 0) */\n fromBlock?: bigint\n /** Ending block for transaction search (defaults to latest) */\n toBlock?: bigint\n}\n\n/**\n * Snapshot recovery result.\n */\nexport interface SnapshotRecoveryResult {\n /** Whether recovery was successful */\n success: boolean\n /** Position IDs from the final position list */\n positionIds: bigint[]\n /** Block number of the recovery transaction */\n blockNumber: bigint\n /** Block hash of the recovery transaction */\n blockHash: Hash\n /** Transaction hash used for recovery */\n transactionHash: Hash\n}\n\n/**\n * Recover position snapshot from the last dispatch transaction.\n * This is the primary recovery method - it finds the most recent dispatch()\n * call and extracts the finalPositionIdList from the calldata.\n *\n * @param params - Recovery parameters\n * @returns Snapshot recovery result\n */\nexport async function recoverSnapshot(\n params: RecoverSnapshotParams,\n): Promise<SnapshotRecoveryResult | null> {\n const { client, poolAddress, account, toBlock } = params\n\n // Get the latest block if not specified\n const latestBlock = toBlock ?? (await client.getBlockNumber())\n\n // Search for transactions from the account to the pool\n // We need to find dispatch() or dispatchFrom() calls\n // Note: This requires the account to have sent transactions directly,\n // or we need to look at internal transactions\n\n // Strategy: Look for OptionMinted or OptionBurnt events to find transactions,\n // then decode the transaction input to get the full position list\n\n const searchFromBlock = params.fromBlock ?? 0n\n if (latestBlock < searchFromBlock) return null\n\n // Fast path: a single getLogs per event type over the entire\n // [searchFromBlock, latest] range. The queries are filtered by `address` and\n // an indexed account topic, so providers like Alchemy impose no block-range\n // cap on them (only a result-count cap) — one call per event type is enough\n // and the returned set is already complete, so there are no older windows to\n // scan. This avoids walking the whole chain in 10k-block chunks (4 getLogs\n // per chunk), which for accounts with no history is thousands of empty calls.\n try {\n const events = await getSnapshotEventsForWindow({\n client,\n poolAddress,\n account,\n fromBlock: searchFromBlock,\n toBlock: latestBlock,\n })\n return await recoverSnapshotFromEvents({ client, account, events })\n } catch (error) {\n // Only fall back to windowed scanning when the provider rejected the wide\n // range. Any other error (e.g. transport failure) should propagate.\n if (!isRangeLimitError(error)) throw error\n }\n\n // Fallback for providers that cap getLogs block range: scan newest-to-oldest\n // in 10k-block windows and stop at the first window that yields a snapshot.\n let windowToBlock = latestBlock\n while (true) {\n const windowFromBlock =\n windowToBlock - searchFromBlock + 1n > LOG_SCAN_WINDOW\n ? windowToBlock - LOG_SCAN_WINDOW + 1n\n : searchFromBlock\n\n const events = await getSnapshotEventsForWindow({\n client,\n poolAddress,\n account,\n fromBlock: windowFromBlock,\n toBlock: windowToBlock,\n })\n const snapshot = await recoverSnapshotFromEvents({ client, account, events })\n if (snapshot) return snapshot\n\n if (windowFromBlock === searchFromBlock) break\n windowToBlock = windowFromBlock - 1n\n }\n\n // No snapshot found\n return null\n}\n\n/**\n * Detect provider errors that indicate the requested getLogs block range was\n * too wide (so the caller should retry with smaller windows). Covers the common\n * phrasings used by Alchemy, Infura, and other JSON-RPC providers.\n */\nfunction isRangeLimitError(error: unknown): boolean {\n const parts: string[] = []\n let current: unknown = error\n let depth = 0\n while (current && typeof current === 'object' && depth < 5) {\n const obj = current as Record<string, unknown>\n if (typeof obj.message === 'string') parts.push(obj.message)\n if (typeof obj.details === 'string') parts.push(obj.details)\n current = obj.cause\n depth += 1\n }\n if (typeof error === 'string') parts.push(error)\n\n const message = parts.join(' ').toLowerCase()\n if (!message) return false\n\n return (\n message.includes('block range') ||\n message.includes('range is too large') ||\n message.includes('range too large') ||\n message.includes('query returned more than') ||\n message.includes('too many results') ||\n message.includes('log response size exceeded') ||\n message.includes('exceeds the limit') ||\n (message.includes('range') && message.includes('limit'))\n )\n}\n\nasync function getSnapshotEventsForWindow(params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n fromBlock: bigint\n toBlock: bigint\n}): Promise<SnapshotEventLog[]> {\n const { client, poolAddress, account, fromBlock, toBlock } = params\n\n // OptionMinted/OptionBurnt cover the account's own dispatches.\n // ForcedExercised/AccountLiquidated cover third-party dispatchFrom calls\n // where the tx sender is not the account but calldata contains the final list.\n const [mintEvents, burnEvents, forceExerciseEvents, liquidationEvents] = 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,\n toBlock,\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: 'uint128', name: 'positionSize', indexed: false },\n { type: 'uint256', name: 'tokenId', indexed: true },\n { type: 'int256[4]', name: 'premiaByLeg', indexed: false },\n ],\n },\n args: {\n recipient: account,\n },\n fromBlock,\n toBlock,\n }),\n client.getLogs({\n address: poolAddress,\n event: {\n type: 'event',\n name: 'ForcedExercised',\n inputs: [\n { type: 'address', name: 'exercisor', indexed: true },\n { type: 'address', name: 'user', indexed: true },\n { type: 'uint256', name: 'tokenId', indexed: true },\n { type: 'int256', name: 'exerciseFee', indexed: false },\n ],\n },\n args: {\n user: account,\n },\n fromBlock,\n toBlock,\n }),\n client.getLogs({\n address: poolAddress,\n event: {\n type: 'event',\n name: 'AccountLiquidated',\n inputs: [\n { type: 'address', name: 'liquidator', indexed: true },\n { type: 'address', name: 'liquidatee', indexed: true },\n { type: 'int256', name: 'bonusAmounts', indexed: false },\n ],\n },\n args: {\n liquidatee: account,\n },\n fromBlock,\n toBlock,\n }),\n ])\n\n return [...mintEvents, ...burnEvents, ...forceExerciseEvents, ...liquidationEvents]\n}\n\nasync function recoverSnapshotFromEvents(params: {\n client: PublicClient\n account: Address\n events: SnapshotEventLog[]\n}): Promise<SnapshotRecoveryResult | null> {\n const { client, account, events } = params\n\n // Combine and sort by block number (descending) to get most recent first\n const allEvents = events.filter(isSnapshotCandidateEvent).sort((a, b) => {\n const blockDiff = Number(b.blockNumber - a.blockNumber)\n if (blockDiff !== 0) return blockDiff\n return Number(b.logIndex - a.logIndex)\n })\n\n // Deduplicate by transaction hash — multiple events from the same tx\n // (e.g. OptionMinted for each leg) would produce duplicate entries\n const seen = new Set<string>()\n const uniqueEvents = allEvents.filter((e) => {\n if (seen.has(e.transactionHash)) return false\n seen.add(e.transactionHash)\n return true\n })\n\n // Find the most recent transaction with position data\n for (const event of uniqueEvents) {\n try {\n const [tx, block] = await Promise.all([\n client.getTransaction({ hash: event.transactionHash }),\n client.getBlock({ blockNumber: event.blockNumber }),\n ])\n\n // A single tx (e.g. a force-exercise multicall) can embed several\n // dispatch/dispatchFrom calls — the exercisor's own dispatch alongside the\n // victim's dispatchFrom. Select a strict account match first, then allow a\n // plain dispatch only because this tx came from an account-indexed event.\n const candidates = decodeAllDispatchCalldata(tx.input)\n const decoded =\n selectDispatchForAccount(candidates, account, tx.from) ??\n selectDispatchProvenByAccountEvent(candidates)\n if (!decoded) {\n continue\n }\n\n return {\n success: true,\n positionIds: decoded.positionIds,\n blockNumber: event.blockNumber,\n blockHash: block.hash,\n transactionHash: event.transactionHash,\n }\n } catch {\n // Transaction fetch failed, continue\n }\n }\n\n return null\n}\n\nfunction isSnapshotCandidateEvent(event: SnapshotEventLog): event is SnapshotCandidateEvent {\n return event.transactionHash !== null && event.blockNumber !== null && event.logIndex !== null\n}\n\n/**\n * Parameters for recovering a snapshot from a known transaction hash.\n */\nexport interface RecoverSnapshotFromTxParams {\n /** viem public client */\n client: PublicClient\n /** Transaction hash of a known dispatch() call */\n transactionHash: Hash\n /** Account to verify. When set, rejects transactions not sent by (or targeting) this account. */\n account?: Address\n /** Pool address to validate against. When set, rejects transactions not sent to this pool. */\n pool?: Address\n}\n\n/**\n * Recover position snapshot from a specific dispatch transaction hash.\n *\n * This is an O(1) alternative to {@link recoverSnapshot} when you already\n * know the tx hash of the most recent dispatch. It fetches the transaction,\n * decodes the `finalPositionIdList` from the calldata, and returns the result\n * — no event scanning required.\n *\n * @param params - Recovery parameters including the transaction hash\n * @returns Snapshot recovery result, or null if the tx is not a dispatch call\n *\n * @example\n * ```typescript\n * const snapshot = await recoverSnapshotFromTx({\n * client,\n * transactionHash: '0xabc...',\n * })\n * if (snapshot) {\n * console.log('Open positions:', snapshot.positionIds)\n * }\n * ```\n */\nexport async function recoverSnapshotFromTx(\n params: RecoverSnapshotFromTxParams,\n): Promise<SnapshotRecoveryResult | null> {\n const { client, transactionHash, account, pool } = params\n\n const tx = await client.getTransaction({ hash: transactionHash })\n\n // Pending transactions have no block number — cannot recover snapshot\n if (tx.blockNumber == null) return null\n\n // Validate pool: transaction must have been sent to the expected pool address\n if (pool && tx.to?.toLowerCase() !== pool.toLowerCase()) {\n return null\n }\n\n const candidates = decodeAllDispatchCalldata(tx.input)\n if (candidates.length === 0) return null\n\n // Validate account context:\n // - dispatch: tx.from must be the account (msg.sender is the trader)\n // - dispatchFrom: decoded.targetAccount must be the account (builder sends on behalf of trader)\n // A tx may embed several dispatch calls (e.g. a force-exercise multicall carrying both\n // the exercisor's dispatch and the victim's dispatchFrom); pick the one for `account`.\n const decoded = account\n ? selectDispatchForAccount(candidates, account, tx.from)\n : candidates[candidates.length - 1]\n if (!decoded) return null\n\n const blockNumber = tx.blockNumber\n const block = await client.getBlock({ blockNumber })\n\n return {\n success: true,\n positionIds: decoded.positionIds,\n blockNumber,\n blockHash: block.hash,\n transactionHash,\n }\n}\n\n/**\n * Decoded dispatch calldata result.\n */\nexport interface DispatchCalldata {\n /** Final position ID list after the dispatch */\n positionIds: bigint[]\n /** Target account (only set for dispatchFrom) */\n targetAccount?: Address\n}\n\n/**\n * Decode position IDs from dispatch calldata.\n *\n * When the tx embeds multiple dispatch/dispatchFrom calls (e.g. a force-exercise\n * multicall), this returns the last one — prefer {@link decodeAllDispatchCalldata}\n * plus {@link selectDispatchForAccount} when the account context matters.\n *\n * @param input - Transaction input data\n * @returns Decoded dispatch data or null if not a dispatch call\n */\nexport function decodeDispatchCalldata(input: `0x${string}`): DispatchCalldata | null {\n const all = decodeAllDispatchCalldata(input)\n return all.length > 0 ? all[all.length - 1] : null\n}\n\n/**\n * Decode every dispatch/dispatchFrom call embedded in transaction calldata.\n *\n * A single tx can carry more than one such call — most importantly a force-exercise\n * `multicall` that bundles the exercisor's own `dispatch` together with the victim's\n * `dispatchFrom`. Returning all candidates lets the caller select the one attributable\n * to the relevant account ({@link selectDispatchForAccount}).\n *\n * @param input - Transaction input data\n * @returns All decoded dispatch calls, in calldata order (may be empty)\n */\nexport function decodeAllDispatchCalldata(input: `0x${string}`): DispatchCalldata[] {\n // Try direct dispatch/dispatchFrom first\n const direct = decodeDirectDispatch(input)\n if (direct) return [direct]\n\n // Try unwrapping smart contract wallet wrappers (executeBatch, execute, multicall)\n return decodeWrappedDispatch(input)\n}\n\n/**\n * Select the dispatch call attributable to `account` from a set of candidates.\n *\n * - `dispatchFrom`: matches when `targetAccount === account` (builder/exercisor acting\n * on behalf of the account).\n * - `dispatch` (no `targetAccount`): matches only when the tx sender is the account.\n *\n * Returns the LAST matching candidate (in calldata order), or null when none are\n * attributable to `account`. The last dispatch reflects the final post-transaction\n * state when a single tx contains multiple dispatches for the same account (e.g. a\n * multicall). Matching also prevents accepting a third party's `dispatch` (e.g. the\n * exercisor's own, bundled in a force-exercise multicall) as the account's snapshot.\n *\n * @param candidates - Decoded dispatch calls from a single tx, in calldata order\n * @param account - Account whose position list we are recovering\n * @param txFrom - The transaction sender (`tx.from`)\n */\nexport function selectDispatchForAccount(\n candidates: DispatchCalldata[],\n account: Address,\n txFrom: Address,\n): DispatchCalldata | null {\n const acct = account.toLowerCase()\n let match: DispatchCalldata | null = null\n for (const candidate of candidates) {\n if (candidate.targetAccount) {\n if (candidate.targetAccount.toLowerCase() === acct) match = candidate\n } else if (txFrom.toLowerCase() === acct) {\n match = candidate\n }\n }\n return match\n}\n\nfunction selectDispatchProvenByAccountEvent(\n candidates: DispatchCalldata[],\n): DispatchCalldata | null {\n let match: DispatchCalldata | null = null\n for (const candidate of candidates) {\n if (candidate.targetAccount === undefined) match = candidate\n }\n return match\n}\n\n/**\n * Try to decode input as a direct dispatch or dispatchFrom call.\n */\nfunction decodeDirectDispatch(input: `0x${string}`): DispatchCalldata | null {\n try {\n const decoded = decodeFunctionData({\n abi: panopticPoolV2Abi,\n data: input,\n })\n\n if (decoded.functionName === 'dispatch') {\n const args = decoded.args as readonly [\n bigint[],\n bigint[],\n bigint[],\n readonly [number, number, number][],\n boolean,\n bigint,\n ]\n return { positionIds: [...args[1]] } // finalPositionIdList\n }\n\n if (decoded.functionName === 'dispatchFrom') {\n const args = decoded.args as readonly [bigint[], Address, bigint[], bigint[], bigint]\n return {\n positionIds: [...args[3]], // positionIdListToFinal\n targetAccount: args[1],\n }\n }\n\n return null\n } catch {\n return null\n }\n}\n\n/**\n * 4-byte function selectors for dispatch/dispatchFrom, derived from the generated ABI.\n * Used for scanning raw calldata inside smart contract wallet wrappers.\n */\nconst DISPATCH_SELECTOR = toFunctionSelector(\n panopticPoolV2Abi.find((e) => e.type === 'function' && e.name === 'dispatch') as AbiFunction,\n).slice(2) // strip 0x prefix for hex scanning\n\nconst DISPATCH_FROM_SELECTOR = toFunctionSelector(\n panopticPoolV2Abi.find((e) => e.type === 'function' && e.name === 'dispatchFrom') as AbiFunction,\n).slice(2)\n\n/**\n * Scan raw transaction input for embedded dispatch calldata.\n *\n * Smart contract wallets (Safe, Turnkey, ERC-4337) and vault managers\n * wrap dispatch calls inside executeBatch → manage → dispatch chains.\n * Instead of decoding each wrapper layer, we scan the raw hex for the\n * dispatch function selector and attempt to decode from that offset.\n *\n * This handles arbitrary nesting depth without knowing wrapper ABIs.\n */\nfunction decodeWrappedDispatch(input: `0x${string}`): DispatchCalldata[] {\n const hex = input.slice(2).toLowerCase()\n const selectors = [DISPATCH_SELECTOR, DISPATCH_FROM_SELECTOR]\n\n // Single left-to-right pass: find the earliest selector match at each offset and\n // collect every successful decode, in calldata order. The caller selects the call\n // attributable to the relevant account rather than blindly taking one.\n const results: DispatchCalldata[] = []\n let offset = 0\n\n while (offset < hex.length) {\n // Find the nearest selector match from current offset\n let earliestIdx = -1\n for (const selector of selectors) {\n const idx = hex.indexOf(selector, offset)\n if (idx !== -1 && (earliestIdx === -1 || idx < earliestIdx)) {\n earliestIdx = idx\n }\n }\n if (earliestIdx === -1) break\n\n const candidate = `0x${hex.slice(earliestIdx)}` as `0x${string}`\n const result = decodeDirectDispatch(candidate)\n if (result) results.push(result)\n\n offset = earliestIdx + 8 // Move past this selector\n }\n\n return results\n}\n","/**\n * Get tracked position IDs from local cache.\n * @module v2/sync/getTrackedPositionIds\n */\n\nimport type { Address, Hash, PublicClient } from 'viem'\n\nimport type { StorageAdapter } from '../storage'\nimport { getPositionsKey, jsonSerializer } from '../storage'\nimport {\n type SnapshotRecoveryResult,\n recoverSnapshot,\n recoverSnapshotFromTx,\n} from './snapshotRecovery'\n\n/**\n * Parameters for getTrackedPositionIds.\n */\nexport interface GetTrackedPositionIdsParams {\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account to get positions for */\n account: Address\n /** Storage adapter */\n storage: StorageAdapter\n}\n\n/**\n * Get all tracked position IDs for an account from local cache.\n *\n * This function reads from the storage adapter without making RPC calls.\n * The positions returned may include closed positions if the cache is stale.\n * Use `getPositions()` for authoritative on-chain data.\n *\n * @param params - Query parameters\n * @returns Array of position token IDs\n */\nexport async function getTrackedPositionIds(\n params: GetTrackedPositionIdsParams,\n): Promise<bigint[]> {\n const { chainId, poolAddress, account, storage } = params\n\n const key = getPositionsKey(chainId, poolAddress, account)\n const data = await storage.get(key)\n\n if (!data) {\n return []\n }\n\n try {\n const positionIds = jsonSerializer.parse(data) as bigint[]\n return positionIds\n } catch {\n // Corrupted data, return empty\n return []\n }\n}\n\n/**\n * Check if a specific position ID is tracked.\n *\n * @param params - Query parameters\n * @param tokenId - Token ID to check\n * @returns Whether the position is tracked\n */\nexport async function isPositionTracked(\n params: GetTrackedPositionIdsParams,\n tokenId: bigint,\n): Promise<boolean> {\n const positionIds = await getTrackedPositionIds(params)\n return positionIds.some((id) => id === tokenId)\n}\n\n/**\n * Clear all tracked positions for an account.\n *\n * @param params - Query parameters\n */\nexport async function clearTrackedPositions(params: GetTrackedPositionIdsParams): Promise<void> {\n const { chainId, poolAddress, account, storage } = params\n\n const key = getPositionsKey(chainId, poolAddress, account)\n await storage.delete(key)\n}\n\n/**\n * Parameters for getOpenPositionIds.\n */\nexport interface GetOpenPositionIdsParams {\n /** viem PublicClient */\n client: PublicClient\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account to get positions for */\n account: Address\n /** Storage adapter (used to update local cache with the authoritative list) */\n storage?: StorageAdapter\n /**\n * Transaction hash of a known dispatch() call. When provided, the position\n * list is decoded directly from this tx's calldata (O(1)) instead of\n * scanning events to find the most recent dispatch.\n */\n lastDispatchTxHash?: Hash\n /**\n * Starting block for event scanning in recoverSnapshot.\n * When set, limits the getLogs window to [fromBlock, latest] instead of\n * scanning from block 0. Use the checkpoint's lastBlock for incremental syncs.\n */\n fromBlock?: bigint\n}\n\n/**\n * Get the authoritative list of open position IDs from the chain.\n *\n * Recovers the `finalPositionIdList` from the account's most recent\n * `dispatch()` transaction calldata. This is the on-chain–validated set of\n * open positions (verified against `s_positionsHash` by the contract) and\n * requires only a few RPC calls regardless of account history length.\n *\n * This is the recommended way to get position IDs for `existingPositionIds`\n * (openPosition) and `positionIdList` (closePosition).\n *\n * If `storage` is provided, the local cache is updated with the result.\n *\n * @param params - Query parameters\n * @returns Array of currently open position token IDs, or null if no snapshot was found\n */\nexport async function getOpenPositionIds(\n params: GetOpenPositionIdsParams,\n): Promise<bigint[] | null> {\n const { client, chainId, poolAddress, account, storage, lastDispatchTxHash, fromBlock } = params\n\n // Fast path: decode directly from a known tx hash (O(1), no event scanning)\n // Falls back to full event-scanning recovery if the fast path returns null or throws\n let snapshot: SnapshotRecoveryResult | null = null\n if (lastDispatchTxHash) {\n try {\n snapshot = await recoverSnapshotFromTx({\n client,\n transactionHash: lastDispatchTxHash,\n account,\n pool: poolAddress,\n })\n } catch {\n // Fast path failed (e.g. RPC error, validation mismatch); fall through to slow-path\n snapshot = null\n }\n }\n\n if (!snapshot) {\n snapshot = await recoverSnapshot({ client, poolAddress, account, fromBlock })\n }\n\n if (!snapshot) {\n return null\n }\n\n // Update local cache if storage provided\n if (storage) {\n const key = getPositionsKey(chainId, poolAddress, account)\n await storage.set(key, jsonSerializer.stringify(snapshot.positionIds))\n }\n\n return snapshot.positionIds\n}\n","/**\n * Position operations for the Panoptic v2 SDK.\n * @module v2/writes/position\n */\n\nimport type { Address, Hex, PublicClient, WalletClient } from 'viem'\nimport { encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { InvalidTickLimitsError, MissingPositionIdsError } from '../errors'\nimport type { StorageAdapter } from '../storage'\nimport { getPositionsKey, jsonSerializer } from '../storage'\nimport { getTrackedPositionIds } from '../sync/getTrackedPositionIds'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\n/**\n * Optional storage parameters for auto-tracking positions.\n * When provided, `*AndWait` variants will automatically update the local\n * position cache after a successful transaction.\n */\nexport interface PositionStorageParams {\n /** Storage adapter for position tracking */\n storage: StorageAdapter\n /** Chain ID (required for storage key construction) */\n chainId: bigint\n}\n\n/**\n * Resolve the position ID list: use the explicit param if provided,\n * otherwise read from storage. Throws if neither is available.\n */\nasync function resolvePositionIds(\n explicit: bigint[] | undefined,\n storage: StorageAdapter | undefined,\n chainId: bigint | undefined,\n poolAddress: Address,\n account: Address,\n): Promise<bigint[]> {\n if (explicit !== undefined) return explicit\n if (storage && chainId !== undefined) {\n return getTrackedPositionIds({ chainId, poolAddress, account, storage })\n }\n throw new MissingPositionIdsError()\n}\n\n/**\n * Save a position ID list to storage.\n */\nasync function savePositionIds(\n storage: StorageAdapter,\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n positionIds: bigint[],\n): Promise<void> {\n const key = getPositionsKey(chainId, poolAddress, account)\n await storage.set(key, jsonSerializer.stringify(positionIds))\n}\n\n/**\n * Tick and spread limits for position operations.\n * [tickLimitLow, tickLimitHigh, spreadLimitTick]\n *\n * SDK uses bigint for all numerics. Converted to number at viem boundary.\n *\n * @deprecated Use individual tickLimitLow, tickLimitHigh, spreadLimit params with swapAtMint flag\n */\nexport type TickAndSpreadLimits = readonly [bigint, bigint, bigint]\n\n/**\n * Parameters for opening a position.\n */\nexport interface OpenPositionParams extends Partial<PositionStorageParams> {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Existing position IDs held by the account (before this mint). Optional if storage + chainId are provided. */\n existingPositionIds?: bigint[]\n /** TokenId of the position to open */\n tokenId: bigint\n /** Position size (number of contracts) */\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 mint 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 (defaults to 0) */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Open a new position using dispatch.\n *\n * @param params - Position parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * import { MIN_TICK, MAX_TICK } from '@panoptic/sdk'\n *\n * const result = await openPosition({\n * client,\n * walletClient,\n * account,\n * poolAddress,\n * existingPositionIds: [], // Existing positions held before this mint\n * tokenId,\n * positionSize: 1n,\n * tickLimitLow: MIN_TICK,\n * tickLimitHigh: MAX_TICK,\n * swapAtMint: false, // true for covered/single-sided exposure\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function openPosition(params: OpenPositionParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n existingPositionIds: explicitIds,\n tokenId,\n positionSize,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit = 0n,\n swapAtMint = false,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n storage,\n chainId,\n txOverrides,\n } = params\n\n // Validate tick limits\n if (tickLimitLow > tickLimitHigh) {\n throw new InvalidTickLimitsError(tickLimitLow, tickLimitHigh)\n }\n\n const existingPositionIds = await resolvePositionIds(\n explicitIds,\n storage,\n chainId,\n poolAddress,\n account,\n )\n\n // Prepare position lists for dispatch:\n // - positionIdList: positions being minted in this call (just the new tokenId)\n // - finalPositionIdList: all positions the user will have after the mint\n const positionIdList = [tokenId]\n const finalPositionIdList = [...existingPositionIds, tokenId]\n\n // Position sizes array contains the size for the new position\n const positionSizes = [positionSize]\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 return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n positionSizes,\n [tickLimits],\n usePremiaAsCollateral,\n builderCode,\n ],\n txOverrides,\n })\n}\n\n/**\n * Build the dispatch calldata for opening a position without executing.\n * Returns the target address and encoded calldata, suitable for manual\n * transaction construction (e.g. RFQ broadcast-reconstruct flow).\n *\n * @param params - Position parameters (existingPositionIds required, no storage resolution)\n * @returns { to, data } — contract address and encoded dispatch calldata\n */\nexport function buildOpenPositionCalldata(params: {\n poolAddress: Address\n existingPositionIds: bigint[]\n tokenId: bigint\n positionSize: bigint\n tickLimitLow: bigint\n tickLimitHigh: bigint\n spreadLimit?: bigint\n swapAtMint?: boolean\n usePremiaAsCollateral?: boolean\n builderCode?: bigint\n}): { to: Address; data: Hex } {\n const {\n poolAddress,\n existingPositionIds,\n tokenId,\n positionSize,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit = 0n,\n swapAtMint = false,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n } = params\n\n if (tickLimitLow > tickLimitHigh) {\n throw new InvalidTickLimitsError(tickLimitLow, tickLimitHigh)\n }\n\n const positionIdList = [tokenId]\n const finalPositionIdList = [...existingPositionIds, tokenId]\n const positionSizes = [positionSize]\n\n const tickLimits: readonly [number, number, number] = swapAtMint\n ? [Number(tickLimitHigh), Number(tickLimitLow), Number(spreadLimit)]\n : [Number(tickLimitLow), Number(tickLimitHigh), Number(spreadLimit)]\n\n const data = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n positionSizes,\n [tickLimits],\n usePremiaAsCollateral,\n builderCode,\n ],\n })\n\n return { to: poolAddress, data }\n}\n\n/**\n * Open position and wait for confirmation.\n */\nexport async function openPositionAndWait(params: OpenPositionParams): Promise<TxReceipt> {\n const result = await openPosition(params)\n const receipt = await result.wait()\n\n // Auto-update storage if provided\n const {\n storage,\n chainId,\n account,\n poolAddress,\n tokenId,\n existingPositionIds: explicitIds,\n } = params\n if (storage && chainId !== undefined) {\n const base =\n explicitIds ?? (await getTrackedPositionIds({ chainId, poolAddress, account, storage }))\n await savePositionIds(storage, chainId, poolAddress, account, [...base, tokenId])\n }\n\n return receipt\n}\n\n/**\n * Parameters for closing a position.\n */\nexport interface ClosePositionParams extends Partial<PositionStorageParams> {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Current position ID list. Optional if storage + chainId are provided. */\n positionIdList?: bigint[]\n /** TokenId of the position to close */\n tokenId: bigint\n /** Position size to close (use full size for complete 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 (defaults to 0) */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Close an existing position using dispatch.\n *\n * @param params - Close parameters\n * @returns TxResult\n */\nexport async function closePosition(params: ClosePositionParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n positionIdList: explicitList,\n tokenId,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit = 0n,\n swapAtMint = false,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n storage,\n chainId,\n txOverrides,\n } = params\n\n // Validate tick limits\n if (tickLimitLow > tickLimitHigh) {\n throw new InvalidTickLimitsError(tickLimitLow, tickLimitHigh)\n }\n\n const positionIdList = await resolvePositionIds(\n explicitList,\n storage,\n chainId,\n poolAddress,\n account,\n )\n\n // For closing, final list excludes the closed position\n const finalPositionIdList = positionIdList.filter((id) => id !== 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 ? [Number(tickLimitHigh), Number(tickLimitLow), Number(spreadLimit)]\n : [Number(tickLimitLow), Number(tickLimitHigh), Number(spreadLimit)]\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [[tokenId], finalPositionIdList, [0n], [tickLimits], usePremiaAsCollateral, builderCode],\n txOverrides,\n })\n}\n\n/**\n * Close position and wait for confirmation.\n */\nexport async function closePositionAndWait(params: ClosePositionParams): Promise<TxReceipt> {\n const result = await closePosition(params)\n const receipt = await result.wait()\n\n // Auto-update storage if provided\n const { storage, chainId, account, poolAddress, tokenId, positionIdList: explicitList } = params\n if (storage && chainId !== undefined) {\n const base =\n explicitList ?? (await getTrackedPositionIds({ chainId, poolAddress, account, storage }))\n await savePositionIds(\n storage,\n chainId,\n poolAddress,\n account,\n base.filter((id) => id !== tokenId),\n )\n }\n\n return receipt\n}\n\n/**\n * Parameters for rolling a position.\n */\nexport interface RollPositionParams extends Partial<PositionStorageParams> {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Current position ID list. Optional if storage + chainId are provided. */\n positionIdList?: bigint[]\n /** TokenId of position to close */\n oldTokenId: bigint\n /** Size of position being closed */\n oldPositionSize: bigint\n /** TokenId of new position to open */\n newTokenId: bigint\n /** Size of new position */\n newPositionSize: bigint\n /** Lower tick limit for close (always <= closeTickLimitHigh) */\n closeTickLimitLow: bigint\n /** Upper tick limit for close (always >= closeTickLimitLow) */\n closeTickLimitHigh: bigint\n /** Spread limit for close (use 0n for no spread limit) */\n closeSpreadLimit?: bigint\n /** Whether to swap tokens when closing */\n closeSwapAtMint?: boolean\n /** Lower tick limit for open (always <= openTickLimitHigh) */\n openTickLimitLow: bigint\n /** Upper tick limit for open (always >= openTickLimitLow) */\n openTickLimitHigh: bigint\n /** Spread limit for open (use 0n for no spread limit) */\n openSpreadLimit?: bigint\n /** Whether to swap tokens when opening */\n openSwapAtMint?: boolean\n /** Whether to use premia as collateral */\n usePremiaAsCollateral?: boolean\n /** Builder code */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Roll a position (close one, open another) in a single transaction.\n *\n * @param params - Roll parameters\n * @returns TxResult\n */\nexport async function rollPosition(params: RollPositionParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n positionIdList: explicitList,\n oldTokenId,\n oldPositionSize,\n newTokenId,\n newPositionSize,\n closeTickLimitLow,\n closeTickLimitHigh,\n closeSpreadLimit = 0n,\n closeSwapAtMint = false,\n openTickLimitLow,\n openTickLimitHigh,\n openSpreadLimit = 0n,\n openSwapAtMint = false,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n storage,\n chainId,\n txOverrides,\n } = params\n\n // Validate tick limits\n if (closeTickLimitLow > closeTickLimitHigh) {\n throw new InvalidTickLimitsError(closeTickLimitLow, closeTickLimitHigh)\n }\n if (openTickLimitLow > openTickLimitHigh) {\n throw new InvalidTickLimitsError(openTickLimitLow, openTickLimitHigh)\n }\n\n const positionIdList = await resolvePositionIds(\n explicitList,\n storage,\n chainId,\n poolAddress,\n account,\n )\n\n // Final list: remove old, add new\n const finalPositionIdList = positionIdList.filter((id) => id !== oldTokenId).concat([newTokenId])\n\n // Position sizes for both operations\n const positionSizes = [oldPositionSize, newPositionSize]\n\n // Build tick limits based on swapAtMint flags\n const closeLimits: readonly [number, number, number] = closeSwapAtMint\n ? [Number(closeTickLimitHigh), Number(closeTickLimitLow), Number(closeSpreadLimit)]\n : [Number(closeTickLimitLow), Number(closeTickLimitHigh), Number(closeSpreadLimit)]\n\n const openLimits: readonly [number, number, number] = openSwapAtMint\n ? [Number(openTickLimitHigh), Number(openTickLimitLow), Number(openSpreadLimit)]\n : [Number(openTickLimitLow), Number(openTickLimitHigh), Number(openSpreadLimit)]\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n positionSizes as bigint[],\n [closeLimits, openLimits],\n usePremiaAsCollateral,\n builderCode,\n ],\n txOverrides,\n })\n}\n\n/**\n * Roll position and wait for confirmation.\n */\nexport async function rollPositionAndWait(params: RollPositionParams): Promise<TxReceipt> {\n const result = await rollPosition(params)\n const receipt = await result.wait()\n\n // Auto-update storage if provided\n const {\n storage,\n chainId,\n account,\n poolAddress,\n oldTokenId,\n newTokenId,\n positionIdList: explicitList,\n } = params\n if (storage && chainId !== undefined) {\n const base =\n explicitList ?? (await getTrackedPositionIds({ chainId, poolAddress, account, storage }))\n const updated = base.filter((id) => id !== oldTokenId).concat([newTokenId])\n await savePositionIds(storage, chainId, poolAddress, account, updated)\n }\n\n return receipt\n}\n","/**\n * Raw dispatch function for the Panoptic v2 SDK.\n * @module v2/writes/dispatch\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport type { TickAndSpreadLimits } from './position'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for dispatch function.\n */\nexport interface DispatchParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Current position ID list */\n positionIdList: bigint[]\n /** Final position ID list after operations */\n finalPositionIdList: 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 /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Execute a raw dispatch operation.\n * This is the low-level function for multi-position operations.\n *\n * @param params - Dispatch parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * // Open multiple positions atomically\n * const result = await dispatch({\n * client,\n * walletClient,\n * account,\n * poolAddress,\n * positionIdList: [],\n * finalPositionIdList: [tokenId1, tokenId2],\n * positionSizes: [size1, size2],\n * tickAndSpreadLimits: [limits1, limits2],\n * })\n * ```\n */\nexport async function dispatch(params: DispatchParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n positionIdList,\n finalPositionIdList,\n positionSizes,\n tickAndSpreadLimits,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\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 usePremiaAsCollateral,\n builderCode,\n ],\n txOverrides,\n })\n}\n\n/**\n * Execute dispatch and wait for confirmation.\n */\nexport async function dispatchAndWait(params: DispatchParams): Promise<TxReceipt> {\n const result = await dispatch(params)\n return result.wait()\n}\n","/**\n * Pure validator for batched mint/burn dispatch operations.\n * @module v2/batch/validate\n */\n\nimport type { BatchDiagnostic, BatchOp } from './types'\n\nexport interface ValidateBatchParams {\n items: BatchOp[]\n /** Current on-chain positionIdList for the account. */\n existingPositionIds: bigint[]\n}\n\n/**\n * Run all batch-level and item-level validations.\n * Pure function; never throws. Empty array means \"ready to build\".\n */\nexport function validateBatch(params: ValidateBatchParams): BatchDiagnostic[] {\n const { items, existingPositionIds } = params\n const diagnostics: BatchDiagnostic[] = []\n\n if (items.length === 0) {\n diagnostics.push({\n itemIndex: -1n,\n tokenId: 0n,\n code: 'empty-batch',\n message: 'Batch is empty.',\n })\n return diagnostics\n }\n\n const head = items[0]\n if (!head) return diagnostics\n const firstPool = head.poolAddress.toLowerCase()\n const existing = new Set(existingPositionIds)\n const seen = new Map<bigint, bigint>()\n\n items.forEach((item, idx) => {\n const itemIndex = BigInt(idx)\n if (item.poolAddress.toLowerCase() !== firstPool) {\n diagnostics.push({\n itemIndex,\n tokenId: item.tokenId,\n code: 'cross-pool',\n message: `Item ${idx} targets pool ${item.poolAddress}, expected ${head.poolAddress}.`,\n })\n }\n\n if (item.tickLimitLow > item.tickLimitHigh) {\n diagnostics.push({\n itemIndex,\n tokenId: item.tokenId,\n code: 'invalid-tick-limits',\n message: `Item ${idx} tickLimitLow (${item.tickLimitLow}) > tickLimitHigh (${item.tickLimitHigh}).`,\n })\n }\n\n if (item.kind === 'mint') {\n if (item.positionSize <= 0n) {\n diagnostics.push({\n itemIndex,\n tokenId: item.tokenId,\n code: 'invalid-position-size',\n message: `Mint at index ${idx} must have positionSize > 0.`,\n })\n }\n if (existing.has(item.tokenId)) {\n diagnostics.push({\n itemIndex,\n tokenId: item.tokenId,\n code: 'mint-already-onchain',\n message: `Mint at index ${idx} targets tokenId ${item.tokenId} which is already open on-chain.`,\n })\n }\n } else if (!existing.has(item.tokenId)) {\n diagnostics.push({\n itemIndex,\n tokenId: item.tokenId,\n code: 'burn-not-found',\n message: `Burn at index ${idx} targets tokenId ${item.tokenId} which is not in the account's positions.`,\n })\n }\n\n const prior = seen.get(item.tokenId)\n if (prior !== undefined) {\n diagnostics.push({\n itemIndex,\n tokenId: item.tokenId,\n code: 'duplicate-tokenid-in-batch',\n message: `Item ${idx} duplicates tokenId ${item.tokenId} also at index ${prior}.`,\n })\n } else {\n seen.set(item.tokenId, itemIndex)\n }\n })\n\n return diagnostics\n}\n","/**\n * Pure builder converting batched mint/burn ops into PanopticPool.dispatch() args.\n * @module v2/batch/build\n */\n\nimport type { TickAndSpreadLimits } from '../writes/position'\nimport type { BatchDiagnostic, BatchDispatchArgs, BatchOp } from './types'\nimport { validateBatch } from './validate'\n\nexport interface BuildBatchDispatchArgsParams {\n items: BatchOp[]\n /** Current on-chain positionIdList for the account. */\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}\n\nexport interface BuildBatchDispatchArgsResult {\n /** Null when diagnostics are non-empty. */\n args: BatchDispatchArgs | null\n diagnostics: BatchDiagnostic[]\n}\n\n/**\n * Build dispatch() args from a list of batch ops + the account's current\n * on-chain positionIdList. Returns diagnostics instead of throwing so callers\n * (UIs, bots) can render conflicts before deciding what to do.\n *\n * The order in `items` is preserved as the operation order in `positionIdList`,\n * `positionSizes`, and `tickAndSpreadLimits`. `finalPositionIdList` is the\n * post-execution state: existing minus burns, plus mints.\n */\nexport function buildBatchDispatchArgs(\n params: BuildBatchDispatchArgsParams,\n): BuildBatchDispatchArgsResult {\n const { items, existingPositionIds, usePremiaAsCollateral = false, builderCode = 0n } = params\n\n const diagnostics = validateBatch({ items, existingPositionIds })\n if (diagnostics.length > 0) {\n return { args: null, diagnostics }\n }\n\n const positionIdList = items.map((i) => i.tokenId)\n const positionSizes = items.map((i) => (i.kind === 'mint' ? i.positionSize : 0n))\n\n const tickAndSpreadLimits: TickAndSpreadLimits[] = items.map((i) => {\n const low = i.tickLimitLow <= i.tickLimitHigh ? i.tickLimitLow : i.tickLimitHigh\n const high = i.tickLimitLow <= i.tickLimitHigh ? i.tickLimitHigh : i.tickLimitLow\n const spread = i.kind === 'mint' ? i.spreadLimit : 0n\n return i.swapAtMint ? ([high, low, spread] as const) : ([low, high, spread] as const)\n })\n\n const mintIds = items.filter((i) => i.kind === 'mint').map((i) => i.tokenId)\n const burnIds = new Set(items.filter((i) => i.kind === 'burn').map((i) => i.tokenId))\n const mintIdSet = new Set(mintIds)\n const finalPositionIdList = [\n ...existingPositionIds.filter((id) => !burnIds.has(id) && !mintIdSet.has(id)),\n ...mintIds,\n ]\n\n return {\n args: {\n positionIdList,\n finalPositionIdList,\n positionSizes,\n tickAndSpreadLimits,\n usePremiaAsCollateral,\n builderCode,\n },\n diagnostics: [],\n }\n}\n","/**\n * Item-based wrapper around dispatch() for batched mint/burn ops.\n * @module v2/writes/executeBatchDispatch\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { buildBatchDispatchArgs } from '../batch/build'\nimport type { BatchOp } from '../batch/types'\nimport { BatchValidationError } from '../errors'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { dispatch } from './dispatch'\n\nexport interface ExecuteBatchDispatchParams {\n client: PublicClient\n walletClient: WalletClient\n account: Address\n poolAddress: 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 txOverrides?: TxOverrides\n}\n\n/**\n * Build dispatch args from a batch and submit them as a single transaction.\n *\n * Throws `BatchValidationError` (with the full diagnostics list) when the batch\n * fails validation. Callers that want to render diagnostics in UI should run\n * `buildBatchDispatchArgs` or `simulateBatchDispatch` first.\n */\nexport async function executeBatchDispatch(params: ExecuteBatchDispatchParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n items,\n existingPositionIds,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n txOverrides,\n } = params\n\n const { args, diagnostics } = buildBatchDispatchArgs({\n items,\n existingPositionIds,\n usePremiaAsCollateral,\n builderCode,\n })\n\n if (args === null) {\n throw new BatchValidationError(diagnostics)\n }\n\n return dispatch({\n client,\n walletClient,\n account,\n poolAddress,\n positionIdList: args.positionIdList,\n finalPositionIdList: args.finalPositionIdList,\n positionSizes: args.positionSizes,\n tickAndSpreadLimits: args.tickAndSpreadLimits,\n usePremiaAsCollateral: args.usePremiaAsCollateral,\n builderCode: args.builderCode,\n txOverrides,\n })\n}\n\n/**\n * Execute a batch dispatch and wait for confirmation.\n */\nexport async function executeBatchDispatchAndWait(\n params: ExecuteBatchDispatchParams,\n): Promise<TxReceipt> {\n const result = await executeBatchDispatch(params)\n return result.wait()\n}\n","/**\n * Liquidation functions for the Panoptic v2 SDK.\n * @module v2/writes/liquidate\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for liquidating an account.\n */\nexport interface LiquidateParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Liquidator account address */\n account: Address\n /** PanopticPool address */\n poolAddress: 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 (positions to liquidate) */\n positionIdListTo: bigint[]\n /** Final position ID list for the liquidatee after liquidation */\n positionIdListToFinal: bigint[]\n /** Packed value for using premia as collateral */\n usePremiaAsCollateral?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Liquidate an undercollateralized account using dispatchFrom.\n *\n * The liquidator calls dispatchFrom to close the liquidatee's positions\n * and receive a bonus.\n *\n * @param params - Liquidation parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await liquidate({\n * client,\n * walletClient,\n * account: liquidatorAddress,\n * poolAddress,\n * liquidatee: undercollateralizedAccount,\n * positionIdListFrom: liquidatorPositions,\n * positionIdListTo: liquidateePositions,\n * positionIdListToFinal: [], // Close all positions\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function liquidate(params: LiquidateParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n liquidatee,\n positionIdListFrom,\n positionIdListTo,\n positionIdListToFinal,\n usePremiaAsCollateral = 0n,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatchFrom',\n args: [\n positionIdListFrom,\n liquidatee,\n positionIdListTo,\n positionIdListToFinal,\n usePremiaAsCollateral,\n ],\n txOverrides,\n })\n}\n\n/**\n * Liquidate and wait for confirmation.\n */\nexport async function liquidateAndWait(params: LiquidateParams): Promise<TxReceipt> {\n const result = await liquidate(params)\n return result.wait()\n}\n","/**\n * Bot utilities for the Panoptic v2 SDK.\n *\n * Assertion functions for validating preconditions before executing operations.\n * These throw typed errors on failure, making bot code cleaner and failures explicit.\n *\n * @module v2/bot\n */\n\nimport { SafeModeError, StaleDataError, UnhealthyPoolError } from '../errors'\nimport type { BlockMeta, Pool, SafeModeState } from '../types'\n\n/**\n * Data with block metadata (anything returned by SDK read functions).\n */\nexport interface DataWithMeta {\n _meta: BlockMeta\n}\n\n/**\n * Assert that data is fresh (not stale).\n *\n * Throws StaleDataError if the data's block timestamp is older than maxAgeSeconds.\n *\n * @param data - Any SDK data with _meta field\n * @param maxAgeSeconds - Maximum allowed age in seconds\n * @param currentTimestamp - Current timestamp (defaults to Date.now() / 1000)\n * @throws StaleDataError if data is stale\n *\n * @example\n * ```typescript\n * const pool = await getPool({ client, poolAddress })\n * assertFresh(pool, 60) // Must be < 60 seconds old\n * ```\n */\nexport function assertFresh(\n data: DataWithMeta,\n maxAgeSeconds: bigint | number,\n currentTimestamp?: bigint | number,\n): void {\n const maxAge = BigInt(maxAgeSeconds)\n const now =\n currentTimestamp !== undefined\n ? BigInt(currentTimestamp)\n : BigInt(Math.floor(Date.now() / 1000))\n const blockTimestamp = data._meta.blockTimestamp\n const age = now - blockTimestamp\n\n if (age > maxAge) {\n throw new StaleDataError(blockTimestamp, now, age)\n }\n}\n\n/**\n * Assert that a pool is healthy.\n *\n * Throws UnhealthyPoolError if the pool health status is not 'active'.\n *\n * @param pool - Pool data from getPool()\n * @throws UnhealthyPoolError if pool is unhealthy (low_liquidity or paused)\n *\n * @example\n * ```typescript\n * const pool = await getPool({ client, poolAddress })\n * assertHealthy(pool) // Throws if pool is paused or has low liquidity\n * ```\n */\nexport function assertHealthy(pool: Pool): void {\n if (pool.healthStatus !== 'active') {\n throw new UnhealthyPoolError(pool.healthStatus)\n }\n}\n\n/**\n * Assert that trading is allowed on a pool.\n *\n * Checks both pool health and safe mode status. Throws appropriate errors\n * if trading is restricted.\n *\n * @param pool - Pool data from getPool()\n * @param safeMode - Optional SafeModeState from getSafeMode()\n * @throws UnhealthyPoolError if pool is unhealthy\n * @throws SafeModeError if pool is in restricted or emergency safe mode\n *\n * @example\n * ```typescript\n * const pool = await getPool({ client, poolAddress })\n * const safeMode = await getSafeMode({ client, poolAddress })\n * assertTradeable(pool, safeMode)\n * ```\n */\nexport function assertTradeable(pool: Pool, safeMode?: SafeModeState): void {\n // First check pool health\n assertHealthy(pool)\n\n // Then check safe mode if provided\n if (safeMode && safeMode.mode !== 'normal') {\n throw new SafeModeError(safeMode.mode, safeMode.reason ?? 'Trading restricted')\n }\n}\n\n/**\n * Assert that minting is allowed.\n *\n * @param safeMode - SafeModeState from getSafeMode()\n * @throws SafeModeError if minting is not allowed\n *\n * @example\n * ```typescript\n * const safeMode = await getSafeMode({ client, poolAddress })\n * assertCanMint(safeMode)\n * await openPosition({ ... })\n * ```\n */\nexport function assertCanMint(safeMode: SafeModeState): void {\n if (!safeMode.canMint) {\n throw new SafeModeError(safeMode.mode, safeMode.reason ?? 'Minting not allowed')\n }\n}\n\n/**\n * Assert that burning is allowed.\n *\n * @param safeMode - SafeModeState from getSafeMode()\n * @throws SafeModeError if burning is not allowed\n */\nexport function assertCanBurn(safeMode: SafeModeState): void {\n if (!safeMode.canBurn) {\n throw new SafeModeError(safeMode.mode, safeMode.reason ?? 'Burning not allowed')\n }\n}\n\n/**\n * Assert that liquidations are allowed.\n *\n * @param safeMode - SafeModeState from getSafeMode()\n * @throws SafeModeError if liquidations are not allowed\n */\nexport function assertCanLiquidate(safeMode: SafeModeState): void {\n if (!safeMode.canLiquidate) {\n throw new SafeModeError(safeMode.mode, safeMode.reason ?? 'Liquidations not allowed')\n }\n}\n\n/**\n * Assert that force exercise is allowed.\n *\n * @param safeMode - SafeModeState from getSafeMode()\n * @throws SafeModeError if force exercise is not allowed\n */\nexport function assertCanForceExercise(safeMode: SafeModeState): void {\n if (!safeMode.canForceExercise) {\n throw new SafeModeError(safeMode.mode, safeMode.reason ?? 'Force exercise not allowed')\n }\n}\n\n// --- RPC Error Classification ---\n\n/**\n * Common retryable RPC error codes.\n */\nconst RETRYABLE_RPC_CODES = new Set([\n -32000, // Server error (generic)\n -32001, // Resource not found (can be transient)\n -32002, // Resource unavailable\n -32003, // Transaction rejected (can retry with new nonce)\n -32005, // Limit exceeded (rate limit)\n -32097, // Rate limit\n -32098, // Request timeout\n -32099, // Internal error\n])\n\n/**\n * Common retryable error message patterns.\n */\nconst RETRYABLE_PATTERNS = [\n /timeout/i,\n /timed out/i,\n /rate limit/i,\n /too many requests/i,\n /429/i,\n /503/i,\n /504/i,\n /502/i,\n /connection refused/i,\n /connection reset/i,\n /network error/i,\n /econnreset/i,\n /econnrefused/i,\n /etimedout/i,\n /socket hang up/i,\n /temporarily unavailable/i,\n /service unavailable/i,\n /server error/i,\n /internal error/i,\n /nonce too low/i, // Can retry with correct nonce\n /replacement transaction underpriced/i, // Can retry with higher gas\n /already known/i, // Transaction already in mempool\n]\n\n/**\n * Check if an error is a retryable RPC error.\n *\n * Returns true for transient errors that may succeed on retry:\n * - Timeouts\n * - Rate limits\n * - Connection errors\n * - Server errors (5xx)\n * - Nonce errors (recoverable with correct nonce)\n *\n * @param error - The error to check\n * @returns True if the error is likely retryable\n *\n * @example\n * ```typescript\n * try {\n * await openPosition({ ... })\n * } catch (error) {\n * if (isRetryableRpcError(error)) {\n * // Wait and retry\n * await sleep(1000)\n * await openPosition({ ... })\n * } else {\n * throw error // Non-retryable, propagate\n * }\n * }\n * ```\n */\nexport function isRetryableRpcError(error: unknown): boolean {\n if (error === null || error === undefined) {\n return false\n }\n\n // Check for RPC error code\n if (typeof error === 'object') {\n const errorObj = error as Record<string, unknown>\n\n // Check code property (standard JSON-RPC error)\n if (typeof errorObj.code === 'number' && RETRYABLE_RPC_CODES.has(errorObj.code)) {\n return true\n }\n\n // Check nested cause\n if (errorObj.cause && isRetryableRpcError(errorObj.cause)) {\n return true\n }\n\n // Check details object (viem style)\n if (errorObj.details && typeof errorObj.details === 'object') {\n const details = errorObj.details as Record<string, unknown>\n if (typeof details.code === 'number' && RETRYABLE_RPC_CODES.has(details.code)) {\n return true\n }\n }\n }\n\n // Check error message patterns\n const message = getErrorMessage(error)\n if (message) {\n for (const pattern of RETRYABLE_PATTERNS) {\n if (pattern.test(message)) {\n return true\n }\n }\n }\n\n return false\n}\n\n/**\n * Extract error message from various error types.\n */\nfunction getErrorMessage(error: unknown): string | undefined {\n if (typeof error === 'string') {\n return error\n }\n if (error instanceof Error) {\n return error.message\n }\n if (typeof error === 'object' && error !== null) {\n const errorObj = error as Record<string, unknown>\n if (typeof errorObj.message === 'string') {\n return errorObj.message\n }\n if (typeof errorObj.shortMessage === 'string') {\n return errorObj.shortMessage\n }\n }\n return undefined\n}\n\n/**\n * Check if an error is a nonce-related error that can be recovered.\n *\n * @param error - The error to check\n * @returns True if this is a nonce error\n */\nexport function isNonceError(error: unknown): boolean {\n const message = getErrorMessage(error)\n if (!message) return false\n\n return (\n /nonce too low/i.test(message) ||\n /nonce too high/i.test(message) ||\n /already known/i.test(message)\n )\n}\n\n/**\n * Check if an error is a gas-related error that can be recovered.\n *\n * @param error - The error to check\n * @returns True if this is a gas error\n */\nexport function isGasError(error: unknown): boolean {\n const message = getErrorMessage(error)\n if (!message) return false\n\n return (\n /replacement transaction underpriced/i.test(message) ||\n /gas too low/i.test(message) ||\n /intrinsic gas too low/i.test(message) ||\n /max fee per gas less than block base fee/i.test(message)\n )\n}\n","/**\n * Reorg detection and handling for position sync.\n * @module v2/sync/reorgHandling\n */\n\nimport type { Address, Hash, PublicClient } from 'viem'\n\nimport type { StorageAdapter } from '../storage'\nimport { getSyncCheckpointKey, jsonSerializer } from '../storage'\nimport type { ReorgDetection, SyncCheckpoint } from '../types'\nimport { REORG_DEPTH } from '../utils/constants'\n\n/**\n * Parameters for reorg detection.\n */\nexport interface DetectReorgParams {\n /** viem public client */\n client: PublicClient\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account being synced */\n account: Address\n /** Storage adapter for checkpoint retrieval */\n storage: StorageAdapter\n}\n\n/**\n * Detect chain reorganization by comparing stored block hash with current chain.\n *\n * @param params - Detection parameters\n * @returns Reorg detection result\n */\nexport async function detectReorg(params: DetectReorgParams): Promise<ReorgDetection> {\n const { client, chainId, poolAddress, account, storage } = params\n\n // Load checkpoint\n const checkpointKey = getSyncCheckpointKey(chainId, poolAddress, account)\n const checkpointData = await storage.get(checkpointKey)\n\n if (!checkpointData) {\n // No checkpoint, no reorg to detect\n return { detected: false }\n }\n\n const checkpoint = jsonSerializer.parse(checkpointData) as SyncCheckpoint\n\n // Get the block at the checkpoint height\n try {\n const block = await client.getBlock({\n blockNumber: checkpoint.lastBlock,\n })\n\n // Compare hashes\n if (block.hash !== checkpoint.lastBlockHash) {\n // Reorg detected!\n return {\n detected: true,\n reorgBlock: checkpoint.lastBlock,\n expectedHash: checkpoint.lastBlockHash,\n actualHash: block.hash,\n blocksToResync: REORG_DEPTH,\n }\n }\n\n // No reorg\n return { detected: false }\n } catch (error) {\n // Block not found - this could mean the block was orphaned\n // Treat as a reorg\n return {\n detected: true,\n reorgBlock: checkpoint.lastBlock,\n expectedHash: checkpoint.lastBlockHash,\n actualHash: '0x0000000000000000000000000000000000000000000000000000000000000000' as Hash,\n blocksToResync: REORG_DEPTH,\n }\n }\n}\n\n/**\n * Calculate the safe resync block after a reorg.\n *\n * @param reorgBlock - Block where reorg was detected\n * @param reorgDepth - Number of blocks to roll back (default: REORG_DEPTH = 128)\n * @returns Safe block to resync from\n */\nexport function calculateResyncBlock(reorgBlock: bigint, reorgDepth: bigint = REORG_DEPTH): bigint {\n // Roll back reorgDepth blocks, but don't go below 0\n if (reorgBlock <= reorgDepth) {\n return 0n\n }\n return reorgBlock - reorgDepth\n}\n\n/**\n * Parameters for checkpoint save.\n */\nexport interface SaveCheckpointParams {\n /** Storage adapter */\n storage: StorageAdapter\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account */\n account: Address\n /** Last synced block */\n lastBlock: bigint\n /** Last synced block hash */\n lastBlockHash: Hash\n /** Position IDs discovered */\n positionIds: bigint[]\n}\n\n/**\n * Save a sync checkpoint.\n *\n * @param params - Checkpoint parameters\n */\nexport async function saveCheckpoint(params: SaveCheckpointParams): Promise<void> {\n const { storage, chainId, poolAddress, account, lastBlock, lastBlockHash, positionIds } = params\n\n const checkpoint: SyncCheckpoint = {\n chainId,\n poolAddress,\n account,\n lastBlock,\n lastBlockHash,\n positionIds,\n createdAt: BigInt(Math.floor(Date.now() / 1000)),\n }\n\n const key = getSyncCheckpointKey(chainId, poolAddress, account)\n await storage.set(key, jsonSerializer.stringify(checkpoint))\n}\n\n/**\n * Load a sync checkpoint.\n *\n * @param storage - Storage adapter\n * @param chainId - Chain ID\n * @param poolAddress - Pool address\n * @param account - Account address\n * @returns Checkpoint or null if not found\n */\nexport async function loadCheckpoint(\n storage: StorageAdapter,\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n): Promise<SyncCheckpoint | null> {\n const key = getSyncCheckpointKey(chainId, poolAddress, account)\n const data = await storage.get(key)\n\n if (!data) {\n return null\n }\n\n return jsonSerializer.parse(data) as SyncCheckpoint\n}\n\n/**\n * Clear a sync checkpoint.\n *\n * @param storage - Storage adapter\n * @param chainId - Chain ID\n * @param poolAddress - Pool address\n * @param account - Account address\n */\nexport async function clearCheckpoint(\n storage: StorageAdapter,\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n): Promise<void> {\n const key = getSyncCheckpointKey(chainId, poolAddress, account)\n await storage.delete(key)\n}\n\n/**\n * Verify block continuity for a range of blocks.\n * This checks that each block's parentHash matches the previous block's hash.\n *\n * @param client - viem public client\n * @param fromBlock - Starting block\n * @param toBlock - Ending block\n * @returns True if blocks form a valid chain\n */\nexport async function verifyBlockContinuity(\n client: PublicClient,\n fromBlock: bigint,\n toBlock: bigint,\n): Promise<boolean> {\n if (fromBlock >= toBlock) {\n return true\n }\n\n // Sample a few blocks to verify continuity\n const sampleSize = Math.min(5, Number(toBlock - fromBlock))\n const step = (toBlock - fromBlock) / BigInt(sampleSize)\n\n let previousHash: Hash | null = null\n\n for (let i = 0; i <= sampleSize; i++) {\n const blockNumber = fromBlock + step * BigInt(i)\n const block = await client.getBlock({ blockNumber })\n\n if (previousHash !== null && i > 0) {\n // For non-consecutive blocks, we can't verify parentHash\n // but we can check that the block exists\n }\n\n previousHash = block.hash\n }\n\n return true\n}\n","/**\n * Main position synchronization function.\n * @module v2/sync/syncPositions\n */\n\nimport type { Address, Hash, PublicClient } from 'viem'\n\nimport { isRetryableRpcError } from '../bot'\nimport { ProviderLagError, SyncTimeoutError } from '../errors'\nimport { getPoolMetadata } from '../reads/pool'\nimport { getPositions } from '../reads/position'\nimport type { StorageAdapter } from '../storage'\nimport { getPoolMetaKey, getPositionMetaKey, getPositionsKey, jsonSerializer } from '../storage'\nimport type { StoredPoolMeta, StoredPositionData } from '../types'\nimport { getOpenPositionIds } from './getTrackedPositionIds'\nimport { detectReorg, loadCheckpoint, saveCheckpoint } from './reorgHandling'\n\n/**\n * Parameters for syncPositions.\n */\nexport interface SyncPositionsParams {\n /** viem public client */\n client: PublicClient\n /** Chain ID */\n chainId: bigint\n /** Pool address */\n poolAddress: Address\n /** Account to sync */\n account: Address\n /** Storage adapter for persistence */\n storage: StorageAdapter\n /** Starting block for sync (defaults to pool deployment block) */\n fromBlock?: bigint\n /** Ending block for sync (defaults to latest) */\n toBlock?: bigint\n /** Max block range per eth_getLogs call (default: 10000n) */\n maxLogsPerQuery?: bigint\n /** Max sync duration in ms (default: 300000n = 5 min) */\n syncTimeout?: bigint\n /** Optional callback for sync progress */\n onUpdate?: (event: SyncProgressEvent) => void\n /** If provider is behind this block, throw ProviderLagError */\n minBlockNumber?: bigint\n /** Manual snapshot tx hash for recovery when automatic fails */\n snapshotTxHash?: Hash\n}\n\n/**\n * Sync progress event for callbacks.\n */\nexport interface SyncProgressEvent {\n /** Event type */\n type: 'position-opened' | 'position-closed' | 'progress' | 'reorg-detected'\n /** TokenId for position events */\n tokenId?: bigint\n /** Current block being processed */\n blockNumber: bigint\n /** Progress info */\n progress?: {\n /** Current block */\n current: bigint\n /** Total blocks to process */\n total: bigint\n }\n}\n\n/**\n * Result of syncPositions.\n */\nexport interface SyncPositionsResult {\n /** Last synced block number */\n lastSyncedBlock: bigint\n /** Last synced block hash */\n lastSyncedBlockHash: Hash\n /** Number of open positions */\n positionCount: bigint\n /** Position IDs discovered */\n positionIds: bigint[]\n /** Whether this was an incremental sync (vs full) */\n incremental: boolean\n /** Duration in milliseconds */\n durationMs: bigint\n}\n\n/**\n * Synchronize positions for an account.\n *\n * This function:\n * 1. Checks for existing checkpoint\n * 2. If no checkpoint: recovers from dispatch() calldata or falls back to full event scan\n * 3. If checkpoint exists: detects reorgs and syncs incrementally\n * 4. Persists positions and checkpoint to storage\n *\n * @param params - Sync parameters\n * @returns Sync result with position count and sync metadata\n * @throws SyncTimeoutError if sync exceeds timeout\n * @throws ProviderLagError if provider is behind minBlockNumber\n * @throws PositionSnapshotNotFoundError if no positions found and no snapshot available\n */\nexport async function syncPositions(params: SyncPositionsParams): Promise<SyncPositionsResult> {\n const {\n client,\n chainId,\n poolAddress,\n account,\n storage,\n syncTimeout = 300000n, // 5 minutes\n onUpdate,\n minBlockNumber,\n snapshotTxHash,\n } = params\n\n const startTime = Date.now()\n\n const checkTimeout = () => {\n const elapsed = BigInt(Date.now() - startTime)\n if (elapsed > syncTimeout) {\n throw new SyncTimeoutError(elapsed, toBlock, 0n)\n }\n }\n\n // Get latest block\n const latestBlock = await client.getBlockNumber()\n const toBlock = params.toBlock ?? latestBlock\n\n // Check for provider lag\n if (minBlockNumber !== undefined && latestBlock < minBlockNumber) {\n throw new ProviderLagError(minBlockNumber, latestBlock)\n }\n\n // Reorg detection using existing checkpoint\n const checkpoint = await loadCheckpoint(storage, chainId, poolAddress, account)\n if (checkpoint) {\n const reorgResult = await detectReorg({\n client,\n chainId,\n poolAddress,\n account,\n storage,\n })\n\n if (reorgResult.detected) {\n onUpdate?.({\n type: 'reorg-detected',\n blockNumber: reorgResult.reorgBlock ?? 0n,\n })\n }\n }\n\n checkTimeout()\n\n // Get authoritative position IDs from latest dispatch calldata.\n // When resuming from a checkpoint, narrow the event scan window to avoid\n // re-scanning the entire chain history on every incremental sync.\n // Returns null when no dispatch event was found in the scanned range,\n // or [] when a dispatch was found with an empty position list.\n const snapshotResult = await getOpenPositionIds({\n client,\n chainId,\n poolAddress,\n account,\n storage,\n lastDispatchTxHash: snapshotTxHash,\n fromBlock: checkpoint?.lastBlock ?? params.fromBlock,\n })\n\n // If no dispatch events were found in the scanned range (null) but the\n // checkpoint had positions, the user simply hasn't traded since the last\n // sync — keep the cached list. An explicit empty array means a dispatch\n // was found that authoritatively shows zero open positions.\n let positionIds: bigint[]\n if (snapshotResult === null && checkpoint && checkpoint.positionIds.length > 0) {\n positionIds = checkpoint.positionIds\n } else {\n positionIds = snapshotResult ?? []\n }\n\n // If no positions and no history, save empty checkpoint and return early\n if (positionIds.length === 0) {\n const hasAnyEvents = await accountHasPositionEvents({\n client,\n poolAddress,\n account,\n fromBlock: params.fromBlock,\n toBlock,\n })\n\n if (!hasAnyEvents) {\n const finalBlock = await client.getBlock({ blockNumber: toBlock })\n\n const poolMetaKey = getPoolMetaKey(chainId, poolAddress)\n const existingPoolMeta = await storage.get(poolMetaKey)\n if (!existingPoolMeta) {\n await fetchAndStorePoolMeta(client, poolAddress, poolMetaKey, storage)\n }\n\n await saveCheckpoint({\n storage,\n chainId,\n poolAddress,\n account,\n lastBlock: toBlock,\n lastBlockHash: finalBlock.hash,\n positionIds: [],\n })\n\n const positionsKey = getPositionsKey(chainId, poolAddress, account)\n await storage.set(positionsKey, jsonSerializer.stringify([]))\n\n return {\n lastSyncedBlock: toBlock,\n lastSyncedBlockHash: finalBlock.hash,\n positionCount: 0n,\n positionIds: [],\n incremental: false,\n durationMs: BigInt(Date.now() - startTime),\n }\n }\n }\n\n checkTimeout()\n\n // Get final block info\n const finalBlock = await client.getBlock({ blockNumber: toBlock })\n\n // Fetch and store pool metadata if not already stored\n const poolMetaKey = getPoolMetaKey(chainId, poolAddress)\n const existingPoolMeta = await storage.get(poolMetaKey)\n if (!existingPoolMeta) {\n await fetchAndStorePoolMeta(client, poolAddress, poolMetaKey, storage)\n }\n\n // Fetch and store position data for all positions\n if (positionIds.length > 0) {\n const { positions } = await getPositions({\n client,\n poolAddress,\n owner: account,\n tokenIds: positionIds,\n blockNumber: toBlock,\n })\n\n for (const pos of positions) {\n const positionMetaKey = getPositionMetaKey(chainId, poolAddress, pos.tokenId)\n const storedData: StoredPositionData = {\n tokenId: pos.tokenId,\n positionSize: pos.positionSize,\n legs: pos.legs,\n tickAtMint: pos.tickAtMint,\n poolUtilization0AtMint: pos.poolUtilization0AtMint,\n poolUtilization1AtMint: pos.poolUtilization1AtMint,\n timestampAtMint: pos.timestampAtMint,\n blockNumberAtMint: pos.blockNumberAtMint,\n swapAtMint: pos.swapAtMint,\n }\n await storage.set(positionMetaKey, jsonSerializer.stringify(storedData))\n }\n }\n\n // Save checkpoint\n await saveCheckpoint({\n storage,\n chainId,\n poolAddress,\n account,\n lastBlock: toBlock,\n lastBlockHash: finalBlock.hash,\n positionIds,\n })\n\n // Save positions to storage\n const positionsKey = getPositionsKey(chainId, poolAddress, account)\n await storage.set(positionsKey, jsonSerializer.stringify(positionIds))\n\n return {\n lastSyncedBlock: toBlock,\n lastSyncedBlockHash: finalBlock.hash,\n positionCount: BigInt(positionIds.length),\n positionIds,\n incremental: !!checkpoint,\n durationMs: BigInt(Date.now() - startTime),\n }\n}\n\n/**\n * Quick check if an account has ANY position events.\n * Checks OptionMinted, OptionBurnt, ForcedExercised (user), and AccountLiquidated (liquidatee).\n * All checked fields are indexed so this is fast.\n *\n * **Warning:** RPC index lag can cause false negatives for recently minted positions.\n * If the RPC node's event index is behind the chain tip, this function may return\n * `false` even though the account has just minted a position. Callers should either\n * wait a few blocks after minting before calling syncPositions, or skip this\n * optimization (by providing a `snapshotTxHash`) when freshness is critical.\n *\n * @param params - Check parameters\n * @returns true if account has any position events, false otherwise\n */\nasync function accountHasPositionEvents(params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n fromBlock?: bigint\n toBlock: bigint\n}): Promise<boolean> {\n const { client, poolAddress, account, fromBlock = 0n, toBlock } = params\n\n const [mintEvents, burnEvents, forceExerciseEvents, liquidationEvents] = await Promise.all([\n withRetry(() =>\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,\n toBlock,\n }),\n ),\n withRetry(() =>\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,\n toBlock,\n }),\n ),\n withRetry(() =>\n client.getLogs({\n address: poolAddress,\n event: {\n type: 'event',\n name: 'ForcedExercised',\n inputs: [\n { type: 'address', name: 'exercisor', indexed: true },\n { type: 'address', name: 'user', indexed: true },\n { type: 'uint256', name: 'tokenId', indexed: true },\n { type: 'int256', name: 'exerciseFee', indexed: false },\n ],\n },\n args: {\n user: account,\n },\n fromBlock,\n toBlock,\n }),\n ),\n withRetry(() =>\n client.getLogs({\n address: poolAddress,\n event: {\n type: 'event',\n name: 'AccountLiquidated',\n inputs: [\n { type: 'address', name: 'liquidator', indexed: true },\n { type: 'address', name: 'liquidatee', indexed: true },\n { type: 'int256', name: 'bonusAmounts', indexed: false },\n ],\n },\n args: {\n liquidatee: account,\n },\n fromBlock,\n toBlock,\n }),\n ),\n ])\n\n return (\n mintEvents.length > 0 ||\n burnEvents.length > 0 ||\n forceExerciseEvents.length > 0 ||\n liquidationEvents.length > 0\n )\n}\n\n/**\n * Fetch full pool metadata and store it.\n * Uses getPoolMetadata to fetch all immutable pool data in minimal RPC calls.\n */\nasync function fetchAndStorePoolMeta(\n client: PublicClient,\n poolAddress: Address,\n poolMetaKey: string,\n storage: StorageAdapter,\n): Promise<void> {\n const metadata = await getPoolMetadata({ client, poolAddress })\n\n const poolMeta: StoredPoolMeta = {\n tickSpacing: metadata.tickSpacing,\n fee: metadata.fee,\n poolId: metadata.poolId,\n collateralToken0Address: metadata.collateralToken0Address,\n collateralToken1Address: metadata.collateralToken1Address,\n riskEngineAddress: metadata.riskEngineAddress,\n token0Asset: metadata.token0Asset,\n token1Asset: metadata.token1Asset,\n token0Symbol: metadata.token0Symbol,\n token1Symbol: metadata.token1Symbol,\n token0Decimals: metadata.token0Decimals,\n token1Decimals: metadata.token1Decimals,\n }\n\n await storage.set(poolMetaKey, jsonSerializer.stringify(poolMeta))\n}\n\n/**\n * Retry helper with exponential backoff for transient RPC errors.\n *\n * @param fn - Async function to retry\n * @param maxRetries - Maximum number of retries (default: 3)\n * @returns The result of the function\n */\nasync function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {\n let lastError: unknown\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn()\n } catch (error) {\n lastError = error\n if (attempt < maxRetries && isRetryableRpcError(error)) {\n // Exponential backoff: 1s, 2s, 4s\n await new Promise((resolve) => setTimeout(resolve, 1000 * 2 ** attempt))\n continue\n }\n throw error\n }\n }\n throw lastError\n}\n","/**\n * Force exercise functions for the Panoptic v2 SDK.\n * @module v2/writes/forceExercise\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport type { StorageAdapter } from '../storage'\nimport { syncPositions } from '../sync/syncPositions'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for force exercising a position.\n */\nexport interface ForceExerciseParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Exercisor account address */\n account: Address\n /** PanopticPool address */\n poolAddress: 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 /** Packed value for using premia as collateral */\n usePremiaAsCollateral?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n /** Storage adapter for auto-syncing positions after confirmation */\n storage?: StorageAdapter\n /** Chain ID (required when storage is provided) */\n chainId?: bigint\n}\n\n/**\n * Force exercise an ITM (in-the-money) long position.\n *\n * The exercisor calls dispatchFrom to exercise another user's ITM long positions,\n * paying the exercise fee.\n *\n * @param params - Force exercise parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await forceExercise({\n * client,\n * walletClient,\n * account: exercisorAddress,\n * poolAddress,\n * user: targetAccount,\n * positionIdListFrom: exercisorPositions,\n * positionIdListTo: targetPositions,\n * positionIdListToFinal: [], // Exercise all ITM positions\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function forceExercise(params: ForceExerciseParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n user,\n positionIdListFrom,\n positionIdListTo,\n positionIdListToFinal,\n usePremiaAsCollateral = 0n,\n txOverrides,\n } = params\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatchFrom',\n args: [\n positionIdListFrom,\n user,\n positionIdListTo,\n positionIdListToFinal,\n usePremiaAsCollateral,\n ],\n txOverrides,\n })\n}\n\n/**\n * Force exercise and wait for confirmation.\n *\n * When `storage` and `chainId` are provided, automatically syncs the\n * exercisor's positions after the transaction confirms.\n */\nexport async function forceExerciseAndWait(params: ForceExerciseParams): Promise<TxReceipt> {\n const result = await forceExercise(params)\n const receipt = await result.wait()\n\n const { storage, chainId, client, poolAddress, account } = params\n if (storage && chainId !== undefined) {\n await syncPositions({\n client,\n chainId,\n poolAddress,\n account,\n storage,\n })\n }\n\n return receipt\n}\n","/**\n * Premium settlement functions for the Panoptic v2 SDK.\n * @module v2/writes/settle\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport type { TickAndSpreadLimits } from './position'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for settling accumulated premia.\n */\nexport interface SettleParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Current position ID list */\n positionIdList: bigint[]\n /** Whether to use premia as collateral */\n usePremiaAsCollateral?: boolean\n /** Builder code */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Settle accumulated premia on existing positions.\n *\n * This function triggers premium collection without changing position size.\n * It calls dispatch with unchanged position lists.\n *\n * @param params - Settlement parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await settleAccumulatedPremia({\n * client,\n * walletClient,\n * account,\n * poolAddress,\n * positionIdList: existingPositions,\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function settleAccumulatedPremia(params: SettleParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n positionIdList,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n txOverrides,\n } = params\n\n // For settlement, we call dispatch with:\n // - Same position lists (no change)\n // - Zero position sizes (no size change, just settle)\n // - Wide tick limits\n const positionSizes: bigint[] = positionIdList.map(() => 0n)\n const tickAndSpreadLimits: TickAndSpreadLimits[] = positionIdList.map(\n () => [-887272n, 887272n, 0n] as const,\n )\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n positionIdList, // Same list - no change\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 usePremiaAsCollateral,\n builderCode,\n ],\n txOverrides,\n })\n}\n\n/**\n * Settle premia and wait for confirmation.\n */\nexport async function settleAccumulatedPremiaAndWait(params: SettleParams): Promise<TxReceipt> {\n const result = await settleAccumulatedPremia(params)\n return result.wait()\n}\n","/**\n * Oracle poke function for the Panoptic v2 SDK.\n * @module v2/writes/pokeOracle\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { OracleRateLimitedError } from '../errors'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for poking the oracle.\n */\nexport interface PokeOracleParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Whether to check rate limit before calling (optional) */\n checkRateLimit?: boolean\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Poke the oracle to update its state.\n *\n * This function can be called to advance the oracle epoch.\n * Note: The oracle can only be poked once per epoch (64 seconds).\n *\n * @param params - Poke oracle parameters\n * @returns TxResult\n * @throws OracleRateLimitedError if checkRateLimit is true and oracle was recently poked\n *\n * @example\n * ```typescript\n * const result = await pokeOracle({\n * client,\n * walletClient,\n * account,\n * poolAddress,\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function pokeOracle(params: PokeOracleParams): Promise<TxResult> {\n const { client, walletClient, account, poolAddress, checkRateLimit = false, txOverrides } = params\n\n if (checkRateLimit) {\n // Check current oracle state to see if we can poke\n // Fetch oracle data and block in parallel\n const [oracleData, block] = await Promise.all([\n client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getOracleTicks',\n }),\n client.getBlock(),\n ])\n\n // oracleData[4] is the oraclePack\n const oraclePack = oracleData[4]\n // Epoch is in bits 232-255 (24 bits)\n const epoch = oraclePack >> 232n\n\n const currentEpoch = block.timestamp / 64n\n\n // If current epoch equals oracle epoch, we can't poke yet\n if (currentEpoch <= epoch) {\n const lastUpdate = epoch * 64n\n throw new OracleRateLimitedError(lastUpdate, block.timestamp)\n }\n }\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'pokeOracle',\n args: [],\n txOverrides,\n })\n}\n\n/**\n * Poke oracle and wait for confirmation.\n */\nexport async function pokeOracleAndWait(params: PokeOracleParams): Promise<TxReceipt> {\n const result = await pokeOracle(params)\n return result.wait()\n}\n","/**\n * Factory write functions for the Panoptic v2 SDK.\n * @module v2/writes/factory\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticFactoryV3Abi, panopticFactoryV4Abi } from '../../../generated'\nimport type { PoolKey, TxOverrides, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\ninterface DeployNewPoolCommon {\n /** Public client */\n client: PublicClient\n /** Wallet client for signing */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticFactory address */\n factoryAddress: Address\n /** Risk engine address */\n riskEngine: Address\n /** Salt (uint96) */\n salt: bigint\n /** Optional transaction overrides */\n txOverrides?: TxOverrides\n}\n\nexport interface DeployNewPoolV3Params extends DeployNewPoolCommon {\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 DeployNewPoolV4Params extends DeployNewPoolCommon {\n /** V4 pool key */\n poolKey: PoolKey\n}\n\nexport type DeployNewPoolParams =\n | ({ version: 'v3' } & DeployNewPoolV3Params)\n | ({ version: 'v4' } & DeployNewPoolV4Params)\n\n/**\n * Deploy a new Panoptic pool via the factory.\n *\n * @param params - Deployment parameters (versioned: 'v3' or 'v4')\n * @returns Transaction result with hash and wait function\n */\nexport async function deployNewPool(params: DeployNewPoolParams): Promise<TxResult> {\n const { client, walletClient, account, factoryAddress, riskEngine, salt, txOverrides } = params\n\n if (params.version === 'v3') {\n return submitWrite({\n client,\n walletClient,\n account,\n address: factoryAddress,\n abi: panopticFactoryV3Abi,\n functionName: 'deployNewPool',\n args: [params.token0, params.token1, params.fee, riskEngine, salt],\n txOverrides,\n })\n }\n\n return submitWrite({\n client,\n walletClient,\n account,\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 txOverrides,\n })\n}\n\n/**\n * Deploy a new Panoptic pool and wait for confirmation.\n */\nexport async function deployNewPoolAndWait(params: DeployNewPoolParams) {\n const result = await deployNewPool(params)\n return result.wait()\n}\n","/**\n * Transaction replacement utilities for the Panoptic v2 SDK.\n * Provides speedUp and cancel functionality for pending transactions.\n * @module v2/writes/txManagement\n */\n\nimport type { Address, Hash, PublicClient, WalletClient } from 'viem'\n\nimport type { TxBroadcaster, TxResult } from '../types'\nimport { createTxResult } from './utils'\n\n/** Default gas price multiplier for replacement (12.5% bump = minimum for replacement) */\nconst DEFAULT_GAS_PRICE_MULTIPLIER = 1.125\n\n/**\n * Parameters for speeding up a pending transaction.\n */\nexport interface SpeedUpParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Hash of the pending transaction to speed up */\n hash: Hash\n /** Explicit max fee per gas (overrides multiplier) */\n maxFeePerGas?: bigint\n /** Explicit max priority fee per gas (overrides multiplier) */\n maxPriorityFeePerGas?: bigint\n /** Multiplier for gas price bump (default 1.125 = 12.5%, minimum to replace) */\n gasPriceMultiplier?: number\n /** Custom broadcaster for MEV protection */\n broadcaster?: TxBroadcaster\n}\n\n/**\n * Parameters for cancelling a pending transaction.\n */\nexport interface CancelParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address (for self-transfer) */\n account: Address\n /** Hash of the pending transaction to cancel */\n hash: Hash\n /** Explicit max fee per gas (overrides multiplier) */\n maxFeePerGas?: bigint\n /** Explicit max priority fee per gas (overrides multiplier) */\n maxPriorityFeePerGas?: bigint\n /** Multiplier for gas price bump (default 1.125 = 12.5%, minimum to replace) */\n gasPriceMultiplier?: number\n /** Custom broadcaster for MEV protection */\n broadcaster?: TxBroadcaster\n}\n\n/**\n * Apply a multiplier to a bigint gas value.\n * Uses integer arithmetic to avoid floating point issues.\n */\nfunction applyMultiplier(value: bigint, multiplier: number): bigint {\n // Convert multiplier to basis points (e.g., 1.125 => 11250)\n const bps = BigInt(Math.ceil(multiplier * 10000))\n return (value * bps) / 10000n\n}\n\n/**\n * Compute bumped gas parameters from the original transaction.\n */\nfunction computeBumpedGas(\n originalMaxFeePerGas: bigint | undefined,\n originalMaxPriorityFeePerGas: bigint | undefined,\n explicitMaxFeePerGas: bigint | undefined,\n explicitMaxPriorityFeePerGas: bigint | undefined,\n multiplier: number,\n): { maxFeePerGas: bigint; maxPriorityFeePerGas: bigint } {\n const maxFeePerGas =\n explicitMaxFeePerGas ?? applyMultiplier(originalMaxFeePerGas ?? 0n, multiplier)\n\n const maxPriorityFeePerGas =\n explicitMaxPriorityFeePerGas ?? applyMultiplier(originalMaxPriorityFeePerGas ?? 0n, multiplier)\n\n return { maxFeePerGas, maxPriorityFeePerGas }\n}\n\n/**\n * Speed up a pending transaction by resubmitting with higher gas.\n *\n * Fetches the original transaction, extracts its parameters,\n * bumps the gas price, and resubmits with the same nonce.\n *\n * @param params - Speed up parameters\n * @returns TxResult for the replacement transaction\n * @throws Error if the original transaction is not found\n *\n * @example\n * ```typescript\n * // Speed up with default 12.5% bump\n * const result = await speedUpTransaction({\n * client,\n * walletClient,\n * hash: pendingTxHash,\n * })\n *\n * // Speed up with explicit gas prices\n * const result = await speedUpTransaction({\n * client,\n * walletClient,\n * hash: pendingTxHash,\n * maxFeePerGas: 50_000_000_000n, // 50 gwei\n * maxPriorityFeePerGas: 3_000_000_000n, // 3 gwei\n * })\n * ```\n */\nexport async function speedUpTransaction(params: SpeedUpParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n hash,\n maxFeePerGas: explicitMaxFee,\n maxPriorityFeePerGas: explicitMaxPriority,\n gasPriceMultiplier = DEFAULT_GAS_PRICE_MULTIPLIER,\n broadcaster,\n } = params\n\n const tx = await client.getTransaction({ hash })\n\n const { maxFeePerGas, maxPriorityFeePerGas } = computeBumpedGas(\n tx.maxFeePerGas ?? undefined,\n tx.maxPriorityFeePerGas ?? undefined,\n explicitMaxFee,\n explicitMaxPriority,\n gasPriceMultiplier,\n )\n\n if (broadcaster) {\n const request = await walletClient.prepareTransactionRequest({\n account: tx.from,\n to: tx.to ?? undefined,\n data: tx.input,\n value: tx.value,\n nonce: tx.nonce,\n gas: tx.gas,\n maxFeePerGas,\n maxPriorityFeePerGas,\n chain: walletClient.chain,\n })\n\n const signedTx = await walletClient.signTransaction({\n ...request,\n account: tx.from,\n } as unknown as Parameters<WalletClient['signTransaction']>[0])\n const replacementHash = await broadcaster.broadcast(signedTx)\n return createTxResult(client, replacementHash)\n }\n\n const replacementHash = await walletClient.sendTransaction({\n account: tx.from,\n to: tx.to ?? undefined,\n data: tx.input,\n value: tx.value,\n nonce: tx.nonce,\n gas: tx.gas,\n maxFeePerGas,\n maxPriorityFeePerGas,\n chain: walletClient.chain,\n })\n\n return createTxResult(client, replacementHash)\n}\n\n/**\n * Cancel a pending transaction by sending a 0-value self-transfer\n * with the same nonce and higher gas price.\n *\n * @param params - Cancel parameters\n * @returns TxResult for the cancellation transaction\n * @throws Error if the original transaction is not found\n *\n * @example\n * ```typescript\n * const result = await cancelTransaction({\n * client,\n * walletClient,\n * account,\n * hash: pendingTxHash,\n * })\n * await result.wait()\n * ```\n */\nexport async function cancelTransaction(params: CancelParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n hash,\n maxFeePerGas: explicitMaxFee,\n maxPriorityFeePerGas: explicitMaxPriority,\n gasPriceMultiplier = DEFAULT_GAS_PRICE_MULTIPLIER,\n broadcaster,\n } = params\n\n const tx = await client.getTransaction({ hash })\n\n const { maxFeePerGas, maxPriorityFeePerGas } = computeBumpedGas(\n tx.maxFeePerGas ?? undefined,\n tx.maxPriorityFeePerGas ?? undefined,\n explicitMaxFee,\n explicitMaxPriority,\n gasPriceMultiplier,\n )\n\n if (broadcaster) {\n const request = await walletClient.prepareTransactionRequest({\n account,\n to: account,\n value: 0n,\n nonce: tx.nonce,\n gas: 21000n,\n maxFeePerGas,\n maxPriorityFeePerGas,\n chain: walletClient.chain,\n })\n\n const signedTx = await walletClient.signTransaction({\n ...request,\n account,\n } as unknown as Parameters<WalletClient['signTransaction']>[0])\n const cancelHash = await broadcaster.broadcast(signedTx)\n return createTxResult(client, cancelHash)\n }\n\n const cancelHash = await walletClient.sendTransaction({\n account,\n to: account,\n value: 0n,\n nonce: tx.nonce,\n gas: 21000n,\n maxFeePerGas,\n maxPriorityFeePerGas,\n chain: walletClient.chain,\n })\n\n return createTxResult(client, cancelHash)\n}\n","/**\n * Low-level TokenId encoding utilities for the Panoptic v2 SDK.\n * @module v2/tokenId/encoding\n */\n\nimport type { Address, Hex } from 'viem'\n\nimport {\n DEFAULT_VEGOID,\n LEG_BITS,\n LEG_MASKS,\n STRIKE_CONVERSION_FACTOR,\n TOKEN_ID_BITS,\n} from './constants'\n\n/**\n * Leg parameters for encoding.\n */\nexport interface EncodeLegParams {\n /** Leg index (0-3) */\n index: bigint\n /** Asset index (0 or 1) */\n asset: bigint\n /** Option ratio (1-127) */\n optionRatio: bigint\n /** Whether this is a long position (1n = long, 0n = short) */\n isLong: bigint\n /** Token type (0 or 1) */\n tokenType: bigint\n /** Risk partner leg index (0-3) */\n riskPartner: bigint\n /** Strike tick */\n strike: bigint\n /** Width in tick spacing units */\n width: bigint\n}\n\n/**\n * Convert a signed strike tick to unsigned representation for encoding.\n *\n * @param strike - The signed strike tick\n * @returns The unsigned representation\n */\nexport function convertStrikeToUnsigned(strike: bigint): bigint {\n if (strike < 0n) {\n return STRIKE_CONVERSION_FACTOR + strike\n }\n return strike\n}\n\n/**\n * Convert an unsigned encoded strike back to signed representation.\n *\n * @param encodedStrike - The unsigned encoded strike\n * @returns The signed strike tick\n */\nexport function convertStrikeToSigned(encodedStrike: bigint): bigint {\n // If the value is greater than max positive int24, it's negative\n if (encodedStrike > 2n ** 23n - 1n) {\n return encodedStrike - STRIKE_CONVERSION_FACTOR\n }\n return encodedStrike\n}\n\n/**\n * Get the bit offset for a leg at the given index.\n *\n * @param legIndex - The leg index (0-3)\n * @returns The bit offset from the start of the legs section\n */\nexport function getLegOffset(legIndex: bigint): bigint {\n return legIndex * TOKEN_ID_BITS.LEG_SIZE\n}\n\n/**\n * Encode a pool ID from a Uniswap V3 pool address.\n *\n * The encoded PoolId structure: [16-bit tickSpacing][8-bit vegoid][40-bit pool address]\n *\n * @param address - The Uniswap V3 pool address\n * @param tickSpacing - The tick spacing of the pool\n * @param vegoid - The vegoid value (defaults to 4)\n * @returns The encoded pool ID\n */\nexport function encodePoolId(\n address: Address,\n tickSpacing: bigint,\n vegoid: bigint = DEFAULT_VEGOID,\n): bigint {\n // Remove 0x prefix and get first 10 hex chars (5 bytes = 40 bits)\n const addressHex = address.slice(2, 12).toLowerCase()\n\n // Convert to bytes array (big-endian), then reverse to little-endian\n const bytes: number[] = []\n for (let i = 0; i < 10; i += 2) {\n bytes.push(parseInt(addressHex.slice(i, i + 2), 16))\n }\n bytes.reverse()\n\n // Build poolId: pool address (5 bytes) + vegoid (1 byte) + tickSpacing (2 bytes)\n let poolId = 0n\n for (let i = 0; i < bytes.length; i++) {\n poolId |= BigInt(bytes[i]) << BigInt(i * 8)\n }\n\n // Add vegoid at bit 40\n poolId |= (vegoid & 0xffn) << TOKEN_ID_BITS.VEGOID_STARTING_BIT\n\n // Add tickSpacing at bit 48\n poolId |= (tickSpacing & 0xffffn) << TOKEN_ID_BITS.TICK_SPACING_STARTING_BIT\n\n return poolId\n}\n\n/**\n * Encode a pool ID from a Uniswap V4 pool ID (bytes32).\n *\n * @param poolIdHex - The V4 pool ID (bytes32 hex string)\n * @param tickSpacing - The tick spacing of the pool\n * @param vegoid - The vegoid value (defaults to 4)\n * @returns The encoded pool ID\n */\nexport function encodeV4PoolId(\n poolIdHex: Hex,\n tickSpacing: bigint,\n vegoid: bigint = DEFAULT_VEGOID,\n): bigint {\n // Remove 0x prefix and get last 10 hex chars (5 bytes = 40 bits)\n const hex = poolIdHex.slice(2)\n const last5BytesHex = hex.slice(-10).toLowerCase()\n\n // Convert to bytes array (big-endian), then reverse to little-endian\n const bytes: number[] = []\n for (let i = 0; i < 10; i += 2) {\n bytes.push(parseInt(last5BytesHex.slice(i, i + 2), 16))\n }\n bytes.reverse()\n\n // Build encoded poolId\n let encodedPoolId = 0n\n for (let i = 0; i < bytes.length; i++) {\n encodedPoolId |= BigInt(bytes[i]) << BigInt(i * 8)\n }\n\n // Add vegoid at bit 40\n encodedPoolId |= (vegoid & 0xffn) << TOKEN_ID_BITS.VEGOID_STARTING_BIT\n\n // Add tickSpacing at bit 48\n encodedPoolId |= (tickSpacing & 0xffffn) << TOKEN_ID_BITS.TICK_SPACING_STARTING_BIT\n\n return encodedPoolId\n}\n\n/**\n * Decode the vegoid from a TokenId.\n *\n * @param tokenId - The TokenId to decode\n * @returns The vegoid value\n */\nexport function decodeVegoid(tokenId: bigint): bigint {\n const poolId = tokenId & ((1n << TOKEN_ID_BITS.POOL_ID_SIZE) - 1n)\n return (poolId >> TOKEN_ID_BITS.VEGOID_STARTING_BIT) & ((1n << TOKEN_ID_BITS.VEGOID_SIZE) - 1n)\n}\n\n/**\n * Decode the tick spacing from a TokenId.\n *\n * @param tokenId - The TokenId to decode\n * @returns The tick spacing\n */\nexport function decodeTickSpacing(tokenId: bigint): bigint {\n const poolId = tokenId & ((1n << TOKEN_ID_BITS.POOL_ID_SIZE) - 1n)\n return poolId >> TOKEN_ID_BITS.TICK_SPACING_STARTING_BIT\n}\n\n/**\n * Decode the pool ID portion from a TokenId.\n *\n * @param tokenId - The TokenId to decode\n * @returns The pool ID as a hex string\n */\nexport function decodePoolId(tokenId: bigint): Hex {\n const poolId = tokenId & ((1n << TOKEN_ID_BITS.POOL_ID_SIZE) - 1n)\n let hex = poolId.toString(16)\n // Pad to 16 characters (64 bits)\n while (hex.length < 16) {\n hex = '0' + hex\n }\n return `0x${hex}` as Hex\n}\n\n/**\n * Encode a single leg field.\n *\n * @param value - The value to encode\n * @param bitPosition - The bit position within the leg\n * @param legIndex - The leg index\n * @returns The encoded value shifted to the correct position\n */\nfunction encodeLegField(value: bigint, bitPosition: bigint, legIndex: bigint): bigint {\n return value << (getLegOffset(legIndex) + bitPosition + TOKEN_ID_BITS.POOL_ID_SIZE)\n}\n\n/**\n * Encode a single leg into a TokenId.\n *\n * @param leg - The leg parameters\n * @returns The encoded leg value (to be ORed with existing TokenId)\n */\nexport function encodeLeg(leg: EncodeLegParams): bigint {\n const { index, asset, optionRatio, isLong, tokenType, riskPartner, strike, width } = leg\n\n return (\n encodeLegField(asset & LEG_MASKS.ASSET, LEG_BITS.ASSET_BIT, index) |\n encodeLegField(optionRatio & LEG_MASKS.RATIO, LEG_BITS.RATIO_BIT, index) |\n encodeLegField(isLong & LEG_MASKS.IS_LONG, LEG_BITS.IS_LONG_BIT, index) |\n encodeLegField(tokenType & LEG_MASKS.TOKEN_TYPE, LEG_BITS.TOKEN_TYPE_BIT, index) |\n encodeLegField(riskPartner & LEG_MASKS.RISK_PARTNER, LEG_BITS.RISK_PARTNER_BIT, index) |\n encodeLegField(convertStrikeToUnsigned(strike) & LEG_MASKS.STRIKE, LEG_BITS.STRIKE_BIT, index) |\n encodeLegField(width & LEG_MASKS.WIDTH, LEG_BITS.WIDTH_BIT, index)\n )\n}\n\n/**\n * Add a leg to an existing TokenId.\n *\n * @param tokenId - The existing TokenId (can be just poolId or partial TokenId)\n * @param leg - The leg parameters to add\n * @returns The TokenId with the leg added\n */\nexport function addLegToTokenId(tokenId: bigint, leg: EncodeLegParams): bigint {\n return tokenId | encodeLeg(leg)\n}\n\n/**\n * Decoded leg data.\n */\nexport interface DecodedLeg {\n /** Leg index (0-3) */\n index: bigint\n /** Asset index (0 or 1) */\n asset: bigint\n /** Option ratio (1-127) */\n optionRatio: bigint\n /** Whether this is a long position */\n isLong: boolean\n /** Token type (0 or 1) */\n tokenType: bigint\n /** Risk partner leg index */\n riskPartner: bigint\n /** Strike tick (signed) */\n strike: bigint\n /** Width in tick spacing units */\n width: bigint\n}\n\n/**\n * Decode a single leg from a TokenId.\n *\n * @param tokenId - The TokenId to decode\n * @param legIndex - The leg index (0-3)\n * @returns The decoded leg data\n */\nexport function decodeLeg(tokenId: bigint, legIndex: bigint): DecodedLeg {\n const offset = getLegOffset(legIndex) + TOKEN_ID_BITS.POOL_ID_SIZE\n const leg = (tokenId >> offset) & LEG_MASKS.LEG\n\n const asset = leg & LEG_MASKS.ASSET\n const optionRatio = (leg >> LEG_BITS.RATIO_BIT) & LEG_MASKS.RATIO\n const isLong = ((leg >> LEG_BITS.IS_LONG_BIT) & LEG_MASKS.IS_LONG) === 1n\n const tokenType = (leg >> LEG_BITS.TOKEN_TYPE_BIT) & LEG_MASKS.TOKEN_TYPE\n const riskPartner = (leg >> LEG_BITS.RISK_PARTNER_BIT) & LEG_MASKS.RISK_PARTNER\n const encodedStrike = (leg >> LEG_BITS.STRIKE_BIT) & LEG_MASKS.STRIKE\n const strike = convertStrikeToSigned(encodedStrike)\n const width = (leg >> LEG_BITS.WIDTH_BIT) & LEG_MASKS.WIDTH\n\n return {\n index: legIndex,\n asset,\n optionRatio,\n isLong,\n tokenType,\n riskPartner,\n strike,\n width,\n }\n}\n\n/**\n * Count the number of active legs in a TokenId.\n * A leg is active if its optionRatio > 0.\n *\n * @param tokenId - The TokenId to check\n * @returns The number of active legs\n */\nexport function countLegs(tokenId: bigint): bigint {\n let count = 0n\n for (let i = 0n; i < TOKEN_ID_BITS.MAX_LEGS; i++) {\n const leg = decodeLeg(tokenId, i)\n if (leg.optionRatio > 0n) {\n count++\n }\n }\n return count\n}\n\n/**\n * Decode all active legs from a TokenId.\n *\n * @param tokenId - The TokenId to decode\n * @returns Array of decoded legs (only active legs with optionRatio > 0)\n */\nexport function decodeAllLegs(tokenId: bigint): DecodedLeg[] {\n const legs: DecodedLeg[] = []\n for (let i = 0n; i < TOKEN_ID_BITS.MAX_LEGS; i++) {\n const leg = decodeLeg(tokenId, i)\n if (leg.optionRatio > 0n) {\n legs.push(leg)\n }\n }\n return legs\n}\n","/**\n * TokenId builder for the Panoptic v2 SDK.\n * @module v2/tokenId/builder\n */\n\nimport { InvalidTokenIdParameterError } from '../errors'\nimport { LEG_LIMITS, TOKEN_ID_BITS } from './constants'\nimport { type EncodeLegParams, addLegToTokenId } from './encoding'\n\n/**\n * Leg configuration for the builder.\n */\nexport interface LegConfig {\n /** Asset index (0 or 1) */\n asset: bigint\n /** Option ratio (1-127) */\n optionRatio: bigint\n /** Whether this is a long position */\n isLong: boolean\n /** Token type (0 or 1) */\n tokenType: bigint\n /** Risk partner leg index (defaults to self) */\n riskPartner?: bigint\n /** Strike tick (center of the range) */\n strike: bigint\n /** Width in tick spacing units (0 for loans/credits) */\n width: bigint\n}\n\n/**\n * Loan/credit leg configuration.\n * Uses width=0 encoding to signal the loan/credit branch.\n */\nexport interface LoanCreditConfig {\n /** Asset index (0 or 1) */\n asset: bigint\n /** Token type (0 or 1) - which token to borrow/lend */\n tokenType: bigint\n /** Strike tick (price point for the loan/credit) */\n strike: bigint\n /** Option ratio (1-127, defaults to 1) */\n optionRatio?: bigint\n /** Risk partner leg index (defaults to self) */\n riskPartner?: bigint\n}\n\n/**\n * TokenId builder interface.\n * Provides a fluent API for constructing TokenIds.\n */\nexport interface TokenIdBuilder {\n /**\n * Add a leg to the TokenId.\n * @param config - The leg configuration\n * @returns The builder for chaining\n * @throws InvalidTokenIdParameterError if leg parameters are invalid\n */\n addLeg: (config: LegConfig) => TokenIdBuilder\n\n /**\n * Add a call leg. A call is when tokenType === asset.\n * @param config - Partial leg config (tokenType set automatically based on asset, asset defaults to 0)\n * @returns The builder for chaining\n */\n addCall: (config: Omit<LegConfig, 'tokenType' | 'asset'> & { asset?: bigint }) => TokenIdBuilder\n\n /**\n * Add a put leg. A put is when tokenType !== asset.\n * @param config - Partial leg config (tokenType set automatically based on asset, asset defaults to 0)\n * @returns The builder for chaining\n */\n addPut: (config: Omit<LegConfig, 'tokenType' | 'asset'> & { asset?: bigint }) => TokenIdBuilder\n\n /**\n * Add a loan leg (borrow liquidity). Uses width=0 with isLong=false.\n *\n * A loan borrows liquidity from the pool at a specific strike price.\n * The borrower receives the token and owes interest (streaming premium).\n *\n * @param config - Loan configuration (tokenType, strike, optionRatio)\n * @returns The builder for chaining\n */\n addLoan: (config: LoanCreditConfig) => TokenIdBuilder\n\n /**\n * Add a credit leg (lend liquidity). Uses width=0 with isLong=true.\n *\n * A credit lends liquidity to the pool at a specific strike price.\n * The lender deposits the token and earns interest (streaming premium).\n *\n * @param config - Credit configuration (tokenType, strike, optionRatio)\n * @returns The builder for chaining\n */\n addCredit: (config: LoanCreditConfig) => TokenIdBuilder\n\n /**\n * Build the final TokenId.\n * @returns The constructed TokenId\n * @throws InvalidTokenIdParameterError if the TokenId has no legs\n */\n build: () => bigint\n\n /**\n * Get the current number of legs.\n * @returns The leg count\n */\n legCount: () => bigint\n\n /**\n * Reset the builder to start fresh with just the pool ID.\n * @returns The builder for chaining\n */\n reset: () => TokenIdBuilder\n}\n\n/**\n * Create a TokenId builder from an encoded pool ID.\n *\n * Use the 64-bit poolId from `getPool().poolId` or `fetchPoolId()`.\n * For offline encoding, use `encodePoolId()` or `encodeV4PoolId()` first.\n *\n * @param poolId - The encoded 64-bit pool ID\n * @returns A TokenId builder instance\n *\n * @example\n * ```typescript\n * const pool = await getPool({ client, poolAddress, chainId })\n * const tokenId = createTokenIdBuilder(pool.poolId)\n * .addCall({ strike: 100n, width: 10n, optionRatio: 1n, isLong: false })\n * .addPut({ strike: -100n, width: 10n, optionRatio: 1n, isLong: false })\n * .build()\n * ```\n */\nexport function createTokenIdBuilder(poolId: bigint): TokenIdBuilder {\n let tokenId = poolId\n let currentLegIndex = 0n\n\n const validateLegConfig = (config: LegConfig, legIndex: bigint): void => {\n if (legIndex >= TOKEN_ID_BITS.MAX_LEGS) {\n throw new InvalidTokenIdParameterError(0n) // Too many legs\n }\n\n if (config.optionRatio < 1n || config.optionRatio > LEG_LIMITS.MAX_RATIO) {\n throw new InvalidTokenIdParameterError(1n) // Invalid option ratio\n }\n\n // width == 0 is valid for loans/credits, otherwise must be 1-4095\n if (config.width < 0n || config.width > LEG_LIMITS.MAX_WIDTH) {\n throw new InvalidTokenIdParameterError(2n) // Invalid width\n }\n\n if (config.strike < LEG_LIMITS.MIN_STRIKE || config.strike > LEG_LIMITS.MAX_STRIKE) {\n throw new InvalidTokenIdParameterError(3n) // Invalid strike\n }\n\n if (config.asset !== 0n && config.asset !== 1n) {\n throw new InvalidTokenIdParameterError(4n) // Invalid asset\n }\n\n if (config.tokenType !== 0n && config.tokenType !== 1n) {\n throw new InvalidTokenIdParameterError(5n) // Invalid tokenType\n }\n\n const riskPartner = config.riskPartner ?? legIndex\n if (riskPartner < 0n || riskPartner > 3n) {\n throw new InvalidTokenIdParameterError(6n) // Invalid risk partner\n }\n }\n\n const builder: TokenIdBuilder = {\n addLeg(config: LegConfig): TokenIdBuilder {\n validateLegConfig(config, currentLegIndex)\n\n const leg: EncodeLegParams = {\n index: currentLegIndex,\n asset: config.asset,\n optionRatio: config.optionRatio,\n isLong: config.isLong ? 1n : 0n,\n tokenType: config.tokenType,\n riskPartner: config.riskPartner ?? currentLegIndex,\n strike: config.strike,\n width: config.width,\n }\n\n tokenId = addLegToTokenId(tokenId, leg)\n currentLegIndex++\n\n return builder\n },\n\n addCall(config: Omit<LegConfig, 'tokenType' | 'asset'> & { asset?: bigint }): TokenIdBuilder {\n const asset = config.asset ?? 0n\n return builder.addLeg({\n ...config,\n tokenType: asset, // Call: tokenType === asset\n asset,\n })\n },\n\n addPut(config: Omit<LegConfig, 'tokenType' | 'asset'> & { asset?: bigint }): TokenIdBuilder {\n const asset = config.asset ?? 0n\n return builder.addLeg({\n ...config,\n tokenType: asset === 0n ? 1n : 0n, // Put: tokenType !== asset\n asset,\n })\n },\n\n addLoan(config: LoanCreditConfig): TokenIdBuilder {\n // Loan: width=0, isLong=false (borrowing liquidity)\n // asset is set to same as tokenType for loans\n return builder.addLeg({\n asset: config.asset,\n optionRatio: config.optionRatio ?? 1n,\n isLong: false,\n tokenType: config.tokenType,\n riskPartner: config.riskPartner,\n strike: config.strike,\n width: 0n, // width=0 signals loan/credit branch\n })\n },\n\n addCredit(config: LoanCreditConfig): TokenIdBuilder {\n // Credit: width=0, isLong=true (lending liquidity)\n // asset is set to same as tokenType for credits\n return builder.addLeg({\n asset: config.asset,\n optionRatio: config.optionRatio ?? 1n,\n isLong: true,\n tokenType: config.tokenType,\n riskPartner: config.riskPartner,\n strike: config.strike,\n width: 0n, // width=0 signals loan/credit branch\n })\n },\n\n build(): bigint {\n if (currentLegIndex === 0n) {\n throw new InvalidTokenIdParameterError(7n) // No legs\n }\n return tokenId\n },\n\n legCount(): bigint {\n return currentLegIndex\n },\n\n reset(): TokenIdBuilder {\n tokenId = poolId\n currentLegIndex = 0n\n return builder\n },\n }\n\n return builder\n}\n","/**\n * Shared loan utilities for swap and lending modules.\n * @module v2/writes/loanUtils\n */\n\nimport type { Address } from 'viem'\n\nimport {\n InputListFailError,\n LoanSlotExhaustedError,\n MissingPositionIdsError,\n parsePanopticError,\n SwapTokenMismatchError,\n} from '../errors'\nimport type { StorageAdapter } from '../storage'\nimport { getTrackedPositionIds } from '../sync/getTrackedPositionIds'\nimport { createTokenIdBuilder } from '../tokenId/builder'\n\n/** Maximum retry attempts on InputListFail */\nexport const MAX_RETRIES = 3\n\n/**\n * Resolve token index (0 or 1) for the given token address against the pool.\n * Throws SwapTokenMismatchError if the token isn't in the pool.\n */\nexport function 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 * Resolve existing position IDs from explicit param or storage.\n */\nexport async function resolvePositionIds(\n explicit: bigint[] | undefined,\n storage: StorageAdapter | undefined,\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n): Promise<bigint[]> {\n if (explicit !== undefined) return explicit\n if (storage) {\n return getTrackedPositionIds({ chainId, poolAddress, account, storage })\n }\n throw new MissingPositionIdsError()\n}\n\n/**\n * Check if a caught error is an InputListFail contract revert.\n * Works with both raw viem errors and parsed PanopticError instances.\n */\nexport function isInputListFailError(error: unknown): boolean {\n if (error instanceof InputListFailError) return true\n const parsed = parsePanopticError(error)\n return parsed?.errorName === 'InputListFail'\n}\n\n/**\n * Build a unique loan tokenId that doesn't collide with existing positions.\n * Bumps optionRatio (1-127) and returns adjusted size to maintain equivalent exposure.\n *\n * @param asset - Which token denominates the positionSize (0 or 1).\n */\nexport function buildUniqueLoan(\n poolId: bigint,\n asset: bigint,\n tokenType: bigint,\n currentTick: bigint,\n tickSpacing: bigint,\n existingPositionIds: bigint[],\n positionSize: bigint,\n): { tokenId: bigint; adjustedSize: bigint } {\n // Floor-align to tick spacing (bigint % preserves sign, so handle negatives)\n const mod = currentTick % tickSpacing\n let strike = currentTick - ((mod + tickSpacing) % tickSpacing)\n\n for (let ratio = 1n; ratio <= 127n; ratio++) {\n const tokenId = createTokenIdBuilder(poolId)\n .addLoan({ asset, tokenType, strike, optionRatio: ratio })\n .build()\n\n if (!existingPositionIds.includes(tokenId)) {\n const adjustedSize = positionSize / ratio\n if (adjustedSize === 0n || positionSize % ratio !== 0n) {\n continue\n }\n return { tokenId, adjustedSize }\n }\n }\n\n // Fallback: try different strikes at ratio=1\n const mod2 = currentTick % tickSpacing\n strike = currentTick - ((mod2 + tickSpacing) % tickSpacing) + tickSpacing\n for (let i = 0; i < 100; i++) {\n const tokenId = createTokenIdBuilder(poolId).addLoan({ asset, tokenType, strike }).build()\n\n if (!existingPositionIds.includes(tokenId)) {\n return { tokenId, adjustedSize: positionSize }\n }\n strike += tickSpacing\n }\n\n throw new LoanSlotExhaustedError()\n}\n","/**\n * Swap functions for the Panoptic v2 SDK.\n *\n * Implements token swaps via Panoptic's loan mechanism:\n * open a loan with swapAtMint and immediately close it.\n *\n * @module v2/writes/swap\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { MaxRetriesExceededError } from '../errors'\nimport { tickLimits } from '../formatters/tick'\nimport { getPool } from '../reads/pool'\nimport type { StorageAdapter } from '../storage'\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport {\n buildUniqueLoan,\n isInputListFailError,\n MAX_RETRIES,\n resolvePositionIds,\n resolveTokenIndex,\n} from './loanUtils'\nimport { submitWrite } from './utils'\n\n/**\n * Parameters for swapExactOut.\n */\nexport interface SwapExactOutParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID (required for pool data fetch) */\n chainId: bigint\n /** Token address you want to receive */\n tokenOut: Address\n /** Exact amount of tokenOut to receive */\n amountOut: bigint\n /** Slippage tolerance in bps (e.g. 500n = 5%) */\n slippageBps: bigint\n /** Existing position IDs. If omitted, resolved from storage. */\n existingPositionIds?: bigint[]\n /** Storage adapter for position ID resolution */\n storage?: StorageAdapter\n /** Builder code for referral fee attribution. Defaults to `0n`. */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Parameters for swapExactIn.\n */\nexport interface SwapExactInParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID (required for pool data fetch) */\n chainId: bigint\n /** Token address you want to sell */\n tokenIn: Address\n /** Exact amount of tokenIn to spend */\n amountIn: bigint\n /** Slippage tolerance in bps (e.g. 500n = 5%) */\n slippageBps: bigint\n /** Existing position IDs. If omitted, resolved from storage. */\n existingPositionIds?: bigint[]\n /** Storage adapter for position ID resolution */\n storage?: StorageAdapter\n /** Builder code for referral fee attribution. Defaults to `0n`. */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Swap tokens using Panoptic's exact-output mechanism.\n *\n * Opens a loan with `swapAtMint=true` and immediately burns it with `swapAtMint=false`.\n * The user receives exactly `amountOut` of `tokenOut`.\n *\n * @param params - Swap parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await swapExactOut({\n * client, walletClient, account, poolAddress,\n * chainId: 11155111n,\n * tokenOut: WETH_ADDRESS,\n * amountOut: 5n * 10n**16n, // 0.05 WETH\n * slippageBps: 500n, // 5% slippage\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function swapExactOut(params: SwapExactOutParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n tokenOut,\n amountOut,\n slippageBps,\n existingPositionIds: explicitIds,\n storage,\n builderCode = 0n,\n txOverrides,\n } = params\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n // Re-fetch pool + positions on each attempt for freshness\n const [pool, positionIds] = await Promise.all([\n getPool({ client, poolAddress, chainId }),\n resolvePositionIds(explicitIds, storage, chainId, poolAddress, account),\n ])\n\n const token0 = pool.collateralTracker0.token\n const token1 = pool.collateralTracker1.token\n const tokenOutIndex = resolveTokenIndex(tokenOut, token0, token1)\n\n // For exact output: borrow the OTHER token, swap it to tokenOut\n const tokenType = tokenOutIndex === 0n ? 1n : 0n\n\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n\n // asset = tokenOutIndex so positionSize is denominated in tokenOut units\n const { tokenId: loanTokenId, adjustedSize } = buildUniqueLoan(\n pool.poolId,\n tokenOutIndex,\n tokenType,\n pool.currentTick,\n pool.tickSpacing,\n positionIds,\n amountOut,\n )\n\n // Op 1 (mint): loan with swapAtMint=true → borrow + swap\n // swapAtMint=true → descending tick limits: [high, low, spread]\n const mintTickLimits: readonly [number, number, number] = [\n Number(tickLimitHigh),\n Number(tickLimitLow),\n 0,\n ]\n\n // Op 2 (burn): same loan with swapAtMint=false → repay without swap\n // swapAtMint=false → ascending tick limits: [low, high, spread]\n const burnTickLimits: readonly [number, number, number] = [\n Number(tickLimitLow),\n Number(tickLimitHigh),\n 0,\n ]\n\n // positionIdList: [mint tokenId, burn tokenId]\n // finalPositionIdList: existing positions (loan opens and closes in same tx, net zero)\n // positionSizes: mint gets the size, burn gets 0n (= burn all)\n const positionIdList = [loanTokenId, loanTokenId]\n const finalPositionIdList = [...positionIds]\n const positionSizes = [adjustedSize, 0n]\n\n try {\n return await submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n positionSizes,\n [mintTickLimits, burnTickLimits],\n false, // usePremiaAsCollateral\n builderCode,\n ],\n txOverrides,\n })\n } catch (error) {\n if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) {\n continue\n }\n throw error\n }\n }\n\n throw new MaxRetriesExceededError('swapExactOut')\n}\n\n/**\n * Swap exact output and wait for confirmation.\n */\nexport async function swapExactOutAndWait(params: SwapExactOutParams): Promise<TxReceipt> {\n const result = await swapExactOut(params)\n return result.wait()\n}\n\n/**\n * Swap tokens using Panoptic's exact-input mechanism.\n *\n * Opens a loan with `swapAtMint=false` (borrows tokenIn to wallet),\n * then burns with `swapAtMint=true` (swaps tokenIn back to repay).\n * The user spends exactly `amountIn` of `tokenIn`.\n *\n * @param params - Swap parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await swapExactIn({\n * client, walletClient, account, poolAddress,\n * chainId: 11155111n,\n * tokenIn: USDC_ADDRESS,\n * amountIn: 1000n * 10n**6n, // 1000 USDC\n * slippageBps: 500n,\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function swapExactIn(params: SwapExactInParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n tokenIn,\n amountIn,\n slippageBps,\n existingPositionIds: explicitIds,\n storage,\n builderCode = 0n,\n txOverrides,\n } = params\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n const [pool, positionIds] = await Promise.all([\n getPool({ client, poolAddress, chainId }),\n resolvePositionIds(explicitIds, storage, chainId, poolAddress, account),\n ])\n\n const token0 = pool.collateralTracker0.token\n const token1 = pool.collateralTracker1.token\n const tokenInIndex = resolveTokenIndex(tokenIn, token0, token1)\n\n // For exact input: borrow tokenIn itself\n const tokenType = tokenInIndex\n\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n\n // asset = tokenInIndex so positionSize is denominated in tokenIn units\n const { tokenId: loanTokenId, adjustedSize } = buildUniqueLoan(\n pool.poolId,\n tokenInIndex,\n tokenType,\n pool.currentTick,\n pool.tickSpacing,\n positionIds,\n amountIn,\n )\n\n // Op 1 (mint): loan with swapAtMint=false → borrow tokenIn to wallet\n // swapAtMint=false → ascending tick limits: [low, high, spread]\n const mintTickLimits: readonly [number, number, number] = [\n Number(tickLimitLow),\n Number(tickLimitHigh),\n 0,\n ]\n\n // Op 2 (burn): same loan with swapAtMint=true → repay with swap\n // swapAtMint=true → descending tick limits: [high, low, spread]\n const burnTickLimits: readonly [number, number, number] = [\n Number(tickLimitHigh),\n Number(tickLimitLow),\n 0,\n ]\n\n // positionSizes: mint gets the size, burn gets 0n (= burn all)\n const positionIdList = [loanTokenId, loanTokenId]\n const finalPositionIdList = [...positionIds]\n const positionSizes = [adjustedSize, 0n]\n\n try {\n return await submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n positionSizes,\n [mintTickLimits, burnTickLimits],\n false,\n builderCode,\n ],\n txOverrides,\n })\n } catch (error) {\n if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) {\n continue\n }\n throw error\n }\n }\n\n throw new MaxRetriesExceededError('swapExactIn')\n}\n\n/**\n * Swap exact input and wait for confirmation.\n */\nexport async function swapExactInAndWait(params: SwapExactInParams): Promise<TxReceipt> {\n const result = await swapExactIn(params)\n return result.wait()\n}\n","/**\n * Wrap / unwrap operations for Backed xStock ERC4626 wrappers.\n *\n * xStocks are rebasing and can't be used in Panoptic/Uniswap pools directly;\n * those trade the non-rebasing **wrapper** (a standard ERC4626 vault whose\n * `asset()` is the underlying xStock). Wrapping is an ERC4626 `deposit`,\n * unwrapping an ERC4626 `redeem`. CoW Swap trades the unwrapped token, so a\n * user who buys an xStock on CoW must wrap it before lending it or selling it\n * through the Uniswap venue.\n *\n * Resolve a token's wrapper with `getXstockWrapper` from `@panoptic-eng/sdk`.\n *\n * @module v2/writes/wrap\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport type { TxOverrides, TxReceipt, TxResult } from '../types'\nimport { submitWrite } from './utils'\n\n/** Minimal ERC4626 surface used by the xStock wrappers. */\nexport const xstockWrapperAbi = [\n {\n type: 'function',\n name: 'deposit',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'assets', type: 'uint256' },\n { name: 'receiver', type: 'address' },\n ],\n outputs: [{ name: 'shares', type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'redeem',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'shares', type: 'uint256' },\n { name: 'receiver', type: 'address' },\n { name: 'owner', type: 'address' },\n ],\n outputs: [{ name: 'assets', type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'asset',\n stateMutability: 'view',\n inputs: [],\n outputs: [{ type: 'address' }],\n },\n {\n type: 'function',\n name: 'previewDeposit',\n stateMutability: 'view',\n inputs: [{ name: 'assets', type: 'uint256' }],\n outputs: [{ name: 'shares', type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'previewRedeem',\n stateMutability: 'view',\n inputs: [{ name: 'shares', type: 'uint256' }],\n outputs: [{ name: 'assets', type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'maxRedeem',\n stateMutability: 'view',\n inputs: [{ name: 'owner', type: 'address' }],\n outputs: [{ name: 'maxShares', type: 'uint256' }],\n },\n] as const\n\n/** Parameters for {@link wrapXstock}. */\nexport interface WrapXstockParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** Wrapper (ERC4626) address — resolve via `getXstockWrapper`. */\n wrapper: Address\n /** Amount of the underlying xStock to wrap. */\n assets: bigint\n /** Receiver of the wrapper shares (defaults to account). */\n receiver?: Address\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Wrap an underlying xStock into its ERC4626 wrapper (`deposit`). Requires a\n * prior ERC20 approval of the underlying to the wrapper address.\n *\n * @returns TxResult with hash and wait function\n */\nexport async function wrapXstock(params: WrapXstockParams): Promise<TxResult> {\n const { client, walletClient, account, wrapper, assets, receiver = account, txOverrides } = params\n return submitWrite({\n client,\n walletClient,\n account,\n address: wrapper,\n abi: xstockWrapperAbi,\n functionName: 'deposit',\n args: [assets, receiver],\n txOverrides,\n })\n}\n\n/** Wrap and wait for confirmation. */\nexport async function wrapXstockAndWait(params: WrapXstockParams): Promise<TxReceipt> {\n const result = await wrapXstock(params)\n return result.wait()\n}\n\n/** Parameters for {@link unwrapXstock}. */\nexport interface UnwrapXstockParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** Wrapper (ERC4626) address — resolve via `getXstockUnderlying`. */\n wrapper: Address\n /** Amount of wrapper shares to unwrap (redeem). */\n shares: bigint\n /** Receiver of the underlying xStock (defaults to account). */\n receiver?: Address\n /** Owner of the shares (defaults to account). */\n owner?: Address\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Unwrap wrapper shares back into the underlying xStock (`redeem`). When\n * `owner` defaults to (or equals) `account` the caller burns their own shares\n * and no approval is needed. Passing a different `owner` redeems on its behalf\n * and requires that owner to have granted the caller an ERC-4626 share\n * allowance (`approve`), or the `redeem` call reverts.\n *\n * @returns TxResult with hash and wait function\n */\nexport async function unwrapXstock(params: UnwrapXstockParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n wrapper,\n shares,\n receiver = account,\n owner = account,\n txOverrides,\n } = params\n return submitWrite({\n client,\n walletClient,\n account,\n address: wrapper,\n abi: xstockWrapperAbi,\n functionName: 'redeem',\n args: [shares, receiver, owner],\n txOverrides,\n })\n}\n\n/** Unwrap and wait for confirmation. */\nexport async function unwrapXstockAndWait(params: UnwrapXstockParams): Promise<TxReceipt> {\n const result = await unwrapXstock(params)\n return result.wait()\n}\n\n/** Parameters for the wrap/unwrap amount previews. */\nexport interface PreviewWrapParams {\n /** Public client */\n client: PublicClient\n /** Wrapper (ERC4626) address. */\n wrapper: Address\n /** Amount to convert: underlying assets for wrap, shares for unwrap. */\n amount: bigint\n}\n\n/**\n * Preview the wrapper shares minted for a given amount of underlying xStock.\n */\nexport async function previewWrap(params: PreviewWrapParams): Promise<bigint> {\n const { client, wrapper, amount } = params\n return client.readContract({\n address: wrapper,\n abi: xstockWrapperAbi,\n functionName: 'previewDeposit',\n args: [amount],\n })\n}\n\n/**\n * Preview the underlying xStock returned for a given amount of wrapper shares.\n */\nexport async function previewUnwrap(params: PreviewWrapParams): Promise<bigint> {\n const { client, wrapper, amount } = params\n return client.readContract({\n address: wrapper,\n abi: xstockWrapperAbi,\n functionName: 'previewRedeem',\n args: [amount],\n })\n}\n\n/**\n * Minimal canonical WETH9 surface used for ETH<->WETH wrapping. Unlike the\n * ERC4626 xStock wrapper, WETH is a 1:1 wrapper: `deposit` is payable and wraps\n * `msg.value`, `withdraw` unwraps an exact amount back to native ETH.\n */\nexport const wethWrapAbi = [\n {\n type: 'function',\n name: 'deposit',\n stateMutability: 'payable',\n inputs: [],\n outputs: [],\n },\n {\n type: 'function',\n name: 'withdraw',\n stateMutability: 'nonpayable',\n inputs: [{ name: 'wad', type: 'uint256' }],\n outputs: [],\n },\n] as const\n\n/** Parameters for {@link wrapEth}. */\nexport interface WrapEthParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** Canonical WETH9 address for the chain. */\n weth: Address\n /** Amount of native ETH to wrap (sent as msg.value). */\n amount: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Wrap native ETH into WETH (`deposit` payable). No approval needed.\n *\n * @returns TxResult with hash and wait function\n */\nexport async function wrapEth(params: WrapEthParams): Promise<TxResult> {\n const { client, walletClient, account, weth, amount, txOverrides } = params\n return submitWrite({\n client,\n walletClient,\n account,\n address: weth,\n abi: wethWrapAbi,\n functionName: 'deposit',\n args: [],\n value: amount,\n txOverrides,\n })\n}\n\n/** Wrap ETH and wait for confirmation. */\nexport async function wrapEthAndWait(params: WrapEthParams): Promise<TxReceipt> {\n const result = await wrapEth(params)\n return result.wait()\n}\n\n/** Parameters for {@link unwrapWeth}. */\nexport interface UnwrapWethParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** Canonical WETH9 address for the chain. */\n weth: Address\n /** Amount of WETH to unwrap back to native ETH. */\n amount: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Unwrap WETH back into native ETH (`withdraw`). Burns the caller's own WETH —\n * no approval needed.\n *\n * @returns TxResult with hash and wait function\n */\nexport async function unwrapWeth(params: UnwrapWethParams): Promise<TxResult> {\n const { client, walletClient, account, weth, amount, txOverrides } = params\n return submitWrite({\n client,\n walletClient,\n account,\n address: weth,\n abi: wethWrapAbi,\n functionName: 'withdraw',\n args: [amount],\n txOverrides,\n })\n}\n\n/** Unwrap WETH and wait for confirmation. */\nexport async function unwrapWethAndWait(params: UnwrapWethParams): Promise<TxReceipt> {\n const result = await unwrapWeth(params)\n return result.wait()\n}\n","/**\n * TokenId decoding for the Panoptic v2 SDK.\n * @module v2/tokenId/decode\n */\n\nimport type { TokenIdLeg } from '../types'\nimport {\n type DecodedLeg,\n countLegs,\n decodeAllLegs,\n decodePoolId,\n decodeTickSpacing,\n decodeVegoid,\n} from './encoding'\n\n/**\n * Decoded TokenId data.\n */\nexport interface DecodedTokenId {\n /** The original TokenId */\n tokenId: bigint\n /** The pool ID portion as hex */\n poolId: `0x${string}`\n /** The vegoid value */\n vegoid: bigint\n /** The tick spacing */\n tickSpacing: bigint\n /** The decoded legs */\n legs: TokenIdLeg[]\n /** Number of active legs */\n legCount: bigint\n}\n\n/**\n * Convert a DecodedLeg to TokenIdLeg format.\n *\n * @param leg - The decoded leg from encoding utils\n * @param tickSpacing - The tick spacing for calculating tick bounds\n * @returns The TokenIdLeg format\n */\nfunction convertToTokenIdLeg(leg: DecodedLeg, tickSpacing: bigint): TokenIdLeg {\n // Calculate tick bounds from strike and width\n // width is in tick spacing units, so actual width = width * tickSpacing\n const halfWidth = (leg.width * tickSpacing) / 2n\n const tickLower = leg.strike - halfWidth\n const tickUpper = leg.strike + halfWidth\n\n return {\n index: leg.index,\n asset: leg.asset,\n optionRatio: leg.optionRatio,\n isLong: leg.isLong,\n tokenType: leg.tokenType,\n riskPartner: leg.riskPartner,\n strike: leg.strike,\n width: leg.width,\n tickLower,\n tickUpper,\n }\n}\n\n/**\n * Decode a TokenId into its component parts.\n *\n * @param tokenId - The TokenId to decode\n * @returns The decoded TokenId data\n *\n * @example\n * ```typescript\n * const decoded = decodeTokenId(tokenId)\n * console.log(decoded.legs) // Array of legs\n * console.log(decoded.tickSpacing) // Tick spacing\n * ```\n */\nexport function decodeTokenId(tokenId: bigint): DecodedTokenId {\n const poolId = decodePoolId(tokenId)\n const vegoid = decodeVegoid(tokenId)\n const tickSpacing = decodeTickSpacing(tokenId)\n const rawLegs = decodeAllLegs(tokenId)\n const numLegs = countLegs(tokenId)\n\n const legs = rawLegs.map((leg) => convertToTokenIdLeg(leg, tickSpacing))\n\n return {\n tokenId,\n poolId,\n vegoid,\n tickSpacing,\n legs,\n legCount: numLegs,\n }\n}\n\n/**\n * Validate that a TokenId has the expected pool ID.\n *\n * @param tokenId - The TokenId to validate\n * @param expectedPoolId - The expected pool ID\n * @returns True if the pool IDs match\n */\nexport function validatePoolId(tokenId: bigint, expectedPoolId: bigint): boolean {\n const actualPoolId = tokenId & ((1n << 64n) - 1n)\n return actualPoolId === expectedPoolId\n}\n\n/**\n * Check if a TokenId represents a long position (any leg is long).\n *\n * @param tokenId - The TokenId to check\n * @returns True if any leg is long\n */\nexport function hasLongLeg(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.some((leg) => leg.isLong)\n}\n\n/**\n * Check if a TokenId represents a short-only position.\n *\n * @param tokenId - The TokenId to check\n * @returns True if all legs are short\n */\nexport function isShortOnly(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.length > 0 && legs.every((leg) => !leg.isLong)\n}\n\n/**\n * Check if a TokenId represents a spread (legs with different risk partners).\n *\n * @param tokenId - The TokenId to check\n * @returns True if any leg has a different risk partner\n */\nexport function isSpread(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.some((leg) => leg.riskPartner !== leg.index)\n}\n\n/**\n * Get the asset index for a TokenId (from the first leg).\n *\n * @param tokenId - The TokenId\n * @returns The asset index (0 or 1), or undefined if no legs\n */\nexport function getAssetIndex(tokenId: bigint): bigint | undefined {\n const legs = decodeAllLegs(tokenId)\n if (legs.length === 0) {\n return undefined\n }\n return legs[0].asset\n}\n\n/**\n * Check if a leg is a loan (width=0 and isLong=false).\n *\n * Loans borrow liquidity from the pool at a specific strike price.\n *\n * @param leg - The decoded leg to check\n * @returns True if the leg is a loan\n */\nexport function isLoanLeg(leg: DecodedLeg): boolean {\n return leg.width === 0n && !leg.isLong\n}\n\n/**\n * Check if a leg is a credit (width=0 and isLong=true).\n *\n * Credits lend liquidity to the pool at a specific strike price.\n *\n * @param leg - The decoded leg to check\n * @returns True if the leg is a credit\n */\nexport function isCreditLeg(leg: DecodedLeg): boolean {\n return leg.width === 0n && leg.isLong\n}\n\n/**\n * Check if a TokenId has any loan legs.\n *\n * @param tokenId - The TokenId to check\n * @returns True if any leg is a loan (width=0, isLong=false)\n */\nexport function hasLoanLeg(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.some(isLoanLeg)\n}\n\n/**\n * Check if a TokenId has any credit legs.\n *\n * @param tokenId - The TokenId to check\n * @returns True if any leg is a credit (width=0, isLong=true)\n */\nexport function hasCreditLeg(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.some(isCreditLeg)\n}\n\n/**\n * Check if a TokenId is a pure loan (all legs are loans).\n *\n * @param tokenId - The TokenId to check\n * @returns True if all legs are loans\n */\nexport function isLoan(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.length > 0 && legs.every(isLoanLeg)\n}\n\n/**\n * Check if a TokenId is a pure credit (all legs are credits).\n *\n * @param tokenId - The TokenId to check\n * @returns True if all legs are credits\n */\nexport function isCredit(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.length > 0 && legs.every(isCreditLeg)\n}\n\n/**\n * Check if a TokenId contains loan or credit legs (width=0).\n *\n * @param tokenId - The TokenId to check\n * @returns True if any leg has width=0 (loan or credit)\n */\nexport function hasLoanOrCredit(tokenId: bigint): boolean {\n const legs = decodeAllLegs(tokenId)\n return legs.some((leg) => leg.width === 0n)\n}\n","/**\n * Token flow simulation utility using PanopticPool.multicall.\n *\n * Uses getAssetsOf-dispatch-getAssetsOf pattern within a single eth_call\n * to measure exact collateral asset movements from any dispatch call.\n *\n * @module v2/simulations/tokenFlow\n */\n\nimport {\n type Address,\n type Hex,\n type PublicClient,\n decodeFunctionResult,\n encodeFunctionData,\n} from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { panopticErrorsAbi } from '../errors/errorsAbi'\n\n/**\n * PanopticPool getAssetsOf ABI.\n * Returns collateral assets (shares converted to underlying) for an account.\n */\nconst getAssetsOfAbi = [\n {\n type: 'function',\n name: 'getAssetsOf',\n inputs: [{ name: 'account', type: 'address' }],\n outputs: [\n { name: 'assets0', type: 'uint256' },\n { name: 'assets1', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n] as const\n\n/**\n * PanopticPool multicall ABI (inherited from Uniswap).\n * Uses delegatecall, preserving msg.sender throughout the chain.\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 // Include error definitions so viem can decode revert data with full args\n ...panopticErrorsAbi,\n] as const\n\n/**\n * Token flow result from simulation.\n * Measures collateral asset changes via getAssetsOf-dispatch-getAssetsOf pattern.\n */\nexport interface TokenFlow {\n /** Token 0 collateral change (negative = user deposits, positive = user receives) */\n delta0: bigint\n /** Token 1 collateral change (negative = user deposits, positive = user receives) */\n delta1: bigint\n /** Collateral assets in token 0 before the call */\n balanceBefore0: bigint\n /** Collateral assets in token 1 before the call */\n balanceBefore1: bigint\n /** Collateral assets in token 0 after the call */\n balanceAfter0: bigint\n /** Collateral assets in token 1 after the call */\n balanceAfter1: bigint\n /** Pool tick before the operation */\n tickBefore: bigint | null\n /** Pool tick after the operation */\n tickAfter: bigint | null\n}\n\n/**\n * Parameters for simulateWithTokenFlow.\n */\nexport interface SimulateWithTokenFlowParams {\n /** viem public client */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** User address whose collateral changes we're measuring */\n user: Address\n /** Encoded call data (typically dispatch) */\n callData: Hex\n /** Optional block number for simulation */\n blockNumber?: bigint\n /**\n * Optional additional encoded calls to append after the 5-call pattern.\n * These execute post-dispatch within the same multicall (same state).\n * Raw encoded bytes are returned in `postCallResults`.\n */\n postCallData?: Hex[]\n /**\n * Optional additional encoded calls to insert between the pre-dispatch\n * `getAssetsOf` / `getCurrentTick` and the target call. These execute\n * pre-dispatch within the same multicall — useful for reading per-position\n * data (e.g. `getFullPositionsData`) against the original `positionIdList`\n * before state mutates. Raw encoded bytes are returned in `preCallResults`.\n */\n preCallData?: Hex[]\n}\n\n/**\n * Result of simulateWithTokenFlow.\n */\nexport interface SimulateWithTokenFlowResult {\n /** Whether the simulation succeeded */\n success: boolean\n /** Token flow data (only if success) */\n tokenFlow?: TokenFlow\n /** Error message (only if failed) */\n error?: string\n /** Raw error object preserving viem cause chain and revert data */\n rawError?: Error\n /** Gas estimate for the inner call */\n gasEstimate: bigint\n /** Raw results from postCallData entries (only if success and postCallData was provided) */\n postCallResults?: Hex[]\n /** Raw results from preCallData entries (only if success and preCallData was provided) */\n preCallResults?: Hex[]\n}\n\n/**\n * Simulate a contract call and measure token flow using PanopticPool.multicall.\n *\n * This function uses PanopticPool's inherited multicall (delegatecall-based) to chain:\n * 1. getAssetsOf(user) - read collateral assets before\n * 2. getCurrentTick() - read pool tick before\n * 3. Execute the target call (e.g., dispatch)\n * 4. getCurrentTick() - read pool tick after\n * 5. getAssetsOf(user) - read collateral assets after\n *\n * ## Why PanopticPool.multicall instead of Multicall3?\n * - Measures **collateral assets** (shares → underlying), not raw wallet balances\n * - Uses **delegatecall**, preserving msg.sender throughout the chain\n * - Single contract interaction with PanopticPool\n * - Correctly reflects what happens during position operations\n *\n * ## Same-Block Guarantee\n * All operations execute within a single eth_call, ensuring atomic consistency.\n *\n * @param params - Simulation parameters\n * @returns Token flow result\n *\n * @example\n * ```typescript\n * const callData = encodeFunctionData({\n * abi: panopticPoolV2Abi,\n * functionName: 'dispatch',\n * args: [positionIdList, finalPositionIdList, positionSizes, tickAndSpreadLimits, false, 0n],\n * })\n *\n * const result = await simulateWithTokenFlow({\n * client,\n * poolAddress,\n * user: userAddress,\n * callData,\n * })\n *\n * if (result.success) {\n * console.log('Token 0 change:', result.tokenFlow.delta0)\n * console.log('Token 1 change:', result.tokenFlow.delta1)\n * }\n * ```\n */\nexport async function simulateWithTokenFlow(\n params: SimulateWithTokenFlowParams,\n): Promise<SimulateWithTokenFlowResult> {\n const { client, poolAddress, user, callData, blockNumber, postCallData, preCallData } = params\n\n // Encode getAssetsOf call\n const getAssetsOfCallData = encodeFunctionData({\n abi: getAssetsOfAbi,\n functionName: 'getAssetsOf',\n args: [user],\n })\n\n // Encode getCurrentTick call\n const getCurrentTickCallData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n })\n\n const preLen = preCallData?.length ?? 0\n\n // Build multicall: [getAssetsOf, getCurrentTick, ...preCallData, targetCall, getCurrentTick, getAssetsOf, ...postCallData]\n const multicallData: Hex[] = [\n getAssetsOfCallData,\n getCurrentTickCallData,\n ...(preCallData ?? []),\n callData,\n getCurrentTickCallData,\n getAssetsOfCallData,\n ...(postCallData ?? []),\n ]\n\n try {\n // Execute via simulateContract on PanopticPool's multicall\n const { result } = await client.simulateContract({\n address: poolAddress,\n abi: multicallAbi,\n functionName: 'multicall',\n args: [multicallData],\n account: user,\n blockNumber,\n })\n\n // Decode getAssetsOf results\n const decodeAssets = (data: Hex): { assets0: bigint; assets1: bigint } => {\n const decoded = decodeFunctionResult({\n abi: getAssetsOfAbi,\n functionName: 'getAssetsOf',\n data,\n })\n return { assets0: decoded[0], assets1: decoded[1] }\n }\n\n // Decode getCurrentTick result (int24 decodes as number, convert to bigint)\n const decodeTick = (data: Hex): bigint => {\n return BigInt(\n decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n data,\n }),\n )\n }\n\n const assetsBefore = decodeAssets(result[0])\n const tickBefore = decodeTick(result[1])\n // result[2..2+preLen-1] are preCallData results\n // result[2+preLen] is the target call result (dispatch)\n const tickAfter = decodeTick(result[3 + preLen])\n const assetsAfter = decodeAssets(result[4 + preLen])\n\n const preCallResults = preLen > 0 ? (result.slice(2, 2 + preLen) as Hex[]) : undefined\n const postCallResults =\n postCallData && postCallData.length > 0 ? (result.slice(5 + preLen) as Hex[]) : undefined\n\n const delta0 = assetsAfter.assets0 - assetsBefore.assets0\n const delta1 = assetsAfter.assets1 - assetsBefore.assets1\n\n // Estimate gas for the target call directly\n let gasEstimate = 0n\n try {\n gasEstimate = await client.estimateGas({\n account: user,\n to: poolAddress,\n data: callData,\n blockNumber,\n })\n } catch {\n // Gas estimation may fail, use 0\n }\n\n return {\n success: true,\n tokenFlow: {\n delta0,\n delta1,\n balanceBefore0: assetsBefore.assets0,\n balanceBefore1: assetsBefore.assets1,\n balanceAfter0: assetsAfter.assets0,\n balanceAfter1: assetsAfter.assets1,\n tickBefore,\n tickAfter,\n },\n gasEstimate,\n postCallResults,\n preCallResults,\n }\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Simulation failed',\n rawError: error instanceof Error ? error : undefined,\n gasEstimate: 0n,\n }\n }\n}\n\n/**\n * Parameters for getting pool tokens.\n */\nexport interface GetPoolTokensParams {\n /** viem public client */\n client: PublicClient\n /** Pool address */\n poolAddress: Address\n /** Optional block number */\n blockNumber?: bigint\n}\n\n/**\n * Pool token addresses result.\n */\nexport interface PoolTokens {\n /** Token 0 address */\n token0: Address\n /** Token 1 address */\n token1: Address\n /** Collateral tracker 0 address */\n collateralTracker0: Address\n /** Collateral tracker 1 address */\n collateralTracker1: Address\n}\n\n/**\n * Get pool token addresses for reference.\n *\n * @param params - Parameters\n * @returns Pool token addresses\n */\nexport async function getPoolTokensForSimulation(params: GetPoolTokensParams): Promise<PoolTokens> {\n const { client, poolAddress, blockNumber } = params\n\n // Minimal ABI for the calls we need\n const poolAbi = [\n {\n type: 'function',\n name: 'collateralToken0',\n inputs: [],\n outputs: [{ type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'collateralToken1',\n inputs: [],\n outputs: [{ type: 'address' }],\n stateMutability: 'view',\n },\n ] as const\n\n const collateralAbi = [\n {\n type: 'function',\n name: 'asset',\n inputs: [],\n outputs: [{ type: 'address' }],\n stateMutability: 'view',\n },\n ] as const\n\n // Get collateral tracker addresses\n const [ct0, ct1] = await client.multicall({\n contracts: [\n { address: poolAddress, abi: poolAbi, functionName: 'collateralToken0' },\n { address: poolAddress, abi: poolAbi, functionName: 'collateralToken1' },\n ],\n blockNumber,\n allowFailure: false,\n })\n\n // Get underlying token addresses from collateral trackers\n const [token0, token1] = await client.multicall({\n contracts: [\n { address: ct0, abi: collateralAbi, functionName: 'asset' },\n { address: ct1, abi: collateralAbi, functionName: 'asset' },\n ],\n blockNumber,\n allowFailure: false,\n })\n\n return {\n token0,\n token1,\n collateralTracker0: ct0,\n collateralTracker1: ct1,\n }\n}\n","/**\n * Open position simulation for the Panoptic v2 SDK.\n * @module v2/simulations/simulateOpenPosition\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { decodeFunctionResult, encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError } from '../errors'\nimport { calculatePositionGreeks } from '../greeks'\nimport { getPool } from '../reads/pool'\nimport { decodeTokenId } from '../tokenId/decode'\nimport type { OpenPositionSimulation, SimulationResult } from '../types'\nimport { decodeLeftRightUnsigned } from '../writes/utils'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\n/**\n * Parameters for simulating position opening.\n */\nexport interface SimulateOpenPositionParams {\n /** Public client */\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 /**\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 mint 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 /** Chain ID (required for pool data fetch used in greeks) */\n chainId?: bigint\n /** Optional block number for simulation */\n blockNumber?: bigint\n}\n\n/**\n * Simulate opening a position.\n *\n * Uses PanopticPool.multicall with getAssetsOf-dispatch-getAssetsOf pattern\n * to measure exact collateral asset movements, then enriches with decoded\n * position data and client-side greeks.\n *\n * @param params - Simulation parameters\n * @returns Simulation result with position data or error\n *\n * @example\n * ```typescript\n * import { MIN_TICK, MAX_TICK } from '@panoptic/sdk'\n *\n * const result = await simulateOpenPosition({\n * client,\n * poolAddress,\n * account,\n * existingPositionIds: [],\n * tokenId,\n * positionSize: 1n,\n * tickLimitLow: MIN_TICK,\n * tickLimitHigh: MAX_TICK,\n * swapAtMint: false,\n * chainId: 11155111n, // Sepolia\n * })\n *\n * if (result.success) {\n * console.log('Gas estimate:', result.gasEstimate)\n * console.log('Token 0 required:', result.data.amount0Required)\n * console.log('Token 1 required:', result.data.amount1Required)\n * console.log('Delta:', result.data.greeks.delta)\n * } else {\n * console.log('Error:', result.error)\n * }\n * ```\n */\nexport async function simulateOpenPosition(\n params: SimulateOpenPositionParams,\n): Promise<SimulationResult<OpenPositionSimulation>> {\n const {\n client,\n poolAddress,\n account,\n existingPositionIds,\n tokenId,\n positionSize,\n tickLimitLow,\n tickLimitHigh,\n spreadLimit = 0n,\n swapAtMint = false,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n chainId,\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 position lists for dispatch:\n // - positionIdList: positions being minted in this call (just the new tokenId)\n // - finalPositionIdList: all positions the user will have after the mint\n const positionIdList = [tokenId]\n const finalPositionIdList = [...existingPositionIds, tokenId]\n\n // Encode dispatch call data\n const callData = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n // ABI declares uint128 but TS only knows bigint — viem/abitype limitation\n [BigInt(positionSize) as unknown as bigint & { readonly __uint128: true }],\n [tickLimits],\n usePremiaAsCollateral,\n builderCode,\n ],\n })\n\n // Encode getFullPositionsData to run post-dispatch in the same multicall\n const getFullPositionsDataCallData = 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 postCallData: [getFullPositionsDataCallData],\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\n // Decode post-mint collateral requirements from getFullPositionsData result\n let postMintCollateralReqToken0 = 0n\n let postMintCollateralReqToken1 = 0n\n const perPositionCollateralReqs: { token0: bigint; token1: bigint }[] = []\n if (flowResult.postCallResults?.[0]) {\n try {\n const decoded = decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n data: flowResult.postCallResults[0],\n })\n // Result: [shortPremium, longPremium, balances[], collateralReqs[], netPremia[]]\n const collateralReqs = decoded[3]\n if (collateralReqs.length > 0) {\n // Each entry is a LeftRightUnsigned: right=token0, left=token1\n // Sum across all positions in finalPositionIdList\n for (const packed of collateralReqs) {\n const req = decodeLeftRightUnsigned(packed)\n postMintCollateralReqToken0 += req.right\n postMintCollateralReqToken1 += req.left\n perPositionCollateralReqs.push({ token0: req.right, token1: req.left })\n }\n }\n } catch {\n // Decode failure — leave at 0n\n }\n }\n\n // Decode tokenId to get legs and tick spacing\n const decoded = decodeTokenId(tokenId)\n\n // Fetch pool state for greeks (currentTick, tickSpacing) if chainId provided\n let currentTick = 0n\n let poolTickSpacing = decoded.tickSpacing\n let utilization0 = 0n\n let utilization1 = 0n\n\n if (chainId !== undefined) {\n try {\n const pool = await getPool({ client, poolAddress, chainId, blockNumber: targetBlockNumber })\n currentTick = pool.currentTick\n poolTickSpacing = pool.tickSpacing\n utilization0 = pool.collateralTracker0.utilization\n utilization1 = pool.collateralTracker1.utilization\n } catch {\n // Pool fetch failed - use decoded tickSpacing, skip greeks\n }\n }\n\n // Calculate greeks if we have legs and pool data\n const greeks =\n decoded.legs.length > 0 && (chainId !== undefined || currentTick !== 0n)\n ? calculatePositionGreeks({\n legs: decoded.legs,\n currentTick,\n mintTick: currentTick, // At simulation time, mintTick = currentTick\n positionSize,\n poolTickSpacing,\n })\n : { value: 0n, delta: 0n, gamma: 0n }\n\n const _meta = await metaPromise\n\n // Map token flow to simulation fields:\n // Negative delta = user deposits (required), so amount required = -delta\n const amount0Required = -tokenFlow.delta0\n const amount1Required = -tokenFlow.delta1\n\n const data: OpenPositionSimulation = {\n position: {\n tokenId,\n positionSize,\n owner: account,\n poolAddress,\n legs: decoded.legs,\n poolUtilization0AtMint: utilization0,\n poolUtilization1AtMint: utilization1,\n tickAtMint: currentTick,\n timestampAtMint: _meta.blockTimestamp,\n blockNumberAtMint: _meta.blockNumber,\n swapAtMint,\n premiaOwed0: 0n,\n premiaOwed1: 0n,\n assetIndex: 0n,\n _meta,\n },\n greeks,\n amount0Required,\n amount1Required,\n postCollateral0: tokenFlow.balanceAfter0,\n postCollateral1: tokenFlow.balanceAfter1,\n postMintCollateralReqToken0,\n postMintCollateralReqToken1,\n perPositionCollateralReqs,\n commission0: null, // Embedded in contract logic, not extractable from token flow\n commission1: 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 * Lending API for the Panoptic v2 SDK.\n *\n * Provides Aave/Compound-style supply/borrow/repay/unsupply functions\n * that wrap the lower-level vault and position primitives.\n *\n * @module v2/writes/lending\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { MaxRetriesExceededError, NoLoanPositionsError } from '../errors'\nimport { tickLimits } from '../formatters/tick'\nimport { getPool } from '../reads/pool'\nimport { simulateOpenPosition } from '../simulations/simulateOpenPosition'\nimport type { StorageAdapter } from '../storage'\nimport { getPositionsKey, jsonSerializer } from '../storage'\nimport { getTrackedPositionIds } from '../sync/getTrackedPositionIds'\nimport { isLoan } from '../tokenId/decode'\nimport { decodeAllLegs } from '../tokenId/encoding'\nimport type {\n OpenPositionSimulation,\n SimulationResult,\n TxOverrides,\n TxReceipt,\n TxResult,\n} from '../types'\nimport {\n buildUniqueLoan,\n isInputListFailError,\n MAX_RETRIES,\n resolvePositionIds,\n resolveTokenIndex,\n} from './loanUtils'\nimport { submitWrite } from './utils'\nimport { deposit, withdraw } from './vault'\n\n// ---------------------------------------------------------------------------\n// Parameter types\n// ---------------------------------------------------------------------------\n\n/** Parameters for supplying collateral into a pool. */\nexport interface SupplyParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID */\n chainId: bigint\n /** Token address to supply (must be token0 or token1 of the pool) */\n token: Address\n /** Amount of token to supply */\n amount: bigint\n /** Whether the token is native ETH (requires sending msg.value) */\n isNativeETH?: boolean\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/** Parameters for withdrawing (unsupplying) collateral from a pool. */\nexport interface UnsupplyParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID */\n chainId: bigint\n /** Token address to withdraw (must be token0 or token1 of the pool) */\n token: Address\n /** Amount of token to withdraw */\n amount: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/** Parameters for borrowing tokens via a loan position. */\nexport interface BorrowParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID */\n chainId: bigint\n /** Token address to borrow (must be token0 or token1 of the pool) */\n token: Address\n /** Amount of token to borrow */\n amount: bigint\n /** Slippage tolerance in bps (e.g. 500n = 5%) */\n slippageBps: bigint\n /** Existing position IDs. If omitted, resolved from storage. */\n existingPositionIds?: bigint[]\n /** Storage adapter for position ID resolution and tracking */\n storage?: StorageAdapter\n /** Builder code for fee routing (0 = no builder). */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/** Parameters for repaying a loan (full or partial). */\nexport interface RepayParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID */\n chainId: bigint\n /** TokenId of the loan position to repay */\n loanTokenId: bigint\n /** Amount to repay. If >= current position size, does full repay. */\n amount: bigint\n /** Slippage tolerance in bps (e.g. 500n = 5%) */\n slippageBps: bigint\n /** Current position IDs. If omitted, resolved from storage. */\n existingPositionIds?: bigint[]\n /** Storage adapter for position ID resolution and tracking */\n storage?: StorageAdapter\n /** Builder code for fee routing (0 = no builder). */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve collateral tracker address for a given token in the pool.\n */\nasync function resolveCollateralTracker(\n client: PublicClient,\n poolAddress: Address,\n chainId: bigint,\n token: Address,\n): Promise<Address> {\n const pool = await getPool({ client, poolAddress, chainId })\n const tokenIndex = resolveTokenIndex(\n token,\n pool.collateralTracker0.token,\n pool.collateralTracker1.token,\n )\n return tokenIndex === 0n ? pool.collateralTracker0.address : pool.collateralTracker1.address\n}\n\n/**\n * Save a position ID list to storage.\n */\nasync function savePositionIds(\n storage: StorageAdapter,\n chainId: bigint,\n poolAddress: Address,\n account: Address,\n positionIds: bigint[],\n): Promise<void> {\n const key = getPositionsKey(chainId, poolAddress, account)\n await storage.set(key, jsonSerializer.stringify(positionIds))\n}\n\n// ---------------------------------------------------------------------------\n// supply / unsupply\n// ---------------------------------------------------------------------------\n\n/**\n * Supply collateral into a pool.\n *\n * Resolves the correct collateral tracker from the token address,\n * then delegates to the low-level `deposit()`.\n *\n * @param params - Supply parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await supply({\n * client, walletClient, account, poolAddress,\n * chainId: 11155111n,\n * token: WETH_ADDRESS,\n * amount: 1n * 10n**18n,\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function supply(params: SupplyParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n token,\n amount,\n isNativeETH,\n txOverrides,\n } = params\n const collateralTrackerAddress = await resolveCollateralTracker(\n client,\n poolAddress,\n chainId,\n token,\n )\n return deposit({\n client,\n walletClient,\n account,\n collateralTrackerAddress,\n assets: amount,\n isNativeETH,\n txOverrides,\n })\n}\n\n/**\n * Supply collateral and wait for confirmation.\n */\nexport async function supplyAndWait(params: SupplyParams): Promise<TxReceipt> {\n const result = await supply(params)\n return result.wait()\n}\n\n/**\n * Withdraw (unsupply) collateral from a pool.\n *\n * Resolves the correct collateral tracker from the token address,\n * then delegates to the low-level `withdraw()`.\n *\n * @param params - Unsupply parameters\n * @returns TxResult\n */\nexport async function unsupply(params: UnsupplyParams): Promise<TxResult> {\n const { client, walletClient, account, poolAddress, chainId, token, amount, txOverrides } = params\n const collateralTrackerAddress = await resolveCollateralTracker(\n client,\n poolAddress,\n chainId,\n token,\n )\n return withdraw({\n client,\n walletClient,\n account,\n collateralTrackerAddress,\n assets: amount,\n txOverrides,\n })\n}\n\n/**\n * Withdraw collateral and wait for confirmation.\n */\nexport async function unsupplyAndWait(params: UnsupplyParams): Promise<TxReceipt> {\n const result = await unsupply(params)\n return result.wait()\n}\n\n// ---------------------------------------------------------------------------\n// borrow\n// ---------------------------------------------------------------------------\n\n/**\n * Borrow tokens from a pool via a loan position.\n *\n * Creates a loan tokenId and mints it via dispatch. The loan borrows the\n * specified token without swapping (ascending tick limits = no swap).\n *\n * @param params - Borrow parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * const result = await borrow({\n * client, walletClient, account, poolAddress,\n * chainId: 11155111n,\n * token: USDC_ADDRESS,\n * amount: 100n * 10n**6n,\n * slippageBps: 500n,\n * })\n * const receipt = await result.wait()\n * ```\n */\nexport async function borrow(params: BorrowParams): Promise<TxResult & { loanTokenId: bigint }> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n token,\n amount,\n slippageBps,\n existingPositionIds: explicitIds,\n builderCode = 0n,\n storage,\n txOverrides,\n } = params\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n const [pool, positionIds] = await Promise.all([\n getPool({ client, poolAddress, chainId }),\n resolvePositionIds(explicitIds, storage, chainId, poolAddress, account),\n ])\n\n const token0 = pool.collateralTracker0.token\n const token1 = pool.collateralTracker1.token\n const tokenIndex = resolveTokenIndex(token, token0, token1)\n\n // For a loan: both asset and tokenType = the borrowed token index\n const { tokenId: loanTokenId, adjustedSize } = buildUniqueLoan(\n pool.poolId,\n tokenIndex,\n tokenIndex,\n pool.currentTick,\n pool.tickSpacing,\n positionIds,\n amount,\n )\n\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n\n // Ascending tick limits = no swap at mint\n const mintTickLimits: readonly [number, number, number] = [\n Number(tickLimitLow),\n Number(tickLimitHigh),\n 0,\n ]\n\n const positionIdList = [loanTokenId]\n const finalPositionIdList = [...positionIds, loanTokenId]\n const positionSizes = [adjustedSize]\n\n try {\n const txResult = await submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n positionIdList,\n finalPositionIdList,\n positionSizes,\n [mintTickLimits],\n false,\n builderCode,\n ],\n txOverrides,\n })\n return { ...txResult, loanTokenId }\n } catch (error) {\n if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) {\n continue\n }\n throw error\n }\n }\n\n throw new MaxRetriesExceededError('borrow')\n}\n\n/**\n * Borrow tokens and wait for confirmation.\n * If storage is provided, auto-tracks the new loan position.\n */\nexport async function borrowAndWait(params: BorrowParams): Promise<TxReceipt> {\n const result = await borrow(params)\n const receipt = await result.wait()\n\n // Auto-update storage if provided\n if (params.storage && params.chainId !== undefined) {\n const { poolAddress, chainId, storage, account, existingPositionIds: explicitIds } = params\n\n const positionIds =\n explicitIds ?? (await getTrackedPositionIds({ chainId, poolAddress, account, storage }))\n\n await savePositionIds(storage, chainId, poolAddress, account, [\n ...positionIds,\n result.loanTokenId,\n ])\n }\n\n return receipt\n}\n\n// ---------------------------------------------------------------------------\n// preview borrow\n// ---------------------------------------------------------------------------\n\n/** Parameters for previewing a borrow (read-only, no wallet required). */\nexport interface PreviewBorrowParams {\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 borrow (must be token0 or token1 of the pool) */\n token: Address\n /** Amount of token to borrow */\n amount: bigint\n /** Slippage tolerance in bps (e.g. 500n = 5%) */\n slippageBps: bigint\n /** Existing position IDs */\n existingPositionIds: bigint[]\n}\n\n/** Result of a borrow preview. */\nexport interface PreviewBorrowResult {\n /** The loan tokenId that would be minted */\n loanTokenId: bigint\n /** Adjusted position size (after optionRatio scaling) */\n adjustedSize: bigint\n /** Simulation result from dry-run dispatch */\n simulation: SimulationResult<OpenPositionSimulation>\n /** Collateral requirement for the new loan position only (token0). Null if simulation failed. */\n collateralReqToken0: bigint | null\n /** Collateral requirement for the new loan position only (token1). Null if simulation failed. */\n collateralReqToken1: bigint | null\n}\n\n/**\n * Preview a borrow without executing it.\n *\n * Builds the loan tokenId (same logic as `borrow`) and runs a\n * dry-run `simulateOpenPosition` to check feasibility and return\n * post-mint collateral requirements.\n *\n * @param params - Preview parameters\n * @returns Preview result with tokenId, size, and simulation data\n */\nexport async function previewBorrow(params: PreviewBorrowParams): Promise<PreviewBorrowResult> {\n const { client, poolAddress, chainId, token, amount, slippageBps, account, existingPositionIds } =\n params\n\n const pool = await getPool({ client, poolAddress, chainId })\n\n const token0 = pool.collateralTracker0.token\n const token1 = pool.collateralTracker1.token\n const tokenIndex = resolveTokenIndex(token, token0, token1)\n\n const { tokenId: loanTokenId, adjustedSize } = buildUniqueLoan(\n pool.poolId,\n tokenIndex,\n tokenIndex,\n pool.currentTick,\n pool.tickSpacing,\n existingPositionIds,\n amount,\n )\n\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n\n const simulation = await simulateOpenPosition({\n client,\n poolAddress,\n account,\n existingPositionIds,\n tokenId: loanTokenId,\n positionSize: adjustedSize,\n tickLimitLow: BigInt(tickLimitLow),\n tickLimitHigh: BigInt(tickLimitHigh),\n chainId,\n })\n\n // Extract the new loan's collateral requirement (last entry in perPositionCollateralReqs)\n let collateralReqToken0: bigint | null = null\n let collateralReqToken1: bigint | null = null\n if (simulation.success) {\n const reqs = simulation.data.perPositionCollateralReqs\n if (reqs.length > 0) {\n const loanReq = reqs[reqs.length - 1]\n collateralReqToken0 = loanReq.token0\n collateralReqToken1 = loanReq.token1\n }\n }\n\n return { loanTokenId, adjustedSize, simulation, collateralReqToken0, collateralReqToken1 }\n}\n\n// ---------------------------------------------------------------------------\n// repay\n// ---------------------------------------------------------------------------\n\n/**\n * Repay a loan position (full or partial).\n *\n * - Full repay (`amount >= currentSize`): Burns the loan position entirely.\n * - Partial repay (`amount < currentSize`): Uses roll-same-tokenId pattern\n * to reduce the position size.\n *\n * @param params - Repay parameters\n * @returns TxResult\n *\n * @example\n * ```typescript\n * // Full repay\n * await repay({\n * client, walletClient, account, poolAddress,\n * chainId: 11155111n,\n * loanTokenId,\n * amount: MAX_UINT128, // repay all\n * slippageBps: 500n,\n * })\n *\n * // Partial repay\n * await repay({\n * client, walletClient, account, poolAddress,\n * chainId: 11155111n,\n * loanTokenId,\n * amount: 50n * 10n**6n, // repay 50 USDC\n * slippageBps: 500n,\n * })\n * ```\n */\nexport async function repay(params: RepayParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n loanTokenId,\n amount,\n slippageBps,\n existingPositionIds: explicitIds,\n builderCode = 0n,\n storage,\n txOverrides,\n } = params\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n const [positionIds, fullDataResult] = await Promise.all([\n resolvePositionIds(explicitIds, storage, chainId, poolAddress, account),\n client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, [loanTokenId]],\n }),\n ])\n\n // Extract positionSize from the packed PositionBalance\n const balanceRaw = fullDataResult[2][0] // positionBalances[0]\n const currentSize = balanceRaw & ((1n << 128n) - 1n)\n\n const pool = await getPool({ client, poolAddress, chainId })\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n\n // Ascending tick limits = no swap\n const ascendingLimits: readonly [number, number, number] = [\n Number(tickLimitLow),\n Number(tickLimitHigh),\n 0,\n ]\n\n if (amount >= currentSize) {\n // Full repay: burn the entire position\n const finalPositionIdList = positionIds.filter((id) => id !== loanTokenId)\n\n try {\n return await submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n [loanTokenId],\n finalPositionIdList,\n [0n], // 0n = burn all\n [ascendingLimits],\n false,\n builderCode,\n ],\n txOverrides,\n })\n } catch (error) {\n if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) {\n continue\n }\n throw error\n }\n } else {\n // Partial repay: roll-same-tokenId pattern\n // Op 1: burn current position at full size\n // Op 2: re-mint same tokenId at reduced size\n const newSize = currentSize - amount\n const finalPositionIdList = positionIds\n .filter((id) => id !== loanTokenId)\n .concat([loanTokenId])\n\n try {\n return await submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n [loanTokenId, loanTokenId],\n finalPositionIdList,\n [currentSize, newSize],\n [ascendingLimits, ascendingLimits],\n false,\n builderCode,\n ],\n txOverrides,\n })\n } catch (error) {\n if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) {\n continue\n }\n throw error\n }\n }\n }\n\n throw new MaxRetriesExceededError('repay')\n}\n\n/**\n * Repay a loan and wait for confirmation.\n * If storage is provided, auto-updates the tracked positions (removes on full repay).\n */\nexport async function repayAndWait(params: RepayParams): Promise<TxReceipt> {\n const result = await repay(params)\n const receipt = await result.wait()\n\n // Auto-update storage on full repay\n if (params.storage && params.chainId !== undefined) {\n const {\n client,\n account,\n poolAddress,\n chainId,\n loanTokenId,\n storage,\n existingPositionIds: explicitIds,\n } = params\n\n const fullDataResult = await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, [loanTokenId]],\n })\n const balanceRaw = fullDataResult[2][0] // positionBalances[0]\n const currentSize = balanceRaw & ((1n << 128n) - 1n)\n\n // Only remove if the position was fully burned\n if (currentSize === 0n) {\n const positionIds =\n explicitIds ?? (await getTrackedPositionIds({ chainId, poolAddress, account, storage }))\n await savePositionIds(\n storage,\n chainId,\n poolAddress,\n account,\n positionIds.filter((id) => id !== loanTokenId),\n )\n }\n }\n\n return receipt\n}\n\n// ---------------------------------------------------------------------------\n// smart repay\n// ---------------------------------------------------------------------------\n\n/** Parameters for smart repay (burns all loans for a token, optionally re-opens a smaller one). */\nexport interface SmartRepayParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID */\n chainId: bigint\n /** Token address to repay loans for (must be token0 or token1 of the pool) */\n token: Address\n /** Amount of token to repay */\n amount: bigint\n /** Slippage tolerance in bps (e.g. 500n = 5%) */\n slippageBps: bigint\n /** Existing position IDs (all positions, not just loans) */\n existingPositionIds: bigint[]\n /** Builder code for fee routing (0 = no builder). */\n builderCode?: bigint\n /** Gas and transaction overrides */\n txOverrides?: TxOverrides\n /** Optional storage adapter — when provided, smartRepayAndWait auto-updates tracked positions. */\n storage?: StorageAdapter\n}\n\n/**\n * Identify loan tokenIds for a specific token and return their sizes.\n */\nasync function getLoanPositionsForToken(\n client: PublicClient,\n poolAddress: Address,\n account: Address,\n existingPositionIds: bigint[],\n tokenIndex: bigint,\n): Promise<{ tokenId: bigint; positionSize: bigint; optionRatio: bigint; tokenAmount: bigint }[]> {\n const loanIds = existingPositionIds.filter((id) => {\n if (!isLoan(id)) return false\n const legs = decodeAllLegs(id)\n return legs.length > 0 && legs[0].tokenType === tokenIndex\n })\n\n if (loanIds.length === 0) return []\n\n const fullData = await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, loanIds],\n })\n\n const balances = fullData[2]\n return loanIds.map((tokenId, i) => {\n const positionSize = balances[i] & ((1n << 128n) - 1n)\n const legs = decodeAllLegs(tokenId)\n const optionRatio = legs[0].optionRatio\n // Actual token amount = positionSize * optionRatio\n const tokenAmount = positionSize * optionRatio\n return { tokenId, positionSize, optionRatio, tokenAmount }\n })\n}\n\n/**\n * Smart repay: burns all loan positions for a token and optionally re-opens a smaller one.\n *\n * Unlike `repay()` which targets a single loanTokenId, this function handles\n * multiple loans transparently. The user specifies a repay amount and the SDK:\n * 1. Finds all loan positions for the specified token\n * 2. Burns them all\n * 3. If repayAmount < totalDebt, opens a new loan for the remainder\n *\n * @param params - Smart repay parameters\n * @returns TxResult\n */\nexport async function smartRepay(params: SmartRepayParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n token,\n amount,\n slippageBps,\n existingPositionIds,\n builderCode = 0n,\n txOverrides,\n } = params\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n const pool = await getPool({ client, poolAddress, chainId })\n const tokenIndex = resolveTokenIndex(\n token,\n pool.collateralTracker0.token,\n pool.collateralTracker1.token,\n )\n\n const loans = await getLoanPositionsForToken(\n client,\n poolAddress,\n account,\n existingPositionIds,\n tokenIndex,\n )\n if (loans.length === 0) {\n throw new NoLoanPositionsError(token)\n }\n\n const totalDebt = loans.reduce((sum, l) => sum + l.tokenAmount, 0n)\n const loanIds = loans.map((l) => l.tokenId)\n const remainder = totalDebt > amount ? totalDebt - amount : 0n\n\n const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps)\n const ascendingLimits: readonly [number, number, number] = [\n Number(tickLimitLow),\n Number(tickLimitHigh),\n 0,\n ]\n\n const nonLoanIds = existingPositionIds.filter((id) => !loanIds.includes(id))\n\n const opsPositionIds: bigint[] = [...loanIds]\n const opsSizes: bigint[] = loanIds.map(() => 0n)\n const opsLimits = loanIds.map(() => ascendingLimits)\n\n let finalPositionIdList: bigint[]\n\n if (remainder > 0n) {\n const { tokenId: newLoanId, adjustedSize } = buildUniqueLoan(\n pool.poolId,\n tokenIndex,\n tokenIndex,\n pool.currentTick,\n pool.tickSpacing,\n nonLoanIds,\n remainder,\n )\n opsPositionIds.push(newLoanId)\n opsSizes.push(adjustedSize)\n opsLimits.push(ascendingLimits)\n finalPositionIdList = [...nonLoanIds, newLoanId]\n } else {\n finalPositionIdList = nonLoanIds\n }\n\n try {\n return await submitWrite({\n client,\n walletClient,\n account,\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [opsPositionIds, finalPositionIdList, opsSizes, opsLimits, false, builderCode],\n txOverrides,\n })\n } catch (error) {\n if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) {\n continue\n }\n throw error\n }\n }\n\n throw new MaxRetriesExceededError('smartRepay')\n}\n\n/**\n * Smart repay and wait for confirmation.\n */\nexport async function smartRepayAndWait(params: SmartRepayParams): Promise<TxReceipt> {\n const result = await smartRepay(params)\n const receipt = await result.wait()\n\n // Auto-update storage: remove fully-repaid loans, insert remainder loan if any\n if (params.storage && params.chainId !== undefined) {\n const { client, account, poolAddress, chainId, token, amount, storage, existingPositionIds } =\n params\n\n const pool = await getPool({ client, poolAddress, chainId })\n const tokenIndex = resolveTokenIndex(\n token,\n pool.collateralTracker0.token,\n pool.collateralTracker1.token,\n )\n\n const loans = await getLoanPositionsForToken(\n client,\n poolAddress,\n account,\n existingPositionIds,\n tokenIndex,\n )\n const loanIds = loans.map((l) => l.tokenId)\n const totalDebt = loans.reduce((sum, l) => sum + l.tokenAmount, 0n)\n const remainder = totalDebt > amount ? totalDebt - amount : 0n\n\n const positionIds =\n existingPositionIds ??\n (await getTrackedPositionIds({ chainId, poolAddress, account, storage }))\n\n // Remove all old loan IDs\n let updatedIds = positionIds.filter((id) => !loanIds.includes(id))\n\n // If there's a remainder, the contract minted a new loan — find it\n if (remainder > 0n) {\n const nonLoanIds = existingPositionIds.filter((id) => !loanIds.includes(id))\n const newLoan = buildUniqueLoan(\n pool.poolId,\n tokenIndex,\n tokenIndex,\n pool.currentTick,\n pool.tickSpacing,\n nonLoanIds,\n remainder,\n )\n updatedIds = [...updatedIds, newLoan.tokenId]\n }\n\n await savePositionIds(storage, chainId, poolAddress, account, updatedIds)\n }\n\n return receipt\n}\n"],"mappings":"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"}
|