Search code examples
node.jssocket.iomtgox

Authenticated Commands With MtGox's Streaming API


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.


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.