ccxt 4.4.2 → 4.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/ccxt.js CHANGED
@@ -194,7 +194,7 @@ var xt$1 = require('./src/pro/xt.js');
194
194
 
195
195
  //-----------------------------------------------------------------------------
196
196
  // this is updated by vss.js when building
197
- const version = '4.4.2';
197
+ const version = '4.4.3';
198
198
  Exchange["default"].ccxtVersion = version;
199
199
  const exchanges = {
200
200
  'ace': ace,
@@ -6400,8 +6400,8 @@ class binance extends binance$1 {
6400
6400
  [marginMode, params] = this.handleMarginModeAndParams('fetchOrders', params);
6401
6401
  let isPortfolioMargin = undefined;
6402
6402
  [isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'fetchOrders', 'papi', 'portfolioMargin', false);
6403
- const isConditional = this.safeBool2(params, 'stop', 'conditional');
6404
- params = this.omit(params, ['stop', 'conditional', 'type']);
6403
+ const isConditional = this.safeBoolN(params, ['stop', 'trigger', 'conditional']);
6404
+ params = this.omit(params, ['stop', 'trigger', 'conditional', 'type']);
6405
6405
  let request = {
6406
6406
  'symbol': market['id'],
6407
6407
  };
@@ -6670,7 +6670,7 @@ class binance extends binance$1 {
6670
6670
  [marginMode, params] = this.handleMarginModeAndParams('fetchOpenOrders', params);
6671
6671
  let isPortfolioMargin = undefined;
6672
6672
  [isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'fetchOpenOrders', 'papi', 'portfolioMargin', false);
6673
- const isConditional = this.safeBoolN(params, ['stop', 'conditional', 'trigger']);
6673
+ const isConditional = this.safeBoolN(params, ['stop', 'trigger', 'conditional']);
6674
6674
  if (symbol !== undefined) {
6675
6675
  market = this.market(symbol);
6676
6676
  request['symbol'] = market['id'];
@@ -6687,7 +6687,7 @@ class binance extends binance$1 {
6687
6687
  }
6688
6688
  let subType = undefined;
6689
6689
  [subType, params] = this.handleSubTypeAndParams('fetchOpenOrders', market, params);
6690
- params = this.omit(params, ['type', 'stop', 'conditional', 'trigger']);
6690
+ params = this.omit(params, ['type', 'stop', 'trigger', 'conditional']);
6691
6691
  let response = undefined;
6692
6692
  if (type === 'option') {
6693
6693
  if (since !== undefined) {
@@ -6770,8 +6770,8 @@ class binance extends binance$1 {
6770
6770
  };
6771
6771
  let isPortfolioMargin = undefined;
6772
6772
  [isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'fetchOpenOrder', 'papi', 'portfolioMargin', false);
6773
- const isConditional = this.safeBoolN(params, ['stop', 'conditional', 'trigger']);
6774
- params = this.omit(params, ['stop', 'conditional', 'trigger']);
6773
+ const isConditional = this.safeBoolN(params, ['stop', 'trigger', 'conditional']);
6774
+ params = this.omit(params, ['stop', 'trigger', 'conditional']);
6775
6775
  const isPortfolioMarginConditional = (isPortfolioMargin && isConditional);
6776
6776
  const orderIdRequest = isPortfolioMarginConditional ? 'strategyId' : 'orderId';
6777
6777
  request[orderIdRequest] = id;
@@ -7086,7 +7086,7 @@ class binance extends binance$1 {
7086
7086
  [marginMode, params] = this.handleMarginModeAndParams('cancelOrder', params);
7087
7087
  let isPortfolioMargin = undefined;
7088
7088
  [isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'cancelOrder', 'papi', 'portfolioMargin', false);
7089
- const isConditional = this.safeBool2(params, 'stop', 'conditional');
7089
+ const isConditional = this.safeBoolN(params, ['stop', 'trigger', 'conditional']);
7090
7090
  const request = {
7091
7091
  'symbol': market['id'],
7092
7092
  };
@@ -7112,7 +7112,7 @@ class binance extends binance$1 {
7112
7112
  request['orderId'] = id;
7113
7113
  }
7114
7114
  }
7115
- params = this.omit(params, ['type', 'origClientOrderId', 'clientOrderId', 'newClientStrategyId', 'stop', 'conditional']);
7115
+ params = this.omit(params, ['type', 'origClientOrderId', 'clientOrderId', 'newClientStrategyId', 'stop', 'trigger', 'conditional']);
7116
7116
  let response = undefined;
7117
7117
  if (market['option']) {
7118
7118
  response = await this.eapiPrivateDeleteOrder(this.extend(request, params));
@@ -7190,9 +7190,9 @@ class binance extends binance$1 {
7190
7190
  };
7191
7191
  let isPortfolioMargin = undefined;
7192
7192
  [isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'cancelAllOrders', 'papi', 'portfolioMargin', false);
7193
- const isConditional = this.safeBool2(params, 'stop', 'conditional');
7193
+ const isConditional = this.safeBoolN(params, ['stop', 'trigger', 'conditional']);
7194
7194
  const type = this.safeString(params, 'type', market['type']);
7195
- params = this.omit(params, ['type', 'stop', 'conditional']);
7195
+ params = this.omit(params, ['type', 'stop', 'trigger', 'conditional']);
7196
7196
  let marginMode = undefined;
7197
7197
  [marginMode, params] = this.handleMarginModeAndParams('cancelAllOrders', params);
7198
7198
  let response = undefined;
@@ -229,6 +229,7 @@ class bitmart extends bitmart$1 {
229
229
  'spot/v4/query/trades': 5,
230
230
  'spot/v4/query/order-trades': 5,
231
231
  'spot/v4/cancel_orders': 3,
232
+ 'spot/v4/cancel_all': 90,
232
233
  'spot/v4/batch_orders': 3,
233
234
  // newer endpoint
234
235
  'spot/v3/cancel_order': 1,
@@ -2964,6 +2965,7 @@ class bitmart extends bitmart$1 {
2964
2965
  * @name bitmart#cancelAllOrders
2965
2966
  * @description cancel all open orders in a market
2966
2967
  * @see https://developer-pro.bitmart.com/en/spot/#cancel-all-orders
2968
+ * @see https://developer-pro.bitmart.com/en/spot/#new-batch-order-v4-signed
2967
2969
  * @see https://developer-pro.bitmart.com/en/futures/#cancel-all-orders-signed
2968
2970
  * @see https://developer-pro.bitmart.com/en/futuresv2/#cancel-all-orders-signed
2969
2971
  * @param {string} symbol unified market symbol of the market to cancel orders in
@@ -2982,7 +2984,7 @@ class bitmart extends bitmart$1 {
2982
2984
  let type = undefined;
2983
2985
  [type, params] = this.handleMarketTypeAndParams('cancelAllOrders', market, params);
2984
2986
  if (type === 'spot') {
2985
- response = await this.privatePostSpotV1CancelOrders(this.extend(request, params));
2987
+ response = await this.privatePostSpotV4CancelAll(this.extend(request, params));
2986
2988
  }
2987
2989
  else if (type === 'swap') {
2988
2990
  if (symbol === undefined) {
@@ -389,46 +389,34 @@ class bitstamp extends bitstamp$1 {
389
389
  'trading': {
390
390
  'tierBased': true,
391
391
  'percentage': true,
392
- 'taker': this.parseNumber('0.005'),
393
- 'maker': this.parseNumber('0.005'),
392
+ 'taker': this.parseNumber('0.004'),
393
+ 'maker': this.parseNumber('0.004'),
394
394
  'tiers': {
395
395
  'taker': [
396
- [this.parseNumber('0'), this.parseNumber('0.005')],
397
- [this.parseNumber('20000'), this.parseNumber('0.0025')],
398
- [this.parseNumber('100000'), this.parseNumber('0.0024')],
399
- [this.parseNumber('200000'), this.parseNumber('0.0022')],
400
- [this.parseNumber('400000'), this.parseNumber('0.0020')],
401
- [this.parseNumber('600000'), this.parseNumber('0.0015')],
402
- [this.parseNumber('1000000'), this.parseNumber('0.0014')],
403
- [this.parseNumber('2000000'), this.parseNumber('0.0013')],
404
- [this.parseNumber('4000000'), this.parseNumber('0.0012')],
405
- [this.parseNumber('20000000'), this.parseNumber('0.0011')],
406
- [this.parseNumber('50000000'), this.parseNumber('0.0010')],
407
- [this.parseNumber('100000000'), this.parseNumber('0.0007')],
408
- [this.parseNumber('500000000'), this.parseNumber('0.0005')],
409
- [this.parseNumber('2000000000'), this.parseNumber('0.0003')],
410
- [this.parseNumber('6000000000'), this.parseNumber('0.0001')],
411
- [this.parseNumber('20000000000'), this.parseNumber('0.00005')],
412
- [this.parseNumber('20000000001'), this.parseNumber('0')],
396
+ [this.parseNumber('0'), this.parseNumber('0.004')],
397
+ [this.parseNumber('10000'), this.parseNumber('0.003')],
398
+ [this.parseNumber('100000'), this.parseNumber('0.002')],
399
+ [this.parseNumber('500000'), this.parseNumber('0.0018')],
400
+ [this.parseNumber('1500000'), this.parseNumber('0.0016')],
401
+ [this.parseNumber('5000000'), this.parseNumber('0.0012')],
402
+ [this.parseNumber('20000000'), this.parseNumber('0.001')],
403
+ [this.parseNumber('50000000'), this.parseNumber('0.0008')],
404
+ [this.parseNumber('100000000'), this.parseNumber('0.0006')],
405
+ [this.parseNumber('250000000'), this.parseNumber('0.0005')],
406
+ [this.parseNumber('1000000000'), this.parseNumber('0.0003')],
413
407
  ],
414
408
  'maker': [
415
- [this.parseNumber('0'), this.parseNumber('0.005')],
416
- [this.parseNumber('20000'), this.parseNumber('0.0025')],
417
- [this.parseNumber('100000'), this.parseNumber('0.0024')],
418
- [this.parseNumber('200000'), this.parseNumber('0.0022')],
419
- [this.parseNumber('400000'), this.parseNumber('0.0020')],
420
- [this.parseNumber('600000'), this.parseNumber('0.0015')],
421
- [this.parseNumber('1000000'), this.parseNumber('0.0014')],
422
- [this.parseNumber('2000000'), this.parseNumber('0.0013')],
423
- [this.parseNumber('4000000'), this.parseNumber('0.0012')],
424
- [this.parseNumber('20000000'), this.parseNumber('0.0011')],
425
- [this.parseNumber('50000000'), this.parseNumber('0.0010')],
426
- [this.parseNumber('100000000'), this.parseNumber('0.0007')],
427
- [this.parseNumber('500000000'), this.parseNumber('0.0005')],
428
- [this.parseNumber('2000000000'), this.parseNumber('0.0003')],
429
- [this.parseNumber('6000000000'), this.parseNumber('0.0001')],
430
- [this.parseNumber('20000000000'), this.parseNumber('0.00005')],
431
- [this.parseNumber('20000000001'), this.parseNumber('0')],
409
+ [this.parseNumber('0'), this.parseNumber('0.003')],
410
+ [this.parseNumber('10000'), this.parseNumber('0.002')],
411
+ [this.parseNumber('100000'), this.parseNumber('0.001')],
412
+ [this.parseNumber('500000'), this.parseNumber('0.0008')],
413
+ [this.parseNumber('1500000'), this.parseNumber('0.0006')],
414
+ [this.parseNumber('5000000'), this.parseNumber('0.0003')],
415
+ [this.parseNumber('20000000'), this.parseNumber('0.002')],
416
+ [this.parseNumber('50000000'), this.parseNumber('0.0001')],
417
+ [this.parseNumber('100000000'), this.parseNumber('0')],
418
+ [this.parseNumber('250000000'), this.parseNumber('0')],
419
+ [this.parseNumber('1000000000'), this.parseNumber('0')],
432
420
  ],
433
421
  },
434
422
  },
@@ -976,6 +976,7 @@ class bybit extends bybit$1 {
976
976
  '3200300': errors.InsufficientFunds, // {"retCode":3200300,"retMsg":"Insufficient margin balance.","result":null,"retExtMap":{}}
977
977
  },
978
978
  'broad': {
979
+ 'Not supported symbols': errors.BadSymbol,
979
980
  'Request timeout': errors.RequestTimeout,
980
981
  'unknown orderInfo': errors.OrderNotFound,
981
982
  'invalid api_key': errors.AuthenticationError,
@@ -602,7 +602,7 @@ class cryptocom extends cryptocom$1 {
602
602
  * @method
603
603
  * @name cryptocom#fetchTickers
604
604
  * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
605
- * @see https://exchange-docs.crypto.com/spot/index.html#public-get-ticker
605
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-tickers
606
606
  * @see https://exchange-docs.crypto.com/derivatives/index.html#public-get-tickers
607
607
  * @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
608
608
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -1796,6 +1796,7 @@ class cryptocom extends cryptocom$1 {
1796
1796
  * @method
1797
1797
  * @name cryptocom#fetchDepositAddress
1798
1798
  * @description fetch the deposit address for a currency associated with this account
1799
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-deposit-address
1799
1800
  * @param {string} code unified currency code
1800
1801
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1801
1802
  * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
@@ -5192,6 +5192,16 @@ class mexc extends mexc$1 {
5192
5192
  return this.parseTransaction(response, currency);
5193
5193
  }
5194
5194
  async setPositionMode(hedged, symbol = undefined, params = {}) {
5195
+ /**
5196
+ * @method
5197
+ * @name mexc#setPositionMode
5198
+ * @description set hedged to true or false for a market
5199
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#change-position-mode
5200
+ * @param {bool} hedged set to true to use dualSidePosition
5201
+ * @param {string} symbol not used by mexc setPositionMode ()
5202
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
5203
+ * @returns {object} response from the exchange
5204
+ */
5195
5205
  const request = {
5196
5206
  'positionMode': hedged ? 1 : 2, // 1 Hedge, 2 One-way, before changing position mode make sure that there are no active orders, planned orders, or open positions, the risk limit level will be reset to 1
5197
5207
  };
@@ -5205,6 +5215,15 @@ class mexc extends mexc$1 {
5205
5215
  return response;
5206
5216
  }
5207
5217
  async fetchPositionMode(symbol = undefined, params = {}) {
5218
+ /**
5219
+ * @method
5220
+ * @name mexc#fetchPositionMode
5221
+ * @description fetchs the position mode, hedged or one way, hedged for binance is set identically for all linear markets or all inverse markets
5222
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-position-mode
5223
+ * @param {string} symbol not used by mexc fetchPositionMode
5224
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
5225
+ * @returns {object} an object detailing whether the market is in hedged or one-way mode
5226
+ */
5208
5227
  const response = await this.contractPrivateGetPositionPositionMode(params);
5209
5228
  //
5210
5229
  // {
@@ -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,7 @@ class mexc extends mexc$1 {
27
27
  'watchOrderBook': true,
28
28
  'watchOrders': true,
29
29
  'watchTicker': true,
30
- 'watchTickers': false,
30
+ 'watchTickers': true,
31
31
  'watchTrades': true,
32
32
  'watchTradesForSymbols': false,
33
33
  },
@@ -125,6 +125,84 @@ class mexc extends mexc$1 {
125
125
  const messageHash = 'ticker:' + symbol;
126
126
  client.resolve(ticker, messageHash);
127
127
  }
128
+ async watchTickers(symbols = undefined, params = {}) {
129
+ /**
130
+ * @method
131
+ * @name mexc#watchTickers
132
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
133
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#individual-symbol-book-ticker-streams
134
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#public-channels
135
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
136
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
137
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
138
+ */
139
+ await this.loadMarkets();
140
+ symbols = this.marketSymbols(symbols, undefined, false);
141
+ const messageHashes = [];
142
+ const marketIds = this.marketIds(symbols);
143
+ const firstMarket = this.market(symbols[0]);
144
+ const isSpot = firstMarket['spot'];
145
+ const url = (isSpot) ? this.urls['api']['ws']['spot'] : this.urls['api']['ws']['swap'];
146
+ const request = {};
147
+ if (isSpot) {
148
+ const topics = [];
149
+ for (let i = 0; i < marketIds.length; i++) {
150
+ const marketId = marketIds[i];
151
+ messageHashes.push('ticker:' + symbols[i]);
152
+ topics.push('spot@public.bookTicker.v3.api@' + marketId);
153
+ }
154
+ request['method'] = 'SUBSCRIPTION';
155
+ request['params'] = topics;
156
+ }
157
+ else {
158
+ request['method'] = 'sub.tickers';
159
+ request['params'] = {};
160
+ messageHashes.push('ticker');
161
+ }
162
+ const ticker = await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes);
163
+ if (isSpot && this.newUpdates) {
164
+ const result = {};
165
+ result[ticker['symbol']] = ticker;
166
+ return result;
167
+ }
168
+ return this.filterByArray(this.tickers, 'symbol', symbols);
169
+ }
170
+ handleTickers(client, message) {
171
+ //
172
+ // {
173
+ // "channel": "push.tickers",
174
+ // "data": [
175
+ // {
176
+ // "symbol": "ETH_USDT",
177
+ // "lastPrice": 2324.5,
178
+ // "riseFallRate": 0.0356,
179
+ // "fairPrice": 2324.32,
180
+ // "indexPrice": 2325.44,
181
+ // "volume24": 25868309,
182
+ // "amount24": 591752573.9792,
183
+ // "maxBidPrice": 2557.98,
184
+ // "minAskPrice": 2092.89,
185
+ // "lower24Price": 2239.39,
186
+ // "high24Price": 2332.59,
187
+ // "timestamp": 1725872514111
188
+ // }
189
+ // ],
190
+ // "ts": 1725872514111
191
+ // }
192
+ //
193
+ const data = this.safeList(message, 'data');
194
+ const topic = 'ticker';
195
+ const result = [];
196
+ for (let i = 0; i < data.length; i++) {
197
+ const ticker = this.parseTicker(data[i]);
198
+ const symbol = ticker['symbol'];
199
+ this.tickers[symbol] = ticker;
200
+ result.push(ticker);
201
+ const messageHash = topic + ':' + symbol;
202
+ client.resolve(ticker, messageHash);
203
+ }
204
+ client.resolve(result, topic);
205
+ }
128
206
  parseWsTicker(ticker, market = undefined) {
129
207
  //
130
208
  // spot
@@ -1132,8 +1210,8 @@ class mexc extends mexc$1 {
1132
1210
  // "code": 0,
1133
1211
  // "msg": "spot@public.increase.depth.v3.api@BTCUSDT"
1134
1212
  // }
1135
- //
1136
- const msg = this.safeString(message, 'msg');
1213
+ // Set the default to an empty string if the message is empty during the test.
1214
+ const msg = this.safeString(message, 'msg', '');
1137
1215
  if (msg === 'PONG') {
1138
1216
  this.handlePong(client, message);
1139
1217
  }
@@ -1177,6 +1255,7 @@ class mexc extends mexc$1 {
1177
1255
  'push.kline': this.handleOHLCV,
1178
1256
  'public.bookTicker.v3.api': this.handleTicker,
1179
1257
  'push.ticker': this.handleTicker,
1258
+ 'push.tickers': this.handleTickers,
1180
1259
  'public.increase.depth.v3.api': this.handleOrderBook,
1181
1260
  'push.depth': this.handleOrderBook,
1182
1261
  '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,