@lifi/perps-sdk-provider-hyperliquid 1.5.4 → 1.5.5
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/cjs/services/getFills.d.ts.map +1 -1
- package/dist/cjs/services/getFills.js +13 -6
- package/dist/cjs/services/getFills.js.map +1 -1
- package/dist/cjs/services/getOrders.js +1 -1
- package/dist/cjs/services/getOrders.js.map +1 -1
- package/dist/cjs/types/order.d.ts +1 -1
- package/dist/cjs/types/order.d.ts.map +1 -1
- package/dist/cjs/websocket/HyperliquidWsProvider.d.ts +2 -0
- package/dist/cjs/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/dist/cjs/websocket/HyperliquidWsProvider.js +59 -38
- package/dist/cjs/websocket/HyperliquidWsProvider.js.map +1 -1
- package/dist/esm/services/getFills.d.ts +4 -4
- package/dist/esm/services/getFills.d.ts.map +1 -1
- package/dist/esm/services/getFills.js +19 -9
- package/dist/esm/services/getFills.js.map +1 -1
- package/dist/esm/services/getOrders.js +1 -1
- package/dist/esm/services/getOrders.js.map +1 -1
- package/dist/esm/types/order.d.ts +1 -1
- package/dist/esm/types/order.d.ts.map +1 -1
- package/dist/esm/websocket/HyperliquidWsProvider.d.ts +13 -2
- package/dist/esm/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/dist/esm/websocket/HyperliquidWsProvider.js +75 -44
- package/dist/esm/websocket/HyperliquidWsProvider.js.map +1 -1
- package/dist/types/services/getFills.d.ts +4 -4
- package/dist/types/services/getFills.d.ts.map +1 -1
- package/dist/types/types/order.d.ts +1 -1
- package/dist/types/types/order.d.ts.map +1 -1
- package/dist/types/websocket/HyperliquidWsProvider.d.ts +13 -2
- package/dist/types/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/services/getFills.ts +37 -11
- package/src/services/getOrders.ts +1 -1
- package/src/types/order.ts +1 -1
- package/src/websocket/HyperliquidWsProvider.ts +79 -47
|
@@ -99,6 +99,7 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
99
99
|
private readonly registry: MarketRegistry | undefined
|
|
100
100
|
private perpCtxBySubDex = new Map<string, Record<string, HlWsPerpAssetCtx>>()
|
|
101
101
|
private spotCtxByMarketId: Record<string, HlWsSpotAssetCtx> = {}
|
|
102
|
+
private marketsContextByMarketId: Record<string, MarketContext> = {}
|
|
102
103
|
private orderbookKeysByMarketId = new Map<string, Set<string>>()
|
|
103
104
|
private latestOrderbookByMarketId = new Map<string, OrderbookResponse>()
|
|
104
105
|
// Latest mid/mark per `Market.id` from the high-frequency `fastAssetCtxs`
|
|
@@ -173,6 +174,7 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
173
174
|
this.perpCtxBySubDex.clear()
|
|
174
175
|
this.spotCtxByMarketId = {}
|
|
175
176
|
this.fastCtxByMarketId = {}
|
|
177
|
+
this.marketsContextByMarketId = {}
|
|
176
178
|
}
|
|
177
179
|
}
|
|
178
180
|
|
|
@@ -292,6 +294,7 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
292
294
|
this.perpCtxBySubDex.clear()
|
|
293
295
|
this.spotCtxByMarketId = {}
|
|
294
296
|
this.fastCtxByMarketId = {}
|
|
297
|
+
this.marketsContextByMarketId = {}
|
|
295
298
|
this.orderbookKeysByMarketId.clear()
|
|
296
299
|
this.latestOrderbookByMarketId.clear()
|
|
297
300
|
this.fastDecodeChain = Promise.resolve()
|
|
@@ -483,41 +486,47 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
483
486
|
}
|
|
484
487
|
|
|
485
488
|
private handleAllDexsAssetCtxs(data: HlWsAllDexsAssetCtxsData) {
|
|
486
|
-
this.
|
|
487
|
-
|
|
489
|
+
this.emitMarketsContext(
|
|
490
|
+
this.mergePerpAssetCtxEntries(allDexsAssetCtxEntries(data))
|
|
491
|
+
)
|
|
488
492
|
}
|
|
489
493
|
|
|
490
494
|
private handlePac(base64: string) {
|
|
491
495
|
this.pacDecodeChain = this.pacDecodeChain
|
|
492
496
|
.then(async () => {
|
|
493
|
-
this.
|
|
494
|
-
|
|
497
|
+
this.emitMarketsContext(
|
|
498
|
+
this.mergePerpAssetCtxEntries(
|
|
499
|
+
await decodeCompressedJson<HlWsPacData>(base64)
|
|
500
|
+
)
|
|
495
501
|
)
|
|
496
|
-
this.emitMarketsContext()
|
|
497
502
|
})
|
|
498
503
|
.catch((error) => wsLog.handlerFailure(this.providerKey, error))
|
|
499
504
|
}
|
|
500
505
|
|
|
506
|
+
/** Merge perp asset contexts in place; returns the marketIds this frame touched. */
|
|
501
507
|
private mergePerpAssetCtxEntries(
|
|
502
508
|
entries: [string, HlWsPerpAssetCtxPayload[]][]
|
|
503
|
-
) {
|
|
509
|
+
): Set<string> {
|
|
510
|
+
const touched = new Set<string>()
|
|
504
511
|
for (const [dex, ctxs] of entries) {
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
512
|
+
let byMarketId = this.perpCtxBySubDex.get(dex || 'default')
|
|
513
|
+
if (byMarketId === undefined) {
|
|
514
|
+
byMarketId = {}
|
|
515
|
+
this.perpCtxBySubDex.set(dex || 'default', byMarketId)
|
|
508
516
|
}
|
|
509
517
|
for (const ctx of ctxs) {
|
|
510
518
|
const marketId = ctx.coin
|
|
511
519
|
if (marketId === undefined) {
|
|
512
520
|
continue
|
|
513
521
|
}
|
|
514
|
-
const merged = mergePerpAssetCtx(
|
|
522
|
+
const merged = mergePerpAssetCtx(byMarketId[marketId], marketId, ctx)
|
|
515
523
|
if (merged !== undefined) {
|
|
516
524
|
byMarketId[marketId] = merged
|
|
525
|
+
touched.add(marketId)
|
|
517
526
|
}
|
|
518
527
|
}
|
|
519
|
-
this.perpCtxBySubDex.set(dex || 'default', byMarketId)
|
|
520
528
|
}
|
|
529
|
+
return touched
|
|
521
530
|
}
|
|
522
531
|
|
|
523
532
|
private handleSac(base64: string) {
|
|
@@ -525,6 +534,7 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
525
534
|
.then(async () => {
|
|
526
535
|
const spotMarketIdBySacKey = this.spotMarketIdBySacKey()
|
|
527
536
|
const ctxs = await decodeCompressedJson<HlWsSacData>(base64)
|
|
537
|
+
const touched = new Set<string>()
|
|
528
538
|
for (const [sacKey, ctx] of Object.entries(ctxs)) {
|
|
529
539
|
const marketId = spotMarketIdBySacKey.get(sacKey)
|
|
530
540
|
if (marketId === undefined) {
|
|
@@ -534,8 +544,9 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
534
544
|
...this.spotCtxByMarketId[marketId],
|
|
535
545
|
...ctx,
|
|
536
546
|
}
|
|
547
|
+
touched.add(marketId)
|
|
537
548
|
}
|
|
538
|
-
this.emitMarketsContext()
|
|
549
|
+
this.emitMarketsContext(touched)
|
|
539
550
|
})
|
|
540
551
|
.catch((error) => wsLog.handlerFailure(this.providerKey, error))
|
|
541
552
|
}
|
|
@@ -572,52 +583,66 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
572
583
|
midPx: 'midPx' in ctx ? ctx.midPx : prev?.midPx,
|
|
573
584
|
}
|
|
574
585
|
}
|
|
575
|
-
this.emitMarketsContext()
|
|
586
|
+
this.emitMarketsContext(Object.keys(ctxs))
|
|
576
587
|
})
|
|
577
588
|
.catch((error) => wsLog.handlerFailure(this.providerKey, error))
|
|
578
589
|
}
|
|
579
590
|
|
|
580
591
|
/**
|
|
581
|
-
*
|
|
582
|
-
*
|
|
592
|
+
* Emit the all-markets context map, re-mapping only the markets the incoming
|
|
593
|
+
* frame touched. Each emission is a fresh snapshot object that carries
|
|
594
|
+
* untouched entries over by reference, so a listener holding an earlier
|
|
595
|
+
* snapshot never observes later-frame mutation.
|
|
583
596
|
*/
|
|
584
|
-
private emitMarketsContext() {
|
|
585
|
-
const data: Record<string, MarketContext> = {
|
|
586
|
-
|
|
587
|
-
for (const [marketId, ctx] of Object.entries(byMarketId)) {
|
|
588
|
-
const base = mapMarketContext(marketId, ctx)
|
|
589
|
-
const fast = this.fastCtxByMarketId[marketId]
|
|
590
|
-
data[marketId] = {
|
|
591
|
-
...base,
|
|
592
|
-
midPrice: fast?.midPx != null ? fast.midPx : base.midPrice,
|
|
593
|
-
markPrice: fast?.markPx != null ? fast.markPx : base.markPrice,
|
|
594
|
-
}
|
|
595
|
-
}
|
|
597
|
+
private emitMarketsContext(touchedMarketIds: Iterable<string>) {
|
|
598
|
+
const data: Record<string, MarketContext> = {
|
|
599
|
+
...this.marketsContextByMarketId,
|
|
596
600
|
}
|
|
597
|
-
for (const
|
|
598
|
-
const context =
|
|
599
|
-
marketId,
|
|
600
|
-
ctx,
|
|
601
|
-
this.fastCtxByMarketId[marketId]
|
|
602
|
-
)
|
|
601
|
+
for (const marketId of touchedMarketIds) {
|
|
602
|
+
const context = this.computeMarketContext(marketId)
|
|
603
603
|
if (context === undefined) {
|
|
604
|
-
|
|
604
|
+
delete data[marketId]
|
|
605
|
+
} else {
|
|
606
|
+
data[marketId] = context
|
|
605
607
|
}
|
|
606
|
-
data[marketId] = context
|
|
607
608
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
609
|
+
this.marketsContextByMarketId = data
|
|
610
|
+
this.emit('marketsContext', { channel: 'marketsContext', data })
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Context for one market from the cached feeds: spot asset context when it
|
|
615
|
+
* maps, else perp asset context with mid + mark overlaid from
|
|
616
|
+
* `fastAssetCtxs`, else the fast feed alone — each price standing in for the
|
|
617
|
+
* other where it carries only one of mid/mark.
|
|
618
|
+
*/
|
|
619
|
+
private computeMarketContext(marketId: string): MarketContext | undefined {
|
|
620
|
+
const fast = this.fastCtxByMarketId[marketId]
|
|
621
|
+
const spotCtx = this.spotCtxByMarketId[marketId]
|
|
622
|
+
if (spotCtx !== undefined) {
|
|
623
|
+
const context = mapSpotMarketContext(marketId, spotCtx, fast)
|
|
624
|
+
if (context !== undefined) {
|
|
625
|
+
return context
|
|
611
626
|
}
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
627
|
+
}
|
|
628
|
+
let perpCtx: HlWsPerpAssetCtx | undefined
|
|
629
|
+
for (const byMarketId of this.perpCtxBySubDex.values()) {
|
|
630
|
+
perpCtx = byMarketId[marketId] ?? perpCtx
|
|
631
|
+
}
|
|
632
|
+
if (perpCtx !== undefined) {
|
|
633
|
+
const base = mapMarketContext(marketId, perpCtx)
|
|
634
|
+
return {
|
|
635
|
+
...base,
|
|
636
|
+
midPrice: fast?.midPx != null ? fast.midPx : base.midPrice,
|
|
637
|
+
markPrice: fast?.markPx != null ? fast.markPx : base.markPrice,
|
|
618
638
|
}
|
|
619
639
|
}
|
|
620
|
-
|
|
640
|
+
const midPrice = fast?.midPx ?? fast?.markPx
|
|
641
|
+
const markPrice = fast?.markPx ?? fast?.midPx
|
|
642
|
+
if (midPrice != null && markPrice != null) {
|
|
643
|
+
return { marketId, midPrice, markPrice }
|
|
644
|
+
}
|
|
645
|
+
return undefined
|
|
621
646
|
}
|
|
622
647
|
|
|
623
648
|
private handleActiveAssetCtx(data: HlWsActiveAssetCtxData, raw: string) {
|
|
@@ -725,6 +750,14 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
725
750
|
return
|
|
726
751
|
}
|
|
727
752
|
|
|
753
|
+
// Compact deltas decode asynchronously via `orderbookDecodeChain`, so one
|
|
754
|
+
// can resolve after a newer frame (sync snapshot/update, or a later delta)
|
|
755
|
+
// has already been applied. A delta no newer than the maintained book is
|
|
756
|
+
// stale; applying it would overwrite fresher state with older levels.
|
|
757
|
+
if (delta.t <= previous.timestamp) {
|
|
758
|
+
return
|
|
759
|
+
}
|
|
760
|
+
|
|
728
761
|
const book: OrderbookResponse = {
|
|
729
762
|
provider: this.providerKey,
|
|
730
763
|
marketId: delta.c,
|
|
@@ -806,8 +839,7 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
806
839
|
continue
|
|
807
840
|
}
|
|
808
841
|
const type = mapOrderType(o.orderType)
|
|
809
|
-
//
|
|
810
|
-
// (the id may have listed after the snapshot); skip just this item.
|
|
842
|
+
// Unknown market id (absent from the synced snapshot); skip just this item.
|
|
811
843
|
const market = this.registry?.get(o.coin)
|
|
812
844
|
if (!market) {
|
|
813
845
|
continue
|