ccxt 4.4.99__py2.py3-none-any.whl → 4.5.0__py2.py3-none-any.whl

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 (198) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/bingx.py +1 -0
  3. ccxt/alpaca.py +1 -1
  4. ccxt/apex.py +1 -1
  5. ccxt/ascendex.py +1 -1
  6. ccxt/async_support/__init__.py +1 -1
  7. ccxt/async_support/alpaca.py +1 -1
  8. ccxt/async_support/apex.py +1 -1
  9. ccxt/async_support/ascendex.py +1 -1
  10. ccxt/async_support/base/exchange.py +44 -9
  11. ccxt/async_support/base/ws/client.py +3 -1
  12. ccxt/async_support/bigone.py +1 -1
  13. ccxt/async_support/binance.py +3 -2
  14. ccxt/async_support/bingx.py +33 -4
  15. ccxt/async_support/bitbank.py +1 -1
  16. ccxt/async_support/bitfinex.py +4 -1
  17. ccxt/async_support/bitflyer.py +1 -1
  18. ccxt/async_support/bitget.py +32 -14
  19. ccxt/async_support/bithumb.py +1 -1
  20. ccxt/async_support/bitmart.py +2 -2
  21. ccxt/async_support/bitmex.py +3 -2
  22. ccxt/async_support/bitopro.py +1 -1
  23. ccxt/async_support/bitrue.py +2 -2
  24. ccxt/async_support/bitso.py +1 -1
  25. ccxt/async_support/bitstamp.py +1 -1
  26. ccxt/async_support/bittrade.py +1 -1
  27. ccxt/async_support/bitvavo.py +1 -1
  28. ccxt/async_support/blockchaincom.py +1 -1
  29. ccxt/async_support/blofin.py +1 -1
  30. ccxt/async_support/btcmarkets.py +1 -1
  31. ccxt/async_support/bybit.py +2 -2
  32. ccxt/async_support/coinbase.py +1 -1
  33. ccxt/async_support/coinbaseexchange.py +1 -1
  34. ccxt/async_support/coinbaseinternational.py +1 -1
  35. ccxt/async_support/coincatch.py +2 -2
  36. ccxt/async_support/coinex.py +3 -3
  37. ccxt/async_support/coinmate.py +1 -1
  38. ccxt/async_support/coinsph.py +1 -1
  39. ccxt/async_support/cryptocom.py +1 -1
  40. ccxt/async_support/defx.py +2 -2
  41. ccxt/async_support/delta.py +1 -1
  42. ccxt/async_support/deribit.py +1 -1
  43. ccxt/async_support/digifinex.py +2 -2
  44. ccxt/async_support/ellipx.py +1 -1
  45. ccxt/async_support/exmo.py +1 -1
  46. ccxt/async_support/foxbit.py +3 -3
  47. ccxt/async_support/gate.py +17 -2
  48. ccxt/async_support/gemini.py +1 -1
  49. ccxt/async_support/hashkey.py +2 -2
  50. ccxt/async_support/hibachi.py +1 -1
  51. ccxt/async_support/hitbtc.py +2 -2
  52. ccxt/async_support/hollaex.py +1 -1
  53. ccxt/async_support/htx.py +4 -3
  54. ccxt/async_support/hyperliquid.py +71 -29
  55. ccxt/async_support/independentreserve.py +1 -1
  56. ccxt/async_support/indodax.py +1 -1
  57. ccxt/async_support/kraken.py +1 -1
  58. ccxt/async_support/krakenfutures.py +2 -1
  59. ccxt/async_support/kucoin.py +2 -2
  60. ccxt/async_support/kucoinfutures.py +2 -1
  61. ccxt/async_support/lbank.py +2 -2
  62. ccxt/async_support/mercado.py +1 -1
  63. ccxt/async_support/mexc.py +9 -2
  64. ccxt/async_support/modetrade.py +93 -2
  65. ccxt/async_support/ndax.py +1 -1
  66. ccxt/async_support/novadax.py +1 -1
  67. ccxt/async_support/okcoin.py +1 -1
  68. ccxt/async_support/okx.py +2 -2
  69. ccxt/async_support/onetrading.py +33 -0
  70. ccxt/async_support/oxfun.py +1 -1
  71. ccxt/async_support/p2b.py +32 -0
  72. ccxt/async_support/paradex.py +2 -1
  73. ccxt/async_support/phemex.py +2 -2
  74. ccxt/async_support/poloniex.py +2 -2
  75. ccxt/async_support/probit.py +36 -1
  76. ccxt/async_support/tokocrypto.py +1 -1
  77. ccxt/async_support/upbit.py +1 -1
  78. ccxt/async_support/vertex.py +1 -1
  79. ccxt/async_support/wavesexchange.py +1 -1
  80. ccxt/async_support/whitebit.py +2 -2
  81. ccxt/async_support/woo.py +4 -4
  82. ccxt/async_support/woofipro.py +93 -2
  83. ccxt/async_support/xt.py +2 -2
  84. ccxt/async_support/yobit.py +1 -1
  85. ccxt/async_support/zaif.py +1 -1
  86. ccxt/async_support/zonda.py +1 -1
  87. ccxt/base/errors.py +6 -0
  88. ccxt/base/exchange.py +11 -9
  89. ccxt/base/types.py +1 -0
  90. ccxt/bigone.py +1 -1
  91. ccxt/binance.py +3 -2
  92. ccxt/bingx.py +33 -4
  93. ccxt/bitbank.py +1 -1
  94. ccxt/bitfinex.py +4 -1
  95. ccxt/bitflyer.py +1 -1
  96. ccxt/bitget.py +32 -14
  97. ccxt/bithumb.py +1 -1
  98. ccxt/bitmart.py +2 -2
  99. ccxt/bitmex.py +3 -2
  100. ccxt/bitopro.py +1 -1
  101. ccxt/bitrue.py +2 -2
  102. ccxt/bitso.py +1 -1
  103. ccxt/bitstamp.py +1 -1
  104. ccxt/bittrade.py +1 -1
  105. ccxt/bitvavo.py +1 -1
  106. ccxt/blockchaincom.py +1 -1
  107. ccxt/blofin.py +1 -1
  108. ccxt/btcmarkets.py +1 -1
  109. ccxt/bybit.py +2 -2
  110. ccxt/coinbase.py +1 -1
  111. ccxt/coinbaseexchange.py +1 -1
  112. ccxt/coinbaseinternational.py +1 -1
  113. ccxt/coincatch.py +2 -2
  114. ccxt/coinex.py +3 -3
  115. ccxt/coinmate.py +1 -1
  116. ccxt/coinsph.py +1 -1
  117. ccxt/cryptocom.py +1 -1
  118. ccxt/defx.py +2 -2
  119. ccxt/delta.py +1 -1
  120. ccxt/deribit.py +1 -1
  121. ccxt/digifinex.py +2 -2
  122. ccxt/ellipx.py +1 -1
  123. ccxt/exmo.py +1 -1
  124. ccxt/foxbit.py +3 -3
  125. ccxt/gate.py +17 -2
  126. ccxt/gemini.py +1 -1
  127. ccxt/hashkey.py +2 -2
  128. ccxt/hibachi.py +1 -1
  129. ccxt/hitbtc.py +2 -2
  130. ccxt/hollaex.py +1 -1
  131. ccxt/htx.py +4 -3
  132. ccxt/hyperliquid.py +71 -29
  133. ccxt/independentreserve.py +1 -1
  134. ccxt/indodax.py +1 -1
  135. ccxt/kraken.py +1 -1
  136. ccxt/krakenfutures.py +2 -1
  137. ccxt/kucoin.py +2 -2
  138. ccxt/kucoinfutures.py +2 -1
  139. ccxt/lbank.py +2 -2
  140. ccxt/mercado.py +1 -1
  141. ccxt/mexc.py +9 -2
  142. ccxt/modetrade.py +93 -2
  143. ccxt/ndax.py +1 -1
  144. ccxt/novadax.py +1 -1
  145. ccxt/okcoin.py +1 -1
  146. ccxt/okx.py +2 -2
  147. ccxt/onetrading.py +33 -0
  148. ccxt/oxfun.py +1 -1
  149. ccxt/p2b.py +32 -0
  150. ccxt/paradex.py +2 -1
  151. ccxt/phemex.py +2 -2
  152. ccxt/poloniex.py +2 -2
  153. ccxt/pro/__init__.py +1 -1
  154. ccxt/pro/binance.py +2 -1
  155. ccxt/pro/bitvavo.py +1 -1
  156. ccxt/pro/bybit.py +1 -0
  157. ccxt/pro/coinex.py +1 -1
  158. ccxt/pro/hyperliquid.py +99 -12
  159. ccxt/pro/kucoin.py +1 -1
  160. ccxt/pro/kucoinfutures.py +1 -1
  161. ccxt/pro/mexc.py +337 -149
  162. ccxt/pro/okx.py +2 -1
  163. ccxt/pro/oxfun.py +1 -1
  164. ccxt/probit.py +36 -1
  165. ccxt/protobuf/__init__.py +0 -0
  166. ccxt/protobuf/mexc/PrivateAccountV3Api_pb2.py +37 -0
  167. ccxt/protobuf/mexc/PrivateDealsV3Api_pb2.py +37 -0
  168. ccxt/protobuf/mexc/PrivateOrdersV3Api_pb2.py +37 -0
  169. ccxt/protobuf/mexc/PublicAggreBookTickerV3Api_pb2.py +37 -0
  170. ccxt/protobuf/mexc/PublicAggreDealsV3Api_pb2.py +39 -0
  171. ccxt/protobuf/mexc/PublicAggreDepthsV3Api_pb2.py +39 -0
  172. ccxt/protobuf/mexc/PublicBookTickerBatchV3Api_pb2.py +38 -0
  173. ccxt/protobuf/mexc/PublicBookTickerV3Api_pb2.py +37 -0
  174. ccxt/protobuf/mexc/PublicDealsV3Api_pb2.py +39 -0
  175. ccxt/protobuf/mexc/PublicIncreaseDepthsBatchV3Api_pb2.py +38 -0
  176. ccxt/protobuf/mexc/PublicIncreaseDepthsV3Api_pb2.py +39 -0
  177. ccxt/protobuf/mexc/PublicLimitDepthsV3Api_pb2.py +39 -0
  178. ccxt/protobuf/mexc/PublicMiniTickerV3Api_pb2.py +37 -0
  179. ccxt/protobuf/mexc/PublicMiniTickersV3Api_pb2.py +38 -0
  180. ccxt/protobuf/mexc/PublicSpotKlineV3Api_pb2.py +37 -0
  181. ccxt/protobuf/mexc/PushDataV3ApiWrapper_pb2.py +52 -0
  182. ccxt/protobuf/mexc/__init__.py +0 -0
  183. ccxt/tokocrypto.py +1 -1
  184. ccxt/upbit.py +1 -1
  185. ccxt/vertex.py +1 -1
  186. ccxt/wavesexchange.py +1 -1
  187. ccxt/whitebit.py +2 -2
  188. ccxt/woo.py +4 -4
  189. ccxt/woofipro.py +93 -2
  190. ccxt/xt.py +2 -2
  191. ccxt/yobit.py +1 -1
  192. ccxt/zaif.py +1 -1
  193. ccxt/zonda.py +1 -1
  194. {ccxt-4.4.99.dist-info → ccxt-4.5.0.dist-info}/METADATA +5 -5
  195. {ccxt-4.4.99.dist-info → ccxt-4.5.0.dist-info}/RECORD +198 -180
  196. {ccxt-4.4.99.dist-info → ccxt-4.5.0.dist-info}/LICENSE.txt +0 -0
  197. {ccxt-4.4.99.dist-info → ccxt-4.5.0.dist-info}/WHEEL +0 -0
  198. {ccxt-4.4.99.dist-info → ccxt-4.5.0.dist-info}/top_level.txt +0 -0
ccxt/pro/mexc.py CHANGED
@@ -49,13 +49,14 @@ class mexc(ccxt.async_support.mexc):
49
49
  'urls': {
50
50
  'api': {
51
51
  'ws': {
52
- 'spot': 'wss://wbs.mexc.com/ws',
52
+ 'spot': 'wss://wbs-api.mexc.com/ws',
53
53
  'swap': 'wss://contract.mexc.com/edge',
54
54
  },
55
55
  },
56
56
  },
57
57
  'options': {
58
58
  'listenKeyRefreshRate': 1200000,
59
+ 'decompressBinary': False,
59
60
  # TODO add reset connection after #16754 is merged
60
61
  'timeframes': {
61
62
  '1m': 'Min1',
@@ -100,13 +101,7 @@ class mexc(ccxt.async_support.mexc):
100
101
  market = self.market(symbol)
101
102
  messageHash = 'ticker:' + market['symbol']
102
103
  if market['spot']:
103
- miniTicker = False
104
- miniTicker, params = self.handle_option_and_params(params, 'watchTicker', 'miniTicker')
105
- channel = None
106
- if miniTicker:
107
- channel = 'spot@public.miniTicker.v3.api@' + market['id'] + '@UTC+8'
108
- else:
109
- channel = 'spot@public.bookTicker.v3.api@' + market['id']
104
+ channel = 'spot@public.aggre.bookTicker.v3.api.pb@100ms@' + market['id']
110
105
  return await self.watch_spot_public(channel, messageHash, params)
111
106
  else:
112
107
  channel = 'sub.ticker'
@@ -184,9 +179,9 @@ class mexc(ccxt.async_support.mexc):
184
179
  # }
185
180
  #
186
181
  self.handle_bid_ask(client, message)
187
- rawTicker = self.safe_dict_2(message, 'd', 'data')
182
+ rawTicker = self.safe_dict_n(message, ['d', 'data', 'publicAggreBookTicker'])
188
183
  marketId = self.safe_string_2(message, 's', 'symbol')
189
- timestamp = self.safe_integer(message, 't')
184
+ timestamp = self.safe_integer_2(message, 't', 'sendtime')
190
185
  market = self.safe_market(marketId)
191
186
  symbol = market['symbol']
192
187
  ticker = None
@@ -226,27 +221,33 @@ class mexc(ccxt.async_support.mexc):
226
221
  url = self.urls['api']['ws']['spot'] if (isSpot) else self.urls['api']['ws']['swap']
227
222
  request: dict = {}
228
223
  if isSpot:
229
- miniTicker = False
230
- miniTicker, params = self.handle_option_and_params(params, 'watchTickers', 'miniTicker')
231
- topics = []
232
- if not miniTicker:
233
- if symbols is None:
234
- raise ArgumentsRequired(self.id + ' watchTickers required symbols argument for the bookTicker channel')
235
- marketIds = self.market_ids(symbols)
236
- for i in range(0, len(marketIds)):
237
- marketId = marketIds[i]
238
- messageHashes.append('ticker:' + symbols[i])
239
- channel = 'spot@public.bookTicker.v3.api@' + marketId
240
- topics.append(channel)
241
- else:
242
- topics.append('spot@public.miniTickers.v3.api@UTC+8')
243
- if symbols is None:
244
- messageHashes.append('spot:ticker')
245
- else:
246
- for i in range(0, len(symbols)):
247
- messageHashes.append('ticker:' + symbols[i])
248
- request['method'] = 'SUBSCRIPTION'
249
- request['params'] = topics
224
+ raise NotSupported(self.id + ' watchTickers does not support spot markets')
225
+ # miniTicker = False
226
+ # miniTicker, params = self.handle_option_and_params(params, 'watchTickers', 'miniTicker')
227
+ # topics = []
228
+ # if not miniTicker:
229
+ # if symbols is None:
230
+ # raise ArgumentsRequired(self.id + ' watchTickers required symbols argument for the bookTicker channel')
231
+ # }
232
+ # marketIds = self.market_ids(symbols)
233
+ # for i in range(0, len(marketIds)):
234
+ # marketId = marketIds[i]
235
+ # messageHashes.append('ticker:' + symbols[i])
236
+ # channel = 'spot@public.bookTicker.v3.api@' + marketId
237
+ # topics.append(channel)
238
+ # }
239
+ # else:
240
+ # topics.append('spot@public.miniTickers.v3.api@UTC+8')
241
+ # if symbols is None:
242
+ # messageHashes.append('spot:ticker')
243
+ # else:
244
+ # for i in range(0, len(symbols)):
245
+ # messageHashes.append('ticker:' + symbols[i])
246
+ # }
247
+ # }
248
+ # }
249
+ # request['method'] = 'SUBSCRIPTION'
250
+ # request['params'] = topics
250
251
  else:
251
252
  request['method'] = 'sub.tickers'
252
253
  request['params'] = {}
@@ -345,6 +346,11 @@ class mexc(ccxt.async_support.mexc):
345
346
  client.resolve(result, topic)
346
347
 
347
348
  def parse_ws_ticker(self, ticker, market=None):
349
+ # protobuf ticker
350
+ # "bidprice": "93387.28", # Best bid price
351
+ # "bidquantity": "3.73485", # Best bid quantity
352
+ # "askprice": "93387.29", # Best ask price
353
+ # "askquantity": "7.669875" # Best ask quantity
348
354
  #
349
355
  # spot
350
356
  #
@@ -359,7 +365,7 @@ class mexc(ccxt.async_support.mexc):
359
365
  #
360
366
  # {
361
367
  # "s": "BTCUSDT",
362
- # "p": "76522",
368
+ # "p": "76521",
363
369
  # "r": "0.0012",
364
370
  # "tr": "0.0012",
365
371
  # "h": "77196.3",
@@ -385,10 +391,10 @@ class mexc(ccxt.async_support.mexc):
385
391
  'low': self.safe_number(ticker, 'l'),
386
392
  'close': price,
387
393
  'last': price,
388
- 'bid': self.safe_number(ticker, 'b'),
389
- 'bidVolume': self.safe_number(ticker, 'B'),
390
- 'ask': self.safe_number(ticker, 'a'),
391
- 'askVolume': self.safe_number(ticker, 'A'),
394
+ 'bid': self.safe_number_2(ticker, 'b', 'bidPrice'),
395
+ 'bidVolume': self.safe_number_2(ticker, 'B', 'bidQuantity'),
396
+ 'ask': self.safe_number_2(ticker, 'a', 'askPrice'),
397
+ 'askVolume': self.safe_number_2(ticker, 'A', 'askQuantity'),
392
398
  'vwap': None,
393
399
  'previousClose': None,
394
400
  'change': None,
@@ -423,7 +429,7 @@ class mexc(ccxt.async_support.mexc):
423
429
  for i in range(0, len(symbols)):
424
430
  if isSpot:
425
431
  market = self.market(symbols[i])
426
- topics.append('spot@public.bookTicker.v3.api@' + market['id'])
432
+ topics.append('spot@public.aggre.bookTicker.v3.api.pb@100ms@' + market['id'])
427
433
  messageHashes.append('bidask:' + symbols[i])
428
434
  url = self.urls['api']['ws']['spot']
429
435
  request: dict = {
@@ -527,7 +533,7 @@ class mexc(ccxt.async_support.mexc):
527
533
  async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
528
534
  """
529
535
 
530
- https://mexcdevelop.github.io/apidocs/spot_v3_en/#kline-streams
536
+ https://www.mexc.com/api-docs/spot-v3/websocket-market-streams#trade-streams
531
537
 
532
538
  watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
533
539
  :param str symbol: unified symbol of the market to fetch OHLCV data for
@@ -545,7 +551,7 @@ class mexc(ccxt.async_support.mexc):
545
551
  messageHash = 'candles:' + symbol + ':' + timeframe
546
552
  ohlcv = None
547
553
  if market['spot']:
548
- channel = 'spot@public.kline.v3.api@' + market['id'] + '@' + timeframeId
554
+ channel = 'spot@public.kline.v3.api.pb@' + market['id'] + '@' + timeframeId
549
555
  ohlcv = await self.watch_spot_public(channel, messageHash, params)
550
556
  else:
551
557
  channel = 'sub.kline'
@@ -604,17 +610,45 @@ class mexc(ccxt.async_support.mexc):
604
610
  # "symbol": "BTC_USDT",
605
611
  # "ts": 1651230713067
606
612
  # }
613
+ # protobuf
614
+ # {
615
+ # "channel":"spot@public.kline.v3.api.pb@BTCUSDT@Min1",
616
+ # "symbol":"BTCUSDT",
617
+ # "symbolId":"2fb942154ef44a4ab2ef98c8afb6a4a7",
618
+ # "createTime":"1754737941062",
619
+ # "publicSpotKline":{
620
+ # "interval":"Min1",
621
+ # "windowStart":"1754737920",
622
+ # "openingPrice":"117317.31",
623
+ # "closingPrice":"117325.26",
624
+ # "highestPrice":"117341",
625
+ # "lowestPrice":"117317.3",
626
+ # "volume":"3.12599854",
627
+ # "amount":"366804.43",
628
+ # "windowEnd":"1754737980"
629
+ # }
630
+ # }
607
631
  #
608
- d = self.safe_value_2(message, 'd', 'data', {})
609
- rawOhlcv = self.safe_value(d, 'k', d)
610
- timeframeId = self.safe_string_2(rawOhlcv, 'i', 'interval')
611
- timeframes = self.safe_value(self.options, 'timeframes', {})
612
- timeframe = self.find_timeframe(timeframeId, timeframes)
613
- marketId = self.safe_string_2(message, 's', 'symbol')
614
- market = self.safe_market(marketId)
615
- symbol = market['symbol']
632
+ parsed: dict = None
633
+ symbol: Str = None
634
+ timeframe: Str = None
635
+ if 'publicSpotKline' in message:
636
+ symbol = self.symbol(self.safe_string(message, 'symbol'))
637
+ data = self.safe_dict(message, 'publicSpotKline', {})
638
+ timeframeId = self.safe_string(data, 'interval')
639
+ timeframe = self.find_timeframe(timeframeId, self.options['timeframes'])
640
+ parsed = self.parse_ws_ohlcv(data, self.safe_market(symbol))
641
+ else:
642
+ d = self.safe_value_2(message, 'd', 'data', {})
643
+ rawOhlcv = self.safe_value(d, 'k', d)
644
+ timeframeId = self.safe_string_2(rawOhlcv, 'i', 'interval')
645
+ timeframes = self.safe_value(self.options, 'timeframes', {})
646
+ timeframe = self.find_timeframe(timeframeId, timeframes)
647
+ marketId = self.safe_string_2(message, 's', 'symbol')
648
+ market = self.safe_market(marketId)
649
+ symbol = market['symbol']
650
+ parsed = self.parse_ws_ohlcv(rawOhlcv, market)
616
651
  messageHash = 'candles:' + symbol + ':' + timeframe
617
- parsed = self.parse_ws_ohlcv(rawOhlcv, market)
618
652
  self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
619
653
  stored = self.safe_value(self.ohlcvs[symbol], timeframe)
620
654
  if stored is None:
@@ -656,26 +690,38 @@ class mexc(ccxt.async_support.mexc):
656
690
  # "rh": 27301.8,
657
691
  # "rl": 27301.8
658
692
  # }
693
+ # protobuf
694
+ #
695
+ # "interval":"Min1",
696
+ # "windowStart":"1754737920",
697
+ # "openingPrice":"117317.31",
698
+ # "closingPrice":"117325.26",
699
+ # "highestPrice":"117341",
700
+ # "lowestPrice":"117317.3",
701
+ # "volume":"3.12599854",
702
+ # "amount":"366804.43",
703
+ # "windowEnd":"1754737980"
659
704
  #
660
705
  return [
661
- self.safe_timestamp(ohlcv, 't'),
662
- self.safe_number(ohlcv, 'o'),
663
- self.safe_number(ohlcv, 'h'),
664
- self.safe_number(ohlcv, 'l'),
665
- self.safe_number(ohlcv, 'c'),
666
- self.safe_number_2(ohlcv, 'v', 'q'),
706
+ self.safe_timestamp_2(ohlcv, 't', 'windowStart'),
707
+ self.safe_number_2(ohlcv, 'o', 'openingPrice'),
708
+ self.safe_number_2(ohlcv, 'h', 'highestPrice'),
709
+ self.safe_number_2(ohlcv, 'l', 'lowestPrice'),
710
+ self.safe_number_2(ohlcv, 'c', 'closingPrice'),
711
+ self.safe_number_2(ohlcv, 'v', 'volume'),
667
712
  ]
668
713
 
669
714
  async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
670
715
  """
671
716
 
672
- https://mexcdevelop.github.io/apidocs/spot_v3_en/#diff-depth-stream
717
+ https://www.mexc.com/api-docs/spot-v3/websocket-market-streams#trade-streams
673
718
  https://mexcdevelop.github.io/apidocs/contract_v1_en/#public-channels
674
719
 
675
720
  watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
676
721
  :param str symbol: unified symbol of the market to fetch the order book for
677
722
  :param int [limit]: the maximum amount of order book entries to return
678
723
  :param dict [params]: extra parameters specific to the exchange API endpoint
724
+ :param str [params.frequency]: the frequency of the order book updates, default is '10ms', can be '100ms' or '10ms
679
725
  :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
680
726
  """
681
727
  await self.load_markets()
@@ -684,7 +730,9 @@ class mexc(ccxt.async_support.mexc):
684
730
  messageHash = 'orderbook:' + symbol
685
731
  orderbook = None
686
732
  if market['spot']:
687
- channel = 'spot@public.increase.depth.v3.api@' + market['id']
733
+ frequency = None
734
+ frequency, params = self.handle_option_and_params(params, 'watchOrderBook', 'frequency', '100ms')
735
+ channel = 'spot@public.aggre.depth.v3.api.pb@' + frequency + '@' + market['id']
688
736
  orderbook = await self.watch_spot_public(channel, messageHash, params)
689
737
  else:
690
738
  channel = 'sub.depth'
@@ -708,12 +756,12 @@ class mexc(ccxt.async_support.mexc):
708
756
  # return the first index of the cache that can be applied to the orderbook or -1 if not possible
709
757
  nonce = self.safe_integer(orderbook, 'nonce')
710
758
  firstDelta = self.safe_value(cache, 0)
711
- firstDeltaNonce = self.safe_integer_2(firstDelta, 'r', 'version')
759
+ firstDeltaNonce = self.safe_integer_n(firstDelta, ['r', 'version', 'fromVersion'])
712
760
  if nonce < firstDeltaNonce - 1:
713
761
  return -1
714
762
  for i in range(0, len(cache)):
715
763
  delta = cache[i]
716
- deltaNonce = self.safe_integer_2(delta, 'r', 'version')
764
+ deltaNonce = self.safe_integer_n(delta, ['r', 'version', 'fromVersion'])
717
765
  if deltaNonce >= nonce:
718
766
  return i
719
767
  return len(cache)
@@ -761,8 +809,31 @@ class mexc(ccxt.async_support.mexc):
761
809
  # "symbol":"BTC_USDT",
762
810
  # "ts":1651239652372
763
811
  # }
812
+ # protofbuf
813
+ # {
814
+ # "channel":"spot@public.aggre.depth.v3.api.pb@100ms@BTCUSDT",
815
+ # "symbol":"BTCUSDT",
816
+ # "sendTime":"1754741322152",
817
+ # "publicAggreDepths":{
818
+ # "asks":[
819
+ # {
820
+ # "price":"117145.49",
821
+ # "quantity":"0"
822
+ # }
823
+ # ],
824
+ # "bids":[
825
+ # {
826
+ # "price":"117053.41",
827
+ # "quantity":"1.86837271"
828
+ # }
829
+ # ],
830
+ # "eventType":"spot@public.aggre.depth.v3.api.pb@100ms",
831
+ # "fromVersion":"43296363236",
832
+ # "toVersion":"43296363255"
833
+ # }
834
+ # }
764
835
  #
765
- data = self.safe_value_2(message, 'd', 'data')
836
+ data = self.safe_dict_n(message, ['d', 'data', 'publicAggreDepths'])
766
837
  marketId = self.safe_string_2(message, 's', 'symbol')
767
838
  symbol = self.safe_symbol(marketId)
768
839
  messageHash = 'orderbook:' + symbol
@@ -781,7 +852,7 @@ class mexc(ccxt.async_support.mexc):
781
852
  return
782
853
  try:
783
854
  self.handle_delta(storedOrderBook, data)
784
- timestamp = self.safe_integer_2(message, 't', 'ts')
855
+ timestamp = self.safe_integer_n(message, ['t', 'ts', 'sendTime'])
785
856
  storedOrderBook['timestamp'] = timestamp
786
857
  storedOrderBook['datetime'] = self.iso8601(timestamp)
787
858
  except Exception as e:
@@ -801,13 +872,13 @@ class mexc(ccxt.async_support.mexc):
801
872
  if isinstance(bidask, list):
802
873
  bookside.storeArray(bidask)
803
874
  else:
804
- price = self.safe_float(bidask, 'p')
805
- amount = self.safe_float(bidask, 'v')
875
+ price = self.safe_float_2(bidask, 'p', 'price')
876
+ amount = self.safe_float_2(bidask, 'v', 'quantity')
806
877
  bookside.store(price, amount)
807
878
 
808
879
  def handle_delta(self, orderbook, delta):
809
880
  existingNonce = self.safe_integer(orderbook, 'nonce')
810
- deltaNonce = self.safe_integer_2(delta, 'r', 'version')
881
+ deltaNonce = self.safe_integer_n(delta, ['r', 'version', 'fromVersion'])
811
882
  if deltaNonce < existingNonce:
812
883
  # even when doing < comparison, self happens: https://app.travis-ci.com/github/ccxt/ccxt/builds/269234741#L1809
813
884
  # so, we just skip old updates
@@ -823,7 +894,7 @@ class mexc(ccxt.async_support.mexc):
823
894
  async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
824
895
  """
825
896
 
826
- https://mexcdevelop.github.io/apidocs/spot_v3_en/#trade-streams
897
+ https://www.mexc.com/api-docs/spot-v3/websocket-market-streams#trade-streams
827
898
  https://mexcdevelop.github.io/apidocs/contract_v1_en/#public-channels
828
899
 
829
900
  get the list of most recent trades for a particular symbol
@@ -839,7 +910,7 @@ class mexc(ccxt.async_support.mexc):
839
910
  messageHash = 'trades:' + symbol
840
911
  trades = None
841
912
  if market['spot']:
842
- channel = 'spot@public.deals.v3.api@' + market['id']
913
+ channel = 'spot@public.aggre.deals.v3.api.pb@100ms@' + market['id']
843
914
  trades = await self.watch_spot_public(channel, messageHash, params)
844
915
  else:
845
916
  channel = 'sub.deal'
@@ -852,6 +923,23 @@ class mexc(ccxt.async_support.mexc):
852
923
  return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
853
924
 
854
925
  def handle_trades(self, client: Client, message):
926
+ # protobuf
927
+ # {
928
+ # "channel": "spot@public.aggre.deals.v3.api.pb@100ms@BTCUSDT",
929
+ # "publicdeals": {
930
+ # "dealsList": [
931
+ # {
932
+ # "price": "93220.00", # Trade price
933
+ # "quantity": "0.04438243", # Trade quantity
934
+ # "tradetype": 2, # Trade type(1: Buy, 2: Sell)
935
+ # "time": 1736409765051 # Trade time
936
+ # }
937
+ # ],
938
+ # "eventtype": "spot@public.aggre.deals.v3.api.pb@100ms" # Event type
939
+ # },
940
+ # "symbol": "BTCUSDT", # Trading pair
941
+ # "sendtime": 1736409765052 # Event time
942
+ # }
855
943
  #
856
944
  # {
857
945
  # "c": "spot@public.deals.v3.api@BTCUSDT",
@@ -892,8 +980,8 @@ class mexc(ccxt.async_support.mexc):
892
980
  limit = self.safe_integer(self.options, 'tradesLimit', 1000)
893
981
  stored = ArrayCache(limit)
894
982
  self.trades[symbol] = stored
895
- d = self.safe_value_2(message, 'd', 'data')
896
- trades = self.safe_value(d, 'deals', [d])
983
+ d = self.safe_dict_n(message, ['d', 'data', 'publicAggreDeals'])
984
+ trades = self.safe_list_2(d, 'deals', 'dealsList', [d])
897
985
  for j in range(0, len(trades)):
898
986
  parsedTrade = None
899
987
  if market['spot']:
@@ -906,7 +994,7 @@ class mexc(ccxt.async_support.mexc):
906
994
  async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
907
995
  """
908
996
 
909
- https://mexcdevelop.github.io/apidocs/spot_v3_en/#spot-account-deals
997
+ https://www.mexc.com/api-docs/spot-v3/websocket-user-data-streams#spot-account-deals
910
998
  https://mexcdevelop.github.io/apidocs/contract_v1_en/#private-channels
911
999
 
912
1000
  watches information on multiple trades made by the user
@@ -927,7 +1015,7 @@ class mexc(ccxt.async_support.mexc):
927
1015
  type, params = self.handle_market_type_and_params('watchMyTrades', market, params)
928
1016
  trades = None
929
1017
  if type == 'spot':
930
- channel = 'spot@private.deals.v3.api'
1018
+ channel = 'spot@private.deals.v3.api.pb'
931
1019
  trades = await self.watch_spot_private(channel, messageHash, params)
932
1020
  else:
933
1021
  trades = await self.watch_swap_private(messageHash, params)
@@ -953,11 +1041,27 @@ class mexc(ccxt.async_support.mexc):
953
1041
  # "s": "BTCUSDT",
954
1042
  # "t": 1678670940700
955
1043
  # }
1044
+ # {
1045
+ # channel: "spot@private.deals.v3.api.pb",
1046
+ # symbol: "MXUSDT",
1047
+ # sendTime: 1736417034332,
1048
+ # privateDeals {
1049
+ # price: "3.6962",
1050
+ # quantity: "1",
1051
+ # amount: "3.6962",
1052
+ # tradeType: 2,
1053
+ # tradeId: "505979017439002624X1",
1054
+ # orderId: "C02__505979017439002624115",
1055
+ # feeAmount: "0.0003998377369698171",
1056
+ # feeCurrency: "MX",
1057
+ # time: 1736417034280
1058
+ # }
1059
+ # }
956
1060
  #
957
1061
  messageHash = 'myTrades'
958
- data = self.safe_value_2(message, 'd', 'data')
1062
+ data = self.safe_dict_n(message, ['d', 'data', 'privateDeals'])
959
1063
  futuresMarketId = self.safe_string(data, 'symbol')
960
- marketId = self.safe_string(message, 's', futuresMarketId)
1064
+ marketId = self.safe_string_2(message, 's', 'symbol', futuresMarketId)
961
1065
  market = self.safe_market(marketId)
962
1066
  symbol = market['symbol']
963
1067
  trade = None
@@ -977,7 +1081,7 @@ class mexc(ccxt.async_support.mexc):
977
1081
 
978
1082
  def parse_ws_trade(self, trade, market=None):
979
1083
  #
980
- # public trade
1084
+ # public trade(protobuf)
981
1085
  # {
982
1086
  # "p": "20382.70",
983
1087
  # "v": "0.043800",
@@ -997,7 +1101,6 @@ class mexc(ccxt.async_support.mexc):
997
1101
  # "v": "5"
998
1102
  # }
999
1103
  #
1000
- #
1001
1104
  # d: {
1002
1105
  # p: '1.0005',
1003
1106
  # v: '5.71',
@@ -1012,22 +1115,36 @@ class mexc(ccxt.async_support.mexc):
1012
1115
  # n: '0.005712855',
1013
1116
  # N: 'USDT'
1014
1117
  # }
1015
- timestamp = self.safe_integer(trade, 'T')
1016
- tradeId = self.safe_string(trade, 't')
1118
+ # protobuf
1119
+ #
1120
+ # {
1121
+ # price: "3.6962",
1122
+ # quantity: "1",
1123
+ # amount: "3.6962",
1124
+ # tradeType: 2,
1125
+ # tradeId: "505979017439002624X1",
1126
+ # orderId: "C02__505979017439002624115",
1127
+ # feeAmount: "0.0003998377369698171",
1128
+ # feeCurrency: "MX",
1129
+ # time: 1736417034280
1130
+ # }
1131
+ #
1132
+ timestamp = self.safe_integer_2(trade, 'T', 'time')
1133
+ tradeId = self.safe_string_2(trade, 't', 'tradeId')
1017
1134
  if timestamp is None:
1018
1135
  timestamp = self.safe_integer(trade, 't')
1019
1136
  tradeId = None
1020
- priceString = self.safe_string(trade, 'p')
1021
- amountString = self.safe_string(trade, 'v')
1022
- rawSide = self.safe_string(trade, 'S')
1137
+ priceString = self.safe_string_2(trade, 'p', 'price')
1138
+ amountString = self.safe_string_2(trade, 'v', 'quantity')
1139
+ rawSide = self.safe_string_2(trade, 'S', 'tradeType')
1023
1140
  side = 'buy' if (rawSide == '1') else 'sell'
1024
1141
  isMaker = self.safe_integer(trade, 'm')
1025
- feeAmount = self.safe_number(trade, 'n')
1026
- feeCurrencyId = self.safe_string(trade, 'N')
1142
+ feeAmount = self.safe_string_2(trade, 'n', 'feeAmount')
1143
+ feeCurrencyId = self.safe_string_2(trade, 'N', 'feeCurrency')
1027
1144
  return self.safe_trade({
1028
1145
  'info': trade,
1029
1146
  'id': tradeId,
1030
- 'order': self.safe_string(trade, 'i'),
1147
+ 'order': self.safe_string_2(trade, 'i', 'orderId'),
1031
1148
  'timestamp': timestamp,
1032
1149
  'datetime': self.iso8601(timestamp),
1033
1150
  'symbol': self.safe_symbol(None, market),
@@ -1036,7 +1153,7 @@ class mexc(ccxt.async_support.mexc):
1036
1153
  'takerOrMaker': 'maker' if (isMaker) else 'taker',
1037
1154
  'price': priceString,
1038
1155
  'amount': amountString,
1039
- 'cost': None,
1156
+ 'cost': self.safe_string(trade, 'amount'),
1040
1157
  'fee': {
1041
1158
  'cost': feeAmount,
1042
1159
  'currency': self.safe_currency_code(feeCurrencyId),
@@ -1046,7 +1163,7 @@ class mexc(ccxt.async_support.mexc):
1046
1163
  async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1047
1164
  """
1048
1165
 
1049
- https://mexcdevelop.github.io/apidocs/spot_v3_en/#spot-account-orders
1166
+ https://www.mexc.com/api-docs/spot-v3/websocket-user-data-streams#spot-account-orders
1050
1167
  https://mexcdevelop.github.io/apidocs/spot_v3_en/#margin-account-orders
1051
1168
 
1052
1169
  watches information on multiple orders made by the user
@@ -1068,7 +1185,7 @@ class mexc(ccxt.async_support.mexc):
1068
1185
  type, params = self.handle_market_type_and_params('watchOrders', market, params)
1069
1186
  orders = None
1070
1187
  if type == 'spot':
1071
- channel = type + '@private.orders.v3.api'
1188
+ channel = 'spot@private.orders.v3.api.pb'
1072
1189
  orders = await self.watch_spot_private(channel, messageHash, params)
1073
1190
  else:
1074
1191
  orders = await self.watch_swap_private(messageHash, params)
@@ -1141,11 +1258,18 @@ class mexc(ccxt.async_support.mexc):
1141
1258
  # "s": "MXUSDT",
1142
1259
  # "t":1661938138193
1143
1260
  # }
1261
+ # protobuf
1262
+ # {
1263
+ # channel: "spot@private.orders.v3.api.pb",
1264
+ # symbol: "MXUSDT",
1265
+ # sendTime: 1736417034281,
1266
+ # privateOrders {}
1267
+ # }
1144
1268
  #
1145
1269
  messageHash = 'orders'
1146
- data = self.safe_value_2(message, 'd', 'data')
1270
+ data = self.safe_dict_n(message, ['d', 'data', 'privateOrders'])
1147
1271
  futuresMarketId = self.safe_string(data, 'symbol')
1148
- marketId = self.safe_string(message, 's', futuresMarketId)
1272
+ marketId = self.safe_string_2(message, 's', 'symbol', futuresMarketId)
1149
1273
  market = self.safe_market(marketId)
1150
1274
  symbol = market['symbol']
1151
1275
  parsed = None
@@ -1213,11 +1337,28 @@ class mexc(ccxt.async_support.mexc):
1213
1337
  # "s":1,
1214
1338
  # "i":"e03a5c7441e44ed899466a7140b71391",
1215
1339
  # }
1340
+ # protofbuf spot order
1341
+ # {
1342
+ # "id":"C02__583905164440776704043",
1343
+ # "price":"0.001053",
1344
+ # "quantity":"2000",
1345
+ # "amount":"0",
1346
+ # "avgPrice":"0.001007",
1347
+ # "orderType":5,
1348
+ # "tradeType":1,
1349
+ # "remainAmount":"0.092",
1350
+ # "remainQuantity":"0",
1351
+ # "lastDealQuantity":"2000",
1352
+ # "cumulativeQuantity":"2000",
1353
+ # "cumulativeAmount":"2.014",
1354
+ # "status":2,
1355
+ # "createTime":"1754996075502"
1356
+ # }
1216
1357
  #
1217
- timestamp = self.safe_integer(order, 'O')
1218
- side = self.safe_string(order, 'S')
1219
- status = self.safe_string(order, 's')
1220
- type = self.safe_string(order, 'o')
1358
+ timestamp = self.safe_integer(order, 'createTime')
1359
+ side = self.safe_string(order, 'tradeType')
1360
+ status = self.safe_string(order, 'status')
1361
+ type = self.safe_string(order, 'orderType')
1221
1362
  fee = None
1222
1363
  feeCurrency = self.safe_string(order, 'N')
1223
1364
  if feeCurrency is not None:
@@ -1226,8 +1367,8 @@ class mexc(ccxt.async_support.mexc):
1226
1367
  'cost': None,
1227
1368
  }
1228
1369
  return self.safe_order({
1229
- 'id': self.safe_string(order, 'i'),
1230
- 'clientOrderId': self.safe_string(order, 'c'),
1370
+ 'id': self.safe_string(order, 'id'),
1371
+ 'clientOrderId': self.safe_string(order, 'clientOrderId'),
1231
1372
  'timestamp': timestamp,
1232
1373
  'datetime': self.iso8601(timestamp),
1233
1374
  'lastTradeTimestamp': None,
@@ -1236,14 +1377,14 @@ class mexc(ccxt.async_support.mexc):
1236
1377
  'type': self.parse_ws_order_type(type),
1237
1378
  'timeInForce': self.parse_ws_time_in_force(type),
1238
1379
  'side': 'buy' if (side == '1') else 'sell',
1239
- 'price': self.safe_string(order, 'p'),
1380
+ 'price': self.safe_string(order, 'price'),
1240
1381
  'stopPrice': None,
1241
- 'triggerPrice': self.safe_number(order, 'P'),
1242
- 'average': self.safe_string(order, 'ap'),
1243
- 'amount': self.safe_string(order, 'v'),
1244
- 'cost': self.safe_string(order, 'a'),
1245
- 'filled': self.safe_string(order, 'cv'),
1246
- 'remaining': self.safe_string(order, 'V'),
1382
+ 'triggerPrice': None,
1383
+ 'average': self.safe_string(order, 'avgPrice'),
1384
+ 'amount': self.safe_string(order, 'quantity'),
1385
+ 'cost': self.safe_string(order, 'amount'),
1386
+ 'filled': self.safe_string(order, 'cumulativeQuantity'),
1387
+ 'remaining': self.safe_string(order, 'remainQuantity'),
1247
1388
  'fee': fee,
1248
1389
  'trades': None,
1249
1390
  'info': order,
@@ -1266,7 +1407,7 @@ class mexc(ccxt.async_support.mexc):
1266
1407
  def parse_ws_order_type(self, type):
1267
1408
  types: dict = {
1268
1409
  '1': 'limit', # LIMIT_ORDER
1269
- '2': None, # POST_ONLY
1410
+ '2': 'limit', # POST_ONLY
1270
1411
  '3': None, # IMMEDIATE_OR_CANCEL
1271
1412
  '4': None, # FILL_OR_KILL
1272
1413
  '5': 'market', # MARKET_ORDER
@@ -1288,7 +1429,7 @@ class mexc(ccxt.async_support.mexc):
1288
1429
  async def watch_balance(self, params={}) -> Balances:
1289
1430
  """
1290
1431
 
1291
- https://mexcdevelop.github.io/apidocs/spot_v3_en/#spot-account-upadte
1432
+ https://www.mexc.com/api-docs/spot-v3/websocket-user-data-streams#spot-account-update
1292
1433
 
1293
1434
  watch balance and get the amount of funds available for trading or funds locked in orders
1294
1435
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1299,7 +1440,7 @@ class mexc(ccxt.async_support.mexc):
1299
1440
  type, params = self.handle_market_type_and_params('watchBalance', None, params)
1300
1441
  messageHash = 'balance:' + type
1301
1442
  if type == 'spot':
1302
- channel = 'spot@private.account.v3.api'
1443
+ channel = 'spot@private.account.v3.api.pb'
1303
1444
  return await self.watch_spot_private(channel, messageHash, params)
1304
1445
  else:
1305
1446
  return await self.watch_swap_private(messageHash, params)
@@ -1336,22 +1477,22 @@ class mexc(ccxt.async_support.mexc):
1336
1477
  # "ts": 1680059188190
1337
1478
  # }
1338
1479
  #
1339
- c = self.safe_string(message, 'c')
1480
+ c = self.safe_string_2(message, 'c', 'channel')
1340
1481
  type = 'swap' if (c is None) else 'spot'
1341
1482
  messageHash = 'balance:' + type
1342
- data = self.safe_value_2(message, 'd', 'data')
1483
+ data = self.safe_dict_n(message, ['d', 'data', 'privateAccount'])
1343
1484
  futuresTimestamp = self.safe_integer(message, 'ts')
1344
- timestamp = self.safe_integer(data, 'c', futuresTimestamp)
1485
+ timestamp = self.safe_integer_2(data, 'c', 'time', futuresTimestamp)
1345
1486
  if not (type in self.balance):
1346
1487
  self.balance[type] = {}
1347
1488
  self.balance[type]['info'] = data
1348
1489
  self.balance[type]['timestamp'] = timestamp
1349
1490
  self.balance[type]['datetime'] = self.iso8601(timestamp)
1350
- currencyId = self.safe_string_2(data, 'a', 'currency')
1491
+ currencyId = self.safe_string_n(data, ['a', 'currency', 'vcoinName'])
1351
1492
  code = self.safe_currency_code(currencyId)
1352
1493
  account = self.account()
1353
- account['free'] = self.safe_string_2(data, 'f', 'availableBalance')
1354
- account['used'] = self.safe_string_2(data, 'l', 'frozenBalance')
1494
+ account['total'] = self.safe_string_n(data, ['f', 'availableBalance', 'balanceAmount'])
1495
+ account['used'] = self.safe_string_n(data, ['l', 'frozenBalance', 'frozenAmount'])
1355
1496
  self.balance[type][code] = account
1356
1497
  self.balance[type] = self.safe_balance(self.balance[type])
1357
1498
  client.resolve(self.balance[type], messageHash)
@@ -1369,22 +1510,17 @@ class mexc(ccxt.async_support.mexc):
1369
1510
  url = None
1370
1511
  channel = None
1371
1512
  if market['spot']:
1372
- miniTicker = False
1373
- miniTicker, params = self.handle_option_and_params(params, 'watchTicker', 'miniTicker')
1374
- if miniTicker:
1375
- channel = 'spot@public.miniTicker.v3.api@' + market['id'] + '@UTC+8'
1376
- else:
1377
- channel = 'spot@public.bookTicker.v3.api@' + market['id']
1513
+ channel = 'spot@public.aggre.bookTicker.v3.api.pb@100ms@' + market['id']
1378
1514
  url = self.urls['api']['ws']['spot']
1379
1515
  params['unsubscribed'] = True
1380
- await self.watch_spot_public(channel, messageHash, params)
1516
+ self.watch_spot_public(channel, messageHash, params)
1381
1517
  else:
1382
1518
  channel = 'unsub.ticker'
1383
1519
  requestParams: dict = {
1384
1520
  'symbol': market['id'],
1385
1521
  }
1386
1522
  url = self.urls['api']['ws']['swap']
1387
- await self.watch_swap_public(channel, messageHash, requestParams, params)
1523
+ self.watch_swap_public(channel, messageHash, requestParams, params)
1388
1524
  client = self.client(url)
1389
1525
  self.handle_unsubscriptions(client, [messageHash])
1390
1526
  return None
@@ -1409,33 +1545,39 @@ class mexc(ccxt.async_support.mexc):
1409
1545
  url = self.urls['api']['ws']['spot'] if (isSpot) else self.urls['api']['ws']['swap']
1410
1546
  request: dict = {}
1411
1547
  if isSpot:
1412
- miniTicker = False
1413
- miniTicker, params = self.handle_option_and_params(params, 'watchTickers', 'miniTicker')
1414
- topics = []
1415
- if not miniTicker:
1416
- if symbols is None:
1417
- raise ArgumentsRequired(self.id + ' watchTickers required symbols argument for the bookTicker channel')
1418
- marketIds = self.market_ids(symbols)
1419
- for i in range(0, len(marketIds)):
1420
- marketId = marketIds[i]
1421
- messageHashes.append('unsubscribe:ticker:' + symbols[i])
1422
- channel = 'spot@public.bookTicker.v3.api@' + marketId
1423
- topics.append(channel)
1424
- else:
1425
- topics.append('spot@public.miniTickers.v3.api@UTC+8')
1426
- if symbols is None:
1427
- messageHashes.append('unsubscribe:spot:ticker')
1428
- else:
1429
- for i in range(0, len(symbols)):
1430
- messageHashes.append('unsubscribe:ticker:' + symbols[i])
1431
- request['method'] = 'UNSUBSCRIPTION'
1432
- request['params'] = topics
1548
+ raise NotSupported(self.id + ' watchTickers does not support spot markets')
1549
+ # miniTicker = False
1550
+ # miniTicker, params = self.handle_option_and_params(params, 'watchTickers', 'miniTicker')
1551
+ # topics = []
1552
+ # if not miniTicker:
1553
+ # if symbols is None:
1554
+ # raise ArgumentsRequired(self.id + ' watchTickers required symbols argument for the bookTicker channel')
1555
+ # }
1556
+ # marketIds = self.market_ids(symbols)
1557
+ # for i in range(0, len(marketIds)):
1558
+ # marketId = marketIds[i]
1559
+ # messageHashes.append('unsubscribe:ticker:' + symbols[i])
1560
+ # channel = 'spot@public.bookTicker.v3.api@' + marketId
1561
+ # topics.append(channel)
1562
+ # }
1563
+ # else:
1564
+ # topics.append('spot@public.miniTickers.v3.api@UTC+8')
1565
+ # if symbols is None:
1566
+ # messageHashes.append('unsubscribe:spot:ticker')
1567
+ # else:
1568
+ # for i in range(0, len(symbols)):
1569
+ # messageHashes.append('unsubscribe:ticker:' + symbols[i])
1570
+ # }
1571
+ # }
1572
+ # }
1573
+ # request['method'] = 'UNSUBSCRIPTION'
1574
+ # request['params'] = topics
1433
1575
  else:
1434
1576
  request['method'] = 'unsub.tickers'
1435
1577
  request['params'] = {}
1436
1578
  messageHashes.append('unsubscribe:ticker')
1437
1579
  client = self.client(url)
1438
- await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
1580
+ self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
1439
1581
  self.handle_unsubscriptions(client, messageHashes)
1440
1582
  return None
1441
1583
 
@@ -1461,7 +1603,7 @@ class mexc(ccxt.async_support.mexc):
1461
1603
  for i in range(0, len(symbols)):
1462
1604
  if isSpot:
1463
1605
  market = self.market(symbols[i])
1464
- topics.append('spot@public.bookTicker.v3.api@' + market['id'])
1606
+ topics.append('spot@public.aggre.bookTicker.v3.api.pb@100ms@' + market['id'])
1465
1607
  messageHashes.append('unsubscribe:bidask:' + symbols[i])
1466
1608
  url = self.urls['api']['ws']['spot']
1467
1609
  request: dict = {
@@ -1469,7 +1611,7 @@ class mexc(ccxt.async_support.mexc):
1469
1611
  'params': topics,
1470
1612
  }
1471
1613
  client = self.client(url)
1472
- await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
1614
+ self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
1473
1615
  self.handle_unsubscriptions(client, messageHashes)
1474
1616
  return None
1475
1617
 
@@ -1491,9 +1633,9 @@ class mexc(ccxt.async_support.mexc):
1491
1633
  url = None
1492
1634
  if market['spot']:
1493
1635
  url = self.urls['api']['ws']['spot']
1494
- channel = 'spot@public.kline.v3.api@' + market['id'] + '@' + timeframeId
1636
+ channel = 'spot@public.kline.v3.api.pb@' + market['id'] + '@' + timeframeId
1495
1637
  params['unsubscribed'] = True
1496
- await self.watch_spot_public(channel, messageHash, params)
1638
+ self.watch_spot_public(channel, messageHash, params)
1497
1639
  else:
1498
1640
  url = self.urls['api']['ws']['swap']
1499
1641
  channel = 'unsub.kline'
@@ -1501,7 +1643,7 @@ class mexc(ccxt.async_support.mexc):
1501
1643
  'symbol': market['id'],
1502
1644
  'interval': timeframeId,
1503
1645
  }
1504
- await self.watch_swap_public(channel, messageHash, requestParams, params)
1646
+ self.watch_swap_public(channel, messageHash, requestParams, params)
1505
1647
  client = self.client(url)
1506
1648
  self.handle_unsubscriptions(client, [messageHash])
1507
1649
  return None
@@ -1511,6 +1653,7 @@ class mexc(ccxt.async_support.mexc):
1511
1653
  unWatches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1512
1654
  :param str symbol: unified array of symbols
1513
1655
  :param dict [params]: extra parameters specific to the exchange API endpoint
1656
+ :param str [params.frequency]: the frequency of the order book updates, default is '10ms', can be '100ms' or '10ms
1514
1657
  :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
1515
1658
  """
1516
1659
  await self.load_markets()
@@ -1520,16 +1663,18 @@ class mexc(ccxt.async_support.mexc):
1520
1663
  url = None
1521
1664
  if market['spot']:
1522
1665
  url = self.urls['api']['ws']['spot']
1523
- channel = 'spot@public.increase.depth.v3.api@' + market['id']
1666
+ frequency = None
1667
+ frequency, params = self.handle_option_and_params(params, 'watchOrderBook', 'frequency', '100ms')
1668
+ channel = 'spot@public.aggre.depth.v3.api.pb@' + frequency + '@' + market['id']
1524
1669
  params['unsubscribed'] = True
1525
- await self.watch_spot_public(channel, messageHash, params)
1670
+ self.watch_spot_public(channel, messageHash, params)
1526
1671
  else:
1527
1672
  url = self.urls['api']['ws']['swap']
1528
1673
  channel = 'unsub.depth'
1529
1674
  requestParams: dict = {
1530
1675
  'symbol': market['id'],
1531
1676
  }
1532
- await self.watch_swap_public(channel, messageHash, requestParams, params)
1677
+ self.watch_swap_public(channel, messageHash, requestParams, params)
1533
1678
  client = self.client(url)
1534
1679
  self.handle_unsubscriptions(client, [messageHash])
1535
1680
  return None
@@ -1549,16 +1694,16 @@ class mexc(ccxt.async_support.mexc):
1549
1694
  url = None
1550
1695
  if market['spot']:
1551
1696
  url = self.urls['api']['ws']['spot']
1552
- channel = 'spot@public.deals.v3.api@' + market['id']
1697
+ channel = 'spot@public.aggre.deals.v3.api.pb@100ms@' + market['id']
1553
1698
  params['unsubscribed'] = True
1554
- await self.watch_spot_public(channel, messageHash, params)
1699
+ self.watch_spot_public(channel, messageHash, params)
1555
1700
  else:
1556
1701
  url = self.urls['api']['ws']['swap']
1557
1702
  channel = 'unsub.deal'
1558
1703
  requestParams: dict = {
1559
1704
  'symbol': market['id'],
1560
1705
  }
1561
- await self.watch_swap_public(channel, messageHash, requestParams, params)
1706
+ self.watch_swap_public(channel, messageHash, requestParams, params)
1562
1707
  client = self.client(url)
1563
1708
  self.handle_unsubscriptions(client, [messageHash])
1564
1709
  return None
@@ -1651,16 +1796,59 @@ class mexc(ccxt.async_support.mexc):
1651
1796
  channel = self.safe_string(parts, 1)
1652
1797
  methods: dict = {
1653
1798
  'public.increase.depth.v3.api': self.handle_order_book_subscription,
1799
+ 'public.aggre.depth.v3.api.pb': self.handle_order_book_subscription,
1654
1800
  }
1655
1801
  method = self.safe_value(methods, channel)
1656
1802
  if method is not None:
1657
1803
  method(client, message)
1658
1804
 
1805
+ def handle_protobuf_message(self, client: Client, message):
1806
+ # protobuf message decoded
1807
+ # {
1808
+ # "channel":"spot@public.kline.v3.api.pb@BTCUSDT@Min1",
1809
+ # "symbol":"BTCUSDT",
1810
+ # "symbolId":"2fb942154ef44a4ab2ef98c8afb6a4a7",
1811
+ # "createTime":"1754737941062",
1812
+ # "publicSpotKline":{
1813
+ # "interval":"Min1",
1814
+ # "windowStart":"1754737920",
1815
+ # "openingPrice":"117317.31",
1816
+ # "closingPrice":"117325.26",
1817
+ # "highestPrice":"117341",
1818
+ # "lowestPrice":"117317.3",
1819
+ # "volume":"3.12599854",
1820
+ # "amount":"366804.43",
1821
+ # "windowEnd":"1754737980"
1822
+ # }
1823
+ # }
1824
+ channel = self.safe_string(message, 'channel')
1825
+ channelParts = channel.split('@')
1826
+ channelId = self.safe_string(channelParts, 1)
1827
+ if channelId == 'public.kline.v3.api.pb':
1828
+ self.handle_ohlcv(client, message)
1829
+ elif channelId == 'public.aggre.deals.v3.api.pb':
1830
+ self.handle_trades(client, message)
1831
+ elif channelId == 'public.aggre.bookTicker.v3.api.pb':
1832
+ self.handle_ticker(client, message)
1833
+ elif channelId == 'public.aggre.depth.v3.api.pb':
1834
+ self.handle_order_book(client, message)
1835
+ elif channelId == 'private.account.v3.api.pb':
1836
+ self.handle_balance(client, message)
1837
+ elif channelId == 'private.deals.v3.api.pb':
1838
+ self.handle_my_trade(client, message)
1839
+ elif channelId == 'private.orders.v3.api.pb':
1840
+ self.handle_order(client, message)
1841
+ return True
1842
+
1659
1843
  def handle_message(self, client: Client, message):
1660
1844
  if isinstance(message, str):
1661
1845
  if message == 'Invalid listen key':
1662
1846
  error = AuthenticationError(self.id + ' invalid listen key')
1663
1847
  client.reject(error)
1848
+ return
1849
+ if self.is_binary_message(message):
1850
+ message = self.decode_proto_msg(message)
1851
+ self.handle_protobuf_message(client, message)
1664
1852
  return
1665
1853
  if 'msg' in message:
1666
1854
  self.handle_subscription_status(client, message)