binance 3.0.0-beta.8 → 3.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 +1 -1
- package/lib/main-client.d.ts +56 -2
- package/lib/main-client.js +44 -1
- package/lib/main-client.js.map +1 -1
- package/lib/types/futures.d.ts +10 -0
- package/lib/types/shared.d.ts +8 -1
- package/lib/types/spot.d.ts +48 -3
- package/lib/types/websockets/ws-api-requests.d.ts +37 -29
- package/lib/types/websockets/ws-api-responses.d.ts +35 -1
- package/lib/types/websockets/ws-api.d.ts +11 -9
- package/lib/types/websockets/ws-api.js +1 -0
- package/lib/types/websockets/ws-api.js.map +1 -1
- package/lib/types/websockets/ws-events-formatted.d.ts +14 -12
- package/lib/types/websockets/ws-events-raw.d.ts +10 -0
- package/lib/types/websockets/ws-general.d.ts +5 -0
- package/lib/usdm-client.d.ts +4 -1
- package/lib/usdm-client.js +3 -0
- package/lib/usdm-client.js.map +1 -1
- package/lib/util/BaseRestClient.d.ts +2 -1
- package/lib/util/BaseRestClient.js +6 -5
- package/lib/util/BaseRestClient.js.map +1 -1
- package/lib/util/BaseWSClient.js +28 -5
- package/lib/util/BaseWSClient.js.map +1 -1
- package/lib/util/beautifier-maps.d.ts +34 -0
- package/lib/util/beautifier-maps.js +34 -0
- package/lib/util/beautifier-maps.js.map +1 -1
- package/lib/util/beautifier.d.ts +1 -0
- package/lib/util/beautifier.js +46 -7
- package/lib/util/beautifier.js.map +1 -1
- package/lib/util/node-support.js +3 -1
- package/lib/util/node-support.js.map +1 -1
- package/lib/util/requestUtils.d.ts +2 -2
- package/lib/util/requestUtils.js +69 -16
- package/lib/util/requestUtils.js.map +1 -1
- package/lib/util/typeGuards.d.ts +27 -4
- package/lib/util/typeGuards.js +103 -41
- package/lib/util/typeGuards.js.map +1 -1
- package/lib/util/webCryptoAPI.js +0 -2
- package/lib/util/webCryptoAPI.js.map +1 -1
- package/lib/util/websockets/WsStore.js.map +1 -1
- package/lib/util/websockets/user-data-stream-manager.js +2 -2
- package/lib/util/websockets/user-data-stream-manager.js.map +1 -1
- package/lib/util/websockets/websocket-util.d.ts +16 -2
- package/lib/util/websockets/websocket-util.js +92 -42
- package/lib/util/websockets/websocket-util.js.map +1 -1
- package/lib/websocket-api-client.d.ts +14 -8
- package/lib/websocket-api-client.js +39 -24
- package/lib/websocket-api-client.js.map +1 -1
- package/lib/websocket-client-legacy.js +3 -3
- package/lib/websocket-client-legacy.js.map +1 -1
- package/lib/websocket-client.d.ts +48 -14
- package/lib/websocket-client.js +312 -154
- package/lib/websocket-client.js.map +1 -1
- package/package.json +1 -1
package/lib/websocket-client.js
CHANGED
|
@@ -8,6 +8,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
12
|
+
var t = {};
|
|
13
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
14
|
+
t[p] = s[p];
|
|
15
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
16
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
17
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
18
|
+
t[p[i]] = s[p[i]];
|
|
19
|
+
}
|
|
20
|
+
return t;
|
|
21
|
+
};
|
|
11
22
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
23
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
24
|
};
|
|
@@ -44,9 +55,12 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
44
55
|
super(options, logger);
|
|
45
56
|
this.restClientCache = new rest_client_cache_1.RestClientCache();
|
|
46
57
|
this.beautifier = new beautifier_1.default({
|
|
47
|
-
warnKeyMissingInMap:
|
|
58
|
+
warnKeyMissingInMap: false,
|
|
48
59
|
});
|
|
49
60
|
this.respawnTimeoutCache = {};
|
|
61
|
+
if (options === null || options === void 0 ? void 0 : options.beautifyWarnIfMissing) {
|
|
62
|
+
this.beautifier.setWarnIfMissing(options.beautifyWarnIfMissing);
|
|
63
|
+
}
|
|
50
64
|
/**
|
|
51
65
|
* Binance uses native WebSocket ping/pong frames, which cannot be directly used in
|
|
52
66
|
* some environents (e.g. most browsers do not support sending raw ping/pong frames).
|
|
@@ -57,7 +71,7 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
57
71
|
* be found here: https://stackoverflow.com/questions/10585355/sending-websocket-ping-pong-frame-from-browser
|
|
58
72
|
*/
|
|
59
73
|
if (!(0, websocket_util_1.isWSPingFrameAvailable)()) {
|
|
60
|
-
this.logger.
|
|
74
|
+
this.logger.info('Disabled WS heartbeats. WS.ping() is not available in your environment.');
|
|
61
75
|
this.options.disableHeartbeat = true;
|
|
62
76
|
}
|
|
63
77
|
this.userDataStreamManager = new user_data_stream_manager_1.UserDataStreamManager({
|
|
@@ -65,8 +79,12 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
65
79
|
wsStore: this.getWsStore(),
|
|
66
80
|
restClientCache: this.restClientCache,
|
|
67
81
|
// fn pointers:
|
|
68
|
-
respawnUserDataFn: (wsKey, market, context = {}) =>
|
|
69
|
-
|
|
82
|
+
respawnUserDataFn: (wsKey, market, context = {}) => {
|
|
83
|
+
return this.respawnUserDataStream(wsKey, market, context);
|
|
84
|
+
},
|
|
85
|
+
getWsUrlFn: (wsKey, connectionType) => {
|
|
86
|
+
return this.getWsUrl(wsKey, connectionType);
|
|
87
|
+
},
|
|
70
88
|
getRestClientOptionsFn: () => this.getRestClientOptions(),
|
|
71
89
|
getWsClientOptionsfn: () => this.options,
|
|
72
90
|
closeWsFn: (wsKey, force) => this.close(wsKey, force),
|
|
@@ -114,7 +132,10 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
114
132
|
* You do not need to call this, but if you call this before making any WS API requests,
|
|
115
133
|
* it can accelerate the first request (by preparing the connection in advance).
|
|
116
134
|
*/
|
|
117
|
-
connectWSAPI(wsKey) {
|
|
135
|
+
connectWSAPI(wsKey, skipAuth) {
|
|
136
|
+
if (skipAuth) {
|
|
137
|
+
return this.assertIsConnected(wsKey);
|
|
138
|
+
}
|
|
118
139
|
/** This call automatically ensures the connection is active AND authenticated before resolving */
|
|
119
140
|
return this.assertIsAuthenticated(wsKey);
|
|
120
141
|
}
|
|
@@ -146,27 +167,48 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
146
167
|
const normalisedTopicRequests = (0, websocket_util_1.getNormalisedTopicRequests)(topicRequests);
|
|
147
168
|
return this.unsubscribeTopicsForWsKey(normalisedTopicRequests, wsKey);
|
|
148
169
|
}
|
|
149
|
-
sendWSAPIRequest(wsKey, operation, params) {
|
|
170
|
+
sendWSAPIRequest(wsKey, operation, params, requestFlags) {
|
|
150
171
|
return __awaiter(this, void 0, void 0, function* () {
|
|
151
172
|
/**
|
|
152
|
-
* Spot:
|
|
173
|
+
* Spot:
|
|
174
|
+
* -> https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/general-api-information
|
|
175
|
+
* -> https://github.com/binance/binance-spot-api-docs/blob/master/web-socket-api.md#public-api-requests
|
|
153
176
|
* USDM Futures: https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-api-general-info
|
|
154
177
|
* COINM Futures: https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-api-general-info
|
|
155
178
|
*/
|
|
156
|
-
var _a;
|
|
179
|
+
var _a, _b;
|
|
157
180
|
// If testnet, enforce testnet wskey for WS API calls
|
|
158
181
|
const resolvedWsKey = this.options.testnet ? (0, websocket_util_1.getTestnetWsKey)(wsKey) : wsKey;
|
|
159
182
|
// this.logger.trace(`sendWSAPIRequest(): assertIsConnected("${wsKey}")...`);
|
|
183
|
+
const timestampBeforeAuth = Date.now();
|
|
160
184
|
yield this.assertIsConnected(resolvedWsKey);
|
|
161
185
|
// this.logger.trace('sendWSAPIRequest(): assertIsConnected(${wsKey}) ok');
|
|
162
|
-
//
|
|
163
|
-
|
|
164
|
-
|
|
186
|
+
// Some commands don't require authentication.
|
|
187
|
+
if ((requestFlags === null || requestFlags === void 0 ? void 0 : requestFlags.authIsOptional) !== true) {
|
|
188
|
+
// this.logger.trace('sendWSAPIRequest(): assertIsAuthenticated(${wsKey})...');
|
|
189
|
+
yield this.assertIsAuthenticated(resolvedWsKey);
|
|
190
|
+
// this.logger.trace('sendWSAPIRequest(): assertIsAuthenticated(${wsKey}) ok');
|
|
191
|
+
}
|
|
192
|
+
const timestampAfterAuth = Date.now();
|
|
165
193
|
const request = {
|
|
166
194
|
id: this.getNewRequestId(),
|
|
167
195
|
method: operation,
|
|
168
196
|
params: Object.assign({}, params),
|
|
169
197
|
};
|
|
198
|
+
/**
|
|
199
|
+
* Some WS API requests require a timestamp to be included. assertIsConnected and assertIsAuthenticated
|
|
200
|
+
* can introduce a small delay before the actual request is sent, if not connected before that request is
|
|
201
|
+
* made. This can lead to a curious race condition, where the request timestamp is before
|
|
202
|
+
* the "authorizedSince" timestamp - as such, binance does not recognise the session as already authenticated.
|
|
203
|
+
*
|
|
204
|
+
* The below mechanism measures any delay introduced from the assert calls, and if the request includes a timestamp,
|
|
205
|
+
* it offsets that timestamp by the delay.
|
|
206
|
+
*/
|
|
207
|
+
const delayFromAuthAssert = timestampAfterAuth - timestampBeforeAuth;
|
|
208
|
+
if (delayFromAuthAssert && ((_a = request.params) === null || _a === void 0 ? void 0 : _a.timestamp)) {
|
|
209
|
+
request.params.timestamp += delayFromAuthAssert;
|
|
210
|
+
this.logger.trace(`sendWSAPIRequest(): adjust timestamp - delay seen by connect/auth assert and delayed request includes timestamp, adjusting timestamp by ${delayFromAuthAssert}ms`);
|
|
211
|
+
}
|
|
170
212
|
if ((0, requestUtils_1.requiresWSAPINewClientOID)(request, resolvedWsKey)) {
|
|
171
213
|
(0, requestUtils_1.validateWSAPINewClientOID)(request, resolvedWsKey);
|
|
172
214
|
}
|
|
@@ -175,17 +217,24 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
175
217
|
// Store deferred promise, resolved within the "resolveEmittableEvents" method while parsing incoming events
|
|
176
218
|
const promiseRef = (0, websocket_util_1.getPromiseRefForWSAPIRequest)(resolvedWsKey, signedEvent);
|
|
177
219
|
const deferredPromise = this.getWsStore().createDeferredPromise(resolvedWsKey, promiseRef, false);
|
|
178
|
-
|
|
220
|
+
// Enrich returned promise with request context for easier debugging
|
|
221
|
+
(_b = deferredPromise.promise) === null || _b === void 0 ? void 0 : _b.then((res) => {
|
|
222
|
+
if (!Array.isArray(res)) {
|
|
223
|
+
res.request = Object.assign({ wsKey: resolvedWsKey }, signedEvent);
|
|
224
|
+
}
|
|
225
|
+
return res;
|
|
226
|
+
}).catch((e) => {
|
|
179
227
|
if (typeof e === 'string') {
|
|
180
228
|
this.logger.error('unexpcted string', { e });
|
|
181
|
-
|
|
229
|
+
return e;
|
|
182
230
|
}
|
|
183
231
|
e.request = {
|
|
184
232
|
wsKey: resolvedWsKey,
|
|
185
233
|
operation,
|
|
186
|
-
params,
|
|
234
|
+
params: signedEvent.params,
|
|
187
235
|
};
|
|
188
|
-
throw e;
|
|
236
|
+
// throw e;
|
|
237
|
+
return e;
|
|
189
238
|
});
|
|
190
239
|
// this.logger.trace(
|
|
191
240
|
// `sendWSAPIRequest(): sending raw request: ${JSON.stringify(signedEvent)} with promiseRef(${promiseRef})`,
|
|
@@ -226,8 +275,26 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
226
275
|
}
|
|
227
276
|
signWSAPIRequest(requestEvent) {
|
|
228
277
|
return __awaiter(this, void 0, void 0, function* () {
|
|
229
|
-
|
|
230
|
-
|
|
278
|
+
if (!requestEvent.params) {
|
|
279
|
+
return requestEvent;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Not really needed for most commands on Binance. Their WS API supports
|
|
283
|
+
* sending signed WS API commands, but that adds latency to every request.
|
|
284
|
+
*
|
|
285
|
+
* Instead, this SDK will authenticate once after connecting. All requests
|
|
286
|
+
* after authentication can then be sent without sign for maximum speed.
|
|
287
|
+
*/
|
|
288
|
+
const _a = requestEvent.params, { signRequest } = _a, otherParams = __rest(_a, ["signRequest"]);
|
|
289
|
+
if (signRequest) {
|
|
290
|
+
const strictParamValidation = true;
|
|
291
|
+
const encodeValues = true;
|
|
292
|
+
const filterUndefinedParams = true;
|
|
293
|
+
const semiFinalRequestParams = Object.assign({ apiKey: this.options.api_key }, otherParams);
|
|
294
|
+
const serialisedParams = (0, requestUtils_1.serialiseParams)(semiFinalRequestParams, strictParamValidation, encodeValues, filterUndefinedParams);
|
|
295
|
+
const signature = yield this.signMessage(serialisedParams, this.options.api_secret, 'base64', 'SHA-256');
|
|
296
|
+
return Object.assign(Object.assign({}, requestEvent), { params: Object.assign(Object.assign({}, semiFinalRequestParams), { signature }) });
|
|
297
|
+
}
|
|
231
298
|
return requestEvent;
|
|
232
299
|
});
|
|
233
300
|
}
|
|
@@ -238,21 +305,23 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
238
305
|
// If you do not want to specify apiKey and signature in each individual request, you can authenticate your API key for the active WebSocket session.
|
|
239
306
|
// Once authenticated, you no longer have to specify apiKey and signature for those requests that need them. Requests will be performed on behalf of the account owning the authenticated API key.
|
|
240
307
|
// Note: You still have to specify the timestamp parameter for SIGNED requests.
|
|
241
|
-
const
|
|
242
|
-
const timestamp = Date.now() + (this.getTimeOffsetMs() || 0) + recvWindow;
|
|
308
|
+
const timestamp = Date.now() + (this.getTimeOffsetMs() || 0);
|
|
243
309
|
const strictParamValidation = true;
|
|
244
310
|
const encodeValues = true;
|
|
245
311
|
const filterUndefinedParams = true;
|
|
246
|
-
|
|
312
|
+
if (!this.options.api_key || !this.options.api_secret) {
|
|
313
|
+
throw new Error('API key and/or secret missing, unable to prepare WS auth event without valid API keys.');
|
|
314
|
+
}
|
|
315
|
+
const params = {
|
|
247
316
|
apiKey: this.options.api_key,
|
|
248
317
|
timestamp,
|
|
249
318
|
};
|
|
250
|
-
const serialisedParams = (0, requestUtils_1.serialiseParams)(
|
|
319
|
+
const serialisedParams = (0, requestUtils_1.serialiseParams)(params, strictParamValidation, encodeValues, filterUndefinedParams);
|
|
251
320
|
const signature = yield this.signMessage(serialisedParams, this.options.api_secret, 'base64', 'SHA-256');
|
|
252
321
|
const request = {
|
|
253
322
|
id: this.getNewRequestId(),
|
|
254
323
|
method: 'session.logon',
|
|
255
|
-
params: Object.assign(Object.assign({},
|
|
324
|
+
params: Object.assign(Object.assign({}, params), { signature }),
|
|
256
325
|
};
|
|
257
326
|
return request;
|
|
258
327
|
}
|
|
@@ -390,26 +459,71 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
390
459
|
* Abstraction called to sort ws events into emittable event types (response to a request, data update, etc)
|
|
391
460
|
*/
|
|
392
461
|
resolveEmittableEvents(wsKey, event) {
|
|
393
|
-
var _a, _b
|
|
462
|
+
var _a, _b;
|
|
463
|
+
// this.logger.trace(`resolveEmittableEvents(${wsKey}): `, event?.data);
|
|
394
464
|
const results = [];
|
|
395
465
|
try {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
466
|
+
/**
|
|
467
|
+
*
|
|
468
|
+
* Extract event from JSON
|
|
469
|
+
*
|
|
470
|
+
*/
|
|
471
|
+
const parsedEvent = (0, websocket_util_1.parseRawWsMessage)(event);
|
|
472
|
+
/**
|
|
473
|
+
*
|
|
474
|
+
* Minor data normalisation & preparation
|
|
475
|
+
*
|
|
476
|
+
*/
|
|
477
|
+
// ws consumers: { data: ... }
|
|
478
|
+
// ws api consumers (user data): { event: ... }
|
|
479
|
+
// other responses: { ... }
|
|
480
|
+
const eventData = (parsedEvent === null || parsedEvent === void 0 ? void 0 : parsedEvent.data) || (parsedEvent === null || parsedEvent === void 0 ? void 0 : parsedEvent.event) || parsedEvent;
|
|
481
|
+
const parsedEventId = parsedEvent === null || parsedEvent === void 0 ? void 0 : parsedEvent.id;
|
|
482
|
+
const parsedEventErrorCode = (_a = parsedEvent === null || parsedEvent === void 0 ? void 0 : parsedEvent.error) === null || _a === void 0 ? void 0 : _a.code;
|
|
483
|
+
const streamName = parsedEvent === null || parsedEvent === void 0 ? void 0 : parsedEvent.stream;
|
|
484
|
+
const eventType =
|
|
485
|
+
// First try, the child node
|
|
486
|
+
(0, websocket_util_1.parseEventTypeFromMessage)(wsKey, eventData) ||
|
|
487
|
+
// Second try, the parent
|
|
488
|
+
(0, websocket_util_1.parseEventTypeFromMessage)(wsKey, parsedEvent);
|
|
399
489
|
// Some events don't include the topic (event name)
|
|
400
490
|
// This tries to extract and append it, using available context
|
|
401
|
-
(0, requestUtils_1.appendEventIfMissing)(
|
|
491
|
+
(0, requestUtils_1.appendEventIfMissing)(eventData, wsKey, eventType);
|
|
402
492
|
const legacyContext = (0, websocket_util_1.getLegacyWsKeyContext)(wsKey);
|
|
403
|
-
|
|
404
|
-
|
|
493
|
+
const wsMarket = legacyContext
|
|
494
|
+
? legacyContext.market
|
|
495
|
+
: (0, websocket_util_1.resolveUserDataMarketForWsKey)(wsKey);
|
|
496
|
+
// This attaches `wsMarket` and `streamName` to incoming events
|
|
497
|
+
// If the event is an array, it's attached to each element in the array
|
|
498
|
+
if (Array.isArray(eventData)) {
|
|
499
|
+
for (const row of eventData) {
|
|
500
|
+
row.wsMarket = wsMarket;
|
|
501
|
+
if (streamName && !row.streamName) {
|
|
502
|
+
row.streamName = streamName;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
eventData.wsMarket = wsMarket;
|
|
508
|
+
if (streamName && !eventData.streamName) {
|
|
509
|
+
eventData.streamName = streamName;
|
|
510
|
+
}
|
|
405
511
|
}
|
|
512
|
+
/**
|
|
513
|
+
*
|
|
514
|
+
*
|
|
515
|
+
* Main parsing logic below:
|
|
516
|
+
*
|
|
517
|
+
*
|
|
518
|
+
*/
|
|
406
519
|
const traceEmittable = false;
|
|
407
520
|
if (traceEmittable) {
|
|
408
|
-
this.logger.trace('resolveEmittableEvents', Object.assign(Object.assign({}, WS_LOGGER_CATEGORY), { wsKey,
|
|
409
|
-
|
|
521
|
+
this.logger.trace('resolveEmittableEvents', Object.assign(Object.assign({}, WS_LOGGER_CATEGORY), { wsKey, parsedEvent: JSON.stringify(parsedEvent), parsedEventData: JSON.stringify(eventData), eventType, properties: {
|
|
522
|
+
parsedEventId,
|
|
523
|
+
parsedEventErrorCode,
|
|
524
|
+
} }));
|
|
410
525
|
}
|
|
411
|
-
const
|
|
412
|
-
const isWSAPIResponse = typeof parsed.id === 'number';
|
|
526
|
+
const isWSAPIResponse = typeof parsedEventId === 'number';
|
|
413
527
|
const EVENTS_AUTHENTICATED = ['auth'];
|
|
414
528
|
const EVENTS_RESPONSES = [
|
|
415
529
|
'subscribe',
|
|
@@ -454,65 +568,66 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
454
568
|
isWSAPIResponse: true
|
|
455
569
|
}
|
|
456
570
|
*/
|
|
457
|
-
const isError = typeof
|
|
571
|
+
const isError = typeof parsedEventErrorCode === 'number' &&
|
|
572
|
+
parsedEventErrorCode !== 0;
|
|
458
573
|
// This is the counterpart to getPromiseRefForWSAPIRequest
|
|
459
|
-
const promiseRef = [wsKey,
|
|
460
|
-
if (!
|
|
574
|
+
const promiseRef = [wsKey, parsedEventId].join('_');
|
|
575
|
+
if (!parsedEventId) {
|
|
461
576
|
this.logger.error('WS API response is missing reqId - promisified workflow could get stuck. If this happens, please get in touch with steps to reproduce. Trace:', {
|
|
462
577
|
wsKey,
|
|
463
578
|
promiseRef,
|
|
464
|
-
parsedEvent:
|
|
579
|
+
parsedEvent: eventData,
|
|
465
580
|
});
|
|
466
581
|
}
|
|
467
582
|
// WS API Exception
|
|
468
583
|
if (isError) {
|
|
469
584
|
try {
|
|
470
|
-
this.getWsStore().rejectDeferredPromise(wsKey, promiseRef, Object.assign({ wsKey },
|
|
585
|
+
this.getWsStore().rejectDeferredPromise(wsKey, promiseRef, Object.assign({ wsKey }, eventData), true);
|
|
471
586
|
}
|
|
472
587
|
catch (e) {
|
|
473
588
|
this.logger.error('Exception trying to reject WSAPI promise', {
|
|
474
589
|
wsKey,
|
|
475
590
|
promiseRef,
|
|
476
|
-
parsedEvent:
|
|
591
|
+
parsedEvent: eventData,
|
|
477
592
|
e,
|
|
478
593
|
});
|
|
479
594
|
}
|
|
480
595
|
results.push({
|
|
481
596
|
eventType: 'exception',
|
|
482
|
-
event:
|
|
597
|
+
event: eventData,
|
|
483
598
|
isWSAPIResponse: isWSAPIResponse,
|
|
484
599
|
});
|
|
485
600
|
return results;
|
|
486
601
|
}
|
|
487
602
|
// authenticated
|
|
488
|
-
if ((
|
|
603
|
+
if ((_b = eventData.result) === null || _b === void 0 ? void 0 : _b.apiKey) {
|
|
489
604
|
// Note: Without this check, this will also trigger "onWsAuthenticated()" for session.status requests
|
|
490
605
|
if (this.getWsStore().getAuthenticationInProgressPromise(wsKey)) {
|
|
491
606
|
results.push({
|
|
492
607
|
eventType: 'authenticated',
|
|
493
|
-
event:
|
|
608
|
+
event: eventData,
|
|
494
609
|
isWSAPIResponse: isWSAPIResponse,
|
|
495
610
|
});
|
|
496
611
|
}
|
|
497
612
|
}
|
|
498
613
|
// WS API Success
|
|
499
614
|
try {
|
|
500
|
-
this.getWsStore().resolveDeferredPromise(wsKey, promiseRef, Object.assign({ wsKey },
|
|
615
|
+
this.getWsStore().resolveDeferredPromise(wsKey, promiseRef, Object.assign({ wsKey }, eventData), true);
|
|
501
616
|
}
|
|
502
617
|
catch (e) {
|
|
503
618
|
this.logger.error('Exception trying to resolve WSAPI promise', {
|
|
504
619
|
wsKey,
|
|
505
620
|
promiseRef,
|
|
506
|
-
parsedEvent:
|
|
621
|
+
parsedEvent: eventData,
|
|
507
622
|
e,
|
|
508
623
|
});
|
|
509
624
|
}
|
|
510
625
|
results.push({
|
|
511
626
|
eventType: 'response',
|
|
512
|
-
event: Object.assign(Object.assign({},
|
|
627
|
+
event: Object.assign(Object.assign({}, eventData), { request: this.getCachedMidFlightRequest(wsKey, `${parsedEventId}`) }),
|
|
513
628
|
isWSAPIResponse: isWSAPIResponse,
|
|
514
629
|
});
|
|
515
|
-
this.removeCachedMidFlightRequest(wsKey,
|
|
630
|
+
this.removeCachedMidFlightRequest(wsKey, `${parsedEventId}`);
|
|
516
631
|
return results;
|
|
517
632
|
}
|
|
518
633
|
// Handle incoming event that listen key expired
|
|
@@ -522,14 +637,14 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
522
637
|
// handle this how?
|
|
523
638
|
throw new Error('No context found within wsKey - fatal error with expired listen key');
|
|
524
639
|
}
|
|
525
|
-
this.logger.info(`${legacyContext.market} listenKey EXPIRED - attempting to respawn user data stream: ${wsKey}`,
|
|
640
|
+
this.logger.info(`${legacyContext.market} listenKey EXPIRED - attempting to respawn user data stream: ${wsKey}`, eventData);
|
|
526
641
|
// Just closing the connection (with the last parameter as true) will handle cleanup and respawn
|
|
527
642
|
// Automatically leads to triggerCustomReconnectionWorkflow() to handle fresh user data respawn
|
|
528
643
|
this.getUserDataStreamManager().teardownUserDataListenKey(legacyContext.listenKey, this.getWsStore().getWs(wsKey));
|
|
529
644
|
this.executeReconnectableClose(wsKey, 'listenKeyExpired');
|
|
530
645
|
}
|
|
531
646
|
if (this.options.beautify) {
|
|
532
|
-
const beautifiedMessage = this.beautifier.beautifyWsMessage(
|
|
647
|
+
const beautifiedMessage = this.beautifier.beautifyWsMessage(eventData, eventType, false,
|
|
533
648
|
// Suffix all events for the beautifier, if market is options
|
|
534
649
|
// Options has some conflicting keys with different intentions, so will be suffixed
|
|
535
650
|
wsKey === 'eoptions' ? 'Options' : '');
|
|
@@ -540,19 +655,7 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
540
655
|
});
|
|
541
656
|
// emit an additional event for user data messages
|
|
542
657
|
if (!Array.isArray(beautifiedMessage) && eventType) {
|
|
543
|
-
if (
|
|
544
|
-
'balanceUpdate',
|
|
545
|
-
'executionReport',
|
|
546
|
-
'listStatus',
|
|
547
|
-
'listenKeyExpired',
|
|
548
|
-
'outboundAccountPosition',
|
|
549
|
-
'ACCOUNT_CONFIG_UPDATE',
|
|
550
|
-
'ACCOUNT_UPDATE',
|
|
551
|
-
'MARGIN_CALL',
|
|
552
|
-
'ORDER_TRADE_UPDATE',
|
|
553
|
-
'TRADE_LITE',
|
|
554
|
-
'CONDITIONAL_ORDER_TRIGGER_REJECT',
|
|
555
|
-
].includes(eventType)) {
|
|
658
|
+
if (websocket_util_1.EVENT_TYPES_USER_DATA.includes(eventType)) {
|
|
556
659
|
results.push({
|
|
557
660
|
eventType: 'formattedUserDataMessage',
|
|
558
661
|
event: beautifiedMessage,
|
|
@@ -565,25 +668,25 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
565
668
|
if (typeof eventType === 'string') {
|
|
566
669
|
results.push({
|
|
567
670
|
eventType: 'message',
|
|
568
|
-
event: (
|
|
671
|
+
event: (eventData === null || eventData === void 0 ? void 0 : eventData.data) ? eventData.data : eventData,
|
|
569
672
|
});
|
|
570
673
|
return results;
|
|
571
674
|
}
|
|
572
675
|
// Messages that are a "reply" to a request/command (e.g. subscribe to these topics) typically include the "op" property
|
|
573
676
|
if (typeof eventType === 'string') {
|
|
574
677
|
// Failed request
|
|
575
|
-
if (
|
|
678
|
+
if (eventData.success === false) {
|
|
576
679
|
results.push({
|
|
577
680
|
eventType: 'exception',
|
|
578
|
-
event:
|
|
681
|
+
event: eventData,
|
|
579
682
|
});
|
|
580
683
|
return results;
|
|
581
684
|
}
|
|
582
|
-
// These are
|
|
685
|
+
// These are request/reply pattern events (e.g. after subscribing to topics or authenticating)
|
|
583
686
|
if (EVENTS_RESPONSES.includes(eventType)) {
|
|
584
687
|
results.push({
|
|
585
688
|
eventType: 'response',
|
|
586
|
-
event:
|
|
689
|
+
event: eventData,
|
|
587
690
|
});
|
|
588
691
|
return results;
|
|
589
692
|
}
|
|
@@ -591,19 +694,19 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
591
694
|
if (EVENTS_AUTHENTICATED.includes(eventType)) {
|
|
592
695
|
results.push({
|
|
593
696
|
eventType: 'authenticated',
|
|
594
|
-
event:
|
|
697
|
+
event: eventData,
|
|
595
698
|
});
|
|
596
699
|
return results;
|
|
597
700
|
}
|
|
598
|
-
this.logger.error(`!! Unhandled string operation type "${eventType}". Defaulting to "update" channel
|
|
701
|
+
this.logger.error(`!! Unhandled string operation type "${eventType}". Defaulting to "update" channel... raw event:`, JSON.stringify(parsedEvent));
|
|
599
702
|
}
|
|
600
703
|
else {
|
|
601
|
-
this.logger.error(`!!!! Unhandled non-string event type "${eventType}". Defaulting to "update" channel
|
|
704
|
+
this.logger.error(`!!!! Unhandled non-string event type "${eventType}". Defaulting to "update" channel... raw event:`, JSON.stringify(parsedEvent));
|
|
602
705
|
}
|
|
603
706
|
// In case of catastrophic failure, fallback to noisy emit update
|
|
604
707
|
results.push({
|
|
605
708
|
eventType: 'message',
|
|
606
|
-
event:
|
|
709
|
+
event: eventData,
|
|
607
710
|
});
|
|
608
711
|
}
|
|
609
712
|
catch (e) {
|
|
@@ -650,7 +753,9 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
650
753
|
});
|
|
651
754
|
}
|
|
652
755
|
/**
|
|
653
|
-
* Subscribe to spot user data stream - listen key is
|
|
756
|
+
* Subscribe to spot user data stream - listen key is automatically generated. Calling multiple times only opens one connection.
|
|
757
|
+
*
|
|
758
|
+
* Note: the wsKey parameter is optional, but can be used to connect to other environments for this product group (e.g. port 9443 (main) vs 443 (main2))
|
|
654
759
|
*/
|
|
655
760
|
subscribeSpotUserDataStream() {
|
|
656
761
|
return __awaiter(this, arguments, void 0, function* (wsKey = 'main', forceNewConnection, miscState) {
|
|
@@ -672,8 +777,13 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
672
777
|
}
|
|
673
778
|
});
|
|
674
779
|
}
|
|
780
|
+
unsubscribeSpotUserDataStream(wsKey = 'main') {
|
|
781
|
+
return this.closeUserDataStream(wsKey, 'spot');
|
|
782
|
+
}
|
|
675
783
|
/**
|
|
676
|
-
* Subscribe to margin user data stream - listen key is automatically generated.
|
|
784
|
+
* Subscribe to margin user data stream - listen key is automatically generated. Calling multiple times only opens one connection.
|
|
785
|
+
*
|
|
786
|
+
* Note: the wsKey parameter is optional, but can be used to connect to other environments for this product group (e.g. port 9443 (main) vs 443 (main2))
|
|
677
787
|
*/
|
|
678
788
|
subscribeCrossMarginUserDataStream() {
|
|
679
789
|
return __awaiter(this, arguments, void 0, function* (wsKey = 'main', forceNewConnection, miscState) {
|
|
@@ -691,8 +801,13 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
691
801
|
}
|
|
692
802
|
});
|
|
693
803
|
}
|
|
804
|
+
unsubscribeCrossMarginUserDataStream(wsKey = 'main') {
|
|
805
|
+
return this.closeUserDataStream(wsKey, 'crossMargin');
|
|
806
|
+
}
|
|
694
807
|
/**
|
|
695
|
-
* Subscribe to isolated margin user data stream - listen key is automatically generated.
|
|
808
|
+
* Subscribe to isolated margin user data stream - listen key is automatically generated. Calling multiple times only opens one connection.
|
|
809
|
+
*
|
|
810
|
+
* Note: the wsKey parameter is optional, but can be used to connect to other environments for this product group (e.g. port 9443 (main) vs 443 (main2))
|
|
696
811
|
*/
|
|
697
812
|
subscribeIsolatedMarginUserDataStream(symbol_1) {
|
|
698
813
|
return __awaiter(this, arguments, void 0, function* (symbol, wsKey = 'main', forceNewConnection, miscState) {
|
|
@@ -704,17 +819,27 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
704
819
|
symbol: lowerCaseSymbol,
|
|
705
820
|
});
|
|
706
821
|
const market = 'isolatedMargin';
|
|
707
|
-
return this.getUserDataStreamManager().subscribeGeneralUserDataStreamWithListenKey(wsKey, market, listenKey, forceNewConnection, miscState);
|
|
822
|
+
return this.getUserDataStreamManager().subscribeGeneralUserDataStreamWithListenKey(wsKey, market, listenKey, forceNewConnection, Object.assign(Object.assign({}, miscState), { symbol }));
|
|
708
823
|
}
|
|
709
824
|
catch (e) {
|
|
710
825
|
this.logger.error('Failed to connect to isolated margin user data', Object.assign(Object.assign({}, WS_LOGGER_CATEGORY), { error: e, symbol }));
|
|
711
|
-
this.emit('exception',
|
|
712
|
-
|
|
826
|
+
this.emit('exception', {
|
|
827
|
+
functionRef: 'subscribeIsolatedMarginUserDataStream()',
|
|
828
|
+
wsKey,
|
|
829
|
+
forceNewConnection,
|
|
830
|
+
miscState: Object.assign(Object.assign({}, miscState), { symbol }),
|
|
831
|
+
error: (e === null || e === void 0 ? void 0 : e.stack) || e,
|
|
832
|
+
});
|
|
713
833
|
}
|
|
714
834
|
});
|
|
715
835
|
}
|
|
836
|
+
unsubscribeIsolatedMarginUserDataStream(symbol, wsKey = 'main') {
|
|
837
|
+
return this.closeUserDataStream(wsKey, 'isolatedMargin', symbol);
|
|
838
|
+
}
|
|
716
839
|
/**
|
|
717
|
-
* Subscribe to margin risk user data stream - listen key is automatically generated.
|
|
840
|
+
* Subscribe to margin risk user data stream - listen key is automatically generated. Calling multiple times only opens one connection.
|
|
841
|
+
*
|
|
842
|
+
* Note: the wsKey parameter is optional, but can be used to connect to other environments for this product group (e.g. port 9443 (main) vs 443 (main2))
|
|
718
843
|
*/
|
|
719
844
|
subscribeMarginRiskUserDataStream() {
|
|
720
845
|
return __awaiter(this, arguments, void 0, function* (wsKey = 'main', forceNewConnection, miscState) {
|
|
@@ -732,6 +857,116 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
732
857
|
}
|
|
733
858
|
});
|
|
734
859
|
}
|
|
860
|
+
unsubscribeMarginRiskUserDataStream(wsKey = 'main') {
|
|
861
|
+
return this.closeUserDataStream(wsKey, 'riskDataMargin');
|
|
862
|
+
}
|
|
863
|
+
/**
|
|
864
|
+
* --------------------------
|
|
865
|
+
* End of SPOT market websocket streams
|
|
866
|
+
* --------------------------
|
|
867
|
+
**/
|
|
868
|
+
/**
|
|
869
|
+
* Subscribe to USD-M Futures user data stream - listen key is automatically generated. Calling multiple times only opens one connection.
|
|
870
|
+
*
|
|
871
|
+
* Note: the wsKey parameter is optional, but can be used to connect to other environments for this product group.
|
|
872
|
+
*/
|
|
873
|
+
subscribeUsdFuturesUserDataStream() {
|
|
874
|
+
return __awaiter(this, arguments, void 0, function* (wsKey = 'usdm', // usdm | usdmTestnet
|
|
875
|
+
forceNewConnection, miscState) {
|
|
876
|
+
try {
|
|
877
|
+
const isTestnet = wsKey === websocket_util_1.WS_KEY_MAP.usdmTestnet;
|
|
878
|
+
const restClient = this.restClientCache.getUSDMRestClient(this.getRestClientOptions(), this.options.requestOptions);
|
|
879
|
+
const { listenKey } = yield restClient.getFuturesUserDataListenKey();
|
|
880
|
+
const market = isTestnet ? 'usdmTestnet' : 'usdm';
|
|
881
|
+
return this.getUserDataStreamManager().subscribeGeneralUserDataStreamWithListenKey(wsKey, market, listenKey, forceNewConnection, miscState);
|
|
882
|
+
}
|
|
883
|
+
catch (e) {
|
|
884
|
+
this.logger.error('Failed to connect to USD Futures user data', Object.assign(Object.assign({}, WS_LOGGER_CATEGORY), { error: e }));
|
|
885
|
+
this.emit('exception', Object.assign(Object.assign({ functionRef: 'subscribeUsdFuturesUserDataStream()', wsKey,
|
|
886
|
+
forceNewConnection }, miscState), { error: (e === null || e === void 0 ? void 0 : e.stack) || e }));
|
|
887
|
+
}
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
unsubscribeUsdFuturesUserDataStream(wsKey = 'usdm') {
|
|
891
|
+
return this.closeUserDataStream(wsKey, 'usdm');
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Subscribe to COIN-M Futures user data stream - listen key is automatically generated. Calling multiple times only opens one connection.
|
|
895
|
+
*
|
|
896
|
+
* Note: the wsKey parameter is optional, but can be used to connect to other environments for this product group.
|
|
897
|
+
*/
|
|
898
|
+
subscribeCoinFuturesUserDataStream() {
|
|
899
|
+
return __awaiter(this, arguments, void 0, function* (wsKey = 'coinm', // coinm | coinmTestnet
|
|
900
|
+
forceNewConnection, miscState) {
|
|
901
|
+
try {
|
|
902
|
+
const isTestnet = wsKey === websocket_util_1.WS_KEY_MAP.coinmTestnet;
|
|
903
|
+
const { listenKey } = yield this.restClientCache
|
|
904
|
+
.getCOINMRestClient(this.getRestClientOptions(), this.options.requestOptions)
|
|
905
|
+
.getFuturesUserDataListenKey();
|
|
906
|
+
const market = isTestnet ? 'coinmTestnet' : 'coinm';
|
|
907
|
+
return this.getUserDataStreamManager().subscribeGeneralUserDataStreamWithListenKey(wsKey, market, listenKey, forceNewConnection, miscState);
|
|
908
|
+
}
|
|
909
|
+
catch (e) {
|
|
910
|
+
this.logger.error('Failed to connect to COIN Futures user data', Object.assign(Object.assign({}, WS_LOGGER_CATEGORY), { error: e }));
|
|
911
|
+
this.emit('exception', Object.assign(Object.assign({ functionRef: 'subscribeCoinFuturesUserDataStream()', wsKey,
|
|
912
|
+
forceNewConnection }, miscState), { error: (e === null || e === void 0 ? void 0 : e.stack) || e }));
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
unsubscribeCoinFuturesUserDataStream(wsKey = 'coinm') {
|
|
917
|
+
return this.closeUserDataStream(wsKey, 'coinm');
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Subscribe to Portfolio Margin user data stream - listen key is automatically generated. Calling multiple times only opens one connection.
|
|
921
|
+
*
|
|
922
|
+
* Note: the wsKey parameter is optional, but can be used to connect to other environments for this product group.
|
|
923
|
+
*/
|
|
924
|
+
subscribePortfolioMarginUserDataStream() {
|
|
925
|
+
return __awaiter(this, arguments, void 0, function* (wsKey = 'portfolioMarginUserData', forceNewConnection, miscState) {
|
|
926
|
+
try {
|
|
927
|
+
const { listenKey } = yield this.restClientCache
|
|
928
|
+
.getPortfolioClient(this.getRestClientOptions(), this.options.requestOptions)
|
|
929
|
+
.getPMUserDataListenKey();
|
|
930
|
+
const market = 'portfoliom';
|
|
931
|
+
return this.getUserDataStreamManager().subscribeGeneralUserDataStreamWithListenKey(wsKey, market, listenKey, forceNewConnection, miscState);
|
|
932
|
+
}
|
|
933
|
+
catch (e) {
|
|
934
|
+
this.logger.error('Failed to connect to Portfolio Margin user data', Object.assign(Object.assign({}, WS_LOGGER_CATEGORY), { error: e }));
|
|
935
|
+
this.emit('exception', Object.assign(Object.assign({ functionRef: 'subscribePortfolioMarginUserDataStream()', wsKey,
|
|
936
|
+
forceNewConnection }, miscState), { error: (e === null || e === void 0 ? void 0 : e.stack) || e }));
|
|
937
|
+
}
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
unsubscribePortfolioMarginUserDataStream(wsKey = 'portfolioMarginUserData') {
|
|
941
|
+
return this.closeUserDataStream(wsKey, 'portfoliom');
|
|
942
|
+
}
|
|
943
|
+
/**
|
|
944
|
+
* Close an active, dedicated, user data stream connection.
|
|
945
|
+
*
|
|
946
|
+
* @param wsKey - the connection key used to open the connection (excluding any automatic parameters such as the listen key). E.g. 'main' for spot/margin, 'usdm' for futures.
|
|
947
|
+
* @param wsMarket - the product group, recommended if you're subscribed to both spot and margin (since they're on the same wsKey (main)).
|
|
948
|
+
*/
|
|
949
|
+
closeUserDataStream(wsKey, wsMarket, symbol) {
|
|
950
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
951
|
+
const wsKeys = this.getWsStore().getKeys();
|
|
952
|
+
const userDataWsKey = wsKeys.find((key) => {
|
|
953
|
+
if (key === wsKey) {
|
|
954
|
+
return true;
|
|
955
|
+
}
|
|
956
|
+
// built around the assumption in how per-connection listen key wskeys are created
|
|
957
|
+
// isolatedMargin_userData_BTCUSDC_6RszN123x213x1233x213x1233x213xx123x1uzkTV_main
|
|
958
|
+
// coinm_userData__WRAVTxGaQa1Nhd1243312kjn13kj12n3m5wRFv6JoFQgwUR5AEFofZtlk_coinm
|
|
959
|
+
const symbolSuffix = symbol ? '_' + symbol : '';
|
|
960
|
+
const prefixMatch = wsMarket + '_userData' + symbolSuffix;
|
|
961
|
+
return key.startsWith(prefixMatch) && key.endsWith(wsKey);
|
|
962
|
+
});
|
|
963
|
+
if (!userDataWsKey) {
|
|
964
|
+
throw new Error(`No matching connection found with wsKey "${wsKey}". Active connections: ${JSON.stringify(wsKeys)}`);
|
|
965
|
+
}
|
|
966
|
+
// todo: close?
|
|
967
|
+
this.close(userDataWsKey);
|
|
968
|
+
});
|
|
969
|
+
}
|
|
735
970
|
isCustomReconnectionNeeded(wsKey) {
|
|
736
971
|
return wsKey.includes('userData');
|
|
737
972
|
}
|
|
@@ -824,83 +1059,6 @@ class WebsocketClient extends BaseWSClient_1.BaseWebsocketClient {
|
|
|
824
1059
|
}
|
|
825
1060
|
});
|
|
826
1061
|
}
|
|
827
|
-
/**
|
|
828
|
-
* --------------------------
|
|
829
|
-
* End of SPOT market websocket streams
|
|
830
|
-
* --------------------------
|
|
831
|
-
**/
|
|
832
|
-
/**
|
|
833
|
-
* Subscribe to USD-M Futures user data stream - listen key is automatically generated.
|
|
834
|
-
*/
|
|
835
|
-
subscribeUsdFuturesUserDataStream() {
|
|
836
|
-
return __awaiter(this, arguments, void 0, function* (wsKey = 'usdm', // usdm | usdmTestnet
|
|
837
|
-
forceNewConnection, miscState) {
|
|
838
|
-
try {
|
|
839
|
-
const isTestnet = wsKey === websocket_util_1.WS_KEY_MAP.usdmTestnet;
|
|
840
|
-
const restClient = this.restClientCache.getUSDMRestClient(this.getRestClientOptions(), this.options.requestOptions);
|
|
841
|
-
const { listenKey } = yield restClient.getFuturesUserDataListenKey();
|
|
842
|
-
const market = isTestnet ? 'usdmTestnet' : 'usdm';
|
|
843
|
-
return this.getUserDataStreamManager().subscribeGeneralUserDataStreamWithListenKey(wsKey, market, listenKey, forceNewConnection, miscState);
|
|
844
|
-
}
|
|
845
|
-
catch (e) {
|
|
846
|
-
this.logger.error('Failed to connect to USD Futures user data', Object.assign(Object.assign({}, WS_LOGGER_CATEGORY), { error: e }));
|
|
847
|
-
this.emit('exception', Object.assign(Object.assign({ functionRef: 'subscribeUsdFuturesUserDataStream()', wsKey,
|
|
848
|
-
forceNewConnection }, miscState), { error: (e === null || e === void 0 ? void 0 : e.stack) || e }));
|
|
849
|
-
}
|
|
850
|
-
});
|
|
851
|
-
}
|
|
852
|
-
closeUserDataStream() {
|
|
853
|
-
return __awaiter(this, arguments, void 0, function* (wsKey = 'usdm') {
|
|
854
|
-
const wsKeys = this.getWsStore().getKeys();
|
|
855
|
-
const userDataWsKey = wsKeys.find((key) => {
|
|
856
|
-
return key === wsKey || key.startsWith(wsKey + '_userData');
|
|
857
|
-
});
|
|
858
|
-
if (!userDataWsKey) {
|
|
859
|
-
throw new Error(`No matching connection found with wsKey "${wsKey}". Active connections: [${JSON.stringify(wsKey)}]`);
|
|
860
|
-
}
|
|
861
|
-
this.close(userDataWsKey);
|
|
862
|
-
});
|
|
863
|
-
}
|
|
864
|
-
/**
|
|
865
|
-
* Subscribe to COIN-M Futures user data stream - listen key is automatically generated.
|
|
866
|
-
*/
|
|
867
|
-
subscribeCoinFuturesUserDataStream() {
|
|
868
|
-
return __awaiter(this, arguments, void 0, function* (wsKey = 'coinm', // coinm | coinmTestnet
|
|
869
|
-
forceNewConnection, miscState) {
|
|
870
|
-
try {
|
|
871
|
-
const isTestnet = wsKey === websocket_util_1.WS_KEY_MAP.coinmTestnet;
|
|
872
|
-
const { listenKey } = yield this.restClientCache
|
|
873
|
-
.getCOINMRestClient(this.getRestClientOptions(), this.options.requestOptions)
|
|
874
|
-
.getFuturesUserDataListenKey();
|
|
875
|
-
const market = isTestnet ? 'coinmTestnet' : 'coinm';
|
|
876
|
-
return this.getUserDataStreamManager().subscribeGeneralUserDataStreamWithListenKey(wsKey, market, listenKey, forceNewConnection, miscState);
|
|
877
|
-
}
|
|
878
|
-
catch (e) {
|
|
879
|
-
this.logger.error('Failed to connect to COIN Futures user data', Object.assign(Object.assign({}, WS_LOGGER_CATEGORY), { error: e }));
|
|
880
|
-
this.emit('exception', Object.assign(Object.assign({ functionRef: 'subscribeCoinFuturesUserDataStream()', wsKey,
|
|
881
|
-
forceNewConnection }, miscState), { error: (e === null || e === void 0 ? void 0 : e.stack) || e }));
|
|
882
|
-
}
|
|
883
|
-
});
|
|
884
|
-
}
|
|
885
|
-
/**
|
|
886
|
-
* Subscribe to Portfolio Margin user data stream - listen key is automatically generated.
|
|
887
|
-
*/
|
|
888
|
-
subscribePortfolioMarginUserDataStream() {
|
|
889
|
-
return __awaiter(this, arguments, void 0, function* (wsKey = 'portfolioMarginUserData', forceNewConnection, miscState) {
|
|
890
|
-
try {
|
|
891
|
-
const { listenKey } = yield this.restClientCache
|
|
892
|
-
.getPortfolioClient(this.getRestClientOptions(), this.options.requestOptions)
|
|
893
|
-
.getPMUserDataListenKey();
|
|
894
|
-
const market = 'portfoliom';
|
|
895
|
-
return this.getUserDataStreamManager().subscribeGeneralUserDataStreamWithListenKey(wsKey, market, listenKey, forceNewConnection, miscState);
|
|
896
|
-
}
|
|
897
|
-
catch (e) {
|
|
898
|
-
this.logger.error('Failed to connect to Portfolio Margin user data', Object.assign(Object.assign({}, WS_LOGGER_CATEGORY), { error: e }));
|
|
899
|
-
this.emit('exception', Object.assign(Object.assign({ functionRef: 'subscribePortfolioMarginUserDataStream()', wsKey,
|
|
900
|
-
forceNewConnection }, miscState), { error: (e === null || e === void 0 ? void 0 : e.stack) || e }));
|
|
901
|
-
}
|
|
902
|
-
});
|
|
903
|
-
}
|
|
904
1062
|
/**
|
|
905
1063
|
* Subscribe to the European Options user data stream - listen key is automatically generated.
|
|
906
1064
|
*
|