Comparing version 0.0.1 to 0.0.2
@@ -18,2 +18,3 @@ | ||
getHashesPerSecond: 'gethashespersec', | ||
getHashesPerSec: 'gethashespersec', | ||
getInfo: 'getinfo', | ||
@@ -48,3 +49,3 @@ getNewAddress: 'getnewaddress', | ||
this.rpc = rpc.getClient(port, host, user, pass); | ||
this.rpc = new rpc.Client(port, host, user, pass); | ||
} | ||
@@ -54,2 +55,30 @@ | ||
//===----------------------------------------------------------------------===// | ||
// cmd | ||
// Call custom jsonrpc commands | ||
//===----------------------------------------------------------------------===// | ||
Client.prototype.cmd = function() { | ||
var args = [].slice.call(arguments); | ||
var cmd = args.shift(); | ||
callRpc(cmd, args, this.rpc); | ||
} | ||
//===----------------------------------------------------------------------===// | ||
// callRpc | ||
//===----------------------------------------------------------------------===// | ||
function callRpc(cmd, args, rpc) { | ||
var fn = args[args.length-1]; | ||
// If the last function is a callback, pop it from the args list | ||
if(_.isFunction(fn)) { | ||
args.pop(); | ||
} else { | ||
fn = function () {}; | ||
} | ||
rpc.call(cmd, args, fn); | ||
} | ||
//===----------------------------------------------------------------------===// | ||
// Initialize wrappers | ||
@@ -61,12 +90,3 @@ //===----------------------------------------------------------------------===// | ||
var args = [].slice.call(arguments); | ||
var fn = args[args.length-1]; | ||
// If the last function is a callback, pop it from the args list | ||
if(_.isFunction(fn)) { | ||
args.pop(); | ||
} else { | ||
fn = function () {}; | ||
} | ||
this.rpc.call(jsonFn, args, fn); | ||
callRpc(jsonFn, args, this.rpc); | ||
}; | ||
@@ -73,0 +93,0 @@ }); |
module.exports = { | ||
Client: require('./client'), | ||
}; | ||
module.exports.Client = require('./client'); |
var sys = require('sys'); | ||
var http = require('http'); | ||
var functions = {}; | ||
var METHOD_NOT_ALLOWED = "Method Not Allowed\n"; | ||
var INVALID_REQUEST = "Invalid Request\n"; | ||
var JSONRPCClient = function(port, host, user, password) { | ||
this.port = port; | ||
this.host = host; | ||
this.user = user; | ||
this.password = password; | ||
this.call = function(method, params, callback, errback, path) { | ||
var client = http.createClient(port, host); | ||
// First we encode the request into JSON | ||
var requestJSON = JSON.stringify({ | ||
'id': '' + (new Date()).getTime(), | ||
'method': method, | ||
'params': params | ||
}); | ||
var headers = {}; | ||
if (user && password) { | ||
var buff = new Buffer(this.user + ":" + this.password).toString('base64'); | ||
var auth = 'Basic ' + buff; | ||
headers['Authorization'] = auth; | ||
} | ||
//===----------------------------------------------------------------------===// | ||
// Server Client | ||
//===----------------------------------------------------------------------===// | ||
var Client = function(port, host, user, password) { | ||
this.port = port; | ||
this.host = host; | ||
this.user = user; | ||
this.password = password; | ||
// Then we build some basic headers. | ||
headers['Host'] = host; | ||
headers['Content-Length'] = requestJSON.length; | ||
this.call = function(method, params, callback, errback, path) { | ||
var client = http.createClient(port, host); | ||
// Now we'll make a request to the server | ||
var request = client.request('POST', path || '/', headers); | ||
request.write(requestJSON); | ||
request.on('response', function(response) { | ||
// We need to buffer the response chunks in a nonblocking way. | ||
var buffer = ''; | ||
response.on('data', function(chunk) { | ||
buffer = buffer + chunk; | ||
}); | ||
// When all the responses are finished, we decode the JSON and | ||
// depending on whether it's got a result or an error, we call | ||
// emitSuccess or emitError on the promise. | ||
response.on('end', function() { | ||
var decoded = JSON.parse(buffer); | ||
if(decoded.hasOwnProperty('result')) { | ||
if (callback) | ||
callback(decoded.result); | ||
} | ||
else { | ||
if (errback) | ||
errback(decoded.error); | ||
} | ||
}); | ||
}); | ||
}; | ||
} | ||
// First we encode the request into JSON | ||
var requestJSON = JSON.stringify({ | ||
'id': '' + (new Date()).getTime(), | ||
'method': method, | ||
'params': params | ||
}); | ||
var JSONRPC = { | ||
functions: functions, | ||
exposeModule: function(mod, object) { | ||
var funcs = []; | ||
for(var funcName in object) { | ||
var funcObj = object[funcName]; | ||
if(typeof(funcObj) == 'function') { | ||
functions[mod + '.' + funcName] = funcObj; | ||
funcs.push(funcName); | ||
} | ||
} | ||
JSONRPC.trace('***', 'exposing module: ' + mod + ' [funs: ' + funcs.join(', ') + ']'); | ||
return object; | ||
}, | ||
expose: function(name, func) { | ||
JSONRPC.trace('***', 'exposing: ' + name); | ||
functions[name] = func; | ||
}, | ||
trace: function(direction, message) { | ||
sys.puts(' ' + direction + ' ' + message); | ||
}, | ||
listen: function(port, host) { | ||
JSONRPC.server.listen(port, host); | ||
JSONRPC.trace('***', 'Server listening on http://' + (host || '127.0.0.1') + ':' + port + '/'); | ||
}, | ||
handleInvalidRequest: function(req, res) { | ||
res.writeHead(400, {'Content-Type': 'text/plain', | ||
'Content-Length': INVALID_REQUEST.length}); | ||
res.write(INVALID_REQUEST); | ||
res.finish(); | ||
}, | ||
handlePOST: function(req, res) { | ||
var buffer = ''; | ||
var promise = new process.Promise(); | ||
promise.addCallback(function(buf) { | ||
var headers = {}; | ||
var decoded = JSON.parse(buf); | ||
// Check for the required fields, and if they aren't there, then | ||
// dispatch to the handleInvalidRequest function. | ||
if(!(decoded.method && decoded.params && decoded.id)) { | ||
return JSONRPC.handleInvalidRequest(req, res); | ||
} | ||
if(!JSONRPC.functions.hasOwnProperty(decoded.method)) { | ||
return JSONRPC.handleInvalidRequest(req, res); | ||
} | ||
// Build our success handler | ||
var onSuccess = function(funcResp) { | ||
JSONRPC.trace('-->', 'response (id ' + decoded.id + '): ' + JSON.stringify(funcResp)); | ||
var encoded = JSON.stringify({ | ||
'result': funcResp, | ||
'error': null, | ||
'id': decoded.id | ||
}); | ||
res.writeHead(200, {'Content-Type': 'application/json', | ||
'Content-Length': encoded.length}); | ||
res.write(encoded); | ||
res.finish(); | ||
}; | ||
// Build our failure handler (note that error must not be null) | ||
var onFailure = function(failure) { | ||
JSONRPC.trace('-->', 'failure: ' + JSON.stringify(failure)); | ||
var encoded = JSON.stringify({ | ||
'result': null, | ||
'error': failure || 'Unspecified Failure', | ||
'id': decoded.id | ||
}); | ||
res.writeHead(200, {'Content-Type': 'application/json', | ||
'Content-Length': encoded.length}); | ||
res.write(encoded); | ||
res.finish(); | ||
}; | ||
JSONRPC.trace('<--', 'request (id ' + decoded.id + '): ' + decoded.method + '(' + decoded.params.join(', ') + ')'); | ||
// Try to call the method, but intercept errors and call our | ||
// onFailure handler. | ||
var method = JSONRPC.functions[decoded.method]; | ||
var resp = null; | ||
try { | ||
resp = method.apply(null, decoded.params); | ||
} | ||
catch(err) { | ||
return onFailure(err); | ||
} | ||
// If it's a promise, we should add callbacks and errbacks, | ||
// but if it's not, we can just go ahead and call the callback. | ||
if(resp instanceof process.Promise) { | ||
resp.addCallback(onSuccess); | ||
resp.addErrback(onFailure); | ||
} | ||
else { | ||
onSuccess(resp); | ||
} | ||
}); | ||
req.addListener('body', function(chunk) { | ||
buffer = buffer + chunk; | ||
}); | ||
req.addListener('complete', function() { | ||
promise.emitSuccess(buffer); | ||
}); | ||
}, | ||
handleNonPOST: function(req, res) { | ||
res.writeHead(405, {'Content-Type': 'text/plain', | ||
'Content-Length': METHOD_NOT_ALLOWED.length, | ||
'Allow': 'POST'}); | ||
res.write(METHOD_NOT_ALLOWED); | ||
res.finish(); | ||
}, | ||
handleRequest: function(req, res) { | ||
JSONRPC.trace('<--', 'accepted request'); | ||
if(req.method === 'POST') { | ||
JSONRPC.handlePOST(req, res); | ||
if (user && password) { | ||
var buff = new Buffer(this.user + ":" + this.password) | ||
.toString('base64'); | ||
var auth = 'Basic ' + buff; | ||
headers['Authorization'] = auth; | ||
} | ||
// Then we build some basic headers. | ||
headers['Host'] = host; | ||
headers['Content-Length'] = requestJSON.length; | ||
// Now we'll make a request to the server | ||
var request = client.request('POST', path || '/', headers); | ||
request.write(requestJSON); | ||
request.on('response', function(response) { | ||
// We need to buffer the response chunks in a nonblocking way. | ||
var buffer = ''; | ||
response.on('data', function(chunk) { | ||
buffer = buffer + chunk; | ||
}); | ||
// When all the responses are finished, we decode the JSON and | ||
// depending on whether it's got a result or an error, we call | ||
// emitSuccess or emitError on the promise. | ||
response.on('end', function() { | ||
var decoded = JSON.parse(buffer); | ||
if(decoded.hasOwnProperty('result')) { | ||
if (callback) | ||
callback(decoded.result); | ||
} | ||
else { | ||
JSONRPC.handleNonPOST(req, res); | ||
if (errback) | ||
errback(decoded.error); | ||
} | ||
}, | ||
server: http.createServer(function(req, res) { | ||
// TODO: Get rid of this extraneous extra function call. | ||
JSONRPC.handleRequest(req, res); | ||
}), | ||
getClient: function(port, host, user, password) { | ||
return new JSONRPCClient(port, host, user, password); | ||
}); | ||
}); | ||
}; | ||
} | ||
//===----------------------------------------------------------------------===// | ||
// Server | ||
//===----------------------------------------------------------------------===// | ||
function Server() { | ||
var self = this; | ||
this.functions = {}; | ||
this.server = http.createServer(function(req, res) { | ||
Server.trace('<--', 'accepted request'); | ||
if(req.method === 'POST') { | ||
self.handlePOST(req, res); | ||
} | ||
}; | ||
else { | ||
Server.handleNonPOST(req, res); | ||
} | ||
}); | ||
} | ||
module.exports = JSONRPC; | ||
//===----------------------------------------------------------------------===// | ||
// exposeModule | ||
//===----------------------------------------------------------------------===// | ||
Server.prototype.exposeModule = function(mod, object) { | ||
var funcs = []; | ||
for(var funcName in object) { | ||
var funcObj = object[funcName]; | ||
if(typeof(funcObj) == 'function') { | ||
this.functions[mod + '.' + funcName] = funcObj; | ||
funcs.push(funcName); | ||
} | ||
} | ||
Server.trace('***', 'exposing module: ' + mod + ' [funs: ' + funcs.join(', ') | ||
+ ']'); | ||
return object; | ||
} | ||
//===----------------------------------------------------------------------===// | ||
// expose | ||
//===----------------------------------------------------------------------===// | ||
Server.prototype.expose = function(name, func) { | ||
Server.trace('***', 'exposing: ' + name); | ||
this.functions[name] = func; | ||
} | ||
//===----------------------------------------------------------------------===// | ||
// trace | ||
//===----------------------------------------------------------------------===// | ||
Server.trace = function(direction, message) { | ||
sys.puts(' ' + direction + ' ' + message); | ||
} | ||
//===----------------------------------------------------------------------===// | ||
// listen | ||
//===----------------------------------------------------------------------===// | ||
Server.prototype.listen = function(port, host) { | ||
this.server.listen(port, host); | ||
Server.trace('***', 'Server listening on http://' + (host || '127.0.0.1') + | ||
':' + port + '/'); | ||
} | ||
//===----------------------------------------------------------------------===// | ||
// handleInvalidRequest | ||
//===----------------------------------------------------------------------===// | ||
Server.handleInvalidRequest = function(req, res) { | ||
res.writeHead(400, {'Content-Type': 'text/plain', | ||
'Content-Length': INVALID_REQUEST.length}); | ||
res.write(INVALID_REQUEST); | ||
res.end(); | ||
} | ||
//===----------------------------------------------------------------------===// | ||
// handlePOST | ||
//===----------------------------------------------------------------------===// | ||
Server.prototype.handlePOST = function(req, res) { | ||
var buffer = ''; | ||
var self = this; | ||
var handle = function (buf) { | ||
var decoded = JSON.parse(buf); | ||
console.log(decoded); | ||
// Check for the required fields, and if they aren't there, then | ||
// dispatch to the handleInvalidRequest function. | ||
if(!(decoded.method && decoded.params)) { | ||
return Server.handleInvalidRequest(req, res); | ||
} | ||
if(!self.functions.hasOwnProperty(decoded.method)) { | ||
return Server.handleInvalidRequest(req, res); | ||
} | ||
// Build our success handler | ||
var onSuccess = function(funcResp) { | ||
Server.trace('-->', 'response (id ' + decoded.id + '): ' + | ||
JSON.stringify(funcResp)); | ||
var encoded = JSON.stringify({ | ||
'result': funcResp, | ||
'error': null, | ||
'id': decoded.id | ||
}); | ||
res.writeHead(200, {'Content-Type': 'application/json', | ||
'Content-Length': encoded.length}); | ||
res.write(encoded); | ||
res.end(); | ||
}; | ||
// Build our failure handler (note that error must not be null) | ||
var onFailure = function(failure) { | ||
Server.trace('-->', 'failure: ' + JSON.stringify(failure)); | ||
var encoded = JSON.stringify({ | ||
'result': null, | ||
'error': failure || 'Unspecified Failure', | ||
'id': decoded.id | ||
}); | ||
res.writeHead(200, {'Content-Type': 'application/json', | ||
'Content-Length': encoded.length}); | ||
res.write(encoded); | ||
res.end(); | ||
}; | ||
Server.trace('<--', 'request (id ' + decoded.id + '): ' + | ||
decoded.method + '(' + decoded.params.join(', ') + ')'); | ||
// Try to call the method, but intercept errors and call our | ||
// onFailure handler. | ||
var method = self.functions[decoded.method]; | ||
var args = decoded.params.unshift(function(resp) { | ||
onSuccess(resp); | ||
}); | ||
try { | ||
method.apply(null, decoded.params); | ||
} | ||
catch(err) { | ||
return onFailure(err); | ||
} | ||
} // function handle(buf) | ||
req.addListener('data', function(chunk) { | ||
buffer = buffer + chunk; | ||
}); | ||
req.addListener('end', function() { | ||
handle(buffer); | ||
}); | ||
} | ||
//===----------------------------------------------------------------------===// | ||
// handleNonPOST | ||
//===----------------------------------------------------------------------===// | ||
Server.handleNonPOST = function(req, res) { | ||
res.writeHead(405, {'Content-Type': 'text/plain', | ||
'Content-Length': METHOD_NOT_ALLOWED.length, | ||
'Allow': 'POST'}); | ||
res.write(METHOD_NOT_ALLOWED); | ||
res.end(); | ||
} | ||
module.exports.Server = Server; | ||
module.exports.Client = Client; |
{ | ||
"name": "bitcoin", | ||
"description": "Bitcoin client API library and related utilities", | ||
"version": "0.0.1", | ||
"contributors": [ | ||
{ "name": "Bill Casarin", "email": "jb@jb55.com" }, | ||
"version": "0.0.2", | ||
"contributors": [ | ||
{ "name": "Bill Casarin", "email": "jb@jb55.com" } | ||
], | ||
"dependencies": { "underscore": ">= 1.0.3" }, | ||
"dependencies": { | ||
"underscore": ">= 1.0.3", | ||
"vows": ">= 0.4.0" | ||
}, | ||
"directories": { "lib": "./lib/bitcoin" }, | ||
"engines": { "node": ">= 0.2.3" } | ||
} |
# node-bitcoin | ||
node-bitcoin is a simple wrapper for the Bitcoin client's JSON-RPC API. | ||
node-bitcoin is a simple wrapper for the Bitcoin client's JSON-RPC API. | ||
The API is equivalent to the API document [here](http://www.bitcoin.org/wiki/doku.php?id=api#methods). | ||
The methods are exposed as lower camelcase methods on the `bitcoin.Client` | ||
The API is equivalent to the API document [here](https://en.bitcoin.it/wiki/Original_Bitcoin_client/API_Calls_list). | ||
The methods are exposed as lower camelcase methods on the `bitcoin.Client` | ||
object. | ||
## Install | ||
`npm install bitcoin` | ||
## Setup | ||
@@ -35,3 +39,3 @@ | ||
console.log("Balance:", balance); | ||
} | ||
}); | ||
@@ -5,9 +5,3 @@ | ||
doCmd('getBalance'); | ||
doCmd('getConnectionCount'); | ||
doCmd('getDifficulty'); | ||
doCmd('getInfo'); | ||
doCmd('getHashesPerSecond'); | ||
doCmd('getGenerate'); | ||
doCmd('listTransactions'); | ||
doCmd('getWork'); | ||
@@ -14,0 +8,0 @@ function doCmd(cmd) { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Invalid manifest file
QualityPackage has an invalid manifest file and can cause installation problems if you try to use it.
Found 1 instance in 1 package
Misc. License Issues
License(Experimental) A package's licensing information has fine-grained problems.
Found 1 instance in 1 package
13379
8
0
347
1
41
2
1
2
1
+ Addedunderscore@>= 1.0.3
+ Addedvows@>= 0.4.0
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbrace-expansion@1.1.11(transitive)
+ Addedconcat-map@0.0.1(transitive)
+ Addeddiff@4.0.2(transitive)
+ Addedeyes@0.1.8(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedunderscore@1.13.7(transitive)
+ Addedvows@0.8.3(transitive)
+ Addedwrappy@1.0.2(transitive)