@percolatorct/sdk 1.0.0-beta.20 → 1.0.0-beta.22

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,12 +1679,12 @@ 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;
1648
1686
  var V12_15_ENGINE_CURRENT_SLOT_OFF = 224;
1649
1687
  var V12_15_ENGINE_FUNDING_RATE_E9_OFF = 240;
1650
- var V12_15_ENGINE_MARKET_MODE_OFF = 256;
1651
1688
  var V12_15_ENGINE_C_TOT_OFF = 344;
1652
1689
  var V12_15_ENGINE_PNL_POS_TOT_OFF = 368;
1653
1690
  var V12_15_ENGINE_PNL_MATURED_POS_TOT_OFF = 384;
@@ -1739,6 +1776,14 @@ for (const [, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Large",
1739
1776
  const total = V12_1_SBF_ENGINE_OFF + accountsOff + n * V12_1_SBF_ACCOUNT_SIZE;
1740
1777
  V12_1_SIZES.set(total, n);
1741
1778
  }
1779
+ var V12_1_EP_SIZES = /* @__PURE__ */ new Map();
1780
+ for (const [, n] of [["Micro", 64], ["Small", 256], ["Medium", 1024], ["Large", 4096]]) {
1781
+ const bitmapBytes = Math.ceil(n / 64) * 8;
1782
+ const preAccLen = V12_1_SBF_BITMAP_OFF + bitmapBytes + 18 + n * 2;
1783
+ const accountsOff = Math.ceil(preAccLen / 8) * 8;
1784
+ const total = V12_1_SBF_ENGINE_OFF + accountsOff + n * V12_1_EP_SBF_ACCOUNT_SIZE;
1785
+ V12_1_EP_SIZES.set(total, n);
1786
+ }
1742
1787
  var SLAB_TIERS_V2 = {
1743
1788
  small: { maxAccounts: 256, dataSize: 65088, label: "Small", description: "256 slots (V2 BPF intermediate)" },
1744
1789
  large: { maxAccounts: 4096, dataSize: 1025568, label: "Large", description: "4,096 slots (V2 BPF intermediate)" }
@@ -2304,16 +2349,12 @@ function buildLayoutV12_1(maxAccounts, dataLen) {
2304
2349
  engineLastFundingSlotOff: isSbf ? -1 : V12_1_ENGINE_LAST_FUNDING_SLOT_OFF,
2305
2350
  // not in deployed struct
2306
2351
  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
2352
+ engineMarkPriceOff: isSbf ? V12_1_SBF_OFF_MARK_PRICE_E6 : V12_1_ENGINE_MARK_PRICE_OFF,
2309
2353
  engineLastCrankSlotOff: isSbf ? V12_1_SBF_OFF_LAST_CRANK_SLOT : V12_1_ENGINE_LAST_CRANK_SLOT_OFF,
2310
2354
  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
2355
+ engineTotalOiOff: isSbf ? V12_1_SBF_OFF_TOTAL_OI : V12_1_ENGINE_TOTAL_OI_OFF,
2356
+ engineLongOiOff: isSbf ? V12_1_SBF_OFF_LONG_OI : V12_1_ENGINE_LONG_OI_OFF,
2357
+ engineShortOiOff: isSbf ? V12_1_SBF_OFF_SHORT_OI : V12_1_ENGINE_SHORT_OI_OFF,
2317
2358
  engineCTotOff: isSbf ? V12_1_SBF_OFF_C_TOT : V12_1_ENGINE_C_TOT_OFF,
2318
2359
  enginePnlPosTotOff: isSbf ? V12_1_SBF_OFF_PNL_POS_TOT : V12_1_ENGINE_PNL_POS_TOT_OFF,
2319
2360
  engineLiqCursorOff: isSbf ? V12_1_SBF_OFF_LIQ_CURSOR : V12_1_ENGINE_LIQ_CURSOR_OFF,
@@ -2349,6 +2390,71 @@ function buildLayoutV12_1(maxAccounts, dataLen) {
2349
2390
  engineInsuranceIsolationBpsOff: isSbf ? -1 : 64
2350
2391
  };
2351
2392
  }
2393
+ function buildLayoutV12_1EP(maxAccounts) {
2394
+ const engineOff = V12_1_SBF_ENGINE_OFF;
2395
+ const bitmapOff = V12_1_SBF_BITMAP_OFF;
2396
+ const accountSize = V12_1_EP_SBF_ACCOUNT_SIZE;
2397
+ const bitmapWords = Math.ceil(maxAccounts / 64);
2398
+ const bitmapBytes = bitmapWords * 8;
2399
+ const postBitmap = 18;
2400
+ const nextFreeBytes = maxAccounts * 2;
2401
+ const preAccountsLen = bitmapOff + bitmapBytes + postBitmap + nextFreeBytes;
2402
+ const accountsOffRel = Math.ceil(preAccountsLen / 8) * 8;
2403
+ return {
2404
+ version: 1,
2405
+ headerLen: 72,
2406
+ configOffset: 72,
2407
+ configLen: 544,
2408
+ reservedOff: 80,
2409
+ // V1_RESERVED_OFF
2410
+ engineOff,
2411
+ accountSize,
2412
+ maxAccounts,
2413
+ bitmapWords,
2414
+ accountsOff: engineOff + accountsOffRel,
2415
+ engineInsuranceOff: 16,
2416
+ engineParamsOff: 32,
2417
+ // V12_1_ENGINE_PARAMS_OFF_SBF
2418
+ paramsSize: 184,
2419
+ // V12_1_PARAMS_SIZE_SBF
2420
+ // Engine offsets identical to V12_1 SBF
2421
+ engineCurrentSlotOff: V12_1_SBF_OFF_CURRENT_SLOT,
2422
+ engineFundingIndexOff: -1,
2423
+ engineLastFundingSlotOff: -1,
2424
+ engineFundingRateBpsOff: V12_1_SBF_OFF_FUNDING_RATE,
2425
+ engineMarkPriceOff: V12_1_SBF_OFF_MARK_PRICE_E6,
2426
+ engineLastCrankSlotOff: V12_1_SBF_OFF_LAST_CRANK_SLOT,
2427
+ engineMaxCrankStalenessOff: V12_1_SBF_OFF_MAX_CRANK_STALENESS,
2428
+ engineTotalOiOff: V12_1_SBF_OFF_TOTAL_OI,
2429
+ engineLongOiOff: V12_1_SBF_OFF_LONG_OI,
2430
+ engineShortOiOff: V12_1_SBF_OFF_SHORT_OI,
2431
+ engineCTotOff: V12_1_SBF_OFF_C_TOT,
2432
+ enginePnlPosTotOff: V12_1_SBF_OFF_PNL_POS_TOT,
2433
+ engineLiqCursorOff: V12_1_SBF_OFF_LIQ_CURSOR,
2434
+ engineGcCursorOff: V12_1_SBF_OFF_GC_CURSOR,
2435
+ engineLastSweepStartOff: V12_1_SBF_OFF_LAST_SWEEP_START,
2436
+ engineLastSweepCompleteOff: V12_1_SBF_OFF_LAST_SWEEP_COMPLETE,
2437
+ engineCrankCursorOff: V12_1_SBF_OFF_CRANK_CURSOR,
2438
+ engineSweepStartIdxOff: V12_1_SBF_OFF_SWEEP_START_IDX,
2439
+ engineLifetimeLiquidationsOff: V12_1_SBF_OFF_LIFETIME_LIQUIDATIONS,
2440
+ engineLifetimeForceClosesOff: -1,
2441
+ engineNetLpPosOff: -1,
2442
+ engineLpSumAbsOff: -1,
2443
+ engineLpMaxAbsOff: -1,
2444
+ engineLpMaxAbsSweepOff: -1,
2445
+ engineEmergencyOiModeOff: -1,
2446
+ engineEmergencyStartSlotOff: -1,
2447
+ engineLastBreakerSlotOff: -1,
2448
+ engineBitmapOff: bitmapOff,
2449
+ postBitmap: 18,
2450
+ // Account offsets — shifted +8 from V12_1 due to entry_price insertion
2451
+ acctOwnerOff: V12_1_EP_ACCT_OWNER_OFF,
2452
+ // 216 (was 208)
2453
+ hasInsuranceIsolation: false,
2454
+ engineInsuranceIsolatedOff: -1,
2455
+ engineInsuranceIsolationBpsOff: -1
2456
+ };
2457
+ }
2352
2458
  function buildLayoutV12_15(maxAccounts, dataLen) {
2353
2459
  const isSbf = dataLen === 237512;
2354
2460
  const accountSize = isSbf ? V12_15_ACCOUNT_SIZE_SMALL : V12_15_ACCOUNT_SIZE;
@@ -2364,7 +2470,7 @@ function buildLayoutV12_15(maxAccounts, dataLen) {
2364
2470
  return {
2365
2471
  version: 2,
2366
2472
  headerLen: V0_HEADER_LEN,
2367
- // 72 (same as V12_1)
2473
+ // 72
2368
2474
  configOffset: V0_HEADER_LEN,
2369
2475
  // 72
2370
2476
  configLen: 552,
@@ -2387,14 +2493,12 @@ function buildLayoutV12_15(maxAccounts, dataLen) {
2387
2493
  // not present in v12.15 engine struct
2388
2494
  engineLastFundingSlotOff: -1,
2389
2495
  // 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
2496
  engineFundingRateBpsOff: isSbf ? 224 : V12_15_ENGINE_FUNDING_RATE_E9_OFF,
2393
2497
  // SBF=224, native=240
2394
2498
  engineMarkPriceOff: -1,
2395
- // not present in v12.15 (removed with oracle refactor)
2499
+ // not present in v12.15
2396
2500
  engineLastCrankSlotOff: -1,
2397
- // not yet mapped; set -1 until offset verified on-chain
2501
+ // not yet mapped
2398
2502
  engineMaxCrankStalenessOff: -1,
2399
2503
  // not yet mapped
2400
2504
  engineTotalOiOff: -1,
@@ -2443,7 +2547,6 @@ function buildLayoutV12_15(maxAccounts, dataLen) {
2443
2547
  acctOwnerOff: V12_15_ACCT_OWNER_OFF,
2444
2548
  // 192
2445
2549
  hasInsuranceIsolation: false,
2446
- // InsuranceFund = {balance: u128} = 16 bytes in v12.15
2447
2550
  engineInsuranceIsolatedOff: -1,
2448
2551
  engineInsuranceIsolationBpsOff: -1
2449
2552
  };
@@ -2451,6 +2554,8 @@ function buildLayoutV12_15(maxAccounts, dataLen) {
2451
2554
  function detectSlabLayout(dataLen, data) {
2452
2555
  const v1215n = V12_15_SIZES.get(dataLen);
2453
2556
  if (v1215n !== void 0) return buildLayoutV12_15(v1215n, dataLen);
2557
+ const v121epn = V12_1_EP_SIZES.get(dataLen);
2558
+ if (v121epn !== void 0) return buildLayoutV12_1EP(v121epn);
2454
2559
  const v121n = V12_1_SIZES.get(dataLen);
2455
2560
  if (v121n !== void 0) return buildLayoutV12_1(v121n, dataLen);
2456
2561
  const vsdpn = V_SETDEXPOOL_SIZES.get(dataLen);
@@ -2497,6 +2602,15 @@ var PARAMS_LIQUIDATION_FEE_BPS_OFF = 96;
2497
2602
  var PARAMS_LIQUIDATION_FEE_CAP_OFF = 104;
2498
2603
  var PARAMS_LIQUIDATION_BUFFER_OFF = 120;
2499
2604
  var PARAMS_MIN_LIQUIDATION_OFF = 128;
2605
+ var V12_1_PARAMS_MAINT_FEE_OFF = 56;
2606
+ var V12_1_PARAMS_MAX_CRANK_OFF = 72;
2607
+ var V12_1_PARAMS_LIQ_FEE_BPS_OFF = 80;
2608
+ var V12_1_PARAMS_LIQ_FEE_CAP_OFF = 88;
2609
+ var V12_1_PARAMS_MIN_LIQ_OFF = 104;
2610
+ var V12_1_PARAMS_MIN_INITIAL_DEP_OFF = 120;
2611
+ var V12_1_PARAMS_MIN_NZ_MM_OFF = 136;
2612
+ var V12_1_PARAMS_MIN_NZ_IM_OFF = 152;
2613
+ var V12_1_PARAMS_INS_FLOOR_OFF = 168;
2500
2614
  var ACCT_ACCOUNT_ID_OFF = 0;
2501
2615
  var ACCT_CAPITAL_OFF = 8;
2502
2616
  var ACCT_KIND_OFF = 24;
@@ -2747,14 +2861,15 @@ function parseParams(data, layoutHint) {
2747
2861
  throw new Error("Slab data too short for RiskParams");
2748
2862
  }
2749
2863
  const isV12_15Params = paramsSize === V12_15_PARAMS_SIZE || paramsSize === 184;
2864
+ const isV12_1Sbf = !isV12_15Params && layout !== null && layout !== void 0 && layout.engineOff === V12_1_SBF_ENGINE_OFF && paramsSize === 184;
2750
2865
  const result = {
2751
2866
  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),
2867
+ maintenanceMarginBps: isV12_15Params ? readU64LE(data, base + 0) : readU64LE(data, base + PARAMS_MAINTENANCE_MARGIN_OFF),
2868
+ initialMarginBps: isV12_15Params ? readU64LE(data, base + 8) : readU64LE(data, base + PARAMS_INITIAL_MARGIN_OFF),
2869
+ tradingFeeBps: isV12_15Params ? readU64LE(data, base + 16) : readU64LE(data, base + PARAMS_TRADING_FEE_OFF),
2755
2870
  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)
2871
+ newAccountFee: isV12_15Params ? readU128LE(data, base + 32) : readU128LE(data, base + PARAMS_NEW_ACCOUNT_FEE_OFF),
2872
+ // Extended params: defaults; overwritten below if layout supports them
2758
2873
  riskReductionThreshold: 0n,
2759
2874
  maintenanceFeePerSlot: 0n,
2760
2875
  maxCrankStalenessSlots: 0n,
@@ -2762,12 +2877,17 @@ function parseParams(data, layoutHint) {
2762
2877
  liquidationFeeCap: 0n,
2763
2878
  liquidationBufferBps: 0n,
2764
2879
  minLiquidationAbs: 0n,
2880
+ minInitialDeposit: 0n,
2881
+ minNonzeroMmReq: 0n,
2882
+ minNonzeroImReq: 0n,
2883
+ insuranceFloor: 0n,
2765
2884
  hMin: 0n,
2766
2885
  hMax: 0n
2767
2886
  };
2768
2887
  if (isV12_15Params) {
2769
2888
  result.hMin = readU64LE(data, base + V12_15_PARAMS_H_MIN_OFF);
2770
2889
  result.hMax = readU64LE(data, base + V12_15_PARAMS_H_MAX_OFF);
2890
+ result.insuranceFloor = readU128LE(data, base + V12_15_PARAMS_INSURANCE_FLOOR_OFF);
2771
2891
  result.riskReductionThreshold = 0n;
2772
2892
  result.maintenanceFeePerSlot = 0n;
2773
2893
  result.maxCrankStalenessSlots = readU64LE(data, base + 48);
@@ -2775,6 +2895,21 @@ function parseParams(data, layoutHint) {
2775
2895
  result.liquidationFeeCap = readU128LE(data, base + 64);
2776
2896
  result.liquidationBufferBps = 0n;
2777
2897
  result.minLiquidationAbs = readU128LE(data, base + 80);
2898
+ result.minInitialDeposit = readU128LE(data, base + 96);
2899
+ result.minNonzeroMmReq = readU128LE(data, base + 112);
2900
+ result.minNonzeroImReq = readU128LE(data, base + 128);
2901
+ } else if (isV12_1Sbf) {
2902
+ result.maintenanceFeePerSlot = readU128LE(data, base + V12_1_PARAMS_MAINT_FEE_OFF);
2903
+ result.maxCrankStalenessSlots = readU64LE(data, base + V12_1_PARAMS_MAX_CRANK_OFF);
2904
+ result.liquidationFeeBps = readU64LE(data, base + V12_1_PARAMS_LIQ_FEE_BPS_OFF);
2905
+ result.liquidationFeeCap = readU128LE(data, base + V12_1_PARAMS_LIQ_FEE_CAP_OFF);
2906
+ result.minLiquidationAbs = readU128LE(data, base + V12_1_PARAMS_MIN_LIQ_OFF);
2907
+ result.minInitialDeposit = readU128LE(data, base + V12_1_PARAMS_MIN_INITIAL_DEP_OFF);
2908
+ result.minNonzeroMmReq = readU128LE(data, base + V12_1_PARAMS_MIN_NZ_MM_OFF);
2909
+ result.minNonzeroImReq = readU128LE(data, base + V12_1_PARAMS_MIN_NZ_IM_OFF);
2910
+ result.insuranceFloor = readU128LE(data, base + V12_1_PARAMS_INS_FLOOR_OFF);
2911
+ result.hMin = result.warmupPeriodSlots;
2912
+ result.hMax = result.warmupPeriodSlots;
2778
2913
  } else if (paramsSize >= 144) {
2779
2914
  result.riskReductionThreshold = readU128LE(data, base + PARAMS_RISK_THRESHOLD_OFF);
2780
2915
  result.maintenanceFeePerSlot = readU128LE(data, base + PARAMS_MAINTENANCE_FEE_OFF);
@@ -2794,7 +2929,7 @@ function parseEngine(data) {
2794
2929
  throw new Error(`Unrecognized slab data length: ${data.length}. Cannot determine layout version.`);
2795
2930
  }
2796
2931
  const base = layout.engineOff;
2797
- const isV12_15 = layout.accountSize === V12_15_ACCOUNT_SIZE || layout.accountSize === V12_15_ACCOUNT_SIZE_SMALL;
2932
+ const isV12_15 = (layout.accountSize === V12_15_ACCOUNT_SIZE || layout.accountSize === V12_15_ACCOUNT_SIZE_SMALL) && (layout.engineOff === V12_15_ENGINE_OFF || layout.engineOff === V12_15_ENGINE_OFF_SBF);
2798
2933
  const fundingRateBpsPerSlotLast = isV12_15 ? readI128LE(data, base + layout.engineFundingRateBpsOff) : readI64LE(data, base + layout.engineFundingRateBpsOff);
2799
2934
  return {
2800
2935
  vault: readU128LE(data, base),
@@ -2810,22 +2945,22 @@ function parseEngine(data) {
2810
2945
  lastFundingSlot: layout.engineLastFundingSlotOff >= 0 ? readU64LE(data, base + layout.engineLastFundingSlotOff) : 0n,
2811
2946
  fundingRateBpsPerSlotLast,
2812
2947
  fundingRateE9: isV12_15 ? readI128LE(data, base + layout.engineFundingRateBpsOff) : 0n,
2813
- 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,
2948
+ marketMode: isV12_15 ? readU8(data, base + layout.engineFundingRateBpsOff + 16) === 1 ? 1 : 0 : null,
2949
+ lastCrankSlot: readU64LE(data, base + layout.engineLastCrankSlotOff),
2950
+ maxCrankStalenessSlots: readU64LE(data, base + layout.engineMaxCrankStalenessOff),
2816
2951
  totalOpenInterest: layout.engineTotalOiOff >= 0 ? readU128LE(data, base + layout.engineTotalOiOff) : 0n,
2817
2952
  longOi: layout.engineLongOiOff >= 0 ? readU128LE(data, base + layout.engineLongOiOff) : 0n,
2818
2953
  shortOi: layout.engineShortOiOff >= 0 ? readU128LE(data, base + layout.engineShortOiOff) : 0n,
2819
2954
  cTot: readU128LE(data, base + layout.engineCTotOff),
2820
2955
  pnlPosTot: readU128LE(data, base + layout.enginePnlPosTotOff),
2821
2956
  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,
2957
+ liqCursor: readU16LE(data, base + layout.engineLiqCursorOff),
2958
+ gcCursor: readU16LE(data, base + layout.engineGcCursorOff),
2959
+ lastSweepStartSlot: readU64LE(data, base + layout.engineLastSweepStartOff),
2960
+ lastSweepCompleteSlot: readU64LE(data, base + layout.engineLastSweepCompleteOff),
2961
+ crankCursor: readU16LE(data, base + layout.engineCrankCursorOff),
2962
+ sweepStartIdx: readU16LE(data, base + layout.engineSweepStartIdxOff),
2963
+ lifetimeLiquidations: readU64LE(data, base + layout.engineLifetimeLiquidationsOff),
2829
2964
  lifetimeForceCloses: layout.engineLifetimeForceClosesOff >= 0 ? readU64LE(data, base + layout.engineLifetimeForceClosesOff) : 0n,
2830
2965
  netLpPos: layout.engineNetLpPosOff >= 0 ? readI128LE(data, base + layout.engineNetLpPosOff) : 0n,
2831
2966
  lpSumAbs: layout.engineLpSumAbsOff >= 0 ? readU128LE(data, base + layout.engineLpSumAbsOff) : 0n,
@@ -2896,8 +3031,9 @@ function parseAccount(data, idx) {
2896
3031
  throw new Error("Slab data too short for account");
2897
3032
  }
2898
3033
  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);
3034
+ const isV12_1EP = !isV12_15 && layout.accountSize === V12_1_EP_SBF_ACCOUNT_SIZE && layout.engineOff === V12_1_SBF_ENGINE_OFF;
3035
+ 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);
3036
+ const isAdl = !isV12_15 && (layout.accountSize >= 312 || isV12_1 || isV12_1EP);
2901
3037
  if (isV12_15) {
2902
3038
  const kindByte2 = readU8(data, base + V12_15_ACCT_KIND_OFF);
2903
3039
  const kind2 = kindByte2 === 1 ? 1 /* LP */ : 0 /* User */;
@@ -2940,13 +3076,13 @@ function parseAccount(data, idx) {
2940
3076
  }
2941
3077
  const warmupStartedOff = isAdl ? V_ADL_ACCT_WARMUP_STARTED_OFF : ACCT_WARMUP_STARTED_OFF;
2942
3078
  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;
3079
+ const positionSizeOff = isV12_1 || isV12_1EP ? V12_1_ACCT_POSITION_SIZE_OFF : isAdl ? V_ADL_ACCT_POSITION_SIZE_OFF : ACCT_POSITION_SIZE_OFF;
3080
+ 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;
3081
+ const fundingIndexOff = isV12_1 || isV12_1EP ? -1 : isAdl ? V_ADL_ACCT_FUNDING_INDEX_OFF : ACCT_FUNDING_INDEX_OFF;
3082
+ 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;
3083
+ 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;
3084
+ 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;
3085
+ 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
3086
  const kindByte = readU8(data, base + ACCT_KIND_OFF);
2951
3087
  const kind = kindByte === 1 ? 1 /* LP */ : 0 /* User */;
2952
3088
  return {
@@ -2959,9 +3095,8 @@ function parseAccount(data, idx) {
2959
3095
  warmupSlopePerStep: readU128LE(data, base + warmupSlopeOff),
2960
3096
  positionSize: readI128LE(data, base + positionSizeOff),
2961
3097
  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),
3098
+ // V12_1/V12_1_EP: funding_index not present in SBF layout
3099
+ fundingIndex: isV12_1 || isV12_1EP ? fundingIndexOff >= 0 ? BigInt(readI64LE(data, base + fundingIndexOff)) : 0n : readI128LE(data, base + fundingIndexOff),
2965
3100
  matcherProgram: new PublicKey3(data.subarray(base + matcherProgOff, base + matcherProgOff + 32)),
2966
3101
  matcherContext: new PublicKey3(data.subarray(base + matcherCtxOff, base + matcherCtxOff + 32)),
2967
3102
  owner: new PublicKey3(data.subarray(base + layout.acctOwnerOff, base + layout.acctOwnerOff + 32)),
@@ -3003,6 +3138,12 @@ function deriveVaultAuthority(programId, slab) {
3003
3138
  programId
3004
3139
  );
3005
3140
  }
3141
+ function deriveInsuranceLpMint(programId, slab) {
3142
+ return PublicKey4.findProgramAddressSync(
3143
+ [textEncoder.encode("ins_lp"), slab.toBytes()],
3144
+ programId
3145
+ );
3146
+ }
3006
3147
  var LP_INDEX_U16_MAX = 65535;
3007
3148
  function deriveLpPda(programId, slab, lpIdx) {
3008
3149
  if (typeof lpIdx !== "number" || !Number.isInteger(lpIdx) || lpIdx < 0 || lpIdx > LP_INDEX_U16_MAX) {
@@ -3053,14 +3194,7 @@ function derivePythPushOraclePDA(feedIdHex) {
3053
3194
  }
3054
3195
  const feedId = new Uint8Array(32);
3055
3196
  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;
3197
+ feedId[i] = parseInt(normalized.substring(i * 2, i * 2 + 2), 16);
3064
3198
  }
3065
3199
  const shardBuf = new Uint8Array(2);
3066
3200
  return PublicKey4.findProgramAddressSync(
@@ -3092,9 +3226,7 @@ import { PublicKey as PublicKey6 } from "@solana/web3.js";
3092
3226
  // src/solana/static-markets.ts
3093
3227
  import { PublicKey as PublicKey5 } from "@solana/web3.js";
3094
3228
  var MAINNET_MARKETS = [
3095
- // Populated at mainnet launch currently empty.
3096
- // To add entries:
3097
- // { slabAddress: "ABC123...", symbol: "SOL-PERP", name: "SOL Perpetual" },
3229
+ { slabAddress: "7psyeWRts4pRX2cyAWD1NH87bR9ugXP7pe6ARgfG79Do", symbol: "SOL-PERP", name: "SOL/USDC Perpetual" }
3098
3230
  ];
3099
3231
  var DEVNET_MARKETS = [
3100
3232
  // Populated from prior discoverMarkets() runs on devnet.
@@ -3874,7 +4006,9 @@ function computeRaydiumClmmPriceE6(data) {
3874
4006
  }
3875
4007
  const sqrtPriceX64 = readU128LE3(dv3, 253);
3876
4008
  if (sqrtPriceX64 === 0n) return 0n;
3877
- const priceE6Raw = sqrtPriceX64 * sqrtPriceX64 * 1000000n >> 128n;
4009
+ const scaledSqrt = sqrtPriceX64 * 1000000n;
4010
+ const term = scaledSqrt >> 64n;
4011
+ const priceE6Raw = term * sqrtPriceX64 >> 64n;
3878
4012
  const decimalDiff = 6 + decimals0 - decimals1;
3879
4013
  const adjustedDiff = decimalDiff - 6;
3880
4014
  if (adjustedDiff >= 0) {
@@ -3915,26 +4049,13 @@ function computeMeteoraDlmmPriceE6(data) {
3915
4049
  `Meteora DLMM: |activeId| ${Math.abs(activeId)} exceeds max ${MAX_ACTIVE_ID_ABS}`
3916
4050
  );
3917
4051
  }
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
4052
  const SCALE = 1000000000000000000n;
3925
4053
  const base = SCALE + BigInt(binStep) * SCALE / 10000n;
3926
4054
  const isNeg = activeId < 0;
3927
4055
  let exp = isNeg ? BigInt(-activeId) : BigInt(activeId);
3928
4056
  let result = SCALE;
3929
4057
  let b = base;
3930
- let iterations = 0;
3931
- const MAX_ITERATIONS = 25;
3932
4058
  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
4059
  if (exp & 1n) {
3939
4060
  result = result * b / SCALE;
3940
4061
  }
@@ -3965,7 +4086,6 @@ function readU128LE3(dv3, offset) {
3965
4086
  var CHAINLINK_MIN_SIZE = 224;
3966
4087
  var MAX_DECIMALS = 18;
3967
4088
  var CHAINLINK_DECIMALS_OFFSET = 138;
3968
- var CHAINLINK_TIMESTAMP_OFFSET = 168;
3969
4089
  var CHAINLINK_ANSWER_OFFSET = 216;
3970
4090
  function readU82(data, off) {
3971
4091
  return data[off];
@@ -3973,7 +4093,7 @@ function readU82(data, off) {
3973
4093
  function readBigInt64LE(data, off) {
3974
4094
  return new DataView(data.buffer, data.byteOffset, data.byteLength).getBigInt64(off, true);
3975
4095
  }
3976
- function parseChainlinkPrice(data, options) {
4096
+ function parseChainlinkPrice(data) {
3977
4097
  if (data.length < CHAINLINK_MIN_SIZE) {
3978
4098
  throw new Error(
3979
4099
  `Oracle account data too small: ${data.length} bytes (need at least ${CHAINLINK_MIN_SIZE})`
@@ -3991,18 +4111,7 @@ function parseChainlinkPrice(data, options) {
3991
4111
  `Oracle price is non-positive: ${price}`
3992
4112
  );
3993
4113
  }
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 };
4114
+ return { price, decimals };
4006
4115
  }
4007
4116
  function isValidChainlinkOracle(data) {
4008
4117
  try {
@@ -4022,11 +4131,7 @@ var TOKEN_2022_PROGRAM_ID = new PublicKey8(
4022
4131
  async function detectTokenProgram(connection, mint) {
4023
4132
  const info = await connection.getAccountInfo(mint);
4024
4133
  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
- );
4134
+ return info.owner;
4030
4135
  }
4031
4136
  function isToken2022(tokenProgramId) {
4032
4137
  return tokenProgramId.equals(TOKEN_2022_PROGRAM_ID);
@@ -4059,14 +4164,12 @@ var PROGRAM_IDS = {
4059
4164
  }
4060
4165
  };
4061
4166
  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
- }
4167
+ const override = safeEnv("PROGRAM_ID");
4168
+ if (override) {
4169
+ console.warn(
4170
+ `[percolator-sdk] PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
4171
+ );
4172
+ return new PublicKey9(override);
4070
4173
  }
4071
4174
  const detectedNetwork = getCurrentNetwork();
4072
4175
  const targetNetwork = network ?? detectedNetwork;
@@ -4074,14 +4177,12 @@ function getProgramId(network) {
4074
4177
  return new PublicKey9(programId);
4075
4178
  }
4076
4179
  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
- }
4180
+ const override = safeEnv("MATCHER_PROGRAM_ID");
4181
+ if (override) {
4182
+ console.warn(
4183
+ `[percolator-sdk] MATCHER_PROGRAM_ID env override active: ${override} \u2014 ensure this points to a trusted program`
4184
+ );
4185
+ return new PublicKey9(override);
4085
4186
  }
4086
4187
  const detectedNetwork = getCurrentNetwork();
4087
4188
  const targetNetwork = network ?? detectedNetwork;
@@ -4114,7 +4215,10 @@ function getStakeProgramId(network) {
4114
4215
  }
4115
4216
  const detectedNetwork = network ?? (() => {
4116
4217
  const n = safeEnv("NEXT_PUBLIC_DEFAULT_NETWORK")?.toLowerCase() ?? safeEnv("NETWORK")?.toLowerCase() ?? "";
4117
- return n === "mainnet" || n === "mainnet-beta" ? "mainnet" : "devnet";
4218
+ if (n === "mainnet" || n === "mainnet-beta") return "mainnet";
4219
+ if (n === "devnet") return "devnet";
4220
+ if (typeof window !== "undefined") return "mainnet";
4221
+ return "devnet";
4118
4222
  })();
4119
4223
  const id = STAKE_PROGRAM_IDS[detectedNetwork];
4120
4224
  if (!id) {
@@ -4124,7 +4228,7 @@ function getStakeProgramId(network) {
4124
4228
  }
4125
4229
  return new PublicKey10(id);
4126
4230
  }
4127
- var STAKE_PROGRAM_ID = new PublicKey10(STAKE_PROGRAM_IDS.mainnet);
4231
+ var STAKE_PROGRAM_ID = new PublicKey10(STAKE_PROGRAM_IDS.devnet);
4128
4232
  var STAKE_IX = {
4129
4233
  InitPool: 0,
4130
4234
  Deposit: 1,
@@ -4185,9 +4289,6 @@ function readU16LE3(data, off) {
4185
4289
  );
4186
4290
  }
4187
4291
  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
4292
  const big = BigInt(v);
4192
4293
  if (big < 0n) throw new Error(`u64Le: value must be non-negative, got ${big}`);
4193
4294
  if (big > 0xFFFFFFFFFFFFFFFFn) throw new Error(`u64Le: value exceeds u64 max`);
@@ -4196,9 +4297,6 @@ function u64Le(v) {
4196
4297
  return arr;
4197
4298
  }
4198
4299
  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
4300
  const big = BigInt(v);
4203
4301
  if (big < 0n) throw new Error(`u128Le: value must be non-negative, got ${big}`);
4204
4302
  if (big > (1n << 128n) - 1n) throw new Error(`u128Le: value exceeds u128 max`);
@@ -4209,7 +4307,7 @@ function u128Le(v) {
4209
4307
  return arr;
4210
4308
  }
4211
4309
  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}`);
4310
+ if (v < 0 || v > 65535) throw new Error(`u16Le: value out of u16 range (0..65535), got ${v}`);
4213
4311
  const arr = new Uint8Array(2);
4214
4312
  new DataView(arr.buffer).setUint16(0, v, true);
4215
4313
  return arr;
@@ -4464,9 +4562,7 @@ function computePnlPct(pnl, capital) {
4464
4562
  }
4465
4563
  function isAdlTriggered(slabData) {
4466
4564
  const layout = detectSlabLayout(slabData.length);
4467
- if (!layout) {
4468
- return false;
4469
- }
4565
+ if (!layout) return false;
4470
4566
  try {
4471
4567
  const engine = parseEngine(slabData);
4472
4568
  if (engine.pnlPosTot === 0n) return false;
@@ -4509,14 +4605,6 @@ function rankAdlPositions(slabData) {
4509
4605
  if (account.kind !== 0 /* User */) continue;
4510
4606
  if (account.positionSize === 0n) continue;
4511
4607
  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
4608
  const pnlPct = computePnlPct(account.pnl, account.capital);
4521
4609
  positions.push({
4522
4610
  idx,
@@ -4549,8 +4637,7 @@ function buildAdlInstruction(caller, slab, oracle, programId, targetIdx, backupO
4549
4637
  `buildAdlInstruction: targetIdx must be a non-negative integer, got ${targetIdx}`
4550
4638
  );
4551
4639
  }
4552
- const dataBytes = encodeExecuteAdl({ targetIdx });
4553
- const data = Buffer.from(dataBytes);
4640
+ const data = Buffer.from(encodeExecuteAdl({ targetIdx }));
4554
4641
  const keys = [
4555
4642
  { pubkey: caller, isSigner: true, isWritable: false },
4556
4643
  { pubkey: slab, isSigner: false, isWritable: true },
@@ -4590,11 +4677,7 @@ function parseAdlEvent(logs) {
4590
4677
  }
4591
4678
  if (tag !== ADL_EVENT_TAG) continue;
4592
4679
  try {
4593
- const targetIdxBig = BigInt(match[2]);
4594
- if (targetIdxBig < 0n || targetIdxBig > 65535n) {
4595
- continue;
4596
- }
4597
- const targetIdx = Number(targetIdxBig);
4680
+ const targetIdx = Number(BigInt(match[2]));
4598
4681
  const price = BigInt(match[3]);
4599
4682
  const closedLo = BigInt(match[4]);
4600
4683
  const closedHi = BigInt(match[5]);
@@ -4622,22 +4705,6 @@ async function fetchAdlRankings(apiBase, slab, fetchFn = fetch) {
4622
4705
  );
4623
4706
  }
4624
4707
  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
4708
  return json;
4642
4709
  }
4643
4710
 
@@ -5159,7 +5226,7 @@ import { PublicKey as PublicKey13, Transaction as Transaction2 } from "@solana/w
5159
5226
  var LIGHTHOUSE_PROGRAM_ID = new PublicKey13(
5160
5227
  "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95"
5161
5228
  );
5162
- var LIGHTHOUSE_PROGRAM_ID_STR2 = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
5229
+ var LIGHTHOUSE_PROGRAM_ID_STR = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95";
5163
5230
  var LIGHTHOUSE_CONSTRAINT_ADDRESS = 6400;
5164
5231
  var LIGHTHOUSE_ERROR_CODES = /* @__PURE__ */ new Set([
5165
5232
  6e3,
@@ -5205,7 +5272,7 @@ function isLighthouseInstruction(ix) {
5205
5272
  function isLighthouseError(error) {
5206
5273
  const msg = extractErrorMessage(error);
5207
5274
  if (!msg) return false;
5208
- if (msg.includes(LIGHTHOUSE_PROGRAM_ID_STR2)) return true;
5275
+ if (msg.includes(LIGHTHOUSE_PROGRAM_ID_STR)) return true;
5209
5276
  if (/custom\s+program\s+error:\s*0x1900\b/i.test(msg)) return true;
5210
5277
  if (/"Custom"\s*:\s*6400\b/.test(msg) && /InstructionError/i.test(msg)) return true;
5211
5278
  return false;
@@ -5215,18 +5282,18 @@ function isLighthouseFailureInLogs(logs) {
5215
5282
  let insideLighthouse = false;
5216
5283
  for (const line of logs) {
5217
5284
  if (typeof line !== "string") continue;
5218
- if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} invoke`)) {
5285
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {
5219
5286
  insideLighthouse = true;
5220
5287
  continue;
5221
5288
  }
5222
- if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} success`)) {
5289
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} success`)) {
5223
5290
  insideLighthouse = false;
5224
5291
  continue;
5225
5292
  }
5226
5293
  if (insideLighthouse && /failed/i.test(line)) {
5227
5294
  return true;
5228
5295
  }
5229
- if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR2} failed`)) {
5296
+ if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} failed`)) {
5230
5297
  return true;
5231
5298
  }
5232
5299
  }
@@ -5311,10 +5378,16 @@ function computeLiqPrice(entryPrice, capital, positionSize, maintenanceMarginBps
5311
5378
  function computePreTradeLiqPrice(oracleE6, margin, posSize, maintBps, feeBps, direction) {
5312
5379
  if (oracleE6 === 0n || margin === 0n || posSize === 0n) return 0n;
5313
5380
  const absPos = posSize < 0n ? -posSize : posSize;
5314
- const fee = absPos * feeBps / 10000n;
5315
- const effectiveCapital = margin > fee ? margin - fee : 0n;
5316
5381
  const signedPos = direction === "long" ? absPos : -absPos;
5317
- return computeLiqPrice(oracleE6, effectiveCapital, signedPos, maintBps);
5382
+ const feeAdjust = oracleE6 * feeBps / 10000n;
5383
+ let adjustedEntry;
5384
+ if (direction === "long") {
5385
+ adjustedEntry = oracleE6 + feeAdjust;
5386
+ } else {
5387
+ const shortEntry = oracleE6 - feeAdjust;
5388
+ adjustedEntry = shortEntry > 0n ? shortEntry : 1n;
5389
+ }
5390
+ return computeLiqPrice(adjustedEntry, margin, signedPos, maintBps);
5318
5391
  }
5319
5392
  function computeTradingFee(notional, tradingFeeBps) {
5320
5393
  return notional * tradingFeeBps / 10000n;
@@ -5334,20 +5407,9 @@ function computeFeeSplit(totalFee, config) {
5334
5407
  if (config.lpBps === 0n && config.protocolBps === 0n && config.creatorBps === 0n) {
5335
5408
  return [totalFee, 0n, 0n];
5336
5409
  }
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
5410
  const lp = totalFee * config.lpBps / 10000n;
5344
5411
  const protocol = totalFee * config.protocolBps / 10000n;
5345
5412
  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
5413
  return [lp, protocol, creator];
5352
5414
  }
5353
5415
  function computePnlPercent(pnlTokens, capital) {
@@ -5362,17 +5424,10 @@ function computePnlPercent(pnlTokens, capital) {
5362
5424
  }
5363
5425
  function computeEstimatedEntryPrice(oracleE6, tradingFeeBps, direction) {
5364
5426
  if (oracleE6 === 0n) return 0n;
5365
- if (tradingFeeBps < 0n) {
5366
- throw new Error(`computeEstimatedEntryPrice: tradingFeeBps must be non-negative, got ${tradingFeeBps}`);
5367
- }
5368
5427
  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;
5428
+ if (direction === "long") return oracleE6 + feeImpact;
5429
+ const shortEntry = oracleE6 - feeImpact;
5430
+ return shortEntry > 0n ? shortEntry : 1n;
5376
5431
  }
5377
5432
  var MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
5378
5433
  var MIN_SAFE_BIGINT = BigInt(-Number.MAX_SAFE_INTEGER);
@@ -5393,12 +5448,7 @@ function computeMaxLeverage(initialMarginBps) {
5393
5448
  if (initialMarginBps <= 0n) {
5394
5449
  throw new Error("computeMaxLeverage: initialMarginBps must be positive");
5395
5450
  }
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);
5451
+ return Number(10000n / initialMarginBps);
5402
5452
  }
5403
5453
 
5404
5454
  // src/math/warmup.ts
@@ -5410,9 +5460,6 @@ function computeWarmupUnlockedCapital(totalCapital, currentSlot, warmupStartSlot
5410
5460
  return totalCapital * elapsed / warmupPeriodSlots;
5411
5461
  }
5412
5462
  function computeWarmupLeverageCap(initialMarginBps, totalCapital, currentSlot, warmupStartSlot, warmupPeriodSlots) {
5413
- if (initialMarginBps <= 0n) {
5414
- throw new Error("computeWarmupLeverageCap: initialMarginBps must be positive");
5415
- }
5416
5463
  const maxLev = computeMaxLeverage(initialMarginBps);
5417
5464
  if (warmupPeriodSlots === 0n || warmupStartSlot === 0n) return maxLev;
5418
5465
  if (totalCapital <= 0n) return 1;
@@ -5423,14 +5470,7 @@ function computeWarmupLeverageCap(initialMarginBps, totalCapital, currentSlot, w
5423
5470
  warmupPeriodSlots
5424
5471
  );
5425
5472
  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);
5473
+ const effectiveLev = Number(BigInt(maxLev) * unlocked / totalCapital);
5434
5474
  return Math.max(1, effectiveLev);
5435
5475
  }
5436
5476
  function computeWarmupMaxPositionSize(initialMarginBps, totalCapital, currentSlot, warmupStartSlot, warmupPeriodSlots) {
@@ -5443,41 +5483,10 @@ function computeWarmupMaxPositionSize(initialMarginBps, totalCapital, currentSlo
5443
5483
  );
5444
5484
  return unlocked * BigInt(maxLev);
5445
5485
  }
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
5486
 
5478
5487
  // src/validation.ts
5479
5488
  import { PublicKey as PublicKey14 } from "@solana/web3.js";
5480
- var U16_MAX = 65535;
5489
+ var U16_MAX2 = 65535;
5481
5490
  var U64_MAX = BigInt("18446744073709551615");
5482
5491
  var I64_MIN = BigInt("-9223372036854775808");
5483
5492
  var I64_MAX = BigInt("9223372036854775807");
@@ -5517,26 +5526,24 @@ function validatePublicKey(value, field) {
5517
5526
  function validateIndex(value, field) {
5518
5527
  const t = requireDecimalUIntString(value, field);
5519
5528
  const bi = BigInt(t);
5520
- if (bi > BigInt(U16_MAX)) {
5529
+ if (bi > BigInt(U16_MAX2)) {
5521
5530
  throw new ValidationError(
5522
5531
  field,
5523
- `must be <= ${U16_MAX} (u16 max), got ${t}`
5532
+ `must be <= ${U16_MAX2} (u16 max), got ${t}`
5524
5533
  );
5525
5534
  }
5526
- if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5527
- throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);
5528
- }
5529
5535
  return Number(bi);
5530
5536
  }
5531
5537
  function validateAmount(value, field) {
5532
- const t = value.trim();
5533
- if (!/^(0|[1-9]\d*)$/.test(t)) {
5538
+ let num;
5539
+ try {
5540
+ num = BigInt(value);
5541
+ } catch {
5534
5542
  throw new ValidationError(
5535
5543
  field,
5536
- `"${value}" is not a valid non-negative integer. Use decimal digits only.`
5544
+ `"${value}" is not a valid number. Use decimal digits only.`
5537
5545
  );
5538
5546
  }
5539
- const num = BigInt(t);
5540
5547
  if (num < 0n) {
5541
5548
  throw new ValidationError(field, `must be non-negative, got ${num}`);
5542
5549
  }
@@ -5549,14 +5556,15 @@ function validateAmount(value, field) {
5549
5556
  return num;
5550
5557
  }
5551
5558
  function validateU128(value, field) {
5552
- const t = value.trim();
5553
- if (!/^(0|[1-9]\d*)$/.test(t)) {
5559
+ let num;
5560
+ try {
5561
+ num = BigInt(value);
5562
+ } catch {
5554
5563
  throw new ValidationError(
5555
5564
  field,
5556
- `"${value}" is not a valid non-negative integer. Use decimal digits only.`
5565
+ `"${value}" is not a valid number. Use decimal digits only.`
5557
5566
  );
5558
5567
  }
5559
- const num = BigInt(t);
5560
5568
  if (num < 0n) {
5561
5569
  throw new ValidationError(field, `must be non-negative, got ${num}`);
5562
5570
  }
@@ -5569,14 +5577,15 @@ function validateU128(value, field) {
5569
5577
  return num;
5570
5578
  }
5571
5579
  function validateI64(value, field) {
5572
- const t = value.trim();
5573
- if (!/^-?(0|[1-9]\d*)$/.test(t)) {
5580
+ let num;
5581
+ try {
5582
+ num = BigInt(value);
5583
+ } catch {
5574
5584
  throw new ValidationError(
5575
5585
  field,
5576
- `"${value}" is not a valid integer. Use decimal digits only, with optional leading minus.`
5586
+ `"${value}" is not a valid number. Use decimal digits only, with optional leading minus.`
5577
5587
  );
5578
5588
  }
5579
- const num = BigInt(t);
5580
5589
  if (num < I64_MIN) {
5581
5590
  throw new ValidationError(
5582
5591
  field,
@@ -5592,14 +5601,15 @@ function validateI64(value, field) {
5592
5601
  return num;
5593
5602
  }
5594
5603
  function validateI128(value, field) {
5595
- const t = value.trim();
5596
- if (!/^-?(0|[1-9]\d*)$/.test(t)) {
5604
+ let num;
5605
+ try {
5606
+ num = BigInt(value);
5607
+ } catch {
5597
5608
  throw new ValidationError(
5598
5609
  field,
5599
- `"${value}" is not a valid integer. Use decimal digits only, with optional leading minus.`
5610
+ `"${value}" is not a valid number. Use decimal digits only, with optional leading minus.`
5600
5611
  );
5601
5612
  }
5602
- const num = BigInt(t);
5603
5613
  if (num < I128_MIN) {
5604
5614
  throw new ValidationError(
5605
5615
  field,
@@ -5623,9 +5633,6 @@ function validateBps(value, field) {
5623
5633
  `must be <= 10000 (100%), got ${t}`
5624
5634
  );
5625
5635
  }
5626
- if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5627
- throw new ValidationError(field, `internal error: bps value exceeds MAX_SAFE_INTEGER`);
5628
- }
5629
5636
  return Number(bi);
5630
5637
  }
5631
5638
  function validateU64(value, field) {
@@ -5634,15 +5641,12 @@ function validateU64(value, field) {
5634
5641
  function validateU16(value, field) {
5635
5642
  const t = requireDecimalUIntString(value, field);
5636
5643
  const bi = BigInt(t);
5637
- if (bi > BigInt(U16_MAX)) {
5644
+ if (bi > BigInt(U16_MAX2)) {
5638
5645
  throw new ValidationError(
5639
5646
  field,
5640
- `must be <= ${U16_MAX} (u16 max), got ${t}`
5647
+ `must be <= ${U16_MAX2} (u16 max), got ${t}`
5641
5648
  );
5642
5649
  }
5643
- if (bi > BigInt(Number.MAX_SAFE_INTEGER)) {
5644
- throw new ValidationError(field, `internal error: u16 value exceeds MAX_SAFE_INTEGER`);
5645
- }
5646
5650
  return Number(bi);
5647
5651
  }
5648
5652
 
@@ -5693,9 +5697,7 @@ function parseDexScreenerPairs(json) {
5693
5697
  else if (liquidity > 1e4) confidence = 60;
5694
5698
  else if (liquidity > 1e3) confidence = 45;
5695
5699
  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;
5700
+ const price = typeof priceUsd === "string" || typeof priceUsd === "number" ? parseFloat(String(priceUsd)) || 0 : 0;
5699
5701
  let baseSym = "?";
5700
5702
  let quoteSym = "?";
5701
5703
  if (isRecord(pair.baseToken) && typeof pair.baseToken.symbol === "string") {
@@ -5726,8 +5728,8 @@ function parseJupiterMintEntry(json, mint) {
5726
5728
  if (!isRecord(row)) return null;
5727
5729
  const rawPrice = row.price;
5728
5730
  if (rawPrice === void 0 || rawPrice === null) return null;
5729
- const price = parseFloat(String(rawPrice));
5730
- if (!Number.isFinite(price) || price <= 0) return null;
5731
+ const price = parseFloat(String(rawPrice)) || 0;
5732
+ if (price <= 0) return null;
5731
5733
  let mintSymbol = "?";
5732
5734
  if (typeof row.mintSymbol === "string") mintSymbol = row.mintSymbol;
5733
5735
  return { price, mintSymbol };
@@ -5793,17 +5795,10 @@ async function fetchDexSources(mint, signal) {
5793
5795
  headers: { "User-Agent": "percolator/1.0" }
5794
5796
  }
5795
5797
  );
5796
- if (!resp.ok) {
5797
- console.debug(`[fetchDexSources] HTTP ${resp.status} for mint ${mint}`);
5798
- return [];
5799
- }
5798
+ if (!resp.ok) return [];
5800
5799
  const json = await resp.json();
5801
5800
  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
- );
5801
+ } catch {
5807
5802
  return [];
5808
5803
  }
5809
5804
  }
@@ -5814,7 +5809,7 @@ function lookupPythSource(mint) {
5814
5809
  type: "pyth",
5815
5810
  address: entry.feedId,
5816
5811
  pairLabel: `${entry.symbol} / USD (Pyth)`,
5817
- liquidity: Number.MAX_SAFE_INTEGER,
5812
+ liquidity: Infinity,
5818
5813
  // Pyth is considered deep liquidity
5819
5814
  price: 0,
5820
5815
  // We don't fetch live price here; caller can enrich
@@ -5831,16 +5826,10 @@ async function fetchJupiterSource(mint, signal) {
5831
5826
  headers: { "User-Agent": "percolator/1.0" }
5832
5827
  }
5833
5828
  );
5834
- if (!resp.ok) {
5835
- console.debug(`[fetchJupiterSource] HTTP ${resp.status} for mint ${mint}`);
5836
- return null;
5837
- }
5829
+ if (!resp.ok) return null;
5838
5830
  const json = await resp.json();
5839
5831
  const row = parseJupiterMintEntry(json, mint);
5840
- if (!row) {
5841
- console.debug(`[fetchJupiterSource] No price data from Jupiter for mint ${mint}`);
5842
- return null;
5843
- }
5832
+ if (!row) return null;
5844
5833
  return {
5845
5834
  type: "jupiter",
5846
5835
  address: mint,
@@ -5851,39 +5840,23 @@ async function fetchJupiterSource(mint, signal) {
5851
5840
  confidence: 40
5852
5841
  // Fallback — lower confidence
5853
5842
  };
5854
- } catch (err) {
5855
- console.warn(
5856
- `[fetchJupiterSource] Error fetching Jupiter data for mint ${mint}:`,
5857
- err instanceof Error ? err.message : String(err)
5858
- );
5843
+ } catch {
5859
5844
  return null;
5860
5845
  }
5861
5846
  }
5862
5847
  async function resolvePrice(mint, signal, options) {
5863
5848
  const timeoutMs = options?.timeoutMs ?? DEFAULT_RESOLVE_TIMEOUT_MS;
5864
5849
  const timeoutSignal = AbortSignal.timeout(timeoutMs);
5865
- const effectiveSignal2 = signal ? combineAbortSignals([signal, timeoutSignal]) : timeoutSignal;
5850
+ const combinedSignal = signal ? combineAbortSignals([signal, timeoutSignal]) : timeoutSignal;
5866
5851
  const [dexSources, jupiterSource] = await Promise.all([
5867
- fetchDexSources(mint, effectiveSignal2),
5868
- fetchJupiterSource(mint, effectiveSignal2)
5852
+ fetchDexSources(mint, combinedSignal),
5853
+ fetchJupiterSource(mint, combinedSignal)
5869
5854
  ]);
5870
5855
  const pythSource = lookupPythSource(mint);
5871
5856
  const allSources = [];
5872
5857
  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
- }
5858
+ const refPrice = dexSources[0]?.price || jupiterSource?.price || 0;
5859
+ pythSource.price = refPrice;
5887
5860
  allSources.push(pythSource);
5888
5861
  }
5889
5862
  allSources.push(...dexSources);
@@ -5908,7 +5881,9 @@ export {
5908
5881
  ACCOUNTS_CLOSE_ACCOUNT,
5909
5882
  ACCOUNTS_CLOSE_SLAB,
5910
5883
  ACCOUNTS_CLOSE_STALE_SLABS,
5884
+ ACCOUNTS_CREATE_INSURANCE_MINT,
5911
5885
  ACCOUNTS_DEPOSIT_COLLATERAL,
5886
+ ACCOUNTS_DEPOSIT_INSURANCE_LP,
5912
5887
  ACCOUNTS_EXECUTE_ADL,
5913
5888
  ACCOUNTS_FUND_MARKET_INSURANCE,
5914
5889
  ACCOUNTS_INIT_LP,
@@ -5924,6 +5899,7 @@ export {
5924
5899
  ACCOUNTS_QUEUE_WITHDRAWAL,
5925
5900
  ACCOUNTS_RECLAIM_SLAB_RENT,
5926
5901
  ACCOUNTS_RESOLVE_MARKET,
5902
+ ACCOUNTS_SET_DEX_POOL,
5927
5903
  ACCOUNTS_SET_INSURANCE_ISOLATION,
5928
5904
  ACCOUNTS_SET_MAINTENANCE_FEE,
5929
5905
  ACCOUNTS_SET_OI_IMBALANCE_HARD_BLOCK,
@@ -5941,11 +5917,11 @@ export {
5941
5917
  ACCOUNTS_UPDATE_CONFIG,
5942
5918
  ACCOUNTS_WITHDRAW_COLLATERAL,
5943
5919
  ACCOUNTS_WITHDRAW_INSURANCE,
5920
+ ACCOUNTS_WITHDRAW_INSURANCE_LP,
5944
5921
  AccountKind,
5945
5922
  CHAINLINK_ANSWER_OFFSET,
5946
5923
  CHAINLINK_DECIMALS_OFFSET,
5947
5924
  CHAINLINK_MIN_SIZE,
5948
- CHAINLINK_TIMESTAMP_OFFSET,
5949
5925
  CREATOR_LOCK_SEED,
5950
5926
  CTX_VAMM_OFFSET,
5951
5927
  DEFAULT_OI_RAMP_SLOTS,
@@ -5955,7 +5931,7 @@ export {
5955
5931
  LIGHTHOUSE_CONSTRAINT_ADDRESS,
5956
5932
  LIGHTHOUSE_ERROR_CODES,
5957
5933
  LIGHTHOUSE_PROGRAM_ID,
5958
- LIGHTHOUSE_PROGRAM_ID_STR2 as LIGHTHOUSE_PROGRAM_ID_STR,
5934
+ LIGHTHOUSE_PROGRAM_ID_STR,
5959
5935
  LIGHTHOUSE_USER_MESSAGE,
5960
5936
  MARK_PRICE_EMA_ALPHA_E6,
5961
5937
  MARK_PRICE_EMA_WINDOW_SLOTS,
@@ -6021,7 +5997,6 @@ export {
6021
5997
  computeLiqPrice,
6022
5998
  computeMarkPnl,
6023
5999
  computeMaxLeverage,
6024
- computeMaxWithdrawable,
6025
6000
  computePnlPercent,
6026
6001
  computePreTradeLiqPrice,
6027
6002
  computeRequiredMargin,
@@ -6029,7 +6004,6 @@ export {
6029
6004
  computeVammQuote,
6030
6005
  computeWarmupLeverageCap,
6031
6006
  computeWarmupMaxPositionSize,
6032
- computeWarmupProgress,
6033
6007
  computeWarmupUnlockedCapital,
6034
6008
  concatBytes,
6035
6009
  countLighthouseInstructions,
@@ -6038,6 +6012,7 @@ export {
6038
6012
  depositAccounts,
6039
6013
  deriveCreatorLockPda,
6040
6014
  deriveDepositPda,
6015
+ deriveInsuranceLpMint,
6041
6016
  deriveLpPda,
6042
6017
  derivePythPriceUpdateAccount,
6043
6018
  derivePythPushOraclePDA,
@@ -6076,8 +6051,10 @@ export {
6076
6051
  encodeCloseOrphanSlab,
6077
6052
  encodeCloseSlab,
6078
6053
  encodeCloseStaleSlabs,
6054
+ encodeCreateInsuranceMint,
6079
6055
  encodeCreateLpVault,
6080
6056
  encodeDepositCollateral,
6057
+ encodeDepositInsuranceLP,
6081
6058
  encodeDepositLpCollateral,
6082
6059
  encodeExecuteAdl,
6083
6060
  encodeForceCloseResolved,
@@ -6147,6 +6124,7 @@ export {
6147
6124
  encodeUpdateRiskParams,
6148
6125
  encodeWithdrawCollateral,
6149
6126
  encodeWithdrawInsurance,
6127
+ encodeWithdrawInsuranceLP,
6150
6128
  encodeWithdrawInsuranceLimited,
6151
6129
  encodeWithdrawLpCollateral,
6152
6130
  fetchAdlRankedPositions,
@@ -6168,7 +6146,6 @@ export {
6168
6146
  initPoolAccounts,
6169
6147
  isAccountUsed,
6170
6148
  isAdlTriggered,
6171
- isAnchorErrorCode,
6172
6149
  isLighthouseError,
6173
6150
  isLighthouseFailureInLogs,
6174
6151
  isLighthouseInstruction,