@nktkas/hyperliquid 0.25.0-beta.1 → 0.25.0-beta.3
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 +64 -16
- package/esm/bin/cli.d.ts +3 -0
- package/esm/bin/cli.d.ts.map +1 -0
- package/esm/bin/cli.js +452 -0
- package/esm/bin/cli.js.map +1 -0
- package/{script/src/errors.d.ts → esm/src/_errors.d.ts} +1 -1
- package/esm/src/_errors.d.ts.map +1 -0
- package/esm/src/{errors.js → _errors.js} +1 -0
- package/esm/src/_errors.js.map +1 -0
- package/esm/src/clients/exchange.d.ts +4 -11
- package/esm/src/clients/exchange.d.ts.map +1 -1
- package/esm/src/clients/exchange.js +8 -9
- package/esm/src/clients/exchange.js.map +1 -0
- package/esm/src/clients/info.d.ts +86 -2
- package/esm/src/clients/info.d.ts.map +1 -1
- package/esm/src/clients/info.js +103 -1
- package/esm/src/clients/info.js.map +1 -0
- package/esm/src/clients/multiSign.d.ts +1 -1
- package/esm/src/clients/multiSign.d.ts.map +1 -1
- package/esm/src/clients/multiSign.js +3 -2
- package/esm/src/clients/multiSign.js.map +1 -0
- package/esm/src/clients/subscription.js +1 -0
- package/esm/src/clients/subscription.js.map +1 -0
- package/esm/src/mod.d.ts +21 -0
- package/esm/src/mod.d.ts.map +1 -0
- package/esm/src/mod.js +14 -0
- package/esm/src/mod.js.map +1 -0
- package/esm/src/schemas/_base.d.ts +11 -3
- package/esm/src/schemas/_base.d.ts.map +1 -1
- package/esm/src/schemas/_base.js +30 -2
- package/esm/src/schemas/_base.js.map +1 -0
- package/esm/src/schemas/exchange/requests.d.ts +1872 -1872
- package/esm/src/schemas/exchange/requests.d.ts.map +1 -1
- package/esm/src/schemas/exchange/requests.js +277 -281
- package/esm/src/schemas/exchange/requests.js.map +1 -0
- package/esm/src/schemas/exchange/responses.d.ts +51 -51
- package/esm/src/schemas/exchange/responses.js +55 -54
- package/esm/src/schemas/exchange/responses.js.map +1 -0
- package/esm/src/schemas/explorer/requests.d.ts +5 -5
- package/esm/src/schemas/explorer/requests.js +6 -5
- package/esm/src/schemas/explorer/requests.js.map +1 -0
- package/esm/src/schemas/explorer/responses.d.ts +10 -10
- package/esm/src/schemas/explorer/responses.js +12 -11
- package/esm/src/schemas/explorer/responses.js.map +1 -0
- package/esm/src/schemas/info/accounts.d.ts +1042 -296
- package/esm/src/schemas/info/accounts.d.ts.map +1 -1
- package/esm/src/schemas/info/accounts.js +154 -109
- package/esm/src/schemas/info/accounts.js.map +1 -0
- package/esm/src/schemas/info/assets.d.ts +130 -101
- package/esm/src/schemas/info/assets.d.ts.map +1 -1
- package/esm/src/schemas/info/assets.js +69 -49
- package/esm/src/schemas/info/assets.js.map +1 -0
- package/esm/src/schemas/info/markets.d.ts +35 -18
- package/esm/src/schemas/info/markets.d.ts.map +1 -1
- package/esm/src/schemas/info/markets.js +27 -15
- package/esm/src/schemas/info/markets.js.map +1 -0
- package/esm/src/schemas/info/orders.d.ts +151 -151
- package/esm/src/schemas/info/orders.js +37 -36
- package/esm/src/schemas/info/orders.js.map +1 -0
- package/esm/src/schemas/info/requests.d.ts +145 -88
- package/esm/src/schemas/info/requests.d.ts.map +1 -1
- package/esm/src/schemas/info/requests.js +116 -73
- package/esm/src/schemas/info/requests.js.map +1 -0
- package/esm/src/schemas/info/validators.d.ts +60 -39
- package/esm/src/schemas/info/validators.d.ts.map +1 -1
- package/esm/src/schemas/info/validators.js +40 -26
- package/esm/src/schemas/info/validators.js.map +1 -0
- package/esm/src/schemas/info/vaults.d.ts +59 -59
- package/esm/src/schemas/info/vaults.js +20 -19
- package/esm/src/schemas/info/vaults.js.map +1 -0
- package/esm/src/schemas/mod.d.ts +4 -3
- package/esm/src/schemas/mod.d.ts.map +1 -1
- package/esm/src/schemas/mod.js +5 -3
- package/esm/src/schemas/mod.js.map +1 -0
- package/esm/src/schemas/subscriptions/requests.d.ts +23 -23
- package/esm/src/schemas/subscriptions/requests.d.ts.map +1 -1
- package/esm/src/schemas/subscriptions/requests.js +25 -24
- package/esm/src/schemas/subscriptions/requests.js.map +1 -0
- package/esm/src/schemas/subscriptions/responses.d.ts +547 -547
- package/esm/src/schemas/subscriptions/responses.js +41 -40
- package/esm/src/schemas/subscriptions/responses.js.map +1 -0
- package/esm/src/signing/mod.d.ts +1 -1
- package/esm/src/signing/mod.d.ts.map +1 -1
- package/esm/src/signing/mod.js +3 -2
- package/esm/src/signing/mod.js.map +1 -0
- package/esm/src/signing/signTypedData/ethers.d.ts.map +1 -0
- package/esm/src/signing/{_signTypedData → signTypedData}/ethers.js +1 -0
- package/esm/src/signing/signTypedData/ethers.js.map +1 -0
- package/esm/src/signing/signTypedData/mod.d.ts.map +1 -0
- package/esm/src/signing/{_signTypedData → signTypedData}/mod.js +1 -0
- package/esm/src/signing/signTypedData/mod.js.map +1 -0
- package/esm/src/signing/signTypedData/private_key.d.ts.map +1 -0
- package/esm/src/signing/{_signTypedData → signTypedData}/private_key.js +10 -8
- package/esm/src/signing/signTypedData/private_key.js.map +1 -0
- package/esm/src/signing/signTypedData/viem.d.ts.map +1 -0
- package/esm/src/signing/{_signTypedData → signTypedData}/viem.js +1 -0
- package/esm/src/signing/signTypedData/viem.js.map +1 -0
- package/esm/src/transports/base.d.ts +4 -4
- package/esm/src/transports/base.d.ts.map +1 -1
- package/esm/src/transports/base.js +3 -2
- package/esm/src/transports/base.js.map +1 -0
- package/esm/src/transports/http/http_transport.d.ts +1 -1
- package/esm/src/transports/http/http_transport.js +1 -0
- package/esm/src/transports/http/http_transport.js.map +1 -0
- package/esm/src/transports/websocket/_hyperliquid_event_target.js +1 -0
- package/esm/src/transports/websocket/_hyperliquid_event_target.js.map +1 -0
- package/esm/src/transports/websocket/_reconnecting_websocket.js +1 -0
- package/esm/src/transports/websocket/_reconnecting_websocket.js.map +1 -0
- package/esm/src/transports/websocket/_websocket_async_request.js +1 -0
- package/esm/src/transports/websocket/_websocket_async_request.js.map +1 -0
- package/esm/src/transports/websocket/websocket_transport.d.ts +7 -0
- package/esm/src/transports/websocket/websocket_transport.d.ts.map +1 -1
- package/esm/src/transports/websocket/websocket_transport.js +4 -0
- package/esm/src/transports/websocket/websocket_transport.js.map +1 -0
- package/package.json +15 -7
- package/script/bin/cli.d.ts +3 -0
- package/script/bin/cli.d.ts.map +1 -0
- package/script/bin/cli.js +490 -0
- package/script/bin/cli.js.map +1 -0
- package/{esm/src/errors.d.ts → script/src/_errors.d.ts} +1 -1
- package/script/src/_errors.d.ts.map +1 -0
- package/script/src/{errors.js → _errors.js} +1 -0
- package/script/src/_errors.js.map +1 -0
- package/script/src/clients/exchange.d.ts +4 -11
- package/script/src/clients/exchange.d.ts.map +1 -1
- package/script/src/clients/exchange.js +9 -10
- package/script/src/clients/exchange.js.map +1 -0
- package/script/src/clients/info.d.ts +86 -2
- package/script/src/clients/info.d.ts.map +1 -1
- package/script/src/clients/info.js +102 -0
- package/script/src/clients/info.js.map +1 -0
- package/script/src/clients/multiSign.d.ts +1 -1
- package/script/src/clients/multiSign.d.ts.map +1 -1
- package/script/src/clients/multiSign.js +3 -2
- package/script/src/clients/multiSign.js.map +1 -0
- package/script/src/clients/subscription.js +1 -0
- package/script/src/clients/subscription.js.map +1 -0
- package/script/src/mod.d.ts +21 -0
- package/script/src/mod.d.ts.map +1 -0
- package/script/{mod.js → src/mod.js} +13 -8
- package/script/src/mod.js.map +1 -0
- package/script/src/schemas/_base.d.ts +11 -3
- package/script/src/schemas/_base.d.ts.map +1 -1
- package/script/src/schemas/_base.js +31 -3
- package/script/src/schemas/_base.js.map +1 -0
- package/script/src/schemas/exchange/requests.d.ts +1872 -1872
- package/script/src/schemas/exchange/requests.d.ts.map +1 -1
- package/script/src/schemas/exchange/requests.js +276 -280
- package/script/src/schemas/exchange/requests.js.map +1 -0
- package/script/src/schemas/exchange/responses.d.ts +51 -51
- package/script/src/schemas/exchange/responses.js +54 -53
- package/script/src/schemas/exchange/responses.js.map +1 -0
- package/script/src/schemas/explorer/requests.d.ts +5 -5
- package/script/src/schemas/explorer/requests.js +5 -4
- package/script/src/schemas/explorer/requests.js.map +1 -0
- package/script/src/schemas/explorer/responses.d.ts +10 -10
- package/script/src/schemas/explorer/responses.js +11 -10
- package/script/src/schemas/explorer/responses.js.map +1 -0
- package/script/src/schemas/info/accounts.d.ts +1042 -296
- package/script/src/schemas/info/accounts.d.ts.map +1 -1
- package/script/src/schemas/info/accounts.js +154 -109
- package/script/src/schemas/info/accounts.js.map +1 -0
- package/script/src/schemas/info/assets.d.ts +130 -101
- package/script/src/schemas/info/assets.d.ts.map +1 -1
- package/script/src/schemas/info/assets.js +69 -49
- package/script/src/schemas/info/assets.js.map +1 -0
- package/script/src/schemas/info/markets.d.ts +35 -18
- package/script/src/schemas/info/markets.d.ts.map +1 -1
- package/script/src/schemas/info/markets.js +27 -15
- package/script/src/schemas/info/markets.js.map +1 -0
- package/script/src/schemas/info/orders.d.ts +151 -151
- package/script/src/schemas/info/orders.js +36 -35
- package/script/src/schemas/info/orders.js.map +1 -0
- package/script/src/schemas/info/requests.d.ts +145 -88
- package/script/src/schemas/info/requests.d.ts.map +1 -1
- package/script/src/schemas/info/requests.js +116 -73
- package/script/src/schemas/info/requests.js.map +1 -0
- package/script/src/schemas/info/validators.d.ts +60 -39
- package/script/src/schemas/info/validators.d.ts.map +1 -1
- package/script/src/schemas/info/validators.js +40 -26
- package/script/src/schemas/info/validators.js.map +1 -0
- package/script/src/schemas/info/vaults.d.ts +59 -59
- package/script/src/schemas/info/vaults.js +19 -18
- package/script/src/schemas/info/vaults.js.map +1 -0
- package/script/src/schemas/mod.d.ts +4 -3
- package/script/src/schemas/mod.d.ts.map +1 -1
- package/script/src/schemas/mod.js +8 -5
- package/script/src/schemas/mod.js.map +1 -0
- package/script/src/schemas/subscriptions/requests.d.ts +23 -23
- package/script/src/schemas/subscriptions/requests.d.ts.map +1 -1
- package/script/src/schemas/subscriptions/requests.js +24 -23
- package/script/src/schemas/subscriptions/requests.js.map +1 -0
- package/script/src/schemas/subscriptions/responses.d.ts +547 -547
- package/script/src/schemas/subscriptions/responses.js +40 -39
- package/script/src/schemas/subscriptions/responses.js.map +1 -0
- package/script/src/signing/mod.d.ts +1 -1
- package/script/src/signing/mod.d.ts.map +1 -1
- package/script/src/signing/mod.js +4 -3
- package/script/src/signing/mod.js.map +1 -0
- package/script/src/signing/signTypedData/ethers.d.ts.map +1 -0
- package/script/src/signing/{_signTypedData → signTypedData}/ethers.js +1 -0
- package/script/src/signing/signTypedData/ethers.js.map +1 -0
- package/script/src/signing/signTypedData/mod.d.ts.map +1 -0
- package/script/src/signing/{_signTypedData → signTypedData}/mod.js +1 -0
- package/script/src/signing/signTypedData/mod.js.map +1 -0
- package/script/src/signing/signTypedData/private_key.d.ts.map +1 -0
- package/script/src/signing/{_signTypedData → signTypedData}/private_key.js +17 -15
- package/script/src/signing/signTypedData/private_key.js.map +1 -0
- package/script/src/signing/signTypedData/viem.d.ts.map +1 -0
- package/script/src/signing/{_signTypedData → signTypedData}/viem.js +1 -0
- package/script/src/signing/signTypedData/viem.js.map +1 -0
- package/script/src/transports/base.d.ts +4 -4
- package/script/src/transports/base.d.ts.map +1 -1
- package/script/src/transports/base.js +4 -3
- package/script/src/transports/base.js.map +1 -0
- package/script/src/transports/http/http_transport.d.ts +1 -1
- package/script/src/transports/http/http_transport.js +1 -0
- package/script/src/transports/http/http_transport.js.map +1 -0
- package/script/src/transports/websocket/_hyperliquid_event_target.js +1 -0
- package/script/src/transports/websocket/_hyperliquid_event_target.js.map +1 -0
- package/script/src/transports/websocket/_reconnecting_websocket.js +1 -0
- package/script/src/transports/websocket/_reconnecting_websocket.js.map +1 -0
- package/script/src/transports/websocket/_websocket_async_request.js +1 -0
- package/script/src/transports/websocket/_websocket_async_request.js.map +1 -0
- package/script/src/transports/websocket/websocket_transport.d.ts +7 -0
- package/script/src/transports/websocket/websocket_transport.d.ts.map +1 -1
- package/script/src/transports/websocket/websocket_transport.js +4 -0
- package/script/src/transports/websocket/websocket_transport.js.map +1 -0
- package/src/bin/cli.ts +481 -0
- package/src/src/_errors.ts +7 -0
- package/src/src/clients/exchange.ts +2246 -0
- package/src/src/clients/info.ts +2110 -0
- package/src/src/clients/multiSign.ts +183 -0
- package/src/src/clients/subscription.ts +841 -0
- package/src/src/mod.ts +29 -0
- package/src/src/schemas/_base.ts +82 -0
- package/src/src/schemas/exchange/requests.ts +3052 -0
- package/src/src/schemas/exchange/responses.ts +540 -0
- package/src/src/schemas/explorer/requests.ts +65 -0
- package/src/src/schemas/explorer/responses.ts +138 -0
- package/src/src/schemas/info/accounts.ts +1598 -0
- package/src/src/schemas/info/assets.ts +693 -0
- package/src/src/schemas/info/markets.ts +171 -0
- package/src/src/schemas/info/orders.ts +597 -0
- package/src/src/schemas/info/requests.ts +1401 -0
- package/src/src/schemas/info/validators.ts +297 -0
- package/src/src/schemas/info/vaults.ts +262 -0
- package/src/src/schemas/mod.ts +121 -0
- package/src/src/schemas/subscriptions/requests.ts +514 -0
- package/src/src/schemas/subscriptions/responses.ts +576 -0
- package/src/src/signing/mod.ts +572 -0
- package/src/src/signing/signTypedData/ethers.ts +59 -0
- package/src/src/signing/signTypedData/mod.ts +121 -0
- package/src/src/signing/signTypedData/private_key.ts +234 -0
- package/src/src/signing/signTypedData/viem.ts +55 -0
- package/src/src/transports/base.ts +54 -0
- package/src/src/transports/http/http_transport.ts +208 -0
- package/src/src/transports/websocket/_hyperliquid_event_target.ts +118 -0
- package/src/src/transports/websocket/_reconnecting_websocket.ts +404 -0
- package/src/src/transports/websocket/_websocket_async_request.ts +229 -0
- package/src/src/transports/websocket/websocket_transport.ts +394 -0
- package/esm/mod.d.ts +0 -20
- package/esm/mod.d.ts.map +0 -1
- package/esm/mod.js +0 -11
- package/esm/src/errors.d.ts.map +0 -1
- package/esm/src/signing/_signTypedData/ethers.d.ts.map +0 -1
- package/esm/src/signing/_signTypedData/mod.d.ts.map +0 -1
- package/esm/src/signing/_signTypedData/private_key.d.ts.map +0 -1
- package/esm/src/signing/_signTypedData/viem.d.ts.map +0 -1
- package/script/mod.d.ts +0 -20
- package/script/mod.d.ts.map +0 -1
- package/script/src/errors.d.ts.map +0 -1
- package/script/src/signing/_signTypedData/ethers.d.ts.map +0 -1
- package/script/src/signing/_signTypedData/mod.d.ts.map +0 -1
- package/script/src/signing/_signTypedData/private_key.d.ts.map +0 -1
- package/script/src/signing/_signTypedData/viem.d.ts.map +0 -1
- /package/esm/src/signing/{_signTypedData → signTypedData}/ethers.d.ts +0 -0
- /package/esm/src/signing/{_signTypedData → signTypedData}/mod.d.ts +0 -0
- /package/esm/src/signing/{_signTypedData → signTypedData}/private_key.d.ts +0 -0
- /package/esm/src/signing/{_signTypedData → signTypedData}/viem.d.ts +0 -0
- /package/script/src/signing/{_signTypedData → signTypedData}/ethers.d.ts +0 -0
- /package/script/src/signing/{_signTypedData → signTypedData}/mod.d.ts +0 -0
- /package/script/src/signing/{_signTypedData → signTypedData}/private_key.d.ts +0 -0
- /package/script/src/signing/{_signTypedData → signTypedData}/viem.d.ts +0 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import type { ReconnectingWebSocket } from "./_reconnecting_websocket.js";
|
|
2
|
+
import type { HyperliquidEventMap, HyperliquidEventTarget } from "./_hyperliquid_event_target.js";
|
|
3
|
+
import { WebSocketRequestError } from "./websocket_transport.js";
|
|
4
|
+
|
|
5
|
+
interface PostRequest {
|
|
6
|
+
method: "post";
|
|
7
|
+
id: number;
|
|
8
|
+
request: unknown;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface SubscribeUnsubscribeRequest {
|
|
12
|
+
method: "subscribe" | "unsubscribe";
|
|
13
|
+
subscription: unknown;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface PingRequest {
|
|
17
|
+
method: "ping";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Manages WebSocket requests to the Hyperliquid API.
|
|
22
|
+
* Handles request creation, sending, and mapping responses to their corresponding requests.
|
|
23
|
+
*/
|
|
24
|
+
export class WebSocketAsyncRequest {
|
|
25
|
+
protected lastId: number = 0;
|
|
26
|
+
protected queue: {
|
|
27
|
+
id: number | string;
|
|
28
|
+
// deno-lint-ignore no-explicit-any
|
|
29
|
+
resolve: (value?: any) => void;
|
|
30
|
+
// deno-lint-ignore no-explicit-any
|
|
31
|
+
reject: (reason?: any) => void;
|
|
32
|
+
}[] = [];
|
|
33
|
+
lastRequestTime: number = 0;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Creates a new WebSocket async request handler.
|
|
37
|
+
* @param socket - WebSocket connection instance for sending requests to the Hyperliquid WebSocket API
|
|
38
|
+
* @param hlEvents - Used to recognize Hyperliquid responses and match them with sent requests
|
|
39
|
+
*/
|
|
40
|
+
constructor(protected socket: ReconnectingWebSocket, hlEvents: HyperliquidEventTarget) {
|
|
41
|
+
// Monitor responses and match the pending request
|
|
42
|
+
hlEvents.addEventListener("subscriptionResponse", (event) => {
|
|
43
|
+
const detail = (event as HyperliquidEventMap["subscriptionResponse"]).detail;
|
|
44
|
+
|
|
45
|
+
// Use a stringified request as an id
|
|
46
|
+
const id = WebSocketAsyncRequest.requestToId(detail);
|
|
47
|
+
this.queue.findLast((item) => item.id === id)?.resolve(detail);
|
|
48
|
+
});
|
|
49
|
+
hlEvents.addEventListener("post", (event) => {
|
|
50
|
+
const detail = (event as HyperliquidEventMap["post"]).detail;
|
|
51
|
+
|
|
52
|
+
const data = detail.response.type === "info" ? detail.response.payload.data : detail.response.payload;
|
|
53
|
+
this.queue.findLast((item) => item.id === detail.id)?.resolve(data);
|
|
54
|
+
});
|
|
55
|
+
hlEvents.addEventListener("pong", () => {
|
|
56
|
+
this.queue.findLast((item) => item.id === "ping")?.resolve();
|
|
57
|
+
});
|
|
58
|
+
hlEvents.addEventListener("error", (event) => {
|
|
59
|
+
const detail = (event as HyperliquidEventMap["error"]).detail;
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
// Error event doesn't have an id, use original request to match
|
|
63
|
+
const request = detail.match(/{.*}/)?.[0];
|
|
64
|
+
if (!request) return;
|
|
65
|
+
|
|
66
|
+
const parsedRequest = JSON.parse(request) as Record<string, unknown>;
|
|
67
|
+
|
|
68
|
+
// For `post` requests
|
|
69
|
+
if ("id" in parsedRequest && typeof parsedRequest.id === "number") {
|
|
70
|
+
this.queue.findLast((item) => item.id === parsedRequest.id)
|
|
71
|
+
?.reject(new WebSocketRequestError(`Server error: ${detail}`, { cause: detail }));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// For `subscribe` and `unsubscribe` requests
|
|
76
|
+
if (
|
|
77
|
+
"subscription" in parsedRequest &&
|
|
78
|
+
typeof parsedRequest.subscription === "object" && parsedRequest.subscription !== null
|
|
79
|
+
) {
|
|
80
|
+
const id = WebSocketAsyncRequest.requestToId(parsedRequest);
|
|
81
|
+
this.queue.findLast((item) => item.id === id)
|
|
82
|
+
?.reject(new WebSocketRequestError(`Server error: ${detail}`, { cause: detail }));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// For `Already subscribed` and `Invalid subscription` requests
|
|
87
|
+
if (detail.startsWith("Already subscribed") || detail.startsWith("Invalid subscription")) {
|
|
88
|
+
const id = WebSocketAsyncRequest.requestToId({
|
|
89
|
+
method: "subscribe",
|
|
90
|
+
subscription: parsedRequest,
|
|
91
|
+
});
|
|
92
|
+
this.queue.findLast((item) => item.id === id)
|
|
93
|
+
?.reject(new WebSocketRequestError(`Server error: ${detail}`, { cause: detail }));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// For `Already unsubscribed` requests
|
|
97
|
+
if (detail.startsWith("Already unsubscribed")) {
|
|
98
|
+
const id = WebSocketAsyncRequest.requestToId({
|
|
99
|
+
method: "unsubscribe",
|
|
100
|
+
subscription: parsedRequest,
|
|
101
|
+
});
|
|
102
|
+
this.queue.findLast((item) => item.id === id)
|
|
103
|
+
?.reject(new WebSocketRequestError(`Server error: ${detail}`, { cause: detail }));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// For unknown requests
|
|
108
|
+
const id = WebSocketAsyncRequest.requestToId(parsedRequest);
|
|
109
|
+
this.queue.findLast((item) => item.id === id)
|
|
110
|
+
?.reject(new WebSocketRequestError(`Server error: ${detail}`, { cause: detail }));
|
|
111
|
+
} catch {
|
|
112
|
+
// Ignore JSON parsing errors
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Throws all pending requests if the connection is dropped
|
|
117
|
+
socket.addEventListener("close", () => {
|
|
118
|
+
this.queue.forEach(({ reject }) => {
|
|
119
|
+
reject(new WebSocketRequestError("WebSocket connection closed."));
|
|
120
|
+
});
|
|
121
|
+
this.queue = [];
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Sends a request to the Hyperliquid API.
|
|
127
|
+
* @returns A promise that resolves with the parsed JSON response body.
|
|
128
|
+
*/
|
|
129
|
+
async request(method: "ping", signal?: AbortSignal): Promise<void>;
|
|
130
|
+
async request<T>(method: "post" | "subscribe" | "unsubscribe", payload: unknown, signal?: AbortSignal): Promise<T>;
|
|
131
|
+
async request<T>(
|
|
132
|
+
method: "post" | "subscribe" | "unsubscribe" | "ping",
|
|
133
|
+
payload_or_signal?: unknown | AbortSignal,
|
|
134
|
+
maybeSignal?: AbortSignal,
|
|
135
|
+
): Promise<T> {
|
|
136
|
+
const payload = payload_or_signal instanceof AbortSignal ? undefined : payload_or_signal;
|
|
137
|
+
const signal = payload_or_signal instanceof AbortSignal ? payload_or_signal : maybeSignal;
|
|
138
|
+
|
|
139
|
+
// Reject the request if the signal is aborted
|
|
140
|
+
if (signal?.aborted) return Promise.reject(signal.reason);
|
|
141
|
+
// or if the WebSocket connection is permanently closed
|
|
142
|
+
if (this.socket.reconnectAbortController.signal.aborted) {
|
|
143
|
+
return Promise.reject(this.socket.reconnectAbortController.signal.reason);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Create a request
|
|
147
|
+
let id: string | number;
|
|
148
|
+
let request: SubscribeUnsubscribeRequest | PostRequest | PingRequest;
|
|
149
|
+
if (method === "post") {
|
|
150
|
+
id = ++this.lastId;
|
|
151
|
+
request = { method, id, request: payload };
|
|
152
|
+
} else if (method === "ping") {
|
|
153
|
+
id = "ping";
|
|
154
|
+
request = { method };
|
|
155
|
+
} else {
|
|
156
|
+
request = { method, subscription: payload };
|
|
157
|
+
id = WebSocketAsyncRequest.requestToId(request);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Send the request
|
|
161
|
+
this.socket.send(JSON.stringify(request), signal);
|
|
162
|
+
this.lastRequestTime = Date.now();
|
|
163
|
+
|
|
164
|
+
// Wait for a response
|
|
165
|
+
const { promise, resolve, reject } = Promise.withResolvers<T>();
|
|
166
|
+
this.queue.push({ id, resolve, reject });
|
|
167
|
+
|
|
168
|
+
const onAbort = () => reject(signal?.reason);
|
|
169
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
170
|
+
|
|
171
|
+
return await promise.finally(() => {
|
|
172
|
+
const index = this.queue.findLastIndex((item) => item.id === id);
|
|
173
|
+
if (index !== -1) this.queue.splice(index, 1);
|
|
174
|
+
|
|
175
|
+
signal?.removeEventListener("abort", onAbort);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Normalizes an object and then converts it to a string. */
|
|
180
|
+
static requestToId(value: unknown): string {
|
|
181
|
+
const lowerHex = deepLowerHex(value);
|
|
182
|
+
const sorted = deepSortKeys(lowerHex);
|
|
183
|
+
return JSON.stringify(sorted); // Also removes undefined
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Deeply converts hexadecimal strings in an object/array to lowercase. */
|
|
188
|
+
function deepLowerHex(obj: unknown): unknown {
|
|
189
|
+
if (typeof obj === "string") {
|
|
190
|
+
return /^(0X[0-9a-fA-F]*|0x[0-9a-fA-F]*[A-F][0-9a-fA-F]*)$/.test(obj) ? obj.toLowerCase() : obj;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (Array.isArray(obj)) {
|
|
194
|
+
return obj.map((value) => deepLowerHex(value));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (typeof obj === "object" && obj !== null) {
|
|
198
|
+
const result: Record<string, unknown> = {};
|
|
199
|
+
const entries = Object.entries(obj);
|
|
200
|
+
|
|
201
|
+
for (const [key, value] of entries) {
|
|
202
|
+
result[key] = deepLowerHex(value);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return obj;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** Deeply sort the keys of an object. */
|
|
212
|
+
function deepSortKeys<T>(obj: T): T {
|
|
213
|
+
if (typeof obj !== "object" || obj === null) {
|
|
214
|
+
return obj;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (Array.isArray(obj)) {
|
|
218
|
+
return obj.map(deepSortKeys) as T;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const result: Record<string, unknown> = {};
|
|
222
|
+
const keys = Object.keys(obj).sort();
|
|
223
|
+
|
|
224
|
+
for (const key of keys) {
|
|
225
|
+
result[key] = deepSortKeys((obj as Record<string, unknown>)[key]);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return result as T;
|
|
229
|
+
}
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import { TransportError } from "../base.js";
|
|
2
|
+
import type { IRequestTransport, ISubscriptionTransport, Subscription } from "../base.js";
|
|
3
|
+
import {
|
|
4
|
+
type MessageBufferStrategy,
|
|
5
|
+
ReconnectingWebSocket,
|
|
6
|
+
ReconnectingWebSocketError,
|
|
7
|
+
type ReconnectingWebSocketOptions,
|
|
8
|
+
} from "./_reconnecting_websocket.js";
|
|
9
|
+
import { HyperliquidEventTarget } from "./_hyperliquid_event_target.js";
|
|
10
|
+
import { WebSocketAsyncRequest } from "./_websocket_async_request.js";
|
|
11
|
+
|
|
12
|
+
export { type MessageBufferStrategy, ReconnectingWebSocketError, type ReconnectingWebSocketOptions };
|
|
13
|
+
|
|
14
|
+
/** Configuration options for the WebSocket transport layer. */
|
|
15
|
+
export interface WebSocketTransportOptions {
|
|
16
|
+
/**
|
|
17
|
+
* The WebSocket URL.
|
|
18
|
+
* - Mainnet:
|
|
19
|
+
* - API: `wss://api.hyperliquid.xyz/ws`
|
|
20
|
+
* - Explorer: `wss://rpc.hyperliquid.xyz/ws`
|
|
21
|
+
* - Testnet:
|
|
22
|
+
* - API: `wss://api.hyperliquid-testnet.xyz/ws`
|
|
23
|
+
* - Explorer: `wss://rpc.hyperliquid-testnet.xyz/ws`
|
|
24
|
+
* @defaultValue `wss://api.hyperliquid.xyz/ws`
|
|
25
|
+
*/
|
|
26
|
+
url?: string | URL;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Indicates this transport uses testnet endpoint.
|
|
30
|
+
* @defaultValue `false`
|
|
31
|
+
*/
|
|
32
|
+
isTestnet?: boolean;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Timeout for requests in ms.
|
|
36
|
+
* Set to `null` to disable.
|
|
37
|
+
* @defaultValue `10_000`
|
|
38
|
+
*/
|
|
39
|
+
timeout?: number | null;
|
|
40
|
+
|
|
41
|
+
/** Keep-alive configuration. */
|
|
42
|
+
keepAlive?: {
|
|
43
|
+
/**
|
|
44
|
+
* Interval between sending ping messages in ms.
|
|
45
|
+
* Set to `null` to disable.
|
|
46
|
+
* @defaultValue `30_000`
|
|
47
|
+
*/
|
|
48
|
+
interval?: number | null;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Timeout for the ping request in ms.
|
|
52
|
+
* Set to `null` to disable.
|
|
53
|
+
* @defaultValue same as {@link timeout} for requests.
|
|
54
|
+
*/
|
|
55
|
+
timeout?: number | null;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/** Reconnection policy configuration for closed connections. */
|
|
59
|
+
reconnect?: ReconnectingWebSocketOptions;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Enable automatic event resubscription after reconnection.
|
|
63
|
+
* @defaultValue `true`
|
|
64
|
+
*/
|
|
65
|
+
autoResubscribe?: boolean;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Error thrown when a WebSocket request fails. */
|
|
69
|
+
export class WebSocketRequestError extends TransportError {
|
|
70
|
+
constructor(message?: string, options?: ErrorOptions) {
|
|
71
|
+
super(message, options);
|
|
72
|
+
this.name = "WebSocketRequestError";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** WebSocket implementation of the REST and Subscription transport interfaces. */
|
|
77
|
+
export class WebSocketTransport implements IRequestTransport, ISubscriptionTransport, AsyncDisposable {
|
|
78
|
+
protected _wsRequester: WebSocketAsyncRequest;
|
|
79
|
+
protected _hlEvents: HyperliquidEventTarget;
|
|
80
|
+
protected _keepAliveTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
81
|
+
protected _subscriptions: Map<
|
|
82
|
+
string, // Unique identifier based on the payload
|
|
83
|
+
{
|
|
84
|
+
listeners: Map<
|
|
85
|
+
(data: CustomEvent) => void, // Event listener function
|
|
86
|
+
() => Promise<void> // Unsubscribe function
|
|
87
|
+
>;
|
|
88
|
+
promise: Promise<unknown>; // Subscription request promise
|
|
89
|
+
resubscribeAbortController?: AbortController; // To monitor reconnection errors
|
|
90
|
+
}
|
|
91
|
+
> = new Map();
|
|
92
|
+
protected _isReconnecting = false;
|
|
93
|
+
|
|
94
|
+
/** Indicates this transport uses testnet endpoint. */
|
|
95
|
+
isTestnet: boolean;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Request timeout in ms.
|
|
99
|
+
* Set to `null` to disable.
|
|
100
|
+
*/
|
|
101
|
+
timeout: number | null;
|
|
102
|
+
|
|
103
|
+
/** Keep-alive configuration. */
|
|
104
|
+
keepAlive: {
|
|
105
|
+
/**
|
|
106
|
+
* Interval between sending ping messages in ms.
|
|
107
|
+
* Set to `null` to disable.
|
|
108
|
+
*/
|
|
109
|
+
interval: number | null;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Timeout for the ping request in ms.
|
|
113
|
+
* Set to `null` to disable.
|
|
114
|
+
*/
|
|
115
|
+
timeout?: number | null;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/** Enable automatic resubscription after reconnection. */
|
|
119
|
+
autoResubscribe: boolean;
|
|
120
|
+
|
|
121
|
+
/** The WebSocket that is used for communication. */
|
|
122
|
+
readonly socket: ReconnectingWebSocket;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Creates a new WebSocket transport instance.
|
|
126
|
+
* @param options - Configuration options for the WebSocket transport layer.
|
|
127
|
+
*/
|
|
128
|
+
constructor(options?: WebSocketTransportOptions) {
|
|
129
|
+
this.socket = new ReconnectingWebSocket(
|
|
130
|
+
options?.url ?? "wss://api.hyperliquid.xyz/ws",
|
|
131
|
+
undefined,
|
|
132
|
+
options?.reconnect,
|
|
133
|
+
);
|
|
134
|
+
this._hlEvents = new HyperliquidEventTarget(this.socket);
|
|
135
|
+
this._wsRequester = new WebSocketAsyncRequest(this.socket, this._hlEvents);
|
|
136
|
+
|
|
137
|
+
this.isTestnet = options?.isTestnet ?? false;
|
|
138
|
+
this.timeout = options?.timeout === undefined ? 10_000 : options.timeout;
|
|
139
|
+
this.keepAlive = {
|
|
140
|
+
interval: options?.keepAlive?.interval === undefined ? 30_000 : options.keepAlive?.interval,
|
|
141
|
+
timeout: options?.keepAlive?.timeout === undefined ? this.timeout : options.keepAlive?.timeout,
|
|
142
|
+
};
|
|
143
|
+
this.autoResubscribe = options?.autoResubscribe ?? true;
|
|
144
|
+
|
|
145
|
+
// Initialize listeners
|
|
146
|
+
this.socket.addEventListener("open", () => {
|
|
147
|
+
this._keepAliveStart();
|
|
148
|
+
this._resubscribeStart();
|
|
149
|
+
});
|
|
150
|
+
this.socket.addEventListener("close", () => {
|
|
151
|
+
this._keepAliveStop();
|
|
152
|
+
this._resubscribeStop();
|
|
153
|
+
this._isReconnecting = true;
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Sends a request to the Hyperliquid API via WebSocket.
|
|
159
|
+
*
|
|
160
|
+
* Note: Explorer requests are not supported in the Hyperliquid WebSocket API.
|
|
161
|
+
*
|
|
162
|
+
* @param endpoint - The API endpoint to send the request to (`explorer` requests are not supported).
|
|
163
|
+
* @param payload - The payload to send with the request.
|
|
164
|
+
* @param signal - An {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal | AbortSignal}. If this option is set, the request can be canceled by calling {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort | abort()} on the corresponding {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/AbortController | AbortController}.
|
|
165
|
+
* @returns A promise that resolves with parsed JSON response body.
|
|
166
|
+
*
|
|
167
|
+
* @throws {WebSocketRequestError} - An error that occurs when a WebSocket request fails.
|
|
168
|
+
*/
|
|
169
|
+
async request<T>(type: "info" | "exchange", payload: unknown, signal?: AbortSignal): Promise<T> {
|
|
170
|
+
try {
|
|
171
|
+
const timeoutSignal = this.timeout ? AbortSignal.timeout(this.timeout) : undefined;
|
|
172
|
+
const combinedSignal = signal && timeoutSignal
|
|
173
|
+
? AbortSignal.any([signal, timeoutSignal])
|
|
174
|
+
: signal ?? timeoutSignal;
|
|
175
|
+
|
|
176
|
+
return await this._wsRequester.request(
|
|
177
|
+
"post",
|
|
178
|
+
{
|
|
179
|
+
type: type === "exchange" ? "action" : type,
|
|
180
|
+
payload,
|
|
181
|
+
},
|
|
182
|
+
combinedSignal,
|
|
183
|
+
);
|
|
184
|
+
} catch (error) {
|
|
185
|
+
if (error instanceof TransportError) throw error; // Re-throw known errors
|
|
186
|
+
throw new WebSocketRequestError(
|
|
187
|
+
`Unknown error while making a WebSocket request: ${error}`,
|
|
188
|
+
{ cause: error },
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Subscribes to a Hyperliquid event channel.
|
|
195
|
+
* Sends a subscription request to the server and listens for events.
|
|
196
|
+
*
|
|
197
|
+
* @param channel - The event channel to listen to.
|
|
198
|
+
* @param payload - A payload to send with the subscription request.
|
|
199
|
+
* @param listener - A function to call when the event is dispatched.
|
|
200
|
+
* @returns A promise that resolves with a {@link Subscription} object to manage the subscription lifecycle.
|
|
201
|
+
*
|
|
202
|
+
* @throws {WebSocketRequestError} - An error that occurs when a WebSocket request fails.
|
|
203
|
+
*/
|
|
204
|
+
async subscribe<T>(
|
|
205
|
+
channel: string,
|
|
206
|
+
payload: unknown,
|
|
207
|
+
listener: (data: CustomEvent<T>) => void,
|
|
208
|
+
): Promise<Subscription> {
|
|
209
|
+
try {
|
|
210
|
+
// Create a unique identifier for the subscription
|
|
211
|
+
const id = WebSocketAsyncRequest.requestToId(payload);
|
|
212
|
+
|
|
213
|
+
// Initialize new subscription, if it doesn't exist
|
|
214
|
+
let subscription = this._subscriptions.get(id);
|
|
215
|
+
if (!subscription) {
|
|
216
|
+
// Send subscription request
|
|
217
|
+
const promise = this._wsRequester.request("subscribe", payload);
|
|
218
|
+
|
|
219
|
+
// Cache subscription info
|
|
220
|
+
subscription = {
|
|
221
|
+
listeners: new Map(),
|
|
222
|
+
promise,
|
|
223
|
+
resubscribeAbortController: new AbortController(),
|
|
224
|
+
};
|
|
225
|
+
this._subscriptions.set(id, subscription);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Initialize new listener, if it doesn't exist
|
|
229
|
+
let unsubscribe = subscription.listeners.get(listener);
|
|
230
|
+
if (!unsubscribe) {
|
|
231
|
+
// Create new unsubscribe function
|
|
232
|
+
unsubscribe = async () => {
|
|
233
|
+
try {
|
|
234
|
+
// Remove listener and cleanup
|
|
235
|
+
this._hlEvents.removeEventListener(channel, listener as EventListener);
|
|
236
|
+
const subscription = this._subscriptions.get(id);
|
|
237
|
+
subscription?.listeners.delete(listener);
|
|
238
|
+
|
|
239
|
+
// If no listeners remain, remove subscription entirely
|
|
240
|
+
if (subscription?.listeners.size === 0) {
|
|
241
|
+
// Cleanup subscription
|
|
242
|
+
this._subscriptions.delete(id);
|
|
243
|
+
|
|
244
|
+
// If the socket is open, send unsubscription request
|
|
245
|
+
if (this.socket.readyState === ReconnectingWebSocket.OPEN) {
|
|
246
|
+
await this._wsRequester.request("unsubscribe", payload);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
} catch (error) {
|
|
250
|
+
if (error instanceof TransportError) throw error; // Re-throw known errors
|
|
251
|
+
throw new WebSocketRequestError(
|
|
252
|
+
`Unknown error while unsubscribing from a WebSocket channel: ${error}`,
|
|
253
|
+
{ cause: error },
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// Add listener and cache unsubscribe function
|
|
259
|
+
this._hlEvents.addEventListener(channel, listener as EventListener);
|
|
260
|
+
subscription.listeners.set(listener, unsubscribe);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Wait for the initial subscription request to complete
|
|
264
|
+
await subscription.promise;
|
|
265
|
+
|
|
266
|
+
// Return subscription control object
|
|
267
|
+
return {
|
|
268
|
+
unsubscribe,
|
|
269
|
+
resubscribeSignal: subscription.resubscribeAbortController?.signal,
|
|
270
|
+
};
|
|
271
|
+
} catch (error) {
|
|
272
|
+
if (error instanceof TransportError) throw error; // Re-throw known errors
|
|
273
|
+
throw new WebSocketRequestError(
|
|
274
|
+
`Unknown error while subscribing to a WebSocket channel: ${error}`,
|
|
275
|
+
{ cause: error },
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Waits until the WebSocket connection is ready.
|
|
282
|
+
* @param signal - An {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal | AbortSignal}. If this option is set, the promise can be canceled by calling {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort | abort()} on the corresponding {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/AbortController | AbortController}.
|
|
283
|
+
* @returns A promise that resolves when the connection is ready.
|
|
284
|
+
*/
|
|
285
|
+
ready(signal?: AbortSignal): Promise<void> {
|
|
286
|
+
return new Promise((resolve, reject) => {
|
|
287
|
+
const combinedSignal = signal
|
|
288
|
+
? AbortSignal.any([this.socket.reconnectAbortController.signal, signal])
|
|
289
|
+
: this.socket.reconnectAbortController.signal;
|
|
290
|
+
|
|
291
|
+
if (combinedSignal.aborted) return reject(combinedSignal.reason);
|
|
292
|
+
if (this.socket.readyState === ReconnectingWebSocket.OPEN) return resolve();
|
|
293
|
+
|
|
294
|
+
const handleOpen = () => {
|
|
295
|
+
combinedSignal.removeEventListener("abort", handleAbort);
|
|
296
|
+
resolve();
|
|
297
|
+
};
|
|
298
|
+
const handleAbort = () => {
|
|
299
|
+
this.socket.removeEventListener("open", handleOpen);
|
|
300
|
+
reject(combinedSignal.reason);
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
this.socket.addEventListener("open", handleOpen, { once: true });
|
|
304
|
+
combinedSignal.addEventListener("abort", handleAbort, { once: true });
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Closes the WebSocket connection and waits until it is fully closed.
|
|
310
|
+
* @param signal - An {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal | AbortSignal}. If this option is set, the promise can be canceled by calling {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort | abort()} on the corresponding {@linkcode https://developer.mozilla.org/en-US/docs/Web/API/AbortController | AbortController}.
|
|
311
|
+
* @returns A promise that resolves when the connection is fully closed.
|
|
312
|
+
*/
|
|
313
|
+
close(signal?: AbortSignal): Promise<void> {
|
|
314
|
+
return new Promise((resolve, reject) => {
|
|
315
|
+
if (signal?.aborted) return reject(signal.reason);
|
|
316
|
+
if (this.socket.readyState === ReconnectingWebSocket.CLOSED) return resolve();
|
|
317
|
+
|
|
318
|
+
const handleClose = () => {
|
|
319
|
+
signal?.removeEventListener("abort", handleAbort);
|
|
320
|
+
resolve();
|
|
321
|
+
};
|
|
322
|
+
const handleAbort = () => {
|
|
323
|
+
this.socket.removeEventListener("close", handleClose);
|
|
324
|
+
reject(signal?.reason);
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
this.socket.addEventListener("close", handleClose, { once: true });
|
|
328
|
+
signal?.addEventListener("abort", handleAbort, { once: true });
|
|
329
|
+
|
|
330
|
+
this.socket.close();
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/** Keep the connection alive. Sends ping only when necessary. */
|
|
335
|
+
protected _keepAliveStart(): void {
|
|
336
|
+
if (this.keepAlive.interval === null || this._keepAliveTimeout) return;
|
|
337
|
+
|
|
338
|
+
const tick = async () => {
|
|
339
|
+
if (
|
|
340
|
+
this.socket.readyState !== ReconnectingWebSocket.OPEN || !this._keepAliveTimeout ||
|
|
341
|
+
this.keepAlive.interval === null
|
|
342
|
+
) return;
|
|
343
|
+
|
|
344
|
+
// Check if the last request was sent more than the keep-alive interval ago
|
|
345
|
+
if (Date.now() - this._wsRequester.lastRequestTime >= this.keepAlive.interval) {
|
|
346
|
+
const timeoutSignal = this.keepAlive.timeout ? AbortSignal.timeout(this.keepAlive.timeout) : undefined;
|
|
347
|
+
await this._wsRequester.request("ping", timeoutSignal)
|
|
348
|
+
.catch(() => undefined); // Ignore errors
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Schedule the next ping
|
|
352
|
+
if (
|
|
353
|
+
this.socket.readyState === ReconnectingWebSocket.OPEN && this._keepAliveTimeout &&
|
|
354
|
+
this.keepAlive.interval !== null
|
|
355
|
+
) {
|
|
356
|
+
const nextDelay = this.keepAlive.interval - (Date.now() - this._wsRequester.lastRequestTime);
|
|
357
|
+
this._keepAliveTimeout = setTimeout(tick, nextDelay);
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
this._keepAliveTimeout = setTimeout(tick, this.keepAlive.interval);
|
|
362
|
+
}
|
|
363
|
+
protected _keepAliveStop(): void {
|
|
364
|
+
if (this._keepAliveTimeout !== null) {
|
|
365
|
+
clearTimeout(this._keepAliveTimeout);
|
|
366
|
+
this._keepAliveTimeout = null;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/** Resubscribe to all existing subscriptions if auto-resubscribe is enabled. */
|
|
371
|
+
protected _resubscribeStart(): void {
|
|
372
|
+
if (this.autoResubscribe && this._isReconnecting) {
|
|
373
|
+
for (const [id, subscriptionInfo] of this._subscriptions.entries()) {
|
|
374
|
+
subscriptionInfo.promise = this._wsRequester.request("subscribe", JSON.parse(id))
|
|
375
|
+
.catch((error) => {
|
|
376
|
+
subscriptionInfo.resubscribeAbortController?.abort(error);
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
protected _resubscribeStop(): void {
|
|
382
|
+
if (!this.autoResubscribe || this.socket.reconnectAbortController.signal.aborted) {
|
|
383
|
+
for (const subscriptionInfo of this._subscriptions.values()) {
|
|
384
|
+
for (const [_, unsubscribe] of subscriptionInfo.listeners) {
|
|
385
|
+
unsubscribe(); // does not cause an error if used when the connection is closed
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
async [Symbol.asyncDispose](): Promise<void> {
|
|
392
|
+
await this.close();
|
|
393
|
+
}
|
|
394
|
+
}
|
package/esm/mod.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export * from "./src/errors.js";
|
|
2
|
-
export * from "./src/transports/base.js";
|
|
3
|
-
export type { AbstractWallet } from "./src/signing/mod.js";
|
|
4
|
-
export * from "./src/clients/exchange.js";
|
|
5
|
-
export * from "./src/clients/info.js";
|
|
6
|
-
export * from "./src/clients/multiSign.js";
|
|
7
|
-
export * from "./src/clients/subscription.js";
|
|
8
|
-
export * from "./src/transports/http/http_transport.js";
|
|
9
|
-
export * from "./src/transports/websocket/websocket_transport.js";
|
|
10
|
-
export type { OrderParams, Signature } from "./src/schemas/exchange/requests.js";
|
|
11
|
-
export type * from "./src/schemas/exchange/responses.js";
|
|
12
|
-
export type * from "./src/schemas/explorer/responses.js";
|
|
13
|
-
export type * from "./src/schemas/info/accounts.js";
|
|
14
|
-
export type * from "./src/schemas/info/assets.js";
|
|
15
|
-
export type * from "./src/schemas/info/validators.js";
|
|
16
|
-
export type * from "./src/schemas/info/markets.js";
|
|
17
|
-
export type * from "./src/schemas/info/orders.js";
|
|
18
|
-
export type * from "./src/schemas/info/vaults.js";
|
|
19
|
-
export type * from "./src/schemas/subscriptions/responses.js";
|
|
20
|
-
//# sourceMappingURL=mod.d.ts.map
|
package/esm/mod.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AAGzC,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,+BAA+B,CAAC;AAG9C,cAAc,yCAAyC,CAAC;AACxD,cAAc,mDAAmD,CAAC;AAGlE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AACjF,mBAAmB,qCAAqC,CAAC;AACzD,mBAAmB,qCAAqC,CAAC;AACzD,mBAAmB,gCAAgC,CAAC;AACpD,mBAAmB,8BAA8B,CAAC;AAClD,mBAAmB,kCAAkC,CAAC;AACtD,mBAAmB,+BAA+B,CAAC;AACnD,mBAAmB,8BAA8B,CAAC;AAClD,mBAAmB,8BAA8B,CAAC;AAClD,mBAAmB,0CAA0C,CAAC"}
|
package/esm/mod.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// Base interfaces
|
|
2
|
-
export * from "./src/errors.js";
|
|
3
|
-
export * from "./src/transports/base.js";
|
|
4
|
-
// Clients
|
|
5
|
-
export * from "./src/clients/exchange.js";
|
|
6
|
-
export * from "./src/clients/info.js";
|
|
7
|
-
export * from "./src/clients/multiSign.js";
|
|
8
|
-
export * from "./src/clients/subscription.js";
|
|
9
|
-
// Transports
|
|
10
|
-
export * from "./src/transports/http/http_transport.js";
|
|
11
|
-
export * from "./src/transports/websocket/websocket_transport.js";
|
package/esm/src/errors.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/src/errors.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,qBAAa,gBAAiB,SAAQ,KAAK;gBAC3B,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIvD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ethers.d.ts","sourceRoot":"","sources":["../../../../src/src/signing/_signTypedData/ethers.ts"],"names":[],"mappings":"AAAA,6GAA6G;AAC7G,MAAM,WAAW,sBAAsB;IACnC,aAAa,CACT,MAAM,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,iBAAiB,EAAE,MAAM,CAAC;KAC7B,EACD,KAAK,EAAE;QACH,CAAC,GAAG,EAAE,MAAM,GAAG;YACX,IAAI,EAAE,MAAM,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;SAChB,EAAE,CAAC;KACP,EACD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,UAAU,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,EACH;QAAE,UAAU,IAAI,OAAO,CAAC;YAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,GACvD,IAAI,CAAC;CACd;AAED,sGAAsG;AACtG,MAAM,WAAW,sBAAsB;IACnC,cAAc,CACV,MAAM,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,iBAAiB,EAAE,MAAM,CAAC;KAC7B,EACD,KAAK,EAAE;QACH,CAAC,GAAG,EAAE,MAAM,GAAG;YACX,IAAI,EAAE,MAAM,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;SAChB,EAAE,CAAC;KACP,EACD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,UAAU,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,EACH;QAAE,UAAU,IAAI,OAAO,CAAC;YAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,GACvD,IAAI,CAAC;CACd;AAED,8DAA8D;AAC9D,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,sBAAsB,CAI1F;AAED,iEAAiE;AACjE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,sBAAsB,CAI1F"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../../../src/src/signing/_signTypedData/mod.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAG9B,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,KAAK,0BAA0B,EAAE,KAAK,wBAAwB,EAAwB,MAAM,WAAW,CAAC;AAEjH,gEAAgE;AAChE,MAAM,MAAM,cAAc,GACpB,KAAK,MAAM,EAAE,GACb,0BAA0B,GAC1B,wBAAwB,GACxB,sBAAsB,GACtB,sBAAsB,CAAC;AAE7B,2EAA2E;AAC3E,MAAM,WAAW,SAAS;IACtB,iDAAiD;IACjD,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IACjB,kDAAkD;IAClD,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IACjB,0BAA0B;IAC1B,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC;CACd;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACtC,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,iBAAiB,EAAE,KAAK,MAAM,EAAE,CAAC;KACpC,CAAC;IACF,KAAK,EAAE;QACH,CAAC,GAAG,EAAE,MAAM,GAAG;YACX,IAAI,EAAE,MAAM,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;SAChB,EAAE,CAAC;KACP,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,GAAG,OAAO,CAAC,SAAS,CAAC,CA8BrB;AASD,sCAAsC;AACtC,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,CAkBrF;AAED,wDAAwD;AACxD,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,CAgBrF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"private_key.d.ts","sourceRoot":"","sources":["../../../../src/src/signing/_signTypedData/private_key.ts"],"names":[],"mappings":"AAGA,UAAU,KAAK;IACX,CAAC,IAAI,EAAE,MAAM,GAAG;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KAChB,EAAE,CAAC;CACP;AAED,UAAU,MAAO,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,MAAM,EAAE,CAAC;IACnD,iBAAiB,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IAClC,IAAI,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;CACxB;AAED,2CAA2C;AAC3C,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,GAAG,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,CAkBzB;AAsKD,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,OAAO,GAAG,UAAU,IAAI,MAAM,CAG3E;AAED,qDAAqD;AACrD,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,CAYrE"}
|