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

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,8 +258,10 @@ function encodeFeedId(feedId) {
230
258
  }
231
259
  return bytes;
232
260
  }
233
- var INIT_MARKET_DATA_LEN = 264;
261
+ var INIT_MARKET_DATA_LEN = 344;
234
262
  function encodeInitMarket(args) {
263
+ const hMin = args.hMin ?? args.warmupPeriodSlots ?? 0n;
264
+ const hMax = args.hMax ?? args.warmupPeriodSlots ?? 0n;
235
265
  const data = concatBytes(
236
266
  encU8(IX_TAG.InitMarket),
237
267
  encPubkey(args.admin),
@@ -242,19 +272,33 @@ function encodeInitMarket(args) {
242
272
  encU8(args.invert),
243
273
  encU32(args.unitScale),
244
274
  encU64(args.initialMarkPriceE6),
245
- encU64(args.warmupPeriodSlots),
275
+ // 3 fields between header and RiskParams (immutable after init)
276
+ encU128(args.maxMaintenanceFeePerSlot ?? 0n),
277
+ encU128(args.maxInsuranceFloor ?? 0n),
278
+ encU64(args.minOraclePriceCap ?? 0n),
279
+ // RiskParams wire format — must match read_risk_params() in percolator.rs
280
+ // In v12.15: warmup_period_slots replaced by hMin/hMax. hMin is written first (same slot),
281
+ // hMax appended at end. liquidationBufferBps is read but discarded (kept for wire compat).
282
+ encU64(hMin),
246
283
  encU64(args.maintenanceMarginBps),
247
284
  encU64(args.initialMarginBps),
248
285
  encU64(args.tradingFeeBps),
249
286
  encU64(args.maxAccounts),
250
287
  encU128(args.newAccountFee),
251
- encU128(args.riskReductionThreshold),
252
- encU128(args.maintenanceFeePerSlot),
288
+ encU128(args.insuranceFloor ?? 0n),
289
+ // wire slot: old riskReductionThreshold → now insurance_floor
290
+ encU64(hMax),
291
+ // h_max (u64)
253
292
  encU64(args.maxCrankStalenessSlots),
293
+ // v12.17: no padding between hMax and maxCrankStalenessSlots
254
294
  encU64(args.liquidationFeeBps),
255
295
  encU128(args.liquidationFeeCap),
256
- encU64(args.liquidationBufferBps),
257
- encU128(args.minLiquidationAbs)
296
+ encU64(args.liquidationBufferBps ?? 0n),
297
+ // v12.17: read as resolve_price_deviation_bps by program
298
+ encU128(args.minLiquidationAbs),
299
+ encU128(args.minInitialDeposit),
300
+ encU128(args.minNonzeroMmReq),
301
+ encU128(args.minNonzeroImReq)
258
302
  );
259
303
  if (data.length !== INIT_MARKET_DATA_LEN) {
260
304
  throw new Error(
@@ -288,12 +332,28 @@ function encodeWithdrawCollateral(args) {
288
332
  encU64(args.amount)
289
333
  );
290
334
  }
335
+ var LiquidationPolicyTag = {
336
+ FullClose: 0,
337
+ ExactPartial: 1,
338
+ TouchOnly: 255
339
+ };
291
340
  function encodeKeeperCrank(args) {
292
- return concatBytes(
341
+ const parts = [
293
342
  encU8(IX_TAG.KeeperCrank),
294
343
  encU16(args.callerIdx),
295
- encU8(args.allowPanic ? 1 : 0)
296
- );
344
+ encU8(1)
345
+ // format_version = 1 (REQUIRED by v12.17)
346
+ ];
347
+ if (args.candidates) {
348
+ for (const c of args.candidates) {
349
+ parts.push(encU16(c.idx));
350
+ parts.push(encU8(c.policy));
351
+ if (c.policy === LiquidationPolicyTag.ExactPartial) {
352
+ parts.push(encU128(c.quantity));
353
+ }
354
+ }
355
+ }
356
+ return concatBytes(...parts);
297
357
  }
298
358
  function encodeTradeNoCpi(args) {
299
359
  return concatBytes(
@@ -320,7 +380,8 @@ function encodeTradeCpi(args) {
320
380
  encU8(IX_TAG.TradeCpi),
321
381
  encU16(args.lpIdx),
322
382
  encU16(args.userIdx),
323
- encI128(args.size)
383
+ encI128(args.size),
384
+ encU64(args.limitPriceE6)
324
385
  );
325
386
  }
326
387
  function encodeTradeCpiV2(args) {
@@ -332,6 +393,9 @@ function encodeTradeCpiV2(args) {
332
393
  encU8(args.bump)
333
394
  );
334
395
  }
396
+ function encodeUnresolveMarket(args) {
397
+ return concatBytes(encU8(IX_TAG.UnresolveMarket), encU64(args.confirmation));
398
+ }
335
399
  function encodeSetRiskThreshold(args) {
336
400
  return concatBytes(
337
401
  encU8(IX_TAG.SetRiskThreshold),
@@ -349,19 +413,10 @@ function encodeUpdateConfig(args) {
349
413
  encU8(IX_TAG.UpdateConfig),
350
414
  encU64(args.fundingHorizonSlots),
351
415
  encU64(args.fundingKBps),
352
- encU128(args.fundingInvScaleNotionalE6),
353
416
  encI64(args.fundingMaxPremiumBps),
354
417
  // Rust: i64 (can be negative)
355
- encI64(args.fundingMaxBpsPerSlot),
418
+ encI64(args.fundingMaxBpsPerSlot)
356
419
  // 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
420
  );
366
421
  }
367
422
  function encodeSetMaintenanceFee(args) {
@@ -370,26 +425,6 @@ function encodeSetMaintenanceFee(args) {
370
425
  encU128(args.newFee)
371
426
  );
372
427
  }
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
428
  function encodeSetOraclePriceCap(args) {
394
429
  return concatBytes(
395
430
  encU8(IX_TAG.SetOraclePriceCap),
@@ -443,23 +478,18 @@ function encodeSetPythOracle(args) {
443
478
  const dv3 = new DataView(buf.buffer);
444
479
  buf[0] = 32;
445
480
  buf.set(args.feedId, 1);
446
- dv3.setBigUint64(
447
- 33,
448
- args.maxStalenessSecs,
449
- /* little-endian */
450
- true
451
- );
481
+ dv3.setBigUint64(33, args.maxStalenessSecs, true);
452
482
  dv3.setUint16(41, args.confFilterBps, true);
453
483
  return buf;
454
484
  }
455
485
  var PYTH_RECEIVER_PROGRAM_ID = "rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ";
456
486
  async function derivePythPriceUpdateAccount(feedId, shardId = 0) {
457
- const { PublicKey: PublicKey15 } = await import("@solana/web3.js");
487
+ const { PublicKey: PublicKey16 } = await import("@solana/web3.js");
458
488
  const shardBuf = new Uint8Array(2);
459
489
  new DataView(shardBuf.buffer).setUint16(0, shardId, true);
460
- const [pda] = PublicKey15.findProgramAddressSync(
490
+ const [pda] = PublicKey16.findProgramAddressSync(
461
491
  [shardBuf, feedId],
462
- new PublicKey15(PYTH_RECEIVER_PROGRAM_ID)
492
+ new PublicKey16(PYTH_RECEIVER_PROGRAM_ID)
463
493
  );
464
494
  return pda.toBase58();
465
495
  }
@@ -570,9 +600,6 @@ function checkPhaseTransition(currentSlot, marketCreatedSlot, oraclePhase, cumul
570
600
  return [ORACLE_PHASE_MATURE, false];
571
601
  }
572
602
  }
573
- function encodeTopUpKeeperFund(args) {
574
- return concatBytes(encU8(IX_TAG.TopUpKeeperFund), encU64(args.amount));
575
- }
576
603
  function encodeSlashCreationDeposit() {
577
604
  return encU8(IX_TAG.SlashCreationDeposit);
578
605
  }
@@ -642,6 +669,105 @@ function encodeInitMatcherCtx(args) {
642
669
  encU16(args.skewSpreadMultBps)
643
670
  );
644
671
  }
672
+ function encodeSetInsuranceWithdrawPolicy(args) {
673
+ return concatBytes(encU8(IX_TAG.SetInsuranceWithdrawPolicy), encPubkey(args.authority), encU64(args.minWithdrawBase), encU16(args.maxWithdrawBps), encU64(args.cooldownSlots));
674
+ }
675
+ function encodeWithdrawInsuranceLimited(args) {
676
+ return concatBytes(encU8(IX_TAG.WithdrawInsuranceLimited), encU64(args.amount));
677
+ }
678
+ function encodeResolvePermissionless() {
679
+ return concatBytes(encU8(IX_TAG.ResolvePermissionless));
680
+ }
681
+ function encodeForceCloseResolved(args) {
682
+ return concatBytes(encU8(IX_TAG.ForceCloseResolved), encU16(args.userIdx));
683
+ }
684
+ function encodeCreateLpVault(args) {
685
+ const parts = [encU8(IX_TAG.CreateLpVault), encU64(args.feeShareBps)];
686
+ if (args.utilCurveEnabled !== void 0) {
687
+ parts.push(encU8(args.utilCurveEnabled ? 1 : 0));
688
+ }
689
+ return concatBytes(...parts);
690
+ }
691
+ function encodeLpVaultDeposit(args) {
692
+ return concatBytes(encU8(IX_TAG.LpVaultDeposit), encU64(args.amount));
693
+ }
694
+ function encodeLpVaultCrankFees() {
695
+ return concatBytes(encU8(IX_TAG.LpVaultCrankFees));
696
+ }
697
+ function encodeChallengeSettlement(args) {
698
+ return concatBytes(encU8(IX_TAG.ChallengeSettlement), encU64(args.proposedPriceE6));
699
+ }
700
+ function encodeResolveDispute(args) {
701
+ return concatBytes(encU8(IX_TAG.ResolveDispute), encU8(args.accept));
702
+ }
703
+ function encodeDepositLpCollateral(args) {
704
+ return concatBytes(encU8(IX_TAG.DepositLpCollateral), encU16(args.userIdx), encU64(args.lpAmount));
705
+ }
706
+ function encodeWithdrawLpCollateral(args) {
707
+ return concatBytes(encU8(IX_TAG.WithdrawLpCollateral), encU16(args.userIdx), encU64(args.lpAmount));
708
+ }
709
+ function encodeSetOffsetPair(args) {
710
+ return concatBytes(encU8(IX_TAG.SetOffsetPair), encU16(args.offsetBps));
711
+ }
712
+ function encodeAttestCrossMargin(args) {
713
+ return concatBytes(encU8(IX_TAG.AttestCrossMargin), encU16(args.userIdxA), encU16(args.userIdxB));
714
+ }
715
+ function encodeRescueOrphanVault() {
716
+ return concatBytes(encU8(IX_TAG.RescueOrphanVault));
717
+ }
718
+ function encodeCloseOrphanSlab() {
719
+ return concatBytes(encU8(IX_TAG.CloseOrphanSlab));
720
+ }
721
+ function encodeSetDexPool(args) {
722
+ return concatBytes(encU8(IX_TAG.SetDexPool), encPubkey(args.pool));
723
+ }
724
+ function encodeCreateInsuranceMint() {
725
+ return encodeCreateLpVault({ feeShareBps: 0n });
726
+ }
727
+ function encodeDepositInsuranceLP(args) {
728
+ return encodeLpVaultDeposit({ amount: args.amount });
729
+ }
730
+ function encodeWithdrawInsuranceLP(args) {
731
+ return encodeLpVaultWithdraw({ lpAmount: args.lpAmount });
732
+ }
733
+ function encodeSetMaxPnlCap(args) {
734
+ return concatBytes(encU8(IX_TAG.SetMaxPnlCap), encU64(args.cap));
735
+ }
736
+ function encodeSetOiCapMultiplier(args) {
737
+ return concatBytes(encU8(IX_TAG.SetOiCapMultiplier), encU64(args.packed));
738
+ }
739
+ function packOiCap(multiplierBps, softCapBps) {
740
+ if (multiplierBps < 0 || multiplierBps > 4294967295) {
741
+ throw new Error(`packOiCap: multiplier_bps out of u32 range: ${multiplierBps}`);
742
+ }
743
+ if (softCapBps < 0 || softCapBps > 4294967295) {
744
+ throw new Error(`packOiCap: soft_cap_bps out of u32 range: ${softCapBps}`);
745
+ }
746
+ return BigInt(multiplierBps) | BigInt(softCapBps) << 32n;
747
+ }
748
+ function encodeSetDisputeParams(args) {
749
+ return concatBytes(
750
+ encU8(IX_TAG.SetDisputeParams),
751
+ encU64(args.windowSlots),
752
+ encU64(args.bondAmount)
753
+ );
754
+ }
755
+ function encodeSetLpCollateralParams(args) {
756
+ if (args.enabled !== 0 && args.enabled !== 1) {
757
+ throw new Error(`encodeSetLpCollateralParams: enabled must be 0 or 1, got ${args.enabled}`);
758
+ }
759
+ if (args.ltvBps < 0 || args.ltvBps > 1e4) {
760
+ throw new Error(`encodeSetLpCollateralParams: ltvBps ${args.ltvBps} out of range [0, 10000]`);
761
+ }
762
+ return concatBytes(
763
+ encU8(IX_TAG.SetLpCollateralParams),
764
+ encU8(args.enabled),
765
+ encU16(args.ltvBps)
766
+ );
767
+ }
768
+ function encodeAcceptAdmin() {
769
+ return encU8(IX_TAG.AcceptAdmin);
770
+ }
645
771
 
646
772
  // src/abi/accounts.ts
647
773
  import {
@@ -666,7 +792,8 @@ var ACCOUNTS_INIT_USER = [
666
792
  { name: "slab", signer: false, writable: true },
667
793
  { name: "userAta", signer: false, writable: true },
668
794
  { name: "vault", signer: false, writable: true },
669
- { name: "tokenProgram", signer: false, writable: false }
795
+ { name: "tokenProgram", signer: false, writable: false },
796
+ { name: "clock", signer: false, writable: false }
670
797
  ];
671
798
  var ACCOUNTS_INIT_LP = [
672
799
  { name: "user", signer: true, writable: true },
@@ -733,6 +860,7 @@ var ACCOUNTS_TRADE_CPI = [
733
860
  { name: "lpOwner", signer: false, writable: false },
734
861
  // LP delegated to matcher - no signature needed
735
862
  { name: "slab", signer: false, writable: true },
863
+ { name: "clock", signer: false, writable: false },
736
864
  { name: "oracle", signer: false, writable: false },
737
865
  { name: "matcherProg", signer: false, writable: false },
738
866
  { name: "matcherCtx", signer: false, writable: true },
@@ -758,18 +886,10 @@ var ACCOUNTS_SET_MAINTENANCE_FEE = [
758
886
  { name: "admin", signer: true, writable: true },
759
887
  { name: "slab", signer: false, writable: true }
760
888
  ];
761
- var ACCOUNTS_SET_ORACLE_AUTHORITY = [
762
- { name: "admin", signer: true, writable: true },
763
- { name: "slab", signer: false, writable: true }
764
- ];
765
889
  var ACCOUNTS_SET_ORACLE_PRICE_CAP = [
766
890
  { name: "admin", signer: true, writable: true },
767
891
  { name: "slab", signer: false, writable: true }
768
892
  ];
769
- var ACCOUNTS_PUSH_ORACLE_PRICE = [
770
- { name: "authority", signer: true, writable: true },
771
- { name: "slab", signer: false, writable: true }
772
- ];
773
893
  var ACCOUNTS_RESOLVE_MARKET = [
774
894
  { name: "admin", signer: true, writable: true },
775
895
  { name: "slab", signer: false, writable: true }
@@ -782,6 +902,19 @@ var ACCOUNTS_WITHDRAW_INSURANCE = [
782
902
  { name: "tokenProgram", signer: false, writable: false },
783
903
  { name: "vaultPda", signer: false, writable: false }
784
904
  ];
905
+ var ACCOUNTS_WITHDRAW_INSURANCE_LIMITED_RESOLVED = [
906
+ { name: "authority", signer: true, writable: true },
907
+ { name: "slab", signer: false, writable: true },
908
+ { name: "authorityAta", signer: false, writable: true },
909
+ { name: "vault", signer: false, writable: true },
910
+ { name: "tokenProgram", signer: false, writable: false },
911
+ { name: "vaultPda", signer: false, writable: false },
912
+ { name: "clock", signer: false, writable: false }
913
+ ];
914
+ var ACCOUNTS_WITHDRAW_INSURANCE_LIMITED_LIVE = [
915
+ ...ACCOUNTS_WITHDRAW_INSURANCE_LIMITED_RESOLVED,
916
+ { name: "oracle", signer: false, writable: false }
917
+ ];
785
918
  var ACCOUNTS_PAUSE_MARKET = [
786
919
  { name: "admin", signer: true, writable: true },
787
920
  { name: "slab", signer: false, writable: true }
@@ -816,6 +949,37 @@ function buildAccountMetas(spec, keys) {
816
949
  isWritable: s.writable
817
950
  }));
818
951
  }
952
+ var ACCOUNTS_CREATE_INSURANCE_MINT = [
953
+ { name: "admin", signer: true, writable: false },
954
+ { name: "slab", signer: false, writable: false },
955
+ { name: "insLpMint", signer: false, writable: true },
956
+ { name: "vaultAuthority", signer: false, writable: false },
957
+ { name: "collateralMint", signer: false, writable: false },
958
+ { name: "systemProgram", signer: false, writable: false },
959
+ { name: "tokenProgram", signer: false, writable: false },
960
+ { name: "rent", signer: false, writable: false },
961
+ { name: "payer", signer: true, writable: true }
962
+ ];
963
+ var ACCOUNTS_DEPOSIT_INSURANCE_LP = [
964
+ { name: "depositor", signer: true, writable: false },
965
+ { name: "slab", signer: false, writable: true },
966
+ { name: "depositorAta", signer: false, writable: true },
967
+ { name: "vault", signer: false, writable: true },
968
+ { name: "tokenProgram", signer: false, writable: false },
969
+ { name: "insLpMint", signer: false, writable: true },
970
+ { name: "depositorLpAta", signer: false, writable: true },
971
+ { name: "vaultAuthority", signer: false, writable: false }
972
+ ];
973
+ var ACCOUNTS_WITHDRAW_INSURANCE_LP = [
974
+ { name: "withdrawer", signer: true, writable: false },
975
+ { name: "slab", signer: false, writable: true },
976
+ { name: "withdrawerAta", signer: false, writable: true },
977
+ { name: "vault", signer: false, writable: true },
978
+ { name: "tokenProgram", signer: false, writable: false },
979
+ { name: "insLpMint", signer: false, writable: true },
980
+ { name: "withdrawerLpAta", signer: false, writable: true },
981
+ { name: "vaultAuthority", signer: false, writable: false }
982
+ ];
819
983
  var ACCOUNTS_LP_VAULT_WITHDRAW = [
820
984
  { name: "withdrawer", signer: true, writable: false },
821
985
  { name: "slab", signer: false, writable: true },
@@ -883,11 +1047,6 @@ var ACCOUNTS_AUDIT_CRANK = [
883
1047
  var ACCOUNTS_ADVANCE_ORACLE_PHASE = [
884
1048
  { name: "slab", signer: false, writable: true }
885
1049
  ];
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
1050
  var ACCOUNTS_SET_OI_IMBALANCE_HARD_BLOCK = [
892
1051
  { name: "admin", signer: true, writable: false },
893
1052
  { name: "slab", signer: false, writable: true }
@@ -937,6 +1096,11 @@ var ACCOUNTS_SET_WALLET_CAP = [
937
1096
  { name: "admin", signer: true, writable: false },
938
1097
  { name: "slab", signer: false, writable: true }
939
1098
  ];
1099
+ var ACCOUNTS_SET_DEX_POOL = [
1100
+ { name: "admin", signer: true, writable: false },
1101
+ { name: "slab", signer: false, writable: true },
1102
+ { name: "poolAccount", signer: false, writable: false }
1103
+ ];
940
1104
  var ACCOUNTS_INIT_MATCHER_CTX = [
941
1105
  { name: "admin", signer: true, writable: false },
942
1106
  { name: "slab", signer: false, writable: false },
@@ -1228,24 +1392,11 @@ function getErrorName(code) {
1228
1392
  function getErrorHint(code) {
1229
1393
  return PERCOLATOR_ERRORS[code]?.hint;
1230
1394
  }
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
1395
  var CUSTOM_ERROR_HEX_MAX_LEN = 8;
1244
1396
  function parseErrorFromLogs(logs) {
1245
1397
  if (!Array.isArray(logs)) {
1246
1398
  return null;
1247
1399
  }
1248
- let insideLighthouse = false;
1249
1400
  const re = new RegExp(
1250
1401
  `custom program error: 0x([0-9a-fA-F]{1,${CUSTOM_ERROR_HEX_MAX_LEN}})(?![0-9a-fA-F])`,
1251
1402
  "i"
@@ -1254,44 +1405,201 @@ function parseErrorFromLogs(logs) {
1254
1405
  if (typeof log !== "string") {
1255
1406
  continue;
1256
1407
  }
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
1408
  const match = log.match(re);
1263
1409
  if (match) {
1264
1410
  const code = parseInt(match[1], 16);
1265
1411
  if (!Number.isFinite(code) || code < 0 || code > 4294967295) {
1266
1412
  continue;
1267
1413
  }
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
1414
  const info = decodeError(code);
1278
1415
  return {
1279
1416
  code,
1280
1417
  name: info?.name ?? `Unknown(${code})`,
1281
- hint: info?.hint,
1282
- source: info ? "percolator" : "unknown"
1418
+ hint: info?.hint
1283
1419
  };
1284
1420
  }
1285
1421
  }
1286
1422
  return null;
1287
1423
  }
1288
1424
 
1289
- // src/solana/slab.ts
1425
+ // src/abi/nft.ts
1426
+ import { PublicKey as PublicKey4 } from "@solana/web3.js";
1427
+
1428
+ // src/config/program-ids.ts
1290
1429
  import { PublicKey as PublicKey3 } from "@solana/web3.js";
1430
+ function safeEnv(key) {
1431
+ try {
1432
+ return typeof process !== "undefined" && process?.env ? process.env[key] : void 0;
1433
+ } catch {
1434
+ return void 0;
1435
+ }
1436
+ }
1437
+ var PROGRAM_IDS = {
1438
+ devnet: {
1439
+ percolator: "FxfD37s1AZTeWfFQps9Zpebi2dNQ9QSSDtfMKdbsfKrD",
1440
+ matcher: "GTRgyTDfrMvBubALAqtHuQwT8tbGyXid7svXZKtWfC9k"
1441
+ },
1442
+ mainnet: {
1443
+ percolator: "ESa89R5Es3rJ5mnwGybVRG1GrNt9etP11Z5V2QWD4edv",
1444
+ matcher: "GDK8wx38kpiSVSfGTVNiSdptX3Z5R4kQyqh6Q3QX6wmi"
1445
+ }
1446
+ };
1447
+ function getProgramId(network) {
1448
+ const override = safeEnv("PROGRAM_ID");
1449
+ if (override) {
1450
+ console.warn(
1451
+ `[percolator-sdk] PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
1452
+ );
1453
+ return new PublicKey3(override);
1454
+ }
1455
+ const detectedNetwork = getCurrentNetwork();
1456
+ const targetNetwork = network ?? detectedNetwork;
1457
+ const programId = PROGRAM_IDS[targetNetwork].percolator;
1458
+ return new PublicKey3(programId);
1459
+ }
1460
+ function getMatcherProgramId(network) {
1461
+ const override = safeEnv("MATCHER_PROGRAM_ID");
1462
+ if (override) {
1463
+ console.warn(
1464
+ `[percolator-sdk] MATCHER_PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
1465
+ );
1466
+ return new PublicKey3(override);
1467
+ }
1468
+ const detectedNetwork = getCurrentNetwork();
1469
+ const targetNetwork = network ?? detectedNetwork;
1470
+ const programId = PROGRAM_IDS[targetNetwork].matcher;
1471
+ if (!programId) {
1472
+ throw new Error(`Matcher program not deployed on ${targetNetwork}`);
1473
+ }
1474
+ return new PublicKey3(programId);
1475
+ }
1476
+ function getCurrentNetwork() {
1477
+ const network = safeEnv("NETWORK")?.toLowerCase();
1478
+ if (network === "mainnet" || network === "mainnet-beta") {
1479
+ return "mainnet";
1480
+ }
1481
+ return "devnet";
1482
+ }
1483
+
1484
+ // src/abi/nft.ts
1485
+ var NFT_PROGRAM_OVERRIDE = safeEnv("NFT_PROGRAM_ID");
1486
+ var NFT_PROGRAM_ID = new PublicKey4(
1487
+ NFT_PROGRAM_OVERRIDE ?? "FqhKJT9gtScjrmfUuRMjeg7cXNpif1fqsy5Jh65tJmTS"
1488
+ );
1489
+ function getNftProgramId() {
1490
+ return NFT_PROGRAM_ID;
1491
+ }
1492
+ var NFT_IX_TAG = {
1493
+ MintPositionNft: 0,
1494
+ BurnPositionNft: 1,
1495
+ SettleFunding: 2,
1496
+ GetPositionValue: 3,
1497
+ ExecuteTransferHook: 4,
1498
+ EmergencyBurn: 5
1499
+ };
1500
+ function encodeNftMint(userIdx) {
1501
+ const buf = new Uint8Array(3);
1502
+ buf[0] = NFT_IX_TAG.MintPositionNft;
1503
+ buf[1] = userIdx & 255;
1504
+ buf[2] = userIdx >> 8 & 255;
1505
+ return buf;
1506
+ }
1507
+ function encodeNftBurn() {
1508
+ return new Uint8Array([NFT_IX_TAG.BurnPositionNft]);
1509
+ }
1510
+ function encodeNftSettleFunding() {
1511
+ return new Uint8Array([NFT_IX_TAG.SettleFunding]);
1512
+ }
1513
+ function encodeNftEmergencyBurn() {
1514
+ return new Uint8Array([NFT_IX_TAG.EmergencyBurn]);
1515
+ }
1516
+ var ACCOUNTS_NFT_MINT = [
1517
+ "sw",
1518
+ "w",
1519
+ "sw",
1520
+ "w",
1521
+ "r",
1522
+ "r",
1523
+ "r",
1524
+ "r",
1525
+ "r",
1526
+ "w"
1527
+ ];
1528
+ var ACCOUNTS_NFT_BURN = [
1529
+ "s",
1530
+ "w",
1531
+ "w",
1532
+ "w",
1533
+ "r",
1534
+ "r",
1535
+ "r"
1536
+ ];
1537
+ var ACCOUNTS_NFT_EMERGENCY_BURN = [
1538
+ "s",
1539
+ "w",
1540
+ "w",
1541
+ "w",
1542
+ "r",
1543
+ "r",
1544
+ "r"
1545
+ ];
1546
+ var TEXT = new TextEncoder();
1547
+ function idxBuf(userIdx) {
1548
+ const buf = new Uint8Array(2);
1549
+ new DataView(buf.buffer).setUint16(0, userIdx, true);
1550
+ return buf;
1551
+ }
1552
+ function deriveNftPda(slab, userIdx, programId = NFT_PROGRAM_ID) {
1553
+ return PublicKey4.findProgramAddressSync(
1554
+ [TEXT.encode("position_nft"), slab.toBytes(), idxBuf(userIdx)],
1555
+ programId
1556
+ );
1557
+ }
1558
+ function deriveNftMint(slab, userIdx, programId = NFT_PROGRAM_ID) {
1559
+ return PublicKey4.findProgramAddressSync(
1560
+ [TEXT.encode("position_nft_mint"), slab.toBytes(), idxBuf(userIdx)],
1561
+ programId
1562
+ );
1563
+ }
1564
+ function deriveMintAuthority(programId = NFT_PROGRAM_ID) {
1565
+ return PublicKey4.findProgramAddressSync(
1566
+ [TEXT.encode("mint_authority")],
1567
+ programId
1568
+ );
1569
+ }
1570
+ var POSITION_NFT_STATE_LEN = 208;
1571
+ function parsePositionNftAccount(data) {
1572
+ if (data.length < POSITION_NFT_STATE_LEN) {
1573
+ throw new Error(
1574
+ `PositionNft account too small: ${data.length} < ${POSITION_NFT_STATE_LEN}`
1575
+ );
1576
+ }
1577
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
1578
+ return {
1579
+ version: data[8],
1580
+ bump: data[9],
1581
+ slab: new PublicKey4(data.subarray(16, 48)),
1582
+ userIdx: view.getUint16(48, true),
1583
+ nftMint: new PublicKey4(data.subarray(56, 88)),
1584
+ entryPriceE6: view.getBigUint64(88, true),
1585
+ positionSize: view.getBigUint64(96, true),
1586
+ isLong: data[104] === 1,
1587
+ positionBasisQ: view.getBigInt64(112, true) | view.getBigInt64(120, true) << 64n,
1588
+ lastFundingIndexE18: view.getBigInt64(128, true) | view.getBigInt64(136, true) << 64n,
1589
+ mintedAt: view.getBigInt64(144, true),
1590
+ accountId: view.getBigUint64(152, true)
1591
+ };
1592
+ }
1593
+
1594
+ // src/solana/slab.ts
1595
+ import { PublicKey as PublicKey5 } from "@solana/web3.js";
1291
1596
  function dv(data) {
1292
1597
  return new DataView(data.buffer, data.byteOffset, data.byteLength);
1293
1598
  }
1294
1599
  function readU8(data, off) {
1600
+ if (off >= data.length) {
1601
+ throw new RangeError(`readU8: offset ${off} out of bounds (length ${data.length})`);
1602
+ }
1295
1603
  return data[off];
1296
1604
  }
1297
1605
  function readU16LE(data, off) {
@@ -1322,6 +1630,7 @@ function readU128LE(buf, offset) {
1322
1630
  return hi << 64n | lo;
1323
1631
  }
1324
1632
  var MAGIC = 0x504552434f4c4154n;
1633
+ var SLAB_MAGIC = MAGIC;
1325
1634
  var FLAG_RESOLVED = 1 << 0;
1326
1635
  var V0_HEADER_LEN = 72;
1327
1636
  var V0_CONFIG_LEN = 408;
@@ -1491,9 +1800,29 @@ var V_ADL_ACCT_FEE_CREDITS_OFF = 224;
1491
1800
  var V_ADL_ACCT_LAST_FEE_SLOT_OFF = 240;
1492
1801
  var V12_1_ENGINE_OFF = 648;
1493
1802
  var V12_1_ACCOUNT_SIZE = 320;
1803
+ var V12_1_ACCOUNT_SIZE_SBF = 280;
1494
1804
  var V12_1_ENGINE_BITMAP_OFF = 1016;
1495
- var V12_1_ENGINE_PARAMS_OFF = 96;
1805
+ var V12_1_ENGINE_PARAMS_OFF_SBF = 32;
1806
+ var V12_1_ENGINE_PARAMS_OFF_HOST = 96;
1807
+ var V12_1_PARAMS_SIZE_SBF = 184;
1496
1808
  var V12_1_PARAMS_SIZE = 352;
1809
+ var V12_1_SBF_OFF_CURRENT_SLOT = 216;
1810
+ var V12_1_SBF_OFF_FUNDING_RATE = 224;
1811
+ var V12_1_SBF_OFF_LAST_CRANK_SLOT = 232;
1812
+ var V12_1_SBF_OFF_MAX_CRANK_STALENESS = 240;
1813
+ var V12_1_SBF_OFF_C_TOT = 248;
1814
+ var V12_1_SBF_OFF_PNL_POS_TOT = 264;
1815
+ var V12_1_SBF_OFF_LIQ_CURSOR = 296;
1816
+ var V12_1_SBF_OFF_GC_CURSOR = 298;
1817
+ var V12_1_SBF_OFF_LAST_SWEEP_START = 304;
1818
+ var V12_1_SBF_OFF_LAST_SWEEP_COMPLETE = 312;
1819
+ var V12_1_SBF_OFF_CRANK_CURSOR = 320;
1820
+ var V12_1_SBF_OFF_SWEEP_START_IDX = 322;
1821
+ var V12_1_SBF_OFF_LIFETIME_LIQUIDATIONS = 328;
1822
+ var V12_1_SBF_OFF_TOTAL_OI = 448;
1823
+ var V12_1_SBF_OFF_LONG_OI = 464;
1824
+ var V12_1_SBF_OFF_SHORT_OI = 480;
1825
+ var V12_1_SBF_OFF_MARK_PRICE_E6 = 560;
1497
1826
  var V12_1_ENGINE_CURRENT_SLOT_OFF = 448;
1498
1827
  var V12_1_ENGINE_FUNDING_RATE_BPS_OFF = 456;
1499
1828
  var V12_1_ENGINE_LAST_CRANK_SLOT_OFF = 464;
@@ -1526,9 +1855,105 @@ var V12_1_ACCT_MATCHER_CONTEXT_OFF = 176;
1526
1855
  var V12_1_ACCT_OWNER_OFF = 208;
1527
1856
  var V12_1_ACCT_FEE_CREDITS_OFF = 240;
1528
1857
  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;
1858
+ var V12_1_ACCT_POSITION_SIZE_OFF = 88;
1859
+ var V12_1_ACCT_ENTRY_PRICE_OFF = -1;
1860
+ var V12_1_EP_SBF_ACCOUNT_SIZE = 288;
1861
+ var V12_1_EP_ACCT_ENTRY_PRICE_OFF = 144;
1862
+ var V12_1_EP_ACCT_MATCHER_PROGRAM_OFF = 152;
1863
+ var V12_1_EP_ACCT_MATCHER_CONTEXT_OFF = 184;
1864
+ var V12_1_EP_ACCT_OWNER_OFF = 216;
1865
+ var V12_1_EP_ACCT_FEE_CREDITS_OFF = 248;
1866
+ var V12_1_EP_ACCT_LAST_FEE_SLOT_OFF = 264;
1867
+ var V12_15_ENGINE_OFF = 624;
1868
+ var V12_15_ENGINE_OFF_SBF = 616;
1869
+ var V12_15_ACCOUNT_SIZE = 4400;
1870
+ var V12_15_ACCOUNT_SIZE_SMALL = 920;
1871
+ var V12_15_ACCT_ACCOUNT_ID_OFF = 0;
1872
+ var V12_15_ACCT_CAPITAL_OFF = 8;
1873
+ var V12_15_ACCT_KIND_OFF = 24;
1874
+ var V12_15_ACCT_PNL_OFF = 32;
1875
+ var V12_15_ACCT_RESERVED_PNL_OFF = 48;
1876
+ var V12_15_ACCT_POSITION_BASIS_Q_OFF = 64;
1877
+ var V12_15_ACCT_ENTRY_PRICE_OFF = 120;
1878
+ var V12_15_ACCT_MATCHER_PROGRAM_OFF = 128;
1879
+ var V12_15_ACCT_MATCHER_CONTEXT_OFF = 160;
1880
+ var V12_15_ACCT_OWNER_OFF = 192;
1881
+ var V12_15_ACCT_FEE_CREDITS_OFF = 224;
1882
+ var V12_15_ACCT_FEES_EARNED_TOTAL_OFF = 240;
1883
+ var V12_15_ACCT_EXACT_RESERVE_COHORTS_OFF = 256;
1884
+ var V12_15_ACCT_EXACT_COHORT_COUNT_OFF = 4224;
1885
+ var V12_15_ACCT_OVERFLOW_OLDER_OFF = 4240;
1886
+ var V12_15_ACCT_OVERFLOW_OLDER_PRESENT_OFF = 4304;
1887
+ var V12_15_ACCT_OVERFLOW_NEWEST_OFF = 4320;
1888
+ var V12_15_ACCT_OVERFLOW_NEWEST_PRESENT_OFF = 4384;
1889
+ var V12_15_PARAMS_SIZE = 192;
1890
+ var V12_15_PARAMS_MAX_ACCOUNTS_OFF = 24;
1891
+ var V12_15_PARAMS_INSURANCE_FLOOR_OFF = 144;
1892
+ var V12_15_PARAMS_H_MIN_OFF = 160;
1893
+ var V12_15_PARAMS_H_MAX_OFF = 168;
1894
+ var V12_15_ENGINE_PARAMS_OFF = 32;
1895
+ var V12_15_ENGINE_CURRENT_SLOT_OFF = 224;
1896
+ var V12_15_ENGINE_FUNDING_RATE_E9_OFF = 240;
1897
+ var V12_15_ENGINE_C_TOT_OFF = 344;
1898
+ var V12_15_ENGINE_PNL_POS_TOT_OFF = 368;
1899
+ var V12_15_ENGINE_PNL_MATURED_POS_TOT_OFF = 384;
1900
+ var V12_15_ENGINE_BITMAP_OFF = 862;
1901
+ var V12_15_SIZES = /* @__PURE__ */ new Map();
1902
+ var V12_17_ENGINE_OFF = 512;
1903
+ var V12_17_ACCOUNT_SIZE = 368;
1904
+ var V12_17_ENGINE_BITMAP_OFF = 752;
1905
+ var V12_17_RISK_BUF_LEN = 160;
1906
+ var V12_17_ENGINE_OFF_SBF = 504;
1907
+ var V12_17_ACCOUNT_SIZE_SBF = 352;
1908
+ var V12_17_ENGINE_BITMAP_OFF_SBF = 712;
1909
+ var V12_17_ACCT_CAPITAL_OFF = 0;
1910
+ var V12_17_ACCT_KIND_OFF = 16;
1911
+ var V12_17_ACCT_PNL_OFF = 32;
1912
+ var V12_17_ACCT_RESERVED_PNL_OFF = 48;
1913
+ var V12_17_ACCT_POSITION_BASIS_Q_OFF = 64;
1914
+ var V12_17_ACCT_ADL_A_BASIS_OFF = 80;
1915
+ var V12_17_ACCT_ADL_K_SNAP_OFF = 96;
1916
+ var V12_17_ACCT_F_SNAP_OFF = 112;
1917
+ var V12_17_ACCT_ADL_EPOCH_SNAP_OFF = 128;
1918
+ var V12_17_ACCT_MATCHER_PROGRAM_OFF = 136;
1919
+ var V12_17_ACCT_MATCHER_CONTEXT_OFF = 168;
1920
+ var V12_17_ACCT_OWNER_OFF = 200;
1921
+ var V12_17_ACCT_FEE_CREDITS_OFF = 232;
1922
+ var V12_17_ACCT_SCHED_PRESENT_OFF = 248;
1923
+ var V12_17_ACCT_SCHED_REMAINING_Q_OFF = 256;
1924
+ var V12_17_ACCT_SCHED_ANCHOR_Q_OFF = 272;
1925
+ var V12_17_ACCT_SCHED_START_SLOT_OFF = 288;
1926
+ var V12_17_ACCT_SCHED_HORIZON_OFF = 296;
1927
+ var V12_17_ACCT_SCHED_RELEASE_Q_OFF = 304;
1928
+ var V12_17_ACCT_PENDING_PRESENT_OFF = 320;
1929
+ var V12_17_ACCT_PENDING_REMAINING_Q_OFF = 336;
1930
+ var V12_17_ACCT_PENDING_HORIZON_OFF = 352;
1931
+ var V12_17_ACCT_PENDING_CREATED_SLOT_OFF = 360;
1932
+ var V12_17_ENGINE_PARAMS_OFF = 32;
1933
+ var V12_17_ENGINE_CURRENT_SLOT_OFF = 224;
1934
+ var V12_17_ENGINE_MARKET_MODE_OFF = 232;
1935
+ var V12_17_ENGINE_RESOLVED_K_LONG_OFF = 304;
1936
+ var V12_17_ENGINE_RESOLVED_K_SHORT_OFF = 320;
1937
+ var V12_17_ENGINE_RESOLVED_LIVE_PRICE_OFF = 336;
1938
+ var V12_17_ENGINE_C_TOT_OFF = 352;
1939
+ var V12_17_ENGINE_PNL_POS_TOT_OFF = 368;
1940
+ var V12_17_ENGINE_PNL_MATURED_POS_TOT_OFF = 384;
1941
+ var V12_17_ENGINE_NEG_PNL_COUNT_OFF = 648;
1942
+ var V12_17_ENGINE_LAST_ORACLE_PRICE_OFF = 656;
1943
+ var V12_17_ENGINE_FUND_PX_LAST_OFF = 664;
1944
+ var V12_17_ENGINE_F_LONG_NUM_OFF = 688;
1945
+ var V12_17_ENGINE_F_SHORT_NUM_OFF = 704;
1946
+ var V12_17_SBF_ENGINE_CURRENT_SLOT_OFF = 216;
1947
+ var V12_17_SBF_ENGINE_MARKET_MODE_OFF = 224;
1948
+ var V12_17_SBF_ENGINE_C_TOT_OFF = 336;
1949
+ var V12_17_SBF_ENGINE_PNL_POS_TOT_OFF = 352;
1950
+ var V12_17_SBF_ENGINE_PNL_MATURED_POS_TOT_OFF = 368;
1951
+ var V12_17_SBF_ENGINE_NEG_PNL_COUNT_OFF = 616;
1952
+ var V12_17_SBF_ENGINE_LAST_ORACLE_PRICE_OFF = 624;
1953
+ var V12_17_SBF_ENGINE_FUND_PX_LAST_OFF = 632;
1954
+ var V12_17_SBF_ENGINE_F_LONG_NUM_OFF = 648;
1955
+ var V12_17_SBF_ENGINE_F_SHORT_NUM_OFF = 664;
1956
+ var V12_17_SIZES = /* @__PURE__ */ new Map();
1532
1957
  var V1M_ENGINE_OFF = 640;
1533
1958
  var V1M_CONFIG_LEN = 536;
1534
1959
  var V1M_ACCOUNT_SIZE = 248;
@@ -1601,6 +2026,42 @@ for (const n of TIERS) {
1601
2026
  V1M2_SIZES.set(computeSlabSize(V1M2_ENGINE_OFF, V1M2_ENGINE_BITMAP_OFF, V1M2_ACCOUNT_SIZE, n, 18), n);
1602
2027
  V_SETDEXPOOL_SIZES.set(computeSlabSize(V_SETDEXPOOL_ENGINE_OFF, V_ADL_ENGINE_BITMAP_OFF, V_ADL_ACCOUNT_SIZE, n, 18), n);
1603
2028
  V12_1_SIZES.set(computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, n, 18), n);
2029
+ V12_15_SIZES.set(computeSlabSize(V12_15_ENGINE_OFF, V12_15_ENGINE_BITMAP_OFF, V12_15_ACCOUNT_SIZE, n, 18), n);
2030
+ }
2031
+ V12_15_SIZES.set(computeSlabSize(V12_15_ENGINE_OFF, V12_15_ENGINE_BITMAP_OFF, V12_15_ACCOUNT_SIZE, 2048, 18), 2048);
2032
+ V12_15_SIZES.set(237512, 256);
2033
+ var V12_17_TIERS = [256, 1024, 4096];
2034
+ for (const n of V12_17_TIERS) {
2035
+ const bitmapWords = Math.ceil(n / 64);
2036
+ const bitmapBytes = bitmapWords * 8;
2037
+ const postBitmap = 4;
2038
+ const nextFreeBytes = n * 2;
2039
+ const preAccNative = V12_17_ENGINE_BITMAP_OFF + bitmapBytes + postBitmap + nextFreeBytes;
2040
+ const accountsOffNative = Math.ceil(preAccNative / 16) * 16;
2041
+ const nativeSize = V12_17_ENGINE_OFF + accountsOffNative + n * V12_17_ACCOUNT_SIZE + V12_17_RISK_BUF_LEN;
2042
+ V12_17_SIZES.set(nativeSize, n);
2043
+ const preAccSbf = V12_17_ENGINE_BITMAP_OFF_SBF + bitmapBytes + postBitmap + nextFreeBytes;
2044
+ const accountsOffSbf = Math.ceil(preAccSbf / 8) * 8;
2045
+ const sbfSize = V12_17_ENGINE_OFF_SBF + accountsOffSbf + n * V12_17_ACCOUNT_SIZE_SBF + V12_17_RISK_BUF_LEN;
2046
+ V12_17_SIZES.set(sbfSize, n);
2047
+ }
2048
+ var V12_1_SBF_ACCOUNT_SIZE = 280;
2049
+ var V12_1_SBF_ENGINE_OFF = 616;
2050
+ var V12_1_SBF_BITMAP_OFF = 584;
2051
+ for (const [, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Large", 4096]]) {
2052
+ const bitmapBytes = Math.ceil(n / 64) * 8;
2053
+ const preAccLen = V12_1_SBF_BITMAP_OFF + bitmapBytes + 18 + n * 2;
2054
+ const accountsOff = Math.ceil(preAccLen / 8) * 8;
2055
+ const total = V12_1_SBF_ENGINE_OFF + accountsOff + n * V12_1_SBF_ACCOUNT_SIZE;
2056
+ V12_1_SIZES.set(total, n);
2057
+ }
2058
+ var V12_1_EP_SIZES = /* @__PURE__ */ new Map();
2059
+ for (const [, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Large", 4096]]) {
2060
+ const bitmapBytes = Math.ceil(n / 64) * 8;
2061
+ const preAccLen = V12_1_SBF_BITMAP_OFF + bitmapBytes + 18 + n * 2;
2062
+ const accountsOff = Math.ceil(preAccLen / 8) * 8;
2063
+ const total = V12_1_SBF_ENGINE_OFF + accountsOff + n * V12_1_EP_SBF_ACCOUNT_SIZE;
2064
+ V12_1_EP_SIZES.set(total, n);
1604
2065
  }
1605
2066
  var SLAB_TIERS_V2 = {
1606
2067
  small: { maxAccounts: 256, dataSize: 65088, label: "Small", description: "256 slots (V2 BPF intermediate)" },
@@ -2066,6 +2527,19 @@ for (const [label, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Lar
2066
2527
  const size = computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, n, 18);
2067
2528
  SLAB_TIERS_V12_1[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (v12.1)` };
2068
2529
  }
2530
+ var SLAB_TIERS_V12_15 = {};
2531
+ for (const [label, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Medium2048", 2048], ["Large", 4096]]) {
2532
+ const size = computeSlabSize(V12_15_ENGINE_OFF, V12_15_ENGINE_BITMAP_OFF, V12_15_ACCOUNT_SIZE, n, 18);
2533
+ SLAB_TIERS_V12_15[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (v12.15)` };
2534
+ }
2535
+ var SLAB_TIERS_V12_17 = {};
2536
+ for (const [label, n] of [["Small", 256], ["Medium", 1024], ["Large", 4096]]) {
2537
+ const bitmapBytes = Math.ceil(n / 64) * 8;
2538
+ const preAcc = V12_17_ENGINE_BITMAP_OFF_SBF + bitmapBytes + 4 + n * 2;
2539
+ const accountsOff = Math.ceil(preAcc / 8) * 8;
2540
+ const size = V12_17_ENGINE_OFF_SBF + accountsOff + n * V12_17_ACCOUNT_SIZE_SBF + V12_17_RISK_BUF_LEN;
2541
+ SLAB_TIERS_V12_17[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (v12.17)` };
2542
+ }
2069
2543
  function buildLayoutVSetDexPool(maxAccounts) {
2070
2544
  const engineOff = V_SETDEXPOOL_ENGINE_OFF;
2071
2545
  const bitmapOff = V_ADL_ENGINE_BITMAP_OFF;
@@ -2126,10 +2600,12 @@ function buildLayoutVSetDexPool(maxAccounts) {
2126
2600
  engineInsuranceIsolationBpsOff: 64
2127
2601
  };
2128
2602
  }
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;
2603
+ function buildLayoutV12_1(maxAccounts, dataLen) {
2604
+ const hostSize = computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, maxAccounts, 18);
2605
+ const isSbf = dataLen !== void 0 && dataLen !== hostSize;
2606
+ const engineOff = isSbf ? V12_1_SBF_ENGINE_OFF : V12_1_ENGINE_OFF;
2607
+ const bitmapOff = isSbf ? V12_1_SBF_BITMAP_OFF : V12_1_ENGINE_BITMAP_OFF - V12_1_ENGINE_OFF;
2608
+ const accountSize = isSbf ? V12_1_ACCOUNT_SIZE_SBF : V12_1_ACCOUNT_SIZE;
2133
2609
  const bitmapWords = Math.ceil(maxAccounts / 64);
2134
2610
  const bitmapBytes = bitmapWords * 8;
2135
2611
  const postBitmap = 18;
@@ -2138,10 +2614,11 @@ function buildLayoutV12_1(maxAccounts) {
2138
2614
  const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;
2139
2615
  return {
2140
2616
  version: 1,
2141
- headerLen: V1_HEADER_LEN,
2142
- configOffset: V1_HEADER_LEN,
2143
- configLen: V_SETDEXPOOL_CONFIG_LEN,
2144
- // 544 (same as V_SETDEXPOOL)
2617
+ headerLen: V0_HEADER_LEN,
2618
+ // 72
2619
+ configOffset: V0_HEADER_LEN,
2620
+ // 72
2621
+ configLen: isSbf ? 544 : 576,
2145
2622
  reservedOff: V1_RESERVED_OFF,
2146
2623
  engineOff,
2147
2624
  accountSize,
@@ -2149,46 +2626,302 @@ function buildLayoutV12_1(maxAccounts) {
2149
2626
  bitmapWords,
2150
2627
  accountsOff: engineOff + accountsOffRel,
2151
2628
  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,
2629
+ engineParamsOff: isSbf ? V12_1_ENGINE_PARAMS_OFF_SBF : V12_1_ENGINE_PARAMS_OFF_HOST,
2630
+ paramsSize: isSbf ? V12_1_PARAMS_SIZE_SBF : V12_1_PARAMS_SIZE,
2631
+ // SBF engine offsets — all verified by cargo build-sbf offset_of! assertions.
2632
+ // Fields that don't exist in the deployed program are set to -1 on SBF.
2633
+ engineCurrentSlotOff: isSbf ? V12_1_SBF_OFF_CURRENT_SLOT : V12_1_ENGINE_CURRENT_SLOT_OFF,
2634
+ engineFundingIndexOff: isSbf ? -1 : V12_1_ENGINE_FUNDING_INDEX_OFF,
2635
+ // not in deployed struct
2636
+ engineLastFundingSlotOff: isSbf ? -1 : V12_1_ENGINE_LAST_FUNDING_SLOT_OFF,
2637
+ // not in deployed struct
2638
+ engineFundingRateBpsOff: isSbf ? V12_1_SBF_OFF_FUNDING_RATE : V12_1_ENGINE_FUNDING_RATE_BPS_OFF,
2639
+ engineMarkPriceOff: isSbf ? V12_1_SBF_OFF_MARK_PRICE_E6 : V12_1_ENGINE_MARK_PRICE_OFF,
2640
+ engineLastCrankSlotOff: isSbf ? V12_1_SBF_OFF_LAST_CRANK_SLOT : V12_1_ENGINE_LAST_CRANK_SLOT_OFF,
2641
+ engineMaxCrankStalenessOff: isSbf ? V12_1_SBF_OFF_MAX_CRANK_STALENESS : V12_1_ENGINE_MAX_CRANK_STALENESS_OFF,
2642
+ engineTotalOiOff: isSbf ? V12_1_SBF_OFF_TOTAL_OI : V12_1_ENGINE_TOTAL_OI_OFF,
2643
+ engineLongOiOff: isSbf ? V12_1_SBF_OFF_LONG_OI : V12_1_ENGINE_LONG_OI_OFF,
2644
+ engineShortOiOff: isSbf ? V12_1_SBF_OFF_SHORT_OI : V12_1_ENGINE_SHORT_OI_OFF,
2645
+ engineCTotOff: isSbf ? V12_1_SBF_OFF_C_TOT : V12_1_ENGINE_C_TOT_OFF,
2646
+ enginePnlPosTotOff: isSbf ? V12_1_SBF_OFF_PNL_POS_TOT : V12_1_ENGINE_PNL_POS_TOT_OFF,
2647
+ engineLiqCursorOff: isSbf ? V12_1_SBF_OFF_LIQ_CURSOR : V12_1_ENGINE_LIQ_CURSOR_OFF,
2648
+ engineGcCursorOff: isSbf ? V12_1_SBF_OFF_GC_CURSOR : V12_1_ENGINE_GC_CURSOR_OFF,
2649
+ engineLastSweepStartOff: isSbf ? V12_1_SBF_OFF_LAST_SWEEP_START : V12_1_ENGINE_LAST_SWEEP_START_OFF,
2650
+ engineLastSweepCompleteOff: isSbf ? V12_1_SBF_OFF_LAST_SWEEP_COMPLETE : V12_1_ENGINE_LAST_SWEEP_COMPLETE_OFF,
2651
+ engineCrankCursorOff: isSbf ? V12_1_SBF_OFF_CRANK_CURSOR : V12_1_ENGINE_CRANK_CURSOR_OFF,
2652
+ engineSweepStartIdxOff: isSbf ? V12_1_SBF_OFF_SWEEP_START_IDX : V12_1_ENGINE_SWEEP_START_IDX_OFF,
2653
+ engineLifetimeLiquidationsOff: isSbf ? V12_1_SBF_OFF_LIFETIME_LIQUIDATIONS : V12_1_ENGINE_LIFETIME_LIQUIDATIONS_OFF,
2654
+ engineLifetimeForceClosesOff: isSbf ? -1 : V12_1_ENGINE_LIFETIME_FORCE_CLOSES_OFF,
2655
+ // not in deployed struct
2656
+ engineNetLpPosOff: isSbf ? -1 : V12_1_ENGINE_NET_LP_POS_OFF,
2657
+ // not in deployed struct
2658
+ engineLpSumAbsOff: isSbf ? -1 : V12_1_ENGINE_LP_SUM_ABS_OFF,
2659
+ // not in deployed struct
2660
+ engineLpMaxAbsOff: isSbf ? -1 : V12_1_ENGINE_LP_MAX_ABS_OFF,
2661
+ // not in deployed struct
2662
+ engineLpMaxAbsSweepOff: isSbf ? -1 : V12_1_ENGINE_LP_MAX_ABS_SWEEP_OFF,
2663
+ // not in deployed struct
2664
+ engineEmergencyOiModeOff: isSbf ? -1 : V12_1_ENGINE_EMERGENCY_OI_MODE_OFF,
2665
+ // not in deployed struct
2666
+ engineEmergencyStartSlotOff: isSbf ? -1 : V12_1_ENGINE_EMERGENCY_START_SLOT_OFF,
2667
+ // not in deployed struct
2668
+ engineLastBreakerSlotOff: isSbf ? -1 : V12_1_ENGINE_LAST_BREAKER_SLOT_OFF,
2669
+ // not in deployed struct
2670
+ engineBitmapOff: bitmapOff,
2182
2671
  postBitmap: 18,
2183
2672
  acctOwnerOff: V12_1_ACCT_OWNER_OFF,
2184
- hasInsuranceIsolation: true,
2185
- engineInsuranceIsolatedOff: 48,
2186
- engineInsuranceIsolationBpsOff: 64
2673
+ // InsuranceFund on deployed program is just {balance: U128} = 16 bytes.
2674
+ // No isolated_balance or insurance_isolation_bps fields.
2675
+ hasInsuranceIsolation: !isSbf,
2676
+ engineInsuranceIsolatedOff: isSbf ? -1 : 48,
2677
+ engineInsuranceIsolationBpsOff: isSbf ? -1 : 64
2678
+ };
2679
+ }
2680
+ function buildLayoutV12_1EP(maxAccounts) {
2681
+ const engineOff = V12_1_SBF_ENGINE_OFF;
2682
+ const bitmapOff = V12_1_SBF_BITMAP_OFF;
2683
+ const accountSize = V12_1_EP_SBF_ACCOUNT_SIZE;
2684
+ const bitmapWords = Math.ceil(maxAccounts / 64);
2685
+ const bitmapBytes = bitmapWords * 8;
2686
+ const postBitmap = 18;
2687
+ const nextFreeBytes = maxAccounts * 2;
2688
+ const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;
2689
+ const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;
2690
+ return {
2691
+ version: 1,
2692
+ headerLen: 72,
2693
+ configOffset: 72,
2694
+ configLen: 544,
2695
+ reservedOff: 80,
2696
+ // V1_RESERVED_OFF
2697
+ engineOff,
2698
+ accountSize,
2699
+ maxAccounts,
2700
+ bitmapWords,
2701
+ accountsOff: engineOff + accountsOffRel,
2702
+ engineInsuranceOff: 16,
2703
+ engineParamsOff: 32,
2704
+ // V12_1_ENGINE_PARAMS_OFF_SBF
2705
+ paramsSize: 184,
2706
+ // V12_1_PARAMS_SIZE_SBF
2707
+ // Engine offsets identical to V12_1 SBF
2708
+ engineCurrentSlotOff: V12_1_SBF_OFF_CURRENT_SLOT,
2709
+ engineFundingIndexOff: -1,
2710
+ engineLastFundingSlotOff: -1,
2711
+ engineFundingRateBpsOff: V12_1_SBF_OFF_FUNDING_RATE,
2712
+ engineMarkPriceOff: V12_1_SBF_OFF_MARK_PRICE_E6,
2713
+ engineLastCrankSlotOff: V12_1_SBF_OFF_LAST_CRANK_SLOT,
2714
+ engineMaxCrankStalenessOff: V12_1_SBF_OFF_MAX_CRANK_STALENESS,
2715
+ engineTotalOiOff: V12_1_SBF_OFF_TOTAL_OI,
2716
+ engineLongOiOff: V12_1_SBF_OFF_LONG_OI,
2717
+ engineShortOiOff: V12_1_SBF_OFF_SHORT_OI,
2718
+ engineCTotOff: V12_1_SBF_OFF_C_TOT,
2719
+ enginePnlPosTotOff: V12_1_SBF_OFF_PNL_POS_TOT,
2720
+ engineLiqCursorOff: V12_1_SBF_OFF_LIQ_CURSOR,
2721
+ engineGcCursorOff: V12_1_SBF_OFF_GC_CURSOR,
2722
+ engineLastSweepStartOff: V12_1_SBF_OFF_LAST_SWEEP_START,
2723
+ engineLastSweepCompleteOff: V12_1_SBF_OFF_LAST_SWEEP_COMPLETE,
2724
+ engineCrankCursorOff: V12_1_SBF_OFF_CRANK_CURSOR,
2725
+ engineSweepStartIdxOff: V12_1_SBF_OFF_SWEEP_START_IDX,
2726
+ engineLifetimeLiquidationsOff: V12_1_SBF_OFF_LIFETIME_LIQUIDATIONS,
2727
+ engineLifetimeForceClosesOff: -1,
2728
+ engineNetLpPosOff: -1,
2729
+ engineLpSumAbsOff: -1,
2730
+ engineLpMaxAbsOff: -1,
2731
+ engineLpMaxAbsSweepOff: -1,
2732
+ engineEmergencyOiModeOff: -1,
2733
+ engineEmergencyStartSlotOff: -1,
2734
+ engineLastBreakerSlotOff: -1,
2735
+ engineBitmapOff: bitmapOff,
2736
+ postBitmap: 18,
2737
+ // Account offsets — shifted +8 from V12_1 due to entry_price insertion
2738
+ acctOwnerOff: V12_1_EP_ACCT_OWNER_OFF,
2739
+ // 216 (was 208)
2740
+ hasInsuranceIsolation: false,
2741
+ engineInsuranceIsolatedOff: -1,
2742
+ engineInsuranceIsolationBpsOff: -1
2743
+ };
2744
+ }
2745
+ function buildLayoutV12_15(maxAccounts, dataLen) {
2746
+ const isSbf = dataLen === 237512;
2747
+ const accountSize = isSbf ? V12_15_ACCOUNT_SIZE_SMALL : V12_15_ACCOUNT_SIZE;
2748
+ const engineOff = isSbf ? V12_15_ENGINE_OFF_SBF : V12_15_ENGINE_OFF;
2749
+ const bitmapOff = V12_15_ENGINE_BITMAP_OFF;
2750
+ const effectiveBitmapOff = isSbf ? 648 : bitmapOff;
2751
+ const bitmapWords = Math.ceil(maxAccounts / 64);
2752
+ const bitmapBytes = bitmapWords * 8;
2753
+ const postBitmap = 18;
2754
+ const nextFreeBytes = maxAccounts * 2;
2755
+ const preAccountsLen = effectiveBitmapOff + bitmapBytes + postBitmap + nextFreeBytes;
2756
+ const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;
2757
+ return {
2758
+ version: 2,
2759
+ headerLen: V0_HEADER_LEN,
2760
+ // 72
2761
+ configOffset: V0_HEADER_LEN,
2762
+ // 72
2763
+ configLen: 552,
2764
+ // SBF CONFIG_LEN for v12.15
2765
+ reservedOff: V1_RESERVED_OFF,
2766
+ // 80
2767
+ engineOff,
2768
+ accountSize,
2769
+ maxAccounts,
2770
+ bitmapWords,
2771
+ accountsOff: engineOff + accountsOffRel,
2772
+ engineInsuranceOff: 16,
2773
+ engineParamsOff: V12_15_ENGINE_PARAMS_OFF,
2774
+ // 32
2775
+ paramsSize: isSbf ? 184 : V12_15_PARAMS_SIZE,
2776
+ // SBF=184 (no trailing pad), native=192
2777
+ engineCurrentSlotOff: isSbf ? 216 : V12_15_ENGINE_CURRENT_SLOT_OFF,
2778
+ // SBF=216, native=224
2779
+ engineFundingIndexOff: -1,
2780
+ // not present in v12.15 engine struct
2781
+ engineLastFundingSlotOff: -1,
2782
+ // not present in v12.15 engine struct
2783
+ engineFundingRateBpsOff: isSbf ? 224 : V12_15_ENGINE_FUNDING_RATE_E9_OFF,
2784
+ // SBF=224, native=240
2785
+ engineMarkPriceOff: -1,
2786
+ // not present in v12.15
2787
+ engineLastCrankSlotOff: -1,
2788
+ // not yet mapped
2789
+ engineMaxCrankStalenessOff: -1,
2790
+ // not yet mapped
2791
+ engineTotalOiOff: -1,
2792
+ // not present in v12.15 engine
2793
+ engineLongOiOff: -1,
2794
+ // not present in v12.15 engine
2795
+ engineShortOiOff: -1,
2796
+ // not present in v12.15 engine
2797
+ engineCTotOff: isSbf ? 320 : V12_15_ENGINE_C_TOT_OFF,
2798
+ // SBF=320 (verified on-chain), native=344
2799
+ enginePnlPosTotOff: isSbf ? 336 : V12_15_ENGINE_PNL_POS_TOT_OFF,
2800
+ // SBF=336 (verified), native=368
2801
+ engineLiqCursorOff: -1,
2802
+ // not yet mapped
2803
+ engineGcCursorOff: -1,
2804
+ // not yet mapped
2805
+ engineLastSweepStartOff: -1,
2806
+ // not yet mapped
2807
+ engineLastSweepCompleteOff: -1,
2808
+ // not yet mapped
2809
+ engineCrankCursorOff: -1,
2810
+ // not yet mapped
2811
+ engineSweepStartIdxOff: -1,
2812
+ // not yet mapped
2813
+ engineLifetimeLiquidationsOff: -1,
2814
+ // not yet mapped
2815
+ engineLifetimeForceClosesOff: -1,
2816
+ // not present in v12.15
2817
+ engineNetLpPosOff: -1,
2818
+ // not present in v12.15
2819
+ engineLpSumAbsOff: -1,
2820
+ // not present in v12.15
2821
+ engineLpMaxAbsOff: -1,
2822
+ // not present in v12.15
2823
+ engineLpMaxAbsSweepOff: -1,
2824
+ // not present in v12.15
2825
+ engineEmergencyOiModeOff: -1,
2826
+ // not present in v12.15
2827
+ engineEmergencyStartSlotOff: -1,
2828
+ // not present in v12.15
2829
+ engineLastBreakerSlotOff: -1,
2830
+ // not present in v12.15
2831
+ engineBitmapOff: effectiveBitmapOff,
2832
+ // SBF=640, native=862
2833
+ postBitmap,
2834
+ acctOwnerOff: V12_15_ACCT_OWNER_OFF,
2835
+ // 192
2836
+ hasInsuranceIsolation: false,
2837
+ engineInsuranceIsolatedOff: -1,
2838
+ engineInsuranceIsolationBpsOff: -1
2839
+ };
2840
+ }
2841
+ function buildLayoutV12_17(maxAccounts, dataLen) {
2842
+ const isSbf = (() => {
2843
+ const bitmapBytes2 = Math.ceil(maxAccounts / 64) * 8;
2844
+ const preAccNative = V12_17_ENGINE_BITMAP_OFF + bitmapBytes2 + 4 + maxAccounts * 2;
2845
+ const accountsOffNative = Math.ceil(preAccNative / 16) * 16;
2846
+ const nativeSize = V12_17_ENGINE_OFF + accountsOffNative + maxAccounts * V12_17_ACCOUNT_SIZE + V12_17_RISK_BUF_LEN;
2847
+ return dataLen !== nativeSize;
2848
+ })();
2849
+ const engineOff = isSbf ? V12_17_ENGINE_OFF_SBF : V12_17_ENGINE_OFF;
2850
+ const accountSize = isSbf ? V12_17_ACCOUNT_SIZE_SBF : V12_17_ACCOUNT_SIZE;
2851
+ const bitmapOff = isSbf ? V12_17_ENGINE_BITMAP_OFF_SBF : V12_17_ENGINE_BITMAP_OFF;
2852
+ const bitmapWords = Math.ceil(maxAccounts / 64);
2853
+ const bitmapBytes = bitmapWords * 8;
2854
+ const postBitmap = 4;
2855
+ const nextFreeBytes = maxAccounts * 2;
2856
+ const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;
2857
+ const acctAlign = isSbf ? 8 : 16;
2858
+ const accountsOffRel = Math.ceil(preAccountsLen / acctAlign) * acctAlign;
2859
+ return {
2860
+ version: 2,
2861
+ headerLen: V0_HEADER_LEN,
2862
+ // 72
2863
+ configOffset: V0_HEADER_LEN,
2864
+ // 72
2865
+ configLen: 432,
2866
+ // upstream 400 + dex_pool 32
2867
+ reservedOff: V1_RESERVED_OFF,
2868
+ // 80
2869
+ engineOff,
2870
+ accountSize,
2871
+ maxAccounts,
2872
+ bitmapWords,
2873
+ accountsOff: engineOff + accountsOffRel,
2874
+ engineInsuranceOff: 16,
2875
+ engineParamsOff: V12_17_ENGINE_PARAMS_OFF,
2876
+ // 32
2877
+ paramsSize: isSbf ? 184 : 192,
2878
+ engineCurrentSlotOff: isSbf ? V12_17_SBF_ENGINE_CURRENT_SLOT_OFF : V12_17_ENGINE_CURRENT_SLOT_OFF,
2879
+ engineFundingIndexOff: -1,
2880
+ // replaced by per-side f_long_num/f_short_num
2881
+ engineLastFundingSlotOff: -1,
2882
+ engineFundingRateBpsOff: -1,
2883
+ // no stored funding rate in v12.17
2884
+ engineMarkPriceOff: -1,
2885
+ engineLastCrankSlotOff: -1,
2886
+ engineMaxCrankStalenessOff: -1,
2887
+ engineTotalOiOff: -1,
2888
+ engineLongOiOff: -1,
2889
+ engineShortOiOff: -1,
2890
+ engineCTotOff: isSbf ? V12_17_SBF_ENGINE_C_TOT_OFF : V12_17_ENGINE_C_TOT_OFF,
2891
+ enginePnlPosTotOff: isSbf ? V12_17_SBF_ENGINE_PNL_POS_TOT_OFF : V12_17_ENGINE_PNL_POS_TOT_OFF,
2892
+ engineLiqCursorOff: -1,
2893
+ engineGcCursorOff: -1,
2894
+ engineLastSweepStartOff: -1,
2895
+ engineLastSweepCompleteOff: -1,
2896
+ engineCrankCursorOff: -1,
2897
+ engineSweepStartIdxOff: -1,
2898
+ engineLifetimeLiquidationsOff: -1,
2899
+ engineLifetimeForceClosesOff: -1,
2900
+ engineNetLpPosOff: -1,
2901
+ engineLpSumAbsOff: -1,
2902
+ engineLpMaxAbsOff: -1,
2903
+ engineLpMaxAbsSweepOff: -1,
2904
+ engineEmergencyOiModeOff: -1,
2905
+ engineEmergencyStartSlotOff: -1,
2906
+ engineLastBreakerSlotOff: -1,
2907
+ engineBitmapOff: bitmapOff,
2908
+ postBitmap,
2909
+ acctOwnerOff: isSbf ? 192 : V12_17_ACCT_OWNER_OFF,
2910
+ // SBF=192, native=200
2911
+ hasInsuranceIsolation: false,
2912
+ engineInsuranceIsolatedOff: -1,
2913
+ engineInsuranceIsolationBpsOff: -1
2187
2914
  };
2188
2915
  }
2189
2916
  function detectSlabLayout(dataLen, data) {
2917
+ const v1217n = V12_17_SIZES.get(dataLen);
2918
+ if (v1217n !== void 0) return buildLayoutV12_17(v1217n, dataLen);
2919
+ const v1215n = V12_15_SIZES.get(dataLen);
2920
+ if (v1215n !== void 0) return buildLayoutV12_15(v1215n, dataLen);
2921
+ const v121epn = V12_1_EP_SIZES.get(dataLen);
2922
+ if (v121epn !== void 0) return buildLayoutV12_1EP(v121epn);
2190
2923
  const v121n = V12_1_SIZES.get(dataLen);
2191
- if (v121n !== void 0) return buildLayoutV12_1(v121n);
2924
+ if (v121n !== void 0) return buildLayoutV12_1(v121n, dataLen);
2192
2925
  const vsdpn = V_SETDEXPOOL_SIZES.get(dataLen);
2193
2926
  if (vsdpn !== void 0) return buildLayoutVSetDexPool(vsdpn);
2194
2927
  const v1m2n = V1M2_SIZES.get(dataLen);
@@ -2233,6 +2966,15 @@ var PARAMS_LIQUIDATION_FEE_BPS_OFF = 96;
2233
2966
  var PARAMS_LIQUIDATION_FEE_CAP_OFF = 104;
2234
2967
  var PARAMS_LIQUIDATION_BUFFER_OFF = 120;
2235
2968
  var PARAMS_MIN_LIQUIDATION_OFF = 128;
2969
+ var V12_1_PARAMS_MAINT_FEE_OFF = 56;
2970
+ var V12_1_PARAMS_MAX_CRANK_OFF = 72;
2971
+ var V12_1_PARAMS_LIQ_FEE_BPS_OFF = 80;
2972
+ var V12_1_PARAMS_LIQ_FEE_CAP_OFF = 88;
2973
+ var V12_1_PARAMS_MIN_LIQ_OFF = 104;
2974
+ var V12_1_PARAMS_MIN_INITIAL_DEP_OFF = 120;
2975
+ var V12_1_PARAMS_MIN_NZ_MM_OFF = 136;
2976
+ var V12_1_PARAMS_MIN_NZ_IM_OFF = 152;
2977
+ var V12_1_PARAMS_INS_FLOOR_OFF = 168;
2236
2978
  var ACCT_ACCOUNT_ID_OFF = 0;
2237
2979
  var ACCT_CAPITAL_OFF = 8;
2238
2980
  var ACCT_KIND_OFF = 24;
@@ -2303,7 +3045,7 @@ function parseHeader(data) {
2303
3045
  const version = readU32LE(data, 8);
2304
3046
  const bump = readU8(data, 12);
2305
3047
  const flags = readU8(data, 13);
2306
- const admin = new PublicKey3(data.subarray(16, 48));
3048
+ const admin = new PublicKey5(data.subarray(16, 48));
2307
3049
  const layout = detectSlabLayout(data.length, data);
2308
3050
  const roff = layout ? layout.reservedOff : V0_RESERVED_OFF;
2309
3051
  const nonce = readU64LE(data, roff);
@@ -2324,16 +3066,17 @@ function parseConfig(data, layoutHint) {
2324
3066
  const layout = layoutHint !== void 0 ? layoutHint : detectSlabLayout(data.length, data);
2325
3067
  const configOff = layout ? layout.configOffset : V0_HEADER_LEN;
2326
3068
  const configLen = layout ? layout.configLen : V0_CONFIG_LEN;
2327
- const minLen = configOff + Math.min(configLen, 120);
3069
+ const MIN_CONFIG_BYTES = 376;
3070
+ const minLen = configOff + Math.min(configLen, MIN_CONFIG_BYTES);
2328
3071
  if (data.length < minLen) {
2329
3072
  throw new Error(`Slab data too short for config: ${data.length} < ${minLen}`);
2330
3073
  }
2331
3074
  let off = configOff;
2332
- const collateralMint = new PublicKey3(data.subarray(off, off + 32));
3075
+ const collateralMint = new PublicKey5(data.subarray(off, off + 32));
2333
3076
  off += 32;
2334
- const vaultPubkey = new PublicKey3(data.subarray(off, off + 32));
3077
+ const vaultPubkey = new PublicKey5(data.subarray(off, off + 32));
2335
3078
  off += 32;
2336
- const indexFeedId = new PublicKey3(data.subarray(off, off + 32));
3079
+ const indexFeedId = new PublicKey5(data.subarray(off, off + 32));
2337
3080
  off += 32;
2338
3081
  const maxStalenessSlots = readU64LE(data, off);
2339
3082
  off += 8;
@@ -2355,14 +3098,6 @@ function parseConfig(data, layoutHint) {
2355
3098
  off += 8;
2356
3099
  const fundingMaxBpsPerSlot = readI64LE(data, off);
2357
3100
  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
3101
  const threshFloor = readU128LE(data, off);
2367
3102
  off += 16;
2368
3103
  const threshRiskBps = readU64LE(data, off);
@@ -2379,7 +3114,7 @@ function parseConfig(data, layoutHint) {
2379
3114
  off += 16;
2380
3115
  const threshMinStep = readU128LE(data, off);
2381
3116
  off += 16;
2382
- const oracleAuthority = new PublicKey3(data.subarray(off, off + 32));
3117
+ const oracleAuthority = new PublicKey5(data.subarray(off, off + 32));
2383
3118
  off += 32;
2384
3119
  const authorityPriceE6 = readU64LE(data, off);
2385
3120
  off += 8;
@@ -2432,7 +3167,7 @@ function parseConfig(data, layoutHint) {
2432
3167
  if (configLen >= DEX_POOL_REL_OFF + 32 && data.length >= configOff + DEX_POOL_REL_OFF + 32) {
2433
3168
  const dexPoolBytes = data.subarray(configOff + DEX_POOL_REL_OFF, configOff + DEX_POOL_REL_OFF + 32);
2434
3169
  if (dexPoolBytes.some((b) => b !== 0)) {
2435
- dexPool = new PublicKey3(dexPoolBytes);
3170
+ dexPool = new PublicKey5(dexPoolBytes);
2436
3171
  }
2437
3172
  }
2438
3173
  return {
@@ -2449,10 +3184,10 @@ function parseConfig(data, layoutHint) {
2449
3184
  fundingInvScaleNotionalE6,
2450
3185
  fundingMaxPremiumBps,
2451
3186
  fundingMaxBpsPerSlot,
2452
- fundingPremiumWeightBps,
2453
- fundingSettlementIntervalSlots,
2454
- fundingPremiumDampeningE6,
2455
- fundingPremiumMaxBpsPerSlot,
3187
+ fundingPremiumWeightBps: 0n,
3188
+ fundingSettlementIntervalSlots: 0n,
3189
+ fundingPremiumDampeningE6: 0n,
3190
+ fundingPremiumMaxBpsPerSlot: 0n,
2456
3191
  threshFloor,
2457
3192
  threshRiskBps,
2458
3193
  threshUpdateIntervalSlots,
@@ -2487,26 +3222,61 @@ function parseParams(data, layoutHint) {
2487
3222
  const paramsOff = layout ? layout.engineParamsOff : V0_ENGINE_PARAMS_OFF;
2488
3223
  const paramsSize = layout ? layout.paramsSize : V0_PARAMS_SIZE;
2489
3224
  const base = engineOff + paramsOff;
2490
- if (data.length < base + Math.min(paramsSize, 56)) {
2491
- throw new Error("Slab data too short for RiskParams");
3225
+ const MIN_PARAMS_BYTES = paramsSize >= 144 ? 144 : 56;
3226
+ if (data.length < base + MIN_PARAMS_BYTES) {
3227
+ throw new Error(`Slab data too short for RiskParams: ${data.length} < ${base + MIN_PARAMS_BYTES}`);
2492
3228
  }
3229
+ const isV12_15Params = paramsSize === V12_15_PARAMS_SIZE || paramsSize === 184;
3230
+ const isV12_1Sbf = !isV12_15Params && layout !== null && layout !== void 0 && layout.engineOff === V12_1_SBF_ENGINE_OFF && paramsSize === 184;
2493
3231
  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)
3232
+ warmupPeriodSlots: isV12_15Params ? readU64LE(data, base + V12_15_PARAMS_H_MIN_OFF) : readU64LE(data, base + PARAMS_WARMUP_PERIOD_OFF),
3233
+ maintenanceMarginBps: isV12_15Params ? readU64LE(data, base + 0) : readU64LE(data, base + PARAMS_MAINTENANCE_MARGIN_OFF),
3234
+ initialMarginBps: isV12_15Params ? readU64LE(data, base + 8) : readU64LE(data, base + PARAMS_INITIAL_MARGIN_OFF),
3235
+ tradingFeeBps: isV12_15Params ? readU64LE(data, base + 16) : readU64LE(data, base + PARAMS_TRADING_FEE_OFF),
3236
+ maxAccounts: isV12_15Params ? readU64LE(data, base + V12_15_PARAMS_MAX_ACCOUNTS_OFF) : readU64LE(data, base + PARAMS_MAX_ACCOUNTS_OFF),
3237
+ newAccountFee: isV12_15Params ? readU128LE(data, base + 32) : readU128LE(data, base + PARAMS_NEW_ACCOUNT_FEE_OFF),
3238
+ // Extended params: defaults; overwritten below if layout supports them
2501
3239
  riskReductionThreshold: 0n,
2502
3240
  maintenanceFeePerSlot: 0n,
2503
3241
  maxCrankStalenessSlots: 0n,
2504
3242
  liquidationFeeBps: 0n,
2505
3243
  liquidationFeeCap: 0n,
2506
3244
  liquidationBufferBps: 0n,
2507
- minLiquidationAbs: 0n
3245
+ minLiquidationAbs: 0n,
3246
+ minInitialDeposit: 0n,
3247
+ minNonzeroMmReq: 0n,
3248
+ minNonzeroImReq: 0n,
3249
+ insuranceFloor: 0n,
3250
+ hMin: 0n,
3251
+ hMax: 0n
2508
3252
  };
2509
- if (paramsSize >= 144) {
3253
+ if (isV12_15Params) {
3254
+ result.hMin = readU64LE(data, base + V12_15_PARAMS_H_MIN_OFF);
3255
+ result.hMax = readU64LE(data, base + V12_15_PARAMS_H_MAX_OFF);
3256
+ result.insuranceFloor = readU128LE(data, base + V12_15_PARAMS_INSURANCE_FLOOR_OFF);
3257
+ result.riskReductionThreshold = 0n;
3258
+ result.maintenanceFeePerSlot = 0n;
3259
+ result.maxCrankStalenessSlots = readU64LE(data, base + 48);
3260
+ result.liquidationFeeBps = readU64LE(data, base + 56);
3261
+ result.liquidationFeeCap = readU128LE(data, base + 64);
3262
+ result.liquidationBufferBps = 0n;
3263
+ result.minLiquidationAbs = readU128LE(data, base + 80);
3264
+ result.minInitialDeposit = readU128LE(data, base + 96);
3265
+ result.minNonzeroMmReq = readU128LE(data, base + 112);
3266
+ result.minNonzeroImReq = readU128LE(data, base + 128);
3267
+ } else if (isV12_1Sbf) {
3268
+ result.maintenanceFeePerSlot = readU128LE(data, base + V12_1_PARAMS_MAINT_FEE_OFF);
3269
+ result.maxCrankStalenessSlots = readU64LE(data, base + V12_1_PARAMS_MAX_CRANK_OFF);
3270
+ result.liquidationFeeBps = readU64LE(data, base + V12_1_PARAMS_LIQ_FEE_BPS_OFF);
3271
+ result.liquidationFeeCap = readU128LE(data, base + V12_1_PARAMS_LIQ_FEE_CAP_OFF);
3272
+ result.minLiquidationAbs = readU128LE(data, base + V12_1_PARAMS_MIN_LIQ_OFF);
3273
+ result.minInitialDeposit = readU128LE(data, base + V12_1_PARAMS_MIN_INITIAL_DEP_OFF);
3274
+ result.minNonzeroMmReq = readU128LE(data, base + V12_1_PARAMS_MIN_NZ_MM_OFF);
3275
+ result.minNonzeroImReq = readU128LE(data, base + V12_1_PARAMS_MIN_NZ_IM_OFF);
3276
+ result.insuranceFloor = readU128LE(data, base + V12_1_PARAMS_INS_FLOOR_OFF);
3277
+ result.hMin = result.warmupPeriodSlots;
3278
+ result.hMax = result.warmupPeriodSlots;
3279
+ } else if (paramsSize >= 144) {
2510
3280
  result.riskReductionThreshold = readU128LE(data, base + PARAMS_RISK_THRESHOLD_OFF);
2511
3281
  result.maintenanceFeePerSlot = readU128LE(data, base + PARAMS_MAINTENANCE_FEE_OFF);
2512
3282
  result.maxCrankStalenessSlots = readU64LE(data, base + PARAMS_MAX_CRANK_STALENESS_OFF);
@@ -2514,6 +3284,8 @@ function parseParams(data, layoutHint) {
2514
3284
  result.liquidationFeeCap = readU128LE(data, base + PARAMS_LIQUIDATION_FEE_CAP_OFF);
2515
3285
  result.liquidationBufferBps = readU64LE(data, base + PARAMS_LIQUIDATION_BUFFER_OFF);
2516
3286
  result.minLiquidationAbs = readU128LE(data, base + PARAMS_MIN_LIQUIDATION_OFF);
3287
+ result.hMin = result.warmupPeriodSlots;
3288
+ result.hMax = result.warmupPeriodSlots;
2517
3289
  }
2518
3290
  return result;
2519
3291
  }
@@ -2523,41 +3295,122 @@ function parseEngine(data) {
2523
3295
  throw new Error(`Unrecognized slab data length: ${data.length}. Cannot determine layout version.`);
2524
3296
  }
2525
3297
  const base = layout.engineOff;
3298
+ const isV12_17 = layout.accountSize === V12_17_ACCOUNT_SIZE || layout.accountSize === V12_17_ACCOUNT_SIZE_SBF;
3299
+ 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);
3300
+ if (isV12_17) {
3301
+ const isSbf = layout.engineOff === V12_17_ENGINE_OFF_SBF;
3302
+ const currentSlotOff = isSbf ? V12_17_SBF_ENGINE_CURRENT_SLOT_OFF : V12_17_ENGINE_CURRENT_SLOT_OFF;
3303
+ const marketModeOff = isSbf ? V12_17_SBF_ENGINE_MARKET_MODE_OFF : V12_17_ENGINE_MARKET_MODE_OFF;
3304
+ const cTotOff = isSbf ? V12_17_SBF_ENGINE_C_TOT_OFF : V12_17_ENGINE_C_TOT_OFF;
3305
+ const pnlPosTotOff = isSbf ? V12_17_SBF_ENGINE_PNL_POS_TOT_OFF : V12_17_ENGINE_PNL_POS_TOT_OFF;
3306
+ const pnlMaturedOff = isSbf ? V12_17_SBF_ENGINE_PNL_MATURED_POS_TOT_OFF : V12_17_ENGINE_PNL_MATURED_POS_TOT_OFF;
3307
+ const negPnlOff = isSbf ? V12_17_SBF_ENGINE_NEG_PNL_COUNT_OFF : V12_17_ENGINE_NEG_PNL_COUNT_OFF;
3308
+ const oraclePriceOff = isSbf ? V12_17_SBF_ENGINE_LAST_ORACLE_PRICE_OFF : V12_17_ENGINE_LAST_ORACLE_PRICE_OFF;
3309
+ const fundPxLastOff = isSbf ? V12_17_SBF_ENGINE_FUND_PX_LAST_OFF : V12_17_ENGINE_FUND_PX_LAST_OFF;
3310
+ const fLongNumOff = isSbf ? V12_17_SBF_ENGINE_F_LONG_NUM_OFF : V12_17_ENGINE_F_LONG_NUM_OFF;
3311
+ const fShortNumOff = isSbf ? V12_17_SBF_ENGINE_F_SHORT_NUM_OFF : V12_17_ENGINE_F_SHORT_NUM_OFF;
3312
+ const resolvedKLongOff = isSbf ? 288 : V12_17_ENGINE_RESOLVED_K_LONG_OFF;
3313
+ const resolvedKShortOff = isSbf ? 304 : V12_17_ENGINE_RESOLVED_K_SHORT_OFF;
3314
+ const resolvedLivePriceOff = isSbf ? 320 : V12_17_ENGINE_RESOLVED_LIVE_PRICE_OFF;
3315
+ const bitmapEnd = layout.engineBitmapOff + layout.bitmapWords * 8;
3316
+ return {
3317
+ vault: readU128LE(data, base),
3318
+ insuranceFund: {
3319
+ balance: readU128LE(data, base + 16),
3320
+ feeRevenue: 0n,
3321
+ isolatedBalance: 0n,
3322
+ isolationBps: 0
3323
+ },
3324
+ currentSlot: readU64LE(data, base + currentSlotOff),
3325
+ fundingIndexQpbE6: 0n,
3326
+ // replaced by per-side funding
3327
+ lastFundingSlot: 0n,
3328
+ fundingRateBpsPerSlotLast: 0n,
3329
+ // no stored funding rate in v12.17
3330
+ fundingRateE9: 0n,
3331
+ // no stored funding rate in v12.17
3332
+ marketMode: readU8(data, base + marketModeOff) === 1 ? 1 : 0,
3333
+ lastCrankSlot: 0n,
3334
+ maxCrankStalenessSlots: 0n,
3335
+ totalOpenInterest: 0n,
3336
+ longOi: 0n,
3337
+ shortOi: 0n,
3338
+ cTot: readU128LE(data, base + cTotOff),
3339
+ pnlPosTot: readU128LE(data, base + pnlPosTotOff),
3340
+ pnlMaturedPosTot: readU128LE(data, base + pnlMaturedOff),
3341
+ liqCursor: 0,
3342
+ gcCursor: 0,
3343
+ lastSweepStartSlot: 0n,
3344
+ lastSweepCompleteSlot: 0n,
3345
+ crankCursor: 0,
3346
+ sweepStartIdx: 0,
3347
+ lifetimeLiquidations: 0n,
3348
+ lifetimeForceCloses: 0n,
3349
+ netLpPos: 0n,
3350
+ lpSumAbs: 0n,
3351
+ lpMaxAbs: 0n,
3352
+ lpMaxAbsSweep: 0n,
3353
+ emergencyOiMode: false,
3354
+ emergencyStartSlot: 0n,
3355
+ lastBreakerSlot: 0n,
3356
+ markPriceE6: 0n,
3357
+ oraclePriceE6: readU64LE(data, base + oraclePriceOff),
3358
+ numUsedAccounts: readU16LE(data, base + bitmapEnd),
3359
+ nextAccountId: 0n,
3360
+ // removed in v12.17 (replaced by mat_counter in header)
3361
+ // V12_17 fields
3362
+ fLongNum: readI128LE(data, base + fLongNumOff),
3363
+ fShortNum: readI128LE(data, base + fShortNumOff),
3364
+ negPnlAccountCount: readU64LE(data, base + negPnlOff),
3365
+ fundPxLast: readU64LE(data, base + fundPxLastOff),
3366
+ resolvedKLongTerminalDelta: readI128LE(data, base + resolvedKLongOff),
3367
+ resolvedKShortTerminalDelta: readI128LE(data, base + resolvedKShortOff),
3368
+ resolvedLivePrice: readU64LE(data, base + resolvedLivePriceOff)
3369
+ };
3370
+ }
3371
+ const fundingRateBpsPerSlotLast = isV12_15 ? readI128LE(data, base + layout.engineFundingRateBpsOff) : readI64LE(data, base + layout.engineFundingRateBpsOff);
2526
3372
  return {
2527
3373
  vault: readU128LE(data, base),
2528
3374
  insuranceFund: {
2529
3375
  balance: readU128LE(data, base + layout.engineInsuranceOff),
2530
- feeRevenue: readU128LE(data, base + layout.engineInsuranceOff + 16),
3376
+ // feeRevenue: only exists in percolator-core (80-byte InsuranceFund), not deployed (16-byte)
3377
+ feeRevenue: layout.hasInsuranceIsolation ? readU128LE(data, base + layout.engineInsuranceOff + 16) : 0n,
2531
3378
  isolatedBalance: layout.hasInsuranceIsolation ? readU128LE(data, base + layout.engineInsuranceIsolatedOff) : 0n,
2532
3379
  isolationBps: layout.hasInsuranceIsolation ? readU16LE(data, base + layout.engineInsuranceIsolationBpsOff) : 0
2533
3380
  },
2534
3381
  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),
3382
+ fundingIndexQpbE6: layout.engineFundingIndexOff >= 0 ? readI128LE(data, base + layout.engineFundingIndexOff) : 0n,
3383
+ lastFundingSlot: layout.engineLastFundingSlotOff >= 0 ? readU64LE(data, base + layout.engineLastFundingSlotOff) : 0n,
3384
+ fundingRateBpsPerSlotLast,
3385
+ fundingRateE9: isV12_15 ? readI128LE(data, base + layout.engineFundingRateBpsOff) : 0n,
3386
+ marketMode: isV12_15 ? readU8(data, base + layout.engineFundingRateBpsOff + 16) === 1 ? 1 : 0 : null,
3387
+ lastCrankSlot: layout.engineLastCrankSlotOff >= 0 ? readU64LE(data, base + layout.engineLastCrankSlotOff) : 0n,
3388
+ maxCrankStalenessSlots: layout.engineMaxCrankStalenessOff >= 0 ? readU64LE(data, base + layout.engineMaxCrankStalenessOff) : 0n,
3389
+ totalOpenInterest: layout.engineTotalOiOff >= 0 ? readU128LE(data, base + layout.engineTotalOiOff) : 0n,
2541
3390
  longOi: layout.engineLongOiOff >= 0 ? readU128LE(data, base + layout.engineLongOiOff) : 0n,
2542
3391
  shortOi: layout.engineShortOiOff >= 0 ? readU128LE(data, base + layout.engineShortOiOff) : 0n,
2543
3392
  cTot: readU128LE(data, base + layout.engineCTotOff),
2544
3393
  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),
3394
+ pnlMaturedPosTot: isV12_15 ? readU128LE(data, base + V12_15_ENGINE_PNL_MATURED_POS_TOT_OFF) : 0n,
3395
+ liqCursor: layout.engineLiqCursorOff >= 0 ? readU16LE(data, base + layout.engineLiqCursorOff) : 0,
3396
+ gcCursor: layout.engineGcCursorOff >= 0 ? readU16LE(data, base + layout.engineGcCursorOff) : 0,
3397
+ lastSweepStartSlot: layout.engineLastSweepStartOff >= 0 ? readU64LE(data, base + layout.engineLastSweepStartOff) : 0n,
3398
+ lastSweepCompleteSlot: layout.engineLastSweepCompleteOff >= 0 ? readU64LE(data, base + layout.engineLastSweepCompleteOff) : 0n,
3399
+ crankCursor: layout.engineCrankCursorOff >= 0 ? readU16LE(data, base + layout.engineCrankCursorOff) : 0,
3400
+ sweepStartIdx: layout.engineSweepStartIdxOff >= 0 ? readU16LE(data, base + layout.engineSweepStartIdxOff) : 0,
3401
+ lifetimeLiquidations: layout.engineLifetimeLiquidationsOff >= 0 ? readU64LE(data, base + layout.engineLifetimeLiquidationsOff) : 0n,
3402
+ lifetimeForceCloses: layout.engineLifetimeForceClosesOff >= 0 ? readU64LE(data, base + layout.engineLifetimeForceClosesOff) : 0n,
3403
+ netLpPos: layout.engineNetLpPosOff >= 0 ? readI128LE(data, base + layout.engineNetLpPosOff) : 0n,
3404
+ lpSumAbs: layout.engineLpSumAbsOff >= 0 ? readU128LE(data, base + layout.engineLpSumAbsOff) : 0n,
2555
3405
  lpMaxAbs: layout.engineLpMaxAbsOff >= 0 ? readU128LE(data, base + layout.engineLpMaxAbsOff) : 0n,
2556
3406
  lpMaxAbsSweep: layout.engineLpMaxAbsSweepOff >= 0 ? readU128LE(data, base + layout.engineLpMaxAbsSweepOff) : 0n,
2557
3407
  emergencyOiMode: layout.engineEmergencyOiModeOff >= 0 ? data[base + layout.engineEmergencyOiModeOff] !== 0 : false,
2558
3408
  emergencyStartSlot: layout.engineEmergencyStartSlotOff >= 0 ? readU64LE(data, base + layout.engineEmergencyStartSlotOff) : 0n,
2559
3409
  lastBreakerSlot: layout.engineLastBreakerSlotOff >= 0 ? readU64LE(data, base + layout.engineLastBreakerSlotOff) : 0n,
2560
3410
  markPriceE6: layout.engineMarkPriceOff >= 0 ? readU64LE(data, base + layout.engineMarkPriceOff) : 0n,
3411
+ // V12_15: last_oracle_price at engine+608 (SBF) / engine+... (native).
3412
+ // Located at bitmapOff - 40 on SBF (648-40=608, verified on-chain).
3413
+ oraclePriceE6: isV12_15 ? readU64LE(data, base + layout.engineBitmapOff - 40) : 0n,
2561
3414
  numUsedAccounts: (() => {
2562
3415
  if (layout.postBitmap < 18) return 0;
2563
3416
  const bw = layout.bitmapWords;
@@ -2568,7 +3421,15 @@ function parseEngine(data) {
2568
3421
  const bw = layout.bitmapWords;
2569
3422
  const numUsedOff = layout.engineBitmapOff + bw * 8;
2570
3423
  return readU64LE(data, base + Math.ceil((numUsedOff + 2) / 8) * 8);
2571
- })()
3424
+ })(),
3425
+ // V12_17 fields (not present in pre-v12.17)
3426
+ fLongNum: 0n,
3427
+ fShortNum: 0n,
3428
+ negPnlAccountCount: 0n,
3429
+ fundPxLast: 0n,
3430
+ resolvedKLongTerminalDelta: 0n,
3431
+ resolvedKShortTerminalDelta: 0n,
3432
+ resolvedLivePrice: 0n
2572
3433
  };
2573
3434
  }
2574
3435
  function parseUsedIndices(data) {
@@ -2618,17 +3479,129 @@ function parseAccount(data, idx) {
2618
3479
  if (data.length < base + layout.accountSize) {
2619
3480
  throw new Error("Slab data too short for account");
2620
3481
  }
2621
- const isV12_1 = layout.accountSize >= 320;
2622
- const isAdl = layout.accountSize >= 312;
3482
+ const isV12_17 = layout.accountSize === V12_17_ACCOUNT_SIZE || layout.accountSize === V12_17_ACCOUNT_SIZE_SBF;
3483
+ const isV12_15 = !isV12_17 && (layout.accountSize === V12_15_ACCOUNT_SIZE || layout.accountSize === V12_15_ACCOUNT_SIZE_SMALL);
3484
+ const isV12_1EP = !isV12_17 && !isV12_15 && layout.accountSize === V12_1_EP_SBF_ACCOUNT_SIZE && layout.engineOff === V12_1_SBF_ENGINE_OFF;
3485
+ 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);
3486
+ const isAdl = !isV12_17 && !isV12_15 && (layout.accountSize >= 312 || isV12_1 || isV12_1EP);
3487
+ if (isV12_17) {
3488
+ const isSbf = layout.accountSize === V12_17_ACCOUNT_SIZE_SBF;
3489
+ const d1 = isSbf ? 8 : 0;
3490
+ const d2 = isSbf ? 16 : 0;
3491
+ const kindByte2 = readU8(data, base + V12_17_ACCT_KIND_OFF);
3492
+ const kind2 = kindByte2 === 1 ? 1 /* LP */ : 0 /* User */;
3493
+ return {
3494
+ kind: kind2,
3495
+ accountId: 0n,
3496
+ // removed in v12.17
3497
+ capital: readU128LE(data, base + V12_17_ACCT_CAPITAL_OFF),
3498
+ pnl: readI128LE(data, base + V12_17_ACCT_PNL_OFF - d1),
3499
+ reservedPnl: readU128LE(data, base + V12_17_ACCT_RESERVED_PNL_OFF - d1),
3500
+ warmupStartedAtSlot: 0n,
3501
+ // removed
3502
+ warmupSlopePerStep: 0n,
3503
+ // removed
3504
+ positionSize: readI128LE(data, base + V12_17_ACCT_POSITION_BASIS_Q_OFF - d1),
3505
+ entryPrice: 0n,
3506
+ // removed — compute off-chain from position_basis_q / effective_pos_q
3507
+ fundingIndex: 0n,
3508
+ // replaced by per-side f_long_num/f_short_num + per-account f_snap
3509
+ matcherProgram: new PublicKey5(data.subarray(base + V12_17_ACCT_MATCHER_PROGRAM_OFF - d1, base + V12_17_ACCT_MATCHER_PROGRAM_OFF - d1 + 32)),
3510
+ matcherContext: new PublicKey5(data.subarray(base + V12_17_ACCT_MATCHER_CONTEXT_OFF - d1, base + V12_17_ACCT_MATCHER_CONTEXT_OFF - d1 + 32)),
3511
+ owner: new PublicKey5(data.subarray(base + V12_17_ACCT_OWNER_OFF - d1, base + V12_17_ACCT_OWNER_OFF - d1 + 32)),
3512
+ feeCredits: readI128LE(data, base + V12_17_ACCT_FEE_CREDITS_OFF - d1),
3513
+ lastFeeSlot: 0n,
3514
+ // removed
3515
+ feesEarnedTotal: 0n,
3516
+ // removed in v12.17
3517
+ exactReserveCohorts: null,
3518
+ // replaced by two-bucket warmup
3519
+ exactCohortCount: null,
3520
+ overflowOlder: null,
3521
+ overflowOlderPresent: null,
3522
+ overflowNewest: null,
3523
+ overflowNewestPresent: null,
3524
+ // V12_17 fields
3525
+ fSnap: readI128LE(data, base + V12_17_ACCT_F_SNAP_OFF - d1),
3526
+ adlABasis: readU128LE(data, base + V12_17_ACCT_ADL_A_BASIS_OFF - d1),
3527
+ adlKSnap: readI128LE(data, base + V12_17_ACCT_ADL_K_SNAP_OFF - d1),
3528
+ adlEpochSnap: readU64LE(data, base + V12_17_ACCT_ADL_EPOCH_SNAP_OFF - d1),
3529
+ schedPresent: readU8(data, base + V12_17_ACCT_SCHED_PRESENT_OFF - d1) !== 0,
3530
+ schedRemainingQ: readU128LE(data, base + V12_17_ACCT_SCHED_REMAINING_Q_OFF - d1),
3531
+ schedAnchorQ: readU128LE(data, base + V12_17_ACCT_SCHED_ANCHOR_Q_OFF - d1),
3532
+ schedStartSlot: readU64LE(data, base + V12_17_ACCT_SCHED_START_SLOT_OFF - d1),
3533
+ schedHorizon: readU64LE(data, base + V12_17_ACCT_SCHED_HORIZON_OFF - d1),
3534
+ schedReleaseQ: readU128LE(data, base + V12_17_ACCT_SCHED_RELEASE_Q_OFF - d1),
3535
+ pendingPresent: readU8(data, base + V12_17_ACCT_PENDING_PRESENT_OFF - d1) !== 0,
3536
+ pendingRemainingQ: readU128LE(data, base + V12_17_ACCT_PENDING_REMAINING_Q_OFF - d2),
3537
+ pendingHorizon: readU64LE(data, base + V12_17_ACCT_PENDING_HORIZON_OFF - d2),
3538
+ pendingCreatedSlot: readU64LE(data, base + V12_17_ACCT_PENDING_CREATED_SLOT_OFF - d2)
3539
+ };
3540
+ }
3541
+ if (isV12_15) {
3542
+ const kindByte2 = readU8(data, base + V12_15_ACCT_KIND_OFF);
3543
+ const kind2 = kindByte2 === 1 ? 1 /* LP */ : 0 /* User */;
3544
+ const cohortCount = readU8(data, base + V12_15_ACCT_EXACT_COHORT_COUNT_OFF);
3545
+ const exactReserveCohorts = [];
3546
+ for (let i = 0; i < 62; i++) {
3547
+ const cohortOff = base + V12_15_ACCT_EXACT_RESERVE_COHORTS_OFF + i * 64;
3548
+ exactReserveCohorts.push(data.slice(cohortOff, cohortOff + 64));
3549
+ }
3550
+ const overflowOlderPresent = readU8(data, base + V12_15_ACCT_OVERFLOW_OLDER_PRESENT_OFF) !== 0;
3551
+ const overflowNewestPresent = readU8(data, base + V12_15_ACCT_OVERFLOW_NEWEST_PRESENT_OFF) !== 0;
3552
+ return {
3553
+ kind: kind2,
3554
+ accountId: readU64LE(data, base + V12_15_ACCT_ACCOUNT_ID_OFF),
3555
+ capital: readU128LE(data, base + V12_15_ACCT_CAPITAL_OFF),
3556
+ pnl: readI128LE(data, base + V12_15_ACCT_PNL_OFF),
3557
+ reservedPnl: readU128LE(data, base + V12_15_ACCT_RESERVED_PNL_OFF),
3558
+ warmupStartedAtSlot: 0n,
3559
+ // removed in v12.15
3560
+ warmupSlopePerStep: 0n,
3561
+ // removed in v12.15
3562
+ positionSize: readI128LE(data, base + V12_15_ACCT_POSITION_BASIS_Q_OFF),
3563
+ entryPrice: readU64LE(data, base + V12_15_ACCT_ENTRY_PRICE_OFF),
3564
+ fundingIndex: 0n,
3565
+ // not present in v12.15 account struct
3566
+ matcherProgram: new PublicKey5(data.subarray(base + V12_15_ACCT_MATCHER_PROGRAM_OFF, base + V12_15_ACCT_MATCHER_PROGRAM_OFF + 32)),
3567
+ matcherContext: new PublicKey5(data.subarray(base + V12_15_ACCT_MATCHER_CONTEXT_OFF, base + V12_15_ACCT_MATCHER_CONTEXT_OFF + 32)),
3568
+ owner: new PublicKey5(data.subarray(base + V12_15_ACCT_OWNER_OFF, base + V12_15_ACCT_OWNER_OFF + 32)),
3569
+ feeCredits: readI128LE(data, base + V12_15_ACCT_FEE_CREDITS_OFF),
3570
+ lastFeeSlot: 0n,
3571
+ // removed in v12.15
3572
+ feesEarnedTotal: readU128LE(data, base + V12_15_ACCT_FEES_EARNED_TOTAL_OFF),
3573
+ exactReserveCohorts,
3574
+ exactCohortCount: cohortCount,
3575
+ overflowOlder: data.slice(base + V12_15_ACCT_OVERFLOW_OLDER_OFF, base + V12_15_ACCT_OVERFLOW_OLDER_OFF + 64),
3576
+ overflowOlderPresent,
3577
+ overflowNewest: data.slice(base + V12_15_ACCT_OVERFLOW_NEWEST_OFF, base + V12_15_ACCT_OVERFLOW_NEWEST_OFF + 64),
3578
+ overflowNewestPresent,
3579
+ // v12.17 fields (not present in v12.15)
3580
+ fSnap: 0n,
3581
+ adlABasis: 0n,
3582
+ adlKSnap: 0n,
3583
+ adlEpochSnap: 0n,
3584
+ schedPresent: null,
3585
+ schedRemainingQ: null,
3586
+ schedAnchorQ: null,
3587
+ schedStartSlot: null,
3588
+ schedHorizon: null,
3589
+ schedReleaseQ: null,
3590
+ pendingPresent: null,
3591
+ pendingRemainingQ: null,
3592
+ pendingHorizon: null,
3593
+ pendingCreatedSlot: null
3594
+ };
3595
+ }
2623
3596
  const warmupStartedOff = isAdl ? V_ADL_ACCT_WARMUP_STARTED_OFF : ACCT_WARMUP_STARTED_OFF;
2624
3597
  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;
3598
+ const positionSizeOff = isV12_1 || isV12_1EP ? V12_1_ACCT_POSITION_SIZE_OFF : isAdl ? V_ADL_ACCT_POSITION_SIZE_OFF : ACCT_POSITION_SIZE_OFF;
3599
+ 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;
3600
+ const fundingIndexOff = isV12_1 || isV12_1EP ? -1 : isAdl ? V_ADL_ACCT_FUNDING_INDEX_OFF : ACCT_FUNDING_INDEX_OFF;
3601
+ 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;
3602
+ 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;
3603
+ 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;
3604
+ 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
3605
  const kindByte = readU8(data, base + ACCT_KIND_OFF);
2633
3606
  const kind = kindByte === 1 ? 1 /* LP */ : 0 /* User */;
2634
3607
  return {
@@ -2640,14 +3613,38 @@ function parseAccount(data, idx) {
2640
3613
  warmupStartedAtSlot: readU64LE(data, base + warmupStartedOff),
2641
3614
  warmupSlopePerStep: readU128LE(data, base + warmupSlopeOff),
2642
3615
  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)),
3616
+ entryPrice: entryPriceOff >= 0 ? readU64LE(data, base + entryPriceOff) : 0n,
3617
+ // V12_1/V12_1_EP: funding_index not present in SBF layout
3618
+ fundingIndex: isV12_1 || isV12_1EP ? fundingIndexOff >= 0 ? BigInt(readI64LE(data, base + fundingIndexOff)) : 0n : readI128LE(data, base + fundingIndexOff),
3619
+ matcherProgram: new PublicKey5(data.subarray(base + matcherProgOff, base + matcherProgOff + 32)),
3620
+ matcherContext: new PublicKey5(data.subarray(base + matcherCtxOff, base + matcherCtxOff + 32)),
3621
+ owner: new PublicKey5(data.subarray(base + layout.acctOwnerOff, base + layout.acctOwnerOff + 32)),
2649
3622
  feeCredits: readI128LE(data, base + feeCreditsOff),
2650
- lastFeeSlot: readU64LE(data, base + lastFeeSlotOff)
3623
+ lastFeeSlot: readU64LE(data, base + lastFeeSlotOff),
3624
+ feesEarnedTotal: 0n,
3625
+ // not present in pre-v12.15 layouts
3626
+ exactReserveCohorts: null,
3627
+ // not present in pre-v12.15 layouts
3628
+ exactCohortCount: null,
3629
+ overflowOlder: null,
3630
+ overflowOlderPresent: null,
3631
+ overflowNewest: null,
3632
+ overflowNewestPresent: null,
3633
+ // v12.17 fields (not present in pre-v12.17)
3634
+ fSnap: 0n,
3635
+ adlABasis: 0n,
3636
+ adlKSnap: 0n,
3637
+ adlEpochSnap: 0n,
3638
+ schedPresent: null,
3639
+ schedRemainingQ: null,
3640
+ schedAnchorQ: null,
3641
+ schedStartSlot: null,
3642
+ schedHorizon: null,
3643
+ schedReleaseQ: null,
3644
+ pendingPresent: null,
3645
+ pendingRemainingQ: null,
3646
+ pendingHorizon: null,
3647
+ pendingCreatedSlot: null
2651
3648
  };
2652
3649
  }
2653
3650
  function parseAllAccounts(data) {
@@ -2667,14 +3664,20 @@ function parseAllAccounts(data) {
2667
3664
  }
2668
3665
 
2669
3666
  // src/solana/pda.ts
2670
- import { PublicKey as PublicKey4 } from "@solana/web3.js";
3667
+ import { PublicKey as PublicKey6 } from "@solana/web3.js";
2671
3668
  var textEncoder = new TextEncoder();
2672
3669
  function deriveVaultAuthority(programId, slab) {
2673
- return PublicKey4.findProgramAddressSync(
3670
+ return PublicKey6.findProgramAddressSync(
2674
3671
  [textEncoder.encode("vault"), slab.toBytes()],
2675
3672
  programId
2676
3673
  );
2677
3674
  }
3675
+ function deriveInsuranceLpMint(programId, slab) {
3676
+ return PublicKey6.findProgramAddressSync(
3677
+ [textEncoder.encode("ins_lp"), slab.toBytes()],
3678
+ programId
3679
+ );
3680
+ }
2678
3681
  var LP_INDEX_U16_MAX = 65535;
2679
3682
  function deriveLpPda(programId, slab, lpIdx) {
2680
3683
  if (typeof lpIdx !== "number" || !Number.isInteger(lpIdx) || lpIdx < 0 || lpIdx > LP_INDEX_U16_MAX) {
@@ -2682,34 +3685,28 @@ function deriveLpPda(programId, slab, lpIdx) {
2682
3685
  `deriveLpPda: lpIdx must be an integer in [0, ${LP_INDEX_U16_MAX}], got ${lpIdx}`
2683
3686
  );
2684
3687
  }
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],
3688
+ const idxBuf2 = new Uint8Array(2);
3689
+ new DataView(idxBuf2.buffer).setUint16(0, lpIdx, true);
3690
+ return PublicKey6.findProgramAddressSync(
3691
+ [textEncoder.encode("lp"), slab.toBytes(), idxBuf2],
2689
3692
  programId
2690
3693
  );
2691
3694
  }
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(
3695
+ var PUMPSWAP_PROGRAM_ID = new PublicKey6(
2699
3696
  "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA"
2700
3697
  );
2701
- var RAYDIUM_CLMM_PROGRAM_ID = new PublicKey4(
3698
+ var RAYDIUM_CLMM_PROGRAM_ID = new PublicKey6(
2702
3699
  "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK"
2703
3700
  );
2704
- var METEORA_DLMM_PROGRAM_ID = new PublicKey4(
3701
+ var METEORA_DLMM_PROGRAM_ID = new PublicKey6(
2705
3702
  "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo"
2706
3703
  );
2707
- var PYTH_PUSH_ORACLE_PROGRAM_ID = new PublicKey4(
3704
+ var PYTH_PUSH_ORACLE_PROGRAM_ID = new PublicKey6(
2708
3705
  "pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT"
2709
3706
  );
2710
3707
  var CREATOR_LOCK_SEED = "creator_lock";
2711
3708
  function deriveCreatorLockPda(programId, slab) {
2712
- return PublicKey4.findProgramAddressSync(
3709
+ return PublicKey6.findProgramAddressSync(
2713
3710
  [textEncoder.encode(CREATOR_LOCK_SEED), slab.toBytes()],
2714
3711
  programId
2715
3712
  );
@@ -2731,17 +3728,10 @@ function derivePythPushOraclePDA(feedIdHex) {
2731
3728
  }
2732
3729
  const feedId = new Uint8Array(32);
2733
3730
  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;
3731
+ feedId[i] = parseInt(normalized.substring(i * 2, i * 2 + 2), 16);
2742
3732
  }
2743
3733
  const shardBuf = new Uint8Array(2);
2744
- return PublicKey4.findProgramAddressSync(
3734
+ return PublicKey6.findProgramAddressSync(
2745
3735
  [shardBuf, feedId],
2746
3736
  PYTH_PUSH_ORACLE_PROGRAM_ID
2747
3737
  );
@@ -2765,14 +3755,12 @@ async function fetchTokenAccount(connection, address, tokenProgramId = TOKEN_PRO
2765
3755
  }
2766
3756
 
2767
3757
  // src/solana/discovery.ts
2768
- import { PublicKey as PublicKey6 } from "@solana/web3.js";
3758
+ import { PublicKey as PublicKey8 } from "@solana/web3.js";
2769
3759
 
2770
3760
  // src/solana/static-markets.ts
2771
- import { PublicKey as PublicKey5 } from "@solana/web3.js";
3761
+ import { PublicKey as PublicKey7 } from "@solana/web3.js";
2772
3762
  var MAINNET_MARKETS = [
2773
- // Populated at mainnet launch currently empty.
2774
- // To add entries:
2775
- // { slabAddress: "ABC123...", symbol: "SOL-PERP", name: "SOL Perpetual" },
3763
+ { slabAddress: "7psyeWRts4pRX2cyAWD1NH87bR9ugXP7pe6ARgfG79Do", symbol: "SOL-PERP", name: "SOL/USDC Perpetual" }
2776
3764
  ];
2777
3765
  var DEVNET_MARKETS = [
2778
3766
  // Populated from prior discoverMarkets() runs on devnet.
@@ -2806,7 +3794,7 @@ function registerStaticMarkets(network, entries) {
2806
3794
  if (!entry.slabAddress) continue;
2807
3795
  if (seen.has(entry.slabAddress)) continue;
2808
3796
  try {
2809
- new PublicKey5(entry.slabAddress);
3797
+ new PublicKey7(entry.slabAddress);
2810
3798
  } catch {
2811
3799
  console.warn(
2812
3800
  `[registerStaticMarkets] Skipping invalid slabAddress: ${entry.slabAddress}`
@@ -2830,10 +3818,9 @@ function clearStaticMarkets(network) {
2830
3818
  var ENGINE_BITMAP_OFF_V0 = 320;
2831
3819
  var MAGIC_BYTES = new Uint8Array([84, 65, 76, 79, 67, 82, 69, 80]);
2832
3820
  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"]
3821
+ small: SLAB_TIERS_V12_17["small"],
3822
+ medium: SLAB_TIERS_V12_17["medium"],
3823
+ large: SLAB_TIERS_V12_17["large"]
2837
3824
  };
2838
3825
  var SLAB_TIERS_V0 = {
2839
3826
  small: { maxAccounts: 256, dataSize: 62808, label: "Small", description: "256 slots \xB7 ~0.44 SOL" },
@@ -2940,6 +3927,8 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
2940
3927
  fundingIndexQpbE6: readI128LE2(data, base + 112),
2941
3928
  lastFundingSlot: readU64LE2(data, base + 128),
2942
3929
  fundingRateBpsPerSlotLast: readI64LE2(data, base + 136),
3930
+ fundingRateE9: 0n,
3931
+ marketMode: null,
2943
3932
  lastCrankSlot: readU64LE2(data, base + 144),
2944
3933
  maxCrankStalenessSlots: readU64LE2(data, base + 152),
2945
3934
  totalOpenInterest: readU128LE2(data, base + 160),
@@ -2947,6 +3936,7 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
2947
3936
  shortOi: 0n,
2948
3937
  cTot: readU128LE2(data, base + 176),
2949
3938
  pnlPosTot: readU128LE2(data, base + 192),
3939
+ pnlMaturedPosTot: 0n,
2950
3940
  liqCursor: readU16LE2(data, base + 208),
2951
3941
  gcCursor: readU16LE2(data, base + 210),
2952
3942
  lastSweepStartSlot: readU64LE2(data, base + 216),
@@ -2964,6 +3954,14 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
2964
3954
  lastBreakerSlot: 0n,
2965
3955
  markPriceE6: 0n,
2966
3956
  // V0 engine has no mark_price field
3957
+ oraclePriceE6: 0n,
3958
+ fLongNum: 0n,
3959
+ fShortNum: 0n,
3960
+ negPnlAccountCount: 0n,
3961
+ fundPxLast: 0n,
3962
+ resolvedKLongTerminalDelta: 0n,
3963
+ resolvedKShortTerminalDelta: 0n,
3964
+ resolvedLivePrice: 0n,
2967
3965
  numUsedAccounts: canReadNumUsed ? readU16LE2(data, base + numUsedOff) : 0,
2968
3966
  nextAccountId: canReadNextId ? readU64LE2(data, base + nextAccountIdOff) : 0n
2969
3967
  };
@@ -2982,6 +3980,8 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
2982
3980
  fundingIndexQpbE6: readI128LE2(data, base + 360),
2983
3981
  lastFundingSlot: readU64LE2(data, base + 376),
2984
3982
  fundingRateBpsPerSlotLast: readI64LE2(data, base + 384),
3983
+ fundingRateE9: 0n,
3984
+ marketMode: null,
2985
3985
  lastCrankSlot: readU64LE2(data, base + 392),
2986
3986
  maxCrankStalenessSlots: readU64LE2(data, base + 400),
2987
3987
  totalOpenInterest: readU128LE2(data, base + 408),
@@ -2991,6 +3991,7 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
2991
3991
  // V2 has no short_oi
2992
3992
  cTot: readU128LE2(data, base + 424),
2993
3993
  pnlPosTot: readU128LE2(data, base + 440),
3994
+ pnlMaturedPosTot: 0n,
2994
3995
  liqCursor: readU16LE2(data, base + 456),
2995
3996
  gcCursor: readU16LE2(data, base + 458),
2996
3997
  lastSweepStartSlot: readU64LE2(data, base + 464),
@@ -3009,6 +4010,14 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3009
4010
  lastBreakerSlot: 0n,
3010
4011
  markPriceE6: 0n,
3011
4012
  // V2 has no mark_price
4013
+ oraclePriceE6: 0n,
4014
+ fLongNum: 0n,
4015
+ fShortNum: 0n,
4016
+ negPnlAccountCount: 0n,
4017
+ fundPxLast: 0n,
4018
+ resolvedKLongTerminalDelta: 0n,
4019
+ resolvedKShortTerminalDelta: 0n,
4020
+ resolvedLivePrice: 0n,
3012
4021
  numUsedAccounts: canReadNumUsed ? readU16LE2(data, base + numUsedOff) : 0,
3013
4022
  nextAccountId: canReadNextId ? readU64LE2(data, base + nextAccountIdOff) : 0n
3014
4023
  };
@@ -3028,6 +4037,8 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3028
4037
  fundingIndexQpbE6: readI128LE2(data, base + l.engineFundingIndexOff),
3029
4038
  lastFundingSlot: readU64LE2(data, base + l.engineLastFundingSlotOff),
3030
4039
  fundingRateBpsPerSlotLast: readI64LE2(data, base + l.engineFundingRateBpsOff),
4040
+ fundingRateE9: 0n,
4041
+ marketMode: null,
3031
4042
  lastCrankSlot: readU64LE2(data, base + l.engineLastCrankSlotOff),
3032
4043
  maxCrankStalenessSlots: readU64LE2(data, base + l.engineMaxCrankStalenessOff),
3033
4044
  totalOpenInterest: readU128LE2(data, base + l.engineTotalOiOff),
@@ -3035,6 +4046,7 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3035
4046
  shortOi: l.engineShortOiOff >= 0 ? readU128LE2(data, base + l.engineShortOiOff) : 0n,
3036
4047
  cTot: readU128LE2(data, base + l.engineCTotOff),
3037
4048
  pnlPosTot: readU128LE2(data, base + l.enginePnlPosTotOff),
4049
+ pnlMaturedPosTot: 0n,
3038
4050
  liqCursor: readU16LE2(data, base + l.engineLiqCursorOff),
3039
4051
  gcCursor: readU16LE2(data, base + l.engineGcCursorOff),
3040
4052
  lastSweepStartSlot: readU64LE2(data, base + l.engineLastSweepStartOff),
@@ -3051,6 +4063,14 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3051
4063
  emergencyStartSlot: l.engineEmergencyStartSlotOff >= 0 ? readU64LE2(data, base + l.engineEmergencyStartSlotOff) : 0n,
3052
4064
  lastBreakerSlot: l.engineLastBreakerSlotOff >= 0 ? readU64LE2(data, base + l.engineLastBreakerSlotOff) : 0n,
3053
4065
  markPriceE6: l.engineMarkPriceOff >= 0 ? readU64LE2(data, base + l.engineMarkPriceOff) : 0n,
4066
+ oraclePriceE6: 0n,
4067
+ fLongNum: 0n,
4068
+ fShortNum: 0n,
4069
+ negPnlAccountCount: 0n,
4070
+ fundPxLast: 0n,
4071
+ resolvedKLongTerminalDelta: 0n,
4072
+ resolvedKShortTerminalDelta: 0n,
4073
+ resolvedLivePrice: 0n,
3054
4074
  numUsedAccounts: canReadNumUsed ? readU16LE2(data, base + numUsedOff) : 0,
3055
4075
  nextAccountId: canReadNextId ? readU64LE2(data, base + nextAccountIdOff) : 0n
3056
4076
  };
@@ -3068,6 +4088,8 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3068
4088
  fundingIndexQpbE6: readI128LE2(data, base + 368),
3069
4089
  lastFundingSlot: readU64LE2(data, base + 384),
3070
4090
  fundingRateBpsPerSlotLast: readI64LE2(data, base + 392),
4091
+ fundingRateE9: 0n,
4092
+ marketMode: null,
3071
4093
  lastCrankSlot: readU64LE2(data, base + 424),
3072
4094
  maxCrankStalenessSlots: readU64LE2(data, base + 408),
3073
4095
  totalOpenInterest: readU128LE2(data, base + 416),
@@ -3075,6 +4097,7 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3075
4097
  shortOi: readU128LE2(data, base + 448),
3076
4098
  cTot: readU128LE2(data, base + 464),
3077
4099
  pnlPosTot: readU128LE2(data, base + 480),
4100
+ pnlMaturedPosTot: 0n,
3078
4101
  liqCursor: readU16LE2(data, base + 496),
3079
4102
  gcCursor: readU16LE2(data, base + 498),
3080
4103
  lastSweepStartSlot: readU64LE2(data, base + 504),
@@ -3092,6 +4115,14 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3092
4115
  lastBreakerSlot: readU64LE2(data, base + 624),
3093
4116
  markPriceE6: readU64LE2(data, base + 400),
3094
4117
  // PERC-1094: was 392
4118
+ oraclePriceE6: 0n,
4119
+ fLongNum: 0n,
4120
+ fShortNum: 0n,
4121
+ negPnlAccountCount: 0n,
4122
+ fundPxLast: 0n,
4123
+ resolvedKLongTerminalDelta: 0n,
4124
+ resolvedKShortTerminalDelta: 0n,
4125
+ resolvedLivePrice: 0n,
3095
4126
  numUsedAccounts: canReadNumUsed ? readU16LE2(data, base + numUsedOff) : 0,
3096
4127
  nextAccountId: canReadNextId ? readU64LE2(data, base + nextAccountIdOff) : 0n
3097
4128
  };
@@ -3113,12 +4144,19 @@ async function discoverMarkets(connection, programId, options = {}) {
3113
4144
  } = options;
3114
4145
  const ALL_TIERS = [
3115
4146
  ...Object.values(SLAB_TIERS),
4147
+ // v12.17 (default)
4148
+ ...Object.values(SLAB_TIERS_V12_15),
4149
+ // v12.15
4150
+ ...Object.values(SLAB_TIERS_V12_1),
4151
+ // v12.1
3116
4152
  ...Object.values(SLAB_TIERS_V0),
3117
4153
  ...Object.values(SLAB_TIERS_V1D),
3118
4154
  ...Object.values(SLAB_TIERS_V1D_LEGACY),
3119
4155
  ...Object.values(SLAB_TIERS_V2),
3120
4156
  ...Object.values(SLAB_TIERS_V1M),
3121
- ...Object.values(SLAB_TIERS_V_ADL)
4157
+ ...Object.values(SLAB_TIERS_V1M2),
4158
+ ...Object.values(SLAB_TIERS_V_ADL),
4159
+ ...Object.values(SLAB_TIERS_V_SETDEXPOOL)
3122
4160
  ];
3123
4161
  let rawAccounts = [];
3124
4162
  async function fetchTierWithRetry(tier) {
@@ -3416,7 +4454,7 @@ async function discoverMarketsViaApi(connection, programId, apiBaseUrl, options
3416
4454
  for (const entry of apiMarkets) {
3417
4455
  if (!entry.slab_address || typeof entry.slab_address !== "string") continue;
3418
4456
  try {
3419
- addresses.push(new PublicKey6(entry.slab_address));
4457
+ addresses.push(new PublicKey8(entry.slab_address));
3420
4458
  } catch {
3421
4459
  console.warn(
3422
4460
  `[discoverMarketsViaApi] Skipping invalid slab address: ${entry.slab_address}`
@@ -3438,7 +4476,7 @@ async function discoverMarketsViaStaticBundle(connection, programId, entries, op
3438
4476
  for (const entry of entries) {
3439
4477
  if (!entry.slabAddress || typeof entry.slabAddress !== "string") continue;
3440
4478
  try {
3441
- addresses.push(new PublicKey6(entry.slabAddress));
4479
+ addresses.push(new PublicKey8(entry.slabAddress));
3442
4480
  } catch {
3443
4481
  console.warn(
3444
4482
  `[discoverMarketsViaStaticBundle] Skipping invalid slab address: ${entry.slabAddress}`
@@ -3456,7 +4494,7 @@ async function discoverMarketsViaStaticBundle(connection, programId, entries, op
3456
4494
  }
3457
4495
 
3458
4496
  // src/solana/dex-oracle.ts
3459
- import { PublicKey as PublicKey7 } from "@solana/web3.js";
4497
+ import { PublicKey as PublicKey9 } from "@solana/web3.js";
3460
4498
  function detectDexType(ownerProgramId) {
3461
4499
  if (ownerProgramId.equals(PUMPSWAP_PROGRAM_ID)) return "pumpswap";
3462
4500
  if (ownerProgramId.equals(RAYDIUM_CLMM_PROGRAM_ID)) return "raydium-clmm";
@@ -3492,10 +4530,10 @@ function parsePumpSwapPool(poolAddress, data) {
3492
4530
  return {
3493
4531
  dexType: "pumpswap",
3494
4532
  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))
4533
+ baseMint: new PublicKey9(data.slice(35, 67)),
4534
+ quoteMint: new PublicKey9(data.slice(67, 99)),
4535
+ baseVault: new PublicKey9(data.slice(131, 163)),
4536
+ quoteVault: new PublicKey9(data.slice(163, 195))
3499
4537
  };
3500
4538
  }
3501
4539
  var SPL_TOKEN_AMOUNT_MIN_LEN = 72;
@@ -3521,8 +4559,8 @@ function parseRaydiumClmmPool(poolAddress, data) {
3521
4559
  return {
3522
4560
  dexType: "raydium-clmm",
3523
4561
  poolAddress,
3524
- baseMint: new PublicKey7(data.slice(73, 105)),
3525
- quoteMint: new PublicKey7(data.slice(105, 137))
4562
+ baseMint: new PublicKey9(data.slice(73, 105)),
4563
+ quoteMint: new PublicKey9(data.slice(105, 137))
3526
4564
  };
3527
4565
  }
3528
4566
  var MAX_TOKEN_DECIMALS = 24;
@@ -3540,7 +4578,9 @@ function computeRaydiumClmmPriceE6(data) {
3540
4578
  }
3541
4579
  const sqrtPriceX64 = readU128LE3(dv3, 253);
3542
4580
  if (sqrtPriceX64 === 0n) return 0n;
3543
- const priceE6Raw = sqrtPriceX64 * sqrtPriceX64 * 1000000n >> 128n;
4581
+ const scaledSqrt = sqrtPriceX64 * 1000000n;
4582
+ const term = scaledSqrt >> 64n;
4583
+ const priceE6Raw = term * sqrtPriceX64 >> 64n;
3544
4584
  const decimalDiff = 6 + decimals0 - decimals1;
3545
4585
  const adjustedDiff = decimalDiff - 6;
3546
4586
  if (adjustedDiff >= 0) {
@@ -3559,8 +4599,8 @@ function parseMeteoraPool(poolAddress, data) {
3559
4599
  return {
3560
4600
  dexType: "meteora-dlmm",
3561
4601
  poolAddress,
3562
- baseMint: new PublicKey7(data.slice(81, 113)),
3563
- quoteMint: new PublicKey7(data.slice(113, 145))
4602
+ baseMint: new PublicKey9(data.slice(81, 113)),
4603
+ quoteMint: new PublicKey9(data.slice(113, 145))
3564
4604
  };
3565
4605
  }
3566
4606
  var MAX_BIN_STEP = 1e4;
@@ -3581,26 +4621,13 @@ function computeMeteoraDlmmPriceE6(data) {
3581
4621
  `Meteora DLMM: |activeId| ${Math.abs(activeId)} exceeds max ${MAX_ACTIVE_ID_ABS}`
3582
4622
  );
3583
4623
  }
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
4624
  const SCALE = 1000000000000000000n;
3591
4625
  const base = SCALE + BigInt(binStep) * SCALE / 10000n;
3592
4626
  const isNeg = activeId < 0;
3593
4627
  let exp = isNeg ? BigInt(-activeId) : BigInt(activeId);
3594
4628
  let result = SCALE;
3595
4629
  let b = base;
3596
- let iterations = 0;
3597
- const MAX_ITERATIONS = 25;
3598
4630
  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
4631
  if (exp & 1n) {
3605
4632
  result = result * b / SCALE;
3606
4633
  }
@@ -3631,7 +4658,6 @@ function readU128LE3(dv3, offset) {
3631
4658
  var CHAINLINK_MIN_SIZE = 224;
3632
4659
  var MAX_DECIMALS = 18;
3633
4660
  var CHAINLINK_DECIMALS_OFFSET = 138;
3634
- var CHAINLINK_TIMESTAMP_OFFSET = 168;
3635
4661
  var CHAINLINK_ANSWER_OFFSET = 216;
3636
4662
  function readU82(data, off) {
3637
4663
  return data[off];
@@ -3639,7 +4665,7 @@ function readU82(data, off) {
3639
4665
  function readBigInt64LE(data, off) {
3640
4666
  return new DataView(data.buffer, data.byteOffset, data.byteLength).getBigInt64(off, true);
3641
4667
  }
3642
- function parseChainlinkPrice(data, options) {
4668
+ function parseChainlinkPrice(data) {
3643
4669
  if (data.length < CHAINLINK_MIN_SIZE) {
3644
4670
  throw new Error(
3645
4671
  `Oracle account data too small: ${data.length} bytes (need at least ${CHAINLINK_MIN_SIZE})`
@@ -3657,18 +4683,7 @@ function parseChainlinkPrice(data, options) {
3657
4683
  `Oracle price is non-positive: ${price}`
3658
4684
  );
3659
4685
  }
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 };
4686
+ return { price, decimals };
3672
4687
  }
3673
4688
  function isValidChainlinkOracle(data) {
3674
4689
  try {
@@ -3680,19 +4695,15 @@ function isValidChainlinkOracle(data) {
3680
4695
  }
3681
4696
 
3682
4697
  // src/solana/token-program.ts
3683
- import { PublicKey as PublicKey8 } from "@solana/web3.js";
4698
+ import { PublicKey as PublicKey10 } from "@solana/web3.js";
3684
4699
  import { TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID3 } from "@solana/spl-token";
3685
- var TOKEN_2022_PROGRAM_ID = new PublicKey8(
4700
+ var TOKEN_2022_PROGRAM_ID = new PublicKey10(
3686
4701
  "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
3687
4702
  );
3688
4703
  async function detectTokenProgram(connection, mint) {
3689
4704
  const info = await connection.getAccountInfo(mint);
3690
4705
  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
- );
4706
+ return info.owner;
3696
4707
  }
3697
4708
  function isToken2022(tokenProgramId) {
3698
4709
  return tokenProgramId.equals(TOKEN_2022_PROGRAM_ID);
@@ -3702,74 +4713,11 @@ function isStandardToken(tokenProgramId) {
3702
4713
  }
3703
4714
 
3704
4715
  // 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";
4716
+ 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
4717
  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
4718
  var STAKE_PROGRAM_IDS = {
3770
4719
  devnet: "6aJb1F9CDCVWCNYFwj8aQsVb696YnW6J1FznteHq4Q6k",
3771
- mainnet: ""
3772
- // TODO: populate once DevOps deploys percolator-stake to mainnet
4720
+ mainnet: "DC5fovFQD5SZYsetwvEqd4Wi4PFY1Yfnc669VMe6oa7F"
3773
4721
  };
3774
4722
  function getStakeProgramId(network) {
3775
4723
  const override = safeEnv("STAKE_PROGRAM_ID");
@@ -3777,11 +4725,14 @@ function getStakeProgramId(network) {
3777
4725
  console.warn(
3778
4726
  `[percolator-sdk] STAKE_PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
3779
4727
  );
3780
- return new PublicKey10(override);
4728
+ return new PublicKey11(override);
3781
4729
  }
3782
4730
  const detectedNetwork = network ?? (() => {
3783
4731
  const n = safeEnv("NEXT_PUBLIC_DEFAULT_NETWORK")?.toLowerCase() ?? safeEnv("NETWORK")?.toLowerCase() ?? "";
3784
- return n === "mainnet" || n === "mainnet-beta" ? "mainnet" : "devnet";
4732
+ if (n === "mainnet" || n === "mainnet-beta") return "mainnet";
4733
+ if (n === "devnet") return "devnet";
4734
+ if (typeof window !== "undefined") return "mainnet";
4735
+ return "devnet";
3785
4736
  })();
3786
4737
  const id = STAKE_PROGRAM_IDS[detectedNetwork];
3787
4738
  if (!id) {
@@ -3789,9 +4740,9 @@ function getStakeProgramId(network) {
3789
4740
  `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
4741
  );
3791
4742
  }
3792
- return new PublicKey10(id);
4743
+ return new PublicKey11(id);
3793
4744
  }
3794
- var STAKE_PROGRAM_ID = new PublicKey10(STAKE_PROGRAM_IDS.devnet);
4745
+ var STAKE_PROGRAM_ID = new PublicKey11(STAKE_PROGRAM_IDS.devnet);
3795
4746
  var STAKE_IX = {
3796
4747
  InitPool: 0,
3797
4748
  Deposit: 1,
@@ -3816,22 +4767,22 @@ var STAKE_IX = {
3816
4767
  /** PERC-303: Deposit into junior (first-loss) tranche */
3817
4768
  DepositJunior: 16
3818
4769
  };
3819
- var TEXT = new TextEncoder();
4770
+ var TEXT2 = new TextEncoder();
3820
4771
  function deriveStakePool(slab, programId) {
3821
- return PublicKey10.findProgramAddressSync(
3822
- [TEXT.encode("stake_pool"), slab.toBytes()],
4772
+ return PublicKey11.findProgramAddressSync(
4773
+ [TEXT2.encode("stake_pool"), slab.toBytes()],
3823
4774
  programId ?? getStakeProgramId()
3824
4775
  );
3825
4776
  }
3826
4777
  function deriveStakeVaultAuth(pool, programId) {
3827
- return PublicKey10.findProgramAddressSync(
3828
- [TEXT.encode("vault_auth"), pool.toBytes()],
4778
+ return PublicKey11.findProgramAddressSync(
4779
+ [TEXT2.encode("vault_auth"), pool.toBytes()],
3829
4780
  programId ?? getStakeProgramId()
3830
4781
  );
3831
4782
  }
3832
4783
  function deriveDepositPda(pool, user, programId) {
3833
- return PublicKey10.findProgramAddressSync(
3834
- [TEXT.encode("deposit"), pool.toBytes(), user.toBytes()],
4784
+ return PublicKey11.findProgramAddressSync(
4785
+ [TEXT2.encode("stake_deposit"), pool.toBytes(), user.toBytes()],
3835
4786
  programId ?? getStakeProgramId()
3836
4787
  );
3837
4788
  }
@@ -3852,9 +4803,6 @@ function readU16LE3(data, off) {
3852
4803
  );
3853
4804
  }
3854
4805
  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
4806
  const big = BigInt(v);
3859
4807
  if (big < 0n) throw new Error(`u64Le: value must be non-negative, got ${big}`);
3860
4808
  if (big > 0xFFFFFFFFFFFFFFFFn) throw new Error(`u64Le: value exceeds u64 max`);
@@ -3863,9 +4811,6 @@ function u64Le(v) {
3863
4811
  return arr;
3864
4812
  }
3865
4813
  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
4814
  const big = BigInt(v);
3870
4815
  if (big < 0n) throw new Error(`u128Le: value must be non-negative, got ${big}`);
3871
4816
  if (big > (1n << 128n) - 1n) throw new Error(`u128Le: value exceeds u128 max`);
@@ -3876,7 +4821,7 @@ function u128Le(v) {
3876
4821
  return arr;
3877
4822
  }
3878
4823
  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}`);
4824
+ if (v < 0 || v > 65535) throw new Error(`u16Le: value out of u16 range (0..65535), got ${v}`);
3880
4825
  const arr = new Uint8Array(2);
3881
4826
  new DataView(arr.buffer).setUint16(0, v, true);
3882
4827
  return arr;
@@ -3987,15 +4932,15 @@ function decodeStakePool(data) {
3987
4932
  const adminTransferred = bytes[off] === 1;
3988
4933
  off += 1;
3989
4934
  off += 4;
3990
- const slab = new PublicKey10(bytes.subarray(off, off + 32));
4935
+ const slab = new PublicKey11(bytes.subarray(off, off + 32));
3991
4936
  off += 32;
3992
- const admin = new PublicKey10(bytes.subarray(off, off + 32));
4937
+ const admin = new PublicKey11(bytes.subarray(off, off + 32));
3993
4938
  off += 32;
3994
- const collateralMint = new PublicKey10(bytes.subarray(off, off + 32));
4939
+ const collateralMint = new PublicKey11(bytes.subarray(off, off + 32));
3995
4940
  off += 32;
3996
- const lpMint = new PublicKey10(bytes.subarray(off, off + 32));
4941
+ const lpMint = new PublicKey11(bytes.subarray(off, off + 32));
3997
4942
  off += 32;
3998
- const vault = new PublicKey10(bytes.subarray(off, off + 32));
4943
+ const vault = new PublicKey11(bytes.subarray(off, off + 32));
3999
4944
  off += 32;
4000
4945
  const totalDeposited = readU64LE4(bytes, off);
4001
4946
  off += 8;
@@ -4011,7 +4956,7 @@ function decodeStakePool(data) {
4011
4956
  off += 8;
4012
4957
  const totalWithdrawn = readU64LE4(bytes, off);
4013
4958
  off += 8;
4014
- const percolatorProgram = new PublicKey10(bytes.subarray(off, off + 32));
4959
+ const percolatorProgram = new PublicKey11(bytes.subarray(off, off + 32));
4015
4960
  off += 32;
4016
4961
  const totalFeesEarned = readU64LE4(bytes, off);
4017
4962
  off += 8;
@@ -4063,6 +5008,20 @@ function decodeStakePool(data) {
4063
5008
  juniorFeeMultBps
4064
5009
  };
4065
5010
  }
5011
+ var STAKE_DEPOSIT_SIZE = 152;
5012
+ function decodeDepositPda(data) {
5013
+ if (data.length < STAKE_DEPOSIT_SIZE) {
5014
+ throw new Error(`StakeDeposit data too short: ${data.length} < ${STAKE_DEPOSIT_SIZE}`);
5015
+ }
5016
+ return {
5017
+ isInitialized: data[0] === 1,
5018
+ bump: data[1],
5019
+ pool: new PublicKey11(data.subarray(8, 40)),
5020
+ user: new PublicKey11(data.subarray(40, 72)),
5021
+ lastDepositSlot: readU64LE4(data, 72),
5022
+ lpAmount: readU64LE4(data, 80)
5023
+ };
5024
+ }
4066
5025
  function initPoolAccounts(a) {
4067
5026
  return [
4068
5027
  { pubkey: a.admin, isSigner: true, isWritable: true },
@@ -4131,9 +5090,7 @@ function computePnlPct(pnl, capital) {
4131
5090
  }
4132
5091
  function isAdlTriggered(slabData) {
4133
5092
  const layout = detectSlabLayout(slabData.length);
4134
- if (!layout) {
4135
- return false;
4136
- }
5093
+ if (!layout) return false;
4137
5094
  try {
4138
5095
  const engine = parseEngine(slabData);
4139
5096
  if (engine.pnlPosTot === 0n) return false;
@@ -4176,14 +5133,6 @@ function rankAdlPositions(slabData) {
4176
5133
  if (account.kind !== 0 /* User */) continue;
4177
5134
  if (account.positionSize === 0n) continue;
4178
5135
  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
5136
  const pnlPct = computePnlPct(account.pnl, account.capital);
4188
5137
  positions.push({
4189
5138
  idx,
@@ -4216,8 +5165,7 @@ function buildAdlInstruction(caller, slab, oracle, programId, targetIdx, backupO
4216
5165
  `buildAdlInstruction: targetIdx must be a non-negative integer, got ${targetIdx}`
4217
5166
  );
4218
5167
  }
4219
- const dataBytes = encodeExecuteAdl({ targetIdx });
4220
- const data = Buffer.from(dataBytes);
5168
+ const data = Buffer.from(encodeExecuteAdl({ targetIdx }));
4221
5169
  const keys = [
4222
5170
  { pubkey: caller, isSigner: true, isWritable: false },
4223
5171
  { pubkey: slab, isSigner: false, isWritable: true },
@@ -4257,11 +5205,7 @@ function parseAdlEvent(logs) {
4257
5205
  }
4258
5206
  if (tag !== ADL_EVENT_TAG) continue;
4259
5207
  try {
4260
- const targetIdxBig = BigInt(match[2]);
4261
- if (targetIdxBig < 0n || targetIdxBig > 65535n) {
4262
- continue;
4263
- }
4264
- const targetIdx = Number(targetIdxBig);
5208
+ const targetIdx = Number(BigInt(match[2]));
4265
5209
  const price = BigInt(match[3]);
4266
5210
  const closedLo = BigInt(match[4]);
4267
5211
  const closedHi = BigInt(match[5]);
@@ -4289,22 +5233,6 @@ async function fetchAdlRankings(apiBase, slab, fetchFn = fetch) {
4289
5233
  );
4290
5234
  }
4291
5235
  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
5236
  return json;
4309
5237
  }
4310
5238
 
@@ -4822,11 +5750,11 @@ function formatResult(result, jsonMode) {
4822
5750
  }
4823
5751
 
4824
5752
  // src/runtime/lighthouse.ts
4825
- import { PublicKey as PublicKey13, Transaction as Transaction2 } from "@solana/web3.js";
4826
- var LIGHTHOUSE_PROGRAM_ID = new PublicKey13(
5753
+ import { PublicKey as PublicKey14, Transaction as Transaction2 } from "@solana/web3.js";
5754
+ var LIGHTHOUSE_PROGRAM_ID = new PublicKey14(
4827
5755
  "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95"
4828
5756
  );
4829
- var LIGHTHOUSE_PROGRAM_ID_STR2 = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
5757
+ var LIGHTHOUSE_PROGRAM_ID_STR = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
4830
5758
  var LIGHTHOUSE_CONSTRAINT_ADDRESS = 6400;
4831
5759
  var LIGHTHOUSE_ERROR_CODES = /* @__PURE__ */ new Set([
4832
5760
  6e3,
@@ -4872,7 +5800,7 @@ function isLighthouseInstruction(ix) {
4872
5800
  function isLighthouseError(error) {
4873
5801
  const msg = extractErrorMessage(error);
4874
5802
  if (!msg) return false;
4875
- if (msg.includes(LIGHTHOUSE_PROGRAM_ID_STR2)) return true;
5803
+ if (msg.includes(LIGHTHOUSE_PROGRAM_ID_STR)) return true;
4876
5804
  if (/custom\s+program\s+error:\s*0x1900\b/i.test(msg)) return true;
4877
5805
  if (/"Custom"\s*:\s*6400\b/.test(msg) && /InstructionError/i.test(msg)) return true;
4878
5806
  return false;
@@ -4882,18 +5810,18 @@ function isLighthouseFailureInLogs(logs) {
4882
5810
  let insideLighthouse = false;
4883
5811
  for (const line of logs) {
4884
5812
  if (typeof line !== "string") continue;
4885
- if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} invoke`)) {
5813
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {
4886
5814
  insideLighthouse = true;
4887
5815
  continue;
4888
5816
  }
4889
- if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} success`)) {
5817
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {
4890
5818
  insideLighthouse = false;
4891
5819
  continue;
4892
5820
  }
4893
5821
  if (insideLighthouse && /failed/i.test(line)) {
4894
5822
  return true;
4895
5823
  }
4896
- if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} failed`)) {
5824
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} failed`)) {
4897
5825
  return true;
4898
5826
  }
4899
5827
  }
@@ -4978,10 +5906,16 @@ function computeLiqPrice(entryPrice, capital, positionSize, maintenanceMarginBps
4978
5906
  function computePreTradeLiqPrice(oracleE6, margin, posSize, maintBps, feeBps, direction) {
4979
5907
  if (oracleE6 === 0n || margin === 0n || posSize === 0n) return 0n;
4980
5908
  const absPos = posSize < 0n ? -posSize : posSize;
4981
- const fee = absPos * feeBps / 10000n;
4982
- const effectiveCapital = margin > fee ? margin - fee : 0n;
4983
5909
  const signedPos = direction === "long" ? absPos : -absPos;
4984
- return computeLiqPrice(oracleE6, effectiveCapital, signedPos, maintBps);
5910
+ const feeAdjust = oracleE6 * feeBps / 10000n;
5911
+ let adjustedEntry;
5912
+ if (direction === "long") {
5913
+ adjustedEntry = oracleE6 + feeAdjust;
5914
+ } else {
5915
+ const shortEntry = oracleE6 - feeAdjust;
5916
+ adjustedEntry = shortEntry > 0n ? shortEntry : 1n;
5917
+ }
5918
+ return computeLiqPrice(adjustedEntry, margin, signedPos, maintBps);
4985
5919
  }
4986
5920
  function computeTradingFee(notional, tradingFeeBps) {
4987
5921
  return notional * tradingFeeBps / 10000n;
@@ -5001,20 +5935,9 @@ function computeFeeSplit(totalFee, config) {
5001
5935
  if (config.lpBps === 0n && config.protocolBps === 0n && config.creatorBps === 0n) {
5002
5936
  return [totalFee, 0n, 0n];
5003
5937
  }
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
5938
  const lp = totalFee * config.lpBps / 10000n;
5011
5939
  const protocol = totalFee * config.protocolBps / 10000n;
5012
5940
  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
5941
  return [lp, protocol, creator];
5019
5942
  }
5020
5943
  function computePnlPercent(pnlTokens, capital) {
@@ -5029,17 +5952,10 @@ function computePnlPercent(pnlTokens, capital) {
5029
5952
  }
5030
5953
  function computeEstimatedEntryPrice(oracleE6, tradingFeeBps, direction) {
5031
5954
  if (oracleE6 === 0n) return 0n;
5032
- if (tradingFeeBps < 0n) {
5033
- throw new Error(`computeEstimatedEntryPrice: tradingFeeBps must be non-negative, got ${tradingFeeBps}`);
5034
- }
5035
5955
  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;
5956
+ if (direction === "long") return oracleE6 + feeImpact;
5957
+ const shortEntry = oracleE6 - feeImpact;
5958
+ return shortEntry > 0n ? shortEntry : 1n;
5043
5959
  }
5044
5960
  var MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
5045
5961
  var MIN_SAFE_BIGINT = BigInt(-Number.MAX_SAFE_INTEGER);
@@ -5060,12 +5976,7 @@ function computeMaxLeverage(initialMarginBps) {
5060
5976
  if (initialMarginBps <= 0n) {
5061
5977
  throw new Error("computeMaxLeverage: initialMarginBps must be positive");
5062
5978
  }
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);
5979
+ return Number(10000n / initialMarginBps);
5069
5980
  }
5070
5981
 
5071
5982
  // src/math/warmup.ts
@@ -5077,9 +5988,6 @@ function computeWarmupUnlockedCapital(totalCapital, currentSlot, warmupStartSlot
5077
5988
  return totalCapital * elapsed / warmupPeriodSlots;
5078
5989
  }
5079
5990
  function computeWarmupLeverageCap(initialMarginBps, totalCapital, currentSlot, warmupStartSlot, warmupPeriodSlots) {
5080
- if (initialMarginBps <= 0n) {
5081
- throw new Error("computeWarmupLeverageCap: initialMarginBps must be positive");
5082
- }
5083
5991
  const maxLev = computeMaxLeverage(initialMarginBps);
5084
5992
  if (warmupPeriodSlots === 0n || warmupStartSlot === 0n) return maxLev;
5085
5993
  if (totalCapital <= 0n) return 1;
@@ -5090,14 +5998,7 @@ function computeWarmupLeverageCap(initialMarginBps, totalCapital, currentSlot, w
5090
5998
  warmupPeriodSlots
5091
5999
  );
5092
6000
  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);
6001
+ const effectiveLev = Number(BigInt(maxLev) * unlocked / totalCapital);
5101
6002
  return Math.max(1, effectiveLev);
5102
6003
  }
5103
6004
  function computeWarmupMaxPositionSize(initialMarginBps, totalCapital, currentSlot, warmupStartSlot, warmupPeriodSlots) {
@@ -5110,41 +6011,10 @@ function computeWarmupMaxPositionSize(initialMarginBps, totalCapital, currentSlo
5110
6011
  );
5111
6012
  return unlocked * BigInt(maxLev);
5112
6013
  }
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
6014
 
5145
6015
  // src/validation.ts
5146
- import { PublicKey as PublicKey14 } from "@solana/web3.js";
5147
- var U16_MAX = 65535;
6016
+ import { PublicKey as PublicKey15 } from "@solana/web3.js";
6017
+ var U16_MAX2 = 65535;
5148
6018
  var U64_MAX = BigInt("18446744073709551615");
5149
6019
  var I64_MIN = BigInt("-9223372036854775808");
5150
6020
  var I64_MAX = BigInt("9223372036854775807");
@@ -5173,7 +6043,7 @@ var ValidationError = class extends Error {
5173
6043
  };
5174
6044
  function validatePublicKey(value, field) {
5175
6045
  try {
5176
- return new PublicKey14(value);
6046
+ return new PublicKey15(value);
5177
6047
  } catch {
5178
6048
  throw new ValidationError(
5179
6049
  field,
@@ -5184,26 +6054,24 @@ function validatePublicKey(value, field) {
5184
6054
  function validateIndex(value, field) {
5185
6055
  const t = requireDecimalUIntString(value, field);
5186
6056
  const bi = BigInt(t);
5187
- if (bi > BigInt(U16_MAX)) {
6057
+ if (bi > BigInt(U16_MAX2)) {
5188
6058
  throw new ValidationError(
5189
6059
  field,
5190
- `must be <= ${U16_MAX} (u16 max), got ${t}`
6060
+ `must be <= ${U16_MAX2} (u16 max), got ${t}`
5191
6061
  );
5192
6062
  }
5193
- if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5194
- throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);
5195
- }
5196
6063
  return Number(bi);
5197
6064
  }
5198
6065
  function validateAmount(value, field) {
5199
- const t = value.trim();
5200
- if (!/^(0|[1-9]\d*)$/.test(t)) {
6066
+ let num;
6067
+ try {
6068
+ num = BigInt(value);
6069
+ } catch {
5201
6070
  throw new ValidationError(
5202
6071
  field,
5203
- `"${value}" is not a valid non-negative integer. Use decimal digits only.`
6072
+ `"${value}" is not a valid number. Use decimal digits only.`
5204
6073
  );
5205
6074
  }
5206
- const num = BigInt(t);
5207
6075
  if (num < 0n) {
5208
6076
  throw new ValidationError(field, `must be non-negative, got ${num}`);
5209
6077
  }
@@ -5216,14 +6084,15 @@ function validateAmount(value, field) {
5216
6084
  return num;
5217
6085
  }
5218
6086
  function validateU128(value, field) {
5219
- const t = value.trim();
5220
- if (!/^(0|[1-9]\d*)$/.test(t)) {
6087
+ let num;
6088
+ try {
6089
+ num = BigInt(value);
6090
+ } catch {
5221
6091
  throw new ValidationError(
5222
6092
  field,
5223
- `"${value}" is not a valid non-negative integer. Use decimal digits only.`
6093
+ `"${value}" is not a valid number. Use decimal digits only.`
5224
6094
  );
5225
6095
  }
5226
- const num = BigInt(t);
5227
6096
  if (num < 0n) {
5228
6097
  throw new ValidationError(field, `must be non-negative, got ${num}`);
5229
6098
  }
@@ -5236,14 +6105,15 @@ function validateU128(value, field) {
5236
6105
  return num;
5237
6106
  }
5238
6107
  function validateI64(value, field) {
5239
- const t = value.trim();
5240
- if (!/^-?(0|[1-9]\d*)$/.test(t)) {
6108
+ let num;
6109
+ try {
6110
+ num = BigInt(value);
6111
+ } catch {
5241
6112
  throw new ValidationError(
5242
6113
  field,
5243
- `"${value}" is not a valid integer. Use decimal digits only, with optional leading minus.`
6114
+ `"${value}" is not a valid number. Use decimal digits only, with optional leading minus.`
5244
6115
  );
5245
6116
  }
5246
- const num = BigInt(t);
5247
6117
  if (num < I64_MIN) {
5248
6118
  throw new ValidationError(
5249
6119
  field,
@@ -5259,14 +6129,15 @@ function validateI64(value, field) {
5259
6129
  return num;
5260
6130
  }
5261
6131
  function validateI128(value, field) {
5262
- const t = value.trim();
5263
- if (!/^-?(0|[1-9]\d*)$/.test(t)) {
6132
+ let num;
6133
+ try {
6134
+ num = BigInt(value);
6135
+ } catch {
5264
6136
  throw new ValidationError(
5265
6137
  field,
5266
- `"${value}" is not a valid integer. Use decimal digits only, with optional leading minus.`
6138
+ `"${value}" is not a valid number. Use decimal digits only, with optional leading minus.`
5267
6139
  );
5268
6140
  }
5269
- const num = BigInt(t);
5270
6141
  if (num < I128_MIN) {
5271
6142
  throw new ValidationError(
5272
6143
  field,
@@ -5290,9 +6161,6 @@ function validateBps(value, field) {
5290
6161
  `must be <= 10000 (100%), got ${t}`
5291
6162
  );
5292
6163
  }
5293
- if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5294
- throw new ValidationError(field, `internal error: bps value exceeds MAX_SAFE_INTEGER`);
5295
- }
5296
6164
  return Number(bi);
5297
6165
  }
5298
6166
  function validateU64(value, field) {
@@ -5301,15 +6169,12 @@ function validateU64(value, field) {
5301
6169
  function validateU16(value, field) {
5302
6170
  const t = requireDecimalUIntString(value, field);
5303
6171
  const bi = BigInt(t);
5304
- if (bi > BigInt(U16_MAX)) {
6172
+ if (bi > BigInt(U16_MAX2)) {
5305
6173
  throw new ValidationError(
5306
6174
  field,
5307
- `must be <= ${U16_MAX} (u16 max), got ${t}`
6175
+ `must be <= ${U16_MAX2} (u16 max), got ${t}`
5308
6176
  );
5309
6177
  }
5310
- if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5311
- throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);
5312
- }
5313
6178
  return Number(bi);
5314
6179
  }
5315
6180
 
@@ -5360,9 +6225,7 @@ function parseDexScreenerPairs(json) {
5360
6225
  else if (liquidity > 1e4) confidence = 60;
5361
6226
  else if (liquidity > 1e3) confidence = 45;
5362
6227
  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;
6228
+ const price = typeof priceUsd === "string" || typeof priceUsd === "number" ? parseFloat(String(priceUsd)) || 0 : 0;
5366
6229
  let baseSym = "?";
5367
6230
  let quoteSym = "?";
5368
6231
  if (isRecord(pair.baseToken) && typeof pair.baseToken.symbol === "string") {
@@ -5393,8 +6256,8 @@ function parseJupiterMintEntry(json, mint) {
5393
6256
  if (!isRecord(row)) return null;
5394
6257
  const rawPrice = row.price;
5395
6258
  if (rawPrice === void 0 || rawPrice === null) return null;
5396
- const price = parseFloat(String(rawPrice));
5397
- if (!Number.isFinite(price) || price <= 0) return null;
6259
+ const price = parseFloat(String(rawPrice)) || 0;
6260
+ if (price <= 0) return null;
5398
6261
  let mintSymbol = "?";
5399
6262
  if (typeof row.mintSymbol === "string") mintSymbol = row.mintSymbol;
5400
6263
  return { price, mintSymbol };
@@ -5460,17 +6323,10 @@ async function fetchDexSources(mint, signal) {
5460
6323
  headers: { "User-Agent": "percolator/1.0" }
5461
6324
  }
5462
6325
  );
5463
- if (!resp.ok) {
5464
- console.debug(`[fetchDexSources] HTTP ${resp.status} for mint ${mint}`);
5465
- return [];
5466
- }
6326
+ if (!resp.ok) return [];
5467
6327
  const json = await resp.json();
5468
6328
  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
- );
6329
+ } catch {
5474
6330
  return [];
5475
6331
  }
5476
6332
  }
@@ -5481,7 +6337,7 @@ function lookupPythSource(mint) {
5481
6337
  type: "pyth",
5482
6338
  address: entry.feedId,
5483
6339
  pairLabel: `${entry.symbol} / USD (Pyth)`,
5484
- liquidity: Number.MAX_SAFE_INTEGER,
6340
+ liquidity: Infinity,
5485
6341
  // Pyth is considered deep liquidity
5486
6342
  price: 0,
5487
6343
  // We don't fetch live price here; caller can enrich
@@ -5498,16 +6354,10 @@ async function fetchJupiterSource(mint, signal) {
5498
6354
  headers: { "User-Agent": "percolator/1.0" }
5499
6355
  }
5500
6356
  );
5501
- if (!resp.ok) {
5502
- console.debug(`[fetchJupiterSource] HTTP ${resp.status} for mint ${mint}`);
5503
- return null;
5504
- }
6357
+ if (!resp.ok) return null;
5505
6358
  const json = await resp.json();
5506
6359
  const row = parseJupiterMintEntry(json, mint);
5507
- if (!row) {
5508
- console.debug(`[fetchJupiterSource] No price data from Jupiter for mint ${mint}`);
5509
- return null;
5510
- }
6360
+ if (!row) return null;
5511
6361
  return {
5512
6362
  type: "jupiter",
5513
6363
  address: mint,
@@ -5518,39 +6368,23 @@ async function fetchJupiterSource(mint, signal) {
5518
6368
  confidence: 40
5519
6369
  // Fallback — lower confidence
5520
6370
  };
5521
- } catch (err) {
5522
- console.warn(
5523
- `[fetchJupiterSource] Error fetching Jupiter data for mint ${mint}:`,
5524
- err instanceof Error ? err.message : String(err)
5525
- );
6371
+ } catch {
5526
6372
  return null;
5527
6373
  }
5528
6374
  }
5529
6375
  async function resolvePrice(mint, signal, options) {
5530
6376
  const timeoutMs = options?.timeoutMs ?? DEFAULT_RESOLVE_TIMEOUT_MS;
5531
6377
  const timeoutSignal = AbortSignal.timeout(timeoutMs);
5532
- const effectiveSignal2 = signal ? combineAbortSignals([signal, timeoutSignal]) : timeoutSignal;
6378
+ const combinedSignal = signal ? combineAbortSignals([signal, timeoutSignal]) : timeoutSignal;
5533
6379
  const [dexSources, jupiterSource] = await Promise.all([
5534
- fetchDexSources(mint, effectiveSignal2),
5535
- fetchJupiterSource(mint, effectiveSignal2)
6380
+ fetchDexSources(mint, combinedSignal),
6381
+ fetchJupiterSource(mint, combinedSignal)
5536
6382
  ]);
5537
6383
  const pythSource = lookupPythSource(mint);
5538
6384
  const allSources = [];
5539
6385
  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
- }
6386
+ const refPrice = dexSources[0]?.price || jupiterSource?.price || 0;
6387
+ pythSource.price = refPrice;
5554
6388
  allSources.push(pythSource);
5555
6389
  }
5556
6390
  allSources.push(...dexSources);
@@ -5575,7 +6409,9 @@ export {
5575
6409
  ACCOUNTS_CLOSE_ACCOUNT,
5576
6410
  ACCOUNTS_CLOSE_SLAB,
5577
6411
  ACCOUNTS_CLOSE_STALE_SLABS,
6412
+ ACCOUNTS_CREATE_INSURANCE_MINT,
5578
6413
  ACCOUNTS_DEPOSIT_COLLATERAL,
6414
+ ACCOUNTS_DEPOSIT_INSURANCE_LP,
5579
6415
  ACCOUNTS_EXECUTE_ADL,
5580
6416
  ACCOUNTS_FUND_MARKET_INSURANCE,
5581
6417
  ACCOUNTS_INIT_LP,
@@ -5586,21 +6422,22 @@ export {
5586
6422
  ACCOUNTS_LIQUIDATE_AT_ORACLE,
5587
6423
  ACCOUNTS_LP_VAULT_WITHDRAW,
5588
6424
  ACCOUNTS_MINT_POSITION_NFT,
6425
+ ACCOUNTS_NFT_BURN,
6426
+ ACCOUNTS_NFT_EMERGENCY_BURN,
6427
+ ACCOUNTS_NFT_MINT,
5589
6428
  ACCOUNTS_PAUSE_MARKET,
5590
- ACCOUNTS_PUSH_ORACLE_PRICE,
5591
6429
  ACCOUNTS_QUEUE_WITHDRAWAL,
5592
6430
  ACCOUNTS_RECLAIM_SLAB_RENT,
5593
6431
  ACCOUNTS_RESOLVE_MARKET,
6432
+ ACCOUNTS_SET_DEX_POOL,
5594
6433
  ACCOUNTS_SET_INSURANCE_ISOLATION,
5595
6434
  ACCOUNTS_SET_MAINTENANCE_FEE,
5596
6435
  ACCOUNTS_SET_OI_IMBALANCE_HARD_BLOCK,
5597
- ACCOUNTS_SET_ORACLE_AUTHORITY,
5598
6436
  ACCOUNTS_SET_ORACLE_PRICE_CAP,
5599
6437
  ACCOUNTS_SET_PENDING_SETTLEMENT,
5600
6438
  ACCOUNTS_SET_RISK_THRESHOLD,
5601
6439
  ACCOUNTS_SET_WALLET_CAP,
5602
6440
  ACCOUNTS_TOPUP_INSURANCE,
5603
- ACCOUNTS_TOPUP_KEEPER_FUND,
5604
6441
  ACCOUNTS_TRADE_CPI,
5605
6442
  ACCOUNTS_TRADE_NOCPI,
5606
6443
  ACCOUNTS_TRANSFER_POSITION_OWNERSHIP,
@@ -5609,11 +6446,13 @@ export {
5609
6446
  ACCOUNTS_UPDATE_CONFIG,
5610
6447
  ACCOUNTS_WITHDRAW_COLLATERAL,
5611
6448
  ACCOUNTS_WITHDRAW_INSURANCE,
6449
+ ACCOUNTS_WITHDRAW_INSURANCE_LIMITED_LIVE,
6450
+ ACCOUNTS_WITHDRAW_INSURANCE_LIMITED_RESOLVED,
6451
+ ACCOUNTS_WITHDRAW_INSURANCE_LP,
5612
6452
  AccountKind,
5613
6453
  CHAINLINK_ANSWER_OFFSET,
5614
6454
  CHAINLINK_DECIMALS_OFFSET,
5615
6455
  CHAINLINK_MIN_SIZE,
5616
- CHAINLINK_TIMESTAMP_OFFSET,
5617
6456
  CREATOR_LOCK_SEED,
5618
6457
  CTX_VAMM_OFFSET,
5619
6458
  DEFAULT_OI_RAMP_SLOTS,
@@ -5623,13 +6462,15 @@ export {
5623
6462
  LIGHTHOUSE_CONSTRAINT_ADDRESS,
5624
6463
  LIGHTHOUSE_ERROR_CODES,
5625
6464
  LIGHTHOUSE_PROGRAM_ID,
5626
- LIGHTHOUSE_PROGRAM_ID_STR2 as LIGHTHOUSE_PROGRAM_ID_STR,
6465
+ LIGHTHOUSE_PROGRAM_ID_STR,
5627
6466
  LIGHTHOUSE_USER_MESSAGE,
6467
+ LiquidationPolicyTag,
5628
6468
  MARK_PRICE_EMA_ALPHA_E6,
5629
6469
  MARK_PRICE_EMA_WINDOW_SLOTS,
5630
6470
  MAX_DECIMALS,
5631
- MAX_ORACLE_PRICE,
5632
6471
  METEORA_DLMM_PROGRAM_ID,
6472
+ NFT_IX_TAG,
6473
+ NFT_PROGRAM_ID,
5633
6474
  ORACLE_PHASE_GROWING,
5634
6475
  ORACLE_PHASE_MATURE,
5635
6476
  ORACLE_PHASE_NASCENT,
@@ -5638,6 +6479,7 @@ export {
5638
6479
  PHASE1_VOLUME_MIN_SLOTS,
5639
6480
  PHASE2_MATURITY_SLOTS,
5640
6481
  PHASE2_VOLUME_THRESHOLD,
6482
+ POSITION_NFT_STATE_LEN,
5641
6483
  PROGRAM_IDS,
5642
6484
  PUMPSWAP_PROGRAM_ID,
5643
6485
  PYTH_PUSH_ORACLE_PROGRAM_ID,
@@ -5647,10 +6489,13 @@ export {
5647
6489
  RAYDIUM_CLMM_PROGRAM_ID,
5648
6490
  RENOUNCE_ADMIN_CONFIRMATION,
5649
6491
  RpcPool,
6492
+ SLAB_MAGIC,
5650
6493
  SLAB_TIERS,
5651
6494
  SLAB_TIERS_V0,
5652
6495
  SLAB_TIERS_V1,
5653
6496
  SLAB_TIERS_V12_1,
6497
+ SLAB_TIERS_V12_15,
6498
+ SLAB_TIERS_V12_17,
5654
6499
  SLAB_TIERS_V1D,
5655
6500
  SLAB_TIERS_V1D_LEGACY,
5656
6501
  SLAB_TIERS_V1M,
@@ -5659,6 +6504,7 @@ export {
5659
6504
  SLAB_TIERS_V_ADL,
5660
6505
  SLAB_TIERS_V_ADL_DISCOVERY,
5661
6506
  SLAB_TIERS_V_SETDEXPOOL,
6507
+ STAKE_DEPOSIT_SIZE,
5662
6508
  STAKE_IX,
5663
6509
  STAKE_POOL_SIZE,
5664
6510
  STAKE_PROGRAM_ID,
@@ -5688,7 +6534,6 @@ export {
5688
6534
  computeLiqPrice,
5689
6535
  computeMarkPnl,
5690
6536
  computeMaxLeverage,
5691
- computeMaxWithdrawable,
5692
6537
  computePnlPercent,
5693
6538
  computePreTradeLiqPrice,
5694
6539
  computeRequiredMargin,
@@ -5696,17 +6541,20 @@ export {
5696
6541
  computeVammQuote,
5697
6542
  computeWarmupLeverageCap,
5698
6543
  computeWarmupMaxPositionSize,
5699
- computeWarmupProgress,
5700
6544
  computeWarmupUnlockedCapital,
5701
6545
  concatBytes,
5702
6546
  countLighthouseInstructions,
6547
+ decodeDepositPda,
5703
6548
  decodeError,
5704
6549
  decodeStakePool,
5705
6550
  depositAccounts,
5706
6551
  deriveCreatorLockPda,
5707
6552
  deriveDepositPda,
5708
- deriveKeeperFund,
6553
+ deriveInsuranceLpMint,
5709
6554
  deriveLpPda,
6555
+ deriveMintAuthority,
6556
+ deriveNftMint,
6557
+ deriveNftPda,
5710
6558
  derivePythPriceUpdateAccount,
5711
6559
  derivePythPushOraclePDA,
5712
6560
  deriveStakePool,
@@ -5728,21 +6576,30 @@ export {
5728
6576
  encU32,
5729
6577
  encU64,
5730
6578
  encU8,
6579
+ encodeAcceptAdmin,
5731
6580
  encodeAdminForceClose,
5732
6581
  encodeAdvanceEpoch,
5733
6582
  encodeAdvanceOraclePhase,
5734
6583
  encodeAllocateMarket,
6584
+ encodeAttestCrossMargin,
5735
6585
  encodeAuditCrank,
5736
6586
  encodeBurnPositionNft,
5737
6587
  encodeCancelQueuedWithdrawal,
6588
+ encodeChallengeSettlement,
5738
6589
  encodeClaimEpochWithdrawal,
5739
6590
  encodeClaimQueuedWithdrawal,
5740
6591
  encodeClearPendingSettlement,
5741
6592
  encodeCloseAccount,
6593
+ encodeCloseOrphanSlab,
5742
6594
  encodeCloseSlab,
5743
6595
  encodeCloseStaleSlabs,
6596
+ encodeCreateInsuranceMint,
6597
+ encodeCreateLpVault,
5744
6598
  encodeDepositCollateral,
6599
+ encodeDepositInsuranceLP,
6600
+ encodeDepositLpCollateral,
5745
6601
  encodeExecuteAdl,
6602
+ encodeForceCloseResolved,
5746
6603
  encodeFundMarketInsurance,
5747
6604
  encodeInitLP,
5748
6605
  encodeInitMarket,
@@ -5751,19 +6608,33 @@ export {
5751
6608
  encodeInitUser,
5752
6609
  encodeKeeperCrank,
5753
6610
  encodeLiquidateAtOracle,
6611
+ encodeLpVaultCrankFees,
6612
+ encodeLpVaultDeposit,
5754
6613
  encodeLpVaultWithdraw,
5755
6614
  encodeMintPositionNft,
6615
+ encodeNftBurn,
6616
+ encodeNftEmergencyBurn,
6617
+ encodeNftMint,
6618
+ encodeNftSettleFunding,
5756
6619
  encodePauseMarket,
5757
- encodePushOraclePrice,
5758
6620
  encodeQueueWithdrawal,
5759
6621
  encodeQueueWithdrawalSV,
5760
6622
  encodeReclaimSlabRent,
5761
6623
  encodeRenounceAdmin,
6624
+ encodeRescueOrphanVault,
6625
+ encodeResolveDispute,
5762
6626
  encodeResolveMarket,
6627
+ encodeResolvePermissionless,
6628
+ encodeSetDexPool,
6629
+ encodeSetDisputeParams,
5763
6630
  encodeSetInsuranceIsolation,
6631
+ encodeSetInsuranceWithdrawPolicy,
6632
+ encodeSetLpCollateralParams,
5764
6633
  encodeSetMaintenanceFee,
6634
+ encodeSetMaxPnlCap,
6635
+ encodeSetOffsetPair,
6636
+ encodeSetOiCapMultiplier,
5765
6637
  encodeSetOiImbalanceHardBlock,
5766
- encodeSetOracleAuthority,
5767
6638
  encodeSetOraclePriceCap,
5768
6639
  encodeSetPendingSettlement,
5769
6640
  encodeSetPythOracle,
@@ -5788,13 +6659,13 @@ export {
5788
6659
  encodeStakeUpdateConfig,
5789
6660
  encodeStakeWithdraw,
5790
6661
  encodeTopUpInsurance,
5791
- encodeTopUpKeeperFund,
5792
6662
  encodeTradeCpi,
5793
6663
  encodeTradeCpiV2,
5794
6664
  encodeTradeNoCpi,
5795
6665
  encodeTransferOwnershipCpi,
5796
6666
  encodeTransferPositionOwnership,
5797
6667
  encodeUnpauseMarket,
6668
+ encodeUnresolveMarket,
5798
6669
  encodeUpdateAdmin,
5799
6670
  encodeUpdateConfig,
5800
6671
  encodeUpdateHyperpMark,
@@ -5802,6 +6673,9 @@ export {
5802
6673
  encodeUpdateRiskParams,
5803
6674
  encodeWithdrawCollateral,
5804
6675
  encodeWithdrawInsurance,
6676
+ encodeWithdrawInsuranceLP,
6677
+ encodeWithdrawInsuranceLimited,
6678
+ encodeWithdrawLpCollateral,
5805
6679
  fetchAdlRankedPositions,
5806
6680
  fetchAdlRankings,
5807
6681
  fetchSlab,
@@ -5815,13 +6689,13 @@ export {
5815
6689
  getErrorName,
5816
6690
  getMarketsByAddress,
5817
6691
  getMatcherProgramId,
6692
+ getNftProgramId,
5818
6693
  getProgramId,
5819
6694
  getStakeProgramId,
5820
6695
  getStaticMarkets,
5821
6696
  initPoolAccounts,
5822
6697
  isAccountUsed,
5823
6698
  isAdlTriggered,
5824
- isAnchorErrorCode,
5825
6699
  isLighthouseError,
5826
6700
  isLighthouseFailureInLogs,
5827
6701
  isLighthouseInstruction,
@@ -5829,6 +6703,7 @@ export {
5829
6703
  isToken2022,
5830
6704
  isValidChainlinkOracle,
5831
6705
  maxAccountIndex,
6706
+ packOiCap,
5832
6707
  parseAccount,
5833
6708
  parseAdlEvent,
5834
6709
  parseAllAccounts,
@@ -5839,6 +6714,7 @@ export {
5839
6714
  parseErrorFromLogs,
5840
6715
  parseHeader,
5841
6716
  parseParams,
6717
+ parsePositionNftAccount,
5842
6718
  parseUsedIndices,
5843
6719
  rankAdlPositions,
5844
6720
  readLastThrUpdateSlot,