exchanges-wrapper 2.1.15__tar.gz → 2.1.17__tar.gz

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 (20) hide show
  1. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/PKG-INFO +1 -1
  2. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/__init__.py +1 -1
  3. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/client.py +10 -7
  4. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/exch_srv.py +1 -1
  5. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/parsers/okx_parser.py +1 -1
  6. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/web_sockets.py +23 -8
  7. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/LICENSE.md +0 -0
  8. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/README.md +0 -0
  9. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/definitions.py +0 -0
  10. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/errors.py +0 -0
  11. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/events.py +0 -0
  12. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/exch_srv_cfg.toml.template +0 -0
  13. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/http_client.py +0 -0
  14. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/lib.py +0 -0
  15. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/martin/__init__.py +0 -0
  16. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/parsers/bitfinex_parser.py +0 -0
  17. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/parsers/bybit_parser.py +0 -0
  18. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/parsers/huobi_parser.py +0 -0
  19. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/exchanges_wrapper/proto/martin.proto +0 -0
  20. {exchanges_wrapper-2.1.15 → exchanges_wrapper-2.1.17}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: exchanges-wrapper
3
- Version: 2.1.15
3
+ Version: 2.1.17
4
4
  Summary: REST API and WebSocket asyncio wrapper with grpc powered multiplexer server
5
5
  Author-email: Thomas Marchand <thomas.marchand@tuta.io>, Jerry Fedorenko <jerry.fedorenko@yahoo.com>
6
6
  Requires-Python: >=3.9
@@ -12,7 +12,7 @@ __maintainer__ = "Jerry Fedorenko"
12
12
  __contact__ = "https://github.com/DogsTailFarmer"
13
13
  __email__ = "jerry.fedorenko@yahoo.com"
14
14
  __credits__ = ["https://github.com/DanyaSWorlD"]
15
- __version__ = "2.1.15"
15
+ __version__ = "2.1.17"
16
16
 
17
17
  from pathlib import Path
18
18
  import shutil
@@ -354,13 +354,7 @@ class Client:
354
354
  server_time = await self.fetch_server_time()
355
355
  params = {'symbols': symbol.lower()}
356
356
  trading_symbol = await self.http.send_api_call("v1/settings/common/market-symbols", **params)
357
- if self.account_id is None:
358
- accounts = await self.http.send_api_call("v1/account/accounts", signed=True)
359
- for account in accounts:
360
- if account.get('type') == 'spot':
361
- self.account_id = account.get('id')
362
- break
363
- self.account_uid = await self.http.send_api_call("v2/user/uid", signed=True)
357
+ await self.set_htx_ids()
364
358
  binance_res = hbp.exchange_info(server_time.get('serverTime'), trading_symbol[0])
365
359
  elif self.exchange == 'okx':
366
360
  params = {'instType': 'SPOT'}
@@ -376,6 +370,15 @@ class Client:
376
370
  # logger.info(f"fetch_exchange_info: binance_res: {binance_res}")
377
371
  return binance_res
378
372
 
373
+ async def set_htx_ids(self):
374
+ if self.account_id is None:
375
+ accounts = await self.http.send_api_call("v1/account/accounts", signed=True)
376
+ for account in accounts:
377
+ if account.get('type') == 'spot':
378
+ self.account_id = account.get('id')
379
+ break
380
+ self.account_uid = await self.http.send_api_call("v2/user/uid", signed=True)
381
+
379
382
  # MARKET DATA ENDPOINTS
380
383
 
381
384
  # https://github.com/binance/binance-spot-api-docs/blob/master/rest-api.md#order-book
@@ -173,7 +173,7 @@ class Martin(mr.MartinBase):
173
173
  # For HuobiPro get master account uid and account_id
174
174
  main_account = get_account(open_client.client.master_name)
175
175
  main_client = Client(*main_account)
176
- await main_client.fetch_exchange_info(request.symbol)
176
+ await asyncio.wait_for(main_client.set_htx_ids(), timeout=HEARTBEAT * 60)
177
177
  if main_client.account_uid and main_client.account_id:
178
178
  open_client.client.main_account_uid = main_client.account_uid
179
179
  open_client.client.main_account_id = main_client.account_id
@@ -16,7 +16,7 @@ def fetch_server_time(res: []) -> {}:
16
16
  def exchange_info(server_time: int, trading_symbol: [], tickers: [], symbol_t) -> {}:
17
17
  symbols = []
18
18
  symbols_price = {
19
- pair.get('instId').replace('-', ''): Decimal(pair.get('last'))
19
+ pair.get('instId').replace('-', ''): Decimal(pair.get('last', '0'))
20
20
  for pair in tickers
21
21
  }
22
22
  for market in trading_symbol:
@@ -17,10 +17,7 @@ import exchanges_wrapper.parsers.bybit_parser as bbt
17
17
  from crypto_ws_api.ws_session import generate_signature
18
18
  from exchanges_wrapper import LOG_PATH
19
19
 
20
- logger = logging.getLogger('exch_srv_logger')
21
-
22
- logger_ws = logging.getLogger(__name__)
23
- logger_ws.level = logging.INFO
20
+ logger = logging.getLogger(__name__)
24
21
  formatter = logging.Formatter(fmt="[%(asctime)s: %(levelname)s] %(message)s")
25
22
  #
26
23
  fh = logging.handlers.RotatingFileHandler(Path(LOG_PATH, 'websockets.log'), maxBytes=1000000, backupCount=10)
@@ -31,8 +28,9 @@ sh = logging.StreamHandler()
31
28
  sh.setFormatter(formatter)
32
29
  sh.setLevel(logging.INFO)
33
30
 
34
- logger_ws.addHandler(fh)
35
- logger_ws.addHandler(sh)
31
+ logger.addHandler(fh)
32
+ logger.addHandler(sh)
33
+ logger.propagate = False
36
34
 
37
35
  sys.tracebacklimit = 0
38
36
 
@@ -50,12 +48,13 @@ class EventsDataStream:
50
48
  self._price = None
51
49
  self.tasks = set()
52
50
  self.wss_started = False
51
+ self.ping = 0
53
52
 
54
53
  async def start(self):
55
54
  ping_interval = None if self.exchange == 'huobi' else 20
56
55
  async for self.websocket in websockets.connect(
57
56
  self.endpoint,
58
- logger=logger_ws,
57
+ logger=logger,
59
58
  ping_interval=ping_interval
60
59
  ):
61
60
  try:
@@ -66,7 +65,7 @@ class EventsDataStream:
66
65
  logger.info(f"WSS closed for {self.exchange}:{self.trade_id}")
67
66
  break
68
67
  else:
69
- logger.warning(f"Restart WSS for {self.exchange}")
68
+ logger.warning(f"Restart WSS for {self.exchange}: {ex}")
70
69
  continue
71
70
  except Exception as ex:
72
71
  self.tasks_cancel()
@@ -187,9 +186,11 @@ class EventsDataStream:
187
186
  logger.debug(f"Bitfinex undefined WSS: symbol: {symbol}, ch_type: {ch_type}, msg_data: {msg_data}")
188
187
  elif self.exchange == 'huobi':
189
188
  if ping := msg_data.get('ping'):
189
+ self.ping = 0
190
190
  await self.websocket.send(json.dumps({"pong": ping}))
191
191
  await asyncio.sleep(0)
192
192
  elif msg_data.get('action') == 'ping':
193
+ self.ping = 0
193
194
  pong = {
194
195
  "action": "pong",
195
196
  "data": {
@@ -229,6 +230,17 @@ class EventsDataStream:
229
230
  await asyncio.sleep(interval)
230
231
  await self.websocket.send(json.dumps({"req_id": req_id, "op": "ping"}))
231
232
 
233
+ async def htx_keepalive(self, interval=60):
234
+ await asyncio.sleep(interval * 10)
235
+ while True:
236
+ await asyncio.sleep(interval)
237
+ if self.ping:
238
+ break
239
+ else:
240
+ self.ping = 1
241
+ logger.warning("From HTX server PING timeout exceeded")
242
+ await self.websocket.close()
243
+
232
244
 
233
245
  class MarketEventsDataStream(EventsDataStream):
234
246
  def __init__(self, client, endpoint, exchange, trade_id, channel=None):
@@ -300,6 +312,8 @@ class MarketEventsDataStream(EventsDataStream):
300
312
  elif ch_type == 'depth5':
301
313
  request = {'sub': f"market.{symbol}.depth.step0"}
302
314
 
315
+ self.tasks_manage(self.htx_keepalive(interval=30))
316
+
303
317
  await self.ws_listener(request, symbol, ch_type)
304
318
 
305
319
  async def _handle_event(self, content, symbol=None, ch_type=str()):
@@ -404,6 +418,7 @@ class HbpPrivateEventsDataStream(EventsDataStream):
404
418
  "action": "sub",
405
419
  "ch": f"trade.clearing#{self.symbol.lower()}#0"
406
420
  }
421
+ self.tasks_manage(self.htx_keepalive())
407
422
  await self.ws_listener(request, symbol=self.symbol)
408
423
 
409
424
  async def _handle_event(self, msg_data, *args):