Skip to content

Commit

Permalink
v3.3.0 release (#69)
Browse files Browse the repository at this point in the history
  • Loading branch information
2pd committed Jan 11, 2023
1 parent d30576a commit e09bb46
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 23 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
python-version: ["3.7", "3.8", "3.9", "3.10"]

steps:
- uses: actions/checkout@v2
Expand Down
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 3.3.0 - 2023-01-11

### Add
- RSA Key support

### Remove
- Python 3.6 Support Deprecated

## 3.2.0 - 2022-08-29

### Add
Expand Down Expand Up @@ -32,4 +40,4 @@

## 3.0.0 - 2022-05-26

- Refactor the connector
- Refactor the connector
25 changes: 22 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Binance Futures Public API Connector Python
[![Python 3.6](https://img.shields.io/badge/python-3.6+-blue.svg)](https://www.python.org/downloads/release/python-360/)
[![Python version](https://img.shields.io/pypi/pyversions/binance-futures-connector)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

This is a lightweight library that works as a connector to [Binance Futures public API](https://binance-docs.github.io/apidocs/futures/en/)
Expand Down Expand Up @@ -52,6 +52,25 @@ print(response)
```
Please find `examples` folder to check for more endpoints.

## Authentication
Binance supports HMAC and RSA API authentication.

```python
# HMAC Authentication
client = Client(api_key, api_secret)
print(client.account())

# RSA Authentication
key = ""
with open("/Users/john/private_key.pem", "r") as f: # Location of private key file
private_key = f.read()
private_key_passphrase = "" # Optional: only used for encrypted RSA key

client = Client(key=key, private_key=private_key, private_key_passphrase=private_key_passphrase)
print(client.account())
```
Please see `examples/um_futures/trade/get_account.py` or `examples/cm_futures/trade/get_account.py` for more details.

### Base URL

For USDT-M Futures, if `base_url` is not provided, it defaults to `fapi.binance.com`.<br/>
Expand Down Expand Up @@ -151,7 +170,7 @@ There are 2 types of error returned from the library:
- `status_code` - HTTP status code
- `error_code` - Server's error code, e.g. `-1102`
- `error_message` - Server's error message, e.g. `Unknown order sent.`
- `header` - Full response header.
- `header` - Full response header.
- `binance.error.ServerError`
- This is thrown when server returns `5XX`, it's an issue from server side.

Expand Down Expand Up @@ -193,4 +212,4 @@ Once connected, the websocket server sends a ping frame every 3 minutes and requ
a 10 minutes period. This package handles the pong responses automatically.

## License
MIT
MIT
2 changes: 1 addition & 1 deletion binance/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "3.2.0"
__version__ = "3.3.0"
23 changes: 13 additions & 10 deletions binance/api.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import hmac
import json
import logging
import hashlib
from json import JSONDecodeError

import requests
from .__version__ import __version__
from binance.error import ClientError, ServerError
from binance.lib.utils import get_timestamp
from binance.lib.utils import cleanNoneValue
from binance.lib.utils import encoded_string
from binance.lib.utils import check_required_parameter
from binance.lib.authentication import hmac_hashing, rsa_signature


class API(object):
Expand All @@ -33,13 +31,17 @@ def __init__(
proxies=None,
show_limit_usage=False,
show_header=False,
private_key=None,
private_key_passphrase=None,
):
self.key = key
self.secret = secret
self.timeout = timeout
self.show_limit_usage = False
self.show_header = False
self.proxies = None
self.private_key = private_key
self.private_key_pass = private_key_passphrase
self.session = requests.Session()
self.session.headers.update(
{
Expand Down Expand Up @@ -77,8 +79,7 @@ def sign_request(self, http_method, url_path, payload=None, special=False):
payload = {}
payload["timestamp"] = get_timestamp()
query_string = self._prepare_params(payload, special)
signature = self._get_sign(query_string)
payload["signature"] = signature
payload["signature"] = self._get_sign(query_string)
return self.send_request(http_method, url_path, payload, special)

def limited_encoded_sign_request(self, http_method, url_path, payload=None):
Expand All @@ -94,8 +95,9 @@ def limited_encoded_sign_request(self, http_method, url_path, payload=None):
payload = {}
payload["timestamp"] = get_timestamp()
query_string = self._prepare_params(payload)
signature = self._get_sign(query_string)
url_path = url_path + "?" + query_string + "&signature=" + signature
url_path = (
url_path + "?" + query_string + "&signature=" + self._get_sign(query_string)
)
return self.send_request(http_method, url_path)

def send_request(self, http_method, url_path, payload=None, special=False):
Expand Down Expand Up @@ -145,9 +147,10 @@ def send_request(self, http_method, url_path, payload=None, special=False):
def _prepare_params(self, params, special=False):
return encoded_string(cleanNoneValue(params), special)

def _get_sign(self, data):
m = hmac.new(self.secret.encode("utf-8"), data.encode("utf-8"), hashlib.sha256)
return m.hexdigest()
def _get_sign(self, payload):
if self.private_key:
return rsa_signature(self.private_key, payload, self.private_key_pass)
return hmac_hashing(self.secret, payload)

def _dispatch_request(self, http_method):
return {
Expand Down
18 changes: 18 additions & 0 deletions binance/lib/authentication.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import hmac
import hashlib
from base64 import b64encode
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256
from Crypto.Signature import pkcs1_15


def hmac_hashing(secret, payload):
m = hmac.new(secret.encode("utf-8"), payload.encode("utf-8"), hashlib.sha256)
return m.hexdigest()


def rsa_signature(private_key, payload, private_key_pass=None):
private_key = RSA.import_key(private_key, passphrase=private_key_pass)
h = SHA256.new(payload.encode("utf-8"))
signature = pkcs1_15.new(private_key).sign(h)
return b64encode(signature)
13 changes: 11 additions & 2 deletions examples/cm_futures/trade/get_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,22 @@

config_logging(logging, logging.DEBUG)

# HMAC authentication with API key and secret
key = ""
secret = ""

client = Client(key, secret)
hmac_client = Client(key=key, secret=secret)
logging.info(hmac_client.account(recvWindow=6000))

# RSA authentication with RSA key
key = ""
with open("/Users/john/private_key.pem", "r") as f:
private_key = f.read()

rsa_client = Client(key=key, private_key=private_key)

try:
response = client.account(recvWindow=6000)
response = rsa_client.account(recvWindow=6000)
logging.info(response)
except ClientError as error:
logging.error(
Expand Down
13 changes: 11 additions & 2 deletions examples/um_futures/trade/get_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,22 @@

config_logging(logging, logging.DEBUG)

# HMAC authentication with API key and secret
key = ""
secret = ""

um_futures_client = UMFutures(key=key, secret=secret)
hmac_client = UMFutures(key=key, secret=secret)
logging.info(hmac_client.account(recvWindow=6000))

# RSA authentication with RSA key
key = ""
with open("/Users/john/private_key.pem", "r") as f:
private_key = f.read()

rsa_client = UMFutures(key=key, private_key=private_key)

try:
response = um_futures_client.account(recvWindow=6000)
response = rsa_client.account(recvWindow=6000)
logging.info(response)
except ClientError as error:
logging.error(
Expand Down
3 changes: 2 additions & 1 deletion requirements/common.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ autobahn>=21.2.1
Twisted>=22.2.0
requests>=2.25.1
pyOpenSSL>=19.0.0
service-identity>=21.1.0
service-identity>=21.1.0
pycryptodome>=3.15.0
4 changes: 2 additions & 2 deletions 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.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
],
python_requires=">=3.6",
python_requires=">=3.7",
)

0 comments on commit e09bb46

Please sign in to comment.