@0xarchive/sdk 0.6.2 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -41,6 +41,7 @@ __export(index_exports, {
41
41
  OpenInterestResponseSchema: () => OpenInterestResponseSchema,
42
42
  OpenInterestSchema: () => OpenInterestSchema,
43
43
  OrderBookArrayResponseSchema: () => OrderBookArrayResponseSchema,
44
+ OrderBookReconstructor: () => OrderBookReconstructor,
44
45
  OrderBookResponseSchema: () => OrderBookResponseSchema,
45
46
  OrderBookSchema: () => OrderBookSchema,
46
47
  OxArchive: () => OxArchive,
@@ -71,7 +72,9 @@ __export(index_exports, {
71
72
  WsStreamStoppedSchema: () => WsStreamStoppedSchema,
72
73
  WsSubscribedSchema: () => WsSubscribedSchema,
73
74
  WsUnsubscribedSchema: () => WsUnsubscribedSchema,
74
- default: () => OxArchive
75
+ default: () => OxArchive,
76
+ reconstructFinal: () => reconstructFinal,
77
+ reconstructOrderBook: () => reconstructOrderBook
75
78
  });
76
79
  module.exports = __toCommonJS(index_exports);
77
80
 
@@ -412,6 +415,185 @@ var OpenInterestArrayResponseSchema = ApiResponseSchema(import_zod.z.array(OpenI
412
415
  var CandleArrayResponseSchema = ApiResponseSchema(import_zod.z.array(CandleSchema));
413
416
  var LiquidationArrayResponseSchema = ApiResponseSchema(import_zod.z.array(LiquidationSchema));
414
417
 
418
+ // src/orderbook-reconstructor.ts
419
+ var OrderBookReconstructor = class {
420
+ bids = /* @__PURE__ */ new Map();
421
+ asks = /* @__PURE__ */ new Map();
422
+ coin = "";
423
+ lastTimestamp = "";
424
+ lastSequence = 0;
425
+ /**
426
+ * Initialize or reset the reconstructor with a checkpoint
427
+ */
428
+ initialize(checkpoint) {
429
+ this.bids.clear();
430
+ this.asks.clear();
431
+ this.coin = checkpoint.coin;
432
+ this.lastTimestamp = checkpoint.timestamp;
433
+ this.lastSequence = 0;
434
+ for (const level of checkpoint.bids) {
435
+ const price = parseFloat(level.px);
436
+ this.bids.set(price, {
437
+ price,
438
+ size: parseFloat(level.sz),
439
+ orders: level.n
440
+ });
441
+ }
442
+ for (const level of checkpoint.asks) {
443
+ const price = parseFloat(level.px);
444
+ this.asks.set(price, {
445
+ price,
446
+ size: parseFloat(level.sz),
447
+ orders: level.n
448
+ });
449
+ }
450
+ }
451
+ /**
452
+ * Apply a single delta to the current state
453
+ */
454
+ applyDelta(delta) {
455
+ const book = delta.side === "bid" ? this.bids : this.asks;
456
+ if (delta.size === 0) {
457
+ book.delete(delta.price);
458
+ } else {
459
+ book.set(delta.price, {
460
+ price: delta.price,
461
+ size: delta.size,
462
+ orders: 1
463
+ // Deltas don't include order count, assume 1
464
+ });
465
+ }
466
+ this.lastTimestamp = new Date(delta.timestamp).toISOString();
467
+ this.lastSequence = delta.sequence;
468
+ }
469
+ /**
470
+ * Get the current orderbook state as a snapshot
471
+ */
472
+ getSnapshot(depth) {
473
+ const sortedBids = Array.from(this.bids.values()).sort((a, b) => b.price - a.price);
474
+ const sortedAsks = Array.from(this.asks.values()).sort((a, b) => a.price - b.price);
475
+ const bidsOutput = (depth ? sortedBids.slice(0, depth) : sortedBids).map(this.toLevel);
476
+ const asksOutput = (depth ? sortedAsks.slice(0, depth) : sortedAsks).map(this.toLevel);
477
+ const bestBid = sortedBids[0]?.price;
478
+ const bestAsk = sortedAsks[0]?.price;
479
+ const midPrice = bestBid && bestAsk ? (bestBid + bestAsk) / 2 : void 0;
480
+ const spread = bestBid && bestAsk ? bestAsk - bestBid : void 0;
481
+ const spreadBps = midPrice && spread ? spread / midPrice * 1e4 : void 0;
482
+ return {
483
+ coin: this.coin,
484
+ timestamp: this.lastTimestamp,
485
+ bids: bidsOutput,
486
+ asks: asksOutput,
487
+ midPrice: midPrice?.toString(),
488
+ spread: spread?.toString(),
489
+ spreadBps: spreadBps?.toFixed(2),
490
+ sequence: this.lastSequence
491
+ };
492
+ }
493
+ /**
494
+ * Convert internal level to API format
495
+ */
496
+ toLevel = (level) => ({
497
+ px: level.price.toString(),
498
+ sz: level.size.toString(),
499
+ n: level.orders
500
+ });
501
+ /**
502
+ * Reconstruct all orderbook states from checkpoint + deltas.
503
+ * Returns an array of snapshots, one after each delta.
504
+ *
505
+ * For large datasets, prefer `iterate()` to avoid memory issues.
506
+ *
507
+ * @param checkpoint - Initial orderbook state
508
+ * @param deltas - Array of delta updates
509
+ * @param options - Reconstruction options
510
+ * @returns Array of reconstructed orderbook snapshots
511
+ */
512
+ reconstructAll(checkpoint, deltas, options = {}) {
513
+ const { depth, emitAll = true } = options;
514
+ const snapshots = [];
515
+ this.initialize(checkpoint);
516
+ const sortedDeltas = [...deltas].sort((a, b) => a.sequence - b.sequence);
517
+ if (emitAll) {
518
+ snapshots.push(this.getSnapshot(depth));
519
+ }
520
+ for (const delta of sortedDeltas) {
521
+ this.applyDelta(delta);
522
+ if (emitAll) {
523
+ snapshots.push(this.getSnapshot(depth));
524
+ }
525
+ }
526
+ if (!emitAll) {
527
+ snapshots.push(this.getSnapshot(depth));
528
+ }
529
+ return snapshots;
530
+ }
531
+ /**
532
+ * Iterate over reconstructed orderbook states (memory-efficient).
533
+ * Yields a snapshot after each delta is applied.
534
+ *
535
+ * @param checkpoint - Initial orderbook state
536
+ * @param deltas - Array of delta updates
537
+ * @param options - Reconstruction options
538
+ * @yields Reconstructed orderbook snapshots
539
+ */
540
+ *iterate(checkpoint, deltas, options = {}) {
541
+ const { depth } = options;
542
+ this.initialize(checkpoint);
543
+ yield this.getSnapshot(depth);
544
+ const sortedDeltas = [...deltas].sort((a, b) => a.sequence - b.sequence);
545
+ for (const delta of sortedDeltas) {
546
+ this.applyDelta(delta);
547
+ yield this.getSnapshot(depth);
548
+ }
549
+ }
550
+ /**
551
+ * Get the final reconstructed state without intermediate snapshots.
552
+ * Most efficient when you only need the end result.
553
+ *
554
+ * @param checkpoint - Initial orderbook state
555
+ * @param deltas - Array of delta updates
556
+ * @param depth - Maximum price levels to include
557
+ * @returns Final orderbook state after all deltas applied
558
+ */
559
+ reconstructFinal(checkpoint, deltas, depth) {
560
+ this.initialize(checkpoint);
561
+ const sortedDeltas = [...deltas].sort((a, b) => a.sequence - b.sequence);
562
+ for (const delta of sortedDeltas) {
563
+ this.applyDelta(delta);
564
+ }
565
+ return this.getSnapshot(depth);
566
+ }
567
+ /**
568
+ * Check for sequence gaps in deltas.
569
+ * Returns array of missing sequence numbers.
570
+ *
571
+ * @param deltas - Array of delta updates
572
+ * @returns Array of [expectedSeq, actualSeq] tuples where gaps exist
573
+ */
574
+ static detectGaps(deltas) {
575
+ if (deltas.length < 2) return [];
576
+ const sorted = [...deltas].sort((a, b) => a.sequence - b.sequence);
577
+ const gaps = [];
578
+ for (let i = 1; i < sorted.length; i++) {
579
+ const expected = sorted[i - 1].sequence + 1;
580
+ const actual = sorted[i].sequence;
581
+ if (actual !== expected) {
582
+ gaps.push([expected, actual]);
583
+ }
584
+ }
585
+ return gaps;
586
+ }
587
+ };
588
+ function reconstructOrderBook(tickData, options = {}) {
589
+ const reconstructor = new OrderBookReconstructor();
590
+ return reconstructor.reconstructAll(tickData.checkpoint, tickData.deltas, options);
591
+ }
592
+ function reconstructFinal(tickData, depth) {
593
+ const reconstructor = new OrderBookReconstructor();
594
+ return reconstructor.reconstructFinal(tickData.checkpoint, tickData.deltas, depth);
595
+ }
596
+
415
597
  // src/resources/orderbook.ts
416
598
  var OrderBookResource = class {
417
599
  constructor(http, basePath = "/v1") {
@@ -471,6 +653,120 @@ var OrderBookResource = class {
471
653
  nextCursor: response.meta.nextCursor
472
654
  };
473
655
  }
656
+ /**
657
+ * Get raw tick-level orderbook data (Enterprise tier only).
658
+ *
659
+ * Returns a checkpoint (full orderbook state) and array of deltas.
660
+ * Use this when you want to implement custom reconstruction logic
661
+ * (e.g., in Rust for maximum performance).
662
+ *
663
+ * For automatic reconstruction, use `historyReconstructed()` instead.
664
+ *
665
+ * @param coin - The coin symbol (e.g., 'BTC', 'ETH')
666
+ * @param params - Time range parameters
667
+ * @returns Tick data with checkpoint and deltas
668
+ *
669
+ * @example
670
+ * ```typescript
671
+ * const tickData = await client.lighter.orderbook.historyTick('BTC', {
672
+ * start: Date.now() - 3600000,
673
+ * end: Date.now()
674
+ * });
675
+ *
676
+ * console.log('Checkpoint:', tickData.checkpoint);
677
+ * console.log('Deltas:', tickData.deltas.length);
678
+ *
679
+ * // Implement your own reconstruction...
680
+ * for (const delta of tickData.deltas) {
681
+ * // delta: { timestamp, side, price, size, sequence }
682
+ * }
683
+ * ```
684
+ */
685
+ async historyTick(coin, params) {
686
+ const response = await this.http.get(
687
+ `${this.basePath}/orderbook/${coin.toUpperCase()}/history`,
688
+ {
689
+ ...params,
690
+ granularity: "tick"
691
+ }
692
+ );
693
+ const tickData = response.data;
694
+ if (!tickData?.checkpoint || !tickData?.deltas) {
695
+ const errorMsg = response.error || response.message || "Tick-level orderbook data requires Enterprise tier. Upgrade your subscription or use a different granularity.";
696
+ throw new Error(errorMsg);
697
+ }
698
+ return {
699
+ checkpoint: tickData.checkpoint,
700
+ deltas: tickData.deltas
701
+ };
702
+ }
703
+ /**
704
+ * Get reconstructed tick-level orderbook history (Enterprise tier only).
705
+ *
706
+ * Fetches raw tick data and reconstructs full orderbook state at each delta.
707
+ * All reconstruction happens client-side for optimal server performance.
708
+ *
709
+ * For large time ranges, consider using `historyTick()` with the
710
+ * `OrderBookReconstructor.iterate()` method for memory efficiency.
711
+ *
712
+ * @param coin - The coin symbol (e.g., 'BTC', 'ETH')
713
+ * @param params - Time range parameters
714
+ * @param options - Reconstruction options
715
+ * @returns Array of reconstructed orderbook snapshots
716
+ *
717
+ * @example
718
+ * ```typescript
719
+ * // Get all snapshots
720
+ * const snapshots = await client.lighter.orderbook.historyReconstructed('BTC', {
721
+ * start: Date.now() - 3600000,
722
+ * end: Date.now()
723
+ * });
724
+ *
725
+ * for (const ob of snapshots) {
726
+ * console.log(ob.timestamp, 'Best bid:', ob.bids[0]?.px, 'Best ask:', ob.asks[0]?.px);
727
+ * }
728
+ *
729
+ * // Get only final state
730
+ * const [final] = await client.lighter.orderbook.historyReconstructed('BTC',
731
+ * { start, end },
732
+ * { emitAll: false }
733
+ * );
734
+ * ```
735
+ */
736
+ async historyReconstructed(coin, params, options = {}) {
737
+ const tickData = await this.historyTick(coin, params);
738
+ const reconstructor = new OrderBookReconstructor();
739
+ return reconstructor.reconstructAll(tickData.checkpoint, tickData.deltas, options);
740
+ }
741
+ /**
742
+ * Create a reconstructor for streaming tick-level data.
743
+ *
744
+ * Returns an OrderBookReconstructor instance that you can use
745
+ * to process tick data incrementally or with custom logic.
746
+ *
747
+ * @returns A new OrderBookReconstructor instance
748
+ *
749
+ * @example
750
+ * ```typescript
751
+ * const reconstructor = client.lighter.orderbook.createReconstructor();
752
+ * const tickData = await client.lighter.orderbook.historyTick('BTC', { start, end });
753
+ *
754
+ * // Memory-efficient iteration
755
+ * for (const snapshot of reconstructor.iterate(tickData.checkpoint, tickData.deltas)) {
756
+ * // Process each snapshot
757
+ * if (someCondition(snapshot)) break; // Early exit if needed
758
+ * }
759
+ *
760
+ * // Check for gaps
761
+ * const gaps = OrderBookReconstructor.detectGaps(tickData.deltas);
762
+ * if (gaps.length > 0) {
763
+ * console.warn('Sequence gaps detected:', gaps);
764
+ * }
765
+ * ```
766
+ */
767
+ createReconstructor() {
768
+ return new OrderBookReconstructor();
769
+ }
474
770
  };
475
771
 
476
772
  // src/resources/trades.ts
@@ -1673,6 +1969,7 @@ var OxArchiveWs = class {
1673
1969
  OpenInterestResponseSchema,
1674
1970
  OpenInterestSchema,
1675
1971
  OrderBookArrayResponseSchema,
1972
+ OrderBookReconstructor,
1676
1973
  OrderBookResponseSchema,
1677
1974
  OrderBookSchema,
1678
1975
  OxArchive,
@@ -1702,6 +1999,8 @@ var OxArchiveWs = class {
1702
1999
  WsStreamStartedSchema,
1703
2000
  WsStreamStoppedSchema,
1704
2001
  WsSubscribedSchema,
1705
- WsUnsubscribedSchema
2002
+ WsUnsubscribedSchema,
2003
+ reconstructFinal,
2004
+ reconstructOrderBook
1706
2005
  });
1707
2006
  //# sourceMappingURL=index.js.map