Skip to content

Commit 4a4aa19

Browse files
authored
Merge pull request #139 from kevinszielinski/ISSUE-128
ISSUE-128: fixed auth keys and encoding issues with websocket client
2 parents 1871e1b + d4c4521 commit 4a4aa19

File tree

3 files changed

+47
-41
lines changed

3 files changed

+47
-41
lines changed

gdax/authenticated_client.py

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import json
1313
from requests.auth import AuthBase
1414
from gdax.public_client import PublicClient
15+
from gdax.gdax_auth import GdaxAuth
1516

1617

1718
class AuthenticatedClient(PublicClient):
@@ -288,28 +289,4 @@ def get_report(self, report_id=""):
288289
def get_trailing_volume(self):
289290
r = requests.get(self.url + "/users/self/trailing-volume", auth=self.auth, timeout=30)
290291
# r.raise_for_status()
291-
return r.json()
292-
293-
294-
class GdaxAuth(AuthBase):
295-
# Provided by gdax: https://docs.gdax.com/#signing-a-message
296-
def __init__(self, api_key, secret_key, passphrase):
297-
self.api_key = api_key
298-
self.secret_key = secret_key
299-
self.passphrase = passphrase
300-
301-
def __call__(self, request):
302-
timestamp = str(time.time())
303-
message = timestamp + request.method + request.path_url + (request.body or '')
304-
message = message.encode('ascii')
305-
hmac_key = base64.b64decode(self.secret_key)
306-
signature = hmac.new(hmac_key, message, hashlib.sha256)
307-
signature_b64 = base64.b64encode(signature.digest())
308-
request.headers.update({
309-
'Content-Type': 'Application/JSON',
310-
'CB-ACCESS-SIGN': signature_b64,
311-
'CB-ACCESS-TIMESTAMP': timestamp,
312-
'CB-ACCESS-KEY': self.api_key,
313-
'CB-ACCESS-PASSPHRASE': self.passphrase
314-
})
315-
return request
292+
return r.json()

gdax/gdax_auth.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import hmac
2+
import hashlib
3+
import time
4+
import base64
5+
from requests.auth import AuthBase
6+
7+
8+
class GdaxAuth(AuthBase):
9+
# Provided by gdax: https://docs.gdax.com/#signing-a-message
10+
def __init__(self, api_key, secret_key, passphrase):
11+
self.api_key = api_key
12+
self.secret_key = secret_key
13+
self.passphrase = passphrase
14+
15+
def __call__(self, request):
16+
timestamp = str(time.time())
17+
message = timestamp + request.method + request.path_url + (request.body or '')
18+
request.headers.update(get_auth_headers(timestamp, message, self.api_key, self.secret_key,
19+
self.passphrase))
20+
return request
21+
22+
23+
def get_auth_headers(timestamp, message, api_key, secret_key, passphrase):
24+
message = message.encode('ascii')
25+
hmac_key = base64.b64decode(secret_key)
26+
signature = hmac.new(hmac_key, message, hashlib.sha256)
27+
signature_b64 = base64.b64encode(signature.digest()).decode('utf-8')
28+
return {
29+
'Content-Type': 'Application/JSON',
30+
'CB-ACCESS-SIGN': signature_b64,
31+
'CB-ACCESS-TIMESTAMP': timestamp,
32+
'CB-ACCESS-KEY': api_key,
33+
'CB-ACCESS-PASSPHRASE': passphrase
34+
}

gdax/websocket_client.py

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414
from threading import Thread
1515
from websocket import create_connection, WebSocketConnectionClosedException
1616
from pymongo import MongoClient
17+
from gdax.gdax_auth import get_auth_headers
1718

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

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

5758
if self.channels is None:
58-
sub_params = {'type': 'subscribe', 'product_ids': self.products}
59+
sub_params = {'type': 'subscribe', 'product_ids': self.products}
5960
else:
60-
sub_params = {'type': 'subscribe', 'product_ids': self.products, 'channels': self.channels}
61-
61+
sub_params = {'type': 'subscribe', 'product_ids': self.products, 'channels': self.channels}
6262

6363
if self.auth:
6464
timestamp = str(time.time())
6565
message = timestamp + 'GET' + '/users/self'
66-
message = message.encode('ascii')
67-
hmac_key = base64.b64decode(self.api_secret)
68-
signature = hmac.new(hmac_key, message, hashlib.sha256)
69-
signature_b64 = base64.b64encode(signature.digest())
70-
sub_params['signature'] = signature_b64
71-
sub_params['key'] = self.api_key
72-
sub_params['passphrase'] = self.api_passphrase
73-
sub_params['timestamp'] = timestamp
66+
sub_params.update(get_auth_headers(timestamp, message, self.api_key, self.api_secret, self.api_passphrase))
7467

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

84-
8577
def _listen(self):
8678
while not self.stop:
8779
try:
@@ -123,19 +115,21 @@ def on_close(self):
123115
def on_message(self, msg):
124116
if self.should_print:
125117
print(msg)
126-
if self.mongo_collection: # dump JSON to given mongo collection
118+
if self.mongo_collection: # dump JSON to given mongo collection
127119
self.mongo_collection.insert_one(msg)
128120

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

126+
134127
if __name__ == "__main__":
135128
import sys
136129
import gdax
137130
import time
138131

132+
139133
class MyWebsocketClient(gdax.WebsocketClient):
140134
def on_open(self):
141135
self.url = "wss://ws-feed.gdax.com/"
@@ -150,6 +144,7 @@ def on_message(self, msg):
150144
def on_close(self):
151145
print("-- Goodbye! --")
152146

147+
153148
wsClient = MyWebsocketClient()
154149
wsClient.start()
155150
print(wsClient.url, wsClient.products)

0 commit comments

Comments
 (0)