From c035b34aefa65164857f521a75f356e65448b9e6 Mon Sep 17 00:00:00 2001 From: Rui Marinho Date: Mon, 27 Nov 2017 12:08:48 +0000 Subject: [PATCH] Release 2.0.0 --- CHANGELOG.md | 21 +- dist/src/errors/rpc-error.js | 28 +- dist/src/errors/standard-error.js | 16 +- dist/src/index.js | 337 +++++++++---------- dist/src/logging/request-logger.js | 33 +- dist/src/logging/request-obfuscator.js | 46 +-- dist/src/methods.js | 444 +++++++++++++++++++------ dist/src/parser.js | 122 ++++--- dist/src/requester.js | 41 ++- package.json | 2 +- 10 files changed, 661 insertions(+), 429 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d37341..e228036 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,24 @@ # Changelog -## [1.2.0](https://github.com/ruimarinho/bitcoin-core/tree/1.2.0) (2017-02-12) -[Full Changelog](https://github.com/ruimarinho/bitcoin-core/compare/v1.1.0...1.2.0) +## [2.0.0](https://github.com/ruimarinho/bitcoin-core/tree/2.0.0) (2017-11-27) +[Full Changelog](https://github.com/ruimarinho/bitcoin-core/compare/v1.2.0...2.0.0) + +**Merged pull requests:** + +- Add support for named parameters when using the JSON-RPC interface [\#51](https://github.com/ruimarinho/bitcoin-core/pull/51) ([ruimarinho](https://github.com/ruimarinho)) +- Improve response handling [\#50](https://github.com/ruimarinho/bitcoin-core/pull/50) ([ruimarinho](https://github.com/ruimarinho)) +- Update dependencies [\#49](https://github.com/ruimarinho/bitcoin-core/pull/49) ([ruimarinho](https://github.com/ruimarinho)) +- Update references [\#44](https://github.com/ruimarinho/bitcoin-core/pull/44) ([ruimarinho](https://github.com/ruimarinho)) +- Fix bug when calling REST method with extension `bin` [\#43](https://github.com/ruimarinho/bitcoin-core/pull/43) ([pedrobranco](https://github.com/pedrobranco)) +- Fix bug in rpc error class [\#42](https://github.com/ruimarinho/bitcoin-core/pull/42) ([pedrobranco](https://github.com/pedrobranco)) +- Obfuscate private keys from importmulti request logging [\#38](https://github.com/ruimarinho/bitcoin-core/pull/38) ([pedrobranco](https://github.com/pedrobranco)) +- Add support for bitcoin@0.15.0 methods [\#36](https://github.com/ruimarinho/bitcoin-core/pull/36) ([joaopaulofonseca](https://github.com/joaopaulofonseca)) +- Add support for bitcoin 0.13.2 [\#24](https://github.com/ruimarinho/bitcoin-core/pull/24) ([pedrobranco](https://github.com/pedrobranco)) +- Fix mempool naming inconsistency in getRawMempool method name [\#22](https://github.com/ruimarinho/bitcoin-core/pull/22) ([ruimarinho](https://github.com/ruimarinho)) +- Add support for bignumbers [\#17](https://github.com/ruimarinho/bitcoin-core/pull/17) ([pedrobranco](https://github.com/pedrobranco)) + +## [v1.2.0](https://github.com/ruimarinho/bitcoin-core/tree/v1.2.0) (2017-02-12) +[Full Changelog](https://github.com/ruimarinho/bitcoin-core/compare/v1.1.0...v1.2.0) **Merged pull requests:** diff --git a/dist/src/errors/rpc-error.js b/dist/src/errors/rpc-error.js index f4e85c1..b882936 100755 --- a/dist/src/errors/rpc-error.js +++ b/dist/src/errors/rpc-error.js @@ -1,27 +1,25 @@ -'use strict'; +"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = void 0; -var _http = require('http'); +var _http = require("http"); -var _standardError = require('./standard-error'); - -var _standardError2 = _interopRequireDefault(_standardError); +var _standardError = _interopRequireDefault(require("./standard-error")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** - * Export `RpcError` class. + * Module dependencies. */ /** - * Module dependencies. + * Export `RpcError` class. */ - -class RpcError extends _standardError2.default { - constructor(code, msg, props) { +class RpcError extends _standardError.default { + constructor(code, msg, props = {}) { if (typeof code != 'number') { throw new TypeError(`Non-numeric HTTP code`); } @@ -31,9 +29,8 @@ class RpcError extends _standardError2.default { msg = null; } + props.code = code; super(msg || _http.STATUS_CODES[code], props); - - this.code = code; } get status() { @@ -44,7 +41,7 @@ class RpcError extends _standardError2.default { Object.defineProperty(this, 'status', { configurable: true, enumerable: true, - value: value, + value, writable: true }); } @@ -52,6 +49,7 @@ class RpcError extends _standardError2.default { toString() { return `${this.name}: ${this.code} ${this.message}`; } + } -exports.default = RpcError; -module.exports = exports['default']; \ No newline at end of file + +exports.default = RpcError; \ No newline at end of file diff --git a/dist/src/errors/standard-error.js b/dist/src/errors/standard-error.js index aa589c5..5517b99 100755 --- a/dist/src/errors/standard-error.js +++ b/dist/src/errors/standard-error.js @@ -1,23 +1,21 @@ -'use strict'; +"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = void 0; -var _standardError = require('standard-error'); - -var _standardError2 = _interopRequireDefault(_standardError); +var _standardError = _interopRequireDefault(require("standard-error")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** - * Export `StandardError` class. + * Module dependencies. */ -class StandardError extends _standardError2.default {} -exports.default = StandardError; /** - * Module dependencies. + * Export `StandardError` class. */ +class StandardError extends _standardError.default {} -module.exports = exports['default']; \ No newline at end of file +exports.default = StandardError; \ No newline at end of file diff --git a/dist/src/index.js b/dist/src/index.js index 3a6864c..6950842 100755 --- a/dist/src/index.js +++ b/dist/src/index.js @@ -1,308 +1,273 @@ -'use strict'; +"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = void 0; -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); -/** - * Module dependencies. - */ - -var _parser = require('./parser'); - -var _parser2 = _interopRequireDefault(_parser); - -var _bluebird = require('bluebird'); - -var _bluebird2 = _interopRequireDefault(_bluebird); - -var _requester = require('./requester'); +var _parser = _interopRequireDefault(require("./parser")); -var _requester2 = _interopRequireDefault(_requester); +var _bluebird = _interopRequireDefault(require("bluebird")); -var _lodash = require('lodash'); +var _requester = _interopRequireDefault(require("./requester")); -var _lodash2 = _interopRequireDefault(_lodash); +var _lodash = _interopRequireDefault(require("lodash")); -var _debugnyan = require('debugnyan'); +var _debugnyan = _interopRequireDefault(require("debugnyan")); -var _debugnyan2 = _interopRequireDefault(_debugnyan); +var _methods = _interopRequireDefault(require("./methods")); -var _methods = require('./methods'); +var _requestLogger = _interopRequireDefault(require("./logging/request-logger")); -var _methods2 = _interopRequireDefault(_methods); - -var _requestLogger = require('./logging/request-logger'); - -var _requestLogger2 = _interopRequireDefault(_requestLogger); - -var _semver = require('semver'); - -var _semver2 = _interopRequireDefault(_semver); +var _semver = _interopRequireDefault(require("semver")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** - * Source arguments to find out if a callback has been passed. + * Module dependencies. */ -function source() { - for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - const last = _lodash2.default.last(args); +/** + * Source arguments to find out if a callback has been passed. + */ +function source(...args) { + const last = _lodash.default.last(args); let callback; - if (_lodash2.default.isFunction(last)) { + if (_lodash.default.isFunction(last)) { callback = last; - args = _lodash2.default.dropRight(args); + args = _lodash.default.dropRight(args); } return [args, callback]; } - /** * List of networks and their default port mapping. */ + const networks = { mainnet: 8332, regtest: 18332, testnet: 18332 }; - /** * Constructor. */ class Client { - constructor() { - var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - - let agentOptions = _ref.agentOptions; - var _ref$headers = _ref.headers; - let headers = _ref$headers === undefined ? false : _ref$headers; - var _ref$host = _ref.host; - let host = _ref$host === undefined ? 'localhost' : _ref$host; - var _ref$logger = _ref.logger; - let logger = _ref$logger === undefined ? (0, _debugnyan2.default)('bitcoin-core') : _ref$logger; - var _ref$network = _ref.network; - let network = _ref$network === undefined ? 'mainnet' : _ref$network, - password = _ref.password, - port = _ref.port; - var _ref$ssl = _ref.ssl; - let ssl = _ref$ssl === undefined ? false : _ref$ssl; - var _ref$timeout = _ref.timeout; - let timeout = _ref$timeout === undefined ? 30000 : _ref$timeout, - username = _ref.username, - version = _ref.version; - - if (!_lodash2.default.has(networks, network)) { - throw new Error(`Invalid network name "${network}"`, { network: network }); + constructor({ + agentOptions, + headers = false, + host = 'localhost', + logger = (0, _debugnyan.default)('bitcoin-core'), + network = 'mainnet', + password, + port, + ssl = false, + timeout = 30000, + username, + version + } = {}) { + if (!_lodash.default.has(networks, network)) { + throw new Error(`Invalid network name "${network}"`, { + network + }); } this.agentOptions = agentOptions; - this.auth = (password || username) && { pass: password, user: username }; + this.auth = (password || username) && { + pass: password, + user: username + }; + this.hasNamedParametersSupport = false; this.headers = headers; this.host = host; this.password = password; this.port = port || networks[network]; this.timeout = timeout; this.ssl = { - enabled: _lodash2.default.get(ssl, 'enabled', ssl), - strict: _lodash2.default.get(ssl, 'strict', _lodash2.default.get(ssl, 'enabled', ssl)) - }; + enabled: _lodash.default.get(ssl, 'enabled', ssl), + strict: _lodash.default.get(ssl, 'strict', _lodash.default.get(ssl, 'enabled', ssl)) + }; // Find unsupported methods according to version. - // Find unsupported methods according to version. let unsupported = []; if (version) { - unsupported = _lodash2.default.chain(_methods2.default).pickBy(method => !_semver2.default.satisfies(version, method.version)).keys().invokeMap(String.prototype.toLowerCase).value(); - } + // Capture X.Y.Z when X.Y.Z.A is passed to support oddly formatted Bitcoin Core + // versions such as 0.15.0.1. + const result = /[0-9]+\.[0-9]+\.[0-9]+/.exec(version); + + if (!result) { + throw new Error(`Invalid Version "${version}"`, { + version + }); + } - const request = (0, _requestLogger2.default)(logger); + [version] = result; + this.hasNamedParametersSupport = _semver.default.satisfies(version, '>=0.14.0'); + unsupported = _lodash.default.chain(_methods.default).pickBy(method => !_semver.default.satisfies(version, method.version)).keys().invokeMap(String.prototype.toLowerCase).value(); + } - this.request = _bluebird2.default.promisifyAll(request.defaults({ + const request = (0, _requestLogger.default)(logger); + this.request = _bluebird.default.promisifyAll(request.defaults({ agentOptions: this.agentOptions, baseUrl: `${this.ssl.enabled ? 'https' : 'http'}://${this.host}:${this.port}`, - json: true, strictSSL: this.ssl.strict, timeout: this.timeout - }), { multiArgs: true }); - this.requester = new _requester2.default({ unsupported: unsupported, version: version }); - this.parser = new _parser2.default({ headers: this.headers }); + }), { + multiArgs: true + }); + this.requester = new _requester.default({ + unsupported, + version + }); + this.parser = new _parser.default({ + headers: this.headers + }); } - /** * Execute `rpc` command. */ - command() { + + command(...args) { let body; let callback; - for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } + let parameters = _lodash.default.tail(args); - let parameters = _lodash2.default.tail(args); - const input = _lodash2.default.head(args); - const lastArg = _lodash2.default.last(args); + const input = _lodash.default.head(args); - if (_lodash2.default.isFunction(lastArg)) { + const lastArg = _lodash.default.last(args); + + if (_lodash.default.isFunction(lastArg)) { callback = lastArg; - parameters = _lodash2.default.dropRight(parameters); + parameters = _lodash.default.dropRight(parameters); + } + + if (this.hasNamedParametersSupport && parameters.length === 1 && _lodash.default.isPlainObject(parameters[0])) { + parameters = parameters[0]; } - return _bluebird2.default.try(() => { + return _bluebird.default.try(() => { if (Array.isArray(input)) { - body = input.map((method, index) => this.requester.prepare({ method: method.method, parameters: method.parameters, suffix: index })); + body = input.map((method, index) => this.requester.prepare({ + method: method.method, + parameters: method.parameters, + suffix: index + })); } else { - body = this.requester.prepare({ method: input, parameters: parameters }); + body = this.requester.prepare({ + method: input, + parameters + }); } return this.request.postAsync({ - auth: _lodash2.default.pickBy(this.auth, _lodash2.default.identity), - body: body, + auth: _lodash.default.pickBy(this.auth, _lodash.default.identity), + body: JSON.stringify(body), uri: '/' }).bind(this).then(this.parser.rpc); }).asCallback(callback); } - /** * Given a transaction hash, returns a transaction in binary, hex-encoded binary, or JSON formats. */ - getTransactionByHash() { - var _source = source.apply(undefined, arguments), - _source2 = _slicedToArray(_source, 2), - _source2$ = _slicedToArray(_source2[0], 2); - const hash = _source2$[0]; - var _source2$$ = _source2$[1]; - _source2$$ = _source2$$ === undefined ? {} : _source2$$; - var _source2$$$extension = _source2$$.extension; - const extension = _source2$$$extension === undefined ? 'json' : _source2$$$extension, - callback = _source2[1]; - - - return _bluebird2.default.try(() => { - return this.request.getAsync(`/rest/tx/${hash}.${extension}`).bind(this).then(this.parser.rest); + getTransactionByHash(...args) { + const [[hash, { + extension = 'json' + } = {}], callback] = source(...args); + return _bluebird.default.try(() => { + return this.request.getAsync({ + encoding: extension === 'bin' ? null : undefined, + url: `/rest/tx/${hash}.${extension}` + }).bind(this).then(_lodash.default.partial(this.parser.rest, extension)); }).asCallback(callback); } - /** * Given a block hash, returns a block, in binary, hex-encoded binary or JSON formats. * With `summary` set to `false`, the JSON response will only contain the transaction * hash instead of the complete transaction details. The option only affects the JSON response. */ - getBlockByHash() { - var _source3 = source.apply(undefined, arguments), - _source4 = _slicedToArray(_source3, 2), - _source4$ = _slicedToArray(_source4[0], 2); - - const hash = _source4$[0]; - var _source4$$ = _source4$[1]; - _source4$$ = _source4$$ === undefined ? {} : _source4$$; - var _source4$$$summary = _source4$$.summary; - const summary = _source4$$$summary === undefined ? false : _source4$$$summary; - var _source4$$$extension = _source4$$.extension; - const extension = _source4$$$extension === undefined ? 'json' : _source4$$$extension, - callback = _source4[1]; - - return _bluebird2.default.try(() => { - return this.request.getAsync(`/rest/block${summary ? '/notxdetails/' : '/'}${hash}.${extension}`).bind(this).then(this.parser.rest); + getBlockByHash(...args) { + const [[hash, { + summary = false, + extension = 'json' + } = {}], callback] = source(...args); + return _bluebird.default.try(() => { + return this.request.getAsync({ + encoding: extension === 'bin' ? null : undefined, + url: `/rest/block${summary ? '/notxdetails/' : '/'}${hash}.${extension}` + }).bind(this).then(_lodash.default.partial(this.parser.rest, extension)); }).asCallback(callback); } - /** * Given a block hash, returns amount of blockheaders in upward direction. */ - getBlockHeadersByHash() { - var _source5 = source.apply(undefined, arguments), - _source6 = _slicedToArray(_source5, 2), - _source6$ = _slicedToArray(_source6[0], 3); - - const hash = _source6$[0], - count = _source6$[1]; - var _source6$$ = _source6$[2]; - _source6$$ = _source6$$ === undefined ? {} : _source6$$; - var _source6$$$extension = _source6$$.extension; - const extension = _source6$$$extension === undefined ? 'json' : _source6$$$extension, - callback = _source6[1]; - - return _bluebird2.default.try(() => { - if (!_lodash2.default.includes(['bin', 'hex'], extension)) { + getBlockHeadersByHash(...args) { + const [[hash, count, { + extension = 'json' + } = {}], callback] = source(...args); + return _bluebird.default.try(() => { + if (!_lodash.default.includes(['bin', 'hex'], extension)) { throw new Error(`Extension "${extension}" is not supported`); } - return this.request.getAsync(`/rest/headers/${count}/${hash}.${extension}`).bind(this).then(this.parser.rest); + return this.request.getAsync({ + encoding: extension === 'bin' ? null : undefined, + url: `/rest/headers/${count}/${hash}.${extension}` + }).bind(this).then(_lodash.default.partial(this.parser.rest, extension)); }).asCallback(callback); } - /** * Returns various state info regarding block chain processing. * Only supports JSON as output format. */ - getBlockchainInformation() { - var _source7 = source.apply(undefined, arguments), - _source8 = _slicedToArray(_source7, 2); - - const callback = _source8[1]; - - return this.request.getAsync(`/rest/chaininfo.json`).bind(this).then(this.parser.rest).asCallback(callback); + getBlockchainInformation(...args) { + const [, callback] = source(...args); + return this.request.getAsync(`/rest/chaininfo.json`).bind(this).then(_lodash.default.partial(this.parser.rest, 'json')).asCallback(callback); } - /** * Query unspent transaction outputs for a given set of outpoints. * See BIP64 for input and output serialisation: * - https://github.com/bitcoin/bips/blob/master/bip-0064.mediawiki */ - getUnspentTransactionOutputs() { - var _source9 = source.apply(undefined, arguments), - _source10 = _slicedToArray(_source9, 2), - _source10$ = _slicedToArray(_source10[0], 2); - - const outpoints = _source10$[0]; - var _source10$$ = _source10$[1]; - _source10$$ = _source10$$ === undefined ? {} : _source10$$; - var _source10$$$extension = _source10$$.extension; - const extension = _source10$$$extension === undefined ? 'json' : _source10$$$extension, - callback = _source10[1]; + getUnspentTransactionOutputs(...args) { + const [[outpoints, { + extension = 'json' + } = {}], callback] = source(...args); - const sets = _lodash2.default.flatten([outpoints]).map(outpoint => { + const sets = _lodash.default.flatten([outpoints]).map(outpoint => { return `${outpoint.id}-${outpoint.index}`; }).join('/'); - return this.request.getAsync(`/rest/getutxos/checkmempool/${sets}.${extension}`).bind(this).then(this.parser.rest).asCallback(callback); + return this.request.getAsync({ + encoding: extension === 'bin' ? null : undefined, + url: `/rest/getutxos/checkmempool/${sets}.${extension}` + }).bind(this).then(_lodash.default.partial(this.parser.rest, extension)).asCallback(callback); } - /** * Returns transactions in the transaction memory pool. * Only supports JSON as output format. */ - getMemoryPoolContent() { - var _source11 = source.apply(undefined, arguments), - _source12 = _slicedToArray(_source11, 2); - - const callback = _source12[1]; - - return this.request.getAsync('/rest/mempool/contents.json').bind(this).then(this.parser.rest).asCallback(callback); + getMemoryPoolContent(...args) { + const [, callback] = source(...args); + return this.request.getAsync('/rest/mempool/contents.json').bind(this).then(_lodash.default.partial(this.parser.rest, 'json')).asCallback(callback); } - /** * Returns various information about the transaction memory pool. * Only supports JSON as output format. @@ -312,28 +277,30 @@ class Client { * - usage: total transaction memory pool memory usage. */ - getMemoryPoolInformation() { - var _source13 = source.apply(undefined, arguments), - _source14 = _slicedToArray(_source13, 2); - - const callback = _source14[1]; - - return this.request.getAsync('/rest/mempool/info.json').bind(this).then(this.parser.rest).asCallback(callback); + getMemoryPoolInformation(...args) { + const [, callback] = source(...args); + return this.request.getAsync('/rest/mempool/info.json').bind(this).then(_lodash.default.partial(this.parser.rest, 'json')).asCallback(callback); } -} +} /** * Add all known RPC methods. */ -_lodash2.default.forOwn(_methods2.default, (range, method) => { - Client.prototype[method] = _lodash2.default.partial(Client.prototype.command, method.toLowerCase()); + +_lodash.default.forOwn(_methods.default, (range, method) => { + Client.prototype[method] = _lodash.default.partial(Client.prototype.command, method.toLowerCase()); }); +/** + * Export Client class (ESM). + */ + +var _default = Client; /** - * Export Client class. + * Export Client class (CJS) for compatibility with require('bitcoin-core'). */ -exports.default = Client; -module.exports = exports['default']; \ No newline at end of file +exports.default = _default; +module.exports = Client; \ No newline at end of file diff --git a/dist/src/logging/request-logger.js b/dist/src/logging/request-logger.js index 90103d9..a290b85 100644 --- a/dist/src/logging/request-logger.js +++ b/dist/src/logging/request-logger.js @@ -1,36 +1,37 @@ -'use strict'; +"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = void 0; -var _requestObfuscator = require('./request-obfuscator'); +var _requestObfuscator = require("./request-obfuscator"); -var _request = require('request'); +var _request = _interopRequireDefault(require("request")); -var _request2 = _interopRequireDefault(_request); - -var _requestLogger = require('@uphold/request-logger'); - -var _requestLogger2 = _interopRequireDefault(_requestLogger); +var _requestLogger = _interopRequireDefault(require("@uphold/request-logger")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** - * Exports. + * Module dependencies. */ -exports.default = logger => (0, _requestLogger2.default)(_request2.default, (request, instance) => { +/** + * Exports. + */ +var _default = logger => (0, _requestLogger.default)(_request.default, (request, instance) => { (0, _requestObfuscator.obfuscate)(request, instance); if (request.type === 'response') { - return logger.debug({ request: request }, `Received response for request ${request.id}`); + return logger.debug({ + request + }, `Received response for request ${request.id}`); } - return logger.debug({ request: request }, `Making request ${request.id} to ${request.method} ${request.uri}`); + return logger.debug({ + request + }, `Making request ${request.id} to ${request.method} ${request.uri}`); }); -/** - * Module dependencies. - */ -module.exports = exports['default']; \ No newline at end of file +exports.default = _default; \ No newline at end of file diff --git a/dist/src/logging/request-obfuscator.js b/dist/src/logging/request-obfuscator.js index a10bccc..51c459b 100644 --- a/dist/src/logging/request-obfuscator.js +++ b/dist/src/logging/request-obfuscator.js @@ -1,28 +1,24 @@ -'use strict'; +"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.obfuscate = obfuscate; -var _methods = require('../methods'); +var _lodash = require("lodash"); -var _methods2 = _interopRequireDefault(_methods); - -var _lodash = require('lodash'); +var _methods = _interopRequireDefault(require("../methods")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** - * Map all methods to lowercase. + * Module dependencies. */ /** - * Module dependencies. + * Map all methods to lowercase. */ - -const lowercaseMethods = (0, _lodash.mapKeys)(_methods2.default, (value, key) => key.toLowerCase()); - +const lowercaseMethods = (0, _lodash.mapKeys)(_methods.default, (value, key) => key.toLowerCase()); /** * Obfuscate the response body. */ @@ -34,21 +30,26 @@ function obfuscateResponseBody(body, method) { return body; } - return (0, _lodash.defaults)({ result: fn(body.result) }, body); + return (0, _lodash.defaults)({ + result: fn(body.result) + }, body); } - /** * Obfuscate the response. */ + function obfuscateResponse(request, instance) { + if (request.type !== 'response') { + return; + } + if (!(0, _lodash.get)(request, 'response.body')) { return; } if ((0, _lodash.get)(request, `response.headers['content-type']`) === 'application/octet-stream') { request.response.body = '******'; - return; } @@ -60,19 +61,17 @@ function obfuscateResponse(request, instance) { if ((0, _lodash.isArray)(request.response.body)) { const methodsById = (0, _lodash.mapKeys)(requestBody, method => method.id); - request.response.body = (0, _lodash.map)(request.response.body, request => obfuscateResponseBody(request, methodsById[request.id].method)); - return; } request.response.body = obfuscateResponseBody(request.response.body, requestBody.method); } - /** * Obfuscate the request body. */ + function obfuscateRequestBody(body) { const method = (0, _lodash.get)(lowercaseMethods[body.method], 'obfuscate.request'); @@ -81,15 +80,18 @@ function obfuscateRequestBody(body) { } body.params = method(body.params); - return body; } - /** * Obfuscate the request. */ + function obfuscateRequest(request) { + if (request.type !== 'request') { + return; + } + if (!(0, _lodash.isString)(request.body)) { return; } @@ -104,23 +106,27 @@ function obfuscateRequest(request) { request.body = JSON.stringify(request.body); } - /** * Obfuscate headers. */ + function obfuscateHeaders(request) { + if (request.type !== 'request') { + return; + } + if (!(0, _lodash.has)(request, 'headers.authorization')) { return; } request.headers.authorization = request.headers.authorization.replace(/(Basic )(.*)/, `$1******`); } - /** * Export `RequestObfuscator`. */ + function obfuscate(request, instance) { obfuscateHeaders(request); obfuscateRequest(request); diff --git a/dist/src/methods.js b/dist/src/methods.js index 4c6e7f3..02e5b63 100755 --- a/dist/src/methods.js +++ b/dist/src/methods.js @@ -1,12 +1,13 @@ -'use strict'; +"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = void 0; -var _lodash = require('lodash'); +var _lodash = require("lodash"); -function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } } /* eslint-disable no-inline-comments */ +/* eslint-disable no-inline-comments */ /** * Module dependencies. @@ -15,140 +16,369 @@ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr /** * Export available rpc methods. */ - -exports.default = { - abandonTransaction: { version: '>=0.12.0' }, - addMultiSigAddress: { version: '>=0.1.0' }, - addNode: { version: '>=0.8.0' }, - addWitnessAddress: { version: '>=0.13.0' }, - backupWallet: { version: '>=0.3.12' }, - clearBanned: { version: '>=0.12.0' }, - createMultiSig: { version: '>=0.1.0' }, - createRawTransaction: { version: '>=0.7.0' }, - createWitnessAddress: { version: '>=0.13.0' }, - decodeRawTransaction: { version: '>=0.7.0' }, - decodeScript: { version: '>=0.9.0' }, - disconnectNode: { version: '>=0.12.0' }, +var _default = { + abandonTransaction: { + version: '>=0.12.0' + }, + abortRescan: { + version: '>=0.15.0' + }, + addMultiSigAddress: { + version: '>=0.1.0' + }, + addNode: { + version: '>=0.8.0' + }, + addWitnessAddress: { + version: '>=0.13.0' + }, + backupWallet: { + version: '>=0.3.12' + }, + bumpFee: { + version: '>=0.14.0' + }, + clearBanned: { + version: '>=0.12.0' + }, + combineRawTransaction: { + version: '>=0.15.0' + }, + createMultiSig: { + version: '>=0.1.0' + }, + createRawTransaction: { + version: '>=0.7.0' + }, + createWitnessAddress: { + version: '=0.13.0' + }, + decodeRawTransaction: { + version: '>=0.7.0' + }, + decodeScript: { + version: '>=0.9.0' + }, + disconnectNode: { + version: '>=0.12.0' + }, dumpPrivKey: { obfuscate: { response: () => '******' }, version: '>=0.6.0' }, - dumpWallet: { version: '>=0.9.0' }, + dumpWallet: { + version: '>=0.9.0' + }, encryptWallet: { obfuscate: { - request: params => (0, _lodash.set)([].concat(_toConsumableArray(params)), '[0]', '******') + request: params => (0, _lodash.set)([...params], '[0]', '******') }, version: '>=0.1.0' }, - estimateFee: { version: '>=0.10.0' }, - estimatePriority: { version: '>=0.10.0' }, - estimateSmartFee: { version: '>=0.12.0' }, - estimateSmartPriority: { version: '>=0.12.0' }, - fundRawTransaction: { version: '>=0.12.0' }, - generate: { version: '>=0.11.0' }, - generateToAddress: { version: '>=0.13.0' }, - getAccount: { version: '>=0.1.0' }, - getAccountAddress: { version: '>=0.3.18' }, - getAddedNodeInfo: { version: '>=0.8.0' }, - getAddressesByAccount: { version: '>=0.1.0' }, - getBalance: { version: '>=0.3.18' }, - getBestBlockHash: { version: '>=0.9.0' }, - getBlock: { version: '>=0.6.0' }, - getBlockCount: { version: '>=0.1.0' }, - getBlockHash: { version: '>=0.6.0' }, - getBlockHeader: { version: '>=0.12.0' }, - getBlockTemplate: { version: '>=0.7.0' }, - getBlockchainInfo: { version: '>=0.9.2' }, - getChainTips: { version: '>=0.10.0' }, - getConnectionCount: { version: '>=0.1.0' }, - getDifficulty: { version: '>=0.1.0' }, - getGenerate: { version: '<0.13.0' }, - getHashesPerSec: { version: '<0.10.0' }, - getInfo: { version: '>=0.1.0' }, - getMempoolAncestors: { version: '>=0.13.0' }, - getMempoolDescendants: { version: '>=0.13.0' }, - getMempoolEntry: { version: '>=0.13.0' }, - getMempoolInfo: { version: '>=0.10.0' }, - getMiningInfo: { version: '>=0.6.0' }, - getNetTotals: { version: '>=0.1.0' }, - getNetworkHashPs: { version: '>=0.9.0' }, - getNetworkInfo: { version: '>=0.9.2' }, - getNewAddress: { version: '>=0.1.0' }, - getPeerInfo: { version: '>=0.7.0' }, - getRawChangeAddress: { version: '>=0.9.0' }, - getRawMemPool: { version: '>=0.7.0' }, - getRawTransaction: { version: '>=0.7.0' }, - getReceivedByAccount: { version: '>=0.1.0' }, - getReceivedByAddress: { version: '>=0.1.0' }, - getTransaction: { version: '>=0.1.0' }, - getTxOut: { version: '>=0.7.0' }, - getTxOutProof: { version: '>=0.11.0' }, - getTxOutSetInfo: { version: '>=0.7.0' }, - getUnconfirmedBalance: { version: '>=0.9.0' }, - getWalletInfo: { version: '>=0.9.2' }, - getWork: { version: '<0.10.0' }, - help: { version: '>=0.1.0' }, - importAddress: { version: '>=0.10.0' }, + estimateFee: { + version: '>=0.10.0' + }, + estimatePriority: { + version: '>=0.10.0 <0.15.0' + }, + estimateSmartFee: { + version: '>=0.12.0' + }, + estimateSmartPriority: { + version: '>=0.12.0 <0.15.0' + }, + fundRawTransaction: { + version: '>=0.12.0' + }, + generate: { + version: '>=0.11.0' + }, + generateToAddress: { + version: '>=0.13.0' + }, + getAccount: { + version: '>=0.1.0' + }, + getAccountAddress: { + version: '>=0.3.18' + }, + getAddedNodeInfo: { + version: '>=0.8.0' + }, + getAddressesByAccount: { + version: '>=0.1.0' + }, + getBalance: { + version: '>=0.3.18' + }, + getBestBlockHash: { + version: '>=0.9.0' + }, + getBlock: { + version: '>=0.6.0' + }, + getBlockCount: { + version: '>=0.1.0' + }, + getBlockHash: { + version: '>=0.6.0' + }, + getBlockHeader: { + version: '>=0.12.0' + }, + getBlockTemplate: { + version: '>=0.7.0' + }, + getBlockchainInfo: { + version: '>=0.9.2' + }, + getChainTips: { + version: '>=0.10.0' + }, + getChainTxStats: { + version: '>=0.15.0' + }, + getConnectionCount: { + version: '>=0.1.0' + }, + getDifficulty: { + version: '>=0.1.0' + }, + getGenerate: { + version: '<0.13.0' + }, + getHashesPerSec: { + version: '<0.10.0' + }, + getInfo: { + version: '>=0.1.0' + }, + getMemoryInfo: { + version: '>=0.14.0' + }, + getMempoolAncestors: { + version: '>=0.13.0' + }, + getMempoolDescendants: { + version: '>=0.13.0' + }, + getMempoolEntry: { + version: '>=0.13.0' + }, + getMempoolInfo: { + version: '>=0.10.0' + }, + getMiningInfo: { + version: '>=0.6.0' + }, + getNetTotals: { + version: '>=0.1.0' + }, + getNetworkHashPs: { + version: '>=0.9.0' + }, + getNetworkInfo: { + version: '>=0.9.2' + }, + getNewAddress: { + version: '>=0.1.0' + }, + getPeerInfo: { + version: '>=0.7.0' + }, + getRawChangeAddress: { + version: '>=0.9.0' + }, + getRawMempool: { + version: '>=0.7.0' + }, + getRawTransaction: { + version: '>=0.7.0' + }, + getReceivedByAccount: { + version: '>=0.1.0' + }, + getReceivedByAddress: { + version: '>=0.1.0' + }, + getTransaction: { + version: '>=0.1.0' + }, + getTxOut: { + version: '>=0.7.0' + }, + getTxOutProof: { + version: '>=0.11.0' + }, + getTxOutSetInfo: { + version: '>=0.7.0' + }, + getUnconfirmedBalance: { + version: '>=0.9.0' + }, + getWalletInfo: { + version: '>=0.9.2' + }, + getWork: { + version: '<0.10.0' + }, + help: { + version: '>=0.1.0' + }, + importAddress: { + version: '>=0.10.0' + }, + importMulti: { + obfuscate: { + request: params => (0, _lodash.set)(params, '[0]', (0, _lodash.map)(params[0], request => (0, _lodash.set)(request, 'keys', (0, _lodash.map)(request.keys, () => '******')))) + }, + version: '>=0.14.0' + }, importPrivKey: { obfuscate: { request: () => ['******'] }, version: '>=0.6.0' }, - importPrunedFunds: { version: '>=0.13.0' }, - importPubKey: { version: '>=0.12.0' }, - importWallet: { version: '>=0.9.0' }, - keypoolRefill: { version: '>=0.1.0' }, - listAccounts: { version: '>=0.1.0' }, - listAddressGroupings: { version: '>=0.7.0' }, - listBanned: { version: '>=0.12.0' }, - listLockUnspent: { version: '>=0.8.0' }, - listReceivedByAccount: { version: '>=0.1.0' }, - listReceivedByAddress: { version: '>=0.1.0' }, - listSinceBlock: { version: '>=0.5.0' }, - listTransactions: { version: '>=0.3.18' }, - listUnspent: { version: '>=0.7.0' }, - lockUnspent: { version: '>=0.8.0' }, - move: { version: '>=0.3.18' }, - ping: { version: '>=0.9.0' }, - prioritiseTransaction: { version: '>=0.10.0' }, - removePrunedFunds: { version: '>=0.13.0' }, - sendFrom: { version: '>=0.3.18' }, - sendMany: { version: '>=0.3.21' }, - sendRawTransaction: { version: '>=0.7.0' }, - sendToAddress: { version: '>=0.1.0' }, - setAccount: { version: '>=0.1.0' }, - setBan: { version: '>=0.12.0' }, - setGenerate: { version: '<0.13.0' }, - setTxFee: { version: '>=0.3.22' }, - signMessage: { version: '>=0.5.0' }, + importPrunedFunds: { + version: '>=0.13.0' + }, + importPubKey: { + version: '>=0.12.0' + }, + importWallet: { + version: '>=0.9.0' + }, + keypoolRefill: { + version: '>=0.1.0' + }, + listAccounts: { + version: '>=0.1.0' + }, + listAddressGroupings: { + version: '>=0.7.0' + }, + listBanned: { + version: '>=0.12.0' + }, + listLockUnspent: { + version: '>=0.8.0' + }, + listReceivedByAccount: { + version: '>=0.1.0' + }, + listReceivedByAddress: { + version: '>=0.1.0' + }, + listSinceBlock: { + version: '>=0.5.0' + }, + listTransactions: { + version: '>=0.3.18' + }, + listUnspent: { + version: '>=0.7.0' + }, + listWallets: { + version: '>=0.15.0' + }, + lockUnspent: { + version: '>=0.8.0' + }, + move: { + version: '>=0.3.18' + }, + ping: { + version: '>=0.9.0' + }, + preciousBlock: { + version: '>=0.14.0' + }, + prioritiseTransaction: { + version: '>=0.10.0' + }, + pruneBlockchain: { + version: '>=0.14.0' + }, + removePrunedFunds: { + version: '>=0.13.0' + }, + sendFrom: { + version: '>=0.3.18' + }, + sendMany: { + version: '>=0.3.21' + }, + sendRawTransaction: { + version: '>=0.7.0' + }, + sendToAddress: { + version: '>=0.1.0' + }, + setAccount: { + version: '>=0.1.0' + }, + setBan: { + version: '>=0.12.0' + }, + setGenerate: { + version: '<0.13.0' + }, + setNetworkActive: { + version: '>=0.14.0' + }, + setTxFee: { + version: '>=0.3.22' + }, + signMessage: { + version: '>=0.5.0' + }, signMessageWithPrivKey: { obfuscate: { - request: params => (0, _lodash.set)([].concat(_toConsumableArray(params)), '[0]', '******') + request: params => (0, _lodash.set)([...params], '[0]', '******') }, version: '>=0.13.0' }, signRawTransaction: { obfuscate: { - request: params => (0, _lodash.set)([].concat(_toConsumableArray(params)), '[2]', (0, _lodash.map)(params[2], () => '******')) + request: params => (0, _lodash.set)([...params], '[2]', (0, _lodash.map)(params[2], () => '******')) }, version: '>=0.7.0' }, - stop: { version: '>=0.1.0' }, - submitBlock: { version: '>=0.7.0' }, - validateAddress: { version: '>=0.3.14' }, - verifyChain: { version: '>=0.9.0' }, - verifyMessage: { version: '>=0.5.0' }, - verifyTxOutProof: { version: '>0.11.0' }, - walletLock: { version: '>=0.1.0' }, + stop: { + version: '>=0.1.0' + }, + submitBlock: { + version: '>=0.7.0' + }, + upTime: { + version: '>=0.15.0' + }, + validateAddress: { + version: '>=0.3.14' + }, + verifyChain: { + version: '>=0.9.0' + }, + verifyMessage: { + version: '>=0.5.0' + }, + verifyTxOutProof: { + version: '>0.11.0' + }, + walletLock: { + version: '>=0.1.0' + }, walletPassphrase: { obfuscate: { - request: params => (0, _lodash.set)([].concat(_toConsumableArray(params)), '[0]', '******') + request: params => (0, _lodash.set)([...params], '[0]', '******') }, version: '>=0.1.0' }, - walletPassphraseChange: { version: '>=0.1.0' } + walletPassphraseChange: { + version: '>=0.1.0' + } }; -module.exports = exports['default']; \ No newline at end of file +exports.default = _default; \ No newline at end of file diff --git a/dist/src/parser.js b/dist/src/parser.js index 6de0127..6d402d9 100644 --- a/dist/src/parser.js +++ b/dist/src/parser.js @@ -1,45 +1,47 @@ -'use strict'; +"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = void 0; -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); -/** - * Module dependencies. - */ - -var _rpcError = require('./errors/rpc-error'); +var _jsonBigint = _interopRequireDefault(require("json-bigint")); -var _rpcError2 = _interopRequireDefault(_rpcError); +var _rpcError = _interopRequireDefault(require("./errors/rpc-error")); -var _lodash = require('lodash'); - -var _lodash2 = _interopRequireDefault(_lodash); +var _lodash = _interopRequireDefault(require("lodash")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** - * Get response result and errors. + * Module dependencies. */ -function get(body) { - var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, - _ref$headers = _ref.headers; - - let headers = _ref$headers === undefined ? false : _ref$headers, - response = _ref.response; +/** + * JSONBigInt parser. + */ +const { + parse +} = (0, _jsonBigint.default)({ + storeAsString: true, + strict: true +}); // eslint-disable-line new-cap - if (!body) { - throw new _rpcError2.default(response.statusCode, response.statusMessage); - } +/** + * Get RPC response body result. + */ +function getRpcResult(body, { + headers = false, + response +} = {}) { if (body.error !== null) { - throw new _rpcError2.default(_lodash2.default.get(body, 'error.code', -32603), _lodash2.default.get(body, 'error.message', 'An error occurred while processing the RPC call to bitcoind')); - } + throw new _rpcError.default(_lodash.default.get(body, 'error.code', -32603), _lodash.default.get(body, 'error.message', 'An error occurred while processing the RPC call to bitcoind')); + } // Defensive measure. This should not happen on a RPC call. + - if (!_lodash2.default.has(body, 'result')) { - throw new _rpcError2.default(-32700, 'Missing `result` on the RPC call result'); + if (!_lodash.default.has(body, 'result')) { + throw new _rpcError.default(-32700, 'Missing `result` on the RPC call result'); } if (headers) { @@ -48,43 +50,48 @@ function get(body) { return body.result; } - /** * Export Parser class. */ -class Parser { - constructor() { - var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - - let headers = _ref2.headers; +class Parser { + constructor({ + headers + } = {}) { this.headers = headers; } - /** * Parse rpc response. */ - rpc(_ref3) { - var _ref4 = _slicedToArray(_ref3, 2); - let response = _ref4[0], - body = _ref4[1]; + rpc([response, body]) { + // The RPC api returns a `text/html; charset=ISO-8859-1` encoded response with an empty string as the body + // when an error occurs. + if (typeof body === 'string' && response.headers['content-type'] !== 'application/json' && response.statusCode !== 200) { + throw new _rpcError.default(response.statusCode, response.statusMessage, { + body + }); + } // Parsing the body with custom parser to support BigNumbers. - // Body contains HTML (e.g. 401 Unauthorized). - if (typeof body === 'string' && response.statusCode !== 200) { - throw new _rpcError2.default(response.statusCode); - } + + body = parse(body); if (!Array.isArray(body)) { - return get(body, { headers: this.headers, response: response }); - } + return getRpcResult(body, { + headers: this.headers, + response + }); + } // Batch response parsing where each response may or may not be successful. + - // Batch response parsing where each response may or may not be successful. const batch = body.map(response => { try { - return get(response, { headers: false, response: response }); + return getRpcResult(response, { + headers: false, + response + }); } catch (e) { return e; } @@ -97,14 +104,24 @@ class Parser { return batch; } - rest(_ref5) { - var _ref6 = _slicedToArray(_ref5, 2); + rest(extension, [response, body]) { + // The REST api returns a `text/plain` encoded response with the error line and the control + // characters \r\n. For readability and debuggability, the error message is set to this content. + // When requesting a binary response, the body will be returned as a Buffer representation of + // this error string. + if (response.headers['content-type'] !== 'application/json' && response.statusCode !== 200) { + if (body instanceof Buffer) { + body = body.toString('utf-8'); + } + + throw new _rpcError.default(response.statusCode, body.replace('\r\n', ''), { + body + }); + } // Parsing the body with custom parser to support BigNumbers. - let response = _ref6[0], - body = _ref6[1]; - if (body.error) { - throw new _rpcError2.default(body.error.code, body.error.message); + if (extension === 'json') { + body = parse(body); } if (this.headers) { @@ -113,6 +130,7 @@ class Parser { return body; } + } -exports.default = Parser; -module.exports = exports['default']; \ No newline at end of file + +exports.default = Parser; \ No newline at end of file diff --git a/dist/src/requester.js b/dist/src/requester.js index 343425e..fa09abb 100644 --- a/dist/src/requester.js +++ b/dist/src/requester.js @@ -1,37 +1,37 @@ -'use strict'; +"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = void 0; -var _lodash = require('lodash'); +var _lodash = require("lodash"); /** - * Export Requester class. + * Module dependencies. */ +/** + * Export Requester class. + */ class Requester { - constructor() { - var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, - _ref$unsupported = _ref.unsupported; - - let unsupported = _ref$unsupported === undefined ? [] : _ref$unsupported, - version = _ref.version; - + constructor({ + unsupported = [], + version + } = {}) { this.unsupported = unsupported; this.version = version; } - /** * Prepare rpc request. */ - prepare(_ref2) { - let method = _ref2.method; - var _ref2$parameters = _ref2.parameters; - let parameters = _ref2$parameters === undefined ? [] : _ref2$parameters, - suffix = _ref2.suffix; + prepare({ + method, + parameters = [], + suffix + }) { method = method.toLowerCase(); if (this.version && (0, _lodash.includes)(this.unsupported, method)) { @@ -40,14 +40,11 @@ class Requester { return { id: `${Date.now()}${suffix !== undefined ? `-${suffix}` : ''}`, - method: method, + method, params: parameters }; } + } -exports.default = Requester; -/** - * Module dependencies. - */ -module.exports = exports['default']; \ No newline at end of file +exports.default = Requester; \ No newline at end of file diff --git a/package.json b/package.json index e60ae14..bfbc465 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bitcoin-core", - "version": "1.2.0", + "version": "2.0.0", "description": "A modern Bitcoin Core REST and RPC client.", "keywords": [ "bitcoin",