Skip to content

Commit

Permalink
Merge pull request danpaquin#139 from kevinszielinski/ISSUE-128
Browse files Browse the repository at this point in the history
ISSUE-128: fixed auth keys and encoding issues with websocket client
  • Loading branch information
danpaquin authored Nov 8, 2017
2 parents 1871e1b + d4c4521 commit 4a4aa19
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 41 deletions.
27 changes: 2 additions & 25 deletions gdax/authenticated_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import json
from requests.auth import AuthBase
from gdax.public_client import PublicClient
from gdax.gdax_auth import GdaxAuth


class AuthenticatedClient(PublicClient):
Expand Down Expand Up @@ -288,28 +289,4 @@ def get_report(self, report_id=""):
def get_trailing_volume(self):
r = requests.get(self.url + "/users/self/trailing-volume", auth=self.auth, timeout=30)
# r.raise_for_status()
return r.json()


class GdaxAuth(AuthBase):
# Provided by gdax: https://docs.gdax.com/#signing-a-message
def __init__(self, api_key, secret_key, passphrase):
self.api_key = api_key
self.secret_key = secret_key
self.passphrase = passphrase

def __call__(self, request):
timestamp = str(time.time())
message = timestamp + request.method + request.path_url + (request.body or '')
message = message.encode('ascii')
hmac_key = base64.b64decode(self.secret_key)
signature = hmac.new(hmac_key, message, hashlib.sha256)
signature_b64 = base64.b64encode(signature.digest())
request.headers.update({
'Content-Type': 'Application/JSON',
'CB-ACCESS-SIGN': signature_b64,
'CB-ACCESS-TIMESTAMP': timestamp,
'CB-ACCESS-KEY': self.api_key,
'CB-ACCESS-PASSPHRASE': self.passphrase
})
return request
return r.json()
34 changes: 34 additions & 0 deletions gdax/gdax_auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import hmac
import hashlib
import time
import base64
from requests.auth import AuthBase


class GdaxAuth(AuthBase):
# Provided by gdax: https://docs.gdax.com/#signing-a-message
def __init__(self, api_key, secret_key, passphrase):
self.api_key = api_key
self.secret_key = secret_key
self.passphrase = passphrase

def __call__(self, request):
timestamp = str(time.time())
message = timestamp + request.method + request.path_url + (request.body or '')
request.headers.update(get_auth_headers(timestamp, message, self.api_key, self.secret_key,
self.passphrase))
return request


def get_auth_headers(timestamp, message, api_key, secret_key, passphrase):
message = message.encode('ascii')
hmac_key = base64.b64decode(secret_key)
signature = hmac.new(hmac_key, message, hashlib.sha256)
signature_b64 = base64.b64encode(signature.digest()).decode('utf-8')
return {
'Content-Type': 'Application/JSON',
'CB-ACCESS-SIGN': signature_b64,
'CB-ACCESS-TIMESTAMP': timestamp,
'CB-ACCESS-KEY': api_key,
'CB-ACCESS-PASSPHRASE': passphrase
}
27 changes: 11 additions & 16 deletions gdax/websocket_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
from threading import Thread
from websocket import create_connection, WebSocketConnectionClosedException
from pymongo import MongoClient
from gdax.gdax_auth import get_auth_headers

class WebsocketClient(object):
def __init__(self, url="wss://ws-feed.gdax.com", products=None, message_type="subscribe", mongo_collection=None,
should_print=True, auth=False, api_key="", api_secret="", api_passphrase="", channels=None):

class WebsocketClient(object):
def __init__(self, url="wss://ws-feed.gdax.com", products=None, message_type="subscribe", mongo_collection=None,
should_print=True, auth=False, api_key="", api_secret="", api_passphrase="", channels=None):
self.url = url
self.products = products
self.channels = channels
Expand Down Expand Up @@ -55,22 +56,14 @@ def _connect(self):
self.url = self.url[:-1]

if self.channels is None:
sub_params = {'type': 'subscribe', 'product_ids': self.products}
sub_params = {'type': 'subscribe', 'product_ids': self.products}
else:
sub_params = {'type': 'subscribe', 'product_ids': self.products, 'channels': self.channels}

sub_params = {'type': 'subscribe', 'product_ids': self.products, 'channels': self.channels}

if self.auth:
timestamp = str(time.time())
message = timestamp + 'GET' + '/users/self'
message = message.encode('ascii')
hmac_key = base64.b64decode(self.api_secret)
signature = hmac.new(hmac_key, message, hashlib.sha256)
signature_b64 = base64.b64encode(signature.digest())
sub_params['signature'] = signature_b64
sub_params['key'] = self.api_key
sub_params['passphrase'] = self.api_passphrase
sub_params['timestamp'] = timestamp
sub_params.update(get_auth_headers(timestamp, message, self.api_key, self.api_secret, self.api_passphrase))

self.ws = create_connection(self.url)
self.ws.send(json.dumps(sub_params))
Expand All @@ -81,7 +74,6 @@ def _connect(self):
sub_params = {"type": "heartbeat", "on": False}
self.ws.send(json.dumps(sub_params))


def _listen(self):
while not self.stop:
try:
Expand Down Expand Up @@ -123,19 +115,21 @@ def on_close(self):
def on_message(self, msg):
if self.should_print:
print(msg)
if self.mongo_collection: # dump JSON to given mongo collection
if self.mongo_collection: # dump JSON to given mongo collection
self.mongo_collection.insert_one(msg)

def on_error(self, e, data=None):
self.error = e
self.stop
print('{} - data: {}'.format(e, data))


if __name__ == "__main__":
import sys
import gdax
import time


class MyWebsocketClient(gdax.WebsocketClient):
def on_open(self):
self.url = "wss://ws-feed.gdax.com/"
Expand All @@ -150,6 +144,7 @@ def on_message(self, msg):
def on_close(self):
print("-- Goodbye! --")


wsClient = MyWebsocketClient()
wsClient.start()
print(wsClient.url, wsClient.products)
Expand Down

0 comments on commit 4a4aa19

Please sign in to comment.