@exponent-labs/exponent-fetcher 0.1.6 → 0.1.8

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.
Files changed (50) hide show
  1. package/build/exponentFetcher.d.ts +303 -31
  2. package/build/exponentFetcher.js +666 -168
  3. package/build/exponentFetcher.js.map +1 -1
  4. package/build/index.d.ts +10 -0
  5. package/build/index.js +10 -0
  6. package/build/index.js.map +1 -1
  7. package/build/utils/adrena.d.ts +13 -0
  8. package/build/utils/adrena.js +29 -0
  9. package/build/utils/adrena.js.map +1 -0
  10. package/build/utils/fragmetric.d.ts +17 -0
  11. package/build/utils/fragmetric.js +23 -0
  12. package/build/utils/fragmetric.js.map +1 -0
  13. package/build/utils/jito.d.ts +7 -0
  14. package/build/utils/jito.js +29 -0
  15. package/build/utils/jito.js.map +1 -0
  16. package/build/utils/jupiter.d.ts +30 -0
  17. package/build/utils/jupiter.js +63 -0
  18. package/build/utils/jupiter.js.map +1 -0
  19. package/build/utils/kamino.d.ts +5 -0
  20. package/build/utils/kamino.js +10 -0
  21. package/build/utils/kamino.js.map +1 -0
  22. package/build/utils/meteora.d.ts +19 -0
  23. package/build/utils/meteora.js +36 -1
  24. package/build/utils/meteora.js.map +1 -1
  25. package/build/utils/ore.d.ts +74 -0
  26. package/build/utils/ore.js +217 -0
  27. package/build/utils/ore.js.map +1 -0
  28. package/build/utils/perena.d.ts +12 -0
  29. package/build/utils/perena.js +27 -0
  30. package/build/utils/perena.js.map +1 -0
  31. package/build/utils/sanctum.d.ts +6 -0
  32. package/build/utils/sanctum.js +26 -0
  33. package/build/utils/sanctum.js.map +1 -0
  34. package/build/utils/solstice.d.ts +12 -0
  35. package/build/utils/solstice.js +45 -0
  36. package/build/utils/solstice.js.map +1 -0
  37. package/package.json +20 -18
  38. package/src/exponentFetcher.ts +1077 -222
  39. package/src/index.ts +10 -0
  40. package/src/utils/adrena.ts +44 -0
  41. package/src/utils/fragmetric.ts +34 -0
  42. package/src/utils/jito.ts +30 -0
  43. package/src/utils/jupiter.ts +98 -0
  44. package/src/utils/kamino.ts +6 -0
  45. package/src/utils/meteora.ts +73 -1
  46. package/src/utils/ore.ts +322 -0
  47. package/src/utils/perena.ts +28 -0
  48. package/src/utils/sanctum.ts +24 -0
  49. package/src/utils/solstice.ts +51 -0
  50. package/tsconfig.json +2 -0
@@ -3,18 +3,18 @@ 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.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.ExponentFetcher = exports.MyWallet = exports.deserializeAnchorizedPNumFromJson = exports.serializeAnchorizedPNumFromJson = void 0;
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;
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
- const spl_token_2 = require("@solana/spl-token");
11
+ const bs58_1 = __importDefault(require("bs58"));
12
12
  const decimal_js_1 = __importDefault(require("decimal.js"));
13
+ const exponent_clmm_idl_1 = require("@exponent-labs/exponent-clmm-idl");
13
14
  const exponent_idl_1 = require("@exponent-labs/exponent-idl");
15
+ const exponent_orderbook_idl_1 = require("@exponent-labs/exponent-orderbook-idl");
14
16
  const exponent_types_1 = require("@exponent-labs/exponent-types");
15
- const fragmetric_idl_1 = require("@exponent-labs/fragmetric-idl");
16
- const jupiter_lend_idl_1 = require("@exponent-labs/jupiter-lend-idl");
17
- const kamino_vault_idl_1 = require("@exponent-labs/kamino-vault-idl");
17
+ const exponent_types_2 = require("@exponent-labs/exponent-types");
18
18
  const generic_sy_idl_1 = require("@exponent-labs/generic-sy-idl");
19
19
  const jito_restaking_sy_idl_1 = require("@exponent-labs/jito-restaking-sy-idl");
20
20
  const jito_restaking_sy_idl_2 = require("@exponent-labs/jito-restaking-sy-idl");
@@ -22,22 +22,31 @@ const kamino_reserve_deserializer_1 = require("@exponent-labs/kamino-reserve-des
22
22
  const kamino_reserve_deserializer_2 = require("@exponent-labs/kamino-reserve-deserializer");
23
23
  const kamino_sy_idl_1 = require("@exponent-labs/kamino-sy-idl");
24
24
  const kamino_sy_idl_2 = require("@exponent-labs/kamino-sy-idl");
25
+ const kamino_vault_idl_1 = require("@exponent-labs/kamino-vault-idl");
25
26
  const marginfi_sy_idl_1 = require("@exponent-labs/marginfi-sy-idl");
26
27
  const meteora_idl_1 = require("@exponent-labs/meteora-idl");
27
28
  const perena_sy_idl_1 = require("@exponent-labs/perena-sy-idl");
28
29
  const perena_sy_idl_2 = require("@exponent-labs/perena-sy-idl");
29
30
  const precise_number_1 = require("@exponent-labs/precise-number");
30
- const sanctum_idl_1 = require("@exponent-labs/sanctum-idl");
31
- const adrena_idl_1 = require("@exponent-labs/adrena-idl");
32
- const solstice_idl_1 = require("@exponent-labs/solstice-idl");
31
+ const adrena_1 = require("./utils/adrena");
32
+ const fragmetric_1 = require("./utils/fragmetric");
33
+ const jito_1 = require("./utils/jito");
34
+ const jupiter_1 = require("./utils/jupiter");
33
35
  const meteora_1 = require("./utils/meteora");
34
- // Decode Jupiter Perps pool accounts via helper using Anchor 0.29.0
35
- const jupiter_perps_idl_1 = require("@exponent-labs/jupiter-perps-idl");
36
+ const ore_1 = require("./utils/ore");
37
+ const perena_1 = require("./utils/perena");
38
+ const sanctum_1 = require("./utils/sanctum");
39
+ const solstice_1 = require("./utils/solstice");
36
40
  function serializeAnchorizedPNumFromJson(pnum) {
37
41
  const serializedArray = pnum[0].map((bn) => bn.toString());
38
42
  return { 0: serializedArray };
39
43
  }
40
44
  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
+ }
41
50
  function deserializeAnchorizedPNumFromJson(serialized) {
42
51
  const bnArray = serialized[0].map((str) => new anchor_1.BN(str));
43
52
  return { 0: bnArray };
@@ -81,6 +90,8 @@ class ExponentFetcher {
81
90
  jitoRestakingSyProgram;
82
91
  perenaSyProgram;
83
92
  genericStandardProgram;
93
+ exponentClmmProgram;
94
+ orderbookProgram;
84
95
  connection;
85
96
  coreProgramId;
86
97
  marginfiSyProgramId;
@@ -105,6 +116,8 @@ class ExponentFetcher {
105
116
  this.jitoRestakingSyProgram = new anchor_1.Program(jito_restaking_sy_idl_2.IDL, provider);
106
117
  this.perenaSyProgram = new anchor_1.Program(perena_sy_idl_2.IDL, provider);
107
118
  this.genericStandardProgram = new anchor_1.Program(generic_sy_idl_1.IDL, provider);
119
+ this.exponentClmmProgram = new anchor_1.Program(exponent_clmm_idl_1.IDL, provider);
120
+ this.orderbookProgram = new anchor_1.Program(exponent_orderbook_idl_1.IDL, provider);
108
121
  }
109
122
  async fetchVault(address) {
110
123
  try {
@@ -128,6 +141,28 @@ class ExponentFetcher {
128
141
  throw e;
129
142
  }
130
143
  }
144
+ async fetchOrderbook(address) {
145
+ try {
146
+ const o = (await this.connection.getAccountInfo(address)).data;
147
+ return deserializeOrderbook(o);
148
+ }
149
+ catch (e) {
150
+ console.error(`Error fetching orderbook ${address.toBase58()}`);
151
+ console.error(e);
152
+ throw e;
153
+ }
154
+ }
155
+ async fetchOrderbookCpiAccounts(address) {
156
+ try {
157
+ const orderbookCpiAccounts = await this.orderbookProgram.account.cpiAccountsOrderbook.fetch(address);
158
+ return orderbookCpiAccounts;
159
+ }
160
+ catch (e) {
161
+ console.error(`Error fetching orderbook ${address.toBase58()}`);
162
+ console.error(e);
163
+ throw e;
164
+ }
165
+ }
131
166
  async fetchMarginfiSyMeta(address) {
132
167
  const x = await this.marginfiSyProgram.account.syMeta.fetch(address);
133
168
  return deserializeMarginfiSyMeta(x);
@@ -200,10 +235,59 @@ class ExponentFetcher {
200
235
  const x = await this.program.account.lpPosition.fetch(address);
201
236
  return deserializeLpPosition(x);
202
237
  }
238
+ async fetchLpPositionCLMM(address) {
239
+ try {
240
+ const raw = await this.exponentClmmProgram.account.lpPosition.fetch(address);
241
+ const v = {
242
+ owner: raw.owner,
243
+ market: raw.market,
244
+ feeInsideLastPt: raw.feeInsideLastPt,
245
+ feeInsideLastSy: raw.feeInsideLastSy,
246
+ lpBalance: raw.lpBalance,
247
+ tokensOwedSy: raw.tokensOwedSy,
248
+ tokensOwedPt: raw.tokensOwedPt,
249
+ lowerTickIdx: raw.lowerTickIdx,
250
+ upperTickIdx: raw.upperTickIdx,
251
+ farms: {
252
+ trackers: raw.farms.trackers.map((t) => ({
253
+ staged: t.staged,
254
+ lastSeenIndex: t.lastSeenIndex,
255
+ })),
256
+ },
257
+ shareTrackers: {
258
+ trackers: raw.shareTrackers.trackers.map((tracker) => ({
259
+ tickIdx: tracker.tickIdx,
260
+ rightTickIdx: tracker.rightTickIdx,
261
+ splitEpoch: tracker.splitEpoch,
262
+ lpShare: tracker.lpShare,
263
+ emissions: {
264
+ trackers: tracker.emissions.trackers.map((e) => ({
265
+ staged: e.staged,
266
+ lastSeenIndex: e.lastSeenIndex,
267
+ })),
268
+ },
269
+ })),
270
+ },
271
+ };
272
+ return deserializeLpPositionCLMM(v);
273
+ }
274
+ catch (e) {
275
+ console.error(`Error fetching clmm lp position ${address.toBase58()}`);
276
+ console.error(e);
277
+ throw e;
278
+ }
279
+ }
203
280
  async fetchYtPosition(address) {
204
281
  const x = await this.program.account.yieldTokenPosition.fetch(address);
205
282
  return deserializeYtPosition(x);
206
283
  }
284
+ /** Batch fetch multiple YT positions in a single RPC call */
285
+ async fetchYtPositions(addresses) {
286
+ if (addresses.length === 0)
287
+ return [];
288
+ const results = await this.program.account.yieldTokenPosition.fetchMultiple(addresses);
289
+ return results.map((x) => (x ? deserializeYtPosition(x) : null));
290
+ }
207
291
  async fetchJitoRestakingSyMeta(address) {
208
292
  const x = await this.jitoRestakingSyProgram.account.syMeta.fetch(address);
209
293
  return (0, exponent_types_1.deserializeJitoRestakingSyMetaAccountRaw)(x);
@@ -216,8 +300,234 @@ class ExponentFetcher {
216
300
  const x = await this.genericStandardProgram.account.syMeta.fetch(address);
217
301
  return (0, exponent_types_1.deserializeGenericSyMetaAccountRaw)(x);
218
302
  }
303
+ async fetchAllMarketThree() {
304
+ //TODO Replace with the following code when all damaged markets are removed onchain
305
+ // const marketsProgramAccounts: ProgramAccount<MarketThreeRaw>[] =
306
+ // await this.exponentClmmProgram.account.marketThree.all()
307
+ // return marketsProgramAccounts.map(({ account }) => deserializeMarketThree(account))
308
+ const MARKET_THREE_DISCRIMINATOR = Buffer.from([242, 240, 26, 15, 148, 186, 185, 205]);
309
+ const marketsProgramAccounts = await this.connection.getProgramAccounts(this.exponentClmmProgram.programId, {
310
+ filters: [
311
+ {
312
+ memcmp: {
313
+ offset: 0,
314
+ bytes: bs58_1.default.encode(MARKET_THREE_DISCRIMINATOR),
315
+ },
316
+ },
317
+ ],
318
+ });
319
+ return marketsProgramAccounts
320
+ .map(({ account, pubkey }) => {
321
+ try {
322
+ return this.exponentClmmProgram.coder.accounts.decode("marketThree", account.data);
323
+ }
324
+ catch (error) {
325
+ return null;
326
+ }
327
+ })
328
+ .filter((m) => !!m);
329
+ }
330
+ async fetchMarketThree(address) {
331
+ try {
332
+ const m = await this.exponentClmmProgram.account.marketThree.fetch(address);
333
+ return deserializeMarketThree(m);
334
+ }
335
+ catch (e) {
336
+ console.error(`Error fetching market ${address.toBase58()}`);
337
+ console.error(e);
338
+ throw e;
339
+ }
340
+ }
341
+ async fetchAllMarketThreeTicks() {
342
+ const TICKS_DISCRIMINATOR = Buffer.from([122, 104, 41, 141, 214, 36, 222, 37]);
343
+ const ticksAccounts = await this.connection.getProgramAccounts(this.exponentClmmProgram.programId, {
344
+ filters: [
345
+ {
346
+ memcmp: {
347
+ offset: 0,
348
+ bytes: bs58_1.default.encode(TICKS_DISCRIMINATOR),
349
+ },
350
+ },
351
+ ],
352
+ });
353
+ return ticksAccounts.map(({ account }) => deserializeMarketThreeTicks(account.data));
354
+ }
355
+ async fetchMarketThreeTicks(address) {
356
+ try {
357
+ const m = (await this.connection.getAccountInfo(address)).data;
358
+ return deserializeMarketThreeTicks(m);
359
+ }
360
+ catch (e) {
361
+ console.error(`Error fetching market ${address.toBase58()}`);
362
+ console.error(e);
363
+ throw e;
364
+ }
365
+ }
219
366
  }
220
367
  exports.ExponentFetcher = ExponentFetcher;
368
+ function deserializeMarketThreeTicks(data) {
369
+ let offset = 8;
370
+ const MAX_TICK_NODES = 100;
371
+ const PERSONAL_TICK_YIELD_TRACKER_SIZE = 3;
372
+ const readPubkey = () => {
373
+ const pk = new anchor_1.web3.PublicKey(data.slice(offset, offset + 32));
374
+ offset += 32;
375
+ return pk;
376
+ };
377
+ const readNumber = () => {
378
+ // Number is 32 bytes (4 x u64)
379
+ const nums = [];
380
+ for (let i = 0; i < 4; i++) {
381
+ nums.push(new anchor_1.BN(data.slice(offset + i * 8, offset + (i + 1) * 8), undefined, "le"));
382
+ }
383
+ offset += 32;
384
+ return parseFloat(precise_number_1.PreciseNumber.fromRaw(nums).valueString);
385
+ };
386
+ // ─── Parse RedBlackTree slab ───────────────────────────────────────────────
387
+ // repr(C) gives: root: u32, pad to align NodeAllocator's u64, then the NodeAllocator header
388
+ const root = data.readUInt32LE(offset);
389
+ offset += 4;
390
+ const padTo8 = 12;
391
+ offset += padTo8;
392
+ // NodeAllocator<T=RBNode<u32,PriceNode>, N=MAX_PRICE_NODES, R=3>
393
+ // header: size:u64, bump_index:u32, free_list_head:u32
394
+ const tickTreeSize = Number(data.readBigUInt64LE(offset));
395
+ offset += 8;
396
+ const ticksTreeBump = data.readUInt32LE(offset);
397
+ offset += 4;
398
+ const ticksTreeFreeIdx = data.readUInt32LE(offset);
399
+ offset += 4;
400
+ const ticks = [];
401
+ for (let i = 0; i < MAX_TICK_NODES; i++) {
402
+ const left = data.readUInt32LE(offset);
403
+ offset += 4;
404
+ const right = data.readUInt32LE(offset);
405
+ offset += 4;
406
+ const parent = data.readUInt32LE(offset);
407
+ offset += 4;
408
+ offset += 4; // skip color
409
+ const apyBasePoints = data.readUInt32LE(offset);
410
+ offset += 8;
411
+ const feeGrowthOutsidePt = readU128LE(data, offset);
412
+ offset += 16;
413
+ const feeGrowthOutsideSy = readU128LE(data, offset);
414
+ offset += 16;
415
+ const liquidityNet = data.readBigInt64LE(offset);
416
+ offset += 8;
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)
428
+ const farms = [];
429
+ for (let j = 0; j < PERSONAL_TICK_YIELD_TRACKER_SIZE; j++) {
430
+ farms.push({ lastSeenIndex: readNumber() });
431
+ }
432
+ // Parse EmissionYieldTrackers (3 trackers x 64 bytes each)
433
+ const emissions = [];
434
+ for (let j = 0; j < PERSONAL_TICK_YIELD_TRACKER_SIZE; j++) {
435
+ const lastSeenIndex = readNumber();
436
+ const lastPositionIndex = readNumber();
437
+ emissions.push({ lastSeenIndex, lastPositionIndex });
438
+ }
439
+ // Parse last_split_epoch (u64)
440
+ const lastSplitEpoch = data.readBigUInt64LE(offset);
441
+ offset += 8;
442
+ // Skip padding (u64)
443
+ offset += 8;
444
+ if (apyBasePoints === 0)
445
+ continue;
446
+ ticks.push({
447
+ apyBasePoints,
448
+ liquidityNet,
449
+ feeGrowthOutsidePt,
450
+ feeGrowthOutsideSy,
451
+ liquidityGross,
452
+ impliedRate,
453
+ principalPt,
454
+ principalSy,
455
+ principalShareSupply,
456
+ farms,
457
+ emissions,
458
+ lastSplitEpoch,
459
+ });
460
+ // console.log(ticks)
461
+ }
462
+ const market = readPubkey();
463
+ const feeGrowthIndexGlobalPt = readU128LE(data, offset);
464
+ offset += 16;
465
+ const feeGrowthIndexGlobalSy = readU128LE(data, offset);
466
+ offset += 16;
467
+ const currentPrefixSum = data.readBigUInt64LE(offset); // Active liquidity at current tick
468
+ offset += 8;
469
+ const currentSpotPrice = data.readDoubleLE(offset);
470
+ offset += 8;
471
+ const currentTick = data.readUint32LE(offset);
472
+ offset += 4;
473
+ offset += 12; // padding
474
+ return {
475
+ ticksTree: ticks,
476
+ market,
477
+ feeGrowthIndexGlobalPt,
478
+ feeGrowthIndexGlobalSy,
479
+ currentPrefixSum,
480
+ currentSpotPrice,
481
+ currentTick,
482
+ };
483
+ }
484
+ exports.deserializeMarketThreeTicks = deserializeMarketThreeTicks;
485
+ function deserializeMarketThree(m) {
486
+ return {
487
+ addressLookupTable: m.addressLookupTable,
488
+ mintSy: m.mintSy,
489
+ mintPt: m.mintPt,
490
+ vault: m.vault,
491
+ tokenSyEscrow: m.tokenSyEscrow,
492
+ tokenPtEscrow: m.tokenPtEscrow,
493
+ tokenFeeTreasurySy: m.tokenFeeTreasurySy,
494
+ tokenFeeTreasuryPt: m.tokenFeeTreasuryPt,
495
+ selfAddress: m.selfAddress,
496
+ syProgram: m.syProgram,
497
+ statusFlags: m.statusFlags,
498
+ cpiSyAccounts: m.cpiSyAccounts,
499
+ isCurrentFlashSwap: m.isCurrentFlashSwap,
500
+ lpFarm: m.lpFarm,
501
+ mintYt: m.mintYt,
502
+ tokenYtEscrow: m.tokenYtEscrow,
503
+ emissions: {
504
+ trackers: m.emissions.trackers.map((t) => ({
505
+ tokenEscrow: t.tokenEscrow,
506
+ lpShareIndex: deserializeAnchorizedPNum(t.lpShareIndex),
507
+ lastSeenStaged: Number(t.lastSeenStaged),
508
+ })),
509
+ },
510
+ liquidityNetBalanceLimits: m.liquidityNetBalanceLimits,
511
+ admin: m.admin,
512
+ ticks: m.ticks,
513
+ configurationOptions: {
514
+ lnFeeRateRoot: m.configurationOptions.lnFeeRateRoot,
515
+ treasuryFeeBps: m.configurationOptions.treasuryFeeBps,
516
+ minLpTickAmount: BigInt(m.configurationOptions.minLpTickAmount.toString()),
517
+ epsilonClamp: m.configurationOptions.epsilonClamp,
518
+ maxLpSupply: BigInt(m.configurationOptions.maxLpSupply.toString()),
519
+ tickSpace: m.configurationOptions.tickSpace,
520
+ },
521
+ financials: {
522
+ expirationTs: BigInt(m.financials.expirationTs),
523
+ ptBalance: BigInt(m.financials.ptBalance.toString()),
524
+ syBalance: BigInt(m.financials.syBalance.toString()),
525
+ liquidityBalance: BigInt(m.financials.liquidityBalance.toString()),
526
+ },
527
+ cpiCoreAccounts: m.cpiCoreAccounts,
528
+ exponentCoreProgram: m.exponentCoreProgram,
529
+ };
530
+ }
221
531
  function deserializeMarketTwo(m) {
222
532
  return {
223
533
  ptBalance: BigInt(m.financials.ptBalance.toString()),
@@ -255,6 +565,33 @@ function deserializeMarketTwo(m) {
255
565
  seedId: m.seedId,
256
566
  };
257
567
  }
568
+ function deserializeLpPositionCLMM(x) {
569
+ return {
570
+ owner: x.owner,
571
+ market: x.market,
572
+ feeInsideLastPt: BigInt(x.feeInsideLastPt.toString()),
573
+ feeInsideLastSy: BigInt(x.feeInsideLastSy.toString()),
574
+ lpBalance: BigInt(x.lpBalance.toString()),
575
+ tokensOwedSy: BigInt(x.tokensOwedSy.toString()),
576
+ tokensOwedPt: BigInt(x.tokensOwedPt.toString()),
577
+ lowerTickIdx: x.lowerTickIdx,
578
+ upperTickIdx: x.upperTickIdx,
579
+ farms: x.farms.trackers.map((t) => ({
580
+ staged: BigInt(t.staged.toString()),
581
+ lastSeenIndex: parseFloat(precise_number_1.PreciseNumber.fromRaw(t.lastSeenIndex[0]).valueString),
582
+ })),
583
+ shareTrackers: x.shareTrackers.trackers.map((tracker) => ({
584
+ tickIdx: tracker.tickIdx,
585
+ rightTickIdx: tracker.rightTickIdx,
586
+ splitEpoch: BigInt(tracker.splitEpoch.toString()),
587
+ lpShare: BigInt(tracker.lpShare.toString()),
588
+ emissions: tracker.emissions.trackers.map((e) => ({
589
+ staged: BigInt(e.staged.toString()),
590
+ lastSeenIndex: parseFloat(precise_number_1.PreciseNumber.fromRaw(e.lastSeenIndex[0]).valueString),
591
+ })),
592
+ })),
593
+ };
594
+ }
258
595
  function deserializeVault(x) {
259
596
  return {
260
597
  syProgram: x.syProgram,
@@ -285,6 +622,227 @@ function deserializeVault(x) {
285
622
  maxPySupply: BigInt(x.maxPySupply.toString()),
286
623
  };
287
624
  }
625
+ function deserializeOrderbook(data) {
626
+ let offset = 0;
627
+ // 1) Skip Anchor discriminator
628
+ offset += anchor_1.DISCRIMINATOR_SIZE;
629
+ const readPubkey = () => {
630
+ const pk = new anchor_1.web3.PublicKey(data.slice(offset, offset + 32));
631
+ offset += 32;
632
+ return pk;
633
+ };
634
+ // ConfigurationOptions struct
635
+ const thresholdAmount = data.readBigUInt64LE(offset);
636
+ offset += 8;
637
+ const lnMakerFeeRate = data.readDoubleLE(offset);
638
+ offset += 8;
639
+ const lnTakerFeeRate = data.readDoubleLE(offset);
640
+ offset += 8;
641
+ const priceDecimals = data.readUint8(offset);
642
+ offset += 1;
643
+ // Skip ConfigurationOptions padding: _placeholder_one[15] + _placeholder_two[32] + _placeholder_three[32] + _placeholder_four[32] = 111 bytes
644
+ offset += 111;
645
+ // Pubkeys
646
+ const vault = readPubkey();
647
+ const yieldPosition = readPubkey();
648
+ const addressLookupTable = readPubkey();
649
+ const exponentCoreProgram = readPubkey();
650
+ const syProgram = readPubkey();
651
+ const tokenEscrowSy = readPubkey();
652
+ const tokenEscrowYt = readPubkey();
653
+ const tokenEscrowPt = readPubkey();
654
+ const cpiAccountOrderbook = readPubkey();
655
+ const admin = readPubkey();
656
+ // Skip last_sy_exchange_rate (Number type = 32 bytes)
657
+ offset += 32;
658
+ // OrderbookFinancials struct
659
+ // Skip last_seen_sy_index (Number type = 32 bytes)
660
+ offset += 32;
661
+ const ytBalance = data.readBigUInt64LE(offset);
662
+ offset += 8;
663
+ const syBalance = data.readBigUInt64LE(offset);
664
+ offset += 8;
665
+ const ptBalance = data.readBigUInt64LE(offset);
666
+ offset += 8;
667
+ const ytFeeBalance = data.readBigUInt64LE(offset);
668
+ offset += 8;
669
+ const syFeeBalance = data.readBigUInt64LE(offset);
670
+ offset += 8;
671
+ const ptFeeBalance = data.readBigUInt64LE(offset);
672
+ offset += 8;
673
+ const stagedSyBalance = data.readBigUInt64LE(offset);
674
+ offset += 8;
675
+ const expirationTs = data.readUInt32LE(offset);
676
+ offset += 4;
677
+ // Skip financials _padding: [u8; 4]
678
+ offset += 4;
679
+ const configurationOptions = {
680
+ priceDecimals,
681
+ thresholdAmount,
682
+ lnMakerFeeRate,
683
+ lnTakerFeeRate,
684
+ };
685
+ const financials = {
686
+ expirationTs,
687
+ syBalance: syBalance,
688
+ ytBalance: ytBalance,
689
+ ptBalance: ptBalance,
690
+ ytFeeBalance,
691
+ syFeeBalance,
692
+ ptFeeBalance,
693
+ stagedSy: stagedSyBalance,
694
+ };
695
+ // console.log("financials", financials)
696
+ // ─── Parse RedBlackTree slab ───────────────────────────────────────────────
697
+ // repr(C) gives: root: u32, pad to align NodeAllocator’s u64, then the NodeAllocator header
698
+ const root = data.readUInt32LE(offset);
699
+ offset += 4;
700
+ const padTo8 = 8;
701
+ offset += padTo8;
702
+ // NodeAllocator<T=RBNode<u32,PriceNode>, N=MAX_PRICE_NODES, R=3>
703
+ // header: size:u64, bump_index:u32, free_list_head:u32
704
+ const priceTreeSize = Number(data.readBigUInt64LE(offset));
705
+ offset += 8;
706
+ const _priceTreeBump = data.readUInt32LE(offset);
707
+ offset += 4;
708
+ const _priceTreeFreeIdx = data.readUInt32LE(offset);
709
+ offset += 4;
710
+ // each RBNode entry = registers[3] + key:u32 + first_offer:u32
711
+ const prices = [];
712
+ for (let i = 0; i < exponent_types_2.MAX_PRICE_NODES; i++) {
713
+ const left = data.readUInt32LE(offset);
714
+ offset += 4;
715
+ const right = data.readUInt32LE(offset);
716
+ offset += 4;
717
+ const parent = data.readUInt32LE(offset);
718
+ offset += 4;
719
+ offset += 4; // skip color
720
+ const key = data.readUInt32LE(offset);
721
+ offset += 4;
722
+ const firstOfferSellYt = data.readUInt32LE(offset);
723
+ offset += 4;
724
+ const firstOfferBuyYt = data.readUInt32LE(offset);
725
+ offset += 4;
726
+ const lastOfferSellYt = data.readUInt32LE(offset);
727
+ offset += 4;
728
+ const lastOfferBuyYt = data.readUInt32LE(offset);
729
+ offset += 4;
730
+ if (key === 0)
731
+ continue;
732
+ prices.push({ key, firstOfferSellYt, firstOfferBuyYt, lastOfferSellYt, lastOfferBuyYt, parent, left, right });
733
+ }
734
+ // ─── Parse Offers slab ────────────────────────────────────────────────────
735
+ // NodeAllocator<Offer, MAX_OFFERS, 4>
736
+ // header: size:u64, bump_index:u32, free_list_head:u32
737
+ const offersSize = Number(data.readBigUInt64LE(offset));
738
+ offset += 8;
739
+ const _offersBump = data.readUInt32LE(offset);
740
+ offset += 4;
741
+ const _offersFreeIdx = data.readUInt32LE(offset);
742
+ offset += 4;
743
+ const offers = [];
744
+ for (let i = 0; i < exponent_types_2.MAX_OFFERS; i++) {
745
+ const register = data.readUInt32LE(offset);
746
+ offset += 4;
747
+ const nextOfferPointer = data.readUInt32LE(offset);
748
+ offset += 4;
749
+ const userVaultPointer = data.readUInt32LE(offset);
750
+ offset += 4;
751
+ const pricePointer = data.readUInt32LE(offset);
752
+ offset += 4;
753
+ const amount = data.readBigUInt64LE(offset);
754
+ offset += 8;
755
+ const expiryAt = data.readUInt32LE(offset);
756
+ offset += 4;
757
+ const createdAt = data.readUInt32LE(offset);
758
+ offset += 4;
759
+ const virtualOffer = data.readUInt8(offset) !== 0;
760
+ offset += 1;
761
+ const orderTypeFlag = data.readUInt8(offset);
762
+ offset += 1;
763
+ const fillOrKill = data.readUInt8(offset) !== 0;
764
+ offset += 1;
765
+ offset += 5; // reserved padding
766
+ if (userVaultPointer === 0)
767
+ continue;
768
+ offers.push({
769
+ nextOfferPointer,
770
+ amount,
771
+ userVaultPointer,
772
+ expiryAt,
773
+ createdAt,
774
+ virtualOffer,
775
+ orderTypeFlag,
776
+ fillOrKill,
777
+ pricePointer,
778
+ });
779
+ }
780
+ // ─── Parse UserEscrow slab ────────────────────────────────────────────────
781
+ // NodeAllocator<UserEscrow, MAX_USER_ESCROWS, 2>
782
+ // header: size:u64, bump_index:u32, free_list_head:u32
783
+ const escSize = Number(data.readBigUInt64LE(offset));
784
+ offset += 8;
785
+ const _escBump = data.readUInt32LE(offset);
786
+ offset += 4;
787
+ const _escFreeIdx = data.readUInt32LE(offset);
788
+ offset += 4;
789
+ // each Node = [ no registers ] + UserEscrow.value
790
+ const userEscrows = [];
791
+ for (let i = 0; i < exponent_types_2.MAX_USER_ESCROWS; i++) {
792
+ const register = data.readUInt32LE(offset);
793
+ offset += 4;
794
+ const register2 = data.readUInt32LE(offset);
795
+ offset += 4;
796
+ const user = new anchor_1.web3.PublicKey(data.slice(offset, offset + 32));
797
+ offset += 32;
798
+ /*const yieldIndex = data.readBigUInt64LE(offset).toString();*/ offset += 32;
799
+ const ptAmount = data.readBigUInt64LE(offset);
800
+ offset += 8;
801
+ const syAmount = data.readBigUInt64LE(offset);
802
+ offset += 8;
803
+ const ytAmount = data.readBigUInt64LE(offset);
804
+ offset += 8;
805
+ const stakedYtAmount = data.readBigInt64LE(offset);
806
+ offset += 8;
807
+ const staged = data.readBigInt64LE(offset);
808
+ offset += 8;
809
+ offset += 8; // reserved
810
+ if (user.toBase58() == "11111111111111111111111111111111")
811
+ continue;
812
+ userEscrows.push({ user, yieldIndex: 0, ptAmount, syAmount, ytAmount, stakedYtAmount, staged });
813
+ }
814
+ // ─── Finally, seed_id + signer_bump + reserved ─────────────────────────────
815
+ // seed_id: [u8; 4]
816
+ const seedId = [
817
+ data.readUInt8(offset),
818
+ data.readUInt8(offset + 1),
819
+ data.readUInt8(offset + 2),
820
+ data.readUInt8(offset + 3),
821
+ ];
822
+ offset += 4;
823
+ // signer_bump: [u8; 1]
824
+ const signerBump = data.readUInt8(offset);
825
+ offset += 1;
826
+ // _reserved: [u8; 3] - skip
827
+ offset += 3;
828
+ return {
829
+ vault,
830
+ yieldPosition,
831
+ addressLookupTable,
832
+ exponentCoreProgram,
833
+ syProgram,
834
+ admin,
835
+ tokenEscrowSy,
836
+ tokenEscrowYt,
837
+ tokenEscrowPt,
838
+ cpiAccountOrderbook,
839
+ financials,
840
+ prices,
841
+ configurationOptions,
842
+ offers,
843
+ userEscrows,
844
+ };
845
+ }
288
846
  function deserializeMarginfiSyMeta(x) {
289
847
  return {
290
848
  ...x,
@@ -320,6 +878,7 @@ function deserializeLpPosition(x) {
320
878
  })),
321
879
  };
322
880
  }
881
+ exports.deserializeLpPosition = deserializeLpPosition;
323
882
  function deserializeYtPosition(x) {
324
883
  return {
325
884
  owner: x.owner,
@@ -329,6 +888,7 @@ function deserializeYtPosition(x) {
329
888
  emissions: x.emissions.map(deserializeYieldTokenTracker),
330
889
  };
331
890
  }
891
+ exports.deserializeYtPosition = deserializeYtPosition;
332
892
  function deserializeYieldTokenTracker(x) {
333
893
  return {
334
894
  staged: BigInt(x.staged.toString()),
@@ -340,10 +900,13 @@ async function fetchKaminoReserve(address, connection) {
340
900
  if (!reserve) {
341
901
  throw new Error("Reserve not found");
342
902
  }
903
+ const rawScopePriceFeed = reserve.config.tokenInfo.scopeConfiguration.priceFeed;
904
+ const scopePriceFeed = rawScopePriceFeed.equals(anchor_1.web3.PublicKey.default) ? undefined : rawScopePriceFeed;
343
905
  return {
344
906
  lendingMarket: reserve.lendingMarket,
345
907
  baseMint: reserve.liquidity.mintPubkey,
346
908
  assetShareValue: reserve.getCollateralExchangeRate(),
909
+ scopePriceFeed,
347
910
  };
348
911
  }
349
912
  exports.fetchKaminoReserve = fetchKaminoReserve;
@@ -406,24 +969,7 @@ function deserializeAnchorizedPNum(x) {
406
969
  /** Fetch the exchange rate of a JitoRestaking vault's VRT to JitoSOL */
407
970
  async function fetchJitoVaultData({ connection, vaultAddress, }) {
408
971
  const vaultAccountInfo = await connection.getAccountInfo(vaultAddress);
409
- const d = vaultAccountInfo.data;
410
- // the vault has an 8 byte discriminator at the beginning
411
- const discriminatorOffset = 8;
412
- const vrtMintOffset = 32 + discriminatorOffset;
413
- const vrtSupplyOffset = 96 + discriminatorOffset;
414
- const jitoVaultTotalDepositsOffset = 104 + discriminatorOffset;
415
- const mintBase = new anchor_1.web3.PublicKey(d.slice(vrtMintOffset, vrtMintOffset + 32));
416
- // For Borsh, numbers are serialized in little-endian format
417
- const jitoVaultTotalSharesBuffer = d.slice(vrtSupplyOffset, vrtSupplyOffset + 8);
418
- const jitoVaultTotalShares = new anchor_1.BN(jitoVaultTotalSharesBuffer, "le");
419
- const jitoVaultTotalDepositsBuffer = d.slice(jitoVaultTotalDepositsOffset, jitoVaultTotalDepositsOffset + 8);
420
- const jitoVaultTotalDeposits = new anchor_1.BN(jitoVaultTotalDepositsBuffer, "le");
421
- const jitoVaultTotalSharesD = new decimal_js_1.default(jitoVaultTotalShares.toString());
422
- const jitoVaultTotalDepositsD = new decimal_js_1.default(jitoVaultTotalDeposits.toString());
423
- const exchangeRate = jitoVaultTotalDepositsD.isZero()
424
- ? "1.0"
425
- : jitoVaultTotalDepositsD.div(jitoVaultTotalSharesD).toString();
426
- return { exchangeRate: parseFloat(exchangeRate), mintBase };
972
+ return (0, jito_1.decodeJitoVaultData)(vaultAccountInfo.data);
427
973
  }
428
974
  async function fetchJitoSolToSolExchangeRate({ connection, interfaceType, accounts, }) {
429
975
  if (interfaceType.splStakePool) {
@@ -438,16 +984,13 @@ async function fetchSplStakePoolIndex({ connection, stakePool, }) {
438
984
  }
439
985
  exports.fetchSplStakePoolIndex = fetchSplStakePoolIndex;
440
986
  async function fetchPerenaStablePoolData({ connection, perenaStablePool, }) {
441
- const [lpMint, _] = anchor_1.web3.PublicKey.findProgramAddressSync([perenaStablePool.toBuffer(), Buffer.from("liquidity")], new anchor_1.web3.PublicKey("NUMERUNsFCP3kuNmWZuXtm1AaQCPj9uw6Guv2Ekoi5P"));
987
+ const lpMint = (0, perena_1.getPerenaLpMint)(perenaStablePool);
442
988
  const [accountInfo, lpMintInfo] = await connection.getMultipleAccountsInfo([perenaStablePool, lpMint]);
443
- const lpMintDeserialized = spl_token_2.MintLayout.decode(lpMintInfo.data);
444
- const d = accountInfo.data;
445
- const discriminatorOffset = 8;
446
- const invTOffset = discriminatorOffset + 32 + 32 + 32 + 32; // 4 Pubkeys before invT
447
- const invTBuffer = d.slice(invTOffset, invTOffset + 8);
448
- const invT = Buffer.from(invTBuffer).readBigUInt64LE(0);
449
- const exchangeRate = new decimal_js_1.default(invT.toString()).div(new decimal_js_1.default(lpMintDeserialized.supply.toString())).toString();
450
- return { lpSupply: lpMintDeserialized.supply, invT, exchangeRate, lpMint };
989
+ const { lpSupply, invT, exchangeRate } = (0, perena_1.getPerenaStablePoolData)({
990
+ perenaStablePoolData: accountInfo.data,
991
+ lpMintData: lpMintInfo.data,
992
+ });
993
+ return { lpSupply, invT, exchangeRate, lpMint };
451
994
  }
452
995
  exports.fetchPerenaStablePoolData = fetchPerenaStablePoolData;
453
996
  /**
@@ -477,40 +1020,14 @@ exports.fetchJitoRestaking = fetchJitoRestaking;
477
1020
  * and tracks last_* values to compute the next index increment similar to the program.
478
1021
  */
479
1022
  async function fetchJupiterPerpsIndex({ connection, pool, lastFeeUsdResetUnixTimestamp, lastRealizedFeeUsd, lastAumUsd, currentIndex, lastRealizedFeeUsdUpdateUnixTimestamp, }) {
480
- // Decode pool account using helper that leverages Anchor 0.29.0
481
1023
  const accountInfo = await connection.getAccountInfo(pool);
482
- const account = (0, jupiter_perps_idl_1.decodePoolAccount)(accountInfo?.data);
483
- const SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
484
- let newFeesBn;
485
- if (lastRealizedFeeUsdUpdateUnixTimestamp === 0) {
486
- newFeesBn = new anchor_1.BN(account.poolApr.realizedFeeUsd.toString());
487
- }
488
- else if (Number(account.poolApr.lastUpdated) > lastFeeUsdResetUnixTimestamp) {
489
- const timeBetweenResets = Number(account.poolApr.lastUpdated) - lastFeeUsdResetUnixTimestamp;
490
- const feeAprBps = new anchor_1.BN(account.poolApr.feeAprBps);
491
- const estTotalFees = lastAumUsd.gt(new anchor_1.BN(0)) && timeBetweenResets > 0
492
- ? feeAprBps.mul(lastAumUsd).mul(new anchor_1.BN(timeBetweenResets)).div(new anchor_1.BN(SECONDS_PER_YEAR)).div(new anchor_1.BN(10_000))
493
- : new anchor_1.BN(0);
494
- const missingFees = estTotalFees.sub(lastRealizedFeeUsd);
495
- const feesSinceReset = new anchor_1.BN(account.poolApr.realizedFeeUsd.toString());
496
- newFeesBn = missingFees.add(feesSinceReset);
497
- }
498
- else {
499
- newFeesBn = new anchor_1.BN(account.poolApr.realizedFeeUsd.toString()).sub(lastRealizedFeeUsd);
500
- }
501
- const aumUsd = new anchor_1.BN(account.aumUsd.toString());
502
- const indexIncrease = new decimal_js_1.default(newFeesBn.toString()).div(new decimal_js_1.default(aumUsd.toString())).toNumber();
503
- const currentIndexNum = parseFloat(precise_number_1.PreciseNumber.fromRaw(currentIndex[0]).valueString);
504
- const nextIndex = currentIndexNum + indexIncrease;
505
- return {
506
- index: nextIndex,
507
- newState: {
508
- lastAumUsd: aumUsd,
509
- lastRealizedFeeUsd: new anchor_1.BN(account.poolApr.realizedFeeUsd.toString()),
510
- lastFeeUsdResetUnixTimestamp: Number(account.poolApr.lastUpdated),
511
- lastRealizedFeeUsdUpdateUnixTimestamp: Math.floor(Date.now() / 1000),
512
- },
513
- };
1024
+ return (0, jupiter_1.calculateJupiterPerpsIndex)({ pool: accountInfo.data }, {
1025
+ lastFeeUsdResetUnixTimestamp,
1026
+ lastRealizedFeeUsd,
1027
+ lastAumUsd,
1028
+ currentIndex,
1029
+ lastRealizedFeeUsdUpdateUnixTimestamp,
1030
+ });
514
1031
  }
515
1032
  exports.fetchJupiterPerpsIndex = fetchJupiterPerpsIndex;
516
1033
  async function fetchPyth(connection) {
@@ -543,28 +1060,27 @@ async function fetchGenericSyMetaIndex({ connection, genericSyMeta, }) {
543
1060
  }
544
1061
  exports.fetchGenericSyMetaIndex = fetchGenericSyMetaIndex;
545
1062
  async function fetchFragmetricIndex({ connection, fragmetricFund, }) {
546
- const account = await connection.getAccountInfo(fragmetricFund);
547
- const coder = new anchor_2.BorshCoder(fragmetric_idl_1.IDL);
548
- const data = coder.accounts.decode("FundAccount", account.data);
549
- const index = Number(data.one_receipt_token_as_sol) / Number(10 ** data.receipt_token_decimals);
550
- const receiptTokenMint = new anchor_1.web3.PublicKey(data.receipt_token_mint);
551
- const wrappedTokenMint = new anchor_1.web3.PublicKey(data.wrapped_token.mint);
1063
+ const fragmetricFundRaw = await connection.getAccountInfo(fragmetricFund);
1064
+ const { index, receiptTokenMint, wrappedTokenMint } = (0, fragmetric_1.calculateFragmetricIndex)({
1065
+ fragmetricFund: fragmetricFundRaw.data,
1066
+ });
552
1067
  return { index, receiptTokenMint, wrappedTokenMint };
553
1068
  }
554
1069
  exports.fetchFragmetricIndex = fetchFragmetricIndex;
555
1070
  async function fetchJupiterLendIndex({ connection, jupiterLendAccount, }) {
556
1071
  const account = await connection.getAccountInfo(jupiterLendAccount);
557
- const coder = new anchor_2.BorshCoder(jupiter_lend_idl_1.IDL);
558
- const data = coder.accounts.decode("Lending", account.data);
559
- const index = Number(data.token_exchange_price) / Number(10 ** 12);
560
- const tokenReservesLiquidity = data.token_reserves_liquidity;
561
- const lendingSupplyPosition = data.supply_position_on_liquidity;
562
- const rewardsRateModel = data.rewards_rate_model;
563
1072
  const rateModel = jupiterLendAccount.equals(new anchor_1.web3.PublicKey("BeAqbxfrcXmzEYT2Ra62oW2MqkuFDHaCtps47Mzg6Zj3"))
564
1073
  ? new anchor_1.web3.PublicKey("Acvyi9HBGmqh3Exe1N4PjBVyY8fokq2AdC6fSLqV6KSo")
565
1074
  : new anchor_1.web3.PublicKey("6iHHKAK9Mqjn57CVmWe4szAPyTH8s8pniXSj6vWaKW5r");
566
- console.log("token reserves liquidity in fetch jupiter lend index", tokenReservesLiquidity.toBase58());
567
- return { index, baseTokenMint: data.mint, tokenReservesLiquidity, lendingSupplyPosition, rewardsRateModel, rateModel };
1075
+ const { index, baseTokenMint, tokenReservesLiquidity, lendingSupplyPosition, rewardsRateModel } = (0, jupiter_1.calculateJupiterLendIndex)({ jupiterLend: account.data });
1076
+ return {
1077
+ rateModel,
1078
+ index,
1079
+ baseTokenMint,
1080
+ tokenReservesLiquidity,
1081
+ lendingSupplyPosition,
1082
+ rewardsRateModel,
1083
+ };
568
1084
  }
569
1085
  exports.fetchJupiterLendIndex = fetchJupiterLendIndex;
570
1086
  async function fetchKaminoVaultIndex({ connection, kaminoVaultAccount, }) {
@@ -593,24 +1109,18 @@ async function fetchKaminoVaultIndex({ connection, kaminoVaultAccount, }) {
593
1109
  exports.fetchKaminoVaultIndex = fetchKaminoVaultIndex;
594
1110
  async function fetchFragmetricSupportedTokenIndex({ connection, fragmetricFund, index, }) {
595
1111
  const account = await connection.getAccountInfo(fragmetricFund);
596
- const coder = new anchor_2.BorshCoder(fragmetric_idl_1.IDL);
597
- const data = coder.accounts.decode("FundAccount", account.data);
598
- const syIndex = Number(10 ** data.supported_tokens[index].decimals) /
599
- Number(data.supported_tokens[index].one_token_as_receipt_token);
600
- const receiptTokenMint = new anchor_1.web3.PublicKey(data.receipt_token_mint);
601
- const wrappedTokenMint = new anchor_1.web3.PublicKey(data.wrapped_token.mint);
602
- return { index: syIndex, receiptTokenMint, wrappedTokenMint };
1112
+ return (0, fragmetric_1.calculateFragmetricSupportedTokenIndex)({ fragmetricFund: account.data }, index);
603
1113
  }
604
1114
  exports.fetchFragmetricSupportedTokenIndex = fetchFragmetricSupportedTokenIndex;
605
1115
  async function fetchMeteoraIndex({ connection, accounts, onChainTime, }) {
606
1116
  try {
607
1117
  const VIRTUAL_PRICE_PRECISION = new anchor_1.BN(100_000_000);
608
- const pool = await (0, meteora_idl_1.decodePoolAccount)(connection, accounts.pool);
1118
+ const pool = await (0, meteora_idl_1.fetchPoolAccount)(connection, accounts.pool);
609
1119
  const poolMint = await (0, spl_token_1.getMint)(connection, pool.lpMint);
610
1120
  const poolLpSupply = new anchor_1.BN(poolMint.supply.toString());
611
1121
  const poolLpDecimals = Number(poolMint.decimals.toString());
612
- const vaultA = await (0, meteora_idl_1.decodeVaultAccount)(connection, accounts.vaultA);
613
- const vaultB = await (0, meteora_idl_1.decodeVaultAccount)(connection, accounts.vaultB);
1122
+ const vaultA = await (0, meteora_idl_1.fetchVaultAccount)(connection, accounts.vaultA);
1123
+ const vaultB = await (0, meteora_idl_1.fetchVaultAccount)(connection, accounts.vaultB);
614
1124
  const vaultLpMintA = await (0, spl_token_1.getMint)(connection, vaultA.lpMint);
615
1125
  const vaultLpMintB = await (0, spl_token_1.getMint)(connection, vaultB.lpMint);
616
1126
  const vaultALpSupply = vaultLpMintA.supply;
@@ -640,7 +1150,6 @@ async function fetchMeteoraIndex({ connection, accounts, onChainTime, }) {
640
1150
  exports.fetchMeteoraIndex = fetchMeteoraIndex;
641
1151
  async function fetchAdrenaIndex({ connection, accounts, previousTotalFees, currentIndex, }) {
642
1152
  try {
643
- const zero = new anchor_1.BN(0);
644
1153
  // Fetch all account data in a single RPC call
645
1154
  const accountInfos = await connection.getMultipleAccountsInfo([
646
1155
  accounts.pool,
@@ -652,19 +1161,13 @@ async function fetchAdrenaIndex({ connection, accounts, previousTotalFees, curre
652
1161
  if (!accountInfos[0] || !accountInfos[1] || !accountInfos[2] || !accountInfos[3] || !accountInfos[4]) {
653
1162
  throw new Error("One or more Adrena accounts not found");
654
1163
  }
655
- // Decode accounts using adrena-idl package functions
656
- const { poolAccount, custodyAccounts } = (0, adrena_idl_1.decodePoolAndCustodyAccounts)(accountInfos);
657
- // @ts-ignore
658
- const currentTotalFees = (0, adrena_idl_1.calculateTotalFeesFromCustodies)(custodyAccounts);
659
- let yieldIncrement;
660
- let aumValue = poolAccount.aumUsd.low;
661
- if (aumValue.eq(zero)) {
662
- yieldIncrement = 0;
663
- }
664
- let feeDifference = currentTotalFees.gte(previousTotalFees) ? currentTotalFees.sub(previousTotalFees) : zero;
665
- yieldIncrement = feeDifference.toNumber() / aumValue.toNumber();
666
- let currentIndexNumber = parseFloat(precise_number_1.PreciseNumber.fromRaw(currentIndex[0]).valueString);
667
- return { index: currentIndexNumber + yieldIncrement };
1164
+ return (0, adrena_1.calculateAdrenaIndex)({
1165
+ pool: accountInfos[0].data,
1166
+ custody1: accountInfos[1].data,
1167
+ custody2: accountInfos[2].data,
1168
+ custody3: accountInfos[3].data,
1169
+ custody4: accountInfos[4].data,
1170
+ }, previousTotalFees, currentIndex);
668
1171
  }
669
1172
  catch (error) {
670
1173
  throw error;
@@ -672,70 +1175,65 @@ async function fetchAdrenaIndex({ connection, accounts, previousTotalFees, curre
672
1175
  }
673
1176
  exports.fetchAdrenaIndex = fetchAdrenaIndex;
674
1177
  async function fetchSanctumIndex({ connection, accounts, }) {
675
- try {
676
- const poolState = await (0, sanctum_idl_1.decodePoolStateAccount)(connection, accounts.poolState);
677
- const lpMint = await (0, spl_token_1.getMint)(connection, accounts.lpMint);
678
- const zeroBn = new anchor_1.BN(0);
679
- const precision = new anchor_1.BN(10 ** lpMint.decimals);
680
- const lpTokenSupplyBn = new anchor_1.BN(lpMint.supply.toString());
681
- const poolTotalSolValueBn = new anchor_1.BN(poolState.totalSolValue.toString());
682
- if (lpTokenSupplyBn.eq(zeroBn) || poolTotalSolValueBn.eq(zeroBn)) {
683
- return 1;
684
- }
685
- const exchangeRateBn = lpTokenSupplyBn.mul(precision).div(poolTotalSolValueBn);
686
- const exchangeRate = new decimal_js_1.default(exchangeRateBn.toString()).div(precision.toString()).toNumber();
687
- return 1 / exchangeRate; // We return inverse exchange rate
688
- }
689
- catch (error) {
690
- throw error;
691
- }
1178
+ const [poolStateAccountRaw, lpMintAccountRaw] = await Promise.all([accounts.poolState, accounts.lpMint].map((pk) => connection.getAccountInfo(pk)));
1179
+ return (0, sanctum_1.calculateSanctumIndex)({
1180
+ poolStateAccountData: poolStateAccountRaw.data,
1181
+ lpMintAccountData: lpMintAccountRaw.data,
1182
+ });
692
1183
  }
693
1184
  exports.fetchSanctumIndex = fetchSanctumIndex;
694
1185
  async function fetchSolsticeRedemptionRate({ connection, yieldPool, vestingSchedule, }) {
695
- try {
696
- // Fetch both accounts in a single RPC call for efficiency
697
- const accountInfos = await connection.getMultipleAccountsInfo([yieldPool, vestingSchedule]);
698
- if (!accountInfos[0] || !accountInfos[1]) {
699
- throw new Error("One or more Solstice accounts not found");
700
- }
701
- // Decode accounts using solstice-idl package function
702
- const { yieldPoolAccount, vestingScheduleAccount } = (0, solstice_idl_1.decodeYieldPoolAndVestingScheduleAccounts)(accountInfos);
703
- // Extract fields for calculation (convert BN to bigint)
704
- const poolTotalAssets = BigInt(yieldPoolAccount.total_assets.toString());
705
- const poolSharesSupply = BigInt(yieldPoolAccount.shares_supply.toString());
706
- const vestingAmount = BigInt(vestingScheduleAccount.vesting_amount.toString());
707
- // Calculate total vested assets (mimicking the Rust logic)
708
- let totalVestedAssets;
709
- if (vestingAmount === 0n) {
710
- totalVestedAssets = poolTotalAssets; // If no vesting amount, all assets are considered vested
711
- }
712
- else {
713
- const vestingStart = BigInt(vestingScheduleAccount.start_time.toString());
714
- const vestingEnd = BigInt(vestingScheduleAccount.end_time.toString());
715
- const currentTime = BigInt(Math.floor(Date.now() / 1000)); // Current Unix timestamp
716
- // Calculate unvested amount
717
- let unvestedAmount;
718
- if (currentTime > vestingEnd) {
719
- unvestedAmount = 0n; // If current time passed the vesting end, no unvested amount
720
- }
721
- else {
722
- unvestedAmount = (vestingAmount * (vestingEnd - currentTime)) / (vestingEnd - vestingStart);
723
- }
724
- totalVestedAssets = poolTotalAssets - unvestedAmount;
725
- }
726
- // Calculate redemption rate: (total_vested_assets + 1) / (pool_shares_supply + 1)
727
- const redemptionRate = Number(totalVestedAssets + 1n) / Number(poolSharesSupply + 1n);
728
- return {
729
- redemptionRate,
730
- totalAssets: poolTotalAssets.toString(),
731
- sharesSupply: poolSharesSupply.toString(),
732
- vestingAmount: vestingAmount.toString(),
733
- totalVestedAssets: totalVestedAssets.toString(),
734
- };
735
- }
736
- catch (error) {
737
- throw error;
1186
+ // Fetch both accounts in a single RPC call for efficiency
1187
+ const accountInfos = await connection.getMultipleAccountsInfo([yieldPool, vestingSchedule]);
1188
+ if (!accountInfos[0] || !accountInfos[1]) {
1189
+ throw new Error("One or more Solstice accounts not found");
738
1190
  }
1191
+ return (0, solstice_1.calculateSolsticeRedemptionRate)({ yieldPool: accountInfos[0].data, vestingSchedule: accountInfos[1].data });
739
1192
  }
740
1193
  exports.fetchSolsticeRedemptionRate = fetchSolsticeRedemptionRate;
1194
+ const REFLECT_ORACLE_LEN = 17;
1195
+ const REFLECT_MAX_STALENESS_SLOTS = 150;
1196
+ async function fetchReflectRedemptionRate({ connection, oracle, }) {
1197
+ const accountInfo = await connection.getAccountInfo(oracle);
1198
+ if (!accountInfo) {
1199
+ throw new Error("Reflect oracle account not found");
1200
+ }
1201
+ if (accountInfo.data.length !== REFLECT_ORACLE_LEN) {
1202
+ throw new Error(`Reflect oracle account has invalid length: ${accountInfo.data.length}`);
1203
+ }
1204
+ const slot = Number(accountInfo.data.readBigUInt64LE(0));
1205
+ const price = Number(accountInfo.data.readBigUInt64LE(8));
1206
+ const precision = accountInfo.data.readUInt8(16);
1207
+ const currentSlot = await connection.getSlot();
1208
+ if (slot > currentSlot) {
1209
+ throw new Error("Reflect oracle slot is ahead of the current slot");
1210
+ }
1211
+ const slotDelta = currentSlot - slot;
1212
+ if (slotDelta > REFLECT_MAX_STALENESS_SLOTS) {
1213
+ throw new Error("Reflect oracle data is stale");
1214
+ }
1215
+ const scale = Math.pow(10, precision);
1216
+ if (scale === 0) {
1217
+ throw new Error("Invalid oracle precision");
1218
+ }
1219
+ return price / scale;
1220
+ }
1221
+ exports.fetchReflectRedemptionRate = fetchReflectRedemptionRate;
1222
+ async function fetchOreExchangeRate({ connection, storeMint, stakeAccount, treasury, }) {
1223
+ // Fetch all accounts in parallel for efficiency
1224
+ const [storeMintInfo, stakeAccountInfo, treasuryAccountInfo] = await Promise.all([
1225
+ connection.getAccountInfo(storeMint),
1226
+ connection.getAccountInfo(stakeAccount),
1227
+ connection.getAccountInfo(treasury),
1228
+ ]);
1229
+ if (!storeMintInfo || !stakeAccountInfo || !treasuryAccountInfo) {
1230
+ throw new Error("One or more ORE accounts not found");
1231
+ }
1232
+ return (0, ore_1.calculateOreExchangeRate)({
1233
+ stakeAccount: stakeAccountInfo.data,
1234
+ treasuryAccount: treasuryAccountInfo.data,
1235
+ storeMint: storeMintInfo.data,
1236
+ });
1237
+ }
1238
+ exports.fetchOreExchangeRate = fetchOreExchangeRate;
741
1239
  //# sourceMappingURL=exponentFetcher.js.map