@solncebro/exchange-engine 0.1.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.
Files changed (108) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/LICENSE +21 -0
  3. package/README.md +390 -0
  4. package/dist/auth/binanceAuth.d.ts +9 -0
  5. package/dist/auth/binanceAuth.d.ts.map +1 -0
  6. package/dist/auth/binanceAuth.js +31 -0
  7. package/dist/auth/binanceAuth.js.map +1 -0
  8. package/dist/auth/bybitAuth.d.ts +10 -0
  9. package/dist/auth/bybitAuth.d.ts.map +1 -0
  10. package/dist/auth/bybitAuth.js +23 -0
  11. package/dist/auth/bybitAuth.js.map +1 -0
  12. package/dist/constants/binance.d.ts +9 -0
  13. package/dist/constants/binance.d.ts.map +1 -0
  14. package/dist/constants/binance.js +28 -0
  15. package/dist/constants/binance.js.map +1 -0
  16. package/dist/constants/bybit.d.ts +14 -0
  17. package/dist/constants/bybit.d.ts.map +1 -0
  18. package/dist/constants/bybit.js +33 -0
  19. package/dist/constants/bybit.js.map +1 -0
  20. package/dist/exchanges/BinanceFutures.d.ts +28 -0
  21. package/dist/exchanges/BinanceFutures.d.ts.map +1 -0
  22. package/dist/exchanges/BinanceFutures.js +125 -0
  23. package/dist/exchanges/BinanceFutures.js.map +1 -0
  24. package/dist/exchanges/BinanceSpot.d.ts +28 -0
  25. package/dist/exchanges/BinanceSpot.d.ts.map +1 -0
  26. package/dist/exchanges/BinanceSpot.js +116 -0
  27. package/dist/exchanges/BinanceSpot.js.map +1 -0
  28. package/dist/exchanges/BybitLinear.d.ts +28 -0
  29. package/dist/exchanges/BybitLinear.d.ts.map +1 -0
  30. package/dist/exchanges/BybitLinear.js +131 -0
  31. package/dist/exchanges/BybitLinear.js.map +1 -0
  32. package/dist/exchanges/BybitSpot.d.ts +27 -0
  33. package/dist/exchanges/BybitSpot.d.ts.map +1 -0
  34. package/dist/exchanges/BybitSpot.js +113 -0
  35. package/dist/exchanges/BybitSpot.js.map +1 -0
  36. package/dist/exchanges/Exchange.d.ts +11 -0
  37. package/dist/exchanges/Exchange.d.ts.map +1 -0
  38. package/dist/exchanges/Exchange.js +32 -0
  39. package/dist/exchanges/Exchange.js.map +1 -0
  40. package/dist/http/BaseHttpClient.d.ts +14 -0
  41. package/dist/http/BaseHttpClient.d.ts.map +1 -0
  42. package/dist/http/BaseHttpClient.js +77 -0
  43. package/dist/http/BaseHttpClient.js.map +1 -0
  44. package/dist/http/BinanceFuturesHttpClient.d.ts +53 -0
  45. package/dist/http/BinanceFuturesHttpClient.d.ts.map +1 -0
  46. package/dist/http/BinanceFuturesHttpClient.js +235 -0
  47. package/dist/http/BinanceFuturesHttpClient.js.map +1 -0
  48. package/dist/http/BinanceSpotHttpClient.d.ts +26 -0
  49. package/dist/http/BinanceSpotHttpClient.d.ts.map +1 -0
  50. package/dist/http/BinanceSpotHttpClient.js +98 -0
  51. package/dist/http/BinanceSpotHttpClient.js.map +1 -0
  52. package/dist/http/BybitHttpClient.d.ts +143 -0
  53. package/dist/http/BybitHttpClient.d.ts.map +1 -0
  54. package/dist/http/BybitHttpClient.js +233 -0
  55. package/dist/http/BybitHttpClient.js.map +1 -0
  56. package/dist/index.d.ts +4 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +6 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/normalizers/binanceNormalizer.d.ts +79 -0
  61. package/dist/normalizers/binanceNormalizer.d.ts.map +1 -0
  62. package/dist/normalizers/binanceNormalizer.js +133 -0
  63. package/dist/normalizers/binanceNormalizer.js.map +1 -0
  64. package/dist/normalizers/bybitNormalizer.d.ts +79 -0
  65. package/dist/normalizers/bybitNormalizer.d.ts.map +1 -0
  66. package/dist/normalizers/bybitNormalizer.js +150 -0
  67. package/dist/normalizers/bybitNormalizer.js.map +1 -0
  68. package/dist/precision/precision.d.ts +6 -0
  69. package/dist/precision/precision.d.ts.map +1 -0
  70. package/dist/precision/precision.js +29 -0
  71. package/dist/precision/precision.js.map +1 -0
  72. package/dist/types/common.d.ts +86 -0
  73. package/dist/types/common.d.ts.map +1 -0
  74. package/dist/types/common.js +3 -0
  75. package/dist/types/common.js.map +1 -0
  76. package/dist/types/exchange.d.ts +43 -0
  77. package/dist/types/exchange.d.ts.map +1 -0
  78. package/dist/types/exchange.js +3 -0
  79. package/dist/types/exchange.js.map +1 -0
  80. package/dist/types/index.d.ts +3 -0
  81. package/dist/types/index.d.ts.map +1 -0
  82. package/dist/types/index.js +3 -0
  83. package/dist/types/index.js.map +1 -0
  84. package/dist/ws/BinanceFuturesPublicStream.d.ts +30 -0
  85. package/dist/ws/BinanceFuturesPublicStream.d.ts.map +1 -0
  86. package/dist/ws/BinanceFuturesPublicStream.js +216 -0
  87. package/dist/ws/BinanceFuturesPublicStream.js.map +1 -0
  88. package/dist/ws/BinanceSpotPublicStream.d.ts +24 -0
  89. package/dist/ws/BinanceSpotPublicStream.d.ts.map +1 -0
  90. package/dist/ws/BinanceSpotPublicStream.js +186 -0
  91. package/dist/ws/BinanceSpotPublicStream.js.map +1 -0
  92. package/dist/ws/BinanceUserDataStream.d.ts +23 -0
  93. package/dist/ws/BinanceUserDataStream.d.ts.map +1 -0
  94. package/dist/ws/BinanceUserDataStream.js +48 -0
  95. package/dist/ws/BinanceUserDataStream.js.map +1 -0
  96. package/dist/ws/BybitPrivateStream.d.ts +25 -0
  97. package/dist/ws/BybitPrivateStream.d.ts.map +1 -0
  98. package/dist/ws/BybitPrivateStream.js +79 -0
  99. package/dist/ws/BybitPrivateStream.js.map +1 -0
  100. package/dist/ws/BybitPublicStream.d.ts +25 -0
  101. package/dist/ws/BybitPublicStream.d.ts.map +1 -0
  102. package/dist/ws/BybitPublicStream.js +178 -0
  103. package/dist/ws/BybitPublicStream.js.map +1 -0
  104. package/dist/ws/BybitTradeStream.d.ts +27 -0
  105. package/dist/ws/BybitTradeStream.d.ts.map +1 -0
  106. package/dist/ws/BybitTradeStream.js +146 -0
  107. package/dist/ws/BybitTradeStream.js.map +1 -0
  108. package/package.json +58 -0
@@ -0,0 +1,216 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BinanceFuturesPublicStream = void 0;
4
+ const websocket_engine_1 = require("@solncebro/websocket-engine");
5
+ const binanceNormalizer_1 = require("../normalizers/binanceNormalizer");
6
+ const binance_1 = require("../constants/binance");
7
+ const MAX_STREAMS_PER_CONNECTION = 200;
8
+ function parseBinanceCombinedMessage(rawData) {
9
+ return JSON.parse(rawData.toString());
10
+ }
11
+ function buildKlineStreamList(klineHandlerByKey) {
12
+ const streamList = [];
13
+ for (const key of klineHandlerByKey.keys()) {
14
+ const separatorIndex = key.lastIndexOf('_');
15
+ const symbol = key.slice(0, separatorIndex);
16
+ const interval = key.slice(separatorIndex + 1);
17
+ const binanceInterval = binance_1.BINANCE_KLINE_INTERVAL[interval];
18
+ streamList.push(`${symbol.toLowerCase()}_perpetual@continuousKline_${binanceInterval}`);
19
+ }
20
+ return streamList;
21
+ }
22
+ function resolveUnifiedInterval(binanceInterval) {
23
+ for (const [unified, binance] of Object.entries(binance_1.BINANCE_KLINE_INTERVAL)) {
24
+ if (binance === binanceInterval) {
25
+ return unified;
26
+ }
27
+ }
28
+ return '1m';
29
+ }
30
+ class BinanceFuturesPublicStream {
31
+ logger;
32
+ onNotify;
33
+ tickerHandlerSet = new Set();
34
+ klineHandlerByKey = new Map();
35
+ connections = [];
36
+ connectScheduled = false;
37
+ subscriptionIdCounter = 1;
38
+ constructor(logger, onNotify) {
39
+ this.logger = logger;
40
+ this.onNotify = onNotify;
41
+ }
42
+ subscribeAllTickers(handler) {
43
+ this.tickerHandlerSet.add(handler);
44
+ this.scheduleConnect();
45
+ }
46
+ unsubscribeAllTickers(handler) {
47
+ this.tickerHandlerSet.delete(handler);
48
+ }
49
+ subscribeKlines(symbol, interval, handler) {
50
+ const key = `${symbol}_${interval}`;
51
+ if (!this.klineHandlerByKey.has(key)) {
52
+ this.klineHandlerByKey.set(key, new Set());
53
+ }
54
+ this.klineHandlerByKey.get(key).add(handler);
55
+ if (this.connections.length > 0) {
56
+ const binanceInterval = binance_1.BINANCE_KLINE_INTERVAL[interval];
57
+ const stream = `${symbol.toLowerCase()}_perpetual@continuousKline_${binanceInterval}`;
58
+ this.addStreamToConnection(stream);
59
+ }
60
+ else {
61
+ this.scheduleConnect();
62
+ }
63
+ }
64
+ unsubscribeKlines(symbol, interval, handler) {
65
+ const key = `${symbol}_${interval}`;
66
+ const handlerSet = this.klineHandlerByKey.get(key);
67
+ if (!handlerSet) {
68
+ return;
69
+ }
70
+ handlerSet.delete(handler);
71
+ if (handlerSet.size === 0) {
72
+ this.klineHandlerByKey.delete(key);
73
+ const binanceInterval = binance_1.BINANCE_KLINE_INTERVAL[interval];
74
+ const stream = `${symbol.toLowerCase()}_perpetual@continuousKline_${binanceInterval}`;
75
+ this.removeStreamFromConnection(stream);
76
+ }
77
+ }
78
+ close() {
79
+ for (const conn of this.connections) {
80
+ conn.ws.close();
81
+ }
82
+ this.connections.length = 0;
83
+ }
84
+ scheduleConnect() {
85
+ if (this.connectScheduled || this.connections.length > 0) {
86
+ return;
87
+ }
88
+ this.connectScheduled = true;
89
+ queueMicrotask(() => {
90
+ this.connectScheduled = false;
91
+ this.createConnections();
92
+ });
93
+ }
94
+ createConnections() {
95
+ const tickerStreams = this.tickerHandlerSet.size > 0 ? ['!miniTicker@arr'] : [];
96
+ const klineStreams = buildKlineStreamList(this.klineHandlerByKey);
97
+ const allStreams = [...tickerStreams, ...klineStreams];
98
+ if (allStreams.length === 0) {
99
+ return;
100
+ }
101
+ for (let i = 0; i < allStreams.length; i += MAX_STREAMS_PER_CONNECTION) {
102
+ const chunk = allStreams.slice(i, i + MAX_STREAMS_PER_CONNECTION);
103
+ this.createConnection(chunk);
104
+ }
105
+ this.logger.info(`BinanceFuturesPublicStream: created ${this.connections.length} connection(s) for ${allStreams.length} streams`);
106
+ }
107
+ createConnection(streams) {
108
+ const conn = { ws: null, streams };
109
+ conn.ws = new websocket_engine_1.ReliableWebSocket({
110
+ label: 'BinanceFuturesPublicStream',
111
+ url: binance_1.BINANCE_FUTURES_WS_COMBINED_URL,
112
+ logger: this.logger,
113
+ parseMessage: parseBinanceCombinedMessage,
114
+ onMessage: (message) => this.handleMessage(message),
115
+ onOpen: async () => {
116
+ this.logger.info(`BinanceFuturesPublicStream connected (${conn.streams.length} streams)`);
117
+ this.sendSubscribe(conn);
118
+ },
119
+ onReconnectSuccess: () => this.sendSubscribe(conn),
120
+ onNotify: this.onNotify,
121
+ heartbeat: {
122
+ buildPayload: () => ({ method: 'PING' }),
123
+ isResponse: (message) => {
124
+ const raw = message;
125
+ return raw['id'] !== undefined && raw['result'] === null;
126
+ },
127
+ },
128
+ configuration: {
129
+ pingInterval: 30000,
130
+ },
131
+ });
132
+ this.connections.push(conn);
133
+ }
134
+ addStreamToConnection(stream) {
135
+ let targetConn = this.connections.find((c) => c.streams.length < MAX_STREAMS_PER_CONNECTION);
136
+ if (!targetConn) {
137
+ this.createConnection([stream]);
138
+ return;
139
+ }
140
+ targetConn.streams.push(stream);
141
+ try {
142
+ targetConn.ws.sendToConnectedSocket({
143
+ method: 'SUBSCRIBE',
144
+ params: [stream],
145
+ id: this.subscriptionIdCounter++,
146
+ });
147
+ }
148
+ catch {
149
+ // Will be subscribed on reconnect
150
+ }
151
+ }
152
+ removeStreamFromConnection(stream) {
153
+ for (const conn of this.connections) {
154
+ const idx = conn.streams.indexOf(stream);
155
+ if (idx !== -1) {
156
+ conn.streams.splice(idx, 1);
157
+ try {
158
+ conn.ws.sendToConnectedSocket({
159
+ method: 'UNSUBSCRIBE',
160
+ params: [stream],
161
+ id: this.subscriptionIdCounter++,
162
+ });
163
+ }
164
+ catch {
165
+ // Will be reflected on reconnect
166
+ }
167
+ break;
168
+ }
169
+ }
170
+ }
171
+ sendSubscribe(conn) {
172
+ try {
173
+ conn.ws.sendToConnectedSocket({
174
+ method: 'SUBSCRIBE',
175
+ params: conn.streams,
176
+ id: this.subscriptionIdCounter++,
177
+ });
178
+ }
179
+ catch {
180
+ this.logger.warn('BinanceFuturesPublicStream: failed to subscribe, socket not connected');
181
+ }
182
+ }
183
+ handleMessage(message) {
184
+ if (message.data === undefined) {
185
+ return;
186
+ }
187
+ if (Array.isArray(message.data)) {
188
+ const tickers = (0, binanceNormalizer_1.normalizeBinanceTickers)(message.data);
189
+ for (const handler of this.tickerHandlerSet) {
190
+ handler(tickers);
191
+ }
192
+ return;
193
+ }
194
+ if (message.stream && message.stream.includes('@continuousKline_')) {
195
+ const klineRaw = message.data['k'];
196
+ if (!klineRaw) {
197
+ return;
198
+ }
199
+ const kline = (0, binanceNormalizer_1.normalizeBinanceKlineWsMessage)(klineRaw);
200
+ const continuousKlineIndex = message.stream.indexOf('@continuousKline_');
201
+ const symbolLower = message.stream.slice(0, continuousKlineIndex).replace(/_perpetual$/, '');
202
+ const symbol = symbolLower.toUpperCase();
203
+ const binanceInterval = message.stream.slice(continuousKlineIndex + '@continuousKline_'.length);
204
+ const unifiedInterval = resolveUnifiedInterval(binanceInterval);
205
+ const key = `${symbol}_${unifiedInterval}`;
206
+ const handlerSet = this.klineHandlerByKey.get(key);
207
+ if (handlerSet) {
208
+ for (const handler of handlerSet) {
209
+ handler(kline);
210
+ }
211
+ }
212
+ }
213
+ }
214
+ }
215
+ exports.BinanceFuturesPublicStream = BinanceFuturesPublicStream;
216
+ //# sourceMappingURL=BinanceFuturesPublicStream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BinanceFuturesPublicStream.js","sourceRoot":"","sources":["../../src/ws/BinanceFuturesPublicStream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { ExchangeLogger, Kline, KlineInterval, TickerBySymbol } from '../types/common';
2
+ declare class BinanceSpotPublicStream {
3
+ private ws;
4
+ private readonly logger;
5
+ private readonly onNotify?;
6
+ private readonly tickerHandlerSet;
7
+ private readonly klineHandlerByKey;
8
+ private subscriptionIdCounter;
9
+ constructor(logger: ExchangeLogger, onNotify?: (message: string) => void | Promise<void>);
10
+ subscribeAllTickers(handler: (tickers: TickerBySymbol) => void): void;
11
+ unsubscribeAllTickers(handler: (tickers: TickerBySymbol) => void): void;
12
+ subscribeKlines(symbol: string, interval: KlineInterval, handler: (kline: Kline) => void): void;
13
+ unsubscribeKlines(symbol: string, interval: KlineInterval, handler: (kline: Kline) => void): void;
14
+ close(): void;
15
+ private ensureConnected;
16
+ private handleOpen;
17
+ private handleMessage;
18
+ private handleKlineFromStream;
19
+ private resubscribeAll;
20
+ private sendSubscribe;
21
+ private sendUnsubscribe;
22
+ }
23
+ export { BinanceSpotPublicStream };
24
+ //# sourceMappingURL=BinanceSpotPublicStream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BinanceSpotPublicStream.d.ts","sourceRoot":"","sources":["../../src/ws/BinanceSpotPublicStream.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA0B5F,cAAM,uBAAuB;IAC3B,OAAO,CAAC,EAAE,CAAyD;IACnE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAA4C;IACtE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqD;IACtF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAuD;IACzF,OAAO,CAAC,qBAAqB,CAAK;gBAEtB,MAAM,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxF,mBAAmB,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI;IAKrE,qBAAqB,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI;IAIvE,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAkB/F,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAqBjG,KAAK,IAAI,IAAI;IAQb,OAAO,CAAC,eAAe;YAwBT,UAAU;IAKxB,OAAO,CAAC,aAAa;IA8BrB,OAAO,CAAC,qBAAqB;IA4B7B,OAAO,CAAC,cAAc;IAoBtB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,eAAe;CAWxB;AAED,OAAO,EAAE,uBAAuB,EAAE,CAAC"}
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BinanceSpotPublicStream = void 0;
4
+ const websocket_engine_1 = require("@solncebro/websocket-engine");
5
+ const binanceNormalizer_1 = require("../normalizers/binanceNormalizer");
6
+ const binance_1 = require("../constants/binance");
7
+ function parseBinanceSpotMessage(rawData) {
8
+ return JSON.parse(rawData.toString());
9
+ }
10
+ function resolveUnifiedInterval(binanceInterval) {
11
+ for (const [unified, binance] of Object.entries(binance_1.BINANCE_KLINE_INTERVAL)) {
12
+ if (binance === binanceInterval) {
13
+ return unified;
14
+ }
15
+ }
16
+ return '1m';
17
+ }
18
+ class BinanceSpotPublicStream {
19
+ ws = null;
20
+ logger;
21
+ onNotify;
22
+ tickerHandlerSet = new Set();
23
+ klineHandlerByKey = new Map();
24
+ subscriptionIdCounter = 1;
25
+ constructor(logger, onNotify) {
26
+ this.logger = logger;
27
+ this.onNotify = onNotify;
28
+ }
29
+ subscribeAllTickers(handler) {
30
+ this.tickerHandlerSet.add(handler);
31
+ this.ensureConnected();
32
+ }
33
+ unsubscribeAllTickers(handler) {
34
+ this.tickerHandlerSet.delete(handler);
35
+ }
36
+ subscribeKlines(symbol, interval, handler) {
37
+ const key = `${symbol}_${interval}`;
38
+ if (!this.klineHandlerByKey.has(key)) {
39
+ this.klineHandlerByKey.set(key, new Set());
40
+ }
41
+ this.klineHandlerByKey.get(key).add(handler);
42
+ if (this.ws !== null) {
43
+ const binanceInterval = binance_1.BINANCE_KLINE_INTERVAL[interval];
44
+ const stream = `${symbol.toLowerCase()}@kline_${binanceInterval}`;
45
+ this.sendSubscribe([stream]);
46
+ }
47
+ else {
48
+ this.ensureConnected();
49
+ }
50
+ }
51
+ unsubscribeKlines(symbol, interval, handler) {
52
+ const key = `${symbol}_${interval}`;
53
+ const handlerSet = this.klineHandlerByKey.get(key);
54
+ if (!handlerSet) {
55
+ return;
56
+ }
57
+ handlerSet.delete(handler);
58
+ if (handlerSet.size === 0) {
59
+ this.klineHandlerByKey.delete(key);
60
+ if (this.ws !== null) {
61
+ const binanceInterval = binance_1.BINANCE_KLINE_INTERVAL[interval];
62
+ const stream = `${symbol.toLowerCase()}@kline_${binanceInterval}`;
63
+ this.sendUnsubscribe([stream]);
64
+ }
65
+ }
66
+ }
67
+ close() {
68
+ if (this.ws !== null) {
69
+ this.ws.close();
70
+ this.ws = null;
71
+ }
72
+ }
73
+ ensureConnected() {
74
+ if (this.ws !== null) {
75
+ return;
76
+ }
77
+ this.ws = new websocket_engine_1.ReliableWebSocket({
78
+ label: 'BinanceSpotPublicStream',
79
+ url: binance_1.BINANCE_SPOT_WS_STREAM_URL,
80
+ logger: this.logger,
81
+ parseMessage: parseBinanceSpotMessage,
82
+ onMessage: (message) => this.handleMessage(message),
83
+ onOpen: (context) => this.handleOpen(context),
84
+ onReconnectSuccess: () => this.resubscribeAll(),
85
+ onNotify: this.onNotify,
86
+ heartbeat: {
87
+ buildPayload: () => ({ method: 'PING' }),
88
+ isResponse: (message) => message['id'] !== undefined && message['result'] === null,
89
+ },
90
+ configuration: {
91
+ pingInterval: 30000,
92
+ },
93
+ });
94
+ }
95
+ async handleOpen(_context) {
96
+ this.logger.info('BinanceSpotPublicStream connected');
97
+ this.resubscribeAll();
98
+ }
99
+ handleMessage(message) {
100
+ if (message.e === '24hrMiniTicker' && Array.isArray(message.data)) {
101
+ const tickers = (0, binanceNormalizer_1.normalizeBinanceTickers)(message.data);
102
+ for (const handler of this.tickerHandlerSet) {
103
+ handler(tickers);
104
+ }
105
+ return;
106
+ }
107
+ if (!message.stream) {
108
+ return;
109
+ }
110
+ if (message.stream === '!miniTicker@arr' && Array.isArray(message.data)) {
111
+ const tickers = (0, binanceNormalizer_1.normalizeBinanceTickers)(message.data);
112
+ for (const handler of this.tickerHandlerSet) {
113
+ handler(tickers);
114
+ }
115
+ return;
116
+ }
117
+ if (message.stream.includes('@kline_')) {
118
+ this.handleKlineFromStream(message.stream, message.data);
119
+ }
120
+ }
121
+ handleKlineFromStream(stream, data) {
122
+ if (data === undefined || data === null) {
123
+ return;
124
+ }
125
+ const klineWrapper = data;
126
+ const klineRaw = klineWrapper['k'];
127
+ if (!klineRaw) {
128
+ return;
129
+ }
130
+ const kline = (0, binanceNormalizer_1.normalizeBinanceKlineWsMessage)(klineRaw);
131
+ const atIndex = stream.indexOf('@kline_');
132
+ const symbolLower = stream.slice(0, atIndex);
133
+ const binanceInterval = stream.slice(atIndex + '@kline_'.length);
134
+ const symbol = symbolLower.toUpperCase();
135
+ const unifiedInterval = resolveUnifiedInterval(binanceInterval);
136
+ const key = `${symbol}_${unifiedInterval}`;
137
+ const handlerSet = this.klineHandlerByKey.get(key);
138
+ if (handlerSet) {
139
+ for (const handler of handlerSet) {
140
+ handler(kline);
141
+ }
142
+ }
143
+ }
144
+ resubscribeAll() {
145
+ const streamList = [];
146
+ if (this.tickerHandlerSet.size > 0) {
147
+ streamList.push('!miniTicker@arr');
148
+ }
149
+ for (const key of this.klineHandlerByKey.keys()) {
150
+ const separatorIndex = key.lastIndexOf('_');
151
+ const symbol = key.slice(0, separatorIndex);
152
+ const interval = key.slice(separatorIndex + 1);
153
+ const binanceInterval = binance_1.BINANCE_KLINE_INTERVAL[interval];
154
+ streamList.push(`${symbol.toLowerCase()}@kline_${binanceInterval}`);
155
+ }
156
+ if (streamList.length > 0) {
157
+ this.sendSubscribe(streamList);
158
+ }
159
+ }
160
+ sendSubscribe(streamList) {
161
+ try {
162
+ this.ws.sendToConnectedSocket({
163
+ method: 'SUBSCRIBE',
164
+ params: streamList,
165
+ id: this.subscriptionIdCounter++,
166
+ });
167
+ }
168
+ catch {
169
+ this.logger.warn('BinanceSpotPublicStream: failed to subscribe, socket not connected');
170
+ }
171
+ }
172
+ sendUnsubscribe(streamList) {
173
+ try {
174
+ this.ws.sendToConnectedSocket({
175
+ method: 'UNSUBSCRIBE',
176
+ params: streamList,
177
+ id: this.subscriptionIdCounter++,
178
+ });
179
+ }
180
+ catch {
181
+ this.logger.warn('BinanceSpotPublicStream: failed to unsubscribe, socket not connected');
182
+ }
183
+ }
184
+ }
185
+ exports.BinanceSpotPublicStream = BinanceSpotPublicStream;
186
+ //# sourceMappingURL=BinanceSpotPublicStream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BinanceSpotPublicStream.js","sourceRoot":"","sources":["../../src/ws/BinanceSpotPublicStream.ts"],"names":[],"mappings":";;;AACA,kEAAgE;AAIhE,wEAA2G;AAE3G,kDAA0F;AAS1F,SAAS,uBAAuB,CAAC,OAAgB;IAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAA0B,CAAC;AACjE,CAAC;AAED,SAAS,sBAAsB,CAAC,eAAuB;IACrD,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gCAAsB,CAAC,EAAE,CAAC;QACxE,IAAI,OAAO,KAAK,eAAe,EAAE,CAAC;YAChC,OAAO,OAAwB,CAAC;QAClC,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,uBAAuB;IACnB,EAAE,GAAoD,IAAI,CAAC;IAClD,MAAM,CAAiB;IACvB,QAAQ,CAA6C;IACrD,gBAAgB,GAA2C,IAAI,GAAG,EAAE,CAAC;IACrE,iBAAiB,GAA6C,IAAI,GAAG,EAAE,CAAC;IACjF,qBAAqB,GAAG,CAAC,CAAC;IAElC,YAAY,MAAsB,EAAE,QAAoD;QACtF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,mBAAmB,CAAC,OAA0C;QAC5D,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;IAED,qBAAqB,CAAC,OAA0C;QAC9D,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,eAAe,CAAC,MAAc,EAAE,QAAuB,EAAE,OAA+B;QACtF,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,QAAQ,EAAE,CAAC;QAEpC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACrC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QAC7C,CAAC;QAED,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAE9C,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;YACrB,MAAM,eAAe,GAAG,gCAAsB,CAAC,QAAQ,CAAC,CAAC;YACzD,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,EAAE,UAAU,eAAe,EAAE,CAAC;YAClE,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IAED,iBAAiB,CAAC,MAAc,EAAE,QAAuB,EAAE,OAA+B;QACxF,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,QAAQ,EAAE,CAAC;QACpC,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEnD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QAED,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAE3B,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAEnC,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;gBACrB,MAAM,eAAe,GAAG,gCAAsB,CAAC,QAAQ,CAAC,CAAC;gBACzD,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,EAAE,UAAU,eAAe,EAAE,CAAC;gBAClE,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;YACrB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;YAEhB,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;QACjB,CAAC;IACH,CAAC;IAEO,eAAe;QACrB,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,EAAE,GAAG,IAAI,oCAAiB,CAAwB;YACrD,KAAK,EAAE,yBAAyB;YAChC,GAAG,EAAE,oCAA0B;YAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,YAAY,EAAE,uBAAuB;YACrC,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;YACnD,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YAC7C,kBAAkB,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE;YAC/C,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,SAAS,EAAE;gBACT,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;gBACxC,UAAU,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,IAAI;aACnF;YACD,aAAa,EAAE;gBACb,YAAY,EAAE,KAAK;aACpB;SACF,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,QAAqD;QAC5E,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QACtD,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAEO,aAAa,CAAC,OAA8B;QAClD,IAAI,OAAO,CAAC,CAAC,KAAK,gBAAgB,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAClE,MAAM,OAAO,GAAG,IAAA,2CAAuB,EAAC,OAAO,CAAC,IAA8B,CAAC,CAAC;YAEhF,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC5C,OAAO,CAAC,OAAO,CAAC,CAAC;YACnB,CAAC;YAED,OAAO;QACT,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,KAAK,iBAAiB,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxE,MAAM,OAAO,GAAG,IAAA,2CAAuB,EAAC,OAAO,CAAC,IAA8B,CAAC,CAAC;YAEhF,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC5C,OAAO,CAAC,OAAO,CAAC,CAAC;YACnB,CAAC;YAED,OAAO;QACT,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAEO,qBAAqB,CAAC,MAAc,EAAE,IAAa;QACzD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACxC,OAAO;QACT,CAAC;QAED,MAAM,YAAY,GAAG,IAA6B,CAAC;QACnD,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAkC,CAAC;QAEpE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,IAAA,kDAA8B,EAAC,QAAQ,CAAC,CAAC;QACvD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAC7C,MAAM,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;QACzC,MAAM,eAAe,GAAG,sBAAsB,CAAC,eAAe,CAAC,CAAC;QAChE,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,eAAe,EAAE,CAAC;QAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEnD,IAAI,UAAU,EAAE,CAAC;YACf,KAAK,MAAM,OAAO,IAAI,UAAU,EAAE,CAAC;gBACjC,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IAEO,cAAc;QACpB,MAAM,UAAU,GAAa,EAAE,CAAC;QAEhC,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACnC,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACrC,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,EAAE,CAAC;YAChD,MAAM,cAAc,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YAC5C,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;YAC5C,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC;YAC/C,MAAM,eAAe,GAAG,gCAAsB,CAAC,QAAQ,CAAC,CAAC;YACzD,UAAU,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,UAAU,eAAe,EAAE,CAAC,CAAC;QACtE,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAEO,aAAa,CAAC,UAAoB;QACxC,IAAI,CAAC;YACH,IAAI,CAAC,EAAG,CAAC,qBAAqB,CAAC;gBAC7B,MAAM,EAAE,WAAW;gBACnB,MAAM,EAAE,UAAU;gBAClB,EAAE,EAAE,IAAI,CAAC,qBAAqB,EAAE;aACjC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAC;QACzF,CAAC;IACH,CAAC;IAEO,eAAe,CAAC,UAAoB;QAC1C,IAAI,CAAC;YACH,IAAI,CAAC,EAAG,CAAC,qBAAqB,CAAC;gBAC7B,MAAM,EAAE,aAAa;gBACrB,MAAM,EAAE,UAAU;gBAClB,EAAE,EAAE,IAAI,CAAC,qBAAqB,EAAE;aACjC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;CACF;AAEQ,0DAAuB"}
@@ -0,0 +1,23 @@
1
+ import type { ExchangeLogger } from '../types/common';
2
+ interface BinanceUserDataStreamArgs {
3
+ listenKey: string;
4
+ baseWsUrl: string;
5
+ logger: ExchangeLogger;
6
+ onNotify?: (message: string) => void | Promise<void>;
7
+ onMessage: (event: Record<string, unknown>) => void;
8
+ }
9
+ declare class BinanceUserDataStream {
10
+ private ws;
11
+ private readonly logger;
12
+ private readonly listenKey;
13
+ private readonly baseWsUrl;
14
+ private readonly onNotify?;
15
+ private readonly onMessageHandler;
16
+ constructor(args: BinanceUserDataStreamArgs);
17
+ connect(): void;
18
+ close(): void;
19
+ isConnected(): boolean;
20
+ }
21
+ export { BinanceUserDataStream };
22
+ export type { BinanceUserDataStreamArgs };
23
+ //# sourceMappingURL=BinanceUserDataStream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BinanceUserDataStream.d.ts","sourceRoot":"","sources":["../../src/ws/BinanceUserDataStream.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,UAAU,yBAAyB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACrD;AAMD,cAAM,qBAAqB;IACzB,OAAO,CAAC,EAAE,CAA2D;IACrE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAA4C;IACtE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA2C;gBAEhE,IAAI,EAAE,yBAAyB;IAQ3C,OAAO,IAAI,IAAI;IAmBf,KAAK,IAAI,IAAI;IAOb,WAAW,IAAI,OAAO;CAGvB;AAED,OAAO,EAAE,qBAAqB,EAAE,CAAC;AACjC,YAAY,EAAE,yBAAyB,EAAE,CAAC"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BinanceUserDataStream = void 0;
4
+ const websocket_engine_1 = require("@solncebro/websocket-engine");
5
+ function parseUserDataMessage(rawData) {
6
+ return JSON.parse(rawData.toString());
7
+ }
8
+ class BinanceUserDataStream {
9
+ ws = null;
10
+ logger;
11
+ listenKey;
12
+ baseWsUrl;
13
+ onNotify;
14
+ onMessageHandler;
15
+ constructor(args) {
16
+ this.logger = args.logger;
17
+ this.listenKey = args.listenKey;
18
+ this.baseWsUrl = args.baseWsUrl;
19
+ this.onNotify = args.onNotify;
20
+ this.onMessageHandler = args.onMessage;
21
+ }
22
+ connect() {
23
+ if (this.ws !== null) {
24
+ return;
25
+ }
26
+ const url = `${this.baseWsUrl}/${this.listenKey}`;
27
+ this.ws = new websocket_engine_1.ReliableWebSocket({
28
+ label: 'BinanceUserDataStream',
29
+ url,
30
+ logger: this.logger,
31
+ parseMessage: parseUserDataMessage,
32
+ onMessage: (message) => this.onMessageHandler(message),
33
+ onNotify: this.onNotify,
34
+ });
35
+ this.logger.info(`BinanceUserDataStream connected with listenKey: ${this.listenKey}`);
36
+ }
37
+ close() {
38
+ if (this.ws !== null) {
39
+ this.ws.close();
40
+ this.ws = null;
41
+ }
42
+ }
43
+ isConnected() {
44
+ return this.ws !== null;
45
+ }
46
+ }
47
+ exports.BinanceUserDataStream = BinanceUserDataStream;
48
+ //# sourceMappingURL=BinanceUserDataStream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BinanceUserDataStream.js","sourceRoot":"","sources":["../../src/ws/BinanceUserDataStream.ts"],"names":[],"mappings":";;;AACA,kEAAgE;AAYhE,SAAS,oBAAoB,CAAC,OAAgB;IAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAA4B,CAAC;AACnE,CAAC;AAED,MAAM,qBAAqB;IACjB,EAAE,GAAsD,IAAI,CAAC;IACpD,MAAM,CAAiB;IACvB,SAAS,CAAS;IAClB,SAAS,CAAS;IAClB,QAAQ,CAA6C;IACrD,gBAAgB,CAA2C;IAE5E,YAAY,IAA+B;QACzC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC;IACzC,CAAC;IAED,OAAO;QACL,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QAED,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QAElD,IAAI,CAAC,EAAE,GAAG,IAAI,oCAAiB,CAA0B;YACvD,KAAK,EAAE,uBAAuB;YAC9B,GAAG;YACH,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,YAAY,EAAE,oBAAoB;YAClC,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;YACtD,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mDAAmD,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IACxF,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;YACrB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;QACjB,CAAC;IACH,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC;IAC1B,CAAC;CACF;AAEQ,sDAAqB"}
@@ -0,0 +1,25 @@
1
+ import type { ExchangeLogger } from '../types/common';
2
+ interface BybitPrivateStreamArgs {
3
+ apiKey: string;
4
+ secret: string;
5
+ logger: ExchangeLogger;
6
+ onNotify?: (message: string) => void | Promise<void>;
7
+ onMessage: (event: Record<string, unknown>) => void;
8
+ }
9
+ declare class BybitPrivateStream {
10
+ private ws;
11
+ private readonly logger;
12
+ private readonly apiKey;
13
+ private readonly secret;
14
+ private readonly onNotify?;
15
+ private readonly onMessageHandler;
16
+ constructor(args: BybitPrivateStreamArgs);
17
+ connect(): void;
18
+ close(): void;
19
+ isConnected(): boolean;
20
+ private authenticate;
21
+ private handleMessage;
22
+ }
23
+ export { BybitPrivateStream };
24
+ export type { BybitPrivateStreamArgs };
25
+ //# sourceMappingURL=BybitPrivateStream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BybitPrivateStream.d.ts","sourceRoot":"","sources":["../../src/ws/BybitPrivateStream.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAYtD,UAAU,sBAAsB;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACrD;AAUD,cAAM,kBAAkB;IACtB,OAAO,CAAC,EAAE,CAAuD;IACjE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAA4C;IACtE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA2C;gBAEhE,IAAI,EAAE,sBAAsB;IAQxC,OAAO,IAAI,IAAI;IAuBf,KAAK,IAAI,IAAI;IAOb,WAAW,IAAI,OAAO;YAIR,YAAY;IAoB1B,OAAO,CAAC,aAAa;CAOtB;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAC9B,YAAY,EAAE,sBAAsB,EAAE,CAAC"}
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.BybitPrivateStream = void 0;
7
+ const node_crypto_1 = __importDefault(require("node:crypto"));
8
+ const websocket_engine_1 = require("@solncebro/websocket-engine");
9
+ const bybit_1 = require("../constants/bybit");
10
+ function parseBybitPrivateMessage(rawData) {
11
+ return JSON.parse(rawData.toString());
12
+ }
13
+ function isBybitPongResponse(message) {
14
+ return message.op === 'pong' || message.ret_msg === 'pong';
15
+ }
16
+ class BybitPrivateStream {
17
+ ws = null;
18
+ logger;
19
+ apiKey;
20
+ secret;
21
+ onNotify;
22
+ onMessageHandler;
23
+ constructor(args) {
24
+ this.logger = args.logger;
25
+ this.apiKey = args.apiKey;
26
+ this.secret = args.secret;
27
+ this.onNotify = args.onNotify;
28
+ this.onMessageHandler = args.onMessage;
29
+ }
30
+ connect() {
31
+ if (this.ws !== null) {
32
+ return;
33
+ }
34
+ this.ws = new websocket_engine_1.ReliableWebSocket({
35
+ label: 'BybitPrivateStream',
36
+ url: bybit_1.BYBIT_PRIVATE_WS_URL,
37
+ logger: this.logger,
38
+ parseMessage: parseBybitPrivateMessage,
39
+ onMessage: (message) => this.handleMessage(message),
40
+ onOpen: (context) => this.authenticate(context),
41
+ onNotify: this.onNotify,
42
+ heartbeat: {
43
+ buildPayload: () => ({ op: 'ping' }),
44
+ isResponse: isBybitPongResponse,
45
+ },
46
+ configuration: {
47
+ pingInterval: 20000,
48
+ },
49
+ });
50
+ }
51
+ close() {
52
+ if (this.ws !== null) {
53
+ this.ws.close();
54
+ this.ws = null;
55
+ }
56
+ }
57
+ isConnected() {
58
+ return this.ws !== null;
59
+ }
60
+ async authenticate(context) {
61
+ const timestamp = Date.now();
62
+ const payload = `GET/realtime${timestamp}`;
63
+ const signature = node_crypto_1.default.createHmac('sha256', this.secret).update(payload).digest('hex');
64
+ context.send({
65
+ op: 'auth',
66
+ args: [this.apiKey, timestamp, signature],
67
+ });
68
+ await context.waitForMessage((message) => message.op === 'auth' && message.success === true, 10000);
69
+ this.logger.info('BybitPrivateStream authenticated');
70
+ }
71
+ handleMessage(message) {
72
+ if (message.op === 'auth') {
73
+ return;
74
+ }
75
+ this.onMessageHandler(message);
76
+ }
77
+ }
78
+ exports.BybitPrivateStream = BybitPrivateStream;
79
+ //# sourceMappingURL=BybitPrivateStream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BybitPrivateStream.js","sourceRoot":"","sources":["../../src/ws/BybitPrivateStream.ts"],"names":[],"mappings":"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"}