@lifi/perps-sdk-provider-hyperliquid 15.0.0 → 16.0.0
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/HyperliquidProvider.d.ts.map +1 -1
- package/dist/cjs/HyperliquidProvider.js +4 -0
- package/dist/cjs/HyperliquidProvider.js.map +1 -1
- package/dist/cjs/accountSummary.d.ts.map +1 -1
- package/dist/cjs/accountSummary.js +34 -7
- package/dist/cjs/accountSummary.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/services/activeAssetData.d.ts +6 -0
- package/dist/cjs/services/activeAssetData.d.ts.map +1 -0
- package/dist/cjs/services/activeAssetData.js +7 -0
- package/dist/cjs/services/activeAssetData.js.map +1 -0
- package/dist/cjs/services/getAccount.d.ts.map +1 -1
- package/dist/cjs/services/getAccount.js +23 -35
- package/dist/cjs/services/getAccount.js.map +1 -1
- package/dist/cjs/services/getAvailableToTrade.d.ts +10 -0
- package/dist/cjs/services/getAvailableToTrade.d.ts.map +1 -0
- package/dist/cjs/services/getAvailableToTrade.js +32 -0
- package/dist/cjs/services/getAvailableToTrade.js.map +1 -0
- package/dist/cjs/services/getMarketSettings.d.ts +1 -1
- package/dist/cjs/services/getMarketSettings.d.ts.map +1 -1
- package/dist/cjs/services/getMarketSettings.js +3 -7
- package/dist/cjs/services/getMarketSettings.js.map +1 -1
- package/dist/cjs/services/getWithdrawableBalances.d.ts +5 -0
- package/dist/cjs/services/getWithdrawableBalances.d.ts.map +1 -0
- package/dist/cjs/services/getWithdrawableBalances.js +27 -0
- package/dist/cjs/services/getWithdrawableBalances.js.map +1 -0
- package/dist/cjs/types/account.d.ts +11 -8
- package/dist/cjs/types/account.d.ts.map +1 -1
- package/dist/cjs/types/account.js.map +1 -1
- package/dist/cjs/types/ws.d.ts +3 -4
- package/dist/cjs/types/ws.d.ts.map +1 -1
- package/dist/cjs/utils/abstractionMode.d.ts +1 -1
- package/dist/cjs/utils/abstractionMode.d.ts.map +1 -1
- package/dist/cjs/utils/abstractionMode.js.map +1 -1
- package/dist/cjs/utils/index.d.ts +2 -0
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +6 -1
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/mapPosition.d.ts.map +1 -1
- package/dist/cjs/utils/mapPosition.js +1 -4
- package/dist/cjs/utils/mapPosition.js.map +1 -1
- package/dist/cjs/utils/spotCollateral.d.ts +1 -1
- package/dist/cjs/utils/spotCollateral.d.ts.map +1 -1
- package/dist/cjs/utils/spotCollateral.js +1 -12
- package/dist/cjs/utils/spotCollateral.js.map +1 -1
- package/dist/cjs/utils/venueTotals.d.ts +11 -0
- package/dist/cjs/utils/venueTotals.d.ts.map +1 -0
- package/dist/cjs/utils/venueTotals.js +24 -0
- package/dist/cjs/utils/venueTotals.js.map +1 -0
- package/dist/cjs/utils/withdrawableBalances.d.ts +4 -0
- package/dist/cjs/utils/withdrawableBalances.d.ts.map +1 -0
- package/dist/cjs/utils/withdrawableBalances.js +35 -0
- package/dist/cjs/utils/withdrawableBalances.js.map +1 -0
- package/dist/cjs/websocket/HyperliquidWsProvider.d.ts +3 -1
- package/dist/cjs/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/dist/cjs/websocket/HyperliquidWsProvider.js +102 -36
- package/dist/cjs/websocket/HyperliquidWsProvider.js.map +1 -1
- package/dist/esm/HyperliquidProvider.d.ts.map +1 -1
- package/dist/esm/HyperliquidProvider.js +4 -0
- package/dist/esm/HyperliquidProvider.js.map +1 -1
- package/dist/esm/accountSummary.d.ts +4 -3
- package/dist/esm/accountSummary.d.ts.map +1 -1
- package/dist/esm/accountSummary.js +36 -18
- package/dist/esm/accountSummary.js.map +1 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/services/activeAssetData.d.ts +13 -0
- package/dist/esm/services/activeAssetData.d.ts.map +1 -0
- package/dist/esm/services/activeAssetData.js +10 -0
- package/dist/esm/services/activeAssetData.js.map +1 -0
- package/dist/esm/services/getAccount.d.ts.map +1 -1
- package/dist/esm/services/getAccount.js +19 -29
- package/dist/esm/services/getAccount.js.map +1 -1
- package/dist/esm/services/getAvailableToTrade.d.ts +26 -0
- package/dist/esm/services/getAvailableToTrade.d.ts.map +1 -0
- package/dist/esm/services/getAvailableToTrade.js +42 -0
- package/dist/esm/services/getAvailableToTrade.js.map +1 -0
- package/dist/esm/services/getMarketSettings.d.ts +1 -1
- package/dist/esm/services/getMarketSettings.d.ts.map +1 -1
- package/dist/esm/services/getMarketSettings.js +3 -7
- package/dist/esm/services/getMarketSettings.js.map +1 -1
- package/dist/esm/services/getWithdrawableBalances.d.ts +22 -0
- package/dist/esm/services/getWithdrawableBalances.d.ts.map +1 -0
- package/dist/esm/services/getWithdrawableBalances.js +35 -0
- package/dist/esm/services/getWithdrawableBalances.js.map +1 -0
- package/dist/esm/types/account.d.ts +21 -8
- package/dist/esm/types/account.d.ts.map +1 -1
- package/dist/esm/types/account.js.map +1 -1
- package/dist/esm/types/ws.d.ts +10 -4
- package/dist/esm/types/ws.d.ts.map +1 -1
- package/dist/esm/utils/abstractionMode.d.ts +1 -1
- package/dist/esm/utils/abstractionMode.d.ts.map +1 -1
- package/dist/esm/utils/abstractionMode.js.map +1 -1
- package/dist/esm/utils/index.d.ts +2 -0
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/esm/utils/index.js +2 -0
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/mapPosition.d.ts.map +1 -1
- package/dist/esm/utils/mapPosition.js +1 -4
- package/dist/esm/utils/mapPosition.js.map +1 -1
- package/dist/esm/utils/spotCollateral.d.ts +4 -4
- package/dist/esm/utils/spotCollateral.d.ts.map +1 -1
- package/dist/esm/utils/spotCollateral.js +4 -23
- package/dist/esm/utils/spotCollateral.js.map +1 -1
- package/dist/esm/utils/venueTotals.d.ts +26 -0
- package/dist/esm/utils/venueTotals.d.ts.map +1 -0
- package/dist/esm/utils/venueTotals.js +26 -0
- package/dist/esm/utils/venueTotals.js.map +1 -0
- package/dist/esm/utils/withdrawableBalances.d.ts +14 -0
- package/dist/esm/utils/withdrawableBalances.d.ts.map +1 -0
- package/dist/esm/utils/withdrawableBalances.js +41 -0
- package/dist/esm/utils/withdrawableBalances.js.map +1 -0
- package/dist/esm/websocket/HyperliquidWsProvider.d.ts +4 -1
- package/dist/esm/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/dist/esm/websocket/HyperliquidWsProvider.js +101 -35
- package/dist/esm/websocket/HyperliquidWsProvider.js.map +1 -1
- package/dist/types/HyperliquidProvider.d.ts.map +1 -1
- package/dist/types/accountSummary.d.ts +4 -3
- package/dist/types/accountSummary.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/services/activeAssetData.d.ts +13 -0
- package/dist/types/services/activeAssetData.d.ts.map +1 -0
- package/dist/types/services/getAccount.d.ts.map +1 -1
- package/dist/types/services/getAvailableToTrade.d.ts +26 -0
- package/dist/types/services/getAvailableToTrade.d.ts.map +1 -0
- package/dist/types/services/getMarketSettings.d.ts +1 -1
- package/dist/types/services/getMarketSettings.d.ts.map +1 -1
- package/dist/types/services/getWithdrawableBalances.d.ts +22 -0
- package/dist/types/services/getWithdrawableBalances.d.ts.map +1 -0
- package/dist/types/types/account.d.ts +21 -8
- package/dist/types/types/account.d.ts.map +1 -1
- package/dist/types/types/ws.d.ts +10 -4
- package/dist/types/types/ws.d.ts.map +1 -1
- package/dist/types/utils/abstractionMode.d.ts +1 -1
- package/dist/types/utils/abstractionMode.d.ts.map +1 -1
- package/dist/types/utils/index.d.ts +2 -0
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/mapPosition.d.ts.map +1 -1
- package/dist/types/utils/spotCollateral.d.ts +4 -4
- package/dist/types/utils/spotCollateral.d.ts.map +1 -1
- package/dist/types/utils/venueTotals.d.ts +26 -0
- package/dist/types/utils/venueTotals.d.ts.map +1 -0
- package/dist/types/utils/withdrawableBalances.d.ts +14 -0
- package/dist/types/utils/withdrawableBalances.d.ts.map +1 -0
- package/dist/types/websocket/HyperliquidWsProvider.d.ts +4 -1
- package/dist/types/websocket/HyperliquidWsProvider.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/HyperliquidProvider.ts +26 -0
- package/src/accountSummary.ts +64 -19
- package/src/index.ts +2 -0
- package/src/services/activeAssetData.ts +24 -0
- package/src/services/getAccount.ts +37 -52
- package/src/services/getAvailableToTrade.ts +72 -0
- package/src/services/getMarketSettings.ts +7 -11
- package/src/services/getWithdrawableBalances.ts +84 -0
- package/src/types/account.ts +22 -8
- package/src/types/ws.ts +18 -5
- package/src/utils/abstractionMode.ts +1 -1
- package/src/utils/index.ts +6 -0
- package/src/utils/mapPosition.ts +1 -5
- package/src/utils/spotCollateral.ts +4 -25
- package/src/utils/venueTotals.ts +48 -0
- package/src/utils/withdrawableBalances.ts +57 -0
- package/src/websocket/HyperliquidWsProvider.ts +149 -42
- package/dist/cjs/websocket/decodeChain.d.ts +0 -11
- package/dist/cjs/websocket/decodeChain.d.ts.map +0 -1
- package/dist/cjs/websocket/decodeChain.js +0 -37
- package/dist/cjs/websocket/decodeChain.js.map +0 -1
- package/dist/esm/websocket/decodeChain.d.ts +0 -30
- package/dist/esm/websocket/decodeChain.d.ts.map +0 -1
- package/dist/esm/websocket/decodeChain.js +0 -44
- package/dist/esm/websocket/decodeChain.js.map +0 -1
- package/dist/types/websocket/decodeChain.d.ts +0 -30
- package/dist/types/websocket/decodeChain.d.ts.map +0 -1
- package/src/websocket/decodeChain.ts +0 -54
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
DecodeChain,
|
|
2
3
|
getMarketRegistry,
|
|
3
4
|
isActiveMarket,
|
|
4
5
|
isActiveOrderStatus,
|
|
@@ -10,7 +11,7 @@ import {
|
|
|
10
11
|
ReconnectingWebSocket,
|
|
11
12
|
resolveSubscribeQuote,
|
|
12
13
|
type SubscriptionListener,
|
|
13
|
-
|
|
14
|
+
toAssetDisplay,
|
|
14
15
|
toPerpsMarketDisplay,
|
|
15
16
|
WsProviderBase,
|
|
16
17
|
type WsProviderFactory,
|
|
@@ -19,7 +20,6 @@ import {
|
|
|
19
20
|
wsLog,
|
|
20
21
|
} from '@lifi/perps-sdk'
|
|
21
22
|
import type {
|
|
22
|
-
AccountResponse,
|
|
23
23
|
Balance,
|
|
24
24
|
MarketContext,
|
|
25
25
|
Order,
|
|
@@ -37,9 +37,11 @@ import {
|
|
|
37
37
|
SPOT_MARKET_ID,
|
|
38
38
|
} from '../constants.js'
|
|
39
39
|
import type {
|
|
40
|
+
HlActiveAssetData,
|
|
40
41
|
HlAssetPosition,
|
|
41
42
|
HlOrderDetail,
|
|
42
43
|
HlOrderStatusResponse,
|
|
44
|
+
HlSpotClearinghouseState,
|
|
43
45
|
HlUserFill,
|
|
44
46
|
HlWsActiveAssetCtxData,
|
|
45
47
|
HlWsActiveSpotAssetCtxData,
|
|
@@ -75,12 +77,13 @@ import {
|
|
|
75
77
|
mapOrder,
|
|
76
78
|
mapPosition,
|
|
77
79
|
partitionSpotBalances,
|
|
80
|
+
perpsTotals,
|
|
78
81
|
priceStepToAggregation,
|
|
79
82
|
spotAssetFromToken,
|
|
80
83
|
spotBalance,
|
|
81
84
|
spotPriceById,
|
|
85
|
+
sumUnrealizedPnl,
|
|
82
86
|
} from '../utils/index.js'
|
|
83
|
-
import { DecodeChain } from './decodeChain.js'
|
|
84
87
|
|
|
85
88
|
/** HL's compact `l2` snapshot carries 20 levels per side. */
|
|
86
89
|
const HL_L2_BOOK_MAX_LEVELS_PER_SIDE = 20
|
|
@@ -88,6 +91,15 @@ const HL_L2_BOOK_MAX_LEVELS_PER_SIDE = 20
|
|
|
88
91
|
const normalizeHlAddress = (address: string): string =>
|
|
89
92
|
isAddress(address, { strict: false }) ? address.toLowerCase() : address
|
|
90
93
|
|
|
94
|
+
/** Venue buying power for the asset the main perps dex settles in. */
|
|
95
|
+
const availableAfterMaintenance = (
|
|
96
|
+
spotState: { tokenToAvailableAfterMaintenance?: readonly [number, string][] },
|
|
97
|
+
quoteAssetId: string | undefined
|
|
98
|
+
): string | undefined =>
|
|
99
|
+
spotState.tokenToAvailableAfterMaintenance?.find(
|
|
100
|
+
([token]) => String(token) === quoteAssetId
|
|
101
|
+
)?.[1]
|
|
102
|
+
|
|
91
103
|
/**
|
|
92
104
|
* `WsProviderFactory` constructor for Hyperliquid — pass to
|
|
93
105
|
* `new PerpsWsClient(client, { wsProviders: { hyperliquid: hyperliquidWsProvider() } })`.
|
|
@@ -147,11 +159,16 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
147
159
|
{
|
|
148
160
|
releaseSpot: Promise<() => void>
|
|
149
161
|
spot?: { collateralBalances: Balance[]; balances: Balance[] }
|
|
162
|
+
availableMargin?: string
|
|
163
|
+
availableMarginPending?: boolean
|
|
150
164
|
}
|
|
151
165
|
>()
|
|
152
166
|
// Kept outside the pipeline entry: the first clearinghouse frame lands
|
|
153
167
|
// while the mode read is still pending, before the pipeline exists.
|
|
154
|
-
private readonly
|
|
168
|
+
private readonly latestPerpsByUser = new Map<
|
|
169
|
+
string,
|
|
170
|
+
{ positions: Position[]; marginUsed: string }
|
|
171
|
+
>()
|
|
155
172
|
private readonly heldSummaryByUser = new Map<
|
|
156
173
|
string,
|
|
157
174
|
{
|
|
@@ -273,7 +290,8 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
273
290
|
(sub.channel === 'marketContext' ||
|
|
274
291
|
sub.channel === 'orderbook' ||
|
|
275
292
|
sub.channel === 'candle' ||
|
|
276
|
-
sub.channel === 'trades'
|
|
293
|
+
sub.channel === 'trades' ||
|
|
294
|
+
sub.channel === 'availableToTrade')
|
|
277
295
|
) {
|
|
278
296
|
this.registry.requireActive(sub.marketId)
|
|
279
297
|
}
|
|
@@ -331,7 +349,7 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
331
349
|
// subscription so a resubscribe reflects an account-mode change.
|
|
332
350
|
this.abstractionByUser.delete(user)
|
|
333
351
|
this.heldSummaryByUser.delete(user)
|
|
334
|
-
this.
|
|
352
|
+
this.latestPerpsByUser.delete(user)
|
|
335
353
|
this.syncUnifiedPipeline(user, user, null)
|
|
336
354
|
this.unregisterSub(wireKey)
|
|
337
355
|
this.rws.send(
|
|
@@ -506,6 +524,8 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
506
524
|
return `accountSummary:${sub.address.toLowerCase()}`
|
|
507
525
|
case 'spotBalances':
|
|
508
526
|
return `spotState:${sub.address.toLowerCase()}`
|
|
527
|
+
case 'availableToTrade':
|
|
528
|
+
return `activeAssetData:${sub.address.toLowerCase()}:${sub.marketId}`
|
|
509
529
|
}
|
|
510
530
|
}
|
|
511
531
|
|
|
@@ -581,6 +601,12 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
581
601
|
}
|
|
582
602
|
case 'spotBalances':
|
|
583
603
|
return { type: 'spotState', user: normalizeHlAddress(sub.address) }
|
|
604
|
+
case 'availableToTrade':
|
|
605
|
+
return {
|
|
606
|
+
type: 'activeAssetData',
|
|
607
|
+
user: normalizeHlAddress(sub.address),
|
|
608
|
+
coin: sub.marketId,
|
|
609
|
+
}
|
|
584
610
|
}
|
|
585
611
|
}
|
|
586
612
|
|
|
@@ -656,6 +682,9 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
656
682
|
case 'spotState':
|
|
657
683
|
this.handleSpotState(msg.data as HlWsSpotStateData)
|
|
658
684
|
break
|
|
685
|
+
case 'activeAssetData':
|
|
686
|
+
this.handleActiveAssetData(msg.data as HlActiveAssetData)
|
|
687
|
+
break
|
|
659
688
|
}
|
|
660
689
|
} catch (error) {
|
|
661
690
|
wsLog.handlerFailure(this.providerKey, error)
|
|
@@ -1130,30 +1159,26 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
1130
1159
|
data: positions,
|
|
1131
1160
|
})
|
|
1132
1161
|
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
let accountValue = 0
|
|
1137
|
-
let marginUsed = 0
|
|
1138
|
-
for (const [, state] of data.clearinghouseStates) {
|
|
1139
|
-
accountValue +=
|
|
1140
|
-
Number.parseFloat(state.marginSummary?.accountValue ?? '') || 0
|
|
1141
|
-
marginUsed +=
|
|
1142
|
-
Number.parseFloat(state.marginSummary?.totalMarginUsed ?? '') || 0
|
|
1143
|
-
}
|
|
1144
|
-
const unrealizedPnl = positions.reduce(
|
|
1145
|
-
(sum, p) => sum + (Number.parseFloat(p.unrealizedPnl) || 0),
|
|
1146
|
-
0
|
|
1162
|
+
const { accountValue, marginUsed } = perpsTotals(
|
|
1163
|
+
data.clearinghouseStates.map(([, state]) => state)
|
|
1147
1164
|
)
|
|
1165
|
+
|
|
1166
|
+
const key = data.user.toLowerCase()
|
|
1167
|
+
this.latestPerpsByUser.set(key, {
|
|
1168
|
+
positions,
|
|
1169
|
+
marginUsed: marginUsed.toFixed(),
|
|
1170
|
+
})
|
|
1171
|
+
this.emitUnifiedSummary(key)
|
|
1172
|
+
|
|
1148
1173
|
// Equity semantics, matching the REST summary: `accountValue` already
|
|
1149
1174
|
// carries locked margin and unrealized PnL. Spot balances stream apart,
|
|
1150
1175
|
// so this portfolio value covers perps equity only — which is why the
|
|
1151
1176
|
// frame is gated on the abstraction mode below.
|
|
1152
1177
|
this.emitSummaryIfModeAllows(data.user, {
|
|
1153
|
-
portfolioValue: accountValue.
|
|
1154
|
-
availableMargin: (
|
|
1155
|
-
marginUsed: marginUsed.
|
|
1156
|
-
unrealizedPnl:
|
|
1178
|
+
portfolioValue: accountValue.toFixed(),
|
|
1179
|
+
availableMargin: accountValue.minus(marginUsed).toFixed(),
|
|
1180
|
+
marginUsed: marginUsed.toFixed(),
|
|
1181
|
+
unrealizedPnl: sumUnrealizedPnl(positions).toFixed(),
|
|
1157
1182
|
})
|
|
1158
1183
|
}
|
|
1159
1184
|
|
|
@@ -1219,24 +1244,32 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
1219
1244
|
|
|
1220
1245
|
private emitUnifiedSummary(key: string) {
|
|
1221
1246
|
const pipeline = this.unifiedSummaryByUser.get(key)
|
|
1222
|
-
const
|
|
1247
|
+
const perps = this.latestPerpsByUser.get(key)
|
|
1223
1248
|
// Both envelopes must have arrived: a spot-only summary would report
|
|
1224
1249
|
// zero margin used against real positions.
|
|
1225
|
-
if (
|
|
1250
|
+
if (
|
|
1251
|
+
pipeline?.spot === undefined ||
|
|
1252
|
+
pipeline.availableMargin === undefined ||
|
|
1253
|
+
perps === undefined
|
|
1254
|
+
) {
|
|
1226
1255
|
return
|
|
1227
1256
|
}
|
|
1228
|
-
const
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
'gross'
|
|
1257
|
+
const portfolioValue = [
|
|
1258
|
+
...pipeline.spot.collateralBalances,
|
|
1259
|
+
...pipeline.spot.balances,
|
|
1260
|
+
].reduce(
|
|
1261
|
+
(sum, balance) =>
|
|
1262
|
+
sum.plus(toWireBig(balance.valueUsd, 'spotBalance.valueUsd')),
|
|
1263
|
+
new Big(0)
|
|
1236
1264
|
)
|
|
1237
1265
|
this.emit(`accountSummary:${key}`, {
|
|
1238
1266
|
channel: 'accountSummary',
|
|
1239
|
-
data:
|
|
1267
|
+
data: {
|
|
1268
|
+
portfolioValue: portfolioValue.toFixed(),
|
|
1269
|
+
availableMargin: pipeline.availableMargin,
|
|
1270
|
+
marginUsed: perps.marginUsed,
|
|
1271
|
+
unrealizedPnl: sumUnrealizedPnl(perps.positions).toFixed(),
|
|
1272
|
+
},
|
|
1240
1273
|
})
|
|
1241
1274
|
}
|
|
1242
1275
|
|
|
@@ -1334,6 +1367,27 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
1334
1367
|
)
|
|
1335
1368
|
}
|
|
1336
1369
|
|
|
1370
|
+
private handleActiveAssetData(data: HlActiveAssetData) {
|
|
1371
|
+
const market = this.registry?.get(data.coin)
|
|
1372
|
+
if (market === undefined) {
|
|
1373
|
+
throw new PerpsError(
|
|
1374
|
+
PerpsErrorCode.ValidationError,
|
|
1375
|
+
`[${this.providerKey}] activeAssetData frame names unknown market '${data.coin}'.`
|
|
1376
|
+
)
|
|
1377
|
+
}
|
|
1378
|
+
const [buy, sell] = data.availableToTrade
|
|
1379
|
+
this.emit(`activeAssetData:${data.user.toLowerCase()}:${data.coin}`, {
|
|
1380
|
+
channel: 'availableToTrade',
|
|
1381
|
+
data: {
|
|
1382
|
+
providerId: market.providerId,
|
|
1383
|
+
marketId: market.id,
|
|
1384
|
+
asset: toAssetDisplay(market.quoteAsset),
|
|
1385
|
+
buy,
|
|
1386
|
+
sell,
|
|
1387
|
+
},
|
|
1388
|
+
})
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1337
1391
|
private handleSpotState(data: HlWsSpotStateData) {
|
|
1338
1392
|
const user = data.user.toLowerCase()
|
|
1339
1393
|
const markets = this.registry?.activeMarkets ?? []
|
|
@@ -1360,20 +1414,66 @@ export class HyperliquidWsProvider extends WsProviderBase<object> {
|
|
|
1360
1414
|
const pipeline = this.unifiedSummaryByUser.get(user)
|
|
1361
1415
|
if (pipeline !== undefined) {
|
|
1362
1416
|
const quoteAssetIds = new Set(markets.map((m) => m.quoteAsset.id))
|
|
1363
|
-
const entry = this.abstractionByUser.get(user)
|
|
1364
|
-
const portfolioMargin =
|
|
1365
|
-
entry !== undefined &&
|
|
1366
|
-
entry !== 'pending' &&
|
|
1367
|
-
entry.mode === HlAbstractionMode.PORTFOLIO_MARGIN
|
|
1368
1417
|
// Same partition as getAccount so REST and WS agree on collateral.
|
|
1369
1418
|
pipeline.spot = partitionSpotBalances(
|
|
1370
1419
|
rows.map(({ balance }) => balance),
|
|
1371
|
-
quoteAssetIds
|
|
1372
|
-
portfolioMargin
|
|
1420
|
+
quoteAssetIds
|
|
1373
1421
|
)
|
|
1422
|
+
const settlementAssetId = markets.find(
|
|
1423
|
+
(m) => m.categoryId === this.providerKey
|
|
1424
|
+
)?.quoteAsset.id
|
|
1425
|
+
const available = availableAfterMaintenance(
|
|
1426
|
+
data.spotState,
|
|
1427
|
+
settlementAssetId
|
|
1428
|
+
)
|
|
1429
|
+
if (available === undefined) {
|
|
1430
|
+
this.fetchAvailableAfterMaintenance(user, data.user, settlementAssetId)
|
|
1431
|
+
} else {
|
|
1432
|
+
pipeline.availableMargin = available
|
|
1433
|
+
}
|
|
1374
1434
|
this.emitUnifiedSummary(user)
|
|
1375
1435
|
}
|
|
1376
1436
|
}
|
|
1437
|
+
|
|
1438
|
+
/** Read the venue buying power over REST when the spot frame omits it. */
|
|
1439
|
+
private fetchAvailableAfterMaintenance(
|
|
1440
|
+
key: string,
|
|
1441
|
+
user: string,
|
|
1442
|
+
quoteAssetId: string | undefined
|
|
1443
|
+
) {
|
|
1444
|
+
const client = this.client
|
|
1445
|
+
const pipeline = this.unifiedSummaryByUser.get(key)
|
|
1446
|
+
if (
|
|
1447
|
+
client === undefined ||
|
|
1448
|
+
pipeline === undefined ||
|
|
1449
|
+
pipeline.availableMarginPending
|
|
1450
|
+
) {
|
|
1451
|
+
return
|
|
1452
|
+
}
|
|
1453
|
+
pipeline.availableMarginPending = true
|
|
1454
|
+
infoRequest<HlSpotClearinghouseState>(
|
|
1455
|
+
DEFAULT_HYPERLIQUID_API_URL,
|
|
1456
|
+
{ type: 'spotClearinghouseState', user },
|
|
1457
|
+
hlInfoOptions(client)
|
|
1458
|
+
).then(
|
|
1459
|
+
(state) => {
|
|
1460
|
+
const current = this.unifiedSummaryByUser.get(key)
|
|
1461
|
+
if (current === undefined) {
|
|
1462
|
+
return
|
|
1463
|
+
}
|
|
1464
|
+
current.availableMarginPending = false
|
|
1465
|
+
current.availableMargin = availableAfterMaintenance(state, quoteAssetId)
|
|
1466
|
+
this.emitUnifiedSummary(key)
|
|
1467
|
+
},
|
|
1468
|
+
(error) => {
|
|
1469
|
+
const current = this.unifiedSummaryByUser.get(key)
|
|
1470
|
+
if (current !== undefined) {
|
|
1471
|
+
current.availableMarginPending = false
|
|
1472
|
+
}
|
|
1473
|
+
wsLog.handlerFailure(this.providerKey, error)
|
|
1474
|
+
}
|
|
1475
|
+
)
|
|
1476
|
+
}
|
|
1377
1477
|
}
|
|
1378
1478
|
|
|
1379
1479
|
const isObject = (v: unknown): v is Record<string, unknown> =>
|
|
@@ -1599,6 +1699,13 @@ function isValidHlFrame(channel: string, data: unknown): boolean {
|
|
|
1599
1699
|
isObject(data.spotState) &&
|
|
1600
1700
|
Array.isArray(data.spotState.balances)
|
|
1601
1701
|
)
|
|
1702
|
+
case 'activeAssetData':
|
|
1703
|
+
return (
|
|
1704
|
+
typeof data.user === 'string' &&
|
|
1705
|
+
typeof data.coin === 'string' &&
|
|
1706
|
+
Array.isArray(data.availableToTrade) &&
|
|
1707
|
+
data.availableToTrade.length === 2
|
|
1708
|
+
)
|
|
1602
1709
|
default:
|
|
1603
1710
|
return true
|
|
1604
1711
|
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export type DecodeChainMode = 'every' | 'latest';
|
|
2
|
-
export declare class DecodeChain {
|
|
3
|
-
private readonly mode;
|
|
4
|
-
private readonly onError;
|
|
5
|
-
private tail;
|
|
6
|
-
private queued;
|
|
7
|
-
constructor(mode: DecodeChainMode, onError: (error: unknown) => void);
|
|
8
|
-
push(decode: () => Promise<void>): void;
|
|
9
|
-
reset(): void;
|
|
10
|
-
}
|
|
11
|
-
//# sourceMappingURL=decodeChain.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"decodeChain.d.ts","sourceRoot":"","sources":["../../../src/websocket/decodeChain.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,QAAQ,CAAA;AAQhD,qBAAa,WAAW;IAKpB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAL1B,OAAO,CAAC,IAAI,CAAmC;IAC/C,OAAO,CAAC,MAAM,CAAmC;gBAG9B,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI;IAGpD,IAAI,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAwBvC,KAAK,IAAI,IAAI;CAId"}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DecodeChain = void 0;
|
|
4
|
-
class DecodeChain {
|
|
5
|
-
mode;
|
|
6
|
-
onError;
|
|
7
|
-
tail = Promise.resolve();
|
|
8
|
-
queued;
|
|
9
|
-
constructor(mode, onError) {
|
|
10
|
-
this.mode = mode;
|
|
11
|
-
this.onError = onError;
|
|
12
|
-
}
|
|
13
|
-
push(decode) {
|
|
14
|
-
if (this.mode === 'every') {
|
|
15
|
-
this.tail = this.tail.then(decode).catch(this.onError);
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
const drainScheduled = this.queued !== undefined;
|
|
19
|
-
this.queued = decode;
|
|
20
|
-
if (drainScheduled) {
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
this.tail = this.tail
|
|
24
|
-
.then(() => {
|
|
25
|
-
const next = this.queued;
|
|
26
|
-
this.queued = undefined;
|
|
27
|
-
return next?.();
|
|
28
|
-
})
|
|
29
|
-
.catch(this.onError);
|
|
30
|
-
}
|
|
31
|
-
reset() {
|
|
32
|
-
this.tail = Promise.resolve();
|
|
33
|
-
this.queued = undefined;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
exports.DecodeChain = DecodeChain;
|
|
37
|
-
//# sourceMappingURL=decodeChain.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"decodeChain.js","sourceRoot":"","sources":["../../../src/websocket/decodeChain.ts"],"names":[],"mappings":";;;AAgBA,MAAa,WAAW;IAKH;IACA;IALX,IAAI,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAA;IACvC,MAAM,CAAmC;IAEjD,YACmB,IAAqB,EACrB,OAAiC;QADjC,SAAI,GAAJ,IAAI,CAAiB;QACrB,YAAO,GAAP,OAAO,CAA0B;IACjD,CAAC;IAEJ,IAAI,CAAC,MAA2B;QAC9B,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACtD,OAAM;QACR,CAAC;QACD,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,KAAK,SAAS,CAAA;QAChD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,cAAc,EAAE,CAAC;YACnB,OAAM;QACR,CAAC;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI;aAClB,IAAI,CAAC,GAAG,EAAE;YACT,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAA;YACxB,IAAI,CAAC,MAAM,GAAG,SAAS,CAAA;YACvB,OAAO,IAAI,EAAE,EAAE,CAAA;QACjB,CAAC,CAAC;aACD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACxB,CAAC;IAOD,KAAK;QACH,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,CAAA;QAC7B,IAAI,CAAC,MAAM,GAAG,SAAS,CAAA;IACzB,CAAC;CACF;AArCD,kCAqCC"}
|
|
@@ -1,30 +0,0 @@
|
|
|
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
|
-
* Serializes async WS frame decodes so results apply in arrival order.
|
|
12
|
-
* In `'latest'` mode a backlog (e.g. queued behind a main-thread stall)
|
|
13
|
-
* collapses to its newest frame instead of replaying every stale decode.
|
|
14
|
-
* Decode failures are reported to `onError` and never break the chain.
|
|
15
|
-
*/
|
|
16
|
-
export declare class DecodeChain {
|
|
17
|
-
private readonly mode;
|
|
18
|
-
private readonly onError;
|
|
19
|
-
private tail;
|
|
20
|
-
private queued;
|
|
21
|
-
constructor(mode: DecodeChainMode, onError: (error: unknown) => void);
|
|
22
|
-
push(decode: () => Promise<void>): void;
|
|
23
|
-
/**
|
|
24
|
-
* Detach on connection teardown: drops the queued latest-mode decode and
|
|
25
|
-
* starts subsequent pushes on a fresh chain. A decode already in flight
|
|
26
|
-
* still settles.
|
|
27
|
-
*/
|
|
28
|
-
reset(): void;
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=decodeChain.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"decodeChain.d.ts","sourceRoot":"","sources":["../../../src/websocket/decodeChain.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEhD;;;;;GAKG;AACH,qBAAa,WAAW;IAKpB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAL1B,OAAO,CAAC,IAAI,CAAmC;IAC/C,OAAO,CAAC,MAAM,CAAmC;gBAG9B,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI;IAGpD,IAAI,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAmBvC;;;;OAIG;IACH,KAAK,IAAI,IAAI;CAId"}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Serializes async WS frame decodes so results apply in arrival order.
|
|
3
|
-
* In `'latest'` mode a backlog (e.g. queued behind a main-thread stall)
|
|
4
|
-
* collapses to its newest frame instead of replaying every stale decode.
|
|
5
|
-
* Decode failures are reported to `onError` and never break the chain.
|
|
6
|
-
*/
|
|
7
|
-
export class DecodeChain {
|
|
8
|
-
mode;
|
|
9
|
-
onError;
|
|
10
|
-
tail = Promise.resolve();
|
|
11
|
-
queued;
|
|
12
|
-
constructor(mode, onError) {
|
|
13
|
-
this.mode = mode;
|
|
14
|
-
this.onError = onError;
|
|
15
|
-
}
|
|
16
|
-
push(decode) {
|
|
17
|
-
if (this.mode === 'every') {
|
|
18
|
-
this.tail = this.tail.then(decode).catch(this.onError);
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
const drainScheduled = this.queued !== undefined;
|
|
22
|
-
this.queued = decode;
|
|
23
|
-
if (drainScheduled) {
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
this.tail = this.tail
|
|
27
|
-
.then(() => {
|
|
28
|
-
const next = this.queued;
|
|
29
|
-
this.queued = undefined;
|
|
30
|
-
return next?.();
|
|
31
|
-
})
|
|
32
|
-
.catch(this.onError);
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Detach on connection teardown: drops the queued latest-mode decode and
|
|
36
|
-
* starts subsequent pushes on a fresh chain. A decode already in flight
|
|
37
|
-
* still settles.
|
|
38
|
-
*/
|
|
39
|
-
reset() {
|
|
40
|
-
this.tail = Promise.resolve();
|
|
41
|
-
this.queued = undefined;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
//# sourceMappingURL=decodeChain.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"decodeChain.js","sourceRoot":"","sources":["../../../src/websocket/decodeChain.ts"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH,MAAM,OAAO,WAAW;IAKH;IACA;IALX,IAAI,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAA;IACvC,MAAM,CAAmC;IAEjD,YACmB,IAAqB,EACrB,OAAiC;QADjC,SAAI,GAAJ,IAAI,CAAiB;QACrB,YAAO,GAAP,OAAO,CAA0B;IACjD,CAAC;IAEJ,IAAI,CAAC,MAA2B;QAC9B,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACtD,OAAM;QACR,CAAC;QACD,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,KAAK,SAAS,CAAA;QAChD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,cAAc,EAAE,CAAC;YACnB,OAAM;QACR,CAAC;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI;aAClB,IAAI,CAAC,GAAG,EAAE;YACT,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAA;YACxB,IAAI,CAAC,MAAM,GAAG,SAAS,CAAA;YACvB,OAAO,IAAI,EAAE,EAAE,CAAA;QACjB,CAAC,CAAC;aACD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACxB,CAAC;IAED;;;;OAIG;IACH,KAAK;QACH,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,CAAA;QAC7B,IAAI,CAAC,MAAM,GAAG,SAAS,CAAA;IACzB,CAAC;CACF"}
|
|
@@ -1,30 +0,0 @@
|
|
|
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
|
-
* Serializes async WS frame decodes so results apply in arrival order.
|
|
12
|
-
* In `'latest'` mode a backlog (e.g. queued behind a main-thread stall)
|
|
13
|
-
* collapses to its newest frame instead of replaying every stale decode.
|
|
14
|
-
* Decode failures are reported to `onError` and never break the chain.
|
|
15
|
-
*/
|
|
16
|
-
export declare class DecodeChain {
|
|
17
|
-
private readonly mode;
|
|
18
|
-
private readonly onError;
|
|
19
|
-
private tail;
|
|
20
|
-
private queued;
|
|
21
|
-
constructor(mode: DecodeChainMode, onError: (error: unknown) => void);
|
|
22
|
-
push(decode: () => Promise<void>): void;
|
|
23
|
-
/**
|
|
24
|
-
* Detach on connection teardown: drops the queued latest-mode decode and
|
|
25
|
-
* starts subsequent pushes on a fresh chain. A decode already in flight
|
|
26
|
-
* still settles.
|
|
27
|
-
*/
|
|
28
|
-
reset(): void;
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=decodeChain.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"decodeChain.d.ts","sourceRoot":"","sources":["../../../src/websocket/decodeChain.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEhD;;;;;GAKG;AACH,qBAAa,WAAW;IAKpB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAL1B,OAAO,CAAC,IAAI,CAAmC;IAC/C,OAAO,CAAC,MAAM,CAAmC;gBAG9B,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI;IAGpD,IAAI,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAmBvC;;;;OAIG;IACH,KAAK,IAAI,IAAI;CAId"}
|
|
@@ -1,54 +0,0 @@
|
|
|
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
|
-
}
|