Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

API Call Authentication in Python ( Working PHP example )

I'm trying to write a script to communicate with an online exchange.
'Public' requests are sent to : https://yobit.net/api/3/
'Trade' requests are sent to: https://yobit.net/tapi/

My public requests work great. My 'private calls' however return a 404 error. My keys are 100% correct.
I currently produce the following URL: https://yobit.net/tapi/activeorders/ltc_btc/&apikey=MY_APIKEY_HERE&nonce=1456192036

Did I missinterpret the documentation? Perhaps a false URL structure?

Documentation Link ---> here
Each Trade API request should pass authentication. Authentication is fulfilled by sending the following HTTP-titles: Key - API-key, example: FAF816D16FFDFBD1D46EEF5D5B10D8A2 Sign - digital signature, POST-parameters (?param0=val0 & ...& nonce=1) signed by secret key through HMAC-SHA512 Parameter nonce (1 minimum to 2147483646 maximum) in succeeding request should exceed that in the previous one. To null nonce it is necessary to generate new key.

My script

class yobit(object):

def __init__(self, key, secret):
    self.key = key
    self.secret = secret
    self.public = ['info', 'ticker', 'depth', 'trades']
    self.trade = ['activeorders']


def query(self, method, values={}):
    if method in self.public:
        url = 'https://yobit.net/api/3/'
    elif method in self.trade:
        url = 'https://yobit.net/tapi/'
    else:
        return 'You're doing it wrong'

    urlString = ''
    for i, k in values.iteritems():
        urlString += k+'/'

    url += method + '/' + urlString

    print url
    if method not in self.public:
        url += '&apikey=' + self.key
        url += '&nonce=' + str(int(time.time()))
        signature = hmac.new(self.secret, url, hashlib.sha512).hexdigest()
        headers = {'apisign': signature}
    else:
        headers = {}
    print url

    req = requests.get(url, headers=headers)
    response = json.loads(req.text)
    return response
####### PUBLIC API
def getinfo(self):
    return self.query('info')

def getticker(self, currency):
    return self.query('ticker', {'currency': currency})

def getdepth(self, currency):
    return self.query('depth', {'currency': currency})

def gettrades(self, currency):
    return self.query('trades', {'currency': currency})
##### TRADE API
def getactiveorders(self, pair):
    return self.query('activeorders', {'pair': pair})

A working example in PHP
I believe this to be a working example of PHP, unfortunately I can't read this language.

function yobit_api_query2($method, $req = array())
{
$api_key    = '';
$api_secret = '';

$req['method'] = $method;
$req['nonce'] = time();
$post_data = http_build_query($req, '', '&');
$sign = hash_hmac("sha512", $post_data, $api_secret);
$headers = array(
    'Sign: '.$sign,
    'Key: '.$api_key,
);

$ch = null;
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; SMART_API PHP client; '.php_uname('s').'; PHP/'.phpversion().')');
curl_setopt($ch, CURLOPT_URL, 'https://yobit.net/tapi/');
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_ENCODING , 'gzip');
$res = curl_exec($ch);
if($res === false)
{
    $e = curl_error($ch);
    debuglog($e);
    curl_close($ch);
    return null;
}

curl_close($ch);

$result = json_decode($res, true);
if(!$result) debuglog($res);

return $result;
}
like image 316
gunth223 Ha Avatar asked Oct 19 '22 14:10

gunth223 Ha


1 Answers

I just figured this out myself and came across your question in the process. The YoBit documentation on the trade API is a bit lacking as far as how to format the request.

You want to make a POST request to the API endpoint and include all params including the method itself as POST params. Then, you sign the request body (POST params) and include that along with your public key as HTTP headers.

This is pseudocode for a request for TradeHistory; I don't quite know Python. Hopefully you can decipher or someone else can Pythonize it!

request_url = "https://yobit.net/tapi";
request_body = "method=TradeHistory&pair=ltc_btc&nonce=123";
signature = hmac_sha512(request_body,yobit_secret);
http_headers = {
    "Content-Type":"application/x-www-form-urlencoded",
    "Key":yobit_public_key,
    "Sign":signature
}

response = http_post_request(request_url,request_body,http_headers);
result = json_decode(response.text);

Update: here's how you might do it in Python 3, using your object as reference:

import time,hmac,hashlib,requests,json
from urllib.parse import urlencode

class yobit(object):

def __init__(self, key, secret):
    self.key = 'KEY'
    self.secret = b'SECRET'
    self.public = ['info', 'ticker', 'depth', 'trades']
    self.trade = ['activeorders']

def query(self, method, values={}):
    if method in self.public:
        url = 'https://yobit.net/api/3/'+method
        for i, k in values.iteritems():
            url += '/'+k

        req = requests.get(url)
        return = json.loads(req.text)

    elif method in self.trade:
        url = 'https://yobit.net/tapi'
        values['method'] = method
        values['nonce'] = str(int(time.time()))
        body = urlencode(values)
        signature = hmac.new(self.secret, body, hashlib.sha512).hexdigest()
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Key': self.key,
            'Sign': signature
        }

        req = requests.post(url,data=values,headers=headers)
        return json.loads(req.text)

    return false
like image 119
Darren Avatar answered Oct 21 '22 05:10

Darren