Bitcoin Forum
July 04, 2024, 02:21:59 PM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Poloniex tradingApi, from JAVA  (Read 5046 times)
drbobbo (OP)
Newbie
*
Offline Offline

Activity: 41
Merit: 0


View Profile
November 11, 2014, 09:58:24 PM
Last edit: November 12, 2014, 10:45:18 AM by drbobbo
 #1

I throw this question out here in hope of some input, I am totally stuck here ....

I am trying to access the Poloniex tradingApi from JAVA code, and all I get is the error "invalid command". A standalone static (utilities) method that illustrates the problem

public static final long generateNonce(){
      
      Date d = new Date();
      return d.getTime();
   }
   
   public static final String getAddressPoloniex(String currency, double amount, String address) throws IOException{
   
      String result = null;
      String nonce = new BigDecimal(WithdrawUtils.generateNonce()).toString();
      
      String connectionString = "https://poloniex.com/trading?command=returnDepositAddresses&nonce="+nonce;
      
      String hmac512 = MyUtils.hmac512Digest(connectionString, Keys.POLONIEX_SECRET_KEY);
      
      HttpsURLConnection poloniexCon = null;
      
      try {
         poloniexCon = (HttpsURLConnection)new URL(connectionString).openConnection();
         poloniexCon.addRequestProperty("Key", Keys.POLONIEX_API_KEY);
         poloniexCon.addRequestProperty("Sign", hmac512);
      } catch (MalformedURLException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      } catch (IOException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }
      
      try {
         poloniexCon.setRequestMethod("POST");
      } catch (ProtocolException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }
      poloniexCon.setRequestProperty("Content-length", String.valueOf(connectionString.length()));
      poloniexCon.setRequestProperty("Content-Type","application/x-www- form-urlencoded");
      poloniexCon.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0;Windows98;DigExt)");
      poloniexCon.setDoInput(true);

      DataInputStream input = new DataInputStream( poloniexCon.getInputStream() );

      StringBuffer s = new StringBuffer();
      for( int c = input.read(); c != -1; c = input.read() ) {
         s.append((char)c);
      }
      
      result = s.toString();
      input.close();
      
      return result; // here result has {"error":"Invalid command."}
   }


This approach works well with for example Bittrex exchange. My feeling is that the problem is in the HMAC SHA512 signing. I do that like this:

   public static String hmac512Digest(String msg, String keyString) {
      String digest = null;
      try {
         SecretKeySpec key = new SecretKeySpec((keyString).getBytes("UTF-8"), "HmacSHA512");
         Mac mac = Mac.getInstance("HmacSHA512");
         mac.init(key);

         byte[] bytes = mac.doFinal(msg.getBytes("ASCII"));

         StringBuffer hash = new StringBuffer();
         for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes);
            if (hex.length() == 1) {
               hash.append('0');
            }
            hash.append(hex);
         }
         digest = hash.toString();
      } catch (UnsupportedEncodingException e) {
      } catch (InvalidKeyException e) {
      } catch (NoSuchAlgorithmException e) {
      }
      return digest;
   }

If it is not that, I am out of ideas. This HMAC digest works fine with Bittrex. The Poloniex API doc is relatively brief on how this should be calculated. The error is confusing and indicates there is a problem with the command, but all other commands to the trading (private) API gives me the same error. All calls to the public API works fine. I have spent several hours on this now. I know my keys are fine, they work with python code.

The first person with a solution that actually fixes this and send me / post their BTC address will get a 0.1 BTC bounty!

/
sebbes
Newbie
*
Offline Offline

Activity: 4
Merit: 0


View Profile
January 14, 2015, 05:47:25 AM
 #2

I throw this question out here in hope of some input, I am totally stuck here ....

I am trying to access the Poloniex tradingApi from JAVA code, and all I get is the error "invalid command". A standalone static (utilities) method that illustrates the problem

public static final long generateNonce(){
      
      Date d = new Date();
      return d.getTime();
   }
   
   public static final String getAddressPoloniex(String currency, double amount, String address) throws IOException{
   
      String result = null;
      String nonce = new BigDecimal(WithdrawUtils.generateNonce()).toString();
      
      String connectionString = "https://poloniex.com/trading?command=returnDepositAddresses&nonce="+nonce;
      
      String hmac512 = MyUtils.hmac512Digest(connectionString, Keys.POLONIEX_SECRET_KEY);
      
      HttpsURLConnection poloniexCon = null;
      
      try {
         poloniexCon = (HttpsURLConnection)new URL(connectionString).openConnection();
         poloniexCon.addRequestProperty("Key", Keys.POLONIEX_API_KEY);
         poloniexCon.addRequestProperty("Sign", hmac512);
      } catch (MalformedURLException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      } catch (IOException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }
      
      try {
         poloniexCon.setRequestMethod("POST");
      } catch (ProtocolException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }
      poloniexCon.setRequestProperty("Content-length", String.valueOf(connectionString.length()));
      poloniexCon.setRequestProperty("Content-Type","application/x-www- form-urlencoded");
      poloniexCon.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0;Windows98;DigExt)");
      poloniexCon.setDoInput(true);

      DataInputStream input = new DataInputStream( poloniexCon.getInputStream() );

      StringBuffer s = new StringBuffer();
      for( int c = input.read(); c != -1; c = input.read() ) {
         s.append((char)c);
      }
      
      result = s.toString();
      input.close();
      
      return result; // here result has {"error":"Invalid command."}
   }


This approach works well with for example Bittrex exchange. My feeling is that the problem is in the HMAC SHA512 signing. I do that like this:

   public static String hmac512Digest(String msg, String keyString) {
      String digest = null;
      try {
         SecretKeySpec key = new SecretKeySpec((keyString).getBytes("UTF-8"), "HmacSHA512");
         Mac mac = Mac.getInstance("HmacSHA512");
         mac.init(key);

         byte[] bytes = mac.doFinal(msg.getBytes("ASCII"));

         StringBuffer hash = new StringBuffer();
         for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes);
            if (hex.length() == 1) {
               hash.append('0');
            }
            hash.append(hex);
         }
         digest = hash.toString();
      } catch (UnsupportedEncodingException e) {
      } catch (InvalidKeyException e) {
      } catch (NoSuchAlgorithmException e) {
      }
      return digest;
   }

If it is not that, I am out of ideas. This HMAC digest works fine with Bittrex. The Poloniex API doc is relatively brief on how this should be calculated. The error is confusing and indicates there is a problem with the command, but all other commands to the trading (private) API gives me the same error. All calls to the public API works fine. I have spent several hours on this now. I know my keys are fine, they work with python code.

The first person with a solution that actually fixes this and send me / post their BTC address will get a 0.1 BTC bounty!

/


Are you still looking for a solution to this? Here are your problems:

1) You are not doing a POST request, but a GET. Poloniex trading api docu states you must use POST. Just setting the request method to "POST" is not enough.
2) You are only supposed to hash the query parameters, not the full url. But when you so POST you will see, because with a post you don't concatenate the url and the params, rather you write the params in the connection outputstream.

Let me know if you need help...

Cheers,
Sebastian
kb4scv
Legendary
*
Offline Offline

Activity: 966
Merit: 1000


View Profile
March 16, 2015, 03:09:02 PM
 #3

I have exactly the same problem with http post call in JavaScript.  It has to be the hash method as I can change the hash string and it doesn't care when I send it.  Get the invalid command return on all private post calls, even after Poloniex guy sent me a sample call for the post call.  I am stumped as well at this point, but will post if I figure it out.

Best of Luck!
arunka71
Sr. Member
****
Offline Offline

Activity: 410
Merit: 257


View Profile
March 17, 2015, 03:01:44 AM
 #4

Java != JavaScript ?
sebbes
Newbie
*
Offline Offline

Activity: 4
Merit: 0


View Profile
April 24, 2015, 08:35:20 AM
Last edit: April 24, 2015, 09:01:06 AM by sebbes
 #5

I have exactly the same problem with http post call in JavaScript.  It has to be the hash method as I can change the hash string and it doesn't care when I send it.  Get the invalid command return on all private post calls, even after Poloniex guy sent me a sample call for the post call.  I am stumped as well at this point, but will post if I figure it out.

Best of Luck!

The hash method works, I successfully connect to Poloniex. You need to add an HTTP header with your public API key and another one with the the encrypted  query args; the query args (plain as in not encrypted) you also write on the connection outputstream (same for JavaScript, Java, Python etc.).

so in Java that would look like this:

Code:
   ...   
   conn.setRequestProperty("Key", "your public key");

   //build your args query parameter String (needs to include "command", "nonce" ), e.g.
   String queryArgs = "command=cancelOrder&orderNumber=12345"
   //encrypt the queryArgs using HmacSHA512. In java that looks something like this
   Mac shaMac = Mac.getInstance("HmacSHA512") //with try/catch for NoSuchAlgorithmException
   SecretKeySpec  keySpec = new SecretKeySpec(<your secret API key>.getBytes(), "HmacSHA512");

   shaMac.init(keySpec);
   final byte[] macData = shaMac.doFinal(queryArgs.getBytes());
   String result = Hex.encodeHexString(macData); //again with try/catch for InvalidKeyException
   //this result you add as header param
   conn.setRequestProperty("Sign", result);
   //and the queryArgs themselves you write onto the connection's outputstream
   OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
   out.write(queryArgs);
    ...

But without posting your code it is impossible to assist!

Regards,
Sebastian
flash10101
Full Member
***
Offline Offline

Activity: 372
Merit: 130


View Profile WWW
August 23, 2016, 01:46:00 PM
 #6

I also tried to connect to the Poloniex API with Java. I followed some advice from this thread and came up with the following code, but for some reason, I always get the error: Invalid command

Any idea what I am doing wrong? Huh

Code:
public static String POLONIEX_SECRET_KEY = "my secret"; //KEY
public static String POLONIEX_API_KEY = "my key"; // TODO API KEY


public static void main(String[] args) {

    try {
        accessPoloniex();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}
public static final long generateNonce(){

    Date d = new Date();
    return d.getTime();
}

public static final void accessPoloniex() throws IOException{

    String nonce = new BigDecimal(Polo2.generateNonce()).toString();

    String connectionString = "https://poloniex.com/tradingApi";

    String queryArgs = "command=returnBalances";

    String hmac512 = hmac512Digest(queryArgs, POLONIEX_SECRET_KEY);

    // Produce the output
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    Writer writer = new OutputStreamWriter(out, "UTF-8");
    writer.append(queryArgs);


    CloseableHttpClient httpClient = HttpClients.createDefault();
    HttpPost post = new HttpPost(connectionString);

    post.setHeader("Key", POLONIEX_API_KEY);
    post.setHeader("Sign", hmac512);

    post.setEntity(new ByteArrayEntity(out.toByteArray()));
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("nonce", nonce));

    CloseableHttpResponse response = null;
    Scanner in = null;
    try
    {
        post.setEntity(new UrlEncodedFormEntity(params));
        response = httpClient.execute(post);
        // System.out.println(response.getStatusLine());
        HttpEntity entity = response.getEntity();
        in = new Scanner(entity.getContent());
        while (in.hasNext())
        {
            System.out.println(in.next());

        }
        EntityUtils.consume(entity);
    } finally
    {
        in.close();
        response.close();
    }

}

public static String hmac512Digest(String msg, String keyString) {

    Mac shaMac;
    try {
        shaMac = Mac.getInstance("HmacSHA512");
        SecretKeySpec  keySpec = new SecretKeySpec(keyString.getBytes(), "HmacSHA512");

        shaMac.init(keySpec);
        final byte[] macData = shaMac.doFinal(msg.getBytes());
        return Hex.encodeHexString(macData); //again with try/catch for InvalidKeyException

    } catch (Exception e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    return null;
}

COINLEND  |  The Lending-Bot for Bitfinex, Poloniex & Quoinex
▬▬▬▬▬▬▬▬  AUTOMATED  ▬  SIMPLE SETUP  ▬  FREE OF CHARGE  ▬  SAFE  ▬▬▬▬▬▬▬▬
\\\\\   Blog  FAQ  Calculator  Rates  Facebook  Twitter  Telegram  Instagram   /////
tf315
Member
**
Offline Offline

Activity: 71
Merit: 10


View Profile
September 13, 2016, 12:58:48 AM
 #7

I also tried to connect to the Poloniex API with Java. I followed some advice from this thread and came up with the following code, but for some reason, I always get the error: Invalid command

Any idea what I am doing wrong? Huh

Code:
public static String POLONIEX_SECRET_KEY = "my secret"; //KEY
public static String POLONIEX_API_KEY = "my key"; // TODO API KEY


public static void main(String[] args) {

    try {
        accessPoloniex();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}
public static final long generateNonce(){

    Date d = new Date();
    return d.getTime();
}

public static final void accessPoloniex() throws IOException{

    String nonce = new BigDecimal(Polo2.generateNonce()).toString();

    String connectionString = "https://poloniex.com/tradingApi";

    String queryArgs = "command=returnBalances";

    String hmac512 = hmac512Digest(queryArgs, POLONIEX_SECRET_KEY);

    // Produce the output
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    Writer writer = new OutputStreamWriter(out, "UTF-8");
    writer.append(queryArgs);


    CloseableHttpClient httpClient = HttpClients.createDefault();
    HttpPost post = new HttpPost(connectionString);

    post.setHeader("Key", POLONIEX_API_KEY);
    post.setHeader("Sign", hmac512);

    post.setEntity(new ByteArrayEntity(out.toByteArray()));
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("nonce", nonce));

    CloseableHttpResponse response = null;
    Scanner in = null;
    try
    {
        post.setEntity(new UrlEncodedFormEntity(params));
        response = httpClient.execute(post);
        // System.out.println(response.getStatusLine());
        HttpEntity entity = response.getEntity();
        in = new Scanner(entity.getContent());
        while (in.hasNext())
        {
            System.out.println(in.next());

        }
        EntityUtils.consume(entity);
    } finally
    {
        in.close();
        response.close();
    }

}

public static String hmac512Digest(String msg, String keyString) {

    Mac shaMac;
    try {
        shaMac = Mac.getInstance("HmacSHA512");
        SecretKeySpec  keySpec = new SecretKeySpec(keyString.getBytes(), "HmacSHA512");

        shaMac.init(keySpec);
        final byte[] macData = shaMac.doFinal(msg.getBytes());
        return Hex.encodeHexString(macData); //again with try/catch for InvalidKeyException

    } catch (Exception e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    return null;
}


I haven't tried your code but two things that work in my code:

- nonce is part of the query string
- I use System.currentTimeMillis() to create the nonce. Not sure if your way will work or not but I know mine does and its much simpler.
freemanjackal
Sr. Member
****
Offline Offline

Activity: 378
Merit: 250


View Profile
March 30, 2017, 04:13:45 AM
 #8

why dont you try to use the push api, if you are not behind an internet proxy i suggest you to use it for getting all the info, i havent been able to use it but it is because i am behind a proxy and i havent found a solution for the existing wamp libraries in java to set this configuration, on internet there is an example of how to with poliniex
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!