exchanges-wrapper 1.3.6.post1.dev1__tar.gz → 1.3.7.post1__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 (31) hide show
  1. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/PKG-INFO +5 -4
  2. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/__init__.py +1 -1
  3. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/c_structures.py +6 -0
  4. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/client.py +21 -27
  5. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/exch_srv.py +104 -172
  6. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/http_client.py +10 -0
  7. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/huobi_parser.py +1 -1
  8. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/web_sockets.py +149 -166
  9. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/pyproject.toml +4 -3
  10. exchanges-wrapper-1.3.6.post1.dev1/.deepsource.toml +0 -12
  11. exchanges-wrapper-1.3.6.post1.dev1/.dockerignore +0 -3
  12. exchanges-wrapper-1.3.6.post1.dev1/.github/FUNDING.yml +0 -1
  13. exchanges-wrapper-1.3.6.post1.dev1/.github/dependabot.yml +0 -11
  14. exchanges-wrapper-1.3.6.post1.dev1/.github/workflows/docker-image.yml +0 -32
  15. exchanges-wrapper-1.3.6.post1.dev1/.github/workflows/python-publish.yml +0 -40
  16. exchanges-wrapper-1.3.6.post1.dev1/CHANGELOG.md +0 -289
  17. exchanges-wrapper-1.3.6.post1.dev1/Dockerfile +0 -23
  18. exchanges-wrapper-1.3.6.post1.dev1/example/exch_client.py +0 -415
  19. exchanges-wrapper-1.3.6.post1.dev1/example/ms_cfg.toml +0 -5
  20. exchanges-wrapper-1.3.6.post1.dev1/requirements.txt +0 -6
  21. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/LICENSE.md +0 -0
  22. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/README.md +0 -0
  23. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/api_pb2.py +0 -0
  24. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/api_pb2_grpc.py +0 -0
  25. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/bitfinex_parser.py +0 -0
  26. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/definitions.py +0 -0
  27. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/errors.py +0 -0
  28. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/events.py +0 -0
  29. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/exch_srv_cfg.toml.template +0 -0
  30. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/okx_parser.py +0 -0
  31. {exchanges-wrapper-1.3.6.post1.dev1 → exchanges_wrapper-1.3.7.post1}/exchanges_wrapper/proto/exchanges_wrapper/api.proto +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: exchanges-wrapper
3
- Version: 1.3.6.post1.dev1
3
+ Version: 1.3.7.post1
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.8
@@ -11,12 +11,13 @@ Classifier: License :: OSI Approved :: MIT License
11
11
  Classifier: Operating System :: Unix
12
12
  Classifier: Operating System :: Microsoft :: Windows
13
13
  Classifier: Operating System :: MacOS
14
- Requires-Dist: crypto-ws-api==2.0.1
15
- Requires-Dist: grpcio==1.57.0
16
- Requires-Dist: grpcio-tools==1.57.0
14
+ Requires-Dist: crypto-ws-api==2.0.2.post1
15
+ Requires-Dist: grpcio==1.48.2
16
+ Requires-Dist: grpcio-tools==1.48.2
17
17
  Requires-Dist: idna==3.4
18
18
  Requires-Dist: pyotp~=2.9.0
19
19
  Requires-Dist: simplejson==3.19.1
20
+ Requires-Dist: websockets~=11.0.3
20
21
  Project-URL: Source, https://github.com/DogsTailFarmer/exchanges-wrapper
21
22
 
22
23
  <h1 align="center"><img align="center" src="https://raw.githubusercontent.com/gist/DogsTailFarmer/167eaf65cebfe95d954082c7f181a2cc/raw/a67270de8663ad3de4733330ff64c9ba3153f87d/Logo%202v3.svg" width="75">Crypto exchanges API/WSS wrapper with grpc powered server</h1>
@@ -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__ = "1.3.6-1.dev1"
15
+ __version__ = "1.3.7.post1"
16
16
 
17
17
  from pathlib import Path
18
18
  import shutil
@@ -1,5 +1,11 @@
1
1
  from decimal import Decimal
2
2
 
3
+ REST_RATE_LIMIT_INTERVAL = {
4
+ "bitfinex": {
5
+ "default": 0.6667, # 90 requests per minute
6
+ },
7
+ }
8
+
3
9
 
4
10
  class OrderUpdateEvent:
5
11
  def __init__(self, event_data: {}):
@@ -26,7 +26,7 @@ from crypto_ws_api.ws_session import UserWSSession
26
26
 
27
27
  logger = logging.getLogger(__name__)
28
28
 
29
- STATUS_TIMEOUT = 5 # sec
29
+ STATUS_TIMEOUT = 5 # sec, also use for lifetime limit for inactive order (Bitfinex) as 60 * STATUS_TIMEOUT
30
30
 
31
31
 
32
32
  def truncate(f, n):
@@ -64,7 +64,6 @@ class Client:
64
64
  }
65
65
  if self.exchange in ('binance', 'okx', 'bitfinex'):
66
66
  self.user_wss_session = UserWSSession(
67
- self.session,
68
67
  self.exchange,
69
68
  self.endpoint_ws_api,
70
69
  self.api_key,
@@ -136,7 +135,7 @@ class Client:
136
135
  logger.info(f"Start '{self.exchange}' user events listener for {_trade_id}")
137
136
  user_data_stream = None
138
137
  if self.exchange == 'binance':
139
- user_data_stream = UserEventsDataStream(self, self.endpoint_ws_auth, self.exchange, _trade_id)
138
+ user_data_stream = await UserEventsDataStream(self, self.endpoint_ws_auth, self.exchange, _trade_id)
140
139
  elif self.exchange == 'bitfinex':
141
140
  user_data_stream = BfxPrivateEventsDataStream(self, self.endpoint_ws_auth, self.exchange, _trade_id)
142
141
  elif self.exchange == 'huobi':
@@ -149,15 +148,17 @@ class Client:
149
148
  self.symbol_to_okx(symbol))
150
149
  if user_data_stream:
151
150
  self.data_streams[_trade_id] |= {user_data_stream}
152
- await user_data_stream.start()
151
+ await asyncio.sleep(1)
152
+ asyncio.ensure_future(user_data_stream.start())
153
153
 
154
154
  async def start_market_events_listener(self, _trade_id):
155
155
  _events = self.events.registered_streams.get(self.exchange, {}).get(_trade_id, set())
156
- start_list = []
157
156
  if self.exchange == 'binance':
158
157
  market_data_stream = MarketEventsDataStream(self, self.endpoint_ws_public, self.exchange, _trade_id)
159
158
  self.data_streams[_trade_id] |= {market_data_stream}
160
- start_list.append(market_data_stream.start())
159
+ await asyncio.sleep(1)
160
+ asyncio.ensure_future(market_data_stream.start())
161
+ # start_list.append(market_data_stream.start())
161
162
  else:
162
163
  for channel in _events:
163
164
  # https://www.okx.com/help-center/changes-to-v5-api-websocket-subscription-parameter-and-url
@@ -166,13 +167,10 @@ class Client:
166
167
  else:
167
168
  _endpoint = self.endpoint_ws_public
168
169
  #
169
- market_data_stream = MarketEventsDataStream(self,
170
- _endpoint,
171
- self.exchange, _trade_id,
172
- channel)
170
+ market_data_stream = MarketEventsDataStream(self, _endpoint, self.exchange, _trade_id, channel)
173
171
  self.data_streams[_trade_id] |= {market_data_stream}
174
- start_list.append(market_data_stream.start())
175
- await asyncio.gather(*start_list, return_exceptions=True)
172
+ await asyncio.sleep(1)
173
+ asyncio.ensure_future(market_data_stream.start())
176
174
 
177
175
  async def stop_events_listener(self, _trade_id):
178
176
  logger.info(f"Stop events listener data streams for {_trade_id}")
@@ -201,11 +199,10 @@ class Client:
201
199
  return f"{symbol_info.get('baseAsset')}-{symbol_info.get('quoteAsset')}"
202
200
 
203
201
  def active_orders_clear(self, active_orders: list = None):
204
- limit_time = int(time.time())
205
- self.active_orders = {key: val for key, val in self.active_orders.items()
206
- if not val['filledTime'] or val['filledTime'] > limit_time}
207
- for order_id in set(self.active_orders.keys()).difference(set(active_orders)):
208
- self.active_orders[order_id]['filledTime'] = limit_time + 60 * 30
202
+ ts = int(time.time())
203
+ self.active_orders = {key: val for key, val in self.active_orders.items() if val['lifeTime'] > ts}
204
+ for order_id in active_orders:
205
+ self.active_orders[order_id]['lifeTime'] = ts + 60 * STATUS_TIMEOUT
209
206
 
210
207
  def refine_amount(self, symbol, amount: Union[str, decimal.Decimal], quote=False):
211
208
  if type(amount) is str: # to save time for developers
@@ -726,16 +723,13 @@ class Client:
726
723
  ahead_ws = self.wss_buffer.pop(order_id, [])
727
724
  logger.debug(f"create_order.ahead_ws: {ahead_ws}")
728
725
  binance_res = bfx.order(res[4][0], response_type=False, wss_te=ahead_ws)
729
- self.active_orders.update(
730
- {order_id:
731
- {'filledTime': int(),
732
- 'origQty': quantity,
733
- 'executedQty': "0",
734
- 'lastEvent': (),
735
- 'cancelled': False
736
- }
737
- }
738
- )
726
+ self.active_orders[order_id] = {
727
+ 'lifeTime': int(time.time()) + 60 * STATUS_TIMEOUT,
728
+ 'origQty': quantity,
729
+ 'executedQty': "0",
730
+ 'lastEvent': (),
731
+ 'cancelled': False
732
+ }
739
733
  elif self.exchange == 'huobi':
740
734
  params = {
741
735
  'account-id': str(self.hbp_account_id),