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.
Files changed (100) hide show
  1. package/README.md +5 -2
  2. package/lib/coinm-client.js.map +1 -1
  3. package/lib/index.d.ts +10 -4
  4. package/lib/index.js +10 -4
  5. package/lib/index.js.map +1 -1
  6. package/lib/main-client.d.ts +13 -2
  7. package/lib/main-client.js +15 -1
  8. package/lib/main-client.js.map +1 -1
  9. package/lib/portfolio-client.js.map +1 -1
  10. package/lib/types/futures.d.ts +1 -0
  11. package/lib/types/futures.js +3 -3
  12. package/lib/types/futures.js.map +1 -1
  13. package/lib/types/spot.js +4 -4
  14. package/lib/types/spot.js.map +1 -1
  15. package/lib/types/websockets/ws-api-requests.d.ts +7 -0
  16. package/lib/types/websockets/ws-api-requests.js +3 -0
  17. package/lib/types/websockets/ws-api-requests.js.map +1 -0
  18. package/lib/types/websockets/ws-api-responses.d.ts +8 -0
  19. package/lib/types/websockets/ws-api-responses.js +3 -0
  20. package/lib/types/websockets/ws-api-responses.js.map +1 -0
  21. package/lib/types/websockets/ws-api.d.ts +201 -0
  22. package/lib/types/websockets/ws-api.js +29 -0
  23. package/lib/types/websockets/ws-api.js.map +1 -0
  24. package/lib/types/{websockets.d.ts → websockets/ws-events-formatted.d.ts} +4 -410
  25. package/lib/types/websockets/ws-events-formatted.js +3 -0
  26. package/lib/types/websockets/ws-events-formatted.js.map +1 -0
  27. package/lib/types/websockets/ws-events-raw.d.ts +401 -0
  28. package/lib/types/{websockets.js → websockets/ws-events-raw.js} +1 -1
  29. package/lib/types/websockets/ws-events-raw.js.map +1 -0
  30. package/lib/types/websockets/ws-general.d.ts +98 -0
  31. package/lib/types/websockets/ws-general.js +11 -0
  32. package/lib/types/websockets/ws-general.js.map +1 -0
  33. package/lib/usdm-client.js.map +1 -1
  34. package/lib/util/BaseRestClient.d.ts +1 -1
  35. package/lib/util/BaseRestClient.js +1 -1
  36. package/lib/util/BaseRestClient.js.map +1 -1
  37. package/lib/util/BaseWSClient.d.ts +225 -0
  38. package/lib/util/BaseWSClient.js +729 -0
  39. package/lib/util/BaseWSClient.js.map +1 -0
  40. package/lib/util/beautifier-maps.d.ts +151 -0
  41. package/lib/util/beautifier-maps.js +198 -37
  42. package/lib/util/beautifier-maps.js.map +1 -1
  43. package/lib/util/beautifier.d.ts +7 -3
  44. package/lib/util/beautifier.js +40 -11
  45. package/lib/util/beautifier.js.map +1 -1
  46. package/lib/util/browser-support.d.ts +2 -1
  47. package/lib/util/browser-support.js +46 -28
  48. package/lib/util/browser-support.js.map +1 -1
  49. package/lib/util/logger.d.ts +8 -0
  50. package/lib/util/logger.js +17 -0
  51. package/lib/util/logger.js.map +1 -0
  52. package/lib/util/node-support.d.ts +2 -1
  53. package/lib/util/node-support.js +35 -15
  54. package/lib/util/node-support.js.map +1 -1
  55. package/lib/util/requestUtils.d.ts +19 -19
  56. package/lib/util/requestUtils.js +119 -38
  57. package/lib/util/requestUtils.js.map +1 -1
  58. package/lib/util/typeGuards.d.ts +9 -1
  59. package/lib/util/typeGuards.js +59 -34
  60. package/lib/util/typeGuards.js.map +1 -1
  61. package/lib/util/usdm/exchangeInfo.js +2 -3
  62. package/lib/util/usdm/exchangeInfo.js.map +1 -1
  63. package/lib/util/webCryptoAPI.d.ts +14 -0
  64. package/lib/util/webCryptoAPI.js +120 -0
  65. package/lib/util/webCryptoAPI.js.map +1 -0
  66. package/lib/util/websockets/WsStore.d.ts +74 -0
  67. package/lib/util/websockets/WsStore.js +279 -0
  68. package/lib/util/websockets/WsStore.js.map +1 -0
  69. package/lib/util/websockets/WsStore.types.d.ts +53 -0
  70. package/lib/util/websockets/WsStore.types.js +14 -0
  71. package/lib/util/websockets/WsStore.types.js.map +1 -0
  72. package/lib/util/websockets/listen-key-state-cache.d.ts +21 -0
  73. package/lib/util/websockets/listen-key-state-cache.js +80 -0
  74. package/lib/util/websockets/listen-key-state-cache.js.map +1 -0
  75. package/lib/util/websockets/rest-client-cache.d.ts +13 -0
  76. package/lib/util/websockets/rest-client-cache.js +56 -0
  77. package/lib/util/websockets/rest-client-cache.js.map +1 -0
  78. package/lib/util/websockets/user-data-stream-manager.d.ts +54 -0
  79. package/lib/util/websockets/user-data-stream-manager.js +256 -0
  80. package/lib/util/websockets/user-data-stream-manager.js.map +1 -0
  81. package/lib/util/websockets/websocket-util.d.ts +124 -0
  82. package/lib/util/websockets/websocket-util.js +481 -0
  83. package/lib/util/websockets/websocket-util.js.map +1 -0
  84. package/lib/websocket-client-legacy.d.ts +288 -0
  85. package/lib/websocket-client-legacy.js +1113 -0
  86. package/lib/websocket-client-legacy.js.map +1 -0
  87. package/lib/websocket-client.d.ts +228 -168
  88. package/lib/websocket-client.js +927 -834
  89. package/lib/websocket-client.js.map +1 -1
  90. package/package.json +5 -5
  91. package/lib/logger.d.ts +0 -9
  92. package/lib/logger.js +0 -23
  93. package/lib/logger.js.map +0 -1
  94. package/lib/types/websockets.js.map +0 -1
  95. package/lib/util/WsStore.d.ts +0 -57
  96. package/lib/util/WsStore.js +0 -101
  97. package/lib/util/WsStore.js.map +0 -1
  98. package/lib/util/ws-utils.d.ts +0 -7
  99. package/lib/util/ws-utils.js +0 -16
  100. package/lib/util/ws-utils.js.map +0 -1
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ListenKeyStateCache = void 0;
4
+ const logger_1 = require("../logger");
5
+ class ListenKeyStateCache {
6
+ constructor(customLogger) {
7
+ this.listenKeyStateStore = {};
8
+ this.logger = customLogger || logger_1.DefaultLogger;
9
+ }
10
+ getListenKeyState(listenKey, market) {
11
+ const state = this.listenKeyStateStore[listenKey];
12
+ if (state) {
13
+ return state;
14
+ }
15
+ // this.logger.trace(
16
+ // `--> getListenKeyState(${market}) -> CREATED NEW listenKeyState for ${listenKey}`,
17
+ // );
18
+ this.listenKeyStateStore[listenKey] = {
19
+ market,
20
+ lastKeepAlive: 0,
21
+ keepAliveTimer: undefined,
22
+ keepAliveRetryTimer: undefined,
23
+ keepAliveFailures: 0,
24
+ };
25
+ return this.listenKeyStateStore[listenKey];
26
+ }
27
+ clearUserDataKeepAliveTimer(listenKey) {
28
+ const state = this.listenKeyStateStore[listenKey];
29
+ if (!state) {
30
+ // this.logger.trace(
31
+ // `clearUserDataKeepAliveTimer() -> No listenKeyState found for ${listenKey}`,
32
+ // );
33
+ return;
34
+ }
35
+ if (state.keepAliveTimer) {
36
+ // this.logger.trace(
37
+ // `----> clearUserDataKeepAliveTimer() -> CLEARED old listenKey keepAlive INTERVAL timer for ${listenKey}`,
38
+ // );
39
+ clearInterval(state.keepAliveTimer);
40
+ }
41
+ else {
42
+ // this.logger.trace(
43
+ // `----> clearUserDataKeepAliveTimer() -> No listen key keepAlive INTERVAL timer to clear for ${listenKey}`,
44
+ // );
45
+ }
46
+ if (state.keepAliveRetryTimer) {
47
+ // this.logger.trace(
48
+ // `----> clearUserDataKeepAliveTimer() -> CLEARED old listen key keepAlive RETRY timer for ${listenKey}`,
49
+ // );
50
+ clearTimeout(state.keepAliveRetryTimer);
51
+ }
52
+ else {
53
+ // this.logger.trace(
54
+ // `----> clearUserDataKeepAliveTimer() -> No keepAlive RETRY timer to clear for ${listenKey}`,
55
+ // );
56
+ }
57
+ }
58
+ /**
59
+ * Remove all state for listen key. Clears timers too, if any exist on this listen key store.
60
+ */
61
+ clearAllListenKeyState(listenKey) {
62
+ // this.logger.trace(
63
+ // `clearAllListenKeyState() -> Checking whether we need to clear timers and remove state for ${listenKey}`,
64
+ // );
65
+ this.clearUserDataKeepAliveTimer(listenKey);
66
+ if (this.listenKeyStateStore[listenKey]) {
67
+ // this.logger.trace(
68
+ // `-> clearAllListenKeyState() -> CLEARED ALL listen key state for ${listenKey}`,
69
+ // );
70
+ }
71
+ else {
72
+ // this.logger.trace(
73
+ // `-> clearAllListenKeyState() -> No listen key state to clear ${listenKey}`,
74
+ // );
75
+ }
76
+ delete this.listenKeyStateStore[listenKey];
77
+ }
78
+ }
79
+ exports.ListenKeyStateCache = ListenKeyStateCache;
80
+ //# sourceMappingURL=listen-key-state-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listen-key-state-cache.js","sourceRoot":"","sources":["../../../src/util/websockets/listen-key-state-cache.ts"],"names":[],"mappings":";;;AACA,sCAA0C;AAU1C,MAAa,mBAAmB;IAK9B,YAAY,YAA4B;QAFhC,wBAAmB,GAA8C,EAAE,CAAC;QAG1E,IAAI,CAAC,MAAM,GAAG,YAAY,IAAI,sBAAa,CAAC;IAC9C,CAAC;IAEM,iBAAiB,CACtB,SAAiB,EACjB,MAAgB;QAEhB,MAAM,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,KAAK,CAAC;QACf,CAAC;QAED,qBAAqB;QACrB,uFAAuF;QACvF,KAAK;QACL,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,GAAG;YACpC,MAAM;YACN,aAAa,EAAE,CAAC;YAChB,cAAc,EAAE,SAAS;YACzB,mBAAmB,EAAE,SAAS;YAC9B,iBAAiB,EAAE,CAAC;SACrB,CAAC;QACF,OAAO,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC;IAEO,2BAA2B,CAAC,SAAiB;QACnD,MAAM,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,qBAAqB;YACrB,iFAAiF;YACjF,KAAK;YACL,OAAO;QACT,CAAC;QAED,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;YACzB,qBAAqB;YACrB,8GAA8G;YAC9G,KAAK;YACL,aAAa,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACtC,CAAC;aAAM,CAAC;YACN,qBAAqB;YACrB,+GAA+G;YAC/G,KAAK;QACP,CAAC;QAED,IAAI,KAAK,CAAC,mBAAmB,EAAE,CAAC;YAC9B,qBAAqB;YACrB,4GAA4G;YAC5G,KAAK;YACL,YAAY,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,qBAAqB;YACrB,iGAAiG;YACjG,KAAK;QACP,CAAC;IACH,CAAC;IAED;;OAEG;IACI,sBAAsB,CAAC,SAAiB;QAC7C,qBAAqB;QACrB,8GAA8G;QAC9G,KAAK;QACL,IAAI,CAAC,2BAA2B,CAAC,SAAS,CAAC,CAAC;QAE5C,IAAI,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC;YACxC,qBAAqB;YACrB,oFAAoF;YACpF,KAAK;QACP,CAAC;aAAM,CAAC;YACN,qBAAqB;YACrB,gFAAgF;YAChF,KAAK;QACP,CAAC;QAED,OAAO,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC;CACF;AApFD,kDAoFC"}
@@ -0,0 +1,13 @@
1
+ import { AxiosRequestConfig } from 'axios';
2
+ import { CoinMClient } from '../../coinm-client';
3
+ import { MainClient } from '../../main-client';
4
+ import { PortfolioClient } from '../../portfolio-client';
5
+ import { USDMClient } from '../../usdm-client';
6
+ import { RestClientOptions } from '../requestUtils';
7
+ export declare class RestClientCache {
8
+ private restClients;
9
+ getSpotRestClient(restOptions: RestClientOptions, requestOptions?: AxiosRequestConfig, isTestnet?: boolean): MainClient;
10
+ getUSDMRestClient(restOptions: RestClientOptions, requestOptions?: AxiosRequestConfig, isTestnet?: boolean): USDMClient;
11
+ getCOINMRestClient(restOptions: RestClientOptions, requestOptions?: AxiosRequestConfig, isTestnet?: boolean): CoinMClient;
12
+ getPortfolioClient(restOptions: RestClientOptions, requestOptions?: AxiosRequestConfig): PortfolioClient;
13
+ }
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RestClientCache = void 0;
4
+ const coinm_client_1 = require("../../coinm-client");
5
+ const main_client_1 = require("../../main-client");
6
+ const portfolio_client_1 = require("../../portfolio-client");
7
+ const usdm_client_1 = require("../../usdm-client");
8
+ class RestClientCache {
9
+ constructor() {
10
+ this.restClients = {};
11
+ }
12
+ getSpotRestClient(restOptions, requestOptions, isTestnet) {
13
+ if (isTestnet) {
14
+ if (!this.restClients.spotTestnet) {
15
+ this.restClients.spotTestnet = new main_client_1.MainClient(Object.assign(Object.assign({}, restOptions), { useTestnet: true }), requestOptions);
16
+ }
17
+ return this.restClients.spotTestnet;
18
+ }
19
+ if (!this.restClients.spot) {
20
+ this.restClients.spot = new main_client_1.MainClient(restOptions, requestOptions);
21
+ }
22
+ return this.restClients.spot;
23
+ }
24
+ getUSDMRestClient(restOptions, requestOptions, isTestnet) {
25
+ if (isTestnet) {
26
+ if (!this.restClients.usdmFuturesTestnet) {
27
+ this.restClients.usdmFuturesTestnet = new usdm_client_1.USDMClient(restOptions, requestOptions, isTestnet);
28
+ }
29
+ return this.restClients.usdmFuturesTestnet;
30
+ }
31
+ if (!this.restClients.usdmFutures) {
32
+ this.restClients.usdmFutures = new usdm_client_1.USDMClient(restOptions, requestOptions);
33
+ }
34
+ return this.restClients.usdmFutures;
35
+ }
36
+ getCOINMRestClient(restOptions, requestOptions, isTestnet) {
37
+ if (isTestnet) {
38
+ if (!this.restClients.coinmFuturesTestnet) {
39
+ this.restClients.coinmFuturesTestnet = new coinm_client_1.CoinMClient(restOptions, requestOptions, isTestnet);
40
+ }
41
+ return this.restClients.coinmFuturesTestnet;
42
+ }
43
+ if (!this.restClients.coinmFutures) {
44
+ this.restClients.coinmFutures = new coinm_client_1.CoinMClient(restOptions, requestOptions);
45
+ }
46
+ return this.restClients.coinmFutures;
47
+ }
48
+ getPortfolioClient(restOptions, requestOptions) {
49
+ if (!this.restClients.portfolio) {
50
+ this.restClients.portfolio = new portfolio_client_1.PortfolioClient(restOptions, requestOptions);
51
+ }
52
+ return this.restClients.portfolio;
53
+ }
54
+ }
55
+ exports.RestClientCache = RestClientCache;
56
+ //# sourceMappingURL=rest-client-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rest-client-cache.js","sourceRoot":"","sources":["../../../src/util/websockets/rest-client-cache.ts"],"names":[],"mappings":";;;AAEA,qDAAiD;AACjD,mDAA+C;AAC/C,6DAAyD;AACzD,mDAA+C;AAe/C,MAAa,eAAe;IAA5B;QACU,gBAAW,GAA6B,EAAE,CAAC;IAoFrD,CAAC;IAlFQ,iBAAiB,CACtB,WAA8B,EAC9B,cAAmC,EACnC,SAAmB;QAEnB,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;gBAClC,IAAI,CAAC,WAAW,CAAC,WAAW,GAAG,IAAI,wBAAU,iCACtC,WAAW,KAAE,UAAU,EAAE,IAAI,KAClC,cAAc,CACf,CAAC;YACJ,CAAC;YACD,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC;QACtC,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;YAC3B,IAAI,CAAC,WAAW,CAAC,IAAI,GAAG,IAAI,wBAAU,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IAC/B,CAAC;IAEM,iBAAiB,CACtB,WAA8B,EAC9B,cAAmC,EACnC,SAAmB;QAEnB,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,kBAAkB,EAAE,CAAC;gBACzC,IAAI,CAAC,WAAW,CAAC,kBAAkB,GAAG,IAAI,wBAAU,CAClD,WAAW,EACX,cAAc,EACd,SAAS,CACV,CAAC;YACJ,CAAC;YACD,OAAO,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC;QAC7C,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;YAClC,IAAI,CAAC,WAAW,CAAC,WAAW,GAAG,IAAI,wBAAU,CAC3C,WAAW,EACX,cAAc,CACf,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC;IACtC,CAAC;IAEM,kBAAkB,CACvB,WAA8B,EAC9B,cAAmC,EACnC,SAAmB;QAEnB,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,mBAAmB,EAAE,CAAC;gBAC1C,IAAI,CAAC,WAAW,CAAC,mBAAmB,GAAG,IAAI,0BAAW,CACpD,WAAW,EACX,cAAc,EACd,SAAS,CACV,CAAC;YACJ,CAAC;YACD,OAAO,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAAC;QAC9C,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;YACnC,IAAI,CAAC,WAAW,CAAC,YAAY,GAAG,IAAI,0BAAW,CAC7C,WAAW,EACX,cAAc,CACf,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC;IACvC,CAAC;IAEM,kBAAkB,CACvB,WAA8B,EAC9B,cAAmC;QAEnC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;YAChC,IAAI,CAAC,WAAW,CAAC,SAAS,GAAG,IAAI,kCAAe,CAC9C,WAAW,EACX,cAAc,CACf,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC;IACpC,CAAC;CACF;AArFD,0CAqFC"}
@@ -0,0 +1,54 @@
1
+ import { WebsocketClientOptions, WsMarket } from '../../types/websockets/ws-general';
2
+ import { DefaultLogger } from '../logger';
3
+ import { RestClientOptions } from '../requestUtils';
4
+ import { RestClientCache } from './rest-client-cache';
5
+ import { MiscUserDataConnectionState, WsKey, WsTopicRequest } from './websocket-util';
6
+ import { WsStore } from './WsStore';
7
+ import { WSConnectedResult } from './WsStore.types';
8
+ export interface UserDataStreamManagerConfig {
9
+ logger: DefaultLogger;
10
+ wsStore: WsStore<WsKey, WsTopicRequest<string>>;
11
+ restClientCache: RestClientCache;
12
+ /** Fn pointers so we don't have direct access to the WS client */
13
+ respawnUserDataFn: (wsKey: WsKey, market: WsMarket, context: {
14
+ symbol?: string;
15
+ isTestnet?: boolean;
16
+ respawnAttempt?: number;
17
+ }) => Promise<void>;
18
+ getWsUrlFn(wsKey: WsKey, connectionType: 'market' | 'userData' | 'wsAPI'): Promise<string>;
19
+ getRestClientOptionsFn: () => RestClientOptions;
20
+ getWsClientOptionsfn: () => WebsocketClientOptions;
21
+ closeWsFn: (wsKey: WsKey, force?: boolean) => any;
22
+ connectFn: (wsKey: WsKey, customUrl?: string | undefined, throwOnError?: boolean) => Promise<WSConnectedResult | undefined>;
23
+ }
24
+ /**
25
+ * A minimal attempt at separating all the user data stream handling workflows from
26
+ * the rest of the WS Client logic.
27
+ *
28
+ * This abstraction handles:
29
+ *
30
+ * - spawning the ws connection with the listen key
31
+ * - tracking metadata for a connection & the embedded listen key
32
+ * - handling listen key keep-alive triggers
33
+ * - handling ws respawn with listen key checks
34
+ */
35
+ export declare class UserDataStreamManager {
36
+ private logger;
37
+ private listenKeyStateCache;
38
+ private wsStore;
39
+ private restClientCache;
40
+ private respawnUserDataStream;
41
+ private closeWsFn;
42
+ private connectFn;
43
+ private getWsUrlFn;
44
+ private getRestClientOptionsFn;
45
+ private getWsClientOptionsfn;
46
+ constructor(config: UserDataStreamManagerConfig);
47
+ getWsStore(): WsStore<WsKey, WsTopicRequest<string, unknown>>;
48
+ subscribeGeneralUserDataStreamWithListenKey(wsKey: WsKey, market: WsMarket, listenKey: string, forceNewConnection?: boolean, miscState?: MiscUserDataConnectionState): Promise<WSConnectedResult | undefined>;
49
+ private setKeepAliveListenKeyTimer;
50
+ private checkKeepAliveListenKey;
51
+ teardownUserDataListenKey(listenKey?: string, ws?: WebSocket): void;
52
+ triggerUserDataReconnectionWorkflow(legacyWsKey: string): Promise<void>;
53
+ private sendKeepAliveForMarket;
54
+ }
@@ -0,0 +1,256 @@
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.UserDataStreamManager = void 0;
13
+ const typeGuards_1 = require("../typeGuards");
14
+ const listen_key_state_cache_1 = require("./listen-key-state-cache");
15
+ const websocket_util_1 = require("./websocket-util");
16
+ const WsStore_types_1 = require("./WsStore.types");
17
+ /**
18
+ * A minimal attempt at separating all the user data stream handling workflows from
19
+ * the rest of the WS Client logic.
20
+ *
21
+ * This abstraction handles:
22
+ *
23
+ * - spawning the ws connection with the listen key
24
+ * - tracking metadata for a connection & the embedded listen key
25
+ * - handling listen key keep-alive triggers
26
+ * - handling ws respawn with listen key checks
27
+ */
28
+ class UserDataStreamManager {
29
+ constructor(config) {
30
+ this.logger = config.logger;
31
+ this.wsStore = config.wsStore;
32
+ this.restClientCache = config.restClientCache;
33
+ this.respawnUserDataStream = config.respawnUserDataFn;
34
+ this.closeWsFn = config.closeWsFn;
35
+ this.connectFn = config.connectFn;
36
+ this.getWsUrlFn = config.getWsUrlFn;
37
+ this.getRestClientOptionsFn = config.getRestClientOptionsFn;
38
+ this.getWsClientOptionsfn = config.getWsClientOptionsfn;
39
+ this.listenKeyStateCache = new listen_key_state_cache_1.ListenKeyStateCache(this.logger);
40
+ // this.wsClient = config.wsClient;
41
+ }
42
+ // getWSClient(): WebsocketClient {
43
+ // return this.wsClient;
44
+ // }
45
+ getWsStore() {
46
+ return this.wsStore;
47
+ }
48
+ subscribeGeneralUserDataStreamWithListenKey(wsKey, market, listenKey, forceNewConnection, miscState) {
49
+ return __awaiter(this, void 0, void 0, function* () {
50
+ const streamName = 'userData';
51
+ const symbol = undefined;
52
+ this.logger.trace('subscribeGeneralUserDataStreamWithListenKey(): ', {
53
+ wsKey,
54
+ market,
55
+ listenKey,
56
+ forceNewConnection,
57
+ miscState,
58
+ });
59
+ const derivedWsKey = (0, websocket_util_1.getLegacyWsStoreKeyWithContext)(market, streamName, symbol, listenKey, wsKey);
60
+ const wsState = this.getWsStore().get(derivedWsKey, true);
61
+ if (!forceNewConnection &&
62
+ this.getWsStore().isConnectionAttemptInProgress(derivedWsKey)) {
63
+ const stateLastChangedAt = wsState === null || wsState === void 0 ? void 0 : wsState.connectionStateChangedAt;
64
+ const timestamp = stateLastChangedAt === null || stateLastChangedAt === void 0 ? void 0 : stateLastChangedAt.getTime();
65
+ const timestampNow = new Date().getTime();
66
+ const stateChangedTimeAgo = timestampNow - (timestamp || NaN);
67
+ this.logger.trace(`Existing ${wsKey} user data connection in progress for listen key. Avoiding duplicate`, { stateLastChangedAt, stateChangedTimeAgo, wsKey, derivedWsKey });
68
+ return this.getWsStore().getWs(derivedWsKey);
69
+ }
70
+ // Prepare the WS state for awareness whether this is a reconnect or fresh connect
71
+ if (miscState === null || miscState === void 0 ? void 0 : miscState.isReconnecting) {
72
+ this.getWsStore().setConnectionState(derivedWsKey, WsStore_types_1.WsConnectionStateEnum.RECONNECTING);
73
+ }
74
+ // Begin the connection process with the active listen key
75
+ try {
76
+ const wsBaseUrl = yield this.getWsUrlFn(wsKey, 'userData');
77
+ const wsURL = wsBaseUrl + `/${listenKey}`;
78
+ const throwOnConnectionError = true;
79
+ const connectResult = yield this.connectFn(derivedWsKey, wsURL, throwOnConnectionError);
80
+ if (!connectResult) {
81
+ this.logger.error('Exception in user data manager, connection error? ', { wsBaseUrl, wsURL, connectResult });
82
+ throw new Error('userDataManager->subscribeGeneral()-> connection error?');
83
+ }
84
+ // Start & store timer to keep alive listen key (and handle expiration)
85
+ this.setKeepAliveListenKeyTimer(listenKey, market, connectResult.ws, derivedWsKey);
86
+ return connectResult.ws;
87
+ }
88
+ catch (e) {
89
+ this.logger.error('Exception in subscribeGeneralUserDataStreamWithListenKey()', Object.assign(Object.assign({}, websocket_util_1.WS_LOGGER_CATEGORY), { wsKey, derivedWsKey, e: (e === null || e === void 0 ? void 0 : e.stack) || e }));
90
+ // In case any timers already exist, pre-wipe
91
+ this.listenKeyStateCache.clearAllListenKeyState(listenKey);
92
+ // So the next attempt doesn't think an attempt is already in progress
93
+ this.getWsStore().setConnectionState(derivedWsKey, WsStore_types_1.WsConnectionStateEnum.ERROR);
94
+ throw e;
95
+ }
96
+ });
97
+ }
98
+ setKeepAliveListenKeyTimer(listenKey, market, ws, wsKey, symbol, isTestnet) {
99
+ // This MUST happen before fetching listenKey state,
100
+ // since the getListenKeyState() creates new state,
101
+ // while clearAllListenKeyState DELETES it
102
+ this.listenKeyStateCache.clearAllListenKeyState(listenKey);
103
+ const listenKeyState = this.listenKeyStateCache.getListenKeyState(listenKey, market);
104
+ // this.logger.trace(
105
+ // `----> setKeepAliveListenKeyTimer() -> CREATED NEW keepAliveListenKey INTERVAL timer for ${listenKey}`,
106
+ // );
107
+ // Set timer to keep WS alive every 50 minutes
108
+ const minutes50 = 1000 * 60 * 50;
109
+ listenKeyState.keepAliveTimer = setInterval(() => this.checkKeepAliveListenKey(listenKey, market, ws, wsKey, symbol, isTestnet), minutes50);
110
+ }
111
+ checkKeepAliveListenKey(listenKey, market, ws, derivedWsKey, symbol, isTestnet) {
112
+ return __awaiter(this, void 0, void 0, function* () {
113
+ const listenKeyState = this.listenKeyStateCache.getListenKeyState(listenKey, market);
114
+ const wsKey = (0, websocket_util_1.getRealWsKeyFromDerivedWsKey)(derivedWsKey);
115
+ try {
116
+ if (listenKeyState.keepAliveRetryTimer) {
117
+ clearTimeout(listenKeyState.keepAliveRetryTimer);
118
+ listenKeyState.keepAliveRetryTimer = undefined;
119
+ this.logger.trace(`checkKeepAliveListenKey() -> CLEARED old one-off keepAliveRetryTimer timer for ${listenKey}`);
120
+ }
121
+ yield this.sendKeepAliveForMarket(listenKey, market, ws, wsKey, derivedWsKey, symbol, isTestnet);
122
+ listenKeyState.lastKeepAlive = Date.now();
123
+ listenKeyState.keepAliveFailures = 0;
124
+ this.logger.info(`Completed keep alive cycle for listenKey(${listenKey}) in market(${market})`, Object.assign(Object.assign({}, websocket_util_1.WS_LOGGER_CATEGORY), { listenKey }));
125
+ }
126
+ catch (e) {
127
+ listenKeyState.keepAliveFailures++;
128
+ // Reconnect follows a less automatic workflow since this is tied to a listen key (which may need a new one).
129
+ // - Kill connection first, with instruction NOT to reconnect automatically
130
+ // - Then respawn a connection with a potentially new listen key (since the old one may be invalid now)
131
+ const shouldReconnectAfterClose = false;
132
+ // code: -1125,
133
+ // message: 'This listenKey does not exist.',
134
+ const errorCode = e === null || e === void 0 ? void 0 : e.code;
135
+ if (errorCode === -1125) {
136
+ this.logger.error('FATAL: Failed to keep WS alive for listen key - listen key expired/invalid. Respawning with fresh listen key...', Object.assign(Object.assign({}, websocket_util_1.WS_LOGGER_CATEGORY), { listenKey, error: e, errorCode, errorMsg: e === null || e === void 0 ? void 0 : e.message }));
137
+ this.closeWsFn(derivedWsKey, shouldReconnectAfterClose);
138
+ this.respawnUserDataStream(wsKey, market, { symbol, isTestnet });
139
+ return;
140
+ }
141
+ // If max failurees reached, tear down and respawn if allowed
142
+ if (listenKeyState.keepAliveFailures >= 3) {
143
+ this.logger.error('FATAL: Failed to keep WS alive for listen key after 3 attempts', Object.assign(Object.assign({}, websocket_util_1.WS_LOGGER_CATEGORY), { listenKey, error: e }));
144
+ this.closeWsFn(derivedWsKey, shouldReconnectAfterClose);
145
+ this.respawnUserDataStream(wsKey, market, { symbol, isTestnet });
146
+ return;
147
+ }
148
+ const reconnectDelaySeconds = 1000 * 15;
149
+ this.logger.info(`Userdata keep alive request failed due to error, trying again with short delay (${reconnectDelaySeconds} seconds)`, Object.assign(Object.assign({}, websocket_util_1.WS_LOGGER_CATEGORY), { listenKey, error: e, keepAliveAttempts: listenKeyState.keepAliveFailures }));
150
+ this.logger.trace(`checkKeepAliveListenKey() -> CREATED NEW one-off keepAliveRetryTimer timer for ${listenKey}`);
151
+ listenKeyState.keepAliveRetryTimer = setTimeout(() => this.checkKeepAliveListenKey(listenKey, market, ws, derivedWsKey, symbol), reconnectDelaySeconds);
152
+ }
153
+ });
154
+ }
155
+ teardownUserDataListenKey(listenKey, ws) {
156
+ if (listenKey) {
157
+ this.listenKeyStateCache.clearAllListenKeyState(listenKey);
158
+ (0, websocket_util_1.safeTerminateWs)(ws, true);
159
+ }
160
+ }
161
+ triggerUserDataReconnectionWorkflow(legacyWsKey) {
162
+ return __awaiter(this, void 0, void 0, function* () {
163
+ console.log(`triggerCustomReconnectionWorkflow(${legacyWsKey})`);
164
+ if (legacyWsKey.includes('userData')) {
165
+ const legacyWsKeyContext = (0, websocket_util_1.getLegacyWsKeyContext)(legacyWsKey);
166
+ if (!legacyWsKeyContext) {
167
+ throw new Error(`triggerCustomReconnectionWorkflow(): no context found in supplied wsKey: "${legacyWsKey}"`);
168
+ }
169
+ const { market, symbol, isTestnet, listenKey, wsKey } = legacyWsKeyContext;
170
+ this.logger.info('Preparing to reconnect userData stream...', Object.assign(Object.assign({}, websocket_util_1.WS_LOGGER_CATEGORY), { legacyWsKey,
171
+ market,
172
+ symbol,
173
+ isTestnet,
174
+ listenKey,
175
+ wsKey }));
176
+ if (listenKey) {
177
+ this.logger.trace('Checking if old listenKey has active timers...', {
178
+ listenKey,
179
+ });
180
+ this.listenKeyStateCache.clearAllListenKeyState(listenKey);
181
+ }
182
+ else {
183
+ throw new Error('No listenKey stashed in legacyWsKey context???');
184
+ }
185
+ this.logger.info('Reconnecting to user data stream...', Object.assign(Object.assign(Object.assign({}, websocket_util_1.WS_LOGGER_CATEGORY), legacyWsKeyContext), { wsKey,
186
+ market,
187
+ symbol }));
188
+ // We'll set a new one once the new stream respawns, it might have a diff listenKey in the wsKey
189
+ this.getWsStore().delete(legacyWsKey);
190
+ if (!wsKey) {
191
+ const errorMessage = 'triggerCustomReconnectionWorkflow(): missing real "wsKey" from legacy context';
192
+ this.logger.error(errorMessage, {
193
+ legacyWsKeyContext,
194
+ legacyWsKey,
195
+ });
196
+ throw new Error(errorMessage);
197
+ }
198
+ this.respawnUserDataStream(wsKey, market, {
199
+ symbol,
200
+ isTestnet,
201
+ });
202
+ return;
203
+ }
204
+ });
205
+ }
206
+ sendKeepAliveForMarket(listenKey, market, ws, wsKey, deriedWsKey, symbol, isTestnet) {
207
+ switch (market) {
208
+ case 'spot':
209
+ return this.restClientCache
210
+ .getSpotRestClient(this.getRestClientOptionsFn(), this.getWsClientOptionsfn().requestOptions)
211
+ .keepAliveSpotUserDataListenKey(listenKey);
212
+ case 'spotTestnet':
213
+ return this.restClientCache
214
+ .getSpotRestClient(this.getRestClientOptionsFn(), this.getWsClientOptionsfn().requestOptions, true)
215
+ .keepAliveSpotUserDataListenKey(listenKey);
216
+ case 'crossMargin':
217
+ return this.restClientCache
218
+ .getSpotRestClient(this.getRestClientOptionsFn(), this.getWsClientOptionsfn().requestOptions)
219
+ .keepAliveMarginUserDataListenKey(listenKey);
220
+ case 'riskDataMargin':
221
+ return this.restClientCache
222
+ .getSpotRestClient(this.getRestClientOptionsFn(), this.getWsClientOptionsfn().requestOptions)
223
+ .keepAliveMarginRiskUserDataListenKey(listenKey);
224
+ case 'isolatedMargin':
225
+ return this.restClientCache
226
+ .getSpotRestClient(this.getRestClientOptionsFn(), this.getWsClientOptionsfn().requestOptions)
227
+ .keepAliveIsolatedMarginUserDataListenKey({
228
+ listenKey,
229
+ symbol: symbol,
230
+ });
231
+ case 'coinm':
232
+ case 'options':
233
+ case 'optionsTestnet':
234
+ case 'usdm':
235
+ return this.restClientCache
236
+ .getUSDMRestClient(this.getRestClientOptionsFn(), this.getWsClientOptionsfn().requestOptions)
237
+ .keepAliveFuturesUserDataListenKey();
238
+ case 'usdmTestnet':
239
+ return this.restClientCache
240
+ .getUSDMRestClient(this.getRestClientOptionsFn(), this.getWsClientOptionsfn().requestOptions, isTestnet)
241
+ .keepAliveFuturesUserDataListenKey();
242
+ case 'coinmTestnet':
243
+ return this.restClientCache
244
+ .getCOINMRestClient(this.getRestClientOptionsFn(), this.getWsClientOptionsfn().requestOptions, isTestnet)
245
+ .keepAliveFuturesUserDataListenKey();
246
+ case 'portfoliom':
247
+ return this.restClientCache
248
+ .getPortfolioClient(this.getRestClientOptionsFn(), this.getWsClientOptionsfn().requestOptions)
249
+ .keepAlivePMUserDataListenKey();
250
+ default:
251
+ throw (0, typeGuards_1.neverGuard)(market, `Failed to send keep alive for user data stream in unhandled market ${market}`);
252
+ }
253
+ }
254
+ }
255
+ exports.UserDataStreamManager = UserDataStreamManager;
256
+ //# sourceMappingURL=user-data-stream-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-data-stream-manager.js","sourceRoot":"","sources":["../../../src/util/websockets/user-data-stream-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ import WebSocket from 'isomorphic-ws';
2
+ import { WebsocketClientOptions, WsMarket, WsTopic } from '../../types/websockets/ws-general';
3
+ import { DefaultLogger } from '../logger';
4
+ import { WsRequestOperationBinance } from '../../types/websockets/ws-api';
5
+ export declare const WS_LOGGER_CATEGORY: {
6
+ category: string;
7
+ };
8
+ /**
9
+ * These WS Key values correspond to a WS API connection
10
+ */
11
+ export type WSAPIWsKey = 'mainWSAPI' | 'mainWSAPI2' | 'mainWSAPITestnet' | 'usdmWSAPI' | 'usdmWSAPITestnet';
12
+ export declare const WS_KEY_MAP: {
13
+ readonly main: "main";
14
+ readonly main2: "main2";
15
+ readonly main3: "main3";
16
+ readonly mainTestnetPublic: "mainTestnetPublic";
17
+ readonly mainTestnetUserData: "mainTestnetUserData";
18
+ readonly mainWSAPI: "mainWSAPI";
19
+ readonly mainWSAPI2: "mainWSAPI2";
20
+ readonly mainWSAPITestnet: "mainWSAPITestnet";
21
+ readonly marginRiskUserData: "marginRiskUserData";
22
+ readonly usdm: "usdm";
23
+ readonly usdmTestnet: "usdmTestnet";
24
+ readonly usdmWSAPI: "usdmWSAPI";
25
+ readonly usdmWSAPITestnet: "usdmWSAPITestnet";
26
+ readonly coinm: "coinm";
27
+ readonly coinm2: "coinm2";
28
+ readonly coinmTestnet: "coinmTestnet";
29
+ readonly eoptions: "eoptions";
30
+ readonly portfolioMarginUserData: "portfolioMarginUserData";
31
+ readonly portfolioMarginProUserData: "portfolioMarginProUserData";
32
+ };
33
+ export type WsKey = (typeof WS_KEY_MAP)[keyof typeof WS_KEY_MAP];
34
+ export declare const WS_KEY_URL_MAP: Record<WsKey, string>;
35
+ export declare function getWsURLSuffix(wsKey: WsKey, connectionType: 'market' | 'userData' | 'wsAPI'): string;
36
+ export declare const WS_AUTH_ON_CONNECT_KEYS: WsKey[];
37
+ /**
38
+ * Normalised internal format for a request (subscribe/unsubscribe/etc) on a topic, with optional parameters.
39
+ *
40
+ * - Topic: the topic this event is for
41
+ * - Payload: the parameters to include, optional. E.g. auth requires key + sign. Some topics allow configurable parameters.
42
+ * - Category: required for bybit, since different categories have different public endpoints
43
+ */
44
+ export interface WsTopicRequest<TWSTopic extends string = string, TWSPayload = unknown> {
45
+ topic: TWSTopic;
46
+ payload?: TWSPayload;
47
+ }
48
+ /**
49
+ * Conveniently allow users to request a topic either as string topics or objects (containing string topic + params)
50
+ */
51
+ export type WsTopicRequestOrStringTopic<TWSTopic extends string, TWSPayload = unknown> = WsTopicRequest<TWSTopic, TWSPayload> | string;
52
+ export declare function isPrivateWsTopic(topic: string): boolean;
53
+ export declare function getWsKeyForTopic(wsKey: string): WsKey;
54
+ export declare function getWsUrl(wsKey: WsKey, wsClientOptions: WebsocketClientOptions, logger: typeof DefaultLogger): string;
55
+ export declare function getMaxTopicsPerSubscribeEvent(wsKey: WsKey): number | null;
56
+ export declare const WS_ERROR_ENUM: {
57
+ NOT_AUTHENTICATED_SPOT_V3: string;
58
+ API_ERROR_GENERIC: string;
59
+ API_SIGN_AUTH_FAILED: string;
60
+ USDC_OPTION_AUTH_FAILED: string;
61
+ };
62
+ /**
63
+ * #305: ws.terminate() is undefined in browsers.
64
+ * This only works in node.js, not in browsers.
65
+ * Does nothing if `ws` is undefined. Does nothing in browsers.
66
+ */
67
+ export declare function safeTerminateWs(ws?: WebSocket | any, fallbackToClose?: boolean): boolean;
68
+ /**
69
+ * WS API promises are stored using a primary key. This key is constructed using
70
+ * properties found in every request & reply.
71
+ *
72
+ * The counterpart to this is in resolveEmittableEvents
73
+ */
74
+ export declare function getPromiseRefForWSAPIRequest(wsKey: WsKey, requestEvent: WsRequestOperationBinance<string>): string;
75
+ /**
76
+ * Users can conveniently pass topics as strings or objects (object has topic name + optional params).
77
+ *
78
+ * This method normalises topics into objects (object has topic name + optional params).
79
+ */
80
+ export declare function getNormalisedTopicRequests(wsTopicRequests: WsTopicRequestOrStringTopic<string>[]): WsTopicRequest<string>[];
81
+ /**
82
+ * Groups topics in request into per-wsKey groups
83
+ * @param normalisedTopicRequests
84
+ * @param wsKey
85
+ * @param isPrivateTopic
86
+ * @returns
87
+ */
88
+ export declare function getTopicsPerWSKey(normalisedTopicRequests: WsTopicRequest[], wsKey: WsKey): {
89
+ [key in WsKey]?: WsTopicRequest<WsTopic>[];
90
+ };
91
+ export declare function parseEventTypeFromMessage(wsKey: WsKey, parsedMsg?: any): string | undefined;
92
+ export declare function resolveUserDataMarketForWsKey(wsKey: WsKey): WsMarket;
93
+ /**
94
+ * Used by the legacy subscribe* utility methods to determine which wsKey to route the subscription to.
95
+ */
96
+ export declare function resolveWsKeyForLegacyMarket(market: 'spot' | 'usdm' | 'coinm'): WsKey;
97
+ /**
98
+ * Try to resolve event.data. Example circumstance: {"stream":"!forceOrder@arr","data":{"e":"forceOrder","E":1634653599186,"o":{"s":"IOTXUSDT","S":"SELL","o":"LIMIT","f":"IOC","q":"3661","p":"0.06606","ap":"0.06669","X":"FILLED","l":"962","z":"3661","T":1634653599180}}}
99
+ */
100
+ export declare function parseRawWsMessage(event: any): any;
101
+ export interface MiscUserDataConnectionState {
102
+ isReconnecting?: boolean;
103
+ respawnAttempt?: number;
104
+ }
105
+ interface WsContext {
106
+ symbol: string | undefined;
107
+ legacyWsKey: string | undefined;
108
+ wsKey: WsKey | undefined;
109
+ market: WsMarket;
110
+ isTestnet: boolean | undefined;
111
+ isUserData: boolean;
112
+ streamName: string;
113
+ listenKey: string | undefined;
114
+ otherParams: undefined | string[];
115
+ }
116
+ export declare function getContextFromWsKey(legacyWsKey: any): WsContext;
117
+ /**
118
+ * The legacy WS client creates a deterministic WS Key based on consistent input parameters
119
+ */
120
+ export declare function getLegacyWsStoreKeyWithContext(market: WsMarket, streamName: string, symbol?: string | undefined, listenKey?: string | undefined, ...otherParams: (string | boolean)[]): any;
121
+ export declare function getLegacyWsKeyContext(wsKey: string): WsContext | undefined;
122
+ export declare function getRealWsKeyFromDerivedWsKey(wsKey: string | WsKey): WsKey;
123
+ export declare function appendEventMarket(wsMsg: any, wsKey: WsKey): void;
124
+ export {};