Compare commits
No commits in common. "master" and "v2.3.2" have entirely different histories.
22
.travis.yml
22
.travis.yml
@ -1,18 +1,14 @@
|
|||||||
# need sudo for docker
|
|
||||||
sudo: required
|
|
||||||
|
|
||||||
language: node_js
|
language: node_js
|
||||||
|
|
||||||
# skip install step (npm install)
|
node_js:
|
||||||
# See http://docs.travis-ci.com/user/customizing-the-build/#Skipping-the-Installation-Step
|
- "0.10"
|
||||||
install: true
|
- "0.12"
|
||||||
|
- "iojs"
|
||||||
|
|
||||||
services:
|
before_install:
|
||||||
- docker
|
- sudo add-apt-repository --yes ppa:bitcoin/bitcoin
|
||||||
|
- sudo apt-get update
|
||||||
|
- sudo apt-get install bitcoind
|
||||||
|
|
||||||
before_script:
|
after_install:
|
||||||
- git submodule update --init
|
- git submodule update --init
|
||||||
- docker build -t node-bitcoin .
|
|
||||||
|
|
||||||
script:
|
|
||||||
- docker run node-bitcoin
|
|
||||||
|
|||||||
16
Changelog.md
16
Changelog.md
@ -1,21 +1,5 @@
|
|||||||
# node-bitcoin changelog
|
# node-bitcoin changelog
|
||||||
|
|
||||||
## v3.0.1 (2015/10/25)
|
|
||||||
* fix redefinition of already defined variable (does not actually affect behavior)
|
|
||||||
|
|
||||||
## v3.0.0 (2015/10/18)
|
|
||||||
* make public domain license explicit
|
|
||||||
* remove commands dropped in bitcoind v0.11
|
|
||||||
* `getHashesPerSecond`
|
|
||||||
* `getHashesPerSec`
|
|
||||||
* add missing commands for bitcoind v0.11
|
|
||||||
* `generate`
|
|
||||||
* `verifyTxOutProof`
|
|
||||||
|
|
||||||
## v2.4.0 (2015/07/16)
|
|
||||||
* don't lazy-load http/https modules
|
|
||||||
* add command for bitcoind v0.11.0: `getTxOutProof`
|
|
||||||
|
|
||||||
## v2.3.2 (2015/06/26)
|
## v2.3.2 (2015/06/26)
|
||||||
* fix bug in test suite that was supposed to detect missing commands
|
* fix bug in test suite that was supposed to detect missing commands
|
||||||
* add missing commands
|
* add missing commands
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
# Dockerfile for running node-bitcoin tests
|
|
||||||
FROM freewil/bitcoin-testnet-box
|
FROM freewil/bitcoin-testnet-box
|
||||||
MAINTAINER Sean Lavine <lavis88@gmail.com>
|
MAINTAINER Sean Lavine <lavis88@gmail.com>
|
||||||
|
|
||||||
# install node.js
|
# install node.js (sudo for bash needed?)
|
||||||
USER root
|
USER root
|
||||||
RUN apt-get install --yes curl
|
RUN apt-get install --yes curl
|
||||||
RUN curl --silent --location https://deb.nodesource.com/setup_0.12 | bash -
|
RUN curl -sL https://deb.nodesource.com/setup_0.12 | bash -
|
||||||
RUN apt-get install --yes nodejs
|
RUN apt-get install --yes nodejs
|
||||||
|
|
||||||
# set permissions for tester user on project
|
# set permissions for tester user on project
|
||||||
|
|||||||
24
LICENSE
24
LICENSE
@ -1,24 +0,0 @@
|
|||||||
This is free and unencumbered software released into the public domain.
|
|
||||||
|
|
||||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
||||||
distribute this software, either in source code form or as a compiled
|
|
||||||
binary, for any purpose, commercial or non-commercial, and by any
|
|
||||||
means.
|
|
||||||
|
|
||||||
In jurisdictions that recognize copyright laws, the author or authors
|
|
||||||
of this software dedicate any and all copyright interest in the
|
|
||||||
software to the public domain. We make this dedication for the benefit
|
|
||||||
of the public at large and to the detriment of our heirs and
|
|
||||||
successors. We intend this dedication to be an overt act of
|
|
||||||
relinquishment in perpetuity of all present and future rights to this
|
|
||||||
software under copyright law.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
||||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
||||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
For more information, please refer to <http://unlicense.org/>
|
|
||||||
20
Readme.md
20
Readme.md
@ -1,25 +1,7 @@
|
|||||||
# node-bitcoin
|
# node-bitcoin [](https://travis-ci.org/freewil/node-bitcoin)
|
||||||
[![travis][travis-image]][travis-url]
|
|
||||||
[![npm][npm-image]][npm-url]
|
|
||||||
[![downloads][downloads-image]][downloads-url]
|
|
||||||
[![js-standard-style][standard-image]][standard-url]
|
|
||||||
|
|
||||||
[travis-image]: https://travis-ci.org/freewil/node-bitcoin.svg?branch=master
|
|
||||||
[travis-url]: https://travis-ci.org/freewil/node-bitcoin
|
|
||||||
|
|
||||||
[npm-image]: https://img.shields.io/npm/v/bitcoin.svg?style=flat
|
|
||||||
[npm-url]: https://npmjs.org/package/bitcoin
|
|
||||||
|
|
||||||
[downloads-image]: https://img.shields.io/npm/dm/bitcoin.svg?style=flat
|
|
||||||
[downloads-url]: https://npmjs.org/package/bitcoin
|
|
||||||
|
|
||||||
[standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat
|
|
||||||
[standard-url]: http://standardjs.com
|
|
||||||
|
|
||||||
node-bitcoin is a simple wrapper for the Bitcoin client's JSON-RPC API.
|
node-bitcoin is a simple wrapper for the Bitcoin client's JSON-RPC API.
|
||||||
|
|
||||||
**Unmaintained, please see [bitcoin-core](https://github.com/ruimarinho/bitcoin-core)**
|
|
||||||
|
|
||||||
The API is equivalent to the API document [here](https://en.bitcoin.it/wiki/Original_Bitcoin_client/API_Calls_list).
|
The API is equivalent to the API document [here](https://en.bitcoin.it/wiki/Original_Bitcoin_client/API_Calls_list).
|
||||||
The methods are exposed as lower camelcase methods on the `bitcoin.Client`
|
The methods are exposed as lower camelcase methods on the `bitcoin.Client`
|
||||||
object, or you may call the API directly using the `cmd` method.
|
object, or you may call the API directly using the `cmd` method.
|
||||||
|
|||||||
@ -11,7 +11,6 @@ module.exports = {
|
|||||||
encryptWallet: 'encryptwallet',
|
encryptWallet: 'encryptwallet',
|
||||||
estimateFee: 'estimatefee', // bitcoind v0.10.0x
|
estimateFee: 'estimatefee', // bitcoind v0.10.0x
|
||||||
estimatePriority: 'estimatepriority', // bitcoind v0.10.0+
|
estimatePriority: 'estimatepriority', // bitcoind v0.10.0+
|
||||||
generate: 'generate', // bitcoind v0.11.0+
|
|
||||||
getAccount: 'getaccount',
|
getAccount: 'getaccount',
|
||||||
getAccountAddress: 'getaccountaddress',
|
getAccountAddress: 'getaccountaddress',
|
||||||
getAddedNodeInfo: 'getaddednodeinfo', // bitcoind v0.8.0+
|
getAddedNodeInfo: 'getaddednodeinfo', // bitcoind v0.8.0+
|
||||||
@ -19,22 +18,17 @@ module.exports = {
|
|||||||
getBalance: 'getbalance',
|
getBalance: 'getbalance',
|
||||||
getBestBlockHash: 'getbestblockhash', // bitcoind v0.9.0+
|
getBestBlockHash: 'getbestblockhash', // bitcoind v0.9.0+
|
||||||
getBlock: 'getblock',
|
getBlock: 'getblock',
|
||||||
getBlockStats: 'getblockstats',
|
getBlockchainInfo : 'getblockchaininfo', // bitcoind v0.9.2+
|
||||||
getBlockFilter: 'getblockfilter',
|
|
||||||
getBlockchainInfo: 'getblockchaininfo', // bitcoind v0.9.2+
|
|
||||||
getBlockCount: 'getblockcount',
|
getBlockCount: 'getblockcount',
|
||||||
getBlockHash: 'getblockhash',
|
getBlockHash: 'getblockhash',
|
||||||
getBlockHeader: 'getblockheader',
|
|
||||||
getBlockTemplate: 'getblocktemplate', // bitcoind v0.7.0+
|
getBlockTemplate: 'getblocktemplate', // bitcoind v0.7.0+
|
||||||
getChainTips: 'getchaintips', // bitcoind v0.10.0+
|
getChainTips: 'getchaintips', // bitcoind v0.10.0+
|
||||||
getChainTxStats: 'getchaintxstats',
|
|
||||||
getConnectionCount: 'getconnectioncount',
|
getConnectionCount: 'getconnectioncount',
|
||||||
getDifficulty: 'getdifficulty',
|
getDifficulty: 'getdifficulty',
|
||||||
getGenerate: 'getgenerate',
|
getGenerate: 'getgenerate',
|
||||||
|
getHashesPerSecond: 'gethashespersec',
|
||||||
|
getHashesPerSec: 'gethashespersec',
|
||||||
getInfo: 'getinfo',
|
getInfo: 'getinfo',
|
||||||
getMempoolAncestors: 'getmempoolancestors',
|
|
||||||
getMempoolDescendants: 'getmempooldescendants',
|
|
||||||
getMempoolEntry: 'getmempoolentry',
|
|
||||||
getMempoolInfo: 'getmempoolinfo', // bitcoind v0.10+
|
getMempoolInfo: 'getmempoolinfo', // bitcoind v0.10+
|
||||||
getMiningInfo: 'getmininginfo',
|
getMiningInfo: 'getmininginfo',
|
||||||
getNetTotals: 'getnettotals',
|
getNetTotals: 'getnettotals',
|
||||||
@ -49,7 +43,6 @@ module.exports = {
|
|||||||
getReceivedByAddress: 'getreceivedbyaddress',
|
getReceivedByAddress: 'getreceivedbyaddress',
|
||||||
getTransaction: 'gettransaction',
|
getTransaction: 'gettransaction',
|
||||||
getTxOut: 'gettxout', // bitcoind v0.7.0+
|
getTxOut: 'gettxout', // bitcoind v0.7.0+
|
||||||
getTxOutProof: 'gettxoutproof', // bitcoind v0.11.0+
|
|
||||||
getTxOutSetInfo: 'gettxoutsetinfo', // bitcoind v0.7.0+
|
getTxOutSetInfo: 'gettxoutsetinfo', // bitcoind v0.7.0+
|
||||||
getUnconfirmedBalance: 'getunconfirmedbalance', // bitcoind v0.9.0+
|
getUnconfirmedBalance: 'getunconfirmedbalance', // bitcoind v0.9.0+
|
||||||
getWalletInfo: 'getwalletinfo', // bitcoind v0.9.2+
|
getWalletInfo: 'getwalletinfo', // bitcoind v0.9.2+
|
||||||
@ -85,8 +78,7 @@ module.exports = {
|
|||||||
validateAddress: 'validateaddress',
|
validateAddress: 'validateaddress',
|
||||||
verifyChain: 'verifychain', // bitcoind v0.9.0+
|
verifyChain: 'verifychain', // bitcoind v0.9.0+
|
||||||
verifyMessage: 'verifymessage',
|
verifyMessage: 'verifymessage',
|
||||||
verifyTxOutProof: 'verifytxoutproof', // bitcoind v0.11.0+
|
|
||||||
walletLock: 'walletlock',
|
walletLock: 'walletlock',
|
||||||
walletPassphrase: 'walletpassphrase',
|
walletPassphrase: 'walletpassphrase',
|
||||||
walletPassphraseChange: 'walletpassphrasechange'
|
walletPassphraseChange: 'walletpassphrasechange'
|
||||||
}
|
};
|
||||||
|
|||||||
76
lib/index.js
76
lib/index.js
@ -1,58 +1,62 @@
|
|||||||
var commands = require('./commands')
|
var commands = require('./commands'),
|
||||||
var rpc = require('./jsonrpc')
|
rpc = require('./jsonrpc');
|
||||||
|
|
||||||
// ===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Client
|
// Client
|
||||||
// ===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
function Client (opts) {
|
function Client(opts) {
|
||||||
this.rpc = new rpc.Client(opts)
|
this.rpc = new rpc.Client(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===----------------------------------------------------------------------===//
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
// cmd
|
// cmd
|
||||||
// ===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
Client.prototype.cmd = function () {
|
Client.prototype.cmd = function() {
|
||||||
var args = [].slice.call(arguments)
|
var args = [].slice.call(arguments);
|
||||||
var cmd = args.shift()
|
var cmd = args.shift();
|
||||||
|
|
||||||
callRpc(cmd, args, this.rpc)
|
callRpc(cmd, args, this.rpc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===----------------------------------------------------------------------===//
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
// callRpc
|
// callRpc
|
||||||
// ===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
function callRpc (cmd, args, rpc) {
|
function callRpc(cmd, args, rpc) {
|
||||||
var fn = args[args.length - 1]
|
var fn = args[args.length-1];
|
||||||
|
|
||||||
// If the last argument is a callback, pop it from the args list
|
// If the last argument is a callback, pop it from the args list
|
||||||
if (typeof fn === 'function') {
|
if (typeof fn === 'function') {
|
||||||
args.pop()
|
args.pop();
|
||||||
} else {
|
} else {
|
||||||
fn = function () {}
|
fn = function() {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return rpc.call(cmd, args, function () {
|
rpc.call(cmd, args, function(){
|
||||||
var args = [].slice.call(arguments)
|
var args = [].slice.call(arguments);
|
||||||
args.unshift(null)
|
args.unshift(null);
|
||||||
fn.apply(this, args)
|
fn.apply(this, args);
|
||||||
}, function (err) {
|
}, function(err){
|
||||||
fn(err)
|
fn(err);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Initialize wrappers
|
// Initialize wrappers
|
||||||
// ===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
(function () {
|
(function() {
|
||||||
|
|
||||||
for (var protoFn in commands) {
|
for (var protoFn in commands) {
|
||||||
(function (protoFn) {
|
(function(protoFn) {
|
||||||
Client.prototype[protoFn] = function () {
|
Client.prototype[protoFn] = function() {
|
||||||
var args = [].slice.call(arguments)
|
var args = [].slice.call(arguments);
|
||||||
return callRpc(commands[protoFn], args, this.rpc)
|
callRpc(commands[protoFn], args, this.rpc);
|
||||||
}
|
};
|
||||||
})(protoFn)
|
})(protoFn);
|
||||||
}
|
}
|
||||||
})()
|
|
||||||
|
})();
|
||||||
|
|
||||||
// Export!
|
// Export!
|
||||||
module.exports.Client = Client
|
module.exports.Client = Client;
|
||||||
|
|||||||
286
lib/jsonrpc.js
286
lib/jsonrpc.js
@ -1,155 +1,153 @@
|
|||||||
var http = require('http')
|
var Client = function(opts) {
|
||||||
var https = require('https')
|
this.opts = opts || {};
|
||||||
|
this.http = this.opts.ssl ? require('https') : require('http');
|
||||||
|
};
|
||||||
|
|
||||||
var Client = function (opts) {
|
Client.prototype.call = function(method, params, callback, errback, path) {
|
||||||
this.opts = opts || {}
|
var time = Date.now();
|
||||||
this.http = this.opts.ssl ? https : http
|
var requestJSON;
|
||||||
}
|
|
||||||
|
|
||||||
Client.prototype.call = function (method, params) {
|
if (Array.isArray(method)) {
|
||||||
return new Promise((resolve, reject) => {
|
// multiple rpc batch call
|
||||||
var time = Date.now()
|
requestJSON = [];
|
||||||
var requestJSON
|
method.forEach(function(batchCall, i) {
|
||||||
|
requestJSON.push({
|
||||||
|
id: time + '-' + i,
|
||||||
|
method: batchCall.method,
|
||||||
|
params: batchCall.params
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// single rpc call
|
||||||
|
requestJSON = {
|
||||||
|
id: time,
|
||||||
|
method: method,
|
||||||
|
params: params
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (Array.isArray(method)) {
|
// First we encode the request into JSON
|
||||||
// multiple rpc batch call
|
var requestJSON = JSON.stringify(requestJSON);
|
||||||
requestJSON = []
|
|
||||||
method.forEach(function (batchCall, i) {
|
|
||||||
requestJSON.push({
|
|
||||||
id: time + '-' + i,
|
|
||||||
method: batchCall.method,
|
|
||||||
params: batchCall.params
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// single rpc call
|
|
||||||
requestJSON = {
|
|
||||||
id: time,
|
|
||||||
method: method,
|
|
||||||
params: params
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// First we encode the request into JSON
|
// prepare request options
|
||||||
requestJSON = JSON.stringify(requestJSON)
|
var requestOptions = {
|
||||||
|
host: this.opts.host || 'localhost',
|
||||||
|
port: this.opts.port || 8332,
|
||||||
|
method: 'POST',
|
||||||
|
path: path || '/',
|
||||||
|
headers: {
|
||||||
|
'Host': this.opts.host || 'localhost',
|
||||||
|
'Content-Length': requestJSON.length
|
||||||
|
},
|
||||||
|
agent: false,
|
||||||
|
rejectUnauthorized: this.opts.ssl && this.opts.sslStrict !== false
|
||||||
|
};
|
||||||
|
|
||||||
// prepare request options
|
if (this.opts.ssl && this.opts.sslCa) {
|
||||||
var requestOptions = {
|
requestOptions.ca = this.opts.sslCa;
|
||||||
host: this.opts.host || 'localhost',
|
}
|
||||||
port: this.opts.port || 8332,
|
|
||||||
method: 'POST',
|
|
||||||
path: '/',
|
|
||||||
headers: {
|
|
||||||
'Host': this.opts.host || 'localhost',
|
|
||||||
'Content-Length': requestJSON.length
|
|
||||||
},
|
|
||||||
agent: false,
|
|
||||||
rejectUnauthorized: this.opts.ssl && this.opts.sslStrict !== false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.opts.ssl && this.opts.sslCa) {
|
// use HTTP auth if user and password set
|
||||||
requestOptions.ca = this.opts.sslCa
|
if (this.opts.user && this.opts.pass) {
|
||||||
}
|
requestOptions.auth = this.opts.user + ':' + this.opts.pass;
|
||||||
|
}
|
||||||
|
|
||||||
// use HTTP auth if user and password set
|
// Now we'll make a request to the server
|
||||||
if (this.opts.user && this.opts.pass) {
|
var cbCalled = false;
|
||||||
requestOptions.auth = this.opts.user + ':' + this.opts.pass
|
var request = this.http.request(requestOptions);
|
||||||
}
|
|
||||||
|
|
||||||
// Now we'll make a request to the server
|
// start request timeout timer
|
||||||
var cbCalled = false
|
var reqTimeout = setTimeout(function() {
|
||||||
var request = this.http.request(requestOptions)
|
if (cbCalled) return;
|
||||||
|
cbCalled = true;
|
||||||
|
request.abort();
|
||||||
|
var err = new Error('ETIMEDOUT');
|
||||||
|
err.code = 'ETIMEDOUT';
|
||||||
|
errback(err);
|
||||||
|
}, this.opts.timeout || 30000);
|
||||||
|
|
||||||
// start request timeout timer
|
// set additional timeout on socket in case of remote freeze after sending headers
|
||||||
var reqTimeout = setTimeout(function () {
|
request.setTimeout(this.opts.timeout || 30000, function() {
|
||||||
if (cbCalled) return
|
if (cbCalled) return;
|
||||||
cbCalled = true
|
cbCalled = true;
|
||||||
request.abort()
|
request.abort();
|
||||||
var err = new Error('ETIMEDOUT')
|
var err = new Error('ESOCKETTIMEDOUT')
|
||||||
err.code = 'ETIMEDOUT'
|
err.code = 'ESOCKETTIMEDOUT'
|
||||||
reject(err)
|
errback(err);
|
||||||
}, this.opts.timeout || 30000)
|
|
||||||
|
|
||||||
// set additional timeout on socket in case of remote freeze after sending headers
|
|
||||||
request.setTimeout(this.opts.timeout || 30000, function () {
|
|
||||||
if (cbCalled) return
|
|
||||||
cbCalled = true
|
|
||||||
request.abort()
|
|
||||||
var err = new Error('ESOCKETTIMEDOUT')
|
|
||||||
err.code = 'ESOCKETTIMEDOUT'
|
|
||||||
reject(err)
|
|
||||||
})
|
|
||||||
|
|
||||||
request.on('error', function (err) {
|
|
||||||
if (cbCalled) return
|
|
||||||
cbCalled = true
|
|
||||||
clearTimeout(reqTimeout)
|
|
||||||
reject(err)
|
|
||||||
})
|
|
||||||
|
|
||||||
request.on('response', function (response) {
|
|
||||||
clearTimeout(reqTimeout)
|
|
||||||
|
|
||||||
// We need to buffer the response chunks in a nonblocking way.
|
|
||||||
var buffer = ''
|
|
||||||
response.on('data', function (chunk) {
|
|
||||||
buffer = buffer + chunk
|
|
||||||
})
|
|
||||||
// When all the responses are finished, we decode the JSON and
|
|
||||||
// depending on whether it's got a result or an error, we call
|
|
||||||
// emitSuccess or emitError on the promise.
|
|
||||||
response.on('end', function () {
|
|
||||||
var err
|
|
||||||
|
|
||||||
if (cbCalled) return
|
|
||||||
cbCalled = true
|
|
||||||
|
|
||||||
try {
|
|
||||||
var decoded = JSON.parse(buffer)
|
|
||||||
} catch (e) {
|
|
||||||
if (response.statusCode !== 200) {
|
|
||||||
err = new Error('Invalid params, response status code: ' + response.statusCode)
|
|
||||||
err.code = -32602
|
|
||||||
reject(err)
|
|
||||||
} else {
|
|
||||||
err = new Error('Problem parsing JSON response from server')
|
|
||||||
err.code = -32603
|
|
||||||
reject(err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Array.isArray(decoded)) {
|
|
||||||
decoded = [decoded]
|
|
||||||
}
|
|
||||||
|
|
||||||
// iterate over each response, normally there will be just one
|
|
||||||
// unless a batch rpc call response is being processed
|
|
||||||
decoded.forEach(function (decodedResponse, i) {
|
|
||||||
if (decodedResponse.hasOwnProperty('error') && decodedResponse.error != null) {
|
|
||||||
if (reject) {
|
|
||||||
err = new Error(decodedResponse.error.message || '')
|
|
||||||
if (decodedResponse.error.code) {
|
|
||||||
err.code = decodedResponse.error.code
|
|
||||||
}
|
|
||||||
reject(err)
|
|
||||||
}
|
|
||||||
} else if (decodedResponse.hasOwnProperty('result')) {
|
|
||||||
resolve(decodedResponse.result, response.headers)
|
|
||||||
} else {
|
|
||||||
if (reject) {
|
|
||||||
err = new Error(decodedResponse.error.message || '')
|
|
||||||
if (decodedResponse.error.code) {
|
|
||||||
err.code = decodedResponse.error.code
|
|
||||||
}
|
|
||||||
reject(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
request.end(requestJSON);
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
module.exports.Client = Client
|
request.on('error', function(err) {
|
||||||
|
if (cbCalled) return;
|
||||||
|
cbCalled = true;
|
||||||
|
clearTimeout(reqTimeout);
|
||||||
|
errback(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
request.on('response', function(response) {
|
||||||
|
clearTimeout(reqTimeout);
|
||||||
|
|
||||||
|
// We need to buffer the response chunks in a nonblocking way.
|
||||||
|
var buffer = '';
|
||||||
|
response.on('data', function(chunk) {
|
||||||
|
buffer = buffer + chunk;
|
||||||
|
});
|
||||||
|
// When all the responses are finished, we decode the JSON and
|
||||||
|
// depending on whether it's got a result or an error, we call
|
||||||
|
// emitSuccess or emitError on the promise.
|
||||||
|
response.on('end', function() {
|
||||||
|
var err;
|
||||||
|
|
||||||
|
if (cbCalled) return;
|
||||||
|
cbCalled = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
var decoded = JSON.parse(buffer);
|
||||||
|
} catch (e) {
|
||||||
|
if (response.statusCode !== 200) {
|
||||||
|
err = new Error('Invalid params, response status code: ' + response.statusCode);
|
||||||
|
err.code = -32602;
|
||||||
|
errback(err);
|
||||||
|
} else {
|
||||||
|
err = new Error('Problem parsing JSON response from server');
|
||||||
|
err.code = -32603;
|
||||||
|
errback(err);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(decoded)) {
|
||||||
|
decoded = [decoded];
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate over each response, normally there will be just one
|
||||||
|
// unless a batch rpc call response is being processed
|
||||||
|
decoded.forEach(function(decodedResponse, i) {
|
||||||
|
if (decodedResponse.hasOwnProperty('error') && decodedResponse.error != null) {
|
||||||
|
if (errback) {
|
||||||
|
err = new Error(decodedResponse.error.message || '');
|
||||||
|
if (decodedResponse.error.code) {
|
||||||
|
err.code = decodedResponse.error.code;
|
||||||
|
}
|
||||||
|
errback(err);
|
||||||
|
}
|
||||||
|
} else if (decodedResponse.hasOwnProperty('result')) {
|
||||||
|
if (callback) {
|
||||||
|
callback(decodedResponse.result, response.headers);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (errback) {
|
||||||
|
err = new Error(decodedResponse.error.message || '');
|
||||||
|
if (decodedResponse.error.code) {
|
||||||
|
err.code = decodedResponse.error.code;
|
||||||
|
}
|
||||||
|
errback(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
request.end(requestJSON);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.Client = Client;
|
||||||
|
|||||||
22
package.json
22
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@mempool/bitcoin",
|
"name": "bitcoin",
|
||||||
"description": "Communicate with bitcoind via JSON-RPC",
|
"description": "Communicate with bitcoind via JSON-RPC",
|
||||||
"version": "3.0.3",
|
"version": "2.3.2",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"bitcoin",
|
"bitcoin",
|
||||||
@ -13,28 +13,18 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"clone": "^1.0.2",
|
"clone": "^0.1.18",
|
||||||
"mocha": "^2.3.3",
|
"mocha": "^2.1.0"
|
||||||
"standard": "^5.3.1"
|
|
||||||
},
|
},
|
||||||
"optionalDependencies": {},
|
"optionalDependencies": {},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git://github.com/mempool/node-bitcoin.git"
|
"url": "git://github.com/freewil/node-bitcoin.git"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.10.0"
|
"node": ">= 0.10.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"pretest": "standard --verbose",
|
|
||||||
"test": "make test"
|
"test": "make test"
|
||||||
},
|
}
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/mempool/node-bitcoin/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/mempool/node-bitcoin#readme",
|
|
||||||
"directories": {
|
|
||||||
"test": "test"
|
|
||||||
},
|
|
||||||
"license": "Unlicense"
|
|
||||||
}
|
}
|
||||||
|
|||||||
512
test/index.js
512
test/index.js
@ -1,292 +1,306 @@
|
|||||||
/* global describe, it */
|
var assert = require('assert'),
|
||||||
|
clone = require('clone'),
|
||||||
var assert = require('assert')
|
http = require('http'),
|
||||||
var clone = require('clone')
|
bitcoin = require('../'),
|
||||||
var http = require('http')
|
config = require('./config');
|
||||||
var bitcoin = require('../')
|
|
||||||
var config = require('./config')
|
|
||||||
|
|
||||||
var test = {
|
var test = {
|
||||||
account: 'test'
|
account: 'test'
|
||||||
}
|
};
|
||||||
|
|
||||||
var makeClient = function makeClient () {
|
var makeClient = function makeClient() {
|
||||||
return new bitcoin.Client(config)
|
return new bitcoin.Client(config);
|
||||||
}
|
};
|
||||||
|
|
||||||
var notEmpty = function notEmpty (data) {
|
var notEmpty = function notEmpty(data) {
|
||||||
if (data === 0) return
|
if (data === 0) return;
|
||||||
assert.ok(data)
|
assert.ok(data);
|
||||||
}
|
};
|
||||||
|
|
||||||
var makeServer = function (port) {
|
var makeServer = function(port) {
|
||||||
var server = http.createServer()
|
var server = http.createServer();
|
||||||
server.listen(port)
|
server.listen(port);
|
||||||
return server
|
return server;
|
||||||
}
|
};
|
||||||
|
|
||||||
describe('Client', function () {
|
describe('Client', function() {
|
||||||
describe('getAccountAddress()', function () {
|
|
||||||
it('should be able to get an account address', function (done) {
|
|
||||||
var client = makeClient()
|
|
||||||
client.getAccountAddress(test.account, function (err, address) {
|
|
||||||
assert.ifError(err)
|
|
||||||
assert.ok(address)
|
|
||||||
client.getAccount(address, function (err, account) {
|
|
||||||
assert.ifError(err)
|
|
||||||
assert.equal(account, test.account)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('listTransactions()', function () {
|
describe('getAccountAddress()', function() {
|
||||||
it('should be able to listTransactions with specific count', function (done) {
|
it('should be able to get an account address', function(done) {
|
||||||
var client = makeClient()
|
var client = makeClient();
|
||||||
client.listTransactions(test.account, 15, function (err, txs) {
|
client.getAccountAddress(test.account, function(err, address) {
|
||||||
assert.ifError(err)
|
assert.ifError(err);
|
||||||
assert.ok(txs)
|
assert.ok(address);
|
||||||
assert.ok(Array.isArray(txs))
|
client.getAccount(address, function(err, account) {
|
||||||
done()
|
assert.ifError(err);
|
||||||
})
|
assert.equal(account, test.account);
|
||||||
})
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should be able to listTransactions without specific count', function (done) {
|
describe('listTransactions()', function() {
|
||||||
var client = makeClient()
|
it('should be able to listTransactions with specific count', function(done) {
|
||||||
client.listTransactions(test.account, function (err, txs) {
|
var client = makeClient();
|
||||||
assert.ifError(err)
|
client.listTransactions(test.account, 15, function(err, txs) {
|
||||||
assert.ok(txs)
|
assert.ifError(err);
|
||||||
assert.ok(Array.isArray(txs))
|
assert.ok(txs);
|
||||||
done()
|
assert.ok(Array.isArray(txs));
|
||||||
})
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
describe('getNewAddress()', function () {
|
it('should be able to listTransactions without specific count', function(done) {
|
||||||
it('should be able to get new address', function (done) {
|
var client = makeClient();
|
||||||
var client = makeClient()
|
client.listTransactions(test.account, function(err, txs) {
|
||||||
client.getNewAddress(test.account, function (err, address) {
|
assert.ifError(err);
|
||||||
assert.ifError(err)
|
assert.ok(txs);
|
||||||
client.getAddressesByAccount(test.account, function (err, addresses) {
|
assert.ok(Array.isArray(txs));
|
||||||
assert.ifError(err)
|
done();
|
||||||
assert.ok(addresses && addresses.length > 0)
|
});
|
||||||
done()
|
});
|
||||||
})
|
});
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('getBalance()', function () {
|
describe('getNewAddress()', function() {
|
||||||
it('should return balance without any args', function (done) {
|
it('should be able to get new address', function(done) {
|
||||||
var client = makeClient()
|
var client = makeClient();
|
||||||
client.getBalance(function (err, balance) {
|
client.getNewAddress(test.account, function(err, address) {
|
||||||
assert.ifError(err)
|
assert.ifError(err);
|
||||||
assert.ok(typeof balance === 'number')
|
client.getAddressesByAccount(test.account, function(err, addresses) {
|
||||||
done()
|
assert.ifError(err);
|
||||||
})
|
assert.ok(addresses && addresses.length > 0);
|
||||||
})
|
done();
|
||||||
})
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('getDifficulty()', function () {
|
describe('getBalance()', function() {
|
||||||
it('should get difficulty', function (done) {
|
it('should return balance without any args', function(done) {
|
||||||
var client = makeClient()
|
var client = makeClient();
|
||||||
client.getDifficulty(function (err, difficulty) {
|
client.getBalance(function(err, balance) {
|
||||||
assert.ifError(err)
|
assert.ifError(err);
|
||||||
assert.ok(typeof difficulty === 'number')
|
assert.ok(typeof balance === 'number');
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
describe('getInfo()', function () {
|
describe('getDifficulty()', function() {
|
||||||
it('should get info', function (done) {
|
it('should get difficulty', function(done) {
|
||||||
var client = makeClient()
|
var client = makeClient();
|
||||||
client.getInfo(function (err, info, headers) {
|
client.getDifficulty(function(err, difficulty) {
|
||||||
assert.ifError(err)
|
assert.ifError(err);
|
||||||
notEmpty(info)
|
assert.ok(typeof difficulty === 'number');
|
||||||
assert.ok(info.errors === '')
|
done();
|
||||||
done()
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
|
||||||
|
|
||||||
describe('help()', function () {
|
describe('getInfo()', function() {
|
||||||
it('should return help', function (done) {
|
it('should get info', function(done) {
|
||||||
var client = makeClient()
|
var client = makeClient();
|
||||||
client.help(function (err, help) {
|
client.getInfo(function(err, info, headers) {
|
||||||
assert.ifError(err)
|
assert.ifError(err);
|
||||||
notEmpty(help)
|
notEmpty(info);
|
||||||
done()
|
assert.ok(info.errors === '');
|
||||||
})
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('bitcoin related error should be an Error object', function (done) {
|
describe('getHashesPerSec()', function() {
|
||||||
var client = makeClient()
|
it('should get hashes per second', function(done) {
|
||||||
client.cmd('nomethod', function (err, expectedValue) {
|
var client = makeClient();
|
||||||
assert.ok(err instanceof Error)
|
client.getHashesPerSec(function(err, data) {
|
||||||
assert.equal(err.message, 'Method not found')
|
assert.ifError(err);
|
||||||
assert.equal(err.code, -32601)
|
notEmpty(data);
|
||||||
assert.equal(expectedValue, undefined)
|
assert.ok(typeof data === 'number');
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('running batch of rpc calls', function (done) {
|
describe('help()', function() {
|
||||||
this.timeout(5000)
|
it('should return help', function(done) {
|
||||||
var batch = []
|
var client = makeClient();
|
||||||
|
client.help(function(err, help) {
|
||||||
|
assert.ifError(err);
|
||||||
|
notEmpty(help);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('bitcoin related error should be an Error object', function(done) {
|
||||||
|
var client = makeClient();
|
||||||
|
client.cmd('nomethod', function(err, expectedValue) {
|
||||||
|
assert.ok(err instanceof Error);
|
||||||
|
assert.equal(err.message, 'Method not found');
|
||||||
|
assert.equal(err.code, -32601);
|
||||||
|
assert.equal(expectedValue, undefined);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('running batch of rpc calls', function(done) {
|
||||||
|
this.timeout(5000);
|
||||||
|
var batch = [];
|
||||||
for (var i = 0; i < 10; ++i) {
|
for (var i = 0; i < 10; ++i) {
|
||||||
batch.push({
|
batch.push({
|
||||||
method: 'getnewaddress',
|
method: 'getnewaddress',
|
||||||
params: [test.account]
|
params: [test.account]
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
var client = makeClient()
|
var client = makeClient();
|
||||||
var batchCallbackCount = 0
|
var batchCallbackCount = 0;
|
||||||
client.cmd(batch, function (err, address) {
|
client.cmd(batch, function(err, address) {
|
||||||
assert.ifError(err)
|
assert.ifError(err);
|
||||||
assert.ok(++batchCallbackCount <= 10)
|
assert.ok(++batchCallbackCount <= 10);
|
||||||
assert.ok(address)
|
assert.ok(address);
|
||||||
if (batchCallbackCount === 10) done()
|
if (batchCallbackCount === 10) done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
describe('invalid credentials', function () {
|
describe('invalid credentials', function() {
|
||||||
var badCredentials = clone(config)
|
var badCredentials = clone(config);
|
||||||
badCredentials.user = 'baduser'
|
badCredentials.user = 'baduser';
|
||||||
badCredentials.pass = 'badpwd'
|
badCredentials.pass = 'badpwd';
|
||||||
var client = new bitcoin.Client(badCredentials)
|
var client = new bitcoin.Client(badCredentials);
|
||||||
|
|
||||||
it('should still return client object', function (done) {
|
it('should still return client object', function(done) {
|
||||||
assert.ok(client instanceof bitcoin.Client)
|
assert.ok(client instanceof bitcoin.Client);
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should return status 401 with html', function (done) {
|
it('should return status 401 with html', function(done) {
|
||||||
client.getDifficulty(function (err, difficulty) {
|
client.getDifficulty(function(err, difficulty) {
|
||||||
assert.ok(err instanceof Error)
|
assert.ok(err instanceof Error);
|
||||||
assert.equal(err.message, 'Invalid params, response status code: 401')
|
assert.equal(err.message, 'Invalid params, response status code: 401');
|
||||||
assert.equal(err.code, -32602)
|
assert.equal(err.code, -32602);
|
||||||
assert.equal(difficulty, undefined)
|
assert.equal(difficulty, undefined);
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
describe('creating client on non-listening port', function () {
|
describe('creating client on non-listening port', function() {
|
||||||
var badPort = clone(config)
|
var badPort = clone(config);
|
||||||
badPort.port = 9897
|
badPort.port = 9897;
|
||||||
badPort.user = 'baduser'
|
badPort.user = 'baduser';
|
||||||
badPort.pass = 'badpwd'
|
badPort.pass = 'badpwd';
|
||||||
var client = new bitcoin.Client(badPort)
|
var client = new bitcoin.Client(badPort);
|
||||||
|
|
||||||
it('will return client object', function (done) {
|
it('will return client object', function(done) {
|
||||||
assert.ok(client instanceof bitcoin.Client)
|
assert.ok(client instanceof bitcoin.Client);
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should not call callback more than once', function (done) {
|
it('should not call callback more than once', function(done) {
|
||||||
client.listSinceBlock(function (err, result) {
|
client.listSinceBlock(function(err, result) {
|
||||||
assert.ok(err instanceof Error)
|
assert.ok(err instanceof Error);
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
describe('request timeouts', function () {
|
describe('request timeouts', function() {
|
||||||
it('should occur by default after 30000ms', function (done) {
|
it('should occur by default after 30000ms', function(done) {
|
||||||
this.timeout(31000)
|
this.timeout(31000);
|
||||||
var server = makeServer(19998)
|
var server = makeServer(19998);
|
||||||
var request // eslint-disable-line no-unused-vars
|
var request;
|
||||||
var response
|
var response;
|
||||||
server.on('request', function (req, res) {
|
server.on('request', function(req, res) {
|
||||||
request = req
|
request = req;
|
||||||
response = res
|
response = res;
|
||||||
})
|
});
|
||||||
var client = new bitcoin.Client({
|
var client = new bitcoin.Client({
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
port: 19998,
|
port: 19998,
|
||||||
user: 'admin1',
|
user: 'admin1',
|
||||||
pass: '123'
|
pass: '123'
|
||||||
})
|
});
|
||||||
var start = Date.now()
|
var start = Date.now();
|
||||||
client.getInfo(function (err, info) {
|
client.getInfo(function(err, info) {
|
||||||
var delta = Date.now() - start
|
var delta = Date.now() - start;
|
||||||
assert.ok(err instanceof Error)
|
assert.ok(err instanceof Error);
|
||||||
assert.ok(err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT')
|
assert.ok(err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT');
|
||||||
assert.ok(delta >= 30000, 'delta should be >= 30000: ' + delta)
|
assert.ok(delta >= 30000, 'delta should be >= 30000: ' + delta);
|
||||||
response.end()
|
response.end();
|
||||||
server.close()
|
server.close();
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should be customizable', function (done) {
|
it('should be customizable', function(done) {
|
||||||
this.timeout(4500)
|
this.timeout(4500);
|
||||||
var server = makeServer(19999)
|
var server = makeServer(19999);
|
||||||
var request // eslint-disable-line no-unused-vars
|
var request;
|
||||||
var response
|
var response;
|
||||||
server.on('request', function (req, res) {
|
server.on('request', function(req, res) {
|
||||||
request = req
|
request = req;
|
||||||
response = res
|
response = res;
|
||||||
})
|
});
|
||||||
var client = new bitcoin.Client({
|
var client = new bitcoin.Client({
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
port: 19999,
|
port: 19999,
|
||||||
user: 'admin1',
|
user: 'admin1',
|
||||||
pass: '123',
|
pass: '123',
|
||||||
timeout: 2500
|
timeout: 2500
|
||||||
})
|
});
|
||||||
var start = Date.now()
|
var start = Date.now();
|
||||||
client.getInfo(function (err, info) {
|
client.getInfo(function(err, info) {
|
||||||
var delta = Date.now() - start
|
var delta = Date.now() - start;
|
||||||
assert.ok(err instanceof Error)
|
assert.ok(err instanceof Error);
|
||||||
assert.ok(err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT')
|
assert.ok(err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT');
|
||||||
assert.ok(delta >= 2500, 'delta should be >= 2500:' + delta)
|
assert.ok(delta >= 2500, 'delta should be >= 2500:' + delta);
|
||||||
response.end()
|
response.end();
|
||||||
server.close()
|
server.close();
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
|
||||||
|
|
||||||
describe('response headers', function () {
|
});
|
||||||
var assertResHeaders = function (resHeaders) {
|
|
||||||
assert.ok(resHeaders)
|
|
||||||
assert.ok(resHeaders.server)
|
|
||||||
assert.ok(/bitcoin/.test(resHeaders.server))
|
|
||||||
}
|
|
||||||
it('should be returned for no parameter calls', function (done) {
|
|
||||||
var client = makeClient()
|
|
||||||
client.getInfo(function (err, info, resHeaders) {
|
|
||||||
assert.ifError(err)
|
|
||||||
notEmpty(info)
|
|
||||||
assert.ok(info.errors === '')
|
|
||||||
assertResHeaders(resHeaders)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should be returned for 1-parameter call', function (done) {
|
describe('response headers', function() {
|
||||||
var client = makeClient()
|
var assertResHeaders = function(resHeaders) {
|
||||||
client.getNewAddress(test.account, function (err, address, resHeaders) {
|
assert.ok(resHeaders);
|
||||||
assert.ifError(err)
|
assert.ok(resHeaders.server);
|
||||||
assert.ok(address)
|
assert.ok(/bitcoin/.test(resHeaders.server));
|
||||||
assertResHeaders(resHeaders)
|
};
|
||||||
done()
|
it('should be returned for no parameter calls', function(done) {
|
||||||
})
|
var client = makeClient();
|
||||||
|
client.getInfo(function(err, info, resHeaders) {
|
||||||
|
assert.ifError(err);
|
||||||
|
notEmpty(info);
|
||||||
|
assert.ok(info.errors === '');
|
||||||
|
assertResHeaders(resHeaders);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should be returned for 2-parameter call', function (done) {
|
it('should be returned for 1-parameter call', function(done) {
|
||||||
var client = makeClient()
|
var client = makeClient();
|
||||||
client.listTransactions(test.account, 15, function (err, txs, resHeaders) {
|
client.getNewAddress(test.account, function(err, address, resHeaders) {
|
||||||
assert.ifError(err)
|
assert.ifError(err);
|
||||||
assert.ok(txs)
|
assert.ok(address);
|
||||||
assert.ok(Array.isArray(txs))
|
assertResHeaders(resHeaders);
|
||||||
assertResHeaders(resHeaders)
|
done();
|
||||||
done()
|
});
|
||||||
})
|
|
||||||
})
|
it('should be returned for 2-parameter call', function(done) {
|
||||||
})
|
var client = makeClient();
|
||||||
})
|
client.listTransactions(test.account, 15, function(err, txs, resHeaders) {
|
||||||
})
|
assert.ifError(err);
|
||||||
|
assert.ok(txs);
|
||||||
|
assert.ok(Array.isArray(txs));
|
||||||
|
assertResHeaders(resHeaders);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|||||||
@ -1,75 +1,76 @@
|
|||||||
/* global describe, it */
|
var assert = require('assert'),
|
||||||
|
bitcoin = require('../'),
|
||||||
|
config = require('./config'),
|
||||||
|
commands = require('../lib/commands');
|
||||||
|
|
||||||
var assert = require('assert')
|
|
||||||
var bitcoin = require('../')
|
|
||||||
var config = require('./config')
|
|
||||||
var commands = require('../lib/commands')
|
|
||||||
|
|
||||||
var getHelpCommands = function (client, cb) {
|
var getHelpCommands = function(client, cb) {
|
||||||
var commandRegex = /^([a-z]+)/
|
var commandRegex = /^([a-z]+)/;
|
||||||
client.cmd('help', function (err, commandList) {
|
client.cmd('help', function(err, commandList) {
|
||||||
if (err) return cb(err)
|
if (err) return cb(err);
|
||||||
|
|
||||||
var helpCommands = []
|
var helpCommands = [];
|
||||||
|
|
||||||
// split up the command list by newlines
|
// split up the command list by newlines
|
||||||
var commandListLines = commandList.split('\n')
|
var commandListLines = commandList.split('\n');
|
||||||
var result
|
var result;
|
||||||
for (var i in commandListLines) {
|
for (var i in commandListLines) {
|
||||||
result = commandRegex.exec(commandListLines[i])
|
result = commandRegex.exec(commandListLines[i]);
|
||||||
if (!result) continue
|
if (!result) continue;
|
||||||
helpCommands.push(result[1])
|
helpCommands.push(result[1]);
|
||||||
}
|
}
|
||||||
cb(null, helpCommands)
|
cb(null, helpCommands);
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
describe('Client Commands', function () {
|
describe('Client Commands', function() {
|
||||||
it('should have all the commands listed by `help`', function (done) {
|
|
||||||
var client = new bitcoin.Client(config)
|
it('should have all the commands listed by `help`', function(done) {
|
||||||
getHelpCommands(client, function (err, helpCommands) {
|
var client = new bitcoin.Client(config);
|
||||||
assert.ifError(err)
|
getHelpCommands(client, function(err, helpCommands) {
|
||||||
|
assert.ifError(err);
|
||||||
|
|
||||||
for (var i in helpCommands) {
|
for (var i in helpCommands) {
|
||||||
var found = false
|
var found = false;
|
||||||
for (var j in commands) {
|
for (var j in commands) {
|
||||||
if (commands[j] === helpCommands[i]) {
|
if (commands[j] === helpCommands[i]) {
|
||||||
found = true
|
found = true;
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert.ok(found, 'missing command found in `help`: ' + helpCommands[i])
|
assert.ok(found, 'missing command found in `help`: ' + helpCommands[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should not have any commands not listed by `help`', function (done) {
|
it('should not have any commands not listed by `help`', function(done) {
|
||||||
var client = new bitcoin.Client(config)
|
var client = new bitcoin.Client(config);
|
||||||
getHelpCommands(client, function (err, helpCommands) {
|
getHelpCommands(client, function(err, helpCommands) {
|
||||||
assert.ifError(err)
|
assert.ifError(err);
|
||||||
|
|
||||||
for (var i in commands) {
|
for (var i in commands) {
|
||||||
var found = false
|
var found = false;
|
||||||
for (var j in helpCommands) {
|
for (var j in helpCommands) {
|
||||||
if (commands[i] === helpCommands[j]) {
|
if (commands[i] === helpCommands[j]) {
|
||||||
found = true
|
found = true;
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore commands not found in help because they are hidden
|
// ignore commands not found in help because they are hidden
|
||||||
// if the wallet isn't encrypted
|
// if the wallet isn't encrypted
|
||||||
var ignore = ['walletlock', 'walletpassphrase', 'walletpassphrasechange']
|
var ignore = ['walletlock', 'walletpassphrase', 'walletpassphrasechange'];
|
||||||
if (~ignore.indexOf(commands[i])) {
|
if (~ignore.indexOf(commands[i])) {
|
||||||
assert.ok(!found, 'command found in `help`: ' + commands[i])
|
assert.ok(!found, 'command found in `help`: ' + commands[i]);
|
||||||
} else {
|
} else {
|
||||||
assert.ok(found, 'command not found in `help`: ' + commands[i])
|
assert.ok(found, 'command not found in `help`: ' + commands[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
|
||||||
|
});
|
||||||
|
|||||||
103
test/ssl.js
103
test/ssl.js
@ -1,63 +1,62 @@
|
|||||||
/* global describe, it */
|
var assert = require('assert'),
|
||||||
|
fs = require('fs'),
|
||||||
|
clone = require('clone'),
|
||||||
|
bitcoin = require('../'),
|
||||||
|
config = require('./config');
|
||||||
|
|
||||||
var assert = require('assert')
|
var getInfo = function(opts, cb) {
|
||||||
var fs = require('fs')
|
var client = new bitcoin.Client(opts);
|
||||||
var clone = require('clone')
|
client.getInfo(cb);
|
||||||
var bitcoin = require('../')
|
};
|
||||||
var config = require('./config')
|
|
||||||
|
|
||||||
var getInfo = function (opts, cb) {
|
describe('Client SSL', function() {
|
||||||
var client = new bitcoin.Client(opts)
|
it('use sslStrict by default', function(done) {
|
||||||
client.getInfo(cb)
|
var opts = clone(config);
|
||||||
}
|
opts.ssl = true;
|
||||||
|
getInfo(opts, function(err, info) {
|
||||||
describe('Client SSL', function () {
|
assert.ok(err instanceof Error);
|
||||||
it('use sslStrict by default', function (done) {
|
|
||||||
var opts = clone(config)
|
|
||||||
opts.ssl = true
|
|
||||||
getInfo(opts, function (err, info) {
|
|
||||||
assert.ok(err instanceof Error)
|
|
||||||
// node v0.11 adds `code` param to this error
|
// node v0.11 adds `code` param to this error
|
||||||
// and uses a user-friendly `message`
|
// and uses a user-friendly `message`
|
||||||
// continue using err.message for v0.8 and v0.10
|
// continue using err.message for v0.8 and v0.10
|
||||||
assert.equal(err.code || err.message, 'DEPTH_ZERO_SELF_SIGNED_CERT')
|
assert.equal(err.code || err.message, 'DEPTH_ZERO_SELF_SIGNED_CERT');
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('strictSSL should fail with self-signed certificate', function (done) {
|
it('strictSSL should fail with self-signed certificate', function(done) {
|
||||||
var opts = clone(config)
|
var opts = clone(config);
|
||||||
opts.ssl = true
|
opts.ssl = true;
|
||||||
opts.sslStrict = true
|
opts.sslStrict = true;
|
||||||
getInfo(opts, function (err, info) {
|
getInfo(opts, function(err, info) {
|
||||||
assert.ok(err instanceof Error)
|
assert.ok(err instanceof Error);
|
||||||
// node v0.11 adds `code` param to this error
|
// node v0.11 adds `code` param to this error
|
||||||
// and uses a user-friendly `message`
|
// and uses a user-friendly `message`
|
||||||
// continue using err.message for v0.8 and v0.10
|
// continue using err.message for v0.8 and v0.10
|
||||||
assert.equal(err.code || err.message, 'DEPTH_ZERO_SELF_SIGNED_CERT')
|
assert.equal(err.code || err.message, 'DEPTH_ZERO_SELF_SIGNED_CERT');
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('self-signed certificate with sslStrict false', function (done) {
|
it('self-signed certificate with sslStrict false', function(done) {
|
||||||
var opts = clone(config)
|
var opts = clone(config);
|
||||||
opts.ssl = true
|
opts.ssl = true;
|
||||||
opts.sslStrict = false
|
opts.sslStrict = false;
|
||||||
getInfo(opts, function (err, info) {
|
getInfo(opts, function(err, info) {
|
||||||
assert.ifError(err)
|
assert.ifError(err);
|
||||||
assert.ok(info)
|
assert.ok(info);
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('self-signed certificate with sslStrict and CA specified', function (done) {
|
it('self-signed certificate with sslStrict and CA specified', function(done) {
|
||||||
var opts = clone(config)
|
var opts = clone(config);
|
||||||
opts.ssl = true
|
opts.ssl = true;
|
||||||
opts.sslCa = fs.readFileSync(__dirname + '/testnet-box/1/regtest/server.cert')
|
opts.sslCa = fs.readFileSync(__dirname + '/testnet-box/1/regtest/server.cert');
|
||||||
getInfo(opts, function (err, info) {
|
getInfo(opts, function(err, info) {
|
||||||
assert.ifError(err)
|
assert.ifError(err);
|
||||||
assert.ok(info)
|
assert.ok(info);
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
|
||||||
|
});
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
Subproject commit 24f5214acfddfec498cca21dd96dac480e9b9013
|
Subproject commit 54e884df1f49959b21cf4e2014424a172722ed5c
|
||||||
Loading…
Reference in New Issue
Block a user