ccxt 4.4.1__py2.py3-none-any.whl → 4.4.3__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.
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.1'
7
+ __version__ = '4.4.3'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/binance.py CHANGED
@@ -14,7 +14,6 @@ from ccxt.base.errors import ArgumentsRequired
14
14
  from ccxt.base.errors import BadRequest
15
15
  from ccxt.base.errors import NotSupported
16
16
  from ccxt.base.errors import ChecksumError
17
- from ccxt.base.errors import UnsubscribeError
18
17
  from ccxt.base.precise import Precise
19
18
 
20
19
 
@@ -952,52 +951,9 @@ class binance(ccxt.async_support.binance):
952
951
  for j in range(0, len(messageHashes)):
953
952
  unsubHash = messageHashes[j]
954
953
  subHash = subMessageHashes[j]
955
- if unsubHash in client.subscriptions:
956
- del client.subscriptions[unsubHash]
957
- if subHash in client.subscriptions:
958
- del client.subscriptions[subHash]
959
- error = UnsubscribeError(self.id + ' ' + subHash)
960
- client.reject(error, subHash)
961
- client.resolve(True, unsubHash)
954
+ self.clean_unsubscription(client, subHash, unsubHash)
962
955
  self.clean_cache(subscription)
963
956
 
964
- def clean_cache(self, subscription: dict):
965
- topic = self.safe_string(subscription, 'topic')
966
- symbols = self.safe_list(subscription, 'symbols', [])
967
- symbolsLength = len(symbols)
968
- if topic == 'ohlcv':
969
- symbolsAndTimeFrames = self.safe_list(subscription, 'symbolsAndTimeframes', [])
970
- for i in range(0, len(symbolsAndTimeFrames)):
971
- symbolAndTimeFrame = symbolsAndTimeFrames[i]
972
- symbol = self.safe_string(symbolAndTimeFrame, 0)
973
- timeframe = self.safe_string(symbolAndTimeFrame, 1)
974
- if timeframe in self.ohlcvs[symbol]:
975
- del self.ohlcvs[symbol][timeframe]
976
- elif symbolsLength > 0:
977
- for i in range(0, len(symbols)):
978
- symbol = symbols[i]
979
- if topic == 'trade':
980
- del self.trades[symbol]
981
- elif topic == 'orderbook':
982
- del self.orderbooks[symbol]
983
- elif topic == 'ticker':
984
- del self.tickers[symbol]
985
- else:
986
- if topic == 'myTrades':
987
- # don't reset self.myTrades directly here
988
- # because in c# we need to use a different object
989
- keys = list(self.myTrades.keys())
990
- for i in range(0, len(keys)):
991
- del self.myTrades[keys[i]]
992
- elif topic == 'orders':
993
- orderSymbols = list(self.orders.keys())
994
- for i in range(0, len(orderSymbols)):
995
- del self.orders[orderSymbols[i]]
996
- elif topic == 'ticker':
997
- tickerSymbols = list(self.tickers.keys())
998
- for i in range(0, len(tickerSymbols)):
999
- del self.tickers[tickerSymbols[i]]
1000
-
1001
957
  async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1002
958
  """
1003
959
  get the list of most recent trades for a list of symbols
@@ -1106,7 +1062,7 @@ class binance(ccxt.async_support.binance):
1106
1062
  'subMessageHashes': subMessageHashes,
1107
1063
  'messageHashes': messageHashes,
1108
1064
  'symbols': symbols,
1109
- 'topic': 'trade',
1065
+ 'topic': 'trades',
1110
1066
  }
1111
1067
  return await self.watch_multiple(url, messageHashes, self.extend(request, query), messageHashes, subscription)
1112
1068
 
@@ -1810,7 +1766,7 @@ class binance(ccxt.async_support.binance):
1810
1766
  result = await self.watch_multi_ticker_helper('watchBidsAsks', 'bookTicker', symbols, params)
1811
1767
  if self.newUpdates:
1812
1768
  return result
1813
- return self.filter_by_array(self.tickers, 'symbol', symbols)
1769
+ return self.filter_by_array(self.bidsasks, 'symbol', symbols)
1814
1770
 
1815
1771
  async def watch_multi_ticker_helper(self, methodName, channelName: str, symbols: Strings = None, params={}):
1816
1772
  await self.load_markets()
ccxt/pro/bitget.py CHANGED
@@ -1876,13 +1876,7 @@ class bitget(ccxt.async_support.bitget):
1876
1876
  if symbol in self.ohlcvs:
1877
1877
  if timeframe in self.ohlcvs[symbol]:
1878
1878
  del self.ohlcvs[symbol][timeframe]
1879
- if subMessageHash in client.subscriptions:
1880
- del client.subscriptions[subMessageHash]
1881
- if messageHash in client.subscriptions:
1882
- del client.subscriptions[messageHash]
1883
- error = UnsubscribeError(self.id + ' ohlcv ' + timeframe + ' ' + symbol)
1884
- client.reject(error, subMessageHash)
1885
- client.resolve(True, messageHash)
1879
+ self.clean_unsubscription(client, subMessageHash, messageHash)
1886
1880
 
1887
1881
  def handle_un_subscription_status(self, client: Client, message):
1888
1882
  #
ccxt/pro/bitmex.py CHANGED
@@ -66,6 +66,7 @@ class bitmex(ccxt.async_support.bitmex):
66
66
  async def watch_ticker(self, symbol: str, params={}) -> Ticker:
67
67
  """
68
68
  watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
69
+ :see: https://www.bitmex.com/app/wsAPI#Subscriptions
69
70
  :param str symbol: unified symbol of the market to fetch the ticker for
70
71
  :param dict [params]: extra parameters specific to the exchange API endpoint
71
72
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -78,6 +79,7 @@ class bitmex(ccxt.async_support.bitmex):
78
79
  async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
79
80
  """
80
81
  watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
82
+ :see: https://www.bitmex.com/app/wsAPI#Subscriptions
81
83
  :param str[] symbols: unified symbol of the market to fetch the ticker for
82
84
  :param dict [params]: extra parameters specific to the exchange API endpoint
83
85
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -449,6 +451,7 @@ class bitmex(ccxt.async_support.bitmex):
449
451
  async def watch_balance(self, params={}) -> Balances:
450
452
  """
451
453
  watch balance and get the amount of funds available for trading or funds locked in orders
454
+ :see: https://www.bitmex.com/app/wsAPI#Subscriptions
452
455
  :param dict [params]: extra parameters specific to the exchange API endpoint
453
456
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
454
457
  """
@@ -651,6 +654,7 @@ class bitmex(ccxt.async_support.bitmex):
651
654
  async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
652
655
  """
653
656
  get the list of most recent trades for a particular symbol
657
+ :see: https://www.bitmex.com/app/wsAPI#Subscriptions
654
658
  :param str symbol: unified symbol of the market to fetch trades for
655
659
  :param int [since]: timestamp in ms of the earliest trade to fetch
656
660
  :param int [limit]: the maximum amount of trades to fetch
@@ -697,8 +701,8 @@ class bitmex(ccxt.async_support.bitmex):
697
701
 
698
702
  async def watch_positions(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
699
703
  """
700
- :see: https://www.bitmex.com/app/wsAPI
701
704
  watch all open positions
705
+ :see: https://www.bitmex.com/app/wsAPI#Subscriptions
702
706
  :param str[]|None symbols: list of unified market symbols
703
707
  :param dict params: extra parameters specific to the exchange API endpoint
704
708
  :returns dict[]: a list of `position structure <https://docs.ccxt.com/en/latest/manual.html#position-structure>`
@@ -894,6 +898,7 @@ class bitmex(ccxt.async_support.bitmex):
894
898
  async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
895
899
  """
896
900
  watches information on multiple orders made by the user
901
+ :see: https://www.bitmex.com/app/wsAPI#Subscriptions
897
902
  :param str symbol: unified market symbol of the market orders were made in
898
903
  :param int [since]: the earliest time in ms to fetch orders for
899
904
  :param int [limit]: the maximum number of order structures to retrieve
@@ -1100,6 +1105,7 @@ class bitmex(ccxt.async_support.bitmex):
1100
1105
  async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1101
1106
  """
1102
1107
  watches information on multiple trades made by the user
1108
+ :see: https://www.bitmex.com/app/wsAPI#Subscriptions
1103
1109
  :param str symbol: unified market symbol of the market trades were made in
1104
1110
  :param int [since]: the earliest time in ms to fetch trades for
1105
1111
  :param int [limit]: the maximum number of trade structures to retrieve
@@ -1209,6 +1215,7 @@ class bitmex(ccxt.async_support.bitmex):
1209
1215
  async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
1210
1216
  """
1211
1217
  watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1218
+ :see: https://www.bitmex.com/app/wsAPI#OrderBookL2
1212
1219
  :param str symbol: unified symbol of the market to fetch the order book for
1213
1220
  :param int [limit]: the maximum amount of order book entries to return
1214
1221
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1219,6 +1226,7 @@ class bitmex(ccxt.async_support.bitmex):
1219
1226
  async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
1220
1227
  """
1221
1228
  watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
1229
+ :see: https://www.bitmex.com/app/wsAPI#OrderBookL2
1222
1230
  :param str[] symbols: unified array of symbols
1223
1231
  :param int [limit]: the maximum amount of order book entries to return
1224
1232
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1255,6 +1263,7 @@ class bitmex(ccxt.async_support.bitmex):
1255
1263
  async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1256
1264
  """
1257
1265
  get the list of most recent trades for a list of symbols
1266
+ :see: https://www.bitmex.com/app/wsAPI#Subscriptions
1258
1267
  :param str[] symbols: unified symbol of the market to fetch trades for
1259
1268
  :param int [since]: timestamp in ms of the earliest trade to fetch
1260
1269
  :param int [limit]: the maximum amount of trades to fetch
@@ -1288,6 +1297,7 @@ class bitmex(ccxt.async_support.bitmex):
1288
1297
  async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1289
1298
  """
1290
1299
  watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1300
+ :see: https://www.bitmex.com/app/wsAPI#Subscriptions
1291
1301
  :param str symbol: unified symbol of the market to fetch OHLCV data for
1292
1302
  :param str timeframe: the length of time each candle represents
1293
1303
  :param int [since]: timestamp in ms of the earliest candle to fetch
ccxt/pro/bybit.py CHANGED
@@ -15,7 +15,6 @@ from ccxt.base.errors import ExchangeError
15
15
  from ccxt.base.errors import AuthenticationError
16
16
  from ccxt.base.errors import ArgumentsRequired
17
17
  from ccxt.base.errors import BadRequest
18
- from ccxt.base.errors import UnsubscribeError
19
18
 
20
19
 
21
20
  class bybit(ccxt.async_support.bybit):
@@ -953,7 +952,7 @@ class bybit(ccxt.async_support.bybit):
953
952
  messageHash = 'unsubscribe:trade:' + symbol
954
953
  messageHashes.append(messageHash)
955
954
  subMessageHashes.append('trade:' + symbol)
956
- return await self.un_watch_topics(url, 'trade', symbols, messageHashes, subMessageHashes, topics, params)
955
+ return await self.un_watch_topics(url, 'trades', symbols, messageHashes, subMessageHashes, topics, params)
957
956
 
958
957
  async def un_watch_trades(self, symbol: str, params={}) -> Any:
959
958
  """
@@ -2310,44 +2309,6 @@ class bybit(ccxt.async_support.bybit):
2310
2309
  for j in range(0, len(messageHashes)):
2311
2310
  unsubHash = messageHashes[j]
2312
2311
  subHash = subMessageHashes[j]
2313
- if unsubHash in client.subscriptions:
2314
- del client.subscriptions[unsubHash]
2315
- if subHash in client.subscriptions:
2316
- del client.subscriptions[subHash]
2317
- error = UnsubscribeError(self.id + ' ' + messageHash)
2318
- client.reject(error, subHash)
2319
- client.resolve(True, unsubHash)
2312
+ self.clean_unsubscription(client, subHash, unsubHash)
2320
2313
  self.clean_cache(subscription)
2321
2314
  return message
2322
-
2323
- def clean_cache(self, subscription: dict):
2324
- topic = self.safe_string(subscription, 'topic')
2325
- symbols = self.safe_list(subscription, 'symbols', [])
2326
- symbolsLength = len(symbols)
2327
- if topic == 'ohlcv':
2328
- symbolsAndTimeFrames = self.safe_list(subscription, 'symbolsAndTimeframes', [])
2329
- for i in range(0, len(symbolsAndTimeFrames)):
2330
- symbolAndTimeFrame = symbolsAndTimeFrames[i]
2331
- symbol = self.safe_string(symbolAndTimeFrame, 0)
2332
- timeframe = self.safe_string(symbolAndTimeFrame, 1)
2333
- del self.ohlcvs[symbol][timeframe]
2334
- elif symbolsLength > 0:
2335
- for i in range(0, len(symbols)):
2336
- symbol = symbols[i]
2337
- if topic == 'trade':
2338
- del self.trades[symbol]
2339
- elif topic == 'orderbook':
2340
- del self.orderbooks[symbol]
2341
- elif topic == 'ticker':
2342
- del self.tickers[symbol]
2343
- else:
2344
- if topic == 'myTrades':
2345
- # don't reset self.myTrades directly here
2346
- # because in c# we need to use a different object
2347
- keys = list(self.myTrades.keys())
2348
- for i in range(0, len(keys)):
2349
- del self.myTrades[keys[i]]
2350
- elif topic == 'orders':
2351
- orderSymbols = list(self.orders.keys())
2352
- for i in range(0, len(orderSymbols)):
2353
- del self.orders[orderSymbols[i]]
ccxt/pro/cryptocom.py CHANGED
@@ -6,7 +6,7 @@
6
6
  import ccxt.async_support
7
7
  from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Trade
9
+ from ccxt.base.types import Balances, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
10
10
  from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
12
  from typing import Any
@@ -14,7 +14,6 @@ from ccxt.base.errors import ExchangeError
14
14
  from ccxt.base.errors import AuthenticationError
15
15
  from ccxt.base.errors import NetworkError
16
16
  from ccxt.base.errors import ChecksumError
17
- from ccxt.base.errors import UnsubscribeError
18
17
 
19
18
 
20
19
  class cryptocom(ccxt.async_support.cryptocom):
@@ -25,7 +24,8 @@ class cryptocom(ccxt.async_support.cryptocom):
25
24
  'ws': True,
26
25
  'watchBalance': True,
27
26
  'watchTicker': True,
28
- 'watchTickers': False,
27
+ 'watchTickers': True,
28
+ 'watchBidsAsks': True,
29
29
  'watchMyTrades': True,
30
30
  'watchTrades': True,
31
31
  'watchTradesForSymbols': True,
@@ -349,7 +349,7 @@ class cryptocom(ccxt.async_support.cryptocom):
349
349
  currentTopic = 'trade' + '.' + market['id']
350
350
  messageHashes.append('unsubscribe:trades:' + market['symbol'])
351
351
  topics.append(currentTopic)
352
- return await self.un_watch_public_multiple('trade', symbols, messageHashes, topics, topics, params)
352
+ return await self.un_watch_public_multiple('trades', symbols, messageHashes, topics, topics, params)
353
353
 
354
354
  def handle_trades(self, client: Client, message):
355
355
  #
@@ -444,40 +444,198 @@ class cryptocom(ccxt.async_support.cryptocom):
444
444
  messageHash = 'unsubscribe:ticker:' + market['symbol']
445
445
  return await self.un_watch_public_multiple('ticker', [market['symbol']], [messageHash], [subMessageHash], [subMessageHash], params)
446
446
 
447
+ async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
448
+ """
449
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
450
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#ticker-instrument_name
451
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
452
+ :param dict [params]: extra parameters specific to the exchange API endpoint
453
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
454
+ """
455
+ await self.load_markets()
456
+ symbols = self.market_symbols(symbols, None, False)
457
+ messageHashes = []
458
+ marketIds = self.market_ids(symbols)
459
+ for i in range(0, len(marketIds)):
460
+ marketId = marketIds[i]
461
+ messageHashes.append('ticker.' + marketId)
462
+ url = self.urls['api']['ws']['public']
463
+ id = self.nonce()
464
+ request: dict = {
465
+ 'method': 'subscribe',
466
+ 'params': {
467
+ 'channels': messageHashes,
468
+ },
469
+ 'nonce': id,
470
+ }
471
+ ticker = await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
472
+ if self.newUpdates:
473
+ result: dict = {}
474
+ result[ticker['symbol']] = ticker
475
+ return result
476
+ return self.filter_by_array(self.tickers, 'symbol', symbols)
477
+
478
+ async def un_watch_tickers(self, symbols: Strings = None, params={}) -> Any:
479
+ """
480
+ unWatches a price ticker
481
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#ticker-instrument_name
482
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
483
+ :param dict [params]: extra parameters specific to the exchange API endpoint
484
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
485
+ """
486
+ await self.load_markets()
487
+ symbols = self.market_symbols(symbols, None, False)
488
+ messageHashes = []
489
+ subMessageHashes = []
490
+ marketIds = self.market_ids(symbols)
491
+ for i in range(0, len(marketIds)):
492
+ marketId = marketIds[i]
493
+ symbol = symbols[i]
494
+ subMessageHashes.append('ticker.' + marketId)
495
+ messageHashes.append('unsubscribe:ticker:' + symbol)
496
+ return await self.un_watch_public_multiple('ticker', symbols, messageHashes, subMessageHashes, subMessageHashes, params)
497
+
447
498
  def handle_ticker(self, client: Client, message):
448
499
  #
449
- # {
450
- # "info":{
451
- # "instrument_name":"BTC_USDT",
452
- # "subscription":"ticker.BTC_USDT",
453
- # "channel":"ticker",
454
- # "data":[
455
- # {
456
- # "i":"BTC_USDT",
457
- # "b":43063.19,
458
- # "k":43063.2,
459
- # "a":43063.19,
460
- # "t":1648121165658,
461
- # "v":43573.912409,
462
- # "h":43498.51,
463
- # "l":41876.58,
464
- # "c":1087.43
465
- # }
466
- # ]
500
+ # {
501
+ # "instrument_name": "ETHUSD-PERP",
502
+ # "subscription": "ticker.ETHUSD-PERP",
503
+ # "channel": "ticker",
504
+ # "data": [
505
+ # {
506
+ # "h": "2400.20",
507
+ # "l": "2277.10",
508
+ # "a": "2335.25",
509
+ # "c": "-0.0022",
510
+ # "b": "2335.10",
511
+ # "bs": "5.4000",
512
+ # "k": "2335.16",
513
+ # "ks": "1.9970",
514
+ # "i": "ETHUSD-PERP",
515
+ # "v": "1305697.6462",
516
+ # "vv": "3058704939.17",
517
+ # "oi": "161646.3614",
518
+ # "t": 1726069647560
519
+ # }
520
+ # ]
467
521
  # }
468
- # }
469
522
  #
523
+ self.handle_bid_ask(client, message)
470
524
  messageHash = self.safe_string(message, 'subscription')
471
525
  marketId = self.safe_string(message, 'instrument_name')
472
526
  market = self.safe_market(marketId)
473
527
  data = self.safe_value(message, 'data', [])
474
528
  for i in range(0, len(data)):
475
529
  ticker = data[i]
476
- parsed = self.parse_ticker(ticker, market)
530
+ parsed = self.parse_ws_ticker(ticker, market)
477
531
  symbol = parsed['symbol']
478
532
  self.tickers[symbol] = parsed
479
533
  client.resolve(parsed, messageHash)
480
534
 
535
+ def parse_ws_ticker(self, ticker: dict, market: Market = None) -> Ticker:
536
+ #
537
+ # {
538
+ # "h": "2400.20",
539
+ # "l": "2277.10",
540
+ # "a": "2335.25",
541
+ # "c": "-0.0022",
542
+ # "b": "2335.10",
543
+ # "bs": "5.4000",
544
+ # "k": "2335.16",
545
+ # "ks": "1.9970",
546
+ # "i": "ETHUSD-PERP",
547
+ # "v": "1305697.6462",
548
+ # "vv": "3058704939.17",
549
+ # "oi": "161646.3614",
550
+ # "t": 1726069647560
551
+ # }
552
+ #
553
+ timestamp = self.safe_integer(ticker, 't')
554
+ marketId = self.safe_string(ticker, 'i')
555
+ market = self.safe_market(marketId, market, '_')
556
+ quote = self.safe_string(market, 'quote')
557
+ last = self.safe_string(ticker, 'a')
558
+ return self.safe_ticker({
559
+ 'symbol': market['symbol'],
560
+ 'timestamp': timestamp,
561
+ 'datetime': self.iso8601(timestamp),
562
+ 'high': self.safe_number(ticker, 'h'),
563
+ 'low': self.safe_number(ticker, 'l'),
564
+ 'bid': self.safe_number(ticker, 'b'),
565
+ 'bidVolume': self.safe_number(ticker, 'bs'),
566
+ 'ask': self.safe_number(ticker, 'k'),
567
+ 'askVolume': self.safe_number(ticker, 'ks'),
568
+ 'vwap': None,
569
+ 'open': None,
570
+ 'close': last,
571
+ 'last': last,
572
+ 'previousClose': None,
573
+ 'change': None,
574
+ 'percentage': self.safe_string(ticker, 'c'),
575
+ 'average': None,
576
+ 'baseVolume': self.safe_string(ticker, 'v'),
577
+ 'quoteVolume': self.safe_string(ticker, 'vv') if (quote == 'USD') else None,
578
+ 'info': ticker,
579
+ }, market)
580
+
581
+ async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
582
+ """
583
+ :see: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#ticker-instrument_name
584
+ watches best bid & ask for symbols
585
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
586
+ :param dict [params]: extra parameters specific to the exchange API endpoint
587
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
588
+ """
589
+ await self.load_markets()
590
+ symbols = self.market_symbols(symbols, None, False)
591
+ messageHashes = []
592
+ topics = []
593
+ marketIds = self.market_ids(symbols)
594
+ for i in range(0, len(marketIds)):
595
+ marketId = marketIds[i]
596
+ messageHashes.append('bidask.' + symbols[i])
597
+ topics.append('ticker.' + marketId)
598
+ url = self.urls['api']['ws']['public']
599
+ id = self.nonce()
600
+ request: dict = {
601
+ 'method': 'subscribe',
602
+ 'params': {
603
+ 'channels': topics,
604
+ },
605
+ 'nonce': id,
606
+ }
607
+ newTickers = await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes)
608
+ if self.newUpdates:
609
+ tickers: dict = {}
610
+ tickers[newTickers['symbol']] = newTickers
611
+ return tickers
612
+ return self.filter_by_array(self.bidsasks, 'symbol', symbols)
613
+
614
+ def handle_bid_ask(self, client: Client, message):
615
+ data = self.safe_list(message, 'data', [])
616
+ ticker = self.safe_dict(data, 0, {})
617
+ parsedTicker = self.parse_ws_bid_ask(ticker)
618
+ symbol = parsedTicker['symbol']
619
+ self.bidsasks[symbol] = parsedTicker
620
+ messageHash = 'bidask.' + symbol
621
+ client.resolve(parsedTicker, messageHash)
622
+
623
+ def parse_ws_bid_ask(self, ticker, market=None):
624
+ marketId = self.safe_string(ticker, 'i')
625
+ market = self.safe_market(marketId, market)
626
+ symbol = self.safe_string(market, 'symbol')
627
+ timestamp = self.safe_integer(ticker, 't')
628
+ return self.safe_ticker({
629
+ 'symbol': symbol,
630
+ 'timestamp': timestamp,
631
+ 'datetime': self.iso8601(timestamp),
632
+ 'ask': self.safe_string(ticker, 'k'),
633
+ 'askVolume': self.safe_string(ticker, 'ks'),
634
+ 'bid': self.safe_string(ticker, 'b'),
635
+ 'bidVolume': self.safe_string(ticker, 'bs'),
636
+ 'info': ticker,
637
+ }, market)
638
+
481
639
  async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
482
640
  """
483
641
  watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
@@ -1118,33 +1276,5 @@ class cryptocom(ccxt.async_support.cryptocom):
1118
1276
  for j in range(0, len(messageHashes)):
1119
1277
  unsubHash = messageHashes[j]
1120
1278
  subHash = subMessageHashes[j]
1121
- if unsubHash in client.subscriptions:
1122
- del client.subscriptions[unsubHash]
1123
- if subHash in client.subscriptions:
1124
- del client.subscriptions[subHash]
1125
- error = UnsubscribeError(self.id + ' ' + subHash)
1126
- client.reject(error, subHash)
1127
- client.resolve(True, unsubHash)
1279
+ self.clean_unsubscription(client, subHash, unsubHash)
1128
1280
  self.clean_cache(subscription)
1129
-
1130
- def clean_cache(self, subscription: dict):
1131
- topic = self.safe_string(subscription, 'topic')
1132
- symbols = self.safe_list(subscription, 'symbols', [])
1133
- symbolsLength = len(symbols)
1134
- if topic == 'ohlcv':
1135
- symbolsAndTimeFrames = self.safe_list(subscription, 'symbolsAndTimeframes', [])
1136
- for i in range(0, len(symbolsAndTimeFrames)):
1137
- symbolAndTimeFrame = symbolsAndTimeFrames[i]
1138
- symbol = self.safe_string(symbolAndTimeFrame, 0)
1139
- timeframe = self.safe_string(symbolAndTimeFrame, 1)
1140
- if timeframe in self.ohlcvs[symbol]:
1141
- del self.ohlcvs[symbol][timeframe]
1142
- elif symbolsLength > 0:
1143
- for i in range(0, len(symbols)):
1144
- symbol = symbols[i]
1145
- if topic == 'trade':
1146
- del self.trades[symbol]
1147
- elif topic == 'orderbook':
1148
- del self.orderbooks[symbol]
1149
- elif topic == 'ticker':
1150
- del self.tickers[symbol]
ccxt/pro/gate.py CHANGED
@@ -16,7 +16,6 @@ from ccxt.base.errors import ArgumentsRequired
16
16
  from ccxt.base.errors import BadRequest
17
17
  from ccxt.base.errors import NotSupported
18
18
  from ccxt.base.errors import ChecksumError
19
- from ccxt.base.errors import UnsubscribeError
20
19
  from ccxt.base.precise import Precise
21
20
 
22
21
 
@@ -1539,13 +1538,7 @@ class gate(ccxt.async_support.gate):
1539
1538
  for j in range(0, len(messageHashes)):
1540
1539
  unsubHash = messageHashes[j]
1541
1540
  subHash = subMessageHashes[j]
1542
- if unsubHash in client.subscriptions:
1543
- del client.subscriptions[unsubHash]
1544
- if subHash in client.subscriptions:
1545
- del client.subscriptions[subHash]
1546
- error = UnsubscribeError(self.id + ' ' + messageHash)
1547
- client.reject(error, subHash)
1548
- client.resolve(True, unsubHash)
1541
+ self.clean_unsubscription(client, subHash, unsubHash)
1549
1542
  self.clean_cache(subscription)
1550
1543
 
1551
1544
  def clean_cache(self, subscription: dict):
ccxt/pro/hyperliquid.py CHANGED
@@ -10,7 +10,6 @@ from ccxt.async_support.base.ws.client import Client
10
10
  from typing import List
11
11
  from typing import Any
12
12
  from ccxt.base.errors import ExchangeError
13
- from ccxt.base.errors import UnsubscribeError
14
13
 
15
14
 
16
15
  class hyperliquid(ccxt.async_support.hyperliquid):
@@ -805,13 +804,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
805
804
  symbol = self.safe_symbol(marketId)
806
805
  subMessageHash = 'orderbook:' + symbol
807
806
  messageHash = 'unsubscribe:' + subMessageHash
808
- if messageHash in client.subscriptions:
809
- del client.subscriptions[messageHash]
810
- if subMessageHash in client.subscriptions:
811
- del client.subscriptions[subMessageHash]
812
- error = UnsubscribeError(self.id + ' ' + subMessageHash)
813
- client.reject(error, subMessageHash)
814
- client.resolve(True, messageHash)
807
+ self.clean_unsubscription(client, subMessageHash, messageHash)
815
808
  if symbol in self.orderbooks:
816
809
  del self.orderbooks[symbol]
817
810
 
@@ -822,13 +815,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
822
815
  symbol = self.safe_symbol(marketId)
823
816
  subMessageHash = 'trade:' + symbol
824
817
  messageHash = 'unsubscribe:' + subMessageHash
825
- if messageHash in client.subscriptions:
826
- del client.subscriptions[messageHash]
827
- if subMessageHash in client.subscriptions:
828
- del client.subscriptions[subMessageHash]
829
- error = UnsubscribeError(self.id + ' ' + subMessageHash)
830
- client.reject(error, subMessageHash)
831
- client.resolve(True, messageHash)
818
+ self.clean_unsubscription(client, subMessageHash, messageHash)
832
819
  if symbol in self.trades:
833
820
  del self.trades[symbol]
834
821
 
@@ -836,13 +823,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
836
823
  #
837
824
  subMessageHash = 'tickers'
838
825
  messageHash = 'unsubscribe:' + subMessageHash
839
- if messageHash in client.subscriptions:
840
- del client.subscriptions[messageHash]
841
- if subMessageHash in client.subscriptions:
842
- del client.subscriptions[subMessageHash]
843
- error = UnsubscribeError(self.id + ' ' + subMessageHash)
844
- client.reject(error, subMessageHash)
845
- client.resolve(True, messageHash)
826
+ self.clean_unsubscription(client, subMessageHash, messageHash)
846
827
  symbols = list(self.tickers.keys())
847
828
  for i in range(0, len(symbols)):
848
829
  del self.tickers[symbols[i]]
@@ -855,13 +836,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
855
836
  timeframe = self.find_timeframe(interval)
856
837
  subMessageHash = 'candles:' + timeframe + ':' + symbol
857
838
  messageHash = 'unsubscribe:' + subMessageHash
858
- if messageHash in client.subscriptions:
859
- del client.subscriptions[messageHash]
860
- if subMessageHash in client.subscriptions:
861
- del client.subscriptions[subMessageHash]
862
- error = UnsubscribeError(self.id + ' ' + subMessageHash)
863
- client.reject(error, subMessageHash)
864
- client.resolve(True, messageHash)
839
+ self.clean_unsubscription(client, subMessageHash, messageHash)
865
840
  if symbol in self.ohlcvs:
866
841
  if timeframe in self.ohlcvs[symbol]:
867
842
  del self.ohlcvs[symbol][timeframe]