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