@nktkas/hyperliquid 0.19.2 → 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.
Files changed (123) hide show
  1. package/README.md +21 -29
  2. package/esm/_dnt.polyfills.d.ts +20 -0
  3. package/esm/_dnt.polyfills.d.ts.map +1 -0
  4. package/esm/_dnt.polyfills.js +12 -0
  5. package/esm/mod.d.ts +3 -0
  6. package/esm/mod.d.ts.map +1 -1
  7. package/esm/mod.js +2 -0
  8. package/esm/src/base.d.ts +1 -47
  9. package/esm/src/base.d.ts.map +1 -1
  10. package/esm/src/base.js +1 -8
  11. package/esm/src/clients/event.d.ts +2 -3
  12. package/esm/src/clients/event.d.ts.map +1 -1
  13. package/esm/src/clients/event.js +49 -57
  14. package/esm/src/clients/public.d.ts +24 -5
  15. package/esm/src/clients/public.d.ts.map +1 -1
  16. package/esm/src/clients/public.js +23 -7
  17. package/esm/src/clients/wallet.d.ts +12 -13
  18. package/esm/src/clients/wallet.d.ts.map +1 -1
  19. package/esm/src/clients/wallet.js +55 -265
  20. package/esm/src/signing.d.ts +5 -0
  21. package/esm/src/signing.d.ts.map +1 -1
  22. package/esm/src/signing.js +24 -5
  23. package/esm/src/transports/base.d.ts +49 -0
  24. package/esm/src/transports/base.d.ts.map +1 -0
  25. package/esm/src/transports/base.js +8 -0
  26. package/esm/src/transports/http/http_transport.d.ts +8 -5
  27. package/esm/src/transports/http/http_transport.d.ts.map +1 -1
  28. package/esm/src/transports/http/http_transport.js +15 -62
  29. package/esm/src/transports/websocket/_hyperliquid_event_target.d.ts +36 -39
  30. package/esm/src/transports/websocket/_hyperliquid_event_target.d.ts.map +1 -1
  31. package/esm/src/transports/websocket/_reconnecting_websocket.d.ts +18 -25
  32. package/esm/src/transports/websocket/_reconnecting_websocket.d.ts.map +1 -1
  33. package/esm/src/transports/websocket/_reconnecting_websocket.js +80 -179
  34. package/{script/src/transports/websocket/_websocket_request_dispatcher.d.ts → esm/src/transports/websocket/_websocket_async_request.d.ts} +14 -18
  35. package/esm/src/transports/websocket/_websocket_async_request.d.ts.map +1 -0
  36. package/esm/src/transports/websocket/{_websocket_request_dispatcher.js → _websocket_async_request.js} +41 -74
  37. package/esm/src/transports/websocket/websocket_transport.d.ts +38 -28
  38. package/esm/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  39. package/esm/src/transports/websocket/websocket_transport.js +61 -76
  40. package/esm/src/types/info/assets.d.ts +0 -48
  41. package/esm/src/types/info/assets.d.ts.map +1 -1
  42. package/esm/src/types/info/markets.d.ts +52 -0
  43. package/esm/src/types/info/markets.d.ts.map +1 -0
  44. package/esm/src/types/info/markets.js +1 -0
  45. package/esm/src/types/info/requests.d.ts +9 -0
  46. package/esm/src/types/info/requests.d.ts.map +1 -1
  47. package/esm/src/types/mod.d.ts +4 -0
  48. package/esm/src/types/mod.d.ts.map +1 -1
  49. package/esm/src/types/mod.js +3 -1
  50. package/package.json +12 -9
  51. package/script/_dnt.polyfills.d.ts +20 -0
  52. package/script/_dnt.polyfills.d.ts.map +1 -0
  53. package/script/_dnt.polyfills.js +23 -0
  54. package/script/mod.d.ts +3 -0
  55. package/script/mod.d.ts.map +1 -1
  56. package/script/mod.js +3 -1
  57. package/script/src/base.d.ts +1 -47
  58. package/script/src/base.d.ts.map +1 -1
  59. package/script/src/base.js +2 -10
  60. package/script/src/clients/event.d.ts +2 -3
  61. package/script/src/clients/event.d.ts.map +1 -1
  62. package/script/src/clients/event.js +49 -57
  63. package/script/src/clients/public.d.ts +24 -5
  64. package/script/src/clients/public.d.ts.map +1 -1
  65. package/script/src/clients/public.js +23 -7
  66. package/script/src/clients/wallet.d.ts +12 -13
  67. package/script/src/clients/wallet.d.ts.map +1 -1
  68. package/script/src/clients/wallet.js +55 -265
  69. package/script/src/signing.d.ts +5 -0
  70. package/script/src/signing.d.ts.map +1 -1
  71. package/script/src/signing.js +75 -56
  72. package/script/src/transports/base.d.ts +49 -0
  73. package/script/src/transports/base.d.ts.map +1 -0
  74. package/script/src/transports/base.js +22 -0
  75. package/script/src/transports/http/http_transport.d.ts +8 -5
  76. package/script/src/transports/http/http_transport.d.ts.map +1 -1
  77. package/script/src/transports/http/http_transport.js +16 -63
  78. package/script/src/transports/websocket/_hyperliquid_event_target.d.ts +36 -39
  79. package/script/src/transports/websocket/_hyperliquid_event_target.d.ts.map +1 -1
  80. package/script/src/transports/websocket/_reconnecting_websocket.d.ts +18 -25
  81. package/script/src/transports/websocket/_reconnecting_websocket.d.ts.map +1 -1
  82. package/script/src/transports/websocket/_reconnecting_websocket.js +81 -180
  83. package/{esm/src/transports/websocket/_websocket_request_dispatcher.d.ts → script/src/transports/websocket/_websocket_async_request.d.ts} +14 -18
  84. package/script/src/transports/websocket/_websocket_async_request.d.ts.map +1 -0
  85. package/script/src/transports/websocket/{_websocket_request_dispatcher.js → _websocket_async_request.js} +44 -77
  86. package/script/src/transports/websocket/websocket_transport.d.ts +38 -28
  87. package/script/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  88. package/script/src/transports/websocket/websocket_transport.js +63 -78
  89. package/script/src/types/info/assets.d.ts +0 -48
  90. package/script/src/types/info/assets.d.ts.map +1 -1
  91. package/script/src/types/info/markets.d.ts +52 -0
  92. package/script/src/types/info/markets.d.ts.map +1 -0
  93. package/script/{deps/jsr.io/@noble/hashes/1.8.0/src/crypto.js → src/types/info/markets.js} +0 -2
  94. package/script/src/types/info/requests.d.ts +9 -0
  95. package/script/src/types/info/requests.d.ts.map +1 -1
  96. package/script/src/types/mod.d.ts +4 -0
  97. package/script/src/types/mod.d.ts.map +1 -1
  98. package/script/src/types/mod.js +25 -22
  99. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.d.ts +0 -55
  100. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.d.ts.map +0 -1
  101. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.js +0 -66
  102. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/crypto.d.ts +0 -2
  103. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/crypto.d.ts.map +0 -1
  104. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/crypto.js +0 -1
  105. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.d.ts +0 -53
  106. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.d.ts.map +0 -1
  107. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.js +0 -294
  108. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/utils.d.ts +0 -161
  109. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/utils.d.ts.map +0 -1
  110. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/utils.js +0 -280
  111. package/esm/src/transports/websocket/_websocket_request_dispatcher.d.ts.map +0 -1
  112. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.d.ts +0 -55
  113. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.d.ts.map +0 -1
  114. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.js +0 -99
  115. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/crypto.d.ts +0 -2
  116. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/crypto.d.ts.map +0 -1
  117. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.d.ts +0 -53
  118. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.d.ts.map +0 -1
  119. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.js +0 -309
  120. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/utils.d.ts +0 -161
  121. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/utils.d.ts.map +0 -1
  122. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/utils.js +0 -322
  123. package/script/src/transports/websocket/_websocket_request_dispatcher.d.ts.map +0 -1
@@ -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", "../../../deps/jsr.io/@std/async/1.0.13/delay.js", "../../base.js"], factory);
7
+ define(["require", "exports", "../../../deps/jsr.io/@std/async/1.0.13/delay.js", "../base.js"], factory);
8
8
  }
9
9
  })(function (require, exports) {
10
10
  "use strict";
@@ -12,44 +12,27 @@
12
12
  exports.ReconnectingWebSocket = exports.ReconnectingWebSocketError = void 0;
13
13
  // deno-lint-ignore-file no-explicit-any
14
14
  const delay_js_1 = require("../../../deps/jsr.io/@std/async/1.0.13/delay.js");
15
- const base_js_1 = require("../../base.js");
15
+ const base_js_1 = require("../base.js");
16
16
  /** Simple FIFO (First In, First Out) buffer implementation. */
17
17
  class FIFOMessageBuffer {
18
- constructor() {
19
- Object.defineProperty(this, "messages", {
20
- enumerable: true,
21
- configurable: true,
22
- writable: true,
23
- value: []
24
- });
25
- }
18
+ queue = [];
26
19
  push(data) {
27
- this.messages.push(data);
28
- }
29
- shift() {
30
- return this.messages.shift();
20
+ this.queue.push(data);
31
21
  }
32
- clear() {
33
- this.messages = [];
22
+ *[Symbol.iterator]() {
23
+ while (this.queue.length > 0) {
24
+ yield this.queue.shift();
25
+ }
34
26
  }
35
27
  }
36
28
  /** Error thrown when reconnection problems occur. */
37
29
  class ReconnectingWebSocketError extends base_js_1.TransportError {
38
- constructor(code, originalError) {
30
+ code;
31
+ constructor(code, cause) {
39
32
  super(`Error when reconnecting WebSocket: ${code}`);
40
- Object.defineProperty(this, "code", {
41
- enumerable: true,
42
- configurable: true,
43
- writable: true,
44
- value: code
45
- });
46
- Object.defineProperty(this, "originalError", {
47
- enumerable: true,
48
- configurable: true,
49
- writable: true,
50
- value: originalError
51
- });
33
+ this.code = code;
52
34
  this.name = "ReconnectingWebSocketError";
35
+ this.cause = cause;
53
36
  }
54
37
  }
55
38
  exports.ReconnectingWebSocketError = ReconnectingWebSocketError;
@@ -58,131 +41,13 @@
58
41
  * Fully compatible with standard WebSocket API.
59
42
  */
60
43
  class ReconnectingWebSocket {
44
+ _socket;
45
+ _protocols;
46
+ _listeners = [];
47
+ _attempt = 0;
48
+ reconnectOptions;
49
+ reconnectAbortController = new AbortController();
61
50
  constructor(url, protocols, options) {
62
- Object.defineProperty(this, "_socket", {
63
- enumerable: true,
64
- configurable: true,
65
- writable: true,
66
- value: void 0
67
- });
68
- Object.defineProperty(this, "_protocols", {
69
- enumerable: true,
70
- configurable: true,
71
- writable: true,
72
- value: void 0
73
- });
74
- Object.defineProperty(this, "_listeners", {
75
- enumerable: true,
76
- configurable: true,
77
- writable: true,
78
- value: []
79
- });
80
- Object.defineProperty(this, "_attempt", {
81
- enumerable: true,
82
- configurable: true,
83
- writable: true,
84
- value: 0
85
- });
86
- Object.defineProperty(this, "reconnectOptions", {
87
- enumerable: true,
88
- configurable: true,
89
- writable: true,
90
- value: void 0
91
- });
92
- Object.defineProperty(this, "reconnectAbortController", {
93
- enumerable: true,
94
- configurable: true,
95
- writable: true,
96
- value: new AbortController()
97
- });
98
- Object.defineProperty(this, "_open", {
99
- enumerable: true,
100
- configurable: true,
101
- writable: true,
102
- value: () => {
103
- // Reset the attempt counter
104
- this._attempt = 0;
105
- // Send all buffered messages
106
- let message;
107
- while ((message = this.reconnectOptions.messageBuffer.shift()) !== undefined) {
108
- this._socket.send(message);
109
- }
110
- }
111
- });
112
- Object.defineProperty(this, "_close", {
113
- enumerable: true,
114
- configurable: true,
115
- writable: true,
116
- value: async (event) => {
117
- try {
118
- // If the event was triggered but the socket is not closing, ignore it
119
- if (this._socket.readyState !== ReconnectingWebSocket.CLOSING &&
120
- this._socket.readyState !== ReconnectingWebSocket.CLOSED)
121
- return;
122
- // If the instance is terminated, do not attempt to reconnect
123
- if (this.reconnectAbortController.signal.aborted)
124
- return;
125
- // Check if reconnection should be attempted
126
- if (++this._attempt > this.reconnectOptions.maxRetries) {
127
- this._cleanup("RECONNECTION_LIMIT_REACHED");
128
- return;
129
- }
130
- const userDecision = await this.reconnectOptions.shouldReconnect(event, this.reconnectAbortController.signal);
131
- if (this.reconnectAbortController.signal.aborted)
132
- return;
133
- if (!userDecision) {
134
- this._cleanup("RECONNECTION_STOPPED_BY_USER");
135
- return;
136
- }
137
- // Delay before reconnecting
138
- const reconnectDelay = typeof this.reconnectOptions.connectionDelay === "number"
139
- ? this.reconnectOptions.connectionDelay
140
- : await this.reconnectOptions.connectionDelay(this._attempt, this.reconnectAbortController.signal);
141
- if (this.reconnectAbortController.signal.aborted)
142
- return;
143
- await (0, delay_js_1.delay)(reconnectDelay, { signal: this.reconnectAbortController.signal });
144
- // Create a new WebSocket instance
145
- const { onclose, onerror, onmessage, onopen } = this._socket;
146
- this._socket = this._createSocket(this._socket.url, this._protocols);
147
- // Reconnect all listeners
148
- this._setupEventListeners();
149
- this._listeners.forEach(({ type, listenerProxy, options }) => {
150
- this._socket.addEventListener(type, listenerProxy, options);
151
- });
152
- this._socket.onclose = onclose;
153
- this._socket.onerror = onerror;
154
- this._socket.onmessage = onmessage;
155
- this._socket.onopen = onopen;
156
- }
157
- catch (error) {
158
- this._cleanup("UNKNOWN_ERROR", error);
159
- }
160
- }
161
- });
162
- Object.defineProperty(this, "CONNECTING", {
163
- enumerable: true,
164
- configurable: true,
165
- writable: true,
166
- value: 0
167
- });
168
- Object.defineProperty(this, "OPEN", {
169
- enumerable: true,
170
- configurable: true,
171
- writable: true,
172
- value: 1
173
- });
174
- Object.defineProperty(this, "CLOSING", {
175
- enumerable: true,
176
- configurable: true,
177
- writable: true,
178
- value: 2
179
- });
180
- Object.defineProperty(this, "CLOSED", {
181
- enumerable: true,
182
- configurable: true,
183
- writable: true,
184
- value: 3
185
- });
186
51
  this.reconnectOptions = {
187
52
  maxRetries: options?.maxRetries ?? 3,
188
53
  connectionTimeout: options?.connectionTimeout === undefined ? 10_000 : options.connectionTimeout,
@@ -220,10 +85,62 @@
220
85
  this._socket.addEventListener("open", this._open, { once: true });
221
86
  this._socket.addEventListener("close", this._close, { once: true });
222
87
  }
88
+ _open = () => {
89
+ // Reset the attempt counter
90
+ this._attempt = 0;
91
+ // Send all buffered messages
92
+ for (const message of this.reconnectOptions.messageBuffer) {
93
+ this._socket.send(message);
94
+ }
95
+ };
96
+ _close = async (event) => {
97
+ try {
98
+ // If the event was triggered but the socket is not closing, ignore it
99
+ if (this._socket.readyState !== ReconnectingWebSocket.CLOSING &&
100
+ this._socket.readyState !== ReconnectingWebSocket.CLOSED)
101
+ return;
102
+ // If the instance is terminated, do not attempt to reconnect
103
+ if (this.reconnectAbortController.signal.aborted)
104
+ return;
105
+ // Check if reconnection should be attempted
106
+ if (++this._attempt > this.reconnectOptions.maxRetries) {
107
+ this._cleanup("RECONNECTION_LIMIT_REACHED");
108
+ return;
109
+ }
110
+ const userDecision = await this.reconnectOptions.shouldReconnect(event, this.reconnectAbortController.signal);
111
+ if (this.reconnectAbortController.signal.aborted)
112
+ return;
113
+ if (!userDecision) {
114
+ this._cleanup("RECONNECTION_STOPPED_BY_USER");
115
+ return;
116
+ }
117
+ // Delay before reconnecting
118
+ const reconnectDelay = typeof this.reconnectOptions.connectionDelay === "number"
119
+ ? this.reconnectOptions.connectionDelay
120
+ : await this.reconnectOptions.connectionDelay(this._attempt, this.reconnectAbortController.signal);
121
+ if (this.reconnectAbortController.signal.aborted)
122
+ return;
123
+ await (0, delay_js_1.delay)(reconnectDelay, { signal: this.reconnectAbortController.signal });
124
+ // Create a new WebSocket instance
125
+ const { onclose, onerror, onmessage, onopen } = this._socket;
126
+ this._socket = this._createSocket(this._socket.url, this._protocols);
127
+ // Reconnect all listeners
128
+ this._setupEventListeners();
129
+ this._listeners.forEach(({ type, listenerProxy, options }) => {
130
+ this._socket.addEventListener(type, listenerProxy, options);
131
+ });
132
+ this._socket.onclose = onclose;
133
+ this._socket.onerror = onerror;
134
+ this._socket.onmessage = onmessage;
135
+ this._socket.onopen = onopen;
136
+ }
137
+ catch (error) {
138
+ this._cleanup("UNKNOWN_ERROR", error);
139
+ }
140
+ };
223
141
  /** Clean up internal resources. */
224
- _cleanup(code, error) {
225
- this.reconnectAbortController.abort(new ReconnectingWebSocketError(code, error));
226
- this.reconnectOptions.messageBuffer.clear();
142
+ _cleanup(code, cause) {
143
+ this.reconnectAbortController.abort(new ReconnectingWebSocketError(code, cause));
227
144
  this._listeners = [];
228
145
  this._socket.close();
229
146
  }
@@ -249,6 +166,14 @@
249
166
  set binaryType(value) {
250
167
  this._socket.binaryType = value;
251
168
  }
169
+ CONNECTING = 0;
170
+ OPEN = 1;
171
+ CLOSING = 2;
172
+ CLOSED = 3;
173
+ static CONNECTING = 0;
174
+ static OPEN = 1;
175
+ static CLOSING = 2;
176
+ static CLOSED = 3;
252
177
  get onclose() {
253
178
  return this._socket.onclose;
254
179
  }
@@ -351,30 +276,6 @@
351
276
  }
352
277
  }
353
278
  exports.ReconnectingWebSocket = ReconnectingWebSocket;
354
- Object.defineProperty(ReconnectingWebSocket, "CONNECTING", {
355
- enumerable: true,
356
- configurable: true,
357
- writable: true,
358
- value: 0
359
- });
360
- Object.defineProperty(ReconnectingWebSocket, "OPEN", {
361
- enumerable: true,
362
- configurable: true,
363
- writable: true,
364
- value: 1
365
- });
366
- Object.defineProperty(ReconnectingWebSocket, "CLOSING", {
367
- enumerable: true,
368
- configurable: true,
369
- writable: true,
370
- value: 2
371
- });
372
- Object.defineProperty(ReconnectingWebSocket, "CLOSED", {
373
- enumerable: true,
374
- configurable: true,
375
- writable: true,
376
- value: 3
377
- });
378
279
  /** Check if two event listeners are the same (just like EventTarget). */
379
280
  function listenersMatch(a, b) {
380
281
  // 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 "../../base.js";
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 WebSocketRequestDispatcher {
16
- private socket;
17
- /** Last used post request ID */
18
- private lastId;
19
- /** Map of pending requests waiting for responses */
20
- private pending;
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 dispatcher.
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: "post" | "subscribe" | "unsubscribe", payload: unknown, signal?: AbortSignal): Promise<unknown>;
35
- /**
36
- * Normalizes a request object to an ID.
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=_websocket_request_dispatcher.d.ts.map
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", "../../base.js"], factory);
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.WebSocketRequestDispatcher = exports.WebSocketRequestError = void 0;
13
- const base_js_1 = require("../../base.js");
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 WebSocketRequestDispatcher {
30
+ class WebSocketAsyncRequest {
31
+ socket;
32
+ lastId = 0;
33
+ queue = new Map();
34
+ lastRequestTime = 0;
31
35
  /**
32
- * Creates a new WebSocket request dispatcher.
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
- Object.defineProperty(this, "socket", {
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 = WebSocketRequestDispatcher.requestToId(event.detail.subscription);
61
- this.pending.get(id)?.resolve(event.detail);
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.pending.get(event.detail.id)?.resolve(data);
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.pending.get(parsedRequest.id)?.reject(new WebSocketRequestError(`Cannot complete WebSocket request: ${event.detail}`));
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 = WebSocketRequestDispatcher.requestToId(parsedRequest.subscription);
84
- this.pending.get(id)?.reject(new WebSocketRequestError(`Cannot complete WebSocket request: ${event.detail}`));
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 = WebSocketRequestDispatcher.requestToId(parsedRequest);
89
- this.pending.get(id)?.reject(new WebSocketRequestError(`Cannot complete WebSocket request: ${event.detail}`));
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.pending.forEach(({ reject }) => {
87
+ this.queue.forEach(({ reject }) => {
100
88
  reject(new WebSocketRequestError("Cannot complete WebSocket request: connection is closed"));
101
89
  });
102
- this.pending.clear();
90
+ this.queue.clear();
103
91
  });
104
92
  }
105
- /**
106
- * Sends a request to the Hyperliquid API.
107
- * @param method - The method of websocket request.
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 object
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 = WebSocketRequestDispatcher.requestToId(payload);
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
- let onAbort;
131
- return await new Promise((resolve, reject) => {
132
- // Add an abort listener
133
- onAbort = () => reject(signal?.reason);
134
- signal?.addEventListener("abort", onAbort, { once: true });
135
- // Add the promise to the pending list
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
131
  return JSON.stringify(sorted); // Also removes undefined
153
132
  }
154
133
  }
155
- exports.WebSocketRequestDispatcher = WebSocketRequestDispatcher;
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;