Skip to content

Commit 32eb767

Browse files
committed
Update __init__.py
This allows MOST of the member functions to utilized the updated API Secret method of authentication.
1 parent d3ea80d commit 32eb767

File tree

1 file changed

+102
-62
lines changed

1 file changed

+102
-62
lines changed

coinbase/__init__.py

Lines changed: 102 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,20 @@
3434
__author__ = 'gsibble'
3535

3636
from oauth2client.client import AccessTokenRefreshError, OAuth2Credentials, AccessTokenCredentialsError
37-
37+
import re
3838
import requests
3939
import httplib2
4040
import json
4141
import os
4242
import inspect
43-
43+
import hashlib
44+
import hmac
45+
import time
4446
#TODO: Switch to decimals from floats
4547
#from decimal import Decimal
4648

4749
from coinbase.config import COINBASE_ENDPOINT
48-
from coinbase.models import CoinbaseAmount, CoinbaseTransaction, CoinbaseUser, CoinbaseTransfer, CoinbaseError, CoinbasePaymentButton
50+
from coinbase.models import CoinbaseAmount, CoinbaseTransaction, CoinbaseUser, CoinbaseTransfer, CoinbaseError
4951

5052

5153
class CoinbaseAccount(object):
@@ -57,7 +59,8 @@ class CoinbaseAccount(object):
5759

5860
def __init__(self,
5961
oauth2_credentials=None,
60-
api_key=None):
62+
api_key=None,
63+
api_secret=None):
6164
"""
6265
6366
:param oauth2_credentials: JSON representation of Coinbase oauth2 credentials
@@ -96,6 +99,14 @@ def __init__(self,
9699
#Set our request parameters to be empty
97100
self.global_request_params = {}
98101

102+
elif api_key and api_secret:
103+
104+
self.api_key = api_key
105+
self.api_secret = api_secret
106+
107+
self.session.headers.update({'ACCESS_KEY': api_key})
108+
109+
99110
elif api_key:
100111
if type(api_key) is str:
101112

@@ -167,7 +178,15 @@ def balance(self):
167178
"""
168179

169180
url = COINBASE_ENDPOINT + '/account/balance'
170-
response = self.session.get(url, params=self.global_request_params)
181+
if(self.api_secret):
182+
nonce = int(time.time() * 1e6)
183+
message = str(nonce) + url
184+
signature = hmac.new(self.api_secret, message, hashlib.sha256).hexdigest()
185+
self.session.headers.update({'ACCESS_SIGNATURE': signature})
186+
self.session.headers.update({'ACCESS_NONCE': nonce})
187+
response = self.session.get(url=url, data=None)
188+
else:
189+
response = self.session.get(url, params=self.global_request_params)
171190
results = response.json()
172191
return CoinbaseAmount(results['amount'], results['currency'])
173192

@@ -179,8 +198,19 @@ def receive_address(self):
179198
:return: String address of account
180199
"""
181200
url = COINBASE_ENDPOINT + '/account/receive_address'
182-
response = self.session.get(url, params=self.global_request_params)
183-
return response.json()['address']
201+
if(self.api_secret):
202+
nonce = int(time.time() * 1e6)
203+
message = str(nonce) + url
204+
signature = hmac.new(self.api_secret, message, hashlib.sha256).hexdigest()
205+
self.session.headers.update({'ACCESS_SIGNATURE': signature})
206+
self.session.headers.update({'ACCESS_NONCE': nonce})
207+
response = self.session.get(url=url, data=None)
208+
209+
else:
210+
response = self.session.get(url, params=self.global_request_params)
211+
212+
results=response.json()
213+
return str(results['address'])
184214

185215
@property
186216
def contacts(self):
@@ -190,7 +220,15 @@ def contacts(self):
190220
:return: List of contacts in the account
191221
"""
192222
url = COINBASE_ENDPOINT + '/contacts'
193-
response = self.session.get(url, params=self.global_request_params)
223+
if(self.api_secret):
224+
nonce = int(time.time() * 1e6)
225+
message = str(nonce) + url
226+
signature = hmac.new(self.api_secret, message, hashlib.sha256).hexdigest()
227+
self.session.headers.update({'ACCESS_SIGNATURE': signature})
228+
self.session.headers.update({'ACCESS_NONCE': nonce})
229+
response = self.session.get(url=url, data=None)
230+
else:
231+
response = self.session.get(url, params=self.global_request_params)
194232
return [contact['contact'] for contact in response.json()['contacts']]
195233

196234

@@ -205,7 +243,8 @@ def buy_price(self, qty=1):
205243
"""
206244
url = COINBASE_ENDPOINT + '/prices/buy'
207245
params = {'qty': qty}
208-
params.update(self.global_request_params)
246+
if(self.api_secret==None):
247+
params.update(self.global_request_params)
209248
response = self.session.get(url, params=params)
210249
results = response.json()
211250
return CoinbaseAmount(results['amount'], results['currency'])
@@ -218,7 +257,8 @@ def sell_price(self, qty=1):
218257
"""
219258
url = COINBASE_ENDPOINT + '/prices/sell'
220259
params = {'qty': qty}
221-
params.update(self.global_request_params)
260+
if(self.api_secret==None):
261+
params.update(self.global_request_params)
222262
response = self.session.get(url, params=params)
223263
results = response.json()
224264
return CoinbaseAmount(results['amount'], results['currency'])
@@ -244,7 +284,16 @@ def buy_btc(self, qty, pricevaries=False):
244284
"qty": qty,
245285
"agree_btc_amount_varies": pricevaries
246286
}
247-
response = self.session.post(url=url, data=json.dumps(request_data), params=self.global_request_params)
287+
data = json.dumps(request_data)
288+
if(self.api_secret):
289+
nonce = int(time.time() * 1e6)
290+
message = str(nonce) + url + data
291+
signature = hmac.new(self.api_secret, message, hashlib.sha256).hexdigest()
292+
self.session.headers.update({'ACCESS_SIGNATURE': signature})
293+
self.session.headers.update({'ACCESS_NONCE': nonce})
294+
response = self.session.post(url=url, data=data)
295+
else:
296+
response = self.session.post(url=url, data=data, params=self.global_requestparams)
248297
response_parsed = response.json()
249298
if response_parsed['success'] == False:
250299
return CoinbaseError(response_parsed['errors'])
@@ -263,7 +312,16 @@ def sell_btc(self, qty):
263312
request_data = {
264313
"qty": qty,
265314
}
266-
response = self.session.post(url=url, data=json.dumps(request_data), params=self.global_request_params)
315+
data = json.dumps(request_data)
316+
if(self.api_secret):
317+
nonce = int(time.time() * 1e6)
318+
message = str(nonce) + url + data
319+
signature = hmac.new(self.api_secret, message, hashlib.sha256).hexdigest()
320+
self.session.headers.update({'ACCESS_SIGNATURE': signature})
321+
self.session.headers.update({'ACCESS_NONCE': nonce})
322+
response = self.session.post(url=url, data=data)
323+
else:
324+
response = self.session.post(url=url, data=data, params=self.global_requestparams)
267325
response_parsed = response.json()
268326
if response_parsed['success'] == False:
269327
return CoinbaseError(response_parsed['errors'])
@@ -300,7 +358,16 @@ def request(self, from_email, amount, notes='', currency='BTC'):
300358
}
301359
}
302360

303-
response = self.session.post(url=url, data=json.dumps(request_data), params=self.global_request_params)
361+
data = json.dumps(request_data)
362+
if(self.api_secret):
363+
nonce = int(time.time() * 1e6)
364+
message = str(nonce) + url + data
365+
signature = hmac.new(self.api_secret, message, hashlib.sha256).hexdigest()
366+
self.session.headers.update({'ACCESS_SIGNATURE': signature})
367+
self.session.headers.update({'ACCESS_NONCE': nonce})
368+
response = self.session.post(url=url, data=data)
369+
else:
370+
response = self.session.post(url=url, data=data, params=self.global_requestparams)
304371
response_parsed = response.json()
305372
if response_parsed['success'] == False:
306373
pass
@@ -338,7 +405,16 @@ def send(self, to_address, amount, notes='', currency='BTC'):
338405
}
339406
}
340407

341-
response = self.session.post(url=url, data=json.dumps(request_data), params=self.global_request_params)
408+
data = json.dumps(request_data)
409+
if(self.api_secret):
410+
nonce = int(time.time() * 1e6)
411+
message = str(nonce) + url + data
412+
signature = hmac.new(self.api_secret, message, hashlib.sha256).hexdigest()
413+
self.session.headers.update({'ACCESS_SIGNATURE': signature})
414+
self.session.headers.update({'ACCESS_NONCE': nonce})
415+
response = self.session.post(url=url, data=data)
416+
else:
417+
response = self.session.post(url=url, data=data, params=self.global_requestparams)
342418
response_parsed = response.json()
343419

344420
if response_parsed['success'] == False:
@@ -428,8 +504,8 @@ def get_user_details(self):
428504
url = COINBASE_ENDPOINT + '/users'
429505
response = self.session.get(url, params=self.global_request_params)
430506
results = response.json()
431-
432-
user_details = results['users'][0]['user']
507+
508+
user_details = results['users'],[0],['user']
433509

434510
#Convert our balance and limits to proper amounts
435511
balance = CoinbaseAmount(user_details['balance']['amount'], user_details['balance']['currency'])
@@ -461,53 +537,17 @@ def generate_receive_address(self, callback_url=None):
461537
"callback_url": callback_url
462538
}
463539
}
464-
response = self.session.post(url=url, data=json.dumps(request_data), params=self.global_request_params)
540+
data = json.dumps(request_data)
541+
if(self.api_secret):
542+
nonce = int(time.time() * 1e6)
543+
message = str(nonce) + url + data
544+
signature = hmac.new(self.api_secret, message, hashlib.sha256).hexdigest()
545+
self.session.headers.update({'ACCESS_SIGNATURE': signature})
546+
self.session.headers.update({'ACCESS_NONCE': nonce})
547+
response = self.session.post(url=url, data=data)
548+
else:
549+
response = self.session.post(url=url, data=data, params=self.global_requestparams)
465550
return response.json()['address']
466551

467552

468-
def create_button(self, name, price, price_currency='BTC',
469-
button_type='buy_now', callback_url=None,
470-
**kwargs):
471-
"""
472-
Create a new payment button, page, or iframe.
473-
474-
Some required parameters are documented, but the rest are supported
475-
as keyword-arguments.
476-
477-
See https://coinbase.com/api/doc/1.0/buttons/create.html for details.
478-
479-
:param name: The name of the item to be purchased, donated for, or
480-
subscribed.
481-
:param price: The price, in whatever currency specified. Preferably a
482-
string or Decimal.
483-
:param price_currency: The ISO currency in which the price is listed.
484-
Eg, BTC or USD.
485-
:param button_type: Choices are 'buy_now', 'donation', and
486-
'subscription'
487-
:param callback_url: The URL to receive instant payment notifications
488553

489-
:return: The embeddable HTML string
490-
"""
491-
url = COINBASE_ENDPOINT + '/buttons'
492-
request_data = {
493-
"button": {
494-
"name":name,
495-
"price_string":unicode(price),
496-
"price_currency_iso":price_currency,
497-
"button_type":button_type
498-
}
499-
}
500-
if callback_url is not None:
501-
request_data['button']['callback_url'] = callback_url
502-
request_data['button'].update(kwargs)
503-
response = self.session.post(url=url, data=json.dumps(request_data),
504-
params=self.global_request_params)
505-
resp_data = response.json()
506-
if not resp_data['success'] or 'button' not in resp_data:
507-
error_msg = 'Error creating button'
508-
if 'errors' in resp_data:
509-
error_msg += ':' + u'\n'.join(resp_data)
510-
else:
511-
error_msg += '.'
512-
raise RuntimeError(error_msg)
513-
return CoinbasePaymentButton(**resp_data['button'])

0 commit comments

Comments
 (0)