finish getting everything to work. add tests

This commit is contained in:
Patrick Nagurny 2015-08-04 16:34:53 -04:00
parent a2962dc7f3
commit e95d4c865f
10 changed files with 176 additions and 34 deletions

View File

@ -1,24 +0,0 @@
'use strict';
var socket = require('socket.io-client')('http://localhost:3000');
socket.on('connect', function(){
console.log('connected');
});
socket.on('disconnect', function(){
console.log('disconnected');
});
var message = {
command: 'getOutputs',
params: ['1HTxCVrXuthad6YW5895K98XmVsdMvvBSw', true]
};
socket.emit('message', message, function(response) {
if(response.error) {
console.log('Error', response.error);
return;
}
console.log(response.result);
});

View File

@ -2,13 +2,14 @@
var BitcoinNode = require('..').Node;
var chainlib = require('chainlib');
var io = require('socket.io')(3000);
var socketio = require('socket.io');
var log = chainlib.log;
log.debug = function() {};
var configuration = {
datadir: process.env.BITCOINDJS_DIR || '~/.bitcoin',
network: process.env.BITCOINDJS_NETWORK || 'livenet'
network: process.env.BITCOINDJS_NETWORK || 'livenet',
port: 3000
};
var node = new BitcoinNode(configuration);
@ -18,6 +19,8 @@ var interval;
node.on('ready', function() {
var io = socketio(configuration.port);
interval = setInterval(function() {
log.info('Sync Status: Tip:', node.chain.tip.hash, 'Height:', node.chain.tip.__height, 'Rate:', count/10, 'blocks per second');
count = 0;
@ -58,15 +61,17 @@ node.on('ready', function() {
}
var callback = function(err, result) {
console.log('callback called');
console.log(err, result);
var response = {};
if(err) {
response.error = err;
}
if(result) {
response.result = result;
if(result.toJSON) {
response.result = result.toJSON();
} else {
response.result = result;
}
}
socketCallback(response);
@ -92,9 +97,20 @@ node.on('ready', function() {
var events = node.getAllPublishEvents();
events.forEach(function(event) {
bus.on(event.name, function(data) {
bus.on(event.name, function() {
if(socket.connected) {
socket.emit(event.name, data);
var results = [];
for(var i = 0; i < arguments.length; i++) {
if(arguments[i].toJSON) {
results.push(arguments[i].toJSON());
} else {
results.push(arguments[i]);
}
}
var params = [event.name].concat(results);
socket.emit.apply(socket, params);
}
});
});

44
example/client.js Normal file
View File

@ -0,0 +1,44 @@
'use strict';
var socket = require('socket.io-client')('http://localhost:3000');
socket.on('connect', function(){
console.log('connected');
});
socket.on('disconnect', function(){
console.log('disconnected');
});
var message = {
command: 'getOutputs',
params: ['1HTxCVrXuthad6YW5895K98XmVsdMvvBSw', true]
};
socket.send(message, function(response) {
if(response.error) {
console.log('Error', response.error);
return;
}
console.log(response.result);
});
var message2 = {
command: 'getTransaction',
params: ['4f793f67fc7465f14fa3a8d3727fa7d133cdb2f298234548b94a5f08b6f4103e', true]
};
socket.send(message2, function(response) {
if(response.error) {
console.log('Error', response.error);
return;
}
console.log(response.result);
});
socket.on('transaction', function(address, block) {
console.log(address, block);
});
socket.emit('subscribe', 'transaction', ['13FMwCYz3hUhwPcaWuD2M1U2KzfTtvLM89']);

View File

@ -60,6 +60,10 @@ Block.prototype.toObject = function() {
};
};
Block.prototype.toJSON = function() {
return JSON.stringify(this.toObject());
};
Block.prototype.headerToBufferWriter = function(bw) {
/* jshint maxstatements: 20 */

View File

@ -41,7 +41,15 @@ Bus.prototype.unsubscribe = function(name) {
};
Bus.prototype.close = function() {
// TODO Unsubscribe from all events
// Unsubscribe from all events
for (var i = 0; i < this.db.modules.length; i++) {
var mod = this.db.modules[i];
var events = mod.getPublishEvents();
for (var j = 0; j < events.length; j++) {
var event = events[j];
event.unsubscribe.call(event.scope, this);
}
}
};
module.exports = Bus;

View File

@ -172,7 +172,10 @@ AddressModule.prototype.subscribe = function(name, emitter, addresses) {
AddressModule.prototype.unsubscribe = function(name, emitter, addresses) {
$.checkArgument(emitter instanceof EventEmitter, 'First argument is expected to be an EventEmitter');
$.checkArgument(Array.isArray(addresses), 'Second argument is expected to be an Array of addresses');
if(!addresses) {
return this.unsubscribeAll(name, emitter);
}
for(var i = 0; i < addresses.length; i++) {
if(this.subscriptions[name][addresses[i]]) {
@ -185,6 +188,18 @@ AddressModule.prototype.unsubscribe = function(name, emitter, addresses) {
}
};
AddressModule.prototype.unsubscribeAll = function(name, emitter) {
$.checkArgument(emitter instanceof EventEmitter, 'First argument is expected to be an EventEmitter');
for(var address in this.subscriptions[name]) {
var emitters = this.subscriptions[name][address];
var index = emitters.indexOf(emitter);
if(index > -1) {
emitters.splice(index, 1);
}
}
};
AddressModule.prototype.getBalance = function(address, queryMempool, callback) {
this.getUnspentOutputs(address, queryMempool, function(err, outputs) {
if(err) {

View File

@ -30,7 +30,7 @@ Node.prototype.openBus = function() {
};
Node.prototype.getAllAPIMethods = function() {
var methods = [];
var methods = this.db.getAPIMethods();
for (var i = 0; i < this.db.modules.length; i++) {
var mod = this.db.modules[i];
methods = methods.concat(mod.getAPIMethods());

View File

@ -58,4 +58,30 @@ describe('Bus', function() {
});
});
describe('#close', function() {
it('will unsubscribe from all events', function() {
var unsubscribe = sinon.spy();
var db = {
modules: [
{
getPublishEvents: sinon.stub().returns([
{
name: 'test',
scope: this,
unsubscribe: unsubscribe
}
])
}
]
};
var bus = new Bus({db: db});
bus.close();
unsubscribe.callCount.should.equal(1);
unsubscribe.args[0].length.should.equal(1);
unsubscribe.args[0][0].should.equal(bus);
});
});
});

View File

@ -295,6 +295,20 @@ describe('AddressModule', function() {
am.unsubscribe(name, emitter, [address]);
am.subscriptions.balance[address].should.deep.equal([emitter2]);
});
it('should unsubscribe from all addresses if no addresses are specified', function() {
var am = new AddressModule({});
var emitter = new EventEmitter();
var emitter2 = new EventEmitter();
am.subscriptions.balance = {
'1KiW1A4dx1oRgLHtDtBjcunUGkYtFgZ1W': [emitter, emitter2],
'1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N': [emitter2, emitter]
};
am.unsubscribe('balance', emitter);
am.subscriptions.balance.should.deep.equal({
'1KiW1A4dx1oRgLHtDtBjcunUGkYtFgZ1W': [emitter2],
'1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N': [emitter2]
});
});
});
describe('#getBalance', function() {

View File

@ -40,6 +40,45 @@ describe('Bitcoind Node', function() {
bus.db.should.equal(db);
});
});
describe('#getAllAPIMethods', function() {
it('should return db methods and modules methods', function() {
var node = new Node({});
var db = {
getAPIMethods: sinon.stub().returns(['db1', 'db2']),
modules: [
{
getAPIMethods: sinon.stub().returns(['mda1', 'mda2'])
},
{
getAPIMethods: sinon.stub().returns(['mdb1', 'mdb2'])
}
]
};
node.db = db;
var methods = node.getAllAPIMethods();
methods.should.deep.equal(['db1', 'db2', 'mda1', 'mda2', 'mdb1', 'mdb2']);
});
});
describe('#getAllPublishEvents', function() {
it('should return modules publish events', function() {
var node = new Node({});
var db = {
modules: [
{
getPublishEvents: sinon.stub().returns(['mda1', 'mda2'])
},
{
getPublishEvents: sinon.stub().returns(['mdb1', 'mdb2'])
}
]
};
node.db = db;
var events = node.getAllPublishEvents();
events.should.deep.equal(['mda1', 'mda2', 'mdb1', 'mdb2']);
});
});
describe('#_loadConfiguration', function() {
it('should call the necessary methods', function() {
var node = new Node({});