@rabby-wallet/hyperliquid-sdk 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -18,8 +18,10 @@ export declare class WebSocketClient {
|
|
|
18
18
|
private readonly url;
|
|
19
19
|
private readonly config;
|
|
20
20
|
private subscriptions;
|
|
21
|
+
private activeSubscriptions;
|
|
21
22
|
private reconnectAttempts;
|
|
22
23
|
private isConnecting;
|
|
24
|
+
private isManualDisconnect;
|
|
23
25
|
private pendingSubscriptions;
|
|
24
26
|
private heartbeatInterval;
|
|
25
27
|
private readonly HEARTBEAT_INTERVAL;
|
|
@@ -90,4 +92,12 @@ export declare class WebSocketClient {
|
|
|
90
92
|
* Get current connection state
|
|
91
93
|
*/
|
|
92
94
|
get readyState(): number;
|
|
95
|
+
/**
|
|
96
|
+
* Get list of active subscription types
|
|
97
|
+
*/
|
|
98
|
+
getActiveSubscriptions(): string[];
|
|
99
|
+
/**
|
|
100
|
+
* Reset reconnection attempts and enable auto-reconnect
|
|
101
|
+
*/
|
|
102
|
+
resetReconnectState(): void;
|
|
93
103
|
}
|
|
@@ -18,8 +18,10 @@ class WebSocketClient {
|
|
|
18
18
|
constructor(config) {
|
|
19
19
|
this.ws = null;
|
|
20
20
|
this.subscriptions = new Map();
|
|
21
|
+
this.activeSubscriptions = new Map();
|
|
21
22
|
this.reconnectAttempts = 0;
|
|
22
23
|
this.isConnecting = false;
|
|
24
|
+
this.isManualDisconnect = false; // 标记是否为主动断开连接
|
|
23
25
|
this.pendingSubscriptions = [];
|
|
24
26
|
this.heartbeatInterval = null;
|
|
25
27
|
this.HEARTBEAT_INTERVAL = 50000; // 50秒发送一次心跳,小于60秒超时
|
|
@@ -67,6 +69,7 @@ class WebSocketClient {
|
|
|
67
69
|
this.ws.onopen = () => {
|
|
68
70
|
this.isConnecting = false;
|
|
69
71
|
this.reconnectAttempts = 0;
|
|
72
|
+
this.isManualDisconnect = false; // 重置手动断开标志
|
|
70
73
|
console.log('hyperliquid sdk WebSocket connected');
|
|
71
74
|
// Start heartbeat
|
|
72
75
|
this.startHeartbeat();
|
|
@@ -75,10 +78,12 @@ class WebSocketClient {
|
|
|
75
78
|
var _a;
|
|
76
79
|
if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
|
|
77
80
|
this.subscriptions.set(message.subscription.type, callback);
|
|
81
|
+
this.activeSubscriptions.set(message.subscription.type, { message, callback });
|
|
78
82
|
this.ws.send(JSON.stringify(Object.assign(Object.assign({}, message), { method: 'subscribe' })));
|
|
79
83
|
}
|
|
80
84
|
});
|
|
81
85
|
this.pendingSubscriptions = [];
|
|
86
|
+
console.log(`Resubscribed to ${this.activeSubscriptions.size} channels after reconnection`);
|
|
82
87
|
resolve();
|
|
83
88
|
};
|
|
84
89
|
this.ws.onmessage = (event) => {
|
|
@@ -104,10 +109,28 @@ class WebSocketClient {
|
|
|
104
109
|
console.log('WebSocket disconnected');
|
|
105
110
|
// Stop heartbeat
|
|
106
111
|
this.stopHeartbeat();
|
|
107
|
-
if
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
// Only attempt reconnection if it's not a manual disconnect
|
|
113
|
+
if (!this.isManualDisconnect && this.config.autoReconnect) {
|
|
114
|
+
// Save current active subscriptions to pending for reconnection
|
|
115
|
+
if (this.activeSubscriptions.size > 0) {
|
|
116
|
+
this.activeSubscriptions.forEach((subscription, type) => {
|
|
117
|
+
const existingPending = this.pendingSubscriptions.find(sub => sub.message.subscription.type === type);
|
|
118
|
+
if (!existingPending) {
|
|
119
|
+
this.pendingSubscriptions.push(subscription);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
if (this.reconnectAttempts < this.config.maxReconnectAttempts) {
|
|
124
|
+
this.reconnectAttempts++;
|
|
125
|
+
console.log(`Reconnecting... (${this.reconnectAttempts}/${this.config.maxReconnectAttempts})`);
|
|
126
|
+
setTimeout(() => this.connect(), this.config.reconnectDelay);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
console.error('Max reconnection attempts reached. Connection failed.');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else if (this.isManualDisconnect) {
|
|
133
|
+
this.isManualDisconnect = false; // Reset flag
|
|
111
134
|
}
|
|
112
135
|
};
|
|
113
136
|
this.ws.onerror = (error) => {
|
|
@@ -144,26 +167,31 @@ class WebSocketClient {
|
|
|
144
167
|
* Disconnect from the WebSocket
|
|
145
168
|
*/
|
|
146
169
|
disconnect() {
|
|
170
|
+
this.isManualDisconnect = true; // 标记为主动断开
|
|
147
171
|
this.stopHeartbeat();
|
|
148
172
|
if (this.ws) {
|
|
149
173
|
this.ws.close();
|
|
150
174
|
this.ws = null;
|
|
151
175
|
}
|
|
152
176
|
this.subscriptions.clear();
|
|
177
|
+
this.activeSubscriptions.clear();
|
|
153
178
|
this.pendingSubscriptions = [];
|
|
179
|
+
this.reconnectAttempts = 0; // 重置重连计数
|
|
154
180
|
}
|
|
155
181
|
/**
|
|
156
182
|
* Subscribe to a channel
|
|
157
183
|
*/
|
|
158
184
|
subscribe(message, callback) {
|
|
159
185
|
var _a;
|
|
186
|
+
const subscriptionData = { message, callback };
|
|
160
187
|
if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
|
|
161
188
|
this.subscriptions.set(message.subscription.type, callback);
|
|
189
|
+
this.activeSubscriptions.set(message.subscription.type, subscriptionData);
|
|
162
190
|
this.ws.send(JSON.stringify(Object.assign(Object.assign({}, message), { method: 'subscribe' })));
|
|
163
191
|
}
|
|
164
192
|
else {
|
|
165
193
|
// Store pending subscription for when connection is established
|
|
166
|
-
this.pendingSubscriptions.push(
|
|
194
|
+
this.pendingSubscriptions.push(subscriptionData);
|
|
167
195
|
// Auto-connect if not connected
|
|
168
196
|
if (!this.isConnecting && (!this.ws || this.ws.readyState === WebSocket.CLOSED)) {
|
|
169
197
|
this.connect().catch(console.error);
|
|
@@ -172,12 +200,14 @@ class WebSocketClient {
|
|
|
172
200
|
return {
|
|
173
201
|
unsubscribe: () => {
|
|
174
202
|
var _a;
|
|
175
|
-
|
|
203
|
+
const type = message.subscription.type;
|
|
204
|
+
this.subscriptions.delete(type);
|
|
205
|
+
this.activeSubscriptions.delete(type);
|
|
176
206
|
if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
|
|
177
207
|
this.ws.send(JSON.stringify(Object.assign(Object.assign({}, message), { method: 'unsubscribe' })));
|
|
178
208
|
}
|
|
179
209
|
// Remove from pending subscriptions
|
|
180
|
-
this.pendingSubscriptions = this.pendingSubscriptions.filter(sub => sub.message.subscription.type !==
|
|
210
|
+
this.pendingSubscriptions = this.pendingSubscriptions.filter(sub => sub.message.subscription.type !== type);
|
|
181
211
|
},
|
|
182
212
|
};
|
|
183
213
|
}
|
|
@@ -280,5 +310,18 @@ class WebSocketClient {
|
|
|
280
310
|
var _a, _b;
|
|
281
311
|
return (_b = (_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) !== null && _b !== void 0 ? _b : WebSocket.CLOSED;
|
|
282
312
|
}
|
|
313
|
+
/**
|
|
314
|
+
* Get list of active subscription types
|
|
315
|
+
*/
|
|
316
|
+
getActiveSubscriptions() {
|
|
317
|
+
return Array.from(this.activeSubscriptions.keys());
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Reset reconnection attempts and enable auto-reconnect
|
|
321
|
+
*/
|
|
322
|
+
resetReconnectState() {
|
|
323
|
+
this.reconnectAttempts = 0;
|
|
324
|
+
this.isManualDisconnect = false;
|
|
325
|
+
}
|
|
283
326
|
}
|
|
284
327
|
exports.WebSocketClient = WebSocketClient;
|