Ryan X. Charles
11 years ago
15 changed files with 806 additions and 39388 deletions
File diff suppressed because one or more lines are too long
@ -0,0 +1,29 @@ |
|||
'use strict'; |
|||
|
|||
var run = function() { |
|||
// Replace '../bitcore' with 'bitcore' if you use this code elsewhere.
|
|||
var bitcore = require('../bitcore'); |
|||
var NetworkMonitor = bitcore.NetworkMonitor; |
|||
|
|||
var config = { |
|||
networkName: 'testnet', |
|||
host: 'localhost', |
|||
port: 18333 |
|||
}; |
|||
|
|||
|
|||
var nm = new NetworkMonitor.create(config); |
|||
// monitor incoming transactions to http://tpfaucet.appspot.com/ donation address
|
|||
nm.incoming('msj42CCGruhRsFrGATiUuh25dtxYtnpbTx', function(tx) { |
|||
console.log('Donation to tpfaucet! '+JSON.stringify(tx.getStandardizedObject())); |
|||
}); |
|||
|
|||
// connect to bitcoin network and start listening
|
|||
nm.start(); |
|||
|
|||
}; |
|||
|
|||
module.exports.run = run; |
|||
if (require.main === module) { |
|||
run(); |
|||
} |
@ -0,0 +1,82 @@ |
|||
var log = require('../util/log'); |
|||
var networks = require('../networks'); |
|||
var Address = require('./Address'); |
|||
var Peer = require('./Peer'); |
|||
var PeerManager = require('./PeerManager'); |
|||
var util = require('util'); |
|||
var EventEmitter = require('events').EventEmitter; |
|||
var preconditions = require('preconditions').singleton(); |
|||
|
|||
var NetworkMonitor = function(peerman) { |
|||
preconditions.checkArgument(peerman); |
|||
this.peerman = peerman; |
|||
this.networkName = peerman.config.network; |
|||
this.init(); |
|||
} |
|||
|
|||
util.inherits(NetworkMonitor, EventEmitter); |
|||
|
|||
NetworkMonitor.create = function(config) { |
|||
var peerman = new PeerManager({ |
|||
network: config.networkName |
|||
}); |
|||
|
|||
peerman.addPeer(new Peer(config.host, config.port)); |
|||
return new NetworkMonitor(peerman); |
|||
}; |
|||
|
|||
NetworkMonitor.prototype.init = function() { |
|||
var self = this; |
|||
var handleInv = function(info) { |
|||
var invs = info.message.invs; |
|||
info.conn.sendGetData(invs); |
|||
}; |
|||
|
|||
var handleBlock = function(info) { |
|||
self.emit('block', info.message); |
|||
}; |
|||
|
|||
var handleTx = function(info) { |
|||
var tx = info.message.tx; |
|||
self.emit('tx', tx); |
|||
|
|||
var from = tx.getSendingAddresses(self.networkName); |
|||
for (var i = 0; i < from.length; i++) { |
|||
var addr = from[i]; |
|||
self.emit('out:'+addr, tx); |
|||
} |
|||
var to = tx.getReceivingAddresses(self.networkName); |
|||
for (var i = 0; i < to.length; i++) { |
|||
var addr = to[i]; |
|||
self.emit('in:'+addr, tx); |
|||
} |
|||
}; |
|||
|
|||
this.peerman.on('connection', function(conn) { |
|||
if (self.connection) throw new Error('Cant handle more than one connection'); |
|||
self.connection = conn; |
|||
conn.on('inv', handleInv); |
|||
conn.on('block', handleBlock); |
|||
conn.on('tx', handleTx); |
|||
}); |
|||
}; |
|||
|
|||
NetworkMonitor.prototype.incoming = function(addrStr, callback) { |
|||
preconditions.checkArgument(Address.validate(addrStr)); |
|||
this.on('in:'+addrStr, callback); |
|||
}; |
|||
|
|||
NetworkMonitor.prototype.outgoing = function(addrStr, callback) { |
|||
preconditions.checkArgument(Address.validate(addrStr)); |
|||
this.on('out:'+addrStr, callback); |
|||
}; |
|||
|
|||
NetworkMonitor.prototype.start = function() { |
|||
this.peerman.start(); |
|||
}; |
|||
|
|||
NetworkMonitor.prototype.stop = function() { |
|||
this.peerman.stop(); |
|||
}; |
|||
|
|||
module.exports = NetworkMonitor; |
@ -0,0 +1,161 @@ |
|||
'use strict'; |
|||
|
|||
var chai = chai || require('chai'); |
|||
var sinon = sinon || require('sinon'); |
|||
var bitcore = bitcore || require('../bitcore'); |
|||
var Transaction = bitcore.Transaction; |
|||
var NetworkMonitor = bitcore.NetworkMonitor; |
|||
var EventEmitter = require('events').EventEmitter; |
|||
|
|||
var should = chai.should(); |
|||
|
|||
var nop = function() {}; |
|||
|
|||
describe('NetworkMonitor', function() { |
|||
var config = { |
|||
networkName: 'testnet', |
|||
host: 'localhost', |
|||
port: 18333 |
|||
}; |
|||
var fakePM = {}; |
|||
fakePM.on = nop; |
|||
fakePM.config = { |
|||
network: config.networkName |
|||
}; |
|||
it('should initialze the main object', function() { |
|||
should.exist(NetworkMonitor); |
|||
}); |
|||
it('should be able to instanciate', function() { |
|||
var nm = new NetworkMonitor(fakePM); |
|||
should.exist(nm); |
|||
}); |
|||
it('should be able to create instance', function() { |
|||
var nm = new NetworkMonitor.create(config); |
|||
should.exist(nm); |
|||
}); |
|||
it('should be able to start instance', function() { |
|||
var nm = new NetworkMonitor.create(config); |
|||
nm.start.bind(nm).should.not.throw(); |
|||
nm.stop(); |
|||
}); |
|||
it('should be able to stop instance', function() { |
|||
var nm = new NetworkMonitor.create(config); |
|||
nm.start(); |
|||
nm.stop.bind(nm).should.not.throw(); |
|||
}); |
|||
it('should be able to register listeners', function() { |
|||
var nm = new NetworkMonitor.create(config); |
|||
(function() { |
|||
nm.on('block', nop); |
|||
}).should.not.throw(); |
|||
(function() { |
|||
nm.incoming('n2tTCgsJPJBZZEKLiJx9KoU4idJQB37j9E', nop); |
|||
}).should.not.throw(); |
|||
(function() { |
|||
nm.outgoing('n2tTCgsJPJBZZEKLiJx9KoU4idJQB37j9E', nop); |
|||
}).should.not.throw(); |
|||
}); |
|||
var createConnectedNM = function() { |
|||
var nm = new NetworkMonitor.create(config); |
|||
var fakeConnection = new EventEmitter(); |
|||
nm.peerman.emit('connection', fakeConnection); |
|||
return nm; |
|||
}; |
|||
it('should store connection', function() { |
|||
var nm = createConnectedNM(); |
|||
should.exist(nm.connection); |
|||
}); |
|||
describe('block event', function() { |
|||
it('should be called on blocks', function(done) { |
|||
var nm = createConnectedNM(); |
|||
nm.on('block', function(m) { |
|||
should.exist(m); |
|||
done(); |
|||
}); |
|||
nm.connection.emit('block', { |
|||
message: 'test' |
|||
}); |
|||
}); |
|||
}); |
|||
var observedAddress = 'mwABUqsGjjeTgExrBmyyWEErS8yA4QNAUJ'; |
|||
var simulateNetworkTx = function(raw, nm) { |
|||
var tx = new Transaction(); |
|||
tx.parse(new Buffer(raw, 'hex')); |
|||
nm.connection.emit('tx', { |
|||
message: { |
|||
tx: tx |
|||
} |
|||
}); |
|||
return tx; |
|||
}; |
|||
var incomingRaw = '01000000017ee4912333a1add2b03041b7abf4f64c365634a2d31ebfef4f47684c5adcfc49010000006a473044022064e5a4bd31615d184f7c660fcb7e072bfaaf8d87ad8f208ec85276b66420aeb102201c4fe9921495b07492a26648d4b124b346028dbdd91fea1ce3a32a21f1accb31012102749393ba256c17f67ff1c3e7d3ad72e610f07146b2d1d996287b1c500a75062effffffff0200ca9a3b000000001976a914ab9448d3b5adab710665e82506ae5cbd4ba7ba1288acf0bfe71c000000001976a9146c45fa9d90420668f7ff16e33d3d21b0d7e73bc188ac00000000'; |
|||
var unrelatedRaw = '010000000114bae675546f758e0dbab95aa88d4db0c63e26f8fd6cbbce3a4827446d4937cf00000000700048304502201da760691f18a0ab140de1437e4bd29767b74add8cca8e38d46a2f37d9a8188f022100cbf4e121d97b4db846d236957da7fc17fd706ad47b41ae63adf953982e34f70901255121022f58491a833933a9bea80d8e820e66bee91bd8c71bfa972fe70482360b48129951aeffffffff01706f9800000000001976a91400a26ff8123593e10d0a9eba2a74db33cd69299288ac00000000'; |
|||
var outgoingRaw = '0100000001613b50ef601ac068b7805afb8615bb06371881321a478b62d1f52d21f2a8529c000000006b483045022100e3c38e6da99bc8e4b6150404d3afc9ee74b5b48a245311e8fb0e019a3f69570102201eda167b14d675f7b9cf60cf1b0c65b1d66efa4a339743aaec047ce90b92e52e0121031915a253ead0da95c46ff64d07fe4d562a29b7fc211c6a8f49764ac85c039de4ffffffff01f0a29a3b000000001976a914c69536a7d60748bb1953e5e186edf920efa823e388ac00000000'; |
|||
|
|||
describe('tx event', function() { |
|||
it('should be called on network transactions', function() { |
|||
var nm = createConnectedNM(); |
|||
var spy = sinon.spy(); |
|||
nm.on('tx', spy); |
|||
var tx1 = simulateNetworkTx(incomingRaw, nm); |
|||
var tx2 = simulateNetworkTx(unrelatedRaw, nm); |
|||
var tx3 = simulateNetworkTx(outgoingRaw, nm); |
|||
spy.calledWith(tx1).should.equal(true); |
|||
spy.calledWith(tx2).should.equal(true); |
|||
spy.calledWith(tx3).should.equal(true); |
|||
spy.callCount.should.equal(3); |
|||
}); |
|||
}); |
|||
describe('incoming tx event', function() { |
|||
it('should be called on incoming transactions', function() { |
|||
var nm = createConnectedNM(); |
|||
var spy = sinon.spy(); |
|||
nm.incoming(observedAddress, spy); |
|||
var tx = simulateNetworkTx(incomingRaw, nm); |
|||
spy.calledWith(tx).should.equal(true); |
|||
spy.callCount.should.equal(1); |
|||
}); |
|||
it('should not be called on unrelated transactions', function() { |
|||
var nm = createConnectedNM(); |
|||
var spy = sinon.spy(); |
|||
nm.incoming(observedAddress, spy); |
|||
var tx = simulateNetworkTx(unrelatedRaw, nm); |
|||
spy.calledWith(tx).should.equal(false); |
|||
spy.callCount.should.equal(0); |
|||
}); |
|||
it('should not be called on outgoing transactions', function() { |
|||
var nm = createConnectedNM(); |
|||
var spy = sinon.spy(); |
|||
nm.incoming(observedAddress, spy); |
|||
var tx = simulateNetworkTx(outgoingRaw, nm); |
|||
spy.calledWith(tx).should.equal(false); |
|||
spy.callCount.should.equal(0); |
|||
}); |
|||
}); |
|||
describe('outgoing tx event', function() { |
|||
it('should be called on outgoing transactions', function() { |
|||
var nm = createConnectedNM(); |
|||
var spy = sinon.spy(); |
|||
nm.outgoing(observedAddress, spy); |
|||
var tx = simulateNetworkTx(outgoingRaw, nm); |
|||
spy.calledWith(tx).should.equal(true); |
|||
spy.callCount.should.equal(1); |
|||
}); |
|||
it('should not be called on unrelated transactions', function() { |
|||
var nm = createConnectedNM(); |
|||
var spy = sinon.spy(); |
|||
nm.outgoing(observedAddress, spy); |
|||
var tx = simulateNetworkTx(unrelatedRaw, nm); |
|||
spy.calledWith(tx).should.equal(false); |
|||
spy.callCount.should.equal(0); |
|||
}); |
|||
it('should not be called on incoming transactions', function() { |
|||
var nm = createConnectedNM(); |
|||
var spy = sinon.spy(); |
|||
nm.outgoing(observedAddress, spy); |
|||
var tx = simulateNetworkTx(incomingRaw, nm); |
|||
spy.calledWith(tx).should.equal(false); |
|||
spy.callCount.should.equal(0); |
|||
}); |
|||
}); |
|||
}); |
Loading…
Reference in new issue