bybit-api 3.6.1 → 3.7.1-beta.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 (93) hide show
  1. package/lib/contract-client.d.ts +17 -3
  2. package/lib/contract-client.js +17 -3
  3. package/lib/contract-client.js.map +1 -1
  4. package/lib/rest-client-v5.d.ts +259 -10
  5. package/lib/rest-client-v5.js +196 -7
  6. package/lib/rest-client-v5.js.map +1 -1
  7. package/lib/types/request/contract.d.ts +21 -11
  8. package/lib/types/request/index.d.ts +1 -0
  9. package/lib/types/request/index.js +1 -0
  10. package/lib/types/request/index.js.map +1 -1
  11. package/lib/types/request/v5-account.d.ts +5 -0
  12. package/lib/types/request/v5-market.d.ts +10 -2
  13. package/lib/types/request/v5-position.d.ts +13 -2
  14. package/lib/types/request/v5-pre-upgrade.d.ts +34 -0
  15. package/lib/types/request/v5-pre-upgrade.js +3 -0
  16. package/lib/types/request/v5-pre-upgrade.js.map +1 -0
  17. package/lib/types/request/v5-trade.d.ts +24 -1
  18. package/lib/types/response/contract.d.ts +22 -12
  19. package/lib/types/response/v5-account.d.ts +1 -0
  20. package/lib/types/response/v5-market.d.ts +6 -0
  21. package/lib/types/response/v5-position.d.ts +26 -0
  22. package/lib/types/response/v5-trade.d.ts +7 -0
  23. package/lib/types/v5-shared.d.ts +4 -1
  24. package/lib/util/websocket-util.d.ts +2 -1
  25. package/lib/util/websocket-util.js +2 -2
  26. package/lib/util/websocket-util.js.map +1 -1
  27. package/lib/websocket-client.js +1 -1
  28. package/lib/websocket-client.js.map +1 -1
  29. package/package.json +13 -1
  30. package/src/account-asset-client-v3.ts +310 -0
  31. package/src/account-asset-client.ts +149 -0
  32. package/src/constants/enum.ts +105 -0
  33. package/src/contract-client.ts +360 -0
  34. package/src/copy-trading-client.ts +159 -0
  35. package/src/index.ts +18 -0
  36. package/src/inverse-client.ts +337 -0
  37. package/src/inverse-futures-client.ts +403 -0
  38. package/src/linear-client.ts +387 -0
  39. package/src/rest-client-v5.ts +1638 -0
  40. package/src/spot-client-v3.ts +303 -0
  41. package/src/spot-client.ts +180 -0
  42. package/src/types/index.ts +5 -0
  43. package/src/types/request/account-asset.ts +258 -0
  44. package/src/types/request/contract.ts +139 -0
  45. package/src/types/request/copy-trading.ts +53 -0
  46. package/src/types/request/index.ts +18 -0
  47. package/src/types/request/inverse.ts +135 -0
  48. package/src/types/request/linear.ts +201 -0
  49. package/src/types/request/spot.ts +89 -0
  50. package/src/types/request/unified-margin.ts +247 -0
  51. package/src/types/request/usdc-options.ts +134 -0
  52. package/src/types/request/usdc-perp.ts +100 -0
  53. package/src/types/request/usdc-shared.ts +39 -0
  54. package/src/types/request/v5-account.ts +40 -0
  55. package/src/types/request/v5-asset.ts +133 -0
  56. package/src/types/request/v5-market.ts +127 -0
  57. package/src/types/request/v5-position.ts +107 -0
  58. package/src/types/request/v5-pre-upgrade.ts +37 -0
  59. package/src/types/request/v5-spot-leverage-token.ts +23 -0
  60. package/src/types/request/v5-trade.ts +133 -0
  61. package/src/types/request/v5-user.ts +21 -0
  62. package/src/types/response/account-asset.ts +236 -0
  63. package/src/types/response/contract.ts +74 -0
  64. package/src/types/response/index.ts +13 -0
  65. package/src/types/response/shared.ts +19 -0
  66. package/src/types/response/spot.ts +17 -0
  67. package/src/types/response/unified-margin.ts +71 -0
  68. package/src/types/response/usdt-perp.ts +58 -0
  69. package/src/types/response/v5-account.ts +122 -0
  70. package/src/types/response/v5-asset.ts +170 -0
  71. package/src/types/response/v5-market.ts +271 -0
  72. package/src/types/response/v5-position.ts +118 -0
  73. package/src/types/response/v5-spot-leverage-token.ts +70 -0
  74. package/src/types/response/v5-trade.ts +103 -0
  75. package/src/types/response/v5-user.ts +58 -0
  76. package/src/types/shared.ts +175 -0
  77. package/src/types/v5-shared.ts +213 -0
  78. package/src/types/websockets.ts +115 -0
  79. package/src/types/ws-events/failed-topic-subscription-confirmation.ts +6 -0
  80. package/src/types/ws-events/succeeded-topic-subscription-confirmation.ts +6 -0
  81. package/src/types/ws-events/topic-subscription-confirmation.ts +7 -0
  82. package/src/unified-margin-client.ts +400 -0
  83. package/src/usdc-option-client.ts +333 -0
  84. package/src/usdc-perpetual-client.ts +312 -0
  85. package/src/util/BaseRestClient.ts +502 -0
  86. package/src/util/WsStore.ts +160 -0
  87. package/src/util/browser-support.ts +29 -0
  88. package/src/util/index.ts +5 -0
  89. package/src/util/logger.ts +26 -0
  90. package/src/util/node-support.ts +9 -0
  91. package/src/util/requestUtils.ts +171 -0
  92. package/src/util/websocket-util.ts +550 -0
  93. package/src/websocket-client.ts +1262 -0
@@ -0,0 +1,550 @@
1
+ import { APIMarket, CategoryV5, WsKey } from '../types';
2
+ import { DefaultLogger } from './logger';
3
+
4
+ interface NetworkMapV3 {
5
+ livenet: string;
6
+ livenet2?: string;
7
+ testnet: string;
8
+ testnet2?: string;
9
+ }
10
+
11
+ type PublicPrivateNetwork = 'public' | 'private';
12
+
13
+ /**
14
+ * The following WS keys are logical.
15
+ *
16
+ * They're not directly used as a market. They usually have one private endpoint but many public ones,
17
+ * so they need a bit of extra handling for seamless messaging between endpoints.
18
+ *
19
+ * For the unified keys, the "split" happens using the symbol. Symbols suffixed with USDT are obviously USDT topics.
20
+ * For the v5 endpoints, the subscribe/unsubscribe call must specify the category the subscription should route to.
21
+ */
22
+ type PublicOnlyWsKeys =
23
+ | 'unifiedPerpUSDT'
24
+ | 'unifiedPerpUSDC'
25
+ | 'v5SpotPublic'
26
+ | 'v5LinearPublic'
27
+ | 'v5InversePublic'
28
+ | 'v5OptionPublic';
29
+
30
+ export const WS_BASE_URL_MAP: Record<
31
+ APIMarket,
32
+ Record<PublicPrivateNetwork, NetworkMapV3>
33
+ > &
34
+ Record<PublicOnlyWsKeys, Record<'public', NetworkMapV3>> = {
35
+ inverse: {
36
+ public: {
37
+ livenet: 'wss://stream.bybit.com/realtime',
38
+ testnet: 'wss://stream-testnet.bybit.com/realtime',
39
+ },
40
+ private: {
41
+ livenet: 'wss://stream.bybit.com/realtime',
42
+ testnet: 'wss://stream-testnet.bybit.com/realtime',
43
+ },
44
+ },
45
+ linear: {
46
+ public: {
47
+ livenet: 'wss://stream.bybit.com/realtime_public',
48
+ livenet2: 'wss://stream.bytick.com/realtime_public',
49
+ testnet: 'wss://stream-testnet.bybit.com/realtime_public',
50
+ },
51
+ private: {
52
+ livenet: 'wss://stream.bybit.com/realtime_private',
53
+ livenet2: 'wss://stream.bytick.com/realtime_private',
54
+ testnet: 'wss://stream-testnet.bybit.com/realtime_private',
55
+ },
56
+ },
57
+ spot: {
58
+ public: {
59
+ livenet: 'wss://stream.bybit.com/spot/quote/ws/v1',
60
+ livenet2: 'wss://stream.bybit.com/spot/quote/ws/v2',
61
+ testnet: 'wss://stream-testnet.bybit.com/spot/quote/ws/v1',
62
+ testnet2: 'wss://stream-testnet.bybit.com/spot/quote/ws/v2',
63
+ },
64
+ private: {
65
+ livenet: 'wss://stream.bybit.com/spot/ws',
66
+ testnet: 'wss://stream-testnet.bybit.com/spot/ws',
67
+ },
68
+ },
69
+ spotv3: {
70
+ public: {
71
+ livenet: 'wss://stream.bybit.com/spot/public/v3',
72
+ testnet: 'wss://stream-testnet.bybit.com/spot/public/v3',
73
+ },
74
+ private: {
75
+ livenet: 'wss://stream.bybit.com/spot/private/v3',
76
+ testnet: 'wss://stream-testnet.bybit.com/spot/private/v3',
77
+ },
78
+ },
79
+ usdcOption: {
80
+ public: {
81
+ livenet: 'wss://stream.bybit.com/trade/option/usdc/public/v1',
82
+ livenet2: 'wss://stream.bytick.com/trade/option/usdc/public/v1',
83
+ testnet: 'wss://stream-testnet.bybit.com/trade/option/usdc/public/v1',
84
+ },
85
+ private: {
86
+ livenet: 'wss://stream.bybit.com/trade/option/usdc/private/v1',
87
+ livenet2: 'wss://stream.bytick.com/trade/option/usdc/private/v1',
88
+ testnet: 'wss://stream-testnet.bybit.com/trade/option/usdc/private/v1',
89
+ },
90
+ },
91
+ usdcPerp: {
92
+ public: {
93
+ livenet: 'wss://stream.bybit.com/perpetual/ws/v1/realtime_public',
94
+ livenet2: 'wss://stream.bytick.com/perpetual/ws/v1/realtime_public',
95
+ testnet: 'wss://stream-testnet.bybit.com/perpetual/ws/v1/realtime_public',
96
+ },
97
+ private: {
98
+ livenet: 'wss://stream.bybit.com/trade/option/usdc/private/v1',
99
+ livenet2: 'wss://stream.bytick.com/trade/option/usdc/private/v1',
100
+ testnet: 'wss://stream-testnet.bybit.com/trade/option/usdc/private/v1',
101
+ },
102
+ },
103
+ unifiedOption: {
104
+ public: {
105
+ livenet: 'wss://stream.bybit.com/option/usdc/public/v3',
106
+ testnet: 'wss://stream-testnet.bybit.com/option/usdc/public/v3',
107
+ },
108
+ private: {
109
+ livenet: 'wss://stream.bybit.com/unified/private/v3',
110
+ testnet: 'wss://stream-testnet.bybit.com/unified/private/v3',
111
+ },
112
+ },
113
+ unifiedPerp: {
114
+ public: {
115
+ livenet: 'useBaseSpecificEndpoint',
116
+ testnet: 'useBaseSpecificEndpoint',
117
+ },
118
+ private: {
119
+ livenet: 'wss://stream.bybit.com/unified/private/v3',
120
+ testnet: 'wss://stream-testnet.bybit.com/unified/private/v3',
121
+ },
122
+ },
123
+ unifiedPerpUSDT: {
124
+ public: {
125
+ livenet: 'wss://stream.bybit.com/contract/usdt/public/v3',
126
+ testnet: 'wss://stream-testnet.bybit.com/contract/usdt/public/v3',
127
+ },
128
+ },
129
+ unifiedPerpUSDC: {
130
+ public: {
131
+ livenet: 'wss://stream.bybit.com/contract/usdc/public/v3',
132
+ testnet: 'wss://stream-testnet.bybit.com/contract/usdc/public/v3',
133
+ },
134
+ },
135
+ contractUSDT: {
136
+ public: {
137
+ livenet: 'wss://stream.bybit.com/contract/usdt/public/v3',
138
+ testnet: 'wss://stream-testnet.bybit.com/contract/usdt/public/v3',
139
+ },
140
+ private: {
141
+ livenet: 'wss://stream.bybit.com/contract/private/v3',
142
+ testnet: 'wss://stream-testnet.bybit.com/contract/private/v3',
143
+ },
144
+ },
145
+ contractInverse: {
146
+ public: {
147
+ livenet: 'wss://stream.bybit.com/contract/inverse/public/v3',
148
+ testnet: 'wss://stream-testnet.bybit.com/contract/inverse/public/v3',
149
+ },
150
+ private: {
151
+ livenet: 'wss://stream.bybit.com/contract/private/v3',
152
+ testnet: 'wss://stream-testnet.bybit.com/contract/private/v3',
153
+ },
154
+ },
155
+ v5: {
156
+ public: {
157
+ livenet: 'public topics are routed internally via the public wskeys',
158
+ testnet: 'public topics are routed internally via the public wskeys',
159
+ },
160
+ private: {
161
+ livenet: 'wss://stream.bybit.com/v5/private',
162
+ testnet: 'wss://stream-testnet.bybit.com/v5/private',
163
+ },
164
+ },
165
+ v5SpotPublic: {
166
+ public: {
167
+ livenet: 'wss://stream.bybit.com/v5/public/spot',
168
+ testnet: 'wss://stream-testnet.bybit.com/v5/public/spot',
169
+ },
170
+ },
171
+ v5LinearPublic: {
172
+ public: {
173
+ livenet: 'wss://stream.bybit.com/v5/public/linear',
174
+ testnet: 'wss://stream-testnet.bybit.com/v5/public/linear',
175
+ },
176
+ },
177
+ v5InversePublic: {
178
+ public: {
179
+ livenet: 'wss://stream.bybit.com/v5/public/inverse',
180
+ testnet: 'wss://stream-testnet.bybit.com/v5/public/inverse',
181
+ },
182
+ },
183
+ v5OptionPublic: {
184
+ public: {
185
+ livenet: 'wss://stream.bybit.com/v5/public/option',
186
+ testnet: 'wss://stream-testnet.bybit.com/v5/public/option',
187
+ },
188
+ },
189
+ };
190
+
191
+ export const WS_KEY_MAP = {
192
+ inverse: 'inverse',
193
+ linearPrivate: 'linearPrivate',
194
+ linearPublic: 'linearPublic',
195
+ spotPrivate: 'spotPrivate',
196
+ spotPublic: 'spotPublic',
197
+ spotV3Private: 'spotV3Private',
198
+ spotV3Public: 'spotV3Public',
199
+ usdcOptionPrivate: 'usdcOptionPrivate',
200
+ usdcOptionPublic: 'usdcOptionPublic',
201
+ usdcPerpPrivate: 'usdcPerpPrivate',
202
+ usdcPerpPublic: 'usdcPerpPublic',
203
+ unifiedPrivate: 'unifiedPrivate',
204
+ unifiedOptionPublic: 'unifiedOptionPublic',
205
+ unifiedPerpUSDTPublic: 'unifiedPerpUSDTPublic',
206
+ unifiedPerpUSDCPublic: 'unifiedPerpUSDCPublic',
207
+ contractUSDTPublic: 'contractUSDTPublic',
208
+ contractUSDTPrivate: 'contractUSDTPrivate',
209
+ contractInversePublic: 'contractInversePublic',
210
+ contractInversePrivate: 'contractInversePrivate',
211
+ v5SpotPublic: 'v5SpotPublic',
212
+ v5LinearPublic: 'v5LinearPublic',
213
+ v5InversePublic: 'v5InversePublic',
214
+ v5OptionPublic: 'v5OptionPublic',
215
+ v5Private: 'v5Private',
216
+ } as const;
217
+
218
+ export const WS_AUTH_ON_CONNECT_KEYS: WsKey[] = [
219
+ WS_KEY_MAP.spotV3Private,
220
+ WS_KEY_MAP.usdcOptionPrivate,
221
+ WS_KEY_MAP.usdcPerpPrivate,
222
+ WS_KEY_MAP.unifiedPrivate,
223
+ WS_KEY_MAP.contractUSDTPrivate,
224
+ WS_KEY_MAP.contractInversePrivate,
225
+ WS_KEY_MAP.v5Private,
226
+ ];
227
+
228
+ export const PUBLIC_WS_KEYS = [
229
+ WS_KEY_MAP.linearPublic,
230
+ WS_KEY_MAP.spotPublic,
231
+ WS_KEY_MAP.spotV3Public,
232
+ WS_KEY_MAP.usdcOptionPublic,
233
+ WS_KEY_MAP.usdcPerpPublic,
234
+ WS_KEY_MAP.unifiedOptionPublic,
235
+ WS_KEY_MAP.unifiedPerpUSDTPublic,
236
+ WS_KEY_MAP.unifiedPerpUSDCPublic,
237
+ WS_KEY_MAP.contractUSDTPublic,
238
+ WS_KEY_MAP.contractInversePublic,
239
+ WS_KEY_MAP.v5SpotPublic,
240
+ WS_KEY_MAP.v5LinearPublic,
241
+ WS_KEY_MAP.v5InversePublic,
242
+ WS_KEY_MAP.v5OptionPublic,
243
+ ] as string[];
244
+
245
+ /** Used to automatically determine if a sub request should be to the public or private ws (when there's two) */
246
+ const PRIVATE_TOPICS = [
247
+ 'stop_order',
248
+ 'outboundAccountInfo',
249
+ 'executionReport',
250
+ 'ticketInfo',
251
+ // copy trading apis
252
+ 'copyTradePosition',
253
+ 'copyTradeOrder',
254
+ 'copyTradeExecution',
255
+ 'copyTradeWallet',
256
+ // usdc options
257
+ 'user.openapi.option.position',
258
+ 'user.openapi.option.trade',
259
+ 'user.order',
260
+ 'user.openapi.option.order',
261
+ 'user.service',
262
+ 'user.openapi.greeks',
263
+ 'user.mmp.event',
264
+ // usdc perps
265
+ 'user.openapi.perp.position',
266
+ 'user.openapi.perp.trade',
267
+ 'user.openapi.perp.order',
268
+ 'user.service',
269
+ // unified margin
270
+ 'user.position.unifiedAccount',
271
+ 'user.execution.unifiedAccount',
272
+ 'user.order.unifiedAccount',
273
+ 'user.wallet.unifiedAccount',
274
+ 'user.greeks.unifiedAccount',
275
+ // contract v3
276
+ 'user.position.contractAccount',
277
+ 'user.execution.contractAccount',
278
+ 'user.order.contractAccount',
279
+ 'user.wallet.contractAccount',
280
+ // v5
281
+ 'position',
282
+ 'execution',
283
+ 'order',
284
+ 'wallet',
285
+ 'greeks',
286
+ ];
287
+
288
+ export function isPrivateWsTopic(topic: string): boolean {
289
+ return PRIVATE_TOPICS.includes(topic);
290
+ }
291
+
292
+ export function getWsKeyForTopic(
293
+ market: APIMarket,
294
+ topic: string,
295
+ isPrivate?: boolean,
296
+ category?: CategoryV5,
297
+ ): WsKey {
298
+ const isPrivateTopic = isPrivate === true || PRIVATE_TOPICS.includes(topic);
299
+ switch (market) {
300
+ case 'inverse': {
301
+ return WS_KEY_MAP.inverse;
302
+ }
303
+ case 'linear': {
304
+ return isPrivateTopic
305
+ ? WS_KEY_MAP.linearPrivate
306
+ : WS_KEY_MAP.linearPublic;
307
+ }
308
+ case 'spot': {
309
+ return isPrivateTopic ? WS_KEY_MAP.spotPrivate : WS_KEY_MAP.spotPublic;
310
+ }
311
+ case 'spotv3': {
312
+ return isPrivateTopic
313
+ ? WS_KEY_MAP.spotV3Private
314
+ : WS_KEY_MAP.spotV3Public;
315
+ }
316
+ case 'usdcOption': {
317
+ return isPrivateTopic
318
+ ? WS_KEY_MAP.usdcOptionPrivate
319
+ : WS_KEY_MAP.usdcOptionPublic;
320
+ }
321
+ case 'usdcPerp': {
322
+ return isPrivateTopic
323
+ ? WS_KEY_MAP.usdcPerpPrivate
324
+ : WS_KEY_MAP.usdcPerpPublic;
325
+ }
326
+ case 'unifiedOption': {
327
+ return isPrivateTopic
328
+ ? WS_KEY_MAP.unifiedPrivate
329
+ : WS_KEY_MAP.unifiedOptionPublic;
330
+ }
331
+ case 'unifiedPerp': {
332
+ if (isPrivateTopic) {
333
+ return WS_KEY_MAP.unifiedPrivate;
334
+ }
335
+
336
+ const upperTopic = topic.toUpperCase();
337
+ if (upperTopic.indexOf('USDT') !== -1) {
338
+ return WS_KEY_MAP.unifiedPerpUSDTPublic;
339
+ }
340
+
341
+ if (
342
+ upperTopic.indexOf('USDC') !== -1 ||
343
+ upperTopic.indexOf('PERP') !== -1
344
+ ) {
345
+ return WS_KEY_MAP.unifiedPerpUSDCPublic;
346
+ }
347
+
348
+ throw new Error(
349
+ `Failed to determine wskey for unified perps topic: "${topic}"`,
350
+ );
351
+ }
352
+ case 'contractInverse': {
353
+ return isPrivateTopic
354
+ ? WS_KEY_MAP.contractInversePrivate
355
+ : WS_KEY_MAP.contractInversePublic;
356
+ }
357
+ case 'contractUSDT': {
358
+ return isPrivateTopic
359
+ ? WS_KEY_MAP.contractUSDTPrivate
360
+ : WS_KEY_MAP.contractUSDTPublic;
361
+ }
362
+ case 'v5': {
363
+ if (isPrivateTopic) {
364
+ return WS_KEY_MAP.v5Private;
365
+ }
366
+
367
+ switch (category) {
368
+ case 'spot': {
369
+ return WS_KEY_MAP.v5SpotPublic;
370
+ }
371
+ case 'linear': {
372
+ return WS_KEY_MAP.v5LinearPublic;
373
+ }
374
+ case 'inverse': {
375
+ return WS_KEY_MAP.v5InversePublic;
376
+ }
377
+ case 'option': {
378
+ return WS_KEY_MAP.v5OptionPublic;
379
+ }
380
+ case undefined: {
381
+ throw new Error('Category cannot be undefined');
382
+ }
383
+ default: {
384
+ throw neverGuard(
385
+ category,
386
+ 'getWsKeyForTopic(v5): Unhandled v5 category',
387
+ );
388
+ }
389
+ }
390
+ }
391
+ default: {
392
+ throw neverGuard(market, 'getWsKeyForTopic(): Unhandled market');
393
+ }
394
+ }
395
+ }
396
+
397
+ export function getWsUrl(
398
+ wsKey: WsKey,
399
+ wsUrl: string | undefined,
400
+ isTestnet: boolean,
401
+ logger: typeof DefaultLogger,
402
+ ): string {
403
+ if (wsUrl) {
404
+ return wsUrl;
405
+ }
406
+
407
+ const networkKey = isTestnet ? 'testnet' : 'livenet';
408
+
409
+ switch (wsKey) {
410
+ case WS_KEY_MAP.linearPublic: {
411
+ return WS_BASE_URL_MAP.linear.public[networkKey];
412
+ }
413
+ case WS_KEY_MAP.linearPrivate: {
414
+ return WS_BASE_URL_MAP.linear.private[networkKey];
415
+ }
416
+ case WS_KEY_MAP.spotPublic: {
417
+ return WS_BASE_URL_MAP.spot.public[networkKey];
418
+ }
419
+ case WS_KEY_MAP.spotPrivate: {
420
+ return WS_BASE_URL_MAP.spot.private[networkKey];
421
+ }
422
+ case WS_KEY_MAP.spotV3Public: {
423
+ return WS_BASE_URL_MAP.spotv3.public[networkKey];
424
+ }
425
+ case WS_KEY_MAP.spotV3Private: {
426
+ return WS_BASE_URL_MAP.spotv3.private[networkKey];
427
+ }
428
+ case WS_KEY_MAP.inverse: {
429
+ // private and public are on the same WS connection
430
+ return WS_BASE_URL_MAP.inverse.public[networkKey];
431
+ }
432
+ case WS_KEY_MAP.usdcOptionPublic: {
433
+ return WS_BASE_URL_MAP.usdcOption.public[networkKey];
434
+ }
435
+ case WS_KEY_MAP.usdcOptionPrivate: {
436
+ return WS_BASE_URL_MAP.usdcOption.private[networkKey];
437
+ }
438
+ case WS_KEY_MAP.usdcPerpPublic: {
439
+ return WS_BASE_URL_MAP.usdcPerp.public[networkKey];
440
+ }
441
+ case WS_KEY_MAP.usdcPerpPrivate: {
442
+ return WS_BASE_URL_MAP.usdcPerp.private[networkKey];
443
+ }
444
+ case WS_KEY_MAP.unifiedOptionPublic: {
445
+ return WS_BASE_URL_MAP.unifiedOption.public[networkKey];
446
+ }
447
+ case WS_KEY_MAP.unifiedPerpUSDTPublic: {
448
+ return WS_BASE_URL_MAP.unifiedPerpUSDT.public[networkKey];
449
+ }
450
+ case WS_KEY_MAP.unifiedPerpUSDCPublic: {
451
+ return WS_BASE_URL_MAP.unifiedPerpUSDC.public[networkKey];
452
+ }
453
+ case WS_KEY_MAP.unifiedPrivate: {
454
+ return WS_BASE_URL_MAP.unifiedPerp.private[networkKey];
455
+ }
456
+ case WS_KEY_MAP.contractInversePrivate: {
457
+ return WS_BASE_URL_MAP.contractInverse.private[networkKey];
458
+ }
459
+ case WS_KEY_MAP.contractInversePublic: {
460
+ return WS_BASE_URL_MAP.contractInverse.public[networkKey];
461
+ }
462
+ case WS_KEY_MAP.contractUSDTPrivate: {
463
+ return WS_BASE_URL_MAP.contractUSDT.private[networkKey];
464
+ }
465
+ case WS_KEY_MAP.contractUSDTPublic: {
466
+ return WS_BASE_URL_MAP.contractUSDT.public[networkKey];
467
+ }
468
+ case WS_KEY_MAP.v5Private: {
469
+ return WS_BASE_URL_MAP.v5.private[networkKey];
470
+ }
471
+ case WS_KEY_MAP.v5SpotPublic: {
472
+ return WS_BASE_URL_MAP.v5SpotPublic.public[networkKey];
473
+ }
474
+ case WS_KEY_MAP.v5LinearPublic: {
475
+ return WS_BASE_URL_MAP.v5LinearPublic.public[networkKey];
476
+ }
477
+ case WS_KEY_MAP.v5InversePublic: {
478
+ return WS_BASE_URL_MAP.v5InversePublic.public[networkKey];
479
+ }
480
+ case WS_KEY_MAP.v5OptionPublic: {
481
+ return WS_BASE_URL_MAP.v5OptionPublic.public[networkKey];
482
+ }
483
+ default: {
484
+ logger.error('getWsUrl(): Unhandled wsKey: ', {
485
+ category: 'bybit-ws',
486
+ wsKey,
487
+ });
488
+ throw neverGuard(wsKey, 'getWsUrl(): Unhandled wsKey');
489
+ }
490
+ }
491
+ }
492
+
493
+ export function getMaxTopicsPerSubscribeEvent(
494
+ market: APIMarket,
495
+ wsKey: WsKey,
496
+ ): number | null {
497
+ const topicsPerEventSpot = 10;
498
+ switch (market) {
499
+ case 'inverse':
500
+ case 'linear':
501
+ case 'usdcOption':
502
+ case 'usdcPerp':
503
+ case 'unifiedOption':
504
+ case 'unifiedPerp':
505
+ case 'spot':
506
+ case 'contractInverse':
507
+ case 'contractUSDT':
508
+ case 'v5': {
509
+ if (wsKey === WS_KEY_MAP.v5SpotPublic) {
510
+ return topicsPerEventSpot;
511
+ }
512
+ return null;
513
+ }
514
+ case 'spotv3': {
515
+ return topicsPerEventSpot;
516
+ }
517
+ default: {
518
+ throw neverGuard(market, 'getWsKeyForTopic(): Unhandled market');
519
+ }
520
+ }
521
+ }
522
+
523
+ export function getUsdcWsKeyForTopic(
524
+ topic: string,
525
+ subGroup: 'option' | 'perp',
526
+ ): WsKey {
527
+ const isPrivateTopic = PRIVATE_TOPICS.includes(topic);
528
+ if (subGroup === 'option') {
529
+ return isPrivateTopic
530
+ ? WS_KEY_MAP.usdcOptionPrivate
531
+ : WS_KEY_MAP.usdcOptionPublic;
532
+ }
533
+ return isPrivateTopic
534
+ ? WS_KEY_MAP.usdcOptionPrivate
535
+ : WS_KEY_MAP.usdcOptionPublic;
536
+ // return isPrivateTopic
537
+ // ? WS_KEY_MAP.usdcPerpPrivate
538
+ // : WS_KEY_MAP.usdcPerpPublic;
539
+ }
540
+
541
+ export const WS_ERROR_ENUM = {
542
+ NOT_AUTHENTICATED_SPOT_V3: '-1004',
543
+ API_ERROR_GENERIC: '10001',
544
+ API_SIGN_AUTH_FAILED: '10003',
545
+ USDC_OPTION_AUTH_FAILED: '3303006',
546
+ };
547
+
548
+ export function neverGuard(x: never, msg: string): Error {
549
+ return new Error(`Unhandled value exception "x", ${msg}`);
550
+ }