@panoptic-eng/sdk 1.0.53 → 1.0.55
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/deployments.d.ts +8 -1
- package/dist/deployments.d.ts.map +1 -1
- package/dist/deployments.js +30 -10
- package/dist/deployments.js.map +1 -1
- package/dist/index.d.ts +277 -60
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +433 -221
- package/dist/index.js.map +1 -1
- package/dist/{irm-9az4Pqsp.js → irm-BsRdsXMS.js} +30 -10
- package/dist/panoptic/v2/index.d.ts +39 -1
- package/dist/panoptic/v2/index.d.ts.map +1 -1
- package/dist/panoptic/v2/index.js +91 -10
- package/dist/panoptic/v2/index.js.map +1 -1
- package/dist/panoptic/v2/react-public.d.ts +39 -1
- package/dist/panoptic/v2/react-public.d.ts.map +1 -1
- package/dist/panoptic/v2/react-public.js +91 -10
- package/dist/panoptic/v2/react-public.js.map +1 -1
- package/dist/uniswap/index.d.ts +80 -1
- package/dist/uniswap/index.d.ts.map +1 -1
- package/dist/uniswap/index.js +113 -1
- package/dist/uniswap/index.js.map +1 -1
- package/dist/{v2-CUv4jWCQ.js → v2-bpvC_P3W.js} +63 -2
- package/dist/zodiac/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["D","tick: number","steps: { lower: number; upper: number; up: boolean; d0: Decimal; d1: Decimal }[]","Q192","tick: bigint","message: string","cause?: Error","encodedStrike: bigint","legIndex: bigint","tokenId: bigint","legs: DecodedLeg[]","POOL_ID_MASK","Q192","MAX_UINT128","Q192","POOL_ID_MASK","MAX_UINT128","Q96","n: bigint","d: bigint","ranges: readonly LpFeeRange[]","sqrtPriceX96: bigint","params: LpPositionFundingParams","params: Omit<LpPositionFundingParams, 'positionSize'> & {\n availableInQuote: bigint\n minimumRequirement?: { referenceSize: bigint; requiredInQuote: bigint }\n }","Q96","Q192","sqrtPriceX96: bigint","sqrtRatioAX96: bigint","sqrtRatioBX96: bigint","liquidity: bigint","input: LpGreeksInput","value","delta","gamma","feeReturnPercent: Decimal","durationSeconds: bigint","validTick","tick: number","chainId: bigint","cause?: Error","token: Address","currency0: Address","currency1: Address","amount: bigint","UNISWAP_V3_ADDRESSES: Record<number, UniswapV3Addresses>","chainId: number | bigint","overrides?: Partial<UniswapV3Addresses>","MSG_SENDER: Address","UINT128_MAX","assertUint128","amount: bigint","tokenIn: Address","fee: bigint","tokenOut: Address","args: BuildV3SwapCalldataArgs","args: BuildV3ExactOutSwapCalldataArgs","BPS_DENOMINATOR","UINT128_MAX","params: QuoteV3ExactInParams","params: QuoteV3ExactOutParams","assertSlippageBps","slippageBps: bigint","isRevert","err: unknown","params: GetBlockMetaParams","erc20Abi","params: GetPoolMetadataParams","underlyingPoolId: string","fee: bigint","tickSpacing: bigint","params: GetPoolParams","vegoid","SECONDS_PER_YEAR","collateralTracker0: CollateralTracker","collateralTracker1: CollateralTracker","riskEngine: RiskEngine","poolId: bigint","poolKeyBytes: `0x${string}`","params: ResolveV3SwapRouteParams","FALLBACK_META","params: QuoteSwapExactInViaV3RouterParams","params: QuoteSwapExactOutViaV3RouterParams","balanceData: bigint","value: bigint","logs: Log[]","events: PanopticEvent[]","client: PublicClient","hash: Hash","confirmations?: bigint","params: SubmitWriteParams","hash","gasOverrides: Record<string, unknown>","PERMIT2_ADDRESS: Address","UNISWAP_V4_ADDRESSES: Record<number, UniswapV4Addresses>","chainId: bigint","overrides?: Partial<UniswapV4Addresses>","merged: Partial<UniswapV4Addresses>","DEFAULT_DEADLINE_SECONDS","params: SwapExactInViaV3RouterParams","params: SwapExactOutViaV3RouterParams","UINT128_MAX","amount: bigint","recipient: Address","tokenOut: Address","recipient: Address | undefined","nativeAmount: bigint","erc20Amount: bigint","args: BuildV4SwapCalldataArgs","args: BuildV4ExactOutSwapCalldataArgs","commandList: number[]","inputs: Hex[]","Q96","BIT_MASK_128","params: CheckRouterApprovalParams","params: ApproveErc20ForPermit2Params","params: ApproveRouterViaPermit2Params","params: ResolveSwapRouteParams","BPS_DENOMINATOR","UINT128_MAX","slippageBps: bigint","params: QuoteSwapExactInViaRouterParams","params: QuoteSwapExactOutViaRouterParams","params: QuoteV4ExactInByPoolKeyParams","err: unknown","params: SwapExactInViaRouterParams","params: SwapExactOutViaRouterParams"],"sources":["../../src/uniswap/estimateLpFees.ts","../../src/panoptic/v2/utils/constants.ts","../../src/panoptic/v2/formatters/tick.ts","../../src/panoptic/v2/errors/base.ts","../../src/generated.ts","../../src/panoptic/v2/errors/errorsAbi.ts","../../src/panoptic/v2/errors/parser.ts","../../src/panoptic/v2/tokenId/constants.ts","../../src/panoptic/v2/tokenId/encoding.ts","../../src/panoptic/v2/tokenId/deriveUniqueTokenId.ts","../../src/panoptic/v2/formatters/rates.ts","../../src/panoptic/v2/tokenId/generateOverlapping.ts","../../src/panoptic/v2/tokenId/split.ts","../../src/uniswap/lpDeposit.ts","../../src/uniswap/lpGreeks.ts","../../src/uniswap/lpFeeReturn.ts","../../src/uniswap/v4/router/errors.ts","../../src/uniswap/v3/addresses.ts","../../src/uniswap/v4/abis/universalRouter.ts","../../src/uniswap/v3/router/encodeSwap.ts","../../src/uniswap/v3/abis/quoterV2.ts","../../src/uniswap/v3/router/quote.ts","../../src/panoptic/v2/clients/blockMeta.ts","../../src/panoptic/v2/abis/stateView.ts","../../src/panoptic/v2/abis/uniswapV3Pool.ts","../../src/panoptic/v2/utils/oraclePack.ts","../../src/panoptic/v2/utils/oracleSafeMode.ts","../../src/panoptic/v2/reads/pool.ts","../../src/uniswap/v3/router/resolveRoute.ts","../../src/uniswap/v3/router/quoteViaRouter.ts","../../src/panoptic/v2/writes/utils.ts","../../src/uniswap/v4/addresses.ts","../../src/uniswap/v3/router/swap.ts","../../src/uniswap/v4/router/encodeSwap.ts","../../src/panoptic/v2/sync/snapshotRecovery.ts","../../src/panoptic/v2/greeks/index.ts","../../src/panoptic/v2/utils/option-encoding-v2.ts","../../src/panoptic/v2/sync/eventReconstruction.ts","../../src/panoptic/v2/writes/protectedSettle.ts","../../src/panoptic/v2/reads/positionSizes.ts","../../src/panoptic/v2/simulations/tokenFlow.ts","../../src/panoptic/v2/simulations/simulateSettle.ts","../../src/uniswap/v4/abis/permit2.ts","../../src/uniswap/v4/router/permit2.ts","../../src/uniswap/v4/abis/v4Quoter.ts","../../src/uniswap/v4/router/resolvePoolKey.ts","../../src/uniswap/v4/router/quote.ts","../../src/uniswap/v4/router/quoteByPoolKey.ts","../../src/uniswap/v4/router/swap.ts"],"sourcesContent":["import Decimal from 'decimal.js'\n\n// Keep precision local: do not change the caller's Decimal configuration.\nconst D = Decimal.clone({ precision: 60 })\n\nexport interface LpFeeCandle {\n t: number\n o: number\n h: number\n l: number\n c: number\n /** Absolute swap volume (inputs + outputs), in raw token units. */\n v0: string\n v1: string\n /** Historical active liquidity at the candle close, when available. */\n liq?: string\n}\n\nexport interface LpFeeRange {\n tickLower: number\n tickUpper: number\n liquidity: bigint\n}\n\nconst validTick = (tick: number) => Number.isInteger(tick) && Math.abs(tick) <= 887272\n\n/**\n * Hypothetical added LP liquidity, with no compounding or price impact. Fees are raw\n * token units. Bullish candles follow O→L→H→C; bearish candles O→H→L→C.\n * Uniswap v3 deltas distribute absolute volume between inputs and outputs; only\n * inputs pay fees. Split moves at every LP boundary, so overlapping ranges share\n * the same denominator and out-of-range portions earn nothing.\n *\n * Closing historical liquidity approximates liquidity throughout a candle. If\n * absent, infer it from volume / path deltas. Flat candles with volume use equal\n * buy/sell flow and require historical liquidity; otherwise report them skipped.\n * OHLC cannot recover unseen oscillations, exact swap ordering or liquidity changes.\n */\nexport function estimateLpFees({\n candles,\n ranges,\n feePips,\n}: {\n candles: readonly LpFeeCandle[]\n ranges: readonly LpFeeRange[]\n feePips: bigint\n}) {\n if (feePips < 0n || feePips >= 1_000_000n) throw new Error('Invalid swap fee')\n for (const range of ranges) {\n if (\n !validTick(range.tickLower) ||\n !validTick(range.tickUpper) ||\n range.tickLower >= range.tickUpper ||\n range.liquidity < 0n\n ) {\n throw new Error('Invalid LP range')\n }\n }\n const fee = new D(feePips.toString()).div(1_000_000)\n const net = new D(1).minus(fee)\n const sqrtCache = new Map<number, Decimal>()\n const sqrtAt = (tick: number) => {\n const cached = sqrtCache.get(tick)\n if (cached) return cached\n const sqrt = new D('1.0001').pow(new D(tick).div(2))\n sqrtCache.set(tick, sqrt)\n return sqrt\n }\n const positions = ranges.map((r) => ({ ...r, liquidity: new D(r.liquidity.toString()) }))\n let fees0 = new D(0)\n let fees1 = new D(0)\n let skippedCandles = 0\n let inferredCandles = 0\n let previousTime = -Infinity\n const points = candles.map((candle) => {\n const { o, h, l, c, t } = candle\n if (\n !Number.isSafeInteger(t) ||\n t <= previousTime ||\n ![o, h, l, c].every(validTick) ||\n l > Math.min(o, c) ||\n h < Math.max(o, c) ||\n l > h\n ) {\n throw new Error('Invalid or unordered OHLC candles')\n }\n previousTime = t\n const v0 = new D(candle.v0)\n const v1 = new D(candle.v1)\n const historical = new D(candle.liq ?? '0')\n if (![v0, v1, historical].every((v) => v.isFinite() && v.isInteger() && v.gte(0))) {\n throw new Error('Invalid candle volume or liquidity')\n }\n const path = c >= o ? [o, l, h, c] : [o, h, l, c]\n const steps: { lower: number; upper: number; up: boolean; d0: Decimal; d1: Decimal }[] = []\n for (let i = 1; i < path.length; i++) {\n const from = path[i - 1]\n const to = path[i]\n if (from === undefined || to === undefined || from === to) continue\n const lower = Math.min(from, to)\n const upper = Math.max(from, to)\n const cuts = [\n ...new Set([lower, upper, ...positions.flatMap((p) => [p.tickLower, p.tickUpper])]),\n ]\n .filter((tick) => tick >= lower && tick <= upper)\n .sort((a, b) => a - b)\n for (let j = 1; j < cuts.length; j++) {\n const a = cuts[j - 1]\n const b = cuts[j]\n if (a === undefined || b === undefined) continue\n const sa = sqrtAt(a)\n const sb = sqrtAt(b)\n steps.push({\n lower: a,\n upper: b,\n up: to > from,\n d0: new D(1).div(sa).minus(new D(1).div(sb)),\n d1: sb.minus(sa),\n })\n }\n }\n const total0 = steps.reduce((sum, s) => sum.plus(s.up ? s.d0 : s.d0.div(net)), new D(0))\n const total1 = steps.reduce((sum, s) => sum.plus(s.up ? s.d1.div(net) : s.d1), new D(0))\n const hasVolume = v0.gt(0) || v1.gt(0)\n const inferred =\n total0.gt(0) && total1.gt(0) ? v0.div(total0).plus(v1.div(total1)).div(2) : new D(0)\n const poolLiquidity = historical.gt(0) ? historical : inferred\n if (hasVolume && poolLiquidity.eq(0)) skippedCandles++\n else if (hasVolume && fee.gt(0)) {\n if (historical.eq(0)) inferredCandles++\n if (steps.length === 0) {\n const active = positions\n .filter((p) => p.tickLower <= c && c < p.tickUpper)\n .reduce((sum, p) => sum.plus(p.liquidity), new D(0))\n const share = active.div(poolLiquidity.plus(active))\n // Absolute volume counts both sides; equal directional flow implies\n // input fraction 1 / (2 - fee), including fees in gross inputs.\n fees0 = fees0.plus(v0.div(new D(2).minus(fee)).mul(fee).mul(share))\n fees1 = fees1.plus(v1.div(new D(2).minus(fee)).mul(fee).mul(share))\n } else {\n for (const step of steps) {\n const active = positions\n .filter((p) => p.tickLower <= step.lower && p.tickUpper >= step.upper)\n .reduce((sum, p) => sum.plus(p.liquidity), new D(0))\n const share = active.div(poolLiquidity.plus(active))\n if (step.up) fees1 = fees1.plus(v1.mul(step.d1.div(net)).div(total1).mul(fee).mul(share))\n else fees0 = fees0.plus(v0.mul(step.d0.div(net)).div(total0).mul(fee).mul(share))\n }\n }\n }\n return {\n time: t,\n fees0: BigInt(fees0.floor().toFixed(0)),\n fees1: BigInt(fees1.floor().toFixed(0)),\n }\n })\n return { points, skippedCandles, inferredCandles }\n}\n","/**\n * Constants for the Panoptic v2 SDK.\n * @module v2/utils/constants\n */\n\n/**\n * WAD constant (10^18) used for fixed-point arithmetic.\n * Commonly used for spread calculations and other WAD-scaled values.\n */\nexport const WAD = 10n ** 18n\n\n/**\n * Zero collateral object for guest mode.\n * Returns safe defaults when no wallet is connected.\n */\nexport const ZERO_COLLATERAL = {\n token0: {\n assets: 0n,\n shares: 0n,\n availableAssets: 0n,\n lockedAssets: 0n,\n },\n token1: {\n assets: 0n,\n shares: 0n,\n availableAssets: 0n,\n lockedAssets: 0n,\n },\n} as const\n\n/**\n * Zero valuation object for guest mode.\n * Returns safe defaults when no wallet is connected.\n */\nexport const ZERO_VALUATION = {\n netLiquidationValue0: 0n,\n netLiquidationValue1: 0n,\n maintenanceMargin0: 0n,\n maintenanceMargin1: 0n,\n marginExcess0: 0n,\n marginExcess1: 0n,\n} as const\n\n/**\n * Storage schema version for the SDK.\n * Increment when storage format changes (triggers migration or clear).\n */\nexport const SCHEMA_VERSION = 1\n\n/**\n * Storage key prefix for all SDK data.\n */\nexport const STORAGE_PREFIX = 'panoptic-v2-sdk'\n\n/**\n * Maximum number of chunks that can be tracked per pool.\n * Exceeding this limit throws ChunkLimitError.\n */\nexport const MAX_TRACKED_CHUNKS = 1000\n\n/**\n * Default reorg depth for chain reorganization handling.\n * On reorg detection, rollback this many blocks and re-sync.\n */\nexport const REORG_DEPTH = 128n\n\n/**\n * Oracle epoch duration in seconds (64 seconds per epoch).\n */\nexport const ORACLE_EPOCH_SECONDS = 64n\n\n/**\n * Minimum tick value for Uniswap v3/v4 pools.\n */\nexport const MIN_TICK = -887272n\n\n/**\n * Maximum tick value for Uniswap v3/v4 pools.\n */\nexport const MAX_TICK = 887272n\n\n/**\n * PanopticQuery sentinel indicating that no lower liquidation boundary exists.\n * This is int24.min, not Uniswap's minimum usable tick.\n */\nexport const NO_LOWER_LIQUIDATION_TICK = -(1n << 23n)\n\n/**\n * PanopticQuery sentinel indicating that no upper liquidation boundary exists.\n * This is int24.max, not Uniswap's maximum usable tick.\n */\nexport const NO_UPPER_LIQUIDATION_TICK = (1n << 23n) - 1n\n\n/**\n * Basis points denominator (100% = 10000 bps).\n */\nexport const BPS_DENOMINATOR = 10000n\n\n/**\n * Utilization denominator (100% = 10000).\n */\nexport const UTILIZATION_DENOMINATOR = 10000n\n","/**\n * Tick and price formatters for Uniswap V3/V4 pools.\n *\n * Ticks represent logarithmic prices where: price = 1.0001^tick\n *\n * @module v2/formatters/tick\n */\n\nimport { MAX_TICK, MIN_TICK } from '../utils/constants'\n\nconst Q192 = 1n << 192n\nconst RAW_PRICE_PRECISION = 40n\n\nfunction pow10(exponent: bigint): bigint {\n if (exponent < 0n) {\n throw new RangeError('Exponent must be non-negative')\n }\n return 10n ** exponent\n}\n\nfunction absBigint(value: bigint): bigint {\n return value < 0n ? -value : value\n}\n\nfunction trimTrailingZeros(value: string): string {\n const dotIndex = value.indexOf('.')\n if (dotIndex === -1) return value\n\n let end = value.length\n while (end > dotIndex && value[end - 1] === '0') {\n end -= 1\n }\n\n if (end === dotIndex + 1) {\n end = dotIndex\n }\n\n return value.slice(0, end)\n}\n\nfunction formatRatio(numerator: bigint, denominator: bigint, precision: bigint): string {\n if (precision < 0n) {\n throw new RangeError('Precision must be non-negative')\n }\n\n const sign = numerator < 0n ? '-' : ''\n const absNumerator = numerator < 0n ? -numerator : numerator\n\n const scale = pow10(precision)\n const scaled = (absNumerator * scale + denominator / 2n) / denominator\n const integerPart = scaled / scale\n const fractionalPart = scaled % scale\n\n if (precision === 0n) {\n return `${sign}${integerPart}`\n }\n\n return `${sign}${integerPart}.${fractionalPart.toString().padStart(Number(precision), '0')}`\n}\n\nfunction parseDecimalToFraction(value: string): { numerator: bigint; denominator: bigint } {\n const trimmed = value.trim()\n if (trimmed.length === 0) {\n throw new Error('Price must be a number')\n }\n\n const isNegative = trimmed.startsWith('-')\n const unsigned = isNegative || trimmed.startsWith('+') ? trimmed.slice(1) : trimmed\n\n const [basePart, exponentPart] = unsigned.toLowerCase().split('e')\n const [integerStr, fractionalStr = ''] = basePart.split('.')\n\n if (integerStr === '' && fractionalStr === '') {\n throw new Error('Price must be a number')\n }\n\n const integerDigits = integerStr === '' ? '0' : integerStr\n const digits = `${integerDigits}${fractionalStr}`\n\n let numerator = BigInt(digits === '' ? '0' : digits)\n let denominator = pow10(BigInt(fractionalStr.length))\n\n if (exponentPart !== undefined && exponentPart !== '') {\n const exponent = BigInt(exponentPart)\n if (exponent > 0n) {\n numerator *= pow10(exponent)\n } else if (exponent < 0n) {\n denominator *= pow10(-exponent)\n }\n }\n\n if (isNegative) {\n numerator = -numerator\n }\n\n return { numerator, denominator }\n}\n\nfunction compareRatios(\n leftNumerator: bigint,\n leftDenominator: bigint,\n rightNumerator: bigint,\n rightDenominator: bigint,\n): -1 | 0 | 1 {\n const left = leftNumerator * rightDenominator\n const right = rightNumerator * leftDenominator\n\n if (left === right) return 0\n return left < right ? -1 : 1\n}\n\nexport function tickToSqrtPriceX96(tick: bigint): bigint {\n if (tick < MIN_TICK || tick > MAX_TICK) {\n throw new RangeError('Tick out of bounds')\n }\n\n const absTick = tick < 0n ? -tick : tick\n\n let ratio =\n (absTick & 0x1n) !== 0n\n ? 0xfffcb933bd6fad37aa2d162d1a594001n\n : 0x100000000000000000000000000000000n\n if ((absTick & 0x2n) !== 0n) ratio = (ratio * 0xfff97272373d413259a46990580e213an) >> 128n\n if ((absTick & 0x4n) !== 0n) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdccn) >> 128n\n if ((absTick & 0x8n) !== 0n) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0n) >> 128n\n if ((absTick & 0x10n) !== 0n) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644n) >> 128n\n if ((absTick & 0x20n) !== 0n) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0n) >> 128n\n if ((absTick & 0x40n) !== 0n) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861n) >> 128n\n if ((absTick & 0x80n) !== 0n) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053n) >> 128n\n if ((absTick & 0x100n) !== 0n) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4n) >> 128n\n if ((absTick & 0x200n) !== 0n) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54n) >> 128n\n if ((absTick & 0x400n) !== 0n) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3n) >> 128n\n if ((absTick & 0x800n) !== 0n) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9n) >> 128n\n if ((absTick & 0x1000n) !== 0n) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825n) >> 128n\n if ((absTick & 0x2000n) !== 0n) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5n) >> 128n\n if ((absTick & 0x4000n) !== 0n) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7n) >> 128n\n if ((absTick & 0x8000n) !== 0n) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6n) >> 128n\n if ((absTick & 0x10000n) !== 0n) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9n) >> 128n\n if ((absTick & 0x20000n) !== 0n) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604n) >> 128n\n if ((absTick & 0x40000n) !== 0n) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98n) >> 128n\n if ((absTick & 0x80000n) !== 0n) ratio = (ratio * 0x48a170391f7dc42444e8fa2n) >> 128n\n\n if (tick > 0n) {\n ratio = ((1n << 256n) - 1n) / ratio\n }\n\n const remainderMask = (1n << 32n) - 1n\n const sqrtPriceX96 = (ratio >> 32n) + ((ratio & remainderMask) === 0n ? 0n : 1n)\n\n return sqrtPriceX96\n}\n\nconst MIN_SQRT_PRICE_X96 = tickToSqrtPriceX96(MIN_TICK)\nconst MAX_SQRT_PRICE_X96 = tickToSqrtPriceX96(MAX_TICK)\n\nfunction getPriceRatioFromSqrtPriceX96(sqrtPriceX96: bigint): {\n numerator: bigint\n denominator: bigint\n} {\n return {\n numerator: sqrtPriceX96 * sqrtPriceX96,\n denominator: Q192,\n }\n}\n\nfunction getRawPriceRatio(tick: bigint): { numerator: bigint; denominator: bigint } {\n return getPriceRatioFromSqrtPriceX96(tickToSqrtPriceX96(tick))\n}\n\nfunction adjustRatioForDecimals(\n numerator: bigint,\n denominator: bigint,\n decimals0: bigint,\n decimals1: bigint,\n): { numerator: bigint; denominator: bigint } {\n const diff = decimals0 - decimals1\n if (diff === 0n) {\n return { numerator, denominator }\n }\n\n if (diff > 0n) {\n return { numerator: numerator * pow10(diff), denominator }\n }\n\n return { numerator, denominator: denominator * pow10(-diff) }\n}\n\n/**\n * Convert a tick to a raw price string (no decimal adjustment).\n * Uses the formula: price = 1.0001^tick\n *\n * This returns the raw price ratio, not adjusted for token decimals.\n * A fixed internal precision is used and trailing zeros are trimmed.\n *\n * @param tick - The tick value\n * @returns Price string\n *\n * @example\n * ```typescript\n * tickToPrice(0n) // \"1\"\n * tickToPrice(1000n) // \"1.105...\" (approximately)\n * tickToPrice(-1000n) // \"0.904...\" (approximately)\n * tickToPrice(200000n) // Very large number\n * ```\n */\nexport function tickToPrice(tick: bigint): string {\n const { numerator, denominator } = getRawPriceRatio(tick)\n const price = formatRatio(numerator, denominator, RAW_PRICE_PRECISION)\n return trimTrailingZeros(price)\n}\n\n/**\n * Convert a tick to a human-readable price with decimal scaling.\n * Uses the formula: price = 1.0001^tick * 10^(decimals0-decimals1)\n *\n * This adjusts for the different decimals of the two tokens in the pair.\n *\n * @param tick - The tick value\n * @param decimals0 - Decimals of token0\n * @param decimals1 - Decimals of token1\n * @param precision - Number of decimal places to display\n * @returns Formatted price string\n *\n * @example\n * ```typescript\n * // WETH/USDC pool (18 decimals / 6 decimals)\n * // At tick ~200000, price is roughly $2000 per ETH\n * tickToPriceDecimalScaled(200000n, 18n, 6n, 2n) // \"2000.00\" (approximately)\n *\n * // For token1/token0 price, swap the decimals\n * tickToPriceDecimalScaled(200000n, 6n, 18n, 6n) // \"0.000500\" (approximately)\n * ```\n */\nexport function tickToPriceDecimalScaled(\n tick: bigint,\n decimals0: bigint,\n decimals1: bigint,\n precision: bigint,\n): string {\n const rawRatio = getRawPriceRatio(tick)\n const { numerator, denominator } = adjustRatioForDecimals(\n rawRatio.numerator,\n rawRatio.denominator,\n decimals0,\n decimals1,\n )\n\n return formatRatio(numerator, denominator, precision)\n}\n\n/**\n * Convert a sqrtPriceX96 to a human-readable price with decimal scaling.\n *\n * Uses the formula: price = (sqrtPriceX96^2 / 2^192) * 10^(decimals0-decimals1)\n *\n * @param sqrtPriceX96 - The sqrt price in Q64.96 format\n * @param decimals0 - Decimals of token0\n * @param decimals1 - Decimals of token1\n * @param precision - Number of decimal places to display\n * @returns Formatted price string\n *\n * @example\n * ```typescript\n * sqrtPriceX96ToPriceDecimalScaled(2n ** 96n, 18n, 18n, 2n) // \"1.00\"\n * ```\n */\nexport function sqrtPriceX96ToPriceDecimalScaled(\n sqrtPriceX96: bigint,\n decimals0: bigint,\n decimals1: bigint,\n precision: bigint,\n): string {\n const rawRatio = getPriceRatioFromSqrtPriceX96(sqrtPriceX96)\n const { numerator, denominator } = adjustRatioForDecimals(\n rawRatio.numerator,\n rawRatio.denominator,\n decimals0,\n decimals1,\n )\n\n return formatRatio(numerator, denominator, precision)\n}\n\n/**\n * Convert a price to a tick value.\n *\n * @param price - The price string\n * @param decimals0 - Decimals of token0\n * @param decimals1 - Decimals of token1\n * @returns The tick value (rounded to nearest integer)\n *\n * @example\n * ```typescript\n * // WETH/USDC: What tick for $2000 per ETH?\n * priceToTick(\"2000\", 18n, 6n) // ~200000n\n *\n * // Inverse: What tick for 0.0005 ETH per USDC?\n * priceToTick(\"0.0005\", 6n, 18n) // ~200000n\n * ```\n */\nexport function priceToTick(price: string, decimals0: bigint, decimals1: bigint): bigint {\n const parsed = parseDecimalToFraction(price)\n if (parsed.numerator <= 0n) {\n throw new Error('Price must be positive')\n }\n\n let targetNumerator = parsed.numerator\n let targetDenominator = parsed.denominator\n\n const diff = decimals0 - decimals1\n if (diff > 0n) {\n targetDenominator *= pow10(diff)\n } else if (diff < 0n) {\n targetNumerator *= pow10(-diff)\n }\n\n let low = MIN_TICK\n let high = MAX_TICK\n\n while (low <= high) {\n const mid = (low + high) / 2n\n const { numerator, denominator } = getRawPriceRatio(mid)\n const cmp = compareRatios(numerator, denominator, targetNumerator, targetDenominator)\n\n if (cmp === 0) {\n return mid\n }\n\n if (cmp < 0) {\n low = mid + 1n\n } else {\n high = mid - 1n\n }\n }\n\n const floorTick = high\n const ceilTick = low\n\n if (floorTick < MIN_TICK) return MIN_TICK\n if (ceilTick > MAX_TICK) return MAX_TICK\n\n const floorRatio = getRawPriceRatio(floorTick)\n const ceilRatio = getRawPriceRatio(ceilTick)\n\n const floorDiffNumerator = absBigint(\n targetNumerator * floorRatio.denominator - floorRatio.numerator * targetDenominator,\n )\n const ceilDiffNumerator = absBigint(\n targetNumerator * ceilRatio.denominator - ceilRatio.numerator * targetDenominator,\n )\n const floorDiffDenominator = targetDenominator * floorRatio.denominator\n const ceilDiffDenominator = targetDenominator * ceilRatio.denominator\n\n return floorDiffNumerator * ceilDiffDenominator <= ceilDiffNumerator * floorDiffDenominator\n ? floorTick\n : ceilTick\n}\n\n/**\n * Convert a sqrtPriceX96 value to the nearest tick.\n *\n * @param sqrtPriceX96 - The sqrt price in Q64.96 format\n * @returns The tick value (rounded to nearest integer)\n *\n * @example\n * ```typescript\n * const tick = sqrtPriceX96ToTick(2n ** 96n) // 0n\n * ```\n */\nexport function sqrtPriceX96ToTick(sqrtPriceX96: bigint): bigint {\n if (sqrtPriceX96 <= 0n) {\n throw new Error('Sqrt price must be positive')\n }\n\n if (sqrtPriceX96 < MIN_SQRT_PRICE_X96 || sqrtPriceX96 > MAX_SQRT_PRICE_X96) {\n throw new RangeError('Sqrt price out of bounds')\n }\n\n let low = MIN_TICK\n let high = MAX_TICK\n\n while (low <= high) {\n const mid = (low + high) / 2n\n const midSqrt = tickToSqrtPriceX96(mid)\n\n if (midSqrt === sqrtPriceX96) {\n return mid\n }\n\n if (midSqrt < sqrtPriceX96) {\n low = mid + 1n\n } else {\n high = mid - 1n\n }\n }\n\n const floorTick = high\n const ceilTick = low\n\n if (floorTick < MIN_TICK) return MIN_TICK\n if (ceilTick > MAX_TICK) return MAX_TICK\n\n const floorSqrt = tickToSqrtPriceX96(floorTick)\n const ceilSqrt = tickToSqrtPriceX96(ceilTick)\n\n const floorDiff = absBigint(sqrtPriceX96 - floorSqrt)\n const ceilDiff = absBigint(ceilSqrt - sqrtPriceX96)\n\n return floorDiff <= ceilDiff ? floorTick : ceilTick\n}\n\n/**\n * Format a tick value for display.\n *\n * @param tick - The tick value\n * @returns Formatted tick string\n *\n * @example\n * ```typescript\n * formatTick(200000n) // \"200000\"\n * formatTick(-50000n) // \"-50000\"\n * ```\n */\nexport function formatTick(tick: bigint): string {\n return tick.toString()\n}\n\n/**\n * Get the price at a specific tick, returning both token0/token1 and token1/token0 prices.\n *\n * @param tick - The tick value\n * @param decimals0 - Decimals of token0\n * @param decimals1 - Decimals of token1\n * @param precision - Number of decimal places to display\n * @returns Object with both price directions\n *\n * @example\n * ```typescript\n * const prices = getPricesAtTick(200000n, 18n, 6n, 2n)\n * // prices.token0PerToken1 = \"0.00\" (very small)\n * // prices.token1PerToken0 = \"2000.00\" (USDC per ETH)\n * ```\n */\nexport function getPricesAtTick(\n tick: bigint,\n decimals0: bigint,\n decimals1: bigint,\n precision: bigint,\n): { token0PerToken1: string; token1PerToken0: string } {\n const rawRatio = getRawPriceRatio(tick)\n const adjustedRatio = adjustRatioForDecimals(\n rawRatio.numerator,\n rawRatio.denominator,\n decimals0,\n decimals1,\n )\n\n return {\n token0PerToken1: formatRatio(adjustedRatio.denominator, adjustedRatio.numerator, precision),\n token1PerToken0: formatRatio(adjustedRatio.numerator, adjustedRatio.denominator, precision),\n }\n}\n\n/**\n * Format a tick range for display.\n *\n * @param tickLower - Lower tick\n * @param tickUpper - Upper tick\n * @returns Formatted tick range string\n *\n * @example\n * ```typescript\n * formatTickRange(-50000n, 200000n) // \"-50000 - 200000\"\n * ```\n */\nexport function formatTickRange(tickLower: bigint, tickUpper: bigint): string {\n return `${tickLower} - ${tickUpper}`\n}\n\n/**\n * Format a price range for display.\n *\n * @param tickLower - Lower tick\n * @param tickUpper - Upper tick\n * @param decimals0 - Decimals of token0\n * @param decimals1 - Decimals of token1\n * @param precision - Number of decimal places to display\n * @returns Formatted price range string\n *\n * @example\n * ```typescript\n * formatPriceRange(0n, 0n, 18n, 18n, 2n) // \"1.00 - 1.00\"\n * ```\n */\nexport function formatPriceRange(\n tickLower: bigint,\n tickUpper: bigint,\n decimals0: bigint,\n decimals1: bigint,\n precision: bigint,\n): string {\n const lower = tickToPriceDecimalScaled(tickLower, decimals0, decimals1, precision)\n const upper = tickToPriceDecimalScaled(tickUpper, decimals0, decimals1, precision)\n return `${lower} - ${upper}`\n}\n\n/**\n * Calculate the tick spacing for a given fee tier.\n *\n * @param feeBps - Fee in basis points (e.g., 500n for 0.05%)\n * @returns Tick spacing\n *\n * @example\n * ```typescript\n * getTickSpacing(100n) // 1n (0.01% fee tier)\n * getTickSpacing(500n) // 10n (0.05% fee tier)\n * getTickSpacing(3000n) // 60n (0.30% fee tier)\n * getTickSpacing(10000n) // 200n (1.00% fee tier)\n * ```\n */\nexport function getTickSpacing(feeBps: bigint): bigint {\n // Standard Uniswap V3 tick spacings\n switch (feeBps) {\n case 100n:\n return 1n\n case 500n:\n return 10n\n case 3000n:\n return 60n\n case 10000n:\n return 200n\n default: {\n const spacing = feeBps / 50n\n return spacing > 1n ? spacing : 1n\n }\n }\n}\n\n/**\n * Round a tick to the nearest valid tick for a given tick spacing.\n *\n * @param tick - The tick to round\n * @param tickSpacing - The tick spacing\n * @returns Rounded tick\n *\n * @example\n * ```typescript\n * roundToTickSpacing(12345n, 10n) // 12340n\n * roundToTickSpacing(12345n, 60n) // 12360n\n * roundToTickSpacing(-12345n, 10n) // -12350n\n * ```\n */\nexport function roundToTickSpacing(tick: bigint, tickSpacing: bigint): bigint {\n const remainder = tick % tickSpacing\n if (remainder === 0n) {\n return tick\n }\n // Round to nearest\n if (tick >= 0n) {\n return remainder >= tickSpacing / 2n ? tick + (tickSpacing - remainder) : tick - remainder\n }\n\n const absRemainder = -remainder\n return absRemainder >= tickSpacing / 2n\n ? tick - (tickSpacing - absRemainder)\n : tick + absRemainder\n}\n\n/**\n * Result of {@link tickLimits}.\n */\nexport interface TickLimitsResult {\n /** Lower tick limit (clamped to MIN_TICK). */\n low: bigint\n /** Upper tick limit (clamped to MAX_TICK). */\n high: bigint\n}\n\n/**\n * Compute slippage-bounded tick limits around the current tick.\n *\n * 1 tick ≈ 1 basis point (0.01 %) of price change, so a `toleranceBps`\n * of 500 allows roughly 5 % price movement. The result is clamped to\n * the protocol's `[MIN_TICK, MAX_TICK]` range.\n *\n * Useful for setting `tickLimitLow` / `tickLimitHigh` on `openPosition`\n * and `closePosition` to protect against MEV sandwiches and volatile\n * tick moves.\n *\n * @param currentTick - The current pool tick (must be within [MIN_TICK, MAX_TICK]).\n * @param toleranceBps - Slippage tolerance in basis points (≈ ticks). Must be non-negative.\n * @returns Clamped `{ low, high }` tick limits.\n * @throws {RangeError} If `toleranceBps` is negative or `currentTick` is out of bounds.\n *\n * @example\n * ```typescript\n * const { low, high } = tickLimits(200_000n, 500n)\n * // low = 199_500n\n * // high = 200_500n\n *\n * await openPosition({ ..., tickLimitLow: low, tickLimitHigh: high })\n * ```\n */\nexport function tickLimits(currentTick: bigint, toleranceBps: bigint): TickLimitsResult {\n if (toleranceBps < 0n) {\n throw new RangeError(`toleranceBps must be non-negative, got ${toleranceBps}`)\n }\n if (currentTick < MIN_TICK || currentTick > MAX_TICK) {\n throw new RangeError(`currentTick ${currentTick} is out of bounds [${MIN_TICK}, ${MAX_TICK}]`)\n }\n\n const rawLow = currentTick - toleranceBps\n const rawHigh = currentTick + toleranceBps\n const low = rawLow < MIN_TICK ? MIN_TICK : rawLow\n const high = rawHigh > MAX_TICK ? MAX_TICK : rawHigh\n\n if (low > high) {\n throw new RangeError(\n `Computed tick limits are inverted: low ${low} > high ${high} (currentTick=${currentTick}, toleranceBps=${toleranceBps})`,\n )\n }\n\n return { low, high }\n}\n","/**\n * Base error class for the Panoptic v2 SDK.\n * @module v2/errors/base\n */\n\n/**\n * Base error class for all Panoptic SDK errors.\n * All errors thrown by the SDK extend this class.\n *\n * @example\n * ```typescript\n * try {\n * await openPosition(config, params)\n * } catch (error) {\n * if (error instanceof PanopticError) {\n * console.log('Panoptic error:', error.name, error.message)\n * console.log('Original cause:', error.cause)\n * }\n * }\n * ```\n */\nexport class PanopticError extends Error {\n override readonly name: string = 'PanopticError'\n\n /** The Solidity error name (e.g. 'PriceBoundFail', 'InputListFail'). Set by the parser. */\n errorName?: string\n\n /**\n * Creates a new PanopticError.\n *\n * @param message - Human-readable error message\n * @param cause - Optional underlying error that caused this error\n */\n constructor(\n message: string,\n public readonly cause?: Error,\n ) {\n super(message)\n\n // Maintains proper stack trace for where error was thrown (V8 only)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor)\n }\n\n // Ensure prototype chain is correctly set up\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\n","//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// CollateralTrackerV2\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const collateralTrackerV2Abi = [\n { type: 'constructor', inputs: [], stateMutability: 'nonpayable' },\n {\n type: 'function',\n inputs: [],\n name: 'accrueInterest',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'spender', internalType: 'address', type: 'address' },\n ],\n name: 'allowance',\n outputs: [{ name: 'allowance', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'spender', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'approve',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'asset',\n outputs: [{ name: 'assetTokenAddress', internalType: 'address', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'assetsAndInterest',\n outputs: [\n { name: '', internalType: 'uint256', type: 'uint256' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'assetsOf',\n outputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'account', internalType: 'address', type: 'address' }],\n name: 'balanceOf',\n outputs: [{ name: 'balance', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'borrowIndex',\n outputs: [{ name: '', internalType: 'uint80', type: 'uint80' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n name: 'convertToAssets',\n outputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n name: 'convertToShares',\n outputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'decimals',\n outputs: [{ name: '', internalType: 'uint8', type: 'uint8' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'delegatee', internalType: 'address', type: 'address' }],\n name: 'delegate',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'assets', internalType: 'uint256', type: 'uint256' },\n { name: 'receiver', internalType: 'address', type: 'address' },\n ],\n name: 'deposit',\n outputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'getPoolData',\n outputs: [\n { name: 'depositedAssets', internalType: 'uint256', type: 'uint256' },\n { name: 'insideAMM', internalType: 'uint256', type: 'uint256' },\n { name: 'creditedShares', internalType: 'uint256', type: 'uint256' },\n {\n name: 'currentPoolUtilization',\n internalType: 'uint256',\n type: 'uint256',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'initialize',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'interestRate',\n outputs: [{ name: '', internalType: 'uint128', type: 'uint128' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'user', internalType: 'address', type: 'address' }],\n name: 'interestState',\n outputs: [\n { name: 'userBorrowIndex', internalType: 'int128', type: 'int128' },\n { name: 'netBorrows', internalType: 'int128', type: 'int128' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'lastInteractionTimestamp',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: '', internalType: 'address', type: 'address' }],\n name: 'maxDeposit',\n outputs: [{ name: 'maxAssets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [{ name: '', internalType: 'address', type: 'address' }],\n name: 'maxMint',\n outputs: [{ name: 'maxShares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'maxRedeem',\n outputs: [{ name: 'maxShares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'maxWithdraw',\n outputs: [{ name: 'maxAssets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'shares', internalType: 'uint256', type: 'uint256' },\n { name: 'receiver', internalType: 'address', type: 'address' },\n ],\n name: 'mint',\n outputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes[]', type: 'bytes[]' }],\n name: 'multicall',\n outputs: [{ name: 'results', internalType: 'bytes[]', type: 'bytes[]' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'name',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'owedInterest',\n outputs: [{ name: '', internalType: 'uint128', type: 'uint128' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'panopticPool',\n outputs: [{ name: '', internalType: 'contract PanopticPoolV2', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'poolFee',\n outputs: [{ name: '_poolFee', internalType: 'uint24', type: 'uint24' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'poolManager',\n outputs: [{ name: '', internalType: 'contract IPoolManager', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n name: 'previewDeposit',\n outputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n name: 'previewMint',\n outputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'previewOwedInterest',\n outputs: [{ name: '', internalType: 'uint128', type: 'uint128' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n name: 'previewRedeem',\n outputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n name: 'previewWithdraw',\n outputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'rateAtTarget',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'shares', internalType: 'uint256', type: 'uint256' },\n { name: 'receiver', internalType: 'address', type: 'address' },\n { name: 'owner', internalType: 'address', type: 'address' },\n ],\n name: 'redeem',\n outputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'reentrancyGuardEntered',\n outputs: [{ name: 'entered', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'refunder', internalType: 'address', type: 'address' },\n { name: 'refundee', internalType: 'address', type: 'address' },\n { name: 'assets', internalType: 'int256', type: 'int256' },\n ],\n name: 'refund',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'delegatee', internalType: 'address', type: 'address' }],\n name: 'revoke',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'riskEngine',\n outputs: [{ name: '', internalType: 'contract IRiskEngine', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'optionOwner', internalType: 'address', type: 'address' },\n { name: 'longAmount', internalType: 'int128', type: 'int128' },\n { name: 'shortAmount', internalType: 'int128', type: 'int128' },\n { name: 'ammDeltaAmount', internalType: 'int128', type: 'int128' },\n { name: 'realizedPremium', internalType: 'int128', type: 'int128' },\n {\n name: 'riskParameters',\n internalType: 'RiskParameters',\n type: 'uint256',\n },\n ],\n name: 'settleBurn',\n outputs: [{ name: '', internalType: 'int128', type: 'int128' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'liquidator', internalType: 'address', type: 'address' },\n { name: 'liquidatee', internalType: 'address', type: 'address' },\n { name: 'bonus', internalType: 'int256', type: 'int256' },\n ],\n name: 'settleLiquidation',\n outputs: [],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'optionOwner', internalType: 'address', type: 'address' },\n { name: 'longAmount', internalType: 'int128', type: 'int128' },\n { name: 'shortAmount', internalType: 'int128', type: 'int128' },\n { name: 'ammDeltaAmount', internalType: 'int128', type: 'int128' },\n {\n name: 'riskParameters',\n internalType: 'RiskParameters',\n type: 'uint256',\n },\n ],\n name: 'settleMint',\n outputs: [\n { name: '', internalType: 'uint32', type: 'uint32' },\n { name: '', internalType: 'int128', type: 'int128' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'symbol',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'token0',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'token1',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'totalAssets',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'totalSupply',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'recipient', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'transfer',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'transferFrom',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'underlyingIsToken0',\n outputs: [{ name: '_underlyingIsToken0', internalType: 'bool', type: 'bool' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'underlyingToken',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes', type: 'bytes' }],\n name: 'unlockCallback',\n outputs: [{ name: '', internalType: 'bytes', type: 'bytes' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'unrealizedGlobalInterest',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'assets', internalType: 'uint256', type: 'uint256' },\n { name: 'receiver', internalType: 'address', type: 'address' },\n { name: 'owner', internalType: 'address', type: 'address' },\n ],\n name: 'withdraw',\n outputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'assets', internalType: 'uint256', type: 'uint256' },\n { name: 'receiver', internalType: 'address', type: 'address' },\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n { name: 'usePremiaAsCollateral', internalType: 'bool', type: 'bool' },\n ],\n name: 'withdraw',\n outputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'spender',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'amount',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'Approval',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'builder',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'commissionPaidProtocol',\n internalType: 'uint128',\n type: 'uint128',\n indexed: false,\n },\n {\n name: 'commissionPaidBuilder',\n internalType: 'uint128',\n type: 'uint128',\n indexed: false,\n },\n ],\n name: 'CommissionPaid',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'sender',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'assets',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n {\n name: 'shares',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'Deposit',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'interestOwed',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n {\n name: 'interestPaid',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n {\n name: 'sharesBurned',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'InsolvencyPenaltyApplied',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'liquidatee',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'liquidator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'protocolLossAssets',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n {\n name: 'protocolLossShares',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'ProtocolLossRealized',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'from', internalType: 'address', type: 'address', indexed: true },\n { name: 'to', internalType: 'address', type: 'address', indexed: true },\n {\n name: 'amount',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'Transfer',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'sender',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'receiver',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'assets',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n {\n name: 'shares',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'Withdraw',\n },\n { type: 'error', inputs: [], name: 'AlreadyInitialized' },\n { type: 'error', inputs: [], name: 'BelowMinimumRedemption' },\n { type: 'error', inputs: [], name: 'CastingError' },\n { type: 'error', inputs: [], name: 'DepositTooLarge' },\n { type: 'error', inputs: [], name: 'ExceedsMaximumRedemption' },\n {\n type: 'error',\n inputs: [\n { name: 'tokenAddress', internalType: 'address', type: 'address' },\n { name: 'assetsRequested', internalType: 'uint256', type: 'uint256' },\n { name: 'assetBalance', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'NotEnoughTokens',\n },\n { type: 'error', inputs: [], name: 'NotPanopticPool' },\n { type: 'error', inputs: [], name: 'PositionCountNotZero' },\n { type: 'error', inputs: [], name: 'Reentrancy' },\n {\n type: 'error',\n inputs: [\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n { name: 'balance', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'TransferFailed',\n },\n { type: 'error', inputs: [], name: 'UnauthorizedUniswapCallback' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// PanopticFactoryV3\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const panopticFactoryV3Abi = [\n {\n type: 'constructor',\n inputs: [\n {\n name: '_SFPM',\n internalType: 'contract SemiFungiblePositionManagerV3',\n type: 'address',\n },\n {\n name: '_univ3Factory',\n internalType: 'contract IUniswapV3Factory',\n type: 'address',\n },\n { name: '_poolReference', internalType: 'address', type: 'address' },\n {\n name: '_collateralReference',\n internalType: 'address',\n type: 'address',\n },\n { name: 'properties', internalType: 'bytes32[]', type: 'bytes32[]' },\n { name: 'indices', internalType: 'uint256[][]', type: 'uint256[][]' },\n { name: 'pointers', internalType: 'Pointer[][]', type: 'uint256[][]' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'spender', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'approve',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'balanceOf',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'panopticPool', internalType: 'address', type: 'address' },\n { name: 'symbol0', internalType: 'string', type: 'string' },\n { name: 'symbol1', internalType: 'string', type: 'string' },\n { name: 'fee', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'constructMetadata',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'token0', internalType: 'address', type: 'address' },\n { name: 'token1', internalType: 'address', type: 'address' },\n { name: 'fee', internalType: 'uint24', type: 'uint24' },\n {\n name: 'riskEngine',\n internalType: 'contract IRiskEngine',\n type: 'address',\n },\n { name: 'salt', internalType: 'uint96', type: 'uint96' },\n ],\n name: 'deployNewPool',\n outputs: [\n {\n name: 'newPoolContract',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n name: 'getApproved',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'univ3pool',\n internalType: 'contract IUniswapV3Pool',\n type: 'address',\n },\n {\n name: 'riskEngine',\n internalType: 'contract IRiskEngine',\n type: 'address',\n },\n ],\n name: 'getPanopticPool',\n outputs: [{ name: '', internalType: 'contract PanopticPoolV2', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'address', type: 'address' },\n ],\n name: 'isApprovedForAll',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'deployerAddress', internalType: 'address', type: 'address' },\n { name: 'v3Pool', internalType: 'address', type: 'address' },\n { name: 'riskEngine', internalType: 'address', type: 'address' },\n { name: 'salt', internalType: 'uint96', type: 'uint96' },\n { name: 'loops', internalType: 'uint256', type: 'uint256' },\n { name: 'minTargetRarity', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'minePoolAddress',\n outputs: [\n { name: 'bestSalt', internalType: 'uint96', type: 'uint96' },\n { name: 'highestRarity', internalType: 'uint256', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes[]', type: 'bytes[]' }],\n name: 'multicall',\n outputs: [{ name: 'results', internalType: 'bytes[]', type: 'bytes[]' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'name',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'id', internalType: 'uint256', type: 'uint256' }],\n name: 'ownerOf',\n outputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'safeTransferFrom',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n { name: 'data', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'safeTransferFrom',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'operator', internalType: 'address', type: 'address' },\n { name: 'approved', internalType: 'bool', type: 'bool' },\n ],\n name: 'setApprovalForAll',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'interfaceId', internalType: 'bytes4', type: 'bytes4' }],\n name: 'supportsInterface',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'symbol',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'tokenId', internalType: 'uint256', type: 'uint256' }],\n name: 'tokenURI',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'transferFrom',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'spender',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'id', internalType: 'uint256', type: 'uint256', indexed: true },\n ],\n name: 'Approval',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'approved', internalType: 'bool', type: 'bool', indexed: false },\n ],\n name: 'ApprovalForAll',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'poolAddress',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n indexed: true,\n },\n {\n name: 'uniswapPool',\n internalType: 'contract IUniswapV3Pool',\n type: 'address',\n indexed: true,\n },\n {\n name: 'collateralTracker0',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n indexed: false,\n },\n {\n name: 'collateralTracker1',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n indexed: false,\n },\n {\n name: 'riskEngine',\n internalType: 'contract IRiskEngine',\n type: 'address',\n indexed: false,\n },\n ],\n name: 'PoolDeployed',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'from', internalType: 'address', type: 'address', indexed: true },\n { name: 'to', internalType: 'address', type: 'address', indexed: true },\n { name: 'id', internalType: 'uint256', type: 'uint256', indexed: true },\n ],\n name: 'Transfer',\n },\n { type: 'error', inputs: [], name: 'AlreadyInitialized' },\n { type: 'error', inputs: [], name: 'CreateFail' },\n { type: 'error', inputs: [], name: 'PoolNotInitialized' },\n { type: 'error', inputs: [], name: 'ZeroAddress' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// PanopticFactoryV4\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const panopticFactoryV4Abi = [\n {\n type: 'constructor',\n inputs: [\n {\n name: '_SFPM',\n internalType: 'contract SemiFungiblePositionManagerV4',\n type: 'address',\n },\n {\n name: '_manager',\n internalType: 'contract IPoolManager',\n type: 'address',\n },\n { name: '_poolReference', internalType: 'address', type: 'address' },\n {\n name: '_collateralReference',\n internalType: 'address',\n type: 'address',\n },\n { name: 'properties', internalType: 'bytes32[]', type: 'bytes32[]' },\n { name: 'indices', internalType: 'uint256[][]', type: 'uint256[][]' },\n { name: 'pointers', internalType: 'Pointer[][]', type: 'uint256[][]' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'spender', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'approve',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'balanceOf',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'panopticPool', internalType: 'address', type: 'address' },\n { name: 'symbol0', internalType: 'string', type: 'string' },\n { name: 'symbol1', internalType: 'string', type: 'string' },\n { name: 'fee', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'constructMetadata',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'key',\n internalType: 'struct PoolKey',\n type: 'tuple',\n components: [\n { name: 'currency0', internalType: 'Currency', type: 'address' },\n { name: 'currency1', internalType: 'Currency', type: 'address' },\n { name: 'fee', internalType: 'uint24', type: 'uint24' },\n { name: 'tickSpacing', internalType: 'int24', type: 'int24' },\n { name: 'hooks', internalType: 'contract IHooks', type: 'address' },\n ],\n },\n {\n name: 'riskEngine',\n internalType: 'contract IRiskEngine',\n type: 'address',\n },\n { name: 'salt', internalType: 'uint96', type: 'uint96' },\n ],\n name: 'deployNewPool',\n outputs: [\n {\n name: 'newPoolContract',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n name: 'getApproved',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'keyV4',\n internalType: 'struct PoolKey',\n type: 'tuple',\n components: [\n { name: 'currency0', internalType: 'Currency', type: 'address' },\n { name: 'currency1', internalType: 'Currency', type: 'address' },\n { name: 'fee', internalType: 'uint24', type: 'uint24' },\n { name: 'tickSpacing', internalType: 'int24', type: 'int24' },\n { name: 'hooks', internalType: 'contract IHooks', type: 'address' },\n ],\n },\n {\n name: 'riskEngine',\n internalType: 'contract IRiskEngine',\n type: 'address',\n },\n ],\n name: 'getPanopticPool',\n outputs: [{ name: '', internalType: 'contract PanopticPoolV2', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'address', type: 'address' },\n ],\n name: 'isApprovedForAll',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'deployerAddress', internalType: 'address', type: 'address' },\n {\n name: 'key',\n internalType: 'struct PoolKey',\n type: 'tuple',\n components: [\n { name: 'currency0', internalType: 'Currency', type: 'address' },\n { name: 'currency1', internalType: 'Currency', type: 'address' },\n { name: 'fee', internalType: 'uint24', type: 'uint24' },\n { name: 'tickSpacing', internalType: 'int24', type: 'int24' },\n { name: 'hooks', internalType: 'contract IHooks', type: 'address' },\n ],\n },\n { name: 'riskEngine', internalType: 'address', type: 'address' },\n { name: 'salt', internalType: 'uint96', type: 'uint96' },\n { name: 'loops', internalType: 'uint256', type: 'uint256' },\n { name: 'minTargetRarity', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'minePoolAddress',\n outputs: [\n { name: 'bestSalt', internalType: 'uint96', type: 'uint96' },\n { name: 'highestRarity', internalType: 'uint256', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes[]', type: 'bytes[]' }],\n name: 'multicall',\n outputs: [{ name: 'results', internalType: 'bytes[]', type: 'bytes[]' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'name',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'id', internalType: 'uint256', type: 'uint256' }],\n name: 'ownerOf',\n outputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'safeTransferFrom',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n { name: 'data', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'safeTransferFrom',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'operator', internalType: 'address', type: 'address' },\n { name: 'approved', internalType: 'bool', type: 'bool' },\n ],\n name: 'setApprovalForAll',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'interfaceId', internalType: 'bytes4', type: 'bytes4' }],\n name: 'supportsInterface',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'symbol',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'tokenId', internalType: 'uint256', type: 'uint256' }],\n name: 'tokenURI',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'transferFrom',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'spender',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'id', internalType: 'uint256', type: 'uint256', indexed: true },\n ],\n name: 'Approval',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'approved', internalType: 'bool', type: 'bool', indexed: false },\n ],\n name: 'ApprovalForAll',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'poolAddress',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n indexed: true,\n },\n { name: 'idV4', internalType: 'PoolId', type: 'bytes32', indexed: true },\n {\n name: 'collateralTracker0',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n indexed: false,\n },\n {\n name: 'collateralTracker1',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n indexed: false,\n },\n {\n name: 'riskEngine',\n internalType: 'contract IRiskEngine',\n type: 'address',\n indexed: false,\n },\n ],\n name: 'PoolDeployed',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'from', internalType: 'address', type: 'address', indexed: true },\n { name: 'to', internalType: 'address', type: 'address', indexed: true },\n { name: 'id', internalType: 'uint256', type: 'uint256', indexed: true },\n ],\n name: 'Transfer',\n },\n { type: 'error', inputs: [], name: 'AlreadyInitialized' },\n { type: 'error', inputs: [], name: 'CreateFail' },\n { type: 'error', inputs: [], name: 'PoolNotInitialized' },\n { type: 'error', inputs: [], name: 'ZeroAddress' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// PanopticGuardian\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const panopticGuardianAbi = [\n {\n type: 'constructor',\n inputs: [\n { name: 'guardianAdmin', internalType: 'address', type: 'address' },\n { name: 'treasurer', internalType: 'address', type: 'address' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'GUARDIAN_ADMIN',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'TREASURER',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'UNLOCK_DELAY',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: '', internalType: 'address', type: 'address' }],\n name: 'builderAdminRevoked',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'cancelUnlock',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'riskEngine',\n internalType: 'contract IRiskEngine',\n type: 'address',\n },\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'recipient', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'collect',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'builderCode', internalType: 'uint256', type: 'uint256' },\n { name: 'builderAdmin', internalType: 'address', type: 'address' },\n {\n name: 'builderFactory',\n internalType: 'contract BuilderFactory',\n type: 'address',\n },\n ],\n name: 'deployBuilder',\n outputs: [{ name: 'wallet', internalType: 'address', type: 'address' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'executeUnlock',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'account', internalType: 'address', type: 'address' },\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'builderCode', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'isBuilderAdmin',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'isPoolUnlockReady',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'lockPool',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'builderCode', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'lockPoolAsBuilder',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'requestUnlock',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'admin', internalType: 'address', type: 'address' },\n { name: 'revoked', internalType: 'bool', type: 'bool' },\n ],\n name: 'setBuilderAdminRevoked',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: '', internalType: 'contract PanopticPoolV2', type: 'address' }],\n name: 'unlockEta',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'admin',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n ],\n name: 'BuilderAdminRestored',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'admin',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n ],\n name: 'BuilderAdminRevoked',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'builderCode',\n internalType: 'uint256',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'wallet',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n ],\n name: 'BuilderDeployed',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n indexed: true,\n },\n {\n name: 'locker',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n ],\n name: 'PoolLocked',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n indexed: true,\n },\n ],\n name: 'PoolUnlocked',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'token',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'recipient',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'amount',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'TokensCollected',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n indexed: true,\n },\n ],\n name: 'UnlockCancelled',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n indexed: true,\n },\n { name: 'eta', internalType: 'uint256', type: 'uint256', indexed: false },\n ],\n name: 'UnlockRequested',\n },\n { type: 'error', inputs: [], name: 'InvalidBuilderCode' },\n { type: 'error', inputs: [], name: 'NoPendingUnlock' },\n { type: 'error', inputs: [], name: 'NotAuthorizedBuilder' },\n { type: 'error', inputs: [], name: 'NotFactoryAdmin' },\n { type: 'error', inputs: [], name: 'NotGuardianAdmin' },\n { type: 'error', inputs: [], name: 'NotTreasurer' },\n { type: 'error', inputs: [], name: 'UnlockAlreadyPending' },\n {\n type: 'error',\n inputs: [{ name: 'eta', internalType: 'uint256', type: 'uint256' }],\n name: 'UnlockNotReady',\n },\n { type: 'error', inputs: [], name: 'ZeroAddress' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// PanopticLiquidator\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const panopticLiquidatorAbi = [\n {\n type: 'constructor',\n inputs: [\n { name: 'morpho', internalType: 'contract IMorpho', type: 'address' },\n { name: 'owner_', internalType: 'address', type: 'address' },\n ],\n stateMutability: 'nonpayable',\n },\n { type: 'receive', stateMutability: 'payable' },\n {\n type: 'function',\n inputs: [],\n name: 'MORPHO',\n outputs: [{ name: '', internalType: 'contract IMorpho', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'target', internalType: 'address', type: 'address' },\n { name: 'value', internalType: 'uint256', type: 'uint256' },\n { name: 'data', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'execute',\n outputs: [{ name: 'ret', internalType: 'bytes', type: 'bytes' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'initializePool',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'params',\n internalType: 'struct PanopticLiquidator.LiquidateParams',\n type: 'tuple',\n components: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n {\n name: 'positionIdListTo',\n internalType: 'TokenId[]',\n type: 'uint256[]',\n },\n {\n name: 'usePremiaAsCollateral',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n { name: 'flashToken', internalType: 'address', type: 'address' },\n { name: 'flashAmount', internalType: 'uint256', type: 'uint256' },\n {\n name: 'nativeFundingAmount',\n internalType: 'uint256',\n type: 'uint256',\n },\n { name: 'preSwapTarget', internalType: 'address', type: 'address' },\n { name: 'preSwapCallData', internalType: 'bytes', type: 'bytes' },\n { name: 'preSwapTokenIn', internalType: 'address', type: 'address' },\n { name: 'preSwapAmountIn', internalType: 'uint256', type: 'uint256' },\n { name: 'swapTarget', internalType: 'address', type: 'address' },\n { name: 'swapCallData', internalType: 'bytes', type: 'bytes' },\n { name: 'swapTokenIn', internalType: 'address', type: 'address' },\n { name: 'swapAmountIn', internalType: 'uint256', type: 'uint256' },\n { name: 'minDelta0', internalType: 'int256', type: 'int256' },\n { name: 'minDelta1', internalType: 'int256', type: 'int256' },\n ],\n },\n ],\n name: 'liquidate',\n outputs: [\n { name: 'delta0', internalType: 'int256', type: 'int256' },\n { name: 'delta1', internalType: 'int256', type: 'int256' },\n ],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes[]', type: 'bytes[]' }],\n name: 'multicall',\n outputs: [{ name: 'results', internalType: 'bytes[]', type: 'bytes[]' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'assets', internalType: 'uint256', type: 'uint256' },\n { name: 'data', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'onMorphoFlashLoan',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'owner',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'params',\n internalType: 'struct PanopticLiquidator.LiquidateParams',\n type: 'tuple',\n components: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n {\n name: 'positionIdListTo',\n internalType: 'TokenId[]',\n type: 'uint256[]',\n },\n {\n name: 'usePremiaAsCollateral',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n { name: 'flashToken', internalType: 'address', type: 'address' },\n { name: 'flashAmount', internalType: 'uint256', type: 'uint256' },\n {\n name: 'nativeFundingAmount',\n internalType: 'uint256',\n type: 'uint256',\n },\n { name: 'preSwapTarget', internalType: 'address', type: 'address' },\n { name: 'preSwapCallData', internalType: 'bytes', type: 'bytes' },\n { name: 'preSwapTokenIn', internalType: 'address', type: 'address' },\n { name: 'preSwapAmountIn', internalType: 'uint256', type: 'uint256' },\n { name: 'swapTarget', internalType: 'address', type: 'address' },\n { name: 'swapCallData', internalType: 'bytes', type: 'bytes' },\n { name: 'swapTokenIn', internalType: 'address', type: 'address' },\n { name: 'swapAmountIn', internalType: 'uint256', type: 'uint256' },\n { name: 'minDelta0', internalType: 'int256', type: 'int256' },\n { name: 'minDelta1', internalType: 'int256', type: 'int256' },\n ],\n },\n ],\n name: 'quoteLiquidation',\n outputs: [\n { name: 'bonus0', internalType: 'int256', type: 'int256' },\n { name: 'bonus1', internalType: 'int256', type: 'int256' },\n { name: 'shortfall0', internalType: 'uint256', type: 'uint256' },\n { name: 'shortfall1', internalType: 'uint256', type: 'uint256' },\n { name: 'protocolLoss0', internalType: 'uint256', type: 'uint256' },\n { name: 'protocolLoss1', internalType: 'uint256', type: 'uint256' },\n ],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [{ name: 'newOwner', internalType: 'address', type: 'address' }],\n name: 'setOwner',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'sweep',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'user', internalType: 'address', type: 'address', indexed: true },\n {\n name: 'newOwner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n ],\n name: 'OwnerUpdated',\n },\n { type: 'error', inputs: [], name: 'ApproveFailed' },\n { type: 'error', inputs: [], name: 'CallFailed' },\n {\n type: 'error',\n inputs: [\n { name: 'delta0', internalType: 'int256', type: 'int256' },\n { name: 'delta1', internalType: 'int256', type: 'int256' },\n ],\n name: 'InsufficientDelta',\n },\n { type: 'error', inputs: [], name: 'SwapFailed' },\n {\n type: 'error',\n inputs: [\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n { name: 'balance', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'TransferFailed',\n },\n { type: 'error', inputs: [], name: 'UntrustedFlashLoanInitiator' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// PanopticPoolV2\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const panopticPoolV2Abi = [\n {\n type: 'constructor',\n inputs: [\n {\n name: '_sfpm',\n internalType: 'contract ISemiFungiblePositionManager',\n type: 'address',\n },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'SFPM',\n outputs: [\n {\n name: '',\n internalType: 'contract ISemiFungiblePositionManager',\n type: 'address',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'minValue0', internalType: 'uint256', type: 'uint256' },\n { name: 'minValue1', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'assertMinCollateralValues',\n outputs: [],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'collateralToken0',\n outputs: [\n {\n name: '',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n ],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'collateralToken1',\n outputs: [\n {\n name: '',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n ],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n {\n name: 'finalPositionIdList',\n internalType: 'TokenId[]',\n type: 'uint256[]',\n },\n { name: 'positionSizes', internalType: 'uint128[]', type: 'uint128[]' },\n {\n name: 'tickAndSpreadLimits',\n internalType: 'int24[3][]',\n type: 'int24[3][]',\n },\n { name: 'usePremiaAsCollateral', internalType: 'bool', type: 'bool' },\n { name: 'builderCode', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'dispatch',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'positionIdListFrom',\n internalType: 'TokenId[]',\n type: 'uint256[]',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n {\n name: 'positionIdListTo',\n internalType: 'TokenId[]',\n type: 'uint256[]',\n },\n {\n name: 'positionIdListToFinal',\n internalType: 'TokenId[]',\n type: 'uint256[]',\n },\n {\n name: 'usePremiaAsCollateral',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n ],\n name: 'dispatchFrom',\n outputs: [],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [{ name: 'account', internalType: 'address', type: 'address' }],\n name: 'getAssetsOf',\n outputs: [\n { name: 'assets0', internalType: 'uint256', type: 'uint256' },\n { name: 'assets1', internalType: 'uint256', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'tickLower', internalType: 'int24', type: 'int24' },\n { name: 'tickUpper', internalType: 'int24', type: 'int24' },\n ],\n name: 'getChunkData',\n outputs: [\n {\n name: 'liquidities0',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'liquidities1',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n { name: 'settled0', internalType: 'LeftRightUnsigned', type: 'uint256' },\n { name: 'settled1', internalType: 'LeftRightUnsigned', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'getCurrentTick',\n outputs: [{ name: 'currentTick', internalType: 'int24', type: 'int24' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'user', internalType: 'address', type: 'address' },\n { name: 'includePendingPremium', internalType: 'bool', type: 'bool' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n ],\n name: 'getFullPositionsData',\n outputs: [\n {\n name: 'shortPremium',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'longPremium',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'positionBalances',\n internalType: 'PositionBalance[]',\n type: 'uint256[]',\n },\n {\n name: 'collateralRequirements',\n internalType: 'LeftRightUnsigned[]',\n type: 'uint256[]',\n },\n {\n name: 'netPremiaPerPosition',\n internalType: 'LeftRightSigned[]',\n type: 'int256[]',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'getOracleTicks',\n outputs: [\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n { name: 'spotTick', internalType: 'int24', type: 'int24' },\n { name: 'medianTick', internalType: 'int24', type: 'int24' },\n { name: 'latestTick', internalType: 'int24', type: 'int24' },\n { name: 'oraclePack', internalType: 'OraclePack', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'builderCode', internalType: 'uint256', type: 'uint256' }],\n name: 'getRiskParameters',\n outputs: [\n {\n name: 'riskParameters',\n internalType: 'RiskParameters',\n type: 'uint256',\n },\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'getTWAP',\n outputs: [{ name: 'twapTick', internalType: 'int24', type: 'int24' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'initialize',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'isSafeMode',\n outputs: [{ name: '', internalType: 'uint8', type: 'uint8' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'lockSafeMode',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes[]', type: 'bytes[]' }],\n name: 'multicall',\n outputs: [{ name: 'results', internalType: 'bytes[]', type: 'bytes[]' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [{ name: 'user', internalType: 'address', type: 'address' }],\n name: 'numberOfLegs',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n { name: '', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'onERC1155Received',\n outputs: [{ name: '', internalType: 'bytes4', type: 'bytes4' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'pokeOracle',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'poolId',\n outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'poolKey',\n outputs: [{ name: 'key', internalType: 'bytes', type: 'bytes' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'poolManager',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'reentrancyGuardEntered',\n outputs: [{ name: 'entered', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'riskEngine',\n outputs: [{ name: '', internalType: 'contract IRiskEngine', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'tickSpacing',\n outputs: [{ name: '', internalType: 'int24', type: 'int24' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'unlockSafeMode',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'user', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n { name: 'usePremiaAsCollateral', internalType: 'bool', type: 'bool' },\n ],\n name: 'validateCollateralWithdrawable',\n outputs: [],\n stateMutability: 'view',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'liquidator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'liquidatee',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'bonusAmounts',\n internalType: 'LeftRightSigned',\n type: 'int256',\n indexed: false,\n },\n ],\n name: 'AccountLiquidated',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'exercisor',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'user', internalType: 'address', type: 'address', indexed: true },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'exerciseFee',\n internalType: 'LeftRightSigned',\n type: 'int256',\n indexed: false,\n },\n ],\n name: 'ForcedExercised',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'recipient',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'positionSize',\n internalType: 'uint128',\n type: 'uint128',\n indexed: false,\n },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'premiaByLeg',\n internalType: 'LeftRightSigned[4]',\n type: 'int256[4]',\n indexed: false,\n },\n ],\n name: 'OptionBurnt',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'recipient',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'balanceData',\n internalType: 'PositionBalance',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'OptionMinted',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'user', internalType: 'address', type: 'address', indexed: true },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'legIndex',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n {\n name: 'settledAmounts',\n internalType: 'LeftRightSigned',\n type: 'int256',\n indexed: false,\n },\n ],\n name: 'PremiumSettled',\n },\n {\n type: 'error',\n inputs: [\n { name: 'solvent', internalType: 'uint256', type: 'uint256' },\n { name: 'numberOfTicks', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'AccountInsolvent',\n },\n { type: 'error', inputs: [], name: 'AlreadyInitialized' },\n { type: 'error', inputs: [], name: 'CastingError' },\n { type: 'error', inputs: [], name: 'DuplicateTokenId' },\n { type: 'error', inputs: [], name: 'EffectiveLiquidityAboveThreshold' },\n { type: 'error', inputs: [], name: 'InputListFail' },\n { type: 'error', inputs: [], name: 'InvalidTick' },\n { type: 'error', inputs: [], name: 'InvalidTickBound' },\n { type: 'error', inputs: [], name: 'LiquidityTooHigh' },\n { type: 'error', inputs: [], name: 'NetLiquidityZero' },\n { type: 'error', inputs: [], name: 'NoLegsExercisable' },\n { type: 'error', inputs: [], name: 'NotGuardian' },\n { type: 'error', inputs: [], name: 'NotMarginCalled' },\n { type: 'error', inputs: [], name: 'PositionNotOwned' },\n { type: 'error', inputs: [], name: 'PriceImpactTooLarge' },\n { type: 'error', inputs: [], name: 'Reentrancy' },\n { type: 'error', inputs: [], name: 'StaleOracle' },\n { type: 'error', inputs: [], name: 'TokenIdHasZeroLegs' },\n { type: 'error', inputs: [], name: 'TooManyLegsOpen' },\n { type: 'error', inputs: [], name: 'UnderOverFlow' },\n { type: 'error', inputs: [], name: 'WrongPoolId' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// PanopticQuery\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const panopticQueryAbi = [\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n ],\n name: 'checkCollateral',\n outputs: [\n {\n name: 'collateralBalances0',\n internalType: 'uint256[4]',\n type: 'uint256[4]',\n },\n {\n name: 'requiredCollaterals0',\n internalType: 'uint256[4]',\n type: 'uint256[4]',\n },\n {\n name: 'collateralBalances1',\n internalType: 'uint256[4]',\n type: 'uint256[4]',\n },\n {\n name: 'requiredCollaterals1',\n internalType: 'uint256[4]',\n type: 'uint256[4]',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n ],\n name: 'checkCollateral',\n outputs: [\n {\n name: 'balancesAndRequired',\n internalType: 'uint256[4]',\n type: 'uint256[4]',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n ],\n name: 'checkCollateralListOutput',\n outputs: [\n { name: '', internalType: 'uint256[4][]', type: 'uint256[4][]' },\n { name: '', internalType: 'int256[]', type: 'int256[]' },\n { name: '', internalType: 'int24[]', type: 'int24[]' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n {\n name: 'shortPremium',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'longPremium',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'positionBalanceArray',\n internalType: 'PositionBalance[]',\n type: 'uint256[]',\n },\n { name: 'atTicks', internalType: 'int24[]', type: 'int24[]' },\n ],\n name: 'computeNetLiquidationValue',\n outputs: [\n { name: 'value0', internalType: 'int256[]', type: 'int256[]' },\n { name: 'value1', internalType: 'int256[]', type: 'int256[]' },\n ],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n ],\n name: 'getChunkData',\n outputs: [{ name: '', internalType: 'uint256[2][4][]', type: 'uint256[2][4][]' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n { name: 'positionSize', internalType: 'uint128', type: 'uint128' },\n ],\n name: 'getItmAmounts',\n outputs: [\n { name: 'itm0', internalType: 'int256', type: 'int256' },\n { name: 'itm1', internalType: 'int256', type: 'int256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n ],\n name: 'getLiquidationPrices',\n outputs: [\n { name: 'liquidationPriceDown', internalType: 'int24', type: 'int24' },\n { name: 'liquidationPriceUp', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n {\n name: 'existingPositionIds',\n internalType: 'TokenId[]',\n type: 'uint256[]',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n ],\n name: 'getMaxPositionSizeBounds',\n outputs: [\n { name: 'maxSizeAtMinUtil', internalType: 'uint128', type: 'uint128' },\n { name: 'maxSizeAtMaxUtil', internalType: 'uint128', type: 'uint128' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'includePendingPremium', internalType: 'bool', type: 'bool' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n { name: 'atTicks', internalType: 'int24[]', type: 'int24[]' },\n ],\n name: 'getNetLiquidationValue',\n outputs: [\n { name: 'value0', internalType: 'int256[]', type: 'int256[]' },\n { name: 'value1', internalType: 'int256[]', type: 'int256[]' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n ],\n name: 'getPortfolioValue',\n outputs: [\n { name: 'value0', internalType: 'int256', type: 'int256' },\n { name: 'value1', internalType: 'int256', type: 'int256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n ],\n name: 'getRequiredBase',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'startTick', internalType: 'int24', type: 'int24' },\n { name: 'nTicks', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'getTickNets',\n outputs: [\n { name: 'tickData', internalType: 'int256[]', type: 'int256[]' },\n { name: 'liquidityNets', internalType: 'int256[]', type: 'int256[]' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'univ3pool',\n internalType: 'contract IUniswapV3Pool',\n type: 'address',\n },\n { name: 'startTick', internalType: 'int24', type: 'int24' },\n { name: 'nTicks', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'getTickNetsV3',\n outputs: [\n { name: 'tickData', internalType: 'int256[]', type: 'int256[]' },\n { name: 'liquidityNets', internalType: 'int256[]', type: 'int256[]' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'manager',\n internalType: 'contract IPoolManager',\n type: 'address',\n },\n { name: 'poolId', internalType: 'PoolId', type: 'bytes32' },\n { name: 'tickSpacing', internalType: 'int24', type: 'int24' },\n { name: 'startTick', internalType: 'int24', type: 'int24' },\n { name: 'nTicks', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'getTickNetsV4',\n outputs: [\n { name: 'tickData', internalType: 'int256[]', type: 'int256[]' },\n { name: 'liquidityNets', internalType: 'int256[]', type: 'int256[]' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n ],\n name: 'isAccountSolvent',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n ],\n name: 'optimizeRiskPartners',\n outputs: [{ name: '', internalType: 'TokenId', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'tickLower', internalType: 'int24', type: 'int24' },\n { name: 'tickUpper', internalType: 'int24', type: 'int24' },\n { name: 'width', internalType: 'int24', type: 'int24' },\n ],\n name: 'scanChunks',\n outputs: [\n { name: '', internalType: 'int24[]', type: 'int24[]' },\n { name: '', internalType: 'uint128[2][]', type: 'uint128[2][]' },\n { name: '', internalType: 'uint128[2][]', type: 'uint128[2][]' },\n {\n name: '',\n internalType: 'LeftRightUnsigned[2][]',\n type: 'uint256[2][]',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'self', internalType: 'TokenId', type: 'uint256' }],\n name: 'validateTokenId',\n outputs: [],\n stateMutability: 'pure',\n },\n { type: 'error', inputs: [], name: 'CastingError' },\n { type: 'error', inputs: [], name: 'InvalidTick' },\n {\n type: 'error',\n inputs: [{ name: 'parameterType', internalType: 'uint256', type: 'uint256' }],\n name: 'InvalidTokenIdParameter',\n },\n { type: 'error', inputs: [], name: 'LiquidityTooHigh' },\n { type: 'error', inputs: [], name: 'UnderOverFlow' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// RiskEngine\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const riskEngineAbi = [\n {\n type: 'constructor',\n inputs: [\n { name: '_crossBuffer0', internalType: 'uint256', type: 'uint256' },\n { name: '_crossBuffer1', internalType: 'uint256', type: 'uint256' },\n { name: '_guardian', internalType: 'address', type: 'address' },\n { name: '_builderFactory', internalType: 'address', type: 'address' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'ADJUSTMENT_SPEED',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'BP_DECREASE_BUFFER',\n outputs: [{ name: '', internalType: 'uint32', type: 'uint32' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'BUILDER_FACTORY',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'BUILDER_SPLIT',\n outputs: [{ name: '', internalType: 'uint16', type: 'uint16' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'BUYER_COLLATERAL_RATIO',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'CROSS_BUFFER_0',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'CROSS_BUFFER_1',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'CURVE_STEEPNESS',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'DECIMALS',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'EMA_PERIODS',\n outputs: [{ name: '', internalType: 'uint96', type: 'uint96' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'FORCE_EXERCISE_COST',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'GUARDIAN',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'INITIAL_RATE_AT_TARGET',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'IRM_MAX_ELAPSED_TIME',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAINT_MARGIN_RATE',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAX_BONUS',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAX_CLAMP_DELTA',\n outputs: [{ name: '', internalType: 'int24', type: 'int24' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAX_OPEN_LEGS',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAX_RATE_AT_TARGET',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAX_SPREAD',\n outputs: [{ name: '', internalType: 'uint24', type: 'uint24' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAX_TICKS_DELTA',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAX_TWAP_DELTA_DISPATCH',\n outputs: [{ name: '', internalType: 'uint16', type: 'uint16' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MIN_RATE_AT_TARGET',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'NOTIONAL_FEE',\n outputs: [{ name: '', internalType: 'uint16', type: 'uint16' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'PREMIUM_FEE',\n outputs: [{ name: '', internalType: 'uint16', type: 'uint16' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'PROTOCOL_SPLIT',\n outputs: [{ name: '', internalType: 'uint16', type: 'uint16' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'SATURATED_POOL_UTIL',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'SELLER_COLLATERAL_RATIO',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'TARGET_POOL_UTIL',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'TARGET_UTILIZATION',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'VEGOID',\n outputs: [{ name: '', internalType: 'uint8', type: 'uint8' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'recipient', internalType: 'address', type: 'address' },\n ],\n name: 'collect',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'recipient', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'collect',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'oraclePack', internalType: 'OraclePack', type: 'uint256' },\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n ],\n name: 'computeInternalMedian',\n outputs: [\n { name: 'medianTick', internalType: 'int24', type: 'int24' },\n {\n name: 'updatedOraclePack',\n internalType: 'OraclePack',\n type: 'uint256',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'utilization', internalType: 'int256', type: 'int256' },\n { name: 'crossBuffer', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'crossBufferRatio',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n { name: 'oracleTick', internalType: 'int24', type: 'int24' },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n {\n name: 'positionBalance',\n internalType: 'PositionBalance',\n type: 'uint256',\n },\n ],\n name: 'exerciseCost',\n outputs: [{ name: 'exerciseFees', internalType: 'LeftRightSigned', type: 'int256' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [{ name: 'builderCode', internalType: 'uint256', type: 'uint256' }],\n name: 'getFeeRecipient',\n outputs: [{ name: 'feeRecipient', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'tokenData0',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'tokenData1',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n { name: 'atSqrtPriceX96', internalType: 'uint160', type: 'uint160' },\n { name: 'netPaid', internalType: 'LeftRightSigned', type: 'int256' },\n {\n name: 'shortPremium',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'loanAmounts',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n ],\n name: 'getLiquidationBonus',\n outputs: [\n { name: '', internalType: 'LeftRightSigned', type: 'int256' },\n { name: '', internalType: 'LeftRightSigned', type: 'int256' },\n ],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'positionBalanceArray',\n internalType: 'PositionBalance[]',\n type: 'uint256[]',\n },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n { name: 'user', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n {\n name: 'shortPremia',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'longPremia',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'ct0',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n {\n name: 'ct1',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n ],\n name: 'getMargin',\n outputs: [\n {\n name: 'tokenData0',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'tokenData1',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'globalUtilizations',\n internalType: 'PositionBalance',\n type: 'uint256',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n { name: '_oraclePack', internalType: 'OraclePack', type: 'uint256' },\n ],\n name: 'getOracleTicks',\n outputs: [\n { name: 'spotTick', internalType: 'int24', type: 'int24' },\n { name: 'medianTick', internalType: 'int24', type: 'int24' },\n { name: 'latestTick', internalType: 'int24', type: 'int24' },\n { name: 'oraclePack', internalType: 'OraclePack', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'positionBalanceArray',\n internalType: 'PositionBalance[]',\n type: 'uint256[]',\n },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n ],\n name: 'getPerPositionCollateralRequirements',\n outputs: [\n {\n name: 'collateralRequirements',\n internalType: 'LeftRightUnsigned[]',\n type: 'uint256[]',\n },\n ],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'payor', internalType: 'address', type: 'address' },\n { name: 'fees', internalType: 'LeftRightSigned', type: 'int256' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n {\n name: 'ct0',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n {\n name: 'ct1',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n ],\n name: 'getRefundAmounts',\n outputs: [{ name: '', internalType: 'LeftRightSigned', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n { name: 'oraclePack', internalType: 'OraclePack', type: 'uint256' },\n { name: 'builderCode', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'getRiskParameters',\n outputs: [{ name: '', internalType: 'RiskParameters', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n { name: '_oraclePack', internalType: 'OraclePack', type: 'uint256' },\n { name: 'safeMode', internalType: 'uint8', type: 'uint8' },\n ],\n name: 'getSolvencyTicks',\n outputs: [\n { name: '', internalType: 'int24[]', type: 'int24[]' },\n { name: '', internalType: 'OraclePack', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n {\n name: 'premiasByLeg',\n internalType: 'LeftRightSigned[4][]',\n type: 'int256[4][]',\n },\n {\n name: 'collateralRemaining',\n internalType: 'LeftRightSigned',\n type: 'int256',\n },\n { name: 'atSqrtPriceX96', internalType: 'uint160', type: 'uint160' },\n ],\n name: 'haircutPremia',\n outputs: [\n { name: 'bonusDeltas', internalType: 'LeftRightSigned', type: 'int256' },\n {\n name: 'haircutTotal',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'haircutPerLeg',\n internalType: 'LeftRightSigned[4][]',\n type: 'int256[4][]',\n },\n ],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'utilization', internalType: 'uint256', type: 'uint256' },\n {\n name: 'interestRateAccumulator',\n internalType: 'MarketState',\n type: 'uint256',\n },\n ],\n name: 'interestRate',\n outputs: [{ name: '', internalType: 'uint128', type: 'uint128' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'positionBalanceArray',\n internalType: 'PositionBalance[]',\n type: 'uint256[]',\n },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n { name: 'user', internalType: 'address', type: 'address' },\n {\n name: 'shortPremia',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'longPremia',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'ct0',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n {\n name: 'ct1',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n { name: 'buffer', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'isAccountSolvent',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n { name: 'oraclePack', internalType: 'OraclePack', type: 'uint256' },\n ],\n name: 'isSafeMode',\n outputs: [{ name: 'safeMode', internalType: 'uint8', type: 'uint8' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'lockPool',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'oraclePack', internalType: 'OraclePack', type: 'uint256' }],\n name: 'twapEMA',\n outputs: [{ name: '', internalType: 'int24', type: 'int24' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'unlockPool',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'utilization', internalType: 'uint256', type: 'uint256' },\n {\n name: 'interestRateAccumulator',\n internalType: 'MarketState',\n type: 'uint256',\n },\n ],\n name: 'updateInterestRate',\n outputs: [\n { name: '', internalType: 'uint128', type: 'uint128' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'vegoid',\n outputs: [{ name: '', internalType: 'uint8', type: 'uint8' }],\n stateMutability: 'pure',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'collateralToken',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'avgBorrowRate',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n {\n name: 'rateAtTarget',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'BorrowRateUpdated',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [{ name: 'lockMode', internalType: 'bool', type: 'bool', indexed: false }],\n name: 'GuardianSafeModeUpdated',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'token',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'recipient',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'amount',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'TokensCollected',\n },\n { type: 'error', inputs: [], name: 'BelowMinimumRedemption' },\n { type: 'error', inputs: [], name: 'CastingError' },\n { type: 'error', inputs: [], name: 'InvalidBuilderCode' },\n { type: 'error', inputs: [], name: 'InvalidTick' },\n { type: 'error', inputs: [], name: 'LengthMismatch' },\n { type: 'error', inputs: [], name: 'LiquidityTooHigh' },\n { type: 'error', inputs: [], name: 'NotGuardian' },\n {\n type: 'error',\n inputs: [\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n { name: 'balance', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'TransferFailed',\n },\n { type: 'error', inputs: [], name: 'UnderOverFlow' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// SemiFungiblePositionManagerV3\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const semiFungiblePositionManagerV3Abi = [\n {\n type: 'constructor',\n inputs: [\n {\n name: '_factory',\n internalType: 'contract IUniswapV3Factory',\n type: 'address',\n },\n {\n name: '_minEnforcedTickFillCost',\n internalType: 'uint256',\n type: 'uint256',\n },\n {\n name: '_supplyMultiplierTickFill',\n internalType: 'uint256',\n type: 'uint256',\n },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'tokenId', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'balanceOf',\n outputs: [{ name: 'balance', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'owners', internalType: 'address[]', type: 'address[]' },\n { name: 'ids', internalType: 'uint256[]', type: 'uint256[]' },\n ],\n name: 'balanceOfBatch',\n outputs: [{ name: 'balances', internalType: 'uint256[]', type: 'uint256[]' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n { name: 'positionSize', internalType: 'uint128', type: 'uint128' },\n { name: 'tickLimitLow', internalType: 'int24', type: 'int24' },\n { name: 'tickLimitHigh', internalType: 'int24', type: 'int24' },\n ],\n name: 'burnTokenizedPosition',\n outputs: [\n { name: '', internalType: 'LeftRightUnsigned[4]', type: 'uint256[4]' },\n { name: '', internalType: 'LeftRightSigned', type: 'int256' },\n { name: '', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n name: 'expandEnforcedTickRange',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'tokenType', internalType: 'uint256', type: 'uint256' },\n { name: 'tickLower', internalType: 'int24', type: 'int24' },\n { name: 'tickUpper', internalType: 'int24', type: 'int24' },\n ],\n name: 'getAccountFeesBase',\n outputs: [\n { name: 'feesBase0', internalType: 'int128', type: 'int128' },\n { name: 'feesBase1', internalType: 'int128', type: 'int128' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'tokenType', internalType: 'uint256', type: 'uint256' },\n { name: 'tickLower', internalType: 'int24', type: 'int24' },\n { name: 'tickUpper', internalType: 'int24', type: 'int24' },\n ],\n name: 'getAccountLiquidity',\n outputs: [\n {\n name: 'accountLiquidities',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'tokenType', internalType: 'uint256', type: 'uint256' },\n { name: 'tickLower', internalType: 'int24', type: 'int24' },\n { name: 'tickUpper', internalType: 'int24', type: 'int24' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n { name: 'isLong', internalType: 'uint256', type: 'uint256' },\n { name: 'vegoid', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'getAccountPremium',\n outputs: [\n { name: '', internalType: 'uint128', type: 'uint128' },\n { name: '', internalType: 'uint128', type: 'uint128' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolKey', internalType: 'bytes', type: 'bytes' }],\n name: 'getCurrentTick',\n outputs: [{ name: 'currentTick', internalType: 'int24', type: 'int24' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n name: 'getEnforcedTickLimits',\n outputs: [\n { name: '', internalType: 'int24', type: 'int24' },\n { name: '', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'id', internalType: 'bytes', type: 'bytes' },\n { name: 'vegoid', internalType: 'uint8', type: 'uint8' },\n ],\n name: 'getPoolId',\n outputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n name: 'getUniswapV3PoolFromId',\n outputs: [\n {\n name: 'uniswapV3Pool',\n internalType: 'contract IUniswapV3Pool',\n type: 'address',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'token0', internalType: 'address', type: 'address' },\n { name: 'token1', internalType: 'address', type: 'address' },\n { name: 'fee', internalType: 'uint24', type: 'uint24' },\n { name: 'vegoid', internalType: 'uint8', type: 'uint8' },\n ],\n name: 'initializeAMMPool',\n outputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'operator', internalType: 'address', type: 'address' },\n ],\n name: 'isApprovedForAll',\n outputs: [{ name: 'approvedForAll', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n { name: 'positionSize', internalType: 'uint128', type: 'uint128' },\n { name: 'tickLimitLow', internalType: 'int24', type: 'int24' },\n { name: 'tickLimitHigh', internalType: 'int24', type: 'int24' },\n ],\n name: 'mintTokenizedPosition',\n outputs: [\n { name: '', internalType: 'LeftRightUnsigned[4]', type: 'uint256[4]' },\n { name: '', internalType: 'LeftRightSigned', type: 'int256' },\n { name: '', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes[]', type: 'bytes[]' }],\n name: 'multicall',\n outputs: [{ name: 'results', internalType: 'bytes[]', type: 'bytes[]' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'reentrancyGuardEntered',\n outputs: [{ name: 'entered', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'uint256[]', type: 'uint256[]' },\n { name: '', internalType: 'uint256[]', type: 'uint256[]' },\n { name: '', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'safeBatchTransferFrom',\n outputs: [],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n { name: '', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'safeTransferFrom',\n outputs: [],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'operator', internalType: 'address', type: 'address' },\n { name: 'approved', internalType: 'bool', type: 'bool' },\n ],\n name: 'setApprovalForAll',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'interfaceId', internalType: 'bytes4', type: 'bytes4' }],\n name: 'supportsInterface',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'amount0Owed', internalType: 'uint256', type: 'uint256' },\n { name: 'amount1Owed', internalType: 'uint256', type: 'uint256' },\n { name: 'data', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'uniswapV3MintCallback',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'amount0Delta', internalType: 'int256', type: 'int256' },\n { name: 'amount1Delta', internalType: 'int256', type: 'int256' },\n { name: 'data', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'uniswapV3SwapCallback',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'approved', internalType: 'bool', type: 'bool', indexed: false },\n ],\n name: 'ApprovalForAll',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'uniswapPool',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'minEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'maxEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n ],\n name: 'EnforcedTicksUpdated',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'univ3pool',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'tokenType',\n internalType: 'uint256',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'tickLower',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'tickUpper',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'liquidityDelta',\n internalType: 'int128',\n type: 'int128',\n indexed: false,\n },\n ],\n name: 'LiquidityChunkUpdated',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'uniswapPool',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'poolId',\n internalType: 'uint64',\n type: 'uint64',\n indexed: false,\n },\n {\n name: 'minEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'maxEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n ],\n name: 'PoolInitialized',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'recipient',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'positionSize',\n internalType: 'uint128',\n type: 'uint128',\n indexed: false,\n },\n ],\n name: 'TokenizedPositionBurnt',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'caller',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'positionSize',\n internalType: 'uint128',\n type: 'uint128',\n indexed: false,\n },\n ],\n name: 'TokenizedPositionMinted',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'from', internalType: 'address', type: 'address', indexed: true },\n { name: 'to', internalType: 'address', type: 'address', indexed: true },\n {\n name: 'ids',\n internalType: 'uint256[]',\n type: 'uint256[]',\n indexed: false,\n },\n {\n name: 'amounts',\n internalType: 'uint256[]',\n type: 'uint256[]',\n indexed: false,\n },\n ],\n name: 'TransferBatch',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'from', internalType: 'address', type: 'address', indexed: true },\n { name: 'to', internalType: 'address', type: 'address', indexed: true },\n { name: 'id', internalType: 'uint256', type: 'uint256', indexed: false },\n {\n name: 'amount',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'TransferSingle',\n },\n { type: 'error', inputs: [], name: 'CastingError' },\n { type: 'error', inputs: [], name: 'ChunkHasZeroLiquidity' },\n { type: 'error', inputs: [], name: 'InvalidTick' },\n { type: 'error', inputs: [], name: 'InvalidTickBound' },\n {\n type: 'error',\n inputs: [{ name: 'parameterType', internalType: 'uint256', type: 'uint256' }],\n name: 'InvalidTokenIdParameter',\n },\n { type: 'error', inputs: [], name: 'InvalidUniswapCallback' },\n { type: 'error', inputs: [], name: 'LiquidityTooHigh' },\n { type: 'error', inputs: [], name: 'NotAuthorized' },\n { type: 'error', inputs: [], name: 'NotEnoughLiquidityInChunk' },\n { type: 'error', inputs: [], name: 'PoolNotInitialized' },\n { type: 'error', inputs: [], name: 'PositionTooLarge' },\n {\n type: 'error',\n inputs: [{ name: 'currentTick', internalType: 'int24', type: 'int24' }],\n name: 'PriceBoundFail',\n },\n { type: 'error', inputs: [], name: 'Reentrancy' },\n {\n type: 'error',\n inputs: [\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n { name: 'balance', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'TransferFailed',\n },\n { type: 'error', inputs: [], name: 'UnderOverFlow' },\n { type: 'error', inputs: [], name: 'UnsafeRecipient' },\n { type: 'error', inputs: [], name: 'WrongUniswapPool' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// SemiFungiblePositionManagerV4\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const semiFungiblePositionManagerV4Abi = [\n {\n type: 'constructor',\n inputs: [\n {\n name: 'poolManager',\n internalType: 'contract IPoolManager',\n type: 'address',\n },\n {\n name: '_minEnforcedTickFillCost',\n internalType: 'uint256',\n type: 'uint256',\n },\n {\n name: '_nativeEnforcedTickFillCost',\n internalType: 'uint256',\n type: 'uint256',\n },\n {\n name: '_supplyMultiplierTickFill',\n internalType: 'uint256',\n type: 'uint256',\n },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'tokenId', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'balanceOf',\n outputs: [{ name: 'balance', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'owners', internalType: 'address[]', type: 'address[]' },\n { name: 'ids', internalType: 'uint256[]', type: 'uint256[]' },\n ],\n name: 'balanceOfBatch',\n outputs: [{ name: 'balances', internalType: 'uint256[]', type: 'uint256[]' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n { name: 'positionSize', internalType: 'uint128', type: 'uint128' },\n { name: 'tickLimitLow', internalType: 'int24', type: 'int24' },\n { name: 'tickLimitHigh', internalType: 'int24', type: 'int24' },\n ],\n name: 'burnTokenizedPosition',\n outputs: [\n { name: '', internalType: 'LeftRightUnsigned[4]', type: 'uint256[4]' },\n { name: '', internalType: 'LeftRightSigned', type: 'int256' },\n { name: '', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n name: 'expandEnforcedTickRange',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'tokenType', internalType: 'uint256', type: 'uint256' },\n { name: 'tickLower', internalType: 'int24', type: 'int24' },\n { name: 'tickUpper', internalType: 'int24', type: 'int24' },\n ],\n name: 'getAccountLiquidity',\n outputs: [\n {\n name: 'accountLiquidities',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'tokenType', internalType: 'uint256', type: 'uint256' },\n { name: 'tickLower', internalType: 'int24', type: 'int24' },\n { name: 'tickUpper', internalType: 'int24', type: 'int24' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n { name: 'isLong', internalType: 'uint256', type: 'uint256' },\n { name: 'vegoid', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'getAccountPremium',\n outputs: [\n { name: '', internalType: 'uint128', type: 'uint128' },\n { name: '', internalType: 'uint128', type: 'uint128' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolKey', internalType: 'bytes', type: 'bytes' }],\n name: 'getCurrentTick',\n outputs: [{ name: 'currentTick', internalType: 'int24', type: 'int24' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n name: 'getEnforcedTickLimits',\n outputs: [\n { name: '', internalType: 'int24', type: 'int24' },\n { name: '', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'id', internalType: 'bytes', type: 'bytes' },\n { name: 'vegoid', internalType: 'uint8', type: 'uint8' },\n ],\n name: 'getPoolId',\n outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n name: 'getUniswapV4PoolKeyFromId',\n outputs: [\n {\n name: '',\n internalType: 'struct PoolKey',\n type: 'tuple',\n components: [\n { name: 'currency0', internalType: 'Currency', type: 'address' },\n { name: 'currency1', internalType: 'Currency', type: 'address' },\n { name: 'fee', internalType: 'uint24', type: 'uint24' },\n { name: 'tickSpacing', internalType: 'int24', type: 'int24' },\n { name: 'hooks', internalType: 'contract IHooks', type: 'address' },\n ],\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'key',\n internalType: 'struct PoolKey',\n type: 'tuple',\n components: [\n { name: 'currency0', internalType: 'Currency', type: 'address' },\n { name: 'currency1', internalType: 'Currency', type: 'address' },\n { name: 'fee', internalType: 'uint24', type: 'uint24' },\n { name: 'tickSpacing', internalType: 'int24', type: 'int24' },\n { name: 'hooks', internalType: 'contract IHooks', type: 'address' },\n ],\n },\n { name: 'vegoid', internalType: 'uint8', type: 'uint8' },\n ],\n name: 'initializeAMMPool',\n outputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'operator', internalType: 'address', type: 'address' },\n ],\n name: 'isApprovedForAll',\n outputs: [{ name: 'approvedForAll', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n { name: 'positionSize', internalType: 'uint128', type: 'uint128' },\n { name: 'tickLimitLow', internalType: 'int24', type: 'int24' },\n { name: 'tickLimitHigh', internalType: 'int24', type: 'int24' },\n ],\n name: 'mintTokenizedPosition',\n outputs: [\n { name: '', internalType: 'LeftRightUnsigned[4]', type: 'uint256[4]' },\n { name: '', internalType: 'LeftRightSigned', type: 'int256' },\n { name: '', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes[]', type: 'bytes[]' }],\n name: 'multicall',\n outputs: [{ name: 'results', internalType: 'bytes[]', type: 'bytes[]' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'reentrancyGuardEntered',\n outputs: [{ name: 'entered', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'uint256[]', type: 'uint256[]' },\n { name: '', internalType: 'uint256[]', type: 'uint256[]' },\n { name: '', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'safeBatchTransferFrom',\n outputs: [],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n { name: '', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'safeTransferFrom',\n outputs: [],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'operator', internalType: 'address', type: 'address' },\n { name: 'approved', internalType: 'bool', type: 'bool' },\n ],\n name: 'setApprovalForAll',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'interfaceId', internalType: 'bytes4', type: 'bytes4' }],\n name: 'supportsInterface',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes', type: 'bytes' }],\n name: 'unlockCallback',\n outputs: [{ name: '', internalType: 'bytes', type: 'bytes' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'approved', internalType: 'bool', type: 'bool', indexed: false },\n ],\n name: 'ApprovalForAll',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'idV4', internalType: 'PoolId', type: 'bytes32', indexed: true },\n {\n name: 'minEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'maxEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n ],\n name: 'EnforcedTicksUpdated',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'poolId',\n internalType: 'PoolId',\n type: 'bytes32',\n indexed: true,\n },\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'tokenType',\n internalType: 'uint256',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'tickLower',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'tickUpper',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'liquidityDelta',\n internalType: 'int128',\n type: 'int128',\n indexed: false,\n },\n ],\n name: 'LiquidityChunkUpdated',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'idV4', internalType: 'PoolId', type: 'bytes32', indexed: true },\n {\n name: 'poolId',\n internalType: 'uint64',\n type: 'uint64',\n indexed: false,\n },\n {\n name: 'minEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'maxEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n ],\n name: 'PoolInitialized',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'recipient',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'positionSize',\n internalType: 'uint128',\n type: 'uint128',\n indexed: false,\n },\n ],\n name: 'TokenizedPositionBurnt',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'caller',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'positionSize',\n internalType: 'uint128',\n type: 'uint128',\n indexed: false,\n },\n ],\n name: 'TokenizedPositionMinted',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'from', internalType: 'address', type: 'address', indexed: true },\n { name: 'to', internalType: 'address', type: 'address', indexed: true },\n {\n name: 'ids',\n internalType: 'uint256[]',\n type: 'uint256[]',\n indexed: false,\n },\n {\n name: 'amounts',\n internalType: 'uint256[]',\n type: 'uint256[]',\n indexed: false,\n },\n ],\n name: 'TransferBatch',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'from', internalType: 'address', type: 'address', indexed: true },\n { name: 'to', internalType: 'address', type: 'address', indexed: true },\n { name: 'id', internalType: 'uint256', type: 'uint256', indexed: false },\n {\n name: 'amount',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'TransferSingle',\n },\n { type: 'error', inputs: [], name: 'ChunkHasZeroLiquidity' },\n { type: 'error', inputs: [], name: 'InvalidTick' },\n { type: 'error', inputs: [], name: 'InvalidTickBound' },\n {\n type: 'error',\n inputs: [{ name: 'parameterType', internalType: 'uint256', type: 'uint256' }],\n name: 'InvalidTokenIdParameter',\n },\n { type: 'error', inputs: [], name: 'LiquidityTooHigh' },\n { type: 'error', inputs: [], name: 'NotAuthorized' },\n { type: 'error', inputs: [], name: 'NotEnoughLiquidityInChunk' },\n { type: 'error', inputs: [], name: 'PoolNotInitialized' },\n { type: 'error', inputs: [], name: 'PositionTooLarge' },\n {\n type: 'error',\n inputs: [{ name: 'currentTick', internalType: 'int24', type: 'int24' }],\n name: 'PriceBoundFail',\n },\n { type: 'error', inputs: [], name: 'Reentrancy' },\n { type: 'error', inputs: [], name: 'UnauthorizedUniswapCallback' },\n { type: 'error', inputs: [], name: 'UnderOverFlow' },\n { type: 'error', inputs: [], name: 'UnsafeRecipient' },\n { type: 'error', inputs: [], name: 'WrongUniswapPool' },\n] as const\n","/**\n * Custom error ABI definitions for Panoptic v2 contracts.\n *\n * Contains all custom errors from Errors.sol with their signatures.\n * Used for decoding contract revert data.\n *\n * Selectors sourced from `forge selectors list` output.\n *\n * @module v2/errors/errorsAbi\n */\n\n/**\n * All custom errors from Panoptic Errors.sol\n *\n * Selector computation: keccak256(errorSignature)[:4]\n */\nexport const panopticErrorsAbi = [\n // AccountInsolvent(uint256 solvent, uint256 numberOfTicks) - 0xcdef092d\n {\n type: 'error',\n name: 'AccountInsolvent',\n inputs: [\n { name: 'solvent', type: 'uint256' },\n { name: 'numberOfTicks', type: 'uint256' },\n ],\n },\n\n // AlreadyInitialized() - 0x0dc149f0\n {\n type: 'error',\n name: 'AlreadyInitialized',\n inputs: [],\n },\n\n // BelowMinimumRedemption() - 0x13185bd7\n {\n type: 'error',\n name: 'BelowMinimumRedemption',\n inputs: [],\n },\n\n // CastingError() - 0xb6680045\n {\n type: 'error',\n name: 'CastingError',\n inputs: [],\n },\n\n // ChunkHasZeroLiquidity() - 0x126ae3af\n {\n type: 'error',\n name: 'ChunkHasZeroLiquidity',\n inputs: [],\n },\n\n // CreateFail() - 0xebfef188\n {\n type: 'error',\n name: 'CreateFail',\n inputs: [],\n },\n\n // DepositTooLarge() - 0xc56d46d3\n {\n type: 'error',\n name: 'DepositTooLarge',\n inputs: [],\n },\n\n // DuplicateTokenId() - 0x2bd1a05a\n {\n type: 'error',\n name: 'DuplicateTokenId',\n inputs: [],\n },\n\n // EffectiveLiquidityAboveThreshold() - 0x3a8795c2\n {\n type: 'error',\n name: 'EffectiveLiquidityAboveThreshold',\n inputs: [],\n },\n\n // ExceedsMaximumRedemption() - 0x20adf2ea\n {\n type: 'error',\n name: 'ExceedsMaximumRedemption',\n inputs: [],\n },\n\n // InputListFail() - 0x99e877ce\n {\n type: 'error',\n name: 'InputListFail',\n inputs: [],\n },\n\n // InsufficientCreditLiquidity() - 0x7a70c281\n {\n type: 'error',\n name: 'InsufficientCreditLiquidity',\n inputs: [],\n },\n\n // InvalidBuilderCode() - 0x15b3fb46\n {\n type: 'error',\n name: 'InvalidBuilderCode',\n inputs: [],\n },\n\n // InvalidTick() - 0xce8ef7fc\n {\n type: 'error',\n name: 'InvalidTick',\n inputs: [],\n },\n\n // InvalidTickBound() - 0x1577d966\n {\n type: 'error',\n name: 'InvalidTickBound',\n inputs: [],\n },\n\n // InvalidTokenIdParameter(uint256 parameterType) - 0x93db0263\n {\n type: 'error',\n name: 'InvalidTokenIdParameter',\n inputs: [{ name: 'parameterType', type: 'uint256' }],\n },\n\n // InvalidUniswapCallback() - 0x3a94c705\n {\n type: 'error',\n name: 'InvalidUniswapCallback',\n inputs: [],\n },\n\n // LengthMismatch() - 0xff633a38\n {\n type: 'error',\n name: 'LengthMismatch',\n inputs: [],\n },\n\n // LiquidityTooHigh() - 0xa500e7ea\n {\n type: 'error',\n name: 'LiquidityTooHigh',\n inputs: [],\n },\n\n // NetLiquidityZero() - 0x73582ea0\n {\n type: 'error',\n name: 'NetLiquidityZero',\n inputs: [],\n },\n\n // NoLegsExercisable() - 0x7721f7da\n {\n type: 'error',\n name: 'NoLegsExercisable',\n inputs: [],\n },\n\n // NotALongLeg() - 0xb7d44f76\n {\n type: 'error',\n name: 'NotALongLeg',\n inputs: [],\n },\n\n // NotBuilder() - 0x0404714e\n {\n type: 'error',\n name: 'NotBuilder',\n inputs: [],\n },\n\n // NotEnoughLiquidityInChunk() - 0xc56d518e\n {\n type: 'error',\n name: 'NotEnoughLiquidityInChunk',\n inputs: [],\n },\n\n // NotEnoughTokens(address tokenAddress, uint256 assetsRequested, uint256 assetBalance) - 0x71c3730b\n {\n type: 'error',\n name: 'NotEnoughTokens',\n inputs: [\n { name: 'tokenAddress', type: 'address' },\n { name: 'assetsRequested', type: 'uint256' },\n { name: 'assetBalance', type: 'uint256' },\n ],\n },\n\n // NotGuardian() - 0xef6d0f02\n {\n type: 'error',\n name: 'NotGuardian',\n inputs: [],\n },\n\n // NotMarginCalled() - 0x2a23f1ad\n {\n type: 'error',\n name: 'NotMarginCalled',\n inputs: [],\n },\n\n // NotPanopticPool() - 0x2dd1912a\n {\n type: 'error',\n name: 'NotPanopticPool',\n inputs: [],\n },\n\n // PoolNotInitialized() - 0x486aa307\n {\n type: 'error',\n name: 'PoolNotInitialized',\n inputs: [],\n },\n\n // PositionCountNotZero() - 0x2501f81e\n {\n type: 'error',\n name: 'PositionCountNotZero',\n inputs: [],\n },\n\n // PositionNotOwned() - 0x00bd51c8\n {\n type: 'error',\n name: 'PositionNotOwned',\n inputs: [],\n },\n\n // PositionTooLarge() - 0x543a6e10\n {\n type: 'error',\n name: 'PositionTooLarge',\n inputs: [],\n },\n\n // PriceBoundFail(int24 currentTick) - 0x618ea40c\n {\n type: 'error',\n name: 'PriceBoundFail',\n inputs: [{ name: 'currentTick', type: 'int24' }],\n },\n\n // PriceImpactTooLarge() - 0xcbe5b9a6\n {\n type: 'error',\n name: 'PriceImpactTooLarge',\n inputs: [],\n },\n\n // Reentrancy() - 0xab143c06\n {\n type: 'error',\n name: 'Reentrancy',\n inputs: [],\n },\n\n // StaleOracle() - 0x88cce429\n {\n type: 'error',\n name: 'StaleOracle',\n inputs: [],\n },\n\n // TokenIdHasZeroLegs() - 0x9cd92fb2\n {\n type: 'error',\n name: 'TokenIdHasZeroLegs',\n inputs: [],\n },\n\n // TooManyLegsOpen() - 0x0ed7e777\n {\n type: 'error',\n name: 'TooManyLegsOpen',\n inputs: [],\n },\n\n // TransferFailed(address token, address from, uint256 amount, uint256 balance) - 0x81f20f86\n {\n type: 'error',\n name: 'TransferFailed',\n inputs: [\n { name: 'token', type: 'address' },\n { name: 'from', type: 'address' },\n { name: 'amount', type: 'uint256' },\n { name: 'balance', type: 'uint256' },\n ],\n },\n\n // UnauthorizedUniswapCallback() - 0x3e30718a\n {\n type: 'error',\n name: 'UnauthorizedUniswapCallback',\n inputs: [],\n },\n\n // UnderOverFlow() - 0xd2190174\n {\n type: 'error',\n name: 'UnderOverFlow',\n inputs: [],\n },\n\n // WrongPoolId() - 0xcfa4bfa2\n {\n type: 'error',\n name: 'WrongPoolId',\n inputs: [],\n },\n\n // WrongUniswapPool() - 0x768778de\n {\n type: 'error',\n name: 'WrongUniswapPool',\n inputs: [],\n },\n\n // ZeroAddress() - 0xd92e233d\n {\n type: 'error',\n name: 'ZeroAddress',\n inputs: [],\n },\n\n // ZeroCollateralRequirement() - 0x5b8edb4a\n {\n type: 'error',\n name: 'ZeroCollateralRequirement',\n inputs: [],\n },\n] as const\n","/**\n * Error parsing utilities for the Panoptic v2 SDK.\n *\n * Converts raw contract errors into typed SDK error classes.\n *\n * @module v2/errors/parser\n */\n\nimport { type Abi, BaseError, decodeErrorResult, toFunctionSelector } from 'viem'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi, riskEngineAbi } from '../../../generated'\nimport { PanopticError } from './base'\nimport {\n // Solvency & Margin\n AccountInsolventError,\n AlreadyInitializedError,\n BelowMinimumRedemptionError,\n CastingError,\n // Liquidity\n ChunkHasZeroLiquidityError,\n CreateFailError,\n DepositTooLargeError,\n DuplicateTokenIdError,\n EffectiveLiquidityAboveThresholdError,\n ExceedsMaximumRedemptionError,\n InputListFailError,\n InsufficientCreditLiquidityError,\n InvalidBuilderCodeError,\n InvalidTickBoundError,\n // Tick & Price\n InvalidTickError,\n // Position & TokenId\n InvalidTokenIdParameterError,\n InvalidUniswapCallbackError,\n LengthMismatchError,\n LiquidityTooHighError,\n NetLiquidityZeroError,\n // Exercise\n NoLegsExercisableError,\n NotALongLegError,\n NotBuilderError,\n NotEnoughLiquidityInChunkError,\n // Token & Collateral\n NotEnoughTokensError,\n NotGuardianError,\n NotMarginCalledError,\n // Authorization\n NotPanopticPoolError,\n // Pool & Initialization\n PoolNotInitializedError,\n PositionCountNotZeroError,\n PositionNotOwnedError,\n PositionTooLargeError,\n PriceBoundFailError,\n PriceImpactTooLargeError,\n // Reentrancy\n ReentrancyError,\n // Oracle & Safe Mode\n StaleOracleError,\n TokenIdHasZeroLegsError,\n TooManyLegsOpenError,\n // Transfer & Casting\n TransferFailedError,\n UnauthorizedUniswapCallbackError,\n UnderOverFlowError,\n WrongPoolIdError,\n WrongUniswapPoolError,\n // Other\n ZeroAddressError,\n ZeroCollateralRequirementError,\n} from './contract'\nimport { panopticErrorsAbi } from './errorsAbi'\n\n/**\n * Result of parsing a Panoptic error.\n */\nexport interface ParsedError {\n /** The parsed error instance */\n error: PanopticError\n /** The original error name from the contract */\n errorName: string\n /** The decoded error arguments */\n args: readonly unknown[]\n}\n\n/**\n * Combined ABI for error decoding.\n * Includes the dedicated errors ABI for complete coverage.\n */\nconst combinedAbi = [\n ...panopticPoolV2Abi,\n ...collateralTrackerV2Abi,\n ...riskEngineAbi,\n ...panopticErrorsAbi,\n] as Abi\n\n/**\n * Map of error names to error constructors.\n */\nconst errorConstructors: Record<\n string,\n (args: readonly unknown[], cause?: Error) => PanopticError\n> = {\n // Solvency & Margin\n AccountInsolvent: (args, cause) =>\n new AccountInsolventError(args[0] as bigint, args[1] as bigint, cause),\n NotMarginCalled: (_args, cause) => new NotMarginCalledError(cause),\n\n // Factory\n CreateFail: (_args, cause) => new CreateFailError(cause),\n\n // Token & Collateral\n NotEnoughTokens: (args, cause) =>\n new NotEnoughTokensError(args[0] as `0x${string}`, args[1] as bigint, args[2] as bigint, cause),\n NotEnoughLiquidityInChunk: (_args, cause) => new NotEnoughLiquidityInChunkError(cause),\n InsufficientCreditLiquidity: (_args, cause) => new InsufficientCreditLiquidityError(cause),\n DepositTooLarge: (_args, cause) => new DepositTooLargeError(cause),\n BelowMinimumRedemption: (_args, cause) => new BelowMinimumRedemptionError(cause),\n ExceedsMaximumRedemption: (_args, cause) => new ExceedsMaximumRedemptionError(cause),\n ZeroCollateralRequirement: (_args, cause) => new ZeroCollateralRequirementError(cause),\n\n // Position & TokenId\n InvalidTokenIdParameter: (args, cause) =>\n new InvalidTokenIdParameterError(args[0] as bigint, cause),\n PositionNotOwned: (_args, cause) => new PositionNotOwnedError(cause),\n PositionTooLarge: (_args, cause) => new PositionTooLargeError(cause),\n PositionCountNotZero: (_args, cause) => new PositionCountNotZeroError(cause),\n DuplicateTokenId: (_args, cause) => new DuplicateTokenIdError(cause),\n TokenIdHasZeroLegs: (_args, cause) => new TokenIdHasZeroLegsError(cause),\n TooManyLegsOpen: (_args, cause) => new TooManyLegsOpenError(cause),\n InputListFail: (_args, cause) => new InputListFailError(cause),\n\n // Tick & Price\n InvalidTick: (_args, cause) => new InvalidTickError(cause),\n InvalidTickBound: (_args, cause) => new InvalidTickBoundError(cause),\n PriceBoundFail: (args, cause) => new PriceBoundFailError(args[0] as bigint, cause),\n PriceImpactTooLarge: (_args, cause) => new PriceImpactTooLargeError(cause),\n\n // Liquidity\n ChunkHasZeroLiquidity: (_args, cause) => new ChunkHasZeroLiquidityError(cause),\n LiquidityTooHigh: (_args, cause) => new LiquidityTooHighError(cause),\n NetLiquidityZero: (_args, cause) => new NetLiquidityZeroError(cause),\n EffectiveLiquidityAboveThreshold: (_args, cause) =>\n new EffectiveLiquidityAboveThresholdError(cause),\n\n // Oracle & Safe Mode\n StaleOracle: (_args, cause) => new StaleOracleError(cause),\n\n // Exercise\n NoLegsExercisable: (_args, cause) => new NoLegsExercisableError(cause),\n NotALongLeg: (_args, cause) => new NotALongLegError(cause),\n\n // Pool & Initialization\n PoolNotInitialized: (_args, cause) => new PoolNotInitializedError(cause),\n AlreadyInitialized: (_args, cause) => new AlreadyInitializedError(cause),\n WrongPoolId: (_args, cause) => new WrongPoolIdError(cause),\n WrongUniswapPool: (_args, cause) => new WrongUniswapPoolError(cause),\n\n // Authorization\n NotPanopticPool: (_args, cause) => new NotPanopticPoolError(cause),\n NotGuardian: (_args, cause) => new NotGuardianError(cause),\n NotBuilder: (_args, cause) => new NotBuilderError(cause),\n InvalidBuilderCode: (_args, cause) => new InvalidBuilderCodeError(cause),\n InvalidUniswapCallback: (_args, cause) => new InvalidUniswapCallbackError(cause),\n UnauthorizedUniswapCallback: (_args, cause) => new UnauthorizedUniswapCallbackError(cause),\n\n // Transfer & Casting\n TransferFailed: (args, cause) =>\n new TransferFailedError(\n args[0] as `0x${string}`,\n args[1] as `0x${string}`,\n args[2] as bigint,\n args[3] as bigint,\n cause,\n ),\n CastingError: (_args, cause) => new CastingError(cause),\n UnderOverFlow: (_args, cause) => new UnderOverFlowError(cause),\n\n // Reentrancy\n Reentrancy: (_args, cause) => new ReentrancyError(cause),\n\n // Other\n ZeroAddress: (_args, cause) => new ZeroAddressError(cause),\n LengthMismatch: (_args, cause) => new LengthMismatchError(cause),\n}\n\n/**\n * Parse a raw contract error into a typed SDK error.\n *\n * This function attempts to decode the error data from a failed contract call\n * and return a typed error instance with extracted parameters.\n *\n * @param error - The raw error from a failed contract call\n * @returns Parsed error with typed error instance, or null if parsing fails\n *\n * @example\n * ```typescript\n * try {\n * await contract.openPosition(...)\n * } catch (rawError) {\n * const parsed = parsePanopticError(rawError)\n * if (parsed) {\n * console.log('Error:', parsed.errorName)\n * if (parsed.error instanceof AccountInsolventError) {\n * console.log('Solvent value:', parsed.error.solvent)\n * }\n * }\n * }\n * ```\n */\nexport function parsePanopticError(error: unknown): ParsedError | null {\n // Strategy 1: Check if viem already decoded the error (ContractFunctionRevertedError.data)\n const viemDecoded = extractViemDecodedError(error)\n if (viemDecoded) {\n return buildParsedError(viemDecoded.errorName, viemDecoded.args, error)\n }\n\n // Strategy 2: Extract raw hex data and decode ourselves\n const errorData = extractErrorData(error)\n if (!errorData) return null\n\n try {\n const decoded = decodeErrorResult({\n abi: combinedAbi,\n data: errorData,\n })\n\n return buildParsedError(decoded.errorName, decoded.args ?? [], error)\n } catch {\n // decodeErrorResult failed — possibly we only have the 4-byte selector\n // (e.g. from a multicall error message). Try matching the selector manually.\n if (errorData.length >= 10) {\n const selector = errorData.slice(0, 10) as `0x${string}`\n const match = matchSelectorToErrorName(selector)\n if (match) {\n return buildParsedError(match, [], error)\n }\n }\n return null\n }\n}\n\n/**\n * Walk the cause chain looking for a viem ContractFunctionRevertedError\n * that already has decoded `.data` (an object with `errorName` and `args`).\n * This happens when the ABI passed to simulateContract includes the error definitions.\n */\nfunction extractViemDecodedError(\n error: unknown,\n): { errorName: string; args: readonly unknown[] } | null {\n if (!error || typeof error !== 'object') return null\n\n // Use BaseError.walk if available\n if (error instanceof BaseError) {\n let found: { errorName: string; args: readonly unknown[] } | null = null\n error.walk((e) => {\n if (found) return false\n const node = e as Record<string, unknown>\n if (\n node.data &&\n typeof node.data === 'object' &&\n 'errorName' in (node.data as object) &&\n typeof (node.data as Record<string, unknown>).errorName === 'string'\n ) {\n const data = node.data as { errorName: string; args?: readonly unknown[] }\n found = { errorName: data.errorName, args: data.args ?? [] }\n return true\n }\n return false\n })\n return found\n }\n\n // Manual walk for non-viem errors\n let current: Record<string, unknown> | null = error as Record<string, unknown>\n for (let i = 0; i < 10 && current; i++) {\n if (\n current.data &&\n typeof current.data === 'object' &&\n 'errorName' in (current.data as object) &&\n typeof (current.data as Record<string, unknown>).errorName === 'string'\n ) {\n const data = current.data as { errorName: string; args?: readonly unknown[] }\n return { errorName: data.errorName, args: data.args ?? [] }\n }\n current =\n current.cause && typeof current.cause === 'object'\n ? (current.cause as Record<string, unknown>)\n : null\n }\n\n return null\n}\n\n/**\n * Build a ParsedError from a decoded error name and args.\n */\nfunction buildParsedError(\n errorName: string,\n args: readonly unknown[],\n originalError: unknown,\n): ParsedError {\n const constructor = errorConstructors[errorName]\n const cause = originalError instanceof Error ? originalError : undefined\n\n if (!constructor) {\n const unknownError = new PanopticError(`Unknown contract error: ${errorName}`)\n unknownError.errorName = errorName\n return { error: unknownError, errorName, args }\n }\n\n const typedError = constructor(args, cause)\n typedError.errorName = errorName\n return { error: typedError, errorName, args }\n}\n\n/**\n * Match a 4-byte selector against the panoptic errors ABI.\n * Used as fallback when we only have the selector (no encoded args).\n */\nfunction matchSelectorToErrorName(selector: `0x${string}`): string | null {\n for (const item of panopticErrorsAbi) {\n if (item.type !== 'error') continue\n const computed = toFunctionSelector(\n `${item.name}(${item.inputs.map((i: { type: string }) => i.type).join(',')})`,\n )\n if (computed === selector) {\n return item.name\n }\n }\n return null\n}\n\n/**\n * Extract error data from various error formats.\n *\n * Strategy:\n * 1. Use viem's BaseError.walk() to traverse the full cause chain and find\n * hex data on any node (handles arbitrary nesting depth for multicall etc.)\n * 2. Fall back to manual cause-chain walk for non-viem errors\n * 3. Last resort: extract selector from error message (loses args)\n */\nfunction extractErrorData(error: unknown): `0x${string}` | null {\n if (!error) return null\n\n // Direct hex data\n if (typeof error === 'string' && error.startsWith('0x')) {\n return error as `0x${string}`\n }\n\n if (typeof error !== 'object') return null\n\n // Strategy 1: Use viem's BaseError.walk() — traverses the full cause chain\n if (error instanceof BaseError) {\n let foundData: `0x${string}` | null = null\n\n error.walk((e) => {\n if (foundData) return false\n const node = e as Record<string, unknown>\n\n // Check .data as hex string (full revert bytes on RPC errors)\n if (node.data && typeof node.data === 'string' && node.data.startsWith('0x')) {\n foundData = node.data as `0x${string}`\n return true\n }\n\n // Check .data.data (some RPC providers nest: { data: { data: '0x...' } })\n if (node.data && typeof node.data === 'object') {\n const nested = node.data as Record<string, unknown>\n if (nested.data && typeof nested.data === 'string' && nested.data.startsWith('0x')) {\n foundData = nested.data as `0x${string}`\n return true\n }\n }\n\n return false\n })\n\n if (foundData) return foundData\n\n // Also check .signature on walked nodes (viem stores raw selector here\n // when it can't decode against the provided ABI)\n error.walk((e) => {\n if (foundData) return false\n const node = e as Record<string, unknown>\n if (node.signature && typeof node.signature === 'string' && node.signature.startsWith('0x')) {\n foundData = node.signature as `0x${string}`\n return true\n }\n return false\n })\n\n if (foundData) return foundData\n }\n\n // Strategy 2: Manual cause-chain walk for non-viem errors\n let current: Record<string, unknown> | null = error as Record<string, unknown>\n const maxDepth = 10\n for (let i = 0; i < maxDepth && current; i++) {\n if (current.data && typeof current.data === 'string' && current.data.startsWith('0x')) {\n return current.data as `0x${string}`\n }\n\n if (current.data && typeof current.data === 'object') {\n const nested = current.data as Record<string, unknown>\n if (nested.data && typeof nested.data === 'string' && nested.data.startsWith('0x')) {\n return nested.data as `0x${string}`\n }\n }\n\n if (current.error && typeof current.error === 'object') {\n const rpcError = current.error as Record<string, unknown>\n if (rpcError.data && typeof rpcError.data === 'string' && rpcError.data.startsWith('0x')) {\n return rpcError.data as `0x${string}`\n }\n }\n\n current =\n current.cause && typeof current.cause === 'object'\n ? (current.cause as Record<string, unknown>)\n : null\n }\n\n // Strategy 3: Extract from error message (last resort — may only have 4-byte selector)\n const obj = error as Record<string, unknown>\n if (obj.message && typeof obj.message === 'string') {\n const signatureMatch = obj.message.match(/signature:\\s*(0x[a-fA-F0-9]{8,})/i)\n if (signatureMatch) {\n return signatureMatch[1] as `0x${string}`\n }\n }\n\n return null\n}\n\n/**\n * Check if an error is a specific Panoptic error type.\n *\n * @param error - The error to check\n * @param errorClass - The error class to check against\n * @returns True if the error is an instance of the specified class\n *\n * @example\n * ```typescript\n * const parsed = parsePanopticError(error)\n * if (parsed && isPanopticErrorType(parsed.error, AccountInsolventError)) {\n * console.log('Account is insolvent!')\n * }\n * ```\n */\nexport function isPanopticErrorType<T extends PanopticError>(\n error: PanopticError,\n errorClass: abstract new (...args: never[]) => T,\n): error is T {\n return error instanceof errorClass\n}\n","/**\n * TokenId constants for the Panoptic v2 SDK.\n * @module v2/tokenId/constants\n */\n\n/**\n * Default vegoid value used in pool ID encoding.\n */\nexport const DEFAULT_VEGOID = 8n\n\n/**\n * Default MAX_SPREAD value (90_000 = 9 * 10_000).\n * On-chain: removed/net ratio cap, in units of 1/10_000.\n */\nexport const DEFAULT_MAX_SPREAD = 90_000n\n\n/**\n * Standard tick widths matching DTE gamma profiles.\n *\n * These represent the position width in ticks for each timescale.\n * Width = tickUpper - tickLower.\n */\nexport const STANDARD_TICK_WIDTHS = {\n /** 1-hour expiry profile (240 ticks) */\n '1H': 240n,\n /** 1-day expiry profile (720 ticks) */\n '1D': 720n,\n /** 1-week expiry profile (2400 ticks) */\n '1W': 2400n,\n /** 1-month expiry profile (4800 ticks) */\n '1M': 4800n,\n /** 1-year expiry profile (15000 ticks) */\n '1Y': 15000n,\n} as const\n\n/**\n * Timescale key type for STANDARD_TICK_WIDTHS.\n */\nexport type Timescale = keyof typeof STANDARD_TICK_WIDTHS\n\n/**\n * Bit positions and sizes for TokenId encoding.\n */\nexport const TOKEN_ID_BITS = {\n /** Pool ID occupies bits 0-63 */\n POOL_ID_SIZE: 64n,\n /** Vegoid starts at bit 40 within pool ID */\n VEGOID_STARTING_BIT: 40n,\n /** Vegoid is 8 bits */\n VEGOID_SIZE: 8n,\n /** Tick spacing starts at bit 48 within pool ID */\n TICK_SPACING_STARTING_BIT: 48n,\n /** Tick spacing is 16 bits */\n TICK_SPACING_SIZE: 16n,\n /** Each leg is 48 bits */\n LEG_SIZE: 48n,\n /** Maximum number of legs per TokenId */\n MAX_LEGS: 4n,\n} as const\n\n/**\n * Bit positions within a leg (relative to leg start).\n */\nexport const LEG_BITS = {\n /** Asset bit position */\n ASSET_BIT: 0n,\n /** Asset size in bits */\n ASSET_SIZE: 1n,\n /** Option ratio starting bit */\n RATIO_BIT: 1n,\n /** Option ratio size in bits */\n RATIO_SIZE: 7n,\n /** Is long starting bit */\n IS_LONG_BIT: 8n,\n /** Is long size in bits */\n IS_LONG_SIZE: 1n,\n /** Token type starting bit */\n TOKEN_TYPE_BIT: 9n,\n /** Token type size in bits */\n TOKEN_TYPE_SIZE: 1n,\n /** Risk partner starting bit */\n RISK_PARTNER_BIT: 10n,\n /** Risk partner size in bits */\n RISK_PARTNER_SIZE: 2n,\n /** Strike starting bit */\n STRIKE_BIT: 12n,\n /** Strike size in bits (24 bits, signed int24) */\n STRIKE_SIZE: 24n,\n /** Width starting bit */\n WIDTH_BIT: 36n,\n /** Width size in bits */\n WIDTH_SIZE: 12n,\n} as const\n\n/**\n * Masks for extracting/encoding leg fields.\n */\nexport const LEG_MASKS = {\n /** Mask for asset (1 bit) */\n ASSET: (1n << LEG_BITS.ASSET_SIZE) - 1n,\n /** Mask for option ratio (7 bits) */\n RATIO: (1n << LEG_BITS.RATIO_SIZE) - 1n,\n /** Mask for is long (1 bit) */\n IS_LONG: (1n << LEG_BITS.IS_LONG_SIZE) - 1n,\n /** Mask for token type (1 bit) */\n TOKEN_TYPE: (1n << LEG_BITS.TOKEN_TYPE_SIZE) - 1n,\n /** Mask for risk partner (2 bits) */\n RISK_PARTNER: (1n << LEG_BITS.RISK_PARTNER_SIZE) - 1n,\n /** Mask for strike (24 bits) */\n STRIKE: (1n << LEG_BITS.STRIKE_SIZE) - 1n,\n /** Mask for width (12 bits) */\n WIDTH: (1n << LEG_BITS.WIDTH_SIZE) - 1n,\n /** Mask for entire leg (48 bits) */\n LEG: (1n << TOKEN_ID_BITS.LEG_SIZE) - 1n,\n} as const\n\n/**\n * Maximum and minimum values for leg fields.\n */\nexport const LEG_LIMITS = {\n /** Maximum option ratio (127) */\n MAX_RATIO: 127n,\n /** Maximum width (4095) */\n MAX_WIDTH: 4095n,\n /** Maximum strike (8388607, max int24 positive) */\n MAX_STRIKE: 8388607n,\n /** Minimum strike (-8388608, min int24) */\n MIN_STRIKE: -8388608n,\n} as const\n\n/**\n * Value used to convert negative strike to unsigned representation.\n * Strike is stored as int24, so we use 2^24 for conversion.\n */\nexport const STRIKE_CONVERSION_FACTOR = 16777216n\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 * Derive a unique tokenId to mint alongside a burn (position reduction / roll).\n *\n * dispatch() cannot partial-close a held tokenId — a same-tokenId size change\n * is interpreted as `settlePremium`. To reduce, we burn the old tokenId and\n * mint a DIFFERENT tokenId with the desired smaller size in one dispatch. The\n * new tokenId must merely be unique from the old one.\n *\n * Two derivation paths:\n * 1. **Tiny credit leg (default)** — when the base has a free leg slot\n * (< 4 legs), append a width=0 credit (isLong=1) leg with an extreme\n * strike so its token notional (`positionSize · 1.0001^strike`) rounds\n * down to ~1 wei — tokenId-uniquifying but economically negligible. New\n * positionSize can be any value ≤ current size; arbitrary reduction\n * amounts fall out.\n * 2. **Ratio scaling (fallback)** — only when all 4 leg slots are used:\n * multiply every leg's optionRatio by a factor `N` such that\n * `N · max(optionRatio) ≤ 127`, then set\n * `newPositionSize = ceil(targetSize / N)`. Per-leg preserved liquidity\n * is `newPositionSize · N`, so the reduce still satisfies the target.\n *\n * @module v2/tokenId/deriveUniqueTokenId\n */\n\nimport { PanopticError } from '../errors'\nimport { sqrtPriceX96ToTick } from '../formatters/tick'\nimport { MAX_TICK, MIN_TICK } from '../utils/constants'\nimport { LEG_LIMITS, TOKEN_ID_BITS } from './constants'\nimport { addLegToTokenId, countLegs, decodeAllLegs, decodeLeg } from './encoding'\n\nconst POOL_ID_MASK = (1n << 64n) - 1n\nconst MAX_LEGS = TOKEN_ID_BITS.MAX_LEGS\nconst MAX_OPTION_RATIO = LEG_LIMITS.MAX_RATIO\nconst Q192 = 1n << 192n\n\nexport type DeriveStrategy = 'tiny-credit' | 'ratio-scale'\n\nexport interface DeriveUniqueTokenIdParams {\n /** Base tokenId to derive a unique sibling from. */\n baseTokenId: bigint\n /**\n * Desired new positionSize. Must be > 0 and ≤ the CURRENT stored\n * positionSize on the tokenId being reduced.\n *\n * For `ratio-scale` the effective size (`newPositionSize · N`) may exceed\n * this by a rounding-up wei. `newPositionSize` in the result reflects\n * exactly what to pass to dispatch.\n */\n targetPositionSize: bigint\n /**\n * Pool tickSpacing. Used to keep the appended credit leg's tick range\n * (SFPM internally widens width=0 to a width-2 chunk: `strike ± tickSpacing`)\n * strictly inside `[MIN_POOL_TICK, MAX_POOL_TICK]`. Omit to use a\n * worst-case Uniswap-v3 default of 200.\n */\n tickSpacing?: bigint\n}\n\nexport interface DeriveUniqueTokenIdResult {\n newTokenId: bigint\n /** positionSize to pass to dispatch for the new tokenId. */\n newPositionSize: bigint\n /**\n * Real per-leg liquidity the new tokenId will hold, expressed in the\n * base-token positionSize frame. Equals `newPositionSize · N` for\n * `ratio-scale` (where N is the applied optionRatio multiplier) and\n * `newPositionSize` for `tiny-credit`. Consumers should compare this\n * against the base tokenId's current stored size to validate that a\n * reduction is actually smaller (or, for `ratio-scale`, that the ceiling\n * rounding did not push effective size above the stored size).\n */\n effectivePositionSize: bigint\n strategy: DeriveStrategy\n}\n\n/**\n * Floor integer square root for bigints (Newton's method). Mirrors the isqrt\n * used in reads/collateralEstimate.ts (buildNeutralLeg).\n */\nfunction isqrt(value: bigint): bigint {\n if (value < 0n) throw new PanopticError('isqrt of negative number')\n if (value < 2n) return value\n let x = value\n let y = (x + 1n) >> 1n\n while (y < x) {\n x = y\n y = (x + value / x) >> 1n\n }\n return x\n}\n\nconst DEFAULT_TICK_SPACING = 200n\n\n/**\n * Target notional (in wei of the tokenType-side asset) for the appended\n * tiny credit leg. Chosen at 10 wei — small enough to be economically\n * meaningless against any real position size, large enough to safely\n * clear rounding on the SFPM's width-2 internal chunk math without any\n * risk of underflowing to zero (which would revert ChunkHasZeroLiquidity).\n */\nconst TINY_CREDIT_TARGET_NOTIONAL_WEI = 10n\n\n/**\n * Pick a signedStrike for the appended width=0 credit leg such that:\n * 1. positionSize · 1.0001^signedStrike ≈ TINY_CREDIT_TARGET_NOTIONAL_WEI\n * (~10 wei — economically meaningless but comfortably above any\n * SFPM width-2 chunk rounding);\n * 2. the leg's tick range (SFPM internally treats width=0 as width=2, so\n * the range is `strike ± tickSpacing`) stays strictly inside\n * `[MIN_POOL_TICK, MAX_POOL_TICK]` — otherwise the getSqrtRatioAtTick\n * call reverts with `InvalidTick`.\n *\n * Closed form: `1.0001^signedStrike = target/positionSize`, so\n * `sqrtKrawX96 = isqrt(target · 2^192 / positionSize)` and\n * `signedStrike = sqrtPriceX96ToTick(sqrtKrawX96)`. If the notional-optimal\n * strike falls outside the safe range, we clamp inward. Clamping raises the\n * notional but keeps it << position size for any reasonable strike.\n */\nfunction computeTinyCreditSignedStrike(positionSize: bigint, tickSpacing: bigint): bigint {\n if (positionSize <= 0n) {\n throw new PanopticError('computeTinyCreditSignedStrike: positionSize must be > 0')\n }\n // Leave one tickSpacing of buffer on each side + 1 tick of headroom so the\n // width-2 chunk (strike ± tickSpacing) stays strictly inside the pool bounds.\n const minSafe = MIN_TICK + tickSpacing + 1n\n const maxSafe = MAX_TICK - tickSpacing - 1n\n\n let signedStrike: bigint\n try {\n const sqrtKrawX96 = isqrt((TINY_CREDIT_TARGET_NOTIONAL_WEI * Q192) / positionSize)\n signedStrike = sqrtPriceX96ToTick(sqrtKrawX96)\n } catch {\n // sqrtPriceX96ToTick rejects out-of-bounds sqrt prices; that only happens\n // for extreme (>> 2^128) or dust positionSizes. Fall back to the min-safe\n // edge, which still gives a tiny notional relative to any real position.\n signedStrike = minSafe\n }\n\n if (signedStrike < minSafe) return minSafe\n if (signedStrike > maxSafe) return maxSafe\n return signedStrike\n}\n\n/**\n * Assemble the tiny credit leg struct, picking a strike that avoids\n * colliding with any existing width=0 credit leg on the same (asset,\n * tokenType) pair.\n *\n * The encoded strike stored in the tokenId is\n * `asset === 0 ? signedStrike : -signedStrike` (mirrors\n * {@link buildNeutralLeg} in reads/collateralEstimate.ts).\n */\nfunction pickUniqueTinyCreditLeg(\n baseTokenId: bigint,\n legIndex: bigint,\n positionSize: bigint,\n tickSpacing: bigint,\n): {\n index: bigint\n asset: bigint\n tokenType: bigint\n optionRatio: bigint\n isLong: bigint\n riskPartner: bigint\n strike: bigint\n width: bigint\n} {\n const asset: bigint = 1n\n const tokenType: bigint = 0n\n\n const existingLegs = decodeAllLegs(baseTokenId)\n const maxSafe = MAX_TICK - tickSpacing - 1n\n\n let signedStrike = computeTinyCreditSignedStrike(positionSize, tickSpacing)\n while (signedStrike <= maxSafe) {\n const candidate = asset === 0n ? signedStrike : -signedStrike\n let collides = false\n for (const leg of existingLegs) {\n if (\n leg.width === 0n &&\n leg.isLong &&\n leg.asset === asset &&\n leg.tokenType === tokenType &&\n leg.strike === candidate\n ) {\n collides = true\n break\n }\n }\n if (!collides) break\n signedStrike += 1n\n }\n if (signedStrike > maxSafe) {\n throw new PanopticError(\n 'deriveUniqueTokenId: exhausted strike space picking a unique tiny credit leg',\n )\n }\n\n const encodedStrike = asset === 0n ? signedStrike : -signedStrike\n\n return {\n index: legIndex,\n asset,\n tokenType,\n optionRatio: 1n,\n isLong: 1n,\n riskPartner: legIndex,\n strike: encodedStrike,\n width: 0n,\n }\n}\n\nfunction appendTinyCreditLeg(\n baseTokenId: bigint,\n baseLegCount: bigint,\n positionSize: bigint,\n tickSpacing: bigint,\n): bigint {\n const newLeg = pickUniqueTinyCreditLeg(baseTokenId, baseLegCount, positionSize, tickSpacing)\n return addLegToTokenId(baseTokenId, newLeg)\n}\n\nfunction scaleRatios(baseTokenId: bigint, targetPositionSize: bigint): DeriveUniqueTokenIdResult {\n const legs = decodeAllLegs(baseTokenId)\n const maxRatio = legs.reduce<bigint>((m, leg) => (leg.optionRatio > m ? leg.optionRatio : m), 0n)\n const N = MAX_OPTION_RATIO / maxRatio\n if (N < 2n) {\n throw new PanopticError(\n 'deriveUniqueTokenId: cannot derive a unique tokenId — all 4 leg slots used and optionRatios already near the 127 ceiling',\n )\n }\n // Preserved per-leg liquidity = newSize · N. ceil ensures effective size ≥ target.\n const newPositionSize = (targetPositionSize + N - 1n) / N\n\n const poolId = baseTokenId & POOL_ID_MASK\n let out = poolId\n for (const leg of legs) {\n out = addLegToTokenId(out, {\n index: leg.index,\n asset: leg.asset,\n tokenType: leg.tokenType,\n optionRatio: leg.optionRatio * N,\n isLong: leg.isLong ? 1n : 0n,\n riskPartner: leg.riskPartner,\n strike: leg.strike,\n width: leg.width,\n })\n }\n return {\n newTokenId: out,\n newPositionSize,\n effectivePositionSize: newPositionSize * N,\n strategy: 'ratio-scale',\n }\n}\n\n/**\n * Derive a tokenId unique from `baseTokenId` for a partial reduction.\n *\n * Prefers a tiny-credit-leg extension (arbitrary new size). Falls back to\n * optionRatio scaling only when the base tokenId already occupies all 4 leg\n * slots.\n */\nexport function deriveUniqueTokenId(params: DeriveUniqueTokenIdParams): DeriveUniqueTokenIdResult {\n const { baseTokenId, targetPositionSize, tickSpacing = DEFAULT_TICK_SPACING } = params\n\n if (targetPositionSize <= 0n) {\n throw new PanopticError('deriveUniqueTokenId: targetPositionSize must be > 0')\n }\n\n const legCount = countLegs(baseTokenId)\n if (legCount === 0n) {\n throw new PanopticError('deriveUniqueTokenId: baseTokenId has no legs')\n }\n\n if (legCount < MAX_LEGS) {\n const newTokenId = appendTinyCreditLeg(baseTokenId, legCount, targetPositionSize, tickSpacing)\n return {\n newTokenId,\n newPositionSize: targetPositionSize,\n effectivePositionSize: targetPositionSize,\n strategy: 'tiny-credit',\n }\n }\n\n return scaleRatios(baseTokenId, targetPositionSize)\n}\n\n/**\n * Test hook: exposed only to make the tiny-credit leg strike inspectable.\n * @internal\n */\nexport function _pickUniqueTinyCreditLegForTests(\n baseTokenId: bigint,\n legIndex: bigint,\n positionSize: bigint = 10n ** 18n,\n tickSpacing: bigint = DEFAULT_TICK_SPACING,\n) {\n return pickUniqueTinyCreditLeg(baseTokenId, legIndex, positionSize, tickSpacing)\n}\n\n/**\n * Re-export decoded leg count so callers can gate UI on the strategy that\n * would be chosen (e.g. show a divisibility hint on ratio-scale positions).\n */\nexport function planDeriveStrategy(baseTokenId: bigint): DeriveStrategy {\n return countLegs(baseTokenId) < MAX_LEGS ? 'tiny-credit' : 'ratio-scale'\n}\n\n// Re-export used by consumers who only need the leg-count helper.\nexport { decodeLeg }\n","/**\n * Per-second rate helpers.\n *\n * Collateral tracker rates are returned as WAD-scaled per-second rates.\n * These helpers annualize them for display.\n *\n * @module v2/formatters/rates\n */\n\nimport { formatWadPercent } from './wad'\n\nconst SECONDS_PER_DAY = 86_400n\nconst DAYS_PER_YEAR = 365n\nconst SECONDS_PER_YEAR = SECONDS_PER_DAY * DAYS_PER_YEAR\n\n/**\n * Annualize a per-second WAD-scaled rate to annual WAD.\n *\n * @param ratePerSecondWad - Rate in WAD per second\n * @returns Annualized rate in WAD\n */\nexport function annualizePerSecondRateWad(ratePerSecondWad: bigint): bigint {\n return ratePerSecondWad * SECONDS_PER_YEAR\n}\n\n/**\n * Format a per-second WAD rate as APY percentage text.\n * Uses linear annualization, then formats as WAD percent.\n *\n * @param ratePerSecondWad - Rate in WAD per second\n * @param precision - Decimal places\n * @returns Percentage string, e.g. \"2.41%\"\n */\nexport function formatPerSecondRateWadAsApyPct(\n ratePerSecondWad: bigint,\n precision: bigint,\n): string {\n return formatWadPercent(annualizePerSecondRateWad(ratePerSecondWad), precision)\n}\n\n/**\n * Format a per-second WAD rate as APR percentage text.\n * For this rate model, APR presentation uses the same annualized output.\n *\n * @param ratePerSecondWad - Rate in WAD per second\n * @param precision - Decimal places\n * @returns Percentage string, e.g. \"2.41%\"\n */\nexport function formatPerSecondRateWadAsAprPct(\n ratePerSecondWad: bigint,\n precision: bigint,\n): string {\n return formatWadPercent(annualizePerSecondRateWad(ratePerSecondWad), precision)\n}\n","/**\n * Pure generation of fixed-price TokenId ladders overlapping the current tick.\n * @module v2/tokenId/generateOverlapping\n */\n\nimport { PanopticValidationError } from '../errors'\nimport { priceToTick, roundToTickSpacing, tickToSqrtPriceX96 } from '../formatters'\nimport { MAX_TICK, MIN_TICK } from '../utils/constants'\nimport { createTokenIdBuilder } from './builder'\nimport { type Timescale, LEG_LIMITS, STANDARD_TICK_WIDTHS, TOKEN_ID_BITS } from './constants'\nimport { decodeTickSpacing } from './encoding'\n\nconst MAX_UINT64 = (1n << 64n) - 1n\nconst MAX_UINT128 = (1n << 128n) - 1n\nconst Q192 = 1n << 192n\nconst MAX_TOKEN_DECIMALS = 255n\nconst MAX_DECIMAL_EXPONENT = 512n\n\nexport type OverlappingOptionType = 'call' | 'put'\n\n/** One option leg repeated at every generated strike. */\nexport interface OverlappingOptionLegConfig {\n optionType: OverlappingOptionType\n optionRatio: bigint\n isLong: boolean\n /** Defaults to this leg's index. */\n riskPartner?: bigint\n}\n\n/** Parameters for {@link generateOverlappingTokenIds}. */\nexport interface GenerateOverlappingTokenIdsParams {\n /** Encoded 64-bit Panoptic pool ID, including tick spacing. */\n poolId: bigint\n /** Current Uniswap pool tick. */\n currentTick: bigint\n /** Standard option timescale used to derive every leg's width. */\n timescale: Timescale\n /** Positive quote-token price interval, such as \"25\" or \"50\". */\n strikePriceSpacing: string\n /** Asset token index in the pool (0 or 1). */\n asset: bigint\n assetDecimals: bigint\n quoteDecimals: bigint\n /** One to four call/put legs sharing each generated strike. */\n legs: readonly OverlappingOptionLegConfig[]\n /** Total size divided across all generated TokenIds. */\n positionSize: bigint\n}\n\n/** TokenIds and sizes aligned with the corresponding `dispatch()` arguments. */\nexport interface GenerateOverlappingTokenIdsResult {\n positionIdList: bigint[]\n positionSizes: bigint[]\n}\n\ninterface ResolvedLegConfig extends OverlappingOptionLegConfig {\n riskPartner: bigint\n}\n\ninterface DecimalSpacing {\n units: bigint\n scale: bigint\n denominator: bigint\n}\n\ninterface Fraction {\n numerator: bigint\n denominator: bigint\n}\n\nfunction invalid(message: string): never {\n throw new PanopticValidationError(`generateOverlappingTokenIds: ${message}`)\n}\n\nfunction pow10(exponent: bigint): bigint {\n return 10n ** exponent\n}\n\nfunction parsePriceSpacing(value: string, quoteDecimals: bigint): DecimalSpacing {\n const match = /^\\+?(?:(\\d+)(?:\\.(\\d*))?|\\.(\\d+))(?:e([+-]?\\d+))?$/i.exec(value.trim())\n if (match === null) invalid('strikePriceSpacing must be a positive decimal string')\n\n const integerPart = match[1] ?? '0'\n const fractionalPart = match[2] ?? match[3] ?? ''\n const exponent = BigInt(match[4] ?? '0')\n if (exponent < -MAX_DECIMAL_EXPONENT || exponent > MAX_DECIMAL_EXPONENT) {\n invalid('strikePriceSpacing exponent is too large')\n }\n\n let units = BigInt(`${integerPart}${fractionalPart}`)\n let scale = BigInt(fractionalPart.length) - exponent\n if (scale < 0n) {\n units *= pow10(-scale)\n scale = 0n\n }\n\n while (scale > 0n && units % 10n === 0n) {\n units /= 10n\n scale -= 1n\n }\n\n if (units <= 0n) invalid('strikePriceSpacing must be positive')\n if (scale > quoteDecimals) {\n invalid('strikePriceSpacing exceeds the quote token decimal precision')\n }\n\n return { units, scale, denominator: pow10(scale) }\n}\n\nfunction formatGridPrice(multiple: bigint, spacing: DecimalSpacing): string {\n const scaledPrice = multiple * spacing.units\n if (spacing.scale === 0n) return scaledPrice.toString()\n\n const scale = Number(spacing.scale)\n const digits = scaledPrice.toString().padStart(scale + 1, '0')\n const decimalIndex = digits.length - scale\n return `${digits.slice(0, decimalIndex)}.${digits.slice(decimalIndex)}`\n}\n\nfunction quotePriceAtTick(\n tick: bigint,\n asset: bigint,\n assetDecimals: bigint,\n quoteDecimals: bigint,\n): Fraction {\n const orientedTick = asset === 0n ? tick : -tick\n const sqrtPriceX96 = tickToSqrtPriceX96(orientedTick)\n let numerator = sqrtPriceX96 * sqrtPriceX96\n let denominator = Q192\n const decimalDifference = assetDecimals - quoteDecimals\n\n if (decimalDifference > 0n) {\n numerator *= pow10(decimalDifference)\n } else if (decimalDifference < 0n) {\n denominator *= pow10(-decimalDifference)\n }\n\n return { numerator, denominator }\n}\n\nfunction isPriceGridStrike(\n strike: bigint,\n params: Pick<GenerateOverlappingTokenIdsParams, 'asset' | 'assetDecimals' | 'quoteDecimals'>,\n spacing: DecimalSpacing,\n tickSpacing: bigint,\n): boolean {\n const price = quotePriceAtTick(strike, params.asset, params.assetDecimals, params.quoteDecimals)\n const floorMultiple =\n (price.numerator * spacing.denominator) / (price.denominator * spacing.units)\n\n for (const multiple of [floorMultiple, floorMultiple + 1n]) {\n if (multiple <= 0n) continue\n\n const orientedTick = priceToTick(\n formatGridPrice(multiple, spacing),\n params.assetDecimals,\n params.quoteDecimals,\n )\n const poolTick = params.asset === 0n ? orientedTick : -orientedTick\n if (roundToTickSpacing(poolTick, tickSpacing) === strike) return true\n }\n\n return false\n}\n\nfunction ceilDiv(value: bigint, divisor: bigint): bigint {\n const quotient = value / divisor\n const remainder = value % divisor\n return remainder > 0n ? quotient + 1n : quotient\n}\n\nfunction floorDiv(value: bigint, divisor: bigint): bigint {\n const quotient = value / divisor\n const remainder = value % divisor\n return remainder < 0n ? quotient - 1n : quotient\n}\n\nfunction resolveLegs(legs: readonly OverlappingOptionLegConfig[]): ResolvedLegConfig[] {\n if (legs.length === 0 || legs.length > Number(TOKEN_ID_BITS.MAX_LEGS)) {\n invalid('legs must contain between 1 and 4 entries')\n }\n\n const resolved = legs.map((leg, index) => {\n if (leg.optionType !== 'call' && leg.optionType !== 'put') {\n invalid(`leg ${index} has an invalid optionType`)\n }\n if (typeof leg.isLong !== 'boolean') invalid(`leg ${index} has an invalid isLong value`)\n if (leg.optionRatio < 1n || leg.optionRatio > LEG_LIMITS.MAX_RATIO) {\n invalid(`leg ${index} optionRatio must be between 1 and ${LEG_LIMITS.MAX_RATIO}`)\n }\n\n const riskPartner = leg.riskPartner ?? BigInt(index)\n if (riskPartner < 0n || riskPartner >= BigInt(legs.length)) {\n invalid(`leg ${index} references an inactive risk partner`)\n }\n\n return { ...leg, riskPartner }\n })\n\n for (const [index, leg] of resolved.entries()) {\n if (leg.riskPartner === BigInt(index)) continue\n const partner = resolved[Number(leg.riskPartner)]\n if (partner === undefined || partner.riskPartner !== BigInt(index)) {\n invalid(`leg ${index} has a non-mutual risk partner`)\n }\n }\n\n return resolved\n}\n\nfunction getCandidateStrikes(\n params: GenerateOverlappingTokenIdsParams,\n spacing: DecimalSpacing,\n tickSpacing: bigint,\n halfWidth: bigint,\n): bigint[] {\n const lower =\n MIN_TICK + halfWidth > params.currentTick - halfWidth + 1n\n ? MIN_TICK + halfWidth\n : params.currentTick - halfWidth + 1n\n const upper =\n MAX_TICK - halfWidth < params.currentTick + halfWidth - 1n\n ? MAX_TICK - halfWidth\n : params.currentTick + halfWidth - 1n\n const firstStrike = ceilDiv(lower, tickSpacing) * tickSpacing\n const lastStrike = floorDiv(upper, tickSpacing) * tickSpacing\n const strikes: bigint[] = []\n\n for (let strike = firstStrike; strike <= lastStrike; strike += tickSpacing) {\n if (isPriceGridStrike(strike, params, spacing, tickSpacing)) strikes.push(strike)\n }\n\n if (params.asset === 1n) strikes.reverse()\n return strikes\n}\n\nfunction buildTokenId(\n poolId: bigint,\n strike: bigint,\n width: bigint,\n asset: bigint,\n legs: readonly ResolvedLegConfig[],\n): bigint {\n const builder = createTokenIdBuilder(poolId)\n for (const leg of legs) {\n const config = {\n strike,\n width,\n optionRatio: leg.optionRatio,\n isLong: leg.isLong,\n riskPartner: leg.riskPartner,\n asset,\n }\n if (leg.optionType === 'call') builder.addCall(config)\n else builder.addPut(config)\n }\n return builder.build()\n}\n\nfunction dividePositionSize(positionSize: bigint, count: bigint): bigint[] {\n if (positionSize < count) {\n invalid(`positionSize ${positionSize} is too small for ${count} nonzero positions`)\n }\n\n const quotient = positionSize / count\n const remainder = positionSize % count\n const sizes: bigint[] = []\n for (let index = 0n; index < count; index += 1n) {\n sizes.push(quotient + (index < remainder ? 1n : 0n))\n }\n return sizes\n}\n\n/**\n * Generate a fixed quote-price lattice of co-strike TokenIds whose liquidity\n * ranges strictly contain the current tick. Returned arrays are ordered by\n * ascending quote strike price and are ready for `dispatch()`.\n */\nexport function generateOverlappingTokenIds(\n params: GenerateOverlappingTokenIdsParams,\n): GenerateOverlappingTokenIdsResult {\n if (params.poolId < 0n || params.poolId > MAX_UINT64) invalid('poolId must fit in uint64')\n if (params.currentTick < MIN_TICK || params.currentTick > MAX_TICK) {\n invalid(`currentTick must be between ${MIN_TICK} and ${MAX_TICK}`)\n }\n if (params.asset !== 0n && params.asset !== 1n) invalid('asset must be 0 or 1')\n if (\n params.assetDecimals < 0n ||\n params.assetDecimals > MAX_TOKEN_DECIMALS ||\n params.quoteDecimals < 0n ||\n params.quoteDecimals > MAX_TOKEN_DECIMALS\n ) {\n invalid('assetDecimals and quoteDecimals must be between 0 and 255')\n }\n if (params.positionSize <= 0n || params.positionSize > MAX_UINT128) {\n invalid('positionSize must be between 1 and uint128.max')\n }\n\n const tickSpacing = decodeTickSpacing(params.poolId)\n if (tickSpacing <= 0n) invalid('poolId tick spacing must be positive')\n\n const standardTickWidth = STANDARD_TICK_WIDTHS[params.timescale]\n if (standardTickWidth === undefined) invalid(`unknown timescale ${String(params.timescale)}`)\n const width = (standardTickWidth + tickSpacing - 1n) / tickSpacing\n if (width <= 0n || width > LEG_LIMITS.MAX_WIDTH) {\n invalid(\n `timescale width does not fit in the TokenId width field for tick spacing ${tickSpacing}`,\n )\n }\n\n const halfWidth = (width * tickSpacing) / 2n\n if (halfWidth <= 0n) invalid('timescale width must span at least two ticks')\n\n const spacing = parsePriceSpacing(params.strikePriceSpacing, params.quoteDecimals)\n const legs = resolveLegs(params.legs)\n const strikes = getCandidateStrikes(params, spacing, tickSpacing, halfWidth)\n if (strikes.length === 0) invalid('no price-grid strikes overlap the current tick')\n\n return {\n positionIdList: strikes.map((strike) =>\n buildTokenId(params.poolId, strike, width, params.asset, legs),\n ),\n positionSizes: dividePositionSize(params.positionSize, BigInt(strikes.length)),\n }\n}\n","/**\n * Pure TokenId decomposition into shorter-timescale positions.\n * @module v2/tokenId/split\n */\n\nimport { PanopticValidationError } from '../errors'\nimport { type Timescale, LEG_LIMITS, STANDARD_TICK_WIDTHS, TOKEN_ID_BITS } from './constants'\nimport { type DecodedLeg, addLegToTokenId, decodeAllLegs, decodeTickSpacing } from './encoding'\n\nconst POOL_ID_MASK = (1n << TOKEN_ID_BITS.POOL_ID_SIZE) - 1n\nconst MAX_UINT128 = (1n << 128n) - 1n\nconst MAX_UINT256 = (1n << 256n) - 1n\n\n/** TokenIds and sizes aligned with the corresponding `dispatch()` arguments. */\nexport interface SplitTokenIdByTimescaleResult {\n positionIdList: bigint[]\n positionSizes: bigint[]\n}\n\ntype LegGroup = DecodedLeg[]\n\nfunction invalid(message: string): never {\n throw new PanopticValidationError(`splitTokenIdByTimescale: ${message}`)\n}\n\nfunction validateInput(tokenId: bigint, positionSize: bigint): DecodedLeg[] {\n if (tokenId < 0n || tokenId > MAX_UINT256) invalid('tokenId must fit in uint256')\n if (positionSize <= 0n || positionSize > MAX_UINT128) {\n invalid('positionSize must be between 1 and uint128.max')\n }\n\n const legs = decodeAllLegs(tokenId)\n if (legs.length === 0) invalid('tokenId must contain at least one active leg')\n\n for (const [index, leg] of legs.entries()) {\n if (leg.index !== BigInt(index)) invalid('active legs must be contiguous from index 0')\n }\n\n const firstUnusedBit = TOKEN_ID_BITS.POOL_ID_SIZE + BigInt(legs.length) * TOKEN_ID_BITS.LEG_SIZE\n if (tokenId >> firstUnusedBit !== 0n) invalid('inactive leg slots must be empty')\n\n const byIndex = new Map(legs.map((leg) => [leg.index, leg]))\n for (const leg of legs) {\n const partner = byIndex.get(leg.riskPartner)\n if (partner === undefined) invalid(`leg ${leg.index} references an inactive risk partner`)\n if (partner.index !== leg.index && partner.riskPartner !== leg.index) {\n invalid(`leg ${leg.index} has a non-mutual risk partner`)\n }\n }\n\n return legs\n}\n\nfunction isCall(leg: DecodedLeg): boolean {\n return leg.tokenType === leg.asset\n}\n\nfunction isEconomicStraddlePair(left: DecodedLeg, right: DecodedLeg): boolean {\n return (\n isCall(left) !== isCall(right) &&\n left.asset === right.asset &&\n left.optionRatio === right.optionRatio &&\n left.isLong === right.isLong &&\n left.strike === right.strike &&\n left.width === right.width\n )\n}\n\n/** Preserve mutual pairs, then pair self-partnered economic straddles in source order. */\nfunction groupOptionLegs(optionLegs: DecodedLeg[]): LegGroup[] {\n const byIndex = new Map(optionLegs.map((leg) => [leg.index, leg]))\n const consumed = new Set<bigint>()\n const groups: LegGroup[] = []\n\n for (const leg of optionLegs) {\n if (consumed.has(leg.index)) continue\n\n if (leg.riskPartner !== leg.index) {\n const riskPartner = byIndex.get(leg.riskPartner)\n if (riskPartner === undefined) {\n invalid(`mutual risk pair containing leg ${leg.index} cannot be separated`)\n }\n\n consumed.add(leg.index)\n consumed.add(riskPartner.index)\n groups.push([leg, riskPartner])\n continue\n }\n\n const partner = optionLegs.find(\n (candidate) =>\n candidate.index > leg.index &&\n !consumed.has(candidate.index) &&\n candidate.riskPartner === candidate.index &&\n isEconomicStraddlePair(leg, candidate),\n )\n\n consumed.add(leg.index)\n if (partner === undefined) {\n groups.push([leg])\n continue\n }\n\n consumed.add(partner.index)\n groups.push([leg, partner])\n }\n\n return groups\n}\n\nfunction remapRiskPartner(leg: DecodedLeg, indexBySource: ReadonlyMap<bigint, bigint>): bigint {\n const riskPartner = indexBySource.get(leg.riskPartner)\n if (riskPartner === undefined) {\n invalid(`risk partner for leg ${leg.index} is missing from its output group`)\n }\n return riskPartner\n}\n\nfunction buildTokenId(\n poolId: bigint,\n legs: LegGroup,\n transform: (leg: DecodedLeg) => Pick<DecodedLeg, 'strike' | 'width'>,\n): bigint {\n const indexBySource = new Map(legs.map((leg, index) => [leg.index, BigInt(index)]))\n let output = poolId\n\n for (const [index, leg] of legs.entries()) {\n const newIndex = BigInt(index)\n const { strike, width } = transform(leg)\n if (strike < LEG_LIMITS.MIN_STRIKE || strike > LEG_LIMITS.MAX_STRIKE) {\n invalid(`generated strike ${strike} does not fit in int24`)\n }\n if (width < 0n || width > LEG_LIMITS.MAX_WIDTH) {\n invalid(`generated width ${width} does not fit in the TokenId width field`)\n }\n\n output = addLegToTokenId(output, {\n index: newIndex,\n asset: leg.asset,\n optionRatio: leg.optionRatio,\n isLong: leg.isLong ? 1n : 0n,\n tokenType: leg.tokenType,\n riskPartner: remapRiskPartner(leg, indexBySource),\n strike,\n width,\n })\n }\n\n return output\n}\n\nfunction childWidths(sourceWidth: bigint, targetWidth: bigint): bigint[] {\n if (sourceWidth <= targetWidth) return [sourceWidth]\n\n const fullWidthCount = sourceWidth / targetWidth\n const remainder = sourceWidth % targetWidth\n const widths: bigint[] = []\n for (let remaining = fullWidthCount; remaining > 0n; remaining -= 1n) {\n widths.push(targetWidth)\n }\n if (remainder > 0n) widths.push(remainder)\n return widths\n}\n\nfunction dividePositionSize(positionSize: bigint, count: number): bigint[] {\n const countBigInt = BigInt(count)\n if (positionSize < countBigInt) {\n invalid(`positionSize ${positionSize} is too small for ${count} nonzero child positions`)\n }\n\n const quotient = positionSize / countBigInt\n const remainder = positionSize % countBigInt\n return Array.from(\n { length: count },\n (_, index) => quotient + (BigInt(index) < remainder ? 1n : 0n),\n )\n}\n\nfunction splitGroup(\n poolId: bigint,\n group: LegGroup,\n tickSpacing: bigint,\n targetWidth: bigint,\n positionSize: bigint,\n): SplitTokenIdByTimescaleResult {\n const sourceWidth = group[0]?.width\n if (sourceWidth === undefined || sourceWidth === 0n)\n invalid('option group must have nonzero width')\n if (group.some((leg) => leg.width !== sourceWidth)) {\n invalid('all legs in an option group must have the same width')\n }\n\n const widths = childWidths(sourceWidth, targetWidth)\n const positionSizes = dividePositionSize(positionSize, widths.length)\n let consumedWidth = 0n\n\n const positionIdList = widths.map((width) => {\n const offset = consumedWidth\n consumedWidth += width\n\n return buildTokenId(poolId, group, (leg) => {\n // PanopticMath.getTicks uses floor below the strike and ceil above it.\n const sourceLower = leg.strike - (sourceWidth * tickSpacing) / 2n\n const childLower = sourceLower + offset * tickSpacing\n const strike = childLower + (width * tickSpacing) / 2n\n return { strike, width }\n })\n })\n\n return { positionIdList, positionSizes }\n}\n\n/**\n * Split every standalone option, economic straddle, or mutual risk pair in a\n * TokenId into a shorter standard timescale. Width-zero credit/loan legs are\n * emitted together as one final position. Returned arrays are parallel and\n * ready for `dispatch()`.\n *\n * Each option group divides `positionSize` independently across its children.\n * Integer remainder units are assigned to the lower children first.\n */\nexport function splitTokenIdByTimescale(\n tokenId: bigint,\n positionSize: bigint,\n targetTimescale: Timescale,\n): SplitTokenIdByTimescaleResult {\n const legs = validateInput(tokenId, positionSize)\n const tickSpacing = decodeTickSpacing(tokenId)\n if (tickSpacing <= 0n) invalid('tokenId tick spacing must be positive')\n\n const targetTickWidth = STANDARD_TICK_WIDTHS[targetTimescale]\n if (targetTickWidth === undefined) invalid(`unknown target timescale ${String(targetTimescale)}`)\n const targetWidth = (targetTickWidth + tickSpacing - 1n) / tickSpacing\n\n const poolId = tokenId & POOL_ID_MASK\n const optionLegs = legs.filter((leg) => leg.width > 0n)\n const fundingLegs = legs.filter((leg) => leg.width === 0n)\n const positionIdList: bigint[] = []\n const positionSizes: bigint[] = []\n\n for (const group of groupOptionLegs(optionLegs)) {\n const split = splitGroup(poolId, group, tickSpacing, targetWidth, positionSize)\n positionIdList.push(...split.positionIdList)\n positionSizes.push(...split.positionSizes)\n }\n\n if (fundingLegs.length > 0) {\n positionIdList.push(\n buildTokenId(poolId, fundingLegs, (leg) => ({ strike: leg.strike, width: leg.width })),\n )\n positionSizes.push(positionSize)\n }\n\n return { positionIdList, positionSizes }\n}\n","import { tickToSqrtPriceX96 } from '../panoptic/v2/formatters/tick'\nimport { decodeAllLegs } from '../panoptic/v2/tokenId'\nimport type { LpFeeRange } from './estimateLpFees'\n\nconst Q96 = 1n << 96n\nconst ceilDiv = (n: bigint, d: bigint) => (n + d - 1n) / d\n\n/** Uniswap mint principal in raw token units, rounded up per leg, plus 5% headroom. */\nexport function getLpDepositAmounts(ranges: readonly LpFeeRange[], sqrtPriceX96: bigint) {\n return getLpDepositBreakdown(ranges, sqrtPriceX96).total\n}\n\n/** Principal and separately identified funding headroom, in native token units. */\nexport function getLpDepositBreakdown(ranges: readonly LpFeeRange[], sqrtPriceX96: bigint) {\n if (sqrtPriceX96 <= 0n) throw new Error('Invalid pool price')\n let amount0 = 0n\n let amount1 = 0n\n for (const { tickLower, tickUpper, liquidity } of ranges) {\n if (\n !Number.isInteger(tickLower) ||\n !Number.isInteger(tickUpper) ||\n tickLower < -887272 ||\n tickUpper > 887272 ||\n tickLower >= tickUpper ||\n liquidity < 0n\n )\n throw new Error('Invalid LP range')\n const lower = tickToSqrtPriceX96(BigInt(tickLower))\n const upper = tickToSqrtPriceX96(BigInt(tickUpper))\n const price = sqrtPriceX96 < lower ? lower : sqrtPriceX96 > upper ? upper : sqrtPriceX96\n amount0 += ceilDiv(liquidity * Q96 * (upper - price), upper * price)\n amount1 += ceilDiv(liquidity * (price - lower), Q96)\n }\n const buffer = { amount0: ceilDiv(amount0 * 5n, 100n), amount1: ceilDiv(amount1 * 5n, 100n) }\n return {\n principal: { amount0, amount1 },\n buffer,\n total: { amount0: amount0 + buffer.amount0, amount1: amount1 + buffer.amount1 },\n }\n}\n\nexport interface LpPositionFundingParams {\n tokenId: bigint\n positionSize: bigint\n tickSpacing: bigint\n sqrtPriceX96: bigint\n /** Price used consistently to value funding and account collateral. */\n valuationSqrtPriceX96: bigint\n quoteTokenIndex: 0 | 1\n}\n\n/** Full deployed liquidity value; never a leveraged protocol margin estimate. */\nexport function getLpPositionFunding(params: LpPositionFundingParams) {\n const {\n tokenId,\n positionSize,\n tickSpacing,\n sqrtPriceX96,\n valuationSqrtPriceX96,\n quoteTokenIndex,\n } = params\n if (positionSize < 0n || tickSpacing <= 0n || valuationSqrtPriceX96 <= 0n)\n throw new Error('Invalid LP funding input')\n const legs = decodeAllLegs(tokenId)\n if (legs.length === 0 || legs.some((leg) => leg.isLong || leg.width === 0n))\n throw new Error('AMM Liquidity requires short liquidity legs without loans or credits')\n const ranges = legs.map((leg) => {\n const width = leg.width * tickSpacing\n const tickLower = leg.strike - width / 2n\n const tickUpper = leg.strike + (width + 1n) / 2n\n const lower = tickToSqrtPriceX96(tickLower)\n const upper = tickToSqrtPriceX96(tickUpper)\n const amount = positionSize * leg.optionRatio\n const liquidity =\n leg.asset === 0n\n ? (amount * ((lower * upper) / Q96)) / (upper - lower)\n : (amount * Q96) / (upper - lower)\n return { tickLower: Number(tickLower), tickUpper: Number(tickUpper), liquidity }\n })\n const breakdown = getLpDepositBreakdown(ranges, sqrtPriceX96)\n const priceSquared = valuationSqrtPriceX96 * valuationSqrtPriceX96\n const value = ({ amount0, amount1 }: { amount0: bigint; amount1: bigint }) =>\n quoteTokenIndex === 0\n ? amount0 + ceilDiv(amount1 * Q96 * Q96, priceSquared)\n : amount1 + ceilDiv(amount0 * priceSquared, Q96 * Q96)\n const principalInQuote = value(breakdown.principal)\n const totalInQuote = value(breakdown.total)\n return {\n ...breakdown,\n principalInQuote,\n bufferInQuote: totalInQuote - principalInQuote,\n totalInQuote,\n }\n}\n\n/** Remaining deposit in the requested token mix, rounded up to cover the shortfall. */\nexport function getLpFundingDeposit({\n funding,\n availableInQuote,\n minimumInQuote = 0n,\n quoteTokenIndex,\n valuationSqrtPriceX96,\n quotePercent,\n}: {\n funding: ReturnType<typeof getLpPositionFunding>\n availableInQuote: bigint\n minimumInQuote?: bigint\n quoteTokenIndex: 0 | 1\n valuationSqrtPriceX96: bigint\n quotePercent?: bigint\n}) {\n if (\n valuationSqrtPriceX96 <= 0n ||\n (quotePercent !== undefined && (quotePercent < 0n || quotePercent > 100n))\n )\n throw new Error('Invalid LP funding split')\n const requiredInQuote =\n minimumInQuote > funding.totalInQuote ? minimumInQuote : funding.totalInQuote\n const shortfallInQuote =\n requiredInQuote > availableInQuote ? requiredInQuote - availableInQuote : 0n\n const defaultQuotePercent =\n funding.totalInQuote > 0n\n ? ((quoteTokenIndex === 0 ? funding.total.amount0 : funding.total.amount1) * 100n) /\n funding.totalInQuote\n : 100n\n if (quotePercent === undefined) {\n return {\n requiredInQuote,\n shortfallInQuote,\n defaultQuotePercent,\n amount0:\n funding.totalInQuote > 0n\n ? ceilDiv(funding.total.amount0 * shortfallInQuote, funding.totalInQuote)\n : 0n,\n amount1:\n funding.totalInQuote > 0n\n ? ceilDiv(funding.total.amount1 * shortfallInQuote, funding.totalInQuote)\n : 0n,\n }\n }\n const quoteAmount = (shortfallInQuote * quotePercent) / 100n\n const assetValue = shortfallInQuote - quoteAmount\n const priceSquared = valuationSqrtPriceX96 * valuationSqrtPriceX96\n return {\n requiredInQuote,\n shortfallInQuote,\n defaultQuotePercent,\n amount0: quoteTokenIndex === 0 ? quoteAmount : ceilDiv(assetValue * Q96 * Q96, priceSquared),\n amount1: quoteTokenIndex === 1 ? quoteAmount : ceilDiv(assetValue * priceSquared, Q96 * Q96),\n }\n}\n\n/** Largest raw size funded by available collateral, including native-token rounding. */\nexport function getMaxLpPositionSize(\n params: Omit<LpPositionFundingParams, 'positionSize'> & {\n availableInQuote: bigint\n minimumRequirement?: { referenceSize: bigint; requiredInQuote: bigint }\n },\n) {\n if (\n params.minimumRequirement &&\n (params.minimumRequirement.referenceSize <= 0n ||\n params.minimumRequirement.requiredInQuote < 0n)\n )\n throw new Error('Invalid reference requirement')\n if (params.availableInQuote <= 0n) return 0n\n let low = 0n\n let high = (1n << 128n) - 1n\n while (low < high) {\n const mid = (low + high + 1n) / 2n\n const funding = getLpPositionFunding({ ...params, positionSize: mid })\n const minimum = params.minimumRequirement\n ? ceilDiv(\n params.minimumRequirement.requiredInQuote * mid,\n params.minimumRequirement.referenceSize,\n )\n : 0n\n if (funding.totalInQuote <= params.availableInQuote && minimum <= params.availableInQuote)\n low = mid\n else high = mid - 1n\n }\n return low\n}\n","/**\n * Greeks for plain (non-Panoptic) Uniswap v3/v4 concentrated-liquidity LP\n * positions. Pure math over on-chain position fields (liquidity + tick range)\n * and the pool's current price — no RPC, no protocol dependency.\n *\n * Units follow the Panoptic v2 greeks convention (see\n * `packages/sdk/src/panoptic/v2/greeks/index.ts`) so a caller can present LP\n * and Panoptic greeks side by side:\n * - `value` → numeraire-token smallest units\n * - `delta` → asset-token smallest units (the asset held by the LP)\n * - `gamma` → numeraire-token smallest units (dollar-gamma `P²·d²V/dP²`;\n * always ≤ 0 because an LP is short gamma)\n *\n * `assetIndex` selects which token is the \"asset\" (the volatile leg being\n * hedged): `0` → token0 is the asset / token1 the numeraire; `1` → the reverse.\n *\n * @module uniswap/lpGreeks\n */\n\nimport { tickToSqrtPriceX96 } from '../panoptic/v2/formatters/tick'\n\nconst Q96 = 1n << 96n\nconst Q192 = 1n << 192n\n\n/** Token amounts currently backing a concentrated-liquidity position. */\nexport interface LpAmounts {\n /** token0 amount in its smallest units. */\n amount0: bigint\n /** token1 amount in its smallest units. */\n amount1: bigint\n}\n\n/** Greeks of a Uniswap LP position in one asset frame (see module docs for units). */\nexport interface LpGreeks {\n /** Position value in numeraire-token smallest units. */\n value: bigint\n /** Delta in asset-token smallest units (the asset amount the LP is long). */\n delta: bigint\n /** Dollar-gamma in numeraire-token smallest units; ≤ 0 (LP is short gamma). */\n gamma: bigint\n}\n\n/** Inputs describing a single LP position + the pool's current price. */\nexport interface LpGreeksInput {\n /** Position liquidity `L`. */\n liquidity: bigint\n /** Lower tick of the range. */\n tickLower: bigint\n /** Upper tick of the range. */\n tickUpper: bigint\n /** Pool's current tick. */\n currentTick: bigint\n /** Which token is the asset: `0` (token0) or `1` (token1). */\n assetIndex: 0 | 1\n}\n\n/**\n * Compute the token0/token1 amounts backing `liquidity` over `[sqrtA, sqrtB]`\n * at the current price `sqrtP`, mirroring Uniswap's `LiquidityAmounts`\n * (`getAmountsForLiquidity`). All sqrt prices are X96. The current price is\n * clamped into the range, so out-of-range positions collapse to a single token.\n */\nexport function getAmountsForLiquidity(\n sqrtPriceX96: bigint,\n sqrtRatioAX96: bigint,\n sqrtRatioBX96: bigint,\n liquidity: bigint,\n): LpAmounts {\n // Normalize so A <= B.\n const [sqrtA, sqrtB] =\n sqrtRatioAX96 <= sqrtRatioBX96 ? [sqrtRatioAX96, sqrtRatioBX96] : [sqrtRatioBX96, sqrtRatioAX96]\n\n // Clamp the current price into [A, B].\n const sqrtC = sqrtPriceX96 < sqrtA ? sqrtA : sqrtPriceX96 > sqrtB ? sqrtB : sqrtPriceX96\n\n // amount0 = L * (sqrtB - sqrtC) * 2^96 / (sqrtC * sqrtB)\n const amount0 = sqrtC < sqrtB ? (liquidity * (sqrtB - sqrtC) * Q96) / (sqrtC * sqrtB) : 0n\n\n // amount1 = L * (sqrtC - sqrtA) / 2^96\n const amount1 = sqrtC > sqrtA ? (liquidity * (sqrtC - sqrtA)) / Q96 : 0n\n\n return { amount0, amount1 }\n}\n\n/**\n * Greeks (value, delta, gamma) for a Uniswap LP position in the chosen asset\n * frame. See the module docs for the unit conventions.\n *\n * Closed forms (in-range, numeraire = token1 / asset = token0):\n * value = amount1 + amount0·P (P = sqrtP² / 2^192)\n * delta = amount0 (= dV/dP)\n * gamma = P²·d²V/dP² = -L·sqrt(P)/2 (short gamma)\n * The `assetIndex = 1` frame is the symmetric inverse (numeraire = token0).\n * Gamma is zero when the price is outside the range (no curvature there).\n */\nexport function getLpGreeks(input: LpGreeksInput): LpGreeks {\n const { liquidity, tickLower, tickUpper, currentTick, assetIndex } = input\n\n const sqrtP = tickToSqrtPriceX96(currentTick)\n const sqrtA = tickToSqrtPriceX96(tickLower)\n const sqrtB = tickToSqrtPriceX96(tickUpper)\n\n const { amount0, amount1 } = getAmountsForLiquidity(sqrtP, sqrtA, sqrtB, liquidity)\n\n const sqrtP2 = sqrtP * sqrtP // P in X192\n const inRange = sqrtP > sqrtA && sqrtP < sqrtB\n\n if (assetIndex === 0) {\n // numeraire = token1, asset = token0\n const value = amount1 + (amount0 * sqrtP2) / Q192\n const delta = amount0\n // gamma = -L·sqrt(P)/2, sqrt(P) = sqrtP / 2^96 → in token1 units\n const gamma = inRange ? -(liquidity * sqrtP) / (2n * Q96) : 0n\n return { value, delta, gamma }\n }\n\n // numeraire = token0, asset = token1\n const value = amount0 + (amount1 * Q192) / sqrtP2\n const delta = amount1\n // gamma = -L·sqrt(1/P)/2, sqrt(1/P) = 2^96 / sqrtP → in token0 units\n const gamma = inRange ? -(liquidity * Q96) / (2n * sqrtP) : 0n\n return { value, delta, gamma }\n}\n","import Decimal from 'decimal.js'\n\nimport { tickToSqrtPriceX96 } from '../panoptic/v2/formatters/tick'\nimport type { LpFeeRange } from './estimateLpFees'\nimport { getAmountsForLiquidity } from './lpGreeks'\n\nconst D = Decimal.clone({ precision: 60 })\n\n/** Simple fee APR over the full selected viewport, without compounding. */\nexport function annualizeLpFeeReturn(feeReturnPercent: Decimal, durationSeconds: bigint) {\n if (durationSeconds <= 0n) throw new Error('APR requires a positive window duration')\n return new D(feeReturnPercent).mul(31_536_000).div(durationSeconds.toString())\n}\n\n/**\n * Combine both fee tokens into a fee-only return on deployed LP capital.\n * Value both capital and fees at the window's opening price: this keeps fee\n * return flat when accrual stops and makes the ratio independent of quote\n * orientation. Raw token amounts already account for differing decimals.\n * Excludes principal price changes, impermanent loss and costs; not annualized.\n * Returns undefined when the position has no representable deployed capital.\n */\nexport function getLpFeeReturnSeries<T extends { fees0: bigint; fees1: bigint }>({\n points,\n ranges,\n startTick,\n}: {\n points: readonly T[]\n ranges: readonly LpFeeRange[]\n startTick: number\n}) {\n const validTick = (tick: number) => Number.isInteger(tick) && Math.abs(tick) <= 887272\n if (!validTick(startTick)) throw new Error('Invalid valuation tick')\n const sqrtP = tickToSqrtPriceX96(BigInt(startTick))\n const price = new D(sqrtP.toString()).pow(2).div(new D((1n << 192n).toString()))\n let capital0 = 0n\n let capital1 = 0n\n for (const range of ranges) {\n if (\n !validTick(range.tickLower) ||\n !validTick(range.tickUpper) ||\n range.tickLower >= range.tickUpper ||\n range.liquidity < 0n\n )\n throw new Error('Invalid LP range')\n const amounts = getAmountsForLiquidity(\n sqrtP,\n tickToSqrtPriceX96(BigInt(range.tickLower)),\n tickToSqrtPriceX96(BigInt(range.tickUpper)),\n range.liquidity,\n )\n capital0 += amounts.amount0\n capital1 += amounts.amount1\n }\n const capital = new D(capital0.toString()).mul(price).plus(capital1.toString())\n if (capital.isZero()) return undefined\n return points.map((point) => {\n if (point.fees0 < 0n || point.fees1 < 0n) throw new Error('Invalid fee amount')\n const fees = new D(point.fees0.toString()).mul(price).plus(point.fees1.toString())\n return { ...point, feeReturnPercent: fees.div(capital).mul(100) }\n })\n}\n","/**\n * Errors for the Uniswap v4 Universal Router swap module.\n *\n * All extend {@link PanopticError} so callers can keep a single\n * `instanceof PanopticError` check and so they satisfy `SimulationResult`'s\n * error type.\n *\n * @module uniswap/v4/router/errors\n */\n\nimport type { Address } from 'viem'\n\nimport { PanopticError } from '../../../panoptic/v2/errors'\n\n/**\n * The chain has no configured Uniswap v4 addresses and none were supplied via\n * overrides.\n */\nexport class UnsupportedChainError extends PanopticError {\n override readonly name = 'UnsupportedChainError'\n\n constructor(\n public readonly chainId: bigint,\n cause?: Error,\n ) {\n super(`Uniswap v4 router not configured for chain ${chainId}`, cause)\n }\n}\n\n/**\n * `tokenIn` is neither `currency0` nor `currency1` of the resolved pool.\n */\nexport class InvalidSwapTokenError extends PanopticError {\n override readonly name = 'InvalidSwapTokenError'\n\n constructor(\n public readonly token: Address,\n public readonly currency0: Address,\n public readonly currency1: Address,\n cause?: Error,\n ) {\n super(\n `Token ${token} is not part of the pool (currency0=${currency0}, currency1=${currency1})`,\n cause,\n )\n }\n}\n\n/**\n * An amount exceeds the uint128 range required by the v4 swap encoding.\n */\nexport class AmountExceedsUint128Error extends PanopticError {\n override readonly name = 'AmountExceedsUint128Error'\n\n constructor(\n public readonly amount: bigint,\n cause?: Error,\n ) {\n super(`Amount ${amount} exceeds uint128 maximum`, cause)\n }\n}\n\n/**\n * A native-ETH swap needs a trailing Universal Router SWEEP to deliver the ETH\n * output (or refund the input overpay), but no `recipient` was supplied.\n */\nexport class MissingSweepRecipientError extends PanopticError {\n override readonly name = 'MissingSweepRecipientError'\n\n constructor(cause?: Error) {\n super('A recipient is required to sweep native ETH back to the user', cause)\n }\n}\n\n/**\n * The V4Quoter is not available for the chain (no fallback in v1).\n */\nexport class QuoterUnavailableError extends PanopticError {\n override readonly name = 'QuoterUnavailableError'\n\n constructor(\n public readonly chainId: bigint,\n cause?: Error,\n ) {\n super(`V4Quoter unavailable for chain ${chainId}`, cause)\n }\n}\n","/**\n * Per-chain Uniswap v3 addresses needed for spot quoting via the Universal\n * Router. The Universal Router itself is shared with v4 (see\n * `uniswap/v4/addresses`); only the v3 QuoterV2 is specific to v3.\n *\n * Supports Ethereum mainnet and Robinhood; other chains throw {@link UnsupportedChainError}\n * unless the address is supplied via overrides (fork tests / new chains).\n *\n * @module uniswap/v3/addresses\n */\n\nimport type { Address } from 'viem'\n\nimport { UnsupportedChainError } from '../v4/router/errors'\n\nexport interface UniswapV3Addresses {\n /** Uniswap v3 QuoterV2 — `quoteExactInputSingle` (revert/staticcall-based). */\n quoterV2: Address\n /** Uniswap v3 NonfungiblePositionManager — ERC721 LP position NFTs. */\n nonfungiblePositionManager: Address\n}\n\n/**\n * Verified Uniswap v3 QuoterV2 addresses keyed by chainId. Add a chain only\n * after verifying against the canonical Uniswap v3 deployment listing.\n */\nexport const UNISWAP_V3_ADDRESSES: Record<number, UniswapV3Addresses> = {\n // Ethereum mainnet\n 1: {\n quoterV2: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e',\n nonfungiblePositionManager: '0xC36442b4a4522E871399CD717aBDD847Ab11FE88',\n },\n 4663: {\n quoterV2: '0x33e885ed0ec9bf04ecfb19341582aadcb4c8a9e7',\n nonfungiblePositionManager: '0x73991a25c818bf1f1128deaab1492d45638de0d3',\n },\n}\n\n/**\n * Resolve Uniswap v3 addresses for a chain, applying optional overrides.\n *\n * @throws {UnsupportedChainError} when the chain is not listed and overrides do\n * not supply every required address.\n */\nexport function getUniswapV3Addresses(\n chainId: number | bigint,\n overrides?: Partial<UniswapV3Addresses>,\n): UniswapV3Addresses {\n const id = Number(chainId)\n const base = UNISWAP_V3_ADDRESSES[id]\n const merged = { ...base, ...overrides }\n if (!merged.quoterV2 || !merged.nonfungiblePositionManager) {\n throw new UnsupportedChainError(BigInt(id))\n }\n return merged as UniswapV3Addresses\n}\n","/**\n * Minimal Universal Router ABI (only the `execute` overload we use).\n * @module uniswap/v4/abis/universalRouter\n */\n\nexport const universalRouterAbi = [\n {\n type: 'function',\n name: 'execute',\n stateMutability: 'payable',\n inputs: [\n { name: 'commands', type: 'bytes' },\n { name: 'inputs', type: 'bytes[]' },\n { name: 'deadline', type: 'uint256' },\n ],\n outputs: [],\n },\n] as const\n","/**\n * Pure calldata builder for an exact-in single-hop swap through a Uniswap **v3**\n * pool via the Universal Router.\n *\n * Opcodes verified against `@uniswap/universal-router` `Commands.sol`:\n * - Universal Router command `V3_SWAP_EXACT_IN = 0x00`.\n *\n * The v3 command input is (unlike the v4 action list) a single flat tuple:\n * `(address recipient, uint256 amountIn, uint256 amountOutMinimum,\n * bytes path, bool payerIsUser)`\n * where:\n * - `recipient` is an EXPLICIT field. We encode the Universal Router sentinel\n * `MSG_SENDER = address(1)`, which the router maps to the `execute` caller —\n * so the output is delivered to the caller (e.g. a Safe) with no literal\n * address in the calldata to redirect.\n * - `path` is `abi.encodePacked(tokenIn, fee (uint24), tokenOut)` for a single\n * hop (43 bytes). The direction lives in the path ordering, not a bool.\n * - `payerIsUser = true`: the router pulls `tokenIn` from the caller via Permit2.\n *\n * ERC20-only: native ETH is intentionally unsupported here (the native paths\n * need WRAP/UNWRAP/SWEEP commands with explicit recipients).\n *\n * @module uniswap/v3/router/encodeSwap\n */\n\nimport type { Address, Hex } from 'viem'\nimport { encodeAbiParameters, encodeFunctionData, encodePacked, zeroAddress } from 'viem'\n\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport { universalRouterAbi } from '../../v4/abis/universalRouter'\nimport { AmountExceedsUint128Error } from '../../v4/router/errors'\n\n/** Universal Router command byte for a v3 exact-in swap. */\nexport const V3_SWAP_EXACT_IN = 0x00\n\n/** Universal Router command byte for a v3 exact-out swap. */\nexport const V3_SWAP_EXACT_OUT = 0x01\n\n/**\n * Universal Router recipient sentinel: the router maps `address(1)` to\n * `msg.sender` (the `execute` caller). Uniswap `Constants.MSG_SENDER`.\n */\nexport const MSG_SENDER: Address = '0x0000000000000000000000000000000000000001'\n\nconst UINT128_MAX = (1n << 128n) - 1n\n\nconst v3ExactInInputAbi = [\n { name: 'recipient', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'amountOutMinimum', type: 'uint256' },\n { name: 'path', type: 'bytes' },\n { name: 'payerIsUser', type: 'bool' },\n] as const\n\nfunction assertUint128(amount: bigint): void {\n if (amount < 0n || amount > UINT128_MAX) {\n throw new AmountExceedsUint128Error(amount)\n }\n}\n\n/** Arguments for {@link buildV3SwapExecuteCalldata}. */\nexport interface BuildV3SwapCalldataArgs {\n /** Input token (funds pulled from the caller via Permit2). */\n tokenIn: Address\n /** Output token. */\n tokenOut: Address\n /** v3 pool fee tier (e.g. 500, 3000). */\n fee: bigint\n /** Exact input amount (uint128). */\n amountIn: bigint\n /** Minimum acceptable output (uint128). */\n amountOutMinimum: bigint\n /**\n * Absolute deadline (unix seconds) — the `execute(commands, inputs, deadline)`\n * argument, enforced by the Universal Router.\n */\n deadline: bigint\n}\n\n/**\n * Encode the packed v3 single-hop path `tokenIn ++ fee(uint24) ++ tokenOut`.\n */\nexport function encodeV3Path(tokenIn: Address, fee: bigint, tokenOut: Address): Hex {\n if (fee < 0n || fee > 0xffffffn) {\n throw new PanopticError(`v3 fee ${fee} exceeds uint24`)\n }\n return encodePacked(['address', 'uint24', 'address'], [tokenIn, Number(fee), tokenOut])\n}\n\n/**\n * Build the typed `execute(...)` args for an exact-in single-hop v3 swap whose\n * output is delivered to the `execute` caller (recipient = MSG_SENDER).\n */\nexport function buildV3SwapExecuteArgs(args: BuildV3SwapCalldataArgs): {\n args: readonly [Hex, readonly Hex[], bigint]\n value: bigint\n} {\n const { tokenIn, tokenOut, fee, amountIn, amountOutMinimum, deadline } = args\n\n if (tokenIn === zeroAddress || tokenOut === zeroAddress) {\n throw new PanopticError('native ETH is not supported by the v3 exact-in router builder')\n }\n assertUint128(amountIn)\n assertUint128(amountOutMinimum)\n\n const path = encodeV3Path(tokenIn, fee, tokenOut)\n const input = encodeAbiParameters(v3ExactInInputAbi, [\n MSG_SENDER,\n amountIn,\n amountOutMinimum,\n path,\n true, // payerIsUser: pull tokenIn from the caller via Permit2\n ])\n\n const commands = encodePacked(['uint8'], [V3_SWAP_EXACT_IN])\n return { args: [commands, [input], deadline] as const, value: 0n }\n}\n\n/**\n * Build the `execute(commands, inputs, deadline)` calldata for an exact-in\n * single-hop v3 swap.\n */\nexport function buildV3SwapExecuteCalldata(args: BuildV3SwapCalldataArgs): {\n data: Hex\n value: bigint\n} {\n const { args: executeArgs, value } = buildV3SwapExecuteArgs(args)\n const data = encodeFunctionData({\n abi: universalRouterAbi,\n functionName: 'execute',\n args: executeArgs,\n })\n return { data, value }\n}\n\nexport interface BuildV3ExactOutSwapCalldataArgs {\n tokenIn: Address\n tokenOut: Address\n fee: bigint\n amountOut: bigint\n amountInMaximum: bigint\n deadline: bigint\n}\n\nconst v3ExactOutInputAbi = [\n { name: 'recipient', type: 'address' },\n { name: 'amountOut', type: 'uint256' },\n { name: 'amountInMaximum', type: 'uint256' },\n { name: 'path', type: 'bytes' },\n { name: 'payerIsUser', type: 'bool' },\n] as const\n\n/**\n * Build the typed `execute(...)` args for an exact-out single-hop v3 swap.\n * The v3 exact-out path is reversed: `tokenOut ++ fee ++ tokenIn`.\n */\nexport function buildV3ExactOutSwapExecuteArgs(args: BuildV3ExactOutSwapCalldataArgs): {\n args: readonly [Hex, readonly Hex[], bigint]\n value: bigint\n} {\n const { tokenIn, tokenOut, fee, amountOut, amountInMaximum, deadline } = args\n\n if (tokenIn === zeroAddress || tokenOut === zeroAddress) {\n throw new PanopticError('native ETH is not supported by the v3 exact-out router builder')\n }\n assertUint128(amountOut)\n assertUint128(amountInMaximum)\n\n const path = encodeV3Path(tokenOut, fee, tokenIn)\n const input = encodeAbiParameters(v3ExactOutInputAbi, [\n MSG_SENDER,\n amountOut,\n amountInMaximum,\n path,\n true,\n ])\n\n const commands = encodePacked(['uint8'], [V3_SWAP_EXACT_OUT])\n return { args: [commands, [input], deadline] as const, value: 0n }\n}\n\nexport function buildV3ExactOutSwapExecuteCalldata(args: BuildV3ExactOutSwapCalldataArgs): {\n data: Hex\n value: bigint\n} {\n const { args: executeArgs, value } = buildV3ExactOutSwapExecuteArgs(args)\n const data = encodeFunctionData({\n abi: universalRouterAbi,\n functionName: 'execute',\n args: executeArgs,\n })\n return { data, value }\n}\n","/**\n * Minimal Uniswap v3 QuoterV2 ABI.\n *\n * QuoterV2 is revert/staticcall-based (nonpayable but intended for `eth_call` /\n * `simulateContract`), so it must be simulated, not read.\n * @module uniswap/v3/abis/quoterV2\n */\n\nexport const quoterV2Abi = [\n {\n type: 'function',\n name: 'quoteExactInputSingle',\n stateMutability: 'nonpayable',\n inputs: [\n {\n name: 'params',\n type: 'tuple',\n components: [\n { name: 'tokenIn', type: 'address' },\n { name: 'tokenOut', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'fee', type: 'uint24' },\n { name: 'sqrtPriceLimitX96', type: 'uint160' },\n ],\n },\n ],\n outputs: [\n { name: 'amountOut', type: 'uint256' },\n { name: 'sqrtPriceX96After', type: 'uint160' },\n { name: 'initializedTicksCrossed', type: 'uint32' },\n { name: 'gasEstimate', type: 'uint256' },\n ],\n },\n {\n type: 'function',\n name: 'quoteExactOutputSingle',\n stateMutability: 'nonpayable',\n inputs: [\n {\n name: 'params',\n type: 'tuple',\n components: [\n { name: 'tokenIn', type: 'address' },\n { name: 'tokenOut', type: 'address' },\n { name: 'amount', type: 'uint256' },\n { name: 'fee', type: 'uint24' },\n { name: 'sqrtPriceLimitX96', type: 'uint160' },\n ],\n },\n ],\n outputs: [\n { name: 'amountIn', type: 'uint256' },\n { name: 'sqrtPriceX96After', type: 'uint160' },\n { name: 'initializedTicksCrossed', type: 'uint32' },\n { name: 'gasEstimate', type: 'uint256' },\n ],\n },\n] as const\n","/**\n * Quote exact-in and exact-out single-hop swaps against a Uniswap v3 pool via\n * QuoterV2.\n * @module uniswap/v3/router/quote\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { BaseError, ContractFunctionRevertedError } from 'viem'\n\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport { quoterV2Abi } from '../abis/quoterV2'\nimport { type UniswapV3Addresses, getUniswapV3Addresses } from '../addresses'\n\nconst BPS_DENOMINATOR = 10_000n\nconst UINT128_MAX = (1n << 128n) - 1n\n\nexport interface QuoteV3ExactInParams {\n client: PublicClient\n chainId: bigint\n tokenIn: Address\n tokenOut: Address\n fee: bigint\n amountIn: bigint\n slippageBps: bigint\n blockNumber?: bigint\n addresses?: Partial<UniswapV3Addresses>\n}\n\nexport interface V3ExactInQuote {\n amountOut: bigint\n amountOutMinimum: bigint\n gasEstimate: bigint\n}\n\n/**\n * Quote an exact-in v3 swap. Returns `null` when the quote reverts (e.g. the\n * pool does not exist / has no liquidity) so callers can skip that pool when\n * ranking venues, rather than aborting the whole cycle.\n */\nexport async function quoteV3ExactIn(params: QuoteV3ExactInParams): Promise<V3ExactInQuote | null> {\n const { client, chainId, tokenIn, tokenOut, fee, amountIn, slippageBps, blockNumber } = params\n if (amountIn < 0n || amountIn > UINT128_MAX) {\n throw new PanopticError(`amountIn ${amountIn} exceeds uint128 maximum`)\n }\n assertSlippageBps(slippageBps)\n\n const { quoterV2 } = getUniswapV3Addresses(chainId, params.addresses)\n\n try {\n const { result } = await client.simulateContract({\n address: quoterV2,\n abi: quoterV2Abi,\n functionName: 'quoteExactInputSingle',\n blockNumber,\n args: [{ tokenIn, tokenOut, amountIn, fee: Number(fee), sqrtPriceLimitX96: 0n }],\n })\n const [amountOut, , , gasEstimate] = result\n const amountOutMinimum = (amountOut * (BPS_DENOMINATOR - slippageBps)) / BPS_DENOMINATOR\n return { amountOut, amountOutMinimum, gasEstimate }\n } catch (err) {\n if (isRevert(err)) return null\n throw err\n }\n}\n\nexport interface QuoteV3ExactOutParams {\n client: PublicClient\n chainId: bigint\n tokenIn: Address\n tokenOut: Address\n fee: bigint\n amountOut: bigint\n slippageBps: bigint\n blockNumber?: bigint\n addresses?: Partial<UniswapV3Addresses>\n}\n\nexport interface V3ExactOutQuote {\n amountIn: bigint\n amountInMaximum: bigint\n gasEstimate: bigint\n}\n\n/**\n * Quote an exact-out v3 swap. Returns `null` on revert (no pool / no liquidity).\n */\nexport async function quoteV3ExactOut(\n params: QuoteV3ExactOutParams,\n): Promise<V3ExactOutQuote | null> {\n const { client, chainId, tokenIn, tokenOut, fee, amountOut, slippageBps, blockNumber } = params\n if (amountOut < 0n || amountOut > UINT128_MAX) {\n throw new PanopticError(`amountOut ${amountOut} exceeds uint128 maximum`)\n }\n assertSlippageBps(slippageBps)\n\n const { quoterV2 } = getUniswapV3Addresses(chainId, params.addresses)\n\n try {\n const { result } = await client.simulateContract({\n address: quoterV2,\n abi: quoterV2Abi,\n functionName: 'quoteExactOutputSingle',\n blockNumber,\n args: [{ tokenIn, tokenOut, amount: amountOut, fee: Number(fee), sqrtPriceLimitX96: 0n }],\n })\n const [amountIn, , , gasEstimate] = result\n const amountInMaximum =\n (amountIn * (BPS_DENOMINATOR + slippageBps) + BPS_DENOMINATOR - 1n) / BPS_DENOMINATOR\n return { amountIn, amountInMaximum, gasEstimate }\n } catch (err) {\n if (isRevert(err)) return null\n throw err\n }\n}\n\nfunction assertSlippageBps(slippageBps: bigint): void {\n if (slippageBps < 0n || slippageBps > BPS_DENOMINATOR) {\n throw new PanopticError(`invalid slippageBps ${slippageBps}, must be 0..10000`)\n }\n}\n\nfunction isRevert(err: unknown): boolean {\n return (\n err instanceof BaseError &&\n err.walk((e) => e instanceof ContractFunctionRevertedError) instanceof\n ContractFunctionRevertedError\n )\n}\n","/**\n * Block metadata utilities for the Panoptic v2 SDK.\n * @module v2/clients/blockMeta\n */\n\nimport type { PublicClient } from 'viem'\n\nimport type { BlockMeta } from '../types'\n\n/**\n * Parameters for getBlockMeta.\n */\nexport interface GetBlockMetaParams {\n /** viem PublicClient */\n client: Pick<PublicClient, 'getBlock'>\n /** Optional block number (defaults to latest) */\n blockNumber?: bigint\n}\n\n/**\n * Get block metadata for a given block.\n * Used to tag all read results with same-block consistency proof.\n *\n * @param params - The parameters\n * @returns Block metadata\n */\nexport async function getBlockMeta(params: GetBlockMetaParams): Promise<BlockMeta> {\n const { client, blockNumber } = params\n\n const block = await client.getBlock({\n blockNumber,\n includeTransactions: false,\n })\n\n return {\n blockNumber: block.number,\n blockHash: block.hash,\n blockTimestamp: block.timestamp,\n }\n}\n","/**\n * Minimal Uniswap V4 StateView ABI for fee growth reads.\n * Only includes functions needed by streamia history.\n */\nexport const stateViewAbi = [\n {\n inputs: [{ internalType: 'PoolId', name: 'poolId', type: 'bytes32' }],\n name: 'getSlot0',\n outputs: [\n { internalType: 'uint160', name: 'sqrtPriceX96', type: 'uint160' },\n { internalType: 'int24', name: 'tick', type: 'int24' },\n { internalType: 'uint24', name: 'protocolFee', type: 'uint24' },\n { internalType: 'uint24', name: 'lpFee', type: 'uint24' },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [{ internalType: 'PoolId', name: 'poolId', type: 'bytes32' }],\n name: 'getFeeGrowthGlobals',\n outputs: [\n { internalType: 'uint256', name: 'feeGrowthGlobal0', type: 'uint256' },\n { internalType: 'uint256', name: 'feeGrowthGlobal1', type: 'uint256' },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n { internalType: 'PoolId', name: 'poolId', type: 'bytes32' },\n { internalType: 'int24', name: 'tick', type: 'int24' },\n ],\n name: 'getTickInfo',\n outputs: [\n { internalType: 'uint128', name: 'liquidityGross', type: 'uint128' },\n { internalType: 'int128', name: 'liquidityNet', type: 'int128' },\n { internalType: 'uint256', name: 'feeGrowthOutside0X128', type: 'uint256' },\n { internalType: 'uint256', name: 'feeGrowthOutside1X128', type: 'uint256' },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [{ internalType: 'PoolId', name: 'poolId', type: 'bytes32' }],\n name: 'getLiquidity',\n outputs: [{ internalType: 'uint128', name: 'liquidity', type: 'uint128' }],\n stateMutability: 'view',\n type: 'function',\n },\n] as const\n","/**\n * Minimal Uniswap V3 Pool ABI for fee growth reads.\n * Only includes functions needed by streamia history.\n */\nexport const uniswapV3PoolAbi = [\n {\n inputs: [],\n name: 'slot0',\n outputs: [\n { internalType: 'uint160', name: 'sqrtPriceX96', type: 'uint160' },\n { internalType: 'int24', name: 'tick', type: 'int24' },\n { internalType: 'uint16', name: 'observationIndex', type: 'uint16' },\n { internalType: 'uint16', name: 'observationCardinality', type: 'uint16' },\n { internalType: 'uint16', name: 'observationCardinalityNext', type: 'uint16' },\n { internalType: 'uint8', name: 'feeProtocol', type: 'uint8' },\n { internalType: 'bool', name: 'unlocked', type: 'bool' },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'feeGrowthGlobal0X128',\n outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'feeGrowthGlobal1X128',\n outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [{ internalType: 'int24', name: '', type: 'int24' }],\n name: 'ticks',\n outputs: [\n { internalType: 'uint128', name: 'liquidityGross', type: 'uint128' },\n { internalType: 'int128', name: 'liquidityNet', type: 'int128' },\n { internalType: 'uint256', name: 'feeGrowthOutside0X128', type: 'uint256' },\n { internalType: 'uint256', name: 'feeGrowthOutside1X128', type: 'uint256' },\n { internalType: 'int56', name: 'tickCumulativeOutside', type: 'int56' },\n { internalType: 'uint160', name: 'secondsPerLiquidityOutsideX128', type: 'uint160' },\n { internalType: 'uint32', name: 'secondsOutside', type: 'uint32' },\n { internalType: 'bool', name: 'initialized', type: 'bool' },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'liquidity',\n outputs: [{ internalType: 'uint128', name: '', type: 'uint128' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'fee',\n outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'token0',\n outputs: [{ internalType: 'address', name: '', type: 'address' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'token1',\n outputs: [{ internalType: 'address', name: '', type: 'address' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'tickSpacing',\n outputs: [{ internalType: 'int24', name: '', type: 'int24' }],\n stateMutability: 'view',\n type: 'function',\n },\n] as const\n","import { ORACLE_EPOCH_SECONDS } from './constants'\n\nconst ORACLE_EPOCH_SHIFT = 232n\nconst ORACLE_EPOCH_MASK = (1n << 24n) - 1n\nconst ORACLE_TICK_MASK = (1n << 22n) - 1n\n\nfunction decodeSigned22(value: bigint): bigint {\n const signBit = 1n << 21n\n const truncated = value & ORACLE_TICK_MASK\n return (truncated & signBit) === 0n ? truncated : truncated - (1n << 22n)\n}\n\n/** Timing decoded from an OraclePack and resolved against a specific block. */\nexport interface OracleTiming {\n /** Modulo-2^24 oracle epoch stored on-chain. */\n epoch: bigint\n /** Absolute epoch-boundary timestamp reconstructed at or before the supplied block. */\n timestamp: bigint\n}\n\n/** Fixed-width oracle state decoded from an OraclePack. */\nexport interface DecodedOraclePack {\n referenceTick: bigint\n lockMode: bigint\n spotEMA: bigint\n fastEMA: bigint\n slowEMA: bigint\n eonsEMA: bigint\n epoch: bigint\n timestamp: bigint\n}\n\n/**\n * Decode the 24-bit epoch stored at bits 232..255 of OraclePack.\n *\n * The packed timestamp is modulo 2^30 seconds and only identifies an absolute\n * Unix timestamp within the wrap window containing `blockTimestamp`. Supplying\n * the relevant block timestamp resolves it to the latest matching epoch at or\n * before that block, including across the epoch counter wraparound.\n */\nexport function decodeOracleTiming(oraclePack: bigint, blockTimestamp: bigint): OracleTiming {\n const epoch = (oraclePack >> ORACLE_EPOCH_SHIFT) & ORACLE_EPOCH_MASK\n const currentEpoch = oracleEpochAt(blockTimestamp)\n const elapsedEpochs = (currentEpoch - epoch) & ORACLE_EPOCH_MASK\n const currentEpochTimestamp = blockTimestamp - (blockTimestamp % ORACLE_EPOCH_SECONDS)\n return { epoch, timestamp: currentEpochTimestamp - elapsedEpochs * ORACLE_EPOCH_SECONDS }\n}\n\n/** Decode the fixed-width ticks and guardian state stored in OraclePack. */\nexport function decodeOraclePack(oraclePack: bigint, blockTimestamp: bigint): DecodedOraclePack {\n const timing = decodeOracleTiming(oraclePack, blockTimestamp)\n return {\n referenceTick: decodeSigned22(oraclePack >> 96n),\n lockMode: (oraclePack >> 118n) & 3n,\n spotEMA: decodeSigned22(oraclePack >> 120n),\n fastEMA: decodeSigned22(oraclePack >> 142n),\n slowEMA: decodeSigned22(oraclePack >> 164n),\n eonsEMA: decodeSigned22(oraclePack >> 186n),\n ...timing,\n }\n}\n\n/** Return the contract's modulo-2^24 64-second epoch for a block timestamp. */\nexport function oracleEpochAt(timestamp: bigint): bigint {\n return (timestamp / ORACLE_EPOCH_SECONDS) & ORACLE_EPOCH_MASK\n}\n","import { PanopticValidationError } from '../errors'\nimport type { OracleState } from '../types'\nimport { ORACLE_EPOCH_SECONDS } from './constants'\n\nconst UINT24_MASK = (1n << 24n) - 1n\n\nexport interface OracleEmaPeriods {\n spot: bigint\n fast: bigint\n slow: bigint\n eons: bigint\n}\n\nexport interface OracleRiskParameters {\n emaPeriods: OracleEmaPeriods\n maxTicksDelta: bigint\n /** Informational observation clamp; not used by SafeMode diagnosis. May be zero. */\n maxClampDelta: bigint\n}\n\nexport type OracleSafeModeCause =\n | 'externalShock'\n | 'internalDisagreement'\n | 'highDivergence'\n | 'guardianLock'\n | 'unknown'\n\nexport interface OracleSafeModeDiagnosis {\n /** Authoritative value returned by PanopticPool.isSafeMode(). */\n level: bigint\n /** Value reproduced using the known RiskEngine formula and live constants. */\n reproducedLevel: bigint\n matchesOnchain: boolean\n causes: readonly OracleSafeModeCause[]\n externalShockDelta: bigint\n internalDisagreementDelta: bigint\n highDivergenceDelta: bigint\n guardianLocked: boolean\n /** Minimum whole 64-second oracle epochs to wait after the last observation. */\n minimumPokeEpochs: bigint\n shouldPoke: boolean\n}\n\ntype DiagnosticOracleState = Pick<\n OracleState,\n 'currentTick' | 'spotEMA' | 'fastEMA' | 'slowEMA' | 'medianTick' | 'lockMode'\n>\n\nfunction absoluteDelta(left: bigint, right: bigint): bigint {\n return left >= right ? left - right : right - left\n}\n\nfunction epochsForPeriod(period: bigint): bigint {\n return (period + ORACLE_EPOCH_SECONDS - 1n) / ORACLE_EPOCH_SECONDS\n}\n\n/** Decode the four uint24 periods packed by RiskEngine.EMA_PERIODS(). */\nexport function decodeOracleRiskParameters(\n emaPeriods: bigint,\n maxTicksDelta: bigint,\n maxClampDelta: bigint,\n): OracleRiskParameters {\n const decodedPeriods = {\n spot: emaPeriods & UINT24_MASK,\n fast: (emaPeriods >> 24n) & UINT24_MASK,\n slow: (emaPeriods >> 48n) & UINT24_MASK,\n eons: (emaPeriods >> 72n) & UINT24_MASK,\n }\n if (\n decodedPeriods.spot === 0n ||\n decodedPeriods.fast === 0n ||\n decodedPeriods.slow === 0n ||\n decodedPeriods.eons === 0n ||\n maxTicksDelta <= 0n ||\n maxClampDelta < 0n\n ) {\n throw new PanopticValidationError(\n `RiskEngine returned invalid oracle parameters: EMA_PERIODS=${emaPeriods}, ` +\n `MAX_TICKS_DELTA=${maxTicksDelta}, MAX_CLAMP_DELTA=${maxClampDelta}`,\n )\n }\n return { emaPeriods: decodedPeriods, maxTicksDelta, maxClampDelta }\n}\n\n/** Explain the on-chain SafeMode level using this deployment's RiskEngine constants. */\nexport function diagnoseOracleSafeMode(\n state: DiagnosticOracleState,\n parameters: OracleRiskParameters,\n onchainLevel: bigint,\n): OracleSafeModeDiagnosis {\n const externalShockDelta = absoluteDelta(state.currentTick, state.spotEMA)\n const internalDisagreementDelta = absoluteDelta(state.spotEMA, state.fastEMA)\n const highDivergenceDelta = absoluteDelta(state.medianTick, state.slowEMA)\n const internalThreshold = parameters.maxTicksDelta / 2n\n const externalShock = externalShockDelta > parameters.maxTicksDelta\n const internalDisagreement = internalDisagreementDelta > internalThreshold\n const highDivergence = highDivergenceDelta > internalThreshold\n const guardianLocked = state.lockMode !== 0n\n\n const algorithmicLevel =\n (externalShock ? 1n : 0n) + (internalDisagreement ? 1n : 0n) + (highDivergence ? 1n : 0n)\n const reproducedLevel = algorithmicLevel + state.lockMode\n const matchesOnchain = reproducedLevel === onchainLevel\n const causes: OracleSafeModeCause[] = []\n if (matchesOnchain) {\n if (externalShock) causes.push('externalShock')\n if (internalDisagreement) causes.push('internalDisagreement')\n if (highDivergence) causes.push('highDivergence')\n } else {\n causes.push('unknown')\n }\n if (guardianLocked) causes.push('guardianLock')\n\n const candidateEpochs: bigint[] = []\n if (!matchesOnchain) candidateEpochs.push(1n)\n if (highDivergence) candidateEpochs.push(1n)\n if (externalShock) candidateEpochs.push(epochsForPeriod(parameters.emaPeriods.spot))\n if (internalDisagreement) candidateEpochs.push(epochsForPeriod(parameters.emaPeriods.fast))\n const minimumPokeEpochs = candidateEpochs.reduce(\n (minimum, epochs) => (minimum === 0n || epochs < minimum ? epochs : minimum),\n 0n,\n )\n\n return {\n level: onchainLevel,\n reproducedLevel,\n matchesOnchain,\n causes,\n externalShockDelta,\n internalDisagreementDelta,\n highDivergenceDelta,\n guardianLocked,\n minimumPokeEpochs,\n shouldPoke: onchainLevel > 0n && !guardianLocked,\n }\n}\n","/**\n * Pool read functions for the Panoptic v2 SDK.\n *\n * ## Same-Block Guarantee\n *\n * All dynamic data is fetched in a SINGLE multicall to ensure block consistency.\n * Per PLAN.md §6, immutable \"static prefetch\" data (addresses, decimals, symbols)\n * can be fetched separately and cached - it's not subject to same-block consistency.\n *\n * Functions accept an optional `poolMetadata` parameter containing pre-fetched\n * immutable addresses. If not provided, it will be fetched first (static prefetch).\n * Then ONE multicall fetches all dynamic data at the target block.\n *\n * @module v2/reads/pool\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { decodeAbiParameters, keccak256, zeroAddress } from 'viem'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi, riskEngineAbi } from '../../../generated'\nimport { stateViewAbi } from '../abis/stateView'\nimport { uniswapV3PoolAbi } from '../abis/uniswapV3Pool'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { tickToSqrtPriceX96 } from '../formatters/tick'\nimport type {\n BlockMeta,\n CollateralTracker,\n OracleState,\n Pool,\n PoolKey,\n RiskEngine,\n RiskParameters,\n Utilization,\n} from '../types'\nimport { decodeOraclePack } from '../utils/oraclePack'\nimport { type OracleRiskParameters, decodeOracleRiskParameters } from '../utils/oracleSafeMode'\nimport { DEFAULT_MINT_BUFFER } from './mintBuffer'\n\n// ERC20 minimal ABI for token metadata\nconst erc20Abi = [\n {\n type: 'function',\n name: 'symbol',\n inputs: [],\n outputs: [{ type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'decimals',\n inputs: [],\n outputs: [{ type: 'uint8' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'name',\n inputs: [],\n outputs: [{ type: 'string' }],\n stateMutability: 'view',\n },\n] as const\n\n/**\n * Immutable pool metadata that can be cached.\n * These values never change for a given pool, so they're exempt from\n * same-block consistency requirements (per PLAN.md \"Static Prefetches\" exception).\n */\nexport interface PoolMetadata {\n /** Pool key bytes */\n poolKeyBytes: `0x${string}`\n /** Pool ID */\n poolId: bigint\n /** Collateral tracker 0 address */\n collateralToken0Address: Address\n /** Collateral tracker 1 address */\n collateralToken1Address: Address\n /** Risk engine address */\n riskEngineAddress: Address\n /** Token 0 underlying asset address */\n token0Asset: Address\n /** Token 1 underlying asset address */\n token1Asset: Address\n /** Token 0 symbol */\n token0Symbol: string\n /** Token 1 symbol */\n token1Symbol: string\n /** Token 0 decimals */\n token0Decimals: bigint\n /** Token 1 decimals */\n token1Decimals: bigint\n /** Token 0 name */\n token0Name: string\n /** Token 1 name */\n token1Name: string\n /** Underlying pool ID (V3: pool address, V4: keccak256(poolKeyBytes)) */\n underlyingPoolId: string\n /** Whether this is a V4 pool (poolManager is non-zero) */\n isV4: boolean\n /** Tick spacing */\n tickSpacing: bigint\n /** Fee tier (V4: from poolKey, V3: from Uniswap pool fee()) */\n fee: bigint\n /** SemiFungiblePositionManager address */\n sfpmAddress: Address\n}\n\n/**\n * Parameters for getPoolMetadata.\n */\nexport interface GetPoolMetadataParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n}\n\n/**\n * Fetch immutable pool metadata (addresses, symbols, decimals).\n * This data never changes for a given pool and can be cached indefinitely.\n *\n * This is the \"static prefetch\" per PLAN.md §6 - exempt from same-block consistency.\n *\n * @param params - The parameters\n * @returns Immutable pool metadata\n */\nexport async function getPoolMetadata(params: GetPoolMetadataParams): Promise<PoolMetadata> {\n const { client, poolAddress } = params\n\n // First call: get basic immutable pool data\n const basicResults = await client.multicall({\n contracts: [\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'poolKey',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'poolId',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'collateralToken0',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'collateralToken1',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'riskEngine',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'poolManager',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'SFPM',\n },\n ],\n allowFailure: false,\n })\n\n const [\n poolKeyBytes,\n poolId,\n collateralToken0Address,\n collateralToken1Address,\n riskEngineAddress,\n poolManager,\n sfpmAddress,\n ] = basicResults\n\n // Second call: get underlying asset addresses from collateral trackers\n const assetResults = await client.multicall({\n contracts: [\n {\n address: collateralToken0Address,\n abi: collateralTrackerV2Abi,\n functionName: 'asset',\n },\n {\n address: collateralToken1Address,\n abi: collateralTrackerV2Abi,\n functionName: 'asset',\n },\n ],\n allowFailure: false,\n })\n\n const [token0Asset, token1Asset] = assetResults\n\n // Native ETH (address zero) has no ERC20 contract — use hardcoded metadata\n const NATIVE_ETH_ADDRESS = '0x0000000000000000000000000000000000000000'\n const isToken0Native = token0Asset.toLowerCase() === NATIVE_ETH_ADDRESS\n const isToken1Native = token1Asset.toLowerCase() === NATIVE_ETH_ADDRESS\n\n // Third call: get token metadata (symbols, decimals, names) — skip native ETH tokens\n const erc20Contracts = [\n ...(isToken0Native\n ? []\n : [\n { address: token0Asset, abi: erc20Abi, functionName: 'symbol' as const },\n { address: token0Asset, abi: erc20Abi, functionName: 'decimals' as const },\n { address: token0Asset, abi: erc20Abi, functionName: 'name' as const },\n ]),\n ...(isToken1Native\n ? []\n : [\n { address: token1Asset, abi: erc20Abi, functionName: 'symbol' as const },\n { address: token1Asset, abi: erc20Abi, functionName: 'decimals' as const },\n { address: token1Asset, abi: erc20Abi, functionName: 'name' as const },\n ]),\n ]\n\n const erc20Results =\n erc20Contracts.length > 0\n ? await client.multicall({ contracts: erc20Contracts, allowFailure: false })\n : []\n\n // Reconstruct metadata, inserting native ETH defaults where needed\n let resultIdx = 0\n const token0Symbol = isToken0Native ? 'ETH' : (erc20Results[resultIdx++] as string)\n const token0Decimals = isToken0Native ? 18 : (erc20Results[resultIdx++] as number)\n const token0Name = isToken0Native ? 'Ether' : (erc20Results[resultIdx++] as string)\n const token1Symbol = isToken1Native ? 'ETH' : (erc20Results[resultIdx++] as string)\n const token1Decimals = isToken1Native ? 18 : (erc20Results[resultIdx++] as number)\n const token1Name = isToken1Native ? 'Ether' : (erc20Results[resultIdx++] as string)\n\n // Derive underlyingPoolId, tickSpacing, and fee\n const isV4 = poolManager !== zeroAddress\n const parsedPoolKey = parsePoolKey(poolKeyBytes)\n let underlyingPoolId: string\n let fee: bigint\n let tickSpacing: bigint\n\n if (isV4) {\n underlyingPoolId = keccak256(poolKeyBytes)\n fee = parsedPoolKey.fee\n tickSpacing = tickSpacingFromPoolId(poolId)\n } else {\n const v3PoolAddress = decodeAbiParameters([{ type: 'address' }], poolKeyBytes)[0]\n underlyingPoolId = v3PoolAddress\n const [v3Fee, v3TickSpacing] = await client.multicall({\n contracts: [\n { address: v3PoolAddress, abi: uniswapV3PoolAbi, functionName: 'fee' },\n { address: v3PoolAddress, abi: uniswapV3PoolAbi, functionName: 'tickSpacing' },\n ],\n allowFailure: false,\n })\n fee = BigInt(v3Fee)\n tickSpacing = BigInt(v3TickSpacing)\n }\n\n return {\n poolKeyBytes,\n poolId,\n collateralToken0Address,\n collateralToken1Address,\n isV4,\n riskEngineAddress,\n token0Asset,\n token1Asset,\n token0Symbol,\n token1Symbol,\n token0Decimals: BigInt(token0Decimals),\n token1Decimals: BigInt(token1Decimals),\n token0Name,\n token1Name,\n underlyingPoolId,\n tickSpacing,\n fee,\n sfpmAddress,\n }\n}\n\n/**\n * Parameters for getPool.\n */\nexport interface GetPoolParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID */\n chainId: bigint\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched pool metadata (for caching/optimization) */\n poolMetadata?: PoolMetadata\n /** Optional StateView address for V4 pools (needed to read Uniswap pool liquidity) */\n stateViewAddress?: Address\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get full pool data including both collateral trackers and oracle state.\n *\n * ## Same-Block Guarantee\n * All dynamic data is fetched in ONE multicall at the target block.\n * Static metadata (addresses, symbols, decimals) is either provided via\n * poolMetadata or fetched separately (static prefetch exception).\n *\n * @param params - The parameters\n * @returns Pool data with block metadata\n */\nexport async function getPool(params: GetPoolParams): Promise<Pool> {\n const { client, poolAddress, chainId, blockNumber, poolMetadata } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Get static metadata (either from cache or fetch it)\n const metadata = poolMetadata ?? (await getPoolMetadata({ client, poolAddress }))\n\n // Build Uniswap pool liquidity read (V3 vs V4)\n const liquidityContract =\n metadata.isV4 && params.stateViewAddress\n ? {\n address: params.stateViewAddress,\n abi: stateViewAbi,\n functionName: 'getLiquidity' as const,\n args: [metadata.underlyingPoolId as `0x${string}`] as const,\n }\n : !metadata.isV4\n ? {\n address: metadata.underlyingPoolId as Address,\n abi: uniswapV3PoolAbi,\n functionName: 'liquidity' as const,\n }\n : null // V4 without stateViewAddress — skip\n\n // SINGLE multicall for ALL dynamic data - ensures same-block consistency\n const [dynamicResults, _meta] = await Promise.all([\n client.multicall({\n contracts: [\n // Pool dynamic state\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'isSafeMode',\n },\n // Token 0 collateral tracker dynamic data\n {\n address: metadata.collateralToken0Address,\n abi: collateralTrackerV2Abi,\n functionName: 'getPoolData',\n },\n {\n address: metadata.collateralToken0Address,\n abi: collateralTrackerV2Abi,\n functionName: 'totalSupply',\n },\n {\n address: metadata.collateralToken0Address,\n abi: collateralTrackerV2Abi,\n functionName: 'interestRate',\n },\n // Token 1 collateral tracker dynamic data\n {\n address: metadata.collateralToken1Address,\n abi: collateralTrackerV2Abi,\n functionName: 'getPoolData',\n },\n {\n address: metadata.collateralToken1Address,\n abi: collateralTrackerV2Abi,\n functionName: 'totalSupply',\n },\n {\n address: metadata.collateralToken1Address,\n abi: collateralTrackerV2Abi,\n functionName: 'interestRate',\n },\n // Risk engine parameters (technically immutable but included for completeness)\n {\n address: metadata.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'SELLER_COLLATERAL_RATIO',\n },\n {\n address: metadata.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'MAINT_MARGIN_RATE',\n },\n {\n address: metadata.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'NOTIONAL_FEE',\n },\n {\n address: metadata.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'PREMIUM_FEE',\n },\n {\n address: metadata.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'VEGOID',\n },\n {\n address: metadata.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'MAX_SPREAD',\n },\n // Uniswap pool in-range liquidity (V3 or V4 via StateView)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ...(liquidityContract ? [liquidityContract as any] : []),\n ],\n blockNumber: targetBlockNumber,\n allowFailure: true,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // Extract results — first 14 are core (must succeed), last is liquidity (may fail)\n const coreResults = dynamicResults.slice(0, 14)\n if (coreResults.some((r) => r.status !== 'success')) {\n const failed = coreResults.find((r) => r.status !== 'success')\n throw new Error(`Core pool read failed: ${JSON.stringify(failed)}`)\n }\n const [\n currentTick,\n safeModeRaw,\n token0PoolData,\n token0TotalSupply,\n token0InterestRate,\n token1PoolData,\n token1TotalSupply,\n token1InterestRate,\n sellerCollateralRatio,\n maintMarginRate,\n notionalFee,\n premiumFee,\n vegoid,\n maxSpread,\n ] = coreResults.map((r) => r.result) as [\n bigint, // currentTick\n number, // safeModeRaw\n readonly [bigint, bigint, bigint, bigint], // token0PoolData (getPoolData)\n bigint, // token0TotalSupply\n bigint, // token0InterestRate\n readonly [bigint, bigint, bigint, bigint], // token1PoolData (getPoolData)\n bigint, // token1TotalSupply\n bigint, // token1InterestRate\n bigint, // sellerCollateralRatio\n bigint, // maintMarginRate\n bigint, // notionalFee\n bigint, // premiumFee\n bigint, // vegoid\n bigint, // maxSpread\n ]\n const liquidityResult = dynamicResults[14]\n const uniswapPoolLiquidity =\n liquidityResult?.status === 'success' ? BigInt(liquidityResult.result as bigint) : 0n\n\n // V3 poolKey() only contains the Uniswap pool address, so enrich the parsed\n // key with the immutable fee and tick spacing resolved by getPoolMetadata.\n const tickSpacing = metadata.tickSpacing\n const poolKey = {\n ...parsePoolKey(metadata.poolKeyBytes),\n fee: metadata.fee,\n tickSpacing,\n }\n\n // Annualize rates: interestRate() returns WAD/s, multiply by seconds/year\n const SECONDS_PER_YEAR = 31_536_000n\n const borrowRate0 = BigInt(token0InterestRate) * SECONDS_PER_YEAR\n const borrowRate1 = BigInt(token1InterestRate) * SECONDS_PER_YEAR\n const utilization0 = token0PoolData[3]\n const utilization1 = token1PoolData[3]\n // Supply rate = borrow rate * utilization (utilization is in bps, so /10000)\n const supplyRate0 = (borrowRate0 * utilization0) / 10000n\n const supplyRate1 = (borrowRate1 * utilization1) / 10000n\n const totalAssets0 = token0PoolData[0] + token0PoolData[1]\n const totalAssets1 = token1PoolData[0] + token1PoolData[1]\n\n // Build collateral trackers\n const collateralTracker0: CollateralTracker = {\n address: metadata.collateralToken0Address,\n token: metadata.token0Asset,\n symbol: metadata.token0Symbol,\n decimals: metadata.token0Decimals,\n totalAssets: totalAssets0,\n insideAMM: token0PoolData[1],\n creditedShares: token0PoolData[2],\n totalShares: token0TotalSupply,\n utilization: utilization0,\n borrowRate: borrowRate0,\n supplyRate: supplyRate0,\n }\n\n const collateralTracker1: CollateralTracker = {\n address: metadata.collateralToken1Address,\n token: metadata.token1Asset,\n symbol: metadata.token1Symbol,\n decimals: metadata.token1Decimals,\n totalAssets: totalAssets1,\n insideAMM: token1PoolData[1],\n creditedShares: token1PoolData[2],\n totalShares: token1TotalSupply,\n utilization: utilization1,\n borrowRate: borrowRate1,\n supplyRate: supplyRate1,\n }\n\n // Build risk engine\n const riskEngine: RiskEngine = {\n address: metadata.riskEngineAddress,\n collateralRequirement: sellerCollateralRatio,\n maintenanceMargin: maintMarginRate,\n commissionRate: BigInt(notionalFee),\n premiumFeeRate: BigInt(premiumFee),\n vegoid: BigInt(vegoid),\n maxSpread: BigInt(maxSpread),\n }\n\n // Determine health status based on safe mode\n const healthStatus = safeModeRaw === 0 ? 'active' : safeModeRaw === 1 ? 'low_liquidity' : 'paused'\n\n // sqrtPriceX96 from tick\n const sqrtPriceX96 = tickToSqrtPriceX96(BigInt(currentTick))\n\n return {\n address: poolAddress,\n chainId,\n poolId: metadata.poolId,\n poolKey,\n tickSpacing,\n collateralTracker0,\n collateralTracker1,\n riskEngine,\n currentTick: BigInt(currentTick),\n sqrtPriceX96,\n uniswapPoolLiquidity,\n healthStatus,\n metadata,\n _meta,\n }\n}\n\n/**\n * Parameters for getUtilization.\n */\nexport interface GetUtilizationParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched collateral tracker addresses (for caching/optimization) */\n collateralAddresses?: {\n collateralToken0: Address\n collateralToken1: Address\n }\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get current pool utilization for both tokens.\n *\n * ## Same-Block Guarantee\n * All dynamic data is fetched in ONE multicall at the target block.\n * Collateral tracker addresses are either provided or fetched separately (static prefetch).\n *\n * @param params - The parameters\n * @returns Utilization data with block metadata\n */\nexport async function getUtilization(params: GetUtilizationParams): Promise<Utilization> {\n const { client, poolAddress, blockNumber, collateralAddresses } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Get collateral tracker addresses (static prefetch if not provided)\n let collateralToken0: Address\n let collateralToken1: Address\n\n if (collateralAddresses) {\n collateralToken0 = collateralAddresses.collateralToken0\n collateralToken1 = collateralAddresses.collateralToken1\n } else {\n // Static prefetch - addresses are immutable\n const addressResults = 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 collateralToken0 = addressResults[0]\n collateralToken1 = addressResults[1]\n }\n\n // SINGLE multicall for ALL dynamic data - ensures same-block consistency\n const [poolDataResults, _meta] = await Promise.all([\n client.multicall({\n contracts: [\n {\n address: collateralToken0,\n abi: collateralTrackerV2Abi,\n functionName: 'getPoolData',\n },\n {\n address: collateralToken1,\n abi: collateralTrackerV2Abi,\n functionName: 'getPoolData',\n },\n {\n address: collateralToken0,\n abi: collateralTrackerV2Abi,\n functionName: 'totalSupply',\n },\n {\n address: collateralToken1,\n abi: collateralTrackerV2Abi,\n functionName: 'totalSupply',\n },\n ],\n blockNumber: targetBlockNumber,\n allowFailure: false,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const [poolData0, poolData1, totalSupply0, totalSupply1] = poolDataResults\n\n return {\n utilization0: poolData0[3], // currentPoolUtilization\n utilization1: poolData1[3],\n availableToBorrow0: availableToBorrow(poolData0, totalSupply0),\n availableToBorrow1: availableToBorrow(poolData1, totalSupply1),\n _meta,\n }\n}\n\n/**\n * Assets available to borrow from a collateral tracker.\n *\n * Mirrors `CollateralTracker._maxWithdrawWithPositions`: deposited assets less\n * one wei, less the assets backing credited shares.\n *\n * @param poolData - `getPoolData()` tuple: [depositedAssets, insideAMM, creditedShares, utilization]\n * @param totalSupply - Collateral tracker share supply, for the share→asset conversion\n */\nexport function availableToBorrow(\n poolData: readonly [bigint, bigint, bigint, bigint],\n totalSupply: bigint,\n): bigint {\n const [depositedAssets, insideAMM, creditedShares] = poolData\n const available = depositedAssets > 0n ? depositedAssets - 1n : 0n\n if (creditedShares === 0n || totalSupply === 0n) return available\n\n const totalAssets = depositedAssets + insideAMM\n const creditedAssets = (creditedShares * totalAssets) / totalSupply\n return available > creditedAssets ? available - creditedAssets : 0n\n}\n\n/**\n * Parameters for getOracleState.\n */\nexport interface GetOracleStateParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get current oracle state from the pool.\n *\n * ## Same-Block Guarantee\n * Single contract call + block meta fetch at the same block.\n *\n * @param params - The parameters\n * @returns Oracle state with block metadata\n */\nexport async function getOracleState(params: GetOracleStateParams): Promise<OracleState> {\n const { client, poolAddress, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Read the detailed oracle state and the canonical TWAP used by downstream\n // safety checks at the same block.\n const [[oracleTicks, twapTick], _meta] = await Promise.all([\n client.multicall({\n contracts: [\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getOracleTicks',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getTWAP',\n },\n ],\n allowFailure: false,\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // oracleTicks returns: currentTick, spotTick, medianTick, latestTick, oraclePack\n const [currentTick, spotTick, medianTick, latestTick, oraclePack] = oracleTicks\n\n const decoded = decodeOraclePack(oraclePack, _meta.blockTimestamp)\n\n return {\n epoch: decoded.epoch,\n lastUpdateTimestamp: decoded.timestamp,\n // Deprecated OracleState alias; use currentTick or oracleReferenceTick.\n referenceTick: BigInt(currentTick),\n currentTick: BigInt(currentTick),\n oracleReferenceTick: decoded.referenceTick,\n latestTick: BigInt(latestTick),\n twapTick: BigInt(twapTick),\n spotEMA: BigInt(spotTick),\n fastEMA: decoded.fastEMA,\n slowEMA: decoded.slowEMA,\n eonsEMA: decoded.eonsEMA,\n lockMode: decoded.lockMode,\n medianTick: BigInt(medianTick),\n _meta,\n }\n}\n\nexport interface GetOracleRiskParametersParams {\n client: PublicClient\n riskEngineAddress: Address\n blockNumber?: bigint\n}\n\nexport interface OracleRiskParametersState extends OracleRiskParameters {\n _meta: BlockMeta\n}\n\n/** Read the oracle constants from a specific deployed RiskEngine. */\nexport async function getOracleRiskParameters(\n params: GetOracleRiskParametersParams,\n): Promise<OracleRiskParametersState> {\n const targetBlockNumber = params.blockNumber ?? (await params.client.getBlockNumber())\n const [[emaPeriods, maxTicksDelta, maxClampDelta], _meta] = await Promise.all([\n params.client.multicall({\n contracts: [\n {\n address: params.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'EMA_PERIODS',\n },\n {\n address: params.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'MAX_TICKS_DELTA',\n },\n {\n address: params.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'MAX_CLAMP_DELTA',\n },\n ],\n allowFailure: false,\n blockNumber: targetBlockNumber,\n }),\n getBlockMeta({ client: params.client, blockNumber: targetBlockNumber }),\n ])\n return {\n ...decodeOracleRiskParameters(BigInt(emaPeriods), BigInt(maxTicksDelta), BigInt(maxClampDelta)),\n _meta,\n }\n}\n\n/**\n * Parameters for getRiskParameters.\n */\nexport interface GetRiskParametersParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Builder code (default: 0) */\n builderCode?: bigint\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched risk engine address (for caching/optimization) */\n riskEngineAddress?: Address\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get risk parameters from the pool.\n *\n * ## Same-Block Guarantee\n * All dynamic data is fetched in ONE multicall at the target block.\n * Risk engine address is either provided or fetched separately (static prefetch).\n *\n * @param params - The parameters\n * @returns Risk parameters with block metadata\n */\nexport async function getRiskParameters(params: GetRiskParametersParams): Promise<RiskParameters> {\n const {\n client,\n poolAddress,\n builderCode = 0n,\n blockNumber,\n riskEngineAddress: providedAddress,\n } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Get risk engine address (static prefetch if not provided)\n const riskEngineAddress =\n providedAddress ??\n (await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'riskEngine',\n }))\n\n // SINGLE multicall for ALL risk parameters - ensures same-block consistency\n const [riskEngineResults, _meta] = await Promise.all([\n client.multicall({\n contracts: [\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'SELLER_COLLATERAL_RATIO',\n },\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'BUYER_COLLATERAL_RATIO',\n },\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'MAINT_MARGIN_RATE',\n },\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'NOTIONAL_FEE',\n },\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'TARGET_POOL_UTIL',\n },\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'SATURATED_POOL_UTIL',\n },\n // The mint-time margin buffer, read live rather than compiled in, so a\n // redeployed RiskEngine cannot silently desync the displayed \"required\n // at mint\" from what the solvency check actually enforces.\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'BP_DECREASE_BUFFER',\n },\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'DECIMALS',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getRiskParameters',\n args: [builderCode],\n },\n ],\n blockNumber: targetBlockNumber,\n allowFailure: false,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const [\n sellerCollateralRatio,\n buyerCollateralRatio,\n maintMarginRate,\n notionalFee,\n targetPoolUtil,\n saturatedPoolUtil,\n bpDecreaseBuffer,\n riskEngineDecimals,\n ,\n ] = riskEngineResults\n\n return {\n collateralRequirement: sellerCollateralRatio,\n maintenanceMargin: maintMarginRate,\n commissionRate: BigInt(notionalFee),\n targetUtilization: targetPoolUtil,\n saturatedUtilization: saturatedPoolUtil,\n itmSpreadMultiplier: buyerCollateralRatio, // Using buyer ratio as ITM multiplier\n // A live numerator is meaningful only with its live scale. If the scale is\n // invalid, fall back to the complete compiled-in ratio.\n mintBuffer:\n BigInt(riskEngineDecimals) > 0n\n ? { numerator: BigInt(bpDecreaseBuffer), denominator: BigInt(riskEngineDecimals) }\n : DEFAULT_MINT_BUFFER,\n _meta,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Builder code validation\n// ---------------------------------------------------------------------------\n\n/**\n * Validate whether a builder code maps to a deployed builder wallet.\n *\n * Calls `PanopticPool.getRiskParameters(builderCode)` — the contract reverts\n * with `InvalidBuilderCode` when the computed CREATE2 address has no bytecode.\n *\n * @returns `true` when valid, `false` when the contract reverts.\n */\nexport async function validateBuilderCode(params: {\n client: PublicClient\n poolAddress: Address\n builderCode: bigint\n}): Promise<boolean> {\n const { client, poolAddress, builderCode } = params\n if (builderCode === 0n) return true\n try {\n await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getRiskParameters',\n args: [builderCode],\n })\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Extract tickSpacing from the encoded 64-bit poolId.\n * Layout: poolAddress (5 bytes) + vegoid (1 byte) + tickSpacing (2 bytes).\n * tickSpacing occupies bits 48–63.\n */\nfunction tickSpacingFromPoolId(poolId: bigint): bigint {\n return (poolId >> 48n) & 0xffffn\n}\n\n/**\n * Parse pool key from ABI-encoded bytes.\n *\n * V4 pools: PoolKey struct is ABI-encoded as 5 consecutive 32-byte slots\n * (currency0, currency1, fee, tickSpacing, hooks).\n *\n * V3 pools: poolKey() returns abi.encode(uniswapV3PoolAddress) — a single\n * 32-byte slot. The struct fields are not available, so currency0/currency1\n * are zeroed and tickSpacing/fee are set to 0 (callers should use\n * getV3PoolTickSpacing and getV3PoolFee respectively).\n */\nfunction parsePoolKey(poolKeyBytes: `0x${string}`): PoolKey {\n const hex = poolKeyBytes.slice(2)\n\n // V3: single ABI-encoded address (64 hex chars = 32 bytes)\n if (hex.length <= 64) {\n return {\n currency0: zeroAddress,\n currency1: zeroAddress,\n fee: 0n,\n tickSpacing: 0n,\n hooks: zeroAddress,\n }\n }\n\n if (hex.length < 320) {\n throw new Error(`Malformed V4 pool key: expected 320 hex chars (160 bytes), got ${hex.length}`)\n }\n\n // Each slot is 64 hex chars (32 bytes)\n // Addresses are in the last 40 hex chars (20 bytes) of their slot\n // Numeric values can be parsed from the full 64 hex chars of their slot\n const currency0 = `0x${hex.slice(24, 64)}` as Address // Slot 0: chars 0-64, address at 24-64\n const currency1 = `0x${hex.slice(88, 128)}` as Address // Slot 1: chars 64-128, address at 88-128\n const fee = BigInt(`0x${hex.slice(128, 192)}`) // Slot 2: chars 128-192 (full slot)\n const tickSpacing = BigInt(`0x${hex.slice(192, 256)}`) // Slot 3: chars 192-256 (full slot)\n const hooks = `0x${hex.slice(280, 320)}` as Address // Slot 4: chars 256-320, address at 280-320\n\n return {\n currency0,\n currency1,\n fee,\n tickSpacing,\n hooks,\n }\n}\n\n/**\n * Parameters for fetchPoolId.\n */\nexport interface FetchPoolIdParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n}\n\n/**\n * Result of fetchPoolId, including block metadata for same-block consistency.\n */\nexport interface FetchPoolIdResult {\n /** The encoded 64-bit pool ID */\n poolId: bigint\n /** Block metadata from the pinned read */\n _meta: BlockMeta\n}\n\n/**\n * Fetch the encoded 64-bit pool ID from a PanopticPool contract.\n *\n * Use this when you need the poolId without fetching the full pool state.\n * The returned poolId can be passed directly to `createTokenIdBuilder()`.\n * The read is pinned to the latest block at call time.\n *\n * @param params - The parameters\n * @returns The pool ID and block metadata\n */\nexport async function fetchPoolId(params: FetchPoolIdParams): Promise<FetchPoolIdResult> {\n const { client, poolAddress } = params\n\n const block = await client.getBlock({ blockTag: 'latest' })\n\n const poolId = await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'poolId',\n blockNumber: block.number,\n })\n\n return {\n poolId,\n _meta: {\n blockNumber: block.number,\n blockTimestamp: block.timestamp,\n blockHash: block.hash,\n },\n }\n}\n\nexport { tickToSqrtPriceX96 }\n\n/** Read the pool's spot tick without fetching collateral or risk configuration. */\nexport async function getPoolCurrentTick({\n client,\n poolAddress,\n blockNumber,\n}: {\n client: PublicClient\n poolAddress: Address\n blockNumber?: bigint\n}) {\n return client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n blockNumber,\n })\n}\n","/**\n * Resolve v3 swap routing info from a PanopticPool address.\n * @module uniswap/v3/router/resolveRoute\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { isAddressEqual } from 'viem'\n\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport { getPoolMetadata } from '../../../panoptic/v2/reads/pool'\nimport { InvalidSwapTokenError } from '../../v4/router/errors'\n\nexport interface ResolvedV3SwapRoute {\n tokenIn: Address\n tokenOut: Address\n fee: bigint\n zeroForOne: boolean\n}\n\nexport interface ResolveV3SwapRouteParams {\n client: PublicClient\n poolAddress: Address\n tokenIn: Address\n}\n\nexport async function resolveV3SwapRoute(\n params: ResolveV3SwapRouteParams,\n): Promise<ResolvedV3SwapRoute> {\n const { client, poolAddress, tokenIn } = params\n\n const meta = await getPoolMetadata({ client, poolAddress })\n if (meta.isV4) {\n throw new PanopticError('resolveV3SwapRoute called on a v4 pool')\n }\n\n const isToken0 = isAddressEqual(tokenIn, meta.token0Asset)\n const isToken1 = isAddressEqual(tokenIn, meta.token1Asset)\n if (!isToken0 && !isToken1) {\n throw new InvalidSwapTokenError(tokenIn, meta.token0Asset, meta.token1Asset)\n }\n\n const zeroForOne = isToken0\n return {\n tokenIn,\n tokenOut: zeroForOne ? meta.token1Asset : meta.token0Asset,\n fee: meta.fee,\n zeroForOne,\n }\n}\n","/**\n * Quote v3 swaps with the same `SimulationResult` shape as the v4 path.\n * @module uniswap/v3/router/quoteViaRouter\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { getBlockMeta } from '../../../panoptic/v2/clients/blockMeta'\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport type { SimulationResult } from '../../../panoptic/v2/types'\nimport type { SwapExactInQuote, SwapExactOutQuote } from '../../v4/router/types'\nimport type { UniswapV3Addresses } from '../addresses'\nimport { quoteV3ExactIn, quoteV3ExactOut } from './quote'\nimport { resolveV3SwapRoute } from './resolveRoute'\n\nconst FALLBACK_META = {\n blockNumber: 0n,\n blockTimestamp: 0n,\n blockHash: '0x0' as `0x${string}`,\n}\n\nexport interface QuoteSwapExactInViaV3RouterParams {\n client: PublicClient\n poolAddress: Address\n chainId: bigint\n tokenIn: Address\n amountIn: bigint\n slippageBps: bigint\n blockNumber?: bigint\n addresses?: Partial<UniswapV3Addresses>\n}\n\nexport async function quoteSwapExactInViaV3Router(\n params: QuoteSwapExactInViaV3RouterParams,\n): Promise<SimulationResult<SwapExactInQuote>> {\n const { client, poolAddress, chainId, tokenIn, amountIn, slippageBps, blockNumber, addresses } =\n params\n\n try {\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n void metaPromise.catch(() => undefined)\n\n const route = await resolveV3SwapRoute({ client, poolAddress, tokenIn })\n\n const quote = await quoteV3ExactIn({\n client,\n chainId,\n tokenIn: route.tokenIn,\n tokenOut: route.tokenOut,\n fee: route.fee,\n amountIn,\n slippageBps,\n blockNumber: targetBlockNumber,\n addresses,\n })\n\n if (!quote) {\n throw new PanopticError('v3 quote returned no result (pool may have no liquidity)')\n }\n\n const _meta = await metaPromise\n\n return {\n success: true,\n data: {\n amountOut: quote.amountOut,\n amountOutMinimum: quote.amountOutMinimum,\n zeroForOne: route.zeroForOne,\n tokenOut: route.tokenOut,\n gasEstimate: quote.gasEstimate,\n },\n gasEstimate: quote.gasEstimate,\n _meta,\n }\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Quote failed',\n error instanceof Error ? error : undefined,\n ),\n _meta: FALLBACK_META,\n }\n }\n}\n\nexport interface QuoteSwapExactOutViaV3RouterParams {\n client: PublicClient\n poolAddress: Address\n chainId: bigint\n tokenIn: Address\n amountOut: bigint\n slippageBps: bigint\n blockNumber?: bigint\n addresses?: Partial<UniswapV3Addresses>\n}\n\nexport async function quoteSwapExactOutViaV3Router(\n params: QuoteSwapExactOutViaV3RouterParams,\n): Promise<SimulationResult<SwapExactOutQuote>> {\n const { client, poolAddress, chainId, tokenIn, amountOut, slippageBps, blockNumber, addresses } =\n params\n\n try {\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n void metaPromise.catch(() => undefined)\n\n const route = await resolveV3SwapRoute({ client, poolAddress, tokenIn })\n\n const quote = await quoteV3ExactOut({\n client,\n chainId,\n tokenIn: route.tokenIn,\n tokenOut: route.tokenOut,\n fee: route.fee,\n amountOut,\n slippageBps,\n blockNumber: targetBlockNumber,\n addresses,\n })\n\n if (!quote) {\n throw new PanopticError('v3 quote returned no result (pool may have no liquidity)')\n }\n\n const _meta = await metaPromise\n\n return {\n success: true,\n data: {\n amountIn: quote.amountIn,\n amountInMaximum: quote.amountInMaximum,\n zeroForOne: route.zeroForOne,\n tokenOut: route.tokenOut,\n gasEstimate: quote.gasEstimate,\n },\n gasEstimate: quote.gasEstimate,\n _meta,\n }\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Quote failed',\n error instanceof Error ? error : undefined,\n ),\n _meta: FALLBACK_META,\n }\n }\n}\n","/**\n * Write utilities for the Panoptic v2 SDK.\n * @module v2/writes/utils\n */\n\nimport type { Abi, Address, Hash, Log, PublicClient, WalletClient } from 'viem'\nimport { decodeEventLog, encodeFunctionData } from 'viem'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi } from '../../../generated'\nimport type { PanopticEvent, TxOverrides, TxReceipt, TxResult } from '../types'\n\n/**\n * Decode PositionBalance packed data.\n *\n * Layout (from LSB to MSB):\n * - positionSize: bits 0-127 (uint128)\n * - poolUtilization0: bits 128-143 (uint16)\n * - poolUtilization1: bits 144-159 (uint16)\n * - tickAtMint: bits 160-183 (int24)\n * - timestampAtMint: bits 184-215 (uint32)\n * - blockAtMint: bits 216-254 (uint39)\n * - swapAtMint: bit 255 (bool)\n */\nexport function decodePositionBalance(balanceData: bigint): {\n positionSize: bigint\n poolUtilization0: bigint\n poolUtilization1: bigint\n tickAtMint: bigint\n timestampAtMint: bigint\n blockAtMint: bigint\n swapAtMint: boolean\n} {\n const positionSize = balanceData & ((1n << 128n) - 1n)\n const poolUtilization0 = (balanceData >> 128n) & 0xffffn\n const poolUtilization1 = (balanceData >> 144n) & 0xffffn\n\n // tickAtMint is int24 at bits 160-183\n let tickAtMint = (balanceData >> 160n) & 0xffffffn\n // Sign extend if negative (int24)\n if (tickAtMint > 0x7fffffn) {\n tickAtMint = tickAtMint - 0x1000000n\n }\n\n // timestampAtMint is uint32 at bits 184-215\n const timestampAtMint = (balanceData >> 184n) & 0xffffffffn\n\n // blockAtMint is uint39 at bits 216-254\n const blockAtMint = (balanceData >> 216n) & ((1n << 39n) - 1n)\n\n // swapAtMint is bool at bit 255\n const swapAtMint = balanceData >> 255n === 1n\n\n return {\n positionSize,\n poolUtilization0,\n poolUtilization1,\n tickAtMint,\n timestampAtMint,\n blockAtMint,\n swapAtMint,\n }\n}\n\n/**\n * Decode LeftRightSigned packed value.\n */\nexport function decodeLeftRightSigned(value: bigint): { right: bigint; left: bigint } {\n // Right is bits 0-127 (token0), Left is bits 128-255 (token1)\n // Both are signed int128\n let right = value & ((1n << 128n) - 1n)\n let left = value >> 128n\n\n // Sign extend right if needed\n if (right >= 1n << 127n) {\n right = right - (1n << 128n)\n }\n // Sign extend left if needed\n if (left >= 1n << 127n) {\n left = left - (1n << 128n)\n }\n\n return { right, left }\n}\n\n/**\n * Decode LeftRightUnsigned packed value.\n */\nexport function decodeLeftRightUnsigned(value: bigint): { right: bigint; left: bigint } {\n // Right is bits 0-127 (token0), Left is bits 128-255 (token1)\n // Both are unsigned uint128\n const right = value & ((1n << 128n) - 1n)\n const left = value >> 128n\n\n return { right, left }\n}\n\n/**\n * Parse Panoptic events from transaction logs.\n *\n * @param logs - The transaction logs\n * @returns Parsed Panoptic events\n */\nexport function parsePanopticEvents(logs: Log[]): PanopticEvent[] {\n const events: PanopticEvent[] = []\n\n // Try to decode each log with known ABIs\n for (const log of logs) {\n const baseEvent = {\n blockNumber: log.blockNumber ?? 0n,\n blockHash: (log.blockHash ??\n '0x0000000000000000000000000000000000000000000000000000000000000000') as Hash,\n transactionHash: log.transactionHash ?? ('0x' as Hash),\n logIndex: BigInt(log.logIndex ?? 0),\n }\n\n try {\n // Try PanopticPool events\n const poolEvent = decodeEventLog({\n abi: panopticPoolV2Abi,\n data: log.data,\n topics: log.topics,\n })\n\n if (poolEvent.eventName === 'OptionMinted') {\n const args = poolEvent.args as {\n recipient: `0x${string}`\n tokenId: bigint\n balanceData: bigint\n }\n const balance = decodePositionBalance(args.balanceData)\n events.push({\n type: 'OptionMinted',\n ...baseEvent,\n recipient: args.recipient,\n tokenId: args.tokenId,\n positionSize: balance.positionSize,\n poolUtilization0: balance.poolUtilization0,\n poolUtilization1: balance.poolUtilization1,\n tickAtMint: balance.tickAtMint,\n timestampAtMint: balance.timestampAtMint,\n blockAtMint: balance.blockAtMint,\n swapAtMint: balance.swapAtMint,\n })\n } else if (poolEvent.eventName === 'OptionBurnt') {\n const args = poolEvent.args as {\n recipient: `0x${string}`\n tokenId: bigint\n positionSize: bigint\n premiaByLeg: readonly bigint[]\n }\n events.push({\n type: 'OptionBurnt',\n ...baseEvent,\n recipient: args.recipient,\n tokenId: args.tokenId,\n positionSize: args.positionSize,\n premiaByLeg: [\n args.premiaByLeg[0] ?? 0n,\n args.premiaByLeg[1] ?? 0n,\n args.premiaByLeg[2] ?? 0n,\n args.premiaByLeg[3] ?? 0n,\n ] as const,\n })\n } else if (poolEvent.eventName === 'AccountLiquidated') {\n const args = poolEvent.args as {\n liquidator: `0x${string}`\n liquidatee: `0x${string}`\n bonusAmounts: bigint\n }\n const { right, left } = decodeLeftRightSigned(args.bonusAmounts)\n events.push({\n type: 'AccountLiquidated',\n ...baseEvent,\n liquidator: args.liquidator,\n liquidatee: args.liquidatee,\n bonusAmount0: right,\n bonusAmount1: left,\n })\n } else if (poolEvent.eventName === 'ForcedExercised') {\n const args = poolEvent.args as {\n exercisor: `0x${string}`\n user: `0x${string}`\n tokenId: bigint\n exerciseFee: bigint\n }\n const { right, left } = decodeLeftRightSigned(args.exerciseFee)\n events.push({\n type: 'ForcedExercised',\n ...baseEvent,\n exercisor: args.exercisor,\n user: args.user,\n tokenId: args.tokenId,\n exerciseFee0: right,\n exerciseFee1: left,\n })\n } else if (poolEvent.eventName === 'PremiumSettled') {\n const args = poolEvent.args as {\n user: `0x${string}`\n tokenId: bigint\n legIndex: bigint\n settledAmounts: bigint\n }\n const { right, left } = decodeLeftRightSigned(args.settledAmounts)\n events.push({\n type: 'PremiumSettled',\n ...baseEvent,\n user: args.user,\n tokenId: args.tokenId,\n legIndex: args.legIndex,\n settledAmount0: right,\n settledAmount1: left,\n })\n }\n } catch {\n // Not a PanopticPool event, try CollateralTracker\n try {\n const collateralEvent = decodeEventLog({\n abi: collateralTrackerV2Abi,\n data: log.data,\n topics: log.topics,\n })\n\n if (collateralEvent.eventName === 'Deposit') {\n const args = collateralEvent.args as {\n sender: `0x${string}`\n owner: `0x${string}`\n assets: bigint\n shares: bigint\n }\n events.push({\n type: 'Deposit',\n ...baseEvent,\n sender: args.sender,\n owner: args.owner,\n assets: args.assets,\n shares: args.shares,\n })\n } else if (collateralEvent.eventName === 'Withdraw') {\n const args = collateralEvent.args as {\n sender: `0x${string}`\n receiver: `0x${string}`\n owner: `0x${string}`\n assets: bigint\n shares: bigint\n }\n events.push({\n type: 'Withdraw',\n ...baseEvent,\n sender: args.sender,\n receiver: args.receiver,\n owner: args.owner,\n assets: args.assets,\n shares: args.shares,\n })\n }\n } catch {\n // Unknown event, skip\n }\n }\n }\n\n return events\n}\n\n/**\n * Create a TxResult from a transaction hash.\n *\n * @param client - The public client\n * @param hash - The transaction hash\n * @returns TxResult with wait function\n */\nexport function createTxResult(client: PublicClient, hash: Hash): TxResult {\n return {\n hash,\n wait: async (confirmations?: bigint): Promise<TxReceipt> => {\n const receipt = await client.waitForTransactionReceipt({\n hash,\n confirmations: confirmations !== undefined ? Number(confirmations) : undefined,\n })\n\n const events = parsePanopticEvents(receipt.logs)\n\n return {\n hash: receipt.transactionHash,\n blockNumber: receipt.blockNumber,\n blockHash: receipt.blockHash,\n gasUsed: receipt.gasUsed,\n status: receipt.status === 'success' ? 'success' : 'reverted',\n events,\n }\n },\n }\n}\n\n/**\n * Execute a write operation and return TxResult.\n *\n * @param client - The public client\n * @param hashPromise - Promise that resolves to transaction hash\n * @returns TxResult\n */\nexport async function executeWrite(\n client: PublicClient,\n hashPromise: Promise<Hash>,\n): Promise<TxResult> {\n const hash = await hashPromise\n return createTxResult(client, hash)\n}\n\n/**\n * Execute a write operation and wait for receipt.\n *\n * @param client - The public client\n * @param hashPromise - Promise that resolves to transaction hash\n * @param confirmations - Number of confirmations to wait for\n * @returns TxReceipt\n */\nexport async function executeWriteAndWait(\n client: PublicClient,\n hashPromise: Promise<Hash>,\n confirmations?: bigint,\n): Promise<TxReceipt> {\n const result = await executeWrite(client, hashPromise)\n return result.wait(confirmations)\n}\n\n/**\n * Parameters for the submitWrite helper.\n */\nexport interface SubmitWriteParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** Contract address */\n address: Address\n /** Contract ABI */\n abi: Abi\n /** Function name to call */\n functionName: string\n /** Function arguments */\n args: readonly unknown[]\n /** ETH value to send with the transaction (for native ETH deposits) */\n value?: bigint\n /** Optional gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Submit a write operation, supporting both direct wallet submission\n * and custom broadcaster paths with gas overrides.\n *\n * Normal path (no broadcaster): calls walletClient.writeContract() with gas overrides.\n * Broadcaster path: prepareTransactionRequest → apply overrides → signTransaction → broadcast.\n *\n * @param params - Submit write parameters\n * @returns TxResult\n */\nexport async function submitWrite(params: SubmitWriteParams): Promise<TxResult> {\n const { client, walletClient, account, address, abi, functionName, args, value, txOverrides } =\n params\n\n const broadcaster = txOverrides?.broadcaster\n\n if (broadcaster) {\n // Encode contract calldata before request preparation so gas/tx params\n // are derived from the exact call being signed and broadcast.\n const data = encodeFunctionData({ abi, functionName, args })\n\n // Broadcaster path: prepare → sign → broadcast\n const broadcastAccount = walletClient.account ?? account\n const request = await walletClient.prepareTransactionRequest({\n account: broadcastAccount,\n to: address,\n chain: walletClient.chain,\n data,\n ...(value !== undefined && { value }),\n ...(txOverrides?.maxFeePerGas !== undefined && { maxFeePerGas: txOverrides.maxFeePerGas }),\n ...(txOverrides?.maxPriorityFeePerGas !== undefined && {\n maxPriorityFeePerGas: txOverrides.maxPriorityFeePerGas,\n }),\n ...(txOverrides?.gas !== undefined && { gas: txOverrides.gas }),\n ...(txOverrides?.nonce !== undefined && { nonce: Number(txOverrides.nonce) }),\n })\n\n const signedTx = await walletClient.signTransaction({\n ...request,\n account: broadcastAccount,\n } as unknown as Parameters<WalletClient['signTransaction']>[0])\n\n const hash = await broadcaster.broadcast(signedTx)\n return createTxResult(client, hash)\n }\n\n // Normal path: direct writeContract with gas overrides\n const gasOverrides: Record<string, unknown> = {}\n if (txOverrides?.maxFeePerGas !== undefined) {\n gasOverrides.maxFeePerGas = txOverrides.maxFeePerGas\n }\n if (txOverrides?.maxPriorityFeePerGas !== undefined) {\n gasOverrides.maxPriorityFeePerGas = txOverrides.maxPriorityFeePerGas\n }\n if (txOverrides?.nonce !== undefined) {\n gasOverrides.nonce = Number(txOverrides.nonce)\n }\n\n // Use the walletClient's local account (if available) for local signing.\n // Passing a string address triggers eth_sendTransaction (remote signing),\n // which fails with hosted RPC providers like Alchemy/Infura.\n const resolvedAccount = walletClient.account ?? account\n\n // If no explicit gas override, estimate with a 20% buffer.\n // Panoptic dispatch calls are gas-heavy and viem's default estimate can be tight.\n if (txOverrides?.gas !== undefined) {\n gasOverrides.gas = txOverrides.gas\n } else {\n const estimated = await client.estimateContractGas({\n address,\n abi,\n functionName,\n args,\n account: resolvedAccount,\n ...(value !== undefined && { value }),\n } as Parameters<typeof client.estimateContractGas>[0])\n gasOverrides.gas = (estimated * 120n) / 100n\n }\n\n const hash = await walletClient.writeContract({\n address,\n abi,\n functionName,\n args,\n account: resolvedAccount,\n chain: walletClient.chain,\n ...(value !== undefined && { value }),\n ...gasOverrides,\n })\n\n return createTxResult(client, hash)\n}\n\n/**\n * Parameters required for all write operations.\n */\nexport interface BaseWriteParams {\n /** Public client for reading state */\n client: PublicClient\n}\n","/**\n * Per-chain Uniswap v4 infrastructure addresses (Universal Router, V4Quoter,\n * PoolManager, Permit2).\n *\n * Supports Ethereum mainnet and Robinhood; other chains throw {@link UnsupportedChainError}\n * unless every address is supplied via the `overrides` argument (e.g. anvil\n * fork tests, or bots targeting a not-yet-listed chain).\n *\n * @module uniswap/v4/addresses\n */\n\nimport type { Address } from 'viem'\n\nimport { UnsupportedChainError } from './router/errors'\n\n/**\n * Uniswap v4 contract addresses required for a Universal Router spot swap.\n */\nexport interface UniswapV4Addresses {\n /** Universal Router (v4-capable build) — entrypoint for `execute(...)`. */\n universalRouter: Address\n /** V4Quoter — `quoteExactInputSingle` (revert/staticcall-based). */\n v4Quoter: Address\n /** Uniswap v4 PoolManager (singleton). */\n poolManager: Address\n /** Uniswap v4 PositionManager (posm) — ERC721 LP position NFTs. */\n positionManager: Address\n /** Canonical Permit2 (same address on every chain). */\n permit2: Address\n}\n\n/**\n * Canonical Permit2, identical across all chains.\n */\nexport const PERMIT2_ADDRESS: Address = '0x000000000022D473030F116dDEE9F6B43aC78BA3'\n\n/**\n * Verified Uniswap v4 deployment addresses keyed by chainId.\n *\n * Sourced from the official Uniswap v4 deployments. Add a chain here only after\n * verifying each address against the canonical Uniswap deployment listing —\n * Universal Router in particular is NOT the same address across chains.\n */\nexport const UNISWAP_V4_ADDRESSES: Record<number, UniswapV4Addresses> = {\n // Ethereum mainnet\n 1: {\n universalRouter: '0x66a9893cC07D91D95644AEDD05D03f95e1dBA8Af',\n v4Quoter: '0x52F0E24D1c21C8A0cB1e5a5dD6198556BD9E1203',\n poolManager: '0x000000000004444c5dc75cB358380D2e3dE08A90',\n positionManager: '0xbD216513d74C8cf14cf4747E6AaA6420FF64ee9e',\n permit2: PERMIT2_ADDRESS,\n },\n 4663: {\n universalRouter: '0x8876789976decbfcbbbe364623c63652db8c0904',\n v4Quoter: '0x8dc178efb8111bb0973dd9d722ebeff267c98f94',\n poolManager: '0x8366a39cc670b4001a1121b8f6a443a643e40951',\n positionManager: '0x58daec3116aae6d93017baaea7749052e8a04fa7',\n permit2: PERMIT2_ADDRESS,\n },\n}\n\n/**\n * Resolve the Uniswap v4 addresses for a chain, applying optional overrides.\n *\n * @param chainId - Target chain ID.\n * @param overrides - Partial override of any address (e.g. for fork tests).\n * @returns Fully-resolved {@link UniswapV4Addresses}.\n * @throws {UnsupportedChainError} when the chain is not listed and the\n * overrides do not supply every required address.\n */\nexport function getUniswapV4Addresses(\n chainId: bigint,\n overrides?: Partial<UniswapV4Addresses>,\n): UniswapV4Addresses {\n const base = UNISWAP_V4_ADDRESSES[Number(chainId)]\n\n const merged: Partial<UniswapV4Addresses> = {\n ...base,\n ...overrides,\n permit2: overrides?.permit2 ?? base?.permit2 ?? PERMIT2_ADDRESS,\n }\n\n if (\n merged.universalRouter === undefined ||\n merged.v4Quoter === undefined ||\n merged.poolManager === undefined ||\n merged.positionManager === undefined ||\n merged.permit2 === undefined\n ) {\n throw new UnsupportedChainError(chainId)\n }\n\n return merged as UniswapV4Addresses\n}\n","/**\n * Exact-in and exact-out spot swaps via the Uniswap v3 path on the Universal Router.\n * @module uniswap/v3/router/swap\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\nimport { isAddressEqual } from 'viem'\n\nimport { getBlockMeta } from '../../../panoptic/v2/clients/blockMeta'\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport type { TxOverrides, TxResult } from '../../../panoptic/v2/types'\nimport { submitWrite } from '../../../panoptic/v2/writes/utils'\nimport { universalRouterAbi } from '../../v4/abis/universalRouter'\nimport { type UniswapV4Addresses, getUniswapV4Addresses } from '../../v4/addresses'\nimport type { UniswapV3Addresses } from '../addresses'\nimport { buildV3ExactOutSwapExecuteArgs, buildV3SwapExecuteArgs } from './encodeSwap'\nimport { quoteV3ExactIn, quoteV3ExactOut } from './quote'\nimport { resolveV3SwapRoute } from './resolveRoute'\n\nconst DEFAULT_DEADLINE_SECONDS = 1800n\n\nexport interface SwapExactInViaV3RouterParams {\n client: PublicClient\n walletClient: WalletClient\n account: Address\n poolAddress: Address\n chainId: bigint\n tokenIn: Address\n amountIn: bigint\n slippageBps: bigint\n deadline?: bigint\n recipient?: Address\n txOverrides?: TxOverrides\n addresses?: Partial<UniswapV3Addresses & UniswapV4Addresses>\n}\n\nexport async function swapExactInViaV3Router(\n params: SwapExactInViaV3RouterParams,\n): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n tokenIn,\n amountIn,\n slippageBps,\n deadline,\n recipient,\n txOverrides,\n addresses,\n } = params\n\n if (recipient !== undefined && !isAddressEqual(recipient, account)) {\n throw new PanopticError('Custom recipient is not supported yet; output goes to the sender')\n }\n\n const resolved = getUniswapV4Addresses(chainId, addresses)\n const route = await resolveV3SwapRoute({ client, poolAddress, tokenIn })\n\n const quote = await quoteV3ExactIn({\n client,\n chainId,\n tokenIn: route.tokenIn,\n tokenOut: route.tokenOut,\n fee: route.fee,\n amountIn,\n slippageBps,\n addresses,\n })\n\n if (!quote) {\n throw new PanopticError('v3 quote failed (pool may have no liquidity)')\n }\n\n const resolvedDeadline =\n deadline ?? (await getBlockMeta({ client })).blockTimestamp + DEFAULT_DEADLINE_SECONDS\n\n const { args, value } = buildV3SwapExecuteArgs({\n tokenIn: route.tokenIn,\n tokenOut: route.tokenOut,\n fee: route.fee,\n amountIn,\n amountOutMinimum: quote.amountOutMinimum,\n deadline: resolvedDeadline,\n })\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: resolved.universalRouter,\n abi: universalRouterAbi,\n functionName: 'execute',\n args,\n value,\n txOverrides,\n })\n}\n\nexport interface SwapExactOutViaV3RouterParams {\n client: PublicClient\n walletClient: WalletClient\n account: Address\n poolAddress: Address\n chainId: bigint\n tokenIn: Address\n amountOut: bigint\n slippageBps: bigint\n deadline?: bigint\n recipient?: Address\n txOverrides?: TxOverrides\n addresses?: Partial<UniswapV3Addresses & UniswapV4Addresses>\n}\n\nexport async function swapExactOutViaV3Router(\n params: SwapExactOutViaV3RouterParams,\n): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n tokenIn,\n amountOut,\n slippageBps,\n deadline,\n recipient,\n txOverrides,\n addresses,\n } = params\n\n if (recipient !== undefined && !isAddressEqual(recipient, account)) {\n throw new PanopticError('Custom recipient is not supported yet; output goes to the sender')\n }\n\n const resolved = getUniswapV4Addresses(chainId, addresses)\n const route = await resolveV3SwapRoute({ client, poolAddress, tokenIn })\n\n const quote = await quoteV3ExactOut({\n client,\n chainId,\n tokenIn: route.tokenIn,\n tokenOut: route.tokenOut,\n fee: route.fee,\n amountOut,\n slippageBps,\n addresses,\n })\n\n if (!quote) {\n throw new PanopticError('v3 quote failed (pool may have no liquidity)')\n }\n\n const resolvedDeadline =\n deadline ?? (await getBlockMeta({ client })).blockTimestamp + DEFAULT_DEADLINE_SECONDS\n\n const { args, value } = buildV3ExactOutSwapExecuteArgs({\n tokenIn: route.tokenIn,\n tokenOut: route.tokenOut,\n fee: route.fee,\n amountOut,\n amountInMaximum: quote.amountInMaximum,\n deadline: resolvedDeadline,\n })\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: resolved.universalRouter,\n abi: universalRouterAbi,\n functionName: 'execute',\n args,\n value,\n txOverrides,\n })\n}\n","/**\n * Pure calldata builders for exact-in and exact-out single-hop swaps via the\n * Uniswap v4 Universal Router.\n *\n * Opcodes verified against `@uniswap/universal-router` `Commands.sol` and\n * `@uniswap/v4-periphery` `Actions.sol`:\n * - Universal Router commands `V4_SWAP = 0x10`, `SWEEP = 0x04`.\n * - v4 actions `SWAP_EXACT_IN_SINGLE = 0x06`, `SWAP_EXACT_OUT_SINGLE = 0x08`,\n * `SETTLE_ALL = 0x0c`, `TAKE = 0x0e`, `TAKE_ALL = 0x0f`.\n *\n * Native ETH is `address(0)` in the PoolKey and needs special handling per side:\n * - Native-ETH OUTPUT: the implicit-recipient `TAKE_ALL` leaves the bought ETH\n * held by the Universal Router, so output is taken with the explicit-recipient\n * `TAKE` action instead, delivering ETH straight to the recipient. No trailing\n * SWEEP is appended for native output.\n * - Native-ETH INPUT on exact-out: the router is funded with the full\n * `amountInMaximum` overpay, so a trailing Universal-Router-level `SWEEP`\n * command (NOT the v4 SWEEP action, which this router does not support) refunds\n * the unused ETH to the recipient.\n * Native-ETH input on exact-in needs neither (msg.value equals the exact input;\n * ERC20 output is delivered by `TAKE_ALL`).\n *\n * @module uniswap/v4/router/encodeSwap\n */\n\nimport type { Address, Hex } from 'viem'\nimport { encodeAbiParameters, encodeFunctionData, encodePacked, zeroAddress } from 'viem'\n\nimport type { PoolKey } from '../../../panoptic/v2/types'\nimport { universalRouterAbi } from '../abis/universalRouter'\nimport { AmountExceedsUint128Error, MissingSweepRecipientError } from './errors'\n\n/** Universal Router command byte for a v4 swap. */\nexport const V4_SWAP = 0x10\n/** v4 action: exact-in single-hop swap. */\nexport const SWAP_EXACT_IN_SINGLE = 0x06\n/** v4 action: pay all of the input currency owed. */\nexport const SETTLE_ALL = 0x0c\n/** v4 action: take all of the output currency owed. */\nexport const TAKE_ALL = 0x0f\n/** v4 action: take an output currency to an explicit recipient. */\nexport const TAKE = 0x0e\n/** v4 action: exact-out single-hop swap. */\nexport const SWAP_EXACT_OUT_SINGLE = 0x08\n/** Universal Router command: sweep the router's token balance to a recipient. */\nexport const SWEEP = 0x04\n\n/** v4 sentinel: take the full positive currency delta (used with TAKE). */\nconst OPEN_DELTA = 0n\n\nconst UINT128_MAX = (1n << 128n) - 1n\n\nconst poolKeyComponents = [\n { name: 'currency0', type: 'address' },\n { name: 'currency1', type: 'address' },\n { name: 'fee', type: 'uint24' },\n { name: 'tickSpacing', type: 'int24' },\n { name: 'hooks', type: 'address' },\n] as const\n\nconst exactInputSingleParamsAbi = [\n {\n type: 'tuple',\n components: [\n { name: 'poolKey', type: 'tuple', components: poolKeyComponents },\n { name: 'zeroForOne', type: 'bool' },\n { name: 'amountIn', type: 'uint128' },\n { name: 'amountOutMinimum', type: 'uint128' },\n { name: 'hookData', type: 'bytes' },\n ],\n },\n] as const\n\nconst exactOutputSingleParamsAbi = [\n {\n type: 'tuple',\n components: [\n { name: 'poolKey', type: 'tuple', components: poolKeyComponents },\n { name: 'zeroForOne', type: 'bool' },\n { name: 'amountOut', type: 'uint128' },\n { name: 'amountInMaximum', type: 'uint128' },\n { name: 'hookData', type: 'bytes' },\n ],\n },\n] as const\n\nconst currencyAmountAbi = [\n { name: 'currency', type: 'address' },\n { name: 'amount', type: 'uint256' },\n] as const\n\n// v4 TAKE action params: take `amount` of `currency` to an explicit recipient.\nconst takeToRecipientAbi = [\n { name: 'currency', type: 'address' },\n { name: 'recipient', type: 'address' },\n { name: 'amount', type: 'uint256' },\n] as const\n\n// Universal Router SWEEP command params: forward `token` above `amountMin` to\n// `recipient`.\nconst sweepParamsAbi = [\n { name: 'token', type: 'address' },\n { name: 'recipient', type: 'address' },\n { name: 'amountMin', type: 'uint256' },\n] as const\n\nfunction assertUint128(amount: bigint): void {\n if (amount < 0n || amount > UINT128_MAX) {\n throw new AmountExceedsUint128Error(amount)\n }\n}\n\n/**\n * Encode the input for a Universal Router `SWEEP` command that forwards the\n * router's full native-ETH balance (above `amountMin = 0`) to `recipient`.\n */\nfunction encodeEthSweepInput(recipient: Address): Hex {\n return encodeAbiParameters(sweepParamsAbi, [zeroAddress, recipient, 0n])\n}\n\n/**\n * Build the output-take v4 action byte + param.\n *\n * Native-ETH output is taken with the explicit-recipient `TAKE` action so the\n * router forwards the ETH straight to `recipient` (the implicit-`msgSender`\n * `TAKE_ALL` leaves native ETH held by the router). ERC20 output uses\n * `TAKE_ALL`, which already credits the caller.\n *\n * @param nativeAmount - TAKE amount for native-ETH output: `OPEN_DELTA` (0) to\n * take the full credit (exact-in, protected by the swap's min) or the exact\n * output (exact-out).\n * @param erc20Amount - TAKE_ALL min/amount for ERC20 output: `amountOutMinimum`\n * (exact-in) or the exact output (exact-out).\n */\nfunction buildOutputTake(\n tokenOut: Address,\n recipient: Address | undefined,\n nativeAmount: bigint,\n erc20Amount: bigint,\n): { action: number; param: Hex } {\n if (tokenOut === zeroAddress) {\n if (recipient === undefined) {\n throw new MissingSweepRecipientError()\n }\n return {\n action: TAKE,\n param: encodeAbiParameters(takeToRecipientAbi, [zeroAddress, recipient, nativeAmount]),\n }\n }\n return {\n action: TAKE_ALL,\n param: encodeAbiParameters(currencyAmountAbi, [tokenOut, erc20Amount]),\n }\n}\n\n/**\n * Arguments for {@link buildV4SwapExecuteCalldata}.\n */\nexport interface BuildV4SwapCalldataArgs {\n /** The v4 PoolKey (currency0, currency1, fee, tickSpacing, hooks). */\n poolKey: PoolKey\n /** Whether the swap goes currency0 → currency1. */\n zeroForOne: boolean\n /** Exact input amount (uint128). */\n amountIn: bigint\n /** Minimum acceptable output (uint128). */\n amountOutMinimum: bigint\n /** Input token address (`address(0)` for native ETH). */\n tokenIn: Address\n /** Output token address (`address(0)` for native ETH). */\n tokenOut: Address\n /** Absolute deadline (unix seconds). */\n deadline: bigint\n /**\n * Recipient of native-ETH output. Required when `tokenOut` is `address(0)`,\n * since the explicit-recipient `TAKE` action forwards the bought ETH there\n * (the implicit-recipient `TAKE_ALL` would leave it held by the router).\n */\n recipient?: Address\n /** Hook data; defaults to `0x` (hook-less pools). */\n hookData?: Hex\n}\n\n/**\n * Build the typed `execute(...)` args + msg.value for an exact-in single-hop v4\n * swap. Use this when submitting via viem (`writeContract` / `submitWrite`).\n *\n * When `tokenOut` is native ETH the explicit-recipient `TAKE` action forwards\n * the bought ETH to `recipient` (no trailing SWEEP is needed for exact-in).\n *\n * @returns `args` ready to spread into `execute` and the ETH `value` to send\n * (= `amountIn` for native-ETH input, otherwise `0n`).\n */\nexport function buildV4SwapExecuteArgs(args: BuildV4SwapCalldataArgs): {\n args: readonly [Hex, readonly Hex[], bigint]\n value: bigint\n} {\n const {\n poolKey,\n zeroForOne,\n amountIn,\n amountOutMinimum,\n tokenIn,\n tokenOut,\n deadline,\n recipient,\n hookData = '0x',\n } = args\n\n assertUint128(amountIn)\n assertUint128(amountOutMinimum)\n\n const swapParam = encodeAbiParameters(exactInputSingleParamsAbi, [\n {\n poolKey: {\n currency0: poolKey.currency0,\n currency1: poolKey.currency1,\n fee: Number(poolKey.fee),\n tickSpacing: Number(poolKey.tickSpacing),\n hooks: poolKey.hooks,\n },\n zeroForOne,\n amountIn,\n amountOutMinimum,\n hookData,\n },\n ])\n\n // SETTLE_ALL pays the input; the output take credits the recipient. Native-ETH\n // output uses the explicit-recipient TAKE so the router forwards the ETH (with\n // OPEN_DELTA to take the full, slippage-protected swap output).\n const settleParam = encodeAbiParameters(currencyAmountAbi, [tokenIn, amountIn])\n const take = buildOutputTake(tokenOut, recipient, OPEN_DELTA, amountOutMinimum)\n\n const actions = encodePacked(\n ['uint8', 'uint8', 'uint8'],\n [SWAP_EXACT_IN_SINGLE, SETTLE_ALL, take.action],\n )\n\n const v4Input = encodeAbiParameters(\n [\n { name: 'actions', type: 'bytes' },\n { name: 'params', type: 'bytes[]' },\n ],\n [actions, [swapParam, settleParam, take.param]],\n )\n\n // Native-ETH input on exact-in needs no SWEEP (msg.value equals the exact input).\n const commands = encodePacked(['uint8'], [V4_SWAP])\n const value = tokenIn === zeroAddress ? amountIn : 0n\n\n return { args: [commands, [v4Input], deadline] as const, value }\n}\n\n/**\n * Build the `execute(commands, inputs, deadline)` calldata + msg.value for an\n * exact-in single-hop v4 swap.\n *\n * @returns The encoded calldata and the ETH `value` to send.\n */\nexport function buildV4SwapExecuteCalldata(args: BuildV4SwapCalldataArgs): {\n data: Hex\n value: bigint\n} {\n const { args: executeArgs, value } = buildV4SwapExecuteArgs(args)\n const data = encodeFunctionData({\n abi: universalRouterAbi,\n functionName: 'execute',\n args: executeArgs,\n })\n return { data, value }\n}\n\n/**\n * Arguments for {@link buildV4ExactOutSwapExecuteCalldata}.\n */\nexport interface BuildV4ExactOutSwapCalldataArgs {\n /** The v4 PoolKey (currency0, currency1, fee, tickSpacing, hooks). */\n poolKey: PoolKey\n /** Whether the swap goes currency0 → currency1. */\n zeroForOne: boolean\n /** Exact output amount to receive (uint128). */\n amountOut: bigint\n /** Maximum acceptable input to spend (uint128). */\n amountInMaximum: bigint\n /** Input token address (`address(0)` for native ETH). */\n tokenIn: Address\n /** Output token address (`address(0)` for native ETH). */\n tokenOut: Address\n /** Absolute deadline (unix seconds). */\n deadline: bigint\n /**\n * Recipient of any swept native-ETH refund (only used for native-ETH input).\n * Must be the payer; the leftover `amountInMaximum - actualInput` is returned\n * here.\n */\n recipient: Address\n /** Hook data; defaults to `0x` (hook-less pools). */\n hookData?: Hex\n}\n\n/**\n * Build the typed `execute(...)` args + msg.value for an exact-out single-hop v4\n * swap. Use this when submitting via viem (`writeContract` / `submitWrite`).\n *\n * For native-ETH input, `value` is `amountInMaximum` (an overpay) and a trailing\n * `SWEEP` action refunds the unused ETH to `recipient`. For ERC20 input, Permit2\n * pulls only the settled amount, so no SWEEP is appended and `value` is `0n`.\n *\n * @returns `args` ready to spread into `execute` and the ETH `value` to send.\n */\nexport function buildV4ExactOutSwapExecuteArgs(args: BuildV4ExactOutSwapCalldataArgs): {\n args: readonly [Hex, readonly Hex[], bigint]\n value: bigint\n} {\n const {\n poolKey,\n zeroForOne,\n amountOut,\n amountInMaximum,\n tokenIn,\n tokenOut,\n deadline,\n recipient,\n hookData = '0x',\n } = args\n\n assertUint128(amountOut)\n assertUint128(amountInMaximum)\n\n const swapParam = encodeAbiParameters(exactOutputSingleParamsAbi, [\n {\n poolKey: {\n currency0: poolKey.currency0,\n currency1: poolKey.currency1,\n fee: Number(poolKey.fee),\n tickSpacing: Number(poolKey.tickSpacing),\n hooks: poolKey.hooks,\n },\n zeroForOne,\n amountOut,\n amountInMaximum,\n hookData,\n },\n ])\n\n // SETTLE_ALL caps the input at amountInMaximum; the output take delivers the\n // exact output. Native-ETH output uses the explicit-recipient TAKE so the\n // router forwards the ETH straight to `recipient`.\n const settleParam = encodeAbiParameters(currencyAmountAbi, [tokenIn, amountInMaximum])\n const take = buildOutputTake(tokenOut, recipient, amountOut, amountOut)\n\n const actions = encodePacked(\n ['uint8', 'uint8', 'uint8'],\n [SWAP_EXACT_OUT_SINGLE, SETTLE_ALL, take.action],\n )\n\n const v4Input = encodeAbiParameters(\n [\n { name: 'actions', type: 'bytes' },\n { name: 'params', type: 'bytes[]' },\n ],\n [actions, [swapParam, settleParam, take.param]],\n )\n\n const isNativeIn = tokenIn === zeroAddress\n\n // Native-ETH input funds the router with the full overpay cap; a trailing\n // Universal Router SWEEP command (the v4 SWEEP *action* is unsupported here)\n // refunds the unused ETH to the recipient.\n const commandList: number[] = [V4_SWAP]\n const inputs: Hex[] = [v4Input]\n if (isNativeIn) {\n commandList.push(SWEEP)\n inputs.push(encodeEthSweepInput(recipient))\n }\n\n const commands = encodePacked(\n commandList.map(() => 'uint8'),\n commandList,\n )\n const value = isNativeIn ? amountInMaximum : 0n\n\n return { args: [commands, inputs, deadline] as const, value }\n}\n\n/**\n * Build the `execute(commands, inputs, deadline)` calldata + msg.value for an\n * exact-out single-hop v4 swap.\n *\n * @returns The encoded calldata and the ETH `value` to send.\n */\nexport function buildV4ExactOutSwapExecuteCalldata(args: BuildV4ExactOutSwapCalldataArgs): {\n data: Hex\n value: bigint\n} {\n const { args: executeArgs, value } = buildV4ExactOutSwapExecuteArgs(args)\n const data = encodeFunctionData({\n abi: universalRouterAbi,\n functionName: 'execute',\n args: executeArgs,\n })\n return { data, value }\n}\n","/**\n * Snapshot recovery from dispatch calldata.\n * @module v2/sync/snapshotRecovery\n */\n\nimport type { AbiFunction, Address, Hash, Hex, PublicClient } from 'viem'\nimport { decodeFunctionData, getAddress, parseAbi, toFunctionSelector } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\n\nconst LOG_SCAN_WINDOW = 10_000n\nconst rolesExecutionAbi = parseAbi([\n 'function execTransactionWithRole(address to, uint256 value, bytes data, uint8 operation, bytes32 roleKey, bool shouldRevert)',\n])\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 /** Expected Zodiac Roles wrapper for bot-originated Safe dispatches. */\n rolesContext?: {\n modifier: Address\n member: Address\n roleKey: Hash\n }\n}\n\nexport interface RolesSnapshotContext {\n modifier: Address\n member: Address\n roleKey: Hash\n}\n\nexport function decodeSnapshotTransaction(params: {\n input: Hex\n from: Address\n to: Address | null\n account?: Address\n pool?: Address\n rolesContext?: RolesSnapshotContext\n}): DispatchCalldata | null {\n const { account, pool, rolesContext } = params\n let dispatchInput = params.input\n let dispatchSender = params.from\n\n if (rolesContext) {\n if (\n params.to === null ||\n getAddress(params.to) !== getAddress(rolesContext.modifier) ||\n getAddress(params.from) !== getAddress(rolesContext.member)\n ) {\n return null\n }\n try {\n const decodedRoleCall = decodeFunctionData({ abi: rolesExecutionAbi, data: params.input })\n const [target, value, data, operation, roleKey, shouldRevert] = decodedRoleCall.args\n if (\n !pool ||\n getAddress(target) !== getAddress(pool) ||\n value !== 0n ||\n operation !== 0 ||\n roleKey.toLowerCase() !== rolesContext.roleKey.toLowerCase() ||\n !shouldRevert\n ) {\n return null\n }\n dispatchInput = data\n if (!account) return null\n dispatchSender = account\n } catch {\n return null\n }\n } else if (pool && (params.to === null || getAddress(params.to) !== getAddress(pool))) {\n return null\n }\n\n const candidates = decodeAllDispatchCalldata(dispatchInput)\n if (candidates.length === 0) return null\n return account\n ? selectDispatchForAccount(candidates, account, dispatchSender)\n : candidates[candidates.length - 1]\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, rolesContext } = 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 const decoded = decodeSnapshotTransaction({\n input: tx.input,\n from: tx.from,\n to: tx.to,\n account,\n pool,\n rolesContext,\n })\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 * Client-side greeks for the Panoptic v2 SDK.\n *\n * All functions accept bigint inputs (ticks, sizes) and return bigint values\n * in the natural token units — no artificial WAD scaling. The tick-based price\n * (1.0001^tick) naturally encodes the decimal conversion between tokens.\n *\n * Uses pure sqrtPriceX96 arithmetic for exact on-chain fidelity with PanopticQuery.\n * All intermediate calculations keep X96/X192 precision until final scaling.\n *\n * - Value: in numeraire token smallest units (e.g., USDC wei if numeraire is USDC)\n * - Delta: in asset token smallest units (e.g., WETH wei if asset is WETH)\n * - Gamma (dollar-gamma): in numeraire token smallest units\n *\n * @module v2/greeks\n */\n\nimport { tickToSqrtPriceX96 } from '../formatters/tick'\nimport type { TokenIdLeg } from '../types'\n\n// --- Internal Helpers ---\n\n/** Fixed-point scale constants for sqrtPriceX96 arithmetic */\nconst Q96 = 1n << 96n\nconst Q192 = 1n << 192n\n\n/**\n * Convert tick to quote-denominated tick based on asset direction.\n *\n * When isAssetToken0 = true (asset is token0, numeraire is token1):\n * - Tick already encodes price as token1/token0 (numeraire per asset)\n * - Return tick unchanged\n *\n * When isAssetToken0 = false (asset is token1, numeraire is token0):\n * - Tick encodes price as token1/token0, but we need token0/token1 (numeraire per asset)\n * - Invert by negating: 1/price = 1.0001^(-tick)\n */\nfunction quoteTick(tick: bigint, isAssetToken0: boolean): bigint {\n return isAssetToken0 ? tick : -tick\n}\n\n/**\n * Divide with truncation toward zero (matches Solidity division behavior).\n *\n * JavaScript bigint division uses floor (toward negative infinity), but Solidity\n * truncates toward zero. For on-chain fidelity, we must match Solidity.\n *\n * Example:\n * - Solidity: -7 / 2 = -3 (truncate toward zero)\n * - JS bigint: -7n / 2n = -4n (floor toward -∞)\n * - This function: divTrunc(-7n, 2n) = -3n ✓\n */\nfunction divTrunc(numerator: bigint, denominator: bigint): bigint {\n if (denominator === 0n) return 0n\n\n const quotient = numerator / denominator\n const remainder = numerator % denominator\n\n // If signs differ and there's a remainder, JS floored when we need to truncate\n // Add 1 to move toward zero\n if (numerator < 0n !== denominator < 0n && remainder !== 0n) {\n return quotient + 1n\n }\n\n return quotient\n}\n\n/** Resolve isAssetToken0: optional assetIndex overrides leg.asset */\nfunction resolveAssetDirection(leg: Pick<TokenIdLeg, 'asset'>, assetIndex?: bigint): boolean {\n return assetIndex !== undefined ? assetIndex === 0n : leg.asset === 0n\n}\n\n/**\n * Compute the tokenType-denominated notional of a width=0 (loan/credit) leg.\n *\n * When leg.asset !== leg.tokenType, positionSize is in leg.asset units and\n * the borrowed notional is encoded via leg.strike: notional_tokenType_raw =\n * positionSize_raw × 1.0001^strike (a raw-to-raw ratio, unquoted by pool direction).\n * When leg.asset === leg.tokenType, m is already the notional (old convention).\n *\n * `m > 0` for loans (isLong=false), `m < 0` for credits (isLong=true), so the\n * returned notional is signed the same way.\n */\nfunction computeWidth0Notional(leg: TokenIdLeg, m: bigint): bigint {\n const scaleByStrike = leg.asset !== leg.tokenType\n if (!scaleByStrike) return m\n // The UI stores strike with a sign that depends on leg.asset:\n // priceTokenTypePerAsset = 1.0001^(leg.asset === 0 ? strike : -strike)\n // Mirror that here so K_raw matches the intended notional scaling.\n const signedStrike = leg.asset === 0n ? leg.strike : -leg.strike\n const sqrtKraw = tickToSqrtPriceX96(signedStrike)\n const KrawX192 = sqrtKraw * sqrtKraw\n return divTrunc(m * KrawX192, Q192)\n}\n\n/**\n * Calculate value for a width=0 (loan/credit) leg.\n * Width=0 means the range is a single tick (the strike), so there's no meaningful\n * \"in range\" — we use the below/above formulas which avoid division by (r-1)=0.\n *\n * This is the DEBT-ONLY value (the borrowed/lent obligation), used by delta/greeks\n * aggregation where the held-collateral side lives in a separate wallet/CT term. For\n * a standalone payoff chart that must reflect the net user-experienced payoff (which\n * depends on Zap vs Cover-at-mint), use `getLegNetValueWidth0`.\n */\nfunction getLegValueWidth0(\n leg: TokenIdLeg,\n m: bigint,\n qCurrentTick: bigint,\n qStrikeTick: bigint,\n qMintTick: bigint,\n isAssetToken0: boolean,\n _definedRisk: boolean,\n): bigint {\n // For loan/credit legs (width=0), value depends on the borrowed token.\n // m > 0 for loans (isLong=false), m < 0 for credits (isLong=true).\n const borrowsAsset = isCall(leg.tokenType, isAssetToken0)\n\n const notional = computeWidth0Notional(leg, m)\n\n if (borrowsAsset) {\n // Asset loan/credit: debt PnL = -notional*(P - Pm); crosses y=0 at mint price, delta=-notional.\n const sqrtP = tickToSqrtPriceX96(qCurrentTick)\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const PX192 = sqrtP * sqrtP\n const PmX192 = sqrtPm * sqrtPm\n return divTrunc(-notional * (PX192 - PmX192), Q192)\n } else {\n // Numeraire loan/credit: the obligation is a constant amount of the numeraire token,\n // so its value doesn't change with price. getLegValue is mint-relative PnL (option\n // legs cancel the mint baseline via `itm`; the asset branch above returns\n // -notional*(P - Pm), which is 0 at mint), so the numeraire branch's mint-relative PnL\n // is value(P) - value(Pm) = const - const = 0. Returning a nonzero constant here would\n // shift the whole PnL curve/baseline by the notional (double-counting the credit).\n return 0n\n }\n}\n\n/**\n * Calculate the NET (user-experienced) payoff value for a width=0 (loan/credit) leg.\n *\n * Unlike `getLegValueWidth0` (debt-only), this includes the collateral/holding side and\n * therefore depends on how the position was opened:\n *\n * - **Cover at mint** (`swapAtMint = false`): the collateral is sourced in the SAME token as\n * the debt/credit, so the holding side exactly offsets it → net PnL is FLAT (0 everywhere,\n * mint-relative), regardless of which token the leg is denominated in.\n * - **Zap** (`swapAtMint = true`): the collateral is sourced in the OTHER token, leaving a\n * ±1-delta line in the asset (ETH), anchored to 0 at the mint price:\n * - USDC loan → zap to ETH: +1 (long ETH)\n * - ETH loan → zap to USDC: −1 (short ETH)\n * - USDC credit ← zap from ETH: −1 (short ETH)\n * - ETH credit ← zap from USDC: +1 (long ETH)\n *\n * @returns Net leg value in numeraire token smallest units (mint-relative PnL).\n */\nexport function getLegNetValueWidth0(\n leg: TokenIdLeg,\n m: bigint,\n qCurrentTick: bigint,\n qMintTick: bigint,\n isAssetToken0: boolean,\n swapAtMint: boolean,\n itmOffsetNotional: bigint = 0n,\n): bigint {\n // Cover at mint: collateral in the same token as the debt/credit cancels it → flat.\n if (!swapAtMint) return 0n\n\n const borrowsAsset = isCall(leg.tokenType, isAssetToken0)\n\n // ITM-neutralizing credits/loans are sized to offset an option leg's mint-time ITM,\n // which was zapped into the other token under swapAtMint and therefore carries the same\n // ±delta line this leg would otherwise add. Net the leg's notional against that ITM\n // (`itmOffsetNotional`, same token side, opposite sign) so a correctly-sized credit\n // cancels to flat and only the residual (over/under-sizing) contributes a swap line.\n const notional = computeWidth0Notional(leg, m) + itmOffsetNotional\n\n const sqrtP = tickToSqrtPriceX96(qCurrentTick)\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const PX192 = sqrtP * sqrtP\n const PmX192 = sqrtPm * sqrtPm\n\n if (borrowsAsset) {\n // Debt/credit is in the asset (ETH); zapping the collateral into the numeraire leaves the\n // debt-only asset exposure -notional*(P - Pm). (Loan → short ETH; credit → long ETH.)\n return divTrunc(-notional * (PX192 - PmX192), Q192)\n }\n\n // Debt/credit is in the numeraire (USDC); zapping sources/spends the asset (ETH). We hold\n // notional/Pm units of ETH, worth (notional/Pm)*(P - Pm) = notional*(P/Pm) - notional in\n // numeraire. (Loan → long ETH; credit → short ETH.) Zero at mint by construction.\n return divTrunc(notional * PX192, PmX192) - notional\n}\n\n/**\n * Compute the mint-time ITM (in-the-money) adjustment for an option leg.\n *\n * This is the `itm` baseline used by {@link getLegValue}: the amount by which the\n * position was already ITM at mint, expressed in the leg's natural units:\n * - Puts: numeraire units (added directly to the put's `debt*K + v` value).\n * - Calls: asset-ratio units (the call value multiplies it by price: `itm*P`/`itm*Pm`).\n *\n * Extracted so callers (e.g. {@link calculatePositionValue}) can build a per-side ITM\n * notional pool to net width=0 credit/loan legs against — an ITM-neutralizing credit\n * was sized to offset exactly this amount, so it should not add a spurious swap line.\n */\nfunction computeOptionItm(\n m: bigint,\n qStrikeTick: bigint,\n qMintTick: bigint,\n halfWidthTick: bigint,\n isPut: boolean,\n): bigint {\n if (isPut) {\n // Put ITM adjustment\n if (qMintTick < qStrikeTick - halfWidthTick) {\n // Below range: itm = (K - Pm) * m\n const sqrtK = tickToSqrtPriceX96(qStrikeTick)\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const KX192 = sqrtK * sqrtK\n const PmX192 = sqrtPm * sqrtPm\n return divTrunc(m * (KX192 - PmX192), Q192)\n } else if (qMintTick > qStrikeTick + halfWidthTick) {\n // Above range: itm = 0\n return 0n\n }\n // In range: itm = m * (sqrt(K*r) - sqrt(Pm))^2 / (r - 1)\n const sqrtKR = tickToSqrtPriceX96(qStrikeTick + halfWidthTick)\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const sqrtR = tickToSqrtPriceX96(halfWidthTick)\n const rX192 = sqrtR * sqrtR\n const diff = sqrtKR - sqrtPm // X96\n const diffSqX192 = diff * diff // X192\n return divTrunc(m * diffSqX192, rX192 - Q192)\n }\n\n // Call ITM adjustment\n if (qMintTick < qStrikeTick - halfWidthTick) {\n // Below range: itm = 0\n return 0n\n } else if (qMintTick > qStrikeTick + halfWidthTick) {\n // Above range: itm = (1 - K/Pm) * m\n const sqrtK = tickToSqrtPriceX96(qStrikeTick)\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const KX192 = sqrtK * sqrtK\n const PmX192 = sqrtPm * sqrtPm\n return divTrunc(m * (PmX192 - KX192), PmX192)\n }\n // In range: itm = m * (sqrt(r) - sqrt(K/Pm))^2 / (r - 1)\n const sqrtR = tickToSqrtPriceX96(halfWidthTick)\n const sqrtK = tickToSqrtPriceX96(qStrikeTick)\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const rX192 = sqrtR * sqrtR\n // sqrt(K/Pm) in X96 = sqrtK * 2^96 / sqrtPm\n const sqrtKPmX96 = divTrunc(sqrtK * Q96, sqrtPm)\n const diff = sqrtR - sqrtKPmX96 // X96\n const diffSqX192 = diff * diff // X192\n return divTrunc(m * diffSqX192, rX192 - Q192)\n}\n\n// --- Public Helpers ---\n\n/**\n * Check if leg is a call option (vs put).\n *\n * A call is when the leg moves the asset token:\n * - If asset is token0: call when tokenType=0\n * - If asset is token1: call when tokenType=1\n */\nexport function isCall(tokenType: bigint, isAssetToken0: boolean): boolean {\n return isAssetToken0 ? tokenType === 0n : tokenType === 1n\n}\n\n/**\n * Check if position has defined risk (is a spread).\n *\n * A position is defined risk if it has 2+ legs of the same tokenType\n * with both long and short exposure.\n */\nexport function isDefinedRisk(legs: Pick<TokenIdLeg, 'tokenType' | 'isLong'>[]): boolean {\n if (legs.length < 2) return false\n\n for (const tt of [0n, 1n]) {\n const group = legs.filter((l) => l.tokenType === tt)\n if (group.length >= 2 && group.some((l) => l.isLong) && group.some((l) => !l.isLong)) {\n return true\n }\n }\n return false\n}\n\n// --- Per-Leg Greeks ---\n\n/**\n * Calculate the value of a single leg.\n *\n * Value represents the current P&L of the position in numeraire token units.\n * Combines base value (from Panoptic's piecewise formula), debt, and ITM adjustment.\n *\n * Uses sqrtPriceX96 for all calculations to maintain precision and on-chain fidelity.\n *\n * @param leg - The leg to calculate\n * @param currentTick - Current pool tick\n * @param mintTick - Tick at position mint\n * @param positionSize - Position size in asset token smallest units\n * @param poolTickSpacing - Pool tick spacing\n * @param definedRisk - Whether position is defined risk\n * @param assetIndex - Optional override for leg.asset (0n = token0 is asset, 1n = token1)\n * @returns Leg value in numeraire token smallest units\n */\nexport function getLegValue(\n leg: TokenIdLeg,\n currentTick: bigint,\n mintTick: bigint,\n positionSize: bigint,\n poolTickSpacing: bigint,\n definedRisk: boolean,\n assetIndex?: bigint,\n swapAtMint?: boolean,\n): bigint {\n const isAssetToken0 = resolveAssetDirection(leg, assetIndex)\n const qCurrentTick = quoteTick(currentTick, isAssetToken0)\n const qMintTick = quoteTick(mintTick, isAssetToken0)\n const qStrikeTick = quoteTick(leg.strike, isAssetToken0)\n const halfWidthTick = (leg.width * poolTickSpacing) / 2n\n\n const m = leg.isLong ? -(positionSize * leg.optionRatio) : positionSize * leg.optionRatio\n\n // True loan/credit (leg.width === 0n): when the caller specifies how the position was\n // opened (swapAtMint), return the NET user-experienced payoff (Zap vs Cover) instead of\n // the debt-only value. Narrow options whose halfWidth rounds to 0 are excluded.\n if (leg.width === 0n && swapAtMint !== undefined) {\n return getLegNetValueWidth0(leg, m, qCurrentTick, qMintTick, isAssetToken0, swapAtMint)\n }\n\n // Width=0 (loans/credits): single-tick position, no range to integrate over.\n if (halfWidthTick === 0n) {\n return getLegValueWidth0(\n leg,\n m,\n qCurrentTick,\n qStrikeTick,\n qMintTick,\n isAssetToken0,\n definedRisk,\n )\n }\n\n // Compute base value: v = f(P, K, r) from Panoptic's piecewise formula\n let v: bigint\n\n if (qCurrentTick < qStrikeTick - halfWidthTick) {\n // Below range: v = m * P\n const sqrtP = tickToSqrtPriceX96(qCurrentTick)\n const PX192 = sqrtP * sqrtP\n v = divTrunc(m * PX192, Q192)\n } else if (qCurrentTick > qStrikeTick + halfWidthTick) {\n // Above range: v = m * K\n const sqrtK = tickToSqrtPriceX96(qStrikeTick)\n const KX192 = sqrtK * sqrtK\n v = divTrunc(m * KX192, Q192)\n } else {\n // In range: v = m * (2*sqrt(P*K*r) - P - K) / (r - 1)\n const sqrtP = tickToSqrtPriceX96(qCurrentTick)\n const sqrtK = tickToSqrtPriceX96(qStrikeTick)\n const sqrtPKR = tickToSqrtPriceX96(qCurrentTick + qStrikeTick + halfWidthTick)\n const sqrtR = tickToSqrtPriceX96(halfWidthTick)\n\n const PX192 = sqrtP * sqrtP\n const KX192 = sqrtK * sqrtK\n const rX192 = sqrtR * sqrtR\n\n // v = m * (2*sqrtPKR/2^96 - PX192/2^192 - KX192/2^192) / ((rX192 - 2^192)/2^192)\n // = m * (2*sqrtPKR*2^96 - PX192 - KX192) / (rX192 - 2^192)\n const numerator = m * (2n * sqrtPKR * Q96 - PX192 - KX192)\n const denominator = rX192 - Q192\n v = divTrunc(numerator, denominator)\n }\n\n const debt = -m\n const isPut = !isCall(leg.tokenType, isAssetToken0)\n\n // Compute ITM adjustment (differs for puts vs calls)\n const itm = computeOptionItm(m, qStrikeTick, qMintTick, halfWidthTick, isPut)\n\n // Compute final result based on option type\n if (isPut) {\n // Put: result = debt * K + v + itm\n const sqrtK = tickToSqrtPriceX96(qStrikeTick)\n const KX192 = sqrtK * sqrtK\n const debtK = divTrunc(debt * KX192, Q192)\n return debtK + v + itm\n } else {\n // Call: result = debt*P + v + itm*Pm (if defined risk) or debt*P + v + itm*P (if not)\n const sqrtP = tickToSqrtPriceX96(qCurrentTick)\n const PX192 = sqrtP * sqrtP\n const debtP = divTrunc(debt * PX192, Q192)\n\n if (definedRisk) {\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const PmX192 = sqrtPm * sqrtPm\n const itmPm = divTrunc(itm * PmX192, Q192)\n return debtP + v + itmPm\n } else {\n const itmP = divTrunc(itm * PX192, Q192)\n return debtP + v + itmP\n }\n }\n}\n\n/**\n * Calculate the delta of a single leg.\n *\n * Delta is the rate of change of position value with respect to price.\n * For puts: delta = vDelta\n * For calls: delta = debtDelta + vDelta + itmDelta (if not defined risk)\n *\n * Uses sqrtPriceX96 for all price calculations to maintain precision.\n *\n * @param leg - The leg to calculate\n * @param currentTick - Current pool tick\n * @param positionSize - Position size in asset token smallest units\n * @param poolTickSpacing - Pool tick spacing\n * @param mintTick - Tick at mint (optional, for ITM adjustment)\n * @param definedRisk - Whether position is defined risk\n * @param assetIndex - Optional override for leg.asset (0n = token0 is asset, 1n = token1)\n * @returns Leg delta in asset token smallest units\n */\nexport function getLegDelta(\n leg: TokenIdLeg,\n currentTick: bigint,\n positionSize: bigint,\n poolTickSpacing: bigint,\n mintTick: bigint | undefined,\n definedRisk: boolean,\n assetIndex?: bigint,\n): bigint {\n const isAssetToken0 = resolveAssetDirection(leg, assetIndex)\n const qCurrentTick = quoteTick(currentTick, isAssetToken0)\n const qStrikeTick = quoteTick(leg.strike, isAssetToken0)\n const halfWidthTick = (leg.width * poolTickSpacing) / 2n\n\n const m = leg.isLong ? -(positionSize * leg.optionRatio) : positionSize * leg.optionRatio\n\n // True loan/credit: leg.width === 0n (not just halfWidth rounding to 0).\n // Debt-side exposure only — no option-like piecewise formula.\n if (leg.width === 0n) {\n const borrowsAsset = isAssetToken0 ? leg.tokenType === 0n : leg.tokenType === 1n\n if (!borrowsAsset) return 0n\n // See getLegValueWidth0 for the notional-scaling rationale.\n if (leg.asset === leg.tokenType) return -m\n const signedStrike = leg.asset === 0n ? leg.strike : -leg.strike\n const sqrtKraw = tickToSqrtPriceX96(signedStrike)\n const KrawX192 = sqrtKraw * sqrtKraw\n const notional = divTrunc(m * KrawX192, Q192)\n return -notional\n }\n\n // Narrow option whose halfWidth rounds to 0: use option-like width=0 branch\n if (halfWidthTick === 0n) {\n const vDelta = qCurrentTick <= qStrikeTick ? m : 0n\n const isPut = !isCall(leg.tokenType, isAssetToken0)\n if (isPut) return vDelta\n\n // Call: add debt delta and ITM delta (same as normal path but no in-range branch)\n const debtDelta = -m\n let itmDelta = 0n\n if (mintTick !== undefined && !definedRisk) {\n const qMintTick = quoteTick(mintTick, isAssetToken0)\n if (qMintTick > qStrikeTick) {\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const sqrtK = tickToSqrtPriceX96(qStrikeTick)\n const PmX192 = sqrtPm * sqrtPm\n const KX192 = sqrtK * sqrtK\n itmDelta = divTrunc((PmX192 - KX192) * m, PmX192)\n }\n }\n return definedRisk ? debtDelta + vDelta : debtDelta + vDelta + itmDelta\n }\n\n // Compute vDelta: derivative of value with respect to price\n // vDelta = P < lo ? m : P > hi ? 0 : (m * (sqrt(K*r)/sqrt(P) - 1)) / (r - 1)\n let vDelta: bigint\n\n if (qCurrentTick < qStrikeTick - halfWidthTick) {\n // Below range: vDelta = m\n vDelta = m\n } else if (qCurrentTick > qStrikeTick + halfWidthTick) {\n // Above range: vDelta = 0\n vDelta = 0n\n } else {\n // In range: vDelta = m * (sqrt(K*r) - sqrt(P)) / (sqrt(P) * (r - 1))\n const sqrtP = tickToSqrtPriceX96(qCurrentTick) // X96\n const sqrtKR = tickToSqrtPriceX96(qStrikeTick + halfWidthTick) // sqrt(K*r) in X96\n const sqrtR = tickToSqrtPriceX96(halfWidthTick) // X96\n const rX192 = sqrtR * sqrtR // X192\n\n // vDelta = m * (sqrtKR - sqrtP)/2^96 / (sqrtP/2^96 * (rX192 - 2^192)/2^192)\n // = m * (sqrtKR - sqrtP) * 2^192 / (sqrtP * (rX192 - 2^192))\n const numerator = m * (sqrtKR - sqrtP) * Q192\n const denominator = sqrtP * (rX192 - Q192)\n vDelta = divTrunc(numerator, denominator)\n }\n\n const isPut = !isCall(leg.tokenType, isAssetToken0)\n\n if (isPut) {\n return vDelta\n }\n\n // Call: add debt delta and ITM delta\n const debtDelta = -m\n\n const itmDelta =\n mintTick === undefined\n ? 0n\n : (() => {\n const qMintTick = quoteTick(mintTick, isAssetToken0)\n\n if (qMintTick < qStrikeTick - halfWidthTick) {\n // Below range: itmDelta = 0\n return 0n\n } else if (qMintTick > qStrikeTick + halfWidthTick) {\n // Above range: itmDelta = (1 - K/Pm) * m = (Pm - K) * m / Pm\n const sqrtPm = tickToSqrtPriceX96(qMintTick) // X96\n const sqrtK = tickToSqrtPriceX96(qStrikeTick) // X96\n const PmX192 = sqrtPm * sqrtPm // X192\n const KX192 = sqrtK * sqrtK // X192\n\n // itmDelta = (1 - K/Pm) * m = (PmX192 - KX192) * m / PmX192\n return divTrunc((PmX192 - KX192) * m, PmX192)\n } else {\n // In range: itmDelta = m * (sqrt(r) - sqrt(K/Pm))^2 / (r - 1)\n const sqrtR = tickToSqrtPriceX96(halfWidthTick) // X96\n const sqrtK = tickToSqrtPriceX96(qStrikeTick) // X96\n const sqrtPm = tickToSqrtPriceX96(qMintTick) // X96\n const rX192 = sqrtR * sqrtR // X192\n\n // sqrt(K/Pm) = sqrtK / sqrtPm (both X96, so scale cancels)\n // But we need (sqrt(r) - sqrt(K/Pm))^2, so work in X96:\n // sqrtKPm = sqrt(K/Pm) in X96 = sqrtK * 2^96 / sqrtPm\n const sqrtKPmX96 = (sqrtK * Q96) / sqrtPm // X96\n\n // (sqrt(r) - sqrt(K/Pm))^2 = (sqrtR - sqrtKPmX96)^2 / 2^192\n const diff = sqrtR - sqrtKPmX96 // X96\n const diffSqX192 = diff * diff // X192\n\n // itmDelta = m * diffSqX192 / 2^192 / (rX192 / 2^192 - 1)\n // = m * diffSqX192 / (rX192 - 2^192)\n return divTrunc(m * diffSqX192, rX192 - Q192)\n }\n })()\n\n return definedRisk ? debtDelta + vDelta : debtDelta + vDelta + itmDelta\n}\n\n/** Convert a delta between token frames at the current pool tick. */\nexport function toVaultFrameAtTick(\n delta: bigint,\n fromAsset: bigint,\n vaultAssetIndex: 0n | 1n,\n currentTick: bigint,\n flipSignOnAssetInversion = false,\n): bigint {\n if (fromAsset === vaultAssetIndex) return delta\n const sqrtPriceX96 = tickToSqrtPriceX96(currentTick)\n const converted =\n vaultAssetIndex === 0n\n ? (delta * Q192) / (sqrtPriceX96 * sqrtPriceX96)\n : (delta * sqrtPriceX96 * sqrtPriceX96) / Q192\n return flipSignOnAssetInversion ? -converted : converted\n}\n\n/**\n * Calculate one leg's wallet-aware delta in the vault asset frame.\n *\n * Width-zero loans and credits must be evaluated directly in the vault frame.\n * Option legs remain in their natural leg frame until converted at the mark tick.\n */\nexport function getLegDeltaInVaultFrame(\n leg: TokenIdLeg,\n currentTick: bigint,\n positionSize: bigint,\n poolTickSpacing: bigint,\n mintTick: bigint | undefined,\n definedRisk: boolean,\n vaultAssetIndex: 0n | 1n,\n): bigint {\n if (leg.width === 0n) {\n return getLegDelta(\n leg,\n currentTick,\n positionSize,\n poolTickSpacing,\n mintTick,\n definedRisk,\n vaultAssetIndex,\n )\n }\n\n const legDelta = getLegDelta(\n leg,\n currentTick,\n positionSize,\n poolTickSpacing,\n mintTick,\n definedRisk,\n )\n return toVaultFrameAtTick(legDelta, leg.asset, vaultAssetIndex, currentTick, true)\n}\n\n/**\n * Calculate the gamma (dollar gamma) of a single leg.\n *\n * Formula: gamma = (m * sqrt(K * P * r)) / (2 * (r - 1))\n * where:\n * - m = positionSize * optionRatio (with sign based on long/short)\n * - K = strike price (numeraire/asset)\n * - P = current price (numeraire/asset)\n * - r = 1.0001^(width*tickSpacing/2) ≈ 1 (dimensionless ratio)\n *\n * Uses sqrtPriceX96 arithmetic:\n * - sqrt(K*P*r) = tickToSqrtPriceX96(strikeₜ + currentₜ + widthₜ/2)\n * - Keeps X96/X192 precision until final division\n *\n * @param leg - The leg to calculate\n * @param currentTick - Current pool tick\n * @param positionSize - Position size in asset token smallest units\n * @param poolTickSpacing - Pool tick spacing\n * @param assetIndex - Optional override for leg.asset (0n = token0 is asset, 1n = token1)\n * @returns Leg gamma in numeraire token smallest units\n */\nexport function getLegGamma(\n leg: TokenIdLeg,\n currentTick: bigint,\n positionSize: bigint,\n poolTickSpacing: bigint,\n assetIndex?: bigint,\n): bigint {\n const isAssetToken0 = resolveAssetDirection(leg, assetIndex)\n\n // Convert to quote-denominated ticks (negate if asset is token0)\n const qCurrentTick = quoteTick(currentTick, isAssetToken0)\n const qStrikeTick = quoteTick(leg.strike, isAssetToken0)\n const halfWidthTick = (leg.width * poolTickSpacing) / 2n\n\n // True loan: no gamma\n if (leg.width === 0n) return 0n\n\n // Narrow option whose halfWidth rounds to 0: no curvature (denominator 2*(r-1)=0)\n if (halfWidthTick === 0n) return 0n\n\n // Range check: gamma is zero outside [strike - halfWidth, strike + halfWidth]\n // This works in both normal and inverted tick space\n if (qCurrentTick < qStrikeTick - halfWidthTick || qCurrentTick > qStrikeTick + halfWidthTick) {\n return 0n\n }\n\n // Position size with sign: gamma uses inverted multiplier (long = positive, short = negative)\n const m = leg.isLong ? positionSize * leg.optionRatio : -(positionSize * leg.optionRatio)\n\n // sqrt(K * P * r) using tick addition: sqrt(K*P*r) = sqrt(1.0001^(K_tick + P_tick + r_tick))\n const sqrtKPR = tickToSqrtPriceX96(qStrikeTick + qCurrentTick + halfWidthTick) // X96 scale\n\n // r = 1.0001^(halfWidthTick), compute as (sqrtR)^2 to maintain precision\n const sqrtR = tickToSqrtPriceX96(halfWidthTick) // X96 scale\n const rX192 = sqrtR * sqrtR // X192 scale: r * 2^192\n\n // gamma = m * sqrt(K*P*r) / (2 * (r - 1))\n // = m * (sqrtKPR / 2^96) / (2 * (rX192/2^192 - 1))\n // = m * sqrtKPR * 2^192 / (2^96 * 2 * (rX192 - 2^192))\n // = m * sqrtKPR * 2^96 / (2 * (rX192 - 2^192))\n const numerator = m * sqrtKPR * Q96 // [asset] * [numeraire/asset * 2^96] * 2^96 = [numeraire * 2^192]\n const denominator = 2n * (rX192 - Q192) // 2 * (r - 1) in X192 scale\n\n return divTrunc(numerator, denominator) // [numeraire]\n}\n\n// --- Position-Level Aggregates ---\n\n/**\n * Parameters for position-level greek calculations.\n */\nexport interface PositionGreeksInput {\n /** Position legs */\n legs: TokenIdLeg[]\n /** Current pool tick */\n currentTick: bigint\n /** Tick at position mint */\n mintTick: bigint\n /** Position size in asset token smallest units */\n positionSize: bigint\n /** Pool tick spacing */\n poolTickSpacing: bigint\n /** Optional override for leg.asset on all legs (0n = token0 is asset, 1n = token1) */\n assetIndex?: bigint\n /**\n * How width=0 (loan/credit) legs were opened. When provided, `calculatePositionValue`\n * returns the NET user-experienced payoff for those legs (Zap = ±1 line, Cover = flat)\n * instead of the debt-only value. Leave undefined for delta/greeks aggregation, which\n * accounts for the held collateral separately.\n */\n swapAtMint?: boolean\n}\n\n/**\n * Calculate total value across all legs.\n */\nexport function calculatePositionValue(input: PositionGreeksInput): bigint {\n return preparePositionValue(input)(input.currentTick)\n}\n\n/** Prepare mint-time invariants once for an arbitrary series of valuation ticks. */\nexport function preparePositionValue(input: Omit<PositionGreeksInput, 'currentTick'>) {\n const { legs, mintTick, positionSize, poolTickSpacing, assetIndex, swapAtMint } = input\n const definedRisk = isDefinedRisk(legs)\n\n // Fast path: without swapAtMint there is no width=0 net-payoff (delta/greeks aggregation),\n // so no ITM netting is needed — value each leg independently.\n if (swapAtMint === undefined) {\n return (currentTick: bigint) =>\n legs.reduce(\n (sum, leg) =>\n sum +\n getLegValue(\n leg,\n currentTick,\n mintTick,\n positionSize,\n poolTickSpacing,\n definedRisk,\n assetIndex,\n swapAtMint,\n ),\n 0n,\n )\n }\n\n // Pass 1: accumulate each option leg's mint-time ITM into a per-side notional pool. Under\n // swapAtMint the ITM was zapped into the other token, so a width=0 credit/loan that was\n // created to neutralize it (see getLegNetValueWidth0) should net against this pool instead\n // of adding a duplicate swap line. Puts contribute numeraire ITM; calls contribute asset ITM.\n let numeraireItmPool = 0n\n let assetItmPool = 0n\n for (const leg of legs) {\n const halfWidthTick = (leg.width * poolTickSpacing) / 2n\n if (leg.width === 0n || halfWidthTick === 0n) continue // not a valued option leg\n const isAssetToken0 = resolveAssetDirection(leg, assetIndex)\n const qStrikeTick = quoteTick(leg.strike, isAssetToken0)\n const qMintTick = quoteTick(mintTick, isAssetToken0)\n const m = leg.isLong ? -(positionSize * leg.optionRatio) : positionSize * leg.optionRatio\n const isPut = !isCall(leg.tokenType, isAssetToken0)\n const itm = computeOptionItm(m, qStrikeTick, qMintTick, halfWidthTick, isPut)\n if (isPut) numeraireItmPool += itm\n else assetItmPool += itm\n }\n\n const initialNumeraireItm = numeraireItmPool\n const initialAssetItm = assetItmPool\n return (currentTick: bigint) => {\n let numeraireItmPool = initialNumeraireItm\n let assetItmPool = initialAssetItm\n // Each tick consumes its own copy of the mint-time pools.\n let sum = 0n\n for (const leg of legs) {\n if (leg.width === 0n) {\n const isAssetToken0 = resolveAssetDirection(leg, assetIndex)\n const borrowsAsset = isCall(leg.tokenType, isAssetToken0)\n const offset = borrowsAsset ? assetItmPool : numeraireItmPool\n if (borrowsAsset) assetItmPool = 0n\n else numeraireItmPool = 0n\n const qCurrentTick = quoteTick(currentTick, isAssetToken0)\n const qMintTick = quoteTick(mintTick, isAssetToken0)\n const m = leg.isLong ? -(positionSize * leg.optionRatio) : positionSize * leg.optionRatio\n sum += getLegNetValueWidth0(\n leg,\n m,\n qCurrentTick,\n qMintTick,\n isAssetToken0,\n swapAtMint,\n offset,\n )\n } else {\n sum += getLegValue(\n leg,\n currentTick,\n mintTick,\n positionSize,\n poolTickSpacing,\n definedRisk,\n assetIndex,\n swapAtMint,\n )\n }\n }\n return sum\n }\n}\n\n/** Value a tick series without repeating position preparation. */\nexport function calculatePositionValues(\n input: Omit<PositionGreeksInput, 'currentTick'>,\n ticks: readonly bigint[],\n): bigint[] {\n return ticks.map(preparePositionValue(input))\n}\n\n/**\n * Calculate total delta across all legs.\n */\nexport function calculatePositionDelta(input: PositionGreeksInput): bigint {\n const { legs, currentTick, mintTick, positionSize, poolTickSpacing, assetIndex } = input\n const definedRisk = isDefinedRisk(legs)\n\n return legs.reduce(\n (sum, leg) =>\n sum +\n getLegDelta(\n leg,\n currentTick,\n positionSize,\n poolTickSpacing,\n mintTick,\n definedRisk,\n assetIndex,\n ),\n 0n,\n )\n}\n\n/**\n * Calculate debt-only position delta in a single target asset frame.\n *\n * Option legs are first valued in their natural `leg.asset` frame, then\n * converted into `assetIndex` using the current pool price. Width-zero legs\n * are evaluated directly in the target frame.\n *\n * Width=0 loan/credit legs include only their debt obligation. The held-token\n * side must be added separately from account collateral balances, preventing a\n * zap from being counted once in the position and again in collateral.\n */\nexport function calculatePositionDeltaDebtOnly(\n input: Omit<PositionGreeksInput, 'assetIndex' | 'swapAtMint'> & {\n assetIndex: 0n | 1n\n },\n): bigint {\n const { legs, currentTick, mintTick, positionSize, poolTickSpacing, assetIndex } = input\n const definedRisk = isDefinedRisk(legs)\n\n return legs.reduce(\n (sum, leg) =>\n sum +\n getLegDeltaInVaultFrame(\n leg,\n currentTick,\n positionSize,\n poolTickSpacing,\n mintTick,\n definedRisk,\n assetIndex,\n ),\n 0n,\n )\n}\n\n/** Delta and one strategy contract's notional, both in the requested asset frame. */\nexport function getPositionDeltaMetrics(\n input: Omit<PositionGreeksInput, 'assetIndex' | 'swapAtMint'> & { assetIndex: 0n | 1n },\n) {\n const orderedLegs = [...input.legs].sort((a, b) =>\n a.index < b.index ? -1 : a.index > b.index ? 1 : 0,\n )\n const nativeLeg = orderedLegs.find((leg) => leg.width > 0n) ?? orderedLegs[0]\n return {\n delta: calculatePositionDeltaDebtOnly(input),\n // Ratios belong to the strategy's exposure, not its number of contracts.\n contractSize: nativeLeg\n ? toVaultFrameAtTick(input.positionSize, nativeLeg.asset, input.assetIndex, input.currentTick)\n : 0n,\n }\n}\n\n/**\n * Calculate total gamma across all legs.\n */\nexport function calculatePositionGamma(input: PositionGreeksInput): bigint {\n const { legs, currentTick, positionSize, poolTickSpacing, assetIndex } = input\n\n return legs.reduce(\n (sum, leg) => sum + getLegGamma(leg, currentTick, positionSize, poolTickSpacing, assetIndex),\n 0n,\n )\n}\n\n/**\n * Position greeks result.\n */\nexport interface PositionGreeksResult {\n /** Position value in numeraire token smallest units */\n value: bigint\n /** Position delta in asset token smallest units */\n delta: bigint\n /** Position gamma in numeraire token smallest units */\n gamma: bigint\n}\n\n/**\n * Calculate all greeks for a position.\n */\nexport function calculatePositionGreeks(input: PositionGreeksInput): PositionGreeksResult {\n return {\n value: calculatePositionValue(input),\n delta: calculatePositionDelta(input),\n gamma: calculatePositionGamma(input),\n }\n}\n\n// --- Portfolio (Multi-Position) Aggregates ---\n\n/**\n * Aggregate value across multiple independent positions.\n *\n * Each entry is valued with its OWN `positionSize`, `mintTick`, and legs, then\n * summed. Do NOT collapse multiple positions into one synthetic `PositionGreeksInput`\n * with a shared `positionSize` — `m = positionSize * optionRatio` is per-position, so a\n * shared size double-counts (and integer `optionRatio` cannot encode fractional shares).\n *\n * @param positions - One `PositionGreeksInput` per open position\n * @returns Total value in numeraire token smallest units\n */\nexport function calculatePortfolioValue(positions: PositionGreeksInput[]): bigint {\n return positions.reduce((sum, input) => sum + calculatePositionValue(input), 0n)\n}\n\n/**\n * Aggregate delta across multiple independent positions.\n *\n * See {@link calculatePortfolioValue} for why each position must keep its own\n * `positionSize` rather than being merged into one synthetic position.\n *\n * @param positions - One `PositionGreeksInput` per open position\n * @returns Total delta in asset token smallest units\n */\nexport function calculatePortfolioDelta(positions: PositionGreeksInput[]): bigint {\n return positions.reduce((sum, input) => sum + calculatePositionDelta(input), 0n)\n}\n\n/**\n * Aggregate gamma across multiple independent positions.\n *\n * See {@link calculatePortfolioValue} for why each position must keep its own\n * `positionSize` rather than being merged into one synthetic position.\n *\n * @param positions - One `PositionGreeksInput` per open position\n * @returns Total gamma in numeraire token smallest units\n */\nexport function calculatePortfolioGamma(positions: PositionGreeksInput[]): bigint {\n return positions.reduce((sum, input) => sum + calculatePositionGamma(input), 0n)\n}\n\n/**\n * Calculate all greeks aggregated across multiple independent positions.\n */\nexport function calculatePortfolioGreeks(positions: PositionGreeksInput[]): PositionGreeksResult {\n return {\n value: calculatePortfolioValue(positions),\n delta: calculatePortfolioDelta(positions),\n gamma: calculatePortfolioGamma(positions),\n }\n}\n\n// --- Loan/Credit Swap-Aware Delta ---\n\n/**\n * Calculate the effective delta of a loan leg accounting for swapAtMint.\n *\n * A loan borrows one token and (optionally) swaps it for the other at mint.\n * The net delta depends on whether the swap occurred:\n *\n * | Scenario | Result |\n * |-----------------------|-------------------------------------------------|\n * | No swap | 0n (hold what you owe, net zero) |\n * | Swap + borrows asset | -m (hold numeraire, owe asset → short exposure) |\n * | Swap + borrows numer. | +m (hold asset, owe numeraire → long exposure) |\n *\n * Only meaningful for legs with `width === 0n`. For options, use `getLegDelta`.\n *\n * @param leg - The loan leg\n * @param positionSize - Position size in asset token smallest units\n * @param swapAtMint - Whether the borrowed tokens were swapped at mint\n * @param assetIndex - Optional override for leg.asset (0n = token0 is asset)\n * @returns Effective delta in asset token smallest units\n */\nexport function getLoanEffectiveDelta(\n leg: TokenIdLeg,\n positionSize: bigint,\n swapAtMint: boolean,\n assetIndex?: bigint,\n): bigint {\n if (!swapAtMint) return 0n\n\n const isAssetToken0 = resolveAssetDirection(leg, assetIndex)\n const m = leg.isLong ? -(positionSize * leg.optionRatio) : positionSize * leg.optionRatio\n const borrowsAsset = isAssetToken0 ? leg.tokenType === 0n : leg.tokenType === 1n\n\n return borrowsAsset ? -m : m\n}\n\n/**\n * Calculate total delta for a position, using swap-aware delta for loan legs.\n *\n * For legs with `width === 0n` (loans/credits), uses `getLoanEffectiveDelta`\n * which accounts for the swapAtMint flag. For option legs (`width > 0n`),\n * uses the standard `getLegDelta`.\n *\n * @param input - Position greeks input plus swapAtMint flag\n * @returns Total delta in asset token smallest units\n */\nexport function calculatePositionDeltaWithSwap(\n input: PositionGreeksInput & { swapAtMint: boolean },\n): bigint {\n const { legs, currentTick, mintTick, positionSize, poolTickSpacing, assetIndex, swapAtMint } =\n input\n const optionLegs = legs.filter((l) => l.width !== 0n)\n const definedRisk = isDefinedRisk(optionLegs)\n\n return legs.reduce((sum, leg) => {\n if (leg.width === 0n) {\n return sum + getLoanEffectiveDelta(leg, positionSize, swapAtMint, assetIndex)\n }\n return (\n sum +\n getLegDelta(\n leg,\n currentTick,\n positionSize,\n poolTickSpacing,\n mintTick,\n definedRisk,\n assetIndex,\n )\n )\n }, 0n)\n}\n","import type { Address, Hex } from 'viem'\n\nimport { DEFAULT_VEGOID } from '../tokenId/constants'\n\nexport const vegoid = Number(DEFAULT_VEGOID)\n\nexport interface LegParams {\n index: number\n width: bigint\n optionRatio: bigint\n asset: bigint\n strike: bigint\n isLong: bigint // 0 if short, 1 if long\n tokenType: bigint // Which token (0|1 in underlying pool) is being moved\n riskPartner: bigint\n}\n\nexport const areLegsEqual = (leg1: LegParams, leg2: LegParams): boolean => {\n return (\n leg1.width === leg2.width &&\n leg1.optionRatio === leg2.optionRatio &&\n leg1.asset === leg2.asset &&\n leg1.strike === leg2.strike &&\n leg1.isLong === leg2.isLong &&\n leg1.tokenType === leg2.tokenType &&\n leg1.riskPartner === leg2.riskPartner\n )\n}\n\nexport const stringifyLeg = (leg: LegParams): string => {\n return `Index: ${leg.index} | Width: ${leg.width.toString()} | OptionRatio: ${leg.optionRatio.toString()} | Asset: ${leg.asset.toString()} | Strike: ${leg.strike.toString()} | IsLong?: ${leg.isLong.toString()} | Token Type: ${leg.tokenType.toString()} | Risk Partner: ${leg.riskPartner.toString()}`\n}\n\n// Synthetic TokenIds padding constant\nexport const SYNTH_TOKENID_PADDING = BigInt(\n '115792089237316195423570985007226406215939081747436879206741300988257197096960',\n)\n\nconst POOL_ID_SIZE = 64n\nconst VEGOID_STARTING_BIT = 40n\nconst VEGOID_SIZE = 8n\nconst TICK_SPACING_STARTING_BIT = 48n\nconst ASSET_STARTING_BIT = 0n\nconst ASSET_SIZE = 1n\nconst RATIO_STARTING_BIT = ASSET_STARTING_BIT + ASSET_SIZE // 0 + 1\nconst RATIO_SIZE = 7n\nconst IS_LONG_STARTING_BIT = RATIO_STARTING_BIT + RATIO_SIZE // 1 + 7\nconst IS_LONG_SIZE = 1n\nconst TOKEN_TYPE_STARTING_BIT = IS_LONG_STARTING_BIT + IS_LONG_SIZE // 8 + 1\nconst TOKEN_TYPE_SIZE = 1n\nconst RISK_PARTNER_STARTING_BIT = TOKEN_TYPE_STARTING_BIT + TOKEN_TYPE_SIZE // 9 + 1\nconst RISK_PARTNER_SIZE = 2n\nconst STRIKE_STARTING_BIT = RISK_PARTNER_STARTING_BIT + RISK_PARTNER_SIZE // 10 + 2\nconst STRIKE_SIZE = 24n\nconst WIDTH_STARTING_BIT = STRIKE_STARTING_BIT + STRIKE_SIZE // 12 + 24\nconst WIDTH_SIZE = 12n\nconst LEG_SIZE = WIDTH_STARTING_BIT + WIDTH_SIZE // 36 + 12 = 48\n\n// converts unsigned strike to signed for encoding\nexport const convertStrike = (n: bigint): bigint => {\n if (n < 0n) {\n // 3 bytes because strike is int24\n return 16777216n + n\n } else {\n return n\n }\n}\n\n// converts encoded (unsigned) strike back to signed\nexport const signStrike = (encodedStrike: bigint): bigint => {\n if (encodedStrike > 2n ** 23n) {\n return encodedStrike - 16777216n\n }\n return encodedStrike\n}\n\nconst getLegOffsetByIndex = (index: bigint): bigint => index * LEG_SIZE\n\nconst encodeAsset = (asset: bigint, legIndex: bigint): bigint =>\n asset << (getLegOffsetByIndex(legIndex) + ASSET_STARTING_BIT + POOL_ID_SIZE)\n\nconst encodeRatio = (optionRatio: bigint, legIndex: bigint): bigint =>\n optionRatio << (getLegOffsetByIndex(legIndex) + RATIO_STARTING_BIT + POOL_ID_SIZE)\n\nconst encodeIsLong = (isLong: bigint, legIndex: bigint): bigint =>\n isLong << (getLegOffsetByIndex(legIndex) + IS_LONG_STARTING_BIT + POOL_ID_SIZE)\n\nconst encodeTokenType = (tokenType: bigint, legIndex: bigint): bigint =>\n tokenType << (getLegOffsetByIndex(legIndex) + TOKEN_TYPE_STARTING_BIT + POOL_ID_SIZE)\n\nconst encodeRiskPartner = (riskPartner: bigint, legIndex: bigint): bigint =>\n riskPartner << (getLegOffsetByIndex(legIndex) + RISK_PARTNER_STARTING_BIT + POOL_ID_SIZE)\n\nconst encodeStrike = (strike: bigint, legIndex: bigint): bigint =>\n convertStrike(strike) << (getLegOffsetByIndex(legIndex) + STRIKE_STARTING_BIT + POOL_ID_SIZE)\n\nconst encodeWidth = (width: bigint, legIndex: bigint): bigint =>\n width << (getLegOffsetByIndex(legIndex) + WIDTH_STARTING_BIT + POOL_ID_SIZE)\n\nconst decodeAsset = (leg: bigint): bigint => leg % (1n << ASSET_SIZE)\n\nconst decodeRatio = (leg: bigint): bigint => (leg >> RATIO_STARTING_BIT) % (1n << RATIO_SIZE)\n\nconst decodeIsLong = (leg: bigint): bigint => (leg >> IS_LONG_STARTING_BIT) % (1n << IS_LONG_SIZE)\n\nconst decodeTokenType = (leg: bigint): bigint =>\n (leg >> TOKEN_TYPE_STARTING_BIT) % (1n << TOKEN_TYPE_SIZE)\n\nconst decodeRiskPartner = (leg: bigint): bigint =>\n (leg >> RISK_PARTNER_STARTING_BIT) % (1n << RISK_PARTNER_SIZE)\n\nconst decodeStrike = (leg: bigint): bigint =>\n signStrike((leg >> STRIKE_STARTING_BIT) % (1n << STRIKE_SIZE))\n\nconst decodeWidth = (leg: bigint): bigint => (leg >> WIDTH_STARTING_BIT) % (1n << WIDTH_SIZE)\n\n/**\n * Extract vegoid from a TokenId\n * Vegoid is stored in bits 40-47 (8 bits) of the poolId\n */\nexport const decodeVegoid = (tokenId: bigint): bigint => {\n return ((tokenId % (1n << POOL_ID_SIZE)) >> VEGOID_STARTING_BIT) % (1n << VEGOID_SIZE)\n}\n\n/**\n * Extract vegoid from a poolId\n * Vegoid is stored in bits 40-47 (8 bits) of the poolId\n */\nexport const decodeVegoidFromPoolId = (poolId: bigint): bigint => {\n return (poolId >> VEGOID_STARTING_BIT) % (1n << VEGOID_SIZE)\n}\n\n/**\n * Extract tickSpacing from a TokenId\n * TickSpacing is stored in bits 48-63 (16 bits) of the poolId\n */\nexport const decodeTickSpacing = (tokenId: bigint): bigint => {\n return (tokenId % (1n << POOL_ID_SIZE)) >> TICK_SPACING_STARTING_BIT\n}\n\n/**\n * Encode poolId with vegoid support\n * The encoded PoolId structure: [16-bit tickSpacing][8-bit vegoid][40-bit pool address]\n * @param address The Uniswap V3 pool address (hex string)\n * @param tickSpacing The tick spacing of the pool\n * @param vegoidValue The vegoid value (defaults to 4 if not provided)\n * @return The encoded poolId as bigint\n */\nexport const encodePoolId = (\n address: Address,\n tickSpacing: bigint,\n vegoidValue: bigint = BigInt(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) = 8 bytes\n // All in little-endian format\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 |= (vegoidValue % 256n) << 40n\n\n // Add tickSpacing at bit 48\n poolId |= (tickSpacing % 65536n) << 48n\n\n return poolId\n}\n\n/**\n * Encode V4 poolId with vegoid support\n * The encoded PoolId structure: [16-bit tickSpacing][8-bit vegoid][40-bit pool pattern]\n * @param poolId The V4 pool ID (bytes32 hex string)\n * @param tickSpacing The tick spacing of the pool\n * @param vegoidValue The vegoid value (defaults to 4 if not provided)\n * @return The encoded poolId as bigint\n */\nexport const encodeV4PoolId = (\n poolId: Hex,\n tickSpacing: bigint,\n vegoidValue: bigint = BigInt(vegoid),\n): bigint => {\n // Remove 0x prefix and get last 10 hex chars (5 bytes = 40 bits)\n const poolIdHex = poolId.slice(2)\n const last5BytesHex = poolIdHex.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: pool pattern (5 bytes) + vegoid (1 byte) + tickSpacing (2 bytes) = 8 bytes\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 |= (vegoidValue % 256n) << 40n\n\n // Add tickSpacing at bit 48\n encodedPoolId |= (tickSpacing % 65536n) << 48n\n\n return encodedPoolId\n}\n\n// Can be (ab)used to create a leg id by passing in a tokenId of 0\nexport const addLeg = (tokenId: bigint, leg: LegParams): bigint => {\n const legIndex = BigInt(leg.index)\n const width = leg.width\n const strike = leg.strike\n const riskPartner = leg.riskPartner\n const tokenType = leg.tokenType\n const isLong = leg.isLong\n const optionRatio = leg.optionRatio\n const asset = leg.asset\n\n return (\n tokenId +\n encodeWidth(width, legIndex) +\n encodeStrike(strike, legIndex) +\n (encodeRiskPartner(riskPartner, legIndex) |\n encodeTokenType(tokenType, legIndex) |\n encodeIsLong(isLong, legIndex) |\n encodeRatio(optionRatio, legIndex) |\n encodeAsset(asset, legIndex))\n )\n}\n\nexport const encodePosition = (poolId: bigint, legs: LegParams[]): bigint => {\n return legs.reduce((acc, leg) => addLeg(acc, leg), poolId)\n}\n\nexport interface Position {\n poolId: string\n legs: LegParams[]\n}\n\nexport const decodePosition = (encodedPosition: bigint): Position => {\n const leg4 = (encodedPosition >> (POOL_ID_SIZE + getLegOffsetByIndex(3n))) % (1n << LEG_SIZE)\n\n const leg3 = (encodedPosition >> (POOL_ID_SIZE + getLegOffsetByIndex(2n))) % (1n << LEG_SIZE)\n\n const leg2 = (encodedPosition >> (POOL_ID_SIZE + getLegOffsetByIndex(1n))) % (1n << LEG_SIZE)\n\n const leg1 = (encodedPosition >> (POOL_ID_SIZE + getLegOffsetByIndex(0n))) % (1n << LEG_SIZE)\n\n let poolId = (encodedPosition % (1n << POOL_ID_SIZE)).toString(16)\n\n const poolIdLength = 16 // poolId is 64 bits => 16 hex characters\n if (poolId.length < poolIdLength) {\n poolId = padHexWithZeros('0x' + poolId, poolIdLength + 2) // +2 for 0x prefix\n } else {\n poolId = '0x' + poolId\n }\n\n const encodedLegs = [leg1, leg2, leg3, leg4].filter((leg) => decodeRatio(leg) > 0n)\n\n const legs: LegParams[] = encodedLegs.map((leg, index) => ({\n index: index,\n width: decodeWidth(leg),\n strike: decodeStrike(leg),\n riskPartner: decodeRiskPartner(leg),\n tokenType: decodeTokenType(leg),\n isLong: decodeIsLong(leg),\n optionRatio: decodeRatio(leg),\n asset: decodeAsset(leg),\n }))\n\n return {\n poolId,\n legs,\n }\n}\n\nexport function padHexWithZeros(hex: string, length: number): string {\n // Check if the hex starts with \"0x\"\n if (hex.startsWith('0x')) {\n // Remove the \"0x\" prefix\n hex = hex.substring(2)\n } else {\n throw new Error('do not use padHexWithZeros on non-hex strings')\n }\n\n // Subtract 2 from length to account for the substring(2) call to remove the leading 0x\n while (hex.length < length - 2) {\n hex = '0' + hex\n }\n\n // Add back the \"0x\" prefix\n return '0x' + hex\n}\n","/**\n * Event reconstruction for full position history scan.\n * @module v2/sync/eventReconstruction\n */\n\nimport type { Address, Hash, PublicClient } from 'viem'\nimport { getAbiItem } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport type { SyncEvent } from '../types'\n\ntype EventReconstructionClient = Pick<PublicClient, 'getBlock' | 'getLogs'>\n\n/**\n * Parameters for event reconstruction.\n */\nexport interface EventReconstructionParams {\n /** viem public client */\n client: EventReconstructionClient\n /** Pool address */\n poolAddress: Address\n /** Account to reconstruct positions for */\n account: Address\n /** Starting block for event scan */\n fromBlock: bigint\n /** Ending block for event scan */\n toBlock: bigint\n /** Batch size for log queries (default: 10000) */\n batchSize?: bigint\n /** Progress callback */\n onProgress?: (event: SyncEvent) => void\n}\n\n/**\n * Event reconstruction result.\n */\nexport interface EventReconstructionResult {\n /** Position IDs that are currently open */\n openPositions: bigint[]\n /** Position IDs that have been closed */\n closedPositions: bigint[]\n /** Number of blocks scanned */\n blocksScanned: bigint\n /** Last scanned block number */\n lastBlock: bigint\n /** Last scanned block hash */\n lastBlockHash: Hash\n}\n\n/**\n * Mint event from reconstruction.\n */\ninterface MintEvent {\n tokenId: bigint\n positionSize: bigint\n blockNumber: bigint\n blockHash: Hash\n transactionHash: Hash\n logIndex: number\n}\n\n/**\n * Burn event from reconstruction.\n */\ninterface BurnEvent {\n tokenId: bigint\n positionSize: bigint\n blockNumber: bigint\n blockHash: Hash\n transactionHash: Hash\n logIndex: number\n}\n\n/**\n * Reconstruct position history from events.\n * This is the fallback method when snapshot recovery fails.\n * It scans all OptionMinted and OptionBurnt events to build the position set.\n *\n * @param params - Reconstruction parameters\n * @returns Reconstruction result with open and closed positions\n */\nexport async function reconstructFromEvents(\n params: EventReconstructionParams,\n): Promise<EventReconstructionResult> {\n const {\n client,\n poolAddress,\n account,\n fromBlock,\n toBlock,\n batchSize = 10000n,\n onProgress,\n } = params\n\n const mintEvents: MintEvent[] = []\n const burnEvents: BurnEvent[] = []\n const totalBlocks = toBlock - fromBlock + 1n\n const safeBatchSize = batchSize > 0n ? batchSize : 10000n\n\n const scanRange = async (rangeFromBlock: bigint, rangeToBlock: bigint) => {\n const [mints, burns] = await Promise.all([\n client.getLogs({\n address: poolAddress,\n event: OPTION_MINTED_EVENT,\n args: { recipient: account },\n fromBlock: rangeFromBlock,\n toBlock: rangeToBlock,\n }),\n client.getLogs({\n address: poolAddress,\n event: OPTION_BURNT_EVENT,\n args: { recipient: account },\n fromBlock: rangeFromBlock,\n toBlock: rangeToBlock,\n }),\n ])\n\n // Process mint events\n for (const mint of mints) {\n // Decode position size from balanceData (first 128 bits)\n const balanceData = mint.args.balanceData as bigint\n const positionSize = balanceData & ((1n << 128n) - 1n)\n\n mintEvents.push({\n tokenId: mint.args.tokenId as bigint,\n positionSize,\n blockNumber: mint.blockNumber,\n blockHash: mint.blockHash,\n transactionHash: mint.transactionHash,\n logIndex: mint.logIndex,\n })\n }\n\n // Process burn events\n for (const burn of burns) {\n burnEvents.push({\n tokenId: burn.args.tokenId as bigint,\n positionSize: burn.args.positionSize as bigint,\n blockNumber: burn.blockNumber,\n blockHash: burn.blockHash,\n transactionHash: burn.transactionHash,\n logIndex: burn.logIndex,\n })\n }\n\n const blocksProcessed = rangeToBlock - fromBlock + 1n\n const progress = totalBlocks > 0n ? (blocksProcessed * 100n) / totalBlocks : 100n\n onProgress?.({\n currentBlock: rangeToBlock,\n targetBlock: toBlock,\n positionsFound: BigInt(mintEvents.length),\n progress: progress > 100n ? 100n : progress,\n })\n }\n\n // Account and pool topics make this query selective enough for providers that\n // permit wide eth_getLogs ranges. This keeps the fallback practical on mainnet.\n // Providers with an explicit range cap fall back to bounded requests.\n try {\n await scanRange(fromBlock, toBlock)\n } catch (error) {\n if (!isRangeLimitError(error)) throw error\n\n let currentBlock = fromBlock\n while (currentBlock <= toBlock) {\n const endBlock =\n currentBlock + safeBatchSize - 1n > toBlock ? toBlock : currentBlock + safeBatchSize - 1n\n await scanRange(currentBlock, endBlock)\n currentBlock = endBlock + 1n\n }\n }\n\n // Build position map: tokenId -> net position size\n const positionMap = new Map<bigint, bigint>()\n\n // Sort all events by block and log index\n const allEvents = [\n ...mintEvents.map((e) => ({ ...e, type: 'mint' as const })),\n ...burnEvents.map((e) => ({ ...e, type: 'burn' as const })),\n ].sort((a, b) => {\n const blockDiff = Number(a.blockNumber - b.blockNumber)\n if (blockDiff !== 0) return blockDiff\n return a.logIndex - b.logIndex\n })\n\n // Process events in order\n for (const event of allEvents) {\n const current = positionMap.get(event.tokenId) ?? 0n\n\n if (event.type === 'mint') {\n positionMap.set(event.tokenId, current + event.positionSize)\n } else {\n positionMap.set(event.tokenId, current - event.positionSize)\n }\n }\n\n // Separate open and closed positions\n const openPositions: bigint[] = []\n const closedPositions: bigint[] = []\n\n for (const [tokenId, size] of positionMap) {\n if (size > 0n) {\n openPositions.push(tokenId)\n } else {\n closedPositions.push(tokenId)\n }\n }\n\n // Get the last block hash\n const lastBlock = await client.getBlock({ blockNumber: toBlock })\n\n return {\n openPositions,\n closedPositions,\n blocksScanned: toBlock - fromBlock + 1n,\n lastBlock: toBlock,\n lastBlockHash: lastBlock.hash,\n }\n}\n\nconst OPTION_MINTED_EVENT = getAbiItem({ abi: panopticPoolV2Abi, name: 'OptionMinted' })\nconst OPTION_BURNT_EVENT = getAbiItem({ abi: panopticPoolV2Abi, name: 'OptionBurnt' })\n\nfunction isRangeLimitError(error: unknown): boolean {\n const messages: string[] = []\n let current: unknown = error\n for (let depth = 0; current && typeof current === 'object' && depth < 5; depth += 1) {\n if ('message' in current && typeof current.message === 'string') {\n messages.push(current.message)\n }\n if ('details' in current && typeof current.details === 'string') {\n messages.push(current.details)\n }\n current = 'cause' in current ? current.cause : undefined\n }\n if (typeof error === 'string') messages.push(error)\n\n const message = messages.join(' ').toLowerCase()\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\n/**\n * Get the deployment block for a pool.\n * This searches for the first PoolInitialized event.\n *\n * @param client - viem public client\n * @param poolAddress - Pool address\n * @returns Deployment block number or null if not found\n */\nexport async function getPoolDeploymentBlock(\n client: PublicClient,\n poolAddress: Address,\n): Promise<bigint | null> {\n // Search for the first event from this pool\n // We use a binary search approach to find the deployment block\n\n const currentBlock = await client.getBlockNumber()\n let low = 0n\n let high = currentBlock\n let foundBlock: bigint | null = null\n\n // Binary search with scan windows to find the deployment block.\n // Each iteration checks [mid, mid + scanRange] for logs.\n const scanRange = 10000n\n\n while (low <= high) {\n const mid = (low + high) / 2n\n const rangeEnd = mid + scanRange > high ? high : mid + scanRange\n\n try {\n const logs = await client.getLogs({\n address: poolAddress,\n fromBlock: mid,\n toBlock: rangeEnd,\n })\n\n if (logs.length > 0) {\n // Found logs — record earliest and search before it\n const earliest = logs[0].blockNumber\n if (foundBlock === null || earliest < foundBlock) {\n foundBlock = earliest\n }\n high = earliest - 1n\n } else {\n // No logs in [mid, rangeEnd] — skip the entire checked range\n low = rangeEnd + 1n\n }\n } catch {\n // Range too large for RPC — halve the search space\n high = mid + (rangeEnd - mid) / 2n\n }\n }\n\n return foundBlock\n}\n","/**\n * Construction of fee-protected self-settlement dispatches.\n *\n * A short position's displayed premium can include fees that still live in\n * Uniswap. Minting a temporary, minimal short over the same chunks collects\n * those fees into `settledTokens`; burning it after settlement leaves the\n * caller's position list unchanged.\n * @module v2/writes/protectedSettle\n */\n\nimport { PanopticError } from '../errors'\nimport { tickToSqrtPriceX96 } from '../formatters'\nimport type { DispatchIntent } from '../simulations/creditWrap'\nimport { addLegToTokenId, decodeAllLegs, decodeTickSpacing } from '../tokenId'\n\nconst POOL_ID_MASK = (1n << 64n) - 1n\nconst Q96 = 1n << 96n\nconst MAX_UINT128 = (1n << 128n) - 1n\nconst SETTLE_LIMITS = [-887272n, 887272n, 0n] as const\n\nexport interface BuildProtectedSettleDispatchParams {\n /** Positions whose premium should be settled. */\n positionIdList: bigint[]\n /** The caller's complete held list. A settlement does not change it. */\n finalPositionIdList: bigint[]\n /** Current stored size for every entry in `positionIdList`. */\n positionSizes: bigint[]\n usePremiaAsCollateral?: boolean\n builderCode?: bigint\n}\n\nexport interface ProtectedSettlePlan {\n /** Atomic poke/settle/poke dispatch submitted after buyer settlements. */\n dispatch: DispatchIntent\n /** Poke-only dispatch used to verify no displayed premium remains uncollected. */\n collectionDispatch?: DispatchIntent\n /** Temporary position IDs, one for each settled position containing short chunks. */\n pokingTokenIds: bigint[]\n}\n\nfunction ceilDiv(numerator: bigint, denominator: bigint): bigint {\n return (numerator + denominator - 1n) / denominator\n}\n\n/** Smallest position size that creates non-zero liquidity on every poke leg. */\nfunction minimumPokeSize(\n legs: ReturnType<typeof decodeAllLegs>,\n tickSpacing: bigint,\n): bigint | undefined {\n let requiredSize = 1n\n\n for (const leg of legs) {\n const widthInTicks = leg.width * tickSpacing\n const lowerTick = leg.strike - widthInTicks / 2n\n const upperTick = leg.strike + (widthInTicks + 1n) / 2n\n const sqrtLower = tickToSqrtPriceX96(lowerTick)\n const sqrtUpper = tickToSqrtPriceX96(upperTick)\n const delta = sqrtUpper - sqrtLower\n const liquidityFactor = leg.asset === 0n ? (sqrtLower * sqrtUpper) / Q96 : Q96\n if (liquidityFactor === 0n) return undefined\n const requiredAmount = ceilDiv(delta, liquidityFactor)\n const legSize = ceilDiv(requiredAmount, leg.optionRatio)\n if (legSize > requiredSize) requiredSize = legSize\n }\n\n if (requiredSize > MAX_UINT128) {\n return undefined\n }\n return requiredSize\n}\n\nfunction encodePokeToken(\n sourceTokenId: bigint,\n legs: ReturnType<typeof decodeAllLegs>,\n firstRatio: bigint,\n assetMask: bigint,\n): bigint {\n let tokenId = sourceTokenId & POOL_ID_MASK\n legs.forEach((leg, index) => {\n const encodedIndex = BigInt(index)\n tokenId = addLegToTokenId(tokenId, {\n index: encodedIndex,\n asset: (assetMask >> encodedIndex) & 1n,\n optionRatio: index === 0 ? firstRatio : leg.optionRatio,\n isLong: 0n,\n tokenType: leg.tokenType,\n riskPartner: encodedIndex,\n strike: leg.strike,\n width: leg.width,\n })\n })\n return tokenId\n}\n\nfunction buildUniquePoke(\n sourceTokenId: bigint,\n occupied: Set<bigint>,\n): { tokenId: bigint; size: bigint } | undefined {\n const seenChunks = new Set<string>()\n const shortChunkLegs = decodeAllLegs(sourceTokenId).filter((leg) => {\n if (leg.isLong || leg.width === 0n) return false\n const chunkKey = `${leg.strike}:${leg.width}:${leg.tokenType}`\n if (seenChunks.has(chunkKey)) return false\n seenChunks.add(chunkKey)\n return true\n })\n if (shortChunkLegs.length === 0) return undefined\n\n const originalRatio = shortChunkLegs[0].optionRatio\n for (let ratioOffset = 0n; ratioOffset < 127n; ratioOffset += 1n) {\n const firstRatio = ((originalRatio - 1n + ratioOffset) % 127n) + 1n\n const assetVariants = 1n << BigInt(shortChunkLegs.length)\n for (let assetMask = 0n; assetMask < assetVariants; assetMask += 1n) {\n const tokenId = encodePokeToken(sourceTokenId, shortChunkLegs, firstRatio, assetMask)\n if (!occupied.has(tokenId)) {\n const size = minimumPokeSize(decodeAllLegs(tokenId), decodeTickSpacing(sourceTokenId))\n if (size !== undefined) return { tokenId, size }\n }\n }\n }\n\n throw new PanopticError('Unable to derive a collision-free protected settlement poke')\n}\n\n/**\n * Build `[poke, settle, poke]` for every target containing a width>0 short.\n * Pure-long and width-zero positions are settled directly.\n */\nexport function buildProtectedSettlePlan(\n params: BuildProtectedSettleDispatchParams,\n): ProtectedSettlePlan {\n const {\n positionIdList,\n finalPositionIdList,\n positionSizes,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n } = params\n if (positionIdList.length !== positionSizes.length) {\n throw new PanopticError('Protected settlement: positionSizes length must match positionIdList')\n }\n\n const occupied = new Set(finalPositionIdList)\n const actionIds: bigint[] = []\n const actionSizes: bigint[] = []\n const actionLimits: (readonly [bigint, bigint, bigint])[] = []\n const collectionIds: bigint[] = []\n const collectionSizes: bigint[] = []\n const collectionLimits: (readonly [bigint, bigint, bigint])[] = []\n const pokingTokenIds: bigint[] = []\n\n positionIdList.forEach((tokenId, index) => {\n const poke = buildUniquePoke(tokenId, occupied)\n if (poke === undefined) {\n actionIds.push(tokenId)\n actionSizes.push(positionSizes[index])\n actionLimits.push(SETTLE_LIMITS)\n return\n }\n\n occupied.add(poke.tokenId)\n pokingTokenIds.push(poke.tokenId)\n actionIds.push(poke.tokenId, tokenId, poke.tokenId)\n actionSizes.push(poke.size, positionSizes[index], 0n)\n actionLimits.push(SETTLE_LIMITS, SETTLE_LIMITS, SETTLE_LIMITS)\n collectionIds.push(poke.tokenId, poke.tokenId)\n collectionSizes.push(poke.size, 0n)\n collectionLimits.push(SETTLE_LIMITS, SETTLE_LIMITS)\n })\n\n const base = { finalPositionIdList: [...finalPositionIdList], usePremiaAsCollateral, builderCode }\n return {\n dispatch: {\n ...base,\n positionIdList: actionIds,\n positionSizes: actionSizes,\n tickAndSpreadLimits: actionLimits,\n },\n collectionDispatch:\n collectionIds.length === 0\n ? undefined\n : {\n ...base,\n positionIdList: collectionIds,\n positionSizes: collectionSizes,\n tickAndSpreadLimits: collectionLimits,\n },\n pokingTokenIds,\n }\n}\n\n/**\n * Build the atomic self-settlement dispatch that temporarily pokes each\n * affected short chunk before settling its source position.\n *\n * @param params - Positions, current sizes, and complete held-position list.\n * @returns A dispatch intent ready for simulation or submission.\n */\nexport function buildProtectedSettleDispatch(\n params: BuildProtectedSettleDispatchParams,\n): DispatchIntent {\n return buildProtectedSettlePlan(params).dispatch\n}\n","/**\n * Read current on-chain positionSize for a list of tokenIds.\n *\n * PanopticPool.dispatch() treats `positionSizes[i] == storedSize` as a\n * settlePremium self-call and any mismatch (including 0) as a burn. Callers\n * that want to trigger settle without changing size must pass the CURRENT\n * stored size for each held tokenId — hence this helper.\n *\n * @module v2/reads/positionSizes\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\n\nconst BIT_MASK_128 = (1n << 128n) - 1n\n\nexport interface GetCurrentPositionSizesParams {\n client: PublicClient\n poolAddress: Address\n account: Address\n positionIdList: bigint[]\n blockNumber?: bigint\n}\n\n/**\n * Returns the current stored positionSize for each tokenId, in the same order\n * as the input `positionIdList`. Reverts (via the contract) if any tokenId is\n * not held by `account`.\n */\nexport async function getCurrentPositionSizes(\n params: GetCurrentPositionSizesParams,\n): Promise<bigint[]> {\n const { client, poolAddress, account, positionIdList, blockNumber } = params\n\n if (positionIdList.length === 0) return []\n\n const [, , positionBalances] = await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, positionIdList],\n blockNumber,\n })\n\n return positionBalances.map((packed) => packed & BIT_MASK_128)\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 /** Defaults to true. False returns the existing 0n (unavailable) gas sentinel. */\n estimateGas?: boolean\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 if (params.estimateGas !== false) {\n gasEstimate = await client.estimateGas({\n account: user,\n to: poolAddress,\n data: callData,\n blockNumber,\n })\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","/** Fee-protected premium settlement simulation. @module v2/simulations/simulateSettle */\n\nimport type { Address, Hex, PublicClient } from 'viem'\nimport { decodeFunctionResult, encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError, UnsafePremiumSettlementError } from '../errors'\nimport { getCurrentPositionSizes } from '../reads/positionSizes'\nimport { getForfeitablePremium } from '../reads/premia'\nimport type { SettleSimulation, SimulationResult, TokenFlow } from '../types'\nimport { buildProtectedSettlePlan } from '../writes/protectedSettle'\nimport type { SettleSequenceTarget } from '../writes/settleSequence'\nimport { buildSettleSequenceCalls } from '../writes/settleSequence'\nimport { simulateSettlePremiumBatch } from './simulateSettlePremiumBatch'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\nconst BIT_MASK_128 = (1n << 128n) - 1n\nconst multicallAbi = [\n {\n type: 'function',\n name: 'multicall',\n inputs: [{ name: 'data', type: 'bytes[]' }],\n outputs: [{ name: 'results', type: 'bytes[]' }],\n stateMutability: 'nonpayable',\n },\n] as const\n\nexport interface SimulateSettleParams {\n client: PublicClient\n poolAddress: Address\n account: Address\n positionIdList: bigint[]\n finalPositionIdList?: bigint[]\n positionSizes?: bigint[]\n /** Buyers holding longs against the short chunks being settled. */\n targets?: SettleSequenceTarget[]\n usePremiaAsCollateral?: boolean\n builderCode?: bigint\n /**\n * Allow settlement when premium remains but no buyer settlement or chunk\n * poke can collect it (for example, width-zero legs). Avoidable forfeiture\n * still fails closed. Default false.\n */\n allowForfeit?: boolean\n blockNumber?: bigint\n}\n\nfunction encodeDispatch(plan: ReturnType<typeof buildProtectedSettlePlan>): Hex {\n const dispatch = plan.dispatch\n return encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n dispatch.positionIdList,\n dispatch.finalPositionIdList,\n dispatch.positionSizes,\n dispatch.tickAndSpreadLimits.map(\n (limits) =>\n [Number(limits[0]), Number(limits[1]), Number(limits[2])] as readonly [\n number,\n number,\n number,\n ],\n ),\n dispatch.usePremiaAsCollateral,\n dispatch.builderCode,\n ],\n })\n}\n\nfunction decodeShortPremium(data: Hex): readonly [bigint, bigint] {\n const packed = decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n data,\n })[0]\n return [packed & BIT_MASK_128, packed >> 128n]\n}\n\nasync function remainingForfeitAfterProtection(params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n positionIdList: bigint[]\n finalPositionIdList: bigint[]\n targets: SettleSequenceTarget[]\n plan: ReturnType<typeof buildProtectedSettlePlan>\n blockNumber: bigint\n initial: readonly [bigint, bigint]\n}): Promise<[bigint, bigint]> {\n const { client, poolAddress, account, positionIdList, targets, plan, blockNumber, initial } =\n params\n if (targets.length === 0 && plan.collectionDispatch === undefined) return [...initial]\n\n const protectionCalls = buildSettleSequenceCalls({\n positionIdListFrom: params.finalPositionIdList,\n targets,\n dispatch: plan.collectionDispatch,\n })\n const availableCall = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, positionIdList],\n })\n const totalCall = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, true, positionIdList],\n })\n const { result } = await client.simulateContract({\n address: poolAddress,\n abi: multicallAbi,\n functionName: 'multicall',\n args: [[...protectionCalls, availableCall, totalCall]],\n account,\n blockNumber,\n })\n const available = decodeShortPremium(result[result.length - 2])\n const total = decodeShortPremium(result[result.length - 1])\n return [\n total[0] > available[0] ? total[0] - available[0] : 0n,\n total[1] > available[1] ? total[1] - available[1] : 0n,\n ]\n}\n\nexport async function simulateSettle(\n params: SimulateSettleParams,\n): Promise<SimulationResult<SettleSimulation>> {\n const {\n client,\n poolAddress,\n account,\n positionIdList,\n finalPositionIdList = positionIdList,\n positionSizes: providedSizes,\n targets = [],\n usePremiaAsCollateral = false,\n builderCode = 0n,\n allowForfeit = false,\n blockNumber,\n } = params\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n try {\n if (providedSizes && providedSizes.length !== positionIdList.length) {\n throw new PanopticError('simulateSettle: positionSizes length must match positionIdList')\n }\n const positionSizes =\n providedSizes ??\n (await getCurrentPositionSizes({\n client,\n poolAddress,\n account,\n positionIdList,\n blockNumber: targetBlockNumber,\n }))\n const plan = buildProtectedSettlePlan({\n positionIdList,\n finalPositionIdList,\n positionSizes,\n usePremiaAsCollateral,\n builderCode,\n })\n const initialForfeit = await getForfeitablePremium({\n client,\n poolAddress,\n account,\n tokenIds: positionIdList,\n blockNumber: targetBlockNumber,\n })\n const initial: [bigint, bigint] = [initialForfeit.forfeit0, initialForfeit.forfeit1]\n\n if (targets.length > 0) {\n const buyers = await simulateSettlePremiumBatch({\n client,\n poolAddress,\n account,\n positionIdListFrom: finalPositionIdList,\n targets,\n blockNumber: targetBlockNumber,\n })\n if (buyers.unsettleableCount > 0) {\n throw new UnsafePremiumSettlementError(initial, buyers.unsettleableCount)\n }\n }\n\n const remainingForfeit = await remainingForfeitAfterProtection({\n client,\n poolAddress,\n account,\n positionIdList,\n finalPositionIdList,\n targets,\n plan,\n blockNumber: targetBlockNumber,\n initial,\n })\n if ((remainingForfeit[0] > 0n || remainingForfeit[1] > 0n) && !allowForfeit) {\n throw new UnsafePremiumSettlementError(remainingForfeit, 0)\n }\n\n const callData =\n targets.length === 0\n ? encodeDispatch(plan)\n : encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'multicall',\n args: [\n buildSettleSequenceCalls({\n positionIdListFrom: finalPositionIdList,\n targets,\n dispatch: plan.dispatch,\n }),\n ],\n })\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account,\n callData,\n blockNumber: targetBlockNumber,\n })\n if (!flowResult.success || !flowResult.tokenFlow) {\n throw flowResult.rawError ?? new PanopticError(flowResult.error || 'Simulation failed')\n }\n\n const tokenFlow: TokenFlow = flowResult.tokenFlow\n return {\n success: true,\n data: {\n premiaReceived0: tokenFlow.delta0,\n premiaReceived1: tokenFlow.delta1,\n postCollateral0: tokenFlow.balanceAfter0,\n postCollateral1: tokenFlow.balanceAfter1,\n premiumProtected: [initial[0] - remainingForfeit[0], initial[1] - remainingForfeit[1]],\n remainingForfeit,\n usesPoke: plan.pokingTokenIds.length > 0,\n settledBuyerCount: targets.length,\n },\n gasEstimate: flowResult.gasEstimate,\n tokenFlow,\n _meta: await metaPromise,\n }\n } catch (error) {\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: await metaPromise,\n }\n }\n}\n","/**\n * Minimal Permit2 ABI (`IAllowanceTransfer` subset: `approve` + `allowance`).\n * @module uniswap/v4/abis/permit2\n */\n\nexport const permit2Abi = [\n {\n type: 'function',\n name: 'approve',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'token', type: 'address' },\n { name: 'spender', type: 'address' },\n { name: 'amount', type: 'uint160' },\n { name: 'expiration', type: 'uint48' },\n ],\n outputs: [],\n },\n {\n type: 'function',\n name: 'allowance',\n stateMutability: 'view',\n inputs: [\n { name: 'user', type: 'address' },\n { name: 'token', type: 'address' },\n { name: 'spender', type: 'address' },\n ],\n outputs: [\n { name: 'amount', type: 'uint160' },\n { name: 'expiration', type: 'uint48' },\n { name: 'nonce', type: 'uint48' },\n ],\n },\n] as const\n","/**\n * Permit2 approval helpers for the Universal Router ERC20 input side.\n *\n * Two-step on-chain flow (only when `tokenIn` is an ERC20):\n * 1. ERC20 `approve(Permit2, amount)` — lets Permit2 pull the token.\n * 2. `Permit2.approve(token, universalRouter, amount, expiration)` — lets the\n * router spend via Permit2.\n *\n * Native ETH skips both steps.\n *\n * @module uniswap/v4/router/permit2\n */\n\nimport { erc20Abi, maxUint256 } from 'viem'\n\nimport { getBlockMeta } from '../../../panoptic/v2/clients'\nimport type { TxReceipt, TxResult } from '../../../panoptic/v2/types'\nimport { submitWrite } from '../../../panoptic/v2/writes'\nimport { permit2Abi } from '../abis/permit2'\nimport { getUniswapV4Addresses } from '../addresses'\nimport type {\n ApproveErc20ForPermit2Params,\n ApproveRouterViaPermit2Params,\n CheckRouterApprovalParams,\n RouterApprovalStatus,\n} from './types'\n\n/** uint160 max — the largest Permit2 allowance amount. */\nconst UINT160_MAX = (1n << 160n) - 1n\n/** Default Permit2 allowance expiration window (30 days). */\nconst DEFAULT_EXPIRATION_SECONDS = 2_592_000n\n/** uint48 max — the largest Permit2 expiration. */\nconst UINT48_MAX = (1n << 48n) - 1n\n\n/**\n * Check whether the ERC20 → Permit2 → Universal Router allowance chain is\n * sufficient for an exact-in swap of `amount`.\n */\nexport async function checkRouterApproval(\n params: CheckRouterApprovalParams,\n): Promise<RouterApprovalStatus> {\n const { client, chainId, tokenIn, owner, amount, addresses } = params\n const { permit2, universalRouter } = getUniswapV4Addresses(chainId, addresses)\n\n const [erc20Allowance, permit2Allowance, blockMeta] = await Promise.all([\n client.readContract({\n address: tokenIn,\n abi: erc20Abi,\n functionName: 'allowance',\n args: [owner, permit2],\n }),\n client.readContract({\n address: permit2,\n abi: permit2Abi,\n functionName: 'allowance',\n args: [owner, tokenIn, universalRouter],\n }),\n getBlockMeta({ client }),\n ])\n\n const [permit2Amount, permit2Expiration] = permit2Allowance\n\n const needsErc20Approval = erc20Allowance < amount\n const needsPermit2Approval =\n permit2Amount < amount || BigInt(permit2Expiration) <= blockMeta.blockTimestamp\n\n return {\n needsErc20Approval,\n needsPermit2Approval,\n erc20Allowance,\n permit2Amount,\n permit2Expiration: BigInt(permit2Expiration),\n }\n}\n\n/**\n * Step 1: approve the ERC20 token to Permit2 (defaults to unlimited).\n */\nexport async function approveErc20ForPermit2(\n params: ApproveErc20ForPermit2Params,\n): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n chainId,\n tokenIn,\n amount = maxUint256,\n txOverrides,\n addresses,\n } = params\n const { permit2 } = getUniswapV4Addresses(chainId, addresses)\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: tokenIn,\n abi: erc20Abi,\n functionName: 'approve',\n args: [permit2, amount],\n txOverrides,\n })\n}\n\n/**\n * Step 1 (and wait): approve the ERC20 token to Permit2.\n */\nexport async function approveErc20ForPermit2AndWait(\n params: ApproveErc20ForPermit2Params,\n): Promise<TxReceipt> {\n const result = await approveErc20ForPermit2(params)\n return result.wait()\n}\n\n/**\n * Step 2: approve the Universal Router as a Permit2 spender for the token.\n */\nexport async function approveRouterViaPermit2(\n params: ApproveRouterViaPermit2Params,\n): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n chainId,\n tokenIn,\n amount = UINT160_MAX,\n expiration,\n txOverrides,\n addresses,\n } = params\n const { permit2, universalRouter } = getUniswapV4Addresses(chainId, addresses)\n\n const resolvedExpiration =\n expiration ?? (await getBlockMeta({ client })).blockTimestamp + DEFAULT_EXPIRATION_SECONDS\n const cappedExpiration = resolvedExpiration > UINT48_MAX ? UINT48_MAX : resolvedExpiration\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: permit2,\n abi: permit2Abi,\n functionName: 'approve',\n args: [tokenIn, universalRouter, amount, cappedExpiration],\n txOverrides,\n })\n}\n\n/**\n * Step 2 (and wait): approve the Universal Router via Permit2.\n */\nexport async function approveRouterViaPermit2AndWait(\n params: ApproveRouterViaPermit2Params,\n): Promise<TxReceipt> {\n const result = await approveRouterViaPermit2(params)\n return result.wait()\n}\n","/**\n * Minimal V4Quoter ABI (`quoteExactInputSingle`, `quoteExactOutputSingle`).\n *\n * Note: neither function is `view` — they mutate state internally and are\n * intended to be called via `eth_call` / viem `simulateContract`, never\n * `readContract`.\n *\n * @module uniswap/v4/abis/v4Quoter\n */\n\nconst quoteExactSingleParams = {\n name: 'params',\n type: 'tuple',\n components: [\n {\n name: 'poolKey',\n type: 'tuple',\n components: [\n { name: 'currency0', type: 'address' },\n { name: 'currency1', type: 'address' },\n { name: 'fee', type: 'uint24' },\n { name: 'tickSpacing', type: 'int24' },\n { name: 'hooks', type: 'address' },\n ],\n },\n { name: 'zeroForOne', type: 'bool' },\n { name: 'exactAmount', type: 'uint128' },\n { name: 'hookData', type: 'bytes' },\n ],\n} as const\n\nexport const v4QuoterAbi = [\n {\n type: 'function',\n name: 'quoteExactInputSingle',\n stateMutability: 'nonpayable',\n inputs: [quoteExactSingleParams],\n outputs: [\n { name: 'amountOut', type: 'uint256' },\n { name: 'gasEstimate', type: 'uint256' },\n ],\n },\n {\n type: 'function',\n name: 'quoteExactOutputSingle',\n stateMutability: 'nonpayable',\n inputs: [quoteExactSingleParams],\n outputs: [\n { name: 'amountIn', type: 'uint256' },\n { name: 'gasEstimate', type: 'uint256' },\n ],\n },\n] as const\n","/**\n * Resolve the Uniswap v4 PoolKey + swap direction from a PanopticPool address.\n * @module uniswap/v4/router/resolvePoolKey\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { isAddressEqual } from 'viem'\n\nimport { getPool } from '../../../panoptic/v2/reads/pool'\nimport type { PoolKey } from '../../../panoptic/v2/types'\nimport { InvalidSwapTokenError } from './errors'\n\n/**\n * Resolved swap routing info for a given `tokenIn`.\n */\nexport interface ResolvedSwapRoute {\n /** Underlying v4 PoolKey. */\n poolKey: PoolKey\n /** Whether the swap goes currency0 → currency1. */\n zeroForOne: boolean\n /** Output token address. */\n tokenOut: Address\n /** Decimals of the output token. */\n tokenOutDecimals: bigint\n /** Symbol of the output token. */\n tokenOutSymbol: string\n}\n\n/**\n * Parameters for {@link resolveSwapRoute}.\n */\nexport interface ResolveSwapRouteParams {\n client: PublicClient\n poolAddress: Address\n chainId: bigint\n tokenIn: Address\n blockNumber?: bigint\n}\n\n/**\n * Resolve the PoolKey, swap direction, and output token metadata for a swap.\n *\n * @throws {InvalidSwapTokenError} when `tokenIn` is not part of the pool.\n */\nexport async function resolveSwapRoute(params: ResolveSwapRouteParams): Promise<ResolvedSwapRoute> {\n const { client, poolAddress, chainId, tokenIn, blockNumber } = params\n\n const pool = await getPool({ client, poolAddress, chainId, blockNumber })\n const { poolKey } = pool\n\n const isCurrency0 = isAddressEqual(tokenIn, poolKey.currency0)\n const isCurrency1 = isAddressEqual(tokenIn, poolKey.currency1)\n if (!isCurrency0 && !isCurrency1) {\n throw new InvalidSwapTokenError(tokenIn, poolKey.currency0, poolKey.currency1)\n }\n\n const zeroForOne = isCurrency0\n const tokenOut = zeroForOne ? poolKey.currency1 : poolKey.currency0\n const outTracker = zeroForOne ? pool.collateralTracker1 : pool.collateralTracker0\n\n return {\n poolKey,\n zeroForOne,\n tokenOut,\n tokenOutDecimals: outTracker.decimals,\n tokenOutSymbol: outTracker.symbol,\n }\n}\n","/**\n * Quote exact-in and exact-out swaps via the Uniswap v4 V4Quoter.\n * @module uniswap/v4/router/quote\n */\n\nimport { zeroAddress } from 'viem'\n\nimport { getBlockMeta } from '../../../panoptic/v2/clients'\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport type { SimulationResult } from '../../../panoptic/v2/types'\nimport { v4QuoterAbi } from '../abis/v4Quoter'\nimport { getUniswapV4Addresses } from '../addresses'\nimport { QuoterUnavailableError } from './errors'\nimport { resolveSwapRoute } from './resolvePoolKey'\nimport type {\n QuoteSwapExactInViaRouterParams,\n QuoteSwapExactOutViaRouterParams,\n SwapExactInQuote,\n SwapExactOutQuote,\n} from './types'\n\nconst BPS_DENOMINATOR = 10_000n\nconst UINT128_MAX = (1n << 128n) - 1n\n\n/** Reject out-of-range slippage so the min/max amount math can't underflow/overflow. */\nfunction assertSlippageBps(slippageBps: bigint): void {\n if (slippageBps < 0n || slippageBps > BPS_DENOMINATOR) {\n throw new PanopticError(`invalid slippageBps ${slippageBps}, must be 0..10000`)\n }\n}\n\nconst FALLBACK_META = {\n blockNumber: 0n,\n blockTimestamp: 0n,\n blockHash: '0x0' as `0x${string}`,\n}\n\n/**\n * Quote an exact-in spot swap against the underlying Uniswap v4 pool.\n *\n * Uses the V4Quoter `quoteExactInputSingle` via `eth_call` (the quoter is\n * state-mutating / revert-based, so it must be simulated, not read). Returns a\n * `SimulationResult` so failures carry a structured error rather than throwing.\n */\nexport async function quoteSwapExactInViaRouter(\n params: QuoteSwapExactInViaRouterParams,\n): Promise<SimulationResult<SwapExactInQuote>> {\n const { client, poolAddress, chainId, tokenIn, amountIn, slippageBps, blockNumber, addresses } =\n params\n\n try {\n if (amountIn < 0n || amountIn > UINT128_MAX) {\n throw new PanopticError(`amountIn ${amountIn} exceeds uint128 maximum`)\n }\n assertSlippageBps(slippageBps)\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n const { v4Quoter } = getUniswapV4Addresses(chainId, addresses)\n if (v4Quoter === zeroAddress) {\n throw new QuoterUnavailableError(chainId)\n }\n\n const route = await resolveSwapRoute({\n client,\n poolAddress,\n chainId,\n tokenIn,\n blockNumber: targetBlockNumber,\n })\n\n const { result } = await client.simulateContract({\n address: v4Quoter,\n abi: v4QuoterAbi,\n functionName: 'quoteExactInputSingle',\n blockNumber: targetBlockNumber,\n args: [\n {\n poolKey: {\n currency0: route.poolKey.currency0,\n currency1: route.poolKey.currency1,\n fee: Number(route.poolKey.fee),\n tickSpacing: Number(route.poolKey.tickSpacing),\n hooks: route.poolKey.hooks,\n },\n zeroForOne: route.zeroForOne,\n exactAmount: amountIn,\n hookData: '0x',\n },\n ],\n })\n\n const [amountOut, gasEstimate] = result\n const amountOutMinimum = (amountOut * (BPS_DENOMINATOR - slippageBps)) / BPS_DENOMINATOR\n\n const _meta = await metaPromise\n\n return {\n success: true,\n data: {\n amountOut,\n amountOutMinimum,\n zeroForOne: route.zeroForOne,\n tokenOut: route.tokenOut,\n poolKey: route.poolKey,\n gasEstimate,\n },\n gasEstimate,\n _meta,\n }\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Quote failed',\n error instanceof Error ? error : undefined,\n ),\n _meta: FALLBACK_META,\n }\n }\n}\n\n/**\n * Quote an exact-out spot swap against the underlying Uniswap v4 pool.\n *\n * Uses the V4Quoter `quoteExactOutputSingle` via `eth_call` (the quoter is\n * state-mutating / revert-based, so it must be simulated, not read). Returns a\n * `SimulationResult` so failures carry a structured error rather than throwing.\n */\nexport async function quoteSwapExactOutViaRouter(\n params: QuoteSwapExactOutViaRouterParams,\n): Promise<SimulationResult<SwapExactOutQuote>> {\n const { client, poolAddress, chainId, tokenIn, amountOut, slippageBps, blockNumber, addresses } =\n params\n\n try {\n if (amountOut < 0n || amountOut > UINT128_MAX) {\n throw new PanopticError(`amountOut ${amountOut} exceeds uint128 maximum`)\n }\n assertSlippageBps(slippageBps)\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n const { v4Quoter } = getUniswapV4Addresses(chainId, addresses)\n if (v4Quoter === zeroAddress) {\n throw new QuoterUnavailableError(chainId)\n }\n\n const route = await resolveSwapRoute({\n client,\n poolAddress,\n chainId,\n tokenIn,\n blockNumber: targetBlockNumber,\n })\n\n const { result } = await client.simulateContract({\n address: v4Quoter,\n abi: v4QuoterAbi,\n functionName: 'quoteExactOutputSingle',\n blockNumber: targetBlockNumber,\n args: [\n {\n poolKey: {\n currency0: route.poolKey.currency0,\n currency1: route.poolKey.currency1,\n fee: Number(route.poolKey.fee),\n tickSpacing: Number(route.poolKey.tickSpacing),\n hooks: route.poolKey.hooks,\n },\n zeroForOne: route.zeroForOne,\n exactAmount: amountOut,\n hookData: '0x',\n },\n ],\n })\n\n const [amountIn, gasEstimate] = result\n // Ceiling division: never round the input cap down (would tighten the buffer).\n const amountInMaximum =\n (amountIn * (BPS_DENOMINATOR + slippageBps) + BPS_DENOMINATOR - 1n) / BPS_DENOMINATOR\n\n const _meta = await metaPromise\n\n return {\n success: true,\n data: {\n amountIn,\n amountInMaximum,\n zeroForOne: route.zeroForOne,\n tokenOut: route.tokenOut,\n poolKey: route.poolKey,\n gasEstimate,\n },\n gasEstimate,\n _meta,\n }\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Quote failed',\n error instanceof Error ? error : undefined,\n ),\n _meta: FALLBACK_META,\n }\n }\n}\n","/**\n * Quote an exact-in single-hop v4 swap for an EXPLICIT PoolKey (as opposed to\n * `quoteSwapExactInViaRouter`, which resolves the pool from a PanopticPool\n * address). Used to rank an arbitrary whitelist of hedge pools.\n * @module uniswap/v4/router/quoteByPoolKey\n */\n\nimport type { PublicClient } from 'viem'\nimport { BaseError, ContractFunctionRevertedError } from 'viem'\n\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport type { PoolKey } from '../../../panoptic/v2/types'\nimport { v4QuoterAbi } from '../abis/v4Quoter'\nimport { type UniswapV4Addresses, getUniswapV4Addresses } from '../addresses'\n\nconst BPS_DENOMINATOR = 10_000n\nconst UINT128_MAX = (1n << 128n) - 1n\n\nexport interface QuoteV4ExactInByPoolKeyParams {\n client: PublicClient\n chainId: bigint\n poolKey: PoolKey\n zeroForOne: boolean\n amountIn: bigint\n slippageBps: bigint\n blockNumber?: bigint\n addresses?: Partial<UniswapV4Addresses>\n}\n\nexport interface V4ExactInQuote {\n amountOut: bigint\n amountOutMinimum: bigint\n gasEstimate: bigint\n}\n\n/**\n * Quote an exact-in v4 swap for a specific PoolKey. Returns `null` when the\n * quote reverts (pool missing / no liquidity) so callers can skip that pool when\n * ranking venues rather than aborting the cycle.\n */\nexport async function quoteV4ExactInByPoolKey(\n params: QuoteV4ExactInByPoolKeyParams,\n): Promise<V4ExactInQuote | null> {\n const { client, chainId, poolKey, zeroForOne, amountIn, slippageBps, blockNumber } = params\n if (amountIn < 0n || amountIn > UINT128_MAX) {\n throw new PanopticError(`amountIn ${amountIn} exceeds uint128 maximum`)\n }\n if (slippageBps < 0n || slippageBps > BPS_DENOMINATOR) {\n throw new PanopticError(`invalid slippageBps ${slippageBps}, must be 0..10000`)\n }\n\n const { v4Quoter } = getUniswapV4Addresses(chainId, params.addresses)\n\n try {\n const { result } = await client.simulateContract({\n address: v4Quoter,\n abi: v4QuoterAbi,\n functionName: 'quoteExactInputSingle',\n blockNumber,\n args: [\n {\n poolKey: {\n currency0: poolKey.currency0,\n currency1: poolKey.currency1,\n fee: Number(poolKey.fee),\n tickSpacing: Number(poolKey.tickSpacing),\n hooks: poolKey.hooks,\n },\n zeroForOne,\n exactAmount: amountIn,\n hookData: '0x',\n },\n ],\n })\n const [amountOut, gasEstimate] = result\n const amountOutMinimum = (amountOut * (BPS_DENOMINATOR - slippageBps)) / BPS_DENOMINATOR\n return { amountOut, amountOutMinimum, gasEstimate }\n } catch (err) {\n if (isRevert(err)) return null\n // Transport/RPC/timeout errors are NOT \"no liquidity\" — rethrow so routing\n // doesn't silently treat an unreachable node as an empty pool.\n throw err\n }\n}\n\n/** True only for genuine contract reverts (missing pool / no liquidity). */\nfunction isRevert(err: unknown): boolean {\n return (\n err instanceof BaseError &&\n err.walk((e) => e instanceof ContractFunctionRevertedError) instanceof\n ContractFunctionRevertedError\n )\n}\n","/**\n * Exact-in and exact-out spot swaps via the Uniswap v4 Universal Router.\n *\n * Swaps directly on the underlying Uniswap v4 pool, bypassing Panoptic (no SFPM,\n * no Panoptic LP fees, no pool collateral required). Native ETH (`address(0)`)\n * is supported via `msg.value` with no Permit2 approval.\n *\n * @module uniswap/v4/router/swap\n */\n\nimport { isAddressEqual } from 'viem'\n\nimport { getBlockMeta } from '../../../panoptic/v2/clients'\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport type { TxReceipt, TxResult } from '../../../panoptic/v2/types'\nimport { submitWrite } from '../../../panoptic/v2/writes'\nimport { universalRouterAbi } from '../abis/universalRouter'\nimport { getUniswapV4Addresses } from '../addresses'\nimport { buildV4ExactOutSwapExecuteArgs, buildV4SwapExecuteArgs } from './encodeSwap'\nimport { quoteSwapExactInViaRouter, quoteSwapExactOutViaRouter } from './quote'\nimport type { SwapExactInViaRouterParams, SwapExactOutViaRouterParams } from './types'\n\n/** Default swap deadline window (30 minutes) when no deadline is provided. */\nconst DEFAULT_DEADLINE_SECONDS = 1800n\n\n/**\n * Execute an exact-in spot swap via the Universal Router.\n *\n * @param params - Swap parameters.\n * @returns TxResult with hash + wait().\n *\n * @example\n * ```typescript\n * const result = await swapExactInViaRouter({\n * client, walletClient, account, poolAddress,\n * chainId: 1n,\n * tokenIn: ZERO_ADDRESS, // native ETH\n * amountIn: 10n ** 17n, // 0.1 ETH\n * slippageBps: 50n, // 0.5%\n * })\n * await result.wait()\n * ```\n */\nexport async function swapExactInViaRouter(params: SwapExactInViaRouterParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n tokenIn,\n amountIn,\n slippageBps,\n deadline,\n recipient,\n txOverrides,\n addresses,\n } = params\n\n if (recipient !== undefined && !isAddressEqual(recipient, account)) {\n // The Universal Router pays the configured router recipient; routing output\n // to an arbitrary recipient requires an extra action not wired in v1.\n throw new PanopticError('Custom recipient is not supported yet; output goes to the sender')\n }\n\n const resolved = getUniswapV4Addresses(chainId, addresses)\n\n const quote = await quoteSwapExactInViaRouter({\n client,\n poolAddress,\n chainId,\n tokenIn,\n amountIn,\n slippageBps,\n addresses,\n })\n\n if (!quote.success) {\n throw quote.error\n }\n\n const resolvedDeadline =\n deadline ?? (await getBlockMeta({ client })).blockTimestamp + DEFAULT_DEADLINE_SECONDS\n\n if (!quote.data.poolKey) {\n throw new PanopticError('v4 swap requires a poolKey from the quote')\n }\n\n const { args, value } = buildV4SwapExecuteArgs({\n poolKey: quote.data.poolKey,\n zeroForOne: quote.data.zeroForOne,\n amountIn,\n amountOutMinimum: quote.data.amountOutMinimum,\n tokenIn,\n tokenOut: quote.data.tokenOut,\n deadline: resolvedDeadline,\n recipient: account,\n })\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: resolved.universalRouter,\n abi: universalRouterAbi,\n functionName: 'execute',\n args,\n value,\n txOverrides,\n })\n}\n\n/**\n * Execute an exact-in swap via the Universal Router and wait for confirmation.\n */\nexport async function swapExactInViaRouterAndWait(\n params: SwapExactInViaRouterParams,\n): Promise<TxReceipt> {\n const result = await swapExactInViaRouter(params)\n return result.wait()\n}\n\n/**\n * Execute an exact-out spot swap via the Universal Router.\n *\n * The caller specifies the exact `amountOut` to receive; the input (pay) amount\n * is quoted and capped at `amountInMaximum`. For native-ETH input the router is\n * funded with `amountInMaximum` and the unused surplus is swept back to the\n * sender.\n *\n * @param params - Swap parameters.\n * @returns TxResult with hash + wait().\n */\nexport async function swapExactOutViaRouter(\n params: SwapExactOutViaRouterParams,\n): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n tokenIn,\n amountOut,\n slippageBps,\n deadline,\n recipient,\n txOverrides,\n addresses,\n } = params\n\n if (recipient !== undefined && !isAddressEqual(recipient, account)) {\n // The Universal Router pays the configured router recipient; routing output\n // to an arbitrary recipient requires an extra action not wired in v1.\n throw new PanopticError('Custom recipient is not supported yet; output goes to the sender')\n }\n\n const resolved = getUniswapV4Addresses(chainId, addresses)\n\n const quote = await quoteSwapExactOutViaRouter({\n client,\n poolAddress,\n chainId,\n tokenIn,\n amountOut,\n slippageBps,\n addresses,\n })\n\n if (!quote.success) {\n throw quote.error\n }\n\n const resolvedDeadline =\n deadline ?? (await getBlockMeta({ client })).blockTimestamp + DEFAULT_DEADLINE_SECONDS\n\n if (!quote.data.poolKey) {\n throw new PanopticError('v4 swap requires a poolKey from the quote')\n }\n\n const { args, value } = buildV4ExactOutSwapExecuteArgs({\n poolKey: quote.data.poolKey,\n zeroForOne: quote.data.zeroForOne,\n amountOut,\n amountInMaximum: quote.data.amountInMaximum,\n tokenIn,\n tokenOut: quote.data.tokenOut,\n deadline: resolvedDeadline,\n recipient: account,\n })\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: resolved.universalRouter,\n abi: universalRouterAbi,\n functionName: 'execute',\n args,\n value,\n txOverrides,\n })\n}\n\n/**\n * Execute an exact-out swap via the Universal Router and wait for confirmation.\n */\nexport async function swapExactOutViaRouterAndWait(\n params: SwapExactOutViaRouterParams,\n): Promise<TxReceipt> {\n const result = await swapExactOutViaRouter(params)\n return result.wait()\n}\n"],"mappings":"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;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IAAE,MAAM;IAAQ,cAAc;IAAW,MAAM;IAAW,SAAS;GAAM;GACzE;IAAE,MAAM;IAAM,cAAc;IAA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AM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IAAE,MAAM;IAAQ,cAAc;IAAW,MAAM;IAAW,SAAS;GAAM;GACzE;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IAAE,MAAM;IAAQ,cAAc;IAAW,MAAM;IAAW,SAAS;GAAM;GACzE;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,QAAQ,CACN;GAAE,MAAM;GAAW,cAAc;GAAW,MAAM;EAAW,GAC7D;GAAE,MAAM;GAAiB,cAAc;GAAW,MAAM;EAAW,CACpE;EACD,MAAM;CACP;CACD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAsB;CACzD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAgB;CACnD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAoB;CACvD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAoC;CACvE;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAiB;CACpD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAe;CAClD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAoB;CACvD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAoB;CACvD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAoB;CACvD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAqB;CACxD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAe;CAClD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAmB;CACtD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAoB;CACvD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAuB;CAC1D;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAc;CACjD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAe;CAClD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAsB;CACzD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAmB;CACtD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAiB;CACpD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAe;AACnD;AAqXD,MAAa,gBAAgB;CAC3B;EACE,MAAM;EACN,QAAQ;GACN;IAAE,MAAM;IAAiB,cAAc;IAAW,MAAM;GAAW;GACnE;IAAE,MAAM;IAAiB,cAAc;IAAW,MAAM;GAAW;GACnE;IAAE,MAAM;IAAa,cAAc;IAAW,MAAM;GAAW;GAC/D;IAAE,MAAM;IAAmB,cAAc;IAAW,MAAM;GAAW;EACtE;EACD,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CAAC;EACjE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CAAC;EACjE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CAAC;EACjE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CAAC;EACjE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CAAC;EACjE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CAAC;EACjE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CAAC;EACjE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CAAC;EACjE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CAAC;EACjE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAS,MAAM;EAAS,CAAC;EAC7D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CAAC;EACjE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CAAC;EACjE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CAAC;EACjE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CAAC;EACjE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAU,MAAM;EAAU,CAAC;EAC/D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAS,MAAM;EAAS,CAAC;EAC7D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CACN;GAAE,MAAM;GAAS,cAAc;GAAW,MAAM;EAAW,GAC3D;GAAE,MAAM;GAAa,cAAc;GAAW,MAAM;EAAW,CAChE;EACD,MAAM;EACN,SAAS,CAAE;EACX,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ;GACN;IAAE,MAAM;IAAS,cAAc;IAAW,MAAM;GAAW;GAC3D;IAAE,MAAM;IAAa,cAAc;IAAW,MAAM;GAAW;GAC/D;IAAE,MAAM;IAAU,cAAc;IAAW,MAAM;GAAW;EAC7D;EACD,MAAM;EACN,SAAS,CAAE;EACX,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CACN;GAAE,MAAM;GAAc,cAAc;GAAc,MAAM;EAAW,GACnE;GAAE,MAAM;GAAe,cAAc;GAAS,MAAM;EAAS,CAC9D;EACD,MAAM;EACN,SAAS,CACP;GAAE,MAAM;GAAc,cAAc;GAAS,MAAM;EAAS,GAC5D;GACE,MAAM;GACN,cAAc;GACd,MAAM;EACP,CACF;EACD,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CACN;GAAE,MAAM;GAAe,cAAc;GAAU,MAAM;EAAU,GAC/D;GAAE,MAAM;GAAe,cAAc;GAAW,MAAM;EAAW,CAClE;EACD,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CAAC;EACjE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ;GACN;IAAE,MAAM;IAAe,cAAc;IAAS,MAAM;GAAS;GAC7D;IAAE,MAAM;IAAc,cAAc;IAAS,MAAM;GAAS;GAC5D;IAAE,MAAM;IAAW,cAAc;IAAW,MAAM;GAAW;GAC7D;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;EACF;EACD,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAgB,cAAc;GAAmB,MAAM;EAAU,CAAC;EACpF,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAC;GAAE,MAAM;GAAe,cAAc;GAAW,MAAM;EAAW,CAAC;EAC3E,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAgB,cAAc;GAAW,MAAM;EAAW,CAAC;EAC7E,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IAAE,MAAM;IAAkB,cAAc;IAAW,MAAM;GAAW;GACpE;IAAE,MAAM;IAAW,cAAc;IAAmB,MAAM;GAAU;GACpE;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;EACF;EACD,MAAM;EACN,SAAS,CACP;GAAE,MAAM;GAAI,cAAc;GAAmB,MAAM;EAAU,GAC7D;GAAE,MAAM;GAAI,cAAc;GAAmB,MAAM;EAAU,CAC9D;EACD,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IAAE,MAAM;IAAU,cAAc;IAAS,MAAM;GAAS;GACxD;IAAE,MAAM;IAAQ,cAAc;IAAW,MAAM;GAAW;GAC1D;IAAE,MAAM;IAAkB,cAAc;IAAa,MAAM;GAAa;GACxE;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;EACF;EACD,MAAM;EACN,SAAS;GACP;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;EACF;EACD,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CACN;GAAE,MAAM;GAAe,cAAc;GAAS,MAAM;EAAS,GAC7D;GAAE,MAAM;GAAe,cAAc;GAAc,MAAM;EAAW,CACrE;EACD,MAAM;EACN,SAAS;GACP;IAAE,MAAM;IAAY,cAAc;IAAS,MAAM;GAAS;GAC1D;IAAE,MAAM;IAAc,cAAc;IAAS,MAAM;GAAS;GAC5D;IAAE,MAAM;IAAc,cAAc;IAAS,MAAM;GAAS;GAC5D;IAAE,MAAM;IAAc,cAAc;IAAc,MAAM;GAAW;EACpE;EACD,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IAAE,MAAM;IAAkB,cAAc;IAAa,MAAM;GAAa;GACxE;IAAE,MAAM;IAAU,cAAc;IAAS,MAAM;GAAS;EACzD;EACD,MAAM;EACN,SAAS,CACP;GACE,MAAM;GACN,cAAc;GACd,MAAM;EACP,CACF;EACD,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ;GACN;IAAE,MAAM;IAAS,cAAc;IAAW,MAAM;GAAW;GAC3D;IAAE,MAAM;IAAQ,cAAc;IAAmB,MAAM;GAAU;GACjE;IAAE,MAAM;IAAU,cAAc;IAAS,MAAM;GAAS;GACxD;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;EACF;EACD,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAmB,MAAM;EAAU,CAAC;EACxE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ;GACN;IAAE,MAAM;IAAe,cAAc;IAAS,MAAM;GAAS;GAC7D;IAAE,MAAM;IAAc,cAAc;IAAc,MAAM;GAAW;GACnE;IAAE,MAAM;IAAe,cAAc;IAAW,MAAM;GAAW;EAClE;EACD,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAkB,MAAM;EAAW,CAAC;EACxE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ;GACN;IAAE,MAAM;IAAe,cAAc;IAAS,MAAM;GAAS;GAC7D;IAAE,MAAM;IAAe,cAAc;IAAc,MAAM;GAAW;GACpE;IAAE,MAAM;IAAY,cAAc;IAAS,MAAM;GAAS;EAC3D;EACD,MAAM;EACN,SAAS,CACP;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,GACtD;GAAE,MAAM;GAAI,cAAc;GAAc,MAAM;EAAW,CAC1D;EACD,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ;GACN;IAAE,MAAM;IAAkB,cAAc;IAAa,MAAM;GAAa;GACxE;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IAAE,MAAM;IAAkB,cAAc;IAAW,MAAM;GAAW;EACrE;EACD,MAAM;EACN,SAAS;GACP;IAAE,MAAM;IAAe,cAAc;IAAmB,MAAM;GAAU;GACxE;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;EACF;EACD,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CACN;GAAE,MAAM;GAAe,cAAc;GAAW,MAAM;EAAW,GACjE;GACE,MAAM;GACN,cAAc;GACd,MAAM;EACP,CACF;EACD,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CAAC;EACjE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IAAE,MAAM;IAAkB,cAAc;IAAa,MAAM;GAAa;GACxE;IAAE,MAAM;IAAU,cAAc;IAAS,MAAM;GAAS;GACxD;IAAE,MAAM;IAAQ,cAAc;IAAW,MAAM;GAAW;GAC1D;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;GACP;GACD;IAAE,MAAM;IAAU,cAAc;IAAW,MAAM;GAAW;EAC7D;EACD,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAQ,MAAM;EAAQ,CAAC;EAC3D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CACN;GAAE,MAAM;GAAe,cAAc;GAAS,MAAM;EAAS,GAC7D;GAAE,MAAM;GAAc,cAAc;GAAc,MAAM;EAAW,CACpE;EACD,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAY,cAAc;GAAS,MAAM;EAAS,CAAC;EACrE,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CACN;GACE,MAAM;GACN,cAAc;GACd,MAAM;EACP,CACF;EACD,MAAM;EACN,SAAS,CAAE;EACX,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAC;GAAE,MAAM;GAAc,cAAc;GAAc,MAAM;EAAW,CAAC;EAC7E,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAS,MAAM;EAAS,CAAC;EAC7D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CACN;GACE,MAAM;GACN,cAAc;GACd,MAAM;EACP,CACF;EACD,MAAM;EACN,SAAS,CAAE;EACX,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CACN;GAAE,MAAM;GAAe,cAAc;GAAW,MAAM;EAAW,GACjE;GACE,MAAM;GACN,cAAc;GACd,MAAM;EACP,CACF;EACD,MAAM;EACN,SAAS,CACP;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,GACtD;GAAE,MAAM;GAAI,cAAc;GAAW,MAAM;EAAW,CACvD;EACD,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,MAAM;GAAI,cAAc;GAAS,MAAM;EAAS,CAAC;EAC7D,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ,CAAC;GAAE,MAAM;GAAY,cAAc;GAAQ,MAAM;GAAQ,SAAS;EAAO,CAAC;EAClF,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAA0B;CAC7D;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAgB;CACnD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAsB;CACzD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAe;CAClD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAkB;CACrD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAoB;CACvD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAe;CAClD;EACE,MAAM;EACN,QAAQ;GACN;IAAE,MAAM;IAAS,cAAc;IAAW,MAAM;GAAW;GAC3D;IAAE,MAAM;IAAQ,cAAc;IAAW,MAAM;GAAW;GAC1D;IAAE,MAAM;IAAU,cAAc;IAAW,MAAM;GAAW;GAC5D;IAAE,MAAM;IAAW,cAAc;IAAW,MAAM;GAAW;EAC9D;EACD,MAAM;CACP;CACD;EAAE,MAAM;EAAS,QAAQ,CAAE;EAAE,MAAM;CAAiB;AACrD;;;;;;;;;;;;;;;;;;;ACz4GD,MAAa,oBAAoB;CAE/B;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CACN;GAAE,MAAM;GAAW,MAAM;EAAW,GACpC;GAAE,MAAM;GAAiB,MAAM;EAAW,CAC3C;CACF;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAC;GAAE,MAAM;GAAiB,MAAM;EAAW,CAAC;CACrD;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ;GACN;IAAE,MAAM;IAAgB,MAAM;GAAW;GACzC;IAAE,MAAM;IAAmB,MAAM;GAAW;GAC5C;IAAE,MAAM;IAAgB,MAAM;GAAW;EAC1C;CACF;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAC;GAAE,MAAM;GAAe,MAAM;EAAS,CAAC;CACjD;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ;GACN;IAAE,MAAM;IAAS,MAAM;GAAW;GAClC;IAAE,MAAM;IAAQ,MAAM;GAAW;GACjC;IAAE,MAAM;IAAU,MAAM;GAAW;GACnC;IAAE,MAAM;IAAW,MAAM;GAAW;EACrC;CACF;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;CAGD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;CACX;AACF;;;;;;;;AC9PD,MAAM,cAAc;CAClB,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;AACJ;;;;;;;;;;;ACtFD,MAAa,iBAAiB;;;;AAmC9B,MAAa,gBAAgB;CAE3B,cAAc;CAEd,qBAAqB;CAErB,aAAa;CAEb,2BAA2B;CAE3B,mBAAmB;CAEnB,UAAU;CAEV,UAAU;AACX;;;;AAKD,MAAa,WAAW;CAEtB,WAAW;CAEX,YAAY;CAEZ,WAAW;CAEX,YAAY;CAEZ,aAAa;CAEb,cAAc;CAEd,gBAAgB;CAEhB,iBAAiB;CAEjB,kBAAkB;CAElB,mBAAmB;CAEnB,YAAY;CAEZ,aAAa;CAEb,WAAW;CAEX,YAAY;AACb;;;;AAKD,MAAa,YAAY;CAEvB,QAAQ,MAAM,SAAS,cAAc;CAErC,QAAQ,MAAM,SAAS,cAAc;CAErC,UAAU,MAAM,SAAS,gBAAgB;CAEzC,aAAa,MAAM,SAAS,mBAAmB;CAE/C,eAAe,MAAM,SAAS,qBAAqB;CAEnD,SAAS,MAAM,SAAS,eAAe;CAEvC,QAAQ,MAAM,SAAS,cAAc;CAErC,MAAM,MAAM,cAAc,YAAY;AACvC;;;;AAKD,MAAa,aAAa;CAExB,WAAW;CAEX,WAAW;CAEX,YAAY;CAEZ,aAAa;AACd;;;;;AAMD,MAAa,2BAA2B;;;;;;;;;;AC9ExC,SAAgB,sBAAsBC,eAA+B;AAEnE,KAAI,gBAAgB,MAAM,MAAM,GAC9B,QAAO,gBAAgB;AAEzB,QAAO;AACR;;;;;;;AAQD,SAAgB,aAAaC,UAA0B;AACrD,QAAO,WAAW,cAAc;AACjC;;;;;;;;AA+LD,SAAgB,UAAUC,SAAiBD,UAA8B;CACvE,MAAM,SAAS,aAAa,SAAS,GAAG,cAAc;CACtD,MAAM,MAAO,WAAW,SAAU,UAAU;CAE5C,MAAM,QAAQ,MAAM,UAAU;CAC9B,MAAM,cAAe,OAAO,SAAS,YAAa,UAAU;CAC5D,MAAM,UAAW,OAAO,SAAS,cAAe,UAAU,aAAa;CACvE,MAAM,YAAa,OAAO,SAAS,iBAAkB,UAAU;CAC/D,MAAM,cAAe,OAAO,SAAS,mBAAoB,UAAU;CACnE,MAAM,gBAAiB,OAAO,SAAS,aAAc,UAAU;CAC/D,MAAM,SAAS,sBAAsB,cAAc;CACnD,MAAM,QAAS,OAAO,SAAS,YAAa,UAAU;AAEtD,QAAO;EACL,OAAO;EACP;EACA;EACA;EACA;EACA;EACA;EACA;CACD;AACF;;;;;;;AA0BD,SAAgB,cAAcC,SAA+B;CAC3D,MAAMC,OAAqB,CAAE;AAC7B,MAAK,IAAI,IAAI,IAAI,IAAI,cAAc,UAAU,KAAK;EAChD,MAAM,MAAM,UAAU,SAAS,EAAE;AACjC,MAAI,IAAI,cAAc,GACpB,MAAK,KAAK,IAAI;CAEjB;AACD,QAAO;AACR;;;;ACnSD,MAAMC,kBAAgB,MAAM,OAAO;AACnC,MAAM,WAAW,cAAc;AAC/B,MAAM,mBAAmB,WAAW;AACpC,MAAMC,SAAO,MAAM;;;;ACtBnB,MAAM,kBAAkB;AACxB,MAAM,gBAAgB;AACtB,MAAM,mBAAmB,kBAAkB;;;;ACD3C,MAAM,cAAc,MAAM,OAAO;AACjC,MAAMC,iBAAe,MAAM,QAAQ;AACnC,MAAMC,SAAO,MAAM;;;;ACLnB,MAAMC,kBAAgB,MAAM,cAAc,gBAAgB;AAC1D,MAAMC,iBAAe,MAAM,QAAQ;AACnC,MAAM,eAAe,MAAM,QAAQ;;;;ACPnC,MAAMC,QAAM,MAAM;AAClB,MAAM,UAAU,CAACC,GAAWC,OAAe,IAAI,IAAI,MAAM;;AAGzD,SAAgB,oBAAoBC,QAA+BC,cAAsB;AACvF,QAAO,sBAAsB,QAAQ,aAAa,CAAC;AACpD;;AAGD,SAAgB,sBAAsBD,QAA+BC,cAAsB;AACzF,KAAI,gBAAgB,GAAI,OAAM,IAAI,MAAM;CACxC,IAAI,UAAU;CACd,IAAI,UAAU;AACd,MAAK,MAAM,EAAE,WAAW,WAAW,WAAW,IAAI,QAAQ;AACxD,OACG,OAAO,UAAU,UAAU,KAC3B,OAAO,UAAU,UAAU,IAC5B,YAAY,WACZ,YAAY,UACZ,aAAa,aACb,YAAY,GAEZ,OAAM,IAAI,MAAM;EAClB,MAAM,QAAQ,mBAAmB,OAAO,UAAU,CAAC;EACnD,MAAM,QAAQ,mBAAmB,OAAO,UAAU,CAAC;EACnD,MAAM,QAAQ,eAAe,QAAQ,QAAQ,eAAe,QAAQ,QAAQ;AAC5E,aAAW,QAAQ,YAAYJ,SAAO,QAAQ,QAAQ,QAAQ,MAAM;AACpE,aAAW,QAAQ,aAAa,QAAQ,QAAQA,MAAI;CACrD;CACD,MAAM,SAAS;EAAE,SAAS,QAAQ,UAAU,IAAI,KAAK;EAAE,SAAS,QAAQ,UAAU,IAAI,KAAK;CAAE;AAC7F,QAAO;EACL,WAAW;GAAE;GAAS;EAAS;EAC/B;EACA,OAAO;GAAE,SAAS,UAAU,OAAO;GAAS,SAAS,UAAU,OAAO;EAAS;CAChF;AACF;;AAaD,SAAgB,qBAAqBK,QAAiC;CACpE,MAAM,EACJ,SACA,cACA,aACA,cACA,uBACA,iBACD,GAAG;AACJ,KAAI,eAAe,MAAM,eAAe,MAAM,yBAAyB,GACrE,OAAM,IAAI,MAAM;CAClB,MAAM,OAAO,cAAc,QAAQ;AACnC,KAAI,KAAK,WAAW,KAAK,KAAK,KAAK,CAAC,QAAQ,IAAI,UAAU,IAAI,UAAU,GAAG,CACzE,OAAM,IAAI,MAAM;CAClB,MAAM,SAAS,KAAK,IAAI,CAAC,QAAQ;EAC/B,MAAM,QAAQ,IAAI,QAAQ;EAC1B,MAAM,YAAY,IAAI,SAAS,QAAQ;EACvC,MAAM,YAAY,IAAI,UAAU,QAAQ,MAAM;EAC9C,MAAM,QAAQ,mBAAmB,UAAU;EAC3C,MAAM,QAAQ,mBAAmB,UAAU;EAC3C,MAAM,SAAS,eAAe,IAAI;EAClC,MAAM,YACJ,IAAI,UAAU,KACT,UAAW,QAAQ,QAASL,UAAS,QAAQ,SAC7C,SAASA,SAAQ,QAAQ;AAChC,SAAO;GAAE,WAAW,OAAO,UAAU;GAAE,WAAW,OAAO,UAAU;GAAE;EAAW;CACjF,EAAC;CACF,MAAM,YAAY,sBAAsB,QAAQ,aAAa;CAC7D,MAAM,eAAe,wBAAwB;CAC7C,MAAM,QAAQ,CAAC,EAAE,SAAS,SAA+C,KACvE,oBAAoB,IAChB,UAAU,QAAQ,UAAUA,QAAMA,OAAK,aAAa,GACpD,UAAU,QAAQ,UAAU,cAAcA,QAAMA,MAAI;CAC1D,MAAM,mBAAmB,MAAM,UAAU,UAAU;CACnD,MAAM,eAAe,MAAM,UAAU,MAAM;AAC3C,QAAO;EACL,GAAG;EACH;EACA,eAAe,eAAe;EAC9B;CACD;AACF;;AAGD,SAAgB,oBAAoB,EAClC,SACA,kBACA,iBAAiB,IACjB,iBACA,uBACA,cAQD,EAAE;AACD,KACE,yBAAyB,MACxB,4BAA+B,eAAe,MAAM,eAAe,MAEpE,OAAM,IAAI,MAAM;CAClB,MAAM,kBACJ,iBAAiB,QAAQ,eAAe,iBAAiB,QAAQ;CACnE,MAAM,mBACJ,kBAAkB,mBAAmB,kBAAkB,mBAAmB;CAC5E,MAAM,sBACJ,QAAQ,eAAe,MACjB,oBAAoB,IAAI,QAAQ,MAAM,UAAU,QAAQ,MAAM,WAAW,OAC3E,QAAQ,eACR;AACN,KAAI,wBACF,QAAO;EACL;EACA;EACA;EACA,SACE,QAAQ,eAAe,KACnB,QAAQ,QAAQ,MAAM,UAAU,kBAAkB,QAAQ,aAAa,GACvE;EACN,SACE,QAAQ,eAAe,KACnB,QAAQ,QAAQ,MAAM,UAAU,kBAAkB,QAAQ,aAAa,GACvE;CACP;CAEH,MAAM,cAAe,mBAAmB,eAAgB;CACxD,MAAM,aAAa,mBAAmB;CACtC,MAAM,eAAe,wBAAwB;AAC7C,QAAO;EACL;EACA;EACA;EACA,SAAS,oBAAoB,IAAI,cAAc,QAAQ,aAAaA,QAAMA,OAAK,aAAa;EAC5F,SAAS,oBAAoB,IAAI,cAAc,QAAQ,aAAa,cAAcA,QAAMA,MAAI;CAC7F;AACF;;AAGD,SAAgB,qBACdM,QAIA;AACA,KACE,OAAO,uBACN,OAAO,mBAAmB,iBAAiB,MAC1C,OAAO,mBAAmB,kBAAkB,IAE9C,OAAM,IAAI,MAAM;AAClB,KAAI,OAAO,oBAAoB,GAAI,QAAO;CAC1C,IAAI,MAAM;CACV,IAAI,QAAQ,MAAM,QAAQ;AAC1B,QAAO,MAAM,MAAM;EACjB,MAAM,OAAO,MAAM,OAAO,MAAM;EAChC,MAAM,UAAU,qBAAqB;GAAE,GAAG;GAAQ,cAAc;EAAK,EAAC;EACtE,MAAM,UAAU,OAAO,qBACnB,QACE,OAAO,mBAAmB,kBAAkB,KAC5C,OAAO,mBAAmB,cAC3B,GACD;AACJ,MAAI,QAAQ,gBAAgB,OAAO,oBAAoB,WAAW,OAAO,iBACvE,OAAM;MACH,QAAO,MAAM;CACnB;AACD,QAAO;AACR;;;;ACjKD,MAAMC,QAAM,MAAM;AAClB,MAAMC,SAAO,MAAM;;;;;;;AAwCnB,SAAgB,uBACdC,cACAC,eACAC,eACAC,WACW;CAEX,MAAM,CAAC,OAAO,MAAM,GAClB,iBAAiB,gBAAgB,CAAC,eAAe,aAAc,IAAG,CAAC,eAAe,aAAc;CAGlG,MAAM,QAAQ,eAAe,QAAQ,QAAQ,eAAe,QAAQ,QAAQ;CAG5E,MAAM,UAAU,QAAQ,QAAS,aAAa,QAAQ,SAASL,SAAQ,QAAQ,SAAS;CAGxF,MAAM,UAAU,QAAQ,QAAS,aAAa,QAAQ,SAAUA,QAAM;AAEtE,QAAO;EAAE;EAAS;CAAS;AAC5B;;;;;;;;;;;;AAaD,SAAgB,YAAYM,OAAgC;CAC1D,MAAM,EAAE,WAAW,WAAW,WAAW,aAAa,YAAY,GAAG;CAErE,MAAM,QAAQ,mBAAmB,YAAY;CAC7C,MAAM,QAAQ,mBAAmB,UAAU;CAC3C,MAAM,QAAQ,mBAAmB,UAAU;CAE3C,MAAM,EAAE,SAAS,SAAS,GAAG,uBAAuB,OAAO,OAAO,OAAO,UAAU;CAEnF,MAAM,SAAS,QAAQ;CACvB,MAAM,UAAU,QAAQ,SAAS,QAAQ;AAEzC,KAAI,eAAe,GAAG;EAEpB,MAAMC,UAAQ,UAAW,UAAU,SAAUN;EAC7C,MAAMO,UAAQ;EAEd,MAAMC,UAAQ,YAAY,YAAY,UAAU,KAAKT,SAAO;AAC5D,SAAO;GAAE;GAAO;GAAO;EAAO;CAC/B;CAGD,MAAM,QAAQ,UAAW,UAAUC,SAAQ;CAC3C,MAAM,QAAQ;CAEd,MAAM,QAAQ,YAAY,YAAYD,UAAQ,KAAK,SAAS;AAC5D,QAAO;EAAE;EAAO;EAAO;CAAO;AAC/B;;;;ACpHD,MAAM,IAAI,QAAQ,MAAM,EAAE,WAAW,GAAI,EAAC;;AAG1C,SAAgB,qBAAqBU,kBAA2BC,iBAAyB;AACvF,KAAI,mBAAmB,GAAI,OAAM,IAAI,MAAM;AAC3C,QAAO,IAAI,EAAE,kBAAkB,IAAI,QAAW,CAAC,IAAI,gBAAgB,UAAU,CAAC;AAC/E;;;;;;;;;AAUD,SAAgB,qBAAiE,EAC/E,QACA,QACA,WAKD,EAAE;CACD,MAAMC,cAAY,CAACC,SAAiB,OAAO,UAAU,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI;AAChF,MAAK,YAAU,UAAU,CAAE,OAAM,IAAI,MAAM;CAC3C,MAAM,QAAQ,mBAAmB,OAAO,UAAU,CAAC;CACnD,MAAM,QAAQ,IAAI,EAAE,MAAM,UAAU,EAAE,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,MAAM,MAAM,UAAU,EAAE;CAChF,IAAI,WAAW;CACf,IAAI,WAAW;AACf,MAAK,MAAM,SAAS,QAAQ;AAC1B,OACG,YAAU,MAAM,UAAU,KAC1B,YAAU,MAAM,UAAU,IAC3B,MAAM,aAAa,MAAM,aACzB,MAAM,YAAY,GAElB,OAAM,IAAI,MAAM;EAClB,MAAM,UAAU,uBACd,OACA,mBAAmB,OAAO,MAAM,UAAU,CAAC,EAC3C,mBAAmB,OAAO,MAAM,UAAU,CAAC,EAC3C,MAAM,UACP;AACD,cAAY,QAAQ;AACpB,cAAY,QAAQ;CACrB;CACD,MAAM,UAAU,IAAI,EAAE,SAAS,UAAU,EAAE,IAAI,MAAM,CAAC,KAAK,SAAS,UAAU,CAAC;AAC/E,KAAI,QAAQ,QAAQ,CAAE;AACtB,QAAO,OAAO,IAAI,CAAC,UAAU;AAC3B,MAAI,MAAM,QAAQ,MAAM,MAAM,QAAQ,GAAI,OAAM,IAAI,MAAM;EAC1D,MAAM,OAAO,IAAI,EAAE,MAAM,MAAM,UAAU,EAAE,IAAI,MAAM,CAAC,KAAK,MAAM,MAAM,UAAU,CAAC;AAClF,SAAO;GAAE,GAAG;GAAO,kBAAkB,KAAK,IAAI,QAAQ,CAAC,IAAI,IAAI;EAAE;CAClE,EAAC;AACH;;;;;;;;AC3CD,IAAa,wBAAb,cAA2C,cAAc;CACvD,AAAkB,OAAO;CAEzB,YACkBC,SAChBC,OACA;AACA,SAAO,6CAA6C,QAAQ,GAAG,MAAM;EA8DxE,KAjEmB;CAIjB;AACF;;;;AAKD,IAAa,wBAAb,cAA2C,cAAc;CACvD,AAAkB,OAAO;CAEzB,YACkBC,OACAC,WACAC,WAChBH,OACA;AACA,SACG,QAAQ,MAAM,sCAAsC,UAAU,cAAc,UAAU,IACvF,MACD;EA2CH,KAnDkB;EAmDjB,KAlDiB;EAkDhB,KAjDgB;CAOjB;AACF;;;;AAKD,IAAa,4BAAb,cAA+C,cAAc;CAC3D,AAAkB,OAAO;CAEzB,YACkBI,QAChBJ,OACA;AACA,SAAO,SAAS,OAAO,2BAA2B,MAAM;EA6BvD,KAhCe;CAIjB;AACF;;;;;AAMD,IAAa,6BAAb,cAAgD,cAAc;CAC5D,AAAkB,OAAO;CAEzB,YAAYA,OAAe;AACzB,QAAM,gEAAgE,MAAM;CAC7E;AACF;;;;AAKD,IAAa,yBAAb,cAA4C,cAAc;CACxD,AAAkB,OAAO;CAEzB,YACkBD,SAChBC,OACA;AACA,SAAO,iCAAiC,QAAQ,GAAG,MAAM;EAGvD,KANc;CAIjB;AACF;;;;;;;;AC5DD,MAAaK,uBAA2D;CAEtE,GAAG;EACD,UAAU;EACV,4BAA4B;CAC7B;CACD,MAAM;EACJ,UAAU;EACV,4BAA4B;CAC7B;AACF;;;;;;;AAQD,SAAgB,sBACdC,SACAC,WACoB;CACpB,MAAM,KAAK,OAAO,QAAQ;CAC1B,MAAM,OAAO,qBAAqB;CAClC,MAAM,SAAS;EAAE,GAAG;EAAM,GAAG;CAAW;AACxC,MAAK,OAAO,aAAa,OAAO,2BAC9B,OAAM,IAAI,sBAAsB,OAAO,GAAG;AAE5C,QAAO;AACR;;;;;;;;AClDD,MAAa,qBAAqB,CAChC;CACE,MAAM;CACN,MAAM;CACN,iBAAiB;CACjB,QAAQ;EACN;GAAE,MAAM;GAAY,MAAM;EAAS;EACnC;GAAE,MAAM;GAAU,MAAM;EAAW;EACnC;GAAE,MAAM;GAAY,MAAM;EAAW;CACtC;CACD,SAAS,CAAE;AACZ,CACF;;;;;ACgBD,MAAa,mBAAmB;;AAGhC,MAAa,oBAAoB;;;;;AAMjC,MAAaC,aAAsB;AAEnC,MAAMC,iBAAe,MAAM,QAAQ;AAEnC,MAAM,oBAAoB;CACxB;EAAE,MAAM;EAAa,MAAM;CAAW;CACtC;EAAE,MAAM;EAAY,MAAM;CAAW;CACrC;EAAE,MAAM;EAAoB,MAAM;CAAW;CAC7C;EAAE,MAAM;EAAQ,MAAM;CAAS;CAC/B;EAAE,MAAM;EAAe,MAAM;CAAQ;AACtC;AAED,SAASC,gBAAcC,QAAsB;AAC3C,KAAI,SAAS,MAAM,SAASF,cAC1B,OAAM,IAAI,0BAA0B;AAEvC;;;;AAwBD,SAAgB,aAAaG,SAAkBC,KAAaC,UAAwB;AAClF,KAAI,MAAM,MAAM,MAAM,UACpB,OAAM,IAAI,eAAe,SAAS,IAAI;AAExC,QAAO,aAAa;EAAC;EAAW;EAAU;CAAU,GAAE;EAAC;EAAS,OAAO,IAAI;EAAE;CAAS,EAAC;AACxF;;;;;AAMD,SAAgB,uBAAuBC,MAGrC;CACA,MAAM,EAAE,SAAS,UAAU,KAAK,UAAU,kBAAkB,UAAU,GAAG;AAEzE,KAAI,YAAY,eAAe,aAAa,YAC1C,OAAM,IAAI,cAAc;AAE1B,iBAAc,SAAS;AACvB,iBAAc,iBAAiB;CAE/B,MAAM,OAAO,aAAa,SAAS,KAAK,SAAS;CACjD,MAAM,QAAQ,oBAAoB,mBAAmB;EACnD;EACA;EACA;EACA;EACA;CACD,EAAC;CAEF,MAAM,WAAW,aAAa,CAAC,OAAQ,GAAE,CAAC,gBAAiB,EAAC;AAC5D,QAAO;EAAE,MAAM;GAAC;GAAU,CAAC,KAAM;GAAE;EAAS;EAAW,OAAO;CAAI;AACnE;;;;;AAMD,SAAgB,2BAA2BA,MAGzC;CACA,MAAM,EAAE,MAAM,aAAa,OAAO,GAAG,uBAAuB,KAAK;CACjE,MAAM,OAAO,mBAAmB;EAC9B,KAAK;EACL,cAAc;EACd,MAAM;CACP,EAAC;AACF,QAAO;EAAE;EAAM;CAAO;AACvB;AAWD,MAAM,qBAAqB;CACzB;EAAE,MAAM;EAAa,MAAM;CAAW;CACtC;EAAE,MAAM;EAAa,MAAM;CAAW;CACtC;EAAE,MAAM;EAAmB,MAAM;CAAW;CAC5C;EAAE,MAAM;EAAQ,MAAM;CAAS;CAC/B;EAAE,MAAM;EAAe,MAAM;CAAQ;AACtC;;;;;AAMD,SAAgB,+BAA+BC,MAG7C;CACA,MAAM,EAAE,SAAS,UAAU,KAAK,WAAW,iBAAiB,UAAU,GAAG;AAEzE,KAAI,YAAY,eAAe,aAAa,YAC1C,OAAM,IAAI,cAAc;AAE1B,iBAAc,UAAU;AACxB,iBAAc,gBAAgB;CAE9B,MAAM,OAAO,aAAa,UAAU,KAAK,QAAQ;CACjD,MAAM,QAAQ,oBAAoB,oBAAoB;EACpD;EACA;EACA;EACA;EACA;CACD,EAAC;CAEF,MAAM,WAAW,aAAa,CAAC,OAAQ,GAAE,CAAC,iBAAkB,EAAC;AAC7D,QAAO;EAAE,MAAM;GAAC;GAAU,CAAC,KAAM;GAAE;EAAS;EAAW,OAAO;CAAI;AACnE;AAED,SAAgB,mCAAmCA,MAGjD;CACA,MAAM,EAAE,MAAM,aAAa,OAAO,GAAG,+BAA+B,KAAK;CACzE,MAAM,OAAO,mBAAmB;EAC9B,KAAK;EACL,cAAc;EACd,MAAM;CACP,EAAC;AACF,QAAO;EAAE;EAAM;CAAO;AACvB;;;;;;;;;;;ACxLD,MAAa,cAAc,CACzB;CACE,MAAM;CACN,MAAM;CACN,iBAAiB;CACjB,QAAQ,CACN;EACE,MAAM;EACN,MAAM;EACN,YAAY;GACV;IAAE,MAAM;IAAW,MAAM;GAAW;GACpC;IAAE,MAAM;IAAY,MAAM;GAAW;GACrC;IAAE,MAAM;IAAY,MAAM;GAAW;GACrC;IAAE,MAAM;IAAO,MAAM;GAAU;GAC/B;IAAE,MAAM;IAAqB,MAAM;GAAW;EAC/C;CACF,CACF;CACD,SAAS;EACP;GAAE,MAAM;GAAa,MAAM;EAAW;EACtC;GAAE,MAAM;GAAqB,MAAM;EAAW;EAC9C;GAAE,MAAM;GAA2B,MAAM;EAAU;EACnD;GAAE,MAAM;GAAe,MAAM;EAAW;CACzC;AACF,GACD;CACE,MAAM;CACN,MAAM;CACN,iBAAiB;CACjB,QAAQ,CACN;EACE,MAAM;EACN,MAAM;EACN,YAAY;GACV;IAAE,MAAM;IAAW,MAAM;GAAW;GACpC;IAAE,MAAM;IAAY,MAAM;GAAW;GACrC;IAAE,MAAM;IAAU,MAAM;GAAW;GACnC;IAAE,MAAM;IAAO,MAAM;GAAU;GAC/B;IAAE,MAAM;IAAqB,MAAM;GAAW;EAC/C;CACF,CACF;CACD,SAAS;EACP;GAAE,MAAM;GAAY,MAAM;EAAW;EACrC;GAAE,MAAM;GAAqB,MAAM;EAAW;EAC9C;GAAE,MAAM;GAA2B,MAAM;EAAU;EACnD;GAAE,MAAM;GAAe,MAAM;EAAW;CACzC;AACF,CACF;;;;AC5CD,MAAMC,oBAAkB;AACxB,MAAMC,iBAAe,MAAM,QAAQ;;;;;;AAyBnC,eAAsB,eAAeC,QAA8D;CACjG,MAAM,EAAE,QAAQ,SAAS,SAAS,UAAU,KAAK,UAAU,aAAa,aAAa,GAAG;AACxF,KAAI,WAAW,MAAM,WAAWD,cAC9B,OAAM,IAAI,eAAe,WAAW,SAAS;AAE/C,qBAAkB,YAAY;CAE9B,MAAM,EAAE,UAAU,GAAG,sBAAsB,SAAS,OAAO,UAAU;AAErE,KAAI;EACF,MAAM,EAAE,QAAQ,GAAG,MAAM,OAAO,iBAAiB;GAC/C,SAAS;GACT,KAAK;GACL,cAAc;GACd;GACA,MAAM,CAAC;IAAE;IAAS;IAAU;IAAU,KAAK,OAAO,IAAI;IAAE,mBAAmB;GAAI,CAAC;EACjF,EAAC;EACF,MAAM,CAAC,eAAe,YAAY,GAAG;EACrC,MAAM,mBAAoB,aAAaD,oBAAkB,eAAgBA;AACzE,SAAO;GAAE;GAAW;GAAkB;EAAa;CACpD,SAAQ,KAAK;AACZ,MAAI,WAAS,IAAI,CAAE,QAAO;AAC1B,QAAM;CACP;AACF;;;;AAuBD,eAAsB,gBACpBG,QACiC;CACjC,MAAM,EAAE,QAAQ,SAAS,SAAS,UAAU,KAAK,WAAW,aAAa,aAAa,GAAG;AACzF,KAAI,YAAY,MAAM,YAAYF,cAChC,OAAM,IAAI,eAAe,YAAY,UAAU;AAEjD,qBAAkB,YAAY;CAE9B,MAAM,EAAE,UAAU,GAAG,sBAAsB,SAAS,OAAO,UAAU;AAErE,KAAI;EACF,MAAM,EAAE,QAAQ,GAAG,MAAM,OAAO,iBAAiB;GAC/C,SAAS;GACT,KAAK;GACL,cAAc;GACd;GACA,MAAM,CAAC;IAAE;IAAS;IAAU,QAAQ;IAAW,KAAK,OAAO,IAAI;IAAE,mBAAmB;GAAI,CAAC;EAC1F,EAAC;EACF,MAAM,CAAC,cAAc,YAAY,GAAG;EACpC,MAAM,mBACH,YAAYD,oBAAkB,eAAeA,oBAAkB,MAAMA;AACxE,SAAO;GAAE;GAAU;GAAiB;EAAa;CAClD,SAAQ,KAAK;AACZ,MAAI,WAAS,IAAI,CAAE,QAAO;AAC1B,QAAM;CACP;AACF;AAED,SAASI,oBAAkBC,aAA2B;AACpD,KAAI,cAAc,MAAM,cAAcL,kBACpC,OAAM,IAAI,eAAe,sBAAsB,YAAY;AAE9D;AAED,SAASM,WAASC,KAAuB;AACvC,QACE,eAAe,aACf,IAAI,KAAK,CAAC,MAAM,aAAa,8BAA8B,YACzD;AAEL;;;;;;;;;;;ACrGD,eAAsB,aAAaC,QAAgD;CACjF,MAAM,EAAE,QAAQ,aAAa,GAAG;CAEhC,MAAM,QAAQ,MAAM,OAAO,SAAS;EAClC;EACA,qBAAqB;CACtB,EAAC;AAEF,QAAO;EACL,aAAa,MAAM;EACnB,WAAW,MAAM;EACjB,gBAAgB,MAAM;CACvB;AACF;;;;;;;;ACnCD,MAAa,eAAe;CAC1B;EACE,QAAQ,CAAC;GAAE,cAAc;GAAU,MAAM;GAAU,MAAM;EAAW,CAAC;EACrE,MAAM;EACN,SAAS;GACP;IAAE,cAAc;IAAW,MAAM;IAAgB,MAAM;GAAW;GAClE;IAAE,cAAc;IAAS,MAAM;IAAQ,MAAM;GAAS;GACtD;IAAE,cAAc;IAAU,MAAM;IAAe,MAAM;GAAU;GAC/D;IAAE,cAAc;IAAU,MAAM;IAAS,MAAM;GAAU;EAC1D;EACD,iBAAiB;EACjB,MAAM;CACP;CACD;EACE,QAAQ,CAAC;GAAE,cAAc;GAAU,MAAM;GAAU,MAAM;EAAW,CAAC;EACrE,MAAM;EACN,SAAS,CACP;GAAE,cAAc;GAAW,MAAM;GAAoB,MAAM;EAAW,GACtE;GAAE,cAAc;GAAW,MAAM;GAAoB,MAAM;EAAW,CACvE;EACD,iBAAiB;EACjB,MAAM;CACP;CACD;EACE,QAAQ,CACN;GAAE,cAAc;GAAU,MAAM;GAAU,MAAM;EAAW,GAC3D;GAAE,cAAc;GAAS,MAAM;GAAQ,MAAM;EAAS,CACvD;EACD,MAAM;EACN,SAAS;GACP;IAAE,cAAc;IAAW,MAAM;IAAkB,MAAM;GAAW;GACpE;IAAE,cAAc;IAAU,MAAM;IAAgB,MAAM;GAAU;GAChE;IAAE,cAAc;IAAW,MAAM;IAAyB,MAAM;GAAW;GAC3E;IAAE,cAAc;IAAW,MAAM;IAAyB,MAAM;GAAW;EAC5E;EACD,iBAAiB;EACjB,MAAM;CACP;CACD;EACE,QAAQ,CAAC;GAAE,cAAc;GAAU,MAAM;GAAU,MAAM;EAAW,CAAC;EACrE,MAAM;EACN,SAAS,CAAC;GAAE,cAAc;GAAW,MAAM;GAAa,MAAM;EAAW,CAAC;EAC1E,iBAAiB;EACjB,MAAM;CACP;AACF;;;;;;;;AC7CD,MAAa,mBAAmB;CAC9B;EACE,QAAQ,CAAE;EACV,MAAM;EACN,SAAS;GACP;IAAE,cAAc;IAAW,MAAM;IAAgB,MAAM;GAAW;GAClE;IAAE,cAAc;IAAS,MAAM;IAAQ,MAAM;GAAS;GACtD;IAAE,cAAc;IAAU,MAAM;IAAoB,MAAM;GAAU;GACpE;IAAE,cAAc;IAAU,MAAM;IAA0B,MAAM;GAAU;GAC1E;IAAE,cAAc;IAAU,MAAM;IAA8B,MAAM;GAAU;GAC9E;IAAE,cAAc;IAAS,MAAM;IAAe,MAAM;GAAS;GAC7D;IAAE,cAAc;IAAQ,MAAM;IAAY,MAAM;GAAQ;EACzD;EACD,iBAAiB;EACjB,MAAM;CACP;CACD;EACE,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,cAAc;GAAW,MAAM;GAAI,MAAM;EAAW,CAAC;EACjE,iBAAiB;EACjB,MAAM;CACP;CACD;EACE,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,cAAc;GAAW,MAAM;GAAI,MAAM;EAAW,CAAC;EACjE,iBAAiB;EACjB,MAAM;CACP;CACD;EACE,QAAQ,CAAC;GAAE,cAAc;GAAS,MAAM;GAAI,MAAM;EAAS,CAAC;EAC5D,MAAM;EACN,SAAS;GACP;IAAE,cAAc;IAAW,MAAM;IAAkB,MAAM;GAAW;GACpE;IAAE,cAAc;IAAU,MAAM;IAAgB,MAAM;GAAU;GAChE;IAAE,cAAc;IAAW,MAAM;IAAyB,MAAM;GAAW;GAC3E;IAAE,cAAc;IAAW,MAAM;IAAyB,MAAM;GAAW;GAC3E;IAAE,cAAc;IAAS,MAAM;IAAyB,MAAM;GAAS;GACvE;IAAE,cAAc;IAAW,MAAM;IAAkC,MAAM;GAAW;GACpF;IAAE,cAAc;IAAU,MAAM;IAAkB,MAAM;GAAU;GAClE;IAAE,cAAc;IAAQ,MAAM;IAAe,MAAM;GAAQ;EAC5D;EACD,iBAAiB;EACjB,MAAM;CACP;CACD;EACE,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,cAAc;GAAW,MAAM;GAAI,MAAM;EAAW,CAAC;EACjE,iBAAiB;EACjB,MAAM;CACP;CACD;EACE,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,cAAc;GAAU,MAAM;GAAI,MAAM;EAAU,CAAC;EAC/D,iBAAiB;EACjB,MAAM;CACP;CACD;EACE,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,cAAc;GAAW,MAAM;GAAI,MAAM;EAAW,CAAC;EACjE,iBAAiB;EACjB,MAAM;CACP;CACD;EACE,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,cAAc;GAAW,MAAM;GAAI,MAAM;EAAW,CAAC;EACjE,iBAAiB;EACjB,MAAM;CACP;CACD;EACE,QAAQ,CAAE;EACV,MAAM;EACN,SAAS,CAAC;GAAE,cAAc;GAAS,MAAM;GAAI,MAAM;EAAS,CAAC;EAC7D,iBAAiB;EACjB,MAAM;CACP;AACF;;;;AClFD,MAAM,qBAAqB,MAAM,OAAO;AACxC,MAAM,oBAAoB,MAAM,OAAO;;;;ACAvC,MAAM,eAAe,MAAM,OAAO;;;;ACmClC,MAAMC,aAAW;CACf;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;EACV,SAAS,CAAC,EAAE,MAAM,SAAU,CAAC;EAC7B,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;EACV,SAAS,CAAC,EAAE,MAAM,QAAS,CAAC;EAC5B,iBAAiB;CAClB;CACD;EACE,MAAM;EACN,MAAM;EACN,QAAQ,CAAE;EACV,SAAS,CAAC,EAAE,MAAM,SAAU,CAAC;EAC7B,iBAAiB;CAClB;AACF;;;;;;;;;;AAiED,eAAsB,gBAAgBC,QAAsD;CAC1F,MAAM,EAAE,QAAQ,aAAa,GAAG;CAGhC,MAAM,eAAe,MAAM,OAAO,UAAU;EAC1C,WAAW;GACT;IACE,SAAS;IACT,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS;IACT,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS;IACT,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS;IACT,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS;IACT,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS;IACT,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS;IACT,KAAK;IACL,cAAc;GACf;EACF;EACD,cAAc;CACf,EAAC;CAEF,MAAM,CACJ,cACA,QACA,yBACA,yBACA,mBACA,aACA,YACD,GAAG;CAGJ,MAAM,eAAe,MAAM,OAAO,UAAU;EAC1C,WAAW,CACT;GACE,SAAS;GACT,KAAK;GACL,cAAc;EACf,GACD;GACE,SAAS;GACT,KAAK;GACL,cAAc;EACf,CACF;EACD,cAAc;CACf,EAAC;CAEF,MAAM,CAAC,aAAa,YAAY,GAAG;CAGnC,MAAM,qBAAqB;CAC3B,MAAM,iBAAiB,YAAY,aAAa,KAAK;CACrD,MAAM,iBAAiB,YAAY,aAAa,KAAK;CAGrD,MAAM,iBAAiB,CACrB,GAAI,iBACA,CAAE,IACF;EACE;GAAE,SAAS;GAAa,KAAKD;GAAU,cAAc;EAAmB;EACxE;GAAE,SAAS;GAAa,KAAKA;GAAU,cAAc;EAAqB;EAC1E;GAAE,SAAS;GAAa,KAAKA;GAAU,cAAc;EAAiB;CACvE,GACL,GAAI,iBACA,CAAE,IACF;EACE;GAAE,SAAS;GAAa,KAAKA;GAAU,cAAc;EAAmB;EACxE;GAAE,SAAS;GAAa,KAAKA;GAAU,cAAc;EAAqB;EAC1E;GAAE,SAAS;GAAa,KAAKA;GAAU,cAAc;EAAiB;CACvE,CACN;CAED,MAAM,eACJ,eAAe,SAAS,IACpB,MAAM,OAAO,UAAU;EAAE,WAAW;EAAgB,cAAc;CAAO,EAAC,GAC1E,CAAE;CAGR,IAAI,YAAY;CAChB,MAAM,eAAe,iBAAiB,QAAS,aAAa;CAC5D,MAAM,iBAAiB,iBAAiB,KAAM,aAAa;CAC3D,MAAM,aAAa,iBAAiB,UAAW,aAAa;CAC5D,MAAM,eAAe,iBAAiB,QAAS,aAAa;CAC5D,MAAM,iBAAiB,iBAAiB,KAAM,aAAa;CAC3D,MAAM,aAAa,iBAAiB,UAAW,aAAa;CAG5D,MAAM,OAAO,gBAAgB;CAC7B,MAAM,gBAAgB,aAAa,aAAa;CAChD,IAAIE;CACJ,IAAIC;CACJ,IAAIC;AAEJ,KAAI,MAAM;AACR,qBAAmB,UAAU,aAAa;AAC1C,QAAM,cAAc;AACpB,gBAAc,sBAAsB,OAAO;CAC5C,OAAM;EACL,MAAM,gBAAgB,oBAAoB,CAAC,EAAE,MAAM,UAAW,CAAC,GAAE,aAAa,CAAC;AAC/E,qBAAmB;EACnB,MAAM,CAAC,OAAO,cAAc,GAAG,MAAM,OAAO,UAAU;GACpD,WAAW,CACT;IAAE,SAAS;IAAe,KAAK;IAAkB,cAAc;GAAO,GACtE;IAAE,SAAS;IAAe,KAAK;IAAkB,cAAc;GAAe,CAC/E;GACD,cAAc;EACf,EAAC;AACF,QAAM,OAAO,MAAM;AACnB,gBAAc,OAAO,cAAc;CACpC;AAED,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,gBAAgB,OAAO,eAAe;EACtC,gBAAgB,OAAO,eAAe;EACtC;EACA;EACA;EACA;EACA;EACA;CACD;AACF;;;;;;;;;;;;AAiCD,eAAsB,QAAQC,QAAsC;CAClE,MAAM,EAAE,QAAQ,aAAa,SAAS,aAAa,cAAc,GAAG;CAEpE,MAAM,oBACJ,eAAe,OAAO,OAAO,eAAgB,MAAM,OAAO,gBAAgB;CAG5E,MAAM,WAAW,gBAAiB,MAAM,gBAAgB;EAAE;EAAQ;CAAa,EAAC;CAGhF,MAAM,oBACJ,SAAS,QAAQ,OAAO,mBACpB;EACE,SAAS,OAAO;EAChB,KAAK;EACL,cAAc;EACd,MAAM,CAAC,SAAS,gBAAkC;CACnD,KACA,SAAS,OACR;EACE,SAAS,SAAS;EAClB,KAAK;EACL,cAAc;CACf,IACD;CAGR,MAAM,CAAC,gBAAgB,MAAM,GAAG,MAAM,QAAQ,IAAI,CAChD,OAAO,UAAU;EACf,WAAW;GAET;IACE,SAAS;IACT,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS;IACT,KAAK;IACL,cAAc;GACf;GAED;IACE,SAAS,SAAS;IAClB,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS,SAAS;IAClB,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS,SAAS;IAClB,KAAK;IACL,cAAc;GACf;GAED;IACE,SAAS,SAAS;IAClB,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS,SAAS;IAClB,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS,SAAS;IAClB,KAAK;IACL,cAAc;GACf;GAED;IACE,SAAS,SAAS;IAClB,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS,SAAS;IAClB,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS,SAAS;IAClB,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS,SAAS;IAClB,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS,SAAS;IAClB,KAAK;IACL,cAAc;GACf;GACD;IACE,SAAS,SAAS;IAClB,KAAK;IACL,cAAc;GACf;GAGD,GAAI,oBAAoB,CAAC,iBAAyB,IAAG,CAAE;EACxD;EACD,aAAa;EACb,cAAc;CACf,EAAC,EACF,OAAO,SAAS,aAAa;EAAE;EAAQ,aAAa;CAAmB,EAAC,AACzE,EAAC;CAGF,MAAM,cAAc,eAAe,MAAM,GAAG,GAAG;AAC/C,KAAI,YAAY,KAAK,CAAC,MAAM,EAAE,WAAW,UAAU,EAAE;EACnD,MAAM,SAAS,YAAY,KAAK,CAAC,MAAM,EAAE,WAAW,UAAU;AAC9D,QAAM,IAAI,OAAO,yBAAyB,KAAK,UAAU,OAAO,CAAC;CAClE;CACD,MAAM,CACJ,aACA,aACA,gBACA,mBACA,oBACA,gBACA,mBACA,oBACA,uBACA,iBACA,aACA,YACAC,UACA,UACD,GAAG,YAAY,IAAI,CAAC,MAAM,EAAE,OAAO;CAgBpC,MAAM,kBAAkB,eAAe;CACvC,MAAM,uBACJ,iBAAiB,WAAW,YAAY,OAAO,gBAAgB,OAAiB,GAAG;CAIrF,MAAM,cAAc,SAAS;CAC7B,MAAM,UAAU;EACd,GAAG,aAAa,SAAS,aAAa;EACtC,KAAK,SAAS;EACd;CACD;CAGD,MAAMC,qBAAmB;CACzB,MAAM,cAAc,OAAO,mBAAmB,GAAGA;CACjD,MAAM,cAAc,OAAO,mBAAmB,GAAGA;CACjD,MAAM,eAAe,eAAe;CACpC,MAAM,eAAe,eAAe;CAEpC,MAAM,cAAe,cAAc,eAAgB;CACnD,MAAM,cAAe,cAAc,eAAgB;CACnD,MAAM,eAAe,eAAe,KAAK,eAAe;CACxD,MAAM,eAAe,eAAe,KAAK,eAAe;CAGxD,MAAMC,qBAAwC;EAC5C,SAAS,SAAS;EAClB,OAAO,SAAS;EAChB,QAAQ,SAAS;EACjB,UAAU,SAAS;EACnB,aAAa;EACb,WAAW,eAAe;EAC1B,gBAAgB,eAAe;EAC/B,aAAa;EACb,aAAa;EACb,YAAY;EACZ,YAAY;CACb;CAED,MAAMC,qBAAwC;EAC5C,SAAS,SAAS;EAClB,OAAO,SAAS;EAChB,QAAQ,SAAS;EACjB,UAAU,SAAS;EACnB,aAAa;EACb,WAAW,eAAe;EAC1B,gBAAgB,eAAe;EAC/B,aAAa;EACb,aAAa;EACb,YAAY;EACZ,YAAY;CACb;CAGD,MAAMC,aAAyB;EAC7B,SAAS,SAAS;EAClB,uBAAuB;EACvB,mBAAmB;EACnB,gBAAgB,OAAO,YAAY;EACnC,gBAAgB,OAAO,WAAW;EAClC,QAAQ,OAAOJ,SAAO;EACtB,WAAW,OAAO,UAAU;CAC7B;CAGD,MAAM,eAAe,gBAAgB,IAAI,WAAW,gBAAgB,IAAI,kBAAkB;CAG1F,MAAM,eAAe,mBAAmB,OAAO,YAAY,CAAC;AAE5D,QAAO;EACL,SAAS;EACT;EACA,QAAQ,SAAS;EACjB;EACA;EACA;EACA;EACA;EACA,aAAa,OAAO,YAAY;EAChC;EACA;EACA;EACA;EACA;CACD;AACF;;;;;;AAwaD,SAAS,sBAAsBK,QAAwB;AACrD,QAAQ,UAAU,MAAO;AAC1B;;;;;;;;;;;;AAaD,SAAS,aAAaC,cAAsC;CAC1D,MAAM,MAAM,aAAa,MAAM,EAAE;AAGjC,KAAI,IAAI,UAAU,GAChB,QAAO;EACL,WAAW;EACX,WAAW;EACX,KAAK;EACL,aAAa;EACb,OAAO;CACR;AAGH,KAAI,IAAI,SAAS,IACf,OAAM,IAAI,OAAO,iEAAiE,IAAI,OAAO;CAM/F,MAAM,aAAa,IAAI,IAAI,MAAM,IAAI,GAAG,CAAC;CACzC,MAAM,aAAa,IAAI,IAAI,MAAM,IAAI,IAAI,CAAC;CAC1C,MAAM,MAAM,QAAQ,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC,EAAE;CAC9C,MAAM,cAAc,QAAQ,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC,EAAE;CACtD,MAAM,SAAS,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC;AAEvC,QAAO;EACL;EACA;EACA;EACA;EACA;CACD;AACF;;;;ACz+BD,eAAsB,mBACpBC,QAC8B;CAC9B,MAAM,EAAE,QAAQ,aAAa,SAAS,GAAG;CAEzC,MAAM,OAAO,MAAM,gBAAgB;EAAE;EAAQ;CAAa,EAAC;AAC3D,KAAI,KAAK,KACP,OAAM,IAAI,cAAc;CAG1B,MAAM,WAAW,eAAe,SAAS,KAAK,YAAY;CAC1D,MAAM,WAAW,eAAe,SAAS,KAAK,YAAY;AAC1D,MAAK,aAAa,SAChB,OAAM,IAAI,sBAAsB,SAAS,KAAK,aAAa,KAAK;CAGlE,MAAM,aAAa;AACnB,QAAO;EACL;EACA,UAAU,aAAa,KAAK,cAAc,KAAK;EAC/C,KAAK,KAAK;EACV;CACD;AACF;;;;ACjCD,MAAMC,kBAAgB;CACpB,aAAa;CACb,gBAAgB;CAChB,WAAW;AACZ;AAaD,eAAsB,4BACpBC,QAC6C;CAC7C,MAAM,EAAE,QAAQ,aAAa,SAAS,SAAS,UAAU,aAAa,aAAa,WAAW,GAC5F;AAEF,KAAI;EACF,MAAM,oBAAoB,eAAgB,MAAM,OAAO,gBAAgB;EACvE,MAAM,cAAc,aAAa;GAAE;GAAQ,aAAa;EAAmB,EAAC;AAC5E,EAAK,YAAY,MAAM,aAAgB;EAEvC,MAAM,QAAQ,MAAM,mBAAmB;GAAE;GAAQ;GAAa;EAAS,EAAC;EAExE,MAAM,QAAQ,MAAM,eAAe;GACjC;GACA;GACA,SAAS,MAAM;GACf,UAAU,MAAM;GAChB,KAAK,MAAM;GACX;GACA;GACA,aAAa;GACb;EACD,EAAC;AAEF,OAAK,MACH,OAAM,IAAI,cAAc;EAG1B,MAAM,QAAQ,MAAM;AAEpB,SAAO;GACL,SAAS;GACT,MAAM;IACJ,WAAW,MAAM;IACjB,kBAAkB,MAAM;IACxB,YAAY,MAAM;IAClB,UAAU,MAAM;IAChB,aAAa,MAAM;GACpB;GACD,aAAa,MAAM;GACnB;EACD;CACF,SAAQ,OAAO;AACd,SAAO;GACL,SAAS;GACT,OACE,iBAAiB,gBACb,QACA,IAAI,cACF,iBAAiB,QAAQ,MAAM,UAAU,gBACzC,iBAAiB,QAAQ;GAEjC,OAAOD;EACR;CACF;AACF;AAaD,eAAsB,6BACpBE,QAC8C;CAC9C,MAAM,EAAE,QAAQ,aAAa,SAAS,SAAS,WAAW,aAAa,aAAa,WAAW,GAC7F;AAEF,KAAI;EACF,MAAM,oBAAoB,eAAgB,MAAM,OAAO,gBAAgB;EACvE,MAAM,cAAc,aAAa;GAAE;GAAQ,aAAa;EAAmB,EAAC;AAC5E,EAAK,YAAY,MAAM,aAAgB;EAEvC,MAAM,QAAQ,MAAM,mBAAmB;GAAE;GAAQ;GAAa;EAAS,EAAC;EAExE,MAAM,QAAQ,MAAM,gBAAgB;GAClC;GACA;GACA,SAAS,MAAM;GACf,UAAU,MAAM;GAChB,KAAK,MAAM;GACX;GACA;GACA,aAAa;GACb;EACD,EAAC;AAEF,OAAK,MACH,OAAM,IAAI,cAAc;EAG1B,MAAM,QAAQ,MAAM;AAEpB,SAAO;GACL,SAAS;GACT,MAAM;IACJ,UAAU,MAAM;IAChB,iBAAiB,MAAM;IACvB,YAAY,MAAM;IAClB,UAAU,MAAM;IAChB,aAAa,MAAM;GACpB;GACD,aAAa,MAAM;GACnB;EACD;CACF,SAAQ,OAAO;AACd,SAAO;GACL,SAAS;GACT,OACE,iBAAiB,gBACb,QACA,IAAI,cACF,iBAAiB,QAAQ,MAAM,UAAU,gBACzC,iBAAiB,QAAQ;GAEjC,OAAOF;EACR;CACF;AACF;;;;;;;;;;;;;;;;ACtID,SAAgB,sBAAsBG,aAQpC;CACA,MAAM,eAAe,eAAgB,MAAM,QAAQ;CACnD,MAAM,mBAAoB,eAAe,OAAQ;CACjD,MAAM,mBAAoB,eAAe,OAAQ;CAGjD,IAAI,aAAc,eAAe,OAAQ;AAEzC,KAAI,aAAa,UACf,cAAa,aAAa;CAI5B,MAAM,kBAAmB,eAAe,OAAQ;CAGhD,MAAM,cAAe,eAAe,QAAU,MAAM,OAAO;CAG3D,MAAM,aAAa,eAAe,SAAS;AAE3C,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;CACD;AACF;;;;AAKD,SAAgB,sBAAsBC,OAAgD;CAGpF,IAAI,QAAQ,SAAU,MAAM,QAAQ;CACpC,IAAI,OAAO,SAAS;AAGpB,KAAI,SAAS,MAAM,KACjB,SAAQ,SAAS,MAAM;AAGzB,KAAI,QAAQ,MAAM,KAChB,QAAO,QAAQ,MAAM;AAGvB,QAAO;EAAE;EAAO;CAAM;AACvB;;;;;;;AAoBD,SAAgB,oBAAoBC,MAA8B;CAChE,MAAMC,SAA0B,CAAE;AAGlC,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,YAAY;GAChB,aAAa,IAAI,eAAe;GAChC,WAAY,IAAI,aACd;GACF,iBAAiB,IAAI,mBAAoB;GACzC,UAAU,OAAO,IAAI,YAAY,EAAE;EACpC;AAED,MAAI;GAEF,MAAM,YAAY,eAAe;IAC/B,KAAK;IACL,MAAM,IAAI;IACV,QAAQ,IAAI;GACb,EAAC;AAEF,OAAI,UAAU,cAAc,gBAAgB;IAC1C,MAAM,OAAO,UAAU;IAKvB,MAAM,UAAU,sBAAsB,KAAK,YAAY;AACvD,WAAO,KAAK;KACV,MAAM;KACN,GAAG;KACH,WAAW,KAAK;KAChB,SAAS,KAAK;KACd,cAAc,QAAQ;KACtB,kBAAkB,QAAQ;KAC1B,kBAAkB,QAAQ;KAC1B,YAAY,QAAQ;KACpB,iBAAiB,QAAQ;KACzB,aAAa,QAAQ;KACrB,YAAY,QAAQ;IACrB,EAAC;GACH,WAAU,UAAU,cAAc,eAAe;IAChD,MAAM,OAAO,UAAU;AAMvB,WAAO,KAAK;KACV,MAAM;KACN,GAAG;KACH,WAAW,KAAK;KAChB,SAAS,KAAK;KACd,cAAc,KAAK;KACnB,aAAa;MACX,KAAK,YAAY,MAAM;MACvB,KAAK,YAAY,MAAM;MACvB,KAAK,YAAY,MAAM;MACvB,KAAK,YAAY,MAAM;KACxB;IACF,EAAC;GACH,WAAU,UAAU,cAAc,qBAAqB;IACtD,MAAM,OAAO,UAAU;IAKvB,MAAM,EAAE,OAAO,MAAM,GAAG,sBAAsB,KAAK,aAAa;AAChE,WAAO,KAAK;KACV,MAAM;KACN,GAAG;KACH,YAAY,KAAK;KACjB,YAAY,KAAK;KACjB,cAAc;KACd,cAAc;IACf,EAAC;GACH,WAAU,UAAU,cAAc,mBAAmB;IACpD,MAAM,OAAO,UAAU;IAMvB,MAAM,EAAE,OAAO,MAAM,GAAG,sBAAsB,KAAK,YAAY;AAC/D,WAAO,KAAK;KACV,MAAM;KACN,GAAG;KACH,WAAW,KAAK;KAChB,MAAM,KAAK;KACX,SAAS,KAAK;KACd,cAAc;KACd,cAAc;IACf,EAAC;GACH,WAAU,UAAU,cAAc,kBAAkB;IACnD,MAAM,OAAO,UAAU;IAMvB,MAAM,EAAE,OAAO,MAAM,GAAG,sBAAsB,KAAK,eAAe;AAClE,WAAO,KAAK;KACV,MAAM;KACN,GAAG;KACH,MAAM,KAAK;KACX,SAAS,KAAK;KACd,UAAU,KAAK;KACf,gBAAgB;KAChB,gBAAgB;IACjB,EAAC;GACH;EACF,QAAO;AAEN,OAAI;IACF,MAAM,kBAAkB,eAAe;KACrC,KAAK;KACL,MAAM,IAAI;KACV,QAAQ,IAAI;IACb,EAAC;AAEF,QAAI,gBAAgB,cAAc,WAAW;KAC3C,MAAM,OAAO,gBAAgB;AAM7B,YAAO,KAAK;MACV,MAAM;MACN,GAAG;MACH,QAAQ,KAAK;MACb,OAAO,KAAK;MACZ,QAAQ,KAAK;MACb,QAAQ,KAAK;KACd,EAAC;IACH,WAAU,gBAAgB,cAAc,YAAY;KACnD,MAAM,OAAO,gBAAgB;AAO7B,YAAO,KAAK;MACV,MAAM;MACN,GAAG;MACH,QAAQ,KAAK;MACb,UAAU,KAAK;MACf,OAAO,KAAK;MACZ,QAAQ,KAAK;MACb,QAAQ,KAAK;KACd,EAAC;IACH;GACF,QAAO,CAEP;EACF;CACF;AAED,QAAO;AACR;;;;;;;;AASD,SAAgB,eAAeC,QAAsBC,MAAsB;AACzE,QAAO;EACL;EACA,MAAM,OAAOC,kBAA+C;GAC1D,MAAM,UAAU,MAAM,OAAO,0BAA0B;IACrD;IACA,eAAe,2BAA8B,OAAO,cAAc;GACnE,EAAC;GAEF,MAAM,SAAS,oBAAoB,QAAQ,KAAK;AAEhD,UAAO;IACL,MAAM,QAAQ;IACd,aAAa,QAAQ;IACrB,WAAW,QAAQ;IACnB,SAAS,QAAQ;IACjB,QAAQ,QAAQ,WAAW,YAAY,YAAY;IACnD;GACD;EACF;CACF;AACF;;;;;;;;;;;AAoED,eAAsB,YAAYC,QAA8C;CAC9E,MAAM,EAAE,QAAQ,cAAc,SAAS,SAAS,KAAK,cAAc,MAAM,OAAO,aAAa,GAC3F;CAEF,MAAM,cAAc,aAAa;AAEjC,KAAI,aAAa;EAGf,MAAM,OAAO,mBAAmB;GAAE;GAAK;GAAc;EAAM,EAAC;EAG5D,MAAM,mBAAmB,aAAa,WAAW;EACjD,MAAM,UAAU,MAAM,aAAa,0BAA0B;GAC3D,SAAS;GACT,IAAI;GACJ,OAAO,aAAa;GACpB;GACA,GAAI,oBAAuB,EAAE,MAAO;GACpC,GAAI,aAAa,2BAA8B,EAAE,cAAc,YAAY,aAAc;GACzF,GAAI,aAAa,mCAAsC,EACrD,sBAAsB,YAAY,qBACnC;GACD,GAAI,aAAa,kBAAqB,EAAE,KAAK,YAAY,IAAK;GAC9D,GAAI,aAAa,oBAAuB,EAAE,OAAO,OAAO,YAAY,MAAM,CAAE;EAC7E,EAAC;EAEF,MAAM,WAAW,MAAM,aAAa,gBAAgB;GAClD,GAAG;GACH,SAAS;EACV,EAA8D;EAE/D,MAAMC,SAAO,MAAM,YAAY,UAAU,SAAS;AAClD,SAAO,eAAe,QAAQA,OAAK;CACpC;CAGD,MAAMC,eAAwC,CAAE;AAChD,KAAI,aAAa,wBACf,cAAa,eAAe,YAAY;AAE1C,KAAI,aAAa,gCACf,cAAa,uBAAuB,YAAY;AAElD,KAAI,aAAa,iBACf,cAAa,QAAQ,OAAO,YAAY,MAAM;CAMhD,MAAM,kBAAkB,aAAa,WAAW;AAIhD,KAAI,aAAa,eACf,cAAa,MAAM,YAAY;MAC1B;EACL,MAAM,YAAY,MAAM,OAAO,oBAAoB;GACjD;GACA;GACA;GACA;GACA,SAAS;GACT,GAAI,oBAAuB,EAAE,MAAO;EACrC,EAAqD;AACtD,eAAa,MAAO,YAAY,OAAQ;CACzC;CAED,MAAM,OAAO,MAAM,aAAa,cAAc;EAC5C;EACA;EACA;EACA;EACA,SAAS;EACT,OAAO,aAAa;EACpB,GAAI,oBAAuB,EAAE,MAAO;EACpC,GAAG;CACJ,EAAC;AAEF,QAAO,eAAe,QAAQ,KAAK;AACpC;;;;;;;ACvZD,MAAaC,kBAA2B;;;;;;;;AASxC,MAAaC,uBAA2D;CAEtE,GAAG;EACD,iBAAiB;EACjB,UAAU;EACV,aAAa;EACb,iBAAiB;EACjB,SAAS;CACV;CACD,MAAM;EACJ,iBAAiB;EACjB,UAAU;EACV,aAAa;EACb,iBAAiB;EACjB,SAAS;CACV;AACF;;;;;;;;;;AAWD,SAAgB,sBACdC,SACAC,WACoB;CACpB,MAAM,OAAO,qBAAqB,OAAO,QAAQ;CAEjD,MAAMC,SAAsC;EAC1C,GAAG;EACH,GAAG;EACH,SAAS,WAAW,WAAW,MAAM,WAAW;CACjD;AAED,KACE,OAAO,8BACP,OAAO,uBACP,OAAO,0BACP,OAAO,8BACP,OAAO,mBAEP,OAAM,IAAI,sBAAsB;AAGlC,QAAO;AACR;;;;AC1ED,MAAMC,6BAA2B;AAiBjC,eAAsB,uBACpBC,QACmB;CACnB,MAAM,EACJ,QACA,cACA,SACA,aACA,SACA,SACA,UACA,aACA,UACA,WACA,aACA,WACD,GAAG;AAEJ,KAAI,yBAA4B,eAAe,WAAW,QAAQ,CAChE,OAAM,IAAI,cAAc;CAG1B,MAAM,WAAW,sBAAsB,SAAS,UAAU;CAC1D,MAAM,QAAQ,MAAM,mBAAmB;EAAE;EAAQ;EAAa;CAAS,EAAC;CAExE,MAAM,QAAQ,MAAM,eAAe;EACjC;EACA;EACA,SAAS,MAAM;EACf,UAAU,MAAM;EAChB,KAAK,MAAM;EACX;EACA;EACA;CACD,EAAC;AAEF,MAAK,MACH,OAAM,IAAI,cAAc;CAG1B,MAAM,mBACJ,aAAa,MAAM,aAAa,EAAE,OAAQ,EAAC,EAAE,iBAAiBD;CAEhE,MAAM,EAAE,MAAM,OAAO,GAAG,uBAAuB;EAC7C,SAAS,MAAM;EACf,UAAU,MAAM;EAChB,KAAK,MAAM;EACX;EACA,kBAAkB,MAAM;EACxB,UAAU;CACX,EAAC;AAEF,QAAO,YAAY;EACjB;EACA;EACA;EACA,SAAS,SAAS;EAClB,KAAK;EACL,cAAc;EACd;EACA;EACA;CACD,EAAC;AACH;AAiBD,eAAsB,wBACpBE,QACmB;CACnB,MAAM,EACJ,QACA,cACA,SACA,aACA,SACA,SACA,WACA,aACA,UACA,WACA,aACA,WACD,GAAG;AAEJ,KAAI,yBAA4B,eAAe,WAAW,QAAQ,CAChE,OAAM,IAAI,cAAc;CAG1B,MAAM,WAAW,sBAAsB,SAAS,UAAU;CAC1D,MAAM,QAAQ,MAAM,mBAAmB;EAAE;EAAQ;EAAa;CAAS,EAAC;CAExE,MAAM,QAAQ,MAAM,gBAAgB;EAClC;EACA;EACA,SAAS,MAAM;EACf,UAAU,MAAM;EAChB,KAAK,MAAM;EACX;EACA;EACA;CACD,EAAC;AAEF,MAAK,MACH,OAAM,IAAI,cAAc;CAG1B,MAAM,mBACJ,aAAa,MAAM,aAAa,EAAE,OAAQ,EAAC,EAAE,iBAAiBF;CAEhE,MAAM,EAAE,MAAM,OAAO,GAAG,+BAA+B;EACrD,SAAS,MAAM;EACf,UAAU,MAAM;EAChB,KAAK,MAAM;EACX;EACA,iBAAiB,MAAM;EACvB,UAAU;CACX,EAAC;AAEF,QAAO,YAAY;EACjB;EACA;EACA;EACA,SAAS,SAAS;EAClB,KAAK;EACL,cAAc;EACd;EACA;EACA;CACD,EAAC;AACH;;;;;AClJD,MAAa,UAAU;;AAEvB,MAAa,uBAAuB;;AAEpC,MAAa,aAAa;;AAE1B,MAAa,WAAW;;AAExB,MAAa,OAAO;;AAEpB,MAAa,wBAAwB;;AAErC,MAAa,QAAQ;;AAGrB,MAAM,aAAa;AAEnB,MAAMG,iBAAe,MAAM,QAAQ;AAEnC,MAAM,oBAAoB;CACxB;EAAE,MAAM;EAAa,MAAM;CAAW;CACtC;EAAE,MAAM;EAAa,MAAM;CAAW;CACtC;EAAE,MAAM;EAAO,MAAM;CAAU;CAC/B;EAAE,MAAM;EAAe,MAAM;CAAS;CACtC;EAAE,MAAM;EAAS,MAAM;CAAW;AACnC;AAED,MAAM,4BAA4B,CAChC;CACE,MAAM;CACN,YAAY;EACV;GAAE,MAAM;GAAW,MAAM;GAAS,YAAY;EAAmB;EACjE;GAAE,MAAM;GAAc,MAAM;EAAQ;EACpC;GAAE,MAAM;GAAY,MAAM;EAAW;EACrC;GAAE,MAAM;GAAoB,MAAM;EAAW;EAC7C;GAAE,MAAM;GAAY,MAAM;EAAS;CACpC;AACF,CACF;AAED,MAAM,6BAA6B,CACjC;CACE,MAAM;CACN,YAAY;EACV;GAAE,MAAM;GAAW,MAAM;GAAS,YAAY;EAAmB;EACjE;GAAE,MAAM;GAAc,MAAM;EAAQ;EACpC;GAAE,MAAM;GAAa,MAAM;EAAW;EACtC;GAAE,MAAM;GAAmB,MAAM;EAAW;EAC5C;GAAE,MAAM;GAAY,MAAM;EAAS;CACpC;AACF,CACF;AAED,MAAM,oBAAoB,CACxB;CAAE,MAAM;CAAY,MAAM;AAAW,GACrC;CAAE,MAAM;CAAU,MAAM;AAAW,CACpC;AAGD,MAAM,qBAAqB;CACzB;EAAE,MAAM;EAAY,MAAM;CAAW;CACrC;EAAE,MAAM;EAAa,MAAM;CAAW;CACtC;EAAE,MAAM;EAAU,MAAM;CAAW;AACpC;AAID,MAAM,iBAAiB;CACrB;EAAE,MAAM;EAAS,MAAM;CAAW;CAClC;EAAE,MAAM;EAAa,MAAM;CAAW;CACtC;EAAE,MAAM;EAAa,MAAM;CAAW;AACvC;AAED,SAAS,cAAcC,QAAsB;AAC3C,KAAI,SAAS,MAAM,SAASD,cAC1B,OAAM,IAAI,0BAA0B;AAEvC;;;;;AAMD,SAAS,oBAAoBE,WAAyB;AACpD,QAAO,oBAAoB,gBAAgB;EAAC;EAAa;EAAW;CAAG,EAAC;AACzE;;;;;;;;;;;;;;;AAgBD,SAAS,gBACPC,UACAC,WACAC,cACAC,aACgC;AAChC,KAAI,aAAa,aAAa;AAC5B,MAAI,qBACF,OAAM,IAAI;AAEZ,SAAO;GACL,QAAQ;GACR,OAAO,oBAAoB,oBAAoB;IAAC;IAAa;IAAW;GAAa,EAAC;EACvF;CACF;AACD,QAAO;EACL,QAAQ;EACR,OAAO,oBAAoB,mBAAmB,CAAC,UAAU,WAAY,EAAC;CACvE;AACF;;;;;;;;;;;AAwCD,SAAgB,uBAAuBC,MAGrC;CACA,MAAM,EACJ,SACA,YACA,UACA,kBACA,SACA,UACA,UACA,WACA,WAAW,MACZ,GAAG;AAEJ,eAAc,SAAS;AACvB,eAAc,iBAAiB;CAE/B,MAAM,YAAY,oBAAoB,2BAA2B,CAC/D;EACE,SAAS;GACP,WAAW,QAAQ;GACnB,WAAW,QAAQ;GACnB,KAAK,OAAO,QAAQ,IAAI;GACxB,aAAa,OAAO,QAAQ,YAAY;GACxC,OAAO,QAAQ;EAChB;EACD;EACA;EACA;EACA;CACD,CACF,EAAC;CAKF,MAAM,cAAc,oBAAoB,mBAAmB,CAAC,SAAS,QAAS,EAAC;CAC/E,MAAM,OAAO,gBAAgB,UAAU,WAAW,YAAY,iBAAiB;CAE/E,MAAM,UAAU,aACd;EAAC;EAAS;EAAS;CAAQ,GAC3B;EAAC;EAAsB;EAAY,KAAK;CAAO,EAChD;CAED,MAAM,UAAU,oBACd,CACE;EAAE,MAAM;EAAW,MAAM;CAAS,GAClC;EAAE,MAAM;EAAU,MAAM;CAAW,CACpC,GACD,CAAC,SAAS;EAAC;EAAW;EAAa,KAAK;CAAM,CAAC,EAChD;CAGD,MAAM,WAAW,aAAa,CAAC,OAAQ,GAAE,CAAC,OAAQ,EAAC;CACnD,MAAM,QAAQ,YAAY,cAAc,WAAW;AAEnD,QAAO;EAAE,MAAM;GAAC;GAAU,CAAC,OAAQ;GAAE;EAAS;EAAW;CAAO;AACjE;;;;;;;AAQD,SAAgB,2BAA2BA,MAGzC;CACA,MAAM,EAAE,MAAM,aAAa,OAAO,GAAG,uBAAuB,KAAK;CACjE,MAAM,OAAO,mBAAmB;EAC9B,KAAK;EACL,cAAc;EACd,MAAM;CACP,EAAC;AACF,QAAO;EAAE;EAAM;CAAO;AACvB;;;;;;;;;;;AAwCD,SAAgB,+BAA+BC,MAG7C;CACA,MAAM,EACJ,SACA,YACA,WACA,iBACA,SACA,UACA,UACA,WACA,WAAW,MACZ,GAAG;AAEJ,eAAc,UAAU;AACxB,eAAc,gBAAgB;CAE9B,MAAM,YAAY,oBAAoB,4BAA4B,CAChE;EACE,SAAS;GACP,WAAW,QAAQ;GACnB,WAAW,QAAQ;GACnB,KAAK,OAAO,QAAQ,IAAI;GACxB,aAAa,OAAO,QAAQ,YAAY;GACxC,OAAO,QAAQ;EAChB;EACD;EACA;EACA;EACA;CACD,CACF,EAAC;CAKF,MAAM,cAAc,oBAAoB,mBAAmB,CAAC,SAAS,eAAgB,EAAC;CACtF,MAAM,OAAO,gBAAgB,UAAU,WAAW,WAAW,UAAU;CAEvE,MAAM,UAAU,aACd;EAAC;EAAS;EAAS;CAAQ,GAC3B;EAAC;EAAuB;EAAY,KAAK;CAAO,EACjD;CAED,MAAM,UAAU,oBACd,CACE;EAAE,MAAM;EAAW,MAAM;CAAS,GAClC;EAAE,MAAM;EAAU,MAAM;CAAW,CACpC,GACD,CAAC,SAAS;EAAC;EAAW;EAAa,KAAK;CAAM,CAAC,EAChD;CAED,MAAM,aAAa,YAAY;CAK/B,MAAMC,cAAwB,CAAC,OAAQ;CACvC,MAAMC,SAAgB,CAAC,OAAQ;AAC/B,KAAI,YAAY;AACd,cAAY,KAAK,MAAM;AACvB,SAAO,KAAK,oBAAoB,UAAU,CAAC;CAC5C;CAED,MAAM,WAAW,aACf,YAAY,IAAI,MAAM,QAAQ,EAC9B,YACD;CACD,MAAM,QAAQ,aAAa,kBAAkB;AAE7C,QAAO;EAAE,MAAM;GAAC;GAAU;GAAQ;EAAS;EAAW;CAAO;AAC9D;;;;;;;AAQD,SAAgB,mCAAmCF,MAGjD;CACA,MAAM,EAAE,MAAM,aAAa,OAAO,GAAG,+BAA+B,KAAK;CACzE,MAAM,OAAO,mBAAmB;EAC9B,KAAK;EACL,cAAc;EACd,MAAM;CACP,EAAC;AACF,QAAO;EAAE;EAAM;CAAO;AACvB;;;;ACxYD,MAAM,oBAAoB,SAAS,CACjC,8HACD,EAAC;;;;;AA+iBF,MAAM,oBAAoB,mBACxB,kBAAkB,KAAK,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,SAAS,WAAW,CAC9E,CAAC,MAAM,EAAE;AAEV,MAAM,yBAAyB,mBAC7B,kBAAkB,KAAK,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,SAAS,eAAe,CAClF,CAAC,MAAM,EAAE;;;;;AC3iBV,MAAMG,QAAM,MAAM;AAClB,MAAM,OAAO,MAAM;;;;ACpBnB,MAAa,SAAS,OAAO,eAAe;AA8B5C,MAAa,wBAAwB,OACnC,iFACD;AAMD,MAAM,qBAAqB;AAC3B,MAAM,aAAa;AACnB,MAAM,qBAAqB,qBAAqB;AAChD,MAAM,aAAa;AACnB,MAAM,uBAAuB,qBAAqB;AAClD,MAAM,eAAe;AACrB,MAAM,0BAA0B,uBAAuB;AACvD,MAAM,kBAAkB;AACxB,MAAM,4BAA4B,0BAA0B;AAC5D,MAAM,oBAAoB;AAC1B,MAAM,sBAAsB,4BAA4B;AACxD,MAAM,cAAc;AACpB,MAAM,qBAAqB,sBAAsB;AACjD,MAAM,aAAa;AACnB,MAAM,WAAW,qBAAqB;;;;ACoKtC,MAAM,sBAAsB,WAAW;CAAE,KAAK;CAAmB,MAAM;AAAgB,EAAC;AACxF,MAAM,qBAAqB,WAAW;CAAE,KAAK;CAAmB,MAAM;AAAe,EAAC;;;;AC9MtF,MAAM,gBAAgB,MAAM,OAAO;AACnC,MAAM,MAAM,MAAM;AAClB,MAAM,eAAe,MAAM,QAAQ;;;;ACFnC,MAAMC,kBAAgB,MAAM,QAAQ;;;;;;;;AC0BpC,MAAM,eAAe,CACnB;CACE,MAAM;CACN,MAAM;CACN,QAAQ,CAAC;EAAE,MAAM;EAAQ,MAAM;CAAW,CAAC;CAC3C,SAAS,CAAC;EAAE,MAAM;EAAW,MAAM;CAAW,CAAC;CAC/C,iBAAiB;AAClB,GAED,GAAG,iBACJ;;;;AClCD,MAAM,gBAAgB,MAAM,QAAQ;;;;;;;;ACZpC,MAAa,aAAa,CACxB;CACE,MAAM;CACN,MAAM;CACN,iBAAiB;CACjB,QAAQ;EACN;GAAE,MAAM;GAAS,MAAM;EAAW;EAClC;GAAE,MAAM;GAAW,MAAM;EAAW;EACpC;GAAE,MAAM;GAAU,MAAM;EAAW;EACnC;GAAE,MAAM;GAAc,MAAM;EAAU;CACvC;CACD,SAAS,CAAE;AACZ,GACD;CACE,MAAM;CACN,MAAM;CACN,iBAAiB;CACjB,QAAQ;EACN;GAAE,MAAM;GAAQ,MAAM;EAAW;EACjC;GAAE,MAAM;GAAS,MAAM;EAAW;EAClC;GAAE,MAAM;GAAW,MAAM;EAAW;CACrC;CACD,SAAS;EACP;GAAE,MAAM;GAAU,MAAM;EAAW;EACnC;GAAE,MAAM;GAAc,MAAM;EAAU;EACtC;GAAE,MAAM;GAAS,MAAM;EAAU;CAClC;AACF,CACF;;;;;ACLD,MAAM,eAAe,MAAM,QAAQ;;AAEnC,MAAM,6BAA6B;;AAEnC,MAAM,cAAc,MAAM,OAAO;;;;;AAMjC,eAAsB,oBACpBC,QAC+B;CAC/B,MAAM,EAAE,QAAQ,SAAS,SAAS,OAAO,QAAQ,WAAW,GAAG;CAC/D,MAAM,EAAE,SAAS,iBAAiB,GAAG,sBAAsB,SAAS,UAAU;CAE9E,MAAM,CAAC,gBAAgB,kBAAkB,UAAU,GAAG,MAAM,QAAQ,IAAI;EACtE,OAAO,aAAa;GAClB,SAAS;GACT,KAAK;GACL,cAAc;GACd,MAAM,CAAC,OAAO,OAAQ;EACvB,EAAC;EACF,OAAO,aAAa;GAClB,SAAS;GACT,KAAK;GACL,cAAc;GACd,MAAM;IAAC;IAAO;IAAS;GAAgB;EACxC,EAAC;EACF,aAAa,EAAE,OAAQ,EAAC;CACzB,EAAC;CAEF,MAAM,CAAC,eAAe,kBAAkB,GAAG;CAE3C,MAAM,qBAAqB,iBAAiB;CAC5C,MAAM,uBACJ,gBAAgB,UAAU,OAAO,kBAAkB,IAAI,UAAU;AAEnE,QAAO;EACL;EACA;EACA;EACA;EACA,mBAAmB,OAAO,kBAAkB;CAC7C;AACF;;;;AAKD,eAAsB,uBACpBC,QACmB;CACnB,MAAM,EACJ,QACA,cACA,SACA,SACA,SACA,SAAS,YACT,aACA,WACD,GAAG;CACJ,MAAM,EAAE,SAAS,GAAG,sBAAsB,SAAS,UAAU;AAE7D,QAAO,YAAY;EACjB;EACA;EACA;EACA,SAAS;EACT,KAAK;EACL,cAAc;EACd,MAAM,CAAC,SAAS,MAAO;EACvB;CACD,EAAC;AACH;;;;AAKD,eAAsB,8BACpBA,QACoB;CACpB,MAAM,SAAS,MAAM,uBAAuB,OAAO;AACnD,QAAO,OAAO,MAAM;AACrB;;;;AAKD,eAAsB,wBACpBC,QACmB;CACnB,MAAM,EACJ,QACA,cACA,SACA,SACA,SACA,SAAS,aACT,YACA,aACA,WACD,GAAG;CACJ,MAAM,EAAE,SAAS,iBAAiB,GAAG,sBAAsB,SAAS,UAAU;CAE9E,MAAM,qBACJ,eAAe,MAAM,aAAa,EAAE,OAAQ,EAAC,EAAE,iBAAiB;CAClE,MAAM,mBAAmB,qBAAqB,aAAa,aAAa;AAExE,QAAO,YAAY;EACjB;EACA;EACA;EACA,SAAS;EACT,KAAK;EACL,cAAc;EACd,MAAM;GAAC;GAAS;GAAiB;GAAQ;EAAiB;EAC1D;CACD,EAAC;AACH;;;;AAKD,eAAsB,+BACpBA,QACoB;CACpB,MAAM,SAAS,MAAM,wBAAwB,OAAO;AACpD,QAAO,OAAO,MAAM;AACrB;;;;;;;;;;;;;ACpJD,MAAM,yBAAyB;CAC7B,MAAM;CACN,MAAM;CACN,YAAY;EACV;GACE,MAAM;GACN,MAAM;GACN,YAAY;IACV;KAAE,MAAM;KAAa,MAAM;IAAW;IACtC;KAAE,MAAM;KAAa,MAAM;IAAW;IACtC;KAAE,MAAM;KAAO,MAAM;IAAU;IAC/B;KAAE,MAAM;KAAe,MAAM;IAAS;IACtC;KAAE,MAAM;KAAS,MAAM;IAAW;GACnC;EACF;EACD;GAAE,MAAM;GAAc,MAAM;EAAQ;EACpC;GAAE,MAAM;GAAe,MAAM;EAAW;EACxC;GAAE,MAAM;GAAY,MAAM;EAAS;CACpC;AACF;AAED,MAAa,cAAc,CACzB;CACE,MAAM;CACN,MAAM;CACN,iBAAiB;CACjB,QAAQ,CAAC,sBAAuB;CAChC,SAAS,CACP;EAAE,MAAM;EAAa,MAAM;CAAW,GACtC;EAAE,MAAM;EAAe,MAAM;CAAW,CACzC;AACF,GACD;CACE,MAAM;CACN,MAAM;CACN,iBAAiB;CACjB,QAAQ,CAAC,sBAAuB;CAChC,SAAS,CACP;EAAE,MAAM;EAAY,MAAM;CAAW,GACrC;EAAE,MAAM;EAAe,MAAM;CAAW,CACzC;AACF,CACF;;;;;;;;;ACRD,eAAsB,iBAAiBC,QAA4D;CACjG,MAAM,EAAE,QAAQ,aAAa,SAAS,SAAS,aAAa,GAAG;CAE/D,MAAM,OAAO,MAAM,QAAQ;EAAE;EAAQ;EAAa;EAAS;CAAa,EAAC;CACzE,MAAM,EAAE,SAAS,GAAG;CAEpB,MAAM,cAAc,eAAe,SAAS,QAAQ,UAAU;CAC9D,MAAM,cAAc,eAAe,SAAS,QAAQ,UAAU;AAC9D,MAAK,gBAAgB,YACnB,OAAM,IAAI,sBAAsB,SAAS,QAAQ,WAAW,QAAQ;CAGtE,MAAM,aAAa;CACnB,MAAM,WAAW,aAAa,QAAQ,YAAY,QAAQ;CAC1D,MAAM,aAAa,aAAa,KAAK,qBAAqB,KAAK;AAE/D,QAAO;EACL;EACA;EACA;EACA,kBAAkB,WAAW;EAC7B,gBAAgB,WAAW;CAC5B;AACF;;;;AC9CD,MAAMC,oBAAkB;AACxB,MAAMC,iBAAe,MAAM,QAAQ;;AAGnC,SAAS,kBAAkBC,aAA2B;AACpD,KAAI,cAAc,MAAM,cAAcF,kBACpC,OAAM,IAAI,eAAe,sBAAsB,YAAY;AAE9D;AAED,MAAM,gBAAgB;CACpB,aAAa;CACb,gBAAgB;CAChB,WAAW;AACZ;;;;;;;;AASD,eAAsB,0BACpBG,QAC6C;CAC7C,MAAM,EAAE,QAAQ,aAAa,SAAS,SAAS,UAAU,aAAa,aAAa,WAAW,GAC5F;AAEF,KAAI;AACF,MAAI,WAAW,MAAM,WAAWF,cAC9B,OAAM,IAAI,eAAe,WAAW,SAAS;AAE/C,oBAAkB,YAAY;EAE9B,MAAM,oBAAoB,eAAgB,MAAM,OAAO,gBAAgB;EACvE,MAAM,cAAc,aAAa;GAAE;GAAQ,aAAa;EAAmB,EAAC;EAE5E,MAAM,EAAE,UAAU,GAAG,sBAAsB,SAAS,UAAU;AAC9D,MAAI,aAAa,YACf,OAAM,IAAI,uBAAuB;EAGnC,MAAM,QAAQ,MAAM,iBAAiB;GACnC;GACA;GACA;GACA;GACA,aAAa;EACd,EAAC;EAEF,MAAM,EAAE,QAAQ,GAAG,MAAM,OAAO,iBAAiB;GAC/C,SAAS;GACT,KAAK;GACL,cAAc;GACd,aAAa;GACb,MAAM,CACJ;IACE,SAAS;KACP,WAAW,MAAM,QAAQ;KACzB,WAAW,MAAM,QAAQ;KACzB,KAAK,OAAO,MAAM,QAAQ,IAAI;KAC9B,aAAa,OAAO,MAAM,QAAQ,YAAY;KAC9C,OAAO,MAAM,QAAQ;IACtB;IACD,YAAY,MAAM;IAClB,aAAa;IACb,UAAU;GACX,CACF;EACF,EAAC;EAEF,MAAM,CAAC,WAAW,YAAY,GAAG;EACjC,MAAM,mBAAoB,aAAaD,oBAAkB,eAAgBA;EAEzE,MAAM,QAAQ,MAAM;AAEpB,SAAO;GACL,SAAS;GACT,MAAM;IACJ;IACA;IACA,YAAY,MAAM;IAClB,UAAU,MAAM;IAChB,SAAS,MAAM;IACf;GACD;GACD;GACA;EACD;CACF,SAAQ,OAAO;AACd,SAAO;GACL,SAAS;GACT,OACE,iBAAiB,gBACb,QACA,IAAI,cACF,iBAAiB,QAAQ,MAAM,UAAU,gBACzC,iBAAiB,QAAQ;GAEjC,OAAO;EACR;CACF;AACF;;;;;;;;AASD,eAAsB,2BACpBI,QAC8C;CAC9C,MAAM,EAAE,QAAQ,aAAa,SAAS,SAAS,WAAW,aAAa,aAAa,WAAW,GAC7F;AAEF,KAAI;AACF,MAAI,YAAY,MAAM,YAAYH,cAChC,OAAM,IAAI,eAAe,YAAY,UAAU;AAEjD,oBAAkB,YAAY;EAE9B,MAAM,oBAAoB,eAAgB,MAAM,OAAO,gBAAgB;EACvE,MAAM,cAAc,aAAa;GAAE;GAAQ,aAAa;EAAmB,EAAC;EAE5E,MAAM,EAAE,UAAU,GAAG,sBAAsB,SAAS,UAAU;AAC9D,MAAI,aAAa,YACf,OAAM,IAAI,uBAAuB;EAGnC,MAAM,QAAQ,MAAM,iBAAiB;GACnC;GACA;GACA;GACA;GACA,aAAa;EACd,EAAC;EAEF,MAAM,EAAE,QAAQ,GAAG,MAAM,OAAO,iBAAiB;GAC/C,SAAS;GACT,KAAK;GACL,cAAc;GACd,aAAa;GACb,MAAM,CACJ;IACE,SAAS;KACP,WAAW,MAAM,QAAQ;KACzB,WAAW,MAAM,QAAQ;KACzB,KAAK,OAAO,MAAM,QAAQ,IAAI;KAC9B,aAAa,OAAO,MAAM,QAAQ,YAAY;KAC9C,OAAO,MAAM,QAAQ;IACtB;IACD,YAAY,MAAM;IAClB,aAAa;IACb,UAAU;GACX,CACF;EACF,EAAC;EAEF,MAAM,CAAC,UAAU,YAAY,GAAG;EAEhC,MAAM,mBACH,YAAYD,oBAAkB,eAAeA,oBAAkB,MAAMA;EAExE,MAAM,QAAQ,MAAM;AAEpB,SAAO;GACL,SAAS;GACT,MAAM;IACJ;IACA;IACA,YAAY,MAAM;IAClB,UAAU,MAAM;IAChB,SAAS,MAAM;IACf;GACD;GACD;GACA;EACD;CACF,SAAQ,OAAO;AACd,SAAO;GACL,SAAS;GACT,OACE,iBAAiB,gBACb,QACA,IAAI,cACF,iBAAiB,QAAQ,MAAM,UAAU,gBACzC,iBAAiB,QAAQ;GAEjC,OAAO;EACR;CACF;AACF;;;;ACxMD,MAAM,kBAAkB;AACxB,MAAM,eAAe,MAAM,QAAQ;;;;;;AAwBnC,eAAsB,wBACpBK,QACgC;CAChC,MAAM,EAAE,QAAQ,SAAS,SAAS,YAAY,UAAU,aAAa,aAAa,GAAG;AACrF,KAAI,WAAW,MAAM,WAAW,YAC9B,OAAM,IAAI,eAAe,WAAW,SAAS;AAE/C,KAAI,cAAc,MAAM,cAAc,gBACpC,OAAM,IAAI,eAAe,sBAAsB,YAAY;CAG7D,MAAM,EAAE,UAAU,GAAG,sBAAsB,SAAS,OAAO,UAAU;AAErE,KAAI;EACF,MAAM,EAAE,QAAQ,GAAG,MAAM,OAAO,iBAAiB;GAC/C,SAAS;GACT,KAAK;GACL,cAAc;GACd;GACA,MAAM,CACJ;IACE,SAAS;KACP,WAAW,QAAQ;KACnB,WAAW,QAAQ;KACnB,KAAK,OAAO,QAAQ,IAAI;KACxB,aAAa,OAAO,QAAQ,YAAY;KACxC,OAAO,QAAQ;IAChB;IACD;IACA,aAAa;IACb,UAAU;GACX,CACF;EACF,EAAC;EACF,MAAM,CAAC,WAAW,YAAY,GAAG;EACjC,MAAM,mBAAoB,aAAa,kBAAkB,eAAgB;AACzE,SAAO;GAAE;GAAW;GAAkB;EAAa;CACpD,SAAQ,KAAK;AACZ,MAAI,SAAS,IAAI,CAAE,QAAO;AAG1B,QAAM;CACP;AACF;;AAGD,SAAS,SAASC,KAAuB;AACvC,QACE,eAAe,aACf,IAAI,KAAK,CAAC,MAAM,aAAa,8BAA8B,YACzD;AAEL;;;;;ACrED,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;AAoBjC,eAAsB,qBAAqBC,QAAuD;CAChG,MAAM,EACJ,QACA,cACA,SACA,aACA,SACA,SACA,UACA,aACA,UACA,WACA,aACA,WACD,GAAG;AAEJ,KAAI,yBAA4B,eAAe,WAAW,QAAQ,CAGhE,OAAM,IAAI,cAAc;CAG1B,MAAM,WAAW,sBAAsB,SAAS,UAAU;CAE1D,MAAM,QAAQ,MAAM,0BAA0B;EAC5C;EACA;EACA;EACA;EACA;EACA;EACA;CACD,EAAC;AAEF,MAAK,MAAM,QACT,OAAM,MAAM;CAGd,MAAM,mBACJ,aAAa,MAAM,aAAa,EAAE,OAAQ,EAAC,EAAE,iBAAiB;AAEhE,MAAK,MAAM,KAAK,QACd,OAAM,IAAI,cAAc;CAG1B,MAAM,EAAE,MAAM,OAAO,GAAG,uBAAuB;EAC7C,SAAS,MAAM,KAAK;EACpB,YAAY,MAAM,KAAK;EACvB;EACA,kBAAkB,MAAM,KAAK;EAC7B;EACA,UAAU,MAAM,KAAK;EACrB,UAAU;EACV,WAAW;CACZ,EAAC;AAEF,QAAO,YAAY;EACjB;EACA;EACA;EACA,SAAS,SAAS;EAClB,KAAK;EACL,cAAc;EACd;EACA;EACA;CACD,EAAC;AACH;;;;AAKD,eAAsB,4BACpBA,QACoB;CACpB,MAAM,SAAS,MAAM,qBAAqB,OAAO;AACjD,QAAO,OAAO,MAAM;AACrB;;;;;;;;;;;;AAaD,eAAsB,sBACpBC,QACmB;CACnB,MAAM,EACJ,QACA,cACA,SACA,aACA,SACA,SACA,WACA,aACA,UACA,WACA,aACA,WACD,GAAG;AAEJ,KAAI,yBAA4B,eAAe,WAAW,QAAQ,CAGhE,OAAM,IAAI,cAAc;CAG1B,MAAM,WAAW,sBAAsB,SAAS,UAAU;CAE1D,MAAM,QAAQ,MAAM,2BAA2B;EAC7C;EACA;EACA;EACA;EACA;EACA;EACA;CACD,EAAC;AAEF,MAAK,MAAM,QACT,OAAM,MAAM;CAGd,MAAM,mBACJ,aAAa,MAAM,aAAa,EAAE,OAAQ,EAAC,EAAE,iBAAiB;AAEhE,MAAK,MAAM,KAAK,QACd,OAAM,IAAI,cAAc;CAG1B,MAAM,EAAE,MAAM,OAAO,GAAG,+BAA+B;EACrD,SAAS,MAAM,KAAK;EACpB,YAAY,MAAM,KAAK;EACvB;EACA,iBAAiB,MAAM,KAAK;EAC5B;EACA,UAAU,MAAM,KAAK;EACrB,UAAU;EACV,WAAW;CACZ,EAAC;AAEF,QAAO,YAAY;EACjB;EACA;EACA;EACA,SAAS,SAAS;EAClB,KAAK;EACL,cAAc;EACd;EACA;EACA;CACD,EAAC;AACH;;;;AAKD,eAAsB,6BACpBA,QACoB;CACpB,MAAM,SAAS,MAAM,sBAAsB,OAAO;AAClD,QAAO,OAAO,MAAM;AACrB"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["D","tick: number","steps: { lower: number; upper: number; up: boolean; d0: Decimal; d1: Decimal }[]","Q192","tick: bigint","message: string","cause?: Error","encodedStrike: bigint","legIndex: bigint","tokenId: bigint","legs: DecodedLeg[]","POOL_ID_MASK","Q192","MAX_UINT128","Q192","POOL_ID_MASK","MAX_UINT128","Q96","n: bigint","d: bigint","ranges: readonly LpFeeRange[]","sqrtPriceX96: bigint","params: LpPositionFundingParams","params: Omit<LpPositionFundingParams, 'positionSize'> & {\n availableInQuote: bigint\n minimumRequirement?: { referenceSize: bigint; requiredInQuote: bigint }\n }","Q96","Q192","sqrtPriceX96: bigint","sqrtRatioAX96: bigint","sqrtRatioBX96: bigint","liquidity: bigint","input: LpGreeksInput","value","delta","gamma","feeReturnPercent: Decimal","durationSeconds: bigint","validTick","tick: number","x: number","input: RangeProbabilityInput","input: ExpectedTimeInRangeInput","input: RangeStatsInput","horizonsYears: readonly number[]","p: number[]","e: number[]","chainId: bigint","cause?: Error","token: Address","currency0: Address","currency1: Address","amount: bigint","UNISWAP_V3_ADDRESSES: Record<number, UniswapV3Addresses>","chainId: number | bigint","overrides?: Partial<UniswapV3Addresses>","MSG_SENDER: Address","UINT128_MAX","assertUint128","amount: bigint","tokenIn: Address","fee: bigint","tokenOut: Address","args: BuildV3SwapCalldataArgs","args: BuildV3ExactOutSwapCalldataArgs","BPS_DENOMINATOR","UINT128_MAX","params: QuoteV3ExactInParams","params: QuoteV3ExactOutParams","assertSlippageBps","slippageBps: bigint","isRevert","err: unknown","params: GetBlockMetaParams","erc20Abi","params: GetPoolMetadataParams","underlyingPoolId: string","fee: bigint","tickSpacing: bigint","params: GetPoolParams","vegoid","SECONDS_PER_YEAR","collateralTracker0: CollateralTracker","collateralTracker1: CollateralTracker","riskEngine: RiskEngine","poolId: bigint","poolKeyBytes: `0x${string}`","params: ResolveV3SwapRouteParams","FALLBACK_META","params: QuoteSwapExactInViaV3RouterParams","params: QuoteSwapExactOutViaV3RouterParams","balanceData: bigint","value: bigint","logs: Log[]","events: PanopticEvent[]","client: PublicClient","hash: Hash","confirmations?: bigint","params: SubmitWriteParams","hash","gasOverrides: Record<string, unknown>","PERMIT2_ADDRESS: Address","UNISWAP_V4_ADDRESSES: Record<number, UniswapV4Addresses>","chainId: bigint","overrides?: Partial<UniswapV4Addresses>","merged: Partial<UniswapV4Addresses>","DEFAULT_DEADLINE_SECONDS","params: SwapExactInViaV3RouterParams","params: SwapExactOutViaV3RouterParams","UINT128_MAX","amount: bigint","recipient: Address","tokenOut: Address","recipient: Address | undefined","nativeAmount: bigint","erc20Amount: bigint","args: BuildV4SwapCalldataArgs","args: BuildV4ExactOutSwapCalldataArgs","commandList: number[]","inputs: Hex[]","Q96","BIT_MASK_128","params: CheckRouterApprovalParams","params: ApproveErc20ForPermit2Params","params: ApproveRouterViaPermit2Params","params: ResolveSwapRouteParams","BPS_DENOMINATOR","UINT128_MAX","slippageBps: bigint","params: QuoteSwapExactInViaRouterParams","params: QuoteSwapExactOutViaRouterParams","params: QuoteV4ExactInByPoolKeyParams","err: unknown","params: SwapExactInViaRouterParams","params: SwapExactOutViaRouterParams"],"sources":["../../src/uniswap/estimateLpFees.ts","../../src/panoptic/v2/utils/constants.ts","../../src/panoptic/v2/formatters/tick.ts","../../src/panoptic/v2/errors/base.ts","../../src/generated.ts","../../src/panoptic/v2/errors/errorsAbi.ts","../../src/panoptic/v2/errors/parser.ts","../../src/panoptic/v2/tokenId/constants.ts","../../src/panoptic/v2/tokenId/encoding.ts","../../src/panoptic/v2/tokenId/deriveUniqueTokenId.ts","../../src/panoptic/v2/formatters/rates.ts","../../src/panoptic/v2/tokenId/generateOverlapping.ts","../../src/panoptic/v2/tokenId/split.ts","../../src/uniswap/lpDeposit.ts","../../src/uniswap/lpGreeks.ts","../../src/uniswap/lpFeeReturn.ts","../../src/uniswap/rangeProbability.ts","../../src/uniswap/v4/router/errors.ts","../../src/uniswap/v3/addresses.ts","../../src/uniswap/v4/abis/universalRouter.ts","../../src/uniswap/v3/router/encodeSwap.ts","../../src/uniswap/v3/abis/quoterV2.ts","../../src/uniswap/v3/router/quote.ts","../../src/panoptic/v2/clients/blockMeta.ts","../../src/panoptic/v2/abis/stateView.ts","../../src/panoptic/v2/abis/uniswapV3Pool.ts","../../src/panoptic/v2/utils/oraclePack.ts","../../src/panoptic/v2/utils/oracleSafeMode.ts","../../src/panoptic/v2/reads/pool.ts","../../src/uniswap/v3/router/resolveRoute.ts","../../src/uniswap/v3/router/quoteViaRouter.ts","../../src/panoptic/v2/writes/utils.ts","../../src/uniswap/v4/addresses.ts","../../src/uniswap/v3/router/swap.ts","../../src/uniswap/v4/router/encodeSwap.ts","../../src/panoptic/v2/sync/snapshotRecovery.ts","../../src/panoptic/v2/greeks/index.ts","../../src/panoptic/v2/utils/option-encoding-v2.ts","../../src/panoptic/v2/sync/eventReconstruction.ts","../../src/panoptic/v2/writes/protectedSettle.ts","../../src/panoptic/v2/reads/positionSizes.ts","../../src/panoptic/v2/simulations/tokenFlow.ts","../../src/panoptic/v2/simulations/simulateSettle.ts","../../src/uniswap/v4/abis/permit2.ts","../../src/uniswap/v4/router/permit2.ts","../../src/uniswap/v4/abis/v4Quoter.ts","../../src/uniswap/v4/router/resolvePoolKey.ts","../../src/uniswap/v4/router/quote.ts","../../src/uniswap/v4/router/quoteByPoolKey.ts","../../src/uniswap/v4/router/swap.ts"],"sourcesContent":["import Decimal from 'decimal.js'\n\n// Keep precision local: do not change the caller's Decimal configuration.\nconst D = Decimal.clone({ precision: 60 })\n\nexport interface LpFeeCandle {\n t: number\n o: number\n h: number\n l: number\n c: number\n /** Absolute swap volume (inputs + outputs), in raw token units. */\n v0: string\n v1: string\n /** Historical active liquidity at the candle close, when available. */\n liq?: string\n}\n\nexport interface LpFeeRange {\n tickLower: number\n tickUpper: number\n liquidity: bigint\n}\n\nconst validTick = (tick: number) => Number.isInteger(tick) && Math.abs(tick) <= 887272\n\n/**\n * Hypothetical added LP liquidity, with no compounding or price impact. Fees are raw\n * token units. Bullish candles follow O→L→H→C; bearish candles O→H→L→C.\n * Uniswap v3 deltas distribute absolute volume between inputs and outputs; only\n * inputs pay fees. Split moves at every LP boundary, so overlapping ranges share\n * the same denominator and out-of-range portions earn nothing.\n *\n * Closing historical liquidity approximates liquidity throughout a candle. If\n * absent, infer it from volume / path deltas. Flat candles with volume use equal\n * buy/sell flow and require historical liquidity; otherwise report them skipped.\n * OHLC cannot recover unseen oscillations, exact swap ordering or liquidity changes.\n */\nexport function estimateLpFees({\n candles,\n ranges,\n feePips,\n}: {\n candles: readonly LpFeeCandle[]\n ranges: readonly LpFeeRange[]\n feePips: bigint\n}) {\n if (feePips < 0n || feePips >= 1_000_000n) throw new Error('Invalid swap fee')\n for (const range of ranges) {\n if (\n !validTick(range.tickLower) ||\n !validTick(range.tickUpper) ||\n range.tickLower >= range.tickUpper ||\n range.liquidity < 0n\n ) {\n throw new Error('Invalid LP range')\n }\n }\n const fee = new D(feePips.toString()).div(1_000_000)\n const net = new D(1).minus(fee)\n const sqrtCache = new Map<number, Decimal>()\n const sqrtAt = (tick: number) => {\n const cached = sqrtCache.get(tick)\n if (cached) return cached\n const sqrt = new D('1.0001').pow(new D(tick).div(2))\n sqrtCache.set(tick, sqrt)\n return sqrt\n }\n const positions = ranges.map((r) => ({ ...r, liquidity: new D(r.liquidity.toString()) }))\n let fees0 = new D(0)\n let fees1 = new D(0)\n let skippedCandles = 0\n let inferredCandles = 0\n let previousTime = -Infinity\n const points = candles.map((candle) => {\n const { o, h, l, c, t } = candle\n if (\n !Number.isSafeInteger(t) ||\n t <= previousTime ||\n ![o, h, l, c].every(validTick) ||\n l > Math.min(o, c) ||\n h < Math.max(o, c) ||\n l > h\n ) {\n throw new Error('Invalid or unordered OHLC candles')\n }\n previousTime = t\n const v0 = new D(candle.v0)\n const v1 = new D(candle.v1)\n const historical = new D(candle.liq ?? '0')\n if (![v0, v1, historical].every((v) => v.isFinite() && v.isInteger() && v.gte(0))) {\n throw new Error('Invalid candle volume or liquidity')\n }\n const path = c >= o ? [o, l, h, c] : [o, h, l, c]\n const steps: { lower: number; upper: number; up: boolean; d0: Decimal; d1: Decimal }[] = []\n for (let i = 1; i < path.length; i++) {\n const from = path[i - 1]\n const to = path[i]\n if (from === undefined || to === undefined || from === to) continue\n const lower = Math.min(from, to)\n const upper = Math.max(from, to)\n const cuts = [\n ...new Set([lower, upper, ...positions.flatMap((p) => [p.tickLower, p.tickUpper])]),\n ]\n .filter((tick) => tick >= lower && tick <= upper)\n .sort((a, b) => a - b)\n for (let j = 1; j < cuts.length; j++) {\n const a = cuts[j - 1]\n const b = cuts[j]\n if (a === undefined || b === undefined) continue\n const sa = sqrtAt(a)\n const sb = sqrtAt(b)\n steps.push({\n lower: a,\n upper: b,\n up: to > from,\n d0: new D(1).div(sa).minus(new D(1).div(sb)),\n d1: sb.minus(sa),\n })\n }\n }\n const total0 = steps.reduce((sum, s) => sum.plus(s.up ? s.d0 : s.d0.div(net)), new D(0))\n const total1 = steps.reduce((sum, s) => sum.plus(s.up ? s.d1.div(net) : s.d1), new D(0))\n const hasVolume = v0.gt(0) || v1.gt(0)\n const inferred =\n total0.gt(0) && total1.gt(0) ? v0.div(total0).plus(v1.div(total1)).div(2) : new D(0)\n const poolLiquidity = historical.gt(0) ? historical : inferred\n if (hasVolume && poolLiquidity.eq(0)) skippedCandles++\n else if (hasVolume && fee.gt(0)) {\n if (historical.eq(0)) inferredCandles++\n if (steps.length === 0) {\n const active = positions\n .filter((p) => p.tickLower <= c && c < p.tickUpper)\n .reduce((sum, p) => sum.plus(p.liquidity), new D(0))\n const share = active.div(poolLiquidity.plus(active))\n // Absolute volume counts both sides; equal directional flow implies\n // input fraction 1 / (2 - fee), including fees in gross inputs.\n fees0 = fees0.plus(v0.div(new D(2).minus(fee)).mul(fee).mul(share))\n fees1 = fees1.plus(v1.div(new D(2).minus(fee)).mul(fee).mul(share))\n } else {\n for (const step of steps) {\n const active = positions\n .filter((p) => p.tickLower <= step.lower && p.tickUpper >= step.upper)\n .reduce((sum, p) => sum.plus(p.liquidity), new D(0))\n const share = active.div(poolLiquidity.plus(active))\n if (step.up) fees1 = fees1.plus(v1.mul(step.d1.div(net)).div(total1).mul(fee).mul(share))\n else fees0 = fees0.plus(v0.mul(step.d0.div(net)).div(total0).mul(fee).mul(share))\n }\n }\n }\n return {\n time: t,\n fees0: BigInt(fees0.floor().toFixed(0)),\n fees1: BigInt(fees1.floor().toFixed(0)),\n }\n })\n return { points, skippedCandles, inferredCandles }\n}\n","/**\n * Constants for the Panoptic v2 SDK.\n * @module v2/utils/constants\n */\n\n/**\n * WAD constant (10^18) used for fixed-point arithmetic.\n * Commonly used for spread calculations and other WAD-scaled values.\n */\nexport const WAD = 10n ** 18n\n\n/**\n * Zero collateral object for guest mode.\n * Returns safe defaults when no wallet is connected.\n */\nexport const ZERO_COLLATERAL = {\n token0: {\n assets: 0n,\n shares: 0n,\n availableAssets: 0n,\n lockedAssets: 0n,\n },\n token1: {\n assets: 0n,\n shares: 0n,\n availableAssets: 0n,\n lockedAssets: 0n,\n },\n} as const\n\n/**\n * Zero valuation object for guest mode.\n * Returns safe defaults when no wallet is connected.\n */\nexport const ZERO_VALUATION = {\n netLiquidationValue0: 0n,\n netLiquidationValue1: 0n,\n maintenanceMargin0: 0n,\n maintenanceMargin1: 0n,\n marginExcess0: 0n,\n marginExcess1: 0n,\n} as const\n\n/**\n * Storage schema version for the SDK.\n * Increment when storage format changes (triggers migration or clear).\n */\nexport const SCHEMA_VERSION = 1\n\n/**\n * Storage key prefix for all SDK data.\n */\nexport const STORAGE_PREFIX = 'panoptic-v2-sdk'\n\n/**\n * Maximum number of chunks that can be tracked per pool.\n * Exceeding this limit throws ChunkLimitError.\n */\nexport const MAX_TRACKED_CHUNKS = 1000\n\n/**\n * Default reorg depth for chain reorganization handling.\n * On reorg detection, rollback this many blocks and re-sync.\n */\nexport const REORG_DEPTH = 128n\n\n/**\n * Oracle epoch duration in seconds (64 seconds per epoch).\n */\nexport const ORACLE_EPOCH_SECONDS = 64n\n\n/**\n * Minimum tick value for Uniswap v3/v4 pools.\n */\nexport const MIN_TICK = -887272n\n\n/**\n * Maximum tick value for Uniswap v3/v4 pools.\n */\nexport const MAX_TICK = 887272n\n\n/**\n * PanopticQuery sentinel indicating that no lower liquidation boundary exists.\n * This is int24.min, not Uniswap's minimum usable tick.\n */\nexport const NO_LOWER_LIQUIDATION_TICK = -(1n << 23n)\n\n/**\n * PanopticQuery sentinel indicating that no upper liquidation boundary exists.\n * This is int24.max, not Uniswap's maximum usable tick.\n */\nexport const NO_UPPER_LIQUIDATION_TICK = (1n << 23n) - 1n\n\n/**\n * Basis points denominator (100% = 10000 bps).\n */\nexport const BPS_DENOMINATOR = 10000n\n\n/**\n * Utilization denominator (100% = 10000).\n */\nexport const UTILIZATION_DENOMINATOR = 10000n\n","/**\n * Tick and price formatters for Uniswap V3/V4 pools.\n *\n * Ticks represent logarithmic prices where: price = 1.0001^tick\n *\n * @module v2/formatters/tick\n */\n\nimport { MAX_TICK, MIN_TICK } from '../utils/constants'\n\nconst Q192 = 1n << 192n\nconst RAW_PRICE_PRECISION = 40n\n\nfunction pow10(exponent: bigint): bigint {\n if (exponent < 0n) {\n throw new RangeError('Exponent must be non-negative')\n }\n return 10n ** exponent\n}\n\nfunction absBigint(value: bigint): bigint {\n return value < 0n ? -value : value\n}\n\nfunction trimTrailingZeros(value: string): string {\n const dotIndex = value.indexOf('.')\n if (dotIndex === -1) return value\n\n let end = value.length\n while (end > dotIndex && value[end - 1] === '0') {\n end -= 1\n }\n\n if (end === dotIndex + 1) {\n end = dotIndex\n }\n\n return value.slice(0, end)\n}\n\nfunction formatRatio(numerator: bigint, denominator: bigint, precision: bigint): string {\n if (precision < 0n) {\n throw new RangeError('Precision must be non-negative')\n }\n\n const sign = numerator < 0n ? '-' : ''\n const absNumerator = numerator < 0n ? -numerator : numerator\n\n const scale = pow10(precision)\n const scaled = (absNumerator * scale + denominator / 2n) / denominator\n const integerPart = scaled / scale\n const fractionalPart = scaled % scale\n\n if (precision === 0n) {\n return `${sign}${integerPart}`\n }\n\n return `${sign}${integerPart}.${fractionalPart.toString().padStart(Number(precision), '0')}`\n}\n\nfunction parseDecimalToFraction(value: string): { numerator: bigint; denominator: bigint } {\n const trimmed = value.trim()\n if (trimmed.length === 0) {\n throw new Error('Price must be a number')\n }\n\n const isNegative = trimmed.startsWith('-')\n const unsigned = isNegative || trimmed.startsWith('+') ? trimmed.slice(1) : trimmed\n\n const [basePart, exponentPart] = unsigned.toLowerCase().split('e')\n const [integerStr, fractionalStr = ''] = basePart.split('.')\n\n if (integerStr === '' && fractionalStr === '') {\n throw new Error('Price must be a number')\n }\n\n const integerDigits = integerStr === '' ? '0' : integerStr\n const digits = `${integerDigits}${fractionalStr}`\n\n let numerator = BigInt(digits === '' ? '0' : digits)\n let denominator = pow10(BigInt(fractionalStr.length))\n\n if (exponentPart !== undefined && exponentPart !== '') {\n const exponent = BigInt(exponentPart)\n if (exponent > 0n) {\n numerator *= pow10(exponent)\n } else if (exponent < 0n) {\n denominator *= pow10(-exponent)\n }\n }\n\n if (isNegative) {\n numerator = -numerator\n }\n\n return { numerator, denominator }\n}\n\nfunction compareRatios(\n leftNumerator: bigint,\n leftDenominator: bigint,\n rightNumerator: bigint,\n rightDenominator: bigint,\n): -1 | 0 | 1 {\n const left = leftNumerator * rightDenominator\n const right = rightNumerator * leftDenominator\n\n if (left === right) return 0\n return left < right ? -1 : 1\n}\n\nexport function tickToSqrtPriceX96(tick: bigint): bigint {\n if (tick < MIN_TICK || tick > MAX_TICK) {\n throw new RangeError('Tick out of bounds')\n }\n\n const absTick = tick < 0n ? -tick : tick\n\n let ratio =\n (absTick & 0x1n) !== 0n\n ? 0xfffcb933bd6fad37aa2d162d1a594001n\n : 0x100000000000000000000000000000000n\n if ((absTick & 0x2n) !== 0n) ratio = (ratio * 0xfff97272373d413259a46990580e213an) >> 128n\n if ((absTick & 0x4n) !== 0n) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdccn) >> 128n\n if ((absTick & 0x8n) !== 0n) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0n) >> 128n\n if ((absTick & 0x10n) !== 0n) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644n) >> 128n\n if ((absTick & 0x20n) !== 0n) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0n) >> 128n\n if ((absTick & 0x40n) !== 0n) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861n) >> 128n\n if ((absTick & 0x80n) !== 0n) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053n) >> 128n\n if ((absTick & 0x100n) !== 0n) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4n) >> 128n\n if ((absTick & 0x200n) !== 0n) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54n) >> 128n\n if ((absTick & 0x400n) !== 0n) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3n) >> 128n\n if ((absTick & 0x800n) !== 0n) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9n) >> 128n\n if ((absTick & 0x1000n) !== 0n) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825n) >> 128n\n if ((absTick & 0x2000n) !== 0n) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5n) >> 128n\n if ((absTick & 0x4000n) !== 0n) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7n) >> 128n\n if ((absTick & 0x8000n) !== 0n) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6n) >> 128n\n if ((absTick & 0x10000n) !== 0n) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9n) >> 128n\n if ((absTick & 0x20000n) !== 0n) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604n) >> 128n\n if ((absTick & 0x40000n) !== 0n) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98n) >> 128n\n if ((absTick & 0x80000n) !== 0n) ratio = (ratio * 0x48a170391f7dc42444e8fa2n) >> 128n\n\n if (tick > 0n) {\n ratio = ((1n << 256n) - 1n) / ratio\n }\n\n const remainderMask = (1n << 32n) - 1n\n const sqrtPriceX96 = (ratio >> 32n) + ((ratio & remainderMask) === 0n ? 0n : 1n)\n\n return sqrtPriceX96\n}\n\nconst MIN_SQRT_PRICE_X96 = tickToSqrtPriceX96(MIN_TICK)\nconst MAX_SQRT_PRICE_X96 = tickToSqrtPriceX96(MAX_TICK)\n\nfunction getPriceRatioFromSqrtPriceX96(sqrtPriceX96: bigint): {\n numerator: bigint\n denominator: bigint\n} {\n return {\n numerator: sqrtPriceX96 * sqrtPriceX96,\n denominator: Q192,\n }\n}\n\nfunction getRawPriceRatio(tick: bigint): { numerator: bigint; denominator: bigint } {\n return getPriceRatioFromSqrtPriceX96(tickToSqrtPriceX96(tick))\n}\n\nfunction adjustRatioForDecimals(\n numerator: bigint,\n denominator: bigint,\n decimals0: bigint,\n decimals1: bigint,\n): { numerator: bigint; denominator: bigint } {\n const diff = decimals0 - decimals1\n if (diff === 0n) {\n return { numerator, denominator }\n }\n\n if (diff > 0n) {\n return { numerator: numerator * pow10(diff), denominator }\n }\n\n return { numerator, denominator: denominator * pow10(-diff) }\n}\n\n/**\n * Convert a tick to a raw price string (no decimal adjustment).\n * Uses the formula: price = 1.0001^tick\n *\n * This returns the raw price ratio, not adjusted for token decimals.\n * A fixed internal precision is used and trailing zeros are trimmed.\n *\n * @param tick - The tick value\n * @returns Price string\n *\n * @example\n * ```typescript\n * tickToPrice(0n) // \"1\"\n * tickToPrice(1000n) // \"1.105...\" (approximately)\n * tickToPrice(-1000n) // \"0.904...\" (approximately)\n * tickToPrice(200000n) // Very large number\n * ```\n */\nexport function tickToPrice(tick: bigint): string {\n const { numerator, denominator } = getRawPriceRatio(tick)\n const price = formatRatio(numerator, denominator, RAW_PRICE_PRECISION)\n return trimTrailingZeros(price)\n}\n\n/**\n * Convert a tick to a human-readable price with decimal scaling.\n * Uses the formula: price = 1.0001^tick * 10^(decimals0-decimals1)\n *\n * This adjusts for the different decimals of the two tokens in the pair.\n *\n * @param tick - The tick value\n * @param decimals0 - Decimals of token0\n * @param decimals1 - Decimals of token1\n * @param precision - Number of decimal places to display\n * @returns Formatted price string\n *\n * @example\n * ```typescript\n * // WETH/USDC pool (18 decimals / 6 decimals)\n * // At tick ~200000, price is roughly $2000 per ETH\n * tickToPriceDecimalScaled(200000n, 18n, 6n, 2n) // \"2000.00\" (approximately)\n *\n * // For token1/token0 price, swap the decimals\n * tickToPriceDecimalScaled(200000n, 6n, 18n, 6n) // \"0.000500\" (approximately)\n * ```\n */\nexport function tickToPriceDecimalScaled(\n tick: bigint,\n decimals0: bigint,\n decimals1: bigint,\n precision: bigint,\n): string {\n const rawRatio = getRawPriceRatio(tick)\n const { numerator, denominator } = adjustRatioForDecimals(\n rawRatio.numerator,\n rawRatio.denominator,\n decimals0,\n decimals1,\n )\n\n return formatRatio(numerator, denominator, precision)\n}\n\n/**\n * Convert a sqrtPriceX96 to a human-readable price with decimal scaling.\n *\n * Uses the formula: price = (sqrtPriceX96^2 / 2^192) * 10^(decimals0-decimals1)\n *\n * @param sqrtPriceX96 - The sqrt price in Q64.96 format\n * @param decimals0 - Decimals of token0\n * @param decimals1 - Decimals of token1\n * @param precision - Number of decimal places to display\n * @returns Formatted price string\n *\n * @example\n * ```typescript\n * sqrtPriceX96ToPriceDecimalScaled(2n ** 96n, 18n, 18n, 2n) // \"1.00\"\n * ```\n */\nexport function sqrtPriceX96ToPriceDecimalScaled(\n sqrtPriceX96: bigint,\n decimals0: bigint,\n decimals1: bigint,\n precision: bigint,\n): string {\n const rawRatio = getPriceRatioFromSqrtPriceX96(sqrtPriceX96)\n const { numerator, denominator } = adjustRatioForDecimals(\n rawRatio.numerator,\n rawRatio.denominator,\n decimals0,\n decimals1,\n )\n\n return formatRatio(numerator, denominator, precision)\n}\n\n/**\n * Convert a price to a tick value.\n *\n * @param price - The price string\n * @param decimals0 - Decimals of token0\n * @param decimals1 - Decimals of token1\n * @returns The tick value (rounded to nearest integer)\n *\n * @example\n * ```typescript\n * // WETH/USDC: What tick for $2000 per ETH?\n * priceToTick(\"2000\", 18n, 6n) // ~200000n\n *\n * // Inverse: What tick for 0.0005 ETH per USDC?\n * priceToTick(\"0.0005\", 6n, 18n) // ~200000n\n * ```\n */\nexport function priceToTick(price: string, decimals0: bigint, decimals1: bigint): bigint {\n const parsed = parseDecimalToFraction(price)\n if (parsed.numerator <= 0n) {\n throw new Error('Price must be positive')\n }\n\n let targetNumerator = parsed.numerator\n let targetDenominator = parsed.denominator\n\n const diff = decimals0 - decimals1\n if (diff > 0n) {\n targetDenominator *= pow10(diff)\n } else if (diff < 0n) {\n targetNumerator *= pow10(-diff)\n }\n\n let low = MIN_TICK\n let high = MAX_TICK\n\n while (low <= high) {\n const mid = (low + high) / 2n\n const { numerator, denominator } = getRawPriceRatio(mid)\n const cmp = compareRatios(numerator, denominator, targetNumerator, targetDenominator)\n\n if (cmp === 0) {\n return mid\n }\n\n if (cmp < 0) {\n low = mid + 1n\n } else {\n high = mid - 1n\n }\n }\n\n const floorTick = high\n const ceilTick = low\n\n if (floorTick < MIN_TICK) return MIN_TICK\n if (ceilTick > MAX_TICK) return MAX_TICK\n\n const floorRatio = getRawPriceRatio(floorTick)\n const ceilRatio = getRawPriceRatio(ceilTick)\n\n const floorDiffNumerator = absBigint(\n targetNumerator * floorRatio.denominator - floorRatio.numerator * targetDenominator,\n )\n const ceilDiffNumerator = absBigint(\n targetNumerator * ceilRatio.denominator - ceilRatio.numerator * targetDenominator,\n )\n const floorDiffDenominator = targetDenominator * floorRatio.denominator\n const ceilDiffDenominator = targetDenominator * ceilRatio.denominator\n\n return floorDiffNumerator * ceilDiffDenominator <= ceilDiffNumerator * floorDiffDenominator\n ? floorTick\n : ceilTick\n}\n\n/**\n * Convert a sqrtPriceX96 value to the nearest tick.\n *\n * @param sqrtPriceX96 - The sqrt price in Q64.96 format\n * @returns The tick value (rounded to nearest integer)\n *\n * @example\n * ```typescript\n * const tick = sqrtPriceX96ToTick(2n ** 96n) // 0n\n * ```\n */\nexport function sqrtPriceX96ToTick(sqrtPriceX96: bigint): bigint {\n if (sqrtPriceX96 <= 0n) {\n throw new Error('Sqrt price must be positive')\n }\n\n if (sqrtPriceX96 < MIN_SQRT_PRICE_X96 || sqrtPriceX96 > MAX_SQRT_PRICE_X96) {\n throw new RangeError('Sqrt price out of bounds')\n }\n\n let low = MIN_TICK\n let high = MAX_TICK\n\n while (low <= high) {\n const mid = (low + high) / 2n\n const midSqrt = tickToSqrtPriceX96(mid)\n\n if (midSqrt === sqrtPriceX96) {\n return mid\n }\n\n if (midSqrt < sqrtPriceX96) {\n low = mid + 1n\n } else {\n high = mid - 1n\n }\n }\n\n const floorTick = high\n const ceilTick = low\n\n if (floorTick < MIN_TICK) return MIN_TICK\n if (ceilTick > MAX_TICK) return MAX_TICK\n\n const floorSqrt = tickToSqrtPriceX96(floorTick)\n const ceilSqrt = tickToSqrtPriceX96(ceilTick)\n\n const floorDiff = absBigint(sqrtPriceX96 - floorSqrt)\n const ceilDiff = absBigint(ceilSqrt - sqrtPriceX96)\n\n return floorDiff <= ceilDiff ? floorTick : ceilTick\n}\n\n/**\n * Format a tick value for display.\n *\n * @param tick - The tick value\n * @returns Formatted tick string\n *\n * @example\n * ```typescript\n * formatTick(200000n) // \"200000\"\n * formatTick(-50000n) // \"-50000\"\n * ```\n */\nexport function formatTick(tick: bigint): string {\n return tick.toString()\n}\n\n/**\n * Get the price at a specific tick, returning both token0/token1 and token1/token0 prices.\n *\n * @param tick - The tick value\n * @param decimals0 - Decimals of token0\n * @param decimals1 - Decimals of token1\n * @param precision - Number of decimal places to display\n * @returns Object with both price directions\n *\n * @example\n * ```typescript\n * const prices = getPricesAtTick(200000n, 18n, 6n, 2n)\n * // prices.token0PerToken1 = \"0.00\" (very small)\n * // prices.token1PerToken0 = \"2000.00\" (USDC per ETH)\n * ```\n */\nexport function getPricesAtTick(\n tick: bigint,\n decimals0: bigint,\n decimals1: bigint,\n precision: bigint,\n): { token0PerToken1: string; token1PerToken0: string } {\n const rawRatio = getRawPriceRatio(tick)\n const adjustedRatio = adjustRatioForDecimals(\n rawRatio.numerator,\n rawRatio.denominator,\n decimals0,\n decimals1,\n )\n\n return {\n token0PerToken1: formatRatio(adjustedRatio.denominator, adjustedRatio.numerator, precision),\n token1PerToken0: formatRatio(adjustedRatio.numerator, adjustedRatio.denominator, precision),\n }\n}\n\n/**\n * Format a tick range for display.\n *\n * @param tickLower - Lower tick\n * @param tickUpper - Upper tick\n * @returns Formatted tick range string\n *\n * @example\n * ```typescript\n * formatTickRange(-50000n, 200000n) // \"-50000 - 200000\"\n * ```\n */\nexport function formatTickRange(tickLower: bigint, tickUpper: bigint): string {\n return `${tickLower} - ${tickUpper}`\n}\n\n/**\n * Format a price range for display.\n *\n * @param tickLower - Lower tick\n * @param tickUpper - Upper tick\n * @param decimals0 - Decimals of token0\n * @param decimals1 - Decimals of token1\n * @param precision - Number of decimal places to display\n * @returns Formatted price range string\n *\n * @example\n * ```typescript\n * formatPriceRange(0n, 0n, 18n, 18n, 2n) // \"1.00 - 1.00\"\n * ```\n */\nexport function formatPriceRange(\n tickLower: bigint,\n tickUpper: bigint,\n decimals0: bigint,\n decimals1: bigint,\n precision: bigint,\n): string {\n const lower = tickToPriceDecimalScaled(tickLower, decimals0, decimals1, precision)\n const upper = tickToPriceDecimalScaled(tickUpper, decimals0, decimals1, precision)\n return `${lower} - ${upper}`\n}\n\n/**\n * Calculate the tick spacing for a given fee tier.\n *\n * @param feeBps - Fee in basis points (e.g., 500n for 0.05%)\n * @returns Tick spacing\n *\n * @example\n * ```typescript\n * getTickSpacing(100n) // 1n (0.01% fee tier)\n * getTickSpacing(500n) // 10n (0.05% fee tier)\n * getTickSpacing(3000n) // 60n (0.30% fee tier)\n * getTickSpacing(10000n) // 200n (1.00% fee tier)\n * ```\n */\nexport function getTickSpacing(feeBps: bigint): bigint {\n // Standard Uniswap V3 tick spacings\n switch (feeBps) {\n case 100n:\n return 1n\n case 500n:\n return 10n\n case 3000n:\n return 60n\n case 10000n:\n return 200n\n default: {\n const spacing = feeBps / 50n\n return spacing > 1n ? spacing : 1n\n }\n }\n}\n\n/**\n * Round a tick to the nearest valid tick for a given tick spacing.\n *\n * @param tick - The tick to round\n * @param tickSpacing - The tick spacing\n * @returns Rounded tick\n *\n * @example\n * ```typescript\n * roundToTickSpacing(12345n, 10n) // 12340n\n * roundToTickSpacing(12345n, 60n) // 12360n\n * roundToTickSpacing(-12345n, 10n) // -12350n\n * ```\n */\nexport function roundToTickSpacing(tick: bigint, tickSpacing: bigint): bigint {\n const remainder = tick % tickSpacing\n if (remainder === 0n) {\n return tick\n }\n // Round to nearest\n if (tick >= 0n) {\n return remainder >= tickSpacing / 2n ? tick + (tickSpacing - remainder) : tick - remainder\n }\n\n const absRemainder = -remainder\n return absRemainder >= tickSpacing / 2n\n ? tick - (tickSpacing - absRemainder)\n : tick + absRemainder\n}\n\n/**\n * Result of {@link tickLimits}.\n */\nexport interface TickLimitsResult {\n /** Lower tick limit (clamped to MIN_TICK). */\n low: bigint\n /** Upper tick limit (clamped to MAX_TICK). */\n high: bigint\n}\n\n/**\n * Compute slippage-bounded tick limits around the current tick.\n *\n * 1 tick ≈ 1 basis point (0.01 %) of price change, so a `toleranceBps`\n * of 500 allows roughly 5 % price movement. The result is clamped to\n * the protocol's `[MIN_TICK, MAX_TICK]` range.\n *\n * Useful for setting `tickLimitLow` / `tickLimitHigh` on `openPosition`\n * and `closePosition` to protect against MEV sandwiches and volatile\n * tick moves.\n *\n * @param currentTick - The current pool tick (must be within [MIN_TICK, MAX_TICK]).\n * @param toleranceBps - Slippage tolerance in basis points (≈ ticks). Must be non-negative.\n * @returns Clamped `{ low, high }` tick limits.\n * @throws {RangeError} If `toleranceBps` is negative or `currentTick` is out of bounds.\n *\n * @example\n * ```typescript\n * const { low, high } = tickLimits(200_000n, 500n)\n * // low = 199_500n\n * // high = 200_500n\n *\n * await openPosition({ ..., tickLimitLow: low, tickLimitHigh: high })\n * ```\n */\nexport function tickLimits(currentTick: bigint, toleranceBps: bigint): TickLimitsResult {\n if (toleranceBps < 0n) {\n throw new RangeError(`toleranceBps must be non-negative, got ${toleranceBps}`)\n }\n if (currentTick < MIN_TICK || currentTick > MAX_TICK) {\n throw new RangeError(`currentTick ${currentTick} is out of bounds [${MIN_TICK}, ${MAX_TICK}]`)\n }\n\n const rawLow = currentTick - toleranceBps\n const rawHigh = currentTick + toleranceBps\n const low = rawLow < MIN_TICK ? MIN_TICK : rawLow\n const high = rawHigh > MAX_TICK ? MAX_TICK : rawHigh\n\n if (low > high) {\n throw new RangeError(\n `Computed tick limits are inverted: low ${low} > high ${high} (currentTick=${currentTick}, toleranceBps=${toleranceBps})`,\n )\n }\n\n return { low, high }\n}\n","/**\n * Base error class for the Panoptic v2 SDK.\n * @module v2/errors/base\n */\n\n/**\n * Base error class for all Panoptic SDK errors.\n * All errors thrown by the SDK extend this class.\n *\n * @example\n * ```typescript\n * try {\n * await openPosition(config, params)\n * } catch (error) {\n * if (error instanceof PanopticError) {\n * console.log('Panoptic error:', error.name, error.message)\n * console.log('Original cause:', error.cause)\n * }\n * }\n * ```\n */\nexport class PanopticError extends Error {\n override readonly name: string = 'PanopticError'\n\n /** The Solidity error name (e.g. 'PriceBoundFail', 'InputListFail'). Set by the parser. */\n errorName?: string\n\n /**\n * Creates a new PanopticError.\n *\n * @param message - Human-readable error message\n * @param cause - Optional underlying error that caused this error\n */\n constructor(\n message: string,\n public readonly cause?: Error,\n ) {\n super(message)\n\n // Maintains proper stack trace for where error was thrown (V8 only)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor)\n }\n\n // Ensure prototype chain is correctly set up\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\n","//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// CollateralTrackerV2\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const collateralTrackerV2Abi = [\n { type: 'constructor', inputs: [], stateMutability: 'nonpayable' },\n {\n type: 'function',\n inputs: [],\n name: 'accrueInterest',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'spender', internalType: 'address', type: 'address' },\n ],\n name: 'allowance',\n outputs: [{ name: 'allowance', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'spender', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'approve',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'asset',\n outputs: [{ name: 'assetTokenAddress', internalType: 'address', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'assetsAndInterest',\n outputs: [\n { name: '', internalType: 'uint256', type: 'uint256' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'assetsOf',\n outputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'account', internalType: 'address', type: 'address' }],\n name: 'balanceOf',\n outputs: [{ name: 'balance', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'borrowIndex',\n outputs: [{ name: '', internalType: 'uint80', type: 'uint80' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n name: 'convertToAssets',\n outputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n name: 'convertToShares',\n outputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'decimals',\n outputs: [{ name: '', internalType: 'uint8', type: 'uint8' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'delegatee', internalType: 'address', type: 'address' }],\n name: 'delegate',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'assets', internalType: 'uint256', type: 'uint256' },\n { name: 'receiver', internalType: 'address', type: 'address' },\n ],\n name: 'deposit',\n outputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'getPoolData',\n outputs: [\n { name: 'depositedAssets', internalType: 'uint256', type: 'uint256' },\n { name: 'insideAMM', internalType: 'uint256', type: 'uint256' },\n { name: 'creditedShares', internalType: 'uint256', type: 'uint256' },\n {\n name: 'currentPoolUtilization',\n internalType: 'uint256',\n type: 'uint256',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'initialize',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'interestRate',\n outputs: [{ name: '', internalType: 'uint128', type: 'uint128' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'user', internalType: 'address', type: 'address' }],\n name: 'interestState',\n outputs: [\n { name: 'userBorrowIndex', internalType: 'int128', type: 'int128' },\n { name: 'netBorrows', internalType: 'int128', type: 'int128' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'lastInteractionTimestamp',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: '', internalType: 'address', type: 'address' }],\n name: 'maxDeposit',\n outputs: [{ name: 'maxAssets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [{ name: '', internalType: 'address', type: 'address' }],\n name: 'maxMint',\n outputs: [{ name: 'maxShares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'maxRedeem',\n outputs: [{ name: 'maxShares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'maxWithdraw',\n outputs: [{ name: 'maxAssets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'shares', internalType: 'uint256', type: 'uint256' },\n { name: 'receiver', internalType: 'address', type: 'address' },\n ],\n name: 'mint',\n outputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes[]', type: 'bytes[]' }],\n name: 'multicall',\n outputs: [{ name: 'results', internalType: 'bytes[]', type: 'bytes[]' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'name',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'owedInterest',\n outputs: [{ name: '', internalType: 'uint128', type: 'uint128' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'panopticPool',\n outputs: [{ name: '', internalType: 'contract PanopticPoolV2', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'poolFee',\n outputs: [{ name: '_poolFee', internalType: 'uint24', type: 'uint24' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'poolManager',\n outputs: [{ name: '', internalType: 'contract IPoolManager', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n name: 'previewDeposit',\n outputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n name: 'previewMint',\n outputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'previewOwedInterest',\n outputs: [{ name: '', internalType: 'uint128', type: 'uint128' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n name: 'previewRedeem',\n outputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n name: 'previewWithdraw',\n outputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'rateAtTarget',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'shares', internalType: 'uint256', type: 'uint256' },\n { name: 'receiver', internalType: 'address', type: 'address' },\n { name: 'owner', internalType: 'address', type: 'address' },\n ],\n name: 'redeem',\n outputs: [{ name: 'assets', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'reentrancyGuardEntered',\n outputs: [{ name: 'entered', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'refunder', internalType: 'address', type: 'address' },\n { name: 'refundee', internalType: 'address', type: 'address' },\n { name: 'assets', internalType: 'int256', type: 'int256' },\n ],\n name: 'refund',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'delegatee', internalType: 'address', type: 'address' }],\n name: 'revoke',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'riskEngine',\n outputs: [{ name: '', internalType: 'contract IRiskEngine', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'optionOwner', internalType: 'address', type: 'address' },\n { name: 'longAmount', internalType: 'int128', type: 'int128' },\n { name: 'shortAmount', internalType: 'int128', type: 'int128' },\n { name: 'ammDeltaAmount', internalType: 'int128', type: 'int128' },\n { name: 'realizedPremium', internalType: 'int128', type: 'int128' },\n {\n name: 'riskParameters',\n internalType: 'RiskParameters',\n type: 'uint256',\n },\n ],\n name: 'settleBurn',\n outputs: [{ name: '', internalType: 'int128', type: 'int128' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'liquidator', internalType: 'address', type: 'address' },\n { name: 'liquidatee', internalType: 'address', type: 'address' },\n { name: 'bonus', internalType: 'int256', type: 'int256' },\n ],\n name: 'settleLiquidation',\n outputs: [],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'optionOwner', internalType: 'address', type: 'address' },\n { name: 'longAmount', internalType: 'int128', type: 'int128' },\n { name: 'shortAmount', internalType: 'int128', type: 'int128' },\n { name: 'ammDeltaAmount', internalType: 'int128', type: 'int128' },\n {\n name: 'riskParameters',\n internalType: 'RiskParameters',\n type: 'uint256',\n },\n ],\n name: 'settleMint',\n outputs: [\n { name: '', internalType: 'uint32', type: 'uint32' },\n { name: '', internalType: 'int128', type: 'int128' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'symbol',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'token0',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'token1',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'totalAssets',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'totalSupply',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'recipient', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'transfer',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'transferFrom',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'underlyingIsToken0',\n outputs: [{ name: '_underlyingIsToken0', internalType: 'bool', type: 'bool' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'underlyingToken',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes', type: 'bytes' }],\n name: 'unlockCallback',\n outputs: [{ name: '', internalType: 'bytes', type: 'bytes' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'unrealizedGlobalInterest',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'assets', internalType: 'uint256', type: 'uint256' },\n { name: 'receiver', internalType: 'address', type: 'address' },\n { name: 'owner', internalType: 'address', type: 'address' },\n ],\n name: 'withdraw',\n outputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'assets', internalType: 'uint256', type: 'uint256' },\n { name: 'receiver', internalType: 'address', type: 'address' },\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n { name: 'usePremiaAsCollateral', internalType: 'bool', type: 'bool' },\n ],\n name: 'withdraw',\n outputs: [{ name: 'shares', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'spender',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'amount',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'Approval',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'builder',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'commissionPaidProtocol',\n internalType: 'uint128',\n type: 'uint128',\n indexed: false,\n },\n {\n name: 'commissionPaidBuilder',\n internalType: 'uint128',\n type: 'uint128',\n indexed: false,\n },\n ],\n name: 'CommissionPaid',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'sender',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'assets',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n {\n name: 'shares',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'Deposit',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'interestOwed',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n {\n name: 'interestPaid',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n {\n name: 'sharesBurned',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'InsolvencyPenaltyApplied',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'liquidatee',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'liquidator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'protocolLossAssets',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n {\n name: 'protocolLossShares',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'ProtocolLossRealized',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'from', internalType: 'address', type: 'address', indexed: true },\n { name: 'to', internalType: 'address', type: 'address', indexed: true },\n {\n name: 'amount',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'Transfer',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'sender',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'receiver',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'assets',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n {\n name: 'shares',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'Withdraw',\n },\n { type: 'error', inputs: [], name: 'AlreadyInitialized' },\n { type: 'error', inputs: [], name: 'BelowMinimumRedemption' },\n { type: 'error', inputs: [], name: 'CastingError' },\n { type: 'error', inputs: [], name: 'DepositTooLarge' },\n { type: 'error', inputs: [], name: 'ExceedsMaximumRedemption' },\n {\n type: 'error',\n inputs: [\n { name: 'tokenAddress', internalType: 'address', type: 'address' },\n { name: 'assetsRequested', internalType: 'uint256', type: 'uint256' },\n { name: 'assetBalance', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'NotEnoughTokens',\n },\n { type: 'error', inputs: [], name: 'NotPanopticPool' },\n { type: 'error', inputs: [], name: 'PositionCountNotZero' },\n { type: 'error', inputs: [], name: 'Reentrancy' },\n {\n type: 'error',\n inputs: [\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n { name: 'balance', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'TransferFailed',\n },\n { type: 'error', inputs: [], name: 'UnauthorizedUniswapCallback' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// PanopticFactoryV3\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const panopticFactoryV3Abi = [\n {\n type: 'constructor',\n inputs: [\n {\n name: '_SFPM',\n internalType: 'contract SemiFungiblePositionManagerV3',\n type: 'address',\n },\n {\n name: '_univ3Factory',\n internalType: 'contract IUniswapV3Factory',\n type: 'address',\n },\n { name: '_poolReference', internalType: 'address', type: 'address' },\n {\n name: '_collateralReference',\n internalType: 'address',\n type: 'address',\n },\n { name: 'properties', internalType: 'bytes32[]', type: 'bytes32[]' },\n { name: 'indices', internalType: 'uint256[][]', type: 'uint256[][]' },\n { name: 'pointers', internalType: 'Pointer[][]', type: 'uint256[][]' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'spender', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'approve',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'balanceOf',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'panopticPool', internalType: 'address', type: 'address' },\n { name: 'symbol0', internalType: 'string', type: 'string' },\n { name: 'symbol1', internalType: 'string', type: 'string' },\n { name: 'fee', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'constructMetadata',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'token0', internalType: 'address', type: 'address' },\n { name: 'token1', internalType: 'address', type: 'address' },\n { name: 'fee', internalType: 'uint24', type: 'uint24' },\n {\n name: 'riskEngine',\n internalType: 'contract IRiskEngine',\n type: 'address',\n },\n { name: 'salt', internalType: 'uint96', type: 'uint96' },\n ],\n name: 'deployNewPool',\n outputs: [\n {\n name: 'newPoolContract',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n name: 'getApproved',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'univ3pool',\n internalType: 'contract IUniswapV3Pool',\n type: 'address',\n },\n {\n name: 'riskEngine',\n internalType: 'contract IRiskEngine',\n type: 'address',\n },\n ],\n name: 'getPanopticPool',\n outputs: [{ name: '', internalType: 'contract PanopticPoolV2', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'address', type: 'address' },\n ],\n name: 'isApprovedForAll',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'deployerAddress', internalType: 'address', type: 'address' },\n { name: 'v3Pool', internalType: 'address', type: 'address' },\n { name: 'riskEngine', internalType: 'address', type: 'address' },\n { name: 'salt', internalType: 'uint96', type: 'uint96' },\n { name: 'loops', internalType: 'uint256', type: 'uint256' },\n { name: 'minTargetRarity', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'minePoolAddress',\n outputs: [\n { name: 'bestSalt', internalType: 'uint96', type: 'uint96' },\n { name: 'highestRarity', internalType: 'uint256', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes[]', type: 'bytes[]' }],\n name: 'multicall',\n outputs: [{ name: 'results', internalType: 'bytes[]', type: 'bytes[]' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'name',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'id', internalType: 'uint256', type: 'uint256' }],\n name: 'ownerOf',\n outputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'safeTransferFrom',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n { name: 'data', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'safeTransferFrom',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'operator', internalType: 'address', type: 'address' },\n { name: 'approved', internalType: 'bool', type: 'bool' },\n ],\n name: 'setApprovalForAll',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'interfaceId', internalType: 'bytes4', type: 'bytes4' }],\n name: 'supportsInterface',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'symbol',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'tokenId', internalType: 'uint256', type: 'uint256' }],\n name: 'tokenURI',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'transferFrom',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'spender',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'id', internalType: 'uint256', type: 'uint256', indexed: true },\n ],\n name: 'Approval',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'approved', internalType: 'bool', type: 'bool', indexed: false },\n ],\n name: 'ApprovalForAll',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'poolAddress',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n indexed: true,\n },\n {\n name: 'uniswapPool',\n internalType: 'contract IUniswapV3Pool',\n type: 'address',\n indexed: true,\n },\n {\n name: 'collateralTracker0',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n indexed: false,\n },\n {\n name: 'collateralTracker1',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n indexed: false,\n },\n {\n name: 'riskEngine',\n internalType: 'contract IRiskEngine',\n type: 'address',\n indexed: false,\n },\n ],\n name: 'PoolDeployed',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'from', internalType: 'address', type: 'address', indexed: true },\n { name: 'to', internalType: 'address', type: 'address', indexed: true },\n { name: 'id', internalType: 'uint256', type: 'uint256', indexed: true },\n ],\n name: 'Transfer',\n },\n { type: 'error', inputs: [], name: 'AlreadyInitialized' },\n { type: 'error', inputs: [], name: 'CreateFail' },\n { type: 'error', inputs: [], name: 'PoolNotInitialized' },\n { type: 'error', inputs: [], name: 'ZeroAddress' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// PanopticFactoryV4\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const panopticFactoryV4Abi = [\n {\n type: 'constructor',\n inputs: [\n {\n name: '_SFPM',\n internalType: 'contract SemiFungiblePositionManagerV4',\n type: 'address',\n },\n {\n name: '_manager',\n internalType: 'contract IPoolManager',\n type: 'address',\n },\n { name: '_poolReference', internalType: 'address', type: 'address' },\n {\n name: '_collateralReference',\n internalType: 'address',\n type: 'address',\n },\n { name: 'properties', internalType: 'bytes32[]', type: 'bytes32[]' },\n { name: 'indices', internalType: 'uint256[][]', type: 'uint256[][]' },\n { name: 'pointers', internalType: 'Pointer[][]', type: 'uint256[][]' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'spender', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'approve',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n name: 'balanceOf',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'panopticPool', internalType: 'address', type: 'address' },\n { name: 'symbol0', internalType: 'string', type: 'string' },\n { name: 'symbol1', internalType: 'string', type: 'string' },\n { name: 'fee', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'constructMetadata',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'key',\n internalType: 'struct PoolKey',\n type: 'tuple',\n components: [\n { name: 'currency0', internalType: 'Currency', type: 'address' },\n { name: 'currency1', internalType: 'Currency', type: 'address' },\n { name: 'fee', internalType: 'uint24', type: 'uint24' },\n { name: 'tickSpacing', internalType: 'int24', type: 'int24' },\n { name: 'hooks', internalType: 'contract IHooks', type: 'address' },\n ],\n },\n {\n name: 'riskEngine',\n internalType: 'contract IRiskEngine',\n type: 'address',\n },\n { name: 'salt', internalType: 'uint96', type: 'uint96' },\n ],\n name: 'deployNewPool',\n outputs: [\n {\n name: 'newPoolContract',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n name: 'getApproved',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'keyV4',\n internalType: 'struct PoolKey',\n type: 'tuple',\n components: [\n { name: 'currency0', internalType: 'Currency', type: 'address' },\n { name: 'currency1', internalType: 'Currency', type: 'address' },\n { name: 'fee', internalType: 'uint24', type: 'uint24' },\n { name: 'tickSpacing', internalType: 'int24', type: 'int24' },\n { name: 'hooks', internalType: 'contract IHooks', type: 'address' },\n ],\n },\n {\n name: 'riskEngine',\n internalType: 'contract IRiskEngine',\n type: 'address',\n },\n ],\n name: 'getPanopticPool',\n outputs: [{ name: '', internalType: 'contract PanopticPoolV2', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'address', type: 'address' },\n ],\n name: 'isApprovedForAll',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'deployerAddress', internalType: 'address', type: 'address' },\n {\n name: 'key',\n internalType: 'struct PoolKey',\n type: 'tuple',\n components: [\n { name: 'currency0', internalType: 'Currency', type: 'address' },\n { name: 'currency1', internalType: 'Currency', type: 'address' },\n { name: 'fee', internalType: 'uint24', type: 'uint24' },\n { name: 'tickSpacing', internalType: 'int24', type: 'int24' },\n { name: 'hooks', internalType: 'contract IHooks', type: 'address' },\n ],\n },\n { name: 'riskEngine', internalType: 'address', type: 'address' },\n { name: 'salt', internalType: 'uint96', type: 'uint96' },\n { name: 'loops', internalType: 'uint256', type: 'uint256' },\n { name: 'minTargetRarity', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'minePoolAddress',\n outputs: [\n { name: 'bestSalt', internalType: 'uint96', type: 'uint96' },\n { name: 'highestRarity', internalType: 'uint256', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes[]', type: 'bytes[]' }],\n name: 'multicall',\n outputs: [{ name: 'results', internalType: 'bytes[]', type: 'bytes[]' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'name',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'id', internalType: 'uint256', type: 'uint256' }],\n name: 'ownerOf',\n outputs: [{ name: 'owner', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'safeTransferFrom',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n { name: 'data', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'safeTransferFrom',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'operator', internalType: 'address', type: 'address' },\n { name: 'approved', internalType: 'bool', type: 'bool' },\n ],\n name: 'setApprovalForAll',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'interfaceId', internalType: 'bytes4', type: 'bytes4' }],\n name: 'supportsInterface',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'symbol',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'tokenId', internalType: 'uint256', type: 'uint256' }],\n name: 'tokenURI',\n outputs: [{ name: '', internalType: 'string', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'id', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'transferFrom',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'spender',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'id', internalType: 'uint256', type: 'uint256', indexed: true },\n ],\n name: 'Approval',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'approved', internalType: 'bool', type: 'bool', indexed: false },\n ],\n name: 'ApprovalForAll',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'poolAddress',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n indexed: true,\n },\n { name: 'idV4', internalType: 'PoolId', type: 'bytes32', indexed: true },\n {\n name: 'collateralTracker0',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n indexed: false,\n },\n {\n name: 'collateralTracker1',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n indexed: false,\n },\n {\n name: 'riskEngine',\n internalType: 'contract IRiskEngine',\n type: 'address',\n indexed: false,\n },\n ],\n name: 'PoolDeployed',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'from', internalType: 'address', type: 'address', indexed: true },\n { name: 'to', internalType: 'address', type: 'address', indexed: true },\n { name: 'id', internalType: 'uint256', type: 'uint256', indexed: true },\n ],\n name: 'Transfer',\n },\n { type: 'error', inputs: [], name: 'AlreadyInitialized' },\n { type: 'error', inputs: [], name: 'CreateFail' },\n { type: 'error', inputs: [], name: 'PoolNotInitialized' },\n { type: 'error', inputs: [], name: 'ZeroAddress' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// PanopticGuardian\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const panopticGuardianAbi = [\n {\n type: 'constructor',\n inputs: [\n { name: 'guardianAdmin', internalType: 'address', type: 'address' },\n { name: 'treasurer', internalType: 'address', type: 'address' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'GUARDIAN_ADMIN',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'TREASURER',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'UNLOCK_DELAY',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: '', internalType: 'address', type: 'address' }],\n name: 'builderAdminRevoked',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'cancelUnlock',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'riskEngine',\n internalType: 'contract IRiskEngine',\n type: 'address',\n },\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'recipient', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'collect',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'builderCode', internalType: 'uint256', type: 'uint256' },\n { name: 'builderAdmin', internalType: 'address', type: 'address' },\n {\n name: 'builderFactory',\n internalType: 'contract BuilderFactory',\n type: 'address',\n },\n ],\n name: 'deployBuilder',\n outputs: [{ name: 'wallet', internalType: 'address', type: 'address' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'executeUnlock',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'account', internalType: 'address', type: 'address' },\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'builderCode', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'isBuilderAdmin',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'isPoolUnlockReady',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'lockPool',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'builderCode', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'lockPoolAsBuilder',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'requestUnlock',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'admin', internalType: 'address', type: 'address' },\n { name: 'revoked', internalType: 'bool', type: 'bool' },\n ],\n name: 'setBuilderAdminRevoked',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: '', internalType: 'contract PanopticPoolV2', type: 'address' }],\n name: 'unlockEta',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'admin',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n ],\n name: 'BuilderAdminRestored',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'admin',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n ],\n name: 'BuilderAdminRevoked',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'builderCode',\n internalType: 'uint256',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'wallet',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n ],\n name: 'BuilderDeployed',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n indexed: true,\n },\n {\n name: 'locker',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n ],\n name: 'PoolLocked',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n indexed: true,\n },\n ],\n name: 'PoolUnlocked',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'token',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'recipient',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'amount',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'TokensCollected',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n indexed: true,\n },\n ],\n name: 'UnlockCancelled',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n indexed: true,\n },\n { name: 'eta', internalType: 'uint256', type: 'uint256', indexed: false },\n ],\n name: 'UnlockRequested',\n },\n { type: 'error', inputs: [], name: 'InvalidBuilderCode' },\n { type: 'error', inputs: [], name: 'NoPendingUnlock' },\n { type: 'error', inputs: [], name: 'NotAuthorizedBuilder' },\n { type: 'error', inputs: [], name: 'NotFactoryAdmin' },\n { type: 'error', inputs: [], name: 'NotGuardianAdmin' },\n { type: 'error', inputs: [], name: 'NotTreasurer' },\n { type: 'error', inputs: [], name: 'UnlockAlreadyPending' },\n {\n type: 'error',\n inputs: [{ name: 'eta', internalType: 'uint256', type: 'uint256' }],\n name: 'UnlockNotReady',\n },\n { type: 'error', inputs: [], name: 'ZeroAddress' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// PanopticLiquidator\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const panopticLiquidatorAbi = [\n {\n type: 'constructor',\n inputs: [\n { name: 'morpho', internalType: 'contract IMorpho', type: 'address' },\n { name: 'owner_', internalType: 'address', type: 'address' },\n ],\n stateMutability: 'nonpayable',\n },\n { type: 'receive', stateMutability: 'payable' },\n {\n type: 'function',\n inputs: [],\n name: 'MORPHO',\n outputs: [{ name: '', internalType: 'contract IMorpho', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'target', internalType: 'address', type: 'address' },\n { name: 'value', internalType: 'uint256', type: 'uint256' },\n { name: 'data', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'execute',\n outputs: [{ name: 'ret', internalType: 'bytes', type: 'bytes' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'initializePool',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'params',\n internalType: 'struct PanopticLiquidator.LiquidateParams',\n type: 'tuple',\n components: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n {\n name: 'positionIdListTo',\n internalType: 'TokenId[]',\n type: 'uint256[]',\n },\n {\n name: 'usePremiaAsCollateral',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n { name: 'flashToken', internalType: 'address', type: 'address' },\n { name: 'flashAmount', internalType: 'uint256', type: 'uint256' },\n {\n name: 'nativeFundingAmount',\n internalType: 'uint256',\n type: 'uint256',\n },\n { name: 'preSwapTarget', internalType: 'address', type: 'address' },\n { name: 'preSwapCallData', internalType: 'bytes', type: 'bytes' },\n { name: 'preSwapTokenIn', internalType: 'address', type: 'address' },\n { name: 'preSwapAmountIn', internalType: 'uint256', type: 'uint256' },\n { name: 'swapTarget', internalType: 'address', type: 'address' },\n { name: 'swapCallData', internalType: 'bytes', type: 'bytes' },\n { name: 'swapTokenIn', internalType: 'address', type: 'address' },\n { name: 'swapAmountIn', internalType: 'uint256', type: 'uint256' },\n { name: 'minDelta0', internalType: 'int256', type: 'int256' },\n { name: 'minDelta1', internalType: 'int256', type: 'int256' },\n ],\n },\n ],\n name: 'liquidate',\n outputs: [\n { name: 'delta0', internalType: 'int256', type: 'int256' },\n { name: 'delta1', internalType: 'int256', type: 'int256' },\n ],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes[]', type: 'bytes[]' }],\n name: 'multicall',\n outputs: [{ name: 'results', internalType: 'bytes[]', type: 'bytes[]' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'assets', internalType: 'uint256', type: 'uint256' },\n { name: 'data', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'onMorphoFlashLoan',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'owner',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'params',\n internalType: 'struct PanopticLiquidator.LiquidateParams',\n type: 'tuple',\n components: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n {\n name: 'positionIdListTo',\n internalType: 'TokenId[]',\n type: 'uint256[]',\n },\n {\n name: 'usePremiaAsCollateral',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n { name: 'flashToken', internalType: 'address', type: 'address' },\n { name: 'flashAmount', internalType: 'uint256', type: 'uint256' },\n {\n name: 'nativeFundingAmount',\n internalType: 'uint256',\n type: 'uint256',\n },\n { name: 'preSwapTarget', internalType: 'address', type: 'address' },\n { name: 'preSwapCallData', internalType: 'bytes', type: 'bytes' },\n { name: 'preSwapTokenIn', internalType: 'address', type: 'address' },\n { name: 'preSwapAmountIn', internalType: 'uint256', type: 'uint256' },\n { name: 'swapTarget', internalType: 'address', type: 'address' },\n { name: 'swapCallData', internalType: 'bytes', type: 'bytes' },\n { name: 'swapTokenIn', internalType: 'address', type: 'address' },\n { name: 'swapAmountIn', internalType: 'uint256', type: 'uint256' },\n { name: 'minDelta0', internalType: 'int256', type: 'int256' },\n { name: 'minDelta1', internalType: 'int256', type: 'int256' },\n ],\n },\n ],\n name: 'quoteLiquidation',\n outputs: [\n { name: 'bonus0', internalType: 'int256', type: 'int256' },\n { name: 'bonus1', internalType: 'int256', type: 'int256' },\n { name: 'shortfall0', internalType: 'uint256', type: 'uint256' },\n { name: 'shortfall1', internalType: 'uint256', type: 'uint256' },\n { name: 'protocolLoss0', internalType: 'uint256', type: 'uint256' },\n { name: 'protocolLoss1', internalType: 'uint256', type: 'uint256' },\n ],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [{ name: 'newOwner', internalType: 'address', type: 'address' }],\n name: 'setOwner',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'to', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'sweep',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'user', internalType: 'address', type: 'address', indexed: true },\n {\n name: 'newOwner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n ],\n name: 'OwnerUpdated',\n },\n { type: 'error', inputs: [], name: 'ApproveFailed' },\n { type: 'error', inputs: [], name: 'CallFailed' },\n {\n type: 'error',\n inputs: [\n { name: 'delta0', internalType: 'int256', type: 'int256' },\n { name: 'delta1', internalType: 'int256', type: 'int256' },\n ],\n name: 'InsufficientDelta',\n },\n { type: 'error', inputs: [], name: 'SwapFailed' },\n {\n type: 'error',\n inputs: [\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n { name: 'balance', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'TransferFailed',\n },\n { type: 'error', inputs: [], name: 'UntrustedFlashLoanInitiator' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// PanopticPoolV2\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const panopticPoolV2Abi = [\n {\n type: 'constructor',\n inputs: [\n {\n name: '_sfpm',\n internalType: 'contract ISemiFungiblePositionManager',\n type: 'address',\n },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'SFPM',\n outputs: [\n {\n name: '',\n internalType: 'contract ISemiFungiblePositionManager',\n type: 'address',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'minValue0', internalType: 'uint256', type: 'uint256' },\n { name: 'minValue1', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'assertMinCollateralValues',\n outputs: [],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'collateralToken0',\n outputs: [\n {\n name: '',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n ],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'collateralToken1',\n outputs: [\n {\n name: '',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n ],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n {\n name: 'finalPositionIdList',\n internalType: 'TokenId[]',\n type: 'uint256[]',\n },\n { name: 'positionSizes', internalType: 'uint128[]', type: 'uint128[]' },\n {\n name: 'tickAndSpreadLimits',\n internalType: 'int24[3][]',\n type: 'int24[3][]',\n },\n { name: 'usePremiaAsCollateral', internalType: 'bool', type: 'bool' },\n { name: 'builderCode', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'dispatch',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'positionIdListFrom',\n internalType: 'TokenId[]',\n type: 'uint256[]',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n {\n name: 'positionIdListTo',\n internalType: 'TokenId[]',\n type: 'uint256[]',\n },\n {\n name: 'positionIdListToFinal',\n internalType: 'TokenId[]',\n type: 'uint256[]',\n },\n {\n name: 'usePremiaAsCollateral',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n ],\n name: 'dispatchFrom',\n outputs: [],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [{ name: 'account', internalType: 'address', type: 'address' }],\n name: 'getAssetsOf',\n outputs: [\n { name: 'assets0', internalType: 'uint256', type: 'uint256' },\n { name: 'assets1', internalType: 'uint256', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'tickLower', internalType: 'int24', type: 'int24' },\n { name: 'tickUpper', internalType: 'int24', type: 'int24' },\n ],\n name: 'getChunkData',\n outputs: [\n {\n name: 'liquidities0',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'liquidities1',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n { name: 'settled0', internalType: 'LeftRightUnsigned', type: 'uint256' },\n { name: 'settled1', internalType: 'LeftRightUnsigned', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'getCurrentTick',\n outputs: [{ name: 'currentTick', internalType: 'int24', type: 'int24' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'user', internalType: 'address', type: 'address' },\n { name: 'includePendingPremium', internalType: 'bool', type: 'bool' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n ],\n name: 'getFullPositionsData',\n outputs: [\n {\n name: 'shortPremium',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'longPremium',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'positionBalances',\n internalType: 'PositionBalance[]',\n type: 'uint256[]',\n },\n {\n name: 'collateralRequirements',\n internalType: 'LeftRightUnsigned[]',\n type: 'uint256[]',\n },\n {\n name: 'netPremiaPerPosition',\n internalType: 'LeftRightSigned[]',\n type: 'int256[]',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'getOracleTicks',\n outputs: [\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n { name: 'spotTick', internalType: 'int24', type: 'int24' },\n { name: 'medianTick', internalType: 'int24', type: 'int24' },\n { name: 'latestTick', internalType: 'int24', type: 'int24' },\n { name: 'oraclePack', internalType: 'OraclePack', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'builderCode', internalType: 'uint256', type: 'uint256' }],\n name: 'getRiskParameters',\n outputs: [\n {\n name: 'riskParameters',\n internalType: 'RiskParameters',\n type: 'uint256',\n },\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'getTWAP',\n outputs: [{ name: 'twapTick', internalType: 'int24', type: 'int24' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'initialize',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'isSafeMode',\n outputs: [{ name: '', internalType: 'uint8', type: 'uint8' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'lockSafeMode',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes[]', type: 'bytes[]' }],\n name: 'multicall',\n outputs: [{ name: 'results', internalType: 'bytes[]', type: 'bytes[]' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [{ name: 'user', internalType: 'address', type: 'address' }],\n name: 'numberOfLegs',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n { name: '', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'onERC1155Received',\n outputs: [{ name: '', internalType: 'bytes4', type: 'bytes4' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'pokeOracle',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'poolId',\n outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'poolKey',\n outputs: [{ name: 'key', internalType: 'bytes', type: 'bytes' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'poolManager',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'reentrancyGuardEntered',\n outputs: [{ name: 'entered', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'riskEngine',\n outputs: [{ name: '', internalType: 'contract IRiskEngine', type: 'address' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'tickSpacing',\n outputs: [{ name: '', internalType: 'int24', type: 'int24' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [],\n name: 'unlockSafeMode',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'user', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n { name: 'usePremiaAsCollateral', internalType: 'bool', type: 'bool' },\n ],\n name: 'validateCollateralWithdrawable',\n outputs: [],\n stateMutability: 'view',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'liquidator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'liquidatee',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'bonusAmounts',\n internalType: 'LeftRightSigned',\n type: 'int256',\n indexed: false,\n },\n ],\n name: 'AccountLiquidated',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'exercisor',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'user', internalType: 'address', type: 'address', indexed: true },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'exerciseFee',\n internalType: 'LeftRightSigned',\n type: 'int256',\n indexed: false,\n },\n ],\n name: 'ForcedExercised',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'recipient',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'positionSize',\n internalType: 'uint128',\n type: 'uint128',\n indexed: false,\n },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'premiaByLeg',\n internalType: 'LeftRightSigned[4]',\n type: 'int256[4]',\n indexed: false,\n },\n ],\n name: 'OptionBurnt',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'recipient',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'balanceData',\n internalType: 'PositionBalance',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'OptionMinted',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'user', internalType: 'address', type: 'address', indexed: true },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'legIndex',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n {\n name: 'settledAmounts',\n internalType: 'LeftRightSigned',\n type: 'int256',\n indexed: false,\n },\n ],\n name: 'PremiumSettled',\n },\n {\n type: 'error',\n inputs: [\n { name: 'solvent', internalType: 'uint256', type: 'uint256' },\n { name: 'numberOfTicks', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'AccountInsolvent',\n },\n { type: 'error', inputs: [], name: 'AlreadyInitialized' },\n { type: 'error', inputs: [], name: 'CastingError' },\n { type: 'error', inputs: [], name: 'DuplicateTokenId' },\n { type: 'error', inputs: [], name: 'EffectiveLiquidityAboveThreshold' },\n { type: 'error', inputs: [], name: 'InputListFail' },\n { type: 'error', inputs: [], name: 'InvalidTick' },\n { type: 'error', inputs: [], name: 'InvalidTickBound' },\n { type: 'error', inputs: [], name: 'LiquidityTooHigh' },\n { type: 'error', inputs: [], name: 'NetLiquidityZero' },\n { type: 'error', inputs: [], name: 'NoLegsExercisable' },\n { type: 'error', inputs: [], name: 'NotGuardian' },\n { type: 'error', inputs: [], name: 'NotMarginCalled' },\n { type: 'error', inputs: [], name: 'PositionNotOwned' },\n { type: 'error', inputs: [], name: 'PriceImpactTooLarge' },\n { type: 'error', inputs: [], name: 'Reentrancy' },\n { type: 'error', inputs: [], name: 'StaleOracle' },\n { type: 'error', inputs: [], name: 'TokenIdHasZeroLegs' },\n { type: 'error', inputs: [], name: 'TooManyLegsOpen' },\n { type: 'error', inputs: [], name: 'UnderOverFlow' },\n { type: 'error', inputs: [], name: 'WrongPoolId' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// PanopticQuery\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const panopticQueryAbi = [\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n ],\n name: 'checkCollateral',\n outputs: [\n {\n name: 'collateralBalances0',\n internalType: 'uint256[4]',\n type: 'uint256[4]',\n },\n {\n name: 'requiredCollaterals0',\n internalType: 'uint256[4]',\n type: 'uint256[4]',\n },\n {\n name: 'collateralBalances1',\n internalType: 'uint256[4]',\n type: 'uint256[4]',\n },\n {\n name: 'requiredCollaterals1',\n internalType: 'uint256[4]',\n type: 'uint256[4]',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n ],\n name: 'checkCollateral',\n outputs: [\n {\n name: 'balancesAndRequired',\n internalType: 'uint256[4]',\n type: 'uint256[4]',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n ],\n name: 'checkCollateralListOutput',\n outputs: [\n { name: '', internalType: 'uint256[4][]', type: 'uint256[4][]' },\n { name: '', internalType: 'int256[]', type: 'int256[]' },\n { name: '', internalType: 'int24[]', type: 'int24[]' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n {\n name: 'shortPremium',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'longPremium',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'positionBalanceArray',\n internalType: 'PositionBalance[]',\n type: 'uint256[]',\n },\n { name: 'atTicks', internalType: 'int24[]', type: 'int24[]' },\n ],\n name: 'computeNetLiquidationValue',\n outputs: [\n { name: 'value0', internalType: 'int256[]', type: 'int256[]' },\n { name: 'value1', internalType: 'int256[]', type: 'int256[]' },\n ],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n ],\n name: 'getChunkData',\n outputs: [{ name: '', internalType: 'uint256[2][4][]', type: 'uint256[2][4][]' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n { name: 'positionSize', internalType: 'uint128', type: 'uint128' },\n ],\n name: 'getItmAmounts',\n outputs: [\n { name: 'itm0', internalType: 'int256', type: 'int256' },\n { name: 'itm1', internalType: 'int256', type: 'int256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n ],\n name: 'getLiquidationPrices',\n outputs: [\n { name: 'liquidationPriceDown', internalType: 'int24', type: 'int24' },\n { name: 'liquidationPriceUp', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n {\n name: 'existingPositionIds',\n internalType: 'TokenId[]',\n type: 'uint256[]',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n ],\n name: 'getMaxPositionSizeBounds',\n outputs: [\n { name: 'maxSizeAtMinUtil', internalType: 'uint128', type: 'uint128' },\n { name: 'maxSizeAtMaxUtil', internalType: 'uint128', type: 'uint128' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'includePendingPremium', internalType: 'bool', type: 'bool' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n { name: 'atTicks', internalType: 'int24[]', type: 'int24[]' },\n ],\n name: 'getNetLiquidationValue',\n outputs: [\n { name: 'value0', internalType: 'int256[]', type: 'int256[]' },\n { name: 'value1', internalType: 'int256[]', type: 'int256[]' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n ],\n name: 'getPortfolioValue',\n outputs: [\n { name: 'value0', internalType: 'int256', type: 'int256' },\n { name: 'value1', internalType: 'int256', type: 'int256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n ],\n name: 'getRequiredBase',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'startTick', internalType: 'int24', type: 'int24' },\n { name: 'nTicks', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'getTickNets',\n outputs: [\n { name: 'tickData', internalType: 'int256[]', type: 'int256[]' },\n { name: 'liquidityNets', internalType: 'int256[]', type: 'int256[]' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'univ3pool',\n internalType: 'contract IUniswapV3Pool',\n type: 'address',\n },\n { name: 'startTick', internalType: 'int24', type: 'int24' },\n { name: 'nTicks', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'getTickNetsV3',\n outputs: [\n { name: 'tickData', internalType: 'int256[]', type: 'int256[]' },\n { name: 'liquidityNets', internalType: 'int256[]', type: 'int256[]' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'manager',\n internalType: 'contract IPoolManager',\n type: 'address',\n },\n { name: 'poolId', internalType: 'PoolId', type: 'bytes32' },\n { name: 'tickSpacing', internalType: 'int24', type: 'int24' },\n { name: 'startTick', internalType: 'int24', type: 'int24' },\n { name: 'nTicks', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'getTickNetsV4',\n outputs: [\n { name: 'tickData', internalType: 'int256[]', type: 'int256[]' },\n { name: 'liquidityNets', internalType: 'int256[]', type: 'int256[]' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n ],\n name: 'isAccountSolvent',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n ],\n name: 'optimizeRiskPartners',\n outputs: [{ name: '', internalType: 'TokenId', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n { name: 'tickLower', internalType: 'int24', type: 'int24' },\n { name: 'tickUpper', internalType: 'int24', type: 'int24' },\n { name: 'width', internalType: 'int24', type: 'int24' },\n ],\n name: 'scanChunks',\n outputs: [\n { name: '', internalType: 'int24[]', type: 'int24[]' },\n { name: '', internalType: 'uint128[2][]', type: 'uint128[2][]' },\n { name: '', internalType: 'uint128[2][]', type: 'uint128[2][]' },\n {\n name: '',\n internalType: 'LeftRightUnsigned[2][]',\n type: 'uint256[2][]',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'self', internalType: 'TokenId', type: 'uint256' }],\n name: 'validateTokenId',\n outputs: [],\n stateMutability: 'pure',\n },\n { type: 'error', inputs: [], name: 'CastingError' },\n { type: 'error', inputs: [], name: 'InvalidTick' },\n {\n type: 'error',\n inputs: [{ name: 'parameterType', internalType: 'uint256', type: 'uint256' }],\n name: 'InvalidTokenIdParameter',\n },\n { type: 'error', inputs: [], name: 'LiquidityTooHigh' },\n { type: 'error', inputs: [], name: 'UnderOverFlow' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// RiskEngine\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const riskEngineAbi = [\n {\n type: 'constructor',\n inputs: [\n { name: '_crossBuffer0', internalType: 'uint256', type: 'uint256' },\n { name: '_crossBuffer1', internalType: 'uint256', type: 'uint256' },\n { name: '_guardian', internalType: 'address', type: 'address' },\n { name: '_builderFactory', internalType: 'address', type: 'address' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'ADJUSTMENT_SPEED',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'BP_DECREASE_BUFFER',\n outputs: [{ name: '', internalType: 'uint32', type: 'uint32' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'BUILDER_FACTORY',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'BUILDER_SPLIT',\n outputs: [{ name: '', internalType: 'uint16', type: 'uint16' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'BUYER_COLLATERAL_RATIO',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'CROSS_BUFFER_0',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'CROSS_BUFFER_1',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'CURVE_STEEPNESS',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'DECIMALS',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'EMA_PERIODS',\n outputs: [{ name: '', internalType: 'uint96', type: 'uint96' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'FORCE_EXERCISE_COST',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'GUARDIAN',\n outputs: [{ name: '', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'INITIAL_RATE_AT_TARGET',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'IRM_MAX_ELAPSED_TIME',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAINT_MARGIN_RATE',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAX_BONUS',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAX_CLAMP_DELTA',\n outputs: [{ name: '', internalType: 'int24', type: 'int24' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAX_OPEN_LEGS',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAX_RATE_AT_TARGET',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAX_SPREAD',\n outputs: [{ name: '', internalType: 'uint24', type: 'uint24' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAX_TICKS_DELTA',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MAX_TWAP_DELTA_DISPATCH',\n outputs: [{ name: '', internalType: 'uint16', type: 'uint16' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'MIN_RATE_AT_TARGET',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'NOTIONAL_FEE',\n outputs: [{ name: '', internalType: 'uint16', type: 'uint16' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'PREMIUM_FEE',\n outputs: [{ name: '', internalType: 'uint16', type: 'uint16' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'PROTOCOL_SPLIT',\n outputs: [{ name: '', internalType: 'uint16', type: 'uint16' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'SATURATED_POOL_UTIL',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'SELLER_COLLATERAL_RATIO',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'TARGET_POOL_UTIL',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'TARGET_UTILIZATION',\n outputs: [{ name: '', internalType: 'int256', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'VEGOID',\n outputs: [{ name: '', internalType: 'uint8', type: 'uint8' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'recipient', internalType: 'address', type: 'address' },\n ],\n name: 'collect',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'recipient', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'collect',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'oraclePack', internalType: 'OraclePack', type: 'uint256' },\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n ],\n name: 'computeInternalMedian',\n outputs: [\n { name: 'medianTick', internalType: 'int24', type: 'int24' },\n {\n name: 'updatedOraclePack',\n internalType: 'OraclePack',\n type: 'uint256',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'utilization', internalType: 'int256', type: 'int256' },\n { name: 'crossBuffer', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'crossBufferRatio',\n outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n { name: 'oracleTick', internalType: 'int24', type: 'int24' },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n {\n name: 'positionBalance',\n internalType: 'PositionBalance',\n type: 'uint256',\n },\n ],\n name: 'exerciseCost',\n outputs: [{ name: 'exerciseFees', internalType: 'LeftRightSigned', type: 'int256' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [{ name: 'builderCode', internalType: 'uint256', type: 'uint256' }],\n name: 'getFeeRecipient',\n outputs: [{ name: 'feeRecipient', internalType: 'address', type: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'tokenData0',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'tokenData1',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n { name: 'atSqrtPriceX96', internalType: 'uint160', type: 'uint160' },\n { name: 'netPaid', internalType: 'LeftRightSigned', type: 'int256' },\n {\n name: 'shortPremium',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'loanAmounts',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n ],\n name: 'getLiquidationBonus',\n outputs: [\n { name: '', internalType: 'LeftRightSigned', type: 'int256' },\n { name: '', internalType: 'LeftRightSigned', type: 'int256' },\n ],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'positionBalanceArray',\n internalType: 'PositionBalance[]',\n type: 'uint256[]',\n },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n { name: 'user', internalType: 'address', type: 'address' },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n {\n name: 'shortPremia',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'longPremia',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'ct0',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n {\n name: 'ct1',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n ],\n name: 'getMargin',\n outputs: [\n {\n name: 'tokenData0',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'tokenData1',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'globalUtilizations',\n internalType: 'PositionBalance',\n type: 'uint256',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n { name: '_oraclePack', internalType: 'OraclePack', type: 'uint256' },\n ],\n name: 'getOracleTicks',\n outputs: [\n { name: 'spotTick', internalType: 'int24', type: 'int24' },\n { name: 'medianTick', internalType: 'int24', type: 'int24' },\n { name: 'latestTick', internalType: 'int24', type: 'int24' },\n { name: 'oraclePack', internalType: 'OraclePack', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'positionBalanceArray',\n internalType: 'PositionBalance[]',\n type: 'uint256[]',\n },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n ],\n name: 'getPerPositionCollateralRequirements',\n outputs: [\n {\n name: 'collateralRequirements',\n internalType: 'LeftRightUnsigned[]',\n type: 'uint256[]',\n },\n ],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'payor', internalType: 'address', type: 'address' },\n { name: 'fees', internalType: 'LeftRightSigned', type: 'int256' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n {\n name: 'ct0',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n {\n name: 'ct1',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n ],\n name: 'getRefundAmounts',\n outputs: [{ name: '', internalType: 'LeftRightSigned', type: 'int256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n { name: 'oraclePack', internalType: 'OraclePack', type: 'uint256' },\n { name: 'builderCode', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'getRiskParameters',\n outputs: [{ name: '', internalType: 'RiskParameters', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n { name: '_oraclePack', internalType: 'OraclePack', type: 'uint256' },\n { name: 'safeMode', internalType: 'uint8', type: 'uint8' },\n ],\n name: 'getSolvencyTicks',\n outputs: [\n { name: '', internalType: 'int24[]', type: 'int24[]' },\n { name: '', internalType: 'OraclePack', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n {\n name: 'premiasByLeg',\n internalType: 'LeftRightSigned[4][]',\n type: 'int256[4][]',\n },\n {\n name: 'collateralRemaining',\n internalType: 'LeftRightSigned',\n type: 'int256',\n },\n { name: 'atSqrtPriceX96', internalType: 'uint160', type: 'uint160' },\n ],\n name: 'haircutPremia',\n outputs: [\n { name: 'bonusDeltas', internalType: 'LeftRightSigned', type: 'int256' },\n {\n name: 'haircutTotal',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'haircutPerLeg',\n internalType: 'LeftRightSigned[4][]',\n type: 'int256[4][]',\n },\n ],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'utilization', internalType: 'uint256', type: 'uint256' },\n {\n name: 'interestRateAccumulator',\n internalType: 'MarketState',\n type: 'uint256',\n },\n ],\n name: 'interestRate',\n outputs: [{ name: '', internalType: 'uint128', type: 'uint128' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'positionBalanceArray',\n internalType: 'PositionBalance[]',\n type: 'uint256[]',\n },\n { name: 'positionIdList', internalType: 'TokenId[]', type: 'uint256[]' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n { name: 'user', internalType: 'address', type: 'address' },\n {\n name: 'shortPremia',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'longPremia',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n {\n name: 'ct0',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n {\n name: 'ct1',\n internalType: 'contract CollateralTrackerV2',\n type: 'address',\n },\n { name: 'buffer', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'isAccountSolvent',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'currentTick', internalType: 'int24', type: 'int24' },\n { name: 'oraclePack', internalType: 'OraclePack', type: 'uint256' },\n ],\n name: 'isSafeMode',\n outputs: [{ name: 'safeMode', internalType: 'uint8', type: 'uint8' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'lockPool',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'oraclePack', internalType: 'OraclePack', type: 'uint256' }],\n name: 'twapEMA',\n outputs: [{ name: '', internalType: 'int24', type: 'int24' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'pool',\n internalType: 'contract PanopticPoolV2',\n type: 'address',\n },\n ],\n name: 'unlockPool',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'utilization', internalType: 'uint256', type: 'uint256' },\n {\n name: 'interestRateAccumulator',\n internalType: 'MarketState',\n type: 'uint256',\n },\n ],\n name: 'updateInterestRate',\n outputs: [\n { name: '', internalType: 'uint128', type: 'uint128' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [],\n name: 'vegoid',\n outputs: [{ name: '', internalType: 'uint8', type: 'uint8' }],\n stateMutability: 'pure',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'collateralToken',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'avgBorrowRate',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n {\n name: 'rateAtTarget',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'BorrowRateUpdated',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [{ name: 'lockMode', internalType: 'bool', type: 'bool', indexed: false }],\n name: 'GuardianSafeModeUpdated',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'token',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'recipient',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'amount',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'TokensCollected',\n },\n { type: 'error', inputs: [], name: 'BelowMinimumRedemption' },\n { type: 'error', inputs: [], name: 'CastingError' },\n { type: 'error', inputs: [], name: 'InvalidBuilderCode' },\n { type: 'error', inputs: [], name: 'InvalidTick' },\n { type: 'error', inputs: [], name: 'LengthMismatch' },\n { type: 'error', inputs: [], name: 'LiquidityTooHigh' },\n { type: 'error', inputs: [], name: 'NotGuardian' },\n {\n type: 'error',\n inputs: [\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n { name: 'balance', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'TransferFailed',\n },\n { type: 'error', inputs: [], name: 'UnderOverFlow' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// SemiFungiblePositionManagerV3\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const semiFungiblePositionManagerV3Abi = [\n {\n type: 'constructor',\n inputs: [\n {\n name: '_factory',\n internalType: 'contract IUniswapV3Factory',\n type: 'address',\n },\n {\n name: '_minEnforcedTickFillCost',\n internalType: 'uint256',\n type: 'uint256',\n },\n {\n name: '_supplyMultiplierTickFill',\n internalType: 'uint256',\n type: 'uint256',\n },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'tokenId', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'balanceOf',\n outputs: [{ name: 'balance', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'owners', internalType: 'address[]', type: 'address[]' },\n { name: 'ids', internalType: 'uint256[]', type: 'uint256[]' },\n ],\n name: 'balanceOfBatch',\n outputs: [{ name: 'balances', internalType: 'uint256[]', type: 'uint256[]' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n { name: 'positionSize', internalType: 'uint128', type: 'uint128' },\n { name: 'tickLimitLow', internalType: 'int24', type: 'int24' },\n { name: 'tickLimitHigh', internalType: 'int24', type: 'int24' },\n ],\n name: 'burnTokenizedPosition',\n outputs: [\n { name: '', internalType: 'LeftRightUnsigned[4]', type: 'uint256[4]' },\n { name: '', internalType: 'LeftRightSigned', type: 'int256' },\n { name: '', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n name: 'expandEnforcedTickRange',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'tokenType', internalType: 'uint256', type: 'uint256' },\n { name: 'tickLower', internalType: 'int24', type: 'int24' },\n { name: 'tickUpper', internalType: 'int24', type: 'int24' },\n ],\n name: 'getAccountFeesBase',\n outputs: [\n { name: 'feesBase0', internalType: 'int128', type: 'int128' },\n { name: 'feesBase1', internalType: 'int128', type: 'int128' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'tokenType', internalType: 'uint256', type: 'uint256' },\n { name: 'tickLower', internalType: 'int24', type: 'int24' },\n { name: 'tickUpper', internalType: 'int24', type: 'int24' },\n ],\n name: 'getAccountLiquidity',\n outputs: [\n {\n name: 'accountLiquidities',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'tokenType', internalType: 'uint256', type: 'uint256' },\n { name: 'tickLower', internalType: 'int24', type: 'int24' },\n { name: 'tickUpper', internalType: 'int24', type: 'int24' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n { name: 'isLong', internalType: 'uint256', type: 'uint256' },\n { name: 'vegoid', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'getAccountPremium',\n outputs: [\n { name: '', internalType: 'uint128', type: 'uint128' },\n { name: '', internalType: 'uint128', type: 'uint128' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolKey', internalType: 'bytes', type: 'bytes' }],\n name: 'getCurrentTick',\n outputs: [{ name: 'currentTick', internalType: 'int24', type: 'int24' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n name: 'getEnforcedTickLimits',\n outputs: [\n { name: '', internalType: 'int24', type: 'int24' },\n { name: '', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'id', internalType: 'bytes', type: 'bytes' },\n { name: 'vegoid', internalType: 'uint8', type: 'uint8' },\n ],\n name: 'getPoolId',\n outputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n name: 'getUniswapV3PoolFromId',\n outputs: [\n {\n name: 'uniswapV3Pool',\n internalType: 'contract IUniswapV3Pool',\n type: 'address',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'token0', internalType: 'address', type: 'address' },\n { name: 'token1', internalType: 'address', type: 'address' },\n { name: 'fee', internalType: 'uint24', type: 'uint24' },\n { name: 'vegoid', internalType: 'uint8', type: 'uint8' },\n ],\n name: 'initializeAMMPool',\n outputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'operator', internalType: 'address', type: 'address' },\n ],\n name: 'isApprovedForAll',\n outputs: [{ name: 'approvedForAll', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n { name: 'positionSize', internalType: 'uint128', type: 'uint128' },\n { name: 'tickLimitLow', internalType: 'int24', type: 'int24' },\n { name: 'tickLimitHigh', internalType: 'int24', type: 'int24' },\n ],\n name: 'mintTokenizedPosition',\n outputs: [\n { name: '', internalType: 'LeftRightUnsigned[4]', type: 'uint256[4]' },\n { name: '', internalType: 'LeftRightSigned', type: 'int256' },\n { name: '', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes[]', type: 'bytes[]' }],\n name: 'multicall',\n outputs: [{ name: 'results', internalType: 'bytes[]', type: 'bytes[]' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'reentrancyGuardEntered',\n outputs: [{ name: 'entered', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'uint256[]', type: 'uint256[]' },\n { name: '', internalType: 'uint256[]', type: 'uint256[]' },\n { name: '', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'safeBatchTransferFrom',\n outputs: [],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n { name: '', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'safeTransferFrom',\n outputs: [],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'operator', internalType: 'address', type: 'address' },\n { name: 'approved', internalType: 'bool', type: 'bool' },\n ],\n name: 'setApprovalForAll',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'interfaceId', internalType: 'bytes4', type: 'bytes4' }],\n name: 'supportsInterface',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'amount0Owed', internalType: 'uint256', type: 'uint256' },\n { name: 'amount1Owed', internalType: 'uint256', type: 'uint256' },\n { name: 'data', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'uniswapV3MintCallback',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'amount0Delta', internalType: 'int256', type: 'int256' },\n { name: 'amount1Delta', internalType: 'int256', type: 'int256' },\n { name: 'data', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'uniswapV3SwapCallback',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'approved', internalType: 'bool', type: 'bool', indexed: false },\n ],\n name: 'ApprovalForAll',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'uniswapPool',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'minEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'maxEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n ],\n name: 'EnforcedTicksUpdated',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'univ3pool',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'tokenType',\n internalType: 'uint256',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'tickLower',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'tickUpper',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'liquidityDelta',\n internalType: 'int128',\n type: 'int128',\n indexed: false,\n },\n ],\n name: 'LiquidityChunkUpdated',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'uniswapPool',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'poolId',\n internalType: 'uint64',\n type: 'uint64',\n indexed: false,\n },\n {\n name: 'minEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'maxEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n ],\n name: 'PoolInitialized',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'recipient',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'positionSize',\n internalType: 'uint128',\n type: 'uint128',\n indexed: false,\n },\n ],\n name: 'TokenizedPositionBurnt',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'caller',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'positionSize',\n internalType: 'uint128',\n type: 'uint128',\n indexed: false,\n },\n ],\n name: 'TokenizedPositionMinted',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'from', internalType: 'address', type: 'address', indexed: true },\n { name: 'to', internalType: 'address', type: 'address', indexed: true },\n {\n name: 'ids',\n internalType: 'uint256[]',\n type: 'uint256[]',\n indexed: false,\n },\n {\n name: 'amounts',\n internalType: 'uint256[]',\n type: 'uint256[]',\n indexed: false,\n },\n ],\n name: 'TransferBatch',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'from', internalType: 'address', type: 'address', indexed: true },\n { name: 'to', internalType: 'address', type: 'address', indexed: true },\n { name: 'id', internalType: 'uint256', type: 'uint256', indexed: false },\n {\n name: 'amount',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'TransferSingle',\n },\n { type: 'error', inputs: [], name: 'CastingError' },\n { type: 'error', inputs: [], name: 'ChunkHasZeroLiquidity' },\n { type: 'error', inputs: [], name: 'InvalidTick' },\n { type: 'error', inputs: [], name: 'InvalidTickBound' },\n {\n type: 'error',\n inputs: [{ name: 'parameterType', internalType: 'uint256', type: 'uint256' }],\n name: 'InvalidTokenIdParameter',\n },\n { type: 'error', inputs: [], name: 'InvalidUniswapCallback' },\n { type: 'error', inputs: [], name: 'LiquidityTooHigh' },\n { type: 'error', inputs: [], name: 'NotAuthorized' },\n { type: 'error', inputs: [], name: 'NotEnoughLiquidityInChunk' },\n { type: 'error', inputs: [], name: 'PoolNotInitialized' },\n { type: 'error', inputs: [], name: 'PositionTooLarge' },\n {\n type: 'error',\n inputs: [{ name: 'currentTick', internalType: 'int24', type: 'int24' }],\n name: 'PriceBoundFail',\n },\n { type: 'error', inputs: [], name: 'Reentrancy' },\n {\n type: 'error',\n inputs: [\n { name: 'token', internalType: 'address', type: 'address' },\n { name: 'from', internalType: 'address', type: 'address' },\n { name: 'amount', internalType: 'uint256', type: 'uint256' },\n { name: 'balance', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'TransferFailed',\n },\n { type: 'error', inputs: [], name: 'UnderOverFlow' },\n { type: 'error', inputs: [], name: 'UnsafeRecipient' },\n { type: 'error', inputs: [], name: 'WrongUniswapPool' },\n] as const\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// SemiFungiblePositionManagerV4\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport const semiFungiblePositionManagerV4Abi = [\n {\n type: 'constructor',\n inputs: [\n {\n name: 'poolManager',\n internalType: 'contract IPoolManager',\n type: 'address',\n },\n {\n name: '_minEnforcedTickFillCost',\n internalType: 'uint256',\n type: 'uint256',\n },\n {\n name: '_nativeEnforcedTickFillCost',\n internalType: 'uint256',\n type: 'uint256',\n },\n {\n name: '_supplyMultiplierTickFill',\n internalType: 'uint256',\n type: 'uint256',\n },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'account', internalType: 'address', type: 'address' },\n { name: 'tokenId', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'balanceOf',\n outputs: [{ name: 'balance', internalType: 'uint256', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'owners', internalType: 'address[]', type: 'address[]' },\n { name: 'ids', internalType: 'uint256[]', type: 'uint256[]' },\n ],\n name: 'balanceOfBatch',\n outputs: [{ name: 'balances', internalType: 'uint256[]', type: 'uint256[]' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n { name: 'positionSize', internalType: 'uint128', type: 'uint128' },\n { name: 'tickLimitLow', internalType: 'int24', type: 'int24' },\n { name: 'tickLimitHigh', internalType: 'int24', type: 'int24' },\n ],\n name: 'burnTokenizedPosition',\n outputs: [\n { name: '', internalType: 'LeftRightUnsigned[4]', type: 'uint256[4]' },\n { name: '', internalType: 'LeftRightSigned', type: 'int256' },\n { name: '', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n name: 'expandEnforcedTickRange',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'tokenType', internalType: 'uint256', type: 'uint256' },\n { name: 'tickLower', internalType: 'int24', type: 'int24' },\n { name: 'tickUpper', internalType: 'int24', type: 'int24' },\n ],\n name: 'getAccountLiquidity',\n outputs: [\n {\n name: 'accountLiquidities',\n internalType: 'LeftRightUnsigned',\n type: 'uint256',\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'tokenType', internalType: 'uint256', type: 'uint256' },\n { name: 'tickLower', internalType: 'int24', type: 'int24' },\n { name: 'tickUpper', internalType: 'int24', type: 'int24' },\n { name: 'atTick', internalType: 'int24', type: 'int24' },\n { name: 'isLong', internalType: 'uint256', type: 'uint256' },\n { name: 'vegoid', internalType: 'uint256', type: 'uint256' },\n ],\n name: 'getAccountPremium',\n outputs: [\n { name: '', internalType: 'uint128', type: 'uint128' },\n { name: '', internalType: 'uint128', type: 'uint128' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolKey', internalType: 'bytes', type: 'bytes' }],\n name: 'getCurrentTick',\n outputs: [{ name: 'currentTick', internalType: 'int24', type: 'int24' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n name: 'getEnforcedTickLimits',\n outputs: [\n { name: '', internalType: 'int24', type: 'int24' },\n { name: '', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'id', internalType: 'bytes', type: 'bytes' },\n { name: 'vegoid', internalType: 'uint8', type: 'uint8' },\n ],\n name: 'getPoolId',\n outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n name: 'getUniswapV4PoolKeyFromId',\n outputs: [\n {\n name: '',\n internalType: 'struct PoolKey',\n type: 'tuple',\n components: [\n { name: 'currency0', internalType: 'Currency', type: 'address' },\n { name: 'currency1', internalType: 'Currency', type: 'address' },\n { name: 'fee', internalType: 'uint24', type: 'uint24' },\n { name: 'tickSpacing', internalType: 'int24', type: 'int24' },\n { name: 'hooks', internalType: 'contract IHooks', type: 'address' },\n ],\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n {\n name: 'key',\n internalType: 'struct PoolKey',\n type: 'tuple',\n components: [\n { name: 'currency0', internalType: 'Currency', type: 'address' },\n { name: 'currency1', internalType: 'Currency', type: 'address' },\n { name: 'fee', internalType: 'uint24', type: 'uint24' },\n { name: 'tickSpacing', internalType: 'int24', type: 'int24' },\n { name: 'hooks', internalType: 'contract IHooks', type: 'address' },\n ],\n },\n { name: 'vegoid', internalType: 'uint8', type: 'uint8' },\n ],\n name: 'initializeAMMPool',\n outputs: [{ name: 'poolId', internalType: 'uint64', type: 'uint64' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [\n { name: 'owner', internalType: 'address', type: 'address' },\n { name: 'operator', internalType: 'address', type: 'address' },\n ],\n name: 'isApprovedForAll',\n outputs: [{ name: 'approvedForAll', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: 'poolKey', internalType: 'bytes', type: 'bytes' },\n { name: 'tokenId', internalType: 'TokenId', type: 'uint256' },\n { name: 'positionSize', internalType: 'uint128', type: 'uint128' },\n { name: 'tickLimitLow', internalType: 'int24', type: 'int24' },\n { name: 'tickLimitHigh', internalType: 'int24', type: 'int24' },\n ],\n name: 'mintTokenizedPosition',\n outputs: [\n { name: '', internalType: 'LeftRightUnsigned[4]', type: 'uint256[4]' },\n { name: '', internalType: 'LeftRightSigned', type: 'int256' },\n { name: '', internalType: 'int24', type: 'int24' },\n ],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes[]', type: 'bytes[]' }],\n name: 'multicall',\n outputs: [{ name: 'results', internalType: 'bytes[]', type: 'bytes[]' }],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n inputs: [],\n name: 'reentrancyGuardEntered',\n outputs: [{ name: 'entered', internalType: 'bool', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n inputs: [\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'uint256[]', type: 'uint256[]' },\n { name: '', internalType: 'uint256[]', type: 'uint256[]' },\n { name: '', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'safeBatchTransferFrom',\n outputs: [],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'address', type: 'address' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n { name: '', internalType: 'uint256', type: 'uint256' },\n { name: '', internalType: 'bytes', type: 'bytes' },\n ],\n name: 'safeTransferFrom',\n outputs: [],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [\n { name: 'operator', internalType: 'address', type: 'address' },\n { name: 'approved', internalType: 'bool', type: 'bool' },\n ],\n name: 'setApprovalForAll',\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n inputs: [{ name: 'interfaceId', internalType: 'bytes4', type: 'bytes4' }],\n name: 'supportsInterface',\n outputs: [{ name: '', internalType: 'bool', type: 'bool' }],\n stateMutability: 'pure',\n },\n {\n type: 'function',\n inputs: [{ name: 'data', internalType: 'bytes', type: 'bytes' }],\n name: 'unlockCallback',\n outputs: [{ name: '', internalType: 'bytes', type: 'bytes' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'approved', internalType: 'bool', type: 'bool', indexed: false },\n ],\n name: 'ApprovalForAll',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'idV4', internalType: 'PoolId', type: 'bytes32', indexed: true },\n {\n name: 'minEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'maxEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n ],\n name: 'EnforcedTicksUpdated',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'poolId',\n internalType: 'PoolId',\n type: 'bytes32',\n indexed: true,\n },\n {\n name: 'owner',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'tokenType',\n internalType: 'uint256',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'tickLower',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'tickUpper',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'liquidityDelta',\n internalType: 'int128',\n type: 'int128',\n indexed: false,\n },\n ],\n name: 'LiquidityChunkUpdated',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n { name: 'idV4', internalType: 'PoolId', type: 'bytes32', indexed: true },\n {\n name: 'poolId',\n internalType: 'uint64',\n type: 'uint64',\n indexed: false,\n },\n {\n name: 'minEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n {\n name: 'maxEnforcedTick',\n internalType: 'int24',\n type: 'int24',\n indexed: false,\n },\n ],\n name: 'PoolInitialized',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'recipient',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'positionSize',\n internalType: 'uint128',\n type: 'uint128',\n indexed: false,\n },\n ],\n name: 'TokenizedPositionBurnt',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'caller',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n {\n name: 'tokenId',\n internalType: 'TokenId',\n type: 'uint256',\n indexed: true,\n },\n {\n name: 'positionSize',\n internalType: 'uint128',\n type: 'uint128',\n indexed: false,\n },\n ],\n name: 'TokenizedPositionMinted',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'from', internalType: 'address', type: 'address', indexed: true },\n { name: 'to', internalType: 'address', type: 'address', indexed: true },\n {\n name: 'ids',\n internalType: 'uint256[]',\n type: 'uint256[]',\n indexed: false,\n },\n {\n name: 'amounts',\n internalType: 'uint256[]',\n type: 'uint256[]',\n indexed: false,\n },\n ],\n name: 'TransferBatch',\n },\n {\n type: 'event',\n anonymous: false,\n inputs: [\n {\n name: 'operator',\n internalType: 'address',\n type: 'address',\n indexed: true,\n },\n { name: 'from', internalType: 'address', type: 'address', indexed: true },\n { name: 'to', internalType: 'address', type: 'address', indexed: true },\n { name: 'id', internalType: 'uint256', type: 'uint256', indexed: false },\n {\n name: 'amount',\n internalType: 'uint256',\n type: 'uint256',\n indexed: false,\n },\n ],\n name: 'TransferSingle',\n },\n { type: 'error', inputs: [], name: 'ChunkHasZeroLiquidity' },\n { type: 'error', inputs: [], name: 'InvalidTick' },\n { type: 'error', inputs: [], name: 'InvalidTickBound' },\n {\n type: 'error',\n inputs: [{ name: 'parameterType', internalType: 'uint256', type: 'uint256' }],\n name: 'InvalidTokenIdParameter',\n },\n { type: 'error', inputs: [], name: 'LiquidityTooHigh' },\n { type: 'error', inputs: [], name: 'NotAuthorized' },\n { type: 'error', inputs: [], name: 'NotEnoughLiquidityInChunk' },\n { type: 'error', inputs: [], name: 'PoolNotInitialized' },\n { type: 'error', inputs: [], name: 'PositionTooLarge' },\n {\n type: 'error',\n inputs: [{ name: 'currentTick', internalType: 'int24', type: 'int24' }],\n name: 'PriceBoundFail',\n },\n { type: 'error', inputs: [], name: 'Reentrancy' },\n { type: 'error', inputs: [], name: 'UnauthorizedUniswapCallback' },\n { type: 'error', inputs: [], name: 'UnderOverFlow' },\n { type: 'error', inputs: [], name: 'UnsafeRecipient' },\n { type: 'error', inputs: [], name: 'WrongUniswapPool' },\n] as const\n","/**\n * Custom error ABI definitions for Panoptic v2 contracts.\n *\n * Contains all custom errors from Errors.sol with their signatures.\n * Used for decoding contract revert data.\n *\n * Selectors sourced from `forge selectors list` output.\n *\n * @module v2/errors/errorsAbi\n */\n\n/**\n * All custom errors from Panoptic Errors.sol\n *\n * Selector computation: keccak256(errorSignature)[:4]\n */\nexport const panopticErrorsAbi = [\n // AccountInsolvent(uint256 solvent, uint256 numberOfTicks) - 0xcdef092d\n {\n type: 'error',\n name: 'AccountInsolvent',\n inputs: [\n { name: 'solvent', type: 'uint256' },\n { name: 'numberOfTicks', type: 'uint256' },\n ],\n },\n\n // AlreadyInitialized() - 0x0dc149f0\n {\n type: 'error',\n name: 'AlreadyInitialized',\n inputs: [],\n },\n\n // BelowMinimumRedemption() - 0x13185bd7\n {\n type: 'error',\n name: 'BelowMinimumRedemption',\n inputs: [],\n },\n\n // CastingError() - 0xb6680045\n {\n type: 'error',\n name: 'CastingError',\n inputs: [],\n },\n\n // ChunkHasZeroLiquidity() - 0x126ae3af\n {\n type: 'error',\n name: 'ChunkHasZeroLiquidity',\n inputs: [],\n },\n\n // CreateFail() - 0xebfef188\n {\n type: 'error',\n name: 'CreateFail',\n inputs: [],\n },\n\n // DepositTooLarge() - 0xc56d46d3\n {\n type: 'error',\n name: 'DepositTooLarge',\n inputs: [],\n },\n\n // DuplicateTokenId() - 0x2bd1a05a\n {\n type: 'error',\n name: 'DuplicateTokenId',\n inputs: [],\n },\n\n // EffectiveLiquidityAboveThreshold() - 0x3a8795c2\n {\n type: 'error',\n name: 'EffectiveLiquidityAboveThreshold',\n inputs: [],\n },\n\n // ExceedsMaximumRedemption() - 0x20adf2ea\n {\n type: 'error',\n name: 'ExceedsMaximumRedemption',\n inputs: [],\n },\n\n // InputListFail() - 0x99e877ce\n {\n type: 'error',\n name: 'InputListFail',\n inputs: [],\n },\n\n // InsufficientCreditLiquidity() - 0x7a70c281\n {\n type: 'error',\n name: 'InsufficientCreditLiquidity',\n inputs: [],\n },\n\n // InvalidBuilderCode() - 0x15b3fb46\n {\n type: 'error',\n name: 'InvalidBuilderCode',\n inputs: [],\n },\n\n // InvalidTick() - 0xce8ef7fc\n {\n type: 'error',\n name: 'InvalidTick',\n inputs: [],\n },\n\n // InvalidTickBound() - 0x1577d966\n {\n type: 'error',\n name: 'InvalidTickBound',\n inputs: [],\n },\n\n // InvalidTokenIdParameter(uint256 parameterType) - 0x93db0263\n {\n type: 'error',\n name: 'InvalidTokenIdParameter',\n inputs: [{ name: 'parameterType', type: 'uint256' }],\n },\n\n // InvalidUniswapCallback() - 0x3a94c705\n {\n type: 'error',\n name: 'InvalidUniswapCallback',\n inputs: [],\n },\n\n // LengthMismatch() - 0xff633a38\n {\n type: 'error',\n name: 'LengthMismatch',\n inputs: [],\n },\n\n // LiquidityTooHigh() - 0xa500e7ea\n {\n type: 'error',\n name: 'LiquidityTooHigh',\n inputs: [],\n },\n\n // NetLiquidityZero() - 0x73582ea0\n {\n type: 'error',\n name: 'NetLiquidityZero',\n inputs: [],\n },\n\n // NoLegsExercisable() - 0x7721f7da\n {\n type: 'error',\n name: 'NoLegsExercisable',\n inputs: [],\n },\n\n // NotALongLeg() - 0xb7d44f76\n {\n type: 'error',\n name: 'NotALongLeg',\n inputs: [],\n },\n\n // NotBuilder() - 0x0404714e\n {\n type: 'error',\n name: 'NotBuilder',\n inputs: [],\n },\n\n // NotEnoughLiquidityInChunk() - 0xc56d518e\n {\n type: 'error',\n name: 'NotEnoughLiquidityInChunk',\n inputs: [],\n },\n\n // NotEnoughTokens(address tokenAddress, uint256 assetsRequested, uint256 assetBalance) - 0x71c3730b\n {\n type: 'error',\n name: 'NotEnoughTokens',\n inputs: [\n { name: 'tokenAddress', type: 'address' },\n { name: 'assetsRequested', type: 'uint256' },\n { name: 'assetBalance', type: 'uint256' },\n ],\n },\n\n // NotGuardian() - 0xef6d0f02\n {\n type: 'error',\n name: 'NotGuardian',\n inputs: [],\n },\n\n // NotMarginCalled() - 0x2a23f1ad\n {\n type: 'error',\n name: 'NotMarginCalled',\n inputs: [],\n },\n\n // NotPanopticPool() - 0x2dd1912a\n {\n type: 'error',\n name: 'NotPanopticPool',\n inputs: [],\n },\n\n // PoolNotInitialized() - 0x486aa307\n {\n type: 'error',\n name: 'PoolNotInitialized',\n inputs: [],\n },\n\n // PositionCountNotZero() - 0x2501f81e\n {\n type: 'error',\n name: 'PositionCountNotZero',\n inputs: [],\n },\n\n // PositionNotOwned() - 0x00bd51c8\n {\n type: 'error',\n name: 'PositionNotOwned',\n inputs: [],\n },\n\n // PositionTooLarge() - 0x543a6e10\n {\n type: 'error',\n name: 'PositionTooLarge',\n inputs: [],\n },\n\n // PriceBoundFail(int24 currentTick) - 0x618ea40c\n {\n type: 'error',\n name: 'PriceBoundFail',\n inputs: [{ name: 'currentTick', type: 'int24' }],\n },\n\n // PriceImpactTooLarge() - 0xcbe5b9a6\n {\n type: 'error',\n name: 'PriceImpactTooLarge',\n inputs: [],\n },\n\n // Reentrancy() - 0xab143c06\n {\n type: 'error',\n name: 'Reentrancy',\n inputs: [],\n },\n\n // StaleOracle() - 0x88cce429\n {\n type: 'error',\n name: 'StaleOracle',\n inputs: [],\n },\n\n // TokenIdHasZeroLegs() - 0x9cd92fb2\n {\n type: 'error',\n name: 'TokenIdHasZeroLegs',\n inputs: [],\n },\n\n // TooManyLegsOpen() - 0x0ed7e777\n {\n type: 'error',\n name: 'TooManyLegsOpen',\n inputs: [],\n },\n\n // TransferFailed(address token, address from, uint256 amount, uint256 balance) - 0x81f20f86\n {\n type: 'error',\n name: 'TransferFailed',\n inputs: [\n { name: 'token', type: 'address' },\n { name: 'from', type: 'address' },\n { name: 'amount', type: 'uint256' },\n { name: 'balance', type: 'uint256' },\n ],\n },\n\n // UnauthorizedUniswapCallback() - 0x3e30718a\n {\n type: 'error',\n name: 'UnauthorizedUniswapCallback',\n inputs: [],\n },\n\n // UnderOverFlow() - 0xd2190174\n {\n type: 'error',\n name: 'UnderOverFlow',\n inputs: [],\n },\n\n // WrongPoolId() - 0xcfa4bfa2\n {\n type: 'error',\n name: 'WrongPoolId',\n inputs: [],\n },\n\n // WrongUniswapPool() - 0x768778de\n {\n type: 'error',\n name: 'WrongUniswapPool',\n inputs: [],\n },\n\n // ZeroAddress() - 0xd92e233d\n {\n type: 'error',\n name: 'ZeroAddress',\n inputs: [],\n },\n\n // ZeroCollateralRequirement() - 0x5b8edb4a\n {\n type: 'error',\n name: 'ZeroCollateralRequirement',\n inputs: [],\n },\n] as const\n","/**\n * Error parsing utilities for the Panoptic v2 SDK.\n *\n * Converts raw contract errors into typed SDK error classes.\n *\n * @module v2/errors/parser\n */\n\nimport { type Abi, BaseError, decodeErrorResult, toFunctionSelector } from 'viem'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi, riskEngineAbi } from '../../../generated'\nimport { PanopticError } from './base'\nimport {\n // Solvency & Margin\n AccountInsolventError,\n AlreadyInitializedError,\n BelowMinimumRedemptionError,\n CastingError,\n // Liquidity\n ChunkHasZeroLiquidityError,\n CreateFailError,\n DepositTooLargeError,\n DuplicateTokenIdError,\n EffectiveLiquidityAboveThresholdError,\n ExceedsMaximumRedemptionError,\n InputListFailError,\n InsufficientCreditLiquidityError,\n InvalidBuilderCodeError,\n InvalidTickBoundError,\n // Tick & Price\n InvalidTickError,\n // Position & TokenId\n InvalidTokenIdParameterError,\n InvalidUniswapCallbackError,\n LengthMismatchError,\n LiquidityTooHighError,\n NetLiquidityZeroError,\n // Exercise\n NoLegsExercisableError,\n NotALongLegError,\n NotBuilderError,\n NotEnoughLiquidityInChunkError,\n // Token & Collateral\n NotEnoughTokensError,\n NotGuardianError,\n NotMarginCalledError,\n // Authorization\n NotPanopticPoolError,\n // Pool & Initialization\n PoolNotInitializedError,\n PositionCountNotZeroError,\n PositionNotOwnedError,\n PositionTooLargeError,\n PriceBoundFailError,\n PriceImpactTooLargeError,\n // Reentrancy\n ReentrancyError,\n // Oracle & Safe Mode\n StaleOracleError,\n TokenIdHasZeroLegsError,\n TooManyLegsOpenError,\n // Transfer & Casting\n TransferFailedError,\n UnauthorizedUniswapCallbackError,\n UnderOverFlowError,\n WrongPoolIdError,\n WrongUniswapPoolError,\n // Other\n ZeroAddressError,\n ZeroCollateralRequirementError,\n} from './contract'\nimport { panopticErrorsAbi } from './errorsAbi'\n\n/**\n * Result of parsing a Panoptic error.\n */\nexport interface ParsedError {\n /** The parsed error instance */\n error: PanopticError\n /** The original error name from the contract */\n errorName: string\n /** The decoded error arguments */\n args: readonly unknown[]\n}\n\n/**\n * Combined ABI for error decoding.\n * Includes the dedicated errors ABI for complete coverage.\n */\nconst combinedAbi = [\n ...panopticPoolV2Abi,\n ...collateralTrackerV2Abi,\n ...riskEngineAbi,\n ...panopticErrorsAbi,\n] as Abi\n\n/**\n * Map of error names to error constructors.\n */\nconst errorConstructors: Record<\n string,\n (args: readonly unknown[], cause?: Error) => PanopticError\n> = {\n // Solvency & Margin\n AccountInsolvent: (args, cause) =>\n new AccountInsolventError(args[0] as bigint, args[1] as bigint, cause),\n NotMarginCalled: (_args, cause) => new NotMarginCalledError(cause),\n\n // Factory\n CreateFail: (_args, cause) => new CreateFailError(cause),\n\n // Token & Collateral\n NotEnoughTokens: (args, cause) =>\n new NotEnoughTokensError(args[0] as `0x${string}`, args[1] as bigint, args[2] as bigint, cause),\n NotEnoughLiquidityInChunk: (_args, cause) => new NotEnoughLiquidityInChunkError(cause),\n InsufficientCreditLiquidity: (_args, cause) => new InsufficientCreditLiquidityError(cause),\n DepositTooLarge: (_args, cause) => new DepositTooLargeError(cause),\n BelowMinimumRedemption: (_args, cause) => new BelowMinimumRedemptionError(cause),\n ExceedsMaximumRedemption: (_args, cause) => new ExceedsMaximumRedemptionError(cause),\n ZeroCollateralRequirement: (_args, cause) => new ZeroCollateralRequirementError(cause),\n\n // Position & TokenId\n InvalidTokenIdParameter: (args, cause) =>\n new InvalidTokenIdParameterError(args[0] as bigint, cause),\n PositionNotOwned: (_args, cause) => new PositionNotOwnedError(cause),\n PositionTooLarge: (_args, cause) => new PositionTooLargeError(cause),\n PositionCountNotZero: (_args, cause) => new PositionCountNotZeroError(cause),\n DuplicateTokenId: (_args, cause) => new DuplicateTokenIdError(cause),\n TokenIdHasZeroLegs: (_args, cause) => new TokenIdHasZeroLegsError(cause),\n TooManyLegsOpen: (_args, cause) => new TooManyLegsOpenError(cause),\n InputListFail: (_args, cause) => new InputListFailError(cause),\n\n // Tick & Price\n InvalidTick: (_args, cause) => new InvalidTickError(cause),\n InvalidTickBound: (_args, cause) => new InvalidTickBoundError(cause),\n PriceBoundFail: (args, cause) => new PriceBoundFailError(args[0] as bigint, cause),\n PriceImpactTooLarge: (_args, cause) => new PriceImpactTooLargeError(cause),\n\n // Liquidity\n ChunkHasZeroLiquidity: (_args, cause) => new ChunkHasZeroLiquidityError(cause),\n LiquidityTooHigh: (_args, cause) => new LiquidityTooHighError(cause),\n NetLiquidityZero: (_args, cause) => new NetLiquidityZeroError(cause),\n EffectiveLiquidityAboveThreshold: (_args, cause) =>\n new EffectiveLiquidityAboveThresholdError(cause),\n\n // Oracle & Safe Mode\n StaleOracle: (_args, cause) => new StaleOracleError(cause),\n\n // Exercise\n NoLegsExercisable: (_args, cause) => new NoLegsExercisableError(cause),\n NotALongLeg: (_args, cause) => new NotALongLegError(cause),\n\n // Pool & Initialization\n PoolNotInitialized: (_args, cause) => new PoolNotInitializedError(cause),\n AlreadyInitialized: (_args, cause) => new AlreadyInitializedError(cause),\n WrongPoolId: (_args, cause) => new WrongPoolIdError(cause),\n WrongUniswapPool: (_args, cause) => new WrongUniswapPoolError(cause),\n\n // Authorization\n NotPanopticPool: (_args, cause) => new NotPanopticPoolError(cause),\n NotGuardian: (_args, cause) => new NotGuardianError(cause),\n NotBuilder: (_args, cause) => new NotBuilderError(cause),\n InvalidBuilderCode: (_args, cause) => new InvalidBuilderCodeError(cause),\n InvalidUniswapCallback: (_args, cause) => new InvalidUniswapCallbackError(cause),\n UnauthorizedUniswapCallback: (_args, cause) => new UnauthorizedUniswapCallbackError(cause),\n\n // Transfer & Casting\n TransferFailed: (args, cause) =>\n new TransferFailedError(\n args[0] as `0x${string}`,\n args[1] as `0x${string}`,\n args[2] as bigint,\n args[3] as bigint,\n cause,\n ),\n CastingError: (_args, cause) => new CastingError(cause),\n UnderOverFlow: (_args, cause) => new UnderOverFlowError(cause),\n\n // Reentrancy\n Reentrancy: (_args, cause) => new ReentrancyError(cause),\n\n // Other\n ZeroAddress: (_args, cause) => new ZeroAddressError(cause),\n LengthMismatch: (_args, cause) => new LengthMismatchError(cause),\n}\n\n/**\n * Parse a raw contract error into a typed SDK error.\n *\n * This function attempts to decode the error data from a failed contract call\n * and return a typed error instance with extracted parameters.\n *\n * @param error - The raw error from a failed contract call\n * @returns Parsed error with typed error instance, or null if parsing fails\n *\n * @example\n * ```typescript\n * try {\n * await contract.openPosition(...)\n * } catch (rawError) {\n * const parsed = parsePanopticError(rawError)\n * if (parsed) {\n * console.log('Error:', parsed.errorName)\n * if (parsed.error instanceof AccountInsolventError) {\n * console.log('Solvent value:', parsed.error.solvent)\n * }\n * }\n * }\n * ```\n */\nexport function parsePanopticError(error: unknown): ParsedError | null {\n // Strategy 1: Check if viem already decoded the error (ContractFunctionRevertedError.data)\n const viemDecoded = extractViemDecodedError(error)\n if (viemDecoded) {\n return buildParsedError(viemDecoded.errorName, viemDecoded.args, error)\n }\n\n // Strategy 2: Extract raw hex data and decode ourselves\n const errorData = extractErrorData(error)\n if (!errorData) return null\n\n try {\n const decoded = decodeErrorResult({\n abi: combinedAbi,\n data: errorData,\n })\n\n return buildParsedError(decoded.errorName, decoded.args ?? [], error)\n } catch {\n // decodeErrorResult failed — possibly we only have the 4-byte selector\n // (e.g. from a multicall error message). Try matching the selector manually.\n if (errorData.length >= 10) {\n const selector = errorData.slice(0, 10) as `0x${string}`\n const match = matchSelectorToErrorName(selector)\n if (match) {\n return buildParsedError(match, [], error)\n }\n }\n return null\n }\n}\n\n/**\n * Walk the cause chain looking for a viem ContractFunctionRevertedError\n * that already has decoded `.data` (an object with `errorName` and `args`).\n * This happens when the ABI passed to simulateContract includes the error definitions.\n */\nfunction extractViemDecodedError(\n error: unknown,\n): { errorName: string; args: readonly unknown[] } | null {\n if (!error || typeof error !== 'object') return null\n\n // Use BaseError.walk if available\n if (error instanceof BaseError) {\n let found: { errorName: string; args: readonly unknown[] } | null = null\n error.walk((e) => {\n if (found) return false\n const node = e as Record<string, unknown>\n if (\n node.data &&\n typeof node.data === 'object' &&\n 'errorName' in (node.data as object) &&\n typeof (node.data as Record<string, unknown>).errorName === 'string'\n ) {\n const data = node.data as { errorName: string; args?: readonly unknown[] }\n found = { errorName: data.errorName, args: data.args ?? [] }\n return true\n }\n return false\n })\n return found\n }\n\n // Manual walk for non-viem errors\n let current: Record<string, unknown> | null = error as Record<string, unknown>\n for (let i = 0; i < 10 && current; i++) {\n if (\n current.data &&\n typeof current.data === 'object' &&\n 'errorName' in (current.data as object) &&\n typeof (current.data as Record<string, unknown>).errorName === 'string'\n ) {\n const data = current.data as { errorName: string; args?: readonly unknown[] }\n return { errorName: data.errorName, args: data.args ?? [] }\n }\n current =\n current.cause && typeof current.cause === 'object'\n ? (current.cause as Record<string, unknown>)\n : null\n }\n\n return null\n}\n\n/**\n * Build a ParsedError from a decoded error name and args.\n */\nfunction buildParsedError(\n errorName: string,\n args: readonly unknown[],\n originalError: unknown,\n): ParsedError {\n const constructor = errorConstructors[errorName]\n const cause = originalError instanceof Error ? originalError : undefined\n\n if (!constructor) {\n const unknownError = new PanopticError(`Unknown contract error: ${errorName}`)\n unknownError.errorName = errorName\n return { error: unknownError, errorName, args }\n }\n\n const typedError = constructor(args, cause)\n typedError.errorName = errorName\n return { error: typedError, errorName, args }\n}\n\n/**\n * Match a 4-byte selector against the panoptic errors ABI.\n * Used as fallback when we only have the selector (no encoded args).\n */\nfunction matchSelectorToErrorName(selector: `0x${string}`): string | null {\n for (const item of panopticErrorsAbi) {\n if (item.type !== 'error') continue\n const computed = toFunctionSelector(\n `${item.name}(${item.inputs.map((i: { type: string }) => i.type).join(',')})`,\n )\n if (computed === selector) {\n return item.name\n }\n }\n return null\n}\n\n/**\n * Extract error data from various error formats.\n *\n * Strategy:\n * 1. Use viem's BaseError.walk() to traverse the full cause chain and find\n * hex data on any node (handles arbitrary nesting depth for multicall etc.)\n * 2. Fall back to manual cause-chain walk for non-viem errors\n * 3. Last resort: extract selector from error message (loses args)\n */\nfunction extractErrorData(error: unknown): `0x${string}` | null {\n if (!error) return null\n\n // Direct hex data\n if (typeof error === 'string' && error.startsWith('0x')) {\n return error as `0x${string}`\n }\n\n if (typeof error !== 'object') return null\n\n // Strategy 1: Use viem's BaseError.walk() — traverses the full cause chain\n if (error instanceof BaseError) {\n let foundData: `0x${string}` | null = null\n\n error.walk((e) => {\n if (foundData) return false\n const node = e as Record<string, unknown>\n\n // Check .data as hex string (full revert bytes on RPC errors)\n if (node.data && typeof node.data === 'string' && node.data.startsWith('0x')) {\n foundData = node.data as `0x${string}`\n return true\n }\n\n // Check .data.data (some RPC providers nest: { data: { data: '0x...' } })\n if (node.data && typeof node.data === 'object') {\n const nested = node.data as Record<string, unknown>\n if (nested.data && typeof nested.data === 'string' && nested.data.startsWith('0x')) {\n foundData = nested.data as `0x${string}`\n return true\n }\n }\n\n return false\n })\n\n if (foundData) return foundData\n\n // Also check .signature on walked nodes (viem stores raw selector here\n // when it can't decode against the provided ABI)\n error.walk((e) => {\n if (foundData) return false\n const node = e as Record<string, unknown>\n if (node.signature && typeof node.signature === 'string' && node.signature.startsWith('0x')) {\n foundData = node.signature as `0x${string}`\n return true\n }\n return false\n })\n\n if (foundData) return foundData\n }\n\n // Strategy 2: Manual cause-chain walk for non-viem errors\n let current: Record<string, unknown> | null = error as Record<string, unknown>\n const maxDepth = 10\n for (let i = 0; i < maxDepth && current; i++) {\n if (current.data && typeof current.data === 'string' && current.data.startsWith('0x')) {\n return current.data as `0x${string}`\n }\n\n if (current.data && typeof current.data === 'object') {\n const nested = current.data as Record<string, unknown>\n if (nested.data && typeof nested.data === 'string' && nested.data.startsWith('0x')) {\n return nested.data as `0x${string}`\n }\n }\n\n if (current.error && typeof current.error === 'object') {\n const rpcError = current.error as Record<string, unknown>\n if (rpcError.data && typeof rpcError.data === 'string' && rpcError.data.startsWith('0x')) {\n return rpcError.data as `0x${string}`\n }\n }\n\n current =\n current.cause && typeof current.cause === 'object'\n ? (current.cause as Record<string, unknown>)\n : null\n }\n\n // Strategy 3: Extract from error message (last resort — may only have 4-byte selector)\n const obj = error as Record<string, unknown>\n if (obj.message && typeof obj.message === 'string') {\n const signatureMatch = obj.message.match(/signature:\\s*(0x[a-fA-F0-9]{8,})/i)\n if (signatureMatch) {\n return signatureMatch[1] as `0x${string}`\n }\n }\n\n return null\n}\n\n/**\n * Check if an error is a specific Panoptic error type.\n *\n * @param error - The error to check\n * @param errorClass - The error class to check against\n * @returns True if the error is an instance of the specified class\n *\n * @example\n * ```typescript\n * const parsed = parsePanopticError(error)\n * if (parsed && isPanopticErrorType(parsed.error, AccountInsolventError)) {\n * console.log('Account is insolvent!')\n * }\n * ```\n */\nexport function isPanopticErrorType<T extends PanopticError>(\n error: PanopticError,\n errorClass: abstract new (...args: never[]) => T,\n): error is T {\n return error instanceof errorClass\n}\n","/**\n * TokenId constants for the Panoptic v2 SDK.\n * @module v2/tokenId/constants\n */\n\n/**\n * Default vegoid value used in pool ID encoding.\n */\nexport const DEFAULT_VEGOID = 8n\n\n/**\n * Default MAX_SPREAD value (90_000 = 9 * 10_000).\n * On-chain: removed/net ratio cap, in units of 1/10_000.\n */\nexport const DEFAULT_MAX_SPREAD = 90_000n\n\n/**\n * Standard tick widths matching DTE gamma profiles.\n *\n * These represent the position width in ticks for each timescale.\n * Width = tickUpper - tickLower.\n */\nexport const STANDARD_TICK_WIDTHS = {\n /** 1-hour expiry profile (240 ticks) */\n '1H': 240n,\n /** 1-day expiry profile (720 ticks) */\n '1D': 720n,\n /** 1-week expiry profile (2400 ticks) */\n '1W': 2400n,\n /** 1-month expiry profile (4800 ticks) */\n '1M': 4800n,\n /** 1-year expiry profile (15000 ticks) */\n '1Y': 15000n,\n} as const\n\n/**\n * Timescale key type for STANDARD_TICK_WIDTHS.\n */\nexport type Timescale = keyof typeof STANDARD_TICK_WIDTHS\n\n/**\n * Bit positions and sizes for TokenId encoding.\n */\nexport const TOKEN_ID_BITS = {\n /** Pool ID occupies bits 0-63 */\n POOL_ID_SIZE: 64n,\n /** Vegoid starts at bit 40 within pool ID */\n VEGOID_STARTING_BIT: 40n,\n /** Vegoid is 8 bits */\n VEGOID_SIZE: 8n,\n /** Tick spacing starts at bit 48 within pool ID */\n TICK_SPACING_STARTING_BIT: 48n,\n /** Tick spacing is 16 bits */\n TICK_SPACING_SIZE: 16n,\n /** Each leg is 48 bits */\n LEG_SIZE: 48n,\n /** Maximum number of legs per TokenId */\n MAX_LEGS: 4n,\n} as const\n\n/**\n * Bit positions within a leg (relative to leg start).\n */\nexport const LEG_BITS = {\n /** Asset bit position */\n ASSET_BIT: 0n,\n /** Asset size in bits */\n ASSET_SIZE: 1n,\n /** Option ratio starting bit */\n RATIO_BIT: 1n,\n /** Option ratio size in bits */\n RATIO_SIZE: 7n,\n /** Is long starting bit */\n IS_LONG_BIT: 8n,\n /** Is long size in bits */\n IS_LONG_SIZE: 1n,\n /** Token type starting bit */\n TOKEN_TYPE_BIT: 9n,\n /** Token type size in bits */\n TOKEN_TYPE_SIZE: 1n,\n /** Risk partner starting bit */\n RISK_PARTNER_BIT: 10n,\n /** Risk partner size in bits */\n RISK_PARTNER_SIZE: 2n,\n /** Strike starting bit */\n STRIKE_BIT: 12n,\n /** Strike size in bits (24 bits, signed int24) */\n STRIKE_SIZE: 24n,\n /** Width starting bit */\n WIDTH_BIT: 36n,\n /** Width size in bits */\n WIDTH_SIZE: 12n,\n} as const\n\n/**\n * Masks for extracting/encoding leg fields.\n */\nexport const LEG_MASKS = {\n /** Mask for asset (1 bit) */\n ASSET: (1n << LEG_BITS.ASSET_SIZE) - 1n,\n /** Mask for option ratio (7 bits) */\n RATIO: (1n << LEG_BITS.RATIO_SIZE) - 1n,\n /** Mask for is long (1 bit) */\n IS_LONG: (1n << LEG_BITS.IS_LONG_SIZE) - 1n,\n /** Mask for token type (1 bit) */\n TOKEN_TYPE: (1n << LEG_BITS.TOKEN_TYPE_SIZE) - 1n,\n /** Mask for risk partner (2 bits) */\n RISK_PARTNER: (1n << LEG_BITS.RISK_PARTNER_SIZE) - 1n,\n /** Mask for strike (24 bits) */\n STRIKE: (1n << LEG_BITS.STRIKE_SIZE) - 1n,\n /** Mask for width (12 bits) */\n WIDTH: (1n << LEG_BITS.WIDTH_SIZE) - 1n,\n /** Mask for entire leg (48 bits) */\n LEG: (1n << TOKEN_ID_BITS.LEG_SIZE) - 1n,\n} as const\n\n/**\n * Maximum and minimum values for leg fields.\n */\nexport const LEG_LIMITS = {\n /** Maximum option ratio (127) */\n MAX_RATIO: 127n,\n /** Maximum width (4095) */\n MAX_WIDTH: 4095n,\n /** Maximum strike (8388607, max int24 positive) */\n MAX_STRIKE: 8388607n,\n /** Minimum strike (-8388608, min int24) */\n MIN_STRIKE: -8388608n,\n} as const\n\n/**\n * Value used to convert negative strike to unsigned representation.\n * Strike is stored as int24, so we use 2^24 for conversion.\n */\nexport const STRIKE_CONVERSION_FACTOR = 16777216n\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 * Derive a unique tokenId to mint alongside a burn (position reduction / roll).\n *\n * dispatch() cannot partial-close a held tokenId — a same-tokenId size change\n * is interpreted as `settlePremium`. To reduce, we burn the old tokenId and\n * mint a DIFFERENT tokenId with the desired smaller size in one dispatch. The\n * new tokenId must merely be unique from the old one.\n *\n * Two derivation paths:\n * 1. **Tiny credit leg (default)** — when the base has a free leg slot\n * (< 4 legs), append a width=0 credit (isLong=1) leg with an extreme\n * strike so its token notional (`positionSize · 1.0001^strike`) rounds\n * down to ~1 wei — tokenId-uniquifying but economically negligible. New\n * positionSize can be any value ≤ current size; arbitrary reduction\n * amounts fall out.\n * 2. **Ratio scaling (fallback)** — only when all 4 leg slots are used:\n * multiply every leg's optionRatio by a factor `N` such that\n * `N · max(optionRatio) ≤ 127`, then set\n * `newPositionSize = ceil(targetSize / N)`. Per-leg preserved liquidity\n * is `newPositionSize · N`, so the reduce still satisfies the target.\n *\n * @module v2/tokenId/deriveUniqueTokenId\n */\n\nimport { PanopticError } from '../errors'\nimport { sqrtPriceX96ToTick } from '../formatters/tick'\nimport { MAX_TICK, MIN_TICK } from '../utils/constants'\nimport { LEG_LIMITS, TOKEN_ID_BITS } from './constants'\nimport { addLegToTokenId, countLegs, decodeAllLegs, decodeLeg } from './encoding'\n\nconst POOL_ID_MASK = (1n << 64n) - 1n\nconst MAX_LEGS = TOKEN_ID_BITS.MAX_LEGS\nconst MAX_OPTION_RATIO = LEG_LIMITS.MAX_RATIO\nconst Q192 = 1n << 192n\n\nexport type DeriveStrategy = 'tiny-credit' | 'ratio-scale'\n\nexport interface DeriveUniqueTokenIdParams {\n /** Base tokenId to derive a unique sibling from. */\n baseTokenId: bigint\n /**\n * Desired new positionSize. Must be > 0 and ≤ the CURRENT stored\n * positionSize on the tokenId being reduced.\n *\n * For `ratio-scale` the effective size (`newPositionSize · N`) may exceed\n * this by a rounding-up wei. `newPositionSize` in the result reflects\n * exactly what to pass to dispatch.\n */\n targetPositionSize: bigint\n /**\n * Pool tickSpacing. Used to keep the appended credit leg's tick range\n * (SFPM internally widens width=0 to a width-2 chunk: `strike ± tickSpacing`)\n * strictly inside `[MIN_POOL_TICK, MAX_POOL_TICK]`. Omit to use a\n * worst-case Uniswap-v3 default of 200.\n */\n tickSpacing?: bigint\n}\n\nexport interface DeriveUniqueTokenIdResult {\n newTokenId: bigint\n /** positionSize to pass to dispatch for the new tokenId. */\n newPositionSize: bigint\n /**\n * Real per-leg liquidity the new tokenId will hold, expressed in the\n * base-token positionSize frame. Equals `newPositionSize · N` for\n * `ratio-scale` (where N is the applied optionRatio multiplier) and\n * `newPositionSize` for `tiny-credit`. Consumers should compare this\n * against the base tokenId's current stored size to validate that a\n * reduction is actually smaller (or, for `ratio-scale`, that the ceiling\n * rounding did not push effective size above the stored size).\n */\n effectivePositionSize: bigint\n strategy: DeriveStrategy\n}\n\n/**\n * Floor integer square root for bigints (Newton's method). Mirrors the isqrt\n * used in reads/collateralEstimate.ts (buildNeutralLeg).\n */\nfunction isqrt(value: bigint): bigint {\n if (value < 0n) throw new PanopticError('isqrt of negative number')\n if (value < 2n) return value\n let x = value\n let y = (x + 1n) >> 1n\n while (y < x) {\n x = y\n y = (x + value / x) >> 1n\n }\n return x\n}\n\nconst DEFAULT_TICK_SPACING = 200n\n\n/**\n * Target notional (in wei of the tokenType-side asset) for the appended\n * tiny credit leg. Chosen at 10 wei — small enough to be economically\n * meaningless against any real position size, large enough to safely\n * clear rounding on the SFPM's width-2 internal chunk math without any\n * risk of underflowing to zero (which would revert ChunkHasZeroLiquidity).\n */\nconst TINY_CREDIT_TARGET_NOTIONAL_WEI = 10n\n\n/**\n * Pick a signedStrike for the appended width=0 credit leg such that:\n * 1. positionSize · 1.0001^signedStrike ≈ TINY_CREDIT_TARGET_NOTIONAL_WEI\n * (~10 wei — economically meaningless but comfortably above any\n * SFPM width-2 chunk rounding);\n * 2. the leg's tick range (SFPM internally treats width=0 as width=2, so\n * the range is `strike ± tickSpacing`) stays strictly inside\n * `[MIN_POOL_TICK, MAX_POOL_TICK]` — otherwise the getSqrtRatioAtTick\n * call reverts with `InvalidTick`.\n *\n * Closed form: `1.0001^signedStrike = target/positionSize`, so\n * `sqrtKrawX96 = isqrt(target · 2^192 / positionSize)` and\n * `signedStrike = sqrtPriceX96ToTick(sqrtKrawX96)`. If the notional-optimal\n * strike falls outside the safe range, we clamp inward. Clamping raises the\n * notional but keeps it << position size for any reasonable strike.\n */\nfunction computeTinyCreditSignedStrike(positionSize: bigint, tickSpacing: bigint): bigint {\n if (positionSize <= 0n) {\n throw new PanopticError('computeTinyCreditSignedStrike: positionSize must be > 0')\n }\n // Leave one tickSpacing of buffer on each side + 1 tick of headroom so the\n // width-2 chunk (strike ± tickSpacing) stays strictly inside the pool bounds.\n const minSafe = MIN_TICK + tickSpacing + 1n\n const maxSafe = MAX_TICK - tickSpacing - 1n\n\n let signedStrike: bigint\n try {\n const sqrtKrawX96 = isqrt((TINY_CREDIT_TARGET_NOTIONAL_WEI * Q192) / positionSize)\n signedStrike = sqrtPriceX96ToTick(sqrtKrawX96)\n } catch {\n // sqrtPriceX96ToTick rejects out-of-bounds sqrt prices; that only happens\n // for extreme (>> 2^128) or dust positionSizes. Fall back to the min-safe\n // edge, which still gives a tiny notional relative to any real position.\n signedStrike = minSafe\n }\n\n if (signedStrike < minSafe) return minSafe\n if (signedStrike > maxSafe) return maxSafe\n return signedStrike\n}\n\n/**\n * Assemble the tiny credit leg struct, picking a strike that avoids\n * colliding with any existing width=0 credit leg on the same (asset,\n * tokenType) pair.\n *\n * The encoded strike stored in the tokenId is\n * `asset === 0 ? signedStrike : -signedStrike` (mirrors\n * {@link buildNeutralLeg} in reads/collateralEstimate.ts).\n */\nfunction pickUniqueTinyCreditLeg(\n baseTokenId: bigint,\n legIndex: bigint,\n positionSize: bigint,\n tickSpacing: bigint,\n): {\n index: bigint\n asset: bigint\n tokenType: bigint\n optionRatio: bigint\n isLong: bigint\n riskPartner: bigint\n strike: bigint\n width: bigint\n} {\n const asset: bigint = 1n\n const tokenType: bigint = 0n\n\n const existingLegs = decodeAllLegs(baseTokenId)\n const maxSafe = MAX_TICK - tickSpacing - 1n\n\n let signedStrike = computeTinyCreditSignedStrike(positionSize, tickSpacing)\n while (signedStrike <= maxSafe) {\n const candidate = asset === 0n ? signedStrike : -signedStrike\n let collides = false\n for (const leg of existingLegs) {\n if (\n leg.width === 0n &&\n leg.isLong &&\n leg.asset === asset &&\n leg.tokenType === tokenType &&\n leg.strike === candidate\n ) {\n collides = true\n break\n }\n }\n if (!collides) break\n signedStrike += 1n\n }\n if (signedStrike > maxSafe) {\n throw new PanopticError(\n 'deriveUniqueTokenId: exhausted strike space picking a unique tiny credit leg',\n )\n }\n\n const encodedStrike = asset === 0n ? signedStrike : -signedStrike\n\n return {\n index: legIndex,\n asset,\n tokenType,\n optionRatio: 1n,\n isLong: 1n,\n riskPartner: legIndex,\n strike: encodedStrike,\n width: 0n,\n }\n}\n\nfunction appendTinyCreditLeg(\n baseTokenId: bigint,\n baseLegCount: bigint,\n positionSize: bigint,\n tickSpacing: bigint,\n): bigint {\n const newLeg = pickUniqueTinyCreditLeg(baseTokenId, baseLegCount, positionSize, tickSpacing)\n return addLegToTokenId(baseTokenId, newLeg)\n}\n\nfunction scaleRatios(baseTokenId: bigint, targetPositionSize: bigint): DeriveUniqueTokenIdResult {\n const legs = decodeAllLegs(baseTokenId)\n const maxRatio = legs.reduce<bigint>((m, leg) => (leg.optionRatio > m ? leg.optionRatio : m), 0n)\n const N = MAX_OPTION_RATIO / maxRatio\n if (N < 2n) {\n throw new PanopticError(\n 'deriveUniqueTokenId: cannot derive a unique tokenId — all 4 leg slots used and optionRatios already near the 127 ceiling',\n )\n }\n // Preserved per-leg liquidity = newSize · N. ceil ensures effective size ≥ target.\n const newPositionSize = (targetPositionSize + N - 1n) / N\n\n const poolId = baseTokenId & POOL_ID_MASK\n let out = poolId\n for (const leg of legs) {\n out = addLegToTokenId(out, {\n index: leg.index,\n asset: leg.asset,\n tokenType: leg.tokenType,\n optionRatio: leg.optionRatio * N,\n isLong: leg.isLong ? 1n : 0n,\n riskPartner: leg.riskPartner,\n strike: leg.strike,\n width: leg.width,\n })\n }\n return {\n newTokenId: out,\n newPositionSize,\n effectivePositionSize: newPositionSize * N,\n strategy: 'ratio-scale',\n }\n}\n\n/**\n * Derive a tokenId unique from `baseTokenId` for a partial reduction.\n *\n * Prefers a tiny-credit-leg extension (arbitrary new size). Falls back to\n * optionRatio scaling only when the base tokenId already occupies all 4 leg\n * slots.\n */\nexport function deriveUniqueTokenId(params: DeriveUniqueTokenIdParams): DeriveUniqueTokenIdResult {\n const { baseTokenId, targetPositionSize, tickSpacing = DEFAULT_TICK_SPACING } = params\n\n if (targetPositionSize <= 0n) {\n throw new PanopticError('deriveUniqueTokenId: targetPositionSize must be > 0')\n }\n\n const legCount = countLegs(baseTokenId)\n if (legCount === 0n) {\n throw new PanopticError('deriveUniqueTokenId: baseTokenId has no legs')\n }\n\n if (legCount < MAX_LEGS) {\n const newTokenId = appendTinyCreditLeg(baseTokenId, legCount, targetPositionSize, tickSpacing)\n return {\n newTokenId,\n newPositionSize: targetPositionSize,\n effectivePositionSize: targetPositionSize,\n strategy: 'tiny-credit',\n }\n }\n\n return scaleRatios(baseTokenId, targetPositionSize)\n}\n\n/**\n * Test hook: exposed only to make the tiny-credit leg strike inspectable.\n * @internal\n */\nexport function _pickUniqueTinyCreditLegForTests(\n baseTokenId: bigint,\n legIndex: bigint,\n positionSize: bigint = 10n ** 18n,\n tickSpacing: bigint = DEFAULT_TICK_SPACING,\n) {\n return pickUniqueTinyCreditLeg(baseTokenId, legIndex, positionSize, tickSpacing)\n}\n\n/**\n * Re-export decoded leg count so callers can gate UI on the strategy that\n * would be chosen (e.g. show a divisibility hint on ratio-scale positions).\n */\nexport function planDeriveStrategy(baseTokenId: bigint): DeriveStrategy {\n return countLegs(baseTokenId) < MAX_LEGS ? 'tiny-credit' : 'ratio-scale'\n}\n\n// Re-export used by consumers who only need the leg-count helper.\nexport { decodeLeg }\n","/**\n * Per-second rate helpers.\n *\n * Collateral tracker rates are returned as WAD-scaled per-second rates.\n * These helpers annualize them for display.\n *\n * @module v2/formatters/rates\n */\n\nimport { formatWadPercent } from './wad'\n\nconst SECONDS_PER_DAY = 86_400n\nconst DAYS_PER_YEAR = 365n\nconst SECONDS_PER_YEAR = SECONDS_PER_DAY * DAYS_PER_YEAR\n\n/**\n * Annualize a per-second WAD-scaled rate to annual WAD.\n *\n * @param ratePerSecondWad - Rate in WAD per second\n * @returns Annualized rate in WAD\n */\nexport function annualizePerSecondRateWad(ratePerSecondWad: bigint): bigint {\n return ratePerSecondWad * SECONDS_PER_YEAR\n}\n\n/**\n * Format a per-second WAD rate as APY percentage text.\n * Uses linear annualization, then formats as WAD percent.\n *\n * @param ratePerSecondWad - Rate in WAD per second\n * @param precision - Decimal places\n * @returns Percentage string, e.g. \"2.41%\"\n */\nexport function formatPerSecondRateWadAsApyPct(\n ratePerSecondWad: bigint,\n precision: bigint,\n): string {\n return formatWadPercent(annualizePerSecondRateWad(ratePerSecondWad), precision)\n}\n\n/**\n * Format a per-second WAD rate as APR percentage text.\n * For this rate model, APR presentation uses the same annualized output.\n *\n * @param ratePerSecondWad - Rate in WAD per second\n * @param precision - Decimal places\n * @returns Percentage string, e.g. \"2.41%\"\n */\nexport function formatPerSecondRateWadAsAprPct(\n ratePerSecondWad: bigint,\n precision: bigint,\n): string {\n return formatWadPercent(annualizePerSecondRateWad(ratePerSecondWad), precision)\n}\n","/**\n * Pure generation of fixed-price TokenId ladders overlapping the current tick.\n * @module v2/tokenId/generateOverlapping\n */\n\nimport { PanopticValidationError } from '../errors'\nimport { priceToTick, roundToTickSpacing, tickToSqrtPriceX96 } from '../formatters'\nimport { MAX_TICK, MIN_TICK } from '../utils/constants'\nimport { createTokenIdBuilder } from './builder'\nimport { type Timescale, LEG_LIMITS, STANDARD_TICK_WIDTHS, TOKEN_ID_BITS } from './constants'\nimport { decodeTickSpacing } from './encoding'\n\nconst MAX_UINT64 = (1n << 64n) - 1n\nconst MAX_UINT128 = (1n << 128n) - 1n\nconst Q192 = 1n << 192n\nconst MAX_TOKEN_DECIMALS = 255n\nconst MAX_DECIMAL_EXPONENT = 512n\n\nexport type OverlappingOptionType = 'call' | 'put'\n\n/** One option leg repeated at every generated strike. */\nexport interface OverlappingOptionLegConfig {\n optionType: OverlappingOptionType\n optionRatio: bigint\n isLong: boolean\n /** Defaults to this leg's index. */\n riskPartner?: bigint\n}\n\n/** Parameters for {@link generateOverlappingTokenIds}. */\nexport interface GenerateOverlappingTokenIdsParams {\n /** Encoded 64-bit Panoptic pool ID, including tick spacing. */\n poolId: bigint\n /** Current Uniswap pool tick. */\n currentTick: bigint\n /** Standard option timescale used to derive every leg's width. */\n timescale: Timescale\n /** Positive quote-token price interval, such as \"25\" or \"50\". */\n strikePriceSpacing: string\n /** Asset token index in the pool (0 or 1). */\n asset: bigint\n assetDecimals: bigint\n quoteDecimals: bigint\n /** One to four call/put legs sharing each generated strike. */\n legs: readonly OverlappingOptionLegConfig[]\n /** Total size divided across all generated TokenIds. */\n positionSize: bigint\n}\n\n/** TokenIds and sizes aligned with the corresponding `dispatch()` arguments. */\nexport interface GenerateOverlappingTokenIdsResult {\n positionIdList: bigint[]\n positionSizes: bigint[]\n}\n\ninterface ResolvedLegConfig extends OverlappingOptionLegConfig {\n riskPartner: bigint\n}\n\ninterface DecimalSpacing {\n units: bigint\n scale: bigint\n denominator: bigint\n}\n\ninterface Fraction {\n numerator: bigint\n denominator: bigint\n}\n\nfunction invalid(message: string): never {\n throw new PanopticValidationError(`generateOverlappingTokenIds: ${message}`)\n}\n\nfunction pow10(exponent: bigint): bigint {\n return 10n ** exponent\n}\n\nfunction parsePriceSpacing(value: string, quoteDecimals: bigint): DecimalSpacing {\n const match = /^\\+?(?:(\\d+)(?:\\.(\\d*))?|\\.(\\d+))(?:e([+-]?\\d+))?$/i.exec(value.trim())\n if (match === null) invalid('strikePriceSpacing must be a positive decimal string')\n\n const integerPart = match[1] ?? '0'\n const fractionalPart = match[2] ?? match[3] ?? ''\n const exponent = BigInt(match[4] ?? '0')\n if (exponent < -MAX_DECIMAL_EXPONENT || exponent > MAX_DECIMAL_EXPONENT) {\n invalid('strikePriceSpacing exponent is too large')\n }\n\n let units = BigInt(`${integerPart}${fractionalPart}`)\n let scale = BigInt(fractionalPart.length) - exponent\n if (scale < 0n) {\n units *= pow10(-scale)\n scale = 0n\n }\n\n while (scale > 0n && units % 10n === 0n) {\n units /= 10n\n scale -= 1n\n }\n\n if (units <= 0n) invalid('strikePriceSpacing must be positive')\n if (scale > quoteDecimals) {\n invalid('strikePriceSpacing exceeds the quote token decimal precision')\n }\n\n return { units, scale, denominator: pow10(scale) }\n}\n\nfunction formatGridPrice(multiple: bigint, spacing: DecimalSpacing): string {\n const scaledPrice = multiple * spacing.units\n if (spacing.scale === 0n) return scaledPrice.toString()\n\n const scale = Number(spacing.scale)\n const digits = scaledPrice.toString().padStart(scale + 1, '0')\n const decimalIndex = digits.length - scale\n return `${digits.slice(0, decimalIndex)}.${digits.slice(decimalIndex)}`\n}\n\nfunction quotePriceAtTick(\n tick: bigint,\n asset: bigint,\n assetDecimals: bigint,\n quoteDecimals: bigint,\n): Fraction {\n const orientedTick = asset === 0n ? tick : -tick\n const sqrtPriceX96 = tickToSqrtPriceX96(orientedTick)\n let numerator = sqrtPriceX96 * sqrtPriceX96\n let denominator = Q192\n const decimalDifference = assetDecimals - quoteDecimals\n\n if (decimalDifference > 0n) {\n numerator *= pow10(decimalDifference)\n } else if (decimalDifference < 0n) {\n denominator *= pow10(-decimalDifference)\n }\n\n return { numerator, denominator }\n}\n\nfunction isPriceGridStrike(\n strike: bigint,\n params: Pick<GenerateOverlappingTokenIdsParams, 'asset' | 'assetDecimals' | 'quoteDecimals'>,\n spacing: DecimalSpacing,\n tickSpacing: bigint,\n): boolean {\n const price = quotePriceAtTick(strike, params.asset, params.assetDecimals, params.quoteDecimals)\n const floorMultiple =\n (price.numerator * spacing.denominator) / (price.denominator * spacing.units)\n\n for (const multiple of [floorMultiple, floorMultiple + 1n]) {\n if (multiple <= 0n) continue\n\n const orientedTick = priceToTick(\n formatGridPrice(multiple, spacing),\n params.assetDecimals,\n params.quoteDecimals,\n )\n const poolTick = params.asset === 0n ? orientedTick : -orientedTick\n if (roundToTickSpacing(poolTick, tickSpacing) === strike) return true\n }\n\n return false\n}\n\nfunction ceilDiv(value: bigint, divisor: bigint): bigint {\n const quotient = value / divisor\n const remainder = value % divisor\n return remainder > 0n ? quotient + 1n : quotient\n}\n\nfunction floorDiv(value: bigint, divisor: bigint): bigint {\n const quotient = value / divisor\n const remainder = value % divisor\n return remainder < 0n ? quotient - 1n : quotient\n}\n\nfunction resolveLegs(legs: readonly OverlappingOptionLegConfig[]): ResolvedLegConfig[] {\n if (legs.length === 0 || legs.length > Number(TOKEN_ID_BITS.MAX_LEGS)) {\n invalid('legs must contain between 1 and 4 entries')\n }\n\n const resolved = legs.map((leg, index) => {\n if (leg.optionType !== 'call' && leg.optionType !== 'put') {\n invalid(`leg ${index} has an invalid optionType`)\n }\n if (typeof leg.isLong !== 'boolean') invalid(`leg ${index} has an invalid isLong value`)\n if (leg.optionRatio < 1n || leg.optionRatio > LEG_LIMITS.MAX_RATIO) {\n invalid(`leg ${index} optionRatio must be between 1 and ${LEG_LIMITS.MAX_RATIO}`)\n }\n\n const riskPartner = leg.riskPartner ?? BigInt(index)\n if (riskPartner < 0n || riskPartner >= BigInt(legs.length)) {\n invalid(`leg ${index} references an inactive risk partner`)\n }\n\n return { ...leg, riskPartner }\n })\n\n for (const [index, leg] of resolved.entries()) {\n if (leg.riskPartner === BigInt(index)) continue\n const partner = resolved[Number(leg.riskPartner)]\n if (partner === undefined || partner.riskPartner !== BigInt(index)) {\n invalid(`leg ${index} has a non-mutual risk partner`)\n }\n }\n\n return resolved\n}\n\nfunction getCandidateStrikes(\n params: GenerateOverlappingTokenIdsParams,\n spacing: DecimalSpacing,\n tickSpacing: bigint,\n halfWidth: bigint,\n): bigint[] {\n const lower =\n MIN_TICK + halfWidth > params.currentTick - halfWidth + 1n\n ? MIN_TICK + halfWidth\n : params.currentTick - halfWidth + 1n\n const upper =\n MAX_TICK - halfWidth < params.currentTick + halfWidth - 1n\n ? MAX_TICK - halfWidth\n : params.currentTick + halfWidth - 1n\n const firstStrike = ceilDiv(lower, tickSpacing) * tickSpacing\n const lastStrike = floorDiv(upper, tickSpacing) * tickSpacing\n const strikes: bigint[] = []\n\n for (let strike = firstStrike; strike <= lastStrike; strike += tickSpacing) {\n if (isPriceGridStrike(strike, params, spacing, tickSpacing)) strikes.push(strike)\n }\n\n if (params.asset === 1n) strikes.reverse()\n return strikes\n}\n\nfunction buildTokenId(\n poolId: bigint,\n strike: bigint,\n width: bigint,\n asset: bigint,\n legs: readonly ResolvedLegConfig[],\n): bigint {\n const builder = createTokenIdBuilder(poolId)\n for (const leg of legs) {\n const config = {\n strike,\n width,\n optionRatio: leg.optionRatio,\n isLong: leg.isLong,\n riskPartner: leg.riskPartner,\n asset,\n }\n if (leg.optionType === 'call') builder.addCall(config)\n else builder.addPut(config)\n }\n return builder.build()\n}\n\nfunction dividePositionSize(positionSize: bigint, count: bigint): bigint[] {\n if (positionSize < count) {\n invalid(`positionSize ${positionSize} is too small for ${count} nonzero positions`)\n }\n\n const quotient = positionSize / count\n const remainder = positionSize % count\n const sizes: bigint[] = []\n for (let index = 0n; index < count; index += 1n) {\n sizes.push(quotient + (index < remainder ? 1n : 0n))\n }\n return sizes\n}\n\n/**\n * Generate a fixed quote-price lattice of co-strike TokenIds whose liquidity\n * ranges strictly contain the current tick. Returned arrays are ordered by\n * ascending quote strike price and are ready for `dispatch()`.\n */\nexport function generateOverlappingTokenIds(\n params: GenerateOverlappingTokenIdsParams,\n): GenerateOverlappingTokenIdsResult {\n if (params.poolId < 0n || params.poolId > MAX_UINT64) invalid('poolId must fit in uint64')\n if (params.currentTick < MIN_TICK || params.currentTick > MAX_TICK) {\n invalid(`currentTick must be between ${MIN_TICK} and ${MAX_TICK}`)\n }\n if (params.asset !== 0n && params.asset !== 1n) invalid('asset must be 0 or 1')\n if (\n params.assetDecimals < 0n ||\n params.assetDecimals > MAX_TOKEN_DECIMALS ||\n params.quoteDecimals < 0n ||\n params.quoteDecimals > MAX_TOKEN_DECIMALS\n ) {\n invalid('assetDecimals and quoteDecimals must be between 0 and 255')\n }\n if (params.positionSize <= 0n || params.positionSize > MAX_UINT128) {\n invalid('positionSize must be between 1 and uint128.max')\n }\n\n const tickSpacing = decodeTickSpacing(params.poolId)\n if (tickSpacing <= 0n) invalid('poolId tick spacing must be positive')\n\n const standardTickWidth = STANDARD_TICK_WIDTHS[params.timescale]\n if (standardTickWidth === undefined) invalid(`unknown timescale ${String(params.timescale)}`)\n const width = (standardTickWidth + tickSpacing - 1n) / tickSpacing\n if (width <= 0n || width > LEG_LIMITS.MAX_WIDTH) {\n invalid(\n `timescale width does not fit in the TokenId width field for tick spacing ${tickSpacing}`,\n )\n }\n\n const halfWidth = (width * tickSpacing) / 2n\n if (halfWidth <= 0n) invalid('timescale width must span at least two ticks')\n\n const spacing = parsePriceSpacing(params.strikePriceSpacing, params.quoteDecimals)\n const legs = resolveLegs(params.legs)\n const strikes = getCandidateStrikes(params, spacing, tickSpacing, halfWidth)\n if (strikes.length === 0) invalid('no price-grid strikes overlap the current tick')\n\n return {\n positionIdList: strikes.map((strike) =>\n buildTokenId(params.poolId, strike, width, params.asset, legs),\n ),\n positionSizes: dividePositionSize(params.positionSize, BigInt(strikes.length)),\n }\n}\n","/**\n * Pure TokenId decomposition into shorter-timescale positions.\n * @module v2/tokenId/split\n */\n\nimport { PanopticValidationError } from '../errors'\nimport { type Timescale, LEG_LIMITS, STANDARD_TICK_WIDTHS, TOKEN_ID_BITS } from './constants'\nimport { type DecodedLeg, addLegToTokenId, decodeAllLegs, decodeTickSpacing } from './encoding'\n\nconst POOL_ID_MASK = (1n << TOKEN_ID_BITS.POOL_ID_SIZE) - 1n\nconst MAX_UINT128 = (1n << 128n) - 1n\nconst MAX_UINT256 = (1n << 256n) - 1n\n\n/** TokenIds and sizes aligned with the corresponding `dispatch()` arguments. */\nexport interface SplitTokenIdByTimescaleResult {\n positionIdList: bigint[]\n positionSizes: bigint[]\n}\n\ntype LegGroup = DecodedLeg[]\n\nfunction invalid(message: string): never {\n throw new PanopticValidationError(`splitTokenIdByTimescale: ${message}`)\n}\n\nfunction validateInput(tokenId: bigint, positionSize: bigint): DecodedLeg[] {\n if (tokenId < 0n || tokenId > MAX_UINT256) invalid('tokenId must fit in uint256')\n if (positionSize <= 0n || positionSize > MAX_UINT128) {\n invalid('positionSize must be between 1 and uint128.max')\n }\n\n const legs = decodeAllLegs(tokenId)\n if (legs.length === 0) invalid('tokenId must contain at least one active leg')\n\n for (const [index, leg] of legs.entries()) {\n if (leg.index !== BigInt(index)) invalid('active legs must be contiguous from index 0')\n }\n\n const firstUnusedBit = TOKEN_ID_BITS.POOL_ID_SIZE + BigInt(legs.length) * TOKEN_ID_BITS.LEG_SIZE\n if (tokenId >> firstUnusedBit !== 0n) invalid('inactive leg slots must be empty')\n\n const byIndex = new Map(legs.map((leg) => [leg.index, leg]))\n for (const leg of legs) {\n const partner = byIndex.get(leg.riskPartner)\n if (partner === undefined) invalid(`leg ${leg.index} references an inactive risk partner`)\n if (partner.index !== leg.index && partner.riskPartner !== leg.index) {\n invalid(`leg ${leg.index} has a non-mutual risk partner`)\n }\n }\n\n return legs\n}\n\nfunction isCall(leg: DecodedLeg): boolean {\n return leg.tokenType === leg.asset\n}\n\nfunction isEconomicStraddlePair(left: DecodedLeg, right: DecodedLeg): boolean {\n return (\n isCall(left) !== isCall(right) &&\n left.asset === right.asset &&\n left.optionRatio === right.optionRatio &&\n left.isLong === right.isLong &&\n left.strike === right.strike &&\n left.width === right.width\n )\n}\n\n/** Preserve mutual pairs, then pair self-partnered economic straddles in source order. */\nfunction groupOptionLegs(optionLegs: DecodedLeg[]): LegGroup[] {\n const byIndex = new Map(optionLegs.map((leg) => [leg.index, leg]))\n const consumed = new Set<bigint>()\n const groups: LegGroup[] = []\n\n for (const leg of optionLegs) {\n if (consumed.has(leg.index)) continue\n\n if (leg.riskPartner !== leg.index) {\n const riskPartner = byIndex.get(leg.riskPartner)\n if (riskPartner === undefined) {\n invalid(`mutual risk pair containing leg ${leg.index} cannot be separated`)\n }\n\n consumed.add(leg.index)\n consumed.add(riskPartner.index)\n groups.push([leg, riskPartner])\n continue\n }\n\n const partner = optionLegs.find(\n (candidate) =>\n candidate.index > leg.index &&\n !consumed.has(candidate.index) &&\n candidate.riskPartner === candidate.index &&\n isEconomicStraddlePair(leg, candidate),\n )\n\n consumed.add(leg.index)\n if (partner === undefined) {\n groups.push([leg])\n continue\n }\n\n consumed.add(partner.index)\n groups.push([leg, partner])\n }\n\n return groups\n}\n\nfunction remapRiskPartner(leg: DecodedLeg, indexBySource: ReadonlyMap<bigint, bigint>): bigint {\n const riskPartner = indexBySource.get(leg.riskPartner)\n if (riskPartner === undefined) {\n invalid(`risk partner for leg ${leg.index} is missing from its output group`)\n }\n return riskPartner\n}\n\nfunction buildTokenId(\n poolId: bigint,\n legs: LegGroup,\n transform: (leg: DecodedLeg) => Pick<DecodedLeg, 'strike' | 'width'>,\n): bigint {\n const indexBySource = new Map(legs.map((leg, index) => [leg.index, BigInt(index)]))\n let output = poolId\n\n for (const [index, leg] of legs.entries()) {\n const newIndex = BigInt(index)\n const { strike, width } = transform(leg)\n if (strike < LEG_LIMITS.MIN_STRIKE || strike > LEG_LIMITS.MAX_STRIKE) {\n invalid(`generated strike ${strike} does not fit in int24`)\n }\n if (width < 0n || width > LEG_LIMITS.MAX_WIDTH) {\n invalid(`generated width ${width} does not fit in the TokenId width field`)\n }\n\n output = addLegToTokenId(output, {\n index: newIndex,\n asset: leg.asset,\n optionRatio: leg.optionRatio,\n isLong: leg.isLong ? 1n : 0n,\n tokenType: leg.tokenType,\n riskPartner: remapRiskPartner(leg, indexBySource),\n strike,\n width,\n })\n }\n\n return output\n}\n\nfunction childWidths(sourceWidth: bigint, targetWidth: bigint): bigint[] {\n if (sourceWidth <= targetWidth) return [sourceWidth]\n\n const fullWidthCount = sourceWidth / targetWidth\n const remainder = sourceWidth % targetWidth\n const widths: bigint[] = []\n for (let remaining = fullWidthCount; remaining > 0n; remaining -= 1n) {\n widths.push(targetWidth)\n }\n if (remainder > 0n) widths.push(remainder)\n return widths\n}\n\nfunction dividePositionSize(positionSize: bigint, count: number): bigint[] {\n const countBigInt = BigInt(count)\n if (positionSize < countBigInt) {\n invalid(`positionSize ${positionSize} is too small for ${count} nonzero child positions`)\n }\n\n const quotient = positionSize / countBigInt\n const remainder = positionSize % countBigInt\n return Array.from(\n { length: count },\n (_, index) => quotient + (BigInt(index) < remainder ? 1n : 0n),\n )\n}\n\nfunction splitGroup(\n poolId: bigint,\n group: LegGroup,\n tickSpacing: bigint,\n targetWidth: bigint,\n positionSize: bigint,\n): SplitTokenIdByTimescaleResult {\n const sourceWidth = group[0]?.width\n if (sourceWidth === undefined || sourceWidth === 0n)\n invalid('option group must have nonzero width')\n if (group.some((leg) => leg.width !== sourceWidth)) {\n invalid('all legs in an option group must have the same width')\n }\n\n const widths = childWidths(sourceWidth, targetWidth)\n const positionSizes = dividePositionSize(positionSize, widths.length)\n let consumedWidth = 0n\n\n const positionIdList = widths.map((width) => {\n const offset = consumedWidth\n consumedWidth += width\n\n return buildTokenId(poolId, group, (leg) => {\n // PanopticMath.getTicks uses floor below the strike and ceil above it.\n const sourceLower = leg.strike - (sourceWidth * tickSpacing) / 2n\n const childLower = sourceLower + offset * tickSpacing\n const strike = childLower + (width * tickSpacing) / 2n\n return { strike, width }\n })\n })\n\n return { positionIdList, positionSizes }\n}\n\n/**\n * Split every standalone option, economic straddle, or mutual risk pair in a\n * TokenId into a shorter standard timescale. Width-zero credit/loan legs are\n * emitted together as one final position. Returned arrays are parallel and\n * ready for `dispatch()`.\n *\n * Each option group divides `positionSize` independently across its children.\n * Integer remainder units are assigned to the lower children first.\n */\nexport function splitTokenIdByTimescale(\n tokenId: bigint,\n positionSize: bigint,\n targetTimescale: Timescale,\n): SplitTokenIdByTimescaleResult {\n const legs = validateInput(tokenId, positionSize)\n const tickSpacing = decodeTickSpacing(tokenId)\n if (tickSpacing <= 0n) invalid('tokenId tick spacing must be positive')\n\n const targetTickWidth = STANDARD_TICK_WIDTHS[targetTimescale]\n if (targetTickWidth === undefined) invalid(`unknown target timescale ${String(targetTimescale)}`)\n const targetWidth = (targetTickWidth + tickSpacing - 1n) / tickSpacing\n\n const poolId = tokenId & POOL_ID_MASK\n const optionLegs = legs.filter((leg) => leg.width > 0n)\n const fundingLegs = legs.filter((leg) => leg.width === 0n)\n const positionIdList: bigint[] = []\n const positionSizes: bigint[] = []\n\n for (const group of groupOptionLegs(optionLegs)) {\n const split = splitGroup(poolId, group, tickSpacing, targetWidth, positionSize)\n positionIdList.push(...split.positionIdList)\n positionSizes.push(...split.positionSizes)\n }\n\n if (fundingLegs.length > 0) {\n positionIdList.push(\n buildTokenId(poolId, fundingLegs, (leg) => ({ strike: leg.strike, width: leg.width })),\n )\n positionSizes.push(positionSize)\n }\n\n return { positionIdList, positionSizes }\n}\n","import { tickToSqrtPriceX96 } from '../panoptic/v2/formatters/tick'\nimport { decodeAllLegs } from '../panoptic/v2/tokenId'\nimport type { LpFeeRange } from './estimateLpFees'\n\nconst Q96 = 1n << 96n\nconst ceilDiv = (n: bigint, d: bigint) => (n + d - 1n) / d\n\n/** Uniswap mint principal in raw token units, rounded up per leg, plus 5% headroom. */\nexport function getLpDepositAmounts(ranges: readonly LpFeeRange[], sqrtPriceX96: bigint) {\n return getLpDepositBreakdown(ranges, sqrtPriceX96).total\n}\n\n/** Principal and separately identified funding headroom, in native token units. */\nexport function getLpDepositBreakdown(ranges: readonly LpFeeRange[], sqrtPriceX96: bigint) {\n if (sqrtPriceX96 <= 0n) throw new Error('Invalid pool price')\n let amount0 = 0n\n let amount1 = 0n\n for (const { tickLower, tickUpper, liquidity } of ranges) {\n if (\n !Number.isInteger(tickLower) ||\n !Number.isInteger(tickUpper) ||\n tickLower < -887272 ||\n tickUpper > 887272 ||\n tickLower >= tickUpper ||\n liquidity < 0n\n )\n throw new Error('Invalid LP range')\n const lower = tickToSqrtPriceX96(BigInt(tickLower))\n const upper = tickToSqrtPriceX96(BigInt(tickUpper))\n const price = sqrtPriceX96 < lower ? lower : sqrtPriceX96 > upper ? upper : sqrtPriceX96\n amount0 += ceilDiv(liquidity * Q96 * (upper - price), upper * price)\n amount1 += ceilDiv(liquidity * (price - lower), Q96)\n }\n const buffer = { amount0: ceilDiv(amount0 * 5n, 100n), amount1: ceilDiv(amount1 * 5n, 100n) }\n return {\n principal: { amount0, amount1 },\n buffer,\n total: { amount0: amount0 + buffer.amount0, amount1: amount1 + buffer.amount1 },\n }\n}\n\nexport interface LpPositionFundingParams {\n tokenId: bigint\n positionSize: bigint\n tickSpacing: bigint\n sqrtPriceX96: bigint\n /** Price used consistently to value funding and account collateral. */\n valuationSqrtPriceX96: bigint\n quoteTokenIndex: 0 | 1\n}\n\n/** Full deployed liquidity value; never a leveraged protocol margin estimate. */\nexport function getLpPositionFunding(params: LpPositionFundingParams) {\n const {\n tokenId,\n positionSize,\n tickSpacing,\n sqrtPriceX96,\n valuationSqrtPriceX96,\n quoteTokenIndex,\n } = params\n if (positionSize < 0n || tickSpacing <= 0n || valuationSqrtPriceX96 <= 0n)\n throw new Error('Invalid LP funding input')\n const legs = decodeAllLegs(tokenId)\n if (legs.length === 0 || legs.some((leg) => leg.isLong || leg.width === 0n))\n throw new Error('AMM Liquidity requires short liquidity legs without loans or credits')\n const ranges = legs.map((leg) => {\n const width = leg.width * tickSpacing\n const tickLower = leg.strike - width / 2n\n const tickUpper = leg.strike + (width + 1n) / 2n\n const lower = tickToSqrtPriceX96(tickLower)\n const upper = tickToSqrtPriceX96(tickUpper)\n const amount = positionSize * leg.optionRatio\n const liquidity =\n leg.asset === 0n\n ? (amount * ((lower * upper) / Q96)) / (upper - lower)\n : (amount * Q96) / (upper - lower)\n return { tickLower: Number(tickLower), tickUpper: Number(tickUpper), liquidity }\n })\n const breakdown = getLpDepositBreakdown(ranges, sqrtPriceX96)\n const priceSquared = valuationSqrtPriceX96 * valuationSqrtPriceX96\n const value = ({ amount0, amount1 }: { amount0: bigint; amount1: bigint }) =>\n quoteTokenIndex === 0\n ? amount0 + ceilDiv(amount1 * Q96 * Q96, priceSquared)\n : amount1 + ceilDiv(amount0 * priceSquared, Q96 * Q96)\n const principalInQuote = value(breakdown.principal)\n const totalInQuote = value(breakdown.total)\n return {\n ...breakdown,\n principalInQuote,\n bufferInQuote: totalInQuote - principalInQuote,\n totalInQuote,\n }\n}\n\n/** Remaining deposit in the requested token mix, rounded up to cover the shortfall. */\nexport function getLpFundingDeposit({\n funding,\n availableInQuote,\n minimumInQuote = 0n,\n quoteTokenIndex,\n valuationSqrtPriceX96,\n quotePercent,\n}: {\n funding: ReturnType<typeof getLpPositionFunding>\n availableInQuote: bigint\n minimumInQuote?: bigint\n quoteTokenIndex: 0 | 1\n valuationSqrtPriceX96: bigint\n quotePercent?: bigint\n}) {\n if (\n valuationSqrtPriceX96 <= 0n ||\n (quotePercent !== undefined && (quotePercent < 0n || quotePercent > 100n))\n )\n throw new Error('Invalid LP funding split')\n const requiredInQuote =\n minimumInQuote > funding.totalInQuote ? minimumInQuote : funding.totalInQuote\n const shortfallInQuote =\n requiredInQuote > availableInQuote ? requiredInQuote - availableInQuote : 0n\n const defaultQuotePercent =\n funding.totalInQuote > 0n\n ? ((quoteTokenIndex === 0 ? funding.total.amount0 : funding.total.amount1) * 100n) /\n funding.totalInQuote\n : 100n\n if (quotePercent === undefined) {\n return {\n requiredInQuote,\n shortfallInQuote,\n defaultQuotePercent,\n amount0:\n funding.totalInQuote > 0n\n ? ceilDiv(funding.total.amount0 * shortfallInQuote, funding.totalInQuote)\n : 0n,\n amount1:\n funding.totalInQuote > 0n\n ? ceilDiv(funding.total.amount1 * shortfallInQuote, funding.totalInQuote)\n : 0n,\n }\n }\n const quoteAmount = (shortfallInQuote * quotePercent) / 100n\n const assetValue = shortfallInQuote - quoteAmount\n const priceSquared = valuationSqrtPriceX96 * valuationSqrtPriceX96\n return {\n requiredInQuote,\n shortfallInQuote,\n defaultQuotePercent,\n amount0: quoteTokenIndex === 0 ? quoteAmount : ceilDiv(assetValue * Q96 * Q96, priceSquared),\n amount1: quoteTokenIndex === 1 ? quoteAmount : ceilDiv(assetValue * priceSquared, Q96 * Q96),\n }\n}\n\n/** Largest raw size funded by available collateral, including native-token rounding. */\nexport function getMaxLpPositionSize(\n params: Omit<LpPositionFundingParams, 'positionSize'> & {\n availableInQuote: bigint\n minimumRequirement?: { referenceSize: bigint; requiredInQuote: bigint }\n },\n) {\n if (\n params.minimumRequirement &&\n (params.minimumRequirement.referenceSize <= 0n ||\n params.minimumRequirement.requiredInQuote < 0n)\n )\n throw new Error('Invalid reference requirement')\n if (params.availableInQuote <= 0n) return 0n\n let low = 0n\n let high = (1n << 128n) - 1n\n while (low < high) {\n const mid = (low + high + 1n) / 2n\n const funding = getLpPositionFunding({ ...params, positionSize: mid })\n const minimum = params.minimumRequirement\n ? ceilDiv(\n params.minimumRequirement.requiredInQuote * mid,\n params.minimumRequirement.referenceSize,\n )\n : 0n\n if (funding.totalInQuote <= params.availableInQuote && minimum <= params.availableInQuote)\n low = mid\n else high = mid - 1n\n }\n return low\n}\n","/**\n * Greeks for plain (non-Panoptic) Uniswap v3/v4 concentrated-liquidity LP\n * positions. Pure math over on-chain position fields (liquidity + tick range)\n * and the pool's current price — no RPC, no protocol dependency.\n *\n * Units follow the Panoptic v2 greeks convention (see\n * `packages/sdk/src/panoptic/v2/greeks/index.ts`) so a caller can present LP\n * and Panoptic greeks side by side:\n * - `value` → numeraire-token smallest units\n * - `delta` → asset-token smallest units (the asset held by the LP)\n * - `gamma` → numeraire-token smallest units (dollar-gamma `P²·d²V/dP²`;\n * always ≤ 0 because an LP is short gamma)\n *\n * `assetIndex` selects which token is the \"asset\" (the volatile leg being\n * hedged): `0` → token0 is the asset / token1 the numeraire; `1` → the reverse.\n *\n * @module uniswap/lpGreeks\n */\n\nimport { tickToSqrtPriceX96 } from '../panoptic/v2/formatters/tick'\n\nconst Q96 = 1n << 96n\nconst Q192 = 1n << 192n\n\n/** Token amounts currently backing a concentrated-liquidity position. */\nexport interface LpAmounts {\n /** token0 amount in its smallest units. */\n amount0: bigint\n /** token1 amount in its smallest units. */\n amount1: bigint\n}\n\n/** Greeks of a Uniswap LP position in one asset frame (see module docs for units). */\nexport interface LpGreeks {\n /** Position value in numeraire-token smallest units. */\n value: bigint\n /** Delta in asset-token smallest units (the asset amount the LP is long). */\n delta: bigint\n /** Dollar-gamma in numeraire-token smallest units; ≤ 0 (LP is short gamma). */\n gamma: bigint\n}\n\n/** Inputs describing a single LP position + the pool's current price. */\nexport interface LpGreeksInput {\n /** Position liquidity `L`. */\n liquidity: bigint\n /** Lower tick of the range. */\n tickLower: bigint\n /** Upper tick of the range. */\n tickUpper: bigint\n /** Pool's current tick. */\n currentTick: bigint\n /** Which token is the asset: `0` (token0) or `1` (token1). */\n assetIndex: 0 | 1\n}\n\n/**\n * Compute the token0/token1 amounts backing `liquidity` over `[sqrtA, sqrtB]`\n * at the current price `sqrtP`, mirroring Uniswap's `LiquidityAmounts`\n * (`getAmountsForLiquidity`). All sqrt prices are X96. The current price is\n * clamped into the range, so out-of-range positions collapse to a single token.\n */\nexport function getAmountsForLiquidity(\n sqrtPriceX96: bigint,\n sqrtRatioAX96: bigint,\n sqrtRatioBX96: bigint,\n liquidity: bigint,\n): LpAmounts {\n // Normalize so A <= B.\n const [sqrtA, sqrtB] =\n sqrtRatioAX96 <= sqrtRatioBX96 ? [sqrtRatioAX96, sqrtRatioBX96] : [sqrtRatioBX96, sqrtRatioAX96]\n\n // Clamp the current price into [A, B].\n const sqrtC = sqrtPriceX96 < sqrtA ? sqrtA : sqrtPriceX96 > sqrtB ? sqrtB : sqrtPriceX96\n\n // amount0 = L * (sqrtB - sqrtC) * 2^96 / (sqrtC * sqrtB)\n const amount0 = sqrtC < sqrtB ? (liquidity * (sqrtB - sqrtC) * Q96) / (sqrtC * sqrtB) : 0n\n\n // amount1 = L * (sqrtC - sqrtA) / 2^96\n const amount1 = sqrtC > sqrtA ? (liquidity * (sqrtC - sqrtA)) / Q96 : 0n\n\n return { amount0, amount1 }\n}\n\n/**\n * Greeks (value, delta, gamma) for a Uniswap LP position in the chosen asset\n * frame. See the module docs for the unit conventions.\n *\n * Closed forms (in-range, numeraire = token1 / asset = token0):\n * value = amount1 + amount0·P (P = sqrtP² / 2^192)\n * delta = amount0 (= dV/dP)\n * gamma = P²·d²V/dP² = -L·sqrt(P)/2 (short gamma)\n * The `assetIndex = 1` frame is the symmetric inverse (numeraire = token0).\n * Gamma is zero when the price is outside the range (no curvature there).\n */\nexport function getLpGreeks(input: LpGreeksInput): LpGreeks {\n const { liquidity, tickLower, tickUpper, currentTick, assetIndex } = input\n\n const sqrtP = tickToSqrtPriceX96(currentTick)\n const sqrtA = tickToSqrtPriceX96(tickLower)\n const sqrtB = tickToSqrtPriceX96(tickUpper)\n\n const { amount0, amount1 } = getAmountsForLiquidity(sqrtP, sqrtA, sqrtB, liquidity)\n\n const sqrtP2 = sqrtP * sqrtP // P in X192\n const inRange = sqrtP > sqrtA && sqrtP < sqrtB\n\n if (assetIndex === 0) {\n // numeraire = token1, asset = token0\n const value = amount1 + (amount0 * sqrtP2) / Q192\n const delta = amount0\n // gamma = -L·sqrt(P)/2, sqrt(P) = sqrtP / 2^96 → in token1 units\n const gamma = inRange ? -(liquidity * sqrtP) / (2n * Q96) : 0n\n return { value, delta, gamma }\n }\n\n // numeraire = token0, asset = token1\n const value = amount0 + (amount1 * Q192) / sqrtP2\n const delta = amount1\n // gamma = -L·sqrt(1/P)/2, sqrt(1/P) = 2^96 / sqrtP → in token0 units\n const gamma = inRange ? -(liquidity * Q96) / (2n * sqrtP) : 0n\n return { value, delta, gamma }\n}\n","import Decimal from 'decimal.js'\n\nimport { tickToSqrtPriceX96 } from '../panoptic/v2/formatters/tick'\nimport type { LpFeeRange } from './estimateLpFees'\nimport { getAmountsForLiquidity } from './lpGreeks'\n\nconst D = Decimal.clone({ precision: 60 })\n\n/** Simple fee APR over the full selected viewport, without compounding. */\nexport function annualizeLpFeeReturn(feeReturnPercent: Decimal, durationSeconds: bigint) {\n if (durationSeconds <= 0n) throw new Error('APR requires a positive window duration')\n return new D(feeReturnPercent).mul(31_536_000).div(durationSeconds.toString())\n}\n\n/**\n * Combine both fee tokens into a fee-only return on deployed LP capital.\n * Value both capital and fees at the window's opening price: this keeps fee\n * return flat when accrual stops and makes the ratio independent of quote\n * orientation. Raw token amounts already account for differing decimals.\n * Excludes principal price changes, impermanent loss and costs; not annualized.\n * Returns undefined when the position has no representable deployed capital.\n */\nexport function getLpFeeReturnSeries<T extends { fees0: bigint; fees1: bigint }>({\n points,\n ranges,\n startTick,\n}: {\n points: readonly T[]\n ranges: readonly LpFeeRange[]\n startTick: number\n}) {\n const validTick = (tick: number) => Number.isInteger(tick) && Math.abs(tick) <= 887272\n if (!validTick(startTick)) throw new Error('Invalid valuation tick')\n const sqrtP = tickToSqrtPriceX96(BigInt(startTick))\n const price = new D(sqrtP.toString()).pow(2).div(new D((1n << 192n).toString()))\n let capital0 = 0n\n let capital1 = 0n\n for (const range of ranges) {\n if (\n !validTick(range.tickLower) ||\n !validTick(range.tickUpper) ||\n range.tickLower >= range.tickUpper ||\n range.liquidity < 0n\n )\n throw new Error('Invalid LP range')\n const amounts = getAmountsForLiquidity(\n sqrtP,\n tickToSqrtPriceX96(BigInt(range.tickLower)),\n tickToSqrtPriceX96(BigInt(range.tickUpper)),\n range.liquidity,\n )\n capital0 += amounts.amount0\n capital1 += amounts.amount1\n }\n const capital = new D(capital0.toString()).mul(price).plus(capital1.toString())\n if (capital.isZero()) return undefined\n return points.map((point) => {\n if (point.fees0 < 0n || point.fees1 < 0n) throw new Error('Invalid fee amount')\n const fees = new D(point.fees0.toString()).mul(price).plus(point.fees1.toString())\n return { ...point, feeReturnPercent: fees.div(capital).mul(100) }\n })\n}\n","/**\n * Forward-looking \"will this LP range stay in range?\" statistics.\n *\n * Model: driftless geometric Brownian motion of the pool price. In log space the\n * position is inside its range while `ln(lower) < ln(S_t) < ln(upper)`; with\n * `x_t = ln(S_t) ∼ N(x0, σ²·t)` the probability of being in range at horizon `t`\n * is a difference of two standard-normal CDFs. Expected fraction of time in range\n * over `[0, T]` is the time-average of that same probability (exact by Fubini):\n * `(1/T)·∫₀ᵀ P(in range at t) dt`, computed by numeric integration.\n *\n * Both column values in the portfolio LP rows (P(in range) and E[time in range])\n * fall out of the single {@link pInRangeAt} kernel, so they can never disagree in\n * sign: a position that starts in range always has E ≥ P at every horizon, and one\n * that starts out of range always has E ≤ P.\n *\n * Drift is assumed zero — this is a pure volatility read, not a directional\n * forecast. Vol estimation lives with the caller (the UI already has realized-vol\n * estimators); pass the annualized σ in.\n *\n * @module uniswap/rangeProbability\n */\n\n/**\n * Standard-normal CDF Φ(x). Uses a rational erf approximation\n * (Abramowitz & Stegun 7.1.26), max abs error ≈ 1.5e-7 — ample for a\n * percentage read.\n */\nexport function normalCdf(x: number): number {\n if (!Number.isFinite(x)) return x > 0 ? 1 : 0\n const z = x / Math.SQRT2\n const t = 1 / (1 + 0.3275911 * Math.abs(z))\n const y =\n 1 -\n ((((1.061405429 * t - 1.453152027) * t + 1.421413741) * t - 0.284496736) * t + 0.254829592) *\n t *\n Math.exp(-z * z)\n const erf = z >= 0 ? y : -y\n return 0.5 * (1 + erf)\n}\n\nexport interface RangeProbabilityInput {\n /** Current pool price in the display frame (quote per asset). */\n spot: number\n /** Lower range bound in the same frame. `0` or non-finite means unbounded below. */\n lower: number\n /** Upper range bound in the same frame. `Infinity` or non-finite means unbounded above. */\n upper: number\n /** Annualized volatility as a fraction (e.g. 0.8 = 80%). */\n sigmaAnnual: number\n /** Horizon in years. */\n tYears: number\n}\n\n/**\n * Probability the price is inside `[lower, upper]` at horizon `tYears`.\n * Returns 1 for a full-range position (both bounds unbounded) and is well-defined\n * for an out-of-range spot (then it reads as \"chance of being back in range by t\").\n */\nexport function pInRangeAt(input: RangeProbabilityInput): number {\n const { spot, lower, upper, sigmaAnnual, tYears } = input\n const boundedBelow = lower > 0 && Number.isFinite(lower)\n const boundedAbove = Number.isFinite(upper) && upper > 0\n // Fully unbounded range is always \"in range\".\n if (!boundedBelow && !boundedAbove) return 1\n if (!(spot > 0)) return 0\n\n const s = sigmaAnnual * Math.sqrt(Math.max(0, tYears))\n // Degenerate horizon/vol: the price cannot move, so it is in range iff it is now.\n if (!(s > 0)) {\n const above = boundedBelow ? spot > lower : true\n const below = boundedAbove ? spot < upper : true\n return above && below ? 1 : 0\n }\n\n const x0 = Math.log(spot)\n const hi = boundedAbove ? normalCdf((Math.log(upper) - x0) / s) : 1\n const lo = boundedBelow ? normalCdf((Math.log(lower) - x0) / s) : 0\n return Math.min(1, Math.max(0, hi - lo))\n}\n\nexport interface ExpectedTimeInRangeInput extends RangeProbabilityInput {\n /** Integration steps over [0, T]. Default 64 — smooth to <0.1% for these curves. */\n steps?: number\n}\n\n/**\n * Expected fraction of `[0, tYears]` spent in range — the time-average of\n * {@link pInRangeAt}. Trapezoidal integration; the integrand starts at exactly\n * 1 (in-range now) or 0 (out-of-range now) at t=0, which the trapezoid endpoint\n * captures.\n */\nexport function expectedTimeInRange(input: ExpectedTimeInRangeInput): number {\n const { tYears, steps = 64 } = input\n if (!(tYears > 0)) return pInRangeAt({ ...input, tYears: 0 })\n const n = Math.max(2, Math.floor(steps))\n const dt = tYears / n\n let acc = 0\n for (let i = 0; i <= n; i++) {\n const p = pInRangeAt({ ...input, tYears: i * dt })\n acc += i === 0 || i === n ? p / 2 : p\n }\n return Math.min(1, Math.max(0, (acc * dt) / tYears))\n}\n\nexport interface RangeStatsInput {\n spot: number\n lower: number\n upper: number\n sigmaAnnual: number\n}\n\nexport interface RangeStats {\n /** P(in range at each horizon), index-aligned to `horizonsYears`. */\n p: number[]\n /** E[fraction of time in range up to each horizon], index-aligned. */\n e: number[]\n}\n\n/**\n * Compute both statistics for a set of horizons in one call — the shape the LP\n * row (7d / 30d / 365d) and the portfolio KPI aggregation consume.\n */\nexport function rangeStats(input: RangeStatsInput, horizonsYears: readonly number[]): RangeStats {\n const p: number[] = []\n const e: number[] = []\n for (const tYears of horizonsYears) {\n p.push(pInRangeAt({ ...input, tYears }))\n e.push(expectedTimeInRange({ ...input, tYears }))\n }\n return { p, e }\n}\n\n/** Horizons used by the LP portfolio display, in years. */\nexport const LP_RANGE_HORIZONS_DAYS = [7, 30, 365] as const\nexport const LP_RANGE_HORIZONS_YEARS = LP_RANGE_HORIZONS_DAYS.map((d) => d / 365)\n","/**\n * Errors for the Uniswap v4 Universal Router swap module.\n *\n * All extend {@link PanopticError} so callers can keep a single\n * `instanceof PanopticError` check and so they satisfy `SimulationResult`'s\n * error type.\n *\n * @module uniswap/v4/router/errors\n */\n\nimport type { Address } from 'viem'\n\nimport { PanopticError } from '../../../panoptic/v2/errors'\n\n/**\n * The chain has no configured Uniswap v4 addresses and none were supplied via\n * overrides.\n */\nexport class UnsupportedChainError extends PanopticError {\n override readonly name = 'UnsupportedChainError'\n\n constructor(\n public readonly chainId: bigint,\n cause?: Error,\n ) {\n super(`Uniswap v4 router not configured for chain ${chainId}`, cause)\n }\n}\n\n/**\n * `tokenIn` is neither `currency0` nor `currency1` of the resolved pool.\n */\nexport class InvalidSwapTokenError extends PanopticError {\n override readonly name = 'InvalidSwapTokenError'\n\n constructor(\n public readonly token: Address,\n public readonly currency0: Address,\n public readonly currency1: Address,\n cause?: Error,\n ) {\n super(\n `Token ${token} is not part of the pool (currency0=${currency0}, currency1=${currency1})`,\n cause,\n )\n }\n}\n\n/**\n * An amount exceeds the uint128 range required by the v4 swap encoding.\n */\nexport class AmountExceedsUint128Error extends PanopticError {\n override readonly name = 'AmountExceedsUint128Error'\n\n constructor(\n public readonly amount: bigint,\n cause?: Error,\n ) {\n super(`Amount ${amount} exceeds uint128 maximum`, cause)\n }\n}\n\n/**\n * A native-ETH swap needs a trailing Universal Router SWEEP to deliver the ETH\n * output (or refund the input overpay), but no `recipient` was supplied.\n */\nexport class MissingSweepRecipientError extends PanopticError {\n override readonly name = 'MissingSweepRecipientError'\n\n constructor(cause?: Error) {\n super('A recipient is required to sweep native ETH back to the user', cause)\n }\n}\n\n/**\n * The V4Quoter is not available for the chain (no fallback in v1).\n */\nexport class QuoterUnavailableError extends PanopticError {\n override readonly name = 'QuoterUnavailableError'\n\n constructor(\n public readonly chainId: bigint,\n cause?: Error,\n ) {\n super(`V4Quoter unavailable for chain ${chainId}`, cause)\n }\n}\n","/**\n * Per-chain Uniswap v3 addresses needed for spot quoting via the Universal\n * Router. The Universal Router itself is shared with v4 (see\n * `uniswap/v4/addresses`); only the v3 QuoterV2 is specific to v3.\n *\n * Supports Ethereum mainnet and Robinhood; other chains throw {@link UnsupportedChainError}\n * unless the address is supplied via overrides (fork tests / new chains).\n *\n * @module uniswap/v3/addresses\n */\n\nimport type { Address } from 'viem'\n\nimport { UnsupportedChainError } from '../v4/router/errors'\n\nexport interface UniswapV3Addresses {\n /** Uniswap v3 QuoterV2 — `quoteExactInputSingle` (revert/staticcall-based). */\n quoterV2: Address\n /** Uniswap v3 NonfungiblePositionManager — ERC721 LP position NFTs. */\n nonfungiblePositionManager: Address\n}\n\n/**\n * Verified Uniswap v3 QuoterV2 addresses keyed by chainId. Add a chain only\n * after verifying against the canonical Uniswap v3 deployment listing.\n */\nexport const UNISWAP_V3_ADDRESSES: Record<number, UniswapV3Addresses> = {\n // Ethereum mainnet\n 1: {\n quoterV2: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e',\n nonfungiblePositionManager: '0xC36442b4a4522E871399CD717aBDD847Ab11FE88',\n },\n 4663: {\n quoterV2: '0x33e885ed0ec9bf04ecfb19341582aadcb4c8a9e7',\n nonfungiblePositionManager: '0x73991a25c818bf1f1128deaab1492d45638de0d3',\n },\n}\n\n/**\n * Resolve Uniswap v3 addresses for a chain, applying optional overrides.\n *\n * @throws {UnsupportedChainError} when the chain is not listed and overrides do\n * not supply every required address.\n */\nexport function getUniswapV3Addresses(\n chainId: number | bigint,\n overrides?: Partial<UniswapV3Addresses>,\n): UniswapV3Addresses {\n const id = Number(chainId)\n const base = UNISWAP_V3_ADDRESSES[id]\n const merged = { ...base, ...overrides }\n if (!merged.quoterV2 || !merged.nonfungiblePositionManager) {\n throw new UnsupportedChainError(BigInt(id))\n }\n return merged as UniswapV3Addresses\n}\n","/**\n * Minimal Universal Router ABI (only the `execute` overload we use).\n * @module uniswap/v4/abis/universalRouter\n */\n\nexport const universalRouterAbi = [\n {\n type: 'function',\n name: 'execute',\n stateMutability: 'payable',\n inputs: [\n { name: 'commands', type: 'bytes' },\n { name: 'inputs', type: 'bytes[]' },\n { name: 'deadline', type: 'uint256' },\n ],\n outputs: [],\n },\n] as const\n","/**\n * Pure calldata builder for an exact-in single-hop swap through a Uniswap **v3**\n * pool via the Universal Router.\n *\n * Opcodes verified against `@uniswap/universal-router` `Commands.sol`:\n * - Universal Router command `V3_SWAP_EXACT_IN = 0x00`.\n *\n * The v3 command input is (unlike the v4 action list) a single flat tuple:\n * `(address recipient, uint256 amountIn, uint256 amountOutMinimum,\n * bytes path, bool payerIsUser)`\n * where:\n * - `recipient` is an EXPLICIT field. We encode the Universal Router sentinel\n * `MSG_SENDER = address(1)`, which the router maps to the `execute` caller —\n * so the output is delivered to the caller (e.g. a Safe) with no literal\n * address in the calldata to redirect.\n * - `path` is `abi.encodePacked(tokenIn, fee (uint24), tokenOut)` for a single\n * hop (43 bytes). The direction lives in the path ordering, not a bool.\n * - `payerIsUser = true`: the router pulls `tokenIn` from the caller via Permit2.\n *\n * ERC20-only: native ETH is intentionally unsupported here (the native paths\n * need WRAP/UNWRAP/SWEEP commands with explicit recipients).\n *\n * @module uniswap/v3/router/encodeSwap\n */\n\nimport type { Address, Hex } from 'viem'\nimport { encodeAbiParameters, encodeFunctionData, encodePacked, zeroAddress } from 'viem'\n\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport { universalRouterAbi } from '../../v4/abis/universalRouter'\nimport { AmountExceedsUint128Error } from '../../v4/router/errors'\n\n/** Universal Router command byte for a v3 exact-in swap. */\nexport const V3_SWAP_EXACT_IN = 0x00\n\n/** Universal Router command byte for a v3 exact-out swap. */\nexport const V3_SWAP_EXACT_OUT = 0x01\n\n/**\n * Universal Router recipient sentinel: the router maps `address(1)` to\n * `msg.sender` (the `execute` caller). Uniswap `Constants.MSG_SENDER`.\n */\nexport const MSG_SENDER: Address = '0x0000000000000000000000000000000000000001'\n\nconst UINT128_MAX = (1n << 128n) - 1n\n\nconst v3ExactInInputAbi = [\n { name: 'recipient', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'amountOutMinimum', type: 'uint256' },\n { name: 'path', type: 'bytes' },\n { name: 'payerIsUser', type: 'bool' },\n] as const\n\nfunction assertUint128(amount: bigint): void {\n if (amount < 0n || amount > UINT128_MAX) {\n throw new AmountExceedsUint128Error(amount)\n }\n}\n\n/** Arguments for {@link buildV3SwapExecuteCalldata}. */\nexport interface BuildV3SwapCalldataArgs {\n /** Input token (funds pulled from the caller via Permit2). */\n tokenIn: Address\n /** Output token. */\n tokenOut: Address\n /** v3 pool fee tier (e.g. 500, 3000). */\n fee: bigint\n /** Exact input amount (uint128). */\n amountIn: bigint\n /** Minimum acceptable output (uint128). */\n amountOutMinimum: bigint\n /**\n * Absolute deadline (unix seconds) — the `execute(commands, inputs, deadline)`\n * argument, enforced by the Universal Router.\n */\n deadline: bigint\n}\n\n/**\n * Encode the packed v3 single-hop path `tokenIn ++ fee(uint24) ++ tokenOut`.\n */\nexport function encodeV3Path(tokenIn: Address, fee: bigint, tokenOut: Address): Hex {\n if (fee < 0n || fee > 0xffffffn) {\n throw new PanopticError(`v3 fee ${fee} exceeds uint24`)\n }\n return encodePacked(['address', 'uint24', 'address'], [tokenIn, Number(fee), tokenOut])\n}\n\n/**\n * Build the typed `execute(...)` args for an exact-in single-hop v3 swap whose\n * output is delivered to the `execute` caller (recipient = MSG_SENDER).\n */\nexport function buildV3SwapExecuteArgs(args: BuildV3SwapCalldataArgs): {\n args: readonly [Hex, readonly Hex[], bigint]\n value: bigint\n} {\n const { tokenIn, tokenOut, fee, amountIn, amountOutMinimum, deadline } = args\n\n if (tokenIn === zeroAddress || tokenOut === zeroAddress) {\n throw new PanopticError('native ETH is not supported by the v3 exact-in router builder')\n }\n assertUint128(amountIn)\n assertUint128(amountOutMinimum)\n\n const path = encodeV3Path(tokenIn, fee, tokenOut)\n const input = encodeAbiParameters(v3ExactInInputAbi, [\n MSG_SENDER,\n amountIn,\n amountOutMinimum,\n path,\n true, // payerIsUser: pull tokenIn from the caller via Permit2\n ])\n\n const commands = encodePacked(['uint8'], [V3_SWAP_EXACT_IN])\n return { args: [commands, [input], deadline] as const, value: 0n }\n}\n\n/**\n * Build the `execute(commands, inputs, deadline)` calldata for an exact-in\n * single-hop v3 swap.\n */\nexport function buildV3SwapExecuteCalldata(args: BuildV3SwapCalldataArgs): {\n data: Hex\n value: bigint\n} {\n const { args: executeArgs, value } = buildV3SwapExecuteArgs(args)\n const data = encodeFunctionData({\n abi: universalRouterAbi,\n functionName: 'execute',\n args: executeArgs,\n })\n return { data, value }\n}\n\nexport interface BuildV3ExactOutSwapCalldataArgs {\n tokenIn: Address\n tokenOut: Address\n fee: bigint\n amountOut: bigint\n amountInMaximum: bigint\n deadline: bigint\n}\n\nconst v3ExactOutInputAbi = [\n { name: 'recipient', type: 'address' },\n { name: 'amountOut', type: 'uint256' },\n { name: 'amountInMaximum', type: 'uint256' },\n { name: 'path', type: 'bytes' },\n { name: 'payerIsUser', type: 'bool' },\n] as const\n\n/**\n * Build the typed `execute(...)` args for an exact-out single-hop v3 swap.\n * The v3 exact-out path is reversed: `tokenOut ++ fee ++ tokenIn`.\n */\nexport function buildV3ExactOutSwapExecuteArgs(args: BuildV3ExactOutSwapCalldataArgs): {\n args: readonly [Hex, readonly Hex[], bigint]\n value: bigint\n} {\n const { tokenIn, tokenOut, fee, amountOut, amountInMaximum, deadline } = args\n\n if (tokenIn === zeroAddress || tokenOut === zeroAddress) {\n throw new PanopticError('native ETH is not supported by the v3 exact-out router builder')\n }\n assertUint128(amountOut)\n assertUint128(amountInMaximum)\n\n const path = encodeV3Path(tokenOut, fee, tokenIn)\n const input = encodeAbiParameters(v3ExactOutInputAbi, [\n MSG_SENDER,\n amountOut,\n amountInMaximum,\n path,\n true,\n ])\n\n const commands = encodePacked(['uint8'], [V3_SWAP_EXACT_OUT])\n return { args: [commands, [input], deadline] as const, value: 0n }\n}\n\nexport function buildV3ExactOutSwapExecuteCalldata(args: BuildV3ExactOutSwapCalldataArgs): {\n data: Hex\n value: bigint\n} {\n const { args: executeArgs, value } = buildV3ExactOutSwapExecuteArgs(args)\n const data = encodeFunctionData({\n abi: universalRouterAbi,\n functionName: 'execute',\n args: executeArgs,\n })\n return { data, value }\n}\n","/**\n * Minimal Uniswap v3 QuoterV2 ABI.\n *\n * QuoterV2 is revert/staticcall-based (nonpayable but intended for `eth_call` /\n * `simulateContract`), so it must be simulated, not read.\n * @module uniswap/v3/abis/quoterV2\n */\n\nexport const quoterV2Abi = [\n {\n type: 'function',\n name: 'quoteExactInputSingle',\n stateMutability: 'nonpayable',\n inputs: [\n {\n name: 'params',\n type: 'tuple',\n components: [\n { name: 'tokenIn', type: 'address' },\n { name: 'tokenOut', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'fee', type: 'uint24' },\n { name: 'sqrtPriceLimitX96', type: 'uint160' },\n ],\n },\n ],\n outputs: [\n { name: 'amountOut', type: 'uint256' },\n { name: 'sqrtPriceX96After', type: 'uint160' },\n { name: 'initializedTicksCrossed', type: 'uint32' },\n { name: 'gasEstimate', type: 'uint256' },\n ],\n },\n {\n type: 'function',\n name: 'quoteExactOutputSingle',\n stateMutability: 'nonpayable',\n inputs: [\n {\n name: 'params',\n type: 'tuple',\n components: [\n { name: 'tokenIn', type: 'address' },\n { name: 'tokenOut', type: 'address' },\n { name: 'amount', type: 'uint256' },\n { name: 'fee', type: 'uint24' },\n { name: 'sqrtPriceLimitX96', type: 'uint160' },\n ],\n },\n ],\n outputs: [\n { name: 'amountIn', type: 'uint256' },\n { name: 'sqrtPriceX96After', type: 'uint160' },\n { name: 'initializedTicksCrossed', type: 'uint32' },\n { name: 'gasEstimate', type: 'uint256' },\n ],\n },\n] as const\n","/**\n * Quote exact-in and exact-out single-hop swaps against a Uniswap v3 pool via\n * QuoterV2.\n * @module uniswap/v3/router/quote\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { BaseError, ContractFunctionRevertedError } from 'viem'\n\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport { quoterV2Abi } from '../abis/quoterV2'\nimport { type UniswapV3Addresses, getUniswapV3Addresses } from '../addresses'\n\nconst BPS_DENOMINATOR = 10_000n\nconst UINT128_MAX = (1n << 128n) - 1n\n\nexport interface QuoteV3ExactInParams {\n client: PublicClient\n chainId: bigint\n tokenIn: Address\n tokenOut: Address\n fee: bigint\n amountIn: bigint\n slippageBps: bigint\n blockNumber?: bigint\n addresses?: Partial<UniswapV3Addresses>\n}\n\nexport interface V3ExactInQuote {\n amountOut: bigint\n amountOutMinimum: bigint\n gasEstimate: bigint\n}\n\n/**\n * Quote an exact-in v3 swap. Returns `null` when the quote reverts (e.g. the\n * pool does not exist / has no liquidity) so callers can skip that pool when\n * ranking venues, rather than aborting the whole cycle.\n */\nexport async function quoteV3ExactIn(params: QuoteV3ExactInParams): Promise<V3ExactInQuote | null> {\n const { client, chainId, tokenIn, tokenOut, fee, amountIn, slippageBps, blockNumber } = params\n if (amountIn < 0n || amountIn > UINT128_MAX) {\n throw new PanopticError(`amountIn ${amountIn} exceeds uint128 maximum`)\n }\n assertSlippageBps(slippageBps)\n\n const { quoterV2 } = getUniswapV3Addresses(chainId, params.addresses)\n\n try {\n const { result } = await client.simulateContract({\n address: quoterV2,\n abi: quoterV2Abi,\n functionName: 'quoteExactInputSingle',\n blockNumber,\n args: [{ tokenIn, tokenOut, amountIn, fee: Number(fee), sqrtPriceLimitX96: 0n }],\n })\n const [amountOut, , , gasEstimate] = result\n const amountOutMinimum = (amountOut * (BPS_DENOMINATOR - slippageBps)) / BPS_DENOMINATOR\n return { amountOut, amountOutMinimum, gasEstimate }\n } catch (err) {\n if (isRevert(err)) return null\n throw err\n }\n}\n\nexport interface QuoteV3ExactOutParams {\n client: PublicClient\n chainId: bigint\n tokenIn: Address\n tokenOut: Address\n fee: bigint\n amountOut: bigint\n slippageBps: bigint\n blockNumber?: bigint\n addresses?: Partial<UniswapV3Addresses>\n}\n\nexport interface V3ExactOutQuote {\n amountIn: bigint\n amountInMaximum: bigint\n gasEstimate: bigint\n}\n\n/**\n * Quote an exact-out v3 swap. Returns `null` on revert (no pool / no liquidity).\n */\nexport async function quoteV3ExactOut(\n params: QuoteV3ExactOutParams,\n): Promise<V3ExactOutQuote | null> {\n const { client, chainId, tokenIn, tokenOut, fee, amountOut, slippageBps, blockNumber } = params\n if (amountOut < 0n || amountOut > UINT128_MAX) {\n throw new PanopticError(`amountOut ${amountOut} exceeds uint128 maximum`)\n }\n assertSlippageBps(slippageBps)\n\n const { quoterV2 } = getUniswapV3Addresses(chainId, params.addresses)\n\n try {\n const { result } = await client.simulateContract({\n address: quoterV2,\n abi: quoterV2Abi,\n functionName: 'quoteExactOutputSingle',\n blockNumber,\n args: [{ tokenIn, tokenOut, amount: amountOut, fee: Number(fee), sqrtPriceLimitX96: 0n }],\n })\n const [amountIn, , , gasEstimate] = result\n const amountInMaximum =\n (amountIn * (BPS_DENOMINATOR + slippageBps) + BPS_DENOMINATOR - 1n) / BPS_DENOMINATOR\n return { amountIn, amountInMaximum, gasEstimate }\n } catch (err) {\n if (isRevert(err)) return null\n throw err\n }\n}\n\nfunction assertSlippageBps(slippageBps: bigint): void {\n if (slippageBps < 0n || slippageBps > BPS_DENOMINATOR) {\n throw new PanopticError(`invalid slippageBps ${slippageBps}, must be 0..10000`)\n }\n}\n\nfunction isRevert(err: unknown): boolean {\n return (\n err instanceof BaseError &&\n err.walk((e) => e instanceof ContractFunctionRevertedError) instanceof\n ContractFunctionRevertedError\n )\n}\n","/**\n * Block metadata utilities for the Panoptic v2 SDK.\n * @module v2/clients/blockMeta\n */\n\nimport type { PublicClient } from 'viem'\n\nimport type { BlockMeta } from '../types'\n\n/**\n * Parameters for getBlockMeta.\n */\nexport interface GetBlockMetaParams {\n /** viem PublicClient */\n client: Pick<PublicClient, 'getBlock'>\n /** Optional block number (defaults to latest) */\n blockNumber?: bigint\n}\n\n/**\n * Get block metadata for a given block.\n * Used to tag all read results with same-block consistency proof.\n *\n * @param params - The parameters\n * @returns Block metadata\n */\nexport async function getBlockMeta(params: GetBlockMetaParams): Promise<BlockMeta> {\n const { client, blockNumber } = params\n\n const block = await client.getBlock({\n blockNumber,\n includeTransactions: false,\n })\n\n return {\n blockNumber: block.number,\n blockHash: block.hash,\n blockTimestamp: block.timestamp,\n }\n}\n","/**\n * Minimal Uniswap V4 StateView ABI for fee growth reads.\n * Only includes functions needed by streamia history.\n */\nexport const stateViewAbi = [\n {\n inputs: [{ internalType: 'PoolId', name: 'poolId', type: 'bytes32' }],\n name: 'getSlot0',\n outputs: [\n { internalType: 'uint160', name: 'sqrtPriceX96', type: 'uint160' },\n { internalType: 'int24', name: 'tick', type: 'int24' },\n { internalType: 'uint24', name: 'protocolFee', type: 'uint24' },\n { internalType: 'uint24', name: 'lpFee', type: 'uint24' },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [{ internalType: 'PoolId', name: 'poolId', type: 'bytes32' }],\n name: 'getFeeGrowthGlobals',\n outputs: [\n { internalType: 'uint256', name: 'feeGrowthGlobal0', type: 'uint256' },\n { internalType: 'uint256', name: 'feeGrowthGlobal1', type: 'uint256' },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n { internalType: 'PoolId', name: 'poolId', type: 'bytes32' },\n { internalType: 'int24', name: 'tick', type: 'int24' },\n ],\n name: 'getTickInfo',\n outputs: [\n { internalType: 'uint128', name: 'liquidityGross', type: 'uint128' },\n { internalType: 'int128', name: 'liquidityNet', type: 'int128' },\n { internalType: 'uint256', name: 'feeGrowthOutside0X128', type: 'uint256' },\n { internalType: 'uint256', name: 'feeGrowthOutside1X128', type: 'uint256' },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [{ internalType: 'PoolId', name: 'poolId', type: 'bytes32' }],\n name: 'getLiquidity',\n outputs: [{ internalType: 'uint128', name: 'liquidity', type: 'uint128' }],\n stateMutability: 'view',\n type: 'function',\n },\n] as const\n","/**\n * Minimal Uniswap V3 Pool ABI for fee growth reads.\n * Only includes functions needed by streamia history.\n */\nexport const uniswapV3PoolAbi = [\n {\n inputs: [],\n name: 'slot0',\n outputs: [\n { internalType: 'uint160', name: 'sqrtPriceX96', type: 'uint160' },\n { internalType: 'int24', name: 'tick', type: 'int24' },\n { internalType: 'uint16', name: 'observationIndex', type: 'uint16' },\n { internalType: 'uint16', name: 'observationCardinality', type: 'uint16' },\n { internalType: 'uint16', name: 'observationCardinalityNext', type: 'uint16' },\n { internalType: 'uint8', name: 'feeProtocol', type: 'uint8' },\n { internalType: 'bool', name: 'unlocked', type: 'bool' },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'feeGrowthGlobal0X128',\n outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'feeGrowthGlobal1X128',\n outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [{ internalType: 'int24', name: '', type: 'int24' }],\n name: 'ticks',\n outputs: [\n { internalType: 'uint128', name: 'liquidityGross', type: 'uint128' },\n { internalType: 'int128', name: 'liquidityNet', type: 'int128' },\n { internalType: 'uint256', name: 'feeGrowthOutside0X128', type: 'uint256' },\n { internalType: 'uint256', name: 'feeGrowthOutside1X128', type: 'uint256' },\n { internalType: 'int56', name: 'tickCumulativeOutside', type: 'int56' },\n { internalType: 'uint160', name: 'secondsPerLiquidityOutsideX128', type: 'uint160' },\n { internalType: 'uint32', name: 'secondsOutside', type: 'uint32' },\n { internalType: 'bool', name: 'initialized', type: 'bool' },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'liquidity',\n outputs: [{ internalType: 'uint128', name: '', type: 'uint128' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'fee',\n outputs: [{ internalType: 'uint24', name: '', type: 'uint24' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'token0',\n outputs: [{ internalType: 'address', name: '', type: 'address' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'token1',\n outputs: [{ internalType: 'address', name: '', type: 'address' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'tickSpacing',\n outputs: [{ internalType: 'int24', name: '', type: 'int24' }],\n stateMutability: 'view',\n type: 'function',\n },\n] as const\n","import { ORACLE_EPOCH_SECONDS } from './constants'\n\nconst ORACLE_EPOCH_SHIFT = 232n\nconst ORACLE_EPOCH_MASK = (1n << 24n) - 1n\nconst ORACLE_TICK_MASK = (1n << 22n) - 1n\n\nfunction decodeSigned22(value: bigint): bigint {\n const signBit = 1n << 21n\n const truncated = value & ORACLE_TICK_MASK\n return (truncated & signBit) === 0n ? truncated : truncated - (1n << 22n)\n}\n\n/** Timing decoded from an OraclePack and resolved against a specific block. */\nexport interface OracleTiming {\n /** Modulo-2^24 oracle epoch stored on-chain. */\n epoch: bigint\n /** Absolute epoch-boundary timestamp reconstructed at or before the supplied block. */\n timestamp: bigint\n}\n\n/** Fixed-width oracle state decoded from an OraclePack. */\nexport interface DecodedOraclePack {\n referenceTick: bigint\n lockMode: bigint\n spotEMA: bigint\n fastEMA: bigint\n slowEMA: bigint\n eonsEMA: bigint\n epoch: bigint\n timestamp: bigint\n}\n\n/**\n * Decode the 24-bit epoch stored at bits 232..255 of OraclePack.\n *\n * The packed timestamp is modulo 2^30 seconds and only identifies an absolute\n * Unix timestamp within the wrap window containing `blockTimestamp`. Supplying\n * the relevant block timestamp resolves it to the latest matching epoch at or\n * before that block, including across the epoch counter wraparound.\n */\nexport function decodeOracleTiming(oraclePack: bigint, blockTimestamp: bigint): OracleTiming {\n const epoch = (oraclePack >> ORACLE_EPOCH_SHIFT) & ORACLE_EPOCH_MASK\n const currentEpoch = oracleEpochAt(blockTimestamp)\n const elapsedEpochs = (currentEpoch - epoch) & ORACLE_EPOCH_MASK\n const currentEpochTimestamp = blockTimestamp - (blockTimestamp % ORACLE_EPOCH_SECONDS)\n return { epoch, timestamp: currentEpochTimestamp - elapsedEpochs * ORACLE_EPOCH_SECONDS }\n}\n\n/** Decode the fixed-width ticks and guardian state stored in OraclePack. */\nexport function decodeOraclePack(oraclePack: bigint, blockTimestamp: bigint): DecodedOraclePack {\n const timing = decodeOracleTiming(oraclePack, blockTimestamp)\n return {\n referenceTick: decodeSigned22(oraclePack >> 96n),\n lockMode: (oraclePack >> 118n) & 3n,\n spotEMA: decodeSigned22(oraclePack >> 120n),\n fastEMA: decodeSigned22(oraclePack >> 142n),\n slowEMA: decodeSigned22(oraclePack >> 164n),\n eonsEMA: decodeSigned22(oraclePack >> 186n),\n ...timing,\n }\n}\n\n/** Return the contract's modulo-2^24 64-second epoch for a block timestamp. */\nexport function oracleEpochAt(timestamp: bigint): bigint {\n return (timestamp / ORACLE_EPOCH_SECONDS) & ORACLE_EPOCH_MASK\n}\n","import { PanopticValidationError } from '../errors'\nimport type { OracleState } from '../types'\nimport { ORACLE_EPOCH_SECONDS } from './constants'\n\nconst UINT24_MASK = (1n << 24n) - 1n\n\nexport interface OracleEmaPeriods {\n spot: bigint\n fast: bigint\n slow: bigint\n eons: bigint\n}\n\nexport interface OracleRiskParameters {\n emaPeriods: OracleEmaPeriods\n maxTicksDelta: bigint\n /** Informational observation clamp; not used by SafeMode diagnosis. May be zero. */\n maxClampDelta: bigint\n}\n\nexport type OracleSafeModeCause =\n | 'externalShock'\n | 'internalDisagreement'\n | 'highDivergence'\n | 'guardianLock'\n | 'unknown'\n\nexport interface OracleSafeModeDiagnosis {\n /** Authoritative value returned by PanopticPool.isSafeMode(). */\n level: bigint\n /** Value reproduced using the known RiskEngine formula and live constants. */\n reproducedLevel: bigint\n matchesOnchain: boolean\n causes: readonly OracleSafeModeCause[]\n externalShockDelta: bigint\n internalDisagreementDelta: bigint\n highDivergenceDelta: bigint\n guardianLocked: boolean\n /** Minimum whole 64-second oracle epochs to wait after the last observation. */\n minimumPokeEpochs: bigint\n shouldPoke: boolean\n}\n\ntype DiagnosticOracleState = Pick<\n OracleState,\n 'currentTick' | 'spotEMA' | 'fastEMA' | 'slowEMA' | 'medianTick' | 'lockMode'\n>\n\nfunction absoluteDelta(left: bigint, right: bigint): bigint {\n return left >= right ? left - right : right - left\n}\n\nfunction epochsForPeriod(period: bigint): bigint {\n return (period + ORACLE_EPOCH_SECONDS - 1n) / ORACLE_EPOCH_SECONDS\n}\n\n/** Decode the four uint24 periods packed by RiskEngine.EMA_PERIODS(). */\nexport function decodeOracleRiskParameters(\n emaPeriods: bigint,\n maxTicksDelta: bigint,\n maxClampDelta: bigint,\n): OracleRiskParameters {\n const decodedPeriods = {\n spot: emaPeriods & UINT24_MASK,\n fast: (emaPeriods >> 24n) & UINT24_MASK,\n slow: (emaPeriods >> 48n) & UINT24_MASK,\n eons: (emaPeriods >> 72n) & UINT24_MASK,\n }\n if (\n decodedPeriods.spot === 0n ||\n decodedPeriods.fast === 0n ||\n decodedPeriods.slow === 0n ||\n decodedPeriods.eons === 0n ||\n maxTicksDelta <= 0n ||\n maxClampDelta < 0n\n ) {\n throw new PanopticValidationError(\n `RiskEngine returned invalid oracle parameters: EMA_PERIODS=${emaPeriods}, ` +\n `MAX_TICKS_DELTA=${maxTicksDelta}, MAX_CLAMP_DELTA=${maxClampDelta}`,\n )\n }\n return { emaPeriods: decodedPeriods, maxTicksDelta, maxClampDelta }\n}\n\n/** Explain the on-chain SafeMode level using this deployment's RiskEngine constants. */\nexport function diagnoseOracleSafeMode(\n state: DiagnosticOracleState,\n parameters: OracleRiskParameters,\n onchainLevel: bigint,\n): OracleSafeModeDiagnosis {\n const externalShockDelta = absoluteDelta(state.currentTick, state.spotEMA)\n const internalDisagreementDelta = absoluteDelta(state.spotEMA, state.fastEMA)\n const highDivergenceDelta = absoluteDelta(state.medianTick, state.slowEMA)\n const internalThreshold = parameters.maxTicksDelta / 2n\n const externalShock = externalShockDelta > parameters.maxTicksDelta\n const internalDisagreement = internalDisagreementDelta > internalThreshold\n const highDivergence = highDivergenceDelta > internalThreshold\n const guardianLocked = state.lockMode !== 0n\n\n const algorithmicLevel =\n (externalShock ? 1n : 0n) + (internalDisagreement ? 1n : 0n) + (highDivergence ? 1n : 0n)\n const reproducedLevel = algorithmicLevel + state.lockMode\n const matchesOnchain = reproducedLevel === onchainLevel\n const causes: OracleSafeModeCause[] = []\n if (matchesOnchain) {\n if (externalShock) causes.push('externalShock')\n if (internalDisagreement) causes.push('internalDisagreement')\n if (highDivergence) causes.push('highDivergence')\n } else {\n causes.push('unknown')\n }\n if (guardianLocked) causes.push('guardianLock')\n\n const candidateEpochs: bigint[] = []\n if (!matchesOnchain) candidateEpochs.push(1n)\n if (highDivergence) candidateEpochs.push(1n)\n if (externalShock) candidateEpochs.push(epochsForPeriod(parameters.emaPeriods.spot))\n if (internalDisagreement) candidateEpochs.push(epochsForPeriod(parameters.emaPeriods.fast))\n const minimumPokeEpochs = candidateEpochs.reduce(\n (minimum, epochs) => (minimum === 0n || epochs < minimum ? epochs : minimum),\n 0n,\n )\n\n return {\n level: onchainLevel,\n reproducedLevel,\n matchesOnchain,\n causes,\n externalShockDelta,\n internalDisagreementDelta,\n highDivergenceDelta,\n guardianLocked,\n minimumPokeEpochs,\n shouldPoke: onchainLevel > 0n && !guardianLocked,\n }\n}\n","/**\n * Pool read functions for the Panoptic v2 SDK.\n *\n * ## Same-Block Guarantee\n *\n * All dynamic data is fetched in a SINGLE multicall to ensure block consistency.\n * Per PLAN.md §6, immutable \"static prefetch\" data (addresses, decimals, symbols)\n * can be fetched separately and cached - it's not subject to same-block consistency.\n *\n * Functions accept an optional `poolMetadata` parameter containing pre-fetched\n * immutable addresses. If not provided, it will be fetched first (static prefetch).\n * Then ONE multicall fetches all dynamic data at the target block.\n *\n * @module v2/reads/pool\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { decodeAbiParameters, keccak256, zeroAddress } from 'viem'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi, riskEngineAbi } from '../../../generated'\nimport { stateViewAbi } from '../abis/stateView'\nimport { uniswapV3PoolAbi } from '../abis/uniswapV3Pool'\nimport { getBlockMeta } from '../clients/blockMeta'\nimport { tickToSqrtPriceX96 } from '../formatters/tick'\nimport type {\n BlockMeta,\n CollateralTracker,\n OracleState,\n Pool,\n PoolKey,\n RiskEngine,\n RiskParameters,\n Utilization,\n} from '../types'\nimport { decodeOraclePack } from '../utils/oraclePack'\nimport { type OracleRiskParameters, decodeOracleRiskParameters } from '../utils/oracleSafeMode'\nimport { DEFAULT_MINT_BUFFER } from './mintBuffer'\n\n// ERC20 minimal ABI for token metadata\nconst erc20Abi = [\n {\n type: 'function',\n name: 'symbol',\n inputs: [],\n outputs: [{ type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'decimals',\n inputs: [],\n outputs: [{ type: 'uint8' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'name',\n inputs: [],\n outputs: [{ type: 'string' }],\n stateMutability: 'view',\n },\n] as const\n\n/**\n * Immutable pool metadata that can be cached.\n * These values never change for a given pool, so they're exempt from\n * same-block consistency requirements (per PLAN.md \"Static Prefetches\" exception).\n */\nexport interface PoolMetadata {\n /** Pool key bytes */\n poolKeyBytes: `0x${string}`\n /** Pool ID */\n poolId: bigint\n /** Collateral tracker 0 address */\n collateralToken0Address: Address\n /** Collateral tracker 1 address */\n collateralToken1Address: Address\n /** Risk engine address */\n riskEngineAddress: Address\n /** Token 0 underlying asset address */\n token0Asset: Address\n /** Token 1 underlying asset address */\n token1Asset: Address\n /** Token 0 symbol */\n token0Symbol: string\n /** Token 1 symbol */\n token1Symbol: string\n /** Token 0 decimals */\n token0Decimals: bigint\n /** Token 1 decimals */\n token1Decimals: bigint\n /** Token 0 name */\n token0Name: string\n /** Token 1 name */\n token1Name: string\n /** Underlying pool ID (V3: pool address, V4: keccak256(poolKeyBytes)) */\n underlyingPoolId: string\n /** Whether this is a V4 pool (poolManager is non-zero) */\n isV4: boolean\n /** Tick spacing */\n tickSpacing: bigint\n /** Fee tier (V4: from poolKey, V3: from Uniswap pool fee()) */\n fee: bigint\n /** SemiFungiblePositionManager address */\n sfpmAddress: Address\n}\n\n/**\n * Parameters for getPoolMetadata.\n */\nexport interface GetPoolMetadataParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n}\n\n/**\n * Fetch immutable pool metadata (addresses, symbols, decimals).\n * This data never changes for a given pool and can be cached indefinitely.\n *\n * This is the \"static prefetch\" per PLAN.md §6 - exempt from same-block consistency.\n *\n * @param params - The parameters\n * @returns Immutable pool metadata\n */\nexport async function getPoolMetadata(params: GetPoolMetadataParams): Promise<PoolMetadata> {\n const { client, poolAddress } = params\n\n // First call: get basic immutable pool data\n const basicResults = await client.multicall({\n contracts: [\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'poolKey',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'poolId',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'collateralToken0',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'collateralToken1',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'riskEngine',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'poolManager',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'SFPM',\n },\n ],\n allowFailure: false,\n })\n\n const [\n poolKeyBytes,\n poolId,\n collateralToken0Address,\n collateralToken1Address,\n riskEngineAddress,\n poolManager,\n sfpmAddress,\n ] = basicResults\n\n // Second call: get underlying asset addresses from collateral trackers\n const assetResults = await client.multicall({\n contracts: [\n {\n address: collateralToken0Address,\n abi: collateralTrackerV2Abi,\n functionName: 'asset',\n },\n {\n address: collateralToken1Address,\n abi: collateralTrackerV2Abi,\n functionName: 'asset',\n },\n ],\n allowFailure: false,\n })\n\n const [token0Asset, token1Asset] = assetResults\n\n // Native ETH (address zero) has no ERC20 contract — use hardcoded metadata\n const NATIVE_ETH_ADDRESS = '0x0000000000000000000000000000000000000000'\n const isToken0Native = token0Asset.toLowerCase() === NATIVE_ETH_ADDRESS\n const isToken1Native = token1Asset.toLowerCase() === NATIVE_ETH_ADDRESS\n\n // Third call: get token metadata (symbols, decimals, names) — skip native ETH tokens\n const erc20Contracts = [\n ...(isToken0Native\n ? []\n : [\n { address: token0Asset, abi: erc20Abi, functionName: 'symbol' as const },\n { address: token0Asset, abi: erc20Abi, functionName: 'decimals' as const },\n { address: token0Asset, abi: erc20Abi, functionName: 'name' as const },\n ]),\n ...(isToken1Native\n ? []\n : [\n { address: token1Asset, abi: erc20Abi, functionName: 'symbol' as const },\n { address: token1Asset, abi: erc20Abi, functionName: 'decimals' as const },\n { address: token1Asset, abi: erc20Abi, functionName: 'name' as const },\n ]),\n ]\n\n const erc20Results =\n erc20Contracts.length > 0\n ? await client.multicall({ contracts: erc20Contracts, allowFailure: false })\n : []\n\n // Reconstruct metadata, inserting native ETH defaults where needed\n let resultIdx = 0\n const token0Symbol = isToken0Native ? 'ETH' : (erc20Results[resultIdx++] as string)\n const token0Decimals = isToken0Native ? 18 : (erc20Results[resultIdx++] as number)\n const token0Name = isToken0Native ? 'Ether' : (erc20Results[resultIdx++] as string)\n const token1Symbol = isToken1Native ? 'ETH' : (erc20Results[resultIdx++] as string)\n const token1Decimals = isToken1Native ? 18 : (erc20Results[resultIdx++] as number)\n const token1Name = isToken1Native ? 'Ether' : (erc20Results[resultIdx++] as string)\n\n // Derive underlyingPoolId, tickSpacing, and fee\n const isV4 = poolManager !== zeroAddress\n const parsedPoolKey = parsePoolKey(poolKeyBytes)\n let underlyingPoolId: string\n let fee: bigint\n let tickSpacing: bigint\n\n if (isV4) {\n underlyingPoolId = keccak256(poolKeyBytes)\n fee = parsedPoolKey.fee\n tickSpacing = tickSpacingFromPoolId(poolId)\n } else {\n const v3PoolAddress = decodeAbiParameters([{ type: 'address' }], poolKeyBytes)[0]\n underlyingPoolId = v3PoolAddress\n const [v3Fee, v3TickSpacing] = await client.multicall({\n contracts: [\n { address: v3PoolAddress, abi: uniswapV3PoolAbi, functionName: 'fee' },\n { address: v3PoolAddress, abi: uniswapV3PoolAbi, functionName: 'tickSpacing' },\n ],\n allowFailure: false,\n })\n fee = BigInt(v3Fee)\n tickSpacing = BigInt(v3TickSpacing)\n }\n\n return {\n poolKeyBytes,\n poolId,\n collateralToken0Address,\n collateralToken1Address,\n isV4,\n riskEngineAddress,\n token0Asset,\n token1Asset,\n token0Symbol,\n token1Symbol,\n token0Decimals: BigInt(token0Decimals),\n token1Decimals: BigInt(token1Decimals),\n token0Name,\n token1Name,\n underlyingPoolId,\n tickSpacing,\n fee,\n sfpmAddress,\n }\n}\n\n/**\n * Parameters for getPool.\n */\nexport interface GetPoolParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Chain ID */\n chainId: bigint\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched pool metadata (for caching/optimization) */\n poolMetadata?: PoolMetadata\n /** Optional StateView address for V4 pools (needed to read Uniswap pool liquidity) */\n stateViewAddress?: Address\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get full pool data including both collateral trackers and oracle state.\n *\n * ## Same-Block Guarantee\n * All dynamic data is fetched in ONE multicall at the target block.\n * Static metadata (addresses, symbols, decimals) is either provided via\n * poolMetadata or fetched separately (static prefetch exception).\n *\n * @param params - The parameters\n * @returns Pool data with block metadata\n */\nexport async function getPool(params: GetPoolParams): Promise<Pool> {\n const { client, poolAddress, chainId, blockNumber, poolMetadata } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Get static metadata (either from cache or fetch it)\n const metadata = poolMetadata ?? (await getPoolMetadata({ client, poolAddress }))\n\n // Build Uniswap pool liquidity read (V3 vs V4)\n const liquidityContract =\n metadata.isV4 && params.stateViewAddress\n ? {\n address: params.stateViewAddress,\n abi: stateViewAbi,\n functionName: 'getLiquidity' as const,\n args: [metadata.underlyingPoolId as `0x${string}`] as const,\n }\n : !metadata.isV4\n ? {\n address: metadata.underlyingPoolId as Address,\n abi: uniswapV3PoolAbi,\n functionName: 'liquidity' as const,\n }\n : null // V4 without stateViewAddress — skip\n\n // SINGLE multicall for ALL dynamic data - ensures same-block consistency\n const [dynamicResults, _meta] = await Promise.all([\n client.multicall({\n contracts: [\n // Pool dynamic state\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'isSafeMode',\n },\n // Token 0 collateral tracker dynamic data\n {\n address: metadata.collateralToken0Address,\n abi: collateralTrackerV2Abi,\n functionName: 'getPoolData',\n },\n {\n address: metadata.collateralToken0Address,\n abi: collateralTrackerV2Abi,\n functionName: 'totalSupply',\n },\n {\n address: metadata.collateralToken0Address,\n abi: collateralTrackerV2Abi,\n functionName: 'interestRate',\n },\n // Token 1 collateral tracker dynamic data\n {\n address: metadata.collateralToken1Address,\n abi: collateralTrackerV2Abi,\n functionName: 'getPoolData',\n },\n {\n address: metadata.collateralToken1Address,\n abi: collateralTrackerV2Abi,\n functionName: 'totalSupply',\n },\n {\n address: metadata.collateralToken1Address,\n abi: collateralTrackerV2Abi,\n functionName: 'interestRate',\n },\n // Risk engine parameters (technically immutable but included for completeness)\n {\n address: metadata.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'SELLER_COLLATERAL_RATIO',\n },\n {\n address: metadata.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'MAINT_MARGIN_RATE',\n },\n {\n address: metadata.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'NOTIONAL_FEE',\n },\n {\n address: metadata.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'PREMIUM_FEE',\n },\n {\n address: metadata.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'VEGOID',\n },\n {\n address: metadata.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'MAX_SPREAD',\n },\n // Uniswap pool in-range liquidity (V3 or V4 via StateView)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ...(liquidityContract ? [liquidityContract as any] : []),\n ],\n blockNumber: targetBlockNumber,\n allowFailure: true,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // Extract results — first 14 are core (must succeed), last is liquidity (may fail)\n const coreResults = dynamicResults.slice(0, 14)\n if (coreResults.some((r) => r.status !== 'success')) {\n const failed = coreResults.find((r) => r.status !== 'success')\n throw new Error(`Core pool read failed: ${JSON.stringify(failed)}`)\n }\n const [\n currentTick,\n safeModeRaw,\n token0PoolData,\n token0TotalSupply,\n token0InterestRate,\n token1PoolData,\n token1TotalSupply,\n token1InterestRate,\n sellerCollateralRatio,\n maintMarginRate,\n notionalFee,\n premiumFee,\n vegoid,\n maxSpread,\n ] = coreResults.map((r) => r.result) as [\n bigint, // currentTick\n number, // safeModeRaw\n readonly [bigint, bigint, bigint, bigint], // token0PoolData (getPoolData)\n bigint, // token0TotalSupply\n bigint, // token0InterestRate\n readonly [bigint, bigint, bigint, bigint], // token1PoolData (getPoolData)\n bigint, // token1TotalSupply\n bigint, // token1InterestRate\n bigint, // sellerCollateralRatio\n bigint, // maintMarginRate\n bigint, // notionalFee\n bigint, // premiumFee\n bigint, // vegoid\n bigint, // maxSpread\n ]\n const liquidityResult = dynamicResults[14]\n const uniswapPoolLiquidity =\n liquidityResult?.status === 'success' ? BigInt(liquidityResult.result as bigint) : 0n\n\n // V3 poolKey() only contains the Uniswap pool address, so enrich the parsed\n // key with the immutable fee and tick spacing resolved by getPoolMetadata.\n const tickSpacing = metadata.tickSpacing\n const poolKey = {\n ...parsePoolKey(metadata.poolKeyBytes),\n fee: metadata.fee,\n tickSpacing,\n }\n\n // Annualize rates: interestRate() returns WAD/s, multiply by seconds/year\n const SECONDS_PER_YEAR = 31_536_000n\n const borrowRate0 = BigInt(token0InterestRate) * SECONDS_PER_YEAR\n const borrowRate1 = BigInt(token1InterestRate) * SECONDS_PER_YEAR\n const utilization0 = token0PoolData[3]\n const utilization1 = token1PoolData[3]\n // Supply rate = borrow rate * utilization (utilization is in bps, so /10000)\n const supplyRate0 = (borrowRate0 * utilization0) / 10000n\n const supplyRate1 = (borrowRate1 * utilization1) / 10000n\n const totalAssets0 = token0PoolData[0] + token0PoolData[1]\n const totalAssets1 = token1PoolData[0] + token1PoolData[1]\n\n // Build collateral trackers\n const collateralTracker0: CollateralTracker = {\n address: metadata.collateralToken0Address,\n token: metadata.token0Asset,\n symbol: metadata.token0Symbol,\n decimals: metadata.token0Decimals,\n totalAssets: totalAssets0,\n insideAMM: token0PoolData[1],\n creditedShares: token0PoolData[2],\n totalShares: token0TotalSupply,\n utilization: utilization0,\n borrowRate: borrowRate0,\n supplyRate: supplyRate0,\n }\n\n const collateralTracker1: CollateralTracker = {\n address: metadata.collateralToken1Address,\n token: metadata.token1Asset,\n symbol: metadata.token1Symbol,\n decimals: metadata.token1Decimals,\n totalAssets: totalAssets1,\n insideAMM: token1PoolData[1],\n creditedShares: token1PoolData[2],\n totalShares: token1TotalSupply,\n utilization: utilization1,\n borrowRate: borrowRate1,\n supplyRate: supplyRate1,\n }\n\n // Build risk engine\n const riskEngine: RiskEngine = {\n address: metadata.riskEngineAddress,\n collateralRequirement: sellerCollateralRatio,\n maintenanceMargin: maintMarginRate,\n commissionRate: BigInt(notionalFee),\n premiumFeeRate: BigInt(premiumFee),\n vegoid: BigInt(vegoid),\n maxSpread: BigInt(maxSpread),\n }\n\n // Determine health status based on safe mode\n const healthStatus = safeModeRaw === 0 ? 'active' : safeModeRaw === 1 ? 'low_liquidity' : 'paused'\n\n // sqrtPriceX96 from tick\n const sqrtPriceX96 = tickToSqrtPriceX96(BigInt(currentTick))\n\n return {\n address: poolAddress,\n chainId,\n poolId: metadata.poolId,\n poolKey,\n tickSpacing,\n collateralTracker0,\n collateralTracker1,\n riskEngine,\n currentTick: BigInt(currentTick),\n sqrtPriceX96,\n uniswapPoolLiquidity,\n healthStatus,\n metadata,\n _meta,\n }\n}\n\n/**\n * Parameters for getUtilization.\n */\nexport interface GetUtilizationParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched collateral tracker addresses (for caching/optimization) */\n collateralAddresses?: {\n collateralToken0: Address\n collateralToken1: Address\n }\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get current pool utilization for both tokens.\n *\n * ## Same-Block Guarantee\n * All dynamic data is fetched in ONE multicall at the target block.\n * Collateral tracker addresses are either provided or fetched separately (static prefetch).\n *\n * @param params - The parameters\n * @returns Utilization data with block metadata\n */\nexport async function getUtilization(params: GetUtilizationParams): Promise<Utilization> {\n const { client, poolAddress, blockNumber, collateralAddresses } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Get collateral tracker addresses (static prefetch if not provided)\n let collateralToken0: Address\n let collateralToken1: Address\n\n if (collateralAddresses) {\n collateralToken0 = collateralAddresses.collateralToken0\n collateralToken1 = collateralAddresses.collateralToken1\n } else {\n // Static prefetch - addresses are immutable\n const addressResults = 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 collateralToken0 = addressResults[0]\n collateralToken1 = addressResults[1]\n }\n\n // SINGLE multicall for ALL dynamic data - ensures same-block consistency\n const [poolDataResults, _meta] = await Promise.all([\n client.multicall({\n contracts: [\n {\n address: collateralToken0,\n abi: collateralTrackerV2Abi,\n functionName: 'getPoolData',\n },\n {\n address: collateralToken1,\n abi: collateralTrackerV2Abi,\n functionName: 'getPoolData',\n },\n {\n address: collateralToken0,\n abi: collateralTrackerV2Abi,\n functionName: 'totalSupply',\n },\n {\n address: collateralToken1,\n abi: collateralTrackerV2Abi,\n functionName: 'totalSupply',\n },\n ],\n blockNumber: targetBlockNumber,\n allowFailure: false,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const [poolData0, poolData1, totalSupply0, totalSupply1] = poolDataResults\n\n return {\n utilization0: poolData0[3], // currentPoolUtilization\n utilization1: poolData1[3],\n availableToBorrow0: availableToBorrow(poolData0, totalSupply0),\n availableToBorrow1: availableToBorrow(poolData1, totalSupply1),\n _meta,\n }\n}\n\n/**\n * Assets available to borrow from a collateral tracker.\n *\n * Mirrors `CollateralTracker._maxWithdrawWithPositions`: deposited assets less\n * one wei, less the assets backing credited shares.\n *\n * @param poolData - `getPoolData()` tuple: [depositedAssets, insideAMM, creditedShares, utilization]\n * @param totalSupply - Collateral tracker share supply, for the share→asset conversion\n */\nexport function availableToBorrow(\n poolData: readonly [bigint, bigint, bigint, bigint],\n totalSupply: bigint,\n): bigint {\n const [depositedAssets, insideAMM, creditedShares] = poolData\n const available = depositedAssets > 0n ? depositedAssets - 1n : 0n\n if (creditedShares === 0n || totalSupply === 0n) return available\n\n const totalAssets = depositedAssets + insideAMM\n const creditedAssets = (creditedShares * totalAssets) / totalSupply\n return available > creditedAssets ? available - creditedAssets : 0n\n}\n\n/**\n * Parameters for getOracleState.\n */\nexport interface GetOracleStateParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get current oracle state from the pool.\n *\n * ## Same-Block Guarantee\n * Single contract call + block meta fetch at the same block.\n *\n * @param params - The parameters\n * @returns Oracle state with block metadata\n */\nexport async function getOracleState(params: GetOracleStateParams): Promise<OracleState> {\n const { client, poolAddress, blockNumber } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Read the detailed oracle state and the canonical TWAP used by downstream\n // safety checks at the same block.\n const [[oracleTicks, twapTick], _meta] = await Promise.all([\n client.multicall({\n contracts: [\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getOracleTicks',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getTWAP',\n },\n ],\n allowFailure: false,\n blockNumber: targetBlockNumber,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n // oracleTicks returns: currentTick, spotTick, medianTick, latestTick, oraclePack\n const [currentTick, spotTick, medianTick, latestTick, oraclePack] = oracleTicks\n\n const decoded = decodeOraclePack(oraclePack, _meta.blockTimestamp)\n\n return {\n epoch: decoded.epoch,\n lastUpdateTimestamp: decoded.timestamp,\n // Deprecated OracleState alias; use currentTick or oracleReferenceTick.\n referenceTick: BigInt(currentTick),\n currentTick: BigInt(currentTick),\n oracleReferenceTick: decoded.referenceTick,\n latestTick: BigInt(latestTick),\n twapTick: BigInt(twapTick),\n spotEMA: BigInt(spotTick),\n fastEMA: decoded.fastEMA,\n slowEMA: decoded.slowEMA,\n eonsEMA: decoded.eonsEMA,\n lockMode: decoded.lockMode,\n medianTick: BigInt(medianTick),\n _meta,\n }\n}\n\nexport interface GetOracleRiskParametersParams {\n client: PublicClient\n riskEngineAddress: Address\n blockNumber?: bigint\n}\n\nexport interface OracleRiskParametersState extends OracleRiskParameters {\n _meta: BlockMeta\n}\n\n/** Read the oracle constants from a specific deployed RiskEngine. */\nexport async function getOracleRiskParameters(\n params: GetOracleRiskParametersParams,\n): Promise<OracleRiskParametersState> {\n const targetBlockNumber = params.blockNumber ?? (await params.client.getBlockNumber())\n const [[emaPeriods, maxTicksDelta, maxClampDelta], _meta] = await Promise.all([\n params.client.multicall({\n contracts: [\n {\n address: params.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'EMA_PERIODS',\n },\n {\n address: params.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'MAX_TICKS_DELTA',\n },\n {\n address: params.riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'MAX_CLAMP_DELTA',\n },\n ],\n allowFailure: false,\n blockNumber: targetBlockNumber,\n }),\n getBlockMeta({ client: params.client, blockNumber: targetBlockNumber }),\n ])\n return {\n ...decodeOracleRiskParameters(BigInt(emaPeriods), BigInt(maxTicksDelta), BigInt(maxClampDelta)),\n _meta,\n }\n}\n\n/**\n * Parameters for getRiskParameters.\n */\nexport interface GetRiskParametersParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n /** Builder code (default: 0) */\n builderCode?: bigint\n /** Optional block number for historical queries */\n blockNumber?: bigint\n /** Optional pre-fetched risk engine address (for caching/optimization) */\n riskEngineAddress?: Address\n /** Optional pre-fetched block metadata (skips getBlockMeta RPC call) */\n _meta?: BlockMeta\n}\n\n/**\n * Get risk parameters from the pool.\n *\n * ## Same-Block Guarantee\n * All dynamic data is fetched in ONE multicall at the target block.\n * Risk engine address is either provided or fetched separately (static prefetch).\n *\n * @param params - The parameters\n * @returns Risk parameters with block metadata\n */\nexport async function getRiskParameters(params: GetRiskParametersParams): Promise<RiskParameters> {\n const {\n client,\n poolAddress,\n builderCode = 0n,\n blockNumber,\n riskEngineAddress: providedAddress,\n } = params\n\n const targetBlockNumber =\n blockNumber ?? params._meta?.blockNumber ?? (await client.getBlockNumber())\n\n // Get risk engine address (static prefetch if not provided)\n const riskEngineAddress =\n providedAddress ??\n (await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'riskEngine',\n }))\n\n // SINGLE multicall for ALL risk parameters - ensures same-block consistency\n const [riskEngineResults, _meta] = await Promise.all([\n client.multicall({\n contracts: [\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'SELLER_COLLATERAL_RATIO',\n },\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'BUYER_COLLATERAL_RATIO',\n },\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'MAINT_MARGIN_RATE',\n },\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'NOTIONAL_FEE',\n },\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'TARGET_POOL_UTIL',\n },\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'SATURATED_POOL_UTIL',\n },\n // The mint-time margin buffer, read live rather than compiled in, so a\n // redeployed RiskEngine cannot silently desync the displayed \"required\n // at mint\" from what the solvency check actually enforces.\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'BP_DECREASE_BUFFER',\n },\n {\n address: riskEngineAddress,\n abi: riskEngineAbi,\n functionName: 'DECIMALS',\n },\n {\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getRiskParameters',\n args: [builderCode],\n },\n ],\n blockNumber: targetBlockNumber,\n allowFailure: false,\n }),\n params._meta ?? getBlockMeta({ client, blockNumber: targetBlockNumber }),\n ])\n\n const [\n sellerCollateralRatio,\n buyerCollateralRatio,\n maintMarginRate,\n notionalFee,\n targetPoolUtil,\n saturatedPoolUtil,\n bpDecreaseBuffer,\n riskEngineDecimals,\n ,\n ] = riskEngineResults\n\n return {\n collateralRequirement: sellerCollateralRatio,\n maintenanceMargin: maintMarginRate,\n commissionRate: BigInt(notionalFee),\n targetUtilization: targetPoolUtil,\n saturatedUtilization: saturatedPoolUtil,\n itmSpreadMultiplier: buyerCollateralRatio, // Using buyer ratio as ITM multiplier\n // A live numerator is meaningful only with its live scale. If the scale is\n // invalid, fall back to the complete compiled-in ratio.\n mintBuffer:\n BigInt(riskEngineDecimals) > 0n\n ? { numerator: BigInt(bpDecreaseBuffer), denominator: BigInt(riskEngineDecimals) }\n : DEFAULT_MINT_BUFFER,\n _meta,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Builder code validation\n// ---------------------------------------------------------------------------\n\n/**\n * Validate whether a builder code maps to a deployed builder wallet.\n *\n * Calls `PanopticPool.getRiskParameters(builderCode)` — the contract reverts\n * with `InvalidBuilderCode` when the computed CREATE2 address has no bytecode.\n *\n * @returns `true` when valid, `false` when the contract reverts.\n */\nexport async function validateBuilderCode(params: {\n client: PublicClient\n poolAddress: Address\n builderCode: bigint\n}): Promise<boolean> {\n const { client, poolAddress, builderCode } = params\n if (builderCode === 0n) return true\n try {\n await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getRiskParameters',\n args: [builderCode],\n })\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Extract tickSpacing from the encoded 64-bit poolId.\n * Layout: poolAddress (5 bytes) + vegoid (1 byte) + tickSpacing (2 bytes).\n * tickSpacing occupies bits 48–63.\n */\nfunction tickSpacingFromPoolId(poolId: bigint): bigint {\n return (poolId >> 48n) & 0xffffn\n}\n\n/**\n * Parse pool key from ABI-encoded bytes.\n *\n * V4 pools: PoolKey struct is ABI-encoded as 5 consecutive 32-byte slots\n * (currency0, currency1, fee, tickSpacing, hooks).\n *\n * V3 pools: poolKey() returns abi.encode(uniswapV3PoolAddress) — a single\n * 32-byte slot. The struct fields are not available, so currency0/currency1\n * are zeroed and tickSpacing/fee are set to 0 (callers should use\n * getV3PoolTickSpacing and getV3PoolFee respectively).\n */\nfunction parsePoolKey(poolKeyBytes: `0x${string}`): PoolKey {\n const hex = poolKeyBytes.slice(2)\n\n // V3: single ABI-encoded address (64 hex chars = 32 bytes)\n if (hex.length <= 64) {\n return {\n currency0: zeroAddress,\n currency1: zeroAddress,\n fee: 0n,\n tickSpacing: 0n,\n hooks: zeroAddress,\n }\n }\n\n if (hex.length < 320) {\n throw new Error(`Malformed V4 pool key: expected 320 hex chars (160 bytes), got ${hex.length}`)\n }\n\n // Each slot is 64 hex chars (32 bytes)\n // Addresses are in the last 40 hex chars (20 bytes) of their slot\n // Numeric values can be parsed from the full 64 hex chars of their slot\n const currency0 = `0x${hex.slice(24, 64)}` as Address // Slot 0: chars 0-64, address at 24-64\n const currency1 = `0x${hex.slice(88, 128)}` as Address // Slot 1: chars 64-128, address at 88-128\n const fee = BigInt(`0x${hex.slice(128, 192)}`) // Slot 2: chars 128-192 (full slot)\n const tickSpacing = BigInt(`0x${hex.slice(192, 256)}`) // Slot 3: chars 192-256 (full slot)\n const hooks = `0x${hex.slice(280, 320)}` as Address // Slot 4: chars 256-320, address at 280-320\n\n return {\n currency0,\n currency1,\n fee,\n tickSpacing,\n hooks,\n }\n}\n\n/**\n * Parameters for fetchPoolId.\n */\nexport interface FetchPoolIdParams {\n /** viem PublicClient */\n client: PublicClient\n /** PanopticPool address */\n poolAddress: Address\n}\n\n/**\n * Result of fetchPoolId, including block metadata for same-block consistency.\n */\nexport interface FetchPoolIdResult {\n /** The encoded 64-bit pool ID */\n poolId: bigint\n /** Block metadata from the pinned read */\n _meta: BlockMeta\n}\n\n/**\n * Fetch the encoded 64-bit pool ID from a PanopticPool contract.\n *\n * Use this when you need the poolId without fetching the full pool state.\n * The returned poolId can be passed directly to `createTokenIdBuilder()`.\n * The read is pinned to the latest block at call time.\n *\n * @param params - The parameters\n * @returns The pool ID and block metadata\n */\nexport async function fetchPoolId(params: FetchPoolIdParams): Promise<FetchPoolIdResult> {\n const { client, poolAddress } = params\n\n const block = await client.getBlock({ blockTag: 'latest' })\n\n const poolId = await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'poolId',\n blockNumber: block.number,\n })\n\n return {\n poolId,\n _meta: {\n blockNumber: block.number,\n blockTimestamp: block.timestamp,\n blockHash: block.hash,\n },\n }\n}\n\nexport { tickToSqrtPriceX96 }\n\n/** Read the pool's spot tick without fetching collateral or risk configuration. */\nexport async function getPoolCurrentTick({\n client,\n poolAddress,\n blockNumber,\n}: {\n client: PublicClient\n poolAddress: Address\n blockNumber?: bigint\n}) {\n return client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getCurrentTick',\n blockNumber,\n })\n}\n","/**\n * Resolve v3 swap routing info from a PanopticPool address.\n * @module uniswap/v3/router/resolveRoute\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { isAddressEqual } from 'viem'\n\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport { getPoolMetadata } from '../../../panoptic/v2/reads/pool'\nimport { InvalidSwapTokenError } from '../../v4/router/errors'\n\nexport interface ResolvedV3SwapRoute {\n tokenIn: Address\n tokenOut: Address\n fee: bigint\n zeroForOne: boolean\n}\n\nexport interface ResolveV3SwapRouteParams {\n client: PublicClient\n poolAddress: Address\n tokenIn: Address\n}\n\nexport async function resolveV3SwapRoute(\n params: ResolveV3SwapRouteParams,\n): Promise<ResolvedV3SwapRoute> {\n const { client, poolAddress, tokenIn } = params\n\n const meta = await getPoolMetadata({ client, poolAddress })\n if (meta.isV4) {\n throw new PanopticError('resolveV3SwapRoute called on a v4 pool')\n }\n\n const isToken0 = isAddressEqual(tokenIn, meta.token0Asset)\n const isToken1 = isAddressEqual(tokenIn, meta.token1Asset)\n if (!isToken0 && !isToken1) {\n throw new InvalidSwapTokenError(tokenIn, meta.token0Asset, meta.token1Asset)\n }\n\n const zeroForOne = isToken0\n return {\n tokenIn,\n tokenOut: zeroForOne ? meta.token1Asset : meta.token0Asset,\n fee: meta.fee,\n zeroForOne,\n }\n}\n","/**\n * Quote v3 swaps with the same `SimulationResult` shape as the v4 path.\n * @module uniswap/v3/router/quoteViaRouter\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { getBlockMeta } from '../../../panoptic/v2/clients/blockMeta'\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport type { SimulationResult } from '../../../panoptic/v2/types'\nimport type { SwapExactInQuote, SwapExactOutQuote } from '../../v4/router/types'\nimport type { UniswapV3Addresses } from '../addresses'\nimport { quoteV3ExactIn, quoteV3ExactOut } from './quote'\nimport { resolveV3SwapRoute } from './resolveRoute'\n\nconst FALLBACK_META = {\n blockNumber: 0n,\n blockTimestamp: 0n,\n blockHash: '0x0' as `0x${string}`,\n}\n\nexport interface QuoteSwapExactInViaV3RouterParams {\n client: PublicClient\n poolAddress: Address\n chainId: bigint\n tokenIn: Address\n amountIn: bigint\n slippageBps: bigint\n blockNumber?: bigint\n addresses?: Partial<UniswapV3Addresses>\n}\n\nexport async function quoteSwapExactInViaV3Router(\n params: QuoteSwapExactInViaV3RouterParams,\n): Promise<SimulationResult<SwapExactInQuote>> {\n const { client, poolAddress, chainId, tokenIn, amountIn, slippageBps, blockNumber, addresses } =\n params\n\n try {\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n void metaPromise.catch(() => undefined)\n\n const route = await resolveV3SwapRoute({ client, poolAddress, tokenIn })\n\n const quote = await quoteV3ExactIn({\n client,\n chainId,\n tokenIn: route.tokenIn,\n tokenOut: route.tokenOut,\n fee: route.fee,\n amountIn,\n slippageBps,\n blockNumber: targetBlockNumber,\n addresses,\n })\n\n if (!quote) {\n throw new PanopticError('v3 quote returned no result (pool may have no liquidity)')\n }\n\n const _meta = await metaPromise\n\n return {\n success: true,\n data: {\n amountOut: quote.amountOut,\n amountOutMinimum: quote.amountOutMinimum,\n zeroForOne: route.zeroForOne,\n tokenOut: route.tokenOut,\n gasEstimate: quote.gasEstimate,\n },\n gasEstimate: quote.gasEstimate,\n _meta,\n }\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Quote failed',\n error instanceof Error ? error : undefined,\n ),\n _meta: FALLBACK_META,\n }\n }\n}\n\nexport interface QuoteSwapExactOutViaV3RouterParams {\n client: PublicClient\n poolAddress: Address\n chainId: bigint\n tokenIn: Address\n amountOut: bigint\n slippageBps: bigint\n blockNumber?: bigint\n addresses?: Partial<UniswapV3Addresses>\n}\n\nexport async function quoteSwapExactOutViaV3Router(\n params: QuoteSwapExactOutViaV3RouterParams,\n): Promise<SimulationResult<SwapExactOutQuote>> {\n const { client, poolAddress, chainId, tokenIn, amountOut, slippageBps, blockNumber, addresses } =\n params\n\n try {\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n void metaPromise.catch(() => undefined)\n\n const route = await resolveV3SwapRoute({ client, poolAddress, tokenIn })\n\n const quote = await quoteV3ExactOut({\n client,\n chainId,\n tokenIn: route.tokenIn,\n tokenOut: route.tokenOut,\n fee: route.fee,\n amountOut,\n slippageBps,\n blockNumber: targetBlockNumber,\n addresses,\n })\n\n if (!quote) {\n throw new PanopticError('v3 quote returned no result (pool may have no liquidity)')\n }\n\n const _meta = await metaPromise\n\n return {\n success: true,\n data: {\n amountIn: quote.amountIn,\n amountInMaximum: quote.amountInMaximum,\n zeroForOne: route.zeroForOne,\n tokenOut: route.tokenOut,\n gasEstimate: quote.gasEstimate,\n },\n gasEstimate: quote.gasEstimate,\n _meta,\n }\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Quote failed',\n error instanceof Error ? error : undefined,\n ),\n _meta: FALLBACK_META,\n }\n }\n}\n","/**\n * Write utilities for the Panoptic v2 SDK.\n * @module v2/writes/utils\n */\n\nimport type { Abi, Address, Hash, Log, PublicClient, WalletClient } from 'viem'\nimport { decodeEventLog, encodeFunctionData } from 'viem'\n\nimport { collateralTrackerV2Abi, panopticPoolV2Abi } from '../../../generated'\nimport type { PanopticEvent, TxOverrides, TxReceipt, TxResult } from '../types'\n\n/**\n * Decode PositionBalance packed data.\n *\n * Layout (from LSB to MSB):\n * - positionSize: bits 0-127 (uint128)\n * - poolUtilization0: bits 128-143 (uint16)\n * - poolUtilization1: bits 144-159 (uint16)\n * - tickAtMint: bits 160-183 (int24)\n * - timestampAtMint: bits 184-215 (uint32)\n * - blockAtMint: bits 216-254 (uint39)\n * - swapAtMint: bit 255 (bool)\n */\nexport function decodePositionBalance(balanceData: bigint): {\n positionSize: bigint\n poolUtilization0: bigint\n poolUtilization1: bigint\n tickAtMint: bigint\n timestampAtMint: bigint\n blockAtMint: bigint\n swapAtMint: boolean\n} {\n const positionSize = balanceData & ((1n << 128n) - 1n)\n const poolUtilization0 = (balanceData >> 128n) & 0xffffn\n const poolUtilization1 = (balanceData >> 144n) & 0xffffn\n\n // tickAtMint is int24 at bits 160-183\n let tickAtMint = (balanceData >> 160n) & 0xffffffn\n // Sign extend if negative (int24)\n if (tickAtMint > 0x7fffffn) {\n tickAtMint = tickAtMint - 0x1000000n\n }\n\n // timestampAtMint is uint32 at bits 184-215\n const timestampAtMint = (balanceData >> 184n) & 0xffffffffn\n\n // blockAtMint is uint39 at bits 216-254\n const blockAtMint = (balanceData >> 216n) & ((1n << 39n) - 1n)\n\n // swapAtMint is bool at bit 255\n const swapAtMint = balanceData >> 255n === 1n\n\n return {\n positionSize,\n poolUtilization0,\n poolUtilization1,\n tickAtMint,\n timestampAtMint,\n blockAtMint,\n swapAtMint,\n }\n}\n\n/**\n * Decode LeftRightSigned packed value.\n */\nexport function decodeLeftRightSigned(value: bigint): { right: bigint; left: bigint } {\n // Right is bits 0-127 (token0), Left is bits 128-255 (token1)\n // Both are signed int128\n let right = value & ((1n << 128n) - 1n)\n let left = value >> 128n\n\n // Sign extend right if needed\n if (right >= 1n << 127n) {\n right = right - (1n << 128n)\n }\n // Sign extend left if needed\n if (left >= 1n << 127n) {\n left = left - (1n << 128n)\n }\n\n return { right, left }\n}\n\n/**\n * Decode LeftRightUnsigned packed value.\n */\nexport function decodeLeftRightUnsigned(value: bigint): { right: bigint; left: bigint } {\n // Right is bits 0-127 (token0), Left is bits 128-255 (token1)\n // Both are unsigned uint128\n const right = value & ((1n << 128n) - 1n)\n const left = value >> 128n\n\n return { right, left }\n}\n\n/**\n * Parse Panoptic events from transaction logs.\n *\n * @param logs - The transaction logs\n * @returns Parsed Panoptic events\n */\nexport function parsePanopticEvents(logs: Log[]): PanopticEvent[] {\n const events: PanopticEvent[] = []\n\n // Try to decode each log with known ABIs\n for (const log of logs) {\n const baseEvent = {\n blockNumber: log.blockNumber ?? 0n,\n blockHash: (log.blockHash ??\n '0x0000000000000000000000000000000000000000000000000000000000000000') as Hash,\n transactionHash: log.transactionHash ?? ('0x' as Hash),\n logIndex: BigInt(log.logIndex ?? 0),\n }\n\n try {\n // Try PanopticPool events\n const poolEvent = decodeEventLog({\n abi: panopticPoolV2Abi,\n data: log.data,\n topics: log.topics,\n })\n\n if (poolEvent.eventName === 'OptionMinted') {\n const args = poolEvent.args as {\n recipient: `0x${string}`\n tokenId: bigint\n balanceData: bigint\n }\n const balance = decodePositionBalance(args.balanceData)\n events.push({\n type: 'OptionMinted',\n ...baseEvent,\n recipient: args.recipient,\n tokenId: args.tokenId,\n positionSize: balance.positionSize,\n poolUtilization0: balance.poolUtilization0,\n poolUtilization1: balance.poolUtilization1,\n tickAtMint: balance.tickAtMint,\n timestampAtMint: balance.timestampAtMint,\n blockAtMint: balance.blockAtMint,\n swapAtMint: balance.swapAtMint,\n })\n } else if (poolEvent.eventName === 'OptionBurnt') {\n const args = poolEvent.args as {\n recipient: `0x${string}`\n tokenId: bigint\n positionSize: bigint\n premiaByLeg: readonly bigint[]\n }\n events.push({\n type: 'OptionBurnt',\n ...baseEvent,\n recipient: args.recipient,\n tokenId: args.tokenId,\n positionSize: args.positionSize,\n premiaByLeg: [\n args.premiaByLeg[0] ?? 0n,\n args.premiaByLeg[1] ?? 0n,\n args.premiaByLeg[2] ?? 0n,\n args.premiaByLeg[3] ?? 0n,\n ] as const,\n })\n } else if (poolEvent.eventName === 'AccountLiquidated') {\n const args = poolEvent.args as {\n liquidator: `0x${string}`\n liquidatee: `0x${string}`\n bonusAmounts: bigint\n }\n const { right, left } = decodeLeftRightSigned(args.bonusAmounts)\n events.push({\n type: 'AccountLiquidated',\n ...baseEvent,\n liquidator: args.liquidator,\n liquidatee: args.liquidatee,\n bonusAmount0: right,\n bonusAmount1: left,\n })\n } else if (poolEvent.eventName === 'ForcedExercised') {\n const args = poolEvent.args as {\n exercisor: `0x${string}`\n user: `0x${string}`\n tokenId: bigint\n exerciseFee: bigint\n }\n const { right, left } = decodeLeftRightSigned(args.exerciseFee)\n events.push({\n type: 'ForcedExercised',\n ...baseEvent,\n exercisor: args.exercisor,\n user: args.user,\n tokenId: args.tokenId,\n exerciseFee0: right,\n exerciseFee1: left,\n })\n } else if (poolEvent.eventName === 'PremiumSettled') {\n const args = poolEvent.args as {\n user: `0x${string}`\n tokenId: bigint\n legIndex: bigint\n settledAmounts: bigint\n }\n const { right, left } = decodeLeftRightSigned(args.settledAmounts)\n events.push({\n type: 'PremiumSettled',\n ...baseEvent,\n user: args.user,\n tokenId: args.tokenId,\n legIndex: args.legIndex,\n settledAmount0: right,\n settledAmount1: left,\n })\n }\n } catch {\n // Not a PanopticPool event, try CollateralTracker\n try {\n const collateralEvent = decodeEventLog({\n abi: collateralTrackerV2Abi,\n data: log.data,\n topics: log.topics,\n })\n\n if (collateralEvent.eventName === 'Deposit') {\n const args = collateralEvent.args as {\n sender: `0x${string}`\n owner: `0x${string}`\n assets: bigint\n shares: bigint\n }\n events.push({\n type: 'Deposit',\n ...baseEvent,\n sender: args.sender,\n owner: args.owner,\n assets: args.assets,\n shares: args.shares,\n })\n } else if (collateralEvent.eventName === 'Withdraw') {\n const args = collateralEvent.args as {\n sender: `0x${string}`\n receiver: `0x${string}`\n owner: `0x${string}`\n assets: bigint\n shares: bigint\n }\n events.push({\n type: 'Withdraw',\n ...baseEvent,\n sender: args.sender,\n receiver: args.receiver,\n owner: args.owner,\n assets: args.assets,\n shares: args.shares,\n })\n }\n } catch {\n // Unknown event, skip\n }\n }\n }\n\n return events\n}\n\n/**\n * Create a TxResult from a transaction hash.\n *\n * @param client - The public client\n * @param hash - The transaction hash\n * @returns TxResult with wait function\n */\nexport function createTxResult(client: PublicClient, hash: Hash): TxResult {\n return {\n hash,\n wait: async (confirmations?: bigint): Promise<TxReceipt> => {\n const receipt = await client.waitForTransactionReceipt({\n hash,\n confirmations: confirmations !== undefined ? Number(confirmations) : undefined,\n })\n\n const events = parsePanopticEvents(receipt.logs)\n\n return {\n hash: receipt.transactionHash,\n blockNumber: receipt.blockNumber,\n blockHash: receipt.blockHash,\n gasUsed: receipt.gasUsed,\n status: receipt.status === 'success' ? 'success' : 'reverted',\n events,\n }\n },\n }\n}\n\n/**\n * Execute a write operation and return TxResult.\n *\n * @param client - The public client\n * @param hashPromise - Promise that resolves to transaction hash\n * @returns TxResult\n */\nexport async function executeWrite(\n client: PublicClient,\n hashPromise: Promise<Hash>,\n): Promise<TxResult> {\n const hash = await hashPromise\n return createTxResult(client, hash)\n}\n\n/**\n * Execute a write operation and wait for receipt.\n *\n * @param client - The public client\n * @param hashPromise - Promise that resolves to transaction hash\n * @param confirmations - Number of confirmations to wait for\n * @returns TxReceipt\n */\nexport async function executeWriteAndWait(\n client: PublicClient,\n hashPromise: Promise<Hash>,\n confirmations?: bigint,\n): Promise<TxReceipt> {\n const result = await executeWrite(client, hashPromise)\n return result.wait(confirmations)\n}\n\n/**\n * Parameters for the submitWrite helper.\n */\nexport interface SubmitWriteParams {\n /** Public client */\n client: PublicClient\n /** Wallet client */\n walletClient: WalletClient\n /** Account address */\n account: Address\n /** Contract address */\n address: Address\n /** Contract ABI */\n abi: Abi\n /** Function name to call */\n functionName: string\n /** Function arguments */\n args: readonly unknown[]\n /** ETH value to send with the transaction (for native ETH deposits) */\n value?: bigint\n /** Optional gas and transaction overrides */\n txOverrides?: TxOverrides\n}\n\n/**\n * Submit a write operation, supporting both direct wallet submission\n * and custom broadcaster paths with gas overrides.\n *\n * Normal path (no broadcaster): calls walletClient.writeContract() with gas overrides.\n * Broadcaster path: prepareTransactionRequest → apply overrides → signTransaction → broadcast.\n *\n * @param params - Submit write parameters\n * @returns TxResult\n */\nexport async function submitWrite(params: SubmitWriteParams): Promise<TxResult> {\n const { client, walletClient, account, address, abi, functionName, args, value, txOverrides } =\n params\n\n const broadcaster = txOverrides?.broadcaster\n\n if (broadcaster) {\n // Encode contract calldata before request preparation so gas/tx params\n // are derived from the exact call being signed and broadcast.\n const data = encodeFunctionData({ abi, functionName, args })\n\n // Broadcaster path: prepare → sign → broadcast\n const broadcastAccount = walletClient.account ?? account\n const request = await walletClient.prepareTransactionRequest({\n account: broadcastAccount,\n to: address,\n chain: walletClient.chain,\n data,\n ...(value !== undefined && { value }),\n ...(txOverrides?.maxFeePerGas !== undefined && { maxFeePerGas: txOverrides.maxFeePerGas }),\n ...(txOverrides?.maxPriorityFeePerGas !== undefined && {\n maxPriorityFeePerGas: txOverrides.maxPriorityFeePerGas,\n }),\n ...(txOverrides?.gas !== undefined && { gas: txOverrides.gas }),\n ...(txOverrides?.nonce !== undefined && { nonce: Number(txOverrides.nonce) }),\n })\n\n const signedTx = await walletClient.signTransaction({\n ...request,\n account: broadcastAccount,\n } as unknown as Parameters<WalletClient['signTransaction']>[0])\n\n const hash = await broadcaster.broadcast(signedTx)\n return createTxResult(client, hash)\n }\n\n // Normal path: direct writeContract with gas overrides\n const gasOverrides: Record<string, unknown> = {}\n if (txOverrides?.maxFeePerGas !== undefined) {\n gasOverrides.maxFeePerGas = txOverrides.maxFeePerGas\n }\n if (txOverrides?.maxPriorityFeePerGas !== undefined) {\n gasOverrides.maxPriorityFeePerGas = txOverrides.maxPriorityFeePerGas\n }\n if (txOverrides?.nonce !== undefined) {\n gasOverrides.nonce = Number(txOverrides.nonce)\n }\n\n // Use the walletClient's local account (if available) for local signing.\n // Passing a string address triggers eth_sendTransaction (remote signing),\n // which fails with hosted RPC providers like Alchemy/Infura.\n const resolvedAccount = walletClient.account ?? account\n\n // If no explicit gas override, estimate with a 20% buffer.\n // Panoptic dispatch calls are gas-heavy and viem's default estimate can be tight.\n if (txOverrides?.gas !== undefined) {\n gasOverrides.gas = txOverrides.gas\n } else {\n const estimated = await client.estimateContractGas({\n address,\n abi,\n functionName,\n args,\n account: resolvedAccount,\n ...(value !== undefined && { value }),\n } as Parameters<typeof client.estimateContractGas>[0])\n gasOverrides.gas = (estimated * 120n) / 100n\n }\n\n const hash = await walletClient.writeContract({\n address,\n abi,\n functionName,\n args,\n account: resolvedAccount,\n chain: walletClient.chain,\n ...(value !== undefined && { value }),\n ...gasOverrides,\n })\n\n return createTxResult(client, hash)\n}\n\n/**\n * Parameters required for all write operations.\n */\nexport interface BaseWriteParams {\n /** Public client for reading state */\n client: PublicClient\n}\n","/**\n * Per-chain Uniswap v4 infrastructure addresses (Universal Router, V4Quoter,\n * PoolManager, Permit2).\n *\n * Supports Ethereum mainnet and Robinhood; other chains throw {@link UnsupportedChainError}\n * unless every address is supplied via the `overrides` argument (e.g. anvil\n * fork tests, or bots targeting a not-yet-listed chain).\n *\n * @module uniswap/v4/addresses\n */\n\nimport type { Address } from 'viem'\n\nimport { UnsupportedChainError } from './router/errors'\n\n/**\n * Uniswap v4 contract addresses required for a Universal Router spot swap.\n */\nexport interface UniswapV4Addresses {\n /** Universal Router (v4-capable build) — entrypoint for `execute(...)`. */\n universalRouter: Address\n /** V4Quoter — `quoteExactInputSingle` (revert/staticcall-based). */\n v4Quoter: Address\n /** Uniswap v4 PoolManager (singleton). */\n poolManager: Address\n /** Uniswap v4 PositionManager (posm) — ERC721 LP position NFTs. */\n positionManager: Address\n /** Canonical Permit2 (same address on every chain). */\n permit2: Address\n}\n\n/**\n * Canonical Permit2, identical across all chains.\n */\nexport const PERMIT2_ADDRESS: Address = '0x000000000022D473030F116dDEE9F6B43aC78BA3'\n\n/**\n * Verified Uniswap v4 deployment addresses keyed by chainId.\n *\n * Sourced from the official Uniswap v4 deployments. Add a chain here only after\n * verifying each address against the canonical Uniswap deployment listing —\n * Universal Router in particular is NOT the same address across chains.\n */\nexport const UNISWAP_V4_ADDRESSES: Record<number, UniswapV4Addresses> = {\n // Ethereum mainnet\n 1: {\n universalRouter: '0x66a9893cC07D91D95644AEDD05D03f95e1dBA8Af',\n v4Quoter: '0x52F0E24D1c21C8A0cB1e5a5dD6198556BD9E1203',\n poolManager: '0x000000000004444c5dc75cB358380D2e3dE08A90',\n positionManager: '0xbD216513d74C8cf14cf4747E6AaA6420FF64ee9e',\n permit2: PERMIT2_ADDRESS,\n },\n 4663: {\n universalRouter: '0x8876789976decbfcbbbe364623c63652db8c0904',\n v4Quoter: '0x8dc178efb8111bb0973dd9d722ebeff267c98f94',\n poolManager: '0x8366a39cc670b4001a1121b8f6a443a643e40951',\n positionManager: '0x58daec3116aae6d93017baaea7749052e8a04fa7',\n permit2: PERMIT2_ADDRESS,\n },\n}\n\n/**\n * Resolve the Uniswap v4 addresses for a chain, applying optional overrides.\n *\n * @param chainId - Target chain ID.\n * @param overrides - Partial override of any address (e.g. for fork tests).\n * @returns Fully-resolved {@link UniswapV4Addresses}.\n * @throws {UnsupportedChainError} when the chain is not listed and the\n * overrides do not supply every required address.\n */\nexport function getUniswapV4Addresses(\n chainId: bigint,\n overrides?: Partial<UniswapV4Addresses>,\n): UniswapV4Addresses {\n const base = UNISWAP_V4_ADDRESSES[Number(chainId)]\n\n const merged: Partial<UniswapV4Addresses> = {\n ...base,\n ...overrides,\n permit2: overrides?.permit2 ?? base?.permit2 ?? PERMIT2_ADDRESS,\n }\n\n if (\n merged.universalRouter === undefined ||\n merged.v4Quoter === undefined ||\n merged.poolManager === undefined ||\n merged.positionManager === undefined ||\n merged.permit2 === undefined\n ) {\n throw new UnsupportedChainError(chainId)\n }\n\n return merged as UniswapV4Addresses\n}\n","/**\n * Exact-in and exact-out spot swaps via the Uniswap v3 path on the Universal Router.\n * @module uniswap/v3/router/swap\n */\n\nimport type { Address, PublicClient, WalletClient } from 'viem'\nimport { isAddressEqual } from 'viem'\n\nimport { getBlockMeta } from '../../../panoptic/v2/clients/blockMeta'\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport type { TxOverrides, TxResult } from '../../../panoptic/v2/types'\nimport { submitWrite } from '../../../panoptic/v2/writes/utils'\nimport { universalRouterAbi } from '../../v4/abis/universalRouter'\nimport { type UniswapV4Addresses, getUniswapV4Addresses } from '../../v4/addresses'\nimport type { UniswapV3Addresses } from '../addresses'\nimport { buildV3ExactOutSwapExecuteArgs, buildV3SwapExecuteArgs } from './encodeSwap'\nimport { quoteV3ExactIn, quoteV3ExactOut } from './quote'\nimport { resolveV3SwapRoute } from './resolveRoute'\n\nconst DEFAULT_DEADLINE_SECONDS = 1800n\n\nexport interface SwapExactInViaV3RouterParams {\n client: PublicClient\n walletClient: WalletClient\n account: Address\n poolAddress: Address\n chainId: bigint\n tokenIn: Address\n amountIn: bigint\n slippageBps: bigint\n deadline?: bigint\n recipient?: Address\n txOverrides?: TxOverrides\n addresses?: Partial<UniswapV3Addresses & UniswapV4Addresses>\n}\n\nexport async function swapExactInViaV3Router(\n params: SwapExactInViaV3RouterParams,\n): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n tokenIn,\n amountIn,\n slippageBps,\n deadline,\n recipient,\n txOverrides,\n addresses,\n } = params\n\n if (recipient !== undefined && !isAddressEqual(recipient, account)) {\n throw new PanopticError('Custom recipient is not supported yet; output goes to the sender')\n }\n\n const resolved = getUniswapV4Addresses(chainId, addresses)\n const route = await resolveV3SwapRoute({ client, poolAddress, tokenIn })\n\n const quote = await quoteV3ExactIn({\n client,\n chainId,\n tokenIn: route.tokenIn,\n tokenOut: route.tokenOut,\n fee: route.fee,\n amountIn,\n slippageBps,\n addresses,\n })\n\n if (!quote) {\n throw new PanopticError('v3 quote failed (pool may have no liquidity)')\n }\n\n const resolvedDeadline =\n deadline ?? (await getBlockMeta({ client })).blockTimestamp + DEFAULT_DEADLINE_SECONDS\n\n const { args, value } = buildV3SwapExecuteArgs({\n tokenIn: route.tokenIn,\n tokenOut: route.tokenOut,\n fee: route.fee,\n amountIn,\n amountOutMinimum: quote.amountOutMinimum,\n deadline: resolvedDeadline,\n })\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: resolved.universalRouter,\n abi: universalRouterAbi,\n functionName: 'execute',\n args,\n value,\n txOverrides,\n })\n}\n\nexport interface SwapExactOutViaV3RouterParams {\n client: PublicClient\n walletClient: WalletClient\n account: Address\n poolAddress: Address\n chainId: bigint\n tokenIn: Address\n amountOut: bigint\n slippageBps: bigint\n deadline?: bigint\n recipient?: Address\n txOverrides?: TxOverrides\n addresses?: Partial<UniswapV3Addresses & UniswapV4Addresses>\n}\n\nexport async function swapExactOutViaV3Router(\n params: SwapExactOutViaV3RouterParams,\n): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n tokenIn,\n amountOut,\n slippageBps,\n deadline,\n recipient,\n txOverrides,\n addresses,\n } = params\n\n if (recipient !== undefined && !isAddressEqual(recipient, account)) {\n throw new PanopticError('Custom recipient is not supported yet; output goes to the sender')\n }\n\n const resolved = getUniswapV4Addresses(chainId, addresses)\n const route = await resolveV3SwapRoute({ client, poolAddress, tokenIn })\n\n const quote = await quoteV3ExactOut({\n client,\n chainId,\n tokenIn: route.tokenIn,\n tokenOut: route.tokenOut,\n fee: route.fee,\n amountOut,\n slippageBps,\n addresses,\n })\n\n if (!quote) {\n throw new PanopticError('v3 quote failed (pool may have no liquidity)')\n }\n\n const resolvedDeadline =\n deadline ?? (await getBlockMeta({ client })).blockTimestamp + DEFAULT_DEADLINE_SECONDS\n\n const { args, value } = buildV3ExactOutSwapExecuteArgs({\n tokenIn: route.tokenIn,\n tokenOut: route.tokenOut,\n fee: route.fee,\n amountOut,\n amountInMaximum: quote.amountInMaximum,\n deadline: resolvedDeadline,\n })\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: resolved.universalRouter,\n abi: universalRouterAbi,\n functionName: 'execute',\n args,\n value,\n txOverrides,\n })\n}\n","/**\n * Pure calldata builders for exact-in and exact-out single-hop swaps via the\n * Uniswap v4 Universal Router.\n *\n * Opcodes verified against `@uniswap/universal-router` `Commands.sol` and\n * `@uniswap/v4-periphery` `Actions.sol`:\n * - Universal Router commands `V4_SWAP = 0x10`, `SWEEP = 0x04`.\n * - v4 actions `SWAP_EXACT_IN_SINGLE = 0x06`, `SWAP_EXACT_OUT_SINGLE = 0x08`,\n * `SETTLE_ALL = 0x0c`, `TAKE = 0x0e`, `TAKE_ALL = 0x0f`.\n *\n * Native ETH is `address(0)` in the PoolKey and needs special handling per side:\n * - Native-ETH OUTPUT: the implicit-recipient `TAKE_ALL` leaves the bought ETH\n * held by the Universal Router, so output is taken with the explicit-recipient\n * `TAKE` action instead, delivering ETH straight to the recipient. No trailing\n * SWEEP is appended for native output.\n * - Native-ETH INPUT on exact-out: the router is funded with the full\n * `amountInMaximum` overpay, so a trailing Universal-Router-level `SWEEP`\n * command (NOT the v4 SWEEP action, which this router does not support) refunds\n * the unused ETH to the recipient.\n * Native-ETH input on exact-in needs neither (msg.value equals the exact input;\n * ERC20 output is delivered by `TAKE_ALL`).\n *\n * @module uniswap/v4/router/encodeSwap\n */\n\nimport type { Address, Hex } from 'viem'\nimport { encodeAbiParameters, encodeFunctionData, encodePacked, zeroAddress } from 'viem'\n\nimport type { PoolKey } from '../../../panoptic/v2/types'\nimport { universalRouterAbi } from '../abis/universalRouter'\nimport { AmountExceedsUint128Error, MissingSweepRecipientError } from './errors'\n\n/** Universal Router command byte for a v4 swap. */\nexport const V4_SWAP = 0x10\n/** v4 action: exact-in single-hop swap. */\nexport const SWAP_EXACT_IN_SINGLE = 0x06\n/** v4 action: pay all of the input currency owed. */\nexport const SETTLE_ALL = 0x0c\n/** v4 action: take all of the output currency owed. */\nexport const TAKE_ALL = 0x0f\n/** v4 action: take an output currency to an explicit recipient. */\nexport const TAKE = 0x0e\n/** v4 action: exact-out single-hop swap. */\nexport const SWAP_EXACT_OUT_SINGLE = 0x08\n/** Universal Router command: sweep the router's token balance to a recipient. */\nexport const SWEEP = 0x04\n\n/** v4 sentinel: take the full positive currency delta (used with TAKE). */\nconst OPEN_DELTA = 0n\n\nconst UINT128_MAX = (1n << 128n) - 1n\n\nconst poolKeyComponents = [\n { name: 'currency0', type: 'address' },\n { name: 'currency1', type: 'address' },\n { name: 'fee', type: 'uint24' },\n { name: 'tickSpacing', type: 'int24' },\n { name: 'hooks', type: 'address' },\n] as const\n\nconst exactInputSingleParamsAbi = [\n {\n type: 'tuple',\n components: [\n { name: 'poolKey', type: 'tuple', components: poolKeyComponents },\n { name: 'zeroForOne', type: 'bool' },\n { name: 'amountIn', type: 'uint128' },\n { name: 'amountOutMinimum', type: 'uint128' },\n { name: 'hookData', type: 'bytes' },\n ],\n },\n] as const\n\nconst exactOutputSingleParamsAbi = [\n {\n type: 'tuple',\n components: [\n { name: 'poolKey', type: 'tuple', components: poolKeyComponents },\n { name: 'zeroForOne', type: 'bool' },\n { name: 'amountOut', type: 'uint128' },\n { name: 'amountInMaximum', type: 'uint128' },\n { name: 'hookData', type: 'bytes' },\n ],\n },\n] as const\n\nconst currencyAmountAbi = [\n { name: 'currency', type: 'address' },\n { name: 'amount', type: 'uint256' },\n] as const\n\n// v4 TAKE action params: take `amount` of `currency` to an explicit recipient.\nconst takeToRecipientAbi = [\n { name: 'currency', type: 'address' },\n { name: 'recipient', type: 'address' },\n { name: 'amount', type: 'uint256' },\n] as const\n\n// Universal Router SWEEP command params: forward `token` above `amountMin` to\n// `recipient`.\nconst sweepParamsAbi = [\n { name: 'token', type: 'address' },\n { name: 'recipient', type: 'address' },\n { name: 'amountMin', type: 'uint256' },\n] as const\n\nfunction assertUint128(amount: bigint): void {\n if (amount < 0n || amount > UINT128_MAX) {\n throw new AmountExceedsUint128Error(amount)\n }\n}\n\n/**\n * Encode the input for a Universal Router `SWEEP` command that forwards the\n * router's full native-ETH balance (above `amountMin = 0`) to `recipient`.\n */\nfunction encodeEthSweepInput(recipient: Address): Hex {\n return encodeAbiParameters(sweepParamsAbi, [zeroAddress, recipient, 0n])\n}\n\n/**\n * Build the output-take v4 action byte + param.\n *\n * Native-ETH output is taken with the explicit-recipient `TAKE` action so the\n * router forwards the ETH straight to `recipient` (the implicit-`msgSender`\n * `TAKE_ALL` leaves native ETH held by the router). ERC20 output uses\n * `TAKE_ALL`, which already credits the caller.\n *\n * @param nativeAmount - TAKE amount for native-ETH output: `OPEN_DELTA` (0) to\n * take the full credit (exact-in, protected by the swap's min) or the exact\n * output (exact-out).\n * @param erc20Amount - TAKE_ALL min/amount for ERC20 output: `amountOutMinimum`\n * (exact-in) or the exact output (exact-out).\n */\nfunction buildOutputTake(\n tokenOut: Address,\n recipient: Address | undefined,\n nativeAmount: bigint,\n erc20Amount: bigint,\n): { action: number; param: Hex } {\n if (tokenOut === zeroAddress) {\n if (recipient === undefined) {\n throw new MissingSweepRecipientError()\n }\n return {\n action: TAKE,\n param: encodeAbiParameters(takeToRecipientAbi, [zeroAddress, recipient, nativeAmount]),\n }\n }\n return {\n action: TAKE_ALL,\n param: encodeAbiParameters(currencyAmountAbi, [tokenOut, erc20Amount]),\n }\n}\n\n/**\n * Arguments for {@link buildV4SwapExecuteCalldata}.\n */\nexport interface BuildV4SwapCalldataArgs {\n /** The v4 PoolKey (currency0, currency1, fee, tickSpacing, hooks). */\n poolKey: PoolKey\n /** Whether the swap goes currency0 → currency1. */\n zeroForOne: boolean\n /** Exact input amount (uint128). */\n amountIn: bigint\n /** Minimum acceptable output (uint128). */\n amountOutMinimum: bigint\n /** Input token address (`address(0)` for native ETH). */\n tokenIn: Address\n /** Output token address (`address(0)` for native ETH). */\n tokenOut: Address\n /** Absolute deadline (unix seconds). */\n deadline: bigint\n /**\n * Recipient of native-ETH output. Required when `tokenOut` is `address(0)`,\n * since the explicit-recipient `TAKE` action forwards the bought ETH there\n * (the implicit-recipient `TAKE_ALL` would leave it held by the router).\n */\n recipient?: Address\n /** Hook data; defaults to `0x` (hook-less pools). */\n hookData?: Hex\n}\n\n/**\n * Build the typed `execute(...)` args + msg.value for an exact-in single-hop v4\n * swap. Use this when submitting via viem (`writeContract` / `submitWrite`).\n *\n * When `tokenOut` is native ETH the explicit-recipient `TAKE` action forwards\n * the bought ETH to `recipient` (no trailing SWEEP is needed for exact-in).\n *\n * @returns `args` ready to spread into `execute` and the ETH `value` to send\n * (= `amountIn` for native-ETH input, otherwise `0n`).\n */\nexport function buildV4SwapExecuteArgs(args: BuildV4SwapCalldataArgs): {\n args: readonly [Hex, readonly Hex[], bigint]\n value: bigint\n} {\n const {\n poolKey,\n zeroForOne,\n amountIn,\n amountOutMinimum,\n tokenIn,\n tokenOut,\n deadline,\n recipient,\n hookData = '0x',\n } = args\n\n assertUint128(amountIn)\n assertUint128(amountOutMinimum)\n\n const swapParam = encodeAbiParameters(exactInputSingleParamsAbi, [\n {\n poolKey: {\n currency0: poolKey.currency0,\n currency1: poolKey.currency1,\n fee: Number(poolKey.fee),\n tickSpacing: Number(poolKey.tickSpacing),\n hooks: poolKey.hooks,\n },\n zeroForOne,\n amountIn,\n amountOutMinimum,\n hookData,\n },\n ])\n\n // SETTLE_ALL pays the input; the output take credits the recipient. Native-ETH\n // output uses the explicit-recipient TAKE so the router forwards the ETH (with\n // OPEN_DELTA to take the full, slippage-protected swap output).\n const settleParam = encodeAbiParameters(currencyAmountAbi, [tokenIn, amountIn])\n const take = buildOutputTake(tokenOut, recipient, OPEN_DELTA, amountOutMinimum)\n\n const actions = encodePacked(\n ['uint8', 'uint8', 'uint8'],\n [SWAP_EXACT_IN_SINGLE, SETTLE_ALL, take.action],\n )\n\n const v4Input = encodeAbiParameters(\n [\n { name: 'actions', type: 'bytes' },\n { name: 'params', type: 'bytes[]' },\n ],\n [actions, [swapParam, settleParam, take.param]],\n )\n\n // Native-ETH input on exact-in needs no SWEEP (msg.value equals the exact input).\n const commands = encodePacked(['uint8'], [V4_SWAP])\n const value = tokenIn === zeroAddress ? amountIn : 0n\n\n return { args: [commands, [v4Input], deadline] as const, value }\n}\n\n/**\n * Build the `execute(commands, inputs, deadline)` calldata + msg.value for an\n * exact-in single-hop v4 swap.\n *\n * @returns The encoded calldata and the ETH `value` to send.\n */\nexport function buildV4SwapExecuteCalldata(args: BuildV4SwapCalldataArgs): {\n data: Hex\n value: bigint\n} {\n const { args: executeArgs, value } = buildV4SwapExecuteArgs(args)\n const data = encodeFunctionData({\n abi: universalRouterAbi,\n functionName: 'execute',\n args: executeArgs,\n })\n return { data, value }\n}\n\n/**\n * Arguments for {@link buildV4ExactOutSwapExecuteCalldata}.\n */\nexport interface BuildV4ExactOutSwapCalldataArgs {\n /** The v4 PoolKey (currency0, currency1, fee, tickSpacing, hooks). */\n poolKey: PoolKey\n /** Whether the swap goes currency0 → currency1. */\n zeroForOne: boolean\n /** Exact output amount to receive (uint128). */\n amountOut: bigint\n /** Maximum acceptable input to spend (uint128). */\n amountInMaximum: bigint\n /** Input token address (`address(0)` for native ETH). */\n tokenIn: Address\n /** Output token address (`address(0)` for native ETH). */\n tokenOut: Address\n /** Absolute deadline (unix seconds). */\n deadline: bigint\n /**\n * Recipient of any swept native-ETH refund (only used for native-ETH input).\n * Must be the payer; the leftover `amountInMaximum - actualInput` is returned\n * here.\n */\n recipient: Address\n /** Hook data; defaults to `0x` (hook-less pools). */\n hookData?: Hex\n}\n\n/**\n * Build the typed `execute(...)` args + msg.value for an exact-out single-hop v4\n * swap. Use this when submitting via viem (`writeContract` / `submitWrite`).\n *\n * For native-ETH input, `value` is `amountInMaximum` (an overpay) and a trailing\n * `SWEEP` action refunds the unused ETH to `recipient`. For ERC20 input, Permit2\n * pulls only the settled amount, so no SWEEP is appended and `value` is `0n`.\n *\n * @returns `args` ready to spread into `execute` and the ETH `value` to send.\n */\nexport function buildV4ExactOutSwapExecuteArgs(args: BuildV4ExactOutSwapCalldataArgs): {\n args: readonly [Hex, readonly Hex[], bigint]\n value: bigint\n} {\n const {\n poolKey,\n zeroForOne,\n amountOut,\n amountInMaximum,\n tokenIn,\n tokenOut,\n deadline,\n recipient,\n hookData = '0x',\n } = args\n\n assertUint128(amountOut)\n assertUint128(amountInMaximum)\n\n const swapParam = encodeAbiParameters(exactOutputSingleParamsAbi, [\n {\n poolKey: {\n currency0: poolKey.currency0,\n currency1: poolKey.currency1,\n fee: Number(poolKey.fee),\n tickSpacing: Number(poolKey.tickSpacing),\n hooks: poolKey.hooks,\n },\n zeroForOne,\n amountOut,\n amountInMaximum,\n hookData,\n },\n ])\n\n // SETTLE_ALL caps the input at amountInMaximum; the output take delivers the\n // exact output. Native-ETH output uses the explicit-recipient TAKE so the\n // router forwards the ETH straight to `recipient`.\n const settleParam = encodeAbiParameters(currencyAmountAbi, [tokenIn, amountInMaximum])\n const take = buildOutputTake(tokenOut, recipient, amountOut, amountOut)\n\n const actions = encodePacked(\n ['uint8', 'uint8', 'uint8'],\n [SWAP_EXACT_OUT_SINGLE, SETTLE_ALL, take.action],\n )\n\n const v4Input = encodeAbiParameters(\n [\n { name: 'actions', type: 'bytes' },\n { name: 'params', type: 'bytes[]' },\n ],\n [actions, [swapParam, settleParam, take.param]],\n )\n\n const isNativeIn = tokenIn === zeroAddress\n\n // Native-ETH input funds the router with the full overpay cap; a trailing\n // Universal Router SWEEP command (the v4 SWEEP *action* is unsupported here)\n // refunds the unused ETH to the recipient.\n const commandList: number[] = [V4_SWAP]\n const inputs: Hex[] = [v4Input]\n if (isNativeIn) {\n commandList.push(SWEEP)\n inputs.push(encodeEthSweepInput(recipient))\n }\n\n const commands = encodePacked(\n commandList.map(() => 'uint8'),\n commandList,\n )\n const value = isNativeIn ? amountInMaximum : 0n\n\n return { args: [commands, inputs, deadline] as const, value }\n}\n\n/**\n * Build the `execute(commands, inputs, deadline)` calldata + msg.value for an\n * exact-out single-hop v4 swap.\n *\n * @returns The encoded calldata and the ETH `value` to send.\n */\nexport function buildV4ExactOutSwapExecuteCalldata(args: BuildV4ExactOutSwapCalldataArgs): {\n data: Hex\n value: bigint\n} {\n const { args: executeArgs, value } = buildV4ExactOutSwapExecuteArgs(args)\n const data = encodeFunctionData({\n abi: universalRouterAbi,\n functionName: 'execute',\n args: executeArgs,\n })\n return { data, value }\n}\n","/**\n * Snapshot recovery from dispatch calldata.\n * @module v2/sync/snapshotRecovery\n */\n\nimport type { AbiFunction, Address, Hash, Hex, PublicClient } from 'viem'\nimport { decodeFunctionData, getAddress, parseAbi, toFunctionSelector } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\n\nconst LOG_SCAN_WINDOW = 10_000n\nconst rolesExecutionAbi = parseAbi([\n 'function execTransactionWithRole(address to, uint256 value, bytes data, uint8 operation, bytes32 roleKey, bool shouldRevert)',\n])\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 /** Expected Zodiac Roles wrapper for bot-originated Safe dispatches. */\n rolesContext?: {\n modifier: Address\n member: Address\n roleKey: Hash\n }\n}\n\nexport interface RolesSnapshotContext {\n modifier: Address\n member: Address\n roleKey: Hash\n}\n\nexport function decodeSnapshotTransaction(params: {\n input: Hex\n from: Address\n to: Address | null\n account?: Address\n pool?: Address\n rolesContext?: RolesSnapshotContext\n}): DispatchCalldata | null {\n const { account, pool, rolesContext } = params\n let dispatchInput = params.input\n let dispatchSender = params.from\n\n if (rolesContext) {\n if (\n params.to === null ||\n getAddress(params.to) !== getAddress(rolesContext.modifier) ||\n getAddress(params.from) !== getAddress(rolesContext.member)\n ) {\n return null\n }\n try {\n const decodedRoleCall = decodeFunctionData({ abi: rolesExecutionAbi, data: params.input })\n const [target, value, data, operation, roleKey, shouldRevert] = decodedRoleCall.args\n if (\n !pool ||\n getAddress(target) !== getAddress(pool) ||\n value !== 0n ||\n operation !== 0 ||\n roleKey.toLowerCase() !== rolesContext.roleKey.toLowerCase() ||\n !shouldRevert\n ) {\n return null\n }\n dispatchInput = data\n if (!account) return null\n dispatchSender = account\n } catch {\n return null\n }\n } else if (pool && (params.to === null || getAddress(params.to) !== getAddress(pool))) {\n return null\n }\n\n const candidates = decodeAllDispatchCalldata(dispatchInput)\n if (candidates.length === 0) return null\n return account\n ? selectDispatchForAccount(candidates, account, dispatchSender)\n : candidates[candidates.length - 1]\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, rolesContext } = 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 const decoded = decodeSnapshotTransaction({\n input: tx.input,\n from: tx.from,\n to: tx.to,\n account,\n pool,\n rolesContext,\n })\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 * Client-side greeks for the Panoptic v2 SDK.\n *\n * All functions accept bigint inputs (ticks, sizes) and return bigint values\n * in the natural token units — no artificial WAD scaling. The tick-based price\n * (1.0001^tick) naturally encodes the decimal conversion between tokens.\n *\n * Uses pure sqrtPriceX96 arithmetic for exact on-chain fidelity with PanopticQuery.\n * All intermediate calculations keep X96/X192 precision until final scaling.\n *\n * - Value: in numeraire token smallest units (e.g., USDC wei if numeraire is USDC)\n * - Delta: in asset token smallest units (e.g., WETH wei if asset is WETH)\n * - Gamma (dollar-gamma): in numeraire token smallest units\n *\n * @module v2/greeks\n */\n\nimport { tickToSqrtPriceX96 } from '../formatters/tick'\nimport type { TokenIdLeg } from '../types'\n\n// --- Internal Helpers ---\n\n/** Fixed-point scale constants for sqrtPriceX96 arithmetic */\nconst Q96 = 1n << 96n\nconst Q192 = 1n << 192n\n\n/**\n * Convert tick to quote-denominated tick based on asset direction.\n *\n * When isAssetToken0 = true (asset is token0, numeraire is token1):\n * - Tick already encodes price as token1/token0 (numeraire per asset)\n * - Return tick unchanged\n *\n * When isAssetToken0 = false (asset is token1, numeraire is token0):\n * - Tick encodes price as token1/token0, but we need token0/token1 (numeraire per asset)\n * - Invert by negating: 1/price = 1.0001^(-tick)\n */\nfunction quoteTick(tick: bigint, isAssetToken0: boolean): bigint {\n return isAssetToken0 ? tick : -tick\n}\n\n/**\n * Divide with truncation toward zero (matches Solidity division behavior).\n *\n * JavaScript bigint division uses floor (toward negative infinity), but Solidity\n * truncates toward zero. For on-chain fidelity, we must match Solidity.\n *\n * Example:\n * - Solidity: -7 / 2 = -3 (truncate toward zero)\n * - JS bigint: -7n / 2n = -4n (floor toward -∞)\n * - This function: divTrunc(-7n, 2n) = -3n ✓\n */\nfunction divTrunc(numerator: bigint, denominator: bigint): bigint {\n if (denominator === 0n) return 0n\n\n const quotient = numerator / denominator\n const remainder = numerator % denominator\n\n // If signs differ and there's a remainder, JS floored when we need to truncate\n // Add 1 to move toward zero\n if (numerator < 0n !== denominator < 0n && remainder !== 0n) {\n return quotient + 1n\n }\n\n return quotient\n}\n\n/** Resolve isAssetToken0: optional assetIndex overrides leg.asset */\nfunction resolveAssetDirection(leg: Pick<TokenIdLeg, 'asset'>, assetIndex?: bigint): boolean {\n return assetIndex !== undefined ? assetIndex === 0n : leg.asset === 0n\n}\n\n/**\n * Compute the tokenType-denominated notional of a width=0 (loan/credit) leg.\n *\n * When leg.asset !== leg.tokenType, positionSize is in leg.asset units and\n * the borrowed notional is encoded via leg.strike: notional_tokenType_raw =\n * positionSize_raw × 1.0001^strike (a raw-to-raw ratio, unquoted by pool direction).\n * When leg.asset === leg.tokenType, m is already the notional (old convention).\n *\n * `m > 0` for loans (isLong=false), `m < 0` for credits (isLong=true), so the\n * returned notional is signed the same way.\n */\nfunction computeWidth0Notional(leg: TokenIdLeg, m: bigint): bigint {\n const scaleByStrike = leg.asset !== leg.tokenType\n if (!scaleByStrike) return m\n // The UI stores strike with a sign that depends on leg.asset:\n // priceTokenTypePerAsset = 1.0001^(leg.asset === 0 ? strike : -strike)\n // Mirror that here so K_raw matches the intended notional scaling.\n const signedStrike = leg.asset === 0n ? leg.strike : -leg.strike\n const sqrtKraw = tickToSqrtPriceX96(signedStrike)\n const KrawX192 = sqrtKraw * sqrtKraw\n return divTrunc(m * KrawX192, Q192)\n}\n\n/**\n * Calculate value for a width=0 (loan/credit) leg.\n * Width=0 means the range is a single tick (the strike), so there's no meaningful\n * \"in range\" — we use the below/above formulas which avoid division by (r-1)=0.\n *\n * This is the DEBT-ONLY value (the borrowed/lent obligation), used by delta/greeks\n * aggregation where the held-collateral side lives in a separate wallet/CT term. For\n * a standalone payoff chart that must reflect the net user-experienced payoff (which\n * depends on Zap vs Cover-at-mint), use `getLegNetValueWidth0`.\n */\nfunction getLegValueWidth0(\n leg: TokenIdLeg,\n m: bigint,\n qCurrentTick: bigint,\n qStrikeTick: bigint,\n qMintTick: bigint,\n isAssetToken0: boolean,\n _definedRisk: boolean,\n): bigint {\n // For loan/credit legs (width=0), value depends on the borrowed token.\n // m > 0 for loans (isLong=false), m < 0 for credits (isLong=true).\n const borrowsAsset = isCall(leg.tokenType, isAssetToken0)\n\n const notional = computeWidth0Notional(leg, m)\n\n if (borrowsAsset) {\n // Asset loan/credit: debt PnL = -notional*(P - Pm); crosses y=0 at mint price, delta=-notional.\n const sqrtP = tickToSqrtPriceX96(qCurrentTick)\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const PX192 = sqrtP * sqrtP\n const PmX192 = sqrtPm * sqrtPm\n return divTrunc(-notional * (PX192 - PmX192), Q192)\n } else {\n // Numeraire loan/credit: the obligation is a constant amount of the numeraire token,\n // so its value doesn't change with price. getLegValue is mint-relative PnL (option\n // legs cancel the mint baseline via `itm`; the asset branch above returns\n // -notional*(P - Pm), which is 0 at mint), so the numeraire branch's mint-relative PnL\n // is value(P) - value(Pm) = const - const = 0. Returning a nonzero constant here would\n // shift the whole PnL curve/baseline by the notional (double-counting the credit).\n return 0n\n }\n}\n\n/**\n * Calculate the NET (user-experienced) payoff value for a width=0 (loan/credit) leg.\n *\n * Unlike `getLegValueWidth0` (debt-only), this includes the collateral/holding side and\n * therefore depends on how the position was opened:\n *\n * - **Cover at mint** (`swapAtMint = false`): the collateral is sourced in the SAME token as\n * the debt/credit, so the holding side exactly offsets it → net PnL is FLAT (0 everywhere,\n * mint-relative), regardless of which token the leg is denominated in.\n * - **Zap** (`swapAtMint = true`): the collateral is sourced in the OTHER token, leaving a\n * ±1-delta line in the asset (ETH), anchored to 0 at the mint price:\n * - USDC loan → zap to ETH: +1 (long ETH)\n * - ETH loan → zap to USDC: −1 (short ETH)\n * - USDC credit ← zap from ETH: −1 (short ETH)\n * - ETH credit ← zap from USDC: +1 (long ETH)\n *\n * @returns Net leg value in numeraire token smallest units (mint-relative PnL).\n */\nexport function getLegNetValueWidth0(\n leg: TokenIdLeg,\n m: bigint,\n qCurrentTick: bigint,\n qMintTick: bigint,\n isAssetToken0: boolean,\n swapAtMint: boolean,\n itmOffsetNotional: bigint = 0n,\n): bigint {\n // Cover at mint: collateral in the same token as the debt/credit cancels it → flat.\n if (!swapAtMint) return 0n\n\n const borrowsAsset = isCall(leg.tokenType, isAssetToken0)\n\n // ITM-neutralizing credits/loans are sized to offset an option leg's mint-time ITM,\n // which was zapped into the other token under swapAtMint and therefore carries the same\n // ±delta line this leg would otherwise add. Net the leg's notional against that ITM\n // (`itmOffsetNotional`, same token side, opposite sign) so a correctly-sized credit\n // cancels to flat and only the residual (over/under-sizing) contributes a swap line.\n const notional = computeWidth0Notional(leg, m) + itmOffsetNotional\n\n const sqrtP = tickToSqrtPriceX96(qCurrentTick)\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const PX192 = sqrtP * sqrtP\n const PmX192 = sqrtPm * sqrtPm\n\n if (borrowsAsset) {\n // Debt/credit is in the asset (ETH); zapping the collateral into the numeraire leaves the\n // debt-only asset exposure -notional*(P - Pm). (Loan → short ETH; credit → long ETH.)\n return divTrunc(-notional * (PX192 - PmX192), Q192)\n }\n\n // Debt/credit is in the numeraire (USDC); zapping sources/spends the asset (ETH). We hold\n // notional/Pm units of ETH, worth (notional/Pm)*(P - Pm) = notional*(P/Pm) - notional in\n // numeraire. (Loan → long ETH; credit → short ETH.) Zero at mint by construction.\n return divTrunc(notional * PX192, PmX192) - notional\n}\n\n/**\n * Compute the mint-time ITM (in-the-money) adjustment for an option leg.\n *\n * This is the `itm` baseline used by {@link getLegValue}: the amount by which the\n * position was already ITM at mint, expressed in the leg's natural units:\n * - Puts: numeraire units (added directly to the put's `debt*K + v` value).\n * - Calls: asset-ratio units (the call value multiplies it by price: `itm*P`/`itm*Pm`).\n *\n * Extracted so callers (e.g. {@link calculatePositionValue}) can build a per-side ITM\n * notional pool to net width=0 credit/loan legs against — an ITM-neutralizing credit\n * was sized to offset exactly this amount, so it should not add a spurious swap line.\n */\nfunction computeOptionItm(\n m: bigint,\n qStrikeTick: bigint,\n qMintTick: bigint,\n halfWidthTick: bigint,\n isPut: boolean,\n): bigint {\n if (isPut) {\n // Put ITM adjustment\n if (qMintTick < qStrikeTick - halfWidthTick) {\n // Below range: itm = (K - Pm) * m\n const sqrtK = tickToSqrtPriceX96(qStrikeTick)\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const KX192 = sqrtK * sqrtK\n const PmX192 = sqrtPm * sqrtPm\n return divTrunc(m * (KX192 - PmX192), Q192)\n } else if (qMintTick > qStrikeTick + halfWidthTick) {\n // Above range: itm = 0\n return 0n\n }\n // In range: itm = m * (sqrt(K*r) - sqrt(Pm))^2 / (r - 1)\n const sqrtKR = tickToSqrtPriceX96(qStrikeTick + halfWidthTick)\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const sqrtR = tickToSqrtPriceX96(halfWidthTick)\n const rX192 = sqrtR * sqrtR\n const diff = sqrtKR - sqrtPm // X96\n const diffSqX192 = diff * diff // X192\n return divTrunc(m * diffSqX192, rX192 - Q192)\n }\n\n // Call ITM adjustment\n if (qMintTick < qStrikeTick - halfWidthTick) {\n // Below range: itm = 0\n return 0n\n } else if (qMintTick > qStrikeTick + halfWidthTick) {\n // Above range: itm = (1 - K/Pm) * m\n const sqrtK = tickToSqrtPriceX96(qStrikeTick)\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const KX192 = sqrtK * sqrtK\n const PmX192 = sqrtPm * sqrtPm\n return divTrunc(m * (PmX192 - KX192), PmX192)\n }\n // In range: itm = m * (sqrt(r) - sqrt(K/Pm))^2 / (r - 1)\n const sqrtR = tickToSqrtPriceX96(halfWidthTick)\n const sqrtK = tickToSqrtPriceX96(qStrikeTick)\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const rX192 = sqrtR * sqrtR\n // sqrt(K/Pm) in X96 = sqrtK * 2^96 / sqrtPm\n const sqrtKPmX96 = divTrunc(sqrtK * Q96, sqrtPm)\n const diff = sqrtR - sqrtKPmX96 // X96\n const diffSqX192 = diff * diff // X192\n return divTrunc(m * diffSqX192, rX192 - Q192)\n}\n\n// --- Public Helpers ---\n\n/**\n * Check if leg is a call option (vs put).\n *\n * A call is when the leg moves the asset token:\n * - If asset is token0: call when tokenType=0\n * - If asset is token1: call when tokenType=1\n */\nexport function isCall(tokenType: bigint, isAssetToken0: boolean): boolean {\n return isAssetToken0 ? tokenType === 0n : tokenType === 1n\n}\n\n/**\n * Check if position has defined risk (is a spread).\n *\n * A position is defined risk if it has 2+ legs of the same tokenType\n * with both long and short exposure.\n */\nexport function isDefinedRisk(legs: Pick<TokenIdLeg, 'tokenType' | 'isLong'>[]): boolean {\n if (legs.length < 2) return false\n\n for (const tt of [0n, 1n]) {\n const group = legs.filter((l) => l.tokenType === tt)\n if (group.length >= 2 && group.some((l) => l.isLong) && group.some((l) => !l.isLong)) {\n return true\n }\n }\n return false\n}\n\n// --- Per-Leg Greeks ---\n\n/**\n * Calculate the value of a single leg.\n *\n * Value represents the current P&L of the position in numeraire token units.\n * Combines base value (from Panoptic's piecewise formula), debt, and ITM adjustment.\n *\n * Uses sqrtPriceX96 for all calculations to maintain precision and on-chain fidelity.\n *\n * @param leg - The leg to calculate\n * @param currentTick - Current pool tick\n * @param mintTick - Tick at position mint\n * @param positionSize - Position size in asset token smallest units\n * @param poolTickSpacing - Pool tick spacing\n * @param definedRisk - Whether position is defined risk\n * @param assetIndex - Optional override for leg.asset (0n = token0 is asset, 1n = token1)\n * @returns Leg value in numeraire token smallest units\n */\nexport function getLegValue(\n leg: TokenIdLeg,\n currentTick: bigint,\n mintTick: bigint,\n positionSize: bigint,\n poolTickSpacing: bigint,\n definedRisk: boolean,\n assetIndex?: bigint,\n swapAtMint?: boolean,\n): bigint {\n const isAssetToken0 = resolveAssetDirection(leg, assetIndex)\n const qCurrentTick = quoteTick(currentTick, isAssetToken0)\n const qMintTick = quoteTick(mintTick, isAssetToken0)\n const qStrikeTick = quoteTick(leg.strike, isAssetToken0)\n const halfWidthTick = (leg.width * poolTickSpacing) / 2n\n\n const m = leg.isLong ? -(positionSize * leg.optionRatio) : positionSize * leg.optionRatio\n\n // True loan/credit (leg.width === 0n): when the caller specifies how the position was\n // opened (swapAtMint), return the NET user-experienced payoff (Zap vs Cover) instead of\n // the debt-only value. Narrow options whose halfWidth rounds to 0 are excluded.\n if (leg.width === 0n && swapAtMint !== undefined) {\n return getLegNetValueWidth0(leg, m, qCurrentTick, qMintTick, isAssetToken0, swapAtMint)\n }\n\n // Width=0 (loans/credits): single-tick position, no range to integrate over.\n if (halfWidthTick === 0n) {\n return getLegValueWidth0(\n leg,\n m,\n qCurrentTick,\n qStrikeTick,\n qMintTick,\n isAssetToken0,\n definedRisk,\n )\n }\n\n // Compute base value: v = f(P, K, r) from Panoptic's piecewise formula\n let v: bigint\n\n if (qCurrentTick < qStrikeTick - halfWidthTick) {\n // Below range: v = m * P\n const sqrtP = tickToSqrtPriceX96(qCurrentTick)\n const PX192 = sqrtP * sqrtP\n v = divTrunc(m * PX192, Q192)\n } else if (qCurrentTick > qStrikeTick + halfWidthTick) {\n // Above range: v = m * K\n const sqrtK = tickToSqrtPriceX96(qStrikeTick)\n const KX192 = sqrtK * sqrtK\n v = divTrunc(m * KX192, Q192)\n } else {\n // In range: v = m * (2*sqrt(P*K*r) - P - K) / (r - 1)\n const sqrtP = tickToSqrtPriceX96(qCurrentTick)\n const sqrtK = tickToSqrtPriceX96(qStrikeTick)\n const sqrtPKR = tickToSqrtPriceX96(qCurrentTick + qStrikeTick + halfWidthTick)\n const sqrtR = tickToSqrtPriceX96(halfWidthTick)\n\n const PX192 = sqrtP * sqrtP\n const KX192 = sqrtK * sqrtK\n const rX192 = sqrtR * sqrtR\n\n // v = m * (2*sqrtPKR/2^96 - PX192/2^192 - KX192/2^192) / ((rX192 - 2^192)/2^192)\n // = m * (2*sqrtPKR*2^96 - PX192 - KX192) / (rX192 - 2^192)\n const numerator = m * (2n * sqrtPKR * Q96 - PX192 - KX192)\n const denominator = rX192 - Q192\n v = divTrunc(numerator, denominator)\n }\n\n const debt = -m\n const isPut = !isCall(leg.tokenType, isAssetToken0)\n\n // Compute ITM adjustment (differs for puts vs calls)\n const itm = computeOptionItm(m, qStrikeTick, qMintTick, halfWidthTick, isPut)\n\n // Compute final result based on option type\n if (isPut) {\n // Put: result = debt * K + v + itm\n const sqrtK = tickToSqrtPriceX96(qStrikeTick)\n const KX192 = sqrtK * sqrtK\n const debtK = divTrunc(debt * KX192, Q192)\n return debtK + v + itm\n } else {\n // Call: result = debt*P + v + itm*Pm (if defined risk) or debt*P + v + itm*P (if not)\n const sqrtP = tickToSqrtPriceX96(qCurrentTick)\n const PX192 = sqrtP * sqrtP\n const debtP = divTrunc(debt * PX192, Q192)\n\n if (definedRisk) {\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const PmX192 = sqrtPm * sqrtPm\n const itmPm = divTrunc(itm * PmX192, Q192)\n return debtP + v + itmPm\n } else {\n const itmP = divTrunc(itm * PX192, Q192)\n return debtP + v + itmP\n }\n }\n}\n\n/**\n * Calculate the delta of a single leg.\n *\n * Delta is the rate of change of position value with respect to price.\n * For puts: delta = vDelta\n * For calls: delta = debtDelta + vDelta + itmDelta (if not defined risk)\n *\n * Uses sqrtPriceX96 for all price calculations to maintain precision.\n *\n * @param leg - The leg to calculate\n * @param currentTick - Current pool tick\n * @param positionSize - Position size in asset token smallest units\n * @param poolTickSpacing - Pool tick spacing\n * @param mintTick - Tick at mint (optional, for ITM adjustment)\n * @param definedRisk - Whether position is defined risk\n * @param assetIndex - Optional override for leg.asset (0n = token0 is asset, 1n = token1)\n * @returns Leg delta in asset token smallest units\n */\nexport function getLegDelta(\n leg: TokenIdLeg,\n currentTick: bigint,\n positionSize: bigint,\n poolTickSpacing: bigint,\n mintTick: bigint | undefined,\n definedRisk: boolean,\n assetIndex?: bigint,\n): bigint {\n const isAssetToken0 = resolveAssetDirection(leg, assetIndex)\n const qCurrentTick = quoteTick(currentTick, isAssetToken0)\n const qStrikeTick = quoteTick(leg.strike, isAssetToken0)\n const halfWidthTick = (leg.width * poolTickSpacing) / 2n\n\n const m = leg.isLong ? -(positionSize * leg.optionRatio) : positionSize * leg.optionRatio\n\n // True loan/credit: leg.width === 0n (not just halfWidth rounding to 0).\n // Debt-side exposure only — no option-like piecewise formula.\n if (leg.width === 0n) {\n const borrowsAsset = isAssetToken0 ? leg.tokenType === 0n : leg.tokenType === 1n\n if (!borrowsAsset) return 0n\n // See getLegValueWidth0 for the notional-scaling rationale.\n if (leg.asset === leg.tokenType) return -m\n const signedStrike = leg.asset === 0n ? leg.strike : -leg.strike\n const sqrtKraw = tickToSqrtPriceX96(signedStrike)\n const KrawX192 = sqrtKraw * sqrtKraw\n const notional = divTrunc(m * KrawX192, Q192)\n return -notional\n }\n\n // Narrow option whose halfWidth rounds to 0: use option-like width=0 branch\n if (halfWidthTick === 0n) {\n const vDelta = qCurrentTick <= qStrikeTick ? m : 0n\n const isPut = !isCall(leg.tokenType, isAssetToken0)\n if (isPut) return vDelta\n\n // Call: add debt delta and ITM delta (same as normal path but no in-range branch)\n const debtDelta = -m\n let itmDelta = 0n\n if (mintTick !== undefined && !definedRisk) {\n const qMintTick = quoteTick(mintTick, isAssetToken0)\n if (qMintTick > qStrikeTick) {\n const sqrtPm = tickToSqrtPriceX96(qMintTick)\n const sqrtK = tickToSqrtPriceX96(qStrikeTick)\n const PmX192 = sqrtPm * sqrtPm\n const KX192 = sqrtK * sqrtK\n itmDelta = divTrunc((PmX192 - KX192) * m, PmX192)\n }\n }\n return definedRisk ? debtDelta + vDelta : debtDelta + vDelta + itmDelta\n }\n\n // Compute vDelta: derivative of value with respect to price\n // vDelta = P < lo ? m : P > hi ? 0 : (m * (sqrt(K*r)/sqrt(P) - 1)) / (r - 1)\n let vDelta: bigint\n\n if (qCurrentTick < qStrikeTick - halfWidthTick) {\n // Below range: vDelta = m\n vDelta = m\n } else if (qCurrentTick > qStrikeTick + halfWidthTick) {\n // Above range: vDelta = 0\n vDelta = 0n\n } else {\n // In range: vDelta = m * (sqrt(K*r) - sqrt(P)) / (sqrt(P) * (r - 1))\n const sqrtP = tickToSqrtPriceX96(qCurrentTick) // X96\n const sqrtKR = tickToSqrtPriceX96(qStrikeTick + halfWidthTick) // sqrt(K*r) in X96\n const sqrtR = tickToSqrtPriceX96(halfWidthTick) // X96\n const rX192 = sqrtR * sqrtR // X192\n\n // vDelta = m * (sqrtKR - sqrtP)/2^96 / (sqrtP/2^96 * (rX192 - 2^192)/2^192)\n // = m * (sqrtKR - sqrtP) * 2^192 / (sqrtP * (rX192 - 2^192))\n const numerator = m * (sqrtKR - sqrtP) * Q192\n const denominator = sqrtP * (rX192 - Q192)\n vDelta = divTrunc(numerator, denominator)\n }\n\n const isPut = !isCall(leg.tokenType, isAssetToken0)\n\n if (isPut) {\n return vDelta\n }\n\n // Call: add debt delta and ITM delta\n const debtDelta = -m\n\n const itmDelta =\n mintTick === undefined\n ? 0n\n : (() => {\n const qMintTick = quoteTick(mintTick, isAssetToken0)\n\n if (qMintTick < qStrikeTick - halfWidthTick) {\n // Below range: itmDelta = 0\n return 0n\n } else if (qMintTick > qStrikeTick + halfWidthTick) {\n // Above range: itmDelta = (1 - K/Pm) * m = (Pm - K) * m / Pm\n const sqrtPm = tickToSqrtPriceX96(qMintTick) // X96\n const sqrtK = tickToSqrtPriceX96(qStrikeTick) // X96\n const PmX192 = sqrtPm * sqrtPm // X192\n const KX192 = sqrtK * sqrtK // X192\n\n // itmDelta = (1 - K/Pm) * m = (PmX192 - KX192) * m / PmX192\n return divTrunc((PmX192 - KX192) * m, PmX192)\n } else {\n // In range: itmDelta = m * (sqrt(r) - sqrt(K/Pm))^2 / (r - 1)\n const sqrtR = tickToSqrtPriceX96(halfWidthTick) // X96\n const sqrtK = tickToSqrtPriceX96(qStrikeTick) // X96\n const sqrtPm = tickToSqrtPriceX96(qMintTick) // X96\n const rX192 = sqrtR * sqrtR // X192\n\n // sqrt(K/Pm) = sqrtK / sqrtPm (both X96, so scale cancels)\n // But we need (sqrt(r) - sqrt(K/Pm))^2, so work in X96:\n // sqrtKPm = sqrt(K/Pm) in X96 = sqrtK * 2^96 / sqrtPm\n const sqrtKPmX96 = (sqrtK * Q96) / sqrtPm // X96\n\n // (sqrt(r) - sqrt(K/Pm))^2 = (sqrtR - sqrtKPmX96)^2 / 2^192\n const diff = sqrtR - sqrtKPmX96 // X96\n const diffSqX192 = diff * diff // X192\n\n // itmDelta = m * diffSqX192 / 2^192 / (rX192 / 2^192 - 1)\n // = m * diffSqX192 / (rX192 - 2^192)\n return divTrunc(m * diffSqX192, rX192 - Q192)\n }\n })()\n\n return definedRisk ? debtDelta + vDelta : debtDelta + vDelta + itmDelta\n}\n\n/** Convert a delta between token frames at the current pool tick. */\nexport function toVaultFrameAtTick(\n delta: bigint,\n fromAsset: bigint,\n vaultAssetIndex: 0n | 1n,\n currentTick: bigint,\n flipSignOnAssetInversion = false,\n): bigint {\n if (fromAsset === vaultAssetIndex) return delta\n const sqrtPriceX96 = tickToSqrtPriceX96(currentTick)\n const converted =\n vaultAssetIndex === 0n\n ? (delta * Q192) / (sqrtPriceX96 * sqrtPriceX96)\n : (delta * sqrtPriceX96 * sqrtPriceX96) / Q192\n return flipSignOnAssetInversion ? -converted : converted\n}\n\n/**\n * Calculate one leg's wallet-aware delta in the vault asset frame.\n *\n * Width-zero loans and credits must be evaluated directly in the vault frame.\n * Option legs remain in their natural leg frame until converted at the mark tick.\n */\nexport function getLegDeltaInVaultFrame(\n leg: TokenIdLeg,\n currentTick: bigint,\n positionSize: bigint,\n poolTickSpacing: bigint,\n mintTick: bigint | undefined,\n definedRisk: boolean,\n vaultAssetIndex: 0n | 1n,\n): bigint {\n if (leg.width === 0n) {\n return getLegDelta(\n leg,\n currentTick,\n positionSize,\n poolTickSpacing,\n mintTick,\n definedRisk,\n vaultAssetIndex,\n )\n }\n\n const legDelta = getLegDelta(\n leg,\n currentTick,\n positionSize,\n poolTickSpacing,\n mintTick,\n definedRisk,\n )\n return toVaultFrameAtTick(legDelta, leg.asset, vaultAssetIndex, currentTick, true)\n}\n\n/**\n * Calculate the gamma (dollar gamma) of a single leg.\n *\n * Formula: gamma = (m * sqrt(K * P * r)) / (2 * (r - 1))\n * where:\n * - m = positionSize * optionRatio (with sign based on long/short)\n * - K = strike price (numeraire/asset)\n * - P = current price (numeraire/asset)\n * - r = 1.0001^(width*tickSpacing/2) ≈ 1 (dimensionless ratio)\n *\n * Uses sqrtPriceX96 arithmetic:\n * - sqrt(K*P*r) = tickToSqrtPriceX96(strikeₜ + currentₜ + widthₜ/2)\n * - Keeps X96/X192 precision until final division\n *\n * @param leg - The leg to calculate\n * @param currentTick - Current pool tick\n * @param positionSize - Position size in asset token smallest units\n * @param poolTickSpacing - Pool tick spacing\n * @param assetIndex - Optional override for leg.asset (0n = token0 is asset, 1n = token1)\n * @returns Leg gamma in numeraire token smallest units\n */\nexport function getLegGamma(\n leg: TokenIdLeg,\n currentTick: bigint,\n positionSize: bigint,\n poolTickSpacing: bigint,\n assetIndex?: bigint,\n): bigint {\n const isAssetToken0 = resolveAssetDirection(leg, assetIndex)\n\n // Convert to quote-denominated ticks (negate if asset is token0)\n const qCurrentTick = quoteTick(currentTick, isAssetToken0)\n const qStrikeTick = quoteTick(leg.strike, isAssetToken0)\n const halfWidthTick = (leg.width * poolTickSpacing) / 2n\n\n // True loan: no gamma\n if (leg.width === 0n) return 0n\n\n // Narrow option whose halfWidth rounds to 0: no curvature (denominator 2*(r-1)=0)\n if (halfWidthTick === 0n) return 0n\n\n // Range check: gamma is zero outside [strike - halfWidth, strike + halfWidth]\n // This works in both normal and inverted tick space\n if (qCurrentTick < qStrikeTick - halfWidthTick || qCurrentTick > qStrikeTick + halfWidthTick) {\n return 0n\n }\n\n // Position size with sign: gamma uses inverted multiplier (long = positive, short = negative)\n const m = leg.isLong ? positionSize * leg.optionRatio : -(positionSize * leg.optionRatio)\n\n // sqrt(K * P * r) using tick addition: sqrt(K*P*r) = sqrt(1.0001^(K_tick + P_tick + r_tick))\n const sqrtKPR = tickToSqrtPriceX96(qStrikeTick + qCurrentTick + halfWidthTick) // X96 scale\n\n // r = 1.0001^(halfWidthTick), compute as (sqrtR)^2 to maintain precision\n const sqrtR = tickToSqrtPriceX96(halfWidthTick) // X96 scale\n const rX192 = sqrtR * sqrtR // X192 scale: r * 2^192\n\n // gamma = m * sqrt(K*P*r) / (2 * (r - 1))\n // = m * (sqrtKPR / 2^96) / (2 * (rX192/2^192 - 1))\n // = m * sqrtKPR * 2^192 / (2^96 * 2 * (rX192 - 2^192))\n // = m * sqrtKPR * 2^96 / (2 * (rX192 - 2^192))\n const numerator = m * sqrtKPR * Q96 // [asset] * [numeraire/asset * 2^96] * 2^96 = [numeraire * 2^192]\n const denominator = 2n * (rX192 - Q192) // 2 * (r - 1) in X192 scale\n\n return divTrunc(numerator, denominator) // [numeraire]\n}\n\n// --- Position-Level Aggregates ---\n\n/**\n * Parameters for position-level greek calculations.\n */\nexport interface PositionGreeksInput {\n /** Position legs */\n legs: TokenIdLeg[]\n /** Current pool tick */\n currentTick: bigint\n /** Tick at position mint */\n mintTick: bigint\n /** Position size in asset token smallest units */\n positionSize: bigint\n /** Pool tick spacing */\n poolTickSpacing: bigint\n /** Optional override for leg.asset on all legs (0n = token0 is asset, 1n = token1) */\n assetIndex?: bigint\n /**\n * How width=0 (loan/credit) legs were opened. When provided, `calculatePositionValue`\n * returns the NET user-experienced payoff for those legs (Zap = ±1 line, Cover = flat)\n * instead of the debt-only value. Leave undefined for delta/greeks aggregation, which\n * accounts for the held collateral separately.\n */\n swapAtMint?: boolean\n}\n\n/**\n * Calculate total value across all legs.\n */\nexport function calculatePositionValue(input: PositionGreeksInput): bigint {\n return preparePositionValue(input)(input.currentTick)\n}\n\n/** Prepare mint-time invariants once for an arbitrary series of valuation ticks. */\nexport function preparePositionValue(input: Omit<PositionGreeksInput, 'currentTick'>) {\n const { legs, mintTick, positionSize, poolTickSpacing, assetIndex, swapAtMint } = input\n const definedRisk = isDefinedRisk(legs)\n\n // Fast path: without swapAtMint there is no width=0 net-payoff (delta/greeks aggregation),\n // so no ITM netting is needed — value each leg independently.\n if (swapAtMint === undefined) {\n return (currentTick: bigint) =>\n legs.reduce(\n (sum, leg) =>\n sum +\n getLegValue(\n leg,\n currentTick,\n mintTick,\n positionSize,\n poolTickSpacing,\n definedRisk,\n assetIndex,\n swapAtMint,\n ),\n 0n,\n )\n }\n\n // Pass 1: accumulate each option leg's mint-time ITM into a per-side notional pool. Under\n // swapAtMint the ITM was zapped into the other token, so a width=0 credit/loan that was\n // created to neutralize it (see getLegNetValueWidth0) should net against this pool instead\n // of adding a duplicate swap line. Puts contribute numeraire ITM; calls contribute asset ITM.\n let numeraireItmPool = 0n\n let assetItmPool = 0n\n for (const leg of legs) {\n const halfWidthTick = (leg.width * poolTickSpacing) / 2n\n if (leg.width === 0n || halfWidthTick === 0n) continue // not a valued option leg\n const isAssetToken0 = resolveAssetDirection(leg, assetIndex)\n const qStrikeTick = quoteTick(leg.strike, isAssetToken0)\n const qMintTick = quoteTick(mintTick, isAssetToken0)\n const m = leg.isLong ? -(positionSize * leg.optionRatio) : positionSize * leg.optionRatio\n const isPut = !isCall(leg.tokenType, isAssetToken0)\n const itm = computeOptionItm(m, qStrikeTick, qMintTick, halfWidthTick, isPut)\n if (isPut) numeraireItmPool += itm\n else assetItmPool += itm\n }\n\n const initialNumeraireItm = numeraireItmPool\n const initialAssetItm = assetItmPool\n return (currentTick: bigint) => {\n let numeraireItmPool = initialNumeraireItm\n let assetItmPool = initialAssetItm\n // Each tick consumes its own copy of the mint-time pools.\n let sum = 0n\n for (const leg of legs) {\n if (leg.width === 0n) {\n const isAssetToken0 = resolveAssetDirection(leg, assetIndex)\n const borrowsAsset = isCall(leg.tokenType, isAssetToken0)\n const offset = borrowsAsset ? assetItmPool : numeraireItmPool\n if (borrowsAsset) assetItmPool = 0n\n else numeraireItmPool = 0n\n const qCurrentTick = quoteTick(currentTick, isAssetToken0)\n const qMintTick = quoteTick(mintTick, isAssetToken0)\n const m = leg.isLong ? -(positionSize * leg.optionRatio) : positionSize * leg.optionRatio\n sum += getLegNetValueWidth0(\n leg,\n m,\n qCurrentTick,\n qMintTick,\n isAssetToken0,\n swapAtMint,\n offset,\n )\n } else {\n sum += getLegValue(\n leg,\n currentTick,\n mintTick,\n positionSize,\n poolTickSpacing,\n definedRisk,\n assetIndex,\n swapAtMint,\n )\n }\n }\n return sum\n }\n}\n\n/** Value a tick series without repeating position preparation. */\nexport function calculatePositionValues(\n input: Omit<PositionGreeksInput, 'currentTick'>,\n ticks: readonly bigint[],\n): bigint[] {\n return ticks.map(preparePositionValue(input))\n}\n\n/**\n * Calculate total delta across all legs.\n */\nexport function calculatePositionDelta(input: PositionGreeksInput): bigint {\n const { legs, currentTick, mintTick, positionSize, poolTickSpacing, assetIndex } = input\n const definedRisk = isDefinedRisk(legs)\n\n return legs.reduce(\n (sum, leg) =>\n sum +\n getLegDelta(\n leg,\n currentTick,\n positionSize,\n poolTickSpacing,\n mintTick,\n definedRisk,\n assetIndex,\n ),\n 0n,\n )\n}\n\n/**\n * Calculate debt-only position delta in a single target asset frame.\n *\n * Option legs are first valued in their natural `leg.asset` frame, then\n * converted into `assetIndex` using the current pool price. Width-zero legs\n * are evaluated directly in the target frame.\n *\n * Width=0 loan/credit legs include only their debt obligation. The held-token\n * side must be added separately from account collateral balances, preventing a\n * zap from being counted once in the position and again in collateral.\n */\nexport function calculatePositionDeltaDebtOnly(\n input: Omit<PositionGreeksInput, 'assetIndex' | 'swapAtMint'> & {\n assetIndex: 0n | 1n\n },\n): bigint {\n const { legs, currentTick, mintTick, positionSize, poolTickSpacing, assetIndex } = input\n const definedRisk = isDefinedRisk(legs)\n\n return legs.reduce(\n (sum, leg) =>\n sum +\n getLegDeltaInVaultFrame(\n leg,\n currentTick,\n positionSize,\n poolTickSpacing,\n mintTick,\n definedRisk,\n assetIndex,\n ),\n 0n,\n )\n}\n\n/** Delta and one strategy contract's notional, both in the requested asset frame. */\nexport function getPositionDeltaMetrics(\n input: Omit<PositionGreeksInput, 'assetIndex' | 'swapAtMint'> & { assetIndex: 0n | 1n },\n) {\n const orderedLegs = [...input.legs].sort((a, b) =>\n a.index < b.index ? -1 : a.index > b.index ? 1 : 0,\n )\n const nativeLeg = orderedLegs.find((leg) => leg.width > 0n) ?? orderedLegs[0]\n return {\n delta: calculatePositionDeltaDebtOnly(input),\n // Ratios belong to the strategy's exposure, not its number of contracts.\n contractSize: nativeLeg\n ? toVaultFrameAtTick(input.positionSize, nativeLeg.asset, input.assetIndex, input.currentTick)\n : 0n,\n }\n}\n\n/**\n * Calculate total gamma across all legs.\n */\nexport function calculatePositionGamma(input: PositionGreeksInput): bigint {\n const { legs, currentTick, positionSize, poolTickSpacing, assetIndex } = input\n\n return legs.reduce(\n (sum, leg) => sum + getLegGamma(leg, currentTick, positionSize, poolTickSpacing, assetIndex),\n 0n,\n )\n}\n\n/**\n * Position greeks result.\n */\nexport interface PositionGreeksResult {\n /** Position value in numeraire token smallest units */\n value: bigint\n /** Position delta in asset token smallest units */\n delta: bigint\n /** Position gamma in numeraire token smallest units */\n gamma: bigint\n}\n\n/**\n * Calculate all greeks for a position.\n */\nexport function calculatePositionGreeks(input: PositionGreeksInput): PositionGreeksResult {\n return {\n value: calculatePositionValue(input),\n delta: calculatePositionDelta(input),\n gamma: calculatePositionGamma(input),\n }\n}\n\n// --- Portfolio (Multi-Position) Aggregates ---\n\n/**\n * Aggregate value across multiple independent positions.\n *\n * Each entry is valued with its OWN `positionSize`, `mintTick`, and legs, then\n * summed. Do NOT collapse multiple positions into one synthetic `PositionGreeksInput`\n * with a shared `positionSize` — `m = positionSize * optionRatio` is per-position, so a\n * shared size double-counts (and integer `optionRatio` cannot encode fractional shares).\n *\n * @param positions - One `PositionGreeksInput` per open position\n * @returns Total value in numeraire token smallest units\n */\nexport function calculatePortfolioValue(positions: PositionGreeksInput[]): bigint {\n return positions.reduce((sum, input) => sum + calculatePositionValue(input), 0n)\n}\n\n/**\n * Aggregate delta across multiple independent positions.\n *\n * See {@link calculatePortfolioValue} for why each position must keep its own\n * `positionSize` rather than being merged into one synthetic position.\n *\n * @param positions - One `PositionGreeksInput` per open position\n * @returns Total delta in asset token smallest units\n */\nexport function calculatePortfolioDelta(positions: PositionGreeksInput[]): bigint {\n return positions.reduce((sum, input) => sum + calculatePositionDelta(input), 0n)\n}\n\n/**\n * Aggregate gamma across multiple independent positions.\n *\n * See {@link calculatePortfolioValue} for why each position must keep its own\n * `positionSize` rather than being merged into one synthetic position.\n *\n * @param positions - One `PositionGreeksInput` per open position\n * @returns Total gamma in numeraire token smallest units\n */\nexport function calculatePortfolioGamma(positions: PositionGreeksInput[]): bigint {\n return positions.reduce((sum, input) => sum + calculatePositionGamma(input), 0n)\n}\n\n/**\n * Calculate all greeks aggregated across multiple independent positions.\n */\nexport function calculatePortfolioGreeks(positions: PositionGreeksInput[]): PositionGreeksResult {\n return {\n value: calculatePortfolioValue(positions),\n delta: calculatePortfolioDelta(positions),\n gamma: calculatePortfolioGamma(positions),\n }\n}\n\n// --- Loan/Credit Swap-Aware Delta ---\n\n/**\n * Calculate the effective delta of a loan leg accounting for swapAtMint.\n *\n * A loan borrows one token and (optionally) swaps it for the other at mint.\n * The net delta depends on whether the swap occurred:\n *\n * | Scenario | Result |\n * |-----------------------|-------------------------------------------------|\n * | No swap | 0n (hold what you owe, net zero) |\n * | Swap + borrows asset | -m (hold numeraire, owe asset → short exposure) |\n * | Swap + borrows numer. | +m (hold asset, owe numeraire → long exposure) |\n *\n * Only meaningful for legs with `width === 0n`. For options, use `getLegDelta`.\n *\n * @param leg - The loan leg\n * @param positionSize - Position size in asset token smallest units\n * @param swapAtMint - Whether the borrowed tokens were swapped at mint\n * @param assetIndex - Optional override for leg.asset (0n = token0 is asset)\n * @returns Effective delta in asset token smallest units\n */\nexport function getLoanEffectiveDelta(\n leg: TokenIdLeg,\n positionSize: bigint,\n swapAtMint: boolean,\n assetIndex?: bigint,\n): bigint {\n if (!swapAtMint) return 0n\n\n const isAssetToken0 = resolveAssetDirection(leg, assetIndex)\n const m = leg.isLong ? -(positionSize * leg.optionRatio) : positionSize * leg.optionRatio\n const borrowsAsset = isAssetToken0 ? leg.tokenType === 0n : leg.tokenType === 1n\n\n return borrowsAsset ? -m : m\n}\n\n/**\n * Calculate total delta for a position, using swap-aware delta for loan legs.\n *\n * For legs with `width === 0n` (loans/credits), uses `getLoanEffectiveDelta`\n * which accounts for the swapAtMint flag. For option legs (`width > 0n`),\n * uses the standard `getLegDelta`.\n *\n * @param input - Position greeks input plus swapAtMint flag\n * @returns Total delta in asset token smallest units\n */\nexport function calculatePositionDeltaWithSwap(\n input: PositionGreeksInput & { swapAtMint: boolean },\n): bigint {\n const { legs, currentTick, mintTick, positionSize, poolTickSpacing, assetIndex, swapAtMint } =\n input\n const optionLegs = legs.filter((l) => l.width !== 0n)\n const definedRisk = isDefinedRisk(optionLegs)\n\n return legs.reduce((sum, leg) => {\n if (leg.width === 0n) {\n return sum + getLoanEffectiveDelta(leg, positionSize, swapAtMint, assetIndex)\n }\n return (\n sum +\n getLegDelta(\n leg,\n currentTick,\n positionSize,\n poolTickSpacing,\n mintTick,\n definedRisk,\n assetIndex,\n )\n )\n }, 0n)\n}\n","import type { Address, Hex } from 'viem'\n\nimport { DEFAULT_VEGOID } from '../tokenId/constants'\n\nexport const vegoid = Number(DEFAULT_VEGOID)\n\nexport interface LegParams {\n index: number\n width: bigint\n optionRatio: bigint\n asset: bigint\n strike: bigint\n isLong: bigint // 0 if short, 1 if long\n tokenType: bigint // Which token (0|1 in underlying pool) is being moved\n riskPartner: bigint\n}\n\nexport const areLegsEqual = (leg1: LegParams, leg2: LegParams): boolean => {\n return (\n leg1.width === leg2.width &&\n leg1.optionRatio === leg2.optionRatio &&\n leg1.asset === leg2.asset &&\n leg1.strike === leg2.strike &&\n leg1.isLong === leg2.isLong &&\n leg1.tokenType === leg2.tokenType &&\n leg1.riskPartner === leg2.riskPartner\n )\n}\n\nexport const stringifyLeg = (leg: LegParams): string => {\n return `Index: ${leg.index} | Width: ${leg.width.toString()} | OptionRatio: ${leg.optionRatio.toString()} | Asset: ${leg.asset.toString()} | Strike: ${leg.strike.toString()} | IsLong?: ${leg.isLong.toString()} | Token Type: ${leg.tokenType.toString()} | Risk Partner: ${leg.riskPartner.toString()}`\n}\n\n// Synthetic TokenIds padding constant\nexport const SYNTH_TOKENID_PADDING = BigInt(\n '115792089237316195423570985007226406215939081747436879206741300988257197096960',\n)\n\nconst POOL_ID_SIZE = 64n\nconst VEGOID_STARTING_BIT = 40n\nconst VEGOID_SIZE = 8n\nconst TICK_SPACING_STARTING_BIT = 48n\nconst ASSET_STARTING_BIT = 0n\nconst ASSET_SIZE = 1n\nconst RATIO_STARTING_BIT = ASSET_STARTING_BIT + ASSET_SIZE // 0 + 1\nconst RATIO_SIZE = 7n\nconst IS_LONG_STARTING_BIT = RATIO_STARTING_BIT + RATIO_SIZE // 1 + 7\nconst IS_LONG_SIZE = 1n\nconst TOKEN_TYPE_STARTING_BIT = IS_LONG_STARTING_BIT + IS_LONG_SIZE // 8 + 1\nconst TOKEN_TYPE_SIZE = 1n\nconst RISK_PARTNER_STARTING_BIT = TOKEN_TYPE_STARTING_BIT + TOKEN_TYPE_SIZE // 9 + 1\nconst RISK_PARTNER_SIZE = 2n\nconst STRIKE_STARTING_BIT = RISK_PARTNER_STARTING_BIT + RISK_PARTNER_SIZE // 10 + 2\nconst STRIKE_SIZE = 24n\nconst WIDTH_STARTING_BIT = STRIKE_STARTING_BIT + STRIKE_SIZE // 12 + 24\nconst WIDTH_SIZE = 12n\nconst LEG_SIZE = WIDTH_STARTING_BIT + WIDTH_SIZE // 36 + 12 = 48\n\n// converts unsigned strike to signed for encoding\nexport const convertStrike = (n: bigint): bigint => {\n if (n < 0n) {\n // 3 bytes because strike is int24\n return 16777216n + n\n } else {\n return n\n }\n}\n\n// converts encoded (unsigned) strike back to signed\nexport const signStrike = (encodedStrike: bigint): bigint => {\n if (encodedStrike > 2n ** 23n) {\n return encodedStrike - 16777216n\n }\n return encodedStrike\n}\n\nconst getLegOffsetByIndex = (index: bigint): bigint => index * LEG_SIZE\n\nconst encodeAsset = (asset: bigint, legIndex: bigint): bigint =>\n asset << (getLegOffsetByIndex(legIndex) + ASSET_STARTING_BIT + POOL_ID_SIZE)\n\nconst encodeRatio = (optionRatio: bigint, legIndex: bigint): bigint =>\n optionRatio << (getLegOffsetByIndex(legIndex) + RATIO_STARTING_BIT + POOL_ID_SIZE)\n\nconst encodeIsLong = (isLong: bigint, legIndex: bigint): bigint =>\n isLong << (getLegOffsetByIndex(legIndex) + IS_LONG_STARTING_BIT + POOL_ID_SIZE)\n\nconst encodeTokenType = (tokenType: bigint, legIndex: bigint): bigint =>\n tokenType << (getLegOffsetByIndex(legIndex) + TOKEN_TYPE_STARTING_BIT + POOL_ID_SIZE)\n\nconst encodeRiskPartner = (riskPartner: bigint, legIndex: bigint): bigint =>\n riskPartner << (getLegOffsetByIndex(legIndex) + RISK_PARTNER_STARTING_BIT + POOL_ID_SIZE)\n\nconst encodeStrike = (strike: bigint, legIndex: bigint): bigint =>\n convertStrike(strike) << (getLegOffsetByIndex(legIndex) + STRIKE_STARTING_BIT + POOL_ID_SIZE)\n\nconst encodeWidth = (width: bigint, legIndex: bigint): bigint =>\n width << (getLegOffsetByIndex(legIndex) + WIDTH_STARTING_BIT + POOL_ID_SIZE)\n\nconst decodeAsset = (leg: bigint): bigint => leg % (1n << ASSET_SIZE)\n\nconst decodeRatio = (leg: bigint): bigint => (leg >> RATIO_STARTING_BIT) % (1n << RATIO_SIZE)\n\nconst decodeIsLong = (leg: bigint): bigint => (leg >> IS_LONG_STARTING_BIT) % (1n << IS_LONG_SIZE)\n\nconst decodeTokenType = (leg: bigint): bigint =>\n (leg >> TOKEN_TYPE_STARTING_BIT) % (1n << TOKEN_TYPE_SIZE)\n\nconst decodeRiskPartner = (leg: bigint): bigint =>\n (leg >> RISK_PARTNER_STARTING_BIT) % (1n << RISK_PARTNER_SIZE)\n\nconst decodeStrike = (leg: bigint): bigint =>\n signStrike((leg >> STRIKE_STARTING_BIT) % (1n << STRIKE_SIZE))\n\nconst decodeWidth = (leg: bigint): bigint => (leg >> WIDTH_STARTING_BIT) % (1n << WIDTH_SIZE)\n\n/**\n * Extract vegoid from a TokenId\n * Vegoid is stored in bits 40-47 (8 bits) of the poolId\n */\nexport const decodeVegoid = (tokenId: bigint): bigint => {\n return ((tokenId % (1n << POOL_ID_SIZE)) >> VEGOID_STARTING_BIT) % (1n << VEGOID_SIZE)\n}\n\n/**\n * Extract vegoid from a poolId\n * Vegoid is stored in bits 40-47 (8 bits) of the poolId\n */\nexport const decodeVegoidFromPoolId = (poolId: bigint): bigint => {\n return (poolId >> VEGOID_STARTING_BIT) % (1n << VEGOID_SIZE)\n}\n\n/**\n * Extract tickSpacing from a TokenId\n * TickSpacing is stored in bits 48-63 (16 bits) of the poolId\n */\nexport const decodeTickSpacing = (tokenId: bigint): bigint => {\n return (tokenId % (1n << POOL_ID_SIZE)) >> TICK_SPACING_STARTING_BIT\n}\n\n/**\n * Encode poolId with vegoid support\n * The encoded PoolId structure: [16-bit tickSpacing][8-bit vegoid][40-bit pool address]\n * @param address The Uniswap V3 pool address (hex string)\n * @param tickSpacing The tick spacing of the pool\n * @param vegoidValue The vegoid value (defaults to 4 if not provided)\n * @return The encoded poolId as bigint\n */\nexport const encodePoolId = (\n address: Address,\n tickSpacing: bigint,\n vegoidValue: bigint = BigInt(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) = 8 bytes\n // All in little-endian format\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 |= (vegoidValue % 256n) << 40n\n\n // Add tickSpacing at bit 48\n poolId |= (tickSpacing % 65536n) << 48n\n\n return poolId\n}\n\n/**\n * Encode V4 poolId with vegoid support\n * The encoded PoolId structure: [16-bit tickSpacing][8-bit vegoid][40-bit pool pattern]\n * @param poolId The V4 pool ID (bytes32 hex string)\n * @param tickSpacing The tick spacing of the pool\n * @param vegoidValue The vegoid value (defaults to 4 if not provided)\n * @return The encoded poolId as bigint\n */\nexport const encodeV4PoolId = (\n poolId: Hex,\n tickSpacing: bigint,\n vegoidValue: bigint = BigInt(vegoid),\n): bigint => {\n // Remove 0x prefix and get last 10 hex chars (5 bytes = 40 bits)\n const poolIdHex = poolId.slice(2)\n const last5BytesHex = poolIdHex.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: pool pattern (5 bytes) + vegoid (1 byte) + tickSpacing (2 bytes) = 8 bytes\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 |= (vegoidValue % 256n) << 40n\n\n // Add tickSpacing at bit 48\n encodedPoolId |= (tickSpacing % 65536n) << 48n\n\n return encodedPoolId\n}\n\n// Can be (ab)used to create a leg id by passing in a tokenId of 0\nexport const addLeg = (tokenId: bigint, leg: LegParams): bigint => {\n const legIndex = BigInt(leg.index)\n const width = leg.width\n const strike = leg.strike\n const riskPartner = leg.riskPartner\n const tokenType = leg.tokenType\n const isLong = leg.isLong\n const optionRatio = leg.optionRatio\n const asset = leg.asset\n\n return (\n tokenId +\n encodeWidth(width, legIndex) +\n encodeStrike(strike, legIndex) +\n (encodeRiskPartner(riskPartner, legIndex) |\n encodeTokenType(tokenType, legIndex) |\n encodeIsLong(isLong, legIndex) |\n encodeRatio(optionRatio, legIndex) |\n encodeAsset(asset, legIndex))\n )\n}\n\nexport const encodePosition = (poolId: bigint, legs: LegParams[]): bigint => {\n return legs.reduce((acc, leg) => addLeg(acc, leg), poolId)\n}\n\nexport interface Position {\n poolId: string\n legs: LegParams[]\n}\n\nexport const decodePosition = (encodedPosition: bigint): Position => {\n const leg4 = (encodedPosition >> (POOL_ID_SIZE + getLegOffsetByIndex(3n))) % (1n << LEG_SIZE)\n\n const leg3 = (encodedPosition >> (POOL_ID_SIZE + getLegOffsetByIndex(2n))) % (1n << LEG_SIZE)\n\n const leg2 = (encodedPosition >> (POOL_ID_SIZE + getLegOffsetByIndex(1n))) % (1n << LEG_SIZE)\n\n const leg1 = (encodedPosition >> (POOL_ID_SIZE + getLegOffsetByIndex(0n))) % (1n << LEG_SIZE)\n\n let poolId = (encodedPosition % (1n << POOL_ID_SIZE)).toString(16)\n\n const poolIdLength = 16 // poolId is 64 bits => 16 hex characters\n if (poolId.length < poolIdLength) {\n poolId = padHexWithZeros('0x' + poolId, poolIdLength + 2) // +2 for 0x prefix\n } else {\n poolId = '0x' + poolId\n }\n\n const encodedLegs = [leg1, leg2, leg3, leg4].filter((leg) => decodeRatio(leg) > 0n)\n\n const legs: LegParams[] = encodedLegs.map((leg, index) => ({\n index: index,\n width: decodeWidth(leg),\n strike: decodeStrike(leg),\n riskPartner: decodeRiskPartner(leg),\n tokenType: decodeTokenType(leg),\n isLong: decodeIsLong(leg),\n optionRatio: decodeRatio(leg),\n asset: decodeAsset(leg),\n }))\n\n return {\n poolId,\n legs,\n }\n}\n\nexport function padHexWithZeros(hex: string, length: number): string {\n // Check if the hex starts with \"0x\"\n if (hex.startsWith('0x')) {\n // Remove the \"0x\" prefix\n hex = hex.substring(2)\n } else {\n throw new Error('do not use padHexWithZeros on non-hex strings')\n }\n\n // Subtract 2 from length to account for the substring(2) call to remove the leading 0x\n while (hex.length < length - 2) {\n hex = '0' + hex\n }\n\n // Add back the \"0x\" prefix\n return '0x' + hex\n}\n","/**\n * Event reconstruction for full position history scan.\n * @module v2/sync/eventReconstruction\n */\n\nimport type { Address, Hash, PublicClient } from 'viem'\nimport { getAbiItem } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport type { SyncEvent } from '../types'\n\ntype EventReconstructionClient = Pick<PublicClient, 'getBlock' | 'getLogs'>\n\n/**\n * Parameters for event reconstruction.\n */\nexport interface EventReconstructionParams {\n /** viem public client */\n client: EventReconstructionClient\n /** Pool address */\n poolAddress: Address\n /** Account to reconstruct positions for */\n account: Address\n /** Starting block for event scan */\n fromBlock: bigint\n /** Ending block for event scan */\n toBlock: bigint\n /** Batch size for log queries (default: 10000) */\n batchSize?: bigint\n /** Progress callback */\n onProgress?: (event: SyncEvent) => void\n}\n\n/**\n * Event reconstruction result.\n */\nexport interface EventReconstructionResult {\n /** Position IDs that are currently open */\n openPositions: bigint[]\n /** Position IDs that have been closed */\n closedPositions: bigint[]\n /** Number of blocks scanned */\n blocksScanned: bigint\n /** Last scanned block number */\n lastBlock: bigint\n /** Last scanned block hash */\n lastBlockHash: Hash\n}\n\n/**\n * Mint event from reconstruction.\n */\ninterface MintEvent {\n tokenId: bigint\n positionSize: bigint\n blockNumber: bigint\n blockHash: Hash\n transactionHash: Hash\n logIndex: number\n}\n\n/**\n * Burn event from reconstruction.\n */\ninterface BurnEvent {\n tokenId: bigint\n positionSize: bigint\n blockNumber: bigint\n blockHash: Hash\n transactionHash: Hash\n logIndex: number\n}\n\n/**\n * Reconstruct position history from events.\n * This is the fallback method when snapshot recovery fails.\n * It scans all OptionMinted and OptionBurnt events to build the position set.\n *\n * @param params - Reconstruction parameters\n * @returns Reconstruction result with open and closed positions\n */\nexport async function reconstructFromEvents(\n params: EventReconstructionParams,\n): Promise<EventReconstructionResult> {\n const {\n client,\n poolAddress,\n account,\n fromBlock,\n toBlock,\n batchSize = 10000n,\n onProgress,\n } = params\n\n const mintEvents: MintEvent[] = []\n const burnEvents: BurnEvent[] = []\n const totalBlocks = toBlock - fromBlock + 1n\n const safeBatchSize = batchSize > 0n ? batchSize : 10000n\n\n const scanRange = async (rangeFromBlock: bigint, rangeToBlock: bigint) => {\n const [mints, burns] = await Promise.all([\n client.getLogs({\n address: poolAddress,\n event: OPTION_MINTED_EVENT,\n args: { recipient: account },\n fromBlock: rangeFromBlock,\n toBlock: rangeToBlock,\n }),\n client.getLogs({\n address: poolAddress,\n event: OPTION_BURNT_EVENT,\n args: { recipient: account },\n fromBlock: rangeFromBlock,\n toBlock: rangeToBlock,\n }),\n ])\n\n // Process mint events\n for (const mint of mints) {\n // Decode position size from balanceData (first 128 bits)\n const balanceData = mint.args.balanceData as bigint\n const positionSize = balanceData & ((1n << 128n) - 1n)\n\n mintEvents.push({\n tokenId: mint.args.tokenId as bigint,\n positionSize,\n blockNumber: mint.blockNumber,\n blockHash: mint.blockHash,\n transactionHash: mint.transactionHash,\n logIndex: mint.logIndex,\n })\n }\n\n // Process burn events\n for (const burn of burns) {\n burnEvents.push({\n tokenId: burn.args.tokenId as bigint,\n positionSize: burn.args.positionSize as bigint,\n blockNumber: burn.blockNumber,\n blockHash: burn.blockHash,\n transactionHash: burn.transactionHash,\n logIndex: burn.logIndex,\n })\n }\n\n const blocksProcessed = rangeToBlock - fromBlock + 1n\n const progress = totalBlocks > 0n ? (blocksProcessed * 100n) / totalBlocks : 100n\n onProgress?.({\n currentBlock: rangeToBlock,\n targetBlock: toBlock,\n positionsFound: BigInt(mintEvents.length),\n progress: progress > 100n ? 100n : progress,\n })\n }\n\n // Account and pool topics make this query selective enough for providers that\n // permit wide eth_getLogs ranges. This keeps the fallback practical on mainnet.\n // Providers with an explicit range cap fall back to bounded requests.\n try {\n await scanRange(fromBlock, toBlock)\n } catch (error) {\n if (!isRangeLimitError(error)) throw error\n\n let currentBlock = fromBlock\n while (currentBlock <= toBlock) {\n const endBlock =\n currentBlock + safeBatchSize - 1n > toBlock ? toBlock : currentBlock + safeBatchSize - 1n\n await scanRange(currentBlock, endBlock)\n currentBlock = endBlock + 1n\n }\n }\n\n // Build position map: tokenId -> net position size\n const positionMap = new Map<bigint, bigint>()\n\n // Sort all events by block and log index\n const allEvents = [\n ...mintEvents.map((e) => ({ ...e, type: 'mint' as const })),\n ...burnEvents.map((e) => ({ ...e, type: 'burn' as const })),\n ].sort((a, b) => {\n const blockDiff = Number(a.blockNumber - b.blockNumber)\n if (blockDiff !== 0) return blockDiff\n return a.logIndex - b.logIndex\n })\n\n // Process events in order\n for (const event of allEvents) {\n const current = positionMap.get(event.tokenId) ?? 0n\n\n if (event.type === 'mint') {\n positionMap.set(event.tokenId, current + event.positionSize)\n } else {\n positionMap.set(event.tokenId, current - event.positionSize)\n }\n }\n\n // Separate open and closed positions\n const openPositions: bigint[] = []\n const closedPositions: bigint[] = []\n\n for (const [tokenId, size] of positionMap) {\n if (size > 0n) {\n openPositions.push(tokenId)\n } else {\n closedPositions.push(tokenId)\n }\n }\n\n // Get the last block hash\n const lastBlock = await client.getBlock({ blockNumber: toBlock })\n\n return {\n openPositions,\n closedPositions,\n blocksScanned: toBlock - fromBlock + 1n,\n lastBlock: toBlock,\n lastBlockHash: lastBlock.hash,\n }\n}\n\nconst OPTION_MINTED_EVENT = getAbiItem({ abi: panopticPoolV2Abi, name: 'OptionMinted' })\nconst OPTION_BURNT_EVENT = getAbiItem({ abi: panopticPoolV2Abi, name: 'OptionBurnt' })\n\nfunction isRangeLimitError(error: unknown): boolean {\n const messages: string[] = []\n let current: unknown = error\n for (let depth = 0; current && typeof current === 'object' && depth < 5; depth += 1) {\n if ('message' in current && typeof current.message === 'string') {\n messages.push(current.message)\n }\n if ('details' in current && typeof current.details === 'string') {\n messages.push(current.details)\n }\n current = 'cause' in current ? current.cause : undefined\n }\n if (typeof error === 'string') messages.push(error)\n\n const message = messages.join(' ').toLowerCase()\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\n/**\n * Get the deployment block for a pool.\n * This searches for the first PoolInitialized event.\n *\n * @param client - viem public client\n * @param poolAddress - Pool address\n * @returns Deployment block number or null if not found\n */\nexport async function getPoolDeploymentBlock(\n client: PublicClient,\n poolAddress: Address,\n): Promise<bigint | null> {\n // Search for the first event from this pool\n // We use a binary search approach to find the deployment block\n\n const currentBlock = await client.getBlockNumber()\n let low = 0n\n let high = currentBlock\n let foundBlock: bigint | null = null\n\n // Binary search with scan windows to find the deployment block.\n // Each iteration checks [mid, mid + scanRange] for logs.\n const scanRange = 10000n\n\n while (low <= high) {\n const mid = (low + high) / 2n\n const rangeEnd = mid + scanRange > high ? high : mid + scanRange\n\n try {\n const logs = await client.getLogs({\n address: poolAddress,\n fromBlock: mid,\n toBlock: rangeEnd,\n })\n\n if (logs.length > 0) {\n // Found logs — record earliest and search before it\n const earliest = logs[0].blockNumber\n if (foundBlock === null || earliest < foundBlock) {\n foundBlock = earliest\n }\n high = earliest - 1n\n } else {\n // No logs in [mid, rangeEnd] — skip the entire checked range\n low = rangeEnd + 1n\n }\n } catch {\n // Range too large for RPC — halve the search space\n high = mid + (rangeEnd - mid) / 2n\n }\n }\n\n return foundBlock\n}\n","/**\n * Construction of fee-protected self-settlement dispatches.\n *\n * A short position's displayed premium can include fees that still live in\n * Uniswap. Minting a temporary, minimal short over the same chunks collects\n * those fees into `settledTokens`; burning it after settlement leaves the\n * caller's position list unchanged.\n * @module v2/writes/protectedSettle\n */\n\nimport { PanopticError } from '../errors'\nimport { tickToSqrtPriceX96 } from '../formatters'\nimport type { DispatchIntent } from '../simulations/creditWrap'\nimport { addLegToTokenId, decodeAllLegs, decodeTickSpacing } from '../tokenId'\n\nconst POOL_ID_MASK = (1n << 64n) - 1n\nconst Q96 = 1n << 96n\nconst MAX_UINT128 = (1n << 128n) - 1n\nconst SETTLE_LIMITS = [-887272n, 887272n, 0n] as const\n\nexport interface BuildProtectedSettleDispatchParams {\n /** Positions whose premium should be settled. */\n positionIdList: bigint[]\n /** The caller's complete held list. A settlement does not change it. */\n finalPositionIdList: bigint[]\n /** Current stored size for every entry in `positionIdList`. */\n positionSizes: bigint[]\n usePremiaAsCollateral?: boolean\n builderCode?: bigint\n}\n\nexport interface ProtectedSettlePlan {\n /** Atomic poke/settle/poke dispatch submitted after buyer settlements. */\n dispatch: DispatchIntent\n /** Poke-only dispatch used to verify no displayed premium remains uncollected. */\n collectionDispatch?: DispatchIntent\n /** Temporary position IDs, one for each settled position containing short chunks. */\n pokingTokenIds: bigint[]\n}\n\nfunction ceilDiv(numerator: bigint, denominator: bigint): bigint {\n return (numerator + denominator - 1n) / denominator\n}\n\n/** Smallest position size that creates non-zero liquidity on every poke leg. */\nfunction minimumPokeSize(\n legs: ReturnType<typeof decodeAllLegs>,\n tickSpacing: bigint,\n): bigint | undefined {\n let requiredSize = 1n\n\n for (const leg of legs) {\n const widthInTicks = leg.width * tickSpacing\n const lowerTick = leg.strike - widthInTicks / 2n\n const upperTick = leg.strike + (widthInTicks + 1n) / 2n\n const sqrtLower = tickToSqrtPriceX96(lowerTick)\n const sqrtUpper = tickToSqrtPriceX96(upperTick)\n const delta = sqrtUpper - sqrtLower\n const liquidityFactor = leg.asset === 0n ? (sqrtLower * sqrtUpper) / Q96 : Q96\n if (liquidityFactor === 0n) return undefined\n const requiredAmount = ceilDiv(delta, liquidityFactor)\n const legSize = ceilDiv(requiredAmount, leg.optionRatio)\n if (legSize > requiredSize) requiredSize = legSize\n }\n\n if (requiredSize > MAX_UINT128) {\n return undefined\n }\n return requiredSize\n}\n\nfunction encodePokeToken(\n sourceTokenId: bigint,\n legs: ReturnType<typeof decodeAllLegs>,\n firstRatio: bigint,\n assetMask: bigint,\n): bigint {\n let tokenId = sourceTokenId & POOL_ID_MASK\n legs.forEach((leg, index) => {\n const encodedIndex = BigInt(index)\n tokenId = addLegToTokenId(tokenId, {\n index: encodedIndex,\n asset: (assetMask >> encodedIndex) & 1n,\n optionRatio: index === 0 ? firstRatio : leg.optionRatio,\n isLong: 0n,\n tokenType: leg.tokenType,\n riskPartner: encodedIndex,\n strike: leg.strike,\n width: leg.width,\n })\n })\n return tokenId\n}\n\nfunction buildUniquePoke(\n sourceTokenId: bigint,\n occupied: Set<bigint>,\n): { tokenId: bigint; size: bigint } | undefined {\n const seenChunks = new Set<string>()\n const shortChunkLegs = decodeAllLegs(sourceTokenId).filter((leg) => {\n if (leg.isLong || leg.width === 0n) return false\n const chunkKey = `${leg.strike}:${leg.width}:${leg.tokenType}`\n if (seenChunks.has(chunkKey)) return false\n seenChunks.add(chunkKey)\n return true\n })\n if (shortChunkLegs.length === 0) return undefined\n\n const originalRatio = shortChunkLegs[0].optionRatio\n for (let ratioOffset = 0n; ratioOffset < 127n; ratioOffset += 1n) {\n const firstRatio = ((originalRatio - 1n + ratioOffset) % 127n) + 1n\n const assetVariants = 1n << BigInt(shortChunkLegs.length)\n for (let assetMask = 0n; assetMask < assetVariants; assetMask += 1n) {\n const tokenId = encodePokeToken(sourceTokenId, shortChunkLegs, firstRatio, assetMask)\n if (!occupied.has(tokenId)) {\n const size = minimumPokeSize(decodeAllLegs(tokenId), decodeTickSpacing(sourceTokenId))\n if (size !== undefined) return { tokenId, size }\n }\n }\n }\n\n throw new PanopticError('Unable to derive a collision-free protected settlement poke')\n}\n\n/**\n * Build `[poke, settle, poke]` for every target containing a width>0 short.\n * Pure-long and width-zero positions are settled directly.\n */\nexport function buildProtectedSettlePlan(\n params: BuildProtectedSettleDispatchParams,\n): ProtectedSettlePlan {\n const {\n positionIdList,\n finalPositionIdList,\n positionSizes,\n usePremiaAsCollateral = false,\n builderCode = 0n,\n } = params\n if (positionIdList.length !== positionSizes.length) {\n throw new PanopticError('Protected settlement: positionSizes length must match positionIdList')\n }\n\n const occupied = new Set(finalPositionIdList)\n const actionIds: bigint[] = []\n const actionSizes: bigint[] = []\n const actionLimits: (readonly [bigint, bigint, bigint])[] = []\n const collectionIds: bigint[] = []\n const collectionSizes: bigint[] = []\n const collectionLimits: (readonly [bigint, bigint, bigint])[] = []\n const pokingTokenIds: bigint[] = []\n\n positionIdList.forEach((tokenId, index) => {\n const poke = buildUniquePoke(tokenId, occupied)\n if (poke === undefined) {\n actionIds.push(tokenId)\n actionSizes.push(positionSizes[index])\n actionLimits.push(SETTLE_LIMITS)\n return\n }\n\n occupied.add(poke.tokenId)\n pokingTokenIds.push(poke.tokenId)\n actionIds.push(poke.tokenId, tokenId, poke.tokenId)\n actionSizes.push(poke.size, positionSizes[index], 0n)\n actionLimits.push(SETTLE_LIMITS, SETTLE_LIMITS, SETTLE_LIMITS)\n collectionIds.push(poke.tokenId, poke.tokenId)\n collectionSizes.push(poke.size, 0n)\n collectionLimits.push(SETTLE_LIMITS, SETTLE_LIMITS)\n })\n\n const base = { finalPositionIdList: [...finalPositionIdList], usePremiaAsCollateral, builderCode }\n return {\n dispatch: {\n ...base,\n positionIdList: actionIds,\n positionSizes: actionSizes,\n tickAndSpreadLimits: actionLimits,\n },\n collectionDispatch:\n collectionIds.length === 0\n ? undefined\n : {\n ...base,\n positionIdList: collectionIds,\n positionSizes: collectionSizes,\n tickAndSpreadLimits: collectionLimits,\n },\n pokingTokenIds,\n }\n}\n\n/**\n * Build the atomic self-settlement dispatch that temporarily pokes each\n * affected short chunk before settling its source position.\n *\n * @param params - Positions, current sizes, and complete held-position list.\n * @returns A dispatch intent ready for simulation or submission.\n */\nexport function buildProtectedSettleDispatch(\n params: BuildProtectedSettleDispatchParams,\n): DispatchIntent {\n return buildProtectedSettlePlan(params).dispatch\n}\n","/**\n * Read current on-chain positionSize for a list of tokenIds.\n *\n * PanopticPool.dispatch() treats `positionSizes[i] == storedSize` as a\n * settlePremium self-call and any mismatch (including 0) as a burn. Callers\n * that want to trigger settle without changing size must pass the CURRENT\n * stored size for each held tokenId — hence this helper.\n *\n * @module v2/reads/positionSizes\n */\n\nimport type { Address, PublicClient } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\n\nconst BIT_MASK_128 = (1n << 128n) - 1n\n\nexport interface GetCurrentPositionSizesParams {\n client: PublicClient\n poolAddress: Address\n account: Address\n positionIdList: bigint[]\n blockNumber?: bigint\n}\n\n/**\n * Returns the current stored positionSize for each tokenId, in the same order\n * as the input `positionIdList`. Reverts (via the contract) if any tokenId is\n * not held by `account`.\n */\nexport async function getCurrentPositionSizes(\n params: GetCurrentPositionSizesParams,\n): Promise<bigint[]> {\n const { client, poolAddress, account, positionIdList, blockNumber } = params\n\n if (positionIdList.length === 0) return []\n\n const [, , positionBalances] = await client.readContract({\n address: poolAddress,\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, positionIdList],\n blockNumber,\n })\n\n return positionBalances.map((packed) => packed & BIT_MASK_128)\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 /** Defaults to true. False returns the existing 0n (unavailable) gas sentinel. */\n estimateGas?: boolean\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 if (params.estimateGas !== false) {\n gasEstimate = await client.estimateGas({\n account: user,\n to: poolAddress,\n data: callData,\n blockNumber,\n })\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","/** Fee-protected premium settlement simulation. @module v2/simulations/simulateSettle */\n\nimport type { Address, Hex, PublicClient } from 'viem'\nimport { decodeFunctionResult, encodeFunctionData } from 'viem'\n\nimport { panopticPoolV2Abi } from '../../../generated'\nimport { getBlockMeta } from '../clients'\nimport { PanopticError, UnsafePremiumSettlementError } from '../errors'\nimport { getCurrentPositionSizes } from '../reads/positionSizes'\nimport { getForfeitablePremium } from '../reads/premia'\nimport type { SettleSimulation, SimulationResult, TokenFlow } from '../types'\nimport { buildProtectedSettlePlan } from '../writes/protectedSettle'\nimport type { SettleSequenceTarget } from '../writes/settleSequence'\nimport { buildSettleSequenceCalls } from '../writes/settleSequence'\nimport { simulateSettlePremiumBatch } from './simulateSettlePremiumBatch'\nimport { simulateWithTokenFlow } from './tokenFlow'\n\nconst BIT_MASK_128 = (1n << 128n) - 1n\nconst multicallAbi = [\n {\n type: 'function',\n name: 'multicall',\n inputs: [{ name: 'data', type: 'bytes[]' }],\n outputs: [{ name: 'results', type: 'bytes[]' }],\n stateMutability: 'nonpayable',\n },\n] as const\n\nexport interface SimulateSettleParams {\n client: PublicClient\n poolAddress: Address\n account: Address\n positionIdList: bigint[]\n finalPositionIdList?: bigint[]\n positionSizes?: bigint[]\n /** Buyers holding longs against the short chunks being settled. */\n targets?: SettleSequenceTarget[]\n usePremiaAsCollateral?: boolean\n builderCode?: bigint\n /**\n * Allow settlement when premium remains but no buyer settlement or chunk\n * poke can collect it (for example, width-zero legs). Avoidable forfeiture\n * still fails closed. Default false.\n */\n allowForfeit?: boolean\n blockNumber?: bigint\n}\n\nfunction encodeDispatch(plan: ReturnType<typeof buildProtectedSettlePlan>): Hex {\n const dispatch = plan.dispatch\n return encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'dispatch',\n args: [\n dispatch.positionIdList,\n dispatch.finalPositionIdList,\n dispatch.positionSizes,\n dispatch.tickAndSpreadLimits.map(\n (limits) =>\n [Number(limits[0]), Number(limits[1]), Number(limits[2])] as readonly [\n number,\n number,\n number,\n ],\n ),\n dispatch.usePremiaAsCollateral,\n dispatch.builderCode,\n ],\n })\n}\n\nfunction decodeShortPremium(data: Hex): readonly [bigint, bigint] {\n const packed = decodeFunctionResult({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n data,\n })[0]\n return [packed & BIT_MASK_128, packed >> 128n]\n}\n\nasync function remainingForfeitAfterProtection(params: {\n client: PublicClient\n poolAddress: Address\n account: Address\n positionIdList: bigint[]\n finalPositionIdList: bigint[]\n targets: SettleSequenceTarget[]\n plan: ReturnType<typeof buildProtectedSettlePlan>\n blockNumber: bigint\n initial: readonly [bigint, bigint]\n}): Promise<[bigint, bigint]> {\n const { client, poolAddress, account, positionIdList, targets, plan, blockNumber, initial } =\n params\n if (targets.length === 0 && plan.collectionDispatch === undefined) return [...initial]\n\n const protectionCalls = buildSettleSequenceCalls({\n positionIdListFrom: params.finalPositionIdList,\n targets,\n dispatch: plan.collectionDispatch,\n })\n const availableCall = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, false, positionIdList],\n })\n const totalCall = encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'getFullPositionsData',\n args: [account, true, positionIdList],\n })\n const { result } = await client.simulateContract({\n address: poolAddress,\n abi: multicallAbi,\n functionName: 'multicall',\n args: [[...protectionCalls, availableCall, totalCall]],\n account,\n blockNumber,\n })\n const available = decodeShortPremium(result[result.length - 2])\n const total = decodeShortPremium(result[result.length - 1])\n return [\n total[0] > available[0] ? total[0] - available[0] : 0n,\n total[1] > available[1] ? total[1] - available[1] : 0n,\n ]\n}\n\nexport async function simulateSettle(\n params: SimulateSettleParams,\n): Promise<SimulationResult<SettleSimulation>> {\n const {\n client,\n poolAddress,\n account,\n positionIdList,\n finalPositionIdList = positionIdList,\n positionSizes: providedSizes,\n targets = [],\n usePremiaAsCollateral = false,\n builderCode = 0n,\n allowForfeit = false,\n blockNumber,\n } = params\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n try {\n if (providedSizes && providedSizes.length !== positionIdList.length) {\n throw new PanopticError('simulateSettle: positionSizes length must match positionIdList')\n }\n const positionSizes =\n providedSizes ??\n (await getCurrentPositionSizes({\n client,\n poolAddress,\n account,\n positionIdList,\n blockNumber: targetBlockNumber,\n }))\n const plan = buildProtectedSettlePlan({\n positionIdList,\n finalPositionIdList,\n positionSizes,\n usePremiaAsCollateral,\n builderCode,\n })\n const initialForfeit = await getForfeitablePremium({\n client,\n poolAddress,\n account,\n tokenIds: positionIdList,\n blockNumber: targetBlockNumber,\n })\n const initial: [bigint, bigint] = [initialForfeit.forfeit0, initialForfeit.forfeit1]\n\n if (targets.length > 0) {\n const buyers = await simulateSettlePremiumBatch({\n client,\n poolAddress,\n account,\n positionIdListFrom: finalPositionIdList,\n targets,\n blockNumber: targetBlockNumber,\n })\n if (buyers.unsettleableCount > 0) {\n throw new UnsafePremiumSettlementError(initial, buyers.unsettleableCount)\n }\n }\n\n const remainingForfeit = await remainingForfeitAfterProtection({\n client,\n poolAddress,\n account,\n positionIdList,\n finalPositionIdList,\n targets,\n plan,\n blockNumber: targetBlockNumber,\n initial,\n })\n if ((remainingForfeit[0] > 0n || remainingForfeit[1] > 0n) && !allowForfeit) {\n throw new UnsafePremiumSettlementError(remainingForfeit, 0)\n }\n\n const callData =\n targets.length === 0\n ? encodeDispatch(plan)\n : encodeFunctionData({\n abi: panopticPoolV2Abi,\n functionName: 'multicall',\n args: [\n buildSettleSequenceCalls({\n positionIdListFrom: finalPositionIdList,\n targets,\n dispatch: plan.dispatch,\n }),\n ],\n })\n const flowResult = await simulateWithTokenFlow({\n client,\n poolAddress,\n user: account,\n callData,\n blockNumber: targetBlockNumber,\n })\n if (!flowResult.success || !flowResult.tokenFlow) {\n throw flowResult.rawError ?? new PanopticError(flowResult.error || 'Simulation failed')\n }\n\n const tokenFlow: TokenFlow = flowResult.tokenFlow\n return {\n success: true,\n data: {\n premiaReceived0: tokenFlow.delta0,\n premiaReceived1: tokenFlow.delta1,\n postCollateral0: tokenFlow.balanceAfter0,\n postCollateral1: tokenFlow.balanceAfter1,\n premiumProtected: [initial[0] - remainingForfeit[0], initial[1] - remainingForfeit[1]],\n remainingForfeit,\n usesPoke: plan.pokingTokenIds.length > 0,\n settledBuyerCount: targets.length,\n },\n gasEstimate: flowResult.gasEstimate,\n tokenFlow,\n _meta: await metaPromise,\n }\n } catch (error) {\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: await metaPromise,\n }\n }\n}\n","/**\n * Minimal Permit2 ABI (`IAllowanceTransfer` subset: `approve` + `allowance`).\n * @module uniswap/v4/abis/permit2\n */\n\nexport const permit2Abi = [\n {\n type: 'function',\n name: 'approve',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'token', type: 'address' },\n { name: 'spender', type: 'address' },\n { name: 'amount', type: 'uint160' },\n { name: 'expiration', type: 'uint48' },\n ],\n outputs: [],\n },\n {\n type: 'function',\n name: 'allowance',\n stateMutability: 'view',\n inputs: [\n { name: 'user', type: 'address' },\n { name: 'token', type: 'address' },\n { name: 'spender', type: 'address' },\n ],\n outputs: [\n { name: 'amount', type: 'uint160' },\n { name: 'expiration', type: 'uint48' },\n { name: 'nonce', type: 'uint48' },\n ],\n },\n] as const\n","/**\n * Permit2 approval helpers for the Universal Router ERC20 input side.\n *\n * Two-step on-chain flow (only when `tokenIn` is an ERC20):\n * 1. ERC20 `approve(Permit2, amount)` — lets Permit2 pull the token.\n * 2. `Permit2.approve(token, universalRouter, amount, expiration)` — lets the\n * router spend via Permit2.\n *\n * Native ETH skips both steps.\n *\n * @module uniswap/v4/router/permit2\n */\n\nimport { erc20Abi, maxUint256 } from 'viem'\n\nimport { getBlockMeta } from '../../../panoptic/v2/clients'\nimport type { TxReceipt, TxResult } from '../../../panoptic/v2/types'\nimport { submitWrite } from '../../../panoptic/v2/writes'\nimport { permit2Abi } from '../abis/permit2'\nimport { getUniswapV4Addresses } from '../addresses'\nimport type {\n ApproveErc20ForPermit2Params,\n ApproveRouterViaPermit2Params,\n CheckRouterApprovalParams,\n RouterApprovalStatus,\n} from './types'\n\n/** uint160 max — the largest Permit2 allowance amount. */\nconst UINT160_MAX = (1n << 160n) - 1n\n/** Default Permit2 allowance expiration window (30 days). */\nconst DEFAULT_EXPIRATION_SECONDS = 2_592_000n\n/** uint48 max — the largest Permit2 expiration. */\nconst UINT48_MAX = (1n << 48n) - 1n\n\n/**\n * Check whether the ERC20 → Permit2 → Universal Router allowance chain is\n * sufficient for an exact-in swap of `amount`.\n */\nexport async function checkRouterApproval(\n params: CheckRouterApprovalParams,\n): Promise<RouterApprovalStatus> {\n const { client, chainId, tokenIn, owner, amount, addresses } = params\n const { permit2, universalRouter } = getUniswapV4Addresses(chainId, addresses)\n\n const [erc20Allowance, permit2Allowance, blockMeta] = await Promise.all([\n client.readContract({\n address: tokenIn,\n abi: erc20Abi,\n functionName: 'allowance',\n args: [owner, permit2],\n }),\n client.readContract({\n address: permit2,\n abi: permit2Abi,\n functionName: 'allowance',\n args: [owner, tokenIn, universalRouter],\n }),\n getBlockMeta({ client }),\n ])\n\n const [permit2Amount, permit2Expiration] = permit2Allowance\n\n const needsErc20Approval = erc20Allowance < amount\n const needsPermit2Approval =\n permit2Amount < amount || BigInt(permit2Expiration) <= blockMeta.blockTimestamp\n\n return {\n needsErc20Approval,\n needsPermit2Approval,\n erc20Allowance,\n permit2Amount,\n permit2Expiration: BigInt(permit2Expiration),\n }\n}\n\n/**\n * Step 1: approve the ERC20 token to Permit2 (defaults to unlimited).\n */\nexport async function approveErc20ForPermit2(\n params: ApproveErc20ForPermit2Params,\n): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n chainId,\n tokenIn,\n amount = maxUint256,\n txOverrides,\n addresses,\n } = params\n const { permit2 } = getUniswapV4Addresses(chainId, addresses)\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: tokenIn,\n abi: erc20Abi,\n functionName: 'approve',\n args: [permit2, amount],\n txOverrides,\n })\n}\n\n/**\n * Step 1 (and wait): approve the ERC20 token to Permit2.\n */\nexport async function approveErc20ForPermit2AndWait(\n params: ApproveErc20ForPermit2Params,\n): Promise<TxReceipt> {\n const result = await approveErc20ForPermit2(params)\n return result.wait()\n}\n\n/**\n * Step 2: approve the Universal Router as a Permit2 spender for the token.\n */\nexport async function approveRouterViaPermit2(\n params: ApproveRouterViaPermit2Params,\n): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n chainId,\n tokenIn,\n amount = UINT160_MAX,\n expiration,\n txOverrides,\n addresses,\n } = params\n const { permit2, universalRouter } = getUniswapV4Addresses(chainId, addresses)\n\n const resolvedExpiration =\n expiration ?? (await getBlockMeta({ client })).blockTimestamp + DEFAULT_EXPIRATION_SECONDS\n const cappedExpiration = resolvedExpiration > UINT48_MAX ? UINT48_MAX : resolvedExpiration\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: permit2,\n abi: permit2Abi,\n functionName: 'approve',\n args: [tokenIn, universalRouter, amount, cappedExpiration],\n txOverrides,\n })\n}\n\n/**\n * Step 2 (and wait): approve the Universal Router via Permit2.\n */\nexport async function approveRouterViaPermit2AndWait(\n params: ApproveRouterViaPermit2Params,\n): Promise<TxReceipt> {\n const result = await approveRouterViaPermit2(params)\n return result.wait()\n}\n","/**\n * Minimal V4Quoter ABI (`quoteExactInputSingle`, `quoteExactOutputSingle`).\n *\n * Note: neither function is `view` — they mutate state internally and are\n * intended to be called via `eth_call` / viem `simulateContract`, never\n * `readContract`.\n *\n * @module uniswap/v4/abis/v4Quoter\n */\n\nconst quoteExactSingleParams = {\n name: 'params',\n type: 'tuple',\n components: [\n {\n name: 'poolKey',\n type: 'tuple',\n components: [\n { name: 'currency0', type: 'address' },\n { name: 'currency1', type: 'address' },\n { name: 'fee', type: 'uint24' },\n { name: 'tickSpacing', type: 'int24' },\n { name: 'hooks', type: 'address' },\n ],\n },\n { name: 'zeroForOne', type: 'bool' },\n { name: 'exactAmount', type: 'uint128' },\n { name: 'hookData', type: 'bytes' },\n ],\n} as const\n\nexport const v4QuoterAbi = [\n {\n type: 'function',\n name: 'quoteExactInputSingle',\n stateMutability: 'nonpayable',\n inputs: [quoteExactSingleParams],\n outputs: [\n { name: 'amountOut', type: 'uint256' },\n { name: 'gasEstimate', type: 'uint256' },\n ],\n },\n {\n type: 'function',\n name: 'quoteExactOutputSingle',\n stateMutability: 'nonpayable',\n inputs: [quoteExactSingleParams],\n outputs: [\n { name: 'amountIn', type: 'uint256' },\n { name: 'gasEstimate', type: 'uint256' },\n ],\n },\n] as const\n","/**\n * Resolve the Uniswap v4 PoolKey + swap direction from a PanopticPool address.\n * @module uniswap/v4/router/resolvePoolKey\n */\n\nimport type { Address, PublicClient } from 'viem'\nimport { isAddressEqual } from 'viem'\n\nimport { getPool } from '../../../panoptic/v2/reads/pool'\nimport type { PoolKey } from '../../../panoptic/v2/types'\nimport { InvalidSwapTokenError } from './errors'\n\n/**\n * Resolved swap routing info for a given `tokenIn`.\n */\nexport interface ResolvedSwapRoute {\n /** Underlying v4 PoolKey. */\n poolKey: PoolKey\n /** Whether the swap goes currency0 → currency1. */\n zeroForOne: boolean\n /** Output token address. */\n tokenOut: Address\n /** Decimals of the output token. */\n tokenOutDecimals: bigint\n /** Symbol of the output token. */\n tokenOutSymbol: string\n}\n\n/**\n * Parameters for {@link resolveSwapRoute}.\n */\nexport interface ResolveSwapRouteParams {\n client: PublicClient\n poolAddress: Address\n chainId: bigint\n tokenIn: Address\n blockNumber?: bigint\n}\n\n/**\n * Resolve the PoolKey, swap direction, and output token metadata for a swap.\n *\n * @throws {InvalidSwapTokenError} when `tokenIn` is not part of the pool.\n */\nexport async function resolveSwapRoute(params: ResolveSwapRouteParams): Promise<ResolvedSwapRoute> {\n const { client, poolAddress, chainId, tokenIn, blockNumber } = params\n\n const pool = await getPool({ client, poolAddress, chainId, blockNumber })\n const { poolKey } = pool\n\n const isCurrency0 = isAddressEqual(tokenIn, poolKey.currency0)\n const isCurrency1 = isAddressEqual(tokenIn, poolKey.currency1)\n if (!isCurrency0 && !isCurrency1) {\n throw new InvalidSwapTokenError(tokenIn, poolKey.currency0, poolKey.currency1)\n }\n\n const zeroForOne = isCurrency0\n const tokenOut = zeroForOne ? poolKey.currency1 : poolKey.currency0\n const outTracker = zeroForOne ? pool.collateralTracker1 : pool.collateralTracker0\n\n return {\n poolKey,\n zeroForOne,\n tokenOut,\n tokenOutDecimals: outTracker.decimals,\n tokenOutSymbol: outTracker.symbol,\n }\n}\n","/**\n * Quote exact-in and exact-out swaps via the Uniswap v4 V4Quoter.\n * @module uniswap/v4/router/quote\n */\n\nimport { zeroAddress } from 'viem'\n\nimport { getBlockMeta } from '../../../panoptic/v2/clients'\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport type { SimulationResult } from '../../../panoptic/v2/types'\nimport { v4QuoterAbi } from '../abis/v4Quoter'\nimport { getUniswapV4Addresses } from '../addresses'\nimport { QuoterUnavailableError } from './errors'\nimport { resolveSwapRoute } from './resolvePoolKey'\nimport type {\n QuoteSwapExactInViaRouterParams,\n QuoteSwapExactOutViaRouterParams,\n SwapExactInQuote,\n SwapExactOutQuote,\n} from './types'\n\nconst BPS_DENOMINATOR = 10_000n\nconst UINT128_MAX = (1n << 128n) - 1n\n\n/** Reject out-of-range slippage so the min/max amount math can't underflow/overflow. */\nfunction assertSlippageBps(slippageBps: bigint): void {\n if (slippageBps < 0n || slippageBps > BPS_DENOMINATOR) {\n throw new PanopticError(`invalid slippageBps ${slippageBps}, must be 0..10000`)\n }\n}\n\nconst FALLBACK_META = {\n blockNumber: 0n,\n blockTimestamp: 0n,\n blockHash: '0x0' as `0x${string}`,\n}\n\n/**\n * Quote an exact-in spot swap against the underlying Uniswap v4 pool.\n *\n * Uses the V4Quoter `quoteExactInputSingle` via `eth_call` (the quoter is\n * state-mutating / revert-based, so it must be simulated, not read). Returns a\n * `SimulationResult` so failures carry a structured error rather than throwing.\n */\nexport async function quoteSwapExactInViaRouter(\n params: QuoteSwapExactInViaRouterParams,\n): Promise<SimulationResult<SwapExactInQuote>> {\n const { client, poolAddress, chainId, tokenIn, amountIn, slippageBps, blockNumber, addresses } =\n params\n\n try {\n if (amountIn < 0n || amountIn > UINT128_MAX) {\n throw new PanopticError(`amountIn ${amountIn} exceeds uint128 maximum`)\n }\n assertSlippageBps(slippageBps)\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n const { v4Quoter } = getUniswapV4Addresses(chainId, addresses)\n if (v4Quoter === zeroAddress) {\n throw new QuoterUnavailableError(chainId)\n }\n\n const route = await resolveSwapRoute({\n client,\n poolAddress,\n chainId,\n tokenIn,\n blockNumber: targetBlockNumber,\n })\n\n const { result } = await client.simulateContract({\n address: v4Quoter,\n abi: v4QuoterAbi,\n functionName: 'quoteExactInputSingle',\n blockNumber: targetBlockNumber,\n args: [\n {\n poolKey: {\n currency0: route.poolKey.currency0,\n currency1: route.poolKey.currency1,\n fee: Number(route.poolKey.fee),\n tickSpacing: Number(route.poolKey.tickSpacing),\n hooks: route.poolKey.hooks,\n },\n zeroForOne: route.zeroForOne,\n exactAmount: amountIn,\n hookData: '0x',\n },\n ],\n })\n\n const [amountOut, gasEstimate] = result\n const amountOutMinimum = (amountOut * (BPS_DENOMINATOR - slippageBps)) / BPS_DENOMINATOR\n\n const _meta = await metaPromise\n\n return {\n success: true,\n data: {\n amountOut,\n amountOutMinimum,\n zeroForOne: route.zeroForOne,\n tokenOut: route.tokenOut,\n poolKey: route.poolKey,\n gasEstimate,\n },\n gasEstimate,\n _meta,\n }\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Quote failed',\n error instanceof Error ? error : undefined,\n ),\n _meta: FALLBACK_META,\n }\n }\n}\n\n/**\n * Quote an exact-out spot swap against the underlying Uniswap v4 pool.\n *\n * Uses the V4Quoter `quoteExactOutputSingle` via `eth_call` (the quoter is\n * state-mutating / revert-based, so it must be simulated, not read). Returns a\n * `SimulationResult` so failures carry a structured error rather than throwing.\n */\nexport async function quoteSwapExactOutViaRouter(\n params: QuoteSwapExactOutViaRouterParams,\n): Promise<SimulationResult<SwapExactOutQuote>> {\n const { client, poolAddress, chainId, tokenIn, amountOut, slippageBps, blockNumber, addresses } =\n params\n\n try {\n if (amountOut < 0n || amountOut > UINT128_MAX) {\n throw new PanopticError(`amountOut ${amountOut} exceeds uint128 maximum`)\n }\n assertSlippageBps(slippageBps)\n\n const targetBlockNumber = blockNumber ?? (await client.getBlockNumber())\n const metaPromise = getBlockMeta({ client, blockNumber: targetBlockNumber })\n\n const { v4Quoter } = getUniswapV4Addresses(chainId, addresses)\n if (v4Quoter === zeroAddress) {\n throw new QuoterUnavailableError(chainId)\n }\n\n const route = await resolveSwapRoute({\n client,\n poolAddress,\n chainId,\n tokenIn,\n blockNumber: targetBlockNumber,\n })\n\n const { result } = await client.simulateContract({\n address: v4Quoter,\n abi: v4QuoterAbi,\n functionName: 'quoteExactOutputSingle',\n blockNumber: targetBlockNumber,\n args: [\n {\n poolKey: {\n currency0: route.poolKey.currency0,\n currency1: route.poolKey.currency1,\n fee: Number(route.poolKey.fee),\n tickSpacing: Number(route.poolKey.tickSpacing),\n hooks: route.poolKey.hooks,\n },\n zeroForOne: route.zeroForOne,\n exactAmount: amountOut,\n hookData: '0x',\n },\n ],\n })\n\n const [amountIn, gasEstimate] = result\n // Ceiling division: never round the input cap down (would tighten the buffer).\n const amountInMaximum =\n (amountIn * (BPS_DENOMINATOR + slippageBps) + BPS_DENOMINATOR - 1n) / BPS_DENOMINATOR\n\n const _meta = await metaPromise\n\n return {\n success: true,\n data: {\n amountIn,\n amountInMaximum,\n zeroForOne: route.zeroForOne,\n tokenOut: route.tokenOut,\n poolKey: route.poolKey,\n gasEstimate,\n },\n gasEstimate,\n _meta,\n }\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof PanopticError\n ? error\n : new PanopticError(\n error instanceof Error ? error.message : 'Quote failed',\n error instanceof Error ? error : undefined,\n ),\n _meta: FALLBACK_META,\n }\n }\n}\n","/**\n * Quote an exact-in single-hop v4 swap for an EXPLICIT PoolKey (as opposed to\n * `quoteSwapExactInViaRouter`, which resolves the pool from a PanopticPool\n * address). Used to rank an arbitrary whitelist of hedge pools.\n * @module uniswap/v4/router/quoteByPoolKey\n */\n\nimport type { PublicClient } from 'viem'\nimport { BaseError, ContractFunctionRevertedError } from 'viem'\n\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport type { PoolKey } from '../../../panoptic/v2/types'\nimport { v4QuoterAbi } from '../abis/v4Quoter'\nimport { type UniswapV4Addresses, getUniswapV4Addresses } from '../addresses'\n\nconst BPS_DENOMINATOR = 10_000n\nconst UINT128_MAX = (1n << 128n) - 1n\n\nexport interface QuoteV4ExactInByPoolKeyParams {\n client: PublicClient\n chainId: bigint\n poolKey: PoolKey\n zeroForOne: boolean\n amountIn: bigint\n slippageBps: bigint\n blockNumber?: bigint\n addresses?: Partial<UniswapV4Addresses>\n}\n\nexport interface V4ExactInQuote {\n amountOut: bigint\n amountOutMinimum: bigint\n gasEstimate: bigint\n}\n\n/**\n * Quote an exact-in v4 swap for a specific PoolKey. Returns `null` when the\n * quote reverts (pool missing / no liquidity) so callers can skip that pool when\n * ranking venues rather than aborting the cycle.\n */\nexport async function quoteV4ExactInByPoolKey(\n params: QuoteV4ExactInByPoolKeyParams,\n): Promise<V4ExactInQuote | null> {\n const { client, chainId, poolKey, zeroForOne, amountIn, slippageBps, blockNumber } = params\n if (amountIn < 0n || amountIn > UINT128_MAX) {\n throw new PanopticError(`amountIn ${amountIn} exceeds uint128 maximum`)\n }\n if (slippageBps < 0n || slippageBps > BPS_DENOMINATOR) {\n throw new PanopticError(`invalid slippageBps ${slippageBps}, must be 0..10000`)\n }\n\n const { v4Quoter } = getUniswapV4Addresses(chainId, params.addresses)\n\n try {\n const { result } = await client.simulateContract({\n address: v4Quoter,\n abi: v4QuoterAbi,\n functionName: 'quoteExactInputSingle',\n blockNumber,\n args: [\n {\n poolKey: {\n currency0: poolKey.currency0,\n currency1: poolKey.currency1,\n fee: Number(poolKey.fee),\n tickSpacing: Number(poolKey.tickSpacing),\n hooks: poolKey.hooks,\n },\n zeroForOne,\n exactAmount: amountIn,\n hookData: '0x',\n },\n ],\n })\n const [amountOut, gasEstimate] = result\n const amountOutMinimum = (amountOut * (BPS_DENOMINATOR - slippageBps)) / BPS_DENOMINATOR\n return { amountOut, amountOutMinimum, gasEstimate }\n } catch (err) {\n if (isRevert(err)) return null\n // Transport/RPC/timeout errors are NOT \"no liquidity\" — rethrow so routing\n // doesn't silently treat an unreachable node as an empty pool.\n throw err\n }\n}\n\n/** True only for genuine contract reverts (missing pool / no liquidity). */\nfunction isRevert(err: unknown): boolean {\n return (\n err instanceof BaseError &&\n err.walk((e) => e instanceof ContractFunctionRevertedError) instanceof\n ContractFunctionRevertedError\n )\n}\n","/**\n * Exact-in and exact-out spot swaps via the Uniswap v4 Universal Router.\n *\n * Swaps directly on the underlying Uniswap v4 pool, bypassing Panoptic (no SFPM,\n * no Panoptic LP fees, no pool collateral required). Native ETH (`address(0)`)\n * is supported via `msg.value` with no Permit2 approval.\n *\n * @module uniswap/v4/router/swap\n */\n\nimport { isAddressEqual } from 'viem'\n\nimport { getBlockMeta } from '../../../panoptic/v2/clients'\nimport { PanopticError } from '../../../panoptic/v2/errors'\nimport type { TxReceipt, TxResult } from '../../../panoptic/v2/types'\nimport { submitWrite } from '../../../panoptic/v2/writes'\nimport { universalRouterAbi } from '../abis/universalRouter'\nimport { getUniswapV4Addresses } from '../addresses'\nimport { buildV4ExactOutSwapExecuteArgs, buildV4SwapExecuteArgs } from './encodeSwap'\nimport { quoteSwapExactInViaRouter, quoteSwapExactOutViaRouter } from './quote'\nimport type { SwapExactInViaRouterParams, SwapExactOutViaRouterParams } from './types'\n\n/** Default swap deadline window (30 minutes) when no deadline is provided. */\nconst DEFAULT_DEADLINE_SECONDS = 1800n\n\n/**\n * Execute an exact-in spot swap via the Universal Router.\n *\n * @param params - Swap parameters.\n * @returns TxResult with hash + wait().\n *\n * @example\n * ```typescript\n * const result = await swapExactInViaRouter({\n * client, walletClient, account, poolAddress,\n * chainId: 1n,\n * tokenIn: ZERO_ADDRESS, // native ETH\n * amountIn: 10n ** 17n, // 0.1 ETH\n * slippageBps: 50n, // 0.5%\n * })\n * await result.wait()\n * ```\n */\nexport async function swapExactInViaRouter(params: SwapExactInViaRouterParams): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n tokenIn,\n amountIn,\n slippageBps,\n deadline,\n recipient,\n txOverrides,\n addresses,\n } = params\n\n if (recipient !== undefined && !isAddressEqual(recipient, account)) {\n // The Universal Router pays the configured router recipient; routing output\n // to an arbitrary recipient requires an extra action not wired in v1.\n throw new PanopticError('Custom recipient is not supported yet; output goes to the sender')\n }\n\n const resolved = getUniswapV4Addresses(chainId, addresses)\n\n const quote = await quoteSwapExactInViaRouter({\n client,\n poolAddress,\n chainId,\n tokenIn,\n amountIn,\n slippageBps,\n addresses,\n })\n\n if (!quote.success) {\n throw quote.error\n }\n\n const resolvedDeadline =\n deadline ?? (await getBlockMeta({ client })).blockTimestamp + DEFAULT_DEADLINE_SECONDS\n\n if (!quote.data.poolKey) {\n throw new PanopticError('v4 swap requires a poolKey from the quote')\n }\n\n const { args, value } = buildV4SwapExecuteArgs({\n poolKey: quote.data.poolKey,\n zeroForOne: quote.data.zeroForOne,\n amountIn,\n amountOutMinimum: quote.data.amountOutMinimum,\n tokenIn,\n tokenOut: quote.data.tokenOut,\n deadline: resolvedDeadline,\n recipient: account,\n })\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: resolved.universalRouter,\n abi: universalRouterAbi,\n functionName: 'execute',\n args,\n value,\n txOverrides,\n })\n}\n\n/**\n * Execute an exact-in swap via the Universal Router and wait for confirmation.\n */\nexport async function swapExactInViaRouterAndWait(\n params: SwapExactInViaRouterParams,\n): Promise<TxReceipt> {\n const result = await swapExactInViaRouter(params)\n return result.wait()\n}\n\n/**\n * Execute an exact-out spot swap via the Universal Router.\n *\n * The caller specifies the exact `amountOut` to receive; the input (pay) amount\n * is quoted and capped at `amountInMaximum`. For native-ETH input the router is\n * funded with `amountInMaximum` and the unused surplus is swept back to the\n * sender.\n *\n * @param params - Swap parameters.\n * @returns TxResult with hash + wait().\n */\nexport async function swapExactOutViaRouter(\n params: SwapExactOutViaRouterParams,\n): Promise<TxResult> {\n const {\n client,\n walletClient,\n account,\n poolAddress,\n chainId,\n tokenIn,\n amountOut,\n slippageBps,\n deadline,\n recipient,\n txOverrides,\n addresses,\n } = params\n\n if (recipient !== undefined && !isAddressEqual(recipient, account)) {\n // The Universal Router pays the configured router recipient; routing output\n // to an arbitrary recipient requires an extra action not wired in v1.\n throw new PanopticError('Custom recipient is not supported yet; output goes to the sender')\n }\n\n const resolved = getUniswapV4Addresses(chainId, addresses)\n\n const quote = await quoteSwapExactOutViaRouter({\n client,\n poolAddress,\n chainId,\n tokenIn,\n amountOut,\n slippageBps,\n addresses,\n })\n\n if (!quote.success) {\n throw quote.error\n }\n\n const resolvedDeadline =\n deadline ?? (await getBlockMeta({ client })).blockTimestamp + DEFAULT_DEADLINE_SECONDS\n\n if (!quote.data.poolKey) {\n throw new PanopticError('v4 swap requires a poolKey from the quote')\n }\n\n const { args, value } = buildV4ExactOutSwapExecuteArgs({\n poolKey: quote.data.poolKey,\n zeroForOne: quote.data.zeroForOne,\n amountOut,\n amountInMaximum: quote.data.amountInMaximum,\n tokenIn,\n tokenOut: quote.data.tokenOut,\n deadline: resolvedDeadline,\n recipient: account,\n })\n\n return submitWrite({\n client,\n walletClient,\n account,\n address: resolved.universalRouter,\n abi: universalRouterAbi,\n functionName: 'execute',\n args,\n value,\n txOverrides,\n })\n}\n\n/**\n * Execute an exact-out swap via the Universal Router and wait for confirmation.\n */\nexport async function swapExactOutViaRouterAndWait(\n params: SwapExactOutViaRouterParams,\n): Promise<TxReceipt> {\n const result = await swapExactOutViaRouter(params)\n return result.wait()\n}\n"],"mappings":"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;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IAAE,MAAM;IAAQ,cAAc;IAAW,MAAM;IAAW,SAAS;GAAM;GACzE;IAAE,MAAM;IAAM,cAAc;IAA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AM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IAAE,MAAM;IAAQ,cAAc;IAAW,MAAM;IAAW,SAAS;GAAM;GACzE;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,WAAW;EACX,QAAQ;GACN;IAAE,MAAM;IAAQ,cAAc;IAAW,MAAM;IAAW,SAAS;GAAM;GACzE;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;GACD;IACE,MAAM;IACN,cAAc;IACd,MAAM;IACN,SAAS;GACV;EACF;EACD,MAAM;CACP;CACD;EACE,MAAM;EACN,QAAQ,CACN;GAAE,MAAM;GAAW,cAAc;GAAW,MAAM;EAAW,GAC7D;GAAE,MAAM;GAAiB,cAA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"}
|