Rename modules to services.

This commit is contained in:
Braydon Fuller 2015-08-31 09:00:00 -04:00
parent 16eef1279c
commit 7551f487f8
22 changed files with 436 additions and 444 deletions

View File

@ -10,7 +10,7 @@ process.title = 'libbitcoind';
/** /**
* daemon * daemon
*/ */
var daemon = require('../').modules.BitcoinModule({ var daemon = require('../').services.Bitcoin({
node: { node: {
datadir: process.env.BITCORENODE_DIR || process.env.HOME + '/.bitcoin', datadir: process.env.BITCORENODE_DIR || process.env.HOME + '/.bitcoin',
network: { network: {

View File

@ -3,13 +3,13 @@
module.exports = require('./lib'); module.exports = require('./lib');
module.exports.Node = require('./lib/node'); module.exports.Node = require('./lib/node');
module.exports.Transaction = require('./lib/transaction'); module.exports.Transaction = require('./lib/transaction');
module.exports.Module = require('./lib/module'); module.exports.Service = require('./lib/service');
module.exports.errors = require('./lib/errors'); module.exports.errors = require('./lib/errors');
module.exports.modules = {}; module.exports.services = {};
module.exports.modules.AddressModule = require('./lib/modules/address'); module.exports.services.Address = require('./lib/services/address');
module.exports.modules.BitcoinModule = require('./lib/modules/bitcoind'); module.exports.services.Bitcoin = require('./lib/services/bitcoind');
module.exports.modules.DBModule = require('./lib/modules/db'); module.exports.services.DB = require('./lib/services/db');
module.exports.scaffold = {}; module.exports.scaffold = {};
module.exports.scaffold.create = require('./lib/scaffold/create'); module.exports.scaffold.create = require('./lib/scaffold/create');

View File

@ -25,9 +25,9 @@ var should = chai.should();
var BitcoinRPC = require('bitcoind-rpc'); var BitcoinRPC = require('bitcoind-rpc');
var index = require('..'); var index = require('..');
var BitcoreNode = index.Node; var BitcoreNode = index.Node;
var AddressModule = index.modules.AddressModule; var AddressService = index.services.Address;
var BitcoinModule = index.modules.BitcoinModule; var BitcoinService = index.services.Bitcoin;
var DBModule = index.modules.DBModule; var DBService = index.services.DB;
var testWIF = 'cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG'; var testWIF = 'cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG';
var testKey; var testKey;
var client; var client;
@ -65,21 +65,21 @@ describe('Node Functionality', function() {
var configuration = { var configuration = {
datadir: datadir, datadir: datadir,
network: 'regtest', network: 'regtest',
modules: [ services: [
{ {
name: 'db', name: 'db',
module: DBModule, module: DBService,
dependencies: DBModule.dependencies dependencies: DBService.dependencies
}, },
{ {
name: 'bitcoind', name: 'bitcoind',
module: BitcoinModule, module: BitcoinService,
dependencies: BitcoinModule.dependencies dependencies: BitcoinService.dependencies
}, },
{ {
name: 'address', name: 'address',
module: AddressModule, module: AddressService,
dependencies: AddressModule.dependencies dependencies: AddressService.dependencies
} }
] ]
}; };
@ -102,7 +102,7 @@ describe('Node Functionality', function() {
}); });
var syncedHandler = function() { var syncedHandler = function() {
if (node.modules.db.tip.__height === 150) { if (node.services.db.tip.__height === 150) {
node.removeListener('synced', syncedHandler); node.removeListener('synced', syncedHandler);
done(); done();
} }
@ -178,18 +178,18 @@ describe('Node Functionality', function() {
blocksRemoved++; blocksRemoved++;
}; };
node.modules.db.on('removeblock', removeBlock); node.services.db.on('removeblock', removeBlock);
var addBlock = function() { var addBlock = function() {
blocksAdded++; blocksAdded++;
if (blocksAdded === 2 && blocksRemoved === 1) { if (blocksAdded === 2 && blocksRemoved === 1) {
node.modules.db.removeListener('addblock', addBlock); node.services.db.removeListener('addblock', addBlock);
node.modules.db.removeListener('removeblock', removeBlock); node.services.db.removeListener('removeblock', removeBlock);
done(); done();
} }
}; };
node.modules.db.on('addblock', addBlock); node.services.db.on('addblock', addBlock);
// We need to add a transaction to the mempool so that the next block will // We need to add a transaction to the mempool so that the next block will
// have a different hash as the hash has been invalidated. // have a different hash as the hash has been invalidated.

View File

@ -61,7 +61,7 @@ describe('Daemon Binding Functionality', function() {
throw err; throw err;
} }
bitcoind = require('../').modules.BitcoinModule({ bitcoind = require('../').services.Bitcoin({
node: { node: {
datadir: datadir, datadir: datadir,
network: { network: {

View File

@ -11,11 +11,11 @@ function Bus(params) {
util.inherits(Bus, events.EventEmitter); util.inherits(Bus, events.EventEmitter);
Bus.prototype.subscribe = function(name) { Bus.prototype.subscribe = function(name) {
var events = this.node.db.getPublishEvents(); var events = [];
for(var i in this.node.modules) { for(var i in this.node.services) {
var mod = this.node.modules[i]; var service = this.node.services[i];
events = events.concat(mod.getPublishEvents()); events = events.concat(service.getPublishEvents());
} }
for (var j = 0; j < events.length; j++) { for (var j = 0; j < events.length; j++) {
@ -29,11 +29,11 @@ Bus.prototype.subscribe = function(name) {
}; };
Bus.prototype.unsubscribe = function(name) { Bus.prototype.unsubscribe = function(name) {
var events = this.node.db.getPublishEvents(); var events = [];
for(var i in this.node.modules) { for(var i in this.node.services) {
var mod = this.node.modules[i]; var service = this.node.services[i];
events = events.concat(mod.getPublishEvents()); events = events.concat(service.getPublishEvents());
} }
for (var j = 0; j < events.length; j++) { for (var j = 0; j < events.length; j++) {
@ -47,11 +47,11 @@ Bus.prototype.unsubscribe = function(name) {
}; };
Bus.prototype.close = function() { Bus.prototype.close = function() {
var events = this.node.db.getPublishEvents(); var events = [];
for(var i in this.node.modules) { for(var i in this.node.services) {
var mod = this.node.modules[i]; var service = this.node.services[i];
events = events.concat(mod.getPublishEvents()); events = events.concat(service.getPublishEvents());
} }
// Unsubscribe from all events // Unsubscribe from all events

View File

@ -9,7 +9,7 @@ var $ = bitcore.util.preconditions;
var index = require('./'); var index = require('./');
var log = index.log; var log = index.log;
var Bus = require('./bus'); var Bus = require('./bus');
var BaseModule = require('./module'); var BaseService = require('./service');
function Node(config) { function Node(config) {
if(!(this instanceof Node)) { if(!(this instanceof Node)) {
@ -19,13 +19,13 @@ function Node(config) {
var self = this; var self = this;
this.network = null; this.network = null;
this.modules = {}; this.services = {};
this._unloadedModules = []; this._unloadedServices = [];
// TODO type check the arguments of config.modules // TODO type check the arguments of config.services
if (config.modules) { if (config.services) {
$.checkArgument(Array.isArray(config.modules)); $.checkArgument(Array.isArray(config.services));
this._unloadedModules = config.modules; this._unloadedServices = config.services;
} }
$.checkState(config.datadir, 'Node config expects "datadir"'); $.checkState(config.datadir, 'Node config expects "datadir"');
@ -71,13 +71,13 @@ Node.prototype._setNetwork = function(config) {
}; };
Node.prototype.openBus = function() { Node.prototype.openBus = function() {
return new Bus({db: this.modules.db}); return new Bus({node: this});
}; };
Node.prototype.getAllAPIMethods = function() { Node.prototype.getAllAPIMethods = function() {
var methods = []; var methods = [];
for(var i in this.modules) { for(var i in this.services) {
var mod = this.modules[i]; var mod = this.services[i];
methods = methods.concat(mod.getAPIMethods()); methods = methods.concat(mod.getAPIMethods());
} }
return methods; return methods;
@ -85,8 +85,8 @@ Node.prototype.getAllAPIMethods = function() {
Node.prototype.getAllPublishEvents = function() { Node.prototype.getAllPublishEvents = function() {
var events = []; var events = [];
for (var i in this.modules) { for (var i in this.services) {
var mod = this.modules[i]; var mod = this.services[i];
events = events.concat(mod.getPublishEvents()); events = events.concat(mod.getPublishEvents());
} }
return events; return events;
@ -94,7 +94,7 @@ Node.prototype.getAllPublishEvents = function() {
Node.prototype.getServiceOrder = function() { Node.prototype.getServiceOrder = function() {
var services = this._unloadedModules; var services = this._unloadedServices;
// organize data for sorting // organize data for sorting
var names = []; var names = [];
@ -132,19 +132,19 @@ Node.prototype.getServiceOrder = function() {
return stack; return stack;
}; };
Node.prototype._instantiateModule = function(service) { Node.prototype._instantiateService = function(service) {
var self = this; var self = this;
var mod = new service.module({ var mod = new service.module({
node: this node: this
}); });
$.checkState( $.checkState(
mod instanceof BaseModule, mod instanceof BaseService,
'Unexpected module instance type for module:' + service.name 'Unexpected module instance type for service:' + service.name
); );
// include in loaded modules // include in loaded services
this.modules[service.name] = mod; this.services[service.name] = mod;
// add API methods // add API methods
var methodData = mod.getAPIMethods(); var methodData = mod.getAPIMethods();
@ -172,11 +172,11 @@ Node.prototype.start = function(callback) {
function(service, next) { function(service, next) {
log.info('Starting ' + service.name); log.info('Starting ' + service.name);
try { try {
self._instantiateModule(service); self._instantiateService(service);
} catch(err) { } catch(err) {
return callback(err); return callback(err);
} }
self.modules[service.name].start(next); self.services[service.name].start(next);
}, },
callback callback
); );
@ -194,7 +194,7 @@ Node.prototype.stop = function(callback) {
services, services,
function(service, next) { function(service, next) {
log.info('Stopping ' + service.name); log.info('Stopping ' + service.name);
self.modules[service.name].stop(next); self.services[service.name].stop(next);
}, },
callback callback
); );

View File

@ -10,10 +10,10 @@ var _ = bitcore.deps._;
/** /**
* @param {String} configFilePath - The absolute path to the configuration file * @param {String} configFilePath - The absolute path to the configuration file
* @param {String} module - The name of the module * @param {String} service - The name of the service
* @param {Function} done * @param {Function} done
*/ */
function addConfig(configFilePath, module, done) { function addConfig(configFilePath, service, done) {
$.checkState(path.isAbsolute(configFilePath), 'An absolute path is expected'); $.checkState(path.isAbsolute(configFilePath), 'An absolute path is expected');
fs.readFile(configFilePath, function(err, data) { fs.readFile(configFilePath, function(err, data) {
if (err) { if (err) {
@ -21,12 +21,12 @@ function addConfig(configFilePath, module, done) {
} }
var config = JSON.parse(data); var config = JSON.parse(data);
$.checkState( $.checkState(
Array.isArray(config.modules), Array.isArray(config.services),
'Configuration file is expected to have a modules array.' 'Configuration file is expected to have a services array.'
); );
config.modules.push(module); config.services.push(service);
config.modules = _.unique(config.modules); config.services = _.unique(config.services);
config.modules.sort(function(a, b) { config.services.sort(function(a, b) {
return a > b; return a > b;
}); });
fs.writeFile(configFilePath, JSON.stringify(config, null, 2), done); fs.writeFile(configFilePath, JSON.stringify(config, null, 2), done);
@ -35,12 +35,12 @@ function addConfig(configFilePath, module, done) {
/** /**
* @param {String} configDir - The absolute configuration directory path * @param {String} configDir - The absolute configuration directory path
* @param {String} module - The name of the module * @param {String} service - The name of the service
* @param {Function} done * @param {Function} done
*/ */
function addModule(configDir, module, done) { function addService(configDir, service, done) {
$.checkState(path.isAbsolute(configDir), 'An absolute path is expected'); $.checkState(path.isAbsolute(configDir), 'An absolute path is expected');
var npm = spawn('npm', ['install', module, '--save'], {cwd: configDir}); var npm = spawn('npm', ['install', service, '--save'], {cwd: configDir});
npm.stdout.on('data', function(data) { npm.stdout.on('data', function(data) {
process.stdout.write(data); process.stdout.write(data);
@ -52,7 +52,7 @@ function addModule(configDir, module, done) {
npm.on('close', function(code) { npm.on('close', function(code) {
if (code !== 0) { if (code !== 0) {
return done(new Error('There was an error installing module: ' + module)); return done(new Error('There was an error installing service: ' + service));
} else { } else {
return done(); return done();
} }
@ -62,7 +62,7 @@ function addModule(configDir, module, done) {
/** /**
* @param {String} options.cwd - The current working directory * @param {String} options.cwd - The current working directory
* @param {String} options.dirname - The bitcore-node configuration directory * @param {String} options.dirname - The bitcore-node configuration directory
* @param {Array} options.modules - An array of strings of module names * @param {Array} options.services - An array of strings of service names
* @param {Function} done - A callback function called when finished * @param {Function} done - A callback function called when finished
*/ */
function add(options, done) { function add(options, done) {
@ -72,10 +72,10 @@ function add(options, done) {
_.isString(options.path) && path.isAbsolute(options.path), _.isString(options.path) && path.isAbsolute(options.path),
'An absolute path is expected' 'An absolute path is expected'
); );
$.checkArgument(Array.isArray(options.modules)); $.checkArgument(Array.isArray(options.services));
var configPath = options.path; var configPath = options.path;
var modules = options.modules; var services = options.services;
var bitcoreConfigPath = path.resolve(configPath, 'bitcore-node.json'); var bitcoreConfigPath = path.resolve(configPath, 'bitcore-node.json');
var packagePath = path.resolve(configPath, 'package.json'); var packagePath = path.resolve(configPath, 'package.json');
@ -87,15 +87,15 @@ function add(options, done) {
} }
async.eachSeries( async.eachSeries(
modules, services,
function(module, next) { function(service, next) {
// npm install <module_name> --save // npm install <service_name> --save
addModule(configPath, module, function(err) { addService(configPath, service, function(err) {
if (err) { if (err) {
return next(err); return next(err);
} }
// add module to bitcore-node.json // add service to bitcore-node.json
addConfig(bitcoreConfigPath, module, next); addConfig(bitcoreConfigPath, service, next);
}); });
}, done }, done
); );

View File

@ -12,7 +12,7 @@ var fs = require('fs');
var BASE_CONFIG = { var BASE_CONFIG = {
name: 'My Node', name: 'My Node',
modules: [ services: [
'address' 'address'
], ],
datadir: './data', datadir: './data',
@ -61,7 +61,7 @@ function createBitcoinDirectory(datadir, done) {
* @param {String} configDir - The absolute path * @param {String} configDir - The absolute path
* @param {String} name - The name of the node * @param {String} name - The name of the node
* @param {String} datadir - The bitcoin database directory * @param {String} datadir - The bitcoin database directory
* @param {Boolean} isGlobal - If the configuration depends on globally installed node modules. * @param {Boolean} isGlobal - If the configuration depends on globally installed node services.
* @param {Function} done - The callback function called when finished * @param {Function} done - The callback function called when finished
*/ */
function createConfigDirectory(configDir, name, datadir, isGlobal, done) { function createConfigDirectory(configDir, name, datadir, isGlobal, done) {

View File

@ -13,7 +13,7 @@ function getDefaultConfig() {
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: ['bitcoind', 'db', 'address'] services: ['bitcoind', 'db', 'address']
} }
}; };
} }

View File

@ -15,42 +15,42 @@ var interval = false;
function start(options) { function start(options) {
/* jshint maxstatements: 100 */ /* jshint maxstatements: 100 */
var bitcoreModules = []; var services = [];
var configPath = options.path; var configPath = options.path;
var config = options.config; var config = options.config;
if (config.modules) { if (config.services) {
for (var i = 0; i < config.modules.length; i++) { for (var i = 0; i < config.services.length; i++) {
var moduleName = config.modules[i]; var serviceName = config.services[i];
var bitcoreModule; var service;
try { try {
// first try in the built-in bitcore-node modules directory // first try in the built-in bitcore-node services directory
bitcoreModule = require(path.resolve(__dirname, '../modules/' + moduleName)); service = require(path.resolve(__dirname, '../services/' + serviceName));
} catch(e) { } catch(e) {
// check if the package.json specifies a specific file to use // check if the package.json specifies a specific file to use
var modulePackage = require(moduleName + '/package.json'); var servicePackage = require(serviceName + '/package.json');
var bitcoreNodeModule = moduleName; var serviceModule = serviceName;
if (modulePackage.bitcoreNode) { if (servicePackage.bitcoreNode) {
bitcoreNodeModule = moduleName + '/' + modulePackage.bitcoreNode; serviceModule = serviceName + '/' + servicePackage.bitcoreNode;
} }
bitcoreModule = require(bitcoreNodeModule); service = require(serviceModule);
} }
// check that the module supports expected methods // check that the service supports expected methods
if (!bitcoreModule.prototype || if (!service.prototype ||
!bitcoreModule.dependencies || !service.dependencies ||
!bitcoreModule.prototype.start || !service.prototype.start ||
!bitcoreModule.prototype.stop) { !service.prototype.stop) {
throw new Error( throw new Error(
'Could not load module "' + moduleName + '" as it does not support necessary methods.' 'Could not load service "' + serviceName + '" as it does not support necessary methods.'
); );
} }
bitcoreModules.push({ services.push({
name: moduleName, name: serviceName,
module: bitcoreModule, module: service,
dependencies: bitcoreModule.dependencies dependencies: service.dependencies
}); });
} }
@ -61,15 +61,15 @@ 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);
// load the modules // load the services
fullConfig.modules = bitcoreModules; fullConfig.services = services;
var node = new BitcoreNode(fullConfig); var node = new BitcoreNode(fullConfig);
function logSyncStatus() { function logSyncStatus() {
log.info( log.info(
'Sync Status: Tip:', node.modules.db.tip.hash, 'Sync Status: Tip:', node.services.db.tip.hash,
'Height:', node.modules.db.tip.__height, 'Height:', node.services.db.tip.__height,
'Rate:', count/10, 'blocks per second' 'Rate:', count/10, 'blocks per second'
); );
} }
@ -185,7 +185,7 @@ function start(options) {
}); });
node.on('ready', function() { node.on('ready', function() {
node.modules.db.on('addblock', function(block) { node.services.db.on('addblock', function(block) {
count++; count++;
// Initialize logging if not already instantiated // Initialize logging if not already instantiated
if (!interval) { if (!interval) {

View File

@ -3,18 +3,18 @@
var util = require('util'); var util = require('util');
var EventEmitter = require('events').EventEmitter; var EventEmitter = require('events').EventEmitter;
var Module = function(options) { var Service = function(options) {
EventEmitter.call(this); EventEmitter.call(this);
this.node = options.node; this.node = options.node;
}; };
util.inherits(Module, EventEmitter); util.inherits(Service, EventEmitter);
/** /**
* Describes the dependencies that should be loaded before this module. * Describes the dependencies that should be loaded before this service.
*/ */
Module.dependencies = []; Service.dependencies = [];
/** /**
* blockHandler * blockHandler
@ -22,7 +22,7 @@ Module.dependencies = [];
* @param {Boolean} add - whether the block is being added or removed * @param {Boolean} add - whether the block is being added or removed
* @param {Function} callback - call with the leveldb database operations to perform * @param {Function} callback - call with the leveldb database operations to perform
*/ */
Module.prototype.blockHandler = function(block, add, callback) { Service.prototype.blockHandler = function(block, add, callback) {
// implement in the child class // implement in the child class
setImmediate(callback); setImmediate(callback);
}; };
@ -31,7 +31,7 @@ Module.prototype.blockHandler = function(block, add, callback) {
* the bus events available for subscription * the bus events available for subscription
* @return {Array} an array of event info * @return {Array} an array of event info
*/ */
Module.prototype.getPublishEvents = function() { Service.prototype.getPublishEvents = function() {
// Example: // Example:
// return [ // return [
// ['eventname', this, this.subscribeEvent, this.unsubscribeEvent], // ['eventname', this, this.subscribeEvent, this.unsubscribeEvent],
@ -43,7 +43,7 @@ Module.prototype.getPublishEvents = function() {
* the API methods to expose * the API methods to expose
* @return {Array} return array of methods * @return {Array} return array of methods
*/ */
Module.prototype.getAPIMethods = function() { Service.prototype.getAPIMethods = function() {
// Example: // Example:
// return [ // return [
// ['getData', this, this.getData, 1] // ['getData', this, this.getData, 1]
@ -53,16 +53,16 @@ Module.prototype.getAPIMethods = function() {
}; };
// Example: // Example:
// Module.prototype.getData = function(arg1, callback) { // Service.prototype.getData = function(arg1, callback) {
// //
// }; // };
Module.prototype.start = function(done) { Service.prototype.start = function(done) {
setImmediate(done); setImmediate(done);
}; };
Module.prototype.stop = function(done) { Service.prototype.stop = function(done) {
setImmediate(done); setImmediate(done);
}; };
module.exports = Module; module.exports = Service;

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
var BaseModule = require('../module'); var BaseService = require('../service');
var inherits = require('util').inherits; var inherits = require('util').inherits;
var async = require('async'); var async = require('async');
var index = require('../'); var index = require('../');
@ -14,30 +14,30 @@ var EventEmitter = require('events').EventEmitter;
var PublicKey = bitcore.PublicKey; var PublicKey = bitcore.PublicKey;
var Address = bitcore.Address; var Address = bitcore.Address;
var AddressModule = function(options) { var AddressService = function(options) {
BaseModule.call(this, options); BaseService.call(this, options);
this.subscriptions = {}; this.subscriptions = {};
this.subscriptions['address/transaction'] = {}; this.subscriptions['address/transaction'] = {};
this.subscriptions['address/balance'] = {}; this.subscriptions['address/balance'] = {};
this.node.modules.bitcoind.on('tx', this.transactionHandler.bind(this)); this.node.services.bitcoind.on('tx', this.transactionHandler.bind(this));
}; };
inherits(AddressModule, BaseModule); inherits(AddressService, BaseService);
AddressModule.dependencies = [ AddressService.dependencies = [
'bitcoind', 'bitcoind',
'db' 'db'
]; ];
AddressModule.PREFIXES = { AddressService.PREFIXES = {
OUTPUTS: 'outs', OUTPUTS: 'outs',
SPENTS: 'sp' SPENTS: 'sp'
}; };
AddressModule.prototype.getAPIMethods = function() { AddressService.prototype.getAPIMethods = function() {
return [ return [
['getBalance', this, this.getBalance, 2], ['getBalance', this, this.getBalance, 2],
['getOutputs', this, this.getOutputs, 2], ['getOutputs', this, this.getOutputs, 2],
@ -47,7 +47,7 @@ AddressModule.prototype.getAPIMethods = function() {
]; ];
}; };
AddressModule.prototype.getPublishEvents = function() { AddressService.prototype.getPublishEvents = function() {
return [ return [
{ {
name: 'address/transaction', name: 'address/transaction',
@ -73,7 +73,7 @@ AddressModule.prototype.getPublishEvents = function() {
* @param {Number} outputIndex - The index of the output in the transaction * @param {Number} outputIndex - The index of the output in the transaction
* @param {Boolean} rejected - If the transaction was rejected by the mempool * @param {Boolean} rejected - If the transaction was rejected by the mempool
*/ */
AddressModule.prototype.transactionOutputHandler = function(messages, tx, outputIndex, rejected) { AddressService.prototype.transactionOutputHandler = function(messages, tx, outputIndex, rejected) {
var script = tx.outputs[outputIndex].script; var script = tx.outputs[outputIndex].script;
// If the script is invalid skip // If the script is invalid skip
@ -112,7 +112,7 @@ AddressModule.prototype.transactionOutputHandler = function(messages, tx, output
* @param {Boolean} txInfo.mempool - If the transaction was accepted in the mempool * @param {Boolean} txInfo.mempool - If the transaction was accepted in the mempool
* @param {String} txInfo.hash - The hash of the transaction * @param {String} txInfo.hash - The hash of the transaction
*/ */
AddressModule.prototype.transactionHandler = function(txInfo) { AddressService.prototype.transactionHandler = function(txInfo) {
// Basic transaction format is handled by the daemon // Basic transaction format is handled by the daemon
// and we can safely assume the buffer is properly formatted. // and we can safely assume the buffer is properly formatted.
@ -130,7 +130,7 @@ AddressModule.prototype.transactionHandler = function(txInfo) {
} }
}; };
AddressModule.prototype.blockHandler = function(block, addOutput, callback) { AddressService.prototype.blockHandler = function(block, addOutput, callback) {
var txs = block.transactions; var txs = block.transactions;
var action = 'put'; var action = 'put';
@ -178,7 +178,7 @@ AddressModule.prototype.blockHandler = function(block, addOutput, callback) {
var addressStr = address.toString(); var addressStr = address.toString();
var scriptHex = output._scriptBuffer.toString('hex'); var scriptHex = output._scriptBuffer.toString('hex');
var key = [AddressModule.PREFIXES.OUTPUTS, addressStr, timestamp, txid, outputIndex].join('-'); var key = [AddressService.PREFIXES.OUTPUTS, addressStr, timestamp, txid, outputIndex].join('-');
var value = [output.satoshis, scriptHex, height].join(':'); var value = [output.satoshis, scriptHex, height].join(':');
operations.push({ operations.push({
@ -217,7 +217,7 @@ AddressModule.prototype.blockHandler = function(block, addOutput, callback) {
var input = inputs[k].toObject(); var input = inputs[k].toObject();
operations.push({ operations.push({
type: action, type: action,
key: [AddressModule.PREFIXES.SPENTS, input.prevTxId, input.outputIndex].join('-'), key: [AddressService.PREFIXES.SPENTS, input.prevTxId, input.outputIndex].join('-'),
value: [txid, k].join(':') value: [txid, k].join(':')
}); });
} }
@ -238,7 +238,7 @@ AddressModule.prototype.blockHandler = function(block, addOutput, callback) {
* @param {Number} [obj.height] - The height of the block the transaction was included * @param {Number} [obj.height] - The height of the block the transaction was included
* @param {Boolean} [obj.rejected] - If the transaction was not accepted in the mempool * @param {Boolean} [obj.rejected] - If the transaction was not accepted in the mempool
*/ */
AddressModule.prototype.transactionEventHandler = function(obj) { AddressService.prototype.transactionEventHandler = function(obj) {
if(this.subscriptions['address/transaction'][obj.address]) { if(this.subscriptions['address/transaction'][obj.address]) {
var emitters = this.subscriptions['address/transaction'][obj.address]; var emitters = this.subscriptions['address/transaction'][obj.address];
for(var i = 0; i < emitters.length; i++) { for(var i = 0; i < emitters.length; i++) {
@ -247,7 +247,7 @@ AddressModule.prototype.transactionEventHandler = function(obj) {
} }
}; };
AddressModule.prototype.balanceEventHandler = function(block, address) { AddressService.prototype.balanceEventHandler = function(block, address) {
if(this.subscriptions['address/balance'][address]) { if(this.subscriptions['address/balance'][address]) {
var emitters = this.subscriptions['address/balance'][address]; var emitters = this.subscriptions['address/balance'][address];
this.getBalance(address, true, function(err, balance) { this.getBalance(address, true, function(err, balance) {
@ -262,7 +262,7 @@ AddressModule.prototype.balanceEventHandler = function(block, address) {
} }
}; };
AddressModule.prototype.subscribe = function(name, emitter, addresses) { AddressService.prototype.subscribe = function(name, emitter, addresses) {
$.checkArgument(emitter instanceof EventEmitter, 'First argument is expected to be an EventEmitter'); $.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'); $.checkArgument(Array.isArray(addresses), 'Second argument is expected to be an Array of addresses');
@ -274,7 +274,7 @@ AddressModule.prototype.subscribe = function(name, emitter, addresses) {
} }
}; };
AddressModule.prototype.unsubscribe = function(name, emitter, addresses) { AddressService.prototype.unsubscribe = function(name, emitter, addresses) {
$.checkArgument(emitter instanceof EventEmitter, 'First argument is expected to be an EventEmitter'); $.checkArgument(emitter instanceof EventEmitter, 'First argument is expected to be an EventEmitter');
$.checkArgument(Array.isArray(addresses) || _.isUndefined(addresses), 'Second argument is expected to be an Array of addresses or undefined'); $.checkArgument(Array.isArray(addresses) || _.isUndefined(addresses), 'Second argument is expected to be an Array of addresses or undefined');
@ -293,7 +293,7 @@ AddressModule.prototype.unsubscribe = function(name, emitter, addresses) {
} }
}; };
AddressModule.prototype.unsubscribeAll = function(name, emitter) { AddressService.prototype.unsubscribeAll = function(name, emitter) {
$.checkArgument(emitter instanceof EventEmitter, 'First argument is expected to be an EventEmitter'); $.checkArgument(emitter instanceof EventEmitter, 'First argument is expected to be an EventEmitter');
for(var address in this.subscriptions[name]) { for(var address in this.subscriptions[name]) {
@ -305,7 +305,7 @@ AddressModule.prototype.unsubscribeAll = function(name, emitter) {
} }
}; };
AddressModule.prototype.getBalance = function(address, queryMempool, callback) { AddressService.prototype.getBalance = function(address, queryMempool, callback) {
this.getUnspentOutputs(address, queryMempool, function(err, outputs) { this.getUnspentOutputs(address, queryMempool, function(err, outputs) {
if(err) { if(err) {
return callback(err); return callback(err);
@ -323,13 +323,13 @@ AddressModule.prototype.getBalance = function(address, queryMempool, callback) {
}); });
}; };
AddressModule.prototype.getOutputs = function(addressStr, queryMempool, callback) { AddressService.prototype.getOutputs = function(addressStr, queryMempool, callback) {
var self = this; var self = this;
var outputs = []; var outputs = [];
var key = [AddressModule.PREFIXES.OUTPUTS, addressStr].join('-'); var key = [AddressService.PREFIXES.OUTPUTS, addressStr].join('-');
var stream = this.node.modules.db.store.createReadStream({ var stream = this.node.services.db.store.createReadStream({
start: key, start: key,
end: key + '~' end: key + '~'
}); });
@ -347,7 +347,7 @@ AddressModule.prototype.getOutputs = function(addressStr, queryMempool, callback
satoshis: Number(value[0]), satoshis: Number(value[0]),
script: value[1], script: value[1],
blockHeight: Number(value[2]), blockHeight: Number(value[2]),
confirmations: self.node.modules.db.tip.__height - Number(value[2]) + 1 confirmations: self.node.services.db.tip.__height - Number(value[2]) + 1
}; };
outputs.push(output); outputs.push(output);
@ -368,7 +368,7 @@ AddressModule.prototype.getOutputs = function(addressStr, queryMempool, callback
} }
if(queryMempool) { if(queryMempool) {
outputs = outputs.concat(self.node.modules.bitcoind.getMempoolOutputs(addressStr)); outputs = outputs.concat(self.node.services.bitcoind.getMempoolOutputs(addressStr));
} }
callback(null, outputs); callback(null, outputs);
@ -378,7 +378,7 @@ AddressModule.prototype.getOutputs = function(addressStr, queryMempool, callback
}; };
AddressModule.prototype.getUnspentOutputs = function(addresses, queryMempool, callback) { AddressService.prototype.getUnspentOutputs = function(addresses, queryMempool, callback) {
var self = this; var self = this;
if(!Array.isArray(addresses)) { if(!Array.isArray(addresses)) {
@ -403,7 +403,7 @@ AddressModule.prototype.getUnspentOutputs = function(addresses, queryMempool, ca
}); });
}; };
AddressModule.prototype.getUnspentOutputsForAddress = function(address, queryMempool, callback) { AddressService.prototype.getUnspentOutputsForAddress = function(address, queryMempool, callback) {
var self = this; var self = this;
@ -424,26 +424,26 @@ AddressModule.prototype.getUnspentOutputsForAddress = function(address, queryMem
}); });
}; };
AddressModule.prototype.isUnspent = function(output, queryMempool, callback) { AddressService.prototype.isUnspent = function(output, queryMempool, callback) {
this.isSpent(output, queryMempool, function(spent) { this.isSpent(output, queryMempool, function(spent) {
callback(!spent); callback(!spent);
}); });
}; };
AddressModule.prototype.isSpent = function(output, queryMempool, callback) { AddressService.prototype.isSpent = function(output, queryMempool, callback) {
var self = this; var self = this;
var txid = output.prevTxId ? output.prevTxId.toString('hex') : output.txid; var txid = output.prevTxId ? output.prevTxId.toString('hex') : output.txid;
setImmediate(function() { setImmediate(function() {
callback(self.node.modules.bitcoind.isSpent(txid, output.outputIndex)); callback(self.node.services.bitcoind.isSpent(txid, output.outputIndex));
}); });
}; };
AddressModule.prototype.getSpendInfoForOutput = function(txid, outputIndex, callback) { AddressService.prototype.getSpendInfoForOutput = function(txid, outputIndex, callback) {
var self = this; var self = this;
var key = [AddressModule.PREFIXES.SPENTS, txid, outputIndex].join('-'); var key = [AddressService.PREFIXES.SPENTS, txid, outputIndex].join('-');
this.node.modules.db.store.get(key, function(err, value) { this.node.services.db.store.get(key, function(err, value) {
if(err) { if(err) {
return callback(err); return callback(err);
} }
@ -459,7 +459,7 @@ AddressModule.prototype.getSpendInfoForOutput = function(txid, outputIndex, call
}); });
}; };
AddressModule.prototype.getAddressHistory = function(addresses, queryMempool, callback) { AddressService.prototype.getAddressHistory = function(addresses, queryMempool, callback) {
var self = this; var self = this;
if(!Array.isArray(addresses)) { if(!Array.isArray(addresses)) {
@ -482,7 +482,7 @@ AddressModule.prototype.getAddressHistory = function(addresses, queryMempool, ca
}); });
}; };
AddressModule.prototype.getAddressHistoryForAddress = function(address, queryMempool, callback) { AddressService.prototype.getAddressHistoryForAddress = function(address, queryMempool, callback) {
var self = this; var self = this;
var txinfos = {}; var txinfos = {};
@ -492,19 +492,19 @@ AddressModule.prototype.getAddressHistoryForAddress = function(address, queryMem
return callback(null, txinfos[txid]); return callback(null, txinfos[txid]);
} }
self.node.modules.db.getTransactionWithBlockInfo(txid, queryMempool, function(err, transaction) { self.node.services.db.getTransactionWithBlockInfo(txid, queryMempool, function(err, transaction) {
if(err) { if(err) {
return callback(err); return callback(err);
} }
transaction.populateInputs(self.node.modules.db, [], function(err) { transaction.populateInputs(self.node.services.db, [], function(err) {
if(err) { if(err) {
return callback(err); return callback(err);
} }
var confirmations = 0; var confirmations = 0;
if(transaction.__height >= 0) { if(transaction.__height >= 0) {
confirmations = self.node.modules.db.tip.__height - transaction.__height; confirmations = self.node.services.db.tip.__height - transaction.__height;
} }
txinfos[transaction.hash] = { txinfos[transaction.hash] = {
@ -581,4 +581,4 @@ AddressModule.prototype.getAddressHistoryForAddress = function(address, queryMem
}); });
}; };
module.exports = AddressModule; module.exports = AddressService;

View File

@ -8,8 +8,7 @@ var bitcore = require('bitcore');
var $ = bitcore.util.preconditions; var $ = bitcore.util.preconditions;
var index = require('../'); var index = require('../');
var log = index.log; var log = index.log;
var Module = require('../module'); var Service = require('../service');
/** /**
* Provides an interface to native bindings to Bitcoin Core * Provides an interface to native bindings to Bitcoin Core
@ -24,7 +23,7 @@ function Bitcoin(options) {
var self = this; var self = this;
Module.call(this, options); Service.call(this, options);
if (Object.keys(this.instances).length) { if (Object.keys(this.instances).length) {
throw new Error('Bitcoin cannot be instantiated more than once.'); throw new Error('Bitcoin cannot be instantiated more than once.');
@ -38,7 +37,7 @@ function Bitcoin(options) {
} }
util.inherits(Bitcoin, Module); util.inherits(Bitcoin, Service);
Bitcoin.dependencies = []; Bitcoin.dependencies = [];

View File

@ -15,13 +15,13 @@ 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 Module = require('../module'); var Service = require('../service');
var utils = require('../utils'); var utils = require('../utils');
var MAX_STACK_DEPTH = 1000; var MAX_STACK_DEPTH = 1000;
/** /**
* Represents the current state of the bitcoin blockchain. Other modules * Represents the current state of the bitcoin blockchain. Other services
* can extend the data that is indexed by implementing a `blockHandler` method. * can extend the data that is indexed by implementing a `blockHandler` method.
* *
* @param {Object} options * @param {Object} options
@ -38,7 +38,7 @@ function DB(options) {
options = {}; options = {};
} }
Module.call(this, options); Service.call(this, options);
this.tip = null; this.tip = null;
this.genesis = null; this.genesis = null;
@ -66,7 +66,7 @@ function DB(options) {
}; };
} }
util.inherits(DB, Module); util.inherits(DB, Service);
DB.dependencies = ['bitcoind']; DB.dependencies = ['bitcoind'];
@ -90,17 +90,17 @@ DB.prototype.start = function(callback) {
mkdirp.sync(this.dataPath); mkdirp.sync(this.dataPath);
} }
this.genesis = Block.fromBuffer(this.node.modules.bitcoind.genesisBuffer); this.genesis = Block.fromBuffer(this.node.services.bitcoind.genesisBuffer);
this.store = levelup(this.dataPath, { db: this.levelupStore }); this.store = levelup(this.dataPath, { db: this.levelupStore });
this.node.modules.bitcoind.on('tx', this.transactionHandler.bind(this)); this.node.services.bitcoind.on('tx', this.transactionHandler.bind(this));
this.once('ready', function() { this.once('ready', function() {
log.info('Bitcoin Database Ready'); log.info('Bitcoin Database Ready');
// Notify that there is a new tip // Notify that there is a new tip
self.node.modules.bitcoind.on('tip', function(height) { self.node.services.bitcoind.on('tip', function(height) {
if(!self.node.stopping) { if(!self.node.stopping) {
var percentage = self.node.modules.bitcoind.syncPercentage(); var percentage = self.node.services.bitcoind.syncPercentage();
log.info('Bitcoin Core Daemon New Height:', height, 'Percentage:', percentage); log.info('Bitcoin Core Daemon New Height:', height, 'Percentage:', percentage);
self.sync(); self.sync();
} }
@ -189,7 +189,7 @@ DB.prototype.getAPIMethods = function() {
}; };
DB.prototype.getBlock = function(hash, callback) { DB.prototype.getBlock = function(hash, callback) {
this.node.modules.bitcoind.getBlock(hash, function(err, blockData) { this.node.services.bitcoind.getBlock(hash, function(err, blockData) {
if (err) { if (err) {
return callback(err); return callback(err);
} }
@ -198,7 +198,7 @@ DB.prototype.getBlock = function(hash, callback) {
}; };
DB.prototype.getTransaction = function(txid, queryMempool, callback) { DB.prototype.getTransaction = function(txid, queryMempool, callback) {
this.node.modules.bitcoind.getTransaction(txid, queryMempool, function(err, txBuffer) { this.node.services.bitcoind.getTransaction(txid, queryMempool, function(err, txBuffer) {
if (err) { if (err) {
return callback(err); return callback(err);
} }
@ -211,7 +211,7 @@ DB.prototype.getTransaction = function(txid, queryMempool, callback) {
}; };
DB.prototype.getTransactionWithBlockInfo = function(txid, queryMempool, callback) { DB.prototype.getTransactionWithBlockInfo = function(txid, queryMempool, callback) {
this.node.modules.bitcoind.getTransactionWithBlockInfo(txid, queryMempool, function(err, obj) { this.node.services.bitcoind.getTransactionWithBlockInfo(txid, queryMempool, function(err, obj) {
if (err) { if (err) {
return callback(err); return callback(err);
} }
@ -231,7 +231,7 @@ DB.prototype.sendTransaction = function(tx, callback) {
$.checkArgument(typeof tx === 'string', 'Argument must be a hex string or Transaction'); $.checkArgument(typeof tx === 'string', 'Argument must be a hex string or Transaction');
try { try {
var txid = this.node.modules.bitcoind.sendTransaction(tx); var txid = this.node.services.bitcoind.sendTransaction(tx);
return callback(null, txid); return callback(null, txid);
} catch(err) { } catch(err) {
return callback(err); return callback(err);
@ -241,7 +241,7 @@ DB.prototype.sendTransaction = function(tx, callback) {
DB.prototype.estimateFee = function(blocks, callback) { DB.prototype.estimateFee = function(blocks, callback) {
var self = this; var self = this;
setImmediate(function() { setImmediate(function() {
callback(null, self.node.modules.bitcoind.estimateFee(blocks)); callback(null, self.node.services.bitcoind.estimateFee(blocks));
}); });
}; };
@ -279,7 +279,7 @@ DB.prototype.unsubscribe = function(name, emitter) {
* @param {Function} callback * @param {Function} callback
*/ */
DB.prototype.getPrevHash = function(blockHash, callback) { DB.prototype.getPrevHash = function(blockHash, callback) {
var blockIndex = this.node.modules.bitcoind.getBlockIndex(blockHash); var blockIndex = this.node.services.bitcoind.getBlockIndex(blockHash);
setImmediate(function() { setImmediate(function() {
if (blockIndex) { if (blockIndex) {
callback(null, blockIndex.prevHash); callback(null, blockIndex.prevHash);
@ -364,7 +364,7 @@ DB.prototype.disconnectBlock = function(block, callback) {
}; };
/** /**
* Will collect all database operations for a block from other modules * Will collect all database operations for a block from other services
* and save to the database. * and save to the database.
* @param {Block} block - The bitcore block * @param {Block} block - The bitcore block
* @param {Boolean} add - If the block is being added/connected or removed/disconnected * @param {Boolean} add - If the block is being added/connected or removed/disconnected
@ -380,7 +380,7 @@ DB.prototype.runAllBlockHandlers = function(block, add, callback) {
} }
async.eachSeries( async.eachSeries(
this.node.modules, this.node.services,
function(mod, next) { function(mod, next) {
mod.blockHandler.call(mod, block, add, function(err, ops) { mod.blockHandler.call(mod, block, add, function(err, ops) {
if (err) { if (err) {
@ -501,7 +501,7 @@ DB.prototype.findCommonAncestor = function(block, done) {
// and thus don't need to find the entire chain of hashes. // and thus don't need to find the entire chain of hashes.
while(ancestorHash && !currentHashesMap[ancestorHash]) { while(ancestorHash && !currentHashesMap[ancestorHash]) {
var blockIndex = self.node.modules.bitcoind.getBlockIndex(ancestorHash); var blockIndex = self.node.services.bitcoind.getBlockIndex(ancestorHash);
ancestorHash = blockIndex ? blockIndex.prevHash : null; ancestorHash = blockIndex ? blockIndex.prevHash : null;
} }
@ -595,9 +595,9 @@ DB.prototype.sync = function() {
async.whilst(function() { async.whilst(function() {
height = self.tip.__height; height = self.tip.__height;
return height < self.node.modules.bitcoind.height && !self.node.stopping; return height < self.node.services.bitcoind.height && !self.node.stopping;
}, function(done) { }, function(done) {
self.node.modules.bitcoind.getBlock(height + 1, function(err, blockBuffer) { self.node.services.bitcoind.getBlock(height + 1, function(err, blockBuffer) {
if (err) { if (err) {
return done(err); return done(err);
} }
@ -659,7 +659,7 @@ DB.prototype.sync = function() {
self.lastSavedMetadataThreshold = 0; self.lastSavedMetadataThreshold = 0;
// If bitcoind is completely synced // If bitcoind is completely synced
if (self.node.modules.bitcoind.isSynced()) { if (self.node.services.bitcoind.isSynced()) {
self.node.emit('synced'); self.node.emit('synced');
} }

View File

@ -7,28 +7,26 @@ var Bus = require('../lib/bus');
describe('Bus', function() { describe('Bus', function() {
describe('#subscribe', function() { describe('#subscribe', function() {
it('will call db and modules subscribe function with the correct arguments', function() { it('will call db and services subscribe function with the correct arguments', function() {
var subscribeDb = sinon.spy(); var subscribeDb = sinon.spy();
var subscribeModule = sinon.spy(); var subscribeService = sinon.spy();
var db = { var node = {
services: {
db: {
getPublishEvents: sinon.stub().returns([ getPublishEvents: sinon.stub().returns([
{ {
name: 'dbtest', name: 'dbtest',
scope: this, scope: this,
subscribe: subscribeDb subscribe: subscribeDb
} }
] ])
) },
}; service1: {
var node = {
db: db,
modules: {
module1: {
getPublishEvents: sinon.stub().returns([ getPublishEvents: sinon.stub().returns([
{ {
name: 'test', name: 'test',
scope: this, scope: this,
subscribe: subscribeModule, subscribe: subscribeService,
} }
]) ])
} }
@ -37,42 +35,40 @@ describe('Bus', function() {
var bus = new Bus({node: node}); var bus = new Bus({node: node});
bus.subscribe('dbtest', 'a', 'b', 'c'); bus.subscribe('dbtest', 'a', 'b', 'c');
bus.subscribe('test', 'a', 'b', 'c'); bus.subscribe('test', 'a', 'b', 'c');
subscribeModule.callCount.should.equal(1); subscribeService.callCount.should.equal(1);
subscribeDb.callCount.should.equal(1); subscribeDb.callCount.should.equal(1);
subscribeDb.args[0][0].should.equal(bus); subscribeDb.args[0][0].should.equal(bus);
subscribeDb.args[0][1].should.equal('a'); subscribeDb.args[0][1].should.equal('a');
subscribeDb.args[0][2].should.equal('b'); subscribeDb.args[0][2].should.equal('b');
subscribeDb.args[0][3].should.equal('c'); subscribeDb.args[0][3].should.equal('c');
subscribeModule.args[0][0].should.equal(bus); subscribeService.args[0][0].should.equal(bus);
subscribeModule.args[0][1].should.equal('a'); subscribeService.args[0][1].should.equal('a');
subscribeModule.args[0][2].should.equal('b'); subscribeService.args[0][2].should.equal('b');
subscribeModule.args[0][3].should.equal('c'); subscribeService.args[0][3].should.equal('c');
}); });
}); });
describe('#unsubscribe', function() { describe('#unsubscribe', function() {
it('will call db and modules unsubscribe function with the correct arguments', function() { it('will call db and services unsubscribe function with the correct arguments', function() {
var unsubscribeDb = sinon.spy(); var unsubscribeDb = sinon.spy();
var unsubscribeModule = sinon.spy(); var unsubscribeService = sinon.spy();
var db = { var node = {
services: {
db: {
getPublishEvents: sinon.stub().returns([ getPublishEvents: sinon.stub().returns([
{ {
name: 'dbtest', name: 'dbtest',
scope: this, scope: this,
unsubscribe: unsubscribeDb unsubscribe: unsubscribeDb
} }
] ])
) },
}; service1: {
var node = {
db: db,
modules: {
module1: {
getPublishEvents: sinon.stub().returns([ getPublishEvents: sinon.stub().returns([
{ {
name: 'test', name: 'test',
scope: this, scope: this,
unsubscribe: unsubscribeModule, unsubscribe: unsubscribeService,
} }
]) ])
} }
@ -81,42 +77,40 @@ describe('Bus', function() {
var bus = new Bus({node: node}); var bus = new Bus({node: node});
bus.unsubscribe('dbtest', 'a', 'b', 'c'); bus.unsubscribe('dbtest', 'a', 'b', 'c');
bus.unsubscribe('test', 'a', 'b', 'c'); bus.unsubscribe('test', 'a', 'b', 'c');
unsubscribeModule.callCount.should.equal(1); unsubscribeService.callCount.should.equal(1);
unsubscribeDb.callCount.should.equal(1); unsubscribeDb.callCount.should.equal(1);
unsubscribeDb.args[0][0].should.equal(bus); unsubscribeDb.args[0][0].should.equal(bus);
unsubscribeDb.args[0][1].should.equal('a'); unsubscribeDb.args[0][1].should.equal('a');
unsubscribeDb.args[0][2].should.equal('b'); unsubscribeDb.args[0][2].should.equal('b');
unsubscribeDb.args[0][3].should.equal('c'); unsubscribeDb.args[0][3].should.equal('c');
unsubscribeModule.args[0][0].should.equal(bus); unsubscribeService.args[0][0].should.equal(bus);
unsubscribeModule.args[0][1].should.equal('a'); unsubscribeService.args[0][1].should.equal('a');
unsubscribeModule.args[0][2].should.equal('b'); unsubscribeService.args[0][2].should.equal('b');
unsubscribeModule.args[0][3].should.equal('c'); unsubscribeService.args[0][3].should.equal('c');
}); });
}); });
describe('#close', function() { describe('#close', function() {
it('will unsubscribe from all events', function() { it('will unsubscribe from all events', function() {
var unsubscribeDb = sinon.spy(); var unsubscribeDb = sinon.spy();
var unsubscribeModule = sinon.spy(); var unsubscribeService = sinon.spy();
var db = { var node = {
services: {
db: {
getPublishEvents: sinon.stub().returns([ getPublishEvents: sinon.stub().returns([
{ {
name: 'dbtest', name: 'dbtest',
scope: this, scope: this,
unsubscribe: unsubscribeDb unsubscribe: unsubscribeDb
} }
] ])
) },
}; service1: {
var node = {
db: db,
modules: {
module1: {
getPublishEvents: sinon.stub().returns([ getPublishEvents: sinon.stub().returns([
{ {
name: 'test', name: 'test',
scope: this, scope: this,
unsubscribe: unsubscribeModule unsubscribe: unsubscribeService
} }
]) ])
} }
@ -126,11 +120,11 @@ describe('Bus', function() {
bus.close(); bus.close();
unsubscribeDb.callCount.should.equal(1); unsubscribeDb.callCount.should.equal(1);
unsubscribeModule.callCount.should.equal(1); unsubscribeService.callCount.should.equal(1);
unsubscribeDb.args[0].length.should.equal(1); unsubscribeDb.args[0].length.should.equal(1);
unsubscribeDb.args[0][0].should.equal(bus); unsubscribeDb.args[0][0].should.equal(bus);
unsubscribeModule.args[0].length.should.equal(1); unsubscribeService.args[0].length.should.equal(1);
unsubscribeModule.args[0][0].should.equal(bus); unsubscribeService.args[0][0].should.equal(bus);
}); });
}); });

View File

@ -6,7 +6,7 @@ var bitcore = require('bitcore');
var Networks = bitcore.Networks; var Networks = bitcore.Networks;
var proxyquire = require('proxyquire'); var proxyquire = require('proxyquire');
var util = require('util'); var util = require('util');
var BaseModule = require('../lib/module'); var BaseService = require('../lib/service');
describe('Bitcore Node', function() { describe('Bitcore Node', function() {
@ -47,18 +47,18 @@ describe('Bitcore Node', function() {
}); });
describe('@constructor', function() { describe('@constructor', function() {
var TestModule; var TestService;
before(function() { before(function() {
TestModule = function TestModule() {}; TestService = function TestService() {};
util.inherits(TestModule, BaseModule); util.inherits(TestService, BaseService);
}); });
it('will set properties', function() { it('will set properties', function() {
var config = { var config = {
datadir: 'testdir', datadir: 'testdir',
modules: [ services: [
{ {
name: 'test1', name: 'test1',
module: TestModule module: TestService
} }
], ],
}; };
@ -66,19 +66,19 @@ describe('Bitcore Node', function() {
TestNode.prototype.start = sinon.spy(); TestNode.prototype.start = sinon.spy();
var node = new TestNode(config); var node = new TestNode(config);
TestNode.prototype.start.callCount.should.equal(1); TestNode.prototype.start.callCount.should.equal(1);
node._unloadedModules.length.should.equal(1); node._unloadedServices.length.should.equal(1);
node._unloadedModules[0].name.should.equal('test1'); node._unloadedServices[0].name.should.equal('test1');
node._unloadedModules[0].module.should.equal(TestModule); node._unloadedServices[0].module.should.equal(TestService);
node.network.should.equal(Networks.defaultNetwork); node.network.should.equal(Networks.defaultNetwork);
}); });
it('will set network to testnet', function() { it('will set network to testnet', function() {
var config = { var config = {
network: 'testnet', network: 'testnet',
datadir: 'testdir', datadir: 'testdir',
modules: [ services: [
{ {
name: 'test1', name: 'test1',
module: TestModule module: TestService
} }
], ],
}; };
@ -91,10 +91,10 @@ describe('Bitcore Node', function() {
var config = { var config = {
network: 'regtest', network: 'regtest',
datadir: 'testdir', datadir: 'testdir',
modules: [ services: [
{ {
name: 'test1', name: 'test1',
module: TestModule module: TestService
} }
], ],
}; };
@ -108,10 +108,10 @@ describe('Bitcore Node', function() {
it('should emit error if an error occurred starting services', function(done) { it('should emit error if an error occurred starting services', function(done) {
var config = { var config = {
datadir: 'testdir', datadir: 'testdir',
modules: [ services: [
{ {
name: 'test1', name: 'test1',
module: TestModule module: TestService
} }
], ],
}; };
@ -139,16 +139,16 @@ describe('Bitcore Node', function() {
}); });
describe('#getAllAPIMethods', function() { describe('#getAllAPIMethods', function() {
it('should return db methods and modules methods', function() { it('should return db methods and service methods', function() {
var node = new Node(baseConfig); var node = new Node(baseConfig);
node.modules = { node.services = {
db: { db: {
getAPIMethods: sinon.stub().returns(['db1', 'db2']), getAPIMethods: sinon.stub().returns(['db1', 'db2']),
}, },
module1: { service1: {
getAPIMethods: sinon.stub().returns(['mda1', 'mda2']) getAPIMethods: sinon.stub().returns(['mda1', 'mda2'])
}, },
module2: { service2: {
getAPIMethods: sinon.stub().returns(['mdb1', 'mdb2']) getAPIMethods: sinon.stub().returns(['mdb1', 'mdb2'])
} }
}; };
@ -159,16 +159,16 @@ describe('Bitcore Node', function() {
}); });
describe('#getAllPublishEvents', function() { describe('#getAllPublishEvents', function() {
it('should return modules publish events', function() { it('should return services publish events', function() {
var node = new Node(baseConfig); var node = new Node(baseConfig);
node.modules = { node.services = {
db: { db: {
getPublishEvents: sinon.stub().returns(['db1', 'db2']), getPublishEvents: sinon.stub().returns(['db1', 'db2']),
}, },
module1: { service1: {
getPublishEvents: sinon.stub().returns(['mda1', 'mda2']) getPublishEvents: sinon.stub().returns(['mda1', 'mda2'])
}, },
module2: { service2: {
getPublishEvents: sinon.stub().returns(['mdb1', 'mdb2']) getPublishEvents: sinon.stub().returns(['mdb1', 'mdb2'])
} }
}; };
@ -180,7 +180,7 @@ describe('Bitcore Node', function() {
describe('#getServiceOrder', function() { describe('#getServiceOrder', 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(baseConfig); var node = new Node(baseConfig);
node._unloadedModules = [ node._unloadedServices = [
{ {
name: 'chain', name: 'chain',
dependencies: ['db'] dependencies: ['db']
@ -206,46 +206,46 @@ describe('Bitcore Node', function() {
}); });
}); });
describe('#_instantiateModule', function() { describe('#_instantiateService', function() {
it('will instantiate an instance and load api methods', function() { it('will instantiate an instance and load api methods', function() {
var node = new Node(baseConfig); var node = new Node(baseConfig);
function TestModule() {} function TestService() {}
util.inherits(TestModule, BaseModule); util.inherits(TestService, BaseService);
TestModule.prototype.getData = function() {}; TestService.prototype.getData = function() {};
TestModule.prototype.getAPIMethods = function() { TestService.prototype.getAPIMethods = function() {
return [ return [
['getData', this, this.getData, 1] ['getData', this, this.getData, 1]
]; ];
}; };
var service = { var service = {
name: 'testmodule', name: 'testservice',
module: TestModule module: TestService
}; };
node._instantiateModule(service); node._instantiateService(service);
should.exist(node.modules.testmodule); should.exist(node.services.testservice);
should.exist(node.getData); should.exist(node.getData);
}); });
}); });
describe('#start', function() { describe('#start', function() {
it('will call start for each module', function(done) { it('will call start for each service', function(done) {
var node = new Node(baseConfig); var node = new Node(baseConfig);
function TestModule() {} function TestService() {}
util.inherits(TestModule, BaseModule); util.inherits(TestService, BaseService);
TestModule.prototype.start = sinon.stub().callsArg(0); TestService.prototype.start = sinon.stub().callsArg(0);
TestModule.prototype.getData = function() {}; TestService.prototype.getData = function() {};
TestModule.prototype.getAPIMethods = function() { TestService.prototype.getAPIMethods = function() {
return [ return [
['getData', this, this.getData, 1] ['getData', this, this.getData, 1]
]; ];
}; };
function TestModule2() {} function TestService2() {}
util.inherits(TestModule2, BaseModule); util.inherits(TestService2, BaseService);
TestModule2.prototype.start = sinon.stub().callsArg(0); TestService2.prototype.start = sinon.stub().callsArg(0);
TestModule2.prototype.getData2 = function() {}; TestService2.prototype.getData2 = function() {};
TestModule2.prototype.getAPIMethods = function() { TestService2.prototype.getAPIMethods = function() {
return [ return [
['getData2', this, this.getData2, 1] ['getData2', this, this.getData2, 1]
]; ];
@ -254,16 +254,16 @@ describe('Bitcore Node', function() {
node.getServiceOrder = sinon.stub().returns([ node.getServiceOrder = sinon.stub().returns([
{ {
name: 'test1', name: 'test1',
module: TestModule module: TestService
}, },
{ {
name: 'test2', name: 'test2',
module: TestModule2 module: TestService2
} }
]); ]);
node.start(function() { node.start(function() {
TestModule2.prototype.start.callCount.should.equal(1); TestService2.prototype.start.callCount.should.equal(1);
TestModule.prototype.start.callCount.should.equal(1); TestService.prototype.start.callCount.should.equal(1);
should.exist(node.getData2); should.exist(node.getData2);
should.exist(node.getData); should.exist(node.getData);
done(); done();
@ -272,21 +272,21 @@ describe('Bitcore Node', function() {
it('will error if there are conflicting API methods', function(done) { it('will error if there are conflicting API methods', function(done) {
var node = new Node(baseConfig); var node = new Node(baseConfig);
function TestModule() {} function TestService() {}
util.inherits(TestModule, BaseModule); util.inherits(TestService, BaseService);
TestModule.prototype.start = sinon.stub().callsArg(0); TestService.prototype.start = sinon.stub().callsArg(0);
TestModule.prototype.getData = function() {}; TestService.prototype.getData = function() {};
TestModule.prototype.getAPIMethods = function() { TestService.prototype.getAPIMethods = function() {
return [ return [
['getData', this, this.getData, 1] ['getData', this, this.getData, 1]
]; ];
}; };
function ConflictModule() {} function ConflictService() {}
util.inherits(ConflictModule, BaseModule); util.inherits(ConflictService, BaseService);
ConflictModule.prototype.start = sinon.stub().callsArg(0); ConflictService.prototype.start = sinon.stub().callsArg(0);
ConflictModule.prototype.getData = function() {}; ConflictService.prototype.getData = function() {};
ConflictModule.prototype.getAPIMethods = function() { ConflictService.prototype.getAPIMethods = function() {
return [ return [
['getData', this, this.getData, 1] ['getData', this, this.getData, 1]
]; ];
@ -295,11 +295,11 @@ describe('Bitcore Node', function() {
node.getServiceOrder = sinon.stub().returns([ node.getServiceOrder = sinon.stub().returns([
{ {
name: 'test', name: 'test',
module: TestModule module: TestService
}, },
{ {
name: 'conflict', name: 'conflict',
module: ConflictModule module: ConflictService
} }
]); ]);
@ -313,30 +313,30 @@ describe('Bitcore Node', function() {
}); });
describe('#stop', function() { describe('#stop', function() {
it('will call stop for each module', function(done) { it('will call stop for each service', function(done) {
var node = new Node(baseConfig); var node = new Node(baseConfig);
function TestModule() {} function TestService() {}
util.inherits(TestModule, BaseModule); util.inherits(TestService, BaseService);
TestModule.prototype.stop = sinon.stub().callsArg(0); TestService.prototype.stop = sinon.stub().callsArg(0);
TestModule.prototype.getData = function() {}; TestService.prototype.getData = function() {};
TestModule.prototype.getAPIMethods = function() { TestService.prototype.getAPIMethods = function() {
return [ return [
['getData', this, this.getData, 1] ['getData', this, this.getData, 1]
]; ];
}; };
node.modules = { node.services = {
'test1': new TestModule({node: node}) 'test1': new TestService({node: node})
}; };
node.test2 = {}; node.test2 = {};
node.test2.stop = sinon.stub().callsArg(0); node.test2.stop = sinon.stub().callsArg(0);
node.getServiceOrder = sinon.stub().returns([ node.getServiceOrder = sinon.stub().returns([
{ {
name: 'test1', name: 'test1',
module: TestModule module: TestService
} }
]); ]);
node.stop(function() { node.stop(function() {
TestModule.prototype.stop.callCount.should.equal(1); TestService.prototype.stop.callCount.should.equal(1);
done(); done();
}); });
}); });

View File

@ -15,7 +15,7 @@ describe('#add', function() {
var testDir = path.resolve(basePath, 'temporary-test-data'); var testDir = path.resolve(basePath, 'temporary-test-data');
var startConfig = { var startConfig = {
name: 'My Node', name: 'My Node',
modules: [] services: []
}; };
var startPackage = {}; var startPackage = {};
@ -56,7 +56,7 @@ describe('#add', function() {
it('will give an error if expected files do not exist', function(done) { it('will give an error if expected files do not exist', function(done) {
add({ add({
path: path.resolve(testDir, 's0'), path: path.resolve(testDir, 's0'),
modules: ['a', 'b', 'c'] services: ['a', 'b', 'c']
}, function(err) { }, function(err) {
should.exist(err); should.exist(err);
err.message.match(/^Invalid state/); err.message.match(/^Invalid state/);
@ -82,15 +82,15 @@ describe('#add', function() {
addtest({ addtest({
path: path.resolve(testDir, 's0/s1/'), path: path.resolve(testDir, 's0/s1/'),
modules: ['a', 'b', 'c'] services: ['a', 'b', 'c']
}, function(err) { }, function(err) {
should.exist(err); should.exist(err);
err.message.should.equal('There was an error installing module: a'); err.message.should.equal('There was an error installing service: a');
done(); done();
}); });
}); });
it('will update bitcore-node.json modules', function(done) { it('will update bitcore-node.json services', function(done) {
var spawn = sinon.stub().returns({ var spawn = sinon.stub().returns({
stdout: { stdout: {
on: sinon.stub() on: sinon.stub()
@ -107,12 +107,12 @@ describe('#add', function() {
}); });
addtest({ addtest({
path: path.resolve(testDir, 's0/s1/'), path: path.resolve(testDir, 's0/s1/'),
modules: ['a', 'b', 'c'] services: ['a', 'b', 'c']
}, function(err) { }, function(err) {
should.not.exist(err); should.not.exist(err);
var configPath = path.resolve(testDir, 's0/s1/bitcore-node.json'); var configPath = path.resolve(testDir, 's0/s1/bitcore-node.json');
var config = JSON.parse(fs.readFileSync(configPath)); var config = JSON.parse(fs.readFileSync(configPath));
config.modules.should.deep.equal(['a','b','c']); config.services.should.deep.equal(['a','b','c']);
done(); done();
}); });
}); });

View File

@ -75,7 +75,7 @@ describe('#create', function() {
var config = JSON.parse(fs.readFileSync(configPath)); var config = JSON.parse(fs.readFileSync(configPath));
config.name.should.equal('My Node 1'); config.name.should.equal('My Node 1');
config.modules.should.deep.equal(['address']); config.services.should.deep.equal(['address']);
config.datadir.should.equal('./data'); config.datadir.should.equal('./data');
config.network.should.equal('livenet'); config.network.should.equal('livenet');

View File

@ -3,18 +3,18 @@
var should = require('chai').should(); var should = require('chai').should();
var sinon = require('sinon'); var sinon = require('sinon');
var proxyquire = require('proxyquire'); var proxyquire = require('proxyquire');
var AddressModule = require('../../lib/modules/address'); var AddressService = require('../../lib/services/address');
describe('#start', function() { describe('#start', function() {
describe('will dynamically create a node from a configuration', function() { describe('will dynamically create a node from a configuration', function() {
it('require each bitcore-node module', function(done) { it('require each bitcore-node service', function(done) {
var node; var node;
var TestNode = function(options) { var TestNode = function(options) {
options.modules[0].should.deep.equal({ options.services[0].should.deep.equal({
name: 'address', name: 'address',
module: AddressModule, module: AddressService,
dependencies: ['bitcoind', 'db'] dependencies: ['bitcoind', 'db']
}); });
}; };
@ -30,7 +30,7 @@ describe('#start', function() {
node = starttest({ node = starttest({
path: __dirname, path: __dirname,
config: { config: {
modules: [ services: [
'address' 'address'
], ],
datadir: './data' datadir: './data'

View File

@ -3,7 +3,7 @@
var should = require('chai').should(); var should = require('chai').should();
var sinon = require('sinon'); var sinon = require('sinon');
var bitcorenode = require('../../'); var bitcorenode = require('../../');
var AddressModule = bitcorenode.modules.AddressModule; var AddressService = bitcorenode.services.Address;
var blockData = require('../data/livenet-345003.json'); var blockData = require('../data/livenet-345003.json');
var bitcore = require('bitcore'); var bitcore = require('bitcore');
var Networks = bitcore.Networks; var Networks = bitcore.Networks;
@ -16,18 +16,18 @@ var mockdb = {
var mocknode = { var mocknode = {
db: mockdb, db: mockdb,
modules: { services: {
bitcoind: { bitcoind: {
on: sinon.stub() on: sinon.stub()
} }
} }
}; };
describe('Address Module', function() { describe('Address Service', function() {
describe('#getAPIMethods', function() { describe('#getAPIMethods', function() {
it('should return the correct methods', function() { it('should return the correct methods', function() {
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
var methods = am.getAPIMethods(); var methods = am.getAPIMethods();
methods.length.should.equal(5); methods.length.should.equal(5);
}); });
@ -35,7 +35,7 @@ describe('Address Module', function() {
describe('#getPublishEvents', function() { describe('#getPublishEvents', function() {
it('will return an array of publish event objects', function() { it('will return an array of publish event objects', function() {
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
am.subscribe = sinon.spy(); am.subscribe = sinon.spy();
am.unsubscribe = sinon.spy(); am.unsubscribe = sinon.spy();
var events = am.getPublishEvents(); var events = am.getPublishEvents();
@ -71,7 +71,7 @@ describe('Address Module', function() {
it('create a message for an address', function() { it('create a message for an address', function() {
var txBuf = new Buffer('01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000', 'hex'); var txBuf = new Buffer('01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000', 'hex');
var tx = bitcore.Transaction().fromBuffer(txBuf); var tx = bitcore.Transaction().fromBuffer(txBuf);
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
am.node.network = Networks.livenet; am.node.network = Networks.livenet;
var address = '12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'; var address = '12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX';
var messages = {}; var messages = {};
@ -88,7 +88,7 @@ describe('Address Module', function() {
describe('#transactionHandler', function() { describe('#transactionHandler', function() {
it('will pass outputs to transactionOutputHandler and call transactionEventHandler', function() { it('will pass outputs to transactionOutputHandler and call transactionEventHandler', function() {
var txBuf = new Buffer('01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000', 'hex'); var txBuf = new Buffer('01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000', 'hex');
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
var address = '12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'; var address = '12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX';
var message = {}; var message = {};
am.transactionOutputHandler = function(messages) { am.transactionOutputHandler = function(messages) {
@ -153,7 +153,7 @@ describe('Address Module', function() {
var value64 = data[2].value; var value64 = data[2].value;
before(function() { before(function() {
am = new AddressModule({node: mocknode}); am = new AddressService({node: mocknode});
am.node.network = Networks.livenet; am.node.network = Networks.livenet;
}); });
@ -208,7 +208,7 @@ describe('Address Module', function() {
}); });
}); });
it('should continue if output script is null', function(done) { it('should continue if output script is null', function(done) {
var am = new AddressModule({node: mocknode, network: 'livenet'}); var am = new AddressService({node: mocknode, network: 'livenet'});
var block = { var block = {
__height: 345003, __height: 345003,
@ -240,13 +240,13 @@ describe('Address Module', function() {
var db = {}; var db = {};
var testnode = { var testnode = {
db: db, db: db,
modules: { services: {
bitcoind: { bitcoind: {
on: sinon.stub() on: sinon.stub()
} }
} }
}; };
var am = new AddressModule({node: testnode, network: 'livenet'}); var am = new AddressService({node: testnode, network: 'livenet'});
am.transactionEventHandler = sinon.spy(); am.transactionEventHandler = sinon.spy();
am.balanceEventHandler = sinon.spy(); am.balanceEventHandler = sinon.spy();
@ -274,7 +274,7 @@ describe('Address Module', function() {
describe('#transactionEventHandler', function() { describe('#transactionEventHandler', function() {
it('will emit a transaction if there is a subscriber', function(done) { it('will emit a transaction if there is a subscriber', function(done) {
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
var emitter = new EventEmitter(); var emitter = new EventEmitter();
am.subscriptions['address/transaction'] = { am.subscriptions['address/transaction'] = {
'1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N': [emitter] '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N': [emitter]
@ -304,7 +304,7 @@ describe('Address Module', function() {
describe('#balanceEventHandler', function() { describe('#balanceEventHandler', function() {
it('will emit a balance if there is a subscriber', function(done) { it('will emit a balance if there is a subscriber', function(done) {
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
var emitter = new EventEmitter(); var emitter = new EventEmitter();
am.subscriptions['address/balance'] = { am.subscriptions['address/balance'] = {
'1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N': [emitter] '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N': [emitter]
@ -324,7 +324,7 @@ describe('Address Module', function() {
describe('#subscribe', function() { describe('#subscribe', function() {
it('will add emitters to the subscribers array (transaction)', function() { it('will add emitters to the subscribers array (transaction)', function() {
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
var emitter = new EventEmitter(); var emitter = new EventEmitter();
var address = '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N'; var address = '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N';
@ -341,7 +341,7 @@ describe('Address Module', function() {
am.subscriptions['address/transaction'][address].should.deep.equal([emitter, emitter2]); am.subscriptions['address/transaction'][address].should.deep.equal([emitter, emitter2]);
}); });
it('will add an emitter to the subscribers array (balance)', function() { it('will add an emitter to the subscribers array (balance)', function() {
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
var emitter = new EventEmitter(); var emitter = new EventEmitter();
var name = 'address/balance'; var name = 'address/balance';
var address = '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N'; var address = '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N';
@ -360,7 +360,7 @@ describe('Address Module', function() {
describe('#unsubscribe', function() { describe('#unsubscribe', function() {
it('will remove emitter from subscribers array (transaction)', function() { it('will remove emitter from subscribers array (transaction)', function() {
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
var emitter = new EventEmitter(); var emitter = new EventEmitter();
var emitter2 = new EventEmitter(); var emitter2 = new EventEmitter();
var address = '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N'; var address = '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N';
@ -370,7 +370,7 @@ describe('Address Module', function() {
am.subscriptions['address/transaction'][address].should.deep.equal([emitter2]); am.subscriptions['address/transaction'][address].should.deep.equal([emitter2]);
}); });
it('will remove emitter from subscribers array (balance)', function() { it('will remove emitter from subscribers array (balance)', function() {
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
var emitter = new EventEmitter(); var emitter = new EventEmitter();
var emitter2 = new EventEmitter(); var emitter2 = new EventEmitter();
var address = '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N'; var address = '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N';
@ -380,7 +380,7 @@ describe('Address Module', function() {
am.subscriptions['address/balance'][address].should.deep.equal([emitter2]); am.subscriptions['address/balance'][address].should.deep.equal([emitter2]);
}); });
it('should unsubscribe from all addresses if no addresses are specified', function() { it('should unsubscribe from all addresses if no addresses are specified', function() {
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
var emitter = new EventEmitter(); var emitter = new EventEmitter();
var emitter2 = new EventEmitter(); var emitter2 = new EventEmitter();
am.subscriptions['address/balance'] = { am.subscriptions['address/balance'] = {
@ -397,7 +397,7 @@ describe('Address Module', function() {
describe('#getBalance', function() { describe('#getBalance', function() {
it('should sum up the unspent outputs', function(done) { it('should sum up the unspent outputs', function(done) {
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
var outputs = [ var outputs = [
{satoshis: 1000}, {satoshis: 2000}, {satoshis: 3000} {satoshis: 1000}, {satoshis: 2000}, {satoshis: 3000}
]; ];
@ -410,7 +410,7 @@ describe('Address Module', function() {
}); });
it('will handle error from unspent outputs', function(done) { it('will handle error from unspent outputs', function(done) {
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
am.getUnspentOutputs = sinon.stub().callsArgWith(2, new Error('error')); am.getUnspentOutputs = sinon.stub().callsArgWith(2, new Error('error'));
am.getBalance('someaddress', false, function(err) { am.getBalance('someaddress', false, function(err) {
should.exist(err); should.exist(err);
@ -430,7 +430,7 @@ describe('Address Module', function() {
} }
}; };
var testnode = { var testnode = {
modules: { services: {
db: db, db: db,
bitcoind: { bitcoind: {
on: sinon.stub() on: sinon.stub()
@ -439,12 +439,12 @@ describe('Address Module', function() {
}; };
before(function() { before(function() {
am = new AddressModule({node: testnode}); am = new AddressService({node: testnode});
}); });
it('should get outputs for an address', function(done) { it('should get outputs for an address', function(done) {
var readStream1 = new EventEmitter(); var readStream1 = new EventEmitter();
am.node.modules.db.store = { am.node.services.db.store = {
createReadStream: sinon.stub().returns(readStream1) createReadStream: sinon.stub().returns(readStream1)
}; };
var mempoolOutputs = [ var mempoolOutputs = [
@ -456,7 +456,7 @@ describe('Address Module', function() {
blockHeight: 352532 blockHeight: 352532
} }
]; ];
am.node.modules.bitcoind = { am.node.services.bitcoind = {
getMempoolOutputs: sinon.stub().returns(mempoolOutputs) getMempoolOutputs: sinon.stub().returns(mempoolOutputs)
}; };
@ -499,7 +499,7 @@ describe('Address Module', function() {
it('should give an error if the readstream has an error', function(done) { it('should give an error if the readstream has an error', function(done) {
var readStream2 = new EventEmitter(); var readStream2 = new EventEmitter();
am.node.modules.db.store = { am.node.services.db.store = {
createReadStream: sinon.stub().returns(readStream2) createReadStream: sinon.stub().returns(readStream2)
}; };
@ -526,14 +526,14 @@ describe('Address Module', function() {
var db = {}; var db = {};
var testnode = { var testnode = {
modules: { services: {
db: db, db: db,
bitcoind: { bitcoind: {
on: sinon.stub() on: sinon.stub()
} }
} }
}; };
var am = new AddressModule({node: testnode}); var am = new AddressService({node: testnode});
am.getUnspentOutputsForAddress = function(address, queryMempool, callback) { am.getUnspentOutputsForAddress = function(address, queryMempool, callback) {
var result = addresses[address]; var result = addresses[address];
if(result instanceof Error) { if(result instanceof Error) {
@ -559,13 +559,13 @@ describe('Address Module', function() {
var db = {}; var db = {};
var testnode = { var testnode = {
db: db, db: db,
modules: { services: {
bitcoind: { bitcoind: {
on: sinon.stub() on: sinon.stub()
} }
} }
}; };
var am = new AddressModule({node: testnode}); var am = new AddressService({node: testnode});
am.getUnspentOutputsForAddress = function(address, queryMempool, callback) { am.getUnspentOutputsForAddress = function(address, queryMempool, callback) {
var result = addresses[address]; var result = addresses[address];
if(result instanceof Error) { if(result instanceof Error) {
@ -592,13 +592,13 @@ describe('Address Module', function() {
var db = {}; var db = {};
var testnode = { var testnode = {
db: db, db: db,
modules: { services: {
bitcoind: { bitcoind: {
on: sinon.stub() on: sinon.stub()
} }
} }
}; };
var am = new AddressModule({node: testnode}); var am = new AddressService({node: testnode});
am.getUnspentOutputsForAddress = function(address, queryMempool, callback) { am.getUnspentOutputsForAddress = function(address, queryMempool, callback) {
var result = addresses[address]; var result = addresses[address];
if(result instanceof Error) { if(result instanceof Error) {
@ -634,7 +634,7 @@ describe('Address Module', function() {
]; ];
var i = 0; var i = 0;
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
am.getOutputs = sinon.stub().callsArgWith(2, null, outputs); am.getOutputs = sinon.stub().callsArgWith(2, null, outputs);
am.isUnspent = function(output, queryMempool, callback) { am.isUnspent = function(output, queryMempool, callback) {
callback(!outputs[i].spent); callback(!outputs[i].spent);
@ -650,7 +650,7 @@ describe('Address Module', function() {
}); });
}); });
it('should handle an error from getOutputs', function(done) { it('should handle an error from getOutputs', function(done) {
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
am.getOutputs = sinon.stub().callsArgWith(2, new Error('error')); am.getOutputs = sinon.stub().callsArgWith(2, new Error('error'));
am.getUnspentOutputsForAddress('1KiW1A4dx1oRgLHtDtBjcunUGkYtFgZ1W', false, function(err, outputs) { am.getUnspentOutputsForAddress('1KiW1A4dx1oRgLHtDtBjcunUGkYtFgZ1W', false, function(err, outputs) {
should.exist(err); should.exist(err);
@ -659,7 +659,7 @@ describe('Address Module', function() {
}); });
}); });
it('should handle when there are no outputs', function(done) { it('should handle when there are no outputs', function(done) {
var am = new AddressModule({node: mocknode}); var am = new AddressService({node: mocknode});
am.getOutputs = sinon.stub().callsArgWith(2, null, []); am.getOutputs = sinon.stub().callsArgWith(2, null, []);
am.getUnspentOutputsForAddress('1KiW1A4dx1oRgLHtDtBjcunUGkYtFgZ1W', false, function(err, outputs) { am.getUnspentOutputsForAddress('1KiW1A4dx1oRgLHtDtBjcunUGkYtFgZ1W', false, function(err, outputs) {
should.exist(err); should.exist(err);
@ -674,7 +674,7 @@ describe('Address Module', function() {
var am; var am;
before(function() { before(function() {
am = new AddressModule({node: mocknode}); am = new AddressService({node: mocknode});
}); });
it('should give true when isSpent() gives false', function(done) { it('should give true when isSpent() gives false', function(done) {
@ -707,15 +707,15 @@ describe('Address Module', function() {
var db = {}; var db = {};
var testnode = { var testnode = {
db: db, db: db,
modules: { services: {
bitcoind: { bitcoind: {
on: sinon.stub() on: sinon.stub()
} }
} }
}; };
before(function() { before(function() {
am = new AddressModule({node: testnode}); am = new AddressService({node: testnode});
am.node.modules.bitcoind = { am.node.services.bitcoind = {
isSpent: sinon.stub().returns(true), isSpent: sinon.stub().returns(true),
on: sinon.stub() on: sinon.stub()
}; };
@ -737,14 +737,14 @@ describe('Address Module', function() {
} }
}; };
var testnode = { var testnode = {
modules: { services: {
db: db, db: db,
bitcoind: { bitcoind: {
on: sinon.stub() on: sinon.stub()
} }
} }
}; };
var am = new AddressModule({node: testnode}); var am = new AddressService({node: testnode});
am.getSpendInfoForOutput('txid', 3, function(err, info) { am.getSpendInfoForOutput('txid', 3, function(err, info) {
should.not.exist(err); should.not.exist(err);
info.txid.should.equal('spendtxid'); info.txid.should.equal('spendtxid');
@ -855,14 +855,14 @@ describe('Address Module', function() {
} }
}; };
var testnode = { var testnode = {
modules: { services: {
db: db, db: db,
bitcoind: { bitcoind: {
on: sinon.stub() on: sinon.stub()
} }
} }
}; };
var am = new AddressModule({node: testnode}); var am = new AddressService({node: testnode});
am.getOutputs = sinon.stub().callsArgWith(2, null, incoming); am.getOutputs = sinon.stub().callsArgWith(2, null, incoming);
am.getSpendInfoForOutput = function(txid, outputIndex, callback) { am.getSpendInfoForOutput = function(txid, outputIndex, callback) {

View File

@ -4,18 +4,18 @@ var should = require('chai').should();
var proxyquire = require('proxyquire'); var proxyquire = require('proxyquire');
var fs = require('fs'); var fs = require('fs');
var sinon = require('sinon'); var sinon = require('sinon');
var BitcoinModule = proxyquire('../../lib/modules/bitcoind', { var BitcoinService = proxyquire('../../lib/services/bitcoind', {
fs: { fs: {
readFileSync: sinon.stub().returns(fs.readFileSync(__dirname + '/../data/bitcoin.conf')) readFileSync: sinon.stub().returns(fs.readFileSync(__dirname + '/../data/bitcoin.conf'))
} }
}); });
var BadBitcoin = proxyquire('../../lib/modules/bitcoind', { var BadBitcoin = proxyquire('../../lib/services/bitcoind', {
fs: { fs: {
readFileSync: sinon.stub().returns(fs.readFileSync(__dirname + '/../data/badbitcoin.conf')) readFileSync: sinon.stub().returns(fs.readFileSync(__dirname + '/../data/badbitcoin.conf'))
} }
}); });
describe('Bitcoin Module', function() { describe('Bitcoin Service', function() {
var baseConfig = { var baseConfig = {
node: { node: {
datadir: 'testdir', datadir: 'testdir',
@ -26,7 +26,7 @@ describe('Bitcoin Module', function() {
}; };
describe('#_loadConfiguration', function() { describe('#_loadConfiguration', function() {
it('will parse a bitcoin.conf file', function() { it('will parse a bitcoin.conf file', function() {
var bitcoind = new BitcoinModule(baseConfig); var bitcoind = new BitcoinService(baseConfig);
bitcoind._loadConfiguration({datadir: process.env.HOME + '/.bitcoin'}); bitcoind._loadConfiguration({datadir: process.env.HOME + '/.bitcoin'});
should.exist(bitcoind.configuration); should.exist(bitcoind.configuration);
bitcoind.configuration.should.deep.equal({ bitcoind.configuration.should.deep.equal({

View File

@ -5,7 +5,7 @@ var sinon = require('sinon');
var EventEmitter = require('events').EventEmitter; var EventEmitter = require('events').EventEmitter;
var proxyquire = require('proxyquire'); var proxyquire = require('proxyquire');
var index = require('../../'); var index = require('../../');
var DB = index.modules.DBModule; var DB = index.services.DB;
var blockData = require('../data/livenet-345003.json'); var blockData = require('../data/livenet-345003.json');
var bitcore = require('bitcore'); var bitcore = require('bitcore');
var Networks = bitcore.Networks; var Networks = bitcore.Networks;
@ -19,7 +19,7 @@ var memdown = require('memdown');
var bitcore = require('bitcore'); var bitcore = require('bitcore');
var Transaction = bitcore.Transaction; var Transaction = bitcore.Transaction;
describe('DB Module', function() { describe('DB Service', function() {
function hexlebuf(hexString){ function hexlebuf(hexString){
return BufferUtil.reverse(new Buffer(hexString, 'hex')); return BufferUtil.reverse(new Buffer(hexString, 'hex'));
@ -106,7 +106,7 @@ describe('DB Module', function() {
var genesisBuffer; var genesisBuffer;
before(function() { before(function() {
TestDB = proxyquire('../../lib/modules/db', { TestDB = proxyquire('../../lib/services/db', {
fs: { fs: {
existsSync: sinon.stub().returns(true) existsSync: sinon.stub().returns(true)
}, },
@ -118,12 +118,11 @@ describe('DB Module', function() {
it('should emit ready', function(done) { it('should emit ready', function(done) {
var db = new TestDB(baseConfig); var db = new TestDB(baseConfig);
db.node = {}; db.node = {};
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
on: sinon.spy(), on: sinon.spy(),
genesisBuffer: genesisBuffer genesisBuffer: genesisBuffer
}; };
db._addModule = sinon.spy();
db.getMetadata = sinon.stub().callsArg(0); db.getMetadata = sinon.stub().callsArg(0);
db.connectBlock = sinon.stub().callsArg(1); db.connectBlock = sinon.stub().callsArg(1);
db.saveMetadata = sinon.stub(); db.saveMetadata = sinon.stub();
@ -142,7 +141,7 @@ describe('DB Module', function() {
var node = { var node = {
network: Networks.testnet, network: Networks.testnet,
datadir: 'testdir', datadir: 'testdir',
modules: { services: {
bitcoind: { bitcoind: {
genesisBuffer: genesisBuffer, genesisBuffer: genesisBuffer,
on: sinon.stub() on: sinon.stub()
@ -165,7 +164,7 @@ describe('DB Module', function() {
var node = { var node = {
network: Networks.testnet, network: Networks.testnet,
datadir: 'testdir', datadir: 'testdir',
modules: { services: {
bitcoind: { bitcoind: {
genesisBuffer: genesisBuffer, genesisBuffer: genesisBuffer,
on: sinon.stub() on: sinon.stub()
@ -193,7 +192,7 @@ describe('DB Module', function() {
var node = { var node = {
network: Networks.testnet, network: Networks.testnet,
datadir: 'testdir', datadir: 'testdir',
modules: { services: {
bitcoind: { bitcoind: {
genesisBuffer: genesisBuffer, genesisBuffer: genesisBuffer,
on: sinon.stub() on: sinon.stub()
@ -213,7 +212,7 @@ describe('DB Module', function() {
var node = { var node = {
network: Networks.testnet, network: Networks.testnet,
datadir: 'testdir', datadir: 'testdir',
modules: { services: {
bitcoind: { bitcoind: {
genesisBuffer: genesisBuffer, genesisBuffer: genesisBuffer,
on: sinon.stub() on: sinon.stub()
@ -236,29 +235,29 @@ describe('DB Module', function() {
it('will call sync when there is a new tip', function(done) { it('will call sync when there is a new tip', function(done) {
var db = new TestDB(baseConfig); var db = new TestDB(baseConfig);
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = new EventEmitter(); db.node.services.bitcoind = new EventEmitter();
db.node.modules.bitcoind.syncPercentage = sinon.spy(); db.node.services.bitcoind.syncPercentage = sinon.spy();
db.node.modules.bitcoind.genesisBuffer = genesisBuffer; db.node.services.bitcoind.genesisBuffer = genesisBuffer;
db.getMetadata = sinon.stub().callsArg(0); db.getMetadata = sinon.stub().callsArg(0);
db.connectBlock = sinon.stub().callsArg(1); db.connectBlock = sinon.stub().callsArg(1);
db.saveMetadata = sinon.stub(); db.saveMetadata = sinon.stub();
db.sync = sinon.stub(); db.sync = sinon.stub();
db.start(function() { db.start(function() {
db.sync = function() { db.sync = function() {
db.node.modules.bitcoind.syncPercentage.callCount.should.equal(1); db.node.services.bitcoind.syncPercentage.callCount.should.equal(1);
done(); done();
}; };
db.node.modules.bitcoind.emit('tip', 10); db.node.services.bitcoind.emit('tip', 10);
}); });
}); });
it('will not call sync when there is a new tip and shutting down', function(done) { it('will not call sync when there is a new tip and shutting down', function(done) {
var db = new TestDB(baseConfig); var db = new TestDB(baseConfig);
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = new EventEmitter(); db.node.services.bitcoind = new EventEmitter();
db.node.modules.bitcoind.syncPercentage = sinon.spy(); db.node.services.bitcoind.syncPercentage = sinon.spy();
db.node.modules.bitcoind.genesisBuffer = genesisBuffer; db.node.services.bitcoind.genesisBuffer = genesisBuffer;
db.getMetadata = sinon.stub().callsArg(0); db.getMetadata = sinon.stub().callsArg(0);
db.connectBlock = sinon.stub().callsArg(1); db.connectBlock = sinon.stub().callsArg(1);
db.saveMetadata = sinon.stub(); db.saveMetadata = sinon.stub();
@ -266,11 +265,11 @@ describe('DB Module', function() {
db.sync = sinon.stub(); db.sync = sinon.stub();
db.start(function() { db.start(function() {
db.sync.callCount.should.equal(1); db.sync.callCount.should.equal(1);
db.node.modules.bitcoind.once('tip', function() { db.node.services.bitcoind.once('tip', function() {
db.sync.callCount.should.equal(1); db.sync.callCount.should.equal(1);
done(); done();
}); });
db.node.modules.bitcoind.emit('tip', 10); db.node.services.bitcoind.emit('tip', 10);
}); });
}); });
@ -291,8 +290,8 @@ describe('DB Module', function() {
it('will return a NotFound error', function(done) { it('will return a NotFound error', function(done) {
var db = new DB(baseConfig); var db = new DB(baseConfig);
db.node = {}; db.node = {};
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
getTransaction: sinon.stub().callsArgWith(2, null, null) getTransaction: sinon.stub().callsArgWith(2, null, null)
}; };
var txid = '7426c707d0e9705bdd8158e60983e37d0f5d63529086d6672b07d9238d5aa623'; var txid = '7426c707d0e9705bdd8158e60983e37d0f5d63529086d6672b07d9238d5aa623';
@ -304,8 +303,8 @@ describe('DB Module', function() {
it('will return an error from bitcoind', function(done) { it('will return an error from bitcoind', function(done) {
var db = new DB(baseConfig); var db = new DB(baseConfig);
db.node = {}; db.node = {};
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
getTransaction: sinon.stub().callsArgWith(2, new Error('test error')) getTransaction: sinon.stub().callsArgWith(2, new Error('test error'))
}; };
var txid = '7426c707d0e9705bdd8158e60983e37d0f5d63529086d6672b07d9238d5aa623'; var txid = '7426c707d0e9705bdd8158e60983e37d0f5d63529086d6672b07d9238d5aa623';
@ -317,8 +316,8 @@ describe('DB Module', function() {
it('will return an error from bitcoind', function(done) { it('will return an error from bitcoind', function(done) {
var db = new DB(baseConfig); var db = new DB(baseConfig);
db.node = {}; db.node = {};
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
getTransaction: sinon.stub().callsArgWith(2, null, new Buffer(transactionData[0].hex, 'hex')) getTransaction: sinon.stub().callsArgWith(2, null, new Buffer(transactionData[0].hex, 'hex'))
}; };
var txid = '7426c707d0e9705bdd8158e60983e37d0f5d63529086d6672b07d9238d5aa623'; var txid = '7426c707d0e9705bdd8158e60983e37d0f5d63529086d6672b07d9238d5aa623';
@ -337,8 +336,8 @@ describe('DB Module', function() {
var blockBuffer = new Buffer(blockData, 'hex'); var blockBuffer = new Buffer(blockData, 'hex');
var expectedBlock = Block.fromBuffer(blockBuffer); var expectedBlock = Block.fromBuffer(blockBuffer);
db.node = {}; db.node = {};
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
getBlock: sinon.stub().callsArgWith(1, null, blockBuffer) getBlock: sinon.stub().callsArgWith(1, null, blockBuffer)
}; };
@ -351,9 +350,9 @@ describe('DB Module', function() {
}); });
it('should give an error when bitcoind.js gives an error', function(done) { it('should give an error when bitcoind.js gives an error', function(done) {
db.node = {}; db.node = {};
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = {}; db.node.services.bitcoind = {};
db.node.modules.bitcoind.getBlock = sinon.stub().callsArgWith(1, new Error('error')); db.node.services.bitcoind.getBlock = sinon.stub().callsArgWith(1, new Error('error'));
db.getBlock('00000000000000000593b60d8b4f40fd1ec080bdb0817d475dae47b5f5b1f735', function(err, block) { db.getBlock('00000000000000000593b60d8b4f40fd1ec080bdb0817d475dae47b5f5b1f735', function(err, block) {
should.exist(err); should.exist(err);
err.message.should.equal('error'); err.message.should.equal('error');
@ -366,8 +365,8 @@ describe('DB Module', function() {
it('should return prevHash from bitcoind', function(done) { it('should return prevHash from bitcoind', function(done) {
var db = new DB(baseConfig); var db = new DB(baseConfig);
db.node = {}; db.node = {};
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
getBlockIndex: sinon.stub().returns({ getBlockIndex: sinon.stub().returns({
prevHash: 'prevhash' prevHash: 'prevhash'
}) })
@ -383,8 +382,8 @@ describe('DB Module', function() {
it('should give an error if bitcoind could not find it', function(done) { it('should give an error if bitcoind could not find it', function(done) {
var db = new DB(baseConfig); var db = new DB(baseConfig);
db.node = {}; db.node = {};
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
getBlockIndex: sinon.stub().returns(null) getBlockIndex: sinon.stub().returns(null)
}; };
@ -406,8 +405,8 @@ describe('DB Module', function() {
var db = new DB(baseConfig); var db = new DB(baseConfig);
db.node = {}; db.node = {};
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
getTransactionWithBlockInfo: sinon.stub().callsArgWith(2, null, info) getTransactionWithBlockInfo: sinon.stub().callsArgWith(2, null, info)
}; };
@ -421,8 +420,8 @@ describe('DB Module', function() {
it('should give an error if one occurred', function(done) { it('should give an error if one occurred', function(done) {
var db = new DB(baseConfig); var db = new DB(baseConfig);
db.node = {}; db.node = {};
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
getTransactionWithBlockInfo: sinon.stub().callsArgWith(2, new Error('error')) getTransactionWithBlockInfo: sinon.stub().callsArgWith(2, new Error('error'))
}; };
@ -437,8 +436,8 @@ describe('DB Module', function() {
it('should give the txid on success', function(done) { it('should give the txid on success', function(done) {
var db = new DB(baseConfig); var db = new DB(baseConfig);
db.node = {}; db.node = {};
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
sendTransaction: sinon.stub().returns('txid') sendTransaction: sinon.stub().returns('txid')
}; };
@ -452,8 +451,8 @@ describe('DB Module', function() {
it('should give an error if bitcoind threw an error', function(done) { it('should give an error if bitcoind threw an error', function(done) {
var db = new DB(baseConfig); var db = new DB(baseConfig);
db.node = {}; db.node = {};
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
sendTransaction: sinon.stub().throws(new Error('error')) sendTransaction: sinon.stub().throws(new Error('error'))
}; };
@ -469,15 +468,15 @@ describe('DB Module', function() {
it('should pass along the fee from bitcoind', function(done) { it('should pass along the fee from bitcoind', function(done) {
var db = new DB(baseConfig); var db = new DB(baseConfig);
db.node = {}; db.node = {};
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
estimateFee: sinon.stub().returns(1000) estimateFee: sinon.stub().returns(1000)
}; };
db.estimateFee(5, function(err, fee) { db.estimateFee(5, function(err, fee) {
should.not.exist(err); should.not.exist(err);
fee.should.equal(1000); fee.should.equal(1000);
db.node.modules.bitcoind.estimateFee.args[0][0].should.equal(5); db.node.services.bitcoind.estimateFee.args[0][0].should.equal(5);
done(); done();
}); });
}); });
@ -512,20 +511,20 @@ describe('DB Module', function() {
describe('#runAllBlockHandlers', function() { describe('#runAllBlockHandlers', function() {
var db = new DB(baseConfig); var db = new DB(baseConfig);
var Module1 = function() {}; var Service1 = function() {};
Module1.prototype.blockHandler = sinon.stub().callsArgWith(2, null, ['op1', 'op2', 'op3']); Service1.prototype.blockHandler = sinon.stub().callsArgWith(2, null, ['op1', 'op2', 'op3']);
var Module2 = function() {}; var Service2 = function() {};
Module2.prototype.blockHandler = sinon.stub().callsArgWith(2, null, ['op4', 'op5']); Service2.prototype.blockHandler = sinon.stub().callsArgWith(2, null, ['op4', 'op5']);
db.node = {}; db.node = {};
db.node.modules = { db.node.services = {
module1: new Module1(), service1: new Service1(),
module2: new Module2() service2: new Service2()
}; };
db.store = { db.store = {
batch: sinon.stub().callsArg(1) batch: sinon.stub().callsArg(1)
}; };
it('should call blockHandler in all modules and perform operations', function(done) { it('should call blockHandler in all services and perform operations', function(done) {
db.runAllBlockHandlers('block', true, function(err) { db.runAllBlockHandlers('block', true, function(err) {
should.not.exist(err); should.not.exist(err);
db.store.batch.args[0][0].should.deep.equal(['op1', 'op2', 'op3', 'op4', 'op5']); db.store.batch.args[0][0].should.deep.equal(['op1', 'op2', 'op3', 'op4', 'op5']);
@ -533,10 +532,10 @@ describe('DB Module', 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 services gives an error', function(done) {
var Module3 = function() {}; var Service3 = function() {};
Module3.prototype.blockHandler = sinon.stub().callsArgWith(2, new Error('error')); Service3.prototype.blockHandler = sinon.stub().callsArgWith(2, new Error('error'));
db.node.modules.module3 = new Module3(); db.node.services.service3 = new Service3();
db.runAllBlockHandlers('block', true, function(err) { db.runAllBlockHandlers('block', true, function(err) {
should.exist(err); should.exist(err);
@ -549,7 +548,7 @@ describe('DB Module', function() {
it('should return the correct db methods', function() { it('should return the correct db methods', function() {
var db = new DB(baseConfig); var db = new DB(baseConfig);
db.node = {}; db.node = {};
db.node.modules = {}; db.node.services = {};
var methods = db.getAPIMethods(); var methods = db.getAPIMethods();
methods.length.should.equal(5); methods.length.should.equal(5);
}); });
@ -631,8 +630,8 @@ describe('DB Module', function() {
} }
}, },
}; };
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
getBlockIndex: function(hash) { getBlockIndex: function(hash) {
var block = forkedBlocks[hash]; var block = forkedBlocks[hash];
return { return {
@ -678,7 +677,7 @@ describe('DB Module', function() {
} }
}); });
}; };
db.node.modules = {}; db.node.services = {};
db.disconnectBlock = function(block, callback) { db.disconnectBlock = function(block, callback) {
setImmediate(callback); setImmediate(callback);
}; };
@ -710,8 +709,8 @@ describe('DB Module', function() {
var db = new DB(syncConfig); var db = new DB(syncConfig);
var blockBuffer = new Buffer(blockData, 'hex'); var blockBuffer = new Buffer(blockData, 'hex');
var block = Block.fromBuffer(blockBuffer); var block = Block.fromBuffer(blockBuffer);
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
getBlock: sinon.stub().callsArgWith(1, null, blockBuffer), getBlock: sinon.stub().callsArgWith(1, null, blockBuffer),
isSynced: sinon.stub().returns(true), isSynced: sinon.stub().returns(true),
height: 1 height: 1
@ -737,8 +736,8 @@ describe('DB Module', function() {
}); });
it('will exit and emit error with error from bitcoind.getBlock', function(done) { it('will exit and emit error with error from bitcoind.getBlock', function(done) {
var db = new DB(syncConfig); var db = new DB(syncConfig);
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
getBlock: sinon.stub().callsArgWith(1, new Error('test error')), getBlock: sinon.stub().callsArgWith(1, new Error('test error')),
height: 1 height: 1
}; };
@ -755,8 +754,8 @@ describe('DB Module', function() {
var db = new DB(syncConfig); var db = new DB(syncConfig);
var blockBuffer = new Buffer(blockData, 'hex'); var blockBuffer = new Buffer(blockData, 'hex');
var block = Block.fromBuffer(blockBuffer); var block = Block.fromBuffer(blockBuffer);
db.node.modules = {}; db.node.services = {};
db.node.modules.bitcoind = { db.node.services.bitcoind = {
getBlock: sinon.stub().callsArgWith(1, null, blockBuffer), getBlock: sinon.stub().callsArgWith(1, null, blockBuffer),
isSynced: sinon.stub().returns(true), isSynced: sinon.stub().returns(true),
height: 1 height: 1