Question

I am using nodejs with socket.io-client to connect to the MtGox Streaming API described here: https://en.bitcoin.it/wiki/MtGox/API/Streaming#Authenticated_commands

The examples are written in php and I tried my best to convert them to JS but I keep getting a response from the server "Invalid call"

var sec_key_buffer = Buffer(secret_key, 'base64');
var hmac = crypto.createHmac('sha512', sec_key_buffer);
var nonce = Date.now() + "";
var id = crypto.createHash('md5').update(nonce).digest('hex');
var query = {
    "call": 'private/info',
    "id": id,
    "nonce": nonce
};
var body = JSON.stringify(query);
var sign = hmac.update(body).digest('binary');

// The 'api_key' field has already stripped of the '-' character
var callBody = new Buffer(api_key + sign + body).toString('base64');

// 'connection' is the socket.io connection to 'https://socketio.mtgox.com/mtgox'    
connection.json.send({
    "op": "call",
    "id": id,
    "call": callBody,
    "context": 'mtgox.com'
});

Any help would be appreciated.

Was it helpful?

Solution

Here's what seemed to work for me:

var io = require('socket.io-client');
var crypto = require('crypto');

var socket = io.connect('https://socketio.mtgox.com/mtgox');

var MTGOX_API_INFO = {
  key: '<YOUR_KEY>',
  secret: '<YOUR_SECRET>'
}

var MTGOX_CHANNELS = {
  trade: 'dbf1dee9-4f2e-4a08-8cb7-748919a71b21',
  depth: '24e67e0d-1cad-4cc0-9e7a-f8523ef460fe',
  ticker: 'd5f06780-30a8-4a48-a2f8-7ed181b4a13f'
}

// unsubscribe from depth and trade messages
socket.emit('message', {
  op: 'unsubscribe', 
  channel: MTGOX_CHANNELS.trade
});
socket.emit('message', {
  op: 'unsubscribe', 
  channel: MTGOX_CHANNELS.depth
});
socket.emit('message', {
  op: 'unsubscribe', 
  channel: MTGOX_CHANNELS.ticker
});


var getNonce = function() {
  return ((new Date()).getTime() * 1000).toString();
}

var nonce = getNonce();
var requestId = crypto.createHash('md5').update(nonce).digest('hex');
var query = {
  id: requestId,
  call: 'private/info',
  nonce: nonce
  // params: {},
  // item: 'BTC',
  // currency: 'USD'
};
var queryJSON = JSON.stringify(query);

var signedQuery = crypto.createHmac('sha512', new Buffer(MTGOX_API_INFO.secret, 'base64')).update(queryJSON).digest('binary');
var binKey = (new Buffer(MTGOX_API_INFO.key.replace(/-/g, ''), 'hex')).toString('binary');
var buffer = new Buffer(binKey + signedQuery + queryJSON, 'binary');
var call = buffer.toString('base64');

var command = {
  op: 'call',
  id: requestId,
  call: call,
  context: 'mtgox.com'
};

console.log("REQUEST:", command);

socket.emit('message', command);
socket.on('message', function(data) {
  console.log(data);
});

UPDATE: I've also abstracted it into a simple node module.

OTHER TIPS

You must hex decode the api key to raw bytes before appending the hash and message content.

Not familiar enough with node.js to provide code, but in Java (using Guava) it's:

byte[] apiKey = BaseEncoding.base16().lowerCase().decode(API_KEY.replace("-", ""));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top