@nktkas/hyperliquid 0.15.1 → 0.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/esm/src/signing.d.ts +3 -3
- package/esm/src/signing.d.ts.map +1 -1
- package/esm/src/transports/http/http_transport.d.ts +2 -6
- package/esm/src/transports/http/http_transport.d.ts.map +1 -1
- package/esm/src/transports/http/http_transport.js +2 -4
- package/esm/src/transports/websocket/_reconnecting_websocket.d.ts +22 -42
- package/esm/src/transports/websocket/_reconnecting_websocket.d.ts.map +1 -1
- package/esm/src/transports/websocket/_reconnecting_websocket.js +133 -82
- package/esm/src/transports/websocket/_websocket_request_dispatcher.d.ts +6 -11
- package/esm/src/transports/websocket/_websocket_request_dispatcher.d.ts.map +1 -1
- package/esm/src/transports/websocket/_websocket_request_dispatcher.js +8 -12
- package/esm/src/transports/websocket/websocket_transport.d.ts +2 -4
- package/esm/src/transports/websocket/websocket_transport.d.ts.map +1 -1
- package/esm/src/transports/websocket/websocket_transport.js +14 -12
- package/package.json +1 -1
- package/script/src/signing.d.ts +3 -3
- package/script/src/signing.d.ts.map +1 -1
- package/script/src/transports/http/http_transport.d.ts +2 -6
- package/script/src/transports/http/http_transport.d.ts.map +1 -1
- package/script/src/transports/http/http_transport.js +2 -4
- package/script/src/transports/websocket/_reconnecting_websocket.d.ts +22 -42
- package/script/src/transports/websocket/_reconnecting_websocket.d.ts.map +1 -1
- package/script/src/transports/websocket/_reconnecting_websocket.js +133 -82
- package/script/src/transports/websocket/_websocket_request_dispatcher.d.ts +6 -11
- package/script/src/transports/websocket/_websocket_request_dispatcher.d.ts.map +1 -1
- package/script/src/transports/websocket/_websocket_request_dispatcher.js +8 -12
- package/script/src/transports/websocket/websocket_transport.d.ts +2 -4
- package/script/src/transports/websocket/websocket_transport.d.ts.map +1 -1
- package/script/src/transports/websocket/websocket_transport.js +14 -12
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@ import * as hl from "https://esm.sh/jsr/@nktkas/hyperliquid"
|
|
|
49
49
|
First, choose and configure your transport layer (more details in the [API Reference](#transports)):
|
|
50
50
|
|
|
51
51
|
```typescript
|
|
52
|
-
import * as hl from "@nktkas/hyperliquid";
|
|
52
|
+
import * as hl from "@nktkas/hyperliquid"; // ESM & Common.js
|
|
53
53
|
|
|
54
54
|
// HTTP Transport
|
|
55
55
|
const httpTransport = new hl.HttpTransport(); // Accepts optional parameters (e.g. url, timeout, fetchOptions)
|
|
@@ -65,7 +65,7 @@ Next, initialize a client with the transport layer (more details in the [API Ref
|
|
|
65
65
|
#### Create PublicClient
|
|
66
66
|
|
|
67
67
|
```typescript
|
|
68
|
-
import * as hl from "@nktkas/hyperliquid";
|
|
68
|
+
import * as hl from "@nktkas/hyperliquid"; // ESM & Common.js
|
|
69
69
|
|
|
70
70
|
const transport = new hl.HttpTransport(); // or WebSocketTransport
|
|
71
71
|
const client = new hl.PublicClient({ transport });
|
|
@@ -74,7 +74,7 @@ const client = new hl.PublicClient({ transport });
|
|
|
74
74
|
#### Create WalletClient
|
|
75
75
|
|
|
76
76
|
```typescript
|
|
77
|
-
import * as hl from "@nktkas/hyperliquid";
|
|
77
|
+
import * as hl from "@nktkas/hyperliquid"; // ESM & Common.js
|
|
78
78
|
import { createWalletClient, custom } from "viem";
|
|
79
79
|
import { privateKeyToAccount } from "viem/accounts";
|
|
80
80
|
import { ethers } from "ethers";
|
|
@@ -101,7 +101,7 @@ const windowMetamaskClient = new hl.WalletClient({ wallet: window.ethereum, tran
|
|
|
101
101
|
#### Create EventClient
|
|
102
102
|
|
|
103
103
|
```typescript
|
|
104
|
-
import * as hl from "@nktkas/hyperliquid";
|
|
104
|
+
import * as hl from "@nktkas/hyperliquid"; // ESM & Common.js
|
|
105
105
|
|
|
106
106
|
const transport = new hl.WebSocketTransport(); // Only WebSocketTransport is supported
|
|
107
107
|
const client = new hl.EventClient({ transport });
|
|
@@ -116,7 +116,7 @@ Finally, use client methods to interact with the Hyperliquid API (more details i
|
|
|
116
116
|
```typescript
|
|
117
117
|
import * as hl from "@nktkas/hyperliquid";
|
|
118
118
|
|
|
119
|
-
const transport = new hl.HttpTransport();
|
|
119
|
+
const transport = new hl.HttpTransport();
|
|
120
120
|
const client = new hl.PublicClient({ transport });
|
|
121
121
|
|
|
122
122
|
// L2 Book
|
package/esm/src/signing.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { type ValueType } from "../deps/jsr.io/@std/msgpack/1.0.3/encode.js";
|
|
1
|
+
import { type ValueMap, type ValueType } from "../deps/jsr.io/@std/msgpack/1.0.3/encode.js";
|
|
2
2
|
import type { Hex } from "./base.js";
|
|
3
|
-
export type { Hex }
|
|
4
|
-
export type { ValueMap, ValueType }
|
|
3
|
+
export type { Hex };
|
|
4
|
+
export type { ValueMap, ValueType };
|
|
5
5
|
/** Abstract interface for a [viem wallet](https://viem.sh/docs/clients/wallet). */
|
|
6
6
|
export interface AbstractViemWalletClient {
|
|
7
7
|
signTypedData(params: {
|
package/esm/src/signing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../../src/src/signing.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,KAAK,SAAS,EAAE,MAAM,6CAA6C,CAAC;
|
|
1
|
+
{"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../../src/src/signing.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,9 +15,7 @@ export declare class HttpRequestError extends TransportError {
|
|
|
15
15
|
*/
|
|
16
16
|
constructor(response: Response, responseBody?: string | undefined);
|
|
17
17
|
}
|
|
18
|
-
/**
|
|
19
|
-
* Configuration options for the HTTP transport layer.
|
|
20
|
-
*/
|
|
18
|
+
/** Configuration options for the HTTP transport layer. */
|
|
21
19
|
export interface HttpTransportOptions {
|
|
22
20
|
/**
|
|
23
21
|
* Base URL for API endpoints.
|
|
@@ -47,9 +45,7 @@ export interface HttpTransportOptions {
|
|
|
47
45
|
*/
|
|
48
46
|
onResponse?: (response: Response) => MaybePromise<Response | void | null | undefined>;
|
|
49
47
|
}
|
|
50
|
-
/**
|
|
51
|
-
* HTTP implementation of the REST transport interface.
|
|
52
|
-
*/
|
|
48
|
+
/** HTTP implementation of the REST transport interface. */
|
|
53
49
|
export declare class HttpTransport implements IRequestTransport, HttpTransportOptions {
|
|
54
50
|
url: string | URL;
|
|
55
51
|
timeout: number | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http_transport.d.ts","sourceRoot":"","sources":["../../../../src/src/transports/http/http_transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEvE,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,cAAc;IAM7B,QAAQ,EAAE,QAAQ;IAAS,YAAY,CAAC,EAAE,MAAM;IALnE;;;;OAIG;gBACgB,QAAQ,EAAE,QAAQ,EAAS,YAAY,CAAC,EAAE,MAAM,YAAA;CAOtE;AAED
|
|
1
|
+
{"version":3,"file":"http_transport.d.ts","sourceRoot":"","sources":["../../../../src/src/transports/http/http_transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEvE,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,cAAc;IAM7B,QAAQ,EAAE,QAAQ;IAAS,YAAY,CAAC,EAAE,MAAM;IALnE;;;;OAIG;gBACgB,QAAQ,EAAE,QAAQ,EAAS,YAAY,CAAC,EAAE,MAAM,YAAA;CAOtE;AAED,0DAA0D;AAC1D,MAAM,WAAW,oBAAoB;IACjC;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IAEnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB,2IAA2I;IAC3I,YAAY,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC;IAEpD;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,YAAY,CAAC,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAElF;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,YAAY,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CACzF;AAED,2DAA2D;AAC3D,qBAAa,aAAc,YAAW,iBAAiB,EAAE,oBAAoB;IACzE,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC;IACnD,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,YAAY,CAAC,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAClF,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,YAAY,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAEtF;;;OAGG;gBACS,OAAO,CAAC,EAAE,oBAAoB;IAQ1C;;;;;;;;OAQG;IACG,OAAO,CACT,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU,EAC1C,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,OAAO,CAAC;CAqDtB"}
|
|
@@ -30,9 +30,7 @@ export class HttpRequestError extends TransportError {
|
|
|
30
30
|
this.name = "HttpRequestError";
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
-
/**
|
|
34
|
-
* HTTP implementation of the REST transport interface.
|
|
35
|
-
*/
|
|
33
|
+
/** HTTP implementation of the REST transport interface. */
|
|
36
34
|
export class HttpTransport {
|
|
37
35
|
/**
|
|
38
36
|
* Creates a new HTTP transport instance.
|
|
@@ -89,7 +87,7 @@ export class HttpTransport {
|
|
|
89
87
|
const url = new URL(endpoint, this.url);
|
|
90
88
|
// FIXME: Temporary hack: replace `api.hyperliquid-testnet.xyz/explorer` with `rpc.hyperliquid-testnet.xyz/explorer`
|
|
91
89
|
// until the new rpc url becomes the standard for mainnet.
|
|
92
|
-
// Maybe after that should split the url property into api and rpc variants.
|
|
90
|
+
// TODO: Maybe after that should split the url property into api and rpc variants.
|
|
93
91
|
if (url.hostname === "api.hyperliquid-testnet.xyz" && url.pathname === "/explorer") {
|
|
94
92
|
url.hostname = "rpc.hyperliquid-testnet.xyz";
|
|
95
93
|
}
|
|
@@ -61,25 +61,28 @@ export declare class ReconnectingWebSocketError extends TransportError {
|
|
|
61
61
|
* Fully compatible with standard WebSocket API.
|
|
62
62
|
*/
|
|
63
63
|
export declare class ReconnectingWebSocket implements WebSocket {
|
|
64
|
-
/** Controller for handling connection termination */
|
|
65
|
-
|
|
66
|
-
/** WebSocket protocols */
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
|
|
64
|
+
/** Controller for handling connection termination. */
|
|
65
|
+
private _terminationController;
|
|
66
|
+
/** WebSocket protocols defined in constructor. */
|
|
67
|
+
private _protocols?;
|
|
68
|
+
/** Non-permanent original instance of WebSocket. */
|
|
69
|
+
private _socket;
|
|
70
70
|
/** Current number of reconnection attempts */
|
|
71
71
|
protected _reconnectCount: number;
|
|
72
|
-
/**
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
72
|
+
/** The array of registered event listeners to recover from reconnection. */
|
|
73
|
+
private _eventListeners;
|
|
74
|
+
/** WebSocket event handlers for reconnection. */
|
|
75
|
+
private _onclose;
|
|
76
|
+
/** WebSocket event handlers for reconnection. */
|
|
77
|
+
private _onerror;
|
|
78
|
+
/** WebSocket event handlers for reconnection. */
|
|
79
|
+
private _onmessage;
|
|
80
|
+
/** WebSocket event handlers for reconnection. */
|
|
81
|
+
private _onopen;
|
|
82
|
+
/** Configuration options for WebSocket reconnection. */
|
|
80
83
|
reconnectOptions: Required<ReconnectingWebSocketOptions>;
|
|
81
|
-
/**
|
|
82
|
-
|
|
84
|
+
/** The signal that is aborted when the connection is permanently closed. */
|
|
85
|
+
terminationSignal: AbortSignal;
|
|
83
86
|
/**
|
|
84
87
|
* Creates a new reconnecting WebSocket.
|
|
85
88
|
* @param url - The WebSocket URL to connect to.
|
|
@@ -87,36 +90,13 @@ export declare class ReconnectingWebSocket implements WebSocket {
|
|
|
87
90
|
* @param options - The configuration options.
|
|
88
91
|
*/
|
|
89
92
|
constructor(url: string | URL, protocols?: string | string[], options?: ReconnectingWebSocketOptions);
|
|
90
|
-
/**
|
|
91
|
-
* Creates a WebSocket connection with timeout.
|
|
92
|
-
* @param url - The WebSocket URL to connect to.
|
|
93
|
-
* @param protocols - The WebSocket protocols to use.
|
|
94
|
-
* @param timeout - The connection timeout in ms.
|
|
95
|
-
* @returns A new WebSocket instance.
|
|
96
|
-
*/
|
|
97
|
-
protected _connectWithTimeout(url: string | URL, protocols: string | string[] | undefined, timeout: number): WebSocket;
|
|
98
93
|
/** Initializes the internal event listeners for the WebSocket. */
|
|
99
|
-
|
|
94
|
+
private _initEventListeners;
|
|
100
95
|
/**
|
|
101
96
|
* Clean up internal resources.
|
|
102
97
|
* @param reason - The reason for cleanup.
|
|
103
98
|
*/
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Check if two event listeners are the same (just like EventTarget).
|
|
107
|
-
* @param a - First event listener configuration.
|
|
108
|
-
* @param b - Second event listener configuration.
|
|
109
|
-
* @returns True if the listeners match.
|
|
110
|
-
*/
|
|
111
|
-
protected _isListenerMatch(a: {
|
|
112
|
-
type: string;
|
|
113
|
-
listener: EventListenerOrEventListenerObject;
|
|
114
|
-
options?: boolean | AddEventListenerOptions;
|
|
115
|
-
}, b: {
|
|
116
|
-
type: string;
|
|
117
|
-
listener: EventListenerOrEventListenerObject;
|
|
118
|
-
options?: boolean | AddEventListenerOptions;
|
|
119
|
-
}): boolean;
|
|
99
|
+
private _cleanup;
|
|
120
100
|
get url(): string;
|
|
121
101
|
get readyState(): number;
|
|
122
102
|
get bufferedAmount(): number;
|
|
@@ -141,7 +121,7 @@ export declare class ReconnectingWebSocket implements WebSocket {
|
|
|
141
121
|
get onopen(): ((this: WebSocket, ev: Event) => any) | null;
|
|
142
122
|
set onopen(value: ((this: WebSocket, ev: Event) => any) | null);
|
|
143
123
|
/**
|
|
144
|
-
* @param permanently - If true
|
|
124
|
+
* @param permanently - If `true`, the connection will be permanently closed. Default is `true`.
|
|
145
125
|
*/
|
|
146
126
|
close(code?: number, reason?: string, permanently?: boolean): void;
|
|
147
127
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_reconnecting_websocket.d.ts","sourceRoot":"","sources":["../../../../src/src/transports/websocket/_reconnecting_websocket.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC,6DAA6D;AAC7D,MAAM,WAAW,4BAA4B;IACzC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAElC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IAEvE;;;;;OAKG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,YAAY,CAAC,OAAO,CAAC,CAAC;IAE/D;;;OAGG;IACH,aAAa,CAAC,EAAE,qBAAqB,CAAC;CACzC;AAED,yCAAyC;AACzC,MAAM,WAAW,qBAAqB;IAClC,kCAAkC;IAClC,QAAQ,EAAE,CAAC,MAAM,GAAG,eAAe,GAAG,IAAI,GAAG,eAAe,CAAC,EAAE,CAAC;IAChE;;;OAGG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,GAAG,eAAe,GAAG,IAAI,CAAC;IAEpE;;;OAGG;IACH,KAAK,IAAI,CAAC,MAAM,GAAG,eAAe,GAAG,IAAI,GAAG,eAAe,CAAC,GAAG,SAAS,CAAC;IAEzE,mCAAmC;IACnC,KAAK,IAAI,IAAI,CAAC;CACjB;AAiBD,qDAAqD;AACrD,qBAAa,0BAA2B,SAAQ,cAAc;IAE/C,IAAI,EACL,4BAA4B,GAC5B,8BAA8B,GAC9B,sBAAsB,GACtB,eAAe;IACd,aAAa,CAAC,EAAE,OAAO;gBALvB,IAAI,EACL,4BAA4B,GAC5B,8BAA8B,GAC9B,sBAAsB,GACtB,eAAe,EACd,aAAa,CAAC,EAAE,OAAO,YAAA;CAKrC;AAED;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,SAAS;IACnD,
|
|
1
|
+
{"version":3,"file":"_reconnecting_websocket.d.ts","sourceRoot":"","sources":["../../../../src/src/transports/websocket/_reconnecting_websocket.ts"],"names":[],"mappings":"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"}
|
|
@@ -51,21 +51,21 @@ export class ReconnectingWebSocket {
|
|
|
51
51
|
* @param options - The configuration options.
|
|
52
52
|
*/
|
|
53
53
|
constructor(url, protocols, options) {
|
|
54
|
-
/** Controller for handling connection termination */
|
|
54
|
+
/** Controller for handling connection termination. */
|
|
55
55
|
Object.defineProperty(this, "_terminationController", {
|
|
56
56
|
enumerable: true,
|
|
57
57
|
configurable: true,
|
|
58
58
|
writable: true,
|
|
59
59
|
value: new AbortController()
|
|
60
60
|
});
|
|
61
|
-
/** WebSocket protocols */
|
|
61
|
+
/** WebSocket protocols defined in constructor. */
|
|
62
62
|
Object.defineProperty(this, "_protocols", {
|
|
63
63
|
enumerable: true,
|
|
64
64
|
configurable: true,
|
|
65
65
|
writable: true,
|
|
66
66
|
value: void 0
|
|
67
67
|
});
|
|
68
|
-
/**
|
|
68
|
+
/** Non-permanent original instance of WebSocket. */
|
|
69
69
|
Object.defineProperty(this, "_socket", {
|
|
70
70
|
enumerable: true,
|
|
71
71
|
configurable: true,
|
|
@@ -79,21 +79,49 @@ export class ReconnectingWebSocket {
|
|
|
79
79
|
writable: true,
|
|
80
80
|
value: 0
|
|
81
81
|
});
|
|
82
|
-
/**
|
|
82
|
+
/** The array of registered event listeners to recover from reconnection. */
|
|
83
83
|
Object.defineProperty(this, "_eventListeners", {
|
|
84
84
|
enumerable: true,
|
|
85
85
|
configurable: true,
|
|
86
86
|
writable: true,
|
|
87
87
|
value: []
|
|
88
88
|
});
|
|
89
|
-
/**
|
|
89
|
+
/** WebSocket event handlers for reconnection. */
|
|
90
|
+
Object.defineProperty(this, "_onclose", {
|
|
91
|
+
enumerable: true,
|
|
92
|
+
configurable: true,
|
|
93
|
+
writable: true,
|
|
94
|
+
value: void 0
|
|
95
|
+
});
|
|
96
|
+
/** WebSocket event handlers for reconnection. */
|
|
97
|
+
Object.defineProperty(this, "_onerror", {
|
|
98
|
+
enumerable: true,
|
|
99
|
+
configurable: true,
|
|
100
|
+
writable: true,
|
|
101
|
+
value: void 0
|
|
102
|
+
});
|
|
103
|
+
/** WebSocket event handlers for reconnection. */
|
|
104
|
+
Object.defineProperty(this, "_onmessage", {
|
|
105
|
+
enumerable: true,
|
|
106
|
+
configurable: true,
|
|
107
|
+
writable: true,
|
|
108
|
+
value: void 0
|
|
109
|
+
});
|
|
110
|
+
/** WebSocket event handlers for reconnection. */
|
|
111
|
+
Object.defineProperty(this, "_onopen", {
|
|
112
|
+
enumerable: true,
|
|
113
|
+
configurable: true,
|
|
114
|
+
writable: true,
|
|
115
|
+
value: void 0
|
|
116
|
+
});
|
|
117
|
+
/** Configuration options for WebSocket reconnection. */
|
|
90
118
|
Object.defineProperty(this, "reconnectOptions", {
|
|
91
119
|
enumerable: true,
|
|
92
120
|
configurable: true,
|
|
93
121
|
writable: true,
|
|
94
122
|
value: void 0
|
|
95
123
|
});
|
|
96
|
-
/**
|
|
124
|
+
/** The signal that is aborted when the connection is permanently closed. */
|
|
97
125
|
Object.defineProperty(this, "terminationSignal", {
|
|
98
126
|
enumerable: true,
|
|
99
127
|
configurable: true,
|
|
@@ -124,6 +152,7 @@ export class ReconnectingWebSocket {
|
|
|
124
152
|
writable: true,
|
|
125
153
|
value: WebSocket.OPEN
|
|
126
154
|
});
|
|
155
|
+
// Set the default options
|
|
127
156
|
this.reconnectOptions = {
|
|
128
157
|
maxRetries: options?.maxRetries ?? 3,
|
|
129
158
|
connectionTimeout: options?.connectionTimeout === undefined ? 10_000 : options.connectionTimeout,
|
|
@@ -132,42 +161,19 @@ export class ReconnectingWebSocket {
|
|
|
132
161
|
messageBuffer: options?.messageBuffer ?? new FIFOMessageBuffer(),
|
|
133
162
|
};
|
|
134
163
|
this._protocols = protocols;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
164
|
+
// Create the WebSocket instance
|
|
165
|
+
this._socket = createWebSocketWithTimeout(url, this._protocols, this.reconnectOptions.connectionTimeout);
|
|
166
|
+
// Initialize the reconnection event listeners
|
|
138
167
|
this._initEventListeners();
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
* @param timeout - The connection timeout in ms.
|
|
145
|
-
* @returns A new WebSocket instance.
|
|
146
|
-
*/
|
|
147
|
-
_connectWithTimeout(url, protocols, timeout) {
|
|
148
|
-
const socket = new WebSocket(url, protocols);
|
|
149
|
-
const timeoutId = setTimeout(() => {
|
|
150
|
-
socket.removeEventListener("open", openHandler);
|
|
151
|
-
socket.removeEventListener("close", closeHandler);
|
|
152
|
-
socket.close(3008, "Timeout"); // https://www.iana.org/assignments/websocket/websocket.xml#close-code-number
|
|
153
|
-
}, timeout);
|
|
154
|
-
const openHandler = () => {
|
|
155
|
-
socket.removeEventListener("close", closeHandler);
|
|
156
|
-
clearTimeout(timeoutId);
|
|
157
|
-
};
|
|
158
|
-
const closeHandler = () => {
|
|
159
|
-
socket.removeEventListener("open", openHandler);
|
|
160
|
-
clearTimeout(timeoutId);
|
|
161
|
-
};
|
|
162
|
-
socket.addEventListener("open", openHandler, { once: true });
|
|
163
|
-
socket.addEventListener("close", closeHandler, { once: true });
|
|
164
|
-
return socket;
|
|
168
|
+
// Store the original event listeners for reconnection
|
|
169
|
+
this._onclose = this._socket.onclose;
|
|
170
|
+
this._onerror = this._socket.onerror;
|
|
171
|
+
this._onmessage = this._socket.onmessage;
|
|
172
|
+
this._onopen = this._socket.onopen;
|
|
165
173
|
}
|
|
166
174
|
/** Initializes the internal event listeners for the WebSocket. */
|
|
167
175
|
_initEventListeners() {
|
|
168
176
|
this._socket.addEventListener("open", () => {
|
|
169
|
-
// Reset reconnection count
|
|
170
|
-
this._reconnectCount = 0;
|
|
171
177
|
// Send all buffered messages
|
|
172
178
|
let message;
|
|
173
179
|
while ((message = this.reconnectOptions.messageBuffer.shift()) !== undefined) {
|
|
@@ -177,7 +183,7 @@ export class ReconnectingWebSocket {
|
|
|
177
183
|
this._socket.addEventListener("close", async (event) => {
|
|
178
184
|
try {
|
|
179
185
|
// If the termination signal is already aborted, do not attempt to reconnect
|
|
180
|
-
if (this.
|
|
186
|
+
if (this._terminationController.signal.aborted)
|
|
181
187
|
return;
|
|
182
188
|
// Check if reconnection should be attempted
|
|
183
189
|
if (++this._reconnectCount > this.reconnectOptions.maxRetries) {
|
|
@@ -185,7 +191,7 @@ export class ReconnectingWebSocket {
|
|
|
185
191
|
return;
|
|
186
192
|
}
|
|
187
193
|
const userDecision = await this.reconnectOptions.shouldReconnect(event);
|
|
188
|
-
if (this.
|
|
194
|
+
if (this._terminationController.signal.aborted)
|
|
189
195
|
return; // Check again after the await
|
|
190
196
|
if (!userDecision) {
|
|
191
197
|
this._cleanup(new ReconnectingWebSocketError("RECONNECTION_STOPPED_BY_USER"));
|
|
@@ -195,18 +201,20 @@ export class ReconnectingWebSocket {
|
|
|
195
201
|
const delay = typeof this.reconnectOptions.connectionDelay === "number"
|
|
196
202
|
? this.reconnectOptions.connectionDelay
|
|
197
203
|
: await this.reconnectOptions.connectionDelay(this._reconnectCount);
|
|
198
|
-
if (this.
|
|
204
|
+
if (this._terminationController.signal.aborted)
|
|
199
205
|
return; // Check again after the await
|
|
200
|
-
await sleep(delay, this.
|
|
201
|
-
//
|
|
202
|
-
this._socket = this.reconnectOptions.connectionTimeout
|
|
203
|
-
? this._connectWithTimeout(this.url, this._protocols, this.reconnectOptions.connectionTimeout)
|
|
204
|
-
: new WebSocket(this.url, this._protocols);
|
|
206
|
+
await sleep(delay, this._terminationController.signal);
|
|
207
|
+
// Create a new WebSocket instance
|
|
208
|
+
this._socket = createWebSocketWithTimeout(this.url, this._protocols, this.reconnectOptions.connectionTimeout);
|
|
205
209
|
// Reconnect all listeners
|
|
206
210
|
this._initEventListeners();
|
|
207
211
|
this._eventListeners.forEach(({ type, listenerProxy, options }) => {
|
|
208
212
|
this._socket.addEventListener(type, listenerProxy, options);
|
|
209
213
|
});
|
|
214
|
+
this._socket.onclose = this._onclose;
|
|
215
|
+
this._socket.onerror = this._onerror;
|
|
216
|
+
this._socket.onmessage = this._onmessage;
|
|
217
|
+
this._socket.onopen = this._onopen;
|
|
210
218
|
}
|
|
211
219
|
catch (error) {
|
|
212
220
|
this._cleanup(new ReconnectingWebSocketError("UNKNOWN_ERROR", error));
|
|
@@ -221,17 +229,7 @@ export class ReconnectingWebSocket {
|
|
|
221
229
|
this._terminationController.abort(reason);
|
|
222
230
|
this.reconnectOptions.messageBuffer.clear();
|
|
223
231
|
this._eventListeners = [];
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Check if two event listeners are the same (just like EventTarget).
|
|
227
|
-
* @param a - First event listener configuration.
|
|
228
|
-
* @param b - Second event listener configuration.
|
|
229
|
-
* @returns True if the listeners match.
|
|
230
|
-
*/
|
|
231
|
-
_isListenerMatch(a, b) {
|
|
232
|
-
const aCapture = Boolean(typeof a.options === "object" ? a.options.capture : a.options);
|
|
233
|
-
const bCapture = Boolean(typeof b.options === "object" ? b.options.capture : b.options);
|
|
234
|
-
return a.type === b.type && a.listener === b.listener && aCapture === bCapture;
|
|
232
|
+
this._socket.dispatchEvent(new CustomEvent("error", { detail: reason }));
|
|
235
233
|
}
|
|
236
234
|
// WebSocket property implementations
|
|
237
235
|
get url() {
|
|
@@ -260,38 +258,43 @@ export class ReconnectingWebSocket {
|
|
|
260
258
|
}
|
|
261
259
|
set onclose(value) {
|
|
262
260
|
this._socket.onclose = value;
|
|
261
|
+
this._onclose = value; // Store the listener for reconnection
|
|
263
262
|
}
|
|
264
263
|
get onerror() {
|
|
265
264
|
return this._socket.onerror;
|
|
266
265
|
}
|
|
267
266
|
set onerror(value) {
|
|
268
267
|
this._socket.onerror = value;
|
|
268
|
+
this._onerror = value; // Store the listener for reconnection
|
|
269
269
|
}
|
|
270
270
|
get onmessage() {
|
|
271
271
|
return this._socket.onmessage;
|
|
272
272
|
}
|
|
273
273
|
set onmessage(value) {
|
|
274
274
|
this._socket.onmessage = value;
|
|
275
|
+
this._onmessage = value; // Store the listener for reconnection
|
|
275
276
|
}
|
|
276
277
|
get onopen() {
|
|
277
278
|
return this._socket.onopen;
|
|
278
279
|
}
|
|
279
280
|
set onopen(value) {
|
|
280
281
|
this._socket.onopen = value;
|
|
282
|
+
this._onopen = value; // Store the listener for reconnection
|
|
281
283
|
}
|
|
282
284
|
/**
|
|
283
|
-
* @param permanently - If true
|
|
285
|
+
* @param permanently - If `true`, the connection will be permanently closed. Default is `true`.
|
|
284
286
|
*/
|
|
285
287
|
close(code, reason, permanently = true) {
|
|
286
|
-
if (permanently)
|
|
287
|
-
this._cleanup(new ReconnectingWebSocketError("USER_INITIATED_CLOSE"));
|
|
288
288
|
this._socket.close(code, reason);
|
|
289
|
+
if (permanently) {
|
|
290
|
+
this._cleanup(new ReconnectingWebSocketError("USER_INITIATED_CLOSE"));
|
|
291
|
+
}
|
|
289
292
|
}
|
|
290
293
|
/**
|
|
291
294
|
* @note If the connection is not open, the data will be buffered and sent when the connection is established.
|
|
292
295
|
*/
|
|
293
296
|
send(data) {
|
|
294
|
-
if (this._socket.readyState !== WebSocket.OPEN && !this.
|
|
297
|
+
if (this._socket.readyState !== WebSocket.OPEN && !this._terminationController.signal.aborted) {
|
|
295
298
|
this.reconnectOptions.messageBuffer.push(data);
|
|
296
299
|
}
|
|
297
300
|
else {
|
|
@@ -299,38 +302,57 @@ export class ReconnectingWebSocket {
|
|
|
299
302
|
}
|
|
300
303
|
}
|
|
301
304
|
addEventListener(type, listener, options) {
|
|
302
|
-
//
|
|
303
|
-
|
|
304
|
-
if (
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
305
|
+
// Wrap the listener to handle reconnection
|
|
306
|
+
let listenerProxy;
|
|
307
|
+
if (this._terminationController.signal.aborted) {
|
|
308
|
+
// If the connection is permanently closed, use the original listener
|
|
309
|
+
listenerProxy = listener;
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
// Check if the listener is already registered
|
|
313
|
+
const index = this._eventListeners.findIndex((e) => listenersMatch(e, { type, listener, options }));
|
|
314
|
+
if (index !== -1) {
|
|
315
|
+
// Use the existing listener proxy
|
|
316
|
+
listenerProxy = this._eventListeners[index].listenerProxy;
|
|
315
317
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
318
|
+
else {
|
|
319
|
+
// Wrap the original listener to follow the once option when reconnecting
|
|
320
|
+
listenerProxy = (event) => {
|
|
321
|
+
try {
|
|
322
|
+
if (typeof listener === "function") {
|
|
323
|
+
listener.call(this, event);
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
listener.handleEvent(event);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
finally {
|
|
330
|
+
if (typeof options === "object" && options.once === true) {
|
|
331
|
+
const index = this._eventListeners.findIndex((e) => listenersMatch(e, { type, listener, options }));
|
|
332
|
+
if (index !== -1) {
|
|
333
|
+
this._eventListeners.splice(index, 1);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
this._eventListeners.push({ type, listener, options, listenerProxy });
|
|
322
339
|
}
|
|
323
|
-
}
|
|
324
|
-
|
|
340
|
+
}
|
|
341
|
+
// Add the wrapped (or original) listener
|
|
325
342
|
this._socket.addEventListener(type, listenerProxy, options);
|
|
326
343
|
}
|
|
327
344
|
removeEventListener(type, listener, options) {
|
|
328
|
-
|
|
345
|
+
// Remove a wrapped listener, not an original listener
|
|
346
|
+
const index = this._eventListeners.findIndex((e) => listenersMatch(e, { type, listener, options }));
|
|
329
347
|
if (index !== -1) {
|
|
330
348
|
const { listenerProxy } = this._eventListeners[index];
|
|
331
349
|
this._socket.removeEventListener(type, listenerProxy, options);
|
|
332
350
|
this._eventListeners.splice(index, 1);
|
|
333
351
|
}
|
|
352
|
+
else {
|
|
353
|
+
// If the wrapped listener is not found, remove the original listener
|
|
354
|
+
this._socket.removeEventListener(type, listener, options);
|
|
355
|
+
}
|
|
334
356
|
}
|
|
335
357
|
dispatchEvent(event) {
|
|
336
358
|
return this._socket.dispatchEvent(event);
|
|
@@ -360,6 +382,35 @@ Object.defineProperty(ReconnectingWebSocket, "OPEN", {
|
|
|
360
382
|
writable: true,
|
|
361
383
|
value: WebSocket.OPEN
|
|
362
384
|
});
|
|
385
|
+
/** Creates a WebSocket with connection timeout. */
|
|
386
|
+
function createWebSocketWithTimeout(url, protocols, timeout) {
|
|
387
|
+
const socket = new WebSocket(url, protocols);
|
|
388
|
+
if (timeout === null || timeout === undefined)
|
|
389
|
+
return socket;
|
|
390
|
+
const timeoutId = setTimeout(() => {
|
|
391
|
+
socket.removeEventListener("open", openHandler);
|
|
392
|
+
socket.removeEventListener("close", closeHandler);
|
|
393
|
+
socket.close(3008, "Timeout"); // https://www.iana.org/assignments/websocket/websocket.xml#close-code-number
|
|
394
|
+
}, timeout);
|
|
395
|
+
const openHandler = () => {
|
|
396
|
+
socket.removeEventListener("close", closeHandler);
|
|
397
|
+
clearTimeout(timeoutId);
|
|
398
|
+
};
|
|
399
|
+
const closeHandler = () => {
|
|
400
|
+
socket.removeEventListener("open", openHandler);
|
|
401
|
+
clearTimeout(timeoutId);
|
|
402
|
+
};
|
|
403
|
+
socket.addEventListener("open", openHandler, { once: true });
|
|
404
|
+
socket.addEventListener("close", closeHandler, { once: true });
|
|
405
|
+
return socket;
|
|
406
|
+
}
|
|
407
|
+
/** Check if two event listeners are the same (just like EventTarget). */
|
|
408
|
+
function listenersMatch(a, b) {
|
|
409
|
+
// EventTarget only compares capture in options, even if one is an object and the other is boolean
|
|
410
|
+
const aCapture = Boolean(typeof a.options === "object" ? a.options.capture : a.options);
|
|
411
|
+
const bCapture = Boolean(typeof b.options === "object" ? b.options.capture : b.options);
|
|
412
|
+
return a.type === b.type && a.listener === b.listener && aCapture === bCapture;
|
|
413
|
+
}
|
|
363
414
|
/**
|
|
364
415
|
* Returns a promise that resolves after the specified number of ms,
|
|
365
416
|
* or rejects as soon as the given signal is aborted.
|
|
@@ -13,22 +13,17 @@ export declare class WebSocketRequestError extends TransportError {
|
|
|
13
13
|
* Handles request creation, sending, and mapping responses to their corresponding requests.
|
|
14
14
|
*/
|
|
15
15
|
export declare class WebSocketRequestDispatcher {
|
|
16
|
-
|
|
17
|
-
/** Last used request ID */
|
|
18
|
-
|
|
16
|
+
private socket;
|
|
17
|
+
/** Last used post request ID */
|
|
18
|
+
private lastId;
|
|
19
19
|
/** Map of pending requests waiting for responses */
|
|
20
|
-
|
|
21
|
-
resolve: (value: unknown) => void;
|
|
22
|
-
reject: (reason: unknown) => void;
|
|
23
|
-
}>;
|
|
20
|
+
private pending;
|
|
24
21
|
/**
|
|
25
22
|
* Creates a new WebSocket request dispatcher.
|
|
26
23
|
* @param socket - WebSocket connection instance for sending requests to the Hyperliquid WebSocket API
|
|
27
24
|
* @param hlEvents - Used to recognize Hyperliquid responses and match them with sent requests
|
|
28
25
|
*/
|
|
29
26
|
constructor(socket: WebSocket, hlEvents: HyperliquidEventTarget);
|
|
30
|
-
/** Gets the next request ID */
|
|
31
|
-
protected get nextId(): number;
|
|
32
27
|
/**
|
|
33
28
|
* Sends a request to the Hyperliquid API.
|
|
34
29
|
* @param method - The method of websocket request.
|
|
@@ -42,13 +37,13 @@ export declare class WebSocketRequestDispatcher {
|
|
|
42
37
|
* @param id - A request ID or a stringified request.
|
|
43
38
|
* @param value - A resolution value.
|
|
44
39
|
*/
|
|
45
|
-
|
|
40
|
+
private resolve;
|
|
46
41
|
/**
|
|
47
42
|
* Rejects a pending request.
|
|
48
43
|
* @param id - A request ID or a stringified request.
|
|
49
44
|
* @param reason - A rejection reason.
|
|
50
45
|
*/
|
|
51
|
-
|
|
46
|
+
private reject;
|
|
52
47
|
/**
|
|
53
48
|
* Normalizes a request object to an ID.
|
|
54
49
|
* @param value - A request object.
|