@percolatorct/sdk 1.0.0-beta.2 → 1.0.0-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,13 +1,16 @@
1
1
  // src/abi/encode.ts
2
2
  import { PublicKey } from "@solana/web3.js";
3
+ var U8_MAX = 255;
4
+ var U16_MAX = 65535;
5
+ var U32_MAX = 4294967295;
3
6
  function encU8(val) {
4
- if (!Number.isInteger(val) || val < 0 || val > 255) {
7
+ if (!Number.isInteger(val) || val < 0 || val > U8_MAX) {
5
8
  throw new Error(`encU8: value out of range (0..255), got ${val}`);
6
9
  }
7
10
  return new Uint8Array([val]);
8
11
  }
9
12
  function encU16(val) {
10
- if (!Number.isInteger(val) || val < 0 || val > 65535) {
13
+ if (!Number.isInteger(val) || val < 0 || val > U16_MAX) {
11
14
  throw new Error(`encU16: value out of range (0..65535), got ${val}`);
12
15
  }
13
16
  const buf = new Uint8Array(2);
@@ -15,7 +18,7 @@ function encU16(val) {
15
18
  return buf;
16
19
  }
17
20
  function encU32(val) {
18
- if (!Number.isInteger(val) || val < 0 || val > 4294967295) {
21
+ if (!Number.isInteger(val) || val < 0 || val > U32_MAX) {
19
22
  throw new Error(`encU32: value out of range (0..4294967295), got ${val}`);
20
23
  }
21
24
  const buf = new Uint8Array(4);
@@ -117,16 +120,28 @@ var IX_TAG = {
117
120
  ResolveMarket: 19,
118
121
  WithdrawInsurance: 20,
119
122
  AdminForceClose: 21,
123
+ // Tags 22-23: on-chain these are SetInsuranceWithdrawPolicy / WithdrawInsuranceLimited.
124
+ // Legacy aliases (UpdateRiskParams/RenounceAdmin) kept for backward compat.
125
+ SetInsuranceWithdrawPolicy: 22,
126
+ /** @deprecated Use SetInsuranceWithdrawPolicy */
120
127
  UpdateRiskParams: 22,
128
+ WithdrawInsuranceLimited: 23,
129
+ /** @deprecated Use WithdrawInsuranceLimited */
121
130
  RenounceAdmin: 23,
122
- CreateInsuranceMint: 24,
123
- DepositInsuranceLP: 25,
124
- WithdrawInsuranceLP: 26,
125
- PauseMarket: 27,
126
- UnpauseMarket: 28,
131
+ // Tags 24–26: on-chain = QueryLpFees/ReclaimEmptyAccount/SettleAccount.
132
+ // Old insurance LP tags removed — those moved to percolator-stake.
133
+ QueryLpFees: 24,
134
+ ReclaimEmptyAccount: 25,
135
+ SettleAccount: 26,
136
+ // Tags 27-28: on-chain = DepositFeeCredits/ConvertReleasedPnl.
137
+ DepositFeeCredits: 27,
138
+ ConvertReleasedPnl: 28,
139
+ // Tags 29-30: on-chain = ResolvePermissionless/ForceCloseResolved.
140
+ ResolvePermissionless: 29,
141
+ /** @deprecated Use ResolvePermissionless */
127
142
  AcceptAdmin: 29,
128
- SetInsuranceWithdrawPolicy: 30,
129
- WithdrawInsuranceLimited: 31,
143
+ ForceCloseResolved: 30,
144
+ // Tag 31: gap (no decode arm on-chain)
130
145
  SetPythOracle: 32,
131
146
  UpdateMarkPrice: 33,
132
147
  UpdateHyperpMark: 34,
@@ -171,8 +186,7 @@ var IX_TAG = {
171
186
  AttestCrossMargin: 55,
172
187
  /** PERC-622: Advance oracle phase (permissionless crank) */
173
188
  AdvanceOraclePhase: 56,
174
- /** PERC-623: Top up a market's keeper fund (permissionless) */
175
- TopUpKeeperFund: 57,
189
+ // 57: removed (keeper fund)
176
190
  /** PERC-629: Slash a market creator's deposit (permissionless) */
177
191
  SlashCreationDeposit: 58,
178
192
  /** PERC-628: Initialize the global shared vault (admin) */
@@ -208,7 +222,12 @@ var IX_TAG = {
208
222
  /** PERC-SetDexPool: Pin admin-approved DEX pool address for a HYPERP market (admin). */
209
223
  SetDexPool: 74,
210
224
  /** CPI to the matcher program to initialize a matcher context account for an LP slot. Admin-only. */
211
- InitMatcherCtx: 75
225
+ InitMatcherCtx: 75,
226
+ /** PauseMarket (tag 76): admin emergency pause. Blocks Trade/Deposit/Withdraw/InitUser. */
227
+ PauseMarket: 76,
228
+ /** UnpauseMarket (tag 77): admin unpause. Re-enables all operations. */
229
+ UnpauseMarket: 77
230
+ // 78: removed (keeper fund)
212
231
  };
213
232
  Object.freeze(IX_TAG);
214
233
  var HEX_RE = /^[0-9a-fA-F]{64}$/;
@@ -231,8 +250,10 @@ function encodeFeedId(feedId) {
231
250
  }
232
251
  return bytes;
233
252
  }
234
- var INIT_MARKET_DATA_LEN = 264;
253
+ var INIT_MARKET_DATA_LEN = 352;
235
254
  function encodeInitMarket(args) {
255
+ const hMin = args.hMin ?? args.warmupPeriodSlots ?? 0n;
256
+ const hMax = args.hMax ?? args.warmupPeriodSlots ?? 0n;
236
257
  const data = concatBytes(
237
258
  encU8(IX_TAG.InitMarket),
238
259
  encPubkey(args.admin),
@@ -243,19 +264,34 @@ function encodeInitMarket(args) {
243
264
  encU8(args.invert),
244
265
  encU32(args.unitScale),
245
266
  encU64(args.initialMarkPriceE6),
246
- encU64(args.warmupPeriodSlots),
267
+ // 3 fields between header and RiskParams (immutable after init)
268
+ encU128(args.maxMaintenanceFeePerSlot ?? 0n),
269
+ encU128(args.maxInsuranceFloor ?? 0n),
270
+ encU64(args.minOraclePriceCap ?? 0n),
271
+ // RiskParams wire format — must match read_risk_params() in percolator.rs
272
+ // In v12.15: warmup_period_slots replaced by hMin/hMax. hMin is written first (same slot),
273
+ // hMax appended at end. liquidationBufferBps is read but discarded (kept for wire compat).
274
+ encU64(hMin),
247
275
  encU64(args.maintenanceMarginBps),
248
276
  encU64(args.initialMarginBps),
249
277
  encU64(args.tradingFeeBps),
250
278
  encU64(args.maxAccounts),
251
279
  encU128(args.newAccountFee),
252
- encU128(args.riskReductionThreshold),
253
- encU128(args.maintenanceFeePerSlot),
280
+ encU128(args.insuranceFloor ?? 0n),
281
+ // wire slot: old riskReductionThreshold → now insurance_floor
282
+ 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
254
286
  encU64(args.maxCrankStalenessSlots),
255
287
  encU64(args.liquidationFeeBps),
256
288
  encU128(args.liquidationFeeCap),
257
- encU64(args.liquidationBufferBps),
258
- encU128(args.minLiquidationAbs)
289
+ encU64(args.liquidationBufferBps ?? 0n),
290
+ // wire slot: read as resolve_price_deviation_bps by program
291
+ encU128(args.minLiquidationAbs),
292
+ encU128(args.minInitialDeposit),
293
+ encU128(args.minNonzeroMmReq),
294
+ encU128(args.minNonzeroImReq)
259
295
  );
260
296
  if (data.length !== INIT_MARKET_DATA_LEN) {
261
297
  throw new Error(
@@ -428,15 +464,6 @@ function encodeRenounceAdmin() {
428
464
  encU64(RENOUNCE_ADMIN_CONFIRMATION)
429
465
  );
430
466
  }
431
- function encodeCreateInsuranceMint() {
432
- return encU8(IX_TAG.CreateInsuranceMint);
433
- }
434
- function encodeDepositInsuranceLP(args) {
435
- return concatBytes(encU8(IX_TAG.DepositInsuranceLP), encU64(args.amount));
436
- }
437
- function encodeWithdrawInsuranceLP(args) {
438
- return concatBytes(encU8(IX_TAG.WithdrawInsuranceLP), encU64(args.lpAmount));
439
- }
440
467
  function encodeLpVaultWithdraw(args) {
441
468
  return concatBytes(encU8(IX_TAG.LpVaultWithdraw), encU64(args.lpAmount));
442
469
  }
@@ -580,9 +607,6 @@ function checkPhaseTransition(currentSlot, marketCreatedSlot, oraclePhase, cumul
580
607
  return [ORACLE_PHASE_MATURE, false];
581
608
  }
582
609
  }
583
- function encodeTopUpKeeperFund(args) {
584
- return concatBytes(encU8(IX_TAG.TopUpKeeperFund), encU64(args.amount));
585
- }
586
610
  function encodeSlashCreationDeposit() {
587
611
  return encU8(IX_TAG.SlashCreationDeposit);
588
612
  }
@@ -652,6 +676,67 @@ function encodeInitMatcherCtx(args) {
652
676
  encU16(args.skewSpreadMultBps)
653
677
  );
654
678
  }
679
+ function encodeSetInsuranceWithdrawPolicy(args) {
680
+ return concatBytes(encU8(IX_TAG.SetInsuranceWithdrawPolicy), encPubkey(args.authority), encU64(args.minWithdrawBase), encU16(args.maxWithdrawBps), encU64(args.cooldownSlots));
681
+ }
682
+ function encodeWithdrawInsuranceLimited(args) {
683
+ return concatBytes(encU8(IX_TAG.WithdrawInsuranceLimited), encU64(args.amount));
684
+ }
685
+ function encodeResolvePermissionless() {
686
+ return concatBytes(encU8(IX_TAG.ResolvePermissionless));
687
+ }
688
+ function encodeForceCloseResolved(args) {
689
+ return concatBytes(encU8(IX_TAG.ForceCloseResolved), encU16(args.userIdx));
690
+ }
691
+ function encodeCreateLpVault(args) {
692
+ const parts = [encU8(IX_TAG.CreateLpVault), encU64(args.feeShareBps)];
693
+ if (args.utilCurveEnabled !== void 0) {
694
+ parts.push(encU8(args.utilCurveEnabled ? 1 : 0));
695
+ }
696
+ return concatBytes(...parts);
697
+ }
698
+ function encodeLpVaultDeposit(args) {
699
+ return concatBytes(encU8(IX_TAG.LpVaultDeposit), encU64(args.amount));
700
+ }
701
+ function encodeLpVaultCrankFees() {
702
+ return concatBytes(encU8(IX_TAG.LpVaultCrankFees));
703
+ }
704
+ function encodeChallengeSettlement(args) {
705
+ return concatBytes(encU8(IX_TAG.ChallengeSettlement), encU64(args.proposedPriceE6));
706
+ }
707
+ function encodeResolveDispute(args) {
708
+ return concatBytes(encU8(IX_TAG.ResolveDispute), encU8(args.accept));
709
+ }
710
+ function encodeDepositLpCollateral(args) {
711
+ return concatBytes(encU8(IX_TAG.DepositLpCollateral), encU16(args.userIdx), encU64(args.lpAmount));
712
+ }
713
+ function encodeWithdrawLpCollateral(args) {
714
+ return concatBytes(encU8(IX_TAG.WithdrawLpCollateral), encU16(args.userIdx), encU64(args.lpAmount));
715
+ }
716
+ function encodeSetOffsetPair(args) {
717
+ return concatBytes(encU8(IX_TAG.SetOffsetPair), encU16(args.offsetBps));
718
+ }
719
+ function encodeAttestCrossMargin(args) {
720
+ return concatBytes(encU8(IX_TAG.AttestCrossMargin), encU16(args.userIdxA), encU16(args.userIdxB));
721
+ }
722
+ function encodeRescueOrphanVault() {
723
+ return concatBytes(encU8(IX_TAG.RescueOrphanVault));
724
+ }
725
+ function encodeCloseOrphanSlab() {
726
+ return concatBytes(encU8(IX_TAG.CloseOrphanSlab));
727
+ }
728
+ function encodeSetDexPool(args) {
729
+ return concatBytes(encU8(IX_TAG.SetDexPool), encPubkey(args.pool));
730
+ }
731
+ function encodeCreateInsuranceMint() {
732
+ return encodeCreateLpVault({ feeShareBps: 0n });
733
+ }
734
+ function encodeDepositInsuranceLP(args) {
735
+ return encodeLpVaultDeposit({ amount: args.amount });
736
+ }
737
+ function encodeWithdrawInsuranceLP(args) {
738
+ return encodeLpVaultWithdraw({ lpAmount: args.lpAmount });
739
+ }
655
740
 
656
741
  // src/abi/accounts.ts
657
742
  import {
@@ -676,7 +761,8 @@ var ACCOUNTS_INIT_USER = [
676
761
  { name: "slab", signer: false, writable: true },
677
762
  { name: "userAta", signer: false, writable: true },
678
763
  { name: "vault", signer: false, writable: true },
679
- { name: "tokenProgram", signer: false, writable: false }
764
+ { name: "tokenProgram", signer: false, writable: false },
765
+ { name: "clock", signer: false, writable: false }
680
766
  ];
681
767
  var ACCOUNTS_INIT_LP = [
682
768
  { name: "user", signer: true, writable: true },
@@ -743,6 +829,7 @@ var ACCOUNTS_TRADE_CPI = [
743
829
  { name: "lpOwner", signer: false, writable: false },
744
830
  // LP delegated to matcher - no signature needed
745
831
  { name: "slab", signer: false, writable: true },
832
+ { name: "clock", signer: false, writable: false },
746
833
  { name: "oracle", signer: false, writable: false },
747
834
  { name: "matcherProg", signer: false, writable: false },
748
835
  { name: "matcherCtx", signer: false, writable: true },
@@ -924,11 +1011,6 @@ var ACCOUNTS_AUDIT_CRANK = [
924
1011
  var ACCOUNTS_ADVANCE_ORACLE_PHASE = [
925
1012
  { name: "slab", signer: false, writable: true }
926
1013
  ];
927
- var ACCOUNTS_TOPUP_KEEPER_FUND = [
928
- { name: "funder", signer: true, writable: true },
929
- { name: "slab", signer: false, writable: true },
930
- { name: "keeperFund", signer: false, writable: true }
931
- ];
932
1014
  var ACCOUNTS_SET_OI_IMBALANCE_HARD_BLOCK = [
933
1015
  { name: "admin", signer: true, writable: false },
934
1016
  { name: "slab", signer: false, writable: true }
@@ -978,6 +1060,11 @@ var ACCOUNTS_SET_WALLET_CAP = [
978
1060
  { name: "admin", signer: true, writable: false },
979
1061
  { name: "slab", signer: false, writable: true }
980
1062
  ];
1063
+ var ACCOUNTS_SET_DEX_POOL = [
1064
+ { name: "admin", signer: true, writable: false },
1065
+ { name: "slab", signer: false, writable: true },
1066
+ { name: "poolAccount", signer: false, writable: false }
1067
+ ];
981
1068
  var ACCOUNTS_INIT_MATCHER_CTX = [
982
1069
  { name: "admin", signer: true, writable: false },
983
1070
  { name: "slab", signer: false, writable: false },
@@ -1269,24 +1356,11 @@ function getErrorName(code) {
1269
1356
  function getErrorHint(code) {
1270
1357
  return PERCOLATOR_ERRORS[code]?.hint;
1271
1358
  }
1272
- var LIGHTHOUSE_PROGRAM_ID_STR = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
1273
- var ANCHOR_ERROR_RANGE_START = 6e3;
1274
- var ANCHOR_ERROR_RANGE_END = 8191;
1275
- var ANCHOR_ERROR_NAMES = {
1276
- 6032: "ConstraintMut",
1277
- 6036: "ConstraintOwner",
1278
- 6038: "ConstraintSeeds",
1279
- 6400: "ConstraintAddress"
1280
- };
1281
- function isAnchorErrorCode(code) {
1282
- return code >= ANCHOR_ERROR_RANGE_START && code <= ANCHOR_ERROR_RANGE_END;
1283
- }
1284
1359
  var CUSTOM_ERROR_HEX_MAX_LEN = 8;
1285
1360
  function parseErrorFromLogs(logs) {
1286
1361
  if (!Array.isArray(logs)) {
1287
1362
  return null;
1288
1363
  }
1289
- let insideLighthouse = false;
1290
1364
  const re = new RegExp(
1291
1365
  `custom program error: 0x([0-9a-fA-F]{1,${CUSTOM_ERROR_HEX_MAX_LEN}})(?![0-9a-fA-F])`,
1292
1366
  "i"
@@ -1295,32 +1369,17 @@ function parseErrorFromLogs(logs) {
1295
1369
  if (typeof log !== "string") {
1296
1370
  continue;
1297
1371
  }
1298
- if (log.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {
1299
- insideLighthouse = true;
1300
- } else if (log.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {
1301
- insideLighthouse = false;
1302
- }
1303
1372
  const match = log.match(re);
1304
1373
  if (match) {
1305
1374
  const code = parseInt(match[1], 16);
1306
1375
  if (!Number.isFinite(code) || code < 0 || code > 4294967295) {
1307
1376
  continue;
1308
1377
  }
1309
- if (isAnchorErrorCode(code) || insideLighthouse) {
1310
- const anchorName = ANCHOR_ERROR_NAMES[code] ?? `AnchorError(0x${code.toString(16)})`;
1311
- return {
1312
- code,
1313
- name: `Lighthouse:${anchorName}`,
1314
- 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).",
1315
- source: "lighthouse"
1316
- };
1317
- }
1318
1378
  const info = decodeError(code);
1319
1379
  return {
1320
1380
  code,
1321
1381
  name: info?.name ?? `Unknown(${code})`,
1322
- hint: info?.hint,
1323
- source: info ? "percolator" : "unknown"
1382
+ hint: info?.hint
1324
1383
  };
1325
1384
  }
1326
1385
  }
@@ -1532,9 +1591,29 @@ var V_ADL_ACCT_FEE_CREDITS_OFF = 224;
1532
1591
  var V_ADL_ACCT_LAST_FEE_SLOT_OFF = 240;
1533
1592
  var V12_1_ENGINE_OFF = 648;
1534
1593
  var V12_1_ACCOUNT_SIZE = 320;
1594
+ var V12_1_ACCOUNT_SIZE_SBF = 280;
1535
1595
  var V12_1_ENGINE_BITMAP_OFF = 1016;
1536
- var V12_1_ENGINE_PARAMS_OFF = 96;
1596
+ var V12_1_ENGINE_PARAMS_OFF_SBF = 32;
1597
+ var V12_1_ENGINE_PARAMS_OFF_HOST = 96;
1598
+ var V12_1_PARAMS_SIZE_SBF = 184;
1537
1599
  var V12_1_PARAMS_SIZE = 352;
1600
+ var V12_1_SBF_OFF_CURRENT_SLOT = 216;
1601
+ var V12_1_SBF_OFF_FUNDING_RATE = 224;
1602
+ var V12_1_SBF_OFF_LAST_CRANK_SLOT = 232;
1603
+ var V12_1_SBF_OFF_MAX_CRANK_STALENESS = 240;
1604
+ var V12_1_SBF_OFF_C_TOT = 248;
1605
+ var V12_1_SBF_OFF_PNL_POS_TOT = 264;
1606
+ var V12_1_SBF_OFF_LIQ_CURSOR = 296;
1607
+ var V12_1_SBF_OFF_GC_CURSOR = 298;
1608
+ var V12_1_SBF_OFF_LAST_SWEEP_START = 304;
1609
+ var V12_1_SBF_OFF_LAST_SWEEP_COMPLETE = 312;
1610
+ var V12_1_SBF_OFF_CRANK_CURSOR = 320;
1611
+ var V12_1_SBF_OFF_SWEEP_START_IDX = 322;
1612
+ var V12_1_SBF_OFF_LIFETIME_LIQUIDATIONS = 328;
1613
+ var V12_1_SBF_OFF_TOTAL_OI = 448;
1614
+ var V12_1_SBF_OFF_LONG_OI = 464;
1615
+ var V12_1_SBF_OFF_SHORT_OI = 480;
1616
+ var V12_1_SBF_OFF_MARK_PRICE_E6 = 560;
1538
1617
  var V12_1_ENGINE_CURRENT_SLOT_OFF = 448;
1539
1618
  var V12_1_ENGINE_FUNDING_RATE_BPS_OFF = 456;
1540
1619
  var V12_1_ENGINE_LAST_CRANK_SLOT_OFF = 464;
@@ -1567,9 +1646,51 @@ var V12_1_ACCT_MATCHER_CONTEXT_OFF = 176;
1567
1646
  var V12_1_ACCT_OWNER_OFF = 208;
1568
1647
  var V12_1_ACCT_FEE_CREDITS_OFF = 240;
1569
1648
  var V12_1_ACCT_LAST_FEE_SLOT_OFF = 256;
1570
- var V12_1_ACCT_POSITION_SIZE_OFF = 296;
1571
- var V12_1_ACCT_ENTRY_PRICE_OFF = 280;
1572
- var V12_1_ACCT_FUNDING_INDEX_OFF = 288;
1649
+ var V12_1_ACCT_POSITION_SIZE_OFF = 88;
1650
+ var V12_1_ACCT_ENTRY_PRICE_OFF = -1;
1651
+ var V12_1_EP_SBF_ACCOUNT_SIZE = 288;
1652
+ var V12_1_EP_ACCT_ENTRY_PRICE_OFF = 144;
1653
+ var V12_1_EP_ACCT_MATCHER_PROGRAM_OFF = 152;
1654
+ var V12_1_EP_ACCT_MATCHER_CONTEXT_OFF = 184;
1655
+ var V12_1_EP_ACCT_OWNER_OFF = 216;
1656
+ var V12_1_EP_ACCT_FEE_CREDITS_OFF = 248;
1657
+ var V12_1_EP_ACCT_LAST_FEE_SLOT_OFF = 264;
1658
+ var V12_15_ENGINE_OFF = 624;
1659
+ var V12_15_ENGINE_OFF_SBF = 616;
1660
+ var V12_15_ACCOUNT_SIZE = 4400;
1661
+ var V12_15_ACCOUNT_SIZE_SMALL = 920;
1662
+ var V12_15_ACCT_ACCOUNT_ID_OFF = 0;
1663
+ var V12_15_ACCT_CAPITAL_OFF = 8;
1664
+ var V12_15_ACCT_KIND_OFF = 24;
1665
+ var V12_15_ACCT_PNL_OFF = 32;
1666
+ var V12_15_ACCT_RESERVED_PNL_OFF = 48;
1667
+ var V12_15_ACCT_POSITION_BASIS_Q_OFF = 64;
1668
+ var V12_15_ACCT_ENTRY_PRICE_OFF = 120;
1669
+ var V12_15_ACCT_MATCHER_PROGRAM_OFF = 128;
1670
+ var V12_15_ACCT_MATCHER_CONTEXT_OFF = 160;
1671
+ var V12_15_ACCT_OWNER_OFF = 192;
1672
+ var V12_15_ACCT_FEE_CREDITS_OFF = 224;
1673
+ var V12_15_ACCT_FEES_EARNED_TOTAL_OFF = 240;
1674
+ var V12_15_ACCT_EXACT_RESERVE_COHORTS_OFF = 256;
1675
+ var V12_15_ACCT_EXACT_COHORT_COUNT_OFF = 4224;
1676
+ var V12_15_ACCT_OVERFLOW_OLDER_OFF = 4240;
1677
+ var V12_15_ACCT_OVERFLOW_OLDER_PRESENT_OFF = 4304;
1678
+ var V12_15_ACCT_OVERFLOW_NEWEST_OFF = 4320;
1679
+ var V12_15_ACCT_OVERFLOW_NEWEST_PRESENT_OFF = 4384;
1680
+ var V12_15_PARAMS_SIZE = 192;
1681
+ var V12_15_PARAMS_MAX_ACCOUNTS_OFF = 24;
1682
+ var V12_15_PARAMS_INSURANCE_FLOOR_OFF = 144;
1683
+ var V12_15_PARAMS_H_MIN_OFF = 160;
1684
+ var V12_15_PARAMS_H_MAX_OFF = 168;
1685
+ var V12_15_ENGINE_PARAMS_OFF = 32;
1686
+ var V12_15_ENGINE_CURRENT_SLOT_OFF = 224;
1687
+ var V12_15_ENGINE_FUNDING_RATE_E9_OFF = 240;
1688
+ var V12_15_ENGINE_MARKET_MODE_OFF = 256;
1689
+ var V12_15_ENGINE_C_TOT_OFF = 344;
1690
+ var V12_15_ENGINE_PNL_POS_TOT_OFF = 368;
1691
+ var V12_15_ENGINE_PNL_MATURED_POS_TOT_OFF = 384;
1692
+ var V12_15_ENGINE_BITMAP_OFF = 862;
1693
+ var V12_15_SIZES = /* @__PURE__ */ new Map();
1573
1694
  var V1M_ENGINE_OFF = 640;
1574
1695
  var V1M_CONFIG_LEN = 536;
1575
1696
  var V1M_ACCOUNT_SIZE = 248;
@@ -1642,6 +1763,27 @@ for (const n of TIERS) {
1642
1763
  V1M2_SIZES.set(computeSlabSize(V1M2_ENGINE_OFF, V1M2_ENGINE_BITMAP_OFF, V1M2_ACCOUNT_SIZE, n, 18), n);
1643
1764
  V_SETDEXPOOL_SIZES.set(computeSlabSize(V_SETDEXPOOL_ENGINE_OFF, V_ADL_ENGINE_BITMAP_OFF, V_ADL_ACCOUNT_SIZE, n, 18), n);
1644
1765
  V12_1_SIZES.set(computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, n, 18), n);
1766
+ V12_15_SIZES.set(computeSlabSize(V12_15_ENGINE_OFF, V12_15_ENGINE_BITMAP_OFF, V12_15_ACCOUNT_SIZE, n, 18), n);
1767
+ }
1768
+ V12_15_SIZES.set(computeSlabSize(V12_15_ENGINE_OFF, V12_15_ENGINE_BITMAP_OFF, V12_15_ACCOUNT_SIZE, 2048, 18), 2048);
1769
+ V12_15_SIZES.set(237512, 256);
1770
+ var V12_1_SBF_ACCOUNT_SIZE = 280;
1771
+ var V12_1_SBF_ENGINE_OFF = 616;
1772
+ var V12_1_SBF_BITMAP_OFF = 584;
1773
+ for (const [, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Large", 4096]]) {
1774
+ const bitmapBytes = Math.ceil(n / 64) * 8;
1775
+ const preAccLen = V12_1_SBF_BITMAP_OFF + bitmapBytes + 18 + n * 2;
1776
+ const accountsOff = Math.ceil(preAccLen / 8) * 8;
1777
+ const total = V12_1_SBF_ENGINE_OFF + accountsOff + n * V12_1_SBF_ACCOUNT_SIZE;
1778
+ V12_1_SIZES.set(total, n);
1779
+ }
1780
+ var V12_1_EP_SIZES = /* @__PURE__ */ new Map();
1781
+ for (const [, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Large", 4096]]) {
1782
+ const bitmapBytes = Math.ceil(n / 64) * 8;
1783
+ const preAccLen = V12_1_SBF_BITMAP_OFF + bitmapBytes + 18 + n * 2;
1784
+ const accountsOff = Math.ceil(preAccLen / 8) * 8;
1785
+ const total = V12_1_SBF_ENGINE_OFF + accountsOff + n * V12_1_EP_SBF_ACCOUNT_SIZE;
1786
+ V12_1_EP_SIZES.set(total, n);
1645
1787
  }
1646
1788
  var SLAB_TIERS_V2 = {
1647
1789
  small: { maxAccounts: 256, dataSize: 65088, label: "Small", description: "256 slots (V2 BPF intermediate)" },
@@ -2107,6 +2249,11 @@ for (const [label, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Lar
2107
2249
  const size = computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, n, 18);
2108
2250
  SLAB_TIERS_V12_1[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (v12.1)` };
2109
2251
  }
2252
+ var SLAB_TIERS_V12_15 = {};
2253
+ for (const [label, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Medium2048", 2048], ["Large", 4096]]) {
2254
+ const size = computeSlabSize(V12_15_ENGINE_OFF, V12_15_ENGINE_BITMAP_OFF, V12_15_ACCOUNT_SIZE, n, 18);
2255
+ SLAB_TIERS_V12_15[label.toLowerCase()] = { maxAccounts: n, dataSize: size, label, description: `${n} slots (v12.15)` };
2256
+ }
2110
2257
  function buildLayoutVSetDexPool(maxAccounts) {
2111
2258
  const engineOff = V_SETDEXPOOL_ENGINE_OFF;
2112
2259
  const bitmapOff = V_ADL_ENGINE_BITMAP_OFF;
@@ -2167,10 +2314,12 @@ function buildLayoutVSetDexPool(maxAccounts) {
2167
2314
  engineInsuranceIsolationBpsOff: 64
2168
2315
  };
2169
2316
  }
2170
- function buildLayoutV12_1(maxAccounts) {
2171
- const engineOff = V12_1_ENGINE_OFF;
2172
- const bitmapOff = V12_1_ENGINE_BITMAP_OFF;
2173
- const accountSize = V12_1_ACCOUNT_SIZE;
2317
+ function buildLayoutV12_1(maxAccounts, dataLen) {
2318
+ const hostSize = computeSlabSize(V12_1_ENGINE_OFF, V12_1_ENGINE_BITMAP_OFF, V12_1_ACCOUNT_SIZE, maxAccounts, 18);
2319
+ const isSbf = dataLen !== void 0 && dataLen !== hostSize;
2320
+ const engineOff = isSbf ? V12_1_SBF_ENGINE_OFF : V12_1_ENGINE_OFF;
2321
+ const bitmapOff = isSbf ? V12_1_SBF_BITMAP_OFF : V12_1_ENGINE_BITMAP_OFF - V12_1_ENGINE_OFF;
2322
+ const accountSize = isSbf ? V12_1_ACCOUNT_SIZE_SBF : V12_1_ACCOUNT_SIZE;
2174
2323
  const bitmapWords = Math.ceil(maxAccounts / 64);
2175
2324
  const bitmapBytes = bitmapWords * 8;
2176
2325
  const postBitmap = 18;
@@ -2179,10 +2328,11 @@ function buildLayoutV12_1(maxAccounts) {
2179
2328
  const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;
2180
2329
  return {
2181
2330
  version: 1,
2182
- headerLen: V1_HEADER_LEN,
2183
- configOffset: V1_HEADER_LEN,
2184
- configLen: V_SETDEXPOOL_CONFIG_LEN,
2185
- // 544 (same as V_SETDEXPOOL)
2331
+ headerLen: V0_HEADER_LEN,
2332
+ // 72
2333
+ configOffset: V0_HEADER_LEN,
2334
+ // 72
2335
+ configLen: isSbf ? 544 : 576,
2186
2336
  reservedOff: V1_RESERVED_OFF,
2187
2337
  engineOff,
2188
2338
  accountSize,
@@ -2190,46 +2340,225 @@ function buildLayoutV12_1(maxAccounts) {
2190
2340
  bitmapWords,
2191
2341
  accountsOff: engineOff + accountsOffRel,
2192
2342
  engineInsuranceOff: 16,
2193
- engineParamsOff: V12_1_ENGINE_PARAMS_OFF,
2194
- paramsSize: V12_1_PARAMS_SIZE,
2195
- engineCurrentSlotOff: V12_1_ENGINE_CURRENT_SLOT_OFF,
2196
- engineFundingIndexOff: V12_1_ENGINE_FUNDING_INDEX_OFF,
2197
- engineLastFundingSlotOff: V12_1_ENGINE_LAST_FUNDING_SLOT_OFF,
2198
- engineFundingRateBpsOff: V12_1_ENGINE_FUNDING_RATE_BPS_OFF,
2199
- engineMarkPriceOff: V12_1_ENGINE_MARK_PRICE_OFF,
2200
- engineLastCrankSlotOff: V12_1_ENGINE_LAST_CRANK_SLOT_OFF,
2201
- engineMaxCrankStalenessOff: V12_1_ENGINE_MAX_CRANK_STALENESS_OFF,
2202
- engineTotalOiOff: V12_1_ENGINE_TOTAL_OI_OFF,
2203
- engineLongOiOff: V12_1_ENGINE_LONG_OI_OFF,
2204
- engineShortOiOff: V12_1_ENGINE_SHORT_OI_OFF,
2205
- engineCTotOff: V12_1_ENGINE_C_TOT_OFF,
2206
- enginePnlPosTotOff: V12_1_ENGINE_PNL_POS_TOT_OFF,
2207
- engineLiqCursorOff: V12_1_ENGINE_LIQ_CURSOR_OFF,
2208
- engineGcCursorOff: V12_1_ENGINE_GC_CURSOR_OFF,
2209
- engineLastSweepStartOff: V12_1_ENGINE_LAST_SWEEP_START_OFF,
2210
- engineLastSweepCompleteOff: V12_1_ENGINE_LAST_SWEEP_COMPLETE_OFF,
2211
- engineCrankCursorOff: V12_1_ENGINE_CRANK_CURSOR_OFF,
2212
- engineSweepStartIdxOff: V12_1_ENGINE_SWEEP_START_IDX_OFF,
2213
- engineLifetimeLiquidationsOff: V12_1_ENGINE_LIFETIME_LIQUIDATIONS_OFF,
2214
- engineLifetimeForceClosesOff: V12_1_ENGINE_LIFETIME_FORCE_CLOSES_OFF,
2215
- engineNetLpPosOff: V12_1_ENGINE_NET_LP_POS_OFF,
2216
- engineLpSumAbsOff: V12_1_ENGINE_LP_SUM_ABS_OFF,
2217
- engineLpMaxAbsOff: V12_1_ENGINE_LP_MAX_ABS_OFF,
2218
- engineLpMaxAbsSweepOff: V12_1_ENGINE_LP_MAX_ABS_SWEEP_OFF,
2219
- engineEmergencyOiModeOff: V12_1_ENGINE_EMERGENCY_OI_MODE_OFF,
2220
- engineEmergencyStartSlotOff: V12_1_ENGINE_EMERGENCY_START_SLOT_OFF,
2221
- engineLastBreakerSlotOff: V12_1_ENGINE_LAST_BREAKER_SLOT_OFF,
2222
- engineBitmapOff: V12_1_ENGINE_BITMAP_OFF,
2343
+ engineParamsOff: isSbf ? V12_1_ENGINE_PARAMS_OFF_SBF : V12_1_ENGINE_PARAMS_OFF_HOST,
2344
+ paramsSize: isSbf ? V12_1_PARAMS_SIZE_SBF : V12_1_PARAMS_SIZE,
2345
+ // SBF engine offsets — all verified by cargo build-sbf offset_of! assertions.
2346
+ // Fields that don't exist in the deployed program are set to -1 on SBF.
2347
+ engineCurrentSlotOff: isSbf ? V12_1_SBF_OFF_CURRENT_SLOT : V12_1_ENGINE_CURRENT_SLOT_OFF,
2348
+ engineFundingIndexOff: isSbf ? -1 : V12_1_ENGINE_FUNDING_INDEX_OFF,
2349
+ // not in deployed struct
2350
+ engineLastFundingSlotOff: isSbf ? -1 : V12_1_ENGINE_LAST_FUNDING_SLOT_OFF,
2351
+ // not in deployed struct
2352
+ engineFundingRateBpsOff: isSbf ? V12_1_SBF_OFF_FUNDING_RATE : V12_1_ENGINE_FUNDING_RATE_BPS_OFF,
2353
+ engineMarkPriceOff: isSbf ? V12_1_SBF_OFF_MARK_PRICE_E6 : V12_1_ENGINE_MARK_PRICE_OFF,
2354
+ engineLastCrankSlotOff: isSbf ? V12_1_SBF_OFF_LAST_CRANK_SLOT : V12_1_ENGINE_LAST_CRANK_SLOT_OFF,
2355
+ engineMaxCrankStalenessOff: isSbf ? V12_1_SBF_OFF_MAX_CRANK_STALENESS : V12_1_ENGINE_MAX_CRANK_STALENESS_OFF,
2356
+ engineTotalOiOff: isSbf ? V12_1_SBF_OFF_TOTAL_OI : V12_1_ENGINE_TOTAL_OI_OFF,
2357
+ engineLongOiOff: isSbf ? V12_1_SBF_OFF_LONG_OI : V12_1_ENGINE_LONG_OI_OFF,
2358
+ engineShortOiOff: isSbf ? V12_1_SBF_OFF_SHORT_OI : V12_1_ENGINE_SHORT_OI_OFF,
2359
+ engineCTotOff: isSbf ? V12_1_SBF_OFF_C_TOT : V12_1_ENGINE_C_TOT_OFF,
2360
+ enginePnlPosTotOff: isSbf ? V12_1_SBF_OFF_PNL_POS_TOT : V12_1_ENGINE_PNL_POS_TOT_OFF,
2361
+ engineLiqCursorOff: isSbf ? V12_1_SBF_OFF_LIQ_CURSOR : V12_1_ENGINE_LIQ_CURSOR_OFF,
2362
+ engineGcCursorOff: isSbf ? V12_1_SBF_OFF_GC_CURSOR : V12_1_ENGINE_GC_CURSOR_OFF,
2363
+ engineLastSweepStartOff: isSbf ? V12_1_SBF_OFF_LAST_SWEEP_START : V12_1_ENGINE_LAST_SWEEP_START_OFF,
2364
+ engineLastSweepCompleteOff: isSbf ? V12_1_SBF_OFF_LAST_SWEEP_COMPLETE : V12_1_ENGINE_LAST_SWEEP_COMPLETE_OFF,
2365
+ engineCrankCursorOff: isSbf ? V12_1_SBF_OFF_CRANK_CURSOR : V12_1_ENGINE_CRANK_CURSOR_OFF,
2366
+ engineSweepStartIdxOff: isSbf ? V12_1_SBF_OFF_SWEEP_START_IDX : V12_1_ENGINE_SWEEP_START_IDX_OFF,
2367
+ engineLifetimeLiquidationsOff: isSbf ? V12_1_SBF_OFF_LIFETIME_LIQUIDATIONS : V12_1_ENGINE_LIFETIME_LIQUIDATIONS_OFF,
2368
+ engineLifetimeForceClosesOff: isSbf ? -1 : V12_1_ENGINE_LIFETIME_FORCE_CLOSES_OFF,
2369
+ // not in deployed struct
2370
+ engineNetLpPosOff: isSbf ? -1 : V12_1_ENGINE_NET_LP_POS_OFF,
2371
+ // not in deployed struct
2372
+ engineLpSumAbsOff: isSbf ? -1 : V12_1_ENGINE_LP_SUM_ABS_OFF,
2373
+ // not in deployed struct
2374
+ engineLpMaxAbsOff: isSbf ? -1 : V12_1_ENGINE_LP_MAX_ABS_OFF,
2375
+ // not in deployed struct
2376
+ engineLpMaxAbsSweepOff: isSbf ? -1 : V12_1_ENGINE_LP_MAX_ABS_SWEEP_OFF,
2377
+ // not in deployed struct
2378
+ engineEmergencyOiModeOff: isSbf ? -1 : V12_1_ENGINE_EMERGENCY_OI_MODE_OFF,
2379
+ // not in deployed struct
2380
+ engineEmergencyStartSlotOff: isSbf ? -1 : V12_1_ENGINE_EMERGENCY_START_SLOT_OFF,
2381
+ // not in deployed struct
2382
+ engineLastBreakerSlotOff: isSbf ? -1 : V12_1_ENGINE_LAST_BREAKER_SLOT_OFF,
2383
+ // not in deployed struct
2384
+ engineBitmapOff: bitmapOff,
2223
2385
  postBitmap: 18,
2224
2386
  acctOwnerOff: V12_1_ACCT_OWNER_OFF,
2225
- hasInsuranceIsolation: true,
2226
- engineInsuranceIsolatedOff: 48,
2227
- engineInsuranceIsolationBpsOff: 64
2387
+ // InsuranceFund on deployed program is just {balance: U128} = 16 bytes.
2388
+ // No isolated_balance or insurance_isolation_bps fields.
2389
+ hasInsuranceIsolation: !isSbf,
2390
+ engineInsuranceIsolatedOff: isSbf ? -1 : 48,
2391
+ engineInsuranceIsolationBpsOff: isSbf ? -1 : 64
2392
+ };
2393
+ }
2394
+ function buildLayoutV12_1EP(maxAccounts) {
2395
+ const engineOff = V12_1_SBF_ENGINE_OFF;
2396
+ const bitmapOff = V12_1_SBF_BITMAP_OFF;
2397
+ const accountSize = V12_1_EP_SBF_ACCOUNT_SIZE;
2398
+ const bitmapWords = Math.ceil(maxAccounts / 64);
2399
+ const bitmapBytes = bitmapWords * 8;
2400
+ const postBitmap = 18;
2401
+ const nextFreeBytes = maxAccounts * 2;
2402
+ const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;
2403
+ const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;
2404
+ return {
2405
+ version: 1,
2406
+ headerLen: 72,
2407
+ configOffset: 72,
2408
+ configLen: 544,
2409
+ reservedOff: 80,
2410
+ // V1_RESERVED_OFF
2411
+ engineOff,
2412
+ accountSize,
2413
+ maxAccounts,
2414
+ bitmapWords,
2415
+ accountsOff: engineOff + accountsOffRel,
2416
+ engineInsuranceOff: 16,
2417
+ engineParamsOff: 32,
2418
+ // V12_1_ENGINE_PARAMS_OFF_SBF
2419
+ paramsSize: 184,
2420
+ // V12_1_PARAMS_SIZE_SBF
2421
+ // Engine offsets identical to V12_1 SBF
2422
+ engineCurrentSlotOff: V12_1_SBF_OFF_CURRENT_SLOT,
2423
+ engineFundingIndexOff: -1,
2424
+ engineLastFundingSlotOff: -1,
2425
+ engineFundingRateBpsOff: V12_1_SBF_OFF_FUNDING_RATE,
2426
+ engineMarkPriceOff: V12_1_SBF_OFF_MARK_PRICE_E6,
2427
+ engineLastCrankSlotOff: V12_1_SBF_OFF_LAST_CRANK_SLOT,
2428
+ engineMaxCrankStalenessOff: V12_1_SBF_OFF_MAX_CRANK_STALENESS,
2429
+ engineTotalOiOff: V12_1_SBF_OFF_TOTAL_OI,
2430
+ engineLongOiOff: V12_1_SBF_OFF_LONG_OI,
2431
+ engineShortOiOff: V12_1_SBF_OFF_SHORT_OI,
2432
+ engineCTotOff: V12_1_SBF_OFF_C_TOT,
2433
+ enginePnlPosTotOff: V12_1_SBF_OFF_PNL_POS_TOT,
2434
+ engineLiqCursorOff: V12_1_SBF_OFF_LIQ_CURSOR,
2435
+ engineGcCursorOff: V12_1_SBF_OFF_GC_CURSOR,
2436
+ engineLastSweepStartOff: V12_1_SBF_OFF_LAST_SWEEP_START,
2437
+ engineLastSweepCompleteOff: V12_1_SBF_OFF_LAST_SWEEP_COMPLETE,
2438
+ engineCrankCursorOff: V12_1_SBF_OFF_CRANK_CURSOR,
2439
+ engineSweepStartIdxOff: V12_1_SBF_OFF_SWEEP_START_IDX,
2440
+ engineLifetimeLiquidationsOff: V12_1_SBF_OFF_LIFETIME_LIQUIDATIONS,
2441
+ engineLifetimeForceClosesOff: -1,
2442
+ engineNetLpPosOff: -1,
2443
+ engineLpSumAbsOff: -1,
2444
+ engineLpMaxAbsOff: -1,
2445
+ engineLpMaxAbsSweepOff: -1,
2446
+ engineEmergencyOiModeOff: -1,
2447
+ engineEmergencyStartSlotOff: -1,
2448
+ engineLastBreakerSlotOff: -1,
2449
+ engineBitmapOff: bitmapOff,
2450
+ postBitmap: 18,
2451
+ // Account offsets — shifted +8 from V12_1 due to entry_price insertion
2452
+ acctOwnerOff: V12_1_EP_ACCT_OWNER_OFF,
2453
+ // 216 (was 208)
2454
+ hasInsuranceIsolation: false,
2455
+ engineInsuranceIsolatedOff: -1,
2456
+ engineInsuranceIsolationBpsOff: -1
2457
+ };
2458
+ }
2459
+ function buildLayoutV12_15(maxAccounts, dataLen) {
2460
+ const isSbf = dataLen === 237512;
2461
+ const accountSize = isSbf ? V12_15_ACCOUNT_SIZE_SMALL : V12_15_ACCOUNT_SIZE;
2462
+ const engineOff = isSbf ? V12_15_ENGINE_OFF_SBF : V12_15_ENGINE_OFF;
2463
+ const bitmapOff = V12_15_ENGINE_BITMAP_OFF;
2464
+ const effectiveBitmapOff = isSbf ? 648 : bitmapOff;
2465
+ const bitmapWords = Math.ceil(maxAccounts / 64);
2466
+ const bitmapBytes = bitmapWords * 8;
2467
+ const postBitmap = 18;
2468
+ const nextFreeBytes = maxAccounts * 2;
2469
+ const preAccountsLen = effectiveBitmapOff + bitmapBytes + postBitmap + nextFreeBytes;
2470
+ const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;
2471
+ return {
2472
+ version: 2,
2473
+ headerLen: V0_HEADER_LEN,
2474
+ // 72
2475
+ configOffset: V0_HEADER_LEN,
2476
+ // 72
2477
+ configLen: 552,
2478
+ // SBF CONFIG_LEN for v12.15
2479
+ reservedOff: V1_RESERVED_OFF,
2480
+ // 80
2481
+ engineOff,
2482
+ accountSize,
2483
+ maxAccounts,
2484
+ bitmapWords,
2485
+ accountsOff: engineOff + accountsOffRel,
2486
+ engineInsuranceOff: 16,
2487
+ engineParamsOff: V12_15_ENGINE_PARAMS_OFF,
2488
+ // 32
2489
+ paramsSize: isSbf ? 184 : V12_15_PARAMS_SIZE,
2490
+ // SBF=184 (no trailing pad), native=192
2491
+ engineCurrentSlotOff: isSbf ? 216 : V12_15_ENGINE_CURRENT_SLOT_OFF,
2492
+ // SBF=216, native=224
2493
+ engineFundingIndexOff: -1,
2494
+ // not present in v12.15 engine struct
2495
+ engineLastFundingSlotOff: -1,
2496
+ // not present in v12.15 engine struct
2497
+ engineFundingRateBpsOff: isSbf ? 224 : V12_15_ENGINE_FUNDING_RATE_E9_OFF,
2498
+ // SBF=224, native=240
2499
+ engineMarkPriceOff: -1,
2500
+ // not present in v12.15
2501
+ engineLastCrankSlotOff: -1,
2502
+ // not yet mapped
2503
+ engineMaxCrankStalenessOff: -1,
2504
+ // not yet mapped
2505
+ engineTotalOiOff: -1,
2506
+ // not present in v12.15 engine
2507
+ engineLongOiOff: -1,
2508
+ // not present in v12.15 engine
2509
+ engineShortOiOff: -1,
2510
+ // not present in v12.15 engine
2511
+ engineCTotOff: isSbf ? 320 : V12_15_ENGINE_C_TOT_OFF,
2512
+ // SBF=320 (verified on-chain), native=344
2513
+ enginePnlPosTotOff: isSbf ? 336 : V12_15_ENGINE_PNL_POS_TOT_OFF,
2514
+ // SBF=336 (verified), native=368
2515
+ engineLiqCursorOff: -1,
2516
+ // not yet mapped
2517
+ engineGcCursorOff: -1,
2518
+ // not yet mapped
2519
+ engineLastSweepStartOff: -1,
2520
+ // not yet mapped
2521
+ engineLastSweepCompleteOff: -1,
2522
+ // not yet mapped
2523
+ engineCrankCursorOff: -1,
2524
+ // not yet mapped
2525
+ engineSweepStartIdxOff: -1,
2526
+ // not yet mapped
2527
+ engineLifetimeLiquidationsOff: -1,
2528
+ // not yet mapped
2529
+ engineLifetimeForceClosesOff: -1,
2530
+ // not present in v12.15
2531
+ engineNetLpPosOff: -1,
2532
+ // not present in v12.15
2533
+ engineLpSumAbsOff: -1,
2534
+ // not present in v12.15
2535
+ engineLpMaxAbsOff: -1,
2536
+ // not present in v12.15
2537
+ engineLpMaxAbsSweepOff: -1,
2538
+ // not present in v12.15
2539
+ engineEmergencyOiModeOff: -1,
2540
+ // not present in v12.15
2541
+ engineEmergencyStartSlotOff: -1,
2542
+ // not present in v12.15
2543
+ engineLastBreakerSlotOff: -1,
2544
+ // not present in v12.15
2545
+ engineBitmapOff: effectiveBitmapOff,
2546
+ // SBF=640, native=862
2547
+ postBitmap,
2548
+ acctOwnerOff: V12_15_ACCT_OWNER_OFF,
2549
+ // 192
2550
+ hasInsuranceIsolation: false,
2551
+ engineInsuranceIsolatedOff: -1,
2552
+ engineInsuranceIsolationBpsOff: -1
2228
2553
  };
2229
2554
  }
2230
2555
  function detectSlabLayout(dataLen, data) {
2556
+ const v1215n = V12_15_SIZES.get(dataLen);
2557
+ if (v1215n !== void 0) return buildLayoutV12_15(v1215n, dataLen);
2558
+ const v121epn = V12_1_EP_SIZES.get(dataLen);
2559
+ if (v121epn !== void 0) return buildLayoutV12_1EP(v121epn);
2231
2560
  const v121n = V12_1_SIZES.get(dataLen);
2232
- if (v121n !== void 0) return buildLayoutV12_1(v121n);
2561
+ if (v121n !== void 0) return buildLayoutV12_1(v121n, dataLen);
2233
2562
  const vsdpn = V_SETDEXPOOL_SIZES.get(dataLen);
2234
2563
  if (vsdpn !== void 0) return buildLayoutVSetDexPool(vsdpn);
2235
2564
  const v1m2n = V1M2_SIZES.get(dataLen);
@@ -2274,6 +2603,15 @@ var PARAMS_LIQUIDATION_FEE_BPS_OFF = 96;
2274
2603
  var PARAMS_LIQUIDATION_FEE_CAP_OFF = 104;
2275
2604
  var PARAMS_LIQUIDATION_BUFFER_OFF = 120;
2276
2605
  var PARAMS_MIN_LIQUIDATION_OFF = 128;
2606
+ var V12_1_PARAMS_MAINT_FEE_OFF = 56;
2607
+ var V12_1_PARAMS_MAX_CRANK_OFF = 72;
2608
+ var V12_1_PARAMS_LIQ_FEE_BPS_OFF = 80;
2609
+ var V12_1_PARAMS_LIQ_FEE_CAP_OFF = 88;
2610
+ var V12_1_PARAMS_MIN_LIQ_OFF = 104;
2611
+ var V12_1_PARAMS_MIN_INITIAL_DEP_OFF = 120;
2612
+ var V12_1_PARAMS_MIN_NZ_MM_OFF = 136;
2613
+ var V12_1_PARAMS_MIN_NZ_IM_OFF = 152;
2614
+ var V12_1_PARAMS_INS_FLOOR_OFF = 168;
2277
2615
  var ACCT_ACCOUNT_ID_OFF = 0;
2278
2616
  var ACCT_CAPITAL_OFF = 8;
2279
2617
  var ACCT_KIND_OFF = 24;
@@ -2396,14 +2734,6 @@ function parseConfig(data, layoutHint) {
2396
2734
  off += 8;
2397
2735
  const fundingMaxBpsPerSlot = readI64LE(data, off);
2398
2736
  off += 8;
2399
- const fundingPremiumWeightBps = readU64LE(data, off);
2400
- off += 8;
2401
- const fundingSettlementIntervalSlots = readU64LE(data, off);
2402
- off += 8;
2403
- const fundingPremiumDampeningE6 = readU64LE(data, off);
2404
- off += 8;
2405
- const fundingPremiumMaxBpsPerSlot = readU64LE(data, off);
2406
- off += 8;
2407
2737
  const threshFloor = readU128LE(data, off);
2408
2738
  off += 16;
2409
2739
  const threshRiskBps = readU64LE(data, off);
@@ -2490,10 +2820,10 @@ function parseConfig(data, layoutHint) {
2490
2820
  fundingInvScaleNotionalE6,
2491
2821
  fundingMaxPremiumBps,
2492
2822
  fundingMaxBpsPerSlot,
2493
- fundingPremiumWeightBps,
2494
- fundingSettlementIntervalSlots,
2495
- fundingPremiumDampeningE6,
2496
- fundingPremiumMaxBpsPerSlot,
2823
+ fundingPremiumWeightBps: 0n,
2824
+ fundingSettlementIntervalSlots: 0n,
2825
+ fundingPremiumDampeningE6: 0n,
2826
+ fundingPremiumMaxBpsPerSlot: 0n,
2497
2827
  threshFloor,
2498
2828
  threshRiskBps,
2499
2829
  threshUpdateIntervalSlots,
@@ -2531,23 +2861,57 @@ function parseParams(data, layoutHint) {
2531
2861
  if (data.length < base + Math.min(paramsSize, 56)) {
2532
2862
  throw new Error("Slab data too short for RiskParams");
2533
2863
  }
2864
+ const isV12_15Params = paramsSize === V12_15_PARAMS_SIZE || paramsSize === 184;
2865
+ const isV12_1Sbf = !isV12_15Params && layout !== null && layout !== void 0 && layout.engineOff === V12_1_SBF_ENGINE_OFF && paramsSize === 184;
2534
2866
  const result = {
2535
- warmupPeriodSlots: readU64LE(data, base + PARAMS_WARMUP_PERIOD_OFF),
2536
- maintenanceMarginBps: readU64LE(data, base + PARAMS_MAINTENANCE_MARGIN_OFF),
2537
- initialMarginBps: readU64LE(data, base + PARAMS_INITIAL_MARGIN_OFF),
2538
- tradingFeeBps: readU64LE(data, base + PARAMS_TRADING_FEE_OFF),
2539
- maxAccounts: readU64LE(data, base + PARAMS_MAX_ACCOUNTS_OFF),
2540
- newAccountFee: readU128LE(data, base + PARAMS_NEW_ACCOUNT_FEE_OFF),
2541
- // Extended params: only read if V1 (paramsSize >= 144)
2867
+ warmupPeriodSlots: isV12_15Params ? readU64LE(data, base + V12_15_PARAMS_H_MIN_OFF) : readU64LE(data, base + PARAMS_WARMUP_PERIOD_OFF),
2868
+ maintenanceMarginBps: isV12_15Params ? readU64LE(data, base + 0) : readU64LE(data, base + PARAMS_MAINTENANCE_MARGIN_OFF),
2869
+ initialMarginBps: isV12_15Params ? readU64LE(data, base + 8) : readU64LE(data, base + PARAMS_INITIAL_MARGIN_OFF),
2870
+ tradingFeeBps: isV12_15Params ? readU64LE(data, base + 16) : readU64LE(data, base + PARAMS_TRADING_FEE_OFF),
2871
+ maxAccounts: isV12_15Params ? readU64LE(data, base + V12_15_PARAMS_MAX_ACCOUNTS_OFF) : readU64LE(data, base + PARAMS_MAX_ACCOUNTS_OFF),
2872
+ newAccountFee: isV12_15Params ? readU128LE(data, base + 32) : readU128LE(data, base + PARAMS_NEW_ACCOUNT_FEE_OFF),
2873
+ // Extended params: defaults; overwritten below if layout supports them
2542
2874
  riskReductionThreshold: 0n,
2543
2875
  maintenanceFeePerSlot: 0n,
2544
2876
  maxCrankStalenessSlots: 0n,
2545
2877
  liquidationFeeBps: 0n,
2546
2878
  liquidationFeeCap: 0n,
2547
2879
  liquidationBufferBps: 0n,
2548
- minLiquidationAbs: 0n
2880
+ minLiquidationAbs: 0n,
2881
+ minInitialDeposit: 0n,
2882
+ minNonzeroMmReq: 0n,
2883
+ minNonzeroImReq: 0n,
2884
+ insuranceFloor: 0n,
2885
+ hMin: 0n,
2886
+ hMax: 0n
2549
2887
  };
2550
- if (paramsSize >= 144) {
2888
+ if (isV12_15Params) {
2889
+ result.hMin = readU64LE(data, base + V12_15_PARAMS_H_MIN_OFF);
2890
+ result.hMax = readU64LE(data, base + V12_15_PARAMS_H_MAX_OFF);
2891
+ result.insuranceFloor = readU128LE(data, base + V12_15_PARAMS_INSURANCE_FLOOR_OFF);
2892
+ result.riskReductionThreshold = 0n;
2893
+ result.maintenanceFeePerSlot = 0n;
2894
+ result.maxCrankStalenessSlots = readU64LE(data, base + 48);
2895
+ result.liquidationFeeBps = readU64LE(data, base + 56);
2896
+ result.liquidationFeeCap = readU128LE(data, base + 64);
2897
+ result.liquidationBufferBps = 0n;
2898
+ result.minLiquidationAbs = readU128LE(data, base + 80);
2899
+ result.minInitialDeposit = readU128LE(data, base + 96);
2900
+ result.minNonzeroMmReq = readU128LE(data, base + 112);
2901
+ result.minNonzeroImReq = readU128LE(data, base + 128);
2902
+ } else if (isV12_1Sbf) {
2903
+ result.maintenanceFeePerSlot = readU128LE(data, base + V12_1_PARAMS_MAINT_FEE_OFF);
2904
+ result.maxCrankStalenessSlots = readU64LE(data, base + V12_1_PARAMS_MAX_CRANK_OFF);
2905
+ result.liquidationFeeBps = readU64LE(data, base + V12_1_PARAMS_LIQ_FEE_BPS_OFF);
2906
+ result.liquidationFeeCap = readU128LE(data, base + V12_1_PARAMS_LIQ_FEE_CAP_OFF);
2907
+ result.minLiquidationAbs = readU128LE(data, base + V12_1_PARAMS_MIN_LIQ_OFF);
2908
+ result.minInitialDeposit = readU128LE(data, base + V12_1_PARAMS_MIN_INITIAL_DEP_OFF);
2909
+ result.minNonzeroMmReq = readU128LE(data, base + V12_1_PARAMS_MIN_NZ_MM_OFF);
2910
+ result.minNonzeroImReq = readU128LE(data, base + V12_1_PARAMS_MIN_NZ_IM_OFF);
2911
+ result.insuranceFloor = readU128LE(data, base + V12_1_PARAMS_INS_FLOOR_OFF);
2912
+ result.hMin = result.warmupPeriodSlots;
2913
+ result.hMax = result.warmupPeriodSlots;
2914
+ } else if (paramsSize >= 144) {
2551
2915
  result.riskReductionThreshold = readU128LE(data, base + PARAMS_RISK_THRESHOLD_OFF);
2552
2916
  result.maintenanceFeePerSlot = readU128LE(data, base + PARAMS_MAINTENANCE_FEE_OFF);
2553
2917
  result.maxCrankStalenessSlots = readU64LE(data, base + PARAMS_MAX_CRANK_STALENESS_OFF);
@@ -2555,6 +2919,8 @@ function parseParams(data, layoutHint) {
2555
2919
  result.liquidationFeeCap = readU128LE(data, base + PARAMS_LIQUIDATION_FEE_CAP_OFF);
2556
2920
  result.liquidationBufferBps = readU64LE(data, base + PARAMS_LIQUIDATION_BUFFER_OFF);
2557
2921
  result.minLiquidationAbs = readU128LE(data, base + PARAMS_MIN_LIQUIDATION_OFF);
2922
+ result.hMin = result.warmupPeriodSlots;
2923
+ result.hMax = result.warmupPeriodSlots;
2558
2924
  }
2559
2925
  return result;
2560
2926
  }
@@ -2564,25 +2930,31 @@ function parseEngine(data) {
2564
2930
  throw new Error(`Unrecognized slab data length: ${data.length}. Cannot determine layout version.`);
2565
2931
  }
2566
2932
  const base = layout.engineOff;
2933
+ const isV12_15 = (layout.accountSize === V12_15_ACCOUNT_SIZE || layout.accountSize === V12_15_ACCOUNT_SIZE_SMALL) && layout.engineOff === V12_15_ENGINE_OFF;
2934
+ const fundingRateBpsPerSlotLast = isV12_15 ? readI128LE(data, base + V12_15_ENGINE_FUNDING_RATE_E9_OFF) : readI64LE(data, base + layout.engineFundingRateBpsOff);
2567
2935
  return {
2568
2936
  vault: readU128LE(data, base),
2569
2937
  insuranceFund: {
2570
2938
  balance: readU128LE(data, base + layout.engineInsuranceOff),
2571
- feeRevenue: readU128LE(data, base + layout.engineInsuranceOff + 16),
2939
+ // feeRevenue: only exists in percolator-core (80-byte InsuranceFund), not deployed (16-byte)
2940
+ feeRevenue: layout.hasInsuranceIsolation ? readU128LE(data, base + layout.engineInsuranceOff + 16) : 0n,
2572
2941
  isolatedBalance: layout.hasInsuranceIsolation ? readU128LE(data, base + layout.engineInsuranceIsolatedOff) : 0n,
2573
2942
  isolationBps: layout.hasInsuranceIsolation ? readU16LE(data, base + layout.engineInsuranceIsolationBpsOff) : 0
2574
2943
  },
2575
2944
  currentSlot: readU64LE(data, base + layout.engineCurrentSlotOff),
2576
- fundingIndexQpbE6: readI128LE(data, base + layout.engineFundingIndexOff),
2577
- lastFundingSlot: readU64LE(data, base + layout.engineLastFundingSlotOff),
2578
- fundingRateBpsPerSlotLast: readI64LE(data, base + layout.engineFundingRateBpsOff),
2945
+ fundingIndexQpbE6: layout.engineFundingIndexOff >= 0 ? readI128LE(data, base + layout.engineFundingIndexOff) : 0n,
2946
+ lastFundingSlot: layout.engineLastFundingSlotOff >= 0 ? readU64LE(data, base + layout.engineLastFundingSlotOff) : 0n,
2947
+ fundingRateBpsPerSlotLast,
2948
+ fundingRateE9: isV12_15 ? readI128LE(data, base + V12_15_ENGINE_FUNDING_RATE_E9_OFF) : 0n,
2949
+ marketMode: isV12_15 ? readU8(data, base + V12_15_ENGINE_MARKET_MODE_OFF) === 1 ? 1 : 0 : null,
2579
2950
  lastCrankSlot: readU64LE(data, base + layout.engineLastCrankSlotOff),
2580
2951
  maxCrankStalenessSlots: readU64LE(data, base + layout.engineMaxCrankStalenessOff),
2581
- totalOpenInterest: readU128LE(data, base + layout.engineTotalOiOff),
2952
+ totalOpenInterest: layout.engineTotalOiOff >= 0 ? readU128LE(data, base + layout.engineTotalOiOff) : 0n,
2582
2953
  longOi: layout.engineLongOiOff >= 0 ? readU128LE(data, base + layout.engineLongOiOff) : 0n,
2583
2954
  shortOi: layout.engineShortOiOff >= 0 ? readU128LE(data, base + layout.engineShortOiOff) : 0n,
2584
2955
  cTot: readU128LE(data, base + layout.engineCTotOff),
2585
2956
  pnlPosTot: readU128LE(data, base + layout.enginePnlPosTotOff),
2957
+ pnlMaturedPosTot: isV12_15 ? readU128LE(data, base + V12_15_ENGINE_PNL_MATURED_POS_TOT_OFF) : 0n,
2586
2958
  liqCursor: readU16LE(data, base + layout.engineLiqCursorOff),
2587
2959
  gcCursor: readU16LE(data, base + layout.engineGcCursorOff),
2588
2960
  lastSweepStartSlot: readU64LE(data, base + layout.engineLastSweepStartOff),
@@ -2590,9 +2962,9 @@ function parseEngine(data) {
2590
2962
  crankCursor: readU16LE(data, base + layout.engineCrankCursorOff),
2591
2963
  sweepStartIdx: readU16LE(data, base + layout.engineSweepStartIdxOff),
2592
2964
  lifetimeLiquidations: readU64LE(data, base + layout.engineLifetimeLiquidationsOff),
2593
- lifetimeForceCloses: readU64LE(data, base + layout.engineLifetimeForceClosesOff),
2594
- netLpPos: readI128LE(data, base + layout.engineNetLpPosOff),
2595
- lpSumAbs: readU128LE(data, base + layout.engineLpSumAbsOff),
2965
+ lifetimeForceCloses: layout.engineLifetimeForceClosesOff >= 0 ? readU64LE(data, base + layout.engineLifetimeForceClosesOff) : 0n,
2966
+ netLpPos: layout.engineNetLpPosOff >= 0 ? readI128LE(data, base + layout.engineNetLpPosOff) : 0n,
2967
+ lpSumAbs: layout.engineLpSumAbsOff >= 0 ? readU128LE(data, base + layout.engineLpSumAbsOff) : 0n,
2596
2968
  lpMaxAbs: layout.engineLpMaxAbsOff >= 0 ? readU128LE(data, base + layout.engineLpMaxAbsOff) : 0n,
2597
2969
  lpMaxAbsSweep: layout.engineLpMaxAbsSweepOff >= 0 ? readU128LE(data, base + layout.engineLpMaxAbsSweepOff) : 0n,
2598
2970
  emergencyOiMode: layout.engineEmergencyOiModeOff >= 0 ? data[base + layout.engineEmergencyOiModeOff] !== 0 : false,
@@ -2659,17 +3031,59 @@ function parseAccount(data, idx) {
2659
3031
  if (data.length < base + layout.accountSize) {
2660
3032
  throw new Error("Slab data too short for account");
2661
3033
  }
2662
- const isV12_1 = layout.accountSize >= 320;
2663
- const isAdl = layout.accountSize >= 312;
3034
+ const isV12_15 = layout.accountSize === V12_15_ACCOUNT_SIZE || layout.accountSize === V12_15_ACCOUNT_SIZE_SMALL;
3035
+ const isV12_1EP = !isV12_15 && layout.accountSize === V12_1_EP_SBF_ACCOUNT_SIZE && layout.engineOff === V12_1_SBF_ENGINE_OFF;
3036
+ 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);
3037
+ const isAdl = !isV12_15 && (layout.accountSize >= 312 || isV12_1 || isV12_1EP);
3038
+ if (isV12_15) {
3039
+ const kindByte2 = readU8(data, base + V12_15_ACCT_KIND_OFF);
3040
+ const kind2 = kindByte2 === 1 ? 1 /* LP */ : 0 /* User */;
3041
+ const cohortCount = readU8(data, base + V12_15_ACCT_EXACT_COHORT_COUNT_OFF);
3042
+ const exactReserveCohorts = [];
3043
+ for (let i = 0; i < 62; i++) {
3044
+ const cohortOff = base + V12_15_ACCT_EXACT_RESERVE_COHORTS_OFF + i * 64;
3045
+ exactReserveCohorts.push(data.slice(cohortOff, cohortOff + 64));
3046
+ }
3047
+ const overflowOlderPresent = readU8(data, base + V12_15_ACCT_OVERFLOW_OLDER_PRESENT_OFF) !== 0;
3048
+ const overflowNewestPresent = readU8(data, base + V12_15_ACCT_OVERFLOW_NEWEST_PRESENT_OFF) !== 0;
3049
+ return {
3050
+ kind: kind2,
3051
+ accountId: readU64LE(data, base + V12_15_ACCT_ACCOUNT_ID_OFF),
3052
+ capital: readU128LE(data, base + V12_15_ACCT_CAPITAL_OFF),
3053
+ pnl: readI128LE(data, base + V12_15_ACCT_PNL_OFF),
3054
+ reservedPnl: readU128LE(data, base + V12_15_ACCT_RESERVED_PNL_OFF),
3055
+ warmupStartedAtSlot: 0n,
3056
+ // removed in v12.15
3057
+ warmupSlopePerStep: 0n,
3058
+ // removed in v12.15
3059
+ positionSize: readI128LE(data, base + V12_15_ACCT_POSITION_BASIS_Q_OFF),
3060
+ entryPrice: readU64LE(data, base + V12_15_ACCT_ENTRY_PRICE_OFF),
3061
+ fundingIndex: 0n,
3062
+ // not present in v12.15 account struct
3063
+ matcherProgram: new PublicKey3(data.subarray(base + V12_15_ACCT_MATCHER_PROGRAM_OFF, base + V12_15_ACCT_MATCHER_PROGRAM_OFF + 32)),
3064
+ matcherContext: new PublicKey3(data.subarray(base + V12_15_ACCT_MATCHER_CONTEXT_OFF, base + V12_15_ACCT_MATCHER_CONTEXT_OFF + 32)),
3065
+ owner: new PublicKey3(data.subarray(base + V12_15_ACCT_OWNER_OFF, base + V12_15_ACCT_OWNER_OFF + 32)),
3066
+ feeCredits: readI128LE(data, base + V12_15_ACCT_FEE_CREDITS_OFF),
3067
+ lastFeeSlot: 0n,
3068
+ // removed in v12.15
3069
+ feesEarnedTotal: readU128LE(data, base + V12_15_ACCT_FEES_EARNED_TOTAL_OFF),
3070
+ exactReserveCohorts,
3071
+ exactCohortCount: cohortCount,
3072
+ overflowOlder: data.slice(base + V12_15_ACCT_OVERFLOW_OLDER_OFF, base + V12_15_ACCT_OVERFLOW_OLDER_OFF + 64),
3073
+ overflowOlderPresent,
3074
+ overflowNewest: data.slice(base + V12_15_ACCT_OVERFLOW_NEWEST_OFF, base + V12_15_ACCT_OVERFLOW_NEWEST_OFF + 64),
3075
+ overflowNewestPresent
3076
+ };
3077
+ }
2664
3078
  const warmupStartedOff = isAdl ? V_ADL_ACCT_WARMUP_STARTED_OFF : ACCT_WARMUP_STARTED_OFF;
2665
3079
  const warmupSlopeOff = isAdl ? V_ADL_ACCT_WARMUP_SLOPE_OFF : ACCT_WARMUP_SLOPE_OFF;
2666
- const positionSizeOff = isV12_1 ? V12_1_ACCT_POSITION_SIZE_OFF : isAdl ? V_ADL_ACCT_POSITION_SIZE_OFF : ACCT_POSITION_SIZE_OFF;
2667
- const entryPriceOff = isV12_1 ? V12_1_ACCT_ENTRY_PRICE_OFF : isAdl ? V_ADL_ACCT_ENTRY_PRICE_OFF : ACCT_ENTRY_PRICE_OFF;
2668
- const fundingIndexOff = isV12_1 ? V12_1_ACCT_FUNDING_INDEX_OFF : isAdl ? V_ADL_ACCT_FUNDING_INDEX_OFF : ACCT_FUNDING_INDEX_OFF;
2669
- const matcherProgOff = isV12_1 ? V12_1_ACCT_MATCHER_PROGRAM_OFF : isAdl ? V_ADL_ACCT_MATCHER_PROGRAM_OFF : ACCT_MATCHER_PROGRAM_OFF;
2670
- const matcherCtxOff = isV12_1 ? V12_1_ACCT_MATCHER_CONTEXT_OFF : isAdl ? V_ADL_ACCT_MATCHER_CONTEXT_OFF : ACCT_MATCHER_CONTEXT_OFF;
2671
- const feeCreditsOff = isV12_1 ? V12_1_ACCT_FEE_CREDITS_OFF : isAdl ? V_ADL_ACCT_FEE_CREDITS_OFF : ACCT_FEE_CREDITS_OFF;
2672
- const lastFeeSlotOff = isV12_1 ? V12_1_ACCT_LAST_FEE_SLOT_OFF : isAdl ? V_ADL_ACCT_LAST_FEE_SLOT_OFF : ACCT_LAST_FEE_SLOT_OFF;
3080
+ const positionSizeOff = isV12_1 || isV12_1EP ? V12_1_ACCT_POSITION_SIZE_OFF : isAdl ? V_ADL_ACCT_POSITION_SIZE_OFF : ACCT_POSITION_SIZE_OFF;
3081
+ const entryPriceOff = isV12_1EP ? V12_1_EP_ACCT_ENTRY_PRICE_OFF : isV12_1 ? V12_1_ACCT_ENTRY_PRICE_OFF : isAdl ? V_ADL_ACCT_ENTRY_PRICE_OFF : ACCT_ENTRY_PRICE_OFF;
3082
+ const fundingIndexOff = isV12_1 || isV12_1EP ? -1 : isAdl ? V_ADL_ACCT_FUNDING_INDEX_OFF : ACCT_FUNDING_INDEX_OFF;
3083
+ const matcherProgOff = isV12_1EP ? V12_1_EP_ACCT_MATCHER_PROGRAM_OFF : isV12_1 ? V12_1_ACCT_MATCHER_PROGRAM_OFF : isAdl ? V_ADL_ACCT_MATCHER_PROGRAM_OFF : ACCT_MATCHER_PROGRAM_OFF;
3084
+ const matcherCtxOff = isV12_1EP ? V12_1_EP_ACCT_MATCHER_CONTEXT_OFF : isV12_1 ? V12_1_ACCT_MATCHER_CONTEXT_OFF : isAdl ? V_ADL_ACCT_MATCHER_CONTEXT_OFF : ACCT_MATCHER_CONTEXT_OFF;
3085
+ const feeCreditsOff = isV12_1EP ? V12_1_EP_ACCT_FEE_CREDITS_OFF : isV12_1 ? V12_1_ACCT_FEE_CREDITS_OFF : isAdl ? V_ADL_ACCT_FEE_CREDITS_OFF : ACCT_FEE_CREDITS_OFF;
3086
+ const lastFeeSlotOff = isV12_1EP ? V12_1_EP_ACCT_LAST_FEE_SLOT_OFF : isV12_1 ? V12_1_ACCT_LAST_FEE_SLOT_OFF : isAdl ? V_ADL_ACCT_LAST_FEE_SLOT_OFF : ACCT_LAST_FEE_SLOT_OFF;
2673
3087
  const kindByte = readU8(data, base + ACCT_KIND_OFF);
2674
3088
  const kind = kindByte === 1 ? 1 /* LP */ : 0 /* User */;
2675
3089
  return {
@@ -2681,14 +3095,23 @@ function parseAccount(data, idx) {
2681
3095
  warmupStartedAtSlot: readU64LE(data, base + warmupStartedOff),
2682
3096
  warmupSlopePerStep: readU128LE(data, base + warmupSlopeOff),
2683
3097
  positionSize: readI128LE(data, base + positionSizeOff),
2684
- entryPrice: readU64LE(data, base + entryPriceOff),
2685
- // V12_1 changed funding_index from i128 to i64 (legacy field moved to end of account)
2686
- fundingIndex: isV12_1 ? BigInt(readI64LE(data, base + fundingIndexOff)) : readI128LE(data, base + fundingIndexOff),
3098
+ entryPrice: entryPriceOff >= 0 ? readU64LE(data, base + entryPriceOff) : 0n,
3099
+ // V12_1/V12_1_EP: funding_index not present in SBF layout
3100
+ fundingIndex: isV12_1 || isV12_1EP ? fundingIndexOff >= 0 ? BigInt(readI64LE(data, base + fundingIndexOff)) : 0n : readI128LE(data, base + fundingIndexOff),
2687
3101
  matcherProgram: new PublicKey3(data.subarray(base + matcherProgOff, base + matcherProgOff + 32)),
2688
3102
  matcherContext: new PublicKey3(data.subarray(base + matcherCtxOff, base + matcherCtxOff + 32)),
2689
3103
  owner: new PublicKey3(data.subarray(base + layout.acctOwnerOff, base + layout.acctOwnerOff + 32)),
2690
3104
  feeCredits: readI128LE(data, base + feeCreditsOff),
2691
- lastFeeSlot: readU64LE(data, base + lastFeeSlotOff)
3105
+ lastFeeSlot: readU64LE(data, base + lastFeeSlotOff),
3106
+ feesEarnedTotal: 0n,
3107
+ // not present in pre-v12.15 layouts
3108
+ exactReserveCohorts: null,
3109
+ // not present in pre-v12.15 layouts
3110
+ exactCohortCount: null,
3111
+ overflowOlder: null,
3112
+ overflowOlderPresent: null,
3113
+ overflowNewest: null,
3114
+ overflowNewestPresent: null
2692
3115
  };
2693
3116
  }
2694
3117
  function parseAllAccounts(data) {
@@ -2736,12 +3159,6 @@ function deriveLpPda(programId, slab, lpIdx) {
2736
3159
  programId
2737
3160
  );
2738
3161
  }
2739
- function deriveKeeperFund(programId, slab) {
2740
- return PublicKey4.findProgramAddressSync(
2741
- [textEncoder.encode("keeper_fund"), slab.toBytes()],
2742
- programId
2743
- );
2744
- }
2745
3162
  var PUMPSWAP_PROGRAM_ID = new PublicKey4(
2746
3163
  "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA"
2747
3164
  );
@@ -2778,14 +3195,7 @@ function derivePythPushOraclePDA(feedIdHex) {
2778
3195
  }
2779
3196
  const feedId = new Uint8Array(32);
2780
3197
  for (let i = 0; i < 32; i++) {
2781
- const hexPair = normalized.substring(i * 2, i * 2 + 2);
2782
- const byte = parseInt(hexPair, 16);
2783
- if (Number.isNaN(byte)) {
2784
- throw new Error(
2785
- `derivePythPushOraclePDA: failed to parse hex byte at position ${i}: "${hexPair}"`
2786
- );
2787
- }
2788
- feedId[i] = byte;
3198
+ feedId[i] = parseInt(normalized.substring(i * 2, i * 2 + 2), 16);
2789
3199
  }
2790
3200
  const shardBuf = new Uint8Array(2);
2791
3201
  return PublicKey4.findProgramAddressSync(
@@ -2817,9 +3227,7 @@ import { PublicKey as PublicKey6 } from "@solana/web3.js";
2817
3227
  // src/solana/static-markets.ts
2818
3228
  import { PublicKey as PublicKey5 } from "@solana/web3.js";
2819
3229
  var MAINNET_MARKETS = [
2820
- // Populated at mainnet launch currently empty.
2821
- // To add entries:
2822
- // { slabAddress: "ABC123...", symbol: "SOL-PERP", name: "SOL Perpetual" },
3230
+ { slabAddress: "7psyeWRts4pRX2cyAWD1NH87bR9ugXP7pe6ARgfG79Do", symbol: "SOL-PERP", name: "SOL/USDC Perpetual" }
2823
3231
  ];
2824
3232
  var DEVNET_MARKETS = [
2825
3233
  // Populated from prior discoverMarkets() runs on devnet.
@@ -2987,6 +3395,8 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
2987
3395
  fundingIndexQpbE6: readI128LE2(data, base + 112),
2988
3396
  lastFundingSlot: readU64LE2(data, base + 128),
2989
3397
  fundingRateBpsPerSlotLast: readI64LE2(data, base + 136),
3398
+ fundingRateE9: 0n,
3399
+ marketMode: null,
2990
3400
  lastCrankSlot: readU64LE2(data, base + 144),
2991
3401
  maxCrankStalenessSlots: readU64LE2(data, base + 152),
2992
3402
  totalOpenInterest: readU128LE2(data, base + 160),
@@ -2994,6 +3404,7 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
2994
3404
  shortOi: 0n,
2995
3405
  cTot: readU128LE2(data, base + 176),
2996
3406
  pnlPosTot: readU128LE2(data, base + 192),
3407
+ pnlMaturedPosTot: 0n,
2997
3408
  liqCursor: readU16LE2(data, base + 208),
2998
3409
  gcCursor: readU16LE2(data, base + 210),
2999
3410
  lastSweepStartSlot: readU64LE2(data, base + 216),
@@ -3029,6 +3440,8 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3029
3440
  fundingIndexQpbE6: readI128LE2(data, base + 360),
3030
3441
  lastFundingSlot: readU64LE2(data, base + 376),
3031
3442
  fundingRateBpsPerSlotLast: readI64LE2(data, base + 384),
3443
+ fundingRateE9: 0n,
3444
+ marketMode: null,
3032
3445
  lastCrankSlot: readU64LE2(data, base + 392),
3033
3446
  maxCrankStalenessSlots: readU64LE2(data, base + 400),
3034
3447
  totalOpenInterest: readU128LE2(data, base + 408),
@@ -3038,6 +3451,7 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3038
3451
  // V2 has no short_oi
3039
3452
  cTot: readU128LE2(data, base + 424),
3040
3453
  pnlPosTot: readU128LE2(data, base + 440),
3454
+ pnlMaturedPosTot: 0n,
3041
3455
  liqCursor: readU16LE2(data, base + 456),
3042
3456
  gcCursor: readU16LE2(data, base + 458),
3043
3457
  lastSweepStartSlot: readU64LE2(data, base + 464),
@@ -3075,6 +3489,8 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3075
3489
  fundingIndexQpbE6: readI128LE2(data, base + l.engineFundingIndexOff),
3076
3490
  lastFundingSlot: readU64LE2(data, base + l.engineLastFundingSlotOff),
3077
3491
  fundingRateBpsPerSlotLast: readI64LE2(data, base + l.engineFundingRateBpsOff),
3492
+ fundingRateE9: 0n,
3493
+ marketMode: null,
3078
3494
  lastCrankSlot: readU64LE2(data, base + l.engineLastCrankSlotOff),
3079
3495
  maxCrankStalenessSlots: readU64LE2(data, base + l.engineMaxCrankStalenessOff),
3080
3496
  totalOpenInterest: readU128LE2(data, base + l.engineTotalOiOff),
@@ -3082,6 +3498,7 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3082
3498
  shortOi: l.engineShortOiOff >= 0 ? readU128LE2(data, base + l.engineShortOiOff) : 0n,
3083
3499
  cTot: readU128LE2(data, base + l.engineCTotOff),
3084
3500
  pnlPosTot: readU128LE2(data, base + l.enginePnlPosTotOff),
3501
+ pnlMaturedPosTot: 0n,
3085
3502
  liqCursor: readU16LE2(data, base + l.engineLiqCursorOff),
3086
3503
  gcCursor: readU16LE2(data, base + l.engineGcCursorOff),
3087
3504
  lastSweepStartSlot: readU64LE2(data, base + l.engineLastSweepStartOff),
@@ -3115,6 +3532,8 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3115
3532
  fundingIndexQpbE6: readI128LE2(data, base + 368),
3116
3533
  lastFundingSlot: readU64LE2(data, base + 384),
3117
3534
  fundingRateBpsPerSlotLast: readI64LE2(data, base + 392),
3535
+ fundingRateE9: 0n,
3536
+ marketMode: null,
3118
3537
  lastCrankSlot: readU64LE2(data, base + 424),
3119
3538
  maxCrankStalenessSlots: readU64LE2(data, base + 408),
3120
3539
  totalOpenInterest: readU128LE2(data, base + 416),
@@ -3122,6 +3541,7 @@ function parseEngineLight(data, layout, maxAccounts = 4096) {
3122
3541
  shortOi: readU128LE2(data, base + 448),
3123
3542
  cTot: readU128LE2(data, base + 464),
3124
3543
  pnlPosTot: readU128LE2(data, base + 480),
3544
+ pnlMaturedPosTot: 0n,
3125
3545
  liqCursor: readU16LE2(data, base + 496),
3126
3546
  gcCursor: readU16LE2(data, base + 498),
3127
3547
  lastSweepStartSlot: readU64LE2(data, base + 504),
@@ -3587,7 +4007,9 @@ function computeRaydiumClmmPriceE6(data) {
3587
4007
  }
3588
4008
  const sqrtPriceX64 = readU128LE3(dv3, 253);
3589
4009
  if (sqrtPriceX64 === 0n) return 0n;
3590
- const priceE6Raw = sqrtPriceX64 * sqrtPriceX64 * 1000000n >> 128n;
4010
+ const scaledSqrt = sqrtPriceX64 * 1000000n;
4011
+ const term = scaledSqrt >> 64n;
4012
+ const priceE6Raw = term * sqrtPriceX64 >> 64n;
3591
4013
  const decimalDiff = 6 + decimals0 - decimals1;
3592
4014
  const adjustedDiff = decimalDiff - 6;
3593
4015
  if (adjustedDiff >= 0) {
@@ -3628,26 +4050,13 @@ function computeMeteoraDlmmPriceE6(data) {
3628
4050
  `Meteora DLMM: |activeId| ${Math.abs(activeId)} exceeds max ${MAX_ACTIVE_ID_ABS}`
3629
4051
  );
3630
4052
  }
3631
- const MAX_ABS_BIN_ID = 5e5;
3632
- if (activeId > MAX_ABS_BIN_ID || activeId < -MAX_ABS_BIN_ID) {
3633
- throw new Error(
3634
- `Meteora DLMM: activeId ${activeId} exceeds safe range (\xB1${MAX_ABS_BIN_ID})`
3635
- );
3636
- }
3637
4053
  const SCALE = 1000000000000000000n;
3638
4054
  const base = SCALE + BigInt(binStep) * SCALE / 10000n;
3639
4055
  const isNeg = activeId < 0;
3640
4056
  let exp = isNeg ? BigInt(-activeId) : BigInt(activeId);
3641
4057
  let result = SCALE;
3642
4058
  let b = base;
3643
- let iterations = 0;
3644
- const MAX_ITERATIONS = 25;
3645
4059
  while (exp > 0n) {
3646
- if (iterations++ >= MAX_ITERATIONS) {
3647
- throw new Error(
3648
- `Meteora DLMM: exponentiation loop exceeded ${MAX_ITERATIONS} iterations (activeId=${activeId})`
3649
- );
3650
- }
3651
4060
  if (exp & 1n) {
3652
4061
  result = result * b / SCALE;
3653
4062
  }
@@ -3678,7 +4087,6 @@ function readU128LE3(dv3, offset) {
3678
4087
  var CHAINLINK_MIN_SIZE = 224;
3679
4088
  var MAX_DECIMALS = 18;
3680
4089
  var CHAINLINK_DECIMALS_OFFSET = 138;
3681
- var CHAINLINK_TIMESTAMP_OFFSET = 168;
3682
4090
  var CHAINLINK_ANSWER_OFFSET = 216;
3683
4091
  function readU82(data, off) {
3684
4092
  return data[off];
@@ -3686,7 +4094,7 @@ function readU82(data, off) {
3686
4094
  function readBigInt64LE(data, off) {
3687
4095
  return new DataView(data.buffer, data.byteOffset, data.byteLength).getBigInt64(off, true);
3688
4096
  }
3689
- function parseChainlinkPrice(data, options) {
4097
+ function parseChainlinkPrice(data) {
3690
4098
  if (data.length < CHAINLINK_MIN_SIZE) {
3691
4099
  throw new Error(
3692
4100
  `Oracle account data too small: ${data.length} bytes (need at least ${CHAINLINK_MIN_SIZE})`
@@ -3704,18 +4112,7 @@ function parseChainlinkPrice(data, options) {
3704
4112
  `Oracle price is non-positive: ${price}`
3705
4113
  );
3706
4114
  }
3707
- const updatedAtBig = readBigInt64LE(data, CHAINLINK_TIMESTAMP_OFFSET);
3708
- const updatedAt = Number(updatedAtBig);
3709
- if (options?.maxStalenessSeconds !== void 0 && updatedAt > 0) {
3710
- const now = Math.floor(Date.now() / 1e3);
3711
- const age = now - updatedAt;
3712
- if (age > options.maxStalenessSeconds) {
3713
- throw new Error(
3714
- `Oracle price is stale: last updated ${age}s ago (max ${options.maxStalenessSeconds}s)`
3715
- );
3716
- }
3717
- }
3718
- return { price, decimals, updatedAt: updatedAt > 0 ? updatedAt : void 0 };
4115
+ return { price, decimals };
3719
4116
  }
3720
4117
  function isValidChainlinkOracle(data) {
3721
4118
  try {
@@ -3735,11 +4132,7 @@ var TOKEN_2022_PROGRAM_ID = new PublicKey8(
3735
4132
  async function detectTokenProgram(connection, mint) {
3736
4133
  const info = await connection.getAccountInfo(mint);
3737
4134
  if (!info) throw new Error(`Mint account not found: ${mint.toBase58()}`);
3738
- if (info.owner.equals(TOKEN_PROGRAM_ID3)) return TOKEN_PROGRAM_ID3;
3739
- if (info.owner.equals(TOKEN_2022_PROGRAM_ID)) return TOKEN_2022_PROGRAM_ID;
3740
- throw new Error(
3741
- `Mint ${mint.toBase58()} is owned by ${info.owner.toBase58()}, which is neither TOKEN_PROGRAM_ID nor TOKEN_2022_PROGRAM_ID`
3742
- );
4135
+ return info.owner;
3743
4136
  }
3744
4137
  function isToken2022(tokenProgramId) {
3745
4138
  return tokenProgramId.equals(TOKEN_2022_PROGRAM_ID);
@@ -3767,19 +4160,17 @@ var PROGRAM_IDS = {
3767
4160
  matcher: "GTRgyTDfrMvBubALAqtHuQwT8tbGyXid7svXZKtWfC9k"
3768
4161
  },
3769
4162
  mainnet: {
3770
- percolator: "GM8zjJ8LTBMv9xEsverh6H6wLyevgMHEJXcEzyY3rY24",
4163
+ percolator: "ESa89R5Es3rJ5mnwGybVRG1GrNt9etP11Z5V2QWD4edv",
3771
4164
  matcher: "DHP6DtwXP1yJsz8YzfoeigRFPB979gzmumkmCxDLSkUX"
3772
4165
  }
3773
4166
  };
3774
4167
  function getProgramId(network) {
3775
- if (!network) {
3776
- const override = safeEnv("PROGRAM_ID");
3777
- if (override) {
3778
- console.warn(
3779
- `[percolator-sdk] PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
3780
- );
3781
- return new PublicKey9(override);
3782
- }
4168
+ const override = safeEnv("PROGRAM_ID");
4169
+ if (override) {
4170
+ console.warn(
4171
+ `[percolator-sdk] PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
4172
+ );
4173
+ return new PublicKey9(override);
3783
4174
  }
3784
4175
  const detectedNetwork = getCurrentNetwork();
3785
4176
  const targetNetwork = network ?? detectedNetwork;
@@ -3787,14 +4178,12 @@ function getProgramId(network) {
3787
4178
  return new PublicKey9(programId);
3788
4179
  }
3789
4180
  function getMatcherProgramId(network) {
3790
- if (!network) {
3791
- const override = safeEnv("MATCHER_PROGRAM_ID");
3792
- if (override) {
3793
- console.warn(
3794
- `[percolator-sdk] MATCHER_PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
3795
- );
3796
- return new PublicKey9(override);
3797
- }
4181
+ const override = safeEnv("MATCHER_PROGRAM_ID");
4182
+ if (override) {
4183
+ console.warn(
4184
+ `[percolator-sdk] MATCHER_PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
4185
+ );
4186
+ return new PublicKey9(override);
3798
4187
  }
3799
4188
  const detectedNetwork = getCurrentNetwork();
3800
4189
  const targetNetwork = network ?? detectedNetwork;
@@ -3815,8 +4204,7 @@ function getCurrentNetwork() {
3815
4204
  // src/solana/stake.ts
3816
4205
  var STAKE_PROGRAM_IDS = {
3817
4206
  devnet: "6aJb1F9CDCVWCNYFwj8aQsVb696YnW6J1FznteHq4Q6k",
3818
- mainnet: ""
3819
- // TODO: populate once DevOps deploys percolator-stake to mainnet
4207
+ mainnet: "DC5fovFQD5SZYsetwvEqd4Wi4PFY1Yfnc669VMe6oa7F"
3820
4208
  };
3821
4209
  function getStakeProgramId(network) {
3822
4210
  const override = safeEnv("STAKE_PROGRAM_ID");
@@ -3828,7 +4216,10 @@ function getStakeProgramId(network) {
3828
4216
  }
3829
4217
  const detectedNetwork = network ?? (() => {
3830
4218
  const n = safeEnv("NEXT_PUBLIC_DEFAULT_NETWORK")?.toLowerCase() ?? safeEnv("NETWORK")?.toLowerCase() ?? "";
3831
- return n === "mainnet" || n === "mainnet-beta" ? "mainnet" : "devnet";
4219
+ if (n === "mainnet" || n === "mainnet-beta") return "mainnet";
4220
+ if (n === "devnet") return "devnet";
4221
+ if (typeof window !== "undefined") return "mainnet";
4222
+ return "devnet";
3832
4223
  })();
3833
4224
  const id = STAKE_PROGRAM_IDS[detectedNetwork];
3834
4225
  if (!id) {
@@ -3878,7 +4269,7 @@ function deriveStakeVaultAuth(pool, programId) {
3878
4269
  }
3879
4270
  function deriveDepositPda(pool, user, programId) {
3880
4271
  return PublicKey10.findProgramAddressSync(
3881
- [TEXT.encode("deposit"), pool.toBytes(), user.toBytes()],
4272
+ [TEXT.encode("stake_deposit"), pool.toBytes(), user.toBytes()],
3882
4273
  programId ?? getStakeProgramId()
3883
4274
  );
3884
4275
  }
@@ -3899,9 +4290,6 @@ function readU16LE3(data, off) {
3899
4290
  );
3900
4291
  }
3901
4292
  function u64Le(v) {
3902
- if (typeof v === "number" && !Number.isSafeInteger(v)) {
3903
- throw new Error(`u64Le: number ${v} exceeds Number.MAX_SAFE_INTEGER \u2014 use BigInt`);
3904
- }
3905
4293
  const big = BigInt(v);
3906
4294
  if (big < 0n) throw new Error(`u64Le: value must be non-negative, got ${big}`);
3907
4295
  if (big > 0xFFFFFFFFFFFFFFFFn) throw new Error(`u64Le: value exceeds u64 max`);
@@ -3910,9 +4298,6 @@ function u64Le(v) {
3910
4298
  return arr;
3911
4299
  }
3912
4300
  function u128Le(v) {
3913
- if (typeof v === "number" && !Number.isSafeInteger(v)) {
3914
- throw new Error(`u128Le: number ${v} exceeds Number.MAX_SAFE_INTEGER \u2014 use BigInt`);
3915
- }
3916
4301
  const big = BigInt(v);
3917
4302
  if (big < 0n) throw new Error(`u128Le: value must be non-negative, got ${big}`);
3918
4303
  if (big > (1n << 128n) - 1n) throw new Error(`u128Le: value exceeds u128 max`);
@@ -3923,7 +4308,7 @@ function u128Le(v) {
3923
4308
  return arr;
3924
4309
  }
3925
4310
  function u16Le(v) {
3926
- if (!Number.isInteger(v) || v < 0 || v > 65535) throw new Error(`u16Le: value must be integer in range 0..65535, got ${v}`);
4311
+ if (v < 0 || v > 65535) throw new Error(`u16Le: value out of u16 range (0..65535), got ${v}`);
3927
4312
  const arr = new Uint8Array(2);
3928
4313
  new DataView(arr.buffer).setUint16(0, v, true);
3929
4314
  return arr;
@@ -4178,9 +4563,7 @@ function computePnlPct(pnl, capital) {
4178
4563
  }
4179
4564
  function isAdlTriggered(slabData) {
4180
4565
  const layout = detectSlabLayout(slabData.length);
4181
- if (!layout) {
4182
- return false;
4183
- }
4566
+ if (!layout) return false;
4184
4567
  try {
4185
4568
  const engine = parseEngine(slabData);
4186
4569
  if (engine.pnlPosTot === 0n) return false;
@@ -4223,14 +4606,6 @@ function rankAdlPositions(slabData) {
4223
4606
  if (account.kind !== 0 /* User */) continue;
4224
4607
  if (account.positionSize === 0n) continue;
4225
4608
  const side = account.positionSize > 0n ? "long" : "short";
4226
- if (side === "long" && account.positionSize <= 0n) {
4227
- console.warn(`[fetchAdlRankedPositions] account idx=${idx}: side=long but positionSize=${account.positionSize}`);
4228
- continue;
4229
- }
4230
- if (side === "short" && account.positionSize >= 0n) {
4231
- console.warn(`[fetchAdlRankedPositions] account idx=${idx}: side=short but positionSize=${account.positionSize}`);
4232
- continue;
4233
- }
4234
4609
  const pnlPct = computePnlPct(account.pnl, account.capital);
4235
4610
  positions.push({
4236
4611
  idx,
@@ -4263,8 +4638,7 @@ function buildAdlInstruction(caller, slab, oracle, programId, targetIdx, backupO
4263
4638
  `buildAdlInstruction: targetIdx must be a non-negative integer, got ${targetIdx}`
4264
4639
  );
4265
4640
  }
4266
- const dataBytes = encodeExecuteAdl({ targetIdx });
4267
- const data = Buffer.from(dataBytes);
4641
+ const data = Buffer.from(encodeExecuteAdl({ targetIdx }));
4268
4642
  const keys = [
4269
4643
  { pubkey: caller, isSigner: true, isWritable: false },
4270
4644
  { pubkey: slab, isSigner: false, isWritable: true },
@@ -4304,11 +4678,7 @@ function parseAdlEvent(logs) {
4304
4678
  }
4305
4679
  if (tag !== ADL_EVENT_TAG) continue;
4306
4680
  try {
4307
- const targetIdxBig = BigInt(match[2]);
4308
- if (targetIdxBig < 0n || targetIdxBig > 65535n) {
4309
- continue;
4310
- }
4311
- const targetIdx = Number(targetIdxBig);
4681
+ const targetIdx = Number(BigInt(match[2]));
4312
4682
  const price = BigInt(match[3]);
4313
4683
  const closedLo = BigInt(match[4]);
4314
4684
  const closedHi = BigInt(match[5]);
@@ -4336,22 +4706,6 @@ async function fetchAdlRankings(apiBase, slab, fetchFn = fetch) {
4336
4706
  );
4337
4707
  }
4338
4708
  const json = await res.json();
4339
- if (typeof json !== "object" || json === null) {
4340
- throw new Error("fetchAdlRankings: API returned non-object response");
4341
- }
4342
- const obj = json;
4343
- if (!Array.isArray(obj.rankings)) {
4344
- throw new Error("fetchAdlRankings: API response missing rankings array");
4345
- }
4346
- for (const entry of obj.rankings) {
4347
- if (typeof entry !== "object" || entry === null) {
4348
- throw new Error("fetchAdlRankings: invalid ranking entry (not an object)");
4349
- }
4350
- const r = entry;
4351
- if (typeof r.idx !== "number" || !Number.isInteger(r.idx) || r.idx < 0) {
4352
- throw new Error(`fetchAdlRankings: invalid ranking idx: ${r.idx}`);
4353
- }
4354
- }
4355
4709
  return json;
4356
4710
  }
4357
4711
 
@@ -4873,7 +5227,7 @@ import { PublicKey as PublicKey13, Transaction as Transaction2 } from "@solana/w
4873
5227
  var LIGHTHOUSE_PROGRAM_ID = new PublicKey13(
4874
5228
  "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95"
4875
5229
  );
4876
- var LIGHTHOUSE_PROGRAM_ID_STR2 = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
5230
+ var LIGHTHOUSE_PROGRAM_ID_STR = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
4877
5231
  var LIGHTHOUSE_CONSTRAINT_ADDRESS = 6400;
4878
5232
  var LIGHTHOUSE_ERROR_CODES = /* @__PURE__ */ new Set([
4879
5233
  6e3,
@@ -4919,7 +5273,7 @@ function isLighthouseInstruction(ix) {
4919
5273
  function isLighthouseError(error) {
4920
5274
  const msg = extractErrorMessage(error);
4921
5275
  if (!msg) return false;
4922
- if (msg.includes(LIGHTHOUSE_PROGRAM_ID_STR2)) return true;
5276
+ if (msg.includes(LIGHTHOUSE_PROGRAM_ID_STR)) return true;
4923
5277
  if (/custom\s+program\s+error:\s*0x1900\b/i.test(msg)) return true;
4924
5278
  if (/"Custom"\s*:\s*6400\b/.test(msg) && /InstructionError/i.test(msg)) return true;
4925
5279
  return false;
@@ -4929,18 +5283,18 @@ function isLighthouseFailureInLogs(logs) {
4929
5283
  let insideLighthouse = false;
4930
5284
  for (const line of logs) {
4931
5285
  if (typeof line !== "string") continue;
4932
- if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} invoke`)) {
5286
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {
4933
5287
  insideLighthouse = true;
4934
5288
  continue;
4935
5289
  }
4936
- if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} success`)) {
5290
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {
4937
5291
  insideLighthouse = false;
4938
5292
  continue;
4939
5293
  }
4940
5294
  if (insideLighthouse && /failed/i.test(line)) {
4941
5295
  return true;
4942
5296
  }
4943
- if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} failed`)) {
5297
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} failed`)) {
4944
5298
  return true;
4945
5299
  }
4946
5300
  }
@@ -5025,10 +5379,16 @@ function computeLiqPrice(entryPrice, capital, positionSize, maintenanceMarginBps
5025
5379
  function computePreTradeLiqPrice(oracleE6, margin, posSize, maintBps, feeBps, direction) {
5026
5380
  if (oracleE6 === 0n || margin === 0n || posSize === 0n) return 0n;
5027
5381
  const absPos = posSize < 0n ? -posSize : posSize;
5028
- const fee = absPos * feeBps / 10000n;
5029
- const effectiveCapital = margin > fee ? margin - fee : 0n;
5030
5382
  const signedPos = direction === "long" ? absPos : -absPos;
5031
- return computeLiqPrice(oracleE6, effectiveCapital, signedPos, maintBps);
5383
+ const feeAdjust = oracleE6 * feeBps / 10000n;
5384
+ let adjustedEntry;
5385
+ if (direction === "long") {
5386
+ adjustedEntry = oracleE6 + feeAdjust;
5387
+ } else {
5388
+ const shortEntry = oracleE6 - feeAdjust;
5389
+ adjustedEntry = shortEntry > 0n ? shortEntry : 1n;
5390
+ }
5391
+ return computeLiqPrice(adjustedEntry, margin, signedPos, maintBps);
5032
5392
  }
5033
5393
  function computeTradingFee(notional, tradingFeeBps) {
5034
5394
  return notional * tradingFeeBps / 10000n;
@@ -5048,20 +5408,9 @@ function computeFeeSplit(totalFee, config) {
5048
5408
  if (config.lpBps === 0n && config.protocolBps === 0n && config.creatorBps === 0n) {
5049
5409
  return [totalFee, 0n, 0n];
5050
5410
  }
5051
- const totalBps = config.lpBps + config.protocolBps + config.creatorBps;
5052
- if (totalBps !== 10000n) {
5053
- throw new Error(
5054
- `Fee split must equal exactly 10000 bps (100%): lpBps=${config.lpBps} + protocolBps=${config.protocolBps} + creatorBps=${config.creatorBps} = ${totalBps}`
5055
- );
5056
- }
5057
5411
  const lp = totalFee * config.lpBps / 10000n;
5058
5412
  const protocol = totalFee * config.protocolBps / 10000n;
5059
5413
  const creator = totalFee - lp - protocol;
5060
- if (creator < 0n) {
5061
- throw new Error(
5062
- `Internal error: creator fee is negative (${creator}). This should not happen if lpBps + protocolBps + creatorBps <= 10000.`
5063
- );
5064
- }
5065
5414
  return [lp, protocol, creator];
5066
5415
  }
5067
5416
  function computePnlPercent(pnlTokens, capital) {
@@ -5076,17 +5425,10 @@ function computePnlPercent(pnlTokens, capital) {
5076
5425
  }
5077
5426
  function computeEstimatedEntryPrice(oracleE6, tradingFeeBps, direction) {
5078
5427
  if (oracleE6 === 0n) return 0n;
5079
- if (tradingFeeBps < 0n) {
5080
- throw new Error(`computeEstimatedEntryPrice: tradingFeeBps must be non-negative, got ${tradingFeeBps}`);
5081
- }
5082
5428
  const feeImpact = oracleE6 * tradingFeeBps / 10000n;
5083
- const result = direction === "long" ? oracleE6 + feeImpact : oracleE6 - feeImpact;
5084
- if (result <= 0n) {
5085
- throw new Error(
5086
- `computeEstimatedEntryPrice: result ${result} is non-positive (tradingFeeBps=${tradingFeeBps} too high for oracle=${oracleE6})`
5087
- );
5088
- }
5089
- return result;
5429
+ if (direction === "long") return oracleE6 + feeImpact;
5430
+ const shortEntry = oracleE6 - feeImpact;
5431
+ return shortEntry > 0n ? shortEntry : 1n;
5090
5432
  }
5091
5433
  var MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
5092
5434
  var MIN_SAFE_BIGINT = BigInt(-Number.MAX_SAFE_INTEGER);
@@ -5107,12 +5449,7 @@ function computeMaxLeverage(initialMarginBps) {
5107
5449
  if (initialMarginBps <= 0n) {
5108
5450
  throw new Error("computeMaxLeverage: initialMarginBps must be positive");
5109
5451
  }
5110
- const scaledResult = 10000n * 1000000n / initialMarginBps;
5111
- return Number(scaledResult) / 1e6;
5112
- }
5113
- function computeMaxWithdrawable(capital, pnl, reservedPnl) {
5114
- const maturedPnl = pnl - reservedPnl;
5115
- return capital + (maturedPnl > 0n ? maturedPnl : 0n);
5452
+ return Number(10000n / initialMarginBps);
5116
5453
  }
5117
5454
 
5118
5455
  // src/math/warmup.ts
@@ -5124,9 +5461,6 @@ function computeWarmupUnlockedCapital(totalCapital, currentSlot, warmupStartSlot
5124
5461
  return totalCapital * elapsed / warmupPeriodSlots;
5125
5462
  }
5126
5463
  function computeWarmupLeverageCap(initialMarginBps, totalCapital, currentSlot, warmupStartSlot, warmupPeriodSlots) {
5127
- if (initialMarginBps <= 0n) {
5128
- throw new Error("computeWarmupLeverageCap: initialMarginBps must be positive");
5129
- }
5130
5464
  const maxLev = computeMaxLeverage(initialMarginBps);
5131
5465
  if (warmupPeriodSlots === 0n || warmupStartSlot === 0n) return maxLev;
5132
5466
  if (totalCapital <= 0n) return 1;
@@ -5137,14 +5471,7 @@ function computeWarmupLeverageCap(initialMarginBps, totalCapital, currentSlot, w
5137
5471
  warmupPeriodSlots
5138
5472
  );
5139
5473
  if (unlocked <= 0n) return 1;
5140
- const scaledResult = BigInt(maxLev) * unlocked / totalCapital;
5141
- if (scaledResult > BigInt(Number.MAX_SAFE_INTEGER)) {
5142
- console.warn(
5143
- `[computeWarmupLeverageCap] Warning: effective leverage ${scaledResult} exceeds MAX_SAFE_INTEGER, returning MAX_SAFE_INTEGER as a safety bound`
5144
- );
5145
- return Number.MAX_SAFE_INTEGER;
5146
- }
5147
- const effectiveLev = Number(scaledResult);
5474
+ const effectiveLev = Number(BigInt(maxLev) * unlocked / totalCapital);
5148
5475
  return Math.max(1, effectiveLev);
5149
5476
  }
5150
5477
  function computeWarmupMaxPositionSize(initialMarginBps, totalCapital, currentSlot, warmupStartSlot, warmupPeriodSlots) {
@@ -5157,41 +5484,10 @@ function computeWarmupMaxPositionSize(initialMarginBps, totalCapital, currentSlo
5157
5484
  );
5158
5485
  return unlocked * BigInt(maxLev);
5159
5486
  }
5160
- function computeWarmupProgress(currentSlot, warmupStartedAtSlot, warmupPeriodSlots, pnl, reservedPnl) {
5161
- if (warmupPeriodSlots === 0n || warmupStartedAtSlot === 0n) {
5162
- return {
5163
- maturedPnl: pnl > 0n ? pnl : 0n,
5164
- reservedPnl: 0n,
5165
- progressBps: 10000n,
5166
- // 100%
5167
- slotsRemaining: 0n
5168
- };
5169
- }
5170
- const elapsed = currentSlot >= warmupStartedAtSlot ? currentSlot - warmupStartedAtSlot : 0n;
5171
- if (elapsed >= warmupPeriodSlots) {
5172
- return {
5173
- maturedPnl: pnl > 0n ? pnl : 0n,
5174
- reservedPnl: 0n,
5175
- progressBps: 10000n,
5176
- // 100%
5177
- slotsRemaining: 0n
5178
- };
5179
- }
5180
- const progressBps = elapsed * 10000n / warmupPeriodSlots;
5181
- const slotsRemaining = warmupPeriodSlots - elapsed;
5182
- const maturedPnl = pnl > 0n ? pnl * progressBps / 10000n : 0n;
5183
- const locked = reservedPnl > 0n ? reservedPnl : 0n;
5184
- return {
5185
- maturedPnl,
5186
- reservedPnl: locked,
5187
- progressBps,
5188
- slotsRemaining
5189
- };
5190
- }
5191
5487
 
5192
5488
  // src/validation.ts
5193
5489
  import { PublicKey as PublicKey14 } from "@solana/web3.js";
5194
- var U16_MAX = 65535;
5490
+ var U16_MAX2 = 65535;
5195
5491
  var U64_MAX = BigInt("18446744073709551615");
5196
5492
  var I64_MIN = BigInt("-9223372036854775808");
5197
5493
  var I64_MAX = BigInt("9223372036854775807");
@@ -5231,26 +5527,24 @@ function validatePublicKey(value, field) {
5231
5527
  function validateIndex(value, field) {
5232
5528
  const t = requireDecimalUIntString(value, field);
5233
5529
  const bi = BigInt(t);
5234
- if (bi > BigInt(U16_MAX)) {
5530
+ if (bi > BigInt(U16_MAX2)) {
5235
5531
  throw new ValidationError(
5236
5532
  field,
5237
- `must be <= ${U16_MAX} (u16 max), got ${t}`
5533
+ `must be <= ${U16_MAX2} (u16 max), got ${t}`
5238
5534
  );
5239
5535
  }
5240
- if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5241
- throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);
5242
- }
5243
5536
  return Number(bi);
5244
5537
  }
5245
5538
  function validateAmount(value, field) {
5246
- const t = value.trim();
5247
- if (!/^(0|[1-9]\d*)$/.test(t)) {
5539
+ let num;
5540
+ try {
5541
+ num = BigInt(value);
5542
+ } catch {
5248
5543
  throw new ValidationError(
5249
5544
  field,
5250
- `"${value}" is not a valid non-negative integer. Use decimal digits only.`
5545
+ `"${value}" is not a valid number. Use decimal digits only.`
5251
5546
  );
5252
5547
  }
5253
- const num = BigInt(t);
5254
5548
  if (num < 0n) {
5255
5549
  throw new ValidationError(field, `must be non-negative, got ${num}`);
5256
5550
  }
@@ -5263,14 +5557,15 @@ function validateAmount(value, field) {
5263
5557
  return num;
5264
5558
  }
5265
5559
  function validateU128(value, field) {
5266
- const t = value.trim();
5267
- if (!/^(0|[1-9]\d*)$/.test(t)) {
5560
+ let num;
5561
+ try {
5562
+ num = BigInt(value);
5563
+ } catch {
5268
5564
  throw new ValidationError(
5269
5565
  field,
5270
- `"${value}" is not a valid non-negative integer. Use decimal digits only.`
5566
+ `"${value}" is not a valid number. Use decimal digits only.`
5271
5567
  );
5272
5568
  }
5273
- const num = BigInt(t);
5274
5569
  if (num < 0n) {
5275
5570
  throw new ValidationError(field, `must be non-negative, got ${num}`);
5276
5571
  }
@@ -5283,14 +5578,15 @@ function validateU128(value, field) {
5283
5578
  return num;
5284
5579
  }
5285
5580
  function validateI64(value, field) {
5286
- const t = value.trim();
5287
- if (!/^-?(0|[1-9]\d*)$/.test(t)) {
5581
+ let num;
5582
+ try {
5583
+ num = BigInt(value);
5584
+ } catch {
5288
5585
  throw new ValidationError(
5289
5586
  field,
5290
- `"${value}" is not a valid integer. Use decimal digits only, with optional leading minus.`
5587
+ `"${value}" is not a valid number. Use decimal digits only, with optional leading minus.`
5291
5588
  );
5292
5589
  }
5293
- const num = BigInt(t);
5294
5590
  if (num < I64_MIN) {
5295
5591
  throw new ValidationError(
5296
5592
  field,
@@ -5306,14 +5602,15 @@ function validateI64(value, field) {
5306
5602
  return num;
5307
5603
  }
5308
5604
  function validateI128(value, field) {
5309
- const t = value.trim();
5310
- if (!/^-?(0|[1-9]\d*)$/.test(t)) {
5605
+ let num;
5606
+ try {
5607
+ num = BigInt(value);
5608
+ } catch {
5311
5609
  throw new ValidationError(
5312
5610
  field,
5313
- `"${value}" is not a valid integer. Use decimal digits only, with optional leading minus.`
5611
+ `"${value}" is not a valid number. Use decimal digits only, with optional leading minus.`
5314
5612
  );
5315
5613
  }
5316
- const num = BigInt(t);
5317
5614
  if (num < I128_MIN) {
5318
5615
  throw new ValidationError(
5319
5616
  field,
@@ -5337,9 +5634,6 @@ function validateBps(value, field) {
5337
5634
  `must be <= 10000 (100%), got ${t}`
5338
5635
  );
5339
5636
  }
5340
- if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5341
- throw new ValidationError(field, `internal error: bps value exceeds MAX_SAFE_INTEGER`);
5342
- }
5343
5637
  return Number(bi);
5344
5638
  }
5345
5639
  function validateU64(value, field) {
@@ -5348,15 +5642,12 @@ function validateU64(value, field) {
5348
5642
  function validateU16(value, field) {
5349
5643
  const t = requireDecimalUIntString(value, field);
5350
5644
  const bi = BigInt(t);
5351
- if (bi > BigInt(U16_MAX)) {
5645
+ if (bi > BigInt(U16_MAX2)) {
5352
5646
  throw new ValidationError(
5353
5647
  field,
5354
- `must be <= ${U16_MAX} (u16 max), got ${t}`
5648
+ `must be <= ${U16_MAX2} (u16 max), got ${t}`
5355
5649
  );
5356
5650
  }
5357
- if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5358
- throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);
5359
- }
5360
5651
  return Number(bi);
5361
5652
  }
5362
5653
 
@@ -5407,9 +5698,7 @@ function parseDexScreenerPairs(json) {
5407
5698
  else if (liquidity > 1e4) confidence = 60;
5408
5699
  else if (liquidity > 1e3) confidence = 45;
5409
5700
  const priceUsd = pair.priceUsd;
5410
- const rawPrice = typeof priceUsd === "string" || typeof priceUsd === "number" ? parseFloat(String(priceUsd)) : NaN;
5411
- if (!Number.isFinite(rawPrice) || rawPrice <= 0) continue;
5412
- const price = rawPrice;
5701
+ const price = typeof priceUsd === "string" || typeof priceUsd === "number" ? parseFloat(String(priceUsd)) || 0 : 0;
5413
5702
  let baseSym = "?";
5414
5703
  let quoteSym = "?";
5415
5704
  if (isRecord(pair.baseToken) && typeof pair.baseToken.symbol === "string") {
@@ -5440,8 +5729,8 @@ function parseJupiterMintEntry(json, mint) {
5440
5729
  if (!isRecord(row)) return null;
5441
5730
  const rawPrice = row.price;
5442
5731
  if (rawPrice === void 0 || rawPrice === null) return null;
5443
- const price = parseFloat(String(rawPrice));
5444
- if (!Number.isFinite(price) || price <= 0) return null;
5732
+ const price = parseFloat(String(rawPrice)) || 0;
5733
+ if (price <= 0) return null;
5445
5734
  let mintSymbol = "?";
5446
5735
  if (typeof row.mintSymbol === "string") mintSymbol = row.mintSymbol;
5447
5736
  return { price, mintSymbol };
@@ -5507,17 +5796,10 @@ async function fetchDexSources(mint, signal) {
5507
5796
  headers: { "User-Agent": "percolator/1.0" }
5508
5797
  }
5509
5798
  );
5510
- if (!resp.ok) {
5511
- console.debug(`[fetchDexSources] HTTP ${resp.status} for mint ${mint}`);
5512
- return [];
5513
- }
5799
+ if (!resp.ok) return [];
5514
5800
  const json = await resp.json();
5515
5801
  return parseDexScreenerPairs(json);
5516
- } catch (err) {
5517
- console.warn(
5518
- `[fetchDexSources] Error fetching DexScreener data for mint ${mint}:`,
5519
- err instanceof Error ? err.message : String(err)
5520
- );
5802
+ } catch {
5521
5803
  return [];
5522
5804
  }
5523
5805
  }
@@ -5528,7 +5810,7 @@ function lookupPythSource(mint) {
5528
5810
  type: "pyth",
5529
5811
  address: entry.feedId,
5530
5812
  pairLabel: `${entry.symbol} / USD (Pyth)`,
5531
- liquidity: Number.MAX_SAFE_INTEGER,
5813
+ liquidity: Infinity,
5532
5814
  // Pyth is considered deep liquidity
5533
5815
  price: 0,
5534
5816
  // We don't fetch live price here; caller can enrich
@@ -5545,16 +5827,10 @@ async function fetchJupiterSource(mint, signal) {
5545
5827
  headers: { "User-Agent": "percolator/1.0" }
5546
5828
  }
5547
5829
  );
5548
- if (!resp.ok) {
5549
- console.debug(`[fetchJupiterSource] HTTP ${resp.status} for mint ${mint}`);
5550
- return null;
5551
- }
5830
+ if (!resp.ok) return null;
5552
5831
  const json = await resp.json();
5553
5832
  const row = parseJupiterMintEntry(json, mint);
5554
- if (!row) {
5555
- console.debug(`[fetchJupiterSource] No price data from Jupiter for mint ${mint}`);
5556
- return null;
5557
- }
5833
+ if (!row) return null;
5558
5834
  return {
5559
5835
  type: "jupiter",
5560
5836
  address: mint,
@@ -5565,39 +5841,23 @@ async function fetchJupiterSource(mint, signal) {
5565
5841
  confidence: 40
5566
5842
  // Fallback — lower confidence
5567
5843
  };
5568
- } catch (err) {
5569
- console.warn(
5570
- `[fetchJupiterSource] Error fetching Jupiter data for mint ${mint}:`,
5571
- err instanceof Error ? err.message : String(err)
5572
- );
5844
+ } catch {
5573
5845
  return null;
5574
5846
  }
5575
5847
  }
5576
5848
  async function resolvePrice(mint, signal, options) {
5577
5849
  const timeoutMs = options?.timeoutMs ?? DEFAULT_RESOLVE_TIMEOUT_MS;
5578
5850
  const timeoutSignal = AbortSignal.timeout(timeoutMs);
5579
- const effectiveSignal2 = signal ? combineAbortSignals([signal, timeoutSignal]) : timeoutSignal;
5851
+ const combinedSignal = signal ? combineAbortSignals([signal, timeoutSignal]) : timeoutSignal;
5580
5852
  const [dexSources, jupiterSource] = await Promise.all([
5581
- fetchDexSources(mint, effectiveSignal2),
5582
- fetchJupiterSource(mint, effectiveSignal2)
5853
+ fetchDexSources(mint, combinedSignal),
5854
+ fetchJupiterSource(mint, combinedSignal)
5583
5855
  ]);
5584
5856
  const pythSource = lookupPythSource(mint);
5585
5857
  const allSources = [];
5586
5858
  if (pythSource) {
5587
- const dexPrice = dexSources[0]?.price ?? 0;
5588
- const jupPrice = jupiterSource?.price ?? 0;
5589
- if (dexPrice > 0 && jupPrice > 0) {
5590
- const mid = (dexPrice + jupPrice) / 2;
5591
- const deviation = Math.abs(dexPrice - jupPrice) / mid;
5592
- if (deviation > 0.5) {
5593
- pythSource.price = 0;
5594
- pythSource.confidence = 20;
5595
- } else {
5596
- pythSource.price = mid;
5597
- }
5598
- } else {
5599
- pythSource.price = dexPrice || jupPrice || 0;
5600
- }
5859
+ const refPrice = dexSources[0]?.price || jupiterSource?.price || 0;
5860
+ pythSource.price = refPrice;
5601
5861
  allSources.push(pythSource);
5602
5862
  }
5603
5863
  allSources.push(...dexSources);
@@ -5640,6 +5900,7 @@ export {
5640
5900
  ACCOUNTS_QUEUE_WITHDRAWAL,
5641
5901
  ACCOUNTS_RECLAIM_SLAB_RENT,
5642
5902
  ACCOUNTS_RESOLVE_MARKET,
5903
+ ACCOUNTS_SET_DEX_POOL,
5643
5904
  ACCOUNTS_SET_INSURANCE_ISOLATION,
5644
5905
  ACCOUNTS_SET_MAINTENANCE_FEE,
5645
5906
  ACCOUNTS_SET_OI_IMBALANCE_HARD_BLOCK,
@@ -5649,7 +5910,6 @@ export {
5649
5910
  ACCOUNTS_SET_RISK_THRESHOLD,
5650
5911
  ACCOUNTS_SET_WALLET_CAP,
5651
5912
  ACCOUNTS_TOPUP_INSURANCE,
5652
- ACCOUNTS_TOPUP_KEEPER_FUND,
5653
5913
  ACCOUNTS_TRADE_CPI,
5654
5914
  ACCOUNTS_TRADE_NOCPI,
5655
5915
  ACCOUNTS_TRANSFER_POSITION_OWNERSHIP,
@@ -5663,7 +5923,6 @@ export {
5663
5923
  CHAINLINK_ANSWER_OFFSET,
5664
5924
  CHAINLINK_DECIMALS_OFFSET,
5665
5925
  CHAINLINK_MIN_SIZE,
5666
- CHAINLINK_TIMESTAMP_OFFSET,
5667
5926
  CREATOR_LOCK_SEED,
5668
5927
  CTX_VAMM_OFFSET,
5669
5928
  DEFAULT_OI_RAMP_SLOTS,
@@ -5673,7 +5932,7 @@ export {
5673
5932
  LIGHTHOUSE_CONSTRAINT_ADDRESS,
5674
5933
  LIGHTHOUSE_ERROR_CODES,
5675
5934
  LIGHTHOUSE_PROGRAM_ID,
5676
- LIGHTHOUSE_PROGRAM_ID_STR2 as LIGHTHOUSE_PROGRAM_ID_STR,
5935
+ LIGHTHOUSE_PROGRAM_ID_STR,
5677
5936
  LIGHTHOUSE_USER_MESSAGE,
5678
5937
  MARK_PRICE_EMA_ALPHA_E6,
5679
5938
  MARK_PRICE_EMA_WINDOW_SLOTS,
@@ -5701,6 +5960,7 @@ export {
5701
5960
  SLAB_TIERS_V0,
5702
5961
  SLAB_TIERS_V1,
5703
5962
  SLAB_TIERS_V12_1,
5963
+ SLAB_TIERS_V12_15,
5704
5964
  SLAB_TIERS_V1D,
5705
5965
  SLAB_TIERS_V1D_LEGACY,
5706
5966
  SLAB_TIERS_V1M,
@@ -5738,7 +5998,6 @@ export {
5738
5998
  computeLiqPrice,
5739
5999
  computeMarkPnl,
5740
6000
  computeMaxLeverage,
5741
- computeMaxWithdrawable,
5742
6001
  computePnlPercent,
5743
6002
  computePreTradeLiqPrice,
5744
6003
  computeRequiredMargin,
@@ -5746,7 +6005,6 @@ export {
5746
6005
  computeVammQuote,
5747
6006
  computeWarmupLeverageCap,
5748
6007
  computeWarmupMaxPositionSize,
5749
- computeWarmupProgress,
5750
6008
  computeWarmupUnlockedCapital,
5751
6009
  concatBytes,
5752
6010
  countLighthouseInstructions,
@@ -5756,7 +6014,6 @@ export {
5756
6014
  deriveCreatorLockPda,
5757
6015
  deriveDepositPda,
5758
6016
  deriveInsuranceLpMint,
5759
- deriveKeeperFund,
5760
6017
  deriveLpPda,
5761
6018
  derivePythPriceUpdateAccount,
5762
6019
  derivePythPushOraclePDA,
@@ -5783,19 +6040,25 @@ export {
5783
6040
  encodeAdvanceEpoch,
5784
6041
  encodeAdvanceOraclePhase,
5785
6042
  encodeAllocateMarket,
6043
+ encodeAttestCrossMargin,
5786
6044
  encodeAuditCrank,
5787
6045
  encodeBurnPositionNft,
5788
6046
  encodeCancelQueuedWithdrawal,
6047
+ encodeChallengeSettlement,
5789
6048
  encodeClaimEpochWithdrawal,
5790
6049
  encodeClaimQueuedWithdrawal,
5791
6050
  encodeClearPendingSettlement,
5792
6051
  encodeCloseAccount,
6052
+ encodeCloseOrphanSlab,
5793
6053
  encodeCloseSlab,
5794
6054
  encodeCloseStaleSlabs,
5795
6055
  encodeCreateInsuranceMint,
6056
+ encodeCreateLpVault,
5796
6057
  encodeDepositCollateral,
5797
6058
  encodeDepositInsuranceLP,
6059
+ encodeDepositLpCollateral,
5798
6060
  encodeExecuteAdl,
6061
+ encodeForceCloseResolved,
5799
6062
  encodeFundMarketInsurance,
5800
6063
  encodeInitLP,
5801
6064
  encodeInitMarket,
@@ -5804,6 +6067,8 @@ export {
5804
6067
  encodeInitUser,
5805
6068
  encodeKeeperCrank,
5806
6069
  encodeLiquidateAtOracle,
6070
+ encodeLpVaultCrankFees,
6071
+ encodeLpVaultDeposit,
5807
6072
  encodeLpVaultWithdraw,
5808
6073
  encodeMintPositionNft,
5809
6074
  encodePauseMarket,
@@ -5812,9 +6077,15 @@ export {
5812
6077
  encodeQueueWithdrawalSV,
5813
6078
  encodeReclaimSlabRent,
5814
6079
  encodeRenounceAdmin,
6080
+ encodeRescueOrphanVault,
6081
+ encodeResolveDispute,
5815
6082
  encodeResolveMarket,
6083
+ encodeResolvePermissionless,
6084
+ encodeSetDexPool,
5816
6085
  encodeSetInsuranceIsolation,
6086
+ encodeSetInsuranceWithdrawPolicy,
5817
6087
  encodeSetMaintenanceFee,
6088
+ encodeSetOffsetPair,
5818
6089
  encodeSetOiImbalanceHardBlock,
5819
6090
  encodeSetOracleAuthority,
5820
6091
  encodeSetOraclePriceCap,
@@ -5841,7 +6112,6 @@ export {
5841
6112
  encodeStakeUpdateConfig,
5842
6113
  encodeStakeWithdraw,
5843
6114
  encodeTopUpInsurance,
5844
- encodeTopUpKeeperFund,
5845
6115
  encodeTradeCpi,
5846
6116
  encodeTradeCpiV2,
5847
6117
  encodeTradeNoCpi,
@@ -5856,6 +6126,8 @@ export {
5856
6126
  encodeWithdrawCollateral,
5857
6127
  encodeWithdrawInsurance,
5858
6128
  encodeWithdrawInsuranceLP,
6129
+ encodeWithdrawInsuranceLimited,
6130
+ encodeWithdrawLpCollateral,
5859
6131
  fetchAdlRankedPositions,
5860
6132
  fetchAdlRankings,
5861
6133
  fetchSlab,
@@ -5875,7 +6147,6 @@ export {
5875
6147
  initPoolAccounts,
5876
6148
  isAccountUsed,
5877
6149
  isAdlTriggered,
5878
- isAnchorErrorCode,
5879
6150
  isLighthouseError,
5880
6151
  isLighthouseFailureInLogs,
5881
6152
  isLighthouseInstruction,