Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Functionnal MtGox client written in Java (Updated for v2 and data.mtgox.com)
package com.mtgox.api;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class Client {
protected final int BUFFER_SIZE = 8192;
protected String key;
protected String secret;
public Client(String key, String secret) {
this.key = key;
this.secret = secret;
}
public String query(String path, HashMap<String, String> args) throws Exception {
// small sanity check
if (args == null) {
args = new HashMap<>();
}
// build URL, actually we may want to fallback to mtgox.com directly for
// private calls, but that should be fine for now
URL queryUrl = new URL("https://data.mtgox.com/api/" + path);
// create connection
HttpURLConnection connection = (HttpURLConnection)queryUrl.openConnection();
// set user agent
connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; Java Test client)");
if (this.secret != null && this.key != null) {
// add nonce and build arg list, nonce is now converted to nanoseconds
// as some implementations uses that, allowing you to use the same value
// across languages. If you use any other library to call the API, make
// sure that you are using the same kind of nonce, or you will encounter
// issues
args.put("nonce", String.valueOf(System.currentTimeMillis() * 1000000));
String sign_data = this.buildQueryString(args);
// api v2 now adds the path followed by a 0 byte in the signature
if (path.startsWith("2/")) {
sign_data = path.substring(2) + "\0" + sign_data;
}
// args signature
Mac mac = Mac.getInstance("HmacSHA512");
SecretKeySpec secret_spec = new SecretKeySpec((new BASE64Decoder()).decodeBuffer(this.secret), "HmacSHA512");
mac.init(secret_spec);
String signature = (new BASE64Encoder()).encode(mac.doFinal(sign_data.getBytes()));
// add signature headers
connection.setRequestProperty("Rest-Key", this.key);
connection.setRequestProperty("Rest-Sign", signature.replaceAll("\n", ""));
}
// write post
if (!args.isEmpty()) {
connection.setDoOutput(true);
connection.getOutputStream().write(this.buildQueryString(args).getBytes());
}
// read info
String result = new String();
byte buffer[] = new byte[this.BUFFER_SIZE];
int len = 0;
// read until eof, no need to increment buffer size too much as the answer will
// most likely arrive in smaller chunks
while ((len = connection.getInputStream().read(buffer, 0, this.BUFFER_SIZE)) > 0) {
result += new String(buffer, 0, len, "UTF-8");
}
return result;
}
protected String buildQueryString(HashMap<String, String> args) throws Exception {
String result = new String();
for (String hashkey : args.keySet()) {
if (result.length() > 0) result += '&';
result += URLEncoder.encode(hashkey, "UTF-8") + "="
+ URLEncoder.encode(args.get(hashkey), "UTF-8");
}
return result;
}
}
@panipsilos

This comment has been minimized.

Copy link

commented Apr 6, 2013

Hey , I tried your example but I am getting the following exception:

6-apr-2013 3:12:09 com.mtgox.api.Client query
SEVERE: null
java.io.IOException: Server returned HTTP response code: 400 for URL: https://mtgox.com/api/1/generic/private/merchant/order/create
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
at com.mtgox.api.Client.query(Client.java:61)
at com.mtgox.api.Client.main(Client.java:30)

I have double checked that my key and secret are the correct ones. Could please verify that the code is the correct one?

@sourtin

This comment has been minimized.

Copy link

commented Apr 12, 2013

The URL has changed, you need to change the base URL on line 55 to "https://data.mtgox.com/api/", and the example query URL on line 33 to "1/generic/merchant/order/create".

@adv0r

This comment has been minimized.

Copy link

commented Apr 26, 2013

if you plan using the v2 of the api you can take a look here -> https://github.com/adv0r/mtgox-api-v2-java

@christopherobin

This comment has been minimized.

Copy link
Owner Author

commented May 7, 2013

Hopefully this new version should work better.
Changes are fairly simple:

  • Key and secret can be left null when creating the Client for calling public APIs
  • Support for API v2
  • Support for data.mtgox.com
  • Exceptions are now bubbled all the way to the top and are the user's responsability
@panipsilos

This comment has been minimized.

Copy link

commented Jun 6, 2013

Hi,

guys I am trying to run the new version mtgox-api-v2-java (UsageExample.java) , but again I am getting the following error:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
jun 06, 2013 8:32:33 PM com.mtgox.api.MtGox getBalance
SEVERE: null
Unexpected token END OF FILE at position 0.
at org.json.simple.parser.JSONParser.parse(JSONParser.java:257)
at org.json.simple.parser.JSONParser.parse(JSONParser.java:81)
at org.json.simple.parser.JSONParser.parse(JSONParser.java:75)
at com.mtgox.api.MtGox.getBalance(MtGox.java:254)
at com.mtgox.examples.UsageExample.main(UsageExample.java:43)

After investigating on the issue, I found out that I may need to download the certificate. So I downloaded and ran the InstallCert java program. But then I didnt know exactly what URL and port to use as argument so I just used the mtgox.com. However I bump into the same exception.

Anybody could help me out please??

@gubatron

This comment has been minimized.

Copy link

commented Nov 9, 2013

does this API allow posting orders?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.