@percolatorct/sdk 1.0.0-beta.24 → 1.0.0-beta.26

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
@@ -226,7 +226,15 @@ var IX_TAG = {
226
226
  /** PauseMarket (tag 76): admin emergency pause. Blocks Trade/Deposit/Withdraw/InitUser. */
227
227
  PauseMarket: 76,
228
228
  /** UnpauseMarket (tag 77): admin unpause. Re-enables all operations. */
229
- UnpauseMarket: 77
229
+ UnpauseMarket: 77,
230
+ /** PERC-305 / SECURITY(H-4): Set PnL cap for ADL pre-check (admin only). */
231
+ SetMaxPnlCap: 78,
232
+ /** PERC-309: Set OI cap multiplier for LP withdrawal limits (admin only). Packed u64. */
233
+ SetOiCapMultiplier: 79,
234
+ /** PERC-314: Set dispute params (window_slots + bond_amount, admin only). */
235
+ SetDisputeParams: 80,
236
+ /** PERC-315: Set LP collateral params (enabled + ltv_bps, admin only). */
237
+ SetLpCollateralParams: 81
230
238
  // 78: removed (keeper fund)
231
239
  };
232
240
  Object.freeze(IX_TAG);
@@ -250,7 +258,7 @@ function encodeFeedId(feedId) {
250
258
  }
251
259
  return bytes;
252
260
  }
253
- var INIT_MARKET_DATA_LEN = 352;
261
+ var INIT_MARKET_DATA_LEN = 344;
254
262
  function encodeInitMarket(args) {
255
263
  const hMin = args.hMin ?? args.warmupPeriodSlots ?? 0n;
256
264
  const hMax = args.hMax ?? args.warmupPeriodSlots ?? 0n;
@@ -280,14 +288,13 @@ function encodeInitMarket(args) {
280
288
  encU128(args.insuranceFloor ?? 0n),
281
289
  // wire slot: old riskReductionThreshold → now insurance_floor
282
290
  encU64(hMax),
283
- // v12.15: h_max (u64) — was low 8 bytes of maintenanceFeePerSlot (u128)
284
- encU64(0n),
285
- // padding (u64) — remaining 8 bytes of old u128 slot
291
+ // h_max (u64)
286
292
  encU64(args.maxCrankStalenessSlots),
293
+ // v12.17: no padding between hMax and maxCrankStalenessSlots
287
294
  encU64(args.liquidationFeeBps),
288
295
  encU128(args.liquidationFeeCap),
289
296
  encU64(args.liquidationBufferBps ?? 0n),
290
- // wire slot: read as resolve_price_deviation_bps by program
297
+ // v12.17: read as resolve_price_deviation_bps by program
291
298
  encU128(args.minLiquidationAbs),
292
299
  encU128(args.minInitialDeposit),
293
300
  encU128(args.minNonzeroMmReq),
@@ -325,12 +332,28 @@ function encodeWithdrawCollateral(args) {
325
332
  encU64(args.amount)
326
333
  );
327
334
  }
335
+ var LiquidationPolicyTag = {
336
+ FullClose: 0,
337
+ ExactPartial: 1,
338
+ TouchOnly: 255
339
+ };
328
340
  function encodeKeeperCrank(args) {
329
- return concatBytes(
341
+ const parts = [
330
342
  encU8(IX_TAG.KeeperCrank),
331
343
  encU16(args.callerIdx),
332
- encU8(args.allowPanic ? 1 : 0)
333
- );
344
+ encU8(1)
345
+ // format_version = 1 (REQUIRED by v12.17)
346
+ ];
347
+ if (args.candidates) {
348
+ for (const c of args.candidates) {
349
+ parts.push(encU16(c.idx));
350
+ parts.push(encU8(c.policy));
351
+ if (c.policy === LiquidationPolicyTag.ExactPartial) {
352
+ parts.push(encU128(c.quantity));
353
+ }
354
+ }
355
+ }
356
+ return concatBytes(...parts);
334
357
  }
335
358
  function encodeTradeNoCpi(args) {
336
359
  return concatBytes(
@@ -357,7 +380,8 @@ function encodeTradeCpi(args) {
357
380
  encU8(IX_TAG.TradeCpi),
358
381
  encU16(args.lpIdx),
359
382
  encU16(args.userIdx),
360
- encI128(args.size)
383
+ encI128(args.size),
384
+ encU64(args.limitPriceE6)
361
385
  );
362
386
  }
363
387
  function encodeTradeCpiV2(args) {
@@ -369,6 +393,9 @@ function encodeTradeCpiV2(args) {
369
393
  encU8(args.bump)
370
394
  );
371
395
  }
396
+ function encodeUnresolveMarket(args) {
397
+ return concatBytes(encU8(IX_TAG.UnresolveMarket), encU64(args.confirmation));
398
+ }
372
399
  function encodeSetRiskThreshold(args) {
373
400
  return concatBytes(
374
401
  encU8(IX_TAG.SetRiskThreshold),
@@ -386,19 +413,10 @@ function encodeUpdateConfig(args) {
386
413
  encU8(IX_TAG.UpdateConfig),
387
414
  encU64(args.fundingHorizonSlots),
388
415
  encU64(args.fundingKBps),
389
- encU128(args.fundingInvScaleNotionalE6),
390
416
  encI64(args.fundingMaxPremiumBps),
391
417
  // Rust: i64 (can be negative)
392
- encI64(args.fundingMaxBpsPerSlot),
418
+ encI64(args.fundingMaxBpsPerSlot)
393
419
  // Rust: i64 (can be negative)
394
- encU128(args.threshFloor),
395
- encU64(args.threshRiskBps),
396
- encU64(args.threshUpdateIntervalSlots),
397
- encU64(args.threshStepBps),
398
- encU64(args.threshAlphaBps),
399
- encU128(args.threshMin),
400
- encU128(args.threshMax),
401
- encU128(args.threshMinStep)
402
420
  );
403
421
  }
404
422
  function encodeSetMaintenanceFee(args) {
@@ -480,23 +498,18 @@ function encodeSetPythOracle(args) {
480
498
  const dv3 = new DataView(buf.buffer);
481
499
  buf[0] = 32;
482
500
  buf.set(args.feedId, 1);
483
- dv3.setBigUint64(
484
- 33,
485
- args.maxStalenessSecs,
486
- /* little-endian */
487
- true
488
- );
501
+ dv3.setBigUint64(33, args.maxStalenessSecs, true);
489
502
  dv3.setUint16(41, args.confFilterBps, true);
490
503
  return buf;
491
504
  }
492
505
  var PYTH_RECEIVER_PROGRAM_ID = "rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ";
493
506
  async function derivePythPriceUpdateAccount(feedId, shardId = 0) {
494
- const { PublicKey: PublicKey15 } = await import("@solana/web3.js");
507
+ const { PublicKey: PublicKey16 } = await import("@solana/web3.js");
495
508
  const shardBuf = new Uint8Array(2);
496
509
  new DataView(shardBuf.buffer).setUint16(0, shardId, true);
497
- const [pda] = PublicKey15.findProgramAddressSync(
510
+ const [pda] = PublicKey16.findProgramAddressSync(
498
511
  [shardBuf, feedId],
499
- new PublicKey15(PYTH_RECEIVER_PROGRAM_ID)
512
+ new PublicKey16(PYTH_RECEIVER_PROGRAM_ID)
500
513
  );
501
514
  return pda.toBase58();
502
515
  }
@@ -737,6 +750,41 @@ function encodeDepositInsuranceLP(args) {
737
750
  function encodeWithdrawInsuranceLP(args) {
738
751
  return encodeLpVaultWithdraw({ lpAmount: args.lpAmount });
739
752
  }
753
+ function encodeSetMaxPnlCap(args) {
754
+ return concatBytes(encU8(IX_TAG.SetMaxPnlCap), encU64(args.cap));
755
+ }
756
+ function encodeSetOiCapMultiplier(args) {
757
+ return concatBytes(encU8(IX_TAG.SetOiCapMultiplier), encU64(args.packed));
758
+ }
759
+ function packOiCap(multiplierBps, softCapBps) {
760
+ if (multiplierBps < 0 || multiplierBps > 4294967295) {
761
+ throw new Error(`packOiCap: multiplier_bps out of u32 range: ${multiplierBps}`);
762
+ }
763
+ if (softCapBps < 0 || softCapBps > 4294967295) {
764
+ throw new Error(`packOiCap: soft_cap_bps out of u32 range: ${softCapBps}`);
765
+ }
766
+ return BigInt(multiplierBps) | BigInt(softCapBps) << 32n;
767
+ }
768
+ function encodeSetDisputeParams(args) {
769
+ return concatBytes(
770
+ encU8(IX_TAG.SetDisputeParams),
771
+ encU64(args.windowSlots),
772
+ encU64(args.bondAmount)
773
+ );
774
+ }
775
+ function encodeSetLpCollateralParams(args) {
776
+ if (args.enabled !== 0 && args.enabled !== 1) {
777
+ throw new Error(`encodeSetLpCollateralParams: enabled must be 0 or 1, got ${args.enabled}`);
778
+ }
779
+ if (args.ltvBps < 0 || args.ltvBps > 1e4) {
780
+ throw new Error(`encodeSetLpCollateralParams: ltvBps ${args.ltvBps} out of range [0, 10000]`);
781
+ }
782
+ return concatBytes(
783
+ encU8(IX_TAG.SetLpCollateralParams),
784
+ encU8(args.enabled),
785
+ encU16(args.ltvBps)
786
+ );
787
+ }
740
788
 
741
789
  // src/abi/accounts.ts
742
790
  import {
@@ -1386,12 +1434,184 @@ function parseErrorFromLogs(logs) {
1386
1434
  return null;
1387
1435
  }
1388
1436
 
1389
- // src/solana/slab.ts
1437
+ // src/abi/nft.ts
1438
+ import { PublicKey as PublicKey4 } from "@solana/web3.js";
1439
+
1440
+ // src/config/program-ids.ts
1390
1441
  import { PublicKey as PublicKey3 } from "@solana/web3.js";
1442
+ function safeEnv(key) {
1443
+ try {
1444
+ return typeof process !== "undefined" && process?.env ? process.env[key] : void 0;
1445
+ } catch {
1446
+ return void 0;
1447
+ }
1448
+ }
1449
+ var PROGRAM_IDS = {
1450
+ devnet: {
1451
+ percolator: "FxfD37s1AZTeWfFQps9Zpebi2dNQ9QSSDtfMKdbsfKrD",
1452
+ matcher: "GTRgyTDfrMvBubALAqtHuQwT8tbGyXid7svXZKtWfC9k"
1453
+ },
1454
+ mainnet: {
1455
+ percolator: "ESa89R5Es3rJ5mnwGybVRG1GrNt9etP11Z5V2QWD4edv",
1456
+ matcher: "GDK8wx38kpiSVSfGTVNiSdptX3Z5R4kQyqh6Q3QX6wmi"
1457
+ }
1458
+ };
1459
+ function getProgramId(network) {
1460
+ const override = safeEnv("PROGRAM_ID");
1461
+ if (override) {
1462
+ console.warn(
1463
+ `[percolator-sdk] PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
1464
+ );
1465
+ return new PublicKey3(override);
1466
+ }
1467
+ const detectedNetwork = getCurrentNetwork();
1468
+ const targetNetwork = network ?? detectedNetwork;
1469
+ const programId = PROGRAM_IDS[targetNetwork].percolator;
1470
+ return new PublicKey3(programId);
1471
+ }
1472
+ function getMatcherProgramId(network) {
1473
+ const override = safeEnv("MATCHER_PROGRAM_ID");
1474
+ if (override) {
1475
+ console.warn(
1476
+ `[percolator-sdk] MATCHER_PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
1477
+ );
1478
+ return new PublicKey3(override);
1479
+ }
1480
+ const detectedNetwork = getCurrentNetwork();
1481
+ const targetNetwork = network ?? detectedNetwork;
1482
+ const programId = PROGRAM_IDS[targetNetwork].matcher;
1483
+ if (!programId) {
1484
+ throw new Error(`Matcher program not deployed on ${targetNetwork}`);
1485
+ }
1486
+ return new PublicKey3(programId);
1487
+ }
1488
+ function getCurrentNetwork() {
1489
+ const network = safeEnv("NETWORK")?.toLowerCase();
1490
+ if (network === "mainnet" || network === "mainnet-beta") {
1491
+ return "mainnet";
1492
+ }
1493
+ return "devnet";
1494
+ }
1495
+
1496
+ // src/abi/nft.ts
1497
+ var NFT_PROGRAM_OVERRIDE = safeEnv("NFT_PROGRAM_ID");
1498
+ var NFT_PROGRAM_ID = new PublicKey4(
1499
+ NFT_PROGRAM_OVERRIDE ?? "FqhKJT9gtScjrmfUuRMjeg7cXNpif1fqsy5Jh65tJmTS"
1500
+ );
1501
+ function getNftProgramId() {
1502
+ return NFT_PROGRAM_ID;
1503
+ }
1504
+ var NFT_IX_TAG = {
1505
+ MintPositionNft: 0,
1506
+ BurnPositionNft: 1,
1507
+ SettleFunding: 2,
1508
+ GetPositionValue: 3,
1509
+ ExecuteTransferHook: 4,
1510
+ EmergencyBurn: 5
1511
+ };
1512
+ function encodeNftMint(userIdx) {
1513
+ const buf = new Uint8Array(3);
1514
+ buf[0] = NFT_IX_TAG.MintPositionNft;
1515
+ buf[1] = userIdx & 255;
1516
+ buf[2] = userIdx >> 8 & 255;
1517
+ return buf;
1518
+ }
1519
+ function encodeNftBurn() {
1520
+ return new Uint8Array([NFT_IX_TAG.BurnPositionNft]);
1521
+ }
1522
+ function encodeNftSettleFunding() {
1523
+ return new Uint8Array([NFT_IX_TAG.SettleFunding]);
1524
+ }
1525
+ function encodeNftEmergencyBurn() {
1526
+ return new Uint8Array([NFT_IX_TAG.EmergencyBurn]);
1527
+ }
1528
+ var ACCOUNTS_NFT_MINT = [
1529
+ "sw",
1530
+ "w",
1531
+ "sw",
1532
+ "w",
1533
+ "r",
1534
+ "r",
1535
+ "r",
1536
+ "r",
1537
+ "r",
1538
+ "w"
1539
+ ];
1540
+ var ACCOUNTS_NFT_BURN = [
1541
+ "s",
1542
+ "w",
1543
+ "w",
1544
+ "w",
1545
+ "r",
1546
+ "r",
1547
+ "r"
1548
+ ];
1549
+ var ACCOUNTS_NFT_EMERGENCY_BURN = [
1550
+ "s",
1551
+ "w",
1552
+ "w",
1553
+ "w",
1554
+ "r",
1555
+ "r",
1556
+ "r"
1557
+ ];
1558
+ var TEXT = new TextEncoder();
1559
+ function idxBuf(userIdx) {
1560
+ const buf = new Uint8Array(2);
1561
+ new DataView(buf.buffer).setUint16(0, userIdx, true);
1562
+ return buf;
1563
+ }
1564
+ function deriveNftPda(slab, userIdx, programId = NFT_PROGRAM_ID) {
1565
+ return PublicKey4.findProgramAddressSync(
1566
+ [TEXT.encode("position_nft"), slab.toBytes(), idxBuf(userIdx)],
1567
+ programId
1568
+ );
1569
+ }
1570
+ function deriveNftMint(slab, userIdx, programId = NFT_PROGRAM_ID) {
1571
+ return PublicKey4.findProgramAddressSync(
1572
+ [TEXT.encode("position_nft_mint"), slab.toBytes(), idxBuf(userIdx)],
1573
+ programId
1574
+ );
1575
+ }
1576
+ function deriveMintAuthority(programId = NFT_PROGRAM_ID) {
1577
+ return PublicKey4.findProgramAddressSync(
1578
+ [TEXT.encode("mint_authority")],
1579
+ programId
1580
+ );
1581
+ }
1582
+ var POSITION_NFT_STATE_LEN = 208;
1583
+ function parsePositionNftAccount(data) {
1584
+ if (data.length < POSITION_NFT_STATE_LEN) {
1585
+ throw new Error(
1586
+ `PositionNft account too small: ${data.length} < ${POSITION_NFT_STATE_LEN}`
1587
+ );
1588
+ }
1589
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
1590
+ return {
1591
+ version: data[8],
1592
+ bump: data[9],
1593
+ slab: new PublicKey4(data.subarray(16, 48)),
1594
+ userIdx: view.getUint16(48, true),
1595
+ nftMint: new PublicKey4(data.subarray(56, 88)),
1596
+ entryPriceE6: view.getBigUint64(88, true),
1597
+ positionSize: view.getBigUint64(96, true),
1598
+ isLong: data[104] === 1,
1599
+ positionBasisQ: view.getBigInt64(112, true) | view.getBigInt64(120, true) << 64n,
1600
+ lastFundingIndexE18: view.getBigInt64(128, true) | view.getBigInt64(136, true) << 64n,
1601
+ mintedAt: view.getBigInt64(144, true),
1602
+ accountId: view.getBigUint64(152, true)
1603
+ };
1604
+ }
1605
+
1606
+ // src/solana/slab.ts
1607
+ import { PublicKey as PublicKey5 } from "@solana/web3.js";
1391
1608
  function dv(data) {
1392
1609
  return new DataView(data.buffer, data.byteOffset, data.byteLength);
1393
1610
  }
1394
1611
  function readU8(data, off) {
1612
+ if (off >= data.length) {
1613
+ throw new RangeError(`readU8: offset ${off} out of bounds (length ${data.length})`);
1614
+ }
1395
1615
  return data[off];
1396
1616
  }
1397
1617
  function readU16LE(data, off) {
@@ -1422,6 +1642,7 @@ function readU128LE(buf, offset) {
1422
1642
  return hi << 64n | lo;
1423
1643
  }
1424
1644
  var MAGIC = 0x504552434f4c4154n;
1645
+ var SLAB_MAGIC = MAGIC;
1425
1646
  var FLAG_RESOLVED = 1 << 0;
1426
1647
  var V0_HEADER_LEN = 72;
1427
1648
  var V0_CONFIG_LEN = 408;
@@ -1690,6 +1911,61 @@ var V12_15_ENGINE_PNL_POS_TOT_OFF = 368;
1690
1911
  var V12_15_ENGINE_PNL_MATURED_POS_TOT_OFF = 384;
1691
1912
  var V12_15_ENGINE_BITMAP_OFF = 862;
1692
1913
  var V12_15_SIZES = /* @__PURE__ */ new Map();
1914
+ var V12_17_ENGINE_OFF = 512;
1915
+ var V12_17_ACCOUNT_SIZE = 368;
1916
+ var V12_17_ENGINE_BITMAP_OFF = 752;
1917
+ var V12_17_RISK_BUF_LEN = 160;
1918
+ var V12_17_ENGINE_OFF_SBF = 504;
1919
+ var V12_17_ACCOUNT_SIZE_SBF = 352;
1920
+ var V12_17_ENGINE_BITMAP_OFF_SBF = 712;
1921
+ var V12_17_ACCT_CAPITAL_OFF = 0;
1922
+ var V12_17_ACCT_KIND_OFF = 16;
1923
+ var V12_17_ACCT_PNL_OFF = 32;
1924
+ var V12_17_ACCT_RESERVED_PNL_OFF = 48;
1925
+ var V12_17_ACCT_POSITION_BASIS_Q_OFF = 64;
1926
+ var V12_17_ACCT_ADL_A_BASIS_OFF = 80;
1927
+ var V12_17_ACCT_ADL_K_SNAP_OFF = 96;
1928
+ var V12_17_ACCT_F_SNAP_OFF = 112;
1929
+ var V12_17_ACCT_ADL_EPOCH_SNAP_OFF = 128;
1930
+ var V12_17_ACCT_MATCHER_PROGRAM_OFF = 136;
1931
+ var V12_17_ACCT_MATCHER_CONTEXT_OFF = 168;
1932
+ var V12_17_ACCT_OWNER_OFF = 200;
1933
+ var V12_17_ACCT_FEE_CREDITS_OFF = 232;
1934
+ var V12_17_ACCT_SCHED_PRESENT_OFF = 248;
1935
+ var V12_17_ACCT_SCHED_REMAINING_Q_OFF = 256;
1936
+ var V12_17_ACCT_SCHED_ANCHOR_Q_OFF = 272;
1937
+ var V12_17_ACCT_SCHED_START_SLOT_OFF = 288;
1938
+ var V12_17_ACCT_SCHED_HORIZON_OFF = 296;
1939
+ var V12_17_ACCT_SCHED_RELEASE_Q_OFF = 304;
1940
+ var V12_17_ACCT_PENDING_PRESENT_OFF = 320;
1941
+ var V12_17_ACCT_PENDING_REMAINING_Q_OFF = 336;
1942
+ var V12_17_ACCT_PENDING_HORIZON_OFF = 352;
1943
+ var V12_17_ACCT_PENDING_CREATED_SLOT_OFF = 360;
1944
+ var V12_17_ENGINE_PARAMS_OFF = 32;
1945
+ var V12_17_ENGINE_CURRENT_SLOT_OFF = 224;
1946
+ var V12_17_ENGINE_MARKET_MODE_OFF = 232;
1947
+ var V12_17_ENGINE_RESOLVED_K_LONG_OFF = 304;
1948
+ var V12_17_ENGINE_RESOLVED_K_SHORT_OFF = 320;
1949
+ var V12_17_ENGINE_RESOLVED_LIVE_PRICE_OFF = 336;
1950
+ var V12_17_ENGINE_C_TOT_OFF = 352;
1951
+ var V12_17_ENGINE_PNL_POS_TOT_OFF = 368;
1952
+ var V12_17_ENGINE_PNL_MATURED_POS_TOT_OFF = 384;
1953
+ var V12_17_ENGINE_NEG_PNL_COUNT_OFF = 648;
1954
+ var V12_17_ENGINE_LAST_ORACLE_PRICE_OFF = 656;
1955
+ var V12_17_ENGINE_FUND_PX_LAST_OFF = 664;
1956
+ var V12_17_ENGINE_F_LONG_NUM_OFF = 688;
1957
+ var V12_17_ENGINE_F_SHORT_NUM_OFF = 704;
1958
+ var V12_17_SBF_ENGINE_CURRENT_SLOT_OFF = 216;
1959
+ var V12_17_SBF_ENGINE_MARKET_MODE_OFF = 224;
1960
+ var V12_17_SBF_ENGINE_C_TOT_OFF = 336;
1961
+ var V12_17_SBF_ENGINE_PNL_POS_TOT_OFF = 352;
1962
+ var V12_17_SBF_ENGINE_PNL_MATURED_POS_TOT_OFF = 368;
1963
+ var V12_17_SBF_ENGINE_NEG_PNL_COUNT_OFF = 616;
1964
+ var V12_17_SBF_ENGINE_LAST_ORACLE_PRICE_OFF = 624;
1965
+ var V12_17_SBF_ENGINE_FUND_PX_LAST_OFF = 632;
1966
+ var V12_17_SBF_ENGINE_F_LONG_NUM_OFF = 648;
1967
+ var V12_17_SBF_ENGINE_F_SHORT_NUM_OFF = 664;
1968
+ var V12_17_SIZES = /* @__PURE__ */ new Map();
1693
1969
  var V1M_ENGINE_OFF = 640;
1694
1970
  var V1M_CONFIG_LEN = 536;
1695
1971
  var V1M_ACCOUNT_SIZE = 248;
@@ -1766,6 +2042,21 @@ for (const n of TIERS) {
1766
2042
  }
1767
2043
  V12_15_SIZES.set(computeSlabSize(V12_15_ENGINE_OFF, V12_15_ENGINE_BITMAP_OFF, V12_15_ACCOUNT_SIZE, 2048, 18), 2048);
1768
2044
  V12_15_SIZES.set(237512, 256);
2045
+ var V12_17_TIERS = [256, 1024, 4096];
2046
+ for (const n of V12_17_TIERS) {
2047
+ const bitmapWords = Math.ceil(n / 64);
2048
+ const bitmapBytes = bitmapWords * 8;
2049
+ const postBitmap = 4;
2050
+ const nextFreeBytes = n * 2;
2051
+ const preAccNative = V12_17_ENGINE_BITMAP_OFF + bitmapBytes + postBitmap + nextFreeBytes;
2052
+ const accountsOffNative = Math.ceil(preAccNative / 16) * 16;
2053
+ const nativeSize = V12_17_ENGINE_OFF + accountsOffNative + n * V12_17_ACCOUNT_SIZE + V12_17_RISK_BUF_LEN;
2054
+ V12_17_SIZES.set(nativeSize, n);
2055
+ const preAccSbf = V12_17_ENGINE_BITMAP_OFF_SBF + bitmapBytes + postBitmap + nextFreeBytes;
2056
+ const accountsOffSbf = Math.ceil(preAccSbf / 8) * 8;
2057
+ const sbfSize = V12_17_ENGINE_OFF_SBF + accountsOffSbf + n * V12_17_ACCOUNT_SIZE_SBF + V12_17_RISK_BUF_LEN;
2058
+ V12_17_SIZES.set(sbfSize, n);
2059
+ }
1769
2060
  var V12_1_SBF_ACCOUNT_SIZE = 280;
1770
2061
  var V12_1_SBF_ENGINE_OFF = 616;
1771
2062
  var V12_1_SBF_BITMAP_OFF = 584;
@@ -2253,6 +2544,14 @@ for (const [label, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Med
2253
2544
  const size = computeSlabSize(V12_15_ENGINE_OFF, V12_15_ENGINE_BITMAP_OFF, V12_15_ACCOUNT_SIZE, n, 18);
2254
2545
  SLAB_TIERS_V12_15[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (v12.15)` };
2255
2546
  }
2547
+ var SLAB_TIERS_V12_17 = {};
2548
+ for (const [label, n] of [["Small", 256], ["Medium", 1024], ["Large", 4096]]) {
2549
+ const bitmapBytes = Math.ceil(n / 64) * 8;
2550
+ const preAcc = V12_17_ENGINE_BITMAP_OFF_SBF + bitmapBytes + 4 + n * 2;
2551
+ const accountsOff = Math.ceil(preAcc / 8) * 8;
2552
+ const size = V12_17_ENGINE_OFF_SBF + accountsOff + n * V12_17_ACCOUNT_SIZE_SBF + V12_17_RISK_BUF_LEN;
2553
+ SLAB_TIERS_V12_17[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (v12.17)` };
2554
+ }
2256
2555
  function buildLayoutVSetDexPool(maxAccounts) {
2257
2556
  const engineOff = V_SETDEXPOOL_ENGINE_OFF;
2258
2557
  const bitmapOff = V_ADL_ENGINE_BITMAP_OFF;
@@ -2551,7 +2850,84 @@ function buildLayoutV12_15(maxAccounts, dataLen) {
2551
2850
  engineInsuranceIsolationBpsOff: -1
2552
2851
  };
2553
2852
  }
2853
+ function buildLayoutV12_17(maxAccounts, dataLen) {
2854
+ const isSbf = (() => {
2855
+ const bitmapBytes2 = Math.ceil(maxAccounts / 64) * 8;
2856
+ const preAccNative = V12_17_ENGINE_BITMAP_OFF + bitmapBytes2 + 4 + maxAccounts * 2;
2857
+ const accountsOffNative = Math.ceil(preAccNative / 16) * 16;
2858
+ const nativeSize = V12_17_ENGINE_OFF + accountsOffNative + maxAccounts * V12_17_ACCOUNT_SIZE + V12_17_RISK_BUF_LEN;
2859
+ return dataLen !== nativeSize;
2860
+ })();
2861
+ const engineOff = isSbf ? V12_17_ENGINE_OFF_SBF : V12_17_ENGINE_OFF;
2862
+ const accountSize = isSbf ? V12_17_ACCOUNT_SIZE_SBF : V12_17_ACCOUNT_SIZE;
2863
+ const bitmapOff = isSbf ? V12_17_ENGINE_BITMAP_OFF_SBF : V12_17_ENGINE_BITMAP_OFF;
2864
+ const bitmapWords = Math.ceil(maxAccounts / 64);
2865
+ const bitmapBytes = bitmapWords * 8;
2866
+ const postBitmap = 4;
2867
+ const nextFreeBytes = maxAccounts * 2;
2868
+ const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;
2869
+ const acctAlign = isSbf ? 8 : 16;
2870
+ const accountsOffRel = Math.ceil(preAccountsLen / acctAlign) * acctAlign;
2871
+ return {
2872
+ version: 2,
2873
+ headerLen: V0_HEADER_LEN,
2874
+ // 72
2875
+ configOffset: V0_HEADER_LEN,
2876
+ // 72
2877
+ configLen: 432,
2878
+ // upstream 400 + dex_pool 32
2879
+ reservedOff: V1_RESERVED_OFF,
2880
+ // 80
2881
+ engineOff,
2882
+ accountSize,
2883
+ maxAccounts,
2884
+ bitmapWords,
2885
+ accountsOff: engineOff + accountsOffRel,
2886
+ engineInsuranceOff: 16,
2887
+ engineParamsOff: V12_17_ENGINE_PARAMS_OFF,
2888
+ // 32
2889
+ paramsSize: isSbf ? 184 : 192,
2890
+ engineCurrentSlotOff: isSbf ? V12_17_SBF_ENGINE_CURRENT_SLOT_OFF : V12_17_ENGINE_CURRENT_SLOT_OFF,
2891
+ engineFundingIndexOff: -1,
2892
+ // replaced by per-side f_long_num/f_short_num
2893
+ engineLastFundingSlotOff: -1,
2894
+ engineFundingRateBpsOff: -1,
2895
+ // no stored funding rate in v12.17
2896
+ engineMarkPriceOff: -1,
2897
+ engineLastCrankSlotOff: -1,
2898
+ engineMaxCrankStalenessOff: -1,
2899
+ engineTotalOiOff: -1,
2900
+ engineLongOiOff: -1,
2901
+ engineShortOiOff: -1,
2902
+ engineCTotOff: isSbf ? V12_17_SBF_ENGINE_C_TOT_OFF : V12_17_ENGINE_C_TOT_OFF,
2903
+ enginePnlPosTotOff: isSbf ? V12_17_SBF_ENGINE_PNL_POS_TOT_OFF : V12_17_ENGINE_PNL_POS_TOT_OFF,
2904
+ engineLiqCursorOff: -1,
2905
+ engineGcCursorOff: -1,
2906
+ engineLastSweepStartOff: -1,
2907
+ engineLastSweepCompleteOff: -1,
2908
+ engineCrankCursorOff: -1,
2909
+ engineSweepStartIdxOff: -1,
2910
+ engineLifetimeLiquidationsOff: -1,
2911
+ engineLifetimeForceClosesOff: -1,
2912
+ engineNetLpPosOff: -1,
2913
+ engineLpSumAbsOff: -1,
2914
+ engineLpMaxAbsOff: -1,
2915
+ engineLpMaxAbsSweepOff: -1,
2916
+ engineEmergencyOiModeOff: -1,
2917
+ engineEmergencyStartSlotOff: -1,
2918
+ engineLastBreakerSlotOff: -1,
2919
+ engineBitmapOff: bitmapOff,
2920
+ postBitmap,
2921
+ acctOwnerOff: isSbf ? 192 : V12_17_ACCT_OWNER_OFF,
2922
+ // SBF=192, native=200
2923
+ hasInsuranceIsolation: false,
2924
+ engineInsuranceIsolatedOff: -1,
2925
+ engineInsuranceIsolationBpsOff: -1
2926
+ };
2927
+ }
2554
2928
  function detectSlabLayout(dataLen, data) {
2929
+ const v1217n = V12_17_SIZES.get(dataLen);
2930
+ if (v1217n !== void 0) return buildLayoutV12_17(v1217n, dataLen);
2555
2931
  const v1215n = V12_15_SIZES.get(dataLen);
2556
2932
  if (v1215n !== void 0) return buildLayoutV12_15(v1215n, dataLen);
2557
2933
  const v121epn = V12_1_EP_SIZES.get(dataLen);
@@ -2681,7 +3057,7 @@ function parseHeader(data) {
2681
3057
  const version = readU32LE(data, 8);
2682
3058
  const bump = readU8(data, 12);
2683
3059
  const flags = readU8(data, 13);
2684
- const admin = new PublicKey3(data.subarray(16, 48));
3060
+ const admin = new PublicKey5(data.subarray(16, 48));
2685
3061
  const layout = detectSlabLayout(data.length, data);
2686
3062
  const roff = layout ? layout.reservedOff : V0_RESERVED_OFF;
2687
3063
  const nonce = readU64LE(data, roff);
@@ -2702,16 +3078,17 @@ function parseConfig(data, layoutHint) {
2702
3078
  const layout = layoutHint !== void 0 ? layoutHint : detectSlabLayout(data.length, data);
2703
3079
  const configOff = layout ? layout.configOffset : V0_HEADER_LEN;
2704
3080
  const configLen = layout ? layout.configLen : V0_CONFIG_LEN;
2705
- const minLen = configOff + Math.min(configLen, 120);
3081
+ const MIN_CONFIG_BYTES = 376;
3082
+ const minLen = configOff + Math.min(configLen, MIN_CONFIG_BYTES);
2706
3083
  if (data.length < minLen) {
2707
3084
  throw new Error(`Slab data too short for config: ${data.length} < ${minLen}`);
2708
3085
  }
2709
3086
  let off = configOff;
2710
- const collateralMint = new PublicKey3(data.subarray(off, off + 32));
3087
+ const collateralMint = new PublicKey5(data.subarray(off, off + 32));
2711
3088
  off += 32;
2712
- const vaultPubkey = new PublicKey3(data.subarray(off, off + 32));
3089
+ const vaultPubkey = new PublicKey5(data.subarray(off, off + 32));
2713
3090
  off += 32;
2714
- const indexFeedId = new PublicKey3(data.subarray(off, off + 32));
3091
+ const indexFeedId = new PublicKey5(data.subarray(off, off + 32));
2715
3092
  off += 32;
2716
3093
  const maxStalenessSlots = readU64LE(data, off);
2717
3094
  off += 8;
@@ -2749,7 +3126,7 @@ function parseConfig(data, layoutHint) {
2749
3126
  off += 16;
2750
3127
  const threshMinStep = readU128LE(data, off);
2751
3128
  off += 16;
2752
- const oracleAuthority = new PublicKey3(data.subarray(off, off + 32));
3129
+ const oracleAuthority = new PublicKey5(data.subarray(off, off + 32));
2753
3130
  off += 32;
2754
3131
  const authorityPriceE6 = readU64LE(data, off);
2755
3132
  off += 8;
@@ -2802,7 +3179,7 @@ function parseConfig(data, layoutHint) {
2802
3179
  if (configLen >= DEX_POOL_REL_OFF + 32 && data.length >= configOff + DEX_POOL_REL_OFF + 32) {
2803
3180
  const dexPoolBytes = data.subarray(configOff + DEX_POOL_REL_OFF, configOff + DEX_POOL_REL_OFF + 32);
2804
3181
  if (dexPoolBytes.some((b) => b !== 0)) {
2805
- dexPool = new PublicKey3(dexPoolBytes);
3182
+ dexPool = new PublicKey5(dexPoolBytes);
2806
3183
  }
2807
3184
  }
2808
3185
  return {
@@ -2857,8 +3234,9 @@ function parseParams(data, layoutHint) {
2857
3234
  const paramsOff = layout ? layout.engineParamsOff : V0_ENGINE_PARAMS_OFF;
2858
3235
  const paramsSize = layout ? layout.paramsSize : V0_PARAMS_SIZE;
2859
3236
  const base = engineOff + paramsOff;
2860
- if (data.length < base + Math.min(paramsSize, 56)) {
2861
- throw new Error("Slab data too short for RiskParams");
3237
+ const MIN_PARAMS_BYTES = paramsSize >= 144 ? 144 : 56;
3238
+ if (data.length < base + MIN_PARAMS_BYTES) {
3239
+ throw new Error(`Slab data too short for RiskParams: ${data.length} < ${base + MIN_PARAMS_BYTES}`);
2862
3240
  }
2863
3241
  const isV12_15Params = paramsSize === V12_15_PARAMS_SIZE || paramsSize === 184;
2864
3242
  const isV12_1Sbf = !isV12_15Params && layout !== null && layout !== void 0 && layout.engineOff === V12_1_SBF_ENGINE_OFF && paramsSize === 184;
@@ -2929,7 +3307,79 @@ function parseEngine(data) {
2929
3307
  throw new Error(`Unrecognized slab data length: ${data.length}. Cannot determine layout version.`);
2930
3308
  }
2931
3309
  const base = layout.engineOff;
2932
- const isV12_15 = (layout.accountSize === V12_15_ACCOUNT_SIZE || layout.accountSize === V12_15_ACCOUNT_SIZE_SMALL) && (layout.engineOff === V12_15_ENGINE_OFF || layout.engineOff === V12_15_ENGINE_OFF_SBF);
3310
+ const isV12_17 = layout.accountSize === V12_17_ACCOUNT_SIZE || layout.accountSize === V12_17_ACCOUNT_SIZE_SBF;
3311
+ const isV12_15 = !isV12_17 && (layout.accountSize === V12_15_ACCOUNT_SIZE || layout.accountSize === V12_15_ACCOUNT_SIZE_SMALL) && (layout.engineOff === V12_15_ENGINE_OFF || layout.engineOff === V12_15_ENGINE_OFF_SBF);
3312
+ if (isV12_17) {
3313
+ const isSbf = layout.engineOff === V12_17_ENGINE_OFF_SBF;
3314
+ const currentSlotOff = isSbf ? V12_17_SBF_ENGINE_CURRENT_SLOT_OFF : V12_17_ENGINE_CURRENT_SLOT_OFF;
3315
+ const marketModeOff = isSbf ? V12_17_SBF_ENGINE_MARKET_MODE_OFF : V12_17_ENGINE_MARKET_MODE_OFF;
3316
+ const cTotOff = isSbf ? V12_17_SBF_ENGINE_C_TOT_OFF : V12_17_ENGINE_C_TOT_OFF;
3317
+ const pnlPosTotOff = isSbf ? V12_17_SBF_ENGINE_PNL_POS_TOT_OFF : V12_17_ENGINE_PNL_POS_TOT_OFF;
3318
+ const pnlMaturedOff = isSbf ? V12_17_SBF_ENGINE_PNL_MATURED_POS_TOT_OFF : V12_17_ENGINE_PNL_MATURED_POS_TOT_OFF;
3319
+ const negPnlOff = isSbf ? V12_17_SBF_ENGINE_NEG_PNL_COUNT_OFF : V12_17_ENGINE_NEG_PNL_COUNT_OFF;
3320
+ const oraclePriceOff = isSbf ? V12_17_SBF_ENGINE_LAST_ORACLE_PRICE_OFF : V12_17_ENGINE_LAST_ORACLE_PRICE_OFF;
3321
+ const fundPxLastOff = isSbf ? V12_17_SBF_ENGINE_FUND_PX_LAST_OFF : V12_17_ENGINE_FUND_PX_LAST_OFF;
3322
+ const fLongNumOff = isSbf ? V12_17_SBF_ENGINE_F_LONG_NUM_OFF : V12_17_ENGINE_F_LONG_NUM_OFF;
3323
+ const fShortNumOff = isSbf ? V12_17_SBF_ENGINE_F_SHORT_NUM_OFF : V12_17_ENGINE_F_SHORT_NUM_OFF;
3324
+ const resolvedKLongOff = isSbf ? 288 : V12_17_ENGINE_RESOLVED_K_LONG_OFF;
3325
+ const resolvedKShortOff = isSbf ? 304 : V12_17_ENGINE_RESOLVED_K_SHORT_OFF;
3326
+ const resolvedLivePriceOff = isSbf ? 320 : V12_17_ENGINE_RESOLVED_LIVE_PRICE_OFF;
3327
+ const bitmapEnd = layout.engineBitmapOff + layout.bitmapWords * 8;
3328
+ return {
3329
+ vault: readU128LE(data, base),
3330
+ insuranceFund: {
3331
+ balance: readU128LE(data, base + 16),
3332
+ feeRevenue: 0n,
3333
+ isolatedBalance: 0n,
3334
+ isolationBps: 0
3335
+ },
3336
+ currentSlot: readU64LE(data, base + currentSlotOff),
3337
+ fundingIndexQpbE6: 0n,
3338
+ // replaced by per-side funding
3339
+ lastFundingSlot: 0n,
3340
+ fundingRateBpsPerSlotLast: 0n,
3341
+ // no stored funding rate in v12.17
3342
+ fundingRateE9: 0n,
3343
+ // no stored funding rate in v12.17
3344
+ marketMode: readU8(data, base + marketModeOff) === 1 ? 1 : 0,
3345
+ lastCrankSlot: 0n,
3346
+ maxCrankStalenessSlots: 0n,
3347
+ totalOpenInterest: 0n,
3348
+ longOi: 0n,
3349
+ shortOi: 0n,
3350
+ cTot: readU128LE(data, base + cTotOff),
3351
+ pnlPosTot: readU128LE(data, base + pnlPosTotOff),
3352
+ pnlMaturedPosTot: readU128LE(data, base + pnlMaturedOff),
3353
+ liqCursor: 0,
3354
+ gcCursor: 0,
3355
+ lastSweepStartSlot: 0n,
3356
+ lastSweepCompleteSlot: 0n,
3357
+ crankCursor: 0,
3358
+ sweepStartIdx: 0,
3359
+ lifetimeLiquidations: 0n,
3360
+ lifetimeForceCloses: 0n,
3361
+ netLpPos: 0n,
3362
+ lpSumAbs: 0n,
3363
+ lpMaxAbs: 0n,
3364
+ lpMaxAbsSweep: 0n,
3365
+ emergencyOiMode: false,
3366
+ emergencyStartSlot: 0n,
3367
+ lastBreakerSlot: 0n,
3368
+ markPriceE6: 0n,
3369
+ oraclePriceE6: readU64LE(data, base + oraclePriceOff),
3370
+ numUsedAccounts: readU16LE(data, base + bitmapEnd),
3371
+ nextAccountId: 0n,
3372
+ // removed in v12.17 (replaced by mat_counter in header)
3373
+ // V12_17 fields
3374
+ fLongNum: readI128LE(data, base + fLongNumOff),
3375
+ fShortNum: readI128LE(data, base + fShortNumOff),
3376
+ negPnlAccountCount: readU64LE(data, base + negPnlOff),
3377
+ fundPxLast: readU64LE(data, base + fundPxLastOff),
3378
+ resolvedKLongTerminalDelta: readI128LE(data, base + resolvedKLongOff),
3379
+ resolvedKShortTerminalDelta: readI128LE(data, base + resolvedKShortOff),
3380
+ resolvedLivePrice: readU64LE(data, base + resolvedLivePriceOff)
3381
+ };
3382
+ }
2933
3383
  const fundingRateBpsPerSlotLast = isV12_15 ? readI128LE(data, base + layout.engineFundingRateBpsOff) : readI64LE(data, base + layout.engineFundingRateBpsOff);
2934
3384
  return {
2935
3385
  vault: readU128LE(data, base),
@@ -2983,7 +3433,15 @@ function parseEngine(data) {
2983
3433
  const bw = layout.bitmapWords;
2984
3434
  const numUsedOff = layout.engineBitmapOff + bw * 8;
2985
3435
  return readU64LE(data, base + Math.ceil((numUsedOff + 2) / 8) * 8);
2986
- })()
3436
+ })(),
3437
+ // V12_17 fields (not present in pre-v12.17)
3438
+ fLongNum: 0n,
3439
+ fShortNum: 0n,
3440
+ negPnlAccountCount: 0n,
3441
+ fundPxLast: 0n,
3442
+ resolvedKLongTerminalDelta: 0n,
3443
+ resolvedKShortTerminalDelta: 0n,
3444
+ resolvedLivePrice: 0n
2987
3445
  };
2988
3446
  }
2989
3447
  function parseUsedIndices(data) {
@@ -3033,10 +3491,65 @@ function parseAccount(data, idx) {
3033
3491
  if (data.length < base + layout.accountSize) {
3034
3492
  throw new Error("Slab data too short for account");
3035
3493
  }
3036
- const isV12_15 = layout.accountSize === V12_15_ACCOUNT_SIZE || layout.accountSize === V12_15_ACCOUNT_SIZE_SMALL;
3037
- const isV12_1EP = !isV12_15 && layout.accountSize === V12_1_EP_SBF_ACCOUNT_SIZE && layout.engineOff === V12_1_SBF_ENGINE_OFF;
3038
- const isV12_1 = !isV12_15 && !isV12_1EP && (layout.engineOff === V12_1_ENGINE_OFF || layout.engineOff === V12_1_SBF_ENGINE_OFF) && (layout.accountSize === V12_1_ACCOUNT_SIZE || layout.accountSize === V12_1_ACCOUNT_SIZE_SBF);
3039
- const isAdl = !isV12_15 && (layout.accountSize >= 312 || isV12_1 || isV12_1EP);
3494
+ const isV12_17 = layout.accountSize === V12_17_ACCOUNT_SIZE || layout.accountSize === V12_17_ACCOUNT_SIZE_SBF;
3495
+ const isV12_15 = !isV12_17 && (layout.accountSize === V12_15_ACCOUNT_SIZE || layout.accountSize === V12_15_ACCOUNT_SIZE_SMALL);
3496
+ const isV12_1EP = !isV12_17 && !isV12_15 && layout.accountSize === V12_1_EP_SBF_ACCOUNT_SIZE && layout.engineOff === V12_1_SBF_ENGINE_OFF;
3497
+ const isV12_1 = !isV12_17 && !isV12_15 && !isV12_1EP && (layout.engineOff === V12_1_ENGINE_OFF || layout.engineOff === V12_1_SBF_ENGINE_OFF) && (layout.accountSize === V12_1_ACCOUNT_SIZE || layout.accountSize === V12_1_ACCOUNT_SIZE_SBF);
3498
+ const isAdl = !isV12_17 && !isV12_15 && (layout.accountSize >= 312 || isV12_1 || isV12_1EP);
3499
+ if (isV12_17) {
3500
+ const isSbf = layout.accountSize === V12_17_ACCOUNT_SIZE_SBF;
3501
+ const d1 = isSbf ? 8 : 0;
3502
+ const d2 = isSbf ? 16 : 0;
3503
+ const kindByte2 = readU8(data, base + V12_17_ACCT_KIND_OFF);
3504
+ const kind2 = kindByte2 === 1 ? 1 /* LP */ : 0 /* User */;
3505
+ return {
3506
+ kind: kind2,
3507
+ accountId: 0n,
3508
+ // removed in v12.17
3509
+ capital: readU128LE(data, base + V12_17_ACCT_CAPITAL_OFF),
3510
+ pnl: readI128LE(data, base + V12_17_ACCT_PNL_OFF - d1),
3511
+ reservedPnl: readU128LE(data, base + V12_17_ACCT_RESERVED_PNL_OFF - d1),
3512
+ warmupStartedAtSlot: 0n,
3513
+ // removed
3514
+ warmupSlopePerStep: 0n,
3515
+ // removed
3516
+ positionSize: readI128LE(data, base + V12_17_ACCT_POSITION_BASIS_Q_OFF - d1),
3517
+ entryPrice: 0n,
3518
+ // removed — compute off-chain from position_basis_q / effective_pos_q
3519
+ fundingIndex: 0n,
3520
+ // replaced by per-side f_long_num/f_short_num + per-account f_snap
3521
+ matcherProgram: new PublicKey5(data.subarray(base + V12_17_ACCT_MATCHER_PROGRAM_OFF - d1, base + V12_17_ACCT_MATCHER_PROGRAM_OFF - d1 + 32)),
3522
+ matcherContext: new PublicKey5(data.subarray(base + V12_17_ACCT_MATCHER_CONTEXT_OFF - d1, base + V12_17_ACCT_MATCHER_CONTEXT_OFF - d1 + 32)),
3523
+ owner: new PublicKey5(data.subarray(base + V12_17_ACCT_OWNER_OFF - d1, base + V12_17_ACCT_OWNER_OFF - d1 + 32)),
3524
+ feeCredits: readI128LE(data, base + V12_17_ACCT_FEE_CREDITS_OFF - d1),
3525
+ lastFeeSlot: 0n,
3526
+ // removed
3527
+ feesEarnedTotal: 0n,
3528
+ // removed in v12.17
3529
+ exactReserveCohorts: null,
3530
+ // replaced by two-bucket warmup
3531
+ exactCohortCount: null,
3532
+ overflowOlder: null,
3533
+ overflowOlderPresent: null,
3534
+ overflowNewest: null,
3535
+ overflowNewestPresent: null,
3536
+ // V12_17 fields
3537
+ fSnap: readI128LE(data, base + V12_17_ACCT_F_SNAP_OFF - d1),
3538
+ adlABasis: readU128LE(data, base + V12_17_ACCT_ADL_A_BASIS_OFF - d1),
3539
+ adlKSnap: readI128LE(data, base + V12_17_ACCT_ADL_K_SNAP_OFF - d1),
3540
+ adlEpochSnap: readU64LE(data, base + V12_17_ACCT_ADL_EPOCH_SNAP_OFF - d1),
3541
+ schedPresent: readU8(data, base + V12_17_ACCT_SCHED_PRESENT_OFF - d1) !== 0,
3542
+ schedRemainingQ: readU128LE(data, base + V12_17_ACCT_SCHED_REMAINING_Q_OFF - d1),
3543
+ schedAnchorQ: readU128LE(data, base + V12_17_ACCT_SCHED_ANCHOR_Q_OFF - d1),
3544
+ schedStartSlot: readU64LE(data, base + V12_17_ACCT_SCHED_START_SLOT_OFF - d1),
3545
+ schedHorizon: readU64LE(data, base + V12_17_ACCT_SCHED_HORIZON_OFF - d1),
3546
+ schedReleaseQ: readU128LE(data, base + V12_17_ACCT_SCHED_RELEASE_Q_OFF - d1),
3547
+ pendingPresent: readU8(data, base + V12_17_ACCT_PENDING_PRESENT_OFF - d1) !== 0,
3548
+ pendingRemainingQ: readU128LE(data, base + V12_17_ACCT_PENDING_REMAINING_Q_OFF - d2),
3549
+ pendingHorizon: readU64LE(data, base + V12_17_ACCT_PENDING_HORIZON_OFF - d2),
3550
+ pendingCreatedSlot: readU64LE(data, base + V12_17_ACCT_PENDING_CREATED_SLOT_OFF - d2)
3551
+ };
3552
+ }
3040
3553
  if (isV12_15) {
3041
3554
  const kindByte2 = readU8(data, base + V12_15_ACCT_KIND_OFF);
3042
3555
  const kind2 = kindByte2 === 1 ? 1 /* LP */ : 0 /* User */;
@@ -3062,9 +3575,9 @@ function parseAccount(data, idx) {
3062
3575
  entryPrice: readU64LE(data, base + V12_15_ACCT_ENTRY_PRICE_OFF),
3063
3576
  fundingIndex: 0n,
3064
3577
  // not present in v12.15 account struct
3065
- matcherProgram: new PublicKey3(data.subarray(base + V12_15_ACCT_MATCHER_PROGRAM_OFF, base + V12_15_ACCT_MATCHER_PROGRAM_OFF + 32)),
3066
- matcherContext: new PublicKey3(data.subarray(base + V12_15_ACCT_MATCHER_CONTEXT_OFF, base + V12_15_ACCT_MATCHER_CONTEXT_OFF + 32)),
3067
- owner: new PublicKey3(data.subarray(base + V12_15_ACCT_OWNER_OFF, base + V12_15_ACCT_OWNER_OFF + 32)),
3578
+ matcherProgram: new PublicKey5(data.subarray(base + V12_15_ACCT_MATCHER_PROGRAM_OFF, base + V12_15_ACCT_MATCHER_PROGRAM_OFF + 32)),
3579
+ matcherContext: new PublicKey5(data.subarray(base + V12_15_ACCT_MATCHER_CONTEXT_OFF, base + V12_15_ACCT_MATCHER_CONTEXT_OFF + 32)),
3580
+ owner: new PublicKey5(data.subarray(base + V12_15_ACCT_OWNER_OFF, base + V12_15_ACCT_OWNER_OFF + 32)),
3068
3581
  feeCredits: readI128LE(data, base + V12_15_ACCT_FEE_CREDITS_OFF),
3069
3582
  lastFeeSlot: 0n,
3070
3583
  // removed in v12.15
@@ -3074,7 +3587,22 @@ function parseAccount(data, idx) {
3074
3587
  overflowOlder: data.slice(base + V12_15_ACCT_OVERFLOW_OLDER_OFF, base + V12_15_ACCT_OVERFLOW_OLDER_OFF + 64),
3075
3588
  overflowOlderPresent,
3076
3589
  overflowNewest: data.slice(base + V12_15_ACCT_OVERFLOW_NEWEST_OFF, base + V12_15_ACCT_OVERFLOW_NEWEST_OFF + 64),
3077
- overflowNewestPresent
3590
+ overflowNewestPresent,
3591
+ // v12.17 fields (not present in v12.15)
3592
+ fSnap: 0n,
3593
+ adlABasis: 0n,
3594
+ adlKSnap: 0n,
3595
+ adlEpochSnap: 0n,
3596
+ schedPresent: null,
3597
+ schedRemainingQ: null,
3598
+ schedAnchorQ: null,
3599
+ schedStartSlot: null,
3600
+ schedHorizon: null,
3601
+ schedReleaseQ: null,
3602
+ pendingPresent: null,
3603
+ pendingRemainingQ: null,
3604
+ pendingHorizon: null,
3605
+ pendingCreatedSlot: null
3078
3606
  };
3079
3607
  }
3080
3608
  const warmupStartedOff = isAdl ? V_ADL_ACCT_WARMUP_STARTED_OFF : ACCT_WARMUP_STARTED_OFF;
@@ -3100,9 +3628,9 @@ function parseAccount(data, idx) {
3100
3628
  entryPrice: entryPriceOff >= 0 ? readU64LE(data, base + entryPriceOff) : 0n,
3101
3629
  // V12_1/V12_1_EP: funding_index not present in SBF layout
3102
3630
  fundingIndex: isV12_1 || isV12_1EP ? fundingIndexOff >= 0 ? BigInt(readI64LE(data, base + fundingIndexOff)) : 0n : readI128LE(data, base + fundingIndexOff),
3103
- matcherProgram: new PublicKey3(data.subarray(base + matcherProgOff, base + matcherProgOff + 32)),
3104
- matcherContext: new PublicKey3(data.subarray(base + matcherCtxOff, base + matcherCtxOff + 32)),
3105
- owner: new PublicKey3(data.subarray(base + layout.acctOwnerOff, base + layout.acctOwnerOff + 32)),
3631
+ matcherProgram: new PublicKey5(data.subarray(base + matcherProgOff, base + matcherProgOff + 32)),
3632
+ matcherContext: new PublicKey5(data.subarray(base + matcherCtxOff, base + matcherCtxOff + 32)),
3633
+ owner: new PublicKey5(data.subarray(base + layout.acctOwnerOff, base + layout.acctOwnerOff + 32)),
3106
3634
  feeCredits: readI128LE(data, base + feeCreditsOff),
3107
3635
  lastFeeSlot: readU64LE(data, base + lastFeeSlotOff),
3108
3636
  feesEarnedTotal: 0n,
@@ -3113,7 +3641,22 @@ function parseAccount(data, idx) {
3113
3641
  overflowOlder: null,
3114
3642
  overflowOlderPresent: null,
3115
3643
  overflowNewest: null,
3116
- overflowNewestPresent: null
3644
+ overflowNewestPresent: null,
3645
+ // v12.17 fields (not present in pre-v12.17)
3646
+ fSnap: 0n,
3647
+ adlABasis: 0n,
3648
+ adlKSnap: 0n,
3649
+ adlEpochSnap: 0n,
3650
+ schedPresent: null,
3651
+ schedRemainingQ: null,
3652
+ schedAnchorQ: null,
3653
+ schedStartSlot: null,
3654
+ schedHorizon: null,
3655
+ schedReleaseQ: null,
3656
+ pendingPresent: null,
3657
+ pendingRemainingQ: null,
3658
+ pendingHorizon: null,
3659
+ pendingCreatedSlot: null
3117
3660
  };
3118
3661
  }
3119
3662
  function parseAllAccounts(data) {
@@ -3133,16 +3676,16 @@ function parseAllAccounts(data) {
3133
3676
  }
3134
3677
 
3135
3678
  // src/solana/pda.ts
3136
- import { PublicKey as PublicKey4 } from "@solana/web3.js";
3679
+ import { PublicKey as PublicKey6 } from "@solana/web3.js";
3137
3680
  var textEncoder = new TextEncoder();
3138
3681
  function deriveVaultAuthority(programId, slab) {
3139
- return PublicKey4.findProgramAddressSync(
3682
+ return PublicKey6.findProgramAddressSync(
3140
3683
  [textEncoder.encode("vault"), slab.toBytes()],
3141
3684
  programId
3142
3685
  );
3143
3686
  }
3144
3687
  function deriveInsuranceLpMint(programId, slab) {
3145
- return PublicKey4.findProgramAddressSync(
3688
+ return PublicKey6.findProgramAddressSync(
3146
3689
  [textEncoder.encode("ins_lp"), slab.toBytes()],
3147
3690
  programId
3148
3691
  );
@@ -3154,28 +3697,28 @@ function deriveLpPda(programId, slab, lpIdx) {
3154
3697
  `deriveLpPda: lpIdx must be an integer in [0, ${LP_INDEX_U16_MAX}], got ${lpIdx}`
3155
3698
  );
3156
3699
  }
3157
- const idxBuf = new Uint8Array(2);
3158
- new DataView(idxBuf.buffer).setUint16(0, lpIdx, true);
3159
- return PublicKey4.findProgramAddressSync(
3160
- [textEncoder.encode("lp"), slab.toBytes(), idxBuf],
3700
+ const idxBuf2 = new Uint8Array(2);
3701
+ new DataView(idxBuf2.buffer).setUint16(0, lpIdx, true);
3702
+ return PublicKey6.findProgramAddressSync(
3703
+ [textEncoder.encode("lp"), slab.toBytes(), idxBuf2],
3161
3704
  programId
3162
3705
  );
3163
3706
  }
3164
- var PUMPSWAP_PROGRAM_ID = new PublicKey4(
3707
+ var PUMPSWAP_PROGRAM_ID = new PublicKey6(
3165
3708
  "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA"
3166
3709
  );
3167
- var RAYDIUM_CLMM_PROGRAM_ID = new PublicKey4(
3710
+ var RAYDIUM_CLMM_PROGRAM_ID = new PublicKey6(
3168
3711
  "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK"
3169
3712
  );
3170
- var METEORA_DLMM_PROGRAM_ID = new PublicKey4(
3713
+ var METEORA_DLMM_PROGRAM_ID = new PublicKey6(
3171
3714
  "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo"
3172
3715
  );
3173
- var PYTH_PUSH_ORACLE_PROGRAM_ID = new PublicKey4(
3716
+ var PYTH_PUSH_ORACLE_PROGRAM_ID = new PublicKey6(
3174
3717
  "pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT"
3175
3718
  );
3176
3719
  var CREATOR_LOCK_SEED = "creator_lock";
3177
3720
  function deriveCreatorLockPda(programId, slab) {
3178
- return PublicKey4.findProgramAddressSync(
3721
+ return PublicKey6.findProgramAddressSync(
3179
3722
  [textEncoder.encode(CREATOR_LOCK_SEED), slab.toBytes()],
3180
3723
  programId
3181
3724
  );
@@ -3200,7 +3743,7 @@ function derivePythPushOraclePDA(feedIdHex) {
3200
3743
  feedId[i] = parseInt(normalized.substring(i * 2, i * 2 + 2), 16);
3201
3744
  }
3202
3745
  const shardBuf = new Uint8Array(2);
3203
- return PublicKey4.findProgramAddressSync(
3746
+ return PublicKey6.findProgramAddressSync(
3204
3747
  [shardBuf, feedId],
3205
3748
  PYTH_PUSH_ORACLE_PROGRAM_ID
3206
3749
  );
@@ -3224,10 +3767,10 @@ async function fetchTokenAccount(connection, address, tokenProgramId = TOKEN_PRO
3224
3767
  }
3225
3768
 
3226
3769
  // src/solana/discovery.ts
3227
- import { PublicKey as PublicKey6 } from "@solana/web3.js";
3770
+ import { PublicKey as PublicKey8 } from "@solana/web3.js";
3228
3771
 
3229
3772
  // src/solana/static-markets.ts
3230
- import { PublicKey as PublicKey5 } from "@solana/web3.js";
3773
+ import { PublicKey as PublicKey7 } from "@solana/web3.js";
3231
3774
  var MAINNET_MARKETS = [
3232
3775
  { slabAddress: "7psyeWRts4pRX2cyAWD1NH87bR9ugXP7pe6ARgfG79Do", symbol: "SOL-PERP", name: "SOL/USDC Perpetual" }
3233
3776
  ];
@@ -3263,7 +3806,7 @@ function registerStaticMarkets(network, entries) {
3263
3806
  if (!entry.slabAddress) continue;
3264
3807
  if (seen.has(entry.slabAddress)) continue;
3265
3808
  try {
3266
- new PublicKey5(entry.slabAddress);
3809
+ new PublicKey7(entry.slabAddress);
3267
3810
  } catch {
3268
3811
  console.warn(
3269
3812
  `[registerStaticMarkets] Skipping invalid slabAddress: ${entry.slabAddress}`
@@ -3287,10 +3830,9 @@ function clearStaticMarkets(network) {
3287
3830
  var ENGINE_BITMAP_OFF_V0 = 320;
3288
3831
  var MAGIC_BYTES = new Uint8Array([84, 65, 76, 79, 67, 82, 69, 80]);
3289
3832
  var SLAB_TIERS = {
3290
- micro: SLAB_TIERS_V12_1["micro"],
3291
- small: SLAB_TIERS_V12_1["small"],
3292
- medium: SLAB_TIERS_V12_1["medium"],
3293
- large: SLAB_TIERS_V12_1["large"]
3833
+ small: SLAB_TIERS_V12_17["small"],
3834
+ medium: SLAB_TIERS_V12_17["medium"],
3835
+ large: SLAB_TIERS_V12_17["large"]
3294
3836
  };
3295
3837
  var SLAB_TIERS_V0 = {
3296
3838
  small: { maxAccounts: 256, dataSize: 62808, label: "Small", description: "256 slots \xB7 ~0.44 SOL" },
@@ -3425,6 +3967,13 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3425
3967
  markPriceE6: 0n,
3426
3968
  // V0 engine has no mark_price field
3427
3969
  oraclePriceE6: 0n,
3970
+ fLongNum: 0n,
3971
+ fShortNum: 0n,
3972
+ negPnlAccountCount: 0n,
3973
+ fundPxLast: 0n,
3974
+ resolvedKLongTerminalDelta: 0n,
3975
+ resolvedKShortTerminalDelta: 0n,
3976
+ resolvedLivePrice: 0n,
3428
3977
  numUsedAccounts: canReadNumUsed ? readU16LE2(data, base + numUsedOff) : 0,
3429
3978
  nextAccountId: canReadNextId ? readU64LE2(data, base + nextAccountIdOff) : 0n
3430
3979
  };
@@ -3474,6 +4023,13 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3474
4023
  markPriceE6: 0n,
3475
4024
  // V2 has no mark_price
3476
4025
  oraclePriceE6: 0n,
4026
+ fLongNum: 0n,
4027
+ fShortNum: 0n,
4028
+ negPnlAccountCount: 0n,
4029
+ fundPxLast: 0n,
4030
+ resolvedKLongTerminalDelta: 0n,
4031
+ resolvedKShortTerminalDelta: 0n,
4032
+ resolvedLivePrice: 0n,
3477
4033
  numUsedAccounts: canReadNumUsed ? readU16LE2(data, base + numUsedOff) : 0,
3478
4034
  nextAccountId: canReadNextId ? readU64LE2(data, base + nextAccountIdOff) : 0n
3479
4035
  };
@@ -3520,6 +4076,13 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3520
4076
  lastBreakerSlot: l.engineLastBreakerSlotOff >= 0 ? readU64LE2(data, base + l.engineLastBreakerSlotOff) : 0n,
3521
4077
  markPriceE6: l.engineMarkPriceOff >= 0 ? readU64LE2(data, base + l.engineMarkPriceOff) : 0n,
3522
4078
  oraclePriceE6: 0n,
4079
+ fLongNum: 0n,
4080
+ fShortNum: 0n,
4081
+ negPnlAccountCount: 0n,
4082
+ fundPxLast: 0n,
4083
+ resolvedKLongTerminalDelta: 0n,
4084
+ resolvedKShortTerminalDelta: 0n,
4085
+ resolvedLivePrice: 0n,
3523
4086
  numUsedAccounts: canReadNumUsed ? readU16LE2(data, base + numUsedOff) : 0,
3524
4087
  nextAccountId: canReadNextId ? readU64LE2(data, base + nextAccountIdOff) : 0n
3525
4088
  };
@@ -3565,6 +4128,13 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3565
4128
  markPriceE6: readU64LE2(data, base + 400),
3566
4129
  // PERC-1094: was 392
3567
4130
  oraclePriceE6: 0n,
4131
+ fLongNum: 0n,
4132
+ fShortNum: 0n,
4133
+ negPnlAccountCount: 0n,
4134
+ fundPxLast: 0n,
4135
+ resolvedKLongTerminalDelta: 0n,
4136
+ resolvedKShortTerminalDelta: 0n,
4137
+ resolvedLivePrice: 0n,
3568
4138
  numUsedAccounts: canReadNumUsed ? readU16LE2(data, base + numUsedOff) : 0,
3569
4139
  nextAccountId: canReadNextId ? readU64LE2(data, base + nextAccountIdOff) : 0n
3570
4140
  };
@@ -3586,12 +4156,19 @@ async function discoverMarkets(connection, programId, options = {}) {
3586
4156
  } = options;
3587
4157
  const ALL_TIERS = [
3588
4158
  ...Object.values(SLAB_TIERS),
4159
+ // v12.17 (default)
4160
+ ...Object.values(SLAB_TIERS_V12_15),
4161
+ // v12.15
4162
+ ...Object.values(SLAB_TIERS_V12_1),
4163
+ // v12.1
3589
4164
  ...Object.values(SLAB_TIERS_V0),
3590
4165
  ...Object.values(SLAB_TIERS_V1D),
3591
4166
  ...Object.values(SLAB_TIERS_V1D_LEGACY),
3592
4167
  ...Object.values(SLAB_TIERS_V2),
3593
4168
  ...Object.values(SLAB_TIERS_V1M),
3594
- ...Object.values(SLAB_TIERS_V_ADL)
4169
+ ...Object.values(SLAB_TIERS_V1M2),
4170
+ ...Object.values(SLAB_TIERS_V_ADL),
4171
+ ...Object.values(SLAB_TIERS_V_SETDEXPOOL)
3595
4172
  ];
3596
4173
  let rawAccounts = [];
3597
4174
  async function fetchTierWithRetry(tier) {
@@ -3889,7 +4466,7 @@ async function discoverMarketsViaApi(connection, programId, apiBaseUrl, options
3889
4466
  for (const entry of apiMarkets) {
3890
4467
  if (!entry.slab_address || typeof entry.slab_address !== "string") continue;
3891
4468
  try {
3892
- addresses.push(new PublicKey6(entry.slab_address));
4469
+ addresses.push(new PublicKey8(entry.slab_address));
3893
4470
  } catch {
3894
4471
  console.warn(
3895
4472
  `[discoverMarketsViaApi] Skipping invalid slab address: ${entry.slab_address}`
@@ -3911,7 +4488,7 @@ async function discoverMarketsViaStaticBundle(connection, programId, entries, op
3911
4488
  for (const entry of entries) {
3912
4489
  if (!entry.slabAddress || typeof entry.slabAddress !== "string") continue;
3913
4490
  try {
3914
- addresses.push(new PublicKey6(entry.slabAddress));
4491
+ addresses.push(new PublicKey8(entry.slabAddress));
3915
4492
  } catch {
3916
4493
  console.warn(
3917
4494
  `[discoverMarketsViaStaticBundle] Skipping invalid slab address: ${entry.slabAddress}`
@@ -3929,7 +4506,7 @@ async function discoverMarketsViaStaticBundle(connection, programId, entries, op
3929
4506
  }
3930
4507
 
3931
4508
  // src/solana/dex-oracle.ts
3932
- import { PublicKey as PublicKey7 } from "@solana/web3.js";
4509
+ import { PublicKey as PublicKey9 } from "@solana/web3.js";
3933
4510
  function detectDexType(ownerProgramId) {
3934
4511
  if (ownerProgramId.equals(PUMPSWAP_PROGRAM_ID)) return "pumpswap";
3935
4512
  if (ownerProgramId.equals(RAYDIUM_CLMM_PROGRAM_ID)) return "raydium-clmm";
@@ -3965,10 +4542,10 @@ function parsePumpSwapPool(poolAddress, data) {
3965
4542
  return {
3966
4543
  dexType: "pumpswap",
3967
4544
  poolAddress,
3968
- baseMint: new PublicKey7(data.slice(35, 67)),
3969
- quoteMint: new PublicKey7(data.slice(67, 99)),
3970
- baseVault: new PublicKey7(data.slice(131, 163)),
3971
- quoteVault: new PublicKey7(data.slice(163, 195))
4545
+ baseMint: new PublicKey9(data.slice(35, 67)),
4546
+ quoteMint: new PublicKey9(data.slice(67, 99)),
4547
+ baseVault: new PublicKey9(data.slice(131, 163)),
4548
+ quoteVault: new PublicKey9(data.slice(163, 195))
3972
4549
  };
3973
4550
  }
3974
4551
  var SPL_TOKEN_AMOUNT_MIN_LEN = 72;
@@ -3994,8 +4571,8 @@ function parseRaydiumClmmPool(poolAddress, data) {
3994
4571
  return {
3995
4572
  dexType: "raydium-clmm",
3996
4573
  poolAddress,
3997
- baseMint: new PublicKey7(data.slice(73, 105)),
3998
- quoteMint: new PublicKey7(data.slice(105, 137))
4574
+ baseMint: new PublicKey9(data.slice(73, 105)),
4575
+ quoteMint: new PublicKey9(data.slice(105, 137))
3999
4576
  };
4000
4577
  }
4001
4578
  var MAX_TOKEN_DECIMALS = 24;
@@ -4034,8 +4611,8 @@ function parseMeteoraPool(poolAddress, data) {
4034
4611
  return {
4035
4612
  dexType: "meteora-dlmm",
4036
4613
  poolAddress,
4037
- baseMint: new PublicKey7(data.slice(81, 113)),
4038
- quoteMint: new PublicKey7(data.slice(113, 145))
4614
+ baseMint: new PublicKey9(data.slice(81, 113)),
4615
+ quoteMint: new PublicKey9(data.slice(113, 145))
4039
4616
  };
4040
4617
  }
4041
4618
  var MAX_BIN_STEP = 1e4;
@@ -4130,9 +4707,9 @@ function isValidChainlinkOracle(data) {
4130
4707
  }
4131
4708
 
4132
4709
  // src/solana/token-program.ts
4133
- import { PublicKey as PublicKey8 } from "@solana/web3.js";
4710
+ import { PublicKey as PublicKey10 } from "@solana/web3.js";
4134
4711
  import { TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID3 } from "@solana/spl-token";
4135
- var TOKEN_2022_PROGRAM_ID = new PublicKey8(
4712
+ var TOKEN_2022_PROGRAM_ID = new PublicKey10(
4136
4713
  "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
4137
4714
  );
4138
4715
  async function detectTokenProgram(connection, mint) {
@@ -4148,66 +4725,8 @@ function isStandardToken(tokenProgramId) {
4148
4725
  }
4149
4726
 
4150
4727
  // src/solana/stake.ts
4151
- 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";
4728
+ import { PublicKey as PublicKey11, SystemProgram as SystemProgram2, SYSVAR_RENT_PUBKEY as SYSVAR_RENT_PUBKEY2, SYSVAR_CLOCK_PUBKEY as SYSVAR_CLOCK_PUBKEY2 } from "@solana/web3.js";
4152
4729
  import { TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID4 } from "@solana/spl-token";
4153
-
4154
- // src/config/program-ids.ts
4155
- import { PublicKey as PublicKey9 } from "@solana/web3.js";
4156
- function safeEnv(key) {
4157
- try {
4158
- return typeof process !== "undefined" && process?.env ? process.env[key] : void 0;
4159
- } catch {
4160
- return void 0;
4161
- }
4162
- }
4163
- var PROGRAM_IDS = {
4164
- devnet: {
4165
- percolator: "FxfD37s1AZTeWfFQps9Zpebi2dNQ9QSSDtfMKdbsfKrD",
4166
- matcher: "GTRgyTDfrMvBubALAqtHuQwT8tbGyXid7svXZKtWfC9k"
4167
- },
4168
- mainnet: {
4169
- percolator: "ESa89R5Es3rJ5mnwGybVRG1GrNt9etP11Z5V2QWD4edv",
4170
- matcher: "DHP6DtwXP1yJsz8YzfoeigRFPB979gzmumkmCxDLSkUX"
4171
- }
4172
- };
4173
- function getProgramId(network) {
4174
- const override = safeEnv("PROGRAM_ID");
4175
- if (override) {
4176
- console.warn(
4177
- `[percolator-sdk] PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
4178
- );
4179
- return new PublicKey9(override);
4180
- }
4181
- const detectedNetwork = getCurrentNetwork();
4182
- const targetNetwork = network ?? detectedNetwork;
4183
- const programId = PROGRAM_IDS[targetNetwork].percolator;
4184
- return new PublicKey9(programId);
4185
- }
4186
- function getMatcherProgramId(network) {
4187
- const override = safeEnv("MATCHER_PROGRAM_ID");
4188
- if (override) {
4189
- console.warn(
4190
- `[percolator-sdk] MATCHER_PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
4191
- );
4192
- return new PublicKey9(override);
4193
- }
4194
- const detectedNetwork = getCurrentNetwork();
4195
- const targetNetwork = network ?? detectedNetwork;
4196
- const programId = PROGRAM_IDS[targetNetwork].matcher;
4197
- if (!programId) {
4198
- throw new Error(`Matcher program not deployed on ${targetNetwork}`);
4199
- }
4200
- return new PublicKey9(programId);
4201
- }
4202
- function getCurrentNetwork() {
4203
- const network = safeEnv("NETWORK")?.toLowerCase();
4204
- if (network === "mainnet" || network === "mainnet-beta") {
4205
- return "mainnet";
4206
- }
4207
- return "devnet";
4208
- }
4209
-
4210
- // src/solana/stake.ts
4211
4730
  var STAKE_PROGRAM_IDS = {
4212
4731
  devnet: "6aJb1F9CDCVWCNYFwj8aQsVb696YnW6J1FznteHq4Q6k",
4213
4732
  mainnet: "DC5fovFQD5SZYsetwvEqd4Wi4PFY1Yfnc669VMe6oa7F"
@@ -4218,7 +4737,7 @@ function getStakeProgramId(network) {
4218
4737
  console.warn(
4219
4738
  `[percolator-sdk] STAKE_PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
4220
4739
  );
4221
- return new PublicKey10(override);
4740
+ return new PublicKey11(override);
4222
4741
  }
4223
4742
  const detectedNetwork = network ?? (() => {
4224
4743
  const n = safeEnv("NEXT_PUBLIC_DEFAULT_NETWORK")?.toLowerCase() ?? safeEnv("NETWORK")?.toLowerCase() ?? "";
@@ -4233,9 +4752,9 @@ function getStakeProgramId(network) {
4233
4752
  `Stake program not deployed on ${detectedNetwork}. Set STAKE_PROGRAM_ID env var or wait for DevOps to deploy and update STAKE_PROGRAM_IDS.mainnet.`
4234
4753
  );
4235
4754
  }
4236
- return new PublicKey10(id);
4755
+ return new PublicKey11(id);
4237
4756
  }
4238
- var STAKE_PROGRAM_ID = new PublicKey10(STAKE_PROGRAM_IDS.devnet);
4757
+ var STAKE_PROGRAM_ID = new PublicKey11(STAKE_PROGRAM_IDS.devnet);
4239
4758
  var STAKE_IX = {
4240
4759
  InitPool: 0,
4241
4760
  Deposit: 1,
@@ -4260,22 +4779,22 @@ var STAKE_IX = {
4260
4779
  /** PERC-303: Deposit into junior (first-loss) tranche */
4261
4780
  DepositJunior: 16
4262
4781
  };
4263
- var TEXT = new TextEncoder();
4782
+ var TEXT2 = new TextEncoder();
4264
4783
  function deriveStakePool(slab, programId) {
4265
- return PublicKey10.findProgramAddressSync(
4266
- [TEXT.encode("stake_pool"), slab.toBytes()],
4784
+ return PublicKey11.findProgramAddressSync(
4785
+ [TEXT2.encode("stake_pool"), slab.toBytes()],
4267
4786
  programId ?? getStakeProgramId()
4268
4787
  );
4269
4788
  }
4270
4789
  function deriveStakeVaultAuth(pool, programId) {
4271
- return PublicKey10.findProgramAddressSync(
4272
- [TEXT.encode("vault_auth"), pool.toBytes()],
4790
+ return PublicKey11.findProgramAddressSync(
4791
+ [TEXT2.encode("vault_auth"), pool.toBytes()],
4273
4792
  programId ?? getStakeProgramId()
4274
4793
  );
4275
4794
  }
4276
4795
  function deriveDepositPda(pool, user, programId) {
4277
- return PublicKey10.findProgramAddressSync(
4278
- [TEXT.encode("stake_deposit"), pool.toBytes(), user.toBytes()],
4796
+ return PublicKey11.findProgramAddressSync(
4797
+ [TEXT2.encode("stake_deposit"), pool.toBytes(), user.toBytes()],
4279
4798
  programId ?? getStakeProgramId()
4280
4799
  );
4281
4800
  }
@@ -4425,15 +4944,15 @@ function decodeStakePool(data) {
4425
4944
  const adminTransferred = bytes[off] === 1;
4426
4945
  off += 1;
4427
4946
  off += 4;
4428
- const slab = new PublicKey10(bytes.subarray(off, off + 32));
4947
+ const slab = new PublicKey11(bytes.subarray(off, off + 32));
4429
4948
  off += 32;
4430
- const admin = new PublicKey10(bytes.subarray(off, off + 32));
4949
+ const admin = new PublicKey11(bytes.subarray(off, off + 32));
4431
4950
  off += 32;
4432
- const collateralMint = new PublicKey10(bytes.subarray(off, off + 32));
4951
+ const collateralMint = new PublicKey11(bytes.subarray(off, off + 32));
4433
4952
  off += 32;
4434
- const lpMint = new PublicKey10(bytes.subarray(off, off + 32));
4953
+ const lpMint = new PublicKey11(bytes.subarray(off, off + 32));
4435
4954
  off += 32;
4436
- const vault = new PublicKey10(bytes.subarray(off, off + 32));
4955
+ const vault = new PublicKey11(bytes.subarray(off, off + 32));
4437
4956
  off += 32;
4438
4957
  const totalDeposited = readU64LE4(bytes, off);
4439
4958
  off += 8;
@@ -4449,7 +4968,7 @@ function decodeStakePool(data) {
4449
4968
  off += 8;
4450
4969
  const totalWithdrawn = readU64LE4(bytes, off);
4451
4970
  off += 8;
4452
- const percolatorProgram = new PublicKey10(bytes.subarray(off, off + 32));
4971
+ const percolatorProgram = new PublicKey11(bytes.subarray(off, off + 32));
4453
4972
  off += 32;
4454
4973
  const totalFeesEarned = readU64LE4(bytes, off);
4455
4974
  off += 8;
@@ -4501,6 +5020,20 @@ function decodeStakePool(data) {
4501
5020
  juniorFeeMultBps
4502
5021
  };
4503
5022
  }
5023
+ var STAKE_DEPOSIT_SIZE = 152;
5024
+ function decodeDepositPda(data) {
5025
+ if (data.length < STAKE_DEPOSIT_SIZE) {
5026
+ throw new Error(`StakeDeposit data too short: ${data.length} < ${STAKE_DEPOSIT_SIZE}`);
5027
+ }
5028
+ return {
5029
+ isInitialized: data[0] === 1,
5030
+ bump: data[1],
5031
+ pool: new PublicKey11(data.subarray(8, 40)),
5032
+ user: new PublicKey11(data.subarray(40, 72)),
5033
+ lastDepositSlot: readU64LE4(data, 72),
5034
+ lpAmount: readU64LE4(data, 80)
5035
+ };
5036
+ }
4504
5037
  function initPoolAccounts(a) {
4505
5038
  return [
4506
5039
  { pubkey: a.admin, isSigner: true, isWritable: true },
@@ -5229,8 +5762,8 @@ function formatResult(result, jsonMode) {
5229
5762
  }
5230
5763
 
5231
5764
  // src/runtime/lighthouse.ts
5232
- import { PublicKey as PublicKey13, Transaction as Transaction2 } from "@solana/web3.js";
5233
- var LIGHTHOUSE_PROGRAM_ID = new PublicKey13(
5765
+ import { PublicKey as PublicKey14, Transaction as Transaction2 } from "@solana/web3.js";
5766
+ var LIGHTHOUSE_PROGRAM_ID = new PublicKey14(
5234
5767
  "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95"
5235
5768
  );
5236
5769
  var LIGHTHOUSE_PROGRAM_ID_STR = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
@@ -5492,7 +6025,7 @@ function computeWarmupMaxPositionSize(initialMarginBps, totalCapital, currentSlo
5492
6025
  }
5493
6026
 
5494
6027
  // src/validation.ts
5495
- import { PublicKey as PublicKey14 } from "@solana/web3.js";
6028
+ import { PublicKey as PublicKey15 } from "@solana/web3.js";
5496
6029
  var U16_MAX2 = 65535;
5497
6030
  var U64_MAX = BigInt("18446744073709551615");
5498
6031
  var I64_MIN = BigInt("-9223372036854775808");
@@ -5522,7 +6055,7 @@ var ValidationError = class extends Error {
5522
6055
  };
5523
6056
  function validatePublicKey(value, field) {
5524
6057
  try {
5525
- return new PublicKey14(value);
6058
+ return new PublicKey15(value);
5526
6059
  } catch {
5527
6060
  throw new ValidationError(
5528
6061
  field,
@@ -5901,6 +6434,9 @@ export {
5901
6434
  ACCOUNTS_LIQUIDATE_AT_ORACLE,
5902
6435
  ACCOUNTS_LP_VAULT_WITHDRAW,
5903
6436
  ACCOUNTS_MINT_POSITION_NFT,
6437
+ ACCOUNTS_NFT_BURN,
6438
+ ACCOUNTS_NFT_EMERGENCY_BURN,
6439
+ ACCOUNTS_NFT_MINT,
5904
6440
  ACCOUNTS_PAUSE_MARKET,
5905
6441
  ACCOUNTS_PUSH_ORACLE_PRICE,
5906
6442
  ACCOUNTS_QUEUE_WITHDRAWAL,
@@ -5940,11 +6476,14 @@ export {
5940
6476
  LIGHTHOUSE_PROGRAM_ID,
5941
6477
  LIGHTHOUSE_PROGRAM_ID_STR,
5942
6478
  LIGHTHOUSE_USER_MESSAGE,
6479
+ LiquidationPolicyTag,
5943
6480
  MARK_PRICE_EMA_ALPHA_E6,
5944
6481
  MARK_PRICE_EMA_WINDOW_SLOTS,
5945
6482
  MAX_DECIMALS,
5946
6483
  MAX_ORACLE_PRICE,
5947
6484
  METEORA_DLMM_PROGRAM_ID,
6485
+ NFT_IX_TAG,
6486
+ NFT_PROGRAM_ID,
5948
6487
  ORACLE_PHASE_GROWING,
5949
6488
  ORACLE_PHASE_MATURE,
5950
6489
  ORACLE_PHASE_NASCENT,
@@ -5953,6 +6492,7 @@ export {
5953
6492
  PHASE1_VOLUME_MIN_SLOTS,
5954
6493
  PHASE2_MATURITY_SLOTS,
5955
6494
  PHASE2_VOLUME_THRESHOLD,
6495
+ POSITION_NFT_STATE_LEN,
5956
6496
  PROGRAM_IDS,
5957
6497
  PUMPSWAP_PROGRAM_ID,
5958
6498
  PYTH_PUSH_ORACLE_PROGRAM_ID,
@@ -5962,11 +6502,13 @@ export {
5962
6502
  RAYDIUM_CLMM_PROGRAM_ID,
5963
6503
  RENOUNCE_ADMIN_CONFIRMATION,
5964
6504
  RpcPool,
6505
+ SLAB_MAGIC,
5965
6506
  SLAB_TIERS,
5966
6507
  SLAB_TIERS_V0,
5967
6508
  SLAB_TIERS_V1,
5968
6509
  SLAB_TIERS_V12_1,
5969
6510
  SLAB_TIERS_V12_15,
6511
+ SLAB_TIERS_V12_17,
5970
6512
  SLAB_TIERS_V1D,
5971
6513
  SLAB_TIERS_V1D_LEGACY,
5972
6514
  SLAB_TIERS_V1M,
@@ -5975,6 +6517,7 @@ export {
5975
6517
  SLAB_TIERS_V_ADL,
5976
6518
  SLAB_TIERS_V_ADL_DISCOVERY,
5977
6519
  SLAB_TIERS_V_SETDEXPOOL,
6520
+ STAKE_DEPOSIT_SIZE,
5978
6521
  STAKE_IX,
5979
6522
  STAKE_POOL_SIZE,
5980
6523
  STAKE_PROGRAM_ID,
@@ -6014,6 +6557,7 @@ export {
6014
6557
  computeWarmupUnlockedCapital,
6015
6558
  concatBytes,
6016
6559
  countLighthouseInstructions,
6560
+ decodeDepositPda,
6017
6561
  decodeError,
6018
6562
  decodeStakePool,
6019
6563
  depositAccounts,
@@ -6021,6 +6565,9 @@ export {
6021
6565
  deriveDepositPda,
6022
6566
  deriveInsuranceLpMint,
6023
6567
  deriveLpPda,
6568
+ deriveMintAuthority,
6569
+ deriveNftMint,
6570
+ deriveNftPda,
6024
6571
  derivePythPriceUpdateAccount,
6025
6572
  derivePythPushOraclePDA,
6026
6573
  deriveStakePool,
@@ -6077,6 +6624,10 @@ export {
6077
6624
  encodeLpVaultDeposit,
6078
6625
  encodeLpVaultWithdraw,
6079
6626
  encodeMintPositionNft,
6627
+ encodeNftBurn,
6628
+ encodeNftEmergencyBurn,
6629
+ encodeNftMint,
6630
+ encodeNftSettleFunding,
6080
6631
  encodePauseMarket,
6081
6632
  encodePushOraclePrice,
6082
6633
  encodeQueueWithdrawal,
@@ -6088,10 +6639,14 @@ export {
6088
6639
  encodeResolveMarket,
6089
6640
  encodeResolvePermissionless,
6090
6641
  encodeSetDexPool,
6642
+ encodeSetDisputeParams,
6091
6643
  encodeSetInsuranceIsolation,
6092
6644
  encodeSetInsuranceWithdrawPolicy,
6645
+ encodeSetLpCollateralParams,
6093
6646
  encodeSetMaintenanceFee,
6647
+ encodeSetMaxPnlCap,
6094
6648
  encodeSetOffsetPair,
6649
+ encodeSetOiCapMultiplier,
6095
6650
  encodeSetOiImbalanceHardBlock,
6096
6651
  encodeSetOracleAuthority,
6097
6652
  encodeSetOraclePriceCap,
@@ -6124,6 +6679,7 @@ export {
6124
6679
  encodeTransferOwnershipCpi,
6125
6680
  encodeTransferPositionOwnership,
6126
6681
  encodeUnpauseMarket,
6682
+ encodeUnresolveMarket,
6127
6683
  encodeUpdateAdmin,
6128
6684
  encodeUpdateConfig,
6129
6685
  encodeUpdateHyperpMark,
@@ -6147,6 +6703,7 @@ export {
6147
6703
  getErrorName,
6148
6704
  getMarketsByAddress,
6149
6705
  getMatcherProgramId,
6706
+ getNftProgramId,
6150
6707
  getProgramId,
6151
6708
  getStakeProgramId,
6152
6709
  getStaticMarkets,
@@ -6160,6 +6717,7 @@ export {
6160
6717
  isToken2022,
6161
6718
  isValidChainlinkOracle,
6162
6719
  maxAccountIndex,
6720
+ packOiCap,
6163
6721
  parseAccount,
6164
6722
  parseAdlEvent,
6165
6723
  parseAllAccounts,
@@ -6170,6 +6728,7 @@ export {
6170
6728
  parseErrorFromLogs,
6171
6729
  parseHeader,
6172
6730
  parseParams,
6731
+ parsePositionNftAccount,
6173
6732
  parseUsedIndices,
6174
6733
  rankAdlPositions,
6175
6734
  readLastThrUpdateSlot,