@nktkas/hyperliquid 0.19.1 → 0.20.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/CONTRIBUTING.md +4 -2
- package/README.md +36 -35
- package/esm/_dnt.polyfills.d.ts +20 -0
- package/esm/_dnt.polyfills.d.ts.map +1 -0
- package/esm/_dnt.polyfills.js +12 -0
- package/esm/mod.d.ts +3 -0
- package/esm/mod.d.ts.map +1 -1
- package/esm/mod.js +2 -0
- package/esm/src/base.d.ts +1 -47
- package/esm/src/base.d.ts.map +1 -1
- package/esm/src/base.js +1 -8
- package/esm/src/clients/event.d.ts +6 -4
- package/esm/src/clients/event.d.ts.map +1 -1
- package/esm/src/clients/event.js +58 -77
- package/esm/src/clients/public.d.ts +26 -5
- package/esm/src/clients/public.d.ts.map +1 -1
- package/esm/src/clients/public.js +29 -41
- package/esm/src/clients/wallet.d.ts +200 -26
- package/esm/src/clients/wallet.d.ts.map +1 -1
- package/esm/src/clients/wallet.js +306 -284
- package/esm/src/signing.d.ts +80 -5
- package/esm/src/signing.d.ts.map +1 -1
- package/esm/src/signing.js +96 -7
- package/esm/src/transports/base.d.ts +49 -0
- package/esm/src/transports/base.d.ts.map +1 -0
- package/esm/src/transports/base.js +8 -0
- package/esm/src/transports/http/http_transport.d.ts +8 -5
- package/esm/src/transports/http/http_transport.d.ts.map +1 -1
- package/esm/src/transports/http/http_transport.js +15 -62
- package/esm/src/transports/websocket/_hyperliquid_event_target.d.ts +36 -39
- package/esm/src/transports/websocket/_hyperliquid_event_target.d.ts.map +1 -1
- package/esm/src/transports/websocket/_reconnecting_websocket.d.ts +18 -25
- package/esm/src/transports/websocket/_reconnecting_websocket.d.ts.map +1 -1
- package/esm/src/transports/websocket/_reconnecting_websocket.js +80 -179
- package/{script/src/transports/websocket/_websocket_request_dispatcher.d.ts → esm/src/transports/websocket/_websocket_async_request.d.ts} +14 -18
- package/esm/src/transports/websocket/_websocket_async_request.d.ts.map +1 -0
- package/esm/src/transports/websocket/{_websocket_request_dispatcher.js → _websocket_async_request.js} +42 -75
- package/esm/src/transports/websocket/websocket_transport.d.ts +38 -28
- package/esm/src/transports/websocket/websocket_transport.d.ts.map +1 -1
- package/esm/src/transports/websocket/websocket_transport.js +61 -76
- package/esm/src/types/exchange/requests.d.ts +278 -66
- package/esm/src/types/exchange/requests.d.ts.map +1 -1
- package/esm/src/types/info/assets.d.ts +0 -48
- package/esm/src/types/info/assets.d.ts.map +1 -1
- package/esm/src/types/info/markets.d.ts +52 -0
- package/esm/src/types/info/markets.d.ts.map +1 -0
- package/esm/src/types/info/markets.js +1 -0
- package/esm/src/types/info/orders.d.ts +1 -1
- package/esm/src/types/info/orders.d.ts.map +1 -1
- package/esm/src/types/info/requests.d.ts +14 -5
- package/esm/src/types/info/requests.d.ts.map +1 -1
- package/esm/src/types/mod.d.ts +4 -0
- package/esm/src/types/mod.d.ts.map +1 -1
- package/esm/src/types/mod.js +3 -1
- package/esm/src/types/subscriptions/requests.d.ts +2 -0
- package/esm/src/types/subscriptions/requests.d.ts.map +1 -1
- package/package.json +12 -9
- package/script/_dnt.polyfills.d.ts +20 -0
- package/script/_dnt.polyfills.d.ts.map +1 -0
- package/script/_dnt.polyfills.js +23 -0
- package/script/mod.d.ts +3 -0
- package/script/mod.d.ts.map +1 -1
- package/script/mod.js +3 -1
- package/script/src/base.d.ts +1 -47
- package/script/src/base.d.ts.map +1 -1
- package/script/src/base.js +2 -10
- package/script/src/clients/event.d.ts +6 -4
- package/script/src/clients/event.d.ts.map +1 -1
- package/script/src/clients/event.js +58 -77
- package/script/src/clients/public.d.ts +26 -5
- package/script/src/clients/public.d.ts.map +1 -1
- package/script/src/clients/public.js +29 -41
- package/script/src/clients/wallet.d.ts +200 -26
- package/script/src/clients/wallet.d.ts.map +1 -1
- package/script/src/clients/wallet.js +305 -283
- package/script/src/signing.d.ts +80 -5
- package/script/src/signing.d.ts.map +1 -1
- package/script/src/signing.js +148 -58
- package/script/src/transports/base.d.ts +49 -0
- package/script/src/transports/base.d.ts.map +1 -0
- package/script/src/transports/base.js +22 -0
- package/script/src/transports/http/http_transport.d.ts +8 -5
- package/script/src/transports/http/http_transport.d.ts.map +1 -1
- package/script/src/transports/http/http_transport.js +16 -63
- package/script/src/transports/websocket/_hyperliquid_event_target.d.ts +36 -39
- package/script/src/transports/websocket/_hyperliquid_event_target.d.ts.map +1 -1
- package/script/src/transports/websocket/_reconnecting_websocket.d.ts +18 -25
- package/script/src/transports/websocket/_reconnecting_websocket.d.ts.map +1 -1
- package/script/src/transports/websocket/_reconnecting_websocket.js +81 -180
- package/{esm/src/transports/websocket/_websocket_request_dispatcher.d.ts → script/src/transports/websocket/_websocket_async_request.d.ts} +14 -18
- package/script/src/transports/websocket/_websocket_async_request.d.ts.map +1 -0
- package/script/src/transports/websocket/{_websocket_request_dispatcher.js → _websocket_async_request.js} +45 -78
- package/script/src/transports/websocket/websocket_transport.d.ts +38 -28
- package/script/src/transports/websocket/websocket_transport.d.ts.map +1 -1
- package/script/src/transports/websocket/websocket_transport.js +63 -78
- package/script/src/types/exchange/requests.d.ts +278 -66
- package/script/src/types/exchange/requests.d.ts.map +1 -1
- package/script/src/types/info/assets.d.ts +0 -48
- package/script/src/types/info/assets.d.ts.map +1 -1
- package/script/src/types/info/markets.d.ts +52 -0
- package/script/src/types/info/markets.d.ts.map +1 -0
- package/script/{deps/jsr.io/@noble/hashes/1.8.0/src/crypto.js → src/types/info/markets.js} +0 -2
- package/script/src/types/info/orders.d.ts +1 -1
- package/script/src/types/info/orders.d.ts.map +1 -1
- package/script/src/types/info/requests.d.ts +14 -5
- package/script/src/types/info/requests.d.ts.map +1 -1
- package/script/src/types/mod.d.ts +4 -0
- package/script/src/types/mod.d.ts.map +1 -1
- package/script/src/types/mod.js +25 -22
- package/script/src/types/subscriptions/requests.d.ts +2 -0
- package/script/src/types/subscriptions/requests.d.ts.map +1 -1
- package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.d.ts +0 -55
- package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.d.ts.map +0 -1
- package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.js +0 -66
- package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/crypto.d.ts +0 -2
- package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/crypto.d.ts.map +0 -1
- package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/crypto.js +0 -1
- package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.d.ts +0 -53
- package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.d.ts.map +0 -1
- package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.js +0 -294
- package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/utils.d.ts +0 -161
- package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/utils.d.ts.map +0 -1
- package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/utils.js +0 -280
- package/esm/src/transports/websocket/_websocket_request_dispatcher.d.ts.map +0 -1
- package/script/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.d.ts +0 -55
- package/script/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.d.ts.map +0 -1
- package/script/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.js +0 -99
- package/script/deps/jsr.io/@noble/hashes/1.8.0/src/crypto.d.ts +0 -2
- package/script/deps/jsr.io/@noble/hashes/1.8.0/src/crypto.d.ts.map +0 -1
- package/script/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.d.ts +0 -53
- package/script/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.d.ts.map +0 -1
- package/script/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.js +0 -309
- package/script/deps/jsr.io/@noble/hashes/1.8.0/src/utils.d.ts +0 -161
- package/script/deps/jsr.io/@noble/hashes/1.8.0/src/utils.d.ts.map +0 -1
- package/script/deps/jsr.io/@noble/hashes/1.8.0/src/utils.js +0 -322
- package/script/src/transports/websocket/_websocket_request_dispatcher.d.ts.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TransportError } from "
|
|
1
|
+
import { TransportError } from "../base.js";
|
|
2
2
|
import type { HyperliquidEventTarget } from "./_hyperliquid_event_target.js";
|
|
3
3
|
/**
|
|
4
4
|
* Error thrown when a WebSocket request fails:
|
|
@@ -12,31 +12,27 @@ export declare class WebSocketRequestError extends TransportError {
|
|
|
12
12
|
* Manages WebSocket requests to the Hyperliquid API.
|
|
13
13
|
* Handles request creation, sending, and mapping responses to their corresponding requests.
|
|
14
14
|
*/
|
|
15
|
-
export declare class
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
export declare class WebSocketAsyncRequest {
|
|
16
|
+
protected socket: WebSocket;
|
|
17
|
+
protected lastId: number;
|
|
18
|
+
protected queue: Map<number | string, {
|
|
19
|
+
resolve: (value?: any) => void;
|
|
20
|
+
reject: (reason?: any) => void;
|
|
21
|
+
}>;
|
|
22
|
+
lastRequestTime: number;
|
|
21
23
|
/**
|
|
22
|
-
* Creates a new WebSocket request
|
|
24
|
+
* Creates a new WebSocket async request handler.
|
|
23
25
|
* @param socket - WebSocket connection instance for sending requests to the Hyperliquid WebSocket API
|
|
24
26
|
* @param hlEvents - Used to recognize Hyperliquid responses and match them with sent requests
|
|
25
27
|
*/
|
|
26
28
|
constructor(socket: WebSocket, hlEvents: HyperliquidEventTarget);
|
|
27
29
|
/**
|
|
28
30
|
* Sends a request to the Hyperliquid API.
|
|
29
|
-
* @param method - The method of websocket request.
|
|
30
|
-
* @param payload - The payload to send with the request.
|
|
31
|
-
* @param signal - An optional abort signal.
|
|
32
31
|
* @returns A promise that resolves with the parsed JSON response body.
|
|
33
32
|
*/
|
|
34
|
-
request(method: "
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
* @param value - A request object.
|
|
38
|
-
* @returns A stringified request.
|
|
39
|
-
*/
|
|
33
|
+
request(method: "ping", signal?: AbortSignal): Promise<void>;
|
|
34
|
+
request<T>(method: "post" | "subscribe" | "unsubscribe", payload: unknown, signal?: AbortSignal): Promise<T>;
|
|
35
|
+
/** Normalizes an object and then converts it to a string. */
|
|
40
36
|
static requestToId(value: unknown): string;
|
|
41
37
|
}
|
|
42
|
-
//# sourceMappingURL=
|
|
38
|
+
//# sourceMappingURL=_websocket_async_request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_websocket_async_request.d.ts","sourceRoot":"","sources":["../../../../src/src/transports/websocket/_websocket_async_request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAiB7E;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,cAAc;gBACzC,OAAO,EAAE,MAAM;CAI9B;AAED;;;GAGG;AACH,qBAAa,qBAAqB;IAkBlB,SAAS,CAAC,MAAM,EAAE,SAAS;IAjBvC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAK;IAC7B,SAAS,CAAC,KAAK,EAAE,GAAG,CAChB,MAAM,GAAG,MAAM,EACf;QAEI,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;QAE/B,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;KAClC,CACJ,CAAa;IACd,eAAe,EAAE,MAAM,CAAK;IAE5B;;;;OAIG;gBACmB,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,sBAAsB;IA2DzE;;;OAGG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAC5D,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;IA2ClH,6DAA6D;IAC7D,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM;CAK7C"}
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
if (v !== undefined) module.exports = v;
|
|
5
5
|
}
|
|
6
6
|
else if (typeof define === "function" && define.amd) {
|
|
7
|
-
define(["require", "exports", "
|
|
7
|
+
define(["require", "exports", "../base.js"], factory);
|
|
8
8
|
}
|
|
9
9
|
})(function (require, exports) {
|
|
10
10
|
"use strict";
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
13
|
-
const base_js_1 = require("
|
|
12
|
+
exports.WebSocketAsyncRequest = exports.WebSocketRequestError = void 0;
|
|
13
|
+
const base_js_1 = require("../base.js");
|
|
14
14
|
/**
|
|
15
15
|
* Error thrown when a WebSocket request fails:
|
|
16
16
|
* - When the WebSocket connection is closed
|
|
@@ -27,44 +27,32 @@
|
|
|
27
27
|
* Manages WebSocket requests to the Hyperliquid API.
|
|
28
28
|
* Handles request creation, sending, and mapping responses to their corresponding requests.
|
|
29
29
|
*/
|
|
30
|
-
class
|
|
30
|
+
class WebSocketAsyncRequest {
|
|
31
|
+
socket;
|
|
32
|
+
lastId = 0;
|
|
33
|
+
queue = new Map();
|
|
34
|
+
lastRequestTime = 0;
|
|
31
35
|
/**
|
|
32
|
-
* Creates a new WebSocket request
|
|
36
|
+
* Creates a new WebSocket async request handler.
|
|
33
37
|
* @param socket - WebSocket connection instance for sending requests to the Hyperliquid WebSocket API
|
|
34
38
|
* @param hlEvents - Used to recognize Hyperliquid responses and match them with sent requests
|
|
35
39
|
*/
|
|
36
40
|
constructor(socket, hlEvents) {
|
|
37
|
-
|
|
38
|
-
enumerable: true,
|
|
39
|
-
configurable: true,
|
|
40
|
-
writable: true,
|
|
41
|
-
value: socket
|
|
42
|
-
});
|
|
43
|
-
/** Last used post request ID */
|
|
44
|
-
Object.defineProperty(this, "lastId", {
|
|
45
|
-
enumerable: true,
|
|
46
|
-
configurable: true,
|
|
47
|
-
writable: true,
|
|
48
|
-
value: 0
|
|
49
|
-
});
|
|
50
|
-
/** Map of pending requests waiting for responses */
|
|
51
|
-
Object.defineProperty(this, "pending", {
|
|
52
|
-
enumerable: true,
|
|
53
|
-
configurable: true,
|
|
54
|
-
writable: true,
|
|
55
|
-
value: new Map()
|
|
56
|
-
});
|
|
41
|
+
this.socket = socket;
|
|
57
42
|
// Monitor responses and match the pending request
|
|
58
43
|
hlEvents.addEventListener("subscriptionResponse", (event) => {
|
|
59
44
|
// Use a stringified request as an id
|
|
60
|
-
const id =
|
|
61
|
-
this.
|
|
45
|
+
const id = WebSocketAsyncRequest.requestToId(event.detail.subscription);
|
|
46
|
+
this.queue.get(id)?.resolve(event.detail);
|
|
62
47
|
});
|
|
63
48
|
hlEvents.addEventListener("post", (event) => {
|
|
64
49
|
const data = event.detail.response.type === "info"
|
|
65
50
|
? event.detail.response.payload.data
|
|
66
51
|
: event.detail.response.payload;
|
|
67
|
-
this.
|
|
52
|
+
this.queue.get(event.detail.id)?.resolve(data);
|
|
53
|
+
});
|
|
54
|
+
hlEvents.addEventListener("pong", () => {
|
|
55
|
+
this.queue.get("ping")?.resolve();
|
|
68
56
|
});
|
|
69
57
|
hlEvents.addEventListener("error", (event) => {
|
|
70
58
|
try {
|
|
@@ -74,19 +62,19 @@
|
|
|
74
62
|
const parsedRequest = JSON.parse(request);
|
|
75
63
|
if ("id" in parsedRequest && typeof parsedRequest.id === "number") {
|
|
76
64
|
// If a post request was sent, it is possible to get the id from the request
|
|
77
|
-
this.
|
|
65
|
+
this.queue.get(parsedRequest.id)?.reject(new WebSocketRequestError(`Cannot complete WebSocket request: ${event.detail}`));
|
|
78
66
|
}
|
|
79
67
|
else if ("subscription" in parsedRequest &&
|
|
80
68
|
typeof parsedRequest.subscription === "object" &&
|
|
81
69
|
parsedRequest.subscription !== null) {
|
|
82
70
|
// If a subscription/unsubscribe request was sent, use the request as an id
|
|
83
|
-
const id =
|
|
84
|
-
this.
|
|
71
|
+
const id = WebSocketAsyncRequest.requestToId(parsedRequest.subscription);
|
|
72
|
+
this.queue.get(id)?.reject(new WebSocketRequestError(`Cannot complete WebSocket request: ${event.detail}`));
|
|
85
73
|
}
|
|
86
74
|
else {
|
|
87
75
|
// If the request is not recognized, use the parsed request as an id
|
|
88
|
-
const id =
|
|
89
|
-
this.
|
|
76
|
+
const id = WebSocketAsyncRequest.requestToId(parsedRequest);
|
|
77
|
+
this.queue.get(id)?.reject(new WebSocketRequestError(`Cannot complete WebSocket request: ${event.detail}`));
|
|
90
78
|
}
|
|
91
79
|
}
|
|
92
80
|
}
|
|
@@ -96,68 +84,55 @@
|
|
|
96
84
|
});
|
|
97
85
|
// Throws all pending requests if the connection is dropped
|
|
98
86
|
socket.addEventListener("close", () => {
|
|
99
|
-
this.
|
|
87
|
+
this.queue.forEach(({ reject }) => {
|
|
100
88
|
reject(new WebSocketRequestError("Cannot complete WebSocket request: connection is closed"));
|
|
101
89
|
});
|
|
102
|
-
this.
|
|
90
|
+
this.queue.clear();
|
|
103
91
|
});
|
|
104
92
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
* @param payload - The payload to send with the request.
|
|
109
|
-
* @param signal - An optional abort signal.
|
|
110
|
-
* @returns A promise that resolves with the parsed JSON response body.
|
|
111
|
-
*/
|
|
112
|
-
async request(method, payload, signal) {
|
|
93
|
+
async request(method, payload_or_signal, maybeSignal) {
|
|
94
|
+
const payload = payload_or_signal instanceof AbortSignal ? undefined : payload_or_signal;
|
|
95
|
+
const signal = payload_or_signal instanceof AbortSignal ? payload_or_signal : maybeSignal;
|
|
113
96
|
// Reject the request if the signal is aborted
|
|
114
97
|
if (signal?.aborted)
|
|
115
98
|
return Promise.reject(signal.reason);
|
|
116
|
-
// Create a request
|
|
99
|
+
// Create a request
|
|
117
100
|
let id;
|
|
118
101
|
let request;
|
|
119
102
|
if (method === "post") {
|
|
120
103
|
id = ++this.lastId;
|
|
121
104
|
request = { method, id, request: payload };
|
|
122
105
|
}
|
|
106
|
+
else if (method === "ping") {
|
|
107
|
+
id = "ping";
|
|
108
|
+
request = { method };
|
|
109
|
+
}
|
|
123
110
|
else {
|
|
124
|
-
id =
|
|
111
|
+
id = WebSocketAsyncRequest.requestToId(payload);
|
|
125
112
|
request = { method, subscription: payload };
|
|
126
113
|
}
|
|
127
114
|
// Send the request
|
|
128
115
|
this.socket.send(JSON.stringify(request));
|
|
116
|
+
this.lastRequestTime = Date.now();
|
|
129
117
|
// Wait for a response
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
this.pending.set(id, { resolve, reject });
|
|
137
|
-
}).finally(() => {
|
|
138
|
-
// Remove the abort listener when the promise is settled
|
|
118
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
119
|
+
this.queue.set(id, { resolve, reject });
|
|
120
|
+
const onAbort = () => reject(signal?.reason);
|
|
121
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
122
|
+
return await promise.finally(() => {
|
|
123
|
+
this.queue.delete(id);
|
|
139
124
|
signal?.removeEventListener("abort", onAbort);
|
|
140
|
-
// Clean up the pending list
|
|
141
|
-
this.pending.delete(id);
|
|
142
125
|
});
|
|
143
126
|
}
|
|
144
|
-
/**
|
|
145
|
-
* Normalizes a request object to an ID.
|
|
146
|
-
* @param value - A request object.
|
|
147
|
-
* @returns A stringified request.
|
|
148
|
-
*/
|
|
127
|
+
/** Normalizes an object and then converts it to a string. */
|
|
149
128
|
static requestToId(value) {
|
|
150
129
|
const lowerHex = containsUppercaseHex(value) ? deepLowerHex(value) : value;
|
|
151
130
|
const sorted = deepSortKeys(lowerHex);
|
|
152
|
-
return JSON.stringify(sorted);
|
|
131
|
+
return JSON.stringify(sorted); // Also removes undefined
|
|
153
132
|
}
|
|
154
133
|
}
|
|
155
|
-
exports.
|
|
156
|
-
/**
|
|
157
|
-
* Deeply converts hexadecimal strings in an object/array to lowercase.
|
|
158
|
-
* @param obj - The object/array to convert hexadecimal strings to lowercase.
|
|
159
|
-
* @returns A new object/array with hexadecimal strings converted to lowercase.
|
|
160
|
-
*/
|
|
134
|
+
exports.WebSocketAsyncRequest = WebSocketAsyncRequest;
|
|
135
|
+
/** Deeply converts hexadecimal strings in an object/array to lowercase. */
|
|
161
136
|
function deepLowerHex(obj) {
|
|
162
137
|
if (typeof obj === "string") {
|
|
163
138
|
return /^(0X[0-9a-fA-F]*|0x[0-9a-fA-F]*[A-F][0-9a-fA-F]*)$/.test(obj) ? obj.toLowerCase() : obj;
|
|
@@ -175,20 +150,12 @@
|
|
|
175
150
|
}
|
|
176
151
|
return obj;
|
|
177
152
|
}
|
|
178
|
-
/**
|
|
179
|
-
* Check if an object contains uppercase hexadecimal strings.
|
|
180
|
-
* @param obj - The object to check.
|
|
181
|
-
* @returns True if the object contains uppercase hexadecimal strings, false otherwise.
|
|
182
|
-
*/
|
|
153
|
+
/** Check if an object contains uppercase hexadecimal strings. */
|
|
183
154
|
function containsUppercaseHex(obj) {
|
|
184
155
|
const str = JSON.stringify(obj);
|
|
185
156
|
return /0X[0-9a-fA-F]*|0x[0-9a-fA-F]*[A-F][0-9a-fA-F]*/.test(str);
|
|
186
157
|
}
|
|
187
|
-
/**
|
|
188
|
-
* Deeply sort the keys of an object.
|
|
189
|
-
* @param obj - An object to sort the keys of.
|
|
190
|
-
* @returns A new object with sorted keys.
|
|
191
|
-
*/
|
|
158
|
+
/** Deeply sort the keys of an object. */
|
|
192
159
|
function deepSortKeys(obj) {
|
|
193
160
|
if (typeof obj !== "object" || obj === null) {
|
|
194
161
|
return obj;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type MessageBufferStrategy, ReconnectingWebSocket, ReconnectingWebSocketError, type ReconnectingWebSocketOptions } from "./_reconnecting_websocket.js";
|
|
2
2
|
import { HyperliquidEventTarget } from "./_hyperliquid_event_target.js";
|
|
3
|
-
import {
|
|
4
|
-
import type { IRequestTransport, ISubscriptionTransport, Subscription } from "
|
|
3
|
+
import { WebSocketAsyncRequest, WebSocketRequestError } from "./_websocket_async_request.js";
|
|
4
|
+
import type { IRequestTransport, ISubscriptionTransport, Subscription } from "../base.js";
|
|
5
5
|
export { WebSocketRequestError };
|
|
6
6
|
export { type MessageBufferStrategy, ReconnectingWebSocketError, type ReconnectingWebSocketOptions };
|
|
7
7
|
/** Configuration options for the WebSocket transport layer. */
|
|
@@ -10,44 +10,42 @@ export interface WebSocketTransportOptions {
|
|
|
10
10
|
* The WebSocket URL.
|
|
11
11
|
* - Mainnet:
|
|
12
12
|
* - API: `wss://api.hyperliquid.xyz/ws`
|
|
13
|
-
* -
|
|
13
|
+
* - Explorer: `wss://rpc.hyperliquid.xyz/ws`
|
|
14
14
|
* - Testnet:
|
|
15
15
|
* - API: `wss://api.hyperliquid-testnet.xyz/ws`
|
|
16
|
-
* -
|
|
16
|
+
* - Explorer: `wss://rpc.hyperliquid-testnet.xyz/ws`
|
|
17
17
|
* @defaultValue `wss://api.hyperliquid.xyz/ws`
|
|
18
18
|
*/
|
|
19
19
|
url?: string | URL;
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* Timeout for requests in ms.
|
|
22
22
|
* Set to `null` to disable.
|
|
23
23
|
* @defaultValue `10_000`
|
|
24
24
|
*/
|
|
25
25
|
timeout?: number | null;
|
|
26
|
-
/**
|
|
27
|
-
* Keep-alive configuration.
|
|
28
|
-
* @defaultValue `{ interval: 20_000 }`
|
|
29
|
-
*/
|
|
26
|
+
/** Keep-alive configuration. */
|
|
30
27
|
keepAlive?: {
|
|
31
28
|
/**
|
|
32
|
-
*
|
|
29
|
+
* Interval between sending ping messages in ms.
|
|
33
30
|
* Set to `null` to disable.
|
|
34
|
-
* @defaultValue `
|
|
31
|
+
* @defaultValue `30_000`
|
|
35
32
|
*/
|
|
36
33
|
interval?: number | null;
|
|
34
|
+
/**
|
|
35
|
+
* Timeout for the ping request in ms.
|
|
36
|
+
* Set to `null` to disable.
|
|
37
|
+
* same as {@link timeout} for requests.
|
|
38
|
+
*/
|
|
39
|
+
timeout?: number | null;
|
|
37
40
|
};
|
|
38
|
-
/**
|
|
39
|
-
* Reconnection policy configuration for closed connections.
|
|
40
|
-
*/
|
|
41
|
+
/** Reconnection policy configuration for closed connections. */
|
|
41
42
|
reconnect?: ReconnectingWebSocketOptions;
|
|
42
43
|
}
|
|
43
44
|
/** WebSocket implementation of the REST and Subscription transport interfaces. */
|
|
44
45
|
export declare class WebSocketTransport implements IRequestTransport, ISubscriptionTransport, AsyncDisposable {
|
|
45
|
-
|
|
46
|
-
protected _keepAliveTimer: number | null;
|
|
47
|
-
/** The WebSocket request dispatcher instance. */
|
|
48
|
-
protected _wsRequester: WebSocketRequestDispatcher;
|
|
49
|
-
/** The Hyperliquid event target instance. */
|
|
46
|
+
protected _wsRequester: WebSocketAsyncRequest;
|
|
50
47
|
protected _hlEvents: HyperliquidEventTarget;
|
|
48
|
+
protected _keepAliveTimeout: ReturnType<typeof setTimeout> | null;
|
|
51
49
|
/**
|
|
52
50
|
* Map of active subscriptions.
|
|
53
51
|
* - Key: Unique subscription identifier based on payload
|
|
@@ -63,13 +61,18 @@ export declare class WebSocketTransport implements IRequestTransport, ISubscript
|
|
|
63
61
|
* Set to `null` to disable.
|
|
64
62
|
*/
|
|
65
63
|
timeout: number | null;
|
|
66
|
-
/** Keep-alive configuration
|
|
64
|
+
/** Keep-alive configuration. */
|
|
67
65
|
readonly keepAlive: {
|
|
68
66
|
/**
|
|
69
|
-
*
|
|
67
|
+
* Interval between sending ping messages in ms.
|
|
70
68
|
* Set to `null` to disable.
|
|
71
69
|
*/
|
|
72
70
|
readonly interval: number | null;
|
|
71
|
+
/**
|
|
72
|
+
* Timeout for the ping request in ms.
|
|
73
|
+
* Set to `null` to disable.
|
|
74
|
+
*/
|
|
75
|
+
timeout?: number | null;
|
|
73
76
|
};
|
|
74
77
|
/** The WebSocket that is used for communication. */
|
|
75
78
|
readonly socket: ReconnectingWebSocket;
|
|
@@ -80,23 +83,29 @@ export declare class WebSocketTransport implements IRequestTransport, ISubscript
|
|
|
80
83
|
constructor(options?: WebSocketTransportOptions);
|
|
81
84
|
/**
|
|
82
85
|
* Sends a request to the Hyperliquid API via WebSocket.
|
|
86
|
+
*
|
|
87
|
+
* Note: Explorer requests are not supported in the Hyperliquid WebSocket API.
|
|
88
|
+
*
|
|
83
89
|
* @param endpoint - The API endpoint to send the request to (`explorer` requests are not supported).
|
|
84
90
|
* @param payload - The payload to send with the request.
|
|
85
91
|
* @param signal - An optional abort signal.
|
|
86
92
|
* @returns A promise that resolves with parsed JSON response body.
|
|
87
93
|
* @throws {WebSocketRequestError} - An error that occurs when a WebSocket request fails.
|
|
88
|
-
* @note Explorer requests are not supported in the Hyperliquid WebSocket API.
|
|
89
94
|
*/
|
|
90
|
-
request(type: "info" | "exchange" | "explorer", payload: unknown, signal?: AbortSignal): Promise<
|
|
95
|
+
request<T>(type: "info" | "exchange" | "explorer", payload: unknown, signal?: AbortSignal): Promise<T>;
|
|
91
96
|
/**
|
|
92
97
|
* Subscribes to a Hyperliquid event channel.
|
|
98
|
+
*
|
|
99
|
+
* Sends a subscription request to the server and listens for events.
|
|
100
|
+
*
|
|
93
101
|
* @param channel - The event channel to listen to.
|
|
94
102
|
* @param payload - A payload to send with the subscription request.
|
|
95
103
|
* @param listener - A function to call when the event is dispatched.
|
|
96
104
|
* @param signal - An optional abort signal for canceling the subscription request.
|
|
97
105
|
* @returns A promise that resolves with a {@link Subscription} object to manage the subscription lifecycle.
|
|
106
|
+
* @throws {WebSocketRequestError} - An error that occurs when a WebSocket request fails.
|
|
98
107
|
*/
|
|
99
|
-
subscribe(channel: string, payload: unknown, listener: (data: CustomEvent) => void, signal?: AbortSignal): Promise<Subscription>;
|
|
108
|
+
subscribe<T>(channel: string, payload: unknown, listener: (data: CustomEvent<T>) => void, signal?: AbortSignal): Promise<Subscription>;
|
|
100
109
|
/**
|
|
101
110
|
* Waits until the WebSocket connection is ready.
|
|
102
111
|
* @param signal - An optional abort signal.
|
|
@@ -109,12 +118,13 @@ export declare class WebSocketTransport implements IRequestTransport, ISubscript
|
|
|
109
118
|
* @returns A promise that resolves when the connection is fully closed.
|
|
110
119
|
*/
|
|
111
120
|
close(signal?: AbortSignal): Promise<void>;
|
|
121
|
+
/** Combines the provided abort signal with the timeout signal. */
|
|
122
|
+
protected _getCombinedTimeoutSignal(signal?: AbortSignal): AbortSignal | undefined;
|
|
112
123
|
/**
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* @returns A combined abort signal or undefined.
|
|
124
|
+
* Initiate background keep the connection alive.
|
|
125
|
+
* Sends ping only when needed.
|
|
116
126
|
*/
|
|
117
|
-
protected
|
|
127
|
+
protected _keepAlive(): void;
|
|
118
128
|
[Symbol.asyncDispose](): Promise<void>;
|
|
119
129
|
}
|
|
120
130
|
//# sourceMappingURL=websocket_transport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket_transport.d.ts","sourceRoot":"","sources":["../../../../src/src/transports/websocket/websocket_transport.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,qBAAqB,EAC1B,qBAAqB,EACrB,0BAA0B,EAC1B,KAAK,4BAA4B,EACpC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"websocket_transport.d.ts","sourceRoot":"","sources":["../../../../src/src/transports/websocket/websocket_transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
if (v !== undefined) module.exports = v;
|
|
5
5
|
}
|
|
6
6
|
else if (typeof define === "function" && define.amd) {
|
|
7
|
-
define(["require", "exports", "./_reconnecting_websocket.js", "./_hyperliquid_event_target.js", "./
|
|
7
|
+
define(["require", "exports", "./_reconnecting_websocket.js", "./_hyperliquid_event_target.js", "./_websocket_async_request.js"], factory);
|
|
8
8
|
}
|
|
9
9
|
})(function (require, exports) {
|
|
10
10
|
"use strict";
|
|
@@ -13,93 +13,52 @@
|
|
|
13
13
|
const _reconnecting_websocket_js_1 = require("./_reconnecting_websocket.js");
|
|
14
14
|
Object.defineProperty(exports, "ReconnectingWebSocketError", { enumerable: true, get: function () { return _reconnecting_websocket_js_1.ReconnectingWebSocketError; } });
|
|
15
15
|
const _hyperliquid_event_target_js_1 = require("./_hyperliquid_event_target.js");
|
|
16
|
-
const
|
|
17
|
-
Object.defineProperty(exports, "WebSocketRequestError", { enumerable: true, get: function () { return
|
|
16
|
+
const _websocket_async_request_js_1 = require("./_websocket_async_request.js");
|
|
17
|
+
Object.defineProperty(exports, "WebSocketRequestError", { enumerable: true, get: function () { return _websocket_async_request_js_1.WebSocketRequestError; } });
|
|
18
18
|
/** WebSocket implementation of the REST and Subscription transport interfaces. */
|
|
19
19
|
class WebSocketTransport {
|
|
20
|
+
_wsRequester;
|
|
21
|
+
_hlEvents;
|
|
22
|
+
_keepAliveTimeout = null;
|
|
23
|
+
/**
|
|
24
|
+
* Map of active subscriptions.
|
|
25
|
+
* - Key: Unique subscription identifier based on payload
|
|
26
|
+
* - Value: Subscription info containing the subscription request promise
|
|
27
|
+
* and a map of listeners to their metadata (channel + unsubscribe function).
|
|
28
|
+
*/
|
|
29
|
+
_subscriptions = new Map();
|
|
30
|
+
/**
|
|
31
|
+
* Request timeout in ms.
|
|
32
|
+
* Set to `null` to disable.
|
|
33
|
+
*/
|
|
34
|
+
timeout;
|
|
35
|
+
/** Keep-alive configuration. */
|
|
36
|
+
keepAlive;
|
|
37
|
+
/** The WebSocket that is used for communication. */
|
|
38
|
+
socket;
|
|
20
39
|
/**
|
|
21
40
|
* Creates a new WebSocket transport instance.
|
|
22
41
|
* @param options - Configuration options for the WebSocket transport layer.
|
|
23
42
|
*/
|
|
24
43
|
constructor(options) {
|
|
25
|
-
/** The interval timer ID for keep-alive messages. */
|
|
26
|
-
Object.defineProperty(this, "_keepAliveTimer", {
|
|
27
|
-
enumerable: true,
|
|
28
|
-
configurable: true,
|
|
29
|
-
writable: true,
|
|
30
|
-
value: null
|
|
31
|
-
});
|
|
32
|
-
/** The WebSocket request dispatcher instance. */
|
|
33
|
-
Object.defineProperty(this, "_wsRequester", {
|
|
34
|
-
enumerable: true,
|
|
35
|
-
configurable: true,
|
|
36
|
-
writable: true,
|
|
37
|
-
value: void 0
|
|
38
|
-
});
|
|
39
|
-
/** The Hyperliquid event target instance. */
|
|
40
|
-
Object.defineProperty(this, "_hlEvents", {
|
|
41
|
-
enumerable: true,
|
|
42
|
-
configurable: true,
|
|
43
|
-
writable: true,
|
|
44
|
-
value: void 0
|
|
45
|
-
});
|
|
46
|
-
/**
|
|
47
|
-
* Map of active subscriptions.
|
|
48
|
-
* - Key: Unique subscription identifier based on payload
|
|
49
|
-
* - Value: Subscription info containing the subscription request promise
|
|
50
|
-
* and a map of listeners to their metadata (channel + unsubscribe function).
|
|
51
|
-
*/
|
|
52
|
-
Object.defineProperty(this, "_subscriptions", {
|
|
53
|
-
enumerable: true,
|
|
54
|
-
configurable: true,
|
|
55
|
-
writable: true,
|
|
56
|
-
value: new Map()
|
|
57
|
-
});
|
|
58
|
-
/**
|
|
59
|
-
* Request timeout in ms.
|
|
60
|
-
* Set to `null` to disable.
|
|
61
|
-
*/
|
|
62
|
-
Object.defineProperty(this, "timeout", {
|
|
63
|
-
enumerable: true,
|
|
64
|
-
configurable: true,
|
|
65
|
-
writable: true,
|
|
66
|
-
value: void 0
|
|
67
|
-
});
|
|
68
|
-
/** Keep-alive configuration settings. */
|
|
69
|
-
Object.defineProperty(this, "keepAlive", {
|
|
70
|
-
enumerable: true,
|
|
71
|
-
configurable: true,
|
|
72
|
-
writable: true,
|
|
73
|
-
value: void 0
|
|
74
|
-
});
|
|
75
|
-
/** The WebSocket that is used for communication. */
|
|
76
|
-
Object.defineProperty(this, "socket", {
|
|
77
|
-
enumerable: true,
|
|
78
|
-
configurable: true,
|
|
79
|
-
writable: true,
|
|
80
|
-
value: void 0
|
|
81
|
-
});
|
|
82
44
|
this.socket = new _reconnecting_websocket_js_1.ReconnectingWebSocket(options?.url ?? "wss://api.hyperliquid.xyz/ws", undefined, options?.reconnect);
|
|
83
45
|
this._hlEvents = new _hyperliquid_event_target_js_1.HyperliquidEventTarget(this.socket);
|
|
84
|
-
this._wsRequester = new
|
|
46
|
+
this._wsRequester = new _websocket_async_request_js_1.WebSocketAsyncRequest(this.socket, this._hlEvents);
|
|
85
47
|
this.timeout = options?.timeout === undefined ? 10_000 : options.timeout;
|
|
86
48
|
this.keepAlive = {
|
|
87
|
-
interval: options?.keepAlive?.interval === undefined ?
|
|
49
|
+
interval: options?.keepAlive?.interval === undefined ? 30_000 : options.keepAlive?.interval,
|
|
50
|
+
timeout: options?.keepAlive?.timeout === undefined ? this.timeout : options.keepAlive?.timeout,
|
|
88
51
|
};
|
|
89
52
|
// Initialize listeners
|
|
90
53
|
this.socket.addEventListener("open", () => {
|
|
91
|
-
// Start keep-alive
|
|
92
|
-
|
|
93
|
-
this._keepAliveTimer = setInterval(() => {
|
|
94
|
-
this.socket.send(JSON.stringify({ method: "ping" }));
|
|
95
|
-
}, this.keepAlive.interval);
|
|
96
|
-
}
|
|
54
|
+
// Start keep-alive handler
|
|
55
|
+
this._keepAlive();
|
|
97
56
|
});
|
|
98
57
|
this.socket.addEventListener("close", () => {
|
|
99
58
|
// Clear keep-alive timer
|
|
100
|
-
if (this.
|
|
101
|
-
|
|
102
|
-
this.
|
|
59
|
+
if (this._keepAliveTimeout !== null) {
|
|
60
|
+
clearTimeout(this._keepAliveTimeout);
|
|
61
|
+
this._keepAliveTimeout = null;
|
|
103
62
|
}
|
|
104
63
|
// Clear all subscriptions
|
|
105
64
|
for (const subscriptionInfo of this._subscriptions.values()) {
|
|
@@ -111,12 +70,14 @@
|
|
|
111
70
|
}
|
|
112
71
|
/**
|
|
113
72
|
* Sends a request to the Hyperliquid API via WebSocket.
|
|
73
|
+
*
|
|
74
|
+
* Note: Explorer requests are not supported in the Hyperliquid WebSocket API.
|
|
75
|
+
*
|
|
114
76
|
* @param endpoint - The API endpoint to send the request to (`explorer` requests are not supported).
|
|
115
77
|
* @param payload - The payload to send with the request.
|
|
116
78
|
* @param signal - An optional abort signal.
|
|
117
79
|
* @returns A promise that resolves with parsed JSON response body.
|
|
118
80
|
* @throws {WebSocketRequestError} - An error that occurs when a WebSocket request fails.
|
|
119
|
-
* @note Explorer requests are not supported in the Hyperliquid WebSocket API.
|
|
120
81
|
*/
|
|
121
82
|
request(type, payload, signal) {
|
|
122
83
|
const combinedTimeoutSignal = this._getCombinedTimeoutSignal(signal);
|
|
@@ -127,15 +88,19 @@
|
|
|
127
88
|
}
|
|
128
89
|
/**
|
|
129
90
|
* Subscribes to a Hyperliquid event channel.
|
|
91
|
+
*
|
|
92
|
+
* Sends a subscription request to the server and listens for events.
|
|
93
|
+
*
|
|
130
94
|
* @param channel - The event channel to listen to.
|
|
131
95
|
* @param payload - A payload to send with the subscription request.
|
|
132
96
|
* @param listener - A function to call when the event is dispatched.
|
|
133
97
|
* @param signal - An optional abort signal for canceling the subscription request.
|
|
134
98
|
* @returns A promise that resolves with a {@link Subscription} object to manage the subscription lifecycle.
|
|
99
|
+
* @throws {WebSocketRequestError} - An error that occurs when a WebSocket request fails.
|
|
135
100
|
*/
|
|
136
101
|
async subscribe(channel, payload, listener, signal) {
|
|
137
102
|
// Create a unique identifier for the subscription
|
|
138
|
-
const id =
|
|
103
|
+
const id = _websocket_async_request_js_1.WebSocketAsyncRequest.requestToId(payload);
|
|
139
104
|
// Initialize new subscription, if it doesn't exist
|
|
140
105
|
let subscription = this._subscriptions.get(id);
|
|
141
106
|
if (!subscription) {
|
|
@@ -236,11 +201,7 @@
|
|
|
236
201
|
this.socket.close();
|
|
237
202
|
});
|
|
238
203
|
}
|
|
239
|
-
/**
|
|
240
|
-
* Combines the provided abort signal with the timeout signal.
|
|
241
|
-
* @param signal An optional abort signal.
|
|
242
|
-
* @returns A combined abort signal or undefined.
|
|
243
|
-
*/
|
|
204
|
+
/** Combines the provided abort signal with the timeout signal. */
|
|
244
205
|
_getCombinedTimeoutSignal(signal) {
|
|
245
206
|
const timeoutSignal = this.timeout ? AbortSignal.timeout(this.timeout) : undefined;
|
|
246
207
|
const combinedSignal = signal && timeoutSignal
|
|
@@ -248,6 +209,30 @@
|
|
|
248
209
|
: signal ?? timeoutSignal;
|
|
249
210
|
return combinedSignal;
|
|
250
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Initiate background keep the connection alive.
|
|
214
|
+
* Sends ping only when needed.
|
|
215
|
+
*/
|
|
216
|
+
_keepAlive() {
|
|
217
|
+
if (this.keepAlive.interval === null || this._keepAliveTimeout)
|
|
218
|
+
return;
|
|
219
|
+
const tick = async () => {
|
|
220
|
+
if (this.socket.readyState !== _reconnecting_websocket_js_1.ReconnectingWebSocket.OPEN || !this._keepAliveTimeout)
|
|
221
|
+
return;
|
|
222
|
+
// Check if the last request was sent more than the keep-alive interval ago
|
|
223
|
+
if (Date.now() - this._wsRequester.lastRequestTime >= this.keepAlive.interval) {
|
|
224
|
+
const timeoutSignal = this.keepAlive.timeout ? AbortSignal.timeout(this.keepAlive.timeout) : undefined;
|
|
225
|
+
await this._wsRequester.request("ping", timeoutSignal)
|
|
226
|
+
.catch(() => undefined); // Ignore errors
|
|
227
|
+
}
|
|
228
|
+
// Schedule the next ping
|
|
229
|
+
if (this.socket.readyState === _reconnecting_websocket_js_1.ReconnectingWebSocket.OPEN && this._keepAliveTimeout) {
|
|
230
|
+
const nextDelay = this.keepAlive.interval - (Date.now() - this._wsRequester.lastRequestTime);
|
|
231
|
+
this._keepAliveTimeout = setTimeout(tick, nextDelay);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
this._keepAliveTimeout = setTimeout(tick, this.keepAlive.interval);
|
|
235
|
+
}
|
|
251
236
|
async [Symbol.asyncDispose]() {
|
|
252
237
|
await this.close();
|
|
253
238
|
}
|