@percolatorct/sdk 1.0.0-beta.20 → 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);
@@ -131,13 +134,8 @@ var IX_TAG = {
131
134
  ReclaimEmptyAccount: 25,
132
135
  SettleAccount: 26,
133
136
  // Tags 27-28: on-chain = DepositFeeCredits/ConvertReleasedPnl.
134
- // Legacy aliases (PauseMarket/UnpauseMarket) kept — those instructions don't exist on-chain.
135
137
  DepositFeeCredits: 27,
136
- /** @deprecated No on-chain PauseMarket instruction */
137
- PauseMarket: 27,
138
138
  ConvertReleasedPnl: 28,
139
- /** @deprecated No on-chain UnpauseMarket instruction */
140
- UnpauseMarket: 28,
141
139
  // Tags 29-30: on-chain = ResolvePermissionless/ForceCloseResolved.
142
140
  ResolvePermissionless: 29,
143
141
  /** @deprecated Use ResolvePermissionless */
@@ -224,7 +222,12 @@ var IX_TAG = {
224
222
  /** PERC-SetDexPool: Pin admin-approved DEX pool address for a HYPERP market (admin). */
225
223
  SetDexPool: 74,
226
224
  /** CPI to the matcher program to initialize a matcher context account for an LP slot. Admin-only. */
227
- 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)
228
231
  };
229
232
  Object.freeze(IX_TAG);
230
233
  var HEX_RE = /^[0-9a-fA-F]{64}$/;
@@ -247,7 +250,7 @@ function encodeFeedId(feedId) {
247
250
  }
248
251
  return bytes;
249
252
  }
250
- var INIT_MARKET_DATA_LEN = 360;
253
+ var INIT_MARKET_DATA_LEN = 352;
251
254
  function encodeInitMarket(args) {
252
255
  const hMin = args.hMin ?? args.warmupPeriodSlots ?? 0n;
253
256
  const hMax = args.hMax ?? args.warmupPeriodSlots ?? 0n;
@@ -265,25 +268,30 @@ function encodeInitMarket(args) {
265
268
  encU128(args.maxMaintenanceFeePerSlot ?? 0n),
266
269
  encU128(args.maxInsuranceFloor ?? 0n),
267
270
  encU64(args.minOraclePriceCap ?? 0n),
268
- // RiskParams block (16 fields h_min replaces warmup_period_slots, h_max added at end)
271
+ // RiskParams wire formatmust 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).
269
274
  encU64(hMin),
270
275
  encU64(args.maintenanceMarginBps),
271
276
  encU64(args.initialMarginBps),
272
277
  encU64(args.tradingFeeBps),
273
278
  encU64(args.maxAccounts),
274
279
  encU128(args.newAccountFee),
275
- encU128(args.riskReductionThreshold),
276
- 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
277
286
  encU64(args.maxCrankStalenessSlots),
278
287
  encU64(args.liquidationFeeBps),
279
288
  encU128(args.liquidationFeeCap),
280
- encU64(args.liquidationBufferBps),
289
+ encU64(args.liquidationBufferBps ?? 0n),
290
+ // wire slot: read as resolve_price_deviation_bps by program
281
291
  encU128(args.minLiquidationAbs),
282
292
  encU128(args.minInitialDeposit),
283
293
  encU128(args.minNonzeroMmReq),
284
- encU128(args.minNonzeroImReq),
285
- encU64(hMax)
286
- // h_max — new in v12.15, appended after minNonzeroImReq
294
+ encU128(args.minNonzeroImReq)
287
295
  );
288
296
  if (data.length !== INIT_MARKET_DATA_LEN) {
289
297
  throw new Error(
@@ -720,6 +728,15 @@ function encodeCloseOrphanSlab() {
720
728
  function encodeSetDexPool(args) {
721
729
  return concatBytes(encU8(IX_TAG.SetDexPool), encPubkey(args.pool));
722
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
+ }
723
740
 
724
741
  // src/abi/accounts.ts
725
742
  import {
@@ -744,7 +761,8 @@ var ACCOUNTS_INIT_USER = [
744
761
  { name: "slab", signer: false, writable: true },
745
762
  { name: "userAta", signer: false, writable: true },
746
763
  { name: "vault", signer: false, writable: true },
747
- { name: "tokenProgram", signer: false, writable: false }
764
+ { name: "tokenProgram", signer: false, writable: false },
765
+ { name: "clock", signer: false, writable: false }
748
766
  ];
749
767
  var ACCOUNTS_INIT_LP = [
750
768
  { name: "user", signer: true, writable: true },
@@ -811,6 +829,7 @@ var ACCOUNTS_TRADE_CPI = [
811
829
  { name: "lpOwner", signer: false, writable: false },
812
830
  // LP delegated to matcher - no signature needed
813
831
  { name: "slab", signer: false, writable: true },
832
+ { name: "clock", signer: false, writable: false },
814
833
  { name: "oracle", signer: false, writable: false },
815
834
  { name: "matcherProg", signer: false, writable: false },
816
835
  { name: "matcherCtx", signer: false, writable: true },
@@ -894,6 +913,37 @@ function buildAccountMetas(spec, keys) {
894
913
  isWritable: s.writable
895
914
  }));
896
915
  }
916
+ var ACCOUNTS_CREATE_INSURANCE_MINT = [
917
+ { name: "admin", signer: true, writable: false },
918
+ { name: "slab", signer: false, writable: false },
919
+ { name: "insLpMint", signer: false, writable: true },
920
+ { name: "vaultAuthority", signer: false, writable: false },
921
+ { name: "collateralMint", signer: false, writable: false },
922
+ { name: "systemProgram", signer: false, writable: false },
923
+ { name: "tokenProgram", signer: false, writable: false },
924
+ { name: "rent", signer: false, writable: false },
925
+ { name: "payer", signer: true, writable: true }
926
+ ];
927
+ var ACCOUNTS_DEPOSIT_INSURANCE_LP = [
928
+ { name: "depositor", signer: true, writable: false },
929
+ { name: "slab", signer: false, writable: true },
930
+ { name: "depositorAta", signer: false, writable: true },
931
+ { name: "vault", signer: false, writable: true },
932
+ { name: "tokenProgram", signer: false, writable: false },
933
+ { name: "insLpMint", signer: false, writable: true },
934
+ { name: "depositorLpAta", signer: false, writable: true },
935
+ { name: "vaultAuthority", signer: false, writable: false }
936
+ ];
937
+ var ACCOUNTS_WITHDRAW_INSURANCE_LP = [
938
+ { name: "withdrawer", signer: true, writable: false },
939
+ { name: "slab", signer: false, writable: true },
940
+ { name: "withdrawerAta", signer: false, writable: true },
941
+ { name: "vault", signer: false, writable: true },
942
+ { name: "tokenProgram", signer: false, writable: false },
943
+ { name: "insLpMint", signer: false, writable: true },
944
+ { name: "withdrawerLpAta", signer: false, writable: true },
945
+ { name: "vaultAuthority", signer: false, writable: false }
946
+ ];
897
947
  var ACCOUNTS_LP_VAULT_WITHDRAW = [
898
948
  { name: "withdrawer", signer: true, writable: false },
899
949
  { name: "slab", signer: false, writable: true },
@@ -1010,6 +1060,11 @@ var ACCOUNTS_SET_WALLET_CAP = [
1010
1060
  { name: "admin", signer: true, writable: false },
1011
1061
  { name: "slab", signer: false, writable: true }
1012
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
+ ];
1013
1068
  var ACCOUNTS_INIT_MATCHER_CTX = [
1014
1069
  { name: "admin", signer: true, writable: false },
1015
1070
  { name: "slab", signer: false, writable: false },
@@ -1301,24 +1356,11 @@ function getErrorName(code) {
1301
1356
  function getErrorHint(code) {
1302
1357
  return PERCOLATOR_ERRORS[code]?.hint;
1303
1358
  }
1304
- var LIGHTHOUSE_PROGRAM_ID_STR = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
1305
- var ANCHOR_ERROR_RANGE_START = 6e3;
1306
- var ANCHOR_ERROR_RANGE_END = 8191;
1307
- var ANCHOR_ERROR_NAMES = {
1308
- 6032: "ConstraintMut",
1309
- 6036: "ConstraintOwner",
1310
- 6038: "ConstraintSeeds",
1311
- 6400: "ConstraintAddress"
1312
- };
1313
- function isAnchorErrorCode(code) {
1314
- return code >= ANCHOR_ERROR_RANGE_START && code <= ANCHOR_ERROR_RANGE_END;
1315
- }
1316
1359
  var CUSTOM_ERROR_HEX_MAX_LEN = 8;
1317
1360
  function parseErrorFromLogs(logs) {
1318
1361
  if (!Array.isArray(logs)) {
1319
1362
  return null;
1320
1363
  }
1321
- let insideLighthouse = false;
1322
1364
  const re = new RegExp(
1323
1365
  `custom program error: 0x([0-9a-fA-F]{1,${CUSTOM_ERROR_HEX_MAX_LEN}})(?![0-9a-fA-F])`,
1324
1366
  "i"
@@ -1327,32 +1369,17 @@ function parseErrorFromLogs(logs) {
1327
1369
  if (typeof log !== "string") {
1328
1370
  continue;
1329
1371
  }
1330
- if (log.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {
1331
- insideLighthouse = true;
1332
- } else if (log.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {
1333
- insideLighthouse = false;
1334
- }
1335
1372
  const match = log.match(re);
1336
1373
  if (match) {
1337
1374
  const code = parseInt(match[1], 16);
1338
1375
  if (!Number.isFinite(code) || code < 0 || code > 4294967295) {
1339
1376
  continue;
1340
1377
  }
1341
- if (isAnchorErrorCode(code) || insideLighthouse) {
1342
- const anchorName = ANCHOR_ERROR_NAMES[code] ?? `AnchorError(0x${code.toString(16)})`;
1343
- return {
1344
- code,
1345
- name: `Lighthouse:${anchorName}`,
1346
- 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).",
1347
- source: "lighthouse"
1348
- };
1349
- }
1350
1378
  const info = decodeError(code);
1351
1379
  return {
1352
1380
  code,
1353
1381
  name: info?.name ?? `Unknown(${code})`,
1354
- hint: info?.hint,
1355
- source: info ? "percolator" : "unknown"
1382
+ hint: info?.hint
1356
1383
  };
1357
1384
  }
1358
1385
  }
@@ -1583,6 +1610,10 @@ var V12_1_SBF_OFF_LAST_SWEEP_COMPLETE = 312;
1583
1610
  var V12_1_SBF_OFF_CRANK_CURSOR = 320;
1584
1611
  var V12_1_SBF_OFF_SWEEP_START_IDX = 322;
1585
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;
1586
1617
  var V12_1_ENGINE_CURRENT_SLOT_OFF = 448;
1587
1618
  var V12_1_ENGINE_FUNDING_RATE_BPS_OFF = 456;
1588
1619
  var V12_1_ENGINE_LAST_CRANK_SLOT_OFF = 464;
@@ -1617,7 +1648,13 @@ var V12_1_ACCT_FEE_CREDITS_OFF = 240;
1617
1648
  var V12_1_ACCT_LAST_FEE_SLOT_OFF = 256;
1618
1649
  var V12_1_ACCT_POSITION_SIZE_OFF = 88;
1619
1650
  var V12_1_ACCT_ENTRY_PRICE_OFF = -1;
1620
- var V12_1_ACCT_FUNDING_INDEX_OFF = 288;
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;
1621
1658
  var V12_15_ENGINE_OFF = 624;
1622
1659
  var V12_15_ENGINE_OFF_SBF = 616;
1623
1660
  var V12_15_ACCOUNT_SIZE = 4400;
@@ -1642,6 +1679,7 @@ var V12_15_ACCT_OVERFLOW_NEWEST_OFF = 4320;
1642
1679
  var V12_15_ACCT_OVERFLOW_NEWEST_PRESENT_OFF = 4384;
1643
1680
  var V12_15_PARAMS_SIZE = 192;
1644
1681
  var V12_15_PARAMS_MAX_ACCOUNTS_OFF = 24;
1682
+ var V12_15_PARAMS_INSURANCE_FLOOR_OFF = 144;
1645
1683
  var V12_15_PARAMS_H_MIN_OFF = 160;
1646
1684
  var V12_15_PARAMS_H_MAX_OFF = 168;
1647
1685
  var V12_15_ENGINE_PARAMS_OFF = 32;
@@ -1739,6 +1777,14 @@ for (const [, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Large",
1739
1777
  const total = V12_1_SBF_ENGINE_OFF + accountsOff + n * V12_1_SBF_ACCOUNT_SIZE;
1740
1778
  V12_1_SIZES.set(total, n);
1741
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);
1787
+ }
1742
1788
  var SLAB_TIERS_V2 = {
1743
1789
  small: { maxAccounts: 256, dataSize: 65088, label: "Small", description: "256 slots (V2 BPF intermediate)" },
1744
1790
  large: { maxAccounts: 4096, dataSize: 1025568, label: "Large", description: "4,096 slots (V2 BPF intermediate)" }
@@ -2304,16 +2350,12 @@ function buildLayoutV12_1(maxAccounts, dataLen) {
2304
2350
  engineLastFundingSlotOff: isSbf ? -1 : V12_1_ENGINE_LAST_FUNDING_SLOT_OFF,
2305
2351
  // not in deployed struct
2306
2352
  engineFundingRateBpsOff: isSbf ? V12_1_SBF_OFF_FUNDING_RATE : V12_1_ENGINE_FUNDING_RATE_BPS_OFF,
2307
- engineMarkPriceOff: isSbf ? -1 : V12_1_ENGINE_MARK_PRICE_OFF,
2308
- // not in deployed struct
2353
+ engineMarkPriceOff: isSbf ? V12_1_SBF_OFF_MARK_PRICE_E6 : V12_1_ENGINE_MARK_PRICE_OFF,
2309
2354
  engineLastCrankSlotOff: isSbf ? V12_1_SBF_OFF_LAST_CRANK_SLOT : V12_1_ENGINE_LAST_CRANK_SLOT_OFF,
2310
2355
  engineMaxCrankStalenessOff: isSbf ? V12_1_SBF_OFF_MAX_CRANK_STALENESS : V12_1_ENGINE_MAX_CRANK_STALENESS_OFF,
2311
- engineTotalOiOff: isSbf ? -1 : V12_1_ENGINE_TOTAL_OI_OFF,
2312
- // not in deployed struct
2313
- engineLongOiOff: isSbf ? -1 : V12_1_ENGINE_LONG_OI_OFF,
2314
- // not in deployed struct
2315
- engineShortOiOff: isSbf ? -1 : V12_1_ENGINE_SHORT_OI_OFF,
2316
- // not in deployed struct
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,
2317
2359
  engineCTotOff: isSbf ? V12_1_SBF_OFF_C_TOT : V12_1_ENGINE_C_TOT_OFF,
2318
2360
  enginePnlPosTotOff: isSbf ? V12_1_SBF_OFF_PNL_POS_TOT : V12_1_ENGINE_PNL_POS_TOT_OFF,
2319
2361
  engineLiqCursorOff: isSbf ? V12_1_SBF_OFF_LIQ_CURSOR : V12_1_ENGINE_LIQ_CURSOR_OFF,
@@ -2349,6 +2391,71 @@ function buildLayoutV12_1(maxAccounts, dataLen) {
2349
2391
  engineInsuranceIsolationBpsOff: isSbf ? -1 : 64
2350
2392
  };
2351
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
+ }
2352
2459
  function buildLayoutV12_15(maxAccounts, dataLen) {
2353
2460
  const isSbf = dataLen === 237512;
2354
2461
  const accountSize = isSbf ? V12_15_ACCOUNT_SIZE_SMALL : V12_15_ACCOUNT_SIZE;
@@ -2364,7 +2471,7 @@ function buildLayoutV12_15(maxAccounts, dataLen) {
2364
2471
  return {
2365
2472
  version: 2,
2366
2473
  headerLen: V0_HEADER_LEN,
2367
- // 72 (same as V12_1)
2474
+ // 72
2368
2475
  configOffset: V0_HEADER_LEN,
2369
2476
  // 72
2370
2477
  configLen: 552,
@@ -2387,14 +2494,12 @@ function buildLayoutV12_15(maxAccounts, dataLen) {
2387
2494
  // not present in v12.15 engine struct
2388
2495
  engineLastFundingSlotOff: -1,
2389
2496
  // not present in v12.15 engine struct
2390
- // funding_rate_e9 is i128 — stored in engineFundingRateBpsOff for EngineState.fundingRateBpsPerSlotLast
2391
- // callers should treat this as the i128 funding rate in e9 units
2392
2497
  engineFundingRateBpsOff: isSbf ? 224 : V12_15_ENGINE_FUNDING_RATE_E9_OFF,
2393
2498
  // SBF=224, native=240
2394
2499
  engineMarkPriceOff: -1,
2395
- // not present in v12.15 (removed with oracle refactor)
2500
+ // not present in v12.15
2396
2501
  engineLastCrankSlotOff: -1,
2397
- // not yet mapped; set -1 until offset verified on-chain
2502
+ // not yet mapped
2398
2503
  engineMaxCrankStalenessOff: -1,
2399
2504
  // not yet mapped
2400
2505
  engineTotalOiOff: -1,
@@ -2443,7 +2548,6 @@ function buildLayoutV12_15(maxAccounts, dataLen) {
2443
2548
  acctOwnerOff: V12_15_ACCT_OWNER_OFF,
2444
2549
  // 192
2445
2550
  hasInsuranceIsolation: false,
2446
- // InsuranceFund = {balance: u128} = 16 bytes in v12.15
2447
2551
  engineInsuranceIsolatedOff: -1,
2448
2552
  engineInsuranceIsolationBpsOff: -1
2449
2553
  };
@@ -2451,6 +2555,8 @@ function buildLayoutV12_15(maxAccounts, dataLen) {
2451
2555
  function detectSlabLayout(dataLen, data) {
2452
2556
  const v1215n = V12_15_SIZES.get(dataLen);
2453
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);
2454
2560
  const v121n = V12_1_SIZES.get(dataLen);
2455
2561
  if (v121n !== void 0) return buildLayoutV12_1(v121n, dataLen);
2456
2562
  const vsdpn = V_SETDEXPOOL_SIZES.get(dataLen);
@@ -2497,6 +2603,15 @@ var PARAMS_LIQUIDATION_FEE_BPS_OFF = 96;
2497
2603
  var PARAMS_LIQUIDATION_FEE_CAP_OFF = 104;
2498
2604
  var PARAMS_LIQUIDATION_BUFFER_OFF = 120;
2499
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;
2500
2615
  var ACCT_ACCOUNT_ID_OFF = 0;
2501
2616
  var ACCT_CAPITAL_OFF = 8;
2502
2617
  var ACCT_KIND_OFF = 24;
@@ -2747,14 +2862,15 @@ function parseParams(data, layoutHint) {
2747
2862
  throw new Error("Slab data too short for RiskParams");
2748
2863
  }
2749
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;
2750
2866
  const result = {
2751
2867
  warmupPeriodSlots: isV12_15Params ? readU64LE(data, base + V12_15_PARAMS_H_MIN_OFF) : readU64LE(data, base + PARAMS_WARMUP_PERIOD_OFF),
2752
- maintenanceMarginBps: readU64LE(data, base + PARAMS_MAINTENANCE_MARGIN_OFF),
2753
- initialMarginBps: readU64LE(data, base + PARAMS_INITIAL_MARGIN_OFF),
2754
- tradingFeeBps: readU64LE(data, base + PARAMS_TRADING_FEE_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),
2755
2871
  maxAccounts: isV12_15Params ? readU64LE(data, base + V12_15_PARAMS_MAX_ACCOUNTS_OFF) : readU64LE(data, base + PARAMS_MAX_ACCOUNTS_OFF),
2756
- newAccountFee: readU128LE(data, base + PARAMS_NEW_ACCOUNT_FEE_OFF),
2757
- // Extended params: only read if V1 (paramsSize >= 144)
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
2758
2874
  riskReductionThreshold: 0n,
2759
2875
  maintenanceFeePerSlot: 0n,
2760
2876
  maxCrankStalenessSlots: 0n,
@@ -2762,12 +2878,17 @@ function parseParams(data, layoutHint) {
2762
2878
  liquidationFeeCap: 0n,
2763
2879
  liquidationBufferBps: 0n,
2764
2880
  minLiquidationAbs: 0n,
2881
+ minInitialDeposit: 0n,
2882
+ minNonzeroMmReq: 0n,
2883
+ minNonzeroImReq: 0n,
2884
+ insuranceFloor: 0n,
2765
2885
  hMin: 0n,
2766
2886
  hMax: 0n
2767
2887
  };
2768
2888
  if (isV12_15Params) {
2769
2889
  result.hMin = readU64LE(data, base + V12_15_PARAMS_H_MIN_OFF);
2770
2890
  result.hMax = readU64LE(data, base + V12_15_PARAMS_H_MAX_OFF);
2891
+ result.insuranceFloor = readU128LE(data, base + V12_15_PARAMS_INSURANCE_FLOOR_OFF);
2771
2892
  result.riskReductionThreshold = 0n;
2772
2893
  result.maintenanceFeePerSlot = 0n;
2773
2894
  result.maxCrankStalenessSlots = readU64LE(data, base + 48);
@@ -2775,6 +2896,21 @@ function parseParams(data, layoutHint) {
2775
2896
  result.liquidationFeeCap = readU128LE(data, base + 64);
2776
2897
  result.liquidationBufferBps = 0n;
2777
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;
2778
2914
  } else if (paramsSize >= 144) {
2779
2915
  result.riskReductionThreshold = readU128LE(data, base + PARAMS_RISK_THRESHOLD_OFF);
2780
2916
  result.maintenanceFeePerSlot = readU128LE(data, base + PARAMS_MAINTENANCE_FEE_OFF);
@@ -2794,8 +2930,8 @@ function parseEngine(data) {
2794
2930
  throw new Error(`Unrecognized slab data length: ${data.length}. Cannot determine layout version.`);
2795
2931
  }
2796
2932
  const base = layout.engineOff;
2797
- const isV12_15 = layout.accountSize === V12_15_ACCOUNT_SIZE || layout.accountSize === V12_15_ACCOUNT_SIZE_SMALL;
2798
- const fundingRateBpsPerSlotLast = isV12_15 ? readI128LE(data, base + layout.engineFundingRateBpsOff) : readI64LE(data, base + layout.engineFundingRateBpsOff);
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);
2799
2935
  return {
2800
2936
  vault: readU128LE(data, base),
2801
2937
  insuranceFund: {
@@ -2809,23 +2945,23 @@ function parseEngine(data) {
2809
2945
  fundingIndexQpbE6: layout.engineFundingIndexOff >= 0 ? readI128LE(data, base + layout.engineFundingIndexOff) : 0n,
2810
2946
  lastFundingSlot: layout.engineLastFundingSlotOff >= 0 ? readU64LE(data, base + layout.engineLastFundingSlotOff) : 0n,
2811
2947
  fundingRateBpsPerSlotLast,
2812
- fundingRateE9: isV12_15 ? readI128LE(data, base + layout.engineFundingRateBpsOff) : 0n,
2948
+ fundingRateE9: isV12_15 ? readI128LE(data, base + V12_15_ENGINE_FUNDING_RATE_E9_OFF) : 0n,
2813
2949
  marketMode: isV12_15 ? readU8(data, base + V12_15_ENGINE_MARKET_MODE_OFF) === 1 ? 1 : 0 : null,
2814
- lastCrankSlot: layout.engineLastCrankSlotOff >= 0 ? readU64LE(data, base + layout.engineLastCrankSlotOff) : 0n,
2815
- maxCrankStalenessSlots: layout.engineMaxCrankStalenessOff >= 0 ? readU64LE(data, base + layout.engineMaxCrankStalenessOff) : 0n,
2950
+ lastCrankSlot: readU64LE(data, base + layout.engineLastCrankSlotOff),
2951
+ maxCrankStalenessSlots: readU64LE(data, base + layout.engineMaxCrankStalenessOff),
2816
2952
  totalOpenInterest: layout.engineTotalOiOff >= 0 ? readU128LE(data, base + layout.engineTotalOiOff) : 0n,
2817
2953
  longOi: layout.engineLongOiOff >= 0 ? readU128LE(data, base + layout.engineLongOiOff) : 0n,
2818
2954
  shortOi: layout.engineShortOiOff >= 0 ? readU128LE(data, base + layout.engineShortOiOff) : 0n,
2819
2955
  cTot: readU128LE(data, base + layout.engineCTotOff),
2820
2956
  pnlPosTot: readU128LE(data, base + layout.enginePnlPosTotOff),
2821
2957
  pnlMaturedPosTot: isV12_15 ? readU128LE(data, base + V12_15_ENGINE_PNL_MATURED_POS_TOT_OFF) : 0n,
2822
- liqCursor: layout.engineLiqCursorOff >= 0 ? readU16LE(data, base + layout.engineLiqCursorOff) : 0,
2823
- gcCursor: layout.engineGcCursorOff >= 0 ? readU16LE(data, base + layout.engineGcCursorOff) : 0,
2824
- lastSweepStartSlot: layout.engineLastSweepStartOff >= 0 ? readU64LE(data, base + layout.engineLastSweepStartOff) : 0n,
2825
- lastSweepCompleteSlot: layout.engineLastSweepCompleteOff >= 0 ? readU64LE(data, base + layout.engineLastSweepCompleteOff) : 0n,
2826
- crankCursor: layout.engineCrankCursorOff >= 0 ? readU16LE(data, base + layout.engineCrankCursorOff) : 0,
2827
- sweepStartIdx: layout.engineSweepStartIdxOff >= 0 ? readU16LE(data, base + layout.engineSweepStartIdxOff) : 0,
2828
- lifetimeLiquidations: layout.engineLifetimeLiquidationsOff >= 0 ? readU64LE(data, base + layout.engineLifetimeLiquidationsOff) : 0n,
2958
+ liqCursor: readU16LE(data, base + layout.engineLiqCursorOff),
2959
+ gcCursor: readU16LE(data, base + layout.engineGcCursorOff),
2960
+ lastSweepStartSlot: readU64LE(data, base + layout.engineLastSweepStartOff),
2961
+ lastSweepCompleteSlot: readU64LE(data, base + layout.engineLastSweepCompleteOff),
2962
+ crankCursor: readU16LE(data, base + layout.engineCrankCursorOff),
2963
+ sweepStartIdx: readU16LE(data, base + layout.engineSweepStartIdxOff),
2964
+ lifetimeLiquidations: readU64LE(data, base + layout.engineLifetimeLiquidationsOff),
2829
2965
  lifetimeForceCloses: layout.engineLifetimeForceClosesOff >= 0 ? readU64LE(data, base + layout.engineLifetimeForceClosesOff) : 0n,
2830
2966
  netLpPos: layout.engineNetLpPosOff >= 0 ? readI128LE(data, base + layout.engineNetLpPosOff) : 0n,
2831
2967
  lpSumAbs: layout.engineLpSumAbsOff >= 0 ? readU128LE(data, base + layout.engineLpSumAbsOff) : 0n,
@@ -2896,8 +3032,9 @@ function parseAccount(data, idx) {
2896
3032
  throw new Error("Slab data too short for account");
2897
3033
  }
2898
3034
  const isV12_15 = layout.accountSize === V12_15_ACCOUNT_SIZE || layout.accountSize === V12_15_ACCOUNT_SIZE_SMALL;
2899
- const isV12_1 = !isV12_15 && (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);
2900
- const isAdl = !isV12_15 && (layout.accountSize >= 312 || isV12_1);
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);
2901
3038
  if (isV12_15) {
2902
3039
  const kindByte2 = readU8(data, base + V12_15_ACCT_KIND_OFF);
2903
3040
  const kind2 = kindByte2 === 1 ? 1 /* LP */ : 0 /* User */;
@@ -2940,13 +3077,13 @@ function parseAccount(data, idx) {
2940
3077
  }
2941
3078
  const warmupStartedOff = isAdl ? V_ADL_ACCT_WARMUP_STARTED_OFF : ACCT_WARMUP_STARTED_OFF;
2942
3079
  const warmupSlopeOff = isAdl ? V_ADL_ACCT_WARMUP_SLOPE_OFF : ACCT_WARMUP_SLOPE_OFF;
2943
- const positionSizeOff = isV12_1 ? V12_1_ACCT_POSITION_SIZE_OFF : isAdl ? V_ADL_ACCT_POSITION_SIZE_OFF : ACCT_POSITION_SIZE_OFF;
2944
- const entryPriceOff = isV12_1 ? V12_1_ACCT_ENTRY_PRICE_OFF : isAdl ? V_ADL_ACCT_ENTRY_PRICE_OFF : ACCT_ENTRY_PRICE_OFF;
2945
- const fundingIndexOff = isV12_1 ? V12_1_ACCT_FUNDING_INDEX_OFF : isAdl ? V_ADL_ACCT_FUNDING_INDEX_OFF : ACCT_FUNDING_INDEX_OFF;
2946
- const matcherProgOff = isV12_1 ? V12_1_ACCT_MATCHER_PROGRAM_OFF : isAdl ? V_ADL_ACCT_MATCHER_PROGRAM_OFF : ACCT_MATCHER_PROGRAM_OFF;
2947
- const matcherCtxOff = isV12_1 ? V12_1_ACCT_MATCHER_CONTEXT_OFF : isAdl ? V_ADL_ACCT_MATCHER_CONTEXT_OFF : ACCT_MATCHER_CONTEXT_OFF;
2948
- const feeCreditsOff = isV12_1 ? V12_1_ACCT_FEE_CREDITS_OFF : isAdl ? V_ADL_ACCT_FEE_CREDITS_OFF : ACCT_FEE_CREDITS_OFF;
2949
- 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;
2950
3087
  const kindByte = readU8(data, base + ACCT_KIND_OFF);
2951
3088
  const kind = kindByte === 1 ? 1 /* LP */ : 0 /* User */;
2952
3089
  return {
@@ -2959,9 +3096,8 @@ function parseAccount(data, idx) {
2959
3096
  warmupSlopePerStep: readU128LE(data, base + warmupSlopeOff),
2960
3097
  positionSize: readI128LE(data, base + positionSizeOff),
2961
3098
  entryPrice: entryPriceOff >= 0 ? readU64LE(data, base + entryPriceOff) : 0n,
2962
- // V12_1: entry_price removed
2963
- // V12_1 changed funding_index from i128 to i64 (legacy field moved to end of account)
2964
- fundingIndex: isV12_1 ? BigInt(readI64LE(data, base + fundingIndexOff)) : readI128LE(data, base + fundingIndexOff),
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),
2965
3101
  matcherProgram: new PublicKey3(data.subarray(base + matcherProgOff, base + matcherProgOff + 32)),
2966
3102
  matcherContext: new PublicKey3(data.subarray(base + matcherCtxOff, base + matcherCtxOff + 32)),
2967
3103
  owner: new PublicKey3(data.subarray(base + layout.acctOwnerOff, base + layout.acctOwnerOff + 32)),
@@ -3003,6 +3139,12 @@ function deriveVaultAuthority(programId, slab) {
3003
3139
  programId
3004
3140
  );
3005
3141
  }
3142
+ function deriveInsuranceLpMint(programId, slab) {
3143
+ return PublicKey4.findProgramAddressSync(
3144
+ [textEncoder.encode("ins_lp"), slab.toBytes()],
3145
+ programId
3146
+ );
3147
+ }
3006
3148
  var LP_INDEX_U16_MAX = 65535;
3007
3149
  function deriveLpPda(programId, slab, lpIdx) {
3008
3150
  if (typeof lpIdx !== "number" || !Number.isInteger(lpIdx) || lpIdx < 0 || lpIdx > LP_INDEX_U16_MAX) {
@@ -3053,14 +3195,7 @@ function derivePythPushOraclePDA(feedIdHex) {
3053
3195
  }
3054
3196
  const feedId = new Uint8Array(32);
3055
3197
  for (let i = 0; i < 32; i++) {
3056
- const hexPair = normalized.substring(i * 2, i * 2 + 2);
3057
- const byte = parseInt(hexPair, 16);
3058
- if (Number.isNaN(byte)) {
3059
- throw new Error(
3060
- `derivePythPushOraclePDA: failed to parse hex byte at position ${i}: "${hexPair}"`
3061
- );
3062
- }
3063
- feedId[i] = byte;
3198
+ feedId[i] = parseInt(normalized.substring(i * 2, i * 2 + 2), 16);
3064
3199
  }
3065
3200
  const shardBuf = new Uint8Array(2);
3066
3201
  return PublicKey4.findProgramAddressSync(
@@ -3092,9 +3227,7 @@ import { PublicKey as PublicKey6 } from "@solana/web3.js";
3092
3227
  // src/solana/static-markets.ts
3093
3228
  import { PublicKey as PublicKey5 } from "@solana/web3.js";
3094
3229
  var MAINNET_MARKETS = [
3095
- // Populated at mainnet launch currently empty.
3096
- // To add entries:
3097
- // { slabAddress: "ABC123...", symbol: "SOL-PERP", name: "SOL Perpetual" },
3230
+ { slabAddress: "7psyeWRts4pRX2cyAWD1NH87bR9ugXP7pe6ARgfG79Do", symbol: "SOL-PERP", name: "SOL/USDC Perpetual" }
3098
3231
  ];
3099
3232
  var DEVNET_MARKETS = [
3100
3233
  // Populated from prior discoverMarkets() runs on devnet.
@@ -3874,7 +4007,9 @@ function computeRaydiumClmmPriceE6(data) {
3874
4007
  }
3875
4008
  const sqrtPriceX64 = readU128LE3(dv3, 253);
3876
4009
  if (sqrtPriceX64 === 0n) return 0n;
3877
- const priceE6Raw = sqrtPriceX64 * sqrtPriceX64 * 1000000n >> 128n;
4010
+ const scaledSqrt = sqrtPriceX64 * 1000000n;
4011
+ const term = scaledSqrt >> 64n;
4012
+ const priceE6Raw = term * sqrtPriceX64 >> 64n;
3878
4013
  const decimalDiff = 6 + decimals0 - decimals1;
3879
4014
  const adjustedDiff = decimalDiff - 6;
3880
4015
  if (adjustedDiff >= 0) {
@@ -3915,26 +4050,13 @@ function computeMeteoraDlmmPriceE6(data) {
3915
4050
  `Meteora DLMM: |activeId| ${Math.abs(activeId)} exceeds max ${MAX_ACTIVE_ID_ABS}`
3916
4051
  );
3917
4052
  }
3918
- const MAX_ABS_BIN_ID = 5e5;
3919
- if (activeId > MAX_ABS_BIN_ID || activeId < -MAX_ABS_BIN_ID) {
3920
- throw new Error(
3921
- `Meteora DLMM: activeId ${activeId} exceeds safe range (\xB1${MAX_ABS_BIN_ID})`
3922
- );
3923
- }
3924
4053
  const SCALE = 1000000000000000000n;
3925
4054
  const base = SCALE + BigInt(binStep) * SCALE / 10000n;
3926
4055
  const isNeg = activeId < 0;
3927
4056
  let exp = isNeg ? BigInt(-activeId) : BigInt(activeId);
3928
4057
  let result = SCALE;
3929
4058
  let b = base;
3930
- let iterations = 0;
3931
- const MAX_ITERATIONS = 25;
3932
4059
  while (exp > 0n) {
3933
- if (iterations++ >= MAX_ITERATIONS) {
3934
- throw new Error(
3935
- `Meteora DLMM: exponentiation loop exceeded ${MAX_ITERATIONS} iterations (activeId=${activeId})`
3936
- );
3937
- }
3938
4060
  if (exp & 1n) {
3939
4061
  result = result * b / SCALE;
3940
4062
  }
@@ -3965,7 +4087,6 @@ function readU128LE3(dv3, offset) {
3965
4087
  var CHAINLINK_MIN_SIZE = 224;
3966
4088
  var MAX_DECIMALS = 18;
3967
4089
  var CHAINLINK_DECIMALS_OFFSET = 138;
3968
- var CHAINLINK_TIMESTAMP_OFFSET = 168;
3969
4090
  var CHAINLINK_ANSWER_OFFSET = 216;
3970
4091
  function readU82(data, off) {
3971
4092
  return data[off];
@@ -3973,7 +4094,7 @@ function readU82(data, off) {
3973
4094
  function readBigInt64LE(data, off) {
3974
4095
  return new DataView(data.buffer, data.byteOffset, data.byteLength).getBigInt64(off, true);
3975
4096
  }
3976
- function parseChainlinkPrice(data, options) {
4097
+ function parseChainlinkPrice(data) {
3977
4098
  if (data.length < CHAINLINK_MIN_SIZE) {
3978
4099
  throw new Error(
3979
4100
  `Oracle account data too small: ${data.length} bytes (need at least ${CHAINLINK_MIN_SIZE})`
@@ -3991,18 +4112,7 @@ function parseChainlinkPrice(data, options) {
3991
4112
  `Oracle price is non-positive: ${price}`
3992
4113
  );
3993
4114
  }
3994
- const updatedAtBig = readBigInt64LE(data, CHAINLINK_TIMESTAMP_OFFSET);
3995
- const updatedAt = Number(updatedAtBig);
3996
- if (options?.maxStalenessSeconds !== void 0 && updatedAt > 0) {
3997
- const now = Math.floor(Date.now() / 1e3);
3998
- const age = now - updatedAt;
3999
- if (age > options.maxStalenessSeconds) {
4000
- throw new Error(
4001
- `Oracle price is stale: last updated ${age}s ago (max ${options.maxStalenessSeconds}s)`
4002
- );
4003
- }
4004
- }
4005
- return { price, decimals, updatedAt: updatedAt > 0 ? updatedAt : void 0 };
4115
+ return { price, decimals };
4006
4116
  }
4007
4117
  function isValidChainlinkOracle(data) {
4008
4118
  try {
@@ -4022,11 +4132,7 @@ var TOKEN_2022_PROGRAM_ID = new PublicKey8(
4022
4132
  async function detectTokenProgram(connection, mint) {
4023
4133
  const info = await connection.getAccountInfo(mint);
4024
4134
  if (!info) throw new Error(`Mint account not found: ${mint.toBase58()}`);
4025
- if (info.owner.equals(TOKEN_PROGRAM_ID3)) return TOKEN_PROGRAM_ID3;
4026
- if (info.owner.equals(TOKEN_2022_PROGRAM_ID)) return TOKEN_2022_PROGRAM_ID;
4027
- throw new Error(
4028
- `Mint ${mint.toBase58()} is owned by ${info.owner.toBase58()}, which is neither TOKEN_PROGRAM_ID nor TOKEN_2022_PROGRAM_ID`
4029
- );
4135
+ return info.owner;
4030
4136
  }
4031
4137
  function isToken2022(tokenProgramId) {
4032
4138
  return tokenProgramId.equals(TOKEN_2022_PROGRAM_ID);
@@ -4059,14 +4165,12 @@ var PROGRAM_IDS = {
4059
4165
  }
4060
4166
  };
4061
4167
  function getProgramId(network) {
4062
- if (!network) {
4063
- const override = safeEnv("PROGRAM_ID");
4064
- if (override) {
4065
- console.warn(
4066
- `[percolator-sdk] PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
4067
- );
4068
- return new PublicKey9(override);
4069
- }
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);
4070
4174
  }
4071
4175
  const detectedNetwork = getCurrentNetwork();
4072
4176
  const targetNetwork = network ?? detectedNetwork;
@@ -4074,14 +4178,12 @@ function getProgramId(network) {
4074
4178
  return new PublicKey9(programId);
4075
4179
  }
4076
4180
  function getMatcherProgramId(network) {
4077
- if (!network) {
4078
- const override = safeEnv("MATCHER_PROGRAM_ID");
4079
- if (override) {
4080
- console.warn(
4081
- `[percolator-sdk] MATCHER_PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
4082
- );
4083
- return new PublicKey9(override);
4084
- }
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);
4085
4187
  }
4086
4188
  const detectedNetwork = getCurrentNetwork();
4087
4189
  const targetNetwork = network ?? detectedNetwork;
@@ -4114,7 +4216,10 @@ function getStakeProgramId(network) {
4114
4216
  }
4115
4217
  const detectedNetwork = network ?? (() => {
4116
4218
  const n = safeEnv("NEXT_PUBLIC_DEFAULT_NETWORK")?.toLowerCase() ?? safeEnv("NETWORK")?.toLowerCase() ?? "";
4117
- 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";
4118
4223
  })();
4119
4224
  const id = STAKE_PROGRAM_IDS[detectedNetwork];
4120
4225
  if (!id) {
@@ -4124,7 +4229,7 @@ function getStakeProgramId(network) {
4124
4229
  }
4125
4230
  return new PublicKey10(id);
4126
4231
  }
4127
- var STAKE_PROGRAM_ID = new PublicKey10(STAKE_PROGRAM_IDS.mainnet);
4232
+ var STAKE_PROGRAM_ID = new PublicKey10(STAKE_PROGRAM_IDS.devnet);
4128
4233
  var STAKE_IX = {
4129
4234
  InitPool: 0,
4130
4235
  Deposit: 1,
@@ -4185,9 +4290,6 @@ function readU16LE3(data, off) {
4185
4290
  );
4186
4291
  }
4187
4292
  function u64Le(v) {
4188
- if (typeof v === "number" && !Number.isSafeInteger(v)) {
4189
- throw new Error(`u64Le: number ${v} exceeds Number.MAX_SAFE_INTEGER \u2014 use BigInt`);
4190
- }
4191
4293
  const big = BigInt(v);
4192
4294
  if (big < 0n) throw new Error(`u64Le: value must be non-negative, got ${big}`);
4193
4295
  if (big > 0xFFFFFFFFFFFFFFFFn) throw new Error(`u64Le: value exceeds u64 max`);
@@ -4196,9 +4298,6 @@ function u64Le(v) {
4196
4298
  return arr;
4197
4299
  }
4198
4300
  function u128Le(v) {
4199
- if (typeof v === "number" && !Number.isSafeInteger(v)) {
4200
- throw new Error(`u128Le: number ${v} exceeds Number.MAX_SAFE_INTEGER \u2014 use BigInt`);
4201
- }
4202
4301
  const big = BigInt(v);
4203
4302
  if (big < 0n) throw new Error(`u128Le: value must be non-negative, got ${big}`);
4204
4303
  if (big > (1n << 128n) - 1n) throw new Error(`u128Le: value exceeds u128 max`);
@@ -4209,7 +4308,7 @@ function u128Le(v) {
4209
4308
  return arr;
4210
4309
  }
4211
4310
  function u16Le(v) {
4212
- 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}`);
4213
4312
  const arr = new Uint8Array(2);
4214
4313
  new DataView(arr.buffer).setUint16(0, v, true);
4215
4314
  return arr;
@@ -4464,9 +4563,7 @@ function computePnlPct(pnl, capital) {
4464
4563
  }
4465
4564
  function isAdlTriggered(slabData) {
4466
4565
  const layout = detectSlabLayout(slabData.length);
4467
- if (!layout) {
4468
- return false;
4469
- }
4566
+ if (!layout) return false;
4470
4567
  try {
4471
4568
  const engine = parseEngine(slabData);
4472
4569
  if (engine.pnlPosTot === 0n) return false;
@@ -4509,14 +4606,6 @@ function rankAdlPositions(slabData) {
4509
4606
  if (account.kind !== 0 /* User */) continue;
4510
4607
  if (account.positionSize === 0n) continue;
4511
4608
  const side = account.positionSize > 0n ? "long" : "short";
4512
- if (side === "long" && account.positionSize <= 0n) {
4513
- console.warn(`[fetchAdlRankedPositions] account idx=${idx}: side=long but positionSize=${account.positionSize}`);
4514
- continue;
4515
- }
4516
- if (side === "short" && account.positionSize >= 0n) {
4517
- console.warn(`[fetchAdlRankedPositions] account idx=${idx}: side=short but positionSize=${account.positionSize}`);
4518
- continue;
4519
- }
4520
4609
  const pnlPct = computePnlPct(account.pnl, account.capital);
4521
4610
  positions.push({
4522
4611
  idx,
@@ -4549,8 +4638,7 @@ function buildAdlInstruction(caller, slab, oracle, programId, targetIdx, backupO
4549
4638
  `buildAdlInstruction: targetIdx must be a non-negative integer, got ${targetIdx}`
4550
4639
  );
4551
4640
  }
4552
- const dataBytes = encodeExecuteAdl({ targetIdx });
4553
- const data = Buffer.from(dataBytes);
4641
+ const data = Buffer.from(encodeExecuteAdl({ targetIdx }));
4554
4642
  const keys = [
4555
4643
  { pubkey: caller, isSigner: true, isWritable: false },
4556
4644
  { pubkey: slab, isSigner: false, isWritable: true },
@@ -4590,11 +4678,7 @@ function parseAdlEvent(logs) {
4590
4678
  }
4591
4679
  if (tag !== ADL_EVENT_TAG) continue;
4592
4680
  try {
4593
- const targetIdxBig = BigInt(match[2]);
4594
- if (targetIdxBig < 0n || targetIdxBig > 65535n) {
4595
- continue;
4596
- }
4597
- const targetIdx = Number(targetIdxBig);
4681
+ const targetIdx = Number(BigInt(match[2]));
4598
4682
  const price = BigInt(match[3]);
4599
4683
  const closedLo = BigInt(match[4]);
4600
4684
  const closedHi = BigInt(match[5]);
@@ -4622,22 +4706,6 @@ async function fetchAdlRankings(apiBase, slab, fetchFn = fetch) {
4622
4706
  );
4623
4707
  }
4624
4708
  const json = await res.json();
4625
- if (typeof json !== "object" || json === null) {
4626
- throw new Error("fetchAdlRankings: API returned non-object response");
4627
- }
4628
- const obj = json;
4629
- if (!Array.isArray(obj.rankings)) {
4630
- throw new Error("fetchAdlRankings: API response missing rankings array");
4631
- }
4632
- for (const entry of obj.rankings) {
4633
- if (typeof entry !== "object" || entry === null) {
4634
- throw new Error("fetchAdlRankings: invalid ranking entry (not an object)");
4635
- }
4636
- const r = entry;
4637
- if (typeof r.idx !== "number" || !Number.isInteger(r.idx) || r.idx < 0) {
4638
- throw new Error(`fetchAdlRankings: invalid ranking idx: ${r.idx}`);
4639
- }
4640
- }
4641
4709
  return json;
4642
4710
  }
4643
4711
 
@@ -5159,7 +5227,7 @@ import { PublicKey as PublicKey13, Transaction as Transaction2 } from "@solana/w
5159
5227
  var LIGHTHOUSE_PROGRAM_ID = new PublicKey13(
5160
5228
  "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95"
5161
5229
  );
5162
- var LIGHTHOUSE_PROGRAM_ID_STR2 = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
5230
+ var LIGHTHOUSE_PROGRAM_ID_STR = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
5163
5231
  var LIGHTHOUSE_CONSTRAINT_ADDRESS = 6400;
5164
5232
  var LIGHTHOUSE_ERROR_CODES = /* @__PURE__ */ new Set([
5165
5233
  6e3,
@@ -5205,7 +5273,7 @@ function isLighthouseInstruction(ix) {
5205
5273
  function isLighthouseError(error) {
5206
5274
  const msg = extractErrorMessage(error);
5207
5275
  if (!msg) return false;
5208
- if (msg.includes(LIGHTHOUSE_PROGRAM_ID_STR2)) return true;
5276
+ if (msg.includes(LIGHTHOUSE_PROGRAM_ID_STR)) return true;
5209
5277
  if (/custom\s+program\s+error:\s*0x1900\b/i.test(msg)) return true;
5210
5278
  if (/"Custom"\s*:\s*6400\b/.test(msg) && /InstructionError/i.test(msg)) return true;
5211
5279
  return false;
@@ -5215,18 +5283,18 @@ function isLighthouseFailureInLogs(logs) {
5215
5283
  let insideLighthouse = false;
5216
5284
  for (const line of logs) {
5217
5285
  if (typeof line !== "string") continue;
5218
- if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} invoke`)) {
5286
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {
5219
5287
  insideLighthouse = true;
5220
5288
  continue;
5221
5289
  }
5222
- if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} success`)) {
5290
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {
5223
5291
  insideLighthouse = false;
5224
5292
  continue;
5225
5293
  }
5226
5294
  if (insideLighthouse && /failed/i.test(line)) {
5227
5295
  return true;
5228
5296
  }
5229
- if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} failed`)) {
5297
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} failed`)) {
5230
5298
  return true;
5231
5299
  }
5232
5300
  }
@@ -5311,10 +5379,16 @@ function computeLiqPrice(entryPrice, capital, positionSize, maintenanceMarginBps
5311
5379
  function computePreTradeLiqPrice(oracleE6, margin, posSize, maintBps, feeBps, direction) {
5312
5380
  if (oracleE6 === 0n || margin === 0n || posSize === 0n) return 0n;
5313
5381
  const absPos = posSize < 0n ? -posSize : posSize;
5314
- const fee = absPos * feeBps / 10000n;
5315
- const effectiveCapital = margin > fee ? margin - fee : 0n;
5316
5382
  const signedPos = direction === "long" ? absPos : -absPos;
5317
- 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);
5318
5392
  }
5319
5393
  function computeTradingFee(notional, tradingFeeBps) {
5320
5394
  return notional * tradingFeeBps / 10000n;
@@ -5334,20 +5408,9 @@ function computeFeeSplit(totalFee, config) {
5334
5408
  if (config.lpBps === 0n && config.protocolBps === 0n && config.creatorBps === 0n) {
5335
5409
  return [totalFee, 0n, 0n];
5336
5410
  }
5337
- const totalBps = config.lpBps + config.protocolBps + config.creatorBps;
5338
- if (totalBps !== 10000n) {
5339
- throw new Error(
5340
- `Fee split must equal exactly 10000 bps (100%): lpBps=${config.lpBps} + protocolBps=${config.protocolBps} + creatorBps=${config.creatorBps} = ${totalBps}`
5341
- );
5342
- }
5343
5411
  const lp = totalFee * config.lpBps / 10000n;
5344
5412
  const protocol = totalFee * config.protocolBps / 10000n;
5345
5413
  const creator = totalFee - lp - protocol;
5346
- if (creator < 0n) {
5347
- throw new Error(
5348
- `Internal error: creator fee is negative (${creator}). This should not happen if lpBps + protocolBps + creatorBps === 10000.`
5349
- );
5350
- }
5351
5414
  return [lp, protocol, creator];
5352
5415
  }
5353
5416
  function computePnlPercent(pnlTokens, capital) {
@@ -5362,17 +5425,10 @@ function computePnlPercent(pnlTokens, capital) {
5362
5425
  }
5363
5426
  function computeEstimatedEntryPrice(oracleE6, tradingFeeBps, direction) {
5364
5427
  if (oracleE6 === 0n) return 0n;
5365
- if (tradingFeeBps < 0n) {
5366
- throw new Error(`computeEstimatedEntryPrice: tradingFeeBps must be non-negative, got ${tradingFeeBps}`);
5367
- }
5368
5428
  const feeImpact = oracleE6 * tradingFeeBps / 10000n;
5369
- const result = direction === "long" ? oracleE6 + feeImpact : oracleE6 - feeImpact;
5370
- if (result <= 0n) {
5371
- throw new Error(
5372
- `computeEstimatedEntryPrice: result ${result} is non-positive (tradingFeeBps=${tradingFeeBps} too high for oracle=${oracleE6})`
5373
- );
5374
- }
5375
- return result;
5429
+ if (direction === "long") return oracleE6 + feeImpact;
5430
+ const shortEntry = oracleE6 - feeImpact;
5431
+ return shortEntry > 0n ? shortEntry : 1n;
5376
5432
  }
5377
5433
  var MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
5378
5434
  var MIN_SAFE_BIGINT = BigInt(-Number.MAX_SAFE_INTEGER);
@@ -5393,12 +5449,7 @@ function computeMaxLeverage(initialMarginBps) {
5393
5449
  if (initialMarginBps <= 0n) {
5394
5450
  throw new Error("computeMaxLeverage: initialMarginBps must be positive");
5395
5451
  }
5396
- const scaledResult = 10000n * 1000000n / initialMarginBps;
5397
- return Number(scaledResult) / 1e6;
5398
- }
5399
- function computeMaxWithdrawable(capital, pnl, reservedPnl) {
5400
- const maturedPnl = pnl - reservedPnl;
5401
- return capital + (maturedPnl > 0n ? maturedPnl : 0n);
5452
+ return Number(10000n / initialMarginBps);
5402
5453
  }
5403
5454
 
5404
5455
  // src/math/warmup.ts
@@ -5410,9 +5461,6 @@ function computeWarmupUnlockedCapital(totalCapital, currentSlot, warmupStartSlot
5410
5461
  return totalCapital * elapsed / warmupPeriodSlots;
5411
5462
  }
5412
5463
  function computeWarmupLeverageCap(initialMarginBps, totalCapital, currentSlot, warmupStartSlot, warmupPeriodSlots) {
5413
- if (initialMarginBps <= 0n) {
5414
- throw new Error("computeWarmupLeverageCap: initialMarginBps must be positive");
5415
- }
5416
5464
  const maxLev = computeMaxLeverage(initialMarginBps);
5417
5465
  if (warmupPeriodSlots === 0n || warmupStartSlot === 0n) return maxLev;
5418
5466
  if (totalCapital <= 0n) return 1;
@@ -5423,14 +5471,7 @@ function computeWarmupLeverageCap(initialMarginBps, totalCapital, currentSlot, w
5423
5471
  warmupPeriodSlots
5424
5472
  );
5425
5473
  if (unlocked <= 0n) return 1;
5426
- const scaledResult = BigInt(maxLev) * unlocked / totalCapital;
5427
- if (scaledResult > BigInt(Number.MAX_SAFE_INTEGER)) {
5428
- console.warn(
5429
- `[computeWarmupLeverageCap] Warning: effective leverage ${scaledResult} exceeds MAX_SAFE_INTEGER, returning MAX_SAFE_INTEGER as a safety bound`
5430
- );
5431
- return Number.MAX_SAFE_INTEGER;
5432
- }
5433
- const effectiveLev = Number(scaledResult);
5474
+ const effectiveLev = Number(BigInt(maxLev) * unlocked / totalCapital);
5434
5475
  return Math.max(1, effectiveLev);
5435
5476
  }
5436
5477
  function computeWarmupMaxPositionSize(initialMarginBps, totalCapital, currentSlot, warmupStartSlot, warmupPeriodSlots) {
@@ -5443,41 +5484,10 @@ function computeWarmupMaxPositionSize(initialMarginBps, totalCapital, currentSlo
5443
5484
  );
5444
5485
  return unlocked * BigInt(maxLev);
5445
5486
  }
5446
- function computeWarmupProgress(currentSlot, warmupStartedAtSlot, warmupPeriodSlots, pnl, reservedPnl) {
5447
- if (warmupPeriodSlots === 0n || warmupStartedAtSlot === 0n) {
5448
- return {
5449
- maturedPnl: pnl > 0n ? pnl : 0n,
5450
- reservedPnl: 0n,
5451
- progressBps: 10000n,
5452
- // 100%
5453
- slotsRemaining: 0n
5454
- };
5455
- }
5456
- const elapsed = currentSlot >= warmupStartedAtSlot ? currentSlot - warmupStartedAtSlot : 0n;
5457
- if (elapsed >= warmupPeriodSlots) {
5458
- return {
5459
- maturedPnl: pnl > 0n ? pnl : 0n,
5460
- reservedPnl: 0n,
5461
- progressBps: 10000n,
5462
- // 100%
5463
- slotsRemaining: 0n
5464
- };
5465
- }
5466
- const progressBps = elapsed * 10000n / warmupPeriodSlots;
5467
- const slotsRemaining = warmupPeriodSlots - elapsed;
5468
- const maturedPnl = pnl > 0n ? pnl * progressBps / 10000n : 0n;
5469
- const locked = reservedPnl > 0n ? reservedPnl : 0n;
5470
- return {
5471
- maturedPnl,
5472
- reservedPnl: locked,
5473
- progressBps,
5474
- slotsRemaining
5475
- };
5476
- }
5477
5487
 
5478
5488
  // src/validation.ts
5479
5489
  import { PublicKey as PublicKey14 } from "@solana/web3.js";
5480
- var U16_MAX = 65535;
5490
+ var U16_MAX2 = 65535;
5481
5491
  var U64_MAX = BigInt("18446744073709551615");
5482
5492
  var I64_MIN = BigInt("-9223372036854775808");
5483
5493
  var I64_MAX = BigInt("9223372036854775807");
@@ -5517,26 +5527,24 @@ function validatePublicKey(value, field) {
5517
5527
  function validateIndex(value, field) {
5518
5528
  const t = requireDecimalUIntString(value, field);
5519
5529
  const bi = BigInt(t);
5520
- if (bi > BigInt(U16_MAX)) {
5530
+ if (bi > BigInt(U16_MAX2)) {
5521
5531
  throw new ValidationError(
5522
5532
  field,
5523
- `must be <= ${U16_MAX} (u16 max), got ${t}`
5533
+ `must be <= ${U16_MAX2} (u16 max), got ${t}`
5524
5534
  );
5525
5535
  }
5526
- if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5527
- throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);
5528
- }
5529
5536
  return Number(bi);
5530
5537
  }
5531
5538
  function validateAmount(value, field) {
5532
- const t = value.trim();
5533
- if (!/^(0|[1-9]\d*)$/.test(t)) {
5539
+ let num;
5540
+ try {
5541
+ num = BigInt(value);
5542
+ } catch {
5534
5543
  throw new ValidationError(
5535
5544
  field,
5536
- `"${value}" is not a valid non-negative integer. Use decimal digits only.`
5545
+ `"${value}" is not a valid number. Use decimal digits only.`
5537
5546
  );
5538
5547
  }
5539
- const num = BigInt(t);
5540
5548
  if (num < 0n) {
5541
5549
  throw new ValidationError(field, `must be non-negative, got ${num}`);
5542
5550
  }
@@ -5549,14 +5557,15 @@ function validateAmount(value, field) {
5549
5557
  return num;
5550
5558
  }
5551
5559
  function validateU128(value, field) {
5552
- const t = value.trim();
5553
- if (!/^(0|[1-9]\d*)$/.test(t)) {
5560
+ let num;
5561
+ try {
5562
+ num = BigInt(value);
5563
+ } catch {
5554
5564
  throw new ValidationError(
5555
5565
  field,
5556
- `"${value}" is not a valid non-negative integer. Use decimal digits only.`
5566
+ `"${value}" is not a valid number. Use decimal digits only.`
5557
5567
  );
5558
5568
  }
5559
- const num = BigInt(t);
5560
5569
  if (num < 0n) {
5561
5570
  throw new ValidationError(field, `must be non-negative, got ${num}`);
5562
5571
  }
@@ -5569,14 +5578,15 @@ function validateU128(value, field) {
5569
5578
  return num;
5570
5579
  }
5571
5580
  function validateI64(value, field) {
5572
- const t = value.trim();
5573
- if (!/^-?(0|[1-9]\d*)$/.test(t)) {
5581
+ let num;
5582
+ try {
5583
+ num = BigInt(value);
5584
+ } catch {
5574
5585
  throw new ValidationError(
5575
5586
  field,
5576
- `"${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.`
5577
5588
  );
5578
5589
  }
5579
- const num = BigInt(t);
5580
5590
  if (num < I64_MIN) {
5581
5591
  throw new ValidationError(
5582
5592
  field,
@@ -5592,14 +5602,15 @@ function validateI64(value, field) {
5592
5602
  return num;
5593
5603
  }
5594
5604
  function validateI128(value, field) {
5595
- const t = value.trim();
5596
- if (!/^-?(0|[1-9]\d*)$/.test(t)) {
5605
+ let num;
5606
+ try {
5607
+ num = BigInt(value);
5608
+ } catch {
5597
5609
  throw new ValidationError(
5598
5610
  field,
5599
- `"${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.`
5600
5612
  );
5601
5613
  }
5602
- const num = BigInt(t);
5603
5614
  if (num < I128_MIN) {
5604
5615
  throw new ValidationError(
5605
5616
  field,
@@ -5623,9 +5634,6 @@ function validateBps(value, field) {
5623
5634
  `must be <= 10000 (100%), got ${t}`
5624
5635
  );
5625
5636
  }
5626
- if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5627
- throw new ValidationError(field, `internal error: bps value exceeds MAX_SAFE_INTEGER`);
5628
- }
5629
5637
  return Number(bi);
5630
5638
  }
5631
5639
  function validateU64(value, field) {
@@ -5634,15 +5642,12 @@ function validateU64(value, field) {
5634
5642
  function validateU16(value, field) {
5635
5643
  const t = requireDecimalUIntString(value, field);
5636
5644
  const bi = BigInt(t);
5637
- if (bi > BigInt(U16_MAX)) {
5645
+ if (bi > BigInt(U16_MAX2)) {
5638
5646
  throw new ValidationError(
5639
5647
  field,
5640
- `must be <= ${U16_MAX} (u16 max), got ${t}`
5648
+ `must be <= ${U16_MAX2} (u16 max), got ${t}`
5641
5649
  );
5642
5650
  }
5643
- if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5644
- throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);
5645
- }
5646
5651
  return Number(bi);
5647
5652
  }
5648
5653
 
@@ -5693,9 +5698,7 @@ function parseDexScreenerPairs(json) {
5693
5698
  else if (liquidity > 1e4) confidence = 60;
5694
5699
  else if (liquidity > 1e3) confidence = 45;
5695
5700
  const priceUsd = pair.priceUsd;
5696
- const rawPrice = typeof priceUsd === "string" || typeof priceUsd === "number" ? parseFloat(String(priceUsd)) : NaN;
5697
- if (!Number.isFinite(rawPrice) || rawPrice <= 0) continue;
5698
- const price = rawPrice;
5701
+ const price = typeof priceUsd === "string" || typeof priceUsd === "number" ? parseFloat(String(priceUsd)) || 0 : 0;
5699
5702
  let baseSym = "?";
5700
5703
  let quoteSym = "?";
5701
5704
  if (isRecord(pair.baseToken) && typeof pair.baseToken.symbol === "string") {
@@ -5726,8 +5729,8 @@ function parseJupiterMintEntry(json, mint) {
5726
5729
  if (!isRecord(row)) return null;
5727
5730
  const rawPrice = row.price;
5728
5731
  if (rawPrice === void 0 || rawPrice === null) return null;
5729
- const price = parseFloat(String(rawPrice));
5730
- if (!Number.isFinite(price) || price <= 0) return null;
5732
+ const price = parseFloat(String(rawPrice)) || 0;
5733
+ if (price <= 0) return null;
5731
5734
  let mintSymbol = "?";
5732
5735
  if (typeof row.mintSymbol === "string") mintSymbol = row.mintSymbol;
5733
5736
  return { price, mintSymbol };
@@ -5793,17 +5796,10 @@ async function fetchDexSources(mint, signal) {
5793
5796
  headers: { "User-Agent": "percolator/1.0" }
5794
5797
  }
5795
5798
  );
5796
- if (!resp.ok) {
5797
- console.debug(`[fetchDexSources] HTTP ${resp.status} for mint ${mint}`);
5798
- return [];
5799
- }
5799
+ if (!resp.ok) return [];
5800
5800
  const json = await resp.json();
5801
5801
  return parseDexScreenerPairs(json);
5802
- } catch (err) {
5803
- console.warn(
5804
- `[fetchDexSources] Error fetching DexScreener data for mint ${mint}:`,
5805
- err instanceof Error ? err.message : String(err)
5806
- );
5802
+ } catch {
5807
5803
  return [];
5808
5804
  }
5809
5805
  }
@@ -5814,7 +5810,7 @@ function lookupPythSource(mint) {
5814
5810
  type: "pyth",
5815
5811
  address: entry.feedId,
5816
5812
  pairLabel: `${entry.symbol} / USD (Pyth)`,
5817
- liquidity: Number.MAX_SAFE_INTEGER,
5813
+ liquidity: Infinity,
5818
5814
  // Pyth is considered deep liquidity
5819
5815
  price: 0,
5820
5816
  // We don't fetch live price here; caller can enrich
@@ -5831,16 +5827,10 @@ async function fetchJupiterSource(mint, signal) {
5831
5827
  headers: { "User-Agent": "percolator/1.0" }
5832
5828
  }
5833
5829
  );
5834
- if (!resp.ok) {
5835
- console.debug(`[fetchJupiterSource] HTTP ${resp.status} for mint ${mint}`);
5836
- return null;
5837
- }
5830
+ if (!resp.ok) return null;
5838
5831
  const json = await resp.json();
5839
5832
  const row = parseJupiterMintEntry(json, mint);
5840
- if (!row) {
5841
- console.debug(`[fetchJupiterSource] No price data from Jupiter for mint ${mint}`);
5842
- return null;
5843
- }
5833
+ if (!row) return null;
5844
5834
  return {
5845
5835
  type: "jupiter",
5846
5836
  address: mint,
@@ -5851,39 +5841,23 @@ async function fetchJupiterSource(mint, signal) {
5851
5841
  confidence: 40
5852
5842
  // Fallback — lower confidence
5853
5843
  };
5854
- } catch (err) {
5855
- console.warn(
5856
- `[fetchJupiterSource] Error fetching Jupiter data for mint ${mint}:`,
5857
- err instanceof Error ? err.message : String(err)
5858
- );
5844
+ } catch {
5859
5845
  return null;
5860
5846
  }
5861
5847
  }
5862
5848
  async function resolvePrice(mint, signal, options) {
5863
5849
  const timeoutMs = options?.timeoutMs ?? DEFAULT_RESOLVE_TIMEOUT_MS;
5864
5850
  const timeoutSignal = AbortSignal.timeout(timeoutMs);
5865
- const effectiveSignal2 = signal ? combineAbortSignals([signal, timeoutSignal]) : timeoutSignal;
5851
+ const combinedSignal = signal ? combineAbortSignals([signal, timeoutSignal]) : timeoutSignal;
5866
5852
  const [dexSources, jupiterSource] = await Promise.all([
5867
- fetchDexSources(mint, effectiveSignal2),
5868
- fetchJupiterSource(mint, effectiveSignal2)
5853
+ fetchDexSources(mint, combinedSignal),
5854
+ fetchJupiterSource(mint, combinedSignal)
5869
5855
  ]);
5870
5856
  const pythSource = lookupPythSource(mint);
5871
5857
  const allSources = [];
5872
5858
  if (pythSource) {
5873
- const dexPrice = dexSources[0]?.price ?? 0;
5874
- const jupPrice = jupiterSource?.price ?? 0;
5875
- if (dexPrice > 0 && jupPrice > 0) {
5876
- const mid = (dexPrice + jupPrice) / 2;
5877
- const deviation = Math.abs(dexPrice - jupPrice) / mid;
5878
- if (deviation > 0.5) {
5879
- pythSource.price = 0;
5880
- pythSource.confidence = 20;
5881
- } else {
5882
- pythSource.price = mid;
5883
- }
5884
- } else {
5885
- pythSource.price = dexPrice || jupPrice || 0;
5886
- }
5859
+ const refPrice = dexSources[0]?.price || jupiterSource?.price || 0;
5860
+ pythSource.price = refPrice;
5887
5861
  allSources.push(pythSource);
5888
5862
  }
5889
5863
  allSources.push(...dexSources);
@@ -5908,7 +5882,9 @@ export {
5908
5882
  ACCOUNTS_CLOSE_ACCOUNT,
5909
5883
  ACCOUNTS_CLOSE_SLAB,
5910
5884
  ACCOUNTS_CLOSE_STALE_SLABS,
5885
+ ACCOUNTS_CREATE_INSURANCE_MINT,
5911
5886
  ACCOUNTS_DEPOSIT_COLLATERAL,
5887
+ ACCOUNTS_DEPOSIT_INSURANCE_LP,
5912
5888
  ACCOUNTS_EXECUTE_ADL,
5913
5889
  ACCOUNTS_FUND_MARKET_INSURANCE,
5914
5890
  ACCOUNTS_INIT_LP,
@@ -5924,6 +5900,7 @@ export {
5924
5900
  ACCOUNTS_QUEUE_WITHDRAWAL,
5925
5901
  ACCOUNTS_RECLAIM_SLAB_RENT,
5926
5902
  ACCOUNTS_RESOLVE_MARKET,
5903
+ ACCOUNTS_SET_DEX_POOL,
5927
5904
  ACCOUNTS_SET_INSURANCE_ISOLATION,
5928
5905
  ACCOUNTS_SET_MAINTENANCE_FEE,
5929
5906
  ACCOUNTS_SET_OI_IMBALANCE_HARD_BLOCK,
@@ -5941,11 +5918,11 @@ export {
5941
5918
  ACCOUNTS_UPDATE_CONFIG,
5942
5919
  ACCOUNTS_WITHDRAW_COLLATERAL,
5943
5920
  ACCOUNTS_WITHDRAW_INSURANCE,
5921
+ ACCOUNTS_WITHDRAW_INSURANCE_LP,
5944
5922
  AccountKind,
5945
5923
  CHAINLINK_ANSWER_OFFSET,
5946
5924
  CHAINLINK_DECIMALS_OFFSET,
5947
5925
  CHAINLINK_MIN_SIZE,
5948
- CHAINLINK_TIMESTAMP_OFFSET,
5949
5926
  CREATOR_LOCK_SEED,
5950
5927
  CTX_VAMM_OFFSET,
5951
5928
  DEFAULT_OI_RAMP_SLOTS,
@@ -5955,7 +5932,7 @@ export {
5955
5932
  LIGHTHOUSE_CONSTRAINT_ADDRESS,
5956
5933
  LIGHTHOUSE_ERROR_CODES,
5957
5934
  LIGHTHOUSE_PROGRAM_ID,
5958
- LIGHTHOUSE_PROGRAM_ID_STR2 as LIGHTHOUSE_PROGRAM_ID_STR,
5935
+ LIGHTHOUSE_PROGRAM_ID_STR,
5959
5936
  LIGHTHOUSE_USER_MESSAGE,
5960
5937
  MARK_PRICE_EMA_ALPHA_E6,
5961
5938
  MARK_PRICE_EMA_WINDOW_SLOTS,
@@ -6021,7 +5998,6 @@ export {
6021
5998
  computeLiqPrice,
6022
5999
  computeMarkPnl,
6023
6000
  computeMaxLeverage,
6024
- computeMaxWithdrawable,
6025
6001
  computePnlPercent,
6026
6002
  computePreTradeLiqPrice,
6027
6003
  computeRequiredMargin,
@@ -6029,7 +6005,6 @@ export {
6029
6005
  computeVammQuote,
6030
6006
  computeWarmupLeverageCap,
6031
6007
  computeWarmupMaxPositionSize,
6032
- computeWarmupProgress,
6033
6008
  computeWarmupUnlockedCapital,
6034
6009
  concatBytes,
6035
6010
  countLighthouseInstructions,
@@ -6038,6 +6013,7 @@ export {
6038
6013
  depositAccounts,
6039
6014
  deriveCreatorLockPda,
6040
6015
  deriveDepositPda,
6016
+ deriveInsuranceLpMint,
6041
6017
  deriveLpPda,
6042
6018
  derivePythPriceUpdateAccount,
6043
6019
  derivePythPushOraclePDA,
@@ -6076,8 +6052,10 @@ export {
6076
6052
  encodeCloseOrphanSlab,
6077
6053
  encodeCloseSlab,
6078
6054
  encodeCloseStaleSlabs,
6055
+ encodeCreateInsuranceMint,
6079
6056
  encodeCreateLpVault,
6080
6057
  encodeDepositCollateral,
6058
+ encodeDepositInsuranceLP,
6081
6059
  encodeDepositLpCollateral,
6082
6060
  encodeExecuteAdl,
6083
6061
  encodeForceCloseResolved,
@@ -6147,6 +6125,7 @@ export {
6147
6125
  encodeUpdateRiskParams,
6148
6126
  encodeWithdrawCollateral,
6149
6127
  encodeWithdrawInsurance,
6128
+ encodeWithdrawInsuranceLP,
6150
6129
  encodeWithdrawInsuranceLimited,
6151
6130
  encodeWithdrawLpCollateral,
6152
6131
  fetchAdlRankedPositions,
@@ -6168,7 +6147,6 @@ export {
6168
6147
  initPoolAccounts,
6169
6148
  isAccountUsed,
6170
6149
  isAdlTriggered,
6171
- isAnchorErrorCode,
6172
6150
  isLighthouseError,
6173
6151
  isLighthouseFailureInLogs,
6174
6152
  isLighthouseInstruction,