From eb1054b09994a68d0b3faaf2988411c60db2d01e Mon Sep 17 00:00:00 2001 From: Pedro Branco Date: Mon, 31 Jul 2023 16:11:35 +0100 Subject: [PATCH] wip --- README.md | 125 +++--------------------------------- docker-compose.yml | 27 +++----- package.json | 2 +- src/index.js | 46 +++++-------- src/parser.js | 22 +------ test/client_test.js | 83 +++--------------------- test/config/index.js | 16 ++--- test/config/ssl/cert.pem | 35 ---------- test/config/ssl/key.pem | 51 --------------- test/config/ssl/stunnel.pem | 86 ------------------------- test/parser_test.js | 26 ++------ 11 files changed, 56 insertions(+), 463 deletions(-) delete mode 100644 test/config/ssl/cert.pem delete mode 100644 test/config/ssl/key.pem delete mode 100644 test/config/ssl/stunnel.pem diff --git a/README.md b/README.md index 28f6e4b..2b6944a 100644 --- a/README.md +++ b/README.md @@ -23,59 +23,17 @@ npm install bitcoin-core --save ## Usage ### Client(...args) #### Arguments -1. `[agentOptions]` _(Object)_: Optional `agent` [options](https://github.com/request/request#using-optionsagentoptions) to configure SSL/TLS. -2. `[headers=false]` _(boolean)_: Whether to return the response headers. -3. `[host=localhost]` _(string)_: The host to connect to. +1. `[allowDefaultWallet=false]` _(boolean)_: Wether allows to use the default wallet. +2. `[headers={}]` _(object)_: Custom request headers. +3. `[host=http://localhost:8332]` _(string)_: The host to connect to. 4. `[logger=debugnyan('bitcoin-core')]` _(Function)_: Custom logger (by default, `debugnyan`). -5. `[network=mainnet]` _(string)_: The network -6. `[password]` _(string)_: The RPC server user password. -7. `[port=[network]]` _(string)_: The RPC server port. -8. `[ssl]` _(boolean|Object)_: Whether to use SSL/TLS with strict checking (_boolean_) or an expanded config (_Object_). -9. `[ssl.enabled]` _(boolean)_: Whether to use SSL/TLS. -10. `[ssl.strict]` _(boolean)_: Whether to do strict SSL/TLS checking (certificate must match host). -11. `[timeout=30000]` _(number)_: How long until the request times out (ms). -12. `[username]` _(number)_: The RPC server user name. -13. `[version]` _(string)_: Which version to check methods for ([read more](#versionchecking)). -14. `[wallet]` _(string)_: Which wallet to manage ([read more](#multiwallet)). +5. `[password]` _(string)_: The RPC server user password. +6. `[timeout=30000]` _(number)_: How long until the request times out (ms). +7. `[username]` _(number)_: The RPC server user name. +8. `[version]` _(string)_: Which version to check methods for ([read more](#versionchecking)). +9. `[wallet]` _(string)_: Which wallet to manage ([read more](#multiwallet)). ### Examples -#### Using network mode -The `network` will automatically determine the port to connect to, just like the `bitcoind` and `bitcoin-cli` commands. - -```js -const Client = require('bitcoin-core'); -const client = new Client({ network: 'regtest' }); -``` - -##### Setting a custom port - -```js -const client = new Client({ port: 28332 }); -``` - -#### Connecting to an SSL/TLS server with strict checking enabled -By default, when `ssl` is enabled, strict checking is implicitly enabled. - -```js -const fs = require('fs'); -const client = new Client({ - agentOptions: { - ca: fs.readFileSync('/etc/ssl/bitcoind/cert.pem') - }, - ssl: true -}); -``` - -#### Connecting to an SSL/TLS server without strict checking enabled - -```js -const client = new Client({ - ssl: { - enabled: true, - strict: false - } -}); -``` #### Using promises to process the response @@ -91,19 +49,6 @@ Callback support was removed. Since every method returns a `Promise`, [callbacki util.callbackify(() => client.getInfo())((error, help) => console.log(help)); ``` -#### Returning headers in the response -For compatibility with other Bitcoin Core clients. - -```js -const client = new Client({ headers: true }); - -// Promise style with headers enabled: -client.getInfo().then(([body, headers]) => console.log(body, headers)); - -// Await style based on promises with headers enabled: -const [body, headers] = await client.getInfo(); -``` - ## Named parameters Since version v0.14.0, it is possible to send commands via the JSON-RPC interface using named parameters instead of positional ones. This comes with the advantage of making the order of arguments irrelevant. It also helps improving the readability of certain function calls when leaving out arguments for their default value. @@ -223,8 +168,6 @@ docker run --rm -it ruimarinho/bitcoin-core:0.12-alpine -printtoconsole -rpcuser These configuration values may also be set on the `bitcoin.conf` file of your platform installation. -By default, port `8332` is used to listen for requests in `mainnet` mode, or `18332` in `testnet` and `regtest` modes (the regtest change will be changed to `18443` in [0.16](https://github.com/bitcoin/bitcoin/pull/10825)). Use the `network` property to initialize the client on the desired mode and automatically set the respective default port. You can optionally set a custom port of your choice too. - The RPC services binds to the localhost loopback network interface, so use `rpcbind` to change where to bind to and `rpcallowip` to whitelist source IP access. #### Methods @@ -386,58 +329,8 @@ client.getUnspentTransactionOutputs([{ }], { extension: 'json' }) ``` -### SSL -This client supports SSL out of the box. Simply pass the SSL public certificate to the client and optionally disable strict SSL checking which will bypass SSL validation (the connection is still encrypted but the server it is connecting to may not be trusted). This is, of course, discouraged unless for testing purposes when using something like self-signed certificates. - -#### Generating a self-signed certificates for testing purposes -Please note that the following procedure should only be used for testing purposes. - -Generate an self-signed certificate together with an unprotected private key: - -```sh -openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 3650 -nodes -``` - #### Connecting via SSL -On Bitcoin Core <0.12, you can start the `bitcoind` RPC server directly with SSL: - -```sh -docker run --rm -it -v $(PWD)/ssl:/etc/ssl ruimarinho/bitcoin-core:0.11-alpine -printtoconsole -rpcuser=foo -rpcpassword=bar -rpcssl -rpcsslcertificatechainfile=/etc/ssl/bitcoind/cert.pem -rpcsslprivatekeyfile=/etc/ssl/bitcoind/key.pem -server -``` - -On Bitcoin Core >0.12, use must use `stunnel` (`brew install stunnel` or `sudo apt-get install stunnel4`) or an HTTPS reverse proxy to configure SSL since the built-in support for SSL has been removed. The trade off with `stunnel` is performance and simplicity versus features, as it lacks more powerful capacities such as Basic Authentication and caching which are standard in reverse proxies. - -You can use `stunnel` by configuring `stunnel.conf` with the following service requirements: - -``` -[bitcoin] -accept = 28332 -connect = 18332 -cert = /etc/ssl/bitcoind/cert.pem -key = /etc/ssl/bitcoind/key.pem -``` - -The `key` option may be omitted if you concatenating your private and public certificates into a single `stunnel.pem` file. - -On some versions of `stunnel` it is also possible to start a service using command line arguments. The equivalent would be: - -```sh -stunnel -d 28332 -r 127.0.0.1:18332 -p stunnel.pem -P '' -``` - -Then pass the public certificate to the client: - -```js -const Client = require('bitcoin-core'); -const fs = require('fs'); -const client = new Client({ - agentOptions: { - ca: fs.readFileSync('/etc/ssl/bitcoind/cert.pem') - }, - port: 28332, - ssl: true -}); -``` +Deprecated since release 0.5.0. ## Logging diff --git a/docker-compose.yml b/docker-compose.yml index b60b674..696a384 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.4' services: bitcoin-core: - image: ruimarinho/bitcoin-core:0.17 + image: ruimarinho/bitcoin-core:24.0.1 command: -printtoconsole -regtest=1 @@ -22,14 +22,14 @@ services: timeout: 2s bitcoin-core-multi-wallet: - image: ruimarinho/bitcoin-core:0.17 + image: ruimarinho/bitcoin-core:24.0.1 command: -printtoconsole -regtest=1 -rest -rpcallowip=::/0 -rpcpassword=bar - -wallet + -wallet=wallet -wallet=wallet1 -wallet=wallet2 -rpcport=18443 @@ -44,43 +44,36 @@ services: start_period: 2s timeout: 2s - bitcoin-core-ssl: - image: ruimarinho/bitcoin-core:0.11 + bitcoin-core-username-only: + image: ruimarinho/bitcoin-core:24.0.1 command: -printtoconsole -regtest=1 -rest -rpcallowip=::/0 - -rpcpassword=bar -rpcport=18443 - -rpcssl - -rpcsslcertificatechainfile=/etc/ssl/bitcoind/cert.pem - -rpcsslprivatekeyfile=/etc/ssl/bitcoind/key.pem -rpcuser=foo -server - volumes: - - ./test/config/ssl:/etc/ssl/bitcoind ports: - - 18463:18443 + - 18473:18443 healthcheck: - test: curl --fail -k "https://foo@localhost:18443/rest/chaininfo.json" || exit 1 + test: curl --fail "http://foo@localhost:18443/rest/chaininfo.json" || exit 1 interval: 2s retries: 100 start_period: 2s timeout: 2s - bitcoin-core-username-only: - image: ruimarinho/bitcoin-core:0.11 + bitcoin-core-no-auth: + image: ruimarinho/bitcoin-core:24.0.1 command: -printtoconsole -regtest=1 -rest -rpcallowip=::/0 -rpcport=18443 - -rpcuser=foo -server ports: - - 18473:18443 + - 18483:18443 healthcheck: test: curl --fail "http://foo@localhost:18443/rest/chaininfo.json" || exit 1 interval: 2s diff --git a/package.json b/package.json index ff93dee..8d0e310 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "scripts": { "changelog": "github_changelog_generator --project bitcoin-core --user ruimarinho --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": "nyc --reporter=html --reporter=text npm test", - "dependencies": "docker-compose up -d bitcoind bitcoind-ssl bitcoind-username-only", + "dependencies": "docker-compose up -d bitcoind bitcoind-username-only", "lint": "eslint src test", "test": "NODE_ENV=test mocha $npm_package_options_mocha", "testdocker": "docker-compose run --rm sut", diff --git a/src/index.js b/src/index.js index 209d1b3..2e6f017 100644 --- a/src/index.js +++ b/src/index.js @@ -11,16 +11,6 @@ const methods = require('./methods'); const requestLogger = require('./logging/request-logger'); const semver = require('semver'); -/** - * List of networks and their default port mapping. - */ - -const networks = { - mainnet: 8332, - regtest: 18332, - testnet: 18332 -}; - /** * Promisify helper. */ @@ -43,36 +33,22 @@ const promisify = fn => (...args) => new Promise((resolve, reject) => { class Client { constructor({ - agentOptions, allowDefaultWallet = false, - headers = false, - host = 'localhost', + headers = {}, + host = 'http://localhost:8332', logger = debugnyan('bitcoin-core'), - network = 'mainnet', password, - port, - ssl = false, timeout = 30000, username, version, wallet } = {}) { - if (!_.has(networks, network)) { - throw new Error(`Invalid network name "${network}"`, { network }); - } - - this.agentOptions = agentOptions; this.allowDefaultWallet = allowDefaultWallet; 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.ssl = { - enabled: _.get(ssl, 'enabled', ssl), - strict: _.get(ssl, 'strict', _.get(ssl, 'enabled', ssl)) - }; this.timeout = timeout; this.wallet = wallet; @@ -106,15 +82,14 @@ class Client { const request = requestLogger(logger); this.request = request.defaults({ - agentOptions: this.agentOptions, - baseUrl: `${this.ssl.enabled ? 'https' : 'http'}://${this.host}:${this.port}`, - strictSSL: this.ssl.strict, + baseUrl: this.host, + headers: this.headers, timeout: this.timeout }); this.request.getAsync = promisify(this.request.get); this.request.postAsync = promisify(this.request.post); this.requester = new Requester({ methods: this.methods, version }); - this.parser = new Parser({ headers: this.headers }); + this.parser = new Parser(); } /** @@ -154,9 +129,18 @@ class Client { uri = '/wallet/'; } + if (this.auth) { + return this.parser.rpc(await this.request.postAsync({ + auth: _.pickBy(this.auth, _.identity), + body: JSON.stringify(body), + followRedirect: true, + uri + })); + } + return this.parser.rpc(await this.request.postAsync({ - auth: _.pickBy(this.auth, _.identity), body: JSON.stringify(body), + followRedirect: true, uri })); } diff --git a/src/parser.js b/src/parser.js index 300e348..8854946 100644 --- a/src/parser.js +++ b/src/parser.js @@ -17,7 +17,7 @@ const { parse } = JSONBigInt({ storeAsString: true, strict: true }); // eslint-d * Get RPC response body result. */ -function getRpcResult(body, { headers = false, response } = {}) { +function getRpcResult(body) { if (body.error !== null) { throw new RpcError( _.get(body, 'error.code', -32603), @@ -30,10 +30,6 @@ function getRpcResult(body, { headers = false, response } = {}) { throw new RpcError(-32700, 'Missing `result` on the RPC call result'); } - if (headers) { - return [body.result, response.headers]; - } - return body.result; } @@ -42,10 +38,6 @@ function getRpcResult(body, { headers = false, response } = {}) { */ module.exports = class Parser { - constructor({ headers } = {}) { - this.headers = headers; - } - /** * Parse rpc response. */ @@ -61,22 +53,18 @@ module.exports = class Parser { const body = parse(response.body); if (!Array.isArray(body)) { - return getRpcResult(body, { headers: this.headers, response }); + return getRpcResult(body); } // Batch response parsing where each response may or may not be successful. const batch = body.map(response => { try { - return getRpcResult(response, { headers: false, response }); + return getRpcResult(response); } catch (e) { return e; } }); - if (this.headers) { - return [batch, response.headers]; - } - return batch; } @@ -98,10 +86,6 @@ module.exports = class Parser { response.body = parse(response.body); } - if (this.headers) { - return [response.body, response.headers]; - } - return response.body; } }; diff --git a/test/client_test.js b/test/client_test.js index 55a5225..13b188c 100644 --- a/test/client_test.js +++ b/test/client_test.js @@ -46,38 +46,17 @@ describe('Client', () => { }); it('should not return headers by default', () => { - should(new Client().headers).be.false(); + should(new Client().returnResponseHeaders).be.false(); }); it('should have default host set to `localhost`', () => { - should(new Client().host).equal('localhost'); + should(new Client().host).equal('http://localhost:8332'); }); it('should not have a password set by default', () => { should.not.exist(new Client().password); }); - it('should have default port set to `mainnet`\'s one', () => { - should(new Client().port).equal(8332); - }); - - it('should set default to port `8332` if network is `mainnet`', () => { - should(new Client({ network: 'mainnet' }).port).equal(8332); - }); - - it('should set default to port `18332` if network is `testnet`', () => { - should(new Client({ network: 'testnet' }).port).equal(18332); - }); - - it('should set default to port `18332` if network is `regtest`', () => { - should(new Client({ network: 'regtest' }).port).equal(18332); - }); - - it('should not have ssl enabled by default', () => { - should(new Client().ssl.enabled).equal(false); - should(new Client().ssl.strict).equal(false); - }); - it('should have default timeout of 30000ms', () => { should(new Client().timeout).equal(30000); }); @@ -125,7 +104,7 @@ describe('Client', () => { it('should throw an error if a connection cannot be established', async () => { try { - await new Client(_.defaults({ port: 9897 }, config.bitcoin)).getDifficulty(); + await new Client(_.defaults({ hostname: 'http://localhost:9897' }, config.bitcoin)).getDifficulty(); should.fail(); } catch (e) { @@ -136,56 +115,6 @@ describe('Client', () => { }); }); - describe('ssl', () => { - it('should use `ssl.strict` by default when `ssl` is enabled', () => { - const sslClient = new Client(_.defaults({ host: config.bitcoinSsl.host, port: config.bitcoinSsl.port, ssl: true }, config.bitcoin)); - - should(sslClient.ssl.strict).be.true(); - }); - - it('should throw an error if certificate is self signed by default', async () => { - const sslClient = new Client(_.defaults({ host: config.bitcoinSsl.host, port: config.bitcoinSsl.port, ssl: true }, config.bitcoin)); - - should(sslClient.ssl.strict).be.true(); - - try { - await sslClient.getInfo(); - } catch (e) { - should(e).be.an.instanceOf(Error); - should(e.code).equal('DEPTH_ZERO_SELF_SIGNED_CERT'); - should(e.message).match(/self[ -]signed certificate/); - } - }); - - 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 */ - ca: fs.readFileSync(path.join(__dirname, '/config/ssl/cert.pem')), - checkServerIdentity() { - // Skip server identity checks otherwise the certificate would be immediately rejected - // as connecting to an IP not listed in the `altname` fails. - return; - } - }, - host: config.bitcoinSsl.host, - port: config.bitcoinSsl.port, - ssl: true - }, config.bitcoin)); - - const info = await sslClient.getInfo(); - - should(info).not.be.empty(); - }); - - it('should establish a connection if certificate is self signed but `ssl.strict` is disabled', async () => { - const sslClient = new Client(_.defaults({ host: config.bitcoinSsl.host, port: config.bitcoinSsl.port, ssl: { enabled: true, strict: false } }, config.bitcoin)); - const info = await sslClient.getInfo(); - - should(info).not.be.empty(); - }); - }); - describe('authentication', () => { it('should throw an error if credentials are invalid', async () => { try { @@ -203,6 +132,12 @@ describe('Client', () => { should(difficulty).equal(0); }); + + it('should support without no auth', async () => { + const difficulty = await new Client(config.bitcoinNoAuth).getDifficulty(); + + should(difficulty).equal(0); + }); }); }); }); diff --git a/test/config/index.js b/test/config/index.js index e04b7e7..0089755 100644 --- a/test/config/index.js +++ b/test/config/index.js @@ -9,26 +9,20 @@ module.exports = { bitcoin: { - host: 'localhost', + host: 'http://localhost:18443', password: 'bar', - port: 18443, username: 'foo' }, bitcoinMultiWallet: { - host: 'localhost', + host: 'http://localhost:18453', password: 'bar', - port: 18453, username: 'foo' }, - bitcoinSsl: { - host: 'localhost', - password: 'bar', - port: 18463, - username: 'foo' + bitcoinNoAuth: { + host: 'http://localhost:18483' }, bitcoinUsernameOnly: { - host: 'localhost', - port: 18473, + host: 'http://localhost:18473', username: 'foo' } }; diff --git a/test/config/ssl/cert.pem b/test/config/ssl/cert.pem deleted file mode 100644 index 541381f..0000000 --- a/test/config/ssl/cert.pem +++ /dev/null @@ -1,35 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIGGDCCBACgAwIBAgIJAOteNnjcS1PLMA0GCSqGSIb3DQEBBQUAMGUxCzAJBgNV -BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp -c2NvMRYwFAYDVQQKEw1EZWNlbnRyYWxpemVkMREwDwYDVQQDEwhiaXRjb2luZDAe -Fw0xNjAxMTQwMDQ5MTJaFw0yNjAxMTEwMDQ5MTJaMGUxCzAJBgNVBAYTAlVTMRMw -EQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRYwFAYD -VQQKEw1EZWNlbnRyYWxpemVkMREwDwYDVQQDEwhiaXRjb2luZDCCAiIwDQYJKoZI -hvcNAQEBBQADggIPADCCAgoCggIBAJl9zk2UfZvw4PC8VWFYqR6bMcl7gGEIi1i6 -yTJOtEb2r2BmUTMGQtsS1cAOKdYIlqm+pkUqjS/uZ//HrDUiXok1Y7ZF+vN4Cpt0 -0ro47wVD/LjZT949J7T+kzH0LdLUTB1TrLyFXB3hDlnPXCm3ZI7BkUkwB0yGb9Ni -jAFBe2BWrIDT2jGumJ+OAkNO6RtlgoBKRePRpw4g+IXgA49KAw/cjwyaJBU+Wtb/ -yqVcY0A593lyLOhE2jMsMiA6OA2AADzwPoChV/wcRSRx4APdPNo0c2zAYLAIj51G -mwwHS6pA7pgVMKR7nHROBERH3HAl/c67/HFS7ni7grauve98h/VGsyguxW78gnBl -nTvQ40ydhg5vBF/TZpFqaWlqttS7utzhrddPyoeNnkojvr3reGiFm6Gv7cN0D1yE -r4DkXcf5AvR92MledvAwnyv9cw0cixNMobAFkUH1Hd3loSgOau0wBI8qgFOytJEE -6CTi/Ye3G0h4ZTec8xMr88HGT0ooeMfbYhRYZDhYU3DSOvKEWNcqFmdFvEp0mQLx -7x2QwBVj3e6Rh/W6rI0XJMnfKDwDn7VQr22+ByR3FDjRqY/SfTkBeyA1dIuFSFB9 -2qi0B38tTFuLMixhXTVrlTBo4/qNCfil22MgOy8CYddToK1JIjyvDJyjIDGxNbD5 -ZjDHJ+tTAgMBAAGjgcowgccwHQYDVR0OBBYEFMihKE31BstFz7ff9ILwHmS4lNga -MIGXBgNVHSMEgY8wgYyAFMihKE31BstFz7ff9ILwHmS4lNgaoWmkZzBlMQswCQYD -VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j -aXNjbzEWMBQGA1UEChMNRGVjZW50cmFsaXplZDERMA8GA1UEAxMIYml0Y29pbmSC -CQDrXjZ43EtTyzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQA7gviw -BFS1AkWc1AqA3yeZrTa6+QZmC6eTQHsCAGIf9VJvVkSsBBAlZtgpU52Z4r9JDTlS -B5ZYKucwOcsXixV9hvjkkr0ISpsjR/5XBbVpqz2/Lue56WH5f7DwxPnGn85CI/fP -vPbGaJYVM+JPe6d0LbiaxFw0R8NNQ96qYaD7ZA1iYPlePWzMPj39YcxtAbK3Ds4g -VDEpfM1BOH0MyX/ZbhEsCFG6egWqflM7A2j7Uvm6LRqayzoD+OhFzNE+Y3zQ9MnS -CkgYSrlIFJVGO6tlFGCEoYgefdKpWuJ2dCxPQwCrBKm9MzD9vBl6bG3Pnr0NR+mU -CdSTITkmMRFkVJtFIX0PnBsIefkZW4aSB01ssNVQ+hZqeWht8hmBQqV3PuqheCj+ -wFRj/a1QAvWC9ayJY2+jzd2MhiXWVXrpEtum8pic+BZmvp3C1RItIi89o/NGN+7c -uPuhD9MHv9DqJFvtOE605xt+90JEsvcbUP72YhtbKAG38dGffKCBX3NP355N/KM2 -fmea8fi9OvsDnPti7UVG1QjDqo+JZ6H7cOmMA725LOsnT8Fj4Yt61HQkZ7TuObRD -tiqlzRR0c1kdviX7MKIedtSrdSmvqIS1qG+VlTbDzQyhXLNZgg3RbzW/92844WyE -p7eXPW1MUbAi6dtHXHPt4RzPwXYz8y35WVk7iQ== ------END CERTIFICATE----- diff --git a/test/config/ssl/key.pem b/test/config/ssl/key.pem deleted file mode 100644 index c43bd89..0000000 --- a/test/config/ssl/key.pem +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -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 ------END RSA PRIVATE KEY----- diff --git a/test/config/ssl/stunnel.pem b/test/config/ssl/stunnel.pem deleted file mode 100644 index 8ed261d..0000000 --- a/test/config/ssl/stunnel.pem +++ /dev/null @@ -1,86 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -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 ------END RSA PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIGGDCCBACgAwIBAgIJAOteNnjcS1PLMA0GCSqGSIb3DQEBBQUAMGUxCzAJBgNV -BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp -c2NvMRYwFAYDVQQKEw1EZWNlbnRyYWxpemVkMREwDwYDVQQDEwhiaXRjb2luZDAe -Fw0xNjAxMTQwMDQ5MTJaFw0yNjAxMTEwMDQ5MTJaMGUxCzAJBgNVBAYTAlVTMRMw -EQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRYwFAYD -VQQKEw1EZWNlbnRyYWxpemVkMREwDwYDVQQDEwhiaXRjb2luZDCCAiIwDQYJKoZI -hvcNAQEBBQADggIPADCCAgoCggIBAJl9zk2UfZvw4PC8VWFYqR6bMcl7gGEIi1i6 -yTJOtEb2r2BmUTMGQtsS1cAOKdYIlqm+pkUqjS/uZ//HrDUiXok1Y7ZF+vN4Cpt0 -0ro47wVD/LjZT949J7T+kzH0LdLUTB1TrLyFXB3hDlnPXCm3ZI7BkUkwB0yGb9Ni -jAFBe2BWrIDT2jGumJ+OAkNO6RtlgoBKRePRpw4g+IXgA49KAw/cjwyaJBU+Wtb/ -yqVcY0A593lyLOhE2jMsMiA6OA2AADzwPoChV/wcRSRx4APdPNo0c2zAYLAIj51G -mwwHS6pA7pgVMKR7nHROBERH3HAl/c67/HFS7ni7grauve98h/VGsyguxW78gnBl -nTvQ40ydhg5vBF/TZpFqaWlqttS7utzhrddPyoeNnkojvr3reGiFm6Gv7cN0D1yE -r4DkXcf5AvR92MledvAwnyv9cw0cixNMobAFkUH1Hd3loSgOau0wBI8qgFOytJEE -6CTi/Ye3G0h4ZTec8xMr88HGT0ooeMfbYhRYZDhYU3DSOvKEWNcqFmdFvEp0mQLx -7x2QwBVj3e6Rh/W6rI0XJMnfKDwDn7VQr22+ByR3FDjRqY/SfTkBeyA1dIuFSFB9 -2qi0B38tTFuLMixhXTVrlTBo4/qNCfil22MgOy8CYddToK1JIjyvDJyjIDGxNbD5 -ZjDHJ+tTAgMBAAGjgcowgccwHQYDVR0OBBYEFMihKE31BstFz7ff9ILwHmS4lNga -MIGXBgNVHSMEgY8wgYyAFMihKE31BstFz7ff9ILwHmS4lNgaoWmkZzBlMQswCQYD -VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j -aXNjbzEWMBQGA1UEChMNRGVjZW50cmFsaXplZDERMA8GA1UEAxMIYml0Y29pbmSC -CQDrXjZ43EtTyzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQA7gviw -BFS1AkWc1AqA3yeZrTa6+QZmC6eTQHsCAGIf9VJvVkSsBBAlZtgpU52Z4r9JDTlS -B5ZYKucwOcsXixV9hvjkkr0ISpsjR/5XBbVpqz2/Lue56WH5f7DwxPnGn85CI/fP -vPbGaJYVM+JPe6d0LbiaxFw0R8NNQ96qYaD7ZA1iYPlePWzMPj39YcxtAbK3Ds4g -VDEpfM1BOH0MyX/ZbhEsCFG6egWqflM7A2j7Uvm6LRqayzoD+OhFzNE+Y3zQ9MnS -CkgYSrlIFJVGO6tlFGCEoYgefdKpWuJ2dCxPQwCrBKm9MzD9vBl6bG3Pnr0NR+mU -CdSTITkmMRFkVJtFIX0PnBsIefkZW4aSB01ssNVQ+hZqeWht8hmBQqV3PuqheCj+ -wFRj/a1QAvWC9ayJY2+jzd2MhiXWVXrpEtum8pic+BZmvp3C1RItIi89o/NGN+7c -uPuhD9MHv9DqJFvtOE605xt+90JEsvcbUP72YhtbKAG38dGffKCBX3NP355N/KM2 -fmea8fi9OvsDnPti7UVG1QjDqo+JZ6H7cOmMA725LOsnT8Fj4Yt61HQkZ7TuObRD -tiqlzRR0c1kdviX7MKIedtSrdSmvqIS1qG+VlTbDzQyhXLNZgg3RbzW/92844WyE -p7eXPW1MUbAi6dtHXHPt4RzPwXYz8y35WVk7iQ== ------END CERTIFICATE----- diff --git a/test/parser_test.js b/test/parser_test.js index 7cdf3ff..c1ee93a 100644 --- a/test/parser_test.js +++ b/test/parser_test.js @@ -24,7 +24,7 @@ afterEach(() => { describe('Parser', () => { it('should throw an error with a generic message if one is not returned on the response', async () => { - nock(`http://${config.bitcoin.host}:${config.bitcoin.port}/`) + nock(config.bitcoin.host) .post('/') .reply(200, '{ "result": null, "error": { "code": -32601 }, "id": "69837016239933"}'); @@ -40,7 +40,7 @@ describe('Parser', () => { }); it('should throw an error if the response does not include a `result`', async () => { - nock(`http://${config.bitcoin.host}:${config.bitcoin.port}/`) + nock(config.bitcoin.host) .post('/') .reply(200, '{ "error": null, "id": "69837016239933"}'); @@ -58,30 +58,12 @@ describe('Parser', () => { it('should throw an error if the response is not successful but is json-formatted', async () => { try { await new Client(_.defaults({ wallet: 'foobar' }, config.bitcoinMultiWallet)).getWalletInfo(); + + should.fail(); } catch (e) { should(e).be.an.instanceOf(RpcError); should(e.message).equal('Requested wallet does not exist or is not loaded'); should(e.code).equal(-18); } }); - - describe('headers', () => { - it('should return the response headers if `headers` is enabled', async () => { - const [info, headers] = await new Client(_.defaults({ headers: true }, config.bitcoin)).getNetworkInfo(); - - should(info).be.an.Object(); - should(headers).have.keys('date', 'connection', 'content-length', 'content-type'); - }); - - it('should return the response headers if `headers` is enabled and batching is used', async () => { - const batch = [ - { method: 'getbalance' }, - { method: 'getbalance' } - ]; - const [addresses, headers] = await new Client(_.defaults({ headers: true }, config.bitcoin)).command(batch); - - should(addresses).have.length(batch.length); - should(headers).have.keys('date', 'connection', 'content-length', 'content-type'); - }); - }); });