@percolatorct/sdk 0.3.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.
@@ -0,0 +1,263 @@
1
+ import { Connection, PublicKey } from "@solana/web3.js";
2
+ import { type SlabHeader, type MarketConfig, type EngineState, type RiskParams } from "./slab.js";
3
+ /**
4
+ * A discovered Percolator market from on-chain program accounts.
5
+ */
6
+ export interface DiscoveredMarket {
7
+ slabAddress: PublicKey;
8
+ /** The program that owns this slab account */
9
+ programId: PublicKey;
10
+ header: SlabHeader;
11
+ config: MarketConfig;
12
+ engine: EngineState;
13
+ params: RiskParams;
14
+ }
15
+ /**
16
+ * Slab tier definitions — V1 layout (all tiers upgraded as of 2026-03-13).
17
+ * IMPORTANT: dataSize must match the compiled program's SLAB_LEN for that MAX_ACCOUNTS.
18
+ * The on-chain program has a hardcoded SLAB_LEN — slab account data.len() must equal it exactly.
19
+ *
20
+ * Layout: HEADER(104) + CONFIG(536) + RiskEngine(variable by tier)
21
+ * ENGINE_OFF = 640 (HEADER=104 + CONFIG=536, padded to 8-byte align on SBF)
22
+ * RiskEngine = fixed(656) + bitmap(BW*8) + post_bitmap(18) + next_free(N*2) + pad + accounts(N*248)
23
+ *
24
+ * Values are empirically verified against on-chain initialized accounts (GH #1109):
25
+ * small = 65,352 (256-acct program, verified on-chain post-V1 upgrade)
26
+ * medium = 257,448 (1024-acct program g9msRSV3, verified on-chain)
27
+ * large = 1,025,832 (4096-acct program FxfD37s1, pre-PERC-118, matches slabDataSizeV1(4096) formula)
28
+ *
29
+ * NOTE: small program (FwfBKZXb) redeployed with --features small,devnet (2026-03-13).
30
+ * Large program FxfD37s1 is pre-PERC-118 — SLAB_LEN=1,025,832, matching formula.
31
+ * See GH #1109, GH #1112.
32
+ *
33
+ * History: Small was V0 (62_808) until 2026-03-13 program upgrade. V0 values preserved
34
+ * in SLAB_TIERS_V0 for discovery of legacy on-chain accounts.
35
+ */
36
+ export declare const SLAB_TIERS: {
37
+ readonly small: {
38
+ readonly maxAccounts: 256;
39
+ readonly dataSize: 65352;
40
+ readonly label: "Small";
41
+ readonly description: "256 slots · ~0.45 SOL";
42
+ };
43
+ readonly medium: {
44
+ readonly maxAccounts: 1024;
45
+ readonly dataSize: 257448;
46
+ readonly label: "Medium";
47
+ readonly description: "1,024 slots · ~1.79 SOL";
48
+ };
49
+ readonly large: {
50
+ readonly maxAccounts: 4096;
51
+ readonly dataSize: 1025832;
52
+ readonly label: "Large";
53
+ readonly description: "4,096 slots · ~7.14 SOL";
54
+ };
55
+ };
56
+ /** @deprecated V0 slab sizes — kept for backward compatibility with old on-chain slabs */
57
+ export declare const SLAB_TIERS_V0: {
58
+ readonly small: {
59
+ readonly maxAccounts: 256;
60
+ readonly dataSize: 62808;
61
+ readonly label: "Small";
62
+ readonly description: "256 slots · ~0.44 SOL";
63
+ };
64
+ readonly medium: {
65
+ readonly maxAccounts: 1024;
66
+ readonly dataSize: 248760;
67
+ readonly label: "Medium";
68
+ readonly description: "1,024 slots · ~1.73 SOL";
69
+ };
70
+ readonly large: {
71
+ readonly maxAccounts: 4096;
72
+ readonly dataSize: 992568;
73
+ readonly label: "Large";
74
+ readonly description: "4,096 slots · ~6.90 SOL";
75
+ };
76
+ };
77
+ /**
78
+ * V1D slab sizes — actually-deployed devnet V1 program (ENGINE_OFF=424, BITMAP_OFF=624).
79
+ * PR #1200 added V1D layout detection in slab.ts but discovery.ts ALL_TIERS was missing
80
+ * these sizes, causing V1D slabs to fall through to the memcmp fallback with wrong dataSize
81
+ * hints → detectSlabLayout returning null → parse failure (GH#1205).
82
+ *
83
+ * Sizes computed via computeSlabSize(ENGINE_OFF=424, BITMAP_OFF=624, ACCOUNT_SIZE=248, N, postBitmap=2):
84
+ * The V1D deployed program uses postBitmap=2 (free_head u16 only — no num_used/pad/next_account_id).
85
+ * This is 16 bytes smaller per tier than the SDK default (postBitmap=18). GH#1234.
86
+ * micro = 17,064 (64 slots)
87
+ * small = 65,088 (256 slots)
88
+ * medium = 257,184 (1,024 slots)
89
+ * large = 1,025,568 (4,096 slots)
90
+ */
91
+ export declare const SLAB_TIERS_V1D: {
92
+ readonly micro: {
93
+ readonly maxAccounts: 64;
94
+ readonly dataSize: 17064;
95
+ readonly label: "Micro";
96
+ readonly description: "64 slots (V1D devnet)";
97
+ };
98
+ readonly small: {
99
+ readonly maxAccounts: 256;
100
+ readonly dataSize: 65088;
101
+ readonly label: "Small";
102
+ readonly description: "256 slots (V1D devnet)";
103
+ };
104
+ readonly medium: {
105
+ readonly maxAccounts: 1024;
106
+ readonly dataSize: 257184;
107
+ readonly label: "Medium";
108
+ readonly description: "1,024 slots (V1D devnet)";
109
+ };
110
+ readonly large: {
111
+ readonly maxAccounts: 4096;
112
+ readonly dataSize: 1025568;
113
+ readonly label: "Large";
114
+ readonly description: "4,096 slots (V1D devnet)";
115
+ };
116
+ };
117
+ /**
118
+ * V1D legacy slab sizes — on-chain V1D slabs created before GH#1234 when the SDK assumed
119
+ * postBitmap=18. These are 16 bytes larger per tier than SLAB_TIERS_V1D.
120
+ * PR #1236 fixed postBitmap for new slabs (→2) but caused slab 6ZytbpV4 (65104 bytes,
121
+ * top active market ~$15k 24h vol) to be unrecognized → "Failed to load market". GH#1237.
122
+ *
123
+ * Sizes computed via computeSlabSize(ENGINE_OFF=424, BITMAP_OFF=624, ACCOUNT_SIZE=248, N, postBitmap=18):
124
+ * micro = 17,080 (64 slots)
125
+ * small = 65,104 (256 slots) ← slab 6ZytbpV4 TEST/USD
126
+ * medium = 257,200 (1,024 slots)
127
+ * large = 1,025,584 (4,096 slots)
128
+ */
129
+ export declare const SLAB_TIERS_V1D_LEGACY: {
130
+ readonly micro: {
131
+ readonly maxAccounts: 64;
132
+ readonly dataSize: 17080;
133
+ readonly label: "Micro";
134
+ readonly description: "64 slots (V1D legacy, postBitmap=18)";
135
+ };
136
+ readonly small: {
137
+ readonly maxAccounts: 256;
138
+ readonly dataSize: 65104;
139
+ readonly label: "Small";
140
+ readonly description: "256 slots (V1D legacy, postBitmap=18)";
141
+ };
142
+ readonly medium: {
143
+ readonly maxAccounts: 1024;
144
+ readonly dataSize: 257200;
145
+ readonly label: "Medium";
146
+ readonly description: "1,024 slots (V1D legacy, postBitmap=18)";
147
+ };
148
+ readonly large: {
149
+ readonly maxAccounts: 4096;
150
+ readonly dataSize: 1025584;
151
+ readonly label: "Large";
152
+ readonly description: "4,096 slots (V1D legacy, postBitmap=18)";
153
+ };
154
+ };
155
+ /** @deprecated Alias — use SLAB_TIERS (already V1) */
156
+ export declare const SLAB_TIERS_V1: {
157
+ readonly small: {
158
+ readonly maxAccounts: 256;
159
+ readonly dataSize: 65352;
160
+ readonly label: "Small";
161
+ readonly description: "256 slots · ~0.45 SOL";
162
+ };
163
+ readonly medium: {
164
+ readonly maxAccounts: 1024;
165
+ readonly dataSize: 257448;
166
+ readonly label: "Medium";
167
+ readonly description: "1,024 slots · ~1.79 SOL";
168
+ };
169
+ readonly large: {
170
+ readonly maxAccounts: 4096;
171
+ readonly dataSize: 1025832;
172
+ readonly label: "Large";
173
+ readonly description: "4,096 slots · ~7.14 SOL";
174
+ };
175
+ };
176
+ /**
177
+ * V_ADL slab tier sizes — PERC-8270/8271 ADL-upgraded program.
178
+ * ENGINE_OFF=624, BITMAP_OFF=1006, ACCOUNT_SIZE=312, postBitmap=18.
179
+ * New account layout adds ADL tracking fields (+64 bytes/account).
180
+ * BPF SLAB_LEN verified by cargo build-sbf in PERC-8271: large (4096) = 1288304 bytes.
181
+ */
182
+ export declare const SLAB_TIERS_V_ADL_DISCOVERY: Record<string, {
183
+ maxAccounts: number;
184
+ dataSize: number;
185
+ label: string;
186
+ description: string;
187
+ }>;
188
+ export type SlabTierKey = keyof typeof SLAB_TIERS;
189
+ /** Calculate slab data size for arbitrary account count.
190
+ *
191
+ * Layout (SBF, u128 align = 8):
192
+ * HEADER(104) + CONFIG(536) → ENGINE_OFF = 640
193
+ * RiskEngine fixed scalars: 656 bytes (PERC-299: +24 emergency OI, +32 long/short OI)
194
+ * + bitmap: ceil(N/64)*8
195
+ * + num_used_accounts(u16) + pad(6) + next_account_id(u64) + free_head(u16) = 18
196
+ * + next_free: N*2
197
+ * + pad to 8-byte alignment for Account array
198
+ * + accounts: N*248
199
+ *
200
+ * Must match the on-chain program's SLAB_LEN exactly.
201
+ */
202
+ export declare function slabDataSize(maxAccounts: number): number;
203
+ /**
204
+ * Calculate slab data size for V1 layout (ENGINE_OFF=640).
205
+ *
206
+ * NOTE: This formula is accurate for small (256) and medium (1024) tiers but
207
+ * underestimates large (4096) by 16 bytes — likely due to a padding/alignment
208
+ * difference at high account counts or a post-PERC-118 struct addition in the
209
+ * deployed binary. Always prefer the hardcoded SLAB_TIERS values (empirically
210
+ * verified on-chain) over this formula for production use.
211
+ */
212
+ export declare function slabDataSizeV1(maxAccounts: number): number;
213
+ /**
214
+ * Validate that a slab data size matches one of the known tier sizes.
215
+ * Use this to catch tier↔program mismatches early (PERC-277).
216
+ *
217
+ * @param dataSize - The expected slab data size (from SLAB_TIERS[tier].dataSize)
218
+ * @param programSlabLen - The program's compiled SLAB_LEN (from on-chain error logs or program introspection)
219
+ * @returns true if sizes match, false if there's a mismatch
220
+ */
221
+ export declare function validateSlabTierMatch(dataSize: number, programSlabLen: number): boolean;
222
+ /** Options for `discoverMarkets`. */
223
+ export interface DiscoverMarketsOptions {
224
+ /**
225
+ * Run tier queries sequentially with per-tier retry on HTTP 429 instead of
226
+ * firing all in parallel. Reduces RPC rate-limit pressure at the cost of
227
+ * slightly slower discovery (~14 round-trips instead of 1 concurrent batch).
228
+ * Default: false (preserves original parallel behaviour).
229
+ *
230
+ * PERC-1650: keeper uses this flag to avoid 429 storms on its fallback RPC
231
+ * (Helius starter tier). Pass `sequential: true` from CrankService.discover().
232
+ */
233
+ sequential?: boolean;
234
+ /**
235
+ * Delay in ms between sequential tier queries (only used when sequential=true).
236
+ * Default: 200 ms.
237
+ */
238
+ interTierDelayMs?: number;
239
+ /**
240
+ * Per-tier retry backoff delays on 429 (ms). Jitter of up to +25% is applied.
241
+ * Only used when sequential=true. Default: [1_000, 3_000, 9_000, 27_000].
242
+ */
243
+ rateLimitBackoffMs?: number[];
244
+ /**
245
+ * In parallel mode (the default), cap how many tier RPC requests are in-flight
246
+ * at once to avoid accidental RPC storms from client code.
247
+ *
248
+ * Default: 6
249
+ */
250
+ maxParallelTiers?: number;
251
+ /**
252
+ * Hard cap on how many tier dataSize queries are attempted.
253
+ * Default: all known tiers.
254
+ */
255
+ maxTierQueries?: number;
256
+ }
257
+ /**
258
+ * Discover all Percolator markets owned by the given program.
259
+ * Uses getProgramAccounts with dataSize filter + dataSlice to download only ~1400 bytes per slab.
260
+ *
261
+ * @param options.sequential - Run tier queries sequentially with 429 retry (PERC-1650).
262
+ */
263
+ export declare function discoverMarkets(connection: Connection, programId: PublicKey, options?: DiscoverMarketsOptions): Promise<DiscoveredMarket[]>;
@@ -0,0 +1,9 @@
1
+ export * from "./slab.js";
2
+ export * from "./pda.js";
3
+ export * from "./ata.js";
4
+ export * from "./discovery.js";
5
+ export * from "./dex-oracle.js";
6
+ export * from "./oracle.js";
7
+ export * from "./token-program.js";
8
+ export * from "./stake.js";
9
+ export * from "./adl.js";
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Oracle account parsing utilities.
3
+ *
4
+ * Chainlink aggregator layout on Solana (from Toly's percolator-cli):
5
+ * offset 138: decimals (u8)
6
+ * offset 216: latest answer (i64 LE)
7
+ *
8
+ * Minimum account size: 224 bytes (offset 216 + 8 bytes for i64).
9
+ *
10
+ * These utilities validate oracle data BEFORE parsing to prevent silent
11
+ * propagation of stale or malformed Chainlink data as price.
12
+ */
13
+ /** Minimum buffer size to read Chainlink price data */
14
+ declare const CHAINLINK_MIN_SIZE = 224;
15
+ /** Maximum reasonable decimals for a price feed */
16
+ declare const MAX_DECIMALS = 18;
17
+ /** Offset of decimals field in Chainlink aggregator account */
18
+ declare const CHAINLINK_DECIMALS_OFFSET = 138;
19
+ /** Offset of latest answer in Chainlink aggregator account */
20
+ declare const CHAINLINK_ANSWER_OFFSET = 216;
21
+ export interface OraclePrice {
22
+ price: bigint;
23
+ decimals: number;
24
+ }
25
+ /**
26
+ * Parse price data from a Chainlink aggregator account buffer.
27
+ *
28
+ * Validates:
29
+ * - Buffer is large enough to contain the required fields (≥ 224 bytes)
30
+ * - Decimals are in a reasonable range (0-18)
31
+ * - Price is positive (non-zero)
32
+ *
33
+ * @param data - Raw account data from Chainlink aggregator
34
+ * @returns Parsed oracle price with decimals
35
+ * @throws if the buffer is invalid or contains unreasonable data
36
+ */
37
+ export declare function parseChainlinkPrice(data: Uint8Array): OraclePrice;
38
+ /**
39
+ * Validate that a buffer looks like a valid Chainlink aggregator account.
40
+ * Returns true if the buffer passes all validation checks, false otherwise.
41
+ * Use this for non-throwing validation.
42
+ */
43
+ export declare function isValidChainlinkOracle(data: Uint8Array): boolean;
44
+ export { CHAINLINK_MIN_SIZE, CHAINLINK_DECIMALS_OFFSET, CHAINLINK_ANSWER_OFFSET, MAX_DECIMALS };
@@ -0,0 +1,54 @@
1
+ import { PublicKey } from "@solana/web3.js";
2
+ /**
3
+ * Derive vault authority PDA.
4
+ * Seeds: ["vault", slab_key]
5
+ */
6
+ export declare function deriveVaultAuthority(programId: PublicKey, slab: PublicKey): [PublicKey, number];
7
+ /**
8
+ * Derive insurance LP mint PDA.
9
+ * Seeds: ["ins_lp", slab_key]
10
+ */
11
+ export declare function deriveInsuranceLpMint(programId: PublicKey, slab: PublicKey): [PublicKey, number];
12
+ /**
13
+ * Derive LP PDA for TradeCpi.
14
+ * Seeds: ["lp", slab_key, lp_idx as u16 LE]
15
+ */
16
+ export declare function deriveLpPda(programId: PublicKey, slab: PublicKey, lpIdx: number): [PublicKey, number];
17
+ /**
18
+ * Derive keeper fund PDA.
19
+ * Seeds: ["keeper_fund", slab_key]
20
+ */
21
+ export declare function deriveKeeperFund(programId: PublicKey, slab: PublicKey): [PublicKey, number];
22
+ /** PumpSwap AMM program ID. */
23
+ export declare const PUMPSWAP_PROGRAM_ID: PublicKey;
24
+ /** Raydium CLMM (Concentrated Liquidity) program ID. */
25
+ export declare const RAYDIUM_CLMM_PROGRAM_ID: PublicKey;
26
+ /** Meteora DLMM (Dynamic Liquidity Market Maker) program ID. */
27
+ export declare const METEORA_DLMM_PROGRAM_ID: PublicKey;
28
+ /** Pyth Push Oracle program on mainnet. */
29
+ export declare const PYTH_PUSH_ORACLE_PROGRAM_ID: PublicKey;
30
+ /**
31
+ * Seed used to derive the creator lock PDA.
32
+ * Matches `creator_lock::CREATOR_LOCK_SEED` in percolator-prog.
33
+ */
34
+ export declare const CREATOR_LOCK_SEED = "creator_lock";
35
+ /**
36
+ * Derive the creator lock PDA for a given slab.
37
+ * Seeds: ["creator_lock", slab_key]
38
+ *
39
+ * This PDA is required as accounts[9] in every LpVaultWithdraw instruction
40
+ * since percolator-prog PR#170 (GH#1926 / PERC-8287).
41
+ * Non-creator withdrawers must pass this key; if no lock exists on-chain the
42
+ * enforcement is a no-op. The SDK must ALWAYS include it — passing it is mandatory.
43
+ *
44
+ * @param programId - The percolator program ID.
45
+ * @param slab - The slab (market) public key.
46
+ * @returns [pda, bump]
47
+ *
48
+ * @example
49
+ * ```ts
50
+ * const [creatorLockPda] = deriveCreatorLockPda(PROGRAM_ID, slabKey);
51
+ * ```
52
+ */
53
+ export declare function deriveCreatorLockPda(programId: PublicKey, slab: PublicKey): [PublicKey, number];
54
+ export declare function derivePythPushOraclePDA(feedIdHex: string): [PublicKey, number];
@@ -0,0 +1,316 @@
1
+ import { Connection, PublicKey } from "@solana/web3.js";
2
+ /**
3
+ * Full slab layout descriptor. Returned by detectSlabLayout().
4
+ * All engine field offsets are relative to engineOff.
5
+ */
6
+ export interface SlabLayout {
7
+ version: 0 | 1 | 2;
8
+ headerLen: number;
9
+ configOffset: number;
10
+ configLen: number;
11
+ reservedOff: number;
12
+ engineOff: number;
13
+ accountSize: number;
14
+ maxAccounts: number;
15
+ bitmapWords: number;
16
+ accountsOff: number;
17
+ engineInsuranceOff: number;
18
+ engineParamsOff: number;
19
+ paramsSize: number;
20
+ engineCurrentSlotOff: number;
21
+ engineFundingIndexOff: number;
22
+ engineLastFundingSlotOff: number;
23
+ engineFundingRateBpsOff: number;
24
+ engineMarkPriceOff: number;
25
+ engineLastCrankSlotOff: number;
26
+ engineMaxCrankStalenessOff: number;
27
+ engineTotalOiOff: number;
28
+ engineLongOiOff: number;
29
+ engineShortOiOff: number;
30
+ engineCTotOff: number;
31
+ enginePnlPosTotOff: number;
32
+ engineLiqCursorOff: number;
33
+ engineGcCursorOff: number;
34
+ engineLastSweepStartOff: number;
35
+ engineLastSweepCompleteOff: number;
36
+ engineCrankCursorOff: number;
37
+ engineSweepStartIdxOff: number;
38
+ engineLifetimeLiquidationsOff: number;
39
+ engineLifetimeForceClosesOff: number;
40
+ engineNetLpPosOff: number;
41
+ engineLpSumAbsOff: number;
42
+ engineLpMaxAbsOff: number;
43
+ engineLpMaxAbsSweepOff: number;
44
+ engineEmergencyOiModeOff: number;
45
+ engineEmergencyStartSlotOff: number;
46
+ engineLastBreakerSlotOff: number;
47
+ engineBitmapOff: number;
48
+ postBitmap: number;
49
+ acctOwnerOff: number;
50
+ hasInsuranceIsolation: boolean;
51
+ engineInsuranceIsolatedOff: number;
52
+ engineInsuranceIsolationBpsOff: number;
53
+ }
54
+ export declare const ENGINE_OFF = 600;
55
+ export declare const ENGINE_MARK_PRICE_OFF = 400;
56
+ /**
57
+ * V2 slab tier sizes (small and large) for discovery.
58
+ * V2 uses ENGINE_OFF=600, BITMAP_OFF=432, ACCOUNT_SIZE=248, postBitmap=18.
59
+ * Sizes overlap with V1D (postBitmap=2) — disambiguation requires reading the version field.
60
+ */
61
+ export declare const SLAB_TIERS_V2: {
62
+ readonly small: {
63
+ readonly maxAccounts: 256;
64
+ readonly dataSize: 65088;
65
+ readonly label: "Small";
66
+ readonly description: "256 slots (V2 BPF intermediate)";
67
+ };
68
+ readonly large: {
69
+ readonly maxAccounts: 4096;
70
+ readonly dataSize: 1025568;
71
+ readonly label: "Large";
72
+ readonly description: "4,096 slots (V2 BPF intermediate)";
73
+ };
74
+ };
75
+ /**
76
+ * V1M slab tier sizes — mainnet-deployed V1 program (ESa89R5).
77
+ * ENGINE_OFF=640, BITMAP_OFF=726, ACCOUNT_SIZE=248, postBitmap=18.
78
+ * Expanded RiskParams (336 bytes) and trade_twap runtime fields.
79
+ * Confirmed by on-chain probing of slab 8NY7rvQ (SOL/USDC Perpetual, 257512 bytes).
80
+ */
81
+ export declare const SLAB_TIERS_V1M: Record<string, {
82
+ maxAccounts: number;
83
+ dataSize: number;
84
+ label: string;
85
+ description: string;
86
+ }>;
87
+ /**
88
+ * V_ADL slab tier sizes — PERC-8270/8271 ADL-upgraded program.
89
+ * ENGINE_OFF=624, BITMAP_OFF=1006, ACCOUNT_SIZE=312, postBitmap=18.
90
+ * New account layout adds ADL tracking fields (+64 bytes/account including alignment padding).
91
+ * BPF SLAB_LEN verified by cargo build-sbf in PERC-8271: large (4096) = 1288304 bytes.
92
+ */
93
+ export declare const SLAB_TIERS_V_ADL: Record<string, {
94
+ maxAccounts: number;
95
+ dataSize: number;
96
+ label: string;
97
+ description: string;
98
+ }>;
99
+ /**
100
+ * Detect the slab layout version from the raw account data length.
101
+ * Returns the full SlabLayout descriptor, or null if the size is unrecognised.
102
+ * Checks V_ADL, V1M, V0, V1D, V1D-legacy, V1, and V1-legacy sizes in priority order.
103
+ *
104
+ * When `data` is provided and the size matches V1D, the version field at offset 8 is read
105
+ * to disambiguate V2 slabs (which produce identical sizes to V1D with postBitmap=2).
106
+ * V2 slabs have version===2 at offset 8 (u32 LE).
107
+ *
108
+ * @param dataLen - The slab account data length in bytes
109
+ * @param data - Optional raw slab data for version-field disambiguation
110
+ */
111
+ export declare function detectSlabLayout(dataLen: number, data?: Uint8Array): SlabLayout | null;
112
+ /**
113
+ * Legacy detectLayout for backward compat.
114
+ * Returns { bitmapWords, accountsOff, maxAccounts } or null.
115
+ *
116
+ * GH#1238: previously recomputed accountsOff with hardcoded postBitmap=18, which gave a value
117
+ * 16 bytes too large for V1D slabs (which use postBitmap=2). Now delegates directly to the
118
+ * SlabLayout descriptor so each variant uses its own correct accountsOff.
119
+ */
120
+ export declare function detectLayout(dataLen: number): {
121
+ bitmapWords: number;
122
+ accountsOff: number;
123
+ maxAccounts: number;
124
+ } | null;
125
+ export interface SlabHeader {
126
+ magic: bigint;
127
+ version: number;
128
+ bump: number;
129
+ flags: number;
130
+ resolved: boolean;
131
+ paused: boolean;
132
+ admin: PublicKey;
133
+ nonce: bigint;
134
+ lastThrUpdateSlot: bigint;
135
+ }
136
+ export interface MarketConfig {
137
+ collateralMint: PublicKey;
138
+ vaultPubkey: PublicKey;
139
+ indexFeedId: PublicKey;
140
+ maxStalenessSlots: bigint;
141
+ confFilterBps: number;
142
+ vaultAuthorityBump: number;
143
+ invert: number;
144
+ unitScale: number;
145
+ fundingHorizonSlots: bigint;
146
+ fundingKBps: bigint;
147
+ fundingInvScaleNotionalE6: bigint;
148
+ fundingMaxPremiumBps: bigint;
149
+ fundingMaxBpsPerSlot: bigint;
150
+ fundingPremiumWeightBps: bigint;
151
+ fundingSettlementIntervalSlots: bigint;
152
+ fundingPremiumDampeningE6: bigint;
153
+ fundingPremiumMaxBpsPerSlot: bigint;
154
+ threshFloor: bigint;
155
+ threshRiskBps: bigint;
156
+ threshUpdateIntervalSlots: bigint;
157
+ threshStepBps: bigint;
158
+ threshAlphaBps: bigint;
159
+ threshMin: bigint;
160
+ threshMax: bigint;
161
+ threshMinStep: bigint;
162
+ oracleAuthority: PublicKey;
163
+ authorityPriceE6: bigint;
164
+ authorityTimestamp: bigint;
165
+ oraclePriceCapE2bps: bigint;
166
+ lastEffectivePriceE6: bigint;
167
+ oiCapMultiplierBps: bigint;
168
+ maxPnlCap: bigint;
169
+ adaptiveFundingEnabled: boolean;
170
+ adaptiveScaleBps: number;
171
+ adaptiveMaxFundingBps: bigint;
172
+ marketCreatedSlot: bigint;
173
+ oiRampSlots: bigint;
174
+ resolvedSlot: bigint;
175
+ insuranceIsolationBps: number;
176
+ /** PERC-622: Oracle phase (0=Nascent, 1=Growing, 2=Mature) */
177
+ oraclePhase: number;
178
+ /** PERC-622: Cumulative trade volume in e6 format */
179
+ cumulativeVolumeE6: bigint;
180
+ /** PERC-622: Slots elapsed from market creation to Phase 2 entry (u24) */
181
+ phase2DeltaSlots: number;
182
+ }
183
+ export interface InsuranceFund {
184
+ balance: bigint;
185
+ feeRevenue: bigint;
186
+ isolatedBalance: bigint;
187
+ isolationBps: number;
188
+ }
189
+ export interface RiskParams {
190
+ warmupPeriodSlots: bigint;
191
+ maintenanceMarginBps: bigint;
192
+ initialMarginBps: bigint;
193
+ tradingFeeBps: bigint;
194
+ maxAccounts: bigint;
195
+ newAccountFee: bigint;
196
+ riskReductionThreshold: bigint;
197
+ maintenanceFeePerSlot: bigint;
198
+ maxCrankStalenessSlots: bigint;
199
+ liquidationFeeBps: bigint;
200
+ liquidationFeeCap: bigint;
201
+ liquidationBufferBps: bigint;
202
+ minLiquidationAbs: bigint;
203
+ }
204
+ export interface EngineState {
205
+ vault: bigint;
206
+ insuranceFund: InsuranceFund;
207
+ currentSlot: bigint;
208
+ fundingIndexQpbE6: bigint;
209
+ lastFundingSlot: bigint;
210
+ fundingRateBpsPerSlotLast: bigint;
211
+ lastCrankSlot: bigint;
212
+ maxCrankStalenessSlots: bigint;
213
+ totalOpenInterest: bigint;
214
+ longOi: bigint;
215
+ shortOi: bigint;
216
+ cTot: bigint;
217
+ pnlPosTot: bigint;
218
+ liqCursor: number;
219
+ gcCursor: number;
220
+ lastSweepStartSlot: bigint;
221
+ lastSweepCompleteSlot: bigint;
222
+ crankCursor: number;
223
+ sweepStartIdx: number;
224
+ lifetimeLiquidations: bigint;
225
+ lifetimeForceCloses: bigint;
226
+ netLpPos: bigint;
227
+ lpSumAbs: bigint;
228
+ lpMaxAbs: bigint;
229
+ lpMaxAbsSweep: bigint;
230
+ emergencyOiMode: boolean;
231
+ emergencyStartSlot: bigint;
232
+ lastBreakerSlot: bigint;
233
+ numUsedAccounts: number;
234
+ nextAccountId: bigint;
235
+ markPriceE6: bigint;
236
+ }
237
+ export declare enum AccountKind {
238
+ User = 0,
239
+ LP = 1
240
+ }
241
+ export interface Account {
242
+ kind: AccountKind;
243
+ accountId: bigint;
244
+ capital: bigint;
245
+ pnl: bigint;
246
+ reservedPnl: bigint;
247
+ warmupStartedAtSlot: bigint;
248
+ warmupSlopePerStep: bigint;
249
+ positionSize: bigint;
250
+ entryPrice: bigint;
251
+ fundingIndex: bigint;
252
+ matcherProgram: PublicKey;
253
+ matcherContext: PublicKey;
254
+ owner: PublicKey;
255
+ feeCredits: bigint;
256
+ lastFeeSlot: bigint;
257
+ }
258
+ export declare function fetchSlab(connection: Connection, slabPubkey: PublicKey): Promise<Uint8Array>;
259
+ export declare const RAMP_START_BPS = 1000n;
260
+ export declare const DEFAULT_OI_RAMP_SLOTS = 432000n;
261
+ export declare function computeEffectiveOiCapBps(config: MarketConfig, currentSlot: bigint): bigint;
262
+ export declare function readNonce(data: Uint8Array): bigint;
263
+ export declare function readLastThrUpdateSlot(data: Uint8Array): bigint;
264
+ /**
265
+ * Parse slab header (first 72 bytes — layout-independent).
266
+ */
267
+ export declare function parseHeader(data: Uint8Array): SlabHeader;
268
+ /**
269
+ * Parse market config. Layout-version aware.
270
+ * For V0 slabs, fields beyond the basic config are read if present in the data,
271
+ * otherwise defaults are returned.
272
+ *
273
+ * @param data - Slab data (may be a partial slice for discovery; pass layoutHint in that case)
274
+ * @param layoutHint - Pre-detected layout to use; if omitted, detected from data.length.
275
+ */
276
+ export declare function parseConfig(data: Uint8Array, layoutHint?: SlabLayout | null): MarketConfig;
277
+ /**
278
+ * Parse RiskParams from engine data. Layout-version aware.
279
+ * For V0 slabs, extended params (risk_threshold, maintenance_fee, etc.) are
280
+ * not present on-chain, so defaults (0) are returned.
281
+ *
282
+ * @param data - Slab data (may be a partial slice; pass layoutHint in that case)
283
+ * @param layoutHint - Pre-detected layout to use; if omitted, detected from data.length.
284
+ */
285
+ export declare function parseParams(data: Uint8Array, layoutHint?: SlabLayout | null): RiskParams;
286
+ /**
287
+ * Parse RiskEngine state (excluding accounts array). Layout-version aware.
288
+ */
289
+ export declare function parseEngine(data: Uint8Array): EngineState;
290
+ /**
291
+ * Read bitmap to get list of used account indices.
292
+ */
293
+ /**
294
+ * Return all account indices whose bitmap bit is set (i.e. slot is in use).
295
+ * Uses the layout-aware bitmap offset so V1_LEGACY slabs (bitmap at rel+672) are handled correctly.
296
+ */
297
+ export declare function parseUsedIndices(data: Uint8Array): number[];
298
+ /**
299
+ * Check if a specific account index is used.
300
+ */
301
+ export declare function isAccountUsed(data: Uint8Array, idx: number): boolean;
302
+ /**
303
+ * Calculate the maximum valid account index for a given slab size.
304
+ */
305
+ export declare function maxAccountIndex(dataLen: number): number;
306
+ /**
307
+ * Parse a single account by index.
308
+ */
309
+ export declare function parseAccount(data: Uint8Array, idx: number): Account;
310
+ /**
311
+ * Parse all used accounts.
312
+ */
313
+ export declare function parseAllAccounts(data: Uint8Array): {
314
+ idx: number;
315
+ account: Account;
316
+ }[];