@lifi/perps-sdk-provider-hyperliquid 1.5.4 → 1.5.6
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/utils/decodeFastAssetCtxs.d.ts.map +1 -1
- package/dist/cjs/utils/decodeFastAssetCtxs.js +11 -6
- package/dist/cjs/utils/decodeFastAssetCtxs.js.map +1 -1
- package/dist/cjs/websocket/HyperliquidWsProvider.d.ts +7 -4
- package/dist/cjs/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/dist/cjs/websocket/HyperliquidWsProvider.js +77 -62
- package/dist/cjs/websocket/HyperliquidWsProvider.js.map +1 -1
- package/dist/cjs/websocket/decodeChain.d.ts +11 -0
- package/dist/cjs/websocket/decodeChain.d.ts.map +1 -0
- package/dist/cjs/websocket/decodeChain.js +37 -0
- package/dist/cjs/websocket/decodeChain.js.map +1 -0
- 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/utils/decodeFastAssetCtxs.d.ts +1 -0
- package/dist/esm/utils/decodeFastAssetCtxs.d.ts.map +1 -1
- package/dist/esm/utils/decodeFastAssetCtxs.js +14 -6
- package/dist/esm/utils/decodeFastAssetCtxs.js.map +1 -1
- package/dist/esm/websocket/HyperliquidWsProvider.d.ts +20 -7
- package/dist/esm/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/dist/esm/websocket/HyperliquidWsProvider.js +100 -71
- package/dist/esm/websocket/HyperliquidWsProvider.js.map +1 -1
- package/dist/esm/websocket/decodeChain.d.ts +30 -0
- package/dist/esm/websocket/decodeChain.d.ts.map +1 -0
- package/dist/esm/websocket/decodeChain.js +44 -0
- package/dist/esm/websocket/decodeChain.js.map +1 -0
- 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/utils/decodeFastAssetCtxs.d.ts +1 -0
- package/dist/types/utils/decodeFastAssetCtxs.d.ts.map +1 -1
- package/dist/types/websocket/HyperliquidWsProvider.d.ts +20 -7
- package/dist/types/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/dist/types/websocket/decodeChain.d.ts +30 -0
- package/dist/types/websocket/decodeChain.d.ts.map +1 -0
- package/package.json +3 -3
- package/src/services/getFills.ts +37 -11
- package/src/services/getOrders.ts +1 -1
- package/src/types/order.ts +1 -1
- package/src/utils/decodeFastAssetCtxs.ts +14 -6
- package/src/websocket/HyperliquidWsProvider.ts +136 -93
- package/src/websocket/decodeChain.ts +54 -0
|
@@ -61,6 +61,7 @@ import {
|
|
|
61
61
|
spotBalance,
|
|
62
62
|
spotPriceById,
|
|
63
63
|
} from '../utils/index.js'
|
|
64
|
+
import { DecodeChain } from './decodeChain.js'
|
|
64
65
|
|
|
65
66
|
/** HL's compact `l2` snapshot carries 20 levels per side. */
|
|
66
67
|
const HL_L2_BOOK_MAX_LEVELS_PER_SIDE = 20
|
|
@@ -99,6 +100,7 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
99
100
|
private readonly registry: MarketRegistry | undefined
|
|
100
101
|
private perpCtxBySubDex = new Map<string, Record<string, HlWsPerpAssetCtx>>()
|
|
101
102
|
private spotCtxByMarketId: Record<string, HlWsSpotAssetCtx> = {}
|
|
103
|
+
private marketsContextByMarketId: Record<string, MarketContext> = {}
|
|
102
104
|
private orderbookKeysByMarketId = new Map<string, Set<string>>()
|
|
103
105
|
private latestOrderbookByMarketId = new Map<string, OrderbookResponse>()
|
|
104
106
|
// Latest mid/mark per `Market.id` from the high-frequency `fastAssetCtxs`
|
|
@@ -106,12 +108,29 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
106
108
|
// frames carry only changed coins — and overlaid onto asset contexts that
|
|
107
109
|
// carry oracle/funding/OI/metadata.
|
|
108
110
|
private fastCtxByMarketId: Record<string, HlWsFastAssetCtx> = {}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
private readonly reportDecodeFailure = (error: unknown) =>
|
|
112
|
+
wsLog.handlerFailure(this.providerKey, error)
|
|
113
|
+
// Compressed payloads (base64 + raw-DEFLATE) decode async, so each channel
|
|
114
|
+
// chains decodes to apply frames in arrival order. Only the fast feed
|
|
115
|
+
// coalesces a stall backlog to its newest frame: a coin's dropped tick is
|
|
116
|
+
// refreshed by its next one. pac/sac field-merges and l2 deltas depend on
|
|
117
|
+
// every frame, so they must not coalesce.
|
|
118
|
+
private readonly fastDecodeChain = new DecodeChain(
|
|
119
|
+
'latest',
|
|
120
|
+
this.reportDecodeFailure
|
|
121
|
+
)
|
|
122
|
+
private readonly pacDecodeChain = new DecodeChain(
|
|
123
|
+
'every',
|
|
124
|
+
this.reportDecodeFailure
|
|
125
|
+
)
|
|
126
|
+
private readonly sacDecodeChain = new DecodeChain(
|
|
127
|
+
'every',
|
|
128
|
+
this.reportDecodeFailure
|
|
129
|
+
)
|
|
130
|
+
private readonly orderbookDecodeChain = new DecodeChain(
|
|
131
|
+
'every',
|
|
132
|
+
this.reportDecodeFailure
|
|
133
|
+
)
|
|
115
134
|
|
|
116
135
|
constructor(wsUrl: string, providerKey: string, client?: PerpsSDKClient) {
|
|
117
136
|
super(
|
|
@@ -173,6 +192,7 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
173
192
|
this.perpCtxBySubDex.clear()
|
|
174
193
|
this.spotCtxByMarketId = {}
|
|
175
194
|
this.fastCtxByMarketId = {}
|
|
195
|
+
this.marketsContextByMarketId = {}
|
|
176
196
|
}
|
|
177
197
|
}
|
|
178
198
|
|
|
@@ -292,12 +312,13 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
292
312
|
this.perpCtxBySubDex.clear()
|
|
293
313
|
this.spotCtxByMarketId = {}
|
|
294
314
|
this.fastCtxByMarketId = {}
|
|
315
|
+
this.marketsContextByMarketId = {}
|
|
295
316
|
this.orderbookKeysByMarketId.clear()
|
|
296
317
|
this.latestOrderbookByMarketId.clear()
|
|
297
|
-
this.fastDecodeChain
|
|
298
|
-
this.pacDecodeChain
|
|
299
|
-
this.sacDecodeChain
|
|
300
|
-
this.orderbookDecodeChain
|
|
318
|
+
this.fastDecodeChain.reset()
|
|
319
|
+
this.pacDecodeChain.reset()
|
|
320
|
+
this.sacDecodeChain.reset()
|
|
321
|
+
this.orderbookDecodeChain.reset()
|
|
301
322
|
this.orderUpdatesKey = undefined
|
|
302
323
|
}
|
|
303
324
|
|
|
@@ -483,61 +504,65 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
483
504
|
}
|
|
484
505
|
|
|
485
506
|
private handleAllDexsAssetCtxs(data: HlWsAllDexsAssetCtxsData) {
|
|
486
|
-
this.
|
|
487
|
-
|
|
507
|
+
this.emitMarketsContext(
|
|
508
|
+
this.mergePerpAssetCtxEntries(allDexsAssetCtxEntries(data))
|
|
509
|
+
)
|
|
488
510
|
}
|
|
489
511
|
|
|
490
512
|
private handlePac(base64: string) {
|
|
491
|
-
this.pacDecodeChain
|
|
492
|
-
.
|
|
513
|
+
this.pacDecodeChain.push(async () => {
|
|
514
|
+
this.emitMarketsContext(
|
|
493
515
|
this.mergePerpAssetCtxEntries(
|
|
494
516
|
await decodeCompressedJson<HlWsPacData>(base64)
|
|
495
517
|
)
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
.catch((error) => wsLog.handlerFailure(this.providerKey, error))
|
|
518
|
+
)
|
|
519
|
+
})
|
|
499
520
|
}
|
|
500
521
|
|
|
522
|
+
/** Merge perp asset contexts in place; returns the marketIds this frame touched. */
|
|
501
523
|
private mergePerpAssetCtxEntries(
|
|
502
524
|
entries: [string, HlWsPerpAssetCtxPayload[]][]
|
|
503
|
-
) {
|
|
525
|
+
): Set<string> {
|
|
526
|
+
const touched = new Set<string>()
|
|
504
527
|
for (const [dex, ctxs] of entries) {
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
528
|
+
let byMarketId = this.perpCtxBySubDex.get(dex || 'default')
|
|
529
|
+
if (byMarketId === undefined) {
|
|
530
|
+
byMarketId = {}
|
|
531
|
+
this.perpCtxBySubDex.set(dex || 'default', byMarketId)
|
|
508
532
|
}
|
|
509
533
|
for (const ctx of ctxs) {
|
|
510
534
|
const marketId = ctx.coin
|
|
511
535
|
if (marketId === undefined) {
|
|
512
536
|
continue
|
|
513
537
|
}
|
|
514
|
-
const merged = mergePerpAssetCtx(
|
|
538
|
+
const merged = mergePerpAssetCtx(byMarketId[marketId], marketId, ctx)
|
|
515
539
|
if (merged !== undefined) {
|
|
516
540
|
byMarketId[marketId] = merged
|
|
541
|
+
touched.add(marketId)
|
|
517
542
|
}
|
|
518
543
|
}
|
|
519
|
-
this.perpCtxBySubDex.set(dex || 'default', byMarketId)
|
|
520
544
|
}
|
|
545
|
+
return touched
|
|
521
546
|
}
|
|
522
547
|
|
|
523
548
|
private handleSac(base64: string) {
|
|
524
|
-
this.sacDecodeChain
|
|
525
|
-
.
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
}
|
|
533
|
-
this.spotCtxByMarketId[marketId] = {
|
|
534
|
-
...this.spotCtxByMarketId[marketId],
|
|
535
|
-
...ctx,
|
|
536
|
-
}
|
|
549
|
+
this.sacDecodeChain.push(async () => {
|
|
550
|
+
const spotMarketIdBySacKey = this.spotMarketIdBySacKey()
|
|
551
|
+
const ctxs = await decodeCompressedJson<HlWsSacData>(base64)
|
|
552
|
+
const touched = new Set<string>()
|
|
553
|
+
for (const [sacKey, ctx] of Object.entries(ctxs)) {
|
|
554
|
+
const marketId = spotMarketIdBySacKey.get(sacKey)
|
|
555
|
+
if (marketId === undefined) {
|
|
556
|
+
continue
|
|
537
557
|
}
|
|
538
|
-
this.
|
|
539
|
-
|
|
540
|
-
|
|
558
|
+
this.spotCtxByMarketId[marketId] = {
|
|
559
|
+
...this.spotCtxByMarketId[marketId],
|
|
560
|
+
...ctx,
|
|
561
|
+
}
|
|
562
|
+
touched.add(marketId)
|
|
563
|
+
}
|
|
564
|
+
this.emitMarketsContext(touched)
|
|
565
|
+
})
|
|
541
566
|
}
|
|
542
567
|
|
|
543
568
|
private spotMarketIdBySacKey(): Map<string, string> {
|
|
@@ -559,65 +584,78 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
559
584
|
* Decode a `fastAssetCtxs` frame (base64 + raw-DEFLATE) and merge its changed
|
|
560
585
|
* coins into the per-market fast-context store. Frames are incremental, so a
|
|
561
586
|
* field absent from this frame keeps its prior value. Decodes are chained to
|
|
562
|
-
* preserve arrival order across the async boundary
|
|
587
|
+
* preserve arrival order across the async boundary; a backlog coalesces to
|
|
588
|
+
* its newest frame (see the chain's mode).
|
|
563
589
|
*/
|
|
564
590
|
private handleFastAssetCtxs(base64: string) {
|
|
565
|
-
this.fastDecodeChain
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
midPx: 'midPx' in ctx ? ctx.midPx : prev?.midPx,
|
|
573
|
-
}
|
|
591
|
+
this.fastDecodeChain.push(async () => {
|
|
592
|
+
const ctxs = await decodeFastAssetCtxs(base64)
|
|
593
|
+
for (const [marketId, ctx] of Object.entries(ctxs)) {
|
|
594
|
+
const prev = this.fastCtxByMarketId[marketId]
|
|
595
|
+
this.fastCtxByMarketId[marketId] = {
|
|
596
|
+
markPx: 'markPx' in ctx ? ctx.markPx : prev?.markPx,
|
|
597
|
+
midPx: 'midPx' in ctx ? ctx.midPx : prev?.midPx,
|
|
574
598
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
599
|
+
}
|
|
600
|
+
this.emitMarketsContext(Object.keys(ctxs))
|
|
601
|
+
})
|
|
578
602
|
}
|
|
579
603
|
|
|
580
604
|
/**
|
|
581
|
-
*
|
|
582
|
-
*
|
|
605
|
+
* Emit the all-markets context map, re-mapping only the markets the incoming
|
|
606
|
+
* frame touched. Each emission is a fresh snapshot object that carries
|
|
607
|
+
* untouched entries over by reference, so a listener holding an earlier
|
|
608
|
+
* snapshot never observes later-frame mutation.
|
|
583
609
|
*/
|
|
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
|
-
}
|
|
610
|
+
private emitMarketsContext(touchedMarketIds: Iterable<string>) {
|
|
611
|
+
const data: Record<string, MarketContext> = {
|
|
612
|
+
...this.marketsContextByMarketId,
|
|
596
613
|
}
|
|
597
|
-
for (const
|
|
598
|
-
const context =
|
|
599
|
-
marketId,
|
|
600
|
-
ctx,
|
|
601
|
-
this.fastCtxByMarketId[marketId]
|
|
602
|
-
)
|
|
614
|
+
for (const marketId of touchedMarketIds) {
|
|
615
|
+
const context = this.computeMarketContext(marketId)
|
|
603
616
|
if (context === undefined) {
|
|
604
|
-
|
|
617
|
+
delete data[marketId]
|
|
618
|
+
} else {
|
|
619
|
+
data[marketId] = context
|
|
605
620
|
}
|
|
606
|
-
data[marketId] = context
|
|
607
621
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
622
|
+
this.marketsContextByMarketId = data
|
|
623
|
+
this.emit('marketsContext', { channel: 'marketsContext', data })
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Context for one market from the cached feeds: spot asset context when it
|
|
628
|
+
* maps, else perp asset context with mid + mark overlaid from
|
|
629
|
+
* `fastAssetCtxs`, else the fast feed alone — each price standing in for the
|
|
630
|
+
* other where it carries only one of mid/mark.
|
|
631
|
+
*/
|
|
632
|
+
private computeMarketContext(marketId: string): MarketContext | undefined {
|
|
633
|
+
const fast = this.fastCtxByMarketId[marketId]
|
|
634
|
+
const spotCtx = this.spotCtxByMarketId[marketId]
|
|
635
|
+
if (spotCtx !== undefined) {
|
|
636
|
+
const context = mapSpotMarketContext(marketId, spotCtx, fast)
|
|
637
|
+
if (context !== undefined) {
|
|
638
|
+
return context
|
|
611
639
|
}
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
640
|
+
}
|
|
641
|
+
let perpCtx: HlWsPerpAssetCtx | undefined
|
|
642
|
+
for (const byMarketId of this.perpCtxBySubDex.values()) {
|
|
643
|
+
perpCtx = byMarketId[marketId] ?? perpCtx
|
|
644
|
+
}
|
|
645
|
+
if (perpCtx !== undefined) {
|
|
646
|
+
const base = mapMarketContext(marketId, perpCtx)
|
|
647
|
+
return {
|
|
648
|
+
...base,
|
|
649
|
+
midPrice: fast?.midPx != null ? fast.midPx : base.midPrice,
|
|
650
|
+
markPrice: fast?.markPx != null ? fast.markPx : base.markPrice,
|
|
618
651
|
}
|
|
619
652
|
}
|
|
620
|
-
|
|
653
|
+
const midPrice = fast?.midPx ?? fast?.markPx
|
|
654
|
+
const markPrice = fast?.markPx ?? fast?.midPx
|
|
655
|
+
if (midPrice != null && markPrice != null) {
|
|
656
|
+
return { marketId, midPrice, markPrice }
|
|
657
|
+
}
|
|
658
|
+
return undefined
|
|
621
659
|
}
|
|
622
660
|
|
|
623
661
|
private handleActiveAssetCtx(data: HlWsActiveAssetCtxData, raw: string) {
|
|
@@ -710,13 +748,11 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
710
748
|
return
|
|
711
749
|
}
|
|
712
750
|
const compressed = data.c
|
|
713
|
-
this.orderbookDecodeChain
|
|
714
|
-
.
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
})
|
|
719
|
-
.catch((error) => wsLog.handlerFailure(this.providerKey, error))
|
|
751
|
+
this.orderbookDecodeChain.push(async () => {
|
|
752
|
+
this.handleCompactL2Delta(
|
|
753
|
+
await decodeCompressedJson<HlWsCompressedL2Data>(compressed)
|
|
754
|
+
)
|
|
755
|
+
})
|
|
720
756
|
}
|
|
721
757
|
|
|
722
758
|
private handleCompactL2Delta(delta: HlWsCompressedL2Data) {
|
|
@@ -725,6 +761,14 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
725
761
|
return
|
|
726
762
|
}
|
|
727
763
|
|
|
764
|
+
// Compact deltas decode asynchronously via `orderbookDecodeChain`, so one
|
|
765
|
+
// can resolve after a newer frame (sync snapshot/update, or a later delta)
|
|
766
|
+
// has already been applied. A delta no newer than the maintained book is
|
|
767
|
+
// stale; applying it would overwrite fresher state with older levels.
|
|
768
|
+
if (delta.t <= previous.timestamp) {
|
|
769
|
+
return
|
|
770
|
+
}
|
|
771
|
+
|
|
728
772
|
const book: OrderbookResponse = {
|
|
729
773
|
provider: this.providerKey,
|
|
730
774
|
marketId: delta.c,
|
|
@@ -806,8 +850,7 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
806
850
|
continue
|
|
807
851
|
}
|
|
808
852
|
const type = mapOrderType(o.orderType)
|
|
809
|
-
//
|
|
810
|
-
// (the id may have listed after the snapshot); skip just this item.
|
|
853
|
+
// Unknown market id (absent from the synced snapshot); skip just this item.
|
|
811
854
|
const market = this.registry?.get(o.coin)
|
|
812
855
|
if (!market) {
|
|
813
856
|
continue
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frame semantics of a {@link DecodeChain}:
|
|
3
|
+
* - `'every'`: every frame decodes and applies in arrival order — required for
|
|
4
|
+
* delta-carrying channels, where dropping a frame corrupts downstream state.
|
|
5
|
+
* - `'latest'`: frames queued behind an in-flight decode coalesce to the
|
|
6
|
+
* newest — for snapshot-like channels, where a newer frame supersedes
|
|
7
|
+
* anything still waiting.
|
|
8
|
+
*/
|
|
9
|
+
export type DecodeChainMode = 'every' | 'latest'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Serializes async WS frame decodes so results apply in arrival order.
|
|
13
|
+
* In `'latest'` mode a backlog (e.g. queued behind a main-thread stall)
|
|
14
|
+
* collapses to its newest frame instead of replaying every stale decode.
|
|
15
|
+
* Decode failures are reported to `onError` and never break the chain.
|
|
16
|
+
*/
|
|
17
|
+
export class DecodeChain {
|
|
18
|
+
private tail: Promise<void> = Promise.resolve()
|
|
19
|
+
private queued: (() => Promise<void>) | undefined
|
|
20
|
+
|
|
21
|
+
constructor(
|
|
22
|
+
private readonly mode: DecodeChainMode,
|
|
23
|
+
private readonly onError: (error: unknown) => void
|
|
24
|
+
) {}
|
|
25
|
+
|
|
26
|
+
push(decode: () => Promise<void>): void {
|
|
27
|
+
if (this.mode === 'every') {
|
|
28
|
+
this.tail = this.tail.then(decode).catch(this.onError)
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
const drainScheduled = this.queued !== undefined
|
|
32
|
+
this.queued = decode
|
|
33
|
+
if (drainScheduled) {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
this.tail = this.tail
|
|
37
|
+
.then(() => {
|
|
38
|
+
const next = this.queued
|
|
39
|
+
this.queued = undefined
|
|
40
|
+
return next?.()
|
|
41
|
+
})
|
|
42
|
+
.catch(this.onError)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Detach on connection teardown: drops the queued latest-mode decode and
|
|
47
|
+
* starts subsequent pushes on a fresh chain. A decode already in flight
|
|
48
|
+
* still settles.
|
|
49
|
+
*/
|
|
50
|
+
reset(): void {
|
|
51
|
+
this.tail = Promise.resolve()
|
|
52
|
+
this.queued = undefined
|
|
53
|
+
}
|
|
54
|
+
}
|