@orderly.network/net 1.0.112-alpha.2 → 1.0.112
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/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -2
- package/.turbo/turbo-build.log +0 -22
- package/CHANGELOG.md +0 -757
- package/__test__/createWebSocket.test.ts +0 -11
- package/__test__/fetch.test.ts +0 -13
- package/babel.config.js +0 -6
- package/src/constants.ts +0 -1
- package/src/errors/apiError.ts +0 -6
- package/src/fetch/index.ts +0 -130
- package/src/index.ts +0 -6
- package/src/sum.test.ts +0 -5
- package/src/sum.ts +0 -1
- package/src/types/ws.ts +0 -13
- package/src/version.ts +0 -14
- package/src/ws/handler/baseHandler.ts +0 -7
- package/src/ws/handler/handler.ts +0 -17
- package/src/ws/handler/ping.ts +0 -7
- package/src/ws/ws.ts +0 -734
- package/tsconfig.json +0 -13
- package/tsup.config.ts +0 -11
package/src/ws/ws.ts
DELETED
|
@@ -1,734 +0,0 @@
|
|
|
1
|
-
import { messageHandlers } from "./handler/handler";
|
|
2
|
-
|
|
3
|
-
export type NetworkId = "testnet" | "mainnet";
|
|
4
|
-
|
|
5
|
-
export type WSOptions = {
|
|
6
|
-
privateUrl: string;
|
|
7
|
-
publicUrl: string;
|
|
8
|
-
networkId?: NetworkId;
|
|
9
|
-
accountId?: string;
|
|
10
|
-
|
|
11
|
-
onSigntureRequest?: (accountId: string) => Promise<any>;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export type unsubscribe = () => void;
|
|
15
|
-
|
|
16
|
-
export enum WebSocketEvent {
|
|
17
|
-
OPEN = "open",
|
|
18
|
-
CLOSE = "close",
|
|
19
|
-
ERROR = "error",
|
|
20
|
-
MESSAGE = "message",
|
|
21
|
-
CONNECTING = "connecting",
|
|
22
|
-
RECONNECTING = "reconnecting",
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type MessageParams = {
|
|
26
|
-
event: string;
|
|
27
|
-
topic: string;
|
|
28
|
-
|
|
29
|
-
onMessage?: (message: any) => any;
|
|
30
|
-
|
|
31
|
-
params?: any;
|
|
32
|
-
// [key: string]: any;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
type WSMessageHandler = {
|
|
36
|
-
onMessage: (message: any) => void;
|
|
37
|
-
onError?: (error: any) => void;
|
|
38
|
-
onClose?: (event: any) => void;
|
|
39
|
-
onUnsubscribe: (event: any) => any;
|
|
40
|
-
formatter?: (message: any) => any;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
type Topics = {
|
|
44
|
-
params: MessageParams;
|
|
45
|
-
isPrivate?: boolean;
|
|
46
|
-
isOnce?: boolean;
|
|
47
|
-
callback: WSMessageHandler[];
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const defaultMessageFormatter = (message: any) => message.data;
|
|
51
|
-
const COMMON_ID = "OqdphuyCtYWxwzhxyLLjOWNdFP7sQt8RPWzmb5xY";
|
|
52
|
-
|
|
53
|
-
const TIME_OUT = 1000 * 60 * 2;
|
|
54
|
-
const CONNECT_LIMIT = 5;
|
|
55
|
-
|
|
56
|
-
export class WS {
|
|
57
|
-
private _publicSocket!: WebSocket;
|
|
58
|
-
private privateSocket?: WebSocket;
|
|
59
|
-
|
|
60
|
-
private _eventContainer: Map<string, Set<Function>> = new Map();
|
|
61
|
-
|
|
62
|
-
private publicIsReconnecting: boolean = false;
|
|
63
|
-
private privateIsReconnecting: boolean = false;
|
|
64
|
-
|
|
65
|
-
private reconnectInterval: number = 1000;
|
|
66
|
-
|
|
67
|
-
private authenticated: boolean = false;
|
|
68
|
-
|
|
69
|
-
private _pendingPrivateSubscribe: any[][] = [];
|
|
70
|
-
private _pendingPublicSubscribe: any[][] = [];
|
|
71
|
-
|
|
72
|
-
// all message handlers
|
|
73
|
-
private _eventHandlers: Map<string, Topics> = new Map();
|
|
74
|
-
private _eventPrivateHandlers: Map<string, Topics> = new Map();
|
|
75
|
-
|
|
76
|
-
private _publicHeartbeatTime?: number;
|
|
77
|
-
private _privateHeartbeatTime?: number;
|
|
78
|
-
|
|
79
|
-
private _publicRetryCount: number = 0;
|
|
80
|
-
private _privateRetryCount: number = 0;
|
|
81
|
-
|
|
82
|
-
constructor(private options: WSOptions) {
|
|
83
|
-
this.createPublicSC(options);
|
|
84
|
-
|
|
85
|
-
if (!!options.accountId) {
|
|
86
|
-
this.createPrivateSC(options);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
this.bindEvents();
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
private bindEvents() {
|
|
93
|
-
if (typeof document !== "undefined") {
|
|
94
|
-
document.addEventListener(
|
|
95
|
-
"visibilitychange",
|
|
96
|
-
this.onVisibilityChange.bind(this)
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (typeof window !== "undefined") {
|
|
101
|
-
window.addEventListener("online", this.onNetworkStatusChange.bind(this));
|
|
102
|
-
// window.addEventListener("offline", this.onNetworkStatusChange);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
private onVisibilityChange() {
|
|
107
|
-
if (document.visibilityState === "visible") {
|
|
108
|
-
this.checkSocketStatus();
|
|
109
|
-
}
|
|
110
|
-
// else {
|
|
111
|
-
// this.publicSocket.close();
|
|
112
|
-
// this.privateSocket?.close();
|
|
113
|
-
// }
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
private onNetworkStatusChange() {
|
|
117
|
-
if (navigator.onLine) {
|
|
118
|
-
this.checkSocketStatus();
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Determine the current connection status,
|
|
124
|
-
* 1. If it is disconnected, reconnect
|
|
125
|
-
* 2. If no message is received for too long, disconnect and reconnect actively
|
|
126
|
-
* 3. When returning from the background and the network status changes, the following process is followed
|
|
127
|
-
*/
|
|
128
|
-
private checkSocketStatus() {
|
|
129
|
-
const now = Date.now();
|
|
130
|
-
|
|
131
|
-
//
|
|
132
|
-
// "👀👀 checkNetworkStatus 👀👀",
|
|
133
|
-
// this._publicHeartbeatTime,
|
|
134
|
-
// this._privateHeartbeatTime,
|
|
135
|
-
// now,
|
|
136
|
-
// this.publicSocket.readyState,
|
|
137
|
-
// this.privateSocket?.readyState
|
|
138
|
-
// );
|
|
139
|
-
|
|
140
|
-
// check the last time
|
|
141
|
-
// If the view is not visible, do not process it
|
|
142
|
-
if (document.visibilityState !== "visible") return;
|
|
143
|
-
// If the network is not available, do not process it
|
|
144
|
-
if (!navigator.onLine) return;
|
|
145
|
-
|
|
146
|
-
// 如果已断开,则重连
|
|
147
|
-
// public
|
|
148
|
-
if (!this.publicIsReconnecting) {
|
|
149
|
-
if (this._publicSocket.readyState === WebSocket.CLOSED) {
|
|
150
|
-
this.reconnectPublic();
|
|
151
|
-
} else {
|
|
152
|
-
if (now - this._publicHeartbeatTime! > TIME_OUT) {
|
|
153
|
-
//unsubscribe all public topic
|
|
154
|
-
this._publicSocket.close();
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (!this.privateIsReconnecting) {
|
|
160
|
-
// private
|
|
161
|
-
if (this.privateSocket?.readyState === WebSocket.CLOSED) {
|
|
162
|
-
this.reconnectPrivate();
|
|
163
|
-
} else {
|
|
164
|
-
if (
|
|
165
|
-
this._privateHeartbeatTime &&
|
|
166
|
-
now - this._privateHeartbeatTime! > TIME_OUT
|
|
167
|
-
) {
|
|
168
|
-
// unsubscribe all private topic
|
|
169
|
-
this.privateSocket?.close();
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
public openPrivate(accountId: string) {
|
|
176
|
-
if (this.privateSocket?.readyState === WebSocket.OPEN) {
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
this.createPrivateSC({
|
|
180
|
-
...this.options,
|
|
181
|
-
accountId,
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
public closePrivate() {
|
|
186
|
-
this.authenticated = false;
|
|
187
|
-
this._pendingPrivateSubscribe = [];
|
|
188
|
-
|
|
189
|
-
this._eventPrivateHandlers.clear();
|
|
190
|
-
|
|
191
|
-
this.privateSocket?.close();
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
private createPublicSC(options: WSOptions) {
|
|
195
|
-
if (this._publicSocket && this._publicSocket.readyState === WebSocket.OPEN)
|
|
196
|
-
return;
|
|
197
|
-
this._publicSocket = new WebSocket(
|
|
198
|
-
`${this.options.publicUrl}/ws/stream/${COMMON_ID}`
|
|
199
|
-
);
|
|
200
|
-
this._publicSocket.onopen = this.onOpen.bind(this);
|
|
201
|
-
// this.publicSocket.onmessage = this.onPublicMessage.bind(this);
|
|
202
|
-
this._publicSocket.addEventListener(
|
|
203
|
-
"message",
|
|
204
|
-
this.onPublicMessage.bind(this)
|
|
205
|
-
);
|
|
206
|
-
this._publicSocket.addEventListener("close", this.onPublicClose.bind(this));
|
|
207
|
-
this._publicSocket.addEventListener("error", this.onPublicError.bind(this));
|
|
208
|
-
// this.publicSocket.onclose = this.onPublicClose.bind(this);
|
|
209
|
-
// this.publicSocket.onerror = this.onPublicError.bind(this);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
private createPrivateSC(options: WSOptions) {
|
|
213
|
-
if (this.privateSocket && this.privateSocket.readyState === WebSocket.OPEN)
|
|
214
|
-
return;
|
|
215
|
-
|
|
216
|
-
this.options = options;
|
|
217
|
-
|
|
218
|
-
this.privateSocket = new WebSocket(
|
|
219
|
-
`${this.options.privateUrl}/v2/ws/private/stream/${options.accountId}`
|
|
220
|
-
);
|
|
221
|
-
this.privateSocket.onopen = this.onPrivateOpen.bind(this);
|
|
222
|
-
this.privateSocket.onmessage = this.onPrivateMessage.bind(this);
|
|
223
|
-
this.privateSocket.onclose = this.onPrivateClose.bind(this);
|
|
224
|
-
this.privateSocket.onerror = this.onPrivateError.bind(this);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
private onOpen(event: Event) {
|
|
228
|
-
//
|
|
229
|
-
if (this._pendingPublicSubscribe.length > 0) {
|
|
230
|
-
this._pendingPublicSubscribe.forEach(([params, cb, isOnce]) => {
|
|
231
|
-
this.subscribe(params, cb, isOnce);
|
|
232
|
-
});
|
|
233
|
-
this._pendingPublicSubscribe = [];
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
this.publicIsReconnecting = false;
|
|
237
|
-
this._publicRetryCount = 0;
|
|
238
|
-
|
|
239
|
-
this.emit("status:change", { type: WebSocketEvent.OPEN, isPrivate: false });
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
private onPrivateOpen(event: Event) {
|
|
243
|
-
//auth
|
|
244
|
-
this.authenticate(this.options.accountId!);
|
|
245
|
-
this.privateIsReconnecting = false;
|
|
246
|
-
this._privateRetryCount = 0;
|
|
247
|
-
|
|
248
|
-
this.emit("status:change", { type: WebSocketEvent.OPEN, isPrivate: true });
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
private onMessage(
|
|
252
|
-
event: MessageEvent,
|
|
253
|
-
socket: WebSocket,
|
|
254
|
-
handlerMap: Map<string, Topics>
|
|
255
|
-
) {
|
|
256
|
-
try {
|
|
257
|
-
const message = JSON.parse(event.data);
|
|
258
|
-
|
|
259
|
-
const commoneHandler = messageHandlers.get(message.event);
|
|
260
|
-
|
|
261
|
-
if (message.event === "auth" && message.success) {
|
|
262
|
-
this.authenticated = true;
|
|
263
|
-
this.handlePendingPrivateTopic();
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (commoneHandler) {
|
|
268
|
-
commoneHandler.handle(message, socket);
|
|
269
|
-
} else {
|
|
270
|
-
const topicKey = this.getTopicKeyFromMessage(message);
|
|
271
|
-
|
|
272
|
-
const eventhandler = handlerMap.get(topicKey);
|
|
273
|
-
//
|
|
274
|
-
if (eventhandler?.callback) {
|
|
275
|
-
// console.log("👀👀👀👀👀👀👀👀👀", topicKey, eventhandler?.callback);
|
|
276
|
-
eventhandler.callback.forEach((cb) => {
|
|
277
|
-
const data = cb.formatter
|
|
278
|
-
? cb.formatter(message)
|
|
279
|
-
: defaultMessageFormatter(message);
|
|
280
|
-
|
|
281
|
-
if (data) {
|
|
282
|
-
cb.onMessage(data);
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// emit event
|
|
288
|
-
this._eventContainer.forEach((_, key) => {
|
|
289
|
-
const reg = new RegExp(key);
|
|
290
|
-
if (reg.test(topicKey)) {
|
|
291
|
-
this.emit(key, message);
|
|
292
|
-
}
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
//
|
|
297
|
-
} catch (e) {}
|
|
298
|
-
|
|
299
|
-
// You can process the received message here
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
private onPublicMessage(event: MessageEvent) {
|
|
303
|
-
this.onMessage(event, this._publicSocket, this._eventHandlers);
|
|
304
|
-
// update last message time for public
|
|
305
|
-
this._publicHeartbeatTime = Date.now();
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
private onPrivateMessage(event: MessageEvent) {
|
|
309
|
-
this.onMessage(event, this.privateSocket!, this._eventPrivateHandlers);
|
|
310
|
-
// update last message time for private
|
|
311
|
-
this._privateHeartbeatTime = Date.now();
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
private handlePendingPrivateTopic() {
|
|
315
|
-
if (this._pendingPrivateSubscribe.length > 0) {
|
|
316
|
-
this._pendingPrivateSubscribe.forEach(([params, cb]) => {
|
|
317
|
-
this.privateSubscribe(params, cb);
|
|
318
|
-
});
|
|
319
|
-
this._pendingPrivateSubscribe = [];
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
private onPublicClose(event: CloseEvent) {
|
|
324
|
-
// move handler to pending
|
|
325
|
-
this._eventHandlers.forEach((value, key) => {
|
|
326
|
-
value.callback.forEach((cb) => {
|
|
327
|
-
this._pendingPublicSubscribe.push([value.params, cb, value.isOnce]);
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
this._eventHandlers.delete(key);
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
this.emit("status:change", {
|
|
334
|
-
type: WebSocketEvent.CLOSE,
|
|
335
|
-
isPrivate: false,
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
setTimeout(() => this.checkSocketStatus(), 0);
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
private onPrivateClose(event: CloseEvent) {
|
|
342
|
-
if (this.privateIsReconnecting) return;
|
|
343
|
-
this._eventPrivateHandlers.forEach((value, key) => {
|
|
344
|
-
value.callback.forEach((cb) => {
|
|
345
|
-
this._pendingPrivateSubscribe.push([value.params, cb, value.isOnce]);
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
this._eventPrivateHandlers.delete(key);
|
|
349
|
-
});
|
|
350
|
-
this.authenticated = false;
|
|
351
|
-
|
|
352
|
-
this.emit("status:change", { type: WebSocketEvent.CLOSE, isPrivate: true });
|
|
353
|
-
|
|
354
|
-
setTimeout(() => this.checkSocketStatus(), 0);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
private onPublicError(event: Event) {
|
|
358
|
-
console.error("public WebSocket error:", event);
|
|
359
|
-
this.publicIsReconnecting = false;
|
|
360
|
-
|
|
361
|
-
if (this._publicSocket.readyState === WebSocket.OPEN) {
|
|
362
|
-
this._publicSocket.close();
|
|
363
|
-
} else {
|
|
364
|
-
// retry connect
|
|
365
|
-
if (this._publicRetryCount > CONNECT_LIMIT) return;
|
|
366
|
-
setTimeout(() => {
|
|
367
|
-
// this.createPublicSC(this.options);
|
|
368
|
-
this.reconnectPublic();
|
|
369
|
-
this._publicRetryCount++;
|
|
370
|
-
}, this._publicRetryCount * 1000);
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
this.errorBoardscast(event, this._eventHandlers);
|
|
374
|
-
this.emit("status:change", {
|
|
375
|
-
type: WebSocketEvent.ERROR,
|
|
376
|
-
isPrivate: false,
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
private onPrivateError(event: Event) {
|
|
381
|
-
console.error("Private WebSocket error:", event);
|
|
382
|
-
this.privateIsReconnecting = false;
|
|
383
|
-
|
|
384
|
-
if (this.privateSocket?.readyState === WebSocket.OPEN) {
|
|
385
|
-
this.privateSocket.close();
|
|
386
|
-
} else {
|
|
387
|
-
// retry connect
|
|
388
|
-
if (this._privateRetryCount > CONNECT_LIMIT) return;
|
|
389
|
-
setTimeout(() => {
|
|
390
|
-
// this.createPublicSC(this.options);
|
|
391
|
-
this.reconnectPrivate();
|
|
392
|
-
this._privateRetryCount++;
|
|
393
|
-
}, this._privateRetryCount * 1000);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
this.errorBoardscast(event, this._eventPrivateHandlers);
|
|
397
|
-
this.emit("status:change", { type: WebSocketEvent.ERROR, isPrivate: true });
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
private errorBoardscast(error: any, eventHandlers: Map<string, Topics>) {
|
|
401
|
-
eventHandlers.forEach((value) => {
|
|
402
|
-
value.callback.forEach((cb) => {
|
|
403
|
-
cb.onError?.(error);
|
|
404
|
-
});
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
send = (message: any) => {
|
|
409
|
-
if (typeof message !== "string") {
|
|
410
|
-
message = JSON.stringify(message);
|
|
411
|
-
}
|
|
412
|
-
if (typeof message === "undefined") return;
|
|
413
|
-
if (this._publicSocket.readyState === WebSocket.OPEN) {
|
|
414
|
-
this._publicSocket.send(message);
|
|
415
|
-
//
|
|
416
|
-
} else {
|
|
417
|
-
console.warn("WebSocket connection is not open. Cannot send message.");
|
|
418
|
-
}
|
|
419
|
-
};
|
|
420
|
-
|
|
421
|
-
close() {
|
|
422
|
-
this._publicSocket.close();
|
|
423
|
-
this.privateSocket?.close();
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
set accountId(accountId: string) {}
|
|
427
|
-
|
|
428
|
-
private async authenticate(accountId: string) {
|
|
429
|
-
if (this.authenticated) return;
|
|
430
|
-
if (!this.privateSocket) {
|
|
431
|
-
console.error("private ws not connected");
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
if (this.privateSocket.readyState !== WebSocket.OPEN) {
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
const message = await this.options.onSigntureRequest?.(accountId);
|
|
440
|
-
|
|
441
|
-
this.privateSocket.send(
|
|
442
|
-
JSON.stringify({
|
|
443
|
-
id: "auth",
|
|
444
|
-
event: "auth",
|
|
445
|
-
params: {
|
|
446
|
-
orderly_key: message.publicKey,
|
|
447
|
-
sign: message.signature,
|
|
448
|
-
timestamp: message.timestamp,
|
|
449
|
-
},
|
|
450
|
-
})
|
|
451
|
-
);
|
|
452
|
-
// this.wsSubject.next({ type: "authenticate" });
|
|
453
|
-
// this.authenticated = true;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
privateSubscribe(
|
|
457
|
-
params: any,
|
|
458
|
-
callback: WSMessageHandler | Omit<WSMessageHandler, "onUnsubscribe">
|
|
459
|
-
) {
|
|
460
|
-
const [subscribeMessage, onUnsubscribe] = this.generateMessage(
|
|
461
|
-
params,
|
|
462
|
-
(callback as WSMessageHandler).onUnsubscribe
|
|
463
|
-
);
|
|
464
|
-
|
|
465
|
-
if (this.privateSocket?.readyState !== WebSocket.OPEN) {
|
|
466
|
-
this._pendingPrivateSubscribe.push([params, callback]);
|
|
467
|
-
return () => {
|
|
468
|
-
this.unsubscribePrivate(subscribeMessage);
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
const topic = subscribeMessage.topic || subscribeMessage.event;
|
|
473
|
-
|
|
474
|
-
const handler = this._eventPrivateHandlers.get(topic);
|
|
475
|
-
const callbacks = {
|
|
476
|
-
...callback,
|
|
477
|
-
onUnsubscribe,
|
|
478
|
-
};
|
|
479
|
-
|
|
480
|
-
if (!handler) {
|
|
481
|
-
this._eventPrivateHandlers.set(topic, {
|
|
482
|
-
params,
|
|
483
|
-
callback: [callbacks],
|
|
484
|
-
});
|
|
485
|
-
this.privateSocket.send(JSON.stringify(subscribeMessage));
|
|
486
|
-
} else {
|
|
487
|
-
handler.callback.push(callbacks);
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
return () => {
|
|
491
|
-
this.unsubscribePrivate(subscribeMessage);
|
|
492
|
-
};
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
subscribe(
|
|
496
|
-
params: any,
|
|
497
|
-
callback: WSMessageHandler | Omit<WSMessageHandler, "onUnsubscribe">,
|
|
498
|
-
once?: boolean,
|
|
499
|
-
id?: string
|
|
500
|
-
): unsubscribe | undefined {
|
|
501
|
-
//
|
|
502
|
-
|
|
503
|
-
const [subscribeMessage, onUnsubscribe] = this.generateMessage(
|
|
504
|
-
params,
|
|
505
|
-
(callback as WSMessageHandler).onUnsubscribe,
|
|
506
|
-
(callback as WSMessageHandler).onMessage
|
|
507
|
-
);
|
|
508
|
-
|
|
509
|
-
//
|
|
510
|
-
|
|
511
|
-
if (this._publicSocket.readyState !== WebSocket.OPEN) {
|
|
512
|
-
this._pendingPublicSubscribe.push([params, callback, once, id]);
|
|
513
|
-
|
|
514
|
-
if (!once) {
|
|
515
|
-
return () => {
|
|
516
|
-
this.unsubscribePublic(subscribeMessage);
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
|
-
return;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
let topic = this.getTopicKeyFromParams(subscribeMessage);
|
|
523
|
-
// const topic = subscribeMessage.topic || subscribeMessage.event;
|
|
524
|
-
|
|
525
|
-
const handler = this._eventHandlers.get(topic);
|
|
526
|
-
const callbacks = {
|
|
527
|
-
...callback,
|
|
528
|
-
onUnsubscribe,
|
|
529
|
-
};
|
|
530
|
-
|
|
531
|
-
if (!handler) {
|
|
532
|
-
this._eventHandlers.set(topic, {
|
|
533
|
-
params,
|
|
534
|
-
isOnce: once,
|
|
535
|
-
callback: [callbacks],
|
|
536
|
-
});
|
|
537
|
-
this._publicSocket.send(JSON.stringify(subscribeMessage));
|
|
538
|
-
} else {
|
|
539
|
-
// 是否once,如果是once,则替换掉之前的callback
|
|
540
|
-
if (once) {
|
|
541
|
-
handler.callback = [callbacks];
|
|
542
|
-
this._publicSocket.send(JSON.stringify(subscribeMessage));
|
|
543
|
-
} else {
|
|
544
|
-
handler.callback.push(callbacks);
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
// this._subscriptionPublicTopics.push({params, cb: [cb]});
|
|
549
|
-
|
|
550
|
-
if (!once) {
|
|
551
|
-
return () => {
|
|
552
|
-
this.unsubscribePublic(subscribeMessage);
|
|
553
|
-
};
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
private getTopicKeyFromParams(params: any): string {
|
|
558
|
-
let topic;
|
|
559
|
-
|
|
560
|
-
if (params.topic) {
|
|
561
|
-
topic = params.topic;
|
|
562
|
-
} else {
|
|
563
|
-
const eventName = params.event;
|
|
564
|
-
topic = params.event;
|
|
565
|
-
|
|
566
|
-
if (params.id) {
|
|
567
|
-
topic += `_${params.id}`;
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
return topic;
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
private getTopicKeyFromMessage(message: any): string {
|
|
575
|
-
let topic;
|
|
576
|
-
if (message.topic) {
|
|
577
|
-
topic = message.topic;
|
|
578
|
-
} else {
|
|
579
|
-
if (message.event) {
|
|
580
|
-
topic = `${message.event}`;
|
|
581
|
-
|
|
582
|
-
if (message.id) {
|
|
583
|
-
topic += `_${message.id}`;
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
return topic;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
// sendPublicMessage(){
|
|
592
|
-
// if(this.publicSocket.readyState !== )
|
|
593
|
-
// }
|
|
594
|
-
|
|
595
|
-
onceSubscribe(
|
|
596
|
-
params: any,
|
|
597
|
-
callback: Omit<WSMessageHandler, "onUnsubscribe">
|
|
598
|
-
) {
|
|
599
|
-
this.subscribe(params, callback, true);
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
private unsubscribe(
|
|
603
|
-
parmas: MessageParams,
|
|
604
|
-
webSocket: WebSocket,
|
|
605
|
-
handlerMap: Map<string, Topics>
|
|
606
|
-
) {
|
|
607
|
-
const topic = parmas.topic || parmas.event;
|
|
608
|
-
const handler = handlerMap.get(topic);
|
|
609
|
-
|
|
610
|
-
// console.log("unsubscribe", topic);
|
|
611
|
-
|
|
612
|
-
if (!!handler && Array.isArray(handler?.callback)) {
|
|
613
|
-
if (handler!.callback.length === 1) {
|
|
614
|
-
const unsubscribeMessage = handler!.callback[0].onUnsubscribe(topic);
|
|
615
|
-
|
|
616
|
-
//
|
|
617
|
-
webSocket.send(JSON.stringify(unsubscribeMessage));
|
|
618
|
-
handlerMap.delete(topic);
|
|
619
|
-
//post unsubscribe message
|
|
620
|
-
} else {
|
|
621
|
-
const index = handler.callback.findIndex(
|
|
622
|
-
(cb) => cb.onMessage === parmas.onMessage
|
|
623
|
-
);
|
|
624
|
-
|
|
625
|
-
// console.log(index, handler.callback.length);
|
|
626
|
-
|
|
627
|
-
if (index === -1) return;
|
|
628
|
-
|
|
629
|
-
handler.callback.splice(index, 1);
|
|
630
|
-
|
|
631
|
-
// handlerMap.set(topic, {
|
|
632
|
-
// ...handler,
|
|
633
|
-
// callback: handler.callback.splice(index, 1),
|
|
634
|
-
// });
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
private unsubscribePrivate(parmas: MessageParams) {
|
|
640
|
-
this.unsubscribe(parmas, this.privateSocket!, this._eventPrivateHandlers);
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
private unsubscribePublic(parmas: MessageParams) {
|
|
644
|
-
this.unsubscribe(parmas, this._publicSocket, this._eventHandlers);
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
private generateMessage(
|
|
648
|
-
params: any,
|
|
649
|
-
onUnsubscribe?: (event: string) => any,
|
|
650
|
-
onMessage?: (message: any) => any
|
|
651
|
-
): [MessageParams, (event: string) => any] {
|
|
652
|
-
let subscribeMessage;
|
|
653
|
-
|
|
654
|
-
if (typeof params === "string") {
|
|
655
|
-
subscribeMessage = { event: "subscribe", topic: params };
|
|
656
|
-
} else {
|
|
657
|
-
subscribeMessage = params;
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
if (typeof onUnsubscribe !== "function") {
|
|
661
|
-
if (typeof params === "string") {
|
|
662
|
-
onUnsubscribe = () => ({ event: "unsubscribe", topic: params });
|
|
663
|
-
} else {
|
|
664
|
-
onUnsubscribe = () => ({ event: "unsubscribe", topic: params.topic });
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
return [{ ...subscribeMessage, onMessage }, onUnsubscribe];
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
private reconnectPublic() {
|
|
672
|
-
if (this.publicIsReconnecting) return;
|
|
673
|
-
this.publicIsReconnecting = true;
|
|
674
|
-
|
|
675
|
-
window.setTimeout(() => {
|
|
676
|
-
this.createPublicSC(this.options);
|
|
677
|
-
// this.emit("reconnect:public", { count: this._publicRetryCount });
|
|
678
|
-
this.emit("status:change", {
|
|
679
|
-
type: WebSocketEvent.RECONNECTING,
|
|
680
|
-
isPrivate: false,
|
|
681
|
-
count: this._publicRetryCount,
|
|
682
|
-
});
|
|
683
|
-
}, this.reconnectInterval);
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
private reconnectPrivate() {
|
|
687
|
-
if (!this.options.accountId) return;
|
|
688
|
-
if (this.privateIsReconnecting) return;
|
|
689
|
-
this.privateIsReconnecting = true;
|
|
690
|
-
|
|
691
|
-
window.setTimeout(() => {
|
|
692
|
-
this.createPrivateSC(this.options);
|
|
693
|
-
|
|
694
|
-
this.emit("status:change", {
|
|
695
|
-
type: WebSocketEvent.RECONNECTING,
|
|
696
|
-
isPrivate: true,
|
|
697
|
-
count: this._privateRetryCount,
|
|
698
|
-
});
|
|
699
|
-
}, this.reconnectInterval);
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
// get publicSocket(): WebSocket {
|
|
703
|
-
// return this._publicSocket;
|
|
704
|
-
// }
|
|
705
|
-
|
|
706
|
-
get client(): {
|
|
707
|
-
public: WebSocket;
|
|
708
|
-
private?: WebSocket;
|
|
709
|
-
} {
|
|
710
|
-
return {
|
|
711
|
-
public: this._publicSocket,
|
|
712
|
-
private: this.privateSocket,
|
|
713
|
-
};
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
on(eventName: string, callback: (message: any) => any) {
|
|
717
|
-
if (this._eventContainer.has(eventName)) {
|
|
718
|
-
this._eventContainer.get(eventName)?.add(callback);
|
|
719
|
-
}
|
|
720
|
-
this._eventContainer.set(eventName, new Set([callback]));
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
off(eventName: string, callback: (message: any) => any) {
|
|
724
|
-
if (this._eventContainer.has(eventName)) {
|
|
725
|
-
this._eventContainer.get(eventName)?.delete(callback);
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
emit(eventName: string, message: any) {
|
|
730
|
-
if (this._eventContainer.has(eventName)) {
|
|
731
|
-
this._eventContainer.get(eventName)?.forEach((cb) => cb(message));
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
}
|