python-binance 1.0.29__tar.gz → 1.0.30__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 (60) hide show
  1. {python_binance-1.0.29/python_binance.egg-info → python-binance-1.0.30}/PKG-INFO +4 -3
  2. {python_binance-1.0.29 → python-binance-1.0.30}/README.rst +3 -2
  3. {python_binance-1.0.29 → python-binance-1.0.30}/binance/__init__.py +1 -1
  4. {python_binance-1.0.29 → python-binance-1.0.30}/binance/async_client.py +105 -18
  5. {python_binance-1.0.29 → python-binance-1.0.30}/binance/base_client.py +31 -7
  6. {python_binance-1.0.29 → python-binance-1.0.30}/binance/client.py +1309 -526
  7. {python_binance-1.0.29 → python-binance-1.0.30}/binance/exceptions.py +4 -0
  8. {python_binance-1.0.29 → python-binance-1.0.30}/binance/ws/keepalive_websocket.py +45 -6
  9. {python_binance-1.0.29 → python-binance-1.0.30}/binance/ws/reconnecting_websocket.py +7 -0
  10. {python_binance-1.0.29 → python-binance-1.0.30}/binance/ws/streams.py +25 -0
  11. {python_binance-1.0.29 → python-binance-1.0.30}/binance/ws/websocket_api.py +20 -7
  12. {python_binance-1.0.29 → python-binance-1.0.30}/pyproject.toml +3 -1
  13. {python_binance-1.0.29 → python-binance-1.0.30/python_binance.egg-info}/PKG-INFO +4 -3
  14. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_async_client.py +16 -0
  15. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_async_client_futures.py +4 -2
  16. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_async_client_options.py +2 -1
  17. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_async_client_ws_api.py +2 -15
  18. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_async_client_ws_futures_requests.py +22 -6
  19. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_client.py +20 -3
  20. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_client_futures.py +8 -6
  21. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_client_options.py +2 -1
  22. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_client_ws_api.py +3 -0
  23. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_client_ws_futures_requests.py +11 -0
  24. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_get_order_book.py +2 -0
  25. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_reconnecting_websocket.py +20 -2
  26. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_socket_manager.py +2 -1
  27. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_streams_options.py +2 -2
  28. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_ws_api.py +56 -33
  29. {python_binance-1.0.29 → python-binance-1.0.30}/LICENSE +0 -0
  30. {python_binance-1.0.29 → python-binance-1.0.30}/binance/enums.py +0 -0
  31. {python_binance-1.0.29 → python-binance-1.0.30}/binance/helpers.py +0 -0
  32. {python_binance-1.0.29 → python-binance-1.0.30}/binance/ws/__init__.py +0 -0
  33. {python_binance-1.0.29 → python-binance-1.0.30}/binance/ws/constants.py +0 -0
  34. {python_binance-1.0.29 → python-binance-1.0.30}/binance/ws/depthcache.py +0 -0
  35. {python_binance-1.0.29 → python-binance-1.0.30}/binance/ws/threaded_stream.py +0 -0
  36. {python_binance-1.0.29 → python-binance-1.0.30}/python_binance.egg-info/SOURCES.txt +0 -0
  37. {python_binance-1.0.29 → python-binance-1.0.30}/python_binance.egg-info/dependency_links.txt +0 -0
  38. {python_binance-1.0.29 → python-binance-1.0.30}/python_binance.egg-info/requires.txt +0 -0
  39. {python_binance-1.0.29 → python-binance-1.0.30}/python_binance.egg-info/top_level.txt +0 -0
  40. {python_binance-1.0.29 → python-binance-1.0.30}/setup.cfg +0 -0
  41. {python_binance-1.0.29 → python-binance-1.0.30}/setup.py +0 -0
  42. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_api_request.py +0 -0
  43. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_async_client_gift_card copy.py +0 -0
  44. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_async_client_margin.py +0 -0
  45. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_async_client_portfolio.py +0 -0
  46. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_client_gift_card.py +0 -0
  47. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_client_margin.py +0 -0
  48. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_client_portfolio.py +0 -0
  49. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_cryptography.py +0 -0
  50. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_depth_cache.py +0 -0
  51. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_futures.py +0 -0
  52. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_headers.py +0 -0
  53. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_historical_klines.py +0 -0
  54. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_ids.py +0 -0
  55. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_init.py +0 -0
  56. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_order.py +0 -0
  57. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_ping.py +0 -0
  58. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_streams.py +0 -0
  59. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_threaded_socket_manager.py +0 -0
  60. {python_binance-1.0.29 → python-binance-1.0.30}/tests/test_threaded_stream.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-binance
3
- Version: 1.0.29
3
+ Version: 1.0.30
4
4
  Summary: Binance REST API python implementation
5
5
  Home-page: https://github.com/sammchardy/python-binance
6
6
  Author: Sam McHardy
@@ -31,7 +31,7 @@ Requires-Dist: websockets
31
31
  Requires-Dist: pycryptodome
32
32
 
33
33
  =================================
34
- Welcome to python-binance v1.0.29
34
+ Welcome to python-binance v1.0.30
35
35
  =================================
36
36
 
37
37
  .. image:: https://img.shields.io/pypi/v/python-binance.svg
@@ -95,7 +95,8 @@ Features
95
95
 
96
96
  - Implementation of all General, Market Data and Account endpoints.
97
97
  - Asyncio implementation
98
- - Testnet support for Spot, Futures and Vanilla Options
98
+ - Demo trading support (by providing demo=True)
99
+ - Testnet support for Spot, Futures and Vanilla Options (deprecated)
99
100
  - Simple handling of authentication include RSA and EDDSA keys
100
101
  - No need to generate timestamps yourself, the wrapper does it for you
101
102
  - RecvWindow sent by default
@@ -1,5 +1,5 @@
1
1
  =================================
2
- Welcome to python-binance v1.0.29
2
+ Welcome to python-binance v1.0.30
3
3
  =================================
4
4
 
5
5
  .. image:: https://img.shields.io/pypi/v/python-binance.svg
@@ -63,7 +63,8 @@ Features
63
63
 
64
64
  - Implementation of all General, Market Data and Account endpoints.
65
65
  - Asyncio implementation
66
- - Testnet support for Spot, Futures and Vanilla Options
66
+ - Demo trading support (by providing demo=True)
67
+ - Testnet support for Spot, Futures and Vanilla Options (deprecated)
67
68
  - Simple handling of authentication include RSA and EDDSA keys
68
69
  - No need to generate timestamps yourself, the wrapper does it for you
69
70
  - RecvWindow sent by default
@@ -4,7 +4,7 @@
4
4
 
5
5
  """
6
6
 
7
- __version__ = "1.0.29"
7
+ __version__ = "1.0.30"
8
8
 
9
9
  from binance.async_client import AsyncClient # noqa
10
10
  from binance.client import Client # noqa
@@ -31,6 +31,7 @@ class AsyncClient(BaseClient):
31
31
  tld: str = "com",
32
32
  base_endpoint: str = BaseClient.BASE_ENDPOINT_DEFAULT,
33
33
  testnet: bool = False,
34
+ demo: bool = False,
34
35
  loop=None,
35
36
  session_params: Optional[Dict[str, Any]] = None,
36
37
  private_key: Optional[Union[str, Path]] = None,
@@ -41,6 +42,15 @@ class AsyncClient(BaseClient):
41
42
  self.https_proxy = https_proxy
42
43
  self.loop = loop or get_loop()
43
44
  self._session_params: Dict[str, Any] = session_params or {}
45
+
46
+ # Convert https_proxy to requests_params format for BaseClient
47
+ if https_proxy and requests_params is None:
48
+ requests_params = {'proxies': {'http': https_proxy, 'https': https_proxy}}
49
+ elif https_proxy and requests_params is not None:
50
+ if 'proxies' not in requests_params:
51
+ requests_params['proxies'] = {}
52
+ requests_params['proxies'].update({'http': https_proxy, 'https': https_proxy})
53
+
44
54
  super().__init__(
45
55
  api_key,
46
56
  api_secret,
@@ -48,6 +58,7 @@ class AsyncClient(BaseClient):
48
58
  tld,
49
59
  base_endpoint,
50
60
  testnet,
61
+ demo,
51
62
  private_key,
52
63
  private_key_pass,
53
64
  time_unit=time_unit,
@@ -62,6 +73,7 @@ class AsyncClient(BaseClient):
62
73
  tld: str = "com",
63
74
  base_endpoint: str = BaseClient.BASE_ENDPOINT_DEFAULT,
64
75
  testnet: bool = False,
76
+ demo: bool = False,
65
77
  loop=None,
66
78
  session_params: Optional[Dict[str, Any]] = None,
67
79
  private_key: Optional[Union[str, Path]] = None,
@@ -76,6 +88,7 @@ class AsyncClient(BaseClient):
76
88
  tld,
77
89
  base_endpoint,
78
90
  testnet,
91
+ demo,
79
92
  loop,
80
93
  session_params,
81
94
  private_key,
@@ -151,6 +164,9 @@ class AsyncClient(BaseClient):
151
164
  url_encoded_data = urlencode(dict_data)
152
165
  data = f"{url_encoded_data}&signature={signature}"
153
166
 
167
+ # Remove proxies from kwargs since aiohttp uses 'proxy' parameter instead
168
+ kwargs.pop('proxies', None)
169
+
154
170
  async with getattr(self.session, method)(
155
171
  yarl.URL(uri, encoded=True),
156
172
  proxy=self.https_proxy,
@@ -283,7 +299,7 @@ class AsyncClient(BaseClient):
283
299
  get_products.__doc__ = Client.get_products.__doc__
284
300
 
285
301
  async def get_exchange_info(self) -> Dict:
286
- return await self._get("exchangeInfo", version=self.PRIVATE_API_VERSION)
302
+ return await self._get("exchangeInfo")
287
303
 
288
304
  get_exchange_info.__doc__ = Client.get_exchange_info.__doc__
289
305
 
@@ -301,12 +317,12 @@ class AsyncClient(BaseClient):
301
317
  # General Endpoints
302
318
 
303
319
  async def ping(self) -> Dict:
304
- return await self._get("ping", version=self.PRIVATE_API_VERSION)
320
+ return await self._get("ping")
305
321
 
306
322
  ping.__doc__ = Client.ping.__doc__
307
323
 
308
324
  async def get_server_time(self) -> Dict:
309
- return await self._get("time", version=self.PRIVATE_API_VERSION)
325
+ return await self._get("time")
310
326
 
311
327
  get_server_time.__doc__ = Client.get_server_time.__doc__
312
328
 
@@ -319,7 +335,7 @@ class AsyncClient(BaseClient):
319
335
  if symbol:
320
336
  params["symbol"] = symbol
321
337
  response = await self._get(
322
- "ticker/price", version=self.PRIVATE_API_VERSION, data=params
338
+ "ticker/price", data=params
323
339
  )
324
340
  if isinstance(response, list) and all(isinstance(item, dict) for item in response):
325
341
  return response
@@ -334,13 +350,13 @@ class AsyncClient(BaseClient):
334
350
  elif "symbols" in params:
335
351
  data["symbols"] = params["symbols"]
336
352
  return await self._get(
337
- "ticker/bookTicker", data=data, version=self.PRIVATE_API_VERSION
353
+ "ticker/bookTicker", data=data
338
354
  )
339
355
 
340
356
  get_orderbook_tickers.__doc__ = Client.get_orderbook_tickers.__doc__
341
357
 
342
358
  async def get_order_book(self, **params) -> Dict:
343
- return await self._get("depth", data=params, version=self.PRIVATE_API_VERSION)
359
+ return await self._get("depth", data=params)
344
360
 
345
361
  get_order_book.__doc__ = Client.get_order_book.__doc__
346
362
 
@@ -351,14 +367,14 @@ class AsyncClient(BaseClient):
351
367
 
352
368
  async def get_historical_trades(self, **params) -> Dict:
353
369
  return await self._get(
354
- "historicalTrades", data=params, version=self.PRIVATE_API_VERSION
370
+ "historicalTrades", data=params
355
371
  )
356
372
 
357
373
  get_historical_trades.__doc__ = Client.get_historical_trades.__doc__
358
374
 
359
375
  async def get_aggregate_trades(self, **params) -> Dict:
360
376
  return await self._get(
361
- "aggTrades", data=params, version=self.PRIVATE_API_VERSION
377
+ "aggTrades", data=params
362
378
  )
363
379
 
364
380
  get_aggregate_trades.__doc__ = Client.get_aggregate_trades.__doc__
@@ -419,12 +435,12 @@ class AsyncClient(BaseClient):
419
435
  aggregate_trade_iter.__doc__ = Client.aggregate_trade_iter.__doc__
420
436
 
421
437
  async def get_ui_klines(self, **params) -> Dict:
422
- return await self._get("uiKlines", data=params, version=self.PRIVATE_API_VERSION)
438
+ return await self._get("uiKlines", data=params)
423
439
 
424
440
  get_ui_klines.__doc__ = Client.get_ui_klines.__doc__
425
441
 
426
442
  async def get_klines(self, **params) -> Dict:
427
- return await self._get("klines", data=params, version=self.PRIVATE_API_VERSION)
443
+ return await self._get("klines", data=params)
428
444
 
429
445
  get_klines.__doc__ = Client.get_klines.__doc__
430
446
 
@@ -655,33 +671,33 @@ class AsyncClient(BaseClient):
655
671
 
656
672
  async def get_avg_price(self, **params):
657
673
  return await self._get(
658
- "avgPrice", data=params, version=self.PRIVATE_API_VERSION
674
+ "avgPrice", data=params
659
675
  )
660
676
 
661
677
  get_avg_price.__doc__ = Client.get_avg_price.__doc__
662
678
 
663
679
  async def get_ticker(self, **params):
664
680
  return await self._get(
665
- "ticker/24hr", data=params, version=self.PRIVATE_API_VERSION
681
+ "ticker/24hr", data=params
666
682
  )
667
683
 
668
684
  get_ticker.__doc__ = Client.get_ticker.__doc__
669
685
 
670
686
  async def get_symbol_ticker(self, **params):
671
687
  return await self._get(
672
- "ticker/price", data=params, version=self.PRIVATE_API_VERSION
688
+ "ticker/price", data=params
673
689
  )
674
690
 
675
691
  get_symbol_ticker.__doc__ = Client.get_symbol_ticker.__doc__
676
692
 
677
693
  async def get_symbol_ticker_window(self, **params):
678
- return await self._get("ticker", data=params, version=self.PRIVATE_API_VERSION)
694
+ return await self._get("ticker", data=params)
679
695
 
680
696
  get_symbol_ticker_window.__doc__ = Client.get_symbol_ticker_window.__doc__
681
697
 
682
698
  async def get_orderbook_ticker(self, **params):
683
699
  return await self._get(
684
- "ticker/bookTicker", data=params, version=self.PRIVATE_API_VERSION
700
+ "ticker/bookTicker", data=params
685
701
  )
686
702
 
687
703
  get_orderbook_ticker.__doc__ = Client.get_orderbook_ticker.__doc__
@@ -1727,11 +1743,11 @@ class AsyncClient(BaseClient):
1727
1743
 
1728
1744
  futures_premium_index_klines.__doc__ = Client.futures_index_price_klines.__doc__
1729
1745
 
1730
- async def futures_continous_klines(self, **params):
1746
+ async def futures_continuous_klines(self, **params):
1731
1747
  return await self._request_futures_api("get", "continuousKlines", data=params)
1732
1748
 
1733
1749
  async def futures_historical_klines(
1734
- self, symbol, interval, start_str, end_str=None, limit=500
1750
+ self, symbol: str, interval: str, start_str, end_str=None, limit=None
1735
1751
  ):
1736
1752
  return await self._historical_klines(
1737
1753
  symbol,
@@ -1876,6 +1892,77 @@ class AsyncClient(BaseClient):
1876
1892
  params["newClientOrderId"] = self.CONTRACT_ORDER_PREFIX + self.uuid22()
1877
1893
  return await self._request_futures_api("post", "order", True, data=params)
1878
1894
 
1895
+ async def futures_limit_order(self, **params):
1896
+ """Send in a new futures limit order.
1897
+
1898
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/rest-api
1899
+
1900
+ """
1901
+ if "newClientOrderId" not in params:
1902
+ params["newClientOrderId"] = self.CONTRACT_ORDER_PREFIX + self.uuid22()
1903
+ params["type"] = "LIMIT"
1904
+ return await self._request_futures_api("post", "order", True, data=params)
1905
+
1906
+ async def futures_market_order(self, **params):
1907
+ """Send in a new futures market order.
1908
+
1909
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/rest-api
1910
+
1911
+ """
1912
+ if "newClientOrderId" not in params:
1913
+ params["newClientOrderId"] = self.CONTRACT_ORDER_PREFIX + self.uuid22()
1914
+ params["type"] = "MARKET"
1915
+ return await self._request_futures_api("post", "order", True, data=params)
1916
+
1917
+
1918
+ async def futures_limit_buy_order(self, **params):
1919
+ """Send in a new futures limit buy order.
1920
+
1921
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/rest-api
1922
+
1923
+ """
1924
+ if "newClientOrderId" not in params:
1925
+ params["newClientOrderId"] = self.CONTRACT_ORDER_PREFIX + self.uuid22()
1926
+ params["side"] = "BUY"
1927
+ params["type"] = "LIMIT"
1928
+ return await self._request_futures_api("post", "order", True, data=params)
1929
+
1930
+ async def futures_limit_sell_order(self, **params):
1931
+ """Send in a new futures limit sell order.
1932
+
1933
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/rest-api
1934
+
1935
+ """
1936
+ if "newClientOrderId" not in params:
1937
+ params["newClientOrderId"] = self.CONTRACT_ORDER_PREFIX + self.uuid22()
1938
+ params["side"] = "SELL"
1939
+ params["type"] = "LIMIT"
1940
+ return await self._request_futures_api("post", "order", True, data=params)
1941
+
1942
+ async def futures_market_buy_order(self, **params):
1943
+ """Send in a new futures market buy order.
1944
+
1945
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/rest-api
1946
+
1947
+ """
1948
+ if "newClientOrderId" not in params:
1949
+ params["newClientOrderId"] = self.CONTRACT_ORDER_PREFIX + self.uuid22()
1950
+ params["side"] = "BUY"
1951
+ params["type"] = "MARKET"
1952
+ return await self._request_futures_api("post", "order", True, data=params)
1953
+
1954
+ async def futures_market_sell_order(self, **params):
1955
+ """Send in a new futures market sell order.
1956
+
1957
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/rest-api
1958
+
1959
+ """
1960
+ if "newClientOrderId" not in params:
1961
+ params["newClientOrderId"] = self.CONTRACT_ORDER_PREFIX + self.uuid22()
1962
+ params["side"] = "SELL"
1963
+ params["type"] = "MARKET"
1964
+ return await self._request_futures_api("post", "order", True, data=params)
1965
+
1879
1966
  async def futures_modify_order(self, **params):
1880
1967
  """Modify an existing order. Currently only LIMIT order modification is supported.
1881
1968
 
@@ -5363,4 +5450,4 @@ class AsyncClient(BaseClient):
5363
5450
  return await self._request_futures_api("get", "convert/orderStatus", signed=True, data=params, version=1)
5364
5451
 
5365
5452
  futures_v1_get_convert_order_status.__doc__ = Client.futures_v1_get_convert_order_status.__doc__
5366
-
5453
+
@@ -22,14 +22,17 @@ from .helpers import get_loop
22
22
  class BaseClient:
23
23
  API_URL = "https://api{}.binance.{}/api"
24
24
  API_TESTNET_URL = "https://testnet.binance.vision/api"
25
+ API_DEMO_URL = "https://demo-api.binance.com/api"
25
26
  MARGIN_API_URL = "https://api{}.binance.{}/sapi"
26
27
  WEBSITE_URL = "https://www.binance.{}"
27
28
  FUTURES_URL = "https://fapi.binance.{}/fapi"
28
29
  FUTURES_TESTNET_URL = "https://testnet.binancefuture.com/fapi"
30
+ FUTURES_DEMO_URL = "https://demo-fapi.binance.com/fapi"
29
31
  FUTURES_DATA_URL = "https://fapi.binance.{}/futures/data"
30
32
  FUTURES_DATA_TESTNET_URL = "https://testnet.binancefuture.com/futures/data"
31
33
  FUTURES_COIN_URL = "https://dapi.binance.{}/dapi"
32
34
  FUTURES_COIN_TESTNET_URL = "https://testnet.binancefuture.com/dapi"
35
+ FUTURES_COIN_DEMO_URL = "https://demo-dapi.binance.com/dapi"
33
36
  FUTURES_COIN_DATA_URL = "https://dapi.binance.{}/futures/data"
34
37
  FUTURES_COIN_DATA_TESTNET_URL = "https://testnet.binancefuture.com/futures/data"
35
38
  OPTIONS_URL = "https://eapi.binance.{}/eapi"
@@ -37,9 +40,11 @@ class BaseClient:
37
40
  PAPI_URL = "https://papi.binance.{}/papi"
38
41
  WS_API_URL = "wss://ws-api.binance.{}/ws-api/v3"
39
42
  WS_API_TESTNET_URL = "wss://ws-api.testnet.binance.vision/ws-api/v3"
43
+ WS_API_DEMO_URL = "wss://demo-ws-api.binance.com/ws-api/v3"
40
44
  WS_FUTURES_URL = "wss://ws-fapi.binance.{}/ws-fapi/v1"
41
45
  WS_FUTURES_TESTNET_URL = "wss://testnet.binancefuture.com/ws-fapi/v1"
42
- PUBLIC_API_VERSION = "v1"
46
+ WS_FUTURES_DEMO_URL = "wss://testnet.binancefuture.com/ws-fapi/v1"
47
+ PUBLIC_API_VERSION = "v3"
43
48
  PRIVATE_API_VERSION = "v3"
44
49
  MARGIN_API_VERSION = "v1"
45
50
  MARGIN_API_VERSION2 = "v2"
@@ -157,6 +162,7 @@ class BaseClient:
157
162
  tld: str = "com",
158
163
  base_endpoint: str = BASE_ENDPOINT_DEFAULT,
159
164
  testnet: bool = False,
165
+ demo: bool = False,
160
166
  private_key: Optional[Union[str, Path]] = None,
161
167
  private_key_pass: Optional[str] = None,
162
168
  loop: Optional[asyncio.AbstractEventLoop] = None,
@@ -201,15 +207,27 @@ class BaseClient:
201
207
  self._requests_params = requests_params
202
208
  self.response = None
203
209
  self.testnet = testnet
210
+ self.demo = demo
204
211
  self.timestamp_offset = 0
205
- ws_api_url = self.WS_API_TESTNET_URL if testnet else self.WS_API_URL.format(tld)
212
+ ws_api_url = self.WS_API_URL.format(tld)
213
+ if testnet:
214
+ ws_api_url = self.WS_API_TESTNET_URL
215
+ elif demo:
216
+ ws_api_url = self.WS_API_DEMO_URL
206
217
  if self.TIME_UNIT:
207
218
  ws_api_url += f"?timeUnit={self.TIME_UNIT}"
208
- self.ws_api = WebsocketAPI(url=ws_api_url, tld=tld)
209
- ws_future_url = (
210
- self.WS_FUTURES_TESTNET_URL if testnet else self.WS_FUTURES_URL.format(tld)
211
- )
212
- self.ws_future = WebsocketAPI(url=ws_future_url, tld=tld)
219
+ # Extract proxy from requests_params for WebSocket connections
220
+ https_proxy = None
221
+ if requests_params and 'proxies' in requests_params:
222
+ https_proxy = requests_params['proxies'].get('https') or requests_params['proxies'].get('http')
223
+
224
+ self.ws_api = WebsocketAPI(url=ws_api_url, tld=tld, https_proxy=https_proxy)
225
+ ws_future_url = self.WS_FUTURES_URL.format(tld)
226
+ if testnet:
227
+ ws_future_url = self.WS_FUTURES_TESTNET_URL
228
+ elif demo:
229
+ ws_future_url = self.WS_FUTURES_DEMO_URL
230
+ self.ws_future = WebsocketAPI(url=ws_future_url, tld=tld, https_proxy=https_proxy)
213
231
  self.loop = loop or get_loop()
214
232
 
215
233
  def _get_headers(self) -> Dict:
@@ -250,6 +268,8 @@ class BaseClient:
250
268
  url = self.API_URL
251
269
  if self.testnet:
252
270
  url = self.API_TESTNET_URL
271
+ elif self.demo:
272
+ url = self.API_DEMO_URL
253
273
  v = self.PRIVATE_API_VERSION if signed else version
254
274
  return url + "/" + v + "/" + path
255
275
 
@@ -273,6 +293,8 @@ class BaseClient:
273
293
  url = self.FUTURES_URL
274
294
  if self.testnet:
275
295
  url = self.FUTURES_TESTNET_URL
296
+ elif self.demo:
297
+ url = self.FUTURES_DEMO_URL
276
298
  options = {
277
299
  1: self.FUTURES_API_VERSION,
278
300
  2: self.FUTURES_API_VERSION2,
@@ -290,6 +312,8 @@ class BaseClient:
290
312
  url = self.FUTURES_COIN_URL
291
313
  if self.testnet:
292
314
  url = self.FUTURES_COIN_TESTNET_URL
315
+ elif self.demo:
316
+ url = self.FUTURES_COIN_DEMO_URL
293
317
  options = {
294
318
  1: self.FUTURES_API_VERSION,
295
319
  2: self.FUTURES_API_VERSION2,