@percolatorct/sdk 1.0.0-beta.9 → 2.0.0
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/README.md +24 -4
- package/dist/abi/accounts.d.ts +129 -25
- package/dist/abi/errors.d.ts +0 -11
- package/dist/abi/index.d.ts +1 -0
- package/dist/abi/instructions.d.ts +429 -150
- package/dist/abi/nft.d.ts +136 -0
- package/dist/config/program-ids.d.ts +1 -1
- package/dist/index.js +1893 -688
- package/dist/index.js.map +1 -1
- package/dist/math/trading.d.ts +1 -116
- package/dist/math/warmup.d.ts +0 -50
- package/dist/runtime/lighthouse.d.ts +1 -1
- package/dist/solana/discovery.d.ts +2 -13
- package/dist/solana/oracle.d.ts +2 -10
- package/dist/solana/pda.d.ts +6 -5
- package/dist/solana/slab.d.ts +133 -9
- package/dist/solana/stake.d.ts +51 -9
- package/dist/validation.d.ts +1 -26
- package/package.json +5 -2
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 // Tags 22-23: on-chain these are SetInsuranceWithdrawPolicy / WithdrawInsuranceLimited.\n // Legacy aliases (UpdateRiskParams/RenounceAdmin) kept for backward compat.\n SetInsuranceWithdrawPolicy: 22,\n /** @deprecated Use SetInsuranceWithdrawPolicy */ UpdateRiskParams: 22,\n WithdrawInsuranceLimited: 23,\n /** @deprecated Use WithdrawInsuranceLimited */ RenounceAdmin: 23,\n // Tags 24–26: on-chain = QueryLpFees/ReclaimEmptyAccount/SettleAccount.\n // Old insurance LP tags removed — those moved to percolator-stake.\n QueryLpFees: 24,\n ReclaimEmptyAccount: 25,\n SettleAccount: 26,\n // Tags 27-28: on-chain = DepositFeeCredits/ConvertReleasedPnl.\n // Legacy aliases (PauseMarket/UnpauseMarket) kept — those instructions don't exist on-chain.\n DepositFeeCredits: 27,\n /** @deprecated No on-chain PauseMarket instruction */ PauseMarket: 27,\n ConvertReleasedPnl: 28,\n /** @deprecated No on-chain UnpauseMarket instruction */ UnpauseMarket: 28,\n // Tags 29-30: on-chain = ResolvePermissionless/ForceCloseResolved.\n ResolvePermissionless: 29,\n /** @deprecated Use ResolvePermissionless */ AcceptAdmin: 29,\n ForceCloseResolved: 30,\n // Tag 31: gap (no decode arm on-chain)\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;\n confFilterBps: number;\n invert: number;\n unitScale: number;\n initialMarkPriceE6: bigint | string;\n // Fields between header and RiskParams (immutable after init, default 0 if omitted)\n maxMaintenanceFeePerSlot?: bigint | string; // u128 — max maintenance fee per slot\n maxInsuranceFloor?: bigint | string; // u128 — max insurance floor\n minOraclePriceCap?: bigint | string; // u64 — min oracle price cap in e2bps\n // RiskParams block (15 fields, read by read_risk_params on-chain)\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; // maps to insurance_floor slot on-chain\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 minInitialDeposit: bigint | string; // u128 — min deposit to open account\n minNonzeroMmReq: bigint | string; // u128 — must be > 0, < minNonzeroImReq\n minNonzeroImReq: bigint | string; // u128 — must be > minNonzeroMmReq, <= minInitialDeposit\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\n// tag(1) + admin(32) + mint(32) + feedId(32) + staleness(8) + conf(2) + invert(1) + scale(4) +\n// markPrice(8) + maxMaintFee(16) + maxInsFloor(16) + minOracleCap(8) +\n// RiskParams: warmup(8) + mmBps(8) + imBps(8) + tradeFee(8) + maxAcct(8) + newAcctFee(16) +\n// riskRedThresh(16) + maintFee(16) + maxStale(8) + liqFee(8) + liqCap(16) + liqBuf(8) +\n// minLiqAbs(16) + minDeposit(16) + minMm(16) + minIm(16)\n// = 1+32+32+32+8+2+1+4+8+16+16+8 + 8+8+8+8+8+16+16+16+8+8+16+8+16+16+16+16 = 352\nconst INIT_MARKET_DATA_LEN = 352;\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 // 3 fields between header and RiskParams (immutable after init)\n encU128(args.maxMaintenanceFeePerSlot ?? 0n),\n encU128(args.maxInsuranceFloor ?? 0n),\n encU64(args.minOraclePriceCap ?? 0n),\n // RiskParams block (15 fields)\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 encU128(args.minInitialDeposit),\n encU128(args.minNonzeroMmReq),\n encU128(args.minNonzeroImReq),\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\n// ============================================================================\n// Missing encoders — corrected tag mappings (tags 22-74)\n// ============================================================================\n\n/** SetInsuranceWithdrawPolicy (tag 22): authority + min_withdraw_base + max_withdraw_bps + cooldown_slots */\nexport interface SetInsuranceWithdrawPolicyArgs {\n authority: PublicKey | string;\n minWithdrawBase: bigint | string;\n maxWithdrawBps: number;\n cooldownSlots: bigint | string;\n}\nexport function encodeSetInsuranceWithdrawPolicy(args: SetInsuranceWithdrawPolicyArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.SetInsuranceWithdrawPolicy), encPubkey(args.authority), encU64(args.minWithdrawBase), encU16(args.maxWithdrawBps), encU64(args.cooldownSlots));\n}\n\n/** WithdrawInsuranceLimited (tag 23): amount */\nexport function encodeWithdrawInsuranceLimited(args: { amount: bigint | string }): Uint8Array {\n return concatBytes(encU8(IX_TAG.WithdrawInsuranceLimited), encU64(args.amount));\n}\n\n/** ResolvePermissionless (tag 29): no args */\nexport function encodeResolvePermissionless(): Uint8Array {\n return concatBytes(encU8(IX_TAG.ResolvePermissionless));\n}\n\n/** ForceCloseResolved (tag 30): user_idx */\nexport function encodeForceCloseResolved(args: { userIdx: number }): Uint8Array {\n return concatBytes(encU8(IX_TAG.ForceCloseResolved), encU16(args.userIdx));\n}\n\n/** CreateLpVault (tag 37): fee_share_bps + util_curve_enabled */\nexport function encodeCreateLpVault(args: { feeShareBps: bigint | string; utilCurveEnabled?: boolean }): Uint8Array {\n const parts = [encU8(IX_TAG.CreateLpVault), encU64(args.feeShareBps)];\n if (args.utilCurveEnabled !== undefined) {\n parts.push(encU8(args.utilCurveEnabled ? 1 : 0));\n }\n return concatBytes(...parts);\n}\n\n/** LpVaultDeposit (tag 38): amount */\nexport function encodeLpVaultDeposit(args: { amount: bigint | string }): Uint8Array {\n return concatBytes(encU8(IX_TAG.LpVaultDeposit), encU64(args.amount));\n}\n\n/** LpVaultCrankFees (tag 40): no args */\nexport function encodeLpVaultCrankFees(): Uint8Array {\n return concatBytes(encU8(IX_TAG.LpVaultCrankFees));\n}\n\n/** ChallengeSettlement (tag 43): proposed_price_e6 */\nexport function encodeChallengeSettlement(args: { proposedPriceE6: bigint | string }): Uint8Array {\n return concatBytes(encU8(IX_TAG.ChallengeSettlement), encU64(args.proposedPriceE6));\n}\n\n/** ResolveDispute (tag 44): accept (0 = reject, 1 = accept) */\nexport function encodeResolveDispute(args: { accept: number }): Uint8Array {\n return concatBytes(encU8(IX_TAG.ResolveDispute), encU8(args.accept));\n}\n\n/** DepositLpCollateral (tag 45): user_idx + lp_amount */\nexport function encodeDepositLpCollateral(args: { userIdx: number; lpAmount: bigint | string }): Uint8Array {\n return concatBytes(encU8(IX_TAG.DepositLpCollateral), encU16(args.userIdx), encU64(args.lpAmount));\n}\n\n/** WithdrawLpCollateral (tag 46): user_idx + lp_amount */\nexport function encodeWithdrawLpCollateral(args: { userIdx: number; lpAmount: bigint | string }): Uint8Array {\n return concatBytes(encU8(IX_TAG.WithdrawLpCollateral), encU16(args.userIdx), encU64(args.lpAmount));\n}\n\n/** SetOffsetPair (tag 54): offset_bps */\nexport function encodeSetOffsetPair(args: { offsetBps: number }): Uint8Array {\n return concatBytes(encU8(IX_TAG.SetOffsetPair), encU16(args.offsetBps));\n}\n\n/** AttestCrossMargin (tag 55): user_idx_a + user_idx_b */\nexport function encodeAttestCrossMargin(args: { userIdxA: number; userIdxB: number }): Uint8Array {\n return concatBytes(encU8(IX_TAG.AttestCrossMargin), encU16(args.userIdxA), encU16(args.userIdxB));\n}\n\n/** RescueOrphanVault (tag 72): no args */\nexport function encodeRescueOrphanVault(): Uint8Array {\n return concatBytes(encU8(IX_TAG.RescueOrphanVault));\n}\n\n/** CloseOrphanSlab (tag 73): no args */\nexport function encodeCloseOrphanSlab(): Uint8Array {\n return concatBytes(encU8(IX_TAG.CloseOrphanSlab));\n}\n\n/** SetDexPool (tag 74): pool pubkey */\nexport function encodeSetDexPool(args: { pool: PublicKey | string }): Uint8Array {\n return concatBytes(encU8(IX_TAG.SetDexPool), encPubkey(args.pool));\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; // aarch64 size (320). SBF uses 280 due to u128 align diff.\nconst V12_1_ACCOUNT_SIZE_SBF = 280; // Empirically verified from mainnet SLAB_LEN\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\n// SBF offsets (empirically verified via repr(C) with u128 align=8):\n// position_basis_q is at offset 88 on SBF (between warmup_slope_per_step and adl_a_basis)\n// entry_price was REMOVED from Account in V12_1 upstream rebase\nconst V12_1_ACCT_POSITION_SIZE_OFF = 88; // position_basis_q: i128 at offset 88 (SBF)\nconst V12_1_ACCT_ENTRY_PRICE_OFF = -1; // REMOVED in V12_1 — does not exist\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 on aarch64, 280 on SBF.\n // The SBF binary has different struct alignment (u128 align=8 vs 16 on aarch64).\n // Register BOTH host-computed and SBF-empirical sizes for detection.\n V12_1_SIZES.set(computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, n, 18), n);\n}\n// SBF-specific V12_1 sizes (empirically verified from deployed mainnet binary).\n// Account=280 bytes on SBF (vs 320 on aarch64) due to u128 alignment difference.\nconst V12_1_SBF_ACCOUNT_SIZE = 280;\nconst V12_1_SBF_ENGINE_PREAMBLE = 558;\nfor (const [, n] of [[\"Micro\", 64], [\"Small\", 256], [\"Medium\", 1024], [\"Large\", 4096]] as const) {\n const bitmapBytes = Math.ceil(n / 64) * 8;\n const preAccLen = V12_1_SBF_ENGINE_PREAMBLE + bitmapBytes + 18 + n * 2;\n const accountsOff = Math.ceil(preAccLen / 8) * 8;\n const total = V12_1_ENGINE_OFF + accountsOff + n * V12_1_SBF_ACCOUNT_SIZE;\n V12_1_SIZES.set(total, 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, dataLen?: number): SlabLayout {\n const engineOff = V12_1_ENGINE_OFF;\n const bitmapOff = V12_1_ENGINE_BITMAP_OFF;\n // Detect SBF vs host alignment from actual slab size.\n // SBF Account=280 (u128 align=8), host Account=320 (u128 align=16).\n const hostSize = computeSlabSize(engineOff, bitmapOff, V12_1_ACCOUNT_SIZE, maxAccounts, 18);\n const isSbf = dataLen !== undefined && dataLen !== hostSize;\n const accountSize = isSbf ? V12_1_ACCOUNT_SIZE_SBF : 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 // V12_1 upstream rebase uses 72-byte header (SlabHeader only, no V1 extension).\n // Empirically verified: USDC mint found at offset 72 on mainnet slab BVjPc6rd.\n headerLen: V0_HEADER_LEN, // 72 (not 104 — V12_1 removed the 32-byte header extension)\n configOffset: V0_HEADER_LEN, // 72\n configLen: 576, // 544 + 32 (dex_pool: [u8;32] added in V12_1)\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, dataLen);\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 etc. removed in V12_1 upstream rebase\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 // NOTE: Extended funding fields (fundingPremiumWeightBps, fundingSettlementIntervalSlots,\n // fundingPremiumDampeningE6, fundingPremiumMaxBpsPerSlot) were removed in V12_1 upstream\n // rebase. They do NOT exist in the on-chain MarketConfig struct. Reading them here shifted\n // all subsequent fields by 32 bytes, causing oracle_authority to read garbage.\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: 0n,\n fundingSettlementIntervalSlots: 0n,\n fundingPremiumDampeningE6: 0n,\n fundingPremiumMaxBpsPerSlot: 0n,\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 // V12_1: engineOff=648 + bitmapOff(rel)=368. Detect by engineOff (most reliable).\n // Account is 320 on aarch64, 280 on SBF — accountSize alone is ambiguous.\n const isV12_1 = layout.engineOff === V12_1_ENGINE_OFF && (layout.accountSize === V12_1_ACCOUNT_SIZE || layout.accountSize === V12_1_ACCOUNT_SIZE_SBF);\n const isAdl = layout.accountSize >= 312 || isV12_1;\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: entryPriceOff >= 0 ? readU64LE(data, base + entryPriceOff) : 0n, // V12_1: entry_price removed\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.mainnet);\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: \"ESa89R5Es3rJ5mnwGybVRG1GrNt9etP11Z5V2QWD4edv\",\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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ACN,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,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,I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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/abi/nft.ts","../src/config/program-ids.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/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 = 0xFF;\nconst U16_MAX = 0xFFFF;\nconst U32_MAX = 0xFFFFFFFF;\n\n/**\n * Encode u8 (1 byte)\n */\nexport function encU8(val: number): Uint8Array {\n if (!Number.isInteger(val) || val < 0 || val > U8_MAX) {\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 > U16_MAX) {\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 > U32_MAX) {\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 * 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 // 16, 17 — removed in v1.0.0-beta.29 (Phase G admin-push oracle removal)\n SetOraclePriceCap: 18,\n ResolveMarket: 19,\n WithdrawInsurance: 20,\n AdminForceClose: 21,\n // Tags 22-23: on-chain these are SetInsuranceWithdrawPolicy / WithdrawInsuranceLimited.\n // Legacy aliases (UpdateRiskParams/RenounceAdmin) kept for backward compat.\n SetInsuranceWithdrawPolicy: 22,\n /** @deprecated Use SetInsuranceWithdrawPolicy */ UpdateRiskParams: 22,\n WithdrawInsuranceLimited: 23,\n /** @deprecated Use WithdrawInsuranceLimited */ RenounceAdmin: 23,\n // Tags 24–26: on-chain = QueryLpFees/ReclaimEmptyAccount/SettleAccount.\n // Old insurance LP tags removed — those moved to percolator-stake.\n QueryLpFees: 24,\n ReclaimEmptyAccount: 25,\n SettleAccount: 26,\n // Tags 27-28: on-chain = DepositFeeCredits/ConvertReleasedPnl.\n DepositFeeCredits: 27,\n ConvertReleasedPnl: 28,\n // Tags 29-30: on-chain = ResolvePermissionless/ForceCloseResolved.\n ResolvePermissionless: 29,\n // Note: `AcceptAdmin` used to be a @deprecated alias for tag 29; removed in\n // beta.27 because AcceptAdmin is now a real instruction at tag 82 (Phase E).\n ForceCloseResolved: 30,\n // Tag 31: gap (no decode arm on-chain)\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 // 57: removed (keeper fund)\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 /** PauseMarket (tag 76): admin emergency pause. Blocks Trade/Deposit/Withdraw/InitUser. */\n PauseMarket: 76,\n /** UnpauseMarket (tag 77): admin unpause. Re-enables all operations. */\n UnpauseMarket: 77,\n /** PERC-305 / SECURITY(H-4): Set PnL cap for ADL pre-check (admin only). */\n SetMaxPnlCap: 78,\n /** PERC-309: Set OI cap multiplier for LP withdrawal limits (admin only). Packed u64. */\n SetOiCapMultiplier: 79,\n /** PERC-314: Set dispute params (window_slots + bond_amount, admin only). */\n SetDisputeParams: 80,\n /** PERC-315: Set LP collateral params (enabled + ltv_bps, admin only). */\n SetLpCollateralParams: 81,\n /** Phase E (2026-04-17): Accept a pending admin transfer. Signer must match pending_admin. */\n AcceptAdmin: 82,\n /**\n * v12.18.x 4-way authority split (added 2026-04-22, wrapper 86ea41f).\n * Unified mutator for admin/hyperp_mark/insurance/insurance_operator.\n * Wrapper handler: src/percolator.rs:6876.\n */\n UpdateAuthority: 83,\n // 78: removed (keeper fund)\n} as const;\nObject.freeze(IX_TAG);\n\nfunction removedInstruction(name: string, tag: number, replacement?: string): never {\n const suffix = replacement ? ` Use ${replacement} instead.` : \"\";\n throw new Error(\n `${name} (tag ${tag}) is not accepted by the deployed wrapper program.${suffix}`,\n );\n}\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 */\n/**\n * Optional 66-byte extended tail for InitMarket (S-4).\n *\n * When present and any field is non-zero the encoder appends a 66-byte block\n * in the exact order that the program reads it (percolator.rs:1516-1545):\n * insurance_withdraw_max_bps u16 (2 bytes)\n * insurance_withdraw_cooldown_slots u64 (8 bytes)\n * permissionless_resolve_stale_slots u64 (8 bytes)\n * funding_horizon_slots u64 (8 bytes)\n * funding_k_bps u64 (8 bytes)\n * funding_max_premium_bps i64 (8 bytes)\n * funding_max_bps_per_slot i64 (8 bytes)\n * mark_min_fee u64 (8 bytes)\n * force_close_delay_slots u64 (8 bytes)\n * total = 2 + 8*8 = 66 bytes\n *\n * When absent (or all fields are zero) the encoder omits the tail and the\n * program treats all extended fields as their default zero values. This\n * preserves full backward compatibility with existing 344-byte payloads.\n */\nexport interface InitMarketExtendedTail {\n /** Maximum percentage of insurance fund withdrawable per cooldown window (0–10 000 bps). */\n insuranceWithdrawMaxBps: number;\n /** Slots that must elapse between insurance withdrawals. Required when insuranceWithdrawMaxBps > 0. */\n insuranceWithdrawCooldownSlots: bigint | string;\n /** Slots after which an unresolved market may be permissionlessly resolved. */\n permissionlessResolveStaleSlots: bigint | string;\n /** Funding rate horizon in slots (custom_funding_k denominator). */\n fundingHorizonSlots: bigint | string;\n /** Funding rate K parameter in bps (0 = disabled). */\n fundingKBps: bigint | string;\n /** Maximum funding premium in bps (i64 — may be negative to flip direction). */\n fundingMaxPremiumBps: bigint | string;\n /** Maximum funding rate change per slot in bps (i64). */\n fundingMaxBpsPerSlot: bigint | string;\n /** Minimum fee charged per mark-price update (u64, in collateral base units). */\n markMinFee: bigint | string;\n /** Slots to delay forced close after trigger condition is met (0 = immediate). */\n forceCloseDelaySlots: bigint | string;\n}\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;\n confFilterBps: number;\n invert: number;\n unitScale: number;\n initialMarkPriceE6: bigint | string;\n // Fields between header and RiskParams (immutable after init, default 0 if omitted)\n maxMaintenanceFeePerSlot?: bigint | string; // u128 — max maintenance fee per slot\n /** @deprecated v12.17-only field. v12.19 wrapper does not read it. Kept for source-compat, value ignored. */\n maxInsuranceFloor?: bigint | string;\n /** @deprecated v12.17-only field. v12.19 wrapper does not read it. Kept for source-compat, value ignored. */\n minOraclePriceCap?: bigint | string;\n // RiskParams block (16 fields, read by read_risk_params on-chain)\n /**\n * @deprecated Use hMin and hMax instead (v12.15+). Accepted as fallback for both hMin and hMax\n * when hMin/hMax are not provided.\n */\n warmupPeriodSlots?: bigint | string;\n /** Minimum horizon slots (v12.15+). Falls back to warmupPeriodSlots if not provided. */\n hMin?: bigint | string;\n /** Maximum horizon slots (v12.15+). Falls back to warmupPeriodSlots if not provided. */\n hMax?: bigint | string;\n maintenanceMarginBps: bigint | string;\n initialMarginBps: bigint | string;\n tradingFeeBps: bigint | string;\n maxAccounts: bigint | string;\n newAccountFee: bigint | string;\n insuranceFloor?: bigint | string; // u128 — wire slot: old riskReductionThreshold → insurance_floor\n maintenanceFeePerSlot: bigint | string;\n maxCrankStalenessSlots: bigint | string;\n liquidationFeeBps: bigint | string;\n liquidationFeeCap: bigint | string;\n liquidationBufferBps?: bigint | string; // u64 — wire compat: read and discarded by program\n minLiquidationAbs: bigint | string;\n /** @deprecated v12.17-only top-level field. v12.19 wrapper does not read a separate min_initial_deposit. Kept for source-compat, value ignored. */\n minInitialDeposit?: bigint | string;\n minNonzeroMmReq: bigint | string; // u128 — must be > 0, < minNonzeroImReq\n minNonzeroImReq: bigint | string; // u128 — must be > minNonzeroMmReq, <= minInitialDeposit\n /**\n * Optional 66-byte extended tail (S-4).\n * When present and any field is non-zero, appended after the 344-byte base payload.\n * When absent (or all zeros), the base 344-byte payload is sent and the program\n * uses default zero values for all extended fields.\n * @see InitMarketExtendedTail\n */\n extendedTail?: InitMarketExtendedTail;\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\n// v12.19 layout: tag(1) + admin(32) + mint(32) + feedId(32) + staleness(8) + conf(2) + invert(1) + scale(4) +\n// markPrice(8) + maxMaintFee(16) +\n// RiskParams: hMin(8) + mmBps(8) + imBps(8) + tradeFee(8) + maxAcct(8) + newAcctFee(16) +\n// insFloor(16) + hMax(8) + maxStale(8) + liqFee(8) + liqCap(16) + resolveDev(8) +\n// minLiqAbs(16) + minMm(16) + minIm(16)\n// = 1+32+32+32+8+2+1+4+8+16 + 8+8+8+8+8+16+16+8+8+8+16+8+16+16+16 = 304\nconst INIT_MARKET_BASE_LEN = 304;\n\n// Extended tail: u16(2) + u64*8(64) = 66 bytes (percolator.rs EXTENDED_TAIL_LEN = 2 + 8*8)\nconst INIT_MARKET_EXTENDED_TAIL_LEN = 66;\n\n/**\n * Returns true if the ExtendedTail contains at least one non-zero field.\n * When all fields are zero the base 344-byte payload is sufficient — the\n * program treats an empty rest as all-zero defaults.\n */\nfunction extendedTailHasNonZero(t: InitMarketExtendedTail): boolean {\n const toBigInt = (v: bigint | string): bigint =>\n typeof v === \"string\" ? BigInt(v) : v;\n return (\n t.insuranceWithdrawMaxBps !== 0 ||\n toBigInt(t.insuranceWithdrawCooldownSlots) !== 0n ||\n toBigInt(t.permissionlessResolveStaleSlots) !== 0n ||\n toBigInt(t.fundingHorizonSlots) !== 0n ||\n toBigInt(t.fundingKBps) !== 0n ||\n toBigInt(t.fundingMaxPremiumBps) !== 0n ||\n toBigInt(t.fundingMaxBpsPerSlot) !== 0n ||\n toBigInt(t.markMinFee) !== 0n ||\n toBigInt(t.forceCloseDelaySlots) !== 0n\n );\n}\n\n/**\n * Encode the optional 66-byte extended tail for InitMarket (S-4).\n *\n * Field order matches percolator.rs:1532-1540 exactly:\n * iwm(u16) iwc(u64) prs(u64) fh(u64) fk(u64) fmp(i64) fms(i64) mmf(u64) fcd(u64)\n *\n * @param t Extended tail parameters\n * @returns 66-byte Uint8Array\n */\nfunction encodeExtendedTail(t: InitMarketExtendedTail): Uint8Array {\n return concatBytes(\n encU16(t.insuranceWithdrawMaxBps),\n encU64(t.insuranceWithdrawCooldownSlots),\n encU64(t.permissionlessResolveStaleSlots),\n encU64(t.fundingHorizonSlots),\n encU64(t.fundingKBps),\n encI64(t.fundingMaxPremiumBps),\n encI64(t.fundingMaxBpsPerSlot),\n encU64(t.markMinFee),\n encU64(t.forceCloseDelaySlots),\n );\n}\n\n/**\n * Encode InitMarket instruction data.\n *\n * Produces either a 344-byte base payload (no extended tail) or a 410-byte\n * payload (344 + 66 extended tail) depending on whether `args.extendedTail`\n * is provided and contains at least one non-zero field.\n *\n * The program (percolator.rs:1527-1545) treats an empty `rest` as all-zero\n * defaults, so the 344-byte form is fully backward-compatible.\n *\n * @param args InitMarket arguments\n * @returns Encoded instruction bytes\n *\n * @example\n * ```ts\n * const ix = encodeInitMarket({\n * admin: adminPk,\n * collateralMint: mintPk,\n * indexFeedId: \"0000...0000\",\n * // ... required fields ...\n * extendedTail: {\n * insuranceWithdrawMaxBps: 500,\n * insuranceWithdrawCooldownSlots: 216000n,\n * permissionlessResolveStaleSlots: 0n,\n * fundingHorizonSlots: 0n,\n * fundingKBps: 0n,\n * fundingMaxPremiumBps: 0n,\n * fundingMaxBpsPerSlot: 0n,\n * markMinFee: 0n,\n * forceCloseDelaySlots: 0n,\n * },\n * });\n * ```\n */\nexport function encodeInitMarket(args: InitMarketArgs): Uint8Array {\n // Resolve hMin/hMax with fallback to warmupPeriodSlots for backwards compat\n const hMin = args.hMin ?? args.warmupPeriodSlots ?? 0n;\n const hMax = args.hMax ?? args.warmupPeriodSlots ?? 0n;\n\n const header = 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 encU128(args.maxMaintenanceFeePerSlot ?? 0n),\n );\n\n // RiskParams wire format — must match read_risk_params() in\n // percolator.rs. 13 fields (h_min through min_liquidation_abs) +\n // (min_nonzero_mm_req, min_nonzero_im_req) tail.\n const riskParamsCommon = concatBytes(\n encU64(hMin),\n encU64(args.maintenanceMarginBps),\n encU64(args.initialMarginBps),\n encU64(args.tradingFeeBps),\n encU64(args.maxAccounts),\n encU128(args.newAccountFee),\n encU128(args.insuranceFloor ?? 0n),\n encU64(hMax),\n encU64(args.maxCrankStalenessSlots),\n encU64(args.liquidationFeeBps),\n encU128(args.liquidationFeeCap),\n encU64(args.liquidationBufferBps ?? 0n),\n encU128(args.minLiquidationAbs),\n );\n\n const riskParamsTail = concatBytes(\n encU128(args.minNonzeroMmReq),\n encU128(args.minNonzeroImReq),\n );\n\n const base = concatBytes(header, riskParamsCommon, riskParamsTail);\n\n if (base.length !== INIT_MARKET_BASE_LEN) {\n throw new Error(\n `encodeInitMarket: base payload expected ${INIT_MARKET_BASE_LEN} bytes, got ${base.length}`,\n );\n }\n\n // Append extended tail only when present and at least one field is non-zero.\n // Omitting the tail preserves current default behavior: program reads empty\n // rest and uses all-zero defaults (percolator.rs:1527-1529).\n if (args.extendedTail && extendedTailHasNonZero(args.extendedTail)) {\n const tail = encodeExtendedTail(args.extendedTail);\n if (tail.length !== INIT_MARKET_EXTENDED_TAIL_LEN) {\n throw new Error(\n `encodeInitMarket: extended tail expected ${INIT_MARKET_EXTENDED_TAIL_LEN} bytes, got ${tail.length}`,\n );\n }\n return concatBytes(base, tail);\n }\n\n return base;\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 * Liquidation policy for KeeperCrank candidates (v12.17 two-phase crank).\n *\n * On-chain wire tags:\n * 0x00 = FullClose — liquidate the entire position\n * 0x01 = ExactPartial(u128) — reduce position by exactly `quantity` units\n * 0xFF = TouchOnly — accrue fees / sweep dust, do NOT liquidate\n */\nexport const LiquidationPolicyTag = {\n FullClose: 0,\n ExactPartial: 1,\n TouchOnly: 0xFF,\n} as const;\n\nexport type KeeperCrankCandidate =\n | { policy: typeof LiquidationPolicyTag.FullClose; idx: number }\n | { policy: typeof LiquidationPolicyTag.ExactPartial; idx: number; quantity: bigint | string }\n | { policy: typeof LiquidationPolicyTag.TouchOnly; idx: number };\n\n/**\n * KeeperCrank instruction data (v12.17 two-phase crank).\n *\n * Wire format: tag(1) + caller_idx(u16) + format_version=1(u8) +\n * candidates: [ idx(u16) + policy_tag(u8) [+ quantity(u128) if ExactPartial] ]*\n *\n * Empty candidates list = simple crank (accrue funding, sweep dust).\n * With candidates = targeted liquidation/touch pass.\n */\nexport interface KeeperCrankArgs {\n callerIdx: number;\n candidates?: KeeperCrankCandidate[];\n}\n\nexport function encodeKeeperCrank(args: KeeperCrankArgs): Uint8Array {\n const parts: Uint8Array[] = [\n encU8(IX_TAG.KeeperCrank),\n encU16(args.callerIdx),\n encU8(1), // format_version = 1 (REQUIRED by v12.17)\n ];\n if (args.candidates) {\n for (const c of args.candidates) {\n parts.push(encU16(c.idx));\n parts.push(encU8(c.policy));\n if (c.policy === LiquidationPolicyTag.ExactPartial) {\n parts.push(encU128(c.quantity));\n }\n }\n }\n return concatBytes(...parts);\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 (29 bytes)\n *\n * v12.17: limit_price_e6 is now REQUIRED (slippage protection).\n * Set to 0 to accept any price (no slippage protection).\n * For buys: tx reverts if execution price > limitPriceE6.\n * For sells: tx reverts if execution price < limitPriceE6.\n */\nexport interface TradeCpiArgs {\n lpIdx: number;\n userIdx: number;\n size: bigint | string;\n /** Limit price in e6 units. 0 = no limit (accept any price). */\n limitPriceE6: 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 encU64(args.limitPriceE6),\n );\n}\n\n/**\n * @deprecated Tag 35 removed in v12.17. Use TradeCpi (tag 10) with limitPriceE6 instead.\n * TradeCpi now handles PDA bump internally. Sending tag 35 will fail with InvalidInstructionData.\n */\nexport interface TradeCpiV2Args {\n lpIdx: number;\n userIdx: number;\n size: bigint | string;\n bump: number;\n}\n\n/** @deprecated Tag 35 removed in v12.17. Use encodeTradeCpi with limitPriceE6 instead. */\nexport function encodeTradeCpiV2(_args: TradeCpiV2Args): Uint8Array {\n return removedInstruction(\"TradeCpiV2\", IX_TAG.TradeCpiV2, \"encodeTradeCpi()\");\n}\n\n/**\n * @deprecated Tag 36 removed in v12.17. Will fail on-chain with InvalidInstructionData.\n */\nexport interface UnresolveMarketArgs {\n confirmation: bigint | string;\n}\n\n/** @deprecated Tag 36 removed in v12.17. Will fail on-chain. */\nexport function encodeUnresolveMarket(_args: UnresolveMarketArgs): Uint8Array {\n return removedInstruction(\"UnresolveMarket\", IX_TAG.UnresolveMarket, \"encodeResolveMarket()\");\n}\n\n/**\n * @deprecated Tag 11 removed in v12.17. Insurance floor is now set at InitMarket.\n * Sending this instruction will fail with InvalidInstructionData.\n */\nexport interface SetRiskThresholdArgs {\n newThreshold: bigint | string;\n}\n\n/** @deprecated Tag 11 removed in v12.17. Will fail on-chain. */\nexport function encodeSetRiskThreshold(_args: SetRiskThresholdArgs): Uint8Array {\n return removedInstruction(\"SetRiskThreshold\", IX_TAG.SetRiskThreshold, \"encodeInitMarket()\");\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 *\n * 35 bytes: tag(1) + funding_horizon_slots(8) + funding_k_bps(8) +\n * funding_max_premium_bps(8) + funding_max_e9_per_slot(8) +\n * tvl_insurance_cap_mult(2). Wire layout matches v12.19 wrapper at\n * src/percolator.rs:2027-2041 (handle_update_config decode).\n */\nexport interface UpdateConfigArgs {\n fundingHorizonSlots: bigint | string;\n fundingKBps: bigint | string;\n fundingMaxPremiumBps: bigint | string;\n fundingMaxBpsPerSlot: bigint | string;\n /**\n * u16 deposit cap multiplier. 0 disables the protocol-enforced cap.\n * Wrapper field added at src/percolator.rs:2031.\n */\n tvlInsuranceCapMult?: number;\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 encI64(args.fundingMaxPremiumBps),\n encI64(args.fundingMaxBpsPerSlot),\n encU16(args.tvlInsuranceCapMult ?? 0),\n );\n}\n\n/**\n * @deprecated Tag 15 removed in v12.17. Maintenance fee is set at InitMarket only.\n * Sending this instruction will fail with InvalidInstructionData.\n */\nexport interface SetMaintenanceFeeArgs {\n newFee: bigint | string;\n}\n\n/** @deprecated Tag 15 removed in v12.17. Will fail on-chain. */\nexport function encodeSetMaintenanceFee(_args: SetMaintenanceFeeArgs): Uint8Array {\n return removedInstruction(\"SetMaintenanceFee\", IX_TAG.SetMaintenanceFee, \"encodeInitMarket()\");\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 * @deprecated Tag 22 is now SetInsuranceWithdrawPolicy in v12.17.\n * This encoder sends the WRONG wire format (u64+u64 instead of pubkey+u64+u16+u64).\n * Use encodeSetInsuranceWithdrawPolicy instead.\n */\nexport interface UpdateRiskParamsArgs {\n initialMarginBps: bigint | string;\n maintenanceMarginBps: bigint | string;\n tradingFeeBps?: bigint | string;\n}\n\n/** @deprecated Use encodeSetInsuranceWithdrawPolicy (tag 22). This sends wrong wire format. */\nexport function encodeUpdateRiskParams(_args: UpdateRiskParamsArgs): Uint8Array {\n return removedInstruction(\n \"UpdateRiskParams\",\n IX_TAG.UpdateRiskParams,\n \"encodeSetInsuranceWithdrawPolicy()\",\n );\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 * @deprecated Tag 23 is now WithdrawInsuranceLimited in v12.17.\n * This encoder sends the confirmation code as a withdrawal amount — DANGEROUS.\n * Use encodeWithdrawInsuranceLimited instead.\n */\nexport function encodeRenounceAdmin(): Uint8Array {\n return removedInstruction(\n \"RenounceAdmin\",\n IX_TAG.RenounceAdmin,\n \"encodeWithdrawInsuranceLimited()\",\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 * @deprecated Tag 32 removed in v12.17. Pyth oracle is configured at InitMarket via indexFeedId.\n * Sending this instruction will fail with InvalidInstructionData.\n */\nexport interface SetPythOracleArgs {\n feedId: Uint8Array;\n maxStalenessSecs: bigint;\n confFilterBps: number;\n}\n\n/** @deprecated Tag 32 removed in v12.17. Pyth is configured at InitMarket. */\nexport function encodeSetPythOracle(args: SetPythOracleArgs): Uint8Array {\n void args;\n return removedInstruction(\"SetPythOracle\", IX_TAG.SetPythOracle, \"encodeInitMarket()\");\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 * @deprecated Tag 33 removed in v12.17. Use UpdateHyperpMark (tag 34) for DEX-oracle markets.\n * Sending this instruction will fail with InvalidInstructionData.\n */\nexport function encodeUpdateMarkPrice(): Uint8Array {\n return removedInstruction(\"UpdateMarkPrice\", IX_TAG.UpdateMarkPrice, \"encodeUpdateHyperpMark()\");\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 void args;\n return removedInstruction(\n \"SetInsuranceIsolation\",\n IX_TAG.SetInsuranceIsolation,\n \"encodeFundMarketInsurance()\",\n );\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 = 0x504552434d415443 */\nexport const VAMM_MAGIC = 0x504552434d415443n;\n/** Alias matching the Rust constant name for parity tests */\nexport const MATCHER_MAGIC = VAMM_MAGIC;\n\n/** Offset where matcher return is written in the context account (always 0 per ABI) */\nexport const CTX_RETURN_OFFSET = 0;\n/** Byte length of the MatcherReturn section of the context account */\nexport const MATCHER_RETURN_LEN = 64;\n/** Offset into matcher context where vAMM params start (= MATCHER_RETURN_LEN) */\nexport const CTX_VAMM_OFFSET = 64;\n/** Byte length of the MatcherCtx (vAMM state) section of the context account */\nexport const CTX_VAMM_LEN = 256;\n/** Total matcher context account size: MATCHER_RETURN_LEN + CTX_VAMM_LEN */\nexport const MATCHER_CONTEXT_LEN = 320;\n/** Byte length of a MatcherCall instruction (tag 0 CPI payload) */\nexport const MATCHER_CALL_LEN = 67;\n/**\n * Byte length of an InitMatcherCtx instruction payload sent to the matcher program.\n * Layout: tag(1) + kind(1) + trading_fee_bps(4) + base_spread_bps(4) +\n * max_total_bps(4) + impact_k_bps(4) + liquidity_notional_e6(16) +\n * max_fill_abs(16) + max_inventory_abs(16) + fee_to_insurance_bps(2) +\n * skew_spread_mult_bps(2) + lp_account_id(8) = 78\n */\nexport const INIT_CTX_LEN = 78;\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-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 removedInstruction(\"SlashCreationDeposit\", 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 * The program creates the ATA internally via CPI when the 11th account (Associated Token\n * Program) is provided. This is required because the NFT mint PDA doesn't exist until the\n * program creates it, so the ATA can't be created in a preceding instruction.\n *\n * Instruction data layout: tag(1) + user_idx(2) = 3 bytes\n *\n * Accounts (11):\n * 0. [signer, writable] payer\n * 1. [writable] slab\n * 2. [writable] position_nft PDA (created — seeds: [\"position_nft\", slab, user_idx_u16_le])\n * 3. [writable] nft_mint PDA (created — seeds: [\"position_nft_mint\", slab, user_idx_u16_le])\n * 4. [writable] owner_ata (Token-2022 ATA for nft_mint — created by program if absent)\n * 5. [signer] owner (must match engine account owner)\n * 6. [] vault_authority PDA (seeds: [\"vault\", slab])\n * 7. [] token_2022_program (TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb)\n * 8. [] system_program\n * 9. [] rent sysvar\n * 10. [] associated_token_program (ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL)\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\n// ============================================================================\n// Missing encoders — corrected tag mappings (tags 22-74)\n// ============================================================================\n\n/** SetInsuranceWithdrawPolicy (tag 22): authority + min_withdraw_base + max_withdraw_bps + cooldown_slots */\nexport interface SetInsuranceWithdrawPolicyArgs {\n authority: PublicKey | string;\n minWithdrawBase: bigint | string;\n maxWithdrawBps: number;\n cooldownSlots: bigint | string;\n}\nexport function encodeSetInsuranceWithdrawPolicy(args: SetInsuranceWithdrawPolicyArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.SetInsuranceWithdrawPolicy), encPubkey(args.authority), encU64(args.minWithdrawBase), encU16(args.maxWithdrawBps), encU64(args.cooldownSlots));\n}\n\n/**\n * WithdrawInsuranceLimited (tag 23): amount.\n * Account count is 7 (resolved markets) or 8 (live markets — oracle required\n * for same-instruction accrue_market_to per upstream 8ce8d54).\n * See ACCOUNTS_WITHDRAW_INSURANCE_LIMITED_LIVE / _RESOLVED in accounts.ts.\n */\nexport function encodeWithdrawInsuranceLimited(args: { amount: bigint | string }): Uint8Array {\n return concatBytes(encU8(IX_TAG.WithdrawInsuranceLimited), encU64(args.amount));\n}\n\n/** ResolvePermissionless (tag 29): no args */\nexport function encodeResolvePermissionless(): Uint8Array {\n return concatBytes(encU8(IX_TAG.ResolvePermissionless));\n}\n\n/** ForceCloseResolved (tag 30): user_idx */\nexport function encodeForceCloseResolved(args: { userIdx: number }): Uint8Array {\n return concatBytes(encU8(IX_TAG.ForceCloseResolved), encU16(args.userIdx));\n}\n\n/** CreateLpVault (tag 37): fee_share_bps + util_curve_enabled */\nexport function encodeCreateLpVault(args: { feeShareBps: bigint | string; utilCurveEnabled?: boolean }): Uint8Array {\n const parts = [encU8(IX_TAG.CreateLpVault), encU64(args.feeShareBps)];\n if (args.utilCurveEnabled !== undefined) {\n parts.push(encU8(args.utilCurveEnabled ? 1 : 0));\n }\n return concatBytes(...parts);\n}\n\n/** LpVaultDeposit (tag 38): amount */\nexport function encodeLpVaultDeposit(args: { amount: bigint | string }): Uint8Array {\n return concatBytes(encU8(IX_TAG.LpVaultDeposit), encU64(args.amount));\n}\n\n/** LpVaultCrankFees (tag 40): no args */\nexport function encodeLpVaultCrankFees(): Uint8Array {\n return concatBytes(encU8(IX_TAG.LpVaultCrankFees));\n}\n\n/** ChallengeSettlement (tag 43): proposed_price_e6 */\nexport function encodeChallengeSettlement(args: { proposedPriceE6: bigint | string }): Uint8Array {\n return concatBytes(encU8(IX_TAG.ChallengeSettlement), encU64(args.proposedPriceE6));\n}\n\n/** ResolveDispute (tag 44): accept (0 = reject, 1 = accept) */\nexport function encodeResolveDispute(args: { accept: number }): Uint8Array {\n return concatBytes(encU8(IX_TAG.ResolveDispute), encU8(args.accept));\n}\n\n/** DepositLpCollateral (tag 45): user_idx + lp_amount */\nexport function encodeDepositLpCollateral(args: { userIdx: number; lpAmount: bigint | string }): Uint8Array {\n return concatBytes(encU8(IX_TAG.DepositLpCollateral), encU16(args.userIdx), encU64(args.lpAmount));\n}\n\n/** WithdrawLpCollateral (tag 46): user_idx + lp_amount */\nexport function encodeWithdrawLpCollateral(args: { userIdx: number; lpAmount: bigint | string }): Uint8Array {\n return concatBytes(encU8(IX_TAG.WithdrawLpCollateral), encU16(args.userIdx), encU64(args.lpAmount));\n}\n\n/** SetOffsetPair (tag 54): offset_bps */\nexport function encodeSetOffsetPair(args: { offsetBps: number }): Uint8Array {\n return concatBytes(encU8(IX_TAG.SetOffsetPair), encU16(args.offsetBps));\n}\n\n/** AttestCrossMargin (tag 55): user_idx_a + user_idx_b */\nexport function encodeAttestCrossMargin(args: { userIdxA: number; userIdxB: number }): Uint8Array {\n return concatBytes(encU8(IX_TAG.AttestCrossMargin), encU16(args.userIdxA), encU16(args.userIdxB));\n}\n\n/** RescueOrphanVault (tag 72): no args */\nexport function encodeRescueOrphanVault(): Uint8Array {\n return concatBytes(encU8(IX_TAG.RescueOrphanVault));\n}\n\n/** CloseOrphanSlab (tag 73): no args */\nexport function encodeCloseOrphanSlab(): Uint8Array {\n return concatBytes(encU8(IX_TAG.CloseOrphanSlab));\n}\n\n/** SetDexPool (tag 74): pool pubkey */\nexport function encodeSetDexPool(args: { pool: PublicKey | string }): Uint8Array {\n return concatBytes(encU8(IX_TAG.SetDexPool), encPubkey(args.pool));\n}\n\n// Insurance LP — aliases for LP Vault instructions (tags 37/38/39).\n// The insurance LP feature uses the same on-chain instructions as the LP vault\n// but with insurance-specific account layouts (ACCOUNTS_*_INSURANCE_LP).\n\n/** CreateInsuranceMint: creates the insurance LP mint PDA (tag 37, same as CreateLpVault) */\nexport function encodeCreateInsuranceMint(): Uint8Array {\n // CreateLpVault with default params (fee_share_bps=0, no util curve)\n return encodeCreateLpVault({ feeShareBps: 0n });\n}\n\n/** DepositInsuranceLP: deposit collateral, receive LP tokens (tag 38, same as LpVaultDeposit) */\nexport function encodeDepositInsuranceLP(args: { amount: bigint | string }): Uint8Array {\n return encodeLpVaultDeposit({ amount: args.amount });\n}\n\n/** WithdrawInsuranceLP: burn LP tokens, withdraw collateral (tag 39, same as LpVaultWithdraw) */\nexport function encodeWithdrawInsuranceLP(args: { lpAmount: bigint | string }): Uint8Array {\n return encodeLpVaultWithdraw({ lpAmount: args.lpAmount });\n}\n\n// ============================================================================\n// Phase B admin setters (tags 78-81) — added 2026-04-17\n// Wire up MarketConfig fields added in prog Phase A. Admin-only, validated.\n// Accounts for all 4: [admin(signer), slab(writable)] (2 accounts).\n// ============================================================================\n\n/**\n * SetMaxPnlCap (Tag 78, PERC-305 / SECURITY(H-4)) — set the PnL cap for ADL\n * pre-check (admin only). When `pnl_pos_tot <= max_pnl_cap`, ADL returns\n * early (no deleveraging needed).\n *\n * `capE6 = 0` disables the cap (ADL always runs when insurance is depleted).\n *\n * Instruction data: tag(1) + cap(u64, 8) = 9 bytes\n */\nexport interface SetMaxPnlCapArgs {\n /** PnL cap in engine quote units (e.g., 1_000_000 = $1 e6). 0 = cap disabled. */\n cap: bigint | string;\n}\n\nexport function encodeSetMaxPnlCap(args: SetMaxPnlCapArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.SetMaxPnlCap), encU64(args.cap));\n}\n\n/**\n * SetOiCapMultiplier (Tag 79, PERC-309) — set the OI cap multiplier for LP\n * withdrawal limits (admin only). Packed u64:\n * lo 32 bits: multiplier_bps (e.g., 15000 = 1.5× soft cap in stressed state)\n * hi 32 bits: soft_cap_bps (e.g., 8000 = 80% base cap)\n *\n * `packed = 0` disables enforcement (no cap on LP withdrawals).\n *\n * Instruction data: tag(1) + packed(u64, 8) = 9 bytes\n */\nexport interface SetOiCapMultiplierArgs {\n /** Packed u64: lo32 = multiplier_bps, hi32 = soft_cap_bps. 0 = disabled. */\n packed: bigint | string;\n}\n\nexport function encodeSetOiCapMultiplier(args: SetOiCapMultiplierArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.SetOiCapMultiplier), encU64(args.packed));\n}\n\n/** Convenience: pack (multiplier_bps, soft_cap_bps) into the u64 expected by SetOiCapMultiplier. */\nexport function packOiCap(multiplierBps: number, softCapBps: number): bigint {\n if (multiplierBps < 0 || multiplierBps > 0xFFFF_FFFF) {\n throw new Error(`packOiCap: multiplier_bps out of u32 range: ${multiplierBps}`);\n }\n if (softCapBps < 0 || softCapBps > 0xFFFF_FFFF) {\n throw new Error(`packOiCap: soft_cap_bps out of u32 range: ${softCapBps}`);\n }\n return BigInt(multiplierBps) | (BigInt(softCapBps) << 32n);\n}\n\n/**\n * SetDisputeParams (Tag 80, PERC-314) — configure settlement dispute window\n * and bond (admin only).\n *\n * - `windowSlots = 0` disables disputes (ChallengeSettlement returns\n * DisputeWindowClosed). Max: 2_000_000 slots (≈ 8 days at 400ms slots) to\n * prevent DoS via absurd freezes.\n * - `bondAmount` (collateral tokens): refunded on dispute upheld, forfeited\n * on reject. 0 = no bond required.\n *\n * Instruction data: tag(1) + window_slots(u64, 8) + bond_amount(u64, 8) = 17 bytes\n */\nexport interface SetDisputeParamsArgs {\n /** Dispute window in slots. 0 = disputes disabled. Max 2_000_000. */\n windowSlots: bigint | string;\n /** Bond required to open a dispute (collateral units). 0 = no bond. */\n bondAmount: bigint | string;\n}\n\nexport function encodeSetDisputeParams(args: SetDisputeParamsArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.SetDisputeParams),\n encU64(args.windowSlots),\n encU64(args.bondAmount),\n );\n}\n\n/**\n * SetLpCollateralParams (Tag 81, PERC-315) — configure LP token collateral\n * acceptance (admin only).\n *\n * - `enabled = 0`: DepositLpCollateral rejects all new deposits.\n * - `enabled = 1`: deposits allowed, subject to `ltvBps` haircut on value.\n * - `ltvBps` max 10_000 (100%). Typical: 5000 (50% LTV).\n *\n * Instruction data: tag(1) + enabled(u8, 1) + ltv_bps(u16, 2) = 4 bytes\n */\nexport interface SetLpCollateralParamsArgs {\n /** 0 = disabled (blocks new deposits), 1 = enabled. */\n enabled: number;\n /** LTV in bps (0-10000). 5000 = 50% LTV. */\n ltvBps: number;\n}\n\nexport function encodeSetLpCollateralParams(args: SetLpCollateralParamsArgs): Uint8Array {\n if (args.enabled !== 0 && args.enabled !== 1) {\n throw new Error(`encodeSetLpCollateralParams: enabled must be 0 or 1, got ${args.enabled}`);\n }\n if (args.ltvBps < 0 || args.ltvBps > 10_000) {\n throw new Error(`encodeSetLpCollateralParams: ltvBps ${args.ltvBps} out of range [0, 10000]`);\n }\n return concatBytes(\n encU8(IX_TAG.SetLpCollateralParams),\n encU8(args.enabled),\n encU16(args.ltvBps),\n );\n}\n\n/**\n * AcceptAdmin (Tag 82, Phase E 2026-04-17) — complete a two-step admin transfer.\n *\n * Called by the PROPOSED new admin (the pubkey passed to UpdateAdmin with\n * `new_admin != default()`). The signer must match config.pending_admin\n * exactly. On success, header.admin is swapped to pending_admin and\n * pending_admin is cleared.\n *\n * Use `try_update_admin` then `try_accept_admin` for a full rotation, or\n * skip AcceptAdmin entirely to leave a pending transfer that the old\n * admin can overwrite (propose-again) or the new admin can never accept.\n *\n * Accounts:\n * [0] new admin (signer, must match pending_admin)\n * [1] slab (writable)\n *\n * Instruction data: tag(1) = 1 byte. No payload.\n */\nexport function encodeAcceptAdmin(): Uint8Array {\n return encU8(IX_TAG.AcceptAdmin);\n}\n\n// ============================================================================\n// G-3 fixes (audit-2026-04-27): missing per-account encoders for tags 25-28.\n// Wrapper handlers exist at src/percolator.rs:2088, 2092, 2097, 2103.\n// ============================================================================\n\n/**\n * ReclaimEmptyAccount (Tag 25) — permissionless reclamation of empty/dust\n * accounts (wrapper §2.6, §10.7).\n *\n * Wrapper decode: src/percolator.rs:2088. Wire: tag(1) + user_idx u16(2).\n *\n * Accounts: see ACCOUNTS_RECLAIM_EMPTY_ACCOUNT.\n */\nexport interface ReclaimEmptyAccountArgs {\n userIdx: number;\n}\n\nexport function encodeReclaimEmptyAccount(args: ReclaimEmptyAccountArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.ReclaimEmptyAccount), encU16(args.userIdx));\n}\n\n/**\n * SettleAccount (Tag 26) — standalone account settlement (wrapper §10.2).\n * Permissionless.\n *\n * Wrapper decode: src/percolator.rs:2092. Wire: tag(1) + user_idx u16(2).\n *\n * Accounts: see ACCOUNTS_SETTLE_ACCOUNT.\n */\nexport interface SettleAccountArgs {\n userIdx: number;\n}\n\nexport function encodeSettleAccount(args: SettleAccountArgs): Uint8Array {\n return concatBytes(encU8(IX_TAG.SettleAccount), encU16(args.userIdx));\n}\n\n/**\n * DepositFeeCredits (Tag 27) — direct fee-debt repayment (wrapper §10.3.1).\n * Owner only.\n *\n * Wrapper decode: src/percolator.rs:2097. Wire: tag(1) + user_idx u16(2)\n * + amount u64(8).\n *\n * Accounts: see ACCOUNTS_DEPOSIT_FEE_CREDITS.\n */\nexport interface DepositFeeCreditsArgs {\n userIdx: number;\n amount: bigint | string;\n}\n\nexport function encodeDepositFeeCredits(args: DepositFeeCreditsArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.DepositFeeCredits),\n encU16(args.userIdx),\n encU64(args.amount),\n );\n}\n\n/**\n * ConvertReleasedPnl (Tag 28) — voluntary PnL conversion with open position\n * (wrapper §10.4.1). Owner only.\n *\n * Wrapper decode: src/percolator.rs:2103. Wire: tag(1) + user_idx u16(2)\n * + amount u64(8).\n *\n * Accounts: see ACCOUNTS_CONVERT_RELEASED_PNL.\n */\nexport interface ConvertReleasedPnlArgs {\n userIdx: number;\n amount: bigint | string;\n}\n\nexport function encodeConvertReleasedPnl(args: ConvertReleasedPnlArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.ConvertReleasedPnl),\n encU16(args.userIdx),\n encU64(args.amount),\n );\n}\n\n// ============================================================================\n// G-2 fix (audit-2026-04-27): UpdateAuthority (tag 83). v12.18.x 4-way split.\n// Wrapper: src/percolator.rs:6876 (handler), 2140-2146 (decode).\n// ============================================================================\n\n/**\n * Authority kind for UpdateAuthority (tag 83). Maps to wrapper constants\n * AUTHORITY_ADMIN/HYPERP_MARK/INSURANCE/INSURANCE_OPERATOR at\n * src/percolator.rs:6862-6868.\n *\n * Note: kind=3 is reserved (the v12.18.x split uses 0/1/2/4).\n */\nexport const AUTHORITY_KIND = {\n Admin: 0,\n HyperpMark: 1,\n Insurance: 2,\n InsuranceOperator: 4,\n} as const;\nObject.freeze(AUTHORITY_KIND);\n\nexport type AuthorityKind = (typeof AUTHORITY_KIND)[keyof typeof AUTHORITY_KIND];\n\n/**\n * UpdateAuthority (Tag 83) — unified mutator for the four authority slots\n * (admin, hyperp_mark, insurance, insurance_operator).\n *\n * The instruction takes both the current authority and the new authority as\n * signers. Setting `newPubkey` to the zero pubkey burns the authority slot;\n * burning admin requires `permissionless_resolve_stale_slots > 0` AND\n * `force_close_delay_slots > 0` per the R4-H1 liveness guard.\n *\n * H-NEW-1 (closed in wrapper d760fc4): atomic admin rotation through this\n * tag now clears `config.pending_admin`, invalidating any stale tag-12\n * proposal.\n *\n * Wire: tag(1) + kind u8(1) + new_pubkey Pubkey(32) = 34 bytes.\n *\n * Accounts: see ACCOUNTS_UPDATE_AUTHORITY.\n */\nexport interface UpdateAuthorityArgs {\n kind: AuthorityKind;\n newPubkey: PublicKey | string;\n}\n\nexport function encodeUpdateAuthority(args: UpdateAuthorityArgs): Uint8Array {\n return concatBytes(\n encU8(IX_TAG.UpdateAuthority),\n encU8(args.kind),\n encPubkey(args.newPubkey),\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 { name: \"clock\", signer: false, writable: false },\n] as const;\n\n/**\n * InitLP: 6 accounts\n * Program at percolator.rs:6607 calls expect_len(accounts, 6).\n * The 6th account (accounts[5]) is the clock sysvar — used via Clock::from_account_info.\n * [0] user signer, writable (LP owner; pays fee)\n * [1] slab writable\n * [2] userAta writable (collateral source for fee)\n * [3] vault writable (collateral destination)\n * [4] tokenProgram read-only\n * [5] clock read-only (SYSVAR_CLOCK_PUBKEY)\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 { name: \"clock\", 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/**\n * TradeNoCpi: 5 accounts.\n * v12.19 wrapper at src/percolator.rs:8484 calls accounts::expect_len(5).\n * Layout: [user(s+w), lp(s+w), slab(w), clock, oracle].\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: \"clock\", signer: false, writable: false },\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: 6 accounts.\n * v12.19 wrapper at src/percolator.rs:9256 calls accounts::expect_len(6).\n * Layout: [user(s+w), slab(w), userAta(w), vault(w), tokenProgram, clock].\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 { name: \"clock\", signer: false, writable: false },\n] as const;\n\n/**\n * TradeCpi: 8 accounts (deployed program expects clock sysvar at index 3)\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: \"clock\", signer: false, writable: false },\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 * AcceptAdmin: 2 accounts (tag 82)\n * Second half of two-step admin transfer. The proposed new admin must sign to\n * complete the transfer. Program at percolator.rs:7994 calls expect_len(accounts, 2).\n * [0] pendingAdmin signer, writable (must match config.pending_admin)\n * [1] slab writable\n */\nexport const ACCOUNTS_ACCEPT_ADMIN: readonly AccountSpec[] = [\n { name: \"pendingAdmin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * CloseSlab: 6 accounts\n * Drains vault and recovers rent after market is fully resolved and all accounts closed.\n * Program at percolator.rs:8033 calls expect_len(accounts, 6).\n * [0] dest signer, writable (receives rent + drained vault tokens)\n * [1] slab writable\n * [2] vault writable (token account — drained)\n * [3] vaultAuthority read-only (PDA that signs the drain transfer)\n * [4] destAta writable (dest's token ATA receiving drained tokens)\n * [5] tokenProgram read-only\n */\nexport const ACCOUNTS_CLOSE_SLAB: readonly AccountSpec[] = [\n { name: \"dest\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"vaultAuthority\", signer: false, writable: false },\n { name: \"destAta\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n] as const;\n\n/**\n * UpdateConfig: 3 accounts (canonical) or 4 (with oracle).\n * v12.19 wrapper at src/percolator.rs:9544 accepts either.\n * 3-account form: [admin(s+w), slab(w), clock].\n * 4-account form: [admin(s+w), slab(w), clock, oracle] (used when the wrapper\n * needs to re-read price during config commit). Default to the 3-account form;\n * callers that need oracle re-reads should append the oracle account themselves.\n */\nexport const ACCOUNTS_UPDATE_CONFIG: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"clock\", signer: false, writable: false },\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 * SetOraclePriceCap: 3 accounts.\n * v12.19 wrapper at src/percolator.rs:9654 calls accounts::expect_len(3).\n * Layout: [admin(s+w), slab(w), clock].\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 { name: \"clock\", signer: false, writable: false },\n] as const;\n\n/**\n * ResolveMarket: 4 accounts.\n * v12.19 wrapper at src/percolator.rs:9748 calls accounts::expect_len(4).\n * Layout: [admin(s+w), slab(w), clock, oracle].\n */\nexport const ACCOUNTS_RESOLVE_MARKET: readonly AccountSpec[] = [\n { name: \"admin\", 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 * 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 * WithdrawInsuranceLimited (tag 23): 7 or 8 accounts.\n * On live markets the 8th oracle account is REQUIRED (upstream 8ce8d54):\n * the handler does a same-instruction accrue_market_to against the fresh\n * oracle price to prevent withdrawals against overstated insurance.\n * On resolved markets the oracle is frozen — 7 accounts suffice.\n */\nexport const ACCOUNTS_WITHDRAW_INSURANCE_LIMITED_RESOLVED: readonly AccountSpec[] = [\n { name: \"authority\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"authorityAta\", 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 { name: \"clock\", signer: false, writable: false },\n] as const;\n\nexport const ACCOUNTS_WITHDRAW_INSURANCE_LIMITED_LIVE: readonly AccountSpec[] = [\n ...ACCOUNTS_WITHDRAW_INSURANCE_LIMITED_RESOLVED,\n { name: \"oracle\", 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// G-3 / G-4 / G-2 fixes (audit-2026-04-27): missing ACCOUNTS_ specs.\n// Wrapper handlers at src/percolator.rs:10470 (reclaim), 10503 (settle),\n// 10557 (deposit_fee_credits), 10636 (convert_released_pnl), 9990\n// (set_insurance_withdraw_policy), 6876 (update_authority).\n// ============================================================================\n\n/**\n * ReclaimEmptyAccount (tag 25): 2 accounts. Permissionless.\n * Wrapper: src/percolator.rs:10470.\n */\nexport const ACCOUNTS_RECLAIM_EMPTY_ACCOUNT: readonly AccountSpec[] = [\n { name: \"slab\", signer: false, writable: true },\n { name: \"clock\", signer: false, writable: false },\n] as const;\n\n/**\n * SettleAccount (tag 26): 3 accounts. Permissionless.\n * Wrapper: src/percolator.rs:10503.\n */\nexport const ACCOUNTS_SETTLE_ACCOUNT: readonly AccountSpec[] = [\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 * DepositFeeCredits (tag 27): 6 accounts. Owner only.\n * Wrapper: src/percolator.rs:10557. SPL transfer requires userAta + vault writable.\n */\nexport const ACCOUNTS_DEPOSIT_FEE_CREDITS: 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 * ConvertReleasedPnl (tag 28): 4 accounts. Owner only.\n * Wrapper: src/percolator.rs:10636.\n */\nexport const ACCOUNTS_CONVERT_RELEASED_PNL: readonly AccountSpec[] = [\n { name: \"user\", 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 * SetInsuranceWithdrawPolicy (tag 22): 2 accounts. Admin only.\n * Wrapper: src/percolator.rs:9990.\n */\nexport const ACCOUNTS_SET_INSURANCE_WITHDRAW_POLICY: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\n/**\n * UpdateAuthority (tag 83, v12.18.x 4-way split): 3 accounts.\n * Wrapper: src/percolator.rs:6876.\n *\n * Both the current authority and the new authority must sign. For burn\n * (`new_pubkey == default()`) the new account is still passed but does\n * not need to sign per wrapper L7036 region.\n */\nexport const ACCOUNTS_UPDATE_AUTHORITY: readonly AccountSpec[] = [\n { name: \"currentAuthority\", signer: true, writable: false },\n { name: \"newAuthority\", signer: true, writable: false },\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\nexport const ACCOUNTS_RESOLVE_PERMISSIONLESS: readonly AccountSpec[] = [\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\nexport const ACCOUNTS_FORCE_CLOSE_RESOLVED: readonly AccountSpec[] = [\n { name: \"slab\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"ownerAta\", signer: false, writable: true },\n { name: \"vaultAuthority\", 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\nexport const ACCOUNTS_ADMIN_FORCE_CLOSE: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"ownerAta\", signer: false, writable: true },\n { name: \"vaultAuthority\", 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// 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\nexport const ACCOUNTS_UPDATE_HYPERP_MARK: readonly AccountSpec[] = [\n { name: \"slab\", signer: false, writable: true },\n { name: \"dexPool\", signer: false, writable: false },\n { name: \"clock\", signer: false, writable: false },\n] as const;\n\nexport const ACCOUNTS_CREATE_LP_VAULT: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"lpVaultState\", signer: false, writable: true },\n { name: \"lpVaultMint\", signer: false, writable: true },\n { name: \"vaultAuthority\", 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] as const;\n\nexport const ACCOUNTS_LP_VAULT_DEPOSIT: readonly AccountSpec[] = [\n { name: \"depositor\", signer: true, writable: true },\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: \"lpVaultMint\", signer: false, writable: true },\n { name: \"depositorLpAta\", signer: false, writable: true },\n { name: \"vaultAuthority\", signer: false, writable: false },\n { name: \"lpVaultState\", signer: false, writable: true },\n] as const;\n\nexport const ACCOUNTS_LP_VAULT_CRANK_FEES: readonly AccountSpec[] = [\n { name: \"slab\", signer: false, writable: true },\n { name: \"lpVaultState\", signer: false, writable: true },\n] as const;\n\nexport const ACCOUNTS_CHALLENGE_SETTLEMENT: readonly AccountSpec[] = [\n { name: \"challenger\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"dispute\", signer: false, writable: true },\n { name: \"challengerAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"systemProgram\", signer: false, writable: false },\n] as const;\n\nexport const ACCOUNTS_RESOLVE_DISPUTE: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"dispute\", signer: false, writable: true },\n { name: \"challengerAta\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n { name: \"vaultAuthority\", signer: false, writable: false },\n { name: \"tokenProgram\", signer: false, writable: false },\n] as const;\n\nexport const ACCOUNTS_DEPOSIT_LP_COLLATERAL: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"userLpAta\", signer: false, writable: true },\n { name: \"lpVaultMint\", signer: false, writable: false },\n { name: \"lpVaultState\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"lpEscrow\", signer: false, writable: true },\n] as const;\n\nexport const ACCOUNTS_WITHDRAW_LP_COLLATERAL: readonly AccountSpec[] = [\n { name: \"user\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"userLpAta\", signer: false, writable: true },\n { name: \"lpVaultMint\", signer: false, writable: false },\n { name: \"lpVaultState\", signer: false, writable: true },\n { name: \"tokenProgram\", signer: false, writable: false },\n { name: \"lpEscrow\", signer: false, writable: true },\n { name: \"vaultAuthority\", signer: false, writable: false },\n] as const;\n\nexport const ACCOUNTS_SET_OFFSET_PAIR: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slabA\", signer: false, writable: true },\n { name: \"slabB\", signer: false, writable: true },\n { name: \"pairPda\", signer: false, writable: true },\n { name: \"systemProgram\", signer: false, writable: false },\n] as const;\n\nexport const ACCOUNTS_ATTEST_CROSS_MARGIN: readonly AccountSpec[] = [\n { name: \"payer\", signer: true, writable: true },\n { name: \"slabA\", signer: false, writable: true },\n { name: \"slabB\", signer: false, writable: true },\n { name: \"attestation\", signer: false, writable: true },\n { name: \"pairPda\", signer: false, writable: false },\n { name: \"systemProgram\", signer: false, writable: false },\n] as const;\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\nexport const ACCOUNTS_SET_MAX_PNL_CAP: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\nexport const ACCOUNTS_SET_OI_CAP_MULTIPLIER: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\nexport const ACCOUNTS_SET_DISPUTE_PARAMS: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n] as const;\n\nexport const ACCOUNTS_SET_LP_COLLATERAL_PARAMS: 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\nexport const ACCOUNTS_TRANSFER_OWNERSHIP_CPI: readonly AccountSpec[] = [\n { name: \"caller\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n { name: \"nftProgram\", signer: false, writable: false },\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\nexport const ACCOUNTS_RESCUE_ORPHAN_VAULT: 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\nexport const ACCOUNTS_CLOSE_ORPHAN_SLAB: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: true },\n { name: \"slab\", signer: false, writable: true },\n { name: \"vault\", signer: false, writable: true },\n] as const;\n\n// ============================================================================\n// PERC-SetDexPool: SetDexPool (tag 74)\n// ============================================================================\n\n/**\n * SetDexPool: 3 accounts\n * Admin pins the approved DEX pool address for a HYPERP market.\n * After this call, UpdateHyperpMark rejects any pool that does not match.\n */\nexport const ACCOUNTS_SET_DEX_POOL: readonly AccountSpec[] = [\n { name: \"admin\", signer: true, writable: false },\n { name: \"slab\", signer: false, writable: true },\n { name: \"poolAccount\", signer: false, writable: false },\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/** 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 */\nexport function parseErrorFromLogs(logs: string[]): {\n code: number;\n name: string;\n hint?: string;\n} | null {\n if (!Array.isArray(logs)) {\n return null;\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 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 const info = decodeError(code);\n return {\n code,\n name: info?.name ?? `Unknown(${code})`,\n hint: info?.hint,\n };\n }\n }\n return null;\n}\n","/**\n * Standalone percolator-nft program SDK module.\n *\n * This covers the NFT program at `PERCOLATOR_NFT_PROGRAM_ID` which is\n * separate from the main Percolator program. It handles:\n * - MintPositionNft (tag 0)\n * - BurnPositionNft (tag 1)\n * - SettleFunding (tag 2)\n * - GetPositionValue (tag 3)\n * - ExecuteTransferHook (tag 4, SPL interface — not called directly)\n * - EmergencyBurn (tag 5)\n *\n * PDA seeds (matches percolator-nft/src/state.rs):\n * PositionNft state : [\"position_nft\", slab, user_idx_u16_LE]\n * PositionNft mint : [\"position_nft_mint\", slab, user_idx_u16_LE]\n * Mint authority : [\"mint_authority\"]\n */\n\nimport { PublicKey } from \"@solana/web3.js\";\nimport { safeEnv } from \"../config/program-ids.js\";\n\n// ---------------------------------------------------------------------------\n// Program ID\n// ---------------------------------------------------------------------------\n\nconst NFT_PROGRAM_OVERRIDE = safeEnv(\"NFT_PROGRAM_ID\");\n\n/** The standalone percolator-nft program (TransferHook + mint authority). */\nexport const NFT_PROGRAM_ID = new PublicKey(\n NFT_PROGRAM_OVERRIDE ?? \"FqhKJT9gtScjrmfUuRMjeg7cXNpif1fqsy5Jh65tJmTS\",\n);\n\nexport function getNftProgramId(): PublicKey {\n return NFT_PROGRAM_ID;\n}\n\n// ---------------------------------------------------------------------------\n// Instruction tags (standalone NFT program — NOT the main Percolator tags)\n// ---------------------------------------------------------------------------\n\nexport const NFT_IX_TAG = {\n MintPositionNft: 0,\n BurnPositionNft: 1,\n SettleFunding: 2,\n GetPositionValue: 3,\n ExecuteTransferHook: 4,\n EmergencyBurn: 5,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Instruction encoders\n// ---------------------------------------------------------------------------\n\n/** Encode MintPositionNft (tag 0). Data: tag(1) + user_idx(2). */\nexport function encodeNftMint(userIdx: number): Uint8Array {\n const buf = new Uint8Array(3);\n buf[0] = NFT_IX_TAG.MintPositionNft;\n buf[1] = userIdx & 0xff;\n buf[2] = (userIdx >> 8) & 0xff;\n return buf;\n}\n\n/** Encode BurnPositionNft (tag 1). Data: tag(1). */\nexport function encodeNftBurn(): Uint8Array {\n return new Uint8Array([NFT_IX_TAG.BurnPositionNft]);\n}\n\n/** Encode SettleFunding (tag 2). Data: tag(1). */\nexport function encodeNftSettleFunding(): Uint8Array {\n return new Uint8Array([NFT_IX_TAG.SettleFunding]);\n}\n\n/** Encode EmergencyBurn (tag 5). Data: tag(1). */\nexport function encodeNftEmergencyBurn(): Uint8Array {\n return new Uint8Array([NFT_IX_TAG.EmergencyBurn]);\n}\n\n// ---------------------------------------------------------------------------\n// Account meta templates\n// ---------------------------------------------------------------------------\n\ntype AccountMeta = \"s\" | \"w\" | \"sw\" | \"r\";\n\n/**\n * Account metas for MintPositionNft (tag 0).\n *\n * 0. [signer, writable] payer / position owner\n * 1. [writable] PositionNft PDA (created)\n * 2. [writable, signer] NFT mint (Token-2022, fresh keypair)\n * 3. [writable] Owner's NFT ATA (created)\n * 4. [] Slab account\n * 5. [] Mint authority PDA\n * 6. [] Token-2022 program\n * 7. [] Associated token account program\n * 8. [] System program\n * 9. [writable] ExtraAccountMetaList PDA\n */\nexport const ACCOUNTS_NFT_MINT: AccountMeta[] = [\n \"sw\", \"w\", \"sw\", \"w\", \"r\", \"r\", \"r\", \"r\", \"r\", \"w\",\n];\n\n/**\n * Account metas for BurnPositionNft (tag 1).\n *\n * 0. [signer] NFT holder\n * 1. [writable] PositionNft PDA (closed)\n * 2. [writable] NFT mint (supply → 0)\n * 3. [writable] Holder's NFT ATA (closed)\n * 4. [] Slab account\n * 5. [] Mint authority PDA\n * 6. [] Token-2022 program\n */\nexport const ACCOUNTS_NFT_BURN: AccountMeta[] = [\n \"s\", \"w\", \"w\", \"w\", \"r\", \"r\", \"r\",\n];\n\n/**\n * Account metas for EmergencyBurn (tag 5).\n *\n * 0. [signer] NFT holder\n * 1. [writable] PositionNft PDA (closed)\n * 2. [writable] NFT mint\n * 3. [writable] Holder's NFT ATA\n * 4. [] Slab account\n * 5. [] Mint authority PDA\n * 6. [] Token-2022 program\n */\nexport const ACCOUNTS_NFT_EMERGENCY_BURN: AccountMeta[] = [\n \"s\", \"w\", \"w\", \"w\", \"r\", \"r\", \"r\",\n];\n\n// ---------------------------------------------------------------------------\n// PDA derivation\n// ---------------------------------------------------------------------------\n\nconst TEXT = new TextEncoder();\n\nfunction idxBuf(userIdx: number): Uint8Array {\n const buf = new Uint8Array(2);\n new DataView(buf.buffer).setUint16(0, userIdx, true);\n return buf;\n}\n\n/**\n * Derive the PositionNft state PDA.\n * Seeds: [\"position_nft\", slab, user_idx_u16_LE]\n */\nexport function deriveNftPda(\n slab: PublicKey,\n userIdx: number,\n programId: PublicKey = NFT_PROGRAM_ID,\n): [PublicKey, number] {\n return PublicKey.findProgramAddressSync(\n [TEXT.encode(\"position_nft\"), slab.toBytes(), idxBuf(userIdx)],\n programId,\n );\n}\n\n/**\n * Derive the PositionNft mint PDA.\n * Seeds: [\"position_nft_mint\", slab, user_idx_u16_LE]\n */\nexport function deriveNftMint(\n slab: PublicKey,\n userIdx: number,\n programId: PublicKey = NFT_PROGRAM_ID,\n): [PublicKey, number] {\n return PublicKey.findProgramAddressSync(\n [TEXT.encode(\"position_nft_mint\"), slab.toBytes(), idxBuf(userIdx)],\n programId,\n );\n}\n\n/**\n * Derive the program-wide mint authority PDA.\n * Seeds: [\"mint_authority\"]\n */\nexport function deriveMintAuthority(\n programId: PublicKey = NFT_PROGRAM_ID,\n): [PublicKey, number] {\n return PublicKey.findProgramAddressSync(\n [TEXT.encode(\"mint_authority\")],\n programId,\n );\n}\n\n// ---------------------------------------------------------------------------\n// Account parser\n// ---------------------------------------------------------------------------\n\n/**\n * On-chain PositionNft state (208 bytes, matches percolator-nft/src/state.rs).\n *\n * [0..8] magic u64\n * [8] version u8\n * [9] bump u8\n * [10..16] _pad0\n * [16..48] slab [u8; 32]\n * [48..50] user_idx u16 LE\n * [50..56] _pad1\n * [56..88] nft_mint [u8; 32]\n * [88..96] entry_price_e6 u64\n * [96..104] position_size u64\n * [104] is_long u8\n * [105..112] _pad2\n * [112..128] position_basis_q i128\n * [128..144] last_funding_index_e18 i128\n * [144..152] minted_at i64\n * [152..160] account_id u64\n * [160..192] position_owner [u8; 32]\n * [192..208] _reserved\n */\nexport const POSITION_NFT_STATE_LEN = 208;\n\nexport interface PositionNftState {\n version: number;\n bump: number;\n slab: PublicKey;\n userIdx: number;\n nftMint: PublicKey;\n positionOwner: PublicKey;\n entryPriceE6: bigint;\n positionSize: bigint;\n isLong: boolean;\n positionBasisQ: bigint;\n lastFundingIndexE18: bigint;\n mintedAt: bigint;\n accountId: bigint;\n}\n\n/**\n * Read a little-endian signed i128 from a DataView at `offset`.\n *\n * Both 64-bit halves are read as UNSIGNED to avoid the sign-extension that\n * `getBigInt64` applies to the low half. If bit 127 of the combined 128-bit\n * value is set the result is negative and two's-complement sign extension is\n * applied explicitly.\n *\n * Bug fixed (S-3): the prior code used `getBigInt64` for the low half, which\n * returns a *signed* BigInt. When bit 63 of the low half is set the value is\n * negative (e.g. -1 rather than 0xffffffffffffffff), so OR-ing it with the\n * shifted high half collapses the sign bit into all high bits and corrupts the\n * result.\n *\n * @param view DataView wrapping the raw account bytes\n * @param offset Byte offset of the i128 field (little-endian)\n * @returns Signed BigInt in the range [-2^127, 2^127)\n */\nfunction readI128FromView(view: DataView, offset: number): bigint {\n const lo = view.getBigUint64(offset, true);\n const hi = view.getBigUint64(offset + 8, true);\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/**\n * Parse a PositionNft account from raw bytes.\n * @throws if data is shorter than POSITION_NFT_STATE_LEN (208 bytes).\n */\nexport function parsePositionNftAccount(data: Uint8Array): PositionNftState {\n if (data.length < POSITION_NFT_STATE_LEN) {\n throw new Error(\n `PositionNft account too small: ${data.length} < ${POSITION_NFT_STATE_LEN}`,\n );\n }\n\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\n return {\n version: data[8],\n bump: data[9],\n slab: new PublicKey(data.subarray(16, 48)),\n userIdx: view.getUint16(48, true),\n nftMint: new PublicKey(data.subarray(56, 88)),\n positionOwner: new PublicKey(data.subarray(160, 192)),\n entryPriceE6: view.getBigUint64(88, true),\n positionSize: view.getBigUint64(96, true),\n isLong: data[104] === 1,\n positionBasisQ: readI128FromView(view, 112),\n lastFundingIndexE18: readI128FromView(view, 128),\n mintedAt: view.getBigInt64(144, true),\n accountId: view.getBigUint64(152, true),\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: \"ESa89R5Es3rJ5mnwGybVRG1GrNt9etP11Z5V2QWD4edv\",\n matcher: \"GDK8wx38kpiSVSfGTVNiSdptX3Z5R4kQyqh6Q3QX6wmi\",\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 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 // 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 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 // 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","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 if (off >= data.length) {\n throw new RangeError(`readU8: offset ${off} out of bounds (length ${data.length})`);\n }\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/** Slab magic number (\"PERCOLAT\" as little-endian u64). */\nexport const SLAB_MAGIC = MAGIC;\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 // Optional fallback for engines without a stored mark_price field (v12.17+):\n // absolute offset into the slab of `config.mark_ewma_e6` (u64 little-endian,\n // scaled 1e6). Consumers that previously read `engine.mark_price` should\n // check this when `engineMarkPriceOff < 0`. Undefined on layouts that\n // predate v12.17 and already expose a real engine.mark_price.\n configMarkEwmaOff?: number;\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.\n// V12_1 layout constants — verified via `cargo build-sbf` compile-time offset_of! assertions.\n// IMPORTANT: The deployed `percolator` library is DIFFERENT from `percolator-core`.\n// The deployed struct has a simpler InsuranceFund (16 bytes), simpler RiskParams (184 bytes),\n// and NO fields for: total_oi, long_oi, short_oi, net_lp_pos, lp_sum_abs, lp_max_abs,\n// mark_price_e6, funding_index, last_funding_slot, emergency_*, lifetime_force_closes.\n// Those fields exist in percolator-core but NOT in the deployed binary.\n//\n// HOST constants below are for aarch64 test builds (percolator-core).\n// SBF constants are for the actual deployed program.\nconst V12_1_ENGINE_OFF = 648; // HOST: align_up(72 + 576, 16) = 648\nconst V12_1_ACCOUNT_SIZE = 320; // HOST aarch64 size\nconst V12_1_ACCOUNT_SIZE_SBF = 280; // SBF: verified by cargo build-sbf\nconst V12_1_ENGINE_BITMAP_OFF = 1016; // HOST bitmap offset (used field in percolator-core RiskEngine)\n// SBF layout: InsuranceFund = {balance: U128} = 16 bytes. RiskParams = 184 bytes.\n// vault(16) + InsuranceFund(16) = 32 → params at engine+32.\nconst V12_1_ENGINE_PARAMS_OFF_SBF = 32; // offset_of!(RiskEngine, params) on SBF\nconst V12_1_ENGINE_PARAMS_OFF_HOST = 96; // HOST value (percolator-core with 80-byte InsuranceFund)\nconst V12_1_ENGINE_PARAMS_OFF = 96;\nconst V12_1_PARAMS_SIZE_SBF = 184; // SBF: size_of::<RiskParams>() = 184\nconst V12_1_PARAMS_SIZE = 352; // HOST: percolator-core RiskParams\n// SBF engine field offsets (relative to engineOff=616), verified by compiler:\nconst V12_1_SBF_OFF_CURRENT_SLOT = 216;\nconst V12_1_SBF_OFF_FUNDING_RATE = 224;\nconst V12_1_SBF_OFF_LAST_CRANK_SLOT = 232;\nconst V12_1_SBF_OFF_MAX_CRANK_STALENESS = 240;\nconst V12_1_SBF_OFF_C_TOT = 248;\nconst V12_1_SBF_OFF_PNL_POS_TOT = 264;\nconst V12_1_SBF_OFF_LIQ_CURSOR = 296;\nconst V12_1_SBF_OFF_GC_CURSOR = 298;\nconst V12_1_SBF_OFF_LAST_SWEEP_START = 304;\nconst V12_1_SBF_OFF_LAST_SWEEP_COMPLETE = 312;\nconst V12_1_SBF_OFF_CRANK_CURSOR = 320;\nconst V12_1_SBF_OFF_SWEEP_START_IDX = 322;\nconst V12_1_SBF_OFF_LIFETIME_LIQUIDATIONS = 328;\n// Probed from mainnet slab FLF9ghf6H4sfSexcQzDwse4gcGZKPb6qYCqo5Btat98 (290120 bytes).\n// These fields DO exist in the deployed SBF binary despite earlier \"not in deployed struct\" notes.\nconst V12_1_SBF_OFF_TOTAL_OI = 448; // u128: totalOpenInterest (verified: 907109 matches sum of abs positions)\nconst V12_1_SBF_OFF_LONG_OI = 464; // u128: longOi (verified: 907109 = all positions are long)\nconst V12_1_SBF_OFF_SHORT_OI = 480; // u128: shortOi (verified: 0)\nconst V12_1_SBF_OFF_MARK_PRICE_E6 = 560; // u64: markPriceE6 (verified: 85187279 = $85.19)\nconst V12_1_SBF_OFF_MARK_PRICE_SLOT = 568; // u64: slot when mark price was last updated\nconst V12_1_SBF_OFF_EFFECTIVE_PRICE_E6 = 576; // u64: lastEffectivePriceE6 (verified: matches mark)\n// ADL state: 336–576 (adl_mult, adl_coeff, adl_epoch, oi_eff, side_mode, etc.)\n// last_oracle_price: 560, last_market_slot: 568, funding_price_sample: 576\n// Bitmap (used field): 584\n// Fields NOT present in deployed program (return -1):\n// total_oi, long_oi, short_oi, net_lp_pos, lp_sum_abs, lp_max_abs, lp_max_abs_sweep,\n// mark_price, funding_index, last_funding_slot, emergency_*, lifetime_force_closes\n//\n// HOST engine field offsets (percolator-core, for test builds):\nconst V12_1_ENGINE_CURRENT_SLOT_OFF = 448;\nconst V12_1_ENGINE_FUNDING_RATE_BPS_OFF = 456;\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;\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// HOST-only fields (percolator-core has these, deployed percolator does not):\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;\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;\nconst V12_1_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 1008;\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 = 88; // position_basis_q: i128 at offset 88 (SBF)\nconst V12_1_ACCT_ENTRY_PRICE_OFF = -1; // -1 for old V12_1 slabs (280-byte accounts)\nconst V12_1_ACCT_FUNDING_INDEX_OFF = -1; // does not exist in SBF layout\n\n// ---- V12_1_EP: V12_1 with entry_price re-added (accountSize=288 on SBF, 304 on host) ----\n// entry_price(u64) inserted after adl_epoch_snap, shifting matcher/owner/fees +8.\n// SBF layout (u128 align=8):\n// ...adl_epoch_snap(u64@136) → entry_price(u64@144) → matcher_program(@152)\n// → matcher_context(@184) → owner(@216) → fee_credits(@248) → last_fee_slot(@264)\n// → fees_earned_total(@272) = 288 bytes\nconst V12_1_EP_SBF_ACCOUNT_SIZE = 288;\nconst V12_1_EP_ACCT_ENTRY_PRICE_OFF = 144;\nconst V12_1_EP_ACCT_MATCHER_PROGRAM_OFF = 152;\nconst V12_1_EP_ACCT_MATCHER_CONTEXT_OFF = 184;\nconst V12_1_EP_ACCT_OWNER_OFF = 216;\nconst V12_1_EP_ACCT_FEE_CREDITS_OFF = 248;\nconst V12_1_EP_ACCT_LAST_FEE_SLOT_OFF = 264;\n\n// ---- V12_15 layout constants (percolator engine+prog v12.15 sync) ----\n// Account struct completely redesigned: sizeof=4400 bytes (SBF and host identical — all fields\n// explicitly sized, no pointer-derived alignment differences).\n// Fields REMOVED: warmupStartedAtSlot, warmupSlopePerStep, lastFeeSlot.\n// Fields ADDED: entry_price(u64@120), exact_reserve_cohorts(62*64=3968 bytes@256),\n// exact_cohort_count(u8@4224), overflow_older(ReserveCohort=64 bytes@4240),\n// overflow_older_present(u8@4304), overflow_newest(ReserveCohort=64@4320),\n// overflow_newest_present(u8@4384).\n// RiskParams sizeof=192: warmup_period_slots split into h_min(u64@160) + h_max(u64@168).\n// Field max_accounts moved to offset 24, insurance_floor at 144.\n// RiskEngine: ENGINE_OFF=624 (HEADER=72 + CONFIG=552, SBF aligned).\n// funding_rate renamed funding_rate_e9, now i128 (16 bytes) at offset 240 (was i64 at 224).\n// market_mode(u8) added at offset 256. pnl_matured_pos_tot(u128) added at 384.\n// RISK_BUF_OFF = ENGINE_OFF + ENGINE_LEN; RISK_BUF_LEN = 160.\n// SBF SLAB_LEN for --features small (MAX_ACCOUNTS=256): 1,128,448 bytes (verified by native test).\n// All account offsets below match both SBF and native (no alignment divergence for this struct).\nconst V12_15_ENGINE_OFF = 624; // native: align_up(616, 16) = 624\nconst V12_15_ENGINE_OFF_SBF = 616; // SBF: align_up(616, 8) = 616 (i128 align=8)\nconst V12_15_ACCOUNT_SIZE = 4400; // sizeof(Account) with 62 cohorts (default)\nconst V12_15_ACCOUNT_SIZE_SMALL = 920; // SBF sizeof(Account) with 8 cohorts (--features small, u128 align=8)\nconst V12_15_DEFAULT_MAX_ACCOUNTS = 2048; // was 4096, changed in v12.15\n\n// V12_15 account field offsets (relative to account slot start):\nconst V12_15_ACCT_ACCOUNT_ID_OFF = 0; // u64\nconst V12_15_ACCT_CAPITAL_OFF = 8; // u128\nconst V12_15_ACCT_KIND_OFF = 24; // u8 + 7 pad\nconst V12_15_ACCT_PNL_OFF = 32; // i128\nconst V12_15_ACCT_RESERVED_PNL_OFF = 48; // u128\nconst V12_15_ACCT_POSITION_BASIS_Q_OFF = 64; // i128\nconst V12_15_ACCT_ADL_A_BASIS_OFF = 80; // u128\nconst V12_15_ACCT_ADL_K_SNAP_OFF = 96; // i128\nconst V12_15_ACCT_ADL_EPOCH_SNAP_OFF = 112; // u64\nconst V12_15_ACCT_ENTRY_PRICE_OFF = 120; // u64 (NEW — re-added in v12.15)\nconst V12_15_ACCT_MATCHER_PROGRAM_OFF = 128; // Pubkey\nconst V12_15_ACCT_MATCHER_CONTEXT_OFF = 160; // Pubkey\nconst V12_15_ACCT_OWNER_OFF = 192; // Pubkey\nconst V12_15_ACCT_FEE_CREDITS_OFF = 224; // i128 (16)\nconst V12_15_ACCT_FEES_EARNED_TOTAL_OFF = 240; // u128 (16)\n// exact_reserve_cohorts: [ReserveCohort; 62], each 64 bytes = 3968 bytes\nconst V12_15_ACCT_EXACT_RESERVE_COHORTS_OFF = 256; // 62 * 64 = 3968 bytes\nconst V12_15_ACCT_EXACT_COHORT_COUNT_OFF = 4224; // u8 (+ 15 pad = 16 bytes)\nconst V12_15_ACCT_OVERFLOW_OLDER_OFF = 4240; // ReserveCohort (64 bytes)\nconst V12_15_ACCT_OVERFLOW_OLDER_PRESENT_OFF = 4304; // u8 (+ 15 pad = 16 bytes)\nconst V12_15_ACCT_OVERFLOW_NEWEST_OFF = 4320; // ReserveCohort (64 bytes)\nconst V12_15_ACCT_OVERFLOW_NEWEST_PRESENT_OFF = 4384; // u8 (+ 15 pad = 16 bytes)\n\n// V12_15 RiskParams offsets (relative to params base):\n// sizeof(RiskParams) = 192\nconst V12_15_PARAMS_SIZE = 192;\nconst V12_15_PARAMS_MAX_ACCOUNTS_OFF = 24; // u64 (moved from 32)\nconst V12_15_PARAMS_INSURANCE_FLOOR_OFF = 144; // u128\nconst V12_15_PARAMS_H_MIN_OFF = 160; // u64 (was warmup_period_slots)\nconst V12_15_PARAMS_H_MAX_OFF = 168; // u64 (NEW)\n\n// V12_15 RiskEngine offsets (relative to ENGINE_OFF):\n// vault(16) + InsuranceFund(16) + RiskParams(192) = 224 before current_slot\nconst V12_15_ENGINE_PARAMS_OFF = 32; // vault(16) + InsuranceFund(16) = 32\nconst V12_15_ENGINE_CURRENT_SLOT_OFF = 224; // u64\n// 8-byte gap at 232 (padding or auxiliary field before i128-aligned funding_rate_e9)\nconst V12_15_ENGINE_FUNDING_RATE_E9_OFF = 240; // i128 (NEW — was i64 funding_rate at 224)\nconst V12_15_ENGINE_MARKET_MODE_OFF = 256; // u8 (NEW — 0=Live, 1=Resolved)\n// c_tot at 344, pnl_pos_tot at 368, pnl_matured_pos_tot at 384 (NEW)\nconst V12_15_ENGINE_C_TOT_OFF = 344; // u128\nconst V12_15_ENGINE_PNL_POS_TOT_OFF = 368; // u128\nconst V12_15_ENGINE_PNL_MATURED_POS_TOT_OFF = 384; // u128 (NEW)\n// Bitmap offset derived from SLAB_LEN=1,128,448 for n=256 and accountsOff_rel=1424:\n// bitmapOff = 1424 - ceil(256/64)*8 - 18 - 256*2 = 1424 - 32 - 18 - 512 = 862\nconst V12_15_ENGINE_BITMAP_OFF = 862;\n\n// V12_15 size map for layout detection\nconst V12_15_SIZES = new Map<number, number>();\n\n// ---- V12_17 layout constants (two-bucket warmup, per-side funding) ----\n// Account: 368 bytes (native, i128 align=16) / 352 bytes (SBF, i128 align=8).\n// 62-cohort reserve queue → two-bucket warmup (sched_* + pending_*).\n// Removed: account_id, entry_price, fees_earned_total, cohort arrays.\n// Added: f_snap(i128), sched_present/remaining_q/anchor_q/start_slot/horizon/release_q,\n// pending_present/remaining_q/horizon/created_slot.\n// RiskParams sizeof=192 (native) / 184 (SBF). Same fields as v12.15.\n// RiskEngine: vault(16) + InsuranceFund(16) + RiskParams = 224 (native) / 216 (SBF) before current_slot.\n// Removed: funding_rate_e9 (stored). Added: per-side f_long_num/f_short_num cumulative funding.\n// Added: market_mode, resolved_*, neg_pnl_account_count, fund_px_last.\n// MAX_ACCOUNTS default=4096 (was 2048 in v12.15).\n// RISK_BUF_OFF = ENGINE_OFF + ENGINE_LEN; RISK_BUF_LEN = 160.\n// On-chain (SBF) SLAB_LEN includes RISK_BUF; native test SLAB_LEN also includes it.\n\n// MarketConfig size — 512 bytes post Phase A/B/E (fork addition of 80 bytes:\n// max_pnl_cap, last_audit_pause_slot, oi_cap_multiplier_bps, dispute_window_slots,\n// dispute_bond_amount, lp_collateral_enabled, lp_collateral_ltv_bps,\n// _new_fields_pad, pending_admin[32]).\n// Verified against percolator-prog/src/percolator.rs::MarketConfig via\n// size_of::<MarketConfig>() = 512 (both native and SBF — u128 fields happen\n// to land on 16-aligned offsets, so the u128 align=8 vs 16 rule is a no-op).\n\n// Native (i128 align=16)\nconst V12_17_ENGINE_OFF = 592; // align_up(72 + 512, 16) = 592\nconst V12_17_ACCOUNT_SIZE = 368;\nconst V12_17_ENGINE_BITMAP_OFF = 752; // offset_of!(RiskEngine, used) on native — relative, unchanged\nconst V12_17_DEFAULT_MAX_ACCOUNTS = 4096;\nconst V12_17_RISK_BUF_LEN = 160;\n// Per-account generation table appended after RISK_BUF in percolator-prog.\n// See percolator-prog/src/percolator.rs:87 — GEN_TABLE_LEN = MAX_ACCOUNTS * 8.\nconst V12_17_GEN_TABLE_ENTRY = 8;\n\n// SBF (i128 align=8)\nconst V12_17_ENGINE_OFF_SBF = 584; // align_up(72 + 512, 8) = 584\nconst V12_17_ACCOUNT_SIZE_SBF = 352;\nconst V12_17_ENGINE_BITMAP_OFF_SBF = 712; // offset_of!(RiskEngine, used) on SBF — relative, unchanged\n\n// V12_17 account field offsets (native — SBF offsets are 8 bytes less for fields after kind)\nconst V12_17_ACCT_CAPITAL_OFF = 0; // U128=[u64;2]\nconst V12_17_ACCT_KIND_OFF = 16; // u8\nconst V12_17_ACCT_PNL_OFF = 32; // i128 (native 16-align pad from 17→32)\nconst V12_17_ACCT_RESERVED_PNL_OFF = 48; // u128\nconst V12_17_ACCT_POSITION_BASIS_Q_OFF = 64; // i128\nconst V12_17_ACCT_ADL_A_BASIS_OFF = 80; // u128\nconst V12_17_ACCT_ADL_K_SNAP_OFF = 96; // i128\nconst V12_17_ACCT_F_SNAP_OFF = 112; // i128\nconst V12_17_ACCT_ADL_EPOCH_SNAP_OFF = 128; // u64\nconst V12_17_ACCT_MATCHER_PROGRAM_OFF = 136; // [u8;32]\nconst V12_17_ACCT_MATCHER_CONTEXT_OFF = 168; // [u8;32]\nconst V12_17_ACCT_OWNER_OFF = 200; // [u8;32]\nconst V12_17_ACCT_FEE_CREDITS_OFF = 232; // I128=[u64;2]\nconst V12_17_ACCT_SCHED_PRESENT_OFF = 248; // u8\nconst V12_17_ACCT_SCHED_REMAINING_Q_OFF = 256; // u128\nconst V12_17_ACCT_SCHED_ANCHOR_Q_OFF = 272; // u128\nconst V12_17_ACCT_SCHED_START_SLOT_OFF = 288; // u64\nconst V12_17_ACCT_SCHED_HORIZON_OFF = 296; // u64\nconst V12_17_ACCT_SCHED_RELEASE_Q_OFF = 304; // u128\nconst V12_17_ACCT_PENDING_PRESENT_OFF = 320; // u8\nconst V12_17_ACCT_PENDING_REMAINING_Q_OFF = 336; // u128\nconst V12_17_ACCT_PENDING_HORIZON_OFF = 352; // u64\nconst V12_17_ACCT_PENDING_CREATED_SLOT_OFF = 360; // u64\n\n// V12_17 RiskEngine field offsets (native, relative to engine start)\nconst V12_17_ENGINE_PARAMS_OFF = 32; // vault(16) + InsuranceFund(16)\nconst V12_17_ENGINE_CURRENT_SLOT_OFF = 224; // params starts at 32, size 192 → 224\nconst V12_17_ENGINE_MARKET_MODE_OFF = 232; // u8 (MarketMode enum)\nconst V12_17_ENGINE_RESOLVED_PRICE_OFF = 240; // u64\nconst V12_17_ENGINE_RESOLVED_K_LONG_OFF = 304; // i128\nconst V12_17_ENGINE_RESOLVED_K_SHORT_OFF = 320; // i128\nconst V12_17_ENGINE_RESOLVED_LIVE_PRICE_OFF = 336; // u64\nconst V12_17_ENGINE_LAST_CRANK_SLOT_OFF = 344; // u64 — verified via offset_of!(RiskEngine, last_crank_slot)\nconst V12_17_ENGINE_C_TOT_OFF = 352; // U128\nconst V12_17_ENGINE_PNL_POS_TOT_OFF = 368; // u128\nconst V12_17_ENGINE_PNL_MATURED_POS_TOT_OFF = 384; // u128\nconst V12_17_ENGINE_GC_CURSOR_OFF = 400; // u16\nconst V12_17_ENGINE_OI_EFF_LONG_OFF = 528; // u128 — oi_eff_long_q\nconst V12_17_ENGINE_OI_EFF_SHORT_OFF = 544; // u128 — oi_eff_short_q\nconst V12_17_ENGINE_NEG_PNL_COUNT_OFF = 648; // u64\nconst V12_17_ENGINE_LAST_ORACLE_PRICE_OFF = 656; // u64\nconst V12_17_ENGINE_FUND_PX_LAST_OFF = 664; // u64\nconst V12_17_ENGINE_F_LONG_NUM_OFF = 688; // i128\nconst V12_17_ENGINE_F_SHORT_NUM_OFF = 704; // i128\n\n// SBF engine field offsets differ because RiskParams=184 (not 192) shifts everything after params.\n// Offset delta: native params=192, SBF params=184, so diff=8 starting from current_slot.\n// Additional differences accumulate from i128 alignment padding changes within the engine struct.\nconst V12_17_SBF_ENGINE_CURRENT_SLOT_OFF = 216;\nconst V12_17_SBF_ENGINE_MARKET_MODE_OFF = 224;\nconst V12_17_SBF_ENGINE_LAST_CRANK_SLOT_OFF = 328; // u64 — native 344 − 16 (resolved u128 pad)\nconst V12_17_SBF_ENGINE_C_TOT_OFF = 336;\nconst V12_17_SBF_ENGINE_PNL_POS_TOT_OFF = 352;\nconst V12_17_SBF_ENGINE_PNL_MATURED_POS_TOT_OFF = 368;\nconst V12_17_SBF_ENGINE_GC_CURSOR_OFF = 384; // u16 — native 400 − 16\nconst V12_17_SBF_ENGINE_OI_EFF_LONG_OFF = 504; // u128 — native 528 − 24 (adl u128 pad)\nconst V12_17_SBF_ENGINE_OI_EFF_SHORT_OFF = 520; // u128 — native 544 − 24\nconst V12_17_SBF_ENGINE_NEG_PNL_COUNT_OFF = 616;\nconst V12_17_SBF_ENGINE_LAST_ORACLE_PRICE_OFF = 624;\nconst V12_17_SBF_ENGINE_FUND_PX_LAST_OFF = 632;\nconst V12_17_SBF_ENGINE_F_LONG_NUM_OFF = 648;\nconst V12_17_SBF_ENGINE_F_SHORT_NUM_OFF = 664;\n\n// V12_17 size map for layout detection\nconst V12_17_SIZES = new Map<number, number>();\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 on aarch64, 280 on SBF.\n // The SBF binary has different struct alignment (u128 align=8 vs 16 on aarch64).\n // Register BOTH host-computed and SBF-empirical sizes for detection.\n V12_1_SIZES.set(computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, n, 18), n);\n // V12_15: account_size=4400, ENGINE_OFF=624. MAX_ACCOUNTS default=2048, also support 256/1024/4096.\n V12_15_SIZES.set(computeSlabSize(V12_15_ENGINE_OFF, V12_15_ENGINE_BITMAP_OFF, V12_15_ACCOUNT_SIZE, n, 18), n);\n}\n// V12_15 additional tier: MAX_ACCOUNTS=2048 (new default, changed from 4096 in v12.15).\nV12_15_SIZES.set(computeSlabSize(V12_15_ENGINE_OFF, V12_15_ENGINE_BITMAP_OFF, V12_15_ACCOUNT_SIZE, 2048, 18), 2048);\n// V12_15_SMALL: --features small (8 cohorts, 944-byte accounts). Hardcoded sizes verified via cargo test.\nV12_15_SIZES.set(237512, 256); // small (SBF): 256 accounts, 8 cohorts, SLAB_LEN=237512 (SBF u128 align=8)\n\n// V12_17 sizes — native and SBF, with and without RISK_BUF (160 bytes).\n// Native: Account align=16 → accountsOff alignment is 16, not 8.\n// SBF: Account align=8 → accountsOff alignment is 8.\n// Both on-chain and wrapper tests use SLAB_LEN which includes RISK_BUF.\n// postBitmap=4 (num_used_accounts: u16 + free_head: u16, no next_account_id or pad).\nconst V12_17_TIERS = [256, 1024, 4096] as const;\nfor (const n of V12_17_TIERS) {\n const bitmapWords = Math.ceil(n / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 4;\n const nextFreeBytes = n * 2;\n\n // Native (i128 align=16, Account align=16)\n const preAccNative = V12_17_ENGINE_BITMAP_OFF + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffNative = Math.ceil(preAccNative / 16) * 16; // align to Account alignment (16)\n const nativeSize = V12_17_ENGINE_OFF + accountsOffNative + n * V12_17_ACCOUNT_SIZE + V12_17_RISK_BUF_LEN + n * V12_17_GEN_TABLE_ENTRY;\n V12_17_SIZES.set(nativeSize, n);\n\n // SBF (i128 align=8, Account align=8)\n const preAccSbf = V12_17_ENGINE_BITMAP_OFF_SBF + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffSbf = Math.ceil(preAccSbf / 8) * 8;\n const sbfSize = V12_17_ENGINE_OFF_SBF + accountsOffSbf + n * V12_17_ACCOUNT_SIZE_SBF + V12_17_RISK_BUF_LEN + n * V12_17_GEN_TABLE_ENTRY;\n V12_17_SIZES.set(sbfSize, n);\n}\n\n// ---- V12_19 layout constants (CONFIG_LEN +16 = 528, ENGINE_OFFSET = 600) ----\n// Verified against /Users/khubair/perc-sync/work/percolator-prog tests/common/mod.rs:60-61\n// (`pub const ENGINE_OFFSET: usize = 600`) and tests/test_conservation.rs:769\n// (engine.vault U128 at slab+616 = ENGINE_OFFSET+16).\n//\n// Engine struct internal layout is unchanged from V12_17 SBF — only the\n// header+config size grew by 16 bytes (MarketConfig added pending_admin_aux\n// and small alignment padding fields). Account size, bitmap offset, and\n// generation table layout inherit from V12_17 SBF exactly.\nconst V12_19_CONFIG_LEN = 528; // V12_17 512 + 16\nconst V12_19_ENGINE_OFF_SBF = 600; // align_up(72 + 528, 8) = 600\n\n// V12_19 SLAB_LEN values verified against\n// /Users/khubair/perc-sync/work/percolator-prog/tests/cu_benchmark.rs:49-64\n// (each value is gated on a separate feature flag — micro/small/medium/large).\n// The 256-tier value 94168 collides with V12_17 SBF small. The deployed\n// program post-2026-04-28 upgrade only produces v12.19 slabs, so detect order\n// (V12_19 first) handles disambiguation in practice.\nconst V12_19_SIZES = new Map<number, number>([\n [19640, 64], // --features micro\n [94168, 256], // --features small (deployed mainnet ESa89R5...)\n [372280, 1024], // --features medium\n [1484728, 4096], // default features (large)\n]);\n\n/**\n * V12_19 slab layout. Engine struct internals are identical to V12_17 SBF.\n * Only header+config grew by 16 bytes (CONFIG_LEN 512 -> 528), shifting\n * engineOff from 584 to 600 and accountsOff by the same 16. Everything\n * else inherits from buildLayoutV12_17 SBF mode.\n */\nfunction buildLayoutV12_19(maxAccounts: number, dataLen: number): SlabLayout {\n const base = buildLayoutV12_17(maxAccounts, dataLen);\n return {\n ...base,\n configLen: V12_19_CONFIG_LEN,\n engineOff: V12_19_ENGINE_OFF_SBF,\n accountsOff: V12_19_ENGINE_OFF_SBF + (base.accountsOff - base.engineOff),\n };\n}\n\n// SBF-specific V12_1 sizes (verified via cargo build-sbf compile-time offset_of! assertions).\n// SBF has ENGINE_OFF=616 (not 648) because HEADER=72 + CONFIG=544 = 616, align_up(616,8)=616.\n// Account=280 bytes on SBF (vs 320 on aarch64) due to u128 align=8 vs 16.\n// Bitmap at engine+584 (used field in RiskEngine).\nconst V12_1_SBF_ACCOUNT_SIZE = 280;\nconst V12_1_SBF_ENGINE_OFF = 616;\nconst V12_1_SBF_BITMAP_OFF = 584; // offset_of!(RiskEngine, used) on SBF\nfor (const [, n] of [[\"Micro\", 64], [\"Small\", 256], [\"Medium\", 1024], [\"Large\", 4096]] as const) {\n const bitmapBytes = Math.ceil(n / 64) * 8;\n const preAccLen = V12_1_SBF_BITMAP_OFF + bitmapBytes + 18 + n * 2;\n const accountsOff = Math.ceil(preAccLen / 8) * 8;\n const total = V12_1_SBF_ENGINE_OFF + accountsOff + n * V12_1_SBF_ACCOUNT_SIZE;\n V12_1_SIZES.set(total, n);\n}\n// V12_1_EP: entry_price re-added, accountSize=288 on SBF. Same engineOff/bitmapOff.\nconst V12_1_EP_SIZES = new Map<number, number>();\nfor (const [, n] of [[\"Micro\", 64], [\"Small\", 256], [\"Medium\", 1024], [\"Large\", 4096]] as const) {\n const bitmapBytes = Math.ceil(n / 64) * 8;\n const preAccLen = V12_1_SBF_BITMAP_OFF + bitmapBytes + 18 + n * 2;\n const accountsOff = Math.ceil(preAccLen / 8) * 8;\n const total = V12_1_SBF_ENGINE_OFF + accountsOff + n * V12_1_EP_SBF_ACCOUNT_SIZE;\n V12_1_EP_SIZES.set(total, 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 * V12_15 slab tier sizes — percolator v12.15 (engine+prog sync).\n * ENGINE_OFF=624, BITMAP_OFF=862 (relative), ACCOUNT_SIZE=4400, postBitmap=18.\n * MAX_ACCOUNTS default changed from 4096 to 2048. Verified SLAB_LEN=1,128,448 for small (256).\n * Account layout completely redesigned with reserve cohort arrays.\n */\nexport const SLAB_TIERS_V12_15: Record<string, { maxAccounts: number; dataSize: number; label: string; description: string }> = {};\nfor (const [label, n] of [[\"Micro\", 64], [\"Small\", 256], [\"Medium\", 1024], [\"Medium2048\", 2048], [\"Large\", 4096]] as const) {\n const size = computeSlabSize(V12_15_ENGINE_OFF, V12_15_ENGINE_BITMAP_OFF, V12_15_ACCOUNT_SIZE, n, 18);\n SLAB_TIERS_V12_15[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (v12.15)` };\n}\n\n/**\n * V12_17 slab tier sizes — percolator v12.17 (two-bucket warmup, per-side funding).\n * Uses SBF sizes (on-chain layout) for the dataSize values.\n * ENGINE_OFF=504 (SBF), ACCOUNT_SIZE=352 (SBF), BITMAP_OFF=712 (SBF), postBitmap=4.\n * RISK_BUF_LEN=160 appended after engine.\n * Supported tiers: small(256), medium(1024), large(4096).\n */\nexport const SLAB_TIERS_V12_17: Record<string, { maxAccounts: number; dataSize: number; label: string; description: string }> = {};\nfor (const [label, n] of [[\"Small\", 256], [\"Medium\", 1024], [\"Large\", 4096]] as const) {\n const bitmapBytes = Math.ceil(n / 64) * 8;\n const preAcc = V12_17_ENGINE_BITMAP_OFF_SBF + bitmapBytes + 4 + n * 2;\n const accountsOff = Math.ceil(preAcc / 8) * 8;\n const size = V12_17_ENGINE_OFF_SBF + accountsOff + n * V12_17_ACCOUNT_SIZE_SBF + V12_17_RISK_BUF_LEN + n * V12_17_GEN_TABLE_ENTRY;\n SLAB_TIERS_V12_17[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (v12.17)` };\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, dataLen?: number): SlabLayout {\n // SBF vs host detection via size comparison.\n // SBF (deployed): HEADER=72, CONFIG=544, ENGINE_OFF=616, ACCOUNT=280, BITMAP=engine+584\n // Host (tests): HEADER=72, CONFIG=576, ENGINE_OFF=648, ACCOUNT=320, BITMAP=engine+1016\n // All SBF offsets verified via `cargo build-sbf` compile-time offset_of! assertions.\n const hostSize = computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, maxAccounts, 18);\n const isSbf = dataLen !== undefined && dataLen !== hostSize;\n const engineOff = isSbf ? V12_1_SBF_ENGINE_OFF : V12_1_ENGINE_OFF;\n const bitmapOff = isSbf ? V12_1_SBF_BITMAP_OFF : (V12_1_ENGINE_BITMAP_OFF - V12_1_ENGINE_OFF);\n const accountSize = isSbf ? V12_1_ACCOUNT_SIZE_SBF : 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: V0_HEADER_LEN, // 72\n configOffset: V0_HEADER_LEN, // 72\n configLen: isSbf ? 544 : 576,\n reservedOff: V1_RESERVED_OFF,\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: isSbf ? V12_1_ENGINE_PARAMS_OFF_SBF : V12_1_ENGINE_PARAMS_OFF_HOST,\n paramsSize: isSbf ? V12_1_PARAMS_SIZE_SBF : V12_1_PARAMS_SIZE,\n // SBF engine offsets — all verified by cargo build-sbf offset_of! assertions.\n // Fields that don't exist in the deployed program are set to -1 on SBF.\n engineCurrentSlotOff: isSbf ? V12_1_SBF_OFF_CURRENT_SLOT : V12_1_ENGINE_CURRENT_SLOT_OFF,\n engineFundingIndexOff: isSbf ? -1 : V12_1_ENGINE_FUNDING_INDEX_OFF, // not in deployed struct\n engineLastFundingSlotOff: isSbf ? -1 : V12_1_ENGINE_LAST_FUNDING_SLOT_OFF, // not in deployed struct\n engineFundingRateBpsOff: isSbf ? V12_1_SBF_OFF_FUNDING_RATE : V12_1_ENGINE_FUNDING_RATE_BPS_OFF,\n engineMarkPriceOff: isSbf ? V12_1_SBF_OFF_MARK_PRICE_E6 : V12_1_ENGINE_MARK_PRICE_OFF,\n engineLastCrankSlotOff: isSbf ? V12_1_SBF_OFF_LAST_CRANK_SLOT : V12_1_ENGINE_LAST_CRANK_SLOT_OFF,\n engineMaxCrankStalenessOff: isSbf ? V12_1_SBF_OFF_MAX_CRANK_STALENESS : V12_1_ENGINE_MAX_CRANK_STALENESS_OFF,\n engineTotalOiOff: isSbf ? V12_1_SBF_OFF_TOTAL_OI : V12_1_ENGINE_TOTAL_OI_OFF,\n engineLongOiOff: isSbf ? V12_1_SBF_OFF_LONG_OI : V12_1_ENGINE_LONG_OI_OFF,\n engineShortOiOff: isSbf ? V12_1_SBF_OFF_SHORT_OI : V12_1_ENGINE_SHORT_OI_OFF,\n engineCTotOff: isSbf ? V12_1_SBF_OFF_C_TOT : V12_1_ENGINE_C_TOT_OFF,\n enginePnlPosTotOff: isSbf ? V12_1_SBF_OFF_PNL_POS_TOT : V12_1_ENGINE_PNL_POS_TOT_OFF,\n engineLiqCursorOff: isSbf ? V12_1_SBF_OFF_LIQ_CURSOR : V12_1_ENGINE_LIQ_CURSOR_OFF,\n engineGcCursorOff: isSbf ? V12_1_SBF_OFF_GC_CURSOR : V12_1_ENGINE_GC_CURSOR_OFF,\n engineLastSweepStartOff: isSbf ? V12_1_SBF_OFF_LAST_SWEEP_START : V12_1_ENGINE_LAST_SWEEP_START_OFF,\n engineLastSweepCompleteOff: isSbf ? V12_1_SBF_OFF_LAST_SWEEP_COMPLETE : V12_1_ENGINE_LAST_SWEEP_COMPLETE_OFF,\n engineCrankCursorOff: isSbf ? V12_1_SBF_OFF_CRANK_CURSOR : V12_1_ENGINE_CRANK_CURSOR_OFF,\n engineSweepStartIdxOff: isSbf ? V12_1_SBF_OFF_SWEEP_START_IDX : V12_1_ENGINE_SWEEP_START_IDX_OFF,\n engineLifetimeLiquidationsOff: isSbf ? V12_1_SBF_OFF_LIFETIME_LIQUIDATIONS : V12_1_ENGINE_LIFETIME_LIQUIDATIONS_OFF,\n engineLifetimeForceClosesOff: isSbf ? -1 : V12_1_ENGINE_LIFETIME_FORCE_CLOSES_OFF, // not in deployed struct\n engineNetLpPosOff: isSbf ? -1 : V12_1_ENGINE_NET_LP_POS_OFF, // not in deployed struct\n engineLpSumAbsOff: isSbf ? -1 : V12_1_ENGINE_LP_SUM_ABS_OFF, // not in deployed struct\n engineLpMaxAbsOff: isSbf ? -1 : V12_1_ENGINE_LP_MAX_ABS_OFF, // not in deployed struct\n engineLpMaxAbsSweepOff: isSbf ? -1 : V12_1_ENGINE_LP_MAX_ABS_SWEEP_OFF, // not in deployed struct\n engineEmergencyOiModeOff: isSbf ? -1 : V12_1_ENGINE_EMERGENCY_OI_MODE_OFF, // not in deployed struct\n engineEmergencyStartSlotOff: isSbf ? -1 : V12_1_ENGINE_EMERGENCY_START_SLOT_OFF, // not in deployed struct\n engineLastBreakerSlotOff: isSbf ? -1 : V12_1_ENGINE_LAST_BREAKER_SLOT_OFF, // not in deployed struct\n engineBitmapOff: bitmapOff,\n postBitmap: 18,\n acctOwnerOff: V12_1_ACCT_OWNER_OFF,\n\n // InsuranceFund on deployed program is just {balance: U128} = 16 bytes.\n // No isolated_balance or insurance_isolation_bps fields.\n hasInsuranceIsolation: !isSbf,\n engineInsuranceIsolatedOff: isSbf ? -1 : 48,\n engineInsuranceIsolationBpsOff: isSbf ? -1 : 64,\n };\n}\n\n/**\n * V12_1 with entry_price re-added (SBF only, accountSize=288).\n * Same engine layout as V12_1 SBF, but account offsets shift +8 after entry_price.\n */\nfunction buildLayoutV12_1EP(maxAccounts: number): SlabLayout {\n const engineOff = V12_1_SBF_ENGINE_OFF; // 616\n const bitmapOff = V12_1_SBF_BITMAP_OFF; // 584\n const accountSize = V12_1_EP_SBF_ACCOUNT_SIZE; // 288\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: 72,\n configOffset: 72,\n configLen: 544,\n reservedOff: 80, // V1_RESERVED_OFF\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: 32, // V12_1_ENGINE_PARAMS_OFF_SBF\n paramsSize: 184, // V12_1_PARAMS_SIZE_SBF\n // Engine offsets identical to V12_1 SBF\n engineCurrentSlotOff: V12_1_SBF_OFF_CURRENT_SLOT,\n engineFundingIndexOff: -1,\n engineLastFundingSlotOff: -1,\n engineFundingRateBpsOff: V12_1_SBF_OFF_FUNDING_RATE,\n engineMarkPriceOff: V12_1_SBF_OFF_MARK_PRICE_E6,\n engineLastCrankSlotOff: V12_1_SBF_OFF_LAST_CRANK_SLOT,\n engineMaxCrankStalenessOff: V12_1_SBF_OFF_MAX_CRANK_STALENESS,\n engineTotalOiOff: V12_1_SBF_OFF_TOTAL_OI,\n engineLongOiOff: V12_1_SBF_OFF_LONG_OI,\n engineShortOiOff: V12_1_SBF_OFF_SHORT_OI,\n engineCTotOff: V12_1_SBF_OFF_C_TOT,\n enginePnlPosTotOff: V12_1_SBF_OFF_PNL_POS_TOT,\n engineLiqCursorOff: V12_1_SBF_OFF_LIQ_CURSOR,\n engineGcCursorOff: V12_1_SBF_OFF_GC_CURSOR,\n engineLastSweepStartOff: V12_1_SBF_OFF_LAST_SWEEP_START,\n engineLastSweepCompleteOff: V12_1_SBF_OFF_LAST_SWEEP_COMPLETE,\n engineCrankCursorOff: V12_1_SBF_OFF_CRANK_CURSOR,\n engineSweepStartIdxOff: V12_1_SBF_OFF_SWEEP_START_IDX,\n engineLifetimeLiquidationsOff: V12_1_SBF_OFF_LIFETIME_LIQUIDATIONS,\n engineLifetimeForceClosesOff: -1,\n engineNetLpPosOff: -1,\n engineLpSumAbsOff: -1,\n engineLpMaxAbsOff: -1,\n engineLpMaxAbsSweepOff: -1,\n engineEmergencyOiModeOff: -1,\n engineEmergencyStartSlotOff: -1,\n engineLastBreakerSlotOff: -1,\n engineBitmapOff: bitmapOff,\n postBitmap: 18,\n // Account offsets — shifted +8 from V12_1 due to entry_price insertion\n acctOwnerOff: V12_1_EP_ACCT_OWNER_OFF, // 216 (was 208)\n hasInsuranceIsolation: false,\n engineInsuranceIsolatedOff: -1,\n engineInsuranceIsolationBpsOff: -1,\n };\n}\n\n/**\n * Build a SlabLayout for V12_15 slabs (percolator v12.15 engine+prog sync).\n * ENGINE_OFF=624, ACCOUNT_SIZE=4400, BITMAP_OFF=862 (relative to engineOff).\n * Account layout: new reserve cohort arrays, entry_price re-added at offset 120,\n * warmupStartedAtSlot/warmupSlopePerStep/lastFeeSlot removed.\n *\n * @param maxAccounts - Number of account slots (256, 1024, 2048, or 4096)\n */\nfunction buildLayoutV12_15(maxAccounts: number, dataLen?: number): SlabLayout {\n // SBF has i128 align=8 (not 16), so ENGINE_OFF=616 (not 624) and params=184 (not 192).\n const isSbf = dataLen === 237512;\n const accountSize = isSbf ? V12_15_ACCOUNT_SIZE_SMALL : V12_15_ACCOUNT_SIZE;\n const engineOff = isSbf ? V12_15_ENGINE_OFF_SBF : V12_15_ENGINE_OFF;\n const bitmapOff = V12_15_ENGINE_BITMAP_OFF;\n // SBF small has different bitmap/accounts offsets due to u128 align=8\n const effectiveBitmapOff = isSbf ? 648 : bitmapOff; // SBF bitmap at engine+648 (verified on-chain)\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 18;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = effectiveBitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;\n\n return {\n version: 2,\n headerLen: V0_HEADER_LEN, // 72\n configOffset: V0_HEADER_LEN, // 72\n configLen: 552, // SBF CONFIG_LEN for v12.15\n reservedOff: V1_RESERVED_OFF, // 80\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: V12_15_ENGINE_PARAMS_OFF, // 32\n paramsSize: isSbf ? 184 : V12_15_PARAMS_SIZE, // SBF=184 (no trailing pad), native=192\n engineCurrentSlotOff: isSbf ? 216 : V12_15_ENGINE_CURRENT_SLOT_OFF, // SBF=216, native=224\n engineFundingIndexOff: -1, // not present in v12.15 engine struct\n engineLastFundingSlotOff: -1, // not present in v12.15 engine struct\n engineFundingRateBpsOff: isSbf ? 224 : V12_15_ENGINE_FUNDING_RATE_E9_OFF, // SBF=224, native=240\n engineMarkPriceOff: -1, // not present in v12.15\n engineLastCrankSlotOff: -1, // not yet mapped\n engineMaxCrankStalenessOff: -1, // not yet mapped\n engineTotalOiOff: -1, // not present in v12.15 engine\n engineLongOiOff: -1, // not present in v12.15 engine\n engineShortOiOff: -1, // not present in v12.15 engine\n engineCTotOff: isSbf ? 320 : V12_15_ENGINE_C_TOT_OFF, // SBF=320 (verified on-chain), native=344\n enginePnlPosTotOff: isSbf ? 336 : V12_15_ENGINE_PNL_POS_TOT_OFF, // SBF=336 (verified), native=368\n engineLiqCursorOff: -1, // not yet mapped\n engineGcCursorOff: -1, // not yet mapped\n engineLastSweepStartOff: -1, // not yet mapped\n engineLastSweepCompleteOff: -1, // not yet mapped\n engineCrankCursorOff: -1, // not yet mapped\n engineSweepStartIdxOff: -1, // not yet mapped\n engineLifetimeLiquidationsOff: -1, // not yet mapped\n engineLifetimeForceClosesOff: -1, // not present in v12.15\n engineNetLpPosOff: -1, // not present in v12.15\n engineLpSumAbsOff: -1, // not present in v12.15\n engineLpMaxAbsOff: -1, // not present in v12.15\n engineLpMaxAbsSweepOff: -1, // not present in v12.15\n engineEmergencyOiModeOff: -1, // not present in v12.15\n engineEmergencyStartSlotOff: -1, // not present in v12.15\n engineLastBreakerSlotOff: -1, // not present in v12.15\n engineBitmapOff: effectiveBitmapOff, // SBF=640, native=862\n postBitmap,\n acctOwnerOff: V12_15_ACCT_OWNER_OFF, // 192\n\n hasInsuranceIsolation: false,\n engineInsuranceIsolatedOff: -1,\n engineInsuranceIsolationBpsOff: -1,\n };\n}\n\n/**\n * Build a SlabLayout for V12_17 slabs (two-bucket warmup, per-side funding).\n * Account: 368 bytes (native) / 352 bytes (SBF). No cohort arrays, no account_id, no entry_price.\n * Engine: per-side cumulative funding (f_long_num/f_short_num), no stored funding_rate_e9.\n * postBitmap=4 (num_used_accounts: u16 + free_head: u16).\n * RISK_BUF_LEN=160 appended after engine.\n */\nfunction buildLayoutV12_17(maxAccounts: number, dataLen: number): SlabLayout {\n // Detect SBF vs native from account size and engine offset.\n // SBF: ACCOUNT_SIZE=352, ENGINE_OFF=504. Native: ACCOUNT_SIZE=368, ENGINE_OFF=512.\n const isSbf = (() => {\n // Compute expected native size for this tier\n const bitmapBytes = Math.ceil(maxAccounts / 64) * 8;\n const preAccNative = V12_17_ENGINE_BITMAP_OFF + bitmapBytes + 4 + maxAccounts * 2;\n const accountsOffNative = Math.ceil(preAccNative / 16) * 16;\n const nativeSize = V12_17_ENGINE_OFF + accountsOffNative + maxAccounts * V12_17_ACCOUNT_SIZE + V12_17_RISK_BUF_LEN + maxAccounts * V12_17_GEN_TABLE_ENTRY;\n return dataLen !== nativeSize;\n })();\n\n const engineOff = isSbf ? V12_17_ENGINE_OFF_SBF : V12_17_ENGINE_OFF;\n const accountSize = isSbf ? V12_17_ACCOUNT_SIZE_SBF : V12_17_ACCOUNT_SIZE;\n const bitmapOff = isSbf ? V12_17_ENGINE_BITMAP_OFF_SBF : V12_17_ENGINE_BITMAP_OFF;\n const bitmapWords = Math.ceil(maxAccounts / 64);\n const bitmapBytes = bitmapWords * 8;\n const postBitmap = 4;\n const nextFreeBytes = maxAccounts * 2;\n const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;\n const acctAlign = isSbf ? 8 : 16;\n const accountsOffRel = Math.ceil(preAccountsLen / acctAlign) * acctAlign;\n\n return {\n version: 2,\n headerLen: V0_HEADER_LEN, // 72\n configOffset: V0_HEADER_LEN, // 72\n // configLen = 512 (SBF-aligned MarketConfig size after Phase A/B/E).\n // Verified field-by-field against percolator-prog/src/percolator.rs MarketConfig struct.\n // Missing 80 bytes from prior value 432: max_pnl_cap, last_audit_pause_slot,\n // oi_cap_multiplier_bps, dispute_window_slots, dispute_bond_amount,\n // lp_collateral_enabled, lp_collateral_ltv_bps, _new_fields_pad, pending_admin.\n configLen: 512,\n reservedOff: V1_RESERVED_OFF, // 80\n engineOff,\n accountSize,\n maxAccounts,\n bitmapWords,\n accountsOff: engineOff + accountsOffRel,\n\n engineInsuranceOff: 16,\n engineParamsOff: V12_17_ENGINE_PARAMS_OFF, // 32\n paramsSize: isSbf ? 184 : 192,\n engineCurrentSlotOff: isSbf ? V12_17_SBF_ENGINE_CURRENT_SLOT_OFF : V12_17_ENGINE_CURRENT_SLOT_OFF,\n engineFundingIndexOff: -1, // replaced by per-side f_long_num/f_short_num\n engineLastFundingSlotOff: -1,\n engineFundingRateBpsOff: -1, // no stored funding rate in v12.17\n engineMarkPriceOff: -1, // v12.17 computes mark from state; no stored field\n engineLastCrankSlotOff: isSbf ? V12_17_SBF_ENGINE_LAST_CRANK_SLOT_OFF : V12_17_ENGINE_LAST_CRANK_SLOT_OFF,\n engineMaxCrankStalenessOff: -1,\n engineTotalOiOff: -1, // parseEngine sums long + short when total offset is -1\n engineLongOiOff: isSbf ? V12_17_SBF_ENGINE_OI_EFF_LONG_OFF : V12_17_ENGINE_OI_EFF_LONG_OFF,\n engineShortOiOff: isSbf ? V12_17_SBF_ENGINE_OI_EFF_SHORT_OFF : V12_17_ENGINE_OI_EFF_SHORT_OFF,\n engineCTotOff: isSbf ? V12_17_SBF_ENGINE_C_TOT_OFF : V12_17_ENGINE_C_TOT_OFF,\n enginePnlPosTotOff: isSbf ? V12_17_SBF_ENGINE_PNL_POS_TOT_OFF : V12_17_ENGINE_PNL_POS_TOT_OFF,\n engineLiqCursorOff: -1, // removed in v12.17\n engineGcCursorOff: isSbf ? V12_17_SBF_ENGINE_GC_CURSOR_OFF : V12_17_ENGINE_GC_CURSOR_OFF,\n engineLastSweepStartOff: -1,\n engineLastSweepCompleteOff: -1,\n engineCrankCursorOff: -1,\n engineSweepStartIdxOff: -1,\n engineLifetimeLiquidationsOff: -1,\n engineLifetimeForceClosesOff: -1,\n engineNetLpPosOff: -1,\n engineLpSumAbsOff: -1,\n engineLpMaxAbsOff: -1,\n engineLpMaxAbsSweepOff: -1,\n engineEmergencyOiModeOff: -1,\n engineEmergencyStartSlotOff: -1,\n engineLastBreakerSlotOff: -1,\n engineBitmapOff: bitmapOff,\n postBitmap,\n acctOwnerOff: isSbf ? 192 : V12_17_ACCT_OWNER_OFF, // SBF=192, native=200\n\n hasInsuranceIsolation: false,\n engineInsuranceIsolatedOff: -1,\n engineInsuranceIsolationBpsOff: -1,\n\n // v12.17 dropped the engine.mark_price field (see engineMarkPriceOff above).\n // The EWMA-smoothed mark that the matcher actually quotes against lives in\n // MarketConfig.mark_ewma_e6 at offset 304 within the config struct.\n // Layout is identical on SBF and native. configOffset is V0_HEADER_LEN = 72,\n // so absolute offset in the slab is 72 + 304 = 376.\n configMarkEwmaOff: V0_HEADER_LEN + 304,\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_15, V12_1_EP, 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_19 sizes first. Mainnet program ESa89R5... was upgraded to\n // v12.19 (--features small) on 2026-04-28; any slab created post-upgrade\n // is v12.19. Some sizes (94168) collide with V12_17 SBF small; the\n // deployed program only emits v12.19 going forward, so this priority\n // is correct for live mainnet reads.\n const v1219n = V12_19_SIZES.get(dataLen);\n if (v1219n !== undefined) return buildLayoutV12_19(v1219n, dataLen);\n\n // Check V12_17 sizes (two-bucket warmup, per-side funding).\n // Unique account sizes (368 native / 352 SBF) + RISK_BUF — no collision with V12_15 (4400-byte accounts).\n const v1217n = V12_17_SIZES.get(dataLen);\n if (v1217n !== undefined) return buildLayoutV12_17(v1217n, dataLen);\n\n // Check V12_15 sizes (v12.15 engine+prog sync, ACCOUNT_SIZE=4400).\n // Vastly larger account size — no collision with any earlier layout possible.\n const v1215n = V12_15_SIZES.get(dataLen);\n if (v1215n !== undefined) return buildLayoutV12_15(v1215n, dataLen);\n\n // Check V12_1_EP sizes (entry_price re-added, ACCOUNT_SIZE=288 on SBF).\n // Must be checked before V12_1 (280-byte accounts) to avoid misdetection.\n const v121epn = V12_1_EP_SIZES.get(dataLen);\n if (v121epn !== undefined) return buildLayoutV12_1EP(v121epn);\n\n // Check V12_1 sizes (percolator-core v12.1, ACCOUNT_SIZE=320/280, no entry_price).\n const v121n = V12_1_SIZES.get(dataLen);\n if (v121n !== undefined) return buildLayoutV12_1(v121n, dataLen);\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+) — legacy offsets (V0/V1/V1D layouts with\n// riskReductionThreshold and liquidationBufferBps fields).\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// V12_1 SBF params offsets — deployed struct has NO riskReductionThreshold or\n// liquidationBufferBps. Instead: maintenance_fee_per_slot follows new_account_fee\n// directly, and min_initial_deposit/min_nonzero_mm_req/min_nonzero_im_req/insurance_floor\n// are appended at the end. Verified via cargo build-sbf offset_of! assertions.\nconst V12_1_PARAMS_MAINT_FEE_OFF = 56; // U128\nconst V12_1_PARAMS_MAX_CRANK_OFF = 72; // u64\nconst V12_1_PARAMS_LIQ_FEE_BPS_OFF = 80; // u64\nconst V12_1_PARAMS_LIQ_FEE_CAP_OFF = 88; // U128\nconst V12_1_PARAMS_MIN_LIQ_OFF = 104; // U128\nconst V12_1_PARAMS_MIN_INITIAL_DEP_OFF = 120; // U128\nconst V12_1_PARAMS_MIN_NZ_MM_OFF = 136; // u128\nconst V12_1_PARAMS_MIN_NZ_IM_OFF = 152; // u128\nconst V12_1_PARAMS_INS_FLOOR_OFF = 168; // U128\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 /** @deprecated Removed in V12_1 — always 0 */ fundingPremiumWeightBps: bigint;\n /** @deprecated Removed in V12_1 — always 0 */ fundingSettlementIntervalSlots: bigint;\n /** @deprecated Removed in V12_1 — always 0 */ fundingPremiumDampeningE6: bigint;\n /** @deprecated Removed in V12_1 — always 0 */ 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 /**\n * @deprecated Split into hMin/hMax in v12.15 RiskParams. On V12_15 slabs this field returns\n * hMin for backwards compatibility. On pre-v12.15 slabs hMin/hMax both mirror this value.\n */\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 /** Minimum initial deposit to open an account (V12_1+ only) */\n minInitialDeposit: bigint;\n /** Minimum nonzero maintenance margin requirement (V12_1+ only) */\n minNonzeroMmReq: bigint;\n /** Minimum nonzero initial margin requirement (V12_1+ only) */\n minNonzeroImReq: bigint;\n /** Insurance fund floor (V12_1+ only) */\n insuranceFloor: bigint;\n /** Minimum horizon slots (v12.15+). Replaces warmupPeriodSlots. 0n on pre-v12.15 slabs. */\n hMin: bigint;\n /** Maximum horizon slots (v12.15+). 0n on pre-v12.15 slabs. */\n hMax: bigint;\n}\n\nexport interface EngineState {\n vault: bigint;\n insuranceFund: InsuranceFund;\n currentSlot: bigint;\n fundingIndexQpbE6: bigint;\n lastFundingSlot: bigint;\n /**\n * Funding rate per slot. On pre-v12.15 slabs: i64 in BPS units.\n * On v12.15+ slabs: i128 in e9 units (field renamed `funding_rate_e9` on-chain).\n */\n fundingRateBpsPerSlotLast: bigint;\n /**\n * Funding rate in e9 units (i128). v12.15+ only.\n * 0n on pre-v12.15 slabs.\n */\n fundingRateE9: bigint;\n /**\n * Market mode. v12.15+ only. 0 = Live, 1 = Resolved. null on pre-v12.15 slabs.\n */\n marketMode: 0 | 1 | null;\n lastCrankSlot: bigint;\n maxCrankStalenessSlots: bigint;\n totalOpenInterest: bigint;\n longOi: bigint;\n shortOi: bigint;\n cTot: bigint;\n pnlPosTot: bigint;\n /**\n * Matured (settled) positive PnL total (u128). v12.15+ only. 0n on pre-v12.15 slabs.\n */\n pnlMaturedPosTot: 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 /** last_oracle_price (u64, e6). V12_15+ only. 0n on pre-v12.15. */\n oraclePriceE6: bigint;\n\n // ---- V12_17 engine fields ----\n /** Cumulative funding numerator for long side (i128). 0n on pre-v12.17. */\n fLongNum: bigint;\n /** Cumulative funding numerator for short side (i128). 0n on pre-v12.17. */\n fShortNum: bigint;\n /** Count of accounts with negative PnL. 0n on pre-v12.17. */\n negPnlAccountCount: bigint;\n /** Last funding-sample price (u64 e6). 0n on pre-v12.17. */\n fundPxLast: bigint;\n /** Matured positive PnL total (u128). v12.15+ only. 0n on pre-v12.15 slabs. */\n resolvedKLongTerminalDelta: bigint;\n /** Terminal K delta for short side (i128). 0n on pre-v12.17. */\n resolvedKShortTerminalDelta: bigint;\n /** Live oracle price used during resolution (u64 e6). 0n on pre-v12.17. */\n resolvedLivePrice: bigint;\n}\n\nexport enum AccountKind {\n User = 0,\n LP = 1,\n}\n\n/** Parsed reserve cohort (64 bytes on-chain). Raw bytes; structure is program-internal. */\nexport type ReserveCohortBytes = Uint8Array;\n\nexport interface Account {\n kind: AccountKind;\n accountId: bigint;\n capital: bigint;\n pnl: bigint;\n reservedPnl: bigint;\n /** @deprecated Removed in v12.15. Always 0n on V12_15 slabs. */\n warmupStartedAtSlot: bigint;\n /** @deprecated Removed in v12.15. Always 0n on V12_15 slabs. */\n warmupSlopePerStep: bigint;\n positionSize: bigint;\n /** Entry price in e6 units. Present in V12_15 (offset 120) and V_ADL/V12_1_EP. -1 signals absent. */\n entryPrice: bigint;\n fundingIndex: bigint;\n matcherProgram: PublicKey;\n matcherContext: PublicKey;\n owner: PublicKey;\n feeCredits: bigint;\n /** @deprecated Removed in v12.15. Always 0n on V12_15 slabs. */\n lastFeeSlot: bigint;\n /** Total fees earned over account lifetime (u128). Present from v12.15. 0n on older layouts. */\n feesEarnedTotal: bigint;\n /**\n * Reserve cohorts array (v12.15+). Up to 62 cohorts of 64 bytes each.\n * `null` on pre-v12.15 slabs. Parse the raw bytes according to the on-chain ReserveCohort struct.\n */\n exactReserveCohorts: ReserveCohortBytes[] | null;\n /** Number of active reserve cohorts (0-62). null on pre-v12.15 slabs. */\n exactCohortCount: number | null;\n /** Overflow (oldest) cohort raw bytes. null on pre-v12.15 slabs or when not present. */\n overflowOlder: ReserveCohortBytes | null;\n /** True if overflowOlder contains valid data. null on pre-v12.15 slabs. */\n overflowOlderPresent: boolean | null;\n /** Overflow (newest) cohort raw bytes. null on pre-v12.15 slabs or when not present. */\n overflowNewest: ReserveCohortBytes | null;\n /** True if overflowNewest contains valid data. null on pre-v12.15 slabs. */\n overflowNewestPresent: boolean | null;\n\n // ---- V12_17 fields (two-bucket warmup, per-side funding) ----\n /** Per-account cumulative funding snapshot (i128). 0n on pre-v12.17 slabs. */\n fSnap: bigint;\n /** ADL A-basis snapshot (u128). 0n on pre-v12.17 slabs. */\n adlABasis: bigint;\n /** ADL K-coefficient snapshot (i128). 0n on pre-v12.17 slabs. */\n adlKSnap: bigint;\n /** ADL epoch snapshot (u64). 0n on pre-v12.17 slabs. */\n adlEpochSnap: bigint;\n\n // Scheduled reserve bucket (older, matures linearly)\n /** True if the scheduled warmup bucket is active. null on pre-v12.17. */\n schedPresent: boolean | null;\n /** Remaining unreleased quantity in scheduled bucket. null on pre-v12.17. */\n schedRemainingQ: bigint | null;\n /** Anchor quantity for scheduled bucket. null on pre-v12.17. */\n schedAnchorQ: bigint | null;\n /** Start slot for scheduled bucket. null on pre-v12.17. */\n schedStartSlot: bigint | null;\n /** Warmup horizon for scheduled bucket. null on pre-v12.17. */\n schedHorizon: bigint | null;\n /** Release quantity for scheduled bucket. null on pre-v12.17. */\n schedReleaseQ: bigint | null;\n\n // Pending reserve bucket (newest, does not mature while pending)\n /** True if the pending warmup bucket is active. null on pre-v12.17. */\n pendingPresent: boolean | null;\n /** Remaining unreleased quantity in pending bucket. null on pre-v12.17. */\n pendingRemainingQ: bigint | null;\n /** Warmup horizon for pending bucket. null on pre-v12.17. */\n pendingHorizon: bigint | null;\n /** Creation slot for pending bucket. null on pre-v12.17. */\n pendingCreatedSlot: bigint | null;\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 */\n/**\n * V12_17 MarketConfig parser. Struct definition: percolator-prog/src/percolator.rs:2194.\n * SBF layout (u128 align=8, total size 512 bytes):\n * 0 collateral_mint [32]\n * 32 vault_pubkey [32]\n * 64 index_feed_id [32]\n * 96 max_staleness_secs u64\n * 104 conf_filter_bps u16\n * 106 vault_authority_bump u8\n * 107 invert u8\n * 108 unit_scale u32\n * 112 funding_horizon_slots u64\n * 120 funding_k_bps u64\n * 128 funding_max_premium_bps i64\n * 136 funding_max_bps_per_slot i64\n * 144 oracle_authority [32]\n * 176 authority_price_e6 u64\n * 184 authority_timestamp i64\n * 192 oracle_price_cap_e2bps u64\n * 200 last_effective_price_e6 u64\n * 208 max_insurance_floor u128\n * 224 min_oracle_price_cap_e2bps u64\n * 232 insurance_withdraw_max_bps u16 (+ 6 pad)\n * 240 insurance_withdraw_cooldown_slots u64\n * 248 _iw_padding2 [u64;2]\n * 264 last_hyperp_index_slot u64\n * 272 last_mark_push_slot u128\n * 288 last_insurance_withdraw_slot u64 (+ 8 pad)\n * 304 mark_ewma_e6 u64\n * 312 mark_ewma_last_slot u64\n * 320 mark_ewma_halflife_slots u64 (+ 8 pad)\n * 336 permissionless_resolve_stale_slots u64\n * 344 last_good_oracle_slot u64\n * 352 maintenance_fee_per_slot u128\n * 368 last_fee_charge_slot u64 (+ 8 pad)\n * 384 mark_min_fee u64\n * 392 force_close_delay_slots u64\n * 400 dex_pool [32]\n * 432 max_pnl_cap u64\n * 440 last_audit_pause_slot u64\n * 448 oi_cap_multiplier_bps u64\n * 456 dispute_window_slots u64\n * 464 dispute_bond_amount u64\n * 472 lp_collateral_enabled u8\n * 473 _pad u8\n * 474 lp_collateral_ltv_bps u16 (+ 4 pad)\n * 480 pending_admin [32]\n * 512 end\n */\nfunction parseConfigV12_17(data: Uint8Array, configOff: number): MarketConfig {\n const MIN_V12_17_BYTES = 512;\n if (data.length < configOff + MIN_V12_17_BYTES) {\n throw new Error(`Slab data too short for V12_17 config: ${data.length} < ${configOff + MIN_V12_17_BYTES}`);\n }\n\n const b = configOff;\n const collateralMint = new PublicKey(data.subarray(b + 0, b + 32));\n const vaultPubkey = new PublicKey(data.subarray(b + 32, b + 64));\n const indexFeedId = new PublicKey(data.subarray(b + 64, b + 96));\n const maxStalenessSlots = readU64LE(data, b + 96);\n const confFilterBps = readU16LE(data, b + 104);\n const vaultAuthorityBump = readU8(data, b + 106);\n const invert = readU8(data, b + 107);\n const unitScale = readU32LE(data, b + 108);\n const fundingHorizonSlots = readU64LE(data, b + 112);\n const fundingKBps = readU64LE(data, b + 120);\n const fundingMaxPremiumBps = readI64LE(data, b + 128);\n const fundingMaxBpsPerSlot = readI64LE(data, b + 136);\n const oracleAuthority = new PublicKey(data.subarray(b + 144, b + 176));\n const authorityPriceE6 = readU64LE(data, b + 176);\n const authorityTimestamp = readI64LE(data, b + 184);\n const oraclePriceCapE2bps = readU64LE(data, b + 192);\n const lastEffectivePriceE6 = readU64LE(data, b + 200);\n // max_insurance_floor, min_oracle_price_cap, mark_ewma, dispute, etc. — not\n // currently surfaced by the MarketConfig type; read them when/if callers\n // need them. Only dex_pool is consumed downstream.\n\n const dexPoolBytes = data.subarray(b + 400, b + 432);\n const dexPool = dexPoolBytes.some(x => x !== 0) ? new PublicKey(dexPoolBytes) : null;\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: 0n, // removed in v12.17\n fundingMaxPremiumBps,\n fundingMaxBpsPerSlot,\n fundingPremiumWeightBps: 0n,\n fundingSettlementIntervalSlots: 0n,\n fundingPremiumDampeningE6: 0n,\n fundingPremiumMaxBpsPerSlot: 0n,\n threshFloor: 0n, // removed in v12.17\n threshRiskBps: 0n,\n threshUpdateIntervalSlots: 0n,\n threshStepBps: 0n,\n threshAlphaBps: 0n,\n threshMin: 0n,\n threshMax: 0n,\n threshMinStep: 0n,\n oracleAuthority,\n authorityPriceE6,\n authorityTimestamp,\n oraclePriceCapE2bps,\n lastEffectivePriceE6,\n oiCapMultiplierBps: readU64LE(data, b + 448),\n maxPnlCap: readU64LE(data, b + 432),\n adaptiveFundingEnabled: false, // removed in v12.17\n adaptiveScaleBps: 0,\n adaptiveMaxFundingBps: 0n,\n marketCreatedSlot: 0n,\n oiRampSlots: 0n,\n resolvedSlot: 0n,\n insuranceIsolationBps: 0,\n oraclePhase: 0,\n cumulativeVolumeE6: 0n,\n phase2DeltaSlots: 0,\n dexPool,\n };\n}\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 // V12_17 MarketConfig has a completely different layout — no funding_inv_scale,\n // no thresh_* fields. Parse it via its own field-ordered reader. The legacy\n // sequential code below covers pre-v12.17 layouts.\n const isV12_17 = layout && (layout.accountSize === V12_17_ACCOUNT_SIZE || layout.accountSize === V12_17_ACCOUNT_SIZE_SBF);\n if (isV12_17) {\n return parseConfigV12_17(data, configOff);\n }\n\n // Mandatory config fields (collateralMint..maxPnlCap) consume 376 bytes.\n // V1 extended fields are optional and guarded by their own `remaining` checks.\n const MIN_CONFIG_BYTES = 376;\n const minLen = configOff + Math.min(configLen, MIN_CONFIG_BYTES);\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 // NOTE: Extended funding fields (fundingPremiumWeightBps, fundingSettlementIntervalSlots,\n // fundingPremiumDampeningE6, fundingPremiumMaxBpsPerSlot) were removed in V12_1 upstream\n // rebase. They do NOT exist in the on-chain MarketConfig struct. Reading them here shifted\n // all subsequent fields by 32 bytes, causing oracle_authority to read garbage.\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: 0n,\n fundingSettlementIntervalSlots: 0n,\n fundingPremiumDampeningE6: 0n,\n fundingPremiumMaxBpsPerSlot: 0n,\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 // Validate we have enough data for the fields we'll actually read.\n // V0 basic params need 56 bytes; V1 extended params need 144 bytes.\n const MIN_PARAMS_BYTES = paramsSize >= 144 ? 144 : 56;\n if (data.length < base + MIN_PARAMS_BYTES) {\n throw new Error(`Slab data too short for RiskParams: ${data.length} < ${base + MIN_PARAMS_BYTES}`);\n }\n\n // Detect V12_15 layout: paramsSize=192. In v12.15, warmup_period_slots is replaced by\n // h_min(u64@160) + h_max(u64@168). max_accounts moved to offset 24 (from 32).\n const isV12_15Params = paramsSize === V12_15_PARAMS_SIZE || paramsSize === 184; // 192=native, 184=SBF\n\n // Detect V12_1 SBF layout — deployed struct has different field order from legacy layouts.\n // V12_1 SBF: no riskReductionThreshold/liquidationBufferBps; adds minInitialDeposit/\n // minNonzeroMmReq/minNonzeroImReq/insuranceFloor at the end.\n const isV12_1Sbf = !isV12_15Params && layout !== null && layout !== undefined &&\n (layout.engineOff === V12_1_SBF_ENGINE_OFF) && paramsSize === 184;\n\n // Basic params present in all layouts (offsets 0-55 are identical)\n const result: RiskParams = {\n warmupPeriodSlots: isV12_15Params\n ? readU64LE(data, base + V12_15_PARAMS_H_MIN_OFF) // backwards compat: return hMin\n : readU64LE(data, base + PARAMS_WARMUP_PERIOD_OFF),\n maintenanceMarginBps: isV12_15Params\n ? readU64LE(data, base + 0) // v12.15: mm_bps is first field (offset 0)\n : readU64LE(data, base + PARAMS_MAINTENANCE_MARGIN_OFF),\n initialMarginBps: isV12_15Params\n ? readU64LE(data, base + 8)\n : readU64LE(data, base + PARAMS_INITIAL_MARGIN_OFF),\n tradingFeeBps: isV12_15Params\n ? readU64LE(data, base + 16)\n : readU64LE(data, base + PARAMS_TRADING_FEE_OFF),\n maxAccounts: isV12_15Params\n ? readU64LE(data, base + V12_15_PARAMS_MAX_ACCOUNTS_OFF) // offset 24 in v12.15\n : readU64LE(data, base + PARAMS_MAX_ACCOUNTS_OFF),\n newAccountFee: isV12_15Params\n ? readU128LE(data, base + 32) // offset 32 in v12.15\n : readU128LE(data, base + PARAMS_NEW_ACCOUNT_FEE_OFF),\n // Extended params: defaults; overwritten below if layout supports them\n riskReductionThreshold: 0n,\n maintenanceFeePerSlot: 0n,\n maxCrankStalenessSlots: 0n,\n liquidationFeeBps: 0n,\n liquidationFeeCap: 0n,\n liquidationBufferBps: 0n,\n minLiquidationAbs: 0n,\n minInitialDeposit: 0n,\n minNonzeroMmReq: 0n,\n minNonzeroImReq: 0n,\n insuranceFloor: 0n,\n hMin: 0n,\n hMax: 0n,\n };\n\n if (isV12_15Params) {\n // V12_15 RiskParams: read hMin/hMax, insurance_floor occupies offset 144.\n result.hMin = readU64LE(data, base + V12_15_PARAMS_H_MIN_OFF);\n result.hMax = readU64LE(data, base + V12_15_PARAMS_H_MAX_OFF);\n result.insuranceFloor = readU128LE(data, base + V12_15_PARAMS_INSURANCE_FLOOR_OFF);\n // v12.15 RiskParams: no riskReductionThreshold, no maintenanceFeePerSlot.\n // All offsets shift -8 from legacy (warmupPeriodSlots removed from start).\n result.riskReductionThreshold = 0n; // removed in v12.15\n result.maintenanceFeePerSlot = 0n; // removed in v12.15\n // v12.15 RiskParams offsets (same on native and SBF — no i128 fields in RiskParams)\n result.maxCrankStalenessSlots = readU64LE(data, base + 48);\n result.liquidationFeeBps = readU64LE(data, base + 56);\n result.liquidationFeeCap = readU128LE(data, base + 64);\n result.liquidationBufferBps = 0n; // removed (wire slot reused as resolve_price_deviation_bps)\n result.minLiquidationAbs = readU128LE(data, base + 80);\n result.minInitialDeposit = readU128LE(data, base + 96);\n result.minNonzeroMmReq = readU128LE(data, base + 112);\n result.minNonzeroImReq = readU128LE(data, base + 128);\n } else if (isV12_1Sbf) {\n // V12_1 SBF deployed struct — no riskReductionThreshold/liquidationBufferBps\n result.maintenanceFeePerSlot = readU128LE(data, base + V12_1_PARAMS_MAINT_FEE_OFF);\n result.maxCrankStalenessSlots = readU64LE(data, base + V12_1_PARAMS_MAX_CRANK_OFF);\n result.liquidationFeeBps = readU64LE(data, base + V12_1_PARAMS_LIQ_FEE_BPS_OFF);\n result.liquidationFeeCap = readU128LE(data, base + V12_1_PARAMS_LIQ_FEE_CAP_OFF);\n result.minLiquidationAbs = readU128LE(data, base + V12_1_PARAMS_MIN_LIQ_OFF);\n result.minInitialDeposit = readU128LE(data, base + V12_1_PARAMS_MIN_INITIAL_DEP_OFF);\n result.minNonzeroMmReq = readU128LE(data, base + V12_1_PARAMS_MIN_NZ_MM_OFF);\n result.minNonzeroImReq = readU128LE(data, base + V12_1_PARAMS_MIN_NZ_IM_OFF);\n result.insuranceFloor = readU128LE(data, base + V12_1_PARAMS_INS_FLOOR_OFF);\n // hMin/hMax: backfill from warmupPeriodSlots for pre-v12.15 callers\n result.hMin = result.warmupPeriodSlots;\n result.hMax = result.warmupPeriodSlots;\n } else if (paramsSize >= 144) {\n // Legacy V0/V1/V1D layouts with riskReductionThreshold + liquidationBufferBps\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 // hMin/hMax: backfill from warmupPeriodSlots for pre-v12.15 callers\n result.hMin = result.warmupPeriodSlots;\n result.hMax = result.warmupPeriodSlots;\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 // Detect layout versions\n const isV12_17 = layout.accountSize === V12_17_ACCOUNT_SIZE || layout.accountSize === V12_17_ACCOUNT_SIZE_SBF;\n const isV12_15 = !isV12_17 && (layout.accountSize === V12_15_ACCOUNT_SIZE || layout.accountSize === V12_15_ACCOUNT_SIZE_SMALL) && (layout.engineOff === V12_15_ENGINE_OFF || layout.engineOff === V12_15_ENGINE_OFF_SBF);\n\n // V12_17: completely new engine layout — per-side funding, no stored funding_rate_e9.\n // V12_19 uses the same engine struct as V12_17 SBF, just with engineOff\n // shifted +16 (configLen 528 vs 512). Treat both 584 and 600 as SBF.\n if (isV12_17) {\n const isSbf = layout.engineOff === V12_17_ENGINE_OFF_SBF || layout.engineOff === V12_19_ENGINE_OFF_SBF;\n\n const currentSlotOff = isSbf ? V12_17_SBF_ENGINE_CURRENT_SLOT_OFF : V12_17_ENGINE_CURRENT_SLOT_OFF;\n const marketModeOff = isSbf ? V12_17_SBF_ENGINE_MARKET_MODE_OFF : V12_17_ENGINE_MARKET_MODE_OFF;\n const cTotOff = isSbf ? V12_17_SBF_ENGINE_C_TOT_OFF : V12_17_ENGINE_C_TOT_OFF;\n const pnlPosTotOff = isSbf ? V12_17_SBF_ENGINE_PNL_POS_TOT_OFF : V12_17_ENGINE_PNL_POS_TOT_OFF;\n const pnlMaturedOff = isSbf ? V12_17_SBF_ENGINE_PNL_MATURED_POS_TOT_OFF : V12_17_ENGINE_PNL_MATURED_POS_TOT_OFF;\n const negPnlOff = isSbf ? V12_17_SBF_ENGINE_NEG_PNL_COUNT_OFF : V12_17_ENGINE_NEG_PNL_COUNT_OFF;\n const oraclePriceOff = isSbf ? V12_17_SBF_ENGINE_LAST_ORACLE_PRICE_OFF : V12_17_ENGINE_LAST_ORACLE_PRICE_OFF;\n const fundPxLastOff = isSbf ? V12_17_SBF_ENGINE_FUND_PX_LAST_OFF : V12_17_ENGINE_FUND_PX_LAST_OFF;\n const fLongNumOff = isSbf ? V12_17_SBF_ENGINE_F_LONG_NUM_OFF : V12_17_ENGINE_F_LONG_NUM_OFF;\n const fShortNumOff = isSbf ? V12_17_SBF_ENGINE_F_SHORT_NUM_OFF : V12_17_ENGINE_F_SHORT_NUM_OFF;\n // resolved_k offsets: native 304/320, SBF 288/304\n const resolvedKLongOff = isSbf ? 288 : V12_17_ENGINE_RESOLVED_K_LONG_OFF;\n const resolvedKShortOff = isSbf ? 304 : V12_17_ENGINE_RESOLVED_K_SHORT_OFF;\n const resolvedLivePriceOff = isSbf ? 320 : V12_17_ENGINE_RESOLVED_LIVE_PRICE_OFF;\n const lastCrankSlotOff = isSbf ? V12_17_SBF_ENGINE_LAST_CRANK_SLOT_OFF : V12_17_ENGINE_LAST_CRANK_SLOT_OFF;\n const gcCursorOff = isSbf ? V12_17_SBF_ENGINE_GC_CURSOR_OFF : V12_17_ENGINE_GC_CURSOR_OFF;\n const oiEffLongOff = isSbf ? V12_17_SBF_ENGINE_OI_EFF_LONG_OFF : V12_17_ENGINE_OI_EFF_LONG_OFF;\n const oiEffShortOff = isSbf ? V12_17_SBF_ENGINE_OI_EFF_SHORT_OFF : V12_17_ENGINE_OI_EFF_SHORT_OFF;\n\n const longOi = readU128LE(data, base + oiEffLongOff);\n const shortOi = readU128LE(data, base + oiEffShortOff);\n\n // numUsedAccounts: at bitmap + bitmapBytes (postBitmap=4: num_used_accounts is first u16)\n const bitmapEnd = layout.engineBitmapOff + layout.bitmapWords * 8;\n\n return {\n vault: readU128LE(data, base),\n insuranceFund: {\n balance: readU128LE(data, base + 16),\n feeRevenue: 0n,\n isolatedBalance: 0n,\n isolationBps: 0,\n },\n currentSlot: readU64LE(data, base + currentSlotOff),\n fundingIndexQpbE6: 0n, // replaced by per-side funding\n lastFundingSlot: 0n,\n fundingRateBpsPerSlotLast: 0n, // no stored funding rate in v12.17\n fundingRateE9: 0n, // no stored funding rate in v12.17\n marketMode: readU8(data, base + marketModeOff) === 1 ? 1 : 0,\n lastCrankSlot: readU64LE(data, base + lastCrankSlotOff),\n maxCrankStalenessSlots: 0n,\n totalOpenInterest: longOi + shortOi,\n longOi,\n shortOi,\n cTot: readU128LE(data, base + cTotOff),\n pnlPosTot: readU128LE(data, base + pnlPosTotOff),\n pnlMaturedPosTot: readU128LE(data, base + pnlMaturedOff),\n liqCursor: 0,\n gcCursor: readU16LE(data, base + gcCursorOff),\n lastSweepStartSlot: 0n,\n lastSweepCompleteSlot: 0n,\n crankCursor: 0,\n sweepStartIdx: 0,\n lifetimeLiquidations: 0n,\n lifetimeForceCloses: 0n,\n netLpPos: 0n,\n lpSumAbs: 0n,\n lpMaxAbs: 0n,\n lpMaxAbsSweep: 0n,\n emergencyOiMode: false,\n emergencyStartSlot: 0n,\n lastBreakerSlot: 0n,\n markPriceE6: 0n,\n oraclePriceE6: readU64LE(data, base + oraclePriceOff),\n numUsedAccounts: readU16LE(data, base + bitmapEnd),\n nextAccountId: 0n, // removed in v12.17 (replaced by mat_counter in header)\n\n // V12_17 fields\n fLongNum: readI128LE(data, base + fLongNumOff),\n fShortNum: readI128LE(data, base + fShortNumOff),\n negPnlAccountCount: readU64LE(data, base + negPnlOff),\n fundPxLast: readU64LE(data, base + fundPxLastOff),\n resolvedKLongTerminalDelta: readI128LE(data, base + resolvedKLongOff),\n resolvedKShortTerminalDelta: readI128LE(data, base + resolvedKShortOff),\n resolvedLivePrice: readU64LE(data, base + resolvedLivePriceOff),\n };\n }\n\n // For v12.15: funding_rate_e9 is i128 at layout.engineFundingRateBpsOff (224 SBF, 240 native).\n // For pre-v12.15: i64 at engineFundingRateBpsOff.\n const fundingRateBpsPerSlotLast = isV12_15\n ? readI128LE(data, base + layout.engineFundingRateBpsOff)\n : readI64LE(data, base + layout.engineFundingRateBpsOff);\n\n return {\n vault: readU128LE(data, base),\n insuranceFund: {\n balance: readU128LE(data, base + layout.engineInsuranceOff),\n // feeRevenue: only exists in percolator-core (80-byte InsuranceFund), not deployed (16-byte)\n feeRevenue: layout.hasInsuranceIsolation\n ? readU128LE(data, base + layout.engineInsuranceOff + 16)\n : 0n,\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: layout.engineFundingIndexOff >= 0\n ? readI128LE(data, base + layout.engineFundingIndexOff) : 0n,\n lastFundingSlot: layout.engineLastFundingSlotOff >= 0\n ? readU64LE(data, base + layout.engineLastFundingSlotOff) : 0n,\n fundingRateBpsPerSlotLast,\n fundingRateE9: isV12_15\n ? readI128LE(data, base + layout.engineFundingRateBpsOff)\n : 0n,\n marketMode: isV12_15\n ? (readU8(data, base + layout.engineFundingRateBpsOff + 16) === 1 ? 1 : 0)\n : null,\n lastCrankSlot: layout.engineLastCrankSlotOff >= 0\n ? readU64LE(data, base + layout.engineLastCrankSlotOff) : 0n,\n maxCrankStalenessSlots: layout.engineMaxCrankStalenessOff >= 0\n ? readU64LE(data, base + layout.engineMaxCrankStalenessOff) : 0n,\n totalOpenInterest: layout.engineTotalOiOff >= 0\n ? readU128LE(data, base + layout.engineTotalOiOff) : 0n,\n longOi: layout.engineLongOiOff >= 0\n ? readU128LE(data, base + layout.engineLongOiOff) : 0n,\n shortOi: layout.engineShortOiOff >= 0\n ? readU128LE(data, base + layout.engineShortOiOff) : 0n,\n cTot: readU128LE(data, base + layout.engineCTotOff),\n pnlPosTot: readU128LE(data, base + layout.enginePnlPosTotOff),\n pnlMaturedPosTot: isV12_15\n ? readU128LE(data, base + V12_15_ENGINE_PNL_MATURED_POS_TOT_OFF)\n : 0n,\n liqCursor: layout.engineLiqCursorOff >= 0\n ? readU16LE(data, base + layout.engineLiqCursorOff) : 0,\n gcCursor: layout.engineGcCursorOff >= 0\n ? readU16LE(data, base + layout.engineGcCursorOff) : 0,\n lastSweepStartSlot: layout.engineLastSweepStartOff >= 0\n ? readU64LE(data, base + layout.engineLastSweepStartOff) : 0n,\n lastSweepCompleteSlot: layout.engineLastSweepCompleteOff >= 0\n ? readU64LE(data, base + layout.engineLastSweepCompleteOff) : 0n,\n crankCursor: layout.engineCrankCursorOff >= 0\n ? readU16LE(data, base + layout.engineCrankCursorOff) : 0,\n sweepStartIdx: layout.engineSweepStartIdxOff >= 0\n ? readU16LE(data, base + layout.engineSweepStartIdxOff) : 0,\n lifetimeLiquidations: layout.engineLifetimeLiquidationsOff >= 0\n ? readU64LE(data, base + layout.engineLifetimeLiquidationsOff) : 0n,\n lifetimeForceCloses: layout.engineLifetimeForceClosesOff >= 0\n ? readU64LE(data, base + layout.engineLifetimeForceClosesOff) : 0n,\n netLpPos: layout.engineNetLpPosOff >= 0\n ? readI128LE(data, base + layout.engineNetLpPosOff) : 0n,\n lpSumAbs: layout.engineLpSumAbsOff >= 0\n ? readU128LE(data, base + layout.engineLpSumAbsOff) : 0n,\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) : 0n,\n lastBreakerSlot: layout.engineLastBreakerSlotOff >= 0\n ? readU64LE(data, base + layout.engineLastBreakerSlotOff) : 0n,\n markPriceE6: layout.engineMarkPriceOff >= 0\n ? readU64LE(data, base + layout.engineMarkPriceOff) : 0n,\n // V12_15: last_oracle_price at engine+608 (SBF) / engine+... (native).\n // Located at bitmapOff - 40 on SBF (648-40=608, verified on-chain).\n oraclePriceE6: isV12_15\n ? readU64LE(data, base + layout.engineBitmapOff - 40)\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 // V12_17 fields (not present in pre-v12.17)\n fLongNum: 0n,\n fShortNum: 0n,\n negPnlAccountCount: 0n,\n fundPxLast: 0n,\n resolvedKLongTerminalDelta: 0n,\n resolvedKShortTerminalDelta: 0n,\n resolvedLivePrice: 0n,\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_15 (account_size=4400): completely new layout, reserve cohorts, warmup/lastFeeSlot removed.\n // V12_1 (account_size=320/280): 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 // V12_1: engineOff=648 + bitmapOff(rel)=368. Detect by engineOff (most reliable).\n // Account is 320 on aarch64, 280 on SBF — accountSize alone is ambiguous.\n // V12_1_EP: entry_price re-added, accountSize=288 on SBF. All offsets after entry_price shift +8.\n const isV12_17 = layout.accountSize === V12_17_ACCOUNT_SIZE || layout.accountSize === V12_17_ACCOUNT_SIZE_SBF;\n const isV12_15 = !isV12_17 && (layout.accountSize === V12_15_ACCOUNT_SIZE || layout.accountSize === V12_15_ACCOUNT_SIZE_SMALL);\n const isV12_1EP = !isV12_17 && !isV12_15 && layout.accountSize === V12_1_EP_SBF_ACCOUNT_SIZE && layout.engineOff === V12_1_SBF_ENGINE_OFF;\n const isV12_1 = !isV12_17 && !isV12_15 && !isV12_1EP && (layout.engineOff === V12_1_ENGINE_OFF || layout.engineOff === V12_1_SBF_ENGINE_OFF) && (layout.accountSize === V12_1_ACCOUNT_SIZE || layout.accountSize === V12_1_ACCOUNT_SIZE_SBF);\n const isAdl = !isV12_17 && !isV12_15 && (layout.accountSize >= 312 || isV12_1 || isV12_1EP);\n\n if (isV12_17) {\n // V12_17 fast path: two-bucket warmup, per-side funding, no account_id/entry_price/cohorts.\n //\n // SBF vs native alignment delta:\n // After `kind: u8`, native i128 (align=16) inserts 15 bytes pad vs SBF (align=8) 7 bytes → d1=8.\n // After `pending_present: u8`, the same happens again: native pads 15 vs SBF 7 → d2=16.\n // The first gap (after sched_present) does NOT add extra delta because sched_present lands at\n // native offset 248 where (249 % 16 = 9) needs only 7 bytes — same as SBF. But pending_present\n // lands at native 320 where (321 % 16 = 1) needs 15 bytes vs SBF's 7.\n const isSbf = layout.accountSize === V12_17_ACCOUNT_SIZE_SBF;\n const d1 = isSbf ? 8 : 0; // fields after kind through pending_present\n const d2 = isSbf ? 16 : 0; // fields after pending_present (pending_remaining_q onward)\n\n const kindByte = readU8(data, base + V12_17_ACCT_KIND_OFF);\n const kind = kindByte === 1 ? AccountKind.LP : AccountKind.User;\n\n return {\n kind,\n accountId: 0n, // removed in v12.17\n capital: readU128LE(data, base + V12_17_ACCT_CAPITAL_OFF),\n pnl: readI128LE(data, base + V12_17_ACCT_PNL_OFF - d1),\n reservedPnl: readU128LE(data, base + V12_17_ACCT_RESERVED_PNL_OFF - d1),\n warmupStartedAtSlot: 0n, // removed\n warmupSlopePerStep: 0n, // removed\n positionSize: readI128LE(data, base + V12_17_ACCT_POSITION_BASIS_Q_OFF - d1),\n entryPrice: 0n, // removed — compute off-chain from position_basis_q / effective_pos_q\n fundingIndex: 0n, // replaced by per-side f_long_num/f_short_num + per-account f_snap\n matcherProgram: new PublicKey(data.subarray(base + V12_17_ACCT_MATCHER_PROGRAM_OFF - d1, base + V12_17_ACCT_MATCHER_PROGRAM_OFF - d1 + 32)),\n matcherContext: new PublicKey(data.subarray(base + V12_17_ACCT_MATCHER_CONTEXT_OFF - d1, base + V12_17_ACCT_MATCHER_CONTEXT_OFF - d1 + 32)),\n owner: new PublicKey(data.subarray(base + V12_17_ACCT_OWNER_OFF - d1, base + V12_17_ACCT_OWNER_OFF - d1 + 32)),\n feeCredits: readI128LE(data, base + V12_17_ACCT_FEE_CREDITS_OFF - d1),\n lastFeeSlot: 0n, // removed\n feesEarnedTotal: 0n, // removed in v12.17\n exactReserveCohorts: null, // replaced by two-bucket warmup\n exactCohortCount: null,\n overflowOlder: null,\n overflowOlderPresent: null,\n overflowNewest: null,\n overflowNewestPresent: null,\n\n // V12_17 fields\n fSnap: readI128LE(data, base + V12_17_ACCT_F_SNAP_OFF - d1),\n adlABasis: readU128LE(data, base + V12_17_ACCT_ADL_A_BASIS_OFF - d1),\n adlKSnap: readI128LE(data, base + V12_17_ACCT_ADL_K_SNAP_OFF - d1),\n adlEpochSnap: readU64LE(data, base + V12_17_ACCT_ADL_EPOCH_SNAP_OFF - d1),\n schedPresent: readU8(data, base + V12_17_ACCT_SCHED_PRESENT_OFF - d1) !== 0,\n schedRemainingQ: readU128LE(data, base + V12_17_ACCT_SCHED_REMAINING_Q_OFF - d1),\n schedAnchorQ: readU128LE(data, base + V12_17_ACCT_SCHED_ANCHOR_Q_OFF - d1),\n schedStartSlot: readU64LE(data, base + V12_17_ACCT_SCHED_START_SLOT_OFF - d1),\n schedHorizon: readU64LE(data, base + V12_17_ACCT_SCHED_HORIZON_OFF - d1),\n schedReleaseQ: readU128LE(data, base + V12_17_ACCT_SCHED_RELEASE_Q_OFF - d1),\n pendingPresent: readU8(data, base + V12_17_ACCT_PENDING_PRESENT_OFF - d1) !== 0,\n pendingRemainingQ: readU128LE(data, base + V12_17_ACCT_PENDING_REMAINING_Q_OFF - d2),\n pendingHorizon: readU64LE(data, base + V12_17_ACCT_PENDING_HORIZON_OFF - d2),\n pendingCreatedSlot: readU64LE(data, base + V12_17_ACCT_PENDING_CREATED_SLOT_OFF - d2),\n };\n }\n\n if (isV12_15) {\n // V12_15 fast path: fixed offsets, all fields explicit.\n const kindByte = readU8(data, base + V12_15_ACCT_KIND_OFF);\n const kind = kindByte === 1 ? AccountKind.LP : AccountKind.User;\n\n // Parse the 62 reserve cohorts\n const cohortCount = readU8(data, base + V12_15_ACCT_EXACT_COHORT_COUNT_OFF);\n const exactReserveCohorts: ReserveCohortBytes[] = [];\n for (let i = 0; i < 62; i++) {\n const cohortOff = base + V12_15_ACCT_EXACT_RESERVE_COHORTS_OFF + i * 64;\n exactReserveCohorts.push(data.slice(cohortOff, cohortOff + 64));\n }\n\n const overflowOlderPresent = readU8(data, base + V12_15_ACCT_OVERFLOW_OLDER_PRESENT_OFF) !== 0;\n const overflowNewestPresent = readU8(data, base + V12_15_ACCT_OVERFLOW_NEWEST_PRESENT_OFF) !== 0;\n\n return {\n kind,\n accountId: readU64LE(data, base + V12_15_ACCT_ACCOUNT_ID_OFF),\n capital: readU128LE(data, base + V12_15_ACCT_CAPITAL_OFF),\n pnl: readI128LE(data, base + V12_15_ACCT_PNL_OFF),\n reservedPnl: readU128LE(data, base + V12_15_ACCT_RESERVED_PNL_OFF),\n warmupStartedAtSlot: 0n, // removed in v12.15\n warmupSlopePerStep: 0n, // removed in v12.15\n positionSize: readI128LE(data, base + V12_15_ACCT_POSITION_BASIS_Q_OFF),\n entryPrice: readU64LE(data, base + V12_15_ACCT_ENTRY_PRICE_OFF),\n fundingIndex: 0n, // not present in v12.15 account struct\n matcherProgram: new PublicKey(data.subarray(base + V12_15_ACCT_MATCHER_PROGRAM_OFF, base + V12_15_ACCT_MATCHER_PROGRAM_OFF + 32)),\n matcherContext: new PublicKey(data.subarray(base + V12_15_ACCT_MATCHER_CONTEXT_OFF, base + V12_15_ACCT_MATCHER_CONTEXT_OFF + 32)),\n owner: new PublicKey(data.subarray(base + V12_15_ACCT_OWNER_OFF, base + V12_15_ACCT_OWNER_OFF + 32)),\n feeCredits: readI128LE(data, base + V12_15_ACCT_FEE_CREDITS_OFF),\n lastFeeSlot: 0n, // removed in v12.15\n feesEarnedTotal: readU128LE(data, base + V12_15_ACCT_FEES_EARNED_TOTAL_OFF),\n exactReserveCohorts,\n exactCohortCount: cohortCount,\n overflowOlder: data.slice(base + V12_15_ACCT_OVERFLOW_OLDER_OFF, base + V12_15_ACCT_OVERFLOW_OLDER_OFF + 64),\n overflowOlderPresent,\n overflowNewest: data.slice(base + V12_15_ACCT_OVERFLOW_NEWEST_OFF, base + V12_15_ACCT_OVERFLOW_NEWEST_OFF + 64),\n overflowNewestPresent,\n\n // v12.17 fields (not present in v12.15)\n fSnap: 0n, adlABasis: 0n, adlKSnap: 0n, adlEpochSnap: 0n,\n schedPresent: null, schedRemainingQ: null, schedAnchorQ: null,\n schedStartSlot: null, schedHorizon: null, schedReleaseQ: null,\n pendingPresent: null, pendingRemainingQ: null, pendingHorizon: null, pendingCreatedSlot: null,\n };\n }\n\n // Pre-v12.15 path\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 || isV12_1EP) ? V12_1_ACCT_POSITION_SIZE_OFF : (isAdl ? V_ADL_ACCT_POSITION_SIZE_OFF : ACCT_POSITION_SIZE_OFF);\n const entryPriceOff = isV12_1EP ? V12_1_EP_ACCT_ENTRY_PRICE_OFF : (isV12_1 ? V12_1_ACCT_ENTRY_PRICE_OFF : (isAdl ? V_ADL_ACCT_ENTRY_PRICE_OFF : ACCT_ENTRY_PRICE_OFF));\n const fundingIndexOff = (isV12_1 || isV12_1EP) ? -1 : (isAdl ? V_ADL_ACCT_FUNDING_INDEX_OFF : ACCT_FUNDING_INDEX_OFF);\n const matcherProgOff = isV12_1EP ? V12_1_EP_ACCT_MATCHER_PROGRAM_OFF : (isV12_1 ? V12_1_ACCT_MATCHER_PROGRAM_OFF : (isAdl ? V_ADL_ACCT_MATCHER_PROGRAM_OFF : ACCT_MATCHER_PROGRAM_OFF));\n const matcherCtxOff = isV12_1EP ? V12_1_EP_ACCT_MATCHER_CONTEXT_OFF : (isV12_1 ? V12_1_ACCT_MATCHER_CONTEXT_OFF : (isAdl ? V_ADL_ACCT_MATCHER_CONTEXT_OFF : ACCT_MATCHER_CONTEXT_OFF));\n const feeCreditsOff = isV12_1EP ? V12_1_EP_ACCT_FEE_CREDITS_OFF : (isV12_1 ? V12_1_ACCT_FEE_CREDITS_OFF : (isAdl ? V_ADL_ACCT_FEE_CREDITS_OFF : ACCT_FEE_CREDITS_OFF));\n const lastFeeSlotOff = isV12_1EP ? V12_1_EP_ACCT_LAST_FEE_SLOT_OFF : (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: entryPriceOff >= 0 ? readU64LE(data, base + entryPriceOff) : 0n,\n // V12_1/V12_1_EP: funding_index not present in SBF layout\n fundingIndex: (isV12_1 || isV12_1EP) ? (fundingIndexOff >= 0 ? BigInt(readI64LE(data, base + fundingIndexOff)) : 0n) : 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 feesEarnedTotal: 0n, // not present in pre-v12.15 layouts\n exactReserveCohorts: null, // not present in pre-v12.15 layouts\n exactCohortCount: null,\n overflowOlder: null,\n overflowOlderPresent: null,\n overflowNewest: null,\n overflowNewestPresent: null,\n\n // v12.17 fields (not present in pre-v12.17)\n fSnap: 0n, adlABasis: 0n, adlKSnap: 0n, adlEpochSnap: 0n,\n schedPresent: null, schedRemainingQ: null, schedAnchorQ: null,\n schedStartSlot: null, schedHorizon: null, schedReleaseQ: null,\n pendingPresent: null, pendingRemainingQ: null, pendingHorizon: null, pendingCreatedSlot: null,\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 (a.k.a. LP vault mint PDA).\n * Seeds: [\"lp_vault_mint\", slab_key]\n * Wrapper anchor: src/percolator.rs:2543 derive_lp_vault_mint.\n */\nexport function deriveInsuranceLpMint(\n programId: PublicKey,\n slab: PublicKey\n): [PublicKey, number] {\n return PublicKey.findProgramAddressSync(\n [textEncoder.encode(\"lp_vault_mint\"), 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// 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 feedId[i] = parseInt(normalized.substring(i * 2, i * 2 + 2), 16);\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_V1M2,\n SLAB_TIERS_V2,\n SLAB_TIERS_V_ADL,\n SLAB_TIERS_V12_1,\n SLAB_TIERS_V12_15,\n SLAB_TIERS_V12_17,\n SLAB_TIERS_V_SETDEXPOOL,\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.17).\n * These are used by useCreateMarket to allocate slab accounts of the correct size.\n * V12_17: two-bucket warmup, per-side funding, ACCOUNT_SIZE=352 (SBF).\n */\nexport const SLAB_TIERS = {\n small: SLAB_TIERS_V12_17[\"small\"],\n medium: SLAB_TIERS_V12_17[\"medium\"],\n large: SLAB_TIERS_V12_17[\"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 fundingRateE9: 0n,\n marketMode: null,\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 pnlMaturedPosTot: 0n,\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 oraclePriceE6: 0n,\n fLongNum: 0n, fShortNum: 0n, negPnlAccountCount: 0n, fundPxLast: 0n,\n resolvedKLongTerminalDelta: 0n, resolvedKShortTerminalDelta: 0n, resolvedLivePrice: 0n,\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 fundingRateE9: 0n,\n marketMode: null,\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 pnlMaturedPosTot: 0n,\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 oraclePriceE6: 0n,\n fLongNum: 0n, fShortNum: 0n, negPnlAccountCount: 0n, fundPxLast: 0n,\n resolvedKLongTerminalDelta: 0n, resolvedKShortTerminalDelta: 0n, resolvedLivePrice: 0n,\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 fundingRateE9: 0n,\n marketMode: null,\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 pnlMaturedPosTot: 0n,\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 oraclePriceE6: 0n,\n fLongNum: 0n, fShortNum: 0n, negPnlAccountCount: 0n, fundPxLast: 0n,\n resolvedKLongTerminalDelta: 0n, resolvedKShortTerminalDelta: 0n, resolvedLivePrice: 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 fundingRateE9: 0n,\n marketMode: null,\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 pnlMaturedPosTot: 0n,\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 oraclePriceE6: 0n,\n fLongNum: 0n, fShortNum: 0n, negPnlAccountCount: 0n, fundPxLast: 0n,\n resolvedKLongTerminalDelta: 0n, resolvedKShortTerminalDelta: 0n, resolvedLivePrice: 0n,\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), // v12.17 (default)\n ...Object.values(SLAB_TIERS_V12_15), // v12.15\n ...Object.values(SLAB_TIERS_V12_1), // v12.1\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_V1M2),\n ...Object.values(SLAB_TIERS_V_ADL),\n ...Object.values(SLAB_TIERS_V_SETDEXPOOL),\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 * (`ESa89R5Es3rJ5mnwGybVRG1GrNt9etP11Z5V2QWD4edv`).\n *\n * **Last updated:** 2026-04-11 (V12_1_EP mainnet market with entry_price support).\n */\nconst MAINNET_MARKETS: StaticMarketEntry[] = [\n { slabAddress: \"7psyeWRts4pRX2cyAWD1NH87bR9ugXP7pe6ARgfG79Do\", symbol: \"SOL-PERP\", name: \"SOL/USDC 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 const scaledSqrt = sqrtPriceX64 * 1_000_000n;\n const term = scaledSqrt >> 64n;\n const priceE6Raw = (term * sqrtPriceX64) >> 64n;\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 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 while (exp > 0n) {\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 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}\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): 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 return { price, decimals };\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_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 return info.owner;\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: DC5fovFQD5SZYsetwvEqd4Wi4PFY1Yfnc669VMe6oa7F\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\n// ═══════════════════════════════════════════════════════════════\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: '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 if (n === 'mainnet' || n === 'mainnet-beta') return 'mainnet' as const;\n if (n === 'devnet') return 'devnet' as const;\n // In browser bundles, process.env is empty (env vars aren't inlined into\n // third-party SDK code). Default to mainnet to match the app's fail-closed\n // behavior — devnet must be opted into explicitly.\n if (typeof window !== 'undefined') return 'mainnet' as const;\n return 'devnet' as const;\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 /** @deprecated Removed on-chain in stake v3. This tag now rejects. */\n TransferAdmin: 5,\n /** @deprecated Removed on-chain in stake v3. This tag now rejects. */\n AdminSetOracleAuthority: 6,\n /** @deprecated Removed on-chain in stake v3. This tag now rejects. */\n AdminSetRiskThreshold: 7,\n /** @deprecated Removed on-chain in stake v3. This tag now rejects. */\n AdminSetMaintenanceFee: 8,\n /** @deprecated Removed on-chain in stake v3. This tag now rejects. */\n AdminResolveMarket: 9,\n /** Current on-chain tag 10: transfer withdrawn insurance back into the pool vault. */\n ReturnInsurance: 10,\n /** @deprecated Legacy alias for ReturnInsurance. */\n AdminWithdrawInsurance: 10,\n /** @deprecated Removed on-chain in stake v3. This tag now rejects. */\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 /** Mark the pool as resolved after the wrapper market has been resolved directly. */\n SetMarketResolved: 18,\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('stake_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 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 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 (v < 0 || v > 0xFFFF) throw new Error(`u16Le: value out of u16 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\nfunction removedStakeInstruction(name: string, tag: number): never {\n throw new Error(\n `${name} (stake tag ${tag}) was removed on-chain in percolator-stake v3 and must not be sent.`,\n );\n}\n\n/** @deprecated Removed on-chain in stake v3. Throws instead of emitting a dead instruction. */\nexport function encodeStakeTransferAdmin(): Uint8Array {\n return removedStakeInstruction('encodeStakeTransferAdmin', STAKE_IX.TransferAdmin);\n}\n\n/** @deprecated Removed on-chain in stake v3. Throws instead of emitting a dead instruction. */\nexport function encodeStakeAdminSetOracleAuthority(newAuthority: PublicKey): Uint8Array {\n void newAuthority;\n return removedStakeInstruction('encodeStakeAdminSetOracleAuthority', STAKE_IX.AdminSetOracleAuthority);\n}\n\n/** @deprecated Removed on-chain in stake v3. Throws instead of emitting a dead instruction. */\nexport function encodeStakeAdminSetRiskThreshold(newThreshold: bigint | number): Uint8Array {\n void newThreshold;\n return removedStakeInstruction('encodeStakeAdminSetRiskThreshold', STAKE_IX.AdminSetRiskThreshold);\n}\n\n/** @deprecated Removed on-chain in stake v3. Throws instead of emitting a dead instruction. */\nexport function encodeStakeAdminSetMaintenanceFee(newFee: bigint | number): Uint8Array {\n void newFee;\n return removedStakeInstruction('encodeStakeAdminSetMaintenanceFee', STAKE_IX.AdminSetMaintenanceFee);\n}\n\n/** @deprecated Removed on-chain in stake v3. Throws instead of emitting a dead instruction. */\nexport function encodeStakeAdminResolveMarket(): Uint8Array {\n return removedStakeInstruction('encodeStakeAdminResolveMarket', STAKE_IX.AdminResolveMarket);\n}\n\n/** Tag 10: ReturnInsurance — transfer withdrawn insurance back into the stake pool vault. */\nexport function encodeStakeReturnInsurance(amount: bigint | number): Uint8Array {\n return concatBytes(\n new Uint8Array([STAKE_IX.ReturnInsurance]),\n u64Le(amount),\n );\n}\n\n/** @deprecated Legacy alias for tag 10. Current on-chain semantics are ReturnInsurance. */\nexport function encodeStakeAdminWithdrawInsurance(amount: bigint | number): Uint8Array {\n return encodeStakeReturnInsurance(amount);\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 18: SetMarketResolved — blocks new deposits after the wrapper market is resolved. */\nexport function encodeStakeSetMarketResolved(): Uint8Array {\n return new Uint8Array([STAKE_IX.SetMarketResolved]);\n}\n\n/** @deprecated Removed on-chain in stake v3. Throws instead of emitting a dead instruction. */\nexport function encodeStakeAdminSetInsurancePolicy(\n authority: PublicKey,\n minWithdrawBase: bigint | number,\n maxWithdrawBps: number,\n cooldownSlots: bigint | number,\n): Uint8Array {\n void authority;\n void minWithdrawBase;\n void maxWithdrawBps;\n void cooldownSlots;\n return removedStakeInstruction('encodeStakeAdminSetInsurancePolicy', STAKE_IX.AdminSetInsurancePolicy);\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 marketResolved: 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] market_resolved\n // [10..32] PERC-313 HWM\n // [32..51] PERC-303 tranches\n // [51..64] free\n\n // PERC-313: HWM fields (from _reserved[10..32])\n hwmEnabled: boolean;\n epochHighWaterTvl: bigint;\n hwmFloorBps: number;\n hwmLastEpoch: bigint;\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 // _reserved[9] = market_resolved\n // PERC-313: _reserved[10] = hwm_enabled, [11..13] = hwm_floor_bps (u16),\n // [16..24] = epoch_high_water_tvl (u64), [24..32] = hwm_last_epoch (u64)\n const marketResolved = bytes[reservedStart + 9] === 1;\n const hwmEnabled = bytes[reservedStart + 10] === 1;\n const hwmFloorBps = readU16LE(bytes, reservedStart + 11);\n const epochHighWaterTvl = readU64LE(bytes, reservedStart + 16);\n const hwmLastEpoch = readU64LE(bytes, reservedStart + 24);\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 marketResolved,\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 hwmLastEpoch,\n trancheEnabled,\n juniorBalance,\n juniorTotalLp,\n juniorFeeMultBps,\n };\n}\n\n// ═══════════════════════════════════════════════════════════════\n// StakeDeposit PDA decoder\n// ═══════════════════════════════════════════════════════════════\n\n/** Size of StakeDeposit on-chain (bytes). */\nexport const STAKE_DEPOSIT_SIZE = 152;\n\n/** Decoded StakeDeposit PDA state. */\nexport interface StakeDepositState {\n isInitialized: boolean;\n bump: number;\n pool: PublicKey;\n user: PublicKey;\n lastDepositSlot: bigint;\n lpAmount: bigint;\n}\n\n/**\n * Decode a StakeDeposit PDA account from raw data.\n *\n * On-chain layout (152 bytes, percolator-stake/src/state.rs):\n * [0] is_initialized u8\n * [1] bump u8\n * [2..8] _padding\n * [8..40] pool [u8; 32]\n * [40..72] user [u8; 32]\n * [72..80] last_deposit_slot u64\n * [80..88] lp_amount u64\n * [88..152] _reserved\n */\nexport function decodeDepositPda(data: Uint8Array): StakeDepositState {\n if (data.length < STAKE_DEPOSIT_SIZE) {\n throw new Error(`StakeDeposit data too short: ${data.length} < ${STAKE_DEPOSIT_SIZE}`);\n }\n return {\n isInitialized: data[0] === 1,\n bump: data[1],\n pool: new PublicKey(data.subarray(8, 40)),\n user: new PublicKey(data.subarray(40, 72)),\n lastDepositSlot: readU64LE(data, 72),\n lpAmount: readU64LE(data, 80),\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","/**\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) return false;\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 const side: AdlSide = account.positionSize > 0n ? \"long\" : \"short\";\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 data = Buffer.from(encodeExecuteAdl({ targetIdx }));\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 targetIdx = Number(BigInt(match[2]));\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 = await res.json() as AdlApiResult;\n return json;\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 */\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 */\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 */\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 signedPos = direction === \"long\" ? absPos : -absPos;\n // Fee adjusts the effective entry price, not the capital.\n // For longs: you pay more (oracle + fee) → worse entry → closer liquidation.\n // For shorts: you receive less (oracle - fee) → worse entry → closer liquidation.\n const feeAdjust = (oracleE6 * feeBps) / 10000n;\n let adjustedEntry: bigint;\n if (direction === \"long\") {\n adjustedEntry = oracleE6 + feeAdjust;\n } else {\n // Clamp short entry to 1n — a zero or negative entry price is nonsensical\n // and causes computeLiqPrice to return 0n (\"no liquidation risk\") when\n // feeBps >= 10000, misleading the UI into showing the position is safe.\n const shortEntry = oracleE6 - feeAdjust;\n adjustedEntry = shortEntry > 0n ? shortEntry : 1n;\n }\n return computeLiqPrice(adjustedEntry, margin, signedPos, maintBps);\n}\n\n/**\n * Compute trading fee from notional value and fee rate in bps.\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 const lp = (totalFee * config.lpBps) / 10000n;\n const protocol = (totalFee * config.protocolBps) / 10000n;\n const creator = totalFee - lp - protocol;\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 */\nexport function computeEstimatedEntryPrice(\n oracleE6: bigint,\n tradingFeeBps: bigint,\n direction: \"long\" | \"short\",\n): bigint {\n if (oracleE6 === 0n) return 0n;\n const feeImpact = (oracleE6 * tradingFeeBps) / 10000n;\n if (direction === \"long\") return oracleE6 + feeImpact;\n // Clamp to 1 to prevent underflow — a zero or negative entry price is nonsensical\n // and would cause computePreTradeLiqPrice to report \"no liquidation risk\" (liqPrice=0)\n // when fee >= 100%, misleading the UI.\n const shortEntry = oracleE6 - feeImpact;\n return shortEntry > 0n ? shortEntry : 1n;\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 */\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 */\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 * @throws Error if initialMarginBps is zero (infinite leverage is undefined)\n */\nexport function computeMaxLeverage(initialMarginBps: bigint): number {\n if (initialMarginBps <= 0n) {\n throw new Error(\"computeMaxLeverage: initialMarginBps must be positive\");\n }\n return Number(10000n / initialMarginBps);\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 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 effectiveLev = Number((BigInt(maxLev) * unlocked) / totalCapital);\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 * 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 */\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 */\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 return Number(bi);\n}\n\n/**\n * Validate a non-negative amount (u64 range).\n */\nexport function validateAmount(value: string, field: string): bigint {\n let num: bigint;\n try {\n num = BigInt(value);\n } catch {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid number. Use decimal digits only.`\n );\n }\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 let num: bigint;\n try {\n num = BigInt(value);\n } catch {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid number. Use decimal digits only.`\n );\n }\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 let num: bigint;\n try {\n num = BigInt(value);\n } catch {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid number. Use decimal digits only, with optional leading minus.`\n );\n }\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 let num: bigint;\n try {\n num = BigInt(value);\n } catch {\n throw new ValidationError(\n field,\n `\"${value}\" is not a valid number. Use decimal digits only, with optional leading minus.`\n );\n }\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 */\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 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 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 price =\n typeof priceUsd === \"string\" || typeof priceUsd === \"number\"\n ? parseFloat(String(priceUsd)) || 0\n : 0;\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)) || 0;\n if (price <= 0) return null;\n let mintSymbol = \"?\";\n if (typeof row.mintSymbol === \"string\") mintSymbol = row.mintSymbol;\n return { price, mintSymbol };\n}\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) return [];\n const json: unknown = await resp.json();\n return parseDexScreenerPairs(json);\n } catch {\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: Infinity, // 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) return null;\n const json: unknown = await resp.json();\n const row = parseJupiterMintEntry(json, mint);\n if (!row) return null;\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 {\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 combinedSignal = signal\n ? combineAbortSignals([signal, timeoutSignal])\n : timeoutSignal;\n\n const [dexSources, jupiterSource] = await Promise.all([\n fetchDexSources(mint, combinedSignal),\n fetchJupiterSource(mint, combinedSignal),\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 Jupiter or DEX if available\n const refPrice = dexSources[0]?.price || jupiterSource?.price || 0;\n pythSource.price = refPrice;\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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AAA,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,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;A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","names":["PublicKey","PublicKey","PublicKey","PublicKey","PublicKey","bitmapBytes","AccountKind","PublicKey","kindByte","kind","PublicKey","idxBuf","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","TEXT","readU64LE","readU16LE","PublicKey","readU64LE","readU16LE","TOKEN_PROGRAM_ID","SystemProgram","SYSVAR_RENT_PUBKEY","SYSVAR_CLOCK_PUBKEY","SYSVAR_CLOCK_PUBKEY","SYSVAR_CLOCK_PUBKEY","Connection","TransactionInstruction","TransactionInstruction","PublicKey","Transaction","PublicKey","U16_MAX"]}
|