@percolatorct/sdk 0.5.1 → 1.0.0-beta.10

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
@@ -93,6 +93,7 @@ function concatBytes(...arrays) {
93
93
  }
94
94
 
95
95
  // src/abi/instructions.ts
96
+ var MAX_ORACLE_PRICE = 1000000000000n;
96
97
  var IX_TAG = {
97
98
  InitMarket: 0,
98
99
  InitUser: 1,
@@ -116,16 +117,33 @@ var IX_TAG = {
116
117
  ResolveMarket: 19,
117
118
  WithdrawInsurance: 20,
118
119
  AdminForceClose: 21,
120
+ // Tags 22-23: on-chain these are SetInsuranceWithdrawPolicy / WithdrawInsuranceLimited.
121
+ // Legacy aliases (UpdateRiskParams/RenounceAdmin) kept for backward compat.
122
+ SetInsuranceWithdrawPolicy: 22,
123
+ /** @deprecated Use SetInsuranceWithdrawPolicy */
119
124
  UpdateRiskParams: 22,
125
+ WithdrawInsuranceLimited: 23,
126
+ /** @deprecated Use WithdrawInsuranceLimited */
120
127
  RenounceAdmin: 23,
121
- CreateInsuranceMint: 24,
122
- DepositInsuranceLP: 25,
123
- WithdrawInsuranceLP: 26,
128
+ // Tags 24–26: on-chain = QueryLpFees/ReclaimEmptyAccount/SettleAccount.
129
+ // Old insurance LP tags removed — those moved to percolator-stake.
130
+ QueryLpFees: 24,
131
+ ReclaimEmptyAccount: 25,
132
+ SettleAccount: 26,
133
+ // Tags 27-28: on-chain = DepositFeeCredits/ConvertReleasedPnl.
134
+ // Legacy aliases (PauseMarket/UnpauseMarket) kept — those instructions don't exist on-chain.
135
+ DepositFeeCredits: 27,
136
+ /** @deprecated No on-chain PauseMarket instruction */
124
137
  PauseMarket: 27,
138
+ ConvertReleasedPnl: 28,
139
+ /** @deprecated No on-chain UnpauseMarket instruction */
125
140
  UnpauseMarket: 28,
141
+ // Tags 29-30: on-chain = ResolvePermissionless/ForceCloseResolved.
142
+ ResolvePermissionless: 29,
143
+ /** @deprecated Use ResolvePermissionless */
126
144
  AcceptAdmin: 29,
127
- SetInsuranceWithdrawPolicy: 30,
128
- WithdrawInsuranceLimited: 31,
145
+ ForceCloseResolved: 30,
146
+ // Tag 31: gap (no decode arm on-chain)
129
147
  SetPythOracle: 32,
130
148
  UpdateMarkPrice: 33,
131
149
  UpdateHyperpMark: 34,
@@ -199,8 +217,17 @@ var IX_TAG = {
199
217
  /** PERC-8111: Set per-wallet position cap (admin only, cap_e6=0 disables). */
200
218
  SetWalletCap: 70,
201
219
  /** PERC-8110: Set OI imbalance hard-block threshold (admin only). */
202
- SetOiImbalanceHardBlock: 71
220
+ SetOiImbalanceHardBlock: 71,
221
+ /** PERC-8270: Rescue orphan vault — recover tokens from a closed market's vault (admin). */
222
+ RescueOrphanVault: 72,
223
+ /** PERC-8270: Close orphan slab — reclaim rent from a slab whose market closed unexpectedly (admin). */
224
+ CloseOrphanSlab: 73,
225
+ /** PERC-SetDexPool: Pin admin-approved DEX pool address for a HYPERP market (admin). */
226
+ SetDexPool: 74,
227
+ /** CPI to the matcher program to initialize a matcher context account for an LP slot. Admin-only. */
228
+ InitMatcherCtx: 75
203
229
  };
230
+ Object.freeze(IX_TAG);
204
231
  var HEX_RE = /^[0-9a-fA-F]{64}$/;
205
232
  function encodeFeedId(feedId) {
206
233
  const hex = feedId.startsWith("0x") ? feedId.slice(2) : feedId;
@@ -211,11 +238,17 @@ function encodeFeedId(feedId) {
211
238
  }
212
239
  const bytes = new Uint8Array(32);
213
240
  for (let i = 0; i < 64; i += 2) {
214
- bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);
241
+ const byte = parseInt(hex.substring(i, i + 2), 16);
242
+ if (Number.isNaN(byte)) {
243
+ throw new Error(
244
+ `Failed to parse hex byte at position ${i}: "${hex.substring(i, i + 2)}"`
245
+ );
246
+ }
247
+ bytes[i / 2] = byte;
215
248
  }
216
249
  return bytes;
217
250
  }
218
- var INIT_MARKET_DATA_LEN = 264;
251
+ var INIT_MARKET_DATA_LEN = 352;
219
252
  function encodeInitMarket(args) {
220
253
  const data = concatBytes(
221
254
  encU8(IX_TAG.InitMarket),
@@ -227,6 +260,11 @@ function encodeInitMarket(args) {
227
260
  encU8(args.invert),
228
261
  encU32(args.unitScale),
229
262
  encU64(args.initialMarkPriceE6),
263
+ // 3 fields between header and RiskParams (immutable after init)
264
+ encU128(args.maxMaintenanceFeePerSlot ?? 0n),
265
+ encU128(args.maxInsuranceFloor ?? 0n),
266
+ encU64(args.minOraclePriceCap ?? 0n),
267
+ // RiskParams block (15 fields)
230
268
  encU64(args.warmupPeriodSlots),
231
269
  encU64(args.maintenanceMarginBps),
232
270
  encU64(args.initialMarginBps),
@@ -239,7 +277,10 @@ function encodeInitMarket(args) {
239
277
  encU64(args.liquidationFeeBps),
240
278
  encU128(args.liquidationFeeCap),
241
279
  encU64(args.liquidationBufferBps),
242
- encU128(args.minLiquidationAbs)
280
+ encU128(args.minLiquidationAbs),
281
+ encU128(args.minInitialDeposit),
282
+ encU128(args.minNonzeroMmReq),
283
+ encU128(args.minNonzeroImReq)
243
284
  );
244
285
  if (data.length !== INIT_MARKET_DATA_LEN) {
245
286
  throw new Error(
@@ -362,9 +403,16 @@ function encodeSetOracleAuthority(args) {
362
403
  );
363
404
  }
364
405
  function encodePushOraclePrice(args) {
406
+ const price = typeof args.priceE6 === "string" ? BigInt(args.priceE6) : args.priceE6;
407
+ if (price === 0n) {
408
+ throw new Error("encodePushOraclePrice: price cannot be zero (division by zero in engine)");
409
+ }
410
+ if (price > MAX_ORACLE_PRICE) {
411
+ throw new Error(`encodePushOraclePrice: price exceeds maximum (${MAX_ORACLE_PRICE}), got ${price}`);
412
+ }
365
413
  return concatBytes(
366
414
  encU8(IX_TAG.PushOraclePrice),
367
- encU64(args.priceE6),
415
+ encU64(price),
368
416
  encI64(args.timestamp)
369
417
  );
370
418
  }
@@ -405,15 +453,6 @@ function encodeRenounceAdmin() {
405
453
  encU64(RENOUNCE_ADMIN_CONFIRMATION)
406
454
  );
407
455
  }
408
- function encodeCreateInsuranceMint() {
409
- return encU8(IX_TAG.CreateInsuranceMint);
410
- }
411
- function encodeDepositInsuranceLP(args) {
412
- return concatBytes(encU8(IX_TAG.DepositInsuranceLP), encU64(args.amount));
413
- }
414
- function encodeWithdrawInsuranceLP(args) {
415
- return concatBytes(encU8(IX_TAG.WithdrawInsuranceLP), encU64(args.lpAmount));
416
- }
417
456
  function encodeLpVaultWithdraw(args) {
418
457
  return concatBytes(encU8(IX_TAG.LpVaultWithdraw), encU64(args.lpAmount));
419
458
  }
@@ -441,17 +480,15 @@ function encodeSetPythOracle(args) {
441
480
  }
442
481
  var PYTH_RECEIVER_PROGRAM_ID = "rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ";
443
482
  async function derivePythPriceUpdateAccount(feedId, shardId = 0) {
444
- const { PublicKey: PublicKey12 } = await import("@solana/web3.js");
483
+ const { PublicKey: PublicKey15 } = await import("@solana/web3.js");
445
484
  const shardBuf = new Uint8Array(2);
446
485
  new DataView(shardBuf.buffer).setUint16(0, shardId, true);
447
- const [pda] = PublicKey12.findProgramAddressSync(
486
+ const [pda] = PublicKey15.findProgramAddressSync(
448
487
  [shardBuf, feedId],
449
- new PublicKey12(PYTH_RECEIVER_PROGRAM_ID)
488
+ new PublicKey15(PYTH_RECEIVER_PROGRAM_ID)
450
489
  );
451
490
  return pda.toBase58();
452
491
  }
453
- IX_TAG["SetPythOracle"] = 32;
454
- IX_TAG["UpdateMarkPrice"] = 33;
455
492
  function encodeUpdateMarkPrice() {
456
493
  return new Uint8Array([33]);
457
494
  }
@@ -462,7 +499,7 @@ function computeEmaMarkPrice(markPrevE6, oracleE6, dtSlots, alphaE6 = MARK_PRICE
462
499
  if (markPrevE6 === 0n || dtSlots === 0n) return oracleE6;
463
500
  let oracleClamped = oracleE6;
464
501
  if (capE2bps > 0n) {
465
- const maxDelta = markPrevE6 * capE2bps * dtSlots / 1000000n;
502
+ const maxDelta = markPrevE6 * capE2bps / 1000000n * dtSlots;
466
503
  const lo = markPrevE6 > maxDelta ? markPrevE6 - maxDelta : 0n;
467
504
  const hi = markPrevE6 + maxDelta;
468
505
  if (oracleClamped < lo) oracleClamped = lo;
@@ -472,7 +509,6 @@ function computeEmaMarkPrice(markPrevE6, oracleE6, dtSlots, alphaE6 = MARK_PRICE
472
509
  const oneMinusAlpha = 1000000n - effectiveAlpha;
473
510
  return (oracleClamped * effectiveAlpha + markPrevE6 * oneMinusAlpha) / 1000000n;
474
511
  }
475
- IX_TAG["UpdateHyperpMark"] = 34;
476
512
  function encodeUpdateHyperpMark() {
477
513
  return new Uint8Array([34]);
478
514
  }
@@ -616,6 +652,74 @@ function encodeTransferOwnershipCpi(args) {
616
652
  function encodeSetWalletCap(args) {
617
653
  return concatBytes(encU8(IX_TAG.SetWalletCap), encU64(args.capE6));
618
654
  }
655
+ function encodeInitMatcherCtx(args) {
656
+ return concatBytes(
657
+ encU8(IX_TAG.InitMatcherCtx),
658
+ encU16(args.lpIdx),
659
+ encU8(args.kind),
660
+ encU32(args.tradingFeeBps),
661
+ encU32(args.baseSpreadBps),
662
+ encU32(args.maxTotalBps),
663
+ encU32(args.impactKBps),
664
+ encU128(args.liquidityNotionalE6),
665
+ encU128(args.maxFillAbs),
666
+ encU128(args.maxInventoryAbs),
667
+ encU16(args.feeToInsuranceBps),
668
+ encU16(args.skewSpreadMultBps)
669
+ );
670
+ }
671
+ function encodeSetInsuranceWithdrawPolicy(args) {
672
+ return concatBytes(encU8(IX_TAG.SetInsuranceWithdrawPolicy), encPubkey(args.authority), encU64(args.minWithdrawBase), encU16(args.maxWithdrawBps), encU64(args.cooldownSlots));
673
+ }
674
+ function encodeWithdrawInsuranceLimited(args) {
675
+ return concatBytes(encU8(IX_TAG.WithdrawInsuranceLimited), encU64(args.amount));
676
+ }
677
+ function encodeResolvePermissionless() {
678
+ return concatBytes(encU8(IX_TAG.ResolvePermissionless));
679
+ }
680
+ function encodeForceCloseResolved(args) {
681
+ return concatBytes(encU8(IX_TAG.ForceCloseResolved), encU16(args.userIdx));
682
+ }
683
+ function encodeCreateLpVault(args) {
684
+ const parts = [encU8(IX_TAG.CreateLpVault), encU64(args.feeShareBps)];
685
+ if (args.utilCurveEnabled !== void 0) {
686
+ parts.push(encU8(args.utilCurveEnabled ? 1 : 0));
687
+ }
688
+ return concatBytes(...parts);
689
+ }
690
+ function encodeLpVaultDeposit(args) {
691
+ return concatBytes(encU8(IX_TAG.LpVaultDeposit), encU64(args.amount));
692
+ }
693
+ function encodeLpVaultCrankFees() {
694
+ return concatBytes(encU8(IX_TAG.LpVaultCrankFees));
695
+ }
696
+ function encodeChallengeSettlement(args) {
697
+ return concatBytes(encU8(IX_TAG.ChallengeSettlement), encU64(args.proposedPriceE6));
698
+ }
699
+ function encodeResolveDispute(args) {
700
+ return concatBytes(encU8(IX_TAG.ResolveDispute), encU8(args.accept));
701
+ }
702
+ function encodeDepositLpCollateral(args) {
703
+ return concatBytes(encU8(IX_TAG.DepositLpCollateral), encU16(args.userIdx), encU64(args.lpAmount));
704
+ }
705
+ function encodeWithdrawLpCollateral(args) {
706
+ return concatBytes(encU8(IX_TAG.WithdrawLpCollateral), encU16(args.userIdx), encU64(args.lpAmount));
707
+ }
708
+ function encodeSetOffsetPair(args) {
709
+ return concatBytes(encU8(IX_TAG.SetOffsetPair), encU16(args.offsetBps));
710
+ }
711
+ function encodeAttestCrossMargin(args) {
712
+ return concatBytes(encU8(IX_TAG.AttestCrossMargin), encU16(args.userIdxA), encU16(args.userIdxB));
713
+ }
714
+ function encodeRescueOrphanVault() {
715
+ return concatBytes(encU8(IX_TAG.RescueOrphanVault));
716
+ }
717
+ function encodeCloseOrphanSlab() {
718
+ return concatBytes(encU8(IX_TAG.CloseOrphanSlab));
719
+ }
720
+ function encodeSetDexPool(args) {
721
+ return concatBytes(encU8(IX_TAG.SetDexPool), encPubkey(args.pool));
722
+ }
619
723
 
620
724
  // src/abi/accounts.ts
621
725
  import {
@@ -790,37 +894,6 @@ function buildAccountMetas(spec, keys) {
790
894
  isWritable: s.writable
791
895
  }));
792
896
  }
793
- var ACCOUNTS_CREATE_INSURANCE_MINT = [
794
- { name: "admin", signer: true, writable: false },
795
- { name: "slab", signer: false, writable: false },
796
- { name: "insLpMint", signer: false, writable: true },
797
- { name: "vaultAuthority", signer: false, writable: false },
798
- { name: "collateralMint", signer: false, writable: false },
799
- { name: "systemProgram", signer: false, writable: false },
800
- { name: "tokenProgram", signer: false, writable: false },
801
- { name: "rent", signer: false, writable: false },
802
- { name: "payer", signer: true, writable: true }
803
- ];
804
- var ACCOUNTS_DEPOSIT_INSURANCE_LP = [
805
- { name: "depositor", signer: true, writable: false },
806
- { name: "slab", signer: false, writable: true },
807
- { name: "depositorAta", signer: false, writable: true },
808
- { name: "vault", signer: false, writable: true },
809
- { name: "tokenProgram", signer: false, writable: false },
810
- { name: "insLpMint", signer: false, writable: true },
811
- { name: "depositorLpAta", signer: false, writable: true },
812
- { name: "vaultAuthority", signer: false, writable: false }
813
- ];
814
- var ACCOUNTS_WITHDRAW_INSURANCE_LP = [
815
- { name: "withdrawer", signer: true, writable: false },
816
- { name: "slab", signer: false, writable: true },
817
- { name: "withdrawerAta", signer: false, writable: true },
818
- { name: "vault", signer: false, writable: true },
819
- { name: "tokenProgram", signer: false, writable: false },
820
- { name: "insLpMint", signer: false, writable: true },
821
- { name: "withdrawerLpAta", signer: false, writable: true },
822
- { name: "vaultAuthority", signer: false, writable: false }
823
- ];
824
897
  var ACCOUNTS_LP_VAULT_WITHDRAW = [
825
898
  { name: "withdrawer", signer: true, writable: false },
826
899
  { name: "slab", signer: false, writable: true },
@@ -942,6 +1015,13 @@ var ACCOUNTS_SET_WALLET_CAP = [
942
1015
  { name: "admin", signer: true, writable: false },
943
1016
  { name: "slab", signer: false, writable: true }
944
1017
  ];
1018
+ var ACCOUNTS_INIT_MATCHER_CTX = [
1019
+ { name: "admin", signer: true, writable: false },
1020
+ { name: "slab", signer: false, writable: false },
1021
+ { name: "matcherCtx", signer: false, writable: true },
1022
+ { name: "matcherProg", signer: false, writable: false },
1023
+ { name: "lpPda", signer: false, writable: false }
1024
+ ];
945
1025
  var WELL_KNOWN = {
946
1026
  tokenProgram: TOKEN_PROGRAM_ID,
947
1027
  clock: SYSVAR_CLOCK_PUBKEY,
@@ -1226,11 +1306,24 @@ function getErrorName(code) {
1226
1306
  function getErrorHint(code) {
1227
1307
  return PERCOLATOR_ERRORS[code]?.hint;
1228
1308
  }
1309
+ var LIGHTHOUSE_PROGRAM_ID_STR = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
1310
+ var ANCHOR_ERROR_RANGE_START = 6e3;
1311
+ var ANCHOR_ERROR_RANGE_END = 8191;
1312
+ var ANCHOR_ERROR_NAMES = {
1313
+ 6032: "ConstraintMut",
1314
+ 6036: "ConstraintOwner",
1315
+ 6038: "ConstraintSeeds",
1316
+ 6400: "ConstraintAddress"
1317
+ };
1318
+ function isAnchorErrorCode(code) {
1319
+ return code >= ANCHOR_ERROR_RANGE_START && code <= ANCHOR_ERROR_RANGE_END;
1320
+ }
1229
1321
  var CUSTOM_ERROR_HEX_MAX_LEN = 8;
1230
1322
  function parseErrorFromLogs(logs) {
1231
1323
  if (!Array.isArray(logs)) {
1232
1324
  return null;
1233
1325
  }
1326
+ let insideLighthouse = false;
1234
1327
  const re = new RegExp(
1235
1328
  `custom program error: 0x([0-9a-fA-F]{1,${CUSTOM_ERROR_HEX_MAX_LEN}})(?![0-9a-fA-F])`,
1236
1329
  "i"
@@ -1239,17 +1332,32 @@ function parseErrorFromLogs(logs) {
1239
1332
  if (typeof log !== "string") {
1240
1333
  continue;
1241
1334
  }
1335
+ if (log.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {
1336
+ insideLighthouse = true;
1337
+ } else if (log.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {
1338
+ insideLighthouse = false;
1339
+ }
1242
1340
  const match = log.match(re);
1243
1341
  if (match) {
1244
1342
  const code = parseInt(match[1], 16);
1245
1343
  if (!Number.isFinite(code) || code < 0 || code > 4294967295) {
1246
1344
  continue;
1247
1345
  }
1346
+ if (isAnchorErrorCode(code) || insideLighthouse) {
1347
+ const anchorName = ANCHOR_ERROR_NAMES[code] ?? `AnchorError(0x${code.toString(16)})`;
1348
+ return {
1349
+ code,
1350
+ name: `Lighthouse:${anchorName}`,
1351
+ 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).",
1352
+ source: "lighthouse"
1353
+ };
1354
+ }
1248
1355
  const info = decodeError(code);
1249
1356
  return {
1250
1357
  code,
1251
1358
  name: info?.name ?? `Unknown(${code})`,
1252
- hint: info?.hint
1359
+ hint: info?.hint,
1360
+ source: info ? "percolator" : "unknown"
1253
1361
  };
1254
1362
  }
1255
1363
  }
@@ -1416,6 +1524,8 @@ var V2_ENGINE_LP_MAX_ABS_OFF = 536;
1416
1524
  var V2_ENGINE_LP_MAX_ABS_SWEEP_OFF = 552;
1417
1525
  var V_ADL_ENGINE_OFF = 624;
1418
1526
  var V_ADL_CONFIG_LEN = 520;
1527
+ var V_SETDEXPOOL_CONFIG_LEN = 544;
1528
+ var V_SETDEXPOOL_ENGINE_OFF = 648;
1419
1529
  var V_ADL_ACCOUNT_SIZE = 312;
1420
1530
  var V_ADL_ENGINE_PARAMS_OFF = 96;
1421
1531
  var V_ADL_PARAMS_SIZE = 336;
@@ -1446,7 +1556,7 @@ var V_ADL_ENGINE_LP_MAX_ABS_SWEEP_OFF = 952;
1446
1556
  var V_ADL_ENGINE_EMERGENCY_OI_MODE_OFF = 968;
1447
1557
  var V_ADL_ENGINE_EMERGENCY_START_SLOT_OFF = 976;
1448
1558
  var V_ADL_ENGINE_LAST_BREAKER_SLOT_OFF = 984;
1449
- var V_ADL_ENGINE_BITMAP_OFF = 1006;
1559
+ var V_ADL_ENGINE_BITMAP_OFF = 1008;
1450
1560
  var V_ADL_ACCT_WARMUP_STARTED_OFF = 64;
1451
1561
  var V_ADL_ACCT_WARMUP_SLOPE_OFF = 72;
1452
1562
  var V_ADL_ACCT_POSITION_SIZE_OFF = 88;
@@ -1457,6 +1567,47 @@ var V_ADL_ACCT_MATCHER_CONTEXT_OFF = 160;
1457
1567
  var V_ADL_ACCT_OWNER_OFF = 192;
1458
1568
  var V_ADL_ACCT_FEE_CREDITS_OFF = 224;
1459
1569
  var V_ADL_ACCT_LAST_FEE_SLOT_OFF = 240;
1570
+ var V12_1_ENGINE_OFF = 648;
1571
+ var V12_1_ACCOUNT_SIZE = 320;
1572
+ var V12_1_ACCOUNT_SIZE_SBF = 280;
1573
+ var V12_1_ENGINE_BITMAP_OFF = 1016;
1574
+ var V12_1_ENGINE_PARAMS_OFF = 96;
1575
+ var V12_1_PARAMS_SIZE = 352;
1576
+ var V12_1_ENGINE_CURRENT_SLOT_OFF = 448;
1577
+ var V12_1_ENGINE_FUNDING_RATE_BPS_OFF = 456;
1578
+ var V12_1_ENGINE_LAST_CRANK_SLOT_OFF = 464;
1579
+ var V12_1_ENGINE_MAX_CRANK_STALENESS_OFF = 472;
1580
+ var V12_1_ENGINE_C_TOT_OFF = 480;
1581
+ var V12_1_ENGINE_PNL_POS_TOT_OFF = 496;
1582
+ var V12_1_ENGINE_LIQ_CURSOR_OFF = 528;
1583
+ var V12_1_ENGINE_GC_CURSOR_OFF = 530;
1584
+ var V12_1_ENGINE_LAST_SWEEP_START_OFF = 536;
1585
+ var V12_1_ENGINE_LAST_SWEEP_COMPLETE_OFF = 544;
1586
+ var V12_1_ENGINE_CRANK_CURSOR_OFF = 552;
1587
+ var V12_1_ENGINE_SWEEP_START_IDX_OFF = 554;
1588
+ var V12_1_ENGINE_LIFETIME_LIQUIDATIONS_OFF = 560;
1589
+ var V12_1_ENGINE_TOTAL_OI_OFF = 816;
1590
+ var V12_1_ENGINE_LONG_OI_OFF = 832;
1591
+ var V12_1_ENGINE_SHORT_OI_OFF = 848;
1592
+ var V12_1_ENGINE_NET_LP_POS_OFF = 864;
1593
+ var V12_1_ENGINE_LP_SUM_ABS_OFF = 880;
1594
+ var V12_1_ENGINE_LP_MAX_ABS_OFF = 896;
1595
+ var V12_1_ENGINE_LP_MAX_ABS_SWEEP_OFF = 912;
1596
+ var V12_1_ENGINE_MARK_PRICE_OFF = 928;
1597
+ var V12_1_ENGINE_FUNDING_INDEX_OFF = 936;
1598
+ var V12_1_ENGINE_LAST_FUNDING_SLOT_OFF = 944;
1599
+ var V12_1_ENGINE_EMERGENCY_OI_MODE_OFF = 968;
1600
+ var V12_1_ENGINE_EMERGENCY_START_SLOT_OFF = 976;
1601
+ var V12_1_ENGINE_LAST_BREAKER_SLOT_OFF = 984;
1602
+ var V12_1_ENGINE_LIFETIME_FORCE_CLOSES_OFF = 1008;
1603
+ var V12_1_ACCT_MATCHER_PROGRAM_OFF = 144;
1604
+ var V12_1_ACCT_MATCHER_CONTEXT_OFF = 176;
1605
+ var V12_1_ACCT_OWNER_OFF = 208;
1606
+ var V12_1_ACCT_FEE_CREDITS_OFF = 240;
1607
+ var V12_1_ACCT_LAST_FEE_SLOT_OFF = 256;
1608
+ var V12_1_ACCT_POSITION_SIZE_OFF = 88;
1609
+ var V12_1_ACCT_ENTRY_PRICE_OFF = -1;
1610
+ var V12_1_ACCT_FUNDING_INDEX_OFF = 288;
1460
1611
  var V1M_ENGINE_OFF = 640;
1461
1612
  var V1M_CONFIG_LEN = 536;
1462
1613
  var V1M_ACCOUNT_SIZE = 248;
@@ -1494,15 +1645,7 @@ var V1M_ENGINE_EMERGENCY_START_SLOT_OFF = 688;
1494
1645
  var V1M_ENGINE_LAST_BREAKER_SLOT_OFF = 696;
1495
1646
  var V1M_ENGINE_BITMAP_OFF = 720;
1496
1647
  var V1M2_ACCOUNT_SIZE = 312;
1497
- var V1M2_ENGINE_BITMAP_OFF = 990;
1498
- var V1M2_ENGINE_CURRENT_SLOT_OFF = 408;
1499
- var V1M2_ENGINE_FUNDING_INDEX_OFF = 416;
1500
- var V1M2_ENGINE_LAST_FUNDING_SLOT_OFF = 432;
1501
- var V1M2_ENGINE_FUNDING_RATE_BPS_OFF = 440;
1502
- var V1M2_ENGINE_MARK_PRICE_OFF = 480;
1503
- var V1M2_ENGINE_LAST_CRANK_SLOT_OFF = 504;
1504
- var V1M2_ENGINE_MAX_CRANK_STALENESS_OFF = 512;
1505
- var V1M2_RUNTIME_SHIFT = 32;
1648
+ var V1M2_ENGINE_BITMAP_OFF = 1008;
1506
1649
  var ENGINE_OFF = V1_ENGINE_OFF;
1507
1650
  var ENGINE_MARK_PRICE_OFF = V1_ENGINE_MARK_PRICE_OFF;
1508
1651
  function computeSlabSize(engineOff, bitmapOff, accountSize, maxAccounts, postBitmap = 18) {
@@ -1521,6 +1664,9 @@ var V1D_SIZES = /* @__PURE__ */ new Map();
1521
1664
  var V2_SIZES = /* @__PURE__ */ new Map();
1522
1665
  var V1M_SIZES = /* @__PURE__ */ new Map();
1523
1666
  var V_ADL_SIZES = /* @__PURE__ */ new Map();
1667
+ var V1M2_SIZES = /* @__PURE__ */ new Map();
1668
+ var V_SETDEXPOOL_SIZES = /* @__PURE__ */ new Map();
1669
+ var V12_1_SIZES = /* @__PURE__ */ new Map();
1524
1670
  var V1D_SIZES_LEGACY = /* @__PURE__ */ new Map();
1525
1671
  for (const n of TIERS) {
1526
1672
  V0_SIZES.set(computeSlabSize(V0_ENGINE_OFF, V0_ENGINE_BITMAP_OFF, V0_ACCOUNT_SIZE, n), n);
@@ -1531,6 +1677,18 @@ for (const n of TIERS) {
1531
1677
  V2_SIZES.set(computeSlabSize(V2_ENGINE_OFF, V2_ENGINE_BITMAP_OFF, V2_ACCOUNT_SIZE, n, 18), n);
1532
1678
  V1M_SIZES.set(computeSlabSize(V1M_ENGINE_OFF, V1M_ENGINE_BITMAP_OFF, V1M_ACCOUNT_SIZE, n, 18), n);
1533
1679
  V_ADL_SIZES.set(computeSlabSize(V_ADL_ENGINE_OFF, V_ADL_ENGINE_BITMAP_OFF, V_ADL_ACCOUNT_SIZE, n, 18), n);
1680
+ V1M2_SIZES.set(computeSlabSize(V1M2_ENGINE_OFF, V1M2_ENGINE_BITMAP_OFF, V1M2_ACCOUNT_SIZE, n, 18), n);
1681
+ V_SETDEXPOOL_SIZES.set(computeSlabSize(V_SETDEXPOOL_ENGINE_OFF, V_ADL_ENGINE_BITMAP_OFF, V_ADL_ACCOUNT_SIZE, n, 18), n);
1682
+ V12_1_SIZES.set(computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, n, 18), n);
1683
+ }
1684
+ var V12_1_SBF_ACCOUNT_SIZE = 280;
1685
+ var V12_1_SBF_ENGINE_PREAMBLE = 558;
1686
+ for (const [, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Large", 4096]]) {
1687
+ const bitmapBytes = Math.ceil(n / 64) * 8;
1688
+ const preAccLen = V12_1_SBF_ENGINE_PREAMBLE + bitmapBytes + 18 + n * 2;
1689
+ const accountsOff = Math.ceil(preAccLen / 8) * 8;
1690
+ const total = V12_1_ENGINE_OFF + accountsOff + n * V12_1_SBF_ACCOUNT_SIZE;
1691
+ V12_1_SIZES.set(total, n);
1534
1692
  }
1535
1693
  var SLAB_TIERS_V2 = {
1536
1694
  small: { maxAccounts: 256, dataSize: 65088, label: "Small", description: "256 slots (V2 BPF intermediate)" },
@@ -1826,41 +1984,68 @@ function buildLayoutV1M2(maxAccounts) {
1826
1984
  accountsOff: engineOff + accountsOffRel,
1827
1985
  engineInsuranceOff: 16,
1828
1986
  engineParamsOff: V1M2_ENGINE_PARAMS_OFF,
1829
- // 96 — expanded InsuranceFund
1830
- paramsSize: V1M_PARAMS_SIZE,
1831
- // 336 — same as V1M
1832
- // Runtime fields: same as V1M up to fundingRateBps, then +32 shift
1833
- engineCurrentSlotOff: V1M2_ENGINE_CURRENT_SLOT_OFF,
1834
- engineFundingIndexOff: V1M2_ENGINE_FUNDING_INDEX_OFF,
1835
- engineLastFundingSlotOff: V1M2_ENGINE_LAST_FUNDING_SLOT_OFF,
1836
- engineFundingRateBpsOff: V1M2_ENGINE_FUNDING_RATE_BPS_OFF,
1837
- engineMarkPriceOff: V1M2_ENGINE_MARK_PRICE_OFF,
1838
- engineLastCrankSlotOff: V1M2_ENGINE_LAST_CRANK_SLOT_OFF,
1839
- engineMaxCrankStalenessOff: V1M2_ENGINE_MAX_CRANK_STALENESS_OFF,
1840
- // Fields after maxCrankStaleness: apply same +32 shift from V1M
1841
- engineTotalOiOff: V1M_ENGINE_TOTAL_OI_OFF + V1M2_RUNTIME_SHIFT,
1842
- engineLongOiOff: V1M_ENGINE_LONG_OI_OFF + V1M2_RUNTIME_SHIFT,
1843
- engineShortOiOff: V1M_ENGINE_SHORT_OI_OFF + V1M2_RUNTIME_SHIFT,
1844
- engineCTotOff: V1M_ENGINE_C_TOT_OFF + V1M2_RUNTIME_SHIFT,
1845
- enginePnlPosTotOff: V1M_ENGINE_PNL_POS_TOT_OFF + V1M2_RUNTIME_SHIFT,
1846
- engineLiqCursorOff: V1M_ENGINE_LIQ_CURSOR_OFF + V1M2_RUNTIME_SHIFT,
1847
- engineGcCursorOff: V1M_ENGINE_GC_CURSOR_OFF + V1M2_RUNTIME_SHIFT,
1848
- engineLastSweepStartOff: V1M_ENGINE_LAST_SWEEP_START_OFF + V1M2_RUNTIME_SHIFT,
1849
- engineLastSweepCompleteOff: V1M_ENGINE_LAST_SWEEP_COMPLETE_OFF + V1M2_RUNTIME_SHIFT,
1850
- engineCrankCursorOff: V1M_ENGINE_CRANK_CURSOR_OFF + V1M2_RUNTIME_SHIFT,
1851
- engineSweepStartIdxOff: V1M_ENGINE_SWEEP_START_IDX_OFF + V1M2_RUNTIME_SHIFT,
1852
- engineLifetimeLiquidationsOff: V1M_ENGINE_LIFETIME_LIQUIDATIONS_OFF + V1M2_RUNTIME_SHIFT,
1853
- engineLifetimeForceClosesOff: V1M_ENGINE_LIFETIME_FORCE_CLOSES_OFF + V1M2_RUNTIME_SHIFT,
1854
- engineNetLpPosOff: V1M_ENGINE_NET_LP_POS_OFF + V1M2_RUNTIME_SHIFT,
1855
- engineLpSumAbsOff: V1M_ENGINE_LP_SUM_ABS_OFF + V1M2_RUNTIME_SHIFT,
1856
- engineLpMaxAbsOff: V1M_ENGINE_LP_MAX_ABS_OFF + V1M2_RUNTIME_SHIFT,
1857
- engineLpMaxAbsSweepOff: V1M_ENGINE_LP_MAX_ABS_SWEEP_OFF + V1M2_RUNTIME_SHIFT,
1858
- engineEmergencyOiModeOff: V1M_ENGINE_EMERGENCY_OI_MODE_OFF + V1M2_RUNTIME_SHIFT,
1859
- engineEmergencyStartSlotOff: V1M_ENGINE_EMERGENCY_START_SLOT_OFF + V1M2_RUNTIME_SHIFT,
1860
- engineLastBreakerSlotOff: V1M_ENGINE_LAST_BREAKER_SLOT_OFF + V1M2_RUNTIME_SHIFT,
1987
+ // 96 — expanded InsuranceFund (same as V_ADL)
1988
+ paramsSize: V_ADL_PARAMS_SIZE,
1989
+ // 336 — same as V_ADL
1990
+ // Runtime fields: V1M2 engine struct is layout-identical to V_ADL reuse V_ADL constants.
1991
+ engineCurrentSlotOff: V_ADL_ENGINE_CURRENT_SLOT_OFF,
1992
+ // 432
1993
+ engineFundingIndexOff: V_ADL_ENGINE_FUNDING_INDEX_OFF,
1994
+ // 440
1995
+ engineLastFundingSlotOff: V_ADL_ENGINE_LAST_FUNDING_SLOT_OFF,
1996
+ // 456
1997
+ engineFundingRateBpsOff: V_ADL_ENGINE_FUNDING_RATE_BPS_OFF,
1998
+ // 464
1999
+ engineMarkPriceOff: V_ADL_ENGINE_MARK_PRICE_OFF,
2000
+ // 504
2001
+ engineLastCrankSlotOff: V_ADL_ENGINE_LAST_CRANK_SLOT_OFF,
2002
+ // 528
2003
+ engineMaxCrankStalenessOff: V_ADL_ENGINE_MAX_CRANK_STALENESS_OFF,
2004
+ // 536
2005
+ engineTotalOiOff: V_ADL_ENGINE_TOTAL_OI_OFF,
2006
+ // 544
2007
+ engineLongOiOff: V_ADL_ENGINE_LONG_OI_OFF,
2008
+ // 560
2009
+ engineShortOiOff: V_ADL_ENGINE_SHORT_OI_OFF,
2010
+ // 576
2011
+ engineCTotOff: V_ADL_ENGINE_C_TOT_OFF,
2012
+ // 592
2013
+ enginePnlPosTotOff: V_ADL_ENGINE_PNL_POS_TOT_OFF,
2014
+ // 608
2015
+ engineLiqCursorOff: V_ADL_ENGINE_LIQ_CURSOR_OFF,
2016
+ // 640
2017
+ engineGcCursorOff: V_ADL_ENGINE_GC_CURSOR_OFF,
2018
+ // 642
2019
+ engineLastSweepStartOff: V_ADL_ENGINE_LAST_SWEEP_START_OFF,
2020
+ // 648
2021
+ engineLastSweepCompleteOff: V_ADL_ENGINE_LAST_SWEEP_COMPLETE_OFF,
2022
+ // 656
2023
+ engineCrankCursorOff: V_ADL_ENGINE_CRANK_CURSOR_OFF,
2024
+ // 664
2025
+ engineSweepStartIdxOff: V_ADL_ENGINE_SWEEP_START_IDX_OFF,
2026
+ // 666
2027
+ engineLifetimeLiquidationsOff: V_ADL_ENGINE_LIFETIME_LIQUIDATIONS_OFF,
2028
+ // 672
2029
+ engineLifetimeForceClosesOff: V_ADL_ENGINE_LIFETIME_FORCE_CLOSES_OFF,
2030
+ // 680
2031
+ engineNetLpPosOff: V_ADL_ENGINE_NET_LP_POS_OFF,
2032
+ // 904
2033
+ engineLpSumAbsOff: V_ADL_ENGINE_LP_SUM_ABS_OFF,
2034
+ // 920
2035
+ engineLpMaxAbsOff: V_ADL_ENGINE_LP_MAX_ABS_OFF,
2036
+ // 936
2037
+ engineLpMaxAbsSweepOff: V_ADL_ENGINE_LP_MAX_ABS_SWEEP_OFF,
2038
+ // 952
2039
+ engineEmergencyOiModeOff: V_ADL_ENGINE_EMERGENCY_OI_MODE_OFF,
2040
+ // 968
2041
+ engineEmergencyStartSlotOff: V_ADL_ENGINE_EMERGENCY_START_SLOT_OFF,
2042
+ // 976
2043
+ engineLastBreakerSlotOff: V_ADL_ENGINE_LAST_BREAKER_SLOT_OFF,
2044
+ // 984
1861
2045
  engineBitmapOff: V1M2_ENGINE_BITMAP_OFF,
1862
2046
  postBitmap: 18,
1863
- acctOwnerOff: ACCT_OWNER_OFF,
2047
+ acctOwnerOff: V_ADL_ACCT_OWNER_OFF,
2048
+ // 192 — same shift as V_ADL (reserved_pnl u64→u128)
1864
2049
  hasInsuranceIsolation: true,
1865
2050
  engineInsuranceIsolatedOff: 48,
1866
2051
  engineInsuranceIsolationBpsOff: 64
@@ -1950,7 +2135,7 @@ function buildLayoutVADL(maxAccounts) {
1950
2135
  engineLastBreakerSlotOff: V_ADL_ENGINE_LAST_BREAKER_SLOT_OFF,
1951
2136
  // 984
1952
2137
  engineBitmapOff: V_ADL_ENGINE_BITMAP_OFF,
1953
- // 1006
2138
+ // 1008
1954
2139
  postBitmap: 18,
1955
2140
  acctOwnerOff: V_ADL_ACCT_OWNER_OFF,
1956
2141
  // 192
@@ -1959,17 +2144,151 @@ function buildLayoutVADL(maxAccounts) {
1959
2144
  engineInsuranceIsolationBpsOff: 64
1960
2145
  };
1961
2146
  }
2147
+ var SLAB_TIERS_V_SETDEXPOOL = {};
2148
+ for (const [label, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Large", 4096]]) {
2149
+ const size = computeSlabSize(V_SETDEXPOOL_ENGINE_OFF, V_ADL_ENGINE_BITMAP_OFF, V_ADL_ACCOUNT_SIZE, n, 18);
2150
+ SLAB_TIERS_V_SETDEXPOOL[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (V_SETDEXPOOL PERC-SetDexPool)` };
2151
+ }
2152
+ var SLAB_TIERS_V12_1 = {};
2153
+ for (const [label, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Large", 4096]]) {
2154
+ const size = computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, n, 18);
2155
+ SLAB_TIERS_V12_1[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (v12.1)` };
2156
+ }
2157
+ function buildLayoutVSetDexPool(maxAccounts) {
2158
+ const engineOff = V_SETDEXPOOL_ENGINE_OFF;
2159
+ const bitmapOff = V_ADL_ENGINE_BITMAP_OFF;
2160
+ const accountSize = V_ADL_ACCOUNT_SIZE;
2161
+ const bitmapWords = Math.ceil(maxAccounts / 64);
2162
+ const bitmapBytes = bitmapWords * 8;
2163
+ const postBitmap = 18;
2164
+ const nextFreeBytes = maxAccounts * 2;
2165
+ const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;
2166
+ const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;
2167
+ return {
2168
+ version: 1,
2169
+ headerLen: V1_HEADER_LEN,
2170
+ configOffset: V1_HEADER_LEN,
2171
+ configLen: V_SETDEXPOOL_CONFIG_LEN,
2172
+ // 544
2173
+ reservedOff: V1_RESERVED_OFF,
2174
+ engineOff,
2175
+ accountSize,
2176
+ maxAccounts,
2177
+ bitmapWords,
2178
+ accountsOff: engineOff + accountsOffRel,
2179
+ engineInsuranceOff: 16,
2180
+ engineParamsOff: V_ADL_ENGINE_PARAMS_OFF,
2181
+ paramsSize: V_ADL_PARAMS_SIZE,
2182
+ engineCurrentSlotOff: V_ADL_ENGINE_CURRENT_SLOT_OFF,
2183
+ engineFundingIndexOff: V_ADL_ENGINE_FUNDING_INDEX_OFF,
2184
+ engineLastFundingSlotOff: V_ADL_ENGINE_LAST_FUNDING_SLOT_OFF,
2185
+ engineFundingRateBpsOff: V_ADL_ENGINE_FUNDING_RATE_BPS_OFF,
2186
+ engineMarkPriceOff: V_ADL_ENGINE_MARK_PRICE_OFF,
2187
+ engineLastCrankSlotOff: V_ADL_ENGINE_LAST_CRANK_SLOT_OFF,
2188
+ engineMaxCrankStalenessOff: V_ADL_ENGINE_MAX_CRANK_STALENESS_OFF,
2189
+ engineTotalOiOff: V_ADL_ENGINE_TOTAL_OI_OFF,
2190
+ engineLongOiOff: V_ADL_ENGINE_LONG_OI_OFF,
2191
+ engineShortOiOff: V_ADL_ENGINE_SHORT_OI_OFF,
2192
+ engineCTotOff: V_ADL_ENGINE_C_TOT_OFF,
2193
+ enginePnlPosTotOff: V_ADL_ENGINE_PNL_POS_TOT_OFF,
2194
+ engineLiqCursorOff: V_ADL_ENGINE_LIQ_CURSOR_OFF,
2195
+ engineGcCursorOff: V_ADL_ENGINE_GC_CURSOR_OFF,
2196
+ engineLastSweepStartOff: V_ADL_ENGINE_LAST_SWEEP_START_OFF,
2197
+ engineLastSweepCompleteOff: V_ADL_ENGINE_LAST_SWEEP_COMPLETE_OFF,
2198
+ engineCrankCursorOff: V_ADL_ENGINE_CRANK_CURSOR_OFF,
2199
+ engineSweepStartIdxOff: V_ADL_ENGINE_SWEEP_START_IDX_OFF,
2200
+ engineLifetimeLiquidationsOff: V_ADL_ENGINE_LIFETIME_LIQUIDATIONS_OFF,
2201
+ engineLifetimeForceClosesOff: V_ADL_ENGINE_LIFETIME_FORCE_CLOSES_OFF,
2202
+ engineNetLpPosOff: V_ADL_ENGINE_NET_LP_POS_OFF,
2203
+ engineLpSumAbsOff: V_ADL_ENGINE_LP_SUM_ABS_OFF,
2204
+ engineLpMaxAbsOff: V_ADL_ENGINE_LP_MAX_ABS_OFF,
2205
+ engineLpMaxAbsSweepOff: V_ADL_ENGINE_LP_MAX_ABS_SWEEP_OFF,
2206
+ engineEmergencyOiModeOff: V_ADL_ENGINE_EMERGENCY_OI_MODE_OFF,
2207
+ engineEmergencyStartSlotOff: V_ADL_ENGINE_EMERGENCY_START_SLOT_OFF,
2208
+ engineLastBreakerSlotOff: V_ADL_ENGINE_LAST_BREAKER_SLOT_OFF,
2209
+ engineBitmapOff: V_ADL_ENGINE_BITMAP_OFF,
2210
+ postBitmap: 18,
2211
+ acctOwnerOff: V_ADL_ACCT_OWNER_OFF,
2212
+ hasInsuranceIsolation: true,
2213
+ engineInsuranceIsolatedOff: 48,
2214
+ engineInsuranceIsolationBpsOff: 64
2215
+ };
2216
+ }
2217
+ function buildLayoutV12_1(maxAccounts, dataLen) {
2218
+ const engineOff = V12_1_ENGINE_OFF;
2219
+ const bitmapOff = V12_1_ENGINE_BITMAP_OFF;
2220
+ const hostSize = computeSlabSize(engineOff, bitmapOff, V12_1_ACCOUNT_SIZE, maxAccounts, 18);
2221
+ const isSbf = dataLen !== void 0 && dataLen !== hostSize;
2222
+ const accountSize = isSbf ? V12_1_ACCOUNT_SIZE_SBF : V12_1_ACCOUNT_SIZE;
2223
+ const bitmapWords = Math.ceil(maxAccounts / 64);
2224
+ const bitmapBytes = bitmapWords * 8;
2225
+ const postBitmap = 18;
2226
+ const nextFreeBytes = maxAccounts * 2;
2227
+ const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;
2228
+ const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;
2229
+ return {
2230
+ version: 1,
2231
+ // V12_1 upstream rebase uses 72-byte header (SlabHeader only, no V1 extension).
2232
+ // Empirically verified: USDC mint found at offset 72 on mainnet slab BVjPc6rd.
2233
+ headerLen: V0_HEADER_LEN,
2234
+ // 72 (not 104 — V12_1 removed the 32-byte header extension)
2235
+ configOffset: V0_HEADER_LEN,
2236
+ // 72
2237
+ configLen: 576,
2238
+ // 544 + 32 (dex_pool: [u8;32] added in V12_1)
2239
+ reservedOff: V1_RESERVED_OFF,
2240
+ engineOff,
2241
+ accountSize,
2242
+ maxAccounts,
2243
+ bitmapWords,
2244
+ accountsOff: engineOff + accountsOffRel,
2245
+ engineInsuranceOff: 16,
2246
+ engineParamsOff: V12_1_ENGINE_PARAMS_OFF,
2247
+ paramsSize: V12_1_PARAMS_SIZE,
2248
+ engineCurrentSlotOff: V12_1_ENGINE_CURRENT_SLOT_OFF,
2249
+ engineFundingIndexOff: V12_1_ENGINE_FUNDING_INDEX_OFF,
2250
+ engineLastFundingSlotOff: V12_1_ENGINE_LAST_FUNDING_SLOT_OFF,
2251
+ engineFundingRateBpsOff: V12_1_ENGINE_FUNDING_RATE_BPS_OFF,
2252
+ engineMarkPriceOff: V12_1_ENGINE_MARK_PRICE_OFF,
2253
+ engineLastCrankSlotOff: V12_1_ENGINE_LAST_CRANK_SLOT_OFF,
2254
+ engineMaxCrankStalenessOff: V12_1_ENGINE_MAX_CRANK_STALENESS_OFF,
2255
+ engineTotalOiOff: V12_1_ENGINE_TOTAL_OI_OFF,
2256
+ engineLongOiOff: V12_1_ENGINE_LONG_OI_OFF,
2257
+ engineShortOiOff: V12_1_ENGINE_SHORT_OI_OFF,
2258
+ engineCTotOff: V12_1_ENGINE_C_TOT_OFF,
2259
+ enginePnlPosTotOff: V12_1_ENGINE_PNL_POS_TOT_OFF,
2260
+ engineLiqCursorOff: V12_1_ENGINE_LIQ_CURSOR_OFF,
2261
+ engineGcCursorOff: V12_1_ENGINE_GC_CURSOR_OFF,
2262
+ engineLastSweepStartOff: V12_1_ENGINE_LAST_SWEEP_START_OFF,
2263
+ engineLastSweepCompleteOff: V12_1_ENGINE_LAST_SWEEP_COMPLETE_OFF,
2264
+ engineCrankCursorOff: V12_1_ENGINE_CRANK_CURSOR_OFF,
2265
+ engineSweepStartIdxOff: V12_1_ENGINE_SWEEP_START_IDX_OFF,
2266
+ engineLifetimeLiquidationsOff: V12_1_ENGINE_LIFETIME_LIQUIDATIONS_OFF,
2267
+ engineLifetimeForceClosesOff: V12_1_ENGINE_LIFETIME_FORCE_CLOSES_OFF,
2268
+ engineNetLpPosOff: V12_1_ENGINE_NET_LP_POS_OFF,
2269
+ engineLpSumAbsOff: V12_1_ENGINE_LP_SUM_ABS_OFF,
2270
+ engineLpMaxAbsOff: V12_1_ENGINE_LP_MAX_ABS_OFF,
2271
+ engineLpMaxAbsSweepOff: V12_1_ENGINE_LP_MAX_ABS_SWEEP_OFF,
2272
+ engineEmergencyOiModeOff: V12_1_ENGINE_EMERGENCY_OI_MODE_OFF,
2273
+ engineEmergencyStartSlotOff: V12_1_ENGINE_EMERGENCY_START_SLOT_OFF,
2274
+ engineLastBreakerSlotOff: V12_1_ENGINE_LAST_BREAKER_SLOT_OFF,
2275
+ engineBitmapOff: V12_1_ENGINE_BITMAP_OFF,
2276
+ postBitmap: 18,
2277
+ acctOwnerOff: V12_1_ACCT_OWNER_OFF,
2278
+ hasInsuranceIsolation: true,
2279
+ engineInsuranceIsolatedOff: 48,
2280
+ engineInsuranceIsolationBpsOff: 64
2281
+ };
2282
+ }
1962
2283
  function detectSlabLayout(dataLen, data) {
2284
+ const v121n = V12_1_SIZES.get(dataLen);
2285
+ if (v121n !== void 0) return buildLayoutV12_1(v121n, dataLen);
2286
+ const vsdpn = V_SETDEXPOOL_SIZES.get(dataLen);
2287
+ if (vsdpn !== void 0) return buildLayoutVSetDexPool(vsdpn);
2288
+ const v1m2n = V1M2_SIZES.get(dataLen);
2289
+ if (v1m2n !== void 0) return buildLayoutV1M2(v1m2n);
1963
2290
  const vadln = V_ADL_SIZES.get(dataLen);
1964
- if (vadln !== void 0) {
1965
- if (data && data.length >= 752) {
1966
- const maxAcctsV1M2 = readU64LE(data, V1M2_ENGINE_OFF + V1M2_ENGINE_PARAMS_OFF + 32);
1967
- if (maxAcctsV1M2 === BigInt(vadln)) {
1968
- return buildLayoutV1M2(vadln);
1969
- }
1970
- }
1971
- return buildLayoutVADL(vadln);
1972
- }
2291
+ if (vadln !== void 0) return buildLayoutVADL(vadln);
1973
2292
  const v1mn = V1M_SIZES.get(dataLen);
1974
2293
  if (v1mn !== void 0) return buildLayoutV1M(v1mn);
1975
2294
  const v0n = V0_SIZES.get(dataLen);
@@ -2130,14 +2449,6 @@ function parseConfig(data, layoutHint) {
2130
2449
  off += 8;
2131
2450
  const fundingMaxBpsPerSlot = readI64LE(data, off);
2132
2451
  off += 8;
2133
- const fundingPremiumWeightBps = readU64LE(data, off);
2134
- off += 8;
2135
- const fundingSettlementIntervalSlots = readU64LE(data, off);
2136
- off += 8;
2137
- const fundingPremiumDampeningE6 = readU64LE(data, off);
2138
- off += 8;
2139
- const fundingPremiumMaxBpsPerSlot = readU64LE(data, off);
2140
- off += 8;
2141
2452
  const threshFloor = readU128LE(data, off);
2142
2453
  off += 16;
2143
2454
  const threshRiskBps = readU64LE(data, off);
@@ -2202,6 +2513,14 @@ function parseConfig(data, layoutHint) {
2202
2513
  }
2203
2514
  }
2204
2515
  }
2516
+ let dexPool = null;
2517
+ const DEX_POOL_REL_OFF = 512;
2518
+ if (configLen >= DEX_POOL_REL_OFF + 32 && data.length >= configOff + DEX_POOL_REL_OFF + 32) {
2519
+ const dexPoolBytes = data.subarray(configOff + DEX_POOL_REL_OFF, configOff + DEX_POOL_REL_OFF + 32);
2520
+ if (dexPoolBytes.some((b) => b !== 0)) {
2521
+ dexPool = new PublicKey3(dexPoolBytes);
2522
+ }
2523
+ }
2205
2524
  return {
2206
2525
  collateralMint,
2207
2526
  vaultPubkey,
@@ -2216,10 +2535,10 @@ function parseConfig(data, layoutHint) {
2216
2535
  fundingInvScaleNotionalE6,
2217
2536
  fundingMaxPremiumBps,
2218
2537
  fundingMaxBpsPerSlot,
2219
- fundingPremiumWeightBps,
2220
- fundingSettlementIntervalSlots,
2221
- fundingPremiumDampeningE6,
2222
- fundingPremiumMaxBpsPerSlot,
2538
+ fundingPremiumWeightBps: 0n,
2539
+ fundingSettlementIntervalSlots: 0n,
2540
+ fundingPremiumDampeningE6: 0n,
2541
+ fundingPremiumMaxBpsPerSlot: 0n,
2223
2542
  threshFloor,
2224
2543
  threshRiskBps,
2225
2544
  threshUpdateIntervalSlots,
@@ -2244,7 +2563,8 @@ function parseConfig(data, layoutHint) {
2244
2563
  insuranceIsolationBps,
2245
2564
  oraclePhase,
2246
2565
  cumulativeVolumeE6,
2247
- phase2DeltaSlots
2566
+ phase2DeltaSlots,
2567
+ dexPool
2248
2568
  };
2249
2569
  }
2250
2570
  function parseParams(data, layoutHint) {
@@ -2384,16 +2704,17 @@ function parseAccount(data, idx) {
2384
2704
  if (data.length < base + layout.accountSize) {
2385
2705
  throw new Error("Slab data too short for account");
2386
2706
  }
2387
- const isAdl = layout.accountSize >= 312;
2707
+ const isV12_1 = layout.engineOff === V12_1_ENGINE_OFF && (layout.accountSize === V12_1_ACCOUNT_SIZE || layout.accountSize === V12_1_ACCOUNT_SIZE_SBF);
2708
+ const isAdl = layout.accountSize >= 312 || isV12_1;
2388
2709
  const warmupStartedOff = isAdl ? V_ADL_ACCT_WARMUP_STARTED_OFF : ACCT_WARMUP_STARTED_OFF;
2389
2710
  const warmupSlopeOff = isAdl ? V_ADL_ACCT_WARMUP_SLOPE_OFF : ACCT_WARMUP_SLOPE_OFF;
2390
- const positionSizeOff = isAdl ? V_ADL_ACCT_POSITION_SIZE_OFF : ACCT_POSITION_SIZE_OFF;
2391
- const entryPriceOff = isAdl ? V_ADL_ACCT_ENTRY_PRICE_OFF : ACCT_ENTRY_PRICE_OFF;
2392
- const fundingIndexOff = isAdl ? V_ADL_ACCT_FUNDING_INDEX_OFF : ACCT_FUNDING_INDEX_OFF;
2393
- const matcherProgOff = isAdl ? V_ADL_ACCT_MATCHER_PROGRAM_OFF : ACCT_MATCHER_PROGRAM_OFF;
2394
- const matcherCtxOff = isAdl ? V_ADL_ACCT_MATCHER_CONTEXT_OFF : ACCT_MATCHER_CONTEXT_OFF;
2395
- const feeCreditsOff = isAdl ? V_ADL_ACCT_FEE_CREDITS_OFF : ACCT_FEE_CREDITS_OFF;
2396
- const lastFeeSlotOff = isAdl ? V_ADL_ACCT_LAST_FEE_SLOT_OFF : ACCT_LAST_FEE_SLOT_OFF;
2711
+ const positionSizeOff = isV12_1 ? V12_1_ACCT_POSITION_SIZE_OFF : isAdl ? V_ADL_ACCT_POSITION_SIZE_OFF : ACCT_POSITION_SIZE_OFF;
2712
+ const entryPriceOff = isV12_1 ? V12_1_ACCT_ENTRY_PRICE_OFF : isAdl ? V_ADL_ACCT_ENTRY_PRICE_OFF : ACCT_ENTRY_PRICE_OFF;
2713
+ const fundingIndexOff = isV12_1 ? V12_1_ACCT_FUNDING_INDEX_OFF : isAdl ? V_ADL_ACCT_FUNDING_INDEX_OFF : ACCT_FUNDING_INDEX_OFF;
2714
+ const matcherProgOff = isV12_1 ? V12_1_ACCT_MATCHER_PROGRAM_OFF : isAdl ? V_ADL_ACCT_MATCHER_PROGRAM_OFF : ACCT_MATCHER_PROGRAM_OFF;
2715
+ const matcherCtxOff = isV12_1 ? V12_1_ACCT_MATCHER_CONTEXT_OFF : isAdl ? V_ADL_ACCT_MATCHER_CONTEXT_OFF : ACCT_MATCHER_CONTEXT_OFF;
2716
+ const feeCreditsOff = isV12_1 ? V12_1_ACCT_FEE_CREDITS_OFF : isAdl ? V_ADL_ACCT_FEE_CREDITS_OFF : ACCT_FEE_CREDITS_OFF;
2717
+ const lastFeeSlotOff = isV12_1 ? V12_1_ACCT_LAST_FEE_SLOT_OFF : isAdl ? V_ADL_ACCT_LAST_FEE_SLOT_OFF : ACCT_LAST_FEE_SLOT_OFF;
2397
2718
  const kindByte = readU8(data, base + ACCT_KIND_OFF);
2398
2719
  const kind = kindByte === 1 ? 1 /* LP */ : 0 /* User */;
2399
2720
  return {
@@ -2405,8 +2726,10 @@ function parseAccount(data, idx) {
2405
2726
  warmupStartedAtSlot: readU64LE(data, base + warmupStartedOff),
2406
2727
  warmupSlopePerStep: readU128LE(data, base + warmupSlopeOff),
2407
2728
  positionSize: readI128LE(data, base + positionSizeOff),
2408
- entryPrice: readU64LE(data, base + entryPriceOff),
2409
- fundingIndex: readI128LE(data, base + fundingIndexOff),
2729
+ entryPrice: entryPriceOff >= 0 ? readU64LE(data, base + entryPriceOff) : 0n,
2730
+ // V12_1: entry_price removed
2731
+ // V12_1 changed funding_index from i128 to i64 (legacy field moved to end of account)
2732
+ fundingIndex: isV12_1 ? BigInt(readI64LE(data, base + fundingIndexOff)) : readI128LE(data, base + fundingIndexOff),
2410
2733
  matcherProgram: new PublicKey3(data.subarray(base + matcherProgOff, base + matcherProgOff + 32)),
2411
2734
  matcherContext: new PublicKey3(data.subarray(base + matcherCtxOff, base + matcherCtxOff + 32)),
2412
2735
  owner: new PublicKey3(data.subarray(base + layout.acctOwnerOff, base + layout.acctOwnerOff + 32)),
@@ -2439,12 +2762,6 @@ function deriveVaultAuthority(programId, slab) {
2439
2762
  programId
2440
2763
  );
2441
2764
  }
2442
- function deriveInsuranceLpMint(programId, slab) {
2443
- return PublicKey4.findProgramAddressSync(
2444
- [textEncoder.encode("ins_lp"), slab.toBytes()],
2445
- programId
2446
- );
2447
- }
2448
2765
  var LP_INDEX_U16_MAX = 65535;
2449
2766
  function deriveLpPda(programId, slab, lpIdx) {
2450
2767
  if (typeof lpIdx !== "number" || !Number.isInteger(lpIdx) || lpIdx < 0 || lpIdx > LP_INDEX_U16_MAX) {
@@ -2501,7 +2818,14 @@ function derivePythPushOraclePDA(feedIdHex) {
2501
2818
  }
2502
2819
  const feedId = new Uint8Array(32);
2503
2820
  for (let i = 0; i < 32; i++) {
2504
- feedId[i] = parseInt(normalized.substring(i * 2, i * 2 + 2), 16);
2821
+ const hexPair = normalized.substring(i * 2, i * 2 + 2);
2822
+ const byte = parseInt(hexPair, 16);
2823
+ if (Number.isNaN(byte)) {
2824
+ throw new Error(
2825
+ `derivePythPushOraclePDA: failed to parse hex byte at position ${i}: "${hexPair}"`
2826
+ );
2827
+ }
2828
+ feedId[i] = byte;
2505
2829
  }
2506
2830
  const shardBuf = new Uint8Array(2);
2507
2831
  return PublicKey4.findProgramAddressSync(
@@ -2527,13 +2851,76 @@ async function fetchTokenAccount(connection, address, tokenProgramId = TOKEN_PRO
2527
2851
  return getAccount(connection, address, void 0, tokenProgramId);
2528
2852
  }
2529
2853
 
2854
+ // src/solana/discovery.ts
2855
+ import { PublicKey as PublicKey6 } from "@solana/web3.js";
2856
+
2857
+ // src/solana/static-markets.ts
2858
+ import { PublicKey as PublicKey5 } from "@solana/web3.js";
2859
+ var MAINNET_MARKETS = [
2860
+ // Populated at mainnet launch — currently empty.
2861
+ // To add entries:
2862
+ // { slabAddress: "ABC123...", symbol: "SOL-PERP", name: "SOL Perpetual" },
2863
+ ];
2864
+ var DEVNET_MARKETS = [
2865
+ // Populated from prior discoverMarkets() runs on devnet.
2866
+ // These serve as the tier-3 safety net for devnet users.
2867
+ ];
2868
+ var STATIC_REGISTRY = {
2869
+ mainnet: MAINNET_MARKETS,
2870
+ devnet: DEVNET_MARKETS
2871
+ };
2872
+ var USER_MARKETS = {
2873
+ mainnet: [],
2874
+ devnet: []
2875
+ };
2876
+ function getStaticMarkets(network) {
2877
+ const builtin = STATIC_REGISTRY[network] ?? [];
2878
+ const user = USER_MARKETS[network] ?? [];
2879
+ if (user.length === 0) return [...builtin];
2880
+ const seen = /* @__PURE__ */ new Map();
2881
+ for (const entry of builtin) {
2882
+ seen.set(entry.slabAddress, entry);
2883
+ }
2884
+ for (const entry of user) {
2885
+ seen.set(entry.slabAddress, entry);
2886
+ }
2887
+ return [...seen.values()];
2888
+ }
2889
+ function registerStaticMarkets(network, entries) {
2890
+ const existing = USER_MARKETS[network];
2891
+ const seen = new Set(existing.map((e) => e.slabAddress));
2892
+ for (const entry of entries) {
2893
+ if (!entry.slabAddress) continue;
2894
+ if (seen.has(entry.slabAddress)) continue;
2895
+ try {
2896
+ new PublicKey5(entry.slabAddress);
2897
+ } catch {
2898
+ console.warn(
2899
+ `[registerStaticMarkets] Skipping invalid slabAddress: ${entry.slabAddress}`
2900
+ );
2901
+ continue;
2902
+ }
2903
+ seen.add(entry.slabAddress);
2904
+ existing.push(entry);
2905
+ }
2906
+ }
2907
+ function clearStaticMarkets(network) {
2908
+ if (network) {
2909
+ USER_MARKETS[network] = [];
2910
+ } else {
2911
+ USER_MARKETS.mainnet = [];
2912
+ USER_MARKETS.devnet = [];
2913
+ }
2914
+ }
2915
+
2530
2916
  // src/solana/discovery.ts
2531
2917
  var ENGINE_BITMAP_OFF_V0 = 320;
2532
2918
  var MAGIC_BYTES = new Uint8Array([84, 65, 76, 79, 67, 82, 69, 80]);
2533
2919
  var SLAB_TIERS = {
2534
- small: { maxAccounts: 256, dataSize: 65352, label: "Small", description: "256 slots \xB7 ~0.45 SOL" },
2535
- medium: { maxAccounts: 1024, dataSize: 257448, label: "Medium", description: "1,024 slots \xB7 ~1.79 SOL" },
2536
- large: { maxAccounts: 4096, dataSize: 1025832, label: "Large", description: "4,096 slots \xB7 ~7.14 SOL" }
2920
+ micro: SLAB_TIERS_V12_1["micro"],
2921
+ small: SLAB_TIERS_V12_1["small"],
2922
+ medium: SLAB_TIERS_V12_1["medium"],
2923
+ large: SLAB_TIERS_V12_1["large"]
2537
2924
  };
2538
2925
  var SLAB_TIERS_V0 = {
2539
2926
  small: { maxAccounts: 256, dataSize: 62808, label: "Small", description: "256 slots \xB7 ~0.44 SOL" },
@@ -2911,22 +3298,77 @@ async function discoverMarkets(connection, programId, options = {}) {
2911
3298
  "[discoverMarkets] dataSize filters failed, falling back to memcmp:",
2912
3299
  err instanceof Error ? err.message : err
2913
3300
  );
2914
- const fallback = await connection.getProgramAccounts(programId, {
2915
- filters: [
2916
- {
2917
- memcmp: {
2918
- offset: 0,
2919
- bytes: "F6P2QNqpQV5"
2920
- // base58 of TALOCREP (u64 LE magic)
3301
+ try {
3302
+ const fallback = await connection.getProgramAccounts(programId, {
3303
+ filters: [
3304
+ {
3305
+ memcmp: {
3306
+ offset: 0,
3307
+ bytes: "F6P2QNqpQV5"
3308
+ // base58 of TALOCREP (u64 LE magic)
3309
+ }
2921
3310
  }
2922
- }
2923
- ],
2924
- dataSlice: { offset: 0, length: HEADER_SLICE_LENGTH }
2925
- });
2926
- rawAccounts = [...fallback].map((e) => ({ ...e, maxAccounts: 4096, dataSize: SLAB_TIERS.large.dataSize }));
3311
+ ],
3312
+ dataSlice: { offset: 0, length: HEADER_SLICE_LENGTH }
3313
+ });
3314
+ rawAccounts = [...fallback].map((e) => ({ ...e, maxAccounts: 4096, dataSize: SLAB_TIERS.large.dataSize }));
3315
+ } catch (memcmpErr) {
3316
+ console.warn(
3317
+ "[discoverMarkets] memcmp fallback also failed:",
3318
+ memcmpErr instanceof Error ? memcmpErr.message : memcmpErr
3319
+ );
3320
+ }
2927
3321
  }
2928
- const accounts = rawAccounts;
2929
- const markets = [];
3322
+ if (rawAccounts.length === 0 && options.apiBaseUrl) {
3323
+ console.warn(
3324
+ "[discoverMarkets] RPC discovery returned 0 markets, falling back to REST API"
3325
+ );
3326
+ try {
3327
+ const apiResult = await discoverMarketsViaApi(
3328
+ connection,
3329
+ programId,
3330
+ options.apiBaseUrl,
3331
+ { timeoutMs: options.apiTimeoutMs }
3332
+ );
3333
+ if (apiResult.length > 0) {
3334
+ return apiResult;
3335
+ }
3336
+ console.warn(
3337
+ "[discoverMarkets] REST API returned 0 markets, checking tier-3 static bundle"
3338
+ );
3339
+ } catch (apiErr) {
3340
+ console.warn(
3341
+ "[discoverMarkets] API fallback also failed:",
3342
+ apiErr instanceof Error ? apiErr.message : apiErr
3343
+ );
3344
+ }
3345
+ }
3346
+ if (rawAccounts.length === 0 && options.network) {
3347
+ const staticEntries = getStaticMarkets(options.network);
3348
+ if (staticEntries.length > 0) {
3349
+ console.warn(
3350
+ `[discoverMarkets] Tier 1+2 failed, falling back to static bundle (${staticEntries.length} addresses for ${options.network})`
3351
+ );
3352
+ try {
3353
+ return await discoverMarketsViaStaticBundle(
3354
+ connection,
3355
+ programId,
3356
+ staticEntries
3357
+ );
3358
+ } catch (staticErr) {
3359
+ console.warn(
3360
+ "[discoverMarkets] Static bundle fallback also failed:",
3361
+ staticErr instanceof Error ? staticErr.message : staticErr
3362
+ );
3363
+ }
3364
+ } else {
3365
+ console.warn(
3366
+ `[discoverMarkets] Static bundle has 0 entries for ${options.network} \u2014 skipping tier 3`
3367
+ );
3368
+ }
3369
+ }
3370
+ const accounts = rawAccounts;
3371
+ const markets = [];
2930
3372
  const seenPubkeys = /* @__PURE__ */ new Set();
2931
3373
  for (const { pubkey, account, maxAccounts, dataSize } of accounts) {
2932
3374
  const pkStr = pubkey.toBase58();
@@ -2963,9 +3405,145 @@ async function discoverMarkets(connection, programId, options = {}) {
2963
3405
  }
2964
3406
  return markets;
2965
3407
  }
3408
+ async function getMarketsByAddress(connection, programId, addresses, options = {}) {
3409
+ if (addresses.length === 0) return [];
3410
+ const {
3411
+ batchSize = 100,
3412
+ interBatchDelayMs = 0
3413
+ } = options;
3414
+ const effectiveBatchSize = Math.max(1, Math.min(batchSize, 100));
3415
+ const fetched = [];
3416
+ for (let offset = 0; offset < addresses.length; offset += effectiveBatchSize) {
3417
+ const batch = addresses.slice(offset, offset + effectiveBatchSize);
3418
+ const response = await connection.getMultipleAccountsInfo(batch);
3419
+ for (let i = 0; i < batch.length; i++) {
3420
+ const info = response[i];
3421
+ if (info && info.data) {
3422
+ if (!info.owner.equals(programId)) {
3423
+ console.warn(
3424
+ `[getMarketsByAddress] Skipping ${batch[i].toBase58()}: owner mismatch (expected ${programId.toBase58()}, got ${info.owner.toBase58()})`
3425
+ );
3426
+ continue;
3427
+ }
3428
+ fetched.push({ pubkey: batch[i], data: info.data });
3429
+ }
3430
+ }
3431
+ if (interBatchDelayMs > 0 && offset + effectiveBatchSize < addresses.length) {
3432
+ await new Promise((r) => setTimeout(r, interBatchDelayMs));
3433
+ }
3434
+ }
3435
+ const markets = [];
3436
+ for (const entry of fetched) {
3437
+ if (!entry) continue;
3438
+ const { pubkey, data: rawData } = entry;
3439
+ const data = new Uint8Array(rawData);
3440
+ let valid = true;
3441
+ for (let i = 0; i < MAGIC_BYTES.length; i++) {
3442
+ if (data[i] !== MAGIC_BYTES[i]) {
3443
+ valid = false;
3444
+ break;
3445
+ }
3446
+ }
3447
+ if (!valid) {
3448
+ console.warn(
3449
+ `[getMarketsByAddress] Skipping ${pubkey.toBase58()}: invalid magic bytes`
3450
+ );
3451
+ continue;
3452
+ }
3453
+ const layout = detectSlabLayout(data.length, data);
3454
+ if (!layout) {
3455
+ console.warn(
3456
+ `[getMarketsByAddress] Skipping ${pubkey.toBase58()}: unrecognized layout for dataSize=${data.length}`
3457
+ );
3458
+ continue;
3459
+ }
3460
+ try {
3461
+ const header = parseHeader(data);
3462
+ const config = parseConfig(data, layout);
3463
+ const engine = parseEngineLight(data, layout, layout.maxAccounts);
3464
+ const params = parseParams(data, layout);
3465
+ markets.push({ slabAddress: pubkey, programId, header, config, engine, params });
3466
+ } catch (err) {
3467
+ console.warn(
3468
+ `[getMarketsByAddress] Failed to parse account ${pubkey.toBase58()}:`,
3469
+ err instanceof Error ? err.message : err
3470
+ );
3471
+ }
3472
+ }
3473
+ return markets;
3474
+ }
3475
+ async function discoverMarketsViaApi(connection, programId, apiBaseUrl, options = {}) {
3476
+ const { timeoutMs = 1e4, onChainOptions } = options;
3477
+ const base = apiBaseUrl.replace(/\/+$/, "");
3478
+ const url = `${base}/markets`;
3479
+ const controller = new AbortController();
3480
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
3481
+ let response;
3482
+ try {
3483
+ response = await fetch(url, {
3484
+ method: "GET",
3485
+ headers: { Accept: "application/json" },
3486
+ signal: controller.signal
3487
+ });
3488
+ } finally {
3489
+ clearTimeout(timer);
3490
+ }
3491
+ if (!response.ok) {
3492
+ throw new Error(
3493
+ `[discoverMarketsViaApi] API returned ${response.status} ${response.statusText} from ${url}`
3494
+ );
3495
+ }
3496
+ const body = await response.json();
3497
+ const apiMarkets = body.markets;
3498
+ if (!Array.isArray(apiMarkets) || apiMarkets.length === 0) {
3499
+ console.warn("[discoverMarketsViaApi] API returned 0 markets");
3500
+ return [];
3501
+ }
3502
+ const addresses = [];
3503
+ for (const entry of apiMarkets) {
3504
+ if (!entry.slab_address || typeof entry.slab_address !== "string") continue;
3505
+ try {
3506
+ addresses.push(new PublicKey6(entry.slab_address));
3507
+ } catch {
3508
+ console.warn(
3509
+ `[discoverMarketsViaApi] Skipping invalid slab address: ${entry.slab_address}`
3510
+ );
3511
+ }
3512
+ }
3513
+ if (addresses.length === 0) {
3514
+ console.warn("[discoverMarketsViaApi] No valid slab addresses from API");
3515
+ return [];
3516
+ }
3517
+ console.log(
3518
+ `[discoverMarketsViaApi] API returned ${addresses.length} slab addresses, fetching on-chain data`
3519
+ );
3520
+ return getMarketsByAddress(connection, programId, addresses, onChainOptions);
3521
+ }
3522
+ async function discoverMarketsViaStaticBundle(connection, programId, entries, options = {}) {
3523
+ if (entries.length === 0) return [];
3524
+ const addresses = [];
3525
+ for (const entry of entries) {
3526
+ if (!entry.slabAddress || typeof entry.slabAddress !== "string") continue;
3527
+ try {
3528
+ addresses.push(new PublicKey6(entry.slabAddress));
3529
+ } catch {
3530
+ console.warn(
3531
+ `[discoverMarketsViaStaticBundle] Skipping invalid slab address: ${entry.slabAddress}`
3532
+ );
3533
+ }
3534
+ }
3535
+ if (addresses.length === 0) {
3536
+ console.warn("[discoverMarketsViaStaticBundle] No valid slab addresses in static bundle");
3537
+ return [];
3538
+ }
3539
+ console.log(
3540
+ `[discoverMarketsViaStaticBundle] Fetching ${addresses.length} slab addresses on-chain`
3541
+ );
3542
+ return getMarketsByAddress(connection, programId, addresses, options.onChainOptions);
3543
+ }
2966
3544
 
2967
3545
  // src/solana/dex-oracle.ts
2968
- import { PublicKey as PublicKey5 } from "@solana/web3.js";
3546
+ import { PublicKey as PublicKey7 } from "@solana/web3.js";
2969
3547
  function detectDexType(ownerProgramId) {
2970
3548
  if (ownerProgramId.equals(PUMPSWAP_PROGRAM_ID)) return "pumpswap";
2971
3549
  if (ownerProgramId.equals(RAYDIUM_CLMM_PROGRAM_ID)) return "raydium-clmm";
@@ -3001,10 +3579,10 @@ function parsePumpSwapPool(poolAddress, data) {
3001
3579
  return {
3002
3580
  dexType: "pumpswap",
3003
3581
  poolAddress,
3004
- baseMint: new PublicKey5(data.slice(35, 67)),
3005
- quoteMint: new PublicKey5(data.slice(67, 99)),
3006
- baseVault: new PublicKey5(data.slice(131, 163)),
3007
- quoteVault: new PublicKey5(data.slice(163, 195))
3582
+ baseMint: new PublicKey7(data.slice(35, 67)),
3583
+ quoteMint: new PublicKey7(data.slice(67, 99)),
3584
+ baseVault: new PublicKey7(data.slice(131, 163)),
3585
+ quoteVault: new PublicKey7(data.slice(163, 195))
3008
3586
  };
3009
3587
  }
3010
3588
  var SPL_TOKEN_AMOUNT_MIN_LEN = 72;
@@ -3030,8 +3608,8 @@ function parseRaydiumClmmPool(poolAddress, data) {
3030
3608
  return {
3031
3609
  dexType: "raydium-clmm",
3032
3610
  poolAddress,
3033
- baseMint: new PublicKey5(data.slice(73, 105)),
3034
- quoteMint: new PublicKey5(data.slice(105, 137))
3611
+ baseMint: new PublicKey7(data.slice(73, 105)),
3612
+ quoteMint: new PublicKey7(data.slice(105, 137))
3035
3613
  };
3036
3614
  }
3037
3615
  var MAX_TOKEN_DECIMALS = 24;
@@ -3049,9 +3627,7 @@ function computeRaydiumClmmPriceE6(data) {
3049
3627
  }
3050
3628
  const sqrtPriceX64 = readU128LE3(dv3, 253);
3051
3629
  if (sqrtPriceX64 === 0n) return 0n;
3052
- const scaledSqrt = sqrtPriceX64 * 1000000n;
3053
- const term = scaledSqrt >> 64n;
3054
- const priceE6Raw = term * sqrtPriceX64 >> 64n;
3630
+ const priceE6Raw = sqrtPriceX64 * sqrtPriceX64 * 1000000n >> 128n;
3055
3631
  const decimalDiff = 6 + decimals0 - decimals1;
3056
3632
  const adjustedDiff = decimalDiff - 6;
3057
3633
  if (adjustedDiff >= 0) {
@@ -3070,8 +3646,8 @@ function parseMeteoraPool(poolAddress, data) {
3070
3646
  return {
3071
3647
  dexType: "meteora-dlmm",
3072
3648
  poolAddress,
3073
- baseMint: new PublicKey5(data.slice(81, 113)),
3074
- quoteMint: new PublicKey5(data.slice(113, 145))
3649
+ baseMint: new PublicKey7(data.slice(81, 113)),
3650
+ quoteMint: new PublicKey7(data.slice(113, 145))
3075
3651
  };
3076
3652
  }
3077
3653
  var MAX_BIN_STEP = 1e4;
@@ -3104,7 +3680,14 @@ function computeMeteoraDlmmPriceE6(data) {
3104
3680
  let exp = isNeg ? BigInt(-activeId) : BigInt(activeId);
3105
3681
  let result = SCALE;
3106
3682
  let b = base;
3683
+ let iterations = 0;
3684
+ const MAX_ITERATIONS = 25;
3107
3685
  while (exp > 0n) {
3686
+ if (iterations++ >= MAX_ITERATIONS) {
3687
+ throw new Error(
3688
+ `Meteora DLMM: exponentiation loop exceeded ${MAX_ITERATIONS} iterations (activeId=${activeId})`
3689
+ );
3690
+ }
3108
3691
  if (exp & 1n) {
3109
3692
  result = result * b / SCALE;
3110
3693
  }
@@ -3135,6 +3718,7 @@ function readU128LE3(dv3, offset) {
3135
3718
  var CHAINLINK_MIN_SIZE = 224;
3136
3719
  var MAX_DECIMALS = 18;
3137
3720
  var CHAINLINK_DECIMALS_OFFSET = 138;
3721
+ var CHAINLINK_TIMESTAMP_OFFSET = 168;
3138
3722
  var CHAINLINK_ANSWER_OFFSET = 216;
3139
3723
  function readU82(data, off) {
3140
3724
  return data[off];
@@ -3142,7 +3726,7 @@ function readU82(data, off) {
3142
3726
  function readBigInt64LE(data, off) {
3143
3727
  return new DataView(data.buffer, data.byteOffset, data.byteLength).getBigInt64(off, true);
3144
3728
  }
3145
- function parseChainlinkPrice(data) {
3729
+ function parseChainlinkPrice(data, options) {
3146
3730
  if (data.length < CHAINLINK_MIN_SIZE) {
3147
3731
  throw new Error(
3148
3732
  `Oracle account data too small: ${data.length} bytes (need at least ${CHAINLINK_MIN_SIZE})`
@@ -3160,7 +3744,18 @@ function parseChainlinkPrice(data) {
3160
3744
  `Oracle price is non-positive: ${price}`
3161
3745
  );
3162
3746
  }
3163
- return { price, decimals };
3747
+ const updatedAtBig = readBigInt64LE(data, CHAINLINK_TIMESTAMP_OFFSET);
3748
+ const updatedAt = Number(updatedAtBig);
3749
+ if (options?.maxStalenessSeconds !== void 0 && updatedAt > 0) {
3750
+ const now = Math.floor(Date.now() / 1e3);
3751
+ const age = now - updatedAt;
3752
+ if (age > options.maxStalenessSeconds) {
3753
+ throw new Error(
3754
+ `Oracle price is stale: last updated ${age}s ago (max ${options.maxStalenessSeconds}s)`
3755
+ );
3756
+ }
3757
+ }
3758
+ return { price, decimals, updatedAt: updatedAt > 0 ? updatedAt : void 0 };
3164
3759
  }
3165
3760
  function isValidChainlinkOracle(data) {
3166
3761
  try {
@@ -3172,15 +3767,19 @@ function isValidChainlinkOracle(data) {
3172
3767
  }
3173
3768
 
3174
3769
  // src/solana/token-program.ts
3175
- import { PublicKey as PublicKey6 } from "@solana/web3.js";
3770
+ import { PublicKey as PublicKey8 } from "@solana/web3.js";
3176
3771
  import { TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID3 } from "@solana/spl-token";
3177
- var TOKEN_2022_PROGRAM_ID = new PublicKey6(
3772
+ var TOKEN_2022_PROGRAM_ID = new PublicKey8(
3178
3773
  "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
3179
3774
  );
3180
3775
  async function detectTokenProgram(connection, mint) {
3181
3776
  const info = await connection.getAccountInfo(mint);
3182
3777
  if (!info) throw new Error(`Mint account not found: ${mint.toBase58()}`);
3183
- return info.owner;
3778
+ if (info.owner.equals(TOKEN_PROGRAM_ID3)) return TOKEN_PROGRAM_ID3;
3779
+ if (info.owner.equals(TOKEN_2022_PROGRAM_ID)) return TOKEN_2022_PROGRAM_ID;
3780
+ throw new Error(
3781
+ `Mint ${mint.toBase58()} is owned by ${info.owner.toBase58()}, which is neither TOKEN_PROGRAM_ID nor TOKEN_2022_PROGRAM_ID`
3782
+ );
3184
3783
  }
3185
3784
  function isToken2022(tokenProgramId) {
3186
3785
  return tokenProgramId.equals(TOKEN_2022_PROGRAM_ID);
@@ -3190,11 +3789,11 @@ function isStandardToken(tokenProgramId) {
3190
3789
  }
3191
3790
 
3192
3791
  // src/solana/stake.ts
3193
- import { PublicKey as PublicKey8, SystemProgram as SystemProgram2, SYSVAR_RENT_PUBKEY as SYSVAR_RENT_PUBKEY2, SYSVAR_CLOCK_PUBKEY as SYSVAR_CLOCK_PUBKEY2 } from "@solana/web3.js";
3792
+ 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";
3194
3793
  import { TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID4 } from "@solana/spl-token";
3195
3794
 
3196
3795
  // src/config/program-ids.ts
3197
- import { PublicKey as PublicKey7 } from "@solana/web3.js";
3796
+ import { PublicKey as PublicKey9 } from "@solana/web3.js";
3198
3797
  function safeEnv(key) {
3199
3798
  try {
3200
3799
  return typeof process !== "undefined" && process?.env ? process.env[key] : void 0;
@@ -3208,30 +3807,34 @@ var PROGRAM_IDS = {
3208
3807
  matcher: "GTRgyTDfrMvBubALAqtHuQwT8tbGyXid7svXZKtWfC9k"
3209
3808
  },
3210
3809
  mainnet: {
3211
- percolator: "GM8zjJ8LTBMv9xEsverh6H6wLyevgMHEJXcEzyY3rY24",
3810
+ percolator: "ESa89R5Es3rJ5mnwGybVRG1GrNt9etP11Z5V2QWD4edv",
3212
3811
  matcher: "DHP6DtwXP1yJsz8YzfoeigRFPB979gzmumkmCxDLSkUX"
3213
3812
  }
3214
3813
  };
3215
3814
  function getProgramId(network) {
3216
- const override = safeEnv("PROGRAM_ID");
3217
- if (override) {
3218
- console.warn(
3219
- `[percolator-sdk] PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
3220
- );
3221
- return new PublicKey7(override);
3815
+ if (!network) {
3816
+ const override = safeEnv("PROGRAM_ID");
3817
+ if (override) {
3818
+ console.warn(
3819
+ `[percolator-sdk] PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
3820
+ );
3821
+ return new PublicKey9(override);
3822
+ }
3222
3823
  }
3223
3824
  const detectedNetwork = getCurrentNetwork();
3224
3825
  const targetNetwork = network ?? detectedNetwork;
3225
3826
  const programId = PROGRAM_IDS[targetNetwork].percolator;
3226
- return new PublicKey7(programId);
3827
+ return new PublicKey9(programId);
3227
3828
  }
3228
3829
  function getMatcherProgramId(network) {
3229
- const override = safeEnv("MATCHER_PROGRAM_ID");
3230
- if (override) {
3231
- console.warn(
3232
- `[percolator-sdk] MATCHER_PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
3233
- );
3234
- return new PublicKey7(override);
3830
+ if (!network) {
3831
+ const override = safeEnv("MATCHER_PROGRAM_ID");
3832
+ if (override) {
3833
+ console.warn(
3834
+ `[percolator-sdk] MATCHER_PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
3835
+ );
3836
+ return new PublicKey9(override);
3837
+ }
3235
3838
  }
3236
3839
  const detectedNetwork = getCurrentNetwork();
3237
3840
  const targetNetwork = network ?? detectedNetwork;
@@ -3239,7 +3842,7 @@ function getMatcherProgramId(network) {
3239
3842
  if (!programId) {
3240
3843
  throw new Error(`Matcher program not deployed on ${targetNetwork}`);
3241
3844
  }
3242
- return new PublicKey7(programId);
3845
+ return new PublicKey9(programId);
3243
3846
  }
3244
3847
  function getCurrentNetwork() {
3245
3848
  const network = safeEnv("NETWORK")?.toLowerCase();
@@ -3252,8 +3855,7 @@ function getCurrentNetwork() {
3252
3855
  // src/solana/stake.ts
3253
3856
  var STAKE_PROGRAM_IDS = {
3254
3857
  devnet: "6aJb1F9CDCVWCNYFwj8aQsVb696YnW6J1FznteHq4Q6k",
3255
- mainnet: ""
3256
- // TODO: populate once DevOps deploys percolator-stake to mainnet
3858
+ mainnet: "DC5fovFQD5SZYsetwvEqd4Wi4PFY1Yfnc669VMe6oa7F"
3257
3859
  };
3258
3860
  function getStakeProgramId(network) {
3259
3861
  const override = safeEnv("STAKE_PROGRAM_ID");
@@ -3261,7 +3863,7 @@ function getStakeProgramId(network) {
3261
3863
  console.warn(
3262
3864
  `[percolator-sdk] STAKE_PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
3263
3865
  );
3264
- return new PublicKey8(override);
3866
+ return new PublicKey10(override);
3265
3867
  }
3266
3868
  const detectedNetwork = network ?? (() => {
3267
3869
  const n = safeEnv("NEXT_PUBLIC_DEFAULT_NETWORK")?.toLowerCase() ?? safeEnv("NETWORK")?.toLowerCase() ?? "";
@@ -3273,9 +3875,9 @@ function getStakeProgramId(network) {
3273
3875
  `Stake program not deployed on ${detectedNetwork}. Set STAKE_PROGRAM_ID env var or wait for DevOps to deploy and update STAKE_PROGRAM_IDS.mainnet.`
3274
3876
  );
3275
3877
  }
3276
- return new PublicKey8(id);
3878
+ return new PublicKey10(id);
3277
3879
  }
3278
- var STAKE_PROGRAM_ID = new PublicKey8(STAKE_PROGRAM_IDS.devnet);
3880
+ var STAKE_PROGRAM_ID = new PublicKey10(STAKE_PROGRAM_IDS.mainnet);
3279
3881
  var STAKE_IX = {
3280
3882
  InitPool: 0,
3281
3883
  Deposit: 1,
@@ -3302,19 +3904,19 @@ var STAKE_IX = {
3302
3904
  };
3303
3905
  var TEXT = new TextEncoder();
3304
3906
  function deriveStakePool(slab, programId) {
3305
- return PublicKey8.findProgramAddressSync(
3907
+ return PublicKey10.findProgramAddressSync(
3306
3908
  [TEXT.encode("stake_pool"), slab.toBytes()],
3307
3909
  programId ?? getStakeProgramId()
3308
3910
  );
3309
3911
  }
3310
3912
  function deriveStakeVaultAuth(pool, programId) {
3311
- return PublicKey8.findProgramAddressSync(
3913
+ return PublicKey10.findProgramAddressSync(
3312
3914
  [TEXT.encode("vault_auth"), pool.toBytes()],
3313
3915
  programId ?? getStakeProgramId()
3314
3916
  );
3315
3917
  }
3316
3918
  function deriveDepositPda(pool, user, programId) {
3317
- return PublicKey8.findProgramAddressSync(
3919
+ return PublicKey10.findProgramAddressSync(
3318
3920
  [TEXT.encode("deposit"), pool.toBytes(), user.toBytes()],
3319
3921
  programId ?? getStakeProgramId()
3320
3922
  );
@@ -3336,6 +3938,9 @@ function readU16LE3(data, off) {
3336
3938
  );
3337
3939
  }
3338
3940
  function u64Le(v) {
3941
+ if (typeof v === "number" && !Number.isSafeInteger(v)) {
3942
+ throw new Error(`u64Le: number ${v} exceeds Number.MAX_SAFE_INTEGER \u2014 use BigInt`);
3943
+ }
3339
3944
  const big = BigInt(v);
3340
3945
  if (big < 0n) throw new Error(`u64Le: value must be non-negative, got ${big}`);
3341
3946
  if (big > 0xFFFFFFFFFFFFFFFFn) throw new Error(`u64Le: value exceeds u64 max`);
@@ -3344,6 +3949,9 @@ function u64Le(v) {
3344
3949
  return arr;
3345
3950
  }
3346
3951
  function u128Le(v) {
3952
+ if (typeof v === "number" && !Number.isSafeInteger(v)) {
3953
+ throw new Error(`u128Le: number ${v} exceeds Number.MAX_SAFE_INTEGER \u2014 use BigInt`);
3954
+ }
3347
3955
  const big = BigInt(v);
3348
3956
  if (big < 0n) throw new Error(`u128Le: value must be non-negative, got ${big}`);
3349
3957
  if (big > (1n << 128n) - 1n) throw new Error(`u128Le: value exceeds u128 max`);
@@ -3354,7 +3962,7 @@ function u128Le(v) {
3354
3962
  return arr;
3355
3963
  }
3356
3964
  function u16Le(v) {
3357
- if (v < 0 || v > 65535) throw new Error(`u16Le: value out of u16 range (0..65535), got ${v}`);
3965
+ if (!Number.isInteger(v) || v < 0 || v > 65535) throw new Error(`u16Le: value must be integer in range 0..65535, got ${v}`);
3358
3966
  const arr = new Uint8Array(2);
3359
3967
  new DataView(arr.buffer).setUint16(0, v, true);
3360
3968
  return arr;
@@ -3465,15 +4073,15 @@ function decodeStakePool(data) {
3465
4073
  const adminTransferred = bytes[off] === 1;
3466
4074
  off += 1;
3467
4075
  off += 4;
3468
- const slab = new PublicKey8(bytes.subarray(off, off + 32));
4076
+ const slab = new PublicKey10(bytes.subarray(off, off + 32));
3469
4077
  off += 32;
3470
- const admin = new PublicKey8(bytes.subarray(off, off + 32));
4078
+ const admin = new PublicKey10(bytes.subarray(off, off + 32));
3471
4079
  off += 32;
3472
- const collateralMint = new PublicKey8(bytes.subarray(off, off + 32));
4080
+ const collateralMint = new PublicKey10(bytes.subarray(off, off + 32));
3473
4081
  off += 32;
3474
- const lpMint = new PublicKey8(bytes.subarray(off, off + 32));
4082
+ const lpMint = new PublicKey10(bytes.subarray(off, off + 32));
3475
4083
  off += 32;
3476
- const vault = new PublicKey8(bytes.subarray(off, off + 32));
4084
+ const vault = new PublicKey10(bytes.subarray(off, off + 32));
3477
4085
  off += 32;
3478
4086
  const totalDeposited = readU64LE4(bytes, off);
3479
4087
  off += 8;
@@ -3489,7 +4097,7 @@ function decodeStakePool(data) {
3489
4097
  off += 8;
3490
4098
  const totalWithdrawn = readU64LE4(bytes, off);
3491
4099
  off += 8;
3492
- const percolatorProgram = new PublicKey8(bytes.subarray(off, off + 32));
4100
+ const percolatorProgram = new PublicKey10(bytes.subarray(off, off + 32));
3493
4101
  off += 32;
3494
4102
  const totalFeesEarned = readU64LE4(bytes, off);
3495
4103
  off += 8;
@@ -3609,7 +4217,9 @@ function computePnlPct(pnl, capital) {
3609
4217
  }
3610
4218
  function isAdlTriggered(slabData) {
3611
4219
  const layout = detectSlabLayout(slabData.length);
3612
- if (!layout) return false;
4220
+ if (!layout) {
4221
+ return false;
4222
+ }
3613
4223
  try {
3614
4224
  const engine = parseEngine(slabData);
3615
4225
  if (engine.pnlPosTot === 0n) return false;
@@ -3652,6 +4262,14 @@ function rankAdlPositions(slabData) {
3652
4262
  if (account.kind !== 0 /* User */) continue;
3653
4263
  if (account.positionSize === 0n) continue;
3654
4264
  const side = account.positionSize > 0n ? "long" : "short";
4265
+ if (side === "long" && account.positionSize <= 0n) {
4266
+ console.warn(`[fetchAdlRankedPositions] account idx=${idx}: side=long but positionSize=${account.positionSize}`);
4267
+ continue;
4268
+ }
4269
+ if (side === "short" && account.positionSize >= 0n) {
4270
+ console.warn(`[fetchAdlRankedPositions] account idx=${idx}: side=short but positionSize=${account.positionSize}`);
4271
+ continue;
4272
+ }
3655
4273
  const pnlPct = computePnlPct(account.pnl, account.capital);
3656
4274
  positions.push({
3657
4275
  idx,
@@ -3725,7 +4343,11 @@ function parseAdlEvent(logs) {
3725
4343
  }
3726
4344
  if (tag !== ADL_EVENT_TAG) continue;
3727
4345
  try {
3728
- const targetIdx = Number(BigInt(match[2]));
4346
+ const targetIdxBig = BigInt(match[2]);
4347
+ if (targetIdxBig < 0n || targetIdxBig > 65535n) {
4348
+ continue;
4349
+ }
4350
+ const targetIdx = Number(targetIdxBig);
3729
4351
  const price = BigInt(match[3]);
3730
4352
  const closedLo = BigInt(match[4]);
3731
4353
  const closedHi = BigInt(match[5]);
@@ -3753,9 +4375,387 @@ async function fetchAdlRankings(apiBase, slab, fetchFn = fetch) {
3753
4375
  );
3754
4376
  }
3755
4377
  const json = await res.json();
4378
+ if (typeof json !== "object" || json === null) {
4379
+ throw new Error("fetchAdlRankings: API returned non-object response");
4380
+ }
4381
+ const obj = json;
4382
+ if (!Array.isArray(obj.rankings)) {
4383
+ throw new Error("fetchAdlRankings: API response missing rankings array");
4384
+ }
4385
+ for (const entry of obj.rankings) {
4386
+ if (typeof entry !== "object" || entry === null) {
4387
+ throw new Error("fetchAdlRankings: invalid ranking entry (not an object)");
4388
+ }
4389
+ const r = entry;
4390
+ if (typeof r.idx !== "number" || !Number.isInteger(r.idx) || r.idx < 0) {
4391
+ throw new Error(`fetchAdlRankings: invalid ranking idx: ${r.idx}`);
4392
+ }
4393
+ }
3756
4394
  return json;
3757
4395
  }
3758
4396
 
4397
+ // src/solana/rpc-pool.ts
4398
+ import {
4399
+ Connection as Connection5
4400
+ } from "@solana/web3.js";
4401
+ async function checkRpcHealth(endpoint, timeoutMs = 5e3) {
4402
+ const conn = new Connection5(endpoint, { commitment: "processed" });
4403
+ const start = performance.now();
4404
+ const timeout = rejectAfter(timeoutMs, `Health probe timed out after ${timeoutMs}ms`);
4405
+ try {
4406
+ const slot = await Promise.race([
4407
+ conn.getSlot("processed"),
4408
+ timeout.promise
4409
+ ]);
4410
+ const latencyMs = Math.round(performance.now() - start);
4411
+ return { endpoint, healthy: true, latencyMs, slot };
4412
+ } catch (err) {
4413
+ const latencyMs = Math.round(performance.now() - start);
4414
+ return {
4415
+ endpoint,
4416
+ healthy: false,
4417
+ latencyMs,
4418
+ slot: 0,
4419
+ error: err instanceof Error ? err.message : String(err)
4420
+ };
4421
+ } finally {
4422
+ timeout.cancel();
4423
+ }
4424
+ }
4425
+ function resolveRetryConfig(cfg) {
4426
+ if (cfg === false) return null;
4427
+ const c = cfg ?? {};
4428
+ return {
4429
+ maxRetries: c.maxRetries ?? 3,
4430
+ baseDelayMs: c.baseDelayMs ?? 500,
4431
+ maxDelayMs: c.maxDelayMs ?? 1e4,
4432
+ jitterFactor: Math.max(0, Math.min(1, c.jitterFactor ?? 0.25)),
4433
+ retryableStatusCodes: c.retryableStatusCodes ?? [429, 502, 503, 504]
4434
+ };
4435
+ }
4436
+ function normalizeEndpoint(ep) {
4437
+ if (typeof ep === "string") return { url: ep };
4438
+ return ep;
4439
+ }
4440
+ function endpointLabel(ep) {
4441
+ if (ep.label) return ep.label;
4442
+ try {
4443
+ return new URL(ep.url).hostname;
4444
+ } catch {
4445
+ return ep.url.slice(0, 40);
4446
+ }
4447
+ }
4448
+ function isRetryable(err, codes) {
4449
+ if (!err) return false;
4450
+ const msg = err instanceof Error ? err.message : String(err);
4451
+ for (const code of codes) {
4452
+ if (msg.includes(String(code))) return true;
4453
+ }
4454
+ if (msg.toLowerCase().includes("rate limit") || msg.toLowerCase().includes("too many requests") || msg.toLowerCase().includes("econnreset") || msg.toLowerCase().includes("econnrefused") || msg.toLowerCase().includes("socket hang up") || msg.toLowerCase().includes("network") || msg.toLowerCase().includes("timeout") || msg.toLowerCase().includes("abort")) {
4455
+ return true;
4456
+ }
4457
+ return false;
4458
+ }
4459
+ function computeDelay(attempt, config) {
4460
+ const raw = Math.min(
4461
+ config.baseDelayMs * Math.pow(2, attempt),
4462
+ config.maxDelayMs
4463
+ );
4464
+ const jitter = Math.floor(Math.random() * raw * config.jitterFactor);
4465
+ return raw + jitter;
4466
+ }
4467
+ function rejectAfter(ms, message) {
4468
+ let timer;
4469
+ const promise = new Promise((_, reject) => {
4470
+ timer = setTimeout(() => reject(new Error(message)), ms);
4471
+ });
4472
+ return { promise, cancel: () => clearTimeout(timer) };
4473
+ }
4474
+ function sleep(ms) {
4475
+ return new Promise((resolve) => setTimeout(resolve, ms));
4476
+ }
4477
+ function redactUrl(raw) {
4478
+ try {
4479
+ const u = new URL(raw);
4480
+ const sensitive = /^(api[-_]?key|access[-_]?token|auth[-_]?token|token|secret|key|password|bearer|credential|jwt)$/i;
4481
+ for (const k of [...u.searchParams.keys()]) {
4482
+ if (sensitive.test(k)) {
4483
+ u.searchParams.set(k, "***");
4484
+ }
4485
+ }
4486
+ return u.toString();
4487
+ } catch {
4488
+ return raw;
4489
+ }
4490
+ }
4491
+ var RpcPool = class _RpcPool {
4492
+ endpoints;
4493
+ strategy;
4494
+ retryConfig;
4495
+ requestTimeoutMs;
4496
+ verbose;
4497
+ /** Round-robin index tracker. */
4498
+ rrIndex = 0;
4499
+ /** Consecutive failure threshold before marking an endpoint unhealthy. */
4500
+ static UNHEALTHY_THRESHOLD = 3;
4501
+ /** Minimum endpoints before auto-recovery is attempted. */
4502
+ static MIN_HEALTHY = 1;
4503
+ constructor(config) {
4504
+ if (!config.endpoints || config.endpoints.length === 0) {
4505
+ throw new Error("RpcPool: at least one endpoint is required");
4506
+ }
4507
+ this.strategy = config.strategy ?? "failover";
4508
+ this.retryConfig = resolveRetryConfig(config.retry);
4509
+ this.requestTimeoutMs = config.requestTimeoutMs ?? 3e4;
4510
+ this.verbose = config.verbose ?? true;
4511
+ const commitment = config.commitment ?? "confirmed";
4512
+ this.endpoints = config.endpoints.map((raw) => {
4513
+ const ep = normalizeEndpoint(raw);
4514
+ const connConfig = {
4515
+ commitment,
4516
+ ...ep.connectionConfig
4517
+ };
4518
+ return {
4519
+ config: ep,
4520
+ connection: new Connection5(ep.url, connConfig),
4521
+ label: endpointLabel(ep),
4522
+ weight: Math.max(1, ep.weight ?? 1),
4523
+ failures: 0,
4524
+ healthy: true,
4525
+ lastLatencyMs: -1
4526
+ };
4527
+ });
4528
+ }
4529
+ // -----------------------------------------------------------------------
4530
+ // Public API
4531
+ // -----------------------------------------------------------------------
4532
+ /**
4533
+ * Execute a function against a pooled connection with automatic retry
4534
+ * and failover.
4535
+ *
4536
+ * @param fn - Async function that receives a `Connection` and returns a result.
4537
+ * @returns The result of `fn`.
4538
+ * @throws The last error if all retries and failovers are exhausted.
4539
+ *
4540
+ * @example
4541
+ * ```ts
4542
+ * const balance = await pool.call(c => c.getBalance(pubkey));
4543
+ * const markets = await pool.call(c => discoverMarkets(c, programId, opts));
4544
+ * ```
4545
+ */
4546
+ async call(fn) {
4547
+ const maxAttempts = this.retryConfig ? this.retryConfig.maxRetries + 1 : 1;
4548
+ let lastError;
4549
+ const triedEndpoints = /* @__PURE__ */ new Set();
4550
+ const maxTotalIterations = maxAttempts + this.endpoints.length;
4551
+ let totalIterations = 0;
4552
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
4553
+ if (++totalIterations > maxTotalIterations) break;
4554
+ const epIdx = this.selectEndpoint(triedEndpoints);
4555
+ if (epIdx === -1) {
4556
+ break;
4557
+ }
4558
+ const ep = this.endpoints[epIdx];
4559
+ const timeout = rejectAfter(this.requestTimeoutMs, `RPC request timed out after ${this.requestTimeoutMs}ms (${ep.label})`);
4560
+ try {
4561
+ const result = await Promise.race([
4562
+ fn(ep.connection),
4563
+ timeout.promise
4564
+ ]);
4565
+ timeout.cancel();
4566
+ ep.failures = 0;
4567
+ ep.healthy = true;
4568
+ return result;
4569
+ } catch (err) {
4570
+ timeout.cancel();
4571
+ lastError = err;
4572
+ ep.failures++;
4573
+ if (ep.failures >= _RpcPool.UNHEALTHY_THRESHOLD) {
4574
+ ep.healthy = false;
4575
+ if (this.verbose) {
4576
+ console.warn(
4577
+ `[RpcPool] Endpoint ${ep.label} marked unhealthy after ${ep.failures} consecutive failures`
4578
+ );
4579
+ }
4580
+ }
4581
+ const retryable = this.retryConfig ? isRetryable(err, this.retryConfig.retryableStatusCodes) : false;
4582
+ if (!retryable) {
4583
+ if (this.strategy === "failover" && this.endpoints.length > 1) {
4584
+ triedEndpoints.add(epIdx);
4585
+ attempt--;
4586
+ if (triedEndpoints.size >= this.endpoints.length) break;
4587
+ continue;
4588
+ }
4589
+ throw err;
4590
+ }
4591
+ if (this.verbose) {
4592
+ console.warn(
4593
+ `[RpcPool] Retryable error on ${ep.label} (attempt ${attempt + 1}/${maxAttempts}):`,
4594
+ err instanceof Error ? err.message : err
4595
+ );
4596
+ }
4597
+ if (this.strategy === "failover" && this.endpoints.length > 1) {
4598
+ triedEndpoints.add(epIdx);
4599
+ }
4600
+ if (attempt < maxAttempts - 1 && this.retryConfig) {
4601
+ const delay = computeDelay(attempt, this.retryConfig);
4602
+ await sleep(delay);
4603
+ }
4604
+ }
4605
+ }
4606
+ this.maybeRecoverEndpoints();
4607
+ throw lastError ?? new Error("RpcPool: all endpoints exhausted");
4608
+ }
4609
+ /**
4610
+ * Get a raw `Connection` from the current preferred endpoint.
4611
+ * Useful when you need to pass a Connection to external code.
4612
+ *
4613
+ * NOTE: This bypasses retry and failover logic. Prefer `call()`.
4614
+ *
4615
+ * @returns Solana Connection from the current preferred endpoint.
4616
+ *
4617
+ * @example
4618
+ * ```ts
4619
+ * const conn = pool.getConnection();
4620
+ * const balance = await conn.getBalance(pubkey);
4621
+ * ```
4622
+ */
4623
+ getConnection() {
4624
+ const idx = this.selectEndpoint();
4625
+ if (idx === -1) {
4626
+ this.maybeRecoverEndpoints();
4627
+ return this.endpoints[0].connection;
4628
+ }
4629
+ return this.endpoints[idx].connection;
4630
+ }
4631
+ /**
4632
+ * Run a health check against all endpoints in the pool.
4633
+ *
4634
+ * @param timeoutMs - Per-endpoint probe timeout (default: 5000)
4635
+ * @returns Array of health results, one per endpoint.
4636
+ *
4637
+ * @example
4638
+ * ```ts
4639
+ * const results = await pool.healthCheck();
4640
+ * for (const r of results) {
4641
+ * console.log(`${r.endpoint}: ${r.healthy ? 'UP' : 'DOWN'} (${r.latencyMs}ms, slot ${r.slot})`);
4642
+ * }
4643
+ * ```
4644
+ */
4645
+ async healthCheck(timeoutMs = 5e3) {
4646
+ const results = await Promise.all(
4647
+ this.endpoints.map(async (ep) => {
4648
+ const result = await checkRpcHealth(ep.config.url, timeoutMs);
4649
+ ep.lastLatencyMs = result.latencyMs;
4650
+ ep.healthy = result.healthy;
4651
+ if (result.healthy) ep.failures = 0;
4652
+ result.endpoint = redactUrl(result.endpoint);
4653
+ return result;
4654
+ })
4655
+ );
4656
+ return results;
4657
+ }
4658
+ /**
4659
+ * Get the number of endpoints in the pool.
4660
+ */
4661
+ get size() {
4662
+ return this.endpoints.length;
4663
+ }
4664
+ /**
4665
+ * Get the number of currently healthy endpoints.
4666
+ */
4667
+ get healthyCount() {
4668
+ return this.endpoints.filter((ep) => ep.healthy).length;
4669
+ }
4670
+ /**
4671
+ * Get endpoint labels and their current status.
4672
+ *
4673
+ * @returns Array of `{ label, url, healthy, failures, lastLatencyMs }`.
4674
+ */
4675
+ status() {
4676
+ return this.endpoints.map((ep) => ({
4677
+ label: ep.label,
4678
+ url: redactUrl(ep.config.url),
4679
+ healthy: ep.healthy,
4680
+ failures: ep.failures,
4681
+ lastLatencyMs: ep.lastLatencyMs
4682
+ }));
4683
+ }
4684
+ // -----------------------------------------------------------------------
4685
+ // Internals
4686
+ // -----------------------------------------------------------------------
4687
+ /**
4688
+ * Select the next endpoint based on strategy.
4689
+ * Returns -1 if no endpoint is available.
4690
+ */
4691
+ selectEndpoint(exclude) {
4692
+ const healthy = this.endpoints.map((ep, i) => ({ ep, i })).filter(({ ep, i }) => ep.healthy && !exclude?.has(i));
4693
+ if (healthy.length === 0) {
4694
+ const remaining = this.endpoints.map((_, i) => i).filter((i) => !exclude?.has(i));
4695
+ return remaining.length > 0 ? remaining[0] : -1;
4696
+ }
4697
+ if (this.strategy === "failover") {
4698
+ return healthy[0].i;
4699
+ }
4700
+ const totalWeight = healthy.reduce((sum, { ep }) => sum + ep.weight, 0);
4701
+ this.rrIndex = (this.rrIndex + 1) % totalWeight;
4702
+ let cumulative = 0;
4703
+ for (const { ep, i } of healthy) {
4704
+ cumulative += ep.weight;
4705
+ if (this.rrIndex < cumulative) return i;
4706
+ }
4707
+ return healthy[healthy.length - 1].i;
4708
+ }
4709
+ /**
4710
+ * If all endpoints are unhealthy, reset them so we at least try again.
4711
+ */
4712
+ maybeRecoverEndpoints() {
4713
+ const healthyCount = this.endpoints.filter((ep) => ep.healthy).length;
4714
+ if (healthyCount < _RpcPool.MIN_HEALTHY) {
4715
+ if (this.verbose) {
4716
+ console.warn("[RpcPool] All endpoints unhealthy \u2014 resetting for recovery");
4717
+ }
4718
+ for (const ep of this.endpoints) {
4719
+ ep.healthy = true;
4720
+ ep.failures = 0;
4721
+ }
4722
+ }
4723
+ }
4724
+ };
4725
+ async function withRetry(fn, config) {
4726
+ const resolved = resolveRetryConfig(config) ?? {
4727
+ maxRetries: 3,
4728
+ baseDelayMs: 500,
4729
+ maxDelayMs: 1e4,
4730
+ jitterFactor: 0.25,
4731
+ retryableStatusCodes: [429, 502, 503, 504]
4732
+ };
4733
+ let lastError;
4734
+ const maxAttempts = resolved.maxRetries + 1;
4735
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
4736
+ try {
4737
+ return await fn();
4738
+ } catch (err) {
4739
+ lastError = err;
4740
+ if (!isRetryable(err, resolved.retryableStatusCodes)) {
4741
+ throw err;
4742
+ }
4743
+ if (attempt < maxAttempts - 1) {
4744
+ const delay = computeDelay(attempt, resolved);
4745
+ await sleep(delay);
4746
+ }
4747
+ }
4748
+ }
4749
+ throw lastError ?? new Error("withRetry: all attempts exhausted");
4750
+ }
4751
+ var _internal = {
4752
+ isRetryable,
4753
+ computeDelay,
4754
+ resolveRetryConfig,
4755
+ normalizeEndpoint,
4756
+ endpointLabel
4757
+ };
4758
+
3759
4759
  // src/runtime/tx.ts
3760
4760
  import {
3761
4761
  TransactionInstruction as TransactionInstruction2,
@@ -3907,6 +4907,139 @@ function formatResult(result, jsonMode) {
3907
4907
  return lines.join("\n");
3908
4908
  }
3909
4909
 
4910
+ // src/runtime/lighthouse.ts
4911
+ import { PublicKey as PublicKey13, Transaction as Transaction2 } from "@solana/web3.js";
4912
+ var LIGHTHOUSE_PROGRAM_ID = new PublicKey13(
4913
+ "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95"
4914
+ );
4915
+ var LIGHTHOUSE_PROGRAM_ID_STR2 = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
4916
+ var LIGHTHOUSE_CONSTRAINT_ADDRESS = 6400;
4917
+ var LIGHTHOUSE_ERROR_CODES = /* @__PURE__ */ new Set([
4918
+ 6e3,
4919
+ // InstructionMissing
4920
+ 6001,
4921
+ // InstructionFallbackNotFound
4922
+ 6002,
4923
+ // InstructionDidNotDeserialize
4924
+ 6003,
4925
+ // InstructionDidNotSerialize
4926
+ 6016,
4927
+ // IdlInstructionStub
4928
+ 6032,
4929
+ // ConstraintMut
4930
+ 6033,
4931
+ // ConstraintHasOne
4932
+ 6034,
4933
+ // ConstraintSigner
4934
+ 6035,
4935
+ // ConstraintRaw
4936
+ 6036,
4937
+ // ConstraintOwner
4938
+ 6037,
4939
+ // ConstraintRentExempt
4940
+ 6038,
4941
+ // ConstraintSeeds
4942
+ 6039,
4943
+ // ConstraintExecutable
4944
+ 6040,
4945
+ // ConstraintState
4946
+ 6041,
4947
+ // ConstraintAssociated
4948
+ 6042,
4949
+ // ConstraintAssociatedInit
4950
+ 6043,
4951
+ // ConstraintClose
4952
+ 6400
4953
+ // ConstraintAddress (the one we hit most often)
4954
+ ]);
4955
+ function isLighthouseInstruction(ix) {
4956
+ return ix.programId.equals(LIGHTHOUSE_PROGRAM_ID);
4957
+ }
4958
+ function isLighthouseError(error) {
4959
+ const msg = extractErrorMessage(error);
4960
+ if (!msg) return false;
4961
+ if (msg.includes(LIGHTHOUSE_PROGRAM_ID_STR2)) return true;
4962
+ if (/custom\s+program\s+error:\s*0x1900\b/i.test(msg)) return true;
4963
+ if (/"Custom"\s*:\s*6400\b/.test(msg) && /InstructionError/i.test(msg)) return true;
4964
+ return false;
4965
+ }
4966
+ function isLighthouseFailureInLogs(logs) {
4967
+ if (!Array.isArray(logs)) return false;
4968
+ let insideLighthouse = false;
4969
+ for (const line of logs) {
4970
+ if (typeof line !== "string") continue;
4971
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} invoke`)) {
4972
+ insideLighthouse = true;
4973
+ continue;
4974
+ }
4975
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} success`)) {
4976
+ insideLighthouse = false;
4977
+ continue;
4978
+ }
4979
+ if (insideLighthouse && /failed/i.test(line)) {
4980
+ return true;
4981
+ }
4982
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} failed`)) {
4983
+ return true;
4984
+ }
4985
+ }
4986
+ return false;
4987
+ }
4988
+ function stripLighthouseInstructions(instructions, percolatorProgramId) {
4989
+ if (percolatorProgramId) {
4990
+ const hasPercolatorIx = instructions.some(
4991
+ (ix) => ix.programId.equals(percolatorProgramId)
4992
+ );
4993
+ if (!hasPercolatorIx) {
4994
+ return instructions;
4995
+ }
4996
+ }
4997
+ return instructions.filter((ix) => !isLighthouseInstruction(ix));
4998
+ }
4999
+ function stripLighthouseFromTransaction(transaction, percolatorProgramId) {
5000
+ if (percolatorProgramId) {
5001
+ const hasPercolatorIx = transaction.instructions.some(
5002
+ (ix) => ix.programId.equals(percolatorProgramId)
5003
+ );
5004
+ if (!hasPercolatorIx) return transaction;
5005
+ }
5006
+ const hasLighthouse = transaction.instructions.some(isLighthouseInstruction);
5007
+ if (!hasLighthouse) return transaction;
5008
+ const clean = new Transaction2();
5009
+ clean.recentBlockhash = transaction.recentBlockhash;
5010
+ clean.feePayer = transaction.feePayer;
5011
+ for (const ix of transaction.instructions) {
5012
+ if (!isLighthouseInstruction(ix)) {
5013
+ clean.add(ix);
5014
+ }
5015
+ }
5016
+ return clean;
5017
+ }
5018
+ function countLighthouseInstructions(ixsOrTx) {
5019
+ const instructions = Array.isArray(ixsOrTx) ? ixsOrTx : ixsOrTx.instructions;
5020
+ return instructions.filter(isLighthouseInstruction).length;
5021
+ }
5022
+ var LIGHTHOUSE_USER_MESSAGE = "Your wallet's transaction guard (Blowfish/Lighthouse) is blocking this transaction. This is a known compatibility issue \u2014 the transaction itself is valid. Try one of these workarounds:\n1. Disable transaction simulation in your wallet settings\n2. Use a wallet without Blowfish protection (e.g., Backpack, Solflare)\n3. The SDK will automatically retry without the guard";
5023
+ function classifyLighthouseError(error) {
5024
+ if (isLighthouseError(error)) {
5025
+ return LIGHTHOUSE_USER_MESSAGE;
5026
+ }
5027
+ return null;
5028
+ }
5029
+ function extractErrorMessage(error) {
5030
+ if (!error) return null;
5031
+ if (typeof error === "string") return error;
5032
+ if (error instanceof Error) return error.message;
5033
+ if (typeof error === "object" && "message" in error) {
5034
+ return String(error.message);
5035
+ }
5036
+ try {
5037
+ return JSON.stringify(error);
5038
+ } catch {
5039
+ return null;
5040
+ }
5041
+ }
5042
+
3910
5043
  // src/math/trading.ts
3911
5044
  function computeMarkPnl(positionSize, entryPrice, oraclePrice) {
3912
5045
  if (positionSize === 0n || oraclePrice === 0n) return 0n;
@@ -3954,9 +5087,20 @@ function computeFeeSplit(totalFee, config) {
3954
5087
  if (config.lpBps === 0n && config.protocolBps === 0n && config.creatorBps === 0n) {
3955
5088
  return [totalFee, 0n, 0n];
3956
5089
  }
5090
+ const totalBps = config.lpBps + config.protocolBps + config.creatorBps;
5091
+ if (totalBps !== 10000n) {
5092
+ throw new Error(
5093
+ `Fee split must equal exactly 10000 bps (100%): lpBps=${config.lpBps} + protocolBps=${config.protocolBps} + creatorBps=${config.creatorBps} = ${totalBps}`
5094
+ );
5095
+ }
3957
5096
  const lp = totalFee * config.lpBps / 10000n;
3958
5097
  const protocol = totalFee * config.protocolBps / 10000n;
3959
5098
  const creator = totalFee - lp - protocol;
5099
+ if (creator < 0n) {
5100
+ throw new Error(
5101
+ `Internal error: creator fee is negative (${creator}). This should not happen if lpBps + protocolBps + creatorBps === 10000.`
5102
+ );
5103
+ }
3960
5104
  return [lp, protocol, creator];
3961
5105
  }
3962
5106
  function computePnlPercent(pnlTokens, capital) {
@@ -3971,8 +5115,17 @@ function computePnlPercent(pnlTokens, capital) {
3971
5115
  }
3972
5116
  function computeEstimatedEntryPrice(oracleE6, tradingFeeBps, direction) {
3973
5117
  if (oracleE6 === 0n) return 0n;
5118
+ if (tradingFeeBps < 0n) {
5119
+ throw new Error(`computeEstimatedEntryPrice: tradingFeeBps must be non-negative, got ${tradingFeeBps}`);
5120
+ }
3974
5121
  const feeImpact = oracleE6 * tradingFeeBps / 10000n;
3975
- return direction === "long" ? oracleE6 + feeImpact : oracleE6 - feeImpact;
5122
+ const result = direction === "long" ? oracleE6 + feeImpact : oracleE6 - feeImpact;
5123
+ if (result <= 0n) {
5124
+ throw new Error(
5125
+ `computeEstimatedEntryPrice: result ${result} is non-positive (tradingFeeBps=${tradingFeeBps} too high for oracle=${oracleE6})`
5126
+ );
5127
+ }
5128
+ return result;
3976
5129
  }
3977
5130
  var MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
3978
5131
  var MIN_SAFE_BIGINT = BigInt(-Number.MAX_SAFE_INTEGER);
@@ -3993,7 +5146,12 @@ function computeMaxLeverage(initialMarginBps) {
3993
5146
  if (initialMarginBps <= 0n) {
3994
5147
  throw new Error("computeMaxLeverage: initialMarginBps must be positive");
3995
5148
  }
3996
- return Number(10000n / initialMarginBps);
5149
+ const scaledResult = 10000n * 1000000n / initialMarginBps;
5150
+ return Number(scaledResult) / 1e6;
5151
+ }
5152
+ function computeMaxWithdrawable(capital, pnl, reservedPnl) {
5153
+ const maturedPnl = pnl - reservedPnl;
5154
+ return capital + (maturedPnl > 0n ? maturedPnl : 0n);
3997
5155
  }
3998
5156
 
3999
5157
  // src/math/warmup.ts
@@ -4005,6 +5163,9 @@ function computeWarmupUnlockedCapital(totalCapital, currentSlot, warmupStartSlot
4005
5163
  return totalCapital * elapsed / warmupPeriodSlots;
4006
5164
  }
4007
5165
  function computeWarmupLeverageCap(initialMarginBps, totalCapital, currentSlot, warmupStartSlot, warmupPeriodSlots) {
5166
+ if (initialMarginBps <= 0n) {
5167
+ throw new Error("computeWarmupLeverageCap: initialMarginBps must be positive");
5168
+ }
4008
5169
  const maxLev = computeMaxLeverage(initialMarginBps);
4009
5170
  if (warmupPeriodSlots === 0n || warmupStartSlot === 0n) return maxLev;
4010
5171
  if (totalCapital <= 0n) return 1;
@@ -4015,7 +5176,14 @@ function computeWarmupLeverageCap(initialMarginBps, totalCapital, currentSlot, w
4015
5176
  warmupPeriodSlots
4016
5177
  );
4017
5178
  if (unlocked <= 0n) return 1;
4018
- const effectiveLev = Number(BigInt(maxLev) * unlocked / totalCapital);
5179
+ const scaledResult = BigInt(maxLev) * unlocked / totalCapital;
5180
+ if (scaledResult > BigInt(Number.MAX_SAFE_INTEGER)) {
5181
+ console.warn(
5182
+ `[computeWarmupLeverageCap] Warning: effective leverage ${scaledResult} exceeds MAX_SAFE_INTEGER, returning MAX_SAFE_INTEGER as a safety bound`
5183
+ );
5184
+ return Number.MAX_SAFE_INTEGER;
5185
+ }
5186
+ const effectiveLev = Number(scaledResult);
4019
5187
  return Math.max(1, effectiveLev);
4020
5188
  }
4021
5189
  function computeWarmupMaxPositionSize(initialMarginBps, totalCapital, currentSlot, warmupStartSlot, warmupPeriodSlots) {
@@ -4028,9 +5196,40 @@ function computeWarmupMaxPositionSize(initialMarginBps, totalCapital, currentSlo
4028
5196
  );
4029
5197
  return unlocked * BigInt(maxLev);
4030
5198
  }
5199
+ function computeWarmupProgress(currentSlot, warmupStartedAtSlot, warmupPeriodSlots, pnl, reservedPnl) {
5200
+ if (warmupPeriodSlots === 0n || warmupStartedAtSlot === 0n) {
5201
+ return {
5202
+ maturedPnl: pnl > 0n ? pnl : 0n,
5203
+ reservedPnl: 0n,
5204
+ progressBps: 10000n,
5205
+ // 100%
5206
+ slotsRemaining: 0n
5207
+ };
5208
+ }
5209
+ const elapsed = currentSlot >= warmupStartedAtSlot ? currentSlot - warmupStartedAtSlot : 0n;
5210
+ if (elapsed >= warmupPeriodSlots) {
5211
+ return {
5212
+ maturedPnl: pnl > 0n ? pnl : 0n,
5213
+ reservedPnl: 0n,
5214
+ progressBps: 10000n,
5215
+ // 100%
5216
+ slotsRemaining: 0n
5217
+ };
5218
+ }
5219
+ const progressBps = elapsed * 10000n / warmupPeriodSlots;
5220
+ const slotsRemaining = warmupPeriodSlots - elapsed;
5221
+ const maturedPnl = pnl > 0n ? pnl * progressBps / 10000n : 0n;
5222
+ const locked = reservedPnl > 0n ? reservedPnl : 0n;
5223
+ return {
5224
+ maturedPnl,
5225
+ reservedPnl: locked,
5226
+ progressBps,
5227
+ slotsRemaining
5228
+ };
5229
+ }
4031
5230
 
4032
5231
  // src/validation.ts
4033
- import { PublicKey as PublicKey11 } from "@solana/web3.js";
5232
+ import { PublicKey as PublicKey14 } from "@solana/web3.js";
4034
5233
  var U16_MAX = 65535;
4035
5234
  var U64_MAX = BigInt("18446744073709551615");
4036
5235
  var I64_MIN = BigInt("-9223372036854775808");
@@ -4060,7 +5259,7 @@ var ValidationError = class extends Error {
4060
5259
  };
4061
5260
  function validatePublicKey(value, field) {
4062
5261
  try {
4063
- return new PublicKey11(value);
5262
+ return new PublicKey14(value);
4064
5263
  } catch {
4065
5264
  throw new ValidationError(
4066
5265
  field,
@@ -4077,18 +5276,20 @@ function validateIndex(value, field) {
4077
5276
  `must be <= ${U16_MAX} (u16 max), got ${t}`
4078
5277
  );
4079
5278
  }
5279
+ if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5280
+ throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);
5281
+ }
4080
5282
  return Number(bi);
4081
5283
  }
4082
5284
  function validateAmount(value, field) {
4083
- let num;
4084
- try {
4085
- num = BigInt(value);
4086
- } catch {
5285
+ const t = value.trim();
5286
+ if (!/^(0|[1-9]\d*)$/.test(t)) {
4087
5287
  throw new ValidationError(
4088
5288
  field,
4089
- `"${value}" is not a valid number. Use decimal digits only.`
5289
+ `"${value}" is not a valid non-negative integer. Use decimal digits only.`
4090
5290
  );
4091
5291
  }
5292
+ const num = BigInt(t);
4092
5293
  if (num < 0n) {
4093
5294
  throw new ValidationError(field, `must be non-negative, got ${num}`);
4094
5295
  }
@@ -4101,15 +5302,14 @@ function validateAmount(value, field) {
4101
5302
  return num;
4102
5303
  }
4103
5304
  function validateU128(value, field) {
4104
- let num;
4105
- try {
4106
- num = BigInt(value);
4107
- } catch {
5305
+ const t = value.trim();
5306
+ if (!/^(0|[1-9]\d*)$/.test(t)) {
4108
5307
  throw new ValidationError(
4109
5308
  field,
4110
- `"${value}" is not a valid number. Use decimal digits only.`
5309
+ `"${value}" is not a valid non-negative integer. Use decimal digits only.`
4111
5310
  );
4112
5311
  }
5312
+ const num = BigInt(t);
4113
5313
  if (num < 0n) {
4114
5314
  throw new ValidationError(field, `must be non-negative, got ${num}`);
4115
5315
  }
@@ -4122,15 +5322,14 @@ function validateU128(value, field) {
4122
5322
  return num;
4123
5323
  }
4124
5324
  function validateI64(value, field) {
4125
- let num;
4126
- try {
4127
- num = BigInt(value);
4128
- } catch {
5325
+ const t = value.trim();
5326
+ if (!/^-?(0|[1-9]\d*)$/.test(t)) {
4129
5327
  throw new ValidationError(
4130
5328
  field,
4131
- `"${value}" is not a valid number. Use decimal digits only, with optional leading minus.`
5329
+ `"${value}" is not a valid integer. Use decimal digits only, with optional leading minus.`
4132
5330
  );
4133
5331
  }
5332
+ const num = BigInt(t);
4134
5333
  if (num < I64_MIN) {
4135
5334
  throw new ValidationError(
4136
5335
  field,
@@ -4146,15 +5345,14 @@ function validateI64(value, field) {
4146
5345
  return num;
4147
5346
  }
4148
5347
  function validateI128(value, field) {
4149
- let num;
4150
- try {
4151
- num = BigInt(value);
4152
- } catch {
5348
+ const t = value.trim();
5349
+ if (!/^-?(0|[1-9]\d*)$/.test(t)) {
4153
5350
  throw new ValidationError(
4154
5351
  field,
4155
- `"${value}" is not a valid number. Use decimal digits only, with optional leading minus.`
5352
+ `"${value}" is not a valid integer. Use decimal digits only, with optional leading minus.`
4156
5353
  );
4157
5354
  }
5355
+ const num = BigInt(t);
4158
5356
  if (num < I128_MIN) {
4159
5357
  throw new ValidationError(
4160
5358
  field,
@@ -4178,6 +5376,9 @@ function validateBps(value, field) {
4178
5376
  `must be <= 10000 (100%), got ${t}`
4179
5377
  );
4180
5378
  }
5379
+ if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5380
+ throw new ValidationError(field, `internal error: bps value exceeds MAX_SAFE_INTEGER`);
5381
+ }
4181
5382
  return Number(bi);
4182
5383
  }
4183
5384
  function validateU64(value, field) {
@@ -4192,6 +5393,9 @@ function validateU16(value, field) {
4192
5393
  `must be <= ${U16_MAX} (u16 max), got ${t}`
4193
5394
  );
4194
5395
  }
5396
+ if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5397
+ throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);
5398
+ }
4195
5399
  return Number(bi);
4196
5400
  }
4197
5401
 
@@ -4242,7 +5446,9 @@ function parseDexScreenerPairs(json) {
4242
5446
  else if (liquidity > 1e4) confidence = 60;
4243
5447
  else if (liquidity > 1e3) confidence = 45;
4244
5448
  const priceUsd = pair.priceUsd;
4245
- const price = typeof priceUsd === "string" || typeof priceUsd === "number" ? parseFloat(String(priceUsd)) || 0 : 0;
5449
+ const rawPrice = typeof priceUsd === "string" || typeof priceUsd === "number" ? parseFloat(String(priceUsd)) : NaN;
5450
+ if (!Number.isFinite(rawPrice) || rawPrice <= 0) continue;
5451
+ const price = rawPrice;
4246
5452
  let baseSym = "?";
4247
5453
  let quoteSym = "?";
4248
5454
  if (isRecord(pair.baseToken) && typeof pair.baseToken.symbol === "string") {
@@ -4273,8 +5479,8 @@ function parseJupiterMintEntry(json, mint) {
4273
5479
  if (!isRecord(row)) return null;
4274
5480
  const rawPrice = row.price;
4275
5481
  if (rawPrice === void 0 || rawPrice === null) return null;
4276
- const price = parseFloat(String(rawPrice)) || 0;
4277
- if (price <= 0) return null;
5482
+ const price = parseFloat(String(rawPrice));
5483
+ if (!Number.isFinite(price) || price <= 0) return null;
4278
5484
  let mintSymbol = "?";
4279
5485
  if (typeof row.mintSymbol === "string") mintSymbol = row.mintSymbol;
4280
5486
  return { price, mintSymbol };
@@ -4340,10 +5546,17 @@ async function fetchDexSources(mint, signal) {
4340
5546
  headers: { "User-Agent": "percolator/1.0" }
4341
5547
  }
4342
5548
  );
4343
- if (!resp.ok) return [];
5549
+ if (!resp.ok) {
5550
+ console.debug(`[fetchDexSources] HTTP ${resp.status} for mint ${mint}`);
5551
+ return [];
5552
+ }
4344
5553
  const json = await resp.json();
4345
5554
  return parseDexScreenerPairs(json);
4346
- } catch {
5555
+ } catch (err) {
5556
+ console.warn(
5557
+ `[fetchDexSources] Error fetching DexScreener data for mint ${mint}:`,
5558
+ err instanceof Error ? err.message : String(err)
5559
+ );
4347
5560
  return [];
4348
5561
  }
4349
5562
  }
@@ -4354,7 +5567,7 @@ function lookupPythSource(mint) {
4354
5567
  type: "pyth",
4355
5568
  address: entry.feedId,
4356
5569
  pairLabel: `${entry.symbol} / USD (Pyth)`,
4357
- liquidity: Infinity,
5570
+ liquidity: Number.MAX_SAFE_INTEGER,
4358
5571
  // Pyth is considered deep liquidity
4359
5572
  price: 0,
4360
5573
  // We don't fetch live price here; caller can enrich
@@ -4371,10 +5584,16 @@ async function fetchJupiterSource(mint, signal) {
4371
5584
  headers: { "User-Agent": "percolator/1.0" }
4372
5585
  }
4373
5586
  );
4374
- if (!resp.ok) return null;
5587
+ if (!resp.ok) {
5588
+ console.debug(`[fetchJupiterSource] HTTP ${resp.status} for mint ${mint}`);
5589
+ return null;
5590
+ }
4375
5591
  const json = await resp.json();
4376
5592
  const row = parseJupiterMintEntry(json, mint);
4377
- if (!row) return null;
5593
+ if (!row) {
5594
+ console.debug(`[fetchJupiterSource] No price data from Jupiter for mint ${mint}`);
5595
+ return null;
5596
+ }
4378
5597
  return {
4379
5598
  type: "jupiter",
4380
5599
  address: mint,
@@ -4385,7 +5604,11 @@ async function fetchJupiterSource(mint, signal) {
4385
5604
  confidence: 40
4386
5605
  // Fallback — lower confidence
4387
5606
  };
4388
- } catch {
5607
+ } catch (err) {
5608
+ console.warn(
5609
+ `[fetchJupiterSource] Error fetching Jupiter data for mint ${mint}:`,
5610
+ err instanceof Error ? err.message : String(err)
5611
+ );
4389
5612
  return null;
4390
5613
  }
4391
5614
  }
@@ -4400,8 +5623,20 @@ async function resolvePrice(mint, signal, options) {
4400
5623
  const pythSource = lookupPythSource(mint);
4401
5624
  const allSources = [];
4402
5625
  if (pythSource) {
4403
- const refPrice = dexSources[0]?.price || jupiterSource?.price || 0;
4404
- pythSource.price = refPrice;
5626
+ const dexPrice = dexSources[0]?.price ?? 0;
5627
+ const jupPrice = jupiterSource?.price ?? 0;
5628
+ if (dexPrice > 0 && jupPrice > 0) {
5629
+ const mid = (dexPrice + jupPrice) / 2;
5630
+ const deviation = Math.abs(dexPrice - jupPrice) / mid;
5631
+ if (deviation > 0.5) {
5632
+ pythSource.price = 0;
5633
+ pythSource.confidence = 20;
5634
+ } else {
5635
+ pythSource.price = mid;
5636
+ }
5637
+ } else {
5638
+ pythSource.price = dexPrice || jupPrice || 0;
5639
+ }
4405
5640
  allSources.push(pythSource);
4406
5641
  }
4407
5642
  allSources.push(...dexSources);
@@ -4426,13 +5661,12 @@ export {
4426
5661
  ACCOUNTS_CLOSE_ACCOUNT,
4427
5662
  ACCOUNTS_CLOSE_SLAB,
4428
5663
  ACCOUNTS_CLOSE_STALE_SLABS,
4429
- ACCOUNTS_CREATE_INSURANCE_MINT,
4430
5664
  ACCOUNTS_DEPOSIT_COLLATERAL,
4431
- ACCOUNTS_DEPOSIT_INSURANCE_LP,
4432
5665
  ACCOUNTS_EXECUTE_ADL,
4433
5666
  ACCOUNTS_FUND_MARKET_INSURANCE,
4434
5667
  ACCOUNTS_INIT_LP,
4435
5668
  ACCOUNTS_INIT_MARKET,
5669
+ ACCOUNTS_INIT_MATCHER_CTX,
4436
5670
  ACCOUNTS_INIT_USER,
4437
5671
  ACCOUNTS_KEEPER_CRANK,
4438
5672
  ACCOUNTS_LIQUIDATE_AT_ORACLE,
@@ -4461,20 +5695,26 @@ export {
4461
5695
  ACCOUNTS_UPDATE_CONFIG,
4462
5696
  ACCOUNTS_WITHDRAW_COLLATERAL,
4463
5697
  ACCOUNTS_WITHDRAW_INSURANCE,
4464
- ACCOUNTS_WITHDRAW_INSURANCE_LP,
4465
5698
  AccountKind,
4466
5699
  CHAINLINK_ANSWER_OFFSET,
4467
5700
  CHAINLINK_DECIMALS_OFFSET,
4468
5701
  CHAINLINK_MIN_SIZE,
5702
+ CHAINLINK_TIMESTAMP_OFFSET,
4469
5703
  CREATOR_LOCK_SEED,
4470
5704
  CTX_VAMM_OFFSET,
4471
5705
  DEFAULT_OI_RAMP_SLOTS,
4472
5706
  ENGINE_MARK_PRICE_OFF,
4473
5707
  ENGINE_OFF,
4474
5708
  IX_TAG,
5709
+ LIGHTHOUSE_CONSTRAINT_ADDRESS,
5710
+ LIGHTHOUSE_ERROR_CODES,
5711
+ LIGHTHOUSE_PROGRAM_ID,
5712
+ LIGHTHOUSE_PROGRAM_ID_STR2 as LIGHTHOUSE_PROGRAM_ID_STR,
5713
+ LIGHTHOUSE_USER_MESSAGE,
4475
5714
  MARK_PRICE_EMA_ALPHA_E6,
4476
5715
  MARK_PRICE_EMA_WINDOW_SLOTS,
4477
5716
  MAX_DECIMALS,
5717
+ MAX_ORACLE_PRICE,
4478
5718
  METEORA_DLMM_PROGRAM_ID,
4479
5719
  ORACLE_PHASE_GROWING,
4480
5720
  ORACLE_PHASE_MATURE,
@@ -4492,9 +5732,11 @@ export {
4492
5732
  RAMP_START_BPS,
4493
5733
  RAYDIUM_CLMM_PROGRAM_ID,
4494
5734
  RENOUNCE_ADMIN_CONFIRMATION,
5735
+ RpcPool,
4495
5736
  SLAB_TIERS,
4496
5737
  SLAB_TIERS_V0,
4497
5738
  SLAB_TIERS_V1,
5739
+ SLAB_TIERS_V12_1,
4498
5740
  SLAB_TIERS_V1D,
4499
5741
  SLAB_TIERS_V1D_LEGACY,
4500
5742
  SLAB_TIERS_V1M,
@@ -4502,6 +5744,7 @@ export {
4502
5744
  SLAB_TIERS_V2,
4503
5745
  SLAB_TIERS_V_ADL,
4504
5746
  SLAB_TIERS_V_ADL_DISCOVERY,
5747
+ SLAB_TIERS_V_SETDEXPOOL,
4505
5748
  STAKE_IX,
4506
5749
  STAKE_POOL_SIZE,
4507
5750
  STAKE_PROGRAM_ID,
@@ -4511,11 +5754,15 @@ export {
4511
5754
  VAMM_MAGIC,
4512
5755
  ValidationError,
4513
5756
  WELL_KNOWN,
5757
+ _internal,
4514
5758
  buildAccountMetas,
4515
5759
  buildAdlInstruction,
4516
5760
  buildAdlTransaction,
4517
5761
  buildIx,
4518
5762
  checkPhaseTransition,
5763
+ checkRpcHealth,
5764
+ classifyLighthouseError,
5765
+ clearStaticMarkets,
4519
5766
  computeDexSpotPriceE6,
4520
5767
  computeDynamicFeeBps,
4521
5768
  computeDynamicTradingFee,
@@ -4527,6 +5774,7 @@ export {
4527
5774
  computeLiqPrice,
4528
5775
  computeMarkPnl,
4529
5776
  computeMaxLeverage,
5777
+ computeMaxWithdrawable,
4530
5778
  computePnlPercent,
4531
5779
  computePreTradeLiqPrice,
4532
5780
  computeRequiredMargin,
@@ -4534,14 +5782,15 @@ export {
4534
5782
  computeVammQuote,
4535
5783
  computeWarmupLeverageCap,
4536
5784
  computeWarmupMaxPositionSize,
5785
+ computeWarmupProgress,
4537
5786
  computeWarmupUnlockedCapital,
4538
5787
  concatBytes,
5788
+ countLighthouseInstructions,
4539
5789
  decodeError,
4540
5790
  decodeStakePool,
4541
5791
  depositAccounts,
4542
5792
  deriveCreatorLockPda,
4543
5793
  deriveDepositPda,
4544
- deriveInsuranceLpMint,
4545
5794
  deriveKeeperFund,
4546
5795
  deriveLpPda,
4547
5796
  derivePythPriceUpdateAccount,
@@ -4554,6 +5803,8 @@ export {
4554
5803
  detectSlabLayout,
4555
5804
  detectTokenProgram,
4556
5805
  discoverMarkets,
5806
+ discoverMarketsViaApi,
5807
+ discoverMarketsViaStaticBundle,
4557
5808
  encBool,
4558
5809
  encI128,
4559
5810
  encI64,
@@ -4567,26 +5818,33 @@ export {
4567
5818
  encodeAdvanceEpoch,
4568
5819
  encodeAdvanceOraclePhase,
4569
5820
  encodeAllocateMarket,
5821
+ encodeAttestCrossMargin,
4570
5822
  encodeAuditCrank,
4571
5823
  encodeBurnPositionNft,
4572
5824
  encodeCancelQueuedWithdrawal,
5825
+ encodeChallengeSettlement,
4573
5826
  encodeClaimEpochWithdrawal,
4574
5827
  encodeClaimQueuedWithdrawal,
4575
5828
  encodeClearPendingSettlement,
4576
5829
  encodeCloseAccount,
5830
+ encodeCloseOrphanSlab,
4577
5831
  encodeCloseSlab,
4578
5832
  encodeCloseStaleSlabs,
4579
- encodeCreateInsuranceMint,
5833
+ encodeCreateLpVault,
4580
5834
  encodeDepositCollateral,
4581
- encodeDepositInsuranceLP,
5835
+ encodeDepositLpCollateral,
4582
5836
  encodeExecuteAdl,
5837
+ encodeForceCloseResolved,
4583
5838
  encodeFundMarketInsurance,
4584
5839
  encodeInitLP,
4585
5840
  encodeInitMarket,
5841
+ encodeInitMatcherCtx,
4586
5842
  encodeInitSharedVault,
4587
5843
  encodeInitUser,
4588
5844
  encodeKeeperCrank,
4589
5845
  encodeLiquidateAtOracle,
5846
+ encodeLpVaultCrankFees,
5847
+ encodeLpVaultDeposit,
4590
5848
  encodeLpVaultWithdraw,
4591
5849
  encodeMintPositionNft,
4592
5850
  encodePauseMarket,
@@ -4595,9 +5853,15 @@ export {
4595
5853
  encodeQueueWithdrawalSV,
4596
5854
  encodeReclaimSlabRent,
4597
5855
  encodeRenounceAdmin,
5856
+ encodeRescueOrphanVault,
5857
+ encodeResolveDispute,
4598
5858
  encodeResolveMarket,
5859
+ encodeResolvePermissionless,
5860
+ encodeSetDexPool,
4599
5861
  encodeSetInsuranceIsolation,
5862
+ encodeSetInsuranceWithdrawPolicy,
4600
5863
  encodeSetMaintenanceFee,
5864
+ encodeSetOffsetPair,
4601
5865
  encodeSetOiImbalanceHardBlock,
4602
5866
  encodeSetOracleAuthority,
4603
5867
  encodeSetOraclePriceCap,
@@ -4638,7 +5902,8 @@ export {
4638
5902
  encodeUpdateRiskParams,
4639
5903
  encodeWithdrawCollateral,
4640
5904
  encodeWithdrawInsurance,
4641
- encodeWithdrawInsuranceLP,
5905
+ encodeWithdrawInsuranceLimited,
5906
+ encodeWithdrawLpCollateral,
4642
5907
  fetchAdlRankedPositions,
4643
5908
  fetchAdlRankings,
4644
5909
  fetchSlab,
@@ -4650,12 +5915,18 @@ export {
4650
5915
  getCurrentNetwork,
4651
5916
  getErrorHint,
4652
5917
  getErrorName,
5918
+ getMarketsByAddress,
4653
5919
  getMatcherProgramId,
4654
5920
  getProgramId,
4655
5921
  getStakeProgramId,
5922
+ getStaticMarkets,
4656
5923
  initPoolAccounts,
4657
5924
  isAccountUsed,
4658
5925
  isAdlTriggered,
5926
+ isAnchorErrorCode,
5927
+ isLighthouseError,
5928
+ isLighthouseFailureInLogs,
5929
+ isLighthouseInstruction,
4659
5930
  isStandardToken,
4660
5931
  isToken2022,
4661
5932
  isValidChainlinkOracle,
@@ -4674,11 +5945,14 @@ export {
4674
5945
  rankAdlPositions,
4675
5946
  readLastThrUpdateSlot,
4676
5947
  readNonce,
5948
+ registerStaticMarkets,
4677
5949
  resolvePrice,
4678
5950
  safeEnv,
4679
5951
  simulateOrSend,
4680
5952
  slabDataSize,
4681
5953
  slabDataSizeV1,
5954
+ stripLighthouseFromTransaction,
5955
+ stripLighthouseInstructions,
4682
5956
  validateAmount,
4683
5957
  validateBps,
4684
5958
  validateI128,
@@ -4689,6 +5963,7 @@ export {
4689
5963
  validateU128,
4690
5964
  validateU16,
4691
5965
  validateU64,
5966
+ withRetry,
4692
5967
  withdrawAccounts
4693
5968
  };
4694
5969
  //# sourceMappingURL=index.js.map