Added regtests for all routes.

This commit is contained in:
Chris Kleeschulte 2017-08-28 14:00:32 -04:00
parent da8920c4dc
commit 32155cead7
No known key found for this signature in database
GPG Key ID: 33195D27EF6BDB7F
11 changed files with 2961 additions and 103 deletions

299
package-lock.json generated
View File

@ -65,6 +65,12 @@
"integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
"optional": true
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
"base64-arraybuffer": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
@ -143,6 +149,12 @@
"safe-buffer": "5.1.1"
}
},
"bitcoind-rpc": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/bitcoind-rpc/-/bitcoind-rpc-0.7.0.tgz",
"integrity": "sha1-2/YkkmfuMovkjeV3hwQpgAksi/I=",
"dev": true
},
"bitcore-lib": {
"version": "5.0.0-beta.1",
"resolved": "https://registry.npmjs.org/bitcore-lib/-/bitcore-lib-5.0.0-beta.1.tgz",
@ -239,6 +251,95 @@
}
}
},
"bitcore-p2p": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/bitcore-p2p/-/bitcore-p2p-1.1.2.tgz",
"integrity": "sha1-F5J8UiE92vDLQGczMrozleQAi1Q=",
"dev": true,
"requires": {
"bitcore-lib": "0.14.0",
"bloom-filter": "0.2.0",
"buffers": "github:bitpay/node-buffers#04f4c4264e0d105db2b99b786843ed64f23230d8",
"socks5-client": "0.3.6"
},
"dependencies": {
"bitcore-lib": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/bitcore-lib/-/bitcore-lib-0.14.0.tgz",
"integrity": "sha1-IcsjWf57mXo7e3c+t9cnWuN9ZE4=",
"dev": true,
"requires": {
"bn.js": "2.0.4",
"bs58": "2.0.0",
"buffer-compare": "1.0.0",
"elliptic": "3.0.3",
"inherits": "2.0.1",
"lodash": "3.10.1"
},
"dependencies": {
"bn.js": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-2.0.4.tgz",
"integrity": "sha1-Igp81nf38b+pNif/QZN3b+eBlIA=",
"dev": true
},
"bs58": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/bs58/-/bs58-2.0.0.tgz",
"integrity": "sha1-crcTvtIjoKxRi72g484/SBfznrU=",
"dev": true
},
"buffer-compare": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-compare/-/buffer-compare-1.0.0.tgz",
"integrity": "sha1-rKp6lm6Y7un64Usxw5pfFY+zxKI=",
"dev": true
},
"elliptic": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-3.0.3.tgz",
"integrity": "sha1-hlybQgv75VAGuflp+XoNLESWZZU=",
"dev": true,
"requires": {
"bn.js": "2.0.4",
"brorand": "1.0.5",
"hash.js": "1.0.3",
"inherits": "2.0.1"
},
"dependencies": {
"brorand": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz",
"integrity": "sha1-B7VMowKGq9Fxig4qgwgD79yb+gQ=",
"dev": true
},
"hash.js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.3.tgz",
"integrity": "sha1-EzL/ABVsCg/92CNgE9B7d6BFFXM=",
"dev": true,
"requires": {
"inherits": "2.0.1"
}
}
}
},
"inherits": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
"dev": true
},
"lodash": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
"integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
"dev": true
}
}
}
}
},
"bl": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz",
@ -253,6 +354,12 @@
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
"integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE="
},
"bloom-filter": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/bloom-filter/-/bloom-filter-0.2.0.tgz",
"integrity": "sha1-hNY7v5Fy2DA+ZMH/FuudvzOpgaM=",
"dev": true
},
"bn.js": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-2.0.4.tgz",
@ -407,6 +514,16 @@
}
}
},
"brace-expansion": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
"integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
"dev": true,
"requires": {
"balanced-match": "1.0.0",
"concat-map": "0.0.1"
}
},
"brorand": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
@ -441,6 +558,10 @@
"integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
"optional": true
},
"buffers": {
"version": "github:bitpay/node-buffers#04f4c4264e0d105db2b99b786843ed64f23230d8",
"dev": true
},
"callsite": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
@ -503,11 +624,37 @@
"safe-buffer": "5.1.1"
}
},
"cli": {
"version": "0.4.5",
"resolved": "https://registry.npmjs.org/cli/-/cli-0.4.5.tgz",
"integrity": "sha1-ePlIXNFhtWbppsctcXDEJw6B22E=",
"dev": true,
"requires": {
"glob": "7.1.2"
}
},
"cliff": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/cliff/-/cliff-0.1.10.tgz",
"integrity": "sha1-U74z6p9ZvshWCe4wCsQgdgPlIBM=",
"dev": true,
"requires": {
"colors": "1.0.3",
"eyes": "0.1.8",
"winston": "0.8.3"
}
},
"code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
},
"colors": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
"integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=",
"dev": true
},
"component-bind": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
@ -616,6 +763,12 @@
}
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
@ -657,6 +810,12 @@
"sha.js": "2.4.8"
}
},
"cycle": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz",
"integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=",
"dev": true
},
"debug": {
"version": "2.6.8",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
@ -769,12 +928,24 @@
"integrity": "sha1-bDAzIxd6YrGyLAcCefeGEoe2mxo=",
"optional": true
},
"eyes": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
"integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=",
"dev": true
},
"fast-future": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/fast-future/-/fast-future-1.0.2.tgz",
"integrity": "sha1-hDWpqqAteSSNF9cE52JZMB2ZKAo=",
"optional": true
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"gauge": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
@ -797,6 +968,20 @@
"integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=",
"optional": true
},
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"dev": true,
"requires": {
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
"inherits": "2.0.1",
"minimatch": "3.0.4",
"once": "1.4.0",
"path-is-absolute": "1.0.1"
}
},
"has-binary2": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz",
@ -862,6 +1047,16 @@
"resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
"integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
}
},
"inherits": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
@ -873,6 +1068,17 @@
"integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=",
"optional": true
},
"ipv6": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/ipv6/-/ipv6-3.1.3.tgz",
"integrity": "sha1-TZBk+cLa+g3RC4t9dv/KSq0xs7k=",
"dev": true,
"requires": {
"cli": "0.4.5",
"cliff": "0.1.10",
"sprintf": "0.1.5"
}
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
@ -886,6 +1092,12 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
"dev": true
},
"jsonparse": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
@ -972,6 +1184,15 @@
"resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
"integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "1.1.8"
}
},
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
@ -1229,6 +1450,12 @@
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
"optional": true
},
"network-byte-order": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/network-byte-order/-/network-byte-order-0.2.0.tgz",
"integrity": "sha1-asEb9Ev2ENrt2+kKCaXIF8bg0rM=",
"dev": true
},
"node-abi": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.1.0.tgz",
@ -1310,6 +1537,18 @@
"better-assert": "1.0.2"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
"pkginfo": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz",
"integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=",
"dev": true
},
"prebuild-install": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.2.2.tgz",
@ -1808,6 +2047,15 @@
}
}
},
"rimraf": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
"integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=",
"dev": true,
"requires": {
"glob": "7.1.2"
}
},
"ripemd160": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz",
@ -2055,6 +2303,28 @@
}
}
},
"socks5-client": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/socks5-client/-/socks5-client-0.3.6.tgz",
"integrity": "sha1-QgW1eR8t93zwdSciJVj+TkasovE=",
"dev": true,
"requires": {
"ipv6": "3.1.3",
"network-byte-order": "0.2.0"
}
},
"sprintf": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.5.tgz",
"integrity": "sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8=",
"dev": true
},
"stack-trace": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
"integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=",
"dev": true
},
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
@ -2162,6 +2432,35 @@
"string-width": "1.0.2"
}
},
"winston": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/winston/-/winston-0.8.3.tgz",
"integrity": "sha1-ZLar9M0Brcrv1QCTk7HY6L7BnbA=",
"dev": true,
"requires": {
"async": "0.2.10",
"colors": "0.6.2",
"cycle": "1.0.3",
"eyes": "0.1.8",
"isstream": "0.1.2",
"pkginfo": "0.3.1",
"stack-trace": "0.0.10"
},
"dependencies": {
"async": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
"integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=",
"dev": true
},
"colors": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz",
"integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=",
"dev": true
}
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",

View File

@ -21,7 +21,8 @@
"node": ">=8.2.0"
},
"scripts": {
"test": "NODE_ENV=test mocha -R spec --recursive"
"test": "NODE_ENV=test mocha -R spec --recursive",
"regtest": "mocha -R spec regtest"
},
"main": "lib",
"bitcoreNode": "lib",
@ -39,9 +40,13 @@
"request": "^2.64.0"
},
"devDependencies": {
"bitcoind-rpc": "^0.7.0",
"bitcore-p2p": "^1.1.2",
"chai": "^3.5.0",
"mkdirp": "^0.5.1",
"mocha": "^2.4.5",
"proxyquire": "^1.7.2",
"rimraf": "^2.6.1",
"should": "^8.3.1",
"sinon": "^1.10.3"
}

766
regtest/address.js Normal file
View File

@ -0,0 +1,766 @@
'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 rpc1Address;
var rpc2Address;
var rpcConfig = {
protocol: 'http',
user: 'local',
pass: 'localtest',
host: '127.0.0.1',
port: 58332,
rejectUnauthorized: false
};
var rpc1 = new RPC(rpcConfig);
rpcConfig.port++;
var rpc2 = new RPC(rpcConfig);
var debug = true;
var bitcoreDataDir = '/tmp/bitcore';
var bitcoinDataDirs = ['/tmp/bitcoin1', '/tmp/bitcoin2'];
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'
}
}
}
},
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 startBitcoind = function(count, callback) {
var listenCount = 0;
async.timesSeries(count, function(n, next) {
var datadir = bitcoinDataDirs.shift();
bitcoin.datadir = datadir;
bitcoin.args.datadir = datadir;
if (listenCount++ > 0) {
bitcoin.args.listen = 0;
bitcoin.args.rpcport++;
bitcoin.args.connect = '127.0.0.1';
}
rimraf(datadir, function(err) {
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();
});
};
var shutdownBitcoind = function(callback) {
bitcoin.processes.forEach(function(process) {
process.kill();
});
setTimeout(callback, 3000);
};
var shutdownBitcore = function(callback) {
if (bitcore.process) {
bitcore.process.kill();
}
callback();
};
var txid;
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) {
console.log('TXID: ' + res.result);
console.log('generating 6 blocks');
rpc1.generate(7, next);
},
function(res, next) {
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) {
txid = 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 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;
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());
}
});
callback();
});
});
};
describe('Address', function() {
this.timeout(60000);
before(function(done) {
async.series([
function(next) {
startBitcoind(2, next);
},
function(next) {
setTimeout(function() {
buildInitialChain(next);
}, 8000);
},
function(next) {
setTimeout(function() {
startBitcore(next);
}, 6000);
}
], function(err) {
if (err) {
return done(err);
}
setTimeout(done, 2000);
});
});
after(function(done) {
shutdownBitcore(function() {
shutdownBitcoind(done);
});
});
it('should get address info correctly: /addr/:addr', function(done) {
var request = http.request('http://localhost:53001/api/addr/' + rpc2Address, function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
console.log(data);
expect(data.balance).to.equal(0);
expect(data.totalSent).to.equal(25);
done();
});
});
request.write('');
request.end();
});
it('should get a utxo: /addr/:addr/utxo', function(done) {
var request = http.request('http://localhost:53001/api/addr/' + rpc1Address + '/utxo', function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
console.log(data);
expect(data.length).equal(1);
expect(data[0].amount).equal(20);
expect(data[0].satoshis).equal(2000000000);
expect(data[0].confirmations).equal(6);
done();
});
});
request.write('');
request.end();
});
it('should get multi-address utxos: /addrs/:addrs/utxo', function(done) {
var request = http.request('http://localhost:53001/api/addrs/' + rpc2Address + ',' + rpc1Address + '/utxo', function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
console.log(data);
expect(data.length).to.equal(1);
expect(data[0].amount).to.equal(20);
expect(data[0].satoshis).to.equal(2000000000);
done();
});
});
request.write('');
request.end();
});
it('should post a utxo: /addrs/:addrs/utxo', function(done) {
var body = JSON.stringify({
addrs: [ rpc1Address, rpc2Address ]
});
var httpOpts = {
hostname: 'localhost',
port: 53001,
path: '/api/addrs/utxo',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': body.length
}
};
var request = http.request(httpOpts, function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
console.log(data);
expect(data.length).to.equal(1);
expect(data[0].amount).to.equal(20);
expect(data[0].satoshis).to.equal(2000000000);
done();
});
});
request.write(body);
request.end();
});
it('should get txs for a set of addresses: /addrs/:addrs/txs', function(done) {
var httpOpts = {
hostname: 'localhost',
port: 53001,
path: '/api/addrs/' + rpc1Address + ',' + rpc2Address + '/txs',
method: 'GET'
};
var request = http.request(httpOpts, function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
console.log(resData);
expect(data.items.length).to.equal(3);
expect(data.from).to.equal(0);
expect(data.to).to.equal(3);
done();
});
});
request.write('');
request.end();
});
it('should post txs for a set of addresses: /addrs/txs', function(done) {
var body = JSON.stringify({
addrs: [ rpc1Address, rpc2Address ]
});
var httpOpts = {
hostname: 'localhost',
port: 53001,
path: '/api/addrs/txs',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
var request = http.request(httpOpts, function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
console.log(resData);
expect(data.items.length).to.equal(3);
expect(data.from).to.equal(0);
expect(data.to).to.equal(3);
done();
});
});
request.write(body);
request.end();
});
it('should get totalReceived for an address: /addr/:addr/totalReceived', function(done) {
var httpOpts = {
hostname: 'localhost',
port: 53001,
path: '/api/addr/' + rpc1Address + '/totalReceived',
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
};
var request = http.request(httpOpts, function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
expect(data).to.equal(2000000000);
done();
});
});
request.write('');
request.end();
});
it('should get totalSent for an address: /addr/:addr/totalSent', function(done) {
var httpOpts = {
hostname: 'localhost',
port: 53001,
path: '/api/addr/' + rpc1Address + '/totalSent',
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
};
var request = http.request(httpOpts, function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
expect(data).to.equal(0);
done();
});
});
request.write('');
request.end();
});
it('should get unconfirmedBalance for an address: /addr/:addr/unconfirmedBalance', function(done) {
var httpOpts = {
hostname: 'localhost',
port: 53001,
path: '/api/addr/' + rpc1Address + '/unconfirmedBalance',
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
};
var request = http.request(httpOpts, function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
expect(data).to.equal(0);
done();
});
});
request.write('');
request.end();
});
});

500
regtest/block.js Normal file
View File

@ -0,0 +1,500 @@
'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 rpc1Address;
var rpc2Address;
var tx1;
var tx2;
var block;
var rpcConfig = {
protocol: 'http',
user: 'local',
pass: 'localtest',
host: '127.0.0.1',
port: 58332,
rejectUnauthorized: false
};
var rpc1 = new RPC(rpcConfig);
rpcConfig.port++;
var rpc2 = new RPC(rpcConfig);
var debug = true;
var bitcoreDataDir = '/tmp/bitcore';
var bitcoinDataDirs = ['/tmp/bitcoin1', '/tmp/bitcoin2'];
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'
}
}
}
},
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 startBitcoind = function(count, callback) {
var listenCount = 0;
async.timesSeries(count, function(n, next) {
var datadir = bitcoinDataDirs.shift();
bitcoin.datadir = datadir;
bitcoin.args.datadir = datadir;
if (listenCount++ > 0) {
bitcoin.args.listen = 0;
bitcoin.args.rpcport++;
bitcoin.args.connect = '127.0.0.1';
}
rimraf(datadir, function(err) {
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();
});
};
var shutdownBitcoind = function(callback) {
bitcoin.processes.forEach(function(process) {
process.kill();
});
setTimeout(callback, 3000);
};
var shutdownBitcore = function(callback) {
if (bitcore.process) {
bitcore.process.kill();
}
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 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;
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());
}
});
callback();
});
});
};
describe('Block', function() {
this.timeout(60000);
before(function(done) {
async.series([
function(next) {
startBitcoind(2, next);
},
function(next) {
setTimeout(function() {
buildInitialChain(next);
}, 8000);
},
function(next) {
setTimeout(function() {
startBitcore(next);
}, 6000);
}
], function(err) {
if (err) {
return done(err);
}
setTimeout(done, 2000);
});
});
after(function(done) {
shutdownBitcore(function() {
shutdownBitcoind(done);
});
});
it('should get blocks: /blocks', function(done) {
var request = http.request('http://localhost:53001/api/blocks', function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
expect(data.length).to.equal(114);
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 error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
expect(data.hash).to.equal(block);
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 error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
console.log(resData);
expect(data.blockHash).to.equal(block);
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 error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
console.log(resData);
expect(data.rawblock).to.not.be.null;
done();
});
});
request.write('');
request.end();
});
});

10
regtest/data/blocks.json Normal file
View File

@ -0,0 +1,10 @@
[
"0000002006226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f0520bf1be2e869376908f7c637214f9f0f9f4fd86c819a8c98a3c5f8d70a65f805ba9559ffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0200f2052a01000000232103e91a98edf4e457b5d5aa1e50e35ce6afb67bf7a9ff98b5c36dabbe994b080205ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
"00000020bd5725c4bc8fb66032523ca18eb2c809ca1935ab35baf5a1bbaf60ef9a616b2b373d5a12492652b1d22c28ce5c6eb6b22f03c69db1eae9a368e1b544147583eb06ba9559ffff7f20030000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03520101ffffffff0200f2052a01000000232103e91a98edf4e457b5d5aa1e50e35ce6afb67bf7a9ff98b5c36dabbe994b080205ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
"00000020af97cfd581a5f0da7925c346c371f6c58131a6b00a95060562f90607aa111e5f97c7b866d2503ee4982569a486f6e25023e72bef588bdef60a06fc740e50001906ba9559ffff7f20020000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03530101ffffffff0200f2052a01000000232103e91a98edf4e457b5d5aa1e50e35ce6afb67bf7a9ff98b5c36dabbe994b080205ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
"000000201c9d9eb8064b9508b3cd10de5927cc47347a6899b66946ecc22d52b04c2f3c5f99435c3a200a2419695565432e3115a5ff0d57ed1975b9efe0c7ad1a709a6a4e07ba9559ffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03540101ffffffff0200f2052a01000000232103e91a98edf4e457b5d5aa1e50e35ce6afb67bf7a9ff98b5c36dabbe994b080205ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
"00000020de37a9c9fbb1dc3ea5ca9e148e5310d639649814b45a424afe1d58a18db5d8327b529f7d58238330d55b82228ea14abcab965319de7e59c6534758c91c137fcb07ba9559ffff7f20020000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03550101ffffffff0200f2052a01000000232103e91a98edf4e457b5d5aa1e50e35ce6afb67bf7a9ff98b5c36dabbe994b080205ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
"00000020e3aa93afbba267bec962a7a38bd064478e5c082e9a73e434b20544950ad8395b3b4a71816a4ce7973d0bcc6a583441fca260f71a175bd2887a9e3e40e4badcd355bb9559ffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03560101ffffffff0200f2052a010000002321023886024ea5984e57b35c3b339f5aee097819ac55235e4fd5822a6ad0a4de1b55ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
"000000201a3c951a20b5d603144ce060c86e95fed1869524e66acfc46bdf08d96f6642094916aa5b965b0016fb8ba8b58e99f6b3edbe1a844aa7948adaccf7f28f08f914b9cb9559ffff7f20030000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03570101ffffffff0200f2052a01000000232102a8ef631320be3e6203329acba88fe0a663c19d59fee8240592dc2a32553a4159ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000"
]

View File

@ -0,0 +1,4 @@
[
"000000201a3c951a20b5d603144ce060c86e95fed1869524e66acfc46bdf08d96f664209b4b1c32ec485f4ad27c5402a1b16a0b1135364b7c9b0dcf4276f9fa3fd215d1b08cc9559ffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03570101ffffffff0200f2052a01000000232102a5566542d1f0f202541d98755628a41dcd4416b50db820e2b04d5ecb0bd02b73ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000"
]

277
regtest/reorg.js Normal file
View File

@ -0,0 +1,277 @@
'use strict';
var expect = require('chai').expect;
var net = require('net');
var spawn = require('child_process').spawn;
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');
var fs = require('fs');
var p2p = require('bitcore-p2p');
var bitcore = require('bitcore-lib');
var Networks = bitcore.Networks;
var BlockHeader = bitcore.BlockHeader;
var Block = bitcore.Block;
var BcoinBlock = require('bcoin').block;
var http = require('http');
Networks.enableRegtest();
var messages = new p2p.Messages({ network: Networks.get('regtest'), Block: BcoinBlock, BlockHeader: BlockHeader });
var server;
var rawBlocks = require('./data/blocks.json');
var rawReorgBlocks = require('./data/blocks_reorg.json')[0];
var reorgBlock = BcoinBlock.fromRaw(rawReorgBlocks, 'hex');
var blocks = rawBlocks.map(function(rawBlock) {
return new Block(new Buffer(rawBlock, 'hex'));
});
var headers = blocks.map(function(block) {
return block.header;
});
var debug = true;
var bitcoreDataDir = '/tmp/bitcore';
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'
}
}
}
},
httpOpts: {
protocol: 'http:',
hostname: 'localhost',
port: 53001,
},
opts: { cwd: bitcoreDataDir },
datadir: bitcoreDataDir,
exec: 'bitcored', // ensure this on your path or add the full, absolute path.
args: ['start'],
process: null
};
var blockIndex = 0;
var tcpSocket;
var startFakeNode = function() {
server = net.createServer(function(socket) {
tcpSocket = socket;
socket.on('end', function() {
console.log('bitcore-node has ended the connection');
});
socket.on('data', function(data) {
var command = data.slice(4, 16).toString('hex');
var message;
if (command === '76657273696f6e0000000000') { //version
message = messages.Version();
}
if (command === '76657261636b000000000000') { //verack
message = messages.VerAck();
}
if (command === '676574686561646572730000') { //getheaders
message = messages.Headers(headers);
}
if (command === '676574626c6f636b73000000') { //getblocks
var block = blocks[blockIndex];
if (!block) {
return;
}
var blockHash = block.hash;
var inv = p2p.Inventory.forBlock(blockHash);
message = messages.Inventory([inv]);
}
if (command === '676574646174610000000000') { //getdata
var raw = rawBlocks[blockIndex++];
var blk = BcoinBlock.fromRaw(raw, 'hex');
message = messages.Block(blk, { Block: BcoinBlock });
}
if (message) {
socket.write(message.toBuffer());
}
});
socket.pipe(socket);
});
server.listen(18444, '127.0.0.1');
};
var shutdownFakeNode = function() {
server.close();
};
var shutdownBitcore = function(callback) {
if (bitcore.process) {
bitcore.process.kill();
}
callback();
};
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;
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());
}
});
callback();
});
});
};
describe('Reorg', function() {
// 1. spin up bitcore-node and have it connect to our custom tcp socket
// 2. feed it a few headers
// 3. feed it a few blocks
// 4. feed it a block that reorgs
this.timeout(60000);
before(function(done) {
startFakeNode();
startBitcore(done);
});
after(function(done) {
shutdownFakeNode();
shutdownBitcore(function() {
setTimeout(done, 3000);
});
});
it('should reorg correctly when already synced', function(done) {
// at this point we have a fully synced chain at height 7....
// we now want to send a new block number 7 whose prev hash is block 6 (it should be block 7)
// we then should reorg back to block 6 then back up to the new block 7
setTimeout(function() {
console.log('From Test: reorging to block: ' + reorgBlock.rhash());
// send the reorg block
rawBlocks.push(rawReorgBlocks);
var blockHash = reorgBlock.rhash();
var inv = p2p.Inventory.forBlock(blockHash);
var msg = messages.Inventory([inv]);
tcpSocket.write(msg.toBuffer());
// wait 2 secs until the reorg happens, if it takes any longer the test ought to fail anyway
setTimeout(function() {
var error;
var request = http.request('http://localhost:53001/api/block/' + reorgBlock.rhash(), function(res) {
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
expect(data.height).to.equal(7);
expect(data.hash).to.equal(reorgBlock.rhash());
done(resError, resData);
});
});
request.on('error', function(e) {
error = e;
done(error);
});
request.write('');
request.end();
}, 2000);
}, 2000);
});
});

549
regtest/status.js Normal file
View File

@ -0,0 +1,549 @@
'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 rpc1Address;
var rpc2Address;
var tx1;
var tx2;
var block;
var rpcConfig = {
protocol: 'http',
user: 'local',
pass: 'localtest',
host: '127.0.0.1',
port: 58332,
rejectUnauthorized: false
};
var rpc1 = new RPC(rpcConfig);
rpcConfig.port++;
var rpc2 = new RPC(rpcConfig);
var debug = true;
var bitcoreDataDir = '/tmp/bitcore';
var bitcoinDataDirs = ['/tmp/bitcoin1', '/tmp/bitcoin2'];
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 }
]
},
'fee': {
'rpc': {
'user': 'local',
'pass': 'localtest',
'host': 'localhost',
'protocol': 'http',
'port': 58332
}
},
'insight-api': {
'routePrefix': 'api'
}
}
}
},
httpOpts: {
protocol: 'http:',
hostname: 'localhost',
port: 53001,
},
opts: { cwd: bitcoreDataDir },
datadir: bitcoreDataDir,
exec: 'bitcored',
args: ['start'],
process: null
};
var startBitcoind = function(count, callback) {
var listenCount = 0;
async.timesSeries(count, function(n, next) {
var datadir = bitcoinDataDirs.shift();
bitcoin.datadir = datadir;
bitcoin.args.datadir = datadir;
if (listenCount++ > 0) {
bitcoin.args.listen = 0;
bitcoin.args.rpcport++;
bitcoin.args.connect = '127.0.0.1';
}
rimraf(datadir, function(err) {
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();
});
};
var shutdownBitcoind = function(callback) {
bitcoin.processes.forEach(function(process) {
process.kill();
});
setTimeout(callback, 3000);
};
var shutdownBitcore = function(callback) {
if (bitcore.process) {
bitcore.process.kill();
}
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 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;
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());
}
});
callback();
});
});
};
describe('Status', function() {
this.timeout(60000);
before(function(done) {
async.series([
function(next) {
startBitcoind(2, next);
},
function(next) {
setTimeout(function() {
buildInitialChain(next);
}, 8000);
},
function(next) {
setTimeout(function() {
startBitcore(next);
}, 6000);
}
], function(err) {
if (err) {
return done(err);
}
setTimeout(done, 2000);
});
});
after(function(done) {
shutdownBitcore(function() {
shutdownBitcoind(done);
});
});
it('should get status: /status', function(done) {
var request = http.request('http://localhost:53001/api/status', function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
expect(data.info).to.not.be.null;
done();
});
});
request.write('');
request.end();
});
it('should get status: /sync', function(done) {
var request = http.request('http://localhost:53001/api/sync', function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
console.log(data);
expect(data.status).to.equal('finished');
done();
});
});
request.write('');
request.end();
});
it('should get peer: /peer', function(done) {
var request = http.request('http://localhost:53001/api/peer', function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
console.log(data);
expect(data.connected).to.be.true;
done();
});
});
request.write('');
request.end();
});
it('should get version: /version', function(done) {
var request = http.request('http://localhost:53001/api/version', function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
console.log(data);
expect(data.version).to.not.be.null;
done();
});
});
request.write('');
request.end();
});
it('should estimate fee: /estimateFee', function(done) {
var request = http.request('http://localhost:53001/api/utils/estimateFee', function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
console.log(data);
expect(data['2']).to.not.be.null;
done();
});
});
request.write('');
request.end();
});
});

448
regtest/transaction.js Normal file
View File

@ -0,0 +1,448 @@
'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 rpc1Address;
var rpc2Address;
var tx1;
var tx2;
var block;
var rpcConfig = {
protocol: 'http',
user: 'local',
pass: 'localtest',
host: '127.0.0.1',
port: 58332,
rejectUnauthorized: false
};
var rpc1 = new RPC(rpcConfig);
rpcConfig.port++;
var rpc2 = new RPC(rpcConfig);
var debug = true;
var bitcoreDataDir = '/tmp/bitcore';
var bitcoinDataDirs = ['/tmp/bitcoin1', '/tmp/bitcoin2'];
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'
}
}
}
},
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 startBitcoind = function(count, callback) {
var listenCount = 0;
async.timesSeries(count, function(n, next) {
var datadir = bitcoinDataDirs.shift();
bitcoin.datadir = datadir;
bitcoin.args.datadir = datadir;
if (listenCount++ > 0) {
bitcoin.args.listen = 0;
bitcoin.args.rpcport++;
bitcoin.args.connect = '127.0.0.1';
}
rimraf(datadir, function(err) {
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();
});
};
var shutdownBitcoind = function(callback) {
bitcoin.processes.forEach(function(process) {
process.kill();
});
setTimeout(callback, 3000);
};
var shutdownBitcore = function(callback) {
if (bitcore.process) {
bitcore.process.kill();
}
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 6 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 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;
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());
}
});
callback();
});
});
};
describe('Transaction', function() {
this.timeout(60000);
before(function(done) {
async.series([
function(next) {
startBitcoind(2, next);
},
function(next) {
setTimeout(function() {
buildInitialChain(next);
}, 8000);
},
function(next) {
setTimeout(function() {
startBitcore(next);
}, 6000);
}
], function(err) {
if (err) {
return done(err);
}
setTimeout(done, 2000);
});
});
after(function(done) {
shutdownBitcore(function() {
shutdownBitcoind(done);
});
});
it('should get a transaction: /tx/:txid', function(done) {
var request = http.request('http://localhost:53001/api/tx/' + tx1, function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
expect(data.txid).to.equal(tx1);
done();
});
});
request.write('');
request.end();
});
it('should get transactions: /txs', function(done) {
var request = http.request('http://localhost:53001/api/txs?block=' + block, function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
console.log(resData);
expect(data.txs.length).to.equal(1);
done();
});
});
request.write('');
request.end();
});
it('should get a raw transactions: /rawtx/:txid', function(done) {
var request = http.request('http://localhost:53001/api/rawtx/' + tx2, function(res) {
var error;
if (res.statusCode !== 200 && res.statusCode !== 201) {
if (error) {
return;
}
return done('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 (error) {
return;
}
var data = JSON.parse(resData);
console.log(resData);
expect(data.rawtx).to.not.be.null;
done();
});
});
request.write('');
request.end();
});
});

View File

@ -184,8 +184,8 @@ var utxos = [
describe('Addresses', function() {
var summary = {
balance: 0,
totalReceived: 2782729129,
totalSpent: 2782729129,
totalReceivedSat: 2782729129,
totalSent: 2782729129,
unconfirmedBalance: 0,
appearances: 2,
unconfirmedAppearances: 0,

View File

@ -13,60 +13,60 @@ describe('Transactions', function() {
it('should have correct data', function(done) {
var insight = {
"txid": "eac9723230b8b632117ac3d75288d6f8eb81cf1ea553eb9fd42562d5f767d54a",
"version": 1,
"locktime": 0,
"vin": [
'txid': 'eac9723230b8b632117ac3d75288d6f8eb81cf1ea553eb9fd42562d5f767d54a',
'version': 1,
'locktime': 0,
'vin': [
{
"txid": "46e58a68bb9ec9b458a9599dc2bac1e1fa09ad15c29c7f923c8f6f0aa33d6456",
"vout": 1,
"sequence": 4294967295,
"n": 0,
"scriptSig": {
"hex": "47304402203ddb49db43074b421ec6d5604ae91aac37f4715139e0c83ea1145379e8cbf02702207fbc92c4038ad501989b097844ae4e337c9388f0713110620b40e582b85fdff3012102cd90aa18ec8e3b35c0447ffc713c945cb837429d33d075d1b0f050c72ea838d2",
"asm": "304402203ddb49db43074b421ec6d5604ae91aac37f4715139e0c83ea1145379e8cbf02702207fbc92c4038ad501989b097844ae4e337c9388f0713110620b40e582b85fdff301 02cd90aa18ec8e3b35c0447ffc713c945cb837429d33d075d1b0f050c72ea838d2"
'txid': '46e58a68bb9ec9b458a9599dc2bac1e1fa09ad15c29c7f923c8f6f0aa33d6456',
'vout': 1,
'sequence': 4294967295,
'n': 0,
'scriptSig': {
'hex': '47304402203ddb49db43074b421ec6d5604ae91aac37f4715139e0c83ea1145379e8cbf02702207fbc92c4038ad501989b097844ae4e337c9388f0713110620b40e582b85fdff3012102cd90aa18ec8e3b35c0447ffc713c945cb837429d33d075d1b0f050c72ea838d2',
'asm': '304402203ddb49db43074b421ec6d5604ae91aac37f4715139e0c83ea1145379e8cbf02702207fbc92c4038ad501989b097844ae4e337c9388f0713110620b40e582b85fdff301 02cd90aa18ec8e3b35c0447ffc713c945cb837429d33d075d1b0f050c72ea838d2'
},
"addr": "1NqgMfGUeELP2BfxD4hQuJSRq2d3DVJcCi",
"valueSat": 1546063700,
"value": 15.460637,
"doubleSpentTxID": null
'addr': '1NqgMfGUeELP2BfxD4hQuJSRq2d3DVJcCi',
'valueSat': 1546063700,
'value': 15.460637,
'doubleSpentTxID': null
}
],
"vout": [
'vout': [
{
"value": "0.37100000",
"n": 0,
"scriptPubKey": {
"hex": "76a914bc345e0e0e5b0dbddb7b35ef3430fedd528dd1b788ac",
"asm": "OP_DUP OP_HASH160 bc345e0e0e5b0dbddb7b35ef3430fedd528dd1b7 OP_EQUALVERIFY OP_CHECKSIG",
"addresses": [
"1JA8mcfrBv1YYsASAp9jtohm8x2q7LnUhs"
'value': '0.37100000',
'n': 0,
'scriptPubKey': {
'hex': '76a914bc345e0e0e5b0dbddb7b35ef3430fedd528dd1b788ac',
'asm': 'OP_DUP OP_HASH160 bc345e0e0e5b0dbddb7b35ef3430fedd528dd1b7 OP_EQUALVERIFY OP_CHECKSIG',
'addresses': [
'1JA8mcfrBv1YYsASAp9jtohm8x2q7LnUhs'
],
"type": "pubkeyhash"
'type': 'pubkeyhash'
}
},
{
"value": "15.08763700",
"n": 1,
"scriptPubKey": {
"hex": "76a914c2c74d7519d4425fc1a253f066d980164341554a88ac",
"asm": "OP_DUP OP_HASH160 c2c74d7519d4425fc1a253f066d980164341554a OP_EQUALVERIFY OP_CHECKSIG",
"addresses": [
"1Jktr121Hm63qtWBMV8dCNJNW2KtWXy4fp"
'value': '15.08763700',
'n': 1,
'scriptPubKey': {
'hex': '76a914c2c74d7519d4425fc1a253f066d980164341554a88ac',
'asm': 'OP_DUP OP_HASH160 c2c74d7519d4425fc1a253f066d980164341554a OP_EQUALVERIFY OP_CHECKSIG',
'addresses': [
'1Jktr121Hm63qtWBMV8dCNJNW2KtWXy4fp'
],
"type": "pubkeyhash"
'type': 'pubkeyhash'
}
}
],
"blockhash": "0000000000000000009d2e9b7a984d55c6c99ba62f98e9bc7dad8b1e779045a3",
"blockheight": 481763,
"confirmations": 4,
"time": 1503507151,
"blocktime": 1503507151,
"valueOut": 15.458637,
"size": 225,
"valueIn": 15.460637,
"fees": 0.002
'blockhash': '0000000000000000009d2e9b7a984d55c6c99ba62f98e9bc7dad8b1e779045a3',
'blockheight': 481763,
'confirmations': 4,
'time': 1503507151,
'blocktime': 1503507151,
'valueOut': 15.458637,
'size': 225,
'valueIn': 15.460637,
'fees': 0.002
};
var bcoinTx = bcoin.tx.fromRaw('010000000156643da30a6f8f3c927f9cc215ad09fae1c1bac29d59a958b4c99ebb688ae546010000006a47304402203ddb49db43074b421ec6d5604ae91aac37f4715139e0c83ea1145379e8cbf02702207fbc92c4038ad501989b097844ae4e337c9388f0713110620b40e582b85fdff3012102cd90aa18ec8e3b35c0447ffc713c945cb837429d33d075d1b0f050c72ea838d2ffffffff02e0193602000000001976a914bc345e0e0e5b0dbddb7b35ef3430fedd528dd1b788ac34e8ed59000000001976a914c2c74d7519d4425fc1a253f066d980164341554a88ac00000000', 'hex');
@ -85,7 +85,7 @@ describe('Transactions', function() {
getTip: sinon.stub().returns({ height: 481766 })
},
transaction: {
getDetailedTransaction: sinon.stub().callsArgWith(1, null, bcoinTx)
getDetailedTransaction: sinon.stub().callsArgWith(2, null, bcoinTx)
}
}
};
@ -156,41 +156,41 @@ describe('Transactions', function() {
var transactions = new TxController(node);
var insight = {
"pagesTotal": 1,
"txs": [
'pagesTotal': 1,
'txs': [
{
"txid": "9b0fc92260312ce44e74ef369f5c66bbb85848f2eddd5a7a1cde251e54ccfdd5",
"version": 1,
"locktime": 0,
"vin": [
'txid': '9b0fc92260312ce44e74ef369f5c66bbb85848f2eddd5a7a1cde251e54ccfdd5',
'version': 1,
'locktime': 0,
'vin': [
{
"coinbase": "04ffff001d010b",
"sequence": 4294967295,
"n": 0
'coinbase': '04ffff001d010b',
'sequence': 4294967295,
'n': 0
}
],
"vout": [
'vout': [
{
"value": "50.00000000",
"n": 0,
"scriptPubKey": {
"hex": "41047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77ac",
"asm": "047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77 OP_CHECKSIG",
"addresses": [
"1HLoD9E4SDFFPDiYfNYnkBLQ85Y51J3Zb1"
'value': '50.00000000',
'n': 0,
'scriptPubKey': {
'hex': '41047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77ac',
'asm': '047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77 OP_CHECKSIG',
'addresses': [
'1HLoD9E4SDFFPDiYfNYnkBLQ85Y51J3Zb1'
],
"type": "pubkeyhash"
'type': 'pubkeyhash'
}
}
],
"blockhash": "000000006a625f06636b8bb6ac7b960a8d03705d1ace08b1a19da3fdcc99ddbd",
"blockheight": 2,
"confirmations": 481772,
"time": 1231469744,
"blocktime": 1231469744,
"isCoinBase": true,
"valueOut": 50,
"size": 134
'blockhash': '000000006a625f06636b8bb6ac7b960a8d03705d1ace08b1a19da3fdcc99ddbd',
'blockheight': 2,
'confirmations': 481772,
'time': 1231469744,
'blocktime': 1231469744,
'isCoinBase': true,
'valueOut': 50,
'size': 134
}
]
};
@ -238,49 +238,49 @@ describe('Transactions', function() {
};
var insight = {
"pagesTotal": 1,
"txs": [
'pagesTotal': 1,
'txs': [
{
"txid": "1c01a2090db0850e1f1049bea02e4bbf44b6790dfeb8e054f2beb69339ef52d4",
"version": 1,
"locktime": 0,
"vin": [
'txid': '1c01a2090db0850e1f1049bea02e4bbf44b6790dfeb8e054f2beb69339ef52d4',
'version': 1,
'locktime': 0,
'vin': [
{
"coinbase": "03835807244d696e656420627920416e74506f6f6c6a2f4542312f4144362f4e59412f1d205999aaa02b1200001fff0200",
"sequence": 4294967295,
"n": 0
'coinbase': '03835807244d696e656420627920416e74506f6f6c6a2f4542312f4144362f4e59412f1d205999aaa02b1200001fff0200',
'sequence': 4294967295,
'n': 0
}
],
"vout": [
'vout': [
{
"value": "12.85927535",
"n": 0,
"scriptPubKey": {
"hex": "76a914ad7309dfc032d7f6b652e0c29ee353e63fffec6688ac",
"asm": "OP_DUP OP_HASH160 ad7309dfc032d7f6b652e0c29ee353e63fffec66 OP_EQUALVERIFY OP_CHECKSIG",
"addresses": [
"1Gp7iCzDGMZiV55Kt8uKsux6VyoHe1aJaN"
'value': '12.85927535',
'n': 0,
'scriptPubKey': {
'hex': '76a914ad7309dfc032d7f6b652e0c29ee353e63fffec6688ac',
'asm': 'OP_DUP OP_HASH160 ad7309dfc032d7f6b652e0c29ee353e63fffec66 OP_EQUALVERIFY OP_CHECKSIG',
'addresses': [
'1Gp7iCzDGMZiV55Kt8uKsux6VyoHe1aJaN'
],
"type": "pubkeyhash"
'type': 'pubkeyhash'
}
},
{
"value": "0.00000000",
"n": 1,
"scriptPubKey": {
"hex": "6a24aa21a9ed55882e9fed16c5d3b6d77e4160a56f58c70d354d02888a99486125b638231c81",
"asm": "OP_RETURN aa21a9ed55882e9fed16c5d3b6d77e4160a56f58c70d354d02888a99486125b638231c81"
'value': '0.00000000',
'n': 1,
'scriptPubKey': {
'hex': '6a24aa21a9ed55882e9fed16c5d3b6d77e4160a56f58c70d354d02888a99486125b638231c81',
'asm': 'OP_RETURN aa21a9ed55882e9fed16c5d3b6d77e4160a56f58c70d354d02888a99486125b638231c81'
}
}
],
"blockhash": "000000000000000000926a0cd4a05ef116514cbf1852edc306d13eb951ec0b54",
"blockheight": 481411,
"confirmations": 52813,
"time": 1503242912,
"blocktime": 1503242912,
"isCoinBase": true,
"valueOut": 12.85927535,
"size": 181
'blockhash': '000000000000000000926a0cd4a05ef116514cbf1852edc306d13eb951ec0b54',
'blockheight': 481411,
'confirmations': 52813,
'time': 1503242912,
'blocktime': 1503242912,
'isCoinBase': true,
'valueOut': 12.85927535,
'size': 181
}
]
};
@ -321,6 +321,7 @@ describe('Transactions', function() {
var transactions = new TxController(node);
var txid = '25a988e54b02e0e5df146a0f8fa7b9db56210533a9f04bdfda5f4ceb6f77aadd';
var res = {};
var req = {
params: {
@ -331,7 +332,6 @@ describe('Transactions', function() {
should(req.rawTransaction.rawtx).eql(hex);
done();
};
var txid = '25a988e54b02e0e5df146a0f8fa7b9db56210533a9f04bdfda5f4ceb6f77aadd';
transactions.rawTransaction(req, res, next);
});
});