2

I am trying to Access the private Poloniex trading API in Unity C# but am getting the error "invalid command" I have my API Key and Secret authorized on Poloniex for the Trading API but can't seem to get access with my current code:

 using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System;
    using System.Security.Cryptography;


    public class PolonScript : MonoBehaviour {


        public TextMesh OutputText;

        const string _apiKey = "---Key---";
        const string _apiSecret = "---secret---";


        void Start () {

            string nonce = DateTime.Now.ToString("HHmmss");

            string myParam = "command=returnBalances&nonce=" + nonce;


            const string WEBSERVICE_URL = "https://poloniex.com/tradingApi";
            try
            {
            var webRequest = System.Net.WebRequest.Create(WEBSERVICE_URL);
                if (webRequest != null)
                {
                    webRequest.Method = "POST";
                    webRequest.Timeout = 12000;
                webRequest.ContentType = "application/x-www-form-urlencoded";
                    webRequest.Headers.Add("Key", _apiKey);
                    webRequest.Headers.Add("Sign", genHMAC(myParam));
                    webRequest.Headers.Add("command", "returnBalances");
                    webRequest.Headers.Add("nonce", nonce.ToString());


    using (System.IO.Stream s = webRequest.GetResponse().GetResponseStream())
                    {
                        using (System.IO.StreamReader sr = new System.IO.StreamReader(s))
                        {
                            var jsonResponse = sr.ReadToEnd();
                            OutputText.text = jsonResponse.ToString();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                OutputText.text = ex.ToString();
            }




        } //end-of-start()

Here is my current signing method which I am quite sure has a mistake (Human error) within, am I doing something wrong obliviously here?

        private string genHMAC(string message)
        {
            byte [] APISecret_Bytes = System.Text.Encoding.UTF8.GetBytes(_apiSecret);
            byte [] MESSAGE_Bytes = System.Text.Encoding.UTF8.GetBytes(message);

            var hmac = new HMACSHA512(APISecret_Bytes);
            var hashmessage = hmac.ComputeHash(MESSAGE_Bytes);

            var sign = BitConverter.ToString(hashmessage).Replace("-", "").ToLower();
            return sign;
        }




    }
DroneLord
  • 53
  • 12

1 Answers1

1

Poloniex Command should not be sent in the header, you should send it as a POST parameter, that's why it's responding "invalid command". Take a look at this answer to see how you send POST parameters in c#:How to add parameters into a WebRequest?

Here's an example of how your Start method should look like:

void Start()
{

    string nonce = DateTime.Now.ToString("HHmmss");

    string myParam = "command=returnBalances&nonce=" + nonce;


    const string WEBSERVICE_URL = "https://poloniex.com/tradingApi";
    try
    {
        var webRequest = System.Net.WebRequest.Create(WEBSERVICE_URL);
        if (webRequest != null)
        {
            webRequest.Method = "POST";
            webRequest.Timeout = 12000;
            webRequest.ContentType = "application/x-www-form-urlencoded";
            webRequest.Headers.Add("Key", _apiKey);
            webRequest.Headers.Add("Sign", genHMAC(myParam));

            byte[] dataStream = Encoding.UTF8.GetBytes($"command=returnBalances&nonce={nonce.ToString()}");
            webRequest.ContentLength = dataStream.Length;

            Stream newStream = webRequest.GetRequestStream();
            newStream.Write(dataStream, 0, dataStream.Length);
            newStream.Close();

            using (System.IO.Stream s = webRequest.GetResponse().GetResponseStream())
            {
                using (System.IO.StreamReader sr = new System.IO.StreamReader(s))
                {
                    var jsonResponse = sr.ReadToEnd();
                    OutputText.text = jsonResponse.ToString();
                }
            }
        }
    }
    catch (Exception ex)
    {
        OutputText.text = ex.ToString();
    }
}
Leonardo Menezes
  • 496
  • 5
  • 11
  • 1
    I gave a look and removed it from the header, in fact I am able to remove everything from the header except for the KEY and Secret and I still get "invalid command." Is this normal? It also doesn't seem to matter if I use my key/secret combination vs. random letters so I know there's something additional wrong even before the HMAC section – DroneLord Apr 13 '18 at 17:36
  • here is the inside of the Web Request: //webRequest.Method = "POST"; //webRequest.Timeout = 12000; //webRequest.ContentType = "application/x-www-form-urlencoded"; webRequest.Headers.Add ("Key", _apiKey); webRequest.Headers.Add ("Sign", genHMAC (myParam)); //webRequest.Headers.Add ("command", "returnBalances"); //webRequest.Headers.Add ("nonce", nonce.ToString ()); – DroneLord Apr 13 '18 at 18:34
  • You need to send the command, you can't just comment it out, i think the response you're getting is normal. Try sending the command as I specified in the answer and see if it still returns the same error. If you have any trouble writing the code just let me know and i will try to help. – Leonardo Menezes Apr 13 '18 at 18:37
  • Are you talking about this part in what you showed me?: if (request.Method == "POST") { if (postData != null) { request.ContentLength = postData.Length; using (var dataStream = request.GetRequestStream()) { dataStream.Write(postData, 0, postData.Length); } } } – DroneLord Apr 13 '18 at 18:46
  • I have edited the answer to reflect how the code would look like, could you give it a try and see if it solves the "invalid command" issue? – Leonardo Menezes Apr 13 '18 at 21:06
  • Wow! I am glad to see something other than "invalid command." Now I get this which is better: System.Net.WebException: The remote server returned an error: (403) Forbidden. at System.Net.HttpWebRequest.CheckFinalStatus (System.Net.WebAsyncResult result) [0x00000] in :0 at System.Net.HttpWebRequest.SetResponseData (System.Net.WebConnectionData data) [0x00000] in :0 – DroneLord Apr 13 '18 at 21:42
  • My API Key and Secret are correct, does this mean I have an error in my HMAC? – DroneLord Apr 13 '18 at 21:44
  • I think your genHMAC function should just be "private string genHMAC() { byte [] APISecret_Bytes = System.Text.Encoding.UTF8.GetBytes(_apiSecret); var hmac = new HMACSHA512(APISecret_Bytes); return hmac; }" – Leonardo Menezes Apr 13 '18 at 21:50
  • I am still getting error(403) however if I take out the "HHmmss" from the nonce I get error(422), I know the command is indeed the correct command because if I misspell it (purposely to troubleshoot test) it returns the old invalid command so either its my HMAC set up how you did or it's my nonce that is forbidding me – DroneLord Apr 13 '18 at 22:15
  • I think it should be your nonce, i would try creating a new one and testing again. Also, could you accept the answer? I think the original question about the "Invalid command" has been solved, i will still keep helping you. – Leonardo Menezes Apr 13 '18 at 22:21
  • I accepted your answer; What do you mean by creating a new nonce? isn't it new every millisecond? – DroneLord Apr 13 '18 at 22:25
  • Sorry, i mixed things up, i meant you should try creating a new API key. – Leonardo Menezes Apr 13 '18 at 22:30
  • I did, still forbidden, if I dissect and don't add the key header at all it says {"error":"Invalid API key\/secret pair."} same if I comment out the Sign header, but when I put anything in right key or wrong key it says (403)forbidden – DroneLord Apr 13 '18 at 22:48
  • Check this github issue: https://github.com/dutu/poloniex-api-node/issues/20, it can help you. Can you also send the body of the 403 response? – Leonardo Menezes Apr 13 '18 at 22:57
  • System.Net.WebException: The remote server returned an error: (403) Forbidden. at System.Net.HttpWebRequest.CheckFinalStatus (System.Net.WebAsyncResult result) [0x00000] in :0 at System.Net.HttpWebRequest.SetResponseData (System.Net.WebConnectionData data) [0x00000] in :0 – DroneLord Apr 13 '18 at 23:01
  • No, we need the 403 response body, not the exception stack trace. See this answer for how to get it: https://stackoverflow.com/questions/5409138/c-sharp-getting-the-response-body-from-a-403-error – Leonardo Menezes Apr 13 '18 at 23:12
  • I started it as a new question, is this the response body at the very bottom section here?: https://stackoverflow.com/questions/49833192/poloniex-c-sharp-trading-api-webrequest-comes-back-403-forbidden If you're able to answer the new one too take a shot – DroneLord Apr 14 '18 at 16:02