@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/abi/accounts.d.ts +22 -1
- package/dist/abi/errors.d.ts +0 -11
- package/dist/abi/instructions.d.ts +36 -28
- package/dist/index.js +328 -351
- package/dist/index.js.map +1 -1
- package/dist/math/trading.d.ts +1 -116
- package/dist/math/warmup.d.ts +0 -50
- package/dist/runtime/lighthouse.d.ts +1 -1
- package/dist/solana/oracle.d.ts +2 -10
- package/dist/solana/pda.d.ts +5 -0
- package/dist/solana/slab.d.ts +13 -8
- package/dist/solana/stake.d.ts +2 -2
- package/dist/validation.d.ts +1 -26
- package/package.json +1 -1
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 >
|
|
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 >
|
|
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 >
|
|
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 =
|
|
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
|
|
271
|
+
// RiskParams wire format — must match read_risk_params() in percolator.rs
|
|
272
|
+
// In v12.15: warmup_period_slots replaced by hMin/hMax. hMin is written first (same slot),
|
|
273
|
+
// hMax appended at end. liquidationBufferBps is read but discarded (kept for wire compat).
|
|
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.
|
|
276
|
-
|
|
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
|
|
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 ?
|
|
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 ?
|
|
2312
|
-
|
|
2313
|
-
|
|
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
|
|
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
|
|
2499
|
+
// not present in v12.15
|
|
2396
2500
|
engineLastCrankSlotOff: -1,
|
|
2397
|
-
// not yet mapped
|
|
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:
|
|
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 +
|
|
2814
|
-
lastCrankSlot:
|
|
2815
|
-
maxCrankStalenessSlots:
|
|
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:
|
|
2823
|
-
gcCursor:
|
|
2824
|
-
lastSweepStartSlot:
|
|
2825
|
-
lastSweepCompleteSlot:
|
|
2826
|
-
crankCursor:
|
|
2827
|
-
sweepStartIdx:
|
|
2828
|
-
lifetimeLiquidations:
|
|
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
|
|
2900
|
-
const
|
|
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 ?
|
|
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:
|
|
2963
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
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
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
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
|
-
|
|
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.
|
|
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 (
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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 ${
|
|
5285
|
+
if (line.includes(`Program ${LIGHTHOUSE_PROGRAM_ID_STR} invoke`)) {
|
|
5219
5286
|
insideLighthouse = true;
|
|
5220
5287
|
continue;
|
|
5221
5288
|
}
|
|
5222
|
-
if (line.includes(`Program ${
|
|
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 ${
|
|
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
|
-
|
|
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
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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(
|
|
5529
|
+
if (bi > BigInt(U16_MAX2)) {
|
|
5521
5530
|
throw new ValidationError(
|
|
5522
5531
|
field,
|
|
5523
|
-
`must be <= ${
|
|
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
|
-
|
|
5533
|
-
|
|
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
|
|
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
|
-
|
|
5553
|
-
|
|
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
|
|
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
|
-
|
|
5573
|
-
|
|
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
|
|
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
|
-
|
|
5596
|
-
|
|
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
|
|
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(
|
|
5644
|
+
if (bi > BigInt(U16_MAX2)) {
|
|
5638
5645
|
throw new ValidationError(
|
|
5639
5646
|
field,
|
|
5640
|
-
`must be <= ${
|
|
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
|
|
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 (
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
5850
|
+
const combinedSignal = signal ? combineAbortSignals([signal, timeoutSignal]) : timeoutSignal;
|
|
5866
5851
|
const [dexSources, jupiterSource] = await Promise.all([
|
|
5867
|
-
fetchDexSources(mint,
|
|
5868
|
-
fetchJupiterSource(mint,
|
|
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
|
|
5874
|
-
|
|
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
|
-
|
|
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,
|