Move Modules from DB to Node
This commit is contained in:
parent
aa6b03ae58
commit
56ebf42403
@ -364,9 +364,7 @@ The module can then be used when running a node:
|
|||||||
```js
|
```js
|
||||||
var configuration = {
|
var configuration = {
|
||||||
datadir: process.env.BITCORENODE_DIR || '~/.bitcoin',
|
datadir: process.env.BITCORENODE_DIR || '~/.bitcoin',
|
||||||
db: {
|
modules: [MyModule]
|
||||||
modules: [MyModule]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var node = new Node(configuration);
|
var node = new Node(configuration);
|
||||||
|
|||||||
33
lib/db.js
33
lib/db.js
@ -12,8 +12,6 @@ var index = require('./');
|
|||||||
var errors = index.errors;
|
var errors = index.errors;
|
||||||
var log = index.log;
|
var log = index.log;
|
||||||
var Transaction = require('./transaction');
|
var Transaction = require('./transaction');
|
||||||
var BaseModule = require('./module');
|
|
||||||
var AddressModule = require('./modules/address');
|
|
||||||
|
|
||||||
function DB(options) {
|
function DB(options) {
|
||||||
/* jshint maxstatements: 30 */
|
/* jshint maxstatements: 30 */
|
||||||
@ -52,12 +50,6 @@ function DB(options) {
|
|||||||
|
|
||||||
this.node = options.node;
|
this.node = options.node;
|
||||||
|
|
||||||
// Modules to be loaded when ready
|
|
||||||
this._modules = options.modules || [];
|
|
||||||
this._modules.push(AddressModule);
|
|
||||||
|
|
||||||
this.modules = [];
|
|
||||||
|
|
||||||
this.subscriptions = {
|
this.subscriptions = {
|
||||||
transaction: [],
|
transaction: [],
|
||||||
block: []
|
block: []
|
||||||
@ -79,12 +71,6 @@ DB.prototype.initialize = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
DB.prototype.start = function(callback) {
|
DB.prototype.start = function(callback) {
|
||||||
// Add all db option modules
|
|
||||||
if(this._modules && this._modules.length) {
|
|
||||||
for(var i = 0; i < this._modules.length; i++) {
|
|
||||||
this.addModule(this._modules[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.node.bitcoind.on('tx', this.transactionHandler.bind(this));
|
this.node.bitcoind.on('tx', this.transactionHandler.bind(this));
|
||||||
this.emit('ready');
|
this.emit('ready');
|
||||||
setImmediate(callback);
|
setImmediate(callback);
|
||||||
@ -278,9 +264,9 @@ DB.prototype.blockHandler = function(block, add, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async.eachSeries(
|
async.eachSeries(
|
||||||
this.modules,
|
this.node.modules,
|
||||||
function(module, next) {
|
function(bitcoreNodeModule, next) {
|
||||||
module['blockHandler'].call(module, block, add, function(err, ops) {
|
bitcoreNodeModule.blockHandler.call(bitcoreNodeModule, block, add, function(err, ops) {
|
||||||
if(err) {
|
if(err) {
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
@ -308,11 +294,6 @@ DB.prototype.getAPIMethods = function() {
|
|||||||
['sendTransaction', this, this.sendTransaction, 1],
|
['sendTransaction', this, this.sendTransaction, 1],
|
||||||
['estimateFee', this, this.estimateFee, 1]
|
['estimateFee', this, this.estimateFee, 1]
|
||||||
];
|
];
|
||||||
|
|
||||||
for(var i = 0; i < this.modules.length; i++) {
|
|
||||||
methods = methods.concat(this.modules[i]['getAPIMethods'].call(this.modules[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return methods;
|
return methods;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -333,14 +314,6 @@ DB.prototype.getPublishEvents = function() {
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
DB.prototype.addModule = function(Module) {
|
|
||||||
var module = new Module({
|
|
||||||
node: this.node
|
|
||||||
});
|
|
||||||
$.checkArgumentType(module, BaseModule);
|
|
||||||
this.modules.push(module);
|
|
||||||
};
|
|
||||||
|
|
||||||
DB.prototype.subscribe = function(name, emitter) {
|
DB.prototype.subscribe = function(name, emitter) {
|
||||||
this.subscriptions[name].push(emitter);
|
this.subscriptions[name].push(emitter);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,6 +4,11 @@ var Module = function(options) {
|
|||||||
this.node = options.node;
|
this.node = options.node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the dependencies that should be loaded before this module.
|
||||||
|
*/
|
||||||
|
Module.dependencies = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* blockHandler
|
* blockHandler
|
||||||
* @param {Block} block - the block being added or removed from the chain
|
* @param {Block} block - the block being added or removed from the chain
|
||||||
@ -45,12 +50,12 @@ Module.prototype.getAPIMethods = function() {
|
|||||||
//
|
//
|
||||||
// };
|
// };
|
||||||
|
|
||||||
Module.prototype.start = function() {
|
Module.prototype.start = function(done) {
|
||||||
|
setImmediate(done);
|
||||||
};
|
};
|
||||||
|
|
||||||
Module.prototype.stop = function() {
|
Module.prototype.stop = function(done) {
|
||||||
|
setImmediate(done);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Module;
|
module.exports = Module;
|
||||||
|
|||||||
@ -27,6 +27,11 @@ var AddressModule = function(options) {
|
|||||||
|
|
||||||
inherits(AddressModule, BaseModule);
|
inherits(AddressModule, BaseModule);
|
||||||
|
|
||||||
|
AddressModule.dependencies = [
|
||||||
|
'bitcoind',
|
||||||
|
'db'
|
||||||
|
];
|
||||||
|
|
||||||
AddressModule.PREFIXES = {
|
AddressModule.PREFIXES = {
|
||||||
OUTPUTS: 'outs',
|
OUTPUTS: 'outs',
|
||||||
SPENTS: 'sp'
|
SPENTS: 'sp'
|
||||||
|
|||||||
135
lib/node.js
135
lib/node.js
@ -17,6 +17,7 @@ var index = require('./');
|
|||||||
var log = index.log;
|
var log = index.log;
|
||||||
var daemon = require('./daemon');
|
var daemon = require('./daemon');
|
||||||
var Bus = require('./bus');
|
var Bus = require('./bus');
|
||||||
|
var BaseModule = require('./module');
|
||||||
|
|
||||||
function Node(config) {
|
function Node(config) {
|
||||||
if(!(this instanceof Node)) {
|
if(!(this instanceof Node)) {
|
||||||
@ -27,10 +28,17 @@ function Node(config) {
|
|||||||
this.chain = null;
|
this.chain = null;
|
||||||
this.network = null;
|
this.network = null;
|
||||||
|
|
||||||
|
this.modules = {};
|
||||||
|
this._unloadedModules = [];
|
||||||
|
|
||||||
|
// TODO type check the arguments of config.modules
|
||||||
|
if (config.modules) {
|
||||||
|
$.checkArgument(Array.isArray(config.modules));
|
||||||
|
this._unloadedModules = config.modules;
|
||||||
|
}
|
||||||
|
|
||||||
this._loadConfiguration(config);
|
this._loadConfiguration(config);
|
||||||
this._initialize();
|
this._initialize();
|
||||||
|
|
||||||
this.testnet = config.testnet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
util.inherits(Node, EventEmitter);
|
util.inherits(Node, EventEmitter);
|
||||||
@ -39,10 +47,41 @@ Node.prototype.openBus = function() {
|
|||||||
return new Bus({db: this.db});
|
return new Bus({db: this.db});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Node.prototype.addModule = function(service) {
|
||||||
|
var self = this;
|
||||||
|
var mod = new service.module({
|
||||||
|
node: this
|
||||||
|
});
|
||||||
|
|
||||||
|
$.checkState(
|
||||||
|
mod instanceof BaseModule,
|
||||||
|
'Unexpected module instance type for module:' + service.name
|
||||||
|
);
|
||||||
|
|
||||||
|
// include in loaded modules
|
||||||
|
this.modules[service.name] = mod;
|
||||||
|
|
||||||
|
// add API methods
|
||||||
|
var methodData = mod.getAPIMethods();
|
||||||
|
methodData.forEach(function(data) {
|
||||||
|
var name = data[0];
|
||||||
|
var instance = data[1];
|
||||||
|
var method = data[2];
|
||||||
|
|
||||||
|
if (self[name]) {
|
||||||
|
throw new Error('Existing API method exists:' + name);
|
||||||
|
} else {
|
||||||
|
self[name] = function() {
|
||||||
|
return method.apply(instance, arguments);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
Node.prototype.getAllAPIMethods = function() {
|
Node.prototype.getAllAPIMethods = function() {
|
||||||
var methods = this.db.getAPIMethods();
|
var methods = this.db.getAPIMethods();
|
||||||
for (var i = 0; i < this.db.modules.length; i++) {
|
for(var i in this.modules) {
|
||||||
var mod = this.db.modules[i];
|
var mod = this.modules[i];
|
||||||
methods = methods.concat(mod.getAPIMethods());
|
methods = methods.concat(mod.getAPIMethods());
|
||||||
}
|
}
|
||||||
return methods;
|
return methods;
|
||||||
@ -50,8 +89,8 @@ Node.prototype.getAllAPIMethods = function() {
|
|||||||
|
|
||||||
Node.prototype.getAllPublishEvents = function() {
|
Node.prototype.getAllPublishEvents = function() {
|
||||||
var events = this.db.getPublishEvents();
|
var events = this.db.getPublishEvents();
|
||||||
for (var i = 0; i < this.db.modules.length; i++) {
|
for (var i in this.modules) {
|
||||||
var mod = this.db.modules[i];
|
var mod = this.modules[i];
|
||||||
events = events.concat(mod.getPublishEvents());
|
events = events.concat(mod.getPublishEvents());
|
||||||
}
|
}
|
||||||
return events;
|
return events;
|
||||||
@ -379,7 +418,6 @@ Node.prototype._loadConsensus = function(config) {
|
|||||||
|
|
||||||
Node.prototype._loadAPI = function() {
|
Node.prototype._loadAPI = function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var methodData = self.db.getAPIMethods();
|
var methodData = self.db.getAPIMethods();
|
||||||
methodData.forEach(function(data) {
|
methodData.forEach(function(data) {
|
||||||
var name = data[0];
|
var name = data[0];
|
||||||
@ -456,32 +494,62 @@ Node.prototype._initializeChain = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Node.prototype.getServices = function() {
|
Node.prototype.getServices = function() {
|
||||||
var defaultServices = {
|
var services = [
|
||||||
'bitcoind': [],
|
{
|
||||||
'db': ['bitcoind'],
|
name: 'bitcoind',
|
||||||
'chain': ['db']
|
dependencies: []
|
||||||
};
|
},
|
||||||
return defaultServices;
|
{
|
||||||
|
name: 'db',
|
||||||
|
dependencies: ['bitcoind'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'chain',
|
||||||
|
dependencies: ['db']
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
services = services.concat(this._unloadedModules);
|
||||||
|
|
||||||
|
return services;
|
||||||
};
|
};
|
||||||
|
|
||||||
Node.prototype.getServiceOrder = function(keys, stack) {
|
Node.prototype.getServiceOrder = function() {
|
||||||
|
|
||||||
var services = this.getServices();
|
var services = this.getServices();
|
||||||
|
|
||||||
if(!keys) {
|
// organize data for sorting
|
||||||
keys = Object.keys(services);
|
var names = [];
|
||||||
|
var servicesByName = {};
|
||||||
|
for (var i = 0; i < services.length; i++) {
|
||||||
|
var service = services[i];
|
||||||
|
names.push(service.name);
|
||||||
|
servicesByName[service.name] = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!stack) {
|
var stackNames = {};
|
||||||
stack = [];
|
var stack = [];
|
||||||
}
|
|
||||||
|
function addToStack(names) {
|
||||||
|
for(var i = 0; i < names.length; i++) {
|
||||||
|
|
||||||
|
var name = names[i];
|
||||||
|
var service = servicesByName[name];
|
||||||
|
|
||||||
|
// first add the dependencies
|
||||||
|
addToStack(service.dependencies);
|
||||||
|
|
||||||
|
// add to the stack if it hasn't been added
|
||||||
|
if(!stackNames[name]) {
|
||||||
|
stack.push(service);
|
||||||
|
stackNames[name] = true;
|
||||||
|
}
|
||||||
|
|
||||||
for(var i = 0; i < keys.length; i++) {
|
|
||||||
this.getServiceOrder(services[keys[i]], stack);
|
|
||||||
if(stack.indexOf(keys[i]) === -1) {
|
|
||||||
stack.push(keys[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addToStack(names);
|
||||||
|
|
||||||
return stack;
|
return stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -492,8 +560,15 @@ Node.prototype.start = function(callback) {
|
|||||||
async.eachSeries(
|
async.eachSeries(
|
||||||
servicesOrder,
|
servicesOrder,
|
||||||
function(service, next) {
|
function(service, next) {
|
||||||
log.info('Starting ' + service);
|
log.info('Starting ' + service.name);
|
||||||
self[service].start(next);
|
|
||||||
|
if (service.module) {
|
||||||
|
self.addModule(service);
|
||||||
|
self.modules[service.name].start(next);
|
||||||
|
} else {
|
||||||
|
// TODO: implement bitcoind, chain and db as modules
|
||||||
|
self[service.name].start(next);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
callback
|
callback
|
||||||
);
|
);
|
||||||
@ -510,12 +585,16 @@ Node.prototype.stop = function(callback) {
|
|||||||
async.eachSeries(
|
async.eachSeries(
|
||||||
services,
|
services,
|
||||||
function(service, next) {
|
function(service, next) {
|
||||||
log.info('Stopping ' + service);
|
log.info('Stopping ' + service.name);
|
||||||
self[service].stop(next);
|
|
||||||
|
if (service.module) {
|
||||||
|
self.modules[service.name].stop(next);
|
||||||
|
} else {
|
||||||
|
self[service.name].stop(next);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
callback
|
callback
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports = Node;
|
module.exports = Node;
|
||||||
|
|||||||
@ -12,7 +12,8 @@ function getDefaultConfig() {
|
|||||||
config: {
|
config: {
|
||||||
datadir: process.env.BITCORENODE_DIR || path.resolve(process.env.HOME, '.bitcoin'),
|
datadir: process.env.BITCORENODE_DIR || path.resolve(process.env.HOME, '.bitcoin'),
|
||||||
network: process.env.BITCORENODE_NETWORK || 'livenet',
|
network: process.env.BITCORENODE_NETWORK || 'livenet',
|
||||||
port: process.env.BITCORENODE_PORT || 3001
|
port: process.env.BITCORENODE_PORT || 3001,
|
||||||
|
modules: ['address']
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,18 +36,23 @@ function start(options) {
|
|||||||
bitcoreNodeModule = moduleName + '/' + modulePackage.bitcoreNode;
|
bitcoreNodeModule = moduleName + '/' + modulePackage.bitcoreNode;
|
||||||
}
|
}
|
||||||
bitcoreModule = require(bitcoreNodeModule);
|
bitcoreModule = require(bitcoreNodeModule);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that the module supports expected methods
|
// check that the module supports expected methods
|
||||||
if (!bitcoreModule.prototype ||
|
if (!bitcoreModule.prototype ||
|
||||||
|
!bitcoreModule.dependencies ||
|
||||||
!bitcoreModule.prototype.start ||
|
!bitcoreModule.prototype.start ||
|
||||||
!bitcoreModule.prototype.stop) {
|
!bitcoreModule.prototype.stop) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Could not load module "' + moduleName + '" as it does not support necessary methods.'
|
'Could not load module "' + moduleName + '" as it does not support necessary methods.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
bitcoreModules.push(bitcoreModule);
|
bitcoreModules.push({
|
||||||
|
name: moduleName,
|
||||||
|
module: bitcoreModule,
|
||||||
|
dependencies: bitcoreModule.dependencies
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,13 +61,8 @@ function start(options) {
|
|||||||
// expand to the full path
|
// expand to the full path
|
||||||
fullConfig.datadir = path.resolve(configPath, config.datadir);
|
fullConfig.datadir = path.resolve(configPath, config.datadir);
|
||||||
|
|
||||||
// delete until modules move to the node
|
|
||||||
delete fullConfig.modules;
|
|
||||||
|
|
||||||
// load the modules
|
// load the modules
|
||||||
fullConfig.db = {
|
fullConfig.modules = bitcoreModules;
|
||||||
modules: bitcoreModules
|
|
||||||
};
|
|
||||||
|
|
||||||
var node = new BitcoreNode(fullConfig);
|
var node = new BitcoreNode(fullConfig);
|
||||||
|
|
||||||
|
|||||||
@ -249,26 +249,16 @@ describe('Bitcoin Chain', function() {
|
|||||||
|
|
||||||
chain.tip = block2;
|
chain.tip = block2;
|
||||||
|
|
||||||
chain.on('ready', function() {
|
delete chain.cache.hashes[block1.hash];
|
||||||
|
|
||||||
// remove one of the cached hashes to force db call
|
// the test
|
||||||
delete chain.cache.hashes[block1.hash];
|
chain.getHashes(block2.hash, function(err, hashes) {
|
||||||
|
|
||||||
// the test
|
|
||||||
chain.getHashes(block2.hash, function(err, hashes) {
|
|
||||||
should.not.exist(err);
|
|
||||||
should.exist(hashes);
|
|
||||||
hashes.length.should.equal(3);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
chain.on('error', function(err) {
|
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
|
should.exist(hashes);
|
||||||
|
hashes.length.should.equal(3);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
chain.initialize();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,6 @@ var bitcore = require('bitcore');
|
|||||||
var Transaction = bitcore.Transaction;
|
var Transaction = bitcore.Transaction;
|
||||||
|
|
||||||
describe('Bitcoin DB', function() {
|
describe('Bitcoin DB', function() {
|
||||||
var coinbaseAmount = 50 * 1e8;
|
|
||||||
|
|
||||||
describe('#start', function() {
|
describe('#start', function() {
|
||||||
it('should emit ready', function(done) {
|
it('should emit ready', function(done) {
|
||||||
@ -336,7 +335,8 @@ describe('Bitcoin DB', function() {
|
|||||||
Module1.prototype.blockHandler = sinon.stub().callsArgWith(2, null, ['op1', 'op2', 'op3']);
|
Module1.prototype.blockHandler = sinon.stub().callsArgWith(2, null, ['op1', 'op2', 'op3']);
|
||||||
var Module2 = function() {};
|
var Module2 = function() {};
|
||||||
Module2.prototype.blockHandler = sinon.stub().callsArgWith(2, null, ['op4', 'op5']);
|
Module2.prototype.blockHandler = sinon.stub().callsArgWith(2, null, ['op4', 'op5']);
|
||||||
db.modules = [
|
db.node = {};
|
||||||
|
db.node.modules = [
|
||||||
new Module1(),
|
new Module1(),
|
||||||
new Module2()
|
new Module2()
|
||||||
];
|
];
|
||||||
@ -355,7 +355,7 @@ describe('Bitcoin DB', function() {
|
|||||||
it('should give an error if one of the modules gives an error', function(done) {
|
it('should give an error if one of the modules gives an error', function(done) {
|
||||||
var Module3 = function() {};
|
var Module3 = function() {};
|
||||||
Module3.prototype.blockHandler = sinon.stub().callsArgWith(2, new Error('error'));
|
Module3.prototype.blockHandler = sinon.stub().callsArgWith(2, new Error('error'));
|
||||||
db.modules.push(new Module3());
|
db.node.modules.push(new Module3());
|
||||||
|
|
||||||
db.blockHandler('block', true, function(err) {
|
db.blockHandler('block', true, function(err) {
|
||||||
should.exist(err);
|
should.exist(err);
|
||||||
@ -367,62 +367,11 @@ describe('Bitcoin DB', function() {
|
|||||||
describe('#getAPIMethods', function() {
|
describe('#getAPIMethods', function() {
|
||||||
it('should return the correct db methods', function() {
|
it('should return the correct db methods', function() {
|
||||||
var db = new DB({store: memdown});
|
var db = new DB({store: memdown});
|
||||||
db.modules = [];
|
db.node = {};
|
||||||
|
db.node.modules = [];
|
||||||
var methods = db.getAPIMethods();
|
var methods = db.getAPIMethods();
|
||||||
methods.length.should.equal(4);
|
methods.length.should.equal(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should also return modules API methods', function() {
|
|
||||||
var module1 = {
|
|
||||||
getAPIMethods: function() {
|
|
||||||
return [
|
|
||||||
['module1-one', module1, module1, 2],
|
|
||||||
['module1-two', module1, module1, 2]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var module2 = {
|
|
||||||
getAPIMethods: function() {
|
|
||||||
return [
|
|
||||||
['moudle2-one', module2, module2, 1]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var db = new DB({store: memdown});
|
|
||||||
db.modules = [module1, module2];
|
|
||||||
|
|
||||||
var methods = db.getAPIMethods();
|
|
||||||
methods.length.should.equal(7);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#addModule', function() {
|
|
||||||
it('instantiate module and add to db.modules', function() {
|
|
||||||
var Module1 = function(options) {
|
|
||||||
BaseModule.call(this, options);
|
|
||||||
};
|
|
||||||
inherits(Module1, BaseModule);
|
|
||||||
|
|
||||||
var db = new DB({store: memdown});
|
|
||||||
var node = {};
|
|
||||||
db.node = node;
|
|
||||||
db.modules = [];
|
|
||||||
db.addModule(Module1);
|
|
||||||
|
|
||||||
db.modules.length.should.equal(1);
|
|
||||||
should.exist(db.modules[0].node);
|
|
||||||
db.modules[0].node.should.equal(node);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error if module is not an instance of BaseModule', function() {
|
|
||||||
var Module2 = function(options) {};
|
|
||||||
var db = new DB({store: memdown});
|
|
||||||
db.modules = [];
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
db.addModule(Module2);
|
|
||||||
}).should.throw('bitcore.ErrorInvalidArgumentType');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -13,8 +13,10 @@ var index = require('..');
|
|||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var bitcoinConfBuffer = fs.readFileSync(__dirname + '/data/bitcoin.conf');
|
var bitcoinConfBuffer = fs.readFileSync(__dirname + '/data/bitcoin.conf');
|
||||||
var chainHashes = require('./data/hashes.json');
|
var chainHashes = require('./data/hashes.json');
|
||||||
|
var util = require('util');
|
||||||
|
var BaseModule = require('../lib/module');
|
||||||
|
|
||||||
describe('Bitcoind Node', function() {
|
describe('Bitcore Node', function() {
|
||||||
|
|
||||||
var Node;
|
var Node;
|
||||||
var BadNode;
|
var BadNode;
|
||||||
@ -47,6 +49,36 @@ describe('Bitcoind Node', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('@constructor', function() {
|
||||||
|
it('will set properties', function() {
|
||||||
|
function TestModule() {}
|
||||||
|
util.inherits(TestModule, BaseModule);
|
||||||
|
TestModule.prototype.getData = function() {};
|
||||||
|
TestModule.prototype.getAPIMethods = function() {
|
||||||
|
return [
|
||||||
|
['getData', this, this.getData, 1]
|
||||||
|
];
|
||||||
|
};
|
||||||
|
var config = {
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
name: 'test1',
|
||||||
|
module: TestModule
|
||||||
|
}
|
||||||
|
],
|
||||||
|
};
|
||||||
|
var TestNode = proxyquire('../lib/node', {});
|
||||||
|
TestNode.prototype._loadConfiguration = sinon.spy();
|
||||||
|
TestNode.prototype._initialize = sinon.spy();
|
||||||
|
var node = new TestNode(config);
|
||||||
|
TestNode.prototype._loadConfiguration.callCount.should.equal(1);
|
||||||
|
TestNode.prototype._initialize.callCount.should.equal(1);
|
||||||
|
node._unloadedModules.length.should.equal(1);
|
||||||
|
node._unloadedModules[0].name.should.equal('test1');
|
||||||
|
node._unloadedModules[0].module.should.equal(TestModule);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('#openBus', function() {
|
describe('#openBus', function() {
|
||||||
it('will create a new bus', function() {
|
it('will create a new bus', function() {
|
||||||
var node = new Node({});
|
var node = new Node({});
|
||||||
@ -56,19 +88,41 @@ describe('Bitcoind Node', function() {
|
|||||||
bus.db.should.equal(db);
|
bus.db.should.equal(db);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#addModule', function() {
|
||||||
|
it('will instantiate an instance and load api methods', function() {
|
||||||
|
var node = new Node({});
|
||||||
|
function TestModule() {}
|
||||||
|
util.inherits(TestModule, BaseModule);
|
||||||
|
TestModule.prototype.getData = function() {};
|
||||||
|
TestModule.prototype.getAPIMethods = function() {
|
||||||
|
return [
|
||||||
|
['getData', this, this.getData, 1]
|
||||||
|
];
|
||||||
|
};
|
||||||
|
var service = {
|
||||||
|
name: 'testmodule',
|
||||||
|
module: TestModule
|
||||||
|
};
|
||||||
|
node.addModule(service);
|
||||||
|
should.exist(node.modules.testmodule);
|
||||||
|
should.exist(node.getData);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('#getAllAPIMethods', function() {
|
describe('#getAllAPIMethods', function() {
|
||||||
it('should return db methods and modules methods', function() {
|
it('should return db methods and modules methods', function() {
|
||||||
var node = new Node({});
|
var node = new Node({});
|
||||||
|
node.modules = [
|
||||||
|
{
|
||||||
|
getAPIMethods: sinon.stub().returns(['mda1', 'mda2'])
|
||||||
|
},
|
||||||
|
{
|
||||||
|
getAPIMethods: sinon.stub().returns(['mdb1', 'mdb2'])
|
||||||
|
}
|
||||||
|
];
|
||||||
var db = {
|
var db = {
|
||||||
getAPIMethods: sinon.stub().returns(['db1', 'db2']),
|
getAPIMethods: sinon.stub().returns(['db1', 'db2']),
|
||||||
modules: [
|
|
||||||
{
|
|
||||||
getAPIMethods: sinon.stub().returns(['mda1', 'mda2'])
|
|
||||||
},
|
|
||||||
{
|
|
||||||
getAPIMethods: sinon.stub().returns(['mdb1', 'mdb2'])
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
node.db = db;
|
node.db = db;
|
||||||
|
|
||||||
@ -79,16 +133,16 @@ describe('Bitcoind Node', function() {
|
|||||||
describe('#getAllPublishEvents', function() {
|
describe('#getAllPublishEvents', function() {
|
||||||
it('should return modules publish events', function() {
|
it('should return modules publish events', function() {
|
||||||
var node = new Node({});
|
var node = new Node({});
|
||||||
|
node.modules = [
|
||||||
|
{
|
||||||
|
getPublishEvents: sinon.stub().returns(['mda1', 'mda2'])
|
||||||
|
},
|
||||||
|
{
|
||||||
|
getPublishEvents: sinon.stub().returns(['mdb1', 'mdb2'])
|
||||||
|
}
|
||||||
|
];
|
||||||
var db = {
|
var db = {
|
||||||
getPublishEvents: sinon.stub().returns(['db1', 'db2']),
|
getPublishEvents: sinon.stub().returns(['db1', 'db2']),
|
||||||
modules: [
|
|
||||||
{
|
|
||||||
getPublishEvents: sinon.stub().returns(['mda1', 'mda2'])
|
|
||||||
},
|
|
||||||
{
|
|
||||||
getPublishEvents: sinon.stub().returns(['mdb1', 'mdb2'])
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
node.db = db;
|
node.db = db;
|
||||||
|
|
||||||
@ -648,15 +702,96 @@ describe('Bitcoind Node', function() {
|
|||||||
it('should return the services in the correct order', function() {
|
it('should return the services in the correct order', function() {
|
||||||
var node = new Node({});
|
var node = new Node({});
|
||||||
node.getServices = function() {
|
node.getServices = function() {
|
||||||
return {
|
return [
|
||||||
'chain': ['db'],
|
{
|
||||||
'db': ['daemon', 'p2p'],
|
name: 'chain',
|
||||||
'daemon': [],
|
dependencies: ['db']
|
||||||
'p2p': []
|
},
|
||||||
};
|
{
|
||||||
|
name: 'db',
|
||||||
|
dependencies: ['daemon', 'p2p']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'daemon',
|
||||||
|
dependencies: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'p2p',
|
||||||
|
dependencies: []
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
var order = node.getServiceOrder();
|
var order = node.getServiceOrder();
|
||||||
order.should.deep.equal(['daemon', 'p2p', 'db', 'chain']);
|
order[0].name.should.equal('daemon');
|
||||||
|
order[1].name.should.equal('p2p');
|
||||||
|
order[2].name.should.equal('db');
|
||||||
|
order[3].name.should.equal('chain');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#start', function() {
|
||||||
|
it('will call start for each module', function(done) {
|
||||||
|
var node = new Node({});
|
||||||
|
function TestModule() {}
|
||||||
|
util.inherits(TestModule, BaseModule);
|
||||||
|
TestModule.prototype.start = sinon.stub().callsArg(0);
|
||||||
|
TestModule.prototype.getData = function() {};
|
||||||
|
TestModule.prototype.getAPIMethods = function() {
|
||||||
|
return [
|
||||||
|
['getData', this, this.getData, 1]
|
||||||
|
];
|
||||||
|
};
|
||||||
|
node.test2 = {};
|
||||||
|
node.test2.start = sinon.stub().callsArg(0);
|
||||||
|
node.getServiceOrder = sinon.stub().returns([
|
||||||
|
{
|
||||||
|
name: 'test1',
|
||||||
|
module: TestModule
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'test2'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
node.start(function() {
|
||||||
|
node.test2.start.callCount.should.equal(1);
|
||||||
|
TestModule.prototype.start.callCount.should.equal(1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#stop', function() {
|
||||||
|
it('will call stop for each module', function(done) {
|
||||||
|
var node = new Node({});
|
||||||
|
function TestModule() {}
|
||||||
|
util.inherits(TestModule, BaseModule);
|
||||||
|
TestModule.prototype.stop = sinon.stub().callsArg(0);
|
||||||
|
TestModule.prototype.getData = function() {};
|
||||||
|
TestModule.prototype.getAPIMethods = function() {
|
||||||
|
return [
|
||||||
|
['getData', this, this.getData, 1]
|
||||||
|
];
|
||||||
|
};
|
||||||
|
node.modules = {
|
||||||
|
'test1': new TestModule({node: node})
|
||||||
|
};
|
||||||
|
node.test2 = {};
|
||||||
|
node.test2.stop = sinon.stub().callsArg(0);
|
||||||
|
node.getServiceOrder = sinon.stub().returns([
|
||||||
|
{
|
||||||
|
name: 'test2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'test1',
|
||||||
|
module: TestModule
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
node.stop(function() {
|
||||||
|
node.test2.stop.callCount.should.equal(1);
|
||||||
|
TestModule.prototype.stop.callCount.should.equal(1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -12,7 +12,11 @@ describe('#start', function() {
|
|||||||
it('require each bitcore-node module', function(done) {
|
it('require each bitcore-node module', function(done) {
|
||||||
var node;
|
var node;
|
||||||
var TestNode = function(options) {
|
var TestNode = function(options) {
|
||||||
options.db.modules.should.deep.equal([AddressModule]);
|
options.modules[0].should.deep.equal({
|
||||||
|
name: 'address',
|
||||||
|
module: AddressModule,
|
||||||
|
dependencies: ['bitcoind', 'db']
|
||||||
|
});
|
||||||
};
|
};
|
||||||
TestNode.prototype.on = sinon.stub();
|
TestNode.prototype.on = sinon.stub();
|
||||||
TestNode.prototype.chain = {
|
TestNode.prototype.chain = {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user