带有Python3的Kraken API'EAPI:Invalid key'

时间:2019-01-30 18:25:18

标签: python-3.x kraken.com

我尝试制作一个简单的函数,该函数向Kraken交换API发出HTTP请求。该方法是私人的,我正在尝试获取我的帐户余额。

根据Kraken文档(https://www.kraken.com/features/api#general-usage):

  

HTTP标头:

     

API密钥= API密钥

     

API签名=使用(URI路径+ SHA256(即刻+ POST数据))的HMAC-SHA512和base64解码的秘密API进行消息签名   键

     

POST数据:

     

nonce =始终增加无符号64位整数

     

otp =两因素密码(如果启用了两因素密码,则不是必需的)

我试图使签名生成类似于“ veox” Python库(可从https://github.com/veox/python3-krakenex/blob/master/krakenex/api.py获得)。

我正在Ubuntu 18.04上使用Python 3.6.7。

我在Kraken交易所的帐户已启用2FA(otp),尽管我不确定是否需要包含在请求中。

我在堆栈溢出中搜索了解决方案,但似乎无法从帖子中得到任何信息。 (请记住,我是Python和Stack Overflow的新手)

我从服务器收到200条响应,因此我很确定问题出在生成签名上。

这是我的代码(xxx,yyy和zzz变量故意这样写):

Kraken_secret_key = 'xxx' 

Kraken_headers ={

    'Kraken_API_key': 'yyy' 

}

def Kraken_account_balance(Kraken_headers):

    URI_path= '/0/private/Balance'

    URL_path = 'https://api.kraken.com/0/private/Balance'

    Kraken_nonce = str(int(time.time()*1000))

    otp = 'zzz'

    Kraken_POST_data = {

        'nonce': Kraken_nonce,
        'otp': str(otp)

    } 

    encoded = (str(Kraken_nonce)+str(otp)).encode()  

    message = URI_path.encode() + hashlib.sha256(encoded).digest() 

    Kraken_signature = hmac.new(base64.b64decode(Kraken_secret_key), message, digestmod=hashlib.sha512)

    Kraken_signature_digest = base64.b64encode(Kraken_signature.digest())

    Kraken_headers['Kraken_API_Signature'] = Kraken_signature_digest.decode()

    response = requests.post(URL_path,data= Kraken_POST_data, headers = Kraken_headers)

    result = response.json()

    print(result)

1 个答案:

答案 0 :(得分:1)

所以我弄清楚了为什么我的代码无法正常工作。

简短答案:

    在Kraken API调用中使用的
  1. POST数据必须经过URL编码。这意味着必须对URL“ nonce”和“ otp”进行编码,API才能正常工作。我使用“ urllib”模块中的“ urllib.parse.urlencode”方法来使API正常工作。
  2. 标头值必须与Kraken API手册中的显式名称相同。

长答案:

  1. 这可能是因为我是编码API的初学者,但是Kraken API手册并未明确指出POST数据必须经过URL编码。 OTP(2要素认证)在这种情况下不影响我的代码,因此我摆脱了调用中的POST数据部分。

就我而言,我使用的唯一POST数据是“ nonce”值。因此,例如,如果在上面的代码中,随机数等于

'nonce': 666999

与调用中使用的值相同,但使用'urllib.parse.urlencode'方法编码的URL 将等于

"nonce=666999"
  1. 同样,对于更有经验的开发人员来说,这可能不是问题,但是对我来说,头值必须与Kraken API手册中的名称显式地相同并不是很明显。

所以在上面的代码中

Kraken_headers ={

'Kraken_API_key': 'yyy' 

}

Kraken_headers['Kraken_API_Signature'] = Kraken_signature_digest.decode() 

应重命名为

Kraken_headers ={

'API-Key': 'yyy' 

}

 Kraken_headers['API-Sign'] = Kraken_signature_digest.decode()

这是完整的工作代码,只需将私钥和公钥值替换为您的值:

import requests
import time 
import hmac
import hashlib
import json
import base64
import urllib

Kraken_secret_key = 'xxx' 

Kraken_headers ={

'API-Key': 'yyy' 

}

def Kraken_account_balance(Kraken_headers):

    URI_path= '/0/private/Balance'

    URL_path = 'https://api.kraken.com/0/private/Balance'

    Kraken_nonce = str(int(time.time()*1000))

    Kraken_POST_data = {

        'nonce': Kraken_nonce
    } 

    url_encoded_post_data = urllib.parse.urlencode(Kraken_POST_data) 

    encoded = (str(Kraken_POST_data['nonce'])+url_encoded_post_data).encode()  

    message = URI_path.encode() + hashlib.sha256(encoded).digest() 

    Kraken_signature = hmac.new(base64.b64decode(Kraken_secret_key), message,  
    hashlib.sha512)

    Kraken_signature_digest = base64.b64encode(Kraken_signature.digest())

    Kraken_headers['API-Sign'] = Kraken_signature_digest.decode()

    response = requests.post(URL_path,data= Kraken_POST_data, headers = 
    Kraken_headers)

    result = response.json()

    print(result)

Kraken_account_balance(Kraken_headers)