@exponent-labs/exponent-fetcher 0.1.8 → 0.9.1
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/build/constants.d.ts +26 -0
- package/build/constants.js +58 -0
- package/build/constants.js.map +1 -0
- package/build/exponentFetcher.d.ts +32 -3
- package/build/exponentFetcher.js +255 -105
- package/build/exponentFetcher.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/package.json +21 -20
- package/src/constants.ts +56 -0
- package/src/exponentFetcher.ts +323 -118
- package/src/index.ts +1 -0
- package/tsconfig.json +2 -1
package/build/exponentFetcher.js
CHANGED
|
@@ -3,13 +3,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.fetchOreExchangeRate = exports.fetchReflectRedemptionRate = exports.fetchSolsticeRedemptionRate = exports.fetchSanctumIndex = exports.fetchAdrenaIndex = exports.fetchMeteoraIndex = exports.fetchFragmetricSupportedTokenIndex = exports.fetchKaminoVaultIndex = exports.fetchJupiterLendIndex = exports.fetchFragmetricIndex = exports.fetchGenericSyMetaIndex = exports.fetchPyth = exports.fetchJupiterPerpsIndex = exports.fetchJitoRestaking = exports.fetchPerenaStablePoolData = exports.fetchSplStakePoolIndex = exports.deserializeEmission = exports.serializeEmission = exports.fetchAllKaminoObligationsByKaminoReserve = exports.fetchKaminoReserve = exports.deserializeYtPosition = exports.deserializeLpPosition = exports.deserializeMarketThreeTicks = exports.ExponentFetcher = exports.MyWallet = exports.deserializeAnchorizedPNumFromJson = exports.serializeAnchorizedPNumFromJson = void 0;
|
|
6
|
+
exports.fetchChainlinkRate = exports.fetchOreExchangeRate = exports.fetchReflectRedemptionRate = exports.fetchSolsticeRedemptionRate = exports.fetchSanctumIndex = exports.fetchAdrenaIndex = exports.fetchMeteoraIndex = exports.fetchFragmetricSupportedTokenIndex = exports.fetchKaminoVaultIndex = exports.fetchJupiterLendIndex = exports.fetchFragmetricIndex = exports.fetchGenericSyMetaIndex = exports.fetchPyth = exports.fetchJupiterPerpsIndex = exports.fetchJitoRestaking = exports.fetchPerenaStablePoolData = exports.fetchSplStakePoolIndex = exports.anchorizedPNumToRawBigint = exports.deserializeEmission = exports.serializeEmission = exports.fetchAllKaminoObligationsByKaminoReserve = exports.fetchKaminoReserve = exports.deserializeYtPosition = exports.deserializeLpPosition = exports.deserializeMarketThree = exports.deserializeMarketThreeTicks = exports.ExponentFetcher = exports.MyWallet = exports.deserializeAnchorizedPNumFromJson = exports.serializeAnchorizedPNumFromJson = void 0;
|
|
7
7
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
8
8
|
const anchor_2 = require("@coral-xyz/anchor");
|
|
9
9
|
const spl_stake_pool_1 = require("@solana/spl-stake-pool");
|
|
10
10
|
const spl_token_1 = require("@solana/spl-token");
|
|
11
11
|
const bs58_1 = __importDefault(require("bs58"));
|
|
12
12
|
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
13
|
+
const chainlink_idl_1 = require("@exponent-labs/chainlink-idl");
|
|
13
14
|
const exponent_clmm_idl_1 = require("@exponent-labs/exponent-clmm-idl");
|
|
14
15
|
const exponent_idl_1 = require("@exponent-labs/exponent-idl");
|
|
15
16
|
const exponent_orderbook_idl_1 = require("@exponent-labs/exponent-orderbook-idl");
|
|
@@ -28,6 +29,7 @@ const meteora_idl_1 = require("@exponent-labs/meteora-idl");
|
|
|
28
29
|
const perena_sy_idl_1 = require("@exponent-labs/perena-sy-idl");
|
|
29
30
|
const perena_sy_idl_2 = require("@exponent-labs/perena-sy-idl");
|
|
30
31
|
const precise_number_1 = require("@exponent-labs/precise-number");
|
|
32
|
+
const constants_1 = require("./constants");
|
|
31
33
|
const adrena_1 = require("./utils/adrena");
|
|
32
34
|
const fragmetric_1 = require("./utils/fragmetric");
|
|
33
35
|
const jito_1 = require("./utils/jito");
|
|
@@ -37,16 +39,12 @@ const ore_1 = require("./utils/ore");
|
|
|
37
39
|
const perena_1 = require("./utils/perena");
|
|
38
40
|
const sanctum_1 = require("./utils/sanctum");
|
|
39
41
|
const solstice_1 = require("./utils/solstice");
|
|
42
|
+
const KAMINO_VAULT_GLOBAL_CONFIG = new anchor_1.web3.PublicKey("BKyTcUe6daNG8HbgBix2ugdRHbykG2dK9hPBBqhUyoEX");
|
|
40
43
|
function serializeAnchorizedPNumFromJson(pnum) {
|
|
41
44
|
const serializedArray = pnum[0].map((bn) => bn.toString());
|
|
42
45
|
return { 0: serializedArray };
|
|
43
46
|
}
|
|
44
47
|
exports.serializeAnchorizedPNumFromJson = serializeAnchorizedPNumFromJson;
|
|
45
|
-
function readU128LE(buf, offset) {
|
|
46
|
-
const lo = buf.readBigUInt64LE(offset);
|
|
47
|
-
const hi = buf.readBigUInt64LE(offset + 8);
|
|
48
|
-
return (hi << 64n) + lo;
|
|
49
|
-
}
|
|
50
48
|
function deserializeAnchorizedPNumFromJson(serialized) {
|
|
51
49
|
const bnArray = serialized[0].map((str) => new anchor_1.BN(str));
|
|
52
50
|
return { 0: bnArray };
|
|
@@ -317,6 +315,7 @@ class ExponentFetcher {
|
|
|
317
315
|
],
|
|
318
316
|
});
|
|
319
317
|
return marketsProgramAccounts
|
|
318
|
+
.filter(({ pubkey }) => !(0, constants_1.isMarketIgnored)(pubkey.toBase58()))
|
|
320
319
|
.map(({ account, pubkey }) => {
|
|
321
320
|
try {
|
|
322
321
|
return this.exponentClmmProgram.coder.accounts.decode("marketThree", account.data);
|
|
@@ -328,12 +327,16 @@ class ExponentFetcher {
|
|
|
328
327
|
.filter((m) => !!m);
|
|
329
328
|
}
|
|
330
329
|
async fetchMarketThree(address) {
|
|
330
|
+
const addressStr = address.toBase58();
|
|
331
|
+
if ((0, constants_1.isMarketIgnored)(addressStr)) {
|
|
332
|
+
throw new constants_1.IgnoredClmmEntityError("market", addressStr);
|
|
333
|
+
}
|
|
331
334
|
try {
|
|
332
335
|
const m = await this.exponentClmmProgram.account.marketThree.fetch(address);
|
|
333
336
|
return deserializeMarketThree(m);
|
|
334
337
|
}
|
|
335
338
|
catch (e) {
|
|
336
|
-
console.error(`Error fetching market ${
|
|
339
|
+
console.error(`Error fetching market ${addressStr}`);
|
|
337
340
|
console.error(e);
|
|
338
341
|
throw e;
|
|
339
342
|
}
|
|
@@ -350,32 +353,75 @@ class ExponentFetcher {
|
|
|
350
353
|
},
|
|
351
354
|
],
|
|
352
355
|
});
|
|
353
|
-
return ticksAccounts
|
|
356
|
+
return ticksAccounts
|
|
357
|
+
.filter(({ pubkey }) => !(0, constants_1.isTicksIgnored)(pubkey.toBase58()))
|
|
358
|
+
.map(({ account }) => deserializeMarketThreeTicks(account.data));
|
|
354
359
|
}
|
|
355
360
|
async fetchMarketThreeTicks(address) {
|
|
361
|
+
const addressStr = address.toBase58();
|
|
362
|
+
if ((0, constants_1.isTicksIgnored)(addressStr)) {
|
|
363
|
+
throw new constants_1.IgnoredClmmEntityError("ticks", addressStr);
|
|
364
|
+
}
|
|
356
365
|
try {
|
|
357
366
|
const m = (await this.connection.getAccountInfo(address)).data;
|
|
358
367
|
return deserializeMarketThreeTicks(m);
|
|
359
368
|
}
|
|
360
369
|
catch (e) {
|
|
361
|
-
console.error(`Error fetching
|
|
370
|
+
console.error(`Error fetching ticks ${addressStr}`);
|
|
362
371
|
console.error(e);
|
|
363
372
|
throw e;
|
|
364
373
|
}
|
|
365
374
|
}
|
|
366
375
|
}
|
|
367
376
|
exports.ExponentFetcher = ExponentFetcher;
|
|
377
|
+
/**
|
|
378
|
+
* Deserializes a CLMM Ticks account from raw buffer data.
|
|
379
|
+
*
|
|
380
|
+
* Layout matches Rust struct `Ticks` with `RedBlackTree<u32, Tick, 1000>`:
|
|
381
|
+
* - Discriminator: 8 bytes
|
|
382
|
+
* - RedBlackTree header: root(4) + padding(12) + size(8) + bump(4) + freeIdx(4) = 32 bytes
|
|
383
|
+
* - 1000 RBTree nodes, each: nodeHeader(16) + key(4) + padding(4) + Tick = variable bytes
|
|
384
|
+
* - Ticks footer: market(32) + feeGrowthPt(16) + feeGrowthSy(16) + prefixSum(8) + spotPrice(8) + currentTick(4) + padding(12) = 96 bytes
|
|
385
|
+
*/
|
|
368
386
|
function deserializeMarketThreeTicks(data) {
|
|
369
|
-
|
|
370
|
-
const
|
|
371
|
-
|
|
387
|
+
const MAX_TICK_NODES = 1000;
|
|
388
|
+
const PERSONAL_TICK_YIELD_TRACKER_SIZE = 2;
|
|
389
|
+
let offset = 8; // Skip discriminator
|
|
390
|
+
// ─── Helper functions ─────────────────────────────────────────────────────
|
|
391
|
+
const readU64 = () => {
|
|
392
|
+
const val = data.readBigUInt64LE(offset);
|
|
393
|
+
offset += 8;
|
|
394
|
+
return val;
|
|
395
|
+
};
|
|
396
|
+
const readU128 = () => {
|
|
397
|
+
const lo = data.readBigUInt64LE(offset);
|
|
398
|
+
const hi = data.readBigUInt64LE(offset + 8);
|
|
399
|
+
offset += 16;
|
|
400
|
+
return (hi << 64n) + lo;
|
|
401
|
+
};
|
|
402
|
+
const readI128 = () => {
|
|
403
|
+
const lo = data.readBigUInt64LE(offset);
|
|
404
|
+
const hi = data.readBigInt64LE(offset + 8); // High part is signed
|
|
405
|
+
offset += 16;
|
|
406
|
+
return (hi << 64n) + lo;
|
|
407
|
+
};
|
|
408
|
+
const readF64 = () => {
|
|
409
|
+
const val = data.readDoubleLE(offset);
|
|
410
|
+
offset += 8;
|
|
411
|
+
return val;
|
|
412
|
+
};
|
|
413
|
+
const readU32 = () => {
|
|
414
|
+
const val = data.readUInt32LE(offset);
|
|
415
|
+
offset += 4;
|
|
416
|
+
return val;
|
|
417
|
+
};
|
|
372
418
|
const readPubkey = () => {
|
|
373
419
|
const pk = new anchor_1.web3.PublicKey(data.slice(offset, offset + 32));
|
|
374
420
|
offset += 32;
|
|
375
421
|
return pk;
|
|
376
422
|
};
|
|
377
|
-
|
|
378
|
-
|
|
423
|
+
/** Reads a PreciseNumber (Number type in Rust) as float - 32 bytes (4 x u64) */
|
|
424
|
+
const readPreciseNumberAsFloat = () => {
|
|
379
425
|
const nums = [];
|
|
380
426
|
for (let i = 0; i < 4; i++) {
|
|
381
427
|
nums.push(new anchor_1.BN(data.slice(offset + i * 8, offset + (i + 1) * 8), undefined, "le"));
|
|
@@ -383,94 +429,81 @@ function deserializeMarketThreeTicks(data) {
|
|
|
383
429
|
offset += 32;
|
|
384
430
|
return parseFloat(precise_number_1.PreciseNumber.fromRaw(nums).valueString);
|
|
385
431
|
};
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
432
|
+
/** Reads a PreciseNumber (Number type in Rust) as raw bigint - 32 bytes (4 x u64 = 256 bits) */
|
|
433
|
+
const readPreciseNumberAsBigint = () => {
|
|
434
|
+
let val = 0n;
|
|
435
|
+
for (let i = 0; i < 4; i++) {
|
|
436
|
+
const chunk = data.readBigUInt64LE(offset + i * 8);
|
|
437
|
+
val += chunk << BigInt(i * 64);
|
|
438
|
+
}
|
|
439
|
+
offset += 32;
|
|
440
|
+
return val;
|
|
441
|
+
};
|
|
442
|
+
const skip = (bytes) => {
|
|
443
|
+
offset += bytes;
|
|
444
|
+
};
|
|
445
|
+
// ─── Parse RedBlackTree header ────────────────────────────────────────────
|
|
446
|
+
skip(4); // root: u32
|
|
447
|
+
skip(12); // padding to align NodeAllocator
|
|
448
|
+
skip(8); // size: u64
|
|
449
|
+
skip(4); // bump_index: u32
|
|
450
|
+
skip(4); // free_list_head: u32
|
|
451
|
+
// ─── Parse tick nodes ─────────────────────────────────────────────────────
|
|
400
452
|
const ticks = [];
|
|
401
453
|
for (let i = 0; i < MAX_TICK_NODES; i++) {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
const
|
|
410
|
-
|
|
411
|
-
const
|
|
412
|
-
|
|
413
|
-
const
|
|
414
|
-
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
const liquidityGross = data.readBigInt64LE(offset);
|
|
418
|
-
offset += 8;
|
|
419
|
-
const impliedRate = data.readDoubleLE(offset);
|
|
420
|
-
offset += 8;
|
|
421
|
-
const principalPt = data.readBigInt64LE(offset);
|
|
422
|
-
offset += 8;
|
|
423
|
-
const principalSy = data.readBigInt64LE(offset);
|
|
424
|
-
offset += 8;
|
|
425
|
-
const principalShareSupply = data.readBigInt64LE(offset);
|
|
426
|
-
offset += 8;
|
|
427
|
-
// Parse FarmYieldTrackers (3 trackers x 32 bytes each)
|
|
454
|
+
// RBNode header: left(4) + right(4) + parent(4) + color(4) = 16 bytes
|
|
455
|
+
skip(16);
|
|
456
|
+
// Key: u32 + padding to 8 bytes
|
|
457
|
+
const apyBasePoints = readU32();
|
|
458
|
+
skip(4); // padding
|
|
459
|
+
// Tick value (416 bytes total)
|
|
460
|
+
const feeGrowthOutsidePt = readU128(); // 16 bytes
|
|
461
|
+
const feeGrowthOutsideSy = readU128(); // 16 bytes
|
|
462
|
+
const liquidityNet = readI128(); // 16 bytes
|
|
463
|
+
const liquidityGross = readU64(); // 8 bytes
|
|
464
|
+
const spotPrice = readF64(); // 8 bytes
|
|
465
|
+
const principalPt = readU64(); // 8 bytes
|
|
466
|
+
const principalSy = readU64(); // 8 bytes
|
|
467
|
+
const principalShareSupply = readPreciseNumberAsBigint(); // 32 bytes - kept as bigint for arithmetic
|
|
468
|
+
// FarmYieldTrackers: 2 x FarmYieldTracker(32 bytes) = 64 bytes
|
|
428
469
|
const farms = [];
|
|
429
470
|
for (let j = 0; j < PERSONAL_TICK_YIELD_TRACKER_SIZE; j++) {
|
|
430
|
-
farms.push({ lastSeenIndex:
|
|
471
|
+
farms.push({ lastSeenIndex: readPreciseNumberAsFloat() });
|
|
431
472
|
}
|
|
432
|
-
//
|
|
473
|
+
// EmissionYieldTrackers: 2 x EmissionYieldTracker(64 bytes) = 128 bytes
|
|
433
474
|
const emissions = [];
|
|
434
475
|
for (let j = 0; j < PERSONAL_TICK_YIELD_TRACKER_SIZE; j++) {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
476
|
+
emissions.push({
|
|
477
|
+
lastSeenIndex: readPreciseNumberAsFloat(),
|
|
478
|
+
lastPositionIndex: readPreciseNumberAsFloat(),
|
|
479
|
+
});
|
|
438
480
|
}
|
|
439
|
-
|
|
440
|
-
const
|
|
441
|
-
offset += 8;
|
|
442
|
-
// Skip padding (u64)
|
|
443
|
-
offset += 8;
|
|
444
|
-
if (apyBasePoints === 0)
|
|
445
|
-
continue;
|
|
481
|
+
const lastSplitEpoch = readU64(); // 8 bytes
|
|
482
|
+
const frozenLiquidity = readU64(); // 8 bytes
|
|
446
483
|
ticks.push({
|
|
447
484
|
apyBasePoints,
|
|
448
485
|
liquidityNet,
|
|
449
486
|
feeGrowthOutsidePt,
|
|
450
487
|
feeGrowthOutsideSy,
|
|
451
488
|
liquidityGross,
|
|
452
|
-
impliedRate,
|
|
489
|
+
impliedRate: spotPrice, // Legacy field name kept for compatibility
|
|
453
490
|
principalPt,
|
|
454
491
|
principalSy,
|
|
455
492
|
principalShareSupply,
|
|
456
493
|
farms,
|
|
457
494
|
emissions,
|
|
458
495
|
lastSplitEpoch,
|
|
496
|
+
frozenLiquidity,
|
|
459
497
|
});
|
|
460
|
-
// console.log(ticks)
|
|
461
498
|
}
|
|
462
|
-
|
|
463
|
-
const
|
|
464
|
-
|
|
465
|
-
const feeGrowthIndexGlobalSy =
|
|
466
|
-
|
|
467
|
-
const
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
offset += 8;
|
|
471
|
-
const currentTick = data.readUint32LE(offset);
|
|
472
|
-
offset += 4;
|
|
473
|
-
offset += 12; // padding
|
|
499
|
+
// ─── Parse Ticks footer ───────────────────────────────────────────────────
|
|
500
|
+
const market = readPubkey(); // 32 bytes
|
|
501
|
+
const feeGrowthIndexGlobalPt = readU128(); // 16 bytes
|
|
502
|
+
const feeGrowthIndexGlobalSy = readU128(); // 16 bytes
|
|
503
|
+
const currentPrefixSum = readU64(); // 8 bytes
|
|
504
|
+
const currentSpotPrice = readF64(); // 8 bytes
|
|
505
|
+
const currentTick = readU32(); // 4 bytes
|
|
506
|
+
skip(12); // padding
|
|
474
507
|
return {
|
|
475
508
|
ticksTree: ticks,
|
|
476
509
|
market,
|
|
@@ -482,7 +515,50 @@ function deserializeMarketThreeTicks(data) {
|
|
|
482
515
|
};
|
|
483
516
|
}
|
|
484
517
|
exports.deserializeMarketThreeTicks = deserializeMarketThreeTicks;
|
|
518
|
+
/** Decoded account may use snake_case (from JSON IDL); normalize to camelCase for app use. */
|
|
519
|
+
function normalizeCpiContext(a) {
|
|
520
|
+
return {
|
|
521
|
+
altIndex: a.altIndex ?? a.alt_index ?? 0,
|
|
522
|
+
isSigner: a.isSigner ?? a.is_signer ?? false,
|
|
523
|
+
isWritable: a.isWritable ?? a.is_writable ?? false,
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
function normalizeCpiAccountIndexes(raw) {
|
|
527
|
+
const arr = (key, snake) => {
|
|
528
|
+
const a = raw[key] ?? raw[snake];
|
|
529
|
+
return Array.isArray(a) ? a.map((x) => normalizeCpiContext(x)) : [];
|
|
530
|
+
};
|
|
531
|
+
const arr2 = (key, snake) => {
|
|
532
|
+
const a = raw[key] ?? raw[snake];
|
|
533
|
+
return Array.isArray(a) ? a.map((inner) => (Array.isArray(inner) ? inner.map((x) => normalizeCpiContext(x)) : [])) : [];
|
|
534
|
+
};
|
|
535
|
+
return {
|
|
536
|
+
getSyState: arr("getSyState", "get_sy_state"),
|
|
537
|
+
withdrawSy: arr("withdrawSy", "withdraw_sy"),
|
|
538
|
+
depositSy: arr("depositSy", "deposit_sy"),
|
|
539
|
+
claimEmission: arr2("claimEmission", "claim_emission"),
|
|
540
|
+
getPositionState: arr("getPositionState", "get_position_state"),
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
function normalizeMarketCpiCoreIndexes(raw) {
|
|
544
|
+
const arr = (key, snake) => {
|
|
545
|
+
const a = raw[key] ?? raw[snake];
|
|
546
|
+
return Array.isArray(a) ? a.map((x) => normalizeCpiContext(x)) : [];
|
|
547
|
+
};
|
|
548
|
+
return {
|
|
549
|
+
stripSy: arr("stripSy", "strip_sy"),
|
|
550
|
+
mergeSy: arr("mergeSy", "merge_sy"),
|
|
551
|
+
};
|
|
552
|
+
}
|
|
485
553
|
function deserializeMarketThree(m) {
|
|
554
|
+
const rawCpiSy = m.cpiSyAccounts ?? m.cpi_sy_accounts;
|
|
555
|
+
const rawCpiCore = m.cpiCoreAccounts ?? m.cpi_core_accounts;
|
|
556
|
+
const cpiSyAccounts = rawCpiSy != null && typeof rawCpiSy === "object"
|
|
557
|
+
? normalizeCpiAccountIndexes(rawCpiSy)
|
|
558
|
+
: (m.cpiSyAccounts ?? { getSyState: [], withdrawSy: [], depositSy: [], claimEmission: [], getPositionState: [] });
|
|
559
|
+
const cpiCoreAccounts = rawCpiCore != null && typeof rawCpiCore === "object"
|
|
560
|
+
? normalizeMarketCpiCoreIndexes(rawCpiCore)
|
|
561
|
+
: (m.cpiCoreAccounts ?? { stripSy: [], mergeSy: [] });
|
|
486
562
|
return {
|
|
487
563
|
addressLookupTable: m.addressLookupTable,
|
|
488
564
|
mintSy: m.mintSy,
|
|
@@ -495,7 +571,7 @@ function deserializeMarketThree(m) {
|
|
|
495
571
|
selfAddress: m.selfAddress,
|
|
496
572
|
syProgram: m.syProgram,
|
|
497
573
|
statusFlags: m.statusFlags,
|
|
498
|
-
cpiSyAccounts
|
|
574
|
+
cpiSyAccounts,
|
|
499
575
|
isCurrentFlashSwap: m.isCurrentFlashSwap,
|
|
500
576
|
lpFarm: m.lpFarm,
|
|
501
577
|
mintYt: m.mintYt,
|
|
@@ -524,10 +600,12 @@ function deserializeMarketThree(m) {
|
|
|
524
600
|
syBalance: BigInt(m.financials.syBalance.toString()),
|
|
525
601
|
liquidityBalance: BigInt(m.financials.liquidityBalance.toString()),
|
|
526
602
|
},
|
|
527
|
-
cpiCoreAccounts
|
|
603
|
+
cpiCoreAccounts,
|
|
528
604
|
exponentCoreProgram: m.exponentCoreProgram,
|
|
605
|
+
seedId: m.seedId,
|
|
529
606
|
};
|
|
530
607
|
}
|
|
608
|
+
exports.deserializeMarketThree = deserializeMarketThree;
|
|
531
609
|
function deserializeMarketTwo(m) {
|
|
532
610
|
return {
|
|
533
611
|
ptBalance: BigInt(m.financials.ptBalance.toString()),
|
|
@@ -584,7 +662,7 @@ function deserializeLpPositionCLMM(x) {
|
|
|
584
662
|
tickIdx: tracker.tickIdx,
|
|
585
663
|
rightTickIdx: tracker.rightTickIdx,
|
|
586
664
|
splitEpoch: BigInt(tracker.splitEpoch.toString()),
|
|
587
|
-
lpShare:
|
|
665
|
+
lpShare: anchorizedPNumToRawBigint(tracker.lpShare),
|
|
588
666
|
emissions: tracker.emissions.trackers.map((e) => ({
|
|
589
667
|
staged: BigInt(e.staged.toString()),
|
|
590
668
|
lastSeenIndex: parseFloat(precise_number_1.PreciseNumber.fromRaw(e.lastSeenIndex[0]).valueString),
|
|
@@ -640,8 +718,8 @@ function deserializeOrderbook(data) {
|
|
|
640
718
|
offset += 8;
|
|
641
719
|
const priceDecimals = data.readUint8(offset);
|
|
642
720
|
offset += 1;
|
|
643
|
-
// Skip ConfigurationOptions padding: _placeholder_one[15] + _placeholder_two[32] + _placeholder_three[32] + _placeholder_four[32] =
|
|
644
|
-
offset +=
|
|
721
|
+
// Skip ConfigurationOptions padding: _placeholder_one[15] + _placeholder_two[32] + _placeholder_three[32] + _placeholder_four[32] + _reserved[1024] = 1135 bytes
|
|
722
|
+
offset += 1135;
|
|
645
723
|
// Pubkeys
|
|
646
724
|
const vault = readPubkey();
|
|
647
725
|
const yieldPosition = readPubkey();
|
|
@@ -653,7 +731,14 @@ function deserializeOrderbook(data) {
|
|
|
653
731
|
const tokenEscrowPt = readPubkey();
|
|
654
732
|
const cpiAccountOrderbook = readPubkey();
|
|
655
733
|
const admin = readPubkey();
|
|
656
|
-
//
|
|
734
|
+
// last_sy_exchange_rate (Number type = 32 bytes, PreciseNumber with 12 decimals)
|
|
735
|
+
const lastSyExchangeRateRaw = (() => {
|
|
736
|
+
let val = 0n;
|
|
737
|
+
for (let i = 0; i < 4; i++) {
|
|
738
|
+
val += data.readBigUInt64LE(offset + i * 8) << BigInt(i * 64);
|
|
739
|
+
}
|
|
740
|
+
return val;
|
|
741
|
+
})();
|
|
657
742
|
offset += 32;
|
|
658
743
|
// OrderbookFinancials struct
|
|
659
744
|
// Skip last_seen_sy_index (Number type = 32 bytes)
|
|
@@ -694,11 +779,12 @@ function deserializeOrderbook(data) {
|
|
|
694
779
|
};
|
|
695
780
|
// console.log("financials", financials)
|
|
696
781
|
// ─── Parse RedBlackTree slab ───────────────────────────────────────────────
|
|
697
|
-
//
|
|
782
|
+
// RedBlackTree struct: root: u32, _padding: [u32; 3], allocator: NodeAllocator<...>
|
|
783
|
+
// Total before allocator = 4 + 12 = 16 bytes
|
|
698
784
|
const root = data.readUInt32LE(offset);
|
|
699
785
|
offset += 4;
|
|
700
|
-
const
|
|
701
|
-
offset +=
|
|
786
|
+
const padding = 12; // _padding: [u32; 3] in RedBlackTree struct
|
|
787
|
+
offset += padding;
|
|
702
788
|
// NodeAllocator<T=RBNode<u32,PriceNode>, N=MAX_PRICE_NODES, R=3>
|
|
703
789
|
// header: size:u64, bump_index:u32, free_list_head:u32
|
|
704
790
|
const priceTreeSize = Number(data.readBigUInt64LE(offset));
|
|
@@ -736,9 +822,9 @@ function deserializeOrderbook(data) {
|
|
|
736
822
|
// header: size:u64, bump_index:u32, free_list_head:u32
|
|
737
823
|
const offersSize = Number(data.readBigUInt64LE(offset));
|
|
738
824
|
offset += 8;
|
|
739
|
-
const
|
|
825
|
+
const offersBumpIndex = data.readUInt32LE(offset);
|
|
740
826
|
offset += 4;
|
|
741
|
-
const
|
|
827
|
+
const offersFreeListHead = data.readUInt32LE(offset);
|
|
742
828
|
offset += 4;
|
|
743
829
|
const offers = [];
|
|
744
830
|
for (let i = 0; i < exponent_types_2.MAX_OFFERS; i++) {
|
|
@@ -766,6 +852,7 @@ function deserializeOrderbook(data) {
|
|
|
766
852
|
if (userVaultPointer === 0)
|
|
767
853
|
continue;
|
|
768
854
|
offers.push({
|
|
855
|
+
offerIndex: i + 1,
|
|
769
856
|
nextOfferPointer,
|
|
770
857
|
amount,
|
|
771
858
|
userVaultPointer,
|
|
@@ -795,7 +882,12 @@ function deserializeOrderbook(data) {
|
|
|
795
882
|
offset += 4;
|
|
796
883
|
const user = new anchor_1.web3.PublicKey(data.slice(offset, offset + 32));
|
|
797
884
|
offset += 32;
|
|
798
|
-
|
|
885
|
+
const yieldIndexRaw = [[new anchor_1.BN(0), new anchor_1.BN(0), new anchor_1.BN(0), new anchor_1.BN(0)]];
|
|
886
|
+
for (let word = 0; word < 4; word++) {
|
|
887
|
+
yieldIndexRaw[0][word] = new anchor_1.BN(data.subarray(offset + word * 8, offset + (word + 1) * 8), "le");
|
|
888
|
+
}
|
|
889
|
+
const yieldIndex = deserializeAnchorizedPNum(yieldIndexRaw);
|
|
890
|
+
offset += 32;
|
|
799
891
|
const ptAmount = data.readBigUInt64LE(offset);
|
|
800
892
|
offset += 8;
|
|
801
893
|
const syAmount = data.readBigUInt64LE(offset);
|
|
@@ -807,9 +899,8 @@ function deserializeOrderbook(data) {
|
|
|
807
899
|
const staged = data.readBigInt64LE(offset);
|
|
808
900
|
offset += 8;
|
|
809
901
|
offset += 8; // reserved
|
|
810
|
-
if (user.toBase58() == "11111111111111111111111111111111")
|
|
811
|
-
|
|
812
|
-
userEscrows.push({ user, yieldIndex: 0, ptAmount, syAmount, ytAmount, stakedYtAmount, staged });
|
|
902
|
+
// if (user.toBase58() == "11111111111111111111111111111111") continue
|
|
903
|
+
userEscrows.push({ user, yieldIndex, ptAmount, syAmount, ytAmount, stakedYtAmount, staged });
|
|
813
904
|
}
|
|
814
905
|
// ─── Finally, seed_id + signer_bump + reserved ─────────────────────────────
|
|
815
906
|
// seed_id: [u8; 4]
|
|
@@ -836,11 +927,14 @@ function deserializeOrderbook(data) {
|
|
|
836
927
|
tokenEscrowYt,
|
|
837
928
|
tokenEscrowPt,
|
|
838
929
|
cpiAccountOrderbook,
|
|
930
|
+
lastSyExchangeRate: lastSyExchangeRateRaw,
|
|
839
931
|
financials,
|
|
840
932
|
prices,
|
|
841
933
|
configurationOptions,
|
|
842
934
|
offers,
|
|
843
935
|
userEscrows,
|
|
936
|
+
offersBumpIndex,
|
|
937
|
+
offersFreeListHead,
|
|
844
938
|
};
|
|
845
939
|
}
|
|
846
940
|
function deserializeMarginfiSyMeta(x) {
|
|
@@ -966,6 +1060,16 @@ exports.deserializeEmission = deserializeEmission;
|
|
|
966
1060
|
function deserializeAnchorizedPNum(x) {
|
|
967
1061
|
return parseFloat(precise_number_1.PreciseNumber.fromRaw(x[0]).valueString);
|
|
968
1062
|
}
|
|
1063
|
+
/** Convert PreciseNumber (Number type in Rust) from Anchor format to raw 256-bit bigint */
|
|
1064
|
+
function anchorizedPNumToRawBigint(pnum) {
|
|
1065
|
+
const bnArray = pnum[0];
|
|
1066
|
+
let val = 0n;
|
|
1067
|
+
for (let i = 0; i < 4; i++) {
|
|
1068
|
+
val += BigInt(bnArray[i].toString()) << BigInt(i * 64);
|
|
1069
|
+
}
|
|
1070
|
+
return val;
|
|
1071
|
+
}
|
|
1072
|
+
exports.anchorizedPNumToRawBigint = anchorizedPNumToRawBigint;
|
|
969
1073
|
/** Fetch the exchange rate of a JitoRestaking vault's VRT to JitoSOL */
|
|
970
1074
|
async function fetchJitoVaultData({ connection, vaultAddress, }) {
|
|
971
1075
|
const vaultAccountInfo = await connection.getAccountInfo(vaultAddress);
|
|
@@ -1087,24 +1191,60 @@ async function fetchKaminoVaultIndex({ connection, kaminoVaultAccount, }) {
|
|
|
1087
1191
|
const account = await connection.getAccountInfo(kaminoVaultAccount);
|
|
1088
1192
|
const coder = new anchor_2.BorshCoder(kamino_vault_idl_1.IDL);
|
|
1089
1193
|
const data = coder.accounts.decode("VaultState", account.data);
|
|
1090
|
-
const
|
|
1091
|
-
.
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1194
|
+
const activeAllocations = data.vault_allocation_strategy
|
|
1195
|
+
.filter((allocation) => allocation.reserve.toBase58() !== anchor_1.web3.PublicKey.default.toBase58());
|
|
1196
|
+
const activeReserves = activeAllocations.map((allocation) => allocation.reserve);
|
|
1197
|
+
const [activeReservesData, tokenMintInfo, sharesMintInfo] = await Promise.all([
|
|
1198
|
+
connection.getMultipleAccountsInfo(activeReserves),
|
|
1199
|
+
connection.getAccountInfo(data.token_mint),
|
|
1200
|
+
connection.getAccountInfo(data.shares_mint),
|
|
1201
|
+
]);
|
|
1202
|
+
const decodedReserves = activeReservesData.map((accountInfo, index) => {
|
|
1203
|
+
if (!accountInfo?.data) {
|
|
1204
|
+
throw new Error(`Missing Kamino reserve account ${activeReserves[index].toBase58()}`);
|
|
1205
|
+
}
|
|
1206
|
+
return kamino_reserve_deserializer_1.Reserve.decode(accountInfo.data);
|
|
1207
|
+
});
|
|
1208
|
+
const collateralMintInfos = await connection.getMultipleAccountsInfo(decodedReserves.map((reserve) => reserve.collateral.mintPubkey));
|
|
1095
1209
|
const reserves = activeReserves.map((r, i) => {
|
|
1096
|
-
|
|
1210
|
+
const reserveAccount = decodedReserves[i];
|
|
1211
|
+
const allocation = activeAllocations[i];
|
|
1212
|
+
const [lendingMarketAuthority] = anchor_1.web3.PublicKey.findProgramAddressSync([Buffer.from("lma"), reserveAccount.lendingMarket.toBuffer()], new anchor_1.web3.PublicKey("KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD"));
|
|
1097
1213
|
return {
|
|
1098
1214
|
reserveAddress: r,
|
|
1099
|
-
|
|
1215
|
+
marketAddress: reserveAccount.lendingMarket,
|
|
1216
|
+
ctokenVault: allocation.ctoken_vault,
|
|
1217
|
+
lendingMarketAuthority,
|
|
1218
|
+
pythOracle: reserveAccount.config.tokenInfo.pythConfiguration.price,
|
|
1219
|
+
switchboardPriceOracle: reserveAccount.config.tokenInfo.switchboardConfiguration.priceAggregator,
|
|
1220
|
+
switchboardTwapOracle: reserveAccount.config.tokenInfo.switchboardConfiguration.twapAggregator,
|
|
1221
|
+
scopePrices: reserveAccount.config.tokenInfo.scopeConfiguration.priceFeed,
|
|
1222
|
+
reserveLiquiditySupply: reserveAccount.liquidity.supplyVault,
|
|
1223
|
+
reserveCollateralMint: reserveAccount.collateral.mintPubkey,
|
|
1224
|
+
reserveCollateralTokenProgram: collateralMintInfos[i]?.owner ?? anchor_1.web3.PublicKey.default,
|
|
1100
1225
|
};
|
|
1101
1226
|
});
|
|
1102
|
-
console.log("reserves", reserves);
|
|
1103
1227
|
const tokenVault = data.token_vault;
|
|
1104
1228
|
const tokenMint = data.token_mint;
|
|
1105
1229
|
const baseVaultAuthority = data.base_vault_authority;
|
|
1106
1230
|
const sharesMint = data.shares_mint;
|
|
1107
|
-
|
|
1231
|
+
const vaultLookupTable = data.vault_lookup_table ?? anchor_1.web3.PublicKey.default;
|
|
1232
|
+
const tokenProgram = tokenMintInfo?.owner ?? anchor_1.web3.PublicKey.default;
|
|
1233
|
+
const sharesTokenProgram = sharesMintInfo?.owner ?? anchor_1.web3.PublicKey.default;
|
|
1234
|
+
return {
|
|
1235
|
+
index: 1,
|
|
1236
|
+
tokenVault,
|
|
1237
|
+
tokenMint,
|
|
1238
|
+
tokenProgram,
|
|
1239
|
+
// Kamino Vault withdraw expects the singleton program global config account.
|
|
1240
|
+
// It is not stored on VaultState, so fetch it from the known program-wide address.
|
|
1241
|
+
globalConfig: KAMINO_VAULT_GLOBAL_CONFIG,
|
|
1242
|
+
baseVaultAuthority,
|
|
1243
|
+
sharesMint,
|
|
1244
|
+
sharesTokenProgram,
|
|
1245
|
+
vaultLookupTable,
|
|
1246
|
+
reserves,
|
|
1247
|
+
};
|
|
1108
1248
|
}
|
|
1109
1249
|
exports.fetchKaminoVaultIndex = fetchKaminoVaultIndex;
|
|
1110
1250
|
async function fetchFragmetricSupportedTokenIndex({ connection, fragmetricFund, index, }) {
|
|
@@ -1192,7 +1332,7 @@ async function fetchSolsticeRedemptionRate({ connection, yieldPool, vestingSched
|
|
|
1192
1332
|
}
|
|
1193
1333
|
exports.fetchSolsticeRedemptionRate = fetchSolsticeRedemptionRate;
|
|
1194
1334
|
const REFLECT_ORACLE_LEN = 17;
|
|
1195
|
-
const REFLECT_MAX_STALENESS_SLOTS =
|
|
1335
|
+
const REFLECT_MAX_STALENESS_SLOTS = 15000000;
|
|
1196
1336
|
async function fetchReflectRedemptionRate({ connection, oracle, }) {
|
|
1197
1337
|
const accountInfo = await connection.getAccountInfo(oracle);
|
|
1198
1338
|
if (!accountInfo) {
|
|
@@ -1236,4 +1376,14 @@ async function fetchOreExchangeRate({ connection, storeMint, stakeAccount, treas
|
|
|
1236
1376
|
});
|
|
1237
1377
|
}
|
|
1238
1378
|
exports.fetchOreExchangeRate = fetchOreExchangeRate;
|
|
1379
|
+
async function fetchChainlinkRate({ connection, priceFeed, }) {
|
|
1380
|
+
const accountInfo = await connection.getAccountInfo(priceFeed);
|
|
1381
|
+
if (!accountInfo) {
|
|
1382
|
+
throw new Error("Chainlink price feed account not found");
|
|
1383
|
+
}
|
|
1384
|
+
const { answer, header } = (0, chainlink_idl_1.decodeChainlinkPriceAccount)(accountInfo);
|
|
1385
|
+
const scale = Math.pow(10, header.decimals);
|
|
1386
|
+
return Number(answer) / scale;
|
|
1387
|
+
}
|
|
1388
|
+
exports.fetchChainlinkRate = fetchChainlinkRate;
|
|
1239
1389
|
//# sourceMappingURL=exponentFetcher.js.map
|