@percolatorct/sdk 1.0.0-beta.3 → 1.0.0-beta.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,13 +1,16 @@
1
1
  // src/abi/encode.ts
2
2
  import { PublicKey } from "@solana/web3.js";
3
+ var U8_MAX = 255;
4
+ var U16_MAX = 65535;
5
+ var U32_MAX = 4294967295;
3
6
  function encU8(val) {
4
- if (!Number.isInteger(val) || val < 0 || val > 255) {
7
+ if (!Number.isInteger(val) || val < 0 || val > U8_MAX) {
5
8
  throw new Error(`encU8: value out of range (0..255), got ${val}`);
6
9
  }
7
10
  return new Uint8Array([val]);
8
11
  }
9
12
  function encU16(val) {
10
- if (!Number.isInteger(val) || val < 0 || val > 65535) {
13
+ if (!Number.isInteger(val) || val < 0 || val > U16_MAX) {
11
14
  throw new Error(`encU16: value out of range (0..65535), got ${val}`);
12
15
  }
13
16
  const buf = new Uint8Array(2);
@@ -15,7 +18,7 @@ function encU16(val) {
15
18
  return buf;
16
19
  }
17
20
  function encU32(val) {
18
- if (!Number.isInteger(val) || val < 0 || val > 4294967295) {
21
+ if (!Number.isInteger(val) || val < 0 || val > U32_MAX) {
19
22
  throw new Error(`encU32: value out of range (0..4294967295), got ${val}`);
20
23
  }
21
24
  const buf = new Uint8Array(4);
@@ -93,7 +96,6 @@ function concatBytes(...arrays) {
93
96
  }
94
97
 
95
98
  // src/abi/instructions.ts
96
- var MAX_ORACLE_PRICE = 1000000000000n;
97
99
  var IX_TAG = {
98
100
  InitMarket: 0,
99
101
  InitUser: 1,
@@ -111,21 +113,33 @@ var IX_TAG = {
111
113
  CloseSlab: 13,
112
114
  UpdateConfig: 14,
113
115
  SetMaintenanceFee: 15,
114
- SetOracleAuthority: 16,
115
- PushOraclePrice: 17,
116
+ // 16, 17 — removed in v1.0.0-beta.29 (Phase G admin-push oracle removal)
116
117
  SetOraclePriceCap: 18,
117
118
  ResolveMarket: 19,
118
119
  WithdrawInsurance: 20,
119
120
  AdminForceClose: 21,
121
+ // Tags 22-23: on-chain these are SetInsuranceWithdrawPolicy / WithdrawInsuranceLimited.
122
+ // Legacy aliases (UpdateRiskParams/RenounceAdmin) kept for backward compat.
123
+ SetInsuranceWithdrawPolicy: 22,
124
+ /** @deprecated Use SetInsuranceWithdrawPolicy */
120
125
  UpdateRiskParams: 22,
126
+ WithdrawInsuranceLimited: 23,
127
+ /** @deprecated Use WithdrawInsuranceLimited */
121
128
  RenounceAdmin: 23,
122
- // Tags 24–26 (CreateInsuranceMint / DepositInsuranceLP / WithdrawInsuranceLP)
123
- // were removed in SDK v1.0.0-beta.3. Replaced by percolator-stake.
124
- PauseMarket: 27,
125
- UnpauseMarket: 28,
126
- AcceptAdmin: 29,
127
- SetInsuranceWithdrawPolicy: 30,
128
- WithdrawInsuranceLimited: 31,
129
+ // Tags 24–26: on-chain = QueryLpFees/ReclaimEmptyAccount/SettleAccount.
130
+ // Old insurance LP tags removed those moved to percolator-stake.
131
+ QueryLpFees: 24,
132
+ ReclaimEmptyAccount: 25,
133
+ SettleAccount: 26,
134
+ // Tags 27-28: on-chain = DepositFeeCredits/ConvertReleasedPnl.
135
+ DepositFeeCredits: 27,
136
+ ConvertReleasedPnl: 28,
137
+ // Tags 29-30: on-chain = ResolvePermissionless/ForceCloseResolved.
138
+ ResolvePermissionless: 29,
139
+ // Note: `AcceptAdmin` used to be a @deprecated alias for tag 29; removed in
140
+ // beta.27 because AcceptAdmin is now a real instruction at tag 82 (Phase E).
141
+ ForceCloseResolved: 30,
142
+ // Tag 31: gap (no decode arm on-chain)
129
143
  SetPythOracle: 32,
130
144
  UpdateMarkPrice: 33,
131
145
  UpdateHyperpMark: 34,
@@ -170,8 +184,7 @@ var IX_TAG = {
170
184
  AttestCrossMargin: 55,
171
185
  /** PERC-622: Advance oracle phase (permissionless crank) */
172
186
  AdvanceOraclePhase: 56,
173
- /** PERC-623: Top up a market's keeper fund (permissionless) */
174
- TopUpKeeperFund: 57,
187
+ // 57: removed (keeper fund)
175
188
  /** PERC-629: Slash a market creator's deposit (permissionless) */
176
189
  SlashCreationDeposit: 58,
177
190
  /** PERC-628: Initialize the global shared vault (admin) */
@@ -207,7 +220,22 @@ var IX_TAG = {
207
220
  /** PERC-SetDexPool: Pin admin-approved DEX pool address for a HYPERP market (admin). */
208
221
  SetDexPool: 74,
209
222
  /** CPI to the matcher program to initialize a matcher context account for an LP slot. Admin-only. */
210
- InitMatcherCtx: 75
223
+ InitMatcherCtx: 75,
224
+ /** PauseMarket (tag 76): admin emergency pause. Blocks Trade/Deposit/Withdraw/InitUser. */
225
+ PauseMarket: 76,
226
+ /** UnpauseMarket (tag 77): admin unpause. Re-enables all operations. */
227
+ UnpauseMarket: 77,
228
+ /** PERC-305 / SECURITY(H-4): Set PnL cap for ADL pre-check (admin only). */
229
+ SetMaxPnlCap: 78,
230
+ /** PERC-309: Set OI cap multiplier for LP withdrawal limits (admin only). Packed u64. */
231
+ SetOiCapMultiplier: 79,
232
+ /** PERC-314: Set dispute params (window_slots + bond_amount, admin only). */
233
+ SetDisputeParams: 80,
234
+ /** PERC-315: Set LP collateral params (enabled + ltv_bps, admin only). */
235
+ SetLpCollateralParams: 81,
236
+ /** Phase E (2026-04-17): Accept a pending admin transfer. Signer must match pending_admin. */
237
+ AcceptAdmin: 82
238
+ // 78: removed (keeper fund)
211
239
  };
212
240
  Object.freeze(IX_TAG);
213
241
  var HEX_RE = /^[0-9a-fA-F]{64}$/;
@@ -230,9 +258,29 @@ function encodeFeedId(feedId) {
230
258
  }
231
259
  return bytes;
232
260
  }
233
- var INIT_MARKET_DATA_LEN = 264;
261
+ var INIT_MARKET_BASE_LEN = 344;
262
+ var INIT_MARKET_EXTENDED_TAIL_LEN = 66;
263
+ function extendedTailHasNonZero(t) {
264
+ const toBigInt = (v) => typeof v === "string" ? BigInt(v) : v;
265
+ return t.insuranceWithdrawMaxBps !== 0 || toBigInt(t.insuranceWithdrawCooldownSlots) !== 0n || toBigInt(t.permissionlessResolveStaleSlots) !== 0n || toBigInt(t.fundingHorizonSlots) !== 0n || toBigInt(t.fundingKBps) !== 0n || toBigInt(t.fundingMaxPremiumBps) !== 0n || toBigInt(t.fundingMaxBpsPerSlot) !== 0n || toBigInt(t.markMinFee) !== 0n || toBigInt(t.forceCloseDelaySlots) !== 0n;
266
+ }
267
+ function encodeExtendedTail(t) {
268
+ return concatBytes(
269
+ encU16(t.insuranceWithdrawMaxBps),
270
+ encU64(t.insuranceWithdrawCooldownSlots),
271
+ encU64(t.permissionlessResolveStaleSlots),
272
+ encU64(t.fundingHorizonSlots),
273
+ encU64(t.fundingKBps),
274
+ encI64(t.fundingMaxPremiumBps),
275
+ encI64(t.fundingMaxBpsPerSlot),
276
+ encU64(t.markMinFee),
277
+ encU64(t.forceCloseDelaySlots)
278
+ );
279
+ }
234
280
  function encodeInitMarket(args) {
235
- const data = concatBytes(
281
+ const hMin = args.hMin ?? args.warmupPeriodSlots ?? 0n;
282
+ const hMax = args.hMax ?? args.warmupPeriodSlots ?? 0n;
283
+ const base = concatBytes(
236
284
  encU8(IX_TAG.InitMarket),
237
285
  encPubkey(args.admin),
238
286
  encPubkey(args.collateralMint),
@@ -242,26 +290,49 @@ function encodeInitMarket(args) {
242
290
  encU8(args.invert),
243
291
  encU32(args.unitScale),
244
292
  encU64(args.initialMarkPriceE6),
245
- encU64(args.warmupPeriodSlots),
293
+ // 3 fields between header and RiskParams (immutable after init)
294
+ encU128(args.maxMaintenanceFeePerSlot ?? 0n),
295
+ encU128(args.maxInsuranceFloor ?? 0n),
296
+ encU64(args.minOraclePriceCap ?? 0n),
297
+ // RiskParams wire format — must match read_risk_params() in percolator.rs
298
+ // In v12.15: warmup_period_slots replaced by hMin/hMax. hMin is written first (same slot),
299
+ // hMax appended at end. liquidationBufferBps is read but discarded (kept for wire compat).
300
+ encU64(hMin),
246
301
  encU64(args.maintenanceMarginBps),
247
302
  encU64(args.initialMarginBps),
248
303
  encU64(args.tradingFeeBps),
249
304
  encU64(args.maxAccounts),
250
305
  encU128(args.newAccountFee),
251
- encU128(args.riskReductionThreshold),
252
- encU128(args.maintenanceFeePerSlot),
306
+ encU128(args.insuranceFloor ?? 0n),
307
+ // wire slot: old riskReductionThreshold → now insurance_floor
308
+ encU64(hMax),
309
+ // h_max (u64)
253
310
  encU64(args.maxCrankStalenessSlots),
311
+ // v12.17: no padding between hMax and maxCrankStalenessSlots
254
312
  encU64(args.liquidationFeeBps),
255
313
  encU128(args.liquidationFeeCap),
256
- encU64(args.liquidationBufferBps),
257
- encU128(args.minLiquidationAbs)
314
+ encU64(args.liquidationBufferBps ?? 0n),
315
+ // v12.17: read as resolve_price_deviation_bps by program
316
+ encU128(args.minLiquidationAbs),
317
+ encU128(args.minInitialDeposit),
318
+ encU128(args.minNonzeroMmReq),
319
+ encU128(args.minNonzeroImReq)
258
320
  );
259
- if (data.length !== INIT_MARKET_DATA_LEN) {
321
+ if (base.length !== INIT_MARKET_BASE_LEN) {
260
322
  throw new Error(
261
- `encodeInitMarket: expected ${INIT_MARKET_DATA_LEN} bytes, got ${data.length}`
323
+ `encodeInitMarket: base payload expected ${INIT_MARKET_BASE_LEN} bytes, got ${base.length}`
262
324
  );
263
325
  }
264
- return data;
326
+ if (args.extendedTail && extendedTailHasNonZero(args.extendedTail)) {
327
+ const tail = encodeExtendedTail(args.extendedTail);
328
+ if (tail.length !== INIT_MARKET_EXTENDED_TAIL_LEN) {
329
+ throw new Error(
330
+ `encodeInitMarket: extended tail expected ${INIT_MARKET_EXTENDED_TAIL_LEN} bytes, got ${tail.length}`
331
+ );
332
+ }
333
+ return concatBytes(base, tail);
334
+ }
335
+ return base;
265
336
  }
266
337
  function encodeInitUser(args) {
267
338
  return concatBytes(encU8(IX_TAG.InitUser), encU64(args.feePayment));
@@ -288,12 +359,28 @@ function encodeWithdrawCollateral(args) {
288
359
  encU64(args.amount)
289
360
  );
290
361
  }
362
+ var LiquidationPolicyTag = {
363
+ FullClose: 0,
364
+ ExactPartial: 1,
365
+ TouchOnly: 255
366
+ };
291
367
  function encodeKeeperCrank(args) {
292
- return concatBytes(
368
+ const parts = [
293
369
  encU8(IX_TAG.KeeperCrank),
294
370
  encU16(args.callerIdx),
295
- encU8(args.allowPanic ? 1 : 0)
296
- );
371
+ encU8(1)
372
+ // format_version = 1 (REQUIRED by v12.17)
373
+ ];
374
+ if (args.candidates) {
375
+ for (const c of args.candidates) {
376
+ parts.push(encU16(c.idx));
377
+ parts.push(encU8(c.policy));
378
+ if (c.policy === LiquidationPolicyTag.ExactPartial) {
379
+ parts.push(encU128(c.quantity));
380
+ }
381
+ }
382
+ }
383
+ return concatBytes(...parts);
297
384
  }
298
385
  function encodeTradeNoCpi(args) {
299
386
  return concatBytes(
@@ -320,7 +407,8 @@ function encodeTradeCpi(args) {
320
407
  encU8(IX_TAG.TradeCpi),
321
408
  encU16(args.lpIdx),
322
409
  encU16(args.userIdx),
323
- encI128(args.size)
410
+ encI128(args.size),
411
+ encU64(args.limitPriceE6)
324
412
  );
325
413
  }
326
414
  function encodeTradeCpiV2(args) {
@@ -332,6 +420,9 @@ function encodeTradeCpiV2(args) {
332
420
  encU8(args.bump)
333
421
  );
334
422
  }
423
+ function encodeUnresolveMarket(args) {
424
+ return concatBytes(encU8(IX_TAG.UnresolveMarket), encU64(args.confirmation));
425
+ }
335
426
  function encodeSetRiskThreshold(args) {
336
427
  return concatBytes(
337
428
  encU8(IX_TAG.SetRiskThreshold),
@@ -349,19 +440,10 @@ function encodeUpdateConfig(args) {
349
440
  encU8(IX_TAG.UpdateConfig),
350
441
  encU64(args.fundingHorizonSlots),
351
442
  encU64(args.fundingKBps),
352
- encU128(args.fundingInvScaleNotionalE6),
353
443
  encI64(args.fundingMaxPremiumBps),
354
444
  // Rust: i64 (can be negative)
355
- encI64(args.fundingMaxBpsPerSlot),
445
+ encI64(args.fundingMaxBpsPerSlot)
356
446
  // Rust: i64 (can be negative)
357
- encU128(args.threshFloor),
358
- encU64(args.threshRiskBps),
359
- encU64(args.threshUpdateIntervalSlots),
360
- encU64(args.threshStepBps),
361
- encU64(args.threshAlphaBps),
362
- encU128(args.threshMin),
363
- encU128(args.threshMax),
364
- encU128(args.threshMinStep)
365
447
  );
366
448
  }
367
449
  function encodeSetMaintenanceFee(args) {
@@ -370,26 +452,6 @@ function encodeSetMaintenanceFee(args) {
370
452
  encU128(args.newFee)
371
453
  );
372
454
  }
373
- function encodeSetOracleAuthority(args) {
374
- return concatBytes(
375
- encU8(IX_TAG.SetOracleAuthority),
376
- encPubkey(args.newAuthority)
377
- );
378
- }
379
- function encodePushOraclePrice(args) {
380
- const price = typeof args.priceE6 === "string" ? BigInt(args.priceE6) : args.priceE6;
381
- if (price === 0n) {
382
- throw new Error("encodePushOraclePrice: price cannot be zero (division by zero in engine)");
383
- }
384
- if (price > MAX_ORACLE_PRICE) {
385
- throw new Error(`encodePushOraclePrice: price exceeds maximum (${MAX_ORACLE_PRICE}), got ${price}`);
386
- }
387
- return concatBytes(
388
- encU8(IX_TAG.PushOraclePrice),
389
- encU64(price),
390
- encI64(args.timestamp)
391
- );
392
- }
393
455
  function encodeSetOraclePriceCap(args) {
394
456
  return concatBytes(
395
457
  encU8(IX_TAG.SetOraclePriceCap),
@@ -443,23 +505,18 @@ function encodeSetPythOracle(args) {
443
505
  const dv3 = new DataView(buf.buffer);
444
506
  buf[0] = 32;
445
507
  buf.set(args.feedId, 1);
446
- dv3.setBigUint64(
447
- 33,
448
- args.maxStalenessSecs,
449
- /* little-endian */
450
- true
451
- );
508
+ dv3.setBigUint64(33, args.maxStalenessSecs, true);
452
509
  dv3.setUint16(41, args.confFilterBps, true);
453
510
  return buf;
454
511
  }
455
512
  var PYTH_RECEIVER_PROGRAM_ID = "rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ";
456
513
  async function derivePythPriceUpdateAccount(feedId, shardId = 0) {
457
- const { PublicKey: PublicKey15 } = await import("@solana/web3.js");
514
+ const { PublicKey: PublicKey16 } = await import("@solana/web3.js");
458
515
  const shardBuf = new Uint8Array(2);
459
516
  new DataView(shardBuf.buffer).setUint16(0, shardId, true);
460
- const [pda] = PublicKey15.findProgramAddressSync(
517
+ const [pda] = PublicKey16.findProgramAddressSync(
461
518
  [shardBuf, feedId],
462
- new PublicKey15(PYTH_RECEIVER_PROGRAM_ID)
519
+ new PublicKey16(PYTH_RECEIVER_PROGRAM_ID)
463
520
  );
464
521
  return pda.toBase58();
465
522
  }
@@ -570,9 +627,6 @@ function checkPhaseTransition(currentSlot, marketCreatedSlot, oraclePhase, cumul
570
627
  return [ORACLE_PHASE_MATURE, false];
571
628
  }
572
629
  }
573
- function encodeTopUpKeeperFund(args) {
574
- return concatBytes(encU8(IX_TAG.TopUpKeeperFund), encU64(args.amount));
575
- }
576
630
  function encodeSlashCreationDeposit() {
577
631
  return encU8(IX_TAG.SlashCreationDeposit);
578
632
  }
@@ -642,6 +696,105 @@ function encodeInitMatcherCtx(args) {
642
696
  encU16(args.skewSpreadMultBps)
643
697
  );
644
698
  }
699
+ function encodeSetInsuranceWithdrawPolicy(args) {
700
+ return concatBytes(encU8(IX_TAG.SetInsuranceWithdrawPolicy), encPubkey(args.authority), encU64(args.minWithdrawBase), encU16(args.maxWithdrawBps), encU64(args.cooldownSlots));
701
+ }
702
+ function encodeWithdrawInsuranceLimited(args) {
703
+ return concatBytes(encU8(IX_TAG.WithdrawInsuranceLimited), encU64(args.amount));
704
+ }
705
+ function encodeResolvePermissionless() {
706
+ return concatBytes(encU8(IX_TAG.ResolvePermissionless));
707
+ }
708
+ function encodeForceCloseResolved(args) {
709
+ return concatBytes(encU8(IX_TAG.ForceCloseResolved), encU16(args.userIdx));
710
+ }
711
+ function encodeCreateLpVault(args) {
712
+ const parts = [encU8(IX_TAG.CreateLpVault), encU64(args.feeShareBps)];
713
+ if (args.utilCurveEnabled !== void 0) {
714
+ parts.push(encU8(args.utilCurveEnabled ? 1 : 0));
715
+ }
716
+ return concatBytes(...parts);
717
+ }
718
+ function encodeLpVaultDeposit(args) {
719
+ return concatBytes(encU8(IX_TAG.LpVaultDeposit), encU64(args.amount));
720
+ }
721
+ function encodeLpVaultCrankFees() {
722
+ return concatBytes(encU8(IX_TAG.LpVaultCrankFees));
723
+ }
724
+ function encodeChallengeSettlement(args) {
725
+ return concatBytes(encU8(IX_TAG.ChallengeSettlement), encU64(args.proposedPriceE6));
726
+ }
727
+ function encodeResolveDispute(args) {
728
+ return concatBytes(encU8(IX_TAG.ResolveDispute), encU8(args.accept));
729
+ }
730
+ function encodeDepositLpCollateral(args) {
731
+ return concatBytes(encU8(IX_TAG.DepositLpCollateral), encU16(args.userIdx), encU64(args.lpAmount));
732
+ }
733
+ function encodeWithdrawLpCollateral(args) {
734
+ return concatBytes(encU8(IX_TAG.WithdrawLpCollateral), encU16(args.userIdx), encU64(args.lpAmount));
735
+ }
736
+ function encodeSetOffsetPair(args) {
737
+ return concatBytes(encU8(IX_TAG.SetOffsetPair), encU16(args.offsetBps));
738
+ }
739
+ function encodeAttestCrossMargin(args) {
740
+ return concatBytes(encU8(IX_TAG.AttestCrossMargin), encU16(args.userIdxA), encU16(args.userIdxB));
741
+ }
742
+ function encodeRescueOrphanVault() {
743
+ return concatBytes(encU8(IX_TAG.RescueOrphanVault));
744
+ }
745
+ function encodeCloseOrphanSlab() {
746
+ return concatBytes(encU8(IX_TAG.CloseOrphanSlab));
747
+ }
748
+ function encodeSetDexPool(args) {
749
+ return concatBytes(encU8(IX_TAG.SetDexPool), encPubkey(args.pool));
750
+ }
751
+ function encodeCreateInsuranceMint() {
752
+ return encodeCreateLpVault({ feeShareBps: 0n });
753
+ }
754
+ function encodeDepositInsuranceLP(args) {
755
+ return encodeLpVaultDeposit({ amount: args.amount });
756
+ }
757
+ function encodeWithdrawInsuranceLP(args) {
758
+ return encodeLpVaultWithdraw({ lpAmount: args.lpAmount });
759
+ }
760
+ function encodeSetMaxPnlCap(args) {
761
+ return concatBytes(encU8(IX_TAG.SetMaxPnlCap), encU64(args.cap));
762
+ }
763
+ function encodeSetOiCapMultiplier(args) {
764
+ return concatBytes(encU8(IX_TAG.SetOiCapMultiplier), encU64(args.packed));
765
+ }
766
+ function packOiCap(multiplierBps, softCapBps) {
767
+ if (multiplierBps < 0 || multiplierBps > 4294967295) {
768
+ throw new Error(`packOiCap: multiplier_bps out of u32 range: ${multiplierBps}`);
769
+ }
770
+ if (softCapBps < 0 || softCapBps > 4294967295) {
771
+ throw new Error(`packOiCap: soft_cap_bps out of u32 range: ${softCapBps}`);
772
+ }
773
+ return BigInt(multiplierBps) | BigInt(softCapBps) << 32n;
774
+ }
775
+ function encodeSetDisputeParams(args) {
776
+ return concatBytes(
777
+ encU8(IX_TAG.SetDisputeParams),
778
+ encU64(args.windowSlots),
779
+ encU64(args.bondAmount)
780
+ );
781
+ }
782
+ function encodeSetLpCollateralParams(args) {
783
+ if (args.enabled !== 0 && args.enabled !== 1) {
784
+ throw new Error(`encodeSetLpCollateralParams: enabled must be 0 or 1, got ${args.enabled}`);
785
+ }
786
+ if (args.ltvBps < 0 || args.ltvBps > 1e4) {
787
+ throw new Error(`encodeSetLpCollateralParams: ltvBps ${args.ltvBps} out of range [0, 10000]`);
788
+ }
789
+ return concatBytes(
790
+ encU8(IX_TAG.SetLpCollateralParams),
791
+ encU8(args.enabled),
792
+ encU16(args.ltvBps)
793
+ );
794
+ }
795
+ function encodeAcceptAdmin() {
796
+ return encU8(IX_TAG.AcceptAdmin);
797
+ }
645
798
 
646
799
  // src/abi/accounts.ts
647
800
  import {
@@ -666,14 +819,16 @@ var ACCOUNTS_INIT_USER = [
666
819
  { name: "slab", signer: false, writable: true },
667
820
  { name: "userAta", signer: false, writable: true },
668
821
  { name: "vault", signer: false, writable: true },
669
- { name: "tokenProgram", signer: false, writable: false }
822
+ { name: "tokenProgram", signer: false, writable: false },
823
+ { name: "clock", signer: false, writable: false }
670
824
  ];
671
825
  var ACCOUNTS_INIT_LP = [
672
826
  { name: "user", signer: true, writable: true },
673
827
  { name: "slab", signer: false, writable: true },
674
828
  { name: "userAta", signer: false, writable: true },
675
829
  { name: "vault", signer: false, writable: true },
676
- { name: "tokenProgram", signer: false, writable: false }
830
+ { name: "tokenProgram", signer: false, writable: false },
831
+ { name: "clock", signer: false, writable: false }
677
832
  ];
678
833
  var ACCOUNTS_DEPOSIT_COLLATERAL = [
679
834
  { name: "user", signer: true, writable: true },
@@ -733,6 +888,7 @@ var ACCOUNTS_TRADE_CPI = [
733
888
  { name: "lpOwner", signer: false, writable: false },
734
889
  // LP delegated to matcher - no signature needed
735
890
  { name: "slab", signer: false, writable: true },
891
+ { name: "clock", signer: false, writable: false },
736
892
  { name: "oracle", signer: false, writable: false },
737
893
  { name: "matcherProg", signer: false, writable: false },
738
894
  { name: "matcherCtx", signer: false, writable: true },
@@ -746,10 +902,18 @@ var ACCOUNTS_UPDATE_ADMIN = [
746
902
  { name: "admin", signer: true, writable: true },
747
903
  { name: "slab", signer: false, writable: true }
748
904
  ];
749
- var ACCOUNTS_CLOSE_SLAB = [
750
- { name: "admin", signer: true, writable: true },
905
+ var ACCOUNTS_ACCEPT_ADMIN = [
906
+ { name: "pendingAdmin", signer: true, writable: true },
751
907
  { name: "slab", signer: false, writable: true }
752
908
  ];
909
+ var ACCOUNTS_CLOSE_SLAB = [
910
+ { name: "dest", signer: true, writable: true },
911
+ { name: "slab", signer: false, writable: true },
912
+ { name: "vault", signer: false, writable: true },
913
+ { name: "vaultAuthority", signer: false, writable: false },
914
+ { name: "destAta", signer: false, writable: true },
915
+ { name: "tokenProgram", signer: false, writable: false }
916
+ ];
753
917
  var ACCOUNTS_UPDATE_CONFIG = [
754
918
  { name: "admin", signer: true, writable: true },
755
919
  { name: "slab", signer: false, writable: true }
@@ -758,18 +922,10 @@ var ACCOUNTS_SET_MAINTENANCE_FEE = [
758
922
  { name: "admin", signer: true, writable: true },
759
923
  { name: "slab", signer: false, writable: true }
760
924
  ];
761
- var ACCOUNTS_SET_ORACLE_AUTHORITY = [
762
- { name: "admin", signer: true, writable: true },
763
- { name: "slab", signer: false, writable: true }
764
- ];
765
925
  var ACCOUNTS_SET_ORACLE_PRICE_CAP = [
766
926
  { name: "admin", signer: true, writable: true },
767
927
  { name: "slab", signer: false, writable: true }
768
928
  ];
769
- var ACCOUNTS_PUSH_ORACLE_PRICE = [
770
- { name: "authority", signer: true, writable: true },
771
- { name: "slab", signer: false, writable: true }
772
- ];
773
929
  var ACCOUNTS_RESOLVE_MARKET = [
774
930
  { name: "admin", signer: true, writable: true },
775
931
  { name: "slab", signer: false, writable: true }
@@ -782,6 +938,19 @@ var ACCOUNTS_WITHDRAW_INSURANCE = [
782
938
  { name: "tokenProgram", signer: false, writable: false },
783
939
  { name: "vaultPda", signer: false, writable: false }
784
940
  ];
941
+ var ACCOUNTS_WITHDRAW_INSURANCE_LIMITED_RESOLVED = [
942
+ { name: "authority", signer: true, writable: true },
943
+ { name: "slab", signer: false, writable: true },
944
+ { name: "authorityAta", signer: false, writable: true },
945
+ { name: "vault", signer: false, writable: true },
946
+ { name: "tokenProgram", signer: false, writable: false },
947
+ { name: "vaultPda", signer: false, writable: false },
948
+ { name: "clock", signer: false, writable: false }
949
+ ];
950
+ var ACCOUNTS_WITHDRAW_INSURANCE_LIMITED_LIVE = [
951
+ ...ACCOUNTS_WITHDRAW_INSURANCE_LIMITED_RESOLVED,
952
+ { name: "oracle", signer: false, writable: false }
953
+ ];
785
954
  var ACCOUNTS_PAUSE_MARKET = [
786
955
  { name: "admin", signer: true, writable: true },
787
956
  { name: "slab", signer: false, writable: true }
@@ -816,6 +985,37 @@ function buildAccountMetas(spec, keys) {
816
985
  isWritable: s.writable
817
986
  }));
818
987
  }
988
+ var ACCOUNTS_CREATE_INSURANCE_MINT = [
989
+ { name: "admin", signer: true, writable: false },
990
+ { name: "slab", signer: false, writable: false },
991
+ { name: "insLpMint", signer: false, writable: true },
992
+ { name: "vaultAuthority", signer: false, writable: false },
993
+ { name: "collateralMint", signer: false, writable: false },
994
+ { name: "systemProgram", signer: false, writable: false },
995
+ { name: "tokenProgram", signer: false, writable: false },
996
+ { name: "rent", signer: false, writable: false },
997
+ { name: "payer", signer: true, writable: true }
998
+ ];
999
+ var ACCOUNTS_DEPOSIT_INSURANCE_LP = [
1000
+ { name: "depositor", signer: true, writable: false },
1001
+ { name: "slab", signer: false, writable: true },
1002
+ { name: "depositorAta", signer: false, writable: true },
1003
+ { name: "vault", signer: false, writable: true },
1004
+ { name: "tokenProgram", signer: false, writable: false },
1005
+ { name: "insLpMint", signer: false, writable: true },
1006
+ { name: "depositorLpAta", signer: false, writable: true },
1007
+ { name: "vaultAuthority", signer: false, writable: false }
1008
+ ];
1009
+ var ACCOUNTS_WITHDRAW_INSURANCE_LP = [
1010
+ { name: "withdrawer", signer: true, writable: false },
1011
+ { name: "slab", signer: false, writable: true },
1012
+ { name: "withdrawerAta", signer: false, writable: true },
1013
+ { name: "vault", signer: false, writable: true },
1014
+ { name: "tokenProgram", signer: false, writable: false },
1015
+ { name: "insLpMint", signer: false, writable: true },
1016
+ { name: "withdrawerLpAta", signer: false, writable: true },
1017
+ { name: "vaultAuthority", signer: false, writable: false }
1018
+ ];
819
1019
  var ACCOUNTS_LP_VAULT_WITHDRAW = [
820
1020
  { name: "withdrawer", signer: true, writable: false },
821
1021
  { name: "slab", signer: false, writable: true },
@@ -883,11 +1083,6 @@ var ACCOUNTS_AUDIT_CRANK = [
883
1083
  var ACCOUNTS_ADVANCE_ORACLE_PHASE = [
884
1084
  { name: "slab", signer: false, writable: true }
885
1085
  ];
886
- var ACCOUNTS_TOPUP_KEEPER_FUND = [
887
- { name: "funder", signer: true, writable: true },
888
- { name: "slab", signer: false, writable: true },
889
- { name: "keeperFund", signer: false, writable: true }
890
- ];
891
1086
  var ACCOUNTS_SET_OI_IMBALANCE_HARD_BLOCK = [
892
1087
  { name: "admin", signer: true, writable: false },
893
1088
  { name: "slab", signer: false, writable: true }
@@ -937,6 +1132,11 @@ var ACCOUNTS_SET_WALLET_CAP = [
937
1132
  { name: "admin", signer: true, writable: false },
938
1133
  { name: "slab", signer: false, writable: true }
939
1134
  ];
1135
+ var ACCOUNTS_SET_DEX_POOL = [
1136
+ { name: "admin", signer: true, writable: false },
1137
+ { name: "slab", signer: false, writable: true },
1138
+ { name: "poolAccount", signer: false, writable: false }
1139
+ ];
940
1140
  var ACCOUNTS_INIT_MATCHER_CTX = [
941
1141
  { name: "admin", signer: true, writable: false },
942
1142
  { name: "slab", signer: false, writable: false },
@@ -1228,24 +1428,11 @@ function getErrorName(code) {
1228
1428
  function getErrorHint(code) {
1229
1429
  return PERCOLATOR_ERRORS[code]?.hint;
1230
1430
  }
1231
- var LIGHTHOUSE_PROGRAM_ID_STR = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
1232
- var ANCHOR_ERROR_RANGE_START = 6e3;
1233
- var ANCHOR_ERROR_RANGE_END = 8191;
1234
- var ANCHOR_ERROR_NAMES = {
1235
- 6032: "ConstraintMut",
1236
- 6036: "ConstraintOwner",
1237
- 6038: "ConstraintSeeds",
1238
- 6400: "ConstraintAddress"
1239
- };
1240
- function isAnchorErrorCode(code) {
1241
- return code >= ANCHOR_ERROR_RANGE_START && code <= ANCHOR_ERROR_RANGE_END;
1242
- }
1243
1431
  var CUSTOM_ERROR_HEX_MAX_LEN = 8;
1244
1432
  function parseErrorFromLogs(logs) {
1245
1433
  if (!Array.isArray(logs)) {
1246
1434
  return null;
1247
1435
  }
1248
- let insideLighthouse = false;
1249
1436
  const re = new RegExp(
1250
1437
  `custom program error: 0x([0-9a-fA-F]{1,${CUSTOM_ERROR_HEX_MAX_LEN}})(?![0-9a-fA-F])`,
1251
1438
  "i"
@@ -1254,44 +1441,211 @@ function parseErrorFromLogs(logs) {
1254
1441
  if (typeof log !== "string") {
1255
1442
  continue;
1256
1443
  }
1257
- if (log.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {
1258
- insideLighthouse = true;
1259
- } else if (log.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {
1260
- insideLighthouse = false;
1261
- }
1262
1444
  const match = log.match(re);
1263
1445
  if (match) {
1264
1446
  const code = parseInt(match[1], 16);
1265
1447
  if (!Number.isFinite(code) || code < 0 || code > 4294967295) {
1266
1448
  continue;
1267
1449
  }
1268
- if (isAnchorErrorCode(code) || insideLighthouse) {
1269
- const anchorName = ANCHOR_ERROR_NAMES[code] ?? `AnchorError(0x${code.toString(16)})`;
1270
- return {
1271
- code,
1272
- name: `Lighthouse:${anchorName}`,
1273
- hint: "This error comes from the Lighthouse/Blowfish wallet guard, not from Percolator. The transaction itself is valid. Disable transaction simulation in your wallet settings, or use a wallet without Blowfish protection (e.g., Backpack, Solflare).",
1274
- source: "lighthouse"
1275
- };
1276
- }
1277
1450
  const info = decodeError(code);
1278
1451
  return {
1279
1452
  code,
1280
1453
  name: info?.name ?? `Unknown(${code})`,
1281
- hint: info?.hint,
1282
- source: info ? "percolator" : "unknown"
1454
+ hint: info?.hint
1283
1455
  };
1284
1456
  }
1285
1457
  }
1286
1458
  return null;
1287
1459
  }
1288
1460
 
1289
- // src/solana/slab.ts
1461
+ // src/abi/nft.ts
1462
+ import { PublicKey as PublicKey4 } from "@solana/web3.js";
1463
+
1464
+ // src/config/program-ids.ts
1290
1465
  import { PublicKey as PublicKey3 } from "@solana/web3.js";
1466
+ function safeEnv(key) {
1467
+ try {
1468
+ return typeof process !== "undefined" && process?.env ? process.env[key] : void 0;
1469
+ } catch {
1470
+ return void 0;
1471
+ }
1472
+ }
1473
+ var PROGRAM_IDS = {
1474
+ devnet: {
1475
+ percolator: "FxfD37s1AZTeWfFQps9Zpebi2dNQ9QSSDtfMKdbsfKrD",
1476
+ matcher: "GTRgyTDfrMvBubALAqtHuQwT8tbGyXid7svXZKtWfC9k"
1477
+ },
1478
+ mainnet: {
1479
+ percolator: "ESa89R5Es3rJ5mnwGybVRG1GrNt9etP11Z5V2QWD4edv",
1480
+ matcher: "GDK8wx38kpiSVSfGTVNiSdptX3Z5R4kQyqh6Q3QX6wmi"
1481
+ }
1482
+ };
1483
+ function getProgramId(network) {
1484
+ const override = safeEnv("PROGRAM_ID");
1485
+ if (override) {
1486
+ console.warn(
1487
+ `[percolator-sdk] PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
1488
+ );
1489
+ return new PublicKey3(override);
1490
+ }
1491
+ const detectedNetwork = getCurrentNetwork();
1492
+ const targetNetwork = network ?? detectedNetwork;
1493
+ const programId = PROGRAM_IDS[targetNetwork].percolator;
1494
+ return new PublicKey3(programId);
1495
+ }
1496
+ function getMatcherProgramId(network) {
1497
+ const override = safeEnv("MATCHER_PROGRAM_ID");
1498
+ if (override) {
1499
+ console.warn(
1500
+ `[percolator-sdk] MATCHER_PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
1501
+ );
1502
+ return new PublicKey3(override);
1503
+ }
1504
+ const detectedNetwork = getCurrentNetwork();
1505
+ const targetNetwork = network ?? detectedNetwork;
1506
+ const programId = PROGRAM_IDS[targetNetwork].matcher;
1507
+ if (!programId) {
1508
+ throw new Error(`Matcher program not deployed on ${targetNetwork}`);
1509
+ }
1510
+ return new PublicKey3(programId);
1511
+ }
1512
+ function getCurrentNetwork() {
1513
+ const network = safeEnv("NETWORK")?.toLowerCase();
1514
+ if (network === "mainnet" || network === "mainnet-beta") {
1515
+ return "mainnet";
1516
+ }
1517
+ return "devnet";
1518
+ }
1519
+
1520
+ // src/abi/nft.ts
1521
+ var NFT_PROGRAM_OVERRIDE = safeEnv("NFT_PROGRAM_ID");
1522
+ var NFT_PROGRAM_ID = new PublicKey4(
1523
+ NFT_PROGRAM_OVERRIDE ?? "FqhKJT9gtScjrmfUuRMjeg7cXNpif1fqsy5Jh65tJmTS"
1524
+ );
1525
+ function getNftProgramId() {
1526
+ return NFT_PROGRAM_ID;
1527
+ }
1528
+ var NFT_IX_TAG = {
1529
+ MintPositionNft: 0,
1530
+ BurnPositionNft: 1,
1531
+ SettleFunding: 2,
1532
+ GetPositionValue: 3,
1533
+ ExecuteTransferHook: 4,
1534
+ EmergencyBurn: 5
1535
+ };
1536
+ function encodeNftMint(userIdx) {
1537
+ const buf = new Uint8Array(3);
1538
+ buf[0] = NFT_IX_TAG.MintPositionNft;
1539
+ buf[1] = userIdx & 255;
1540
+ buf[2] = userIdx >> 8 & 255;
1541
+ return buf;
1542
+ }
1543
+ function encodeNftBurn() {
1544
+ return new Uint8Array([NFT_IX_TAG.BurnPositionNft]);
1545
+ }
1546
+ function encodeNftSettleFunding() {
1547
+ return new Uint8Array([NFT_IX_TAG.SettleFunding]);
1548
+ }
1549
+ function encodeNftEmergencyBurn() {
1550
+ return new Uint8Array([NFT_IX_TAG.EmergencyBurn]);
1551
+ }
1552
+ var ACCOUNTS_NFT_MINT = [
1553
+ "sw",
1554
+ "w",
1555
+ "sw",
1556
+ "w",
1557
+ "r",
1558
+ "r",
1559
+ "r",
1560
+ "r",
1561
+ "r",
1562
+ "w"
1563
+ ];
1564
+ var ACCOUNTS_NFT_BURN = [
1565
+ "s",
1566
+ "w",
1567
+ "w",
1568
+ "w",
1569
+ "r",
1570
+ "r",
1571
+ "r"
1572
+ ];
1573
+ var ACCOUNTS_NFT_EMERGENCY_BURN = [
1574
+ "s",
1575
+ "w",
1576
+ "w",
1577
+ "w",
1578
+ "r",
1579
+ "r",
1580
+ "r"
1581
+ ];
1582
+ var TEXT = new TextEncoder();
1583
+ function idxBuf(userIdx) {
1584
+ const buf = new Uint8Array(2);
1585
+ new DataView(buf.buffer).setUint16(0, userIdx, true);
1586
+ return buf;
1587
+ }
1588
+ function deriveNftPda(slab, userIdx, programId = NFT_PROGRAM_ID) {
1589
+ return PublicKey4.findProgramAddressSync(
1590
+ [TEXT.encode("position_nft"), slab.toBytes(), idxBuf(userIdx)],
1591
+ programId
1592
+ );
1593
+ }
1594
+ function deriveNftMint(slab, userIdx, programId = NFT_PROGRAM_ID) {
1595
+ return PublicKey4.findProgramAddressSync(
1596
+ [TEXT.encode("position_nft_mint"), slab.toBytes(), idxBuf(userIdx)],
1597
+ programId
1598
+ );
1599
+ }
1600
+ function deriveMintAuthority(programId = NFT_PROGRAM_ID) {
1601
+ return PublicKey4.findProgramAddressSync(
1602
+ [TEXT.encode("mint_authority")],
1603
+ programId
1604
+ );
1605
+ }
1606
+ var POSITION_NFT_STATE_LEN = 208;
1607
+ function readI128FromView(view, offset) {
1608
+ const lo = view.getBigUint64(offset, true);
1609
+ const hi = view.getBigUint64(offset + 8, true);
1610
+ const unsigned = hi << 64n | lo;
1611
+ const SIGN_BIT = 1n << 127n;
1612
+ if (unsigned >= SIGN_BIT) {
1613
+ return unsigned - (1n << 128n);
1614
+ }
1615
+ return unsigned;
1616
+ }
1617
+ function parsePositionNftAccount(data) {
1618
+ if (data.length < POSITION_NFT_STATE_LEN) {
1619
+ throw new Error(
1620
+ `PositionNft account too small: ${data.length} < ${POSITION_NFT_STATE_LEN}`
1621
+ );
1622
+ }
1623
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
1624
+ return {
1625
+ version: data[8],
1626
+ bump: data[9],
1627
+ slab: new PublicKey4(data.subarray(16, 48)),
1628
+ userIdx: view.getUint16(48, true),
1629
+ nftMint: new PublicKey4(data.subarray(56, 88)),
1630
+ entryPriceE6: view.getBigUint64(88, true),
1631
+ positionSize: view.getBigUint64(96, true),
1632
+ isLong: data[104] === 1,
1633
+ positionBasisQ: readI128FromView(view, 112),
1634
+ lastFundingIndexE18: readI128FromView(view, 128),
1635
+ mintedAt: view.getBigInt64(144, true),
1636
+ accountId: view.getBigUint64(152, true)
1637
+ };
1638
+ }
1639
+
1640
+ // src/solana/slab.ts
1641
+ import { PublicKey as PublicKey5 } from "@solana/web3.js";
1291
1642
  function dv(data) {
1292
1643
  return new DataView(data.buffer, data.byteOffset, data.byteLength);
1293
1644
  }
1294
1645
  function readU8(data, off) {
1646
+ if (off >= data.length) {
1647
+ throw new RangeError(`readU8: offset ${off} out of bounds (length ${data.length})`);
1648
+ }
1295
1649
  return data[off];
1296
1650
  }
1297
1651
  function readU16LE(data, off) {
@@ -1322,6 +1676,7 @@ function readU128LE(buf, offset) {
1322
1676
  return hi << 64n | lo;
1323
1677
  }
1324
1678
  var MAGIC = 0x504552434f4c4154n;
1679
+ var SLAB_MAGIC = MAGIC;
1325
1680
  var FLAG_RESOLVED = 1 << 0;
1326
1681
  var V0_HEADER_LEN = 72;
1327
1682
  var V0_CONFIG_LEN = 408;
@@ -1491,9 +1846,29 @@ var V_ADL_ACCT_FEE_CREDITS_OFF = 224;
1491
1846
  var V_ADL_ACCT_LAST_FEE_SLOT_OFF = 240;
1492
1847
  var V12_1_ENGINE_OFF = 648;
1493
1848
  var V12_1_ACCOUNT_SIZE = 320;
1849
+ var V12_1_ACCOUNT_SIZE_SBF = 280;
1494
1850
  var V12_1_ENGINE_BITMAP_OFF = 1016;
1495
- var V12_1_ENGINE_PARAMS_OFF = 96;
1851
+ var V12_1_ENGINE_PARAMS_OFF_SBF = 32;
1852
+ var V12_1_ENGINE_PARAMS_OFF_HOST = 96;
1853
+ var V12_1_PARAMS_SIZE_SBF = 184;
1496
1854
  var V12_1_PARAMS_SIZE = 352;
1855
+ var V12_1_SBF_OFF_CURRENT_SLOT = 216;
1856
+ var V12_1_SBF_OFF_FUNDING_RATE = 224;
1857
+ var V12_1_SBF_OFF_LAST_CRANK_SLOT = 232;
1858
+ var V12_1_SBF_OFF_MAX_CRANK_STALENESS = 240;
1859
+ var V12_1_SBF_OFF_C_TOT = 248;
1860
+ var V12_1_SBF_OFF_PNL_POS_TOT = 264;
1861
+ var V12_1_SBF_OFF_LIQ_CURSOR = 296;
1862
+ var V12_1_SBF_OFF_GC_CURSOR = 298;
1863
+ var V12_1_SBF_OFF_LAST_SWEEP_START = 304;
1864
+ var V12_1_SBF_OFF_LAST_SWEEP_COMPLETE = 312;
1865
+ var V12_1_SBF_OFF_CRANK_CURSOR = 320;
1866
+ var V12_1_SBF_OFF_SWEEP_START_IDX = 322;
1867
+ var V12_1_SBF_OFF_LIFETIME_LIQUIDATIONS = 328;
1868
+ var V12_1_SBF_OFF_TOTAL_OI = 448;
1869
+ var V12_1_SBF_OFF_LONG_OI = 464;
1870
+ var V12_1_SBF_OFF_SHORT_OI = 480;
1871
+ var V12_1_SBF_OFF_MARK_PRICE_E6 = 560;
1497
1872
  var V12_1_ENGINE_CURRENT_SLOT_OFF = 448;
1498
1873
  var V12_1_ENGINE_FUNDING_RATE_BPS_OFF = 456;
1499
1874
  var V12_1_ENGINE_LAST_CRANK_SLOT_OFF = 464;
@@ -1526,9 +1901,105 @@ var V12_1_ACCT_MATCHER_CONTEXT_OFF = 176;
1526
1901
  var V12_1_ACCT_OWNER_OFF = 208;
1527
1902
  var V12_1_ACCT_FEE_CREDITS_OFF = 240;
1528
1903
  var V12_1_ACCT_LAST_FEE_SLOT_OFF = 256;
1529
- var V12_1_ACCT_POSITION_SIZE_OFF = 296;
1530
- var V12_1_ACCT_ENTRY_PRICE_OFF = 280;
1531
- var V12_1_ACCT_FUNDING_INDEX_OFF = 288;
1904
+ var V12_1_ACCT_POSITION_SIZE_OFF = 88;
1905
+ var V12_1_ACCT_ENTRY_PRICE_OFF = -1;
1906
+ var V12_1_EP_SBF_ACCOUNT_SIZE = 288;
1907
+ var V12_1_EP_ACCT_ENTRY_PRICE_OFF = 144;
1908
+ var V12_1_EP_ACCT_MATCHER_PROGRAM_OFF = 152;
1909
+ var V12_1_EP_ACCT_MATCHER_CONTEXT_OFF = 184;
1910
+ var V12_1_EP_ACCT_OWNER_OFF = 216;
1911
+ var V12_1_EP_ACCT_FEE_CREDITS_OFF = 248;
1912
+ var V12_1_EP_ACCT_LAST_FEE_SLOT_OFF = 264;
1913
+ var V12_15_ENGINE_OFF = 624;
1914
+ var V12_15_ENGINE_OFF_SBF = 616;
1915
+ var V12_15_ACCOUNT_SIZE = 4400;
1916
+ var V12_15_ACCOUNT_SIZE_SMALL = 920;
1917
+ var V12_15_ACCT_ACCOUNT_ID_OFF = 0;
1918
+ var V12_15_ACCT_CAPITAL_OFF = 8;
1919
+ var V12_15_ACCT_KIND_OFF = 24;
1920
+ var V12_15_ACCT_PNL_OFF = 32;
1921
+ var V12_15_ACCT_RESERVED_PNL_OFF = 48;
1922
+ var V12_15_ACCT_POSITION_BASIS_Q_OFF = 64;
1923
+ var V12_15_ACCT_ENTRY_PRICE_OFF = 120;
1924
+ var V12_15_ACCT_MATCHER_PROGRAM_OFF = 128;
1925
+ var V12_15_ACCT_MATCHER_CONTEXT_OFF = 160;
1926
+ var V12_15_ACCT_OWNER_OFF = 192;
1927
+ var V12_15_ACCT_FEE_CREDITS_OFF = 224;
1928
+ var V12_15_ACCT_FEES_EARNED_TOTAL_OFF = 240;
1929
+ var V12_15_ACCT_EXACT_RESERVE_COHORTS_OFF = 256;
1930
+ var V12_15_ACCT_EXACT_COHORT_COUNT_OFF = 4224;
1931
+ var V12_15_ACCT_OVERFLOW_OLDER_OFF = 4240;
1932
+ var V12_15_ACCT_OVERFLOW_OLDER_PRESENT_OFF = 4304;
1933
+ var V12_15_ACCT_OVERFLOW_NEWEST_OFF = 4320;
1934
+ var V12_15_ACCT_OVERFLOW_NEWEST_PRESENT_OFF = 4384;
1935
+ var V12_15_PARAMS_SIZE = 192;
1936
+ var V12_15_PARAMS_MAX_ACCOUNTS_OFF = 24;
1937
+ var V12_15_PARAMS_INSURANCE_FLOOR_OFF = 144;
1938
+ var V12_15_PARAMS_H_MIN_OFF = 160;
1939
+ var V12_15_PARAMS_H_MAX_OFF = 168;
1940
+ var V12_15_ENGINE_PARAMS_OFF = 32;
1941
+ var V12_15_ENGINE_CURRENT_SLOT_OFF = 224;
1942
+ var V12_15_ENGINE_FUNDING_RATE_E9_OFF = 240;
1943
+ var V12_15_ENGINE_C_TOT_OFF = 344;
1944
+ var V12_15_ENGINE_PNL_POS_TOT_OFF = 368;
1945
+ var V12_15_ENGINE_PNL_MATURED_POS_TOT_OFF = 384;
1946
+ var V12_15_ENGINE_BITMAP_OFF = 862;
1947
+ var V12_15_SIZES = /* @__PURE__ */ new Map();
1948
+ var V12_17_ENGINE_OFF = 512;
1949
+ var V12_17_ACCOUNT_SIZE = 368;
1950
+ var V12_17_ENGINE_BITMAP_OFF = 752;
1951
+ var V12_17_RISK_BUF_LEN = 160;
1952
+ var V12_17_ENGINE_OFF_SBF = 504;
1953
+ var V12_17_ACCOUNT_SIZE_SBF = 352;
1954
+ var V12_17_ENGINE_BITMAP_OFF_SBF = 712;
1955
+ var V12_17_ACCT_CAPITAL_OFF = 0;
1956
+ var V12_17_ACCT_KIND_OFF = 16;
1957
+ var V12_17_ACCT_PNL_OFF = 32;
1958
+ var V12_17_ACCT_RESERVED_PNL_OFF = 48;
1959
+ var V12_17_ACCT_POSITION_BASIS_Q_OFF = 64;
1960
+ var V12_17_ACCT_ADL_A_BASIS_OFF = 80;
1961
+ var V12_17_ACCT_ADL_K_SNAP_OFF = 96;
1962
+ var V12_17_ACCT_F_SNAP_OFF = 112;
1963
+ var V12_17_ACCT_ADL_EPOCH_SNAP_OFF = 128;
1964
+ var V12_17_ACCT_MATCHER_PROGRAM_OFF = 136;
1965
+ var V12_17_ACCT_MATCHER_CONTEXT_OFF = 168;
1966
+ var V12_17_ACCT_OWNER_OFF = 200;
1967
+ var V12_17_ACCT_FEE_CREDITS_OFF = 232;
1968
+ var V12_17_ACCT_SCHED_PRESENT_OFF = 248;
1969
+ var V12_17_ACCT_SCHED_REMAINING_Q_OFF = 256;
1970
+ var V12_17_ACCT_SCHED_ANCHOR_Q_OFF = 272;
1971
+ var V12_17_ACCT_SCHED_START_SLOT_OFF = 288;
1972
+ var V12_17_ACCT_SCHED_HORIZON_OFF = 296;
1973
+ var V12_17_ACCT_SCHED_RELEASE_Q_OFF = 304;
1974
+ var V12_17_ACCT_PENDING_PRESENT_OFF = 320;
1975
+ var V12_17_ACCT_PENDING_REMAINING_Q_OFF = 336;
1976
+ var V12_17_ACCT_PENDING_HORIZON_OFF = 352;
1977
+ var V12_17_ACCT_PENDING_CREATED_SLOT_OFF = 360;
1978
+ var V12_17_ENGINE_PARAMS_OFF = 32;
1979
+ var V12_17_ENGINE_CURRENT_SLOT_OFF = 224;
1980
+ var V12_17_ENGINE_MARKET_MODE_OFF = 232;
1981
+ var V12_17_ENGINE_RESOLVED_K_LONG_OFF = 304;
1982
+ var V12_17_ENGINE_RESOLVED_K_SHORT_OFF = 320;
1983
+ var V12_17_ENGINE_RESOLVED_LIVE_PRICE_OFF = 336;
1984
+ var V12_17_ENGINE_C_TOT_OFF = 352;
1985
+ var V12_17_ENGINE_PNL_POS_TOT_OFF = 368;
1986
+ var V12_17_ENGINE_PNL_MATURED_POS_TOT_OFF = 384;
1987
+ var V12_17_ENGINE_NEG_PNL_COUNT_OFF = 648;
1988
+ var V12_17_ENGINE_LAST_ORACLE_PRICE_OFF = 656;
1989
+ var V12_17_ENGINE_FUND_PX_LAST_OFF = 664;
1990
+ var V12_17_ENGINE_F_LONG_NUM_OFF = 688;
1991
+ var V12_17_ENGINE_F_SHORT_NUM_OFF = 704;
1992
+ var V12_17_SBF_ENGINE_CURRENT_SLOT_OFF = 216;
1993
+ var V12_17_SBF_ENGINE_MARKET_MODE_OFF = 224;
1994
+ var V12_17_SBF_ENGINE_C_TOT_OFF = 336;
1995
+ var V12_17_SBF_ENGINE_PNL_POS_TOT_OFF = 352;
1996
+ var V12_17_SBF_ENGINE_PNL_MATURED_POS_TOT_OFF = 368;
1997
+ var V12_17_SBF_ENGINE_NEG_PNL_COUNT_OFF = 616;
1998
+ var V12_17_SBF_ENGINE_LAST_ORACLE_PRICE_OFF = 624;
1999
+ var V12_17_SBF_ENGINE_FUND_PX_LAST_OFF = 632;
2000
+ var V12_17_SBF_ENGINE_F_LONG_NUM_OFF = 648;
2001
+ var V12_17_SBF_ENGINE_F_SHORT_NUM_OFF = 664;
2002
+ var V12_17_SIZES = /* @__PURE__ */ new Map();
1532
2003
  var V1M_ENGINE_OFF = 640;
1533
2004
  var V1M_CONFIG_LEN = 536;
1534
2005
  var V1M_ACCOUNT_SIZE = 248;
@@ -1601,6 +2072,42 @@ for (const n of TIERS) {
1601
2072
  V1M2_SIZES.set(computeSlabSize(V1M2_ENGINE_OFF, V1M2_ENGINE_BITMAP_OFF, V1M2_ACCOUNT_SIZE, n, 18), n);
1602
2073
  V_SETDEXPOOL_SIZES.set(computeSlabSize(V_SETDEXPOOL_ENGINE_OFF, V_ADL_ENGINE_BITMAP_OFF, V_ADL_ACCOUNT_SIZE, n, 18), n);
1603
2074
  V12_1_SIZES.set(computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, n, 18), n);
2075
+ V12_15_SIZES.set(computeSlabSize(V12_15_ENGINE_OFF, V12_15_ENGINE_BITMAP_OFF, V12_15_ACCOUNT_SIZE, n, 18), n);
2076
+ }
2077
+ V12_15_SIZES.set(computeSlabSize(V12_15_ENGINE_OFF, V12_15_ENGINE_BITMAP_OFF, V12_15_ACCOUNT_SIZE, 2048, 18), 2048);
2078
+ V12_15_SIZES.set(237512, 256);
2079
+ var V12_17_TIERS = [256, 1024, 4096];
2080
+ for (const n of V12_17_TIERS) {
2081
+ const bitmapWords = Math.ceil(n / 64);
2082
+ const bitmapBytes = bitmapWords * 8;
2083
+ const postBitmap = 4;
2084
+ const nextFreeBytes = n * 2;
2085
+ const preAccNative = V12_17_ENGINE_BITMAP_OFF + bitmapBytes + postBitmap + nextFreeBytes;
2086
+ const accountsOffNative = Math.ceil(preAccNative / 16) * 16;
2087
+ const nativeSize = V12_17_ENGINE_OFF + accountsOffNative + n * V12_17_ACCOUNT_SIZE + V12_17_RISK_BUF_LEN;
2088
+ V12_17_SIZES.set(nativeSize, n);
2089
+ const preAccSbf = V12_17_ENGINE_BITMAP_OFF_SBF + bitmapBytes + postBitmap + nextFreeBytes;
2090
+ const accountsOffSbf = Math.ceil(preAccSbf / 8) * 8;
2091
+ const sbfSize = V12_17_ENGINE_OFF_SBF + accountsOffSbf + n * V12_17_ACCOUNT_SIZE_SBF + V12_17_RISK_BUF_LEN;
2092
+ V12_17_SIZES.set(sbfSize, n);
2093
+ }
2094
+ var V12_1_SBF_ACCOUNT_SIZE = 280;
2095
+ var V12_1_SBF_ENGINE_OFF = 616;
2096
+ var V12_1_SBF_BITMAP_OFF = 584;
2097
+ for (const [, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Large", 4096]]) {
2098
+ const bitmapBytes = Math.ceil(n / 64) * 8;
2099
+ const preAccLen = V12_1_SBF_BITMAP_OFF + bitmapBytes + 18 + n * 2;
2100
+ const accountsOff = Math.ceil(preAccLen / 8) * 8;
2101
+ const total = V12_1_SBF_ENGINE_OFF + accountsOff + n * V12_1_SBF_ACCOUNT_SIZE;
2102
+ V12_1_SIZES.set(total, n);
2103
+ }
2104
+ var V12_1_EP_SIZES = /* @__PURE__ */ new Map();
2105
+ for (const [, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Large", 4096]]) {
2106
+ const bitmapBytes = Math.ceil(n / 64) * 8;
2107
+ const preAccLen = V12_1_SBF_BITMAP_OFF + bitmapBytes + 18 + n * 2;
2108
+ const accountsOff = Math.ceil(preAccLen / 8) * 8;
2109
+ const total = V12_1_SBF_ENGINE_OFF + accountsOff + n * V12_1_EP_SBF_ACCOUNT_SIZE;
2110
+ V12_1_EP_SIZES.set(total, n);
1604
2111
  }
1605
2112
  var SLAB_TIERS_V2 = {
1606
2113
  small: { maxAccounts: 256, dataSize: 65088, label: "Small", description: "256 slots (V2 BPF intermediate)" },
@@ -2066,6 +2573,19 @@ for (const [label, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Lar
2066
2573
  const size = computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, n, 18);
2067
2574
  SLAB_TIERS_V12_1[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (v12.1)` };
2068
2575
  }
2576
+ var SLAB_TIERS_V12_15 = {};
2577
+ for (const [label, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Medium2048", 2048], ["Large", 4096]]) {
2578
+ const size = computeSlabSize(V12_15_ENGINE_OFF, V12_15_ENGINE_BITMAP_OFF, V12_15_ACCOUNT_SIZE, n, 18);
2579
+ SLAB_TIERS_V12_15[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (v12.15)` };
2580
+ }
2581
+ var SLAB_TIERS_V12_17 = {};
2582
+ for (const [label, n] of [["Small", 256], ["Medium", 1024], ["Large", 4096]]) {
2583
+ const bitmapBytes = Math.ceil(n / 64) * 8;
2584
+ const preAcc = V12_17_ENGINE_BITMAP_OFF_SBF + bitmapBytes + 4 + n * 2;
2585
+ const accountsOff = Math.ceil(preAcc / 8) * 8;
2586
+ const size = V12_17_ENGINE_OFF_SBF + accountsOff + n * V12_17_ACCOUNT_SIZE_SBF + V12_17_RISK_BUF_LEN;
2587
+ SLAB_TIERS_V12_17[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (v12.17)` };
2588
+ }
2069
2589
  function buildLayoutVSetDexPool(maxAccounts) {
2070
2590
  const engineOff = V_SETDEXPOOL_ENGINE_OFF;
2071
2591
  const bitmapOff = V_ADL_ENGINE_BITMAP_OFF;
@@ -2126,10 +2646,12 @@ function buildLayoutVSetDexPool(maxAccounts) {
2126
2646
  engineInsuranceIsolationBpsOff: 64
2127
2647
  };
2128
2648
  }
2129
- function buildLayoutV12_1(maxAccounts) {
2130
- const engineOff = V12_1_ENGINE_OFF;
2131
- const bitmapOff = V12_1_ENGINE_BITMAP_OFF;
2132
- const accountSize = V12_1_ACCOUNT_SIZE;
2649
+ function buildLayoutV12_1(maxAccounts, dataLen) {
2650
+ const hostSize = computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, maxAccounts, 18);
2651
+ const isSbf = dataLen !== void 0 && dataLen !== hostSize;
2652
+ const engineOff = isSbf ? V12_1_SBF_ENGINE_OFF : V12_1_ENGINE_OFF;
2653
+ const bitmapOff = isSbf ? V12_1_SBF_BITMAP_OFF : V12_1_ENGINE_BITMAP_OFF - V12_1_ENGINE_OFF;
2654
+ const accountSize = isSbf ? V12_1_ACCOUNT_SIZE_SBF : V12_1_ACCOUNT_SIZE;
2133
2655
  const bitmapWords = Math.ceil(maxAccounts / 64);
2134
2656
  const bitmapBytes = bitmapWords * 8;
2135
2657
  const postBitmap = 18;
@@ -2138,10 +2660,11 @@ function buildLayoutV12_1(maxAccounts) {
2138
2660
  const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;
2139
2661
  return {
2140
2662
  version: 1,
2141
- headerLen: V1_HEADER_LEN,
2142
- configOffset: V1_HEADER_LEN,
2143
- configLen: V_SETDEXPOOL_CONFIG_LEN,
2144
- // 544 (same as V_SETDEXPOOL)
2663
+ headerLen: V0_HEADER_LEN,
2664
+ // 72
2665
+ configOffset: V0_HEADER_LEN,
2666
+ // 72
2667
+ configLen: isSbf ? 544 : 576,
2145
2668
  reservedOff: V1_RESERVED_OFF,
2146
2669
  engineOff,
2147
2670
  accountSize,
@@ -2149,46 +2672,306 @@ function buildLayoutV12_1(maxAccounts) {
2149
2672
  bitmapWords,
2150
2673
  accountsOff: engineOff + accountsOffRel,
2151
2674
  engineInsuranceOff: 16,
2152
- engineParamsOff: V12_1_ENGINE_PARAMS_OFF,
2153
- paramsSize: V12_1_PARAMS_SIZE,
2154
- engineCurrentSlotOff: V12_1_ENGINE_CURRENT_SLOT_OFF,
2155
- engineFundingIndexOff: V12_1_ENGINE_FUNDING_INDEX_OFF,
2156
- engineLastFundingSlotOff: V12_1_ENGINE_LAST_FUNDING_SLOT_OFF,
2157
- engineFundingRateBpsOff: V12_1_ENGINE_FUNDING_RATE_BPS_OFF,
2158
- engineMarkPriceOff: V12_1_ENGINE_MARK_PRICE_OFF,
2159
- engineLastCrankSlotOff: V12_1_ENGINE_LAST_CRANK_SLOT_OFF,
2160
- engineMaxCrankStalenessOff: V12_1_ENGINE_MAX_CRANK_STALENESS_OFF,
2161
- engineTotalOiOff: V12_1_ENGINE_TOTAL_OI_OFF,
2162
- engineLongOiOff: V12_1_ENGINE_LONG_OI_OFF,
2163
- engineShortOiOff: V12_1_ENGINE_SHORT_OI_OFF,
2164
- engineCTotOff: V12_1_ENGINE_C_TOT_OFF,
2165
- enginePnlPosTotOff: V12_1_ENGINE_PNL_POS_TOT_OFF,
2166
- engineLiqCursorOff: V12_1_ENGINE_LIQ_CURSOR_OFF,
2167
- engineGcCursorOff: V12_1_ENGINE_GC_CURSOR_OFF,
2168
- engineLastSweepStartOff: V12_1_ENGINE_LAST_SWEEP_START_OFF,
2169
- engineLastSweepCompleteOff: V12_1_ENGINE_LAST_SWEEP_COMPLETE_OFF,
2170
- engineCrankCursorOff: V12_1_ENGINE_CRANK_CURSOR_OFF,
2171
- engineSweepStartIdxOff: V12_1_ENGINE_SWEEP_START_IDX_OFF,
2172
- engineLifetimeLiquidationsOff: V12_1_ENGINE_LIFETIME_LIQUIDATIONS_OFF,
2173
- engineLifetimeForceClosesOff: V12_1_ENGINE_LIFETIME_FORCE_CLOSES_OFF,
2174
- engineNetLpPosOff: V12_1_ENGINE_NET_LP_POS_OFF,
2175
- engineLpSumAbsOff: V12_1_ENGINE_LP_SUM_ABS_OFF,
2176
- engineLpMaxAbsOff: V12_1_ENGINE_LP_MAX_ABS_OFF,
2177
- engineLpMaxAbsSweepOff: V12_1_ENGINE_LP_MAX_ABS_SWEEP_OFF,
2178
- engineEmergencyOiModeOff: V12_1_ENGINE_EMERGENCY_OI_MODE_OFF,
2179
- engineEmergencyStartSlotOff: V12_1_ENGINE_EMERGENCY_START_SLOT_OFF,
2180
- engineLastBreakerSlotOff: V12_1_ENGINE_LAST_BREAKER_SLOT_OFF,
2181
- engineBitmapOff: V12_1_ENGINE_BITMAP_OFF,
2675
+ engineParamsOff: isSbf ? V12_1_ENGINE_PARAMS_OFF_SBF : V12_1_ENGINE_PARAMS_OFF_HOST,
2676
+ paramsSize: isSbf ? V12_1_PARAMS_SIZE_SBF : V12_1_PARAMS_SIZE,
2677
+ // SBF engine offsets — all verified by cargo build-sbf offset_of! assertions.
2678
+ // Fields that don't exist in the deployed program are set to -1 on SBF.
2679
+ engineCurrentSlotOff: isSbf ? V12_1_SBF_OFF_CURRENT_SLOT : V12_1_ENGINE_CURRENT_SLOT_OFF,
2680
+ engineFundingIndexOff: isSbf ? -1 : V12_1_ENGINE_FUNDING_INDEX_OFF,
2681
+ // not in deployed struct
2682
+ engineLastFundingSlotOff: isSbf ? -1 : V12_1_ENGINE_LAST_FUNDING_SLOT_OFF,
2683
+ // not in deployed struct
2684
+ engineFundingRateBpsOff: isSbf ? V12_1_SBF_OFF_FUNDING_RATE : V12_1_ENGINE_FUNDING_RATE_BPS_OFF,
2685
+ engineMarkPriceOff: isSbf ? V12_1_SBF_OFF_MARK_PRICE_E6 : V12_1_ENGINE_MARK_PRICE_OFF,
2686
+ engineLastCrankSlotOff: isSbf ? V12_1_SBF_OFF_LAST_CRANK_SLOT : V12_1_ENGINE_LAST_CRANK_SLOT_OFF,
2687
+ engineMaxCrankStalenessOff: isSbf ? V12_1_SBF_OFF_MAX_CRANK_STALENESS : V12_1_ENGINE_MAX_CRANK_STALENESS_OFF,
2688
+ engineTotalOiOff: isSbf ? V12_1_SBF_OFF_TOTAL_OI : V12_1_ENGINE_TOTAL_OI_OFF,
2689
+ engineLongOiOff: isSbf ? V12_1_SBF_OFF_LONG_OI : V12_1_ENGINE_LONG_OI_OFF,
2690
+ engineShortOiOff: isSbf ? V12_1_SBF_OFF_SHORT_OI : V12_1_ENGINE_SHORT_OI_OFF,
2691
+ engineCTotOff: isSbf ? V12_1_SBF_OFF_C_TOT : V12_1_ENGINE_C_TOT_OFF,
2692
+ enginePnlPosTotOff: isSbf ? V12_1_SBF_OFF_PNL_POS_TOT : V12_1_ENGINE_PNL_POS_TOT_OFF,
2693
+ engineLiqCursorOff: isSbf ? V12_1_SBF_OFF_LIQ_CURSOR : V12_1_ENGINE_LIQ_CURSOR_OFF,
2694
+ engineGcCursorOff: isSbf ? V12_1_SBF_OFF_GC_CURSOR : V12_1_ENGINE_GC_CURSOR_OFF,
2695
+ engineLastSweepStartOff: isSbf ? V12_1_SBF_OFF_LAST_SWEEP_START : V12_1_ENGINE_LAST_SWEEP_START_OFF,
2696
+ engineLastSweepCompleteOff: isSbf ? V12_1_SBF_OFF_LAST_SWEEP_COMPLETE : V12_1_ENGINE_LAST_SWEEP_COMPLETE_OFF,
2697
+ engineCrankCursorOff: isSbf ? V12_1_SBF_OFF_CRANK_CURSOR : V12_1_ENGINE_CRANK_CURSOR_OFF,
2698
+ engineSweepStartIdxOff: isSbf ? V12_1_SBF_OFF_SWEEP_START_IDX : V12_1_ENGINE_SWEEP_START_IDX_OFF,
2699
+ engineLifetimeLiquidationsOff: isSbf ? V12_1_SBF_OFF_LIFETIME_LIQUIDATIONS : V12_1_ENGINE_LIFETIME_LIQUIDATIONS_OFF,
2700
+ engineLifetimeForceClosesOff: isSbf ? -1 : V12_1_ENGINE_LIFETIME_FORCE_CLOSES_OFF,
2701
+ // not in deployed struct
2702
+ engineNetLpPosOff: isSbf ? -1 : V12_1_ENGINE_NET_LP_POS_OFF,
2703
+ // not in deployed struct
2704
+ engineLpSumAbsOff: isSbf ? -1 : V12_1_ENGINE_LP_SUM_ABS_OFF,
2705
+ // not in deployed struct
2706
+ engineLpMaxAbsOff: isSbf ? -1 : V12_1_ENGINE_LP_MAX_ABS_OFF,
2707
+ // not in deployed struct
2708
+ engineLpMaxAbsSweepOff: isSbf ? -1 : V12_1_ENGINE_LP_MAX_ABS_SWEEP_OFF,
2709
+ // not in deployed struct
2710
+ engineEmergencyOiModeOff: isSbf ? -1 : V12_1_ENGINE_EMERGENCY_OI_MODE_OFF,
2711
+ // not in deployed struct
2712
+ engineEmergencyStartSlotOff: isSbf ? -1 : V12_1_ENGINE_EMERGENCY_START_SLOT_OFF,
2713
+ // not in deployed struct
2714
+ engineLastBreakerSlotOff: isSbf ? -1 : V12_1_ENGINE_LAST_BREAKER_SLOT_OFF,
2715
+ // not in deployed struct
2716
+ engineBitmapOff: bitmapOff,
2182
2717
  postBitmap: 18,
2183
2718
  acctOwnerOff: V12_1_ACCT_OWNER_OFF,
2184
- hasInsuranceIsolation: true,
2185
- engineInsuranceIsolatedOff: 48,
2186
- engineInsuranceIsolationBpsOff: 64
2719
+ // InsuranceFund on deployed program is just {balance: U128} = 16 bytes.
2720
+ // No isolated_balance or insurance_isolation_bps fields.
2721
+ hasInsuranceIsolation: !isSbf,
2722
+ engineInsuranceIsolatedOff: isSbf ? -1 : 48,
2723
+ engineInsuranceIsolationBpsOff: isSbf ? -1 : 64
2724
+ };
2725
+ }
2726
+ function buildLayoutV12_1EP(maxAccounts) {
2727
+ const engineOff = V12_1_SBF_ENGINE_OFF;
2728
+ const bitmapOff = V12_1_SBF_BITMAP_OFF;
2729
+ const accountSize = V12_1_EP_SBF_ACCOUNT_SIZE;
2730
+ const bitmapWords = Math.ceil(maxAccounts / 64);
2731
+ const bitmapBytes = bitmapWords * 8;
2732
+ const postBitmap = 18;
2733
+ const nextFreeBytes = maxAccounts * 2;
2734
+ const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;
2735
+ const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;
2736
+ return {
2737
+ version: 1,
2738
+ headerLen: 72,
2739
+ configOffset: 72,
2740
+ configLen: 544,
2741
+ reservedOff: 80,
2742
+ // V1_RESERVED_OFF
2743
+ engineOff,
2744
+ accountSize,
2745
+ maxAccounts,
2746
+ bitmapWords,
2747
+ accountsOff: engineOff + accountsOffRel,
2748
+ engineInsuranceOff: 16,
2749
+ engineParamsOff: 32,
2750
+ // V12_1_ENGINE_PARAMS_OFF_SBF
2751
+ paramsSize: 184,
2752
+ // V12_1_PARAMS_SIZE_SBF
2753
+ // Engine offsets identical to V12_1 SBF
2754
+ engineCurrentSlotOff: V12_1_SBF_OFF_CURRENT_SLOT,
2755
+ engineFundingIndexOff: -1,
2756
+ engineLastFundingSlotOff: -1,
2757
+ engineFundingRateBpsOff: V12_1_SBF_OFF_FUNDING_RATE,
2758
+ engineMarkPriceOff: V12_1_SBF_OFF_MARK_PRICE_E6,
2759
+ engineLastCrankSlotOff: V12_1_SBF_OFF_LAST_CRANK_SLOT,
2760
+ engineMaxCrankStalenessOff: V12_1_SBF_OFF_MAX_CRANK_STALENESS,
2761
+ engineTotalOiOff: V12_1_SBF_OFF_TOTAL_OI,
2762
+ engineLongOiOff: V12_1_SBF_OFF_LONG_OI,
2763
+ engineShortOiOff: V12_1_SBF_OFF_SHORT_OI,
2764
+ engineCTotOff: V12_1_SBF_OFF_C_TOT,
2765
+ enginePnlPosTotOff: V12_1_SBF_OFF_PNL_POS_TOT,
2766
+ engineLiqCursorOff: V12_1_SBF_OFF_LIQ_CURSOR,
2767
+ engineGcCursorOff: V12_1_SBF_OFF_GC_CURSOR,
2768
+ engineLastSweepStartOff: V12_1_SBF_OFF_LAST_SWEEP_START,
2769
+ engineLastSweepCompleteOff: V12_1_SBF_OFF_LAST_SWEEP_COMPLETE,
2770
+ engineCrankCursorOff: V12_1_SBF_OFF_CRANK_CURSOR,
2771
+ engineSweepStartIdxOff: V12_1_SBF_OFF_SWEEP_START_IDX,
2772
+ engineLifetimeLiquidationsOff: V12_1_SBF_OFF_LIFETIME_LIQUIDATIONS,
2773
+ engineLifetimeForceClosesOff: -1,
2774
+ engineNetLpPosOff: -1,
2775
+ engineLpSumAbsOff: -1,
2776
+ engineLpMaxAbsOff: -1,
2777
+ engineLpMaxAbsSweepOff: -1,
2778
+ engineEmergencyOiModeOff: -1,
2779
+ engineEmergencyStartSlotOff: -1,
2780
+ engineLastBreakerSlotOff: -1,
2781
+ engineBitmapOff: bitmapOff,
2782
+ postBitmap: 18,
2783
+ // Account offsets — shifted +8 from V12_1 due to entry_price insertion
2784
+ acctOwnerOff: V12_1_EP_ACCT_OWNER_OFF,
2785
+ // 216 (was 208)
2786
+ hasInsuranceIsolation: false,
2787
+ engineInsuranceIsolatedOff: -1,
2788
+ engineInsuranceIsolationBpsOff: -1
2789
+ };
2790
+ }
2791
+ function buildLayoutV12_15(maxAccounts, dataLen) {
2792
+ const isSbf = dataLen === 237512;
2793
+ const accountSize = isSbf ? V12_15_ACCOUNT_SIZE_SMALL : V12_15_ACCOUNT_SIZE;
2794
+ const engineOff = isSbf ? V12_15_ENGINE_OFF_SBF : V12_15_ENGINE_OFF;
2795
+ const bitmapOff = V12_15_ENGINE_BITMAP_OFF;
2796
+ const effectiveBitmapOff = isSbf ? 648 : bitmapOff;
2797
+ const bitmapWords = Math.ceil(maxAccounts / 64);
2798
+ const bitmapBytes = bitmapWords * 8;
2799
+ const postBitmap = 18;
2800
+ const nextFreeBytes = maxAccounts * 2;
2801
+ const preAccountsLen = effectiveBitmapOff + bitmapBytes + postBitmap + nextFreeBytes;
2802
+ const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;
2803
+ return {
2804
+ version: 2,
2805
+ headerLen: V0_HEADER_LEN,
2806
+ // 72
2807
+ configOffset: V0_HEADER_LEN,
2808
+ // 72
2809
+ configLen: 552,
2810
+ // SBF CONFIG_LEN for v12.15
2811
+ reservedOff: V1_RESERVED_OFF,
2812
+ // 80
2813
+ engineOff,
2814
+ accountSize,
2815
+ maxAccounts,
2816
+ bitmapWords,
2817
+ accountsOff: engineOff + accountsOffRel,
2818
+ engineInsuranceOff: 16,
2819
+ engineParamsOff: V12_15_ENGINE_PARAMS_OFF,
2820
+ // 32
2821
+ paramsSize: isSbf ? 184 : V12_15_PARAMS_SIZE,
2822
+ // SBF=184 (no trailing pad), native=192
2823
+ engineCurrentSlotOff: isSbf ? 216 : V12_15_ENGINE_CURRENT_SLOT_OFF,
2824
+ // SBF=216, native=224
2825
+ engineFundingIndexOff: -1,
2826
+ // not present in v12.15 engine struct
2827
+ engineLastFundingSlotOff: -1,
2828
+ // not present in v12.15 engine struct
2829
+ engineFundingRateBpsOff: isSbf ? 224 : V12_15_ENGINE_FUNDING_RATE_E9_OFF,
2830
+ // SBF=224, native=240
2831
+ engineMarkPriceOff: -1,
2832
+ // not present in v12.15
2833
+ engineLastCrankSlotOff: -1,
2834
+ // not yet mapped
2835
+ engineMaxCrankStalenessOff: -1,
2836
+ // not yet mapped
2837
+ engineTotalOiOff: -1,
2838
+ // not present in v12.15 engine
2839
+ engineLongOiOff: -1,
2840
+ // not present in v12.15 engine
2841
+ engineShortOiOff: -1,
2842
+ // not present in v12.15 engine
2843
+ engineCTotOff: isSbf ? 320 : V12_15_ENGINE_C_TOT_OFF,
2844
+ // SBF=320 (verified on-chain), native=344
2845
+ enginePnlPosTotOff: isSbf ? 336 : V12_15_ENGINE_PNL_POS_TOT_OFF,
2846
+ // SBF=336 (verified), native=368
2847
+ engineLiqCursorOff: -1,
2848
+ // not yet mapped
2849
+ engineGcCursorOff: -1,
2850
+ // not yet mapped
2851
+ engineLastSweepStartOff: -1,
2852
+ // not yet mapped
2853
+ engineLastSweepCompleteOff: -1,
2854
+ // not yet mapped
2855
+ engineCrankCursorOff: -1,
2856
+ // not yet mapped
2857
+ engineSweepStartIdxOff: -1,
2858
+ // not yet mapped
2859
+ engineLifetimeLiquidationsOff: -1,
2860
+ // not yet mapped
2861
+ engineLifetimeForceClosesOff: -1,
2862
+ // not present in v12.15
2863
+ engineNetLpPosOff: -1,
2864
+ // not present in v12.15
2865
+ engineLpSumAbsOff: -1,
2866
+ // not present in v12.15
2867
+ engineLpMaxAbsOff: -1,
2868
+ // not present in v12.15
2869
+ engineLpMaxAbsSweepOff: -1,
2870
+ // not present in v12.15
2871
+ engineEmergencyOiModeOff: -1,
2872
+ // not present in v12.15
2873
+ engineEmergencyStartSlotOff: -1,
2874
+ // not present in v12.15
2875
+ engineLastBreakerSlotOff: -1,
2876
+ // not present in v12.15
2877
+ engineBitmapOff: effectiveBitmapOff,
2878
+ // SBF=640, native=862
2879
+ postBitmap,
2880
+ acctOwnerOff: V12_15_ACCT_OWNER_OFF,
2881
+ // 192
2882
+ hasInsuranceIsolation: false,
2883
+ engineInsuranceIsolatedOff: -1,
2884
+ engineInsuranceIsolationBpsOff: -1
2885
+ };
2886
+ }
2887
+ function buildLayoutV12_17(maxAccounts, dataLen) {
2888
+ const isSbf = (() => {
2889
+ const bitmapBytes2 = Math.ceil(maxAccounts / 64) * 8;
2890
+ const preAccNative = V12_17_ENGINE_BITMAP_OFF + bitmapBytes2 + 4 + maxAccounts * 2;
2891
+ const accountsOffNative = Math.ceil(preAccNative / 16) * 16;
2892
+ const nativeSize = V12_17_ENGINE_OFF + accountsOffNative + maxAccounts * V12_17_ACCOUNT_SIZE + V12_17_RISK_BUF_LEN;
2893
+ return dataLen !== nativeSize;
2894
+ })();
2895
+ const engineOff = isSbf ? V12_17_ENGINE_OFF_SBF : V12_17_ENGINE_OFF;
2896
+ const accountSize = isSbf ? V12_17_ACCOUNT_SIZE_SBF : V12_17_ACCOUNT_SIZE;
2897
+ const bitmapOff = isSbf ? V12_17_ENGINE_BITMAP_OFF_SBF : V12_17_ENGINE_BITMAP_OFF;
2898
+ const bitmapWords = Math.ceil(maxAccounts / 64);
2899
+ const bitmapBytes = bitmapWords * 8;
2900
+ const postBitmap = 4;
2901
+ const nextFreeBytes = maxAccounts * 2;
2902
+ const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;
2903
+ const acctAlign = isSbf ? 8 : 16;
2904
+ const accountsOffRel = Math.ceil(preAccountsLen / acctAlign) * acctAlign;
2905
+ return {
2906
+ version: 2,
2907
+ headerLen: V0_HEADER_LEN,
2908
+ // 72
2909
+ configOffset: V0_HEADER_LEN,
2910
+ // 72
2911
+ // configLen = 512 (SBF-aligned MarketConfig size after Phase A/B/E).
2912
+ // Verified field-by-field against percolator-prog/src/percolator.rs MarketConfig struct.
2913
+ // Missing 80 bytes from prior value 432: max_pnl_cap, last_audit_pause_slot,
2914
+ // oi_cap_multiplier_bps, dispute_window_slots, dispute_bond_amount,
2915
+ // lp_collateral_enabled, lp_collateral_ltv_bps, _new_fields_pad, pending_admin.
2916
+ configLen: 512,
2917
+ reservedOff: V1_RESERVED_OFF,
2918
+ // 80
2919
+ engineOff,
2920
+ accountSize,
2921
+ maxAccounts,
2922
+ bitmapWords,
2923
+ accountsOff: engineOff + accountsOffRel,
2924
+ engineInsuranceOff: 16,
2925
+ engineParamsOff: V12_17_ENGINE_PARAMS_OFF,
2926
+ // 32
2927
+ paramsSize: isSbf ? 184 : 192,
2928
+ engineCurrentSlotOff: isSbf ? V12_17_SBF_ENGINE_CURRENT_SLOT_OFF : V12_17_ENGINE_CURRENT_SLOT_OFF,
2929
+ engineFundingIndexOff: -1,
2930
+ // replaced by per-side f_long_num/f_short_num
2931
+ engineLastFundingSlotOff: -1,
2932
+ engineFundingRateBpsOff: -1,
2933
+ // no stored funding rate in v12.17
2934
+ engineMarkPriceOff: -1,
2935
+ engineLastCrankSlotOff: -1,
2936
+ engineMaxCrankStalenessOff: -1,
2937
+ engineTotalOiOff: -1,
2938
+ engineLongOiOff: -1,
2939
+ engineShortOiOff: -1,
2940
+ engineCTotOff: isSbf ? V12_17_SBF_ENGINE_C_TOT_OFF : V12_17_ENGINE_C_TOT_OFF,
2941
+ enginePnlPosTotOff: isSbf ? V12_17_SBF_ENGINE_PNL_POS_TOT_OFF : V12_17_ENGINE_PNL_POS_TOT_OFF,
2942
+ engineLiqCursorOff: -1,
2943
+ engineGcCursorOff: -1,
2944
+ engineLastSweepStartOff: -1,
2945
+ engineLastSweepCompleteOff: -1,
2946
+ engineCrankCursorOff: -1,
2947
+ engineSweepStartIdxOff: -1,
2948
+ engineLifetimeLiquidationsOff: -1,
2949
+ engineLifetimeForceClosesOff: -1,
2950
+ engineNetLpPosOff: -1,
2951
+ engineLpSumAbsOff: -1,
2952
+ engineLpMaxAbsOff: -1,
2953
+ engineLpMaxAbsSweepOff: -1,
2954
+ engineEmergencyOiModeOff: -1,
2955
+ engineEmergencyStartSlotOff: -1,
2956
+ engineLastBreakerSlotOff: -1,
2957
+ engineBitmapOff: bitmapOff,
2958
+ postBitmap,
2959
+ acctOwnerOff: isSbf ? 192 : V12_17_ACCT_OWNER_OFF,
2960
+ // SBF=192, native=200
2961
+ hasInsuranceIsolation: false,
2962
+ engineInsuranceIsolatedOff: -1,
2963
+ engineInsuranceIsolationBpsOff: -1
2187
2964
  };
2188
2965
  }
2189
2966
  function detectSlabLayout(dataLen, data) {
2967
+ const v1217n = V12_17_SIZES.get(dataLen);
2968
+ if (v1217n !== void 0) return buildLayoutV12_17(v1217n, dataLen);
2969
+ const v1215n = V12_15_SIZES.get(dataLen);
2970
+ if (v1215n !== void 0) return buildLayoutV12_15(v1215n, dataLen);
2971
+ const v121epn = V12_1_EP_SIZES.get(dataLen);
2972
+ if (v121epn !== void 0) return buildLayoutV12_1EP(v121epn);
2190
2973
  const v121n = V12_1_SIZES.get(dataLen);
2191
- if (v121n !== void 0) return buildLayoutV12_1(v121n);
2974
+ if (v121n !== void 0) return buildLayoutV12_1(v121n, dataLen);
2192
2975
  const vsdpn = V_SETDEXPOOL_SIZES.get(dataLen);
2193
2976
  if (vsdpn !== void 0) return buildLayoutVSetDexPool(vsdpn);
2194
2977
  const v1m2n = V1M2_SIZES.get(dataLen);
@@ -2233,6 +3016,15 @@ var PARAMS_LIQUIDATION_FEE_BPS_OFF = 96;
2233
3016
  var PARAMS_LIQUIDATION_FEE_CAP_OFF = 104;
2234
3017
  var PARAMS_LIQUIDATION_BUFFER_OFF = 120;
2235
3018
  var PARAMS_MIN_LIQUIDATION_OFF = 128;
3019
+ var V12_1_PARAMS_MAINT_FEE_OFF = 56;
3020
+ var V12_1_PARAMS_MAX_CRANK_OFF = 72;
3021
+ var V12_1_PARAMS_LIQ_FEE_BPS_OFF = 80;
3022
+ var V12_1_PARAMS_LIQ_FEE_CAP_OFF = 88;
3023
+ var V12_1_PARAMS_MIN_LIQ_OFF = 104;
3024
+ var V12_1_PARAMS_MIN_INITIAL_DEP_OFF = 120;
3025
+ var V12_1_PARAMS_MIN_NZ_MM_OFF = 136;
3026
+ var V12_1_PARAMS_MIN_NZ_IM_OFF = 152;
3027
+ var V12_1_PARAMS_INS_FLOOR_OFF = 168;
2236
3028
  var ACCT_ACCOUNT_ID_OFF = 0;
2237
3029
  var ACCT_CAPITAL_OFF = 8;
2238
3030
  var ACCT_KIND_OFF = 24;
@@ -2303,7 +3095,7 @@ function parseHeader(data) {
2303
3095
  const version = readU32LE(data, 8);
2304
3096
  const bump = readU8(data, 12);
2305
3097
  const flags = readU8(data, 13);
2306
- const admin = new PublicKey3(data.subarray(16, 48));
3098
+ const admin = new PublicKey5(data.subarray(16, 48));
2307
3099
  const layout = detectSlabLayout(data.length, data);
2308
3100
  const roff = layout ? layout.reservedOff : V0_RESERVED_OFF;
2309
3101
  const nonce = readU64LE(data, roff);
@@ -2324,16 +3116,17 @@ function parseConfig(data, layoutHint) {
2324
3116
  const layout = layoutHint !== void 0 ? layoutHint : detectSlabLayout(data.length, data);
2325
3117
  const configOff = layout ? layout.configOffset : V0_HEADER_LEN;
2326
3118
  const configLen = layout ? layout.configLen : V0_CONFIG_LEN;
2327
- const minLen = configOff + Math.min(configLen, 120);
3119
+ const MIN_CONFIG_BYTES = 376;
3120
+ const minLen = configOff + Math.min(configLen, MIN_CONFIG_BYTES);
2328
3121
  if (data.length < minLen) {
2329
3122
  throw new Error(`Slab data too short for config: ${data.length} < ${minLen}`);
2330
3123
  }
2331
3124
  let off = configOff;
2332
- const collateralMint = new PublicKey3(data.subarray(off, off + 32));
3125
+ const collateralMint = new PublicKey5(data.subarray(off, off + 32));
2333
3126
  off += 32;
2334
- const vaultPubkey = new PublicKey3(data.subarray(off, off + 32));
3127
+ const vaultPubkey = new PublicKey5(data.subarray(off, off + 32));
2335
3128
  off += 32;
2336
- const indexFeedId = new PublicKey3(data.subarray(off, off + 32));
3129
+ const indexFeedId = new PublicKey5(data.subarray(off, off + 32));
2337
3130
  off += 32;
2338
3131
  const maxStalenessSlots = readU64LE(data, off);
2339
3132
  off += 8;
@@ -2355,14 +3148,6 @@ function parseConfig(data, layoutHint) {
2355
3148
  off += 8;
2356
3149
  const fundingMaxBpsPerSlot = readI64LE(data, off);
2357
3150
  off += 8;
2358
- const fundingPremiumWeightBps = readU64LE(data, off);
2359
- off += 8;
2360
- const fundingSettlementIntervalSlots = readU64LE(data, off);
2361
- off += 8;
2362
- const fundingPremiumDampeningE6 = readU64LE(data, off);
2363
- off += 8;
2364
- const fundingPremiumMaxBpsPerSlot = readU64LE(data, off);
2365
- off += 8;
2366
3151
  const threshFloor = readU128LE(data, off);
2367
3152
  off += 16;
2368
3153
  const threshRiskBps = readU64LE(data, off);
@@ -2379,7 +3164,7 @@ function parseConfig(data, layoutHint) {
2379
3164
  off += 16;
2380
3165
  const threshMinStep = readU128LE(data, off);
2381
3166
  off += 16;
2382
- const oracleAuthority = new PublicKey3(data.subarray(off, off + 32));
3167
+ const oracleAuthority = new PublicKey5(data.subarray(off, off + 32));
2383
3168
  off += 32;
2384
3169
  const authorityPriceE6 = readU64LE(data, off);
2385
3170
  off += 8;
@@ -2432,7 +3217,7 @@ function parseConfig(data, layoutHint) {
2432
3217
  if (configLen >= DEX_POOL_REL_OFF + 32 && data.length >= configOff + DEX_POOL_REL_OFF + 32) {
2433
3218
  const dexPoolBytes = data.subarray(configOff + DEX_POOL_REL_OFF, configOff + DEX_POOL_REL_OFF + 32);
2434
3219
  if (dexPoolBytes.some((b) => b !== 0)) {
2435
- dexPool = new PublicKey3(dexPoolBytes);
3220
+ dexPool = new PublicKey5(dexPoolBytes);
2436
3221
  }
2437
3222
  }
2438
3223
  return {
@@ -2449,10 +3234,10 @@ function parseConfig(data, layoutHint) {
2449
3234
  fundingInvScaleNotionalE6,
2450
3235
  fundingMaxPremiumBps,
2451
3236
  fundingMaxBpsPerSlot,
2452
- fundingPremiumWeightBps,
2453
- fundingSettlementIntervalSlots,
2454
- fundingPremiumDampeningE6,
2455
- fundingPremiumMaxBpsPerSlot,
3237
+ fundingPremiumWeightBps: 0n,
3238
+ fundingSettlementIntervalSlots: 0n,
3239
+ fundingPremiumDampeningE6: 0n,
3240
+ fundingPremiumMaxBpsPerSlot: 0n,
2456
3241
  threshFloor,
2457
3242
  threshRiskBps,
2458
3243
  threshUpdateIntervalSlots,
@@ -2487,26 +3272,61 @@ function parseParams(data, layoutHint) {
2487
3272
  const paramsOff = layout ? layout.engineParamsOff : V0_ENGINE_PARAMS_OFF;
2488
3273
  const paramsSize = layout ? layout.paramsSize : V0_PARAMS_SIZE;
2489
3274
  const base = engineOff + paramsOff;
2490
- if (data.length < base + Math.min(paramsSize, 56)) {
2491
- throw new Error("Slab data too short for RiskParams");
3275
+ const MIN_PARAMS_BYTES = paramsSize >= 144 ? 144 : 56;
3276
+ if (data.length < base + MIN_PARAMS_BYTES) {
3277
+ throw new Error(`Slab data too short for RiskParams: ${data.length} < ${base + MIN_PARAMS_BYTES}`);
2492
3278
  }
3279
+ const isV12_15Params = paramsSize === V12_15_PARAMS_SIZE || paramsSize === 184;
3280
+ const isV12_1Sbf = !isV12_15Params && layout !== null && layout !== void 0 && layout.engineOff === V12_1_SBF_ENGINE_OFF && paramsSize === 184;
2493
3281
  const result = {
2494
- warmupPeriodSlots: readU64LE(data, base + PARAMS_WARMUP_PERIOD_OFF),
2495
- maintenanceMarginBps: readU64LE(data, base + PARAMS_MAINTENANCE_MARGIN_OFF),
2496
- initialMarginBps: readU64LE(data, base + PARAMS_INITIAL_MARGIN_OFF),
2497
- tradingFeeBps: readU64LE(data, base + PARAMS_TRADING_FEE_OFF),
2498
- maxAccounts: readU64LE(data, base + PARAMS_MAX_ACCOUNTS_OFF),
2499
- newAccountFee: readU128LE(data, base + PARAMS_NEW_ACCOUNT_FEE_OFF),
2500
- // Extended params: only read if V1 (paramsSize >= 144)
3282
+ warmupPeriodSlots: isV12_15Params ? readU64LE(data, base + V12_15_PARAMS_H_MIN_OFF) : readU64LE(data, base + PARAMS_WARMUP_PERIOD_OFF),
3283
+ maintenanceMarginBps: isV12_15Params ? readU64LE(data, base + 0) : readU64LE(data, base + PARAMS_MAINTENANCE_MARGIN_OFF),
3284
+ initialMarginBps: isV12_15Params ? readU64LE(data, base + 8) : readU64LE(data, base + PARAMS_INITIAL_MARGIN_OFF),
3285
+ tradingFeeBps: isV12_15Params ? readU64LE(data, base + 16) : readU64LE(data, base + PARAMS_TRADING_FEE_OFF),
3286
+ maxAccounts: isV12_15Params ? readU64LE(data, base + V12_15_PARAMS_MAX_ACCOUNTS_OFF) : readU64LE(data, base + PARAMS_MAX_ACCOUNTS_OFF),
3287
+ newAccountFee: isV12_15Params ? readU128LE(data, base + 32) : readU128LE(data, base + PARAMS_NEW_ACCOUNT_FEE_OFF),
3288
+ // Extended params: defaults; overwritten below if layout supports them
2501
3289
  riskReductionThreshold: 0n,
2502
3290
  maintenanceFeePerSlot: 0n,
2503
3291
  maxCrankStalenessSlots: 0n,
2504
3292
  liquidationFeeBps: 0n,
2505
3293
  liquidationFeeCap: 0n,
2506
3294
  liquidationBufferBps: 0n,
2507
- minLiquidationAbs: 0n
3295
+ minLiquidationAbs: 0n,
3296
+ minInitialDeposit: 0n,
3297
+ minNonzeroMmReq: 0n,
3298
+ minNonzeroImReq: 0n,
3299
+ insuranceFloor: 0n,
3300
+ hMin: 0n,
3301
+ hMax: 0n
2508
3302
  };
2509
- if (paramsSize >= 144) {
3303
+ if (isV12_15Params) {
3304
+ result.hMin = readU64LE(data, base + V12_15_PARAMS_H_MIN_OFF);
3305
+ result.hMax = readU64LE(data, base + V12_15_PARAMS_H_MAX_OFF);
3306
+ result.insuranceFloor = readU128LE(data, base + V12_15_PARAMS_INSURANCE_FLOOR_OFF);
3307
+ result.riskReductionThreshold = 0n;
3308
+ result.maintenanceFeePerSlot = 0n;
3309
+ result.maxCrankStalenessSlots = readU64LE(data, base + 48);
3310
+ result.liquidationFeeBps = readU64LE(data, base + 56);
3311
+ result.liquidationFeeCap = readU128LE(data, base + 64);
3312
+ result.liquidationBufferBps = 0n;
3313
+ result.minLiquidationAbs = readU128LE(data, base + 80);
3314
+ result.minInitialDeposit = readU128LE(data, base + 96);
3315
+ result.minNonzeroMmReq = readU128LE(data, base + 112);
3316
+ result.minNonzeroImReq = readU128LE(data, base + 128);
3317
+ } else if (isV12_1Sbf) {
3318
+ result.maintenanceFeePerSlot = readU128LE(data, base + V12_1_PARAMS_MAINT_FEE_OFF);
3319
+ result.maxCrankStalenessSlots = readU64LE(data, base + V12_1_PARAMS_MAX_CRANK_OFF);
3320
+ result.liquidationFeeBps = readU64LE(data, base + V12_1_PARAMS_LIQ_FEE_BPS_OFF);
3321
+ result.liquidationFeeCap = readU128LE(data, base + V12_1_PARAMS_LIQ_FEE_CAP_OFF);
3322
+ result.minLiquidationAbs = readU128LE(data, base + V12_1_PARAMS_MIN_LIQ_OFF);
3323
+ result.minInitialDeposit = readU128LE(data, base + V12_1_PARAMS_MIN_INITIAL_DEP_OFF);
3324
+ result.minNonzeroMmReq = readU128LE(data, base + V12_1_PARAMS_MIN_NZ_MM_OFF);
3325
+ result.minNonzeroImReq = readU128LE(data, base + V12_1_PARAMS_MIN_NZ_IM_OFF);
3326
+ result.insuranceFloor = readU128LE(data, base + V12_1_PARAMS_INS_FLOOR_OFF);
3327
+ result.hMin = result.warmupPeriodSlots;
3328
+ result.hMax = result.warmupPeriodSlots;
3329
+ } else if (paramsSize >= 144) {
2510
3330
  result.riskReductionThreshold = readU128LE(data, base + PARAMS_RISK_THRESHOLD_OFF);
2511
3331
  result.maintenanceFeePerSlot = readU128LE(data, base + PARAMS_MAINTENANCE_FEE_OFF);
2512
3332
  result.maxCrankStalenessSlots = readU64LE(data, base + PARAMS_MAX_CRANK_STALENESS_OFF);
@@ -2514,6 +3334,8 @@ function parseParams(data, layoutHint) {
2514
3334
  result.liquidationFeeCap = readU128LE(data, base + PARAMS_LIQUIDATION_FEE_CAP_OFF);
2515
3335
  result.liquidationBufferBps = readU64LE(data, base + PARAMS_LIQUIDATION_BUFFER_OFF);
2516
3336
  result.minLiquidationAbs = readU128LE(data, base + PARAMS_MIN_LIQUIDATION_OFF);
3337
+ result.hMin = result.warmupPeriodSlots;
3338
+ result.hMax = result.warmupPeriodSlots;
2517
3339
  }
2518
3340
  return result;
2519
3341
  }
@@ -2523,41 +3345,122 @@ function parseEngine(data) {
2523
3345
  throw new Error(`Unrecognized slab data length: ${data.length}. Cannot determine layout version.`);
2524
3346
  }
2525
3347
  const base = layout.engineOff;
3348
+ const isV12_17 = layout.accountSize === V12_17_ACCOUNT_SIZE || layout.accountSize === V12_17_ACCOUNT_SIZE_SBF;
3349
+ 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);
3350
+ if (isV12_17) {
3351
+ const isSbf = layout.engineOff === V12_17_ENGINE_OFF_SBF;
3352
+ const currentSlotOff = isSbf ? V12_17_SBF_ENGINE_CURRENT_SLOT_OFF : V12_17_ENGINE_CURRENT_SLOT_OFF;
3353
+ const marketModeOff = isSbf ? V12_17_SBF_ENGINE_MARKET_MODE_OFF : V12_17_ENGINE_MARKET_MODE_OFF;
3354
+ const cTotOff = isSbf ? V12_17_SBF_ENGINE_C_TOT_OFF : V12_17_ENGINE_C_TOT_OFF;
3355
+ const pnlPosTotOff = isSbf ? V12_17_SBF_ENGINE_PNL_POS_TOT_OFF : V12_17_ENGINE_PNL_POS_TOT_OFF;
3356
+ const pnlMaturedOff = isSbf ? V12_17_SBF_ENGINE_PNL_MATURED_POS_TOT_OFF : V12_17_ENGINE_PNL_MATURED_POS_TOT_OFF;
3357
+ const negPnlOff = isSbf ? V12_17_SBF_ENGINE_NEG_PNL_COUNT_OFF : V12_17_ENGINE_NEG_PNL_COUNT_OFF;
3358
+ const oraclePriceOff = isSbf ? V12_17_SBF_ENGINE_LAST_ORACLE_PRICE_OFF : V12_17_ENGINE_LAST_ORACLE_PRICE_OFF;
3359
+ const fundPxLastOff = isSbf ? V12_17_SBF_ENGINE_FUND_PX_LAST_OFF : V12_17_ENGINE_FUND_PX_LAST_OFF;
3360
+ const fLongNumOff = isSbf ? V12_17_SBF_ENGINE_F_LONG_NUM_OFF : V12_17_ENGINE_F_LONG_NUM_OFF;
3361
+ const fShortNumOff = isSbf ? V12_17_SBF_ENGINE_F_SHORT_NUM_OFF : V12_17_ENGINE_F_SHORT_NUM_OFF;
3362
+ const resolvedKLongOff = isSbf ? 288 : V12_17_ENGINE_RESOLVED_K_LONG_OFF;
3363
+ const resolvedKShortOff = isSbf ? 304 : V12_17_ENGINE_RESOLVED_K_SHORT_OFF;
3364
+ const resolvedLivePriceOff = isSbf ? 320 : V12_17_ENGINE_RESOLVED_LIVE_PRICE_OFF;
3365
+ const bitmapEnd = layout.engineBitmapOff + layout.bitmapWords * 8;
3366
+ return {
3367
+ vault: readU128LE(data, base),
3368
+ insuranceFund: {
3369
+ balance: readU128LE(data, base + 16),
3370
+ feeRevenue: 0n,
3371
+ isolatedBalance: 0n,
3372
+ isolationBps: 0
3373
+ },
3374
+ currentSlot: readU64LE(data, base + currentSlotOff),
3375
+ fundingIndexQpbE6: 0n,
3376
+ // replaced by per-side funding
3377
+ lastFundingSlot: 0n,
3378
+ fundingRateBpsPerSlotLast: 0n,
3379
+ // no stored funding rate in v12.17
3380
+ fundingRateE9: 0n,
3381
+ // no stored funding rate in v12.17
3382
+ marketMode: readU8(data, base + marketModeOff) === 1 ? 1 : 0,
3383
+ lastCrankSlot: 0n,
3384
+ maxCrankStalenessSlots: 0n,
3385
+ totalOpenInterest: 0n,
3386
+ longOi: 0n,
3387
+ shortOi: 0n,
3388
+ cTot: readU128LE(data, base + cTotOff),
3389
+ pnlPosTot: readU128LE(data, base + pnlPosTotOff),
3390
+ pnlMaturedPosTot: readU128LE(data, base + pnlMaturedOff),
3391
+ liqCursor: 0,
3392
+ gcCursor: 0,
3393
+ lastSweepStartSlot: 0n,
3394
+ lastSweepCompleteSlot: 0n,
3395
+ crankCursor: 0,
3396
+ sweepStartIdx: 0,
3397
+ lifetimeLiquidations: 0n,
3398
+ lifetimeForceCloses: 0n,
3399
+ netLpPos: 0n,
3400
+ lpSumAbs: 0n,
3401
+ lpMaxAbs: 0n,
3402
+ lpMaxAbsSweep: 0n,
3403
+ emergencyOiMode: false,
3404
+ emergencyStartSlot: 0n,
3405
+ lastBreakerSlot: 0n,
3406
+ markPriceE6: 0n,
3407
+ oraclePriceE6: readU64LE(data, base + oraclePriceOff),
3408
+ numUsedAccounts: readU16LE(data, base + bitmapEnd),
3409
+ nextAccountId: 0n,
3410
+ // removed in v12.17 (replaced by mat_counter in header)
3411
+ // V12_17 fields
3412
+ fLongNum: readI128LE(data, base + fLongNumOff),
3413
+ fShortNum: readI128LE(data, base + fShortNumOff),
3414
+ negPnlAccountCount: readU64LE(data, base + negPnlOff),
3415
+ fundPxLast: readU64LE(data, base + fundPxLastOff),
3416
+ resolvedKLongTerminalDelta: readI128LE(data, base + resolvedKLongOff),
3417
+ resolvedKShortTerminalDelta: readI128LE(data, base + resolvedKShortOff),
3418
+ resolvedLivePrice: readU64LE(data, base + resolvedLivePriceOff)
3419
+ };
3420
+ }
3421
+ const fundingRateBpsPerSlotLast = isV12_15 ? readI128LE(data, base + layout.engineFundingRateBpsOff) : readI64LE(data, base + layout.engineFundingRateBpsOff);
2526
3422
  return {
2527
3423
  vault: readU128LE(data, base),
2528
3424
  insuranceFund: {
2529
3425
  balance: readU128LE(data, base + layout.engineInsuranceOff),
2530
- feeRevenue: readU128LE(data, base + layout.engineInsuranceOff + 16),
3426
+ // feeRevenue: only exists in percolator-core (80-byte InsuranceFund), not deployed (16-byte)
3427
+ feeRevenue: layout.hasInsuranceIsolation ? readU128LE(data, base + layout.engineInsuranceOff + 16) : 0n,
2531
3428
  isolatedBalance: layout.hasInsuranceIsolation ? readU128LE(data, base + layout.engineInsuranceIsolatedOff) : 0n,
2532
3429
  isolationBps: layout.hasInsuranceIsolation ? readU16LE(data, base + layout.engineInsuranceIsolationBpsOff) : 0
2533
3430
  },
2534
3431
  currentSlot: readU64LE(data, base + layout.engineCurrentSlotOff),
2535
- fundingIndexQpbE6: readI128LE(data, base + layout.engineFundingIndexOff),
2536
- lastFundingSlot: readU64LE(data, base + layout.engineLastFundingSlotOff),
2537
- fundingRateBpsPerSlotLast: readI64LE(data, base + layout.engineFundingRateBpsOff),
2538
- lastCrankSlot: readU64LE(data, base + layout.engineLastCrankSlotOff),
2539
- maxCrankStalenessSlots: readU64LE(data, base + layout.engineMaxCrankStalenessOff),
2540
- totalOpenInterest: readU128LE(data, base + layout.engineTotalOiOff),
3432
+ fundingIndexQpbE6: layout.engineFundingIndexOff >= 0 ? readI128LE(data, base + layout.engineFundingIndexOff) : 0n,
3433
+ lastFundingSlot: layout.engineLastFundingSlotOff >= 0 ? readU64LE(data, base + layout.engineLastFundingSlotOff) : 0n,
3434
+ fundingRateBpsPerSlotLast,
3435
+ fundingRateE9: isV12_15 ? readI128LE(data, base + layout.engineFundingRateBpsOff) : 0n,
3436
+ marketMode: isV12_15 ? readU8(data, base + layout.engineFundingRateBpsOff + 16) === 1 ? 1 : 0 : null,
3437
+ lastCrankSlot: layout.engineLastCrankSlotOff >= 0 ? readU64LE(data, base + layout.engineLastCrankSlotOff) : 0n,
3438
+ maxCrankStalenessSlots: layout.engineMaxCrankStalenessOff >= 0 ? readU64LE(data, base + layout.engineMaxCrankStalenessOff) : 0n,
3439
+ totalOpenInterest: layout.engineTotalOiOff >= 0 ? readU128LE(data, base + layout.engineTotalOiOff) : 0n,
2541
3440
  longOi: layout.engineLongOiOff >= 0 ? readU128LE(data, base + layout.engineLongOiOff) : 0n,
2542
3441
  shortOi: layout.engineShortOiOff >= 0 ? readU128LE(data, base + layout.engineShortOiOff) : 0n,
2543
3442
  cTot: readU128LE(data, base + layout.engineCTotOff),
2544
3443
  pnlPosTot: readU128LE(data, base + layout.enginePnlPosTotOff),
2545
- liqCursor: readU16LE(data, base + layout.engineLiqCursorOff),
2546
- gcCursor: readU16LE(data, base + layout.engineGcCursorOff),
2547
- lastSweepStartSlot: readU64LE(data, base + layout.engineLastSweepStartOff),
2548
- lastSweepCompleteSlot: readU64LE(data, base + layout.engineLastSweepCompleteOff),
2549
- crankCursor: readU16LE(data, base + layout.engineCrankCursorOff),
2550
- sweepStartIdx: readU16LE(data, base + layout.engineSweepStartIdxOff),
2551
- lifetimeLiquidations: readU64LE(data, base + layout.engineLifetimeLiquidationsOff),
2552
- lifetimeForceCloses: readU64LE(data, base + layout.engineLifetimeForceClosesOff),
2553
- netLpPos: readI128LE(data, base + layout.engineNetLpPosOff),
2554
- lpSumAbs: readU128LE(data, base + layout.engineLpSumAbsOff),
3444
+ pnlMaturedPosTot: isV12_15 ? readU128LE(data, base + V12_15_ENGINE_PNL_MATURED_POS_TOT_OFF) : 0n,
3445
+ liqCursor: layout.engineLiqCursorOff >= 0 ? readU16LE(data, base + layout.engineLiqCursorOff) : 0,
3446
+ gcCursor: layout.engineGcCursorOff >= 0 ? readU16LE(data, base + layout.engineGcCursorOff) : 0,
3447
+ lastSweepStartSlot: layout.engineLastSweepStartOff >= 0 ? readU64LE(data, base + layout.engineLastSweepStartOff) : 0n,
3448
+ lastSweepCompleteSlot: layout.engineLastSweepCompleteOff >= 0 ? readU64LE(data, base + layout.engineLastSweepCompleteOff) : 0n,
3449
+ crankCursor: layout.engineCrankCursorOff >= 0 ? readU16LE(data, base + layout.engineCrankCursorOff) : 0,
3450
+ sweepStartIdx: layout.engineSweepStartIdxOff >= 0 ? readU16LE(data, base + layout.engineSweepStartIdxOff) : 0,
3451
+ lifetimeLiquidations: layout.engineLifetimeLiquidationsOff >= 0 ? readU64LE(data, base + layout.engineLifetimeLiquidationsOff) : 0n,
3452
+ lifetimeForceCloses: layout.engineLifetimeForceClosesOff >= 0 ? readU64LE(data, base + layout.engineLifetimeForceClosesOff) : 0n,
3453
+ netLpPos: layout.engineNetLpPosOff >= 0 ? readI128LE(data, base + layout.engineNetLpPosOff) : 0n,
3454
+ lpSumAbs: layout.engineLpSumAbsOff >= 0 ? readU128LE(data, base + layout.engineLpSumAbsOff) : 0n,
2555
3455
  lpMaxAbs: layout.engineLpMaxAbsOff >= 0 ? readU128LE(data, base + layout.engineLpMaxAbsOff) : 0n,
2556
3456
  lpMaxAbsSweep: layout.engineLpMaxAbsSweepOff >= 0 ? readU128LE(data, base + layout.engineLpMaxAbsSweepOff) : 0n,
2557
3457
  emergencyOiMode: layout.engineEmergencyOiModeOff >= 0 ? data[base + layout.engineEmergencyOiModeOff] !== 0 : false,
2558
3458
  emergencyStartSlot: layout.engineEmergencyStartSlotOff >= 0 ? readU64LE(data, base + layout.engineEmergencyStartSlotOff) : 0n,
2559
3459
  lastBreakerSlot: layout.engineLastBreakerSlotOff >= 0 ? readU64LE(data, base + layout.engineLastBreakerSlotOff) : 0n,
2560
3460
  markPriceE6: layout.engineMarkPriceOff >= 0 ? readU64LE(data, base + layout.engineMarkPriceOff) : 0n,
3461
+ // V12_15: last_oracle_price at engine+608 (SBF) / engine+... (native).
3462
+ // Located at bitmapOff - 40 on SBF (648-40=608, verified on-chain).
3463
+ oraclePriceE6: isV12_15 ? readU64LE(data, base + layout.engineBitmapOff - 40) : 0n,
2561
3464
  numUsedAccounts: (() => {
2562
3465
  if (layout.postBitmap < 18) return 0;
2563
3466
  const bw = layout.bitmapWords;
@@ -2568,7 +3471,15 @@ function parseEngine(data) {
2568
3471
  const bw = layout.bitmapWords;
2569
3472
  const numUsedOff = layout.engineBitmapOff + bw * 8;
2570
3473
  return readU64LE(data, base + Math.ceil((numUsedOff + 2) / 8) * 8);
2571
- })()
3474
+ })(),
3475
+ // V12_17 fields (not present in pre-v12.17)
3476
+ fLongNum: 0n,
3477
+ fShortNum: 0n,
3478
+ negPnlAccountCount: 0n,
3479
+ fundPxLast: 0n,
3480
+ resolvedKLongTerminalDelta: 0n,
3481
+ resolvedKShortTerminalDelta: 0n,
3482
+ resolvedLivePrice: 0n
2572
3483
  };
2573
3484
  }
2574
3485
  function parseUsedIndices(data) {
@@ -2618,17 +3529,129 @@ function parseAccount(data, idx) {
2618
3529
  if (data.length < base + layout.accountSize) {
2619
3530
  throw new Error("Slab data too short for account");
2620
3531
  }
2621
- const isV12_1 = layout.accountSize >= 320;
2622
- const isAdl = layout.accountSize >= 312;
3532
+ const isV12_17 = layout.accountSize === V12_17_ACCOUNT_SIZE || layout.accountSize === V12_17_ACCOUNT_SIZE_SBF;
3533
+ const isV12_15 = !isV12_17 && (layout.accountSize === V12_15_ACCOUNT_SIZE || layout.accountSize === V12_15_ACCOUNT_SIZE_SMALL);
3534
+ const isV12_1EP = !isV12_17 && !isV12_15 && layout.accountSize === V12_1_EP_SBF_ACCOUNT_SIZE && layout.engineOff === V12_1_SBF_ENGINE_OFF;
3535
+ 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);
3536
+ const isAdl = !isV12_17 && !isV12_15 && (layout.accountSize >= 312 || isV12_1 || isV12_1EP);
3537
+ if (isV12_17) {
3538
+ const isSbf = layout.accountSize === V12_17_ACCOUNT_SIZE_SBF;
3539
+ const d1 = isSbf ? 8 : 0;
3540
+ const d2 = isSbf ? 16 : 0;
3541
+ const kindByte2 = readU8(data, base + V12_17_ACCT_KIND_OFF);
3542
+ const kind2 = kindByte2 === 1 ? 1 /* LP */ : 0 /* User */;
3543
+ return {
3544
+ kind: kind2,
3545
+ accountId: 0n,
3546
+ // removed in v12.17
3547
+ capital: readU128LE(data, base + V12_17_ACCT_CAPITAL_OFF),
3548
+ pnl: readI128LE(data, base + V12_17_ACCT_PNL_OFF - d1),
3549
+ reservedPnl: readU128LE(data, base + V12_17_ACCT_RESERVED_PNL_OFF - d1),
3550
+ warmupStartedAtSlot: 0n,
3551
+ // removed
3552
+ warmupSlopePerStep: 0n,
3553
+ // removed
3554
+ positionSize: readI128LE(data, base + V12_17_ACCT_POSITION_BASIS_Q_OFF - d1),
3555
+ entryPrice: 0n,
3556
+ // removed — compute off-chain from position_basis_q / effective_pos_q
3557
+ fundingIndex: 0n,
3558
+ // replaced by per-side f_long_num/f_short_num + per-account f_snap
3559
+ matcherProgram: new PublicKey5(data.subarray(base + V12_17_ACCT_MATCHER_PROGRAM_OFF - d1, base + V12_17_ACCT_MATCHER_PROGRAM_OFF - d1 + 32)),
3560
+ matcherContext: new PublicKey5(data.subarray(base + V12_17_ACCT_MATCHER_CONTEXT_OFF - d1, base + V12_17_ACCT_MATCHER_CONTEXT_OFF - d1 + 32)),
3561
+ owner: new PublicKey5(data.subarray(base + V12_17_ACCT_OWNER_OFF - d1, base + V12_17_ACCT_OWNER_OFF - d1 + 32)),
3562
+ feeCredits: readI128LE(data, base + V12_17_ACCT_FEE_CREDITS_OFF - d1),
3563
+ lastFeeSlot: 0n,
3564
+ // removed
3565
+ feesEarnedTotal: 0n,
3566
+ // removed in v12.17
3567
+ exactReserveCohorts: null,
3568
+ // replaced by two-bucket warmup
3569
+ exactCohortCount: null,
3570
+ overflowOlder: null,
3571
+ overflowOlderPresent: null,
3572
+ overflowNewest: null,
3573
+ overflowNewestPresent: null,
3574
+ // V12_17 fields
3575
+ fSnap: readI128LE(data, base + V12_17_ACCT_F_SNAP_OFF - d1),
3576
+ adlABasis: readU128LE(data, base + V12_17_ACCT_ADL_A_BASIS_OFF - d1),
3577
+ adlKSnap: readI128LE(data, base + V12_17_ACCT_ADL_K_SNAP_OFF - d1),
3578
+ adlEpochSnap: readU64LE(data, base + V12_17_ACCT_ADL_EPOCH_SNAP_OFF - d1),
3579
+ schedPresent: readU8(data, base + V12_17_ACCT_SCHED_PRESENT_OFF - d1) !== 0,
3580
+ schedRemainingQ: readU128LE(data, base + V12_17_ACCT_SCHED_REMAINING_Q_OFF - d1),
3581
+ schedAnchorQ: readU128LE(data, base + V12_17_ACCT_SCHED_ANCHOR_Q_OFF - d1),
3582
+ schedStartSlot: readU64LE(data, base + V12_17_ACCT_SCHED_START_SLOT_OFF - d1),
3583
+ schedHorizon: readU64LE(data, base + V12_17_ACCT_SCHED_HORIZON_OFF - d1),
3584
+ schedReleaseQ: readU128LE(data, base + V12_17_ACCT_SCHED_RELEASE_Q_OFF - d1),
3585
+ pendingPresent: readU8(data, base + V12_17_ACCT_PENDING_PRESENT_OFF - d1) !== 0,
3586
+ pendingRemainingQ: readU128LE(data, base + V12_17_ACCT_PENDING_REMAINING_Q_OFF - d2),
3587
+ pendingHorizon: readU64LE(data, base + V12_17_ACCT_PENDING_HORIZON_OFF - d2),
3588
+ pendingCreatedSlot: readU64LE(data, base + V12_17_ACCT_PENDING_CREATED_SLOT_OFF - d2)
3589
+ };
3590
+ }
3591
+ if (isV12_15) {
3592
+ const kindByte2 = readU8(data, base + V12_15_ACCT_KIND_OFF);
3593
+ const kind2 = kindByte2 === 1 ? 1 /* LP */ : 0 /* User */;
3594
+ const cohortCount = readU8(data, base + V12_15_ACCT_EXACT_COHORT_COUNT_OFF);
3595
+ const exactReserveCohorts = [];
3596
+ for (let i = 0; i < 62; i++) {
3597
+ const cohortOff = base + V12_15_ACCT_EXACT_RESERVE_COHORTS_OFF + i * 64;
3598
+ exactReserveCohorts.push(data.slice(cohortOff, cohortOff + 64));
3599
+ }
3600
+ const overflowOlderPresent = readU8(data, base + V12_15_ACCT_OVERFLOW_OLDER_PRESENT_OFF) !== 0;
3601
+ const overflowNewestPresent = readU8(data, base + V12_15_ACCT_OVERFLOW_NEWEST_PRESENT_OFF) !== 0;
3602
+ return {
3603
+ kind: kind2,
3604
+ accountId: readU64LE(data, base + V12_15_ACCT_ACCOUNT_ID_OFF),
3605
+ capital: readU128LE(data, base + V12_15_ACCT_CAPITAL_OFF),
3606
+ pnl: readI128LE(data, base + V12_15_ACCT_PNL_OFF),
3607
+ reservedPnl: readU128LE(data, base + V12_15_ACCT_RESERVED_PNL_OFF),
3608
+ warmupStartedAtSlot: 0n,
3609
+ // removed in v12.15
3610
+ warmupSlopePerStep: 0n,
3611
+ // removed in v12.15
3612
+ positionSize: readI128LE(data, base + V12_15_ACCT_POSITION_BASIS_Q_OFF),
3613
+ entryPrice: readU64LE(data, base + V12_15_ACCT_ENTRY_PRICE_OFF),
3614
+ fundingIndex: 0n,
3615
+ // not present in v12.15 account struct
3616
+ matcherProgram: new PublicKey5(data.subarray(base + V12_15_ACCT_MATCHER_PROGRAM_OFF, base + V12_15_ACCT_MATCHER_PROGRAM_OFF + 32)),
3617
+ matcherContext: new PublicKey5(data.subarray(base + V12_15_ACCT_MATCHER_CONTEXT_OFF, base + V12_15_ACCT_MATCHER_CONTEXT_OFF + 32)),
3618
+ owner: new PublicKey5(data.subarray(base + V12_15_ACCT_OWNER_OFF, base + V12_15_ACCT_OWNER_OFF + 32)),
3619
+ feeCredits: readI128LE(data, base + V12_15_ACCT_FEE_CREDITS_OFF),
3620
+ lastFeeSlot: 0n,
3621
+ // removed in v12.15
3622
+ feesEarnedTotal: readU128LE(data, base + V12_15_ACCT_FEES_EARNED_TOTAL_OFF),
3623
+ exactReserveCohorts,
3624
+ exactCohortCount: cohortCount,
3625
+ overflowOlder: data.slice(base + V12_15_ACCT_OVERFLOW_OLDER_OFF, base + V12_15_ACCT_OVERFLOW_OLDER_OFF + 64),
3626
+ overflowOlderPresent,
3627
+ overflowNewest: data.slice(base + V12_15_ACCT_OVERFLOW_NEWEST_OFF, base + V12_15_ACCT_OVERFLOW_NEWEST_OFF + 64),
3628
+ overflowNewestPresent,
3629
+ // v12.17 fields (not present in v12.15)
3630
+ fSnap: 0n,
3631
+ adlABasis: 0n,
3632
+ adlKSnap: 0n,
3633
+ adlEpochSnap: 0n,
3634
+ schedPresent: null,
3635
+ schedRemainingQ: null,
3636
+ schedAnchorQ: null,
3637
+ schedStartSlot: null,
3638
+ schedHorizon: null,
3639
+ schedReleaseQ: null,
3640
+ pendingPresent: null,
3641
+ pendingRemainingQ: null,
3642
+ pendingHorizon: null,
3643
+ pendingCreatedSlot: null
3644
+ };
3645
+ }
2623
3646
  const warmupStartedOff = isAdl ? V_ADL_ACCT_WARMUP_STARTED_OFF : ACCT_WARMUP_STARTED_OFF;
2624
3647
  const warmupSlopeOff = isAdl ? V_ADL_ACCT_WARMUP_SLOPE_OFF : ACCT_WARMUP_SLOPE_OFF;
2625
- const positionSizeOff = isV12_1 ? V12_1_ACCT_POSITION_SIZE_OFF : isAdl ? V_ADL_ACCT_POSITION_SIZE_OFF : ACCT_POSITION_SIZE_OFF;
2626
- const entryPriceOff = isV12_1 ? V12_1_ACCT_ENTRY_PRICE_OFF : isAdl ? V_ADL_ACCT_ENTRY_PRICE_OFF : ACCT_ENTRY_PRICE_OFF;
2627
- const fundingIndexOff = isV12_1 ? V12_1_ACCT_FUNDING_INDEX_OFF : isAdl ? V_ADL_ACCT_FUNDING_INDEX_OFF : ACCT_FUNDING_INDEX_OFF;
2628
- const matcherProgOff = isV12_1 ? V12_1_ACCT_MATCHER_PROGRAM_OFF : isAdl ? V_ADL_ACCT_MATCHER_PROGRAM_OFF : ACCT_MATCHER_PROGRAM_OFF;
2629
- const matcherCtxOff = isV12_1 ? V12_1_ACCT_MATCHER_CONTEXT_OFF : isAdl ? V_ADL_ACCT_MATCHER_CONTEXT_OFF : ACCT_MATCHER_CONTEXT_OFF;
2630
- const feeCreditsOff = isV12_1 ? V12_1_ACCT_FEE_CREDITS_OFF : isAdl ? V_ADL_ACCT_FEE_CREDITS_OFF : ACCT_FEE_CREDITS_OFF;
2631
- const lastFeeSlotOff = isV12_1 ? V12_1_ACCT_LAST_FEE_SLOT_OFF : isAdl ? V_ADL_ACCT_LAST_FEE_SLOT_OFF : ACCT_LAST_FEE_SLOT_OFF;
3648
+ const positionSizeOff = isV12_1 || isV12_1EP ? V12_1_ACCT_POSITION_SIZE_OFF : isAdl ? V_ADL_ACCT_POSITION_SIZE_OFF : ACCT_POSITION_SIZE_OFF;
3649
+ 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;
3650
+ const fundingIndexOff = isV12_1 || isV12_1EP ? -1 : isAdl ? V_ADL_ACCT_FUNDING_INDEX_OFF : ACCT_FUNDING_INDEX_OFF;
3651
+ 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;
3652
+ 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;
3653
+ 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;
3654
+ 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;
2632
3655
  const kindByte = readU8(data, base + ACCT_KIND_OFF);
2633
3656
  const kind = kindByte === 1 ? 1 /* LP */ : 0 /* User */;
2634
3657
  return {
@@ -2640,14 +3663,38 @@ function parseAccount(data, idx) {
2640
3663
  warmupStartedAtSlot: readU64LE(data, base + warmupStartedOff),
2641
3664
  warmupSlopePerStep: readU128LE(data, base + warmupSlopeOff),
2642
3665
  positionSize: readI128LE(data, base + positionSizeOff),
2643
- entryPrice: readU64LE(data, base + entryPriceOff),
2644
- // V12_1 changed funding_index from i128 to i64 (legacy field moved to end of account)
2645
- fundingIndex: isV12_1 ? BigInt(readI64LE(data, base + fundingIndexOff)) : readI128LE(data, base + fundingIndexOff),
2646
- matcherProgram: new PublicKey3(data.subarray(base + matcherProgOff, base + matcherProgOff + 32)),
2647
- matcherContext: new PublicKey3(data.subarray(base + matcherCtxOff, base + matcherCtxOff + 32)),
2648
- owner: new PublicKey3(data.subarray(base + layout.acctOwnerOff, base + layout.acctOwnerOff + 32)),
3666
+ entryPrice: entryPriceOff >= 0 ? readU64LE(data, base + entryPriceOff) : 0n,
3667
+ // V12_1/V12_1_EP: funding_index not present in SBF layout
3668
+ fundingIndex: isV12_1 || isV12_1EP ? fundingIndexOff >= 0 ? BigInt(readI64LE(data, base + fundingIndexOff)) : 0n : readI128LE(data, base + fundingIndexOff),
3669
+ matcherProgram: new PublicKey5(data.subarray(base + matcherProgOff, base + matcherProgOff + 32)),
3670
+ matcherContext: new PublicKey5(data.subarray(base + matcherCtxOff, base + matcherCtxOff + 32)),
3671
+ owner: new PublicKey5(data.subarray(base + layout.acctOwnerOff, base + layout.acctOwnerOff + 32)),
2649
3672
  feeCredits: readI128LE(data, base + feeCreditsOff),
2650
- lastFeeSlot: readU64LE(data, base + lastFeeSlotOff)
3673
+ lastFeeSlot: readU64LE(data, base + lastFeeSlotOff),
3674
+ feesEarnedTotal: 0n,
3675
+ // not present in pre-v12.15 layouts
3676
+ exactReserveCohorts: null,
3677
+ // not present in pre-v12.15 layouts
3678
+ exactCohortCount: null,
3679
+ overflowOlder: null,
3680
+ overflowOlderPresent: null,
3681
+ overflowNewest: null,
3682
+ overflowNewestPresent: null,
3683
+ // v12.17 fields (not present in pre-v12.17)
3684
+ fSnap: 0n,
3685
+ adlABasis: 0n,
3686
+ adlKSnap: 0n,
3687
+ adlEpochSnap: 0n,
3688
+ schedPresent: null,
3689
+ schedRemainingQ: null,
3690
+ schedAnchorQ: null,
3691
+ schedStartSlot: null,
3692
+ schedHorizon: null,
3693
+ schedReleaseQ: null,
3694
+ pendingPresent: null,
3695
+ pendingRemainingQ: null,
3696
+ pendingHorizon: null,
3697
+ pendingCreatedSlot: null
2651
3698
  };
2652
3699
  }
2653
3700
  function parseAllAccounts(data) {
@@ -2667,14 +3714,20 @@ function parseAllAccounts(data) {
2667
3714
  }
2668
3715
 
2669
3716
  // src/solana/pda.ts
2670
- import { PublicKey as PublicKey4 } from "@solana/web3.js";
3717
+ import { PublicKey as PublicKey6 } from "@solana/web3.js";
2671
3718
  var textEncoder = new TextEncoder();
2672
3719
  function deriveVaultAuthority(programId, slab) {
2673
- return PublicKey4.findProgramAddressSync(
3720
+ return PublicKey6.findProgramAddressSync(
2674
3721
  [textEncoder.encode("vault"), slab.toBytes()],
2675
3722
  programId
2676
3723
  );
2677
3724
  }
3725
+ function deriveInsuranceLpMint(programId, slab) {
3726
+ return PublicKey6.findProgramAddressSync(
3727
+ [textEncoder.encode("ins_lp"), slab.toBytes()],
3728
+ programId
3729
+ );
3730
+ }
2678
3731
  var LP_INDEX_U16_MAX = 65535;
2679
3732
  function deriveLpPda(programId, slab, lpIdx) {
2680
3733
  if (typeof lpIdx !== "number" || !Number.isInteger(lpIdx) || lpIdx < 0 || lpIdx > LP_INDEX_U16_MAX) {
@@ -2682,34 +3735,28 @@ function deriveLpPda(programId, slab, lpIdx) {
2682
3735
  `deriveLpPda: lpIdx must be an integer in [0, ${LP_INDEX_U16_MAX}], got ${lpIdx}`
2683
3736
  );
2684
3737
  }
2685
- const idxBuf = new Uint8Array(2);
2686
- new DataView(idxBuf.buffer).setUint16(0, lpIdx, true);
2687
- return PublicKey4.findProgramAddressSync(
2688
- [textEncoder.encode("lp"), slab.toBytes(), idxBuf],
3738
+ const idxBuf2 = new Uint8Array(2);
3739
+ new DataView(idxBuf2.buffer).setUint16(0, lpIdx, true);
3740
+ return PublicKey6.findProgramAddressSync(
3741
+ [textEncoder.encode("lp"), slab.toBytes(), idxBuf2],
2689
3742
  programId
2690
3743
  );
2691
3744
  }
2692
- function deriveKeeperFund(programId, slab) {
2693
- return PublicKey4.findProgramAddressSync(
2694
- [textEncoder.encode("keeper_fund"), slab.toBytes()],
2695
- programId
2696
- );
2697
- }
2698
- var PUMPSWAP_PROGRAM_ID = new PublicKey4(
3745
+ var PUMPSWAP_PROGRAM_ID = new PublicKey6(
2699
3746
  "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA"
2700
3747
  );
2701
- var RAYDIUM_CLMM_PROGRAM_ID = new PublicKey4(
3748
+ var RAYDIUM_CLMM_PROGRAM_ID = new PublicKey6(
2702
3749
  "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK"
2703
3750
  );
2704
- var METEORA_DLMM_PROGRAM_ID = new PublicKey4(
3751
+ var METEORA_DLMM_PROGRAM_ID = new PublicKey6(
2705
3752
  "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo"
2706
3753
  );
2707
- var PYTH_PUSH_ORACLE_PROGRAM_ID = new PublicKey4(
3754
+ var PYTH_PUSH_ORACLE_PROGRAM_ID = new PublicKey6(
2708
3755
  "pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT"
2709
3756
  );
2710
3757
  var CREATOR_LOCK_SEED = "creator_lock";
2711
3758
  function deriveCreatorLockPda(programId, slab) {
2712
- return PublicKey4.findProgramAddressSync(
3759
+ return PublicKey6.findProgramAddressSync(
2713
3760
  [textEncoder.encode(CREATOR_LOCK_SEED), slab.toBytes()],
2714
3761
  programId
2715
3762
  );
@@ -2731,17 +3778,10 @@ function derivePythPushOraclePDA(feedIdHex) {
2731
3778
  }
2732
3779
  const feedId = new Uint8Array(32);
2733
3780
  for (let i = 0; i < 32; i++) {
2734
- const hexPair = normalized.substring(i * 2, i * 2 + 2);
2735
- const byte = parseInt(hexPair, 16);
2736
- if (Number.isNaN(byte)) {
2737
- throw new Error(
2738
- `derivePythPushOraclePDA: failed to parse hex byte at position ${i}: "${hexPair}"`
2739
- );
2740
- }
2741
- feedId[i] = byte;
3781
+ feedId[i] = parseInt(normalized.substring(i * 2, i * 2 + 2), 16);
2742
3782
  }
2743
3783
  const shardBuf = new Uint8Array(2);
2744
- return PublicKey4.findProgramAddressSync(
3784
+ return PublicKey6.findProgramAddressSync(
2745
3785
  [shardBuf, feedId],
2746
3786
  PYTH_PUSH_ORACLE_PROGRAM_ID
2747
3787
  );
@@ -2765,14 +3805,12 @@ async function fetchTokenAccount(connection, address, tokenProgramId = TOKEN_PRO
2765
3805
  }
2766
3806
 
2767
3807
  // src/solana/discovery.ts
2768
- import { PublicKey as PublicKey6 } from "@solana/web3.js";
3808
+ import { PublicKey as PublicKey8 } from "@solana/web3.js";
2769
3809
 
2770
3810
  // src/solana/static-markets.ts
2771
- import { PublicKey as PublicKey5 } from "@solana/web3.js";
3811
+ import { PublicKey as PublicKey7 } from "@solana/web3.js";
2772
3812
  var MAINNET_MARKETS = [
2773
- // Populated at mainnet launch currently empty.
2774
- // To add entries:
2775
- // { slabAddress: "ABC123...", symbol: "SOL-PERP", name: "SOL Perpetual" },
3813
+ { slabAddress: "7psyeWRts4pRX2cyAWD1NH87bR9ugXP7pe6ARgfG79Do", symbol: "SOL-PERP", name: "SOL/USDC Perpetual" }
2776
3814
  ];
2777
3815
  var DEVNET_MARKETS = [
2778
3816
  // Populated from prior discoverMarkets() runs on devnet.
@@ -2806,7 +3844,7 @@ function registerStaticMarkets(network, entries) {
2806
3844
  if (!entry.slabAddress) continue;
2807
3845
  if (seen.has(entry.slabAddress)) continue;
2808
3846
  try {
2809
- new PublicKey5(entry.slabAddress);
3847
+ new PublicKey7(entry.slabAddress);
2810
3848
  } catch {
2811
3849
  console.warn(
2812
3850
  `[registerStaticMarkets] Skipping invalid slabAddress: ${entry.slabAddress}`
@@ -2830,10 +3868,9 @@ function clearStaticMarkets(network) {
2830
3868
  var ENGINE_BITMAP_OFF_V0 = 320;
2831
3869
  var MAGIC_BYTES = new Uint8Array([84, 65, 76, 79, 67, 82, 69, 80]);
2832
3870
  var SLAB_TIERS = {
2833
- micro: SLAB_TIERS_V12_1["micro"],
2834
- small: SLAB_TIERS_V12_1["small"],
2835
- medium: SLAB_TIERS_V12_1["medium"],
2836
- large: SLAB_TIERS_V12_1["large"]
3871
+ small: SLAB_TIERS_V12_17["small"],
3872
+ medium: SLAB_TIERS_V12_17["medium"],
3873
+ large: SLAB_TIERS_V12_17["large"]
2837
3874
  };
2838
3875
  var SLAB_TIERS_V0 = {
2839
3876
  small: { maxAccounts: 256, dataSize: 62808, label: "Small", description: "256 slots \xB7 ~0.44 SOL" },
@@ -2940,6 +3977,8 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
2940
3977
  fundingIndexQpbE6: readI128LE2(data, base + 112),
2941
3978
  lastFundingSlot: readU64LE2(data, base + 128),
2942
3979
  fundingRateBpsPerSlotLast: readI64LE2(data, base + 136),
3980
+ fundingRateE9: 0n,
3981
+ marketMode: null,
2943
3982
  lastCrankSlot: readU64LE2(data, base + 144),
2944
3983
  maxCrankStalenessSlots: readU64LE2(data, base + 152),
2945
3984
  totalOpenInterest: readU128LE2(data, base + 160),
@@ -2947,6 +3986,7 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
2947
3986
  shortOi: 0n,
2948
3987
  cTot: readU128LE2(data, base + 176),
2949
3988
  pnlPosTot: readU128LE2(data, base + 192),
3989
+ pnlMaturedPosTot: 0n,
2950
3990
  liqCursor: readU16LE2(data, base + 208),
2951
3991
  gcCursor: readU16LE2(data, base + 210),
2952
3992
  lastSweepStartSlot: readU64LE2(data, base + 216),
@@ -2964,6 +4004,14 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
2964
4004
  lastBreakerSlot: 0n,
2965
4005
  markPriceE6: 0n,
2966
4006
  // V0 engine has no mark_price field
4007
+ oraclePriceE6: 0n,
4008
+ fLongNum: 0n,
4009
+ fShortNum: 0n,
4010
+ negPnlAccountCount: 0n,
4011
+ fundPxLast: 0n,
4012
+ resolvedKLongTerminalDelta: 0n,
4013
+ resolvedKShortTerminalDelta: 0n,
4014
+ resolvedLivePrice: 0n,
2967
4015
  numUsedAccounts: canReadNumUsed ? readU16LE2(data, base + numUsedOff) : 0,
2968
4016
  nextAccountId: canReadNextId ? readU64LE2(data, base + nextAccountIdOff) : 0n
2969
4017
  };
@@ -2982,6 +4030,8 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
2982
4030
  fundingIndexQpbE6: readI128LE2(data, base + 360),
2983
4031
  lastFundingSlot: readU64LE2(data, base + 376),
2984
4032
  fundingRateBpsPerSlotLast: readI64LE2(data, base + 384),
4033
+ fundingRateE9: 0n,
4034
+ marketMode: null,
2985
4035
  lastCrankSlot: readU64LE2(data, base + 392),
2986
4036
  maxCrankStalenessSlots: readU64LE2(data, base + 400),
2987
4037
  totalOpenInterest: readU128LE2(data, base + 408),
@@ -2991,6 +4041,7 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
2991
4041
  // V2 has no short_oi
2992
4042
  cTot: readU128LE2(data, base + 424),
2993
4043
  pnlPosTot: readU128LE2(data, base + 440),
4044
+ pnlMaturedPosTot: 0n,
2994
4045
  liqCursor: readU16LE2(data, base + 456),
2995
4046
  gcCursor: readU16LE2(data, base + 458),
2996
4047
  lastSweepStartSlot: readU64LE2(data, base + 464),
@@ -3009,6 +4060,14 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3009
4060
  lastBreakerSlot: 0n,
3010
4061
  markPriceE6: 0n,
3011
4062
  // V2 has no mark_price
4063
+ oraclePriceE6: 0n,
4064
+ fLongNum: 0n,
4065
+ fShortNum: 0n,
4066
+ negPnlAccountCount: 0n,
4067
+ fundPxLast: 0n,
4068
+ resolvedKLongTerminalDelta: 0n,
4069
+ resolvedKShortTerminalDelta: 0n,
4070
+ resolvedLivePrice: 0n,
3012
4071
  numUsedAccounts: canReadNumUsed ? readU16LE2(data, base + numUsedOff) : 0,
3013
4072
  nextAccountId: canReadNextId ? readU64LE2(data, base + nextAccountIdOff) : 0n
3014
4073
  };
@@ -3028,6 +4087,8 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3028
4087
  fundingIndexQpbE6: readI128LE2(data, base + l.engineFundingIndexOff),
3029
4088
  lastFundingSlot: readU64LE2(data, base + l.engineLastFundingSlotOff),
3030
4089
  fundingRateBpsPerSlotLast: readI64LE2(data, base + l.engineFundingRateBpsOff),
4090
+ fundingRateE9: 0n,
4091
+ marketMode: null,
3031
4092
  lastCrankSlot: readU64LE2(data, base + l.engineLastCrankSlotOff),
3032
4093
  maxCrankStalenessSlots: readU64LE2(data, base + l.engineMaxCrankStalenessOff),
3033
4094
  totalOpenInterest: readU128LE2(data, base + l.engineTotalOiOff),
@@ -3035,6 +4096,7 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3035
4096
  shortOi: l.engineShortOiOff >= 0 ? readU128LE2(data, base + l.engineShortOiOff) : 0n,
3036
4097
  cTot: readU128LE2(data, base + l.engineCTotOff),
3037
4098
  pnlPosTot: readU128LE2(data, base + l.enginePnlPosTotOff),
4099
+ pnlMaturedPosTot: 0n,
3038
4100
  liqCursor: readU16LE2(data, base + l.engineLiqCursorOff),
3039
4101
  gcCursor: readU16LE2(data, base + l.engineGcCursorOff),
3040
4102
  lastSweepStartSlot: readU64LE2(data, base + l.engineLastSweepStartOff),
@@ -3051,6 +4113,14 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3051
4113
  emergencyStartSlot: l.engineEmergencyStartSlotOff >= 0 ? readU64LE2(data, base + l.engineEmergencyStartSlotOff) : 0n,
3052
4114
  lastBreakerSlot: l.engineLastBreakerSlotOff >= 0 ? readU64LE2(data, base + l.engineLastBreakerSlotOff) : 0n,
3053
4115
  markPriceE6: l.engineMarkPriceOff >= 0 ? readU64LE2(data, base + l.engineMarkPriceOff) : 0n,
4116
+ oraclePriceE6: 0n,
4117
+ fLongNum: 0n,
4118
+ fShortNum: 0n,
4119
+ negPnlAccountCount: 0n,
4120
+ fundPxLast: 0n,
4121
+ resolvedKLongTerminalDelta: 0n,
4122
+ resolvedKShortTerminalDelta: 0n,
4123
+ resolvedLivePrice: 0n,
3054
4124
  numUsedAccounts: canReadNumUsed ? readU16LE2(data, base + numUsedOff) : 0,
3055
4125
  nextAccountId: canReadNextId ? readU64LE2(data, base + nextAccountIdOff) : 0n
3056
4126
  };
@@ -3068,6 +4138,8 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3068
4138
  fundingIndexQpbE6: readI128LE2(data, base + 368),
3069
4139
  lastFundingSlot: readU64LE2(data, base + 384),
3070
4140
  fundingRateBpsPerSlotLast: readI64LE2(data, base + 392),
4141
+ fundingRateE9: 0n,
4142
+ marketMode: null,
3071
4143
  lastCrankSlot: readU64LE2(data, base + 424),
3072
4144
  maxCrankStalenessSlots: readU64LE2(data, base + 408),
3073
4145
  totalOpenInterest: readU128LE2(data, base + 416),
@@ -3075,6 +4147,7 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3075
4147
  shortOi: readU128LE2(data, base + 448),
3076
4148
  cTot: readU128LE2(data, base + 464),
3077
4149
  pnlPosTot: readU128LE2(data, base + 480),
4150
+ pnlMaturedPosTot: 0n,
3078
4151
  liqCursor: readU16LE2(data, base + 496),
3079
4152
  gcCursor: readU16LE2(data, base + 498),
3080
4153
  lastSweepStartSlot: readU64LE2(data, base + 504),
@@ -3092,6 +4165,14 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3092
4165
  lastBreakerSlot: readU64LE2(data, base + 624),
3093
4166
  markPriceE6: readU64LE2(data, base + 400),
3094
4167
  // PERC-1094: was 392
4168
+ oraclePriceE6: 0n,
4169
+ fLongNum: 0n,
4170
+ fShortNum: 0n,
4171
+ negPnlAccountCount: 0n,
4172
+ fundPxLast: 0n,
4173
+ resolvedKLongTerminalDelta: 0n,
4174
+ resolvedKShortTerminalDelta: 0n,
4175
+ resolvedLivePrice: 0n,
3095
4176
  numUsedAccounts: canReadNumUsed ? readU16LE2(data, base + numUsedOff) : 0,
3096
4177
  nextAccountId: canReadNextId ? readU64LE2(data, base + nextAccountIdOff) : 0n
3097
4178
  };
@@ -3113,12 +4194,19 @@ async function discoverMarkets(connection, programId, options = {}) {
3113
4194
  } = options;
3114
4195
  const ALL_TIERS = [
3115
4196
  ...Object.values(SLAB_TIERS),
4197
+ // v12.17 (default)
4198
+ ...Object.values(SLAB_TIERS_V12_15),
4199
+ // v12.15
4200
+ ...Object.values(SLAB_TIERS_V12_1),
4201
+ // v12.1
3116
4202
  ...Object.values(SLAB_TIERS_V0),
3117
4203
  ...Object.values(SLAB_TIERS_V1D),
3118
4204
  ...Object.values(SLAB_TIERS_V1D_LEGACY),
3119
4205
  ...Object.values(SLAB_TIERS_V2),
3120
4206
  ...Object.values(SLAB_TIERS_V1M),
3121
- ...Object.values(SLAB_TIERS_V_ADL)
4207
+ ...Object.values(SLAB_TIERS_V1M2),
4208
+ ...Object.values(SLAB_TIERS_V_ADL),
4209
+ ...Object.values(SLAB_TIERS_V_SETDEXPOOL)
3122
4210
  ];
3123
4211
  let rawAccounts = [];
3124
4212
  async function fetchTierWithRetry(tier) {
@@ -3416,7 +4504,7 @@ async function discoverMarketsViaApi(connection, programId, apiBaseUrl, options
3416
4504
  for (const entry of apiMarkets) {
3417
4505
  if (!entry.slab_address || typeof entry.slab_address !== "string") continue;
3418
4506
  try {
3419
- addresses.push(new PublicKey6(entry.slab_address));
4507
+ addresses.push(new PublicKey8(entry.slab_address));
3420
4508
  } catch {
3421
4509
  console.warn(
3422
4510
  `[discoverMarketsViaApi] Skipping invalid slab address: ${entry.slab_address}`
@@ -3438,7 +4526,7 @@ async function discoverMarketsViaStaticBundle(connection, programId, entries, op
3438
4526
  for (const entry of entries) {
3439
4527
  if (!entry.slabAddress || typeof entry.slabAddress !== "string") continue;
3440
4528
  try {
3441
- addresses.push(new PublicKey6(entry.slabAddress));
4529
+ addresses.push(new PublicKey8(entry.slabAddress));
3442
4530
  } catch {
3443
4531
  console.warn(
3444
4532
  `[discoverMarketsViaStaticBundle] Skipping invalid slab address: ${entry.slabAddress}`
@@ -3456,7 +4544,7 @@ async function discoverMarketsViaStaticBundle(connection, programId, entries, op
3456
4544
  }
3457
4545
 
3458
4546
  // src/solana/dex-oracle.ts
3459
- import { PublicKey as PublicKey7 } from "@solana/web3.js";
4547
+ import { PublicKey as PublicKey9 } from "@solana/web3.js";
3460
4548
  function detectDexType(ownerProgramId) {
3461
4549
  if (ownerProgramId.equals(PUMPSWAP_PROGRAM_ID)) return "pumpswap";
3462
4550
  if (ownerProgramId.equals(RAYDIUM_CLMM_PROGRAM_ID)) return "raydium-clmm";
@@ -3492,10 +4580,10 @@ function parsePumpSwapPool(poolAddress, data) {
3492
4580
  return {
3493
4581
  dexType: "pumpswap",
3494
4582
  poolAddress,
3495
- baseMint: new PublicKey7(data.slice(35, 67)),
3496
- quoteMint: new PublicKey7(data.slice(67, 99)),
3497
- baseVault: new PublicKey7(data.slice(131, 163)),
3498
- quoteVault: new PublicKey7(data.slice(163, 195))
4583
+ baseMint: new PublicKey9(data.slice(35, 67)),
4584
+ quoteMint: new PublicKey9(data.slice(67, 99)),
4585
+ baseVault: new PublicKey9(data.slice(131, 163)),
4586
+ quoteVault: new PublicKey9(data.slice(163, 195))
3499
4587
  };
3500
4588
  }
3501
4589
  var SPL_TOKEN_AMOUNT_MIN_LEN = 72;
@@ -3521,8 +4609,8 @@ function parseRaydiumClmmPool(poolAddress, data) {
3521
4609
  return {
3522
4610
  dexType: "raydium-clmm",
3523
4611
  poolAddress,
3524
- baseMint: new PublicKey7(data.slice(73, 105)),
3525
- quoteMint: new PublicKey7(data.slice(105, 137))
4612
+ baseMint: new PublicKey9(data.slice(73, 105)),
4613
+ quoteMint: new PublicKey9(data.slice(105, 137))
3526
4614
  };
3527
4615
  }
3528
4616
  var MAX_TOKEN_DECIMALS = 24;
@@ -3540,7 +4628,9 @@ function computeRaydiumClmmPriceE6(data) {
3540
4628
  }
3541
4629
  const sqrtPriceX64 = readU128LE3(dv3, 253);
3542
4630
  if (sqrtPriceX64 === 0n) return 0n;
3543
- const priceE6Raw = sqrtPriceX64 * sqrtPriceX64 * 1000000n >> 128n;
4631
+ const scaledSqrt = sqrtPriceX64 * 1000000n;
4632
+ const term = scaledSqrt >> 64n;
4633
+ const priceE6Raw = term * sqrtPriceX64 >> 64n;
3544
4634
  const decimalDiff = 6 + decimals0 - decimals1;
3545
4635
  const adjustedDiff = decimalDiff - 6;
3546
4636
  if (adjustedDiff >= 0) {
@@ -3559,8 +4649,8 @@ function parseMeteoraPool(poolAddress, data) {
3559
4649
  return {
3560
4650
  dexType: "meteora-dlmm",
3561
4651
  poolAddress,
3562
- baseMint: new PublicKey7(data.slice(81, 113)),
3563
- quoteMint: new PublicKey7(data.slice(113, 145))
4652
+ baseMint: new PublicKey9(data.slice(81, 113)),
4653
+ quoteMint: new PublicKey9(data.slice(113, 145))
3564
4654
  };
3565
4655
  }
3566
4656
  var MAX_BIN_STEP = 1e4;
@@ -3581,26 +4671,13 @@ function computeMeteoraDlmmPriceE6(data) {
3581
4671
  `Meteora DLMM: |activeId| ${Math.abs(activeId)} exceeds max ${MAX_ACTIVE_ID_ABS}`
3582
4672
  );
3583
4673
  }
3584
- const MAX_ABS_BIN_ID = 5e5;
3585
- if (activeId > MAX_ABS_BIN_ID || activeId < -MAX_ABS_BIN_ID) {
3586
- throw new Error(
3587
- `Meteora DLMM: activeId ${activeId} exceeds safe range (\xB1${MAX_ABS_BIN_ID})`
3588
- );
3589
- }
3590
4674
  const SCALE = 1000000000000000000n;
3591
4675
  const base = SCALE + BigInt(binStep) * SCALE / 10000n;
3592
4676
  const isNeg = activeId < 0;
3593
4677
  let exp = isNeg ? BigInt(-activeId) : BigInt(activeId);
3594
4678
  let result = SCALE;
3595
4679
  let b = base;
3596
- let iterations = 0;
3597
- const MAX_ITERATIONS = 25;
3598
4680
  while (exp > 0n) {
3599
- if (iterations++ >= MAX_ITERATIONS) {
3600
- throw new Error(
3601
- `Meteora DLMM: exponentiation loop exceeded ${MAX_ITERATIONS} iterations (activeId=${activeId})`
3602
- );
3603
- }
3604
4681
  if (exp & 1n) {
3605
4682
  result = result * b / SCALE;
3606
4683
  }
@@ -3631,7 +4708,6 @@ function readU128LE3(dv3, offset) {
3631
4708
  var CHAINLINK_MIN_SIZE = 224;
3632
4709
  var MAX_DECIMALS = 18;
3633
4710
  var CHAINLINK_DECIMALS_OFFSET = 138;
3634
- var CHAINLINK_TIMESTAMP_OFFSET = 168;
3635
4711
  var CHAINLINK_ANSWER_OFFSET = 216;
3636
4712
  function readU82(data, off) {
3637
4713
  return data[off];
@@ -3639,7 +4715,7 @@ function readU82(data, off) {
3639
4715
  function readBigInt64LE(data, off) {
3640
4716
  return new DataView(data.buffer, data.byteOffset, data.byteLength).getBigInt64(off, true);
3641
4717
  }
3642
- function parseChainlinkPrice(data, options) {
4718
+ function parseChainlinkPrice(data) {
3643
4719
  if (data.length < CHAINLINK_MIN_SIZE) {
3644
4720
  throw new Error(
3645
4721
  `Oracle account data too small: ${data.length} bytes (need at least ${CHAINLINK_MIN_SIZE})`
@@ -3657,18 +4733,7 @@ function parseChainlinkPrice(data, options) {
3657
4733
  `Oracle price is non-positive: ${price}`
3658
4734
  );
3659
4735
  }
3660
- const updatedAtBig = readBigInt64LE(data, CHAINLINK_TIMESTAMP_OFFSET);
3661
- const updatedAt = Number(updatedAtBig);
3662
- if (options?.maxStalenessSeconds !== void 0 && updatedAt > 0) {
3663
- const now = Math.floor(Date.now() / 1e3);
3664
- const age = now - updatedAt;
3665
- if (age > options.maxStalenessSeconds) {
3666
- throw new Error(
3667
- `Oracle price is stale: last updated ${age}s ago (max ${options.maxStalenessSeconds}s)`
3668
- );
3669
- }
3670
- }
3671
- return { price, decimals, updatedAt: updatedAt > 0 ? updatedAt : void 0 };
4736
+ return { price, decimals };
3672
4737
  }
3673
4738
  function isValidChainlinkOracle(data) {
3674
4739
  try {
@@ -3680,19 +4745,15 @@ function isValidChainlinkOracle(data) {
3680
4745
  }
3681
4746
 
3682
4747
  // src/solana/token-program.ts
3683
- import { PublicKey as PublicKey8 } from "@solana/web3.js";
4748
+ import { PublicKey as PublicKey10 } from "@solana/web3.js";
3684
4749
  import { TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID3 } from "@solana/spl-token";
3685
- var TOKEN_2022_PROGRAM_ID = new PublicKey8(
4750
+ var TOKEN_2022_PROGRAM_ID = new PublicKey10(
3686
4751
  "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
3687
4752
  );
3688
4753
  async function detectTokenProgram(connection, mint) {
3689
4754
  const info = await connection.getAccountInfo(mint);
3690
4755
  if (!info) throw new Error(`Mint account not found: ${mint.toBase58()}`);
3691
- if (info.owner.equals(TOKEN_PROGRAM_ID3)) return TOKEN_PROGRAM_ID3;
3692
- if (info.owner.equals(TOKEN_2022_PROGRAM_ID)) return TOKEN_2022_PROGRAM_ID;
3693
- throw new Error(
3694
- `Mint ${mint.toBase58()} is owned by ${info.owner.toBase58()}, which is neither TOKEN_PROGRAM_ID nor TOKEN_2022_PROGRAM_ID`
3695
- );
4756
+ return info.owner;
3696
4757
  }
3697
4758
  function isToken2022(tokenProgramId) {
3698
4759
  return tokenProgramId.equals(TOKEN_2022_PROGRAM_ID);
@@ -3702,74 +4763,11 @@ function isStandardToken(tokenProgramId) {
3702
4763
  }
3703
4764
 
3704
4765
  // src/solana/stake.ts
3705
- import { PublicKey as PublicKey10, SystemProgram as SystemProgram2, SYSVAR_RENT_PUBKEY as SYSVAR_RENT_PUBKEY2, SYSVAR_CLOCK_PUBKEY as SYSVAR_CLOCK_PUBKEY2 } from "@solana/web3.js";
4766
+ import { PublicKey as PublicKey11, SystemProgram as SystemProgram2, SYSVAR_RENT_PUBKEY as SYSVAR_RENT_PUBKEY2, SYSVAR_CLOCK_PUBKEY as SYSVAR_CLOCK_PUBKEY2 } from "@solana/web3.js";
3706
4767
  import { TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID4 } from "@solana/spl-token";
3707
-
3708
- // src/config/program-ids.ts
3709
- import { PublicKey as PublicKey9 } from "@solana/web3.js";
3710
- function safeEnv(key) {
3711
- try {
3712
- return typeof process !== "undefined" && process?.env ? process.env[key] : void 0;
3713
- } catch {
3714
- return void 0;
3715
- }
3716
- }
3717
- var PROGRAM_IDS = {
3718
- devnet: {
3719
- percolator: "FxfD37s1AZTeWfFQps9Zpebi2dNQ9QSSDtfMKdbsfKrD",
3720
- matcher: "GTRgyTDfrMvBubALAqtHuQwT8tbGyXid7svXZKtWfC9k"
3721
- },
3722
- mainnet: {
3723
- percolator: "GM8zjJ8LTBMv9xEsverh6H6wLyevgMHEJXcEzyY3rY24",
3724
- matcher: "DHP6DtwXP1yJsz8YzfoeigRFPB979gzmumkmCxDLSkUX"
3725
- }
3726
- };
3727
- function getProgramId(network) {
3728
- if (!network) {
3729
- const override = safeEnv("PROGRAM_ID");
3730
- if (override) {
3731
- console.warn(
3732
- `[percolator-sdk] PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
3733
- );
3734
- return new PublicKey9(override);
3735
- }
3736
- }
3737
- const detectedNetwork = getCurrentNetwork();
3738
- const targetNetwork = network ?? detectedNetwork;
3739
- const programId = PROGRAM_IDS[targetNetwork].percolator;
3740
- return new PublicKey9(programId);
3741
- }
3742
- function getMatcherProgramId(network) {
3743
- if (!network) {
3744
- const override = safeEnv("MATCHER_PROGRAM_ID");
3745
- if (override) {
3746
- console.warn(
3747
- `[percolator-sdk] MATCHER_PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
3748
- );
3749
- return new PublicKey9(override);
3750
- }
3751
- }
3752
- const detectedNetwork = getCurrentNetwork();
3753
- const targetNetwork = network ?? detectedNetwork;
3754
- const programId = PROGRAM_IDS[targetNetwork].matcher;
3755
- if (!programId) {
3756
- throw new Error(`Matcher program not deployed on ${targetNetwork}`);
3757
- }
3758
- return new PublicKey9(programId);
3759
- }
3760
- function getCurrentNetwork() {
3761
- const network = safeEnv("NETWORK")?.toLowerCase();
3762
- if (network === "mainnet" || network === "mainnet-beta") {
3763
- return "mainnet";
3764
- }
3765
- return "devnet";
3766
- }
3767
-
3768
- // src/solana/stake.ts
3769
4768
  var STAKE_PROGRAM_IDS = {
3770
4769
  devnet: "6aJb1F9CDCVWCNYFwj8aQsVb696YnW6J1FznteHq4Q6k",
3771
- mainnet: ""
3772
- // TODO: populate once DevOps deploys percolator-stake to mainnet
4770
+ mainnet: "DC5fovFQD5SZYsetwvEqd4Wi4PFY1Yfnc669VMe6oa7F"
3773
4771
  };
3774
4772
  function getStakeProgramId(network) {
3775
4773
  const override = safeEnv("STAKE_PROGRAM_ID");
@@ -3777,11 +4775,14 @@ function getStakeProgramId(network) {
3777
4775
  console.warn(
3778
4776
  `[percolator-sdk] STAKE_PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
3779
4777
  );
3780
- return new PublicKey10(override);
4778
+ return new PublicKey11(override);
3781
4779
  }
3782
4780
  const detectedNetwork = network ?? (() => {
3783
4781
  const n = safeEnv("NEXT_PUBLIC_DEFAULT_NETWORK")?.toLowerCase() ?? safeEnv("NETWORK")?.toLowerCase() ?? "";
3784
- return n === "mainnet" || n === "mainnet-beta" ? "mainnet" : "devnet";
4782
+ if (n === "mainnet" || n === "mainnet-beta") return "mainnet";
4783
+ if (n === "devnet") return "devnet";
4784
+ if (typeof window !== "undefined") return "mainnet";
4785
+ return "devnet";
3785
4786
  })();
3786
4787
  const id = STAKE_PROGRAM_IDS[detectedNetwork];
3787
4788
  if (!id) {
@@ -3789,9 +4790,9 @@ function getStakeProgramId(network) {
3789
4790
  `Stake program not deployed on ${detectedNetwork}. Set STAKE_PROGRAM_ID env var or wait for DevOps to deploy and update STAKE_PROGRAM_IDS.mainnet.`
3790
4791
  );
3791
4792
  }
3792
- return new PublicKey10(id);
4793
+ return new PublicKey11(id);
3793
4794
  }
3794
- var STAKE_PROGRAM_ID = new PublicKey10(STAKE_PROGRAM_IDS.devnet);
4795
+ var STAKE_PROGRAM_ID = new PublicKey11(STAKE_PROGRAM_IDS.devnet);
3795
4796
  var STAKE_IX = {
3796
4797
  InitPool: 0,
3797
4798
  Deposit: 1,
@@ -3816,22 +4817,22 @@ var STAKE_IX = {
3816
4817
  /** PERC-303: Deposit into junior (first-loss) tranche */
3817
4818
  DepositJunior: 16
3818
4819
  };
3819
- var TEXT = new TextEncoder();
4820
+ var TEXT2 = new TextEncoder();
3820
4821
  function deriveStakePool(slab, programId) {
3821
- return PublicKey10.findProgramAddressSync(
3822
- [TEXT.encode("stake_pool"), slab.toBytes()],
4822
+ return PublicKey11.findProgramAddressSync(
4823
+ [TEXT2.encode("stake_pool"), slab.toBytes()],
3823
4824
  programId ?? getStakeProgramId()
3824
4825
  );
3825
4826
  }
3826
4827
  function deriveStakeVaultAuth(pool, programId) {
3827
- return PublicKey10.findProgramAddressSync(
3828
- [TEXT.encode("vault_auth"), pool.toBytes()],
4828
+ return PublicKey11.findProgramAddressSync(
4829
+ [TEXT2.encode("vault_auth"), pool.toBytes()],
3829
4830
  programId ?? getStakeProgramId()
3830
4831
  );
3831
4832
  }
3832
4833
  function deriveDepositPda(pool, user, programId) {
3833
- return PublicKey10.findProgramAddressSync(
3834
- [TEXT.encode("deposit"), pool.toBytes(), user.toBytes()],
4834
+ return PublicKey11.findProgramAddressSync(
4835
+ [TEXT2.encode("stake_deposit"), pool.toBytes(), user.toBytes()],
3835
4836
  programId ?? getStakeProgramId()
3836
4837
  );
3837
4838
  }
@@ -3852,9 +4853,6 @@ function readU16LE3(data, off) {
3852
4853
  );
3853
4854
  }
3854
4855
  function u64Le(v) {
3855
- if (typeof v === "number" && !Number.isSafeInteger(v)) {
3856
- throw new Error(`u64Le: number ${v} exceeds Number.MAX_SAFE_INTEGER \u2014 use BigInt`);
3857
- }
3858
4856
  const big = BigInt(v);
3859
4857
  if (big < 0n) throw new Error(`u64Le: value must be non-negative, got ${big}`);
3860
4858
  if (big > 0xFFFFFFFFFFFFFFFFn) throw new Error(`u64Le: value exceeds u64 max`);
@@ -3863,9 +4861,6 @@ function u64Le(v) {
3863
4861
  return arr;
3864
4862
  }
3865
4863
  function u128Le(v) {
3866
- if (typeof v === "number" && !Number.isSafeInteger(v)) {
3867
- throw new Error(`u128Le: number ${v} exceeds Number.MAX_SAFE_INTEGER \u2014 use BigInt`);
3868
- }
3869
4864
  const big = BigInt(v);
3870
4865
  if (big < 0n) throw new Error(`u128Le: value must be non-negative, got ${big}`);
3871
4866
  if (big > (1n << 128n) - 1n) throw new Error(`u128Le: value exceeds u128 max`);
@@ -3876,7 +4871,7 @@ function u128Le(v) {
3876
4871
  return arr;
3877
4872
  }
3878
4873
  function u16Le(v) {
3879
- if (!Number.isInteger(v) || v < 0 || v > 65535) throw new Error(`u16Le: value must be integer in range 0..65535, got ${v}`);
4874
+ if (v < 0 || v > 65535) throw new Error(`u16Le: value out of u16 range (0..65535), got ${v}`);
3880
4875
  const arr = new Uint8Array(2);
3881
4876
  new DataView(arr.buffer).setUint16(0, v, true);
3882
4877
  return arr;
@@ -3987,15 +4982,15 @@ function decodeStakePool(data) {
3987
4982
  const adminTransferred = bytes[off] === 1;
3988
4983
  off += 1;
3989
4984
  off += 4;
3990
- const slab = new PublicKey10(bytes.subarray(off, off + 32));
4985
+ const slab = new PublicKey11(bytes.subarray(off, off + 32));
3991
4986
  off += 32;
3992
- const admin = new PublicKey10(bytes.subarray(off, off + 32));
4987
+ const admin = new PublicKey11(bytes.subarray(off, off + 32));
3993
4988
  off += 32;
3994
- const collateralMint = new PublicKey10(bytes.subarray(off, off + 32));
4989
+ const collateralMint = new PublicKey11(bytes.subarray(off, off + 32));
3995
4990
  off += 32;
3996
- const lpMint = new PublicKey10(bytes.subarray(off, off + 32));
4991
+ const lpMint = new PublicKey11(bytes.subarray(off, off + 32));
3997
4992
  off += 32;
3998
- const vault = new PublicKey10(bytes.subarray(off, off + 32));
4993
+ const vault = new PublicKey11(bytes.subarray(off, off + 32));
3999
4994
  off += 32;
4000
4995
  const totalDeposited = readU64LE4(bytes, off);
4001
4996
  off += 8;
@@ -4011,7 +5006,7 @@ function decodeStakePool(data) {
4011
5006
  off += 8;
4012
5007
  const totalWithdrawn = readU64LE4(bytes, off);
4013
5008
  off += 8;
4014
- const percolatorProgram = new PublicKey10(bytes.subarray(off, off + 32));
5009
+ const percolatorProgram = new PublicKey11(bytes.subarray(off, off + 32));
4015
5010
  off += 32;
4016
5011
  const totalFeesEarned = readU64LE4(bytes, off);
4017
5012
  off += 8;
@@ -4063,6 +5058,20 @@ function decodeStakePool(data) {
4063
5058
  juniorFeeMultBps
4064
5059
  };
4065
5060
  }
5061
+ var STAKE_DEPOSIT_SIZE = 152;
5062
+ function decodeDepositPda(data) {
5063
+ if (data.length < STAKE_DEPOSIT_SIZE) {
5064
+ throw new Error(`StakeDeposit data too short: ${data.length} < ${STAKE_DEPOSIT_SIZE}`);
5065
+ }
5066
+ return {
5067
+ isInitialized: data[0] === 1,
5068
+ bump: data[1],
5069
+ pool: new PublicKey11(data.subarray(8, 40)),
5070
+ user: new PublicKey11(data.subarray(40, 72)),
5071
+ lastDepositSlot: readU64LE4(data, 72),
5072
+ lpAmount: readU64LE4(data, 80)
5073
+ };
5074
+ }
4066
5075
  function initPoolAccounts(a) {
4067
5076
  return [
4068
5077
  { pubkey: a.admin, isSigner: true, isWritable: true },
@@ -4131,9 +5140,7 @@ function computePnlPct(pnl, capital) {
4131
5140
  }
4132
5141
  function isAdlTriggered(slabData) {
4133
5142
  const layout = detectSlabLayout(slabData.length);
4134
- if (!layout) {
4135
- return false;
4136
- }
5143
+ if (!layout) return false;
4137
5144
  try {
4138
5145
  const engine = parseEngine(slabData);
4139
5146
  if (engine.pnlPosTot === 0n) return false;
@@ -4176,14 +5183,6 @@ function rankAdlPositions(slabData) {
4176
5183
  if (account.kind !== 0 /* User */) continue;
4177
5184
  if (account.positionSize === 0n) continue;
4178
5185
  const side = account.positionSize > 0n ? "long" : "short";
4179
- if (side === "long" && account.positionSize <= 0n) {
4180
- console.warn(`[fetchAdlRankedPositions] account idx=${idx}: side=long but positionSize=${account.positionSize}`);
4181
- continue;
4182
- }
4183
- if (side === "short" && account.positionSize >= 0n) {
4184
- console.warn(`[fetchAdlRankedPositions] account idx=${idx}: side=short but positionSize=${account.positionSize}`);
4185
- continue;
4186
- }
4187
5186
  const pnlPct = computePnlPct(account.pnl, account.capital);
4188
5187
  positions.push({
4189
5188
  idx,
@@ -4216,8 +5215,7 @@ function buildAdlInstruction(caller, slab, oracle, programId, targetIdx, backupO
4216
5215
  `buildAdlInstruction: targetIdx must be a non-negative integer, got ${targetIdx}`
4217
5216
  );
4218
5217
  }
4219
- const dataBytes = encodeExecuteAdl({ targetIdx });
4220
- const data = Buffer.from(dataBytes);
5218
+ const data = Buffer.from(encodeExecuteAdl({ targetIdx }));
4221
5219
  const keys = [
4222
5220
  { pubkey: caller, isSigner: true, isWritable: false },
4223
5221
  { pubkey: slab, isSigner: false, isWritable: true },
@@ -4257,11 +5255,7 @@ function parseAdlEvent(logs) {
4257
5255
  }
4258
5256
  if (tag !== ADL_EVENT_TAG) continue;
4259
5257
  try {
4260
- const targetIdxBig = BigInt(match[2]);
4261
- if (targetIdxBig < 0n || targetIdxBig > 65535n) {
4262
- continue;
4263
- }
4264
- const targetIdx = Number(targetIdxBig);
5258
+ const targetIdx = Number(BigInt(match[2]));
4265
5259
  const price = BigInt(match[3]);
4266
5260
  const closedLo = BigInt(match[4]);
4267
5261
  const closedHi = BigInt(match[5]);
@@ -4289,22 +5283,6 @@ async function fetchAdlRankings(apiBase, slab, fetchFn = fetch) {
4289
5283
  );
4290
5284
  }
4291
5285
  const json = await res.json();
4292
- if (typeof json !== "object" || json === null) {
4293
- throw new Error("fetchAdlRankings: API returned non-object response");
4294
- }
4295
- const obj = json;
4296
- if (!Array.isArray(obj.rankings)) {
4297
- throw new Error("fetchAdlRankings: API response missing rankings array");
4298
- }
4299
- for (const entry of obj.rankings) {
4300
- if (typeof entry !== "object" || entry === null) {
4301
- throw new Error("fetchAdlRankings: invalid ranking entry (not an object)");
4302
- }
4303
- const r = entry;
4304
- if (typeof r.idx !== "number" || !Number.isInteger(r.idx) || r.idx < 0) {
4305
- throw new Error(`fetchAdlRankings: invalid ranking idx: ${r.idx}`);
4306
- }
4307
- }
4308
5286
  return json;
4309
5287
  }
4310
5288
 
@@ -4822,11 +5800,11 @@ function formatResult(result, jsonMode) {
4822
5800
  }
4823
5801
 
4824
5802
  // src/runtime/lighthouse.ts
4825
- import { PublicKey as PublicKey13, Transaction as Transaction2 } from "@solana/web3.js";
4826
- var LIGHTHOUSE_PROGRAM_ID = new PublicKey13(
5803
+ import { PublicKey as PublicKey14, Transaction as Transaction2 } from "@solana/web3.js";
5804
+ var LIGHTHOUSE_PROGRAM_ID = new PublicKey14(
4827
5805
  "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95"
4828
5806
  );
4829
- var LIGHTHOUSE_PROGRAM_ID_STR2 = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
5807
+ var LIGHTHOUSE_PROGRAM_ID_STR = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
4830
5808
  var LIGHTHOUSE_CONSTRAINT_ADDRESS = 6400;
4831
5809
  var LIGHTHOUSE_ERROR_CODES = /* @__PURE__ */ new Set([
4832
5810
  6e3,
@@ -4872,7 +5850,7 @@ function isLighthouseInstruction(ix) {
4872
5850
  function isLighthouseError(error) {
4873
5851
  const msg = extractErrorMessage(error);
4874
5852
  if (!msg) return false;
4875
- if (msg.includes(LIGHTHOUSE_PROGRAM_ID_STR2)) return true;
5853
+ if (msg.includes(LIGHTHOUSE_PROGRAM_ID_STR)) return true;
4876
5854
  if (/custom\s+program\s+error:\s*0x1900\b/i.test(msg)) return true;
4877
5855
  if (/"Custom"\s*:\s*6400\b/.test(msg) && /InstructionError/i.test(msg)) return true;
4878
5856
  return false;
@@ -4882,18 +5860,18 @@ function isLighthouseFailureInLogs(logs) {
4882
5860
  let insideLighthouse = false;
4883
5861
  for (const line of logs) {
4884
5862
  if (typeof line !== "string") continue;
4885
- if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} invoke`)) {
5863
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {
4886
5864
  insideLighthouse = true;
4887
5865
  continue;
4888
5866
  }
4889
- if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} success`)) {
5867
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {
4890
5868
  insideLighthouse = false;
4891
5869
  continue;
4892
5870
  }
4893
5871
  if (insideLighthouse && /failed/i.test(line)) {
4894
5872
  return true;
4895
5873
  }
4896
- if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} failed`)) {
5874
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} failed`)) {
4897
5875
  return true;
4898
5876
  }
4899
5877
  }
@@ -4978,10 +5956,16 @@ function computeLiqPrice(entryPrice, capital, positionSize, maintenanceMarginBps
4978
5956
  function computePreTradeLiqPrice(oracleE6, margin, posSize, maintBps, feeBps, direction) {
4979
5957
  if (oracleE6 === 0n || margin === 0n || posSize === 0n) return 0n;
4980
5958
  const absPos = posSize < 0n ? -posSize : posSize;
4981
- const fee = absPos * feeBps / 10000n;
4982
- const effectiveCapital = margin > fee ? margin - fee : 0n;
4983
5959
  const signedPos = direction === "long" ? absPos : -absPos;
4984
- return computeLiqPrice(oracleE6, effectiveCapital, signedPos, maintBps);
5960
+ const feeAdjust = oracleE6 * feeBps / 10000n;
5961
+ let adjustedEntry;
5962
+ if (direction === "long") {
5963
+ adjustedEntry = oracleE6 + feeAdjust;
5964
+ } else {
5965
+ const shortEntry = oracleE6 - feeAdjust;
5966
+ adjustedEntry = shortEntry > 0n ? shortEntry : 1n;
5967
+ }
5968
+ return computeLiqPrice(adjustedEntry, margin, signedPos, maintBps);
4985
5969
  }
4986
5970
  function computeTradingFee(notional, tradingFeeBps) {
4987
5971
  return notional * tradingFeeBps / 10000n;
@@ -5001,20 +5985,9 @@ function computeFeeSplit(totalFee, config) {
5001
5985
  if (config.lpBps === 0n && config.protocolBps === 0n && config.creatorBps === 0n) {
5002
5986
  return [totalFee, 0n, 0n];
5003
5987
  }
5004
- const totalBps = config.lpBps + config.protocolBps + config.creatorBps;
5005
- if (totalBps !== 10000n) {
5006
- throw new Error(
5007
- `Fee split must equal exactly 10000 bps (100%): lpBps=${config.lpBps} + protocolBps=${config.protocolBps} + creatorBps=${config.creatorBps} = ${totalBps}`
5008
- );
5009
- }
5010
5988
  const lp = totalFee * config.lpBps / 10000n;
5011
5989
  const protocol = totalFee * config.protocolBps / 10000n;
5012
5990
  const creator = totalFee - lp - protocol;
5013
- if (creator < 0n) {
5014
- throw new Error(
5015
- `Internal error: creator fee is negative (${creator}). This should not happen if lpBps + protocolBps + creatorBps <= 10000.`
5016
- );
5017
- }
5018
5991
  return [lp, protocol, creator];
5019
5992
  }
5020
5993
  function computePnlPercent(pnlTokens, capital) {
@@ -5029,17 +6002,10 @@ function computePnlPercent(pnlTokens, capital) {
5029
6002
  }
5030
6003
  function computeEstimatedEntryPrice(oracleE6, tradingFeeBps, direction) {
5031
6004
  if (oracleE6 === 0n) return 0n;
5032
- if (tradingFeeBps < 0n) {
5033
- throw new Error(`computeEstimatedEntryPrice: tradingFeeBps must be non-negative, got ${tradingFeeBps}`);
5034
- }
5035
6005
  const feeImpact = oracleE6 * tradingFeeBps / 10000n;
5036
- const result = direction === "long" ? oracleE6 + feeImpact : oracleE6 - feeImpact;
5037
- if (result <= 0n) {
5038
- throw new Error(
5039
- `computeEstimatedEntryPrice: result ${result} is non-positive (tradingFeeBps=${tradingFeeBps} too high for oracle=${oracleE6})`
5040
- );
5041
- }
5042
- return result;
6006
+ if (direction === "long") return oracleE6 + feeImpact;
6007
+ const shortEntry = oracleE6 - feeImpact;
6008
+ return shortEntry > 0n ? shortEntry : 1n;
5043
6009
  }
5044
6010
  var MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
5045
6011
  var MIN_SAFE_BIGINT = BigInt(-Number.MAX_SAFE_INTEGER);
@@ -5060,12 +6026,7 @@ function computeMaxLeverage(initialMarginBps) {
5060
6026
  if (initialMarginBps <= 0n) {
5061
6027
  throw new Error("computeMaxLeverage: initialMarginBps must be positive");
5062
6028
  }
5063
- const scaledResult = 10000n * 1000000n / initialMarginBps;
5064
- return Number(scaledResult) / 1e6;
5065
- }
5066
- function computeMaxWithdrawable(capital, pnl, reservedPnl) {
5067
- const maturedPnl = pnl - reservedPnl;
5068
- return capital + (maturedPnl > 0n ? maturedPnl : 0n);
6029
+ return Number(10000n / initialMarginBps);
5069
6030
  }
5070
6031
 
5071
6032
  // src/math/warmup.ts
@@ -5077,9 +6038,6 @@ function computeWarmupUnlockedCapital(totalCapital, currentSlot, warmupStartSlot
5077
6038
  return totalCapital * elapsed / warmupPeriodSlots;
5078
6039
  }
5079
6040
  function computeWarmupLeverageCap(initialMarginBps, totalCapital, currentSlot, warmupStartSlot, warmupPeriodSlots) {
5080
- if (initialMarginBps <= 0n) {
5081
- throw new Error("computeWarmupLeverageCap: initialMarginBps must be positive");
5082
- }
5083
6041
  const maxLev = computeMaxLeverage(initialMarginBps);
5084
6042
  if (warmupPeriodSlots === 0n || warmupStartSlot === 0n) return maxLev;
5085
6043
  if (totalCapital <= 0n) return 1;
@@ -5090,14 +6048,7 @@ function computeWarmupLeverageCap(initialMarginBps, totalCapital, currentSlot, w
5090
6048
  warmupPeriodSlots
5091
6049
  );
5092
6050
  if (unlocked <= 0n) return 1;
5093
- const scaledResult = BigInt(maxLev) * unlocked / totalCapital;
5094
- if (scaledResult > BigInt(Number.MAX_SAFE_INTEGER)) {
5095
- console.warn(
5096
- `[computeWarmupLeverageCap] Warning: effective leverage ${scaledResult} exceeds MAX_SAFE_INTEGER, returning MAX_SAFE_INTEGER as a safety bound`
5097
- );
5098
- return Number.MAX_SAFE_INTEGER;
5099
- }
5100
- const effectiveLev = Number(scaledResult);
6051
+ const effectiveLev = Number(BigInt(maxLev) * unlocked / totalCapital);
5101
6052
  return Math.max(1, effectiveLev);
5102
6053
  }
5103
6054
  function computeWarmupMaxPositionSize(initialMarginBps, totalCapital, currentSlot, warmupStartSlot, warmupPeriodSlots) {
@@ -5110,41 +6061,10 @@ function computeWarmupMaxPositionSize(initialMarginBps, totalCapital, currentSlo
5110
6061
  );
5111
6062
  return unlocked * BigInt(maxLev);
5112
6063
  }
5113
- function computeWarmupProgress(currentSlot, warmupStartedAtSlot, warmupPeriodSlots, pnl, reservedPnl) {
5114
- if (warmupPeriodSlots === 0n || warmupStartedAtSlot === 0n) {
5115
- return {
5116
- maturedPnl: pnl > 0n ? pnl : 0n,
5117
- reservedPnl: 0n,
5118
- progressBps: 10000n,
5119
- // 100%
5120
- slotsRemaining: 0n
5121
- };
5122
- }
5123
- const elapsed = currentSlot >= warmupStartedAtSlot ? currentSlot - warmupStartedAtSlot : 0n;
5124
- if (elapsed >= warmupPeriodSlots) {
5125
- return {
5126
- maturedPnl: pnl > 0n ? pnl : 0n,
5127
- reservedPnl: 0n,
5128
- progressBps: 10000n,
5129
- // 100%
5130
- slotsRemaining: 0n
5131
- };
5132
- }
5133
- const progressBps = elapsed * 10000n / warmupPeriodSlots;
5134
- const slotsRemaining = warmupPeriodSlots - elapsed;
5135
- const maturedPnl = pnl > 0n ? pnl * progressBps / 10000n : 0n;
5136
- const locked = reservedPnl > 0n ? reservedPnl : 0n;
5137
- return {
5138
- maturedPnl,
5139
- reservedPnl: locked,
5140
- progressBps,
5141
- slotsRemaining
5142
- };
5143
- }
5144
6064
 
5145
6065
  // src/validation.ts
5146
- import { PublicKey as PublicKey14 } from "@solana/web3.js";
5147
- var U16_MAX = 65535;
6066
+ import { PublicKey as PublicKey15 } from "@solana/web3.js";
6067
+ var U16_MAX2 = 65535;
5148
6068
  var U64_MAX = BigInt("18446744073709551615");
5149
6069
  var I64_MIN = BigInt("-9223372036854775808");
5150
6070
  var I64_MAX = BigInt("9223372036854775807");
@@ -5173,7 +6093,7 @@ var ValidationError = class extends Error {
5173
6093
  };
5174
6094
  function validatePublicKey(value, field) {
5175
6095
  try {
5176
- return new PublicKey14(value);
6096
+ return new PublicKey15(value);
5177
6097
  } catch {
5178
6098
  throw new ValidationError(
5179
6099
  field,
@@ -5184,26 +6104,24 @@ function validatePublicKey(value, field) {
5184
6104
  function validateIndex(value, field) {
5185
6105
  const t = requireDecimalUIntString(value, field);
5186
6106
  const bi = BigInt(t);
5187
- if (bi > BigInt(U16_MAX)) {
6107
+ if (bi > BigInt(U16_MAX2)) {
5188
6108
  throw new ValidationError(
5189
6109
  field,
5190
- `must be <= ${U16_MAX} (u16 max), got ${t}`
6110
+ `must be <= ${U16_MAX2} (u16 max), got ${t}`
5191
6111
  );
5192
6112
  }
5193
- if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5194
- throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);
5195
- }
5196
6113
  return Number(bi);
5197
6114
  }
5198
6115
  function validateAmount(value, field) {
5199
- const t = value.trim();
5200
- if (!/^(0|[1-9]\d*)$/.test(t)) {
6116
+ let num;
6117
+ try {
6118
+ num = BigInt(value);
6119
+ } catch {
5201
6120
  throw new ValidationError(
5202
6121
  field,
5203
- `"${value}" is not a valid non-negative integer. Use decimal digits only.`
6122
+ `"${value}" is not a valid number. Use decimal digits only.`
5204
6123
  );
5205
6124
  }
5206
- const num = BigInt(t);
5207
6125
  if (num < 0n) {
5208
6126
  throw new ValidationError(field, `must be non-negative, got ${num}`);
5209
6127
  }
@@ -5216,14 +6134,15 @@ function validateAmount(value, field) {
5216
6134
  return num;
5217
6135
  }
5218
6136
  function validateU128(value, field) {
5219
- const t = value.trim();
5220
- if (!/^(0|[1-9]\d*)$/.test(t)) {
6137
+ let num;
6138
+ try {
6139
+ num = BigInt(value);
6140
+ } catch {
5221
6141
  throw new ValidationError(
5222
6142
  field,
5223
- `"${value}" is not a valid non-negative integer. Use decimal digits only.`
6143
+ `"${value}" is not a valid number. Use decimal digits only.`
5224
6144
  );
5225
6145
  }
5226
- const num = BigInt(t);
5227
6146
  if (num < 0n) {
5228
6147
  throw new ValidationError(field, `must be non-negative, got ${num}`);
5229
6148
  }
@@ -5236,14 +6155,15 @@ function validateU128(value, field) {
5236
6155
  return num;
5237
6156
  }
5238
6157
  function validateI64(value, field) {
5239
- const t = value.trim();
5240
- if (!/^-?(0|[1-9]\d*)$/.test(t)) {
6158
+ let num;
6159
+ try {
6160
+ num = BigInt(value);
6161
+ } catch {
5241
6162
  throw new ValidationError(
5242
6163
  field,
5243
- `"${value}" is not a valid integer. Use decimal digits only, with optional leading minus.`
6164
+ `"${value}" is not a valid number. Use decimal digits only, with optional leading minus.`
5244
6165
  );
5245
6166
  }
5246
- const num = BigInt(t);
5247
6167
  if (num < I64_MIN) {
5248
6168
  throw new ValidationError(
5249
6169
  field,
@@ -5259,14 +6179,15 @@ function validateI64(value, field) {
5259
6179
  return num;
5260
6180
  }
5261
6181
  function validateI128(value, field) {
5262
- const t = value.trim();
5263
- if (!/^-?(0|[1-9]\d*)$/.test(t)) {
6182
+ let num;
6183
+ try {
6184
+ num = BigInt(value);
6185
+ } catch {
5264
6186
  throw new ValidationError(
5265
6187
  field,
5266
- `"${value}" is not a valid integer. Use decimal digits only, with optional leading minus.`
6188
+ `"${value}" is not a valid number. Use decimal digits only, with optional leading minus.`
5267
6189
  );
5268
6190
  }
5269
- const num = BigInt(t);
5270
6191
  if (num < I128_MIN) {
5271
6192
  throw new ValidationError(
5272
6193
  field,
@@ -5290,9 +6211,6 @@ function validateBps(value, field) {
5290
6211
  `must be <= 10000 (100%), got ${t}`
5291
6212
  );
5292
6213
  }
5293
- if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5294
- throw new ValidationError(field, `internal error: bps value exceeds MAX_SAFE_INTEGER`);
5295
- }
5296
6214
  return Number(bi);
5297
6215
  }
5298
6216
  function validateU64(value, field) {
@@ -5301,15 +6219,12 @@ function validateU64(value, field) {
5301
6219
  function validateU16(value, field) {
5302
6220
  const t = requireDecimalUIntString(value, field);
5303
6221
  const bi = BigInt(t);
5304
- if (bi > BigInt(U16_MAX)) {
6222
+ if (bi > BigInt(U16_MAX2)) {
5305
6223
  throw new ValidationError(
5306
6224
  field,
5307
- `must be <= ${U16_MAX} (u16 max), got ${t}`
6225
+ `must be <= ${U16_MAX2} (u16 max), got ${t}`
5308
6226
  );
5309
6227
  }
5310
- if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5311
- throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);
5312
- }
5313
6228
  return Number(bi);
5314
6229
  }
5315
6230
 
@@ -5360,9 +6275,7 @@ function parseDexScreenerPairs(json) {
5360
6275
  else if (liquidity > 1e4) confidence = 60;
5361
6276
  else if (liquidity > 1e3) confidence = 45;
5362
6277
  const priceUsd = pair.priceUsd;
5363
- const rawPrice = typeof priceUsd === "string" || typeof priceUsd === "number" ? parseFloat(String(priceUsd)) : NaN;
5364
- if (!Number.isFinite(rawPrice) || rawPrice <= 0) continue;
5365
- const price = rawPrice;
6278
+ const price = typeof priceUsd === "string" || typeof priceUsd === "number" ? parseFloat(String(priceUsd)) || 0 : 0;
5366
6279
  let baseSym = "?";
5367
6280
  let quoteSym = "?";
5368
6281
  if (isRecord(pair.baseToken) && typeof pair.baseToken.symbol === "string") {
@@ -5393,8 +6306,8 @@ function parseJupiterMintEntry(json, mint) {
5393
6306
  if (!isRecord(row)) return null;
5394
6307
  const rawPrice = row.price;
5395
6308
  if (rawPrice === void 0 || rawPrice === null) return null;
5396
- const price = parseFloat(String(rawPrice));
5397
- if (!Number.isFinite(price) || price <= 0) return null;
6309
+ const price = parseFloat(String(rawPrice)) || 0;
6310
+ if (price <= 0) return null;
5398
6311
  let mintSymbol = "?";
5399
6312
  if (typeof row.mintSymbol === "string") mintSymbol = row.mintSymbol;
5400
6313
  return { price, mintSymbol };
@@ -5460,17 +6373,10 @@ async function fetchDexSources(mint, signal) {
5460
6373
  headers: { "User-Agent": "percolator/1.0" }
5461
6374
  }
5462
6375
  );
5463
- if (!resp.ok) {
5464
- console.debug(`[fetchDexSources] HTTP ${resp.status} for mint ${mint}`);
5465
- return [];
5466
- }
6376
+ if (!resp.ok) return [];
5467
6377
  const json = await resp.json();
5468
6378
  return parseDexScreenerPairs(json);
5469
- } catch (err) {
5470
- console.warn(
5471
- `[fetchDexSources] Error fetching DexScreener data for mint ${mint}:`,
5472
- err instanceof Error ? err.message : String(err)
5473
- );
6379
+ } catch {
5474
6380
  return [];
5475
6381
  }
5476
6382
  }
@@ -5481,7 +6387,7 @@ function lookupPythSource(mint) {
5481
6387
  type: "pyth",
5482
6388
  address: entry.feedId,
5483
6389
  pairLabel: `${entry.symbol} / USD (Pyth)`,
5484
- liquidity: Number.MAX_SAFE_INTEGER,
6390
+ liquidity: Infinity,
5485
6391
  // Pyth is considered deep liquidity
5486
6392
  price: 0,
5487
6393
  // We don't fetch live price here; caller can enrich
@@ -5498,16 +6404,10 @@ async function fetchJupiterSource(mint, signal) {
5498
6404
  headers: { "User-Agent": "percolator/1.0" }
5499
6405
  }
5500
6406
  );
5501
- if (!resp.ok) {
5502
- console.debug(`[fetchJupiterSource] HTTP ${resp.status} for mint ${mint}`);
5503
- return null;
5504
- }
6407
+ if (!resp.ok) return null;
5505
6408
  const json = await resp.json();
5506
6409
  const row = parseJupiterMintEntry(json, mint);
5507
- if (!row) {
5508
- console.debug(`[fetchJupiterSource] No price data from Jupiter for mint ${mint}`);
5509
- return null;
5510
- }
6410
+ if (!row) return null;
5511
6411
  return {
5512
6412
  type: "jupiter",
5513
6413
  address: mint,
@@ -5518,39 +6418,23 @@ async function fetchJupiterSource(mint, signal) {
5518
6418
  confidence: 40
5519
6419
  // Fallback — lower confidence
5520
6420
  };
5521
- } catch (err) {
5522
- console.warn(
5523
- `[fetchJupiterSource] Error fetching Jupiter data for mint ${mint}:`,
5524
- err instanceof Error ? err.message : String(err)
5525
- );
6421
+ } catch {
5526
6422
  return null;
5527
6423
  }
5528
6424
  }
5529
6425
  async function resolvePrice(mint, signal, options) {
5530
6426
  const timeoutMs = options?.timeoutMs ?? DEFAULT_RESOLVE_TIMEOUT_MS;
5531
6427
  const timeoutSignal = AbortSignal.timeout(timeoutMs);
5532
- const effectiveSignal2 = signal ? combineAbortSignals([signal, timeoutSignal]) : timeoutSignal;
6428
+ const combinedSignal = signal ? combineAbortSignals([signal, timeoutSignal]) : timeoutSignal;
5533
6429
  const [dexSources, jupiterSource] = await Promise.all([
5534
- fetchDexSources(mint, effectiveSignal2),
5535
- fetchJupiterSource(mint, effectiveSignal2)
6430
+ fetchDexSources(mint, combinedSignal),
6431
+ fetchJupiterSource(mint, combinedSignal)
5536
6432
  ]);
5537
6433
  const pythSource = lookupPythSource(mint);
5538
6434
  const allSources = [];
5539
6435
  if (pythSource) {
5540
- const dexPrice = dexSources[0]?.price ?? 0;
5541
- const jupPrice = jupiterSource?.price ?? 0;
5542
- if (dexPrice > 0 && jupPrice > 0) {
5543
- const mid = (dexPrice + jupPrice) / 2;
5544
- const deviation = Math.abs(dexPrice - jupPrice) / mid;
5545
- if (deviation > 0.5) {
5546
- pythSource.price = 0;
5547
- pythSource.confidence = 20;
5548
- } else {
5549
- pythSource.price = mid;
5550
- }
5551
- } else {
5552
- pythSource.price = dexPrice || jupPrice || 0;
5553
- }
6436
+ const refPrice = dexSources[0]?.price || jupiterSource?.price || 0;
6437
+ pythSource.price = refPrice;
5554
6438
  allSources.push(pythSource);
5555
6439
  }
5556
6440
  allSources.push(...dexSources);
@@ -5566,6 +6450,7 @@ async function resolvePrice(mint, signal, options) {
5566
6450
  };
5567
6451
  }
5568
6452
  export {
6453
+ ACCOUNTS_ACCEPT_ADMIN,
5569
6454
  ACCOUNTS_ADVANCE_ORACLE_PHASE,
5570
6455
  ACCOUNTS_AUDIT_CRANK,
5571
6456
  ACCOUNTS_BURN_POSITION_NFT,
@@ -5575,7 +6460,9 @@ export {
5575
6460
  ACCOUNTS_CLOSE_ACCOUNT,
5576
6461
  ACCOUNTS_CLOSE_SLAB,
5577
6462
  ACCOUNTS_CLOSE_STALE_SLABS,
6463
+ ACCOUNTS_CREATE_INSURANCE_MINT,
5578
6464
  ACCOUNTS_DEPOSIT_COLLATERAL,
6465
+ ACCOUNTS_DEPOSIT_INSURANCE_LP,
5579
6466
  ACCOUNTS_EXECUTE_ADL,
5580
6467
  ACCOUNTS_FUND_MARKET_INSURANCE,
5581
6468
  ACCOUNTS_INIT_LP,
@@ -5586,21 +6473,22 @@ export {
5586
6473
  ACCOUNTS_LIQUIDATE_AT_ORACLE,
5587
6474
  ACCOUNTS_LP_VAULT_WITHDRAW,
5588
6475
  ACCOUNTS_MINT_POSITION_NFT,
6476
+ ACCOUNTS_NFT_BURN,
6477
+ ACCOUNTS_NFT_EMERGENCY_BURN,
6478
+ ACCOUNTS_NFT_MINT,
5589
6479
  ACCOUNTS_PAUSE_MARKET,
5590
- ACCOUNTS_PUSH_ORACLE_PRICE,
5591
6480
  ACCOUNTS_QUEUE_WITHDRAWAL,
5592
6481
  ACCOUNTS_RECLAIM_SLAB_RENT,
5593
6482
  ACCOUNTS_RESOLVE_MARKET,
6483
+ ACCOUNTS_SET_DEX_POOL,
5594
6484
  ACCOUNTS_SET_INSURANCE_ISOLATION,
5595
6485
  ACCOUNTS_SET_MAINTENANCE_FEE,
5596
6486
  ACCOUNTS_SET_OI_IMBALANCE_HARD_BLOCK,
5597
- ACCOUNTS_SET_ORACLE_AUTHORITY,
5598
6487
  ACCOUNTS_SET_ORACLE_PRICE_CAP,
5599
6488
  ACCOUNTS_SET_PENDING_SETTLEMENT,
5600
6489
  ACCOUNTS_SET_RISK_THRESHOLD,
5601
6490
  ACCOUNTS_SET_WALLET_CAP,
5602
6491
  ACCOUNTS_TOPUP_INSURANCE,
5603
- ACCOUNTS_TOPUP_KEEPER_FUND,
5604
6492
  ACCOUNTS_TRADE_CPI,
5605
6493
  ACCOUNTS_TRADE_NOCPI,
5606
6494
  ACCOUNTS_TRANSFER_POSITION_OWNERSHIP,
@@ -5609,11 +6497,13 @@ export {
5609
6497
  ACCOUNTS_UPDATE_CONFIG,
5610
6498
  ACCOUNTS_WITHDRAW_COLLATERAL,
5611
6499
  ACCOUNTS_WITHDRAW_INSURANCE,
6500
+ ACCOUNTS_WITHDRAW_INSURANCE_LIMITED_LIVE,
6501
+ ACCOUNTS_WITHDRAW_INSURANCE_LIMITED_RESOLVED,
6502
+ ACCOUNTS_WITHDRAW_INSURANCE_LP,
5612
6503
  AccountKind,
5613
6504
  CHAINLINK_ANSWER_OFFSET,
5614
6505
  CHAINLINK_DECIMALS_OFFSET,
5615
6506
  CHAINLINK_MIN_SIZE,
5616
- CHAINLINK_TIMESTAMP_OFFSET,
5617
6507
  CREATOR_LOCK_SEED,
5618
6508
  CTX_VAMM_OFFSET,
5619
6509
  DEFAULT_OI_RAMP_SLOTS,
@@ -5623,13 +6513,15 @@ export {
5623
6513
  LIGHTHOUSE_CONSTRAINT_ADDRESS,
5624
6514
  LIGHTHOUSE_ERROR_CODES,
5625
6515
  LIGHTHOUSE_PROGRAM_ID,
5626
- LIGHTHOUSE_PROGRAM_ID_STR2 as LIGHTHOUSE_PROGRAM_ID_STR,
6516
+ LIGHTHOUSE_PROGRAM_ID_STR,
5627
6517
  LIGHTHOUSE_USER_MESSAGE,
6518
+ LiquidationPolicyTag,
5628
6519
  MARK_PRICE_EMA_ALPHA_E6,
5629
6520
  MARK_PRICE_EMA_WINDOW_SLOTS,
5630
6521
  MAX_DECIMALS,
5631
- MAX_ORACLE_PRICE,
5632
6522
  METEORA_DLMM_PROGRAM_ID,
6523
+ NFT_IX_TAG,
6524
+ NFT_PROGRAM_ID,
5633
6525
  ORACLE_PHASE_GROWING,
5634
6526
  ORACLE_PHASE_MATURE,
5635
6527
  ORACLE_PHASE_NASCENT,
@@ -5638,6 +6530,7 @@ export {
5638
6530
  PHASE1_VOLUME_MIN_SLOTS,
5639
6531
  PHASE2_MATURITY_SLOTS,
5640
6532
  PHASE2_VOLUME_THRESHOLD,
6533
+ POSITION_NFT_STATE_LEN,
5641
6534
  PROGRAM_IDS,
5642
6535
  PUMPSWAP_PROGRAM_ID,
5643
6536
  PYTH_PUSH_ORACLE_PROGRAM_ID,
@@ -5647,10 +6540,13 @@ export {
5647
6540
  RAYDIUM_CLMM_PROGRAM_ID,
5648
6541
  RENOUNCE_ADMIN_CONFIRMATION,
5649
6542
  RpcPool,
6543
+ SLAB_MAGIC,
5650
6544
  SLAB_TIERS,
5651
6545
  SLAB_TIERS_V0,
5652
6546
  SLAB_TIERS_V1,
5653
6547
  SLAB_TIERS_V12_1,
6548
+ SLAB_TIERS_V12_15,
6549
+ SLAB_TIERS_V12_17,
5654
6550
  SLAB_TIERS_V1D,
5655
6551
  SLAB_TIERS_V1D_LEGACY,
5656
6552
  SLAB_TIERS_V1M,
@@ -5659,6 +6555,7 @@ export {
5659
6555
  SLAB_TIERS_V_ADL,
5660
6556
  SLAB_TIERS_V_ADL_DISCOVERY,
5661
6557
  SLAB_TIERS_V_SETDEXPOOL,
6558
+ STAKE_DEPOSIT_SIZE,
5662
6559
  STAKE_IX,
5663
6560
  STAKE_POOL_SIZE,
5664
6561
  STAKE_PROGRAM_ID,
@@ -5688,7 +6585,6 @@ export {
5688
6585
  computeLiqPrice,
5689
6586
  computeMarkPnl,
5690
6587
  computeMaxLeverage,
5691
- computeMaxWithdrawable,
5692
6588
  computePnlPercent,
5693
6589
  computePreTradeLiqPrice,
5694
6590
  computeRequiredMargin,
@@ -5696,17 +6592,20 @@ export {
5696
6592
  computeVammQuote,
5697
6593
  computeWarmupLeverageCap,
5698
6594
  computeWarmupMaxPositionSize,
5699
- computeWarmupProgress,
5700
6595
  computeWarmupUnlockedCapital,
5701
6596
  concatBytes,
5702
6597
  countLighthouseInstructions,
6598
+ decodeDepositPda,
5703
6599
  decodeError,
5704
6600
  decodeStakePool,
5705
6601
  depositAccounts,
5706
6602
  deriveCreatorLockPda,
5707
6603
  deriveDepositPda,
5708
- deriveKeeperFund,
6604
+ deriveInsuranceLpMint,
5709
6605
  deriveLpPda,
6606
+ deriveMintAuthority,
6607
+ deriveNftMint,
6608
+ deriveNftPda,
5710
6609
  derivePythPriceUpdateAccount,
5711
6610
  derivePythPushOraclePDA,
5712
6611
  deriveStakePool,
@@ -5728,21 +6627,30 @@ export {
5728
6627
  encU32,
5729
6628
  encU64,
5730
6629
  encU8,
6630
+ encodeAcceptAdmin,
5731
6631
  encodeAdminForceClose,
5732
6632
  encodeAdvanceEpoch,
5733
6633
  encodeAdvanceOraclePhase,
5734
6634
  encodeAllocateMarket,
6635
+ encodeAttestCrossMargin,
5735
6636
  encodeAuditCrank,
5736
6637
  encodeBurnPositionNft,
5737
6638
  encodeCancelQueuedWithdrawal,
6639
+ encodeChallengeSettlement,
5738
6640
  encodeClaimEpochWithdrawal,
5739
6641
  encodeClaimQueuedWithdrawal,
5740
6642
  encodeClearPendingSettlement,
5741
6643
  encodeCloseAccount,
6644
+ encodeCloseOrphanSlab,
5742
6645
  encodeCloseSlab,
5743
6646
  encodeCloseStaleSlabs,
6647
+ encodeCreateInsuranceMint,
6648
+ encodeCreateLpVault,
5744
6649
  encodeDepositCollateral,
6650
+ encodeDepositInsuranceLP,
6651
+ encodeDepositLpCollateral,
5745
6652
  encodeExecuteAdl,
6653
+ encodeForceCloseResolved,
5746
6654
  encodeFundMarketInsurance,
5747
6655
  encodeInitLP,
5748
6656
  encodeInitMarket,
@@ -5751,19 +6659,33 @@ export {
5751
6659
  encodeInitUser,
5752
6660
  encodeKeeperCrank,
5753
6661
  encodeLiquidateAtOracle,
6662
+ encodeLpVaultCrankFees,
6663
+ encodeLpVaultDeposit,
5754
6664
  encodeLpVaultWithdraw,
5755
6665
  encodeMintPositionNft,
6666
+ encodeNftBurn,
6667
+ encodeNftEmergencyBurn,
6668
+ encodeNftMint,
6669
+ encodeNftSettleFunding,
5756
6670
  encodePauseMarket,
5757
- encodePushOraclePrice,
5758
6671
  encodeQueueWithdrawal,
5759
6672
  encodeQueueWithdrawalSV,
5760
6673
  encodeReclaimSlabRent,
5761
6674
  encodeRenounceAdmin,
6675
+ encodeRescueOrphanVault,
6676
+ encodeResolveDispute,
5762
6677
  encodeResolveMarket,
6678
+ encodeResolvePermissionless,
6679
+ encodeSetDexPool,
6680
+ encodeSetDisputeParams,
5763
6681
  encodeSetInsuranceIsolation,
6682
+ encodeSetInsuranceWithdrawPolicy,
6683
+ encodeSetLpCollateralParams,
5764
6684
  encodeSetMaintenanceFee,
6685
+ encodeSetMaxPnlCap,
6686
+ encodeSetOffsetPair,
6687
+ encodeSetOiCapMultiplier,
5765
6688
  encodeSetOiImbalanceHardBlock,
5766
- encodeSetOracleAuthority,
5767
6689
  encodeSetOraclePriceCap,
5768
6690
  encodeSetPendingSettlement,
5769
6691
  encodeSetPythOracle,
@@ -5788,13 +6710,13 @@ export {
5788
6710
  encodeStakeUpdateConfig,
5789
6711
  encodeStakeWithdraw,
5790
6712
  encodeTopUpInsurance,
5791
- encodeTopUpKeeperFund,
5792
6713
  encodeTradeCpi,
5793
6714
  encodeTradeCpiV2,
5794
6715
  encodeTradeNoCpi,
5795
6716
  encodeTransferOwnershipCpi,
5796
6717
  encodeTransferPositionOwnership,
5797
6718
  encodeUnpauseMarket,
6719
+ encodeUnresolveMarket,
5798
6720
  encodeUpdateAdmin,
5799
6721
  encodeUpdateConfig,
5800
6722
  encodeUpdateHyperpMark,
@@ -5802,6 +6724,9 @@ export {
5802
6724
  encodeUpdateRiskParams,
5803
6725
  encodeWithdrawCollateral,
5804
6726
  encodeWithdrawInsurance,
6727
+ encodeWithdrawInsuranceLP,
6728
+ encodeWithdrawInsuranceLimited,
6729
+ encodeWithdrawLpCollateral,
5805
6730
  fetchAdlRankedPositions,
5806
6731
  fetchAdlRankings,
5807
6732
  fetchSlab,
@@ -5815,13 +6740,13 @@ export {
5815
6740
  getErrorName,
5816
6741
  getMarketsByAddress,
5817
6742
  getMatcherProgramId,
6743
+ getNftProgramId,
5818
6744
  getProgramId,
5819
6745
  getStakeProgramId,
5820
6746
  getStaticMarkets,
5821
6747
  initPoolAccounts,
5822
6748
  isAccountUsed,
5823
6749
  isAdlTriggered,
5824
- isAnchorErrorCode,
5825
6750
  isLighthouseError,
5826
6751
  isLighthouseFailureInLogs,
5827
6752
  isLighthouseInstruction,
@@ -5829,6 +6754,7 @@ export {
5829
6754
  isToken2022,
5830
6755
  isValidChainlinkOracle,
5831
6756
  maxAccountIndex,
6757
+ packOiCap,
5832
6758
  parseAccount,
5833
6759
  parseAdlEvent,
5834
6760
  parseAllAccounts,
@@ -5839,6 +6765,7 @@ export {
5839
6765
  parseErrorFromLogs,
5840
6766
  parseHeader,
5841
6767
  parseParams,
6768
+ parsePositionNftAccount,
5842
6769
  parseUsedIndices,
5843
6770
  rankAdlPositions,
5844
6771
  readLastThrUpdateSlot,