okx-api 0.0.6 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -10
- package/lib/index.d.ts +2 -1
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/rest-client.d.ts +3 -4
- package/lib/rest-client.js +1 -1
- package/lib/rest-client.js.map +1 -1
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.js +2 -0
- package/lib/types/index.js.map +1 -1
- package/lib/types/rest/client.d.ts +5 -0
- package/lib/types/rest/client.js +3 -0
- package/lib/types/rest/client.js.map +1 -0
- package/lib/types/rest/index.d.ts +1 -0
- package/lib/types/rest/index.js +1 -0
- package/lib/types/rest/index.js.map +1 -1
- package/lib/types/shared.d.ts +6 -0
- package/lib/types/shared.js +3 -0
- package/lib/types/shared.js.map +1 -0
- package/lib/types/websockets/client.d.ts +22 -0
- package/lib/types/websockets/client.js +3 -0
- package/lib/types/websockets/client.js.map +1 -0
- package/lib/types/websockets/event.d.ts +21 -0
- package/lib/types/websockets/event.js +3 -0
- package/lib/types/websockets/event.js.map +1 -0
- package/lib/types/websockets/index.d.ts +3 -0
- package/lib/types/websockets/index.js +20 -0
- package/lib/types/websockets/index.js.map +1 -0
- package/lib/types/websockets/request.d.ts +108 -0
- package/lib/types/websockets/request.js +3 -0
- package/lib/types/websockets/request.js.map +1 -0
- package/lib/util/BaseRestClient.d.ts +2 -7
- package/lib/util/BaseRestClient.js +6 -7
- package/lib/util/BaseRestClient.js.map +1 -1
- package/lib/util/WsStore.d.ts +66 -0
- package/lib/util/WsStore.js +168 -0
- package/lib/util/WsStore.js.map +1 -0
- package/lib/util/index.d.ts +4 -0
- package/lib/util/index.js +21 -0
- package/lib/util/index.js.map +1 -0
- package/lib/util/logger.d.ts +9 -0
- package/lib/util/logger.js +24 -0
- package/lib/util/logger.js.map +1 -0
- package/lib/util/requestUtils.d.ts +2 -12
- package/lib/util/requestUtils.js +3 -3
- package/lib/util/requestUtils.js.map +1 -1
- package/lib/util/typeGuards.d.ts +13 -0
- package/lib/util/typeGuards.js +46 -1
- package/lib/util/typeGuards.js.map +1 -1
- package/lib/util/websocket-util.d.ts +26 -0
- package/lib/util/websocket-util.js +131 -0
- package/lib/util/websocket-util.js.map +1 -0
- package/lib/websocket-client.d.ts +99 -0
- package/lib/websocket-client.js +467 -0
- package/lib/websocket-client.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import WebSocket from 'isomorphic-ws';
|
|
4
|
+
import { WsChannelSubUnSubRequestArg, WSClientConfigurableOptions, WsDataEvent, WsEvent } from './types';
|
|
5
|
+
import { DefaultLogger, WsStore } from './util';
|
|
6
|
+
import { WsKey } from './util/websocket-util';
|
|
7
|
+
export declare type WsClientEvent = 'open' | 'update' | 'close' | 'error' | 'reconnect' | 'reconnected' | 'response';
|
|
8
|
+
declare type WsKeyObject = {
|
|
9
|
+
wsKey: WsKey;
|
|
10
|
+
};
|
|
11
|
+
interface WebsocketClientEvents {
|
|
12
|
+
/** Connection opened. If this connection was previously opened and reconnected, expect the reconnected event instead */
|
|
13
|
+
open: (evt: {
|
|
14
|
+
event: any;
|
|
15
|
+
} & WsKeyObject) => void;
|
|
16
|
+
/** Reconnecting a dropped connection */
|
|
17
|
+
reconnect: (evt: {
|
|
18
|
+
event: any;
|
|
19
|
+
} & WsKeyObject) => void;
|
|
20
|
+
/** Successfully reconnected a connection that dropped */
|
|
21
|
+
reconnected: (evt: {
|
|
22
|
+
event: any;
|
|
23
|
+
} & WsKeyObject) => void;
|
|
24
|
+
/** Connection closed */
|
|
25
|
+
close: (evt: {
|
|
26
|
+
event: any;
|
|
27
|
+
} & WsKeyObject) => void;
|
|
28
|
+
/** Received reply to websocket command (e.g. after subscribing to topics or authenticating) */
|
|
29
|
+
response: (response: WsEvent & WsKeyObject) => void;
|
|
30
|
+
/** Received data for a topic/channel */
|
|
31
|
+
update: (response: WsDataEvent & WsKeyObject) => void;
|
|
32
|
+
/** Exception from ws client OR custom listeners */
|
|
33
|
+
error: (response: any) => void;
|
|
34
|
+
}
|
|
35
|
+
export declare interface WebsocketClient {
|
|
36
|
+
on<U extends keyof WebsocketClientEvents>(event: U, listener: WebsocketClientEvents[U]): this;
|
|
37
|
+
emit<U extends keyof WebsocketClientEvents>(event: U, ...args: Parameters<WebsocketClientEvents[U]>): boolean;
|
|
38
|
+
}
|
|
39
|
+
export declare class WebsocketClient extends EventEmitter {
|
|
40
|
+
private logger;
|
|
41
|
+
private options;
|
|
42
|
+
private wsStore;
|
|
43
|
+
constructor(options: WSClientConfigurableOptions, logger?: typeof DefaultLogger);
|
|
44
|
+
/**
|
|
45
|
+
* Subscribe to topics & track/persist them. They will be automatically resubscribed to if the connection drops/reconnects.
|
|
46
|
+
* @param wsEvents topic or list of topics
|
|
47
|
+
* @param isPrivateTopic optional - the library will try to detect private topics, you can use this to mark a topic as private (if the topic isn't recognised yet)
|
|
48
|
+
*/
|
|
49
|
+
subscribe(wsEvents: WsChannelSubUnSubRequestArg[] | WsChannelSubUnSubRequestArg, isPrivateTopic?: boolean): void;
|
|
50
|
+
/**
|
|
51
|
+
* Unsubscribe from topics & remove them from memory. They won't be re-subscribed to if the connection reconnects.
|
|
52
|
+
* @param wsTopics topic or list of topics
|
|
53
|
+
* @param isPrivateTopic optional - the library will try to detect private topics, you can use this to mark a topic as private (if the topic isn't recognised yet)
|
|
54
|
+
*/
|
|
55
|
+
unsubscribe(wsTopics: WsChannelSubUnSubRequestArg[] | WsChannelSubUnSubRequestArg, isPrivateTopic?: boolean): void;
|
|
56
|
+
/** Get the WsStore that tracks websocket & topic state */
|
|
57
|
+
getWsStore(): WsStore<WsChannelSubUnSubRequestArg>;
|
|
58
|
+
close(wsKey: WsKey, force?: boolean): void;
|
|
59
|
+
closeAll(force?: boolean): void;
|
|
60
|
+
/**
|
|
61
|
+
* Request connection of all dependent (public & private) websockets, instead of waiting for automatic connection by library
|
|
62
|
+
*/
|
|
63
|
+
connectAll(): Promise<WebSocket | undefined>[];
|
|
64
|
+
connectPublic(): Promise<WebSocket | undefined>;
|
|
65
|
+
connectPrivate(): Promise<WebSocket | undefined>;
|
|
66
|
+
private connect;
|
|
67
|
+
private parseWsError;
|
|
68
|
+
/**
|
|
69
|
+
* Return params required to make authorized request
|
|
70
|
+
*/
|
|
71
|
+
private getWsAuthRequest;
|
|
72
|
+
private getWsAuthSignature;
|
|
73
|
+
private sendAuthRequest;
|
|
74
|
+
private reconnectWithDelay;
|
|
75
|
+
private ping;
|
|
76
|
+
/**
|
|
77
|
+
* Closes a connection, if it's even open. If open, this will trigger a reconnect asynchronously.
|
|
78
|
+
* If closed, trigger a reconnect immediately
|
|
79
|
+
*/
|
|
80
|
+
private executeReconnectableClose;
|
|
81
|
+
private clearTimers;
|
|
82
|
+
private clearPingTimer;
|
|
83
|
+
private clearPongTimer;
|
|
84
|
+
private clearReconnectTimer;
|
|
85
|
+
/**
|
|
86
|
+
* @private Use the `subscribe(topics)` method to subscribe to topics. Send WS message to subscribe to topics.
|
|
87
|
+
*/
|
|
88
|
+
private requestSubscribeTopics;
|
|
89
|
+
/**
|
|
90
|
+
* @private Use the `unsubscribe(topics)` method to unsubscribe from topics. Send WS message to unsubscribe from topics.
|
|
91
|
+
*/
|
|
92
|
+
private requestUnsubscribeTopics;
|
|
93
|
+
tryWsSend(wsKey: WsKey, wsMessage: string): void;
|
|
94
|
+
private connectToWsUrl;
|
|
95
|
+
private onWsOpen;
|
|
96
|
+
private onWsMessage;
|
|
97
|
+
private onWsClose;
|
|
98
|
+
}
|
|
99
|
+
export {};
|
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.WebsocketClient = void 0;
|
|
16
|
+
const events_1 = require("events");
|
|
17
|
+
const isomorphic_ws_1 = __importDefault(require("isomorphic-ws"));
|
|
18
|
+
const node_support_1 = require("./util/node-support");
|
|
19
|
+
const util_1 = require("./util");
|
|
20
|
+
const websocket_util_1 = require("./util/websocket-util");
|
|
21
|
+
const loggerCategory = { category: 'okx-ws' };
|
|
22
|
+
class WebsocketClient extends events_1.EventEmitter {
|
|
23
|
+
constructor(options, logger) {
|
|
24
|
+
super();
|
|
25
|
+
this.logger = logger || util_1.DefaultLogger;
|
|
26
|
+
this.wsStore = new util_1.WsStore(this.logger);
|
|
27
|
+
this.options = Object.assign({ market: 'prod', pongTimeout: 2000, pingInterval: 10000, reconnectTimeout: 500 }, options);
|
|
28
|
+
// add default error handling so this doesn't crash node (if the user didn't set a handler)
|
|
29
|
+
this.on('error', () => { });
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Subscribe to topics & track/persist them. They will be automatically resubscribed to if the connection drops/reconnects.
|
|
33
|
+
* @param wsEvents topic or list of topics
|
|
34
|
+
* @param isPrivateTopic optional - the library will try to detect private topics, you can use this to mark a topic as private (if the topic isn't recognised yet)
|
|
35
|
+
*/
|
|
36
|
+
subscribe(wsEvents, isPrivateTopic) {
|
|
37
|
+
const wsEventArgs = Array.isArray(wsEvents) ? wsEvents : [wsEvents];
|
|
38
|
+
wsEventArgs.forEach((wsEventArg) => {
|
|
39
|
+
const wsKey = (0, util_1.getWsKeyForTopicChannel)(this.options.market, wsEventArg.channel, isPrivateTopic);
|
|
40
|
+
// Persist topic for reconnects
|
|
41
|
+
this.wsStore.addComplexTopic(wsKey, wsEventArg);
|
|
42
|
+
// if connected, send subscription request
|
|
43
|
+
if (this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTED)) {
|
|
44
|
+
return this.requestSubscribeTopics(wsKey, [wsEventArg]);
|
|
45
|
+
}
|
|
46
|
+
// start connection process if it hasn't yet begun. Topics are automatically subscribed to on-connect
|
|
47
|
+
if (!this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTING) &&
|
|
48
|
+
!this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.RECONNECTING)) {
|
|
49
|
+
return this.connect(wsKey);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Unsubscribe from topics & remove them from memory. They won't be re-subscribed to if the connection reconnects.
|
|
55
|
+
* @param wsTopics topic or list of topics
|
|
56
|
+
* @param isPrivateTopic optional - the library will try to detect private topics, you can use this to mark a topic as private (if the topic isn't recognised yet)
|
|
57
|
+
*/
|
|
58
|
+
unsubscribe(wsTopics, isPrivateTopic) {
|
|
59
|
+
const wsEventArgs = Array.isArray(wsTopics) ? wsTopics : [wsTopics];
|
|
60
|
+
wsEventArgs.forEach((wsEventArg) => {
|
|
61
|
+
const wsKey = (0, util_1.getWsKeyForTopicChannel)(this.options.market, wsEventArg.channel, isPrivateTopic);
|
|
62
|
+
// Remove topic from persistence for reconnects
|
|
63
|
+
this.wsStore.deleteComplexTopic(wsKey, wsEventArg);
|
|
64
|
+
// unsubscribe request only necessary if active connection exists
|
|
65
|
+
if (this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTED)) {
|
|
66
|
+
this.requestUnsubscribeTopics(wsKey, [wsEventArg]);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/** Get the WsStore that tracks websocket & topic state */
|
|
71
|
+
getWsStore() {
|
|
72
|
+
return this.wsStore;
|
|
73
|
+
}
|
|
74
|
+
close(wsKey, force) {
|
|
75
|
+
this.logger.info('Closing connection', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
|
|
76
|
+
this.wsStore.setConnectionState(wsKey, util_1.WsConnectionStateEnum.CLOSING);
|
|
77
|
+
this.clearTimers(wsKey);
|
|
78
|
+
const ws = this.wsStore.getWs(wsKey);
|
|
79
|
+
ws === null || ws === void 0 ? void 0 : ws.close();
|
|
80
|
+
if (force) {
|
|
81
|
+
ws === null || ws === void 0 ? void 0 : ws.terminate();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
closeAll(force) {
|
|
85
|
+
const keys = this.wsStore.getKeys();
|
|
86
|
+
this.logger.info(`Closing all ws connections: ${keys}`);
|
|
87
|
+
keys.forEach((key) => {
|
|
88
|
+
this.close(key, force);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Request connection of all dependent (public & private) websockets, instead of waiting for automatic connection by library
|
|
93
|
+
*/
|
|
94
|
+
connectAll() {
|
|
95
|
+
return [this.connectPublic(), this.connectPrivate()];
|
|
96
|
+
}
|
|
97
|
+
connectPublic() {
|
|
98
|
+
const isPrivate = false;
|
|
99
|
+
const wsKey = (0, websocket_util_1.getWsKeyForMarket)(this.options.market, isPrivate);
|
|
100
|
+
return this.connect(util_1.WS_KEY_MAP[wsKey]);
|
|
101
|
+
}
|
|
102
|
+
connectPrivate() {
|
|
103
|
+
const isPrivate = true;
|
|
104
|
+
const wsKey = (0, websocket_util_1.getWsKeyForMarket)(this.options.market, isPrivate);
|
|
105
|
+
return this.connect(util_1.WS_KEY_MAP[wsKey]);
|
|
106
|
+
}
|
|
107
|
+
connect(wsKey) {
|
|
108
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
109
|
+
try {
|
|
110
|
+
if (this.wsStore.isWsOpen(wsKey)) {
|
|
111
|
+
this.logger.error('Refused to connect to ws with existing active connection', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
|
|
112
|
+
return this.wsStore.getWs(wsKey);
|
|
113
|
+
}
|
|
114
|
+
if (this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTING)) {
|
|
115
|
+
this.logger.error('Refused to connect to ws, connection attempt already active', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (!this.wsStore.getConnectionState(wsKey) ||
|
|
119
|
+
this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.INITIAL)) {
|
|
120
|
+
this.wsStore.setConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTING);
|
|
121
|
+
}
|
|
122
|
+
const url = (0, websocket_util_1.getWsUrlForWsKey)(wsKey, this.options);
|
|
123
|
+
const ws = this.connectToWsUrl(url, wsKey);
|
|
124
|
+
return this.wsStore.setWs(wsKey, ws);
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
this.parseWsError('Connection failed', err, wsKey);
|
|
128
|
+
this.reconnectWithDelay(wsKey, this.options.reconnectTimeout);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
parseWsError(context, error, wsKey) {
|
|
133
|
+
if (!error.message) {
|
|
134
|
+
this.logger.error(`${context} due to unexpected error: `, error);
|
|
135
|
+
this.emit('error', error);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
switch (error.message) {
|
|
139
|
+
default:
|
|
140
|
+
if (this.wsStore.getConnectionState(wsKey) !==
|
|
141
|
+
util_1.WsConnectionStateEnum.CLOSING) {
|
|
142
|
+
this.logger.error(`${context} due to unexpected response error: "${(error === null || error === void 0 ? void 0 : error.msg) || (error === null || error === void 0 ? void 0 : error.message) || error}"`, Object.assign(Object.assign({}, loggerCategory), { wsKey, error }));
|
|
143
|
+
this.executeReconnectableClose(wsKey, 'unhandled onWsError');
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
this.logger.info(`${wsKey} socket forcefully closed. Will not reconnect.`);
|
|
147
|
+
}
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
this.emit('error', error);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Return params required to make authorized request
|
|
154
|
+
*/
|
|
155
|
+
getWsAuthRequest(wsKey) {
|
|
156
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
157
|
+
const isPublicWsKey = util_1.PUBLIC_WS_KEYS.includes(wsKey);
|
|
158
|
+
const accounts = this.options.accounts;
|
|
159
|
+
const hasAccountsToAuth = !!(accounts === null || accounts === void 0 ? void 0 : accounts.length);
|
|
160
|
+
if (isPublicWsKey || !accounts || !hasAccountsToAuth) {
|
|
161
|
+
this.logger.debug('Starting public only websocket client.', Object.assign(Object.assign({}, loggerCategory), { wsKey,
|
|
162
|
+
isPublicWsKey,
|
|
163
|
+
hasAccountsToAuth }));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
const authAccountRequests = accounts.map((credentials) => __awaiter(this, void 0, void 0, function* () {
|
|
168
|
+
try {
|
|
169
|
+
const { signature, timestamp } = yield this.getWsAuthSignature(wsKey, credentials);
|
|
170
|
+
return {
|
|
171
|
+
apiKey: credentials.apiKey,
|
|
172
|
+
passphrase: credentials.apiPass,
|
|
173
|
+
timestamp: timestamp,
|
|
174
|
+
sign: signature,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
catch (e) {
|
|
178
|
+
this.logger.error(`Account with key ${credentials.apiKey} could not be authenticateD: ${e}`);
|
|
179
|
+
}
|
|
180
|
+
return;
|
|
181
|
+
}));
|
|
182
|
+
const signedAuthAccountRequests = yield Promise.all(authAccountRequests);
|
|
183
|
+
// Filter out failed accounts
|
|
184
|
+
const authRequests = signedAuthAccountRequests.filter((request) => !!request);
|
|
185
|
+
const authParams = {
|
|
186
|
+
op: 'login',
|
|
187
|
+
args: authRequests,
|
|
188
|
+
};
|
|
189
|
+
return authParams;
|
|
190
|
+
}
|
|
191
|
+
catch (e) {
|
|
192
|
+
this.logger.error(e, Object.assign(Object.assign({}, loggerCategory), { wsKey }));
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
getWsAuthSignature(wsKey, credentials) {
|
|
198
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
199
|
+
const { apiKey, apiSecret } = credentials;
|
|
200
|
+
if (!apiKey || !apiSecret) {
|
|
201
|
+
this.logger.warning('Cannot authenticate websocket, either api or secret missing.', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
|
|
202
|
+
throw new Error(`Cannot auth - missing api or secret in config (key: ${apiKey})`);
|
|
203
|
+
}
|
|
204
|
+
this.logger.debug("Getting auth'd request params", Object.assign(Object.assign({}, loggerCategory), { wsKey }));
|
|
205
|
+
const timestamp = (Date.now() / 1000).toFixed(0);
|
|
206
|
+
// const signatureExpiresAt = timestamp + 5;
|
|
207
|
+
const signatureRequest = timestamp + 'GET' + '/users/self/verify';
|
|
208
|
+
const signature = yield (0, node_support_1.signMessage)(signatureRequest, apiSecret);
|
|
209
|
+
return {
|
|
210
|
+
signature,
|
|
211
|
+
timestamp,
|
|
212
|
+
};
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
sendAuthRequest(wsKey) {
|
|
216
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
217
|
+
const logContext = Object.assign(Object.assign({}, loggerCategory), { wsKey, method: 'sendAuthRequest' });
|
|
218
|
+
this.logger.info(`Sending auth request...`, logContext);
|
|
219
|
+
try {
|
|
220
|
+
const authRequest = yield this.getWsAuthRequest(wsKey);
|
|
221
|
+
if (!authRequest) {
|
|
222
|
+
throw new Error('Cannot authenticate this connection');
|
|
223
|
+
}
|
|
224
|
+
this.logger.info(`Sending authentication request on wsKey(${wsKey})`, logContext);
|
|
225
|
+
this.logger.silly(`Authenticating with event: ${JSON.stringify(authRequest, null, 2)} on wsKey(${wsKey})`, logContext);
|
|
226
|
+
return this.tryWsSend(wsKey, JSON.stringify(authRequest));
|
|
227
|
+
}
|
|
228
|
+
catch (e) {
|
|
229
|
+
this.logger.error(e, logContext);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
reconnectWithDelay(wsKey, connectionDelayMs) {
|
|
234
|
+
var _a;
|
|
235
|
+
this.clearTimers(wsKey);
|
|
236
|
+
if (this.wsStore.getConnectionState(wsKey) !==
|
|
237
|
+
util_1.WsConnectionStateEnum.CONNECTING) {
|
|
238
|
+
this.wsStore.setConnectionState(wsKey, util_1.WsConnectionStateEnum.RECONNECTING);
|
|
239
|
+
}
|
|
240
|
+
if ((_a = this.wsStore.get(wsKey)) === null || _a === void 0 ? void 0 : _a.activeReconnectTimer) {
|
|
241
|
+
this.clearReconnectTimer(wsKey);
|
|
242
|
+
}
|
|
243
|
+
this.wsStore.get(wsKey, true).activeReconnectTimer = setTimeout(() => {
|
|
244
|
+
this.logger.info('Reconnecting to websocket', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
|
|
245
|
+
this.clearReconnectTimer(wsKey);
|
|
246
|
+
this.connect(wsKey);
|
|
247
|
+
}, connectionDelayMs);
|
|
248
|
+
}
|
|
249
|
+
ping(wsKey) {
|
|
250
|
+
if (this.wsStore.get(wsKey, true).activePongTimer) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
this.clearPongTimer(wsKey);
|
|
254
|
+
this.logger.silly('Sending ping', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
|
|
255
|
+
this.tryWsSend(wsKey, 'ping');
|
|
256
|
+
this.wsStore.get(wsKey, true).activePongTimer = setTimeout(() => this.executeReconnectableClose(wsKey, 'Pong timeout'), this.options.pongTimeout);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Closes a connection, if it's even open. If open, this will trigger a reconnect asynchronously.
|
|
260
|
+
* If closed, trigger a reconnect immediately
|
|
261
|
+
*/
|
|
262
|
+
executeReconnectableClose(wsKey, reason) {
|
|
263
|
+
var _a;
|
|
264
|
+
this.logger.info(`${reason} - closing socket to reconnect`, Object.assign(Object.assign({}, loggerCategory), { wsKey,
|
|
265
|
+
reason }));
|
|
266
|
+
const wasOpen = this.wsStore.isWsOpen(wsKey);
|
|
267
|
+
(_a = this.wsStore.getWs(wsKey)) === null || _a === void 0 ? void 0 : _a.terminate();
|
|
268
|
+
delete this.wsStore.get(wsKey, true).activePongTimer;
|
|
269
|
+
this.clearPingTimer(wsKey);
|
|
270
|
+
this.clearPongTimer(wsKey);
|
|
271
|
+
if (!wasOpen) {
|
|
272
|
+
this.logger.info(`${reason} - socket already closed - trigger immediate reconnect`, Object.assign(Object.assign({}, loggerCategory), { wsKey,
|
|
273
|
+
reason }));
|
|
274
|
+
this.reconnectWithDelay(wsKey, this.options.reconnectTimeout);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
clearTimers(wsKey) {
|
|
278
|
+
this.clearPingTimer(wsKey);
|
|
279
|
+
this.clearPongTimer(wsKey);
|
|
280
|
+
this.clearReconnectTimer(wsKey);
|
|
281
|
+
}
|
|
282
|
+
// Send a ping at intervals
|
|
283
|
+
clearPingTimer(wsKey) {
|
|
284
|
+
const wsState = this.wsStore.get(wsKey);
|
|
285
|
+
if (wsState === null || wsState === void 0 ? void 0 : wsState.activePingTimer) {
|
|
286
|
+
clearInterval(wsState.activePingTimer);
|
|
287
|
+
wsState.activePingTimer = undefined;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
// Expect a pong within a time limit
|
|
291
|
+
clearPongTimer(wsKey) {
|
|
292
|
+
const wsState = this.wsStore.get(wsKey);
|
|
293
|
+
if (wsState === null || wsState === void 0 ? void 0 : wsState.activePongTimer) {
|
|
294
|
+
clearTimeout(wsState.activePongTimer);
|
|
295
|
+
wsState.activePongTimer = undefined;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
clearReconnectTimer(wsKey) {
|
|
299
|
+
const wsState = this.wsStore.get(wsKey);
|
|
300
|
+
if (wsState === null || wsState === void 0 ? void 0 : wsState.activeReconnectTimer) {
|
|
301
|
+
clearTimeout(wsState.activeReconnectTimer);
|
|
302
|
+
wsState.activeReconnectTimer = undefined;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* @private Use the `subscribe(topics)` method to subscribe to topics. Send WS message to subscribe to topics.
|
|
307
|
+
*/
|
|
308
|
+
requestSubscribeTopics(wsKey, topics) {
|
|
309
|
+
if (!topics.length) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
const maxTopicsPerEvent = (0, util_1.getMaxTopicsPerSubscribeEvent)(this.options.market);
|
|
313
|
+
if (maxTopicsPerEvent && topics.length > maxTopicsPerEvent) {
|
|
314
|
+
this.logger.silly(`Subscribing to topics in batches of ${maxTopicsPerEvent}`);
|
|
315
|
+
for (var i = 0; i < topics.length; i += maxTopicsPerEvent) {
|
|
316
|
+
const batch = topics.slice(i, i + maxTopicsPerEvent);
|
|
317
|
+
this.logger.silly(`Subscribing to batch of ${batch.length}`);
|
|
318
|
+
this.requestSubscribeTopics(wsKey, batch);
|
|
319
|
+
}
|
|
320
|
+
this.logger.silly(`Finished batch subscribing to ${topics.length} topics`);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
const request = {
|
|
324
|
+
op: 'subscribe',
|
|
325
|
+
args: topics,
|
|
326
|
+
};
|
|
327
|
+
const wsMessage = JSON.stringify(request);
|
|
328
|
+
this.tryWsSend(wsKey, wsMessage);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* @private Use the `unsubscribe(topics)` method to unsubscribe from topics. Send WS message to unsubscribe from topics.
|
|
332
|
+
*/
|
|
333
|
+
requestUnsubscribeTopics(wsKey, topics) {
|
|
334
|
+
if (!topics.length) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
const maxTopicsPerEvent = (0, util_1.getMaxTopicsPerSubscribeEvent)(this.options.market);
|
|
338
|
+
if (maxTopicsPerEvent && topics.length > maxTopicsPerEvent) {
|
|
339
|
+
this.logger.silly(`Unsubscribing to topics in batches of ${maxTopicsPerEvent}`);
|
|
340
|
+
for (var i = 0; i < topics.length; i += maxTopicsPerEvent) {
|
|
341
|
+
const batch = topics.slice(i, i + maxTopicsPerEvent);
|
|
342
|
+
this.logger.silly(`Unsubscribing to batch of ${batch.length}`);
|
|
343
|
+
this.requestUnsubscribeTopics(wsKey, batch);
|
|
344
|
+
}
|
|
345
|
+
this.logger.silly(`Finished batch unsubscribing to ${topics.length} topics`);
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
const request = {
|
|
349
|
+
op: 'unsubscribe',
|
|
350
|
+
args: topics,
|
|
351
|
+
};
|
|
352
|
+
const wsMessage = JSON.stringify(request);
|
|
353
|
+
this.tryWsSend(wsKey, wsMessage);
|
|
354
|
+
}
|
|
355
|
+
tryWsSend(wsKey, wsMessage) {
|
|
356
|
+
try {
|
|
357
|
+
this.logger.silly(`Sending upstream ws message: `, Object.assign(Object.assign({}, loggerCategory), { wsMessage,
|
|
358
|
+
wsKey }));
|
|
359
|
+
if (!wsKey) {
|
|
360
|
+
throw new Error(`Cannot send message (wsKey not provided: wsKey(${wsKey}))`);
|
|
361
|
+
}
|
|
362
|
+
const ws = this.wsStore.getWs(wsKey);
|
|
363
|
+
if (!ws) {
|
|
364
|
+
throw new Error(`${wsKey} socket not connected yet, call "connect(${wsKey}) first then try again when the "open" event arrives`);
|
|
365
|
+
}
|
|
366
|
+
ws.send(wsMessage);
|
|
367
|
+
}
|
|
368
|
+
catch (e) {
|
|
369
|
+
this.logger.error(`Failed to send WS message`, Object.assign(Object.assign({}, loggerCategory), { wsMessage,
|
|
370
|
+
wsKey, exception: e }));
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
connectToWsUrl(url, wsKey) {
|
|
374
|
+
var _a;
|
|
375
|
+
this.logger.silly(`Opening WS connection to URL: ${url}`, Object.assign(Object.assign({}, loggerCategory), { wsKey }));
|
|
376
|
+
const agent = (_a = this.options.requestOptions) === null || _a === void 0 ? void 0 : _a.agent;
|
|
377
|
+
const ws = new isomorphic_ws_1.default(url, undefined, agent ? { agent } : undefined);
|
|
378
|
+
ws.onopen = (event) => this.onWsOpen(event, wsKey);
|
|
379
|
+
ws.onmessage = (event) => this.onWsMessage(event, wsKey);
|
|
380
|
+
ws.onerror = (event) => this.parseWsError('Websocket onWsError', event, wsKey);
|
|
381
|
+
ws.onclose = (event) => this.onWsClose(event, wsKey);
|
|
382
|
+
return ws;
|
|
383
|
+
}
|
|
384
|
+
onWsOpen(event, wsKey) {
|
|
385
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
386
|
+
if (this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTING)) {
|
|
387
|
+
this.logger.info('Websocket connected', Object.assign(Object.assign({}, loggerCategory), { wsKey, market: this.options.market }));
|
|
388
|
+
this.emit('open', { wsKey, event });
|
|
389
|
+
}
|
|
390
|
+
else if (this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.RECONNECTING)) {
|
|
391
|
+
this.logger.info('Websocket reconnected', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
|
|
392
|
+
this.emit('reconnected', { wsKey, event });
|
|
393
|
+
}
|
|
394
|
+
this.wsStore.setConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTED);
|
|
395
|
+
this.wsStore.get(wsKey, true).activePingTimer = setInterval(() => this.ping(wsKey), this.options.pingInterval);
|
|
396
|
+
// Private websockets require an auth packet to be sent after opening the connection
|
|
397
|
+
if (util_1.PRIVATE_WS_KEYS.includes(wsKey)) {
|
|
398
|
+
// Any requested private topics will be subscribed to once authentication succeeds (in onWsMessage handler)
|
|
399
|
+
yield this.sendAuthRequest(wsKey);
|
|
400
|
+
// Private topics will be subscribed to once authentication is confirmed as successful
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
// Public topics can be subscribed to immediately
|
|
404
|
+
const topics = [
|
|
405
|
+
...this.wsStore.getTopics(wsKey),
|
|
406
|
+
];
|
|
407
|
+
// Since public channels have their own ws key, these topics must be public ones already
|
|
408
|
+
this.requestSubscribeTopics(wsKey, topics);
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
onWsMessage(event, wsKey) {
|
|
412
|
+
const logContext = Object.assign(Object.assign({}, loggerCategory), { wsKey, method: 'onWsMessage' });
|
|
413
|
+
try {
|
|
414
|
+
// any message can clear the pong timer - wouldn't get a message if the ws dropped
|
|
415
|
+
this.clearPongTimer(wsKey);
|
|
416
|
+
if ((0, util_1.isWsPong)(event)) {
|
|
417
|
+
this.logger.silly('Received pong', logContext);
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
const msg = JSON.parse((event === null || event === void 0 ? void 0 : event.data) || event);
|
|
421
|
+
if ((0, util_1.isWsErrorEvent)(msg)) {
|
|
422
|
+
this.logger.error(`WS error event: `, Object.assign(Object.assign({}, msg), { wsKey }));
|
|
423
|
+
return this.emit('error', Object.assign(Object.assign({}, msg), { wsKey }));
|
|
424
|
+
}
|
|
425
|
+
if ((0, util_1.isWsDataEvent)(msg)) {
|
|
426
|
+
return this.emit('update', Object.assign(Object.assign({}, msg), { wsKey }));
|
|
427
|
+
}
|
|
428
|
+
if ((0, util_1.isWsLoginEvent)(msg)) {
|
|
429
|
+
// Successfully authenticated
|
|
430
|
+
if (msg.code === websocket_util_1.WS_EVENT_CODE_ENUM.OK) {
|
|
431
|
+
this.logger.info(`Authenticated succesfully on wsKey(${wsKey})`, logContext);
|
|
432
|
+
this.emit('response', Object.assign(Object.assign({}, msg), { wsKey }));
|
|
433
|
+
const topics = [
|
|
434
|
+
...this.wsStore.getTopics(wsKey),
|
|
435
|
+
];
|
|
436
|
+
// Since private topics have a dedicated WsKey, these are automatically all private topics (no filtering required before the subscribe call)
|
|
437
|
+
this.requestSubscribeTopics(wsKey, topics);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
this.logger.error(`Authentication failed: `, Object.assign(Object.assign(Object.assign({}, logContext), msg), { wsKey }));
|
|
441
|
+
return this.emit('error', Object.assign(Object.assign({}, msg), { wsKey }));
|
|
442
|
+
}
|
|
443
|
+
if ((0, util_1.isWsSubscribeEvent)(msg) || (0, util_1.isWsUnsubscribeEvent)(msg)) {
|
|
444
|
+
// this.logger.silly(`Ws subscribe reply:`, { ...msg, wsKey });
|
|
445
|
+
return this.emit('response', Object.assign(Object.assign({}, msg), { wsKey }));
|
|
446
|
+
}
|
|
447
|
+
this.logger.error('Unhandled/unrecognised ws event message', Object.assign(Object.assign({}, logContext), { eventName: msg.event, msg: JSON.stringify(msg, null, 2), wsKey }));
|
|
448
|
+
}
|
|
449
|
+
catch (e) {
|
|
450
|
+
this.logger.error('Failed to parse ws event message', Object.assign(Object.assign({}, logContext), { error: e, event,
|
|
451
|
+
wsKey }));
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
onWsClose(event, wsKey) {
|
|
455
|
+
this.logger.info('Websocket connection closed', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
|
|
456
|
+
if (this.wsStore.getConnectionState(wsKey) !== util_1.WsConnectionStateEnum.CLOSING) {
|
|
457
|
+
this.reconnectWithDelay(wsKey, this.options.reconnectTimeout);
|
|
458
|
+
this.emit('reconnect', { wsKey, event });
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
this.wsStore.setConnectionState(wsKey, util_1.WsConnectionStateEnum.INITIAL);
|
|
462
|
+
this.emit('close', { wsKey, event });
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
exports.WebsocketClient = WebsocketClient;
|
|
467
|
+
//# sourceMappingURL=websocket-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket-client.js","sourceRoot":"","sources":["../src/websocket-client.ts"],"names":[],"mappings":"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"}
|