bitforexapi / API_Doc_en

BitForex API Document
12 stars 9 forks source link

"SignData Invalid" message. #5

Open cemuney opened 5 years ago

cemuney commented 5 years ago

solved

ryanfalzon commented 5 years ago

How was this solved please?

MarvinBaral commented 5 years ago

Yeah, @cemuney pls show example code. Having same issue. Tried the example given in https://github.com/bitforexapi/API_Doc_en/wiki/API-Call-Description but got other hash.

cemuney commented 5 years ago

I am away from computer. Remind me on Monday. I will try to help

On Sat, Jan 19, 2019 at 21:21 Marvin Baral notifications@github.com wrote:

Yeah, @cemuney https://github.com/cemuney pls show example code. Having same issue. Tried the example given in https://github.com/bitforexapi/API_Doc_en/wiki/API-Call-Description but got other hash.

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/bitforexapi/API_Doc_en/issues/5#issuecomment-455803319, or mute the thread https://github.com/notifications/unsubscribe-auth/AViK9ObEYwKaXVAco-DXt4iCIYYJCfkEks5vE2IpgaJpZM4XRZdO .

MarvinBaral commented 5 years ago

Ok, found the problem: You have to use UTF-8 for encoding (saw it in your post https://github.com/sammchardy/python-binance/issues/346). That worked for me (python2):

import hmac
import hashlib

postDataString = "/api/v1/trade/placeOrder?accessKey=fd91cd9ba2cc78fed6bb40e0bcff29ba&amount=1&nonce=1501234567890&price=1000&symbol=coin-usd-eth&tradeType=1"
secretKey = "82f192d903f363f22a031dfdbbeaf851"
secret = secretKey.encode(encoding='UTF-8')
signData = hmac.new(secret, postDataString, digestmod=hashlib.sha256).hexdigest()
print signData

Result is "2a0a848d76920a425190c5f2c509b45ef730956fac5331c79a988671223fd367". Works fine. Keys are from example on https://github.com/bitforexapi/API_Doc_en/wiki/API-Call-Description. I also made a gist: https://gist.github.com/MarvinBaral/e30763aac68c9dbc8ca6d7f3d20b3a4e

ryanfalzon commented 5 years ago

I am still getting the same error. This is my code:

`private string SendRequest(string endPoint, List parameters, string publicKey, string privateKey) { string signatureResult = ""; long nonce = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc)).TotalMilliseconds; parameters.Add($"nonce={nonce.ToString()}"); parameters.Add($"accessKey={publicKey}");

parameters.Sort();
var concatenatedParameters = "";
foreach(var parameter in parameters)
{
    concatenatedParameters += $"{parameter}";

    if (parameters.IndexOf(parameter) < (parameters.Count - 1))
    {
        concatenatedParameters += "&";
    }
}

var stringToSign = $"{endPoint}?{concatenatedParameters}";

byte[] secretKeyBytes = Encoding.UTF8.GetBytes(privateKey);
byte[] inputBytes = Encoding.UTF8.GetBytes(stringToSign);
using (var hmac = new HMACSHA256(secretKeyBytes))
{
    byte[] hashValue = hmac.ComputeHash(inputBytes);
    signatureResult = ToHex(hashValue);
}

string uri = $"{Properties.Settings.Default.BitforexUri}{stringToSign}&signData={signatureResult}";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";

HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var encoding = ASCIIEncoding.ASCII;
using (var reader = new StreamReader(response.GetResponseStream(), encoding))
{
    return reader.ReadToEnd();
}

}`

MarvinBaral commented 5 years ago

Just a few thoughts (have never used C#, actually used a online code detector to find out what language that is):

shooterdimon commented 5 years ago

import requests import hashlib import hmac import base64 import time from random import choice

useragents = open("useragents.txt").read().split("\n") proxies = open("proxy.txt").read().split("\n") proxy = {"http": "http//" + choice(proxies)} useragent = {"User-Agent": choice(useragents)}

nonce = int(round(time.time() * 1000)) secret = ("...").encode(encoding="UTF-8") message = ("/api/v1/trade/placeOrder?accessKey=....&amount=0.002&nonce="+str(nonce)+"&price=3000&symbol=coin-usdt-btc&tradeType=1").encode(encoding="UTF-8") hash = hmac.new(secret, message, digestmod=hashlib.sha256) signData = hash.digest().hex() url = "https://api.bitforex.com/api/v1/trade/placeBuyOrder?" payload = {"accessKey":"...","amount":0.002,"nonce":nonce,"price":3000,"symbol":"coin-usdt-btc","signData":signData} print(hash.hexdigest())

r = requests.post(url, useragent, proxy, params = payload) print(r.text, r.url)

I have "SignData Invalid" too. What is wrong? @cemuney @MarvinBaral

MarvinBaral commented 5 years ago
  1. I removed your proxy stuff and it worked:
    
    import requests
    import hashlib
    import hmac
    import base64
    import time
    from random import choice

nonce = int(round(time.time() * 1000)) secret = ("...").encode(encoding="UTF-8") message = ("/api/v1/fund/allAccount?accessKey=...&nonce="+str(nonce)).encode(encoding="UTF-8") hash = hmac.new(secret, message, digestmod=hashlib.sha256) signData = hash.digest().hex() url = "https://api.bitforex.com/api/v1/fund/allAccount" #here was a ?, requests.post() seems to add that automatically payload = {"accessKey":"...","nonce":nonce,"signData":signData} print(hash.hexdigest())

r = requests.post(url, params = payload) print(r.text, r.url)


Should be an error with your proxys.
Maybe your http proxy `proxy = {"http": "http//" + choice(proxies)}` should be https?
shooterdimon commented 5 years ago
  1. I removed your proxy stuff and it worked:
import requests
import hashlib
import hmac
import base64
import time
from random import choice

nonce = int(round(time.time() * 1000))
secret = ("...").encode(encoding="UTF-8")
message = ("/api/v1/fund/allAccount?accessKey=...&nonce="+str(nonce)).encode(encoding="UTF-8")
hash = hmac.new(secret, message, digestmod=hashlib.sha256)
signData = hash.digest().hex()
url = "https://api.bitforex.com/api/v1/fund/allAccount" #here was a ?, requests.post() seems to add that automatically
payload = {"accessKey":"...","nonce":nonce,"signData":signData}
print(hash.hexdigest())

r = requests.post(url, params = payload)
print(r.text, r.url)

Should be an error with your proxys. Maybe your http proxy proxy = {"http": "http//" + choice(proxies)} should be https?

But I still can`t make a post order . Why?

MarvinBaral commented 5 years ago

url = "https://api.bitforex.com/api/v1/trade/placeBuyOrder?" is wrong. Use url = "https://api.bitforex.com/api/v1/trade/placeOrder?" instead (as you did in message) and add parameter tradeType=1 to your payload too.

shooterdimon commented 5 years ago

thanks

url = "https://api.bitforex.com/api/v1/trade/placeBuyOrder?" is wrong. Use url = "https://api.bitforex.com/api/v1/trade/placeOrder?" instead (as you did in message) and add parameter tradeType=1 to your payload too.

Thanks. To luck I did this few minutes ago and everything go wright

ryanfalzon commented 5 years ago

Just a few thoughts (have never used C#, actually used a online code detector to find out what language that is):

  • How exactly does the endPoint and the Properties.Settings.Default.BitforexUri string look? Which one has the "/"?
  • Don't you have to convert your signatureResult to string after converting it to hex?
  • Did you test the encryption part with the example given in the doc? Was the result the same? (- I put the whole parameter list in the post data and not in the uri. I made the POST request with uri = BitforexUri + endPoint and data = endPoint + ? + paramterListWithSignData which works, but everything in uri should work too.)

endpoint is the following: "/api/v1/fund/allAccount" Properties.Settings.Default.BitforexUri is the following: "https://api.bitforex.com" The method 'ToHex' return a string as follows:

public string ToHex(byte[] value) { return string.Concat(value.Select(b => b.ToString("x2")).ToArray()); }

I tested the example from bitforex and got the same signData so I guess my code is correct.

MarvinBaral commented 5 years ago
  1. As far is I have read, List is a template. Shouldn't you write List<string> parameters instead of List parameters.
  2. At which point is the post request actually executed? You are defining it and then calling request.GetResponse(). Does this execute the request?
  3. It would be helpful to paste your complete file.
ryanfalzon commented 5 years ago

Ok, managed to get it working with the following code: ` private string SendRequest(string method, string endPoint, List parameters, string publicKey, string privateKey) { string signatureResult = ""; long nonce = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc)).TotalMilliseconds; parameters.Add($"nonce={nonce.ToString()}"); parameters.Add($"accessKey={publicKey}");

parameters.Sort();
var concatenatedParameters = "";
foreach (var parameter in parameters)
{
    concatenatedParameters += $"{parameter}";

    if (parameters.IndexOf(parameter) < (parameters.Count - 1))
    {
        concatenatedParameters += "&";
    }
}

var stringToSign = $"{endPoint}?{concatenatedParameters}";

byte[] secretKeyBytes = Encoding.UTF8.GetBytes(privateKey);
byte[] inputBytes = Encoding.UTF8.GetBytes(stringToSign);
using (var hmac = new HMACSHA256(secretKeyBytes))
{
    byte[] hashValue = hmac.ComputeHash(inputBytes);
    signatureResult = ToHex(hashValue);
}

string uri = $"{Properties.Settings.Default.BitforexUri}{stringToSign}&signData={signatureResult}";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = method;

HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var encoding = ASCIIEncoding.ASCII;
using (var reader = new StreamReader(response.GetResponseStream(), encoding))
{
    return reader.ReadToEnd();
}

} `

The issue was parsing the parameters.

ryanfalzon commented 5 years ago

@MarvinBaral is it possible to get a list of transactions and deposits/withdrawals using their APIs?

cemuney commented 5 years ago

` Thats my code. It is working.

MyBitforexTradingCoinBalance = GetBitForexCoinBalance(symbol);

    public decimal GetBitForexCoinBalance(string symbol)
    {

        var nonce = $"{GetServerTime()}";
        // Result = 1539064162431

        var client1 = new RestClient("https://api.bitforex.com");
        var request1 = new RestRequest($"api/v1/fund/mainAccount", RestSharp.Method.POST);

        var dic = new Dictionary<string, string>();
        dic.Add("accessKey", $"{KeyInfo.BitForexkey}");
        dic.Add("currency", $"{symbol}");
        dic.Add("nonce", $"{nonce}");

        request1.AddParameter("accessKey", $"{KeyInfo.BitForexkey}");
        request1.AddParameter("currency", $"{symbol}");
        request1.AddParameter("nonce", $"{nonce}");
        var queryString = "/api/v1/fund/mainAccount?"+ CalculateSignData(dic);
        request1.AddParameter("signData", GetEncryptedBitForex(queryString));
        var response1 = client1.Execute(request1);

        dynamic obj = JsonConvert.DeserializeObject(response1.Content);
        //obj["data"]["active"]

        decimal Balance = (obj["data"]["fix"] as JValue).Value<decimal>();
        return Balance;
    }

    private string CalculateSignData(Dictionary<string, string> parameters)
    {
        var orderedParams = parameters.OrderBy(x => x.Key).ToList();
        var data = new StringBuilder();

        foreach (var item in orderedParams)
        {
            if (data.Length > 0)
            {
                data.Append("&");
            }
            data.Append($"{item.Key}={item.Value}");
        }
       return  data.ToString();
    }

    private string GetEncryptedBitForex(string data)
    {
        var key = Encoding.UTF8.GetBytes(KeyInfo.BitForexsecret);
        var message = Encoding.UTF8.GetBytes(data);

        var hash = new HMACSHA256(key);
        var hashedData = hash.ComputeHash(message);

        return HashEncode(hashedData);
    }

`

MarvinBaral commented 5 years ago

@MarvinBaral is it possible to get a list of transactions and deposits/withdrawals using their APIs?

For transactions it is "Search Order Information". Haven't seen something for deposit/withdrawal in their doc.

ryanfalzon commented 5 years ago

@MarvinBaral to use 'Search Order Information' you need to specify the symbol as one of the parameters. When I send a request for 'coin-usdt-eth' I get an empty list, even though I have traded in that symbol. Have you ever gone through the same issue?

MarvinBaral commented 5 years ago

Yep, for completed orders its only the last three days:

Note: The interface returns up to 100 records,completed records can only show three days early.

here

zdman135 commented 5 years ago

anyone here want to assist and take a stab at this one? https://github.com/bitforexapi/API_Doc_en/issues/10