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

@panipsilos panipsilos 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

@sourtin sourtin 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

@adv0r adv0r 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

@christopherobin christopherobin 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

@panipsilos panipsilos 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

@gubatron gubatron 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