diff --git a/.babelrc b/.babelrc index e1efc88..6effa34 100644 --- a/.babelrc +++ b/.babelrc @@ -6,7 +6,8 @@ ["transform-async-to-module-method", { "module": "bluebird", "method": "coroutine" - }] + }], + "istanbul" ] } }, diff --git a/.gitignore b/.gitignore index 62562b7..76b1021 100755 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +.nyc_output coverage node_modules diff --git a/.jscsrc b/.jscsrc deleted file mode 100644 index 872495e..0000000 --- a/.jscsrc +++ /dev/null @@ -1,4 +0,0 @@ -plugins: - - jscs-config-seegno - -preset: seegno diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..4ff58a3 --- /dev/null +++ b/.npmignore @@ -0,0 +1,10 @@ +.babelrc +.dockerignore +.eslintrc.yml +.gitattributes +.gitignore +.nyc_output +.travis.yml +/src +/test +docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml index 98da869..86833fc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,7 @@ sut: - bitcoind-username-only bitcoind: - image: seegno/bitcoind:0.12-alpine + image: seegno/bitcoind:0.13-alpine command: -printtoconsole -regtest=1 diff --git a/package.json b/package.json index 2e5bbf0..d7f83dd 100644 --- a/package.json +++ b/package.json @@ -2,19 +2,6 @@ "name": "bitcoin-core", "version": "1.0.0", "description": "A modern Bitcoin Core REST and RPC client.", - "author": { - "name": "Rui Marinho", - "email": "rui.marinho@seegno.com", - "url": "http://seegno.com" - }, - "license": "MIT", - "homepage": "https://github.com/seegno/bitcoin-core", - "bugs": "https://github.com/seegno/bitcoin-core/issues", - "repository": { - "type": "git", - "url": "https://github.com/seegno/bitcoin-core.git" - }, - "main": "dist/src/index.js", "keywords": [ "bitcoin", "bitcoind", @@ -23,22 +10,32 @@ "rest", "rpc" ], - "options": { - "mocha": "--compilers js:babel-register --timeout 20000 --recursive --require should test" + "homepage": "https://github.com/seegno/bitcoin-core", + "bugs": "https://github.com/seegno/bitcoin-core/issues", + "license": "MIT", + "author": { + "name": "Rui Marinho", + "email": "rui.marinho@seegno.com", + "url": "http://seegno.com" + }, + "main": "dist/src/index.js", + "repository": { + "type": "git", + "url": "https://github.com/seegno/bitcoin-core.git" }, "scripts": { "changelog": "github_changelog_generator --no-issues --header-label='# Changelog' --future-release=$npm_config_future_release && sed -i '' -e :a -e '$d;N;2,4ba' -e 'P;D' CHANGELOG.md", - "cover": "babel-node node_modules/.bin/isparta cover --report html _mocha -- $npm_package_options_mocha", + "cover": "nyc --reporter=html --reporter=text npm test", "dependencies": "docker-compose up -d bitcoind bitcoind-ssl bitcoind-username-only", - "lint": "eslint src test && jscs src test", + "lint": "eslint src test", "prepublish": "npm run transpile", - "testdocker": "docker-compose run --rm sut", "test": "NODE_ENV=test mocha $npm_package_options_mocha", + "testdocker": "docker-compose run --rm sut", "transpile": "rm -rf dist/* && babel src --out-dir dist/src", "version": "npm run changelog --future-release=$npm_package_version && npm run transpile && git add -A CHANGELOG.md dist" }, "dependencies": { - "bluebird": "^3.1.1", + "bluebird": "^3.4.1", "lodash": "^4.0.0", "request": "^2.53.0", "semver": "^5.1.0", @@ -47,26 +44,35 @@ "devDependencies": { "babel-cli": "^6.4.0", "babel-eslint": "^6.0.0", - "babel-plugin-add-module-exports": "^0.1.2", + "babel-plugin-add-module-exports": "^0.2.1", + "babel-plugin-istanbul": "^2.0.0", "babel-plugin-transform-async-to-module-method": "^6.5.2", "babel-preset-es2015-node4": "^2.0.2", "babel-register": "^6.3.13", - "eslint": "^2.3.0", - "eslint-config-seegno": "^3.0.0", - "eslint-plugin-babel": "^3.0.0", + "eslint": "^3.3.1", + "eslint-config-seegno": "^6.0.0", "isparta": "^4.0.0", - "jscs": "^2.7.0", - "jscs-config-seegno": "^1.0.0", - "mocha": "^2.3.4", - "nock": "^7.2.2", + "mocha": "^3.0.2", + "nock": "^8.0.0", + "nyc": "^8.1.0", "pre-commit": "^1.1.2", - "should": "^8.0.0", - "sinon": "^1.17.2" + "should": "^11.1.0" }, - "pre-commit": [ - "lint" - ], "engines": { "node": ">=4" - } + }, + "nyc": { + "include": [ + "src/" + ], + "instrument": false, + "report-dir": "./coverage", + "sourceMap": false + }, + "options": { + "mocha": "--compilers js:babel-register --timeout 20000 --recursive --require should" + }, + "pre-commit": [ + "lint" + ] } diff --git a/src/index.js b/src/index.js index ef8f6b9..d480c83 100755 --- a/src/index.js +++ b/src/index.js @@ -3,10 +3,10 @@ * Module dependencies. */ -import _ from 'lodash'; import Parser from './parser'; -import Requester from './requester'; import Promise from 'bluebird'; +import Requester from './requester'; +import _ from 'lodash'; import methods from './methods'; import request from 'request'; import semver from 'semver'; @@ -76,7 +76,7 @@ class Client { if (version) { unsupported = _.chain(methods) - .pickBy((range) => !semver.satisfies(version, range)) + .pickBy(range => !semver.satisfies(version, range)) .keys() .invokeMap(String.prototype.toLowerCase) .value(); @@ -198,7 +198,7 @@ class Client { getUnspentTransactionOutputs(...args) { const [[outpoints, { extension = 'json' } = {}], callback] = source(...args); - const sets = _.flatten([outpoints]).map((outpoint) => { + const sets = _.flatten([outpoints]).map(outpoint => { return `${outpoint.id}-${outpoint.index}`; }).join('/'); diff --git a/src/methods.js b/src/methods.js index a24610f..8c8c1d0 100755 --- a/src/methods.js +++ b/src/methods.js @@ -8,10 +8,12 @@ export default { abandonTransaction: '>=0.12.0', addMultiSigAddress: '>=0.1.0', addNode: '>=0.8.0', + addWitnessAddress: '>=0.13.0', backupWallet: '>=0.3.12', clearBanned: '>=0.12.0', createMultiSig: '>=0.1.0', createRawTransaction: '>=0.7.0', + createWitnessAddress: '>=0.13.0', decodeRawTransaction: '>=0.7.0', decodeScript: '>=0.9.0', disconnectNode: '>=0.12.0', @@ -24,6 +26,7 @@ export default { estimateSmartPriority: '>=0.12.0', fundRawTransaction: '>=0.12.0', generate: '>=0.11.0', + generateToAddress: '>=0.13.0', getAccount: '>=0.1.0', getAccountAddress: '>=0.3.18', getAddedNodeInfo: '>=0.8.0', @@ -39,9 +42,12 @@ export default { getChainTips: '>=0.10.0', getConnectionCount: '>=0.1.0', getDifficulty: '>=0.1.0', - getGenerate: '>=0.1.0', + getGenerate: '<0.13.0', getHashesPerSec: '<0.10.0', getInfo: '>=0.1.0', + getMempoolAncestors: '>=0.13.0', + getMempoolDescendants: '>=0.13.0', + getMempoolEntry: '>=0.13.0', getMempoolInfo: '>=0.10.0', getMiningInfo: '>=0.6.0', getNetTotals: '>=0.1.0', @@ -64,6 +70,7 @@ export default { help: '>=0.1.0', importAddress: '>=0.10.0', importPrivKey: '>=0.6.0', + importPrunedFunds: '>=0.13.0', importPubKey: '>=0.12.0', importWallet: '>=0.9.0', keypoolRefill: '>=0.1.0', @@ -80,15 +87,17 @@ export default { move: '>=0.3.18', ping: '>=0.9.0', prioritiseTransaction: '>=0.10.0', + removePrunedFunds: '>=0.13.0', sendFrom: '>=0.3.18', sendMany: '>=0.3.21', sendRawTransaction: '>=0.7.0', sendToAddress: '>=0.1.0', setAccount: '>=0.1.0', setBan: '>=0.12.0', - setGenerate: '>=0.1.0', + setGenerate: '<0.13.0', setTxFee: '>=0.3.22', signMessage: '>=0.5.0', + signMessageWithPrivKey: '>=0.13.0', signRawTransaction: '>=0.7.0', stop: '>=0.1.0', submitBlock: '>=0.7.0', diff --git a/src/parser.js b/src/parser.js index 2d2f6dc..a834341 100644 --- a/src/parser.js +++ b/src/parser.js @@ -3,8 +3,8 @@ * Module dependencies. */ -import _ from 'lodash'; import RpcError from './errors/rpc-error'; +import _ from 'lodash'; /** * Get response result and errors. @@ -57,7 +57,7 @@ export default class Parser { } // Batch response parsing where each response may or may not be successful. - const batch = body.map((response) => { + const batch = body.map(response => { try { return get(response, { headers: false, response }); } catch (e) { diff --git a/test/config/index.js b/test/config/index.js index 8962060..b92e41d 100755 --- a/test/config/index.js +++ b/test/config/index.js @@ -8,7 +8,7 @@ */ function getHost(name) { - return process.env.CI === 'true' ? name : 'docker.local'; + return process.env.CI === 'true' ? name : '127.0.0.1'; } /** diff --git a/test/index_test.js b/test/index_test.js index 64245b1..675eabf 100755 --- a/test/index_test.js +++ b/test/index_test.js @@ -3,9 +3,9 @@ * Module dependencies. */ -import _ from 'lodash'; import Client from '../src/index'; import RpcError from '../src/errors/rpc-error'; +import _ from 'lodash'; import config from './config'; import fs from 'fs'; import methods from '../src/methods'; @@ -137,7 +137,7 @@ describe('Client', () => { headers.should.have.keys('date', 'connection', 'content-length', 'content-type'); }); - it('should return the response headers if `headers` is enabled using callbacks', (done) => { + it('should return the response headers if `headers` is enabled using callbacks', done => { new Client(_.defaults({ headers: true }, config.bitcoind)).getInfo((err, [info, headers]) => { should.not.exist(err); @@ -160,7 +160,7 @@ describe('Client', () => { headers.should.have.keys('date', 'connection', 'content-length', 'content-type'); }); - it('should return the response headers if `headers` is enabled and batching is used with callbacks', (done) => { + it('should return the response headers if `headers` is enabled and batching is used with callbacks', done => { const batch = []; _.times(5, () => batch.push({ method: 'getnewaddress' })); @@ -269,7 +269,7 @@ describe('Client', () => { it('should establish a connection if certificate is self signed but `ca` agent option is passed', async () => { const sslClient = new Client(_.defaults({ agentOptions: { - /*eslint-disable no-sync */ + /* eslint-disable no-sync */ ca: fs.readFileSync(path.join(__dirname, '/config/ssl/cert.pem')), checkServerIdentity() { // Skip server identity checks otherwise the certificate would be immediately rejected @@ -301,7 +301,7 @@ describe('Client', () => { _.difference(parse(help), _.invokeMap(Object.keys(methods), String.prototype.toLowerCase)).should.be.empty(); }); - it('should support callbacks', (done) => { + it('should support callbacks', done => { new Client(config.bitcoind).help((err, help) => { should.not.exist(err); @@ -406,7 +406,7 @@ describe('Client', () => { const [transaction] = await client.listUnspent(); const hex = await client.getTransactionByHash(transaction.txid); - hex.should.have.keys('blockhash', 'blocktime', 'confirmations', 'locktime', 'size', 'time', 'txid', 'version', 'vin', 'vout'); + hex.should.have.keys('blockhash', 'blocktime', 'confirmations', 'locktime', 'hash', 'size', 'time', 'txid', 'version', 'vin', 'vout', 'vsize'); }); }); @@ -426,15 +426,15 @@ describe('Client', () => { it('should return a block json-encoded by default', async () => { const block = await client.getBlockByHash('0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206', { extension: 'json' }); - block.should.have.keys('bits', 'chainwork', 'confirmations', 'difficulty', 'hash', 'height', 'mediantime', 'merkleroot', 'nextblockhash', 'nonce', 'size', 'time', 'tx', 'version'); - block.tx.should.matchEach((value) => value.should.be.an.Object()); + block.should.have.keys('bits', 'chainwork', 'confirmations', 'difficulty', 'hash', 'height', 'mediantime', 'merkleroot', 'nextblockhash', 'nonce', 'size', 'strippedsize', 'time', 'tx', 'version', 'versionHex', 'weight'); + block.tx.should.matchEach(value => value.should.be.an.Object()); }); it('should return a block summary json-encoded if `summary` is enabled', async () => { const block = await client.getBlockByHash('0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206', { extension: 'json', summary: true }); - block.should.have.keys('bits', 'chainwork', 'confirmations', 'difficulty', 'hash', 'height', 'mediantime', 'merkleroot', 'nextblockhash', 'nonce', 'size', 'time', 'tx', 'version'); - block.tx.should.matchEach((value) => value.should.be.a.String()); + block.should.have.keys('bits', 'chainwork', 'confirmations', 'difficulty', 'hash', 'height', 'mediantime', 'merkleroot', 'nextblockhash', 'nonce', 'size', 'strippedsize', 'time', 'tx', 'version', 'versionHex', 'weight'); + block.tx.should.matchEach(value => value.should.be.a.String()); }); }); @@ -506,7 +506,7 @@ describe('Client', () => { }]); result.should.have.keys('bitmap', 'chainHeight', 'chaintipHash', 'utxos'); - result.chainHeight.should.equal(200); + result.chainHeight.should.be.a.Number(); }); }); @@ -520,9 +520,15 @@ describe('Client', () => { describe('getMemoryPoolInformation()', () => { it('should return memory pool information json-encoded by default', async () => { - const information = await new Client(config.bitcoind).getMemoryPoolContent(); - - information.should.eql({}); + const information = await new Client(config.bitcoind).getMemoryPoolInformation(); + + information.should.eql({ + bytes: 0, + maxmempool: 300000000, + mempoolminfee: 0, + size: 0, + usage: 0 + }); }); }); }); diff --git a/test/utils/help-parser-util.js b/test/utils/help-parser-util.js index 8f81433..4142fa3 100644 --- a/test/utils/help-parser-util.js +++ b/test/utils/help-parser-util.js @@ -11,7 +11,7 @@ import _ from 'lodash'; export default function parse(help) { return _.chain(help.split('\n')) - .reject((line) => line.startsWith('==') || !_.identity(line)) - .map((line) => (/^([a-z]+)/).exec(line)[1]) + .reject(line => line.startsWith('==') || !_.identity(line)) + .map(line => (/^([a-z]+)/).exec(line)[1]) .value(); }