Reputation: 2862
I am trying to use the Bittrex v3 beta API and I keep getting:
{'code': 'INVALID_SIGNATURE'}
as a response.
I have tried it with Javascript and Python, so I am including both scripts - please let me know if you see anything wrong.
Python (first attempt):
#!/Users/eamonwhite/.pyenv/versions/3.6.3/bin/python3.6
import requests
import time
import hashlib
from pprint import pprint
import json
import hmac
import base64
import codecs
# api-endpoint
url = "https://api.bittrex.com/v3/orders/closed"
api_key = b'yyyyyyyyy'
secret = b'xxxxxxxxx'
api_timestamp = str(int(time.time() * 1000))
print(api_timestamp)
params = {'marketSymbol':'BTC-LOOM','pageSize': 200,'startDate': '2019-09-25T01:10:27.000','endDate': '2019-09-25T01:29:27.000'}
signature = hashlib.sha512(b'').hexdigest()
pre_sign = api_timestamp+url+'GET'+signature
print(pre_sign)
pre_sign_var = pre_sign.encode()
sig = hmac.new(secret, pre_sign_var, hashlib.sha512).hexdigest()
headers = {'Api-Key': api_key, 'Api-Timestamp': api_timestamp, 'Api-Content-Hash': signature, 'Api-Signature': sig}
# sending get request and saving the response as response object
r = requests.get(url = url, params = params, headers = headers)
# extracting data in json format
data = r.json()
pprint(data)
Javascript (second attempt - pulling straight from API docs):
var CryptoJS = require("crypto-js");
const fetch = require('node-fetch');
const url = 'https://api.bittrex.com/v3/orders/closed';
const data = {'marketSymbol':'BTC-LOOM','pageSize': 200,'startDate': '2019-09-25T01:10:27.000','endDate': '2019-09-25T01:29:27.000'};
var content_hash = CryptoJS.SHA512('').toString(CryptoJS.enc.Hex);
var api_timestamp = new Date().getTime();
var pre_sign_string = api_timestamp+url+'GET'+content_hash;
var signature = CryptoJS.HmacSHA512(pre_sign_string, 'xxxxxxsecretxxxxx').toString(CryptoJS.enc.Hex);
const headers = {'Api-Key': 'zzzzz', 'Api-Timestamp': api_timestamp, 'Api-Content-Hash': content_hash, 'Api-Signature': signature, 'Content-Type': 'application/json'};
function obj_to_query(obj, base_url) {
var parts = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
}
}
return base_url+"?" + parts.join('&');
}
async function getOrders(url = '', data = {}, headers = {}) {
return fetch(url, {
method: 'get',
headers: headers,
})
.then(res => res.json())
.then(json => {
console.log(json)
return json
});
}
var query_string = obj_to_query(data, url)
var r = getOrders(query_string, data, headers);
console.log(r);
The error I am getting back concerns the Api-Signature
header, all of the other headers are correct or they would have thrown an error - I have output the string that I have before I sign it, and it looks exactly the same as in the documentation, so I feel like this must be a problem with the API because it is still in beta.
Please let me know if this is the case so I stop trying :) Thanks
Upvotes: 2
Views: 1670
Reputation: 51
Thanks for sharing your python code. I made some changes and got it working sharing my code hope it helps someone else:
import requests
import time
import hashlib
from pprint import pprint
import json
import hmac
import base64
import codecs
import urllib.parse
from collections import Counter
def query(method, request, query):
if query != '' and method == 'GET':
url = "https://api.bittrex.com/v3/" + str(request) + str('?') + str(urllib.parse.urlencode(query))
elif method == "DELETE":
url = "https://api.bittrex.com/v3/" + str(request) + str('/') + str(query)
else:
url = "https://api.bittrex.com/v3/" + str(request)
api_key = 'key'
secret = 'secret'
api_timestamp = str(int(time.time() * 1000))
if method == "POST":
payload = json.dumps(query)
else:
payload = ''
contentHash = hashlib.sha512(payload.encode()).hexdigest()
pre_sign = api_timestamp+url+method+contentHash
signature = hmac.new(secret.encode(), pre_sign.encode(), hashlib.sha512).hexdigest()
headers = {'Api-Key': api_key, 'Api-Timestamp': api_timestamp, 'Api-Content-Hash': contentHash, 'Api-Signature': signature, 'Content-Type': 'application/json', 'Accept': 'application/json'}
if method == "POST":
r = requests.post(url = url, data=json.dumps(query), headers = headers)
elif method == "DELETE":
r = requests.delete(url = url, headers = headers)
else:
r = requests.get(url = url, params = payload, headers = headers)
data = r.json()
return data
def getbalance():
return query('GET', 'balances', '')
def getopenorders(market):
return query('GET', 'orders/open', {'marketSymbol': market})
def buylimit(market, quantity, rate):
return query('POST', 'orders', {'marketSymbol': market, 'direction': 'BUY', 'type': 'LIMIT', 'timeInForce': 'GOOD_TIL_CANCELLED', 'quantity': quantity, 'limit': rate})
def selllimit(market, quantity, rate):
return query('POST', 'orders', {'marketSymbol': market, 'direction': 'SELL', 'type': 'LIMIT', 'timeInForce': 'GOOD_TIL_CANCELLED', 'quantity': quantity, 'limit': rate})
def getorderhistory(market):
return query('GET', 'orders/closed', {'marketSymbol': market})
def cancel(uuid):
return query('DELETE', 'orders', uuid)
#print (getbalance())
#print (getopenorders('XRP-USD'))
#print (buylimit('XRP-USD', '60', '0.10000000'))
#print (selllimit('XRP-USD', '100', '0.20000000'))
#print (getorderhistory('XRP-USD'))
#print (cancel('orderid-bla-bla-bla'))
Upvotes: 5
Reputation: 2862
finally got it working not sure why but one thing i did was move my url
out of the variable and included it in the return statement of the function that creates the encodedURI string..however, it always spits back the same data no matter what marketSymbol I use, and only a few trades come back...this is the output i get for /orders/closed everytime regardless of marketSymbol
:
[ { id: '62b7764c-2c35-4588-b01b-15fbc2e6fc16',
marketSymbol: 'BTC-USD',
direction: 'SELL',
type: 'LIMIT',
quantity: '0.00733630',
limit: '8315.81600000',
timeInForce: 'GOOD_TIL_CANCELLED',
fillQuantity: '0.00733630',
commission: '0.15251830',
proceeds: '61.00732139',
status: 'CLOSED',
createdAt: '2019-09-25T16:03:53.09Z',
updatedAt: '2019-09-25T16:03:53.09Z',
closedAt: '2019-09-25T16:03:53.09Z' },
{ id: '21ca06f8-8e00-4d71-993c-3a7d53f57f1c',
marketSymbol: 'BTC-USD',
direction: 'BUY',
type: 'LIMIT',
quantity: '0.00733630',
limit: '8334.93200000',
timeInForce: 'GOOD_TIL_CANCELLED',
fillQuantity: '0.00733630',
commission: '0.15286890',
proceeds: '61.14756163',
status: 'CLOSED',
createdAt: '2019-09-25T15:56:55.57Z',
updatedAt: '2019-09-25T15:57:02.92Z',
closedAt: '2019-09-25T15:57:02.92Z' },
{ id: '59f2d104-1213-4634-bbd9-6dc8e7d6b91f',
marketSymbol: 'BTC-USD',
direction: 'SELL',
type: 'LIMIT',
quantity: '0.00744902',
limit: '8250.00000000',
timeInForce: 'GOOD_TIL_CANCELLED',
fillQuantity: '0.00744902',
commission: '0.15363603',
proceeds: '61.45441500',
status: 'CLOSED',
createdAt: '2019-09-24T19:43:20.76Z',
updatedAt: '2019-09-24T19:43:21.09Z',
closedAt: '2019-09-24T19:43:21.09Z' },
{ id: 'e39d4a85-c144-493b-98e1-99c91db5bdad',
marketSymbol: 'BTC-USDT',
direction: 'BUY',
type: 'LIMIT',
quantity: '0.00939489',
limit: '10001.59789805',
timeInForce: 'GOOD_TIL_CANCELLED',
fillQuantity: '0.00939489',
commission: '0.23468751',
proceeds: '93.87500532',
status: 'CLOSED',
createdAt: '2019-09-22T16:37:46.92Z',
updatedAt: '2019-09-22T16:37:46.92Z',
closedAt: '2019-09-22T16:37:46.92Z' },
{ id: '5dcc5a06-1eab-460f-b353-78263e9dac0b',
marketSymbol: 'BTC-USDT',
direction: 'SELL',
type: 'LIMIT',
quantity: '0.00953213',
limit: '9907.07077638',
timeInForce: 'GOOD_TIL_CANCELLED',
fillQuantity: '0.00953213',
commission: '0.23608870',
proceeds: '94.43548654',
status: 'CLOSED',
createdAt: '2019-09-22T03:21:51.15Z',
updatedAt: '2019-09-22T03:29:40.98Z',
closedAt: '2019-09-22T03:29:40.98Z' },
{ id: 'bdc95671-fee0-46fb-bb48-4fdf2cee7cae',
marketSymbol: 'GRS-BTC',
direction: 'SELL',
type: 'LIMIT',
quantity: '22.56987578',
limit: '0.00002226',
timeInForce: 'GOOD_TIL_CANCELLED',
fillQuantity: '22.56987578',
commission: '0.00000125',
proceeds: '0.00050263',
status: 'CLOSED',
createdAt: '2019-09-22T03:15:19.59Z',
updatedAt: '2019-09-22T03:15:19.59Z',
closedAt: '2019-09-22T03:15:19.59Z' },
{ id: '3528c223-d40d-41bc-866c-6c92f0a38195',
marketSymbol: 'GRS-BTC',
direction: 'BUY',
type: 'LIMIT',
quantity: '22.56987578',
limit: '0.00002254',
timeInForce: 'GOOD_TIL_CANCELLED',
fillQuantity: '22.56987578',
commission: '0.00000126',
proceeds: '0.00050871',
status: 'CLOSED',
createdAt: '2019-09-22T02:55:56.84Z',
updatedAt: '2019-09-22T03:07:04.18Z',
closedAt: '2019-09-22T03:07:04.18Z' } ]
I am submitting a ticket with Bittrex
Upvotes: 0