binance 2.15.14 → 3.0.0-beta.1
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 +5 -2
- package/lib/coinm-client.js.map +1 -1
- package/lib/index.d.ts +10 -4
- package/lib/index.js +10 -4
- package/lib/index.js.map +1 -1
- package/lib/main-client.d.ts +13 -2
- package/lib/main-client.js +15 -1
- package/lib/main-client.js.map +1 -1
- package/lib/portfolio-client.js.map +1 -1
- package/lib/types/futures.d.ts +1 -0
- package/lib/types/futures.js +3 -3
- package/lib/types/futures.js.map +1 -1
- package/lib/types/spot.js +4 -4
- package/lib/types/spot.js.map +1 -1
- package/lib/types/websockets/ws-api-requests.d.ts +7 -0
- package/lib/types/websockets/ws-api-requests.js +3 -0
- package/lib/types/websockets/ws-api-requests.js.map +1 -0
- package/lib/types/websockets/ws-api-responses.d.ts +8 -0
- package/lib/types/websockets/ws-api-responses.js +3 -0
- package/lib/types/websockets/ws-api-responses.js.map +1 -0
- package/lib/types/websockets/ws-api.d.ts +201 -0
- package/lib/types/websockets/ws-api.js +29 -0
- package/lib/types/websockets/ws-api.js.map +1 -0
- package/lib/types/{websockets.d.ts → websockets/ws-events-formatted.d.ts} +4 -410
- package/lib/types/websockets/ws-events-formatted.js +3 -0
- package/lib/types/websockets/ws-events-formatted.js.map +1 -0
- package/lib/types/websockets/ws-events-raw.d.ts +401 -0
- package/lib/types/{websockets.js → websockets/ws-events-raw.js} +1 -1
- package/lib/types/websockets/ws-events-raw.js.map +1 -0
- package/lib/types/websockets/ws-general.d.ts +98 -0
- package/lib/types/websockets/ws-general.js +11 -0
- package/lib/types/websockets/ws-general.js.map +1 -0
- package/lib/usdm-client.js.map +1 -1
- package/lib/util/BaseRestClient.d.ts +1 -1
- package/lib/util/BaseRestClient.js +1 -1
- package/lib/util/BaseRestClient.js.map +1 -1
- package/lib/util/BaseWSClient.d.ts +225 -0
- package/lib/util/BaseWSClient.js +729 -0
- package/lib/util/BaseWSClient.js.map +1 -0
- package/lib/util/beautifier-maps.d.ts +151 -0
- package/lib/util/beautifier-maps.js +198 -37
- package/lib/util/beautifier-maps.js.map +1 -1
- package/lib/util/beautifier.d.ts +7 -3
- package/lib/util/beautifier.js +40 -11
- package/lib/util/beautifier.js.map +1 -1
- package/lib/util/browser-support.d.ts +2 -1
- package/lib/util/browser-support.js +46 -28
- package/lib/util/browser-support.js.map +1 -1
- package/lib/util/logger.d.ts +8 -0
- package/lib/util/logger.js +17 -0
- package/lib/util/logger.js.map +1 -0
- package/lib/util/node-support.d.ts +2 -1
- package/lib/util/node-support.js +35 -15
- package/lib/util/node-support.js.map +1 -1
- package/lib/util/requestUtils.d.ts +19 -19
- package/lib/util/requestUtils.js +119 -38
- package/lib/util/requestUtils.js.map +1 -1
- package/lib/util/typeGuards.d.ts +9 -1
- package/lib/util/typeGuards.js +59 -34
- package/lib/util/typeGuards.js.map +1 -1
- package/lib/util/usdm/exchangeInfo.js +2 -3
- package/lib/util/usdm/exchangeInfo.js.map +1 -1
- package/lib/util/webCryptoAPI.d.ts +14 -0
- package/lib/util/webCryptoAPI.js +120 -0
- package/lib/util/webCryptoAPI.js.map +1 -0
- package/lib/util/websockets/WsStore.d.ts +74 -0
- package/lib/util/websockets/WsStore.js +279 -0
- package/lib/util/websockets/WsStore.js.map +1 -0
- package/lib/util/websockets/WsStore.types.d.ts +53 -0
- package/lib/util/websockets/WsStore.types.js +14 -0
- package/lib/util/websockets/WsStore.types.js.map +1 -0
- package/lib/util/websockets/listen-key-state-cache.d.ts +21 -0
- package/lib/util/websockets/listen-key-state-cache.js +80 -0
- package/lib/util/websockets/listen-key-state-cache.js.map +1 -0
- package/lib/util/websockets/rest-client-cache.d.ts +13 -0
- package/lib/util/websockets/rest-client-cache.js +56 -0
- package/lib/util/websockets/rest-client-cache.js.map +1 -0
- package/lib/util/websockets/user-data-stream-manager.d.ts +54 -0
- package/lib/util/websockets/user-data-stream-manager.js +256 -0
- package/lib/util/websockets/user-data-stream-manager.js.map +1 -0
- package/lib/util/websockets/websocket-util.d.ts +124 -0
- package/lib/util/websockets/websocket-util.js +481 -0
- package/lib/util/websockets/websocket-util.js.map +1 -0
- package/lib/websocket-client-legacy.d.ts +288 -0
- package/lib/websocket-client-legacy.js +1113 -0
- package/lib/websocket-client-legacy.js.map +1 -0
- package/lib/websocket-client.d.ts +228 -168
- package/lib/websocket-client.js +927 -834
- package/lib/websocket-client.js.map +1 -1
- package/package.json +5 -5
- package/lib/logger.d.ts +0 -9
- package/lib/logger.js +0 -23
- package/lib/logger.js.map +0 -1
- package/lib/types/websockets.js.map +0 -1
- package/lib/util/WsStore.d.ts +0 -57
- package/lib/util/WsStore.js +0 -101
- package/lib/util/WsStore.js.map +0 -1
- package/lib/util/ws-utils.d.ts +0 -7
- package/lib/util/ws-utils.js +0 -16
- package/lib/util/ws-utils.js.map +0 -1
|
@@ -0,0 +1,120 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getSignKeyType = getSignKeyType;
|
|
13
|
+
exports.signMessage = signMessage;
|
|
14
|
+
const typeGuards_1 = require("./typeGuards");
|
|
15
|
+
function bufferToB64(buffer) {
|
|
16
|
+
let binary = '';
|
|
17
|
+
const bytes = new Uint8Array(buffer);
|
|
18
|
+
const len = bytes.byteLength;
|
|
19
|
+
for (let i = 0; i < len; i++) {
|
|
20
|
+
binary += String.fromCharCode(bytes[i]);
|
|
21
|
+
}
|
|
22
|
+
return globalThis.btoa(binary);
|
|
23
|
+
}
|
|
24
|
+
function getSignKeyType(secret) {
|
|
25
|
+
if (secret.includes('PRIVATE KEY')) {
|
|
26
|
+
if (secret.includes('RSA PRIVATE KEY')) {
|
|
27
|
+
return 'RSASSA-PKCS1-v1_5';
|
|
28
|
+
}
|
|
29
|
+
return 'Ed25519';
|
|
30
|
+
}
|
|
31
|
+
return 'HMAC';
|
|
32
|
+
}
|
|
33
|
+
// async function importEd25519PrivateKey(
|
|
34
|
+
// pem: string,
|
|
35
|
+
// algorithm: SignAlgorithm,
|
|
36
|
+
// ): Promise<CryptoKey> {
|
|
37
|
+
// const base64Key = pem
|
|
38
|
+
// .replace(/-----BEGIN PRIVATE KEY-----/, '')
|
|
39
|
+
// .replace(/-----END PRIVATE KEY-----/, '')
|
|
40
|
+
// .replace(/\s+/g, ''); // Remove spaces and newlines
|
|
41
|
+
// const binaryKey = Uint8Array.from(atob(base64Key), (c) => c.charCodeAt(0));
|
|
42
|
+
// return crypto.subtle.importKey(
|
|
43
|
+
// 'pkcs8',
|
|
44
|
+
// binaryKey.buffer,
|
|
45
|
+
// { name: 'Ed25519', hash: { name: algorithm } },
|
|
46
|
+
// false,
|
|
47
|
+
// ['sign'],
|
|
48
|
+
// );
|
|
49
|
+
// }
|
|
50
|
+
// async function importRSAPrivateKey(
|
|
51
|
+
// pem: string,
|
|
52
|
+
// algorithm: SignAlgorithm,
|
|
53
|
+
// ): Promise<CryptoKey> {
|
|
54
|
+
// const base64Key = pem
|
|
55
|
+
// .replace(/-----BEGIN RSA PRIVATE KEY-----/, '')
|
|
56
|
+
// .replace(/-----END RSA PRIVATE KEY-----/, '')
|
|
57
|
+
// .replace(/\s+/g, ''); // Remove spaces and newlines
|
|
58
|
+
// const binaryKey = Uint8Array.from(atob(base64Key), (c) => c.charCodeAt(0));
|
|
59
|
+
// return crypto.subtle.importKey(
|
|
60
|
+
// 'pkcs8',
|
|
61
|
+
// binaryKey.buffer,
|
|
62
|
+
// { name: 'RSASSA-PKCS1-v1_5', hash: { name: algorithm } },
|
|
63
|
+
// false,
|
|
64
|
+
// ['sign'],
|
|
65
|
+
// );
|
|
66
|
+
// }
|
|
67
|
+
function importKey(pem, type, algorithm, encoder) {
|
|
68
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
+
switch (type) {
|
|
70
|
+
case 'Ed25519':
|
|
71
|
+
case 'RSASSA-PKCS1-v1_5': {
|
|
72
|
+
const prefix = type === 'Ed25519'
|
|
73
|
+
? /-----BEGIN PRIVATE KEY-----/
|
|
74
|
+
: /-----BEGIN RSA PRIVATE KEY-----/;
|
|
75
|
+
const suffix = type === 'Ed25519'
|
|
76
|
+
? /-----END PRIVATE KEY-----/
|
|
77
|
+
: /-----END RSA PRIVATE KEY-----/;
|
|
78
|
+
const base64Key = pem
|
|
79
|
+
.replace(prefix, '')
|
|
80
|
+
.replace(suffix, '')
|
|
81
|
+
.replace(/\s+/g, ''); // Remove spaces and newlines
|
|
82
|
+
const binaryKey = Uint8Array.from(atob(base64Key), (c) => c.charCodeAt(0));
|
|
83
|
+
return crypto.subtle.importKey('pkcs8', binaryKey.buffer, { name: type, hash: { name: algorithm } }, false, ['sign']);
|
|
84
|
+
}
|
|
85
|
+
case 'HMAC': {
|
|
86
|
+
return globalThis.crypto.subtle.importKey('raw', encoder.encode(pem), { name: type, hash: algorithm }, false, ['sign']);
|
|
87
|
+
}
|
|
88
|
+
default: {
|
|
89
|
+
throw (0, typeGuards_1.neverGuard)(type, `Unhandled key type: "${type}"`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Sign a message, with a secret, using the Web Crypto API
|
|
96
|
+
*
|
|
97
|
+
* Ed25519 is stable as of v23.5.0, but also not available in all browsers
|
|
98
|
+
*/
|
|
99
|
+
function signMessage(message_1, secret_1, method_1, algorithm_1) {
|
|
100
|
+
return __awaiter(this, arguments, void 0, function* (message, secret, method, algorithm, pemEncodeMethod = method) {
|
|
101
|
+
const encoder = new TextEncoder();
|
|
102
|
+
const signKeyType = getSignKeyType(secret);
|
|
103
|
+
const key = yield importKey(secret, signKeyType, algorithm, encoder);
|
|
104
|
+
const buffer = yield globalThis.crypto.subtle.sign({ name: signKeyType }, key, encoder.encode(message));
|
|
105
|
+
switch (method) {
|
|
106
|
+
case 'hex': {
|
|
107
|
+
return Array.from(new Uint8Array(buffer))
|
|
108
|
+
.map((byte) => byte.toString(16).padStart(2, '0'))
|
|
109
|
+
.join('');
|
|
110
|
+
}
|
|
111
|
+
case 'base64': {
|
|
112
|
+
return bufferToB64(buffer);
|
|
113
|
+
}
|
|
114
|
+
default: {
|
|
115
|
+
throw (0, typeGuards_1.neverGuard)(method, `Unhandled sign method: "${method}"`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=webCryptoAPI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webCryptoAPI.js","sourceRoot":"","sources":["../../src/util/webCryptoAPI.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import WebSocket from 'isomorphic-ws';
|
|
2
|
+
import { DefaultLogger } from '../logger';
|
|
3
|
+
import { DeferredPromise, WSConnectedResult, WsConnectionStateEnum, WsStoredState } from './WsStore.types';
|
|
4
|
+
/**
|
|
5
|
+
* Simple comparison of two objects, only checks 1-level deep (nested objects won't match)
|
|
6
|
+
*/
|
|
7
|
+
export declare function isDeepObjectMatch(object1: unknown, object2: unknown): boolean;
|
|
8
|
+
export declare const DEFERRED_PROMISE_REF: {
|
|
9
|
+
readonly CONNECTION_IN_PROGRESS: "CONNECTION_IN_PROGRESS";
|
|
10
|
+
readonly AUTHENTICATION_IN_PROGRESS: "AUTHENTICATION_IN_PROGRESS";
|
|
11
|
+
};
|
|
12
|
+
type DeferredPromiseRef = (typeof DEFERRED_PROMISE_REF)[keyof typeof DEFERRED_PROMISE_REF];
|
|
13
|
+
export declare class WsStore<WsKey extends string, TWSTopicSubscribeEventArgs extends string | object> {
|
|
14
|
+
private wsState;
|
|
15
|
+
private logger;
|
|
16
|
+
constructor(logger: DefaultLogger);
|
|
17
|
+
/** Get WS stored state for key, optionally create if missing */
|
|
18
|
+
get(key: WsKey, createIfMissing?: true): WsStoredState<TWSTopicSubscribeEventArgs>;
|
|
19
|
+
get(key: WsKey, createIfMissing?: false): WsStoredState<TWSTopicSubscribeEventArgs> | undefined;
|
|
20
|
+
getKeys(): WsKey[];
|
|
21
|
+
create(key: WsKey): WsStoredState<TWSTopicSubscribeEventArgs> | undefined;
|
|
22
|
+
delete(key: WsKey): void;
|
|
23
|
+
hasExistingActiveConnection(key: WsKey): boolean;
|
|
24
|
+
getWs(key: WsKey): WebSocket | undefined;
|
|
25
|
+
setWs(key: WsKey, wsConnection: WebSocket): WebSocket;
|
|
26
|
+
/**
|
|
27
|
+
* deferred promises
|
|
28
|
+
*/
|
|
29
|
+
getDeferredPromise<TSuccessResult = any>(wsKey: WsKey, promiseRef: string | DeferredPromiseRef): DeferredPromise<TSuccessResult> | undefined;
|
|
30
|
+
createDeferredPromise<TSuccessResult = any>(wsKey: WsKey, promiseRef: string | DeferredPromiseRef, throwIfExists: boolean): DeferredPromise<TSuccessResult>;
|
|
31
|
+
resolveDeferredPromise(wsKey: WsKey, promiseRef: string | DeferredPromiseRef, value: unknown, removeAfter: boolean): void;
|
|
32
|
+
rejectDeferredPromise(wsKey: WsKey, promiseRef: string | DeferredPromiseRef, value: unknown, removeAfter: boolean): void;
|
|
33
|
+
removeDeferredPromise(wsKey: WsKey, promiseRef: string | DeferredPromiseRef): void;
|
|
34
|
+
rejectAllDeferredPromises(wsKey: WsKey, reason: string): void;
|
|
35
|
+
/** Get promise designed to track a connection attempt in progress. Resolves once connected. */
|
|
36
|
+
getConnectionInProgressPromise(wsKey: WsKey): DeferredPromise<WSConnectedResult> | undefined;
|
|
37
|
+
getAuthenticationInProgressPromise(wsKey: WsKey): DeferredPromise<WSConnectedResult & {
|
|
38
|
+
event: any;
|
|
39
|
+
}> | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Create a deferred promise designed to track a connection attempt in progress.
|
|
42
|
+
*
|
|
43
|
+
* Will throw if existing promise is found.
|
|
44
|
+
*/
|
|
45
|
+
createConnectionInProgressPromise(wsKey: WsKey, throwIfExists: boolean): DeferredPromise<WSConnectedResult>;
|
|
46
|
+
createAuthenticationInProgressPromise(wsKey: WsKey, throwIfExists: boolean): DeferredPromise<WSConnectedResult & {
|
|
47
|
+
event: any;
|
|
48
|
+
}>;
|
|
49
|
+
/** Remove promise designed to track a connection attempt in progress */
|
|
50
|
+
removeConnectingInProgressPromise(wsKey: WsKey): void;
|
|
51
|
+
removeAuthenticationInProgressPromise(wsKey: WsKey): void;
|
|
52
|
+
isWsOpen(key: WsKey): boolean;
|
|
53
|
+
getConnectionState(key: WsKey): WsConnectionStateEnum;
|
|
54
|
+
setConnectionState(key: WsKey, state: WsConnectionStateEnum): void;
|
|
55
|
+
isConnectionState(key: WsKey, state: WsConnectionStateEnum): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Check if we're currently in the process of opening a connection for any reason. Safer than only checking "CONNECTING" as the state
|
|
58
|
+
* @param key
|
|
59
|
+
* @returns
|
|
60
|
+
*/
|
|
61
|
+
isConnectionAttemptInProgress(key: WsKey): boolean;
|
|
62
|
+
getTopics(key: WsKey): Set<TWSTopicSubscribeEventArgs>;
|
|
63
|
+
getTopicsByKey(): Record<string, Set<TWSTopicSubscribeEventArgs>>;
|
|
64
|
+
/**
|
|
65
|
+
* Find matching "topic" request from the store
|
|
66
|
+
* @param key
|
|
67
|
+
* @param topic
|
|
68
|
+
* @returns
|
|
69
|
+
*/
|
|
70
|
+
getMatchingTopic(key: WsKey, topic: TWSTopicSubscribeEventArgs): TWSTopicSubscribeEventArgs | undefined;
|
|
71
|
+
addTopic(key: WsKey, topic: TWSTopicSubscribeEventArgs): Set<TWSTopicSubscribeEventArgs>;
|
|
72
|
+
deleteTopic(key: WsKey, topic: TWSTopicSubscribeEventArgs): Set<TWSTopicSubscribeEventArgs>;
|
|
73
|
+
}
|
|
74
|
+
export {};
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WsStore = exports.DEFERRED_PROMISE_REF = void 0;
|
|
4
|
+
exports.isDeepObjectMatch = isDeepObjectMatch;
|
|
5
|
+
const logger_1 = require("../logger");
|
|
6
|
+
const WsStore_types_1 = require("./WsStore.types");
|
|
7
|
+
/**
|
|
8
|
+
* Simple comparison of two objects, only checks 1-level deep (nested objects won't match)
|
|
9
|
+
*/
|
|
10
|
+
function isDeepObjectMatch(object1, object2) {
|
|
11
|
+
if (typeof object1 === 'string' && typeof object2 === 'string') {
|
|
12
|
+
return object1 === object2;
|
|
13
|
+
}
|
|
14
|
+
if (typeof object1 !== 'object' || typeof object2 !== 'object') {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
for (const key in object1) {
|
|
18
|
+
const value1 = object1[key];
|
|
19
|
+
const value2 = object2[key];
|
|
20
|
+
if (value1 !== value2) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
exports.DEFERRED_PROMISE_REF = {
|
|
27
|
+
CONNECTION_IN_PROGRESS: 'CONNECTION_IN_PROGRESS',
|
|
28
|
+
AUTHENTICATION_IN_PROGRESS: 'AUTHENTICATION_IN_PROGRESS',
|
|
29
|
+
};
|
|
30
|
+
class WsStore {
|
|
31
|
+
constructor(logger) {
|
|
32
|
+
this.wsState = {};
|
|
33
|
+
this.logger = logger || logger_1.DefaultLogger;
|
|
34
|
+
}
|
|
35
|
+
get(key, createIfMissing) {
|
|
36
|
+
if (this.wsState[key]) {
|
|
37
|
+
return this.wsState[key];
|
|
38
|
+
}
|
|
39
|
+
if (createIfMissing) {
|
|
40
|
+
return this.create(key);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
getKeys() {
|
|
44
|
+
return Object.keys(this.wsState);
|
|
45
|
+
}
|
|
46
|
+
create(key) {
|
|
47
|
+
if (this.hasExistingActiveConnection(key)) {
|
|
48
|
+
this.logger.info('WsStore setConnection() overwriting existing open connection: ', this.getWs(key));
|
|
49
|
+
}
|
|
50
|
+
this.wsState[key] = {
|
|
51
|
+
subscribedTopics: new Set(),
|
|
52
|
+
connectionState: WsStore_types_1.WsConnectionStateEnum.INITIAL,
|
|
53
|
+
deferredPromiseStore: {},
|
|
54
|
+
};
|
|
55
|
+
return this.get(key);
|
|
56
|
+
}
|
|
57
|
+
delete(key) {
|
|
58
|
+
// TODO: should we allow this at all? Perhaps block this from happening...
|
|
59
|
+
if (this.hasExistingActiveConnection(key)) {
|
|
60
|
+
const ws = this.getWs(key);
|
|
61
|
+
this.logger.info('WsStore deleting state for connection still open: ', ws);
|
|
62
|
+
ws === null || ws === void 0 ? void 0 : ws.close();
|
|
63
|
+
}
|
|
64
|
+
delete this.wsState[key];
|
|
65
|
+
}
|
|
66
|
+
/* connection websocket */
|
|
67
|
+
hasExistingActiveConnection(key) {
|
|
68
|
+
return this.get(key) && this.isWsOpen(key);
|
|
69
|
+
}
|
|
70
|
+
getWs(key) {
|
|
71
|
+
var _a;
|
|
72
|
+
return (_a = this.get(key)) === null || _a === void 0 ? void 0 : _a.ws;
|
|
73
|
+
}
|
|
74
|
+
setWs(key, wsConnection) {
|
|
75
|
+
if (this.isWsOpen(key)) {
|
|
76
|
+
this.logger.info('WsStore setConnection() overwriting existing open connection: ', this.getWs(key));
|
|
77
|
+
}
|
|
78
|
+
this.get(key, true).ws = wsConnection;
|
|
79
|
+
return wsConnection;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* deferred promises
|
|
83
|
+
*/
|
|
84
|
+
getDeferredPromise(wsKey, promiseRef) {
|
|
85
|
+
const storeForKey = this.get(wsKey);
|
|
86
|
+
if (!storeForKey) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const deferredPromiseStore = storeForKey.deferredPromiseStore;
|
|
90
|
+
return deferredPromiseStore[promiseRef];
|
|
91
|
+
}
|
|
92
|
+
createDeferredPromise(wsKey, promiseRef, throwIfExists) {
|
|
93
|
+
const existingPromise = this.getDeferredPromise(wsKey, promiseRef);
|
|
94
|
+
if (existingPromise) {
|
|
95
|
+
if (throwIfExists) {
|
|
96
|
+
throw new Error(`Promise exists for "${wsKey}"`);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
// console.log('existing promise');
|
|
100
|
+
return existingPromise;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// console.log('create promise');
|
|
104
|
+
const createIfMissing = true;
|
|
105
|
+
const storeForKey = this.get(wsKey, createIfMissing);
|
|
106
|
+
// TODO: Once stable, use Promise.withResolvers in future
|
|
107
|
+
const deferredPromise = {};
|
|
108
|
+
deferredPromise.promise = new Promise((resolve, reject) => {
|
|
109
|
+
deferredPromise.resolve = resolve;
|
|
110
|
+
deferredPromise.reject = reject;
|
|
111
|
+
});
|
|
112
|
+
const deferredPromiseStore = storeForKey.deferredPromiseStore;
|
|
113
|
+
deferredPromiseStore[promiseRef] = deferredPromise;
|
|
114
|
+
return deferredPromise;
|
|
115
|
+
}
|
|
116
|
+
resolveDeferredPromise(wsKey, promiseRef, value, removeAfter) {
|
|
117
|
+
const promise = this.getDeferredPromise(wsKey, promiseRef);
|
|
118
|
+
if (promise === null || promise === void 0 ? void 0 : promise.resolve) {
|
|
119
|
+
promise.resolve(value);
|
|
120
|
+
}
|
|
121
|
+
if (removeAfter) {
|
|
122
|
+
this.removeDeferredPromise(wsKey, promiseRef);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
rejectDeferredPromise(wsKey, promiseRef, value, removeAfter) {
|
|
126
|
+
const promise = this.getDeferredPromise(wsKey, promiseRef);
|
|
127
|
+
if (promise === null || promise === void 0 ? void 0 : promise.reject) {
|
|
128
|
+
this.logger.trace(`rejectDeferredPromise(): rejecting ${wsKey}/${promiseRef}/${value}`);
|
|
129
|
+
promise.reject(value);
|
|
130
|
+
}
|
|
131
|
+
if (removeAfter) {
|
|
132
|
+
this.removeDeferredPromise(wsKey, promiseRef);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
removeDeferredPromise(wsKey, promiseRef) {
|
|
136
|
+
const storeForKey = this.get(wsKey);
|
|
137
|
+
if (!storeForKey) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const deferredPromise = storeForKey.deferredPromiseStore[promiseRef];
|
|
141
|
+
if (deferredPromise) {
|
|
142
|
+
// Just in case it's pending
|
|
143
|
+
if (deferredPromise.resolve) {
|
|
144
|
+
deferredPromise.resolve('promiseRemoved');
|
|
145
|
+
}
|
|
146
|
+
delete storeForKey.deferredPromiseStore[promiseRef];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
rejectAllDeferredPromises(wsKey, reason) {
|
|
150
|
+
const storeForKey = this.get(wsKey);
|
|
151
|
+
const deferredPromiseStore = storeForKey.deferredPromiseStore;
|
|
152
|
+
if (!storeForKey || !deferredPromiseStore) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const reservedKeys = Object.values(exports.DEFERRED_PROMISE_REF);
|
|
156
|
+
for (const promiseRef in deferredPromiseStore) {
|
|
157
|
+
// Skip reserved keys, such as the connection promise
|
|
158
|
+
if (reservedKeys.includes(promiseRef)) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
this.logger.trace(`rejectAllDeferredPromises(): rejecting ${wsKey}/${promiseRef}/${reason}`);
|
|
163
|
+
this.rejectDeferredPromise(wsKey, promiseRef, reason, true);
|
|
164
|
+
}
|
|
165
|
+
catch (e) {
|
|
166
|
+
this.logger.error('rejectAllDeferredPromises(): Exception rejecting deferred promise', { wsKey: wsKey, reason, promiseRef, exception: e });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/** Get promise designed to track a connection attempt in progress. Resolves once connected. */
|
|
171
|
+
getConnectionInProgressPromise(wsKey) {
|
|
172
|
+
return this.getDeferredPromise(wsKey, exports.DEFERRED_PROMISE_REF.CONNECTION_IN_PROGRESS);
|
|
173
|
+
}
|
|
174
|
+
getAuthenticationInProgressPromise(wsKey) {
|
|
175
|
+
return this.getDeferredPromise(wsKey, exports.DEFERRED_PROMISE_REF.AUTHENTICATION_IN_PROGRESS);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Create a deferred promise designed to track a connection attempt in progress.
|
|
179
|
+
*
|
|
180
|
+
* Will throw if existing promise is found.
|
|
181
|
+
*/
|
|
182
|
+
createConnectionInProgressPromise(wsKey, throwIfExists) {
|
|
183
|
+
return this.createDeferredPromise(wsKey, exports.DEFERRED_PROMISE_REF.CONNECTION_IN_PROGRESS, throwIfExists);
|
|
184
|
+
}
|
|
185
|
+
createAuthenticationInProgressPromise(wsKey, throwIfExists) {
|
|
186
|
+
return this.createDeferredPromise(wsKey, exports.DEFERRED_PROMISE_REF.AUTHENTICATION_IN_PROGRESS, throwIfExists);
|
|
187
|
+
}
|
|
188
|
+
/** Remove promise designed to track a connection attempt in progress */
|
|
189
|
+
removeConnectingInProgressPromise(wsKey) {
|
|
190
|
+
return this.removeDeferredPromise(wsKey, exports.DEFERRED_PROMISE_REF.CONNECTION_IN_PROGRESS);
|
|
191
|
+
}
|
|
192
|
+
removeAuthenticationInProgressPromise(wsKey) {
|
|
193
|
+
return this.removeDeferredPromise(wsKey, exports.DEFERRED_PROMISE_REF.AUTHENTICATION_IN_PROGRESS);
|
|
194
|
+
}
|
|
195
|
+
/* connection state */
|
|
196
|
+
isWsOpen(key) {
|
|
197
|
+
const existingConnection = this.getWs(key);
|
|
198
|
+
return (!!existingConnection &&
|
|
199
|
+
existingConnection.readyState === existingConnection.OPEN);
|
|
200
|
+
}
|
|
201
|
+
getConnectionState(key) {
|
|
202
|
+
return this.get(key, true).connectionState;
|
|
203
|
+
}
|
|
204
|
+
setConnectionState(key, state) {
|
|
205
|
+
this.get(key, true).connectionState = state;
|
|
206
|
+
this.get(key, true).connectionStateChangedAt = new Date();
|
|
207
|
+
}
|
|
208
|
+
isConnectionState(key, state) {
|
|
209
|
+
return this.getConnectionState(key) === state;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Check if we're currently in the process of opening a connection for any reason. Safer than only checking "CONNECTING" as the state
|
|
213
|
+
* @param key
|
|
214
|
+
* @returns
|
|
215
|
+
*/
|
|
216
|
+
isConnectionAttemptInProgress(key) {
|
|
217
|
+
const isConnectionInProgress = this.isConnectionState(key, WsStore_types_1.WsConnectionStateEnum.CONNECTING) ||
|
|
218
|
+
this.isConnectionState(key, WsStore_types_1.WsConnectionStateEnum.RECONNECTING);
|
|
219
|
+
if (isConnectionInProgress) {
|
|
220
|
+
const wsState = this.get(key, true);
|
|
221
|
+
const stateLastChangedAt = wsState === null || wsState === void 0 ? void 0 : wsState.connectionStateChangedAt;
|
|
222
|
+
const stateChangedAtTimestamp = stateLastChangedAt === null || stateLastChangedAt === void 0 ? void 0 : stateLastChangedAt.getTime();
|
|
223
|
+
if (stateChangedAtTimestamp) {
|
|
224
|
+
const timestampNow = new Date().getTime();
|
|
225
|
+
const stateChangedTimeAgo = timestampNow - stateChangedAtTimestamp;
|
|
226
|
+
const stateChangeTimeout = 15000; // allow a max 15 second timeout since the last state change before assuming stuck;
|
|
227
|
+
if (stateChangedTimeAgo >= stateChangeTimeout) {
|
|
228
|
+
const msg = 'State change timed out, reconnect workflow stuck?';
|
|
229
|
+
this.logger.error(msg, { key, wsState });
|
|
230
|
+
this.setConnectionState(key, WsStore_types_1.WsConnectionStateEnum.ERROR);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return isConnectionInProgress;
|
|
235
|
+
}
|
|
236
|
+
/* subscribed topics */
|
|
237
|
+
getTopics(key) {
|
|
238
|
+
return this.get(key, true).subscribedTopics;
|
|
239
|
+
}
|
|
240
|
+
getTopicsByKey() {
|
|
241
|
+
const result = {};
|
|
242
|
+
for (const refKey in this.wsState) {
|
|
243
|
+
result[refKey] = this.getTopics(refKey);
|
|
244
|
+
}
|
|
245
|
+
return result;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Find matching "topic" request from the store
|
|
249
|
+
* @param key
|
|
250
|
+
* @param topic
|
|
251
|
+
* @returns
|
|
252
|
+
*/
|
|
253
|
+
getMatchingTopic(key, topic) {
|
|
254
|
+
const allTopics = this.getTopics(key).values();
|
|
255
|
+
for (const storedTopic of allTopics) {
|
|
256
|
+
if (isDeepObjectMatch(topic, storedTopic)) {
|
|
257
|
+
return storedTopic;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
addTopic(key, topic) {
|
|
262
|
+
// Check for duplicate topic. If already tracked, don't store this one
|
|
263
|
+
const existingTopic = this.getMatchingTopic(key, topic);
|
|
264
|
+
if (existingTopic) {
|
|
265
|
+
return this.getTopics(key);
|
|
266
|
+
}
|
|
267
|
+
return this.getTopics(key).add(topic);
|
|
268
|
+
}
|
|
269
|
+
deleteTopic(key, topic) {
|
|
270
|
+
// Check if we're subscribed to a topic like this
|
|
271
|
+
const storedTopic = this.getMatchingTopic(key, topic);
|
|
272
|
+
if (storedTopic) {
|
|
273
|
+
this.getTopics(key).delete(storedTopic);
|
|
274
|
+
}
|
|
275
|
+
return this.getTopics(key);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
exports.WsStore = WsStore;
|
|
279
|
+
//# sourceMappingURL=WsStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WsStore.js","sourceRoot":"","sources":["../../../src/util/websockets/WsStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import WebSocket from 'isomorphic-ws';
|
|
2
|
+
export declare enum WsConnectionStateEnum {
|
|
3
|
+
INITIAL = 0,
|
|
4
|
+
CONNECTING = 1,
|
|
5
|
+
CONNECTED = 2,
|
|
6
|
+
CLOSING = 3,
|
|
7
|
+
RECONNECTING = 4,
|
|
8
|
+
ERROR = 5
|
|
9
|
+
}
|
|
10
|
+
export interface DeferredPromise<TSuccess = any, TError = any> {
|
|
11
|
+
resolve?: (value: TSuccess) => TSuccess;
|
|
12
|
+
reject?: (value: TError) => TError;
|
|
13
|
+
promise?: Promise<TSuccess>;
|
|
14
|
+
}
|
|
15
|
+
export interface WSConnectedResult {
|
|
16
|
+
wsKey: string;
|
|
17
|
+
ws: WebSocket;
|
|
18
|
+
}
|
|
19
|
+
export interface WsStoredState<TWSTopicSubscribeEvent extends string | object> {
|
|
20
|
+
/** The currently active websocket connection */
|
|
21
|
+
ws?: WebSocket;
|
|
22
|
+
/** The current lifecycle state of the connection (enum) */
|
|
23
|
+
connectionState?: WsConnectionStateEnum;
|
|
24
|
+
connectionStateChangedAt?: Date;
|
|
25
|
+
/** A timer that will send an upstream heartbeat (ping) when it expires */
|
|
26
|
+
activePingTimer?: ReturnType<typeof setTimeout> | undefined;
|
|
27
|
+
/** A timer tracking that an upstream heartbeat was sent, expecting a reply before it expires */
|
|
28
|
+
activePongTimer?: ReturnType<typeof setTimeout> | undefined;
|
|
29
|
+
/** If a reconnection is in progress, this will have the timer for the delayed reconnect */
|
|
30
|
+
activeReconnectTimer?: ReturnType<typeof setTimeout> | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* When a connection attempt is in progress (even for reconnect), a promise is stored here.
|
|
33
|
+
*
|
|
34
|
+
* This promise will resolve once connected (and will then get removed);
|
|
35
|
+
*/
|
|
36
|
+
deferredPromiseStore: Record<string, DeferredPromise>;
|
|
37
|
+
/**
|
|
38
|
+
* All the topics we are expected to be subscribed to on this connection (and we automatically resubscribe to if the connection drops)
|
|
39
|
+
*
|
|
40
|
+
* A "Set" and a deep-object-match are used to ensure we only subscribe to a
|
|
41
|
+
* topic once (tracking a list of unique topics we're expected to be connected to)
|
|
42
|
+
*/
|
|
43
|
+
subscribedTopics: Set<TWSTopicSubscribeEvent>;
|
|
44
|
+
/** Whether this connection has completed authentication (only applies to private connections) */
|
|
45
|
+
isAuthenticated?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Whether this connection has completed authentication before for the Websocket API, so it k
|
|
48
|
+
* nows to automatically reauth if reconnected
|
|
49
|
+
*/
|
|
50
|
+
didAuthWSAPI?: boolean;
|
|
51
|
+
/** To reauthenticate on the WS API, which channel do we send to? */
|
|
52
|
+
WSAPIAuthChannel?: string;
|
|
53
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WsConnectionStateEnum = void 0;
|
|
4
|
+
var WsConnectionStateEnum;
|
|
5
|
+
(function (WsConnectionStateEnum) {
|
|
6
|
+
WsConnectionStateEnum[WsConnectionStateEnum["INITIAL"] = 0] = "INITIAL";
|
|
7
|
+
WsConnectionStateEnum[WsConnectionStateEnum["CONNECTING"] = 1] = "CONNECTING";
|
|
8
|
+
WsConnectionStateEnum[WsConnectionStateEnum["CONNECTED"] = 2] = "CONNECTED";
|
|
9
|
+
WsConnectionStateEnum[WsConnectionStateEnum["CLOSING"] = 3] = "CLOSING";
|
|
10
|
+
WsConnectionStateEnum[WsConnectionStateEnum["RECONNECTING"] = 4] = "RECONNECTING";
|
|
11
|
+
// ERROR_RECONNECTING = 5,
|
|
12
|
+
WsConnectionStateEnum[WsConnectionStateEnum["ERROR"] = 5] = "ERROR";
|
|
13
|
+
})(WsConnectionStateEnum || (exports.WsConnectionStateEnum = WsConnectionStateEnum = {}));
|
|
14
|
+
//# sourceMappingURL=WsStore.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WsStore.types.js","sourceRoot":"","sources":["../../../src/util/websockets/WsStore.types.ts"],"names":[],"mappings":";;;AAGA,IAAY,qBAQX;AARD,WAAY,qBAAqB;IAC/B,uEAAW,CAAA;IACX,6EAAc,CAAA;IACd,2EAAa,CAAA;IACb,uEAAW,CAAA;IACX,iFAAgB,CAAA;IAChB,0BAA0B;IAC1B,mEAAS,CAAA;AACX,CAAC,EARW,qBAAqB,qCAArB,qBAAqB,QAQhC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { WsMarket } from '../../types/websockets/ws-general';
|
|
2
|
+
import { DefaultLogger } from '../logger';
|
|
3
|
+
interface ListenKeyPersistenceState {
|
|
4
|
+
keepAliveTimer: ReturnType<typeof setInterval> | undefined;
|
|
5
|
+
keepAliveRetryTimer: ReturnType<typeof setTimeout> | undefined;
|
|
6
|
+
lastKeepAlive: number;
|
|
7
|
+
market: WsMarket;
|
|
8
|
+
keepAliveFailures: number;
|
|
9
|
+
}
|
|
10
|
+
export declare class ListenKeyStateCache {
|
|
11
|
+
private logger;
|
|
12
|
+
private listenKeyStateStore;
|
|
13
|
+
constructor(customLogger?: DefaultLogger);
|
|
14
|
+
getListenKeyState(listenKey: string, market: WsMarket): ListenKeyPersistenceState;
|
|
15
|
+
private clearUserDataKeepAliveTimer;
|
|
16
|
+
/**
|
|
17
|
+
* Remove all state for listen key. Clears timers too, if any exist on this listen key store.
|
|
18
|
+
*/
|
|
19
|
+
clearAllListenKeyState(listenKey: string): void;
|
|
20
|
+
}
|
|
21
|
+
export {};
|