Merge pull request #57 from braydonf/feature/pub-sub
Event Bus Subscriptions
This commit is contained in:
commit
7cf5570071
27
README.md
27
README.md
@ -106,7 +106,7 @@ the blockchain. One built-in module is the address module which exposes the API
|
|||||||
|
|
||||||
### Writing a Module
|
### Writing a Module
|
||||||
|
|
||||||
A new module can be created by inheriting from `BitcoindJS.Module`, implementing the methods `blockHandler()` and `getAPIMethods()`, and any additional methods for querying the data. Here is an example:
|
A new module can be created by inheriting from `BitcoindJS.Module`, implementing the methods `blockHandler()`, `getAPIMethods()`, `getPublishEvents()` and any additional methods for querying the data. Here is an example:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var inherits = require('util').inherits;
|
var inherits = require('util').inherits;
|
||||||
@ -158,6 +158,31 @@ MyModule.prototype.getAPIMethods = function() {
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the bus events available for subscription
|
||||||
|
* @return {Array} array of events
|
||||||
|
*/
|
||||||
|
MyModule.prototype.getPublishEvents = function() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: 'custom',
|
||||||
|
scope: this,
|
||||||
|
subscribe: this.subscribeCustom,
|
||||||
|
unsubscribe: this.unsubscribeCustom
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will keep track of event listeners to later publish and emit events.
|
||||||
|
*/
|
||||||
|
MyModule.prototype.subscribeCustom = function(emitter, param) {
|
||||||
|
if(!this.subscriptions[param]) {
|
||||||
|
this.subscriptions[param] = [];
|
||||||
|
}
|
||||||
|
this.subscriptions[param].push(emitter);
|
||||||
|
}
|
||||||
|
|
||||||
MyModule.prototype.getData = function(arg1, callback) {
|
MyModule.prototype.getData = function(arg1, callback) {
|
||||||
// You can query the data by reading from the leveldb store on db
|
// You can query the data by reading from the leveldb store on db
|
||||||
this.db.store.get(arg1, callback);
|
this.db.store.get(arg1, callback);
|
||||||
|
|||||||
43
lib/bus.js
Normal file
43
lib/bus.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var events = require('events');
|
||||||
|
var util = require('util');
|
||||||
|
|
||||||
|
function Bus(params) {
|
||||||
|
events.EventEmitter.call(this);
|
||||||
|
this.db = params.db;
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(Bus, events.EventEmitter);
|
||||||
|
|
||||||
|
Bus.prototype.subscribe = function(name) {
|
||||||
|
for (var i = 0; i < this.db.modules.length; i++) {
|
||||||
|
var mod = this.db.modules[i];
|
||||||
|
var events = mod.getPublishEvents();
|
||||||
|
for (var j = 0; j < events.length; j++) {
|
||||||
|
var event = events[j];
|
||||||
|
var params = Array.prototype.slice.call(arguments).slice(1);
|
||||||
|
params.unshift(this);
|
||||||
|
if (name === event.name) {
|
||||||
|
event.subscribe.apply(event.scope, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Bus.prototype.unsubscribe = function(name) {
|
||||||
|
for (var i = 0; i < this.db.modules.length; i++) {
|
||||||
|
var mod = this.db.modules[i];
|
||||||
|
var events = mod.getPublishEvents();
|
||||||
|
for (var j = 0; j < events.length; j++) {
|
||||||
|
var event = events[j];
|
||||||
|
var params = Array.prototype.slice.call(arguments).slice(1);
|
||||||
|
params.unshift(this);
|
||||||
|
if (name === event.name) {
|
||||||
|
event.unsubscribe.apply(event.scope, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Bus;
|
||||||
@ -15,6 +15,18 @@ Module.prototype.blockHandler = function(block, add, callback) {
|
|||||||
setImmediate(callback);
|
setImmediate(callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the bus events available for subscription
|
||||||
|
* @return {Array} an array of event info
|
||||||
|
*/
|
||||||
|
Module.prototype.getPublishEvents = function() {
|
||||||
|
// Example:
|
||||||
|
// return [
|
||||||
|
// ['eventname', this, this.subscribeEvent, this.unsubscribeEvent],
|
||||||
|
// ];
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the API methods to expose
|
* the API methods to expose
|
||||||
* @return {Array} return array of methods
|
* @return {Array} return array of methods
|
||||||
@ -33,4 +45,4 @@ Module.prototype.getAPIMethods = function() {
|
|||||||
//
|
//
|
||||||
// };
|
// };
|
||||||
|
|
||||||
module.exports = Module;
|
module.exports = Module;
|
||||||
|
|||||||
@ -7,11 +7,17 @@ var chainlib = require('chainlib');
|
|||||||
var log = chainlib.log;
|
var log = chainlib.log;
|
||||||
var errors = chainlib.errors;
|
var errors = chainlib.errors;
|
||||||
var bitcore = require('bitcore');
|
var bitcore = require('bitcore');
|
||||||
|
var $ = bitcore.util.preconditions;
|
||||||
|
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 AddressModule = function(options) {
|
||||||
BaseModule.call(this, options);
|
BaseModule.call(this, options);
|
||||||
|
|
||||||
|
this.subscriptions = {};
|
||||||
|
this.subscriptions.transaction = {};
|
||||||
|
this.subscriptions.balance = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
inherits(AddressModule, BaseModule);
|
inherits(AddressModule, BaseModule);
|
||||||
@ -29,6 +35,23 @@ AddressModule.prototype.getAPIMethods = function() {
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AddressModule.prototype.getPublishEvents = function() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: 'transaction',
|
||||||
|
scope: this,
|
||||||
|
subscribe: this.subscribe.bind(this, 'transaction'),
|
||||||
|
unsubscribe: this.unsubscribe.bind(this, 'transaction')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'balance',
|
||||||
|
scope: this,
|
||||||
|
subscribe: this.subscribe.bind(this, 'balance'),
|
||||||
|
unsubscribe: this.unsubscribe.bind(this, 'balance')
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
AddressModule.prototype.blockHandler = function(block, addOutput, callback) {
|
AddressModule.prototype.blockHandler = function(block, addOutput, callback) {
|
||||||
var txs = this.db.getTransactionsFromBlock(block);
|
var txs = this.db.getTransactionsFromBlock(block);
|
||||||
|
|
||||||
@ -82,6 +105,11 @@ AddressModule.prototype.blockHandler = function(block, addOutput, callback) {
|
|||||||
key: [AddressModule.PREFIXES.OUTPUTS, address, timestamp, txid, outputIndex].join('-'),
|
key: [AddressModule.PREFIXES.OUTPUTS, address, timestamp, txid, outputIndex].join('-'),
|
||||||
value: [output.satoshis, script, height].join(':')
|
value: [output.satoshis, script, height].join(':')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// publish events to any subscribers
|
||||||
|
this.transactionEventHandler(block, address, tx);
|
||||||
|
this.balanceEventHandler(block, address);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tx.isCoinbase()) {
|
if(tx.isCoinbase()) {
|
||||||
@ -95,6 +123,57 @@ AddressModule.prototype.blockHandler = function(block, addOutput, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AddressModule.prototype.transactionEventHandler = function(block, address, tx) {
|
||||||
|
if(this.subscriptions.transaction[address]) {
|
||||||
|
var emitters = this.subscriptions.transaction[address];
|
||||||
|
for(var k = 0; k < emitters.length; k++) {
|
||||||
|
emitters[k].emit('transaction', address, tx, block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
AddressModule.prototype.balanceEventHandler = function(block, address) {
|
||||||
|
if(this.subscriptions.balance[address]) {
|
||||||
|
var emitters = this.subscriptions.balance[address];
|
||||||
|
this.getBalance(address, true, function(err, balance) {
|
||||||
|
if(err) {
|
||||||
|
return this.emit(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var i = 0; i < emitters.length; i++) {
|
||||||
|
emitters[i].emit('balance', address, balance, block);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
AddressModule.prototype.subscribe = function(name, emitter, addresses) {
|
||||||
|
$.checkArgument(emitter instanceof EventEmitter, 'First argument is expected to be an EventEmitter');
|
||||||
|
$.checkArgument(Array.isArray(addresses), 'Second argument is expected to be an Array of addresses');
|
||||||
|
|
||||||
|
for(var i = 0; i < addresses.length; i++) {
|
||||||
|
if(!this.subscriptions[name][addresses[i]]) {
|
||||||
|
this.subscriptions[name][addresses[i]] = [];
|
||||||
|
}
|
||||||
|
this.subscriptions[name][addresses[i]].push(emitter);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
AddressModule.prototype.unsubscribe = function(name, emitter, addresses) {
|
||||||
|
$.checkArgument(emitter instanceof EventEmitter, 'First argument is expected to be an EventEmitter');
|
||||||
|
$.checkArgument(Array.isArray(addresses), 'Second argument is expected to be an Array of addresses');
|
||||||
|
|
||||||
|
for(var i = 0; i < addresses.length; i++) {
|
||||||
|
if(this.subscriptions[name][addresses[i]]) {
|
||||||
|
var emitters = this.subscriptions[name][addresses[i]];
|
||||||
|
var index = emitters.indexOf(emitter);
|
||||||
|
if(index > -1) {
|
||||||
|
emitters.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
AddressModule.prototype.getBalance = function(address, queryMempool, callback) {
|
AddressModule.prototype.getBalance = function(address, queryMempool, callback) {
|
||||||
this.getUnspentOutputs(address, queryMempool, function(err, outputs) {
|
this.getUnspentOutputs(address, queryMempool, function(err, outputs) {
|
||||||
if(err) {
|
if(err) {
|
||||||
@ -202,4 +281,4 @@ AddressModule.prototype.isSpent = function(output, queryMempool, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = AddressModule;
|
module.exports = AddressModule;
|
||||||
|
|||||||
@ -16,6 +16,7 @@ var _ = bitcore.deps._;
|
|||||||
var $ = bitcore.util.preconditions;
|
var $ = bitcore.util.preconditions;
|
||||||
var genesis = require('./genesis.json');
|
var genesis = require('./genesis.json');
|
||||||
var daemon = require('./daemon');
|
var daemon = require('./daemon');
|
||||||
|
var Bus = require('./bus');
|
||||||
|
|
||||||
function Node(config) {
|
function Node(config) {
|
||||||
BaseNode.call(this, config);
|
BaseNode.call(this, config);
|
||||||
@ -24,6 +25,10 @@ function Node(config) {
|
|||||||
|
|
||||||
util.inherits(Node, BaseNode);
|
util.inherits(Node, BaseNode);
|
||||||
|
|
||||||
|
Node.prototype.openBus = function() {
|
||||||
|
return new Bus({db: this.db});
|
||||||
|
};
|
||||||
|
|
||||||
Node.prototype._loadConfiguration = function(config) {
|
Node.prototype._loadConfiguration = function(config) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this._loadBitcoinConf(config);
|
this._loadBitcoinConf(config);
|
||||||
|
|||||||
10
package.json
10
package.json
@ -38,14 +38,14 @@
|
|||||||
"bitcoind"
|
"bitcoind"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"async": "1.3.0",
|
||||||
"bindings": "^1.2.1",
|
"bindings": "^1.2.1",
|
||||||
"mkdirp": "0.5.0",
|
|
||||||
"nan": "1.3.0",
|
|
||||||
"tiny": "0.0.10",
|
|
||||||
"chainlib": "^0.1.1",
|
"chainlib": "^0.1.1",
|
||||||
"errno": "^0.1.2",
|
"errno": "^0.1.2",
|
||||||
"async": "1.3.0",
|
"memdown": "^1.0.0",
|
||||||
"memdown": "^1.0.0"
|
"mkdirp": "0.5.0",
|
||||||
|
"nan": "1.3.0",
|
||||||
|
"tiny": "0.0.10"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"benchmark": "1.0.0",
|
"benchmark": "1.0.0",
|
||||||
|
|||||||
61
test/bus.unit.js
Normal file
61
test/bus.unit.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var should = require('chai').should();
|
||||||
|
var sinon = require('sinon');
|
||||||
|
var Bus = require('../lib/bus');
|
||||||
|
|
||||||
|
describe('Bus', function() {
|
||||||
|
|
||||||
|
describe('#subscribe', function() {
|
||||||
|
it('will call modules subscribe function with the correct arguments', function() {
|
||||||
|
var subscribe = sinon.spy();
|
||||||
|
var db = {
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
getPublishEvents: sinon.stub().returns([
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
scope: this,
|
||||||
|
subscribe: subscribe,
|
||||||
|
}
|
||||||
|
])
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
var bus = new Bus({db: db});
|
||||||
|
bus.subscribe('test', 'a', 'b', 'c');
|
||||||
|
subscribe.callCount.should.equal(1);
|
||||||
|
subscribe.args[0][0].should.equal(bus);
|
||||||
|
subscribe.args[0][1].should.equal('a');
|
||||||
|
subscribe.args[0][2].should.equal('b');
|
||||||
|
subscribe.args[0][3].should.equal('c');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#unsubscribe', function() {
|
||||||
|
it('will call modules unsubscribe function with the correct arguments', function() {
|
||||||
|
var unsubscribe = sinon.spy();
|
||||||
|
var db = {
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
getPublishEvents: sinon.stub().returns([
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
scope: this,
|
||||||
|
unsubscribe: unsubscribe
|
||||||
|
}
|
||||||
|
])
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
var bus = new Bus({db: db});
|
||||||
|
bus.unsubscribe('test', 'a', 'b', 'c');
|
||||||
|
unsubscribe.callCount.should.equal(1);
|
||||||
|
unsubscribe.args[0][0].should.equal(bus);
|
||||||
|
unsubscribe.args[0][1].should.equal('a');
|
||||||
|
unsubscribe.args[0][2].should.equal('b');
|
||||||
|
unsubscribe.args[0][3].should.equal('c');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
var should = require('chai').should();
|
var should = require('chai').should();
|
||||||
var sinon = require('sinon');
|
var sinon = require('sinon');
|
||||||
var chainlib = require('chainlib');
|
|
||||||
var levelup = chainlib.deps.levelup;
|
|
||||||
var bitcoindjs = require('../../');
|
var bitcoindjs = require('../../');
|
||||||
var AddressModule = bitcoindjs.modules.AddressModule;
|
var AddressModule = bitcoindjs.modules.AddressModule;
|
||||||
var blockData = require('../data/livenet-345003.json');
|
var blockData = require('../data/livenet-345003.json');
|
||||||
@ -21,6 +19,40 @@ describe('AddressModule', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#getPublishEvents', function() {
|
||||||
|
it('will return an array of publish event objects', function() {
|
||||||
|
var am = new AddressModule({});
|
||||||
|
am.subscribe = sinon.spy();
|
||||||
|
am.unsubscribe = sinon.spy();
|
||||||
|
var events = am.getPublishEvents();
|
||||||
|
|
||||||
|
var callCount = 0;
|
||||||
|
function testName(event, name) {
|
||||||
|
event.name.should.equal(name);
|
||||||
|
event.scope.should.equal(am);
|
||||||
|
var emitter = new EventEmitter();
|
||||||
|
var addresses = [];
|
||||||
|
event.subscribe(emitter, addresses);
|
||||||
|
am.subscribe.callCount.should.equal(callCount + 1);
|
||||||
|
am.subscribe.args[callCount][0].should.equal(name);
|
||||||
|
am.subscribe.args[callCount][1].should.equal(emitter);
|
||||||
|
am.subscribe.args[callCount][2].should.equal(addresses);
|
||||||
|
am.subscribe.thisValues[callCount].should.equal(am);
|
||||||
|
event.unsubscribe(emitter, addresses);
|
||||||
|
am.unsubscribe.callCount.should.equal(callCount + 1);
|
||||||
|
am.unsubscribe.args[callCount][0].should.equal(name);
|
||||||
|
am.unsubscribe.args[callCount][1].should.equal(emitter);
|
||||||
|
am.unsubscribe.args[callCount][2].should.equal(addresses);
|
||||||
|
am.unsubscribe.thisValues[callCount].should.equal(am);
|
||||||
|
callCount++;
|
||||||
|
}
|
||||||
|
events.forEach(function(event) {
|
||||||
|
testName(event, event.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('#blockHandler', function() {
|
describe('#blockHandler', function() {
|
||||||
var block = bitcore.Block.fromString(blockData);
|
var block = bitcore.Block.fromString(blockData);
|
||||||
var db = {
|
var db = {
|
||||||
@ -124,6 +156,129 @@ describe('AddressModule', function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('will call event handlers', function() {
|
||||||
|
var block = bitcore.Block.fromString(blockData);
|
||||||
|
var db = {
|
||||||
|
getTransactionsFromBlock: function() {
|
||||||
|
return block.transactions.slice(0, 8);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var am = new AddressModule({db: db, network: 'livenet'});
|
||||||
|
am.transactionEventHandler = sinon.spy();
|
||||||
|
am.balanceEventHandler = sinon.spy();
|
||||||
|
am.blockHandler(
|
||||||
|
{
|
||||||
|
__height: 345003,
|
||||||
|
timestamp: new Date(1424836934000)
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
function(err) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
am.transactionEventHandler.callCount.should.equal(11);
|
||||||
|
am.balanceEventHandler.callCount.should.equal(11);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#transactionEventHandler', function() {
|
||||||
|
it('will emit a transaction if there is a subscriber', function(done) {
|
||||||
|
var am = new AddressModule({});
|
||||||
|
var emitter = new EventEmitter();
|
||||||
|
am.subscriptions.transaction = {
|
||||||
|
'1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N': [emitter]
|
||||||
|
};
|
||||||
|
var block = {};
|
||||||
|
var tx = {};
|
||||||
|
emitter.on('transaction', function(address, t, b) {
|
||||||
|
address.should.equal('1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N');
|
||||||
|
t.should.equal(tx);
|
||||||
|
b.should.equal(block);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
am.transactionEventHandler(block, '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N', tx);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#balanceEventHandler', function() {
|
||||||
|
it('will emit a balance if there is a subscriber', function(done) {
|
||||||
|
var am = new AddressModule({});
|
||||||
|
var emitter = new EventEmitter();
|
||||||
|
am.subscriptions.balance = {
|
||||||
|
'1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N': [emitter]
|
||||||
|
};
|
||||||
|
var block = {};
|
||||||
|
var balance = 1000;
|
||||||
|
am.getBalance = sinon.stub().callsArgWith(2, null, balance);
|
||||||
|
emitter.on('balance', function(address, bal, b) {
|
||||||
|
address.should.equal('1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N');
|
||||||
|
bal.should.equal(balance);
|
||||||
|
b.should.equal(block);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
am.balanceEventHandler(block, '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#subscribe', function() {
|
||||||
|
it('will add emitters to the subscribers array (transaction)', function() {
|
||||||
|
var am = new AddressModule({});
|
||||||
|
var emitter = new EventEmitter();
|
||||||
|
|
||||||
|
var address = '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N';
|
||||||
|
var name = 'transaction';
|
||||||
|
am.subscribe(name, emitter, [address]);
|
||||||
|
am.subscriptions.transaction[address].should.deep.equal([emitter]);
|
||||||
|
|
||||||
|
var address2 = '1KiW1A4dx1oRgLHtDtBjcunUGkYtFgZ1W';
|
||||||
|
am.subscribe(name, emitter, [address2]);
|
||||||
|
am.subscriptions.transaction[address2].should.deep.equal([emitter]);
|
||||||
|
|
||||||
|
var emitter2 = new EventEmitter();
|
||||||
|
am.subscribe(name, emitter2, [address]);
|
||||||
|
am.subscriptions.transaction[address].should.deep.equal([emitter, emitter2]);
|
||||||
|
});
|
||||||
|
it('will add an emitter to the subscribers array (balance)', function() {
|
||||||
|
var am = new AddressModule({});
|
||||||
|
var emitter = new EventEmitter();
|
||||||
|
var name = 'balance';
|
||||||
|
var address = '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N';
|
||||||
|
am.subscribe(name, emitter, [address]);
|
||||||
|
am.subscriptions.balance[address].should.deep.equal([emitter]);
|
||||||
|
|
||||||
|
var address2 = '1KiW1A4dx1oRgLHtDtBjcunUGkYtFgZ1W';
|
||||||
|
am.subscribe(name, emitter, [address2]);
|
||||||
|
am.subscriptions.balance[address2].should.deep.equal([emitter]);
|
||||||
|
|
||||||
|
var emitter2 = new EventEmitter();
|
||||||
|
am.subscribe(name, emitter2, [address]);
|
||||||
|
am.subscriptions.balance[address].should.deep.equal([emitter, emitter2]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#unsubscribe', function() {
|
||||||
|
it('will remove emitter from subscribers array (transaction)', function() {
|
||||||
|
var am = new AddressModule({});
|
||||||
|
var emitter = new EventEmitter();
|
||||||
|
var emitter2 = new EventEmitter();
|
||||||
|
var address = '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N';
|
||||||
|
am.subscriptions.transaction[address] = [emitter, emitter2];
|
||||||
|
var name = 'transaction';
|
||||||
|
am.unsubscribe(name, emitter, [address]);
|
||||||
|
am.subscriptions.transaction[address].should.deep.equal([emitter2]);
|
||||||
|
});
|
||||||
|
it('will remove emitter from subscribers array (balance)', function() {
|
||||||
|
var am = new AddressModule({});
|
||||||
|
var emitter = new EventEmitter();
|
||||||
|
var emitter2 = new EventEmitter();
|
||||||
|
var address = '1DzjESe6SLmAKVPLFMj6Sx1sWki3qt5i8N';
|
||||||
|
var name = 'balance';
|
||||||
|
am.subscriptions.balance[address] = [emitter, emitter2];
|
||||||
|
am.unsubscribe(name, emitter, [address]);
|
||||||
|
am.subscriptions.balance[address].should.deep.equal([emitter2]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#getBalance', function() {
|
describe('#getBalance', function() {
|
||||||
|
|||||||
@ -31,6 +31,15 @@ var Node = proxyquire('../lib/node', {
|
|||||||
chainlib.Node = OriginalNode;
|
chainlib.Node = OriginalNode;
|
||||||
|
|
||||||
describe('Bitcoind Node', function() {
|
describe('Bitcoind Node', function() {
|
||||||
|
describe('#openBus', function() {
|
||||||
|
it('will create a new bus', function() {
|
||||||
|
var node = new Node({});
|
||||||
|
var db = {};
|
||||||
|
node.db = db;
|
||||||
|
var bus = node.openBus();
|
||||||
|
bus.db.should.equal(db);
|
||||||
|
});
|
||||||
|
});
|
||||||
describe('#_loadConfiguration', function() {
|
describe('#_loadConfiguration', function() {
|
||||||
it('should call the necessary methods', function() {
|
it('should call the necessary methods', function() {
|
||||||
var node = new Node({});
|
var node = new Node({});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user