gate-io-api 0.0.74__py3-none-any.whl → 0.0.100__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.

Potentially problematic release.


This version of gate-io-api might be problematic. Click here for more details.

@@ -2,7 +2,7 @@
2
2
 
3
3
  # -----------------------------------------------------------------------------
4
4
 
5
- __version__ = '4.4.95'
5
+ __version__ = '4.5.15'
6
6
 
7
7
  # -----------------------------------------------------------------------------
8
8
 
@@ -25,7 +25,7 @@ from ccxt.async_support.base.throttler import Throttler
25
25
  # -----------------------------------------------------------------------------
26
26
 
27
27
  from ccxt.base.errors import BaseError, BadSymbol, BadRequest, BadResponse, ExchangeError, ExchangeNotAvailable, RequestTimeout, NotSupported, NullResponse, InvalidAddress, RateLimitExceeded, OperationFailed
28
- from ccxt.base.types import ConstructorArgs, OrderType, OrderSide, OrderRequest, CancellationRequest
28
+ from ccxt.base.types import ConstructorArgs, OrderType, OrderSide, OrderRequest, CancellationRequest, Order
29
29
 
30
30
  # -----------------------------------------------------------------------------
31
31
 
@@ -54,6 +54,15 @@ __all__ = [
54
54
  ]
55
55
 
56
56
  # -----------------------------------------------------------------------------
57
+ # --- PROTO BUF IMPORTS
58
+ try:
59
+ from ccxt.protobuf.mexc import PushDataV3ApiWrapper_pb2
60
+ from google.protobuf.json_format import MessageToDict
61
+ except ImportError:
62
+ PushDataV3ApiWrapper_pb2 = None
63
+ MessageToDict = None
64
+
65
+ # -----------------------------------------------------------------------------
57
66
 
58
67
 
59
68
  class Exchange(BaseExchange):
@@ -176,7 +185,7 @@ class Exchange(BaseExchange):
176
185
  if (socksProxy not in self.socks_proxy_sessions):
177
186
  # Create our SSL context object with our CA cert file
178
187
  self.open() # ensure `asyncio_loop` is set
179
- proxy_session = self.get_socks_proxy_session(socksProxy)
188
+ proxy_session = self.get_socks_proxy_session(socksProxy)
180
189
  # add aiohttp_proxy for python as exclusion
181
190
  elif self.aiohttp_proxy:
182
191
  final_proxy = self.aiohttp_proxy
@@ -231,6 +240,8 @@ class Exchange(BaseExchange):
231
240
  self.last_json_response = json_response
232
241
  if self.verbose:
233
242
  self.log("\nfetch Response:", self.id, method, url, http_status_code, "ResponseHeaders:", headers, "ResponseBody:", http_response)
243
+ if json_response and not isinstance(json_response, list) and self.returnResponseHeaders:
244
+ json_response['responseHeaders'] = headers
234
245
  self.logger.debug("%s %s, Response: %s %s %s", method, url, http_status_code, headers, http_response)
235
246
 
236
247
  except socket.gaierror as e:
@@ -416,6 +427,7 @@ class Exchange(BaseExchange):
416
427
  'verbose': self.verbose,
417
428
  'throttle': Throttler(self.tokenBucket, self.asyncio_loop),
418
429
  'asyncio_loop': self.asyncio_loop,
430
+ 'decompressBinary': self.safe_bool(self.options, 'decompressBinary', True),
419
431
  }, ws_options)
420
432
  # we use aiohttp instead of fastClient now because of this
421
433
  # https://github.com/ccxt/ccxt/pull/25995
@@ -571,6 +583,31 @@ class Exchange(BaseExchange):
571
583
  return '0e-00'
572
584
  return format(n, 'g')
573
585
 
586
+ def decode_proto_msg(self, data):
587
+ if not MessageToDict:
588
+ raise NotSupported(self.id + ' requires protobuf to decode messages, please install it with `pip install "protobuf==5.29.5"`')
589
+ message = PushDataV3ApiWrapper_pb2.PushDataV3ApiWrapper()
590
+ message.ParseFromString(data)
591
+ dict_msg = MessageToDict(message)
592
+ # {
593
+ # "channel":"spot@public.kline.v3.api.pb@BTCUSDT@Min1",
594
+ # "symbol":"BTCUSDT",
595
+ # "symbolId":"2fb942154ef44a4ab2ef98c8afb6a4a7",
596
+ # "createTime":"1754735110559",
597
+ # "publicSpotKline":{
598
+ # "interval":"Min1",
599
+ # "windowStart":"1754735100",
600
+ # "openingPrice":"117792.45",
601
+ # "closingPrice":"117805.32",
602
+ # "highestPrice":"117814.63",
603
+ # "lowestPrice":"117792.45",
604
+ # "volume":"0.13425465",
605
+ # "amount":"15815.77",
606
+ # "windowEnd":"1754735160"
607
+ # }
608
+ # }
609
+ return dict_msg
610
+
574
611
  # ########################################################################
575
612
  # ########################################################################
576
613
  # ########################################################################
@@ -608,7 +645,7 @@ class Exchange(BaseExchange):
608
645
  # ########################################################################
609
646
  # ########################################################################
610
647
 
611
- # METHODS BELOW THIS LINE ARE TRANSPILED FROM JAVASCRIPT TO PYTHON AND PHP
648
+ # METHODS BELOW THIS LINE ARE TRANSPILED FROM TYPESCRIPT
612
649
 
613
650
  async def fetch_accounts(self, params={}):
614
651
  raise NotSupported(self.id + ' fetchAccounts() is not supported yet')
@@ -668,6 +705,18 @@ class Exchange(BaseExchange):
668
705
  async def un_watch_order_book_for_symbols(self, symbols: List[str], params={}):
669
706
  raise NotSupported(self.id + ' unWatchOrderBookForSymbols() is not supported yet')
670
707
 
708
+ async def un_watch_positions(self, symbols: Strings = None, params={}):
709
+ raise NotSupported(self.id + ' unWatchPositions() is not supported yet')
710
+
711
+ async def un_watch_ticker(self, symbol: str, params={}):
712
+ raise NotSupported(self.id + ' unWatchTicker() is not supported yet')
713
+
714
+ async def un_watch_mark_price(self, symbol: str, params={}):
715
+ raise NotSupported(self.id + ' unWatchMarkPrice() is not supported yet')
716
+
717
+ async def un_watch_mark_prices(self, symbols: Strings = None, params={}):
718
+ raise NotSupported(self.id + ' unWatchMarkPrices() is not supported yet')
719
+
671
720
  async def fetch_deposit_addresses(self, codes: Strings = None, params={}):
672
721
  raise NotSupported(self.id + ' fetchDepositAddresses() is not supported yet')
673
722
 
@@ -737,13 +786,13 @@ class Exchange(BaseExchange):
737
786
  async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}):
738
787
  raise NotSupported(self.id + ' transfer() is not supported yet')
739
788
 
740
- async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
789
+ async def withdraw(self, code: str, amount: float, address: str, tag: Str = None, params={}):
741
790
  raise NotSupported(self.id + ' withdraw() is not supported yet')
742
791
 
743
792
  async def create_deposit_address(self, code: str, params={}):
744
793
  raise NotSupported(self.id + ' createDepositAddress() is not supported yet')
745
794
 
746
- async def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
795
+ async def set_leverage(self, leverage: int, symbol: Str = None, params={}):
747
796
  raise NotSupported(self.id + ' setLeverage() is not supported yet')
748
797
 
749
798
  async def fetch_leverage(self, symbol: str, params={}):
@@ -792,7 +841,7 @@ class Exchange(BaseExchange):
792
841
  async def fetch_deposit_addresses_by_network(self, code: str, params={}):
793
842
  raise NotSupported(self.id + ' fetchDepositAddressesByNetwork() is not supported yet')
794
843
 
795
- async def fetch_open_interest_history(self, symbol: str, timeframe='1h', since: Int = None, limit: Int = None, params={}):
844
+ async def fetch_open_interest_history(self, symbol: str, timeframe: str = '1h', since: Int = None, limit: Int = None, params={}):
796
845
  raise NotSupported(self.id + ' fetchOpenInterestHistory() is not supported yet')
797
846
 
798
847
  async def fetch_open_interest(self, symbol: str, params={}):
@@ -828,19 +877,19 @@ class Exchange(BaseExchange):
828
877
  async def repay_margin(self, code: str, amount: float, symbol: Str = None, params={}):
829
878
  raise NotSupported(self.id + ' repayMargin is deprecated, please use repayCrossMargin or repayIsolatedMargin instead')
830
879
 
831
- async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
880
+ async def fetch_ohlcv(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}):
832
881
  message = ''
833
882
  if self.has['fetchTrades']:
834
883
  message = '. If you want to build OHLCV candles from trade executions data, visit https://github.com/ccxt/ccxt/tree/master/examples/ and see "build-ohlcv-bars" file'
835
884
  raise NotSupported(self.id + ' fetchOHLCV() is not supported yet' + message)
836
885
 
837
- async def fetch_ohlcv_ws(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
886
+ async def fetch_ohlcv_ws(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}):
838
887
  message = ''
839
888
  if self.has['fetchTradesWs']:
840
889
  message = '. If you want to build OHLCV candles from trade executions data, visit https://github.com/ccxt/ccxt/tree/master/examples/ and see "build-ohlcv-bars" file'
841
890
  raise NotSupported(self.id + ' fetchOHLCVWs() is not supported yet. Try using fetchOHLCV instead.' + message)
842
891
 
843
- async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
892
+ async def watch_ohlcv(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}):
844
893
  raise NotSupported(self.id + ' watchOHLCV() is not supported yet')
845
894
 
846
895
  async def fetch_web_endpoint(self, method, endpointMethod, returnAsJson, startRegex=None, endRegex=None):
@@ -1177,7 +1226,7 @@ class Exchange(BaseExchange):
1177
1226
  async def fetch_position_mode(self, symbol: Str = None, params={}):
1178
1227
  raise NotSupported(self.id + ' fetchPositionMode() is not supported yet')
1179
1228
 
1180
- async def create_trailing_amount_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingAmount=None, trailingTriggerPrice=None, params={}):
1229
+ async def create_trailing_amount_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingAmount: Num = None, trailingTriggerPrice: Num = None, params={}):
1181
1230
  """
1182
1231
  create a trailing order by providing the symbol, type, side, amount, price and trailingAmount
1183
1232
  :param str symbol: unified symbol of the market to create an order in
@@ -1199,7 +1248,7 @@ class Exchange(BaseExchange):
1199
1248
  return await self.create_order(symbol, type, side, amount, price, params)
1200
1249
  raise NotSupported(self.id + ' createTrailingAmountOrder() is not supported yet')
1201
1250
 
1202
- async def create_trailing_amount_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingAmount=None, trailingTriggerPrice=None, params={}):
1251
+ async def create_trailing_amount_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingAmount: Num = None, trailingTriggerPrice: Num = None, params={}):
1203
1252
  """
1204
1253
  create a trailing order by providing the symbol, type, side, amount, price and trailingAmount
1205
1254
  :param str symbol: unified symbol of the market to create an order in
@@ -1221,7 +1270,7 @@ class Exchange(BaseExchange):
1221
1270
  return await self.create_order_ws(symbol, type, side, amount, price, params)
1222
1271
  raise NotSupported(self.id + ' createTrailingAmountOrderWs() is not supported yet')
1223
1272
 
1224
- async def create_trailing_percent_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingPercent=None, trailingTriggerPrice=None, params={}):
1273
+ async def create_trailing_percent_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingPercent: Num = None, trailingTriggerPrice: Num = None, params={}):
1225
1274
  """
1226
1275
  create a trailing order by providing the symbol, type, side, amount, price and trailingPercent
1227
1276
  :param str symbol: unified symbol of the market to create an order in
@@ -1243,7 +1292,7 @@ class Exchange(BaseExchange):
1243
1292
  return await self.create_order(symbol, type, side, amount, price, params)
1244
1293
  raise NotSupported(self.id + ' createTrailingPercentOrder() is not supported yet')
1245
1294
 
1246
- async def create_trailing_percent_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingPercent=None, trailingTriggerPrice=None, params={}):
1295
+ async def create_trailing_percent_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingPercent: Num = None, trailingTriggerPrice: Num = None, params={}):
1247
1296
  """
1248
1297
  create a trailing order by providing the symbol, type, side, amount, price and trailingPercent
1249
1298
  :param str symbol: unified symbol of the market to create an order in
@@ -1496,6 +1545,9 @@ class Exchange(BaseExchange):
1496
1545
  async def cancel_order_ws(self, id: str, symbol: Str = None, params={}):
1497
1546
  raise NotSupported(self.id + ' cancelOrderWs() is not supported yet')
1498
1547
 
1548
+ async def cancel_orders(self, ids: List[str], symbol: Str = None, params={}):
1549
+ raise NotSupported(self.id + ' cancelOrders() is not supported yet')
1550
+
1499
1551
  async def cancel_orders_ws(self, ids: List[str], symbol: Str = None, params={}):
1500
1552
  raise NotSupported(self.id + ' cancelOrdersWs() is not supported yet')
1501
1553
 
@@ -1511,7 +1563,7 @@ class Exchange(BaseExchange):
1511
1563
  async def cancel_all_orders_ws(self, symbol: Str = None, params={}):
1512
1564
  raise NotSupported(self.id + ' cancelAllOrdersWs() is not supported yet')
1513
1565
 
1514
- async def cancel_unified_order(self, order, params={}):
1566
+ async def cancel_unified_order(self, order: Order, params={}):
1515
1567
  return self.cancel_order(self.safe_string(order, 'id'), self.safe_string(order, 'symbol'), params)
1516
1568
 
1517
1569
  async def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
@@ -1596,10 +1648,10 @@ class Exchange(BaseExchange):
1596
1648
  """
1597
1649
  raise NotSupported(self.id + ' fetchDepositsWithdrawals() is not supported yet')
1598
1650
 
1599
- async def fetch_deposits(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1651
+ async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
1600
1652
  raise NotSupported(self.id + ' fetchDeposits() is not supported yet')
1601
1653
 
1602
- async def fetch_withdrawals(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1654
+ async def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
1603
1655
  raise NotSupported(self.id + ' fetchWithdrawals() is not supported yet')
1604
1656
 
1605
1657
  async def fetch_deposits_ws(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
@@ -1810,7 +1862,7 @@ class Exchange(BaseExchange):
1810
1862
  else:
1811
1863
  raise NotSupported(self.id + ' fetchFundingInterval() is not supported yet')
1812
1864
 
1813
- async def fetch_mark_ohlcv(self, symbol, timeframe='1m', since: Int = None, limit: Int = None, params={}):
1865
+ async def fetch_mark_ohlcv(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}):
1814
1866
  """
1815
1867
  fetches historical mark price candlestick data containing the open, high, low, and close price of a market
1816
1868
  :param str symbol: unified symbol of the market to fetch OHLCV data for
@@ -1828,7 +1880,7 @@ class Exchange(BaseExchange):
1828
1880
  else:
1829
1881
  raise NotSupported(self.id + ' fetchMarkOHLCV() is not supported yet')
1830
1882
 
1831
- async def fetch_index_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
1883
+ async def fetch_index_ohlcv(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}):
1832
1884
  """
1833
1885
  fetches historical index price candlestick data containing the open, high, low, and close price of a market
1834
1886
  :param str symbol: unified symbol of the market to fetch OHLCV data for
@@ -1846,7 +1898,7 @@ class Exchange(BaseExchange):
1846
1898
  else:
1847
1899
  raise NotSupported(self.id + ' fetchIndexOHLCV() is not supported yet')
1848
1900
 
1849
- async def fetch_premium_index_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
1901
+ async def fetch_premium_index_ohlcv(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}):
1850
1902
  """
1851
1903
  fetches historical premium index price candlestick data containing the open, high, low, and close price of a market
1852
1904
  :param str symbol: unified symbol of the market to fetch OHLCV data for
@@ -1892,7 +1944,7 @@ class Exchange(BaseExchange):
1892
1944
  calls = 0
1893
1945
  result = []
1894
1946
  errors = 0
1895
- until = self.safe_integer_2(params, 'untill', 'till') # do not omit it from params here
1947
+ until = self.safe_integer_n(params, ['until', 'untill', 'till']) # do not omit it from params here
1896
1948
  maxEntriesPerRequest, params = self.handle_max_entries_per_request_and_params(method, maxEntriesPerRequest, params)
1897
1949
  if (paginationDirection == 'forward'):
1898
1950
  if since is None:
@@ -2138,3 +2190,80 @@ class Exchange(BaseExchange):
2138
2190
  :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
2139
2191
  """
2140
2192
  raise NotSupported(self.id + ' fetchTransfers() is not supported yet')
2193
+
2194
+ async def un_watch_ohlcv(self, symbol: str, timeframe: str = '1m', params={}):
2195
+ """
2196
+ watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
2197
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
2198
+ :param str timeframe: the length of time each candle represents
2199
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2200
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
2201
+ """
2202
+ raise NotSupported(self.id + ' unWatchOHLCV() is not supported yet')
2203
+
2204
+ async def watch_mark_price(self, symbol: str, params={}):
2205
+ """
2206
+ watches a mark price for a specific market
2207
+ :param str symbol: unified symbol of the market to fetch the ticker for
2208
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2209
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
2210
+ """
2211
+ raise NotSupported(self.id + ' watchMarkPrice() is not supported yet')
2212
+
2213
+ async def watch_mark_prices(self, symbols: Strings = None, params={}):
2214
+ """
2215
+ watches the mark price for all markets
2216
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
2217
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2218
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
2219
+ """
2220
+ raise NotSupported(self.id + ' watchMarkPrices() is not supported yet')
2221
+
2222
+ async def withdraw_ws(self, code: str, amount: float, address: str, tag: Str = None, params={}):
2223
+ """
2224
+ make a withdrawal
2225
+ :param str code: unified currency code
2226
+ :param float amount: the amount to withdraw
2227
+ :param str address: the address to withdraw to
2228
+ :param str tag:
2229
+ :param dict [params]: extra parameters specific to the bitvavo api endpoint
2230
+ :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2231
+ """
2232
+ raise NotSupported(self.id + ' withdrawWs() is not supported yet')
2233
+
2234
+ async def un_watch_my_trades(self, symbol: Str = None, params={}):
2235
+ """
2236
+ unWatches information on multiple trades made by the user
2237
+ :param str symbol: unified market symbol of the market orders were made in
2238
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2239
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2240
+ """
2241
+ raise NotSupported(self.id + ' unWatchMyTrades() is not supported yet')
2242
+
2243
+ async def create_orders_ws(self, orders: List[OrderRequest], params={}):
2244
+ """
2245
+ create a list of trade orders
2246
+ :param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
2247
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2248
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2249
+ """
2250
+ raise NotSupported(self.id + ' createOrdersWs() is not supported yet')
2251
+
2252
+ async def fetch_orders_by_status_ws(self, status: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2253
+ """
2254
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
2255
+ :param str symbol: unified symbol of the market to fetch the order book for
2256
+ :param int [limit]: the maximum amount of order book entries to return
2257
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2258
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
2259
+ """
2260
+ raise NotSupported(self.id + ' fetchOrdersByStatusWs() is not supported yet')
2261
+
2262
+ async def un_watch_bids_asks(self, symbols: Strings = None, params={}):
2263
+ """
2264
+ unWatches best bid & ask for symbols
2265
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
2266
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2267
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
2268
+ """
2269
+ raise NotSupported(self.id + ' unWatchBidsAsks() is not supported yet')
@@ -42,7 +42,7 @@ class Throttler:
42
42
  def __call__(self, cost=None):
43
43
  future = asyncio.Future()
44
44
  if len(self.queue) > self.config['maxCapacity']:
45
- raise RuntimeError('throttle queue is over maxCapacity (' + str(int(self.config['maxCapacity'])) + '), see https://github.com/ccxt/ccxt/issues/11645#issuecomment-1195695526')
45
+ raise RuntimeError('throttle queue is over maxCapacity (' + str(int(self.config['maxCapacity'])) + '), see https://docs.ccxt.com/#/README?id=maximum-requests-capacity')
46
46
  self.queue.append((future, cost))
47
47
  if not self.running:
48
48
  self.running = True
@@ -50,6 +50,7 @@ class Client(object):
50
50
  connecting = False
51
51
  asyncio_loop: BaseEventLoop = None
52
52
  ping_looper = None
53
+ decompressBinary = True # decompress binary messages by default
53
54
 
54
55
  def __init__(self, url, on_message_callback, on_error_callback, on_close_callback, on_connected_callback, config={}):
55
56
  defaults = {
@@ -82,6 +83,12 @@ class Client(object):
82
83
  del self.rejections[message_hash]
83
84
  return future
84
85
 
86
+ def reusable_future(self, message_hash):
87
+ return self.future(message_hash) # only used in go
88
+
89
+ def reusableFuture(self, message_hash):
90
+ return self.future(message_hash) # only used in go
91
+
85
92
  def resolve(self, result, message_hash):
86
93
  if self.verbose and message_hash is None:
87
94
  self.log(iso8601(milliseconds()), 'resolve received None messageHash')
@@ -110,7 +117,7 @@ class Client(object):
110
117
  self.log(iso8601(milliseconds()), 'receive loop')
111
118
  if not self.closed():
112
119
  # let's drain the aiohttp buffer to avoid latency
113
- if len(self.buffer) > 1:
120
+ if self.buffer and len(self.buffer) > 1:
114
121
  size_delta = 0
115
122
  while len(self.buffer) > 1:
116
123
  message, size = self.buffer.popleft()
@@ -179,6 +186,16 @@ class Client(object):
179
186
  # looks like they exposed it in C
180
187
  # this means we can bypass it
181
188
  # https://github.com/aio-libs/aiohttp/blob/master/aiohttp/_websocket/reader_c.pxd#L53C24-L53C31
189
+ # these checks are necessary to protect these errors: AttributeError: 'NoneType' object has no attribute '_buffer'
190
+ # upon getting an error message
191
+ if self.connection is None:
192
+ return None
193
+ if self.connection._conn is None:
194
+ return None
195
+ if self.connection._conn.protocol is None:
196
+ return None
197
+ if self.connection._conn.protocol._payload is None:
198
+ return None
182
199
  return self.connection._conn.protocol._payload._buffer
183
200
 
184
201
  def connect(self, session, backoff_delay=0):
@@ -218,7 +235,8 @@ class Client(object):
218
235
  if self.verbose:
219
236
  self.log(iso8601(milliseconds()), 'message', data)
220
237
  if isinstance(data, bytes):
221
- data = data.decode()
238
+ if self.decompressBinary:
239
+ data = data.decode()
222
240
  # decoded = json.loads(data) if is_json_encoded_object(data) else data
223
241
  decode = None
224
242
  if is_json_encoded_object(data):
@@ -1,6 +1,8 @@
1
1
  import asyncio
2
2
 
3
-
3
+ # Test by running:
4
+ # - python python/ccxt/pro/test/base/test_close.py
5
+ # - python python/ccxt/pro/test/base/test_future.py
4
6
  class Future(asyncio.Future):
5
7
 
6
8
  def resolve(self, result=None):
@@ -30,14 +32,14 @@ class Future(asyncio.Future):
30
32
  if err:
31
33
  exceptions.append(err)
32
34
  # if any exceptions return with first exception
35
+ if future.cancelled():
36
+ return
33
37
  if len(exceptions) > 0:
34
38
  future.set_exception(exceptions[0])
35
39
  # else return first result
36
40
  elif cancelled:
37
41
  future.cancel()
38
42
  else:
39
- if future.cancelled():
40
- return
41
43
  first_result = list(complete)[0].result()
42
44
  future.set_result(first_result)
43
45
  task.add_done_callback(callback)