Python 3 hash HMAC-SHA512

I am writing a bot for https://poloniex.com/support/api/

Public methods work great, but the trading API methods require some extra tricks:

All trade API calls are sent via HTTP POST to https://poloniex.com/tradingApi and must contain the following headers:
Key - your API key.
Sign - POST request data signed with your secret key according to HMAC-SHA512 method.
In addition, all requests must include the "nonce" POST parameter. The nonce is an integer and must always be greater than the previous unused.
All responses from the trading API are in JSON format.

My code for returning Balances looks like this:

import hashlib
import hmac
from time import time

import requests


class Poloniex:
    def __init__(self, APIKey, Secret):
        self.APIKey = APIKey
        self.Secret = Secret

    def returnBalances(self):
        url = 'https://poloniex.com/tradingApi'
        payload = {
            'command': 'returnBalances',
            'nonce': int(time() * 1000),
        }

        headers = {
            'Key': self.APIKey,
            'Sign': hmac.new(self.Secret, payload, hashlib.sha512).hexdigest(),
        }

        r = requests.post(url, headers=headers, data=payload)
        return r.json()

      

trading.py:

APIkey = 'AAA-BBB-CCC'
secret = b'123abc'

polo = Poloniex(APIkey, secret)
print(polo.returnBalances())

      

And I got the following error:

Traceback (most recent call last):
  File "C:/Python/Poloniex/trading.py", line 5, in <module>
    print(polo.returnBalances())
  File "C:\Python\Poloniex\poloniex.py", line 22, in returnBalances
    'Sign': hmac.new(self.Secret, payload, hashlib.sha512).hexdigest(),
  File "C:\Users\Balazs91\AppData\Local\Programs\Python\Python35-32\lib\hmac.py", line 144, in new
    return HMAC(key, msg, digestmod)
  File "C:\Users\Balazs91\AppData\Local\Programs\Python\Python35-32\lib\hmac.py", line 84, in __init__
    self.update(msg)
  File "C:\Users\Balazs91\AppData\Local\Programs\Python\Python35-32\lib\hmac.py", line 93, in update
    self.inner.update(msg)
TypeError: object supporting the buffer API required

Process finished with exit code 1

      

I also tried to implement the following, but it did not help: qaru.site/questions/2406397 / ...

Any help is greatly appreciated!

+3


source to share


1 answer


The payload you pass to requests.post

must be either a valid query string or a dict matching that query string. It is generally more convenient to just pass a dict request and receive requests to create a query string for you, but in this case we need to build the HMAC signature from the query string, so we use the standard urlib.parse module to build the query string.

Annoyingly, the function urlib.parse.urlencode

returns a text string, so we need to encode it into a byte string to make it acceptable for hashlib. The obvious encoding to use is UTF-8: encoding a text string that only contains plain ASCII, since UTF-8 will produce a sequence of bytes identical to the equivalent Python 2 string (and of course urlencode

will only return plain ASCII), so this code will do itself is the same with the old Python 2 code on the Poloniex API page you linked to.

from time import time
import urllib.parse
import hashlib
import hmac

APIkey = b'AAA-BBB-CCC'
secret = b'123abc'

payload = {
    'command': 'returnBalances',
    'nonce': int(time() * 1000),
}

paybytes = urllib.parse.urlencode(payload).encode('utf8')
print(paybytes)

sign = hmac.new(secret, paybytes, hashlib.sha512).hexdigest()
print(sign)

      

Output



b'command=returnBalances&nonce=1492868800766'
3cd1630522382abc13f24b78138f30983c9b35614ece329a5abf4b8955429afe7d121ffee14b3c8c042fdaa7a0870102f9fb0b753ab793c084b1ad6a3553ea71

      

And then you can do something like

headers = {
    'Key': APIKey,
    'Sign': sign,
}

r = requests.post(url, headers=headers, data=paybytes)

      

+3


source







All Articles