Kraken API 'EAPI: неверный ключ' с Python3 - PullRequest
0 голосов
/ 30 января 2019

Я попытался сделать простую функцию, которая делает HTTP-запрос к API обмена Kraken.Метод частный, я пытаюсь получить остаток на моем счете.

Согласно документации Kraken (https://www.kraken.com/features/api#general-usage):

HTTP-заголовок:

API-Key = API-ключ

API-Sign = подпись сообщения с использованием HMAC-SHA512 (URI-путь + SHA256 (nonce + POST-данные)) и декодированного base64 секретного API-ключа

POST-данные:

nonce = всегда увеличивающееся 64-разрядное целое число без знака

otp = двухфакторный пароль (если двухфакторный включен, в противном случае не требуется)

Я пытался сделать генерацию моей подписи похожей наPython-библиотека "veox" (доступна по адресу: https://github.com/veox/python3-krakenex/blob/master/krakenex/api.py).

Я использую Python 3.6.7 в Ubuntu 18.04.

2FA (otp) включен для моей учетной записи на обмене Kraken, хотяЯ не уверен, что мне нужно включить в запрос.

Я искал переполнение стека для решения, но я не могу получить что-либо из доступных сообщений. (Пожалуйста, имейте в виду, что я довольноплохо знакомы с Python и переполнением стека)

Я получил 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 голосов
/ 26 февраля 2019

Итак, я понял, почему мой код не работает.

Краткий ответ:

  1. Данные POST, используемые в вызове API Kraken, должны быть закодированы в URL.Это означает, что для правильной работы API «nonce» и «otp» должны быть закодированы в URL.Я использовал метод "urllib.parse.urlencode" из модуля "urllib", чтобы заставить API работать должным образом.
  2. Значения заголовка должны явно называться теми же именами, что и в руководстве по Kraken API.

Длинный ответ:

  1. Это может быть потому, что я новичок в программировании API, но в руководстве по Kraken API явно не указано, что данные POST должны быть закодированы в URL.OTP (двухфакторная аутентификация) в этом случае не повлияла на мой код, поэтому я избавился от этой части данных POST в вызове.

В моем случае единственными данными POST, которые я использовал, было значение "nonce".Так, например, если в приведенном выше коде одноразовый номер был равен

'nonce': 666999

то же значение, которое использовалось в вызове, , но URL, закодированный с помощью метода 'urllib.parse.urlencode', был быравно

"nonce=666999"
Опять же, вероятно, это не проблема для более опытных разработчиков, но для меня не было очевидным, что значения заголовков должны явно называться теми же именами, что и в руководстве по API Kraken.

Так что ввышеуказанный код

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)
...