From 15fe096a072a99228ec524e956c6d27147a6f5f9 Mon Sep 17 00:00:00 2001 From: Chris Kleeschulte Date: Thu, 9 Nov 2017 11:42:57 -0500 Subject: [PATCH] wip on changing subsciption endpoints. --- lib/blocks.js | 2 +- lib/index.js | 8 +- regtest/block.js | 586 +++++++++++++++++++-------------------- regtest/subscriptions.js | 498 +++++++++++++++++++++++++++++++++ 4 files changed, 782 insertions(+), 312 deletions(-) create mode 100644 regtest/subscriptions.js diff --git a/lib/blocks.js b/lib/blocks.js index 89d6113..87b5c41 100644 --- a/lib/blocks.js +++ b/lib/blocks.js @@ -76,7 +76,7 @@ BlockController.prototype.block = function(req, res, next) { } if (!block) { - return self.common.handleErrors(null, res); + return self.common.handleErrors(new Error('block not in index'), res); } self._header.getBlockHeader(hash, function(err, info) { diff --git a/lib/index.js b/lib/index.js index c541c70..41a09c7 100644 --- a/lib/index.js +++ b/lib/index.js @@ -100,11 +100,11 @@ InsightAPI.prototype.start = function(callback) { this._bus = this.node.openBus({remoteAddress: 'localhost-insight-api'}); } - this._bus.on('p2p/transaction', this.transactionEventHandler.bind(this)); - this._bus.subscribe('p2p/transaction'); + this._bus.on('mempool/transaction', this.transactionEventHandler.bind(this)); + this._bus.subscribe('mempool/transaction'); - this._bus.on('p2p/block', this.blockEventHandler.bind(this)); - this._bus.subscribe('p2p/block'); + this._bus.on('block/block', this.blockEventHandler.bind(this)); + this._bus.subscribe('block/block'); callback(); diff --git a/regtest/block.js b/regtest/block.js index fa6b134..7ea6320 100644 --- a/regtest/block.js +++ b/regtest/block.js @@ -8,12 +8,12 @@ var fs = require('fs'); var async = require('async'); var RPC = require('bitcoind-rpc'); var http = require('http'); +var bitcore = require('bitcore-lib'); +var exec = require('child_process').exec; +var bitcore = require('bitcore-lib'); +var Block = bitcore.Block; -var rpc1Address; -var rpc2Address; -var tx1; -var tx2; -var block; +var blocksGenerated = 0; var rpcConfig = { protocol: 'http', @@ -24,12 +24,12 @@ var rpcConfig = { rejectUnauthorized: false }; -var rpc1 = new RPC(rpcConfig); -rpcConfig.port++; -var rpc2 = new RPC(rpcConfig); +var rpc = new RPC(rpcConfig); var debug = true; var bitcoreDataDir = '/tmp/bitcore'; -var bitcoinDataDirs = ['/tmp/bitcoin1', '/tmp/bitcoin2']; +var bitcoinDir = '/tmp/bitcoin'; +var bitcoinDataDirs = [ bitcoinDir ]; +var blocks= []; var bitcoin = { args: { @@ -39,7 +39,7 @@ var bitcoin = { server: 1, rpcuser: 'local', rpcpassword: 'localtest', - //printtoconsole: 1 + //printtoconsole: 1, rpcport: 58332, }, datadir: null, @@ -75,6 +75,9 @@ var bitcore = { }, 'insight-api': { 'routePrefix': 'api' + }, + 'block': { + 'readAheadBlockCount': 1 } } } @@ -86,88 +89,186 @@ var bitcore = { }, opts: { cwd: bitcoreDataDir }, datadir: bitcoreDataDir, - exec: 'bitcored', //if this isn't on your PATH, then provide the absolute path, e.g. /usr/local/bin/bitcored + exec: 'bitcored', //if this isn't on your PATH, then provide the absolute path, e.g. /usr/local/bin/bitcored args: ['start'], process: null }; -var startBitcoind = function(count, callback) { +var request = function(httpOpts, callback) { + + var request = http.request(httpOpts, function(res) { + + if (res.statusCode !== 200 && res.statusCode !== 201) { + return callback('Error from bitcore-node webserver: ' + res.statusCode); + } + + var resError; + var resData = ''; + + res.on('error', function(e) { + resError = e; + }); + + res.on('data', function(data) { + resData += data; + }); + + res.on('end', function() { + + if (resError) { + return callback(resError); + } + var data = JSON.parse(resData); + callback(null, data); + + }); + + }); + + request.on('error', function(err) { + callback(err); + }); + + if (httpOpts.body) { + request.write(httpOpts.body); + } else { + request.write(''); + } + request.end(); +}; + +var waitForBlocksGenerated = function(callback) { + + var httpOpts = { + hostname: 'localhost', + port: 53001, + path: '/api/status', + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }; + + async.retry({ interval: 1000, times: 100 }, function(next) { + + request(httpOpts, function(err, data) { + if (err) { + return next(err); + } + if (data.info.blocks !== blocksGenerated) { + return next(data); + } + next(); + }); + + }, callback); +}; + +var resetDirs = function(dirs, callback) { + + async.each(dirs, function(dir, next) { + + rimraf(dir, function(err) { + + if(err) { + return next(err); + } + + mkdirp(dir, next); + + }); + + }, callback); + +}; + +var startBitcoind = function(callback) { + + var args = bitcoin.args; + var argList = Object.keys(args).map(function(key) { + return '-' + key + '=' + args[key]; + }); + + var bitcoinProcess = spawn(bitcoin.exec, argList, bitcoin.opts); + bitcoin.processes.push(bitcoinProcess); + + bitcoinProcess.stdout.on('data', function(data) { + + if (debug) { + process.stdout.write(data.toString()); + } + + }); + + bitcoinProcess.stderr.on('data', function(data) { + + if (debug) { + process.stderr.write(data.toString()); + } + + }); + + callback(); +}; + + +var reportBitcoindsStarted = function() { + var pids = bitcoin.processes.map(function(process) { + return process.pid; + }); + + console.log(pids.length + ' bitcoind\'s started at pid(s): ' + pids); +}; + +var startBitcoinds = function(datadirs, callback) { var listenCount = 0; - async.timesSeries(count, function(n, next) { - - var datadir = bitcoinDataDirs.shift(); + async.eachSeries(datadirs, function(datadir, next) { bitcoin.datadir = datadir; bitcoin.args.datadir = datadir; if (listenCount++ > 0) { bitcoin.args.listen = 0; - bitcoin.args.rpcport++; + bitcoin.args.rpcport = bitcoin.args.rpcport + 1; bitcoin.args.connect = '127.0.0.1'; } - rimraf(datadir, function(err) { + startBitcoind(next); - if(err) { - return next(err); - } - - mkdirp(datadir, function(err) { - - if(err) { - return next(err); - } - - var args = bitcoin.args; - var argList = Object.keys(args).map(function(key) { - return '-' + key + '=' + args[key]; - }); - - var bitcoinProcess = spawn(bitcoin.exec, argList, bitcoin.opts); - bitcoin.processes.push(bitcoinProcess); - - bitcoinProcess.stdout.on('data', function(data) { - - if (debug) { - process.stdout.write(data.toString()); - } - - }); - - bitcoinProcess.stderr.on('data', function(data) { - - if (debug) { - process.stderr.write(data.toString()); - } - - }); - - next(); - - }); - - }); }, function(err) { - - if (err) { - return callback(err); - } - - var pids = bitcoin.processes.map(function(process) { - return process.pid; - }); - - console.log(count + ' bitcoind\'s started at pid(s): ' + pids); - callback(); + if (err) { + return callback(err); + } + reportBitcoindsStarted(); + callback(); }); }; +var waitForBitcoinReady = function(rpc, callback) { + async.retry({ interval: 1000, times: 1000 }, function(next) { + rpc.getInfo(function(err) { + if (err) { + return next(err); + } + next(); + }); + }, function(err) { + if (err) { + return callback(err); + } + setTimeout(callback, 2000); + }); +}; var shutdownBitcoind = function(callback) { - bitcoin.processes.forEach(function(process) { - process.kill(); - }); + var process; + do { + process = bitcoin.processes.shift(); + if (process) { + process.kill(); + } + } while(process); setTimeout(callback, 3000); }; @@ -178,98 +279,25 @@ var shutdownBitcore = function(callback) { callback(); }; - -var buildInitialChain = function(callback) { - async.waterfall([ - function(next) { - console.log('checking to see if bitcoind\'s are connected to each other.'); - rpc1.getinfo(function(err, res) { - if (err || res.result.connections !== 1) { - next(err || new Error('bitcoind\'s not connected to each other.')); - } - next(); - }); - }, - function(next) { - console.log('generating 101 blocks'); - rpc1.generate(101, next); - }, - function(res, next) { - console.log('getting new address from rpc2'); - rpc2.getNewAddress(function(err, res) { - if (err) { - return next(err); - } - rpc2Address = res.result; - console.log(rpc2Address); - next(null, rpc2Address); - }); - }, - function(addr, next) { - rpc1.sendToAddress(rpc2Address, 25, next); - }, - function(res, next) { - tx1 = res.result; - console.log('TXID: ' + res.result); - console.log('generating 7 blocks'); - rpc1.generate(7, next); - }, - function(res, next) { - block = res.result[res.result.length - 1]; - rpc2.getBalance(function(err, res) { - console.log(res); - next(); - }); - }, - function(next) { - console.log('getting new address from rpc1'); - rpc1.getNewAddress(function(err, res) { - if (err) { - return next(err); - } - rpc1Address = res.result; - next(null, rpc1Address); - }); - }, - function(addr, next) { - rpc2.sendToAddress(rpc1Address, 20, next); - }, - function(res, next) { - tx2 = res.result; - console.log('sending from rpc2Address TXID: ', res); - console.log('generating 6 blocks'); - rpc2.generate(6, next); - } - ], function(err) { - - if (err) { - return callback(err); - } - rpc1.getInfo(function(err, res) { - console.log(res); - callback(); - }); - }); - +var writeBitcoreConf = function() { + fs.writeFileSync(bitcore.configFile.file, JSON.stringify(bitcore.configFile.conf)); }; var startBitcore = function(callback) { - rimraf(bitcoreDataDir, function(err) { - - if(err) { - return callback(err); - } - - mkdirp(bitcoreDataDir, function(err) { - - if(err) { - return callback(err); - } - - fs.writeFileSync(bitcore.configFile.file, JSON.stringify(bitcore.configFile.conf)); - - var args = bitcore.args; + var args = bitcore.args; + console.log('Using bitcored from: '); + async.series([ + function(next) { + exec('which bitcored', function(err, stdout, stderr) { + if(err) { + return next(err); + } + console.log(stdout.toString('hex'), stderr.toString('hex')); + next(); + }); + }, + function(next) { bitcore.process = spawn(bitcore.exec, args, bitcore.opts); bitcore.process.stdout.on('data', function(data) { @@ -287,11 +315,9 @@ var startBitcore = function(callback) { }); - callback(); - }); - - }); - + waitForBlocksGenerated(next); + } + ], callback); }; @@ -303,24 +329,40 @@ describe('Block', function() { async.series([ function(next) { - startBitcoind(2, next); + console.log('step 0: setting up directories.'); + var dirs = bitcoinDataDirs.concat([bitcoreDataDir]); + resetDirs(dirs, function(err) { + if (err) { + return next(err); + } + writeBitcoreConf(); + next(); + }); }, function(next) { - setTimeout(function() { - buildInitialChain(next); - }, 8000); + startBitcoinds(bitcoinDataDirs, function(err) { + if (err) { + return next(err); + } + waitForBitcoinReady(rpc, function(err) { + if (err) { + return next(err); + } + blocksGenerated += 10; + rpc.generate(10, function(err, res) { + if (err) { + return next(err); + } + blocks = res.result; + next(); + }); + }); + }); }, function(next) { - setTimeout(function() { - startBitcore(next); - }, 6000); + startBitcore(next); } - ], function(err) { - if (err) { - return done(err); - } - setTimeout(done, 2000); - }); + ], done); }); @@ -332,169 +374,99 @@ describe('Block', function() { it('should get blocks: /blocks', function(done) { - var request = http.request('http://localhost:53001/api/blocks', function(res) { + var httpOpts = { + hostname: 'localhost', + port: 53001, + path: 'http://localhost:53001/api/blocks', + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }; - var error; - if (res.statusCode !== 200 && res.statusCode !== 201) { - - if (error) { - return; - } - - return done('Error from bitcore-node webserver: ' + res.statusCode); + request(httpOpts, function(err, data) { + if(err) { + return done(err); } - var resError; - var resData = ''; - - res.on('error', function(e) { - resError = e; - }); - - res.on('data', function(data) { - resData += data; - }); - - res.on('end', function() { - if (error) { - return; - } - var data = JSON.parse(resData); - expect(data.length).to.equal(114); - done(); - }); - + expect(data.length).to.equal(10); + expect(data.blocks.length).to.equal(10); + done(); }); - request.write(''); - request.end(); + }); it('should get a block: /block/:hash', function(done) { - var request = http.request('http://localhost:53001/api/block/' + block, function(res) { + var httpOpts = { + hostname: 'localhost', + port: 53001, + path: 'http://localhost:53001/api/block/' + blocks[0], + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }; - var error; - if (res.statusCode !== 200 && res.statusCode !== 201) { - - if (error) { - return; - } - - return done('Error from bitcore-node webserver: ' + res.statusCode); + request(httpOpts, function(err, data) { + if(err) { + return done(err); } - var resError; - var resData = ''; - - res.on('error', function(e) { - resError = e; - }); - - res.on('data', function(data) { - resData += data; - }); - - res.on('end', function() { - if (error) { - return; - } - var data = JSON.parse(resData); - expect(data.hash).to.equal(block); - done(); - }); - + expect(data.hash).to.equal(blocks[0]); + expect(data.height).to.equal(1); + done(); }); - request.write(''); - request.end(); }); it('should get a block-index: /block-index/:height', function(done) { - var request = http.request('http://localhost:53001/api/block-index/' + '108', function(res) { + var httpOpts = { + hostname: 'localhost', + port: 53001, + path: 'http://localhost:53001/api/block-index/7', + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }; - var error; - if (res.statusCode !== 200 && res.statusCode !== 201) { - - if (error) { - return; - } - - return done('Error from bitcore-node webserver: ' + res.statusCode); + request(httpOpts, function(err, data) { + if(err) { + return done(err); } - var resError; - var resData = ''; - - res.on('error', function(e) { - resError = e; - }); - - res.on('data', function(data) { - resData += data; - }); - - res.on('end', function() { - if (error) { - return; - } - var data = JSON.parse(resData); - console.log(resData); - expect(data.blockHash).to.equal(block); - done(); - }); - + expect(data.blockHash).to.equal(blocks[6]); + done(); }); - request.write(''); - request.end(); }); it('should get a raw block: /rawblock/:hash', function(done) { - var request = http.request('http://localhost:53001/api/rawblock/' + block, function(res) { + var httpOpts = { + hostname: 'localhost', + port: 53001, + path: 'http://localhost:53001/api/rawblock/' + blocks[4], + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }; - var error; - if (res.statusCode !== 200 && res.statusCode !== 201) { - - if (error) { - return; - } - - return done('Error from bitcore-node webserver: ' + res.statusCode); + request(httpOpts, function(err, data) { + if(err) { + return done(err); } - var resError; - var resData = ''; - - res.on('error', function(e) { - resError = e; - }); - - res.on('data', function(data) { - resData += data; - }); - - res.on('end', function() { - if (error) { - return; - } - var data = JSON.parse(resData); - console.log(resData); - expect(data.rawblock).to.not.be.null; - done(); - }); - + var block = new Block(new Buffer(data.rawblock, 'hex')); + expect(block.hash).to.equal(blocks[4]); + done(); }); - - request.write(''); - request.end(); }); + }); - - - - diff --git a/regtest/subscriptions.js b/regtest/subscriptions.js new file mode 100644 index 0000000..3c8e86a --- /dev/null +++ b/regtest/subscriptions.js @@ -0,0 +1,498 @@ +'use strict'; + +var expect = require('chai').expect; +var spawn = require('child_process').spawn; +var rimraf = require('rimraf'); +var mkdirp = require('mkdirp'); +var fs = require('fs'); +var async = require('async'); +var RPC = require('bitcoind-rpc'); +var http = require('http'); +var bitcore = require('bitcore-lib'); +var exec = require('child_process').exec; +var bitcore = require('bitcore-lib'); +var Block = bitcore.Block; +var PrivateKey = bitcore.PrivateKey; +var Transaction = bitcore.Transaction; +var io = require('socket.io-client'); + +/* + + Theory behind this test. + + We want to connect a web socket and subscribe to both new txs and blocks. + + When a new tx or block comes in, we want to immediately call the api for that resource. + + +*/ +var blocksGenerated = 0; + +var rpcConfig = { + protocol: 'http', + user: 'local', + pass: 'localtest', + host: '127.0.0.1', + port: 58332, + rejectUnauthorized: false +}; + +var rpc = new RPC(rpcConfig); +var debug = true; +var bitcoreDataDir = '/tmp/bitcore'; +var bitcoinDir = '/tmp/bitcoin'; +var bitcoinDataDirs = [ bitcoinDir ]; +var blocks= []; +var pks = []; +var initialTx; +var startingPk; + +var bitcoin = { + args: { + datadir: null, + listen: 1, + regtest: 1, + server: 1, + rpcuser: 'local', + rpcpassword: 'localtest', + //printtoconsole: 1, + rpcport: 58332, + }, + datadir: null, + exec: 'bitcoind', //if this isn't on your PATH, then provide the absolute path, e.g. /usr/local/bin/bitcoind + processes: [] +}; + +var bitcore = { + configFile: { + file: bitcoreDataDir + '/bitcore-node.json', + conf: { + network: 'regtest', + port: 53001, + datadir: bitcoreDataDir, + services: [ + 'p2p', + 'db', + 'header', + 'block', + 'address', + 'transaction', + 'mempool', + 'web', + 'insight-api', + 'fee', + 'timestamp' + ], + servicesConfig: { + 'p2p': { + 'peers': [ + { 'ip': { 'v4': '127.0.0.1' }, port: 18444 } + ] + }, + 'insight-api': { + 'routePrefix': 'api' + }, + 'block': { + 'readAheadBlockCount': 1 + } + } + } + }, + httpOpts: { + protocol: 'http:', + hostname: 'localhost', + port: 53001, + }, + opts: { cwd: bitcoreDataDir }, + datadir: bitcoreDataDir, + exec: 'bitcored', //if this isn't on your PATH, then provide the absolute path, e.g. /usr/local/bin/bitcored + args: ['start'], + process: null +}; + +var request = function(httpOpts, callback) { + + var request = http.request(httpOpts, function(res) { + + if (res.statusCode !== 200 && res.statusCode !== 201) { + return callback('Error from bitcore-node webserver: ' + res.statusCode); + } + + var resError; + var resData = ''; + + res.on('error', function(e) { + resError = e; + }); + + res.on('data', function(data) { + resData += data; + }); + + res.on('end', function() { + + if (resError) { + return callback(resError); + } + var data = JSON.parse(resData); + callback(null, data); + + }); + + }); + + request.on('error', function(err) { + callback(err); + }); + + if (httpOpts.body) { + request.write(httpOpts.body); + } else { + request.write(''); + } + request.end(); +}; + +var waitForBlocksGenerated = function(callback) { + + var httpOpts = { + hostname: 'localhost', + port: 53001, + path: '/api/status', + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }; + + async.retry({ interval: 1000, times: 100 }, function(next) { + + request(httpOpts, function(err, data) { + if (err) { + return next(err); + } + if (data.info.blocks !== blocksGenerated) { + return next(data); + } + next(); + }); + + }, callback); +}; + +var resetDirs = function(dirs, callback) { + + async.each(dirs, function(dir, next) { + + rimraf(dir, function(err) { + + if(err) { + return next(err); + } + + mkdirp(dir, next); + + }); + + }, callback); + +}; + +var startBitcoind = function(callback) { + + var args = bitcoin.args; + var argList = Object.keys(args).map(function(key) { + return '-' + key + '=' + args[key]; + }); + + var bitcoinProcess = spawn(bitcoin.exec, argList, bitcoin.opts); + bitcoin.processes.push(bitcoinProcess); + + bitcoinProcess.stdout.on('data', function(data) { + + if (debug) { + process.stdout.write(data.toString()); + } + + }); + + bitcoinProcess.stderr.on('data', function(data) { + + if (debug) { + process.stderr.write(data.toString()); + } + + }); + + callback(); +}; + + +var reportBitcoindsStarted = function() { + var pids = bitcoin.processes.map(function(process) { + return process.pid; + }); + + console.log(pids.length + ' bitcoind\'s started at pid(s): ' + pids); +}; + +var startBitcoinds = function(datadirs, callback) { + + var listenCount = 0; + async.eachSeries(datadirs, function(datadir, next) { + + bitcoin.datadir = datadir; + bitcoin.args.datadir = datadir; + + if (listenCount++ > 0) { + bitcoin.args.listen = 0; + bitcoin.args.rpcport = bitcoin.args.rpcport + 1; + bitcoin.args.connect = '127.0.0.1'; + } + + startBitcoind(next); + + }, function(err) { + if (err) { + return callback(err); + } + reportBitcoindsStarted(); + callback(); + }); +}; + +var waitForBitcoinReady = function(rpc, callback) { + async.retry({ interval: 1000, times: 1000 }, function(next) { + rpc.getInfo(function(err) { + if (err) { + return next(err); + } + next(); + }); + }, function(err) { + if (err) { + return callback(err); + } + setTimeout(callback, 2000); + }); +}; + +var shutdownBitcoind = function(callback) { + var process; + do { + process = bitcoin.processes.shift(); + if (process) { + process.kill(); + } + } while(process); + setTimeout(callback, 3000); +}; + +var shutdownBitcore = function(callback) { + if (bitcore.process) { + bitcore.process.kill(); + } + callback(); +}; + +var writeBitcoreConf = function() { + fs.writeFileSync(bitcore.configFile.file, JSON.stringify(bitcore.configFile.conf)); +}; + +var startBitcore = function(callback) { + + var args = bitcore.args; + console.log('Using bitcored from: '); + async.series([ + function(next) { + exec('which bitcored', function(err, stdout, stderr) { + if(err) { + return next(err); + } + console.log(stdout.toString('hex'), stderr.toString('hex')); + next(); + }); + }, + function(next) { + bitcore.process = spawn(bitcore.exec, args, bitcore.opts); + + bitcore.process.stdout.on('data', function(data) { + + if (debug) { + process.stdout.write(data.toString()); + } + + }); + bitcore.process.stderr.on('data', function(data) { + + if (debug) { + process.stderr.write(data.toString()); + } + + }); + + waitForBlocksGenerated(next); + } + ], callback); + +}; + +var makeLocalPrivateKeys = function(num) { + if (!num) { + num = 20; + } + for(var i = 0; i < num; i++) { + pks.push(new PrivateKey('testnet')); + } +}; + +var getFirstIncomingFunds = function(callback) { + initialTx = new Transaction(); + rpc.listUnspent(function(err, res) { + if (err) { + return callback(err); + } + var unspent = res.result[0]; + rpc.dumpPrivKey(unspent.address, function(err, res) { + if (err) { + return callback(err); + } + startingPk = new PrivateKey(res.result); + var utxo = { + txId: unspent.txid, + outputIndex: unspent.vout, + script: unspent.scriptPubKey, + satoshis: unspent.amount * 1e8, + address: unspent.address + }; + initialTx.from(utxo).to(pks[0].toAddress(), 20*1e8).change(startingPk.toAddress()).fee(50000).sign(startingPk); + rpc.sendRawTransaction(initialTx.serialize(), callback); + }); + }); +}; + +var sendTx = function(callback) { + var index; + for(var i = 0; i < initialTx.outputs.length; i++) { + if (initialTx.outputs[i].script.toAddress().toString() === pks[0].toAddress().toString()) { + index = i; + break; + } + } + var utxo = { + address: pks[0].toAddress().toString(), + script: initialTx.outputs[index].script.toHex(), + satoshis: initialTx.outputs[index].satoshis, + outputIndex: index, + txid: initialTx.hash + }; + + txs.push(new Transaction() + .from(utxo) + .to(pks[1].toAddress(), 1e8) + .change(startingPk.toAddress()).fee(50000).sign(pks[0])); + + var body = '{"rawtx":"' + txs[0].serialize() + '"}'; + + var httpOpts = { + hostname: 'localhost', + port: 53001, + path: 'http://localhost:53001/api/tx/send', + method: 'POST', + body: body, + headers: { + 'Content-Type': 'application/json', + 'Content-Length': body.length + }, + }; + + request(httpOpts, function(err, data) { + if (err) { + return callback(err); + } + + txids.push(data.txid); + callback(); + + }); + +}; +describe('Subscriptions', function() { + + this.timeout(60000); + + before(function(done) { + + async.series([ + function(next) { + console.log('step 0: setting up directories.'); + var dirs = bitcoinDataDirs.concat([bitcoreDataDir]); + resetDirs(dirs, function(err) { + if (err) { + return next(err); + } + writeBitcoreConf(); + next(); + }); + }, + function(next) { + console.log('step 1: start bitcoind'); + startBitcoinds(bitcoinDataDirs, function(err) { + if (err) { + return next(err); + } + waitForBitcoinReady(rpc, function(err) { + if (err) { + return next(err); + } + blocksGenerated += 10; + rpc.generate(10, function(err, res) { + if (err) { + return next(err); + } + blocks = res.result; + next(); + }); + }); + }); + }, + function(next) { + console.log('step 2: start bitcore'); + startBitcore(next); + }, + function(next) { + console.log('step 3: make local private keys.'); + makeLocalPrivateKeys(); + }, + function(next) { + console.log('step 4: setup initial tx.'); + getFirstIncomingFunds(next); + } + ], done); + + }); + + after(function(done) { + shutdownBitcore(function() { + shutdownBitcoind(done); + }); + }); + + it('should get transaction after websocket reception of transaction', function(done) { + var socket = io('ws://localhost:53001', { + transports: [ 'websocket' ] + }); + socket.emit('subscribe', 'mempool/transaction'); + // send a transaction + socket.on('message', function(msg) { + console.log(msg); + done(); + }); + sendTx(); + }); + + it('should get block after websocket reception of block', function(done) { + done(); + }); + +});