Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v4.0.0 release #125

Merged
merged 1 commit into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 4.0.0 - 2023-08-08

### Changed
- Add proxy support for websockets
- Remove support for Python 3.7

## 4.0.0rc3 - 2023-07-03

### Changed
Expand Down
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,47 @@ my_client.agg_trade(symbol="bnbusdt", id="my_request_id")
# library will generate a random uuid string
my_client.agg_trade(symbol="bnbusdt")
```
#### Proxy

Proxy is supported for both WebSocket CM futures and UM futures.

To use it, pass in the `proxies` parameter when initializing the client.

The format of the `proxies` parameter is the same as the one used in the Spot RESTful API.

It consists on a dictionary with the following format, where the key is the type of the proxy and the value is the proxy URL:

For websockets, the proxy type is `http`.

```python
proxies = { 'http': 'http://1.2.3.4:8080' }
```

You can also use authentication for the proxy by adding the `username` and `password` parameters to the proxy URL:

```python
proxies = { 'http': 'http://username:password@host:port' }
```

```python
# WebSocket Stream Client
import time
from binance.websocket.um_futures.websocket_client import UMFuturesWebsocketClient

proxies = {'http': 'http://1.2.3.4:8080'}

def message_handler(_, message):
logging.info(message)

my_client = UMFuturesWebsocketClient(on_message=message_handler, proxies=proxies)

# Subscribe to a single symbol stream
my_client.agg_trade(symbol="bnbusdt")
time.sleep(5)
logging.info("closing ws connection")
my_client.stop()
```


#### Combined Streams
- If you set `is_combined` to `True`, `"/stream/"` will be appended to the `baseURL` to allow for Combining streams.
Expand Down
2 changes: 1 addition & 1 deletion binance/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "4.0.0rc3"
__version__ = "4.0.0"
20 changes: 18 additions & 2 deletions binance/lib/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
import time

from urllib.parse import urlencode
from urllib.parse import urlencode, urlparse
from binance.error import (
ParameterRequiredError,
ParameterValueError,
Expand Down Expand Up @@ -40,7 +40,7 @@ def check_enum_parameter(value, enum_class):


def check_type_parameter(value, name, data_type):
if value is not None and type(value) != data_type:
if value is not None and not isinstance(value, data_type):
raise ParameterTypeError([name, data_type])


Expand All @@ -64,3 +64,19 @@ def convert_list_to_json_array(symbols):

def config_logging(logging, logging_devel, log_file=None):
logging.basicConfig(level=logging_devel, filename=log_file)


def parse_proxies(proxies: dict):
"""Parse proxy url from dict, only support http and https proxy, not support socks5 proxy"""
proxy_url = proxies.get("http") or proxies.get("https")
if not proxy_url:
return {}

parsed = urlparse(proxy_url)
return {
"http_proxy_host": parsed.hostname,
"http_proxy_port": parsed.port,
"http_proxy_auth": (parsed.username, parsed.password)
if parsed.username and parsed.password
else None,
}
14 changes: 11 additions & 3 deletions binance/websocket/binance_socket_manager.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Optional

import logging
import threading
from websocket import (
Expand All @@ -6,6 +8,7 @@
WebSocketException,
WebSocketConnectionClosedException,
)
from binance.lib.utils import parse_proxies


class BinanceSocketManager(threading.Thread):
Expand All @@ -19,6 +22,7 @@ def __init__(
on_ping=None,
on_pong=None,
logger=None,
proxies: Optional[dict] = None,
):
threading.Thread.__init__(self)
if not logger:
Expand All @@ -31,15 +35,19 @@ def __init__(
self.on_ping = on_ping
self.on_pong = on_pong
self.on_error = on_error
self.proxies = proxies

self._proxy_params = parse_proxies(proxies) if proxies else {}

self.create_ws_connection()

def create_ws_connection(self):
self.logger.debug(
"Creating connection with WebSocket Server: %s", self.stream_url
f"Creating connection with WebSocket Server: {self.stream_url}, proxies: {self.proxies}",
)
self.ws = create_connection(self.stream_url)
self.ws = create_connection(self.stream_url, **self._proxy_params)
self.logger.debug(
"WebSocket connection has been established: %s", self.stream_url
f"WebSocket connection has been established: {self.stream_url}, proxies: {self.proxies}",
)
self._callback(self.on_open)

Expand Down
4 changes: 4 additions & 0 deletions binance/websocket/cm_futures/websocket_client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Optional

from binance.websocket.websocket_client import BinanceWebsocketClient


Expand All @@ -12,6 +14,7 @@ def __init__(
on_ping=None,
on_pong=None,
is_combined=False,
proxies: Optional[dict] = None,
):
if is_combined:
stream_url = stream_url + "/stream"
Expand All @@ -25,6 +28,7 @@ def __init__(
on_error=on_error,
on_ping=on_ping,
on_pong=on_pong,
proxies=proxies,
)

def agg_trade(self, symbol: str, id=None, action=None, **kwargs):
Expand Down
4 changes: 4 additions & 0 deletions binance/websocket/um_futures/websocket_client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Optional

from binance.websocket.websocket_client import BinanceWebsocketClient


Expand All @@ -12,6 +14,7 @@ def __init__(
on_ping=None,
on_pong=None,
is_combined=False,
proxies: Optional[dict] = None,
):
if is_combined:
stream_url = stream_url + "/stream"
Expand All @@ -25,6 +28,7 @@ def __init__(
on_error=on_error,
on_ping=on_ping,
on_pong=on_pong,
proxies=proxies,
)

def agg_trade(self, symbol: str, id=None, action=None, **kwargs):
Expand Down
7 changes: 7 additions & 0 deletions binance/websocket/websocket_client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from typing import Optional

import json
import logging

from binance.lib.utils import get_timestamp
from binance.websocket.binance_socket_manager import BinanceSocketManager

Expand All @@ -18,6 +21,7 @@ def __init__(
on_ping=None,
on_pong=None,
logger=None,
proxies: Optional[dict] = None,
):
if not logger:
logger = logging.getLogger(__name__)
Expand All @@ -31,6 +35,7 @@ def __init__(
on_ping,
on_pong,
logger,
proxies,
)

# start the thread
Expand All @@ -47,6 +52,7 @@ def _initialize_socket(
on_ping,
on_pong,
logger,
proxies,
):
return BinanceSocketManager(
stream_url,
Expand All @@ -57,6 +63,7 @@ def _initialize_socket(
on_ping=on_ping,
on_pong=on_pong,
logger=logger,
proxies=proxies,
)

def _single_stream(self, stream):
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@
"Intended Audience :: Developers",
"Intended Audience :: Financial and Insurance Industry",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
],
python_requires=">=3.7",
)
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = py36,py37,py38,py39
envlist = py38,py39,py310,py311

[testenv]
deps =
Expand Down
Loading