@0xarchive/sdk 0.6.1 → 0.6.3
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 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +297 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -335,6 +335,185 @@ var OpenInterestArrayResponseSchema = ApiResponseSchema(z.array(OpenInterestSche
|
|
|
335
335
|
var CandleArrayResponseSchema = ApiResponseSchema(z.array(CandleSchema));
|
|
336
336
|
var LiquidationArrayResponseSchema = ApiResponseSchema(z.array(LiquidationSchema));
|
|
337
337
|
|
|
338
|
+
// src/orderbook-reconstructor.ts
|
|
339
|
+
var OrderBookReconstructor = class {
|
|
340
|
+
bids = /* @__PURE__ */ new Map();
|
|
341
|
+
asks = /* @__PURE__ */ new Map();
|
|
342
|
+
coin = "";
|
|
343
|
+
lastTimestamp = "";
|
|
344
|
+
lastSequence = 0;
|
|
345
|
+
/**
|
|
346
|
+
* Initialize or reset the reconstructor with a checkpoint
|
|
347
|
+
*/
|
|
348
|
+
initialize(checkpoint) {
|
|
349
|
+
this.bids.clear();
|
|
350
|
+
this.asks.clear();
|
|
351
|
+
this.coin = checkpoint.coin;
|
|
352
|
+
this.lastTimestamp = checkpoint.timestamp;
|
|
353
|
+
this.lastSequence = 0;
|
|
354
|
+
for (const level of checkpoint.bids) {
|
|
355
|
+
const price = parseFloat(level.px);
|
|
356
|
+
this.bids.set(price, {
|
|
357
|
+
price,
|
|
358
|
+
size: parseFloat(level.sz),
|
|
359
|
+
orders: level.n
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
for (const level of checkpoint.asks) {
|
|
363
|
+
const price = parseFloat(level.px);
|
|
364
|
+
this.asks.set(price, {
|
|
365
|
+
price,
|
|
366
|
+
size: parseFloat(level.sz),
|
|
367
|
+
orders: level.n
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Apply a single delta to the current state
|
|
373
|
+
*/
|
|
374
|
+
applyDelta(delta) {
|
|
375
|
+
const book = delta.side === "bid" ? this.bids : this.asks;
|
|
376
|
+
if (delta.size === 0) {
|
|
377
|
+
book.delete(delta.price);
|
|
378
|
+
} else {
|
|
379
|
+
book.set(delta.price, {
|
|
380
|
+
price: delta.price,
|
|
381
|
+
size: delta.size,
|
|
382
|
+
orders: 1
|
|
383
|
+
// Deltas don't include order count, assume 1
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
this.lastTimestamp = new Date(delta.timestamp).toISOString();
|
|
387
|
+
this.lastSequence = delta.sequence;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Get the current orderbook state as a snapshot
|
|
391
|
+
*/
|
|
392
|
+
getSnapshot(depth) {
|
|
393
|
+
const sortedBids = Array.from(this.bids.values()).sort((a, b) => b.price - a.price);
|
|
394
|
+
const sortedAsks = Array.from(this.asks.values()).sort((a, b) => a.price - b.price);
|
|
395
|
+
const bidsOutput = (depth ? sortedBids.slice(0, depth) : sortedBids).map(this.toLevel);
|
|
396
|
+
const asksOutput = (depth ? sortedAsks.slice(0, depth) : sortedAsks).map(this.toLevel);
|
|
397
|
+
const bestBid = sortedBids[0]?.price;
|
|
398
|
+
const bestAsk = sortedAsks[0]?.price;
|
|
399
|
+
const midPrice = bestBid && bestAsk ? (bestBid + bestAsk) / 2 : void 0;
|
|
400
|
+
const spread = bestBid && bestAsk ? bestAsk - bestBid : void 0;
|
|
401
|
+
const spreadBps = midPrice && spread ? spread / midPrice * 1e4 : void 0;
|
|
402
|
+
return {
|
|
403
|
+
coin: this.coin,
|
|
404
|
+
timestamp: this.lastTimestamp,
|
|
405
|
+
bids: bidsOutput,
|
|
406
|
+
asks: asksOutput,
|
|
407
|
+
midPrice: midPrice?.toString(),
|
|
408
|
+
spread: spread?.toString(),
|
|
409
|
+
spreadBps: spreadBps?.toFixed(2),
|
|
410
|
+
sequence: this.lastSequence
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Convert internal level to API format
|
|
415
|
+
*/
|
|
416
|
+
toLevel = (level) => ({
|
|
417
|
+
px: level.price.toString(),
|
|
418
|
+
sz: level.size.toString(),
|
|
419
|
+
n: level.orders
|
|
420
|
+
});
|
|
421
|
+
/**
|
|
422
|
+
* Reconstruct all orderbook states from checkpoint + deltas.
|
|
423
|
+
* Returns an array of snapshots, one after each delta.
|
|
424
|
+
*
|
|
425
|
+
* For large datasets, prefer `iterate()` to avoid memory issues.
|
|
426
|
+
*
|
|
427
|
+
* @param checkpoint - Initial orderbook state
|
|
428
|
+
* @param deltas - Array of delta updates
|
|
429
|
+
* @param options - Reconstruction options
|
|
430
|
+
* @returns Array of reconstructed orderbook snapshots
|
|
431
|
+
*/
|
|
432
|
+
reconstructAll(checkpoint, deltas, options = {}) {
|
|
433
|
+
const { depth, emitAll = true } = options;
|
|
434
|
+
const snapshots = [];
|
|
435
|
+
this.initialize(checkpoint);
|
|
436
|
+
const sortedDeltas = [...deltas].sort((a, b) => a.sequence - b.sequence);
|
|
437
|
+
if (emitAll) {
|
|
438
|
+
snapshots.push(this.getSnapshot(depth));
|
|
439
|
+
}
|
|
440
|
+
for (const delta of sortedDeltas) {
|
|
441
|
+
this.applyDelta(delta);
|
|
442
|
+
if (emitAll) {
|
|
443
|
+
snapshots.push(this.getSnapshot(depth));
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
if (!emitAll) {
|
|
447
|
+
snapshots.push(this.getSnapshot(depth));
|
|
448
|
+
}
|
|
449
|
+
return snapshots;
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Iterate over reconstructed orderbook states (memory-efficient).
|
|
453
|
+
* Yields a snapshot after each delta is applied.
|
|
454
|
+
*
|
|
455
|
+
* @param checkpoint - Initial orderbook state
|
|
456
|
+
* @param deltas - Array of delta updates
|
|
457
|
+
* @param options - Reconstruction options
|
|
458
|
+
* @yields Reconstructed orderbook snapshots
|
|
459
|
+
*/
|
|
460
|
+
*iterate(checkpoint, deltas, options = {}) {
|
|
461
|
+
const { depth } = options;
|
|
462
|
+
this.initialize(checkpoint);
|
|
463
|
+
yield this.getSnapshot(depth);
|
|
464
|
+
const sortedDeltas = [...deltas].sort((a, b) => a.sequence - b.sequence);
|
|
465
|
+
for (const delta of sortedDeltas) {
|
|
466
|
+
this.applyDelta(delta);
|
|
467
|
+
yield this.getSnapshot(depth);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Get the final reconstructed state without intermediate snapshots.
|
|
472
|
+
* Most efficient when you only need the end result.
|
|
473
|
+
*
|
|
474
|
+
* @param checkpoint - Initial orderbook state
|
|
475
|
+
* @param deltas - Array of delta updates
|
|
476
|
+
* @param depth - Maximum price levels to include
|
|
477
|
+
* @returns Final orderbook state after all deltas applied
|
|
478
|
+
*/
|
|
479
|
+
reconstructFinal(checkpoint, deltas, depth) {
|
|
480
|
+
this.initialize(checkpoint);
|
|
481
|
+
const sortedDeltas = [...deltas].sort((a, b) => a.sequence - b.sequence);
|
|
482
|
+
for (const delta of sortedDeltas) {
|
|
483
|
+
this.applyDelta(delta);
|
|
484
|
+
}
|
|
485
|
+
return this.getSnapshot(depth);
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Check for sequence gaps in deltas.
|
|
489
|
+
* Returns array of missing sequence numbers.
|
|
490
|
+
*
|
|
491
|
+
* @param deltas - Array of delta updates
|
|
492
|
+
* @returns Array of [expectedSeq, actualSeq] tuples where gaps exist
|
|
493
|
+
*/
|
|
494
|
+
static detectGaps(deltas) {
|
|
495
|
+
if (deltas.length < 2) return [];
|
|
496
|
+
const sorted = [...deltas].sort((a, b) => a.sequence - b.sequence);
|
|
497
|
+
const gaps = [];
|
|
498
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
499
|
+
const expected = sorted[i - 1].sequence + 1;
|
|
500
|
+
const actual = sorted[i].sequence;
|
|
501
|
+
if (actual !== expected) {
|
|
502
|
+
gaps.push([expected, actual]);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return gaps;
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
function reconstructOrderBook(tickData, options = {}) {
|
|
509
|
+
const reconstructor = new OrderBookReconstructor();
|
|
510
|
+
return reconstructor.reconstructAll(tickData.checkpoint, tickData.deltas, options);
|
|
511
|
+
}
|
|
512
|
+
function reconstructFinal(tickData, depth) {
|
|
513
|
+
const reconstructor = new OrderBookReconstructor();
|
|
514
|
+
return reconstructor.reconstructFinal(tickData.checkpoint, tickData.deltas, depth);
|
|
515
|
+
}
|
|
516
|
+
|
|
338
517
|
// src/resources/orderbook.ts
|
|
339
518
|
var OrderBookResource = class {
|
|
340
519
|
constructor(http, basePath = "/v1") {
|
|
@@ -394,6 +573,119 @@ var OrderBookResource = class {
|
|
|
394
573
|
nextCursor: response.meta.nextCursor
|
|
395
574
|
};
|
|
396
575
|
}
|
|
576
|
+
/**
|
|
577
|
+
* Get raw tick-level orderbook data (Enterprise tier only).
|
|
578
|
+
*
|
|
579
|
+
* Returns a checkpoint (full orderbook state) and array of deltas.
|
|
580
|
+
* Use this when you want to implement custom reconstruction logic
|
|
581
|
+
* (e.g., in Rust for maximum performance).
|
|
582
|
+
*
|
|
583
|
+
* For automatic reconstruction, use `historyReconstructed()` instead.
|
|
584
|
+
*
|
|
585
|
+
* @param coin - The coin symbol (e.g., 'BTC', 'ETH')
|
|
586
|
+
* @param params - Time range parameters
|
|
587
|
+
* @returns Tick data with checkpoint and deltas
|
|
588
|
+
*
|
|
589
|
+
* @example
|
|
590
|
+
* ```typescript
|
|
591
|
+
* const tickData = await client.lighter.orderbook.historyTick('BTC', {
|
|
592
|
+
* start: Date.now() - 3600000,
|
|
593
|
+
* end: Date.now()
|
|
594
|
+
* });
|
|
595
|
+
*
|
|
596
|
+
* console.log('Checkpoint:', tickData.checkpoint);
|
|
597
|
+
* console.log('Deltas:', tickData.deltas.length);
|
|
598
|
+
*
|
|
599
|
+
* // Implement your own reconstruction...
|
|
600
|
+
* for (const delta of tickData.deltas) {
|
|
601
|
+
* // delta: { timestamp, side, price, size, sequence }
|
|
602
|
+
* }
|
|
603
|
+
* ```
|
|
604
|
+
*/
|
|
605
|
+
async historyTick(coin, params) {
|
|
606
|
+
const response = await this.http.get(
|
|
607
|
+
`${this.basePath}/orderbook/${coin.toUpperCase()}/history`,
|
|
608
|
+
{
|
|
609
|
+
...params,
|
|
610
|
+
granularity: "tick"
|
|
611
|
+
}
|
|
612
|
+
);
|
|
613
|
+
if (!response.checkpoint || !response.deltas) {
|
|
614
|
+
const errorMsg = response.error || response.message || "Tick-level orderbook data requires Enterprise tier. Upgrade your subscription or use a different granularity.";
|
|
615
|
+
throw new Error(errorMsg);
|
|
616
|
+
}
|
|
617
|
+
return {
|
|
618
|
+
checkpoint: response.checkpoint,
|
|
619
|
+
deltas: response.deltas
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Get reconstructed tick-level orderbook history (Enterprise tier only).
|
|
624
|
+
*
|
|
625
|
+
* Fetches raw tick data and reconstructs full orderbook state at each delta.
|
|
626
|
+
* All reconstruction happens client-side for optimal server performance.
|
|
627
|
+
*
|
|
628
|
+
* For large time ranges, consider using `historyTick()` with the
|
|
629
|
+
* `OrderBookReconstructor.iterate()` method for memory efficiency.
|
|
630
|
+
*
|
|
631
|
+
* @param coin - The coin symbol (e.g., 'BTC', 'ETH')
|
|
632
|
+
* @param params - Time range parameters
|
|
633
|
+
* @param options - Reconstruction options
|
|
634
|
+
* @returns Array of reconstructed orderbook snapshots
|
|
635
|
+
*
|
|
636
|
+
* @example
|
|
637
|
+
* ```typescript
|
|
638
|
+
* // Get all snapshots
|
|
639
|
+
* const snapshots = await client.lighter.orderbook.historyReconstructed('BTC', {
|
|
640
|
+
* start: Date.now() - 3600000,
|
|
641
|
+
* end: Date.now()
|
|
642
|
+
* });
|
|
643
|
+
*
|
|
644
|
+
* for (const ob of snapshots) {
|
|
645
|
+
* console.log(ob.timestamp, 'Best bid:', ob.bids[0]?.px, 'Best ask:', ob.asks[0]?.px);
|
|
646
|
+
* }
|
|
647
|
+
*
|
|
648
|
+
* // Get only final state
|
|
649
|
+
* const [final] = await client.lighter.orderbook.historyReconstructed('BTC',
|
|
650
|
+
* { start, end },
|
|
651
|
+
* { emitAll: false }
|
|
652
|
+
* );
|
|
653
|
+
* ```
|
|
654
|
+
*/
|
|
655
|
+
async historyReconstructed(coin, params, options = {}) {
|
|
656
|
+
const tickData = await this.historyTick(coin, params);
|
|
657
|
+
const reconstructor = new OrderBookReconstructor();
|
|
658
|
+
return reconstructor.reconstructAll(tickData.checkpoint, tickData.deltas, options);
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Create a reconstructor for streaming tick-level data.
|
|
662
|
+
*
|
|
663
|
+
* Returns an OrderBookReconstructor instance that you can use
|
|
664
|
+
* to process tick data incrementally or with custom logic.
|
|
665
|
+
*
|
|
666
|
+
* @returns A new OrderBookReconstructor instance
|
|
667
|
+
*
|
|
668
|
+
* @example
|
|
669
|
+
* ```typescript
|
|
670
|
+
* const reconstructor = client.lighter.orderbook.createReconstructor();
|
|
671
|
+
* const tickData = await client.lighter.orderbook.historyTick('BTC', { start, end });
|
|
672
|
+
*
|
|
673
|
+
* // Memory-efficient iteration
|
|
674
|
+
* for (const snapshot of reconstructor.iterate(tickData.checkpoint, tickData.deltas)) {
|
|
675
|
+
* // Process each snapshot
|
|
676
|
+
* if (someCondition(snapshot)) break; // Early exit if needed
|
|
677
|
+
* }
|
|
678
|
+
*
|
|
679
|
+
* // Check for gaps
|
|
680
|
+
* const gaps = OrderBookReconstructor.detectGaps(tickData.deltas);
|
|
681
|
+
* if (gaps.length > 0) {
|
|
682
|
+
* console.warn('Sequence gaps detected:', gaps);
|
|
683
|
+
* }
|
|
684
|
+
* ```
|
|
685
|
+
*/
|
|
686
|
+
createReconstructor() {
|
|
687
|
+
return new OrderBookReconstructor();
|
|
688
|
+
}
|
|
397
689
|
};
|
|
398
690
|
|
|
399
691
|
// src/resources/trades.ts
|
|
@@ -456,7 +748,7 @@ var TradesResource = class {
|
|
|
456
748
|
*/
|
|
457
749
|
async recent(coin, limit) {
|
|
458
750
|
const response = await this.http.get(
|
|
459
|
-
|
|
751
|
+
`${this.basePath}/trades/${coin.toUpperCase()}/recent`,
|
|
460
752
|
{ limit },
|
|
461
753
|
this.http.validationEnabled ? TradeArrayResponseSchema : void 0
|
|
462
754
|
);
|
|
@@ -1595,6 +1887,7 @@ export {
|
|
|
1595
1887
|
OpenInterestResponseSchema,
|
|
1596
1888
|
OpenInterestSchema,
|
|
1597
1889
|
OrderBookArrayResponseSchema,
|
|
1890
|
+
OrderBookReconstructor,
|
|
1598
1891
|
OrderBookResponseSchema,
|
|
1599
1892
|
OrderBookSchema,
|
|
1600
1893
|
OxArchive,
|
|
@@ -1625,6 +1918,8 @@ export {
|
|
|
1625
1918
|
WsStreamStoppedSchema,
|
|
1626
1919
|
WsSubscribedSchema,
|
|
1627
1920
|
WsUnsubscribedSchema,
|
|
1628
|
-
OxArchive as default
|
|
1921
|
+
OxArchive as default,
|
|
1922
|
+
reconstructFinal,
|
|
1923
|
+
reconstructOrderBook
|
|
1629
1924
|
};
|
|
1630
1925
|
//# sourceMappingURL=index.mjs.map
|