Skip to content

Commit f008bac

Browse files
committed
Added error handling. Added tests. Added requirements. Fixed tests
1 parent d7dfc6f commit f008bac

File tree

6 files changed

+200
-66
lines changed

6 files changed

+200
-66
lines changed

gdax/authenticated_client.py

Lines changed: 44 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ def __init__(self, key, b64secret, passphrase, api_url="https://api.gdax.com", t
2323

2424
def get_account(self, account_id):
2525
r = requests.get(self.url + '/accounts/' + account_id, auth=self.auth, timeout=self.timeout)
26-
# r.raise_for_status()
27-
return r.json()
26+
return self._determine_response(r)
2827

2928
def get_accounts(self):
3029
return self.get_account('')
@@ -33,34 +32,35 @@ def get_account_history(self, account_id):
3332
result = []
3433
r = requests.get(self.url + '/accounts/{}/ledger'.format(account_id), auth=self.auth, timeout=self.timeout)
3534
# r.raise_for_status()
36-
result.append(r.json())
35+
r_json = self._determine_response(r)
36+
result.append(r_json)
3737
if "cb-after" in r.headers:
3838
self.history_pagination(account_id, result, r.headers["cb-after"])
3939
return result
4040

4141
def history_pagination(self, account_id, result, after):
4242
r = requests.get(self.url + '/accounts/{}/ledger?after={}'.format(account_id, str(after)), auth=self.auth, timeout=self.timeout)
43-
# r.raise_for_status()
44-
if r.json():
45-
result.append(r.json())
43+
r_json = self._determine_response(r)
44+
if r_json:
45+
result.append(r_json)
4646
if "cb-after" in r.headers:
4747
self.history_pagination(account_id, result, r.headers["cb-after"])
4848
return result
4949

5050
def get_account_holds(self, account_id):
5151
result = []
5252
r = requests.get(self.url + '/accounts/{}/holds'.format(account_id), auth=self.auth, timeout=self.timeout)
53-
# r.raise_for_status()
54-
result.append(r.json())
53+
r_json = self._determine_response(r)
54+
result.append(r_json)
5555
if "cb-after" in r.headers:
5656
self.holds_pagination(account_id, result, r.headers["cb-after"])
5757
return result
5858

5959
def holds_pagination(self, account_id, result, after):
6060
r = requests.get(self.url + '/accounts/{}/holds?after={}'.format(account_id, str(after)), auth=self.auth, timeout=self.timeout)
61-
# r.raise_for_status()
62-
if r.json():
63-
result.append(r.json())
61+
r_json = self._determine_response(r)
62+
if r_json:
63+
result.append(r_json)
6464
if "cb-after" in r.headers:
6565
self.holds_pagination(account_id, result, r.headers["cb-after"])
6666
return result
@@ -73,34 +73,31 @@ def buy(self, **kwargs):
7373
data=json.dumps(kwargs),
7474
auth=self.auth,
7575
timeout=self.timeout)
76-
return r.json()
76+
return self._determine_response(r)
7777

7878
def sell(self, **kwargs):
7979
kwargs["side"] = "sell"
8080
r = requests.post(self.url + '/orders',
8181
data=json.dumps(kwargs),
8282
auth=self.auth,
8383
timeout=self.timeout)
84-
return r.json()
84+
return self._determine_response(r)
8585

8686
def cancel_order(self, order_id):
8787
r = requests.delete(self.url + '/orders/' + order_id, auth=self.auth, timeout=self.timeout)
88-
# r.raise_for_status()
89-
return r.json()
88+
return self._determine_response(r)
9089

9190
def cancel_all(self, product_id=''):
9291
url = self.url + '/orders/'
9392
params = {}
9493
if product_id:
9594
params["product_id"] = product_id
9695
r = requests.delete(url, auth=self.auth, params=params, timeout=self.timeout)
97-
# r.raise_for_status()
98-
return r.json()
96+
return self._determine_response(r)
9997

10098
def get_order(self, order_id):
10199
r = requests.get(self.url + '/orders/' + order_id, auth=self.auth, timeout=self.timeout)
102-
# r.raise_for_status()
103-
return r.json()
100+
return self._determine_response(r)
104101

105102
def get_orders(self, product_id='', status=[]):
106103
result = []
@@ -111,8 +108,8 @@ def get_orders(self, product_id='', status=[]):
111108
if status:
112109
params["status"] = status
113110
r = requests.get(url, auth=self.auth, params=params, timeout=self.timeout)
114-
# r.raise_for_status()
115-
result.append(r.json())
111+
r_json = self._determine_response(r)
112+
result.append(r_json)
116113
if 'cb-after' in r.headers:
117114
self.paginate_orders(product_id, status, result, r.headers['cb-after'])
118115
return result
@@ -128,9 +125,9 @@ def paginate_orders(self, product_id, status, result, after):
128125
if status:
129126
params["status"] = status
130127
r = requests.get(url, auth=self.auth, params=params, timeout=self.timeout)
131-
# r.raise_for_status()
132-
if r.json():
133-
result.append(r.json())
128+
r_json = self._determine_response(r)
129+
if r_json:
130+
result.append(r_json)
134131
if 'cb-after' in r.headers:
135132
self.paginate_orders(product_id, status, result, r.headers['cb-after'])
136133
return result
@@ -149,9 +146,9 @@ def get_fills(self, order_id='', product_id='', before='', after='', limit=''):
149146
if limit:
150147
url += "limit={}&".format(str(limit))
151148
r = requests.get(url, auth=self.auth, timeout=self.timeout)
152-
# r.raise_for_status()
153-
result.append(r.json())
154-
if 'cb-after' in r.headers and limit is not len(r.json()):
149+
r_json = self._determine_response(r)
150+
result.append(r_json)
151+
if 'cb-after' in r.headers and limit is not len(r_json):
155152
return self.paginate_fills(result, r.headers['cb-after'], order_id=order_id, product_id=product_id)
156153
return result
157154

@@ -162,9 +159,9 @@ def paginate_fills(self, result, after, order_id='', product_id=''):
162159
if product_id:
163160
url += "product_id={}&".format(product_id)
164161
r = requests.get(url, auth=self.auth, timeout=self.timeout)
165-
# r.raise_for_status()
166-
if r.json():
167-
result.append(r.json())
162+
r_json = self._determine_response(r)
163+
if r_json:
164+
result.append(r_json)
168165
if 'cb-after' in r.headers:
169166
return self.paginate_fills(result, r.headers['cb-after'], order_id=order_id, product_id=product_id)
170167
return result
@@ -178,8 +175,8 @@ def get_fundings(self, result='', status='', after=''):
178175
if after:
179176
url += 'after={}&'.format(str(after))
180177
r = requests.get(url, auth=self.auth, timeout=self.timeout)
181-
# r.raise_for_status()
182-
result.append(r.json())
178+
r_json = self._determine_response(r)
179+
result.append(r_json)
183180
if 'cb-after' in r.headers:
184181
return self.get_fundings(result, status=status, after=r.headers['cb-after'])
185182
return result
@@ -190,8 +187,7 @@ def repay_funding(self, amount='', currency=''):
190187
"currency": currency # example: USD
191188
}
192189
r = requests.post(self.url + "/funding/repay", data=json.dumps(payload), auth=self.auth, timeout=self.timeout)
193-
# r.raise_for_status()
194-
return r.json()
190+
return self._determine_response(r)
195191

196192
def margin_transfer(self, margin_profile_id="", transfer_type="", currency="", amount=""):
197193
payload = {
@@ -201,21 +197,18 @@ def margin_transfer(self, margin_profile_id="", transfer_type="", currency="", a
201197
"amount": amount
202198
}
203199
r = requests.post(self.url + "/profiles/margin-transfer", data=json.dumps(payload), auth=self.auth, timeout=self.timeout)
204-
# r.raise_for_status()
205-
return r.json()
200+
return self._determine_response(r)
206201

207202
def get_position(self):
208203
r = requests.get(self.url + "/position", auth=self.auth, timeout=self.timeout)
209-
# r.raise_for_status()
210-
return r.json()
204+
return self._determine_response(r)
211205

212206
def close_position(self, repay_only=""):
213207
payload = {
214208
"repay_only": repay_only or False
215209
}
216210
r = requests.post(self.url + "/position/close", data=json.dumps(payload), auth=self.auth, timeout=self.timeout)
217-
# r.raise_for_status()
218-
return r.json()
211+
return self._determine_response(r)
219212

220213
def deposit(self, amount="", currency="", payment_method_id=""):
221214
payload = {
@@ -224,8 +217,7 @@ def deposit(self, amount="", currency="", payment_method_id=""):
224217
"payment_method_id": payment_method_id
225218
}
226219
r = requests.post(self.url + "/deposits/payment-method", data=json.dumps(payload), auth=self.auth, timeout=self.timeout)
227-
# r.raise_for_status()
228-
return r.json()
220+
return self._determine_response(r)
229221

230222
def coinbase_deposit(self, amount="", currency="", coinbase_account_id=""):
231223
payload = {
@@ -234,8 +226,7 @@ def coinbase_deposit(self, amount="", currency="", coinbase_account_id=""):
234226
"coinbase_account_id": coinbase_account_id
235227
}
236228
r = requests.post(self.url + "/deposits/coinbase-account", data=json.dumps(payload), auth=self.auth, timeout=self.timeout)
237-
# r.raise_for_status()
238-
return r.json()
229+
return self._determine_response(r)
239230

240231
def withdraw(self, amount="", currency="", payment_method_id=""):
241232
payload = {
@@ -244,8 +235,7 @@ def withdraw(self, amount="", currency="", payment_method_id=""):
244235
"payment_method_id": payment_method_id
245236
}
246237
r = requests.post(self.url + "/withdrawals/payment-method", data=json.dumps(payload), auth=self.auth, timeout=self.timeout)
247-
# r.raise_for_status()
248-
return r.json()
238+
return self._determine_response(r)
249239

250240
def coinbase_withdraw(self, amount="", currency="", coinbase_account_id=""):
251241
payload = {
@@ -254,8 +244,7 @@ def coinbase_withdraw(self, amount="", currency="", coinbase_account_id=""):
254244
"coinbase_account_id": coinbase_account_id
255245
}
256246
r = requests.post(self.url + "/withdrawals/coinbase-account", data=json.dumps(payload), auth=self.auth, timeout=self.timeout)
257-
# r.raise_for_status()
258-
return r.json()
247+
return self._determine_response(r)
259248

260249
def crypto_withdraw(self, amount="", currency="", crypto_address=""):
261250
payload = {
@@ -264,18 +253,15 @@ def crypto_withdraw(self, amount="", currency="", crypto_address=""):
264253
"crypto_address": crypto_address
265254
}
266255
r = requests.post(self.url + "/withdrawals/crypto", data=json.dumps(payload), auth=self.auth, timeout=self.timeout)
267-
# r.raise_for_status()
268-
return r.json()
256+
return self._determine_response(r)
269257

270258
def get_payment_methods(self):
271259
r = requests.get(self.url + "/payment-methods", auth=self.auth, timeout=self.timeout)
272-
# r.raise_for_status()
273-
return r.json()
260+
return self._determine_response(r)
274261

275262
def get_coinbase_accounts(self):
276263
r = requests.get(self.url + "/coinbase-accounts", auth=self.auth, timeout=self.timeout)
277-
# r.raise_for_status()
278-
return r.json()
264+
return self._determine_response(r)
279265

280266
def create_report(self, report_type="", start_date="", end_date="", product_id="", account_id="", report_format="",
281267
email=""):
@@ -289,20 +275,16 @@ def create_report(self, report_type="", start_date="", end_date="", product_id="
289275
"email": email
290276
}
291277
r = requests.post(self.url + "/reports", data=json.dumps(payload), auth=self.auth, timeout=self.timeout)
292-
# r.raise_for_status()
293-
return r.json()
278+
return self._determine_response(r)
294279

295280
def get_report(self, report_id=""):
296281
r = requests.get(self.url + "/reports/" + report_id, auth=self.auth, timeout=self.timeout)
297-
# r.raise_for_status()
298-
return r.json()
282+
return self._determine_response(r)
299283

300284
def get_trailing_volume(self):
301285
r = requests.get(self.url + "/users/self/trailing-volume", auth=self.auth, timeout=self.timeout)
302-
# r.raise_for_status()
303-
return r.json()
286+
return self._determine_response(r)
304287

305288
def get_deposit_address(self, account_id):
306289
r = requests.post(self.url + '/coinbase-accounts/{}/addresses'.format(account_id), auth=self.auth, timeout=self.timeout)
307-
# r.raise_for_status()
308-
return r.json()
290+
return self._determine_response(r)

gdax/exceptions.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
class GdaxException(Exception):
2+
"""
3+
Base GDAX Exception
4+
Raised when Bad Response returned from GDAX
5+
See: https://docs.gdax.com/?python#errors
6+
"""
7+
8+
def __init__(self, message, code):
9+
"""
10+
:param message: Message from GDAX response
11+
:type message: str
12+
:param code: HTTP Code
13+
:type code: int
14+
"""
15+
self._message = message
16+
self._code = code
17+
18+
@property
19+
def message(self):
20+
return self._message
21+
22+
@message.setter
23+
def message(self, message):
24+
self._message = message
25+
26+
27+
@property
28+
def code(self):
29+
return self._code
30+
31+
@message.setter
32+
def message(self, code):
33+
self._code = code
34+
35+
36+
class InvalidGdaxRequest(GdaxException):
37+
"""
38+
Raised on 400 response from GDAX
39+
"""
40+
pass
41+
42+
43+
class UnauthorizedGdaxRequest(GdaxException):
44+
"""
45+
Raised on 401 response from GDAX
46+
"""
47+
pass
48+
49+
50+
class ForbiddenGdaxRequest(GdaxException):
51+
"""
52+
Raised on 403 response from GDAX
53+
"""
54+
pass
55+
56+
57+
class NotFoundGdaxRequest(GdaxException):
58+
"""
59+
Raised on 404 response from GDAX
60+
"""
61+
pass
62+
63+
64+
class UnknownGdaxClientRequest(GdaxException):
65+
"""
66+
Raised on 4XX responses not tracked
67+
"""
68+
pass
69+
70+
71+
class InternalErrorGdaxRequest(GdaxException):
72+
"""
73+
Raised on 500 response from GDAX
74+
"""
75+
pass

0 commit comments

Comments
 (0)