Skip to content

Instantly share code, notes, and snippets.

@andersonmat
Created May 24, 2013 18:12
Show Gist options
  • Save andersonmat/5645428 to your computer and use it in GitHub Desktop.
Save andersonmat/5645428 to your computer and use it in GitHub Desktop.
MtGox JavaScript API Implementation
/**
The MIT License (MIT)
Copyright (c) 2013 Matt Anderson (Question Everything, LLC)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
var io = require("socket.io-client");
var rstring = require("randomstring");
var crypto = require("crypto");
var MtGox = function(apiKey, apiSecret) {
this.constructor(apiKey, apiSecret);
};
/**
Create a MtGox instance with provided key and secret.
*/
MtGox.prototype.constructor = function(apiKey, apiSecret) {
// Authentication Information
this.apiKey = apiKey;
this.apiSecret = apiSecret;
// Connect to the web socket interface
this.clientSocket = io.connect("https://socketio.mtgox.com/mtgox?Currency=USD");
// Callback associations
this.callbackAssociations = {};
// Message listeners
this.messageHandlers = {};
// Query count
this.queryCount = 0;
var _parentInstance = this;
// Listen for messages
this.clientSocket.on("message", function(socketData) {
// check for appropriate message handler
var messageOperation = socketData["op"];
// special case private calls
if(messageOperation == "result" || messageOperation == "remark") {
// check for callback
if(_parentInstance.callbackAssociations[socketData["id"]] != undefined) {
_parentInstance.callbackAssociations[socketData["id"]](socketData["result"] || socketData["message"]);
return; // do not execute any further matching
}
}
// see if there is data
if(socketData[messageOperation] != undefined) {
// check for listener
if(_parentInstance.messageHandlers[socketData[messageOperation]] != undefined) {
_parentInstance.messageHandlers[socketData[messageOperation]](
socketData[socketData[messageOperation]]
);
return;
}
}
//console.log("Unregistered: ", socketData);
});
};
/**
External listening functions (ticker, depth, trade)
*/
MtGox.prototype.addMessageHandler = function(messageType, callbackFunction) {
this.messageHandlers[messageType] = callbackFunction;
};
/**
Returns information about the account.
*/
MtGox.prototype.getAccountInformation = function(callbackFunction) {
this.queryAPI("private/info", {}, callbackFunction);
};
/**
Returns an array of open order objects.
*/
MtGox.prototype.getOpenOrders = function(callbackFunction) {
this.queryAPI("private/orders", {}, callbackFunction);
};
/**
Attempts to make an ask order at a specified price and quantity.
*/
MtGox.prototype.makeSellOrder = function(btcCount, usdPrice, callbackFunction) {
this.queryAPI(
"private/order/add",
{
"amount_int" : btcCount,
"price_int" : usdPrice,
"type" : "ask"
},
callbackFunction
);
};
/**
Attempts to make a bid order at a specified price and quantity.
*/
MtGox.prototype.makeBuyOrder = function(btcCount, usdPrice, callbackFunction) {
this.queryAPI(
"private/order/add",
{
"amount_int" : btcCount,
"price_int" : usdPrice,
"type" : "bid"
},
callbackFunction
);
};
/**
Cancels a order by provided order id.
*/
MtGox.prototype.cancelOrder = function(orderId, callbackFunction) {
this.queryAPI(
"private/order/cancel",
{
"oid" : orderId
},
callbackFunction
);
};
/**
Returns account trade history.
*/
MtGox.prototype.getHistory = function(historyPage, callbackFunction) {
// account for no history page
callbackFunction = typeof historyPage == 'function'? historyPage : callbackFunction;
historyPage = typeof historyPage == 'function'? 0 : historyPage;
this.queryAPI(
"private/wallet/history", {
"currency" : "USD",
"page" : historyPage
}, callbackFunction
);
};
/**
Sends a command to the connected parent server and associates a callback
to the command so data can be returned.
*/
MtGox.prototype.queryAPI = function(qPath, qData, callbackFunction) {
// Generate Id
var requestId = this.generateId();
// Generate raw request object
var queryObject = {
"id" : requestId,
"call" : qPath,
"params" : qData,
"nonce" : this.getNonce(),
"item" : "BTC",
"currency" : "USD"
};
// Generate signed request
var fullQuery = {
"op" : "call",
"id" : requestId,
"call" : this.signSocketRequest(queryObject),
"context" : "mtgox.com"
};
// Create callback association
this.callbackAssociations[requestId] = callbackFunction;
// Execute
this.clientSocket.emit("message", fullQuery);
};
/**
Follows the outlined process of creating a signed request
(with the provided secret)
*/
MtGox.prototype.signSocketRequest = function(qData) {
// convert object to json
var jsonData = JSON.stringify(qData);
// Create instance of signer
var dataSigner =
crypto.createHmac(
"sha512",
new Buffer(this.apiSecret, "base64")
);
// create full request
var fullSigningRequest = Buffer.concat([
new Buffer(this.apiKey.split("-").join(""), "hex"),
dataSigner.update(new Buffer(jsonData)).digest(),
new Buffer(jsonData)
]);
return fullSigningRequest.toString("base64");
};
/**
Returns the current time plus the local incrementer
(this prevents simultaneous requests from receiving an error)
*/
MtGox.prototype.getNonce = function() {
return new Date().getTime() * 1000 + ((++this.queryCount > 1000)? (this.queryCount = 0) : this.queryCount);
};
/**
Generates a random id to use to associate the returned data to a provided function.
*/
MtGox.prototype.generateId = function() {
return rstring.generate(32);
};
// allow loading it as a module.
module.exports = MtGox;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment