Reputation: 1619
I try to connect to the poloniex.com API https://poloniex.com/support/api/ which says:
(All calls to the trading API are sent via HTTP POST to https://poloniex.com/tradingApi and must contain the following headers:
- Key - Your API key.
- Sign - The query's POST data signed by your key's "secret" according to the HMAC-SHA512 method.
Additionally, all queries must include a "nonce" POST parameter. The nonce parameter is an integer which must always be greater than the previous nonce used.)
But I always get
{"error":"Invalid
API key\/secret pair."}
My hmac512Digest
works fine, I've checked it.
There must be something wrong in my code.
Can someone please Help?
public class Pol2 {
public static String POLONIEX_SECRET_KEY = "12345";
public static String POLONIEX_API_KEY = "ABX";
public static void main(String[] args) {
try {
accessPoloniex();
} catch (IOException e) {
e.printStackTrace();
}
}
public static final void accessPoloniex() throws IOException {
final String nonce = String.valueOf(System.currentTimeMillis());
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);
writer.flush();
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost post = new HttpPost(connectionString);
post.addHeader("Key", POLONIEX_API_KEY); //or setHeader?
post.addHeader("Sign", hmac512); //or setHeader?
post.setEntity(new ByteArrayEntity(out.toByteArray()));
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("command", "returnBalances"));
params.add(new BasicNameValuePair("nonce", nonce));
CloseableHttpResponse response = null;
Scanner in = null;
try {
post.setEntity(new UrlEncodedFormEntity(params));
response = httpClient.execute(post);
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();
}
}
}
Upvotes: 3
Views: 3261
Reputation: 761
The nonce parameter must be MAC'ed along with the command... If a hash is a one way function, and Polo have no idea what nonce I might choose, (or when, if i'm using UTC), how can Polo ever extract anything meaningful from what I send them.
Upvotes: 1
Reputation: 9497
I struggled with this myself and finally got it to work. Here's a very basic, working example:
public class PoloTest {
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, ClientProtocolException, IOException {
String key = "YOUR API KEY HERE";
String secret = "YOUR API SECRET HERE";
String url = "https://poloniex.com/tradingApi";
String nonce = String.valueOf(System.currentTimeMillis());
String queryArgs = "command=returnBalances&nonce=" + nonce;
Mac shaMac = Mac.getInstance("HmacSHA512");
SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes(), "HmacSHA512");
shaMac.init(keySpec);
final byte[] macData = shaMac.doFinal(queryArgs.getBytes());
String sign = Hex.encodeHexString(macData);
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost post = new HttpPost(url);
post.addHeader("Key", key);
post.addHeader("Sign", sign);
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("command", "returnBalances"));
params.add(new BasicNameValuePair("nonce", nonce));
post.setEntity(new UrlEncodedFormEntity(params));
CloseableHttpResponse response = httpClient.execute(post);
HttpEntity responseEntity = response.getEntity();
System.out.println(response.getStatusLine());
System.out.println(EntityUtils.toString(responseEntity));
}
}
Upvotes: 4
Reputation: 61892
I've looked into the Python example that they've linked to on their page. The nonce parameter must be MAC'ed along with the command and the final MAC is appended in Hex-encoded format:
String queryArgs = "command=returnBalances&nonce=" + nonce;
String hmac512 = hmac512Digest(queryArgs, POLONIEX_SECRET_KEY);
Also, the following
ByteArrayOutputStream out = new ByteArrayOutputStream();
Writer writer = new OutputStreamWriter(out, "UTF-8");
writer.append(queryArgs);
writer.flush();
//...
post.setEntity(new ByteArrayEntity(out.toByteArray()));
can be reduced to
post.setEntity(new ByteArrayEntity(queryArgs.getBytes("UTF-8")));
Upvotes: 2