Add authentication for rest client

This commit is contained in:
Jacob Plaster
2018-12-03 14:41:30 +00:00
parent d683faf459
commit 4fedaee51c
3 changed files with 71 additions and 17 deletions

View File

@@ -4,12 +4,16 @@ import time
import json
from ..utils.CustomLogger import CustomLogger
from ..utils.auth import generate_auth_headers
from ..models import Wallet
class BfxRest:
def __init__(self, API_KEY, API_SECRET, host='https://api.bitfinex.com/v2', loop=None,
logLevel='INFO', *args, **kwargs):
self.loop = loop or asyncio.get_event_loop()
self.API_KEY = API_KEY
self.API_SECRET = API_SECRET
self.host = host
self.logger = CustomLogger('BfxRest', logLevel=logLevel)
@@ -19,9 +23,23 @@ class BfxRest:
async with session.get(url) as resp:
text = await resp.text()
if resp.status is not 200:
raise Exception('Unable to seed trades. Received status {} - {}'
.format(resp.status, text))
return json.loads(text)
raise Exception('GET {} failed with status {} - {}'
.format(url, resp.status, text))
return await resp.json(text)
async def post(self, endpoint, data={}):
url = '{}/{}'.format(self.host, endpoint)
sData = json.dumps(data)
headers = generate_auth_headers(
self.API_KEY, self.API_SECRET, endpoint, sData)
headers["content-type"] = "application/json"
async with aiohttp.ClientSession() as session:
async with session.post(url, headers=headers, data=sData) as resp:
text = await resp.text()
if resp.status is not 200:
raise Exception('POST {} failed with status {} - {}'
.format(url, resp.status, text))
return await resp.json()
async def get_seed_candles(self, symbol):
endpoint = 'candles/trade:1m:{}/hist?limit=5000&_bfx=1'.format(symbol)
@@ -43,3 +61,12 @@ class BfxRest:
candles.sort(key=lambda x: x[0], reverse=True)
self.logger.info("Downloaded {} candles.".format(len(candles)))
return candles
##################################################
# Wallets #
##################################################
async def get_wallets(self):
endpoint = "auth/r/wallets"
raw_wallets = await self.post(endpoint)
return [ Wallet(rw[0], rw[1], rw[2], rw[3]) for rw in raw_wallets ]

39
bfxapi/utils/auth.py Normal file
View File

@@ -0,0 +1,39 @@
import hashlib
import hmac
import time
def generate_auth_payload(API_KEY, API_SECRET):
nonce = _gen_nonce()
authMsg, sig = _gen_signature(API_KEY, API_SECRET, nonce)
return {
'apiKey': API_KEY,
'authSig': sig,
'authNonce': nonce,
'authPayload': authMsg,
'event': 'auth'
}
def generate_auth_headers(API_KEY, API_SECRET, path, body):
nonce = str(_gen_nonce())
signature = "/api/v2/{}{}{}".format(path, nonce, body)
print (API_KEY)
print (API_SECRET)
h = hmac.new(API_SECRET.encode('utf8'), signature.encode('utf8'), hashlib.sha384)
signature = h.hexdigest()
return {
"bfx-nonce": nonce,
"bfx-apikey": API_KEY,
"bfx-signature": signature
}
def _gen_signature(API_KEY, API_SECRET, nonce):
authMsg = 'AUTH{}'.format(nonce)
secret = API_SECRET.encode('utf8')
sig = hmac.new(secret, authMsg.encode('utf8'), hashlib.sha384).hexdigest()
return authMsg, sig
def _gen_nonce():
return int(round(time.time() * 1000000))

View File

@@ -1,14 +1,13 @@
import asyncio
import json
import time
import hashlib
import hmac
import random
from .GenericWebsocket import GenericWebsocket, AuthError
from .SubscriptionManager import SubscriptionManager
from .WalletManager import WalletManager
from .OrderManager import OrderManager
from ..utils.auth import generate_auth_payload
from ..models import Order, Trade, OrderBook
class Flags:
@@ -392,18 +391,7 @@ class BfxWebsocket(GenericWebsocket):
self.logger.warn('Unknown websocket response: {}'.format(msg))
async def _ws_authenticate_socket(self):
nonce = int(round(time.time() * 1000000))
authMsg = 'AUTH{}'.format(nonce)
secret = self.API_SECRET.encode()
sig = hmac.new(secret, authMsg.encode(), hashlib.sha384).hexdigest()
hmac.new(secret, self.API_SECRET.encode('utf'), hashlib.sha384).hexdigest()
jdata = {
'apiKey': self.API_KEY,
'authSig': sig,
'authNonce': nonce,
'authPayload': authMsg,
'event': 'auth'
}
jdata = generate_auth_payload(self.API_KEY, self.API_SECRET)
await self.ws.send(json.dumps(jdata))
async def on_open(self):