@percolatorct/sdk 1.0.0-beta.2 → 1.0.0-beta.4

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/abi/encode.ts","../src/abi/instructions.ts","../src/abi/accounts.ts","../src/abi/errors.ts","../src/solana/slab.ts","../src/solana/pda.ts","../src/solana/ata.ts","../src/solana/discovery.ts","../src/solana/static-markets.ts","../src/solana/dex-oracle.ts","../src/solana/oracle.ts","../src/solana/token-program.ts","../src/solana/stake.ts","../src/config/program-ids.ts","../src/solana/adl.ts","../src/solana/rpc-pool.ts","../src/runtime/tx.ts","../src/runtime/lighthouse.ts","../src/math/trading.ts","../src/math/warmup.ts","../src/validation.ts","../src/oracle/price-router.ts"],"sourcesContent":["import { PublicKey } from \"@solana/web3.js\";\n\nconst U8_MAX = 255;\nconst U16_MAX = 65_535;\nconst U32_MAX = 4_294_967_295;\n\n/**\n * Encode u8 (1 byte)\n */\nexport function encU8(val: number): Uint8Array {\n if (!Number.isInteger(val) || val < 0 || val > 0xFF) {\n throw new Error(`encU8: value out of range (0..255), got ${val}`);\n }\n return new Uint8Array([val]);\n}\n\n/**\n * Encode u16 little-endian (2 bytes)\n */\nexport function encU16(val: number): Uint8Array {\n if (!Number.isInteger(val) || val < 0 || val > 0xFFFF) {\n throw new Error(`encU16: value out of range (0..65535), got ${val}`);\n }\n const buf = new Uint8Array(2);\n new DataView(buf.buffer).setUint16(0, val, true);\n return buf;\n}\n\n/**\n * Encode u32 little-endian (4 bytes)\n */\nexport function encU32(val: number): Uint8Array {\n if (!Number.isInteger(val) || val < 0 || val > 0xFFFFFFFF) {\n throw new Error(`encU32: value out of range (0..4294967295), got ${val}`);\n }\n const buf = new Uint8Array(4);\n new DataView(buf.buffer).setUint32(0, val, true);\n return buf;\n}\n\n/**\n * Encode u64 little-endian (8 bytes)\n * Input: bigint or string (decimal)\n */\nexport function encU64(val: bigint | string): Uint8Array {\n const n = typeof val === \"string\" ? BigInt(val) : val;\n if (n < 0n) throw new Error(\"encU64: value must be non-negative\");\n if (n > 0xffff_ffff_ffff_ffffn) throw new Error(\"encU64: value exceeds u64 max\");\n const buf = new Uint8Array(8);\n new DataView(buf.buffer).setBigUint64(0, n, true);\n return buf;\n}\n\n/**\n * Encode i64 little-endian (8 bytes), two's complement\n * Input: bigint or string (decimal, may be negative)\n */\nexport function encI64(val: bigint | string): Uint8Array {\n const n = typeof val === \"string\" ? BigInt(val) : val;\n const min = -(1n << 63n);\n const max = (1n << 63n) - 1n;\n if (n < min || n > max) throw new Error(\"encI64: value out of range\");\n const buf = new Uint8Array(8);\n new DataView(buf.buffer).setBigInt64(0, n, true);\n return buf;\n}\n\n/**\n * Encode u128 little-endian (16 bytes)\n * Input: bigint or string (decimal)\n */\nexport function encU128(val: bigint | string): Uint8Array {\n const n = typeof val === \"string\" ? BigInt(val) : val;\n if (n < 0n) throw new Error(\"encU128: value must be non-negative\");\n const max = (1n << 128n) - 1n;\n if (n > max) throw new Error(\"encU128: value exceeds u128 max\");\n const buf = new Uint8Array(16);\n const view = new DataView(buf.buffer);\n const lo = n & 0xffff_ffff_ffff_ffffn;\n const hi = n >> 64n;\n view.setBigUint64(0, lo, true);\n view.setBigUint64(8, hi, true);\n return buf;\n}\n\n/**\n * Encode i128 little-endian (16 bytes), two's complement\n * Input: bigint or string (decimal, may be negative)\n */\nexport function encI128(val: bigint | string): Uint8Array {\n const n = typeof val === \"string\" ? BigInt(val) : val;\n const min = -(1n << 127n);\n const max = (1n << 127n) - 1n;\n if (n < min || n > max) throw new Error(\"encI128: value out of range\");\n\n // Convert to unsigned representation (two's complement)\n let unsigned = n;\n if (n < 0n) {\n unsigned = (1n << 128n) + n;\n }\n\n const buf = new Uint8Array(16);\n const view = new DataView(buf.buffer);\n const lo = unsigned & 0xffff_ffff_ffff_ffffn;\n const hi = unsigned >> 64n;\n view.setBigUint64(0, lo, true);\n view.setBigUint64(8, hi, true);\n return buf;\n}\n\n/**\n * Encode a PublicKey (32 bytes)\n * Input: PublicKey or base58 string\n */\nexport function encPubkey(val: PublicKey | string): Uint8Array {\n try {\n const pk = typeof val === \"string\" ? new PublicKey(val) : val;\n return pk.toBytes();\n } catch (e: unknown) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new Error(`encPubkey: invalid public key \"${String(val)}\" — ${msg}`);\n }\n}\n\n/**\n * Encode a boolean as u8 (0 = false, 1 = true)\n */\nexport function encBool(val: boolean): Uint8Array {\n return encU8(val ? 1 : 0);\n}\n\n/**\n * Concatenate multiple Uint8Arrays (replaces Buffer.concat)\n */\nexport function concatBytes(...arrays: Uint8Array[]): Uint8Array {\n const totalLen = arrays.reduce((sum, a) => sum + a.length, 0);\n const result = new Uint8Array(totalLen);\n let offset = 0;\n for (const arr of arrays) {\n result.set(arr, offset);\n offset += arr.length;\n }\n return result;\n}\n","import { PublicKey } from \"@solana/web3.js\";\nimport {\n encU8,\n encU16,\n encU32,\n encU64,\n encI64,\n encU128,\n encI128,\n encPubkey,\n concatBytes,\n} from \"./encode.js\";\n\n/**\n * Oracle price constraints.\n * Maximum oracle price that can be pushed to the on-chain oracle authority.\n */\nexport const MAX_ORACLE_PRICE = 1_000_000_000_000n; // 1 trillion e6 = 1M USD/unit\n\n/**\n * Instruction tags - exact match to Rust ix::Instruction::decode\n */\nexport const IX_TAG = {\n InitMarket: 0,\n InitUser: 1,\n InitLP: 2,\n DepositCollateral: 3,\n WithdrawCollateral: 4,\n KeeperCrank: 5,\n TradeNoCpi: 6,\n LiquidateAtOracle: 7,\n CloseAccount: 8,\n TopUpInsurance: 9,\n TradeCpi: 10,\n SetRiskThreshold: 11,\n UpdateAdmin: 12,\n CloseSlab: 13,\n UpdateConfig: 14,\n SetMaintenanceFee: 15,\n SetOracleAuthority: 16,\n PushOraclePrice: 17,\n SetOraclePriceCap: 18,\n ResolveMarket: 19,\n WithdrawInsurance: 20,\n AdminForceClose: 21,\n UpdateRiskParams: 22,\n RenounceAdmin: 23,\n CreateInsuranceMint: 24,\n DepositInsuranceLP: 25,\n WithdrawInsuranceLP: 26,\n PauseMarket: 27,\n UnpauseMarket: 28,\n AcceptAdmin: 29,\n SetInsuranceWithdrawPolicy: 30,\n WithdrawInsuranceLimited: 31,\n SetPythOracle: 32,\n UpdateMarkPrice: 33,\n UpdateHyperpMark: 34,\n TradeCpiV2: 35,\n UnresolveMarket: 36,\n CreateLpVault: 37,\n LpVaultDeposit: 38,\n LpVaultWithdraw: 39,\n LpVaultCrankFees: 40,\n /** PERC-306: Fund per-market isolated insurance balance */\n FundMarketInsurance: 41,\n /** PERC-306: Set insurance isolation BPS for a market */\n SetInsuranceIsolation: 42,\n // Tag 43 is ChallengeSettlement on-chain (PERC-314).\n // PERC-305 (ExecuteAdl) is NOT implemented on-chain — do NOT assign tag 43 here.\n // When PERC-305 is implemented, assign a new unused tag (≥47).\n /** PERC-314: Challenge settlement price during dispute window */\n ChallengeSettlement: 43,\n /** PERC-314: Resolve dispute (admin adjudication) */\n ResolveDispute: 44,\n /** PERC-315: Deposit LP vault tokens as perp collateral */\n DepositLpCollateral: 45,\n /** PERC-315: Withdraw LP collateral (position must be closed) */\n WithdrawLpCollateral: 46,\n /** PERC-309: Queue a large LP withdrawal (user; creates withdraw_queue PDA). */\n QueueWithdrawal: 47,\n /** PERC-309: Claim one epoch tranche from a queued LP withdrawal (user). */\n ClaimQueuedWithdrawal: 48,\n /** PERC-309: Cancel a queued withdrawal, refund remaining LP tokens (user). */\n CancelQueuedWithdrawal: 49,\n /** PERC-305: Auto-deleverage — surgically close profitable positions when PnL cap is exceeded (permissionless). */\n ExecuteAdl: 50,\n /** Close a stale slab of an invalid/old layout and recover rent SOL (admin only). */\n CloseStaleSlabs: 51,\n /** Reclaim rent from an uninitialised slab whose market creation failed mid-flow. Slab must sign. */\n ReclaimSlabRent: 52,\n /** Permissionless on-chain audit crank: verifies conservation invariants and pauses market on violation. */\n AuditCrank: 53,\n /** Cross-Market Portfolio Margining: SetOffsetPair */\n SetOffsetPair: 54,\n /** Cross-Market Portfolio Margining: AttestCrossMargin */\n AttestCrossMargin: 55,\n /** PERC-622: Advance oracle phase (permissionless crank) */\n AdvanceOraclePhase: 56,\n /** PERC-623: Top up a market's keeper fund (permissionless) */\n TopUpKeeperFund: 57,\n /** PERC-629: Slash a market creator's deposit (permissionless) */\n SlashCreationDeposit: 58,\n /** PERC-628: Initialize the global shared vault (admin) */\n InitSharedVault: 59,\n /** PERC-628: Allocate virtual liquidity to a market (admin) */\n AllocateMarket: 60,\n /** PERC-628: Queue a withdrawal for the current epoch */\n QueueWithdrawalSV: 61,\n /** PERC-628: Claim a queued withdrawal after epoch elapses */\n ClaimEpochWithdrawal: 62,\n /** PERC-628: Advance the shared vault epoch (permissionless crank) */\n AdvanceEpoch: 63,\n /** PERC-608: Mint a Position NFT for a user's open position. */\n MintPositionNft: 64,\n /** PERC-608: Transfer position ownership via the NFT (keeper-gated). */\n TransferPositionOwnership: 65,\n /** PERC-608: Burn the Position NFT when a position is closed. */\n BurnPositionNft: 66,\n /** PERC-608: Keeper sets pending_settlement flag before a funding transfer. */\n SetPendingSettlement: 67,\n /** PERC-608: Keeper clears pending_settlement flag after KeeperCrank. */\n ClearPendingSettlement: 68,\n /** PERC-608: Internal CPI call from percolator-nft TransferHook to update on-chain owner. */\n TransferOwnershipCpi: 69,\n /** PERC-8111: Set per-wallet position cap (admin only, cap_e6=0 disables). */\n SetWalletCap: 70,\n /** PERC-8110: Set OI imbalance hard-block threshold (admin only). */\n SetOiImbalanceHardBlock: 71,\n /** PERC-8270: Rescue orphan vault — recover tokens from a closed market's vault (admin). */\n RescueOrphanVault: 72,\n /** PERC-8270: Close orphan slab — reclaim rent from a slab whose market closed unexpectedly (admin). */\n CloseOrphanSlab: 73,\n /** PERC-SetDexPool: Pin admin-approved DEX pool address for a HYPERP market (admin). */\n SetDexPool: 74,\n /** CPI to the matcher program to initialize a matcher context account for an LP slot. Admin-only. */\n InitMatcherCtx: 75,\n} as const;\nObject.freeze(IX_TAG);\n\n/**\n * InitMarket instruction data (256 bytes total)\n * Layout: tag(1) + admin(32) + mint(32) + indexFeedId(32) +\n * maxStaleSecs(8) + confFilter(2) + invert(1) + unitScale(4) +\n * RiskParams(144)\n *\n * Note: indexFeedId is the Pyth Pull feed ID (32 bytes hex), NOT an oracle pubkey.\n * The program validates PriceUpdateV2 accounts against this feed ID at runtime.\n */\nexport interface InitMarketArgs {\n admin: PublicKey | string;\n collateralMint: PublicKey | string;\n indexFeedId: string; // Pyth feed ID (hex string, 64 chars without 0x prefix). All zeros = Hyperp mode.\n maxStalenessSecs: bigint | string; // Max staleness in SECONDS (Pyth Pull uses unix timestamps)\n confFilterBps: number;\n invert: number; // 0 = no inversion, 1 = invert oracle price (USD/SOL -> SOL/USD)\n unitScale: number; // Lamports per unit (0 = no scaling, e.g. 1000 = 1 SOL = 1,000,000 units)\n initialMarkPriceE6: bigint | string; // Initial mark price (required non-zero for Hyperp mode)\n warmupPeriodSlots: bigint | string;\n maintenanceMarginBps: bigint | string;\n initialMarginBps: bigint | string;\n tradingFeeBps: bigint | string;\n maxAccounts: bigint | string;\n newAccountFee: bigint | string;\n riskReductionThreshold: bigint | string;\n maintenanceFeePerSlot: bigint | string;\n maxCrankStalenessSlots: bigint | string;\n liquidationFeeBps: bigint | string;\n liquidationFeeCap: bigint | string;\n liquidationBufferBps: bigint | string;\n minLiquidationAbs: bigint | string;\n}\n\n/**\n * Encode a Pyth feed ID (hex string) to 32-byte Uint8Array.\n */\nconst HEX_RE = /^[0-9a-fA-F]{64}$/;\n\nfunction encodeFeedId(feedId: string): Uint8Array {\n const hex = feedId.startsWith(\"0x\") ? feedId.slice(2) : feedId;\n if (!HEX_RE.test(hex)) {\n throw new Error(\n `Invalid feed ID: expected 64 hex chars, got \"${hex.length === 64 ? \"non-hex characters\" : hex.length + \" chars\"}\"`,\n );\n }\n const bytes = new Uint8Array(32);\n for (let i = 0; i < 64; i += 2) {\n const byte = parseInt(hex.substring(i, i + 2), 16);\n if (Number.isNaN(byte)) {\n throw new Error(\n `Failed to parse hex byte at position ${i}: \"${hex.substring(i, i + 2)}\"`,\n );\n }\n bytes[i / 2] = byte;\n }\n return bytes;\n}\n\nconst INIT_MARKET_DATA_LEN = 264;\n\nexport function encodeInitMarket(args: InitMarketArgs): Uint8Array {\n const data = concatBytes(\n encU8(IX_TAG.InitMarket),\n encPubkey(args.admin),\n encPubkey(args.collateralMint),\n encodeFeedId(args.indexFeedId),\n encU64(args.maxStalenessSecs),\n encU16(args.confFilterBps),\n encU8(args.invert),\n encU32(args.unitScale),\n encU64(args.initialMarkPriceE6),\n encU64(args.warmupPeriodSlots),\n encU64(args.maintenanceMarginBps),\n encU64(args.initialMarginBps),\n encU64(args.tradingFeeBps),\n encU64(args.maxAccounts),\n encU128(args.newAccountFee),\n encU128(args.riskReductionThreshold),\n encU128(args.maintenanceFeePerSlot),\n encU64(args.maxCrankStalenessSlots),\n encU64(args.liquidationFeeBps),\n encU128(args.liquidationFeeCap),\n encU64(args.liquidationBufferBps),\n encU128(args.minLiquidationAbs),\n );\n if (data.length !== INIT_MARKET_DATA_LEN) {\n throw new Error(\n `encodeInitMarket: expected ${INIT_MARKET_DATA_LEN} bytes, got ${data.length}`,\n );\n }\n return data;\n}\n\n/**\n * InitUser instruction data (9 bytes)\n */\nexport interface InitUserArgs {\n feePayment: bigint | string;\n}\n\nexport function encodeInitUser(args: InitUserArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.InitUser), encU64(args.feePayment));\n}\n\n/**\n * InitLP instruction data (73 bytes)\n */\nexport interface InitLPArgs {\n matcherProgram: PublicKey | string;\n matcherContext: PublicKey | string;\n feePayment: bigint | string;\n}\n\nexport function encodeInitLP(args: InitLPArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.InitLP),\n encPubkey(args.matcherProgram),\n encPubkey(args.matcherContext),\n encU64(args.feePayment),\n );\n}\n\n/**\n * DepositCollateral instruction data (11 bytes)\n */\nexport interface DepositCollateralArgs {\n userIdx: number;\n amount: bigint | string;\n}\n\nexport function encodeDepositCollateral(args: DepositCollateralArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.DepositCollateral),\n encU16(args.userIdx),\n encU64(args.amount),\n );\n}\n\n/**\n * WithdrawCollateral instruction data (11 bytes)\n */\nexport interface WithdrawCollateralArgs {\n userIdx: number;\n amount: bigint | string;\n}\n\nexport function encodeWithdrawCollateral(args: WithdrawCollateralArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.WithdrawCollateral),\n encU16(args.userIdx),\n encU64(args.amount),\n );\n}\n\n/**\n * KeeperCrank instruction data (4 bytes)\n * Funding rate is computed on-chain from LP inventory.\n */\nexport interface KeeperCrankArgs {\n callerIdx: number;\n allowPanic: boolean;\n}\n\nexport function encodeKeeperCrank(args: KeeperCrankArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.KeeperCrank),\n encU16(args.callerIdx),\n encU8(args.allowPanic ? 1 : 0),\n );\n}\n\n/**\n * TradeNoCpi instruction data (21 bytes)\n */\nexport interface TradeNoCpiArgs {\n lpIdx: number;\n userIdx: number;\n size: bigint | string;\n}\n\nexport function encodeTradeNoCpi(args: TradeNoCpiArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.TradeNoCpi),\n encU16(args.lpIdx),\n encU16(args.userIdx),\n encI128(args.size),\n );\n}\n\n/**\n * LiquidateAtOracle instruction data (3 bytes)\n */\nexport interface LiquidateAtOracleArgs {\n targetIdx: number;\n}\n\nexport function encodeLiquidateAtOracle(args: LiquidateAtOracleArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.LiquidateAtOracle),\n encU16(args.targetIdx),\n );\n}\n\n/**\n * CloseAccount instruction data (3 bytes)\n */\nexport interface CloseAccountArgs {\n userIdx: number;\n}\n\nexport function encodeCloseAccount(args: CloseAccountArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.CloseAccount), encU16(args.userIdx));\n}\n\n/**\n * TopUpInsurance instruction data (9 bytes)\n */\nexport interface TopUpInsuranceArgs {\n amount: bigint | string;\n}\n\nexport function encodeTopUpInsurance(args: TopUpInsuranceArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.TopUpInsurance), encU64(args.amount));\n}\n\n/**\n * TradeCpi instruction data (21 bytes)\n */\nexport interface TradeCpiArgs {\n lpIdx: number;\n userIdx: number;\n size: bigint | string;\n}\n\nexport function encodeTradeCpi(args: TradeCpiArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.TradeCpi),\n encU16(args.lpIdx),\n encU16(args.userIdx),\n encI128(args.size),\n );\n}\n\n/**\n * TradeCpiV2 instruction data (22 bytes) — PERC-154 optimized trade CPI.\n *\n * Same as TradeCpi but includes a caller-provided PDA bump byte.\n * Uses create_program_address instead of find_program_address,\n * saving ~1500 CU per trade. The bump should be obtained once via\n * deriveLpPda() and cached for the lifetime of the market.\n */\nexport interface TradeCpiV2Args {\n lpIdx: number;\n userIdx: number;\n size: bigint | string;\n bump: number;\n}\n\nexport function encodeTradeCpiV2(args: TradeCpiV2Args): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.TradeCpiV2),\n encU16(args.lpIdx),\n encU16(args.userIdx),\n encI128(args.size),\n encU8(args.bump),\n );\n}\n\n/**\n * SetRiskThreshold instruction data (17 bytes)\n */\nexport interface SetRiskThresholdArgs {\n newThreshold: bigint | string;\n}\n\nexport function encodeSetRiskThreshold(args: SetRiskThresholdArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.SetRiskThreshold),\n encU128(args.newThreshold),\n );\n}\n\n/**\n * UpdateAdmin instruction data (33 bytes)\n */\nexport interface UpdateAdminArgs {\n newAdmin: PublicKey | string;\n}\n\nexport function encodeUpdateAdmin(args: UpdateAdminArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.UpdateAdmin), encPubkey(args.newAdmin));\n}\n\n/**\n * CloseSlab instruction data (1 byte)\n */\nexport function encodeCloseSlab(): Uint8Array {\n return encU8(IX_TAG.CloseSlab);\n}\n\n/**\n * UpdateConfig instruction data\n * Updates funding and threshold parameters at runtime (admin only)\n */\nexport interface UpdateConfigArgs {\n // Funding parameters\n fundingHorizonSlots: bigint | string;\n fundingKBps: bigint | string;\n fundingInvScaleNotionalE6: bigint | string;\n fundingMaxPremiumBps: bigint | string;\n fundingMaxBpsPerSlot: bigint | string;\n // Threshold parameters\n threshFloor: bigint | string;\n threshRiskBps: bigint | string;\n threshUpdateIntervalSlots: bigint | string;\n threshStepBps: bigint | string;\n threshAlphaBps: bigint | string;\n threshMin: bigint | string;\n threshMax: bigint | string;\n threshMinStep: bigint | string;\n}\n\nexport function encodeUpdateConfig(args: UpdateConfigArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.UpdateConfig),\n encU64(args.fundingHorizonSlots),\n encU64(args.fundingKBps),\n encU128(args.fundingInvScaleNotionalE6),\n encI64(args.fundingMaxPremiumBps), // Rust: i64 (can be negative)\n encI64(args.fundingMaxBpsPerSlot), // Rust: i64 (can be negative)\n encU128(args.threshFloor),\n encU64(args.threshRiskBps),\n encU64(args.threshUpdateIntervalSlots),\n encU64(args.threshStepBps),\n encU64(args.threshAlphaBps),\n encU128(args.threshMin),\n encU128(args.threshMax),\n encU128(args.threshMinStep),\n );\n}\n\n/**\n * SetMaintenanceFee instruction data (17 bytes)\n */\nexport interface SetMaintenanceFeeArgs {\n newFee: bigint | string;\n}\n\nexport function encodeSetMaintenanceFee(args: SetMaintenanceFeeArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.SetMaintenanceFee),\n encU128(args.newFee),\n );\n}\n\n/**\n * SetOracleAuthority instruction data (33 bytes)\n * Sets the oracle price authority. Pass zero pubkey to disable and require Pyth/Chainlink.\n */\nexport interface SetOracleAuthorityArgs {\n newAuthority: PublicKey | string;\n}\n\nexport function encodeSetOracleAuthority(args: SetOracleAuthorityArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.SetOracleAuthority),\n encPubkey(args.newAuthority),\n );\n}\n\n/**\n * PushOraclePrice instruction data (17 bytes)\n * Push a new oracle price (oracle authority only).\n * The price should be in e6 format and already include any inversion/scaling.\n */\nexport interface PushOraclePriceArgs {\n priceE6: bigint | string;\n timestamp: bigint | string;\n}\n\n/**\n * Encode PushOraclePrice instruction data with validation.\n *\n * Validates oracle price constraints:\n * - Price cannot be zero (division by zero in on-chain engine)\n * - Price cannot exceed MAX_ORACLE_PRICE (prevents overflow in price math)\n *\n * @param args - PushOraclePrice arguments\n * @returns Encoded instruction data (17 bytes)\n * @throws Error if price is 0 or exceeds MAX_ORACLE_PRICE\n */\nexport function encodePushOraclePrice(args: PushOraclePriceArgs): Uint8Array {\n const price = typeof args.priceE6 === \"string\" ? BigInt(args.priceE6) : args.priceE6;\n\n if (price === 0n) {\n throw new Error(\"encodePushOraclePrice: price cannot be zero (division by zero in engine)\");\n }\n\n if (price > MAX_ORACLE_PRICE) {\n throw new Error(`encodePushOraclePrice: price exceeds maximum (${MAX_ORACLE_PRICE}), got ${price}`);\n }\n\n return concatBytes(\n encU8(IX_TAG.PushOraclePrice),\n encU64(price),\n encI64(args.timestamp),\n );\n}\n\n/**\n * SetOraclePriceCap instruction data (9 bytes)\n * Set oracle price circuit breaker cap (admin only).\n *\n * max_change_e2bps: maximum oracle price movement per slot in 0.01 bps units.\n * 1_000_000 = 100% max move per slot.\n *\n * ⚠️ PERC-8191 (PR#150): cap=0 is NO LONGER accepted for admin-oracle markets.\n * - Hyperp markets: rejected if cap < DEFAULT_HYPERP_PRICE_CAP_E2BPS (1000).\n * - Admin-oracle markets: rejected if cap == 0 (circuit breaker bypass prevention).\n * - Pyth-pinned markets: immune (oracle_authority zeroed), any value accepted.\n *\n * Use a non-zero cap for all admin-oracle and Hyperp markets.\n */\nexport interface SetOraclePriceCapArgs {\n maxChangeE2bps: bigint | string;\n}\n\nexport function encodeSetOraclePriceCap(args: SetOraclePriceCapArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.SetOraclePriceCap),\n encU64(args.maxChangeE2bps),\n );\n}\n\n/**\n * ResolveMarket instruction data (1 byte)\n * Resolves a binary/premarket - sets RESOLVED flag, positions force-closed via crank.\n * Requires admin oracle price (authority_price_e6) to be set first.\n */\nexport function encodeResolveMarket(): Uint8Array {\n return encU8(IX_TAG.ResolveMarket);\n}\n\n/**\n * WithdrawInsurance instruction data (1 byte)\n * Withdraw insurance fund to admin (requires RESOLVED and all positions closed).\n */\nexport function encodeWithdrawInsurance(): Uint8Array {\n return encU8(IX_TAG.WithdrawInsurance);\n}\n\n/**\n * AdminForceClose instruction data (3 bytes)\n * Force-close any position at oracle price (admin only, skips margin checks).\n */\nexport interface AdminForceCloseArgs {\n targetIdx: number;\n}\n\nexport function encodeAdminForceClose(args: AdminForceCloseArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.AdminForceClose),\n encU16(args.targetIdx),\n );\n}\n\n/**\n * UpdateRiskParams instruction data (17 or 25 bytes)\n * Update initial and maintenance margin BPS (admin only).\n *\n * R2-S13: The Rust program uses `data.len() >= 25` to detect the optional\n * tradingFeeBps field, so variable-length encoding is safe. When tradingFeeBps\n * is omitted, the data is 17 bytes (tag + 2×u64). When included, 25 bytes.\n */\nexport interface UpdateRiskParamsArgs {\n initialMarginBps: bigint | string;\n maintenanceMarginBps: bigint | string;\n tradingFeeBps?: bigint | string;\n}\n\nexport function encodeUpdateRiskParams(args: UpdateRiskParamsArgs): Uint8Array {\n const parts = [\n encU8(IX_TAG.UpdateRiskParams),\n encU64(args.initialMarginBps),\n encU64(args.maintenanceMarginBps),\n ];\n if (args.tradingFeeBps !== undefined) {\n parts.push(encU64(args.tradingFeeBps));\n }\n return concatBytes(...parts);\n}\n\n/**\n * On-chain confirmation code for RenounceAdmin (must match program constant).\n * ASCII \"RENOUNCE\" as u64 LE = 0x52454E4F554E4345.\n */\nexport const RENOUNCE_ADMIN_CONFIRMATION = 0x52454E4F554E4345n;\n\n/**\n * On-chain confirmation code for UnresolveMarket (must match program constant).\n */\nexport const UNRESOLVE_CONFIRMATION = 0xDEAD_BEEF_CAFE_1234n;\n\n/**\n * RenounceAdmin instruction data (9 bytes)\n * Irreversibly set admin to all zeros. After this, all admin-only instructions fail.\n *\n * Requires the confirmation code 0x52454E4F554E4345 (\"RENOUNCE\" as u64 LE)\n * to prevent accidental invocation.\n */\nexport function encodeRenounceAdmin(): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.RenounceAdmin),\n encU64(RENOUNCE_ADMIN_CONFIRMATION),\n );\n}\n\n/**\n * CreateInsuranceMint instruction data (1 byte)\n * Creates the SPL mint PDA for insurance LP tokens. Admin only, once per market.\n */\nexport function encodeCreateInsuranceMint(): Uint8Array {\n return encU8(IX_TAG.CreateInsuranceMint);\n}\n\n/**\n * DepositInsuranceLP instruction data (9 bytes)\n * Deposit collateral into insurance fund, receive LP tokens proportional to share.\n */\nexport interface DepositInsuranceLPArgs {\n amount: bigint | string;\n}\n\nexport function encodeDepositInsuranceLP(args: DepositInsuranceLPArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.DepositInsuranceLP), encU64(args.amount));\n}\n\n/**\n * WithdrawInsuranceLP instruction data (9 bytes)\n * Burn LP tokens and withdraw proportional share of insurance fund.\n */\nexport interface WithdrawInsuranceLPArgs {\n lpAmount: bigint | string;\n}\n\nexport function encodeWithdrawInsuranceLP(args: WithdrawInsuranceLPArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.WithdrawInsuranceLP), encU64(args.lpAmount));\n}\n\n// ============================================================================\n// PERC-627 / GH#1926: LpVaultWithdraw (tag 39)\n// ============================================================================\n\n/**\n * LpVaultWithdraw (Tag 39, PERC-627 / GH#1926 / PERC-8287) — burn LP vault tokens and\n * withdraw proportional collateral.\n *\n * **BREAKING (PR#170):** accounts[9] = creatorLockPda is now REQUIRED.\n * Always include `deriveCreatorLockPda(programId, slab)` at position 9.\n * Non-creator withdrawers pass the derived PDA; if no lock exists on-chain\n * the check is a no-op. Omitting this account causes `ExpectLenFailed` on-chain.\n *\n * Instruction data: tag(1) + lp_amount(8) = 9 bytes\n *\n * Accounts (use ACCOUNTS_LP_VAULT_WITHDRAW):\n * [0] withdrawer signer\n * [1] slab writable\n * [2] withdrawerAta writable\n * [3] vault writable\n * [4] tokenProgram\n * [5] lpVaultMint writable\n * [6] withdrawerLpAta writable\n * [7] vaultAuthority\n * [8] lpVaultState writable\n * [9] creatorLockPda writable ← derive with deriveCreatorLockPda(programId, slab)\n *\n * @param lpAmount - Amount of LP vault tokens to burn.\n *\n * @example\n * ```ts\n * import { encodeLpVaultWithdraw, ACCOUNTS_LP_VAULT_WITHDRAW, buildAccountMetas } from \"@percolator/sdk\";\n * import { deriveCreatorLockPda, deriveVaultAuthority } from \"@percolator/sdk\";\n *\n * const [creatorLockPda] = deriveCreatorLockPda(PROGRAM_ID, slabKey);\n * const [vaultAuthority] = deriveVaultAuthority(PROGRAM_ID, slabKey);\n *\n * const data = encodeLpVaultWithdraw({ lpAmount: 1_000_000_000n });\n * const keys = buildAccountMetas(ACCOUNTS_LP_VAULT_WITHDRAW, {\n * withdrawer, slab: slabKey, withdrawerAta, vault, tokenProgram: TOKEN_PROGRAM_ID,\n * lpVaultMint, withdrawerLpAta, vaultAuthority, lpVaultState, creatorLockPda,\n * });\n * ```\n */\nexport interface LpVaultWithdrawArgs {\n /** Amount of LP vault tokens to burn. */\n lpAmount: bigint | string;\n}\n\nexport function encodeLpVaultWithdraw(args: LpVaultWithdrawArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.LpVaultWithdraw), encU64(args.lpAmount));\n}\n\n/**\n * PauseMarket instruction data (1 byte)\n * Pauses the market — disables trading, deposits, and withdrawals.\n */\nexport function encodePauseMarket(): Uint8Array {\n return encU8(IX_TAG.PauseMarket);\n}\n\n/**\n * UnpauseMarket instruction data (1 byte)\n * Unpauses the market — re-enables trading, deposits, and withdrawals.\n */\nexport function encodeUnpauseMarket(): Uint8Array {\n return encU8(IX_TAG.UnpauseMarket);\n}\n\n// ============================================================================\n// PERC-117: Pyth Oracle CPI Instructions\n// ============================================================================\n\n/**\n * SetPythOracle (Tag 32) — switch a market to Pyth-pinned mode.\n *\n * After this instruction:\n * - oracle_authority is cleared → PushOraclePrice is disabled\n * - index_feed_id is set to feed_id → validated on every price read\n * - max_staleness_secs and conf_filter_bps are updated\n * - All price reads go directly to read_pyth_price_e6() with on-chain\n * staleness + confidence + feed-ID validation (no silent fallback)\n *\n * Instruction data: tag(1) + feed_id(32) + max_staleness_secs(8) + conf_filter_bps(2) = 43 bytes\n *\n * Accounts:\n * 0. [signer, writable] Admin\n * 1. [writable] Slab\n */\nexport interface SetPythOracleArgs {\n /** 32-byte Pyth feed ID. All zeros is invalid (reserved for Hyperp mode). */\n feedId: Uint8Array;\n /** Maximum age of Pyth price in seconds before OracleStale is returned. Must be > 0. */\n maxStalenessSecs: bigint;\n /** Max confidence/price ratio in bps (0 = no confidence check). */\n confFilterBps: number;\n}\n\nexport function encodeSetPythOracle(args: SetPythOracleArgs): Uint8Array {\n if (args.feedId.length !== 32) throw new Error('feedId must be 32 bytes');\n if (args.maxStalenessSecs <= 0n) throw new Error('maxStalenessSecs must be > 0');\n\n const buf = new Uint8Array(43);\n const dv = new DataView(buf.buffer);\n\n // Tag 32 (SetPythOracle)\n buf[0] = 32;\n buf.set(args.feedId, 1);\n dv.setBigUint64(33, args.maxStalenessSecs, /* little-endian */ true);\n dv.setUint16(41, args.confFilterBps, true);\n\n return buf;\n}\n\n/**\n * Derive the expected Pyth PriceUpdateV2 account address for a given feed ID.\n * Uses PDA seeds: [shard_id(2), feed_id(32)] under the Pyth Receiver program.\n *\n * @param feedId 32-byte Pyth feed ID\n * @param shardId Shard index (default 0 for mainnet/devnet)\n */\nexport const PYTH_RECEIVER_PROGRAM_ID = 'rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ';\n\nexport async function derivePythPriceUpdateAccount(\n feedId: Uint8Array,\n shardId = 0,\n): Promise<string> {\n const { PublicKey } = await import('@solana/web3.js');\n const shardBuf = new Uint8Array(2);\n new DataView(shardBuf.buffer).setUint16(0, shardId, true);\n const [pda] = PublicKey.findProgramAddressSync(\n [shardBuf, feedId],\n new PublicKey(PYTH_RECEIVER_PROGRAM_ID),\n );\n return pda.toBase58();\n}\n\n// SetPythOracle tag (32) is already defined in IX_TAG above.\n\n// PERC-118: Mark Price EMA Instructions\n// ============================================================================\n\n// Tag 33 — permissionless mark price EMA crank (defined in IX_TAG above).\n\n/**\n * UpdateMarkPrice (Tag 33) — permissionless EMA mark price crank.\n *\n * Reads the current oracle price on-chain, applies 8-hour EMA smoothing\n * with circuit breaker, and writes result to authority_price_e6.\n *\n * Instruction data: 1 byte (tag only — all params read from on-chain state)\n *\n * Accounts:\n * 0. [writable] Slab\n * 1. [] Oracle account (Pyth PriceUpdateV2 / Chainlink / DEX AMM)\n * 2. [] Clock sysvar (SysvarC1ock11111111111111111111111111111111)\n * 3..N [] Remaining accounts (PumpSwap vaults, etc. if needed)\n */\nexport function encodeUpdateMarkPrice(): Uint8Array {\n return new Uint8Array([33]);\n}\n\n/**\n * Mark price EMA parameters (must match program/src/percolator.rs constants).\n */\nexport const MARK_PRICE_EMA_WINDOW_SLOTS = 72_000n;\nexport const MARK_PRICE_EMA_ALPHA_E6 = 2_000_000n / (MARK_PRICE_EMA_WINDOW_SLOTS + 1n);\n\n/**\n * Compute the next EMA mark price step (TypeScript mirror of the on-chain function).\n */\nexport function computeEmaMarkPrice(\n markPrevE6: bigint,\n oracleE6: bigint,\n dtSlots: bigint,\n alphaE6 = MARK_PRICE_EMA_ALPHA_E6,\n capE2bps = 0n,\n): bigint {\n if (oracleE6 === 0n) return markPrevE6;\n if (markPrevE6 === 0n || dtSlots === 0n) return oracleE6;\n\n let oracleClamped = oracleE6;\n if (capE2bps > 0n) {\n // Avoid overflow: divide early to reduce intermediate product\n const maxDelta = (markPrevE6 * capE2bps / 1_000_000n) * dtSlots;\n const lo = markPrevE6 > maxDelta ? markPrevE6 - maxDelta : 0n;\n const hi = markPrevE6 + maxDelta;\n if (oracleClamped < lo) oracleClamped = lo;\n if (oracleClamped > hi) oracleClamped = hi;\n }\n\n const effectiveAlpha = alphaE6 * dtSlots > 1_000_000n ? 1_000_000n : alphaE6 * dtSlots;\n const oneMinusAlpha = 1_000_000n - effectiveAlpha;\n\n return (oracleClamped * effectiveAlpha + markPrevE6 * oneMinusAlpha) / 1_000_000n;\n}\n\n// PERC-119: Hyperp EMA Oracle for Permissionless Tokens\n// ============================================================================\n\n// Tag 34 — permissionless Hyperp mark price oracle (defined in IX_TAG above).\n\n/**\n * UpdateHyperpMark (Tag 34) — permissionless Hyperp EMA oracle crank.\n *\n * Reads the spot price from a PumpSwap, Raydium CLMM, or Meteora DLMM pool,\n * applies 8-hour EMA smoothing with circuit breaker, and writes the new mark\n * to authority_price_e6 on the slab.\n *\n * This is the core mechanism for permissionless token markets — no Pyth or\n * Chainlink feed is needed. The DEX AMM IS the oracle.\n *\n * Instruction data: 1 byte (tag only)\n *\n * Accounts:\n * 0. [writable] Slab\n * 1. [] DEX pool account (PumpSwap / Raydium CLMM / Meteora DLMM)\n * 2. [] Clock sysvar (SysvarC1ock11111111111111111111111111111111)\n * 3..N [] Remaining accounts (e.g. PumpSwap vault0 + vault1)\n */\nexport function encodeUpdateHyperpMark(): Uint8Array {\n return new Uint8Array([34]);\n}\n\n// ============================================================================\n// PERC-306: Per-Market Insurance Isolation\n// ============================================================================\n\n/**\n * Fund per-market isolated insurance balance.\n * Accounts: [admin(signer,writable), slab(writable), admin_ata(writable), vault(writable), token_program]\n */\nexport function encodeFundMarketInsurance(args: { amount: bigint }): Uint8Array {\n return concatBytes(encU8(IX_TAG.FundMarketInsurance), encU64(args.amount));\n}\n\n/**\n * Set insurance isolation BPS for a market.\n * Accounts: [admin(signer), slab(writable)]\n */\nexport function encodeSetInsuranceIsolation(args: { bps: number }): Uint8Array {\n return concatBytes(encU8(IX_TAG.SetInsuranceIsolation), encU16(args.bps));\n}\n\n// ============================================================================\n// NOTE: encodeExecuteAdl() was historically removed when it was discovered\n// that PERC-305 was NOT implemented on-chain and tag 43 was ChallengeSettlement.\n// PERC-305 (ExecuteAdl) is now live at tag 50. Encoder added below.\n// ============================================================================\n\n// ============================================================================\n// PERC-309: QueueWithdrawal / ClaimQueuedWithdrawal / CancelQueuedWithdrawal\n// ============================================================================\n\n/**\n * QueueWithdrawal (Tag 47, PERC-309) — queue a large LP withdrawal.\n *\n * Creates a withdraw_queue PDA. The LP tokens are claimed in epoch tranches\n * via ClaimQueuedWithdrawal. Call CancelQueuedWithdrawal to abort.\n *\n * Accounts: [user(signer,writable), slab(writable), lpVaultState, withdrawQueue(writable), systemProgram]\n *\n * @param lpAmount - Amount of LP tokens to queue for withdrawal.\n *\n * @example\n * ```ts\n * const data = encodeQueueWithdrawal({ lpAmount: 1_000_000_000n });\n * ```\n */\nexport function encodeQueueWithdrawal(args: { lpAmount: bigint | string }): Uint8Array {\n return concatBytes(encU8(IX_TAG.QueueWithdrawal), encU64(args.lpAmount));\n}\n\n/**\n * ClaimQueuedWithdrawal (Tag 48, PERC-309) — claim one epoch tranche from a queued withdrawal.\n *\n * Burns LP tokens and releases one tranche of SOL to the user.\n * Call once per epoch until epochs_remaining == 0.\n *\n * Accounts: [user(signer,writable), slab(writable), withdrawQueue(writable),\n * lpVaultMint(writable), userLpAta(writable), vault(writable),\n * userAta(writable), vaultAuthority, tokenProgram, lpVaultState(writable)]\n */\nexport function encodeClaimQueuedWithdrawal(): Uint8Array {\n return encU8(IX_TAG.ClaimQueuedWithdrawal);\n}\n\n/**\n * CancelQueuedWithdrawal (Tag 49, PERC-309) — cancel a queued withdrawal, refund remaining LP.\n *\n * Closes the withdraw_queue PDA and returns its rent lamports to the user.\n * The queued LP amount that was not yet claimed is NOT refunded — it is burned.\n * Use only to abandon a partial withdrawal.\n *\n * Accounts: [user(signer,writable), slab, withdrawQueue(writable)]\n */\nexport function encodeCancelQueuedWithdrawal(): Uint8Array {\n return encU8(IX_TAG.CancelQueuedWithdrawal);\n}\n\n// ============================================================================\n// PERC-305: ExecuteAdl (Tag 50) — Auto-Deleverage\n// ============================================================================\n\n/**\n * ExecuteAdl (Tag 50, PERC-305) — auto-deleverage the most profitable position.\n *\n * Permissionless. Surgically closes or reduces `targetIdx` position when\n * `pnl_pos_tot > max_pnl_cap` on the market. The caller receives no reward —\n * the incentive is unblocking the market for normal trading.\n *\n * Requires `UpdateRiskParams.max_pnl_cap > 0` on the market.\n *\n * Accounts: [caller(signer), slab(writable), clock, oracle, ...backupOracles?]\n *\n * @param targetIdx - Account index of the position to deleverage.\n *\n * @example\n * ```ts\n * const data = encodeExecuteAdl({ targetIdx: 5 });\n * ```\n */\nexport interface ExecuteAdlArgs {\n targetIdx: number;\n}\n\nexport function encodeExecuteAdl(args: ExecuteAdlArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.ExecuteAdl), encU16(args.targetIdx));\n}\n\n// ============================================================================\n// CloseStaleSlabs (Tag 51) / ReclaimSlabRent (Tag 52) — Slab recovery\n// ============================================================================\n\n/**\n * CloseStaleSlabs (Tag 51) — close a slab of an invalid/old layout and recover rent SOL.\n *\n * Admin only. Skips slab_guard; validates header magic + admin authority instead.\n * Use for slabs created by old program layouts (e.g. pre-PERC-120 devnet deploys)\n * whose size does not match any current valid tier.\n *\n * Accounts: [dest(signer,writable), slab(writable)]\n */\nexport function encodeCloseStaleSlabs(): Uint8Array {\n return encU8(IX_TAG.CloseStaleSlabs);\n}\n\n/**\n * ReclaimSlabRent (Tag 52) — reclaim rent from an uninitialised slab.\n *\n * For use when market creation failed mid-flow (slab funded but InitMarket not called).\n * The slab account must sign (proves the caller holds the slab keypair).\n * Cannot close an initialised slab (magic == PERCOLAT) — use CloseSlab (tag 13).\n *\n * Accounts: [dest(signer,writable), slab(signer,writable)]\n */\nexport function encodeReclaimSlabRent(): Uint8Array {\n return encU8(IX_TAG.ReclaimSlabRent);\n}\n\n// ============================================================================\n// AuditCrank (Tag 53) — Permissionless on-chain invariant check\n// ============================================================================\n\n/**\n * AuditCrank (Tag 53) — verify conservation invariants on-chain (permissionless).\n *\n * Walks all accounts and verifies: capital sum, pnl_pos_tot, total_oi, LP consistency,\n * and solvency. Sets FLAG_PAUSED on violation (with a 150-slot cooldown guard to\n * prevent DoS from transient failures).\n *\n * Accounts: [slab(writable)]\n *\n * @example\n * ```ts\n * const data = encodeAuditCrank();\n * ```\n */\nexport function encodeAuditCrank(): Uint8Array {\n return encU8(IX_TAG.AuditCrank);\n}\n\n// ============================================================================\n// SMART PRICE ROUTER — quote computation for LP selection\n// ============================================================================\n\n/**\n * Parsed vAMM matcher parameters (from on-chain matcher context account)\n */\nexport interface VammMatcherParams {\n mode: number; // 0 = Passive, 1 = vAMM\n tradingFeeBps: number;\n baseSpreadBps: number;\n maxTotalBps: number;\n impactKBps: number;\n liquidityNotionalE6: bigint;\n}\n\n/** Magic bytes identifying a vAMM matcher context: \"PERCMATC\" as u64 LE */\nexport const VAMM_MAGIC = 0x5045_5243_4d41_5443n;\n\n/** Offset into matcher context where vAMM params start */\nexport const CTX_VAMM_OFFSET = 64;\n\nconst BPS_DENOM = 10_000n;\n\n/**\n * Compute execution price for a given LP quote.\n * For buys (isLong=true): price above oracle.\n * For sells (isLong=false): price below oracle.\n */\nexport function computeVammQuote(\n params: VammMatcherParams,\n oraclePriceE6: bigint,\n tradeSize: bigint,\n isLong: boolean,\n): bigint {\n const absSize = tradeSize < 0n ? -tradeSize : tradeSize;\n const absNotionalE6 = (absSize * oraclePriceE6) / 1_000_000n;\n\n // Impact for vAMM mode\n let impactBps = 0n;\n if (params.mode === 1 && params.liquidityNotionalE6 > 0n) {\n impactBps = (absNotionalE6 * BigInt(params.impactKBps)) / params.liquidityNotionalE6;\n }\n\n // Total = base_spread + trading_fee + impact, capped at max_total\n const maxTotal = BigInt(params.maxTotalBps);\n const baseFee = BigInt(params.baseSpreadBps) + BigInt(params.tradingFeeBps);\n const maxImpact = maxTotal > baseFee ? maxTotal - baseFee : 0n;\n const clampedImpact = impactBps < maxImpact ? impactBps : maxImpact;\n let totalBps = baseFee + clampedImpact;\n if (totalBps > maxTotal) totalBps = maxTotal;\n\n if (isLong) {\n return (oraclePriceE6 * (BPS_DENOM + totalBps)) / BPS_DENOM;\n } else {\n // Prevent underflow: if totalBps >= BPS_DENOM, price would go negative\n if (totalBps >= BPS_DENOM) return 1n; // minimum 1 micro-dollar\n return (oraclePriceE6 * (BPS_DENOM - totalBps)) / BPS_DENOM;\n }\n}\n\n// ============================================================================\n// PERC-622: AdvanceOraclePhase (permissionless crank)\n// ============================================================================\n\n/**\n * AdvanceOraclePhase (Tag 56) — permissionless oracle phase advancement.\n *\n * Checks if a market should transition from Phase 0→1→2 based on\n * time elapsed and cumulative volume. Anyone can call this.\n *\n * Instruction data: 1 byte (tag only)\n *\n * Accounts:\n * 0. [writable] Slab\n */\nexport function encodeAdvanceOraclePhase(): Uint8Array {\n return encU8(IX_TAG.AdvanceOraclePhase);\n}\n\n/** Oracle phase constants matching on-chain values */\nexport const ORACLE_PHASE_NASCENT = 0;\nexport const ORACLE_PHASE_GROWING = 1;\nexport const ORACLE_PHASE_MATURE = 2;\n\n/** Phase transition thresholds (must match program constants) */\nexport const PHASE1_MIN_SLOTS = 648_000n; // ~72h at 400ms\nexport const PHASE1_VOLUME_MIN_SLOTS = 36_000n; // ~4h at 400ms\nexport const PHASE2_VOLUME_THRESHOLD = 100_000_000_000n; // $100K in e6\nexport const PHASE2_MATURITY_SLOTS = 3_024_000n; // ~14 days at 400ms\n\n/**\n * Check if an oracle phase transition is due (TypeScript mirror of on-chain logic).\n *\n * @returns [newPhase, shouldTransition]\n */\nexport function checkPhaseTransition(\n currentSlot: bigint,\n marketCreatedSlot: bigint,\n oraclePhase: number,\n cumulativeVolumeE6: bigint,\n phase2DeltaSlots: number,\n hasMatureOracle: boolean,\n): [number, boolean] {\n switch (oraclePhase) {\n case 0: {\n const elapsed = currentSlot - (marketCreatedSlot > 0n ? marketCreatedSlot : currentSlot);\n const timeReady = elapsed >= PHASE1_MIN_SLOTS;\n const volumeReady = elapsed >= PHASE1_VOLUME_MIN_SLOTS\n && cumulativeVolumeE6 >= PHASE2_VOLUME_THRESHOLD;\n if (timeReady || volumeReady) {\n return [ORACLE_PHASE_GROWING, true];\n }\n return [ORACLE_PHASE_NASCENT, false];\n }\n case 1: {\n if (hasMatureOracle) return [ORACLE_PHASE_MATURE, true];\n const phase2Start = marketCreatedSlot + BigInt(phase2DeltaSlots);\n const elapsedSincePhase2 = currentSlot - phase2Start;\n if (elapsedSincePhase2 >= PHASE2_MATURITY_SLOTS) {\n return [ORACLE_PHASE_MATURE, true];\n }\n return [ORACLE_PHASE_GROWING, false];\n }\n default:\n return [ORACLE_PHASE_MATURE, false];\n }\n}\n\n// ============================================================================\n// PERC-623: Keeper Fund Instructions\n// ============================================================================\n\n/**\n * TopUpKeeperFund (Tag 57) — permissionless keeper fund top-up.\n *\n * Instruction data: tag(1) + amount(8) = 9 bytes\n *\n * Accounts:\n * 0. [signer, writable] Funder\n * 1. [writable] Slab\n * 2. [writable] Keeper fund PDA\n * 3. [] System program\n */\nexport interface TopUpKeeperFundArgs {\n amount: bigint | string;\n}\n\nexport function encodeTopUpKeeperFund(args: TopUpKeeperFundArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.TopUpKeeperFund), encU64(args.amount));\n}\n\n// Note: WithdrawKeeperReward does NOT exist as a separate instruction.\n// Keeper rewards are paid automatically during KeeperCrank (tag 5).\n// The keeper fund PDA is debited in-place when a successful crank is executed.\n\n// ============================================================================\n// PERC-629: Dynamic Creation Deposit\n// ============================================================================\n\n/**\n * SlashCreationDeposit (Tag 58) — permissionless: slash a market creator's deposit\n * after the spam grace period has elapsed (PERC-629).\n *\n * **WARNING**: Tag 58 is reserved in tags.rs but has NO instruction decoder or\n * handler in the on-chain program. Sending this instruction will fail with\n * `InvalidInstructionData`. Do not use until the on-chain handler is deployed.\n *\n * Instruction data: 1 byte (tag only)\n *\n * Accounts:\n * 0. [signer] Caller (anyone)\n * 1. [] Slab\n * 2. [writable] Creator history PDA\n * 3. [writable] Insurance vault\n * 4. [writable] Treasury\n * 5. [] System program\n *\n * @deprecated Not yet implemented on-chain — will fail with InvalidInstructionData.\n */\nexport function encodeSlashCreationDeposit(): Uint8Array {\n return encU8(IX_TAG.SlashCreationDeposit);\n}\n\n// ============================================================================\n// PERC-628: Elastic Shared Vault + Epoch Withdrawals\n// ============================================================================\n\n/**\n * InitSharedVault (Tag 59) — admin: create the global shared vault PDA (PERC-628).\n *\n * Instruction data: tag(1) + epochDurationSlots(8) + maxMarketExposureBps(2) = 11 bytes\n *\n * Accounts:\n * 0. [signer] Admin\n * 1. [writable] Shared vault PDA\n * 2. [] System program\n */\nexport interface InitSharedVaultArgs {\n epochDurationSlots: bigint | string;\n maxMarketExposureBps: number;\n}\n\nexport function encodeInitSharedVault(args: InitSharedVaultArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.InitSharedVault),\n encU64(args.epochDurationSlots),\n encU16(args.maxMarketExposureBps),\n );\n}\n\n/**\n * AllocateMarket (Tag 60) — admin: allocate virtual liquidity from the shared vault\n * to a market (PERC-628).\n *\n * Instruction data: tag(1) + amount(16) = 17 bytes\n *\n * Accounts:\n * 0. [signer] Admin\n * 1. [] Slab\n * 2. [writable] Shared vault PDA\n * 3. [writable] Market alloc PDA\n * 4. [] System program\n */\nexport interface AllocateMarketArgs {\n amount: bigint | string;\n}\n\nexport function encodeAllocateMarket(args: AllocateMarketArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.AllocateMarket), encU128(args.amount));\n}\n\n/**\n * QueueWithdrawalSV (Tag 61) — user: queue a withdrawal request for the current\n * epoch (PERC-628). Tokens are locked until the epoch elapses.\n *\n * Instruction data: tag(1) + lpAmount(8) = 9 bytes\n *\n * Accounts:\n * 0. [signer] User\n * 1. [writable] Shared vault PDA\n * 2. [writable] Withdraw request PDA\n * 3. [] System program\n */\nexport interface QueueWithdrawalSVArgs {\n lpAmount: bigint | string;\n}\n\nexport function encodeQueueWithdrawalSV(args: QueueWithdrawalSVArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.QueueWithdrawalSV), encU64(args.lpAmount));\n}\n\n/**\n * ClaimEpochWithdrawal (Tag 62) — user: claim a queued withdrawal after the epoch\n * has elapsed (PERC-628). Receives pro-rata collateral from the vault.\n *\n * Instruction data: 1 byte (tag only)\n *\n * Accounts:\n * 0. [signer] User\n * 1. [writable] Shared vault PDA\n * 2. [writable] Withdraw request PDA\n * 3. [] Slab\n * 4. [writable] Vault\n * 5. [writable] User ATA\n * 6. [] Vault authority\n * 7. [] Token program\n */\nexport function encodeClaimEpochWithdrawal(): Uint8Array {\n return encU8(IX_TAG.ClaimEpochWithdrawal);\n}\n\n/**\n * AdvanceEpoch (Tag 63) — permissionless crank: move the shared vault to the next\n * epoch once `epoch_duration_slots` have elapsed (PERC-628).\n *\n * Instruction data: 1 byte (tag only)\n *\n * Accounts:\n * 0. [signer] Caller (anyone)\n * 1. [writable] Shared vault PDA\n */\nexport function encodeAdvanceEpoch(): Uint8Array {\n return encU8(IX_TAG.AdvanceEpoch);\n}\n\n// PERC-628: Tag 63 ─────────────────────────────────────────────────────────\n\n// PERC-8110 ────────────────────────────────────────────────────────────────\n\n/**\n * SetOiImbalanceHardBlock (Tag 71, PERC-8110) — set OI imbalance hard-block threshold (admin only).\n *\n * When `|long_oi − short_oi| / total_oi * 10_000 >= threshold_bps`, any new trade that would\n * *increase* the imbalance is rejected with `OiImbalanceHardBlock` (error code 59).\n *\n * - `threshold_bps = 0`: hard block disabled.\n * - `threshold_bps = 8_000`: block trades that push skew above 80%.\n * - `threshold_bps = 10_000`: never allow >100% skew (always blocks one side when oi > 0).\n *\n * Instruction data layout: tag(1) + threshold_bps(2) = 3 bytes\n *\n * Accounts:\n * 0. [signer] admin\n * 1. [writable] slab\n *\n * @example\n * ```ts\n * const ix = new TransactionInstruction({\n * programId: PROGRAM_ID,\n * keys: buildAccountMetas(ACCOUNTS_SET_OI_IMBALANCE_HARD_BLOCK, { admin, slab }),\n * data: Buffer.from(encodeSetOiImbalanceHardBlock({ thresholdBps: 8_000 })),\n * });\n * ```\n */\nexport function encodeSetOiImbalanceHardBlock(args: { thresholdBps: number }): Uint8Array {\n if (args.thresholdBps < 0 || args.thresholdBps > 10_000) {\n throw new Error(`encodeSetOiImbalanceHardBlock: thresholdBps must be 0–10_000, got ${args.thresholdBps}`);\n }\n return concatBytes(encU8(IX_TAG.SetOiImbalanceHardBlock), encU16(args.thresholdBps));\n}\n\n// ============================================================================\n// PERC-608 — Position NFT instructions (tags 64–69)\n// ============================================================================\n\n/**\n * MintPositionNft (Tag 64, PERC-608) — mint a Token-2022 NFT representing a position.\n *\n * Creates a PositionNft PDA + Token-2022 mint with metadata, then mints 1 NFT to the\n * position owner's ATA. The NFT represents ownership of `user_idx` in the slab.\n *\n * Instruction data layout: tag(1) + user_idx(2) = 3 bytes\n *\n * Accounts:\n * 0. [signer, writable] payer\n * 1. [writable] slab\n * 2. [writable] position_nft PDA (created — seeds: [\"position_nft\", slab, user_idx])\n * 3. [writable] nft_mint PDA (created)\n * 4. [writable] owner_ata (Token-2022 ATA for owner)\n * 5. [signer] owner (must match engine account owner)\n * 6. [] vault_authority PDA\n * 7. [] token_2022_program\n * 8. [] system_program\n * 9. [] rent sysvar\n *\n * @example\n * ```ts\n * const ix = new TransactionInstruction({\n * programId: PROGRAM_ID,\n * keys: buildAccountMetas(ACCOUNTS_MINT_POSITION_NFT, [payer, slab, nftPda, nftMint, ownerAta, owner, vaultAuth, TOKEN_2022_PROGRAM_ID, SystemProgram.programId, SYSVAR_RENT_PUBKEY]),\n * data: Buffer.from(encodeMintPositionNft({ userIdx: 5 })),\n * });\n * ```\n */\nexport interface MintPositionNftArgs {\n userIdx: number;\n}\n\nexport function encodeMintPositionNft(args: MintPositionNftArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.MintPositionNft), encU16(args.userIdx));\n}\n\n/**\n * TransferPositionOwnership (Tag 65, PERC-608) — transfer an open position to a new owner.\n *\n * Transfers the Token-2022 NFT from current owner to new owner and updates the on-chain\n * engine account's owner field. Requires `pending_settlement == 0`.\n *\n * Instruction data layout: tag(1) + user_idx(2) = 3 bytes\n *\n * Accounts:\n * 0. [signer, writable] current_owner\n * 1. [writable] slab\n * 2. [writable] position_nft PDA\n * 3. [writable] nft_mint PDA\n * 4. [writable] current_owner_ata (source Token-2022 ATA)\n * 5. [writable] new_owner_ata (destination Token-2022 ATA)\n * 6. [] new_owner\n * 7. [] token_2022_program\n */\nexport interface TransferPositionOwnershipArgs {\n userIdx: number;\n}\n\nexport function encodeTransferPositionOwnership(args: TransferPositionOwnershipArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.TransferPositionOwnership), encU16(args.userIdx));\n}\n\n/**\n * BurnPositionNft (Tag 66, PERC-608) — burn the Position NFT when a position is closed.\n *\n * Burns the NFT, closes the PositionNft PDA and the mint PDA, returning rent to the owner.\n * Can only be called after the position is fully closed (size == 0).\n *\n * Instruction data layout: tag(1) + user_idx(2) = 3 bytes\n *\n * Accounts:\n * 0. [signer, writable] owner\n * 1. [writable] slab\n * 2. [writable] position_nft PDA (closed — rent to owner)\n * 3. [writable] nft_mint PDA (closed via Token-2022 close_account)\n * 4. [writable] owner_ata (Token-2022 ATA, balance burned)\n * 5. [] vault_authority PDA\n * 6. [] token_2022_program\n */\nexport interface BurnPositionNftArgs {\n userIdx: number;\n}\n\nexport function encodeBurnPositionNft(args: BurnPositionNftArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.BurnPositionNft), encU16(args.userIdx));\n}\n\n/**\n * SetPendingSettlement (Tag 67, PERC-608) — keeper sets the pending_settlement flag.\n *\n * Called by the keeper/admin before performing a funding settlement transfer.\n * Blocks NFT transfers until ClearPendingSettlement is called.\n * Admin-only (protected by GH#1475 keeper allowlist guard).\n *\n * Instruction data layout: tag(1) + user_idx(2) = 3 bytes\n *\n * Accounts:\n * 0. [signer] keeper / admin\n * 1. [] slab (read — for PDA verification + admin check)\n * 2. [writable] position_nft PDA\n */\nexport interface SetPendingSettlementArgs {\n userIdx: number;\n}\n\nexport function encodeSetPendingSettlement(args: SetPendingSettlementArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.SetPendingSettlement), encU16(args.userIdx));\n}\n\n/**\n * ClearPendingSettlement (Tag 68, PERC-608) — keeper clears the pending_settlement flag.\n *\n * Called by the keeper/admin after KeeperCrank has run and funding is settled.\n * Admin-only (protected by GH#1475 keeper allowlist guard).\n *\n * Instruction data layout: tag(1) + user_idx(2) = 3 bytes\n *\n * Accounts:\n * 0. [signer] keeper / admin\n * 1. [] slab (read — for PDA verification + admin check)\n * 2. [writable] position_nft PDA\n */\nexport interface ClearPendingSettlementArgs {\n userIdx: number;\n}\n\nexport function encodeClearPendingSettlement(args: ClearPendingSettlementArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.ClearPendingSettlement), encU16(args.userIdx));\n}\n\n/**\n * TransferOwnershipCpi (Tag 69, PERC-608) — internal CPI target for percolator-nft TransferHook.\n *\n * Called by the Token-2022 TransferHook on the percolator-nft program during an NFT transfer.\n * Updates the engine account's owner field to the new_owner public key.\n * NOT intended for direct external use — always called via Token-2022 CPI.\n *\n * Instruction data layout: tag(1) + user_idx(2) + new_owner(32) = 35 bytes\n *\n * Accounts:\n * 0. [signer] nft TransferHook program (CPI caller)\n * 1. [writable] slab\n * (remaining accounts per Token-2022 ExtraAccountMeta spec)\n */\nexport interface TransferOwnershipCpiArgs {\n userIdx: number;\n newOwner: PublicKey | string;\n}\n\nexport function encodeTransferOwnershipCpi(args: TransferOwnershipCpiArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.TransferOwnershipCpi),\n encU16(args.userIdx),\n encPubkey(args.newOwner),\n );\n}\n\n// ============================================================================\n// PERC-8111 — SetWalletCap (tag 70)\n// ============================================================================\n\n/**\n * SetWalletCap (Tag 70, PERC-8111) — set the per-wallet position cap (admin only).\n *\n * Limits the maximum absolute position size any single wallet may hold on this market.\n * Enforced on every trade (TradeNoCpi + TradeCpi) after execute_trade.\n *\n * - `capE6 = 0`: disable per-wallet cap (no limit, default).\n * - `capE6 > 0`: max |position_size| in e6 units ($1 = 1_000_000).\n * Phase 1 launch value: 1_000_000_000n ($1,000).\n *\n * When a trade would breach the cap, the on-chain error `WalletPositionCapExceeded`\n * (error code 58) is returned.\n *\n * Instruction data layout: tag(1) + cap_e6(8) = 9 bytes\n *\n * Accounts:\n * 0. [signer] admin\n * 1. [writable] slab\n *\n * @example\n * ```ts\n * // Set $1K per-wallet cap\n * const ix = new TransactionInstruction({\n * programId: PROGRAM_ID,\n * keys: buildAccountMetas(ACCOUNTS_SET_WALLET_CAP, [admin, slab]),\n * data: Buffer.from(encodeSetWalletCap({ capE6: 1_000_000_000n })),\n * });\n *\n * // Disable cap\n * const disableIx = new TransactionInstruction({\n * programId: PROGRAM_ID,\n * keys: buildAccountMetas(ACCOUNTS_SET_WALLET_CAP, [admin, slab]),\n * data: Buffer.from(encodeSetWalletCap({ capE6: 0n })),\n * });\n * ```\n */\nexport interface SetWalletCapArgs {\n /** Max position size in e6 units. 0 = disabled. $1 = 1_000_000n, $1K = 1_000_000_000n. */\n capE6: bigint | string;\n}\n\nexport function encodeSetWalletCap(args: SetWalletCapArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.SetWalletCap), encU64(args.capE6));\n}\n\n// ============================================================================\n// InitMatcherCtx — CPI to matcher program to initialize a matcher context (tag 75)\n// ============================================================================\n\n/**\n * InitMatcherCtx (Tag 75) — admin initializes the matcher context account for an LP slot.\n *\n * The matcher program (DHP6DtwXP1yJsz8YzfoeigRFPB979gzmumkmCxDLSkUX) requires its context\n * account to be initialized before TradeCpi can work. Only the percolator program can sign\n * as the LP PDA via invoke_signed, so this instruction acts as the trusted initializer.\n *\n * Instruction data layout: tag(1) + lp_idx(2) + kind(1) + trading_fee_bps(4) +\n * base_spread_bps(4) + max_total_bps(4) + impact_k_bps(4) +\n * liquidity_notional_e6(16) + max_fill_abs(16) + max_inventory_abs(16) +\n * fee_to_insurance_bps(2) + skew_spread_mult_bps(2) = 72 bytes\n *\n * Accounts:\n * 0. [signer] admin\n * 1. [] slab (program-owned; used to verify admin + LP slot)\n * 2. [writable] matcherCtx (must match LP's stored matcher_context)\n * 3. [] matcherProg (executable; must match LP's stored matcher_program)\n * 4. [] lpPda (PDA [\"lp\", slab, lp_idx]; required by CPI as signer)\n */\nexport interface InitMatcherCtxArgs {\n /** LP account index in the engine (0-based). */\n lpIdx: number;\n /** Matcher kind: 0=Passive, 1=vAMM. */\n kind: number;\n /** Base trading fee in bps (e.g. 30 = 0.30%). */\n tradingFeeBps: number;\n /** Base spread in bps. */\n baseSpreadBps: number;\n /** Max total spread in bps. */\n maxTotalBps: number;\n /** vAMM impact constant in bps (0 for passive matchers). */\n impactKBps: number;\n /** Liquidity notional in e6 units (0 for passive matchers). */\n liquidityNotionalE6: bigint | string;\n /** Max single fill size in absolute units (u128::MAX = no limit). */\n maxFillAbs: bigint | string;\n /** Max inventory size in absolute units (u128::MAX = no limit). */\n maxInventoryAbs: bigint | string;\n /** Fraction of fees routed to insurance fund in bps. */\n feeToInsuranceBps: number;\n /** Skew spread multiplier in bps (0 = disabled). */\n skewSpreadMultBps: number;\n}\n\nexport function encodeInitMatcherCtx(args: InitMatcherCtxArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.InitMatcherCtx),\n encU16(args.lpIdx),\n encU8(args.kind),\n encU32(args.tradingFeeBps),\n encU32(args.baseSpreadBps),\n encU32(args.maxTotalBps),\n encU32(args.impactKBps),\n encU128(args.liquidityNotionalE6),\n encU128(args.maxFillAbs),\n encU128(args.maxInventoryAbs),\n encU16(args.feeToInsuranceBps),\n encU16(args.skewSpreadMultBps),\n );\n}\n","import {\n PublicKey,\n AccountMeta,\n SYSVAR_CLOCK_PUBKEY,\n SYSVAR_RENT_PUBKEY,\n SystemProgram,\n} from \"@solana/web3.js\";\nimport { TOKEN_PROGRAM_ID } from \"@solana/spl-token\";\n\n/**\n * Account spec for building instruction account metas.\n * Each instruction has a fixed ordering that matches the Rust processor.\n */\nexport interface AccountSpec {\n name: string;\n signer: boolean;\n writable: boolean;\n}\n\n// ============================================================================\n// ACCOUNT ORDERINGS - Single source of truth\n// ============================================================================\n\n/**\n * InitMarket: 9 accounts (Pyth Pull - feed_id is in instruction data, not as accounts)\n */\nexport const ACCOUNTS_INIT_MARKET: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"mint\", signer: false, writable: false },\n { name: \"vault\", signer: false, writable: false },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"clock\", signer: false, writable: false },\n { name: \"rent\", signer: false, writable: false },\n { name: \"dummyAta\", signer: false, writable: false },\n { name: \"systemProgram\", signer: false, writable: false },\n] as const;\n\n/**\n * InitUser: 5 accounts (clock/oracle removed in commit 410f947)\n */\nexport const ACCOUNTS_INIT_USER: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"userAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n] as const;\n\n/**\n * InitLP: 5 accounts (clock/oracle removed in commit 410f947)\n */\nexport const ACCOUNTS_INIT_LP: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"userAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n] as const;\n\n/**\n * DepositCollateral: 6 accounts\n */\nexport const ACCOUNTS_DEPOSIT_COLLATERAL: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"userAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"clock\", signer: false, writable: false },\n] as const;\n\n/**\n * WithdrawCollateral: 8 accounts\n */\nexport const ACCOUNTS_WITHDRAW_COLLATERAL: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"userAta\", signer: false, writable: true },\n { name: \"vaultPda\", signer: false, writable: false },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"clock\", signer: false, writable: false },\n { name: \"oracleIdx\", signer: false, writable: false },\n] as const;\n\n/**\n * KeeperCrank: 4 accounts\n */\nexport const ACCOUNTS_KEEPER_CRANK: readonly AccountSpec[] = [\n { name: \"caller\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"clock\", signer: false, writable: false },\n { name: \"oracle\", signer: false, writable: false },\n] as const;\n\n/**\n * TradeNoCpi: 4 accounts (PERC-199: clock sysvar removed — uses Clock::get() syscall)\n */\nexport const ACCOUNTS_TRADE_NOCPI: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"lp\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"oracle\", signer: false, writable: false },\n] as const;\n\n/**\n * LiquidateAtOracle: 4 accounts\n * Note: account[0] is unused but must be present\n */\nexport const ACCOUNTS_LIQUIDATE_AT_ORACLE: readonly AccountSpec[] = [\n { name: \"unused\", signer: false, writable: false },\n { name: \"slab\", signer: false, writable: true },\n { name: \"clock\", signer: false, writable: false },\n { name: \"oracle\", signer: false, writable: false },\n] as const;\n\n/**\n * CloseAccount: 8 accounts\n */\nexport const ACCOUNTS_CLOSE_ACCOUNT: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"userAta\", signer: false, writable: true },\n { name: \"vaultPda\", signer: false, writable: false },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"clock\", signer: false, writable: false },\n { name: \"oracle\", signer: false, writable: false },\n] as const;\n\n/**\n * TopUpInsurance: 5 accounts\n */\nexport const ACCOUNTS_TOPUP_INSURANCE: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"userAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n] as const;\n\n/**\n * TradeCpi: 7 accounts (PERC-199: clock sysvar removed — uses Clock::get() syscall)\n */\nexport const ACCOUNTS_TRADE_CPI: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"lpOwner\", signer: false, writable: false }, // LP delegated to matcher - no signature needed\n { name: \"slab\", signer: false, writable: true },\n { name: \"oracle\", signer: false, writable: false },\n { name: \"matcherProg\", signer: false, writable: false },\n { name: \"matcherCtx\", signer: false, writable: true },\n { name: \"lpPda\", signer: false, writable: false },\n] as const;\n\n/**\n * SetRiskThreshold: 2 accounts\n */\nexport const ACCOUNTS_SET_RISK_THRESHOLD: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * UpdateAdmin: 2 accounts\n */\nexport const ACCOUNTS_UPDATE_ADMIN: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * CloseSlab: 2 accounts\n */\nexport const ACCOUNTS_CLOSE_SLAB: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * UpdateConfig: 2 accounts\n */\nexport const ACCOUNTS_UPDATE_CONFIG: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * SetMaintenanceFee: 2 accounts\n */\nexport const ACCOUNTS_SET_MAINTENANCE_FEE: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * SetOracleAuthority: 2 accounts\n * Sets the oracle price authority (admin only)\n */\nexport const ACCOUNTS_SET_ORACLE_AUTHORITY: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * SetOraclePriceCap: 2 accounts\n * Set oracle price circuit breaker cap (admin only)\n */\nexport const ACCOUNTS_SET_ORACLE_PRICE_CAP: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * PushOraclePrice: 2 accounts\n * Push oracle price (oracle authority only)\n */\nexport const ACCOUNTS_PUSH_ORACLE_PRICE: readonly AccountSpec[] = [\n { name: \"authority\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * ResolveMarket: 2 accounts\n * Resolves a binary/premarket (admin only)\n */\nexport const ACCOUNTS_RESOLVE_MARKET: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * WithdrawInsurance: 6 accounts\n * Withdraw insurance fund after market resolution (admin only)\n */\nexport const ACCOUNTS_WITHDRAW_INSURANCE: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"adminAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"vaultPda\", signer: false, writable: false },\n] as const;\n\n/**\n * PauseMarket: 2 accounts\n */\nexport const ACCOUNTS_PAUSE_MARKET: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * UnpauseMarket: 2 accounts\n */\nexport const ACCOUNTS_UNPAUSE_MARKET: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// ACCOUNT META BUILDERS\n// ============================================================================\n\n/**\n * Build AccountMeta array from spec and provided pubkeys.\n *\n * Accepts either:\n * - `PublicKey[]` — ordered array, one entry per spec account (legacy form)\n * - `Record<string, PublicKey>` — named map keyed by account `name` (preferred form)\n *\n * Named-map form resolves accounts by spec name so callers don't have to\n * remember the positional order, and errors clearly on missing names.\n */\nexport function buildAccountMetas(\n spec: readonly AccountSpec[],\n keys: PublicKey[] | Record<string, PublicKey>\n): AccountMeta[] {\n let keysArray: PublicKey[];\n\n if (Array.isArray(keys)) {\n keysArray = keys;\n } else {\n // Named map: resolve by spec name\n keysArray = spec.map((s) => {\n const key = (keys as Record<string, PublicKey>)[s.name];\n if (!key) {\n throw new Error(\n `buildAccountMetas: missing key for account \"${s.name}\". ` +\n `Provided keys: [${Object.keys(keys).join(\", \")}]`\n );\n }\n return key;\n });\n }\n\n if (keysArray.length !== spec.length) {\n throw new Error(\n `Account count mismatch: expected ${spec.length}, got ${keysArray.length}`\n );\n }\n return spec.map((s, i) => ({\n pubkey: keysArray[i],\n isSigner: s.signer,\n isWritable: s.writable,\n }));\n}\n\n/**\n * CreateInsuranceMint: 9 accounts\n * Creates SPL mint PDA for insurance LP tokens. Admin only, once per market.\n */\nexport const ACCOUNTS_CREATE_INSURANCE_MINT: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: false },\n { name: \"insLpMint\", signer: false, writable: true },\n { name: \"vaultAuthority\", signer: false, writable: false },\n { name: \"collateralMint\", signer: false, writable: false },\n { name: \"systemProgram\", signer: false, writable: false },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"rent\", signer: false, writable: false },\n { name: \"payer\", signer: true, writable: true },\n] as const;\n\n/**\n * DepositInsuranceLP: 8 accounts\n * Deposit collateral into insurance fund, receive LP tokens.\n */\nexport const ACCOUNTS_DEPOSIT_INSURANCE_LP: readonly AccountSpec[] = [\n { name: \"depositor\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n { name: \"depositorAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"insLpMint\", signer: false, writable: true },\n { name: \"depositorLpAta\", signer: false, writable: true },\n { name: \"vaultAuthority\", signer: false, writable: false },\n] as const;\n\n/**\n * WithdrawInsuranceLP: 8 accounts\n * Burn LP tokens and withdraw proportional share of insurance fund.\n */\nexport const ACCOUNTS_WITHDRAW_INSURANCE_LP: readonly AccountSpec[] = [\n { name: \"withdrawer\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n { name: \"withdrawerAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"insLpMint\", signer: false, writable: true },\n { name: \"withdrawerLpAta\", signer: false, writable: true },\n { name: \"vaultAuthority\", signer: false, writable: false },\n] as const;\n\n// ============================================================================\n// PERC-627 / GH#1926: LpVaultWithdraw (tag 39)\n// ============================================================================\n\n/**\n * LpVaultWithdraw: 10 accounts (tag 39, PERC-627 / GH#1926 / PERC-8287)\n *\n * Burn LP vault tokens and withdraw proportional collateral from the LP vault.\n *\n * accounts[9] = creatorLockPda is REQUIRED since percolator-prog PR#170.\n * Non-creator withdrawers must pass the derived PDA key; if no lock exists\n * on-chain the enforcement is a no-op. Omitting it was the bypass vector\n * fixed in GH#1926. Use `deriveCreatorLockPda(programId, slab)` to compute.\n *\n * Accounts:\n * [0] withdrawer signer, read-only\n * [1] slab writable\n * [2] withdrawerAta writable (collateral destination)\n * [3] vault writable (collateral source)\n * [4] tokenProgram read-only\n * [5] lpVaultMint writable (LP tokens burned from here)\n * [6] withdrawerLpAta writable (LP tokens source)\n * [7] vaultAuthority read-only (PDA that signs token transfers)\n * [8] lpVaultState writable\n * [9] creatorLockPda writable (REQUIRED — derived from [\"creator_lock\", slab])\n */\nexport const ACCOUNTS_LP_VAULT_WITHDRAW: readonly AccountSpec[] = [\n { name: \"withdrawer\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n { name: \"withdrawerAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"lpVaultMint\", signer: false, writable: true },\n { name: \"withdrawerLpAta\", signer: false, writable: true },\n { name: \"vaultAuthority\", signer: false, writable: false },\n { name: \"lpVaultState\", signer: false, writable: true },\n { name: \"creatorLockPda\", signer: false, writable: true },\n] as const;\n\n/**\n * FundMarketInsurance: 5 accounts (PERC-306)\n * Fund per-market isolated insurance balance.\n */\nexport const ACCOUNTS_FUND_MARKET_INSURANCE: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"adminAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n] as const;\n\n/**\n * SetInsuranceIsolation: 2 accounts (PERC-306)\n * Set max % of global fund this market can access.\n */\nexport const ACCOUNTS_SET_INSURANCE_ISOLATION: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// PERC-309: QueueWithdrawal / ClaimQueuedWithdrawal / CancelQueuedWithdrawal\n// ============================================================================\n\n/**\n * QueueWithdrawal: 5 accounts (PERC-309)\n * User queues a large LP withdrawal. Creates withdraw_queue PDA.\n */\nexport const ACCOUNTS_QUEUE_WITHDRAWAL: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"lpVaultState\", signer: false, writable: false },\n { name: \"withdrawQueue\", signer: false, writable: true },\n { name: \"systemProgram\", signer: false, writable: false },\n] as const;\n\n/**\n * ClaimQueuedWithdrawal: 10 accounts (PERC-309)\n * Burns LP tokens and releases one epoch tranche of SOL.\n */\nexport const ACCOUNTS_CLAIM_QUEUED_WITHDRAWAL: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"withdrawQueue\", signer: false, writable: true },\n { name: \"lpVaultMint\", signer: false, writable: true },\n { name: \"userLpAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"userAta\", signer: false, writable: true },\n { name: \"vaultAuthority\", signer: false, writable: false },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"lpVaultState\", signer: false, writable: true },\n] as const;\n\n/**\n * CancelQueuedWithdrawal: 3 accounts (PERC-309)\n * Cancels queue, closes withdraw_queue PDA, returns rent to user.\n */\nexport const ACCOUNTS_CANCEL_QUEUED_WITHDRAWAL: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: false },\n { name: \"withdrawQueue\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// PERC-305: ExecuteAdl (tag 50) — Auto-Deleverage\n// ============================================================================\n\n/**\n * ExecuteAdl: 4+ accounts (PERC-305, tag 50)\n * Permissionless — surgically close/reduce the most profitable position\n * when pnl_pos_tot > max_pnl_cap. For non-Hyperp markets with backup oracles,\n * pass additional oracle accounts at accounts[4..].\n */\nexport const ACCOUNTS_EXECUTE_ADL: readonly AccountSpec[] = [\n { name: \"caller\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n { name: \"clock\", signer: false, writable: false },\n { name: \"oracle\", signer: false, writable: false },\n] as const;\n\n// ============================================================================\n// CloseStaleSlabs (tag 51) / ReclaimSlabRent (tag 52)\n// ============================================================================\n\n/**\n * CloseStaleSlabs: 2 accounts (tag 51)\n * Admin closes a slab of an invalid/old layout and recovers rent SOL.\n */\nexport const ACCOUNTS_CLOSE_STALE_SLABS: readonly AccountSpec[] = [\n { name: \"dest\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * ReclaimSlabRent: 2 accounts (tag 52)\n * Reclaim rent from an uninitialised slab. Both dest and slab must sign.\n */\nexport const ACCOUNTS_RECLAIM_SLAB_RENT: readonly AccountSpec[] = [\n { name: \"dest\", signer: true, writable: true },\n { name: \"slab\", signer: true, writable: true },\n] as const;\n\n// ============================================================================\n// AuditCrank (tag 53) — Permissionless invariant check\n// ============================================================================\n\n/**\n * AuditCrank: 1 account (tag 53)\n * Permissionless. Verifies conservation invariants; pauses market on violation.\n */\nexport const ACCOUNTS_AUDIT_CRANK: readonly AccountSpec[] = [\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// PERC-622: AdvanceOraclePhase (permissionless)\n// ============================================================================\n\n/**\n * AdvanceOraclePhase: 1 account\n * Permissionless — no signer required beyond fee payer.\n */\nexport const ACCOUNTS_ADVANCE_ORACLE_PHASE: readonly AccountSpec[] = [\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// PERC-623: Keeper Fund Instructions\n// ============================================================================\n\n/**\n * TopUpKeeperFund: 3 accounts\n * Permissionless — anyone can fund. Transfers lamports directly (no system program).\n */\nexport const ACCOUNTS_TOPUP_KEEPER_FUND: readonly AccountSpec[] = [\n { name: \"funder\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"keeperFund\", signer: false, writable: true },\n] as const;\n\n// Note: WithdrawKeeperReward has no separate instruction.\n// Rewards are paid automatically during KeeperCrank (tag 5).\n\n// ============================================================================\n// PERC-8110: SetOiImbalanceHardBlock\n// ============================================================================\n\n/**\n * SetOiImbalanceHardBlock: 2 accounts\n * Sets the OI imbalance hard-block threshold (admin only)\n */\nexport const ACCOUNTS_SET_OI_IMBALANCE_HARD_BLOCK: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// PERC-608: Position NFT Instructions (tags 64–69)\n// ============================================================================\n\n/**\n * MintPositionNft: 10 accounts\n * Creates a Token-2022 position NFT for an open position.\n */\nexport const ACCOUNTS_MINT_POSITION_NFT: readonly AccountSpec[] = [\n { name: \"payer\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"positionNftPda\", signer: false, writable: true },\n { name: \"nftMint\", signer: false, writable: true },\n { name: \"ownerAta\", signer: false, writable: true },\n { name: \"owner\", signer: true, writable: false },\n { name: \"vaultAuthority\", signer: false, writable: false },\n { name: \"token2022Program\", signer: false, writable: false },\n { name: \"systemProgram\", signer: false, writable: false },\n { name: \"rent\", signer: false, writable: false },\n] as const;\n\n/**\n * TransferPositionOwnership: 8 accounts\n * Transfer position NFT and update on-chain owner. Requires pending_settlement == 0.\n */\nexport const ACCOUNTS_TRANSFER_POSITION_OWNERSHIP: readonly AccountSpec[] = [\n { name: \"currentOwner\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"positionNftPda\", signer: false, writable: true },\n { name: \"nftMint\", signer: false, writable: true },\n { name: \"currentOwnerAta\", signer: false, writable: true },\n { name: \"newOwnerAta\", signer: false, writable: true },\n { name: \"newOwner\", signer: false, writable: false },\n { name: \"token2022Program\", signer: false, writable: false },\n] as const;\n\n/**\n * BurnPositionNft: 7 accounts\n * Burns NFT and closes PositionNft + mint PDAs after position is closed.\n */\nexport const ACCOUNTS_BURN_POSITION_NFT: readonly AccountSpec[] = [\n { name: \"owner\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"positionNftPda\", signer: false, writable: true },\n { name: \"nftMint\", signer: false, writable: true },\n { name: \"ownerAta\", signer: false, writable: true },\n { name: \"vaultAuthority\", signer: false, writable: false },\n { name: \"token2022Program\", signer: false, writable: false },\n] as const;\n\n/**\n * SetPendingSettlement: 3 accounts\n * Keeper/admin sets pending_settlement flag before funding transfer.\n * Protected by admin allowlist (GH#1475).\n */\nexport const ACCOUNTS_SET_PENDING_SETTLEMENT: readonly AccountSpec[] = [\n { name: \"keeper\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: false },\n { name: \"positionNftPda\", signer: false, writable: true },\n] as const;\n\n/**\n * ClearPendingSettlement: 3 accounts\n * Keeper/admin clears pending_settlement flag after KeeperCrank.\n * Protected by admin allowlist (GH#1475).\n */\nexport const ACCOUNTS_CLEAR_PENDING_SETTLEMENT: readonly AccountSpec[] = [\n { name: \"keeper\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: false },\n { name: \"positionNftPda\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// PERC-8111: SetWalletCap\n// ============================================================================\n\n/**\n * SetWalletCap: 2 accounts\n * Sets the per-wallet position cap (admin only). capE6=0 disables.\n */\nexport const ACCOUNTS_SET_WALLET_CAP: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// InitMatcherCtx (tag 75)\n// ============================================================================\n\n/**\n * InitMatcherCtx: 5 accounts\n * Admin CPI-initializes the matcher context account for an LP slot.\n * The LP PDA signs via invoke_signed in the program — it must be included in\n * the transaction's account list even though it carries 0 lamports.\n */\nexport const ACCOUNTS_INIT_MATCHER_CTX: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: false },\n { name: \"matcherCtx\", signer: false, writable: true },\n { name: \"matcherProg\", signer: false, writable: false },\n { name: \"lpPda\", signer: false, writable: false },\n] as const;\n\n// ============================================================================\n// WELL-KNOWN PROGRAM/SYSVAR KEYS\n// ============================================================================\n\nexport const WELL_KNOWN = {\n tokenProgram: TOKEN_PROGRAM_ID,\n clock: SYSVAR_CLOCK_PUBKEY,\n rent: SYSVAR_RENT_PUBKEY,\n systemProgram: SystemProgram.programId,\n} as const;\n","/**\n * Percolator program error definitions.\n * Each error includes a name and actionable guidance.\n */\ninterface ErrorInfo {\n name: string;\n hint: string;\n}\n\nexport const PERCOLATOR_ERRORS: Record<number, ErrorInfo> = {\n 0: {\n name: \"InvalidMagic\",\n hint: \"The slab account has invalid data. Ensure you're using the correct slab address.\",\n },\n 1: {\n name: \"InvalidVersion\",\n hint: \"Slab version mismatch. The program may have been upgraded. Check for CLI updates.\",\n },\n 2: {\n name: \"AlreadyInitialized\",\n hint: \"This account is already initialized. Use a different account or skip initialization.\",\n },\n 3: {\n name: \"NotInitialized\",\n hint: \"The slab is not initialized. Run 'init-market' first.\",\n },\n 4: {\n name: \"InvalidSlabLen\",\n hint: \"Slab account has wrong size. Create a new slab account with correct size.\",\n },\n 5: {\n name: \"InvalidOracleKey\",\n hint: \"Oracle account doesn't match config. Check the --oracle parameter matches the market's oracle.\",\n },\n 6: {\n name: \"OracleStale\",\n hint: \"Oracle price is too old. Wait for oracle to update or check if oracle is paused.\",\n },\n 7: {\n name: \"OracleConfTooWide\",\n hint: \"Oracle confidence interval is too wide. Wait for more stable market conditions.\",\n },\n 8: {\n name: \"InvalidVaultAta\",\n hint: \"Vault token account is invalid. Check the vault account is correctly configured.\",\n },\n 9: {\n name: \"InvalidMint\",\n hint: \"Token mint doesn't match. Ensure you're using the correct collateral token.\",\n },\n 10: {\n name: \"ExpectedSigner\",\n hint: \"Missing required signature. Ensure the correct wallet is specified with --wallet.\",\n },\n 11: {\n name: \"ExpectedWritable\",\n hint: \"Account must be writable. This is likely a CLI bug - please report it.\",\n },\n 12: {\n name: \"OracleInvalid\",\n hint: \"Oracle data is invalid. Check the oracle account is a valid Pyth price feed.\",\n },\n 13: {\n name: \"EngineInsufficientBalance\",\n hint: \"Not enough collateral. Deposit more with 'deposit' before this operation.\",\n },\n 14: {\n name: \"EngineUndercollateralized\",\n hint: \"Account is undercollateralized. Deposit more collateral or reduce position size.\",\n },\n 15: {\n name: \"EngineUnauthorized\",\n hint: \"Not authorized. You must be the account owner or admin for this operation.\",\n },\n 16: {\n name: \"EngineInvalidMatchingEngine\",\n hint: \"Matcher program/context doesn't match LP config. Check --matcher-program and --matcher-context.\",\n },\n 17: {\n name: \"EnginePnlNotWarmedUp\",\n hint: \"PnL not warmed up yet. Wait for the warmup period to complete before trading.\",\n },\n 18: {\n name: \"EngineOverflow\",\n hint: \"Numeric overflow in calculation. Try a smaller amount or position size.\",\n },\n 19: {\n name: \"EngineAccountNotFound\",\n hint: \"Account not found at this index. Run 'init-user' or 'init-lp' first, or check the index.\",\n },\n 20: {\n name: \"EngineNotAnLPAccount\",\n hint: \"Expected an LP account but got a user account. Check the --lp-idx parameter.\",\n },\n 21: {\n name: \"EnginePositionSizeMismatch\",\n hint: \"Position size mismatch between user and LP. This shouldn't happen - please report it.\",\n },\n 22: {\n name: \"EngineRiskReductionOnlyMode\",\n hint: \"Market is in risk-reduction mode. Only position-reducing trades are allowed.\",\n },\n 23: {\n name: \"EngineAccountKindMismatch\",\n hint: \"Wrong account type. User operations require user accounts, LP operations require LP accounts.\",\n },\n 24: {\n name: \"InvalidTokenAccount\",\n hint: \"Token account is invalid. Ensure you have an ATA for the collateral mint.\",\n },\n 25: {\n name: \"InvalidTokenProgram\",\n hint: \"Invalid token program. Ensure SPL Token program is accessible.\",\n },\n 26: {\n name: \"InvalidConfigParam\",\n hint: \"Invalid configuration parameter. Check that leverage, fees, and risk thresholds are within allowed ranges.\",\n },\n 27: {\n name: \"HyperpTradeNoCpiDisabled\",\n hint: \"TradeNoCpi is disabled for this market. Use TradeCpi with LP matching instead.\",\n },\n 28: {\n name: \"InsuranceMintAlreadyExists\",\n hint: \"Insurance LP mint already exists for this market. Cannot recreate.\",\n },\n 29: {\n name: \"InsuranceMintNotCreated\",\n hint: \"Insurance LP mint has not been created yet. Run CreateInsuranceMint first.\",\n },\n 30: {\n name: \"InsuranceBelowThreshold\",\n hint: \"Insurance fund balance is below the required threshold. Deposit more to insurance fund.\",\n },\n 31: {\n name: \"InsuranceZeroAmount\",\n hint: \"Insurance deposit/withdrawal amount must be greater than zero.\",\n },\n 32: {\n name: \"InsuranceSupplyMismatch\",\n hint: \"Insurance LP token supply doesn't match vault balance. This is an internal error - please report it.\",\n },\n 33: {\n name: \"MarketPaused\",\n hint: \"This market is currently paused by the admin. Trading, deposits, and withdrawals are disabled.\",\n },\n 34: {\n name: \"AdminRenounceNotAllowed\",\n hint: \"Cannot renounce admin — the market must be RESOLVED first before renouncing admin control.\",\n },\n 35: {\n name: \"InvalidConfirmation\",\n hint: \"Invalid confirmation code for RenounceAdmin. This is a safety check — please verify the code.\",\n },\n 36: {\n name: \"InsufficientSeed\",\n hint: \"Vault seed balance is below the required minimum (500,000,000 raw tokens). Deposit more tokens to the vault before InitMarket.\",\n },\n 37: {\n name: \"InsufficientDexLiquidity\",\n hint: \"DEX pool has insufficient liquidity for safe Hyperp oracle bootstrapping. The quote-side reserves must meet the minimum threshold.\",\n },\n 38: {\n name: \"LpVaultAlreadyExists\",\n hint: \"LP vault already created for this market. Each market can only have one LP vault.\",\n },\n 39: {\n name: \"LpVaultNotCreated\",\n hint: \"LP vault not yet created. Call CreateLpVault first before depositing or withdrawing.\",\n },\n 40: {\n name: \"LpVaultZeroAmount\",\n hint: \"LP vault deposit or withdrawal amount must be greater than zero.\",\n },\n 41: {\n name: \"LpVaultSupplyMismatch\",\n hint: \"LP vault supply/capital mismatch — LP share supply > 0 but vault capital is 0. This is an internal error — please report it.\",\n },\n 42: {\n name: \"LpVaultWithdrawExceedsAvailable\",\n hint: \"LP vault withdrawal exceeds available capital. Some capital is reserved for open interest coverage.\",\n },\n 43: {\n name: \"LpVaultInvalidFeeShare\",\n hint: \"LP vault fee share basis points out of range. Must be 0–10,000 (0%–100%).\",\n },\n 44: {\n name: \"LpVaultNoNewFees\",\n hint: \"No new fees to distribute to LP vault. Wait for more trading activity to accrue fees.\",\n },\n // ── PERC-312 / PERC-314 / PERC-315 / PERC-309 / PERC-8111 / PERC-8110 (codes 45–60) ─────────\n 45: {\n name: \"SafetyValveDominantSideBlocked\",\n hint: \"New position on the dominant side is blocked while the market is rebalancing (safety valve).\",\n },\n 46: {\n name: \"DisputeWindowClosed\",\n hint: \"The dispute window for this resolved market has closed.\",\n },\n 47: {\n name: \"DisputeAlreadyExists\",\n hint: \"A dispute already exists for this market — cannot open another.\",\n },\n 48: {\n name: \"MarketNotResolved\",\n hint: \"Market is not resolved — cannot dispute an active market.\",\n },\n 49: {\n name: \"NoActiveDispute\",\n hint: \"No active dispute found for this market.\",\n },\n 50: {\n name: \"LpCollateralDisabled\",\n hint: \"LP collateral is not enabled for this market.\",\n },\n 51: {\n name: \"LpCollateralPositionOpen\",\n hint: \"Cannot withdraw LP collateral while a position is still open.\",\n },\n 52: {\n name: \"WithdrawQueueAlreadyExists\",\n hint: \"A withdrawal queue entry already exists for this user/market.\",\n },\n 53: {\n name: \"WithdrawQueueNotFound\",\n hint: \"No queued withdrawal found for this user/market.\",\n },\n 54: {\n name: \"WithdrawQueueNothingClaimable\",\n hint: \"Nothing is claimable from the withdrawal queue this epoch — wait for the next epoch.\",\n },\n 55: {\n name: \"AuditViolation\",\n hint: \"Audit crank detected a conservation invariant violation — this is a critical internal error, please report it.\",\n },\n 56: {\n name: \"CrossMarginPairNotFound\",\n hint: \"Cross-margin offset pair is not configured for these two slabs.\",\n },\n 57: {\n name: \"CrossMarginAttestationStale\",\n hint: \"Cross-margin attestation is stale — too many slots have elapsed since the last attestation.\",\n },\n 58: {\n name: \"WalletPositionCapExceeded\",\n hint: \"Trade rejected: the resulting position would exceed the per-wallet position cap (max_wallet_pos_e6) for this market.\",\n },\n 59: {\n name: \"OiImbalanceHardBlock\",\n hint: \"Trade rejected: it would increase the OI imbalance (|long_oi − short_oi| / total_oi) beyond the configured hard-block threshold (oi_imbalance_hard_block_bps). Try the opposite side.\",\n },\n 60: {\n name: \"EngineInvalidEntryPrice\",\n hint: \"Entry price must be positive when opening a position.\",\n },\n 61: {\n name: \"EngineSideBlocked\",\n hint: \"New position blocked — this side is in DrainOnly or ResetPending mode. Wait for the market to stabilise.\",\n },\n 62: {\n name: \"EngineCorruptState\",\n hint: \"Engine detected a corrupt state invariant violation — this is a critical internal error, please report it.\",\n },\n 63: {\n name: \"InsuranceFundNotDepleted\",\n hint: \"ADL rejected — insurance fund is not fully depleted (balance > 0). ADL is only permitted once insurance is exhausted.\",\n },\n 64: {\n name: \"NoAdlCandidates\",\n hint: \"ADL rejected — no eligible candidate positions found for deleveraging.\",\n },\n 65: {\n name: \"BankruptPositionAlreadyClosed\",\n hint: \"ADL rejected — the target position is already closed (size == 0). Re-rank and pick a different target.\",\n },\n};\n\n/**\n * Decode a custom program error code to its info.\n */\nexport function decodeError(code: number): ErrorInfo | undefined {\n return PERCOLATOR_ERRORS[code];\n}\n\n/**\n * Get error name from code.\n */\nexport function getErrorName(code: number): string {\n return PERCOLATOR_ERRORS[code]?.name ?? `Unknown(${code})`;\n}\n\n/**\n * Get actionable hint for error code.\n */\nexport function getErrorHint(code: number): string | undefined {\n return PERCOLATOR_ERRORS[code]?.hint;\n}\n\n// ============================================================================\n// Lighthouse / Anchor error classification\n// ============================================================================\n\n/** Lighthouse v2 program ID (Blowfish/Phantom wallet middleware). */\nconst LIGHTHOUSE_PROGRAM_ID_STR = \"L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95\";\n\n/**\n * Anchor framework error codes (0x1770–0x1900+) that come from Lighthouse,\n * NOT from Percolator. Our program uses raw BPF with custom codes 0–65.\n */\nconst ANCHOR_ERROR_RANGE_START = 0x1770;\nconst ANCHOR_ERROR_RANGE_END = 0x1FFF;\n\n/** Well-known Anchor error names for common codes emitted by Lighthouse. */\nconst ANCHOR_ERROR_NAMES: Record<number, string> = {\n 0x1790: \"ConstraintMut\",\n 0x1794: \"ConstraintOwner\",\n 0x1796: \"ConstraintSeeds\",\n 0x1900: \"ConstraintAddress\",\n};\n\n/**\n * Check whether an error code is in the Anchor framework error range\n * (used by Lighthouse, not Percolator).\n */\nexport function isAnchorErrorCode(code: number): boolean {\n return code >= ANCHOR_ERROR_RANGE_START && code <= ANCHOR_ERROR_RANGE_END;\n}\n\n/** Max hex digits for `custom program error: 0x...` — Solana custom errors are u32. */\nconst CUSTOM_ERROR_HEX_MAX_LEN = 8;\n\n/**\n * Parse error from transaction logs.\n * Looks for \"Program ... failed: custom program error: 0x...\"\n *\n * Hex capture is bounded (1–8 digits) so pathological logs cannot feed unbounded\n * strings into `parseInt` or produce precision-loss codes above u32.\n *\n * Distinguishes between:\n * - Percolator program errors (codes 0–65): returns Percolator error info\n * - Anchor/Lighthouse errors (codes 0x1770–0x1FFF): returns Lighthouse-specific\n * name and hint so callers can handle wallet middleware failures\n */\nexport function parseErrorFromLogs(logs: string[]): {\n code: number;\n name: string;\n hint?: string;\n source?: \"percolator\" | \"lighthouse\" | \"unknown\";\n} | null {\n if (!Array.isArray(logs)) {\n return null;\n }\n\n // Track whether the failing instruction is inside a Lighthouse invocation\n let insideLighthouse = false;\n\n const re = new RegExp(\n `custom program error: 0x([0-9a-fA-F]{1,${CUSTOM_ERROR_HEX_MAX_LEN}})(?![0-9a-fA-F])`,\n \"i\",\n );\n for (const log of logs) {\n if (typeof log !== \"string\") {\n continue;\n }\n\n // Track Lighthouse program invocation context\n if (log.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {\n insideLighthouse = true;\n } else if (log.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {\n insideLighthouse = false;\n }\n\n const match = log.match(re);\n if (match) {\n const code = parseInt(match[1], 16);\n if (!Number.isFinite(code) || code < 0 || code > 0xffff_ffff) {\n continue;\n }\n\n // Anchor/Lighthouse error range\n if (isAnchorErrorCode(code) || insideLighthouse) {\n const anchorName = ANCHOR_ERROR_NAMES[code] ?? `AnchorError(0x${code.toString(16)})`;\n return {\n code,\n name: `Lighthouse:${anchorName}`,\n hint:\n \"This error comes from the Lighthouse/Blowfish wallet guard, not from Percolator. \" +\n \"The transaction itself is valid. Disable transaction simulation in your wallet \" +\n \"settings, or use a wallet without Blowfish protection (e.g., Backpack, Solflare).\",\n source: \"lighthouse\",\n };\n }\n\n // Percolator program error\n const info = decodeError(code);\n return {\n code,\n name: info?.name ?? `Unknown(${code})`,\n hint: info?.hint,\n source: info ? \"percolator\" : \"unknown\",\n };\n }\n }\n return null;\n}\n","import { Connection, PublicKey } from \"@solana/web3.js\";\n\n// =============================================================================\n// Browser-compatible read helpers using DataView\n// (the npm 'buffer' polyfill lacks readBigUInt64LE / readBigInt64LE)\n// =============================================================================\n\n/** Wrap a Uint8Array in a DataView sharing the same underlying buffer. */\nfunction dv(data: Uint8Array): DataView {\n return new DataView(data.buffer, data.byteOffset, data.byteLength);\n}\n/** Read a single unsigned byte at `off`. */\nfunction readU8(data: Uint8Array, off: number): number {\n return data[off];\n}\n/** Read a little-endian u16 at `off`. */\nfunction readU16LE(data: Uint8Array, off: number): number {\n return dv(data).getUint16(off, true);\n}\n/** Read a little-endian u32 at `off`. */\nfunction readU32LE(data: Uint8Array, off: number): number {\n return dv(data).getUint32(off, true);\n}\n/** Read a little-endian u64 at `off` as a BigInt. */\nfunction readU64LE(data: Uint8Array, off: number): bigint {\n return dv(data).getBigUint64(off, true);\n}\n/** Read a little-endian signed i64 at `off` as a BigInt. */\nfunction readI64LE(data: Uint8Array, off: number): bigint {\n return dv(data).getBigInt64(off, true);\n}\n\n// =============================================================================\n// Helper: read signed/unsigned i128 from buffer\n// =============================================================================\n\n/**\n * Read a little-endian signed i128 at `offset`.\n * Composed from two u64 halves; sign-extends if the high bit is set.\n */\nfunction readI128LE(buf: Uint8Array, offset: number): bigint {\n const lo = readU64LE(buf, offset);\n const hi = readU64LE(buf, offset + 8);\n const unsigned = (hi << 64n) | lo;\n const SIGN_BIT = 1n << 127n;\n if (unsigned >= SIGN_BIT) {\n return unsigned - (1n << 128n);\n }\n return unsigned;\n}\n\n/** Read a little-endian unsigned u128 at `offset` as a BigInt. */\nfunction readU128LE(buf: Uint8Array, offset: number): bigint {\n const lo = readU64LE(buf, offset);\n const hi = readU64LE(buf, offset + 8);\n return (hi << 64n) | lo;\n}\n\n// =============================================================================\n// Slab Layout Version Detection\n// =============================================================================\n// The deployed devnet program uses a different struct layout (V0) than the SDK\n// was updated for (V1). V1 includes PERC-120/121/122/298/299/300/301/306/328\n// struct changes that have NOT been deployed to devnet yet.\n//\n// V0 (deployed devnet): HEADER=72, CONFIG=408, ENGINE_OFF=480, ACCOUNT_SIZE=240\n// - InsuranceFund: {balance: U128, fee_revenue: U128} (32 bytes)\n// - RiskParams: 56 bytes (basic fields only)\n// - No mark_price, no long_oi/short_oi, no emergency OI cap fields\n// - No partial liquidation field in Account (240 bytes)\n//\n// V1 (future upgrade): HEADER=104, CONFIG=536, ENGINE_OFF=640, ACCOUNT_SIZE=248\n// - InsuranceFund: expanded with isolation fields (72 bytes)\n// - RiskParams: 288 bytes (premium funding, partial liq, dynamic fees)\n// - Has mark_price, long_oi/short_oi, emergency fields\n// - Account has last_partial_liquidation_slot (248 bytes)\n// =============================================================================\n\nconst MAGIC: bigint = 0x504552434f4c4154n; // \"PERCOLAT\"\n\n// Flag bits in header._padding[0] at offset 13\nconst FLAG_RESOLVED = 1 << 0;\n\n/**\n * Full slab layout descriptor. Returned by detectSlabLayout().\n * All engine field offsets are relative to engineOff.\n */\nexport interface SlabLayout {\n version: 0 | 1 | 2;\n headerLen: number;\n configOffset: number;\n configLen: number;\n reservedOff: number; // offset of _reserved in header\n engineOff: number;\n accountSize: number;\n maxAccounts: number;\n bitmapWords: number;\n accountsOff: number; // absolute offset of accounts array in slab\n\n // Engine field offsets (relative to engineOff)\n engineInsuranceOff: number;\n engineParamsOff: number;\n paramsSize: number;\n engineCurrentSlotOff: number;\n engineFundingIndexOff: number;\n engineLastFundingSlotOff: number;\n engineFundingRateBpsOff: number;\n engineMarkPriceOff: number; // -1 if not present (V0)\n engineLastCrankSlotOff: number;\n engineMaxCrankStalenessOff: number;\n engineTotalOiOff: number;\n engineLongOiOff: number; // -1 if not present (V0)\n engineShortOiOff: number; // -1 if not present (V0)\n engineCTotOff: number;\n enginePnlPosTotOff: number;\n engineLiqCursorOff: number;\n engineGcCursorOff: number;\n engineLastSweepStartOff: number;\n engineLastSweepCompleteOff: number;\n engineCrankCursorOff: number;\n engineSweepStartIdxOff: number;\n engineLifetimeLiquidationsOff: number;\n engineLifetimeForceClosesOff: number;\n engineNetLpPosOff: number;\n engineLpSumAbsOff: number;\n engineLpMaxAbsOff: number;\n engineLpMaxAbsSweepOff: number;\n engineEmergencyOiModeOff: number; // -1 if not present (V0)\n engineEmergencyStartSlotOff: number; // -1 if not present (V0)\n engineLastBreakerSlotOff: number; // -1 if not present (V0)\n engineBitmapOff: number; // relative to engineOff\n postBitmap: number; // 2 = free_head only (V1D), 18 = num_used + pad + next_account_id + free_head\n acctOwnerOff: number; // byte offset of owner pubkey within an account slot\n\n // Insurance fund layout\n hasInsuranceIsolation: boolean;\n engineInsuranceIsolatedOff: number; // -1 if not present (V0)\n engineInsuranceIsolationBpsOff: number; // -1 if not present (V0)\n}\n\n// ---- V0 layout constants (deployed devnet program) ----\nconst V0_HEADER_LEN = 72;\nconst V0_CONFIG_LEN = 408;\nconst V0_ENGINE_OFF = 480; // align_up(72 + 408, 8) = 480\nconst V0_ACCOUNT_SIZE = 240;\nconst V0_RESERVED_OFF = 48; // magic(8)+version(4)+bump(1)+pad(3)+admin(32) = 48\n\n// V0 engine: vault(16) + insurance{balance(16),fee_revenue(16)}=32 → params at 48\n// V0 RiskParams: 56 bytes → runtime state at 104\nconst V0_ENGINE_PARAMS_OFF = 48;\nconst V0_PARAMS_SIZE = 56;\nconst V0_ENGINE_CURRENT_SLOT_OFF = 104;\nconst V0_ENGINE_FUNDING_INDEX_OFF = 112;\nconst V0_ENGINE_LAST_FUNDING_SLOT_OFF = 128;\nconst V0_ENGINE_FUNDING_RATE_BPS_OFF = 136;\nconst V0_ENGINE_LAST_CRANK_SLOT_OFF = 144;\nconst V0_ENGINE_MAX_CRANK_STALENESS_OFF = 152;\nconst V0_ENGINE_TOTAL_OI_OFF = 160;\nconst V0_ENGINE_C_TOT_OFF = 176;\nconst V0_ENGINE_PNL_POS_TOT_OFF = 192;\nconst V0_ENGINE_LIQ_CURSOR_OFF = 208;\nconst V0_ENGINE_GC_CURSOR_OFF = 210;\nconst V0_ENGINE_LAST_SWEEP_START_OFF = 216;\nconst V0_ENGINE_LAST_SWEEP_COMPLETE_OFF = 224;\nconst V0_ENGINE_CRANK_CURSOR_OFF = 232;\nconst V0_ENGINE_SWEEP_START_IDX_OFF = 234;\nconst V0_ENGINE_LIFETIME_LIQUIDATIONS_OFF = 240;\nconst V0_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 248;\nconst V0_ENGINE_NET_LP_POS_OFF = 256;\nconst V0_ENGINE_LP_SUM_ABS_OFF = 272;\nconst V0_ENGINE_LP_MAX_ABS_OFF = 288;\nconst V0_ENGINE_LP_MAX_ABS_SWEEP_OFF = 304;\nconst V0_ENGINE_BITMAP_OFF = 320;\n\n// ---- V1 layout constants (deployed devnet program, PERC-1094 corrected) ----\n// BPF (SBF) target: u128 alignment = 8, so CONFIG_LEN = 496 on-chain.\n// ENGINE_OFF = align_up(HEADER=104 + CONFIG=496, 8) = 600.\n// Previous value (640) was wrong — it assumed CONFIG_LEN=536 from the native build assertion.\nconst V1_HEADER_LEN = 104;\nconst V1_CONFIG_LEN = 496; // BPF (SBF) on-chain value; native test build would be 512\nconst V1_ENGINE_OFF = 600; // align_up(104 + 496, 8) = 600 (was 640 — corrected in PERC-1094)\n// Legacy: CONFIG_LEN=536 was used in pre-PERC-1094 SDK. Some orphaned slabs on devnet may use\n// ENGINE_OFF=640 (65352 bytes for small). We add them to V1_SIZES_LEGACY for read-only parsing.\nconst V1_ENGINE_OFF_LEGACY = 640;\nconst V1_ACCOUNT_SIZE = 248;\nconst V1_RESERVED_OFF = 80;\n\n// V1 engine: vault(16) + insurance expanded(56) → params at 72\n// V1 RiskParams: 288 bytes → runtime state at 360\nconst V1_ENGINE_PARAMS_OFF = 72;\nconst V1_PARAMS_SIZE = 288;\nconst V1_ENGINE_CURRENT_SLOT_OFF = 360;\nconst V1_ENGINE_FUNDING_INDEX_OFF = 368;\nconst V1_ENGINE_LAST_FUNDING_SLOT_OFF = 384;\nconst V1_ENGINE_FUNDING_RATE_BPS_OFF = 392;\nconst V1_ENGINE_MARK_PRICE_OFF = 400;\nconst V1_ENGINE_LAST_CRANK_SLOT_OFF = 424;\nconst V1_ENGINE_MAX_CRANK_STALENESS_OFF = 432;\nconst V1_ENGINE_TOTAL_OI_OFF = 440;\nconst V1_ENGINE_LONG_OI_OFF = 456;\nconst V1_ENGINE_SHORT_OI_OFF = 472;\nconst V1_ENGINE_C_TOT_OFF = 488;\nconst V1_ENGINE_PNL_POS_TOT_OFF = 504;\nconst V1_ENGINE_LIQ_CURSOR_OFF = 520;\nconst V1_ENGINE_GC_CURSOR_OFF = 522;\nconst V1_ENGINE_LAST_SWEEP_START_OFF = 528;\nconst V1_ENGINE_LAST_SWEEP_COMPLETE_OFF = 536;\nconst V1_ENGINE_CRANK_CURSOR_OFF = 544;\nconst V1_ENGINE_SWEEP_START_IDX_OFF = 546;\nconst V1_ENGINE_LIFETIME_LIQUIDATIONS_OFF = 552;\nconst V1_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 560;\nconst V1_ENGINE_NET_LP_POS_OFF = 568;\nconst V1_ENGINE_LP_SUM_ABS_OFF = 584;\nconst V1_ENGINE_LP_MAX_ABS_OFF = 600;\nconst V1_ENGINE_LP_MAX_ABS_SWEEP_OFF = 616;\nconst V1_ENGINE_EMERGENCY_OI_MODE_OFF = 632;\nconst V1_ENGINE_EMERGENCY_START_SLOT_OFF = 640;\nconst V1_ENGINE_LAST_BREAKER_SLOT_OFF = 648;\nconst V1_ENGINE_BITMAP_OFF = 656;\n// On-chain V1_LEGACY slabs (65352 bytes) place the bitmap 16 bytes later than\n// computeSlabSize predicts (formula bitmapOff=656 gives size=65352 correctly, but\n// the deployed program stores the bitmap at rel=672 and the owner field at +200).\n// These corrected values must be used for actual byte-level parsing.\nconst V1_LEGACY_ENGINE_BITMAP_OFF_ACTUAL = 672; // relative to engineOff (abs = 640+672 = 1312)\nconst V1_LEGACY_ACCT_OWNER_OFF = 200; // vs the usual ACCT_OWNER_OFF=184\n\n// ---- V1D layout constants (actually deployed devnet V1 program, rev ac18a0e) ----\n// The deployed V1 program has a DIFFERENT struct layout than the V1 constants above.\n// Key differences:\n// - MarketConfig is smaller (BPF CONFIG_LEN=320 vs V1's 496) — older revision\n// - InsuranceFund is 80 bytes (V1 assumed 56), so params starts at engine+96 (not 72)\n// - Engine lacks lp_max_abs, lp_max_abs_sweep, emergency_oi, trade_twap fields\n// - Bitmap at engine+624 (not 656)\n// Confirmed by on-chain probing of slab 6ZytbpV4 (the only active V1 market).\nconst V1D_CONFIG_LEN = 320;\nconst V1D_ENGINE_OFF = 424; // align_up(104 + 320, 8) = 424\nconst V1D_ACCOUNT_SIZE = 248;\n\n// V1D engine field offsets (relative to engineOff):\n// vault(16) + InsuranceFund(80) → params at 96; RiskParams(288) → runtime at 384\nconst V1D_ENGINE_INSURANCE_OFF = 16;\nconst V1D_ENGINE_PARAMS_OFF = 96;\nconst V1D_PARAMS_SIZE = 288;\nconst V1D_ENGINE_CURRENT_SLOT_OFF = 384;\nconst V1D_ENGINE_FUNDING_INDEX_OFF = 392;\nconst V1D_ENGINE_LAST_FUNDING_SLOT_OFF = 408;\nconst V1D_ENGINE_FUNDING_RATE_BPS_OFF = 416;\nconst V1D_ENGINE_MARK_PRICE_OFF = 424;\n// funding_frozen(1+7pad) at 432, funding_frozen_rate(8) at 440\nconst V1D_ENGINE_LAST_CRANK_SLOT_OFF = 448;\nconst V1D_ENGINE_MAX_CRANK_STALENESS_OFF = 456;\nconst V1D_ENGINE_TOTAL_OI_OFF = 464;\nconst V1D_ENGINE_LONG_OI_OFF = 480;\nconst V1D_ENGINE_SHORT_OI_OFF = 496;\nconst V1D_ENGINE_C_TOT_OFF = 512;\nconst V1D_ENGINE_PNL_POS_TOT_OFF = 528;\nconst V1D_ENGINE_LIQ_CURSOR_OFF = 544;\nconst V1D_ENGINE_GC_CURSOR_OFF = 546;\nconst V1D_ENGINE_LAST_SWEEP_START_OFF = 552;\nconst V1D_ENGINE_LAST_SWEEP_COMPLETE_OFF = 560;\nconst V1D_ENGINE_CRANK_CURSOR_OFF = 568;\nconst V1D_ENGINE_SWEEP_START_IDX_OFF = 570;\nconst V1D_ENGINE_LIFETIME_LIQUIDATIONS_OFF = 576;\nconst V1D_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 584;\nconst V1D_ENGINE_NET_LP_POS_OFF = 592;\nconst V1D_ENGINE_LP_SUM_ABS_OFF = 608;\n// lp_max_abs, lp_max_abs_sweep, emergency_*, trade_twap_* do NOT exist in this version\nconst V1D_ENGINE_BITMAP_OFF = 624;\n\n// ---- V2 layout constants (BPF intermediate layout, ENGINE_OFF=600, BITMAP_OFF=432) ----\n// V2 shares ENGINE_OFF=600 with V1, but has a completely different engine struct layout:\n// - CONFIG_LEN=496 (same as V1 on-chain), HEADER_LEN=104, ACCOUNT_SIZE=248\n// - Engine lacks mark_price, long_oi, short_oi, emergency OI fields\n// - Different field offsets than V1D (which has ENGINE_OFF=424)\n// V2 is identified by reading the version field at slab header offset 8 (u32 LE) == 2.\n// Without data, V2 cannot be distinguished from V1D by size alone (postBitmap=18 produces\n// identical sizes to V1D postBitmap=2 — both 65088 for 256 accounts).\nconst V2_HEADER_LEN = 104;\nconst V2_CONFIG_LEN = 496;\nconst V2_ENGINE_OFF = 600; // align_up(104 + 496, 8) = 600\nconst V2_ACCOUNT_SIZE = 248;\nconst V2_ENGINE_BITMAP_OFF = 432;\n\n// V2 engine field offsets (relative to engineOff)\nconst V2_ENGINE_CURRENT_SLOT_OFF = 352;\nconst V2_ENGINE_FUNDING_INDEX_OFF = 360;\nconst V2_ENGINE_LAST_FUNDING_SLOT_OFF = 376;\nconst V2_ENGINE_FUNDING_RATE_BPS_OFF = 384;\nconst V2_ENGINE_LAST_CRANK_SLOT_OFF = 392;\nconst V2_ENGINE_MAX_CRANK_STALENESS_OFF = 400;\nconst V2_ENGINE_TOTAL_OI_OFF = 408;\nconst V2_ENGINE_C_TOT_OFF = 424;\nconst V2_ENGINE_PNL_POS_TOT_OFF = 440;\nconst V2_ENGINE_LIQ_CURSOR_OFF = 456;\nconst V2_ENGINE_GC_CURSOR_OFF = 458;\nconst V2_ENGINE_LAST_SWEEP_START_OFF = 464;\nconst V2_ENGINE_LAST_SWEEP_COMPLETE_OFF = 472;\nconst V2_ENGINE_CRANK_CURSOR_OFF = 480;\nconst V2_ENGINE_SWEEP_START_IDX_OFF = 482;\nconst V2_ENGINE_LIFETIME_LIQUIDATIONS_OFF = 488;\nconst V2_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 496;\nconst V2_ENGINE_NET_LP_POS_OFF = 504;\nconst V2_ENGINE_LP_SUM_ABS_OFF = 520;\nconst V2_ENGINE_LP_MAX_ABS_OFF = 536;\nconst V2_ENGINE_LP_MAX_ABS_SWEEP_OFF = 552;\n\n// ---- V_ADL layout constants (ADL-upgraded program, PERC-8270/8271) ----\n// This layout corresponds to the percolator lib at commit ed01137 (PERC-8270) which adds:\n// - Account: position_basis_q(i128,16)+adl_a_basis(u128,16)+adl_k_snap(i128,16)+adl_epoch_snap(u64,8) = +56 bytes\n// Plus 8-byte padding before position_basis_q (i128 requires 16-byte align on BPF) → +64 bytes/account\n// - RiskEngine: last_market_slot(u64)+funding_price_sample_last(u64)+materialized_account_count(u64)+last_oracle_price(u64) = +32 bytes\n// - Also adds: InsuranceFund expanded to 80 bytes (balance_incentive_reserve + _rebate_pad + _isolation_padding),\n// RiskParams expanded to 336 bytes (min_nonzero_mm_req, min_nonzero_im_req, insurance_floor, etc.),\n// pnl_matured_pos_tot(u128,16) field in RiskEngine (PERC-8267),\n// ADL side state fields (PERC-8268, +224 bytes engine before bitmap)\n//\n// BPF SLAB_LEN: 1288304 (large/4096-account tier) — verified by cargo build-sbf (PERC-8271)\n// ENGINE_OFF = 624 (HEADER=104 + CONFIG=520 native, aligned to 8 = 624)\n// ACCOUNT_SIZE = 312 (248 old + 8 pad for i128 alignment + 16+16+16+8 new ADL fields)\n// ENGINE_BITMAP_OFF = 1008 (empirically verified: mainnet CCTegYZ... slab, 323312 bytes, 1024 accts)\n// Prior value of 1006 was an arithmetic transcription error.\n// Derivation: trade_twap_e6(8)@992 + twap_last_slot(8)@1000 = bitmap@1008.\nconst V_ADL_ENGINE_OFF = 624; // align_up(HEADER=104 + CONFIG=520, 8) = 624\nconst V_ADL_CONFIG_LEN = 520; // BPF/native MarketConfig with current fields (pre-SetDexPool)\n\n// V_SETDEXPOOL: PERC-SetDexPool security fix — adds dex_pool: [u8; 32] to MarketConfig.\n// BPF CONFIG_LEN: 496→528 (+32). ENGINE_OFF: align_up(104+528,8) = 632 (+8 from V_ADL=624).\n// Engine struct and account layout are identical to V_ADL — only CONFIG_LEN/ENGINE_OFF changed.\nconst V_SETDEXPOOL_CONFIG_LEN = 544; // SBF on-chain CONFIG_LEN after PERC-SetDexPool (target_arch=sbf uses native alignment)\nconst V_SETDEXPOOL_ENGINE_OFF = 648; // align_up(HEADER=104 + CONFIG=544, 8) = 648\n// All engine field offsets are identical to V_ADL (same engine struct, only engineOff differs).\nconst V_ADL_ACCOUNT_SIZE = 312; // 248 + 8(pad) + 56(new ADL fields) = 312 bytes\nconst V_ADL_ENGINE_PARAMS_OFF = 96; // vault(16) + InsuranceFund(80) = 96\n\n// V_ADL RiskParams: 336 bytes (same as V1M, includes all dynamic fee params)\nconst V_ADL_PARAMS_SIZE = 336;\n\n// V_ADL engine field offsets (relative to engineOff=624):\n// vault(16) + InsuranceFund(80) + RiskParams(336) = 432 bytes before current_slot\nconst V_ADL_ENGINE_CURRENT_SLOT_OFF = 432; // 96 + 336 = 432\nconst V_ADL_ENGINE_FUNDING_INDEX_OFF = 440; // 432 + 8\nconst V_ADL_ENGINE_LAST_FUNDING_SLOT_OFF = 456; // 440 + 16\nconst V_ADL_ENGINE_FUNDING_RATE_BPS_OFF = 464; // 456 + 8\n// PERC-8270 new fields at 472-504:\n// last_market_slot(8)@472, funding_price_sample_last(8)@480, materialized_account_count(8)@488, last_oracle_price(8)@496\nconst V_ADL_ENGINE_MARK_PRICE_OFF = 504; // 464+8+32 = 504 (shifted +104 from V1's 400)\n// funding_frozen(1+7pad=8)@512, funding_frozen_rate_snapshot(i64,8)@520\nconst V_ADL_ENGINE_LAST_CRANK_SLOT_OFF = 528; // was 424 in V1, +104\nconst V_ADL_ENGINE_MAX_CRANK_STALENESS_OFF = 536;\nconst V_ADL_ENGINE_TOTAL_OI_OFF = 544; // was 440 in V1, +104\nconst V_ADL_ENGINE_LONG_OI_OFF = 560; // was 456 in V1, +104\nconst V_ADL_ENGINE_SHORT_OI_OFF = 576; // was 472 in V1, +104\nconst V_ADL_ENGINE_C_TOT_OFF = 592; // was 488 in V1, +104\nconst V_ADL_ENGINE_PNL_POS_TOT_OFF = 608; // was 504 in V1, +104\n// pnl_matured_pos_tot(u128,16)@624 — NEW in PERC-8267\nconst V_ADL_ENGINE_LIQ_CURSOR_OFF = 640; // was 520 in V1, +120 (extra 16 for pnl_matured)\nconst V_ADL_ENGINE_GC_CURSOR_OFF = 642;\n// last_sweep_start(u64)@648, last_sweep_complete(u64)@656, crank_cursor(u16)@664, sweep_idx(u16)@666\nconst V_ADL_ENGINE_LAST_SWEEP_START_OFF = 648;\nconst V_ADL_ENGINE_LAST_SWEEP_COMPLETE_OFF = 656;\nconst V_ADL_ENGINE_CRANK_CURSOR_OFF = 664;\nconst V_ADL_ENGINE_SWEEP_START_IDX_OFF = 666;\n// lifetime_liquidations(u64)@672, lifetime_force_closes(u64)@680\nconst V_ADL_ENGINE_LIFETIME_LIQUIDATIONS_OFF = 672;\nconst V_ADL_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 680;\n// ADL side state (PERC-8268, 224 bytes):\n// adl_mult_long/short(16ea), adl_coeff_long/short(16ea), adl_epoch_long/short(8ea),\n// adl_epoch_start_k_long/short(16ea), oi_eff_long/short_q(16ea),\n// side_mode_long(u8)+side_mode_short(u8)+pad(6), stored_pos_count×2, stale_count×2(all u64,8),\n// phantom_dust_bound_long/short_q(16ea) = 224 bytes at offsets 688–911\n// Then LP aggregates:\nconst V_ADL_ENGINE_NET_LP_POS_OFF = 904; // after ADL side state\nconst V_ADL_ENGINE_LP_SUM_ABS_OFF = 920;\nconst V_ADL_ENGINE_LP_MAX_ABS_OFF = 936;\nconst V_ADL_ENGINE_LP_MAX_ABS_SWEEP_OFF = 952;\n// emergency fields:\nconst V_ADL_ENGINE_EMERGENCY_OI_MODE_OFF = 968;\nconst V_ADL_ENGINE_EMERGENCY_START_SLOT_OFF = 976;\nconst V_ADL_ENGINE_LAST_BREAKER_SLOT_OFF = 984;\n// trade_twap_e6(8)@992, twap_last_slot(8)@1000, bitmap([u64;N])@1008\n// Corrected from 1006 → 1008: 992+8(trade_twap_e6)+8(twap_last_slot)=1008. Arithmetic\n// transcription error in prior constant — 1008+512+18+8192=9730 rounds to 9736 (8-byte align),\n// but empirically mainnet CCTegYZ... slab (323312 bytes, 1024 accts) confirms bitmapOff=1008.\nconst V_ADL_ENGINE_BITMAP_OFF = 1008; // Empirically verified: mainnet slab CCTegYZ...\n\n// V_ADL account field offsets (relative to account slot start):\n// account_id(8)+capital(U128,16)+kind(u8+pad7=8)+pnl(I128,16)+reserved_pnl(u128,16)=64\nconst V_ADL_ACCT_WARMUP_STARTED_OFF = 64; // was 56\nconst V_ADL_ACCT_WARMUP_SLOPE_OFF = 72; // was 64\nconst V_ADL_ACCT_POSITION_SIZE_OFF = 88; // was 80\nconst V_ADL_ACCT_ENTRY_PRICE_OFF = 104; // was 96\nconst V_ADL_ACCT_FUNDING_INDEX_OFF = 112; // was 104\nconst V_ADL_ACCT_MATCHER_PROGRAM_OFF = 128; // was 120\nconst V_ADL_ACCT_MATCHER_CONTEXT_OFF = 160; // was 152\nconst V_ADL_ACCT_OWNER_OFF = 192; // was 184 (shifted +8 from reserved_pnl u64→u128)\nconst V_ADL_ACCT_FEE_CREDITS_OFF = 224; // was 216\nconst V_ADL_ACCT_LAST_FEE_SLOT_OFF = 240; // was 232\n\n// ---- V12_1 layout constants (percolator-core v12.1 merge) ----\n// Account struct grew: 312→320 bytes on SBF (new fields: position_basis_q, adl_a_basis,\n// adl_k_snap, adl_epoch_snap, fees_earned_total; fee_credits/last_fee_slot reordered).\n// RiskParams grew: 336→352 bytes on SBF (new fields: min_initial_deposit, insurance_floor,\n// risk_reduction_threshold, liquidation_buffer_bps, funding premium params, partial liq,\n// dynamic fee tiers, fee splits).\n// Engine field ordering completely reorganized from V_ADL.\n// All values verified by cargo build-sbf compile-time assertions.\nconst V12_1_ENGINE_OFF = 648; // align_up(104 + 544, 8) = 648 (same as V_SETDEXPOOL)\nconst V12_1_ACCOUNT_SIZE = 320; // 312 + 8 (position_size now i128 not just legacy)\nconst V12_1_ENGINE_BITMAP_OFF = 1016; // RiskParams grew 16 bytes + lifetime_force_realize_closes added\nconst V12_1_ENGINE_PARAMS_OFF = 96; // vault(16) + InsuranceFund(80) = 96\nconst V12_1_PARAMS_SIZE = 352; // 336 + 16 (new fields)\n// Engine field offsets (relative to engineOff):\nconst V12_1_ENGINE_CURRENT_SLOT_OFF = 448;\nconst V12_1_ENGINE_FUNDING_RATE_BPS_OFF = 456; // funding_rate_bps_per_slot_last\nconst V12_1_ENGINE_LAST_CRANK_SLOT_OFF = 464;\nconst V12_1_ENGINE_MAX_CRANK_STALENESS_OFF = 472;\nconst V12_1_ENGINE_C_TOT_OFF = 480;\nconst V12_1_ENGINE_PNL_POS_TOT_OFF = 496;\n// pnl_matured_pos_tot(u128)@512\nconst V12_1_ENGINE_LIQ_CURSOR_OFF = 528;\nconst V12_1_ENGINE_GC_CURSOR_OFF = 530;\nconst V12_1_ENGINE_LAST_SWEEP_START_OFF = 536;\nconst V12_1_ENGINE_LAST_SWEEP_COMPLETE_OFF = 544;\nconst V12_1_ENGINE_CRANK_CURSOR_OFF = 552;\nconst V12_1_ENGINE_SWEEP_START_IDX_OFF = 554;\nconst V12_1_ENGINE_LIFETIME_LIQUIDATIONS_OFF = 560;\n// ADL side state at 568–815 (not directly read by SDK)\nconst V12_1_ENGINE_TOTAL_OI_OFF = 816;\nconst V12_1_ENGINE_LONG_OI_OFF = 832;\nconst V12_1_ENGINE_SHORT_OI_OFF = 848;\nconst V12_1_ENGINE_NET_LP_POS_OFF = 864;\nconst V12_1_ENGINE_LP_SUM_ABS_OFF = 880;\nconst V12_1_ENGINE_LP_MAX_ABS_OFF = 896;\nconst V12_1_ENGINE_LP_MAX_ABS_SWEEP_OFF = 912;\nconst V12_1_ENGINE_MARK_PRICE_OFF = 928;\nconst V12_1_ENGINE_FUNDING_INDEX_OFF = 936;\nconst V12_1_ENGINE_LAST_FUNDING_SLOT_OFF = 944;\n// funding_frozen(bool)@952, pad@953-959, funding_frozen_rate_snapshot(i64)@960\nconst V12_1_ENGINE_EMERGENCY_OI_MODE_OFF = 968;\nconst V12_1_ENGINE_EMERGENCY_START_SLOT_OFF = 976;\nconst V12_1_ENGINE_LAST_BREAKER_SLOT_OFF = 984;\n// trade_twap_e6(8)@992, twap_last_slot(8)@1000, lifetime_force_realize_closes(8)@1008\nconst V12_1_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 1008;\n// bitmap at 1016\n// V12_1 account field offsets (relative to account slot start):\n// New fields position_basis_q(i128@88), adl_a_basis(u128@104), adl_k_snap(i128@120),\n// adl_epoch_snap(u64@136) inserted before matcher_*, shifting everything from offset 128+ by +16.\nconst V12_1_ACCT_MATCHER_PROGRAM_OFF = 144; // was 128 in V_ADL (+16 from new ADL fields)\nconst V12_1_ACCT_MATCHER_CONTEXT_OFF = 176; // was 160 in V_ADL (+16 from new ADL fields)\nconst V12_1_ACCT_OWNER_OFF = 208; // was 192 in V_ADL (+16 from new ADL fields)\nconst V12_1_ACCT_FEE_CREDITS_OFF = 240; // was 224 in V_ADL\nconst V12_1_ACCT_LAST_FEE_SLOT_OFF = 256; // was 240 in V_ADL\nconst V12_1_ACCT_POSITION_SIZE_OFF = 296; // moved to end (legacy field)\nconst V12_1_ACCT_ENTRY_PRICE_OFF = 280; // moved to end (legacy field)\nconst V12_1_ACCT_FUNDING_INDEX_OFF = 288; // moved to end (legacy, i64 not i128)\n\n// ---- V1M layout constants (mainnet-deployed V1 program, ESa89R5) ----\n// The mainnet program has a LARGER RiskParams (336 bytes vs V1's 288) and 22 extra\n// bytes in the runtime state (trade_twap_e6 + twap_last_slot + alignment padding).\n// ENGINE_OFF=640 (same as V1_LEGACY), CONFIG_LEN=536, ACCOUNT_SIZE=248.\n// Confirmed by byte-level probing of mainnet slab 8NY7rvQ (SOL/USDC Perpetual).\nconst V1M_ENGINE_OFF = 640; // align_up(104 + 536, 8) = 640 (same as V1_LEGACY)\nconst V1M_CONFIG_LEN = 536; // MarketConfig size in native/mainnet build\nconst V1M_ACCOUNT_SIZE = 248;\n// V1M2: rebuilt from main@4861c56, CONFIG_LEN=512 on SBF → ENGINE_OFF=616\nconst V1M2_ENGINE_OFF = 616; // align_up(104 + 512, 8) = 616\nconst V1M2_CONFIG_LEN = 512; // MarketConfig with u128 native alignment on SBF\nconst V1M_ENGINE_PARAMS_OFF = 72; // vault(16) + InsuranceFund(56) = 72 (same as V1)\nconst V1M2_ENGINE_PARAMS_OFF = 96; // vault(16) + InsuranceFund(80) = 96 (expanded in main@4861c56)\n\n// V1M RiskParams: 336 bytes (+48 over V1's 288)\n// Extra fields: fee_utilization_surge_bps(8) [in SDK V1 already? no → +8],\n// balance_incentive_reserve configs (+8?), min_nonzero_mm_req(u128=16),\n// min_nonzero_im_req(u128=16) = +48 total\nconst V1M_PARAMS_SIZE = 336;\n\n// V1M runtime state starts at engine+408 (72 + 336) instead of V1's +360\nconst V1M_ENGINE_CURRENT_SLOT_OFF = 408;\nconst V1M_ENGINE_FUNDING_INDEX_OFF = 416;\nconst V1M_ENGINE_LAST_FUNDING_SLOT_OFF = 432;\nconst V1M_ENGINE_FUNDING_RATE_BPS_OFF = 440;\nconst V1M_ENGINE_MARK_PRICE_OFF = 448;\n// funding_frozen(1+7pad) at 456, funding_frozen_rate(8) at 464\nconst V1M_ENGINE_LAST_CRANK_SLOT_OFF = 472;\nconst V1M_ENGINE_MAX_CRANK_STALENESS_OFF = 480;\nconst V1M_ENGINE_TOTAL_OI_OFF = 488;\nconst V1M_ENGINE_LONG_OI_OFF = 504;\nconst V1M_ENGINE_SHORT_OI_OFF = 520;\nconst V1M_ENGINE_C_TOT_OFF = 536;\nconst V1M_ENGINE_PNL_POS_TOT_OFF = 552;\nconst V1M_ENGINE_LIQ_CURSOR_OFF = 568;\nconst V1M_ENGINE_GC_CURSOR_OFF = 570;\nconst V1M_ENGINE_LAST_SWEEP_START_OFF = 576;\nconst V1M_ENGINE_LAST_SWEEP_COMPLETE_OFF = 584;\nconst V1M_ENGINE_CRANK_CURSOR_OFF = 592;\nconst V1M_ENGINE_SWEEP_START_IDX_OFF = 594;\nconst V1M_ENGINE_LIFETIME_LIQUIDATIONS_OFF = 600;\nconst V1M_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 608;\nconst V1M_ENGINE_NET_LP_POS_OFF = 616;\nconst V1M_ENGINE_LP_SUM_ABS_OFF = 632;\nconst V1M_ENGINE_LP_MAX_ABS_OFF = 648;\nconst V1M_ENGINE_LP_MAX_ABS_SWEEP_OFF = 664;\nconst V1M_ENGINE_EMERGENCY_OI_MODE_OFF = 680;\nconst V1M_ENGINE_EMERGENCY_START_SLOT_OFF = 688;\nconst V1M_ENGINE_LAST_BREAKER_SLOT_OFF = 696;\n// trade_twap_e6(8) at 704, twap_last_slot(8) at 712 → bitmap at 720\n// No padding between twap_last_slot and used bitmap (u64 array is 8-byte\n// aligned and 720 % 8 == 0). Previous value of 726 was wrong — 726 % 8 = 6\n// which is invalid for a [u64; N] array under #[repr(C)].\nconst V1M_ENGINE_BITMAP_OFF = 720;\n\n// V1M2: mainnet program rebuilt from main@4861c56 with --features medium.\n// ENGINE_OFF=616 (not 640): CONFIG_LEN=512 on SBF because cfg(target_arch=\"bpf\")\n// doesn't match the SBF toolchain (target_arch=\"sbf\"), so u128 align=16 (native) applies.\n// align_up(HEADER=104 + CONFIG=512, 8) = 616.\n// Slab sizes match V_ADL exactly — disambiguation required via data inspection.\n// Confirmed by on-chain probing of slab 7T1Efij9 (SOL-PERP, 323312 bytes, medium tier).\n// Engine struct is larger than V1M (990 vs 720 bitmap offset = +270 runtime bytes).\n// New runtime fields inserted between fundingRateBps and markPrice:\n// +408: currentSlot, +416: fundingIndex(i128), +432: lastFundingSlot, +440: fundingRateBps\n// +448: NEW lastOracleUpdateSlot(?), +456: authorityPriceE6(?), +464-471: reserved\n// +472: lastEffectivePriceE6(?), +480: markPriceE6, +488-503: reserved\n// +504: lastCrankSlot, +512: maxCrankStaleness\nconst V1M2_ACCOUNT_SIZE = 312; // 248 + 64 bytes of new fields per account\n// V1M2 bitmap offset: empirically verified from mainnet slab CCTegYZ... (323312 bytes, 1024 accts).\n// The V1M2 engine struct is layout-identical to V_ADL — same relative field offsets from engineOff.\n// V_ADL_ENGINE_BITMAP_OFF (1008) is correct for V1M2 as well; prior value of 990 was wrong.\nconst V1M2_ENGINE_BITMAP_OFF = 1008; // Same as V_ADL_ENGINE_BITMAP_OFF — V1M2 uses V_ADL engine struct\n\n// For backward compatibility, export ENGINE_OFF and ENGINE_MARK_PRICE_OFF\n// (used by reinit-slab and other scripts). These refer to V1 layout.\nexport const ENGINE_OFF = V1_ENGINE_OFF;\nexport const ENGINE_MARK_PRICE_OFF = V1_ENGINE_MARK_PRICE_OFF;\n\n// ---- Known slab sizes per version and tier ----\n\n/**\n * Compute the total byte size of a slab given its layout parameters.\n * Used to pre-populate the known-size lookup maps at module load time.\n */\nfunction computeSlabSize(\n engineOff: number,\n bitmapOff: number,\n accountSize: number,\n maxAccounts: number,\n // postBitmap bytes immediately after the free-slot bitmap:\n // SDK default (V0/V1/V1-legacy): 18 = num_used(u16,2) + pad(6) + next_account_id(u64,8) + free_head(u16,2)\n // V1D deployed program: 2 = free_head(u16,2) only — no num_used, pad, or next_account_id\n postBitmap = 18,\n): number {\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOff = Math.ceil(preAccountsLen / 8) * 8;\n return engineOff + accountsOff + maxAccounts * accountSize;\n}\n\nconst TIERS = [64, 256, 1024, 4096] as const;\n\n// Pre-compute known slab sizes for fast lookup\nconst V0_SIZES = new Map<number, number>();\nconst V1_SIZES = new Map<number, number>();\n// Legacy V1 sizes using incorrect ENGINE_OFF=640 (pre-PERC-1094). Orphaned on devnet; read-only.\nconst V1_SIZES_LEGACY = new Map<number, number>();\n// V1D: actually deployed V1 program (ENGINE_OFF=424, BITMAP_OFF=624)\nconst V1D_SIZES = new Map<number, number>();\n// V1D_SIZES_LEGACY: on-chain slabs created before GH#1234 when SDK assumed postBitmap=18.\n// These are 16 bytes larger per tier (micro=17080, small=65104, medium=257200, large=1025584).\n// The top active market (6ZytbpV4, $14k 24h vol) was created with postBitmap=18 and uses 65104.\n// PR #1236 fixed postBitmap for new slabs (→2) but broke recognition of these legacy 65104 slabs.\n// GH#1237: add both size variants so detectSlabLayout handles both old and new V1D on-chain data.\n// V2: ENGINE_OFF=600, BITMAP_OFF=432, ACCOUNT_SIZE=248, postBitmap=18\nconst V2_SIZES = new Map<number, number>();\n// V1M: mainnet-deployed V1 program (ENGINE_OFF=640, BITMAP_OFF=726, expanded RiskParams)\nconst V1M_SIZES = new Map<number, number>();\n// V_ADL: PERC-8270/8271 ADL-upgraded program (ENGINE_OFF=624, BITMAP_OFF=1008, ACCOUNT_SIZE=312)\nconst V_ADL_SIZES = new Map<number, number>();\n// V1M2: main@4861c56 with 312-byte accounts (ENGINE_OFF=616, BITMAP_OFF=1008, ACCOUNT_SIZE=312)\n// After fixing bitmapOff to 1008 for both V1M2 and V_ADL, sizes differ because engineOff differs:\n// V1M2 medium (1024 accts): computeSlabSize(616, 1008, 312, 1024, 18) = 323312\n// V_ADL medium (1024 accts): computeSlabSize(624, 1008, 312, 1024, 18) = 323320\n// No disambiguation probe required — size-based detection works correctly.\nconst V1M2_SIZES = new Map<number, number>();\n// V_SETDEXPOOL: PERC-SetDexPool — ENGINE_OFF=648, BITMAP_OFF=1008, ACCOUNT_SIZE=312.\n// Same engine and account layout as V_ADL; only ENGINE_OFF changed (+8 from config growth).\n// e.g. large (4096 accts): computeSlabSize(632, 1008, 312, 4096, 18) = 1288336\nconst V_SETDEXPOOL_SIZES = new Map<number, number>();\n// V12_1: percolator-core v12.1 merge — engineOff=648, bitmapOff=1016, accountSize=320.\n// Verified by cargo build-sbf compile-time assertions. Account grew 8 bytes, bitmap shifted 8.\n// e.g. large (4096 accts): computeSlabSize(648, 1016, 320, 4096, 18) = 1321112\nconst V12_1_SIZES = new Map<number, number>();\nconst V1D_SIZES_LEGACY = new Map<number, number>();\nfor (const n of TIERS) {\n V0_SIZES.set(computeSlabSize(V0_ENGINE_OFF, V0_ENGINE_BITMAP_OFF, V0_ACCOUNT_SIZE, n), n);\n V1_SIZES.set(computeSlabSize(V1_ENGINE_OFF, V1_ENGINE_BITMAP_OFF, V1_ACCOUNT_SIZE, n), n);\n V1_SIZES_LEGACY.set(computeSlabSize(V1_ENGINE_OFF_LEGACY, V1_ENGINE_BITMAP_OFF, V1_ACCOUNT_SIZE, n), n);\n // GH#1234: V1D deployed program omits num_used/pad/next_account_id → postBitmap=2 (free_head only).\n // This yields 65088 (n=256) and 1025568 (n=4096) matching actual devnet account sizes.\n V1D_SIZES.set(computeSlabSize(V1D_ENGINE_OFF, V1D_ENGINE_BITMAP_OFF, V1D_ACCOUNT_SIZE, n, 2), n);\n // GH#1237: also register the legacy postBitmap=18 sizes for slabs created before GH#1234 fix.\n V1D_SIZES_LEGACY.set(computeSlabSize(V1D_ENGINE_OFF, V1D_ENGINE_BITMAP_OFF, V1D_ACCOUNT_SIZE, n, 18), n);\n // V2: postBitmap=18 — produces same sizes as V1D postBitmap=2 (e.g. 65088 for n=256).\n // Disambiguation requires peeking at the version field in the slab header.\n V2_SIZES.set(computeSlabSize(V2_ENGINE_OFF, V2_ENGINE_BITMAP_OFF, V2_ACCOUNT_SIZE, n, 18), n);\n // V1M: mainnet program with expanded RiskParams (336 bytes) and trade_twap fields.\n // e.g. n=1024 → 257512 bytes (confirmed on-chain for slab 8NY7rvQ).\n V1M_SIZES.set(computeSlabSize(V1M_ENGINE_OFF, V1M_ENGINE_BITMAP_OFF, V1M_ACCOUNT_SIZE, n, 18), n);\n // V_ADL: PERC-8270 ADL-upgraded program — new account size (312) and expanded engine layout.\n // e.g. n=4096 → 1288320 bytes (engineOff=624, bitmapOff=1008).\n V_ADL_SIZES.set(computeSlabSize(V_ADL_ENGINE_OFF, V_ADL_ENGINE_BITMAP_OFF, V_ADL_ACCOUNT_SIZE, n, 18), n);\n // V1M2: main@4861c56 rebuild — engineOff=616, bitmapOff=1008, accountSize=312.\n // e.g. n=1024 → 323312 bytes (confirmed on-chain for slab CCTegYZ...).\n V1M2_SIZES.set(computeSlabSize(V1M2_ENGINE_OFF, V1M2_ENGINE_BITMAP_OFF, V1M2_ACCOUNT_SIZE, n, 18), n);\n // V_SETDEXPOOL: PERC-SetDexPool — engineOff=648, bitmapOff=1008, accountSize=312.\n // e.g. n=4096 → 1288336 bytes.\n V_SETDEXPOOL_SIZES.set(computeSlabSize(V_SETDEXPOOL_ENGINE_OFF, V_ADL_ENGINE_BITMAP_OFF, V_ADL_ACCOUNT_SIZE, n, 18), n);\n // V12_1: percolator-core v12.1 — accountSize=320, bitmapOff=1016.\n // e.g. n=4096 → 1321112; n=1024 → 331544; n=256 → 84152; n=64 → 22304.\n V12_1_SIZES.set(computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, n, 18), n);\n}\n\n/**\n * V2 slab tier sizes (small and large) for discovery.\n * V2 uses ENGINE_OFF=600, BITMAP_OFF=432, ACCOUNT_SIZE=248, postBitmap=18.\n * Sizes overlap with V1D (postBitmap=2) — disambiguation requires reading the version field.\n */\nexport const SLAB_TIERS_V2 = {\n small: { maxAccounts: 256, dataSize: 65_088, label: \"Small\", description: \"256 slots (V2 BPF intermediate)\" },\n large: { maxAccounts: 4096, dataSize: 1_025_568, label: \"Large\", description: \"4,096 slots (V2 BPF intermediate)\" },\n} as const;\n\n/**\n * V1M slab tier sizes — mainnet-deployed V1 program (ESa89R5).\n * ENGINE_OFF=640, BITMAP_OFF=726, ACCOUNT_SIZE=248, postBitmap=18.\n * Expanded RiskParams (336 bytes) and trade_twap runtime fields.\n * Confirmed by on-chain probing of slab 8NY7rvQ (SOL/USDC Perpetual, 257512 bytes).\n */\nexport const SLAB_TIERS_V1M: Record<string, { maxAccounts: number; dataSize: number; label: string; description: string }> = {};\nfor (const [label, n] of [[\"Micro\", 64], [\"Small\", 256], [\"Medium\", 1024], [\"Large\", 4096]] as const) {\n const size = computeSlabSize(V1M_ENGINE_OFF, V1M_ENGINE_BITMAP_OFF, V1M_ACCOUNT_SIZE, n, 18);\n SLAB_TIERS_V1M[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (V1M mainnet)` };\n}\n\n/**\n * V1M2 slab tier sizes — mainnet program rebuilt from main@4861c56 with 312-byte accounts.\n * ENGINE_OFF=616, BITMAP_OFF=1008 (empirically verified from CCTegYZ...).\n * Engine struct is layout-identical to V_ADL; differs only in engineOff (616 vs 624).\n * Sizes are unique from V_ADL after the bitmap correction: medium=323312 vs V_ADL=323320.\n */\nexport const SLAB_TIERS_V1M2: Record<string, { maxAccounts: number; dataSize: number; label: string; description: string }> = {};\nfor (const [label, n] of [[\"Micro\", 64], [\"Small\", 256], [\"Medium\", 1024], [\"Large\", 4096]] as const) {\n const size = computeSlabSize(V1M2_ENGINE_OFF, V1M2_ENGINE_BITMAP_OFF, V1M2_ACCOUNT_SIZE, n, 18);\n SLAB_TIERS_V1M2[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (V1M2 mainnet upgraded)` };\n}\n\n/**\n * V_ADL slab tier sizes — PERC-8270/8271 ADL-upgraded program.\n * ENGINE_OFF=624, BITMAP_OFF=1008, ACCOUNT_SIZE=312, postBitmap=18.\n * New account layout adds ADL tracking fields (+64 bytes/account including alignment padding).\n * BPF SLAB_LEN verified by cargo build-sbf in PERC-8271: large (4096) = 1288320 bytes.\n */\nexport const SLAB_TIERS_V_ADL: Record<string, { maxAccounts: number; dataSize: number; label: string; description: string }> = {};\nfor (const [label, n] of [[\"Micro\", 64], [\"Small\", 256], [\"Medium\", 1024], [\"Large\", 4096]] as const) {\n const size = computeSlabSize(V_ADL_ENGINE_OFF, V_ADL_ENGINE_BITMAP_OFF, V_ADL_ACCOUNT_SIZE, n, 18);\n SLAB_TIERS_V_ADL[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (V_ADL PERC-8270)` };\n}\n\n/**\n * Build a complete SlabLayout descriptor for V0 or V1 (including V1-legacy) slabs.\n * Pass `engineOffOverride` to handle orphaned pre-PERC-1094 slabs that used ENGINE_OFF=640.\n */\nfunction buildLayout(version: 0 | 1, maxAccounts: number, engineOffOverride?: number): SlabLayout {\n const isV0 = version === 0;\n const engineOff = engineOffOverride ?? (isV0 ? V0_ENGINE_OFF : V1_ENGINE_OFF);\n const isV1Legacy = !isV0 && engineOffOverride === V1_ENGINE_OFF_LEGACY;\n // For accountsOff calculation, V1_LEGACY must use its actual bitmap offset (672, not 656).\n // Using the formula bitmapOff (656) produces accountsOff=1864, but accounts actually\n // start at 1880 — a 16-byte gap caused by the extra fields in the V1_LEGACY engine.\n // Non-V1_LEGACY slabs: actualBitmapOff === bitmapOff, so no change.\n const bitmapOff = isV0 ? V0_ENGINE_BITMAP_OFF : V1_ENGINE_BITMAP_OFF;\n const actualBitmapOff = isV1Legacy ? V1_LEGACY_ENGINE_BITMAP_OFF_ACTUAL\n : (isV0 ? V0_ENGINE_BITMAP_OFF : V1_ENGINE_BITMAP_OFF);\n const accountSize = isV0 ? V0_ACCOUNT_SIZE : V1_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n // Use actualBitmapOff so V1_LEGACY gets accountsOff=1880 (not 1864).\n const preAccountsLen = actualBitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version,\n headerLen: isV0 ? V0_HEADER_LEN : V1_HEADER_LEN,\n configOffset: isV0 ? V0_HEADER_LEN : V1_HEADER_LEN,\n configLen: isV0 ? V0_CONFIG_LEN : V1_CONFIG_LEN,\n reservedOff: isV0 ? V0_RESERVED_OFF : V1_RESERVED_OFF,\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: isV0 ? V0_ENGINE_PARAMS_OFF : V1_ENGINE_PARAMS_OFF,\n paramsSize: isV0 ? V0_PARAMS_SIZE : V1_PARAMS_SIZE,\n engineCurrentSlotOff: isV0 ? V0_ENGINE_CURRENT_SLOT_OFF : V1_ENGINE_CURRENT_SLOT_OFF,\n engineFundingIndexOff: isV0 ? V0_ENGINE_FUNDING_INDEX_OFF : V1_ENGINE_FUNDING_INDEX_OFF,\n engineLastFundingSlotOff: isV0 ? V0_ENGINE_LAST_FUNDING_SLOT_OFF : V1_ENGINE_LAST_FUNDING_SLOT_OFF,\n engineFundingRateBpsOff: isV0 ? V0_ENGINE_FUNDING_RATE_BPS_OFF : V1_ENGINE_FUNDING_RATE_BPS_OFF,\n engineMarkPriceOff: isV0 ? -1 : V1_ENGINE_MARK_PRICE_OFF,\n engineLastCrankSlotOff: isV0 ? V0_ENGINE_LAST_CRANK_SLOT_OFF : V1_ENGINE_LAST_CRANK_SLOT_OFF,\n engineMaxCrankStalenessOff: isV0 ? V0_ENGINE_MAX_CRANK_STALENESS_OFF : V1_ENGINE_MAX_CRANK_STALENESS_OFF,\n engineTotalOiOff: isV0 ? V0_ENGINE_TOTAL_OI_OFF : V1_ENGINE_TOTAL_OI_OFF,\n engineLongOiOff: isV0 ? -1 : V1_ENGINE_LONG_OI_OFF,\n engineShortOiOff: isV0 ? -1 : V1_ENGINE_SHORT_OI_OFF,\n engineCTotOff: isV0 ? V0_ENGINE_C_TOT_OFF : V1_ENGINE_C_TOT_OFF,\n enginePnlPosTotOff: isV0 ? V0_ENGINE_PNL_POS_TOT_OFF : V1_ENGINE_PNL_POS_TOT_OFF,\n engineLiqCursorOff: isV0 ? V0_ENGINE_LIQ_CURSOR_OFF : V1_ENGINE_LIQ_CURSOR_OFF,\n engineGcCursorOff: isV0 ? V0_ENGINE_GC_CURSOR_OFF : V1_ENGINE_GC_CURSOR_OFF,\n engineLastSweepStartOff: isV0 ? V0_ENGINE_LAST_SWEEP_START_OFF : V1_ENGINE_LAST_SWEEP_START_OFF,\n engineLastSweepCompleteOff: isV0 ? V0_ENGINE_LAST_SWEEP_COMPLETE_OFF : V1_ENGINE_LAST_SWEEP_COMPLETE_OFF,\n engineCrankCursorOff: isV0 ? V0_ENGINE_CRANK_CURSOR_OFF : V1_ENGINE_CRANK_CURSOR_OFF,\n engineSweepStartIdxOff: isV0 ? V0_ENGINE_SWEEP_START_IDX_OFF : V1_ENGINE_SWEEP_START_IDX_OFF,\n engineLifetimeLiquidationsOff: isV0 ? V0_ENGINE_LIFETIME_LIQUIDATIONS_OFF : V1_ENGINE_LIFETIME_LIQUIDATIONS_OFF,\n engineLifetimeForceClosesOff: isV0 ? V0_ENGINE_LIFETIME_FORCE_CLOSES_OFF : V1_ENGINE_LIFETIME_FORCE_CLOSES_OFF,\n engineNetLpPosOff: isV0 ? V0_ENGINE_NET_LP_POS_OFF : V1_ENGINE_NET_LP_POS_OFF,\n engineLpSumAbsOff: isV0 ? V0_ENGINE_LP_SUM_ABS_OFF : V1_ENGINE_LP_SUM_ABS_OFF,\n engineLpMaxAbsOff: isV0 ? V0_ENGINE_LP_MAX_ABS_OFF : V1_ENGINE_LP_MAX_ABS_OFF,\n engineLpMaxAbsSweepOff: isV0 ? V0_ENGINE_LP_MAX_ABS_SWEEP_OFF : V1_ENGINE_LP_MAX_ABS_SWEEP_OFF,\n engineEmergencyOiModeOff: isV0 ? -1 : V1_ENGINE_EMERGENCY_OI_MODE_OFF,\n engineEmergencyStartSlotOff: isV0 ? -1 : V1_ENGINE_EMERGENCY_START_SLOT_OFF,\n engineLastBreakerSlotOff: isV0 ? -1 : V1_ENGINE_LAST_BREAKER_SLOT_OFF,\n engineBitmapOff: actualBitmapOff,\n postBitmap: 18,\n acctOwnerOff: ACCT_OWNER_OFF,\n\n hasInsuranceIsolation: !isV0,\n engineInsuranceIsolatedOff: isV0 ? -1 : 48,\n engineInsuranceIsolationBpsOff: isV0 ? -1 : 64,\n };\n}\n\n/**\n * Build layout for V1D (actually deployed V1 program, rev ac18a0e).\n * Uses correct field offsets derived from on-chain probing.\n *\n * @param maxAccounts - Number of account slots in the slab\n * @param postBitmap - Bytes after the bitmap before next_free array.\n * 2 = free_head(u16) only — deployed program (GH#1234, default for new slabs)\n * 18 = num_used(u16)+pad(6)+next_account_id(u64)+free_head(u16) — legacy on-chain slabs (GH#1237)\n */\n/**\n * Build a SlabLayout for the actually-deployed V1D program (ENGINE_OFF=424).\n * `postBitmap` is 2 for new slabs (free_head only) and 18 for legacy on-chain slabs\n * created before the GH#1234 fix that removed num_used/pad/next_account_id.\n */\nfunction buildLayoutV1D(maxAccounts: number, postBitmap = 2): SlabLayout {\n const engineOff = V1D_ENGINE_OFF;\n const bitmapOff = V1D_ENGINE_BITMAP_OFF;\n const accountSize = V1D_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version: 1,\n headerLen: V1_HEADER_LEN,\n configOffset: V1_HEADER_LEN,\n configLen: V1D_CONFIG_LEN,\n reservedOff: V1_RESERVED_OFF,\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: V1D_ENGINE_INSURANCE_OFF,\n engineParamsOff: V1D_ENGINE_PARAMS_OFF,\n paramsSize: V1D_PARAMS_SIZE,\n engineCurrentSlotOff: V1D_ENGINE_CURRENT_SLOT_OFF,\n engineFundingIndexOff: V1D_ENGINE_FUNDING_INDEX_OFF,\n engineLastFundingSlotOff: V1D_ENGINE_LAST_FUNDING_SLOT_OFF,\n engineFundingRateBpsOff: V1D_ENGINE_FUNDING_RATE_BPS_OFF,\n engineMarkPriceOff: V1D_ENGINE_MARK_PRICE_OFF,\n engineLastCrankSlotOff: V1D_ENGINE_LAST_CRANK_SLOT_OFF,\n engineMaxCrankStalenessOff: V1D_ENGINE_MAX_CRANK_STALENESS_OFF,\n engineTotalOiOff: V1D_ENGINE_TOTAL_OI_OFF,\n engineLongOiOff: V1D_ENGINE_LONG_OI_OFF,\n engineShortOiOff: V1D_ENGINE_SHORT_OI_OFF,\n engineCTotOff: V1D_ENGINE_C_TOT_OFF,\n enginePnlPosTotOff: V1D_ENGINE_PNL_POS_TOT_OFF,\n engineLiqCursorOff: V1D_ENGINE_LIQ_CURSOR_OFF,\n engineGcCursorOff: V1D_ENGINE_GC_CURSOR_OFF,\n engineLastSweepStartOff: V1D_ENGINE_LAST_SWEEP_START_OFF,\n engineLastSweepCompleteOff: V1D_ENGINE_LAST_SWEEP_COMPLETE_OFF,\n engineCrankCursorOff: V1D_ENGINE_CRANK_CURSOR_OFF,\n engineSweepStartIdxOff: V1D_ENGINE_SWEEP_START_IDX_OFF,\n engineLifetimeLiquidationsOff: V1D_ENGINE_LIFETIME_LIQUIDATIONS_OFF,\n engineLifetimeForceClosesOff: V1D_ENGINE_LIFETIME_FORCE_CLOSES_OFF,\n engineNetLpPosOff: V1D_ENGINE_NET_LP_POS_OFF,\n engineLpSumAbsOff: V1D_ENGINE_LP_SUM_ABS_OFF,\n engineLpMaxAbsOff: -1, // not present in deployed V1\n engineLpMaxAbsSweepOff: -1, // not present in deployed V1\n engineEmergencyOiModeOff: -1, // not present in deployed V1\n engineEmergencyStartSlotOff: -1, // not present in deployed V1\n engineLastBreakerSlotOff: -1, // not present in deployed V1\n engineBitmapOff: V1D_ENGINE_BITMAP_OFF,\n postBitmap,\n acctOwnerOff: ACCT_OWNER_OFF,\n\n hasInsuranceIsolation: true,\n engineInsuranceIsolatedOff: 48, // same within InsuranceFund\n engineInsuranceIsolationBpsOff: 64, // same within InsuranceFund\n };\n}\n\n/**\n * Build a SlabLayout for V2 (BPF intermediate layout).\n * ENGINE_OFF=600, BITMAP_OFF=432, ACCOUNT_SIZE=248, postBitmap=18.\n * V2 lacks mark_price, long_oi, short_oi, emergency OI fields.\n */\nfunction buildLayoutV2(maxAccounts: number): SlabLayout {\n const engineOff = V2_ENGINE_OFF;\n const bitmapOff = V2_ENGINE_BITMAP_OFF;\n const accountSize = V2_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version: 2,\n headerLen: V2_HEADER_LEN,\n configOffset: V2_HEADER_LEN,\n configLen: V2_CONFIG_LEN,\n reservedOff: V1_RESERVED_OFF, // V2 shares V1's header layout (reserved at 80)\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: V1_ENGINE_PARAMS_OFF, // same as V1: 72\n paramsSize: V1_PARAMS_SIZE, // same as V1: 288\n engineCurrentSlotOff: V2_ENGINE_CURRENT_SLOT_OFF,\n engineFundingIndexOff: V2_ENGINE_FUNDING_INDEX_OFF,\n engineLastFundingSlotOff: V2_ENGINE_LAST_FUNDING_SLOT_OFF,\n engineFundingRateBpsOff: V2_ENGINE_FUNDING_RATE_BPS_OFF,\n engineMarkPriceOff: -1, // V2 has no mark_price\n engineLastCrankSlotOff: V2_ENGINE_LAST_CRANK_SLOT_OFF,\n engineMaxCrankStalenessOff: V2_ENGINE_MAX_CRANK_STALENESS_OFF,\n engineTotalOiOff: V2_ENGINE_TOTAL_OI_OFF,\n engineLongOiOff: -1, // V2 has no long_oi\n engineShortOiOff: -1, // V2 has no short_oi\n engineCTotOff: V2_ENGINE_C_TOT_OFF,\n enginePnlPosTotOff: V2_ENGINE_PNL_POS_TOT_OFF,\n engineLiqCursorOff: V2_ENGINE_LIQ_CURSOR_OFF,\n engineGcCursorOff: V2_ENGINE_GC_CURSOR_OFF,\n engineLastSweepStartOff: V2_ENGINE_LAST_SWEEP_START_OFF,\n engineLastSweepCompleteOff: V2_ENGINE_LAST_SWEEP_COMPLETE_OFF,\n engineCrankCursorOff: V2_ENGINE_CRANK_CURSOR_OFF,\n engineSweepStartIdxOff: V2_ENGINE_SWEEP_START_IDX_OFF,\n engineLifetimeLiquidationsOff: V2_ENGINE_LIFETIME_LIQUIDATIONS_OFF,\n engineLifetimeForceClosesOff: V2_ENGINE_LIFETIME_FORCE_CLOSES_OFF,\n engineNetLpPosOff: V2_ENGINE_NET_LP_POS_OFF,\n engineLpSumAbsOff: V2_ENGINE_LP_SUM_ABS_OFF,\n engineLpMaxAbsOff: V2_ENGINE_LP_MAX_ABS_OFF,\n engineLpMaxAbsSweepOff: V2_ENGINE_LP_MAX_ABS_SWEEP_OFF,\n engineEmergencyOiModeOff: -1, // V2 has no emergency OI fields\n engineEmergencyStartSlotOff: -1,\n engineLastBreakerSlotOff: -1,\n engineBitmapOff: V2_ENGINE_BITMAP_OFF,\n postBitmap: 18,\n acctOwnerOff: ACCT_OWNER_OFF,\n\n hasInsuranceIsolation: true,\n engineInsuranceIsolatedOff: 48,\n engineInsuranceIsolationBpsOff: 64,\n };\n}\n\n/**\n * Build a SlabLayout for the V1M mainnet program (ESa89R5).\n * ENGINE_OFF=640 (same as V1_LEGACY), but expanded RiskParams (336 bytes)\n * and trade_twap runtime fields push the bitmap to offset 726.\n * Confirmed by on-chain probing of slab 8NY7rvQ (257512 bytes, medium tier).\n */\nfunction buildLayoutV1M(maxAccounts: number): SlabLayout {\n const engineOff = V1M_ENGINE_OFF;\n const bitmapOff = V1M_ENGINE_BITMAP_OFF;\n const accountSize = V1M_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version: 1,\n headerLen: V1_HEADER_LEN,\n configOffset: V1_HEADER_LEN,\n configLen: V1M_CONFIG_LEN,\n reservedOff: V1_RESERVED_OFF,\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: V1M_ENGINE_PARAMS_OFF,\n paramsSize: V1M_PARAMS_SIZE,\n engineCurrentSlotOff: V1M_ENGINE_CURRENT_SLOT_OFF,\n engineFundingIndexOff: V1M_ENGINE_FUNDING_INDEX_OFF,\n engineLastFundingSlotOff: V1M_ENGINE_LAST_FUNDING_SLOT_OFF,\n engineFundingRateBpsOff: V1M_ENGINE_FUNDING_RATE_BPS_OFF,\n engineMarkPriceOff: V1M_ENGINE_MARK_PRICE_OFF,\n engineLastCrankSlotOff: V1M_ENGINE_LAST_CRANK_SLOT_OFF,\n engineMaxCrankStalenessOff: V1M_ENGINE_MAX_CRANK_STALENESS_OFF,\n engineTotalOiOff: V1M_ENGINE_TOTAL_OI_OFF,\n engineLongOiOff: V1M_ENGINE_LONG_OI_OFF,\n engineShortOiOff: V1M_ENGINE_SHORT_OI_OFF,\n engineCTotOff: V1M_ENGINE_C_TOT_OFF,\n enginePnlPosTotOff: V1M_ENGINE_PNL_POS_TOT_OFF,\n engineLiqCursorOff: V1M_ENGINE_LIQ_CURSOR_OFF,\n engineGcCursorOff: V1M_ENGINE_GC_CURSOR_OFF,\n engineLastSweepStartOff: V1M_ENGINE_LAST_SWEEP_START_OFF,\n engineLastSweepCompleteOff: V1M_ENGINE_LAST_SWEEP_COMPLETE_OFF,\n engineCrankCursorOff: V1M_ENGINE_CRANK_CURSOR_OFF,\n engineSweepStartIdxOff: V1M_ENGINE_SWEEP_START_IDX_OFF,\n engineLifetimeLiquidationsOff: V1M_ENGINE_LIFETIME_LIQUIDATIONS_OFF,\n engineLifetimeForceClosesOff: V1M_ENGINE_LIFETIME_FORCE_CLOSES_OFF,\n engineNetLpPosOff: V1M_ENGINE_NET_LP_POS_OFF,\n engineLpSumAbsOff: V1M_ENGINE_LP_SUM_ABS_OFF,\n engineLpMaxAbsOff: V1M_ENGINE_LP_MAX_ABS_OFF,\n engineLpMaxAbsSweepOff: V1M_ENGINE_LP_MAX_ABS_SWEEP_OFF,\n engineEmergencyOiModeOff: V1M_ENGINE_EMERGENCY_OI_MODE_OFF,\n engineEmergencyStartSlotOff: V1M_ENGINE_EMERGENCY_START_SLOT_OFF,\n engineLastBreakerSlotOff: V1M_ENGINE_LAST_BREAKER_SLOT_OFF,\n engineBitmapOff: V1M_ENGINE_BITMAP_OFF,\n postBitmap: 18,\n acctOwnerOff: ACCT_OWNER_OFF,\n\n hasInsuranceIsolation: true,\n engineInsuranceIsolatedOff: 48,\n engineInsuranceIsolationBpsOff: 64,\n };\n}\n\n/**\n * Build a SlabLayout for V1M2 — mainnet program rebuilt from main@4861c56 with 312-byte accounts.\n * ENGINE_OFF=616 (align_up(104+512,8)=616), CONFIG_LEN=512.\n * The engine struct is layout-identical to V_ADL (same relative field offsets from engineOff),\n * so all runtime field offsets reuse V_ADL constants. bitmapOff=1008 (same as V_ADL).\n * This differs from V_ADL only in engineOff (616 vs 624) and configLen (512 vs 520).\n * Confirmed by empirical probing of mainnet slab CCTegYZ... (323312 bytes, 1024-account medium tier).\n */\nfunction buildLayoutV1M2(maxAccounts: number): SlabLayout {\n const engineOff = V1M2_ENGINE_OFF;\n const bitmapOff = V1M2_ENGINE_BITMAP_OFF;\n const accountSize = V1M2_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version: 1,\n headerLen: V1_HEADER_LEN,\n configOffset: V1_HEADER_LEN,\n configLen: V1M2_CONFIG_LEN,\n reservedOff: V1_RESERVED_OFF,\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: V1M2_ENGINE_PARAMS_OFF, // 96 — expanded InsuranceFund (same as V_ADL)\n paramsSize: V_ADL_PARAMS_SIZE, // 336 — same as V_ADL\n // Runtime fields: V1M2 engine struct is layout-identical to V_ADL — reuse V_ADL constants.\n engineCurrentSlotOff: V_ADL_ENGINE_CURRENT_SLOT_OFF, // 432\n engineFundingIndexOff: V_ADL_ENGINE_FUNDING_INDEX_OFF, // 440\n engineLastFundingSlotOff: V_ADL_ENGINE_LAST_FUNDING_SLOT_OFF, // 456\n engineFundingRateBpsOff: V_ADL_ENGINE_FUNDING_RATE_BPS_OFF, // 464\n engineMarkPriceOff: V_ADL_ENGINE_MARK_PRICE_OFF, // 504\n engineLastCrankSlotOff: V_ADL_ENGINE_LAST_CRANK_SLOT_OFF, // 528\n engineMaxCrankStalenessOff: V_ADL_ENGINE_MAX_CRANK_STALENESS_OFF, // 536\n engineTotalOiOff: V_ADL_ENGINE_TOTAL_OI_OFF, // 544\n engineLongOiOff: V_ADL_ENGINE_LONG_OI_OFF, // 560\n engineShortOiOff: V_ADL_ENGINE_SHORT_OI_OFF, // 576\n engineCTotOff: V_ADL_ENGINE_C_TOT_OFF, // 592\n enginePnlPosTotOff: V_ADL_ENGINE_PNL_POS_TOT_OFF, // 608\n engineLiqCursorOff: V_ADL_ENGINE_LIQ_CURSOR_OFF, // 640\n engineGcCursorOff: V_ADL_ENGINE_GC_CURSOR_OFF, // 642\n engineLastSweepStartOff: V_ADL_ENGINE_LAST_SWEEP_START_OFF, // 648\n engineLastSweepCompleteOff: V_ADL_ENGINE_LAST_SWEEP_COMPLETE_OFF, // 656\n engineCrankCursorOff: V_ADL_ENGINE_CRANK_CURSOR_OFF, // 664\n engineSweepStartIdxOff: V_ADL_ENGINE_SWEEP_START_IDX_OFF, // 666\n engineLifetimeLiquidationsOff: V_ADL_ENGINE_LIFETIME_LIQUIDATIONS_OFF, // 672\n engineLifetimeForceClosesOff: V_ADL_ENGINE_LIFETIME_FORCE_CLOSES_OFF, // 680\n engineNetLpPosOff: V_ADL_ENGINE_NET_LP_POS_OFF, // 904\n engineLpSumAbsOff: V_ADL_ENGINE_LP_SUM_ABS_OFF, // 920\n engineLpMaxAbsOff: V_ADL_ENGINE_LP_MAX_ABS_OFF, // 936\n engineLpMaxAbsSweepOff: V_ADL_ENGINE_LP_MAX_ABS_SWEEP_OFF, // 952\n engineEmergencyOiModeOff: V_ADL_ENGINE_EMERGENCY_OI_MODE_OFF, // 968\n engineEmergencyStartSlotOff: V_ADL_ENGINE_EMERGENCY_START_SLOT_OFF, // 976\n engineLastBreakerSlotOff: V_ADL_ENGINE_LAST_BREAKER_SLOT_OFF, // 984\n engineBitmapOff: V1M2_ENGINE_BITMAP_OFF,\n postBitmap: 18,\n acctOwnerOff: V_ADL_ACCT_OWNER_OFF, // 192 — same shift as V_ADL (reserved_pnl u64→u128)\n\n hasInsuranceIsolation: true,\n engineInsuranceIsolatedOff: 48,\n engineInsuranceIsolationBpsOff: 64,\n };\n}\n\n/**\n * Build a SlabLayout for the ADL-upgraded program (PERC-8270/8271).\n * ENGINE_OFF=624, BITMAP_OFF=1008, ACCOUNT_SIZE=312.\n *\n * Verified slab sizes (BPF, cargo build-sbf, bitmapOff corrected to 1008):\n * large (4096 accounts): 1288320 bytes\n * medium (1024 accounts): 323320 bytes\n * small (256 accounts): 82064 bytes\n */\nfunction buildLayoutVADL(maxAccounts: number): SlabLayout {\n const engineOff = V_ADL_ENGINE_OFF;\n const bitmapOff = V_ADL_ENGINE_BITMAP_OFF;\n const accountSize = V_ADL_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version: 1,\n headerLen: V1_HEADER_LEN, // 104 (unchanged)\n configOffset: V1_HEADER_LEN,\n configLen: V_ADL_CONFIG_LEN, // 520\n reservedOff: V1_RESERVED_OFF, // 80\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: V_ADL_ENGINE_PARAMS_OFF, // 96 (vault=16 + InsuranceFund=80)\n paramsSize: V_ADL_PARAMS_SIZE, // 336\n engineCurrentSlotOff: V_ADL_ENGINE_CURRENT_SLOT_OFF, // 432\n engineFundingIndexOff: V_ADL_ENGINE_FUNDING_INDEX_OFF, // 440\n engineLastFundingSlotOff: V_ADL_ENGINE_LAST_FUNDING_SLOT_OFF, // 456\n engineFundingRateBpsOff: V_ADL_ENGINE_FUNDING_RATE_BPS_OFF, // 464\n engineMarkPriceOff: V_ADL_ENGINE_MARK_PRICE_OFF, // 504\n engineLastCrankSlotOff: V_ADL_ENGINE_LAST_CRANK_SLOT_OFF, // 528\n engineMaxCrankStalenessOff: V_ADL_ENGINE_MAX_CRANK_STALENESS_OFF, // 536\n engineTotalOiOff: V_ADL_ENGINE_TOTAL_OI_OFF, // 544\n engineLongOiOff: V_ADL_ENGINE_LONG_OI_OFF, // 560\n engineShortOiOff: V_ADL_ENGINE_SHORT_OI_OFF, // 576\n engineCTotOff: V_ADL_ENGINE_C_TOT_OFF, // 592\n enginePnlPosTotOff: V_ADL_ENGINE_PNL_POS_TOT_OFF, // 608\n engineLiqCursorOff: V_ADL_ENGINE_LIQ_CURSOR_OFF, // 640\n engineGcCursorOff: V_ADL_ENGINE_GC_CURSOR_OFF, // 642\n engineLastSweepStartOff: V_ADL_ENGINE_LAST_SWEEP_START_OFF, // 648\n engineLastSweepCompleteOff: V_ADL_ENGINE_LAST_SWEEP_COMPLETE_OFF, // 656\n engineCrankCursorOff: V_ADL_ENGINE_CRANK_CURSOR_OFF, // 664\n engineSweepStartIdxOff: V_ADL_ENGINE_SWEEP_START_IDX_OFF, // 666\n engineLifetimeLiquidationsOff: V_ADL_ENGINE_LIFETIME_LIQUIDATIONS_OFF, // 672\n engineLifetimeForceClosesOff: V_ADL_ENGINE_LIFETIME_FORCE_CLOSES_OFF, // 680\n engineNetLpPosOff: V_ADL_ENGINE_NET_LP_POS_OFF, // 904\n engineLpSumAbsOff: V_ADL_ENGINE_LP_SUM_ABS_OFF, // 920\n engineLpMaxAbsOff: V_ADL_ENGINE_LP_MAX_ABS_OFF, // 936\n engineLpMaxAbsSweepOff: V_ADL_ENGINE_LP_MAX_ABS_SWEEP_OFF, // 952\n engineEmergencyOiModeOff: V_ADL_ENGINE_EMERGENCY_OI_MODE_OFF, // 968\n engineEmergencyStartSlotOff: V_ADL_ENGINE_EMERGENCY_START_SLOT_OFF, // 976\n engineLastBreakerSlotOff: V_ADL_ENGINE_LAST_BREAKER_SLOT_OFF, // 984\n engineBitmapOff: V_ADL_ENGINE_BITMAP_OFF, // 1008\n postBitmap: 18,\n acctOwnerOff: V_ADL_ACCT_OWNER_OFF, // 192\n\n hasInsuranceIsolation: true,\n engineInsuranceIsolatedOff: 48,\n engineInsuranceIsolationBpsOff: 64,\n };\n}\n\n/**\n * V_SETDEXPOOL slab tier sizes — PERC-SetDexPool security fix.\n * ENGINE_OFF=632, BITMAP_OFF=1008, ACCOUNT_SIZE=312, CONFIG_LEN=528.\n * e.g. large (4096 accts) = 1288336 bytes.\n */\nexport const SLAB_TIERS_V_SETDEXPOOL: Record<string, { maxAccounts: number; dataSize: number; label: string; description: string }> = {};\nfor (const [label, n] of [[\"Micro\", 64], [\"Small\", 256], [\"Medium\", 1024], [\"Large\", 4096]] as const) {\n const size = computeSlabSize(V_SETDEXPOOL_ENGINE_OFF, V_ADL_ENGINE_BITMAP_OFF, V_ADL_ACCOUNT_SIZE, n, 18);\n SLAB_TIERS_V_SETDEXPOOL[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (V_SETDEXPOOL PERC-SetDexPool)` };\n}\n\n/**\n * V12_1 slab tier sizes — percolator-core v12.1 merge.\n * ENGINE_OFF=648, BITMAP_OFF=1016, ACCOUNT_SIZE=320.\n * Verified by cargo build-sbf compile-time assertions.\n */\nexport const SLAB_TIERS_V12_1: Record<string, { maxAccounts: number; dataSize: number; label: string; description: string }> = {};\nfor (const [label, n] of [[\"Micro\", 64], [\"Small\", 256], [\"Medium\", 1024], [\"Large\", 4096]] as const) {\n const size = computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, n, 18);\n SLAB_TIERS_V12_1[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (v12.1)` };\n}\n\n/**\n * Build a SlabLayout for V_SETDEXPOOL slabs (PERC-SetDexPool security fix).\n * ENGINE_OFF=632 (+8 from V_ADL=624 due to CONFIG_LEN growing 520→528).\n * All engine and account field offsets are identical to V_ADL.\n */\nfunction buildLayoutVSetDexPool(maxAccounts: number): SlabLayout {\n const engineOff = V_SETDEXPOOL_ENGINE_OFF;\n const bitmapOff = V_ADL_ENGINE_BITMAP_OFF;\n const accountSize = V_ADL_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version: 1,\n headerLen: V1_HEADER_LEN,\n configOffset: V1_HEADER_LEN,\n configLen: V_SETDEXPOOL_CONFIG_LEN, // 544\n reservedOff: V1_RESERVED_OFF,\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: V_ADL_ENGINE_PARAMS_OFF,\n paramsSize: V_ADL_PARAMS_SIZE,\n engineCurrentSlotOff: V_ADL_ENGINE_CURRENT_SLOT_OFF,\n engineFundingIndexOff: V_ADL_ENGINE_FUNDING_INDEX_OFF,\n engineLastFundingSlotOff: V_ADL_ENGINE_LAST_FUNDING_SLOT_OFF,\n engineFundingRateBpsOff: V_ADL_ENGINE_FUNDING_RATE_BPS_OFF,\n engineMarkPriceOff: V_ADL_ENGINE_MARK_PRICE_OFF,\n engineLastCrankSlotOff: V_ADL_ENGINE_LAST_CRANK_SLOT_OFF,\n engineMaxCrankStalenessOff: V_ADL_ENGINE_MAX_CRANK_STALENESS_OFF,\n engineTotalOiOff: V_ADL_ENGINE_TOTAL_OI_OFF,\n engineLongOiOff: V_ADL_ENGINE_LONG_OI_OFF,\n engineShortOiOff: V_ADL_ENGINE_SHORT_OI_OFF,\n engineCTotOff: V_ADL_ENGINE_C_TOT_OFF,\n enginePnlPosTotOff: V_ADL_ENGINE_PNL_POS_TOT_OFF,\n engineLiqCursorOff: V_ADL_ENGINE_LIQ_CURSOR_OFF,\n engineGcCursorOff: V_ADL_ENGINE_GC_CURSOR_OFF,\n engineLastSweepStartOff: V_ADL_ENGINE_LAST_SWEEP_START_OFF,\n engineLastSweepCompleteOff: V_ADL_ENGINE_LAST_SWEEP_COMPLETE_OFF,\n engineCrankCursorOff: V_ADL_ENGINE_CRANK_CURSOR_OFF,\n engineSweepStartIdxOff: V_ADL_ENGINE_SWEEP_START_IDX_OFF,\n engineLifetimeLiquidationsOff: V_ADL_ENGINE_LIFETIME_LIQUIDATIONS_OFF,\n engineLifetimeForceClosesOff: V_ADL_ENGINE_LIFETIME_FORCE_CLOSES_OFF,\n engineNetLpPosOff: V_ADL_ENGINE_NET_LP_POS_OFF,\n engineLpSumAbsOff: V_ADL_ENGINE_LP_SUM_ABS_OFF,\n engineLpMaxAbsOff: V_ADL_ENGINE_LP_MAX_ABS_OFF,\n engineLpMaxAbsSweepOff: V_ADL_ENGINE_LP_MAX_ABS_SWEEP_OFF,\n engineEmergencyOiModeOff: V_ADL_ENGINE_EMERGENCY_OI_MODE_OFF,\n engineEmergencyStartSlotOff: V_ADL_ENGINE_EMERGENCY_START_SLOT_OFF,\n engineLastBreakerSlotOff: V_ADL_ENGINE_LAST_BREAKER_SLOT_OFF,\n engineBitmapOff: V_ADL_ENGINE_BITMAP_OFF,\n postBitmap: 18,\n acctOwnerOff: V_ADL_ACCT_OWNER_OFF,\n\n hasInsuranceIsolation: true,\n engineInsuranceIsolatedOff: 48,\n engineInsuranceIsolationBpsOff: 64,\n };\n}\n\nfunction buildLayoutV12_1(maxAccounts: number): SlabLayout {\n const engineOff = V12_1_ENGINE_OFF;\n const bitmapOff = V12_1_ENGINE_BITMAP_OFF;\n const accountSize = V12_1_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version: 1,\n headerLen: V1_HEADER_LEN,\n configOffset: V1_HEADER_LEN,\n configLen: V_SETDEXPOOL_CONFIG_LEN, // 544 (same as V_SETDEXPOOL)\n reservedOff: V1_RESERVED_OFF,\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: V12_1_ENGINE_PARAMS_OFF,\n paramsSize: V12_1_PARAMS_SIZE,\n engineCurrentSlotOff: V12_1_ENGINE_CURRENT_SLOT_OFF,\n engineFundingIndexOff: V12_1_ENGINE_FUNDING_INDEX_OFF,\n engineLastFundingSlotOff: V12_1_ENGINE_LAST_FUNDING_SLOT_OFF,\n engineFundingRateBpsOff: V12_1_ENGINE_FUNDING_RATE_BPS_OFF,\n engineMarkPriceOff: V12_1_ENGINE_MARK_PRICE_OFF,\n engineLastCrankSlotOff: V12_1_ENGINE_LAST_CRANK_SLOT_OFF,\n engineMaxCrankStalenessOff: V12_1_ENGINE_MAX_CRANK_STALENESS_OFF,\n engineTotalOiOff: V12_1_ENGINE_TOTAL_OI_OFF,\n engineLongOiOff: V12_1_ENGINE_LONG_OI_OFF,\n engineShortOiOff: V12_1_ENGINE_SHORT_OI_OFF,\n engineCTotOff: V12_1_ENGINE_C_TOT_OFF,\n enginePnlPosTotOff: V12_1_ENGINE_PNL_POS_TOT_OFF,\n engineLiqCursorOff: V12_1_ENGINE_LIQ_CURSOR_OFF,\n engineGcCursorOff: V12_1_ENGINE_GC_CURSOR_OFF,\n engineLastSweepStartOff: V12_1_ENGINE_LAST_SWEEP_START_OFF,\n engineLastSweepCompleteOff: V12_1_ENGINE_LAST_SWEEP_COMPLETE_OFF,\n engineCrankCursorOff: V12_1_ENGINE_CRANK_CURSOR_OFF,\n engineSweepStartIdxOff: V12_1_ENGINE_SWEEP_START_IDX_OFF,\n engineLifetimeLiquidationsOff: V12_1_ENGINE_LIFETIME_LIQUIDATIONS_OFF,\n engineLifetimeForceClosesOff: V12_1_ENGINE_LIFETIME_FORCE_CLOSES_OFF,\n engineNetLpPosOff: V12_1_ENGINE_NET_LP_POS_OFF,\n engineLpSumAbsOff: V12_1_ENGINE_LP_SUM_ABS_OFF,\n engineLpMaxAbsOff: V12_1_ENGINE_LP_MAX_ABS_OFF,\n engineLpMaxAbsSweepOff: V12_1_ENGINE_LP_MAX_ABS_SWEEP_OFF,\n engineEmergencyOiModeOff: V12_1_ENGINE_EMERGENCY_OI_MODE_OFF,\n engineEmergencyStartSlotOff: V12_1_ENGINE_EMERGENCY_START_SLOT_OFF,\n engineLastBreakerSlotOff: V12_1_ENGINE_LAST_BREAKER_SLOT_OFF,\n engineBitmapOff: V12_1_ENGINE_BITMAP_OFF,\n postBitmap: 18,\n acctOwnerOff: V12_1_ACCT_OWNER_OFF,\n\n hasInsuranceIsolation: true,\n engineInsuranceIsolatedOff: 48,\n engineInsuranceIsolationBpsOff: 64,\n };\n}\n\n/**\n * Detect the slab layout version from the raw account data length.\n * Returns the full SlabLayout descriptor, or null if the size is unrecognised.\n * Checks V12_1, V_SETDEXPOOL, V1M2, V_ADL, V1M, V0, V1D, V1D-legacy, V1, and V1-legacy sizes.\n *\n * When `data` is provided and the size matches V1D, the version field at offset 8 is read\n * to disambiguate V2 slabs (which produce identical sizes to V1D with postBitmap=2).\n * V2 slabs have version===2 at offset 8 (u32 LE).\n *\n * @param dataLen - The slab account data length in bytes\n * @param data - Optional raw slab data for version-field disambiguation\n */\nexport function detectSlabLayout(dataLen: number, data?: Uint8Array): SlabLayout | null {\n // Check V12_1 sizes first (percolator-core v12.1, ACCOUNT_SIZE=320, BITMAP_OFF=1016).\n // Largest account size — no size collision with any earlier layout.\n const v121n = V12_1_SIZES.get(dataLen);\n if (v121n !== undefined) return buildLayoutV12_1(v121n);\n\n // Check V_SETDEXPOOL sizes (PERC-SetDexPool, ENGINE_OFF=648, CONFIG_LEN=544).\n // These are the pre-v12.1 newest slabs — largest ENGINE_OFF so no size collision with V_ADL (624).\n const vsdpn = V_SETDEXPOOL_SIZES.get(dataLen);\n if (vsdpn !== undefined) return buildLayoutVSetDexPool(vsdpn);\n\n // Check V1M2 sizes. After fixing bitmapOff to 1008 for both V1M2 and V_ADL,\n // their sizes no longer collide (engineOff differs: 616 vs 624), so size-based detection\n // works directly — no data-probe disambiguation required.\n // V1M2 medium (1024 accts): computeSlabSize(616, 1008, 312, 1024, 18) = 323312\n // V_ADL medium (1024 accts): computeSlabSize(624, 1008, 312, 1024, 18) = 323320\n const v1m2n = V1M2_SIZES.get(dataLen);\n if (v1m2n !== undefined) return buildLayoutV1M2(v1m2n);\n\n // Check V_ADL sizes (PERC-8270/8271, ENGINE_OFF=624, BITMAP_OFF=1008, ACCOUNT_SIZE=312).\n const vadln = V_ADL_SIZES.get(dataLen);\n if (vadln !== undefined) return buildLayoutVADL(vadln);\n\n // Check V1M sizes (mainnet-deployed V1 program, ESa89R5).\n // Must be checked before V1_LEGACY because V1M sizes are unique and don't overlap.\n const v1mn = V1M_SIZES.get(dataLen);\n if (v1mn !== undefined) return buildLayoutV1M(v1mn);\n\n // Check V0 sizes (deployed devnet V0 program)\n const v0n = V0_SIZES.get(dataLen);\n if (v0n !== undefined) return buildLayout(0, v0n);\n\n // Check V1D sizes (actually deployed V1 program — ENGINE_OFF=424, correct struct layout).\n // V2 slabs produce identical sizes (postBitmap=18 for V2 == postBitmap=2 for V1D).\n // When data is available, peek at the version field to disambiguate.\n const v1dn = V1D_SIZES.get(dataLen);\n if (v1dn !== undefined) {\n if (data && data.length >= 12) {\n const version = readU32LE(data, 8);\n if (version === 2) return buildLayoutV2(v1dn);\n }\n return buildLayoutV1D(v1dn, 2);\n }\n\n // Check V1D legacy sizes (postBitmap=18 on-chain slabs created before GH#1234 fix).\n // e.g. slab 6ZytbpV4 (TEST/USD, top active market) = 65104 bytes, uses postBitmap=18.\n // PR #1236 broke these by only registering the postBitmap=2 size; GH#1237 restores support.\n const v1dln = V1D_SIZES_LEGACY.get(dataLen);\n if (v1dln !== undefined) return buildLayoutV1D(v1dln, 18);\n\n // Check V1 sizes (future V1 program — ENGINE_OFF=600, PERC-1094 corrected)\n const v1n = V1_SIZES.get(dataLen);\n if (v1n !== undefined) return buildLayout(1, v1n);\n\n // Check legacy V1 sizes (pre-PERC-1094 SDK used ENGINE_OFF=640; orphaned on devnet)\n const v1ln = V1_SIZES_LEGACY.get(dataLen);\n // PERC-1095 follow-up: must pass V1_ENGINE_OFF_LEGACY (640) so the returned SlabLayout\n // has .engineOff=640 — without the override buildLayout would use V1_ENGINE_OFF=600,\n // causing all engine reads on legacy slabs to land at the wrong byte offset.\n if (v1ln !== undefined) return buildLayout(1, v1ln, V1_ENGINE_OFF_LEGACY);\n\n return null;\n}\n\n/**\n * Legacy detectLayout for backward compat.\n * Returns { bitmapWords, accountsOff, maxAccounts } or null.\n *\n * GH#1238: previously recomputed accountsOff with hardcoded postBitmap=18, which gave a value\n * 16 bytes too large for V1D slabs (which use postBitmap=2). Now delegates directly to the\n * SlabLayout descriptor so each variant uses its own correct accountsOff.\n */\nexport function detectLayout(dataLen: number) {\n const layout = detectSlabLayout(dataLen);\n if (!layout) return null;\n return { bitmapWords: layout.bitmapWords, accountsOff: layout.accountsOff, maxAccounts: layout.maxAccounts };\n}\n\n// =============================================================================\n// RiskParams Layout (field offsets within params, same for V0 and V1 basic fields)\n// =============================================================================\nconst PARAMS_WARMUP_PERIOD_OFF = 0;\nconst PARAMS_MAINTENANCE_MARGIN_OFF = 8;\nconst PARAMS_INITIAL_MARGIN_OFF = 16;\nconst PARAMS_TRADING_FEE_OFF = 24;\nconst PARAMS_MAX_ACCOUNTS_OFF = 32;\nconst PARAMS_NEW_ACCOUNT_FEE_OFF = 40;\n// V1-only extended params (offset 56+)\nconst PARAMS_RISK_THRESHOLD_OFF = 56;\nconst PARAMS_MAINTENANCE_FEE_OFF = 72;\nconst PARAMS_MAX_CRANK_STALENESS_OFF = 88;\nconst PARAMS_LIQUIDATION_FEE_BPS_OFF = 96;\nconst PARAMS_LIQUIDATION_FEE_CAP_OFF = 104;\nconst PARAMS_LIQUIDATION_BUFFER_OFF = 120;\nconst PARAMS_MIN_LIQUIDATION_OFF = 128;\n\n// =============================================================================\n// Account Layout (240/248 bytes)\n// The first 240 bytes are identical in V0 and V1.\n// V1 adds last_partial_liquidation_slot (u64, 8 bytes) at offset 240.\n// =============================================================================\nconst ACCT_ACCOUNT_ID_OFF = 0;\nconst ACCT_CAPITAL_OFF = 8;\nconst ACCT_KIND_OFF = 24;\nconst ACCT_PNL_OFF = 32;\nconst ACCT_RESERVED_PNL_OFF = 48;\nconst ACCT_WARMUP_STARTED_OFF = 56;\nconst ACCT_WARMUP_SLOPE_OFF = 64;\nconst ACCT_POSITION_SIZE_OFF = 80;\nconst ACCT_ENTRY_PRICE_OFF = 96;\nconst ACCT_FUNDING_INDEX_OFF = 104;\nconst ACCT_MATCHER_PROGRAM_OFF = 120;\nconst ACCT_MATCHER_CONTEXT_OFF = 152;\nconst ACCT_OWNER_OFF = 184;\nconst ACCT_FEE_CREDITS_OFF = 216;\nconst ACCT_LAST_FEE_SLOT_OFF = 232;\n\n// =============================================================================\n// Interfaces\n// =============================================================================\n\nexport interface SlabHeader {\n magic: bigint;\n version: number;\n bump: number;\n flags: number;\n resolved: boolean;\n paused: boolean;\n admin: PublicKey;\n nonce: bigint;\n lastThrUpdateSlot: bigint;\n}\n\nexport interface MarketConfig {\n collateralMint: PublicKey;\n vaultPubkey: PublicKey;\n indexFeedId: PublicKey;\n maxStalenessSlots: bigint;\n confFilterBps: number;\n vaultAuthorityBump: number;\n invert: number;\n unitScale: number;\n fundingHorizonSlots: bigint;\n fundingKBps: bigint;\n fundingInvScaleNotionalE6: bigint;\n fundingMaxPremiumBps: bigint;\n fundingMaxBpsPerSlot: bigint;\n fundingPremiumWeightBps: bigint;\n fundingSettlementIntervalSlots: bigint;\n fundingPremiumDampeningE6: bigint;\n fundingPremiumMaxBpsPerSlot: bigint;\n threshFloor: bigint;\n threshRiskBps: bigint;\n threshUpdateIntervalSlots: bigint;\n threshStepBps: bigint;\n threshAlphaBps: bigint;\n threshMin: bigint;\n threshMax: bigint;\n threshMinStep: bigint;\n oracleAuthority: PublicKey;\n authorityPriceE6: bigint;\n authorityTimestamp: bigint;\n oraclePriceCapE2bps: bigint;\n lastEffectivePriceE6: bigint;\n oiCapMultiplierBps: bigint;\n maxPnlCap: bigint;\n adaptiveFundingEnabled: boolean;\n adaptiveScaleBps: number;\n adaptiveMaxFundingBps: bigint;\n marketCreatedSlot: bigint;\n oiRampSlots: bigint;\n resolvedSlot: bigint;\n insuranceIsolationBps: number;\n /** PERC-622: Oracle phase (0=Nascent, 1=Growing, 2=Mature) */\n oraclePhase: number;\n /** PERC-622: Cumulative trade volume in e6 format */\n cumulativeVolumeE6: bigint;\n /** PERC-622: Slots elapsed from market creation to Phase 2 entry (u24) */\n phase2DeltaSlots: number;\n /**\n * PERC-SetDexPool: Admin-pinned DEX pool pubkey for HYPERP markets.\n * Null when reading old slabs (pre-SetDexPool configLen < 528) or when\n * SetDexPool has never been called (all-zero pubkey).\n * Non-null means the program will reject any UpdateHyperpMark that passes\n * a different pool account.\n */\n dexPool: PublicKey | null;\n}\n\nexport interface InsuranceFund {\n balance: bigint;\n feeRevenue: bigint;\n isolatedBalance: bigint;\n isolationBps: number;\n}\n\nexport interface RiskParams {\n warmupPeriodSlots: bigint;\n maintenanceMarginBps: bigint;\n initialMarginBps: bigint;\n tradingFeeBps: bigint;\n maxAccounts: bigint;\n newAccountFee: bigint;\n riskReductionThreshold: bigint;\n maintenanceFeePerSlot: bigint;\n maxCrankStalenessSlots: bigint;\n liquidationFeeBps: bigint;\n liquidationFeeCap: bigint;\n liquidationBufferBps: bigint;\n minLiquidationAbs: bigint;\n}\n\nexport interface EngineState {\n vault: bigint;\n insuranceFund: InsuranceFund;\n currentSlot: bigint;\n fundingIndexQpbE6: bigint;\n lastFundingSlot: bigint;\n fundingRateBpsPerSlotLast: bigint;\n lastCrankSlot: bigint;\n maxCrankStalenessSlots: bigint;\n totalOpenInterest: bigint;\n longOi: bigint;\n shortOi: bigint;\n cTot: bigint;\n pnlPosTot: bigint;\n liqCursor: number;\n gcCursor: number;\n lastSweepStartSlot: bigint;\n lastSweepCompleteSlot: bigint;\n crankCursor: number;\n sweepStartIdx: number;\n lifetimeLiquidations: bigint;\n lifetimeForceCloses: bigint;\n netLpPos: bigint;\n lpSumAbs: bigint;\n lpMaxAbs: bigint;\n lpMaxAbsSweep: bigint;\n emergencyOiMode: boolean;\n emergencyStartSlot: bigint;\n lastBreakerSlot: bigint;\n numUsedAccounts: number;\n nextAccountId: bigint;\n markPriceE6: bigint;\n}\n\nexport enum AccountKind {\n User = 0,\n LP = 1,\n}\n\nexport interface Account {\n kind: AccountKind;\n accountId: bigint;\n capital: bigint;\n pnl: bigint;\n reservedPnl: bigint;\n warmupStartedAtSlot: bigint;\n warmupSlopePerStep: bigint;\n positionSize: bigint;\n entryPrice: bigint;\n fundingIndex: bigint;\n matcherProgram: PublicKey;\n matcherContext: PublicKey;\n owner: PublicKey;\n feeCredits: bigint;\n lastFeeSlot: bigint;\n}\n\n// =============================================================================\n// Fetch\n// =============================================================================\n\nexport async function fetchSlab(\n connection: Connection,\n slabPubkey: PublicKey\n): Promise<Uint8Array> {\n const info = await connection.getAccountInfo(slabPubkey);\n if (!info) {\n throw new Error(`Slab account not found: ${slabPubkey.toBase58()}`);\n }\n return new Uint8Array(info.data);\n}\n\n// =============================================================================\n// PERC-302: Market Maturity OI Ramp\n// =============================================================================\n\nexport const RAMP_START_BPS = 1000n;\nexport const DEFAULT_OI_RAMP_SLOTS = 432_000n;\n\nexport function computeEffectiveOiCapBps(config: MarketConfig, currentSlot: bigint): bigint {\n const target = config.oiCapMultiplierBps;\n if (target === 0n) return 0n;\n if (config.oiRampSlots === 0n) return target;\n if (target <= RAMP_START_BPS) return target;\n const elapsed = currentSlot > config.marketCreatedSlot\n ? currentSlot - config.marketCreatedSlot\n : 0n;\n if (elapsed >= config.oiRampSlots) return target;\n const range = target - RAMP_START_BPS;\n const rampAdd = (range * elapsed) / config.oiRampSlots;\n const result = RAMP_START_BPS + rampAdd;\n return result < target ? result : target;\n}\n\n// =============================================================================\n// Header helpers\n// =============================================================================\n\nexport function readNonce(data: Uint8Array): bigint {\n const layout = detectSlabLayout(data.length, data);\n if (!layout) {\n throw new Error(`readNonce: unrecognized slab data length ${data.length}`);\n }\n const roff = layout.reservedOff;\n if (data.length < roff + 8) throw new Error(\"Slab data too short for nonce\");\n return readU64LE(data, roff);\n}\n\nexport function readLastThrUpdateSlot(data: Uint8Array): bigint {\n const layout = detectSlabLayout(data.length, data);\n if (!layout) {\n throw new Error(`readLastThrUpdateSlot: unrecognized slab data length ${data.length}`);\n }\n const roff = layout.reservedOff;\n if (data.length < roff + 16) throw new Error(\"Slab data too short for lastThrUpdateSlot\");\n return readU64LE(data, roff + 8);\n}\n\n// =============================================================================\n// Parsing Functions\n// =============================================================================\n\n/**\n * Parse slab header (first 72 bytes — layout-independent).\n */\nexport function parseHeader(data: Uint8Array): SlabHeader {\n if (data.length < V0_HEADER_LEN) {\n throw new Error(`Slab data too short for header: ${data.length} < ${V0_HEADER_LEN}`);\n }\n\n const magic = readU64LE(data, 0);\n if (magic !== MAGIC) {\n throw new Error(`Invalid slab magic: expected ${MAGIC.toString(16)}, got ${magic.toString(16)}`);\n }\n\n const version = readU32LE(data, 8);\n const bump = readU8(data, 12);\n const flags = readU8(data, 13);\n const admin = new PublicKey(data.subarray(16, 48));\n\n // Reserved field location depends on layout\n const layout = detectSlabLayout(data.length, data);\n const roff = layout ? layout.reservedOff : V0_RESERVED_OFF;\n const nonce = readU64LE(data, roff);\n const lastThrUpdateSlot = readU64LE(data, roff + 8);\n\n return {\n magic,\n version,\n bump,\n flags,\n resolved: (flags & FLAG_RESOLVED) !== 0,\n paused: (flags & 0x02) !== 0,\n admin,\n nonce,\n lastThrUpdateSlot,\n };\n}\n\n/**\n * Parse market config. Layout-version aware.\n * For V0 slabs, fields beyond the basic config are read if present in the data,\n * otherwise defaults are returned.\n *\n * @param data - Slab data (may be a partial slice for discovery; pass layoutHint in that case)\n * @param layoutHint - Pre-detected layout to use; if omitted, detected from data.length.\n */\nexport function parseConfig(data: Uint8Array, layoutHint?: SlabLayout | null): MarketConfig {\n const layout = layoutHint !== undefined ? layoutHint : detectSlabLayout(data.length, data);\n const configOff = layout ? layout.configOffset : V0_HEADER_LEN;\n const configLen = layout ? layout.configLen : V0_CONFIG_LEN;\n\n const minLen = configOff + Math.min(configLen, 120); // need at least basic fields\n if (data.length < minLen) {\n throw new Error(`Slab data too short for config: ${data.length} < ${minLen}`);\n }\n\n let off = configOff;\n\n const collateralMint = new PublicKey(data.subarray(off, off + 32));\n off += 32;\n\n const vaultPubkey = new PublicKey(data.subarray(off, off + 32));\n off += 32;\n\n const indexFeedId = new PublicKey(data.subarray(off, off + 32));\n off += 32;\n\n const maxStalenessSlots = readU64LE(data, off);\n off += 8;\n\n const confFilterBps = readU16LE(data, off);\n off += 2;\n\n const vaultAuthorityBump = readU8(data, off);\n off += 1;\n\n const invert = readU8(data, off);\n off += 1;\n\n const unitScale = readU32LE(data, off);\n off += 4;\n\n // Funding rate parameters\n const fundingHorizonSlots = readU64LE(data, off);\n off += 8;\n\n const fundingKBps = readU64LE(data, off);\n off += 8;\n\n const fundingInvScaleNotionalE6 = readU128LE(data, off);\n off += 16;\n\n const fundingMaxPremiumBps = readI64LE(data, off);\n off += 8;\n\n const fundingMaxBpsPerSlot = readI64LE(data, off);\n off += 8;\n\n // Extended funding fields\n const fundingPremiumWeightBps = readU64LE(data, off);\n off += 8;\n\n const fundingSettlementIntervalSlots = readU64LE(data, off);\n off += 8;\n\n const fundingPremiumDampeningE6 = readU64LE(data, off);\n off += 8;\n\n const fundingPremiumMaxBpsPerSlot = readU64LE(data, off);\n off += 8;\n\n // Threshold parameters\n const threshFloor = readU128LE(data, off);\n off += 16;\n\n const threshRiskBps = readU64LE(data, off);\n off += 8;\n\n const threshUpdateIntervalSlots = readU64LE(data, off);\n off += 8;\n\n const threshStepBps = readU64LE(data, off);\n off += 8;\n\n const threshAlphaBps = readU64LE(data, off);\n off += 8;\n\n const threshMin = readU128LE(data, off);\n off += 16;\n\n const threshMax = readU128LE(data, off);\n off += 16;\n\n const threshMinStep = readU128LE(data, off);\n off += 16;\n\n // Oracle authority fields\n const oracleAuthority = new PublicKey(data.subarray(off, off + 32));\n off += 32;\n\n const authorityPriceE6 = readU64LE(data, off);\n off += 8;\n\n const authorityTimestamp = readI64LE(data, off);\n off += 8;\n\n // Oracle price circuit breaker\n const oraclePriceCapE2bps = readU64LE(data, off);\n off += 8;\n\n const lastEffectivePriceE6 = readU64LE(data, off);\n off += 8;\n\n // OI cap\n const oiCapMultiplierBps = readU64LE(data, off);\n off += 8;\n\n const maxPnlCap = readU64LE(data, off);\n off += 8;\n\n // Check if we have enough data for V1-only fields\n const remaining = configOff + configLen - off;\n\n let adaptiveFundingEnabled = false;\n let adaptiveScaleBps = 0;\n let adaptiveMaxFundingBps = 0n;\n let marketCreatedSlot = 0n;\n let oiRampSlots = 0n;\n let resolvedSlot = 0n;\n let insuranceIsolationBps = 0;\n let oraclePhase = 0;\n let cumulativeVolumeE6 = 0n;\n let phase2DeltaSlots = 0;\n\n if (remaining >= 40) {\n // V1 extended fields — on-chain order (percolator.rs:3617-3639):\n // market_created_slot(u64), oi_ramp_slots(u64),\n // adaptive_funding_enabled(u8), _pad(u8), adaptive_scale_bps(u16),\n // _pad2(u32), adaptive_max_funding_bps(u64),\n // insurance_isolation_bps(u16), _insurance_isolation_padding([u8;14])\n marketCreatedSlot = readU64LE(data, off);\n off += 8;\n\n oiRampSlots = readU64LE(data, off);\n off += 8;\n\n adaptiveFundingEnabled = readU8(data, off) !== 0;\n off += 1;\n off += 1; // _adaptive_pad\n adaptiveScaleBps = readU16LE(data, off);\n off += 2;\n off += 4; // _adaptive_pad2\n adaptiveMaxFundingBps = readU64LE(data, off);\n off += 8;\n\n if (remaining >= 42) {\n insuranceIsolationBps = readU16LE(data, off);\n // PERC-622: Read oracle phase fields from _insurance_isolation_padding\n // padding starts at off + 2 (after u16 insuranceIsolationBps)\n // [0..2] = mark_oracle_weight (PERC-118), [2] = oracle_phase, [3..11] = cumulative_volume, [11..14] = phase2_delta\n if (remaining >= 56) { // 42 + 14 bytes padding\n const padOff = off + 2;\n oraclePhase = Math.min(readU8(data, padOff + 2), 2);\n cumulativeVolumeE6 = readU64LE(data, padOff + 3);\n // phase2_delta_slots is u24 LE (3 bytes)\n phase2DeltaSlots = data[padOff + 11] | (data[padOff + 12] << 8) | (data[padOff + 13] << 16);\n }\n }\n }\n\n // PERC-SetDexPool: read dex_pool at BPF offset 496 within config.\n // Only present in V_SETDEXPOOL slabs (configLen >= 528).\n // All-zero pubkey means SetDexPool was never called.\n let dexPool: PublicKey | null = null;\n const DEX_POOL_REL_OFF = 512; // SBF offset of dex_pool within MarketConfig (CONFIG_LEN=544, dex_pool at end = 544-32=512)\n if (configLen >= DEX_POOL_REL_OFF + 32 && data.length >= configOff + DEX_POOL_REL_OFF + 32) {\n const dexPoolBytes = data.subarray(configOff + DEX_POOL_REL_OFF, configOff + DEX_POOL_REL_OFF + 32);\n // Return null if all-zero (SetDexPool never called)\n if (dexPoolBytes.some(b => b !== 0)) {\n dexPool = new PublicKey(dexPoolBytes);\n }\n }\n\n return {\n collateralMint,\n vaultPubkey,\n indexFeedId,\n maxStalenessSlots,\n confFilterBps,\n vaultAuthorityBump,\n invert,\n unitScale,\n fundingHorizonSlots,\n fundingKBps,\n fundingInvScaleNotionalE6,\n fundingMaxPremiumBps,\n fundingMaxBpsPerSlot,\n fundingPremiumWeightBps,\n fundingSettlementIntervalSlots,\n fundingPremiumDampeningE6,\n fundingPremiumMaxBpsPerSlot,\n threshFloor,\n threshRiskBps,\n threshUpdateIntervalSlots,\n threshStepBps,\n threshAlphaBps,\n threshMin,\n threshMax,\n threshMinStep,\n oracleAuthority,\n authorityPriceE6,\n authorityTimestamp,\n oraclePriceCapE2bps,\n lastEffectivePriceE6,\n oiCapMultiplierBps,\n maxPnlCap,\n adaptiveFundingEnabled,\n adaptiveScaleBps,\n adaptiveMaxFundingBps,\n marketCreatedSlot,\n oiRampSlots,\n resolvedSlot,\n insuranceIsolationBps,\n oraclePhase,\n cumulativeVolumeE6,\n phase2DeltaSlots,\n dexPool,\n };\n}\n\n/**\n * Parse RiskParams from engine data. Layout-version aware.\n * For V0 slabs, extended params (risk_threshold, maintenance_fee, etc.) are\n * not present on-chain, so defaults (0) are returned.\n *\n * @param data - Slab data (may be a partial slice; pass layoutHint in that case)\n * @param layoutHint - Pre-detected layout to use; if omitted, detected from data.length.\n */\nexport function parseParams(data: Uint8Array, layoutHint?: SlabLayout | null): RiskParams {\n const layout = layoutHint !== undefined ? layoutHint : detectSlabLayout(data.length, data);\n const engineOff = layout ? layout.engineOff : V0_ENGINE_OFF;\n const paramsOff = layout ? layout.engineParamsOff : V0_ENGINE_PARAMS_OFF;\n const paramsSize = layout ? layout.paramsSize : V0_PARAMS_SIZE;\n const base = engineOff + paramsOff;\n\n if (data.length < base + Math.min(paramsSize, 56)) {\n throw new Error(\"Slab data too short for RiskParams\");\n }\n\n // Basic params present in both V0 and V1\n const result: RiskParams = {\n warmupPeriodSlots: readU64LE(data, base + PARAMS_WARMUP_PERIOD_OFF),\n maintenanceMarginBps: readU64LE(data, base + PARAMS_MAINTENANCE_MARGIN_OFF),\n initialMarginBps: readU64LE(data, base + PARAMS_INITIAL_MARGIN_OFF),\n tradingFeeBps: readU64LE(data, base + PARAMS_TRADING_FEE_OFF),\n maxAccounts: readU64LE(data, base + PARAMS_MAX_ACCOUNTS_OFF),\n newAccountFee: readU128LE(data, base + PARAMS_NEW_ACCOUNT_FEE_OFF),\n // Extended params: only read if V1 (paramsSize >= 144)\n riskReductionThreshold: 0n,\n maintenanceFeePerSlot: 0n,\n maxCrankStalenessSlots: 0n,\n liquidationFeeBps: 0n,\n liquidationFeeCap: 0n,\n liquidationBufferBps: 0n,\n minLiquidationAbs: 0n,\n };\n\n if (paramsSize >= 144) {\n result.riskReductionThreshold = readU128LE(data, base + PARAMS_RISK_THRESHOLD_OFF);\n result.maintenanceFeePerSlot = readU128LE(data, base + PARAMS_MAINTENANCE_FEE_OFF);\n result.maxCrankStalenessSlots = readU64LE(data, base + PARAMS_MAX_CRANK_STALENESS_OFF);\n result.liquidationFeeBps = readU64LE(data, base + PARAMS_LIQUIDATION_FEE_BPS_OFF);\n result.liquidationFeeCap = readU128LE(data, base + PARAMS_LIQUIDATION_FEE_CAP_OFF);\n result.liquidationBufferBps = readU64LE(data, base + PARAMS_LIQUIDATION_BUFFER_OFF);\n result.minLiquidationAbs = readU128LE(data, base + PARAMS_MIN_LIQUIDATION_OFF);\n }\n\n return result;\n}\n\n/**\n * Parse RiskEngine state (excluding accounts array). Layout-version aware.\n */\nexport function parseEngine(data: Uint8Array): EngineState {\n const layout = detectSlabLayout(data.length, data);\n if (!layout) {\n throw new Error(`Unrecognized slab data length: ${data.length}. Cannot determine layout version.`);\n }\n\n const base = layout.engineOff;\n\n return {\n vault: readU128LE(data, base),\n insuranceFund: {\n balance: readU128LE(data, base + layout.engineInsuranceOff),\n feeRevenue: readU128LE(data, base + layout.engineInsuranceOff + 16),\n isolatedBalance: layout.hasInsuranceIsolation\n ? readU128LE(data, base + layout.engineInsuranceIsolatedOff)\n : 0n,\n isolationBps: layout.hasInsuranceIsolation\n ? readU16LE(data, base + layout.engineInsuranceIsolationBpsOff)\n : 0,\n },\n currentSlot: readU64LE(data, base + layout.engineCurrentSlotOff),\n fundingIndexQpbE6: readI128LE(data, base + layout.engineFundingIndexOff),\n lastFundingSlot: readU64LE(data, base + layout.engineLastFundingSlotOff),\n fundingRateBpsPerSlotLast: readI64LE(data, base + layout.engineFundingRateBpsOff),\n lastCrankSlot: readU64LE(data, base + layout.engineLastCrankSlotOff),\n maxCrankStalenessSlots: readU64LE(data, base + layout.engineMaxCrankStalenessOff),\n totalOpenInterest: readU128LE(data, base + layout.engineTotalOiOff),\n longOi: layout.engineLongOiOff >= 0\n ? readU128LE(data, base + layout.engineLongOiOff)\n : 0n,\n shortOi: layout.engineShortOiOff >= 0\n ? readU128LE(data, base + layout.engineShortOiOff)\n : 0n,\n cTot: readU128LE(data, base + layout.engineCTotOff),\n pnlPosTot: readU128LE(data, base + layout.enginePnlPosTotOff),\n liqCursor: readU16LE(data, base + layout.engineLiqCursorOff),\n gcCursor: readU16LE(data, base + layout.engineGcCursorOff),\n lastSweepStartSlot: readU64LE(data, base + layout.engineLastSweepStartOff),\n lastSweepCompleteSlot: readU64LE(data, base + layout.engineLastSweepCompleteOff),\n crankCursor: readU16LE(data, base + layout.engineCrankCursorOff),\n sweepStartIdx: readU16LE(data, base + layout.engineSweepStartIdxOff),\n lifetimeLiquidations: readU64LE(data, base + layout.engineLifetimeLiquidationsOff),\n lifetimeForceCloses: readU64LE(data, base + layout.engineLifetimeForceClosesOff),\n netLpPos: readI128LE(data, base + layout.engineNetLpPosOff),\n lpSumAbs: readU128LE(data, base + layout.engineLpSumAbsOff),\n lpMaxAbs: layout.engineLpMaxAbsOff >= 0 ? readU128LE(data, base + layout.engineLpMaxAbsOff) : 0n,\n lpMaxAbsSweep: layout.engineLpMaxAbsSweepOff >= 0 ? readU128LE(data, base + layout.engineLpMaxAbsSweepOff) : 0n,\n emergencyOiMode: layout.engineEmergencyOiModeOff >= 0\n ? data[base + layout.engineEmergencyOiModeOff] !== 0\n : false,\n emergencyStartSlot: layout.engineEmergencyStartSlotOff >= 0\n ? readU64LE(data, base + layout.engineEmergencyStartSlotOff)\n : 0n,\n lastBreakerSlot: layout.engineLastBreakerSlotOff >= 0\n ? readU64LE(data, base + layout.engineLastBreakerSlotOff)\n : 0n,\n markPriceE6: layout.engineMarkPriceOff >= 0\n ? readU64LE(data, base + layout.engineMarkPriceOff)\n : 0n,\n numUsedAccounts: (() => {\n if (layout.postBitmap < 18) return 0;\n const bw = layout.bitmapWords;\n return readU16LE(data, base + layout.engineBitmapOff + bw * 8);\n })(),\n nextAccountId: (() => {\n if (layout.postBitmap < 18) return 0n;\n const bw = layout.bitmapWords;\n const numUsedOff = layout.engineBitmapOff + bw * 8;\n return readU64LE(data, base + Math.ceil((numUsedOff + 2) / 8) * 8);\n })(),\n };\n}\n\n/**\n * Read bitmap to get list of used account indices.\n */\n/**\n * Return all account indices whose bitmap bit is set (i.e. slot is in use).\n * Uses the layout-aware bitmap offset so V1_LEGACY slabs (bitmap at rel+672) are handled correctly.\n */\nexport function parseUsedIndices(data: Uint8Array): number[] {\n const layout = detectSlabLayout(data.length, data);\n if (!layout) throw new Error(`Unrecognized slab data length: ${data.length}`);\n\n const base = layout.engineOff + layout.engineBitmapOff;\n if (data.length < base + layout.bitmapWords * 8) {\n throw new Error(\"Slab data too short for bitmap\");\n }\n\n const used: number[] = [];\n for (let word = 0; word < layout.bitmapWords; word++) {\n const bits = readU64LE(data, base + word * 8);\n if (bits === 0n) continue;\n for (let bit = 0; bit < 64; bit++) {\n if ((bits >> BigInt(bit)) & 1n) {\n used.push(word * 64 + bit);\n }\n }\n }\n return used;\n}\n\n/**\n * Check if a specific account index is used.\n */\nexport function isAccountUsed(data: Uint8Array, idx: number): boolean {\n const layout = detectSlabLayout(data.length, data);\n if (!layout) return false;\n if (!Number.isInteger(idx) || idx < 0 || idx >= layout.maxAccounts) return false;\n const base = layout.engineOff + layout.engineBitmapOff;\n const word = Math.floor(idx / 64);\n const bit = idx % 64;\n const bits = readU64LE(data, base + word * 8);\n return ((bits >> BigInt(bit)) & 1n) !== 0n;\n}\n\n/**\n * Calculate the maximum valid account index for a given slab size.\n */\nexport function maxAccountIndex(dataLen: number): number {\n const layout = detectSlabLayout(dataLen);\n if (!layout) return 0;\n const accountsEnd = dataLen - layout.accountsOff;\n if (accountsEnd <= 0) return 0;\n return Math.floor(accountsEnd / layout.accountSize);\n}\n\n/**\n * Parse a single account by index.\n */\nexport function parseAccount(data: Uint8Array, idx: number): Account {\n const layout = detectSlabLayout(data.length, data);\n if (!layout) throw new Error(`Unrecognized slab data length: ${data.length}`);\n\n const maxIdx = maxAccountIndex(data.length);\n if (!Number.isInteger(idx) || idx < 0 || idx >= maxIdx) {\n throw new Error(`Account index out of range: ${idx} (max: ${maxIdx - 1})`);\n }\n\n const base = layout.accountsOff + idx * layout.accountSize;\n if (data.length < base + layout.accountSize) {\n throw new Error(\"Slab data too short for account\");\n }\n\n // Select layout-dependent account field offsets.\n // V12_1 (account_size=320): new fields (position_basis_q, adl_a_basis, adl_k_snap, adl_epoch_snap)\n // shift matcher/owner/fee offsets +16 from V_ADL, and move legacy fields to end.\n // V_ADL (account_size=312): reserved_pnl grew u64→u128 (PERC-8267), shifting from pre-ADL offsets.\n // Pre-ADL (account_size<312): original offsets.\n const isV12_1 = layout.accountSize >= 320;\n const isAdl = layout.accountSize >= 312;\n const warmupStartedOff = isAdl ? V_ADL_ACCT_WARMUP_STARTED_OFF : ACCT_WARMUP_STARTED_OFF;\n const warmupSlopeOff = isAdl ? V_ADL_ACCT_WARMUP_SLOPE_OFF : ACCT_WARMUP_SLOPE_OFF;\n const positionSizeOff = isV12_1 ? V12_1_ACCT_POSITION_SIZE_OFF : (isAdl ? V_ADL_ACCT_POSITION_SIZE_OFF : ACCT_POSITION_SIZE_OFF);\n const entryPriceOff = isV12_1 ? V12_1_ACCT_ENTRY_PRICE_OFF : (isAdl ? V_ADL_ACCT_ENTRY_PRICE_OFF : ACCT_ENTRY_PRICE_OFF);\n const fundingIndexOff = isV12_1 ? V12_1_ACCT_FUNDING_INDEX_OFF : (isAdl ? V_ADL_ACCT_FUNDING_INDEX_OFF : ACCT_FUNDING_INDEX_OFF);\n const matcherProgOff = isV12_1 ? V12_1_ACCT_MATCHER_PROGRAM_OFF : (isAdl ? V_ADL_ACCT_MATCHER_PROGRAM_OFF : ACCT_MATCHER_PROGRAM_OFF);\n const matcherCtxOff = isV12_1 ? V12_1_ACCT_MATCHER_CONTEXT_OFF : (isAdl ? V_ADL_ACCT_MATCHER_CONTEXT_OFF : ACCT_MATCHER_CONTEXT_OFF);\n const feeCreditsOff = isV12_1 ? V12_1_ACCT_FEE_CREDITS_OFF : (isAdl ? V_ADL_ACCT_FEE_CREDITS_OFF : ACCT_FEE_CREDITS_OFF);\n const lastFeeSlotOff = isV12_1 ? V12_1_ACCT_LAST_FEE_SLOT_OFF : (isAdl ? V_ADL_ACCT_LAST_FEE_SLOT_OFF : ACCT_LAST_FEE_SLOT_OFF);\n\n const kindByte = readU8(data, base + ACCT_KIND_OFF);\n const kind = kindByte === 1 ? AccountKind.LP : AccountKind.User;\n\n return {\n kind,\n accountId: readU64LE(data, base + ACCT_ACCOUNT_ID_OFF),\n capital: readU128LE(data, base + ACCT_CAPITAL_OFF),\n pnl: readI128LE(data, base + ACCT_PNL_OFF),\n reservedPnl: isAdl ? readU128LE(data, base + ACCT_RESERVED_PNL_OFF) : readU64LE(data, base + ACCT_RESERVED_PNL_OFF),\n warmupStartedAtSlot: readU64LE(data, base + warmupStartedOff),\n warmupSlopePerStep: readU128LE(data, base + warmupSlopeOff),\n positionSize: readI128LE(data, base + positionSizeOff),\n entryPrice: readU64LE(data, base + entryPriceOff),\n // V12_1 changed funding_index from i128 to i64 (legacy field moved to end of account)\n fundingIndex: isV12_1 ? BigInt(readI64LE(data, base + fundingIndexOff)) : readI128LE(data, base + fundingIndexOff),\n matcherProgram: new PublicKey(data.subarray(base + matcherProgOff, base + matcherProgOff + 32)),\n matcherContext: new PublicKey(data.subarray(base + matcherCtxOff, base + matcherCtxOff + 32)),\n owner: new PublicKey(data.subarray(base + layout.acctOwnerOff, base + layout.acctOwnerOff + 32)),\n feeCredits: readI128LE(data, base + feeCreditsOff),\n lastFeeSlot: readU64LE(data, base + lastFeeSlotOff),\n };\n}\n\n/**\n * Parse all used accounts.\n */\nexport function parseAllAccounts(data: Uint8Array): { idx: number; account: Account }[] {\n const indices = parseUsedIndices(data);\n const maxIdx = maxAccountIndex(data.length);\n const validIndices = indices.filter(idx => idx < maxIdx);\n const droppedCount = indices.length - validIndices.length;\n if (droppedCount > 0) {\n console.warn(\n `[parseAllAccounts] bitmap claims ${indices.length} used accounts but only ${maxIdx} fit ` +\n `in the slab — ${droppedCount} out-of-bounds indices dropped (possible bitmap corruption)`,\n );\n }\n return validIndices.map(idx => ({\n idx,\n account: parseAccount(data, idx),\n }));\n}\n\n","import { PublicKey } from \"@solana/web3.js\";\n\nconst textEncoder = new TextEncoder();\n\n/**\n * Derive vault authority PDA.\n * Seeds: [\"vault\", slab_key]\n */\nexport function deriveVaultAuthority(\n programId: PublicKey,\n slab: PublicKey\n): [PublicKey, number] {\n return PublicKey.findProgramAddressSync(\n [textEncoder.encode(\"vault\"), slab.toBytes()],\n programId\n );\n}\n\n/**\n * Derive insurance LP mint PDA.\n * Seeds: [\"ins_lp\", slab_key]\n */\nexport function deriveInsuranceLpMint(\n programId: PublicKey,\n slab: PublicKey\n): [PublicKey, number] {\n return PublicKey.findProgramAddressSync(\n [textEncoder.encode(\"ins_lp\"), slab.toBytes()],\n programId\n );\n}\n\nconst LP_INDEX_U16_MAX = 0xffff;\n\n/**\n * Derive LP PDA for TradeCpi.\n * Seeds: [\"lp\", slab_key, lp_idx as u16 LE]\n */\nexport function deriveLpPda(\n programId: PublicKey,\n slab: PublicKey,\n lpIdx: number\n): [PublicKey, number] {\n if (\n typeof lpIdx !== \"number\" ||\n !Number.isInteger(lpIdx) ||\n lpIdx < 0 ||\n lpIdx > LP_INDEX_U16_MAX\n ) {\n throw new Error(\n `deriveLpPda: lpIdx must be an integer in [0, ${LP_INDEX_U16_MAX}], got ${lpIdx}`,\n );\n }\n const idxBuf = new Uint8Array(2);\n new DataView(idxBuf.buffer).setUint16(0, lpIdx, true);\n return PublicKey.findProgramAddressSync(\n [textEncoder.encode(\"lp\"), slab.toBytes(), idxBuf],\n programId\n );\n}\n\n/**\n * Derive keeper fund PDA.\n * Seeds: [\"keeper_fund\", slab_key]\n */\nexport function deriveKeeperFund(\n programId: PublicKey,\n slab: PublicKey\n): [PublicKey, number] {\n return PublicKey.findProgramAddressSync(\n [textEncoder.encode(\"keeper_fund\"), slab.toBytes()],\n programId\n );\n}\n\n// ---------------------------------------------------------------------------\n// DEX Program IDs\n// ---------------------------------------------------------------------------\n\n/** PumpSwap AMM program ID. */\nexport const PUMPSWAP_PROGRAM_ID = new PublicKey(\n \"pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA\"\n);\n\n/** Raydium CLMM (Concentrated Liquidity) program ID. */\nexport const RAYDIUM_CLMM_PROGRAM_ID = new PublicKey(\n \"CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK\"\n);\n\n/** Meteora DLMM (Dynamic Liquidity Market Maker) program ID. */\nexport const METEORA_DLMM_PROGRAM_ID = new PublicKey(\n \"LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo\"\n);\n\n// ---------------------------------------------------------------------------\n// Pyth Push Oracle\n// ---------------------------------------------------------------------------\n\n/** Pyth Push Oracle program on mainnet. */\nexport const PYTH_PUSH_ORACLE_PROGRAM_ID = new PublicKey(\n \"pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT\"\n);\n\n// ---------------------------------------------------------------------------\n// Creator Lock PDA (PERC-627)\n// ---------------------------------------------------------------------------\n\n/**\n * Seed used to derive the creator lock PDA.\n * Matches `creator_lock::CREATOR_LOCK_SEED` in percolator-prog.\n */\nexport const CREATOR_LOCK_SEED = \"creator_lock\";\n\n/**\n * Derive the creator lock PDA for a given slab.\n * Seeds: [\"creator_lock\", slab_key]\n *\n * This PDA is required as accounts[9] in every LpVaultWithdraw instruction\n * since percolator-prog PR#170 (GH#1926 / PERC-8287).\n * Non-creator withdrawers must pass this key; if no lock exists on-chain the\n * enforcement is a no-op. The SDK must ALWAYS include it — passing it is mandatory.\n *\n * @param programId - The percolator program ID.\n * @param slab - The slab (market) public key.\n * @returns [pda, bump]\n *\n * @example\n * ```ts\n * const [creatorLockPda] = deriveCreatorLockPda(PROGRAM_ID, slabKey);\n * ```\n */\nexport function deriveCreatorLockPda(\n programId: PublicKey,\n slab: PublicKey\n): [PublicKey, number] {\n return PublicKey.findProgramAddressSync(\n [textEncoder.encode(CREATOR_LOCK_SEED), slab.toBytes()],\n programId\n );\n}\n/** 32-byte feed id as 64 hex digits (optional `0x` prefix after trim). */\nconst PYTH_FEED_ID_HEX_LEN = 64;\n\nfunction normalizePythFeedIdHex(feedIdHex: string): string {\n let s = feedIdHex.trim();\n if (s.startsWith(\"0x\") || s.startsWith(\"0X\")) {\n s = s.slice(2);\n }\n return s;\n}\n\n/**\n * Derive the Pyth Push Oracle PDA for a given feed ID.\n * Seeds: [shard_id(u16 LE, always 0), feed_id(32 bytes)]\n * Program: pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT\n */\nconst FEED_HEX_RE = /^[0-9a-fA-F]{64}$/;\n\nexport function derivePythPushOraclePDA(feedIdHex: string): [PublicKey, number] {\n const normalized = normalizePythFeedIdHex(feedIdHex);\n if (!FEED_HEX_RE.test(normalized)) {\n throw new Error(\n `derivePythPushOraclePDA: feedIdHex must be 64 hex digits (32 bytes); got ${normalized.length === 64 ? \"non-hexadecimal characters\" : normalized.length + \" chars\"}`, );\n }\n const feedId = new Uint8Array(32);\n for (let i = 0; i < 32; i++) {\n const hexPair = normalized.substring(i * 2, i * 2 + 2);\n const byte = parseInt(hexPair, 16);\n // Defensive check: ensure no NaN values in feed ID\n if (Number.isNaN(byte)) {\n throw new Error(\n `derivePythPushOraclePDA: failed to parse hex byte at position ${i}: \"${hexPair}\"`,\n );\n }\n feedId[i] = byte;\n }\n const shardBuf = new Uint8Array(2); // shard_id = 0 (u16 LE)\n return PublicKey.findProgramAddressSync(\n [shardBuf, feedId],\n PYTH_PUSH_ORACLE_PROGRAM_ID,\n );\n}\n","import { Connection, PublicKey } from \"@solana/web3.js\";\nimport {\n getAssociatedTokenAddress,\n getAssociatedTokenAddressSync,\n getAccount,\n Account,\n TOKEN_PROGRAM_ID,\n} from \"@solana/spl-token\";\nimport { TOKEN_2022_PROGRAM_ID } from \"./token-program.js\";\n\n/**\n * Get the associated token address for an owner and mint.\n * Supports both standard SPL Token and Token2022 via optional tokenProgramId.\n */\nexport async function getAta(\n owner: PublicKey,\n mint: PublicKey,\n allowOwnerOffCurve = false,\n tokenProgramId: PublicKey = TOKEN_PROGRAM_ID,\n): Promise<PublicKey> {\n return getAssociatedTokenAddress(mint, owner, allowOwnerOffCurve, tokenProgramId);\n}\n\n/**\n * Synchronous version of getAta.\n * Supports both standard SPL Token and Token2022 via optional tokenProgramId.\n */\nexport function getAtaSync(\n owner: PublicKey,\n mint: PublicKey,\n allowOwnerOffCurve = false,\n tokenProgramId: PublicKey = TOKEN_PROGRAM_ID,\n): PublicKey {\n return getAssociatedTokenAddressSync(mint, owner, allowOwnerOffCurve, tokenProgramId);\n}\n\n/**\n * Fetch token account info.\n * Supports both standard SPL Token and Token2022 via optional tokenProgramId.\n * Throws if account doesn't exist.\n */\nexport async function fetchTokenAccount(\n connection: Connection,\n address: PublicKey,\n tokenProgramId: PublicKey = TOKEN_PROGRAM_ID,\n): Promise<Account> {\n return getAccount(connection, address, undefined, tokenProgramId);\n}\n","import { Connection, PublicKey } from \"@solana/web3.js\";\nimport {\n parseHeader,\n parseConfig,\n parseParams,\n detectSlabLayout,\n SLAB_TIERS_V1M,\n SLAB_TIERS_V2,\n SLAB_TIERS_V_ADL,\n SLAB_TIERS_V12_1,\n type SlabHeader,\n type MarketConfig,\n type EngineState,\n type RiskParams,\n type SlabLayout,\n} from \"./slab.js\";\nimport { getStaticMarkets, type StaticMarketEntry } from \"./static-markets.js\";\nimport { type Network } from \"../config/program-ids.js\";\n\n/** V1 bitmap offset within engine struct (updated for PERC-120/121/122 struct changes) */\nconst ENGINE_BITMAP_OFF = 656; // Updated for PERC-299 (608 + 24 emergency OI fields)\n/** V0 bitmap offset within engine struct (deployed devnet program) */\nconst ENGINE_BITMAP_OFF_V0 = 320;\n\n/**\n * A discovered Percolator market from on-chain program accounts.\n */\nexport interface DiscoveredMarket {\n slabAddress: PublicKey;\n /** The program that owns this slab account */\n programId: PublicKey;\n header: SlabHeader;\n config: MarketConfig;\n engine: EngineState;\n params: RiskParams;\n}\n\n/** PERCOLAT magic bytes — stored little-endian on-chain as TALOCREP */\nconst MAGIC_BYTES = new Uint8Array([0x54, 0x41, 0x4c, 0x4f, 0x43, 0x52, 0x45, 0x50]);\n\n/**\n * Slab tier definitions — V1 layout (all tiers upgraded as of 2026-03-13).\n * IMPORTANT: dataSize must match the compiled program's SLAB_LEN for that MAX_ACCOUNTS.\n * The on-chain program has a hardcoded SLAB_LEN — slab account data.len() must equal it exactly.\n *\n * Layout: HEADER(104) + CONFIG(536) + RiskEngine(variable by tier)\n * ENGINE_OFF = 640 (HEADER=104 + CONFIG=536, padded to 8-byte align on SBF)\n * RiskEngine = fixed(656) + bitmap(BW*8) + post_bitmap(18) + next_free(N*2) + pad + accounts(N*248)\n *\n * Values are empirically verified against on-chain initialized accounts (GH #1109):\n * small = 65,352 (256-acct program, verified on-chain post-V1 upgrade)\n * medium = 257,448 (1024-acct program g9msRSV3, verified on-chain)\n * large = 1,025,832 (4096-acct program FxfD37s1, pre-PERC-118, matches slabDataSizeV1(4096) formula)\n *\n * NOTE: small program (FwfBKZXb) redeployed with --features small,devnet (2026-03-13).\n * Large program FxfD37s1 is pre-PERC-118 — SLAB_LEN=1,025,832, matching formula.\n * See GH #1109, GH #1112.\n *\n * History: Small was V0 (62_808) until 2026-03-13 program upgrade. V0 values preserved\n * in SLAB_TIERS_V0 for discovery of legacy on-chain accounts.\n */\n/**\n * Default slab tiers for the current mainnet program (v12.1).\n * These are used by useCreateMarket to allocate slab accounts of the correct size.\n */\nexport const SLAB_TIERS = {\n micro: SLAB_TIERS_V12_1[\"micro\"],\n small: SLAB_TIERS_V12_1[\"small\"],\n medium: SLAB_TIERS_V12_1[\"medium\"],\n large: SLAB_TIERS_V12_1[\"large\"],\n} as const;\n\n/** @deprecated V0 slab sizes — kept for backward compatibility with old on-chain slabs */\nexport const SLAB_TIERS_V0 = {\n small: { maxAccounts: 256, dataSize: 62_808, label: \"Small\", description: \"256 slots · ~0.44 SOL\" },\n medium: { maxAccounts: 1024, dataSize: 248_760, label: \"Medium\", description: \"1,024 slots · ~1.73 SOL\" },\n large: { maxAccounts: 4096, dataSize: 992_568, label: \"Large\", description: \"4,096 slots · ~6.90 SOL\" },\n} as const;\n\n/**\n * V1D slab sizes — actually-deployed devnet V1 program (ENGINE_OFF=424, BITMAP_OFF=624).\n * PR #1200 added V1D layout detection in slab.ts but discovery.ts ALL_TIERS was missing\n * these sizes, causing V1D slabs to fall through to the memcmp fallback with wrong dataSize\n * hints → detectSlabLayout returning null → parse failure (GH#1205).\n *\n * Sizes computed via computeSlabSize(ENGINE_OFF=424, BITMAP_OFF=624, ACCOUNT_SIZE=248, N, postBitmap=2):\n * The V1D deployed program uses postBitmap=2 (free_head u16 only — no num_used/pad/next_account_id).\n * This is 16 bytes smaller per tier than the SDK default (postBitmap=18). GH#1234.\n * micro = 17,064 (64 slots)\n * small = 65,088 (256 slots)\n * medium = 257,184 (1,024 slots)\n * large = 1,025,568 (4,096 slots)\n */\nexport const SLAB_TIERS_V1D = {\n micro: { maxAccounts: 64, dataSize: 17_064, label: \"Micro\", description: \"64 slots (V1D devnet)\" },\n small: { maxAccounts: 256, dataSize: 65_088, label: \"Small\", description: \"256 slots (V1D devnet)\" },\n medium: { maxAccounts: 1024, dataSize: 257_184, label: \"Medium\", description: \"1,024 slots (V1D devnet)\" },\n large: { maxAccounts: 4096, dataSize: 1_025_568, label: \"Large\", description: \"4,096 slots (V1D devnet)\" },\n} as const;\n\n/**\n * V1D legacy slab sizes — on-chain V1D slabs created before GH#1234 when the SDK assumed\n * postBitmap=18. These are 16 bytes larger per tier than SLAB_TIERS_V1D.\n * PR #1236 fixed postBitmap for new slabs (→2) but caused slab 6ZytbpV4 (65104 bytes,\n * top active market ~$15k 24h vol) to be unrecognized → \"Failed to load market\". GH#1237.\n *\n * Sizes computed via computeSlabSize(ENGINE_OFF=424, BITMAP_OFF=624, ACCOUNT_SIZE=248, N, postBitmap=18):\n * micro = 17,080 (64 slots)\n * small = 65,104 (256 slots) ← slab 6ZytbpV4 TEST/USD\n * medium = 257,200 (1,024 slots)\n * large = 1,025,584 (4,096 slots)\n */\nexport const SLAB_TIERS_V1D_LEGACY = {\n micro: { maxAccounts: 64, dataSize: 17_080, label: \"Micro\", description: \"64 slots (V1D legacy, postBitmap=18)\" },\n small: { maxAccounts: 256, dataSize: 65_104, label: \"Small\", description: \"256 slots (V1D legacy, postBitmap=18)\" },\n medium: { maxAccounts: 1024, dataSize: 257_200, label: \"Medium\", description: \"1,024 slots (V1D legacy, postBitmap=18)\" },\n large: { maxAccounts: 4096, dataSize: 1_025_584, label: \"Large\", description: \"4,096 slots (V1D legacy, postBitmap=18)\" },\n} as const;\n\n/** @deprecated Alias — use SLAB_TIERS (already V1) */\nexport const SLAB_TIERS_V1 = SLAB_TIERS;\n\n/**\n * V_ADL slab tier sizes — PERC-8270/8271 ADL-upgraded program.\n * ENGINE_OFF=624, BITMAP_OFF=1006, ACCOUNT_SIZE=312, postBitmap=18.\n * New account layout adds ADL tracking fields (+64 bytes/account).\n * BPF SLAB_LEN verified by cargo build-sbf in PERC-8271: large (4096) = 1288304 bytes.\n */\n// Single source of truth lives in slab.ts (SLAB_TIERS_V_ADL).\nexport const SLAB_TIERS_V_ADL_DISCOVERY = SLAB_TIERS_V_ADL;\n\nexport type SlabTierKey = keyof typeof SLAB_TIERS;\n\n/** Calculate slab data size for arbitrary account count.\n *\n * Layout (SBF, u128 align = 8):\n * HEADER(104) + CONFIG(536) → ENGINE_OFF = 640\n * RiskEngine fixed scalars: 656 bytes (PERC-299: +24 emergency OI, +32 long/short OI)\n * + bitmap: ceil(N/64)*8\n * + num_used_accounts(u16) + pad(6) + next_account_id(u64) + free_head(u16) = 18\n * + next_free: N*2\n * + pad to 8-byte alignment for Account array\n * + accounts: N*248\n *\n * Must match the on-chain program's SLAB_LEN exactly.\n */\nexport function slabDataSize(maxAccounts: number): number {\n // V0 layout (deployed devnet): ENGINE_OFF=480, ENGINE_BITMAP_OFF=320, ACCOUNT_SIZE=240\n const ENGINE_OFF_V0 = 480;\n const ENGINE_BITMAP_OFF_V0 = 320;\n const ACCOUNT_SIZE_V0 = 240;\n const bitmapBytes = Math.ceil(maxAccounts / 64) * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = ENGINE_BITMAP_OFF_V0 + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOff = Math.ceil(preAccountsLen / 8) * 8;\n return ENGINE_OFF_V0 + accountsOff + maxAccounts * ACCOUNT_SIZE_V0;\n}\n\n/**\n * Calculate slab data size for V1 layout (ENGINE_OFF=640).\n *\n * NOTE: This formula is accurate for small (256) and medium (1024) tiers but\n * underestimates large (4096) by 16 bytes — likely due to a padding/alignment\n * difference at high account counts or a post-PERC-118 struct addition in the\n * deployed binary. Always prefer the hardcoded SLAB_TIERS values (empirically\n * verified on-chain) over this formula for production use.\n */\nexport function slabDataSizeV1(maxAccounts: number): number {\n const ENGINE_OFF_V1 = 640; // HEADER(104) + CONFIG(536) aligned to 8 on SBF = 640\n const ENGINE_BITMAP_OFF_V1 = 656;\n const ACCOUNT_SIZE_V1 = 248;\n const bitmapBytes = Math.ceil(maxAccounts / 64) * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = ENGINE_BITMAP_OFF_V1 + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOff = Math.ceil(preAccountsLen / 8) * 8;\n return ENGINE_OFF_V1 + accountsOff + maxAccounts * ACCOUNT_SIZE_V1;\n}\n\n/**\n * Validate that a slab data size matches one of the known tier sizes.\n * Use this to catch tier↔program mismatches early (PERC-277).\n *\n * @param dataSize - The expected slab data size (from SLAB_TIERS[tier].dataSize)\n * @param programSlabLen - The program's compiled SLAB_LEN (from on-chain error logs or program introspection)\n * @returns true if sizes match, false if there's a mismatch\n */\nexport function validateSlabTierMatch(dataSize: number, programSlabLen: number): boolean {\n return dataSize === programSlabLen;\n}\n\n/** All known slab data sizes for discovery (V0 + V1 + V1D + V1D legacy + V1M + V_ADL tiers) */\nconst ALL_SLAB_SIZES = [\n ...Object.values(SLAB_TIERS).map(t => t.dataSize),\n ...Object.values(SLAB_TIERS_V0).map(t => t.dataSize),\n ...Object.values(SLAB_TIERS_V1D).map(t => t.dataSize),\n ...Object.values(SLAB_TIERS_V1D_LEGACY).map(t => t.dataSize),\n ...Object.values(SLAB_TIERS_V1M).map(t => t.dataSize),\n ...Object.values(SLAB_TIERS_V_ADL).map(t => t.dataSize),\n];\n\n/** Legacy constant for backward compat */\nconst SLAB_DATA_SIZE = SLAB_TIERS.large.dataSize;\n\n/** We need header(104) + config(536) + engine up to nextAccountId (~1200). Total ~1840. Use 1940 for margin. */\nconst HEADER_SLICE_LENGTH = 1940;\n\nfunction dv(data: Uint8Array): DataView {\n return new DataView(data.buffer, data.byteOffset, data.byteLength);\n}\nfunction readU16LE(data: Uint8Array, off: number): number {\n return dv(data).getUint16(off, true);\n}\nfunction readU64LE(data: Uint8Array, off: number): bigint {\n return dv(data).getBigUint64(off, true);\n}\nfunction readI64LE(data: Uint8Array, off: number): bigint {\n return dv(data).getBigInt64(off, true);\n}\nfunction readU128LE(buf: Uint8Array, offset: number): bigint {\n const lo = readU64LE(buf, offset);\n const hi = readU64LE(buf, offset + 8);\n return (hi << 64n) | lo;\n}\nfunction readI128LE(buf: Uint8Array, offset: number): bigint {\n const lo = readU64LE(buf, offset);\n const hi = readU64LE(buf, offset + 8);\n const unsigned = (hi << 64n) | lo;\n const SIGN_BIT = 1n << 127n;\n if (unsigned >= SIGN_BIT) return unsigned - (1n << 128n);\n return unsigned;\n}\n\n/**\n * Light engine parser that works with partial slab data (dataSlice, no accounts array).\n * Requires a layout hint (from detectSlabLayout on the actual slab size) to use correct offsets.\n *\n * @param data — partial slab slice (HEADER_SLICE_LENGTH bytes)\n * @param layout — SlabLayout from detectSlabLayout(actualDataSize). If null, falls back to V0.\n * @param maxAccounts — tier's max accounts for bitmap offset calculation\n */\nfunction parseEngineLight(\n data: Uint8Array,\n layout: SlabLayout | null,\n maxAccounts: number = 4096,\n): EngineState {\n const isV0 = !layout || layout.version === 0;\n const base = layout ? layout.engineOff : 480; // V0=480, V1=640\n const bitmapOff = layout ? layout.engineBitmapOff : ENGINE_BITMAP_OFF_V0;\n\n const minLen = base + bitmapOff;\n if (data.length < minLen) {\n throw new Error(`Slab data too short for engine light parse: ${data.length} < ${minLen}`);\n }\n\n // Compute tier-dependent offsets for numUsedAccounts and nextAccountId\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const numUsedOff = bitmapOff + bitmapWords * 8; // u16 right after bitmap\n const nextAccountIdOff = Math.ceil((numUsedOff + 2) / 8) * 8; // u64, 8-byte aligned\n\n const canReadNumUsed = data.length >= base + numUsedOff + 2;\n const canReadNextId = data.length >= base + nextAccountIdOff + 8;\n\n if (isV0) {\n // V0 engine struct (deployed devnet): ENGINE_OFF=480\n // vault(0,16) + insurance(16,32) + params(48,56) + currentSlot(104,8)\n // + fundingIndex(112,16) + lastFundingSlot(128,8) + fundingRateBps(136,8)\n // + lastCrankSlot(144,8) + maxCrankStaleness(152,8) + totalOI(160,16)\n // + cTot(176,16) + pnlPosTot(192,16) + liqCursor(208,2) + gcCursor(210,2)\n // + lastSweepStart(216,8) + lastSweepComplete(224,8) + crankCursor(232,2) + sweepStartIdx(234,2)\n // + lifetimeLiquidations(240,8) + lifetimeForceCloses(248,8)\n // + netLpPos(256,16) + lpSumAbs(272,16) + lpMaxAbs(288,16) + bitmap(320)\n return {\n vault: readU128LE(data, base + 0),\n insuranceFund: {\n balance: readU128LE(data, base + 16),\n feeRevenue: readU128LE(data, base + 32),\n isolatedBalance: 0n,\n isolationBps: 0,\n },\n currentSlot: readU64LE(data, base + 104),\n fundingIndexQpbE6: readI128LE(data, base + 112),\n lastFundingSlot: readU64LE(data, base + 128),\n fundingRateBpsPerSlotLast: readI64LE(data, base + 136),\n lastCrankSlot: readU64LE(data, base + 144),\n maxCrankStalenessSlots: readU64LE(data, base + 152),\n totalOpenInterest: readU128LE(data, base + 160),\n longOi: 0n,\n shortOi: 0n,\n cTot: readU128LE(data, base + 176),\n pnlPosTot: readU128LE(data, base + 192),\n liqCursor: readU16LE(data, base + 208),\n gcCursor: readU16LE(data, base + 210),\n lastSweepStartSlot: readU64LE(data, base + 216),\n lastSweepCompleteSlot: readU64LE(data, base + 224),\n crankCursor: readU16LE(data, base + 232),\n sweepStartIdx: readU16LE(data, base + 234),\n lifetimeLiquidations: readU64LE(data, base + 240),\n lifetimeForceCloses: readU64LE(data, base + 248),\n netLpPos: readI128LE(data, base + 256),\n lpSumAbs: readU128LE(data, base + 272),\n lpMaxAbs: readU128LE(data, base + 288),\n lpMaxAbsSweep: 0n,\n emergencyOiMode: false,\n emergencyStartSlot: 0n,\n lastBreakerSlot: 0n,\n markPriceE6: 0n, // V0 engine has no mark_price field\n numUsedAccounts: canReadNumUsed ? readU16LE(data, base + numUsedOff) : 0,\n nextAccountId: canReadNextId ? readU64LE(data, base + nextAccountIdOff) : 0n,\n };\n }\n\n // V2 engine struct (BPF intermediate): ENGINE_OFF=600, BITMAP_OFF=432\n // No mark_price, long_oi, short_oi, emergency OI fields.\n // Field offsets relative to engineOff are different from V1.\n const isV2 = layout?.version === 2;\n if (isV2) {\n return {\n vault: readU128LE(data, base + 0),\n insuranceFund: {\n balance: readU128LE(data, base + 16),\n feeRevenue: readU128LE(data, base + 32),\n isolatedBalance: readU128LE(data, base + 48),\n isolationBps: readU16LE(data, base + 64),\n },\n currentSlot: readU64LE(data, base + 352),\n fundingIndexQpbE6: readI128LE(data, base + 360),\n lastFundingSlot: readU64LE(data, base + 376),\n fundingRateBpsPerSlotLast: readI64LE(data, base + 384),\n lastCrankSlot: readU64LE(data, base + 392),\n maxCrankStalenessSlots: readU64LE(data, base + 400),\n totalOpenInterest: readU128LE(data, base + 408),\n longOi: 0n, // V2 has no long_oi\n shortOi: 0n, // V2 has no short_oi\n cTot: readU128LE(data, base + 424),\n pnlPosTot: readU128LE(data, base + 440),\n liqCursor: readU16LE(data, base + 456),\n gcCursor: readU16LE(data, base + 458),\n lastSweepStartSlot: readU64LE(data, base + 464),\n lastSweepCompleteSlot: readU64LE(data, base + 472),\n crankCursor: readU16LE(data, base + 480),\n sweepStartIdx: readU16LE(data, base + 482),\n lifetimeLiquidations: readU64LE(data, base + 488),\n lifetimeForceCloses: readU64LE(data, base + 496),\n netLpPos: readI128LE(data, base + 504),\n lpSumAbs: readU128LE(data, base + 520),\n lpMaxAbs: readU128LE(data, base + 536),\n lpMaxAbsSweep: readU128LE(data, base + 552),\n emergencyOiMode: false, // V2 has no emergency OI fields\n emergencyStartSlot: 0n,\n lastBreakerSlot: 0n,\n markPriceE6: 0n, // V2 has no mark_price\n numUsedAccounts: canReadNumUsed ? readU16LE(data, base + numUsedOff) : 0,\n nextAccountId: canReadNextId ? readU64LE(data, base + nextAccountIdOff) : 0n,\n };\n }\n\n // V_ADL engine struct (PERC-8270/8271): ENGINE_OFF=624, layout-driven offsets.\n // Must branch here because V_ADL has version===1 same as V1/V1M — differentiate by engineOff.\n // All offsets from SlabLayout descriptor, which is computed by buildLayoutVADL().\n const isVAdl = layout !== null && layout.engineOff === 624 && layout.accountSize === 312;\n if (isVAdl) {\n const l = layout!;\n return {\n vault: readU128LE(data, base + 0),\n insuranceFund: {\n balance: readU128LE(data, base + l.engineInsuranceOff),\n feeRevenue: readU128LE(data, base + l.engineInsuranceOff + 16),\n isolatedBalance: readU128LE(data, base + l.engineInsuranceIsolatedOff),\n isolationBps: readU16LE(data, base + l.engineInsuranceIsolationBpsOff),\n },\n currentSlot: readU64LE(data, base + l.engineCurrentSlotOff),\n fundingIndexQpbE6: readI128LE(data, base + l.engineFundingIndexOff),\n lastFundingSlot: readU64LE(data, base + l.engineLastFundingSlotOff),\n fundingRateBpsPerSlotLast: readI64LE(data, base + l.engineFundingRateBpsOff),\n lastCrankSlot: readU64LE(data, base + l.engineLastCrankSlotOff),\n maxCrankStalenessSlots: readU64LE(data, base + l.engineMaxCrankStalenessOff),\n totalOpenInterest: readU128LE(data, base + l.engineTotalOiOff),\n longOi: l.engineLongOiOff >= 0 ? readU128LE(data, base + l.engineLongOiOff) : 0n,\n shortOi: l.engineShortOiOff >= 0 ? readU128LE(data, base + l.engineShortOiOff) : 0n,\n cTot: readU128LE(data, base + l.engineCTotOff),\n pnlPosTot: readU128LE(data, base + l.enginePnlPosTotOff),\n liqCursor: readU16LE(data, base + l.engineLiqCursorOff),\n gcCursor: readU16LE(data, base + l.engineGcCursorOff),\n lastSweepStartSlot: readU64LE(data, base + l.engineLastSweepStartOff),\n lastSweepCompleteSlot: readU64LE(data, base + l.engineLastSweepCompleteOff),\n crankCursor: readU16LE(data, base + l.engineCrankCursorOff),\n sweepStartIdx: readU16LE(data, base + l.engineSweepStartIdxOff),\n lifetimeLiquidations: readU64LE(data, base + l.engineLifetimeLiquidationsOff),\n lifetimeForceCloses: readU64LE(data, base + l.engineLifetimeForceClosesOff),\n netLpPos: readI128LE(data, base + l.engineNetLpPosOff),\n lpSumAbs: readU128LE(data, base + l.engineLpSumAbsOff),\n lpMaxAbs: readU128LE(data, base + l.engineLpMaxAbsOff),\n lpMaxAbsSweep: readU128LE(data, base + l.engineLpMaxAbsSweepOff),\n emergencyOiMode: l.engineEmergencyOiModeOff >= 0 ? data[base + l.engineEmergencyOiModeOff] !== 0 : false,\n emergencyStartSlot: l.engineEmergencyStartSlotOff >= 0 ? readU64LE(data, base + l.engineEmergencyStartSlotOff) : 0n,\n lastBreakerSlot: l.engineLastBreakerSlotOff >= 0 ? readU64LE(data, base + l.engineLastBreakerSlotOff) : 0n,\n markPriceE6: l.engineMarkPriceOff >= 0 ? readU64LE(data, base + l.engineMarkPriceOff) : 0n,\n numUsedAccounts: canReadNumUsed ? readU16LE(data, base + numUsedOff) : 0,\n nextAccountId: canReadNextId ? readU64LE(data, base + nextAccountIdOff) : 0n,\n };\n }\n\n // V1 engine struct (PERC-1094 corrected): ENGINE_OFF=600 (BPF/SBF, CONFIG_LEN=496)\n // vault(0,16) + insurance(16,56) + params(72,288) + currentSlot(360) + fundingIndex(368,16)\n // + lastFundingSlot(384) + fundingRateBps(392) + markPrice(400) + lastCrankSlot(424)\n // + maxCrankStaleness(432) + totalOI(440,16) + longOi(456,16) + shortOi(472,16)\n // + cTot(488,16) + pnlPosTot(504,16) + liqCursor(520,2) + gcCursor(522,2)\n // + lastSweepStart(528) + lastSweepComplete(536) + crankCursor(544,2) + sweepStartIdx(546,2)\n // + lifetimeLiquidations(552) + lifetimeForceCloses(560)\n // + netLpPos(568,16) + lpSumAbs(584,16) + lpMaxAbs(600,16) + lpMaxAbsSweep(616,16)\n // + emergencyOiMode(632,1+7pad) + emergencyStartSlot(640) + lastBreakerSlot(648) + bitmap(656)\n return {\n vault: readU128LE(data, base + 0),\n insuranceFund: {\n balance: readU128LE(data, base + 16),\n feeRevenue: readU128LE(data, base + 32),\n isolatedBalance: readU128LE(data, base + 48),\n isolationBps: readU16LE(data, base + 64),\n },\n currentSlot: readU64LE(data, base + 360), // PERC-1094: params end at 72+288=360 (was 352)\n fundingIndexQpbE6: readI128LE(data, base + 368),\n lastFundingSlot: readU64LE(data, base + 384),\n fundingRateBpsPerSlotLast: readI64LE(data, base + 392),\n lastCrankSlot: readU64LE(data, base + 424),\n maxCrankStalenessSlots: readU64LE(data, base + 408),\n totalOpenInterest: readU128LE(data, base + 416),\n longOi: readU128LE(data, base + 432),\n shortOi: readU128LE(data, base + 448),\n cTot: readU128LE(data, base + 464),\n pnlPosTot: readU128LE(data, base + 480),\n liqCursor: readU16LE(data, base + 496),\n gcCursor: readU16LE(data, base + 498),\n lastSweepStartSlot: readU64LE(data, base + 504),\n lastSweepCompleteSlot: readU64LE(data, base + 512),\n crankCursor: readU16LE(data, base + 520),\n sweepStartIdx: readU16LE(data, base + 522),\n lifetimeLiquidations: readU64LE(data, base + 528),\n lifetimeForceCloses: readU64LE(data, base + 536),\n netLpPos: readI128LE(data, base + 544),\n lpSumAbs: readU128LE(data, base + 560),\n lpMaxAbs: readU128LE(data, base + 576),\n lpMaxAbsSweep: readU128LE(data, base + 592),\n emergencyOiMode: data[base + 608] !== 0,\n emergencyStartSlot: readU64LE(data, base + 616),\n lastBreakerSlot: readU64LE(data, base + 624),\n markPriceE6: readU64LE(data, base + 400), // PERC-1094: was 392\n numUsedAccounts: canReadNumUsed ? readU16LE(data, base + numUsedOff) : 0,\n nextAccountId: canReadNextId ? readU64LE(data, base + nextAccountIdOff) : 0n,\n };\n}\n\n/** Options for `discoverMarkets`. */\nexport interface DiscoverMarketsOptions {\n /**\n * Run tier queries sequentially with per-tier retry on HTTP 429 instead of\n * firing all in parallel. Reduces RPC rate-limit pressure at the cost of\n * slightly slower discovery (~14 round-trips instead of 1 concurrent batch).\n * Default: false (preserves original parallel behaviour).\n *\n * PERC-1650: keeper uses this flag to avoid 429 storms on its fallback RPC\n * (Helius starter tier). Pass `sequential: true` from CrankService.discover().\n */\n sequential?: boolean;\n /**\n * Delay in ms between sequential tier queries (only used when sequential=true).\n * Default: 200 ms.\n */\n interTierDelayMs?: number;\n /**\n * Per-tier retry backoff delays on 429 (ms). Jitter of up to +25% is applied.\n * Only used when sequential=true. Default: [1_000, 3_000, 9_000, 27_000].\n */\n rateLimitBackoffMs?: number[];\n\n /**\n * In parallel mode (the default), cap how many tier RPC requests are in-flight\n * at once to avoid accidental RPC storms from client code.\n *\n * Default: 6\n */\n maxParallelTiers?: number;\n\n /**\n * Hard cap on how many tier dataSize queries are attempted.\n * Default: all known tiers.\n */\n maxTierQueries?: number;\n\n /**\n * Base URL of the Percolator REST API (e.g. `\"https://percolatorlaunch.com/api\"`).\n *\n * When set, `discoverMarkets` will fall back to the REST API's `GET /markets`\n * endpoint if `getProgramAccounts` fails or returns 0 results (common on public\n * mainnet RPCs that reject `getProgramAccounts`).\n *\n * The API returns slab addresses which are then fetched on-chain via\n * `getMarketsByAddress` (uses `getMultipleAccounts`, works on all RPCs).\n *\n * GH#59 / PERC-8424: Unblocks mainnet users without a Helius API key.\n *\n * @example\n * ```ts\n * const markets = await discoverMarkets(connection, programId, {\n * apiBaseUrl: \"https://percolatorlaunch.com/api\",\n * });\n * ```\n */\n apiBaseUrl?: string;\n\n /**\n * Timeout in ms for the API fallback HTTP request.\n * Only used when `apiBaseUrl` is set.\n * Default: 10_000 (10 seconds).\n */\n apiTimeoutMs?: number;\n\n /**\n * Network hint for tier-3 static bundle fallback (`\"mainnet\"` or `\"devnet\"`).\n *\n * When both `getProgramAccounts` (tier 1) and the REST API (tier 2) fail,\n * `discoverMarkets` will fall back to a bundled static list of known slab\n * addresses for the specified network. The addresses are fetched on-chain\n * via `getMarketsByAddress` (`getMultipleAccounts` — works on all RPCs).\n *\n * If not set, tier-3 fallback is disabled.\n *\n * The static list can be extended at runtime via `registerStaticMarkets()`.\n *\n * @see {@link registerStaticMarkets} to add addresses at runtime\n * @see {@link getStaticMarkets} to inspect the current static list\n *\n * @example\n * ```ts\n * const markets = await discoverMarkets(connection, programId, {\n * apiBaseUrl: \"https://percolatorlaunch.com/api\",\n * network: \"mainnet\", // enables tier-3 static fallback\n * });\n * ```\n */\n network?: Network;\n}\n\n/** Return true if the error looks like an HTTP 429 / rate-limit response. */\nfunction isRateLimitError(err: unknown): boolean {\n if (!err) return false;\n const msg = err instanceof Error ? err.message : String(err);\n return (\n msg.includes(\"429\") ||\n msg.toLowerCase().includes(\"rate limit\") ||\n msg.toLowerCase().includes(\"too many requests\")\n );\n}\n\n/** Add up to 25% random jitter to avoid thundering-herd on retry. */\nfunction withJitter(delayMs: number): number {\n return delayMs + Math.floor(Math.random() * delayMs * 0.25);\n}\n\n/**\n * Discover all Percolator markets owned by the given program.\n * Uses getProgramAccounts with dataSize filter + dataSlice to download only ~1400 bytes per slab.\n *\n * @param options.sequential - Run tier queries sequentially with 429 retry (PERC-1650).\n */\nexport async function discoverMarkets(\n connection: Connection,\n programId: PublicKey,\n options: DiscoverMarketsOptions = {},\n): Promise<DiscoveredMarket[]> {\n const {\n sequential = false,\n interTierDelayMs = 200,\n rateLimitBackoffMs = [1_000, 3_000, 9_000, 27_000],\n maxParallelTiers = 6,\n } = options;\n\n // Query all known slab sizes in parallel — V0, V1D (deployed devnet), V1D legacy, and V1 (upgraded) tiers.\n // We track the actual dataSize per entry so detectSlabLayout can determine the correct layout,\n // and pass that layout to all parse functions (avoids wrong-version offsets on partial slices).\n // GH#1205: V1D tiers were missing here — V1D slabs fell through to memcmp fallback with wrong\n // dataSize hints → detectSlabLayout returned null → parse failure in discoverMarkets.\n // GH#1237/GH#1238: SLAB_TIERS_V1D_LEGACY (postBitmap=18, e.g. 65,104-byte slabs created before\n // GH#1234) must also be included; omitting them causes legacy on-chain slabs to be missed by\n // dataSize filter queries and fall through to memcmp with wrong maxAccounts hint.\n const ALL_TIERS = [\n ...Object.values(SLAB_TIERS),\n ...Object.values(SLAB_TIERS_V0),\n ...Object.values(SLAB_TIERS_V1D),\n ...Object.values(SLAB_TIERS_V1D_LEGACY),\n ...Object.values(SLAB_TIERS_V2),\n ...Object.values(SLAB_TIERS_V1M),\n ...Object.values(SLAB_TIERS_V_ADL),\n ];\n type RawEntry = { pubkey: PublicKey; account: { data: Buffer | Uint8Array }; maxAccounts: number; dataSize: number };\n let rawAccounts: RawEntry[] = [];\n\n /**\n * Fetch one tier with per-attempt 429 retry (sequential mode only).\n * Returns an array of RawEntry on success, or an empty array after exhausting retries.\n */\n async function fetchTierWithRetry(\n tier: { dataSize: number; maxAccounts: number },\n ): Promise<RawEntry[]> {\n for (let attempt = 0; attempt <= rateLimitBackoffMs.length; attempt++) {\n try {\n const results = await connection.getProgramAccounts(programId, {\n filters: [{ dataSize: tier.dataSize }],\n dataSlice: { offset: 0, length: HEADER_SLICE_LENGTH },\n });\n return results.map(entry => ({ ...entry, maxAccounts: tier.maxAccounts, dataSize: tier.dataSize }));\n } catch (err) {\n if (isRateLimitError(err) && attempt < rateLimitBackoffMs.length) {\n const delay = withJitter(rateLimitBackoffMs[attempt]);\n console.warn(\n `[discoverMarkets] 429 on tier dataSize=${tier.dataSize} attempt=${attempt + 1}, backing off ${delay}ms`,\n );\n await new Promise(r => setTimeout(r, delay));\n continue;\n }\n // Non-429 or exhausted retries\n console.warn(\n `[discoverMarkets] Tier query failed (dataSize=${tier.dataSize}, attempt=${attempt + 1}):`,\n err instanceof Error ? err.message : err,\n );\n return [];\n }\n }\n return [];\n }\n\n const maxTierQueries = options.maxTierQueries ?? ALL_TIERS.length;\n const tiersToQuery = ALL_TIERS.slice(0, maxTierQueries);\n\n // Avoid accidental `0`/negative or NaN causing infinite loops.\n const effectiveMaxParallelTiers = Math.max(1, Number.isFinite(maxParallelTiers) ? maxParallelTiers : 6);\n\n try {\n if (sequential) {\n // PERC-1650: sequential mode — one tier at a time with inter-tier spacing + per-tier 429 retry.\n for (let i = 0; i < tiersToQuery.length; i++) {\n const tier = tiersToQuery[i];\n const entries = await fetchTierWithRetry(tier);\n rawAccounts.push(...entries);\n if (i < tiersToQuery.length - 1) {\n await new Promise(r => setTimeout(r, interTierDelayMs));\n }\n }\n } else {\n // Parallel mode: cap tier concurrency so we don't fire 20+ large\n // getProgramAccounts calls at once from a single client call.\n for (let offset = 0; offset < tiersToQuery.length; offset += effectiveMaxParallelTiers) {\n const chunk = tiersToQuery.slice(offset, offset + effectiveMaxParallelTiers);\n const queries = chunk.map(tier =>\n connection.getProgramAccounts(programId, {\n filters: [{ dataSize: tier.dataSize }],\n dataSlice: { offset: 0, length: HEADER_SLICE_LENGTH },\n }).then(results =>\n results.map(entry => ({\n ...entry,\n maxAccounts: tier.maxAccounts,\n dataSize: tier.dataSize,\n })),\n ),\n );\n\n const results = await Promise.allSettled(queries);\n for (const result of results) {\n if (result.status === \"fulfilled\") {\n for (const entry of result.value) {\n rawAccounts.push(entry as RawEntry);\n }\n } else {\n console.warn(\n \"[discoverMarkets] Tier query rejected:\",\n result.reason instanceof Error ? result.reason.message : result.reason,\n );\n }\n }\n }\n }\n\n // NOTE: hadRejection guard removed — dataSize filters silently return 0 when on-chain\n // account size changed; RPC returns no error, so we must fallback on empty results too.\n if (rawAccounts.length === 0) {\n console.warn(\"[discoverMarkets] dataSize filters returned 0 markets, falling back to memcmp\");\n const fallback = await connection.getProgramAccounts(programId, {\n filters: [\n {\n memcmp: {\n offset: 0,\n bytes: \"F6P2QNqpQV5\", // base58 of TALOCREP (u64 LE magic)\n },\n },\n ],\n dataSlice: { offset: 0, length: HEADER_SLICE_LENGTH },\n });\n // Unknown actual size — use large V0 as safe default (maxAccounts=4096)\n rawAccounts = [...fallback].map(e => ({ ...e, maxAccounts: 4096, dataSize: SLAB_TIERS.large.dataSize })) as RawEntry[];\n }\n } catch (err) {\n console.warn(\n \"[discoverMarkets] dataSize filters failed, falling back to memcmp:\",\n err instanceof Error ? err.message : err,\n );\n try {\n const fallback = await connection.getProgramAccounts(programId, {\n filters: [\n {\n memcmp: {\n offset: 0,\n bytes: \"F6P2QNqpQV5\", // base58 of TALOCREP (u64 LE magic)\n },\n },\n ],\n dataSlice: { offset: 0, length: HEADER_SLICE_LENGTH },\n });\n rawAccounts = [...fallback].map(e => ({ ...e, maxAccounts: 4096, dataSize: SLAB_TIERS.large.dataSize })) as RawEntry[];\n } catch (memcmpErr) {\n // GH#59: memcmp also rejected (public mainnet RPCs reject all getProgramAccounts)\n console.warn(\n \"[discoverMarkets] memcmp fallback also failed:\",\n memcmpErr instanceof Error ? memcmpErr.message : memcmpErr,\n );\n }\n }\n\n // GH#59 / PERC-8424: If getProgramAccounts returned nothing (public mainnet RPC\n // rejects it) and an API base URL is configured, fall back to the REST API to\n // discover slab addresses, then use getMarketsByAddress (getMultipleAccounts).\n if (rawAccounts.length === 0 && options.apiBaseUrl) {\n console.warn(\n \"[discoverMarkets] RPC discovery returned 0 markets, falling back to REST API\",\n );\n try {\n const apiResult = await discoverMarketsViaApi(\n connection,\n programId,\n options.apiBaseUrl,\n { timeoutMs: options.apiTimeoutMs },\n );\n if (apiResult.length > 0) {\n return apiResult;\n }\n // API returned 0 markets — fall through to tier 3\n console.warn(\n \"[discoverMarkets] REST API returned 0 markets, checking tier-3 static bundle\",\n );\n } catch (apiErr) {\n console.warn(\n \"[discoverMarkets] API fallback also failed:\",\n apiErr instanceof Error ? apiErr.message : apiErr,\n );\n // Fall through to tier 3\n }\n }\n\n // PERC-8435: Tier 3 — static bundle fallback. If both getProgramAccounts and\n // the REST API failed (or returned 0 results) and a network hint is provided,\n // use the bundled static market list as a last-resort address directory.\n if (rawAccounts.length === 0 && options.network) {\n const staticEntries = getStaticMarkets(options.network);\n if (staticEntries.length > 0) {\n console.warn(\n `[discoverMarkets] Tier 1+2 failed, falling back to static bundle (${staticEntries.length} addresses for ${options.network})`,\n );\n try {\n return await discoverMarketsViaStaticBundle(\n connection,\n programId,\n staticEntries,\n );\n } catch (staticErr) {\n console.warn(\n \"[discoverMarkets] Static bundle fallback also failed:\",\n staticErr instanceof Error ? staticErr.message : staticErr,\n );\n // Fall through to return empty array\n }\n } else {\n console.warn(\n `[discoverMarkets] Static bundle has 0 entries for ${options.network} — skipping tier 3`,\n );\n }\n }\n\n const accounts = rawAccounts;\n\n const markets: DiscoveredMarket[] = [];\n // GH#1115: deduplicate raw accounts by pubkey — the same slab can appear in multiple\n // tier queries if both V0 and V1 sizes match or if the RPC returns duplicate entries.\n const seenPubkeys = new Set<string>();\n\n for (const { pubkey, account, maxAccounts, dataSize } of accounts) {\n const pkStr = pubkey.toBase58();\n if (seenPubkeys.has(pkStr)) continue;\n seenPubkeys.add(pkStr);\n const data = new Uint8Array(account.data);\n\n let valid = true;\n for (let i = 0; i < MAGIC_BYTES.length; i++) {\n if (data[i] !== MAGIC_BYTES[i]) {\n valid = false;\n break;\n }\n }\n if (!valid) continue;\n\n // Detect layout from actual slab size — not slice length — so parse functions\n // get correct V0/V1 offsets even when working on the partial HEADER_SLICE_LENGTH slice.\n // Pass the data buffer so V2 slabs (same size as V1D) can be disambiguated via version field.\n const layout = detectSlabLayout(dataSize, data);\n\n if (!layout) {\n console.warn(\n `[discoverMarkets] Skipping account ${pkStr}: unrecognized layout for dataSize=${dataSize}`,\n );\n continue;\n }\n\n try {\n const header = parseHeader(data);\n const config = parseConfig(data, layout);\n const engine = parseEngineLight(data, layout, maxAccounts);\n const params = parseParams(data, layout);\n\n markets.push({ slabAddress: pubkey, programId, header, config, engine, params });\n } catch (err) {\n console.warn(\n `[discoverMarkets] Failed to parse account ${pubkey.toBase58()}:`,\n err instanceof Error ? err.message : err,\n );\n }\n }\n\n return markets;\n}\n\n/**\n * Options for `getMarketsByAddress`.\n */\nexport interface GetMarketsByAddressOptions {\n /**\n * Maximum number of addresses per `getMultipleAccounts` RPC call.\n * Solana limits a single call to 100 accounts; callers may lower this\n * to reduce per-request payload size or avoid 429s.\n *\n * Default: 100 (Solana maximum).\n */\n batchSize?: number;\n\n /**\n * Delay in ms between batches when the address list exceeds `batchSize`.\n * Helps avoid rate-limiting on public RPCs.\n *\n * Default: 0 (no delay).\n */\n interBatchDelayMs?: number;\n}\n\n/**\n * Fetch and parse Percolator markets by their known slab addresses.\n *\n * Unlike `discoverMarkets()` — which uses `getProgramAccounts` and is blocked\n * on public mainnet RPCs — this function uses `getMultipleAccounts`, which works\n * on any RPC endpoint (including `api.mainnet-beta.solana.com`).\n *\n * Callers must already know the market slab addresses (e.g. from an indexer,\n * a hardcoded registry, or a previous `discoverMarkets` call on a permissive RPC).\n *\n * @param connection - Solana RPC connection\n * @param programId - The Percolator program that owns these slabs\n * @param addresses - Array of slab account public keys to fetch\n * @param options - Optional batching/delay configuration\n * @returns Parsed markets for all valid slab accounts; invalid/missing accounts are silently skipped.\n *\n * @example\n * ```ts\n * import { getMarketsByAddress, getProgramId } from \"@percolator/sdk\";\n * import { Connection, PublicKey } from \"@solana/web3.js\";\n *\n * const connection = new Connection(\"https://api.mainnet-beta.solana.com\");\n * const programId = getProgramId(\"mainnet\");\n * const slabs = [\n * new PublicKey(\"So11111111111111111111111111111111111111112\"),\n * // ... more known slab addresses\n * ];\n *\n * const markets = await getMarketsByAddress(connection, programId, slabs);\n * console.log(`Found ${markets.length} markets`);\n * ```\n */\nexport async function getMarketsByAddress(\n connection: Connection,\n programId: PublicKey,\n addresses: PublicKey[],\n options: GetMarketsByAddressOptions = {},\n): Promise<DiscoveredMarket[]> {\n if (addresses.length === 0) return [];\n\n const {\n batchSize = 100,\n interBatchDelayMs = 0,\n } = options;\n\n const effectiveBatchSize = Math.max(1, Math.min(batchSize, 100));\n\n // Fetch account data in batches (Solana caps getMultipleAccounts at 100)\n type AccountResult = { pubkey: PublicKey; data: Buffer | Uint8Array } | null;\n const fetched: AccountResult[] = [];\n\n for (let offset = 0; offset < addresses.length; offset += effectiveBatchSize) {\n const batch = addresses.slice(offset, offset + effectiveBatchSize);\n\n const response = await connection.getMultipleAccountsInfo(batch);\n\n for (let i = 0; i < batch.length; i++) {\n const info = response[i];\n if (info && info.data) {\n if (!info.owner.equals(programId)) {\n console.warn(\n `[getMarketsByAddress] Skipping ${batch[i].toBase58()}: owner mismatch ` +\n `(expected ${programId.toBase58()}, got ${info.owner.toBase58()})`,\n );\n continue;\n }\n fetched.push({ pubkey: batch[i], data: info.data });\n }\n }\n\n // Inter-batch delay to avoid rate-limiting\n if (interBatchDelayMs > 0 && offset + effectiveBatchSize < addresses.length) {\n await new Promise(r => setTimeout(r, interBatchDelayMs));\n }\n }\n\n // Parse each account into a DiscoveredMarket\n const markets: DiscoveredMarket[] = [];\n\n for (const entry of fetched) {\n if (!entry) continue;\n const { pubkey, data: rawData } = entry;\n const data = new Uint8Array(rawData);\n\n // Validate magic bytes\n let valid = true;\n for (let i = 0; i < MAGIC_BYTES.length; i++) {\n if (data[i] !== MAGIC_BYTES[i]) {\n valid = false;\n break;\n }\n }\n if (!valid) {\n console.warn(\n `[getMarketsByAddress] Skipping ${pubkey.toBase58()}: invalid magic bytes`,\n );\n continue;\n }\n\n // Detect layout from full account data length\n const layout = detectSlabLayout(data.length, data);\n if (!layout) {\n console.warn(\n `[getMarketsByAddress] Skipping ${pubkey.toBase58()}: unrecognized layout for dataSize=${data.length}`,\n );\n continue;\n }\n\n try {\n const header = parseHeader(data);\n const config = parseConfig(data, layout);\n const engine = parseEngineLight(data, layout, layout.maxAccounts);\n const params = parseParams(data, layout);\n\n markets.push({ slabAddress: pubkey, programId, header, config, engine, params });\n } catch (err) {\n console.warn(\n `[getMarketsByAddress] Failed to parse account ${pubkey.toBase58()}:`,\n err instanceof Error ? err.message : err,\n );\n }\n }\n\n return markets;\n}\n\n// ---------------------------------------------------------------------------\n// REST API-based market discovery (GH#59 / PERC-8424)\n// ---------------------------------------------------------------------------\n\n/**\n * Shape of a single market entry returned by the Percolator REST API\n * (`GET /markets`). Only the fields needed for discovery are typed here;\n * the full API response may contain additional statistics fields.\n */\nexport interface ApiMarketEntry {\n slab_address: string;\n symbol?: string;\n name?: string;\n decimals?: number;\n status?: string;\n [key: string]: unknown;\n}\n\n/** Options for {@link discoverMarketsViaApi}. */\nexport interface DiscoverMarketsViaApiOptions {\n /**\n * Timeout in ms for the HTTP request to the REST API.\n * Default: 10_000 (10 seconds).\n */\n timeoutMs?: number;\n\n /**\n * Options forwarded to {@link getMarketsByAddress} for the on-chain fetch\n * step (batch size, inter-batch delay).\n */\n onChainOptions?: GetMarketsByAddressOptions;\n}\n\n/**\n * Discover Percolator markets by first querying the REST API for slab addresses,\n * then fetching full on-chain data via `getMarketsByAddress` (which uses\n * `getMultipleAccounts` — works on all RPCs including public mainnet nodes).\n *\n * This is the recommended discovery path for mainnet users who do not have a\n * Helius API key, since `getProgramAccounts` is rejected by public RPCs.\n *\n * The REST API acts as an address directory only — all market data is verified\n * on-chain via `getMarketsByAddress`, so the caller gets the same\n * `DiscoveredMarket[]` result as `discoverMarkets()`.\n *\n * @param connection - Solana RPC connection (any endpoint, including public)\n * @param programId - The Percolator program that owns the slabs\n * @param apiBaseUrl - Base URL of the Percolator REST API\n * (e.g. `\"https://percolatorlaunch.com/api\"`)\n * @param options - Optional timeout and on-chain fetch configuration\n * @returns Parsed markets for all valid slab accounts discovered via the API\n *\n * @example\n * ```ts\n * import { discoverMarketsViaApi, getProgramId } from \"@percolator/sdk\";\n * import { Connection } from \"@solana/web3.js\";\n *\n * const connection = new Connection(\"https://api.mainnet-beta.solana.com\");\n * const programId = getProgramId(\"mainnet\");\n * const markets = await discoverMarketsViaApi(\n * connection,\n * programId,\n * \"https://percolatorlaunch.com/api\",\n * );\n * console.log(`Discovered ${markets.length} markets via API fallback`);\n * ```\n */\nexport async function discoverMarketsViaApi(\n connection: Connection,\n programId: PublicKey,\n apiBaseUrl: string,\n options: DiscoverMarketsViaApiOptions = {},\n): Promise<DiscoveredMarket[]> {\n const { timeoutMs = 10_000, onChainOptions } = options;\n\n // Normalise base URL — strip trailing slash to avoid double-slash in path\n const base = apiBaseUrl.replace(/\\/+$/, \"\");\n const url = `${base}/markets`;\n\n // Fetch market list from REST API\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"GET\",\n headers: { Accept: \"application/json\" },\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n throw new Error(\n `[discoverMarketsViaApi] API returned ${response.status} ${response.statusText} from ${url}`,\n );\n }\n\n const body = (await response.json()) as { markets?: ApiMarketEntry[] };\n const apiMarkets = body.markets;\n\n if (!Array.isArray(apiMarkets) || apiMarkets.length === 0) {\n console.warn(\"[discoverMarketsViaApi] API returned 0 markets\");\n return [];\n }\n\n // Extract valid slab addresses\n const addresses: PublicKey[] = [];\n for (const entry of apiMarkets) {\n if (!entry.slab_address || typeof entry.slab_address !== \"string\") continue;\n try {\n addresses.push(new PublicKey(entry.slab_address));\n } catch {\n console.warn(\n `[discoverMarketsViaApi] Skipping invalid slab address: ${entry.slab_address}`,\n );\n }\n }\n\n if (addresses.length === 0) {\n console.warn(\"[discoverMarketsViaApi] No valid slab addresses from API\");\n return [];\n }\n\n console.log(\n `[discoverMarketsViaApi] API returned ${addresses.length} slab addresses, fetching on-chain data`,\n );\n\n // Fetch full on-chain data via getMultipleAccounts (works on all RPCs)\n return getMarketsByAddress(connection, programId, addresses, onChainOptions);\n}\n\n// ---------------------------------------------------------------------------\n// Static bundle fallback (PERC-8435 — tier 3)\n// ---------------------------------------------------------------------------\n\n/** Options for {@link discoverMarketsViaStaticBundle}. */\nexport interface DiscoverMarketsViaStaticBundleOptions {\n /**\n * Options forwarded to {@link getMarketsByAddress} for the on-chain fetch\n * step (batch size, inter-batch delay).\n */\n onChainOptions?: GetMarketsByAddressOptions;\n}\n\n/**\n * Discover Percolator markets from a static list of known slab addresses.\n *\n * This is the tier-3 (last-resort) fallback for `discoverMarkets()`. It uses\n * a bundled list of known slab addresses and fetches their full account data\n * on-chain via `getMarketsByAddress` (`getMultipleAccounts` — works on all RPCs).\n *\n * The static list acts as an address directory only — all market data is verified\n * on-chain, so stale entries are silently skipped (the account won't have valid\n * magic bytes or will have been closed).\n *\n * @param connection - Solana RPC connection (any endpoint)\n * @param programId - The Percolator program that owns the slabs\n * @param entries - Static market entries (typically from {@link getStaticMarkets})\n * @param options - Optional on-chain fetch configuration\n * @returns Parsed markets for all valid slab accounts; stale/missing entries are skipped.\n *\n * @example\n * ```ts\n * import {\n * discoverMarketsViaStaticBundle,\n * getStaticMarkets,\n * getProgramId,\n * } from \"@percolator/sdk\";\n * import { Connection } from \"@solana/web3.js\";\n *\n * const connection = new Connection(\"https://api.mainnet-beta.solana.com\");\n * const programId = getProgramId(\"mainnet\");\n * const entries = getStaticMarkets(\"mainnet\");\n *\n * const markets = await discoverMarketsViaStaticBundle(\n * connection,\n * programId,\n * entries,\n * );\n * console.log(`Recovered ${markets.length} markets from static bundle`);\n * ```\n */\nexport async function discoverMarketsViaStaticBundle(\n connection: Connection,\n programId: PublicKey,\n entries: StaticMarketEntry[],\n options: DiscoverMarketsViaStaticBundleOptions = {},\n): Promise<DiscoveredMarket[]> {\n if (entries.length === 0) return [];\n\n // Extract valid slab addresses from static entries\n const addresses: PublicKey[] = [];\n for (const entry of entries) {\n if (!entry.slabAddress || typeof entry.slabAddress !== \"string\") continue;\n try {\n addresses.push(new PublicKey(entry.slabAddress));\n } catch {\n console.warn(\n `[discoverMarketsViaStaticBundle] Skipping invalid slab address: ${entry.slabAddress}`,\n );\n }\n }\n\n if (addresses.length === 0) {\n console.warn(\"[discoverMarketsViaStaticBundle] No valid slab addresses in static bundle\");\n return [];\n }\n\n console.log(\n `[discoverMarketsViaStaticBundle] Fetching ${addresses.length} slab addresses on-chain`,\n );\n\n return getMarketsByAddress(connection, programId, addresses, options.onChainOptions);\n}\n","/**\n * Static market registry — bundled list of known Percolator slab addresses.\n *\n * This is the tier-3 fallback for `discoverMarkets()`: when both\n * `getProgramAccounts` (tier 1) and the REST API (tier 2) are unavailable,\n * the SDK falls back to this bundled list to bootstrap market discovery.\n *\n * The addresses are fetched on-chain via `getMarketsByAddress`\n * (`getMultipleAccounts`), so all data is still verified on-chain. The static\n * list only provides the *address directory* — no cached market data is used.\n *\n * ## Maintenance\n *\n * Update this list when new markets are deployed or old ones are retired.\n * Run `scripts/update-static-markets.ts` to regenerate from a permissive RPC\n * or the REST API.\n *\n * @module\n */\n\nimport { PublicKey } from \"@solana/web3.js\";\nimport type { Network } from \"../config/program-ids.js\";\n\n/**\n * A single entry in the static market registry.\n *\n * Only the slab address (base58) is required. Optional metadata fields\n * (`symbol`, `name`) are provided for debugging/logging purposes only —\n * they are **not** used for on-chain data and may become stale.\n */\nexport interface StaticMarketEntry {\n /** Base58-encoded slab account address. */\n slabAddress: string;\n /** Optional human-readable symbol (e.g. \"SOL-PERP\"). */\n symbol?: string;\n /** Optional descriptive name. */\n name?: string;\n}\n\n/**\n * Known mainnet market slab addresses.\n *\n * These are the markets deployed to the mainnet Percolator program\n * (`GM8zjJ8LTBMv9xEsverh6H6wLyevgMHEJXcEzyY3rY24`).\n *\n * **Last updated:** 2026-04-04 (pre-mainnet launch, populated from devnet\n * deployment addresses as placeholders — update with real mainnet addresses\n * once mainnet markets are live).\n */\nconst MAINNET_MARKETS: StaticMarketEntry[] = [\n // Populated at mainnet launch — currently empty.\n // To add entries:\n // { slabAddress: \"ABC123...\", symbol: \"SOL-PERP\", name: \"SOL Perpetual\" },\n];\n\n/**\n * Known devnet market slab addresses.\n *\n * These are discovered from the devnet Percolator program\n * (`FxfD37s1AZTeWfFQps9Zpebi2dNQ9QSSDtfMKdbsfKrD`).\n *\n * **Last updated:** 2026-04-04.\n */\nconst DEVNET_MARKETS: StaticMarketEntry[] = [\n // Populated from prior discoverMarkets() runs on devnet.\n // These serve as the tier-3 safety net for devnet users.\n];\n\n/**\n * Full static registry indexed by network.\n */\nconst STATIC_REGISTRY: Record<Network, StaticMarketEntry[]> = {\n mainnet: MAINNET_MARKETS,\n devnet: DEVNET_MARKETS,\n};\n\n/**\n * User-provided market entries appended at runtime via {@link registerStaticMarkets}.\n * Keyed by network.\n */\nconst USER_MARKETS: Record<Network, StaticMarketEntry[]> = {\n mainnet: [],\n devnet: [],\n};\n\n/**\n * Get the bundled static market list for a given network.\n *\n * Returns the built-in list merged with any entries added via\n * {@link registerStaticMarkets}. Duplicates (by `slabAddress`) are removed\n * automatically — user-registered entries take precedence.\n *\n * @param network - Target network (`\"mainnet\"` or `\"devnet\"`)\n * @returns Array of static market entries (may be empty if no markets are known)\n *\n * @example\n * ```ts\n * import { getStaticMarkets } from \"@percolator/sdk\";\n *\n * const markets = getStaticMarkets(\"mainnet\");\n * console.log(`${markets.length} known mainnet slab addresses`);\n * ```\n */\nexport function getStaticMarkets(network: Network): StaticMarketEntry[] {\n const builtin = STATIC_REGISTRY[network] ?? [];\n const user = USER_MARKETS[network] ?? [];\n\n if (user.length === 0) return [...builtin];\n\n // Merge: user entries override builtin entries with same slabAddress\n const seen = new Map<string, StaticMarketEntry>();\n for (const entry of builtin) {\n seen.set(entry.slabAddress, entry);\n }\n for (const entry of user) {\n seen.set(entry.slabAddress, entry);\n }\n return [...seen.values()];\n}\n\n/**\n * Register additional static market entries at runtime.\n *\n * Use this to inject known slab addresses before calling `discoverMarkets()`\n * so that tier-3 fallback has addresses to work with — especially useful\n * right after mainnet launch when the bundled list may be empty.\n *\n * Entries are deduplicated by `slabAddress` — calling this multiple times\n * with the same address is safe.\n *\n * @param network - Target network\n * @param entries - One or more static market entries to register\n *\n * @example\n * ```ts\n * import { registerStaticMarkets } from \"@percolator/sdk\";\n *\n * registerStaticMarkets(\"mainnet\", [\n * { slabAddress: \"ABC123...\", symbol: \"SOL-PERP\" },\n * { slabAddress: \"DEF456...\", symbol: \"ETH-PERP\" },\n * ]);\n * ```\n */\nexport function registerStaticMarkets(\n network: Network,\n entries: StaticMarketEntry[],\n): void {\n const existing = USER_MARKETS[network];\n const seen = new Set(existing.map(e => e.slabAddress));\n\n for (const entry of entries) {\n if (!entry.slabAddress) continue;\n if (seen.has(entry.slabAddress)) continue;\n // Validate that slabAddress is a valid base58 public key\n try {\n new PublicKey(entry.slabAddress);\n } catch {\n console.warn(\n `[registerStaticMarkets] Skipping invalid slabAddress: ${entry.slabAddress}`,\n );\n continue;\n }\n seen.add(entry.slabAddress);\n existing.push(entry);\n }\n}\n\n/**\n * Clear all user-registered static market entries for a network.\n *\n * Useful in tests or when resetting state.\n *\n * @param network - Target network to clear (omit to clear all networks)\n */\nexport function clearStaticMarkets(network?: Network): void {\n if (network) {\n USER_MARKETS[network] = [];\n } else {\n USER_MARKETS.mainnet = [];\n USER_MARKETS.devnet = [];\n }\n}\n","import { PublicKey } from \"@solana/web3.js\";\nimport {\n PUMPSWAP_PROGRAM_ID,\n RAYDIUM_CLMM_PROGRAM_ID,\n METEORA_DLMM_PROGRAM_ID,\n} from \"./pda.js\";\n\nexport type DexType = \"pumpswap\" | \"raydium-clmm\" | \"meteora-dlmm\";\n\nexport interface DexPoolInfo {\n dexType: DexType;\n poolAddress: PublicKey;\n baseMint: PublicKey;\n quoteMint: PublicKey;\n baseVault?: PublicKey; // PumpSwap only\n quoteVault?: PublicKey; // PumpSwap only\n}\n\n/**\n * Detect DEX type from the program that owns the pool account.\n *\n * @param ownerProgramId - The program ID that owns the pool account\n * @returns The detected DEX type, or `null` if the owner is not a supported DEX program\n *\n * Supported DEX programs:\n * - PumpSwap (constant-product AMM)\n * - Raydium CLMM (concentrated liquidity)\n * - Meteora DLMM (discretized liquidity)\n */\nexport function detectDexType(ownerProgramId: PublicKey): DexType | null {\n if (ownerProgramId.equals(PUMPSWAP_PROGRAM_ID)) return \"pumpswap\";\n if (ownerProgramId.equals(RAYDIUM_CLMM_PROGRAM_ID)) return \"raydium-clmm\";\n if (ownerProgramId.equals(METEORA_DLMM_PROGRAM_ID)) return \"meteora-dlmm\";\n return null;\n}\n\n/**\n * Parse a DEX pool account into a {@link DexPoolInfo} struct.\n *\n * @param dexType - The type of DEX (pumpswap, raydium-clmm, or meteora-dlmm)\n * @param poolAddress - The on-chain address of the pool account\n * @param data - Raw account data bytes\n * @returns Parsed pool info including mints and (for PumpSwap) vault addresses\n * @throws Error if data is too short for the given DEX type\n */\nexport function parseDexPool(\n dexType: DexType,\n poolAddress: PublicKey,\n data: Uint8Array,\n): DexPoolInfo {\n switch (dexType) {\n case \"pumpswap\":\n return parsePumpSwapPool(poolAddress, data);\n case \"raydium-clmm\":\n return parseRaydiumClmmPool(poolAddress, data);\n case \"meteora-dlmm\":\n return parseMeteoraPool(poolAddress, data);\n }\n}\n\n/**\n * Compute the spot price from a DEX pool in e6 format (i.e., 1.0 = 1_000_000).\n *\n * **SECURITY NOTE:** DEX spot prices have no staleness or confidence checks and are\n * vulnerable to flash-loan manipulation within a single transaction. For high-value\n * markets, prefer Pyth or Chainlink oracles.\n *\n * @param dexType - The type of DEX\n * @param data - Raw pool account data\n * @param vaultData - For PumpSwap only: base and quote vault account data\n * @returns Price in e6 format (quote per base token)\n * @throws Error if data is too short or computation fails\n */\nexport function computeDexSpotPriceE6(\n dexType: DexType,\n data: Uint8Array,\n vaultData?: { base: Uint8Array; quote: Uint8Array },\n): bigint {\n switch (dexType) {\n case \"pumpswap\":\n if (!vaultData) throw new Error(\"PumpSwap requires vaultData (base and quote vault accounts)\");\n return computePumpSwapPriceE6(data, vaultData);\n case \"raydium-clmm\":\n return computeRaydiumClmmPriceE6(data);\n case \"meteora-dlmm\":\n return computeMeteoraDlmmPriceE6(data);\n }\n}\n\n// ============================================================================\n// PumpSwap\n// ============================================================================\n\nconst PUMPSWAP_MIN_LEN = 195;\n\n/**\n * Parse a PumpSwap constant-product AMM pool account.\n * @internal\n */\nfunction parsePumpSwapPool(poolAddress: PublicKey, data: Uint8Array): DexPoolInfo {\n if (data.length < PUMPSWAP_MIN_LEN) {\n throw new Error(`PumpSwap pool data too short: ${data.length} < ${PUMPSWAP_MIN_LEN}`);\n }\n return {\n dexType: \"pumpswap\",\n poolAddress,\n baseMint: new PublicKey(data.slice(35, 67)),\n quoteMint: new PublicKey(data.slice(67, 99)),\n baseVault: new PublicKey(data.slice(131, 163)),\n quoteVault: new PublicKey(data.slice(163, 195)),\n };\n}\n\nconst SPL_TOKEN_AMOUNT_MIN_LEN = 72;\n\n/**\n * Compute PumpSwap price: quote_amount * 1e6 / base_amount.\n * @internal\n */\nfunction computePumpSwapPriceE6(\n _poolData: Uint8Array,\n vaultData: { base: Uint8Array; quote: Uint8Array },\n): bigint {\n if (vaultData.base.length < SPL_TOKEN_AMOUNT_MIN_LEN) {\n throw new Error(`PumpSwap base vault data too short: ${vaultData.base.length} < ${SPL_TOKEN_AMOUNT_MIN_LEN}`);\n }\n if (vaultData.quote.length < SPL_TOKEN_AMOUNT_MIN_LEN) {\n throw new Error(`PumpSwap quote vault data too short: ${vaultData.quote.length} < ${SPL_TOKEN_AMOUNT_MIN_LEN}`);\n }\n\n const baseDv = new DataView(vaultData.base.buffer, vaultData.base.byteOffset, vaultData.base.byteLength);\n const quoteDv = new DataView(vaultData.quote.buffer, vaultData.quote.byteOffset, vaultData.quote.byteLength);\n\n const baseAmount = readU64LE(baseDv, 64);\n const quoteAmount = readU64LE(quoteDv, 64);\n\n if (baseAmount === 0n) return 0n;\n return (quoteAmount * 1_000_000n) / baseAmount;\n}\n\n// ============================================================================\n// Raydium CLMM\n// ============================================================================\n\nconst RAYDIUM_CLMM_MIN_LEN = 269; // need at least through sqrt_price_x64 (253 + 16)\n\n/**\n * Parse a Raydium CLMM (concentrated liquidity) pool account.\n * @internal\n */\nfunction parseRaydiumClmmPool(poolAddress: PublicKey, data: Uint8Array): DexPoolInfo {\n if (data.length < RAYDIUM_CLMM_MIN_LEN) {\n throw new Error(`Raydium CLMM pool data too short: ${data.length} < ${RAYDIUM_CLMM_MIN_LEN}`);\n }\n return {\n dexType: \"raydium-clmm\",\n poolAddress,\n baseMint: new PublicKey(data.slice(73, 105)),\n quoteMint: new PublicKey(data.slice(105, 137)),\n };\n}\n\n/**\n * Compute Raydium CLMM spot price from sqrt_price_x64 (Q64.64 fixed-point).\n *\n * Formula: `price_e6 = (sqrt^2 / 2^128) * 10^(6 + decimals0 - decimals1)`\n *\n * Uses a precision-preserving approach: scales sqrt by 1e6 before shifting,\n * preventing zero results for micro-priced tokens (memecoins where sqrt < 2^64).\n *\n * @internal\n */\nconst MAX_TOKEN_DECIMALS = 24;\n\nfunction computeRaydiumClmmPriceE6(data: Uint8Array): bigint {\n if (data.length < RAYDIUM_CLMM_MIN_LEN) {\n throw new Error(`Raydium CLMM data too short: ${data.length} < ${RAYDIUM_CLMM_MIN_LEN}`);\n }\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\n const decimals0 = data[233];\n const decimals1 = data[234];\n\n if (decimals0 > MAX_TOKEN_DECIMALS || decimals1 > MAX_TOKEN_DECIMALS) {\n throw new Error(\n `Raydium CLMM: decimals out of range (${decimals0}, ${decimals1}); max ${MAX_TOKEN_DECIMALS}`,\n );\n }\n\n const sqrtPriceX64 = readU128LE(dv, 253);\n\n if (sqrtPriceX64 === 0n) return 0n;\n\n // Compute (sqrtPriceX64^2 * 1e6) >> 128 directly using BigInt arbitrary\n // precision. The previous split-shift approach truncated small sqrtPriceX64\n // values (memecoins) to zero due to intermediate >> 64n losing all bits.\n const priceE6Raw = (sqrtPriceX64 * sqrtPriceX64 * 1_000_000n) >> 128n;\n\n const decimalDiff = 6 + decimals0 - decimals1;\n const adjustedDiff = decimalDiff - 6;\n\n if (adjustedDiff >= 0) {\n const scale = 10n ** BigInt(adjustedDiff);\n return priceE6Raw * scale;\n } else {\n const scale = 10n ** BigInt(-adjustedDiff);\n return priceE6Raw / scale;\n }\n}\n\n// ============================================================================\n// Meteora DLMM\n// ============================================================================\n\nconst METEORA_DLMM_MIN_LEN = 145;\n\n/**\n * Parse a Meteora DLMM (discretized liquidity) pool account.\n * @internal\n */\nfunction parseMeteoraPool(poolAddress: PublicKey, data: Uint8Array): DexPoolInfo {\n if (data.length < METEORA_DLMM_MIN_LEN) {\n throw new Error(`Meteora DLMM pool data too short: ${data.length} < ${METEORA_DLMM_MIN_LEN}`);\n }\n return {\n dexType: \"meteora-dlmm\",\n poolAddress,\n baseMint: new PublicKey(data.slice(81, 113)),\n quoteMint: new PublicKey(data.slice(113, 145)),\n };\n}\n\n/**\n * Compute Meteora DLMM spot price from active_id and bin_step.\n *\n * Formula: `price = (1 + bin_step/10000) ^ active_id`\n *\n * Uses binary exponentiation with 1e18 fixed-point precision, then converts to e6.\n * For negative active_id, computes the inverse.\n *\n * @internal\n */\nconst MAX_BIN_STEP = 10_000;\nconst MAX_ACTIVE_ID_ABS = 500_000;\n\nfunction computeMeteoraDlmmPriceE6(data: Uint8Array): bigint {\n if (data.length < METEORA_DLMM_MIN_LEN) {\n throw new Error(`Meteora DLMM data too short: ${data.length} < ${METEORA_DLMM_MIN_LEN}`);\n }\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\n const binStep = dv.getUint16(73, true);\n const activeId = dv.getInt32(76, true);\n\n if (binStep === 0) return 0n;\n if (binStep > MAX_BIN_STEP) {\n throw new Error(`Meteora DLMM: binStep ${binStep} exceeds max ${MAX_BIN_STEP}`);\n }\n if (Math.abs(activeId) > MAX_ACTIVE_ID_ABS) {\n throw new Error(\n `Meteora DLMM: |activeId| ${Math.abs(activeId)} exceeds max ${MAX_ACTIVE_ID_ABS}`,\n );\n }\n\n const MAX_ABS_BIN_ID = 500_000;\n if (activeId > MAX_ABS_BIN_ID || activeId < -MAX_ABS_BIN_ID) {\n throw new Error(\n `Meteora DLMM: activeId ${activeId} exceeds safe range (±${MAX_ABS_BIN_ID})`,\n );\n }\n\n const SCALE = 1_000_000_000_000_000_000n; // 1e18\n const base = SCALE + (BigInt(binStep) * SCALE) / 10_000n;\n\n const isNeg = activeId < 0;\n let exp = isNeg ? BigInt(-activeId) : BigInt(activeId);\n\n let result = SCALE;\n let b = base;\n\n // Limit iterations to ~21 for safety (log2(500_000) + buffer)\n let iterations = 0;\n const MAX_ITERATIONS = 25;\n\n while (exp > 0n) {\n if (iterations++ >= MAX_ITERATIONS) {\n throw new Error(\n `Meteora DLMM: exponentiation loop exceeded ${MAX_ITERATIONS} iterations (activeId=${activeId})`,\n );\n }\n if (exp & 1n) {\n result = (result * b) / SCALE;\n }\n exp >>= 1n;\n if (exp > 0n) {\n b = (b * b) / SCALE;\n }\n }\n\n if (isNeg) {\n if (result === 0n) return 0n;\n return (SCALE * 1_000_000n) / result;\n } else {\n return result / 1_000_000_000_000n; // 1e18 → 1e6\n }\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/** Read a little-endian u64 from a DataView. */\nfunction readU64LE(dv: DataView, offset: number): bigint {\n const lo = BigInt(dv.getUint32(offset, true));\n const hi = BigInt(dv.getUint32(offset + 4, true));\n return lo | (hi << 32n);\n}\n\n/** Read a little-endian u128 from a DataView. */\nfunction readU128LE(dv: DataView, offset: number): bigint {\n const lo = readU64LE(dv, offset);\n const hi = readU64LE(dv, offset + 8);\n return lo | (hi << 64n);\n}\n","/**\n * Oracle account parsing utilities.\n *\n * Chainlink aggregator layout on Solana (from Toly's percolator-cli):\n * offset 138: decimals (u8)\n * offset 216: latest answer (i64 LE)\n *\n * Minimum account size: 224 bytes (offset 216 + 8 bytes for i64).\n *\n * These utilities validate oracle data BEFORE parsing to prevent silent\n * propagation of stale or malformed Chainlink data as price.\n */\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Minimum buffer size to read Chainlink price data */\nconst CHAINLINK_MIN_SIZE = 224; // 216 + 8\n\n/** Maximum reasonable decimals for a price feed */\nconst MAX_DECIMALS = 18;\n\n/** Offset of decimals field in Chainlink aggregator account */\nconst CHAINLINK_DECIMALS_OFFSET = 138;\n\n/** Offset of updated_at timestamp (i64 LE, Unix seconds) in Chainlink aggregator */\nconst CHAINLINK_TIMESTAMP_OFFSET = 168;\n\n/** Offset of latest answer in Chainlink aggregator account */\nconst CHAINLINK_ANSWER_OFFSET = 216;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface OraclePrice {\n price: bigint;\n decimals: number;\n /** Unix timestamp (seconds) of the last oracle update, if available. */\n updatedAt?: number;\n}\n\nexport interface ParseChainlinkOptions {\n /** Maximum allowed staleness in seconds. If the oracle update is older, an error is thrown. */\n maxStalenessSeconds?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Browser-compatible read helpers using DataView\n// ---------------------------------------------------------------------------\n\nfunction readU8(data: Uint8Array, off: number): number {\n return data[off];\n}\n\nfunction readBigInt64LE(data: Uint8Array, off: number): bigint {\n return new DataView(data.buffer, data.byteOffset, data.byteLength).getBigInt64(off, true);\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Parse price data from a Chainlink aggregator account buffer.\n *\n * Validates:\n * - Buffer is large enough to contain the required fields (≥ 224 bytes)\n * - Decimals are in a reasonable range (0-18)\n * - Price is positive (non-zero)\n *\n * @param data - Raw account data from Chainlink aggregator\n * @returns Parsed oracle price with decimals\n * @throws if the buffer is invalid or contains unreasonable data\n */\nexport function parseChainlinkPrice(data: Uint8Array, options?: ParseChainlinkOptions): OraclePrice {\n if (data.length < CHAINLINK_MIN_SIZE) {\n throw new Error(\n `Oracle account data too small: ${data.length} bytes (need at least ${CHAINLINK_MIN_SIZE})`\n );\n }\n\n const decimals = readU8(data, CHAINLINK_DECIMALS_OFFSET);\n if (decimals > MAX_DECIMALS) {\n throw new Error(\n `Oracle decimals out of range: ${decimals} (max ${MAX_DECIMALS})`\n );\n }\n\n const price = readBigInt64LE(data, CHAINLINK_ANSWER_OFFSET);\n if (price <= 0n) {\n throw new Error(\n `Oracle price is non-positive: ${price}`\n );\n }\n\n // Read updated_at timestamp (i64 LE at offset 168)\n const updatedAtBig = readBigInt64LE(data, CHAINLINK_TIMESTAMP_OFFSET);\n const updatedAt = Number(updatedAtBig);\n\n if (options?.maxStalenessSeconds !== undefined && updatedAt > 0) {\n const now = Math.floor(Date.now() / 1000);\n const age = now - updatedAt;\n if (age > options.maxStalenessSeconds) {\n throw new Error(\n `Oracle price is stale: last updated ${age}s ago (max ${options.maxStalenessSeconds}s)`\n );\n }\n }\n\n return { price, decimals, updatedAt: updatedAt > 0 ? updatedAt : undefined };\n}\n\n/**\n * Validate that a buffer looks like a valid Chainlink aggregator account.\n * Returns true if the buffer passes all validation checks, false otherwise.\n * Use this for non-throwing validation.\n */\nexport function isValidChainlinkOracle(data: Uint8Array): boolean {\n try {\n parseChainlinkPrice(data);\n return true;\n } catch {\n return false;\n }\n}\n\n// Re-export constants for consumers\nexport { CHAINLINK_MIN_SIZE, CHAINLINK_DECIMALS_OFFSET, CHAINLINK_TIMESTAMP_OFFSET, CHAINLINK_ANSWER_OFFSET, MAX_DECIMALS };\n","import { Connection, PublicKey } from \"@solana/web3.js\";\nimport { TOKEN_PROGRAM_ID } from \"@solana/spl-token\";\n\n/**\n * Token2022 (Token Extensions) program ID.\n */\nexport const TOKEN_2022_PROGRAM_ID = new PublicKey(\n \"TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb\",\n);\n\n/**\n * Detect which token program owns a given mint account.\n * Returns the owner program ID (TOKEN_PROGRAM_ID or TOKEN_2022_PROGRAM_ID).\n * Throws if the mint account doesn't exist.\n */\nexport async function detectTokenProgram(\n connection: Connection,\n mint: PublicKey,\n): Promise<PublicKey> {\n const info = await connection.getAccountInfo(mint);\n if (!info) throw new Error(`Mint account not found: ${mint.toBase58()}`);\n\n if (info.owner.equals(TOKEN_PROGRAM_ID)) return TOKEN_PROGRAM_ID;\n if (info.owner.equals(TOKEN_2022_PROGRAM_ID)) return TOKEN_2022_PROGRAM_ID;\n\n throw new Error(\n `Mint ${mint.toBase58()} is owned by ${info.owner.toBase58()}, ` +\n `which is neither TOKEN_PROGRAM_ID nor TOKEN_2022_PROGRAM_ID`,\n );\n}\n\n/**\n * Check if a given token program ID is Token2022.\n */\nexport function isToken2022(tokenProgramId: PublicKey): boolean {\n return tokenProgramId.equals(TOKEN_2022_PROGRAM_ID);\n}\n\n/**\n * Check if a given token program ID is the standard SPL Token program.\n */\nexport function isStandardToken(tokenProgramId: PublicKey): boolean {\n return tokenProgramId.equals(TOKEN_PROGRAM_ID);\n}\n","/**\n * @module stake\n * Percolator Insurance LP Staking program — instruction encoders, PDA derivation, and account specs.\n *\n * Program: percolator-stake (dcccrypto/percolator-stake)\n * Deployed devnet: 6aJb1F9CDCVWCNYFwj8aQsVb696YnW6J1FznteHq4Q6k\n * Deployed mainnet: (pending deployment — DevOps must set STAKE_PROGRAM_ID env var or deploy and update STAKE_PROGRAM_IDS.mainnet)\n */\n\nimport { PublicKey, SystemProgram, SYSVAR_RENT_PUBKEY, SYSVAR_CLOCK_PUBKEY } from '@solana/web3.js';\nimport { TOKEN_PROGRAM_ID } from '@solana/spl-token';\nimport { safeEnv } from '../config/program-ids.js';\nimport { concatBytes } from '../abi/encode.js';// ═══════════════════════════════════════════════════════════════\n// Program ID — network-conditional (mirrors program-ids.ts pattern)\n// ═══════════════════════════════════════════════════════════════\n\n/** Known stake program addresses per network. Mainnet is empty until deployed. */\nexport const STAKE_PROGRAM_IDS = {\n devnet: '6aJb1F9CDCVWCNYFwj8aQsVb696YnW6J1FznteHq4Q6k',\n mainnet: '', // TODO: populate once DevOps deploys percolator-stake to mainnet\n} as const;\n\n/**\n * Resolve the stake program ID for the given network.\n *\n * Priority:\n * 1. STAKE_PROGRAM_ID env var (explicit override — DevOps sets this for mainnet until constant is filled)\n * 2. Network-specific constant from STAKE_PROGRAM_IDS\n *\n * Throws a clear error on mainnet when no address is available so callers\n * surface the gap instead of silently hitting the devnet program.\n */\nexport function getStakeProgramId(network?: 'devnet' | 'mainnet'): PublicKey {\n const override = safeEnv('STAKE_PROGRAM_ID');\n if (override) {\n console.warn(\n `[percolator-sdk] STAKE_PROGRAM_ID env override active: ${override} — ensure this points to a trusted program`,\n );\n return new PublicKey(override);\n }\n\n const detectedNetwork =\n network ??\n (() => {\n const n = safeEnv('NEXT_PUBLIC_DEFAULT_NETWORK')?.toLowerCase() ??\n safeEnv('NETWORK')?.toLowerCase() ?? '';\n return n === 'mainnet' || n === 'mainnet-beta' ? 'mainnet' : 'devnet';\n })();\n\n const id = STAKE_PROGRAM_IDS[detectedNetwork];\n if (!id) {\n throw new Error(\n `Stake program not deployed on ${detectedNetwork}. ` +\n `Set STAKE_PROGRAM_ID env var or wait for DevOps to deploy and update STAKE_PROGRAM_IDS.mainnet.`,\n );\n }\n return new PublicKey(id);\n}\n\n/**\n * Default export — resolves for the current runtime network.\n * Use getStakeProgramId() with an explicit network argument where possible.\n *\n * @deprecated Direct use of STAKE_PROGRAM_ID is being phased out in favour of\n * getStakeProgramId() so mainnet callers get a clear error rather than silently\n * resolving to the devnet address.\n */\nexport const STAKE_PROGRAM_ID = new PublicKey(STAKE_PROGRAM_IDS.devnet);\n\n// ═══════════════════════════════════════════════════════════════\n// Instruction Tags (match src/instruction.rs)\n// ═══════════════════════════════════════════════════════════════\n\nexport const STAKE_IX = {\n InitPool: 0,\n Deposit: 1,\n Withdraw: 2,\n FlushToInsurance: 3,\n UpdateConfig: 4,\n TransferAdmin: 5,\n AdminSetOracleAuthority: 6,\n AdminSetRiskThreshold: 7,\n AdminSetMaintenanceFee: 8,\n AdminResolveMarket: 9,\n AdminWithdrawInsurance: 10,\n AdminSetInsurancePolicy: 11,\n /** PERC-272: Accrue trading fees to LP vault */\n AccrueFees: 12,\n /** PERC-272: Init pool in trading LP mode */\n InitTradingPool: 13,\n /** PERC-313: Set HWM config (enable + floor bps) */\n AdminSetHwmConfig: 14,\n /** PERC-303: Enable/configure senior-junior LP tranches */\n AdminSetTrancheConfig: 15,\n /** PERC-303: Deposit into junior (first-loss) tranche */\n DepositJunior: 16,\n} as const;\n\n// ═══════════════════════════════════════════════════════════════\n// PDA Derivation\n// ═══════════════════════════════════════════════════════════════\n\nconst TEXT = new TextEncoder();\n\n/** Derive the stake pool PDA for a given slab (market). */\nexport function deriveStakePool(slab: PublicKey, programId?: PublicKey) {\n return PublicKey.findProgramAddressSync(\n [TEXT.encode('stake_pool'), slab.toBytes()], programId ?? getStakeProgramId(), );\n}\n\n/** Derive the vault authority PDA (signs CPI, owns LP mint + vault). */\nexport function deriveStakeVaultAuth(pool: PublicKey, programId?: PublicKey) {\n return PublicKey.findProgramAddressSync(\n [TEXT.encode('vault_auth'), pool.toBytes()], programId ?? getStakeProgramId(), );\n}\n\n/** Derive the per-user deposit PDA (tracks cooldown, deposit time). */\nexport function deriveDepositPda(pool: PublicKey, user: PublicKey, programId?: PublicKey) {\n return PublicKey.findProgramAddressSync(\n [TEXT.encode('deposit'), pool.toBytes(), user.toBytes()], programId ?? getStakeProgramId(), );\n}\n\n// ═══════════════════════════════════════════════════════════════\n// Browser-safe binary helpers (DataView, no Node.js Buffer dependency)// ═══════════════════════════════════════════════════════════════\n\n/** Read a u64 little-endian from a Uint8Array at the given offset. */\nfunction readU64LE(data: Uint8Array, off: number): bigint {\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n return view.getBigUint64(off, /* littleEndian= */ true);\n}\n\n/** Read a u16 little-endian from a Uint8Array at the given offset. */\nfunction readU16LE(data: Uint8Array, off: number): number {\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n return view.getUint16(off, /* littleEndian= */ true);\n}\n\n// ═══════════════════════════════════════════════════════════════\n// Instruction Encoders\n// ═══════════════════════════════════════════════════════════════\n\nfunction u64Le(v: bigint | number): Uint8Array {\n if (typeof v === \"number\" && !Number.isSafeInteger(v)) {\n throw new Error(`u64Le: number ${v} exceeds Number.MAX_SAFE_INTEGER — use BigInt`);\n }\n const big = BigInt(v);\n if (big < 0n) throw new Error(`u64Le: value must be non-negative, got ${big}`);\n if (big > 0xFFFF_FFFF_FFFF_FFFFn) throw new Error(`u64Le: value exceeds u64 max`);\n const arr = new Uint8Array(8);\n new DataView(arr.buffer).setBigUint64(0, big, true); return arr;\n}\n\nfunction u128Le(v: bigint | number): Uint8Array {\n if (typeof v === \"number\" && !Number.isSafeInteger(v)) {\n throw new Error(`u128Le: number ${v} exceeds Number.MAX_SAFE_INTEGER — use BigInt`);\n }\n const big = BigInt(v);\n if (big < 0n) throw new Error(`u128Le: value must be non-negative, got ${big}`);\n if (big > (1n << 128n) - 1n) throw new Error(`u128Le: value exceeds u128 max`);\n const arr = new Uint8Array(16);\n const view = new DataView(arr.buffer); view.setBigUint64(0, big & 0xFFFFFFFFFFFFFFFFn, true);\n view.setBigUint64(8, big >> 64n, true);\n return arr;\n}\n\nfunction u16Le(v: number): Uint8Array {\n if (!Number.isInteger(v) || v < 0 || v > 0xFFFF) throw new Error(`u16Le: value must be integer in range 0..65535, got ${v}`); const arr = new Uint8Array(2); new DataView(arr.buffer).setUint16(0, v, true);\n return arr;\n}\n\n/** Tag 0: InitPool — create stake pool for a slab. */\nexport function encodeStakeInitPool(cooldownSlots: bigint | number, depositCap: bigint | number): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.InitPool]),\n u64Le(cooldownSlots),\n u64Le(depositCap),\n );\n}\n\n/** Tag 1: Deposit — deposit collateral, receive LP tokens. */\nexport function encodeStakeDeposit(amount: bigint | number): Uint8Array {\n return concatBytes(new Uint8Array([STAKE_IX.Deposit]), u64Le(amount));\n}\n\n/** Tag 2: Withdraw — burn LP tokens, receive collateral (subject to cooldown). */\nexport function encodeStakeWithdraw(lpAmount: bigint | number): Uint8Array {\n return concatBytes(new Uint8Array([STAKE_IX.Withdraw]), u64Le(lpAmount));\n}\n\n/** Tag 3: FlushToInsurance — move collateral from stake vault to wrapper insurance. */\nexport function encodeStakeFlushToInsurance(amount: bigint | number): Uint8Array {\n return concatBytes(new Uint8Array([STAKE_IX.FlushToInsurance]), u64Le(amount));\n}\n\n/** Tag 4: UpdateConfig — update cooldown and/or deposit cap. */\nexport function encodeStakeUpdateConfig(\n newCooldownSlots?: bigint | number,\n newDepositCap?: bigint | number,\n): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.UpdateConfig]),\n new Uint8Array([newCooldownSlots != null ? 1 : 0]),\n u64Le(newCooldownSlots ?? 0n),\n new Uint8Array([newDepositCap != null ? 1 : 0]),\n u64Le(newDepositCap ?? 0n),\n );\n}\n\n/** Tag 5: TransferAdmin — transfer wrapper admin to pool PDA. */\nexport function encodeStakeTransferAdmin(): Uint8Array {\n return new Uint8Array([STAKE_IX.TransferAdmin]);\n}\n\n/** Tag 6: AdminSetOracleAuthority — forward to wrapper via CPI. */\nexport function encodeStakeAdminSetOracleAuthority(newAuthority: PublicKey): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.AdminSetOracleAuthority]),\n newAuthority.toBytes(),\n );\n}\n\n/** Tag 7: AdminSetRiskThreshold — forward to wrapper via CPI. */\nexport function encodeStakeAdminSetRiskThreshold(newThreshold: bigint | number): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.AdminSetRiskThreshold]),\n u128Le(newThreshold),\n );\n}\n\n/** Tag 8: AdminSetMaintenanceFee — forward to wrapper via CPI. */\nexport function encodeStakeAdminSetMaintenanceFee(newFee: bigint | number): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.AdminSetMaintenanceFee]),\n u128Le(newFee),\n );\n}\n\n/** Tag 9: AdminResolveMarket — forward to wrapper via CPI. */\nexport function encodeStakeAdminResolveMarket(): Uint8Array {\n return new Uint8Array([STAKE_IX.AdminResolveMarket]);\n}\n\n/** Tag 10: AdminWithdrawInsurance — withdraw insurance after market resolution. */\nexport function encodeStakeAdminWithdrawInsurance(amount: bigint | number): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.AdminWithdrawInsurance]),\n u64Le(amount),\n );\n}\n\n/** Tag 12: AccrueFees — permissionless: accrue trading fees to LP vault. */\nexport function encodeStakeAccrueFees(): Uint8Array {\n return new Uint8Array([STAKE_IX.AccrueFees]);\n}\n\n/** Tag 13: InitTradingPool — create pool in trading LP mode (pool_mode = 1). */\nexport function encodeStakeInitTradingPool(cooldownSlots: bigint | number, depositCap: bigint | number): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.InitTradingPool]),\n u64Le(cooldownSlots),\n u64Le(depositCap),\n );\n}\n\n/** Tag 14 (PERC-313): AdminSetHwmConfig — enable HWM protection and set floor BPS. */\nexport function encodeStakeAdminSetHwmConfig(\n enabled: boolean,\n hwmFloorBps: number,\n): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.AdminSetHwmConfig]),\n new Uint8Array([enabled ? 1 : 0]),\n u16Le(hwmFloorBps),\n );\n}\n\n/** Tag 15 (PERC-303): AdminSetTrancheConfig — enable senior/junior LP tranches. */\nexport function encodeStakeAdminSetTrancheConfig(juniorFeeMultBps: number): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.AdminSetTrancheConfig]),\n u16Le(juniorFeeMultBps),\n );\n}\n\n/** Tag 16 (PERC-303): DepositJunior — deposit into first-loss junior tranche. */\nexport function encodeStakeDepositJunior(amount: bigint | number): Uint8Array {\n return concatBytes(new Uint8Array([STAKE_IX.DepositJunior]), u64Le(amount));\n}\n\n/** Tag 11: AdminSetInsurancePolicy — set withdrawal policy on wrapper. */\nexport function encodeStakeAdminSetInsurancePolicy(\n authority: PublicKey,\n minWithdrawBase: bigint | number,\n maxWithdrawBps: number,\n cooldownSlots: bigint | number,\n): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.AdminSetInsurancePolicy]),\n authority.toBytes(),\n u64Le(minWithdrawBase),\n u16Le(maxWithdrawBps),\n u64Le(cooldownSlots),\n );\n}\n\n// ═══════════════════════════════════════════════════════════════\n// On-Chain State Layout — StakePool decoded fields\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Decoded StakePool state (352 bytes on-chain).\n * Includes PERC-272 (fee yield), PERC-313 (HWM), and PERC-303 (tranches).\n */\nexport interface StakePoolState {\n isInitialized: boolean;\n bump: number;\n vaultAuthorityBump: number;\n adminTransferred: boolean;\n\n slab: PublicKey;\n admin: PublicKey;\n collateralMint: PublicKey;\n lpMint: PublicKey;\n vault: PublicKey;\n\n totalDeposited: bigint;\n totalLpSupply: bigint;\n cooldownSlots: bigint;\n depositCap: bigint;\n totalFlushed: bigint;\n totalReturned: bigint;\n totalWithdrawn: bigint;\n\n percolatorProgram: PublicKey;\n\n // PERC-272: Fee yield fields\n totalFeesEarned: bigint;\n lastFeeAccrualSlot: bigint;\n lastVaultSnapshot: bigint;\n poolMode: number;\n\n // _reserved layout (64 bytes):\n // [0..8] discriminator\n // [8] version\n // [9..32] PERC-313 HWM\n // [32..51] PERC-303 tranches\n // [51..64] free\n\n // PERC-313: HWM fields (from _reserved[9..32])\n hwmEnabled: boolean;\n epochHighWaterTvl: bigint;\n hwmFloorBps: number;\n\n // PERC-303: Tranche fields (from _reserved[32..51])\n trancheEnabled: boolean;\n juniorBalance: bigint;\n juniorTotalLp: bigint;\n juniorFeeMultBps: number;\n}\n\n/** Size of StakePool on-chain (bytes). */\nexport const STAKE_POOL_SIZE = 352;\n\n/**\n * Decode a StakePool account from raw data buffer. * Uses DataView for all u64/u16 reads — browser-safe.\n */\nexport function decodeStakePool(data: Uint8Array): StakePoolState {\n if (data.length < STAKE_POOL_SIZE) {\n throw new Error(`StakePool data too short: ${data.length} < ${STAKE_POOL_SIZE}`);\n }\n const bytes = new Uint8Array(data.buffer, data.byteOffset, data.byteLength); let off = 0;\n const isInitialized = bytes[off] === 1; off += 1;\n const bump = bytes[off]; off += 1;\n const vaultAuthorityBump = bytes[off]; off += 1;\n const adminTransferred = bytes[off] === 1; off += 1;\n off += 4; // _padding\n\n const slab = new PublicKey(bytes.subarray(off, off + 32)); off += 32;\n const admin = new PublicKey(bytes.subarray(off, off + 32)); off += 32;\n const collateralMint = new PublicKey(bytes.subarray(off, off + 32)); off += 32;\n const lpMint = new PublicKey(bytes.subarray(off, off + 32)); off += 32;\n const vault = new PublicKey(bytes.subarray(off, off + 32)); off += 32;\n\n const totalDeposited = readU64LE(bytes, off); off += 8;\n const totalLpSupply = readU64LE(bytes, off); off += 8;\n const cooldownSlots = readU64LE(bytes, off); off += 8;\n const depositCap = readU64LE(bytes, off); off += 8;\n const totalFlushed = readU64LE(bytes, off); off += 8;\n const totalReturned = readU64LE(bytes, off); off += 8;\n const totalWithdrawn = readU64LE(bytes, off); off += 8;\n\n const percolatorProgram = new PublicKey(bytes.subarray(off, off + 32)); off += 32;\n\n // PERC-272 fields\n const totalFeesEarned = readU64LE(bytes, off); off += 8;\n const lastFeeAccrualSlot = readU64LE(bytes, off); off += 8;\n const lastVaultSnapshot = readU64LE(bytes, off); off += 8;\n const poolMode = bytes[off]; off += 1;\n off += 7; // _mode_padding\n\n // _reserved (64 bytes) starts at off\n const reservedStart = off;\n // _reserved[8] = version (skipped)\n // PERC-313: _reserved[9] = hwm_enabled, [10..26] = epoch_high_water_tvl (u128), [26..28] = hwm_floor_bps (u16)\n const hwmEnabled = bytes[reservedStart + 9] === 1;\n // Read u128 as two u64 parts\n const hwmTvlLow = readU64LE(bytes, reservedStart + 10);\n const hwmTvlHigh = readU64LE(bytes, reservedStart + 18);\n const epochHighWaterTvl = hwmTvlLow | (hwmTvlHigh << 64n);\n const hwmFloorBps = readU16LE(bytes, reservedStart + 26);\n\n // PERC-303: _reserved[32] = tranche_enabled, [33..41] = junior_balance, [41..49] = junior_total_lp, [49..51] = junior_fee_mult_bps\n const trancheEnabled = bytes[reservedStart + 32] === 1;\n const juniorBalance = readU64LE(bytes, reservedStart + 33);\n const juniorTotalLp = readU64LE(bytes, reservedStart + 41);\n const juniorFeeMultBps = readU16LE(bytes, reservedStart + 49);\n\n return {\n isInitialized,\n bump,\n vaultAuthorityBump,\n adminTransferred,\n slab,\n admin,\n collateralMint,\n lpMint,\n vault,\n totalDeposited,\n totalLpSupply,\n cooldownSlots,\n depositCap,\n totalFlushed,\n totalReturned,\n totalWithdrawn,\n percolatorProgram,\n totalFeesEarned,\n lastFeeAccrualSlot,\n lastVaultSnapshot,\n poolMode,\n hwmEnabled,\n epochHighWaterTvl,\n hwmFloorBps,\n trancheEnabled,\n juniorBalance,\n juniorTotalLp,\n juniorFeeMultBps,\n };\n}\n\n// ═══════════════════════════════════════════════════════════════\n// Account Specs (for building TransactionInstructions)\n// ═══════════════════════════════════════════════════════════════\n\nexport interface StakeAccounts {\n /** InitPool accounts */\n initPool: {\n admin: PublicKey;\n slab: PublicKey;\n pool: PublicKey;\n lpMint: PublicKey;\n vault: PublicKey;\n vaultAuth: PublicKey;\n collateralMint: PublicKey;\n percolatorProgram: PublicKey;\n };\n /** Deposit accounts */\n deposit: {\n user: PublicKey;\n pool: PublicKey;\n userCollateralAta: PublicKey;\n vault: PublicKey;\n lpMint: PublicKey;\n userLpAta: PublicKey;\n vaultAuth: PublicKey;\n depositPda: PublicKey;\n };\n /** Withdraw accounts */\n withdraw: {\n user: PublicKey;\n pool: PublicKey;\n userLpAta: PublicKey;\n lpMint: PublicKey;\n vault: PublicKey;\n userCollateralAta: PublicKey;\n vaultAuth: PublicKey;\n depositPda: PublicKey;\n };\n /** FlushToInsurance accounts (CPI from stake → percolator) */\n flushToInsurance: {\n caller: PublicKey;\n pool: PublicKey;\n vault: PublicKey;\n vaultAuth: PublicKey;\n slab: PublicKey;\n wrapperVault: PublicKey;\n percolatorProgram: PublicKey;\n };\n}\n\n/**\n * Build account keys for InitPool instruction.\n * Returns array of {pubkey, isSigner, isWritable} in the order the program expects.\n */\nexport function initPoolAccounts(a: StakeAccounts['initPool']) {\n return [\n { pubkey: a.admin, isSigner: true, isWritable: true },\n { pubkey: a.slab, isSigner: false, isWritable: false },\n { pubkey: a.pool, isSigner: false, isWritable: true },\n { pubkey: a.lpMint, isSigner: false, isWritable: true },\n { pubkey: a.vault, isSigner: false, isWritable: true },\n { pubkey: a.vaultAuth, isSigner: false, isWritable: false },\n { pubkey: a.collateralMint, isSigner: false, isWritable: false },\n { pubkey: a.percolatorProgram, isSigner: false, isWritable: false },\n { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },\n { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },\n { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },\n ];\n}\n\n/**\n * Build account keys for Deposit instruction.\n */\nexport function depositAccounts(a: StakeAccounts['deposit']) {\n return [\n { pubkey: a.user, isSigner: true, isWritable: false },\n { pubkey: a.pool, isSigner: false, isWritable: true },\n { pubkey: a.userCollateralAta, isSigner: false, isWritable: true },\n { pubkey: a.vault, isSigner: false, isWritable: true },\n { pubkey: a.lpMint, isSigner: false, isWritable: true },\n { pubkey: a.userLpAta, isSigner: false, isWritable: true },\n { pubkey: a.vaultAuth, isSigner: false, isWritable: false },\n { pubkey: a.depositPda, isSigner: false, isWritable: true },\n { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },\n { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },\n { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },\n ];\n}\n\n/**\n * Build account keys for Withdraw instruction.\n */\nexport function withdrawAccounts(a: StakeAccounts['withdraw']) {\n return [\n { pubkey: a.user, isSigner: true, isWritable: false },\n { pubkey: a.pool, isSigner: false, isWritable: true },\n { pubkey: a.userLpAta, isSigner: false, isWritable: true },\n { pubkey: a.lpMint, isSigner: false, isWritable: true },\n { pubkey: a.vault, isSigner: false, isWritable: true },\n { pubkey: a.userCollateralAta, isSigner: false, isWritable: true },\n { pubkey: a.vaultAuth, isSigner: false, isWritable: false },\n { pubkey: a.depositPda, isSigner: false, isWritable: true },\n { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },\n { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },\n ];\n}\n\n/**\n * Build account keys for FlushToInsurance instruction.\n */\nexport function flushToInsuranceAccounts(a: StakeAccounts['flushToInsurance']) {\n return [\n { pubkey: a.caller, isSigner: true, isWritable: false },\n { pubkey: a.pool, isSigner: false, isWritable: true },\n { pubkey: a.vault, isSigner: false, isWritable: true },\n { pubkey: a.vaultAuth, isSigner: false, isWritable: false },\n { pubkey: a.slab, isSigner: false, isWritable: true },\n { pubkey: a.wrapperVault, isSigner: false, isWritable: true },\n { pubkey: a.percolatorProgram, isSigner: false, isWritable: false },\n { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },\n ];\n}\n","import { PublicKey } from \"@solana/web3.js\";\n\n/**\n * Read an environment variable safely. Returns `undefined` in browser\n * environments where `process` is not defined, avoiding a\n * `ReferenceError` crash at import time.\n */\nexport function safeEnv(key: string): string | undefined {\n try {\n return typeof process !== \"undefined\" && process?.env\n ? process.env[key]\n : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Centralized PROGRAM_ID configuration\n * \n * Default to environment variable, then fall back to network-specific defaults.\n * This prevents hard-coded program IDs scattered across the codebase.\n */\n\nexport const PROGRAM_IDS = {\n devnet: {\n percolator: \"FxfD37s1AZTeWfFQps9Zpebi2dNQ9QSSDtfMKdbsfKrD\",\n matcher: \"GTRgyTDfrMvBubALAqtHuQwT8tbGyXid7svXZKtWfC9k\",\n },\n mainnet: {\n percolator: \"GM8zjJ8LTBMv9xEsverh6H6wLyevgMHEJXcEzyY3rY24\",\n matcher: \"DHP6DtwXP1yJsz8YzfoeigRFPB979gzmumkmCxDLSkUX\",\n },\n} as const;\n\nexport type Network = \"devnet\" | \"mainnet\";\n\n/**\n * Get the Percolator program ID for the current network\n * \n * Priority:\n * 1. PROGRAM_ID env var (explicit override)\n * 2. Network-specific default (NETWORK env var)\n * 3. Devnet default (safest fallback — bug bounty PERC-697)\n */\nexport function getProgramId(network?: Network): PublicKey {\n // Only allow env override when no explicit network is provided —\n // an explicit parameter should always take precedence to prevent\n // silent program substitution via environment variable injection.\n if (!network) {\n const override = safeEnv(\"PROGRAM_ID\");\n if (override) {\n console.warn(\n `[percolator-sdk] PROGRAM_ID env override active: ${override} — ensure this points to a trusted program`,\n );\n return new PublicKey(override);\n }\n }\n\n // Use provided network or detect from env — default to devnet (never mainnet silently)\n const detectedNetwork = getCurrentNetwork();\n const targetNetwork = network ?? detectedNetwork;\n const programId = PROGRAM_IDS[targetNetwork].percolator;\n\n return new PublicKey(programId);\n}\n\n/**\n * Get the Matcher program ID for the current network\n */\nexport function getMatcherProgramId(network?: Network): PublicKey {\n if (!network) {\n const override = safeEnv(\"MATCHER_PROGRAM_ID\");\n if (override) {\n console.warn(\n `[percolator-sdk] MATCHER_PROGRAM_ID env override active: ${override} — ensure this points to a trusted program`,\n );\n return new PublicKey(override);\n }\n }\n\n // Use provided network or detect from env — default to devnet (never mainnet silently)\n const detectedNetwork = getCurrentNetwork();\n const targetNetwork = network ?? detectedNetwork;\n const programId = PROGRAM_IDS[targetNetwork].matcher;\n\n if (!programId) {\n throw new Error(`Matcher program not deployed on ${targetNetwork}`);\n }\n\n return new PublicKey(programId);\n}\n\n/**\n * Get the current network from environment.\n *\n * SECURITY (PERC-697): Removed silent mainnet default.\n * Previously defaulted to \"mainnet\" when NETWORK was unset, which could cause\n * crank/keeper scripts run without env vars to silently target mainnet program IDs.\n *\n * Now defaults to \"devnet\" — the safer fallback for a devnet-first protocol.\n * Production deployments always set NETWORK explicitly via Railway/env.\n * For mainnet operations use networkValidation.ts (ensureNetworkConfigValid) which\n * enforces FORCE_MAINNET=1.\n */\nexport function getCurrentNetwork(): Network {\n const network = safeEnv(\"NETWORK\")?.toLowerCase();\n if (network === \"mainnet\" || network === \"mainnet-beta\") {\n return \"mainnet\";\n }\n // devnet, testnet, or unset → devnet (fail-open to devnet, not mainnet)\n return \"devnet\";\n}\n","/**\n * @module adl\n * Percolator ADL (Auto-Deleveraging) client utilities.\n *\n * PERC-8278 / PERC-8312 / PERC-305: ADL is triggered when `pnl_pos_tot > max_pnl_cap`\n * on a market (PnL cap exceeded) AND the insurance fund is fully depleted (balance == 0).\n * The most profitable positions on the dominant side are deleveraged first.\n *\n * **Note on caller permissions:** `ExecuteAdl` (tag 50) requires the caller to be the\n * market admin/keeper key (`header.admin`). It is NOT permissionless despite the\n * instruction being structurally available to any signer.\n *\n * API surface:\n * - fetchAdlRankedPositions() — fetch slab + rank all open positions by PnL%\n * - rankAdlPositions() — pure (no-RPC) variant for already-fetched slab bytes\n * - isAdlTriggered() — check if slab's pnl_pos_tot exceeds max_pnl_cap\n * - buildAdlInstruction() — build a single ExecuteAdl TransactionInstruction\n * - buildAdlTransaction() — fetch + rank + pick top target + return instruction\n * - parseAdlEvent() — decode AdlEvent from transaction log lines\n * - fetchAdlRankings() — call /api/adl/rankings HTTP endpoint\n * - AdlRankedPosition — position record with adl_rank and computed pnlPct\n * - AdlRankingResult — full ranking with trigger status\n * - AdlEvent — decoded on-chain AdlEvent log entry (tag 0xAD1E_0001)\n * - AdlApiRanking — single ranked position from /api/adl/rankings\n * - AdlApiResult — full result from /api/adl/rankings\n * - AdlSide — \"long\" | \"short\"\n */\n\nimport {\n Connection,\n PublicKey,\n TransactionInstruction,\n AccountMeta,\n SYSVAR_CLOCK_PUBKEY,\n} from \"@solana/web3.js\";\nimport {\n fetchSlab,\n parseAllAccounts,\n parseEngine,\n parseConfig,\n detectSlabLayout,\n AccountKind,\n Account,\n SlabLayout,\n} from \"./slab.js\";\nimport { encodeExecuteAdl } from \"../abi/instructions.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Position side derived from positionSize sign. */\nexport type AdlSide = \"long\" | \"short\";\n\n/**\n * A ranked open position for ADL purposes.\n * Positions are ranked descending by `pnlPct` — rank 0 is the most profitable\n * and will be deleveraged first.\n */\nexport interface AdlRankedPosition {\n /** Account index in the slab (used as `targetIdx` in ExecuteAdl). */\n idx: number;\n /** Owner public key. */\n owner: PublicKey;\n /** Raw position size (i128 — negative = short, positive = long). */\n positionSize: bigint;\n /** Realised + mark-to-market PnL in lamports (i128 from slab). */\n pnl: bigint;\n /** Capital at entry in lamports (u128). */\n capital: bigint;\n /**\n * PnL as a fraction of capital, expressed as basis points (scaled × 10_000).\n * pnlPct = pnl * 10_000 / capital.\n * Higher = more profitable = deleveraged first.\n */\n pnlPct: bigint;\n /** Long or short. */\n side: AdlSide;\n /**\n * ADL rank among positions on the same side (0 = highest PnL%, deleveraged first).\n * `-1` if position size is zero (inactive).\n */\n adlRank: number;\n}\n\n/**\n * Result of `fetchAdlRankedPositions`.\n */\nexport interface AdlRankingResult {\n /** All open (non-zero) user positions, sorted descending by PnLPct, ranked. */\n ranked: AdlRankedPosition[];\n /**\n * Longs ranked separately (adlRank within this subset).\n * Rank 0 = most profitable long = first to be deleveraged on a net-long market.\n */\n longs: AdlRankedPosition[];\n /**\n * Shorts ranked separately (adlRank within this subset).\n * Rank 0 = most profitable short (most negative pnlPct magnitude — i.e., highest\n * unrealised gain for the short-side holder).\n */\n shorts: AdlRankedPosition[];\n /** Whether ADL is currently triggered (pnlPosTot > maxPnlCap). */\n isTriggered: boolean;\n /** pnl_pos_tot from engine state. */\n pnlPosTot: bigint;\n /** max_pnl_cap from market config. */\n maxPnlCap: bigint;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Compute PnL% in basis points for a position.\n * Returns 0n when capital is 0 to avoid division by zero.\n */\nfunction computePnlPct(pnl: bigint, capital: bigint): bigint {\n if (capital === 0n) return 0n;\n return (pnl * 10_000n) / capital;\n}\n\n// ---------------------------------------------------------------------------\n// Core API\n// ---------------------------------------------------------------------------\n\n/**\n * Check whether ADL is currently triggered on a slab.\n *\n * ADL triggers when pnl_pos_tot > max_pnl_cap (max_pnl_cap must be > 0).\n *\n * @param slabData - Raw slab account bytes.\n * @returns true if ADL is triggered.\n *\n * @example\n * ```ts\n * const data = await fetchSlab(connection, slabKey);\n * if (isAdlTriggered(data)) {\n * const ranking = await fetchAdlRankedPositions(connection, slabKey);\n * }\n * ```\n */\nexport function isAdlTriggered(slabData: Uint8Array): boolean {\n const layout = detectSlabLayout(slabData.length);\n if (!layout) {\n return false;\n }\n try {\n const engine = parseEngine(slabData);\n if (engine.pnlPosTot === 0n) return false;\n const config = parseConfig(slabData, layout);\n if (config.maxPnlCap === 0n) return false;\n return engine.pnlPosTot > config.maxPnlCap;\n } catch {\n return false;\n }\n}\n\n/**\n * Fetch a slab and rank all open user positions by PnL% for ADL targeting.\n *\n * Positions are ranked separately per side:\n * - Longs: rank 0 = highest positive PnL% (most profitable long)\n * - Shorts: rank 0 = highest negative PnL% by abs value (most profitable short)\n *\n * Rank ordering matches the on-chain ADL engine in percolator-prog (PERC-8273):\n * the position at rank 0 of the dominant side is deleveraged first.\n *\n * @param connection - Solana connection.\n * @param slab - Slab (market) public key.\n * @returns AdlRankingResult with ranked longs, ranked shorts, and trigger status.\n *\n * @example\n * ```ts\n * const { ranked, longs, isTriggered } = await fetchAdlRankedPositions(connection, slabKey);\n * if (isTriggered && longs.length > 0) {\n * const target = longs[0]; // highest PnL long\n * const ix = buildAdlInstruction(caller, slabKey, oracleKey, programId, target.idx);\n * }\n * ```\n */\nexport async function fetchAdlRankedPositions(\n connection: Connection,\n slab: PublicKey\n): Promise<AdlRankingResult> {\n const data = await fetchSlab(connection, slab);\n return rankAdlPositions(data);\n}\n\n/**\n * Pure (no-RPC) variant — rank positions from already-fetched slab bytes.\n * Useful when you already have the slab data (e.g., from a subscription).\n */\nexport function rankAdlPositions(slabData: Uint8Array): AdlRankingResult {\n const layout = detectSlabLayout(slabData.length);\n\n let pnlPosTot = 0n;\n try {\n const engine = parseEngine(slabData);\n pnlPosTot = engine.pnlPosTot;\n } catch (err) {\n console.warn(\n `[rankAdlPositions] parseEngine failed:`,\n err instanceof Error ? err.message : err,\n );\n }\n\n let maxPnlCap = 0n;\n let isTriggered = false;\n if (layout) {\n try {\n const config = parseConfig(slabData, layout);\n maxPnlCap = config.maxPnlCap;\n isTriggered = maxPnlCap > 0n && pnlPosTot > maxPnlCap;\n } catch {\n // If config parse fails, leave isTriggered=false; ranking still useful.\n }\n }\n\n // Parse all used accounts.\n const accounts = parseAllAccounts(slabData);\n\n // Build ranked position list (user accounts with non-zero position only).\n const positions: AdlRankedPosition[] = [];\n for (const { idx, account } of accounts) {\n if (account.kind !== AccountKind.User) continue;\n if (account.positionSize === 0n) continue;\n\n // Determine side from sign convention: long (> 0), short (< 0).\n // If positionSize is 0, it was already skipped above.\n const side: AdlSide = account.positionSize > 0n ? \"long\" : \"short\";\n\n // Validate sign convention: longs must be positive, shorts must be negative.\n if (side === \"long\" && account.positionSize <= 0n) {\n console.warn(`[fetchAdlRankedPositions] account idx=${idx}: side=long but positionSize=${account.positionSize}`);\n continue;\n }\n if (side === \"short\" && account.positionSize >= 0n) {\n console.warn(`[fetchAdlRankedPositions] account idx=${idx}: side=short but positionSize=${account.positionSize}`);\n continue;\n }\n\n // For shorts, positionSize is negative — PnL computation is symmetric:\n // a short profits when price falls, so pnl stored in the slab already\n // reflects mark-to-market gain/loss for both sides.\n const pnlPct = computePnlPct(account.pnl, account.capital);\n\n positions.push({\n idx,\n owner: account.owner,\n positionSize: account.positionSize,\n pnl: account.pnl,\n capital: account.capital,\n pnlPct,\n side,\n adlRank: -1, // assigned below\n });\n }\n\n // Rank longs: descending pnlPct (most profitable first).\n const longs = positions\n .filter(p => p.side === \"long\")\n .sort((a, b) => (b.pnlPct > a.pnlPct ? 1 : b.pnlPct < a.pnlPct ? -1 : 0));\n longs.forEach((p, i) => { p.adlRank = i; });\n\n // Rank shorts: descending pnlPct (most profitable short = highest pnlPct\n // magnitude, but pnlPct can be negative; sort descending still puts\n // the \"least negative\" aka \"most profitable\" short first).\n const shorts = positions\n .filter(p => p.side === \"short\")\n .sort((a, b) => (b.pnlPct > a.pnlPct ? 1 : b.pnlPct < a.pnlPct ? -1 : 0));\n shorts.forEach((p, i) => { p.adlRank = i; });\n\n // Overall ranked list = longs + shorts merged, still sorted by pnlPct desc.\n const ranked = [...longs, ...shorts].sort(\n (a, b) => (b.pnlPct > a.pnlPct ? 1 : b.pnlPct < a.pnlPct ? -1 : 0)\n );\n\n return { ranked, longs, shorts, isTriggered, pnlPosTot, maxPnlCap };\n}\n\n/**\n * Build a single `ExecuteAdl` TransactionInstruction (tag 50, PERC-305).\n *\n * Does NOT fetch the slab or check trigger status — use `fetchAdlRankedPositions`\n * first to determine the correct `targetIdx`.\n *\n * **Caller requirement:** The on-chain handler requires the caller to be the market\n * admin/keeper authority (`header.admin`). Passing any other signer will result in\n * `EngineUnauthorized`.\n *\n * @param caller - Signer — must be the market keeper/admin authority.\n * @param slab - Slab (market) public key.\n * @param oracle - Primary oracle public key for this market.\n * @param programId - Percolator program ID.\n * @param targetIdx - Account index to deleverage (from `AdlRankedPosition.idx`).\n * @param backupOracles - Optional additional oracle accounts (non-Hyperp markets).\n *\n * @example\n * ```ts\n * import { fetchAdlRankedPositions, buildAdlInstruction } from \"@percolator/sdk\";\n *\n * const { longs, isTriggered } = await fetchAdlRankedPositions(connection, slabKey);\n * if (isTriggered && longs.length > 0) {\n * const ix = buildAdlInstruction(\n * caller.publicKey, slabKey, oracleKey, PROGRAM_ID, longs[0].idx\n * );\n * await sendAndConfirmTransaction(connection, new Transaction().add(ix), [caller]);\n * }\n * ```\n */\nexport function buildAdlInstruction(\n caller: PublicKey,\n slab: PublicKey,\n oracle: PublicKey,\n programId: PublicKey,\n targetIdx: number,\n backupOracles: PublicKey[] = []\n): TransactionInstruction {\n if (!Number.isInteger(targetIdx) || targetIdx < 0) {\n throw new Error(\n `buildAdlInstruction: targetIdx must be a non-negative integer, got ${targetIdx}`,\n );\n }\n const dataBytes = encodeExecuteAdl({ targetIdx });\n const data = Buffer.from(dataBytes);\n\n const keys: AccountMeta[] = [\n { pubkey: caller, isSigner: true, isWritable: false },\n { pubkey: slab, isSigner: false, isWritable: true },\n { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },\n { pubkey: oracle, isSigner: false, isWritable: false },\n ...backupOracles.map(k => ({ pubkey: k, isSigner: false, isWritable: false })),\n ];\n\n return new TransactionInstruction({ keys, programId, data });\n}\n\n/**\n * Convenience builder: fetch slab, rank positions, pick the highest-ranked\n * target on the given side, and return a ready-to-send `TransactionInstruction`.\n *\n * Returns `null` when ADL is not triggered or no eligible positions exist.\n *\n * @param connection - Solana connection.\n * @param caller - Signer — must be the market keeper/admin authority.\n * @param slab - Slab (market) public key.\n * @param oracle - Primary oracle public key.\n * @param programId - Percolator program ID.\n * @param preferSide - Optional: target \"long\" or \"short\" side only.\n * If omitted, picks the overall top-ranked position.\n * @param backupOracles - Optional extra oracle accounts.\n *\n * @example\n * ```ts\n * const ix = await buildAdlTransaction(\n * connection, caller.publicKey, slabKey, oracleKey, PROGRAM_ID\n * );\n * if (ix) {\n * await sendAndConfirmTransaction(connection, new Transaction().add(ix), [caller]);\n * }\n * ```\n */\nexport async function buildAdlTransaction(\n connection: Connection,\n caller: PublicKey,\n slab: PublicKey,\n oracle: PublicKey,\n programId: PublicKey,\n preferSide?: AdlSide,\n backupOracles: PublicKey[] = []\n): Promise<TransactionInstruction | null> {\n const ranking = await fetchAdlRankedPositions(connection, slab);\n\n if (!ranking.isTriggered) return null;\n\n let target: AdlRankedPosition | undefined;\n if (preferSide === \"long\") {\n target = ranking.longs[0];\n } else if (preferSide === \"short\") {\n target = ranking.shorts[0];\n } else {\n target = ranking.ranked[0];\n }\n\n if (!target) return null;\n\n return buildAdlInstruction(caller, slab, oracle, programId, target.idx, backupOracles);\n}\n\n// ---------------------------------------------------------------------------\n// AdlEvent — on-chain log decoder (PERC-8312)\n// ---------------------------------------------------------------------------\n\n/**\n * Decoded on-chain AdlEvent emitted by the `ExecuteAdl` instruction handler.\n *\n * The on-chain handler emits via `sol_log_64(0xAD1E_0001, target_idx, price, closed_lo, closed_hi)`.\n * `sol_log_64` prints 5 decimal u64 values separated by spaces on a single \"Program log:\" line.\n *\n * Fields:\n * - `tag` — always `0xAD1E_0001` (2970353665n)\n * - `targetIdx` — slab account index that was deleveraged\n * - `price` — oracle price used (in market price units, e.g. e6)\n * - `closedAbs` — absolute size of the position closed (i128, reassembled from lo+hi u64 parts)\n *\n * @example\n * ```ts\n * const logs = tx.meta?.logMessages ?? [];\n * const event = parseAdlEvent(logs);\n * if (event) {\n * console.log(\"ADL closed position\", event.targetIdx, \"size\", event.closedAbs);\n * }\n * ```\n */\nexport interface AdlEvent {\n /** Tag discriminator — always 0xAD1E_0001n (2970353665). */\n tag: bigint;\n /** Slab account index that was deleveraged. */\n targetIdx: number;\n /** Oracle price used for the deleverage (market-native units, e.g. lamports/e6). */\n price: bigint;\n /**\n * Absolute position size closed (reassembled from lo+hi u64).\n * This is the i128 absolute value — always non-negative.\n */\n closedAbs: bigint;\n}\n\n/** Magic discriminator for the ADL event log line. */\nconst ADL_EVENT_TAG = 0xAD1E_0001n;\n\n/**\n * Parse the AdlEvent from a transaction's log messages.\n *\n * Searches for a \"Program log: <a> <b> <c> <d> <e>\" line where the first\n * decimal value equals `0xAD1E_0001` (2970353665). Returns `null` if not found.\n *\n * @param logs - Array of log message strings (from `tx.meta.logMessages`).\n * @returns Decoded `AdlEvent` or `null` if the log is not present.\n *\n * @example\n * ```ts\n * const event = parseAdlEvent(tx.meta?.logMessages ?? []);\n * if (event) {\n * console.log(`ADL: idx=${event.targetIdx} price=${event.price} closed=${event.closedAbs}`);\n * }\n * ```\n */\nexport function parseAdlEvent(logs: string[]): AdlEvent | null {\n for (const line of logs) {\n if (typeof line !== \"string\") continue;\n // sol_log_64 emits: \"Program log: a b c d e\" (5 space-separated decimals)\n const match = line.match(\n /^Program log: (\\d+) (\\d+) (\\d+) (\\d+) (\\d+)$/,\n );\n if (!match) continue;\n\n let tag: bigint;\n try {\n tag = BigInt(match[1]);\n } catch {\n continue;\n }\n\n if (tag !== ADL_EVENT_TAG) continue;\n\n try {\n const targetIdxBig = BigInt(match[2]);\n // Validate that targetIdx fits in u16 range before converting to Number\n if (targetIdxBig < 0n || targetIdxBig > 65535n) {\n continue;\n }\n const targetIdx = Number(targetIdxBig);\n const price = BigInt(match[3]);\n const closedLo = BigInt(match[4]);\n const closedHi = BigInt(match[5]);\n // Reassemble i128 from lo/hi u64 parts (little-endian split).\n const closedAbs = (closedHi << 64n) | closedLo;\n return { tag, targetIdx, price, closedAbs };\n } catch {\n continue;\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// fetchAdlRankings — HTTP client for /api/adl/rankings (PERC-8312)\n// ---------------------------------------------------------------------------\n\n/**\n * A single ranked position as returned by the /api/adl/rankings endpoint.\n */\nexport interface AdlApiRanking {\n /** 1-based rank (1 = highest PnL%, first to be deleveraged). */\n rank: number;\n /** Slab account index. Pass as `targetIdx` to `buildAdlInstruction`. */\n idx: number;\n /** Absolute PnL (lamports) as a decimal string. */\n pnlAbs: string;\n /** Capital at entry (lamports) as a decimal string. */\n capital: string;\n /** PnL as millionths of capital (pnl * 1_000_000 / capital). */\n pnlPctMillionths: string;\n}\n\n/**\n * Full result from the /api/adl/rankings endpoint.\n */\nexport interface AdlApiResult {\n slabAddress: string;\n /** pnl_pos_tot from slab engine state (decimal string). */\n pnlPosTot: string;\n /** max_pnl_cap from market config (decimal string, \"0\" if unconfigured). */\n maxPnlCap: string;\n /** Insurance fund balance (decimal string). */\n insuranceFundBalance: string;\n /** Insurance fund lifetime fee revenue (decimal string). */\n insuranceFundFeeRevenue: string;\n /** Insurance utilization in basis points (0–10000). */\n insuranceUtilizationBps: number;\n /** true if pnlPosTot > maxPnlCap. */\n capExceeded: boolean;\n /** true if insurance fund is fully depleted (balance == 0). */\n insuranceDepleted: boolean;\n /** true if utilization BPS exceeds the configured ADL threshold. */\n utilizationTriggered: boolean;\n /** true if ADL is needed (capExceeded or utilizationTriggered). */\n adlNeeded: boolean;\n /** Excess PnL above cap (decimal string). */\n excess: string;\n /** Ranked positions (empty if adlNeeded=false). */\n rankings: AdlApiRanking[];\n}\n\n/**\n * Fetch ADL rankings from the Percolator API.\n *\n * Calls `GET <apiBase>/api/adl/rankings?slab=<address>` and returns the\n * parsed result. Use this from the frontend or keeper to determine ADL\n * trigger status and pick the target index.\n *\n * @param apiBase - Base URL of the Percolator API (e.g. `https://api.percolator.io`).\n * @param slab - Slab (market) public key or base58 address string.\n * @param fetchFn - Optional custom fetch implementation (defaults to global `fetch`).\n * @returns Parsed `AdlApiResult`.\n * @throws On HTTP error or JSON parse failure.\n *\n * @example\n * ```ts\n * const result = await fetchAdlRankings(\"https://api.percolator.io\", slabKey);\n * if (result.adlNeeded && result.rankings.length > 0) {\n * const target = result.rankings[0]; // rank 1 = highest PnL%\n * const ix = buildAdlInstruction(caller, slabKey, oracleKey, PROGRAM_ID, target.idx);\n * }\n * ```\n */\nexport async function fetchAdlRankings(\n apiBase: string,\n slab: PublicKey | string,\n fetchFn: typeof fetch = fetch,\n): Promise<AdlApiResult> {\n const slabStr = typeof slab === \"string\" ? slab : slab.toBase58();\n const base = apiBase.replace(/\\/$/, \"\");\n const url = `${base}/api/adl/rankings?slab=${encodeURIComponent(slabStr)}`;\n\n const res = await fetchFn(url);\n if (!res.ok) {\n let body = \"\";\n try { body = await res.text(); } catch { /* ignore */ }\n throw new Error(\n `fetchAdlRankings: HTTP ${res.status} from ${url}${body ? ` — ${body}` : \"\"}`,\n );\n }\n\n const json: unknown = await res.json();\n\n // Runtime validation — the API response shape is not guaranteed\n if (typeof json !== \"object\" || json === null) {\n throw new Error(\"fetchAdlRankings: API returned non-object response\");\n }\n const obj = json as Record<string, unknown>;\n if (!Array.isArray(obj.rankings)) {\n throw new Error(\"fetchAdlRankings: API response missing rankings array\");\n }\n for (const entry of obj.rankings) {\n if (typeof entry !== \"object\" || entry === null) {\n throw new Error(\"fetchAdlRankings: invalid ranking entry (not an object)\");\n }\n const r = entry as Record<string, unknown>;\n if (typeof r.idx !== \"number\" || !Number.isInteger(r.idx) || r.idx < 0) {\n throw new Error(`fetchAdlRankings: invalid ranking idx: ${r.idx}`);\n }\n }\n\n return json as AdlApiResult;\n}\n","import {\n Connection,\n type Commitment,\n type ConnectionConfig,\n} from \"@solana/web3.js\";\n\n// ---------------------------------------------------------------------------\n// Configuration Types\n// ---------------------------------------------------------------------------\n\n/**\n * Configuration for exponential-backoff retry on RPC calls.\n *\n * @example\n * ```ts\n * const retryConfig: RetryConfig = {\n * maxRetries: 3,\n * baseDelayMs: 500,\n * maxDelayMs: 10_000,\n * retryableStatusCodes: [429, 502, 503],\n * };\n * ```\n */\nexport interface RetryConfig {\n /**\n * Maximum number of retry attempts after the initial request fails.\n * @default 3\n */\n maxRetries?: number;\n\n /**\n * Base delay in ms for exponential backoff.\n * Delay for attempt N is: `min(baseDelayMs * 2^N, maxDelayMs) + jitter`.\n * @default 500\n */\n baseDelayMs?: number;\n\n /**\n * Maximum delay in ms (backoff cap).\n * @default 10_000\n */\n maxDelayMs?: number;\n\n /**\n * Jitter factor (0–1). Applied as random `[0, jitterFactor * delay]` addition.\n * @default 0.25\n */\n jitterFactor?: number;\n\n /**\n * HTTP status codes considered retryable.\n * Errors matching these codes (or containing their string representation)\n * will be retried.\n * @default [429, 502, 503, 504]\n */\n retryableStatusCodes?: number[];\n}\n\n/**\n * Configuration for a single RPC endpoint in the pool.\n *\n * @example\n * ```ts\n * const endpoint: RpcEndpointConfig = {\n * url: \"https://mainnet.helius-rpc.com/?api-key=YOUR_KEY\",\n * weight: 10,\n * label: \"helius-primary\",\n * };\n * ```\n */\nexport interface RpcEndpointConfig {\n /** RPC endpoint URL. */\n url: string;\n\n /**\n * Relative weight for round-robin selection.\n * Higher weight = more requests routed here.\n * @default 1\n */\n weight?: number;\n\n /**\n * Human-readable label for logging / diagnostics.\n * @default url hostname\n */\n label?: string;\n\n /**\n * Extra `ConnectionConfig` options (commitment, confirmTransactionInitialTimeout, etc.)\n * merged into the Solana `Connection` constructor for this endpoint.\n */\n connectionConfig?: ConnectionConfig;\n}\n\n/**\n * Strategy for selecting the next RPC endpoint from the pool.\n *\n * - `\"round-robin\"` — weighted round-robin across healthy endpoints.\n * - `\"failover\"` — use the first healthy endpoint; only advance on failure.\n */\nexport type SelectionStrategy = \"round-robin\" | \"failover\";\n\n/**\n * Full configuration for the RPC connection pool.\n *\n * @example\n * ```ts\n * import { RpcPool } from \"@percolator/sdk\";\n *\n * const pool = new RpcPool({\n * endpoints: [\n * { url: \"https://mainnet.helius-rpc.com/?api-key=KEY\", weight: 10, label: \"helius\" },\n * { url: \"https://api.mainnet-beta.solana.com\", weight: 1, label: \"public\" },\n * ],\n * strategy: \"failover\",\n * retry: { maxRetries: 3, baseDelayMs: 500 },\n * requestTimeoutMs: 30_000,\n * });\n *\n * // Use like a Connection — same surface\n * const slot = await pool.call(conn => conn.getSlot());\n * ```\n */\nexport interface RpcPoolConfig {\n /**\n * One or more RPC endpoints. At least one is required.\n * If a bare `string[]` is passed, each string is treated as `{ url: string }`.\n */\n endpoints: (RpcEndpointConfig | string)[];\n\n /**\n * How to pick the next endpoint.\n * @default \"failover\"\n */\n strategy?: SelectionStrategy;\n\n /**\n * Retry config applied to every `call()`.\n * Set to `false` to disable retries entirely.\n * @default { maxRetries: 3, baseDelayMs: 500 }\n */\n retry?: RetryConfig | false;\n\n /**\n * Per-request timeout in ms. Applies an `AbortSignal` timeout to `Connection`\n * calls where supported, and is used as a deadline for the health probe.\n * @default 30_000\n */\n requestTimeoutMs?: number;\n\n /**\n * Default Solana commitment level for connections.\n * @default \"confirmed\"\n */\n commitment?: Commitment;\n\n /**\n * If true, `console.warn` diagnostic messages on retries, failovers, etc.\n * @default true\n */\n verbose?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Health Probe\n// ---------------------------------------------------------------------------\n\n/**\n * Result of an RPC health probe.\n *\n * @example\n * ```ts\n * import { checkRpcHealth } from \"@percolator/sdk\";\n *\n * const health = await checkRpcHealth(\"https://api.mainnet-beta.solana.com\");\n * console.log(`Slot: ${health.slot}, Latency: ${health.latencyMs}ms`);\n * if (!health.healthy) console.warn(`Unhealthy: ${health.error}`);\n * ```\n */\nexport interface RpcHealthResult {\n /** The endpoint that was probed. */\n endpoint: string;\n /** Whether the probe succeeded (getSlot returned without error). */\n healthy: boolean;\n /** Round-trip latency in milliseconds (0 if unhealthy). */\n latencyMs: number;\n /** Current slot height (0 if unhealthy). */\n slot: number;\n /** Error message if the probe failed. */\n error?: string;\n}\n\n/**\n * Probe an RPC endpoint's health by calling `getSlot()` and measuring latency.\n *\n * @param endpoint - RPC URL to probe\n * @param timeoutMs - Timeout in ms for the probe request (default: 5000)\n * @returns Health result with latency and slot height\n *\n * @example\n * ```ts\n * import { checkRpcHealth } from \"@percolator/sdk\";\n *\n * const result = await checkRpcHealth(\"https://api.mainnet-beta.solana.com\", 3000);\n * if (result.healthy) {\n * console.log(`Slot ${result.slot} — ${result.latencyMs}ms`);\n * } else {\n * console.error(`RPC down: ${result.error}`);\n * }\n * ```\n */\nexport async function checkRpcHealth(\n endpoint: string,\n timeoutMs: number = 5_000,\n): Promise<RpcHealthResult> {\n const conn = new Connection(endpoint, { commitment: \"processed\" });\n const start = performance.now();\n\n const timeout = rejectAfter<number>(timeoutMs, `Health probe timed out after ${timeoutMs}ms`);\n try {\n const slot = await Promise.race([\n conn.getSlot(\"processed\"),\n timeout.promise,\n ]);\n\n const latencyMs = Math.round(performance.now() - start);\n return { endpoint, healthy: true, latencyMs, slot };\n } catch (err) {\n const latencyMs = Math.round(performance.now() - start);\n return {\n endpoint,\n healthy: false,\n latencyMs,\n slot: 0,\n error: err instanceof Error ? err.message : String(err),\n };\n } finally {\n timeout.cancel();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal Helpers\n// ---------------------------------------------------------------------------\n\n/** Resolved defaults for RetryConfig. */\ninterface ResolvedRetryConfig {\n maxRetries: number;\n baseDelayMs: number;\n maxDelayMs: number;\n jitterFactor: number;\n retryableStatusCodes: number[];\n}\n\nfunction resolveRetryConfig(cfg?: RetryConfig | false): ResolvedRetryConfig | null {\n if (cfg === false) return null;\n const c = cfg ?? {};\n return {\n maxRetries: c.maxRetries ?? 3,\n baseDelayMs: c.baseDelayMs ?? 500,\n maxDelayMs: c.maxDelayMs ?? 10_000,\n jitterFactor: Math.max(0, Math.min(1, c.jitterFactor ?? 0.25)),\n retryableStatusCodes: c.retryableStatusCodes ?? [429, 502, 503, 504],\n };\n}\n\nfunction normalizeEndpoint(ep: RpcEndpointConfig | string): RpcEndpointConfig {\n if (typeof ep === \"string\") return { url: ep };\n return ep;\n}\n\nfunction endpointLabel(ep: RpcEndpointConfig): string {\n if (ep.label) return ep.label;\n try {\n return new URL(ep.url).hostname;\n } catch {\n return ep.url.slice(0, 40);\n }\n}\n\nfunction isRetryable(err: unknown, codes: number[]): boolean {\n if (!err) return false;\n const msg = err instanceof Error ? err.message : String(err);\n for (const code of codes) {\n if (msg.includes(String(code))) return true;\n }\n // Generic network errors\n if (\n msg.toLowerCase().includes(\"rate limit\") ||\n msg.toLowerCase().includes(\"too many requests\") ||\n msg.toLowerCase().includes(\"econnreset\") ||\n msg.toLowerCase().includes(\"econnrefused\") ||\n msg.toLowerCase().includes(\"socket hang up\") ||\n msg.toLowerCase().includes(\"network\") ||\n msg.toLowerCase().includes(\"timeout\") ||\n msg.toLowerCase().includes(\"abort\")\n ) {\n return true;\n }\n return false;\n}\n\nfunction computeDelay(attempt: number, config: ResolvedRetryConfig): number {\n const raw = Math.min(\n config.baseDelayMs * Math.pow(2, attempt),\n config.maxDelayMs,\n );\n const jitter = Math.floor(Math.random() * raw * config.jitterFactor);\n return raw + jitter;\n}\n\nfunction rejectAfter<T>(ms: number, message: string): { promise: Promise<T>; cancel: () => void } {\n let timer: ReturnType<typeof setTimeout>;\n const promise = new Promise<T>((_, reject) => {\n timer = setTimeout(() => reject(new Error(message)), ms);\n });\n return { promise, cancel: () => clearTimeout(timer!) };\n}\n\n/** Sleep utility. */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Redact sensitive query-string parameters (api-key, api_key, token, secret,\n * key, password) from a URL so it is safe for logging / status output.\n */\nfunction redactUrl(raw: string): string {\n try {\n const u = new URL(raw);\n const sensitive = /^(api[-_]?key|access[-_]?token|auth[-_]?token|token|secret|key|password|bearer|credential|jwt)$/i;\n for (const k of [...u.searchParams.keys()]) {\n if (sensitive.test(k)) {\n u.searchParams.set(k, \"***\");\n }\n }\n return u.toString();\n } catch {\n // Not a valid URL — return as-is (unlikely for RPC endpoints).\n return raw;\n }\n}\n\n// ---------------------------------------------------------------------------\n// RpcPool\n// ---------------------------------------------------------------------------\n\n/** Per-endpoint tracked state. */\ninterface EndpointState {\n config: RpcEndpointConfig;\n connection: Connection;\n label: string;\n weight: number;\n /** Consecutive failure count. Resets on success. */\n failures: number;\n /** Whether this endpoint is considered healthy. */\n healthy: boolean;\n /** Last probe latency (ms), -1 if never probed. */\n lastLatencyMs: number;\n}\n\n/**\n * RPC connection pool with retry, failover, and round-robin support.\n *\n * Wraps one or more Solana RPC endpoints behind a single `call()` interface\n * that automatically retries transient errors and fails over to alternate\n * endpoints when one goes down.\n *\n * @example\n * ```ts\n * import { RpcPool } from \"@percolator/sdk\";\n *\n * const pool = new RpcPool({\n * endpoints: [\n * { url: \"https://mainnet.helius-rpc.com/?api-key=KEY\", weight: 10, label: \"helius\" },\n * { url: \"https://api.mainnet-beta.solana.com\", weight: 1, label: \"public\" },\n * ],\n * strategy: \"failover\",\n * retry: { maxRetries: 3 },\n * requestTimeoutMs: 30_000,\n * });\n *\n * // Execute any Connection method through the pool\n * const slot = await pool.call(conn => conn.getSlot());\n *\n * // Or get a raw connection for one-off use\n * const conn = pool.getConnection();\n *\n * // Health check all endpoints\n * const results = await pool.healthCheck();\n * ```\n */\nexport class RpcPool {\n private readonly endpoints: EndpointState[];\n private readonly strategy: SelectionStrategy;\n private readonly retryConfig: ResolvedRetryConfig | null;\n private readonly requestTimeoutMs: number;\n private readonly verbose: boolean;\n\n /** Round-robin index tracker. */\n private rrIndex: number = 0;\n\n /** Consecutive failure threshold before marking an endpoint unhealthy. */\n private static readonly UNHEALTHY_THRESHOLD = 3;\n\n /** Minimum endpoints before auto-recovery is attempted. */\n private static readonly MIN_HEALTHY = 1;\n\n constructor(config: RpcPoolConfig) {\n if (!config.endpoints || config.endpoints.length === 0) {\n throw new Error(\"RpcPool: at least one endpoint is required\");\n }\n\n this.strategy = config.strategy ?? \"failover\";\n this.retryConfig = resolveRetryConfig(config.retry);\n this.requestTimeoutMs = config.requestTimeoutMs ?? 30_000;\n this.verbose = config.verbose ?? true;\n\n const commitment = config.commitment ?? \"confirmed\";\n\n this.endpoints = config.endpoints.map(raw => {\n const ep = normalizeEndpoint(raw);\n const connConfig: ConnectionConfig = {\n commitment,\n ...ep.connectionConfig,\n };\n return {\n config: ep,\n connection: new Connection(ep.url, connConfig),\n label: endpointLabel(ep),\n weight: Math.max(1, ep.weight ?? 1),\n failures: 0,\n healthy: true,\n lastLatencyMs: -1,\n };\n });\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /**\n * Execute a function against a pooled connection with automatic retry\n * and failover.\n *\n * @param fn - Async function that receives a `Connection` and returns a result.\n * @returns The result of `fn`.\n * @throws The last error if all retries and failovers are exhausted.\n *\n * @example\n * ```ts\n * const balance = await pool.call(c => c.getBalance(pubkey));\n * const markets = await pool.call(c => discoverMarkets(c, programId, opts));\n * ```\n */\n async call<T>(fn: (connection: Connection) => Promise<T>): Promise<T> {\n const maxAttempts = this.retryConfig ? this.retryConfig.maxRetries + 1 : 1;\n let lastError: unknown;\n\n // Track which endpoints we have tried in this call to avoid infinite loops.\n const triedEndpoints = new Set<number>();\n // Hard cap on total iterations to prevent amplification from attempt-- failovers\n const maxTotalIterations = maxAttempts + this.endpoints.length;\n let totalIterations = 0;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n if (++totalIterations > maxTotalIterations) break;\n const epIdx = this.selectEndpoint(triedEndpoints);\n if (epIdx === -1) {\n // All endpoints exhausted\n break;\n }\n const ep = this.endpoints[epIdx];\n\n const timeout = rejectAfter<T>(this.requestTimeoutMs, `RPC request timed out after ${this.requestTimeoutMs}ms (${ep.label})`);\n try {\n const result = await Promise.race([\n fn(ep.connection),\n timeout.promise,\n ]);\n\n // Success — reset failure count\n timeout.cancel();\n ep.failures = 0;\n ep.healthy = true;\n return result;\n } catch (err) {\n timeout.cancel();\n lastError = err;\n ep.failures++;\n\n if (ep.failures >= RpcPool.UNHEALTHY_THRESHOLD) {\n ep.healthy = false;\n if (this.verbose) {\n console.warn(\n `[RpcPool] Endpoint ${ep.label} marked unhealthy after ${ep.failures} consecutive failures`,\n );\n }\n }\n\n const retryable = this.retryConfig\n ? isRetryable(err, this.retryConfig.retryableStatusCodes)\n : false;\n\n if (!retryable) {\n // For non-retryable errors in failover mode, try the next endpoint\n if (this.strategy === \"failover\" && this.endpoints.length > 1) {\n triedEndpoints.add(epIdx);\n // Don't count this as a retry attempt — just failover\n attempt--;\n if (triedEndpoints.size >= this.endpoints.length) break;\n continue;\n }\n throw err;\n }\n\n // Retryable error\n if (this.verbose) {\n console.warn(\n `[RpcPool] Retryable error on ${ep.label} (attempt ${attempt + 1}/${maxAttempts}):`,\n err instanceof Error ? err.message : err,\n );\n }\n\n // In failover mode, try next endpoint before retrying same one\n if (this.strategy === \"failover\" && this.endpoints.length > 1) {\n triedEndpoints.add(epIdx);\n }\n\n // Backoff before retry\n if (attempt < maxAttempts - 1 && this.retryConfig) {\n const delay = computeDelay(attempt, this.retryConfig);\n await sleep(delay);\n }\n }\n }\n\n // All attempts exhausted — try recovery before giving up\n this.maybeRecoverEndpoints();\n\n throw lastError ?? new Error(\"RpcPool: all endpoints exhausted\");\n }\n\n /**\n * Get a raw `Connection` from the current preferred endpoint.\n * Useful when you need to pass a Connection to external code.\n *\n * NOTE: This bypasses retry and failover logic. Prefer `call()`.\n *\n * @returns Solana Connection from the current preferred endpoint.\n *\n * @example\n * ```ts\n * const conn = pool.getConnection();\n * const balance = await conn.getBalance(pubkey);\n * ```\n */\n getConnection(): Connection {\n const idx = this.selectEndpoint();\n if (idx === -1) {\n // All marked unhealthy — reset and use first\n this.maybeRecoverEndpoints();\n return this.endpoints[0].connection;\n }\n return this.endpoints[idx].connection;\n }\n\n /**\n * Run a health check against all endpoints in the pool.\n *\n * @param timeoutMs - Per-endpoint probe timeout (default: 5000)\n * @returns Array of health results, one per endpoint.\n *\n * @example\n * ```ts\n * const results = await pool.healthCheck();\n * for (const r of results) {\n * console.log(`${r.endpoint}: ${r.healthy ? 'UP' : 'DOWN'} (${r.latencyMs}ms, slot ${r.slot})`);\n * }\n * ```\n */\n async healthCheck(timeoutMs: number = 5_000): Promise<RpcHealthResult[]> {\n const results = await Promise.all(\n this.endpoints.map(async (ep) => {\n const result = await checkRpcHealth(ep.config.url, timeoutMs);\n ep.lastLatencyMs = result.latencyMs;\n ep.healthy = result.healthy;\n if (result.healthy) ep.failures = 0;\n result.endpoint = redactUrl(result.endpoint);\n return result;\n }),\n );\n return results;\n }\n\n /**\n * Get the number of endpoints in the pool.\n */\n get size(): number {\n return this.endpoints.length;\n }\n\n /**\n * Get the number of currently healthy endpoints.\n */\n get healthyCount(): number {\n return this.endpoints.filter(ep => ep.healthy).length;\n }\n\n /**\n * Get endpoint labels and their current status.\n *\n * @returns Array of `{ label, url, healthy, failures, lastLatencyMs }`.\n */\n status(): Array<{\n label: string;\n url: string;\n healthy: boolean;\n failures: number;\n lastLatencyMs: number;\n }> {\n return this.endpoints.map(ep => ({\n label: ep.label,\n url: redactUrl(ep.config.url),\n healthy: ep.healthy,\n failures: ep.failures,\n lastLatencyMs: ep.lastLatencyMs,\n }));\n }\n\n // -----------------------------------------------------------------------\n // Internals\n // -----------------------------------------------------------------------\n\n /**\n * Select the next endpoint based on strategy.\n * Returns -1 if no endpoint is available.\n */\n private selectEndpoint(exclude?: Set<number>): number {\n const healthy = this.endpoints\n .map((ep, i) => ({ ep, i }))\n .filter(({ ep, i }) => ep.healthy && !(exclude?.has(i)));\n\n if (healthy.length === 0) {\n // No healthy endpoints — try all non-excluded\n const remaining = this.endpoints\n .map((_, i) => i)\n .filter(i => !(exclude?.has(i)));\n return remaining.length > 0 ? remaining[0] : -1;\n }\n\n if (this.strategy === \"failover\") {\n // Return first healthy (by insertion order)\n return healthy[0].i;\n }\n\n // Weighted round-robin\n const totalWeight = healthy.reduce((sum, { ep }) => sum + ep.weight, 0);\n this.rrIndex = (this.rrIndex + 1) % totalWeight;\n\n let cumulative = 0;\n for (const { ep, i } of healthy) {\n cumulative += ep.weight;\n if (this.rrIndex < cumulative) return i;\n }\n\n return healthy[healthy.length - 1].i;\n }\n\n /**\n * If all endpoints are unhealthy, reset them so we at least try again.\n */\n private maybeRecoverEndpoints(): void {\n const healthyCount = this.endpoints.filter(ep => ep.healthy).length;\n if (healthyCount < RpcPool.MIN_HEALTHY) {\n if (this.verbose) {\n console.warn(\"[RpcPool] All endpoints unhealthy — resetting for recovery\");\n }\n for (const ep of this.endpoints) {\n ep.healthy = true;\n ep.failures = 0;\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Standalone retry wrapper (for use without a full pool)\n// ---------------------------------------------------------------------------\n\n/**\n * Execute an async function with exponential-backoff retry.\n *\n * Use this when you already have a `Connection` and just want retry logic\n * without a full pool.\n *\n * @param fn - Async function to execute\n * @param config - Retry configuration (default: 3 retries, 500ms base delay)\n * @returns Result of `fn`\n * @throws The last error if all retries are exhausted\n *\n * @example\n * ```ts\n * import { withRetry } from \"@percolator/sdk\";\n * import { Connection } from \"@solana/web3.js\";\n *\n * const conn = new Connection(\"https://api.mainnet-beta.solana.com\");\n * const slot = await withRetry(\n * () => conn.getSlot(),\n * { maxRetries: 3, baseDelayMs: 1000 },\n * );\n * ```\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n config?: RetryConfig,\n): Promise<T> {\n const resolved = resolveRetryConfig(config) ?? {\n maxRetries: 3,\n baseDelayMs: 500,\n maxDelayMs: 10_000,\n jitterFactor: 0.25,\n retryableStatusCodes: [429, 502, 503, 504],\n };\n\n let lastError: unknown;\n const maxAttempts = resolved.maxRetries + 1;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n\n if (!isRetryable(err, resolved.retryableStatusCodes)) {\n throw err;\n }\n\n if (attempt < maxAttempts - 1) {\n const delay = computeDelay(attempt, resolved);\n await sleep(delay);\n }\n }\n }\n\n throw lastError ?? new Error(\"withRetry: all attempts exhausted\");\n}\n\n// ---------------------------------------------------------------------------\n// Re-export helpers for testing\n// ---------------------------------------------------------------------------\n\n/** @internal — exposed for unit tests only */\nexport const _internal = {\n isRetryable,\n computeDelay,\n resolveRetryConfig,\n normalizeEndpoint,\n endpointLabel,\n} as const;\n","import {\n Connection,\n PublicKey,\n TransactionInstruction,\n Transaction,\n Keypair,\n SendOptions,\n Commitment,\n AccountMeta,\n ComputeBudgetProgram,\n} from \"@solana/web3.js\";\nimport { parseErrorFromLogs } from \"../abi/errors.js\";\n\nexport interface BuildIxParams {\n programId: PublicKey;\n keys: AccountMeta[];\n data: Uint8Array | Buffer;\n}\n\n/**\n * Build a transaction instruction.\n */\nexport function buildIx(params: BuildIxParams): TransactionInstruction {\n return new TransactionInstruction({\n programId: params.programId,\n keys: params.keys,\n // TransactionInstruction types expect Buffer, but Uint8Array works at runtime.\n // Cast to avoid Buffer polyfill issues in the browser.\n data: params.data as Buffer,\n });\n}\n\nexport interface TxResult {\n signature: string;\n slot: number;\n err: string | null;\n hint?: string;\n logs: string[];\n unitsConsumed?: number;\n}\n\nexport interface SimulateOrSendParams {\n connection: Connection;\n ix: TransactionInstruction;\n signers: Keypair[];\n simulate: boolean;\n commitment?: Commitment;\n computeUnitLimit?: number; // Custom compute unit limit (default: 200,000, max: 1,400,000)\n}\n\n/**\n * Simulate or send a transaction.\n * Returns consistent output for both modes.\n */\n/** Solana per-transaction compute unit ceiling (Compute Budget program). */\nconst MAX_COMPUTE_UNIT_LIMIT = 1_400_000;\n\nexport async function simulateOrSend(\n params: SimulateOrSendParams\n): Promise<TxResult> {\n const { connection, ix, signers, simulate, commitment = \"confirmed\", computeUnitLimit } = params;\n\n if (!signers.length) {\n throw new Error(\"simulateOrSend: at least one signer is required\");\n }\n\n if (computeUnitLimit !== undefined) {\n if (\n typeof computeUnitLimit !== \"number\" ||\n !Number.isInteger(computeUnitLimit) ||\n computeUnitLimit < 1 ||\n computeUnitLimit > MAX_COMPUTE_UNIT_LIMIT\n ) {\n throw new Error(\n `computeUnitLimit must be an integer in [1, ${MAX_COMPUTE_UNIT_LIMIT}]`,\n );\n }\n }\n\n const tx = new Transaction();\n\n // Add compute budget instruction if custom limit is specified\n if (computeUnitLimit !== undefined) {\n tx.add(\n ComputeBudgetProgram.setComputeUnitLimit({\n units: computeUnitLimit,\n })\n );\n }\n\n tx.add(ix);\n const latestBlockhash = await connection.getLatestBlockhash(commitment);\n tx.recentBlockhash = latestBlockhash.blockhash;\n tx.feePayer = signers[0].publicKey;\n\n if (simulate) {\n try {\n tx.sign(...signers);\n const result = await connection.simulateTransaction(tx, signers);\n const logs = result.value.logs ?? [];\n let err: string | null = null;\n let hint: string | undefined;\n\n if (result.value.err) {\n const parsed = parseErrorFromLogs(logs);\n if (parsed) {\n err = `${parsed.name} (0x${parsed.code.toString(16)})`;\n hint = parsed.hint;\n } else {\n err = JSON.stringify(result.value.err);\n }\n }\n\n return {\n signature: \"(simulated)\",\n slot: result.context.slot,\n err,\n hint,\n logs,\n unitsConsumed: result.value.unitsConsumed ?? undefined,\n };\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n return {\n signature: \"(simulated)\",\n slot: 0,\n err: message,\n logs: [],\n };\n }\n }\n\n // Send\n const options: SendOptions = {\n skipPreflight: false,\n preflightCommitment: commitment,\n };\n\n try {\n const signature = await connection.sendTransaction(tx, signers, options);\n\n const confirmation = await connection.confirmTransaction(\n {\n signature,\n blockhash: latestBlockhash.blockhash,\n lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,\n },\n commitment\n );\n\n // Fetch logs\n const txInfo = await connection.getTransaction(signature, {\n commitment: \"confirmed\",\n maxSupportedTransactionVersion: 0,\n });\n\n const logs = txInfo?.meta?.logMessages ?? [];\n let err: string | null = null;\n let hint: string | undefined;\n\n if (confirmation.value.err) {\n const parsed = parseErrorFromLogs(logs);\n if (parsed) {\n err = `${parsed.name} (0x${parsed.code.toString(16)})`;\n hint = parsed.hint;\n } else {\n err = JSON.stringify(confirmation.value.err);\n }\n }\n\n return {\n signature,\n slot: txInfo?.slot ?? 0,\n err,\n hint,\n logs,\n };\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n return {\n signature: \"\",\n slot: 0,\n err: message,\n logs: [],\n };\n }\n}\n\n/**\n * Format transaction result for output.\n */\nexport function formatResult(result: TxResult, jsonMode: boolean): string {\n if (jsonMode) {\n return JSON.stringify(result, null, 2);\n }\n\n const lines: string[] = [];\n\n if (result.err) {\n lines.push(`Error: ${result.err}`);\n if (result.hint) {\n lines.push(`Hint: ${result.hint}`);\n }\n if (result.unitsConsumed !== undefined) {\n lines.push(`Compute Units: ${result.unitsConsumed.toLocaleString()}`);\n }\n if (result.logs.length > 0) {\n lines.push(\"Logs:\");\n result.logs.forEach((log) => lines.push(` ${log}`));\n }\n } else {\n lines.push(`Signature: ${result.signature}`);\n lines.push(`Slot: ${result.slot}`);\n if (result.unitsConsumed !== undefined) {\n lines.push(`Compute Units: ${result.unitsConsumed.toLocaleString()}`);\n }\n if (result.signature !== \"(simulated)\") {\n lines.push(`Explorer: https://explorer.solana.com/tx/${result.signature}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n","/**\n * @module lighthouse\n * Lighthouse v2 (Blowfish / Phantom wallet middleware) detection and mitigation.\n *\n * Lighthouse (program L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95) is an Anchor-based\n * wallet guard injected by Phantom and other Solana wallets via the Blowfish transaction\n * scanning service. It adds assertion instructions to transactions that verify account\n * state expectations (e.g., \"this account should be empty\" or \"this account should have\n * X lamports\").\n *\n * **Problem:** Lighthouse doesn't understand Percolator's slab accounts. When a slab\n * (e.g., ESa89R5 with 323,312 bytes) is passed as a TradeCpi account, Lighthouse injects\n * an assertion like `StateInvalidAddress` that expects `data_len == 0` (uninitialised).\n * The slab IS initialised, so the assertion fails with error 0x1900 (Anchor ConstraintAddress\n * = 6400 decimal). This causes the transaction to revert even though the Percolator program\n * logic is correct.\n *\n * **Solution:** The SDK provides utilities to:\n * 1. Detect Lighthouse instructions in a transaction\n * 2. Strip them before sending\n * 3. Classify 0x1900 errors as Lighthouse (not Percolator) errors\n * 4. Provide clear, actionable error messages for end users\n *\n * @example\n * ```ts\n * import { isLighthouseError, stripLighthouseInstructions, LIGHTHOUSE_PROGRAM_ID } from \"@percolator/sdk\";\n *\n * // Before sending: strip injected Lighthouse IXs\n * const cleanIxs = stripLighthouseInstructions(instructions);\n *\n * // After error: classify and give user-friendly message\n * if (isLighthouseError(error)) {\n * console.warn(\"Wallet middleware blocked the transaction\");\n * }\n * ```\n */\n\nimport { PublicKey, TransactionInstruction, Transaction } from \"@solana/web3.js\";\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Lighthouse v2 program ID (Blowfish/Phantom wallet guard).\n *\n * This is an immutable Anchor program deployed at slot 294,179,293.\n * Wallets like Phantom inject instructions from this program into user\n * transactions to enforce Blowfish security assertions.\n */\nexport const LIGHTHOUSE_PROGRAM_ID = new PublicKey(\n \"L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95\",\n);\n\n/** Base58 string form for fast comparison without PublicKey instantiation. */\nexport const LIGHTHOUSE_PROGRAM_ID_STR = \"L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95\";\n\n/**\n * Anchor error code for ConstraintAddress (0x1900 = 6400 decimal).\n * This is NOT a Percolator error — it comes from Lighthouse's Anchor framework\n * when an account constraint check fails.\n */\nexport const LIGHTHOUSE_CONSTRAINT_ADDRESS = 0x1900;\n\n/**\n * Known Lighthouse/Anchor error codes that may appear in transaction logs.\n * All are in the Anchor error range (0x1770–0x1900+).\n */\nexport const LIGHTHOUSE_ERROR_CODES = new Set([\n 0x1770, // InstructionMissing\n 0x1771, // InstructionFallbackNotFound\n 0x1772, // InstructionDidNotDeserialize\n 0x1773, // InstructionDidNotSerialize\n 0x1780, // IdlInstructionStub\n 0x1790, // ConstraintMut\n 0x1791, // ConstraintHasOne\n 0x1792, // ConstraintSigner\n 0x1793, // ConstraintRaw\n 0x1794, // ConstraintOwner\n 0x1795, // ConstraintRentExempt\n 0x1796, // ConstraintSeeds\n 0x1797, // ConstraintExecutable\n 0x1798, // ConstraintState\n 0x1799, // ConstraintAssociated\n 0x179a, // ConstraintAssociatedInit\n 0x179b, // ConstraintClose\n 0x1900, // ConstraintAddress (the one we hit most often)\n] as const);\n\n// ============================================================================\n// Detection\n// ============================================================================\n\n/**\n * Check if a TransactionInstruction is from the Lighthouse program.\n *\n * @param ix - A Solana transaction instruction.\n * @returns `true` if the instruction's programId is Lighthouse.\n *\n * @example\n * ```ts\n * const hasLighthouse = instructions.some(isLighthouseInstruction);\n * ```\n */\nexport function isLighthouseInstruction(ix: TransactionInstruction): boolean {\n return ix.programId.equals(LIGHTHOUSE_PROGRAM_ID);\n}\n\n/**\n * Check if an error message or error object indicates a Lighthouse assertion failure.\n *\n * Detects:\n * - `custom program error: 0x1900` (Anchor ConstraintAddress from Lighthouse)\n * - References to the Lighthouse program ID in error text\n * - `\"Custom\": 6400` in JSON-encoded InstructionError\n * - Any Anchor error code in the LIGHTHOUSE_ERROR_CODES range when the\n * failing program is Lighthouse (identified by program ID in logs)\n *\n * @param error - An Error object, error message string, or transaction logs array.\n * @returns `true` if the error appears to originate from Lighthouse, not Percolator.\n *\n * @example\n * ```ts\n * try {\n * await sendTransaction(tx);\n * } catch (e) {\n * if (isLighthouseError(e)) {\n * // Retry with skipPreflight or notify user about wallet middleware\n * }\n * }\n * ```\n */\nexport function isLighthouseError(error: unknown): boolean {\n const msg = extractErrorMessage(error);\n if (!msg) return false;\n\n // Direct program ID reference\n if (msg.includes(LIGHTHOUSE_PROGRAM_ID_STR)) return true;\n\n // 0x1900 hex error code (case-insensitive)\n if (/custom\\s+program\\s+error:\\s*0x1900\\b/i.test(msg)) return true;\n\n // JSON InstructionError format: {\"Custom\": 6400}\n if (/\"Custom\"\\s*:\\s*6400\\b/.test(msg) && /InstructionError/i.test(msg)) return true;\n\n return false;\n}\n\n/**\n * Check if transaction logs contain evidence of a Lighthouse failure.\n *\n * More precise than `isLighthouseError` on a string — examines the program\n * invocation chain to confirm the error originates from Lighthouse, not from\n * a Percolator instruction that happens to return a similar code.\n *\n * @param logs - Array of transaction log lines from `getTransaction()`.\n * @returns `true` if logs show a Lighthouse program failure.\n */\nexport function isLighthouseFailureInLogs(logs: string[]): boolean {\n if (!Array.isArray(logs)) return false;\n\n let insideLighthouse = false;\n\n for (const line of logs) {\n if (typeof line !== \"string\") continue;\n\n // Track program invocation depth\n if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {\n insideLighthouse = true;\n continue;\n }\n\n // Lighthouse program returned success — reset\n if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {\n insideLighthouse = false;\n continue;\n }\n\n // Error while inside a Lighthouse invocation\n if (insideLighthouse && /failed/i.test(line)) {\n return true;\n }\n\n // Explicit Lighthouse failure log\n if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} failed`)) {\n return true;\n }\n }\n\n return false;\n}\n\n// ============================================================================\n// Stripping / Mitigation\n// ============================================================================\n\n/**\n * Remove all Lighthouse assertion instructions from an instruction array.\n *\n * Call this before building a Transaction to prevent Lighthouse assertion\n * failures. Safe to call even if no Lighthouse instructions are present.\n *\n * @param instructions - Array of transaction instructions.\n * @returns Filtered array with Lighthouse instructions removed.\n *\n * @example\n * ```ts\n * import { stripLighthouseInstructions } from \"@percolator/sdk\";\n *\n * const instructions = [crankIx, tradeIx]; // May have Lighthouse IXs mixed in\n * const clean = stripLighthouseInstructions(instructions);\n * const tx = new Transaction().add(...clean);\n * ```\n */\nexport function stripLighthouseInstructions(\n instructions: TransactionInstruction[],\n percolatorProgramId?: PublicKey,\n): TransactionInstruction[] {\n // When a programId is provided, refuse to strip guards from transactions\n // that don't contain any Percolator instructions — prevents misuse on\n // arbitrary transactions where Lighthouse guards are legitimate protection.\n if (percolatorProgramId) {\n const hasPercolatorIx = instructions.some(\n (ix) => ix.programId.equals(percolatorProgramId),\n );\n if (!hasPercolatorIx) {\n return instructions; // no Percolator instructions — leave guards intact\n }\n }\n return instructions.filter((ix) => !isLighthouseInstruction(ix));\n}\n\n/**\n * Strip Lighthouse instructions from an already-built Transaction.\n *\n * Creates a new Transaction with the same recentBlockhash and feePayer\n * but without any Lighthouse instructions. The returned transaction is\n * unsigned and must be re-signed.\n *\n * @param transaction - A Transaction (signed or unsigned).\n * @returns A new Transaction without Lighthouse instructions, or the same\n * transaction if no Lighthouse instructions were found.\n *\n * @example\n * ```ts\n * const signed = await wallet.signTransaction(tx);\n * if (hasLighthouseInstructions(signed)) {\n * const clean = stripLighthouseFromTransaction(signed);\n * const reSigned = await wallet.signTransaction(clean);\n * await connection.sendRawTransaction(reSigned.serialize());\n * }\n * ```\n */\nexport function stripLighthouseFromTransaction(\n transaction: Transaction,\n percolatorProgramId?: PublicKey,\n): Transaction {\n // When a programId is provided, refuse to strip guards from transactions\n // that don't contain any Percolator instructions.\n if (percolatorProgramId) {\n const hasPercolatorIx = transaction.instructions.some(\n (ix) => ix.programId.equals(percolatorProgramId),\n );\n if (!hasPercolatorIx) return transaction;\n }\n\n const hasLighthouse = transaction.instructions.some(isLighthouseInstruction);\n if (!hasLighthouse) return transaction;\n\n const clean = new Transaction();\n clean.recentBlockhash = transaction.recentBlockhash;\n clean.feePayer = transaction.feePayer;\n\n for (const ix of transaction.instructions) {\n if (!isLighthouseInstruction(ix)) {\n clean.add(ix);\n }\n }\n\n return clean;\n}\n\n/**\n * Count Lighthouse instructions in an instruction array or transaction.\n *\n * @param ixsOrTx - Array of instructions or a Transaction.\n * @returns Number of Lighthouse instructions found.\n */\nexport function countLighthouseInstructions(\n ixsOrTx: TransactionInstruction[] | Transaction,\n): number {\n const instructions = Array.isArray(ixsOrTx) ? ixsOrTx : ixsOrTx.instructions;\n return instructions.filter(isLighthouseInstruction).length;\n}\n\n// ============================================================================\n// User-facing error messages\n// ============================================================================\n\n/**\n * User-friendly error message for Lighthouse assertion failures.\n *\n * Suitable for display in UI toast/modal when `isLighthouseError()` returns true.\n */\nexport const LIGHTHOUSE_USER_MESSAGE =\n \"Your wallet's transaction guard (Blowfish/Lighthouse) is blocking this transaction. \" +\n \"This is a known compatibility issue — the transaction itself is valid. \" +\n \"Try one of these workarounds:\\n\" +\n \"1. Disable transaction simulation in your wallet settings\\n\" +\n \"2. Use a wallet without Blowfish protection (e.g., Backpack, Solflare)\\n\" +\n \"3. The SDK will automatically retry without the guard\";\n\n/**\n * Classify an error and return an appropriate user-facing message.\n *\n * If the error is from Lighthouse, returns the Lighthouse-specific message.\n * Otherwise returns `null` (callers should use their own error display).\n *\n * @param error - An Error, string, or logs array.\n * @returns User-facing message string, or `null` if not a Lighthouse error.\n */\nexport function classifyLighthouseError(error: unknown): string | null {\n if (isLighthouseError(error)) {\n return LIGHTHOUSE_USER_MESSAGE;\n }\n return null;\n}\n\n// ============================================================================\n// Internal helpers\n// ============================================================================\n\nfunction extractErrorMessage(error: unknown): string | null {\n if (!error) return null;\n if (typeof error === \"string\") return error;\n if (error instanceof Error) return error.message;\n if (typeof error === \"object\" && \"message\" in error) {\n return String((error as { message: unknown }).message);\n }\n try {\n return JSON.stringify(error);\n } catch {\n return null;\n }\n}\n","/**\n * Coin-margined perpetual trade math utilities.\n *\n * On-chain PnL formula:\n * mark_pnl = (oracle - entry) * abs_pos / oracle (longs)\n * mark_pnl = (entry - oracle) * abs_pos / oracle (shorts)\n *\n * All prices are in e6 format (1 USD = 1_000_000).\n * All token amounts are in native units (e.g. lamports).\n */\n\n/**\n * Compute mark-to-market PnL for an open position.\n *\n * @param positionSize - Signed position size (positive = long, negative = short).\n * @param entryPrice - Entry price in e6 format (1 USD = 1_000_000).\n * @param oraclePrice - Current oracle price in e6 format.\n * @returns PnL in native token units (positive = profit, negative = loss).\n *\n * @example\n * ```ts\n * // Long 10 SOL at $100, oracle now $110 → profit\n * const pnl = computeMarkPnl(10_000_000n, 100_000_000n, 110_000_000n);\n * ```\n */\nexport function computeMarkPnl(\n positionSize: bigint,\n entryPrice: bigint,\n oraclePrice: bigint,\n): bigint {\n if (positionSize === 0n || oraclePrice === 0n) return 0n;\n const absPos = positionSize < 0n ? -positionSize : positionSize;\n const diff =\n positionSize > 0n\n ? oraclePrice - entryPrice\n : entryPrice - oraclePrice;\n return (diff * absPos) / oraclePrice;\n}\n\n/**\n * Compute liquidation price given entry, capital, position and maintenance margin.\n * Uses pure BigInt arithmetic for precision (no Number() truncation).\n *\n * @param entryPrice - Entry price in e6 format.\n * @param capital - Account capital in native token units.\n * @param positionSize - Signed position size (positive = long, negative = short).\n * @param maintenanceMarginBps - Maintenance margin requirement in basis points (e.g. 500n = 5%).\n * @returns Liquidation price in e6 format. Returns 0n for longs that can't be liquidated,\n * or max u64 for shorts with ≥100% maintenance margin.\n *\n * @example\n * ```ts\n * // Long 1 SOL at $100, $10 capital, 5% maintenance margin\n * const liqPrice = computeLiqPrice(100_000_000n, 10_000_000n, 1_000_000n, 500n);\n * ```\n */\nexport function computeLiqPrice(\n entryPrice: bigint,\n capital: bigint,\n positionSize: bigint,\n maintenanceMarginBps: bigint,\n): bigint {\n if (positionSize === 0n || entryPrice === 0n) return 0n;\n const absPos = positionSize < 0n ? -positionSize : positionSize;\n // capitalPerUnit scaled by 1e6 for precision\n const capitalPerUnitE6 = (capital * 1_000_000n) / absPos;\n\n if (positionSize > 0n) {\n const adjusted = (capitalPerUnitE6 * 10000n) / (10000n + maintenanceMarginBps);\n const liq = entryPrice - adjusted;\n return liq > 0n ? liq : 0n;\n } else {\n // Guard: short positions liquidate when price rises above liq price.\n // With >= 100% maintenance margin the denominator (10000 - maint) would be <= 0,\n // meaning the position can never be liquidated. Return max u64 to signal this.\n if (maintenanceMarginBps >= 10000n) return 18446744073709551615n; // max u64 — unliquidatable\n const adjusted = (capitalPerUnitE6 * 10000n) / (10000n - maintenanceMarginBps);\n return entryPrice + adjusted;\n }\n}\n\n/**\n * Compute estimated liquidation price BEFORE opening a trade.\n * Accounts for trading fees reducing effective capital.\n *\n * @param oracleE6 - Current oracle price in e6 format (used as entry estimate).\n * @param margin - Deposit margin in native token units.\n * @param posSize - Intended position size (absolute value used internally).\n * @param maintBps - Maintenance margin in basis points.\n * @param feeBps - Trading fee in basis points.\n * @param direction - Trade direction: `\"long\"` or `\"short\"`.\n * @returns Estimated liquidation price in e6 format.\n *\n * @example\n * ```ts\n * const liq = computePreTradeLiqPrice(\n * 100_000_000n, 10_000_000n, 1_000_000n, 500n, 30n, \"long\"\n * );\n * ```\n */\nexport function computePreTradeLiqPrice(\n oracleE6: bigint,\n margin: bigint,\n posSize: bigint,\n maintBps: bigint,\n feeBps: bigint,\n direction: \"long\" | \"short\",\n): bigint {\n if (oracleE6 === 0n || margin === 0n || posSize === 0n) return 0n;\n const absPos = posSize < 0n ? -posSize : posSize;\n const fee = (absPos * feeBps) / 10000n;\n const effectiveCapital = margin > fee ? margin - fee : 0n;\n const signedPos = direction === \"long\" ? absPos : -absPos;\n return computeLiqPrice(oracleE6, effectiveCapital, signedPos, maintBps);\n}\n\n/**\n * Compute trading fee from notional value and fee rate in bps.\n *\n * @param notional - Trade notional value in native token units.\n * @param tradingFeeBps - Fee rate in basis points (e.g. 30n = 0.30%).\n * @returns Fee amount in native token units.\n *\n * @example\n * ```ts\n * const fee = computeTradingFee(1_000_000_000n, 30n); // 0.30% of 1 SOL\n * ```\n */\nexport function computeTradingFee(\n notional: bigint,\n tradingFeeBps: bigint,\n): bigint {\n return (notional * tradingFeeBps) / 10000n;\n}\n\n/**\n * Dynamic fee tier configuration.\n */\nexport interface FeeTierConfig {\n /** Base trading fee (Tier 1) in bps */\n baseBps: bigint;\n /** Tier 2 fee in bps (0 = disabled) */\n tier2Bps: bigint;\n /** Tier 3 fee in bps (0 = disabled) */\n tier3Bps: bigint;\n /** Notional threshold to enter Tier 2 (0 = tiered fees disabled) */\n tier2Threshold: bigint;\n /** Notional threshold to enter Tier 3 */\n tier3Threshold: bigint;\n}\n\n/**\n * Compute the effective fee rate in bps using the tiered fee schedule.\n *\n * Mirrors on-chain `compute_dynamic_fee_bps` logic:\n * - notional < tier2Threshold → baseBps (Tier 1)\n * - notional < tier3Threshold → tier2Bps (Tier 2)\n * - notional >= tier3Threshold → tier3Bps (Tier 3)\n *\n * If tier2Threshold == 0, tiered fees are disabled (flat baseBps).\n */\nexport function computeDynamicFeeBps(\n notional: bigint,\n config: FeeTierConfig,\n): bigint {\n if (config.tier2Threshold === 0n) return config.baseBps;\n if (config.tier3Threshold > 0n && notional >= config.tier3Threshold) return config.tier3Bps;\n if (notional >= config.tier2Threshold) return config.tier2Bps;\n return config.baseBps;\n}\n\n/**\n * Compute the dynamic trading fee for a given notional and tier config.\n *\n * Uses ceiling division to match on-chain behavior (prevents fee evasion\n * via micro-trades).\n */\nexport function computeDynamicTradingFee(\n notional: bigint,\n config: FeeTierConfig,\n): bigint {\n const feeBps = computeDynamicFeeBps(notional, config);\n if (notional <= 0n || feeBps <= 0n) return 0n;\n return (notional * feeBps + 9999n) / 10000n;\n}\n\n/**\n * Fee split configuration.\n */\nexport interface FeeSplitConfig {\n /** LP vault share in bps (0–10_000) */\n lpBps: bigint;\n /** Protocol treasury share in bps */\n protocolBps: bigint;\n /** Market creator share in bps */\n creatorBps: bigint;\n}\n\n/**\n * Compute fee split for a total fee amount.\n *\n * Returns [lpShare, protocolShare, creatorShare].\n * If all split params are 0, 100% goes to LP (legacy behavior).\n * Creator gets the rounding remainder to ensure total is preserved.\n */\nexport function computeFeeSplit(\n totalFee: bigint,\n config: FeeSplitConfig,\n): [bigint, bigint, bigint] {\n if (config.lpBps === 0n && config.protocolBps === 0n && config.creatorBps === 0n) {\n return [totalFee, 0n, 0n];\n }\n\n // Validate that splits equal exactly 100%\n const totalBps = config.lpBps + config.protocolBps + config.creatorBps;\n if (totalBps !== 10000n) {\n throw new Error(\n `Fee split must equal exactly 10000 bps (100%): lpBps=${config.lpBps} + protocolBps=${config.protocolBps} + ` +\n `creatorBps=${config.creatorBps} = ${totalBps}`,\n );\n }\n\n const lp = (totalFee * config.lpBps) / 10000n;\n const protocol = (totalFee * config.protocolBps) / 10000n;\n const creator = totalFee - lp - protocol; // only rounding dust (max 2 tokens)\n\n // Sanity check: creator should never be negative if validation above passes\n if (creator < 0n) {\n throw new Error(\n `Internal error: creator fee is negative (${creator}). ` +\n `This should not happen if lpBps + protocolBps + creatorBps <= 10000.`,\n );\n }\n\n return [lp, protocol, creator];\n}\n\n/**\n * Compute PnL as a percentage of capital.\n *\n * Uses BigInt scaling to avoid precision loss from Number(bigint) conversion.\n * Number(bigint) silently truncates values above 2^53, which can produce\n * incorrect percentages for large positions (e.g., tokens with 9 decimals\n * where capital > ~9M tokens in native units exceeds MAX_SAFE_INTEGER).\n */\nexport function computePnlPercent(\n pnlTokens: bigint,\n capital: bigint,\n): number {\n if (capital === 0n) return 0;\n const scaledPct = (pnlTokens * 10_000n) / capital;\n if (scaledPct > BigInt(Number.MAX_SAFE_INTEGER) || scaledPct < BigInt(-Number.MAX_SAFE_INTEGER)) {\n throw new Error(\n `computePnlPercent: scaled result ${scaledPct} exceeds Number.MAX_SAFE_INTEGER — precision loss`,\n );\n }\n return Number(scaledPct) / 100;\n}\n\n/**\n * Estimate entry price including fee impact (slippage approximation).\n *\n * @param oracleE6 - Current oracle price in e6 format.\n * @param tradingFeeBps - Trading fee in basis points.\n * @param direction - Trade direction: `\"long\"` or `\"short\"`.\n * @returns Estimated entry price in e6 format (higher for longs, lower for shorts).\n *\n * @example\n * ```ts\n * const entry = computeEstimatedEntryPrice(100_000_000n, 30n, \"long\");\n * // → 100_030_000n (oracle + 0.30% fee impact)\n * ```\n */\nexport function computeEstimatedEntryPrice(\n oracleE6: bigint,\n tradingFeeBps: bigint,\n direction: \"long\" | \"short\",\n): bigint {\n if (oracleE6 === 0n) return 0n;\n if (tradingFeeBps < 0n) {\n throw new Error(`computeEstimatedEntryPrice: tradingFeeBps must be non-negative, got ${tradingFeeBps}`);\n }\n const feeImpact = (oracleE6 * tradingFeeBps) / 10000n;\n const result = direction === \"long\" ? oracleE6 + feeImpact : oracleE6 - feeImpact;\n if (result <= 0n) {\n throw new Error(\n `computeEstimatedEntryPrice: result ${result} is non-positive (tradingFeeBps=${tradingFeeBps} too high for oracle=${oracleE6})`,\n );\n }\n return result;\n}\n\nconst MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);\nconst MIN_SAFE_BIGINT = BigInt(-Number.MAX_SAFE_INTEGER);\n\n/**\n * Convert per-slot funding rate (bps) to annualized percentage.\n *\n * @param fundingRateBpsPerSlot - Funding rate per slot in basis points (i64 from engine state).\n * @returns Annualized funding rate as a percentage (e.g. 12.5 = 12.5% APR).\n * @throws Error if the value exceeds Number.MAX_SAFE_INTEGER.\n *\n * @example\n * ```ts\n * const apr = computeFundingRateAnnualized(1n); // ~78.84% APR\n * ```\n */\nexport function computeFundingRateAnnualized(\n fundingRateBpsPerSlot: bigint,\n): number {\n if (fundingRateBpsPerSlot > MAX_SAFE_BIGINT || fundingRateBpsPerSlot < MIN_SAFE_BIGINT) {\n throw new Error(\n `computeFundingRateAnnualized: value ${fundingRateBpsPerSlot} exceeds safe integer range`,\n );\n }\n const bpsPerSlot = Number(fundingRateBpsPerSlot);\n const slotsPerYear = 2.5 * 60 * 60 * 24 * 365; // ~400ms slots\n return (bpsPerSlot * slotsPerYear) / 100;\n}\n\n/**\n * Compute margin required for a given notional and initial margin bps.\n *\n * @param notional - Trade notional value in native token units.\n * @param initialMarginBps - Initial margin requirement in basis points (e.g. 1000n = 10%).\n * @returns Required margin in native token units.\n *\n * @example\n * ```ts\n * const margin = computeRequiredMargin(10_000_000_000n, 1000n); // 10% of notional\n * // → 1_000_000_000n\n * ```\n */\nexport function computeRequiredMargin(\n notional: bigint,\n initialMarginBps: bigint,\n): bigint {\n return (notional * initialMarginBps) / 10000n;\n}\n\n/**\n * Compute maximum leverage from initial margin bps.\n *\n * Formula: leverage = 10000 / initialMarginBps\n * Uses scaled arithmetic to preserve precision for fractional leverage values.\n *\n * @param initialMarginBps - Initial margin requirement in basis points (e.g. 500n = 5% → 20x).\n * @returns Maximum leverage as a number (e.g. 20 for 500 bps, 3.003 for 3333 bps).\n * @throws Error if initialMarginBps is zero (infinite leverage is undefined).\n *\n * @example\n * ```ts\n * const maxLev = computeMaxLeverage(500n); // → 20\n * const maxLev2 = computeMaxLeverage(1000n); // → 10\n * const maxLev3 = computeMaxLeverage(3333n); // → 3.003 (not truncated to 3)\n * ```\n */\nexport function computeMaxLeverage(initialMarginBps: bigint): number {\n if (initialMarginBps <= 0n) {\n throw new Error(\"computeMaxLeverage: initialMarginBps must be positive\");\n }\n // Use scaled arithmetic: (10000 * 1e6) / initialMarginBps / 1e6\n // This preserves fractional leverage instead of truncating\n const scaledResult = (10000n * 1_000_000n) / initialMarginBps;\n return Number(scaledResult) / 1_000_000;\n}\n\n/**\n * Compute the maximum amount that can be withdrawn from a position.\n *\n * The withdrawable amount is the capital plus any matured (unreserved) PnL.\n * Reserved PnL is still locked and cannot be withdrawn until the warmup period elapses.\n *\n * Formula: max_withdrawable = capital + max(0, pnl - reserved_pnl)\n *\n * @param capital - Capital allocated to the position (in native token units)\n * @param pnl - Mark-to-market PnL (in native token units, can be negative)\n * @param reservedPnl - PnL that is still locked during warmup (always non-negative)\n * @returns The maximum amount in native units that can be withdrawn without closing the position\n *\n * @example\n * ```ts\n * // Position: 10 SOL capital, +2 SOL mark PnL, 0.5 SOL reserved\n * const max = computeMaxWithdrawable(\n * 10_000_000_000n, // 10 SOL in lamports\n * 2_000_000_000n, // +2 SOL in lamports\n * 500_000_000n // 0.5 SOL reserved in lamports\n * );\n * // Returns: 11_500_000_000n (10 + (2 - 0.5) = 11.5 SOL in lamports)\n * ```\n */\nexport function computeMaxWithdrawable(\n capital: bigint,\n pnl: bigint,\n reservedPnl: bigint,\n): bigint {\n const maturedPnl = pnl - reservedPnl;\n return capital + (maturedPnl > 0n ? maturedPnl : 0n);\n}\n","/**\n * Warmup leverage cap utilities.\n *\n * During the market warmup period, capital is released linearly over\n * `warmupPeriodSlots` slots, which constrains the effective leverage\n * and maximum position size available to traders.\n */\n\nimport { computeMaxLeverage } from \"./trading.js\";\n\n// =============================================================================\n// Warmup leverage cap utilities\n// =============================================================================\n\n/**\n * Compute unlocked capital during the warmup period.\n *\n * Capital is released linearly over `warmupPeriodSlots` slots starting from\n * `warmupStartedAtSlot`. Before warmup starts (startSlot === 0) or if the\n * warmup period is 0, all capital is considered unlocked.\n *\n * @param totalCapital - Total deposited capital (native units).\n * @param currentSlot - The current on-chain slot.\n * @param warmupStartSlot - Slot at which warmup started (0 = not started).\n * @param warmupPeriodSlots - Total slots in the warmup period.\n * @returns The amount of capital currently unlocked.\n */\nexport function computeWarmupUnlockedCapital(\n totalCapital: bigint,\n currentSlot: bigint,\n warmupStartSlot: bigint,\n warmupPeriodSlots: bigint,\n): bigint {\n // No warmup configured or not started → all capital available\n if (warmupPeriodSlots === 0n || warmupStartSlot === 0n) return totalCapital;\n if (totalCapital <= 0n) return 0n;\n\n const elapsed = currentSlot > warmupStartSlot\n ? currentSlot - warmupStartSlot\n : 0n;\n\n // Warmup complete\n if (elapsed >= warmupPeriodSlots) return totalCapital;\n\n // Linear unlock: totalCapital * elapsed / warmupPeriodSlots\n return (totalCapital * elapsed) / warmupPeriodSlots;\n}\n\n/**\n * Compute the effective maximum leverage during the warmup period.\n *\n * During warmup, only unlocked capital can be used as margin. The effective\n * leverage relative to *total* capital is therefore capped at:\n *\n * effectiveMaxLeverage = maxLeverage × (unlockedCapital / totalCapital)\n *\n * This returns a floored integer value (leverage is always a whole number\n * in the UI), with a minimum of 1x if any capital is unlocked.\n *\n * @param initialMarginBps - Initial margin requirement in basis points.\n * @param totalCapital - Total deposited capital (native units).\n * @param currentSlot - The current on-chain slot.\n * @param warmupStartSlot - Slot at which warmup started (0 = not started).\n * @param warmupPeriodSlots - Total slots in the warmup period.\n * @returns The effective maximum leverage (integer, ≥ 1).\n */\nexport function computeWarmupLeverageCap(\n initialMarginBps: bigint,\n totalCapital: bigint,\n currentSlot: bigint,\n warmupStartSlot: bigint,\n warmupPeriodSlots: bigint,\n): number {\n if (initialMarginBps <= 0n) {\n throw new Error(\"computeWarmupLeverageCap: initialMarginBps must be positive\");\n }\n const maxLev = computeMaxLeverage(initialMarginBps);\n\n // No warmup or warmup not started → full leverage\n if (warmupPeriodSlots === 0n || warmupStartSlot === 0n) return maxLev;\n if (totalCapital <= 0n) return 1;\n\n const unlocked = computeWarmupUnlockedCapital(\n totalCapital,\n currentSlot,\n warmupStartSlot,\n warmupPeriodSlots,\n );\n\n if (unlocked <= 0n) return 1; // At least 1x if nothing unlocked yet (slot 0 edge)\n\n // Effective leverage = maxLev * (unlocked / total), floored, min 1\n const scaledResult = (BigInt(maxLev) * unlocked) / totalCapital;\n\n // Ensure conversion to Number doesn't silently truncate for very large values\n if (scaledResult > BigInt(Number.MAX_SAFE_INTEGER)) {\n console.warn(\n `[computeWarmupLeverageCap] Warning: effective leverage ${scaledResult} exceeds MAX_SAFE_INTEGER, ` +\n `returning MAX_SAFE_INTEGER as a safety bound`,\n );\n return Number.MAX_SAFE_INTEGER;\n }\n\n const effectiveLev = Number(scaledResult);\n return Math.max(1, effectiveLev);\n}\n\n/**\n * Compute the maximum position size allowed during warmup.\n *\n * This is the unlocked capital multiplied by the base max leverage.\n * Unlike `computeWarmupLeverageCap` (which gives effective leverage\n * relative to total capital), this gives the absolute notional cap.\n *\n * @param initialMarginBps - Initial margin requirement in basis points.\n * @param totalCapital - Total deposited capital (native units).\n * @param currentSlot - The current on-chain slot.\n * @param warmupStartSlot - Slot at which warmup started (0 = not started).\n * @param warmupPeriodSlots - Total slots in the warmup period.\n * @returns Maximum position size in native units.\n */\nexport function computeWarmupMaxPositionSize(\n initialMarginBps: bigint,\n totalCapital: bigint,\n currentSlot: bigint,\n warmupStartSlot: bigint,\n warmupPeriodSlots: bigint,\n): bigint {\n const maxLev = computeMaxLeverage(initialMarginBps);\n const unlocked = computeWarmupUnlockedCapital(\n totalCapital,\n currentSlot,\n warmupStartSlot,\n warmupPeriodSlots,\n );\n return unlocked * BigInt(maxLev);\n}\n\n/**\n * Warmup progress information for a position.\n */\nexport interface WarmupProgress {\n /** PnL available for withdrawal right now (not locked by warmup). */\n maturedPnl: bigint;\n /** PnL still locked until warmup completes. */\n reservedPnl: bigint;\n /** Progress toward full warmup as a basis point (0–10,000). */\n progressBps: bigint;\n /** Slots remaining until full warmup (0 if fully matured). */\n slotsRemaining: bigint;\n}\n\n/**\n * Compute PnL warmup progress for a position.\n *\n * During the warmup period, a position's unrealized PnL is linearly released.\n * The portion available for withdrawal grows over time. This utility shows:\n * - How much PnL is currently available (matured)\n * - How much is still locked (reserved)\n * - Progress toward full maturation (as %)\n * - Slots remaining\n *\n * Users can display a progress bar or \"unlocks in X slots\" message to give\n * transparency into when their PnL becomes withdrawable.\n *\n * @param currentSlot - Current on-chain slot (from engine state).\n * @param warmupStartedAtSlot - Slot when this position's warmup started.\n * @param warmupPeriodSlots - Total warmup duration in slots (from market config).\n * @param pnl - Total realized + unrealized PnL (from account).\n * @param reservedPnl - PnL locked during warmup (from account).\n * @returns WarmupProgress with matured/reserved PnL, progress %, and slots remaining.\n *\n * @example\n * ```ts\n * const progress = computeWarmupProgress(\n * 10000n, // current slot\n * 9000n, // warmup started at slot 9000\n * 2000n, // warmup period = 2000 slots\n * 1000000000n, // pnl = 1 SOL\n * 600000000n // reserved = 0.6 SOL (60% still locked)\n * );\n * // Returns:\n * // maturedPnl: 400000000n (0.4 SOL available)\n * // reservedPnl: 600000000n (0.6 SOL locked)\n * // progressBps: 5000n (50% complete)\n * // slotsRemaining: 1000n (1000 slots until fully mature)\n * ```\n */\nexport function computeWarmupProgress(\n currentSlot: bigint,\n warmupStartedAtSlot: bigint,\n warmupPeriodSlots: bigint,\n pnl: bigint,\n reservedPnl: bigint,\n): WarmupProgress {\n // Guard: no warmup or hasn't started → all PnL is mature\n if (warmupPeriodSlots === 0n || warmupStartedAtSlot === 0n) {\n return {\n maturedPnl: pnl > 0n ? pnl : 0n,\n reservedPnl: 0n,\n progressBps: 10000n, // 100%\n slotsRemaining: 0n,\n };\n }\n\n const elapsed = currentSlot >= warmupStartedAtSlot\n ? currentSlot - warmupStartedAtSlot\n : 0n;\n\n // If warmup complete, all PnL is mature\n if (elapsed >= warmupPeriodSlots) {\n return {\n maturedPnl: pnl > 0n ? pnl : 0n,\n reservedPnl: 0n,\n progressBps: 10000n, // 100%\n slotsRemaining: 0n,\n };\n }\n\n // Progress: how much of the warmup period has elapsed\n const progressBps = (elapsed * 10000n) / warmupPeriodSlots;\n const slotsRemaining = warmupPeriodSlots - elapsed;\n\n // Matured PnL = total PnL × progress%, capped at total PnL\n // This represents the portion of PnL that has been linearly released\n const maturedPnl = pnl > 0n\n ? ((pnl * progressBps) / 10000n)\n : 0n;\n\n // The actual reserved amount from the account remains reserved, but\n // we can also compute how much is still locked by comparing to matured\n const locked = reservedPnl > 0n ? reservedPnl : 0n;\n\n return {\n maturedPnl,\n reservedPnl: locked,\n progressBps,\n slotsRemaining,\n };\n}\n","/**\n * Input validation utilities for CLI commands.\n * Provides descriptive error messages for invalid input.\n */\n\nimport { PublicKey } from \"@solana/web3.js\";\n\n// Constants for numeric limits\nconst U16_MAX = 65535;\nconst U64_MAX = BigInt(\"18446744073709551615\");\nconst I64_MIN = BigInt(\"-9223372036854775808\");\nconst I64_MAX = BigInt(\"9223372036854775807\");\nconst U128_MAX = (1n << 128n) - 1n;\nconst I128_MIN = -(1n << 127n);\nconst I128_MAX = (1n << 127n) - 1n;\n\n/**\n * Non-empty trimmed string of decimal digits only: `\"0\"` or `[1-9]\\\\d*` (no leading zeros\n * except a single zero). Rejects fractions, scientific notation, hex prefixes, and trailing junk.\n */\nfunction requireDecimalUIntString(value: string, field: string): string {\n const t = value.trim();\n if (t === \"\") {\n throw new ValidationError(field, `\"${value}\" is not a valid number`);\n }\n if (!/^(0|[1-9]\\d*)$/.test(t)) {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid non-negative integer (use decimal digits only, e.g. 123).`\n );\n }\n return t;\n}\n\nexport class ValidationError extends Error {\n constructor(\n public readonly field: string,\n message: string\n ) {\n super(`Invalid ${field}: ${message}`);\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Validate a public key string.\n *\n * @param value - Base58-encoded public key string.\n * @param field - Field name for error messages.\n * @returns Parsed `PublicKey` instance.\n * @throws {@link ValidationError} if the string is not a valid base58 public key.\n *\n * @example\n * ```ts\n * const key = validatePublicKey(\"11111111111111111111111111111111\", \"slab\");\n * ```\n */\nexport function validatePublicKey(value: string, field: string): PublicKey {\n try {\n return new PublicKey(value);\n } catch {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid base58 public key. ` +\n `Example: \"11111111111111111111111111111111\"`\n );\n }\n}\n\n/**\n * Validate a non-negative integer index (u16 range for accounts).\n *\n * @param value - Decimal string representing the index.\n * @param field - Field name for error messages.\n * @returns Parsed integer in `[0, 65535]`.\n * @throws {@link ValidationError} if the value is not a valid u16 integer.\n */\nexport function validateIndex(value: string, field: string): number {\n const t = requireDecimalUIntString(value, field);\n const bi = BigInt(t);\n if (bi > BigInt(U16_MAX)) {\n throw new ValidationError(\n field,\n `must be <= ${U16_MAX} (u16 max), got ${t}`\n );\n }\n // U16 range (0–65535) is always safe to convert to Number\n if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);\n }\n return Number(bi);\n}\n\n/**\n * Validate a non-negative amount (u64 range).\n *\n * @param value - Decimal string representing the amount.\n * @param field - Field name for error messages.\n * @returns Parsed `bigint` in `[0, 2^64 - 1]`.\n * @throws {@link ValidationError} if the value is negative or exceeds u64 max.\n */\nexport function validateAmount(value: string, field: string): bigint {\n const t = value.trim();\n if (!/^(0|[1-9]\\d*)$/.test(t)) {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid non-negative integer. Use decimal digits only.`\n );\n }\n const num = BigInt(t);\n if (num < 0n) {\n throw new ValidationError(field, `must be non-negative, got ${num}`);\n }\n if (num > U64_MAX) {\n throw new ValidationError(\n field,\n `must be <= ${U64_MAX} (u64 max), got ${num}`\n );\n }\n return num;\n}\n\n/**\n * Validate a u128 value.\n */\nexport function validateU128(value: string, field: string): bigint {\n const t = value.trim();\n if (!/^(0|[1-9]\\d*)$/.test(t)) {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid non-negative integer. Use decimal digits only.`\n );\n }\n const num = BigInt(t);\n if (num < 0n) {\n throw new ValidationError(field, `must be non-negative, got ${num}`);\n }\n if (num > U128_MAX) {\n throw new ValidationError(\n field,\n `must be <= ${U128_MAX} (u128 max), got ${num}`\n );\n }\n return num;\n}\n\n/**\n * Validate an i64 value.\n */\nexport function validateI64(value: string, field: string): bigint {\n const t = value.trim();\n if (!/^-?(0|[1-9]\\d*)$/.test(t)) {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid integer. Use decimal digits only, with optional leading minus.`\n );\n }\n const num = BigInt(t);\n if (num < I64_MIN) {\n throw new ValidationError(\n field,\n `must be >= ${I64_MIN} (i64 min), got ${num}`\n );\n }\n if (num > I64_MAX) {\n throw new ValidationError(\n field,\n `must be <= ${I64_MAX} (i64 max), got ${num}`\n );\n }\n return num;\n}\n\n/**\n * Validate an i128 value (trade sizes).\n */\nexport function validateI128(value: string, field: string): bigint {\n const t = value.trim();\n if (!/^-?(0|[1-9]\\d*)$/.test(t)) {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid integer. Use decimal digits only, with optional leading minus.`\n );\n }\n const num = BigInt(t);\n if (num < I128_MIN) {\n throw new ValidationError(\n field,\n `must be >= ${I128_MIN} (i128 min), got ${num}`\n );\n }\n if (num > I128_MAX) {\n throw new ValidationError(\n field,\n `must be <= ${I128_MAX} (i128 max), got ${num}`\n );\n }\n return num;\n}\n\n/**\n * Validate a basis points value (0–10000).\n *\n * @param value - Decimal string representing basis points.\n * @param field - Field name for error messages.\n * @returns Parsed integer in `[0, 10000]`.\n * @throws {@link ValidationError} if the value exceeds 10000.\n */\nexport function validateBps(value: string, field: string): number {\n const t = requireDecimalUIntString(value, field);\n const bi = BigInt(t);\n if (bi > 10000n) {\n throw new ValidationError(\n field,\n `must be <= 10000 (100%), got ${t}`\n );\n }\n // BPS range (0–10000) is always safe to convert to Number\n if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new ValidationError(field, `internal error: bps value exceeds MAX_SAFE_INTEGER`);\n }\n return Number(bi);\n}\n\n/**\n * Validate a u64 value.\n */\nexport function validateU64(value: string, field: string): bigint {\n return validateAmount(value, field);\n}\n\n/**\n * Validate a u16 value.\n */\nexport function validateU16(value: string, field: string): number {\n const t = requireDecimalUIntString(value, field);\n const bi = BigInt(t);\n if (bi > BigInt(U16_MAX)) {\n throw new ValidationError(\n field,\n `must be <= ${U16_MAX} (u16 max), got ${t}`\n );\n }\n // U16 range (0–65535) is always safe to convert to Number\n if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);\n }\n return Number(bi);\n}\n","/**\n * Smart Price Router — automatic oracle selection for any token.\n *\n * Given a token mint, discovers all available price sources (DexScreener, Pyth, Jupiter),\n * ranks them by liquidity/reliability, and returns the best oracle config.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type PriceSourceType = \"pyth\" | \"dex\" | \"jupiter\";\n\nexport interface PriceSource {\n type: PriceSourceType;\n /** Pool address (dex), Pyth feed ID (pyth), or mint (jupiter) */\n address: string;\n /** DEX id for dex sources */\n dexId?: string;\n /** Pair label e.g. \"SOL / USDC\" */\n pairLabel?: string;\n /** USD liquidity depth — higher is better */\n liquidity: number;\n /** Latest spot price in USD */\n price: number;\n /** Confidence score 0-100 (composite of liquidity, staleness, reliability) */\n confidence: number;\n}\n\nexport interface PriceRouterResult {\n mint: string;\n bestSource: PriceSource | null;\n allSources: PriceSource[];\n /** ISO timestamp of resolution */\n resolvedAt: string;\n}\n\n/** Options for {@link resolvePrice}. */\nexport interface ResolvePriceOptions {\n timeoutMs?: number;\n}\n\nconst DEFAULT_RESOLVE_TIMEOUT_MS = 15_000;\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nfunction combineAbortSignals(signals: AbortSignal[]): AbortSignal {\n const already = signals.find((s) => s.aborted);\n if (already) {\n const c = new AbortController();\n c.abort(already.reason);\n return c.signal;\n }\n const active = signals.filter((s) => !s.aborted);\n if (active.length === 0) {\n const c = new AbortController();\n c.abort();\n return c.signal;\n }\n if (active.length === 1) return active[0];\n const ctrl = new AbortController();\n for (const s of active) {\n s.addEventListener(\"abort\", () => ctrl.abort(s.reason), { once: true });\n }\n return ctrl.signal;\n}\n\nconst SUPPORTED_DEX_IDS = new Set([\"pumpswap\", \"raydium\", \"meteora\"]);\n\nfunction parseDexScreenerPairs(json: unknown): PriceSource[] {\n if (!isRecord(json)) return [];\n const rawPairs = json.pairs;\n if (!Array.isArray(rawPairs)) return [];\n const sources: PriceSource[] = [];\n\n for (const pair of rawPairs) {\n if (!isRecord(pair)) continue;\n if (pair.chainId !== \"solana\") continue;\n const dexId = String(pair.dexId || \"\").toLowerCase();\n if (!SUPPORTED_DEX_IDS.has(dexId)) continue;\n\n let liquidity = 0;\n if (isRecord(pair.liquidity) && typeof pair.liquidity.usd === \"number\") {\n liquidity = pair.liquidity.usd;\n }\n if (liquidity < 100) continue;\n\n let confidence = 30;\n if (liquidity > 1_000_000) confidence = 90;\n else if (liquidity > 100_000) confidence = 75;\n else if (liquidity > 10_000) confidence = 60;\n else if (liquidity > 1_000) confidence = 45;\n\n const priceUsd = pair.priceUsd;\n const rawPrice =\n typeof priceUsd === \"string\" || typeof priceUsd === \"number\"\n ? parseFloat(String(priceUsd))\n : NaN;\n if (!Number.isFinite(rawPrice) || rawPrice <= 0) continue;\n const price = rawPrice;\n\n let baseSym = \"?\";\n let quoteSym = \"?\";\n if (isRecord(pair.baseToken) && typeof pair.baseToken.symbol === \"string\") {\n baseSym = pair.baseToken.symbol;\n }\n if (isRecord(pair.quoteToken) && typeof pair.quoteToken.symbol === \"string\") {\n quoteSym = pair.quoteToken.symbol;\n }\n\n const addr = pair.pairAddress;\n sources.push({\n type: \"dex\",\n address: typeof addr === \"string\" ? addr : \"\",\n dexId,\n pairLabel: `${baseSym} / ${quoteSym}`,\n liquidity,\n price,\n confidence,\n });\n }\n\n sources.sort((a, b) => b.liquidity - a.liquidity);\n return sources.slice(0, 10);\n}\n\nfunction parseJupiterMintEntry(\n json: unknown,\n mint: string,\n): { price: number; mintSymbol: string } | null {\n if (!isRecord(json)) return null;\n const data = json.data;\n if (!isRecord(data)) return null;\n const row = data[mint];\n if (!isRecord(row)) return null;\n const rawPrice = row.price;\n if (rawPrice === undefined || rawPrice === null) return null;\n const price = parseFloat(String(rawPrice));\n if (!Number.isFinite(price) || price <= 0) return null;\n let mintSymbol = \"?\";\n if (typeof row.mintSymbol === \"string\") mintSymbol = row.mintSymbol;\n return { price, mintSymbol };}\n\n// ---------------------------------------------------------------------------\n// Top Solana tokens with known Pyth feeds (feed ID → symbol)\n// ---------------------------------------------------------------------------\n\nexport const PYTH_SOLANA_FEEDS: Record<string, { symbol: string; mint: string }> = {\n // SOL\n \"ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d\": { symbol: \"SOL\", mint: \"So11111111111111111111111111111111111111112\" },\n // BTC\n \"e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43\": { symbol: \"BTC\", mint: \"9n4nbM75f5Ui33ZbPYXn59EwSgE8CGsHtAeTH5YFeJ9E\" },\n // ETH\n \"ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace\": { symbol: \"ETH\", mint: \"7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs\" },\n // USDC\n \"eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a\": { symbol: \"USDC\", mint: \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\" },\n // USDT\n \"2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b\": { symbol: \"USDT\", mint: \"Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB\" },\n // BONK\n \"72b021217ca3fe68922a19aaf990109cb9d84e9ad004b4d2025ad6f529314419\": { symbol: \"BONK\", mint: \"DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263\" },\n // JTO\n \"b43660a5f790c69354b0729a5ef9d50d68f1df92107540210b9cccba1f947cc2\": { symbol: \"JTO\", mint: \"jtojtomepa8beP8AuQc6eXt5FriJwfFMwQx2v2f9mCL\" },\n // JUP\n \"0a0408d619e9380abad35060f9192039ed5042fa6f82301d0e48bb52be830996\": { symbol: \"JUP\", mint: \"JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN\" },\n // PYTH\n \"0bbf28e9a841a1cc788f6a361b17ca072d0ea3098a1e5df1c3922d06719579ff\": { symbol: \"PYTH\", mint: \"HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3\" },\n // RAY\n \"91568bae053f70f0c3fbf32eb55df25ec609fb8a21cfb1a0e3b34fc3caa1eab0\": { symbol: \"RAY\", mint: \"4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R\" },\n // ORCA\n \"37505261e557e251f40c2c721e52c4c8bfb2e54a12f450d0e24078276ad51b95\": { symbol: \"ORCA\", mint: \"orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE\" },\n // MNGO\n \"f9abf5eb70a2e68e21b72b68cc6e0a4d25e1d77e1ec16eae5b93068a2cb81f90\": { symbol: \"MNGO\", mint: \"MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac\" },\n // MSOL\n \"c2289a6a43d2ce91c6f55caec370f4acc38a2ed477f58813334c6d03749ff2a4\": { symbol: \"MSOL\", mint: \"mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So\" },\n // JITOSOL\n \"67be9f519b95cf24338801051f9a808eff0a578ccb388db73b7f6fe1de019ffb\": { symbol: \"JITOSOL\", mint: \"J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn\" },\n // WIF\n \"4ca4beeca86f0d164160323817a4e42b10010a724c2217c6ee41b54e6c5c4b03\": { symbol: \"WIF\", mint: \"EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm\" },\n // RENDER\n \"3573eb14b04aa0e4f7cf1e7ae1c2a0e3bc6100b2e476876ca079e10e2c42d7c6\": { symbol: \"RENDER\", mint: \"rndrizKT3MK1iimdxRdWabcF7Zg7AR5T4nud4EkHBof\" },\n // W\n \"eff7446475e218517566ea99e72a4abec2e1bd8498b43b7d8331e29dcb059389\": { symbol: \"W\", mint: \"85VBFQZC9TZkfaptBWjvUw7YbZjy52A6mjtPGjstQAmQ\" },\n // TNSR\n \"05ecd4597cd48fe13d6cc3596c62af4f9675aee06e2e0ca164a73be4b0813f3b\": { symbol: \"TNSR\", mint: \"TNSRxcUxoT9xBG3de7PiJyTDYu7kskLqcpddxnEJAS6\" },\n // HNT\n \"649fdd7ec08e8e2a20f425729854e90293dcbe2376abc47197a14da6ff339756\": { symbol: \"HNT\", mint: \"hntyVP6YFm1Hg25TN9WGLqM12b8TQmcknKrdu1oxWux\" },\n // MOBILE\n \"ff4c53361e36a9b1caa490f1e46e07e3c472d54d2a4856a1e4609bd4db36bff0\": { symbol: \"MOBILE\", mint: \"mb1eu7TzEc71KxDpsmsKoucSSuuoGLv1drys1oP2jh6\" },\n // IOT\n \"8bdd20f0c68bf7370a19389bbb3d17c1db7956c38efa08b2f3dd0e5db9b8c1ef\": { symbol: \"IOT\", mint: \"iotEVVZLEywoTn1QdwNPddxPWszn3zFhEot3MfL9fns\" },\n};\n\n// Reverse lookup: mint → feed ID\nconst MINT_TO_PYTH_FEED = new Map<string, { feedId: string; symbol: string }>();\nfor (const [feedId, info] of Object.entries(PYTH_SOLANA_FEEDS)) {\n MINT_TO_PYTH_FEED.set(info.mint, { feedId, symbol: info.symbol });\n}\n\n// ---------------------------------------------------------------------------\n// DexScreener fetcher\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_FETCH_TIMEOUT_MS = 10_000;\n\nfunction effectiveSignal(signal?: AbortSignal): AbortSignal {\n return signal ?? AbortSignal.timeout(DEFAULT_FETCH_TIMEOUT_MS);\n}\n\nasync function fetchDexSources(mint: string, signal?: AbortSignal): Promise<PriceSource[]> {\n try {\n const resp = await fetch(\n `https://api.dexscreener.com/latest/dex/tokens/${encodeURIComponent(mint)}`,\n {\n signal: effectiveSignal(signal),\n headers: { \"User-Agent\": \"percolator/1.0\" },\n },\n );\n if (!resp.ok) {\n console.debug(`[fetchDexSources] HTTP ${resp.status} for mint ${mint}`);\n return [];\n }\n const json: unknown = await resp.json();\n return parseDexScreenerPairs(json);\n } catch (err) {\n console.warn(\n `[fetchDexSources] Error fetching DexScreener data for mint ${mint}:`,\n err instanceof Error ? err.message : String(err),\n );\n return [];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Pyth lookup\n// ---------------------------------------------------------------------------\n\nfunction lookupPythSource(mint: string): PriceSource | null {\n const entry = MINT_TO_PYTH_FEED.get(mint);\n if (!entry) return null;\n return {\n type: \"pyth\",\n address: entry.feedId,\n pairLabel: `${entry.symbol} / USD (Pyth)`,\n liquidity: Number.MAX_SAFE_INTEGER, // Pyth is considered deep liquidity\n price: 0, // We don't fetch live price here; caller can enrich\n confidence: 95, // Pyth is highest reliability for supported tokens\n };\n}\n\n// ---------------------------------------------------------------------------\n// Jupiter price fallback\n// ---------------------------------------------------------------------------\n\nasync function fetchJupiterSource(mint: string, signal?: AbortSignal): Promise<PriceSource | null> {\n try {\n const resp = await fetch(\n `https://api.jup.ag/price/v2?ids=${encodeURIComponent(mint)}`,\n {\n signal: effectiveSignal(signal),\n headers: { \"User-Agent\": \"percolator/1.0\" },\n },\n );\n if (!resp.ok) {\n console.debug(`[fetchJupiterSource] HTTP ${resp.status} for mint ${mint}`);\n return null;\n }\n const json: unknown = await resp.json();\n const row = parseJupiterMintEntry(json, mint);\n if (!row) {\n console.debug(`[fetchJupiterSource] No price data from Jupiter for mint ${mint}`);\n return null;\n }\n return {\n type: \"jupiter\",\n address: mint,\n pairLabel: `${row.mintSymbol} / USD (Jupiter)`,\n liquidity: 0, // Jupiter aggregator — no single pool liquidity\n price: row.price,\n confidence: 40, // Fallback — lower confidence\n };\n } catch (err) {\n console.warn(\n `[fetchJupiterSource] Error fetching Jupiter data for mint ${mint}:`,\n err instanceof Error ? err.message : String(err),\n );\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Main resolver\n// ---------------------------------------------------------------------------\n\nexport async function resolvePrice(\n mint: string,\n signal?: AbortSignal,\n options?: ResolvePriceOptions,\n): Promise<PriceRouterResult> {\n const timeoutMs = options?.timeoutMs ?? DEFAULT_RESOLVE_TIMEOUT_MS;\n const timeoutSignal = AbortSignal.timeout(timeoutMs);\n const effectiveSignal = signal\n ? combineAbortSignals([signal, timeoutSignal])\n : timeoutSignal;\n\n const [dexSources, jupiterSource] = await Promise.all([\n fetchDexSources(mint, effectiveSignal),\n fetchJupiterSource(mint, effectiveSignal),\n ]);\n\n const pythSource = lookupPythSource(mint);\n\n const allSources: PriceSource[] = [];\n\n // Add Pyth if available (highest priority for supported tokens)\n if (pythSource) {\n // Enrich Pyth price from DEX and/or Jupiter — cross-validate when both exist\n const dexPrice = dexSources[0]?.price ?? 0;\n const jupPrice = jupiterSource?.price ?? 0;\n\n if (dexPrice > 0 && jupPrice > 0) {\n // Cross-validate: reject if sources diverge by more than 50%\n const mid = (dexPrice + jupPrice) / 2;\n const deviation = Math.abs(dexPrice - jupPrice) / mid;\n if (deviation > 0.5) {\n // Sources disagree significantly — don't enrich Pyth, lower confidence\n pythSource.price = 0;\n pythSource.confidence = 20;\n } else {\n pythSource.price = mid;\n }\n } else {\n // Only one source available — use it but note reduced validation\n pythSource.price = dexPrice || jupPrice || 0;\n }\n allSources.push(pythSource);\n }\n\n // Add DEX sources\n allSources.push(...dexSources);\n\n // Add Jupiter as fallback\n if (jupiterSource) {\n allSources.push(jupiterSource);\n }\n\n // Sort by confidence descending (already accounts for liquidity/reliability)\n allSources.sort((a, b) => b.confidence - a.confidence);\n\n return {\n mint,\n bestSource: allSources[0] || null,\n allSources,\n resolvedAt: new Date().toISOString(),\n };\n}\n"],"mappings":"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IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA;AAAA,EAEA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,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","names":["dv","PublicKey","PublicKey","AccountKind","PublicKey","PublicKey","PublicKey","TOKEN_PROGRAM_ID","PublicKey","PublicKey","ENGINE_BITMAP_OFF_V0","dv","readU16LE","readU64LE","readI64LE","readU128LE","readI128LE","results","PublicKey","PublicKey","PublicKey","readU64LE","dv","readU128LE","readU8","PublicKey","TOKEN_PROGRAM_ID","PublicKey","SystemProgram","SYSVAR_RENT_PUBKEY","SYSVAR_CLOCK_PUBKEY","TOKEN_PROGRAM_ID","PublicKey","PublicKey","readU64LE","readU16LE","TOKEN_PROGRAM_ID","SystemProgram","SYSVAR_RENT_PUBKEY","SYSVAR_CLOCK_PUBKEY","SYSVAR_CLOCK_PUBKEY","SYSVAR_CLOCK_PUBKEY","Connection","TransactionInstruction","TransactionInstruction","PublicKey","Transaction","LIGHTHOUSE_PROGRAM_ID_STR","PublicKey","effectiveSignal"]}
1
+ {"version":3,"sources":["../src/abi/encode.ts","../src/abi/instructions.ts","../src/abi/accounts.ts","../src/abi/errors.ts","../src/solana/slab.ts","../src/solana/pda.ts","../src/solana/ata.ts","../src/solana/discovery.ts","../src/solana/static-markets.ts","../src/solana/dex-oracle.ts","../src/solana/oracle.ts","../src/solana/token-program.ts","../src/solana/stake.ts","../src/config/program-ids.ts","../src/solana/adl.ts","../src/solana/rpc-pool.ts","../src/runtime/tx.ts","../src/runtime/lighthouse.ts","../src/math/trading.ts","../src/math/warmup.ts","../src/validation.ts","../src/oracle/price-router.ts"],"sourcesContent":["import { PublicKey } from \"@solana/web3.js\";\n\nconst U8_MAX = 255;\nconst U16_MAX = 65_535;\nconst U32_MAX = 4_294_967_295;\n\n/**\n * Encode u8 (1 byte)\n */\nexport function encU8(val: number): Uint8Array {\n if (!Number.isInteger(val) || val < 0 || val > 0xFF) {\n throw new Error(`encU8: value out of range (0..255), got ${val}`);\n }\n return new Uint8Array([val]);\n}\n\n/**\n * Encode u16 little-endian (2 bytes)\n */\nexport function encU16(val: number): Uint8Array {\n if (!Number.isInteger(val) || val < 0 || val > 0xFFFF) {\n throw new Error(`encU16: value out of range (0..65535), got ${val}`);\n }\n const buf = new Uint8Array(2);\n new DataView(buf.buffer).setUint16(0, val, true);\n return buf;\n}\n\n/**\n * Encode u32 little-endian (4 bytes)\n */\nexport function encU32(val: number): Uint8Array {\n if (!Number.isInteger(val) || val < 0 || val > 0xFFFFFFFF) {\n throw new Error(`encU32: value out of range (0..4294967295), got ${val}`);\n }\n const buf = new Uint8Array(4);\n new DataView(buf.buffer).setUint32(0, val, true);\n return buf;\n}\n\n/**\n * Encode u64 little-endian (8 bytes)\n * Input: bigint or string (decimal)\n */\nexport function encU64(val: bigint | string): Uint8Array {\n const n = typeof val === \"string\" ? BigInt(val) : val;\n if (n < 0n) throw new Error(\"encU64: value must be non-negative\");\n if (n > 0xffff_ffff_ffff_ffffn) throw new Error(\"encU64: value exceeds u64 max\");\n const buf = new Uint8Array(8);\n new DataView(buf.buffer).setBigUint64(0, n, true);\n return buf;\n}\n\n/**\n * Encode i64 little-endian (8 bytes), two's complement\n * Input: bigint or string (decimal, may be negative)\n */\nexport function encI64(val: bigint | string): Uint8Array {\n const n = typeof val === \"string\" ? BigInt(val) : val;\n const min = -(1n << 63n);\n const max = (1n << 63n) - 1n;\n if (n < min || n > max) throw new Error(\"encI64: value out of range\");\n const buf = new Uint8Array(8);\n new DataView(buf.buffer).setBigInt64(0, n, true);\n return buf;\n}\n\n/**\n * Encode u128 little-endian (16 bytes)\n * Input: bigint or string (decimal)\n */\nexport function encU128(val: bigint | string): Uint8Array {\n const n = typeof val === \"string\" ? BigInt(val) : val;\n if (n < 0n) throw new Error(\"encU128: value must be non-negative\");\n const max = (1n << 128n) - 1n;\n if (n > max) throw new Error(\"encU128: value exceeds u128 max\");\n const buf = new Uint8Array(16);\n const view = new DataView(buf.buffer);\n const lo = n & 0xffff_ffff_ffff_ffffn;\n const hi = n >> 64n;\n view.setBigUint64(0, lo, true);\n view.setBigUint64(8, hi, true);\n return buf;\n}\n\n/**\n * Encode i128 little-endian (16 bytes), two's complement\n * Input: bigint or string (decimal, may be negative)\n */\nexport function encI128(val: bigint | string): Uint8Array {\n const n = typeof val === \"string\" ? BigInt(val) : val;\n const min = -(1n << 127n);\n const max = (1n << 127n) - 1n;\n if (n < min || n > max) throw new Error(\"encI128: value out of range\");\n\n // Convert to unsigned representation (two's complement)\n let unsigned = n;\n if (n < 0n) {\n unsigned = (1n << 128n) + n;\n }\n\n const buf = new Uint8Array(16);\n const view = new DataView(buf.buffer);\n const lo = unsigned & 0xffff_ffff_ffff_ffffn;\n const hi = unsigned >> 64n;\n view.setBigUint64(0, lo, true);\n view.setBigUint64(8, hi, true);\n return buf;\n}\n\n/**\n * Encode a PublicKey (32 bytes)\n * Input: PublicKey or base58 string\n */\nexport function encPubkey(val: PublicKey | string): Uint8Array {\n try {\n const pk = typeof val === \"string\" ? new PublicKey(val) : val;\n return pk.toBytes();\n } catch (e: unknown) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new Error(`encPubkey: invalid public key \"${String(val)}\" — ${msg}`);\n }\n}\n\n/**\n * Encode a boolean as u8 (0 = false, 1 = true)\n */\nexport function encBool(val: boolean): Uint8Array {\n return encU8(val ? 1 : 0);\n}\n\n/**\n * Concatenate multiple Uint8Arrays (replaces Buffer.concat)\n */\nexport function concatBytes(...arrays: Uint8Array[]): Uint8Array {\n const totalLen = arrays.reduce((sum, a) => sum + a.length, 0);\n const result = new Uint8Array(totalLen);\n let offset = 0;\n for (const arr of arrays) {\n result.set(arr, offset);\n offset += arr.length;\n }\n return result;\n}\n","import { PublicKey } from \"@solana/web3.js\";\nimport {\n encU8,\n encU16,\n encU32,\n encU64,\n encI64,\n encU128,\n encI128,\n encPubkey,\n concatBytes,\n} from \"./encode.js\";\n\n/**\n * Oracle price constraints.\n * Maximum oracle price that can be pushed to the on-chain oracle authority.\n */\nexport const MAX_ORACLE_PRICE = 1_000_000_000_000n; // 1 trillion e6 = 1M USD/unit\n\n/**\n * Instruction tags - exact match to Rust ix::Instruction::decode\n */\nexport const IX_TAG = {\n InitMarket: 0,\n InitUser: 1,\n InitLP: 2,\n DepositCollateral: 3,\n WithdrawCollateral: 4,\n KeeperCrank: 5,\n TradeNoCpi: 6,\n LiquidateAtOracle: 7,\n CloseAccount: 8,\n TopUpInsurance: 9,\n TradeCpi: 10,\n SetRiskThreshold: 11,\n UpdateAdmin: 12,\n CloseSlab: 13,\n UpdateConfig: 14,\n SetMaintenanceFee: 15,\n SetOracleAuthority: 16,\n PushOraclePrice: 17,\n SetOraclePriceCap: 18,\n ResolveMarket: 19,\n WithdrawInsurance: 20,\n AdminForceClose: 21,\n UpdateRiskParams: 22,\n RenounceAdmin: 23,\n // Tags 24–26 (CreateInsuranceMint / DepositInsuranceLP / WithdrawInsuranceLP)\n // were removed in SDK v1.0.0-beta.3. Replaced by percolator-stake.\n PauseMarket: 27,\n UnpauseMarket: 28,\n AcceptAdmin: 29,\n SetInsuranceWithdrawPolicy: 30,\n WithdrawInsuranceLimited: 31,\n SetPythOracle: 32,\n UpdateMarkPrice: 33,\n UpdateHyperpMark: 34,\n TradeCpiV2: 35,\n UnresolveMarket: 36,\n CreateLpVault: 37,\n LpVaultDeposit: 38,\n LpVaultWithdraw: 39,\n LpVaultCrankFees: 40,\n /** PERC-306: Fund per-market isolated insurance balance */\n FundMarketInsurance: 41,\n /** PERC-306: Set insurance isolation BPS for a market */\n SetInsuranceIsolation: 42,\n // Tag 43 is ChallengeSettlement on-chain (PERC-314).\n // PERC-305 (ExecuteAdl) is NOT implemented on-chain — do NOT assign tag 43 here.\n // When PERC-305 is implemented, assign a new unused tag (≥47).\n /** PERC-314: Challenge settlement price during dispute window */\n ChallengeSettlement: 43,\n /** PERC-314: Resolve dispute (admin adjudication) */\n ResolveDispute: 44,\n /** PERC-315: Deposit LP vault tokens as perp collateral */\n DepositLpCollateral: 45,\n /** PERC-315: Withdraw LP collateral (position must be closed) */\n WithdrawLpCollateral: 46,\n /** PERC-309: Queue a large LP withdrawal (user; creates withdraw_queue PDA). */\n QueueWithdrawal: 47,\n /** PERC-309: Claim one epoch tranche from a queued LP withdrawal (user). */\n ClaimQueuedWithdrawal: 48,\n /** PERC-309: Cancel a queued withdrawal, refund remaining LP tokens (user). */\n CancelQueuedWithdrawal: 49,\n /** PERC-305: Auto-deleverage — surgically close profitable positions when PnL cap is exceeded (permissionless). */\n ExecuteAdl: 50,\n /** Close a stale slab of an invalid/old layout and recover rent SOL (admin only). */\n CloseStaleSlabs: 51,\n /** Reclaim rent from an uninitialised slab whose market creation failed mid-flow. Slab must sign. */\n ReclaimSlabRent: 52,\n /** Permissionless on-chain audit crank: verifies conservation invariants and pauses market on violation. */\n AuditCrank: 53,\n /** Cross-Market Portfolio Margining: SetOffsetPair */\n SetOffsetPair: 54,\n /** Cross-Market Portfolio Margining: AttestCrossMargin */\n AttestCrossMargin: 55,\n /** PERC-622: Advance oracle phase (permissionless crank) */\n AdvanceOraclePhase: 56,\n /** PERC-623: Top up a market's keeper fund (permissionless) */\n TopUpKeeperFund: 57,\n /** PERC-629: Slash a market creator's deposit (permissionless) */\n SlashCreationDeposit: 58,\n /** PERC-628: Initialize the global shared vault (admin) */\n InitSharedVault: 59,\n /** PERC-628: Allocate virtual liquidity to a market (admin) */\n AllocateMarket: 60,\n /** PERC-628: Queue a withdrawal for the current epoch */\n QueueWithdrawalSV: 61,\n /** PERC-628: Claim a queued withdrawal after epoch elapses */\n ClaimEpochWithdrawal: 62,\n /** PERC-628: Advance the shared vault epoch (permissionless crank) */\n AdvanceEpoch: 63,\n /** PERC-608: Mint a Position NFT for a user's open position. */\n MintPositionNft: 64,\n /** PERC-608: Transfer position ownership via the NFT (keeper-gated). */\n TransferPositionOwnership: 65,\n /** PERC-608: Burn the Position NFT when a position is closed. */\n BurnPositionNft: 66,\n /** PERC-608: Keeper sets pending_settlement flag before a funding transfer. */\n SetPendingSettlement: 67,\n /** PERC-608: Keeper clears pending_settlement flag after KeeperCrank. */\n ClearPendingSettlement: 68,\n /** PERC-608: Internal CPI call from percolator-nft TransferHook to update on-chain owner. */\n TransferOwnershipCpi: 69,\n /** PERC-8111: Set per-wallet position cap (admin only, cap_e6=0 disables). */\n SetWalletCap: 70,\n /** PERC-8110: Set OI imbalance hard-block threshold (admin only). */\n SetOiImbalanceHardBlock: 71,\n /** PERC-8270: Rescue orphan vault — recover tokens from a closed market's vault (admin). */\n RescueOrphanVault: 72,\n /** PERC-8270: Close orphan slab — reclaim rent from a slab whose market closed unexpectedly (admin). */\n CloseOrphanSlab: 73,\n /** PERC-SetDexPool: Pin admin-approved DEX pool address for a HYPERP market (admin). */\n SetDexPool: 74,\n /** CPI to the matcher program to initialize a matcher context account for an LP slot. Admin-only. */\n InitMatcherCtx: 75,\n} as const;\nObject.freeze(IX_TAG);\n\n/**\n * InitMarket instruction data (256 bytes total)\n * Layout: tag(1) + admin(32) + mint(32) + indexFeedId(32) +\n * maxStaleSecs(8) + confFilter(2) + invert(1) + unitScale(4) +\n * RiskParams(144)\n *\n * Note: indexFeedId is the Pyth Pull feed ID (32 bytes hex), NOT an oracle pubkey.\n * The program validates PriceUpdateV2 accounts against this feed ID at runtime.\n */\nexport interface InitMarketArgs {\n admin: PublicKey | string;\n collateralMint: PublicKey | string;\n indexFeedId: string; // Pyth feed ID (hex string, 64 chars without 0x prefix). All zeros = Hyperp mode.\n maxStalenessSecs: bigint | string; // Max staleness in SECONDS (Pyth Pull uses unix timestamps)\n confFilterBps: number;\n invert: number; // 0 = no inversion, 1 = invert oracle price (USD/SOL -> SOL/USD)\n unitScale: number; // Lamports per unit (0 = no scaling, e.g. 1000 = 1 SOL = 1,000,000 units)\n initialMarkPriceE6: bigint | string; // Initial mark price (required non-zero for Hyperp mode)\n warmupPeriodSlots: bigint | string;\n maintenanceMarginBps: bigint | string;\n initialMarginBps: bigint | string;\n tradingFeeBps: bigint | string;\n maxAccounts: bigint | string;\n newAccountFee: bigint | string;\n riskReductionThreshold: bigint | string;\n maintenanceFeePerSlot: bigint | string;\n maxCrankStalenessSlots: bigint | string;\n liquidationFeeBps: bigint | string;\n liquidationFeeCap: bigint | string;\n liquidationBufferBps: bigint | string;\n minLiquidationAbs: bigint | string;\n}\n\n/**\n * Encode a Pyth feed ID (hex string) to 32-byte Uint8Array.\n */\nconst HEX_RE = /^[0-9a-fA-F]{64}$/;\n\nfunction encodeFeedId(feedId: string): Uint8Array {\n const hex = feedId.startsWith(\"0x\") ? feedId.slice(2) : feedId;\n if (!HEX_RE.test(hex)) {\n throw new Error(\n `Invalid feed ID: expected 64 hex chars, got \"${hex.length === 64 ? \"non-hex characters\" : hex.length + \" chars\"}\"`,\n );\n }\n const bytes = new Uint8Array(32);\n for (let i = 0; i < 64; i += 2) {\n const byte = parseInt(hex.substring(i, i + 2), 16);\n if (Number.isNaN(byte)) {\n throw new Error(\n `Failed to parse hex byte at position ${i}: \"${hex.substring(i, i + 2)}\"`,\n );\n }\n bytes[i / 2] = byte;\n }\n return bytes;\n}\n\nconst INIT_MARKET_DATA_LEN = 264;\n\nexport function encodeInitMarket(args: InitMarketArgs): Uint8Array {\n const data = concatBytes(\n encU8(IX_TAG.InitMarket),\n encPubkey(args.admin),\n encPubkey(args.collateralMint),\n encodeFeedId(args.indexFeedId),\n encU64(args.maxStalenessSecs),\n encU16(args.confFilterBps),\n encU8(args.invert),\n encU32(args.unitScale),\n encU64(args.initialMarkPriceE6),\n encU64(args.warmupPeriodSlots),\n encU64(args.maintenanceMarginBps),\n encU64(args.initialMarginBps),\n encU64(args.tradingFeeBps),\n encU64(args.maxAccounts),\n encU128(args.newAccountFee),\n encU128(args.riskReductionThreshold),\n encU128(args.maintenanceFeePerSlot),\n encU64(args.maxCrankStalenessSlots),\n encU64(args.liquidationFeeBps),\n encU128(args.liquidationFeeCap),\n encU64(args.liquidationBufferBps),\n encU128(args.minLiquidationAbs),\n );\n if (data.length !== INIT_MARKET_DATA_LEN) {\n throw new Error(\n `encodeInitMarket: expected ${INIT_MARKET_DATA_LEN} bytes, got ${data.length}`,\n );\n }\n return data;\n}\n\n/**\n * InitUser instruction data (9 bytes)\n */\nexport interface InitUserArgs {\n feePayment: bigint | string;\n}\n\nexport function encodeInitUser(args: InitUserArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.InitUser), encU64(args.feePayment));\n}\n\n/**\n * InitLP instruction data (73 bytes)\n */\nexport interface InitLPArgs {\n matcherProgram: PublicKey | string;\n matcherContext: PublicKey | string;\n feePayment: bigint | string;\n}\n\nexport function encodeInitLP(args: InitLPArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.InitLP),\n encPubkey(args.matcherProgram),\n encPubkey(args.matcherContext),\n encU64(args.feePayment),\n );\n}\n\n/**\n * DepositCollateral instruction data (11 bytes)\n */\nexport interface DepositCollateralArgs {\n userIdx: number;\n amount: bigint | string;\n}\n\nexport function encodeDepositCollateral(args: DepositCollateralArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.DepositCollateral),\n encU16(args.userIdx),\n encU64(args.amount),\n );\n}\n\n/**\n * WithdrawCollateral instruction data (11 bytes)\n */\nexport interface WithdrawCollateralArgs {\n userIdx: number;\n amount: bigint | string;\n}\n\nexport function encodeWithdrawCollateral(args: WithdrawCollateralArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.WithdrawCollateral),\n encU16(args.userIdx),\n encU64(args.amount),\n );\n}\n\n/**\n * KeeperCrank instruction data (4 bytes)\n * Funding rate is computed on-chain from LP inventory.\n */\nexport interface KeeperCrankArgs {\n callerIdx: number;\n allowPanic: boolean;\n}\n\nexport function encodeKeeperCrank(args: KeeperCrankArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.KeeperCrank),\n encU16(args.callerIdx),\n encU8(args.allowPanic ? 1 : 0),\n );\n}\n\n/**\n * TradeNoCpi instruction data (21 bytes)\n */\nexport interface TradeNoCpiArgs {\n lpIdx: number;\n userIdx: number;\n size: bigint | string;\n}\n\nexport function encodeTradeNoCpi(args: TradeNoCpiArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.TradeNoCpi),\n encU16(args.lpIdx),\n encU16(args.userIdx),\n encI128(args.size),\n );\n}\n\n/**\n * LiquidateAtOracle instruction data (3 bytes)\n */\nexport interface LiquidateAtOracleArgs {\n targetIdx: number;\n}\n\nexport function encodeLiquidateAtOracle(args: LiquidateAtOracleArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.LiquidateAtOracle),\n encU16(args.targetIdx),\n );\n}\n\n/**\n * CloseAccount instruction data (3 bytes)\n */\nexport interface CloseAccountArgs {\n userIdx: number;\n}\n\nexport function encodeCloseAccount(args: CloseAccountArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.CloseAccount), encU16(args.userIdx));\n}\n\n/**\n * TopUpInsurance instruction data (9 bytes)\n */\nexport interface TopUpInsuranceArgs {\n amount: bigint | string;\n}\n\nexport function encodeTopUpInsurance(args: TopUpInsuranceArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.TopUpInsurance), encU64(args.amount));\n}\n\n/**\n * TradeCpi instruction data (21 bytes)\n */\nexport interface TradeCpiArgs {\n lpIdx: number;\n userIdx: number;\n size: bigint | string;\n}\n\nexport function encodeTradeCpi(args: TradeCpiArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.TradeCpi),\n encU16(args.lpIdx),\n encU16(args.userIdx),\n encI128(args.size),\n );\n}\n\n/**\n * TradeCpiV2 instruction data (22 bytes) — PERC-154 optimized trade CPI.\n *\n * Same as TradeCpi but includes a caller-provided PDA bump byte.\n * Uses create_program_address instead of find_program_address,\n * saving ~1500 CU per trade. The bump should be obtained once via\n * deriveLpPda() and cached for the lifetime of the market.\n */\nexport interface TradeCpiV2Args {\n lpIdx: number;\n userIdx: number;\n size: bigint | string;\n bump: number;\n}\n\nexport function encodeTradeCpiV2(args: TradeCpiV2Args): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.TradeCpiV2),\n encU16(args.lpIdx),\n encU16(args.userIdx),\n encI128(args.size),\n encU8(args.bump),\n );\n}\n\n/**\n * SetRiskThreshold instruction data (17 bytes)\n */\nexport interface SetRiskThresholdArgs {\n newThreshold: bigint | string;\n}\n\nexport function encodeSetRiskThreshold(args: SetRiskThresholdArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.SetRiskThreshold),\n encU128(args.newThreshold),\n );\n}\n\n/**\n * UpdateAdmin instruction data (33 bytes)\n */\nexport interface UpdateAdminArgs {\n newAdmin: PublicKey | string;\n}\n\nexport function encodeUpdateAdmin(args: UpdateAdminArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.UpdateAdmin), encPubkey(args.newAdmin));\n}\n\n/**\n * CloseSlab instruction data (1 byte)\n */\nexport function encodeCloseSlab(): Uint8Array {\n return encU8(IX_TAG.CloseSlab);\n}\n\n/**\n * UpdateConfig instruction data\n * Updates funding and threshold parameters at runtime (admin only)\n */\nexport interface UpdateConfigArgs {\n // Funding parameters\n fundingHorizonSlots: bigint | string;\n fundingKBps: bigint | string;\n fundingInvScaleNotionalE6: bigint | string;\n fundingMaxPremiumBps: bigint | string;\n fundingMaxBpsPerSlot: bigint | string;\n // Threshold parameters\n threshFloor: bigint | string;\n threshRiskBps: bigint | string;\n threshUpdateIntervalSlots: bigint | string;\n threshStepBps: bigint | string;\n threshAlphaBps: bigint | string;\n threshMin: bigint | string;\n threshMax: bigint | string;\n threshMinStep: bigint | string;\n}\n\nexport function encodeUpdateConfig(args: UpdateConfigArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.UpdateConfig),\n encU64(args.fundingHorizonSlots),\n encU64(args.fundingKBps),\n encU128(args.fundingInvScaleNotionalE6),\n encI64(args.fundingMaxPremiumBps), // Rust: i64 (can be negative)\n encI64(args.fundingMaxBpsPerSlot), // Rust: i64 (can be negative)\n encU128(args.threshFloor),\n encU64(args.threshRiskBps),\n encU64(args.threshUpdateIntervalSlots),\n encU64(args.threshStepBps),\n encU64(args.threshAlphaBps),\n encU128(args.threshMin),\n encU128(args.threshMax),\n encU128(args.threshMinStep),\n );\n}\n\n/**\n * SetMaintenanceFee instruction data (17 bytes)\n */\nexport interface SetMaintenanceFeeArgs {\n newFee: bigint | string;\n}\n\nexport function encodeSetMaintenanceFee(args: SetMaintenanceFeeArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.SetMaintenanceFee),\n encU128(args.newFee),\n );\n}\n\n/**\n * SetOracleAuthority instruction data (33 bytes)\n * Sets the oracle price authority. Pass zero pubkey to disable and require Pyth/Chainlink.\n */\nexport interface SetOracleAuthorityArgs {\n newAuthority: PublicKey | string;\n}\n\nexport function encodeSetOracleAuthority(args: SetOracleAuthorityArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.SetOracleAuthority),\n encPubkey(args.newAuthority),\n );\n}\n\n/**\n * PushOraclePrice instruction data (17 bytes)\n * Push a new oracle price (oracle authority only).\n * The price should be in e6 format and already include any inversion/scaling.\n */\nexport interface PushOraclePriceArgs {\n priceE6: bigint | string;\n timestamp: bigint | string;\n}\n\n/**\n * Encode PushOraclePrice instruction data with validation.\n *\n * Validates oracle price constraints:\n * - Price cannot be zero (division by zero in on-chain engine)\n * - Price cannot exceed MAX_ORACLE_PRICE (prevents overflow in price math)\n *\n * @param args - PushOraclePrice arguments\n * @returns Encoded instruction data (17 bytes)\n * @throws Error if price is 0 or exceeds MAX_ORACLE_PRICE\n */\nexport function encodePushOraclePrice(args: PushOraclePriceArgs): Uint8Array {\n const price = typeof args.priceE6 === \"string\" ? BigInt(args.priceE6) : args.priceE6;\n\n if (price === 0n) {\n throw new Error(\"encodePushOraclePrice: price cannot be zero (division by zero in engine)\");\n }\n\n if (price > MAX_ORACLE_PRICE) {\n throw new Error(`encodePushOraclePrice: price exceeds maximum (${MAX_ORACLE_PRICE}), got ${price}`);\n }\n\n return concatBytes(\n encU8(IX_TAG.PushOraclePrice),\n encU64(price),\n encI64(args.timestamp),\n );\n}\n\n/**\n * SetOraclePriceCap instruction data (9 bytes)\n * Set oracle price circuit breaker cap (admin only).\n *\n * max_change_e2bps: maximum oracle price movement per slot in 0.01 bps units.\n * 1_000_000 = 100% max move per slot.\n *\n * ⚠️ PERC-8191 (PR#150): cap=0 is NO LONGER accepted for admin-oracle markets.\n * - Hyperp markets: rejected if cap < DEFAULT_HYPERP_PRICE_CAP_E2BPS (1000).\n * - Admin-oracle markets: rejected if cap == 0 (circuit breaker bypass prevention).\n * - Pyth-pinned markets: immune (oracle_authority zeroed), any value accepted.\n *\n * Use a non-zero cap for all admin-oracle and Hyperp markets.\n */\nexport interface SetOraclePriceCapArgs {\n maxChangeE2bps: bigint | string;\n}\n\nexport function encodeSetOraclePriceCap(args: SetOraclePriceCapArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.SetOraclePriceCap),\n encU64(args.maxChangeE2bps),\n );\n}\n\n/**\n * ResolveMarket instruction data (1 byte)\n * Resolves a binary/premarket - sets RESOLVED flag, positions force-closed via crank.\n * Requires admin oracle price (authority_price_e6) to be set first.\n */\nexport function encodeResolveMarket(): Uint8Array {\n return encU8(IX_TAG.ResolveMarket);\n}\n\n/**\n * WithdrawInsurance instruction data (1 byte)\n * Withdraw insurance fund to admin (requires RESOLVED and all positions closed).\n */\nexport function encodeWithdrawInsurance(): Uint8Array {\n return encU8(IX_TAG.WithdrawInsurance);\n}\n\n/**\n * AdminForceClose instruction data (3 bytes)\n * Force-close any position at oracle price (admin only, skips margin checks).\n */\nexport interface AdminForceCloseArgs {\n targetIdx: number;\n}\n\nexport function encodeAdminForceClose(args: AdminForceCloseArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.AdminForceClose),\n encU16(args.targetIdx),\n );\n}\n\n/**\n * UpdateRiskParams instruction data (17 or 25 bytes)\n * Update initial and maintenance margin BPS (admin only).\n *\n * R2-S13: The Rust program uses `data.len() >= 25` to detect the optional\n * tradingFeeBps field, so variable-length encoding is safe. When tradingFeeBps\n * is omitted, the data is 17 bytes (tag + 2×u64). When included, 25 bytes.\n */\nexport interface UpdateRiskParamsArgs {\n initialMarginBps: bigint | string;\n maintenanceMarginBps: bigint | string;\n tradingFeeBps?: bigint | string;\n}\n\nexport function encodeUpdateRiskParams(args: UpdateRiskParamsArgs): Uint8Array {\n const parts = [\n encU8(IX_TAG.UpdateRiskParams),\n encU64(args.initialMarginBps),\n encU64(args.maintenanceMarginBps),\n ];\n if (args.tradingFeeBps !== undefined) {\n parts.push(encU64(args.tradingFeeBps));\n }\n return concatBytes(...parts);\n}\n\n/**\n * On-chain confirmation code for RenounceAdmin (must match program constant).\n * ASCII \"RENOUNCE\" as u64 LE = 0x52454E4F554E4345.\n */\nexport const RENOUNCE_ADMIN_CONFIRMATION = 0x52454E4F554E4345n;\n\n/**\n * On-chain confirmation code for UnresolveMarket (must match program constant).\n */\nexport const UNRESOLVE_CONFIRMATION = 0xDEAD_BEEF_CAFE_1234n;\n\n/**\n * RenounceAdmin instruction data (9 bytes)\n * Irreversibly set admin to all zeros. After this, all admin-only instructions fail.\n *\n * Requires the confirmation code 0x52454E4F554E4345 (\"RENOUNCE\" as u64 LE)\n * to prevent accidental invocation.\n */\nexport function encodeRenounceAdmin(): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.RenounceAdmin),\n encU64(RENOUNCE_ADMIN_CONFIRMATION),\n );\n}\n\n// ============================================================================\n// PERC-627 / GH#1926: LpVaultWithdraw (tag 39)\n// ============================================================================\n\n/**\n * LpVaultWithdraw (Tag 39, PERC-627 / GH#1926 / PERC-8287) — burn LP vault tokens and\n * withdraw proportional collateral.\n *\n * **BREAKING (PR#170):** accounts[9] = creatorLockPda is now REQUIRED.\n * Always include `deriveCreatorLockPda(programId, slab)` at position 9.\n * Non-creator withdrawers pass the derived PDA; if no lock exists on-chain\n * the check is a no-op. Omitting this account causes `ExpectLenFailed` on-chain.\n *\n * Instruction data: tag(1) + lp_amount(8) = 9 bytes\n *\n * Accounts (use ACCOUNTS_LP_VAULT_WITHDRAW):\n * [0] withdrawer signer\n * [1] slab writable\n * [2] withdrawerAta writable\n * [3] vault writable\n * [4] tokenProgram\n * [5] lpVaultMint writable\n * [6] withdrawerLpAta writable\n * [7] vaultAuthority\n * [8] lpVaultState writable\n * [9] creatorLockPda writable ← derive with deriveCreatorLockPda(programId, slab)\n *\n * @param lpAmount - Amount of LP vault tokens to burn.\n *\n * @example\n * ```ts\n * import { encodeLpVaultWithdraw, ACCOUNTS_LP_VAULT_WITHDRAW, buildAccountMetas } from \"@percolator/sdk\";\n * import { deriveCreatorLockPda, deriveVaultAuthority } from \"@percolator/sdk\";\n *\n * const [creatorLockPda] = deriveCreatorLockPda(PROGRAM_ID, slabKey);\n * const [vaultAuthority] = deriveVaultAuthority(PROGRAM_ID, slabKey);\n *\n * const data = encodeLpVaultWithdraw({ lpAmount: 1_000_000_000n });\n * const keys = buildAccountMetas(ACCOUNTS_LP_VAULT_WITHDRAW, {\n * withdrawer, slab: slabKey, withdrawerAta, vault, tokenProgram: TOKEN_PROGRAM_ID,\n * lpVaultMint, withdrawerLpAta, vaultAuthority, lpVaultState, creatorLockPda,\n * });\n * ```\n */\nexport interface LpVaultWithdrawArgs {\n /** Amount of LP vault tokens to burn. */\n lpAmount: bigint | string;\n}\n\nexport function encodeLpVaultWithdraw(args: LpVaultWithdrawArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.LpVaultWithdraw), encU64(args.lpAmount));\n}\n\n/**\n * PauseMarket instruction data (1 byte)\n * Pauses the market — disables trading, deposits, and withdrawals.\n */\nexport function encodePauseMarket(): Uint8Array {\n return encU8(IX_TAG.PauseMarket);\n}\n\n/**\n * UnpauseMarket instruction data (1 byte)\n * Unpauses the market — re-enables trading, deposits, and withdrawals.\n */\nexport function encodeUnpauseMarket(): Uint8Array {\n return encU8(IX_TAG.UnpauseMarket);\n}\n\n// ============================================================================\n// PERC-117: Pyth Oracle CPI Instructions\n// ============================================================================\n\n/**\n * SetPythOracle (Tag 32) — switch a market to Pyth-pinned mode.\n *\n * After this instruction:\n * - oracle_authority is cleared → PushOraclePrice is disabled\n * - index_feed_id is set to feed_id → validated on every price read\n * - max_staleness_secs and conf_filter_bps are updated\n * - All price reads go directly to read_pyth_price_e6() with on-chain\n * staleness + confidence + feed-ID validation (no silent fallback)\n *\n * Instruction data: tag(1) + feed_id(32) + max_staleness_secs(8) + conf_filter_bps(2) = 43 bytes\n *\n * Accounts:\n * 0. [signer, writable] Admin\n * 1. [writable] Slab\n */\nexport interface SetPythOracleArgs {\n /** 32-byte Pyth feed ID. All zeros is invalid (reserved for Hyperp mode). */\n feedId: Uint8Array;\n /** Maximum age of Pyth price in seconds before OracleStale is returned. Must be > 0. */\n maxStalenessSecs: bigint;\n /** Max confidence/price ratio in bps (0 = no confidence check). */\n confFilterBps: number;\n}\n\nexport function encodeSetPythOracle(args: SetPythOracleArgs): Uint8Array {\n if (args.feedId.length !== 32) throw new Error('feedId must be 32 bytes');\n if (args.maxStalenessSecs <= 0n) throw new Error('maxStalenessSecs must be > 0');\n\n const buf = new Uint8Array(43);\n const dv = new DataView(buf.buffer);\n\n // Tag 32 (SetPythOracle)\n buf[0] = 32;\n buf.set(args.feedId, 1);\n dv.setBigUint64(33, args.maxStalenessSecs, /* little-endian */ true);\n dv.setUint16(41, args.confFilterBps, true);\n\n return buf;\n}\n\n/**\n * Derive the expected Pyth PriceUpdateV2 account address for a given feed ID.\n * Uses PDA seeds: [shard_id(2), feed_id(32)] under the Pyth Receiver program.\n *\n * @param feedId 32-byte Pyth feed ID\n * @param shardId Shard index (default 0 for mainnet/devnet)\n */\nexport const PYTH_RECEIVER_PROGRAM_ID = 'rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ';\n\nexport async function derivePythPriceUpdateAccount(\n feedId: Uint8Array,\n shardId = 0,\n): Promise<string> {\n const { PublicKey } = await import('@solana/web3.js');\n const shardBuf = new Uint8Array(2);\n new DataView(shardBuf.buffer).setUint16(0, shardId, true);\n const [pda] = PublicKey.findProgramAddressSync(\n [shardBuf, feedId],\n new PublicKey(PYTH_RECEIVER_PROGRAM_ID),\n );\n return pda.toBase58();\n}\n\n// SetPythOracle tag (32) is already defined in IX_TAG above.\n\n// PERC-118: Mark Price EMA Instructions\n// ============================================================================\n\n// Tag 33 — permissionless mark price EMA crank (defined in IX_TAG above).\n\n/**\n * UpdateMarkPrice (Tag 33) — permissionless EMA mark price crank.\n *\n * Reads the current oracle price on-chain, applies 8-hour EMA smoothing\n * with circuit breaker, and writes result to authority_price_e6.\n *\n * Instruction data: 1 byte (tag only — all params read from on-chain state)\n *\n * Accounts:\n * 0. [writable] Slab\n * 1. [] Oracle account (Pyth PriceUpdateV2 / Chainlink / DEX AMM)\n * 2. [] Clock sysvar (SysvarC1ock11111111111111111111111111111111)\n * 3..N [] Remaining accounts (PumpSwap vaults, etc. if needed)\n */\nexport function encodeUpdateMarkPrice(): Uint8Array {\n return new Uint8Array([33]);\n}\n\n/**\n * Mark price EMA parameters (must match program/src/percolator.rs constants).\n */\nexport const MARK_PRICE_EMA_WINDOW_SLOTS = 72_000n;\nexport const MARK_PRICE_EMA_ALPHA_E6 = 2_000_000n / (MARK_PRICE_EMA_WINDOW_SLOTS + 1n);\n\n/**\n * Compute the next EMA mark price step (TypeScript mirror of the on-chain function).\n */\nexport function computeEmaMarkPrice(\n markPrevE6: bigint,\n oracleE6: bigint,\n dtSlots: bigint,\n alphaE6 = MARK_PRICE_EMA_ALPHA_E6,\n capE2bps = 0n,\n): bigint {\n if (oracleE6 === 0n) return markPrevE6;\n if (markPrevE6 === 0n || dtSlots === 0n) return oracleE6;\n\n let oracleClamped = oracleE6;\n if (capE2bps > 0n) {\n // Avoid overflow: divide early to reduce intermediate product\n const maxDelta = (markPrevE6 * capE2bps / 1_000_000n) * dtSlots;\n const lo = markPrevE6 > maxDelta ? markPrevE6 - maxDelta : 0n;\n const hi = markPrevE6 + maxDelta;\n if (oracleClamped < lo) oracleClamped = lo;\n if (oracleClamped > hi) oracleClamped = hi;\n }\n\n const effectiveAlpha = alphaE6 * dtSlots > 1_000_000n ? 1_000_000n : alphaE6 * dtSlots;\n const oneMinusAlpha = 1_000_000n - effectiveAlpha;\n\n return (oracleClamped * effectiveAlpha + markPrevE6 * oneMinusAlpha) / 1_000_000n;\n}\n\n// PERC-119: Hyperp EMA Oracle for Permissionless Tokens\n// ============================================================================\n\n// Tag 34 — permissionless Hyperp mark price oracle (defined in IX_TAG above).\n\n/**\n * UpdateHyperpMark (Tag 34) — permissionless Hyperp EMA oracle crank.\n *\n * Reads the spot price from a PumpSwap, Raydium CLMM, or Meteora DLMM pool,\n * applies 8-hour EMA smoothing with circuit breaker, and writes the new mark\n * to authority_price_e6 on the slab.\n *\n * This is the core mechanism for permissionless token markets — no Pyth or\n * Chainlink feed is needed. The DEX AMM IS the oracle.\n *\n * Instruction data: 1 byte (tag only)\n *\n * Accounts:\n * 0. [writable] Slab\n * 1. [] DEX pool account (PumpSwap / Raydium CLMM / Meteora DLMM)\n * 2. [] Clock sysvar (SysvarC1ock11111111111111111111111111111111)\n * 3..N [] Remaining accounts (e.g. PumpSwap vault0 + vault1)\n */\nexport function encodeUpdateHyperpMark(): Uint8Array {\n return new Uint8Array([34]);\n}\n\n// ============================================================================\n// PERC-306: Per-Market Insurance Isolation\n// ============================================================================\n\n/**\n * Fund per-market isolated insurance balance.\n * Accounts: [admin(signer,writable), slab(writable), admin_ata(writable), vault(writable), token_program]\n */\nexport function encodeFundMarketInsurance(args: { amount: bigint }): Uint8Array {\n return concatBytes(encU8(IX_TAG.FundMarketInsurance), encU64(args.amount));\n}\n\n/**\n * Set insurance isolation BPS for a market.\n * Accounts: [admin(signer), slab(writable)]\n */\nexport function encodeSetInsuranceIsolation(args: { bps: number }): Uint8Array {\n return concatBytes(encU8(IX_TAG.SetInsuranceIsolation), encU16(args.bps));\n}\n\n// ============================================================================\n// NOTE: encodeExecuteAdl() was historically removed when it was discovered\n// that PERC-305 was NOT implemented on-chain and tag 43 was ChallengeSettlement.\n// PERC-305 (ExecuteAdl) is now live at tag 50. Encoder added below.\n// ============================================================================\n\n// ============================================================================\n// PERC-309: QueueWithdrawal / ClaimQueuedWithdrawal / CancelQueuedWithdrawal\n// ============================================================================\n\n/**\n * QueueWithdrawal (Tag 47, PERC-309) — queue a large LP withdrawal.\n *\n * Creates a withdraw_queue PDA. The LP tokens are claimed in epoch tranches\n * via ClaimQueuedWithdrawal. Call CancelQueuedWithdrawal to abort.\n *\n * Accounts: [user(signer,writable), slab(writable), lpVaultState, withdrawQueue(writable), systemProgram]\n *\n * @param lpAmount - Amount of LP tokens to queue for withdrawal.\n *\n * @example\n * ```ts\n * const data = encodeQueueWithdrawal({ lpAmount: 1_000_000_000n });\n * ```\n */\nexport function encodeQueueWithdrawal(args: { lpAmount: bigint | string }): Uint8Array {\n return concatBytes(encU8(IX_TAG.QueueWithdrawal), encU64(args.lpAmount));\n}\n\n/**\n * ClaimQueuedWithdrawal (Tag 48, PERC-309) — claim one epoch tranche from a queued withdrawal.\n *\n * Burns LP tokens and releases one tranche of SOL to the user.\n * Call once per epoch until epochs_remaining == 0.\n *\n * Accounts: [user(signer,writable), slab(writable), withdrawQueue(writable),\n * lpVaultMint(writable), userLpAta(writable), vault(writable),\n * userAta(writable), vaultAuthority, tokenProgram, lpVaultState(writable)]\n */\nexport function encodeClaimQueuedWithdrawal(): Uint8Array {\n return encU8(IX_TAG.ClaimQueuedWithdrawal);\n}\n\n/**\n * CancelQueuedWithdrawal (Tag 49, PERC-309) — cancel a queued withdrawal, refund remaining LP.\n *\n * Closes the withdraw_queue PDA and returns its rent lamports to the user.\n * The queued LP amount that was not yet claimed is NOT refunded — it is burned.\n * Use only to abandon a partial withdrawal.\n *\n * Accounts: [user(signer,writable), slab, withdrawQueue(writable)]\n */\nexport function encodeCancelQueuedWithdrawal(): Uint8Array {\n return encU8(IX_TAG.CancelQueuedWithdrawal);\n}\n\n// ============================================================================\n// PERC-305: ExecuteAdl (Tag 50) — Auto-Deleverage\n// ============================================================================\n\n/**\n * ExecuteAdl (Tag 50, PERC-305) — auto-deleverage the most profitable position.\n *\n * Permissionless. Surgically closes or reduces `targetIdx` position when\n * `pnl_pos_tot > max_pnl_cap` on the market. The caller receives no reward —\n * the incentive is unblocking the market for normal trading.\n *\n * Requires `UpdateRiskParams.max_pnl_cap > 0` on the market.\n *\n * Accounts: [caller(signer), slab(writable), clock, oracle, ...backupOracles?]\n *\n * @param targetIdx - Account index of the position to deleverage.\n *\n * @example\n * ```ts\n * const data = encodeExecuteAdl({ targetIdx: 5 });\n * ```\n */\nexport interface ExecuteAdlArgs {\n targetIdx: number;\n}\n\nexport function encodeExecuteAdl(args: ExecuteAdlArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.ExecuteAdl), encU16(args.targetIdx));\n}\n\n// ============================================================================\n// CloseStaleSlabs (Tag 51) / ReclaimSlabRent (Tag 52) — Slab recovery\n// ============================================================================\n\n/**\n * CloseStaleSlabs (Tag 51) — close a slab of an invalid/old layout and recover rent SOL.\n *\n * Admin only. Skips slab_guard; validates header magic + admin authority instead.\n * Use for slabs created by old program layouts (e.g. pre-PERC-120 devnet deploys)\n * whose size does not match any current valid tier.\n *\n * Accounts: [dest(signer,writable), slab(writable)]\n */\nexport function encodeCloseStaleSlabs(): Uint8Array {\n return encU8(IX_TAG.CloseStaleSlabs);\n}\n\n/**\n * ReclaimSlabRent (Tag 52) — reclaim rent from an uninitialised slab.\n *\n * For use when market creation failed mid-flow (slab funded but InitMarket not called).\n * The slab account must sign (proves the caller holds the slab keypair).\n * Cannot close an initialised slab (magic == PERCOLAT) — use CloseSlab (tag 13).\n *\n * Accounts: [dest(signer,writable), slab(signer,writable)]\n */\nexport function encodeReclaimSlabRent(): Uint8Array {\n return encU8(IX_TAG.ReclaimSlabRent);\n}\n\n// ============================================================================\n// AuditCrank (Tag 53) — Permissionless on-chain invariant check\n// ============================================================================\n\n/**\n * AuditCrank (Tag 53) — verify conservation invariants on-chain (permissionless).\n *\n * Walks all accounts and verifies: capital sum, pnl_pos_tot, total_oi, LP consistency,\n * and solvency. Sets FLAG_PAUSED on violation (with a 150-slot cooldown guard to\n * prevent DoS from transient failures).\n *\n * Accounts: [slab(writable)]\n *\n * @example\n * ```ts\n * const data = encodeAuditCrank();\n * ```\n */\nexport function encodeAuditCrank(): Uint8Array {\n return encU8(IX_TAG.AuditCrank);\n}\n\n// ============================================================================\n// SMART PRICE ROUTER — quote computation for LP selection\n// ============================================================================\n\n/**\n * Parsed vAMM matcher parameters (from on-chain matcher context account)\n */\nexport interface VammMatcherParams {\n mode: number; // 0 = Passive, 1 = vAMM\n tradingFeeBps: number;\n baseSpreadBps: number;\n maxTotalBps: number;\n impactKBps: number;\n liquidityNotionalE6: bigint;\n}\n\n/** Magic bytes identifying a vAMM matcher context: \"PERCMATC\" as u64 LE */\nexport const VAMM_MAGIC = 0x5045_5243_4d41_5443n;\n\n/** Offset into matcher context where vAMM params start */\nexport const CTX_VAMM_OFFSET = 64;\n\nconst BPS_DENOM = 10_000n;\n\n/**\n * Compute execution price for a given LP quote.\n * For buys (isLong=true): price above oracle.\n * For sells (isLong=false): price below oracle.\n */\nexport function computeVammQuote(\n params: VammMatcherParams,\n oraclePriceE6: bigint,\n tradeSize: bigint,\n isLong: boolean,\n): bigint {\n const absSize = tradeSize < 0n ? -tradeSize : tradeSize;\n const absNotionalE6 = (absSize * oraclePriceE6) / 1_000_000n;\n\n // Impact for vAMM mode\n let impactBps = 0n;\n if (params.mode === 1 && params.liquidityNotionalE6 > 0n) {\n impactBps = (absNotionalE6 * BigInt(params.impactKBps)) / params.liquidityNotionalE6;\n }\n\n // Total = base_spread + trading_fee + impact, capped at max_total\n const maxTotal = BigInt(params.maxTotalBps);\n const baseFee = BigInt(params.baseSpreadBps) + BigInt(params.tradingFeeBps);\n const maxImpact = maxTotal > baseFee ? maxTotal - baseFee : 0n;\n const clampedImpact = impactBps < maxImpact ? impactBps : maxImpact;\n let totalBps = baseFee + clampedImpact;\n if (totalBps > maxTotal) totalBps = maxTotal;\n\n if (isLong) {\n return (oraclePriceE6 * (BPS_DENOM + totalBps)) / BPS_DENOM;\n } else {\n // Prevent underflow: if totalBps >= BPS_DENOM, price would go negative\n if (totalBps >= BPS_DENOM) return 1n; // minimum 1 micro-dollar\n return (oraclePriceE6 * (BPS_DENOM - totalBps)) / BPS_DENOM;\n }\n}\n\n// ============================================================================\n// PERC-622: AdvanceOraclePhase (permissionless crank)\n// ============================================================================\n\n/**\n * AdvanceOraclePhase (Tag 56) — permissionless oracle phase advancement.\n *\n * Checks if a market should transition from Phase 0→1→2 based on\n * time elapsed and cumulative volume. Anyone can call this.\n *\n * Instruction data: 1 byte (tag only)\n *\n * Accounts:\n * 0. [writable] Slab\n */\nexport function encodeAdvanceOraclePhase(): Uint8Array {\n return encU8(IX_TAG.AdvanceOraclePhase);\n}\n\n/** Oracle phase constants matching on-chain values */\nexport const ORACLE_PHASE_NASCENT = 0;\nexport const ORACLE_PHASE_GROWING = 1;\nexport const ORACLE_PHASE_MATURE = 2;\n\n/** Phase transition thresholds (must match program constants) */\nexport const PHASE1_MIN_SLOTS = 648_000n; // ~72h at 400ms\nexport const PHASE1_VOLUME_MIN_SLOTS = 36_000n; // ~4h at 400ms\nexport const PHASE2_VOLUME_THRESHOLD = 100_000_000_000n; // $100K in e6\nexport const PHASE2_MATURITY_SLOTS = 3_024_000n; // ~14 days at 400ms\n\n/**\n * Check if an oracle phase transition is due (TypeScript mirror of on-chain logic).\n *\n * @returns [newPhase, shouldTransition]\n */\nexport function checkPhaseTransition(\n currentSlot: bigint,\n marketCreatedSlot: bigint,\n oraclePhase: number,\n cumulativeVolumeE6: bigint,\n phase2DeltaSlots: number,\n hasMatureOracle: boolean,\n): [number, boolean] {\n switch (oraclePhase) {\n case 0: {\n const elapsed = currentSlot - (marketCreatedSlot > 0n ? marketCreatedSlot : currentSlot);\n const timeReady = elapsed >= PHASE1_MIN_SLOTS;\n const volumeReady = elapsed >= PHASE1_VOLUME_MIN_SLOTS\n && cumulativeVolumeE6 >= PHASE2_VOLUME_THRESHOLD;\n if (timeReady || volumeReady) {\n return [ORACLE_PHASE_GROWING, true];\n }\n return [ORACLE_PHASE_NASCENT, false];\n }\n case 1: {\n if (hasMatureOracle) return [ORACLE_PHASE_MATURE, true];\n const phase2Start = marketCreatedSlot + BigInt(phase2DeltaSlots);\n const elapsedSincePhase2 = currentSlot - phase2Start;\n if (elapsedSincePhase2 >= PHASE2_MATURITY_SLOTS) {\n return [ORACLE_PHASE_MATURE, true];\n }\n return [ORACLE_PHASE_GROWING, false];\n }\n default:\n return [ORACLE_PHASE_MATURE, false];\n }\n}\n\n// ============================================================================\n// PERC-623: Keeper Fund Instructions\n// ============================================================================\n\n/**\n * TopUpKeeperFund (Tag 57) — permissionless keeper fund top-up.\n *\n * Instruction data: tag(1) + amount(8) = 9 bytes\n *\n * Accounts:\n * 0. [signer, writable] Funder\n * 1. [writable] Slab\n * 2. [writable] Keeper fund PDA\n * 3. [] System program\n */\nexport interface TopUpKeeperFundArgs {\n amount: bigint | string;\n}\n\nexport function encodeTopUpKeeperFund(args: TopUpKeeperFundArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.TopUpKeeperFund), encU64(args.amount));\n}\n\n// Note: WithdrawKeeperReward does NOT exist as a separate instruction.\n// Keeper rewards are paid automatically during KeeperCrank (tag 5).\n// The keeper fund PDA is debited in-place when a successful crank is executed.\n\n// ============================================================================\n// PERC-629: Dynamic Creation Deposit\n// ============================================================================\n\n/**\n * SlashCreationDeposit (Tag 58) — permissionless: slash a market creator's deposit\n * after the spam grace period has elapsed (PERC-629).\n *\n * **WARNING**: Tag 58 is reserved in tags.rs but has NO instruction decoder or\n * handler in the on-chain program. Sending this instruction will fail with\n * `InvalidInstructionData`. Do not use until the on-chain handler is deployed.\n *\n * Instruction data: 1 byte (tag only)\n *\n * Accounts:\n * 0. [signer] Caller (anyone)\n * 1. [] Slab\n * 2. [writable] Creator history PDA\n * 3. [writable] Insurance vault\n * 4. [writable] Treasury\n * 5. [] System program\n *\n * @deprecated Not yet implemented on-chain — will fail with InvalidInstructionData.\n */\nexport function encodeSlashCreationDeposit(): Uint8Array {\n return encU8(IX_TAG.SlashCreationDeposit);\n}\n\n// ============================================================================\n// PERC-628: Elastic Shared Vault + Epoch Withdrawals\n// ============================================================================\n\n/**\n * InitSharedVault (Tag 59) — admin: create the global shared vault PDA (PERC-628).\n *\n * Instruction data: tag(1) + epochDurationSlots(8) + maxMarketExposureBps(2) = 11 bytes\n *\n * Accounts:\n * 0. [signer] Admin\n * 1. [writable] Shared vault PDA\n * 2. [] System program\n */\nexport interface InitSharedVaultArgs {\n epochDurationSlots: bigint | string;\n maxMarketExposureBps: number;\n}\n\nexport function encodeInitSharedVault(args: InitSharedVaultArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.InitSharedVault),\n encU64(args.epochDurationSlots),\n encU16(args.maxMarketExposureBps),\n );\n}\n\n/**\n * AllocateMarket (Tag 60) — admin: allocate virtual liquidity from the shared vault\n * to a market (PERC-628).\n *\n * Instruction data: tag(1) + amount(16) = 17 bytes\n *\n * Accounts:\n * 0. [signer] Admin\n * 1. [] Slab\n * 2. [writable] Shared vault PDA\n * 3. [writable] Market alloc PDA\n * 4. [] System program\n */\nexport interface AllocateMarketArgs {\n amount: bigint | string;\n}\n\nexport function encodeAllocateMarket(args: AllocateMarketArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.AllocateMarket), encU128(args.amount));\n}\n\n/**\n * QueueWithdrawalSV (Tag 61) — user: queue a withdrawal request for the current\n * epoch (PERC-628). Tokens are locked until the epoch elapses.\n *\n * Instruction data: tag(1) + lpAmount(8) = 9 bytes\n *\n * Accounts:\n * 0. [signer] User\n * 1. [writable] Shared vault PDA\n * 2. [writable] Withdraw request PDA\n * 3. [] System program\n */\nexport interface QueueWithdrawalSVArgs {\n lpAmount: bigint | string;\n}\n\nexport function encodeQueueWithdrawalSV(args: QueueWithdrawalSVArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.QueueWithdrawalSV), encU64(args.lpAmount));\n}\n\n/**\n * ClaimEpochWithdrawal (Tag 62) — user: claim a queued withdrawal after the epoch\n * has elapsed (PERC-628). Receives pro-rata collateral from the vault.\n *\n * Instruction data: 1 byte (tag only)\n *\n * Accounts:\n * 0. [signer] User\n * 1. [writable] Shared vault PDA\n * 2. [writable] Withdraw request PDA\n * 3. [] Slab\n * 4. [writable] Vault\n * 5. [writable] User ATA\n * 6. [] Vault authority\n * 7. [] Token program\n */\nexport function encodeClaimEpochWithdrawal(): Uint8Array {\n return encU8(IX_TAG.ClaimEpochWithdrawal);\n}\n\n/**\n * AdvanceEpoch (Tag 63) — permissionless crank: move the shared vault to the next\n * epoch once `epoch_duration_slots` have elapsed (PERC-628).\n *\n * Instruction data: 1 byte (tag only)\n *\n * Accounts:\n * 0. [signer] Caller (anyone)\n * 1. [writable] Shared vault PDA\n */\nexport function encodeAdvanceEpoch(): Uint8Array {\n return encU8(IX_TAG.AdvanceEpoch);\n}\n\n// PERC-628: Tag 63 ─────────────────────────────────────────────────────────\n\n// PERC-8110 ────────────────────────────────────────────────────────────────\n\n/**\n * SetOiImbalanceHardBlock (Tag 71, PERC-8110) — set OI imbalance hard-block threshold (admin only).\n *\n * When `|long_oi − short_oi| / total_oi * 10_000 >= threshold_bps`, any new trade that would\n * *increase* the imbalance is rejected with `OiImbalanceHardBlock` (error code 59).\n *\n * - `threshold_bps = 0`: hard block disabled.\n * - `threshold_bps = 8_000`: block trades that push skew above 80%.\n * - `threshold_bps = 10_000`: never allow >100% skew (always blocks one side when oi > 0).\n *\n * Instruction data layout: tag(1) + threshold_bps(2) = 3 bytes\n *\n * Accounts:\n * 0. [signer] admin\n * 1. [writable] slab\n *\n * @example\n * ```ts\n * const ix = new TransactionInstruction({\n * programId: PROGRAM_ID,\n * keys: buildAccountMetas(ACCOUNTS_SET_OI_IMBALANCE_HARD_BLOCK, { admin, slab }),\n * data: Buffer.from(encodeSetOiImbalanceHardBlock({ thresholdBps: 8_000 })),\n * });\n * ```\n */\nexport function encodeSetOiImbalanceHardBlock(args: { thresholdBps: number }): Uint8Array {\n if (args.thresholdBps < 0 || args.thresholdBps > 10_000) {\n throw new Error(`encodeSetOiImbalanceHardBlock: thresholdBps must be 0–10_000, got ${args.thresholdBps}`);\n }\n return concatBytes(encU8(IX_TAG.SetOiImbalanceHardBlock), encU16(args.thresholdBps));\n}\n\n// ============================================================================\n// PERC-608 — Position NFT instructions (tags 64–69)\n// ============================================================================\n\n/**\n * MintPositionNft (Tag 64, PERC-608) — mint a Token-2022 NFT representing a position.\n *\n * Creates a PositionNft PDA + Token-2022 mint with metadata, then mints 1 NFT to the\n * position owner's ATA. The NFT represents ownership of `user_idx` in the slab.\n *\n * Instruction data layout: tag(1) + user_idx(2) = 3 bytes\n *\n * Accounts:\n * 0. [signer, writable] payer\n * 1. [writable] slab\n * 2. [writable] position_nft PDA (created — seeds: [\"position_nft\", slab, user_idx])\n * 3. [writable] nft_mint PDA (created)\n * 4. [writable] owner_ata (Token-2022 ATA for owner)\n * 5. [signer] owner (must match engine account owner)\n * 6. [] vault_authority PDA\n * 7. [] token_2022_program\n * 8. [] system_program\n * 9. [] rent sysvar\n *\n * @example\n * ```ts\n * const ix = new TransactionInstruction({\n * programId: PROGRAM_ID,\n * keys: buildAccountMetas(ACCOUNTS_MINT_POSITION_NFT, [payer, slab, nftPda, nftMint, ownerAta, owner, vaultAuth, TOKEN_2022_PROGRAM_ID, SystemProgram.programId, SYSVAR_RENT_PUBKEY]),\n * data: Buffer.from(encodeMintPositionNft({ userIdx: 5 })),\n * });\n * ```\n */\nexport interface MintPositionNftArgs {\n userIdx: number;\n}\n\nexport function encodeMintPositionNft(args: MintPositionNftArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.MintPositionNft), encU16(args.userIdx));\n}\n\n/**\n * TransferPositionOwnership (Tag 65, PERC-608) — transfer an open position to a new owner.\n *\n * Transfers the Token-2022 NFT from current owner to new owner and updates the on-chain\n * engine account's owner field. Requires `pending_settlement == 0`.\n *\n * Instruction data layout: tag(1) + user_idx(2) = 3 bytes\n *\n * Accounts:\n * 0. [signer, writable] current_owner\n * 1. [writable] slab\n * 2. [writable] position_nft PDA\n * 3. [writable] nft_mint PDA\n * 4. [writable] current_owner_ata (source Token-2022 ATA)\n * 5. [writable] new_owner_ata (destination Token-2022 ATA)\n * 6. [] new_owner\n * 7. [] token_2022_program\n */\nexport interface TransferPositionOwnershipArgs {\n userIdx: number;\n}\n\nexport function encodeTransferPositionOwnership(args: TransferPositionOwnershipArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.TransferPositionOwnership), encU16(args.userIdx));\n}\n\n/**\n * BurnPositionNft (Tag 66, PERC-608) — burn the Position NFT when a position is closed.\n *\n * Burns the NFT, closes the PositionNft PDA and the mint PDA, returning rent to the owner.\n * Can only be called after the position is fully closed (size == 0).\n *\n * Instruction data layout: tag(1) + user_idx(2) = 3 bytes\n *\n * Accounts:\n * 0. [signer, writable] owner\n * 1. [writable] slab\n * 2. [writable] position_nft PDA (closed — rent to owner)\n * 3. [writable] nft_mint PDA (closed via Token-2022 close_account)\n * 4. [writable] owner_ata (Token-2022 ATA, balance burned)\n * 5. [] vault_authority PDA\n * 6. [] token_2022_program\n */\nexport interface BurnPositionNftArgs {\n userIdx: number;\n}\n\nexport function encodeBurnPositionNft(args: BurnPositionNftArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.BurnPositionNft), encU16(args.userIdx));\n}\n\n/**\n * SetPendingSettlement (Tag 67, PERC-608) — keeper sets the pending_settlement flag.\n *\n * Called by the keeper/admin before performing a funding settlement transfer.\n * Blocks NFT transfers until ClearPendingSettlement is called.\n * Admin-only (protected by GH#1475 keeper allowlist guard).\n *\n * Instruction data layout: tag(1) + user_idx(2) = 3 bytes\n *\n * Accounts:\n * 0. [signer] keeper / admin\n * 1. [] slab (read — for PDA verification + admin check)\n * 2. [writable] position_nft PDA\n */\nexport interface SetPendingSettlementArgs {\n userIdx: number;\n}\n\nexport function encodeSetPendingSettlement(args: SetPendingSettlementArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.SetPendingSettlement), encU16(args.userIdx));\n}\n\n/**\n * ClearPendingSettlement (Tag 68, PERC-608) — keeper clears the pending_settlement flag.\n *\n * Called by the keeper/admin after KeeperCrank has run and funding is settled.\n * Admin-only (protected by GH#1475 keeper allowlist guard).\n *\n * Instruction data layout: tag(1) + user_idx(2) = 3 bytes\n *\n * Accounts:\n * 0. [signer] keeper / admin\n * 1. [] slab (read — for PDA verification + admin check)\n * 2. [writable] position_nft PDA\n */\nexport interface ClearPendingSettlementArgs {\n userIdx: number;\n}\n\nexport function encodeClearPendingSettlement(args: ClearPendingSettlementArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.ClearPendingSettlement), encU16(args.userIdx));\n}\n\n/**\n * TransferOwnershipCpi (Tag 69, PERC-608) — internal CPI target for percolator-nft TransferHook.\n *\n * Called by the Token-2022 TransferHook on the percolator-nft program during an NFT transfer.\n * Updates the engine account's owner field to the new_owner public key.\n * NOT intended for direct external use — always called via Token-2022 CPI.\n *\n * Instruction data layout: tag(1) + user_idx(2) + new_owner(32) = 35 bytes\n *\n * Accounts:\n * 0. [signer] nft TransferHook program (CPI caller)\n * 1. [writable] slab\n * (remaining accounts per Token-2022 ExtraAccountMeta spec)\n */\nexport interface TransferOwnershipCpiArgs {\n userIdx: number;\n newOwner: PublicKey | string;\n}\n\nexport function encodeTransferOwnershipCpi(args: TransferOwnershipCpiArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.TransferOwnershipCpi),\n encU16(args.userIdx),\n encPubkey(args.newOwner),\n );\n}\n\n// ============================================================================\n// PERC-8111 — SetWalletCap (tag 70)\n// ============================================================================\n\n/**\n * SetWalletCap (Tag 70, PERC-8111) — set the per-wallet position cap (admin only).\n *\n * Limits the maximum absolute position size any single wallet may hold on this market.\n * Enforced on every trade (TradeNoCpi + TradeCpi) after execute_trade.\n *\n * - `capE6 = 0`: disable per-wallet cap (no limit, default).\n * - `capE6 > 0`: max |position_size| in e6 units ($1 = 1_000_000).\n * Phase 1 launch value: 1_000_000_000n ($1,000).\n *\n * When a trade would breach the cap, the on-chain error `WalletPositionCapExceeded`\n * (error code 58) is returned.\n *\n * Instruction data layout: tag(1) + cap_e6(8) = 9 bytes\n *\n * Accounts:\n * 0. [signer] admin\n * 1. [writable] slab\n *\n * @example\n * ```ts\n * // Set $1K per-wallet cap\n * const ix = new TransactionInstruction({\n * programId: PROGRAM_ID,\n * keys: buildAccountMetas(ACCOUNTS_SET_WALLET_CAP, [admin, slab]),\n * data: Buffer.from(encodeSetWalletCap({ capE6: 1_000_000_000n })),\n * });\n *\n * // Disable cap\n * const disableIx = new TransactionInstruction({\n * programId: PROGRAM_ID,\n * keys: buildAccountMetas(ACCOUNTS_SET_WALLET_CAP, [admin, slab]),\n * data: Buffer.from(encodeSetWalletCap({ capE6: 0n })),\n * });\n * ```\n */\nexport interface SetWalletCapArgs {\n /** Max position size in e6 units. 0 = disabled. $1 = 1_000_000n, $1K = 1_000_000_000n. */\n capE6: bigint | string;\n}\n\nexport function encodeSetWalletCap(args: SetWalletCapArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.SetWalletCap), encU64(args.capE6));\n}\n\n// ============================================================================\n// InitMatcherCtx — CPI to matcher program to initialize a matcher context (tag 75)\n// ============================================================================\n\n/**\n * InitMatcherCtx (Tag 75) — admin initializes the matcher context account for an LP slot.\n *\n * The matcher program (DHP6DtwXP1yJsz8YzfoeigRFPB979gzmumkmCxDLSkUX) requires its context\n * account to be initialized before TradeCpi can work. Only the percolator program can sign\n * as the LP PDA via invoke_signed, so this instruction acts as the trusted initializer.\n *\n * Instruction data layout: tag(1) + lp_idx(2) + kind(1) + trading_fee_bps(4) +\n * base_spread_bps(4) + max_total_bps(4) + impact_k_bps(4) +\n * liquidity_notional_e6(16) + max_fill_abs(16) + max_inventory_abs(16) +\n * fee_to_insurance_bps(2) + skew_spread_mult_bps(2) = 72 bytes\n *\n * Accounts:\n * 0. [signer] admin\n * 1. [] slab (program-owned; used to verify admin + LP slot)\n * 2. [writable] matcherCtx (must match LP's stored matcher_context)\n * 3. [] matcherProg (executable; must match LP's stored matcher_program)\n * 4. [] lpPda (PDA [\"lp\", slab, lp_idx]; required by CPI as signer)\n */\nexport interface InitMatcherCtxArgs {\n /** LP account index in the engine (0-based). */\n lpIdx: number;\n /** Matcher kind: 0=Passive, 1=vAMM. */\n kind: number;\n /** Base trading fee in bps (e.g. 30 = 0.30%). */\n tradingFeeBps: number;\n /** Base spread in bps. */\n baseSpreadBps: number;\n /** Max total spread in bps. */\n maxTotalBps: number;\n /** vAMM impact constant in bps (0 for passive matchers). */\n impactKBps: number;\n /** Liquidity notional in e6 units (0 for passive matchers). */\n liquidityNotionalE6: bigint | string;\n /** Max single fill size in absolute units (u128::MAX = no limit). */\n maxFillAbs: bigint | string;\n /** Max inventory size in absolute units (u128::MAX = no limit). */\n maxInventoryAbs: bigint | string;\n /** Fraction of fees routed to insurance fund in bps. */\n feeToInsuranceBps: number;\n /** Skew spread multiplier in bps (0 = disabled). */\n skewSpreadMultBps: number;\n}\n\nexport function encodeInitMatcherCtx(args: InitMatcherCtxArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.InitMatcherCtx),\n encU16(args.lpIdx),\n encU8(args.kind),\n encU32(args.tradingFeeBps),\n encU32(args.baseSpreadBps),\n encU32(args.maxTotalBps),\n encU32(args.impactKBps),\n encU128(args.liquidityNotionalE6),\n encU128(args.maxFillAbs),\n encU128(args.maxInventoryAbs),\n encU16(args.feeToInsuranceBps),\n encU16(args.skewSpreadMultBps),\n );\n}\n","import {\n PublicKey,\n AccountMeta,\n SYSVAR_CLOCK_PUBKEY,\n SYSVAR_RENT_PUBKEY,\n SystemProgram,\n} from \"@solana/web3.js\";\nimport { TOKEN_PROGRAM_ID } from \"@solana/spl-token\";\n\n/**\n * Account spec for building instruction account metas.\n * Each instruction has a fixed ordering that matches the Rust processor.\n */\nexport interface AccountSpec {\n name: string;\n signer: boolean;\n writable: boolean;\n}\n\n// ============================================================================\n// ACCOUNT ORDERINGS - Single source of truth\n// ============================================================================\n\n/**\n * InitMarket: 9 accounts (Pyth Pull - feed_id is in instruction data, not as accounts)\n */\nexport const ACCOUNTS_INIT_MARKET: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"mint\", signer: false, writable: false },\n { name: \"vault\", signer: false, writable: false },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"clock\", signer: false, writable: false },\n { name: \"rent\", signer: false, writable: false },\n { name: \"dummyAta\", signer: false, writable: false },\n { name: \"systemProgram\", signer: false, writable: false },\n] as const;\n\n/**\n * InitUser: 5 accounts (clock/oracle removed in commit 410f947)\n */\nexport const ACCOUNTS_INIT_USER: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"userAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n] as const;\n\n/**\n * InitLP: 5 accounts (clock/oracle removed in commit 410f947)\n */\nexport const ACCOUNTS_INIT_LP: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"userAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n] as const;\n\n/**\n * DepositCollateral: 6 accounts\n */\nexport const ACCOUNTS_DEPOSIT_COLLATERAL: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"userAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"clock\", signer: false, writable: false },\n] as const;\n\n/**\n * WithdrawCollateral: 8 accounts\n */\nexport const ACCOUNTS_WITHDRAW_COLLATERAL: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"userAta\", signer: false, writable: true },\n { name: \"vaultPda\", signer: false, writable: false },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"clock\", signer: false, writable: false },\n { name: \"oracleIdx\", signer: false, writable: false },\n] as const;\n\n/**\n * KeeperCrank: 4 accounts\n */\nexport const ACCOUNTS_KEEPER_CRANK: readonly AccountSpec[] = [\n { name: \"caller\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"clock\", signer: false, writable: false },\n { name: \"oracle\", signer: false, writable: false },\n] as const;\n\n/**\n * TradeNoCpi: 4 accounts (PERC-199: clock sysvar removed — uses Clock::get() syscall)\n */\nexport const ACCOUNTS_TRADE_NOCPI: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"lp\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"oracle\", signer: false, writable: false },\n] as const;\n\n/**\n * LiquidateAtOracle: 4 accounts\n * Note: account[0] is unused but must be present\n */\nexport const ACCOUNTS_LIQUIDATE_AT_ORACLE: readonly AccountSpec[] = [\n { name: \"unused\", signer: false, writable: false },\n { name: \"slab\", signer: false, writable: true },\n { name: \"clock\", signer: false, writable: false },\n { name: \"oracle\", signer: false, writable: false },\n] as const;\n\n/**\n * CloseAccount: 8 accounts\n */\nexport const ACCOUNTS_CLOSE_ACCOUNT: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"userAta\", signer: false, writable: true },\n { name: \"vaultPda\", signer: false, writable: false },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"clock\", signer: false, writable: false },\n { name: \"oracle\", signer: false, writable: false },\n] as const;\n\n/**\n * TopUpInsurance: 5 accounts\n */\nexport const ACCOUNTS_TOPUP_INSURANCE: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"userAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n] as const;\n\n/**\n * TradeCpi: 7 accounts (PERC-199: clock sysvar removed — uses Clock::get() syscall)\n */\nexport const ACCOUNTS_TRADE_CPI: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"lpOwner\", signer: false, writable: false }, // LP delegated to matcher - no signature needed\n { name: \"slab\", signer: false, writable: true },\n { name: \"oracle\", signer: false, writable: false },\n { name: \"matcherProg\", signer: false, writable: false },\n { name: \"matcherCtx\", signer: false, writable: true },\n { name: \"lpPda\", signer: false, writable: false },\n] as const;\n\n/**\n * SetRiskThreshold: 2 accounts\n */\nexport const ACCOUNTS_SET_RISK_THRESHOLD: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * UpdateAdmin: 2 accounts\n */\nexport const ACCOUNTS_UPDATE_ADMIN: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * CloseSlab: 2 accounts\n */\nexport const ACCOUNTS_CLOSE_SLAB: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * UpdateConfig: 2 accounts\n */\nexport const ACCOUNTS_UPDATE_CONFIG: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * SetMaintenanceFee: 2 accounts\n */\nexport const ACCOUNTS_SET_MAINTENANCE_FEE: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * SetOracleAuthority: 2 accounts\n * Sets the oracle price authority (admin only)\n */\nexport const ACCOUNTS_SET_ORACLE_AUTHORITY: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * SetOraclePriceCap: 2 accounts\n * Set oracle price circuit breaker cap (admin only)\n */\nexport const ACCOUNTS_SET_ORACLE_PRICE_CAP: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * PushOraclePrice: 2 accounts\n * Push oracle price (oracle authority only)\n */\nexport const ACCOUNTS_PUSH_ORACLE_PRICE: readonly AccountSpec[] = [\n { name: \"authority\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * ResolveMarket: 2 accounts\n * Resolves a binary/premarket (admin only)\n */\nexport const ACCOUNTS_RESOLVE_MARKET: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * WithdrawInsurance: 6 accounts\n * Withdraw insurance fund after market resolution (admin only)\n */\nexport const ACCOUNTS_WITHDRAW_INSURANCE: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"adminAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"vaultPda\", signer: false, writable: false },\n] as const;\n\n/**\n * PauseMarket: 2 accounts\n */\nexport const ACCOUNTS_PAUSE_MARKET: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * UnpauseMarket: 2 accounts\n */\nexport const ACCOUNTS_UNPAUSE_MARKET: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// ACCOUNT META BUILDERS\n// ============================================================================\n\n/**\n * Build AccountMeta array from spec and provided pubkeys.\n *\n * Accepts either:\n * - `PublicKey[]` — ordered array, one entry per spec account (legacy form)\n * - `Record<string, PublicKey>` — named map keyed by account `name` (preferred form)\n *\n * Named-map form resolves accounts by spec name so callers don't have to\n * remember the positional order, and errors clearly on missing names.\n */\nexport function buildAccountMetas(\n spec: readonly AccountSpec[],\n keys: PublicKey[] | Record<string, PublicKey>\n): AccountMeta[] {\n let keysArray: PublicKey[];\n\n if (Array.isArray(keys)) {\n keysArray = keys;\n } else {\n // Named map: resolve by spec name\n keysArray = spec.map((s) => {\n const key = (keys as Record<string, PublicKey>)[s.name];\n if (!key) {\n throw new Error(\n `buildAccountMetas: missing key for account \"${s.name}\". ` +\n `Provided keys: [${Object.keys(keys).join(\", \")}]`\n );\n }\n return key;\n });\n }\n\n if (keysArray.length !== spec.length) {\n throw new Error(\n `Account count mismatch: expected ${spec.length}, got ${keysArray.length}`\n );\n }\n return spec.map((s, i) => ({\n pubkey: keysArray[i],\n isSigner: s.signer,\n isWritable: s.writable,\n }));\n}\n\n// ============================================================================\n// PERC-627 / GH#1926: LpVaultWithdraw (tag 39)\n// ============================================================================\n\n/**\n * LpVaultWithdraw: 10 accounts (tag 39, PERC-627 / GH#1926 / PERC-8287)\n *\n * Burn LP vault tokens and withdraw proportional collateral from the LP vault.\n *\n * accounts[9] = creatorLockPda is REQUIRED since percolator-prog PR#170.\n * Non-creator withdrawers must pass the derived PDA key; if no lock exists\n * on-chain the enforcement is a no-op. Omitting it was the bypass vector\n * fixed in GH#1926. Use `deriveCreatorLockPda(programId, slab)` to compute.\n *\n * Accounts:\n * [0] withdrawer signer, read-only\n * [1] slab writable\n * [2] withdrawerAta writable (collateral destination)\n * [3] vault writable (collateral source)\n * [4] tokenProgram read-only\n * [5] lpVaultMint writable (LP tokens burned from here)\n * [6] withdrawerLpAta writable (LP tokens source)\n * [7] vaultAuthority read-only (PDA that signs token transfers)\n * [8] lpVaultState writable\n * [9] creatorLockPda writable (REQUIRED — derived from [\"creator_lock\", slab])\n */\nexport const ACCOUNTS_LP_VAULT_WITHDRAW: readonly AccountSpec[] = [\n { name: \"withdrawer\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n { name: \"withdrawerAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"lpVaultMint\", signer: false, writable: true },\n { name: \"withdrawerLpAta\", signer: false, writable: true },\n { name: \"vaultAuthority\", signer: false, writable: false },\n { name: \"lpVaultState\", signer: false, writable: true },\n { name: \"creatorLockPda\", signer: false, writable: true },\n] as const;\n\n/**\n * FundMarketInsurance: 5 accounts (PERC-306)\n * Fund per-market isolated insurance balance.\n */\nexport const ACCOUNTS_FUND_MARKET_INSURANCE: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"adminAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n] as const;\n\n/**\n * SetInsuranceIsolation: 2 accounts (PERC-306)\n * Set max % of global fund this market can access.\n */\nexport const ACCOUNTS_SET_INSURANCE_ISOLATION: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// PERC-309: QueueWithdrawal / ClaimQueuedWithdrawal / CancelQueuedWithdrawal\n// ============================================================================\n\n/**\n * QueueWithdrawal: 5 accounts (PERC-309)\n * User queues a large LP withdrawal. Creates withdraw_queue PDA.\n */\nexport const ACCOUNTS_QUEUE_WITHDRAWAL: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"lpVaultState\", signer: false, writable: false },\n { name: \"withdrawQueue\", signer: false, writable: true },\n { name: \"systemProgram\", signer: false, writable: false },\n] as const;\n\n/**\n * ClaimQueuedWithdrawal: 10 accounts (PERC-309)\n * Burns LP tokens and releases one epoch tranche of SOL.\n */\nexport const ACCOUNTS_CLAIM_QUEUED_WITHDRAWAL: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"withdrawQueue\", signer: false, writable: true },\n { name: \"lpVaultMint\", signer: false, writable: true },\n { name: \"userLpAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"userAta\", signer: false, writable: true },\n { name: \"vaultAuthority\", signer: false, writable: false },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"lpVaultState\", signer: false, writable: true },\n] as const;\n\n/**\n * CancelQueuedWithdrawal: 3 accounts (PERC-309)\n * Cancels queue, closes withdraw_queue PDA, returns rent to user.\n */\nexport const ACCOUNTS_CANCEL_QUEUED_WITHDRAWAL: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: false },\n { name: \"withdrawQueue\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// PERC-305: ExecuteAdl (tag 50) — Auto-Deleverage\n// ============================================================================\n\n/**\n * ExecuteAdl: 4+ accounts (PERC-305, tag 50)\n * Permissionless — surgically close/reduce the most profitable position\n * when pnl_pos_tot > max_pnl_cap. For non-Hyperp markets with backup oracles,\n * pass additional oracle accounts at accounts[4..].\n */\nexport const ACCOUNTS_EXECUTE_ADL: readonly AccountSpec[] = [\n { name: \"caller\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n { name: \"clock\", signer: false, writable: false },\n { name: \"oracle\", signer: false, writable: false },\n] as const;\n\n// ============================================================================\n// CloseStaleSlabs (tag 51) / ReclaimSlabRent (tag 52)\n// ============================================================================\n\n/**\n * CloseStaleSlabs: 2 accounts (tag 51)\n * Admin closes a slab of an invalid/old layout and recovers rent SOL.\n */\nexport const ACCOUNTS_CLOSE_STALE_SLABS: readonly AccountSpec[] = [\n { name: \"dest\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * ReclaimSlabRent: 2 accounts (tag 52)\n * Reclaim rent from an uninitialised slab. Both dest and slab must sign.\n */\nexport const ACCOUNTS_RECLAIM_SLAB_RENT: readonly AccountSpec[] = [\n { name: \"dest\", signer: true, writable: true },\n { name: \"slab\", signer: true, writable: true },\n] as const;\n\n// ============================================================================\n// AuditCrank (tag 53) — Permissionless invariant check\n// ============================================================================\n\n/**\n * AuditCrank: 1 account (tag 53)\n * Permissionless. Verifies conservation invariants; pauses market on violation.\n */\nexport const ACCOUNTS_AUDIT_CRANK: readonly AccountSpec[] = [\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// PERC-622: AdvanceOraclePhase (permissionless)\n// ============================================================================\n\n/**\n * AdvanceOraclePhase: 1 account\n * Permissionless — no signer required beyond fee payer.\n */\nexport const ACCOUNTS_ADVANCE_ORACLE_PHASE: readonly AccountSpec[] = [\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// PERC-623: Keeper Fund Instructions\n// ============================================================================\n\n/**\n * TopUpKeeperFund: 3 accounts\n * Permissionless — anyone can fund. Transfers lamports directly (no system program).\n */\nexport const ACCOUNTS_TOPUP_KEEPER_FUND: readonly AccountSpec[] = [\n { name: \"funder\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"keeperFund\", signer: false, writable: true },\n] as const;\n\n// Note: WithdrawKeeperReward has no separate instruction.\n// Rewards are paid automatically during KeeperCrank (tag 5).\n\n// ============================================================================\n// PERC-8110: SetOiImbalanceHardBlock\n// ============================================================================\n\n/**\n * SetOiImbalanceHardBlock: 2 accounts\n * Sets the OI imbalance hard-block threshold (admin only)\n */\nexport const ACCOUNTS_SET_OI_IMBALANCE_HARD_BLOCK: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// PERC-608: Position NFT Instructions (tags 64–69)\n// ============================================================================\n\n/**\n * MintPositionNft: 10 accounts\n * Creates a Token-2022 position NFT for an open position.\n */\nexport const ACCOUNTS_MINT_POSITION_NFT: readonly AccountSpec[] = [\n { name: \"payer\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"positionNftPda\", signer: false, writable: true },\n { name: \"nftMint\", signer: false, writable: true },\n { name: \"ownerAta\", signer: false, writable: true },\n { name: \"owner\", signer: true, writable: false },\n { name: \"vaultAuthority\", signer: false, writable: false },\n { name: \"token2022Program\", signer: false, writable: false },\n { name: \"systemProgram\", signer: false, writable: false },\n { name: \"rent\", signer: false, writable: false },\n] as const;\n\n/**\n * TransferPositionOwnership: 8 accounts\n * Transfer position NFT and update on-chain owner. Requires pending_settlement == 0.\n */\nexport const ACCOUNTS_TRANSFER_POSITION_OWNERSHIP: readonly AccountSpec[] = [\n { name: \"currentOwner\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"positionNftPda\", signer: false, writable: true },\n { name: \"nftMint\", signer: false, writable: true },\n { name: \"currentOwnerAta\", signer: false, writable: true },\n { name: \"newOwnerAta\", signer: false, writable: true },\n { name: \"newOwner\", signer: false, writable: false },\n { name: \"token2022Program\", signer: false, writable: false },\n] as const;\n\n/**\n * BurnPositionNft: 7 accounts\n * Burns NFT and closes PositionNft + mint PDAs after position is closed.\n */\nexport const ACCOUNTS_BURN_POSITION_NFT: readonly AccountSpec[] = [\n { name: \"owner\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"positionNftPda\", signer: false, writable: true },\n { name: \"nftMint\", signer: false, writable: true },\n { name: \"ownerAta\", signer: false, writable: true },\n { name: \"vaultAuthority\", signer: false, writable: false },\n { name: \"token2022Program\", signer: false, writable: false },\n] as const;\n\n/**\n * SetPendingSettlement: 3 accounts\n * Keeper/admin sets pending_settlement flag before funding transfer.\n * Protected by admin allowlist (GH#1475).\n */\nexport const ACCOUNTS_SET_PENDING_SETTLEMENT: readonly AccountSpec[] = [\n { name: \"keeper\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: false },\n { name: \"positionNftPda\", signer: false, writable: true },\n] as const;\n\n/**\n * ClearPendingSettlement: 3 accounts\n * Keeper/admin clears pending_settlement flag after KeeperCrank.\n * Protected by admin allowlist (GH#1475).\n */\nexport const ACCOUNTS_CLEAR_PENDING_SETTLEMENT: readonly AccountSpec[] = [\n { name: \"keeper\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: false },\n { name: \"positionNftPda\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// PERC-8111: SetWalletCap\n// ============================================================================\n\n/**\n * SetWalletCap: 2 accounts\n * Sets the per-wallet position cap (admin only). capE6=0 disables.\n */\nexport const ACCOUNTS_SET_WALLET_CAP: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// InitMatcherCtx (tag 75)\n// ============================================================================\n\n/**\n * InitMatcherCtx: 5 accounts\n * Admin CPI-initializes the matcher context account for an LP slot.\n * The LP PDA signs via invoke_signed in the program — it must be included in\n * the transaction's account list even though it carries 0 lamports.\n */\nexport const ACCOUNTS_INIT_MATCHER_CTX: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: false },\n { name: \"matcherCtx\", signer: false, writable: true },\n { name: \"matcherProg\", signer: false, writable: false },\n { name: \"lpPda\", signer: false, writable: false },\n] as const;\n\n// ============================================================================\n// WELL-KNOWN PROGRAM/SYSVAR KEYS\n// ============================================================================\n\nexport const WELL_KNOWN = {\n tokenProgram: TOKEN_PROGRAM_ID,\n clock: SYSVAR_CLOCK_PUBKEY,\n rent: SYSVAR_RENT_PUBKEY,\n systemProgram: SystemProgram.programId,\n} as const;\n","/**\n * Percolator program error definitions.\n * Each error includes a name and actionable guidance.\n */\ninterface ErrorInfo {\n name: string;\n hint: string;\n}\n\nexport const PERCOLATOR_ERRORS: Record<number, ErrorInfo> = {\n 0: {\n name: \"InvalidMagic\",\n hint: \"The slab account has invalid data. Ensure you're using the correct slab address.\",\n },\n 1: {\n name: \"InvalidVersion\",\n hint: \"Slab version mismatch. The program may have been upgraded. Check for CLI updates.\",\n },\n 2: {\n name: \"AlreadyInitialized\",\n hint: \"This account is already initialized. Use a different account or skip initialization.\",\n },\n 3: {\n name: \"NotInitialized\",\n hint: \"The slab is not initialized. Run 'init-market' first.\",\n },\n 4: {\n name: \"InvalidSlabLen\",\n hint: \"Slab account has wrong size. Create a new slab account with correct size.\",\n },\n 5: {\n name: \"InvalidOracleKey\",\n hint: \"Oracle account doesn't match config. Check the --oracle parameter matches the market's oracle.\",\n },\n 6: {\n name: \"OracleStale\",\n hint: \"Oracle price is too old. Wait for oracle to update or check if oracle is paused.\",\n },\n 7: {\n name: \"OracleConfTooWide\",\n hint: \"Oracle confidence interval is too wide. Wait for more stable market conditions.\",\n },\n 8: {\n name: \"InvalidVaultAta\",\n hint: \"Vault token account is invalid. Check the vault account is correctly configured.\",\n },\n 9: {\n name: \"InvalidMint\",\n hint: \"Token mint doesn't match. Ensure you're using the correct collateral token.\",\n },\n 10: {\n name: \"ExpectedSigner\",\n hint: \"Missing required signature. Ensure the correct wallet is specified with --wallet.\",\n },\n 11: {\n name: \"ExpectedWritable\",\n hint: \"Account must be writable. This is likely a CLI bug - please report it.\",\n },\n 12: {\n name: \"OracleInvalid\",\n hint: \"Oracle data is invalid. Check the oracle account is a valid Pyth price feed.\",\n },\n 13: {\n name: \"EngineInsufficientBalance\",\n hint: \"Not enough collateral. Deposit more with 'deposit' before this operation.\",\n },\n 14: {\n name: \"EngineUndercollateralized\",\n hint: \"Account is undercollateralized. Deposit more collateral or reduce position size.\",\n },\n 15: {\n name: \"EngineUnauthorized\",\n hint: \"Not authorized. You must be the account owner or admin for this operation.\",\n },\n 16: {\n name: \"EngineInvalidMatchingEngine\",\n hint: \"Matcher program/context doesn't match LP config. Check --matcher-program and --matcher-context.\",\n },\n 17: {\n name: \"EnginePnlNotWarmedUp\",\n hint: \"PnL not warmed up yet. Wait for the warmup period to complete before trading.\",\n },\n 18: {\n name: \"EngineOverflow\",\n hint: \"Numeric overflow in calculation. Try a smaller amount or position size.\",\n },\n 19: {\n name: \"EngineAccountNotFound\",\n hint: \"Account not found at this index. Run 'init-user' or 'init-lp' first, or check the index.\",\n },\n 20: {\n name: \"EngineNotAnLPAccount\",\n hint: \"Expected an LP account but got a user account. Check the --lp-idx parameter.\",\n },\n 21: {\n name: \"EnginePositionSizeMismatch\",\n hint: \"Position size mismatch between user and LP. This shouldn't happen - please report it.\",\n },\n 22: {\n name: \"EngineRiskReductionOnlyMode\",\n hint: \"Market is in risk-reduction mode. Only position-reducing trades are allowed.\",\n },\n 23: {\n name: \"EngineAccountKindMismatch\",\n hint: \"Wrong account type. User operations require user accounts, LP operations require LP accounts.\",\n },\n 24: {\n name: \"InvalidTokenAccount\",\n hint: \"Token account is invalid. Ensure you have an ATA for the collateral mint.\",\n },\n 25: {\n name: \"InvalidTokenProgram\",\n hint: \"Invalid token program. Ensure SPL Token program is accessible.\",\n },\n 26: {\n name: \"InvalidConfigParam\",\n hint: \"Invalid configuration parameter. Check that leverage, fees, and risk thresholds are within allowed ranges.\",\n },\n 27: {\n name: \"HyperpTradeNoCpiDisabled\",\n hint: \"TradeNoCpi is disabled for this market. Use TradeCpi with LP matching instead.\",\n },\n 28: {\n name: \"InsuranceMintAlreadyExists\",\n hint: \"Insurance LP mint already exists for this market. Cannot recreate.\",\n },\n 29: {\n name: \"InsuranceMintNotCreated\",\n hint: \"Insurance LP mint has not been created yet. Run CreateInsuranceMint first.\",\n },\n 30: {\n name: \"InsuranceBelowThreshold\",\n hint: \"Insurance fund balance is below the required threshold. Deposit more to insurance fund.\",\n },\n 31: {\n name: \"InsuranceZeroAmount\",\n hint: \"Insurance deposit/withdrawal amount must be greater than zero.\",\n },\n 32: {\n name: \"InsuranceSupplyMismatch\",\n hint: \"Insurance LP token supply doesn't match vault balance. This is an internal error - please report it.\",\n },\n 33: {\n name: \"MarketPaused\",\n hint: \"This market is currently paused by the admin. Trading, deposits, and withdrawals are disabled.\",\n },\n 34: {\n name: \"AdminRenounceNotAllowed\",\n hint: \"Cannot renounce admin — the market must be RESOLVED first before renouncing admin control.\",\n },\n 35: {\n name: \"InvalidConfirmation\",\n hint: \"Invalid confirmation code for RenounceAdmin. This is a safety check — please verify the code.\",\n },\n 36: {\n name: \"InsufficientSeed\",\n hint: \"Vault seed balance is below the required minimum (500,000,000 raw tokens). Deposit more tokens to the vault before InitMarket.\",\n },\n 37: {\n name: \"InsufficientDexLiquidity\",\n hint: \"DEX pool has insufficient liquidity for safe Hyperp oracle bootstrapping. The quote-side reserves must meet the minimum threshold.\",\n },\n 38: {\n name: \"LpVaultAlreadyExists\",\n hint: \"LP vault already created for this market. Each market can only have one LP vault.\",\n },\n 39: {\n name: \"LpVaultNotCreated\",\n hint: \"LP vault not yet created. Call CreateLpVault first before depositing or withdrawing.\",\n },\n 40: {\n name: \"LpVaultZeroAmount\",\n hint: \"LP vault deposit or withdrawal amount must be greater than zero.\",\n },\n 41: {\n name: \"LpVaultSupplyMismatch\",\n hint: \"LP vault supply/capital mismatch — LP share supply > 0 but vault capital is 0. This is an internal error — please report it.\",\n },\n 42: {\n name: \"LpVaultWithdrawExceedsAvailable\",\n hint: \"LP vault withdrawal exceeds available capital. Some capital is reserved for open interest coverage.\",\n },\n 43: {\n name: \"LpVaultInvalidFeeShare\",\n hint: \"LP vault fee share basis points out of range. Must be 0–10,000 (0%–100%).\",\n },\n 44: {\n name: \"LpVaultNoNewFees\",\n hint: \"No new fees to distribute to LP vault. Wait for more trading activity to accrue fees.\",\n },\n // ── PERC-312 / PERC-314 / PERC-315 / PERC-309 / PERC-8111 / PERC-8110 (codes 45–60) ─────────\n 45: {\n name: \"SafetyValveDominantSideBlocked\",\n hint: \"New position on the dominant side is blocked while the market is rebalancing (safety valve).\",\n },\n 46: {\n name: \"DisputeWindowClosed\",\n hint: \"The dispute window for this resolved market has closed.\",\n },\n 47: {\n name: \"DisputeAlreadyExists\",\n hint: \"A dispute already exists for this market — cannot open another.\",\n },\n 48: {\n name: \"MarketNotResolved\",\n hint: \"Market is not resolved — cannot dispute an active market.\",\n },\n 49: {\n name: \"NoActiveDispute\",\n hint: \"No active dispute found for this market.\",\n },\n 50: {\n name: \"LpCollateralDisabled\",\n hint: \"LP collateral is not enabled for this market.\",\n },\n 51: {\n name: \"LpCollateralPositionOpen\",\n hint: \"Cannot withdraw LP collateral while a position is still open.\",\n },\n 52: {\n name: \"WithdrawQueueAlreadyExists\",\n hint: \"A withdrawal queue entry already exists for this user/market.\",\n },\n 53: {\n name: \"WithdrawQueueNotFound\",\n hint: \"No queued withdrawal found for this user/market.\",\n },\n 54: {\n name: \"WithdrawQueueNothingClaimable\",\n hint: \"Nothing is claimable from the withdrawal queue this epoch — wait for the next epoch.\",\n },\n 55: {\n name: \"AuditViolation\",\n hint: \"Audit crank detected a conservation invariant violation — this is a critical internal error, please report it.\",\n },\n 56: {\n name: \"CrossMarginPairNotFound\",\n hint: \"Cross-margin offset pair is not configured for these two slabs.\",\n },\n 57: {\n name: \"CrossMarginAttestationStale\",\n hint: \"Cross-margin attestation is stale — too many slots have elapsed since the last attestation.\",\n },\n 58: {\n name: \"WalletPositionCapExceeded\",\n hint: \"Trade rejected: the resulting position would exceed the per-wallet position cap (max_wallet_pos_e6) for this market.\",\n },\n 59: {\n name: \"OiImbalanceHardBlock\",\n hint: \"Trade rejected: it would increase the OI imbalance (|long_oi − short_oi| / total_oi) beyond the configured hard-block threshold (oi_imbalance_hard_block_bps). Try the opposite side.\",\n },\n 60: {\n name: \"EngineInvalidEntryPrice\",\n hint: \"Entry price must be positive when opening a position.\",\n },\n 61: {\n name: \"EngineSideBlocked\",\n hint: \"New position blocked — this side is in DrainOnly or ResetPending mode. Wait for the market to stabilise.\",\n },\n 62: {\n name: \"EngineCorruptState\",\n hint: \"Engine detected a corrupt state invariant violation — this is a critical internal error, please report it.\",\n },\n 63: {\n name: \"InsuranceFundNotDepleted\",\n hint: \"ADL rejected — insurance fund is not fully depleted (balance > 0). ADL is only permitted once insurance is exhausted.\",\n },\n 64: {\n name: \"NoAdlCandidates\",\n hint: \"ADL rejected — no eligible candidate positions found for deleveraging.\",\n },\n 65: {\n name: \"BankruptPositionAlreadyClosed\",\n hint: \"ADL rejected — the target position is already closed (size == 0). Re-rank and pick a different target.\",\n },\n};\n\n/**\n * Decode a custom program error code to its info.\n */\nexport function decodeError(code: number): ErrorInfo | undefined {\n return PERCOLATOR_ERRORS[code];\n}\n\n/**\n * Get error name from code.\n */\nexport function getErrorName(code: number): string {\n return PERCOLATOR_ERRORS[code]?.name ?? `Unknown(${code})`;\n}\n\n/**\n * Get actionable hint for error code.\n */\nexport function getErrorHint(code: number): string | undefined {\n return PERCOLATOR_ERRORS[code]?.hint;\n}\n\n// ============================================================================\n// Lighthouse / Anchor error classification\n// ============================================================================\n\n/** Lighthouse v2 program ID (Blowfish/Phantom wallet middleware). */\nconst LIGHTHOUSE_PROGRAM_ID_STR = \"L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95\";\n\n/**\n * Anchor framework error codes (0x1770–0x1900+) that come from Lighthouse,\n * NOT from Percolator. Our program uses raw BPF with custom codes 0–65.\n */\nconst ANCHOR_ERROR_RANGE_START = 0x1770;\nconst ANCHOR_ERROR_RANGE_END = 0x1FFF;\n\n/** Well-known Anchor error names for common codes emitted by Lighthouse. */\nconst ANCHOR_ERROR_NAMES: Record<number, string> = {\n 0x1790: \"ConstraintMut\",\n 0x1794: \"ConstraintOwner\",\n 0x1796: \"ConstraintSeeds\",\n 0x1900: \"ConstraintAddress\",\n};\n\n/**\n * Check whether an error code is in the Anchor framework error range\n * (used by Lighthouse, not Percolator).\n */\nexport function isAnchorErrorCode(code: number): boolean {\n return code >= ANCHOR_ERROR_RANGE_START && code <= ANCHOR_ERROR_RANGE_END;\n}\n\n/** Max hex digits for `custom program error: 0x...` — Solana custom errors are u32. */\nconst CUSTOM_ERROR_HEX_MAX_LEN = 8;\n\n/**\n * Parse error from transaction logs.\n * Looks for \"Program ... failed: custom program error: 0x...\"\n *\n * Hex capture is bounded (1–8 digits) so pathological logs cannot feed unbounded\n * strings into `parseInt` or produce precision-loss codes above u32.\n *\n * Distinguishes between:\n * - Percolator program errors (codes 0–65): returns Percolator error info\n * - Anchor/Lighthouse errors (codes 0x1770–0x1FFF): returns Lighthouse-specific\n * name and hint so callers can handle wallet middleware failures\n */\nexport function parseErrorFromLogs(logs: string[]): {\n code: number;\n name: string;\n hint?: string;\n source?: \"percolator\" | \"lighthouse\" | \"unknown\";\n} | null {\n if (!Array.isArray(logs)) {\n return null;\n }\n\n // Track whether the failing instruction is inside a Lighthouse invocation\n let insideLighthouse = false;\n\n const re = new RegExp(\n `custom program error: 0x([0-9a-fA-F]{1,${CUSTOM_ERROR_HEX_MAX_LEN}})(?![0-9a-fA-F])`,\n \"i\",\n );\n for (const log of logs) {\n if (typeof log !== \"string\") {\n continue;\n }\n\n // Track Lighthouse program invocation context\n if (log.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {\n insideLighthouse = true;\n } else if (log.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {\n insideLighthouse = false;\n }\n\n const match = log.match(re);\n if (match) {\n const code = parseInt(match[1], 16);\n if (!Number.isFinite(code) || code < 0 || code > 0xffff_ffff) {\n continue;\n }\n\n // Anchor/Lighthouse error range\n if (isAnchorErrorCode(code) || insideLighthouse) {\n const anchorName = ANCHOR_ERROR_NAMES[code] ?? `AnchorError(0x${code.toString(16)})`;\n return {\n code,\n name: `Lighthouse:${anchorName}`,\n hint:\n \"This error comes from the Lighthouse/Blowfish wallet guard, not from Percolator. \" +\n \"The transaction itself is valid. Disable transaction simulation in your wallet \" +\n \"settings, or use a wallet without Blowfish protection (e.g., Backpack, Solflare).\",\n source: \"lighthouse\",\n };\n }\n\n // Percolator program error\n const info = decodeError(code);\n return {\n code,\n name: info?.name ?? `Unknown(${code})`,\n hint: info?.hint,\n source: info ? \"percolator\" : \"unknown\",\n };\n }\n }\n return null;\n}\n","import { Connection, PublicKey } from \"@solana/web3.js\";\n\n// =============================================================================\n// Browser-compatible read helpers using DataView\n// (the npm 'buffer' polyfill lacks readBigUInt64LE / readBigInt64LE)\n// =============================================================================\n\n/** Wrap a Uint8Array in a DataView sharing the same underlying buffer. */\nfunction dv(data: Uint8Array): DataView {\n return new DataView(data.buffer, data.byteOffset, data.byteLength);\n}\n/** Read a single unsigned byte at `off`. */\nfunction readU8(data: Uint8Array, off: number): number {\n return data[off];\n}\n/** Read a little-endian u16 at `off`. */\nfunction readU16LE(data: Uint8Array, off: number): number {\n return dv(data).getUint16(off, true);\n}\n/** Read a little-endian u32 at `off`. */\nfunction readU32LE(data: Uint8Array, off: number): number {\n return dv(data).getUint32(off, true);\n}\n/** Read a little-endian u64 at `off` as a BigInt. */\nfunction readU64LE(data: Uint8Array, off: number): bigint {\n return dv(data).getBigUint64(off, true);\n}\n/** Read a little-endian signed i64 at `off` as a BigInt. */\nfunction readI64LE(data: Uint8Array, off: number): bigint {\n return dv(data).getBigInt64(off, true);\n}\n\n// =============================================================================\n// Helper: read signed/unsigned i128 from buffer\n// =============================================================================\n\n/**\n * Read a little-endian signed i128 at `offset`.\n * Composed from two u64 halves; sign-extends if the high bit is set.\n */\nfunction readI128LE(buf: Uint8Array, offset: number): bigint {\n const lo = readU64LE(buf, offset);\n const hi = readU64LE(buf, offset + 8);\n const unsigned = (hi << 64n) | lo;\n const SIGN_BIT = 1n << 127n;\n if (unsigned >= SIGN_BIT) {\n return unsigned - (1n << 128n);\n }\n return unsigned;\n}\n\n/** Read a little-endian unsigned u128 at `offset` as a BigInt. */\nfunction readU128LE(buf: Uint8Array, offset: number): bigint {\n const lo = readU64LE(buf, offset);\n const hi = readU64LE(buf, offset + 8);\n return (hi << 64n) | lo;\n}\n\n// =============================================================================\n// Slab Layout Version Detection\n// =============================================================================\n// The deployed devnet program uses a different struct layout (V0) than the SDK\n// was updated for (V1). V1 includes PERC-120/121/122/298/299/300/301/306/328\n// struct changes that have NOT been deployed to devnet yet.\n//\n// V0 (deployed devnet): HEADER=72, CONFIG=408, ENGINE_OFF=480, ACCOUNT_SIZE=240\n// - InsuranceFund: {balance: U128, fee_revenue: U128} (32 bytes)\n// - RiskParams: 56 bytes (basic fields only)\n// - No mark_price, no long_oi/short_oi, no emergency OI cap fields\n// - No partial liquidation field in Account (240 bytes)\n//\n// V1 (future upgrade): HEADER=104, CONFIG=536, ENGINE_OFF=640, ACCOUNT_SIZE=248\n// - InsuranceFund: expanded with isolation fields (72 bytes)\n// - RiskParams: 288 bytes (premium funding, partial liq, dynamic fees)\n// - Has mark_price, long_oi/short_oi, emergency fields\n// - Account has last_partial_liquidation_slot (248 bytes)\n// =============================================================================\n\nconst MAGIC: bigint = 0x504552434f4c4154n; // \"PERCOLAT\"\n\n// Flag bits in header._padding[0] at offset 13\nconst FLAG_RESOLVED = 1 << 0;\n\n/**\n * Full slab layout descriptor. Returned by detectSlabLayout().\n * All engine field offsets are relative to engineOff.\n */\nexport interface SlabLayout {\n version: 0 | 1 | 2;\n headerLen: number;\n configOffset: number;\n configLen: number;\n reservedOff: number; // offset of _reserved in header\n engineOff: number;\n accountSize: number;\n maxAccounts: number;\n bitmapWords: number;\n accountsOff: number; // absolute offset of accounts array in slab\n\n // Engine field offsets (relative to engineOff)\n engineInsuranceOff: number;\n engineParamsOff: number;\n paramsSize: number;\n engineCurrentSlotOff: number;\n engineFundingIndexOff: number;\n engineLastFundingSlotOff: number;\n engineFundingRateBpsOff: number;\n engineMarkPriceOff: number; // -1 if not present (V0)\n engineLastCrankSlotOff: number;\n engineMaxCrankStalenessOff: number;\n engineTotalOiOff: number;\n engineLongOiOff: number; // -1 if not present (V0)\n engineShortOiOff: number; // -1 if not present (V0)\n engineCTotOff: number;\n enginePnlPosTotOff: number;\n engineLiqCursorOff: number;\n engineGcCursorOff: number;\n engineLastSweepStartOff: number;\n engineLastSweepCompleteOff: number;\n engineCrankCursorOff: number;\n engineSweepStartIdxOff: number;\n engineLifetimeLiquidationsOff: number;\n engineLifetimeForceClosesOff: number;\n engineNetLpPosOff: number;\n engineLpSumAbsOff: number;\n engineLpMaxAbsOff: number;\n engineLpMaxAbsSweepOff: number;\n engineEmergencyOiModeOff: number; // -1 if not present (V0)\n engineEmergencyStartSlotOff: number; // -1 if not present (V0)\n engineLastBreakerSlotOff: number; // -1 if not present (V0)\n engineBitmapOff: number; // relative to engineOff\n postBitmap: number; // 2 = free_head only (V1D), 18 = num_used + pad + next_account_id + free_head\n acctOwnerOff: number; // byte offset of owner pubkey within an account slot\n\n // Insurance fund layout\n hasInsuranceIsolation: boolean;\n engineInsuranceIsolatedOff: number; // -1 if not present (V0)\n engineInsuranceIsolationBpsOff: number; // -1 if not present (V0)\n}\n\n// ---- V0 layout constants (deployed devnet program) ----\nconst V0_HEADER_LEN = 72;\nconst V0_CONFIG_LEN = 408;\nconst V0_ENGINE_OFF = 480; // align_up(72 + 408, 8) = 480\nconst V0_ACCOUNT_SIZE = 240;\nconst V0_RESERVED_OFF = 48; // magic(8)+version(4)+bump(1)+pad(3)+admin(32) = 48\n\n// V0 engine: vault(16) + insurance{balance(16),fee_revenue(16)}=32 → params at 48\n// V0 RiskParams: 56 bytes → runtime state at 104\nconst V0_ENGINE_PARAMS_OFF = 48;\nconst V0_PARAMS_SIZE = 56;\nconst V0_ENGINE_CURRENT_SLOT_OFF = 104;\nconst V0_ENGINE_FUNDING_INDEX_OFF = 112;\nconst V0_ENGINE_LAST_FUNDING_SLOT_OFF = 128;\nconst V0_ENGINE_FUNDING_RATE_BPS_OFF = 136;\nconst V0_ENGINE_LAST_CRANK_SLOT_OFF = 144;\nconst V0_ENGINE_MAX_CRANK_STALENESS_OFF = 152;\nconst V0_ENGINE_TOTAL_OI_OFF = 160;\nconst V0_ENGINE_C_TOT_OFF = 176;\nconst V0_ENGINE_PNL_POS_TOT_OFF = 192;\nconst V0_ENGINE_LIQ_CURSOR_OFF = 208;\nconst V0_ENGINE_GC_CURSOR_OFF = 210;\nconst V0_ENGINE_LAST_SWEEP_START_OFF = 216;\nconst V0_ENGINE_LAST_SWEEP_COMPLETE_OFF = 224;\nconst V0_ENGINE_CRANK_CURSOR_OFF = 232;\nconst V0_ENGINE_SWEEP_START_IDX_OFF = 234;\nconst V0_ENGINE_LIFETIME_LIQUIDATIONS_OFF = 240;\nconst V0_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 248;\nconst V0_ENGINE_NET_LP_POS_OFF = 256;\nconst V0_ENGINE_LP_SUM_ABS_OFF = 272;\nconst V0_ENGINE_LP_MAX_ABS_OFF = 288;\nconst V0_ENGINE_LP_MAX_ABS_SWEEP_OFF = 304;\nconst V0_ENGINE_BITMAP_OFF = 320;\n\n// ---- V1 layout constants (deployed devnet program, PERC-1094 corrected) ----\n// BPF (SBF) target: u128 alignment = 8, so CONFIG_LEN = 496 on-chain.\n// ENGINE_OFF = align_up(HEADER=104 + CONFIG=496, 8) = 600.\n// Previous value (640) was wrong — it assumed CONFIG_LEN=536 from the native build assertion.\nconst V1_HEADER_LEN = 104;\nconst V1_CONFIG_LEN = 496; // BPF (SBF) on-chain value; native test build would be 512\nconst V1_ENGINE_OFF = 600; // align_up(104 + 496, 8) = 600 (was 640 — corrected in PERC-1094)\n// Legacy: CONFIG_LEN=536 was used in pre-PERC-1094 SDK. Some orphaned slabs on devnet may use\n// ENGINE_OFF=640 (65352 bytes for small). We add them to V1_SIZES_LEGACY for read-only parsing.\nconst V1_ENGINE_OFF_LEGACY = 640;\nconst V1_ACCOUNT_SIZE = 248;\nconst V1_RESERVED_OFF = 80;\n\n// V1 engine: vault(16) + insurance expanded(56) → params at 72\n// V1 RiskParams: 288 bytes → runtime state at 360\nconst V1_ENGINE_PARAMS_OFF = 72;\nconst V1_PARAMS_SIZE = 288;\nconst V1_ENGINE_CURRENT_SLOT_OFF = 360;\nconst V1_ENGINE_FUNDING_INDEX_OFF = 368;\nconst V1_ENGINE_LAST_FUNDING_SLOT_OFF = 384;\nconst V1_ENGINE_FUNDING_RATE_BPS_OFF = 392;\nconst V1_ENGINE_MARK_PRICE_OFF = 400;\nconst V1_ENGINE_LAST_CRANK_SLOT_OFF = 424;\nconst V1_ENGINE_MAX_CRANK_STALENESS_OFF = 432;\nconst V1_ENGINE_TOTAL_OI_OFF = 440;\nconst V1_ENGINE_LONG_OI_OFF = 456;\nconst V1_ENGINE_SHORT_OI_OFF = 472;\nconst V1_ENGINE_C_TOT_OFF = 488;\nconst V1_ENGINE_PNL_POS_TOT_OFF = 504;\nconst V1_ENGINE_LIQ_CURSOR_OFF = 520;\nconst V1_ENGINE_GC_CURSOR_OFF = 522;\nconst V1_ENGINE_LAST_SWEEP_START_OFF = 528;\nconst V1_ENGINE_LAST_SWEEP_COMPLETE_OFF = 536;\nconst V1_ENGINE_CRANK_CURSOR_OFF = 544;\nconst V1_ENGINE_SWEEP_START_IDX_OFF = 546;\nconst V1_ENGINE_LIFETIME_LIQUIDATIONS_OFF = 552;\nconst V1_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 560;\nconst V1_ENGINE_NET_LP_POS_OFF = 568;\nconst V1_ENGINE_LP_SUM_ABS_OFF = 584;\nconst V1_ENGINE_LP_MAX_ABS_OFF = 600;\nconst V1_ENGINE_LP_MAX_ABS_SWEEP_OFF = 616;\nconst V1_ENGINE_EMERGENCY_OI_MODE_OFF = 632;\nconst V1_ENGINE_EMERGENCY_START_SLOT_OFF = 640;\nconst V1_ENGINE_LAST_BREAKER_SLOT_OFF = 648;\nconst V1_ENGINE_BITMAP_OFF = 656;\n// On-chain V1_LEGACY slabs (65352 bytes) place the bitmap 16 bytes later than\n// computeSlabSize predicts (formula bitmapOff=656 gives size=65352 correctly, but\n// the deployed program stores the bitmap at rel=672 and the owner field at +200).\n// These corrected values must be used for actual byte-level parsing.\nconst V1_LEGACY_ENGINE_BITMAP_OFF_ACTUAL = 672; // relative to engineOff (abs = 640+672 = 1312)\nconst V1_LEGACY_ACCT_OWNER_OFF = 200; // vs the usual ACCT_OWNER_OFF=184\n\n// ---- V1D layout constants (actually deployed devnet V1 program, rev ac18a0e) ----\n// The deployed V1 program has a DIFFERENT struct layout than the V1 constants above.\n// Key differences:\n// - MarketConfig is smaller (BPF CONFIG_LEN=320 vs V1's 496) — older revision\n// - InsuranceFund is 80 bytes (V1 assumed 56), so params starts at engine+96 (not 72)\n// - Engine lacks lp_max_abs, lp_max_abs_sweep, emergency_oi, trade_twap fields\n// - Bitmap at engine+624 (not 656)\n// Confirmed by on-chain probing of slab 6ZytbpV4 (the only active V1 market).\nconst V1D_CONFIG_LEN = 320;\nconst V1D_ENGINE_OFF = 424; // align_up(104 + 320, 8) = 424\nconst V1D_ACCOUNT_SIZE = 248;\n\n// V1D engine field offsets (relative to engineOff):\n// vault(16) + InsuranceFund(80) → params at 96; RiskParams(288) → runtime at 384\nconst V1D_ENGINE_INSURANCE_OFF = 16;\nconst V1D_ENGINE_PARAMS_OFF = 96;\nconst V1D_PARAMS_SIZE = 288;\nconst V1D_ENGINE_CURRENT_SLOT_OFF = 384;\nconst V1D_ENGINE_FUNDING_INDEX_OFF = 392;\nconst V1D_ENGINE_LAST_FUNDING_SLOT_OFF = 408;\nconst V1D_ENGINE_FUNDING_RATE_BPS_OFF = 416;\nconst V1D_ENGINE_MARK_PRICE_OFF = 424;\n// funding_frozen(1+7pad) at 432, funding_frozen_rate(8) at 440\nconst V1D_ENGINE_LAST_CRANK_SLOT_OFF = 448;\nconst V1D_ENGINE_MAX_CRANK_STALENESS_OFF = 456;\nconst V1D_ENGINE_TOTAL_OI_OFF = 464;\nconst V1D_ENGINE_LONG_OI_OFF = 480;\nconst V1D_ENGINE_SHORT_OI_OFF = 496;\nconst V1D_ENGINE_C_TOT_OFF = 512;\nconst V1D_ENGINE_PNL_POS_TOT_OFF = 528;\nconst V1D_ENGINE_LIQ_CURSOR_OFF = 544;\nconst V1D_ENGINE_GC_CURSOR_OFF = 546;\nconst V1D_ENGINE_LAST_SWEEP_START_OFF = 552;\nconst V1D_ENGINE_LAST_SWEEP_COMPLETE_OFF = 560;\nconst V1D_ENGINE_CRANK_CURSOR_OFF = 568;\nconst V1D_ENGINE_SWEEP_START_IDX_OFF = 570;\nconst V1D_ENGINE_LIFETIME_LIQUIDATIONS_OFF = 576;\nconst V1D_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 584;\nconst V1D_ENGINE_NET_LP_POS_OFF = 592;\nconst V1D_ENGINE_LP_SUM_ABS_OFF = 608;\n// lp_max_abs, lp_max_abs_sweep, emergency_*, trade_twap_* do NOT exist in this version\nconst V1D_ENGINE_BITMAP_OFF = 624;\n\n// ---- V2 layout constants (BPF intermediate layout, ENGINE_OFF=600, BITMAP_OFF=432) ----\n// V2 shares ENGINE_OFF=600 with V1, but has a completely different engine struct layout:\n// - CONFIG_LEN=496 (same as V1 on-chain), HEADER_LEN=104, ACCOUNT_SIZE=248\n// - Engine lacks mark_price, long_oi, short_oi, emergency OI fields\n// - Different field offsets than V1D (which has ENGINE_OFF=424)\n// V2 is identified by reading the version field at slab header offset 8 (u32 LE) == 2.\n// Without data, V2 cannot be distinguished from V1D by size alone (postBitmap=18 produces\n// identical sizes to V1D postBitmap=2 — both 65088 for 256 accounts).\nconst V2_HEADER_LEN = 104;\nconst V2_CONFIG_LEN = 496;\nconst V2_ENGINE_OFF = 600; // align_up(104 + 496, 8) = 600\nconst V2_ACCOUNT_SIZE = 248;\nconst V2_ENGINE_BITMAP_OFF = 432;\n\n// V2 engine field offsets (relative to engineOff)\nconst V2_ENGINE_CURRENT_SLOT_OFF = 352;\nconst V2_ENGINE_FUNDING_INDEX_OFF = 360;\nconst V2_ENGINE_LAST_FUNDING_SLOT_OFF = 376;\nconst V2_ENGINE_FUNDING_RATE_BPS_OFF = 384;\nconst V2_ENGINE_LAST_CRANK_SLOT_OFF = 392;\nconst V2_ENGINE_MAX_CRANK_STALENESS_OFF = 400;\nconst V2_ENGINE_TOTAL_OI_OFF = 408;\nconst V2_ENGINE_C_TOT_OFF = 424;\nconst V2_ENGINE_PNL_POS_TOT_OFF = 440;\nconst V2_ENGINE_LIQ_CURSOR_OFF = 456;\nconst V2_ENGINE_GC_CURSOR_OFF = 458;\nconst V2_ENGINE_LAST_SWEEP_START_OFF = 464;\nconst V2_ENGINE_LAST_SWEEP_COMPLETE_OFF = 472;\nconst V2_ENGINE_CRANK_CURSOR_OFF = 480;\nconst V2_ENGINE_SWEEP_START_IDX_OFF = 482;\nconst V2_ENGINE_LIFETIME_LIQUIDATIONS_OFF = 488;\nconst V2_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 496;\nconst V2_ENGINE_NET_LP_POS_OFF = 504;\nconst V2_ENGINE_LP_SUM_ABS_OFF = 520;\nconst V2_ENGINE_LP_MAX_ABS_OFF = 536;\nconst V2_ENGINE_LP_MAX_ABS_SWEEP_OFF = 552;\n\n// ---- V_ADL layout constants (ADL-upgraded program, PERC-8270/8271) ----\n// This layout corresponds to the percolator lib at commit ed01137 (PERC-8270) which adds:\n// - Account: position_basis_q(i128,16)+adl_a_basis(u128,16)+adl_k_snap(i128,16)+adl_epoch_snap(u64,8) = +56 bytes\n// Plus 8-byte padding before position_basis_q (i128 requires 16-byte align on BPF) → +64 bytes/account\n// - RiskEngine: last_market_slot(u64)+funding_price_sample_last(u64)+materialized_account_count(u64)+last_oracle_price(u64) = +32 bytes\n// - Also adds: InsuranceFund expanded to 80 bytes (balance_incentive_reserve + _rebate_pad + _isolation_padding),\n// RiskParams expanded to 336 bytes (min_nonzero_mm_req, min_nonzero_im_req, insurance_floor, etc.),\n// pnl_matured_pos_tot(u128,16) field in RiskEngine (PERC-8267),\n// ADL side state fields (PERC-8268, +224 bytes engine before bitmap)\n//\n// BPF SLAB_LEN: 1288304 (large/4096-account tier) — verified by cargo build-sbf (PERC-8271)\n// ENGINE_OFF = 624 (HEADER=104 + CONFIG=520 native, aligned to 8 = 624)\n// ACCOUNT_SIZE = 312 (248 old + 8 pad for i128 alignment + 16+16+16+8 new ADL fields)\n// ENGINE_BITMAP_OFF = 1008 (empirically verified: mainnet CCTegYZ... slab, 323312 bytes, 1024 accts)\n// Prior value of 1006 was an arithmetic transcription error.\n// Derivation: trade_twap_e6(8)@992 + twap_last_slot(8)@1000 = bitmap@1008.\nconst V_ADL_ENGINE_OFF = 624; // align_up(HEADER=104 + CONFIG=520, 8) = 624\nconst V_ADL_CONFIG_LEN = 520; // BPF/native MarketConfig with current fields (pre-SetDexPool)\n\n// V_SETDEXPOOL: PERC-SetDexPool security fix — adds dex_pool: [u8; 32] to MarketConfig.\n// BPF CONFIG_LEN: 496→528 (+32). ENGINE_OFF: align_up(104+528,8) = 632 (+8 from V_ADL=624).\n// Engine struct and account layout are identical to V_ADL — only CONFIG_LEN/ENGINE_OFF changed.\nconst V_SETDEXPOOL_CONFIG_LEN = 544; // SBF on-chain CONFIG_LEN after PERC-SetDexPool (target_arch=sbf uses native alignment)\nconst V_SETDEXPOOL_ENGINE_OFF = 648; // align_up(HEADER=104 + CONFIG=544, 8) = 648\n// All engine field offsets are identical to V_ADL (same engine struct, only engineOff differs).\nconst V_ADL_ACCOUNT_SIZE = 312; // 248 + 8(pad) + 56(new ADL fields) = 312 bytes\nconst V_ADL_ENGINE_PARAMS_OFF = 96; // vault(16) + InsuranceFund(80) = 96\n\n// V_ADL RiskParams: 336 bytes (same as V1M, includes all dynamic fee params)\nconst V_ADL_PARAMS_SIZE = 336;\n\n// V_ADL engine field offsets (relative to engineOff=624):\n// vault(16) + InsuranceFund(80) + RiskParams(336) = 432 bytes before current_slot\nconst V_ADL_ENGINE_CURRENT_SLOT_OFF = 432; // 96 + 336 = 432\nconst V_ADL_ENGINE_FUNDING_INDEX_OFF = 440; // 432 + 8\nconst V_ADL_ENGINE_LAST_FUNDING_SLOT_OFF = 456; // 440 + 16\nconst V_ADL_ENGINE_FUNDING_RATE_BPS_OFF = 464; // 456 + 8\n// PERC-8270 new fields at 472-504:\n// last_market_slot(8)@472, funding_price_sample_last(8)@480, materialized_account_count(8)@488, last_oracle_price(8)@496\nconst V_ADL_ENGINE_MARK_PRICE_OFF = 504; // 464+8+32 = 504 (shifted +104 from V1's 400)\n// funding_frozen(1+7pad=8)@512, funding_frozen_rate_snapshot(i64,8)@520\nconst V_ADL_ENGINE_LAST_CRANK_SLOT_OFF = 528; // was 424 in V1, +104\nconst V_ADL_ENGINE_MAX_CRANK_STALENESS_OFF = 536;\nconst V_ADL_ENGINE_TOTAL_OI_OFF = 544; // was 440 in V1, +104\nconst V_ADL_ENGINE_LONG_OI_OFF = 560; // was 456 in V1, +104\nconst V_ADL_ENGINE_SHORT_OI_OFF = 576; // was 472 in V1, +104\nconst V_ADL_ENGINE_C_TOT_OFF = 592; // was 488 in V1, +104\nconst V_ADL_ENGINE_PNL_POS_TOT_OFF = 608; // was 504 in V1, +104\n// pnl_matured_pos_tot(u128,16)@624 — NEW in PERC-8267\nconst V_ADL_ENGINE_LIQ_CURSOR_OFF = 640; // was 520 in V1, +120 (extra 16 for pnl_matured)\nconst V_ADL_ENGINE_GC_CURSOR_OFF = 642;\n// last_sweep_start(u64)@648, last_sweep_complete(u64)@656, crank_cursor(u16)@664, sweep_idx(u16)@666\nconst V_ADL_ENGINE_LAST_SWEEP_START_OFF = 648;\nconst V_ADL_ENGINE_LAST_SWEEP_COMPLETE_OFF = 656;\nconst V_ADL_ENGINE_CRANK_CURSOR_OFF = 664;\nconst V_ADL_ENGINE_SWEEP_START_IDX_OFF = 666;\n// lifetime_liquidations(u64)@672, lifetime_force_closes(u64)@680\nconst V_ADL_ENGINE_LIFETIME_LIQUIDATIONS_OFF = 672;\nconst V_ADL_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 680;\n// ADL side state (PERC-8268, 224 bytes):\n// adl_mult_long/short(16ea), adl_coeff_long/short(16ea), adl_epoch_long/short(8ea),\n// adl_epoch_start_k_long/short(16ea), oi_eff_long/short_q(16ea),\n// side_mode_long(u8)+side_mode_short(u8)+pad(6), stored_pos_count×2, stale_count×2(all u64,8),\n// phantom_dust_bound_long/short_q(16ea) = 224 bytes at offsets 688–911\n// Then LP aggregates:\nconst V_ADL_ENGINE_NET_LP_POS_OFF = 904; // after ADL side state\nconst V_ADL_ENGINE_LP_SUM_ABS_OFF = 920;\nconst V_ADL_ENGINE_LP_MAX_ABS_OFF = 936;\nconst V_ADL_ENGINE_LP_MAX_ABS_SWEEP_OFF = 952;\n// emergency fields:\nconst V_ADL_ENGINE_EMERGENCY_OI_MODE_OFF = 968;\nconst V_ADL_ENGINE_EMERGENCY_START_SLOT_OFF = 976;\nconst V_ADL_ENGINE_LAST_BREAKER_SLOT_OFF = 984;\n// trade_twap_e6(8)@992, twap_last_slot(8)@1000, bitmap([u64;N])@1008\n// Corrected from 1006 → 1008: 992+8(trade_twap_e6)+8(twap_last_slot)=1008. Arithmetic\n// transcription error in prior constant — 1008+512+18+8192=9730 rounds to 9736 (8-byte align),\n// but empirically mainnet CCTegYZ... slab (323312 bytes, 1024 accts) confirms bitmapOff=1008.\nconst V_ADL_ENGINE_BITMAP_OFF = 1008; // Empirically verified: mainnet slab CCTegYZ...\n\n// V_ADL account field offsets (relative to account slot start):\n// account_id(8)+capital(U128,16)+kind(u8+pad7=8)+pnl(I128,16)+reserved_pnl(u128,16)=64\nconst V_ADL_ACCT_WARMUP_STARTED_OFF = 64; // was 56\nconst V_ADL_ACCT_WARMUP_SLOPE_OFF = 72; // was 64\nconst V_ADL_ACCT_POSITION_SIZE_OFF = 88; // was 80\nconst V_ADL_ACCT_ENTRY_PRICE_OFF = 104; // was 96\nconst V_ADL_ACCT_FUNDING_INDEX_OFF = 112; // was 104\nconst V_ADL_ACCT_MATCHER_PROGRAM_OFF = 128; // was 120\nconst V_ADL_ACCT_MATCHER_CONTEXT_OFF = 160; // was 152\nconst V_ADL_ACCT_OWNER_OFF = 192; // was 184 (shifted +8 from reserved_pnl u64→u128)\nconst V_ADL_ACCT_FEE_CREDITS_OFF = 224; // was 216\nconst V_ADL_ACCT_LAST_FEE_SLOT_OFF = 240; // was 232\n\n// ---- V12_1 layout constants (percolator-core v12.1 merge) ----\n// Account struct grew: 312→320 bytes on SBF (new fields: position_basis_q, adl_a_basis,\n// adl_k_snap, adl_epoch_snap, fees_earned_total; fee_credits/last_fee_slot reordered).\n// RiskParams grew: 336→352 bytes on SBF (new fields: min_initial_deposit, insurance_floor,\n// risk_reduction_threshold, liquidation_buffer_bps, funding premium params, partial liq,\n// dynamic fee tiers, fee splits).\n// Engine field ordering completely reorganized from V_ADL.\n// All values verified by cargo build-sbf compile-time assertions.\nconst V12_1_ENGINE_OFF = 648; // align_up(104 + 544, 8) = 648 (same as V_SETDEXPOOL)\nconst V12_1_ACCOUNT_SIZE = 320; // 312 + 8 (position_size now i128 not just legacy)\nconst V12_1_ENGINE_BITMAP_OFF = 1016; // RiskParams grew 16 bytes + lifetime_force_realize_closes added\nconst V12_1_ENGINE_PARAMS_OFF = 96; // vault(16) + InsuranceFund(80) = 96\nconst V12_1_PARAMS_SIZE = 352; // 336 + 16 (new fields)\n// Engine field offsets (relative to engineOff):\nconst V12_1_ENGINE_CURRENT_SLOT_OFF = 448;\nconst V12_1_ENGINE_FUNDING_RATE_BPS_OFF = 456; // funding_rate_bps_per_slot_last\nconst V12_1_ENGINE_LAST_CRANK_SLOT_OFF = 464;\nconst V12_1_ENGINE_MAX_CRANK_STALENESS_OFF = 472;\nconst V12_1_ENGINE_C_TOT_OFF = 480;\nconst V12_1_ENGINE_PNL_POS_TOT_OFF = 496;\n// pnl_matured_pos_tot(u128)@512\nconst V12_1_ENGINE_LIQ_CURSOR_OFF = 528;\nconst V12_1_ENGINE_GC_CURSOR_OFF = 530;\nconst V12_1_ENGINE_LAST_SWEEP_START_OFF = 536;\nconst V12_1_ENGINE_LAST_SWEEP_COMPLETE_OFF = 544;\nconst V12_1_ENGINE_CRANK_CURSOR_OFF = 552;\nconst V12_1_ENGINE_SWEEP_START_IDX_OFF = 554;\nconst V12_1_ENGINE_LIFETIME_LIQUIDATIONS_OFF = 560;\n// ADL side state at 568–815 (not directly read by SDK)\nconst V12_1_ENGINE_TOTAL_OI_OFF = 816;\nconst V12_1_ENGINE_LONG_OI_OFF = 832;\nconst V12_1_ENGINE_SHORT_OI_OFF = 848;\nconst V12_1_ENGINE_NET_LP_POS_OFF = 864;\nconst V12_1_ENGINE_LP_SUM_ABS_OFF = 880;\nconst V12_1_ENGINE_LP_MAX_ABS_OFF = 896;\nconst V12_1_ENGINE_LP_MAX_ABS_SWEEP_OFF = 912;\nconst V12_1_ENGINE_MARK_PRICE_OFF = 928;\nconst V12_1_ENGINE_FUNDING_INDEX_OFF = 936;\nconst V12_1_ENGINE_LAST_FUNDING_SLOT_OFF = 944;\n// funding_frozen(bool)@952, pad@953-959, funding_frozen_rate_snapshot(i64)@960\nconst V12_1_ENGINE_EMERGENCY_OI_MODE_OFF = 968;\nconst V12_1_ENGINE_EMERGENCY_START_SLOT_OFF = 976;\nconst V12_1_ENGINE_LAST_BREAKER_SLOT_OFF = 984;\n// trade_twap_e6(8)@992, twap_last_slot(8)@1000, lifetime_force_realize_closes(8)@1008\nconst V12_1_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 1008;\n// bitmap at 1016\n// V12_1 account field offsets (relative to account slot start):\n// New fields position_basis_q(i128@88), adl_a_basis(u128@104), adl_k_snap(i128@120),\n// adl_epoch_snap(u64@136) inserted before matcher_*, shifting everything from offset 128+ by +16.\nconst V12_1_ACCT_MATCHER_PROGRAM_OFF = 144; // was 128 in V_ADL (+16 from new ADL fields)\nconst V12_1_ACCT_MATCHER_CONTEXT_OFF = 176; // was 160 in V_ADL (+16 from new ADL fields)\nconst V12_1_ACCT_OWNER_OFF = 208; // was 192 in V_ADL (+16 from new ADL fields)\nconst V12_1_ACCT_FEE_CREDITS_OFF = 240; // was 224 in V_ADL\nconst V12_1_ACCT_LAST_FEE_SLOT_OFF = 256; // was 240 in V_ADL\nconst V12_1_ACCT_POSITION_SIZE_OFF = 296; // moved to end (legacy field)\nconst V12_1_ACCT_ENTRY_PRICE_OFF = 280; // moved to end (legacy field)\nconst V12_1_ACCT_FUNDING_INDEX_OFF = 288; // moved to end (legacy, i64 not i128)\n\n// ---- V1M layout constants (mainnet-deployed V1 program, ESa89R5) ----\n// The mainnet program has a LARGER RiskParams (336 bytes vs V1's 288) and 22 extra\n// bytes in the runtime state (trade_twap_e6 + twap_last_slot + alignment padding).\n// ENGINE_OFF=640 (same as V1_LEGACY), CONFIG_LEN=536, ACCOUNT_SIZE=248.\n// Confirmed by byte-level probing of mainnet slab 8NY7rvQ (SOL/USDC Perpetual).\nconst V1M_ENGINE_OFF = 640; // align_up(104 + 536, 8) = 640 (same as V1_LEGACY)\nconst V1M_CONFIG_LEN = 536; // MarketConfig size in native/mainnet build\nconst V1M_ACCOUNT_SIZE = 248;\n// V1M2: rebuilt from main@4861c56, CONFIG_LEN=512 on SBF → ENGINE_OFF=616\nconst V1M2_ENGINE_OFF = 616; // align_up(104 + 512, 8) = 616\nconst V1M2_CONFIG_LEN = 512; // MarketConfig with u128 native alignment on SBF\nconst V1M_ENGINE_PARAMS_OFF = 72; // vault(16) + InsuranceFund(56) = 72 (same as V1)\nconst V1M2_ENGINE_PARAMS_OFF = 96; // vault(16) + InsuranceFund(80) = 96 (expanded in main@4861c56)\n\n// V1M RiskParams: 336 bytes (+48 over V1's 288)\n// Extra fields: fee_utilization_surge_bps(8) [in SDK V1 already? no → +8],\n// balance_incentive_reserve configs (+8?), min_nonzero_mm_req(u128=16),\n// min_nonzero_im_req(u128=16) = +48 total\nconst V1M_PARAMS_SIZE = 336;\n\n// V1M runtime state starts at engine+408 (72 + 336) instead of V1's +360\nconst V1M_ENGINE_CURRENT_SLOT_OFF = 408;\nconst V1M_ENGINE_FUNDING_INDEX_OFF = 416;\nconst V1M_ENGINE_LAST_FUNDING_SLOT_OFF = 432;\nconst V1M_ENGINE_FUNDING_RATE_BPS_OFF = 440;\nconst V1M_ENGINE_MARK_PRICE_OFF = 448;\n// funding_frozen(1+7pad) at 456, funding_frozen_rate(8) at 464\nconst V1M_ENGINE_LAST_CRANK_SLOT_OFF = 472;\nconst V1M_ENGINE_MAX_CRANK_STALENESS_OFF = 480;\nconst V1M_ENGINE_TOTAL_OI_OFF = 488;\nconst V1M_ENGINE_LONG_OI_OFF = 504;\nconst V1M_ENGINE_SHORT_OI_OFF = 520;\nconst V1M_ENGINE_C_TOT_OFF = 536;\nconst V1M_ENGINE_PNL_POS_TOT_OFF = 552;\nconst V1M_ENGINE_LIQ_CURSOR_OFF = 568;\nconst V1M_ENGINE_GC_CURSOR_OFF = 570;\nconst V1M_ENGINE_LAST_SWEEP_START_OFF = 576;\nconst V1M_ENGINE_LAST_SWEEP_COMPLETE_OFF = 584;\nconst V1M_ENGINE_CRANK_CURSOR_OFF = 592;\nconst V1M_ENGINE_SWEEP_START_IDX_OFF = 594;\nconst V1M_ENGINE_LIFETIME_LIQUIDATIONS_OFF = 600;\nconst V1M_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 608;\nconst V1M_ENGINE_NET_LP_POS_OFF = 616;\nconst V1M_ENGINE_LP_SUM_ABS_OFF = 632;\nconst V1M_ENGINE_LP_MAX_ABS_OFF = 648;\nconst V1M_ENGINE_LP_MAX_ABS_SWEEP_OFF = 664;\nconst V1M_ENGINE_EMERGENCY_OI_MODE_OFF = 680;\nconst V1M_ENGINE_EMERGENCY_START_SLOT_OFF = 688;\nconst V1M_ENGINE_LAST_BREAKER_SLOT_OFF = 696;\n// trade_twap_e6(8) at 704, twap_last_slot(8) at 712 → bitmap at 720\n// No padding between twap_last_slot and used bitmap (u64 array is 8-byte\n// aligned and 720 % 8 == 0). Previous value of 726 was wrong — 726 % 8 = 6\n// which is invalid for a [u64; N] array under #[repr(C)].\nconst V1M_ENGINE_BITMAP_OFF = 720;\n\n// V1M2: mainnet program rebuilt from main@4861c56 with --features medium.\n// ENGINE_OFF=616 (not 640): CONFIG_LEN=512 on SBF because cfg(target_arch=\"bpf\")\n// doesn't match the SBF toolchain (target_arch=\"sbf\"), so u128 align=16 (native) applies.\n// align_up(HEADER=104 + CONFIG=512, 8) = 616.\n// Slab sizes match V_ADL exactly — disambiguation required via data inspection.\n// Confirmed by on-chain probing of slab 7T1Efij9 (SOL-PERP, 323312 bytes, medium tier).\n// Engine struct is larger than V1M (990 vs 720 bitmap offset = +270 runtime bytes).\n// New runtime fields inserted between fundingRateBps and markPrice:\n// +408: currentSlot, +416: fundingIndex(i128), +432: lastFundingSlot, +440: fundingRateBps\n// +448: NEW lastOracleUpdateSlot(?), +456: authorityPriceE6(?), +464-471: reserved\n// +472: lastEffectivePriceE6(?), +480: markPriceE6, +488-503: reserved\n// +504: lastCrankSlot, +512: maxCrankStaleness\nconst V1M2_ACCOUNT_SIZE = 312; // 248 + 64 bytes of new fields per account\n// V1M2 bitmap offset: empirically verified from mainnet slab CCTegYZ... (323312 bytes, 1024 accts).\n// The V1M2 engine struct is layout-identical to V_ADL — same relative field offsets from engineOff.\n// V_ADL_ENGINE_BITMAP_OFF (1008) is correct for V1M2 as well; prior value of 990 was wrong.\nconst V1M2_ENGINE_BITMAP_OFF = 1008; // Same as V_ADL_ENGINE_BITMAP_OFF — V1M2 uses V_ADL engine struct\n\n// For backward compatibility, export ENGINE_OFF and ENGINE_MARK_PRICE_OFF\n// (used by reinit-slab and other scripts). These refer to V1 layout.\nexport const ENGINE_OFF = V1_ENGINE_OFF;\nexport const ENGINE_MARK_PRICE_OFF = V1_ENGINE_MARK_PRICE_OFF;\n\n// ---- Known slab sizes per version and tier ----\n\n/**\n * Compute the total byte size of a slab given its layout parameters.\n * Used to pre-populate the known-size lookup maps at module load time.\n */\nfunction computeSlabSize(\n engineOff: number,\n bitmapOff: number,\n accountSize: number,\n maxAccounts: number,\n // postBitmap bytes immediately after the free-slot bitmap:\n // SDK default (V0/V1/V1-legacy): 18 = num_used(u16,2) + pad(6) + next_account_id(u64,8) + free_head(u16,2)\n // V1D deployed program: 2 = free_head(u16,2) only — no num_used, pad, or next_account_id\n postBitmap = 18,\n): number {\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOff = Math.ceil(preAccountsLen / 8) * 8;\n return engineOff + accountsOff + maxAccounts * accountSize;\n}\n\nconst TIERS = [64, 256, 1024, 4096] as const;\n\n// Pre-compute known slab sizes for fast lookup\nconst V0_SIZES = new Map<number, number>();\nconst V1_SIZES = new Map<number, number>();\n// Legacy V1 sizes using incorrect ENGINE_OFF=640 (pre-PERC-1094). Orphaned on devnet; read-only.\nconst V1_SIZES_LEGACY = new Map<number, number>();\n// V1D: actually deployed V1 program (ENGINE_OFF=424, BITMAP_OFF=624)\nconst V1D_SIZES = new Map<number, number>();\n// V1D_SIZES_LEGACY: on-chain slabs created before GH#1234 when SDK assumed postBitmap=18.\n// These are 16 bytes larger per tier (micro=17080, small=65104, medium=257200, large=1025584).\n// The top active market (6ZytbpV4, $14k 24h vol) was created with postBitmap=18 and uses 65104.\n// PR #1236 fixed postBitmap for new slabs (→2) but broke recognition of these legacy 65104 slabs.\n// GH#1237: add both size variants so detectSlabLayout handles both old and new V1D on-chain data.\n// V2: ENGINE_OFF=600, BITMAP_OFF=432, ACCOUNT_SIZE=248, postBitmap=18\nconst V2_SIZES = new Map<number, number>();\n// V1M: mainnet-deployed V1 program (ENGINE_OFF=640, BITMAP_OFF=726, expanded RiskParams)\nconst V1M_SIZES = new Map<number, number>();\n// V_ADL: PERC-8270/8271 ADL-upgraded program (ENGINE_OFF=624, BITMAP_OFF=1008, ACCOUNT_SIZE=312)\nconst V_ADL_SIZES = new Map<number, number>();\n// V1M2: main@4861c56 with 312-byte accounts (ENGINE_OFF=616, BITMAP_OFF=1008, ACCOUNT_SIZE=312)\n// After fixing bitmapOff to 1008 for both V1M2 and V_ADL, sizes differ because engineOff differs:\n// V1M2 medium (1024 accts): computeSlabSize(616, 1008, 312, 1024, 18) = 323312\n// V_ADL medium (1024 accts): computeSlabSize(624, 1008, 312, 1024, 18) = 323320\n// No disambiguation probe required — size-based detection works correctly.\nconst V1M2_SIZES = new Map<number, number>();\n// V_SETDEXPOOL: PERC-SetDexPool — ENGINE_OFF=648, BITMAP_OFF=1008, ACCOUNT_SIZE=312.\n// Same engine and account layout as V_ADL; only ENGINE_OFF changed (+8 from config growth).\n// e.g. large (4096 accts): computeSlabSize(632, 1008, 312, 4096, 18) = 1288336\nconst V_SETDEXPOOL_SIZES = new Map<number, number>();\n// V12_1: percolator-core v12.1 merge — engineOff=648, bitmapOff=1016, accountSize=320.\n// Verified by cargo build-sbf compile-time assertions. Account grew 8 bytes, bitmap shifted 8.\n// e.g. large (4096 accts): computeSlabSize(648, 1016, 320, 4096, 18) = 1321112\nconst V12_1_SIZES = new Map<number, number>();\nconst V1D_SIZES_LEGACY = new Map<number, number>();\nfor (const n of TIERS) {\n V0_SIZES.set(computeSlabSize(V0_ENGINE_OFF, V0_ENGINE_BITMAP_OFF, V0_ACCOUNT_SIZE, n), n);\n V1_SIZES.set(computeSlabSize(V1_ENGINE_OFF, V1_ENGINE_BITMAP_OFF, V1_ACCOUNT_SIZE, n), n);\n V1_SIZES_LEGACY.set(computeSlabSize(V1_ENGINE_OFF_LEGACY, V1_ENGINE_BITMAP_OFF, V1_ACCOUNT_SIZE, n), n);\n // GH#1234: V1D deployed program omits num_used/pad/next_account_id → postBitmap=2 (free_head only).\n // This yields 65088 (n=256) and 1025568 (n=4096) matching actual devnet account sizes.\n V1D_SIZES.set(computeSlabSize(V1D_ENGINE_OFF, V1D_ENGINE_BITMAP_OFF, V1D_ACCOUNT_SIZE, n, 2), n);\n // GH#1237: also register the legacy postBitmap=18 sizes for slabs created before GH#1234 fix.\n V1D_SIZES_LEGACY.set(computeSlabSize(V1D_ENGINE_OFF, V1D_ENGINE_BITMAP_OFF, V1D_ACCOUNT_SIZE, n, 18), n);\n // V2: postBitmap=18 — produces same sizes as V1D postBitmap=2 (e.g. 65088 for n=256).\n // Disambiguation requires peeking at the version field in the slab header.\n V2_SIZES.set(computeSlabSize(V2_ENGINE_OFF, V2_ENGINE_BITMAP_OFF, V2_ACCOUNT_SIZE, n, 18), n);\n // V1M: mainnet program with expanded RiskParams (336 bytes) and trade_twap fields.\n // e.g. n=1024 → 257512 bytes (confirmed on-chain for slab 8NY7rvQ).\n V1M_SIZES.set(computeSlabSize(V1M_ENGINE_OFF, V1M_ENGINE_BITMAP_OFF, V1M_ACCOUNT_SIZE, n, 18), n);\n // V_ADL: PERC-8270 ADL-upgraded program — new account size (312) and expanded engine layout.\n // e.g. n=4096 → 1288320 bytes (engineOff=624, bitmapOff=1008).\n V_ADL_SIZES.set(computeSlabSize(V_ADL_ENGINE_OFF, V_ADL_ENGINE_BITMAP_OFF, V_ADL_ACCOUNT_SIZE, n, 18), n);\n // V1M2: main@4861c56 rebuild — engineOff=616, bitmapOff=1008, accountSize=312.\n // e.g. n=1024 → 323312 bytes (confirmed on-chain for slab CCTegYZ...).\n V1M2_SIZES.set(computeSlabSize(V1M2_ENGINE_OFF, V1M2_ENGINE_BITMAP_OFF, V1M2_ACCOUNT_SIZE, n, 18), n);\n // V_SETDEXPOOL: PERC-SetDexPool — engineOff=648, bitmapOff=1008, accountSize=312.\n // e.g. n=4096 → 1288336 bytes.\n V_SETDEXPOOL_SIZES.set(computeSlabSize(V_SETDEXPOOL_ENGINE_OFF, V_ADL_ENGINE_BITMAP_OFF, V_ADL_ACCOUNT_SIZE, n, 18), n);\n // V12_1: percolator-core v12.1 — accountSize=320, bitmapOff=1016.\n // e.g. n=4096 → 1321112; n=1024 → 331544; n=256 → 84152; n=64 → 22304.\n V12_1_SIZES.set(computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, n, 18), n);\n}\n\n/**\n * V2 slab tier sizes (small and large) for discovery.\n * V2 uses ENGINE_OFF=600, BITMAP_OFF=432, ACCOUNT_SIZE=248, postBitmap=18.\n * Sizes overlap with V1D (postBitmap=2) — disambiguation requires reading the version field.\n */\nexport const SLAB_TIERS_V2 = {\n small: { maxAccounts: 256, dataSize: 65_088, label: \"Small\", description: \"256 slots (V2 BPF intermediate)\" },\n large: { maxAccounts: 4096, dataSize: 1_025_568, label: \"Large\", description: \"4,096 slots (V2 BPF intermediate)\" },\n} as const;\n\n/**\n * V1M slab tier sizes — mainnet-deployed V1 program (ESa89R5).\n * ENGINE_OFF=640, BITMAP_OFF=726, ACCOUNT_SIZE=248, postBitmap=18.\n * Expanded RiskParams (336 bytes) and trade_twap runtime fields.\n * Confirmed by on-chain probing of slab 8NY7rvQ (SOL/USDC Perpetual, 257512 bytes).\n */\nexport const SLAB_TIERS_V1M: Record<string, { maxAccounts: number; dataSize: number; label: string; description: string }> = {};\nfor (const [label, n] of [[\"Micro\", 64], [\"Small\", 256], [\"Medium\", 1024], [\"Large\", 4096]] as const) {\n const size = computeSlabSize(V1M_ENGINE_OFF, V1M_ENGINE_BITMAP_OFF, V1M_ACCOUNT_SIZE, n, 18);\n SLAB_TIERS_V1M[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (V1M mainnet)` };\n}\n\n/**\n * V1M2 slab tier sizes — mainnet program rebuilt from main@4861c56 with 312-byte accounts.\n * ENGINE_OFF=616, BITMAP_OFF=1008 (empirically verified from CCTegYZ...).\n * Engine struct is layout-identical to V_ADL; differs only in engineOff (616 vs 624).\n * Sizes are unique from V_ADL after the bitmap correction: medium=323312 vs V_ADL=323320.\n */\nexport const SLAB_TIERS_V1M2: Record<string, { maxAccounts: number; dataSize: number; label: string; description: string }> = {};\nfor (const [label, n] of [[\"Micro\", 64], [\"Small\", 256], [\"Medium\", 1024], [\"Large\", 4096]] as const) {\n const size = computeSlabSize(V1M2_ENGINE_OFF, V1M2_ENGINE_BITMAP_OFF, V1M2_ACCOUNT_SIZE, n, 18);\n SLAB_TIERS_V1M2[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (V1M2 mainnet upgraded)` };\n}\n\n/**\n * V_ADL slab tier sizes — PERC-8270/8271 ADL-upgraded program.\n * ENGINE_OFF=624, BITMAP_OFF=1008, ACCOUNT_SIZE=312, postBitmap=18.\n * New account layout adds ADL tracking fields (+64 bytes/account including alignment padding).\n * BPF SLAB_LEN verified by cargo build-sbf in PERC-8271: large (4096) = 1288320 bytes.\n */\nexport const SLAB_TIERS_V_ADL: Record<string, { maxAccounts: number; dataSize: number; label: string; description: string }> = {};\nfor (const [label, n] of [[\"Micro\", 64], [\"Small\", 256], [\"Medium\", 1024], [\"Large\", 4096]] as const) {\n const size = computeSlabSize(V_ADL_ENGINE_OFF, V_ADL_ENGINE_BITMAP_OFF, V_ADL_ACCOUNT_SIZE, n, 18);\n SLAB_TIERS_V_ADL[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (V_ADL PERC-8270)` };\n}\n\n/**\n * Build a complete SlabLayout descriptor for V0 or V1 (including V1-legacy) slabs.\n * Pass `engineOffOverride` to handle orphaned pre-PERC-1094 slabs that used ENGINE_OFF=640.\n */\nfunction buildLayout(version: 0 | 1, maxAccounts: number, engineOffOverride?: number): SlabLayout {\n const isV0 = version === 0;\n const engineOff = engineOffOverride ?? (isV0 ? V0_ENGINE_OFF : V1_ENGINE_OFF);\n const isV1Legacy = !isV0 && engineOffOverride === V1_ENGINE_OFF_LEGACY;\n // For accountsOff calculation, V1_LEGACY must use its actual bitmap offset (672, not 656).\n // Using the formula bitmapOff (656) produces accountsOff=1864, but accounts actually\n // start at 1880 — a 16-byte gap caused by the extra fields in the V1_LEGACY engine.\n // Non-V1_LEGACY slabs: actualBitmapOff === bitmapOff, so no change.\n const bitmapOff = isV0 ? V0_ENGINE_BITMAP_OFF : V1_ENGINE_BITMAP_OFF;\n const actualBitmapOff = isV1Legacy ? V1_LEGACY_ENGINE_BITMAP_OFF_ACTUAL\n : (isV0 ? V0_ENGINE_BITMAP_OFF : V1_ENGINE_BITMAP_OFF);\n const accountSize = isV0 ? V0_ACCOUNT_SIZE : V1_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n // Use actualBitmapOff so V1_LEGACY gets accountsOff=1880 (not 1864).\n const preAccountsLen = actualBitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version,\n headerLen: isV0 ? V0_HEADER_LEN : V1_HEADER_LEN,\n configOffset: isV0 ? V0_HEADER_LEN : V1_HEADER_LEN,\n configLen: isV0 ? V0_CONFIG_LEN : V1_CONFIG_LEN,\n reservedOff: isV0 ? V0_RESERVED_OFF : V1_RESERVED_OFF,\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: isV0 ? V0_ENGINE_PARAMS_OFF : V1_ENGINE_PARAMS_OFF,\n paramsSize: isV0 ? V0_PARAMS_SIZE : V1_PARAMS_SIZE,\n engineCurrentSlotOff: isV0 ? V0_ENGINE_CURRENT_SLOT_OFF : V1_ENGINE_CURRENT_SLOT_OFF,\n engineFundingIndexOff: isV0 ? V0_ENGINE_FUNDING_INDEX_OFF : V1_ENGINE_FUNDING_INDEX_OFF,\n engineLastFundingSlotOff: isV0 ? V0_ENGINE_LAST_FUNDING_SLOT_OFF : V1_ENGINE_LAST_FUNDING_SLOT_OFF,\n engineFundingRateBpsOff: isV0 ? V0_ENGINE_FUNDING_RATE_BPS_OFF : V1_ENGINE_FUNDING_RATE_BPS_OFF,\n engineMarkPriceOff: isV0 ? -1 : V1_ENGINE_MARK_PRICE_OFF,\n engineLastCrankSlotOff: isV0 ? V0_ENGINE_LAST_CRANK_SLOT_OFF : V1_ENGINE_LAST_CRANK_SLOT_OFF,\n engineMaxCrankStalenessOff: isV0 ? V0_ENGINE_MAX_CRANK_STALENESS_OFF : V1_ENGINE_MAX_CRANK_STALENESS_OFF,\n engineTotalOiOff: isV0 ? V0_ENGINE_TOTAL_OI_OFF : V1_ENGINE_TOTAL_OI_OFF,\n engineLongOiOff: isV0 ? -1 : V1_ENGINE_LONG_OI_OFF,\n engineShortOiOff: isV0 ? -1 : V1_ENGINE_SHORT_OI_OFF,\n engineCTotOff: isV0 ? V0_ENGINE_C_TOT_OFF : V1_ENGINE_C_TOT_OFF,\n enginePnlPosTotOff: isV0 ? V0_ENGINE_PNL_POS_TOT_OFF : V1_ENGINE_PNL_POS_TOT_OFF,\n engineLiqCursorOff: isV0 ? V0_ENGINE_LIQ_CURSOR_OFF : V1_ENGINE_LIQ_CURSOR_OFF,\n engineGcCursorOff: isV0 ? V0_ENGINE_GC_CURSOR_OFF : V1_ENGINE_GC_CURSOR_OFF,\n engineLastSweepStartOff: isV0 ? V0_ENGINE_LAST_SWEEP_START_OFF : V1_ENGINE_LAST_SWEEP_START_OFF,\n engineLastSweepCompleteOff: isV0 ? V0_ENGINE_LAST_SWEEP_COMPLETE_OFF : V1_ENGINE_LAST_SWEEP_COMPLETE_OFF,\n engineCrankCursorOff: isV0 ? V0_ENGINE_CRANK_CURSOR_OFF : V1_ENGINE_CRANK_CURSOR_OFF,\n engineSweepStartIdxOff: isV0 ? V0_ENGINE_SWEEP_START_IDX_OFF : V1_ENGINE_SWEEP_START_IDX_OFF,\n engineLifetimeLiquidationsOff: isV0 ? V0_ENGINE_LIFETIME_LIQUIDATIONS_OFF : V1_ENGINE_LIFETIME_LIQUIDATIONS_OFF,\n engineLifetimeForceClosesOff: isV0 ? V0_ENGINE_LIFETIME_FORCE_CLOSES_OFF : V1_ENGINE_LIFETIME_FORCE_CLOSES_OFF,\n engineNetLpPosOff: isV0 ? V0_ENGINE_NET_LP_POS_OFF : V1_ENGINE_NET_LP_POS_OFF,\n engineLpSumAbsOff: isV0 ? V0_ENGINE_LP_SUM_ABS_OFF : V1_ENGINE_LP_SUM_ABS_OFF,\n engineLpMaxAbsOff: isV0 ? V0_ENGINE_LP_MAX_ABS_OFF : V1_ENGINE_LP_MAX_ABS_OFF,\n engineLpMaxAbsSweepOff: isV0 ? V0_ENGINE_LP_MAX_ABS_SWEEP_OFF : V1_ENGINE_LP_MAX_ABS_SWEEP_OFF,\n engineEmergencyOiModeOff: isV0 ? -1 : V1_ENGINE_EMERGENCY_OI_MODE_OFF,\n engineEmergencyStartSlotOff: isV0 ? -1 : V1_ENGINE_EMERGENCY_START_SLOT_OFF,\n engineLastBreakerSlotOff: isV0 ? -1 : V1_ENGINE_LAST_BREAKER_SLOT_OFF,\n engineBitmapOff: actualBitmapOff,\n postBitmap: 18,\n acctOwnerOff: ACCT_OWNER_OFF,\n\n hasInsuranceIsolation: !isV0,\n engineInsuranceIsolatedOff: isV0 ? -1 : 48,\n engineInsuranceIsolationBpsOff: isV0 ? -1 : 64,\n };\n}\n\n/**\n * Build layout for V1D (actually deployed V1 program, rev ac18a0e).\n * Uses correct field offsets derived from on-chain probing.\n *\n * @param maxAccounts - Number of account slots in the slab\n * @param postBitmap - Bytes after the bitmap before next_free array.\n * 2 = free_head(u16) only — deployed program (GH#1234, default for new slabs)\n * 18 = num_used(u16)+pad(6)+next_account_id(u64)+free_head(u16) — legacy on-chain slabs (GH#1237)\n */\n/**\n * Build a SlabLayout for the actually-deployed V1D program (ENGINE_OFF=424).\n * `postBitmap` is 2 for new slabs (free_head only) and 18 for legacy on-chain slabs\n * created before the GH#1234 fix that removed num_used/pad/next_account_id.\n */\nfunction buildLayoutV1D(maxAccounts: number, postBitmap = 2): SlabLayout {\n const engineOff = V1D_ENGINE_OFF;\n const bitmapOff = V1D_ENGINE_BITMAP_OFF;\n const accountSize = V1D_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version: 1,\n headerLen: V1_HEADER_LEN,\n configOffset: V1_HEADER_LEN,\n configLen: V1D_CONFIG_LEN,\n reservedOff: V1_RESERVED_OFF,\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: V1D_ENGINE_INSURANCE_OFF,\n engineParamsOff: V1D_ENGINE_PARAMS_OFF,\n paramsSize: V1D_PARAMS_SIZE,\n engineCurrentSlotOff: V1D_ENGINE_CURRENT_SLOT_OFF,\n engineFundingIndexOff: V1D_ENGINE_FUNDING_INDEX_OFF,\n engineLastFundingSlotOff: V1D_ENGINE_LAST_FUNDING_SLOT_OFF,\n engineFundingRateBpsOff: V1D_ENGINE_FUNDING_RATE_BPS_OFF,\n engineMarkPriceOff: V1D_ENGINE_MARK_PRICE_OFF,\n engineLastCrankSlotOff: V1D_ENGINE_LAST_CRANK_SLOT_OFF,\n engineMaxCrankStalenessOff: V1D_ENGINE_MAX_CRANK_STALENESS_OFF,\n engineTotalOiOff: V1D_ENGINE_TOTAL_OI_OFF,\n engineLongOiOff: V1D_ENGINE_LONG_OI_OFF,\n engineShortOiOff: V1D_ENGINE_SHORT_OI_OFF,\n engineCTotOff: V1D_ENGINE_C_TOT_OFF,\n enginePnlPosTotOff: V1D_ENGINE_PNL_POS_TOT_OFF,\n engineLiqCursorOff: V1D_ENGINE_LIQ_CURSOR_OFF,\n engineGcCursorOff: V1D_ENGINE_GC_CURSOR_OFF,\n engineLastSweepStartOff: V1D_ENGINE_LAST_SWEEP_START_OFF,\n engineLastSweepCompleteOff: V1D_ENGINE_LAST_SWEEP_COMPLETE_OFF,\n engineCrankCursorOff: V1D_ENGINE_CRANK_CURSOR_OFF,\n engineSweepStartIdxOff: V1D_ENGINE_SWEEP_START_IDX_OFF,\n engineLifetimeLiquidationsOff: V1D_ENGINE_LIFETIME_LIQUIDATIONS_OFF,\n engineLifetimeForceClosesOff: V1D_ENGINE_LIFETIME_FORCE_CLOSES_OFF,\n engineNetLpPosOff: V1D_ENGINE_NET_LP_POS_OFF,\n engineLpSumAbsOff: V1D_ENGINE_LP_SUM_ABS_OFF,\n engineLpMaxAbsOff: -1, // not present in deployed V1\n engineLpMaxAbsSweepOff: -1, // not present in deployed V1\n engineEmergencyOiModeOff: -1, // not present in deployed V1\n engineEmergencyStartSlotOff: -1, // not present in deployed V1\n engineLastBreakerSlotOff: -1, // not present in deployed V1\n engineBitmapOff: V1D_ENGINE_BITMAP_OFF,\n postBitmap,\n acctOwnerOff: ACCT_OWNER_OFF,\n\n hasInsuranceIsolation: true,\n engineInsuranceIsolatedOff: 48, // same within InsuranceFund\n engineInsuranceIsolationBpsOff: 64, // same within InsuranceFund\n };\n}\n\n/**\n * Build a SlabLayout for V2 (BPF intermediate layout).\n * ENGINE_OFF=600, BITMAP_OFF=432, ACCOUNT_SIZE=248, postBitmap=18.\n * V2 lacks mark_price, long_oi, short_oi, emergency OI fields.\n */\nfunction buildLayoutV2(maxAccounts: number): SlabLayout {\n const engineOff = V2_ENGINE_OFF;\n const bitmapOff = V2_ENGINE_BITMAP_OFF;\n const accountSize = V2_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version: 2,\n headerLen: V2_HEADER_LEN,\n configOffset: V2_HEADER_LEN,\n configLen: V2_CONFIG_LEN,\n reservedOff: V1_RESERVED_OFF, // V2 shares V1's header layout (reserved at 80)\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: V1_ENGINE_PARAMS_OFF, // same as V1: 72\n paramsSize: V1_PARAMS_SIZE, // same as V1: 288\n engineCurrentSlotOff: V2_ENGINE_CURRENT_SLOT_OFF,\n engineFundingIndexOff: V2_ENGINE_FUNDING_INDEX_OFF,\n engineLastFundingSlotOff: V2_ENGINE_LAST_FUNDING_SLOT_OFF,\n engineFundingRateBpsOff: V2_ENGINE_FUNDING_RATE_BPS_OFF,\n engineMarkPriceOff: -1, // V2 has no mark_price\n engineLastCrankSlotOff: V2_ENGINE_LAST_CRANK_SLOT_OFF,\n engineMaxCrankStalenessOff: V2_ENGINE_MAX_CRANK_STALENESS_OFF,\n engineTotalOiOff: V2_ENGINE_TOTAL_OI_OFF,\n engineLongOiOff: -1, // V2 has no long_oi\n engineShortOiOff: -1, // V2 has no short_oi\n engineCTotOff: V2_ENGINE_C_TOT_OFF,\n enginePnlPosTotOff: V2_ENGINE_PNL_POS_TOT_OFF,\n engineLiqCursorOff: V2_ENGINE_LIQ_CURSOR_OFF,\n engineGcCursorOff: V2_ENGINE_GC_CURSOR_OFF,\n engineLastSweepStartOff: V2_ENGINE_LAST_SWEEP_START_OFF,\n engineLastSweepCompleteOff: V2_ENGINE_LAST_SWEEP_COMPLETE_OFF,\n engineCrankCursorOff: V2_ENGINE_CRANK_CURSOR_OFF,\n engineSweepStartIdxOff: V2_ENGINE_SWEEP_START_IDX_OFF,\n engineLifetimeLiquidationsOff: V2_ENGINE_LIFETIME_LIQUIDATIONS_OFF,\n engineLifetimeForceClosesOff: V2_ENGINE_LIFETIME_FORCE_CLOSES_OFF,\n engineNetLpPosOff: V2_ENGINE_NET_LP_POS_OFF,\n engineLpSumAbsOff: V2_ENGINE_LP_SUM_ABS_OFF,\n engineLpMaxAbsOff: V2_ENGINE_LP_MAX_ABS_OFF,\n engineLpMaxAbsSweepOff: V2_ENGINE_LP_MAX_ABS_SWEEP_OFF,\n engineEmergencyOiModeOff: -1, // V2 has no emergency OI fields\n engineEmergencyStartSlotOff: -1,\n engineLastBreakerSlotOff: -1,\n engineBitmapOff: V2_ENGINE_BITMAP_OFF,\n postBitmap: 18,\n acctOwnerOff: ACCT_OWNER_OFF,\n\n hasInsuranceIsolation: true,\n engineInsuranceIsolatedOff: 48,\n engineInsuranceIsolationBpsOff: 64,\n };\n}\n\n/**\n * Build a SlabLayout for the V1M mainnet program (ESa89R5).\n * ENGINE_OFF=640 (same as V1_LEGACY), but expanded RiskParams (336 bytes)\n * and trade_twap runtime fields push the bitmap to offset 726.\n * Confirmed by on-chain probing of slab 8NY7rvQ (257512 bytes, medium tier).\n */\nfunction buildLayoutV1M(maxAccounts: number): SlabLayout {\n const engineOff = V1M_ENGINE_OFF;\n const bitmapOff = V1M_ENGINE_BITMAP_OFF;\n const accountSize = V1M_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version: 1,\n headerLen: V1_HEADER_LEN,\n configOffset: V1_HEADER_LEN,\n configLen: V1M_CONFIG_LEN,\n reservedOff: V1_RESERVED_OFF,\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: V1M_ENGINE_PARAMS_OFF,\n paramsSize: V1M_PARAMS_SIZE,\n engineCurrentSlotOff: V1M_ENGINE_CURRENT_SLOT_OFF,\n engineFundingIndexOff: V1M_ENGINE_FUNDING_INDEX_OFF,\n engineLastFundingSlotOff: V1M_ENGINE_LAST_FUNDING_SLOT_OFF,\n engineFundingRateBpsOff: V1M_ENGINE_FUNDING_RATE_BPS_OFF,\n engineMarkPriceOff: V1M_ENGINE_MARK_PRICE_OFF,\n engineLastCrankSlotOff: V1M_ENGINE_LAST_CRANK_SLOT_OFF,\n engineMaxCrankStalenessOff: V1M_ENGINE_MAX_CRANK_STALENESS_OFF,\n engineTotalOiOff: V1M_ENGINE_TOTAL_OI_OFF,\n engineLongOiOff: V1M_ENGINE_LONG_OI_OFF,\n engineShortOiOff: V1M_ENGINE_SHORT_OI_OFF,\n engineCTotOff: V1M_ENGINE_C_TOT_OFF,\n enginePnlPosTotOff: V1M_ENGINE_PNL_POS_TOT_OFF,\n engineLiqCursorOff: V1M_ENGINE_LIQ_CURSOR_OFF,\n engineGcCursorOff: V1M_ENGINE_GC_CURSOR_OFF,\n engineLastSweepStartOff: V1M_ENGINE_LAST_SWEEP_START_OFF,\n engineLastSweepCompleteOff: V1M_ENGINE_LAST_SWEEP_COMPLETE_OFF,\n engineCrankCursorOff: V1M_ENGINE_CRANK_CURSOR_OFF,\n engineSweepStartIdxOff: V1M_ENGINE_SWEEP_START_IDX_OFF,\n engineLifetimeLiquidationsOff: V1M_ENGINE_LIFETIME_LIQUIDATIONS_OFF,\n engineLifetimeForceClosesOff: V1M_ENGINE_LIFETIME_FORCE_CLOSES_OFF,\n engineNetLpPosOff: V1M_ENGINE_NET_LP_POS_OFF,\n engineLpSumAbsOff: V1M_ENGINE_LP_SUM_ABS_OFF,\n engineLpMaxAbsOff: V1M_ENGINE_LP_MAX_ABS_OFF,\n engineLpMaxAbsSweepOff: V1M_ENGINE_LP_MAX_ABS_SWEEP_OFF,\n engineEmergencyOiModeOff: V1M_ENGINE_EMERGENCY_OI_MODE_OFF,\n engineEmergencyStartSlotOff: V1M_ENGINE_EMERGENCY_START_SLOT_OFF,\n engineLastBreakerSlotOff: V1M_ENGINE_LAST_BREAKER_SLOT_OFF,\n engineBitmapOff: V1M_ENGINE_BITMAP_OFF,\n postBitmap: 18,\n acctOwnerOff: ACCT_OWNER_OFF,\n\n hasInsuranceIsolation: true,\n engineInsuranceIsolatedOff: 48,\n engineInsuranceIsolationBpsOff: 64,\n };\n}\n\n/**\n * Build a SlabLayout for V1M2 — mainnet program rebuilt from main@4861c56 with 312-byte accounts.\n * ENGINE_OFF=616 (align_up(104+512,8)=616), CONFIG_LEN=512.\n * The engine struct is layout-identical to V_ADL (same relative field offsets from engineOff),\n * so all runtime field offsets reuse V_ADL constants. bitmapOff=1008 (same as V_ADL).\n * This differs from V_ADL only in engineOff (616 vs 624) and configLen (512 vs 520).\n * Confirmed by empirical probing of mainnet slab CCTegYZ... (323312 bytes, 1024-account medium tier).\n */\nfunction buildLayoutV1M2(maxAccounts: number): SlabLayout {\n const engineOff = V1M2_ENGINE_OFF;\n const bitmapOff = V1M2_ENGINE_BITMAP_OFF;\n const accountSize = V1M2_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version: 1,\n headerLen: V1_HEADER_LEN,\n configOffset: V1_HEADER_LEN,\n configLen: V1M2_CONFIG_LEN,\n reservedOff: V1_RESERVED_OFF,\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: V1M2_ENGINE_PARAMS_OFF, // 96 — expanded InsuranceFund (same as V_ADL)\n paramsSize: V_ADL_PARAMS_SIZE, // 336 — same as V_ADL\n // Runtime fields: V1M2 engine struct is layout-identical to V_ADL — reuse V_ADL constants.\n engineCurrentSlotOff: V_ADL_ENGINE_CURRENT_SLOT_OFF, // 432\n engineFundingIndexOff: V_ADL_ENGINE_FUNDING_INDEX_OFF, // 440\n engineLastFundingSlotOff: V_ADL_ENGINE_LAST_FUNDING_SLOT_OFF, // 456\n engineFundingRateBpsOff: V_ADL_ENGINE_FUNDING_RATE_BPS_OFF, // 464\n engineMarkPriceOff: V_ADL_ENGINE_MARK_PRICE_OFF, // 504\n engineLastCrankSlotOff: V_ADL_ENGINE_LAST_CRANK_SLOT_OFF, // 528\n engineMaxCrankStalenessOff: V_ADL_ENGINE_MAX_CRANK_STALENESS_OFF, // 536\n engineTotalOiOff: V_ADL_ENGINE_TOTAL_OI_OFF, // 544\n engineLongOiOff: V_ADL_ENGINE_LONG_OI_OFF, // 560\n engineShortOiOff: V_ADL_ENGINE_SHORT_OI_OFF, // 576\n engineCTotOff: V_ADL_ENGINE_C_TOT_OFF, // 592\n enginePnlPosTotOff: V_ADL_ENGINE_PNL_POS_TOT_OFF, // 608\n engineLiqCursorOff: V_ADL_ENGINE_LIQ_CURSOR_OFF, // 640\n engineGcCursorOff: V_ADL_ENGINE_GC_CURSOR_OFF, // 642\n engineLastSweepStartOff: V_ADL_ENGINE_LAST_SWEEP_START_OFF, // 648\n engineLastSweepCompleteOff: V_ADL_ENGINE_LAST_SWEEP_COMPLETE_OFF, // 656\n engineCrankCursorOff: V_ADL_ENGINE_CRANK_CURSOR_OFF, // 664\n engineSweepStartIdxOff: V_ADL_ENGINE_SWEEP_START_IDX_OFF, // 666\n engineLifetimeLiquidationsOff: V_ADL_ENGINE_LIFETIME_LIQUIDATIONS_OFF, // 672\n engineLifetimeForceClosesOff: V_ADL_ENGINE_LIFETIME_FORCE_CLOSES_OFF, // 680\n engineNetLpPosOff: V_ADL_ENGINE_NET_LP_POS_OFF, // 904\n engineLpSumAbsOff: V_ADL_ENGINE_LP_SUM_ABS_OFF, // 920\n engineLpMaxAbsOff: V_ADL_ENGINE_LP_MAX_ABS_OFF, // 936\n engineLpMaxAbsSweepOff: V_ADL_ENGINE_LP_MAX_ABS_SWEEP_OFF, // 952\n engineEmergencyOiModeOff: V_ADL_ENGINE_EMERGENCY_OI_MODE_OFF, // 968\n engineEmergencyStartSlotOff: V_ADL_ENGINE_EMERGENCY_START_SLOT_OFF, // 976\n engineLastBreakerSlotOff: V_ADL_ENGINE_LAST_BREAKER_SLOT_OFF, // 984\n engineBitmapOff: V1M2_ENGINE_BITMAP_OFF,\n postBitmap: 18,\n acctOwnerOff: V_ADL_ACCT_OWNER_OFF, // 192 — same shift as V_ADL (reserved_pnl u64→u128)\n\n hasInsuranceIsolation: true,\n engineInsuranceIsolatedOff: 48,\n engineInsuranceIsolationBpsOff: 64,\n };\n}\n\n/**\n * Build a SlabLayout for the ADL-upgraded program (PERC-8270/8271).\n * ENGINE_OFF=624, BITMAP_OFF=1008, ACCOUNT_SIZE=312.\n *\n * Verified slab sizes (BPF, cargo build-sbf, bitmapOff corrected to 1008):\n * large (4096 accounts): 1288320 bytes\n * medium (1024 accounts): 323320 bytes\n * small (256 accounts): 82064 bytes\n */\nfunction buildLayoutVADL(maxAccounts: number): SlabLayout {\n const engineOff = V_ADL_ENGINE_OFF;\n const bitmapOff = V_ADL_ENGINE_BITMAP_OFF;\n const accountSize = V_ADL_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version: 1,\n headerLen: V1_HEADER_LEN, // 104 (unchanged)\n configOffset: V1_HEADER_LEN,\n configLen: V_ADL_CONFIG_LEN, // 520\n reservedOff: V1_RESERVED_OFF, // 80\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: V_ADL_ENGINE_PARAMS_OFF, // 96 (vault=16 + InsuranceFund=80)\n paramsSize: V_ADL_PARAMS_SIZE, // 336\n engineCurrentSlotOff: V_ADL_ENGINE_CURRENT_SLOT_OFF, // 432\n engineFundingIndexOff: V_ADL_ENGINE_FUNDING_INDEX_OFF, // 440\n engineLastFundingSlotOff: V_ADL_ENGINE_LAST_FUNDING_SLOT_OFF, // 456\n engineFundingRateBpsOff: V_ADL_ENGINE_FUNDING_RATE_BPS_OFF, // 464\n engineMarkPriceOff: V_ADL_ENGINE_MARK_PRICE_OFF, // 504\n engineLastCrankSlotOff: V_ADL_ENGINE_LAST_CRANK_SLOT_OFF, // 528\n engineMaxCrankStalenessOff: V_ADL_ENGINE_MAX_CRANK_STALENESS_OFF, // 536\n engineTotalOiOff: V_ADL_ENGINE_TOTAL_OI_OFF, // 544\n engineLongOiOff: V_ADL_ENGINE_LONG_OI_OFF, // 560\n engineShortOiOff: V_ADL_ENGINE_SHORT_OI_OFF, // 576\n engineCTotOff: V_ADL_ENGINE_C_TOT_OFF, // 592\n enginePnlPosTotOff: V_ADL_ENGINE_PNL_POS_TOT_OFF, // 608\n engineLiqCursorOff: V_ADL_ENGINE_LIQ_CURSOR_OFF, // 640\n engineGcCursorOff: V_ADL_ENGINE_GC_CURSOR_OFF, // 642\n engineLastSweepStartOff: V_ADL_ENGINE_LAST_SWEEP_START_OFF, // 648\n engineLastSweepCompleteOff: V_ADL_ENGINE_LAST_SWEEP_COMPLETE_OFF, // 656\n engineCrankCursorOff: V_ADL_ENGINE_CRANK_CURSOR_OFF, // 664\n engineSweepStartIdxOff: V_ADL_ENGINE_SWEEP_START_IDX_OFF, // 666\n engineLifetimeLiquidationsOff: V_ADL_ENGINE_LIFETIME_LIQUIDATIONS_OFF, // 672\n engineLifetimeForceClosesOff: V_ADL_ENGINE_LIFETIME_FORCE_CLOSES_OFF, // 680\n engineNetLpPosOff: V_ADL_ENGINE_NET_LP_POS_OFF, // 904\n engineLpSumAbsOff: V_ADL_ENGINE_LP_SUM_ABS_OFF, // 920\n engineLpMaxAbsOff: V_ADL_ENGINE_LP_MAX_ABS_OFF, // 936\n engineLpMaxAbsSweepOff: V_ADL_ENGINE_LP_MAX_ABS_SWEEP_OFF, // 952\n engineEmergencyOiModeOff: V_ADL_ENGINE_EMERGENCY_OI_MODE_OFF, // 968\n engineEmergencyStartSlotOff: V_ADL_ENGINE_EMERGENCY_START_SLOT_OFF, // 976\n engineLastBreakerSlotOff: V_ADL_ENGINE_LAST_BREAKER_SLOT_OFF, // 984\n engineBitmapOff: V_ADL_ENGINE_BITMAP_OFF, // 1008\n postBitmap: 18,\n acctOwnerOff: V_ADL_ACCT_OWNER_OFF, // 192\n\n hasInsuranceIsolation: true,\n engineInsuranceIsolatedOff: 48,\n engineInsuranceIsolationBpsOff: 64,\n };\n}\n\n/**\n * V_SETDEXPOOL slab tier sizes — PERC-SetDexPool security fix.\n * ENGINE_OFF=632, BITMAP_OFF=1008, ACCOUNT_SIZE=312, CONFIG_LEN=528.\n * e.g. large (4096 accts) = 1288336 bytes.\n */\nexport const SLAB_TIERS_V_SETDEXPOOL: Record<string, { maxAccounts: number; dataSize: number; label: string; description: string }> = {};\nfor (const [label, n] of [[\"Micro\", 64], [\"Small\", 256], [\"Medium\", 1024], [\"Large\", 4096]] as const) {\n const size = computeSlabSize(V_SETDEXPOOL_ENGINE_OFF, V_ADL_ENGINE_BITMAP_OFF, V_ADL_ACCOUNT_SIZE, n, 18);\n SLAB_TIERS_V_SETDEXPOOL[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (V_SETDEXPOOL PERC-SetDexPool)` };\n}\n\n/**\n * V12_1 slab tier sizes — percolator-core v12.1 merge.\n * ENGINE_OFF=648, BITMAP_OFF=1016, ACCOUNT_SIZE=320.\n * Verified by cargo build-sbf compile-time assertions.\n */\nexport const SLAB_TIERS_V12_1: Record<string, { maxAccounts: number; dataSize: number; label: string; description: string }> = {};\nfor (const [label, n] of [[\"Micro\", 64], [\"Small\", 256], [\"Medium\", 1024], [\"Large\", 4096]] as const) {\n const size = computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, n, 18);\n SLAB_TIERS_V12_1[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (v12.1)` };\n}\n\n/**\n * Build a SlabLayout for V_SETDEXPOOL slabs (PERC-SetDexPool security fix).\n * ENGINE_OFF=632 (+8 from V_ADL=624 due to CONFIG_LEN growing 520→528).\n * All engine and account field offsets are identical to V_ADL.\n */\nfunction buildLayoutVSetDexPool(maxAccounts: number): SlabLayout {\n const engineOff = V_SETDEXPOOL_ENGINE_OFF;\n const bitmapOff = V_ADL_ENGINE_BITMAP_OFF;\n const accountSize = V_ADL_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version: 1,\n headerLen: V1_HEADER_LEN,\n configOffset: V1_HEADER_LEN,\n configLen: V_SETDEXPOOL_CONFIG_LEN, // 544\n reservedOff: V1_RESERVED_OFF,\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: V_ADL_ENGINE_PARAMS_OFF,\n paramsSize: V_ADL_PARAMS_SIZE,\n engineCurrentSlotOff: V_ADL_ENGINE_CURRENT_SLOT_OFF,\n engineFundingIndexOff: V_ADL_ENGINE_FUNDING_INDEX_OFF,\n engineLastFundingSlotOff: V_ADL_ENGINE_LAST_FUNDING_SLOT_OFF,\n engineFundingRateBpsOff: V_ADL_ENGINE_FUNDING_RATE_BPS_OFF,\n engineMarkPriceOff: V_ADL_ENGINE_MARK_PRICE_OFF,\n engineLastCrankSlotOff: V_ADL_ENGINE_LAST_CRANK_SLOT_OFF,\n engineMaxCrankStalenessOff: V_ADL_ENGINE_MAX_CRANK_STALENESS_OFF,\n engineTotalOiOff: V_ADL_ENGINE_TOTAL_OI_OFF,\n engineLongOiOff: V_ADL_ENGINE_LONG_OI_OFF,\n engineShortOiOff: V_ADL_ENGINE_SHORT_OI_OFF,\n engineCTotOff: V_ADL_ENGINE_C_TOT_OFF,\n enginePnlPosTotOff: V_ADL_ENGINE_PNL_POS_TOT_OFF,\n engineLiqCursorOff: V_ADL_ENGINE_LIQ_CURSOR_OFF,\n engineGcCursorOff: V_ADL_ENGINE_GC_CURSOR_OFF,\n engineLastSweepStartOff: V_ADL_ENGINE_LAST_SWEEP_START_OFF,\n engineLastSweepCompleteOff: V_ADL_ENGINE_LAST_SWEEP_COMPLETE_OFF,\n engineCrankCursorOff: V_ADL_ENGINE_CRANK_CURSOR_OFF,\n engineSweepStartIdxOff: V_ADL_ENGINE_SWEEP_START_IDX_OFF,\n engineLifetimeLiquidationsOff: V_ADL_ENGINE_LIFETIME_LIQUIDATIONS_OFF,\n engineLifetimeForceClosesOff: V_ADL_ENGINE_LIFETIME_FORCE_CLOSES_OFF,\n engineNetLpPosOff: V_ADL_ENGINE_NET_LP_POS_OFF,\n engineLpSumAbsOff: V_ADL_ENGINE_LP_SUM_ABS_OFF,\n engineLpMaxAbsOff: V_ADL_ENGINE_LP_MAX_ABS_OFF,\n engineLpMaxAbsSweepOff: V_ADL_ENGINE_LP_MAX_ABS_SWEEP_OFF,\n engineEmergencyOiModeOff: V_ADL_ENGINE_EMERGENCY_OI_MODE_OFF,\n engineEmergencyStartSlotOff: V_ADL_ENGINE_EMERGENCY_START_SLOT_OFF,\n engineLastBreakerSlotOff: V_ADL_ENGINE_LAST_BREAKER_SLOT_OFF,\n engineBitmapOff: V_ADL_ENGINE_BITMAP_OFF,\n postBitmap: 18,\n acctOwnerOff: V_ADL_ACCT_OWNER_OFF,\n\n hasInsuranceIsolation: true,\n engineInsuranceIsolatedOff: 48,\n engineInsuranceIsolationBpsOff: 64,\n };\n}\n\nfunction buildLayoutV12_1(maxAccounts: number): SlabLayout {\n const engineOff = V12_1_ENGINE_OFF;\n const bitmapOff = V12_1_ENGINE_BITMAP_OFF;\n const accountSize = V12_1_ACCOUNT_SIZE;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version: 1,\n headerLen: V1_HEADER_LEN,\n configOffset: V1_HEADER_LEN,\n configLen: V_SETDEXPOOL_CONFIG_LEN, // 544 (same as V_SETDEXPOOL)\n reservedOff: V1_RESERVED_OFF,\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: V12_1_ENGINE_PARAMS_OFF,\n paramsSize: V12_1_PARAMS_SIZE,\n engineCurrentSlotOff: V12_1_ENGINE_CURRENT_SLOT_OFF,\n engineFundingIndexOff: V12_1_ENGINE_FUNDING_INDEX_OFF,\n engineLastFundingSlotOff: V12_1_ENGINE_LAST_FUNDING_SLOT_OFF,\n engineFundingRateBpsOff: V12_1_ENGINE_FUNDING_RATE_BPS_OFF,\n engineMarkPriceOff: V12_1_ENGINE_MARK_PRICE_OFF,\n engineLastCrankSlotOff: V12_1_ENGINE_LAST_CRANK_SLOT_OFF,\n engineMaxCrankStalenessOff: V12_1_ENGINE_MAX_CRANK_STALENESS_OFF,\n engineTotalOiOff: V12_1_ENGINE_TOTAL_OI_OFF,\n engineLongOiOff: V12_1_ENGINE_LONG_OI_OFF,\n engineShortOiOff: V12_1_ENGINE_SHORT_OI_OFF,\n engineCTotOff: V12_1_ENGINE_C_TOT_OFF,\n enginePnlPosTotOff: V12_1_ENGINE_PNL_POS_TOT_OFF,\n engineLiqCursorOff: V12_1_ENGINE_LIQ_CURSOR_OFF,\n engineGcCursorOff: V12_1_ENGINE_GC_CURSOR_OFF,\n engineLastSweepStartOff: V12_1_ENGINE_LAST_SWEEP_START_OFF,\n engineLastSweepCompleteOff: V12_1_ENGINE_LAST_SWEEP_COMPLETE_OFF,\n engineCrankCursorOff: V12_1_ENGINE_CRANK_CURSOR_OFF,\n engineSweepStartIdxOff: V12_1_ENGINE_SWEEP_START_IDX_OFF,\n engineLifetimeLiquidationsOff: V12_1_ENGINE_LIFETIME_LIQUIDATIONS_OFF,\n engineLifetimeForceClosesOff: V12_1_ENGINE_LIFETIME_FORCE_CLOSES_OFF,\n engineNetLpPosOff: V12_1_ENGINE_NET_LP_POS_OFF,\n engineLpSumAbsOff: V12_1_ENGINE_LP_SUM_ABS_OFF,\n engineLpMaxAbsOff: V12_1_ENGINE_LP_MAX_ABS_OFF,\n engineLpMaxAbsSweepOff: V12_1_ENGINE_LP_MAX_ABS_SWEEP_OFF,\n engineEmergencyOiModeOff: V12_1_ENGINE_EMERGENCY_OI_MODE_OFF,\n engineEmergencyStartSlotOff: V12_1_ENGINE_EMERGENCY_START_SLOT_OFF,\n engineLastBreakerSlotOff: V12_1_ENGINE_LAST_BREAKER_SLOT_OFF,\n engineBitmapOff: V12_1_ENGINE_BITMAP_OFF,\n postBitmap: 18,\n acctOwnerOff: V12_1_ACCT_OWNER_OFF,\n\n hasInsuranceIsolation: true,\n engineInsuranceIsolatedOff: 48,\n engineInsuranceIsolationBpsOff: 64,\n };\n}\n\n/**\n * Detect the slab layout version from the raw account data length.\n * Returns the full SlabLayout descriptor, or null if the size is unrecognised.\n * Checks V12_1, V_SETDEXPOOL, V1M2, V_ADL, V1M, V0, V1D, V1D-legacy, V1, and V1-legacy sizes.\n *\n * When `data` is provided and the size matches V1D, the version field at offset 8 is read\n * to disambiguate V2 slabs (which produce identical sizes to V1D with postBitmap=2).\n * V2 slabs have version===2 at offset 8 (u32 LE).\n *\n * @param dataLen - The slab account data length in bytes\n * @param data - Optional raw slab data for version-field disambiguation\n */\nexport function detectSlabLayout(dataLen: number, data?: Uint8Array): SlabLayout | null {\n // Check V12_1 sizes first (percolator-core v12.1, ACCOUNT_SIZE=320, BITMAP_OFF=1016).\n // Largest account size — no size collision with any earlier layout.\n const v121n = V12_1_SIZES.get(dataLen);\n if (v121n !== undefined) return buildLayoutV12_1(v121n);\n\n // Check V_SETDEXPOOL sizes (PERC-SetDexPool, ENGINE_OFF=648, CONFIG_LEN=544).\n // These are the pre-v12.1 newest slabs — largest ENGINE_OFF so no size collision with V_ADL (624).\n const vsdpn = V_SETDEXPOOL_SIZES.get(dataLen);\n if (vsdpn !== undefined) return buildLayoutVSetDexPool(vsdpn);\n\n // Check V1M2 sizes. After fixing bitmapOff to 1008 for both V1M2 and V_ADL,\n // their sizes no longer collide (engineOff differs: 616 vs 624), so size-based detection\n // works directly — no data-probe disambiguation required.\n // V1M2 medium (1024 accts): computeSlabSize(616, 1008, 312, 1024, 18) = 323312\n // V_ADL medium (1024 accts): computeSlabSize(624, 1008, 312, 1024, 18) = 323320\n const v1m2n = V1M2_SIZES.get(dataLen);\n if (v1m2n !== undefined) return buildLayoutV1M2(v1m2n);\n\n // Check V_ADL sizes (PERC-8270/8271, ENGINE_OFF=624, BITMAP_OFF=1008, ACCOUNT_SIZE=312).\n const vadln = V_ADL_SIZES.get(dataLen);\n if (vadln !== undefined) return buildLayoutVADL(vadln);\n\n // Check V1M sizes (mainnet-deployed V1 program, ESa89R5).\n // Must be checked before V1_LEGACY because V1M sizes are unique and don't overlap.\n const v1mn = V1M_SIZES.get(dataLen);\n if (v1mn !== undefined) return buildLayoutV1M(v1mn);\n\n // Check V0 sizes (deployed devnet V0 program)\n const v0n = V0_SIZES.get(dataLen);\n if (v0n !== undefined) return buildLayout(0, v0n);\n\n // Check V1D sizes (actually deployed V1 program — ENGINE_OFF=424, correct struct layout).\n // V2 slabs produce identical sizes (postBitmap=18 for V2 == postBitmap=2 for V1D).\n // When data is available, peek at the version field to disambiguate.\n const v1dn = V1D_SIZES.get(dataLen);\n if (v1dn !== undefined) {\n if (data && data.length >= 12) {\n const version = readU32LE(data, 8);\n if (version === 2) return buildLayoutV2(v1dn);\n }\n return buildLayoutV1D(v1dn, 2);\n }\n\n // Check V1D legacy sizes (postBitmap=18 on-chain slabs created before GH#1234 fix).\n // e.g. slab 6ZytbpV4 (TEST/USD, top active market) = 65104 bytes, uses postBitmap=18.\n // PR #1236 broke these by only registering the postBitmap=2 size; GH#1237 restores support.\n const v1dln = V1D_SIZES_LEGACY.get(dataLen);\n if (v1dln !== undefined) return buildLayoutV1D(v1dln, 18);\n\n // Check V1 sizes (future V1 program — ENGINE_OFF=600, PERC-1094 corrected)\n const v1n = V1_SIZES.get(dataLen);\n if (v1n !== undefined) return buildLayout(1, v1n);\n\n // Check legacy V1 sizes (pre-PERC-1094 SDK used ENGINE_OFF=640; orphaned on devnet)\n const v1ln = V1_SIZES_LEGACY.get(dataLen);\n // PERC-1095 follow-up: must pass V1_ENGINE_OFF_LEGACY (640) so the returned SlabLayout\n // has .engineOff=640 — without the override buildLayout would use V1_ENGINE_OFF=600,\n // causing all engine reads on legacy slabs to land at the wrong byte offset.\n if (v1ln !== undefined) return buildLayout(1, v1ln, V1_ENGINE_OFF_LEGACY);\n\n return null;\n}\n\n/**\n * Legacy detectLayout for backward compat.\n * Returns { bitmapWords, accountsOff, maxAccounts } or null.\n *\n * GH#1238: previously recomputed accountsOff with hardcoded postBitmap=18, which gave a value\n * 16 bytes too large for V1D slabs (which use postBitmap=2). Now delegates directly to the\n * SlabLayout descriptor so each variant uses its own correct accountsOff.\n */\nexport function detectLayout(dataLen: number) {\n const layout = detectSlabLayout(dataLen);\n if (!layout) return null;\n return { bitmapWords: layout.bitmapWords, accountsOff: layout.accountsOff, maxAccounts: layout.maxAccounts };\n}\n\n// =============================================================================\n// RiskParams Layout (field offsets within params, same for V0 and V1 basic fields)\n// =============================================================================\nconst PARAMS_WARMUP_PERIOD_OFF = 0;\nconst PARAMS_MAINTENANCE_MARGIN_OFF = 8;\nconst PARAMS_INITIAL_MARGIN_OFF = 16;\nconst PARAMS_TRADING_FEE_OFF = 24;\nconst PARAMS_MAX_ACCOUNTS_OFF = 32;\nconst PARAMS_NEW_ACCOUNT_FEE_OFF = 40;\n// V1-only extended params (offset 56+)\nconst PARAMS_RISK_THRESHOLD_OFF = 56;\nconst PARAMS_MAINTENANCE_FEE_OFF = 72;\nconst PARAMS_MAX_CRANK_STALENESS_OFF = 88;\nconst PARAMS_LIQUIDATION_FEE_BPS_OFF = 96;\nconst PARAMS_LIQUIDATION_FEE_CAP_OFF = 104;\nconst PARAMS_LIQUIDATION_BUFFER_OFF = 120;\nconst PARAMS_MIN_LIQUIDATION_OFF = 128;\n\n// =============================================================================\n// Account Layout (240/248 bytes)\n// The first 240 bytes are identical in V0 and V1.\n// V1 adds last_partial_liquidation_slot (u64, 8 bytes) at offset 240.\n// =============================================================================\nconst ACCT_ACCOUNT_ID_OFF = 0;\nconst ACCT_CAPITAL_OFF = 8;\nconst ACCT_KIND_OFF = 24;\nconst ACCT_PNL_OFF = 32;\nconst ACCT_RESERVED_PNL_OFF = 48;\nconst ACCT_WARMUP_STARTED_OFF = 56;\nconst ACCT_WARMUP_SLOPE_OFF = 64;\nconst ACCT_POSITION_SIZE_OFF = 80;\nconst ACCT_ENTRY_PRICE_OFF = 96;\nconst ACCT_FUNDING_INDEX_OFF = 104;\nconst ACCT_MATCHER_PROGRAM_OFF = 120;\nconst ACCT_MATCHER_CONTEXT_OFF = 152;\nconst ACCT_OWNER_OFF = 184;\nconst ACCT_FEE_CREDITS_OFF = 216;\nconst ACCT_LAST_FEE_SLOT_OFF = 232;\n\n// =============================================================================\n// Interfaces\n// =============================================================================\n\nexport interface SlabHeader {\n magic: bigint;\n version: number;\n bump: number;\n flags: number;\n resolved: boolean;\n paused: boolean;\n admin: PublicKey;\n nonce: bigint;\n lastThrUpdateSlot: bigint;\n}\n\nexport interface MarketConfig {\n collateralMint: PublicKey;\n vaultPubkey: PublicKey;\n indexFeedId: PublicKey;\n maxStalenessSlots: bigint;\n confFilterBps: number;\n vaultAuthorityBump: number;\n invert: number;\n unitScale: number;\n fundingHorizonSlots: bigint;\n fundingKBps: bigint;\n fundingInvScaleNotionalE6: bigint;\n fundingMaxPremiumBps: bigint;\n fundingMaxBpsPerSlot: bigint;\n fundingPremiumWeightBps: bigint;\n fundingSettlementIntervalSlots: bigint;\n fundingPremiumDampeningE6: bigint;\n fundingPremiumMaxBpsPerSlot: bigint;\n threshFloor: bigint;\n threshRiskBps: bigint;\n threshUpdateIntervalSlots: bigint;\n threshStepBps: bigint;\n threshAlphaBps: bigint;\n threshMin: bigint;\n threshMax: bigint;\n threshMinStep: bigint;\n oracleAuthority: PublicKey;\n authorityPriceE6: bigint;\n authorityTimestamp: bigint;\n oraclePriceCapE2bps: bigint;\n lastEffectivePriceE6: bigint;\n oiCapMultiplierBps: bigint;\n maxPnlCap: bigint;\n adaptiveFundingEnabled: boolean;\n adaptiveScaleBps: number;\n adaptiveMaxFundingBps: bigint;\n marketCreatedSlot: bigint;\n oiRampSlots: bigint;\n resolvedSlot: bigint;\n insuranceIsolationBps: number;\n /** PERC-622: Oracle phase (0=Nascent, 1=Growing, 2=Mature) */\n oraclePhase: number;\n /** PERC-622: Cumulative trade volume in e6 format */\n cumulativeVolumeE6: bigint;\n /** PERC-622: Slots elapsed from market creation to Phase 2 entry (u24) */\n phase2DeltaSlots: number;\n /**\n * PERC-SetDexPool: Admin-pinned DEX pool pubkey for HYPERP markets.\n * Null when reading old slabs (pre-SetDexPool configLen < 528) or when\n * SetDexPool has never been called (all-zero pubkey).\n * Non-null means the program will reject any UpdateHyperpMark that passes\n * a different pool account.\n */\n dexPool: PublicKey | null;\n}\n\nexport interface InsuranceFund {\n balance: bigint;\n feeRevenue: bigint;\n isolatedBalance: bigint;\n isolationBps: number;\n}\n\nexport interface RiskParams {\n warmupPeriodSlots: bigint;\n maintenanceMarginBps: bigint;\n initialMarginBps: bigint;\n tradingFeeBps: bigint;\n maxAccounts: bigint;\n newAccountFee: bigint;\n riskReductionThreshold: bigint;\n maintenanceFeePerSlot: bigint;\n maxCrankStalenessSlots: bigint;\n liquidationFeeBps: bigint;\n liquidationFeeCap: bigint;\n liquidationBufferBps: bigint;\n minLiquidationAbs: bigint;\n}\n\nexport interface EngineState {\n vault: bigint;\n insuranceFund: InsuranceFund;\n currentSlot: bigint;\n fundingIndexQpbE6: bigint;\n lastFundingSlot: bigint;\n fundingRateBpsPerSlotLast: bigint;\n lastCrankSlot: bigint;\n maxCrankStalenessSlots: bigint;\n totalOpenInterest: bigint;\n longOi: bigint;\n shortOi: bigint;\n cTot: bigint;\n pnlPosTot: bigint;\n liqCursor: number;\n gcCursor: number;\n lastSweepStartSlot: bigint;\n lastSweepCompleteSlot: bigint;\n crankCursor: number;\n sweepStartIdx: number;\n lifetimeLiquidations: bigint;\n lifetimeForceCloses: bigint;\n netLpPos: bigint;\n lpSumAbs: bigint;\n lpMaxAbs: bigint;\n lpMaxAbsSweep: bigint;\n emergencyOiMode: boolean;\n emergencyStartSlot: bigint;\n lastBreakerSlot: bigint;\n numUsedAccounts: number;\n nextAccountId: bigint;\n markPriceE6: bigint;\n}\n\nexport enum AccountKind {\n User = 0,\n LP = 1,\n}\n\nexport interface Account {\n kind: AccountKind;\n accountId: bigint;\n capital: bigint;\n pnl: bigint;\n reservedPnl: bigint;\n warmupStartedAtSlot: bigint;\n warmupSlopePerStep: bigint;\n positionSize: bigint;\n entryPrice: bigint;\n fundingIndex: bigint;\n matcherProgram: PublicKey;\n matcherContext: PublicKey;\n owner: PublicKey;\n feeCredits: bigint;\n lastFeeSlot: bigint;\n}\n\n// =============================================================================\n// Fetch\n// =============================================================================\n\nexport async function fetchSlab(\n connection: Connection,\n slabPubkey: PublicKey\n): Promise<Uint8Array> {\n const info = await connection.getAccountInfo(slabPubkey);\n if (!info) {\n throw new Error(`Slab account not found: ${slabPubkey.toBase58()}`);\n }\n return new Uint8Array(info.data);\n}\n\n// =============================================================================\n// PERC-302: Market Maturity OI Ramp\n// =============================================================================\n\nexport const RAMP_START_BPS = 1000n;\nexport const DEFAULT_OI_RAMP_SLOTS = 432_000n;\n\nexport function computeEffectiveOiCapBps(config: MarketConfig, currentSlot: bigint): bigint {\n const target = config.oiCapMultiplierBps;\n if (target === 0n) return 0n;\n if (config.oiRampSlots === 0n) return target;\n if (target <= RAMP_START_BPS) return target;\n const elapsed = currentSlot > config.marketCreatedSlot\n ? currentSlot - config.marketCreatedSlot\n : 0n;\n if (elapsed >= config.oiRampSlots) return target;\n const range = target - RAMP_START_BPS;\n const rampAdd = (range * elapsed) / config.oiRampSlots;\n const result = RAMP_START_BPS + rampAdd;\n return result < target ? result : target;\n}\n\n// =============================================================================\n// Header helpers\n// =============================================================================\n\nexport function readNonce(data: Uint8Array): bigint {\n const layout = detectSlabLayout(data.length, data);\n if (!layout) {\n throw new Error(`readNonce: unrecognized slab data length ${data.length}`);\n }\n const roff = layout.reservedOff;\n if (data.length < roff + 8) throw new Error(\"Slab data too short for nonce\");\n return readU64LE(data, roff);\n}\n\nexport function readLastThrUpdateSlot(data: Uint8Array): bigint {\n const layout = detectSlabLayout(data.length, data);\n if (!layout) {\n throw new Error(`readLastThrUpdateSlot: unrecognized slab data length ${data.length}`);\n }\n const roff = layout.reservedOff;\n if (data.length < roff + 16) throw new Error(\"Slab data too short for lastThrUpdateSlot\");\n return readU64LE(data, roff + 8);\n}\n\n// =============================================================================\n// Parsing Functions\n// =============================================================================\n\n/**\n * Parse slab header (first 72 bytes — layout-independent).\n */\nexport function parseHeader(data: Uint8Array): SlabHeader {\n if (data.length < V0_HEADER_LEN) {\n throw new Error(`Slab data too short for header: ${data.length} < ${V0_HEADER_LEN}`);\n }\n\n const magic = readU64LE(data, 0);\n if (magic !== MAGIC) {\n throw new Error(`Invalid slab magic: expected ${MAGIC.toString(16)}, got ${magic.toString(16)}`);\n }\n\n const version = readU32LE(data, 8);\n const bump = readU8(data, 12);\n const flags = readU8(data, 13);\n const admin = new PublicKey(data.subarray(16, 48));\n\n // Reserved field location depends on layout\n const layout = detectSlabLayout(data.length, data);\n const roff = layout ? layout.reservedOff : V0_RESERVED_OFF;\n const nonce = readU64LE(data, roff);\n const lastThrUpdateSlot = readU64LE(data, roff + 8);\n\n return {\n magic,\n version,\n bump,\n flags,\n resolved: (flags & FLAG_RESOLVED) !== 0,\n paused: (flags & 0x02) !== 0,\n admin,\n nonce,\n lastThrUpdateSlot,\n };\n}\n\n/**\n * Parse market config. Layout-version aware.\n * For V0 slabs, fields beyond the basic config are read if present in the data,\n * otherwise defaults are returned.\n *\n * @param data - Slab data (may be a partial slice for discovery; pass layoutHint in that case)\n * @param layoutHint - Pre-detected layout to use; if omitted, detected from data.length.\n */\nexport function parseConfig(data: Uint8Array, layoutHint?: SlabLayout | null): MarketConfig {\n const layout = layoutHint !== undefined ? layoutHint : detectSlabLayout(data.length, data);\n const configOff = layout ? layout.configOffset : V0_HEADER_LEN;\n const configLen = layout ? layout.configLen : V0_CONFIG_LEN;\n\n const minLen = configOff + Math.min(configLen, 120); // need at least basic fields\n if (data.length < minLen) {\n throw new Error(`Slab data too short for config: ${data.length} < ${minLen}`);\n }\n\n let off = configOff;\n\n const collateralMint = new PublicKey(data.subarray(off, off + 32));\n off += 32;\n\n const vaultPubkey = new PublicKey(data.subarray(off, off + 32));\n off += 32;\n\n const indexFeedId = new PublicKey(data.subarray(off, off + 32));\n off += 32;\n\n const maxStalenessSlots = readU64LE(data, off);\n off += 8;\n\n const confFilterBps = readU16LE(data, off);\n off += 2;\n\n const vaultAuthorityBump = readU8(data, off);\n off += 1;\n\n const invert = readU8(data, off);\n off += 1;\n\n const unitScale = readU32LE(data, off);\n off += 4;\n\n // Funding rate parameters\n const fundingHorizonSlots = readU64LE(data, off);\n off += 8;\n\n const fundingKBps = readU64LE(data, off);\n off += 8;\n\n const fundingInvScaleNotionalE6 = readU128LE(data, off);\n off += 16;\n\n const fundingMaxPremiumBps = readI64LE(data, off);\n off += 8;\n\n const fundingMaxBpsPerSlot = readI64LE(data, off);\n off += 8;\n\n // Extended funding fields\n const fundingPremiumWeightBps = readU64LE(data, off);\n off += 8;\n\n const fundingSettlementIntervalSlots = readU64LE(data, off);\n off += 8;\n\n const fundingPremiumDampeningE6 = readU64LE(data, off);\n off += 8;\n\n const fundingPremiumMaxBpsPerSlot = readU64LE(data, off);\n off += 8;\n\n // Threshold parameters\n const threshFloor = readU128LE(data, off);\n off += 16;\n\n const threshRiskBps = readU64LE(data, off);\n off += 8;\n\n const threshUpdateIntervalSlots = readU64LE(data, off);\n off += 8;\n\n const threshStepBps = readU64LE(data, off);\n off += 8;\n\n const threshAlphaBps = readU64LE(data, off);\n off += 8;\n\n const threshMin = readU128LE(data, off);\n off += 16;\n\n const threshMax = readU128LE(data, off);\n off += 16;\n\n const threshMinStep = readU128LE(data, off);\n off += 16;\n\n // Oracle authority fields\n const oracleAuthority = new PublicKey(data.subarray(off, off + 32));\n off += 32;\n\n const authorityPriceE6 = readU64LE(data, off);\n off += 8;\n\n const authorityTimestamp = readI64LE(data, off);\n off += 8;\n\n // Oracle price circuit breaker\n const oraclePriceCapE2bps = readU64LE(data, off);\n off += 8;\n\n const lastEffectivePriceE6 = readU64LE(data, off);\n off += 8;\n\n // OI cap\n const oiCapMultiplierBps = readU64LE(data, off);\n off += 8;\n\n const maxPnlCap = readU64LE(data, off);\n off += 8;\n\n // Check if we have enough data for V1-only fields\n const remaining = configOff + configLen - off;\n\n let adaptiveFundingEnabled = false;\n let adaptiveScaleBps = 0;\n let adaptiveMaxFundingBps = 0n;\n let marketCreatedSlot = 0n;\n let oiRampSlots = 0n;\n let resolvedSlot = 0n;\n let insuranceIsolationBps = 0;\n let oraclePhase = 0;\n let cumulativeVolumeE6 = 0n;\n let phase2DeltaSlots = 0;\n\n if (remaining >= 40) {\n // V1 extended fields — on-chain order (percolator.rs:3617-3639):\n // market_created_slot(u64), oi_ramp_slots(u64),\n // adaptive_funding_enabled(u8), _pad(u8), adaptive_scale_bps(u16),\n // _pad2(u32), adaptive_max_funding_bps(u64),\n // insurance_isolation_bps(u16), _insurance_isolation_padding([u8;14])\n marketCreatedSlot = readU64LE(data, off);\n off += 8;\n\n oiRampSlots = readU64LE(data, off);\n off += 8;\n\n adaptiveFundingEnabled = readU8(data, off) !== 0;\n off += 1;\n off += 1; // _adaptive_pad\n adaptiveScaleBps = readU16LE(data, off);\n off += 2;\n off += 4; // _adaptive_pad2\n adaptiveMaxFundingBps = readU64LE(data, off);\n off += 8;\n\n if (remaining >= 42) {\n insuranceIsolationBps = readU16LE(data, off);\n // PERC-622: Read oracle phase fields from _insurance_isolation_padding\n // padding starts at off + 2 (after u16 insuranceIsolationBps)\n // [0..2] = mark_oracle_weight (PERC-118), [2] = oracle_phase, [3..11] = cumulative_volume, [11..14] = phase2_delta\n if (remaining >= 56) { // 42 + 14 bytes padding\n const padOff = off + 2;\n oraclePhase = Math.min(readU8(data, padOff + 2), 2);\n cumulativeVolumeE6 = readU64LE(data, padOff + 3);\n // phase2_delta_slots is u24 LE (3 bytes)\n phase2DeltaSlots = data[padOff + 11] | (data[padOff + 12] << 8) | (data[padOff + 13] << 16);\n }\n }\n }\n\n // PERC-SetDexPool: read dex_pool at BPF offset 496 within config.\n // Only present in V_SETDEXPOOL slabs (configLen >= 528).\n // All-zero pubkey means SetDexPool was never called.\n let dexPool: PublicKey | null = null;\n const DEX_POOL_REL_OFF = 512; // SBF offset of dex_pool within MarketConfig (CONFIG_LEN=544, dex_pool at end = 544-32=512)\n if (configLen >= DEX_POOL_REL_OFF + 32 && data.length >= configOff + DEX_POOL_REL_OFF + 32) {\n const dexPoolBytes = data.subarray(configOff + DEX_POOL_REL_OFF, configOff + DEX_POOL_REL_OFF + 32);\n // Return null if all-zero (SetDexPool never called)\n if (dexPoolBytes.some(b => b !== 0)) {\n dexPool = new PublicKey(dexPoolBytes);\n }\n }\n\n return {\n collateralMint,\n vaultPubkey,\n indexFeedId,\n maxStalenessSlots,\n confFilterBps,\n vaultAuthorityBump,\n invert,\n unitScale,\n fundingHorizonSlots,\n fundingKBps,\n fundingInvScaleNotionalE6,\n fundingMaxPremiumBps,\n fundingMaxBpsPerSlot,\n fundingPremiumWeightBps,\n fundingSettlementIntervalSlots,\n fundingPremiumDampeningE6,\n fundingPremiumMaxBpsPerSlot,\n threshFloor,\n threshRiskBps,\n threshUpdateIntervalSlots,\n threshStepBps,\n threshAlphaBps,\n threshMin,\n threshMax,\n threshMinStep,\n oracleAuthority,\n authorityPriceE6,\n authorityTimestamp,\n oraclePriceCapE2bps,\n lastEffectivePriceE6,\n oiCapMultiplierBps,\n maxPnlCap,\n adaptiveFundingEnabled,\n adaptiveScaleBps,\n adaptiveMaxFundingBps,\n marketCreatedSlot,\n oiRampSlots,\n resolvedSlot,\n insuranceIsolationBps,\n oraclePhase,\n cumulativeVolumeE6,\n phase2DeltaSlots,\n dexPool,\n };\n}\n\n/**\n * Parse RiskParams from engine data. Layout-version aware.\n * For V0 slabs, extended params (risk_threshold, maintenance_fee, etc.) are\n * not present on-chain, so defaults (0) are returned.\n *\n * @param data - Slab data (may be a partial slice; pass layoutHint in that case)\n * @param layoutHint - Pre-detected layout to use; if omitted, detected from data.length.\n */\nexport function parseParams(data: Uint8Array, layoutHint?: SlabLayout | null): RiskParams {\n const layout = layoutHint !== undefined ? layoutHint : detectSlabLayout(data.length, data);\n const engineOff = layout ? layout.engineOff : V0_ENGINE_OFF;\n const paramsOff = layout ? layout.engineParamsOff : V0_ENGINE_PARAMS_OFF;\n const paramsSize = layout ? layout.paramsSize : V0_PARAMS_SIZE;\n const base = engineOff + paramsOff;\n\n if (data.length < base + Math.min(paramsSize, 56)) {\n throw new Error(\"Slab data too short for RiskParams\");\n }\n\n // Basic params present in both V0 and V1\n const result: RiskParams = {\n warmupPeriodSlots: readU64LE(data, base + PARAMS_WARMUP_PERIOD_OFF),\n maintenanceMarginBps: readU64LE(data, base + PARAMS_MAINTENANCE_MARGIN_OFF),\n initialMarginBps: readU64LE(data, base + PARAMS_INITIAL_MARGIN_OFF),\n tradingFeeBps: readU64LE(data, base + PARAMS_TRADING_FEE_OFF),\n maxAccounts: readU64LE(data, base + PARAMS_MAX_ACCOUNTS_OFF),\n newAccountFee: readU128LE(data, base + PARAMS_NEW_ACCOUNT_FEE_OFF),\n // Extended params: only read if V1 (paramsSize >= 144)\n riskReductionThreshold: 0n,\n maintenanceFeePerSlot: 0n,\n maxCrankStalenessSlots: 0n,\n liquidationFeeBps: 0n,\n liquidationFeeCap: 0n,\n liquidationBufferBps: 0n,\n minLiquidationAbs: 0n,\n };\n\n if (paramsSize >= 144) {\n result.riskReductionThreshold = readU128LE(data, base + PARAMS_RISK_THRESHOLD_OFF);\n result.maintenanceFeePerSlot = readU128LE(data, base + PARAMS_MAINTENANCE_FEE_OFF);\n result.maxCrankStalenessSlots = readU64LE(data, base + PARAMS_MAX_CRANK_STALENESS_OFF);\n result.liquidationFeeBps = readU64LE(data, base + PARAMS_LIQUIDATION_FEE_BPS_OFF);\n result.liquidationFeeCap = readU128LE(data, base + PARAMS_LIQUIDATION_FEE_CAP_OFF);\n result.liquidationBufferBps = readU64LE(data, base + PARAMS_LIQUIDATION_BUFFER_OFF);\n result.minLiquidationAbs = readU128LE(data, base + PARAMS_MIN_LIQUIDATION_OFF);\n }\n\n return result;\n}\n\n/**\n * Parse RiskEngine state (excluding accounts array). Layout-version aware.\n */\nexport function parseEngine(data: Uint8Array): EngineState {\n const layout = detectSlabLayout(data.length, data);\n if (!layout) {\n throw new Error(`Unrecognized slab data length: ${data.length}. Cannot determine layout version.`);\n }\n\n const base = layout.engineOff;\n\n return {\n vault: readU128LE(data, base),\n insuranceFund: {\n balance: readU128LE(data, base + layout.engineInsuranceOff),\n feeRevenue: readU128LE(data, base + layout.engineInsuranceOff + 16),\n isolatedBalance: layout.hasInsuranceIsolation\n ? readU128LE(data, base + layout.engineInsuranceIsolatedOff)\n : 0n,\n isolationBps: layout.hasInsuranceIsolation\n ? readU16LE(data, base + layout.engineInsuranceIsolationBpsOff)\n : 0,\n },\n currentSlot: readU64LE(data, base + layout.engineCurrentSlotOff),\n fundingIndexQpbE6: readI128LE(data, base + layout.engineFundingIndexOff),\n lastFundingSlot: readU64LE(data, base + layout.engineLastFundingSlotOff),\n fundingRateBpsPerSlotLast: readI64LE(data, base + layout.engineFundingRateBpsOff),\n lastCrankSlot: readU64LE(data, base + layout.engineLastCrankSlotOff),\n maxCrankStalenessSlots: readU64LE(data, base + layout.engineMaxCrankStalenessOff),\n totalOpenInterest: readU128LE(data, base + layout.engineTotalOiOff),\n longOi: layout.engineLongOiOff >= 0\n ? readU128LE(data, base + layout.engineLongOiOff)\n : 0n,\n shortOi: layout.engineShortOiOff >= 0\n ? readU128LE(data, base + layout.engineShortOiOff)\n : 0n,\n cTot: readU128LE(data, base + layout.engineCTotOff),\n pnlPosTot: readU128LE(data, base + layout.enginePnlPosTotOff),\n liqCursor: readU16LE(data, base + layout.engineLiqCursorOff),\n gcCursor: readU16LE(data, base + layout.engineGcCursorOff),\n lastSweepStartSlot: readU64LE(data, base + layout.engineLastSweepStartOff),\n lastSweepCompleteSlot: readU64LE(data, base + layout.engineLastSweepCompleteOff),\n crankCursor: readU16LE(data, base + layout.engineCrankCursorOff),\n sweepStartIdx: readU16LE(data, base + layout.engineSweepStartIdxOff),\n lifetimeLiquidations: readU64LE(data, base + layout.engineLifetimeLiquidationsOff),\n lifetimeForceCloses: readU64LE(data, base + layout.engineLifetimeForceClosesOff),\n netLpPos: readI128LE(data, base + layout.engineNetLpPosOff),\n lpSumAbs: readU128LE(data, base + layout.engineLpSumAbsOff),\n lpMaxAbs: layout.engineLpMaxAbsOff >= 0 ? readU128LE(data, base + layout.engineLpMaxAbsOff) : 0n,\n lpMaxAbsSweep: layout.engineLpMaxAbsSweepOff >= 0 ? readU128LE(data, base + layout.engineLpMaxAbsSweepOff) : 0n,\n emergencyOiMode: layout.engineEmergencyOiModeOff >= 0\n ? data[base + layout.engineEmergencyOiModeOff] !== 0\n : false,\n emergencyStartSlot: layout.engineEmergencyStartSlotOff >= 0\n ? readU64LE(data, base + layout.engineEmergencyStartSlotOff)\n : 0n,\n lastBreakerSlot: layout.engineLastBreakerSlotOff >= 0\n ? readU64LE(data, base + layout.engineLastBreakerSlotOff)\n : 0n,\n markPriceE6: layout.engineMarkPriceOff >= 0\n ? readU64LE(data, base + layout.engineMarkPriceOff)\n : 0n,\n numUsedAccounts: (() => {\n if (layout.postBitmap < 18) return 0;\n const bw = layout.bitmapWords;\n return readU16LE(data, base + layout.engineBitmapOff + bw * 8);\n })(),\n nextAccountId: (() => {\n if (layout.postBitmap < 18) return 0n;\n const bw = layout.bitmapWords;\n const numUsedOff = layout.engineBitmapOff + bw * 8;\n return readU64LE(data, base + Math.ceil((numUsedOff + 2) / 8) * 8);\n })(),\n };\n}\n\n/**\n * Read bitmap to get list of used account indices.\n */\n/**\n * Return all account indices whose bitmap bit is set (i.e. slot is in use).\n * Uses the layout-aware bitmap offset so V1_LEGACY slabs (bitmap at rel+672) are handled correctly.\n */\nexport function parseUsedIndices(data: Uint8Array): number[] {\n const layout = detectSlabLayout(data.length, data);\n if (!layout) throw new Error(`Unrecognized slab data length: ${data.length}`);\n\n const base = layout.engineOff + layout.engineBitmapOff;\n if (data.length < base + layout.bitmapWords * 8) {\n throw new Error(\"Slab data too short for bitmap\");\n }\n\n const used: number[] = [];\n for (let word = 0; word < layout.bitmapWords; word++) {\n const bits = readU64LE(data, base + word * 8);\n if (bits === 0n) continue;\n for (let bit = 0; bit < 64; bit++) {\n if ((bits >> BigInt(bit)) & 1n) {\n used.push(word * 64 + bit);\n }\n }\n }\n return used;\n}\n\n/**\n * Check if a specific account index is used.\n */\nexport function isAccountUsed(data: Uint8Array, idx: number): boolean {\n const layout = detectSlabLayout(data.length, data);\n if (!layout) return false;\n if (!Number.isInteger(idx) || idx < 0 || idx >= layout.maxAccounts) return false;\n const base = layout.engineOff + layout.engineBitmapOff;\n const word = Math.floor(idx / 64);\n const bit = idx % 64;\n const bits = readU64LE(data, base + word * 8);\n return ((bits >> BigInt(bit)) & 1n) !== 0n;\n}\n\n/**\n * Calculate the maximum valid account index for a given slab size.\n */\nexport function maxAccountIndex(dataLen: number): number {\n const layout = detectSlabLayout(dataLen);\n if (!layout) return 0;\n const accountsEnd = dataLen - layout.accountsOff;\n if (accountsEnd <= 0) return 0;\n return Math.floor(accountsEnd / layout.accountSize);\n}\n\n/**\n * Parse a single account by index.\n */\nexport function parseAccount(data: Uint8Array, idx: number): Account {\n const layout = detectSlabLayout(data.length, data);\n if (!layout) throw new Error(`Unrecognized slab data length: ${data.length}`);\n\n const maxIdx = maxAccountIndex(data.length);\n if (!Number.isInteger(idx) || idx < 0 || idx >= maxIdx) {\n throw new Error(`Account index out of range: ${idx} (max: ${maxIdx - 1})`);\n }\n\n const base = layout.accountsOff + idx * layout.accountSize;\n if (data.length < base + layout.accountSize) {\n throw new Error(\"Slab data too short for account\");\n }\n\n // Select layout-dependent account field offsets.\n // V12_1 (account_size=320): new fields (position_basis_q, adl_a_basis, adl_k_snap, adl_epoch_snap)\n // shift matcher/owner/fee offsets +16 from V_ADL, and move legacy fields to end.\n // V_ADL (account_size=312): reserved_pnl grew u64→u128 (PERC-8267), shifting from pre-ADL offsets.\n // Pre-ADL (account_size<312): original offsets.\n const isV12_1 = layout.accountSize >= 320;\n const isAdl = layout.accountSize >= 312;\n const warmupStartedOff = isAdl ? V_ADL_ACCT_WARMUP_STARTED_OFF : ACCT_WARMUP_STARTED_OFF;\n const warmupSlopeOff = isAdl ? V_ADL_ACCT_WARMUP_SLOPE_OFF : ACCT_WARMUP_SLOPE_OFF;\n const positionSizeOff = isV12_1 ? V12_1_ACCT_POSITION_SIZE_OFF : (isAdl ? V_ADL_ACCT_POSITION_SIZE_OFF : ACCT_POSITION_SIZE_OFF);\n const entryPriceOff = isV12_1 ? V12_1_ACCT_ENTRY_PRICE_OFF : (isAdl ? V_ADL_ACCT_ENTRY_PRICE_OFF : ACCT_ENTRY_PRICE_OFF);\n const fundingIndexOff = isV12_1 ? V12_1_ACCT_FUNDING_INDEX_OFF : (isAdl ? V_ADL_ACCT_FUNDING_INDEX_OFF : ACCT_FUNDING_INDEX_OFF);\n const matcherProgOff = isV12_1 ? V12_1_ACCT_MATCHER_PROGRAM_OFF : (isAdl ? V_ADL_ACCT_MATCHER_PROGRAM_OFF : ACCT_MATCHER_PROGRAM_OFF);\n const matcherCtxOff = isV12_1 ? V12_1_ACCT_MATCHER_CONTEXT_OFF : (isAdl ? V_ADL_ACCT_MATCHER_CONTEXT_OFF : ACCT_MATCHER_CONTEXT_OFF);\n const feeCreditsOff = isV12_1 ? V12_1_ACCT_FEE_CREDITS_OFF : (isAdl ? V_ADL_ACCT_FEE_CREDITS_OFF : ACCT_FEE_CREDITS_OFF);\n const lastFeeSlotOff = isV12_1 ? V12_1_ACCT_LAST_FEE_SLOT_OFF : (isAdl ? V_ADL_ACCT_LAST_FEE_SLOT_OFF : ACCT_LAST_FEE_SLOT_OFF);\n\n const kindByte = readU8(data, base + ACCT_KIND_OFF);\n const kind = kindByte === 1 ? AccountKind.LP : AccountKind.User;\n\n return {\n kind,\n accountId: readU64LE(data, base + ACCT_ACCOUNT_ID_OFF),\n capital: readU128LE(data, base + ACCT_CAPITAL_OFF),\n pnl: readI128LE(data, base + ACCT_PNL_OFF),\n reservedPnl: isAdl ? readU128LE(data, base + ACCT_RESERVED_PNL_OFF) : readU64LE(data, base + ACCT_RESERVED_PNL_OFF),\n warmupStartedAtSlot: readU64LE(data, base + warmupStartedOff),\n warmupSlopePerStep: readU128LE(data, base + warmupSlopeOff),\n positionSize: readI128LE(data, base + positionSizeOff),\n entryPrice: readU64LE(data, base + entryPriceOff),\n // V12_1 changed funding_index from i128 to i64 (legacy field moved to end of account)\n fundingIndex: isV12_1 ? BigInt(readI64LE(data, base + fundingIndexOff)) : readI128LE(data, base + fundingIndexOff),\n matcherProgram: new PublicKey(data.subarray(base + matcherProgOff, base + matcherProgOff + 32)),\n matcherContext: new PublicKey(data.subarray(base + matcherCtxOff, base + matcherCtxOff + 32)),\n owner: new PublicKey(data.subarray(base + layout.acctOwnerOff, base + layout.acctOwnerOff + 32)),\n feeCredits: readI128LE(data, base + feeCreditsOff),\n lastFeeSlot: readU64LE(data, base + lastFeeSlotOff),\n };\n}\n\n/**\n * Parse all used accounts.\n */\nexport function parseAllAccounts(data: Uint8Array): { idx: number; account: Account }[] {\n const indices = parseUsedIndices(data);\n const maxIdx = maxAccountIndex(data.length);\n const validIndices = indices.filter(idx => idx < maxIdx);\n const droppedCount = indices.length - validIndices.length;\n if (droppedCount > 0) {\n console.warn(\n `[parseAllAccounts] bitmap claims ${indices.length} used accounts but only ${maxIdx} fit ` +\n `in the slab — ${droppedCount} out-of-bounds indices dropped (possible bitmap corruption)`,\n );\n }\n return validIndices.map(idx => ({\n idx,\n account: parseAccount(data, idx),\n }));\n}\n\n","import { PublicKey } from \"@solana/web3.js\";\n\nconst textEncoder = new TextEncoder();\n\n/**\n * Derive vault authority PDA.\n * Seeds: [\"vault\", slab_key]\n */\nexport function deriveVaultAuthority(\n programId: PublicKey,\n slab: PublicKey\n): [PublicKey, number] {\n return PublicKey.findProgramAddressSync(\n [textEncoder.encode(\"vault\"), slab.toBytes()],\n programId\n );\n}\n\nconst LP_INDEX_U16_MAX = 0xffff;\n\n/**\n * Derive LP PDA for TradeCpi.\n * Seeds: [\"lp\", slab_key, lp_idx as u16 LE]\n */\nexport function deriveLpPda(\n programId: PublicKey,\n slab: PublicKey,\n lpIdx: number\n): [PublicKey, number] {\n if (\n typeof lpIdx !== \"number\" ||\n !Number.isInteger(lpIdx) ||\n lpIdx < 0 ||\n lpIdx > LP_INDEX_U16_MAX\n ) {\n throw new Error(\n `deriveLpPda: lpIdx must be an integer in [0, ${LP_INDEX_U16_MAX}], got ${lpIdx}`,\n );\n }\n const idxBuf = new Uint8Array(2);\n new DataView(idxBuf.buffer).setUint16(0, lpIdx, true);\n return PublicKey.findProgramAddressSync(\n [textEncoder.encode(\"lp\"), slab.toBytes(), idxBuf],\n programId\n );\n}\n\n/**\n * Derive keeper fund PDA.\n * Seeds: [\"keeper_fund\", slab_key]\n */\nexport function deriveKeeperFund(\n programId: PublicKey,\n slab: PublicKey\n): [PublicKey, number] {\n return PublicKey.findProgramAddressSync(\n [textEncoder.encode(\"keeper_fund\"), slab.toBytes()],\n programId\n );\n}\n\n// ---------------------------------------------------------------------------\n// DEX Program IDs\n// ---------------------------------------------------------------------------\n\n/** PumpSwap AMM program ID. */\nexport const PUMPSWAP_PROGRAM_ID = new PublicKey(\n \"pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA\"\n);\n\n/** Raydium CLMM (Concentrated Liquidity) program ID. */\nexport const RAYDIUM_CLMM_PROGRAM_ID = new PublicKey(\n \"CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK\"\n);\n\n/** Meteora DLMM (Dynamic Liquidity Market Maker) program ID. */\nexport const METEORA_DLMM_PROGRAM_ID = new PublicKey(\n \"LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo\"\n);\n\n// ---------------------------------------------------------------------------\n// Pyth Push Oracle\n// ---------------------------------------------------------------------------\n\n/** Pyth Push Oracle program on mainnet. */\nexport const PYTH_PUSH_ORACLE_PROGRAM_ID = new PublicKey(\n \"pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT\"\n);\n\n// ---------------------------------------------------------------------------\n// Creator Lock PDA (PERC-627)\n// ---------------------------------------------------------------------------\n\n/**\n * Seed used to derive the creator lock PDA.\n * Matches `creator_lock::CREATOR_LOCK_SEED` in percolator-prog.\n */\nexport const CREATOR_LOCK_SEED = \"creator_lock\";\n\n/**\n * Derive the creator lock PDA for a given slab.\n * Seeds: [\"creator_lock\", slab_key]\n *\n * This PDA is required as accounts[9] in every LpVaultWithdraw instruction\n * since percolator-prog PR#170 (GH#1926 / PERC-8287).\n * Non-creator withdrawers must pass this key; if no lock exists on-chain the\n * enforcement is a no-op. The SDK must ALWAYS include it — passing it is mandatory.\n *\n * @param programId - The percolator program ID.\n * @param slab - The slab (market) public key.\n * @returns [pda, bump]\n *\n * @example\n * ```ts\n * const [creatorLockPda] = deriveCreatorLockPda(PROGRAM_ID, slabKey);\n * ```\n */\nexport function deriveCreatorLockPda(\n programId: PublicKey,\n slab: PublicKey\n): [PublicKey, number] {\n return PublicKey.findProgramAddressSync(\n [textEncoder.encode(CREATOR_LOCK_SEED), slab.toBytes()],\n programId\n );\n}\n/** 32-byte feed id as 64 hex digits (optional `0x` prefix after trim). */\nconst PYTH_FEED_ID_HEX_LEN = 64;\n\nfunction normalizePythFeedIdHex(feedIdHex: string): string {\n let s = feedIdHex.trim();\n if (s.startsWith(\"0x\") || s.startsWith(\"0X\")) {\n s = s.slice(2);\n }\n return s;\n}\n\n/**\n * Derive the Pyth Push Oracle PDA for a given feed ID.\n * Seeds: [shard_id(u16 LE, always 0), feed_id(32 bytes)]\n * Program: pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT\n */\nconst FEED_HEX_RE = /^[0-9a-fA-F]{64}$/;\n\nexport function derivePythPushOraclePDA(feedIdHex: string): [PublicKey, number] {\n const normalized = normalizePythFeedIdHex(feedIdHex);\n if (!FEED_HEX_RE.test(normalized)) {\n throw new Error(\n `derivePythPushOraclePDA: feedIdHex must be 64 hex digits (32 bytes); got ${normalized.length === 64 ? \"non-hexadecimal characters\" : normalized.length + \" chars\"}`, );\n }\n const feedId = new Uint8Array(32);\n for (let i = 0; i < 32; i++) {\n const hexPair = normalized.substring(i * 2, i * 2 + 2);\n const byte = parseInt(hexPair, 16);\n // Defensive check: ensure no NaN values in feed ID\n if (Number.isNaN(byte)) {\n throw new Error(\n `derivePythPushOraclePDA: failed to parse hex byte at position ${i}: \"${hexPair}\"`,\n );\n }\n feedId[i] = byte;\n }\n const shardBuf = new Uint8Array(2); // shard_id = 0 (u16 LE)\n return PublicKey.findProgramAddressSync(\n [shardBuf, feedId],\n PYTH_PUSH_ORACLE_PROGRAM_ID,\n );\n}\n","import { Connection, PublicKey } from \"@solana/web3.js\";\nimport {\n getAssociatedTokenAddress,\n getAssociatedTokenAddressSync,\n getAccount,\n Account,\n TOKEN_PROGRAM_ID,\n} from \"@solana/spl-token\";\nimport { TOKEN_2022_PROGRAM_ID } from \"./token-program.js\";\n\n/**\n * Get the associated token address for an owner and mint.\n * Supports both standard SPL Token and Token2022 via optional tokenProgramId.\n */\nexport async function getAta(\n owner: PublicKey,\n mint: PublicKey,\n allowOwnerOffCurve = false,\n tokenProgramId: PublicKey = TOKEN_PROGRAM_ID,\n): Promise<PublicKey> {\n return getAssociatedTokenAddress(mint, owner, allowOwnerOffCurve, tokenProgramId);\n}\n\n/**\n * Synchronous version of getAta.\n * Supports both standard SPL Token and Token2022 via optional tokenProgramId.\n */\nexport function getAtaSync(\n owner: PublicKey,\n mint: PublicKey,\n allowOwnerOffCurve = false,\n tokenProgramId: PublicKey = TOKEN_PROGRAM_ID,\n): PublicKey {\n return getAssociatedTokenAddressSync(mint, owner, allowOwnerOffCurve, tokenProgramId);\n}\n\n/**\n * Fetch token account info.\n * Supports both standard SPL Token and Token2022 via optional tokenProgramId.\n * Throws if account doesn't exist.\n */\nexport async function fetchTokenAccount(\n connection: Connection,\n address: PublicKey,\n tokenProgramId: PublicKey = TOKEN_PROGRAM_ID,\n): Promise<Account> {\n return getAccount(connection, address, undefined, tokenProgramId);\n}\n","import { Connection, PublicKey } from \"@solana/web3.js\";\nimport {\n parseHeader,\n parseConfig,\n parseParams,\n detectSlabLayout,\n SLAB_TIERS_V1M,\n SLAB_TIERS_V2,\n SLAB_TIERS_V_ADL,\n SLAB_TIERS_V12_1,\n type SlabHeader,\n type MarketConfig,\n type EngineState,\n type RiskParams,\n type SlabLayout,\n} from \"./slab.js\";\nimport { getStaticMarkets, type StaticMarketEntry } from \"./static-markets.js\";\nimport { type Network } from \"../config/program-ids.js\";\n\n/** V1 bitmap offset within engine struct (updated for PERC-120/121/122 struct changes) */\nconst ENGINE_BITMAP_OFF = 656; // Updated for PERC-299 (608 + 24 emergency OI fields)\n/** V0 bitmap offset within engine struct (deployed devnet program) */\nconst ENGINE_BITMAP_OFF_V0 = 320;\n\n/**\n * A discovered Percolator market from on-chain program accounts.\n */\nexport interface DiscoveredMarket {\n slabAddress: PublicKey;\n /** The program that owns this slab account */\n programId: PublicKey;\n header: SlabHeader;\n config: MarketConfig;\n engine: EngineState;\n params: RiskParams;\n}\n\n/** PERCOLAT magic bytes — stored little-endian on-chain as TALOCREP */\nconst MAGIC_BYTES = new Uint8Array([0x54, 0x41, 0x4c, 0x4f, 0x43, 0x52, 0x45, 0x50]);\n\n/**\n * Slab tier definitions — V1 layout (all tiers upgraded as of 2026-03-13).\n * IMPORTANT: dataSize must match the compiled program's SLAB_LEN for that MAX_ACCOUNTS.\n * The on-chain program has a hardcoded SLAB_LEN — slab account data.len() must equal it exactly.\n *\n * Layout: HEADER(104) + CONFIG(536) + RiskEngine(variable by tier)\n * ENGINE_OFF = 640 (HEADER=104 + CONFIG=536, padded to 8-byte align on SBF)\n * RiskEngine = fixed(656) + bitmap(BW*8) + post_bitmap(18) + next_free(N*2) + pad + accounts(N*248)\n *\n * Values are empirically verified against on-chain initialized accounts (GH #1109):\n * small = 65,352 (256-acct program, verified on-chain post-V1 upgrade)\n * medium = 257,448 (1024-acct program g9msRSV3, verified on-chain)\n * large = 1,025,832 (4096-acct program FxfD37s1, pre-PERC-118, matches slabDataSizeV1(4096) formula)\n *\n * NOTE: small program (FwfBKZXb) redeployed with --features small,devnet (2026-03-13).\n * Large program FxfD37s1 is pre-PERC-118 — SLAB_LEN=1,025,832, matching formula.\n * See GH #1109, GH #1112.\n *\n * History: Small was V0 (62_808) until 2026-03-13 program upgrade. V0 values preserved\n * in SLAB_TIERS_V0 for discovery of legacy on-chain accounts.\n */\n/**\n * Default slab tiers for the current mainnet program (v12.1).\n * These are used by useCreateMarket to allocate slab accounts of the correct size.\n */\nexport const SLAB_TIERS = {\n micro: SLAB_TIERS_V12_1[\"micro\"],\n small: SLAB_TIERS_V12_1[\"small\"],\n medium: SLAB_TIERS_V12_1[\"medium\"],\n large: SLAB_TIERS_V12_1[\"large\"],\n} as const;\n\n/** @deprecated V0 slab sizes — kept for backward compatibility with old on-chain slabs */\nexport const SLAB_TIERS_V0 = {\n small: { maxAccounts: 256, dataSize: 62_808, label: \"Small\", description: \"256 slots · ~0.44 SOL\" },\n medium: { maxAccounts: 1024, dataSize: 248_760, label: \"Medium\", description: \"1,024 slots · ~1.73 SOL\" },\n large: { maxAccounts: 4096, dataSize: 992_568, label: \"Large\", description: \"4,096 slots · ~6.90 SOL\" },\n} as const;\n\n/**\n * V1D slab sizes — actually-deployed devnet V1 program (ENGINE_OFF=424, BITMAP_OFF=624).\n * PR #1200 added V1D layout detection in slab.ts but discovery.ts ALL_TIERS was missing\n * these sizes, causing V1D slabs to fall through to the memcmp fallback with wrong dataSize\n * hints → detectSlabLayout returning null → parse failure (GH#1205).\n *\n * Sizes computed via computeSlabSize(ENGINE_OFF=424, BITMAP_OFF=624, ACCOUNT_SIZE=248, N, postBitmap=2):\n * The V1D deployed program uses postBitmap=2 (free_head u16 only — no num_used/pad/next_account_id).\n * This is 16 bytes smaller per tier than the SDK default (postBitmap=18). GH#1234.\n * micro = 17,064 (64 slots)\n * small = 65,088 (256 slots)\n * medium = 257,184 (1,024 slots)\n * large = 1,025,568 (4,096 slots)\n */\nexport const SLAB_TIERS_V1D = {\n micro: { maxAccounts: 64, dataSize: 17_064, label: \"Micro\", description: \"64 slots (V1D devnet)\" },\n small: { maxAccounts: 256, dataSize: 65_088, label: \"Small\", description: \"256 slots (V1D devnet)\" },\n medium: { maxAccounts: 1024, dataSize: 257_184, label: \"Medium\", description: \"1,024 slots (V1D devnet)\" },\n large: { maxAccounts: 4096, dataSize: 1_025_568, label: \"Large\", description: \"4,096 slots (V1D devnet)\" },\n} as const;\n\n/**\n * V1D legacy slab sizes — on-chain V1D slabs created before GH#1234 when the SDK assumed\n * postBitmap=18. These are 16 bytes larger per tier than SLAB_TIERS_V1D.\n * PR #1236 fixed postBitmap for new slabs (→2) but caused slab 6ZytbpV4 (65104 bytes,\n * top active market ~$15k 24h vol) to be unrecognized → \"Failed to load market\". GH#1237.\n *\n * Sizes computed via computeSlabSize(ENGINE_OFF=424, BITMAP_OFF=624, ACCOUNT_SIZE=248, N, postBitmap=18):\n * micro = 17,080 (64 slots)\n * small = 65,104 (256 slots) ← slab 6ZytbpV4 TEST/USD\n * medium = 257,200 (1,024 slots)\n * large = 1,025,584 (4,096 slots)\n */\nexport const SLAB_TIERS_V1D_LEGACY = {\n micro: { maxAccounts: 64, dataSize: 17_080, label: \"Micro\", description: \"64 slots (V1D legacy, postBitmap=18)\" },\n small: { maxAccounts: 256, dataSize: 65_104, label: \"Small\", description: \"256 slots (V1D legacy, postBitmap=18)\" },\n medium: { maxAccounts: 1024, dataSize: 257_200, label: \"Medium\", description: \"1,024 slots (V1D legacy, postBitmap=18)\" },\n large: { maxAccounts: 4096, dataSize: 1_025_584, label: \"Large\", description: \"4,096 slots (V1D legacy, postBitmap=18)\" },\n} as const;\n\n/** @deprecated Alias — use SLAB_TIERS (already V1) */\nexport const SLAB_TIERS_V1 = SLAB_TIERS;\n\n/**\n * V_ADL slab tier sizes — PERC-8270/8271 ADL-upgraded program.\n * ENGINE_OFF=624, BITMAP_OFF=1006, ACCOUNT_SIZE=312, postBitmap=18.\n * New account layout adds ADL tracking fields (+64 bytes/account).\n * BPF SLAB_LEN verified by cargo build-sbf in PERC-8271: large (4096) = 1288304 bytes.\n */\n// Single source of truth lives in slab.ts (SLAB_TIERS_V_ADL).\nexport const SLAB_TIERS_V_ADL_DISCOVERY = SLAB_TIERS_V_ADL;\n\nexport type SlabTierKey = keyof typeof SLAB_TIERS;\n\n/** Calculate slab data size for arbitrary account count.\n *\n * Layout (SBF, u128 align = 8):\n * HEADER(104) + CONFIG(536) → ENGINE_OFF = 640\n * RiskEngine fixed scalars: 656 bytes (PERC-299: +24 emergency OI, +32 long/short OI)\n * + bitmap: ceil(N/64)*8\n * + num_used_accounts(u16) + pad(6) + next_account_id(u64) + free_head(u16) = 18\n * + next_free: N*2\n * + pad to 8-byte alignment for Account array\n * + accounts: N*248\n *\n * Must match the on-chain program's SLAB_LEN exactly.\n */\nexport function slabDataSize(maxAccounts: number): number {\n // V0 layout (deployed devnet): ENGINE_OFF=480, ENGINE_BITMAP_OFF=320, ACCOUNT_SIZE=240\n const ENGINE_OFF_V0 = 480;\n const ENGINE_BITMAP_OFF_V0 = 320;\n const ACCOUNT_SIZE_V0 = 240;\n const bitmapBytes = Math.ceil(maxAccounts / 64) * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = ENGINE_BITMAP_OFF_V0 + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOff = Math.ceil(preAccountsLen / 8) * 8;\n return ENGINE_OFF_V0 + accountsOff + maxAccounts * ACCOUNT_SIZE_V0;\n}\n\n/**\n * Calculate slab data size for V1 layout (ENGINE_OFF=640).\n *\n * NOTE: This formula is accurate for small (256) and medium (1024) tiers but\n * underestimates large (4096) by 16 bytes — likely due to a padding/alignment\n * difference at high account counts or a post-PERC-118 struct addition in the\n * deployed binary. Always prefer the hardcoded SLAB_TIERS values (empirically\n * verified on-chain) over this formula for production use.\n */\nexport function slabDataSizeV1(maxAccounts: number): number {\n const ENGINE_OFF_V1 = 640; // HEADER(104) + CONFIG(536) aligned to 8 on SBF = 640\n const ENGINE_BITMAP_OFF_V1 = 656;\n const ACCOUNT_SIZE_V1 = 248;\n const bitmapBytes = Math.ceil(maxAccounts / 64) * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = ENGINE_BITMAP_OFF_V1 + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOff = Math.ceil(preAccountsLen / 8) * 8;\n return ENGINE_OFF_V1 + accountsOff + maxAccounts * ACCOUNT_SIZE_V1;\n}\n\n/**\n * Validate that a slab data size matches one of the known tier sizes.\n * Use this to catch tier↔program mismatches early (PERC-277).\n *\n * @param dataSize - The expected slab data size (from SLAB_TIERS[tier].dataSize)\n * @param programSlabLen - The program's compiled SLAB_LEN (from on-chain error logs or program introspection)\n * @returns true if sizes match, false if there's a mismatch\n */\nexport function validateSlabTierMatch(dataSize: number, programSlabLen: number): boolean {\n return dataSize === programSlabLen;\n}\n\n/** All known slab data sizes for discovery (V0 + V1 + V1D + V1D legacy + V1M + V_ADL tiers) */\nconst ALL_SLAB_SIZES = [\n ...Object.values(SLAB_TIERS).map(t => t.dataSize),\n ...Object.values(SLAB_TIERS_V0).map(t => t.dataSize),\n ...Object.values(SLAB_TIERS_V1D).map(t => t.dataSize),\n ...Object.values(SLAB_TIERS_V1D_LEGACY).map(t => t.dataSize),\n ...Object.values(SLAB_TIERS_V1M).map(t => t.dataSize),\n ...Object.values(SLAB_TIERS_V_ADL).map(t => t.dataSize),\n];\n\n/** Legacy constant for backward compat */\nconst SLAB_DATA_SIZE = SLAB_TIERS.large.dataSize;\n\n/** We need header(104) + config(536) + engine up to nextAccountId (~1200). Total ~1840. Use 1940 for margin. */\nconst HEADER_SLICE_LENGTH = 1940;\n\nfunction dv(data: Uint8Array): DataView {\n return new DataView(data.buffer, data.byteOffset, data.byteLength);\n}\nfunction readU16LE(data: Uint8Array, off: number): number {\n return dv(data).getUint16(off, true);\n}\nfunction readU64LE(data: Uint8Array, off: number): bigint {\n return dv(data).getBigUint64(off, true);\n}\nfunction readI64LE(data: Uint8Array, off: number): bigint {\n return dv(data).getBigInt64(off, true);\n}\nfunction readU128LE(buf: Uint8Array, offset: number): bigint {\n const lo = readU64LE(buf, offset);\n const hi = readU64LE(buf, offset + 8);\n return (hi << 64n) | lo;\n}\nfunction readI128LE(buf: Uint8Array, offset: number): bigint {\n const lo = readU64LE(buf, offset);\n const hi = readU64LE(buf, offset + 8);\n const unsigned = (hi << 64n) | lo;\n const SIGN_BIT = 1n << 127n;\n if (unsigned >= SIGN_BIT) return unsigned - (1n << 128n);\n return unsigned;\n}\n\n/**\n * Light engine parser that works with partial slab data (dataSlice, no accounts array).\n * Requires a layout hint (from detectSlabLayout on the actual slab size) to use correct offsets.\n *\n * @param data — partial slab slice (HEADER_SLICE_LENGTH bytes)\n * @param layout — SlabLayout from detectSlabLayout(actualDataSize). If null, falls back to V0.\n * @param maxAccounts — tier's max accounts for bitmap offset calculation\n */\nfunction parseEngineLight(\n data: Uint8Array,\n layout: SlabLayout | null,\n maxAccounts: number = 4096,\n): EngineState {\n const isV0 = !layout || layout.version === 0;\n const base = layout ? layout.engineOff : 480; // V0=480, V1=640\n const bitmapOff = layout ? layout.engineBitmapOff : ENGINE_BITMAP_OFF_V0;\n\n const minLen = base + bitmapOff;\n if (data.length < minLen) {\n throw new Error(`Slab data too short for engine light parse: ${data.length} < ${minLen}`);\n }\n\n // Compute tier-dependent offsets for numUsedAccounts and nextAccountId\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const numUsedOff = bitmapOff + bitmapWords * 8; // u16 right after bitmap\n const nextAccountIdOff = Math.ceil((numUsedOff + 2) / 8) * 8; // u64, 8-byte aligned\n\n const canReadNumUsed = data.length >= base + numUsedOff + 2;\n const canReadNextId = data.length >= base + nextAccountIdOff + 8;\n\n if (isV0) {\n // V0 engine struct (deployed devnet): ENGINE_OFF=480\n // vault(0,16) + insurance(16,32) + params(48,56) + currentSlot(104,8)\n // + fundingIndex(112,16) + lastFundingSlot(128,8) + fundingRateBps(136,8)\n // + lastCrankSlot(144,8) + maxCrankStaleness(152,8) + totalOI(160,16)\n // + cTot(176,16) + pnlPosTot(192,16) + liqCursor(208,2) + gcCursor(210,2)\n // + lastSweepStart(216,8) + lastSweepComplete(224,8) + crankCursor(232,2) + sweepStartIdx(234,2)\n // + lifetimeLiquidations(240,8) + lifetimeForceCloses(248,8)\n // + netLpPos(256,16) + lpSumAbs(272,16) + lpMaxAbs(288,16) + bitmap(320)\n return {\n vault: readU128LE(data, base + 0),\n insuranceFund: {\n balance: readU128LE(data, base + 16),\n feeRevenue: readU128LE(data, base + 32),\n isolatedBalance: 0n,\n isolationBps: 0,\n },\n currentSlot: readU64LE(data, base + 104),\n fundingIndexQpbE6: readI128LE(data, base + 112),\n lastFundingSlot: readU64LE(data, base + 128),\n fundingRateBpsPerSlotLast: readI64LE(data, base + 136),\n lastCrankSlot: readU64LE(data, base + 144),\n maxCrankStalenessSlots: readU64LE(data, base + 152),\n totalOpenInterest: readU128LE(data, base + 160),\n longOi: 0n,\n shortOi: 0n,\n cTot: readU128LE(data, base + 176),\n pnlPosTot: readU128LE(data, base + 192),\n liqCursor: readU16LE(data, base + 208),\n gcCursor: readU16LE(data, base + 210),\n lastSweepStartSlot: readU64LE(data, base + 216),\n lastSweepCompleteSlot: readU64LE(data, base + 224),\n crankCursor: readU16LE(data, base + 232),\n sweepStartIdx: readU16LE(data, base + 234),\n lifetimeLiquidations: readU64LE(data, base + 240),\n lifetimeForceCloses: readU64LE(data, base + 248),\n netLpPos: readI128LE(data, base + 256),\n lpSumAbs: readU128LE(data, base + 272),\n lpMaxAbs: readU128LE(data, base + 288),\n lpMaxAbsSweep: 0n,\n emergencyOiMode: false,\n emergencyStartSlot: 0n,\n lastBreakerSlot: 0n,\n markPriceE6: 0n, // V0 engine has no mark_price field\n numUsedAccounts: canReadNumUsed ? readU16LE(data, base + numUsedOff) : 0,\n nextAccountId: canReadNextId ? readU64LE(data, base + nextAccountIdOff) : 0n,\n };\n }\n\n // V2 engine struct (BPF intermediate): ENGINE_OFF=600, BITMAP_OFF=432\n // No mark_price, long_oi, short_oi, emergency OI fields.\n // Field offsets relative to engineOff are different from V1.\n const isV2 = layout?.version === 2;\n if (isV2) {\n return {\n vault: readU128LE(data, base + 0),\n insuranceFund: {\n balance: readU128LE(data, base + 16),\n feeRevenue: readU128LE(data, base + 32),\n isolatedBalance: readU128LE(data, base + 48),\n isolationBps: readU16LE(data, base + 64),\n },\n currentSlot: readU64LE(data, base + 352),\n fundingIndexQpbE6: readI128LE(data, base + 360),\n lastFundingSlot: readU64LE(data, base + 376),\n fundingRateBpsPerSlotLast: readI64LE(data, base + 384),\n lastCrankSlot: readU64LE(data, base + 392),\n maxCrankStalenessSlots: readU64LE(data, base + 400),\n totalOpenInterest: readU128LE(data, base + 408),\n longOi: 0n, // V2 has no long_oi\n shortOi: 0n, // V2 has no short_oi\n cTot: readU128LE(data, base + 424),\n pnlPosTot: readU128LE(data, base + 440),\n liqCursor: readU16LE(data, base + 456),\n gcCursor: readU16LE(data, base + 458),\n lastSweepStartSlot: readU64LE(data, base + 464),\n lastSweepCompleteSlot: readU64LE(data, base + 472),\n crankCursor: readU16LE(data, base + 480),\n sweepStartIdx: readU16LE(data, base + 482),\n lifetimeLiquidations: readU64LE(data, base + 488),\n lifetimeForceCloses: readU64LE(data, base + 496),\n netLpPos: readI128LE(data, base + 504),\n lpSumAbs: readU128LE(data, base + 520),\n lpMaxAbs: readU128LE(data, base + 536),\n lpMaxAbsSweep: readU128LE(data, base + 552),\n emergencyOiMode: false, // V2 has no emergency OI fields\n emergencyStartSlot: 0n,\n lastBreakerSlot: 0n,\n markPriceE6: 0n, // V2 has no mark_price\n numUsedAccounts: canReadNumUsed ? readU16LE(data, base + numUsedOff) : 0,\n nextAccountId: canReadNextId ? readU64LE(data, base + nextAccountIdOff) : 0n,\n };\n }\n\n // V_ADL engine struct (PERC-8270/8271): ENGINE_OFF=624, layout-driven offsets.\n // Must branch here because V_ADL has version===1 same as V1/V1M — differentiate by engineOff.\n // All offsets from SlabLayout descriptor, which is computed by buildLayoutVADL().\n const isVAdl = layout !== null && layout.engineOff === 624 && layout.accountSize === 312;\n if (isVAdl) {\n const l = layout!;\n return {\n vault: readU128LE(data, base + 0),\n insuranceFund: {\n balance: readU128LE(data, base + l.engineInsuranceOff),\n feeRevenue: readU128LE(data, base + l.engineInsuranceOff + 16),\n isolatedBalance: readU128LE(data, base + l.engineInsuranceIsolatedOff),\n isolationBps: readU16LE(data, base + l.engineInsuranceIsolationBpsOff),\n },\n currentSlot: readU64LE(data, base + l.engineCurrentSlotOff),\n fundingIndexQpbE6: readI128LE(data, base + l.engineFundingIndexOff),\n lastFundingSlot: readU64LE(data, base + l.engineLastFundingSlotOff),\n fundingRateBpsPerSlotLast: readI64LE(data, base + l.engineFundingRateBpsOff),\n lastCrankSlot: readU64LE(data, base + l.engineLastCrankSlotOff),\n maxCrankStalenessSlots: readU64LE(data, base + l.engineMaxCrankStalenessOff),\n totalOpenInterest: readU128LE(data, base + l.engineTotalOiOff),\n longOi: l.engineLongOiOff >= 0 ? readU128LE(data, base + l.engineLongOiOff) : 0n,\n shortOi: l.engineShortOiOff >= 0 ? readU128LE(data, base + l.engineShortOiOff) : 0n,\n cTot: readU128LE(data, base + l.engineCTotOff),\n pnlPosTot: readU128LE(data, base + l.enginePnlPosTotOff),\n liqCursor: readU16LE(data, base + l.engineLiqCursorOff),\n gcCursor: readU16LE(data, base + l.engineGcCursorOff),\n lastSweepStartSlot: readU64LE(data, base + l.engineLastSweepStartOff),\n lastSweepCompleteSlot: readU64LE(data, base + l.engineLastSweepCompleteOff),\n crankCursor: readU16LE(data, base + l.engineCrankCursorOff),\n sweepStartIdx: readU16LE(data, base + l.engineSweepStartIdxOff),\n lifetimeLiquidations: readU64LE(data, base + l.engineLifetimeLiquidationsOff),\n lifetimeForceCloses: readU64LE(data, base + l.engineLifetimeForceClosesOff),\n netLpPos: readI128LE(data, base + l.engineNetLpPosOff),\n lpSumAbs: readU128LE(data, base + l.engineLpSumAbsOff),\n lpMaxAbs: readU128LE(data, base + l.engineLpMaxAbsOff),\n lpMaxAbsSweep: readU128LE(data, base + l.engineLpMaxAbsSweepOff),\n emergencyOiMode: l.engineEmergencyOiModeOff >= 0 ? data[base + l.engineEmergencyOiModeOff] !== 0 : false,\n emergencyStartSlot: l.engineEmergencyStartSlotOff >= 0 ? readU64LE(data, base + l.engineEmergencyStartSlotOff) : 0n,\n lastBreakerSlot: l.engineLastBreakerSlotOff >= 0 ? readU64LE(data, base + l.engineLastBreakerSlotOff) : 0n,\n markPriceE6: l.engineMarkPriceOff >= 0 ? readU64LE(data, base + l.engineMarkPriceOff) : 0n,\n numUsedAccounts: canReadNumUsed ? readU16LE(data, base + numUsedOff) : 0,\n nextAccountId: canReadNextId ? readU64LE(data, base + nextAccountIdOff) : 0n,\n };\n }\n\n // V1 engine struct (PERC-1094 corrected): ENGINE_OFF=600 (BPF/SBF, CONFIG_LEN=496)\n // vault(0,16) + insurance(16,56) + params(72,288) + currentSlot(360) + fundingIndex(368,16)\n // + lastFundingSlot(384) + fundingRateBps(392) + markPrice(400) + lastCrankSlot(424)\n // + maxCrankStaleness(432) + totalOI(440,16) + longOi(456,16) + shortOi(472,16)\n // + cTot(488,16) + pnlPosTot(504,16) + liqCursor(520,2) + gcCursor(522,2)\n // + lastSweepStart(528) + lastSweepComplete(536) + crankCursor(544,2) + sweepStartIdx(546,2)\n // + lifetimeLiquidations(552) + lifetimeForceCloses(560)\n // + netLpPos(568,16) + lpSumAbs(584,16) + lpMaxAbs(600,16) + lpMaxAbsSweep(616,16)\n // + emergencyOiMode(632,1+7pad) + emergencyStartSlot(640) + lastBreakerSlot(648) + bitmap(656)\n return {\n vault: readU128LE(data, base + 0),\n insuranceFund: {\n balance: readU128LE(data, base + 16),\n feeRevenue: readU128LE(data, base + 32),\n isolatedBalance: readU128LE(data, base + 48),\n isolationBps: readU16LE(data, base + 64),\n },\n currentSlot: readU64LE(data, base + 360), // PERC-1094: params end at 72+288=360 (was 352)\n fundingIndexQpbE6: readI128LE(data, base + 368),\n lastFundingSlot: readU64LE(data, base + 384),\n fundingRateBpsPerSlotLast: readI64LE(data, base + 392),\n lastCrankSlot: readU64LE(data, base + 424),\n maxCrankStalenessSlots: readU64LE(data, base + 408),\n totalOpenInterest: readU128LE(data, base + 416),\n longOi: readU128LE(data, base + 432),\n shortOi: readU128LE(data, base + 448),\n cTot: readU128LE(data, base + 464),\n pnlPosTot: readU128LE(data, base + 480),\n liqCursor: readU16LE(data, base + 496),\n gcCursor: readU16LE(data, base + 498),\n lastSweepStartSlot: readU64LE(data, base + 504),\n lastSweepCompleteSlot: readU64LE(data, base + 512),\n crankCursor: readU16LE(data, base + 520),\n sweepStartIdx: readU16LE(data, base + 522),\n lifetimeLiquidations: readU64LE(data, base + 528),\n lifetimeForceCloses: readU64LE(data, base + 536),\n netLpPos: readI128LE(data, base + 544),\n lpSumAbs: readU128LE(data, base + 560),\n lpMaxAbs: readU128LE(data, base + 576),\n lpMaxAbsSweep: readU128LE(data, base + 592),\n emergencyOiMode: data[base + 608] !== 0,\n emergencyStartSlot: readU64LE(data, base + 616),\n lastBreakerSlot: readU64LE(data, base + 624),\n markPriceE6: readU64LE(data, base + 400), // PERC-1094: was 392\n numUsedAccounts: canReadNumUsed ? readU16LE(data, base + numUsedOff) : 0,\n nextAccountId: canReadNextId ? readU64LE(data, base + nextAccountIdOff) : 0n,\n };\n}\n\n/** Options for `discoverMarkets`. */\nexport interface DiscoverMarketsOptions {\n /**\n * Run tier queries sequentially with per-tier retry on HTTP 429 instead of\n * firing all in parallel. Reduces RPC rate-limit pressure at the cost of\n * slightly slower discovery (~14 round-trips instead of 1 concurrent batch).\n * Default: false (preserves original parallel behaviour).\n *\n * PERC-1650: keeper uses this flag to avoid 429 storms on its fallback RPC\n * (Helius starter tier). Pass `sequential: true` from CrankService.discover().\n */\n sequential?: boolean;\n /**\n * Delay in ms between sequential tier queries (only used when sequential=true).\n * Default: 200 ms.\n */\n interTierDelayMs?: number;\n /**\n * Per-tier retry backoff delays on 429 (ms). Jitter of up to +25% is applied.\n * Only used when sequential=true. Default: [1_000, 3_000, 9_000, 27_000].\n */\n rateLimitBackoffMs?: number[];\n\n /**\n * In parallel mode (the default), cap how many tier RPC requests are in-flight\n * at once to avoid accidental RPC storms from client code.\n *\n * Default: 6\n */\n maxParallelTiers?: number;\n\n /**\n * Hard cap on how many tier dataSize queries are attempted.\n * Default: all known tiers.\n */\n maxTierQueries?: number;\n\n /**\n * Base URL of the Percolator REST API (e.g. `\"https://percolatorlaunch.com/api\"`).\n *\n * When set, `discoverMarkets` will fall back to the REST API's `GET /markets`\n * endpoint if `getProgramAccounts` fails or returns 0 results (common on public\n * mainnet RPCs that reject `getProgramAccounts`).\n *\n * The API returns slab addresses which are then fetched on-chain via\n * `getMarketsByAddress` (uses `getMultipleAccounts`, works on all RPCs).\n *\n * GH#59 / PERC-8424: Unblocks mainnet users without a Helius API key.\n *\n * @example\n * ```ts\n * const markets = await discoverMarkets(connection, programId, {\n * apiBaseUrl: \"https://percolatorlaunch.com/api\",\n * });\n * ```\n */\n apiBaseUrl?: string;\n\n /**\n * Timeout in ms for the API fallback HTTP request.\n * Only used when `apiBaseUrl` is set.\n * Default: 10_000 (10 seconds).\n */\n apiTimeoutMs?: number;\n\n /**\n * Network hint for tier-3 static bundle fallback (`\"mainnet\"` or `\"devnet\"`).\n *\n * When both `getProgramAccounts` (tier 1) and the REST API (tier 2) fail,\n * `discoverMarkets` will fall back to a bundled static list of known slab\n * addresses for the specified network. The addresses are fetched on-chain\n * via `getMarketsByAddress` (`getMultipleAccounts` — works on all RPCs).\n *\n * If not set, tier-3 fallback is disabled.\n *\n * The static list can be extended at runtime via `registerStaticMarkets()`.\n *\n * @see {@link registerStaticMarkets} to add addresses at runtime\n * @see {@link getStaticMarkets} to inspect the current static list\n *\n * @example\n * ```ts\n * const markets = await discoverMarkets(connection, programId, {\n * apiBaseUrl: \"https://percolatorlaunch.com/api\",\n * network: \"mainnet\", // enables tier-3 static fallback\n * });\n * ```\n */\n network?: Network;\n}\n\n/** Return true if the error looks like an HTTP 429 / rate-limit response. */\nfunction isRateLimitError(err: unknown): boolean {\n if (!err) return false;\n const msg = err instanceof Error ? err.message : String(err);\n return (\n msg.includes(\"429\") ||\n msg.toLowerCase().includes(\"rate limit\") ||\n msg.toLowerCase().includes(\"too many requests\")\n );\n}\n\n/** Add up to 25% random jitter to avoid thundering-herd on retry. */\nfunction withJitter(delayMs: number): number {\n return delayMs + Math.floor(Math.random() * delayMs * 0.25);\n}\n\n/**\n * Discover all Percolator markets owned by the given program.\n * Uses getProgramAccounts with dataSize filter + dataSlice to download only ~1400 bytes per slab.\n *\n * @param options.sequential - Run tier queries sequentially with 429 retry (PERC-1650).\n */\nexport async function discoverMarkets(\n connection: Connection,\n programId: PublicKey,\n options: DiscoverMarketsOptions = {},\n): Promise<DiscoveredMarket[]> {\n const {\n sequential = false,\n interTierDelayMs = 200,\n rateLimitBackoffMs = [1_000, 3_000, 9_000, 27_000],\n maxParallelTiers = 6,\n } = options;\n\n // Query all known slab sizes in parallel — V0, V1D (deployed devnet), V1D legacy, and V1 (upgraded) tiers.\n // We track the actual dataSize per entry so detectSlabLayout can determine the correct layout,\n // and pass that layout to all parse functions (avoids wrong-version offsets on partial slices).\n // GH#1205: V1D tiers were missing here — V1D slabs fell through to memcmp fallback with wrong\n // dataSize hints → detectSlabLayout returned null → parse failure in discoverMarkets.\n // GH#1237/GH#1238: SLAB_TIERS_V1D_LEGACY (postBitmap=18, e.g. 65,104-byte slabs created before\n // GH#1234) must also be included; omitting them causes legacy on-chain slabs to be missed by\n // dataSize filter queries and fall through to memcmp with wrong maxAccounts hint.\n const ALL_TIERS = [\n ...Object.values(SLAB_TIERS),\n ...Object.values(SLAB_TIERS_V0),\n ...Object.values(SLAB_TIERS_V1D),\n ...Object.values(SLAB_TIERS_V1D_LEGACY),\n ...Object.values(SLAB_TIERS_V2),\n ...Object.values(SLAB_TIERS_V1M),\n ...Object.values(SLAB_TIERS_V_ADL),\n ];\n type RawEntry = { pubkey: PublicKey; account: { data: Buffer | Uint8Array }; maxAccounts: number; dataSize: number };\n let rawAccounts: RawEntry[] = [];\n\n /**\n * Fetch one tier with per-attempt 429 retry (sequential mode only).\n * Returns an array of RawEntry on success, or an empty array after exhausting retries.\n */\n async function fetchTierWithRetry(\n tier: { dataSize: number; maxAccounts: number },\n ): Promise<RawEntry[]> {\n for (let attempt = 0; attempt <= rateLimitBackoffMs.length; attempt++) {\n try {\n const results = await connection.getProgramAccounts(programId, {\n filters: [{ dataSize: tier.dataSize }],\n dataSlice: { offset: 0, length: HEADER_SLICE_LENGTH },\n });\n return results.map(entry => ({ ...entry, maxAccounts: tier.maxAccounts, dataSize: tier.dataSize }));\n } catch (err) {\n if (isRateLimitError(err) && attempt < rateLimitBackoffMs.length) {\n const delay = withJitter(rateLimitBackoffMs[attempt]);\n console.warn(\n `[discoverMarkets] 429 on tier dataSize=${tier.dataSize} attempt=${attempt + 1}, backing off ${delay}ms`,\n );\n await new Promise(r => setTimeout(r, delay));\n continue;\n }\n // Non-429 or exhausted retries\n console.warn(\n `[discoverMarkets] Tier query failed (dataSize=${tier.dataSize}, attempt=${attempt + 1}):`,\n err instanceof Error ? err.message : err,\n );\n return [];\n }\n }\n return [];\n }\n\n const maxTierQueries = options.maxTierQueries ?? ALL_TIERS.length;\n const tiersToQuery = ALL_TIERS.slice(0, maxTierQueries);\n\n // Avoid accidental `0`/negative or NaN causing infinite loops.\n const effectiveMaxParallelTiers = Math.max(1, Number.isFinite(maxParallelTiers) ? maxParallelTiers : 6);\n\n try {\n if (sequential) {\n // PERC-1650: sequential mode — one tier at a time with inter-tier spacing + per-tier 429 retry.\n for (let i = 0; i < tiersToQuery.length; i++) {\n const tier = tiersToQuery[i];\n const entries = await fetchTierWithRetry(tier);\n rawAccounts.push(...entries);\n if (i < tiersToQuery.length - 1) {\n await new Promise(r => setTimeout(r, interTierDelayMs));\n }\n }\n } else {\n // Parallel mode: cap tier concurrency so we don't fire 20+ large\n // getProgramAccounts calls at once from a single client call.\n for (let offset = 0; offset < tiersToQuery.length; offset += effectiveMaxParallelTiers) {\n const chunk = tiersToQuery.slice(offset, offset + effectiveMaxParallelTiers);\n const queries = chunk.map(tier =>\n connection.getProgramAccounts(programId, {\n filters: [{ dataSize: tier.dataSize }],\n dataSlice: { offset: 0, length: HEADER_SLICE_LENGTH },\n }).then(results =>\n results.map(entry => ({\n ...entry,\n maxAccounts: tier.maxAccounts,\n dataSize: tier.dataSize,\n })),\n ),\n );\n\n const results = await Promise.allSettled(queries);\n for (const result of results) {\n if (result.status === \"fulfilled\") {\n for (const entry of result.value) {\n rawAccounts.push(entry as RawEntry);\n }\n } else {\n console.warn(\n \"[discoverMarkets] Tier query rejected:\",\n result.reason instanceof Error ? result.reason.message : result.reason,\n );\n }\n }\n }\n }\n\n // NOTE: hadRejection guard removed — dataSize filters silently return 0 when on-chain\n // account size changed; RPC returns no error, so we must fallback on empty results too.\n if (rawAccounts.length === 0) {\n console.warn(\"[discoverMarkets] dataSize filters returned 0 markets, falling back to memcmp\");\n const fallback = await connection.getProgramAccounts(programId, {\n filters: [\n {\n memcmp: {\n offset: 0,\n bytes: \"F6P2QNqpQV5\", // base58 of TALOCREP (u64 LE magic)\n },\n },\n ],\n dataSlice: { offset: 0, length: HEADER_SLICE_LENGTH },\n });\n // Unknown actual size — use large V0 as safe default (maxAccounts=4096)\n rawAccounts = [...fallback].map(e => ({ ...e, maxAccounts: 4096, dataSize: SLAB_TIERS.large.dataSize })) as RawEntry[];\n }\n } catch (err) {\n console.warn(\n \"[discoverMarkets] dataSize filters failed, falling back to memcmp:\",\n err instanceof Error ? err.message : err,\n );\n try {\n const fallback = await connection.getProgramAccounts(programId, {\n filters: [\n {\n memcmp: {\n offset: 0,\n bytes: \"F6P2QNqpQV5\", // base58 of TALOCREP (u64 LE magic)\n },\n },\n ],\n dataSlice: { offset: 0, length: HEADER_SLICE_LENGTH },\n });\n rawAccounts = [...fallback].map(e => ({ ...e, maxAccounts: 4096, dataSize: SLAB_TIERS.large.dataSize })) as RawEntry[];\n } catch (memcmpErr) {\n // GH#59: memcmp also rejected (public mainnet RPCs reject all getProgramAccounts)\n console.warn(\n \"[discoverMarkets] memcmp fallback also failed:\",\n memcmpErr instanceof Error ? memcmpErr.message : memcmpErr,\n );\n }\n }\n\n // GH#59 / PERC-8424: If getProgramAccounts returned nothing (public mainnet RPC\n // rejects it) and an API base URL is configured, fall back to the REST API to\n // discover slab addresses, then use getMarketsByAddress (getMultipleAccounts).\n if (rawAccounts.length === 0 && options.apiBaseUrl) {\n console.warn(\n \"[discoverMarkets] RPC discovery returned 0 markets, falling back to REST API\",\n );\n try {\n const apiResult = await discoverMarketsViaApi(\n connection,\n programId,\n options.apiBaseUrl,\n { timeoutMs: options.apiTimeoutMs },\n );\n if (apiResult.length > 0) {\n return apiResult;\n }\n // API returned 0 markets — fall through to tier 3\n console.warn(\n \"[discoverMarkets] REST API returned 0 markets, checking tier-3 static bundle\",\n );\n } catch (apiErr) {\n console.warn(\n \"[discoverMarkets] API fallback also failed:\",\n apiErr instanceof Error ? apiErr.message : apiErr,\n );\n // Fall through to tier 3\n }\n }\n\n // PERC-8435: Tier 3 — static bundle fallback. If both getProgramAccounts and\n // the REST API failed (or returned 0 results) and a network hint is provided,\n // use the bundled static market list as a last-resort address directory.\n if (rawAccounts.length === 0 && options.network) {\n const staticEntries = getStaticMarkets(options.network);\n if (staticEntries.length > 0) {\n console.warn(\n `[discoverMarkets] Tier 1+2 failed, falling back to static bundle (${staticEntries.length} addresses for ${options.network})`,\n );\n try {\n return await discoverMarketsViaStaticBundle(\n connection,\n programId,\n staticEntries,\n );\n } catch (staticErr) {\n console.warn(\n \"[discoverMarkets] Static bundle fallback also failed:\",\n staticErr instanceof Error ? staticErr.message : staticErr,\n );\n // Fall through to return empty array\n }\n } else {\n console.warn(\n `[discoverMarkets] Static bundle has 0 entries for ${options.network} — skipping tier 3`,\n );\n }\n }\n\n const accounts = rawAccounts;\n\n const markets: DiscoveredMarket[] = [];\n // GH#1115: deduplicate raw accounts by pubkey — the same slab can appear in multiple\n // tier queries if both V0 and V1 sizes match or if the RPC returns duplicate entries.\n const seenPubkeys = new Set<string>();\n\n for (const { pubkey, account, maxAccounts, dataSize } of accounts) {\n const pkStr = pubkey.toBase58();\n if (seenPubkeys.has(pkStr)) continue;\n seenPubkeys.add(pkStr);\n const data = new Uint8Array(account.data);\n\n let valid = true;\n for (let i = 0; i < MAGIC_BYTES.length; i++) {\n if (data[i] !== MAGIC_BYTES[i]) {\n valid = false;\n break;\n }\n }\n if (!valid) continue;\n\n // Detect layout from actual slab size — not slice length — so parse functions\n // get correct V0/V1 offsets even when working on the partial HEADER_SLICE_LENGTH slice.\n // Pass the data buffer so V2 slabs (same size as V1D) can be disambiguated via version field.\n const layout = detectSlabLayout(dataSize, data);\n\n if (!layout) {\n console.warn(\n `[discoverMarkets] Skipping account ${pkStr}: unrecognized layout for dataSize=${dataSize}`,\n );\n continue;\n }\n\n try {\n const header = parseHeader(data);\n const config = parseConfig(data, layout);\n const engine = parseEngineLight(data, layout, maxAccounts);\n const params = parseParams(data, layout);\n\n markets.push({ slabAddress: pubkey, programId, header, config, engine, params });\n } catch (err) {\n console.warn(\n `[discoverMarkets] Failed to parse account ${pubkey.toBase58()}:`,\n err instanceof Error ? err.message : err,\n );\n }\n }\n\n return markets;\n}\n\n/**\n * Options for `getMarketsByAddress`.\n */\nexport interface GetMarketsByAddressOptions {\n /**\n * Maximum number of addresses per `getMultipleAccounts` RPC call.\n * Solana limits a single call to 100 accounts; callers may lower this\n * to reduce per-request payload size or avoid 429s.\n *\n * Default: 100 (Solana maximum).\n */\n batchSize?: number;\n\n /**\n * Delay in ms between batches when the address list exceeds `batchSize`.\n * Helps avoid rate-limiting on public RPCs.\n *\n * Default: 0 (no delay).\n */\n interBatchDelayMs?: number;\n}\n\n/**\n * Fetch and parse Percolator markets by their known slab addresses.\n *\n * Unlike `discoverMarkets()` — which uses `getProgramAccounts` and is blocked\n * on public mainnet RPCs — this function uses `getMultipleAccounts`, which works\n * on any RPC endpoint (including `api.mainnet-beta.solana.com`).\n *\n * Callers must already know the market slab addresses (e.g. from an indexer,\n * a hardcoded registry, or a previous `discoverMarkets` call on a permissive RPC).\n *\n * @param connection - Solana RPC connection\n * @param programId - The Percolator program that owns these slabs\n * @param addresses - Array of slab account public keys to fetch\n * @param options - Optional batching/delay configuration\n * @returns Parsed markets for all valid slab accounts; invalid/missing accounts are silently skipped.\n *\n * @example\n * ```ts\n * import { getMarketsByAddress, getProgramId } from \"@percolator/sdk\";\n * import { Connection, PublicKey } from \"@solana/web3.js\";\n *\n * const connection = new Connection(\"https://api.mainnet-beta.solana.com\");\n * const programId = getProgramId(\"mainnet\");\n * const slabs = [\n * new PublicKey(\"So11111111111111111111111111111111111111112\"),\n * // ... more known slab addresses\n * ];\n *\n * const markets = await getMarketsByAddress(connection, programId, slabs);\n * console.log(`Found ${markets.length} markets`);\n * ```\n */\nexport async function getMarketsByAddress(\n connection: Connection,\n programId: PublicKey,\n addresses: PublicKey[],\n options: GetMarketsByAddressOptions = {},\n): Promise<DiscoveredMarket[]> {\n if (addresses.length === 0) return [];\n\n const {\n batchSize = 100,\n interBatchDelayMs = 0,\n } = options;\n\n const effectiveBatchSize = Math.max(1, Math.min(batchSize, 100));\n\n // Fetch account data in batches (Solana caps getMultipleAccounts at 100)\n type AccountResult = { pubkey: PublicKey; data: Buffer | Uint8Array } | null;\n const fetched: AccountResult[] = [];\n\n for (let offset = 0; offset < addresses.length; offset += effectiveBatchSize) {\n const batch = addresses.slice(offset, offset + effectiveBatchSize);\n\n const response = await connection.getMultipleAccountsInfo(batch);\n\n for (let i = 0; i < batch.length; i++) {\n const info = response[i];\n if (info && info.data) {\n if (!info.owner.equals(programId)) {\n console.warn(\n `[getMarketsByAddress] Skipping ${batch[i].toBase58()}: owner mismatch ` +\n `(expected ${programId.toBase58()}, got ${info.owner.toBase58()})`,\n );\n continue;\n }\n fetched.push({ pubkey: batch[i], data: info.data });\n }\n }\n\n // Inter-batch delay to avoid rate-limiting\n if (interBatchDelayMs > 0 && offset + effectiveBatchSize < addresses.length) {\n await new Promise(r => setTimeout(r, interBatchDelayMs));\n }\n }\n\n // Parse each account into a DiscoveredMarket\n const markets: DiscoveredMarket[] = [];\n\n for (const entry of fetched) {\n if (!entry) continue;\n const { pubkey, data: rawData } = entry;\n const data = new Uint8Array(rawData);\n\n // Validate magic bytes\n let valid = true;\n for (let i = 0; i < MAGIC_BYTES.length; i++) {\n if (data[i] !== MAGIC_BYTES[i]) {\n valid = false;\n break;\n }\n }\n if (!valid) {\n console.warn(\n `[getMarketsByAddress] Skipping ${pubkey.toBase58()}: invalid magic bytes`,\n );\n continue;\n }\n\n // Detect layout from full account data length\n const layout = detectSlabLayout(data.length, data);\n if (!layout) {\n console.warn(\n `[getMarketsByAddress] Skipping ${pubkey.toBase58()}: unrecognized layout for dataSize=${data.length}`,\n );\n continue;\n }\n\n try {\n const header = parseHeader(data);\n const config = parseConfig(data, layout);\n const engine = parseEngineLight(data, layout, layout.maxAccounts);\n const params = parseParams(data, layout);\n\n markets.push({ slabAddress: pubkey, programId, header, config, engine, params });\n } catch (err) {\n console.warn(\n `[getMarketsByAddress] Failed to parse account ${pubkey.toBase58()}:`,\n err instanceof Error ? err.message : err,\n );\n }\n }\n\n return markets;\n}\n\n// ---------------------------------------------------------------------------\n// REST API-based market discovery (GH#59 / PERC-8424)\n// ---------------------------------------------------------------------------\n\n/**\n * Shape of a single market entry returned by the Percolator REST API\n * (`GET /markets`). Only the fields needed for discovery are typed here;\n * the full API response may contain additional statistics fields.\n */\nexport interface ApiMarketEntry {\n slab_address: string;\n symbol?: string;\n name?: string;\n decimals?: number;\n status?: string;\n [key: string]: unknown;\n}\n\n/** Options for {@link discoverMarketsViaApi}. */\nexport interface DiscoverMarketsViaApiOptions {\n /**\n * Timeout in ms for the HTTP request to the REST API.\n * Default: 10_000 (10 seconds).\n */\n timeoutMs?: number;\n\n /**\n * Options forwarded to {@link getMarketsByAddress} for the on-chain fetch\n * step (batch size, inter-batch delay).\n */\n onChainOptions?: GetMarketsByAddressOptions;\n}\n\n/**\n * Discover Percolator markets by first querying the REST API for slab addresses,\n * then fetching full on-chain data via `getMarketsByAddress` (which uses\n * `getMultipleAccounts` — works on all RPCs including public mainnet nodes).\n *\n * This is the recommended discovery path for mainnet users who do not have a\n * Helius API key, since `getProgramAccounts` is rejected by public RPCs.\n *\n * The REST API acts as an address directory only — all market data is verified\n * on-chain via `getMarketsByAddress`, so the caller gets the same\n * `DiscoveredMarket[]` result as `discoverMarkets()`.\n *\n * @param connection - Solana RPC connection (any endpoint, including public)\n * @param programId - The Percolator program that owns the slabs\n * @param apiBaseUrl - Base URL of the Percolator REST API\n * (e.g. `\"https://percolatorlaunch.com/api\"`)\n * @param options - Optional timeout and on-chain fetch configuration\n * @returns Parsed markets for all valid slab accounts discovered via the API\n *\n * @example\n * ```ts\n * import { discoverMarketsViaApi, getProgramId } from \"@percolator/sdk\";\n * import { Connection } from \"@solana/web3.js\";\n *\n * const connection = new Connection(\"https://api.mainnet-beta.solana.com\");\n * const programId = getProgramId(\"mainnet\");\n * const markets = await discoverMarketsViaApi(\n * connection,\n * programId,\n * \"https://percolatorlaunch.com/api\",\n * );\n * console.log(`Discovered ${markets.length} markets via API fallback`);\n * ```\n */\nexport async function discoverMarketsViaApi(\n connection: Connection,\n programId: PublicKey,\n apiBaseUrl: string,\n options: DiscoverMarketsViaApiOptions = {},\n): Promise<DiscoveredMarket[]> {\n const { timeoutMs = 10_000, onChainOptions } = options;\n\n // Normalise base URL — strip trailing slash to avoid double-slash in path\n const base = apiBaseUrl.replace(/\\/+$/, \"\");\n const url = `${base}/markets`;\n\n // Fetch market list from REST API\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"GET\",\n headers: { Accept: \"application/json\" },\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n throw new Error(\n `[discoverMarketsViaApi] API returned ${response.status} ${response.statusText} from ${url}`,\n );\n }\n\n const body = (await response.json()) as { markets?: ApiMarketEntry[] };\n const apiMarkets = body.markets;\n\n if (!Array.isArray(apiMarkets) || apiMarkets.length === 0) {\n console.warn(\"[discoverMarketsViaApi] API returned 0 markets\");\n return [];\n }\n\n // Extract valid slab addresses\n const addresses: PublicKey[] = [];\n for (const entry of apiMarkets) {\n if (!entry.slab_address || typeof entry.slab_address !== \"string\") continue;\n try {\n addresses.push(new PublicKey(entry.slab_address));\n } catch {\n console.warn(\n `[discoverMarketsViaApi] Skipping invalid slab address: ${entry.slab_address}`,\n );\n }\n }\n\n if (addresses.length === 0) {\n console.warn(\"[discoverMarketsViaApi] No valid slab addresses from API\");\n return [];\n }\n\n console.log(\n `[discoverMarketsViaApi] API returned ${addresses.length} slab addresses, fetching on-chain data`,\n );\n\n // Fetch full on-chain data via getMultipleAccounts (works on all RPCs)\n return getMarketsByAddress(connection, programId, addresses, onChainOptions);\n}\n\n// ---------------------------------------------------------------------------\n// Static bundle fallback (PERC-8435 — tier 3)\n// ---------------------------------------------------------------------------\n\n/** Options for {@link discoverMarketsViaStaticBundle}. */\nexport interface DiscoverMarketsViaStaticBundleOptions {\n /**\n * Options forwarded to {@link getMarketsByAddress} for the on-chain fetch\n * step (batch size, inter-batch delay).\n */\n onChainOptions?: GetMarketsByAddressOptions;\n}\n\n/**\n * Discover Percolator markets from a static list of known slab addresses.\n *\n * This is the tier-3 (last-resort) fallback for `discoverMarkets()`. It uses\n * a bundled list of known slab addresses and fetches their full account data\n * on-chain via `getMarketsByAddress` (`getMultipleAccounts` — works on all RPCs).\n *\n * The static list acts as an address directory only — all market data is verified\n * on-chain, so stale entries are silently skipped (the account won't have valid\n * magic bytes or will have been closed).\n *\n * @param connection - Solana RPC connection (any endpoint)\n * @param programId - The Percolator program that owns the slabs\n * @param entries - Static market entries (typically from {@link getStaticMarkets})\n * @param options - Optional on-chain fetch configuration\n * @returns Parsed markets for all valid slab accounts; stale/missing entries are skipped.\n *\n * @example\n * ```ts\n * import {\n * discoverMarketsViaStaticBundle,\n * getStaticMarkets,\n * getProgramId,\n * } from \"@percolator/sdk\";\n * import { Connection } from \"@solana/web3.js\";\n *\n * const connection = new Connection(\"https://api.mainnet-beta.solana.com\");\n * const programId = getProgramId(\"mainnet\");\n * const entries = getStaticMarkets(\"mainnet\");\n *\n * const markets = await discoverMarketsViaStaticBundle(\n * connection,\n * programId,\n * entries,\n * );\n * console.log(`Recovered ${markets.length} markets from static bundle`);\n * ```\n */\nexport async function discoverMarketsViaStaticBundle(\n connection: Connection,\n programId: PublicKey,\n entries: StaticMarketEntry[],\n options: DiscoverMarketsViaStaticBundleOptions = {},\n): Promise<DiscoveredMarket[]> {\n if (entries.length === 0) return [];\n\n // Extract valid slab addresses from static entries\n const addresses: PublicKey[] = [];\n for (const entry of entries) {\n if (!entry.slabAddress || typeof entry.slabAddress !== \"string\") continue;\n try {\n addresses.push(new PublicKey(entry.slabAddress));\n } catch {\n console.warn(\n `[discoverMarketsViaStaticBundle] Skipping invalid slab address: ${entry.slabAddress}`,\n );\n }\n }\n\n if (addresses.length === 0) {\n console.warn(\"[discoverMarketsViaStaticBundle] No valid slab addresses in static bundle\");\n return [];\n }\n\n console.log(\n `[discoverMarketsViaStaticBundle] Fetching ${addresses.length} slab addresses on-chain`,\n );\n\n return getMarketsByAddress(connection, programId, addresses, options.onChainOptions);\n}\n","/**\n * Static market registry — bundled list of known Percolator slab addresses.\n *\n * This is the tier-3 fallback for `discoverMarkets()`: when both\n * `getProgramAccounts` (tier 1) and the REST API (tier 2) are unavailable,\n * the SDK falls back to this bundled list to bootstrap market discovery.\n *\n * The addresses are fetched on-chain via `getMarketsByAddress`\n * (`getMultipleAccounts`), so all data is still verified on-chain. The static\n * list only provides the *address directory* — no cached market data is used.\n *\n * ## Maintenance\n *\n * Update this list when new markets are deployed or old ones are retired.\n * Run `scripts/update-static-markets.ts` to regenerate from a permissive RPC\n * or the REST API.\n *\n * @module\n */\n\nimport { PublicKey } from \"@solana/web3.js\";\nimport type { Network } from \"../config/program-ids.js\";\n\n/**\n * A single entry in the static market registry.\n *\n * Only the slab address (base58) is required. Optional metadata fields\n * (`symbol`, `name`) are provided for debugging/logging purposes only —\n * they are **not** used for on-chain data and may become stale.\n */\nexport interface StaticMarketEntry {\n /** Base58-encoded slab account address. */\n slabAddress: string;\n /** Optional human-readable symbol (e.g. \"SOL-PERP\"). */\n symbol?: string;\n /** Optional descriptive name. */\n name?: string;\n}\n\n/**\n * Known mainnet market slab addresses.\n *\n * These are the markets deployed to the mainnet Percolator program\n * (`GM8zjJ8LTBMv9xEsverh6H6wLyevgMHEJXcEzyY3rY24`).\n *\n * **Last updated:** 2026-04-04 (pre-mainnet launch, populated from devnet\n * deployment addresses as placeholders — update with real mainnet addresses\n * once mainnet markets are live).\n */\nconst MAINNET_MARKETS: StaticMarketEntry[] = [\n // Populated at mainnet launch — currently empty.\n // To add entries:\n // { slabAddress: \"ABC123...\", symbol: \"SOL-PERP\", name: \"SOL Perpetual\" },\n];\n\n/**\n * Known devnet market slab addresses.\n *\n * These are discovered from the devnet Percolator program\n * (`FxfD37s1AZTeWfFQps9Zpebi2dNQ9QSSDtfMKdbsfKrD`).\n *\n * **Last updated:** 2026-04-04.\n */\nconst DEVNET_MARKETS: StaticMarketEntry[] = [\n // Populated from prior discoverMarkets() runs on devnet.\n // These serve as the tier-3 safety net for devnet users.\n];\n\n/**\n * Full static registry indexed by network.\n */\nconst STATIC_REGISTRY: Record<Network, StaticMarketEntry[]> = {\n mainnet: MAINNET_MARKETS,\n devnet: DEVNET_MARKETS,\n};\n\n/**\n * User-provided market entries appended at runtime via {@link registerStaticMarkets}.\n * Keyed by network.\n */\nconst USER_MARKETS: Record<Network, StaticMarketEntry[]> = {\n mainnet: [],\n devnet: [],\n};\n\n/**\n * Get the bundled static market list for a given network.\n *\n * Returns the built-in list merged with any entries added via\n * {@link registerStaticMarkets}. Duplicates (by `slabAddress`) are removed\n * automatically — user-registered entries take precedence.\n *\n * @param network - Target network (`\"mainnet\"` or `\"devnet\"`)\n * @returns Array of static market entries (may be empty if no markets are known)\n *\n * @example\n * ```ts\n * import { getStaticMarkets } from \"@percolator/sdk\";\n *\n * const markets = getStaticMarkets(\"mainnet\");\n * console.log(`${markets.length} known mainnet slab addresses`);\n * ```\n */\nexport function getStaticMarkets(network: Network): StaticMarketEntry[] {\n const builtin = STATIC_REGISTRY[network] ?? [];\n const user = USER_MARKETS[network] ?? [];\n\n if (user.length === 0) return [...builtin];\n\n // Merge: user entries override builtin entries with same slabAddress\n const seen = new Map<string, StaticMarketEntry>();\n for (const entry of builtin) {\n seen.set(entry.slabAddress, entry);\n }\n for (const entry of user) {\n seen.set(entry.slabAddress, entry);\n }\n return [...seen.values()];\n}\n\n/**\n * Register additional static market entries at runtime.\n *\n * Use this to inject known slab addresses before calling `discoverMarkets()`\n * so that tier-3 fallback has addresses to work with — especially useful\n * right after mainnet launch when the bundled list may be empty.\n *\n * Entries are deduplicated by `slabAddress` — calling this multiple times\n * with the same address is safe.\n *\n * @param network - Target network\n * @param entries - One or more static market entries to register\n *\n * @example\n * ```ts\n * import { registerStaticMarkets } from \"@percolator/sdk\";\n *\n * registerStaticMarkets(\"mainnet\", [\n * { slabAddress: \"ABC123...\", symbol: \"SOL-PERP\" },\n * { slabAddress: \"DEF456...\", symbol: \"ETH-PERP\" },\n * ]);\n * ```\n */\nexport function registerStaticMarkets(\n network: Network,\n entries: StaticMarketEntry[],\n): void {\n const existing = USER_MARKETS[network];\n const seen = new Set(existing.map(e => e.slabAddress));\n\n for (const entry of entries) {\n if (!entry.slabAddress) continue;\n if (seen.has(entry.slabAddress)) continue;\n // Validate that slabAddress is a valid base58 public key\n try {\n new PublicKey(entry.slabAddress);\n } catch {\n console.warn(\n `[registerStaticMarkets] Skipping invalid slabAddress: ${entry.slabAddress}`,\n );\n continue;\n }\n seen.add(entry.slabAddress);\n existing.push(entry);\n }\n}\n\n/**\n * Clear all user-registered static market entries for a network.\n *\n * Useful in tests or when resetting state.\n *\n * @param network - Target network to clear (omit to clear all networks)\n */\nexport function clearStaticMarkets(network?: Network): void {\n if (network) {\n USER_MARKETS[network] = [];\n } else {\n USER_MARKETS.mainnet = [];\n USER_MARKETS.devnet = [];\n }\n}\n","import { PublicKey } from \"@solana/web3.js\";\nimport {\n PUMPSWAP_PROGRAM_ID,\n RAYDIUM_CLMM_PROGRAM_ID,\n METEORA_DLMM_PROGRAM_ID,\n} from \"./pda.js\";\n\nexport type DexType = \"pumpswap\" | \"raydium-clmm\" | \"meteora-dlmm\";\n\nexport interface DexPoolInfo {\n dexType: DexType;\n poolAddress: PublicKey;\n baseMint: PublicKey;\n quoteMint: PublicKey;\n baseVault?: PublicKey; // PumpSwap only\n quoteVault?: PublicKey; // PumpSwap only\n}\n\n/**\n * Detect DEX type from the program that owns the pool account.\n *\n * @param ownerProgramId - The program ID that owns the pool account\n * @returns The detected DEX type, or `null` if the owner is not a supported DEX program\n *\n * Supported DEX programs:\n * - PumpSwap (constant-product AMM)\n * - Raydium CLMM (concentrated liquidity)\n * - Meteora DLMM (discretized liquidity)\n */\nexport function detectDexType(ownerProgramId: PublicKey): DexType | null {\n if (ownerProgramId.equals(PUMPSWAP_PROGRAM_ID)) return \"pumpswap\";\n if (ownerProgramId.equals(RAYDIUM_CLMM_PROGRAM_ID)) return \"raydium-clmm\";\n if (ownerProgramId.equals(METEORA_DLMM_PROGRAM_ID)) return \"meteora-dlmm\";\n return null;\n}\n\n/**\n * Parse a DEX pool account into a {@link DexPoolInfo} struct.\n *\n * @param dexType - The type of DEX (pumpswap, raydium-clmm, or meteora-dlmm)\n * @param poolAddress - The on-chain address of the pool account\n * @param data - Raw account data bytes\n * @returns Parsed pool info including mints and (for PumpSwap) vault addresses\n * @throws Error if data is too short for the given DEX type\n */\nexport function parseDexPool(\n dexType: DexType,\n poolAddress: PublicKey,\n data: Uint8Array,\n): DexPoolInfo {\n switch (dexType) {\n case \"pumpswap\":\n return parsePumpSwapPool(poolAddress, data);\n case \"raydium-clmm\":\n return parseRaydiumClmmPool(poolAddress, data);\n case \"meteora-dlmm\":\n return parseMeteoraPool(poolAddress, data);\n }\n}\n\n/**\n * Compute the spot price from a DEX pool in e6 format (i.e., 1.0 = 1_000_000).\n *\n * **SECURITY NOTE:** DEX spot prices have no staleness or confidence checks and are\n * vulnerable to flash-loan manipulation within a single transaction. For high-value\n * markets, prefer Pyth or Chainlink oracles.\n *\n * @param dexType - The type of DEX\n * @param data - Raw pool account data\n * @param vaultData - For PumpSwap only: base and quote vault account data\n * @returns Price in e6 format (quote per base token)\n * @throws Error if data is too short or computation fails\n */\nexport function computeDexSpotPriceE6(\n dexType: DexType,\n data: Uint8Array,\n vaultData?: { base: Uint8Array; quote: Uint8Array },\n): bigint {\n switch (dexType) {\n case \"pumpswap\":\n if (!vaultData) throw new Error(\"PumpSwap requires vaultData (base and quote vault accounts)\");\n return computePumpSwapPriceE6(data, vaultData);\n case \"raydium-clmm\":\n return computeRaydiumClmmPriceE6(data);\n case \"meteora-dlmm\":\n return computeMeteoraDlmmPriceE6(data);\n }\n}\n\n// ============================================================================\n// PumpSwap\n// ============================================================================\n\nconst PUMPSWAP_MIN_LEN = 195;\n\n/**\n * Parse a PumpSwap constant-product AMM pool account.\n * @internal\n */\nfunction parsePumpSwapPool(poolAddress: PublicKey, data: Uint8Array): DexPoolInfo {\n if (data.length < PUMPSWAP_MIN_LEN) {\n throw new Error(`PumpSwap pool data too short: ${data.length} < ${PUMPSWAP_MIN_LEN}`);\n }\n return {\n dexType: \"pumpswap\",\n poolAddress,\n baseMint: new PublicKey(data.slice(35, 67)),\n quoteMint: new PublicKey(data.slice(67, 99)),\n baseVault: new PublicKey(data.slice(131, 163)),\n quoteVault: new PublicKey(data.slice(163, 195)),\n };\n}\n\nconst SPL_TOKEN_AMOUNT_MIN_LEN = 72;\n\n/**\n * Compute PumpSwap price: quote_amount * 1e6 / base_amount.\n * @internal\n */\nfunction computePumpSwapPriceE6(\n _poolData: Uint8Array,\n vaultData: { base: Uint8Array; quote: Uint8Array },\n): bigint {\n if (vaultData.base.length < SPL_TOKEN_AMOUNT_MIN_LEN) {\n throw new Error(`PumpSwap base vault data too short: ${vaultData.base.length} < ${SPL_TOKEN_AMOUNT_MIN_LEN}`);\n }\n if (vaultData.quote.length < SPL_TOKEN_AMOUNT_MIN_LEN) {\n throw new Error(`PumpSwap quote vault data too short: ${vaultData.quote.length} < ${SPL_TOKEN_AMOUNT_MIN_LEN}`);\n }\n\n const baseDv = new DataView(vaultData.base.buffer, vaultData.base.byteOffset, vaultData.base.byteLength);\n const quoteDv = new DataView(vaultData.quote.buffer, vaultData.quote.byteOffset, vaultData.quote.byteLength);\n\n const baseAmount = readU64LE(baseDv, 64);\n const quoteAmount = readU64LE(quoteDv, 64);\n\n if (baseAmount === 0n) return 0n;\n return (quoteAmount * 1_000_000n) / baseAmount;\n}\n\n// ============================================================================\n// Raydium CLMM\n// ============================================================================\n\nconst RAYDIUM_CLMM_MIN_LEN = 269; // need at least through sqrt_price_x64 (253 + 16)\n\n/**\n * Parse a Raydium CLMM (concentrated liquidity) pool account.\n * @internal\n */\nfunction parseRaydiumClmmPool(poolAddress: PublicKey, data: Uint8Array): DexPoolInfo {\n if (data.length < RAYDIUM_CLMM_MIN_LEN) {\n throw new Error(`Raydium CLMM pool data too short: ${data.length} < ${RAYDIUM_CLMM_MIN_LEN}`);\n }\n return {\n dexType: \"raydium-clmm\",\n poolAddress,\n baseMint: new PublicKey(data.slice(73, 105)),\n quoteMint: new PublicKey(data.slice(105, 137)),\n };\n}\n\n/**\n * Compute Raydium CLMM spot price from sqrt_price_x64 (Q64.64 fixed-point).\n *\n * Formula: `price_e6 = (sqrt^2 / 2^128) * 10^(6 + decimals0 - decimals1)`\n *\n * Uses a precision-preserving approach: scales sqrt by 1e6 before shifting,\n * preventing zero results for micro-priced tokens (memecoins where sqrt < 2^64).\n *\n * @internal\n */\nconst MAX_TOKEN_DECIMALS = 24;\n\nfunction computeRaydiumClmmPriceE6(data: Uint8Array): bigint {\n if (data.length < RAYDIUM_CLMM_MIN_LEN) {\n throw new Error(`Raydium CLMM data too short: ${data.length} < ${RAYDIUM_CLMM_MIN_LEN}`);\n }\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\n const decimals0 = data[233];\n const decimals1 = data[234];\n\n if (decimals0 > MAX_TOKEN_DECIMALS || decimals1 > MAX_TOKEN_DECIMALS) {\n throw new Error(\n `Raydium CLMM: decimals out of range (${decimals0}, ${decimals1}); max ${MAX_TOKEN_DECIMALS}`,\n );\n }\n\n const sqrtPriceX64 = readU128LE(dv, 253);\n\n if (sqrtPriceX64 === 0n) return 0n;\n\n // Compute (sqrtPriceX64^2 * 1e6) >> 128 directly using BigInt arbitrary\n // precision. The previous split-shift approach truncated small sqrtPriceX64\n // values (memecoins) to zero due to intermediate >> 64n losing all bits.\n const priceE6Raw = (sqrtPriceX64 * sqrtPriceX64 * 1_000_000n) >> 128n;\n\n const decimalDiff = 6 + decimals0 - decimals1;\n const adjustedDiff = decimalDiff - 6;\n\n if (adjustedDiff >= 0) {\n const scale = 10n ** BigInt(adjustedDiff);\n return priceE6Raw * scale;\n } else {\n const scale = 10n ** BigInt(-adjustedDiff);\n return priceE6Raw / scale;\n }\n}\n\n// ============================================================================\n// Meteora DLMM\n// ============================================================================\n\nconst METEORA_DLMM_MIN_LEN = 145;\n\n/**\n * Parse a Meteora DLMM (discretized liquidity) pool account.\n * @internal\n */\nfunction parseMeteoraPool(poolAddress: PublicKey, data: Uint8Array): DexPoolInfo {\n if (data.length < METEORA_DLMM_MIN_LEN) {\n throw new Error(`Meteora DLMM pool data too short: ${data.length} < ${METEORA_DLMM_MIN_LEN}`);\n }\n return {\n dexType: \"meteora-dlmm\",\n poolAddress,\n baseMint: new PublicKey(data.slice(81, 113)),\n quoteMint: new PublicKey(data.slice(113, 145)),\n };\n}\n\n/**\n * Compute Meteora DLMM spot price from active_id and bin_step.\n *\n * Formula: `price = (1 + bin_step/10000) ^ active_id`\n *\n * Uses binary exponentiation with 1e18 fixed-point precision, then converts to e6.\n * For negative active_id, computes the inverse.\n *\n * @internal\n */\nconst MAX_BIN_STEP = 10_000;\nconst MAX_ACTIVE_ID_ABS = 500_000;\n\nfunction computeMeteoraDlmmPriceE6(data: Uint8Array): bigint {\n if (data.length < METEORA_DLMM_MIN_LEN) {\n throw new Error(`Meteora DLMM data too short: ${data.length} < ${METEORA_DLMM_MIN_LEN}`);\n }\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\n const binStep = dv.getUint16(73, true);\n const activeId = dv.getInt32(76, true);\n\n if (binStep === 0) return 0n;\n if (binStep > MAX_BIN_STEP) {\n throw new Error(`Meteora DLMM: binStep ${binStep} exceeds max ${MAX_BIN_STEP}`);\n }\n if (Math.abs(activeId) > MAX_ACTIVE_ID_ABS) {\n throw new Error(\n `Meteora DLMM: |activeId| ${Math.abs(activeId)} exceeds max ${MAX_ACTIVE_ID_ABS}`,\n );\n }\n\n const MAX_ABS_BIN_ID = 500_000;\n if (activeId > MAX_ABS_BIN_ID || activeId < -MAX_ABS_BIN_ID) {\n throw new Error(\n `Meteora DLMM: activeId ${activeId} exceeds safe range (±${MAX_ABS_BIN_ID})`,\n );\n }\n\n const SCALE = 1_000_000_000_000_000_000n; // 1e18\n const base = SCALE + (BigInt(binStep) * SCALE) / 10_000n;\n\n const isNeg = activeId < 0;\n let exp = isNeg ? BigInt(-activeId) : BigInt(activeId);\n\n let result = SCALE;\n let b = base;\n\n // Limit iterations to ~21 for safety (log2(500_000) + buffer)\n let iterations = 0;\n const MAX_ITERATIONS = 25;\n\n while (exp > 0n) {\n if (iterations++ >= MAX_ITERATIONS) {\n throw new Error(\n `Meteora DLMM: exponentiation loop exceeded ${MAX_ITERATIONS} iterations (activeId=${activeId})`,\n );\n }\n if (exp & 1n) {\n result = (result * b) / SCALE;\n }\n exp >>= 1n;\n if (exp > 0n) {\n b = (b * b) / SCALE;\n }\n }\n\n if (isNeg) {\n if (result === 0n) return 0n;\n return (SCALE * 1_000_000n) / result;\n } else {\n return result / 1_000_000_000_000n; // 1e18 → 1e6\n }\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/** Read a little-endian u64 from a DataView. */\nfunction readU64LE(dv: DataView, offset: number): bigint {\n const lo = BigInt(dv.getUint32(offset, true));\n const hi = BigInt(dv.getUint32(offset + 4, true));\n return lo | (hi << 32n);\n}\n\n/** Read a little-endian u128 from a DataView. */\nfunction readU128LE(dv: DataView, offset: number): bigint {\n const lo = readU64LE(dv, offset);\n const hi = readU64LE(dv, offset + 8);\n return lo | (hi << 64n);\n}\n","/**\n * Oracle account parsing utilities.\n *\n * Chainlink aggregator layout on Solana (from Toly's percolator-cli):\n * offset 138: decimals (u8)\n * offset 216: latest answer (i64 LE)\n *\n * Minimum account size: 224 bytes (offset 216 + 8 bytes for i64).\n *\n * These utilities validate oracle data BEFORE parsing to prevent silent\n * propagation of stale or malformed Chainlink data as price.\n */\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Minimum buffer size to read Chainlink price data */\nconst CHAINLINK_MIN_SIZE = 224; // 216 + 8\n\n/** Maximum reasonable decimals for a price feed */\nconst MAX_DECIMALS = 18;\n\n/** Offset of decimals field in Chainlink aggregator account */\nconst CHAINLINK_DECIMALS_OFFSET = 138;\n\n/** Offset of updated_at timestamp (i64 LE, Unix seconds) in Chainlink aggregator */\nconst CHAINLINK_TIMESTAMP_OFFSET = 168;\n\n/** Offset of latest answer in Chainlink aggregator account */\nconst CHAINLINK_ANSWER_OFFSET = 216;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface OraclePrice {\n price: bigint;\n decimals: number;\n /** Unix timestamp (seconds) of the last oracle update, if available. */\n updatedAt?: number;\n}\n\nexport interface ParseChainlinkOptions {\n /** Maximum allowed staleness in seconds. If the oracle update is older, an error is thrown. */\n maxStalenessSeconds?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Browser-compatible read helpers using DataView\n// ---------------------------------------------------------------------------\n\nfunction readU8(data: Uint8Array, off: number): number {\n return data[off];\n}\n\nfunction readBigInt64LE(data: Uint8Array, off: number): bigint {\n return new DataView(data.buffer, data.byteOffset, data.byteLength).getBigInt64(off, true);\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Parse price data from a Chainlink aggregator account buffer.\n *\n * Validates:\n * - Buffer is large enough to contain the required fields (≥ 224 bytes)\n * - Decimals are in a reasonable range (0-18)\n * - Price is positive (non-zero)\n *\n * @param data - Raw account data from Chainlink aggregator\n * @returns Parsed oracle price with decimals\n * @throws if the buffer is invalid or contains unreasonable data\n */\nexport function parseChainlinkPrice(data: Uint8Array, options?: ParseChainlinkOptions): OraclePrice {\n if (data.length < CHAINLINK_MIN_SIZE) {\n throw new Error(\n `Oracle account data too small: ${data.length} bytes (need at least ${CHAINLINK_MIN_SIZE})`\n );\n }\n\n const decimals = readU8(data, CHAINLINK_DECIMALS_OFFSET);\n if (decimals > MAX_DECIMALS) {\n throw new Error(\n `Oracle decimals out of range: ${decimals} (max ${MAX_DECIMALS})`\n );\n }\n\n const price = readBigInt64LE(data, CHAINLINK_ANSWER_OFFSET);\n if (price <= 0n) {\n throw new Error(\n `Oracle price is non-positive: ${price}`\n );\n }\n\n // Read updated_at timestamp (i64 LE at offset 168)\n const updatedAtBig = readBigInt64LE(data, CHAINLINK_TIMESTAMP_OFFSET);\n const updatedAt = Number(updatedAtBig);\n\n if (options?.maxStalenessSeconds !== undefined && updatedAt > 0) {\n const now = Math.floor(Date.now() / 1000);\n const age = now - updatedAt;\n if (age > options.maxStalenessSeconds) {\n throw new Error(\n `Oracle price is stale: last updated ${age}s ago (max ${options.maxStalenessSeconds}s)`\n );\n }\n }\n\n return { price, decimals, updatedAt: updatedAt > 0 ? updatedAt : undefined };\n}\n\n/**\n * Validate that a buffer looks like a valid Chainlink aggregator account.\n * Returns true if the buffer passes all validation checks, false otherwise.\n * Use this for non-throwing validation.\n */\nexport function isValidChainlinkOracle(data: Uint8Array): boolean {\n try {\n parseChainlinkPrice(data);\n return true;\n } catch {\n return false;\n }\n}\n\n// Re-export constants for consumers\nexport { CHAINLINK_MIN_SIZE, CHAINLINK_DECIMALS_OFFSET, CHAINLINK_TIMESTAMP_OFFSET, CHAINLINK_ANSWER_OFFSET, MAX_DECIMALS };\n","import { Connection, PublicKey } from \"@solana/web3.js\";\nimport { TOKEN_PROGRAM_ID } from \"@solana/spl-token\";\n\n/**\n * Token2022 (Token Extensions) program ID.\n */\nexport const TOKEN_2022_PROGRAM_ID = new PublicKey(\n \"TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb\",\n);\n\n/**\n * Detect which token program owns a given mint account.\n * Returns the owner program ID (TOKEN_PROGRAM_ID or TOKEN_2022_PROGRAM_ID).\n * Throws if the mint account doesn't exist.\n */\nexport async function detectTokenProgram(\n connection: Connection,\n mint: PublicKey,\n): Promise<PublicKey> {\n const info = await connection.getAccountInfo(mint);\n if (!info) throw new Error(`Mint account not found: ${mint.toBase58()}`);\n\n if (info.owner.equals(TOKEN_PROGRAM_ID)) return TOKEN_PROGRAM_ID;\n if (info.owner.equals(TOKEN_2022_PROGRAM_ID)) return TOKEN_2022_PROGRAM_ID;\n\n throw new Error(\n `Mint ${mint.toBase58()} is owned by ${info.owner.toBase58()}, ` +\n `which is neither TOKEN_PROGRAM_ID nor TOKEN_2022_PROGRAM_ID`,\n );\n}\n\n/**\n * Check if a given token program ID is Token2022.\n */\nexport function isToken2022(tokenProgramId: PublicKey): boolean {\n return tokenProgramId.equals(TOKEN_2022_PROGRAM_ID);\n}\n\n/**\n * Check if a given token program ID is the standard SPL Token program.\n */\nexport function isStandardToken(tokenProgramId: PublicKey): boolean {\n return tokenProgramId.equals(TOKEN_PROGRAM_ID);\n}\n","/**\n * @module stake\n * Percolator Insurance LP Staking program — instruction encoders, PDA derivation, and account specs.\n *\n * Program: percolator-stake (dcccrypto/percolator-stake)\n * Deployed devnet: 6aJb1F9CDCVWCNYFwj8aQsVb696YnW6J1FznteHq4Q6k\n * Deployed mainnet: (pending deployment — DevOps must set STAKE_PROGRAM_ID env var or deploy and update STAKE_PROGRAM_IDS.mainnet)\n */\n\nimport { PublicKey, SystemProgram, SYSVAR_RENT_PUBKEY, SYSVAR_CLOCK_PUBKEY } from '@solana/web3.js';\nimport { TOKEN_PROGRAM_ID } from '@solana/spl-token';\nimport { safeEnv } from '../config/program-ids.js';\nimport { concatBytes } from '../abi/encode.js';// ═══════════════════════════════════════════════════════════════\n// Program ID — network-conditional (mirrors program-ids.ts pattern)\n// ═══════════════════════════════════════════════════════════════\n\n/** Known stake program addresses per network. */\nexport const STAKE_PROGRAM_IDS = {\n devnet: '6aJb1F9CDCVWCNYFwj8aQsVb696YnW6J1FznteHq4Q6k',\n mainnet: 'DC5fovFQD5SZYsetwvEqd4Wi4PFY1Yfnc669VMe6oa7F',\n} as const;\n\n/**\n * Resolve the stake program ID for the given network.\n *\n * Priority:\n * 1. STAKE_PROGRAM_ID env var (explicit override — DevOps sets this for mainnet until constant is filled)\n * 2. Network-specific constant from STAKE_PROGRAM_IDS\n *\n * Throws a clear error on mainnet when no address is available so callers\n * surface the gap instead of silently hitting the devnet program.\n */\nexport function getStakeProgramId(network?: 'devnet' | 'mainnet'): PublicKey {\n const override = safeEnv('STAKE_PROGRAM_ID');\n if (override) {\n console.warn(\n `[percolator-sdk] STAKE_PROGRAM_ID env override active: ${override} — ensure this points to a trusted program`,\n );\n return new PublicKey(override);\n }\n\n const detectedNetwork =\n network ??\n (() => {\n const n = safeEnv('NEXT_PUBLIC_DEFAULT_NETWORK')?.toLowerCase() ??\n safeEnv('NETWORK')?.toLowerCase() ?? '';\n return n === 'mainnet' || n === 'mainnet-beta' ? 'mainnet' : 'devnet';\n })();\n\n const id = STAKE_PROGRAM_IDS[detectedNetwork];\n if (!id) {\n throw new Error(\n `Stake program not deployed on ${detectedNetwork}. ` +\n `Set STAKE_PROGRAM_ID env var or wait for DevOps to deploy and update STAKE_PROGRAM_IDS.mainnet.`,\n );\n }\n return new PublicKey(id);\n}\n\n/**\n * Default export — resolves for the current runtime network.\n * Use getStakeProgramId() with an explicit network argument where possible.\n *\n * @deprecated Direct use of STAKE_PROGRAM_ID is being phased out in favour of\n * getStakeProgramId() so mainnet callers get a clear error rather than silently\n * resolving to the devnet address.\n */\nexport const STAKE_PROGRAM_ID = new PublicKey(STAKE_PROGRAM_IDS.devnet);\n\n// ═══════════════════════════════════════════════════════════════\n// Instruction Tags (match src/instruction.rs)\n// ═══════════════════════════════════════════════════════════════\n\nexport const STAKE_IX = {\n InitPool: 0,\n Deposit: 1,\n Withdraw: 2,\n FlushToInsurance: 3,\n UpdateConfig: 4,\n TransferAdmin: 5,\n AdminSetOracleAuthority: 6,\n AdminSetRiskThreshold: 7,\n AdminSetMaintenanceFee: 8,\n AdminResolveMarket: 9,\n AdminWithdrawInsurance: 10,\n AdminSetInsurancePolicy: 11,\n /** PERC-272: Accrue trading fees to LP vault */\n AccrueFees: 12,\n /** PERC-272: Init pool in trading LP mode */\n InitTradingPool: 13,\n /** PERC-313: Set HWM config (enable + floor bps) */\n AdminSetHwmConfig: 14,\n /** PERC-303: Enable/configure senior-junior LP tranches */\n AdminSetTrancheConfig: 15,\n /** PERC-303: Deposit into junior (first-loss) tranche */\n DepositJunior: 16,\n} as const;\n\n// ═══════════════════════════════════════════════════════════════\n// PDA Derivation\n// ═══════════════════════════════════════════════════════════════\n\nconst TEXT = new TextEncoder();\n\n/** Derive the stake pool PDA for a given slab (market). */\nexport function deriveStakePool(slab: PublicKey, programId?: PublicKey) {\n return PublicKey.findProgramAddressSync(\n [TEXT.encode('stake_pool'), slab.toBytes()], programId ?? getStakeProgramId(), );\n}\n\n/** Derive the vault authority PDA (signs CPI, owns LP mint + vault). */\nexport function deriveStakeVaultAuth(pool: PublicKey, programId?: PublicKey) {\n return PublicKey.findProgramAddressSync(\n [TEXT.encode('vault_auth'), pool.toBytes()], programId ?? getStakeProgramId(), );\n}\n\n/** Derive the per-user deposit PDA (tracks cooldown, deposit time). */\nexport function deriveDepositPda(pool: PublicKey, user: PublicKey, programId?: PublicKey) {\n return PublicKey.findProgramAddressSync(\n [TEXT.encode('deposit'), pool.toBytes(), user.toBytes()], programId ?? getStakeProgramId(), );\n}\n\n// ═══════════════════════════════════════════════════════════════\n// Browser-safe binary helpers (DataView, no Node.js Buffer dependency)// ═══════════════════════════════════════════════════════════════\n\n/** Read a u64 little-endian from a Uint8Array at the given offset. */\nfunction readU64LE(data: Uint8Array, off: number): bigint {\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n return view.getBigUint64(off, /* littleEndian= */ true);\n}\n\n/** Read a u16 little-endian from a Uint8Array at the given offset. */\nfunction readU16LE(data: Uint8Array, off: number): number {\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n return view.getUint16(off, /* littleEndian= */ true);\n}\n\n// ═══════════════════════════════════════════════════════════════\n// Instruction Encoders\n// ═══════════════════════════════════════════════════════════════\n\nfunction u64Le(v: bigint | number): Uint8Array {\n if (typeof v === \"number\" && !Number.isSafeInteger(v)) {\n throw new Error(`u64Le: number ${v} exceeds Number.MAX_SAFE_INTEGER — use BigInt`);\n }\n const big = BigInt(v);\n if (big < 0n) throw new Error(`u64Le: value must be non-negative, got ${big}`);\n if (big > 0xFFFF_FFFF_FFFF_FFFFn) throw new Error(`u64Le: value exceeds u64 max`);\n const arr = new Uint8Array(8);\n new DataView(arr.buffer).setBigUint64(0, big, true); return arr;\n}\n\nfunction u128Le(v: bigint | number): Uint8Array {\n if (typeof v === \"number\" && !Number.isSafeInteger(v)) {\n throw new Error(`u128Le: number ${v} exceeds Number.MAX_SAFE_INTEGER — use BigInt`);\n }\n const big = BigInt(v);\n if (big < 0n) throw new Error(`u128Le: value must be non-negative, got ${big}`);\n if (big > (1n << 128n) - 1n) throw new Error(`u128Le: value exceeds u128 max`);\n const arr = new Uint8Array(16);\n const view = new DataView(arr.buffer); view.setBigUint64(0, big & 0xFFFFFFFFFFFFFFFFn, true);\n view.setBigUint64(8, big >> 64n, true);\n return arr;\n}\n\nfunction u16Le(v: number): Uint8Array {\n if (!Number.isInteger(v) || v < 0 || v > 0xFFFF) throw new Error(`u16Le: value must be integer in range 0..65535, got ${v}`); const arr = new Uint8Array(2); new DataView(arr.buffer).setUint16(0, v, true);\n return arr;\n}\n\n/** Tag 0: InitPool — create stake pool for a slab. */\nexport function encodeStakeInitPool(cooldownSlots: bigint | number, depositCap: bigint | number): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.InitPool]),\n u64Le(cooldownSlots),\n u64Le(depositCap),\n );\n}\n\n/** Tag 1: Deposit — deposit collateral, receive LP tokens. */\nexport function encodeStakeDeposit(amount: bigint | number): Uint8Array {\n return concatBytes(new Uint8Array([STAKE_IX.Deposit]), u64Le(amount));\n}\n\n/** Tag 2: Withdraw — burn LP tokens, receive collateral (subject to cooldown). */\nexport function encodeStakeWithdraw(lpAmount: bigint | number): Uint8Array {\n return concatBytes(new Uint8Array([STAKE_IX.Withdraw]), u64Le(lpAmount));\n}\n\n/** Tag 3: FlushToInsurance — move collateral from stake vault to wrapper insurance. */\nexport function encodeStakeFlushToInsurance(amount: bigint | number): Uint8Array {\n return concatBytes(new Uint8Array([STAKE_IX.FlushToInsurance]), u64Le(amount));\n}\n\n/** Tag 4: UpdateConfig — update cooldown and/or deposit cap. */\nexport function encodeStakeUpdateConfig(\n newCooldownSlots?: bigint | number,\n newDepositCap?: bigint | number,\n): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.UpdateConfig]),\n new Uint8Array([newCooldownSlots != null ? 1 : 0]),\n u64Le(newCooldownSlots ?? 0n),\n new Uint8Array([newDepositCap != null ? 1 : 0]),\n u64Le(newDepositCap ?? 0n),\n );\n}\n\n/** Tag 5: TransferAdmin — transfer wrapper admin to pool PDA. */\nexport function encodeStakeTransferAdmin(): Uint8Array {\n return new Uint8Array([STAKE_IX.TransferAdmin]);\n}\n\n/** Tag 6: AdminSetOracleAuthority — forward to wrapper via CPI. */\nexport function encodeStakeAdminSetOracleAuthority(newAuthority: PublicKey): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.AdminSetOracleAuthority]),\n newAuthority.toBytes(),\n );\n}\n\n/** Tag 7: AdminSetRiskThreshold — forward to wrapper via CPI. */\nexport function encodeStakeAdminSetRiskThreshold(newThreshold: bigint | number): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.AdminSetRiskThreshold]),\n u128Le(newThreshold),\n );\n}\n\n/** Tag 8: AdminSetMaintenanceFee — forward to wrapper via CPI. */\nexport function encodeStakeAdminSetMaintenanceFee(newFee: bigint | number): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.AdminSetMaintenanceFee]),\n u128Le(newFee),\n );\n}\n\n/** Tag 9: AdminResolveMarket — forward to wrapper via CPI. */\nexport function encodeStakeAdminResolveMarket(): Uint8Array {\n return new Uint8Array([STAKE_IX.AdminResolveMarket]);\n}\n\n/** Tag 10: AdminWithdrawInsurance — withdraw insurance after market resolution. */\nexport function encodeStakeAdminWithdrawInsurance(amount: bigint | number): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.AdminWithdrawInsurance]),\n u64Le(amount),\n );\n}\n\n/** Tag 12: AccrueFees — permissionless: accrue trading fees to LP vault. */\nexport function encodeStakeAccrueFees(): Uint8Array {\n return new Uint8Array([STAKE_IX.AccrueFees]);\n}\n\n/** Tag 13: InitTradingPool — create pool in trading LP mode (pool_mode = 1). */\nexport function encodeStakeInitTradingPool(cooldownSlots: bigint | number, depositCap: bigint | number): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.InitTradingPool]),\n u64Le(cooldownSlots),\n u64Le(depositCap),\n );\n}\n\n/** Tag 14 (PERC-313): AdminSetHwmConfig — enable HWM protection and set floor BPS. */\nexport function encodeStakeAdminSetHwmConfig(\n enabled: boolean,\n hwmFloorBps: number,\n): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.AdminSetHwmConfig]),\n new Uint8Array([enabled ? 1 : 0]),\n u16Le(hwmFloorBps),\n );\n}\n\n/** Tag 15 (PERC-303): AdminSetTrancheConfig — enable senior/junior LP tranches. */\nexport function encodeStakeAdminSetTrancheConfig(juniorFeeMultBps: number): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.AdminSetTrancheConfig]),\n u16Le(juniorFeeMultBps),\n );\n}\n\n/** Tag 16 (PERC-303): DepositJunior — deposit into first-loss junior tranche. */\nexport function encodeStakeDepositJunior(amount: bigint | number): Uint8Array {\n return concatBytes(new Uint8Array([STAKE_IX.DepositJunior]), u64Le(amount));\n}\n\n/** Tag 11: AdminSetInsurancePolicy — set withdrawal policy on wrapper. */\nexport function encodeStakeAdminSetInsurancePolicy(\n authority: PublicKey,\n minWithdrawBase: bigint | number,\n maxWithdrawBps: number,\n cooldownSlots: bigint | number,\n): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.AdminSetInsurancePolicy]),\n authority.toBytes(),\n u64Le(minWithdrawBase),\n u16Le(maxWithdrawBps),\n u64Le(cooldownSlots),\n );\n}\n\n// ═══════════════════════════════════════════════════════════════\n// On-Chain State Layout — StakePool decoded fields\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Decoded StakePool state (352 bytes on-chain).\n * Includes PERC-272 (fee yield), PERC-313 (HWM), and PERC-303 (tranches).\n */\nexport interface StakePoolState {\n isInitialized: boolean;\n bump: number;\n vaultAuthorityBump: number;\n adminTransferred: boolean;\n\n slab: PublicKey;\n admin: PublicKey;\n collateralMint: PublicKey;\n lpMint: PublicKey;\n vault: PublicKey;\n\n totalDeposited: bigint;\n totalLpSupply: bigint;\n cooldownSlots: bigint;\n depositCap: bigint;\n totalFlushed: bigint;\n totalReturned: bigint;\n totalWithdrawn: bigint;\n\n percolatorProgram: PublicKey;\n\n // PERC-272: Fee yield fields\n totalFeesEarned: bigint;\n lastFeeAccrualSlot: bigint;\n lastVaultSnapshot: bigint;\n poolMode: number;\n\n // _reserved layout (64 bytes):\n // [0..8] discriminator\n // [8] version\n // [9..32] PERC-313 HWM\n // [32..51] PERC-303 tranches\n // [51..64] free\n\n // PERC-313: HWM fields (from _reserved[9..32])\n hwmEnabled: boolean;\n epochHighWaterTvl: bigint;\n hwmFloorBps: number;\n\n // PERC-303: Tranche fields (from _reserved[32..51])\n trancheEnabled: boolean;\n juniorBalance: bigint;\n juniorTotalLp: bigint;\n juniorFeeMultBps: number;\n}\n\n/** Size of StakePool on-chain (bytes). */\nexport const STAKE_POOL_SIZE = 352;\n\n/**\n * Decode a StakePool account from raw data buffer. * Uses DataView for all u64/u16 reads — browser-safe.\n */\nexport function decodeStakePool(data: Uint8Array): StakePoolState {\n if (data.length < STAKE_POOL_SIZE) {\n throw new Error(`StakePool data too short: ${data.length} < ${STAKE_POOL_SIZE}`);\n }\n const bytes = new Uint8Array(data.buffer, data.byteOffset, data.byteLength); let off = 0;\n const isInitialized = bytes[off] === 1; off += 1;\n const bump = bytes[off]; off += 1;\n const vaultAuthorityBump = bytes[off]; off += 1;\n const adminTransferred = bytes[off] === 1; off += 1;\n off += 4; // _padding\n\n const slab = new PublicKey(bytes.subarray(off, off + 32)); off += 32;\n const admin = new PublicKey(bytes.subarray(off, off + 32)); off += 32;\n const collateralMint = new PublicKey(bytes.subarray(off, off + 32)); off += 32;\n const lpMint = new PublicKey(bytes.subarray(off, off + 32)); off += 32;\n const vault = new PublicKey(bytes.subarray(off, off + 32)); off += 32;\n\n const totalDeposited = readU64LE(bytes, off); off += 8;\n const totalLpSupply = readU64LE(bytes, off); off += 8;\n const cooldownSlots = readU64LE(bytes, off); off += 8;\n const depositCap = readU64LE(bytes, off); off += 8;\n const totalFlushed = readU64LE(bytes, off); off += 8;\n const totalReturned = readU64LE(bytes, off); off += 8;\n const totalWithdrawn = readU64LE(bytes, off); off += 8;\n\n const percolatorProgram = new PublicKey(bytes.subarray(off, off + 32)); off += 32;\n\n // PERC-272 fields\n const totalFeesEarned = readU64LE(bytes, off); off += 8;\n const lastFeeAccrualSlot = readU64LE(bytes, off); off += 8;\n const lastVaultSnapshot = readU64LE(bytes, off); off += 8;\n const poolMode = bytes[off]; off += 1;\n off += 7; // _mode_padding\n\n // _reserved (64 bytes) starts at off\n const reservedStart = off;\n // _reserved[8] = version (skipped)\n // PERC-313: _reserved[9] = hwm_enabled, [10..26] = epoch_high_water_tvl (u128), [26..28] = hwm_floor_bps (u16)\n const hwmEnabled = bytes[reservedStart + 9] === 1;\n // Read u128 as two u64 parts\n const hwmTvlLow = readU64LE(bytes, reservedStart + 10);\n const hwmTvlHigh = readU64LE(bytes, reservedStart + 18);\n const epochHighWaterTvl = hwmTvlLow | (hwmTvlHigh << 64n);\n const hwmFloorBps = readU16LE(bytes, reservedStart + 26);\n\n // PERC-303: _reserved[32] = tranche_enabled, [33..41] = junior_balance, [41..49] = junior_total_lp, [49..51] = junior_fee_mult_bps\n const trancheEnabled = bytes[reservedStart + 32] === 1;\n const juniorBalance = readU64LE(bytes, reservedStart + 33);\n const juniorTotalLp = readU64LE(bytes, reservedStart + 41);\n const juniorFeeMultBps = readU16LE(bytes, reservedStart + 49);\n\n return {\n isInitialized,\n bump,\n vaultAuthorityBump,\n adminTransferred,\n slab,\n admin,\n collateralMint,\n lpMint,\n vault,\n totalDeposited,\n totalLpSupply,\n cooldownSlots,\n depositCap,\n totalFlushed,\n totalReturned,\n totalWithdrawn,\n percolatorProgram,\n totalFeesEarned,\n lastFeeAccrualSlot,\n lastVaultSnapshot,\n poolMode,\n hwmEnabled,\n epochHighWaterTvl,\n hwmFloorBps,\n trancheEnabled,\n juniorBalance,\n juniorTotalLp,\n juniorFeeMultBps,\n };\n}\n\n// ═══════════════════════════════════════════════════════════════\n// Account Specs (for building TransactionInstructions)\n// ═══════════════════════════════════════════════════════════════\n\nexport interface StakeAccounts {\n /** InitPool accounts */\n initPool: {\n admin: PublicKey;\n slab: PublicKey;\n pool: PublicKey;\n lpMint: PublicKey;\n vault: PublicKey;\n vaultAuth: PublicKey;\n collateralMint: PublicKey;\n percolatorProgram: PublicKey;\n };\n /** Deposit accounts */\n deposit: {\n user: PublicKey;\n pool: PublicKey;\n userCollateralAta: PublicKey;\n vault: PublicKey;\n lpMint: PublicKey;\n userLpAta: PublicKey;\n vaultAuth: PublicKey;\n depositPda: PublicKey;\n };\n /** Withdraw accounts */\n withdraw: {\n user: PublicKey;\n pool: PublicKey;\n userLpAta: PublicKey;\n lpMint: PublicKey;\n vault: PublicKey;\n userCollateralAta: PublicKey;\n vaultAuth: PublicKey;\n depositPda: PublicKey;\n };\n /** FlushToInsurance accounts (CPI from stake → percolator) */\n flushToInsurance: {\n caller: PublicKey;\n pool: PublicKey;\n vault: PublicKey;\n vaultAuth: PublicKey;\n slab: PublicKey;\n wrapperVault: PublicKey;\n percolatorProgram: PublicKey;\n };\n}\n\n/**\n * Build account keys for InitPool instruction.\n * Returns array of {pubkey, isSigner, isWritable} in the order the program expects.\n */\nexport function initPoolAccounts(a: StakeAccounts['initPool']) {\n return [\n { pubkey: a.admin, isSigner: true, isWritable: true },\n { pubkey: a.slab, isSigner: false, isWritable: false },\n { pubkey: a.pool, isSigner: false, isWritable: true },\n { pubkey: a.lpMint, isSigner: false, isWritable: true },\n { pubkey: a.vault, isSigner: false, isWritable: true },\n { pubkey: a.vaultAuth, isSigner: false, isWritable: false },\n { pubkey: a.collateralMint, isSigner: false, isWritable: false },\n { pubkey: a.percolatorProgram, isSigner: false, isWritable: false },\n { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },\n { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },\n { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },\n ];\n}\n\n/**\n * Build account keys for Deposit instruction.\n */\nexport function depositAccounts(a: StakeAccounts['deposit']) {\n return [\n { pubkey: a.user, isSigner: true, isWritable: false },\n { pubkey: a.pool, isSigner: false, isWritable: true },\n { pubkey: a.userCollateralAta, isSigner: false, isWritable: true },\n { pubkey: a.vault, isSigner: false, isWritable: true },\n { pubkey: a.lpMint, isSigner: false, isWritable: true },\n { pubkey: a.userLpAta, isSigner: false, isWritable: true },\n { pubkey: a.vaultAuth, isSigner: false, isWritable: false },\n { pubkey: a.depositPda, isSigner: false, isWritable: true },\n { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },\n { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },\n { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },\n ];\n}\n\n/**\n * Build account keys for Withdraw instruction.\n */\nexport function withdrawAccounts(a: StakeAccounts['withdraw']) {\n return [\n { pubkey: a.user, isSigner: true, isWritable: false },\n { pubkey: a.pool, isSigner: false, isWritable: true },\n { pubkey: a.userLpAta, isSigner: false, isWritable: true },\n { pubkey: a.lpMint, isSigner: false, isWritable: true },\n { pubkey: a.vault, isSigner: false, isWritable: true },\n { pubkey: a.userCollateralAta, isSigner: false, isWritable: true },\n { pubkey: a.vaultAuth, isSigner: false, isWritable: false },\n { pubkey: a.depositPda, isSigner: false, isWritable: true },\n { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },\n { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },\n ];\n}\n\n/**\n * Build account keys for FlushToInsurance instruction.\n */\nexport function flushToInsuranceAccounts(a: StakeAccounts['flushToInsurance']) {\n return [\n { pubkey: a.caller, isSigner: true, isWritable: false },\n { pubkey: a.pool, isSigner: false, isWritable: true },\n { pubkey: a.vault, isSigner: false, isWritable: true },\n { pubkey: a.vaultAuth, isSigner: false, isWritable: false },\n { pubkey: a.slab, isSigner: false, isWritable: true },\n { pubkey: a.wrapperVault, isSigner: false, isWritable: true },\n { pubkey: a.percolatorProgram, isSigner: false, isWritable: false },\n { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },\n ];\n}\n","import { PublicKey } from \"@solana/web3.js\";\n\n/**\n * Read an environment variable safely. Returns `undefined` in browser\n * environments where `process` is not defined, avoiding a\n * `ReferenceError` crash at import time.\n */\nexport function safeEnv(key: string): string | undefined {\n try {\n return typeof process !== \"undefined\" && process?.env\n ? process.env[key]\n : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Centralized PROGRAM_ID configuration\n * \n * Default to environment variable, then fall back to network-specific defaults.\n * This prevents hard-coded program IDs scattered across the codebase.\n */\n\nexport const PROGRAM_IDS = {\n devnet: {\n percolator: \"FxfD37s1AZTeWfFQps9Zpebi2dNQ9QSSDtfMKdbsfKrD\",\n matcher: \"GTRgyTDfrMvBubALAqtHuQwT8tbGyXid7svXZKtWfC9k\",\n },\n mainnet: {\n percolator: \"GM8zjJ8LTBMv9xEsverh6H6wLyevgMHEJXcEzyY3rY24\",\n matcher: \"DHP6DtwXP1yJsz8YzfoeigRFPB979gzmumkmCxDLSkUX\",\n },\n} as const;\n\nexport type Network = \"devnet\" | \"mainnet\";\n\n/**\n * Get the Percolator program ID for the current network\n * \n * Priority:\n * 1. PROGRAM_ID env var (explicit override)\n * 2. Network-specific default (NETWORK env var)\n * 3. Devnet default (safest fallback — bug bounty PERC-697)\n */\nexport function getProgramId(network?: Network): PublicKey {\n // Only allow env override when no explicit network is provided —\n // an explicit parameter should always take precedence to prevent\n // silent program substitution via environment variable injection.\n if (!network) {\n const override = safeEnv(\"PROGRAM_ID\");\n if (override) {\n console.warn(\n `[percolator-sdk] PROGRAM_ID env override active: ${override} — ensure this points to a trusted program`,\n );\n return new PublicKey(override);\n }\n }\n\n // Use provided network or detect from env — default to devnet (never mainnet silently)\n const detectedNetwork = getCurrentNetwork();\n const targetNetwork = network ?? detectedNetwork;\n const programId = PROGRAM_IDS[targetNetwork].percolator;\n\n return new PublicKey(programId);\n}\n\n/**\n * Get the Matcher program ID for the current network\n */\nexport function getMatcherProgramId(network?: Network): PublicKey {\n if (!network) {\n const override = safeEnv(\"MATCHER_PROGRAM_ID\");\n if (override) {\n console.warn(\n `[percolator-sdk] MATCHER_PROGRAM_ID env override active: ${override} — ensure this points to a trusted program`,\n );\n return new PublicKey(override);\n }\n }\n\n // Use provided network or detect from env — default to devnet (never mainnet silently)\n const detectedNetwork = getCurrentNetwork();\n const targetNetwork = network ?? detectedNetwork;\n const programId = PROGRAM_IDS[targetNetwork].matcher;\n\n if (!programId) {\n throw new Error(`Matcher program not deployed on ${targetNetwork}`);\n }\n\n return new PublicKey(programId);\n}\n\n/**\n * Get the current network from environment.\n *\n * SECURITY (PERC-697): Removed silent mainnet default.\n * Previously defaulted to \"mainnet\" when NETWORK was unset, which could cause\n * crank/keeper scripts run without env vars to silently target mainnet program IDs.\n *\n * Now defaults to \"devnet\" — the safer fallback for a devnet-first protocol.\n * Production deployments always set NETWORK explicitly via Railway/env.\n * For mainnet operations use networkValidation.ts (ensureNetworkConfigValid) which\n * enforces FORCE_MAINNET=1.\n */\nexport function getCurrentNetwork(): Network {\n const network = safeEnv(\"NETWORK\")?.toLowerCase();\n if (network === \"mainnet\" || network === \"mainnet-beta\") {\n return \"mainnet\";\n }\n // devnet, testnet, or unset → devnet (fail-open to devnet, not mainnet)\n return \"devnet\";\n}\n","/**\n * @module adl\n * Percolator ADL (Auto-Deleveraging) client utilities.\n *\n * PERC-8278 / PERC-8312 / PERC-305: ADL is triggered when `pnl_pos_tot > max_pnl_cap`\n * on a market (PnL cap exceeded) AND the insurance fund is fully depleted (balance == 0).\n * The most profitable positions on the dominant side are deleveraged first.\n *\n * **Note on caller permissions:** `ExecuteAdl` (tag 50) requires the caller to be the\n * market admin/keeper key (`header.admin`). It is NOT permissionless despite the\n * instruction being structurally available to any signer.\n *\n * API surface:\n * - fetchAdlRankedPositions() — fetch slab + rank all open positions by PnL%\n * - rankAdlPositions() — pure (no-RPC) variant for already-fetched slab bytes\n * - isAdlTriggered() — check if slab's pnl_pos_tot exceeds max_pnl_cap\n * - buildAdlInstruction() — build a single ExecuteAdl TransactionInstruction\n * - buildAdlTransaction() — fetch + rank + pick top target + return instruction\n * - parseAdlEvent() — decode AdlEvent from transaction log lines\n * - fetchAdlRankings() — call /api/adl/rankings HTTP endpoint\n * - AdlRankedPosition — position record with adl_rank and computed pnlPct\n * - AdlRankingResult — full ranking with trigger status\n * - AdlEvent — decoded on-chain AdlEvent log entry (tag 0xAD1E_0001)\n * - AdlApiRanking — single ranked position from /api/adl/rankings\n * - AdlApiResult — full result from /api/adl/rankings\n * - AdlSide — \"long\" | \"short\"\n */\n\nimport {\n Connection,\n PublicKey,\n TransactionInstruction,\n AccountMeta,\n SYSVAR_CLOCK_PUBKEY,\n} from \"@solana/web3.js\";\nimport {\n fetchSlab,\n parseAllAccounts,\n parseEngine,\n parseConfig,\n detectSlabLayout,\n AccountKind,\n Account,\n SlabLayout,\n} from \"./slab.js\";\nimport { encodeExecuteAdl } from \"../abi/instructions.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Position side derived from positionSize sign. */\nexport type AdlSide = \"long\" | \"short\";\n\n/**\n * A ranked open position for ADL purposes.\n * Positions are ranked descending by `pnlPct` — rank 0 is the most profitable\n * and will be deleveraged first.\n */\nexport interface AdlRankedPosition {\n /** Account index in the slab (used as `targetIdx` in ExecuteAdl). */\n idx: number;\n /** Owner public key. */\n owner: PublicKey;\n /** Raw position size (i128 — negative = short, positive = long). */\n positionSize: bigint;\n /** Realised + mark-to-market PnL in lamports (i128 from slab). */\n pnl: bigint;\n /** Capital at entry in lamports (u128). */\n capital: bigint;\n /**\n * PnL as a fraction of capital, expressed as basis points (scaled × 10_000).\n * pnlPct = pnl * 10_000 / capital.\n * Higher = more profitable = deleveraged first.\n */\n pnlPct: bigint;\n /** Long or short. */\n side: AdlSide;\n /**\n * ADL rank among positions on the same side (0 = highest PnL%, deleveraged first).\n * `-1` if position size is zero (inactive).\n */\n adlRank: number;\n}\n\n/**\n * Result of `fetchAdlRankedPositions`.\n */\nexport interface AdlRankingResult {\n /** All open (non-zero) user positions, sorted descending by PnLPct, ranked. */\n ranked: AdlRankedPosition[];\n /**\n * Longs ranked separately (adlRank within this subset).\n * Rank 0 = most profitable long = first to be deleveraged on a net-long market.\n */\n longs: AdlRankedPosition[];\n /**\n * Shorts ranked separately (adlRank within this subset).\n * Rank 0 = most profitable short (most negative pnlPct magnitude — i.e., highest\n * unrealised gain for the short-side holder).\n */\n shorts: AdlRankedPosition[];\n /** Whether ADL is currently triggered (pnlPosTot > maxPnlCap). */\n isTriggered: boolean;\n /** pnl_pos_tot from engine state. */\n pnlPosTot: bigint;\n /** max_pnl_cap from market config. */\n maxPnlCap: bigint;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Compute PnL% in basis points for a position.\n * Returns 0n when capital is 0 to avoid division by zero.\n */\nfunction computePnlPct(pnl: bigint, capital: bigint): bigint {\n if (capital === 0n) return 0n;\n return (pnl * 10_000n) / capital;\n}\n\n// ---------------------------------------------------------------------------\n// Core API\n// ---------------------------------------------------------------------------\n\n/**\n * Check whether ADL is currently triggered on a slab.\n *\n * ADL triggers when pnl_pos_tot > max_pnl_cap (max_pnl_cap must be > 0).\n *\n * @param slabData - Raw slab account bytes.\n * @returns true if ADL is triggered.\n *\n * @example\n * ```ts\n * const data = await fetchSlab(connection, slabKey);\n * if (isAdlTriggered(data)) {\n * const ranking = await fetchAdlRankedPositions(connection, slabKey);\n * }\n * ```\n */\nexport function isAdlTriggered(slabData: Uint8Array): boolean {\n const layout = detectSlabLayout(slabData.length);\n if (!layout) {\n return false;\n }\n try {\n const engine = parseEngine(slabData);\n if (engine.pnlPosTot === 0n) return false;\n const config = parseConfig(slabData, layout);\n if (config.maxPnlCap === 0n) return false;\n return engine.pnlPosTot > config.maxPnlCap;\n } catch {\n return false;\n }\n}\n\n/**\n * Fetch a slab and rank all open user positions by PnL% for ADL targeting.\n *\n * Positions are ranked separately per side:\n * - Longs: rank 0 = highest positive PnL% (most profitable long)\n * - Shorts: rank 0 = highest negative PnL% by abs value (most profitable short)\n *\n * Rank ordering matches the on-chain ADL engine in percolator-prog (PERC-8273):\n * the position at rank 0 of the dominant side is deleveraged first.\n *\n * @param connection - Solana connection.\n * @param slab - Slab (market) public key.\n * @returns AdlRankingResult with ranked longs, ranked shorts, and trigger status.\n *\n * @example\n * ```ts\n * const { ranked, longs, isTriggered } = await fetchAdlRankedPositions(connection, slabKey);\n * if (isTriggered && longs.length > 0) {\n * const target = longs[0]; // highest PnL long\n * const ix = buildAdlInstruction(caller, slabKey, oracleKey, programId, target.idx);\n * }\n * ```\n */\nexport async function fetchAdlRankedPositions(\n connection: Connection,\n slab: PublicKey\n): Promise<AdlRankingResult> {\n const data = await fetchSlab(connection, slab);\n return rankAdlPositions(data);\n}\n\n/**\n * Pure (no-RPC) variant — rank positions from already-fetched slab bytes.\n * Useful when you already have the slab data (e.g., from a subscription).\n */\nexport function rankAdlPositions(slabData: Uint8Array): AdlRankingResult {\n const layout = detectSlabLayout(slabData.length);\n\n let pnlPosTot = 0n;\n try {\n const engine = parseEngine(slabData);\n pnlPosTot = engine.pnlPosTot;\n } catch (err) {\n console.warn(\n `[rankAdlPositions] parseEngine failed:`,\n err instanceof Error ? err.message : err,\n );\n }\n\n let maxPnlCap = 0n;\n let isTriggered = false;\n if (layout) {\n try {\n const config = parseConfig(slabData, layout);\n maxPnlCap = config.maxPnlCap;\n isTriggered = maxPnlCap > 0n && pnlPosTot > maxPnlCap;\n } catch {\n // If config parse fails, leave isTriggered=false; ranking still useful.\n }\n }\n\n // Parse all used accounts.\n const accounts = parseAllAccounts(slabData);\n\n // Build ranked position list (user accounts with non-zero position only).\n const positions: AdlRankedPosition[] = [];\n for (const { idx, account } of accounts) {\n if (account.kind !== AccountKind.User) continue;\n if (account.positionSize === 0n) continue;\n\n // Determine side from sign convention: long (> 0), short (< 0).\n // If positionSize is 0, it was already skipped above.\n const side: AdlSide = account.positionSize > 0n ? \"long\" : \"short\";\n\n // Validate sign convention: longs must be positive, shorts must be negative.\n if (side === \"long\" && account.positionSize <= 0n) {\n console.warn(`[fetchAdlRankedPositions] account idx=${idx}: side=long but positionSize=${account.positionSize}`);\n continue;\n }\n if (side === \"short\" && account.positionSize >= 0n) {\n console.warn(`[fetchAdlRankedPositions] account idx=${idx}: side=short but positionSize=${account.positionSize}`);\n continue;\n }\n\n // For shorts, positionSize is negative — PnL computation is symmetric:\n // a short profits when price falls, so pnl stored in the slab already\n // reflects mark-to-market gain/loss for both sides.\n const pnlPct = computePnlPct(account.pnl, account.capital);\n\n positions.push({\n idx,\n owner: account.owner,\n positionSize: account.positionSize,\n pnl: account.pnl,\n capital: account.capital,\n pnlPct,\n side,\n adlRank: -1, // assigned below\n });\n }\n\n // Rank longs: descending pnlPct (most profitable first).\n const longs = positions\n .filter(p => p.side === \"long\")\n .sort((a, b) => (b.pnlPct > a.pnlPct ? 1 : b.pnlPct < a.pnlPct ? -1 : 0));\n longs.forEach((p, i) => { p.adlRank = i; });\n\n // Rank shorts: descending pnlPct (most profitable short = highest pnlPct\n // magnitude, but pnlPct can be negative; sort descending still puts\n // the \"least negative\" aka \"most profitable\" short first).\n const shorts = positions\n .filter(p => p.side === \"short\")\n .sort((a, b) => (b.pnlPct > a.pnlPct ? 1 : b.pnlPct < a.pnlPct ? -1 : 0));\n shorts.forEach((p, i) => { p.adlRank = i; });\n\n // Overall ranked list = longs + shorts merged, still sorted by pnlPct desc.\n const ranked = [...longs, ...shorts].sort(\n (a, b) => (b.pnlPct > a.pnlPct ? 1 : b.pnlPct < a.pnlPct ? -1 : 0)\n );\n\n return { ranked, longs, shorts, isTriggered, pnlPosTot, maxPnlCap };\n}\n\n/**\n * Build a single `ExecuteAdl` TransactionInstruction (tag 50, PERC-305).\n *\n * Does NOT fetch the slab or check trigger status — use `fetchAdlRankedPositions`\n * first to determine the correct `targetIdx`.\n *\n * **Caller requirement:** The on-chain handler requires the caller to be the market\n * admin/keeper authority (`header.admin`). Passing any other signer will result in\n * `EngineUnauthorized`.\n *\n * @param caller - Signer — must be the market keeper/admin authority.\n * @param slab - Slab (market) public key.\n * @param oracle - Primary oracle public key for this market.\n * @param programId - Percolator program ID.\n * @param targetIdx - Account index to deleverage (from `AdlRankedPosition.idx`).\n * @param backupOracles - Optional additional oracle accounts (non-Hyperp markets).\n *\n * @example\n * ```ts\n * import { fetchAdlRankedPositions, buildAdlInstruction } from \"@percolator/sdk\";\n *\n * const { longs, isTriggered } = await fetchAdlRankedPositions(connection, slabKey);\n * if (isTriggered && longs.length > 0) {\n * const ix = buildAdlInstruction(\n * caller.publicKey, slabKey, oracleKey, PROGRAM_ID, longs[0].idx\n * );\n * await sendAndConfirmTransaction(connection, new Transaction().add(ix), [caller]);\n * }\n * ```\n */\nexport function buildAdlInstruction(\n caller: PublicKey,\n slab: PublicKey,\n oracle: PublicKey,\n programId: PublicKey,\n targetIdx: number,\n backupOracles: PublicKey[] = []\n): TransactionInstruction {\n if (!Number.isInteger(targetIdx) || targetIdx < 0) {\n throw new Error(\n `buildAdlInstruction: targetIdx must be a non-negative integer, got ${targetIdx}`,\n );\n }\n const dataBytes = encodeExecuteAdl({ targetIdx });\n const data = Buffer.from(dataBytes);\n\n const keys: AccountMeta[] = [\n { pubkey: caller, isSigner: true, isWritable: false },\n { pubkey: slab, isSigner: false, isWritable: true },\n { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },\n { pubkey: oracle, isSigner: false, isWritable: false },\n ...backupOracles.map(k => ({ pubkey: k, isSigner: false, isWritable: false })),\n ];\n\n return new TransactionInstruction({ keys, programId, data });\n}\n\n/**\n * Convenience builder: fetch slab, rank positions, pick the highest-ranked\n * target on the given side, and return a ready-to-send `TransactionInstruction`.\n *\n * Returns `null` when ADL is not triggered or no eligible positions exist.\n *\n * @param connection - Solana connection.\n * @param caller - Signer — must be the market keeper/admin authority.\n * @param slab - Slab (market) public key.\n * @param oracle - Primary oracle public key.\n * @param programId - Percolator program ID.\n * @param preferSide - Optional: target \"long\" or \"short\" side only.\n * If omitted, picks the overall top-ranked position.\n * @param backupOracles - Optional extra oracle accounts.\n *\n * @example\n * ```ts\n * const ix = await buildAdlTransaction(\n * connection, caller.publicKey, slabKey, oracleKey, PROGRAM_ID\n * );\n * if (ix) {\n * await sendAndConfirmTransaction(connection, new Transaction().add(ix), [caller]);\n * }\n * ```\n */\nexport async function buildAdlTransaction(\n connection: Connection,\n caller: PublicKey,\n slab: PublicKey,\n oracle: PublicKey,\n programId: PublicKey,\n preferSide?: AdlSide,\n backupOracles: PublicKey[] = []\n): Promise<TransactionInstruction | null> {\n const ranking = await fetchAdlRankedPositions(connection, slab);\n\n if (!ranking.isTriggered) return null;\n\n let target: AdlRankedPosition | undefined;\n if (preferSide === \"long\") {\n target = ranking.longs[0];\n } else if (preferSide === \"short\") {\n target = ranking.shorts[0];\n } else {\n target = ranking.ranked[0];\n }\n\n if (!target) return null;\n\n return buildAdlInstruction(caller, slab, oracle, programId, target.idx, backupOracles);\n}\n\n// ---------------------------------------------------------------------------\n// AdlEvent — on-chain log decoder (PERC-8312)\n// ---------------------------------------------------------------------------\n\n/**\n * Decoded on-chain AdlEvent emitted by the `ExecuteAdl` instruction handler.\n *\n * The on-chain handler emits via `sol_log_64(0xAD1E_0001, target_idx, price, closed_lo, closed_hi)`.\n * `sol_log_64` prints 5 decimal u64 values separated by spaces on a single \"Program log:\" line.\n *\n * Fields:\n * - `tag` — always `0xAD1E_0001` (2970353665n)\n * - `targetIdx` — slab account index that was deleveraged\n * - `price` — oracle price used (in market price units, e.g. e6)\n * - `closedAbs` — absolute size of the position closed (i128, reassembled from lo+hi u64 parts)\n *\n * @example\n * ```ts\n * const logs = tx.meta?.logMessages ?? [];\n * const event = parseAdlEvent(logs);\n * if (event) {\n * console.log(\"ADL closed position\", event.targetIdx, \"size\", event.closedAbs);\n * }\n * ```\n */\nexport interface AdlEvent {\n /** Tag discriminator — always 0xAD1E_0001n (2970353665). */\n tag: bigint;\n /** Slab account index that was deleveraged. */\n targetIdx: number;\n /** Oracle price used for the deleverage (market-native units, e.g. lamports/e6). */\n price: bigint;\n /**\n * Absolute position size closed (reassembled from lo+hi u64).\n * This is the i128 absolute value — always non-negative.\n */\n closedAbs: bigint;\n}\n\n/** Magic discriminator for the ADL event log line. */\nconst ADL_EVENT_TAG = 0xAD1E_0001n;\n\n/**\n * Parse the AdlEvent from a transaction's log messages.\n *\n * Searches for a \"Program log: <a> <b> <c> <d> <e>\" line where the first\n * decimal value equals `0xAD1E_0001` (2970353665). Returns `null` if not found.\n *\n * @param logs - Array of log message strings (from `tx.meta.logMessages`).\n * @returns Decoded `AdlEvent` or `null` if the log is not present.\n *\n * @example\n * ```ts\n * const event = parseAdlEvent(tx.meta?.logMessages ?? []);\n * if (event) {\n * console.log(`ADL: idx=${event.targetIdx} price=${event.price} closed=${event.closedAbs}`);\n * }\n * ```\n */\nexport function parseAdlEvent(logs: string[]): AdlEvent | null {\n for (const line of logs) {\n if (typeof line !== \"string\") continue;\n // sol_log_64 emits: \"Program log: a b c d e\" (5 space-separated decimals)\n const match = line.match(\n /^Program log: (\\d+) (\\d+) (\\d+) (\\d+) (\\d+)$/,\n );\n if (!match) continue;\n\n let tag: bigint;\n try {\n tag = BigInt(match[1]);\n } catch {\n continue;\n }\n\n if (tag !== ADL_EVENT_TAG) continue;\n\n try {\n const targetIdxBig = BigInt(match[2]);\n // Validate that targetIdx fits in u16 range before converting to Number\n if (targetIdxBig < 0n || targetIdxBig > 65535n) {\n continue;\n }\n const targetIdx = Number(targetIdxBig);\n const price = BigInt(match[3]);\n const closedLo = BigInt(match[4]);\n const closedHi = BigInt(match[5]);\n // Reassemble i128 from lo/hi u64 parts (little-endian split).\n const closedAbs = (closedHi << 64n) | closedLo;\n return { tag, targetIdx, price, closedAbs };\n } catch {\n continue;\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// fetchAdlRankings — HTTP client for /api/adl/rankings (PERC-8312)\n// ---------------------------------------------------------------------------\n\n/**\n * A single ranked position as returned by the /api/adl/rankings endpoint.\n */\nexport interface AdlApiRanking {\n /** 1-based rank (1 = highest PnL%, first to be deleveraged). */\n rank: number;\n /** Slab account index. Pass as `targetIdx` to `buildAdlInstruction`. */\n idx: number;\n /** Absolute PnL (lamports) as a decimal string. */\n pnlAbs: string;\n /** Capital at entry (lamports) as a decimal string. */\n capital: string;\n /** PnL as millionths of capital (pnl * 1_000_000 / capital). */\n pnlPctMillionths: string;\n}\n\n/**\n * Full result from the /api/adl/rankings endpoint.\n */\nexport interface AdlApiResult {\n slabAddress: string;\n /** pnl_pos_tot from slab engine state (decimal string). */\n pnlPosTot: string;\n /** max_pnl_cap from market config (decimal string, \"0\" if unconfigured). */\n maxPnlCap: string;\n /** Insurance fund balance (decimal string). */\n insuranceFundBalance: string;\n /** Insurance fund lifetime fee revenue (decimal string). */\n insuranceFundFeeRevenue: string;\n /** Insurance utilization in basis points (0–10000). */\n insuranceUtilizationBps: number;\n /** true if pnlPosTot > maxPnlCap. */\n capExceeded: boolean;\n /** true if insurance fund is fully depleted (balance == 0). */\n insuranceDepleted: boolean;\n /** true if utilization BPS exceeds the configured ADL threshold. */\n utilizationTriggered: boolean;\n /** true if ADL is needed (capExceeded or utilizationTriggered). */\n adlNeeded: boolean;\n /** Excess PnL above cap (decimal string). */\n excess: string;\n /** Ranked positions (empty if adlNeeded=false). */\n rankings: AdlApiRanking[];\n}\n\n/**\n * Fetch ADL rankings from the Percolator API.\n *\n * Calls `GET <apiBase>/api/adl/rankings?slab=<address>` and returns the\n * parsed result. Use this from the frontend or keeper to determine ADL\n * trigger status and pick the target index.\n *\n * @param apiBase - Base URL of the Percolator API (e.g. `https://api.percolator.io`).\n * @param slab - Slab (market) public key or base58 address string.\n * @param fetchFn - Optional custom fetch implementation (defaults to global `fetch`).\n * @returns Parsed `AdlApiResult`.\n * @throws On HTTP error or JSON parse failure.\n *\n * @example\n * ```ts\n * const result = await fetchAdlRankings(\"https://api.percolator.io\", slabKey);\n * if (result.adlNeeded && result.rankings.length > 0) {\n * const target = result.rankings[0]; // rank 1 = highest PnL%\n * const ix = buildAdlInstruction(caller, slabKey, oracleKey, PROGRAM_ID, target.idx);\n * }\n * ```\n */\nexport async function fetchAdlRankings(\n apiBase: string,\n slab: PublicKey | string,\n fetchFn: typeof fetch = fetch,\n): Promise<AdlApiResult> {\n const slabStr = typeof slab === \"string\" ? slab : slab.toBase58();\n const base = apiBase.replace(/\\/$/, \"\");\n const url = `${base}/api/adl/rankings?slab=${encodeURIComponent(slabStr)}`;\n\n const res = await fetchFn(url);\n if (!res.ok) {\n let body = \"\";\n try { body = await res.text(); } catch { /* ignore */ }\n throw new Error(\n `fetchAdlRankings: HTTP ${res.status} from ${url}${body ? ` — ${body}` : \"\"}`,\n );\n }\n\n const json: unknown = await res.json();\n\n // Runtime validation — the API response shape is not guaranteed\n if (typeof json !== \"object\" || json === null) {\n throw new Error(\"fetchAdlRankings: API returned non-object response\");\n }\n const obj = json as Record<string, unknown>;\n if (!Array.isArray(obj.rankings)) {\n throw new Error(\"fetchAdlRankings: API response missing rankings array\");\n }\n for (const entry of obj.rankings) {\n if (typeof entry !== \"object\" || entry === null) {\n throw new Error(\"fetchAdlRankings: invalid ranking entry (not an object)\");\n }\n const r = entry as Record<string, unknown>;\n if (typeof r.idx !== \"number\" || !Number.isInteger(r.idx) || r.idx < 0) {\n throw new Error(`fetchAdlRankings: invalid ranking idx: ${r.idx}`);\n }\n }\n\n return json as AdlApiResult;\n}\n","import {\n Connection,\n type Commitment,\n type ConnectionConfig,\n} from \"@solana/web3.js\";\n\n// ---------------------------------------------------------------------------\n// Configuration Types\n// ---------------------------------------------------------------------------\n\n/**\n * Configuration for exponential-backoff retry on RPC calls.\n *\n * @example\n * ```ts\n * const retryConfig: RetryConfig = {\n * maxRetries: 3,\n * baseDelayMs: 500,\n * maxDelayMs: 10_000,\n * retryableStatusCodes: [429, 502, 503],\n * };\n * ```\n */\nexport interface RetryConfig {\n /**\n * Maximum number of retry attempts after the initial request fails.\n * @default 3\n */\n maxRetries?: number;\n\n /**\n * Base delay in ms for exponential backoff.\n * Delay for attempt N is: `min(baseDelayMs * 2^N, maxDelayMs) + jitter`.\n * @default 500\n */\n baseDelayMs?: number;\n\n /**\n * Maximum delay in ms (backoff cap).\n * @default 10_000\n */\n maxDelayMs?: number;\n\n /**\n * Jitter factor (0–1). Applied as random `[0, jitterFactor * delay]` addition.\n * @default 0.25\n */\n jitterFactor?: number;\n\n /**\n * HTTP status codes considered retryable.\n * Errors matching these codes (or containing their string representation)\n * will be retried.\n * @default [429, 502, 503, 504]\n */\n retryableStatusCodes?: number[];\n}\n\n/**\n * Configuration for a single RPC endpoint in the pool.\n *\n * @example\n * ```ts\n * const endpoint: RpcEndpointConfig = {\n * url: \"https://mainnet.helius-rpc.com/?api-key=YOUR_KEY\",\n * weight: 10,\n * label: \"helius-primary\",\n * };\n * ```\n */\nexport interface RpcEndpointConfig {\n /** RPC endpoint URL. */\n url: string;\n\n /**\n * Relative weight for round-robin selection.\n * Higher weight = more requests routed here.\n * @default 1\n */\n weight?: number;\n\n /**\n * Human-readable label for logging / diagnostics.\n * @default url hostname\n */\n label?: string;\n\n /**\n * Extra `ConnectionConfig` options (commitment, confirmTransactionInitialTimeout, etc.)\n * merged into the Solana `Connection` constructor for this endpoint.\n */\n connectionConfig?: ConnectionConfig;\n}\n\n/**\n * Strategy for selecting the next RPC endpoint from the pool.\n *\n * - `\"round-robin\"` — weighted round-robin across healthy endpoints.\n * - `\"failover\"` — use the first healthy endpoint; only advance on failure.\n */\nexport type SelectionStrategy = \"round-robin\" | \"failover\";\n\n/**\n * Full configuration for the RPC connection pool.\n *\n * @example\n * ```ts\n * import { RpcPool } from \"@percolator/sdk\";\n *\n * const pool = new RpcPool({\n * endpoints: [\n * { url: \"https://mainnet.helius-rpc.com/?api-key=KEY\", weight: 10, label: \"helius\" },\n * { url: \"https://api.mainnet-beta.solana.com\", weight: 1, label: \"public\" },\n * ],\n * strategy: \"failover\",\n * retry: { maxRetries: 3, baseDelayMs: 500 },\n * requestTimeoutMs: 30_000,\n * });\n *\n * // Use like a Connection — same surface\n * const slot = await pool.call(conn => conn.getSlot());\n * ```\n */\nexport interface RpcPoolConfig {\n /**\n * One or more RPC endpoints. At least one is required.\n * If a bare `string[]` is passed, each string is treated as `{ url: string }`.\n */\n endpoints: (RpcEndpointConfig | string)[];\n\n /**\n * How to pick the next endpoint.\n * @default \"failover\"\n */\n strategy?: SelectionStrategy;\n\n /**\n * Retry config applied to every `call()`.\n * Set to `false` to disable retries entirely.\n * @default { maxRetries: 3, baseDelayMs: 500 }\n */\n retry?: RetryConfig | false;\n\n /**\n * Per-request timeout in ms. Applies an `AbortSignal` timeout to `Connection`\n * calls where supported, and is used as a deadline for the health probe.\n * @default 30_000\n */\n requestTimeoutMs?: number;\n\n /**\n * Default Solana commitment level for connections.\n * @default \"confirmed\"\n */\n commitment?: Commitment;\n\n /**\n * If true, `console.warn` diagnostic messages on retries, failovers, etc.\n * @default true\n */\n verbose?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Health Probe\n// ---------------------------------------------------------------------------\n\n/**\n * Result of an RPC health probe.\n *\n * @example\n * ```ts\n * import { checkRpcHealth } from \"@percolator/sdk\";\n *\n * const health = await checkRpcHealth(\"https://api.mainnet-beta.solana.com\");\n * console.log(`Slot: ${health.slot}, Latency: ${health.latencyMs}ms`);\n * if (!health.healthy) console.warn(`Unhealthy: ${health.error}`);\n * ```\n */\nexport interface RpcHealthResult {\n /** The endpoint that was probed. */\n endpoint: string;\n /** Whether the probe succeeded (getSlot returned without error). */\n healthy: boolean;\n /** Round-trip latency in milliseconds (0 if unhealthy). */\n latencyMs: number;\n /** Current slot height (0 if unhealthy). */\n slot: number;\n /** Error message if the probe failed. */\n error?: string;\n}\n\n/**\n * Probe an RPC endpoint's health by calling `getSlot()` and measuring latency.\n *\n * @param endpoint - RPC URL to probe\n * @param timeoutMs - Timeout in ms for the probe request (default: 5000)\n * @returns Health result with latency and slot height\n *\n * @example\n * ```ts\n * import { checkRpcHealth } from \"@percolator/sdk\";\n *\n * const result = await checkRpcHealth(\"https://api.mainnet-beta.solana.com\", 3000);\n * if (result.healthy) {\n * console.log(`Slot ${result.slot} — ${result.latencyMs}ms`);\n * } else {\n * console.error(`RPC down: ${result.error}`);\n * }\n * ```\n */\nexport async function checkRpcHealth(\n endpoint: string,\n timeoutMs: number = 5_000,\n): Promise<RpcHealthResult> {\n const conn = new Connection(endpoint, { commitment: \"processed\" });\n const start = performance.now();\n\n const timeout = rejectAfter<number>(timeoutMs, `Health probe timed out after ${timeoutMs}ms`);\n try {\n const slot = await Promise.race([\n conn.getSlot(\"processed\"),\n timeout.promise,\n ]);\n\n const latencyMs = Math.round(performance.now() - start);\n return { endpoint, healthy: true, latencyMs, slot };\n } catch (err) {\n const latencyMs = Math.round(performance.now() - start);\n return {\n endpoint,\n healthy: false,\n latencyMs,\n slot: 0,\n error: err instanceof Error ? err.message : String(err),\n };\n } finally {\n timeout.cancel();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal Helpers\n// ---------------------------------------------------------------------------\n\n/** Resolved defaults for RetryConfig. */\ninterface ResolvedRetryConfig {\n maxRetries: number;\n baseDelayMs: number;\n maxDelayMs: number;\n jitterFactor: number;\n retryableStatusCodes: number[];\n}\n\nfunction resolveRetryConfig(cfg?: RetryConfig | false): ResolvedRetryConfig | null {\n if (cfg === false) return null;\n const c = cfg ?? {};\n return {\n maxRetries: c.maxRetries ?? 3,\n baseDelayMs: c.baseDelayMs ?? 500,\n maxDelayMs: c.maxDelayMs ?? 10_000,\n jitterFactor: Math.max(0, Math.min(1, c.jitterFactor ?? 0.25)),\n retryableStatusCodes: c.retryableStatusCodes ?? [429, 502, 503, 504],\n };\n}\n\nfunction normalizeEndpoint(ep: RpcEndpointConfig | string): RpcEndpointConfig {\n if (typeof ep === \"string\") return { url: ep };\n return ep;\n}\n\nfunction endpointLabel(ep: RpcEndpointConfig): string {\n if (ep.label) return ep.label;\n try {\n return new URL(ep.url).hostname;\n } catch {\n return ep.url.slice(0, 40);\n }\n}\n\nfunction isRetryable(err: unknown, codes: number[]): boolean {\n if (!err) return false;\n const msg = err instanceof Error ? err.message : String(err);\n for (const code of codes) {\n if (msg.includes(String(code))) return true;\n }\n // Generic network errors\n if (\n msg.toLowerCase().includes(\"rate limit\") ||\n msg.toLowerCase().includes(\"too many requests\") ||\n msg.toLowerCase().includes(\"econnreset\") ||\n msg.toLowerCase().includes(\"econnrefused\") ||\n msg.toLowerCase().includes(\"socket hang up\") ||\n msg.toLowerCase().includes(\"network\") ||\n msg.toLowerCase().includes(\"timeout\") ||\n msg.toLowerCase().includes(\"abort\")\n ) {\n return true;\n }\n return false;\n}\n\nfunction computeDelay(attempt: number, config: ResolvedRetryConfig): number {\n const raw = Math.min(\n config.baseDelayMs * Math.pow(2, attempt),\n config.maxDelayMs,\n );\n const jitter = Math.floor(Math.random() * raw * config.jitterFactor);\n return raw + jitter;\n}\n\nfunction rejectAfter<T>(ms: number, message: string): { promise: Promise<T>; cancel: () => void } {\n let timer: ReturnType<typeof setTimeout>;\n const promise = new Promise<T>((_, reject) => {\n timer = setTimeout(() => reject(new Error(message)), ms);\n });\n return { promise, cancel: () => clearTimeout(timer!) };\n}\n\n/** Sleep utility. */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Redact sensitive query-string parameters (api-key, api_key, token, secret,\n * key, password) from a URL so it is safe for logging / status output.\n */\nfunction redactUrl(raw: string): string {\n try {\n const u = new URL(raw);\n const sensitive = /^(api[-_]?key|access[-_]?token|auth[-_]?token|token|secret|key|password|bearer|credential|jwt)$/i;\n for (const k of [...u.searchParams.keys()]) {\n if (sensitive.test(k)) {\n u.searchParams.set(k, \"***\");\n }\n }\n return u.toString();\n } catch {\n // Not a valid URL — return as-is (unlikely for RPC endpoints).\n return raw;\n }\n}\n\n// ---------------------------------------------------------------------------\n// RpcPool\n// ---------------------------------------------------------------------------\n\n/** Per-endpoint tracked state. */\ninterface EndpointState {\n config: RpcEndpointConfig;\n connection: Connection;\n label: string;\n weight: number;\n /** Consecutive failure count. Resets on success. */\n failures: number;\n /** Whether this endpoint is considered healthy. */\n healthy: boolean;\n /** Last probe latency (ms), -1 if never probed. */\n lastLatencyMs: number;\n}\n\n/**\n * RPC connection pool with retry, failover, and round-robin support.\n *\n * Wraps one or more Solana RPC endpoints behind a single `call()` interface\n * that automatically retries transient errors and fails over to alternate\n * endpoints when one goes down.\n *\n * @example\n * ```ts\n * import { RpcPool } from \"@percolator/sdk\";\n *\n * const pool = new RpcPool({\n * endpoints: [\n * { url: \"https://mainnet.helius-rpc.com/?api-key=KEY\", weight: 10, label: \"helius\" },\n * { url: \"https://api.mainnet-beta.solana.com\", weight: 1, label: \"public\" },\n * ],\n * strategy: \"failover\",\n * retry: { maxRetries: 3 },\n * requestTimeoutMs: 30_000,\n * });\n *\n * // Execute any Connection method through the pool\n * const slot = await pool.call(conn => conn.getSlot());\n *\n * // Or get a raw connection for one-off use\n * const conn = pool.getConnection();\n *\n * // Health check all endpoints\n * const results = await pool.healthCheck();\n * ```\n */\nexport class RpcPool {\n private readonly endpoints: EndpointState[];\n private readonly strategy: SelectionStrategy;\n private readonly retryConfig: ResolvedRetryConfig | null;\n private readonly requestTimeoutMs: number;\n private readonly verbose: boolean;\n\n /** Round-robin index tracker. */\n private rrIndex: number = 0;\n\n /** Consecutive failure threshold before marking an endpoint unhealthy. */\n private static readonly UNHEALTHY_THRESHOLD = 3;\n\n /** Minimum endpoints before auto-recovery is attempted. */\n private static readonly MIN_HEALTHY = 1;\n\n constructor(config: RpcPoolConfig) {\n if (!config.endpoints || config.endpoints.length === 0) {\n throw new Error(\"RpcPool: at least one endpoint is required\");\n }\n\n this.strategy = config.strategy ?? \"failover\";\n this.retryConfig = resolveRetryConfig(config.retry);\n this.requestTimeoutMs = config.requestTimeoutMs ?? 30_000;\n this.verbose = config.verbose ?? true;\n\n const commitment = config.commitment ?? \"confirmed\";\n\n this.endpoints = config.endpoints.map(raw => {\n const ep = normalizeEndpoint(raw);\n const connConfig: ConnectionConfig = {\n commitment,\n ...ep.connectionConfig,\n };\n return {\n config: ep,\n connection: new Connection(ep.url, connConfig),\n label: endpointLabel(ep),\n weight: Math.max(1, ep.weight ?? 1),\n failures: 0,\n healthy: true,\n lastLatencyMs: -1,\n };\n });\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /**\n * Execute a function against a pooled connection with automatic retry\n * and failover.\n *\n * @param fn - Async function that receives a `Connection` and returns a result.\n * @returns The result of `fn`.\n * @throws The last error if all retries and failovers are exhausted.\n *\n * @example\n * ```ts\n * const balance = await pool.call(c => c.getBalance(pubkey));\n * const markets = await pool.call(c => discoverMarkets(c, programId, opts));\n * ```\n */\n async call<T>(fn: (connection: Connection) => Promise<T>): Promise<T> {\n const maxAttempts = this.retryConfig ? this.retryConfig.maxRetries + 1 : 1;\n let lastError: unknown;\n\n // Track which endpoints we have tried in this call to avoid infinite loops.\n const triedEndpoints = new Set<number>();\n // Hard cap on total iterations to prevent amplification from attempt-- failovers\n const maxTotalIterations = maxAttempts + this.endpoints.length;\n let totalIterations = 0;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n if (++totalIterations > maxTotalIterations) break;\n const epIdx = this.selectEndpoint(triedEndpoints);\n if (epIdx === -1) {\n // All endpoints exhausted\n break;\n }\n const ep = this.endpoints[epIdx];\n\n const timeout = rejectAfter<T>(this.requestTimeoutMs, `RPC request timed out after ${this.requestTimeoutMs}ms (${ep.label})`);\n try {\n const result = await Promise.race([\n fn(ep.connection),\n timeout.promise,\n ]);\n\n // Success — reset failure count\n timeout.cancel();\n ep.failures = 0;\n ep.healthy = true;\n return result;\n } catch (err) {\n timeout.cancel();\n lastError = err;\n ep.failures++;\n\n if (ep.failures >= RpcPool.UNHEALTHY_THRESHOLD) {\n ep.healthy = false;\n if (this.verbose) {\n console.warn(\n `[RpcPool] Endpoint ${ep.label} marked unhealthy after ${ep.failures} consecutive failures`,\n );\n }\n }\n\n const retryable = this.retryConfig\n ? isRetryable(err, this.retryConfig.retryableStatusCodes)\n : false;\n\n if (!retryable) {\n // For non-retryable errors in failover mode, try the next endpoint\n if (this.strategy === \"failover\" && this.endpoints.length > 1) {\n triedEndpoints.add(epIdx);\n // Don't count this as a retry attempt — just failover\n attempt--;\n if (triedEndpoints.size >= this.endpoints.length) break;\n continue;\n }\n throw err;\n }\n\n // Retryable error\n if (this.verbose) {\n console.warn(\n `[RpcPool] Retryable error on ${ep.label} (attempt ${attempt + 1}/${maxAttempts}):`,\n err instanceof Error ? err.message : err,\n );\n }\n\n // In failover mode, try next endpoint before retrying same one\n if (this.strategy === \"failover\" && this.endpoints.length > 1) {\n triedEndpoints.add(epIdx);\n }\n\n // Backoff before retry\n if (attempt < maxAttempts - 1 && this.retryConfig) {\n const delay = computeDelay(attempt, this.retryConfig);\n await sleep(delay);\n }\n }\n }\n\n // All attempts exhausted — try recovery before giving up\n this.maybeRecoverEndpoints();\n\n throw lastError ?? new Error(\"RpcPool: all endpoints exhausted\");\n }\n\n /**\n * Get a raw `Connection` from the current preferred endpoint.\n * Useful when you need to pass a Connection to external code.\n *\n * NOTE: This bypasses retry and failover logic. Prefer `call()`.\n *\n * @returns Solana Connection from the current preferred endpoint.\n *\n * @example\n * ```ts\n * const conn = pool.getConnection();\n * const balance = await conn.getBalance(pubkey);\n * ```\n */\n getConnection(): Connection {\n const idx = this.selectEndpoint();\n if (idx === -1) {\n // All marked unhealthy — reset and use first\n this.maybeRecoverEndpoints();\n return this.endpoints[0].connection;\n }\n return this.endpoints[idx].connection;\n }\n\n /**\n * Run a health check against all endpoints in the pool.\n *\n * @param timeoutMs - Per-endpoint probe timeout (default: 5000)\n * @returns Array of health results, one per endpoint.\n *\n * @example\n * ```ts\n * const results = await pool.healthCheck();\n * for (const r of results) {\n * console.log(`${r.endpoint}: ${r.healthy ? 'UP' : 'DOWN'} (${r.latencyMs}ms, slot ${r.slot})`);\n * }\n * ```\n */\n async healthCheck(timeoutMs: number = 5_000): Promise<RpcHealthResult[]> {\n const results = await Promise.all(\n this.endpoints.map(async (ep) => {\n const result = await checkRpcHealth(ep.config.url, timeoutMs);\n ep.lastLatencyMs = result.latencyMs;\n ep.healthy = result.healthy;\n if (result.healthy) ep.failures = 0;\n result.endpoint = redactUrl(result.endpoint);\n return result;\n }),\n );\n return results;\n }\n\n /**\n * Get the number of endpoints in the pool.\n */\n get size(): number {\n return this.endpoints.length;\n }\n\n /**\n * Get the number of currently healthy endpoints.\n */\n get healthyCount(): number {\n return this.endpoints.filter(ep => ep.healthy).length;\n }\n\n /**\n * Get endpoint labels and their current status.\n *\n * @returns Array of `{ label, url, healthy, failures, lastLatencyMs }`.\n */\n status(): Array<{\n label: string;\n url: string;\n healthy: boolean;\n failures: number;\n lastLatencyMs: number;\n }> {\n return this.endpoints.map(ep => ({\n label: ep.label,\n url: redactUrl(ep.config.url),\n healthy: ep.healthy,\n failures: ep.failures,\n lastLatencyMs: ep.lastLatencyMs,\n }));\n }\n\n // -----------------------------------------------------------------------\n // Internals\n // -----------------------------------------------------------------------\n\n /**\n * Select the next endpoint based on strategy.\n * Returns -1 if no endpoint is available.\n */\n private selectEndpoint(exclude?: Set<number>): number {\n const healthy = this.endpoints\n .map((ep, i) => ({ ep, i }))\n .filter(({ ep, i }) => ep.healthy && !(exclude?.has(i)));\n\n if (healthy.length === 0) {\n // No healthy endpoints — try all non-excluded\n const remaining = this.endpoints\n .map((_, i) => i)\n .filter(i => !(exclude?.has(i)));\n return remaining.length > 0 ? remaining[0] : -1;\n }\n\n if (this.strategy === \"failover\") {\n // Return first healthy (by insertion order)\n return healthy[0].i;\n }\n\n // Weighted round-robin\n const totalWeight = healthy.reduce((sum, { ep }) => sum + ep.weight, 0);\n this.rrIndex = (this.rrIndex + 1) % totalWeight;\n\n let cumulative = 0;\n for (const { ep, i } of healthy) {\n cumulative += ep.weight;\n if (this.rrIndex < cumulative) return i;\n }\n\n return healthy[healthy.length - 1].i;\n }\n\n /**\n * If all endpoints are unhealthy, reset them so we at least try again.\n */\n private maybeRecoverEndpoints(): void {\n const healthyCount = this.endpoints.filter(ep => ep.healthy).length;\n if (healthyCount < RpcPool.MIN_HEALTHY) {\n if (this.verbose) {\n console.warn(\"[RpcPool] All endpoints unhealthy — resetting for recovery\");\n }\n for (const ep of this.endpoints) {\n ep.healthy = true;\n ep.failures = 0;\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Standalone retry wrapper (for use without a full pool)\n// ---------------------------------------------------------------------------\n\n/**\n * Execute an async function with exponential-backoff retry.\n *\n * Use this when you already have a `Connection` and just want retry logic\n * without a full pool.\n *\n * @param fn - Async function to execute\n * @param config - Retry configuration (default: 3 retries, 500ms base delay)\n * @returns Result of `fn`\n * @throws The last error if all retries are exhausted\n *\n * @example\n * ```ts\n * import { withRetry } from \"@percolator/sdk\";\n * import { Connection } from \"@solana/web3.js\";\n *\n * const conn = new Connection(\"https://api.mainnet-beta.solana.com\");\n * const slot = await withRetry(\n * () => conn.getSlot(),\n * { maxRetries: 3, baseDelayMs: 1000 },\n * );\n * ```\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n config?: RetryConfig,\n): Promise<T> {\n const resolved = resolveRetryConfig(config) ?? {\n maxRetries: 3,\n baseDelayMs: 500,\n maxDelayMs: 10_000,\n jitterFactor: 0.25,\n retryableStatusCodes: [429, 502, 503, 504],\n };\n\n let lastError: unknown;\n const maxAttempts = resolved.maxRetries + 1;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n\n if (!isRetryable(err, resolved.retryableStatusCodes)) {\n throw err;\n }\n\n if (attempt < maxAttempts - 1) {\n const delay = computeDelay(attempt, resolved);\n await sleep(delay);\n }\n }\n }\n\n throw lastError ?? new Error(\"withRetry: all attempts exhausted\");\n}\n\n// ---------------------------------------------------------------------------\n// Re-export helpers for testing\n// ---------------------------------------------------------------------------\n\n/** @internal — exposed for unit tests only */\nexport const _internal = {\n isRetryable,\n computeDelay,\n resolveRetryConfig,\n normalizeEndpoint,\n endpointLabel,\n} as const;\n","import {\n Connection,\n PublicKey,\n TransactionInstruction,\n Transaction,\n Keypair,\n SendOptions,\n Commitment,\n AccountMeta,\n ComputeBudgetProgram,\n} from \"@solana/web3.js\";\nimport { parseErrorFromLogs } from \"../abi/errors.js\";\n\nexport interface BuildIxParams {\n programId: PublicKey;\n keys: AccountMeta[];\n data: Uint8Array | Buffer;\n}\n\n/**\n * Build a transaction instruction.\n */\nexport function buildIx(params: BuildIxParams): TransactionInstruction {\n return new TransactionInstruction({\n programId: params.programId,\n keys: params.keys,\n // TransactionInstruction types expect Buffer, but Uint8Array works at runtime.\n // Cast to avoid Buffer polyfill issues in the browser.\n data: params.data as Buffer,\n });\n}\n\nexport interface TxResult {\n signature: string;\n slot: number;\n err: string | null;\n hint?: string;\n logs: string[];\n unitsConsumed?: number;\n}\n\nexport interface SimulateOrSendParams {\n connection: Connection;\n ix: TransactionInstruction;\n signers: Keypair[];\n simulate: boolean;\n commitment?: Commitment;\n computeUnitLimit?: number; // Custom compute unit limit (default: 200,000, max: 1,400,000)\n}\n\n/**\n * Simulate or send a transaction.\n * Returns consistent output for both modes.\n */\n/** Solana per-transaction compute unit ceiling (Compute Budget program). */\nconst MAX_COMPUTE_UNIT_LIMIT = 1_400_000;\n\nexport async function simulateOrSend(\n params: SimulateOrSendParams\n): Promise<TxResult> {\n const { connection, ix, signers, simulate, commitment = \"confirmed\", computeUnitLimit } = params;\n\n if (!signers.length) {\n throw new Error(\"simulateOrSend: at least one signer is required\");\n }\n\n if (computeUnitLimit !== undefined) {\n if (\n typeof computeUnitLimit !== \"number\" ||\n !Number.isInteger(computeUnitLimit) ||\n computeUnitLimit < 1 ||\n computeUnitLimit > MAX_COMPUTE_UNIT_LIMIT\n ) {\n throw new Error(\n `computeUnitLimit must be an integer in [1, ${MAX_COMPUTE_UNIT_LIMIT}]`,\n );\n }\n }\n\n const tx = new Transaction();\n\n // Add compute budget instruction if custom limit is specified\n if (computeUnitLimit !== undefined) {\n tx.add(\n ComputeBudgetProgram.setComputeUnitLimit({\n units: computeUnitLimit,\n })\n );\n }\n\n tx.add(ix);\n const latestBlockhash = await connection.getLatestBlockhash(commitment);\n tx.recentBlockhash = latestBlockhash.blockhash;\n tx.feePayer = signers[0].publicKey;\n\n if (simulate) {\n try {\n tx.sign(...signers);\n const result = await connection.simulateTransaction(tx, signers);\n const logs = result.value.logs ?? [];\n let err: string | null = null;\n let hint: string | undefined;\n\n if (result.value.err) {\n const parsed = parseErrorFromLogs(logs);\n if (parsed) {\n err = `${parsed.name} (0x${parsed.code.toString(16)})`;\n hint = parsed.hint;\n } else {\n err = JSON.stringify(result.value.err);\n }\n }\n\n return {\n signature: \"(simulated)\",\n slot: result.context.slot,\n err,\n hint,\n logs,\n unitsConsumed: result.value.unitsConsumed ?? undefined,\n };\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n return {\n signature: \"(simulated)\",\n slot: 0,\n err: message,\n logs: [],\n };\n }\n }\n\n // Send\n const options: SendOptions = {\n skipPreflight: false,\n preflightCommitment: commitment,\n };\n\n try {\n const signature = await connection.sendTransaction(tx, signers, options);\n\n const confirmation = await connection.confirmTransaction(\n {\n signature,\n blockhash: latestBlockhash.blockhash,\n lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,\n },\n commitment\n );\n\n // Fetch logs\n const txInfo = await connection.getTransaction(signature, {\n commitment: \"confirmed\",\n maxSupportedTransactionVersion: 0,\n });\n\n const logs = txInfo?.meta?.logMessages ?? [];\n let err: string | null = null;\n let hint: string | undefined;\n\n if (confirmation.value.err) {\n const parsed = parseErrorFromLogs(logs);\n if (parsed) {\n err = `${parsed.name} (0x${parsed.code.toString(16)})`;\n hint = parsed.hint;\n } else {\n err = JSON.stringify(confirmation.value.err);\n }\n }\n\n return {\n signature,\n slot: txInfo?.slot ?? 0,\n err,\n hint,\n logs,\n };\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n return {\n signature: \"\",\n slot: 0,\n err: message,\n logs: [],\n };\n }\n}\n\n/**\n * Format transaction result for output.\n */\nexport function formatResult(result: TxResult, jsonMode: boolean): string {\n if (jsonMode) {\n return JSON.stringify(result, null, 2);\n }\n\n const lines: string[] = [];\n\n if (result.err) {\n lines.push(`Error: ${result.err}`);\n if (result.hint) {\n lines.push(`Hint: ${result.hint}`);\n }\n if (result.unitsConsumed !== undefined) {\n lines.push(`Compute Units: ${result.unitsConsumed.toLocaleString()}`);\n }\n if (result.logs.length > 0) {\n lines.push(\"Logs:\");\n result.logs.forEach((log) => lines.push(` ${log}`));\n }\n } else {\n lines.push(`Signature: ${result.signature}`);\n lines.push(`Slot: ${result.slot}`);\n if (result.unitsConsumed !== undefined) {\n lines.push(`Compute Units: ${result.unitsConsumed.toLocaleString()}`);\n }\n if (result.signature !== \"(simulated)\") {\n lines.push(`Explorer: https://explorer.solana.com/tx/${result.signature}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n","/**\n * @module lighthouse\n * Lighthouse v2 (Blowfish / Phantom wallet middleware) detection and mitigation.\n *\n * Lighthouse (program L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95) is an Anchor-based\n * wallet guard injected by Phantom and other Solana wallets via the Blowfish transaction\n * scanning service. It adds assertion instructions to transactions that verify account\n * state expectations (e.g., \"this account should be empty\" or \"this account should have\n * X lamports\").\n *\n * **Problem:** Lighthouse doesn't understand Percolator's slab accounts. When a slab\n * (e.g., ESa89R5 with 323,312 bytes) is passed as a TradeCpi account, Lighthouse injects\n * an assertion like `StateInvalidAddress` that expects `data_len == 0` (uninitialised).\n * The slab IS initialised, so the assertion fails with error 0x1900 (Anchor ConstraintAddress\n * = 6400 decimal). This causes the transaction to revert even though the Percolator program\n * logic is correct.\n *\n * **Solution:** The SDK provides utilities to:\n * 1. Detect Lighthouse instructions in a transaction\n * 2. Strip them before sending\n * 3. Classify 0x1900 errors as Lighthouse (not Percolator) errors\n * 4. Provide clear, actionable error messages for end users\n *\n * @example\n * ```ts\n * import { isLighthouseError, stripLighthouseInstructions, LIGHTHOUSE_PROGRAM_ID } from \"@percolator/sdk\";\n *\n * // Before sending: strip injected Lighthouse IXs\n * const cleanIxs = stripLighthouseInstructions(instructions);\n *\n * // After error: classify and give user-friendly message\n * if (isLighthouseError(error)) {\n * console.warn(\"Wallet middleware blocked the transaction\");\n * }\n * ```\n */\n\nimport { PublicKey, TransactionInstruction, Transaction } from \"@solana/web3.js\";\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Lighthouse v2 program ID (Blowfish/Phantom wallet guard).\n *\n * This is an immutable Anchor program deployed at slot 294,179,293.\n * Wallets like Phantom inject instructions from this program into user\n * transactions to enforce Blowfish security assertions.\n */\nexport const LIGHTHOUSE_PROGRAM_ID = new PublicKey(\n \"L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95\",\n);\n\n/** Base58 string form for fast comparison without PublicKey instantiation. */\nexport const LIGHTHOUSE_PROGRAM_ID_STR = \"L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95\";\n\n/**\n * Anchor error code for ConstraintAddress (0x1900 = 6400 decimal).\n * This is NOT a Percolator error — it comes from Lighthouse's Anchor framework\n * when an account constraint check fails.\n */\nexport const LIGHTHOUSE_CONSTRAINT_ADDRESS = 0x1900;\n\n/**\n * Known Lighthouse/Anchor error codes that may appear in transaction logs.\n * All are in the Anchor error range (0x1770–0x1900+).\n */\nexport const LIGHTHOUSE_ERROR_CODES = new Set([\n 0x1770, // InstructionMissing\n 0x1771, // InstructionFallbackNotFound\n 0x1772, // InstructionDidNotDeserialize\n 0x1773, // InstructionDidNotSerialize\n 0x1780, // IdlInstructionStub\n 0x1790, // ConstraintMut\n 0x1791, // ConstraintHasOne\n 0x1792, // ConstraintSigner\n 0x1793, // ConstraintRaw\n 0x1794, // ConstraintOwner\n 0x1795, // ConstraintRentExempt\n 0x1796, // ConstraintSeeds\n 0x1797, // ConstraintExecutable\n 0x1798, // ConstraintState\n 0x1799, // ConstraintAssociated\n 0x179a, // ConstraintAssociatedInit\n 0x179b, // ConstraintClose\n 0x1900, // ConstraintAddress (the one we hit most often)\n] as const);\n\n// ============================================================================\n// Detection\n// ============================================================================\n\n/**\n * Check if a TransactionInstruction is from the Lighthouse program.\n *\n * @param ix - A Solana transaction instruction.\n * @returns `true` if the instruction's programId is Lighthouse.\n *\n * @example\n * ```ts\n * const hasLighthouse = instructions.some(isLighthouseInstruction);\n * ```\n */\nexport function isLighthouseInstruction(ix: TransactionInstruction): boolean {\n return ix.programId.equals(LIGHTHOUSE_PROGRAM_ID);\n}\n\n/**\n * Check if an error message or error object indicates a Lighthouse assertion failure.\n *\n * Detects:\n * - `custom program error: 0x1900` (Anchor ConstraintAddress from Lighthouse)\n * - References to the Lighthouse program ID in error text\n * - `\"Custom\": 6400` in JSON-encoded InstructionError\n * - Any Anchor error code in the LIGHTHOUSE_ERROR_CODES range when the\n * failing program is Lighthouse (identified by program ID in logs)\n *\n * @param error - An Error object, error message string, or transaction logs array.\n * @returns `true` if the error appears to originate from Lighthouse, not Percolator.\n *\n * @example\n * ```ts\n * try {\n * await sendTransaction(tx);\n * } catch (e) {\n * if (isLighthouseError(e)) {\n * // Retry with skipPreflight or notify user about wallet middleware\n * }\n * }\n * ```\n */\nexport function isLighthouseError(error: unknown): boolean {\n const msg = extractErrorMessage(error);\n if (!msg) return false;\n\n // Direct program ID reference\n if (msg.includes(LIGHTHOUSE_PROGRAM_ID_STR)) return true;\n\n // 0x1900 hex error code (case-insensitive)\n if (/custom\\s+program\\s+error:\\s*0x1900\\b/i.test(msg)) return true;\n\n // JSON InstructionError format: {\"Custom\": 6400}\n if (/\"Custom\"\\s*:\\s*6400\\b/.test(msg) && /InstructionError/i.test(msg)) return true;\n\n return false;\n}\n\n/**\n * Check if transaction logs contain evidence of a Lighthouse failure.\n *\n * More precise than `isLighthouseError` on a string — examines the program\n * invocation chain to confirm the error originates from Lighthouse, not from\n * a Percolator instruction that happens to return a similar code.\n *\n * @param logs - Array of transaction log lines from `getTransaction()`.\n * @returns `true` if logs show a Lighthouse program failure.\n */\nexport function isLighthouseFailureInLogs(logs: string[]): boolean {\n if (!Array.isArray(logs)) return false;\n\n let insideLighthouse = false;\n\n for (const line of logs) {\n if (typeof line !== \"string\") continue;\n\n // Track program invocation depth\n if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {\n insideLighthouse = true;\n continue;\n }\n\n // Lighthouse program returned success — reset\n if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {\n insideLighthouse = false;\n continue;\n }\n\n // Error while inside a Lighthouse invocation\n if (insideLighthouse && /failed/i.test(line)) {\n return true;\n }\n\n // Explicit Lighthouse failure log\n if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} failed`)) {\n return true;\n }\n }\n\n return false;\n}\n\n// ============================================================================\n// Stripping / Mitigation\n// ============================================================================\n\n/**\n * Remove all Lighthouse assertion instructions from an instruction array.\n *\n * Call this before building a Transaction to prevent Lighthouse assertion\n * failures. Safe to call even if no Lighthouse instructions are present.\n *\n * @param instructions - Array of transaction instructions.\n * @returns Filtered array with Lighthouse instructions removed.\n *\n * @example\n * ```ts\n * import { stripLighthouseInstructions } from \"@percolator/sdk\";\n *\n * const instructions = [crankIx, tradeIx]; // May have Lighthouse IXs mixed in\n * const clean = stripLighthouseInstructions(instructions);\n * const tx = new Transaction().add(...clean);\n * ```\n */\nexport function stripLighthouseInstructions(\n instructions: TransactionInstruction[],\n percolatorProgramId?: PublicKey,\n): TransactionInstruction[] {\n // When a programId is provided, refuse to strip guards from transactions\n // that don't contain any Percolator instructions — prevents misuse on\n // arbitrary transactions where Lighthouse guards are legitimate protection.\n if (percolatorProgramId) {\n const hasPercolatorIx = instructions.some(\n (ix) => ix.programId.equals(percolatorProgramId),\n );\n if (!hasPercolatorIx) {\n return instructions; // no Percolator instructions — leave guards intact\n }\n }\n return instructions.filter((ix) => !isLighthouseInstruction(ix));\n}\n\n/**\n * Strip Lighthouse instructions from an already-built Transaction.\n *\n * Creates a new Transaction with the same recentBlockhash and feePayer\n * but without any Lighthouse instructions. The returned transaction is\n * unsigned and must be re-signed.\n *\n * @param transaction - A Transaction (signed or unsigned).\n * @returns A new Transaction without Lighthouse instructions, or the same\n * transaction if no Lighthouse instructions were found.\n *\n * @example\n * ```ts\n * const signed = await wallet.signTransaction(tx);\n * if (hasLighthouseInstructions(signed)) {\n * const clean = stripLighthouseFromTransaction(signed);\n * const reSigned = await wallet.signTransaction(clean);\n * await connection.sendRawTransaction(reSigned.serialize());\n * }\n * ```\n */\nexport function stripLighthouseFromTransaction(\n transaction: Transaction,\n percolatorProgramId?: PublicKey,\n): Transaction {\n // When a programId is provided, refuse to strip guards from transactions\n // that don't contain any Percolator instructions.\n if (percolatorProgramId) {\n const hasPercolatorIx = transaction.instructions.some(\n (ix) => ix.programId.equals(percolatorProgramId),\n );\n if (!hasPercolatorIx) return transaction;\n }\n\n const hasLighthouse = transaction.instructions.some(isLighthouseInstruction);\n if (!hasLighthouse) return transaction;\n\n const clean = new Transaction();\n clean.recentBlockhash = transaction.recentBlockhash;\n clean.feePayer = transaction.feePayer;\n\n for (const ix of transaction.instructions) {\n if (!isLighthouseInstruction(ix)) {\n clean.add(ix);\n }\n }\n\n return clean;\n}\n\n/**\n * Count Lighthouse instructions in an instruction array or transaction.\n *\n * @param ixsOrTx - Array of instructions or a Transaction.\n * @returns Number of Lighthouse instructions found.\n */\nexport function countLighthouseInstructions(\n ixsOrTx: TransactionInstruction[] | Transaction,\n): number {\n const instructions = Array.isArray(ixsOrTx) ? ixsOrTx : ixsOrTx.instructions;\n return instructions.filter(isLighthouseInstruction).length;\n}\n\n// ============================================================================\n// User-facing error messages\n// ============================================================================\n\n/**\n * User-friendly error message for Lighthouse assertion failures.\n *\n * Suitable for display in UI toast/modal when `isLighthouseError()` returns true.\n */\nexport const LIGHTHOUSE_USER_MESSAGE =\n \"Your wallet's transaction guard (Blowfish/Lighthouse) is blocking this transaction. \" +\n \"This is a known compatibility issue — the transaction itself is valid. \" +\n \"Try one of these workarounds:\\n\" +\n \"1. Disable transaction simulation in your wallet settings\\n\" +\n \"2. Use a wallet without Blowfish protection (e.g., Backpack, Solflare)\\n\" +\n \"3. The SDK will automatically retry without the guard\";\n\n/**\n * Classify an error and return an appropriate user-facing message.\n *\n * If the error is from Lighthouse, returns the Lighthouse-specific message.\n * Otherwise returns `null` (callers should use their own error display).\n *\n * @param error - An Error, string, or logs array.\n * @returns User-facing message string, or `null` if not a Lighthouse error.\n */\nexport function classifyLighthouseError(error: unknown): string | null {\n if (isLighthouseError(error)) {\n return LIGHTHOUSE_USER_MESSAGE;\n }\n return null;\n}\n\n// ============================================================================\n// Internal helpers\n// ============================================================================\n\nfunction extractErrorMessage(error: unknown): string | null {\n if (!error) return null;\n if (typeof error === \"string\") return error;\n if (error instanceof Error) return error.message;\n if (typeof error === \"object\" && \"message\" in error) {\n return String((error as { message: unknown }).message);\n }\n try {\n return JSON.stringify(error);\n } catch {\n return null;\n }\n}\n","/**\n * Coin-margined perpetual trade math utilities.\n *\n * On-chain PnL formula:\n * mark_pnl = (oracle - entry) * abs_pos / oracle (longs)\n * mark_pnl = (entry - oracle) * abs_pos / oracle (shorts)\n *\n * All prices are in e6 format (1 USD = 1_000_000).\n * All token amounts are in native units (e.g. lamports).\n */\n\n/**\n * Compute mark-to-market PnL for an open position.\n *\n * @param positionSize - Signed position size (positive = long, negative = short).\n * @param entryPrice - Entry price in e6 format (1 USD = 1_000_000).\n * @param oraclePrice - Current oracle price in e6 format.\n * @returns PnL in native token units (positive = profit, negative = loss).\n *\n * @example\n * ```ts\n * // Long 10 SOL at $100, oracle now $110 → profit\n * const pnl = computeMarkPnl(10_000_000n, 100_000_000n, 110_000_000n);\n * ```\n */\nexport function computeMarkPnl(\n positionSize: bigint,\n entryPrice: bigint,\n oraclePrice: bigint,\n): bigint {\n if (positionSize === 0n || oraclePrice === 0n) return 0n;\n const absPos = positionSize < 0n ? -positionSize : positionSize;\n const diff =\n positionSize > 0n\n ? oraclePrice - entryPrice\n : entryPrice - oraclePrice;\n return (diff * absPos) / oraclePrice;\n}\n\n/**\n * Compute liquidation price given entry, capital, position and maintenance margin.\n * Uses pure BigInt arithmetic for precision (no Number() truncation).\n *\n * @param entryPrice - Entry price in e6 format.\n * @param capital - Account capital in native token units.\n * @param positionSize - Signed position size (positive = long, negative = short).\n * @param maintenanceMarginBps - Maintenance margin requirement in basis points (e.g. 500n = 5%).\n * @returns Liquidation price in e6 format. Returns 0n for longs that can't be liquidated,\n * or max u64 for shorts with ≥100% maintenance margin.\n *\n * @example\n * ```ts\n * // Long 1 SOL at $100, $10 capital, 5% maintenance margin\n * const liqPrice = computeLiqPrice(100_000_000n, 10_000_000n, 1_000_000n, 500n);\n * ```\n */\nexport function computeLiqPrice(\n entryPrice: bigint,\n capital: bigint,\n positionSize: bigint,\n maintenanceMarginBps: bigint,\n): bigint {\n if (positionSize === 0n || entryPrice === 0n) return 0n;\n const absPos = positionSize < 0n ? -positionSize : positionSize;\n // capitalPerUnit scaled by 1e6 for precision\n const capitalPerUnitE6 = (capital * 1_000_000n) / absPos;\n\n if (positionSize > 0n) {\n const adjusted = (capitalPerUnitE6 * 10000n) / (10000n + maintenanceMarginBps);\n const liq = entryPrice - adjusted;\n return liq > 0n ? liq : 0n;\n } else {\n // Guard: short positions liquidate when price rises above liq price.\n // With >= 100% maintenance margin the denominator (10000 - maint) would be <= 0,\n // meaning the position can never be liquidated. Return max u64 to signal this.\n if (maintenanceMarginBps >= 10000n) return 18446744073709551615n; // max u64 — unliquidatable\n const adjusted = (capitalPerUnitE6 * 10000n) / (10000n - maintenanceMarginBps);\n return entryPrice + adjusted;\n }\n}\n\n/**\n * Compute estimated liquidation price BEFORE opening a trade.\n * Accounts for trading fees reducing effective capital.\n *\n * @param oracleE6 - Current oracle price in e6 format (used as entry estimate).\n * @param margin - Deposit margin in native token units.\n * @param posSize - Intended position size (absolute value used internally).\n * @param maintBps - Maintenance margin in basis points.\n * @param feeBps - Trading fee in basis points.\n * @param direction - Trade direction: `\"long\"` or `\"short\"`.\n * @returns Estimated liquidation price in e6 format.\n *\n * @example\n * ```ts\n * const liq = computePreTradeLiqPrice(\n * 100_000_000n, 10_000_000n, 1_000_000n, 500n, 30n, \"long\"\n * );\n * ```\n */\nexport function computePreTradeLiqPrice(\n oracleE6: bigint,\n margin: bigint,\n posSize: bigint,\n maintBps: bigint,\n feeBps: bigint,\n direction: \"long\" | \"short\",\n): bigint {\n if (oracleE6 === 0n || margin === 0n || posSize === 0n) return 0n;\n const absPos = posSize < 0n ? -posSize : posSize;\n const fee = (absPos * feeBps) / 10000n;\n const effectiveCapital = margin > fee ? margin - fee : 0n;\n const signedPos = direction === \"long\" ? absPos : -absPos;\n return computeLiqPrice(oracleE6, effectiveCapital, signedPos, maintBps);\n}\n\n/**\n * Compute trading fee from notional value and fee rate in bps.\n *\n * @param notional - Trade notional value in native token units.\n * @param tradingFeeBps - Fee rate in basis points (e.g. 30n = 0.30%).\n * @returns Fee amount in native token units.\n *\n * @example\n * ```ts\n * const fee = computeTradingFee(1_000_000_000n, 30n); // 0.30% of 1 SOL\n * ```\n */\nexport function computeTradingFee(\n notional: bigint,\n tradingFeeBps: bigint,\n): bigint {\n return (notional * tradingFeeBps) / 10000n;\n}\n\n/**\n * Dynamic fee tier configuration.\n */\nexport interface FeeTierConfig {\n /** Base trading fee (Tier 1) in bps */\n baseBps: bigint;\n /** Tier 2 fee in bps (0 = disabled) */\n tier2Bps: bigint;\n /** Tier 3 fee in bps (0 = disabled) */\n tier3Bps: bigint;\n /** Notional threshold to enter Tier 2 (0 = tiered fees disabled) */\n tier2Threshold: bigint;\n /** Notional threshold to enter Tier 3 */\n tier3Threshold: bigint;\n}\n\n/**\n * Compute the effective fee rate in bps using the tiered fee schedule.\n *\n * Mirrors on-chain `compute_dynamic_fee_bps` logic:\n * - notional < tier2Threshold → baseBps (Tier 1)\n * - notional < tier3Threshold → tier2Bps (Tier 2)\n * - notional >= tier3Threshold → tier3Bps (Tier 3)\n *\n * If tier2Threshold == 0, tiered fees are disabled (flat baseBps).\n */\nexport function computeDynamicFeeBps(\n notional: bigint,\n config: FeeTierConfig,\n): bigint {\n if (config.tier2Threshold === 0n) return config.baseBps;\n if (config.tier3Threshold > 0n && notional >= config.tier3Threshold) return config.tier3Bps;\n if (notional >= config.tier2Threshold) return config.tier2Bps;\n return config.baseBps;\n}\n\n/**\n * Compute the dynamic trading fee for a given notional and tier config.\n *\n * Uses ceiling division to match on-chain behavior (prevents fee evasion\n * via micro-trades).\n */\nexport function computeDynamicTradingFee(\n notional: bigint,\n config: FeeTierConfig,\n): bigint {\n const feeBps = computeDynamicFeeBps(notional, config);\n if (notional <= 0n || feeBps <= 0n) return 0n;\n return (notional * feeBps + 9999n) / 10000n;\n}\n\n/**\n * Fee split configuration.\n */\nexport interface FeeSplitConfig {\n /** LP vault share in bps (0–10_000) */\n lpBps: bigint;\n /** Protocol treasury share in bps */\n protocolBps: bigint;\n /** Market creator share in bps */\n creatorBps: bigint;\n}\n\n/**\n * Compute fee split for a total fee amount.\n *\n * Returns [lpShare, protocolShare, creatorShare].\n * If all split params are 0, 100% goes to LP (legacy behavior).\n * Creator gets the rounding remainder to ensure total is preserved.\n */\nexport function computeFeeSplit(\n totalFee: bigint,\n config: FeeSplitConfig,\n): [bigint, bigint, bigint] {\n if (config.lpBps === 0n && config.protocolBps === 0n && config.creatorBps === 0n) {\n return [totalFee, 0n, 0n];\n }\n\n // Validate that splits equal exactly 100%\n const totalBps = config.lpBps + config.protocolBps + config.creatorBps;\n if (totalBps !== 10000n) {\n throw new Error(\n `Fee split must equal exactly 10000 bps (100%): lpBps=${config.lpBps} + protocolBps=${config.protocolBps} + ` +\n `creatorBps=${config.creatorBps} = ${totalBps}`,\n );\n }\n\n const lp = (totalFee * config.lpBps) / 10000n;\n const protocol = (totalFee * config.protocolBps) / 10000n;\n const creator = totalFee - lp - protocol; // only rounding dust (max 2 tokens)\n\n // Sanity check: creator should never be negative if validation above passes\n if (creator < 0n) {\n throw new Error(\n `Internal error: creator fee is negative (${creator}). ` +\n `This should not happen if lpBps + protocolBps + creatorBps <= 10000.`,\n );\n }\n\n return [lp, protocol, creator];\n}\n\n/**\n * Compute PnL as a percentage of capital.\n *\n * Uses BigInt scaling to avoid precision loss from Number(bigint) conversion.\n * Number(bigint) silently truncates values above 2^53, which can produce\n * incorrect percentages for large positions (e.g., tokens with 9 decimals\n * where capital > ~9M tokens in native units exceeds MAX_SAFE_INTEGER).\n */\nexport function computePnlPercent(\n pnlTokens: bigint,\n capital: bigint,\n): number {\n if (capital === 0n) return 0;\n const scaledPct = (pnlTokens * 10_000n) / capital;\n if (scaledPct > BigInt(Number.MAX_SAFE_INTEGER) || scaledPct < BigInt(-Number.MAX_SAFE_INTEGER)) {\n throw new Error(\n `computePnlPercent: scaled result ${scaledPct} exceeds Number.MAX_SAFE_INTEGER — precision loss`,\n );\n }\n return Number(scaledPct) / 100;\n}\n\n/**\n * Estimate entry price including fee impact (slippage approximation).\n *\n * @param oracleE6 - Current oracle price in e6 format.\n * @param tradingFeeBps - Trading fee in basis points.\n * @param direction - Trade direction: `\"long\"` or `\"short\"`.\n * @returns Estimated entry price in e6 format (higher for longs, lower for shorts).\n *\n * @example\n * ```ts\n * const entry = computeEstimatedEntryPrice(100_000_000n, 30n, \"long\");\n * // → 100_030_000n (oracle + 0.30% fee impact)\n * ```\n */\nexport function computeEstimatedEntryPrice(\n oracleE6: bigint,\n tradingFeeBps: bigint,\n direction: \"long\" | \"short\",\n): bigint {\n if (oracleE6 === 0n) return 0n;\n if (tradingFeeBps < 0n) {\n throw new Error(`computeEstimatedEntryPrice: tradingFeeBps must be non-negative, got ${tradingFeeBps}`);\n }\n const feeImpact = (oracleE6 * tradingFeeBps) / 10000n;\n const result = direction === \"long\" ? oracleE6 + feeImpact : oracleE6 - feeImpact;\n if (result <= 0n) {\n throw new Error(\n `computeEstimatedEntryPrice: result ${result} is non-positive (tradingFeeBps=${tradingFeeBps} too high for oracle=${oracleE6})`,\n );\n }\n return result;\n}\n\nconst MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);\nconst MIN_SAFE_BIGINT = BigInt(-Number.MAX_SAFE_INTEGER);\n\n/**\n * Convert per-slot funding rate (bps) to annualized percentage.\n *\n * @param fundingRateBpsPerSlot - Funding rate per slot in basis points (i64 from engine state).\n * @returns Annualized funding rate as a percentage (e.g. 12.5 = 12.5% APR).\n * @throws Error if the value exceeds Number.MAX_SAFE_INTEGER.\n *\n * @example\n * ```ts\n * const apr = computeFundingRateAnnualized(1n); // ~78.84% APR\n * ```\n */\nexport function computeFundingRateAnnualized(\n fundingRateBpsPerSlot: bigint,\n): number {\n if (fundingRateBpsPerSlot > MAX_SAFE_BIGINT || fundingRateBpsPerSlot < MIN_SAFE_BIGINT) {\n throw new Error(\n `computeFundingRateAnnualized: value ${fundingRateBpsPerSlot} exceeds safe integer range`,\n );\n }\n const bpsPerSlot = Number(fundingRateBpsPerSlot);\n const slotsPerYear = 2.5 * 60 * 60 * 24 * 365; // ~400ms slots\n return (bpsPerSlot * slotsPerYear) / 100;\n}\n\n/**\n * Compute margin required for a given notional and initial margin bps.\n *\n * @param notional - Trade notional value in native token units.\n * @param initialMarginBps - Initial margin requirement in basis points (e.g. 1000n = 10%).\n * @returns Required margin in native token units.\n *\n * @example\n * ```ts\n * const margin = computeRequiredMargin(10_000_000_000n, 1000n); // 10% of notional\n * // → 1_000_000_000n\n * ```\n */\nexport function computeRequiredMargin(\n notional: bigint,\n initialMarginBps: bigint,\n): bigint {\n return (notional * initialMarginBps) / 10000n;\n}\n\n/**\n * Compute maximum leverage from initial margin bps.\n *\n * Formula: leverage = 10000 / initialMarginBps\n * Uses scaled arithmetic to preserve precision for fractional leverage values.\n *\n * @param initialMarginBps - Initial margin requirement in basis points (e.g. 500n = 5% → 20x).\n * @returns Maximum leverage as a number (e.g. 20 for 500 bps, 3.003 for 3333 bps).\n * @throws Error if initialMarginBps is zero (infinite leverage is undefined).\n *\n * @example\n * ```ts\n * const maxLev = computeMaxLeverage(500n); // → 20\n * const maxLev2 = computeMaxLeverage(1000n); // → 10\n * const maxLev3 = computeMaxLeverage(3333n); // → 3.003 (not truncated to 3)\n * ```\n */\nexport function computeMaxLeverage(initialMarginBps: bigint): number {\n if (initialMarginBps <= 0n) {\n throw new Error(\"computeMaxLeverage: initialMarginBps must be positive\");\n }\n // Use scaled arithmetic: (10000 * 1e6) / initialMarginBps / 1e6\n // This preserves fractional leverage instead of truncating\n const scaledResult = (10000n * 1_000_000n) / initialMarginBps;\n return Number(scaledResult) / 1_000_000;\n}\n\n/**\n * Compute the maximum amount that can be withdrawn from a position.\n *\n * The withdrawable amount is the capital plus any matured (unreserved) PnL.\n * Reserved PnL is still locked and cannot be withdrawn until the warmup period elapses.\n *\n * Formula: max_withdrawable = capital + max(0, pnl - reserved_pnl)\n *\n * @param capital - Capital allocated to the position (in native token units)\n * @param pnl - Mark-to-market PnL (in native token units, can be negative)\n * @param reservedPnl - PnL that is still locked during warmup (always non-negative)\n * @returns The maximum amount in native units that can be withdrawn without closing the position\n *\n * @example\n * ```ts\n * // Position: 10 SOL capital, +2 SOL mark PnL, 0.5 SOL reserved\n * const max = computeMaxWithdrawable(\n * 10_000_000_000n, // 10 SOL in lamports\n * 2_000_000_000n, // +2 SOL in lamports\n * 500_000_000n // 0.5 SOL reserved in lamports\n * );\n * // Returns: 11_500_000_000n (10 + (2 - 0.5) = 11.5 SOL in lamports)\n * ```\n */\nexport function computeMaxWithdrawable(\n capital: bigint,\n pnl: bigint,\n reservedPnl: bigint,\n): bigint {\n const maturedPnl = pnl - reservedPnl;\n return capital + (maturedPnl > 0n ? maturedPnl : 0n);\n}\n","/**\n * Warmup leverage cap utilities.\n *\n * During the market warmup period, capital is released linearly over\n * `warmupPeriodSlots` slots, which constrains the effective leverage\n * and maximum position size available to traders.\n */\n\nimport { computeMaxLeverage } from \"./trading.js\";\n\n// =============================================================================\n// Warmup leverage cap utilities\n// =============================================================================\n\n/**\n * Compute unlocked capital during the warmup period.\n *\n * Capital is released linearly over `warmupPeriodSlots` slots starting from\n * `warmupStartedAtSlot`. Before warmup starts (startSlot === 0) or if the\n * warmup period is 0, all capital is considered unlocked.\n *\n * @param totalCapital - Total deposited capital (native units).\n * @param currentSlot - The current on-chain slot.\n * @param warmupStartSlot - Slot at which warmup started (0 = not started).\n * @param warmupPeriodSlots - Total slots in the warmup period.\n * @returns The amount of capital currently unlocked.\n */\nexport function computeWarmupUnlockedCapital(\n totalCapital: bigint,\n currentSlot: bigint,\n warmupStartSlot: bigint,\n warmupPeriodSlots: bigint,\n): bigint {\n // No warmup configured or not started → all capital available\n if (warmupPeriodSlots === 0n || warmupStartSlot === 0n) return totalCapital;\n if (totalCapital <= 0n) return 0n;\n\n const elapsed = currentSlot > warmupStartSlot\n ? currentSlot - warmupStartSlot\n : 0n;\n\n // Warmup complete\n if (elapsed >= warmupPeriodSlots) return totalCapital;\n\n // Linear unlock: totalCapital * elapsed / warmupPeriodSlots\n return (totalCapital * elapsed) / warmupPeriodSlots;\n}\n\n/**\n * Compute the effective maximum leverage during the warmup period.\n *\n * During warmup, only unlocked capital can be used as margin. The effective\n * leverage relative to *total* capital is therefore capped at:\n *\n * effectiveMaxLeverage = maxLeverage × (unlockedCapital / totalCapital)\n *\n * This returns a floored integer value (leverage is always a whole number\n * in the UI), with a minimum of 1x if any capital is unlocked.\n *\n * @param initialMarginBps - Initial margin requirement in basis points.\n * @param totalCapital - Total deposited capital (native units).\n * @param currentSlot - The current on-chain slot.\n * @param warmupStartSlot - Slot at which warmup started (0 = not started).\n * @param warmupPeriodSlots - Total slots in the warmup period.\n * @returns The effective maximum leverage (integer, ≥ 1).\n */\nexport function computeWarmupLeverageCap(\n initialMarginBps: bigint,\n totalCapital: bigint,\n currentSlot: bigint,\n warmupStartSlot: bigint,\n warmupPeriodSlots: bigint,\n): number {\n if (initialMarginBps <= 0n) {\n throw new Error(\"computeWarmupLeverageCap: initialMarginBps must be positive\");\n }\n const maxLev = computeMaxLeverage(initialMarginBps);\n\n // No warmup or warmup not started → full leverage\n if (warmupPeriodSlots === 0n || warmupStartSlot === 0n) return maxLev;\n if (totalCapital <= 0n) return 1;\n\n const unlocked = computeWarmupUnlockedCapital(\n totalCapital,\n currentSlot,\n warmupStartSlot,\n warmupPeriodSlots,\n );\n\n if (unlocked <= 0n) return 1; // At least 1x if nothing unlocked yet (slot 0 edge)\n\n // Effective leverage = maxLev * (unlocked / total), floored, min 1\n const scaledResult = (BigInt(maxLev) * unlocked) / totalCapital;\n\n // Ensure conversion to Number doesn't silently truncate for very large values\n if (scaledResult > BigInt(Number.MAX_SAFE_INTEGER)) {\n console.warn(\n `[computeWarmupLeverageCap] Warning: effective leverage ${scaledResult} exceeds MAX_SAFE_INTEGER, ` +\n `returning MAX_SAFE_INTEGER as a safety bound`,\n );\n return Number.MAX_SAFE_INTEGER;\n }\n\n const effectiveLev = Number(scaledResult);\n return Math.max(1, effectiveLev);\n}\n\n/**\n * Compute the maximum position size allowed during warmup.\n *\n * This is the unlocked capital multiplied by the base max leverage.\n * Unlike `computeWarmupLeverageCap` (which gives effective leverage\n * relative to total capital), this gives the absolute notional cap.\n *\n * @param initialMarginBps - Initial margin requirement in basis points.\n * @param totalCapital - Total deposited capital (native units).\n * @param currentSlot - The current on-chain slot.\n * @param warmupStartSlot - Slot at which warmup started (0 = not started).\n * @param warmupPeriodSlots - Total slots in the warmup period.\n * @returns Maximum position size in native units.\n */\nexport function computeWarmupMaxPositionSize(\n initialMarginBps: bigint,\n totalCapital: bigint,\n currentSlot: bigint,\n warmupStartSlot: bigint,\n warmupPeriodSlots: bigint,\n): bigint {\n const maxLev = computeMaxLeverage(initialMarginBps);\n const unlocked = computeWarmupUnlockedCapital(\n totalCapital,\n currentSlot,\n warmupStartSlot,\n warmupPeriodSlots,\n );\n return unlocked * BigInt(maxLev);\n}\n\n/**\n * Warmup progress information for a position.\n */\nexport interface WarmupProgress {\n /** PnL available for withdrawal right now (not locked by warmup). */\n maturedPnl: bigint;\n /** PnL still locked until warmup completes. */\n reservedPnl: bigint;\n /** Progress toward full warmup as a basis point (0–10,000). */\n progressBps: bigint;\n /** Slots remaining until full warmup (0 if fully matured). */\n slotsRemaining: bigint;\n}\n\n/**\n * Compute PnL warmup progress for a position.\n *\n * During the warmup period, a position's unrealized PnL is linearly released.\n * The portion available for withdrawal grows over time. This utility shows:\n * - How much PnL is currently available (matured)\n * - How much is still locked (reserved)\n * - Progress toward full maturation (as %)\n * - Slots remaining\n *\n * Users can display a progress bar or \"unlocks in X slots\" message to give\n * transparency into when their PnL becomes withdrawable.\n *\n * @param currentSlot - Current on-chain slot (from engine state).\n * @param warmupStartedAtSlot - Slot when this position's warmup started.\n * @param warmupPeriodSlots - Total warmup duration in slots (from market config).\n * @param pnl - Total realized + unrealized PnL (from account).\n * @param reservedPnl - PnL locked during warmup (from account).\n * @returns WarmupProgress with matured/reserved PnL, progress %, and slots remaining.\n *\n * @example\n * ```ts\n * const progress = computeWarmupProgress(\n * 10000n, // current slot\n * 9000n, // warmup started at slot 9000\n * 2000n, // warmup period = 2000 slots\n * 1000000000n, // pnl = 1 SOL\n * 600000000n // reserved = 0.6 SOL (60% still locked)\n * );\n * // Returns:\n * // maturedPnl: 400000000n (0.4 SOL available)\n * // reservedPnl: 600000000n (0.6 SOL locked)\n * // progressBps: 5000n (50% complete)\n * // slotsRemaining: 1000n (1000 slots until fully mature)\n * ```\n */\nexport function computeWarmupProgress(\n currentSlot: bigint,\n warmupStartedAtSlot: bigint,\n warmupPeriodSlots: bigint,\n pnl: bigint,\n reservedPnl: bigint,\n): WarmupProgress {\n // Guard: no warmup or hasn't started → all PnL is mature\n if (warmupPeriodSlots === 0n || warmupStartedAtSlot === 0n) {\n return {\n maturedPnl: pnl > 0n ? pnl : 0n,\n reservedPnl: 0n,\n progressBps: 10000n, // 100%\n slotsRemaining: 0n,\n };\n }\n\n const elapsed = currentSlot >= warmupStartedAtSlot\n ? currentSlot - warmupStartedAtSlot\n : 0n;\n\n // If warmup complete, all PnL is mature\n if (elapsed >= warmupPeriodSlots) {\n return {\n maturedPnl: pnl > 0n ? pnl : 0n,\n reservedPnl: 0n,\n progressBps: 10000n, // 100%\n slotsRemaining: 0n,\n };\n }\n\n // Progress: how much of the warmup period has elapsed\n const progressBps = (elapsed * 10000n) / warmupPeriodSlots;\n const slotsRemaining = warmupPeriodSlots - elapsed;\n\n // Matured PnL = total PnL × progress%, capped at total PnL\n // This represents the portion of PnL that has been linearly released\n const maturedPnl = pnl > 0n\n ? ((pnl * progressBps) / 10000n)\n : 0n;\n\n // The actual reserved amount from the account remains reserved, but\n // we can also compute how much is still locked by comparing to matured\n const locked = reservedPnl > 0n ? reservedPnl : 0n;\n\n return {\n maturedPnl,\n reservedPnl: locked,\n progressBps,\n slotsRemaining,\n };\n}\n","/**\n * Input validation utilities for CLI commands.\n * Provides descriptive error messages for invalid input.\n */\n\nimport { PublicKey } from \"@solana/web3.js\";\n\n// Constants for numeric limits\nconst U16_MAX = 65535;\nconst U64_MAX = BigInt(\"18446744073709551615\");\nconst I64_MIN = BigInt(\"-9223372036854775808\");\nconst I64_MAX = BigInt(\"9223372036854775807\");\nconst U128_MAX = (1n << 128n) - 1n;\nconst I128_MIN = -(1n << 127n);\nconst I128_MAX = (1n << 127n) - 1n;\n\n/**\n * Non-empty trimmed string of decimal digits only: `\"0\"` or `[1-9]\\\\d*` (no leading zeros\n * except a single zero). Rejects fractions, scientific notation, hex prefixes, and trailing junk.\n */\nfunction requireDecimalUIntString(value: string, field: string): string {\n const t = value.trim();\n if (t === \"\") {\n throw new ValidationError(field, `\"${value}\" is not a valid number`);\n }\n if (!/^(0|[1-9]\\d*)$/.test(t)) {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid non-negative integer (use decimal digits only, e.g. 123).`\n );\n }\n return t;\n}\n\nexport class ValidationError extends Error {\n constructor(\n public readonly field: string,\n message: string\n ) {\n super(`Invalid ${field}: ${message}`);\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Validate a public key string.\n *\n * @param value - Base58-encoded public key string.\n * @param field - Field name for error messages.\n * @returns Parsed `PublicKey` instance.\n * @throws {@link ValidationError} if the string is not a valid base58 public key.\n *\n * @example\n * ```ts\n * const key = validatePublicKey(\"11111111111111111111111111111111\", \"slab\");\n * ```\n */\nexport function validatePublicKey(value: string, field: string): PublicKey {\n try {\n return new PublicKey(value);\n } catch {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid base58 public key. ` +\n `Example: \"11111111111111111111111111111111\"`\n );\n }\n}\n\n/**\n * Validate a non-negative integer index (u16 range for accounts).\n *\n * @param value - Decimal string representing the index.\n * @param field - Field name for error messages.\n * @returns Parsed integer in `[0, 65535]`.\n * @throws {@link ValidationError} if the value is not a valid u16 integer.\n */\nexport function validateIndex(value: string, field: string): number {\n const t = requireDecimalUIntString(value, field);\n const bi = BigInt(t);\n if (bi > BigInt(U16_MAX)) {\n throw new ValidationError(\n field,\n `must be <= ${U16_MAX} (u16 max), got ${t}`\n );\n }\n // U16 range (0–65535) is always safe to convert to Number\n if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);\n }\n return Number(bi);\n}\n\n/**\n * Validate a non-negative amount (u64 range).\n *\n * @param value - Decimal string representing the amount.\n * @param field - Field name for error messages.\n * @returns Parsed `bigint` in `[0, 2^64 - 1]`.\n * @throws {@link ValidationError} if the value is negative or exceeds u64 max.\n */\nexport function validateAmount(value: string, field: string): bigint {\n const t = value.trim();\n if (!/^(0|[1-9]\\d*)$/.test(t)) {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid non-negative integer. Use decimal digits only.`\n );\n }\n const num = BigInt(t);\n if (num < 0n) {\n throw new ValidationError(field, `must be non-negative, got ${num}`);\n }\n if (num > U64_MAX) {\n throw new ValidationError(\n field,\n `must be <= ${U64_MAX} (u64 max), got ${num}`\n );\n }\n return num;\n}\n\n/**\n * Validate a u128 value.\n */\nexport function validateU128(value: string, field: string): bigint {\n const t = value.trim();\n if (!/^(0|[1-9]\\d*)$/.test(t)) {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid non-negative integer. Use decimal digits only.`\n );\n }\n const num = BigInt(t);\n if (num < 0n) {\n throw new ValidationError(field, `must be non-negative, got ${num}`);\n }\n if (num > U128_MAX) {\n throw new ValidationError(\n field,\n `must be <= ${U128_MAX} (u128 max), got ${num}`\n );\n }\n return num;\n}\n\n/**\n * Validate an i64 value.\n */\nexport function validateI64(value: string, field: string): bigint {\n const t = value.trim();\n if (!/^-?(0|[1-9]\\d*)$/.test(t)) {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid integer. Use decimal digits only, with optional leading minus.`\n );\n }\n const num = BigInt(t);\n if (num < I64_MIN) {\n throw new ValidationError(\n field,\n `must be >= ${I64_MIN} (i64 min), got ${num}`\n );\n }\n if (num > I64_MAX) {\n throw new ValidationError(\n field,\n `must be <= ${I64_MAX} (i64 max), got ${num}`\n );\n }\n return num;\n}\n\n/**\n * Validate an i128 value (trade sizes).\n */\nexport function validateI128(value: string, field: string): bigint {\n const t = value.trim();\n if (!/^-?(0|[1-9]\\d*)$/.test(t)) {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid integer. Use decimal digits only, with optional leading minus.`\n );\n }\n const num = BigInt(t);\n if (num < I128_MIN) {\n throw new ValidationError(\n field,\n `must be >= ${I128_MIN} (i128 min), got ${num}`\n );\n }\n if (num > I128_MAX) {\n throw new ValidationError(\n field,\n `must be <= ${I128_MAX} (i128 max), got ${num}`\n );\n }\n return num;\n}\n\n/**\n * Validate a basis points value (0–10000).\n *\n * @param value - Decimal string representing basis points.\n * @param field - Field name for error messages.\n * @returns Parsed integer in `[0, 10000]`.\n * @throws {@link ValidationError} if the value exceeds 10000.\n */\nexport function validateBps(value: string, field: string): number {\n const t = requireDecimalUIntString(value, field);\n const bi = BigInt(t);\n if (bi > 10000n) {\n throw new ValidationError(\n field,\n `must be <= 10000 (100%), got ${t}`\n );\n }\n // BPS range (0–10000) is always safe to convert to Number\n if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new ValidationError(field, `internal error: bps value exceeds MAX_SAFE_INTEGER`);\n }\n return Number(bi);\n}\n\n/**\n * Validate a u64 value.\n */\nexport function validateU64(value: string, field: string): bigint {\n return validateAmount(value, field);\n}\n\n/**\n * Validate a u16 value.\n */\nexport function validateU16(value: string, field: string): number {\n const t = requireDecimalUIntString(value, field);\n const bi = BigInt(t);\n if (bi > BigInt(U16_MAX)) {\n throw new ValidationError(\n field,\n `must be <= ${U16_MAX} (u16 max), got ${t}`\n );\n }\n // U16 range (0–65535) is always safe to convert to Number\n if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);\n }\n return Number(bi);\n}\n","/**\n * Smart Price Router — automatic oracle selection for any token.\n *\n * Given a token mint, discovers all available price sources (DexScreener, Pyth, Jupiter),\n * ranks them by liquidity/reliability, and returns the best oracle config.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type PriceSourceType = \"pyth\" | \"dex\" | \"jupiter\";\n\nexport interface PriceSource {\n type: PriceSourceType;\n /** Pool address (dex), Pyth feed ID (pyth), or mint (jupiter) */\n address: string;\n /** DEX id for dex sources */\n dexId?: string;\n /** Pair label e.g. \"SOL / USDC\" */\n pairLabel?: string;\n /** USD liquidity depth — higher is better */\n liquidity: number;\n /** Latest spot price in USD */\n price: number;\n /** Confidence score 0-100 (composite of liquidity, staleness, reliability) */\n confidence: number;\n}\n\nexport interface PriceRouterResult {\n mint: string;\n bestSource: PriceSource | null;\n allSources: PriceSource[];\n /** ISO timestamp of resolution */\n resolvedAt: string;\n}\n\n/** Options for {@link resolvePrice}. */\nexport interface ResolvePriceOptions {\n timeoutMs?: number;\n}\n\nconst DEFAULT_RESOLVE_TIMEOUT_MS = 15_000;\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nfunction combineAbortSignals(signals: AbortSignal[]): AbortSignal {\n const already = signals.find((s) => s.aborted);\n if (already) {\n const c = new AbortController();\n c.abort(already.reason);\n return c.signal;\n }\n const active = signals.filter((s) => !s.aborted);\n if (active.length === 0) {\n const c = new AbortController();\n c.abort();\n return c.signal;\n }\n if (active.length === 1) return active[0];\n const ctrl = new AbortController();\n for (const s of active) {\n s.addEventListener(\"abort\", () => ctrl.abort(s.reason), { once: true });\n }\n return ctrl.signal;\n}\n\nconst SUPPORTED_DEX_IDS = new Set([\"pumpswap\", \"raydium\", \"meteora\"]);\n\nfunction parseDexScreenerPairs(json: unknown): PriceSource[] {\n if (!isRecord(json)) return [];\n const rawPairs = json.pairs;\n if (!Array.isArray(rawPairs)) return [];\n const sources: PriceSource[] = [];\n\n for (const pair of rawPairs) {\n if (!isRecord(pair)) continue;\n if (pair.chainId !== \"solana\") continue;\n const dexId = String(pair.dexId || \"\").toLowerCase();\n if (!SUPPORTED_DEX_IDS.has(dexId)) continue;\n\n let liquidity = 0;\n if (isRecord(pair.liquidity) && typeof pair.liquidity.usd === \"number\") {\n liquidity = pair.liquidity.usd;\n }\n if (liquidity < 100) continue;\n\n let confidence = 30;\n if (liquidity > 1_000_000) confidence = 90;\n else if (liquidity > 100_000) confidence = 75;\n else if (liquidity > 10_000) confidence = 60;\n else if (liquidity > 1_000) confidence = 45;\n\n const priceUsd = pair.priceUsd;\n const rawPrice =\n typeof priceUsd === \"string\" || typeof priceUsd === \"number\"\n ? parseFloat(String(priceUsd))\n : NaN;\n if (!Number.isFinite(rawPrice) || rawPrice <= 0) continue;\n const price = rawPrice;\n\n let baseSym = \"?\";\n let quoteSym = \"?\";\n if (isRecord(pair.baseToken) && typeof pair.baseToken.symbol === \"string\") {\n baseSym = pair.baseToken.symbol;\n }\n if (isRecord(pair.quoteToken) && typeof pair.quoteToken.symbol === \"string\") {\n quoteSym = pair.quoteToken.symbol;\n }\n\n const addr = pair.pairAddress;\n sources.push({\n type: \"dex\",\n address: typeof addr === \"string\" ? addr : \"\",\n dexId,\n pairLabel: `${baseSym} / ${quoteSym}`,\n liquidity,\n price,\n confidence,\n });\n }\n\n sources.sort((a, b) => b.liquidity - a.liquidity);\n return sources.slice(0, 10);\n}\n\nfunction parseJupiterMintEntry(\n json: unknown,\n mint: string,\n): { price: number; mintSymbol: string } | null {\n if (!isRecord(json)) return null;\n const data = json.data;\n if (!isRecord(data)) return null;\n const row = data[mint];\n if (!isRecord(row)) return null;\n const rawPrice = row.price;\n if (rawPrice === undefined || rawPrice === null) return null;\n const price = parseFloat(String(rawPrice));\n if (!Number.isFinite(price) || price <= 0) return null;\n let mintSymbol = \"?\";\n if (typeof row.mintSymbol === \"string\") mintSymbol = row.mintSymbol;\n return { price, mintSymbol };}\n\n// ---------------------------------------------------------------------------\n// Top Solana tokens with known Pyth feeds (feed ID → symbol)\n// ---------------------------------------------------------------------------\n\nexport const PYTH_SOLANA_FEEDS: Record<string, { symbol: string; mint: string }> = {\n // SOL\n \"ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d\": { symbol: \"SOL\", mint: \"So11111111111111111111111111111111111111112\" },\n // BTC\n \"e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43\": { symbol: \"BTC\", mint: \"9n4nbM75f5Ui33ZbPYXn59EwSgE8CGsHtAeTH5YFeJ9E\" },\n // ETH\n \"ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace\": { symbol: \"ETH\", mint: \"7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs\" },\n // USDC\n \"eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a\": { symbol: \"USDC\", mint: \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\" },\n // USDT\n \"2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b\": { symbol: \"USDT\", mint: \"Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB\" },\n // BONK\n \"72b021217ca3fe68922a19aaf990109cb9d84e9ad004b4d2025ad6f529314419\": { symbol: \"BONK\", mint: \"DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263\" },\n // JTO\n \"b43660a5f790c69354b0729a5ef9d50d68f1df92107540210b9cccba1f947cc2\": { symbol: \"JTO\", mint: \"jtojtomepa8beP8AuQc6eXt5FriJwfFMwQx2v2f9mCL\" },\n // JUP\n \"0a0408d619e9380abad35060f9192039ed5042fa6f82301d0e48bb52be830996\": { symbol: \"JUP\", mint: \"JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN\" },\n // PYTH\n \"0bbf28e9a841a1cc788f6a361b17ca072d0ea3098a1e5df1c3922d06719579ff\": { symbol: \"PYTH\", mint: \"HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3\" },\n // RAY\n \"91568bae053f70f0c3fbf32eb55df25ec609fb8a21cfb1a0e3b34fc3caa1eab0\": { symbol: \"RAY\", mint: \"4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R\" },\n // ORCA\n \"37505261e557e251f40c2c721e52c4c8bfb2e54a12f450d0e24078276ad51b95\": { symbol: \"ORCA\", mint: \"orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE\" },\n // MNGO\n \"f9abf5eb70a2e68e21b72b68cc6e0a4d25e1d77e1ec16eae5b93068a2cb81f90\": { symbol: \"MNGO\", mint: \"MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac\" },\n // MSOL\n \"c2289a6a43d2ce91c6f55caec370f4acc38a2ed477f58813334c6d03749ff2a4\": { symbol: \"MSOL\", mint: \"mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So\" },\n // JITOSOL\n \"67be9f519b95cf24338801051f9a808eff0a578ccb388db73b7f6fe1de019ffb\": { symbol: \"JITOSOL\", mint: \"J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn\" },\n // WIF\n \"4ca4beeca86f0d164160323817a4e42b10010a724c2217c6ee41b54e6c5c4b03\": { symbol: \"WIF\", mint: \"EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm\" },\n // RENDER\n \"3573eb14b04aa0e4f7cf1e7ae1c2a0e3bc6100b2e476876ca079e10e2c42d7c6\": { symbol: \"RENDER\", mint: \"rndrizKT3MK1iimdxRdWabcF7Zg7AR5T4nud4EkHBof\" },\n // W\n \"eff7446475e218517566ea99e72a4abec2e1bd8498b43b7d8331e29dcb059389\": { symbol: \"W\", mint: \"85VBFQZC9TZkfaptBWjvUw7YbZjy52A6mjtPGjstQAmQ\" },\n // TNSR\n \"05ecd4597cd48fe13d6cc3596c62af4f9675aee06e2e0ca164a73be4b0813f3b\": { symbol: \"TNSR\", mint: \"TNSRxcUxoT9xBG3de7PiJyTDYu7kskLqcpddxnEJAS6\" },\n // HNT\n \"649fdd7ec08e8e2a20f425729854e90293dcbe2376abc47197a14da6ff339756\": { symbol: \"HNT\", mint: \"hntyVP6YFm1Hg25TN9WGLqM12b8TQmcknKrdu1oxWux\" },\n // MOBILE\n \"ff4c53361e36a9b1caa490f1e46e07e3c472d54d2a4856a1e4609bd4db36bff0\": { symbol: \"MOBILE\", mint: \"mb1eu7TzEc71KxDpsmsKoucSSuuoGLv1drys1oP2jh6\" },\n // IOT\n \"8bdd20f0c68bf7370a19389bbb3d17c1db7956c38efa08b2f3dd0e5db9b8c1ef\": { symbol: \"IOT\", mint: \"iotEVVZLEywoTn1QdwNPddxPWszn3zFhEot3MfL9fns\" },\n};\n\n// Reverse lookup: mint → feed ID\nconst MINT_TO_PYTH_FEED = new Map<string, { feedId: string; symbol: string }>();\nfor (const [feedId, info] of Object.entries(PYTH_SOLANA_FEEDS)) {\n MINT_TO_PYTH_FEED.set(info.mint, { feedId, symbol: info.symbol });\n}\n\n// ---------------------------------------------------------------------------\n// DexScreener fetcher\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_FETCH_TIMEOUT_MS = 10_000;\n\nfunction effectiveSignal(signal?: AbortSignal): AbortSignal {\n return signal ?? AbortSignal.timeout(DEFAULT_FETCH_TIMEOUT_MS);\n}\n\nasync function fetchDexSources(mint: string, signal?: AbortSignal): Promise<PriceSource[]> {\n try {\n const resp = await fetch(\n `https://api.dexscreener.com/latest/dex/tokens/${encodeURIComponent(mint)}`,\n {\n signal: effectiveSignal(signal),\n headers: { \"User-Agent\": \"percolator/1.0\" },\n },\n );\n if (!resp.ok) {\n console.debug(`[fetchDexSources] HTTP ${resp.status} for mint ${mint}`);\n return [];\n }\n const json: unknown = await resp.json();\n return parseDexScreenerPairs(json);\n } catch (err) {\n console.warn(\n `[fetchDexSources] Error fetching DexScreener data for mint ${mint}:`,\n err instanceof Error ? err.message : String(err),\n );\n return [];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Pyth lookup\n// ---------------------------------------------------------------------------\n\nfunction lookupPythSource(mint: string): PriceSource | null {\n const entry = MINT_TO_PYTH_FEED.get(mint);\n if (!entry) return null;\n return {\n type: \"pyth\",\n address: entry.feedId,\n pairLabel: `${entry.symbol} / USD (Pyth)`,\n liquidity: Number.MAX_SAFE_INTEGER, // Pyth is considered deep liquidity\n price: 0, // We don't fetch live price here; caller can enrich\n confidence: 95, // Pyth is highest reliability for supported tokens\n };\n}\n\n// ---------------------------------------------------------------------------\n// Jupiter price fallback\n// ---------------------------------------------------------------------------\n\nasync function fetchJupiterSource(mint: string, signal?: AbortSignal): Promise<PriceSource | null> {\n try {\n const resp = await fetch(\n `https://api.jup.ag/price/v2?ids=${encodeURIComponent(mint)}`,\n {\n signal: effectiveSignal(signal),\n headers: { \"User-Agent\": \"percolator/1.0\" },\n },\n );\n if (!resp.ok) {\n console.debug(`[fetchJupiterSource] HTTP ${resp.status} for mint ${mint}`);\n return null;\n }\n const json: unknown = await resp.json();\n const row = parseJupiterMintEntry(json, mint);\n if (!row) {\n console.debug(`[fetchJupiterSource] No price data from Jupiter for mint ${mint}`);\n return null;\n }\n return {\n type: \"jupiter\",\n address: mint,\n pairLabel: `${row.mintSymbol} / USD (Jupiter)`,\n liquidity: 0, // Jupiter aggregator — no single pool liquidity\n price: row.price,\n confidence: 40, // Fallback — lower confidence\n };\n } catch (err) {\n console.warn(\n `[fetchJupiterSource] Error fetching Jupiter data for mint ${mint}:`,\n err instanceof Error ? err.message : String(err),\n );\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Main resolver\n// ---------------------------------------------------------------------------\n\nexport async function resolvePrice(\n mint: string,\n signal?: AbortSignal,\n options?: ResolvePriceOptions,\n): Promise<PriceRouterResult> {\n const timeoutMs = options?.timeoutMs ?? DEFAULT_RESOLVE_TIMEOUT_MS;\n const timeoutSignal = AbortSignal.timeout(timeoutMs);\n const effectiveSignal = signal\n ? combineAbortSignals([signal, timeoutSignal])\n : timeoutSignal;\n\n const [dexSources, jupiterSource] = await Promise.all([\n fetchDexSources(mint, effectiveSignal),\n fetchJupiterSource(mint, effectiveSignal),\n ]);\n\n const pythSource = lookupPythSource(mint);\n\n const allSources: PriceSource[] = [];\n\n // Add Pyth if available (highest priority for supported tokens)\n if (pythSource) {\n // Enrich Pyth price from DEX and/or Jupiter — cross-validate when both exist\n const dexPrice = dexSources[0]?.price ?? 0;\n const jupPrice = jupiterSource?.price ?? 0;\n\n if (dexPrice > 0 && jupPrice > 0) {\n // Cross-validate: reject if sources diverge by more than 50%\n const mid = (dexPrice + jupPrice) / 2;\n const deviation = Math.abs(dexPrice - jupPrice) / mid;\n if (deviation > 0.5) {\n // Sources disagree significantly — don't enrich Pyth, lower confidence\n pythSource.price = 0;\n pythSource.confidence = 20;\n } else {\n pythSource.price = mid;\n }\n } else {\n // Only one source available — use it but note reduced validation\n pythSource.price = dexPrice || jupPrice || 0;\n }\n allSources.push(pythSource);\n }\n\n // Add DEX sources\n allSources.push(...dexSources);\n\n // Add Jupiter as fallback\n if (jupiterSource) {\n allSources.push(jupiterSource);\n }\n\n // Sort by confidence descending (already accounts for liquidity/reliability)\n allSources.sort((a, b) => b.confidence - a.confidence);\n\n return {\n mint,\n bestSource: allSources[0] || null,\n allSources,\n resolvedAt: new Date().toISOString(),\n };\n}\n"],"mappings":"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AG;AAAA,IACD,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,GAAG;AAAA,IACD,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,GAAG;AAAA,IACD,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,GAAG;AAAA,IACD,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,GAAG;AAAA,IACD,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,GAAG;AAAA,IACD,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA;AAAA,EAEA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MA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","names":["dv","PublicKey","PublicKey","AccountKind","PublicKey","PublicKey","PublicKey","TOKEN_PROGRAM_ID","PublicKey","PublicKey","ENGINE_BITMAP_OFF_V0","dv","readU16LE","readU64LE","readI64LE","readU128LE","readI128LE","results","PublicKey","PublicKey","PublicKey","readU64LE","dv","readU128LE","readU8","PublicKey","TOKEN_PROGRAM_ID","PublicKey","SystemProgram","SYSVAR_RENT_PUBKEY","SYSVAR_CLOCK_PUBKEY","TOKEN_PROGRAM_ID","PublicKey","PublicKey","readU64LE","readU16LE","TOKEN_PROGRAM_ID","SystemProgram","SYSVAR_RENT_PUBKEY","SYSVAR_CLOCK_PUBKEY","SYSVAR_CLOCK_PUBKEY","SYSVAR_CLOCK_PUBKEY","Connection","TransactionInstruction","TransactionInstruction","PublicKey","Transaction","LIGHTHOUSE_PROGRAM_ID_STR","PublicKey","effectiveSignal"]}