@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,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { MaybePromise } from "../../base.js";
|
|
2
|
+
import { TransportError } from "../base.js";
|
|
2
3
|
/** Configuration options for the `ReconnectingWebSocket`. */
|
|
3
4
|
export interface ReconnectingWebSocketOptions {
|
|
4
5
|
/**
|
|
@@ -34,46 +35,38 @@ export interface ReconnectingWebSocketOptions {
|
|
|
34
35
|
}
|
|
35
36
|
/** Message buffer strategy interface. */
|
|
36
37
|
export interface MessageBufferStrategy {
|
|
37
|
-
/** Array of buffered messages. */
|
|
38
|
-
messages: (string | ArrayBufferLike | Blob | ArrayBufferView)[];
|
|
39
|
-
/**
|
|
40
|
-
* Add a message to the buffer.
|
|
41
|
-
* @param data - The message to buffer.
|
|
42
|
-
*/
|
|
43
38
|
push(data: string | ArrayBufferLike | Blob | ArrayBufferView): void;
|
|
44
|
-
|
|
45
|
-
* Get and remove the next message from the buffer.
|
|
46
|
-
* @returns The next message or `undefined` if no more messages are available.
|
|
47
|
-
*/
|
|
48
|
-
shift(): (string | ArrayBufferLike | Blob | ArrayBufferView) | undefined;
|
|
49
|
-
/** Clear all buffered messages. */
|
|
50
|
-
clear(): void;
|
|
39
|
+
[Symbol.iterator](): Iterator<string | ArrayBufferLike | Blob | ArrayBufferView>;
|
|
51
40
|
}
|
|
52
41
|
/** Error thrown when reconnection problems occur. */
|
|
53
42
|
export declare class ReconnectingWebSocketError extends TransportError {
|
|
54
43
|
code: "RECONNECTION_LIMIT_REACHED" | "RECONNECTION_STOPPED_BY_USER" | "USER_INITIATED_CLOSE" | "UNKNOWN_ERROR";
|
|
55
|
-
|
|
56
|
-
constructor(code: "RECONNECTION_LIMIT_REACHED" | "RECONNECTION_STOPPED_BY_USER" | "USER_INITIATED_CLOSE" | "UNKNOWN_ERROR", originalError?: unknown);
|
|
44
|
+
constructor(code: "RECONNECTION_LIMIT_REACHED" | "RECONNECTION_STOPPED_BY_USER" | "USER_INITIATED_CLOSE" | "UNKNOWN_ERROR", cause?: unknown);
|
|
57
45
|
}
|
|
58
46
|
/**
|
|
59
47
|
* A WebSocket that automatically reconnects when disconnected.
|
|
60
48
|
* Fully compatible with standard WebSocket API.
|
|
61
49
|
*/
|
|
62
50
|
export declare class ReconnectingWebSocket implements WebSocket {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
51
|
+
protected _socket: WebSocket;
|
|
52
|
+
protected _protocols?: string | string[];
|
|
53
|
+
protected _listeners: {
|
|
54
|
+
type: string;
|
|
55
|
+
listener: EventListenerOrEventListenerObject;
|
|
56
|
+
options?: boolean | AddEventListenerOptions;
|
|
57
|
+
listenerProxy: EventListenerOrEventListenerObject;
|
|
58
|
+
}[];
|
|
59
|
+
protected _attempt: number;
|
|
67
60
|
reconnectOptions: Required<ReconnectingWebSocketOptions>;
|
|
68
61
|
readonly reconnectAbortController: AbortController;
|
|
69
62
|
constructor(url: string | URL, protocols?: string | string[], options?: ReconnectingWebSocketOptions);
|
|
70
|
-
|
|
63
|
+
protected _createSocket(url: string | URL, protocols?: string | string[]): WebSocket;
|
|
71
64
|
/** Initializes the internal event listeners for the socket. */
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
65
|
+
protected _setupEventListeners(): void;
|
|
66
|
+
protected _open: () => void;
|
|
67
|
+
protected _close: (event: CloseEvent) => Promise<void>;
|
|
75
68
|
/** Clean up internal resources. */
|
|
76
|
-
|
|
69
|
+
protected _cleanup(code: ConstructorParameters<typeof ReconnectingWebSocketError>[0], cause?: unknown): void;
|
|
77
70
|
get url(): string;
|
|
78
71
|
get readyState(): number;
|
|
79
72
|
get bufferedAmount(): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_reconnecting_websocket.d.ts","sourceRoot":"","sources":["../../../../src/src/transports/websocket/_reconnecting_websocket.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"_reconnecting_websocket.d.ts","sourceRoot":"","sources":["../../../../src/src/transports/websocket/_reconnecting_websocket.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,43 +1,26 @@
|
|
|
1
1
|
// deno-lint-ignore-file no-explicit-any
|
|
2
2
|
import { delay } from "../../../deps/jsr.io/@std/async/1.0.13/delay.js";
|
|
3
|
-
import { TransportError } from "
|
|
3
|
+
import { TransportError } from "../base.js";
|
|
4
4
|
/** Simple FIFO (First In, First Out) buffer implementation. */
|
|
5
5
|
class FIFOMessageBuffer {
|
|
6
|
-
|
|
7
|
-
Object.defineProperty(this, "messages", {
|
|
8
|
-
enumerable: true,
|
|
9
|
-
configurable: true,
|
|
10
|
-
writable: true,
|
|
11
|
-
value: []
|
|
12
|
-
});
|
|
13
|
-
}
|
|
6
|
+
queue = [];
|
|
14
7
|
push(data) {
|
|
15
|
-
this.
|
|
16
|
-
}
|
|
17
|
-
shift() {
|
|
18
|
-
return this.messages.shift();
|
|
8
|
+
this.queue.push(data);
|
|
19
9
|
}
|
|
20
|
-
|
|
21
|
-
this.
|
|
10
|
+
*[Symbol.iterator]() {
|
|
11
|
+
while (this.queue.length > 0) {
|
|
12
|
+
yield this.queue.shift();
|
|
13
|
+
}
|
|
22
14
|
}
|
|
23
15
|
}
|
|
24
16
|
/** Error thrown when reconnection problems occur. */
|
|
25
17
|
export class ReconnectingWebSocketError extends TransportError {
|
|
26
|
-
|
|
18
|
+
code;
|
|
19
|
+
constructor(code, cause) {
|
|
27
20
|
super(`Error when reconnecting WebSocket: ${code}`);
|
|
28
|
-
|
|
29
|
-
enumerable: true,
|
|
30
|
-
configurable: true,
|
|
31
|
-
writable: true,
|
|
32
|
-
value: code
|
|
33
|
-
});
|
|
34
|
-
Object.defineProperty(this, "originalError", {
|
|
35
|
-
enumerable: true,
|
|
36
|
-
configurable: true,
|
|
37
|
-
writable: true,
|
|
38
|
-
value: originalError
|
|
39
|
-
});
|
|
21
|
+
this.code = code;
|
|
40
22
|
this.name = "ReconnectingWebSocketError";
|
|
23
|
+
this.cause = cause;
|
|
41
24
|
}
|
|
42
25
|
}
|
|
43
26
|
/**
|
|
@@ -45,131 +28,13 @@ export class ReconnectingWebSocketError extends TransportError {
|
|
|
45
28
|
* Fully compatible with standard WebSocket API.
|
|
46
29
|
*/
|
|
47
30
|
export class ReconnectingWebSocket {
|
|
31
|
+
_socket;
|
|
32
|
+
_protocols;
|
|
33
|
+
_listeners = [];
|
|
34
|
+
_attempt = 0;
|
|
35
|
+
reconnectOptions;
|
|
36
|
+
reconnectAbortController = new AbortController();
|
|
48
37
|
constructor(url, protocols, options) {
|
|
49
|
-
Object.defineProperty(this, "_socket", {
|
|
50
|
-
enumerable: true,
|
|
51
|
-
configurable: true,
|
|
52
|
-
writable: true,
|
|
53
|
-
value: void 0
|
|
54
|
-
});
|
|
55
|
-
Object.defineProperty(this, "_protocols", {
|
|
56
|
-
enumerable: true,
|
|
57
|
-
configurable: true,
|
|
58
|
-
writable: true,
|
|
59
|
-
value: void 0
|
|
60
|
-
});
|
|
61
|
-
Object.defineProperty(this, "_listeners", {
|
|
62
|
-
enumerable: true,
|
|
63
|
-
configurable: true,
|
|
64
|
-
writable: true,
|
|
65
|
-
value: []
|
|
66
|
-
});
|
|
67
|
-
Object.defineProperty(this, "_attempt", {
|
|
68
|
-
enumerable: true,
|
|
69
|
-
configurable: true,
|
|
70
|
-
writable: true,
|
|
71
|
-
value: 0
|
|
72
|
-
});
|
|
73
|
-
Object.defineProperty(this, "reconnectOptions", {
|
|
74
|
-
enumerable: true,
|
|
75
|
-
configurable: true,
|
|
76
|
-
writable: true,
|
|
77
|
-
value: void 0
|
|
78
|
-
});
|
|
79
|
-
Object.defineProperty(this, "reconnectAbortController", {
|
|
80
|
-
enumerable: true,
|
|
81
|
-
configurable: true,
|
|
82
|
-
writable: true,
|
|
83
|
-
value: new AbortController()
|
|
84
|
-
});
|
|
85
|
-
Object.defineProperty(this, "_open", {
|
|
86
|
-
enumerable: true,
|
|
87
|
-
configurable: true,
|
|
88
|
-
writable: true,
|
|
89
|
-
value: () => {
|
|
90
|
-
// Reset the attempt counter
|
|
91
|
-
this._attempt = 0;
|
|
92
|
-
// Send all buffered messages
|
|
93
|
-
let message;
|
|
94
|
-
while ((message = this.reconnectOptions.messageBuffer.shift()) !== undefined) {
|
|
95
|
-
this._socket.send(message);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
Object.defineProperty(this, "_close", {
|
|
100
|
-
enumerable: true,
|
|
101
|
-
configurable: true,
|
|
102
|
-
writable: true,
|
|
103
|
-
value: async (event) => {
|
|
104
|
-
try {
|
|
105
|
-
// If the event was triggered but the socket is not closing, ignore it
|
|
106
|
-
if (this._socket.readyState !== ReconnectingWebSocket.CLOSING &&
|
|
107
|
-
this._socket.readyState !== ReconnectingWebSocket.CLOSED)
|
|
108
|
-
return;
|
|
109
|
-
// If the instance is terminated, do not attempt to reconnect
|
|
110
|
-
if (this.reconnectAbortController.signal.aborted)
|
|
111
|
-
return;
|
|
112
|
-
// Check if reconnection should be attempted
|
|
113
|
-
if (++this._attempt > this.reconnectOptions.maxRetries) {
|
|
114
|
-
this._cleanup("RECONNECTION_LIMIT_REACHED");
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
const userDecision = await this.reconnectOptions.shouldReconnect(event, this.reconnectAbortController.signal);
|
|
118
|
-
if (this.reconnectAbortController.signal.aborted)
|
|
119
|
-
return;
|
|
120
|
-
if (!userDecision) {
|
|
121
|
-
this._cleanup("RECONNECTION_STOPPED_BY_USER");
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
// Delay before reconnecting
|
|
125
|
-
const reconnectDelay = typeof this.reconnectOptions.connectionDelay === "number"
|
|
126
|
-
? this.reconnectOptions.connectionDelay
|
|
127
|
-
: await this.reconnectOptions.connectionDelay(this._attempt, this.reconnectAbortController.signal);
|
|
128
|
-
if (this.reconnectAbortController.signal.aborted)
|
|
129
|
-
return;
|
|
130
|
-
await delay(reconnectDelay, { signal: this.reconnectAbortController.signal });
|
|
131
|
-
// Create a new WebSocket instance
|
|
132
|
-
const { onclose, onerror, onmessage, onopen } = this._socket;
|
|
133
|
-
this._socket = this._createSocket(this._socket.url, this._protocols);
|
|
134
|
-
// Reconnect all listeners
|
|
135
|
-
this._setupEventListeners();
|
|
136
|
-
this._listeners.forEach(({ type, listenerProxy, options }) => {
|
|
137
|
-
this._socket.addEventListener(type, listenerProxy, options);
|
|
138
|
-
});
|
|
139
|
-
this._socket.onclose = onclose;
|
|
140
|
-
this._socket.onerror = onerror;
|
|
141
|
-
this._socket.onmessage = onmessage;
|
|
142
|
-
this._socket.onopen = onopen;
|
|
143
|
-
}
|
|
144
|
-
catch (error) {
|
|
145
|
-
this._cleanup("UNKNOWN_ERROR", error);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
Object.defineProperty(this, "CONNECTING", {
|
|
150
|
-
enumerable: true,
|
|
151
|
-
configurable: true,
|
|
152
|
-
writable: true,
|
|
153
|
-
value: 0
|
|
154
|
-
});
|
|
155
|
-
Object.defineProperty(this, "OPEN", {
|
|
156
|
-
enumerable: true,
|
|
157
|
-
configurable: true,
|
|
158
|
-
writable: true,
|
|
159
|
-
value: 1
|
|
160
|
-
});
|
|
161
|
-
Object.defineProperty(this, "CLOSING", {
|
|
162
|
-
enumerable: true,
|
|
163
|
-
configurable: true,
|
|
164
|
-
writable: true,
|
|
165
|
-
value: 2
|
|
166
|
-
});
|
|
167
|
-
Object.defineProperty(this, "CLOSED", {
|
|
168
|
-
enumerable: true,
|
|
169
|
-
configurable: true,
|
|
170
|
-
writable: true,
|
|
171
|
-
value: 3
|
|
172
|
-
});
|
|
173
38
|
this.reconnectOptions = {
|
|
174
39
|
maxRetries: options?.maxRetries ?? 3,
|
|
175
40
|
connectionTimeout: options?.connectionTimeout === undefined ? 10_000 : options.connectionTimeout,
|
|
@@ -207,10 +72,62 @@ export class ReconnectingWebSocket {
|
|
|
207
72
|
this._socket.addEventListener("open", this._open, { once: true });
|
|
208
73
|
this._socket.addEventListener("close", this._close, { once: true });
|
|
209
74
|
}
|
|
75
|
+
_open = () => {
|
|
76
|
+
// Reset the attempt counter
|
|
77
|
+
this._attempt = 0;
|
|
78
|
+
// Send all buffered messages
|
|
79
|
+
for (const message of this.reconnectOptions.messageBuffer) {
|
|
80
|
+
this._socket.send(message);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
_close = async (event) => {
|
|
84
|
+
try {
|
|
85
|
+
// If the event was triggered but the socket is not closing, ignore it
|
|
86
|
+
if (this._socket.readyState !== ReconnectingWebSocket.CLOSING &&
|
|
87
|
+
this._socket.readyState !== ReconnectingWebSocket.CLOSED)
|
|
88
|
+
return;
|
|
89
|
+
// If the instance is terminated, do not attempt to reconnect
|
|
90
|
+
if (this.reconnectAbortController.signal.aborted)
|
|
91
|
+
return;
|
|
92
|
+
// Check if reconnection should be attempted
|
|
93
|
+
if (++this._attempt > this.reconnectOptions.maxRetries) {
|
|
94
|
+
this._cleanup("RECONNECTION_LIMIT_REACHED");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const userDecision = await this.reconnectOptions.shouldReconnect(event, this.reconnectAbortController.signal);
|
|
98
|
+
if (this.reconnectAbortController.signal.aborted)
|
|
99
|
+
return;
|
|
100
|
+
if (!userDecision) {
|
|
101
|
+
this._cleanup("RECONNECTION_STOPPED_BY_USER");
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
// Delay before reconnecting
|
|
105
|
+
const reconnectDelay = typeof this.reconnectOptions.connectionDelay === "number"
|
|
106
|
+
? this.reconnectOptions.connectionDelay
|
|
107
|
+
: await this.reconnectOptions.connectionDelay(this._attempt, this.reconnectAbortController.signal);
|
|
108
|
+
if (this.reconnectAbortController.signal.aborted)
|
|
109
|
+
return;
|
|
110
|
+
await delay(reconnectDelay, { signal: this.reconnectAbortController.signal });
|
|
111
|
+
// Create a new WebSocket instance
|
|
112
|
+
const { onclose, onerror, onmessage, onopen } = this._socket;
|
|
113
|
+
this._socket = this._createSocket(this._socket.url, this._protocols);
|
|
114
|
+
// Reconnect all listeners
|
|
115
|
+
this._setupEventListeners();
|
|
116
|
+
this._listeners.forEach(({ type, listenerProxy, options }) => {
|
|
117
|
+
this._socket.addEventListener(type, listenerProxy, options);
|
|
118
|
+
});
|
|
119
|
+
this._socket.onclose = onclose;
|
|
120
|
+
this._socket.onerror = onerror;
|
|
121
|
+
this._socket.onmessage = onmessage;
|
|
122
|
+
this._socket.onopen = onopen;
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
this._cleanup("UNKNOWN_ERROR", error);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
210
128
|
/** Clean up internal resources. */
|
|
211
|
-
_cleanup(code,
|
|
212
|
-
this.reconnectAbortController.abort(new ReconnectingWebSocketError(code,
|
|
213
|
-
this.reconnectOptions.messageBuffer.clear();
|
|
129
|
+
_cleanup(code, cause) {
|
|
130
|
+
this.reconnectAbortController.abort(new ReconnectingWebSocketError(code, cause));
|
|
214
131
|
this._listeners = [];
|
|
215
132
|
this._socket.close();
|
|
216
133
|
}
|
|
@@ -236,6 +153,14 @@ export class ReconnectingWebSocket {
|
|
|
236
153
|
set binaryType(value) {
|
|
237
154
|
this._socket.binaryType = value;
|
|
238
155
|
}
|
|
156
|
+
CONNECTING = 0;
|
|
157
|
+
OPEN = 1;
|
|
158
|
+
CLOSING = 2;
|
|
159
|
+
CLOSED = 3;
|
|
160
|
+
static CONNECTING = 0;
|
|
161
|
+
static OPEN = 1;
|
|
162
|
+
static CLOSING = 2;
|
|
163
|
+
static CLOSED = 3;
|
|
239
164
|
get onclose() {
|
|
240
165
|
return this._socket.onclose;
|
|
241
166
|
}
|
|
@@ -337,30 +262,6 @@ export class ReconnectingWebSocket {
|
|
|
337
262
|
return this._socket.dispatchEvent(event);
|
|
338
263
|
}
|
|
339
264
|
}
|
|
340
|
-
Object.defineProperty(ReconnectingWebSocket, "CONNECTING", {
|
|
341
|
-
enumerable: true,
|
|
342
|
-
configurable: true,
|
|
343
|
-
writable: true,
|
|
344
|
-
value: 0
|
|
345
|
-
});
|
|
346
|
-
Object.defineProperty(ReconnectingWebSocket, "OPEN", {
|
|
347
|
-
enumerable: true,
|
|
348
|
-
configurable: true,
|
|
349
|
-
writable: true,
|
|
350
|
-
value: 1
|
|
351
|
-
});
|
|
352
|
-
Object.defineProperty(ReconnectingWebSocket, "CLOSING", {
|
|
353
|
-
enumerable: true,
|
|
354
|
-
configurable: true,
|
|
355
|
-
writable: true,
|
|
356
|
-
value: 2
|
|
357
|
-
});
|
|
358
|
-
Object.defineProperty(ReconnectingWebSocket, "CLOSED", {
|
|
359
|
-
enumerable: true,
|
|
360
|
-
configurable: true,
|
|
361
|
-
writable: true,
|
|
362
|
-
value: 3
|
|
363
|
-
});
|
|
364
265
|
/** Check if two event listeners are the same (just like EventTarget). */
|
|
365
266
|
function listenersMatch(a, b) {
|
|
366
267
|
// EventTarget only compares capture in options, even if one is an object and the other is boolean
|
|
@@ -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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TransportError } from "
|
|
1
|
+
import { TransportError } from "../base.js";
|
|
2
2
|
/**
|
|
3
3
|
* Error thrown when a WebSocket request fails:
|
|
4
4
|
* - When the WebSocket connection is closed
|
|
@@ -14,44 +14,32 @@ export class WebSocketRequestError extends TransportError {
|
|
|
14
14
|
* Manages WebSocket requests to the Hyperliquid API.
|
|
15
15
|
* Handles request creation, sending, and mapping responses to their corresponding requests.
|
|
16
16
|
*/
|
|
17
|
-
export class
|
|
17
|
+
export class WebSocketAsyncRequest {
|
|
18
|
+
socket;
|
|
19
|
+
lastId = 0;
|
|
20
|
+
queue = new Map();
|
|
21
|
+
lastRequestTime = 0;
|
|
18
22
|
/**
|
|
19
|
-
* Creates a new WebSocket request
|
|
23
|
+
* Creates a new WebSocket async request handler.
|
|
20
24
|
* @param socket - WebSocket connection instance for sending requests to the Hyperliquid WebSocket API
|
|
21
25
|
* @param hlEvents - Used to recognize Hyperliquid responses and match them with sent requests
|
|
22
26
|
*/
|
|
23
27
|
constructor(socket, hlEvents) {
|
|
24
|
-
|
|
25
|
-
enumerable: true,
|
|
26
|
-
configurable: true,
|
|
27
|
-
writable: true,
|
|
28
|
-
value: socket
|
|
29
|
-
});
|
|
30
|
-
/** Last used post request ID */
|
|
31
|
-
Object.defineProperty(this, "lastId", {
|
|
32
|
-
enumerable: true,
|
|
33
|
-
configurable: true,
|
|
34
|
-
writable: true,
|
|
35
|
-
value: 0
|
|
36
|
-
});
|
|
37
|
-
/** Map of pending requests waiting for responses */
|
|
38
|
-
Object.defineProperty(this, "pending", {
|
|
39
|
-
enumerable: true,
|
|
40
|
-
configurable: true,
|
|
41
|
-
writable: true,
|
|
42
|
-
value: new Map()
|
|
43
|
-
});
|
|
28
|
+
this.socket = socket;
|
|
44
29
|
// Monitor responses and match the pending request
|
|
45
30
|
hlEvents.addEventListener("subscriptionResponse", (event) => {
|
|
46
31
|
// Use a stringified request as an id
|
|
47
|
-
const id =
|
|
48
|
-
this.
|
|
32
|
+
const id = WebSocketAsyncRequest.requestToId(event.detail.subscription);
|
|
33
|
+
this.queue.get(id)?.resolve(event.detail);
|
|
49
34
|
});
|
|
50
35
|
hlEvents.addEventListener("post", (event) => {
|
|
51
36
|
const data = event.detail.response.type === "info"
|
|
52
37
|
? event.detail.response.payload.data
|
|
53
38
|
: event.detail.response.payload;
|
|
54
|
-
this.
|
|
39
|
+
this.queue.get(event.detail.id)?.resolve(data);
|
|
40
|
+
});
|
|
41
|
+
hlEvents.addEventListener("pong", () => {
|
|
42
|
+
this.queue.get("ping")?.resolve();
|
|
55
43
|
});
|
|
56
44
|
hlEvents.addEventListener("error", (event) => {
|
|
57
45
|
try {
|
|
@@ -61,19 +49,19 @@ export class WebSocketRequestDispatcher {
|
|
|
61
49
|
const parsedRequest = JSON.parse(request);
|
|
62
50
|
if ("id" in parsedRequest && typeof parsedRequest.id === "number") {
|
|
63
51
|
// If a post request was sent, it is possible to get the id from the request
|
|
64
|
-
this.
|
|
52
|
+
this.queue.get(parsedRequest.id)?.reject(new WebSocketRequestError(`Cannot complete WebSocket request: ${event.detail}`));
|
|
65
53
|
}
|
|
66
54
|
else if ("subscription" in parsedRequest &&
|
|
67
55
|
typeof parsedRequest.subscription === "object" &&
|
|
68
56
|
parsedRequest.subscription !== null) {
|
|
69
57
|
// If a subscription/unsubscribe request was sent, use the request as an id
|
|
70
|
-
const id =
|
|
71
|
-
this.
|
|
58
|
+
const id = WebSocketAsyncRequest.requestToId(parsedRequest.subscription);
|
|
59
|
+
this.queue.get(id)?.reject(new WebSocketRequestError(`Cannot complete WebSocket request: ${event.detail}`));
|
|
72
60
|
}
|
|
73
61
|
else {
|
|
74
62
|
// If the request is not recognized, use the parsed request as an id
|
|
75
|
-
const id =
|
|
76
|
-
this.
|
|
63
|
+
const id = WebSocketAsyncRequest.requestToId(parsedRequest);
|
|
64
|
+
this.queue.get(id)?.reject(new WebSocketRequestError(`Cannot complete WebSocket request: ${event.detail}`));
|
|
77
65
|
}
|
|
78
66
|
}
|
|
79
67
|
}
|
|
@@ -83,67 +71,54 @@ export class WebSocketRequestDispatcher {
|
|
|
83
71
|
});
|
|
84
72
|
// Throws all pending requests if the connection is dropped
|
|
85
73
|
socket.addEventListener("close", () => {
|
|
86
|
-
this.
|
|
74
|
+
this.queue.forEach(({ reject }) => {
|
|
87
75
|
reject(new WebSocketRequestError("Cannot complete WebSocket request: connection is closed"));
|
|
88
76
|
});
|
|
89
|
-
this.
|
|
77
|
+
this.queue.clear();
|
|
90
78
|
});
|
|
91
79
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
* @param payload - The payload to send with the request.
|
|
96
|
-
* @param signal - An optional abort signal.
|
|
97
|
-
* @returns A promise that resolves with the parsed JSON response body.
|
|
98
|
-
*/
|
|
99
|
-
async request(method, payload, signal) {
|
|
80
|
+
async request(method, payload_or_signal, maybeSignal) {
|
|
81
|
+
const payload = payload_or_signal instanceof AbortSignal ? undefined : payload_or_signal;
|
|
82
|
+
const signal = payload_or_signal instanceof AbortSignal ? payload_or_signal : maybeSignal;
|
|
100
83
|
// Reject the request if the signal is aborted
|
|
101
84
|
if (signal?.aborted)
|
|
102
85
|
return Promise.reject(signal.reason);
|
|
103
|
-
// Create a request
|
|
86
|
+
// Create a request
|
|
104
87
|
let id;
|
|
105
88
|
let request;
|
|
106
89
|
if (method === "post") {
|
|
107
90
|
id = ++this.lastId;
|
|
108
91
|
request = { method, id, request: payload };
|
|
109
92
|
}
|
|
93
|
+
else if (method === "ping") {
|
|
94
|
+
id = "ping";
|
|
95
|
+
request = { method };
|
|
96
|
+
}
|
|
110
97
|
else {
|
|
111
|
-
id =
|
|
98
|
+
id = WebSocketAsyncRequest.requestToId(payload);
|
|
112
99
|
request = { method, subscription: payload };
|
|
113
100
|
}
|
|
114
101
|
// Send the request
|
|
115
102
|
this.socket.send(JSON.stringify(request));
|
|
103
|
+
this.lastRequestTime = Date.now();
|
|
116
104
|
// Wait for a response
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
this.pending.set(id, { resolve, reject });
|
|
124
|
-
}).finally(() => {
|
|
125
|
-
// Remove the abort listener when the promise is settled
|
|
105
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
106
|
+
this.queue.set(id, { resolve, reject });
|
|
107
|
+
const onAbort = () => reject(signal?.reason);
|
|
108
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
109
|
+
return await promise.finally(() => {
|
|
110
|
+
this.queue.delete(id);
|
|
126
111
|
signal?.removeEventListener("abort", onAbort);
|
|
127
|
-
// Clean up the pending list
|
|
128
|
-
this.pending.delete(id);
|
|
129
112
|
});
|
|
130
113
|
}
|
|
131
|
-
/**
|
|
132
|
-
* Normalizes a request object to an ID.
|
|
133
|
-
* @param value - A request object.
|
|
134
|
-
* @returns A stringified request.
|
|
135
|
-
*/
|
|
114
|
+
/** Normalizes an object and then converts it to a string. */
|
|
136
115
|
static requestToId(value) {
|
|
137
116
|
const lowerHex = containsUppercaseHex(value) ? deepLowerHex(value) : value;
|
|
138
117
|
const sorted = deepSortKeys(lowerHex);
|
|
139
|
-
return JSON.stringify(sorted);
|
|
118
|
+
return JSON.stringify(sorted); // Also removes undefined
|
|
140
119
|
}
|
|
141
120
|
}
|
|
142
|
-
/**
|
|
143
|
-
* Deeply converts hexadecimal strings in an object/array to lowercase.
|
|
144
|
-
* @param obj - The object/array to convert hexadecimal strings to lowercase.
|
|
145
|
-
* @returns A new object/array with hexadecimal strings converted to lowercase.
|
|
146
|
-
*/
|
|
121
|
+
/** Deeply converts hexadecimal strings in an object/array to lowercase. */
|
|
147
122
|
function deepLowerHex(obj) {
|
|
148
123
|
if (typeof obj === "string") {
|
|
149
124
|
return /^(0X[0-9a-fA-F]*|0x[0-9a-fA-F]*[A-F][0-9a-fA-F]*)$/.test(obj) ? obj.toLowerCase() : obj;
|
|
@@ -161,20 +136,12 @@ function deepLowerHex(obj) {
|
|
|
161
136
|
}
|
|
162
137
|
return obj;
|
|
163
138
|
}
|
|
164
|
-
/**
|
|
165
|
-
* Check if an object contains uppercase hexadecimal strings.
|
|
166
|
-
* @param obj - The object to check.
|
|
167
|
-
* @returns True if the object contains uppercase hexadecimal strings, false otherwise.
|
|
168
|
-
*/
|
|
139
|
+
/** Check if an object contains uppercase hexadecimal strings. */
|
|
169
140
|
function containsUppercaseHex(obj) {
|
|
170
141
|
const str = JSON.stringify(obj);
|
|
171
142
|
return /0X[0-9a-fA-F]*|0x[0-9a-fA-F]*[A-F][0-9a-fA-F]*/.test(str);
|
|
172
143
|
}
|
|
173
|
-
/**
|
|
174
|
-
* Deeply sort the keys of an object.
|
|
175
|
-
* @param obj - An object to sort the keys of.
|
|
176
|
-
* @returns A new object with sorted keys.
|
|
177
|
-
*/
|
|
144
|
+
/** Deeply sort the keys of an object. */
|
|
178
145
|
function deepSortKeys(obj) {
|
|
179
146
|
if (typeof obj !== "object" || obj === null) {
|
|
180
147
|
return obj;
|