exchanges-wrapper 2.1.52__tar.gz → 2.2.2__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.
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/PKG-INFO +2 -3
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/__init__.py +1 -1
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/exch_srv.py +60 -56
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/http_client.py +4 -5
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/martin/__init__.py +29 -29
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/proto/martin.proto +14 -12
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/web_sockets.py +16 -16
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/pyproject.toml +1 -2
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/LICENSE.md +0 -0
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/README.md +0 -0
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/client.py +0 -0
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/definitions.py +0 -0
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/errors.py +0 -0
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/events.py +0 -0
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/exch_srv_cfg.toml.template +0 -0
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/lib.py +0 -0
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/parsers/bitfinex.py +0 -0
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/parsers/bybit.py +0 -0
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/parsers/huobi.py +0 -0
- {exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/parsers/okx.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: exchanges-wrapper
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.2
|
|
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.12
|
|
@@ -12,9 +12,8 @@ Classifier: Operating System :: Unix
|
|
|
12
12
|
Classifier: Operating System :: Microsoft :: Windows
|
|
13
13
|
Classifier: Operating System :: MacOS
|
|
14
14
|
License-File: LICENSE.md
|
|
15
|
-
Requires-Dist: crypto-ws-api==2.1.
|
|
15
|
+
Requires-Dist: crypto-ws-api==2.1.15
|
|
16
16
|
Requires-Dist: pyotp==2.10.0
|
|
17
|
-
Requires-Dist: simplejson==4.1.1
|
|
18
17
|
Requires-Dist: aiohttp==3.14.3
|
|
19
18
|
Requires-Dist: expiringdict==1.2.2
|
|
20
19
|
Requires-Dist: betterproto==2.0.0b7
|
|
@@ -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.
|
|
15
|
+
__version__ = "2.2.2"
|
|
16
16
|
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
import shutil
|
|
@@ -16,8 +16,7 @@ import gc
|
|
|
16
16
|
import traceback
|
|
17
17
|
import asyncio
|
|
18
18
|
import functools
|
|
19
|
-
|
|
20
|
-
import ujson as json
|
|
19
|
+
import orjson
|
|
21
20
|
import logging
|
|
22
21
|
from decimal import Decimal
|
|
23
22
|
import ctypes, ctypes.util
|
|
@@ -162,7 +161,7 @@ class Martin(mr.MartinBase):
|
|
|
162
161
|
real_market=open_client.real_market
|
|
163
162
|
)
|
|
164
163
|
|
|
165
|
-
async def reset_rate_limit(self, request: mr.OpenClientConnectionId) ->
|
|
164
|
+
async def reset_rate_limit(self, request: mr.OpenClientConnectionId) -> SimpleResponse:
|
|
166
165
|
Martin.rate_limiter = max(Martin.rate_limiter or 0, request.rate_limiter)
|
|
167
166
|
_success = False
|
|
168
167
|
open_client = OpenClient.get_client(request.client_id)
|
|
@@ -175,7 +174,7 @@ class Martin(mr.MartinBase):
|
|
|
175
174
|
_success = True
|
|
176
175
|
elif client.http.rate_limit_reached:
|
|
177
176
|
Martin.rate_limit_reached_time = time.time()
|
|
178
|
-
return
|
|
177
|
+
return SimpleResponse(success=_success)
|
|
179
178
|
|
|
180
179
|
async def send_request(self, client_method_name, request, rate_limit=False, **kwargs):
|
|
181
180
|
open_client_instance = OpenClient.get_client(request.client_id)
|
|
@@ -233,9 +232,9 @@ class Martin(mr.MartinBase):
|
|
|
233
232
|
server_time = res.get('serverTime')
|
|
234
233
|
return mr.FetchServerTimeResponse(server_time=server_time)
|
|
235
234
|
|
|
236
|
-
async def one_click_arrival_deposit(self, request: mr.MarketRequest) ->
|
|
235
|
+
async def one_click_arrival_deposit(self, request: mr.MarketRequest) -> SimpleResponse:
|
|
237
236
|
res, _, _ = await self.send_request('one_click_arrival_deposit', request, tx_id=request.symbol)
|
|
238
|
-
return
|
|
237
|
+
return SimpleResponse(success=True, result=orjson.dumps(res))
|
|
239
238
|
|
|
240
239
|
async def fetch_open_orders(self, request: mr.MarketRequest) -> mr.FetchOpenOrdersResponse:
|
|
241
240
|
response = mr.FetchOpenOrdersResponse()
|
|
@@ -248,7 +247,7 @@ class Martin(mr.MartinBase):
|
|
|
248
247
|
)
|
|
249
248
|
for order in res:
|
|
250
249
|
order_id = order['orderId']
|
|
251
|
-
response.orders.append(
|
|
250
|
+
response.orders.append(orjson.dumps(order))
|
|
252
251
|
if client.exchange in ('bitfinex', 'huobi'):
|
|
253
252
|
client.active_order(order_id, order['origQty'], order['executedQty'])
|
|
254
253
|
|
|
@@ -302,8 +301,8 @@ class Martin(mr.MartinBase):
|
|
|
302
301
|
await _queue.put(weakref.ref(event)())
|
|
303
302
|
logger.debug(f"{msg_header}: {trades}")
|
|
304
303
|
|
|
305
|
-
async def cancel_all_orders(self, request: mr.MarketRequest) ->
|
|
306
|
-
response =
|
|
304
|
+
async def cancel_all_orders(self, request: mr.MarketRequest) -> SimpleResponse:
|
|
305
|
+
response = SimpleResponse()
|
|
307
306
|
|
|
308
307
|
res, _, _ = await self.send_request(
|
|
309
308
|
'cancel_all_orders',
|
|
@@ -313,7 +312,7 @@ class Martin(mr.MartinBase):
|
|
|
313
312
|
)
|
|
314
313
|
|
|
315
314
|
response.success = True
|
|
316
|
-
response.result =
|
|
315
|
+
response.result = orjson.dumps(res)
|
|
317
316
|
return response
|
|
318
317
|
|
|
319
318
|
async def fetch_exchange_info_symbol(self, request: mr.MarketRequest) -> mr.FetchExchangeInfoSymbolResponse:
|
|
@@ -353,8 +352,8 @@ class Martin(mr.MartinBase):
|
|
|
353
352
|
setattr(filters, filter_type.lower(), filter_instance)
|
|
354
353
|
return filters
|
|
355
354
|
|
|
356
|
-
async def fetch_account_information(self, request: mr.OpenClientConnectionId) -> mr.
|
|
357
|
-
response = mr.
|
|
355
|
+
async def fetch_account_information(self, request: mr.OpenClientConnectionId) -> mr.BytesResponse:
|
|
356
|
+
response = mr.BytesResponse()
|
|
358
357
|
account_information, _, _ = await self.send_request(
|
|
359
358
|
'fetch_account_information',
|
|
360
359
|
request,
|
|
@@ -363,17 +362,21 @@ class Martin(mr.MartinBase):
|
|
|
363
362
|
)
|
|
364
363
|
# Send only balances
|
|
365
364
|
res = account_information.get('balances', [])
|
|
366
|
-
|
|
367
|
-
{
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
365
|
+
response.items.extend(
|
|
366
|
+
orjson.dumps({
|
|
367
|
+
'asset': i['asset'],
|
|
368
|
+
'free': i['free'],
|
|
369
|
+
'locked': i['locked']
|
|
370
|
+
})
|
|
371
|
+
for i in res
|
|
372
|
+
if float(i['free']) or float(i['locked'])
|
|
373
|
+
)
|
|
371
374
|
return response
|
|
372
375
|
|
|
373
|
-
async def fetch_funding_wallet(self, request: mr.FetchFundingWalletRequest) -> mr.
|
|
376
|
+
async def fetch_funding_wallet(self, request: mr.FetchFundingWalletRequest) -> mr.BytesResponse:
|
|
374
377
|
open_client = OpenClient.get_client(request.client_id)
|
|
375
378
|
client = open_client.client
|
|
376
|
-
response = mr.
|
|
379
|
+
response = mr.BytesResponse()
|
|
377
380
|
res = []
|
|
378
381
|
if client.exchange in ('bitfinex', 'okx', 'bybit') \
|
|
379
382
|
or (open_client.real_market and client.exchange == 'binance'):
|
|
@@ -384,7 +387,7 @@ class Martin(mr.MartinBase):
|
|
|
384
387
|
asset=request.asset,
|
|
385
388
|
need_btc_valuation=request.need_btc_valuation
|
|
386
389
|
)
|
|
387
|
-
response.items
|
|
390
|
+
response.items.extend(orjson.dumps(item) for item in res)
|
|
388
391
|
return response
|
|
389
392
|
|
|
390
393
|
async def fetch_order_book(self, request: mr.MarketRequest) -> mr.FetchOrderBookResponse:
|
|
@@ -396,9 +399,10 @@ class Martin(mr.MartinBase):
|
|
|
396
399
|
symbol=request.symbol
|
|
397
400
|
)
|
|
398
401
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
+
response.last_update_id = res.get('lastUpdateId', 0)
|
|
403
|
+
response.bids.extend(orjson.dumps(v) for v in res.get('bids', []))
|
|
404
|
+
response.asks.extend(orjson.dumps(v) for v in res.get('asks', []))
|
|
405
|
+
return response
|
|
402
406
|
|
|
403
407
|
async def fetch_symbol_price_ticker(self, request: mr.MarketRequest) -> mr.FetchSymbolPriceTickerResponse:
|
|
404
408
|
response = mr.FetchSymbolPriceTickerResponse()
|
|
@@ -423,8 +427,8 @@ class Martin(mr.MartinBase):
|
|
|
423
427
|
)
|
|
424
428
|
return response.from_pydict(res)
|
|
425
429
|
|
|
426
|
-
async def fetch_klines(self, request: mr.FetchKlinesRequest) -> mr.
|
|
427
|
-
response = mr.
|
|
430
|
+
async def fetch_klines(self, request: mr.FetchKlinesRequest) -> mr.BytesResponse:
|
|
431
|
+
response = mr.BytesResponse()
|
|
428
432
|
|
|
429
433
|
res, _, _ = await self.send_request(
|
|
430
434
|
'fetch_klines',
|
|
@@ -437,16 +441,16 @@ class Martin(mr.MartinBase):
|
|
|
437
441
|
limit=request.limit
|
|
438
442
|
)
|
|
439
443
|
|
|
440
|
-
response.items
|
|
444
|
+
response.items.extend(orjson.dumps(item) for item in res)
|
|
441
445
|
return response
|
|
442
446
|
|
|
443
447
|
async def on_klines_update(self, request: mr.FetchKlinesRequest) -> AsyncGenerator[OnKlinesUpdateResponse, Any]:
|
|
444
|
-
response =
|
|
448
|
+
response = OnKlinesUpdateResponse()
|
|
445
449
|
open_client = OpenClient.get_client(request.client_id)
|
|
446
450
|
client = open_client.client
|
|
447
451
|
_queue = asyncio.Queue(MAX_QUEUE_SIZE)
|
|
448
452
|
client.stream_queue[request.trade_id] |= {_queue}
|
|
449
|
-
_intervals =
|
|
453
|
+
_intervals = orjson.loads(request.intervals)
|
|
450
454
|
event_types = []
|
|
451
455
|
# Register streams for intervals
|
|
452
456
|
if client.exchange == 'bitfinex':
|
|
@@ -477,7 +481,7 @@ class Martin(mr.MartinBase):
|
|
|
477
481
|
# logger.info(f"OnKlinesUpdate.event: {exchange}:{_event.symbol}:{_event.kline_interval}")
|
|
478
482
|
response.symbol = _event.symbol
|
|
479
483
|
response.interval = _event.kline_interval
|
|
480
|
-
response.candle =
|
|
484
|
+
response.candle = orjson.dumps(
|
|
481
485
|
[_event.kline_start_time,
|
|
482
486
|
_event.kline_open_price,
|
|
483
487
|
_event.kline_high_price,
|
|
@@ -495,8 +499,8 @@ class Martin(mr.MartinBase):
|
|
|
495
499
|
yield response
|
|
496
500
|
_queue.task_done()
|
|
497
501
|
|
|
498
|
-
async def fetch_account_trade_list(self, request: mr.AccountTradeListRequest) -> mr.
|
|
499
|
-
response = mr.
|
|
502
|
+
async def fetch_account_trade_list(self, request: mr.AccountTradeListRequest) -> mr.BytesResponse:
|
|
503
|
+
response = mr.BytesResponse()
|
|
500
504
|
|
|
501
505
|
res, _, _ = await self.send_request(
|
|
502
506
|
'fetch_account_trade_list',
|
|
@@ -510,11 +514,11 @@ class Martin(mr.MartinBase):
|
|
|
510
514
|
limit=request.limit
|
|
511
515
|
)
|
|
512
516
|
|
|
513
|
-
response.items
|
|
517
|
+
response.items.extend(orjson.dumps(item) for item in res)
|
|
514
518
|
return response
|
|
515
519
|
|
|
516
520
|
async def on_ticker_update(self, request: mr.MarketRequest) -> AsyncGenerator[OnTickerUpdateResponse, Any]:
|
|
517
|
-
response =
|
|
521
|
+
response = OnTickerUpdateResponse()
|
|
518
522
|
open_client = OpenClient.get_client(request.client_id)
|
|
519
523
|
client = open_client.client
|
|
520
524
|
_queue = asyncio.Queue(MAX_QUEUE_SIZE)
|
|
@@ -551,7 +555,7 @@ class Martin(mr.MartinBase):
|
|
|
551
555
|
_queue.task_done()
|
|
552
556
|
|
|
553
557
|
async def on_order_book_update(self, request: mr.MarketRequest) -> AsyncGenerator[FetchOrderBookResponse, Any]:
|
|
554
|
-
response =
|
|
558
|
+
response = FetchOrderBookResponse()
|
|
555
559
|
open_client = OpenClient.get_client(request.client_id)
|
|
556
560
|
client = open_client.client
|
|
557
561
|
_queue = asyncio.LifoQueue(MAX_QUEUE_SIZE * 5)
|
|
@@ -579,13 +583,13 @@ class Martin(mr.MartinBase):
|
|
|
579
583
|
else:
|
|
580
584
|
if _event.bids and _event.asks:
|
|
581
585
|
response.last_update_id = _event.last_update_id
|
|
582
|
-
response.bids
|
|
583
|
-
response.asks
|
|
586
|
+
response.bids.extend(orjson.dumps(v) for v in _event.bids)
|
|
587
|
+
response.asks.extend(orjson.dumps(v) for v in _event.asks)
|
|
584
588
|
yield response
|
|
585
589
|
_queue.task_done()
|
|
586
590
|
|
|
587
591
|
async def on_funds_update(self, request: mr.OnFundsUpdateRequest) -> AsyncGenerator[StreamResponse, Any]:
|
|
588
|
-
response =
|
|
592
|
+
response = StreamResponse()
|
|
589
593
|
open_client = OpenClient.get_client(request.client_id)
|
|
590
594
|
client = open_client.client
|
|
591
595
|
_queue = asyncio.Queue(MAX_QUEUE_SIZE)
|
|
@@ -600,12 +604,12 @@ class Martin(mr.MartinBase):
|
|
|
600
604
|
logger.info(f"OnFundsUpdate: Stop user stream for {open_client.name}: {request.symbol}")
|
|
601
605
|
return
|
|
602
606
|
else:
|
|
603
|
-
response.event =
|
|
607
|
+
response.event = orjson.dumps(_event.balances)
|
|
604
608
|
yield response
|
|
605
609
|
_queue.task_done()
|
|
606
610
|
|
|
607
611
|
async def on_balance_update(self, request: mr.MarketRequest) -> AsyncGenerator[StreamResponse, Any]:
|
|
608
|
-
response =
|
|
612
|
+
response = StreamResponse()
|
|
609
613
|
open_client = OpenClient.get_client(request.client_id)
|
|
610
614
|
client = open_client.client
|
|
611
615
|
_queue = asyncio.Queue(MAX_QUEUE_SIZE)
|
|
@@ -644,14 +648,14 @@ class Martin(mr.MartinBase):
|
|
|
644
648
|
"balance_delta": _event.balance_delta,
|
|
645
649
|
"clear_time": _event.clear_time
|
|
646
650
|
}
|
|
647
|
-
response.event =
|
|
651
|
+
response.event = orjson.dumps(balance)
|
|
648
652
|
yield response
|
|
649
653
|
|
|
650
654
|
if _get_event_from_queue:
|
|
651
655
|
_queue.task_done()
|
|
652
656
|
|
|
653
657
|
async def on_order_update(self, request: mr.MarketRequest) -> AsyncGenerator[SimpleResponse, Any]:
|
|
654
|
-
response =
|
|
658
|
+
response = SimpleResponse()
|
|
655
659
|
open_client = OpenClient.get_client(request.client_id)
|
|
656
660
|
client = open_client.client
|
|
657
661
|
_queue = asyncio.Queue(MAX_QUEUE_SIZE)
|
|
@@ -670,7 +674,7 @@ class Martin(mr.MartinBase):
|
|
|
670
674
|
event = vars(_event)
|
|
671
675
|
event.pop('handlers', None)
|
|
672
676
|
response.success = True
|
|
673
|
-
response.result =
|
|
677
|
+
response.result = orjson.dumps(event)
|
|
674
678
|
yield response
|
|
675
679
|
_queue.task_done()
|
|
676
680
|
|
|
@@ -713,8 +717,8 @@ class Martin(mr.MartinBase):
|
|
|
713
717
|
response.from_pydict(res)
|
|
714
718
|
return response
|
|
715
719
|
|
|
716
|
-
async def transfer_to_sub(self, request: mr.MarketRequest) ->
|
|
717
|
-
response =
|
|
720
|
+
async def transfer_to_sub(self, request: mr.MarketRequest) -> SimpleResponse:
|
|
721
|
+
response = SimpleResponse()
|
|
718
722
|
response.success = False
|
|
719
723
|
|
|
720
724
|
res, _, _ = await self.send_request(
|
|
@@ -728,11 +732,11 @@ class Martin(mr.MartinBase):
|
|
|
728
732
|
|
|
729
733
|
if res and res.get("txnId"):
|
|
730
734
|
response.success = True
|
|
731
|
-
response.result =
|
|
735
|
+
response.result = orjson.dumps(res)
|
|
732
736
|
return response
|
|
733
737
|
|
|
734
|
-
async def transfer_to_master(self, request: mr.MarketRequest) ->
|
|
735
|
-
response =
|
|
738
|
+
async def transfer_to_master(self, request: mr.MarketRequest) -> SimpleResponse:
|
|
739
|
+
response = SimpleResponse()
|
|
736
740
|
response.success = False
|
|
737
741
|
|
|
738
742
|
res, _, _ = await self.send_request(
|
|
@@ -745,13 +749,13 @@ class Martin(mr.MartinBase):
|
|
|
745
749
|
|
|
746
750
|
if res and res.get("txnId"):
|
|
747
751
|
response.success = True
|
|
748
|
-
response.result =
|
|
752
|
+
response.result = orjson.dumps(res)
|
|
749
753
|
return response
|
|
750
754
|
|
|
751
|
-
async def start_stream(self, request: mr.StartStreamRequest) ->
|
|
755
|
+
async def start_stream(self, request: mr.StartStreamRequest) -> SimpleResponse:
|
|
752
756
|
open_client = OpenClient.get_client(request.client_id)
|
|
753
757
|
client = open_client.client
|
|
754
|
-
response =
|
|
758
|
+
response = SimpleResponse()
|
|
755
759
|
_market_stream_count = 0
|
|
756
760
|
while _market_stream_count < request.market_stream_count:
|
|
757
761
|
await asyncio.sleep(HEARTBEAT)
|
|
@@ -764,8 +768,8 @@ class Martin(mr.MartinBase):
|
|
|
764
768
|
response.success = True
|
|
765
769
|
return response
|
|
766
770
|
|
|
767
|
-
async def stop_stream(self, request: mr.MarketRequest) ->
|
|
768
|
-
response =
|
|
771
|
+
async def stop_stream(self, request: mr.MarketRequest) -> SimpleResponse:
|
|
772
|
+
response = SimpleResponse()
|
|
769
773
|
if open_client := OpenClient.get_client(request.client_id):
|
|
770
774
|
client = open_client.client
|
|
771
775
|
logger.info(f"StopStream request for {request.symbol} on {client.exchange}")
|
|
@@ -775,17 +779,17 @@ class Martin(mr.MartinBase):
|
|
|
775
779
|
response.success = False
|
|
776
780
|
return response
|
|
777
781
|
|
|
778
|
-
async def check_stream(self, request: mr.MarketRequest) ->
|
|
782
|
+
async def check_stream(self, request: mr.MarketRequest) -> SimpleResponse:
|
|
779
783
|
last_update = Martin.ticker_update_time.get(request.trade_id, 0)
|
|
780
784
|
check_time = time.time() - last_update
|
|
781
785
|
success = check_time < WSS_TICKER_TIMEOUT
|
|
782
|
-
response =
|
|
786
|
+
response = SimpleResponse(success=success)
|
|
783
787
|
if not success:
|
|
784
788
|
Martin.ticker_update_time.pop(request.trade_id, None)
|
|
785
789
|
logger.warning(f"CheckStream request failed for {request.trade_id}")
|
|
786
790
|
return response
|
|
787
791
|
|
|
788
|
-
async def client_restart(self, request: mr.MarketRequest) ->
|
|
792
|
+
async def client_restart(self, request: mr.MarketRequest) -> SimpleResponse:
|
|
789
793
|
await self.stop_stream(request)
|
|
790
794
|
if client := OpenClient.get_client(request.client_id).client:
|
|
791
795
|
if user_session := client.user_session:
|
|
@@ -793,7 +797,7 @@ class Martin(mr.MartinBase):
|
|
|
793
797
|
if session := client.http:
|
|
794
798
|
await session.close_session()
|
|
795
799
|
OpenClient.remove_client(request.client_id)
|
|
796
|
-
return
|
|
800
|
+
return SimpleResponse(success=True)
|
|
797
801
|
|
|
798
802
|
|
|
799
803
|
async def stop_stream_ex(client, trade_id):
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
import
|
|
2
|
+
import orjson
|
|
3
3
|
from urllib.parse import urlencode, urlparse
|
|
4
|
-
|
|
5
4
|
import aiohttp
|
|
6
5
|
import logging
|
|
7
6
|
import time
|
|
@@ -189,7 +188,7 @@ class HttpClient:
|
|
|
189
188
|
async def _bitfinex_request(self, path, method, signed, send_api_key, endpoint, timeout, **kwargs):
|
|
190
189
|
_endpoint = endpoint or self.endpoint
|
|
191
190
|
bfx_post = (method == 'POST' and kwargs) or "params" in kwargs
|
|
192
|
-
_params =
|
|
191
|
+
_params = orjson.dumps(kwargs).decode() if bfx_post else {}
|
|
193
192
|
url = f'{_endpoint}/{path}'
|
|
194
193
|
query_kwargs = {"headers": {"Accept": AJ}}
|
|
195
194
|
if kwargs and not bfx_post:
|
|
@@ -236,7 +235,7 @@ class HttpClient:
|
|
|
236
235
|
signature_payload = f"{ts}{self.api_key}{query_string}"
|
|
237
236
|
else:
|
|
238
237
|
url += path
|
|
239
|
-
data =
|
|
238
|
+
data = orjson.dumps(kwargs).decode()
|
|
240
239
|
signature_payload = f"{ts}{self.api_key}{data}"
|
|
241
240
|
|
|
242
241
|
signature = generate_signature(self.exchange, self.api_secret, signature_payload)
|
|
@@ -288,7 +287,7 @@ class HttpClient:
|
|
|
288
287
|
if signed:
|
|
289
288
|
ts = f"{datetime.now(timezone.utc).replace(tzinfo=None).isoformat('T', 'milliseconds')}Z"
|
|
290
289
|
if method == 'POST' and kwargs:
|
|
291
|
-
data =
|
|
290
|
+
data = orjson.dumps(kwargs.get('data') if 'data' in kwargs else kwargs).decode()
|
|
292
291
|
signature_payload = f"{ts}{method}{path}{data}"
|
|
293
292
|
else:
|
|
294
293
|
signature_payload = f"{ts}{method}{path}"
|
|
@@ -16,7 +16,6 @@ import betterproto
|
|
|
16
16
|
import grpclib
|
|
17
17
|
from betterproto.grpc.grpclib_server import ServiceBase
|
|
18
18
|
|
|
19
|
-
|
|
20
19
|
if TYPE_CHECKING:
|
|
21
20
|
import grpclib.server
|
|
22
21
|
from betterproto.grpc.grpclib_client import MetadataLike
|
|
@@ -24,13 +23,13 @@ if TYPE_CHECKING:
|
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
@dataclass(eq=False, repr=False)
|
|
27
|
-
class
|
|
28
|
-
items: List[
|
|
26
|
+
class BytesResponse(betterproto.Message):
|
|
27
|
+
items: List[bytes] = betterproto.bytes_field(1)
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
@dataclass(eq=False, repr=False)
|
|
32
31
|
class StreamResponse(betterproto.Message):
|
|
33
|
-
event:
|
|
32
|
+
event: bytes = betterproto.bytes_field(1)
|
|
34
33
|
|
|
35
34
|
|
|
36
35
|
@dataclass(eq=False, repr=False)
|
|
@@ -146,7 +145,7 @@ class OnFundsUpdateRequest(betterproto.Message):
|
|
|
146
145
|
@dataclass(eq=False, repr=False)
|
|
147
146
|
class SimpleResponse(betterproto.Message):
|
|
148
147
|
success: bool = betterproto.bool_field(1)
|
|
149
|
-
result:
|
|
148
|
+
result: bytes = betterproto.bytes_field(2)
|
|
150
149
|
|
|
151
150
|
|
|
152
151
|
@dataclass(eq=False, repr=False)
|
|
@@ -169,7 +168,7 @@ class AccountTradeListRequest(betterproto.Message):
|
|
|
169
168
|
class OnKlinesUpdateResponse(betterproto.Message):
|
|
170
169
|
symbol: str = betterproto.string_field(1)
|
|
171
170
|
interval: str = betterproto.string_field(2)
|
|
172
|
-
candle:
|
|
171
|
+
candle: bytes = betterproto.bytes_field(3)
|
|
173
172
|
|
|
174
173
|
|
|
175
174
|
@dataclass(eq=False, repr=False)
|
|
@@ -179,6 +178,7 @@ class FetchKlinesRequest(betterproto.Message):
|
|
|
179
178
|
symbol: str = betterproto.string_field(3)
|
|
180
179
|
interval: str = betterproto.string_field(4)
|
|
181
180
|
limit: int = betterproto.uint32_field(5)
|
|
181
|
+
intervals: bytes = betterproto.bytes_field(6)
|
|
182
182
|
|
|
183
183
|
|
|
184
184
|
@dataclass(eq=False, repr=False)
|
|
@@ -215,8 +215,8 @@ class FetchSymbolPriceTickerResponse(betterproto.Message):
|
|
|
215
215
|
@dataclass(eq=False, repr=False)
|
|
216
216
|
class FetchOrderBookResponse(betterproto.Message):
|
|
217
217
|
last_update_id: int = betterproto.uint64_field(1)
|
|
218
|
-
bids: List[
|
|
219
|
-
asks: List[
|
|
218
|
+
bids: List[bytes] = betterproto.bytes_field(2)
|
|
219
|
+
asks: List[bytes] = betterproto.bytes_field(3)
|
|
220
220
|
|
|
221
221
|
|
|
222
222
|
@dataclass(eq=False, repr=False)
|
|
@@ -397,7 +397,7 @@ class FetchOrderResponse(betterproto.Message):
|
|
|
397
397
|
@dataclass(eq=False, repr=False)
|
|
398
398
|
class FetchOpenOrdersResponse(betterproto.Message):
|
|
399
399
|
rate_limiter: int = betterproto.int32_field(1)
|
|
400
|
-
orders: List[
|
|
400
|
+
orders: List[bytes] = betterproto.bytes_field(2)
|
|
401
401
|
|
|
402
402
|
|
|
403
403
|
@dataclass(eq=False, repr=False)
|
|
@@ -526,11 +526,11 @@ class MartinStub(betterproto.ServiceStub):
|
|
|
526
526
|
timeout: Optional[float] = None,
|
|
527
527
|
deadline: Optional["Deadline"] = None,
|
|
528
528
|
metadata: Optional["MetadataLike"] = None
|
|
529
|
-
) -> "
|
|
529
|
+
) -> "BytesResponse":
|
|
530
530
|
return await self._unary_unary(
|
|
531
531
|
"/martin.Martin/FetchAccountInformation",
|
|
532
532
|
open_client_connection_id,
|
|
533
|
-
|
|
533
|
+
BytesResponse,
|
|
534
534
|
timeout=timeout,
|
|
535
535
|
deadline=deadline,
|
|
536
536
|
metadata=metadata,
|
|
@@ -543,11 +543,11 @@ class MartinStub(betterproto.ServiceStub):
|
|
|
543
543
|
timeout: Optional[float] = None,
|
|
544
544
|
deadline: Optional["Deadline"] = None,
|
|
545
545
|
metadata: Optional["MetadataLike"] = None
|
|
546
|
-
) -> "
|
|
546
|
+
) -> "BytesResponse":
|
|
547
547
|
return await self._unary_unary(
|
|
548
548
|
"/martin.Martin/FetchAccountTradeList",
|
|
549
549
|
account_trade_list_request,
|
|
550
|
-
|
|
550
|
+
BytesResponse,
|
|
551
551
|
timeout=timeout,
|
|
552
552
|
deadline=deadline,
|
|
553
553
|
metadata=metadata,
|
|
@@ -577,11 +577,11 @@ class MartinStub(betterproto.ServiceStub):
|
|
|
577
577
|
timeout: Optional[float] = None,
|
|
578
578
|
deadline: Optional["Deadline"] = None,
|
|
579
579
|
metadata: Optional["MetadataLike"] = None
|
|
580
|
-
) -> "
|
|
580
|
+
) -> "BytesResponse":
|
|
581
581
|
return await self._unary_unary(
|
|
582
582
|
"/martin.Martin/FetchFundingWallet",
|
|
583
583
|
fetch_funding_wallet_request,
|
|
584
|
-
|
|
584
|
+
BytesResponse,
|
|
585
585
|
timeout=timeout,
|
|
586
586
|
deadline=deadline,
|
|
587
587
|
metadata=metadata,
|
|
@@ -594,11 +594,11 @@ class MartinStub(betterproto.ServiceStub):
|
|
|
594
594
|
timeout: Optional[float] = None,
|
|
595
595
|
deadline: Optional["Deadline"] = None,
|
|
596
596
|
metadata: Optional["MetadataLike"] = None
|
|
597
|
-
) -> "
|
|
597
|
+
) -> "BytesResponse":
|
|
598
598
|
return await self._unary_unary(
|
|
599
599
|
"/martin.Martin/FetchKlines",
|
|
600
600
|
fetch_klines_request,
|
|
601
|
-
|
|
601
|
+
BytesResponse,
|
|
602
602
|
timeout=timeout,
|
|
603
603
|
deadline=deadline,
|
|
604
604
|
metadata=metadata,
|
|
@@ -973,12 +973,12 @@ class MartinBase(ServiceBase):
|
|
|
973
973
|
|
|
974
974
|
async def fetch_account_information(
|
|
975
975
|
self, open_client_connection_id: "OpenClientConnectionId"
|
|
976
|
-
) -> "
|
|
976
|
+
) -> "BytesResponse":
|
|
977
977
|
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
978
978
|
|
|
979
979
|
async def fetch_account_trade_list(
|
|
980
980
|
self, account_trade_list_request: "AccountTradeListRequest"
|
|
981
|
-
) -> "
|
|
981
|
+
) -> "BytesResponse":
|
|
982
982
|
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
983
983
|
|
|
984
984
|
async def fetch_exchange_info_symbol(
|
|
@@ -988,12 +988,12 @@ class MartinBase(ServiceBase):
|
|
|
988
988
|
|
|
989
989
|
async def fetch_funding_wallet(
|
|
990
990
|
self, fetch_funding_wallet_request: "FetchFundingWalletRequest"
|
|
991
|
-
) -> "
|
|
991
|
+
) -> "BytesResponse":
|
|
992
992
|
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
993
993
|
|
|
994
994
|
async def fetch_klines(
|
|
995
995
|
self, fetch_klines_request: "FetchKlinesRequest"
|
|
996
|
-
) -> "
|
|
996
|
+
) -> "BytesResponse":
|
|
997
997
|
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
|
998
998
|
|
|
999
999
|
async def fetch_open_orders(
|
|
@@ -1128,14 +1128,14 @@ class MartinBase(ServiceBase):
|
|
|
1128
1128
|
await stream.send_message(response)
|
|
1129
1129
|
|
|
1130
1130
|
async def __rpc_fetch_account_information(
|
|
1131
|
-
self, stream: "grpclib.server.Stream[OpenClientConnectionId,
|
|
1131
|
+
self, stream: "grpclib.server.Stream[OpenClientConnectionId, BytesResponse]"
|
|
1132
1132
|
) -> None:
|
|
1133
1133
|
request = await stream.recv_message()
|
|
1134
1134
|
response = await self.fetch_account_information(request)
|
|
1135
1135
|
await stream.send_message(response)
|
|
1136
1136
|
|
|
1137
1137
|
async def __rpc_fetch_account_trade_list(
|
|
1138
|
-
self, stream: "grpclib.server.Stream[AccountTradeListRequest,
|
|
1138
|
+
self, stream: "grpclib.server.Stream[AccountTradeListRequest, BytesResponse]"
|
|
1139
1139
|
) -> None:
|
|
1140
1140
|
request = await stream.recv_message()
|
|
1141
1141
|
response = await self.fetch_account_trade_list(request)
|
|
@@ -1150,14 +1150,14 @@ class MartinBase(ServiceBase):
|
|
|
1150
1150
|
await stream.send_message(response)
|
|
1151
1151
|
|
|
1152
1152
|
async def __rpc_fetch_funding_wallet(
|
|
1153
|
-
self, stream: "grpclib.server.Stream[FetchFundingWalletRequest,
|
|
1153
|
+
self, stream: "grpclib.server.Stream[FetchFundingWalletRequest, BytesResponse]"
|
|
1154
1154
|
) -> None:
|
|
1155
1155
|
request = await stream.recv_message()
|
|
1156
1156
|
response = await self.fetch_funding_wallet(request)
|
|
1157
1157
|
await stream.send_message(response)
|
|
1158
1158
|
|
|
1159
1159
|
async def __rpc_fetch_klines(
|
|
1160
|
-
self, stream: "grpclib.server.Stream[FetchKlinesRequest,
|
|
1160
|
+
self, stream: "grpclib.server.Stream[FetchKlinesRequest, BytesResponse]"
|
|
1161
1161
|
) -> None:
|
|
1162
1162
|
request = await stream.recv_message()
|
|
1163
1163
|
response = await self.fetch_klines(request)
|
|
@@ -1356,13 +1356,13 @@ class MartinBase(ServiceBase):
|
|
|
1356
1356
|
self.__rpc_fetch_account_information,
|
|
1357
1357
|
grpclib.const.Cardinality.UNARY_UNARY,
|
|
1358
1358
|
OpenClientConnectionId,
|
|
1359
|
-
|
|
1359
|
+
BytesResponse,
|
|
1360
1360
|
),
|
|
1361
1361
|
"/martin.Martin/FetchAccountTradeList": grpclib.const.Handler(
|
|
1362
1362
|
self.__rpc_fetch_account_trade_list,
|
|
1363
1363
|
grpclib.const.Cardinality.UNARY_UNARY,
|
|
1364
1364
|
AccountTradeListRequest,
|
|
1365
|
-
|
|
1365
|
+
BytesResponse,
|
|
1366
1366
|
),
|
|
1367
1367
|
"/martin.Martin/FetchExchangeInfoSymbol": grpclib.const.Handler(
|
|
1368
1368
|
self.__rpc_fetch_exchange_info_symbol,
|
|
@@ -1374,13 +1374,13 @@ class MartinBase(ServiceBase):
|
|
|
1374
1374
|
self.__rpc_fetch_funding_wallet,
|
|
1375
1375
|
grpclib.const.Cardinality.UNARY_UNARY,
|
|
1376
1376
|
FetchFundingWalletRequest,
|
|
1377
|
-
|
|
1377
|
+
BytesResponse,
|
|
1378
1378
|
),
|
|
1379
1379
|
"/martin.Martin/FetchKlines": grpclib.const.Handler(
|
|
1380
1380
|
self.__rpc_fetch_klines,
|
|
1381
1381
|
grpclib.const.Cardinality.UNARY_UNARY,
|
|
1382
1382
|
FetchKlinesRequest,
|
|
1383
|
-
|
|
1383
|
+
BytesResponse,
|
|
1384
1384
|
),
|
|
1385
1385
|
"/martin.Martin/FetchOpenOrders": grpclib.const.Handler(
|
|
1386
1386
|
self.__rpc_fetch_open_orders,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
+
__version__ = "2.2.1"
|
|
2
3
|
Protocol buffer definition for exchanges-wrapper exch_srv.py
|
|
3
4
|
https://grpc.io/docs/languages/python/quickstart/
|
|
4
5
|
For compile use next commands
|
|
@@ -16,11 +17,11 @@ service Martin {
|
|
|
16
17
|
rpc CancelOrder (CancelOrderRequest) returns (CancelOrderResponse) {}
|
|
17
18
|
rpc CheckStream (MarketRequest) returns (SimpleResponse) {}
|
|
18
19
|
rpc CreateLimitOrder (CreateLimitOrderRequest) returns (CreateLimitOrderResponse) {}
|
|
19
|
-
rpc FetchAccountInformation (OpenClientConnectionId) returns (
|
|
20
|
-
rpc FetchAccountTradeList (AccountTradeListRequest) returns (
|
|
20
|
+
rpc FetchAccountInformation (OpenClientConnectionId) returns (BytesResponse) {}
|
|
21
|
+
rpc FetchAccountTradeList (AccountTradeListRequest) returns (BytesResponse) {}
|
|
21
22
|
rpc FetchExchangeInfoSymbol (MarketRequest) returns (FetchExchangeInfoSymbolResponse) {}
|
|
22
|
-
rpc FetchFundingWallet(FetchFundingWalletRequest) returns (
|
|
23
|
-
rpc FetchKlines (FetchKlinesRequest) returns (
|
|
23
|
+
rpc FetchFundingWallet(FetchFundingWalletRequest) returns (BytesResponse) {}
|
|
24
|
+
rpc FetchKlines (FetchKlinesRequest) returns (BytesResponse) {}
|
|
24
25
|
rpc FetchOpenOrders (MarketRequest) returns (FetchOpenOrdersResponse) {}
|
|
25
26
|
rpc FetchOrder (FetchOrderRequest) returns (FetchOrderResponse) {}
|
|
26
27
|
rpc FetchOrderBook (MarketRequest) returns (FetchOrderBookResponse) {}
|
|
@@ -43,12 +44,12 @@ service Martin {
|
|
|
43
44
|
rpc ClientRestart (MarketRequest) returns (SimpleResponse) {}
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
message
|
|
47
|
-
repeated
|
|
47
|
+
message BytesResponse {
|
|
48
|
+
repeated bytes items = 1;
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
message StreamResponse {
|
|
51
|
-
|
|
52
|
+
bytes event = 1;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
message FetchFundingWalletRequest{
|
|
@@ -157,7 +158,7 @@ message OnFundsUpdateRequest {
|
|
|
157
158
|
|
|
158
159
|
message SimpleResponse {
|
|
159
160
|
bool success = 1;
|
|
160
|
-
|
|
161
|
+
bytes result = 2;
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
message OnTickerUpdateResponse {
|
|
@@ -177,7 +178,7 @@ message AccountTradeListRequest {
|
|
|
177
178
|
message OnKlinesUpdateResponse {
|
|
178
179
|
string symbol = 1;
|
|
179
180
|
string interval =2;
|
|
180
|
-
|
|
181
|
+
bytes candle = 3;
|
|
181
182
|
}
|
|
182
183
|
|
|
183
184
|
message FetchKlinesRequest {
|
|
@@ -186,6 +187,7 @@ message FetchKlinesRequest {
|
|
|
186
187
|
string symbol = 3;
|
|
187
188
|
string interval = 4;
|
|
188
189
|
uint32 limit = 5;
|
|
190
|
+
bytes intervals = 6;
|
|
189
191
|
}
|
|
190
192
|
|
|
191
193
|
message FetchTickerPriceChangeStatisticsResponse {
|
|
@@ -219,8 +221,8 @@ message FetchSymbolPriceTickerResponse {
|
|
|
219
221
|
|
|
220
222
|
message FetchOrderBookResponse {
|
|
221
223
|
uint64 lastUpdateId = 1;
|
|
222
|
-
repeated
|
|
223
|
-
repeated
|
|
224
|
+
repeated bytes bids = 2;
|
|
225
|
+
repeated bytes asks = 3;
|
|
224
226
|
}
|
|
225
227
|
|
|
226
228
|
message FetchExchangeInfoSymbolResponse {
|
|
@@ -362,7 +364,7 @@ message FetchOrderResponse {
|
|
|
362
364
|
|
|
363
365
|
message FetchOpenOrdersResponse {
|
|
364
366
|
int32 rate_limiter = 1;
|
|
365
|
-
repeated
|
|
367
|
+
repeated bytes orders = 2;
|
|
366
368
|
}
|
|
367
369
|
|
|
368
370
|
message MarketRequest {
|
|
@@ -2,9 +2,7 @@ import sys
|
|
|
2
2
|
import asyncio
|
|
3
3
|
import gc
|
|
4
4
|
import logging
|
|
5
|
-
|
|
6
|
-
# noinspection PyPackageRequirements
|
|
7
|
-
import ujson as json
|
|
5
|
+
import orjson
|
|
8
6
|
from pathlib import Path
|
|
9
7
|
import time
|
|
10
8
|
from decimal import Decimal
|
|
@@ -114,7 +112,7 @@ class EventsDataStream:
|
|
|
114
112
|
pass # meant to be overridden in a subclass
|
|
115
113
|
|
|
116
114
|
async def _handle_messages(self, msg, symbol=None, ch_type=str()):
|
|
117
|
-
msg_data =
|
|
115
|
+
msg_data = orjson.loads(msg if isinstance(msg, str) else gzip.decompress(msg))
|
|
118
116
|
if self.exchange == 'binance':
|
|
119
117
|
if "stream" in msg_data:
|
|
120
118
|
await self._handle_event(msg_data)
|
|
@@ -217,7 +215,7 @@ class EventsDataStream:
|
|
|
217
215
|
elif self.exchange == 'huobi':
|
|
218
216
|
if ping := msg_data.get('ping'):
|
|
219
217
|
self.ping = 0
|
|
220
|
-
await self.websocket.send(
|
|
218
|
+
await self.websocket.send(orjson.dumps({"pong": ping}), text = True)
|
|
221
219
|
await asyncio.sleep(0)
|
|
222
220
|
elif msg_data.get('action') == 'ping':
|
|
223
221
|
self.ping = 0
|
|
@@ -227,7 +225,7 @@ class EventsDataStream:
|
|
|
227
225
|
"ts": msg_data.get('data').get('ts')
|
|
228
226
|
}
|
|
229
227
|
}
|
|
230
|
-
await self.websocket.send(
|
|
228
|
+
await self.websocket.send(orjson.dumps(pong), text = True)
|
|
231
229
|
await asyncio.sleep(0)
|
|
232
230
|
elif msg_data.get('tick') or msg_data.get('data'):
|
|
233
231
|
if ch_type == 'ticker':
|
|
@@ -252,7 +250,7 @@ class EventsDataStream:
|
|
|
252
250
|
|
|
253
251
|
async def ws_listener(self, request=None, symbol=None, ch_type=str()):
|
|
254
252
|
if request:
|
|
255
|
-
await self.websocket.send(
|
|
253
|
+
await self.websocket.send(orjson.dumps(request), text = True)
|
|
256
254
|
await asyncio.sleep(0)
|
|
257
255
|
async for msg_data in self.websocket:
|
|
258
256
|
await self._handle_messages(msg_data, symbol, ch_type)
|
|
@@ -261,7 +259,7 @@ class EventsDataStream:
|
|
|
261
259
|
while True:
|
|
262
260
|
await asyncio.sleep(interval)
|
|
263
261
|
try:
|
|
264
|
-
await self.websocket.send(
|
|
262
|
+
await self.websocket.send(orjson.dumps({"req_id": req_id, "op": "ping"}), text = True)
|
|
265
263
|
except (ConnectionClosed, asyncio.exceptions.TimeoutError, AttributeError):
|
|
266
264
|
break
|
|
267
265
|
|
|
@@ -418,9 +416,10 @@ class HbpPrivateEventsDataStream(EventsDataStream):
|
|
|
418
416
|
|
|
419
417
|
async def start_wss(self):
|
|
420
418
|
await self.websocket.send(
|
|
421
|
-
|
|
419
|
+
orjson.dumps(
|
|
422
420
|
compose_htx_ws_auth(self.endpoint, self.exchange, self.client.api_key, self.client.api_secret)
|
|
423
|
-
)
|
|
421
|
+
),
|
|
422
|
+
text = True
|
|
424
423
|
)
|
|
425
424
|
await asyncio.sleep(0)
|
|
426
425
|
await self._handle_messages(await self.websocket.recv(), symbol=self.symbol)
|
|
@@ -429,7 +428,7 @@ class HbpPrivateEventsDataStream(EventsDataStream):
|
|
|
429
428
|
"action": "sub",
|
|
430
429
|
"ch": "accounts.update#2"
|
|
431
430
|
}
|
|
432
|
-
await self.websocket.send(
|
|
431
|
+
await self.websocket.send(orjson.dumps(request), text = True)
|
|
433
432
|
await asyncio.sleep(0)
|
|
434
433
|
await self._handle_messages(await self.websocket.recv(), symbol=self.symbol)
|
|
435
434
|
#
|
|
@@ -437,7 +436,7 @@ class HbpPrivateEventsDataStream(EventsDataStream):
|
|
|
437
436
|
"action": "sub",
|
|
438
437
|
"ch": f"orders#{self.symbol.lower()}"
|
|
439
438
|
}
|
|
440
|
-
await self.websocket.send(
|
|
439
|
+
await self.websocket.send(orjson.dumps(request), text = True)
|
|
441
440
|
await asyncio.sleep(0)
|
|
442
441
|
await self._handle_messages(await self.websocket.recv(), symbol=self.symbol)
|
|
443
442
|
#
|
|
@@ -546,7 +545,7 @@ class OkxPrivateEventsDataStream(EventsDataStream):
|
|
|
546
545
|
"sign": signature}
|
|
547
546
|
]
|
|
548
547
|
}
|
|
549
|
-
await self.websocket.send(
|
|
548
|
+
await self.websocket.send(orjson.dumps(request), text = True)
|
|
550
549
|
await asyncio.sleep(0)
|
|
551
550
|
await self._handle_messages(await self.websocket.recv())
|
|
552
551
|
# Channel subscription
|
|
@@ -598,7 +597,7 @@ class BBTPrivateEventsDataStream(EventsDataStream):
|
|
|
598
597
|
"op": 'auth',
|
|
599
598
|
"args": [self.client.api_key, ts, signature]
|
|
600
599
|
}
|
|
601
|
-
await self.websocket.send(
|
|
600
|
+
await self.websocket.send(orjson.dumps(request), text = True)
|
|
602
601
|
await asyncio.sleep(0)
|
|
603
602
|
await self._handle_messages(await self.websocket.recv())
|
|
604
603
|
# Channel subscription
|
|
@@ -633,9 +632,10 @@ class UserEventsDataStream(EventsDataStream):
|
|
|
633
632
|
|
|
634
633
|
async def start_wss(self):
|
|
635
634
|
await self.websocket.send(
|
|
636
|
-
|
|
635
|
+
orjson.dumps(
|
|
637
636
|
compose_binance_ws_auth(self.trade_id, self.client.api_key, self.client.api_secret)
|
|
638
|
-
)
|
|
637
|
+
),
|
|
638
|
+
text = True
|
|
639
639
|
)
|
|
640
640
|
await asyncio.sleep(0)
|
|
641
641
|
await self._handle_messages(await self.websocket.recv())
|
|
@@ -20,9 +20,8 @@ dynamic = ["version", "description"]
|
|
|
20
20
|
requires-python = ">=3.12"
|
|
21
21
|
|
|
22
22
|
dependencies = [
|
|
23
|
-
"crypto-ws-api==2.1.
|
|
23
|
+
"crypto-ws-api==2.1.15",
|
|
24
24
|
"pyotp==2.10.0",
|
|
25
|
-
"simplejson==4.1.1",
|
|
26
25
|
"aiohttp==3.14.3",
|
|
27
26
|
"expiringdict==1.2.2",
|
|
28
27
|
"betterproto==2.0.0b7",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{exchanges_wrapper-2.1.52 → exchanges_wrapper-2.2.2}/exchanges_wrapper/exch_srv_cfg.toml.template
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|