2

trying to view my listed accounts in coinbase and I've generated my hmac hash and got no errors however for some reason I'm still getting {'message': 'invalid signature'} and a 401 error, I even tried to make a new key in coinbase to make sure that wasn't the issue

here is my code for reference I'm just starting out so I have very little to show, I'm trying to make a barebones version of the api documentation shown here https://docs.pro.coinbase.com/#signing-a-message

I have checked to make sure my api key is enabled and has proper access to the coinbase api, but honestly the documentation definitely could use some work as I've seen a lot of unanswered questions similar to this on stack and github and I think some things have been left out, I am also turning my signed hash to lowercase below as that was recommended in another post


def get_accounts(self):
        print("getting accounts")
        secret = bytes(self.secret, 'UTF-8')

        #unicode objects must be encoded before hashing?? what is that??
        timestamp = str(time.time())
        message = timestamp + 'GET' + self.baseurl + 'accounts' + ''
        message = bytes(message, 'UTF-8')
      
        hmac_key = base64.b64decode(secret)
        signature = hmac.new(hmac_key, message, hashlib.sha256)
        signature = signature.hexdigest()
        print('signature',signature)
     

        #final base 64 byte string to send, but we probably need a regular string
        signature_b64 = base64.b64encode(bytes(signature, 'UTF-8'))
        signature_b64 = signature_b64.decode("utf-8") 
        
        print('final',signature_b64.lower())

        headers = {
            'CB-ACCESS-SIGN': signature_b64.lower(),
            'CB-ACCESS-TIMESTAMP': timestamp,
            'CB-ACCESS-KEY': self.key,
            'CB-ACCESS-PASSPHRASE': self.passphrase,
            'Content-Type': 'application/json'
        }
       
        r = requests.get(self.baseurl + 'accounts', headers=headers)
        print (r.status_code)
        print( r.json())
luther wardle
  • 439
  • 5
  • 17

2 Answers2

4

This works for me:

timestamp = str(time.time())
message = timestamp + request.method + request.path_url
message = message.encode('utf-8')
if request.body:
    message = message + request.body
hmac_key = base64.b64decode(self.api_secret)
signature = hmac.new(hmac_key, message, hashlib.sha256)
signature_b64 = base64.b64encode(signature.digest()).decode('utf-8')

request.headers.update({
    'CB-ACCESS-SIGN': signature_b64,
    'CB-ACCESS-TIMESTAMP': timestamp,
    'CB-ACCESS-KEY': self.api_key,
    'CB-ACCESS-PASSPHRASE': self.api_pass,
    'Content-Type': 'application/json'
})
user11499890
  • 131
  • 5
  • wow thanks for sharing, I'm playing around with mine now to see how it compares, do you have a sample of the request object you are using? :P – luther wardle Apr 04 '21 at 00:53
  • `order = { 'type': 'market', 'side': 'buy', 'product_id': "BTC-USD", 'size': 100.0, } response = requests.post("https://api.pro.coinbase.com/orders", json=order, auth=auth)` The auth is from the example code at https://docs.pro.coinbase.com/?python#creating-a-request – user11499890 Apr 05 '21 at 01:59
1

I struggled with this all afternoon, and found the coinbasepro python module to be the solution for me.

import coinbasepro
auth_client = coinbasepro.AuthenticatedClient(
    key=os.getenv(f'COINBASE_API_KEY'),
    secret=os.getenv(f'COINBASE_API_SECRET'),
    passphrase=os.getenv(f'COINBASE_API_PASSPHRASE')
)
accounts = auth_client.get_accounts()

It doesn't help that there are coinbase-commerce, coinbase[DEPRECATED], coinbase, and coinbasepro python modules all with different usage patterns.

Also, make sure you didn't switch the API KEY (shorter) and the API SECRET KEY (longer).

Chris
  • 425
  • 3
  • 12