Add authentication logic to _Requests class in BfxRestInterface.py. Add _RestAuthenticatedEndpoints class. Add InvalidAuthenticationCredentials in bfxapi/rest/exceptions.py.

This commit is contained in:
Davide Casale
2022-12-14 18:56:03 +01:00
parent 07241b1ba8
commit 851184bf75
2 changed files with 57 additions and 7 deletions

View File

@@ -1,4 +1,4 @@
import requests
import time, hmac, hashlib, json, requests
from http import HTTPStatus
@@ -8,15 +8,32 @@ from . import serializers
from .typings import *
from .enums import Config, Precision, Sort
from .exceptions import RequestParametersError, ResourceNotFound
from .exceptions import RequestParametersError, ResourceNotFound, InvalidAuthenticationCredentials
class BfxRestInterface(object):
def __init__(self, host):
def __init__(self, host, API_KEY = None, API_SECRET = None):
self.public = _RestPublicEndpoints(host=host)
self.auth = _RestAuthenticatedEndpoints(host=host, API_KEY=API_KEY, API_SECRET=API_SECRET)
class _Requests(object):
def __init__(self, host: str):
self.host = host
def __init__(self, host, API_KEY = None, API_SECRET = None):
self.host, self.API_KEY, self.API_SECRET = host, API_KEY, API_SECRET
def __build_authentication_headers(self, endpoint, data):
nonce = str(int(time.time()) * 1000)
signature = hmac.new(
self.API_SECRET.encode("utf8"),
f"/api/v2/{endpoint}{nonce}{json.dumps(data)}".encode("utf8"),
hashlib.sha384
).hexdigest()
return {
"bfx-nonce": nonce,
"bfx-signature": signature,
"bfx-apikey": self.API_KEY
}
def _GET(self, endpoint, params = None):
response = requests.get(f"{self.host}/{endpoint}", params=params)
@@ -32,6 +49,28 @@ class _Requests(object):
return data
def _POST(self, endpoint, params = None, data = None, _append_authentication_headers = True):
headers = { "Content-Type": "application/json" }
if _append_authentication_headers:
headers = { **headers, **self.__build_authentication_headers(f"{endpoint}", data) }
response = requests.post(f"{self.host}/{endpoint}", params=params, data=json.dumps(data), headers=headers)
if response.status_code == HTTPStatus.NOT_FOUND:
raise ResourceNotFound(f"No resources found at endpoint <{endpoint}>.")
data = response.json()
if len(data) and data[0] == "error":
if data[1] == 10020:
raise RequestParametersError(f"The request was rejected with the following parameter error: <{data[2]}>")
if data[1] == 10100:
raise InvalidAuthenticationCredentials("Cannot authenticate with given API-KEY and API-SECRET.")
return data
class _RestPublicEndpoints(_Requests):
def platform_status(self) -> PlatformStatus:
return serializers.PlatformStatus.parse(*self._GET("platform/status"))
@@ -185,4 +224,7 @@ class _RestPublicEndpoints(_Requests):
return [ serializers.FundingStat.parse(*subdata) for subdata in data ]
def conf(self, config: Config) -> Any:
return self._GET(f"conf/{config}")[0]
return self._GET(f"conf/{config}")[0]
class _RestAuthenticatedEndpoints(_Requests):
__PREFIX = "auth/"

View File

@@ -1,6 +1,7 @@
__all__ = [
"RequestParametersError",
"ResourceNotFound"
"ResourceNotFound",
"InvalidAuthenticationCredentials"
]
class BfxRestException(Exception):
@@ -22,4 +23,11 @@ class ResourceNotFound(BfxRestException):
This error indicates a failed HTTP request to a non-existent resource.
"""
pass
class InvalidAuthenticationCredentials(BfxRestException):
"""
This error indicates that the user has provided incorrect credentials (API-KEY and API-SECRET) for authentication.
"""
pass