Compare commits

..

No commits in common. "master" and "v2.3.0" have entirely different histories.

14 changed files with 585 additions and 671 deletions

View File

@ -3,4 +3,3 @@ test/
.project
.gitmodules
.travis.yml
Dockerfile

View File

@ -1,18 +1,12 @@
# need sudo for docker
sudo: required
language: node_js
# skip install step (npm install)
# See http://docs.travis-ci.com/user/customizing-the-build/#Skipping-the-Installation-Step
install: true
node_js:
- "0.10"
services:
- docker
before_install:
- 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
- docker build -t node-bitcoin .
script:
- docker run node-bitcoin

View File

@ -1,30 +1,5 @@
# 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)
* fix bug in test suite that was supposed to detect missing commands
* add missing commands
* `prioritiseTransaction`
* `importWallet`
## v2.3.1 (2015/06/24)
* add missing `getMempoolInfo` for bitcoind v0.10
## v2.3.0 (2015/02/04)
* drop node v0.8.x support
* update testnet-box

View File

@ -1,21 +0,0 @@
# Dockerfile for running node-bitcoin tests
FROM freewil/bitcoin-testnet-box
MAINTAINER Sean Lavine <lavis88@gmail.com>
# install node.js
USER root
RUN apt-get install --yes curl
RUN curl --silent --location https://deb.nodesource.com/setup_0.12 | bash -
RUN apt-get install --yes nodejs
# set permissions for tester user on project
ADD . /home/tester/node-bitcoin
RUN chown --recursive tester:tester /home/tester/node-bitcoin
# install module dependencies
USER tester
WORKDIR /home/tester/node-bitcoin
RUN npm install
# run test suite
CMD ["npm", "test"]

24
LICENSE
View File

@ -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/>

View File

@ -1,25 +1,7 @@
# 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 [![Build Status](https://travis-ci.org/freewil/node-bitcoin.svg?branch=master)](https://travis-ci.org/freewil/node-bitcoin)
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 methods are exposed as lower camelcase methods on the `bitcoin.Client`
object, or you may call the API directly using the `cmd` method.

View File

@ -11,7 +11,6 @@ module.exports = {
encryptWallet: 'encryptwallet',
estimateFee: 'estimatefee', // bitcoind v0.10.0x
estimatePriority: 'estimatepriority', // bitcoind v0.10.0+
generate: 'generate', // bitcoind v0.11.0+
getAccount: 'getaccount',
getAccountAddress: 'getaccountaddress',
getAddedNodeInfo: 'getaddednodeinfo', // bitcoind v0.8.0+
@ -19,23 +18,17 @@ module.exports = {
getBalance: 'getbalance',
getBestBlockHash: 'getbestblockhash', // bitcoind v0.9.0+
getBlock: 'getblock',
getBlockStats: 'getblockstats',
getBlockFilter: 'getblockfilter',
getBlockchainInfo: 'getblockchaininfo', // bitcoind v0.9.2+
getBlockchainInfo : 'getblockchaininfo', // bitcoind v0.9.2+
getBlockCount: 'getblockcount',
getBlockHash: 'getblockhash',
getBlockHeader: 'getblockheader',
getBlockTemplate: 'getblocktemplate', // bitcoind v0.7.0+
getChainTips: 'getchaintips', // bitcoind v0.10.0+
getChainTxStats: 'getchaintxstats',
getConnectionCount: 'getconnectioncount',
getDifficulty: 'getdifficulty',
getGenerate: 'getgenerate',
getHashesPerSecond: 'gethashespersec',
getHashesPerSec: 'gethashespersec',
getInfo: 'getinfo',
getMempoolAncestors: 'getmempoolancestors',
getMempoolDescendants: 'getmempooldescendants',
getMempoolEntry: 'getmempoolentry',
getMempoolInfo: 'getmempoolinfo', // bitcoind v0.10+
getMiningInfo: 'getmininginfo',
getNetTotals: 'getnettotals',
getNetworkInfo: 'getnetworkinfo', // bitcoind v0.9.2+
@ -49,14 +42,13 @@ module.exports = {
getReceivedByAddress: 'getreceivedbyaddress',
getTransaction: 'gettransaction',
getTxOut: 'gettxout', // bitcoind v0.7.0+
getTxOutProof: 'gettxoutproof', // bitcoind v0.11.0+
getTxOutSetInfo: 'gettxoutsetinfo', // bitcoind v0.7.0+
getUnconfirmedBalance: 'getunconfirmedbalance', // bitcoind v0.9.0+
getWalletInfo: 'getwalletinfo', // bitcoind v0.9.2+
getWork: 'getwork',
help: 'help',
importAddress: 'importaddress', // bitcoind v0.10.0+
importPrivKey: 'importprivkey',
importWallet: 'importwallet', // bitcoind v0.9.0+
keypoolRefill: 'keypoolrefill',
keyPoolRefill: 'keypoolrefill',
listAccounts: 'listaccounts',
@ -70,7 +62,6 @@ module.exports = {
lockUnspent: 'lockunspent', // bitcoind v0.8.0+
move: 'move',
ping: 'ping', // bitcoind v0.9.0+
prioritiseTransaction: 'prioritisetransaction', // bitcoind v0.10.0+
sendFrom: 'sendfrom',
sendMany: 'sendmany',
sendRawTransaction: 'sendrawtransaction', // bitcoind v0.7.0+
@ -85,8 +76,7 @@ module.exports = {
validateAddress: 'validateaddress',
verifyChain: 'verifychain', // bitcoind v0.9.0+
verifyMessage: 'verifymessage',
verifyTxOutProof: 'verifytxoutproof', // bitcoind v0.11.0+
walletLock: 'walletlock',
walletPassphrase: 'walletpassphrase',
walletPassphraseChange: 'walletpassphrasechange'
}
};

View File

@ -1,58 +1,62 @@
var commands = require('./commands')
var rpc = require('./jsonrpc')
var commands = require('./commands'),
rpc = require('./jsonrpc');
// ===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Client
// ===----------------------------------------------------------------------===//
function Client (opts) {
this.rpc = new rpc.Client(opts)
//===----------------------------------------------------------------------===//
function Client(opts) {
this.rpc = new rpc.Client(opts);
}
// ===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// cmd
// ===----------------------------------------------------------------------===//
Client.prototype.cmd = function () {
var args = [].slice.call(arguments)
var cmd = args.shift()
//===----------------------------------------------------------------------===//
Client.prototype.cmd = function() {
var args = [].slice.call(arguments);
var cmd = args.shift();
callRpc(cmd, args, this.rpc)
callRpc(cmd, args, this.rpc);
}
// ===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// callRpc
// ===----------------------------------------------------------------------===//
function callRpc (cmd, args, rpc) {
var fn = args[args.length - 1]
//===----------------------------------------------------------------------===//
function callRpc(cmd, args, rpc) {
var fn = args[args.length-1];
// If the last argument is a callback, pop it from the args list
if (typeof fn === 'function') {
args.pop()
args.pop();
} else {
fn = function () {}
fn = function() {};
}
return rpc.call(cmd, args, function () {
var args = [].slice.call(arguments)
args.unshift(null)
fn.apply(this, args)
}, function (err) {
fn(err)
})
rpc.call(cmd, args, function(){
var args = [].slice.call(arguments);
args.unshift(null);
fn.apply(this, args);
}, function(err){
fn(err);
});
}
// ===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Initialize wrappers
// ===----------------------------------------------------------------------===//
(function () {
//===----------------------------------------------------------------------===//
(function() {
for (var protoFn in commands) {
(function (protoFn) {
Client.prototype[protoFn] = function () {
var args = [].slice.call(arguments)
return callRpc(commands[protoFn], args, this.rpc)
}
})(protoFn)
(function(protoFn) {
Client.prototype[protoFn] = function() {
var args = [].slice.call(arguments);
callRpc(commands[protoFn], args, this.rpc);
};
})(protoFn);
}
})()
})();
// Export!
module.exports.Client = Client
module.exports.Client = Client;

View File

@ -1,155 +1,153 @@
var http = require('http')
var https = require('https')
var Client = function(opts) {
this.opts = opts || {};
this.http = this.opts.ssl ? require('https') : require('http');
};
var Client = function (opts) {
this.opts = opts || {}
this.http = this.opts.ssl ? https : http
}
Client.prototype.call = function(method, params, callback, errback, path) {
var time = Date.now();
var requestJSON;
Client.prototype.call = function (method, params) {
return new Promise((resolve, reject) => {
var time = Date.now()
var requestJSON
if (Array.isArray(method)) {
// multiple rpc batch call
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)) {
// multiple rpc batch call
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
var requestJSON = JSON.stringify(requestJSON);
// First we encode the request into JSON
requestJSON = JSON.stringify(requestJSON)
// prepare request options
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
var requestOptions = {
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) {
requestOptions.ca = this.opts.sslCa;
}
if (this.opts.ssl && this.opts.sslCa) {
requestOptions.ca = this.opts.sslCa
}
// use HTTP auth if user and password set
if (this.opts.user && this.opts.pass) {
requestOptions.auth = this.opts.user + ':' + this.opts.pass;
}
// use HTTP auth if user and password set
if (this.opts.user && this.opts.pass) {
requestOptions.auth = this.opts.user + ':' + this.opts.pass
}
// Now we'll make a request to the server
var cbCalled = false;
var request = this.http.request(requestOptions);
// Now we'll make a request to the server
var cbCalled = false
var request = this.http.request(requestOptions)
// start request timeout timer
var reqTimeout = setTimeout(function() {
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
var reqTimeout = setTimeout(function () {
if (cbCalled) return
cbCalled = true
request.abort()
var err = new Error('ETIMEDOUT')
err.code = 'ETIMEDOUT'
reject(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);
// 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'
errback(err);
});
}
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;

View File

@ -1,7 +1,7 @@
{
"name": "@mempool/bitcoin",
"name": "bitcoin",
"description": "Communicate with bitcoind via JSON-RPC",
"version": "3.0.3",
"version": "2.3.0",
"main": "lib/index.js",
"keywords": [
"bitcoin",
@ -13,28 +13,18 @@
],
"dependencies": {},
"devDependencies": {
"clone": "^1.0.2",
"mocha": "^2.3.3",
"standard": "^5.3.1"
"clone": "^0.1.18",
"mocha": "^2.1.0"
},
"optionalDependencies": {},
"repository": {
"type": "git",
"url": "git://github.com/mempool/node-bitcoin.git"
"url": "git://github.com/freewil/node-bitcoin.git"
},
"engines": {
"node": ">= 0.10.0"
},
"scripts": {
"pretest": "standard --verbose",
"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"
}
}

View File

@ -1,292 +1,317 @@
/* global describe, it */
var assert = require('assert')
var clone = require('clone')
var http = require('http')
var bitcoin = require('../')
var config = require('./config')
var assert = require('assert'),
clone = require('clone'),
http = require('http'),
bitcoin = require('../'),
config = require('./config');
var test = {
account: 'test'
}
};
var makeClient = function makeClient () {
return new bitcoin.Client(config)
}
var makeClient = function makeClient() {
return new bitcoin.Client(config);
};
var notEmpty = function notEmpty (data) {
if (data === 0) return
assert.ok(data)
}
var notEmpty = function notEmpty(data) {
if (data === 0) return;
assert.ok(data);
};
var makeServer = function (port) {
var server = http.createServer()
server.listen(port)
return server
}
var makeServer = function(port) {
var server = http.createServer();
server.listen(port);
return server;
};
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('Client', function() {
describe('listTransactions()', function () {
it('should be able to listTransactions with specific count', function (done) {
var client = makeClient()
client.listTransactions(test.account, 15, function (err, txs) {
assert.ifError(err)
assert.ok(txs)
assert.ok(Array.isArray(txs))
done()
})
})
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();
});
});
});
});
it('should be able to listTransactions without specific count', function (done) {
var client = makeClient()
client.listTransactions(test.account, function (err, txs) {
assert.ifError(err)
assert.ok(txs)
assert.ok(Array.isArray(txs))
done()
})
})
})
describe('listTransactions()', function() {
it('should be able to listTransactions with specific count', function(done) {
var client = makeClient();
client.listTransactions(test.account, 15, function(err, txs) {
assert.ifError(err);
assert.ok(txs);
assert.ok(Array.isArray(txs));
done();
});
});
describe('getNewAddress()', function () {
it('should be able to get new address', function (done) {
var client = makeClient()
client.getNewAddress(test.account, function (err, address) {
assert.ifError(err)
client.getAddressesByAccount(test.account, function (err, addresses) {
assert.ifError(err)
assert.ok(addresses && addresses.length > 0)
done()
})
})
})
})
it('should be able to listTransactions without specific count', function(done) {
var client = makeClient();
client.listTransactions(test.account, function(err, txs) {
assert.ifError(err);
assert.ok(txs);
assert.ok(Array.isArray(txs));
done();
});
});
});
describe('getBalance()', function () {
it('should return balance without any args', function (done) {
var client = makeClient()
client.getBalance(function (err, balance) {
assert.ifError(err)
assert.ok(typeof balance === 'number')
done()
})
})
})
describe('getNewAddress()', function() {
it('should be able to get new address', function(done) {
var client = makeClient();
client.getNewAddress(test.account, function(err, address) {
assert.ifError(err);
client.getAddressesByAccount(test.account, function(err, addresses) {
assert.ifError(err);
assert.ok(addresses && addresses.length > 0);
done();
});
});
});
});
describe('getDifficulty()', function () {
it('should get difficulty', function (done) {
var client = makeClient()
client.getDifficulty(function (err, difficulty) {
assert.ifError(err)
assert.ok(typeof difficulty === 'number')
done()
})
})
})
describe('getBalance()', function() {
it('should return balance without any args', function(done) {
var client = makeClient();
client.getBalance(function(err, balance) {
assert.ifError(err);
assert.ok(typeof balance === 'number');
done();
});
});
});
describe('getInfo()', function () {
it('should get info', function (done) {
var client = makeClient()
client.getInfo(function (err, info, headers) {
assert.ifError(err)
notEmpty(info)
assert.ok(info.errors === '')
done()
})
})
})
describe('getDifficulty()', function() {
it('should get difficulty', function(done) {
var client = makeClient();
client.getDifficulty(function(err, difficulty) {
assert.ifError(err);
assert.ok(typeof difficulty === 'number');
done();
});
});
});
describe('help()', function () {
it('should return help', function (done) {
var client = makeClient()
client.help(function (err, help) {
assert.ifError(err)
notEmpty(help)
done()
})
})
})
describe('getInfo()', function() {
it('should get info', function(done) {
var client = makeClient();
client.getInfo(function(err, info, headers) {
assert.ifError(err);
notEmpty(info);
assert.ok(info.errors === '');
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()
})
})
describe('getHashesPerSec()', function() {
it('should get hashes per second', function(done) {
var client = makeClient();
client.getHashesPerSec(function(err, data) {
assert.ifError(err);
notEmpty(data);
assert.ok(typeof data === 'number');
done();
});
});
});
it('running batch of rpc calls', function (done) {
this.timeout(5000)
var batch = []
describe('help()', function() {
it('should return help', function(done) {
var client = makeClient();
client.help(function(err, help) {
assert.ifError(err);
notEmpty(help);
done();
});
});
});
describe('getWork()', function() {
it('should get work', function(done) {
var client = makeClient();
client.getWork(function(err, work) {
assert.ifError(err);
notEmpty(work);
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) {
batch.push({
method: 'getnewaddress',
params: [test.account]
})
});
}
var client = makeClient()
var batchCallbackCount = 0
client.cmd(batch, function (err, address) {
assert.ifError(err)
assert.ok(++batchCallbackCount <= 10)
assert.ok(address)
if (batchCallbackCount === 10) done()
})
})
var client = makeClient();
var batchCallbackCount = 0;
client.cmd(batch, function(err, address) {
assert.ifError(err);
assert.ok(++batchCallbackCount <= 10);
assert.ok(address);
if (batchCallbackCount === 10) done();
});
});
describe('invalid credentials', function () {
var badCredentials = clone(config)
badCredentials.user = 'baduser'
badCredentials.pass = 'badpwd'
var client = new bitcoin.Client(badCredentials)
describe('invalid credentials', function() {
var badCredentials = clone(config);
badCredentials.user = 'baduser';
badCredentials.pass = 'badpwd';
var client = new bitcoin.Client(badCredentials);
it('should still return client object', function (done) {
assert.ok(client instanceof bitcoin.Client)
done()
})
it('should still return client object', function(done) {
assert.ok(client instanceof bitcoin.Client);
done();
});
it('should return status 401 with html', function (done) {
client.getDifficulty(function (err, difficulty) {
assert.ok(err instanceof Error)
assert.equal(err.message, 'Invalid params, response status code: 401')
assert.equal(err.code, -32602)
assert.equal(difficulty, undefined)
done()
})
})
})
it('should return status 401 with html', function(done) {
client.getDifficulty(function(err, difficulty) {
assert.ok(err instanceof Error);
assert.equal(err.message, 'Invalid params, response status code: 401');
assert.equal(err.code, -32602);
assert.equal(difficulty, undefined);
done();
});
});
});
describe('creating client on non-listening port', function () {
var badPort = clone(config)
badPort.port = 9897
badPort.user = 'baduser'
badPort.pass = 'badpwd'
var client = new bitcoin.Client(badPort)
describe('creating client on non-listening port', function() {
var badPort = clone(config);
badPort.port = 9897;
badPort.user = 'baduser';
badPort.pass = 'badpwd';
var client = new bitcoin.Client(badPort);
it('will return client object', function (done) {
assert.ok(client instanceof bitcoin.Client)
done()
})
it('will return client object', function(done) {
assert.ok(client instanceof bitcoin.Client);
done();
});
it('should not call callback more than once', function (done) {
client.listSinceBlock(function (err, result) {
assert.ok(err instanceof Error)
done()
})
})
})
it('should not call callback more than once', function(done) {
client.listSinceBlock(function(err, result) {
assert.ok(err instanceof Error);
done();
});
});
});
describe('request timeouts', function () {
it('should occur by default after 30000ms', function (done) {
this.timeout(31000)
var server = makeServer(19998)
var request // eslint-disable-line no-unused-vars
var response
server.on('request', function (req, res) {
request = req
response = res
})
describe('request timeouts', function() {
it('should occur by default after 30000ms', function(done) {
this.timeout(31000);
var server = makeServer(19998);
var request;
var response;
server.on('request', function(req, res) {
request = req;
response = res;
});
var client = new bitcoin.Client({
host: 'localhost',
port: 19998,
user: 'admin1',
pass: '123'
})
var start = Date.now()
client.getInfo(function (err, info) {
var delta = Date.now() - start
assert.ok(err instanceof Error)
assert.ok(err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT')
assert.ok(delta >= 30000, 'delta should be >= 30000: ' + delta)
response.end()
server.close()
done()
})
})
});
var start = Date.now();
client.getInfo(function(err, info) {
var delta = Date.now() - start;
assert.ok(err instanceof Error);
assert.ok(err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT');
assert.ok(delta >= 30000, 'delta should be >= 30000: ' + delta);
response.end();
server.close();
done();
});
});
it('should be customizable', function (done) {
this.timeout(4500)
var server = makeServer(19999)
var request // eslint-disable-line no-unused-vars
var response
server.on('request', function (req, res) {
request = req
response = res
})
it('should be customizable', function(done) {
this.timeout(4500);
var server = makeServer(19999);
var request;
var response;
server.on('request', function(req, res) {
request = req;
response = res;
});
var client = new bitcoin.Client({
host: 'localhost',
port: 19999,
user: 'admin1',
pass: '123',
timeout: 2500
})
var start = Date.now()
client.getInfo(function (err, info) {
var delta = Date.now() - start
assert.ok(err instanceof Error)
assert.ok(err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT')
assert.ok(delta >= 2500, 'delta should be >= 2500:' + delta)
response.end()
server.close()
done()
})
})
})
});
var start = Date.now();
client.getInfo(function(err, info) {
var delta = Date.now() - start;
assert.ok(err instanceof Error);
assert.ok(err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT');
assert.ok(delta >= 2500, 'delta should be >= 2500:' + delta);
response.end();
server.close();
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) {
var client = makeClient()
client.getNewAddress(test.account, function (err, address, resHeaders) {
assert.ifError(err)
assert.ok(address)
assertResHeaders(resHeaders)
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 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()
})
})
})
})
})
it('should be returned for 1-parameter call', function(done) {
var client = makeClient();
client.getNewAddress(test.account, function(err, address, resHeaders) {
assert.ifError(err);
assert.ok(address);
assertResHeaders(resHeaders);
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();
});
});
});
});
});

View File

@ -1,75 +1,78 @@
/* global describe, it */
var assert = require('assert')
var bitcoin = require('../')
var config = require('./config')
var commands = require('../lib/commands')
var getHelpCommands = function (client, cb) {
var commandRegex = /^([a-z]+)/
client.cmd('help', function (err, commandList) {
if (err) return cb(err)
var helpCommands = []
var assert = require('assert'),
bitcoin = require('../'),
config = require('./config'),
commands = require('../lib/commands');
var getHelpCommands = function(client, cb) {
var commandRegex = /^([a-z]+)/;
client.cmd('help', function(err, commandList) {
if (err) return cb(err);
var helpCommands = [];
// split up the command list by newlines
var commandListLines = commandList.split('\n')
var result
var commandListLines = commandList.split('\n');
var result;
for (var i in commandListLines) {
result = commandRegex.exec(commandListLines[i])
if (!result) continue
helpCommands.push(result[1])
result = commandRegex.exec(commandListLines[i]);
if (!result) {
return cb(new Error('command list line failed to match regex: ' + commandListLines[i]));
}
helpCommands.push(result[1]);
}
cb(null, helpCommands)
})
}
describe('Client Commands', function () {
it('should have all the commands listed by `help`', function (done) {
var client = new bitcoin.Client(config)
getHelpCommands(client, function (err, helpCommands) {
assert.ifError(err)
cb(null, helpCommands);
});
};
describe('Client Commands', function() {
it('should have all the commands listed by `help`', function(done) {
var client = new bitcoin.Client(config);
getHelpCommands(client, function(err, helpCommands) {
assert.ifError(err);
for (var i in helpCommands) {
var found = false
var found = true;
for (var j in commands) {
if (commands[j] === helpCommands[i]) {
found = true
break
found = true;
break;
}
}
assert.ok(found, 'missing command found in `help`: ' + helpCommands[i])
assert.ok(found, 'missing command found in `help`: ' + helpCommands[i]);
}
done()
})
})
it('should not have any commands not listed by `help`', function (done) {
var client = new bitcoin.Client(config)
getHelpCommands(client, function (err, helpCommands) {
assert.ifError(err)
done();
});
});
it('should not have any commands not listed by `help`', function(done) {
var client = new bitcoin.Client(config);
getHelpCommands(client, function(err, helpCommands) {
assert.ifError(err);
for (var i in commands) {
var found = false
var found = false;
for (var j in helpCommands) {
if (commands[i] === helpCommands[j]) {
found = true
break
found = true;
break;
}
}
// ignore commands not found in help because they are hidden
// if the wallet isn't encrypted
var ignore = ['walletlock', 'walletpassphrase', 'walletpassphrasechange']
var ignore = ['walletlock', 'walletpassphrase', 'walletpassphrasechange'];
if (~ignore.indexOf(commands[i])) {
assert.ok(!found, 'command found in `help`: ' + commands[i])
assert.ok(!found, 'command found in `help`: ' + commands[i]);
} else {
assert.ok(found, 'command not found in `help`: ' + commands[i])
assert.ok(found, 'command not found in `help`: ' + commands[i]);
}
}
done()
})
})
})
done();
});
});
});

View File

@ -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 fs = require('fs')
var clone = require('clone')
var bitcoin = require('../')
var config = require('./config')
var getInfo = function(opts, cb) {
var client = new bitcoin.Client(opts);
client.getInfo(cb);
};
var getInfo = function (opts, cb) {
var client = new bitcoin.Client(opts)
client.getInfo(cb)
}
describe('Client SSL', function () {
it('use sslStrict by default', function (done) {
var opts = clone(config)
opts.ssl = true
getInfo(opts, function (err, info) {
assert.ok(err instanceof Error)
describe('Client SSL', function() {
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
// and uses a user-friendly `message`
// continue using err.message for v0.8 and v0.10
assert.equal(err.code || err.message, 'DEPTH_ZERO_SELF_SIGNED_CERT')
done()
})
})
assert.equal(err.code || err.message, 'DEPTH_ZERO_SELF_SIGNED_CERT');
done();
});
});
it('strictSSL should fail with self-signed certificate', function (done) {
var opts = clone(config)
opts.ssl = true
opts.sslStrict = true
getInfo(opts, function (err, info) {
assert.ok(err instanceof Error)
it('strictSSL should fail with self-signed certificate', function(done) {
var opts = clone(config);
opts.ssl = true;
opts.sslStrict = true;
getInfo(opts, function(err, info) {
assert.ok(err instanceof Error);
// node v0.11 adds `code` param to this error
// and uses a user-friendly `message`
// continue using err.message for v0.8 and v0.10
assert.equal(err.code || err.message, 'DEPTH_ZERO_SELF_SIGNED_CERT')
done()
})
})
assert.equal(err.code || err.message, 'DEPTH_ZERO_SELF_SIGNED_CERT');
done();
});
});
it('self-signed certificate with sslStrict false', function (done) {
var opts = clone(config)
opts.ssl = true
opts.sslStrict = false
getInfo(opts, function (err, info) {
assert.ifError(err)
assert.ok(info)
done()
})
})
it('self-signed certificate with sslStrict false', function(done) {
var opts = clone(config);
opts.ssl = true;
opts.sslStrict = false;
getInfo(opts, function(err, info) {
assert.ifError(err);
assert.ok(info);
done();
});
});
it('self-signed certificate with sslStrict and CA specified', function (done) {
var opts = clone(config)
opts.ssl = true
opts.sslCa = fs.readFileSync(__dirname + '/testnet-box/1/regtest/server.cert')
getInfo(opts, function (err, info) {
assert.ifError(err)
assert.ok(info)
done()
})
})
})
it('self-signed certificate with sslStrict and CA specified', function(done) {
var opts = clone(config);
opts.ssl = true;
opts.sslCa = fs.readFileSync(__dirname + '/testnet-box/1/regtest/server.cert');
getInfo(opts, function(err, info) {
assert.ifError(err);
assert.ok(info);
done();
});
});
});

@ -1 +1 @@
Subproject commit 24f5214acfddfec498cca21dd96dac480e9b9013
Subproject commit 54e884df1f49959b21cf4e2014424a172722ed5c