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 from http import HTTPStatus
@@ -8,15 +8,32 @@ from . import serializers
from .typings import * from .typings import *
from .enums import Config, Precision, Sort from .enums import Config, Precision, Sort
from .exceptions import RequestParametersError, ResourceNotFound from .exceptions import RequestParametersError, ResourceNotFound, InvalidAuthenticationCredentials
class BfxRestInterface(object): class BfxRestInterface(object):
def __init__(self, host): def __init__(self, host, API_KEY = None, API_SECRET = None):
self.public = _RestPublicEndpoints(host=host) self.public = _RestPublicEndpoints(host=host)
self.auth = _RestAuthenticatedEndpoints(host=host, API_KEY=API_KEY, API_SECRET=API_SECRET)
class _Requests(object): class _Requests(object):
def __init__(self, host: str): def __init__(self, host, API_KEY = None, API_SECRET = None):
self.host = host 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): def _GET(self, endpoint, params = None):
response = requests.get(f"{self.host}/{endpoint}", params=params) response = requests.get(f"{self.host}/{endpoint}", params=params)
@@ -32,6 +49,28 @@ class _Requests(object):
return data 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): class _RestPublicEndpoints(_Requests):
def platform_status(self) -> PlatformStatus: def platform_status(self) -> PlatformStatus:
return serializers.PlatformStatus.parse(*self._GET("platform/status")) return serializers.PlatformStatus.parse(*self._GET("platform/status"))
@@ -186,3 +225,6 @@ class _RestPublicEndpoints(_Requests):
def conf(self, config: Config) -> Any: 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__ = [ __all__ = [
"RequestParametersError", "RequestParametersError",
"ResourceNotFound" "ResourceNotFound",
"InvalidAuthenticationCredentials"
] ]
class BfxRestException(Exception): class BfxRestException(Exception):
@@ -23,3 +24,10 @@ class ResourceNotFound(BfxRestException):
""" """
pass pass
class InvalidAuthenticationCredentials(BfxRestException):
"""
This error indicates that the user has provided incorrect credentials (API-KEY and API-SECRET) for authentication.
"""
pass