@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/README.md +65 -0
- package/dist/index.d.mts +252 -1
- package/dist/index.d.ts +252 -1
- package/dist/index.js +301 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +297 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|