JavaScript (Node.js):
/**
*
* JavaScript (Node.js) secure API wrapper
*
* 版权和限制 (c) 2013人盟比特币公布以下的代码遵循BSD条款。您可以按您的意愿使用或修改,用于个人或商业用途。
*
* 然而您不可以以 "RMBTB", "人盟比特币"来标识您的程序,也不可以有意或无意示意您的软件或服务是由人盟比*特币提供的。
*
* Usage:
* All functions are fully asynchronous, so you need to provide a callback function.
*
* var rmbtb = new rmbtbSecureApi('BTCCNY', myPubKey, myPassPhrase);
*
* rmbtb.addOrder('bid', 3, 591, function(result) {
* console.log('Result: %j', result);
* });
*
*/
// Location where you will store temporary secrets:
var rmbtbStoreLocation = 'rmbtb-secret.dat';
// Node.js dependencies
var
fs = require('fs'),
https = require('https'),
querystring = require('querystring'),
crypto = require('crypto');
function rmbtbSecureApi(currPair, pubKey, passphrase) {
this.currPair = currPair;
this.pubKey = pubKey;
this.passphrase = passphrase;
this.storeLoc = rmbtbStoreLocation;
this.apiHost = 'www.rmbtb.com';
this.apiPath = '/api/secure/' + currPair + '/';
this.secret = false;
this.secretExpiryTime = false;
var that = this;
var twoHrs = 7200000;
// fetches a new secret if necessary, before performing the main request
this.apiCall = function(api, params, httpMethod, auth, callback) {
var cb = function() {
prepRequest(api, params, httpMethod, auth, callback);
};
if(auth) {
if((this.secret === false) || (this.secretExpiryTime === false)) {
loadSecret(cb);
} else if((this.secretExpiryTime.getTime() - 60000) > (new Date()).getTime()) {
rereshSecret(cb);
} else {
cb.call(this);
}
} else {
cb.call(this);
}
};
// prepares the request
function prepRequest(api, params, httpMethod, auth, callback) {
var data = '',
headers = {};
if(this.secret === false) {
throw 'No valid secret!';
}
if(auth) {
params.nonce = (new Date()).getTime() * 1000;
data = querystring.stringify(params);
var hmac = crypto.createHmac("sha512", that.secret);
hmac.update(data);
headers['Rest-Key'] = that.pubKey;
headers['Rest-sign'] = hmac.digest('base64');
} else {
data = querystring.stringify(params);
}
if(httpMethod == 'POST') {
headers['Content-Type'] = 'application/x-www-form-urlencoded';
headers['Content-Length'] = data.length;
}
headers['User-Agent'] = 'Mozilla/4.0 (compatible; RMBTB JavaScript client)';
var opts = {
method: httpMethod,
headers: headers
};
if(httpMethod == 'GET') {
api += '?' + data;
}
doRequest(api, data, opts, callback);
}
// sends a prepared request to the API
function doRequest(api, data, opts, callback) {
opts.host = that.apiHost;
opts.path = that.apiPath + api;
var req = https.request(opts, function(response) {
var resultStr = '';
response.setEncoding('utf8');
response.on('data', function(chunk) {
resultStr += chunk;
});
response.on('error', function(err) {
throw err;
});
response.on('end', function() {
try {
var obj = JSON.parse(resultStr);
} catch(e) {
throw 'Could not understand response';
}
if(obj.error !== false) {
throw 'API returned an error: ' + obj.error;
}
var result = obj.data;
callback.call(that, result);
});
});
req.on('error', function(err) {
throw 'Error communicating: ' + err;
});
if(opts.method == 'POST') {
req.write(data);
}
req.end();
}
// refreshes the temporary secret
function refreshSecret(cb) {
var data = querystring.stringify({'api_passphrase': that.passphrase});
var opts = {
method: 'POST',
headers: {
'Rest-Key': that.pubKey,
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': data.length,
}
};
doRequest('getsecret', data, opts, function(result) {
that.secret = result.secret;
that.secretExpiryTime = new Date((new Date()).getTime() + twoHrs);
fs.writeFile(that.storeLoc, that.secret, 'utf8', function() {
cb.call(that)
});
});
}
// loads the stored secret from the save file
function loadSecret(cb) {
fs.stat(that.storeLoc, function(err, stat) {
if(!err) {
that.secretExpiryTime = new Date(stat.mtime.getTime() + twoHrs);
if((new Date()).getTime() < that.secretExpiryTime.getTime()) {
fs.readFile(that.storeLoc, 'utf8', function(err, data) {
if(!err) {
that.secret = data;
cb.call(that);
} else {
refreshSecret(cb);
}
});
} else {
refreshSecret(cb);
}
} else {
refreshSecret(cb);
}
});
}
}
/**
*
* The public, callable methods:
*
*/
rmbtbSecureApi.prototype.getInfo = function(callback) {
this.apiCall('getinfo', {}, 'GET', true, callback);
};
rmbtbSecureApi.prototype.getFunds = function(callback) {
this.apiCall('wallets', {}, 'GET', true, callback);
};
rmbtbSecureApi.prototype.ticker = function(callback) {
this.apiCall('ticker', {}, 'GET', false, callback);
};
rmbtbSecureApi.prototype.getOrders = function(callback) {
this.apiCall('orders', {}, 'GET', true, callback);
};
rmbtbSecureApi.prototype.addOrder = function(type, amount, price, callback) {
var params = {
'type': type,
'amount': amount,
'price': price
};
this.apiCall('order/add', params, 'POST', true, callback);
};
rmbtbSecureApi.prototype.addOrderInt = function(type, amount, price, callback) {
var params = {
'type': type,
'amount_int': amount,
'price_int': price
};
this.apiCall('order/add', params, 'POST', true, callback);
};
rmbtbSecureApi.prototype.cancelOrder = function(orderid, callback) {
var params = {
'oid': orderid,
};
this.apiCall('order/cancel', params, 'POST', true, callback);
};
rmbtbSecureApi.prototype.fetchOrder = function(orderid, callback) {
var params = {
'oid': orderid,
};
this.apiCall('order/fetch', params, 'POST', true, callback);
};
rmbtbSecureApi.prototype.getTrades = function(callback) {
this.apiCall('trades/mine', {}, 'GET', true, callback);
};
rmbtbSecureApi.prototype.lastTrades = function(callback) {
this.apiCall('trades/all', {}, 'GET', false, callback);
};
rmbtbSecureApi.prototype.getDepth = function(callback) {
this.apiCall('depth', {}, 'GET', false, callback);
};