ccxt 4.4.2 → 4.4.4

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 (137) hide show
  1. package/README.md +4 -4
  2. package/dist/ccxt.browser.min.js +3 -3
  3. package/dist/cjs/ccxt.js +1 -1
  4. package/dist/cjs/src/base/Exchange.js +2 -2
  5. package/dist/cjs/src/base/functions/misc.js +11 -0
  6. package/dist/cjs/src/base/functions.js +1 -0
  7. package/dist/cjs/src/base/ws/WsClient.js +2 -1
  8. package/dist/cjs/src/binance.js +49 -22
  9. package/dist/cjs/src/bingx.js +1 -0
  10. package/dist/cjs/src/bitfinex2.js +7 -6
  11. package/dist/cjs/src/bitget.js +10 -6
  12. package/dist/cjs/src/bitmart.js +3 -1
  13. package/dist/cjs/src/bitmex.js +11 -10
  14. package/dist/cjs/src/bitso.js +5 -4
  15. package/dist/cjs/src/bitstamp.js +33 -45
  16. package/dist/cjs/src/blofin.js +21 -23
  17. package/dist/cjs/src/bybit.js +22 -20
  18. package/dist/cjs/src/coinbase.js +28 -7
  19. package/dist/cjs/src/coinbaseexchange.js +11 -11
  20. package/dist/cjs/src/coinlist.js +6 -5
  21. package/dist/cjs/src/coinmetro.js +3 -3
  22. package/dist/cjs/src/cryptocom.js +9 -6
  23. package/dist/cjs/src/currencycom.js +6 -6
  24. package/dist/cjs/src/delta.js +5 -5
  25. package/dist/cjs/src/digifinex.js +8 -6
  26. package/dist/cjs/src/gate.js +6 -5
  27. package/dist/cjs/src/hashkey.js +9 -7
  28. package/dist/cjs/src/htx.js +13 -16
  29. package/dist/cjs/src/hyperliquid.js +67 -114
  30. package/dist/cjs/src/kraken.js +8 -6
  31. package/dist/cjs/src/kucoin.js +9 -8
  32. package/dist/cjs/src/luno.js +10 -9
  33. package/dist/cjs/src/mexc.js +54 -2
  34. package/dist/cjs/src/ndax.js +6 -5
  35. package/dist/cjs/src/okcoin.js +18 -27
  36. package/dist/cjs/src/okx.js +18 -26
  37. package/dist/cjs/src/p2b.js +2 -2
  38. package/dist/cjs/src/pro/bybit.js +56 -0
  39. package/dist/cjs/src/pro/cryptocom.js +191 -21
  40. package/dist/cjs/src/pro/mexc.js +165 -3
  41. package/dist/cjs/src/pro/okx.js +6 -3
  42. package/dist/cjs/src/pro/oxfun.js +75 -0
  43. package/dist/cjs/src/pro/phemex.js +45 -1
  44. package/dist/cjs/src/pro/woofipro.js +67 -0
  45. package/dist/cjs/src/woo.js +7 -6
  46. package/dist/cjs/src/woofipro.js +8 -6
  47. package/dist/cjs/src/xt.js +10 -4
  48. package/dist/cjs/src/zonda.js +6 -5
  49. package/js/ccxt.d.ts +1 -1
  50. package/js/ccxt.js +1 -1
  51. package/js/src/abstract/bitmart.d.ts +1 -0
  52. package/js/src/base/Exchange.d.ts +2 -2
  53. package/js/src/base/Exchange.js +2 -2
  54. package/js/src/base/functions/misc.d.ts +2 -1
  55. package/js/src/base/functions/misc.js +11 -1
  56. package/js/src/base/types.d.ts +1 -1
  57. package/js/src/base/ws/WsClient.js +2 -2
  58. package/js/src/binance.d.ts +4 -20
  59. package/js/src/binance.js +49 -22
  60. package/js/src/bingx.js +1 -0
  61. package/js/src/bitfinex2.d.ts +3 -19
  62. package/js/src/bitfinex2.js +7 -6
  63. package/js/src/bitget.d.ts +3 -19
  64. package/js/src/bitget.js +10 -6
  65. package/js/src/bitmart.js +3 -1
  66. package/js/src/bitmex.d.ts +3 -22
  67. package/js/src/bitmex.js +11 -10
  68. package/js/src/bitso.d.ts +3 -19
  69. package/js/src/bitso.js +5 -4
  70. package/js/src/bitstamp.d.ts +3 -35
  71. package/js/src/bitstamp.js +33 -45
  72. package/js/src/blofin.d.ts +3 -15
  73. package/js/src/blofin.js +21 -23
  74. package/js/src/bybit.d.ts +3 -19
  75. package/js/src/bybit.js +23 -21
  76. package/js/src/coinbase.d.ts +3 -19
  77. package/js/src/coinbase.js +28 -7
  78. package/js/src/coinbaseexchange.d.ts +3 -19
  79. package/js/src/coinbaseexchange.js +11 -11
  80. package/js/src/coinlist.d.ts +3 -19
  81. package/js/src/coinlist.js +6 -5
  82. package/js/src/coinmetro.d.ts +3 -19
  83. package/js/src/coinmetro.js +3 -3
  84. package/js/src/cryptocom.d.ts +3 -22
  85. package/js/src/cryptocom.js +9 -6
  86. package/js/src/currencycom.d.ts +3 -3
  87. package/js/src/currencycom.js +6 -6
  88. package/js/src/delta.d.ts +3 -19
  89. package/js/src/delta.js +5 -5
  90. package/js/src/digifinex.d.ts +3 -19
  91. package/js/src/digifinex.js +8 -6
  92. package/js/src/gate.d.ts +3 -19
  93. package/js/src/gate.js +6 -5
  94. package/js/src/hashkey.d.ts +3 -20
  95. package/js/src/hashkey.js +9 -7
  96. package/js/src/htx.d.ts +3 -19
  97. package/js/src/htx.js +13 -16
  98. package/js/src/hyperliquid.d.ts +3 -19
  99. package/js/src/hyperliquid.js +68 -115
  100. package/js/src/kraken.d.ts +5 -24
  101. package/js/src/kraken.js +8 -6
  102. package/js/src/kucoin.d.ts +3 -19
  103. package/js/src/kucoin.js +9 -8
  104. package/js/src/luno.d.ts +4 -20
  105. package/js/src/luno.js +10 -9
  106. package/js/src/mexc.js +54 -2
  107. package/js/src/ndax.d.ts +3 -19
  108. package/js/src/ndax.js +6 -5
  109. package/js/src/okcoin.d.ts +3 -19
  110. package/js/src/okcoin.js +18 -27
  111. package/js/src/okx.d.ts +3 -19
  112. package/js/src/okx.js +18 -26
  113. package/js/src/p2b.js +2 -2
  114. package/js/src/pro/bybit.d.ts +2 -0
  115. package/js/src/pro/bybit.js +56 -0
  116. package/js/src/pro/cryptocom.d.ts +7 -1
  117. package/js/src/pro/cryptocom.js +191 -21
  118. package/js/src/pro/mexc.d.ts +6 -1
  119. package/js/src/pro/mexc.js +166 -4
  120. package/js/src/pro/okx.js +6 -3
  121. package/js/src/pro/oxfun.d.ts +3 -0
  122. package/js/src/pro/oxfun.js +75 -0
  123. package/js/src/pro/phemex.d.ts +2 -1
  124. package/js/src/pro/phemex.js +45 -1
  125. package/js/src/pro/woofipro.d.ts +3 -0
  126. package/js/src/pro/woofipro.js +67 -0
  127. package/js/src/static_dependencies/jsencrypt/lib/jsbn/jsbn.d.ts +1 -1
  128. package/js/src/static_dependencies/starknet/utils/calldata/parser/index.d.ts +1 -1
  129. package/js/src/woo.d.ts +3 -19
  130. package/js/src/woo.js +7 -6
  131. package/js/src/woofipro.d.ts +3 -19
  132. package/js/src/woofipro.js +8 -6
  133. package/js/src/xt.d.ts +3 -22
  134. package/js/src/xt.js +10 -4
  135. package/js/src/zonda.d.ts +3 -19
  136. package/js/src/zonda.js +6 -5
  137. package/package.json +1 -1
@@ -14,7 +14,8 @@ class cryptocom extends cryptocom$1 {
14
14
  'ws': true,
15
15
  'watchBalance': true,
16
16
  'watchTicker': true,
17
- 'watchTickers': false,
17
+ 'watchTickers': true,
18
+ 'watchBidsAsks': true,
18
19
  'watchMyTrades': true,
19
20
  'watchTrades': true,
20
21
  'watchTradesForSymbols': true,
@@ -477,41 +478,210 @@ class cryptocom extends cryptocom$1 {
477
478
  const messageHash = 'unsubscribe:ticker:' + market['symbol'];
478
479
  return await this.unWatchPublicMultiple('ticker', [market['symbol']], [messageHash], [subMessageHash], [subMessageHash], params);
479
480
  }
481
+ async watchTickers(symbols = undefined, params = {}) {
482
+ /**
483
+ * @method
484
+ * @name cryptocom#watchTickers
485
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
486
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#ticker-instrument_name
487
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
488
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
489
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
490
+ */
491
+ await this.loadMarkets();
492
+ symbols = this.marketSymbols(symbols, undefined, false);
493
+ const messageHashes = [];
494
+ const marketIds = this.marketIds(symbols);
495
+ for (let i = 0; i < marketIds.length; i++) {
496
+ const marketId = marketIds[i];
497
+ messageHashes.push('ticker.' + marketId);
498
+ }
499
+ const url = this.urls['api']['ws']['public'];
500
+ const id = this.nonce();
501
+ const request = {
502
+ 'method': 'subscribe',
503
+ 'params': {
504
+ 'channels': messageHashes,
505
+ },
506
+ 'nonce': id,
507
+ };
508
+ const ticker = await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes);
509
+ if (this.newUpdates) {
510
+ const result = {};
511
+ result[ticker['symbol']] = ticker;
512
+ return result;
513
+ }
514
+ return this.filterByArray(this.tickers, 'symbol', symbols);
515
+ }
516
+ async unWatchTickers(symbols = undefined, params = {}) {
517
+ /**
518
+ * @method
519
+ * @name cryptocom#unWatchTickers
520
+ * @description unWatches a price ticker
521
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#ticker-instrument_name
522
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
523
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
524
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
525
+ */
526
+ await this.loadMarkets();
527
+ symbols = this.marketSymbols(symbols, undefined, false);
528
+ const messageHashes = [];
529
+ const subMessageHashes = [];
530
+ const marketIds = this.marketIds(symbols);
531
+ for (let i = 0; i < marketIds.length; i++) {
532
+ const marketId = marketIds[i];
533
+ const symbol = symbols[i];
534
+ subMessageHashes.push('ticker.' + marketId);
535
+ messageHashes.push('unsubscribe:ticker:' + symbol);
536
+ }
537
+ return await this.unWatchPublicMultiple('ticker', symbols, messageHashes, subMessageHashes, subMessageHashes, params);
538
+ }
480
539
  handleTicker(client, message) {
481
540
  //
482
- // {
483
- // "info":{
484
- // "instrument_name":"BTC_USDT",
485
- // "subscription":"ticker.BTC_USDT",
486
- // "channel":"ticker",
487
- // "data":[
488
- // {
489
- // "i":"BTC_USDT",
490
- // "b":43063.19,
491
- // "k":43063.2,
492
- // "a":43063.19,
493
- // "t":1648121165658,
494
- // "v":43573.912409,
495
- // "h":43498.51,
496
- // "l":41876.58,
497
- // "c":1087.43
498
- // }
499
- // ]
541
+ // {
542
+ // "instrument_name": "ETHUSD-PERP",
543
+ // "subscription": "ticker.ETHUSD-PERP",
544
+ // "channel": "ticker",
545
+ // "data": [
546
+ // {
547
+ // "h": "2400.20",
548
+ // "l": "2277.10",
549
+ // "a": "2335.25",
550
+ // "c": "-0.0022",
551
+ // "b": "2335.10",
552
+ // "bs": "5.4000",
553
+ // "k": "2335.16",
554
+ // "ks": "1.9970",
555
+ // "i": "ETHUSD-PERP",
556
+ // "v": "1305697.6462",
557
+ // "vv": "3058704939.17",
558
+ // "oi": "161646.3614",
559
+ // "t": 1726069647560
560
+ // }
561
+ // ]
500
562
  // }
501
- // }
502
563
  //
564
+ this.handleBidAsk(client, message);
503
565
  const messageHash = this.safeString(message, 'subscription');
504
566
  const marketId = this.safeString(message, 'instrument_name');
505
567
  const market = this.safeMarket(marketId);
506
568
  const data = this.safeValue(message, 'data', []);
507
569
  for (let i = 0; i < data.length; i++) {
508
570
  const ticker = data[i];
509
- const parsed = this.parseTicker(ticker, market);
571
+ const parsed = this.parseWsTicker(ticker, market);
510
572
  const symbol = parsed['symbol'];
511
573
  this.tickers[symbol] = parsed;
512
574
  client.resolve(parsed, messageHash);
513
575
  }
514
576
  }
577
+ parseWsTicker(ticker, market = undefined) {
578
+ //
579
+ // {
580
+ // "h": "2400.20",
581
+ // "l": "2277.10",
582
+ // "a": "2335.25",
583
+ // "c": "-0.0022",
584
+ // "b": "2335.10",
585
+ // "bs": "5.4000",
586
+ // "k": "2335.16",
587
+ // "ks": "1.9970",
588
+ // "i": "ETHUSD-PERP",
589
+ // "v": "1305697.6462",
590
+ // "vv": "3058704939.17",
591
+ // "oi": "161646.3614",
592
+ // "t": 1726069647560
593
+ // }
594
+ //
595
+ const timestamp = this.safeInteger(ticker, 't');
596
+ const marketId = this.safeString(ticker, 'i');
597
+ market = this.safeMarket(marketId, market, '_');
598
+ const quote = this.safeString(market, 'quote');
599
+ const last = this.safeString(ticker, 'a');
600
+ return this.safeTicker({
601
+ 'symbol': market['symbol'],
602
+ 'timestamp': timestamp,
603
+ 'datetime': this.iso8601(timestamp),
604
+ 'high': this.safeNumber(ticker, 'h'),
605
+ 'low': this.safeNumber(ticker, 'l'),
606
+ 'bid': this.safeNumber(ticker, 'b'),
607
+ 'bidVolume': this.safeNumber(ticker, 'bs'),
608
+ 'ask': this.safeNumber(ticker, 'k'),
609
+ 'askVolume': this.safeNumber(ticker, 'ks'),
610
+ 'vwap': undefined,
611
+ 'open': undefined,
612
+ 'close': last,
613
+ 'last': last,
614
+ 'previousClose': undefined,
615
+ 'change': undefined,
616
+ 'percentage': this.safeString(ticker, 'c'),
617
+ 'average': undefined,
618
+ 'baseVolume': this.safeString(ticker, 'v'),
619
+ 'quoteVolume': (quote === 'USD') ? this.safeString(ticker, 'vv') : undefined,
620
+ 'info': ticker,
621
+ }, market);
622
+ }
623
+ async watchBidsAsks(symbols = undefined, params = {}) {
624
+ /**
625
+ * @method
626
+ * @name cryptocom#watchBidsAsks
627
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#ticker-instrument_name
628
+ * @description watches best bid & ask for symbols
629
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
630
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
631
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
632
+ */
633
+ await this.loadMarkets();
634
+ symbols = this.marketSymbols(symbols, undefined, false);
635
+ const messageHashes = [];
636
+ const topics = [];
637
+ const marketIds = this.marketIds(symbols);
638
+ for (let i = 0; i < marketIds.length; i++) {
639
+ const marketId = marketIds[i];
640
+ messageHashes.push('bidask.' + symbols[i]);
641
+ topics.push('ticker.' + marketId);
642
+ }
643
+ const url = this.urls['api']['ws']['public'];
644
+ const id = this.nonce();
645
+ const request = {
646
+ 'method': 'subscribe',
647
+ 'params': {
648
+ 'channels': topics,
649
+ },
650
+ 'nonce': id,
651
+ };
652
+ const newTickers = await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes);
653
+ if (this.newUpdates) {
654
+ const tickers = {};
655
+ tickers[newTickers['symbol']] = newTickers;
656
+ return tickers;
657
+ }
658
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
659
+ }
660
+ handleBidAsk(client, message) {
661
+ const data = this.safeList(message, 'data', []);
662
+ const ticker = this.safeDict(data, 0, {});
663
+ const parsedTicker = this.parseWsBidAsk(ticker);
664
+ const symbol = parsedTicker['symbol'];
665
+ this.bidsasks[symbol] = parsedTicker;
666
+ const messageHash = 'bidask.' + symbol;
667
+ client.resolve(parsedTicker, messageHash);
668
+ }
669
+ parseWsBidAsk(ticker, market = undefined) {
670
+ const marketId = this.safeString(ticker, 'i');
671
+ market = this.safeMarket(marketId, market);
672
+ const symbol = this.safeString(market, 'symbol');
673
+ const timestamp = this.safeInteger(ticker, 't');
674
+ return this.safeTicker({
675
+ 'symbol': symbol,
676
+ 'timestamp': timestamp,
677
+ 'datetime': this.iso8601(timestamp),
678
+ 'ask': this.safeString(ticker, 'k'),
679
+ 'askVolume': this.safeString(ticker, 'ks'),
680
+ 'bid': this.safeString(ticker, 'b'),
681
+ 'bidVolume': this.safeString(ticker, 'bs'),
682
+ 'info': ticker,
683
+ }, market);
684
+ }
515
685
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
516
686
  /**
517
687
  * @method
@@ -27,7 +27,8 @@ class mexc extends mexc$1 {
27
27
  'watchOrderBook': true,
28
28
  'watchOrders': true,
29
29
  'watchTicker': true,
30
- 'watchTickers': false,
30
+ 'watchTickers': true,
31
+ 'watchBidsAsks': true,
31
32
  'watchTrades': true,
32
33
  'watchTradesForSymbols': false,
33
34
  },
@@ -107,6 +108,7 @@ class mexc extends mexc$1 {
107
108
  // "t": 1678643605721
108
109
  // }
109
110
  //
111
+ this.handleBidAsk(client, message);
110
112
  const rawTicker = this.safeValue2(message, 'd', 'data');
111
113
  const marketId = this.safeString2(message, 's', 'symbol');
112
114
  const timestamp = this.safeInteger(message, 't');
@@ -125,6 +127,84 @@ class mexc extends mexc$1 {
125
127
  const messageHash = 'ticker:' + symbol;
126
128
  client.resolve(ticker, messageHash);
127
129
  }
130
+ async watchTickers(symbols = undefined, params = {}) {
131
+ /**
132
+ * @method
133
+ * @name mexc#watchTickers
134
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
135
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#individual-symbol-book-ticker-streams
136
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#public-channels
137
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
138
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
139
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
140
+ */
141
+ await this.loadMarkets();
142
+ symbols = this.marketSymbols(symbols, undefined, false);
143
+ const messageHashes = [];
144
+ const marketIds = this.marketIds(symbols);
145
+ const firstMarket = this.market(symbols[0]);
146
+ const isSpot = firstMarket['spot'];
147
+ const url = (isSpot) ? this.urls['api']['ws']['spot'] : this.urls['api']['ws']['swap'];
148
+ const request = {};
149
+ if (isSpot) {
150
+ const topics = [];
151
+ for (let i = 0; i < marketIds.length; i++) {
152
+ const marketId = marketIds[i];
153
+ messageHashes.push('ticker:' + symbols[i]);
154
+ topics.push('spot@public.bookTicker.v3.api@' + marketId);
155
+ }
156
+ request['method'] = 'SUBSCRIPTION';
157
+ request['params'] = topics;
158
+ }
159
+ else {
160
+ request['method'] = 'sub.tickers';
161
+ request['params'] = {};
162
+ messageHashes.push('ticker');
163
+ }
164
+ const ticker = await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes);
165
+ if (isSpot && this.newUpdates) {
166
+ const result = {};
167
+ result[ticker['symbol']] = ticker;
168
+ return result;
169
+ }
170
+ return this.filterByArray(this.tickers, 'symbol', symbols);
171
+ }
172
+ handleTickers(client, message) {
173
+ //
174
+ // {
175
+ // "channel": "push.tickers",
176
+ // "data": [
177
+ // {
178
+ // "symbol": "ETH_USDT",
179
+ // "lastPrice": 2324.5,
180
+ // "riseFallRate": 0.0356,
181
+ // "fairPrice": 2324.32,
182
+ // "indexPrice": 2325.44,
183
+ // "volume24": 25868309,
184
+ // "amount24": 591752573.9792,
185
+ // "maxBidPrice": 2557.98,
186
+ // "minAskPrice": 2092.89,
187
+ // "lower24Price": 2239.39,
188
+ // "high24Price": 2332.59,
189
+ // "timestamp": 1725872514111
190
+ // }
191
+ // ],
192
+ // "ts": 1725872514111
193
+ // }
194
+ //
195
+ const data = this.safeList(message, 'data');
196
+ const topic = 'ticker';
197
+ const result = [];
198
+ for (let i = 0; i < data.length; i++) {
199
+ const ticker = this.parseTicker(data[i]);
200
+ const symbol = ticker['symbol'];
201
+ this.tickers[symbol] = ticker;
202
+ result.push(ticker);
203
+ const messageHash = topic + ':' + symbol;
204
+ client.resolve(ticker, messageHash);
205
+ }
206
+ client.resolve(result, topic);
207
+ }
128
208
  parseWsTicker(ticker, market = undefined) {
129
209
  //
130
210
  // spot
@@ -157,6 +237,87 @@ class mexc extends mexc$1 {
157
237
  'info': ticker,
158
238
  }, market);
159
239
  }
240
+ async watchBidsAsks(symbols = undefined, params = {}) {
241
+ /**
242
+ * @method
243
+ * @name mexc#watchBidsAsks
244
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#individual-symbol-book-ticker-streams
245
+ * @description watches best bid & ask for symbols
246
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
247
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
248
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
249
+ */
250
+ await this.loadMarkets();
251
+ symbols = this.marketSymbols(symbols, undefined, true, false, true);
252
+ let marketType = undefined;
253
+ if (symbols === undefined) {
254
+ throw new errors.ArgumentsRequired(this.id + 'watchBidsAsks required symbols argument');
255
+ }
256
+ const markets = this.marketsForSymbols(symbols);
257
+ [marketType, params] = this.handleMarketTypeAndParams('watchBidsAsks', markets[0], params);
258
+ const isSpot = marketType === 'spot';
259
+ if (!isSpot) {
260
+ throw new errors.NotSupported(this.id + 'watchBidsAsks only support spot market');
261
+ }
262
+ const messageHashes = [];
263
+ const topics = [];
264
+ for (let i = 0; i < symbols.length; i++) {
265
+ if (isSpot) {
266
+ const market = this.market(symbols[i]);
267
+ topics.push('spot@public.bookTicker.v3.api@' + market['id']);
268
+ }
269
+ messageHashes.push('bidask:' + symbols[i]);
270
+ }
271
+ const url = this.urls['api']['ws']['spot'];
272
+ const request = {
273
+ 'method': 'SUBSCRIPTION',
274
+ 'params': topics,
275
+ };
276
+ const ticker = await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes);
277
+ if (this.newUpdates) {
278
+ const tickers = {};
279
+ tickers[ticker['symbol']] = ticker;
280
+ return tickers;
281
+ }
282
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
283
+ }
284
+ handleBidAsk(client, message) {
285
+ //
286
+ // {
287
+ // "c": "spot@public.bookTicker.v3.api@BTCUSDT",
288
+ // "d": {
289
+ // "A": "4.70432",
290
+ // "B": "6.714863",
291
+ // "a": "20744.54",
292
+ // "b": "20744.17"
293
+ // },
294
+ // "s": "BTCUSDT",
295
+ // "t": 1678643605721
296
+ // }
297
+ //
298
+ const parsedTicker = this.parseWsBidAsk(message);
299
+ const symbol = parsedTicker['symbol'];
300
+ this.bidsasks[symbol] = parsedTicker;
301
+ const messageHash = 'bidask:' + symbol;
302
+ client.resolve(parsedTicker, messageHash);
303
+ }
304
+ parseWsBidAsk(ticker, market = undefined) {
305
+ const data = this.safeDict(ticker, 'd');
306
+ const marketId = this.safeString(ticker, 's');
307
+ market = this.safeMarket(marketId, market);
308
+ const symbol = this.safeString(market, 'symbol');
309
+ const timestamp = this.safeInteger(ticker, 't');
310
+ return this.safeTicker({
311
+ 'symbol': symbol,
312
+ 'timestamp': timestamp,
313
+ 'datetime': this.iso8601(timestamp),
314
+ 'ask': this.safeNumber(data, 'a'),
315
+ 'askVolume': this.safeNumber(data, 'A'),
316
+ 'bid': this.safeNumber(data, 'b'),
317
+ 'bidVolume': this.safeNumber(data, 'B'),
318
+ 'info': ticker,
319
+ }, market);
320
+ }
160
321
  async watchSpotPublic(channel, messageHash, params = {}) {
161
322
  const url = this.urls['api']['ws']['spot'];
162
323
  const request = {
@@ -1132,8 +1293,8 @@ class mexc extends mexc$1 {
1132
1293
  // "code": 0,
1133
1294
  // "msg": "spot@public.increase.depth.v3.api@BTCUSDT"
1134
1295
  // }
1135
- //
1136
- const msg = this.safeString(message, 'msg');
1296
+ // Set the default to an empty string if the message is empty during the test.
1297
+ const msg = this.safeString(message, 'msg', '');
1137
1298
  if (msg === 'PONG') {
1138
1299
  this.handlePong(client, message);
1139
1300
  }
@@ -1177,6 +1338,7 @@ class mexc extends mexc$1 {
1177
1338
  'push.kline': this.handleOHLCV,
1178
1339
  'public.bookTicker.v3.api': this.handleTicker,
1179
1340
  'push.ticker': this.handleTicker,
1341
+ 'push.tickers': this.handleTickers,
1180
1342
  'public.increase.depth.v3.api': this.handleOrderBook,
1181
1343
  'push.depth': this.handleOrderBook,
1182
1344
  'private.orders.v3.api': this.handleOrder,
@@ -1440,8 +1440,11 @@ class okx extends okx$1 {
1440
1440
  },
1441
1441
  ],
1442
1442
  };
1443
- const message = this.extend(request, params);
1444
- this.watch(url, messageHash, message, messageHash);
1443
+ // Only add params['access'] to prevent sending custom parameters, such as extraParams.
1444
+ if ('access' in params) {
1445
+ request['access'] = params['access'];
1446
+ }
1447
+ this.watch(url, messageHash, request, messageHash);
1445
1448
  }
1446
1449
  return await future;
1447
1450
  }
@@ -1611,7 +1614,7 @@ class okx extends okx$1 {
1611
1614
  'channel': 'positions',
1612
1615
  'instType': 'ANY',
1613
1616
  };
1614
- const args = [arg];
1617
+ const args = [this.extend(arg, params)];
1615
1618
  const nonSymbolRequest = {
1616
1619
  'op': 'subscribe',
1617
1620
  'args': args,
@@ -22,6 +22,7 @@ class oxfun extends oxfun$1 {
22
22
  'watchMyTrades': false,
23
23
  'watchTicker': true,
24
24
  'watchTickers': true,
25
+ 'watchBidsAsks': true,
25
26
  'watchBalance': true,
26
27
  'createOrderWs': true,
27
28
  'editOrderWs': true,
@@ -496,6 +497,77 @@ class oxfun extends oxfun$1 {
496
497
  client.resolve(ticker, messageHash);
497
498
  }
498
499
  }
500
+ async watchBidsAsks(symbols = undefined, params = {}) {
501
+ /**
502
+ * @method
503
+ * @name oxfun#watchBidsAsks
504
+ * @see https://docs.ox.fun/?json#best-bid-ask
505
+ * @description watches best bid & ask for symbols
506
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
507
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
508
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
509
+ */
510
+ await this.loadMarkets();
511
+ symbols = this.marketSymbols(symbols, undefined, false);
512
+ const messageHashes = [];
513
+ const args = [];
514
+ for (let i = 0; i < symbols.length; i++) {
515
+ const market = this.market(symbols[i]);
516
+ args.push('bestBidAsk:' + market['id']);
517
+ messageHashes.push('bidask:' + market['symbol']);
518
+ }
519
+ const newTickers = await this.subscribeMultiple(messageHashes, args, params);
520
+ if (this.newUpdates) {
521
+ const tickers = {};
522
+ tickers[newTickers['symbol']] = newTickers;
523
+ return tickers;
524
+ }
525
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
526
+ }
527
+ handleBidAsk(client, message) {
528
+ //
529
+ // {
530
+ // "table": "bestBidAsk",
531
+ // "data": {
532
+ // "ask": [
533
+ // 19045.0,
534
+ // 1.0
535
+ // ],
536
+ // "checksum": 3790706311,
537
+ // "marketCode": "BTC-USD-SWAP-LIN",
538
+ // "bid": [
539
+ // 19015.0,
540
+ // 1.0
541
+ // ],
542
+ // "timestamp": "1665456882928"
543
+ // }
544
+ // }
545
+ //
546
+ const data = this.safeDict(message, 'data', {});
547
+ const parsedTicker = this.parseWsBidAsk(data);
548
+ const symbol = parsedTicker['symbol'];
549
+ this.bidsasks[symbol] = parsedTicker;
550
+ const messageHash = 'bidask:' + symbol;
551
+ client.resolve(parsedTicker, messageHash);
552
+ }
553
+ parseWsBidAsk(ticker, market = undefined) {
554
+ const marketId = this.safeString(ticker, 'marketCode');
555
+ market = this.safeMarket(marketId, market);
556
+ const symbol = this.safeString(market, 'symbol');
557
+ const timestamp = this.safeInteger(ticker, 'timestamp');
558
+ const ask = this.safeList(ticker, 'ask', []);
559
+ const bid = this.safeList(ticker, 'bid', []);
560
+ return this.safeTicker({
561
+ 'symbol': symbol,
562
+ 'timestamp': timestamp,
563
+ 'datetime': this.iso8601(timestamp),
564
+ 'ask': this.safeNumber(ask, 0),
565
+ 'askVolume': this.safeNumber(ask, 1),
566
+ 'bid': this.safeNumber(bid, 0),
567
+ 'bidVolume': this.safeNumber(bid, 1),
568
+ 'info': ticker,
569
+ }, market);
570
+ }
499
571
  async watchBalance(params = {}) {
500
572
  /**
501
573
  * @method
@@ -1019,6 +1091,9 @@ class oxfun extends oxfun$1 {
1019
1091
  if (table.indexOf('order') > -1) {
1020
1092
  this.handleOrders(client, message);
1021
1093
  }
1094
+ if (table === 'bestBidAsk') {
1095
+ this.handleBidAsk(client, message);
1096
+ }
1022
1097
  }
1023
1098
  else {
1024
1099
  if (event === 'login') {
@@ -14,7 +14,7 @@ class phemex extends phemex$1 {
14
14
  'has': {
15
15
  'ws': true,
16
16
  'watchTicker': true,
17
- 'watchTickers': false,
17
+ 'watchTickers': true,
18
18
  'watchTrades': true,
19
19
  'watchMyTrades': true,
20
20
  'watchOrders': true,
@@ -523,6 +523,50 @@ class phemex extends phemex$1 {
523
523
  const request = this.deepExtend(subscribe, params);
524
524
  return await this.watch(url, messageHash, request, subscriptionHash);
525
525
  }
526
+ async watchTickers(symbols = undefined, params = {}) {
527
+ /**
528
+ * @method
529
+ * @name phemex#watchTickers
530
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#subscribe-24-hours-ticker
531
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#subscribe-24-hours-ticker
532
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Spot-API-en.md#subscribe-24-hours-ticker
533
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
534
+ * @param {string[]} [symbols] unified symbol of the market to fetch the ticker for
535
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
536
+ * @param {string} [params.channel] the channel to subscribe to, tickers by default. Can be tickers, sprd-tickers, index-tickers, block-tickers
537
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
538
+ */
539
+ await this.loadMarkets();
540
+ symbols = this.marketSymbols(symbols, undefined, false);
541
+ const first = symbols[0];
542
+ const market = this.market(first);
543
+ const isSwap = market['swap'];
544
+ const settleIsUSDT = market['settle'] === 'USDT';
545
+ let name = 'spot_market24h';
546
+ if (isSwap) {
547
+ name = settleIsUSDT ? 'perp_market24h_pack_p' : 'market24h';
548
+ }
549
+ const url = this.urls['api']['ws'];
550
+ const requestId = this.requestId();
551
+ const subscriptionHash = name + '.subscribe';
552
+ const messageHashes = [];
553
+ for (let i = 0; i < symbols.length; i++) {
554
+ messageHashes.push('ticker:' + symbols[i]);
555
+ }
556
+ const subscribe = {
557
+ 'method': subscriptionHash,
558
+ 'id': requestId,
559
+ 'params': [],
560
+ };
561
+ const request = this.deepExtend(subscribe, params);
562
+ const ticker = await this.watchMultiple(url, messageHashes, request, messageHashes);
563
+ if (this.newUpdates) {
564
+ const result = {};
565
+ result[ticker['symbol']] = ticker;
566
+ return result;
567
+ }
568
+ return this.filterByArray(this.tickers, 'symbol', symbols);
569
+ }
526
570
  async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
527
571
  /**
528
572
  * @method