exchanges-wrapper 1.4.2__tar.gz → 1.4.4__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 (21) hide show
  1. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/PKG-INFO +1 -1
  2. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/__init__.py +1 -1
  3. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/exch_srv.py +61 -34
  4. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/LICENSE.md +0 -0
  5. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/README.md +0 -0
  6. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/api_pb2.py +0 -0
  7. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/api_pb2_grpc.py +0 -0
  8. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/bitfinex_parser.py +0 -0
  9. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/bybit_parser.py +0 -0
  10. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/c_structures.py +0 -0
  11. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/client.py +0 -0
  12. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/definitions.py +0 -0
  13. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/errors.py +0 -0
  14. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/events.py +0 -0
  15. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/exch_srv_cfg.toml.template +0 -0
  16. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/http_client.py +0 -0
  17. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/huobi_parser.py +0 -0
  18. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/okx_parser.py +0 -0
  19. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/proto/exchanges_wrapper/api.proto +0 -0
  20. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/exchanges_wrapper/web_sockets.py +0 -0
  21. {exchanges_wrapper-1.4.2 → exchanges_wrapper-1.4.4}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: exchanges-wrapper
3
- Version: 1.4.2
3
+ Version: 1.4.4
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
@@ -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.4.2"
15
+ __version__ = "1.4.4"
16
16
 
17
17
  from pathlib import Path
18
18
  import shutil
@@ -268,7 +268,7 @@ class Martin(api_pb2_grpc.MartinServicer):
268
268
  for order in res:
269
269
  order_id = order['orderId']
270
270
  active_orders.append(order_id)
271
- new_order = json_format.ParseDict(order, response_order)
271
+ new_order = json_format.ParseDict(order, response_order, ignore_unknown_fields=True)
272
272
  # logger.debug(f"FetchOpenOrders.new_order: {new_order}")
273
273
  response.items.append(new_order)
274
274
  if client.exchange == 'bitfinex':
@@ -316,20 +316,23 @@ class Martin(api_pb2_grpc.MartinServicer):
316
316
  f"{event.order_status}")
317
317
  await _queue.put(weakref.ref(event)())
318
318
  elif res.get('status') == 'PARTIALLY_FILLED':
319
- try:
320
- trades = await client.fetch_order_trade_list(request.trade_id, request.symbol, request.order_id)
321
- except asyncio.CancelledError:
322
- pass # Task cancellation should not be logged as an error
323
- except Exception as _ex:
324
- logger.error(f"Fetch order trades for {open_client.name}: {request.symbol} exception: {_ex}")
325
- else:
326
- logger.debug(f"FetchOrder.trades: {trades}")
327
- for trade in trades:
328
- event = OrderTradesEvent(trade)
329
- await _queue.put(weakref.ref(event)())
330
- json_format.ParseDict(res, response)
319
+ await self.create_trade_stream_event(_queue, client, open_client, request)
320
+ json_format.ParseDict(res, response, ignore_unknown_fields=True)
331
321
  return response
332
322
 
323
+ async def create_trade_stream_event(self, _queue, client, open_client, request):
324
+ try:
325
+ trades = await client.fetch_order_trade_list(request.trade_id, request.symbol, request.order_id)
326
+ except asyncio.CancelledError:
327
+ pass # Task cancellation should not be logged as an error
328
+ except Exception as _ex:
329
+ logger.error(f"Fetch order trades for {open_client.name}: {request.symbol} exception: {_ex}")
330
+ else:
331
+ logger.debug(f"FetchOrder.trades: {trades}")
332
+ for trade in trades:
333
+ event = OrderTradesEvent(trade)
334
+ await _queue.put(weakref.ref(event)())
335
+
333
336
  async def CancelAllOrders(self, request: api_pb2.MarketRequest,
334
337
  _context: grpc.aio.ServicerContext) -> api_pb2.SimpleResponse():
335
338
  open_client = OpenClient.get_client(request.client_id)
@@ -360,51 +363,71 @@ class Martin(api_pb2_grpc.MartinServicer):
360
363
  else:
361
364
  raise UserWarning(f"Symbol {request.symbol} not exist")
362
365
  await self.rate_limit_control(open_client)
363
- # logger.info(f"exchange_info_symbol: {exchange_info_symbol}")
366
+ # logger.debug(f"exchange_info_symbol: {exchange_info_symbol}")
364
367
  open_client.ts_rlc = time.time()
365
368
  filters_res = exchange_info_symbol.pop('filters', [])
366
- json_format.ParseDict(exchange_info_symbol, response)
369
+ json_format.ParseDict(exchange_info_symbol, response, ignore_unknown_fields=True)
367
370
  # logger.info(f"filters: {filters_res}")
368
371
  filters = response.filters
369
372
  for _filter in filters_res:
370
373
  filter_type = _filter.get('filterType')
371
374
  if filter_type == 'PRICE_FILTER':
372
375
  new_filter_template = api_pb2.FetchExchangeInfoSymbolResponse.Filters.PriceFilter()
373
- filters.price_filter.CopyFrom(json_format.ParseDict(_filter, new_filter_template))
376
+ filters.price_filter.CopyFrom(
377
+ json_format.ParseDict(_filter, new_filter_template, ignore_unknown_fields=True)
378
+ )
374
379
  elif 'PERCENT_PRICE' in filter_type:
375
380
  if filter_type == 'PERCENT_PRICE_BY_SIDE':
376
- _filter['multiplierUp'] = _filter['bidMultiplierUp']
381
+ _filter['multiplierUp'] = _filter['askMultiplierUp']
377
382
  _filter['multiplierDown'] = _filter['bidMultiplierDown']
378
383
  del _filter['bidMultiplierUp']
379
384
  del _filter['bidMultiplierDown']
380
385
  del _filter['askMultiplierUp']
381
386
  del _filter['askMultiplierDown']
382
387
  new_filter_template = api_pb2.FetchExchangeInfoSymbolResponse.Filters.PercentPrice()
383
- filters.percent_price.CopyFrom(json_format.ParseDict(_filter, new_filter_template))
388
+ filters.percent_price.CopyFrom(
389
+ json_format.ParseDict(_filter, new_filter_template, ignore_unknown_fields=True)
390
+ )
384
391
  elif filter_type == 'LOT_SIZE':
385
392
  new_filter_template = api_pb2.FetchExchangeInfoSymbolResponse.Filters.LotSize()
386
- filters.lot_size.CopyFrom(json_format.ParseDict(_filter, new_filter_template))
393
+ filters.lot_size.CopyFrom(
394
+ json_format.ParseDict(_filter, new_filter_template, ignore_unknown_fields=True)
395
+ )
387
396
  elif filter_type == 'MIN_NOTIONAL':
388
397
  new_filter_template = api_pb2.FetchExchangeInfoSymbolResponse.Filters.MinNotional()
389
- filters.min_notional.CopyFrom(json_format.ParseDict(_filter, new_filter_template))
398
+ filters.min_notional.CopyFrom(
399
+ json_format.ParseDict(_filter, new_filter_template, ignore_unknown_fields=True)
400
+ )
390
401
  elif filter_type == 'NOTIONAL':
391
402
  new_filter_template = api_pb2.FetchExchangeInfoSymbolResponse.Filters.Notional()
392
- filters.notional.CopyFrom(json_format.ParseDict(_filter, new_filter_template))
403
+ filters.notional.CopyFrom(
404
+ json_format.ParseDict(_filter, new_filter_template, ignore_unknown_fields=True)
405
+ )
393
406
  elif filter_type == 'ICEBERG_PARTS':
394
407
  new_filter_template = api_pb2.FetchExchangeInfoSymbolResponse.Filters.IcebergParts()
395
- filters.iceberg_parts.CopyFrom(json_format.ParseDict(_filter, new_filter_template))
408
+ filters.iceberg_parts.CopyFrom(
409
+ json_format.ParseDict(_filter, new_filter_template, ignore_unknown_fields=True)
410
+ )
396
411
  elif filter_type == 'MARKET_LOT_SIZE':
397
412
  new_filter_template = api_pb2.FetchExchangeInfoSymbolResponse.Filters.MarketLotSize()
398
- filters.market_lot_size.CopyFrom(json_format.ParseDict(_filter, new_filter_template))
413
+ filters.market_lot_size.CopyFrom(
414
+ json_format.ParseDict(_filter, new_filter_template, ignore_unknown_fields=True)
415
+ )
399
416
  elif filter_type == 'MAX_NUM_ORDERS':
400
417
  new_filter_template = api_pb2.FetchExchangeInfoSymbolResponse.Filters.MaxNumOrders()
401
- filters.max_num_orders.CopyFrom(json_format.ParseDict(_filter, new_filter_template))
418
+ filters.max_num_orders.CopyFrom(
419
+ json_format.ParseDict(_filter, new_filter_template, ignore_unknown_fields=True)
420
+ )
402
421
  elif filter_type == 'MAX_NUM_ICEBERG_ORDERS':
403
422
  new_filter_template = api_pb2.FetchExchangeInfoSymbolResponse.Filters.MaxNumIcebergOrders()
404
- filters.max_num_iceberg_orders.CopyFrom(json_format.ParseDict(_filter, new_filter_template))
423
+ filters.max_num_iceberg_orders.CopyFrom(
424
+ json_format.ParseDict(_filter, new_filter_template, ignore_unknown_fields=True)
425
+ )
405
426
  elif filter_type == 'MAX_POSITION':
406
427
  new_filter_template = api_pb2.FetchExchangeInfoSymbolResponse.Filters.MaxPosition()
407
- filters.max_position.CopyFrom(json_format.ParseDict(_filter, new_filter_template))
428
+ filters.max_position.CopyFrom(
429
+ json_format.ParseDict(_filter, new_filter_template, ignore_unknown_fields=True)
430
+ )
408
431
  return response
409
432
 
410
433
  async def FetchAccountInformation(self, request: api_pb2.OpenClientConnectionId,
@@ -428,7 +451,7 @@ class Martin(api_pb2_grpc.MartinServicer):
428
451
  balances.append({'asset': i.get('asset'), 'free': i.get('free'), 'locked': i.get('locked')})
429
452
  # logger.info(f"account_information.balances: {balances}")
430
453
  for balance in balances:
431
- new_balance = json_format.ParseDict(balance, response_balance)
454
+ new_balance = json_format.ParseDict(balance, response_balance, ignore_unknown_fields=True)
432
455
  response.balances.extend([new_balance])
433
456
  return response
434
457
 
@@ -451,7 +474,7 @@ class Martin(api_pb2_grpc.MartinServicer):
451
474
  open_client.ts_rlc = time.time()
452
475
  logger.debug(f"funding_wallet: {res}")
453
476
  for balance in res:
454
- new_balance = json_format.ParseDict(balance, response_balance)
477
+ new_balance = json_format.ParseDict(balance, response_balance, ignore_unknown_fields=True)
455
478
  response.balances.extend([new_balance])
456
479
  return response
457
480
 
@@ -482,7 +505,7 @@ class Martin(api_pb2_grpc.MartinServicer):
482
505
  await self.rate_limit_control(open_client)
483
506
  res = await client.fetch_symbol_price_ticker(symbol=request.symbol)
484
507
  open_client.ts_rlc = time.time()
485
- json_format.ParseDict(res, response)
508
+ json_format.ParseDict(res, response, ignore_unknown_fields=True)
486
509
  return response
487
510
 
488
511
  async def FetchTickerPriceChangeStatistics(
@@ -494,7 +517,7 @@ class Martin(api_pb2_grpc.MartinServicer):
494
517
  await self.rate_limit_control(open_client)
495
518
  res = await client.fetch_ticker_price_change_statistics(symbol=request.symbol)
496
519
  open_client.ts_rlc = time.time()
497
- json_format.ParseDict(res, response)
520
+ json_format.ParseDict(res, response, ignore_unknown_fields=True)
498
521
  return response
499
522
 
500
523
  async def FetchKlines(self, request: api_pb2.FetchKlinesRequest,
@@ -597,7 +620,7 @@ class Martin(api_pb2_grpc.MartinServicer):
597
620
  # logger.info(f"FetchAccountTradeList: {res}")
598
621
  open_client.ts_rlc = time.time()
599
622
  for trade in res:
600
- trade_order = json_format.ParseDict(trade, response_trade)
623
+ trade_order = json_format.ParseDict(trade, response_trade, ignore_unknown_fields=True)
601
624
  response.items.append(trade_order)
602
625
  return response
603
626
 
@@ -632,7 +655,7 @@ class Martin(api_pb2_grpc.MartinServicer):
632
655
  'close_price': _event.close_price,
633
656
  'event_time': _event.event_time}
634
657
  # logger.info(f"OnTickerUpdate.event: {_event.symbol}, ticker_24h: {ticker_24h}")
635
- json_format.ParseDict(ticker_24h, response)
658
+ json_format.ParseDict(ticker_24h, response, ignore_unknown_fields=True)
636
659
  yield response
637
660
  _queue.task_done()
638
661
 
@@ -813,7 +836,7 @@ class Martin(api_pb2_grpc.MartinServicer):
813
836
  origin_client_order_id=request.new_client_order_id,
814
837
  receive_window=None,
815
838
  response_type=False)
816
- json_format.ParseDict(res, response)
839
+ json_format.ParseDict(res, response, ignore_unknown_fields=True)
817
840
  logger.debug(f"CreateLimitOrder: for {open_client.name}:{request.symbol}: created: {res.get('orderId')}")
818
841
  return response
819
842
 
@@ -822,6 +845,7 @@ class Martin(api_pb2_grpc.MartinServicer):
822
845
  response = api_pb2.CancelOrderResponse()
823
846
  open_client = OpenClient.get_client(request.client_id)
824
847
  client = open_client.client
848
+ _queue = client.on_order_update_queues.get(request.trade_id)
825
849
  try:
826
850
  res = await client.cancel_order(
827
851
  request.trade_id,
@@ -842,7 +866,10 @@ class Martin(api_pb2_grpc.MartinServicer):
842
866
  _context.set_details(f"{ex}")
843
867
  _context.set_code(grpc.StatusCode.UNKNOWN)
844
868
  else:
845
- json_format.ParseDict(res, response)
869
+ if float(res['executedQty']):
870
+ await self.create_trade_stream_event(_queue, client, open_client, request)
871
+ await asyncio.sleep(HEARTBEAT)
872
+ json_format.ParseDict(res, response, ignore_unknown_fields=True)
846
873
  return response
847
874
 
848
875
  async def TransferToMaster(self, request: api_pb2.MarketRequest,