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 import json
from ..utils.CustomLogger import CustomLogger from ..utils.CustomLogger import CustomLogger
from ..utils.auth import generate_auth_headers
from ..models import Wallet
class BfxRest: class BfxRest:
def __init__(self, API_KEY, API_SECRET, host='https://api.bitfinex.com/v2', loop=None, def __init__(self, API_KEY, API_SECRET, host='https://api.bitfinex.com/v2', loop=None,
logLevel='INFO', *args, **kwargs): logLevel='INFO', *args, **kwargs):
self.loop = loop or asyncio.get_event_loop() self.loop = loop or asyncio.get_event_loop()
self.API_KEY = API_KEY
self.API_SECRET = API_SECRET
self.host = host self.host = host
self.logger = CustomLogger('BfxRest', logLevel=logLevel) self.logger = CustomLogger('BfxRest', logLevel=logLevel)
@@ -19,9 +23,23 @@ class BfxRest:
async with session.get(url) as resp: async with session.get(url) as resp:
text = await resp.text() text = await resp.text()
if resp.status is not 200: if resp.status is not 200:
raise Exception('Unable to seed trades. Received status {} - {}' raise Exception('GET {} failed with status {} - {}'
.format(resp.status, text)) .format(url, resp.status, text))
return json.loads(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): async def get_seed_candles(self, symbol):
endpoint = 'candles/trade:1m:{}/hist?limit=5000&_bfx=1'.format(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) candles.sort(key=lambda x: x[0], reverse=True)
self.logger.info("Downloaded {} candles.".format(len(candles))) self.logger.info("Downloaded {} candles.".format(len(candles)))
return 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 asyncio
import json import json
import time import time
import hashlib
import hmac
import random import random
from .GenericWebsocket import GenericWebsocket, AuthError from .GenericWebsocket import GenericWebsocket, AuthError
from .SubscriptionManager import SubscriptionManager from .SubscriptionManager import SubscriptionManager
from .WalletManager import WalletManager from .WalletManager import WalletManager
from .OrderManager import OrderManager from .OrderManager import OrderManager
from ..utils.auth import generate_auth_payload
from ..models import Order, Trade, OrderBook from ..models import Order, Trade, OrderBook
class Flags: class Flags:
@@ -392,18 +391,7 @@ class BfxWebsocket(GenericWebsocket):
self.logger.warn('Unknown websocket response: {}'.format(msg)) self.logger.warn('Unknown websocket response: {}'.format(msg))
async def _ws_authenticate_socket(self): async def _ws_authenticate_socket(self):
nonce = int(round(time.time() * 1000000)) jdata = generate_auth_payload(self.API_KEY, self.API_SECRET)
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'
}
await self.ws.send(json.dumps(jdata)) await self.ws.send(json.dumps(jdata))
async def on_open(self): async def on_open(self):