Compare commits
142 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6eaefd223 | ||
|
|
c097b9c81e | ||
|
|
cb6e5c811b | ||
|
|
e969b3844f | ||
|
|
07d320d630 | ||
|
|
7b739e8eb9 | ||
|
|
e956310d43 | ||
|
|
b444d23f00 | ||
|
|
fe1ab3fc52 | ||
|
|
33d4ff9079 | ||
|
|
b9a2a749d8 | ||
|
|
b136254de9 | ||
|
|
bfedefd8c4 | ||
|
|
12860e83de | ||
|
|
2a067655c5 | ||
|
|
b93026db3a | ||
|
|
1d76ea1e14 | ||
|
|
16f07d9a7a | ||
|
|
990d5c472a | ||
|
|
41818121ae | ||
|
|
67e6545d88 | ||
|
|
43e1412066 | ||
|
|
12d8fd898a | ||
|
|
a245166a65 | ||
|
|
d25098240b | ||
|
|
0ef43d8555 | ||
|
|
a83c454525 | ||
|
|
bd63966e43 | ||
|
|
6973183179 | ||
|
|
4328a49b63 | ||
|
|
2e56677ab9 | ||
|
|
69393ae38c | ||
|
|
4e0851d859 | ||
|
|
4f47030c53 | ||
|
|
2e4c46cc41 | ||
|
|
00047173d5 | ||
|
|
cb95f56e9c | ||
|
|
bb8d05e556 | ||
|
|
b2900f01b9 | ||
|
|
75c204c109 | ||
|
|
fff3333c6c | ||
|
|
ce29b1d74e | ||
|
|
b9a3043de6 | ||
|
|
c8e5a1dda5 | ||
|
|
3cbf41caad | ||
|
|
db518ff059 | ||
|
|
af727e9f91 | ||
|
|
5e7df878ce | ||
|
|
ee52f9ef5a | ||
|
|
15819275f5 | ||
|
|
25aaeee5af | ||
|
|
b8aeff8750 | ||
|
|
1aea9f2006 | ||
|
|
8d02a1e7e6 | ||
|
|
d716cf99ef | ||
|
|
b75262f501 | ||
|
|
03f16394db | ||
|
|
d9352f0cc5 | ||
|
|
654b4a675b | ||
|
|
cd6382afca | ||
|
|
347df714c4 | ||
|
|
66a132ccfb | ||
|
|
0d5fb299af | ||
|
|
1377f69351 | ||
|
|
a26112a640 | ||
|
|
c964c962c4 | ||
|
|
4623696d6b | ||
|
|
1e5fae327d | ||
|
|
af7cd16428 | ||
|
|
8512417889 | ||
|
|
4324d1c177 | ||
|
|
491fc3576d | ||
|
|
145cef5885 | ||
|
|
f68721c0ca | ||
|
|
7e578b43d7 | ||
|
|
5d83f0e43a | ||
|
|
b490f03e1c | ||
|
|
50825e3a11 | ||
|
|
6b237fe61e | ||
|
|
0fca45ecad | ||
|
|
8f4f522b47 | ||
|
|
39c4ebb0b7 | ||
|
|
788ae6a41b | ||
|
|
820d79adff | ||
|
|
3b307a27d0 | ||
|
|
6f44193d4b | ||
|
|
e2f755d313 | ||
|
|
915742cd17 | ||
|
|
8f1a886dc7 | ||
|
|
88457b5eed | ||
|
|
70742c87e4 | ||
|
|
2f05ad1107 | ||
|
|
13e1a46a86 | ||
|
|
596a828f07 | ||
|
|
3c20e34d1a | ||
|
|
03f124363c | ||
|
|
7e14ede5ca | ||
|
|
07edb0c4f5 | ||
|
|
0c1389612f | ||
|
|
1c2aba3c20 | ||
|
|
76873d1743 | ||
|
|
aec981d0fe | ||
|
|
a91b3474e9 | ||
|
|
2412d014d0 | ||
|
|
3619e6f038 | ||
|
|
106b922e82 | ||
|
|
8daa9085b3 | ||
|
|
1ac9e7d201 | ||
|
|
36417a5657 | ||
|
|
beeee58631 | ||
|
|
7d8269bc6d | ||
|
|
0a19d625c5 | ||
|
|
fb79db9b06 | ||
|
|
d11e048188 | ||
|
|
e6ac2d313b | ||
|
|
bcd0afbdf5 | ||
|
|
456477cedc | ||
|
|
a649d14852 | ||
|
|
bf4c75cc0c | ||
|
|
c989985b2c | ||
|
|
2127609f4c | ||
|
|
8b78279472 | ||
|
|
cb6c39dcf5 | ||
|
|
eb35da94d7 | ||
|
|
f1c94aab43 | ||
|
|
20a563f047 | ||
|
|
d012b9b315 | ||
|
|
1aee0ec091 | ||
|
|
e9e9b9f4e5 | ||
|
|
f29440b2da | ||
|
|
1077753fbf | ||
|
|
024e40dad8 | ||
|
|
7940a86028 | ||
|
|
24480cecec | ||
|
|
1cfefb82c7 | ||
|
|
c4be38158c | ||
|
|
c28f78c983 | ||
|
|
1a2947d9aa | ||
|
|
d7d4684918 | ||
|
|
637bc2ee65 | ||
|
|
292637c16e | ||
|
|
ff2ea67a7f |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
||||
node_modules/
|
||||
test/config.js
|
||||
.project
|
||||
|
||||
|
||||
6
.npmignore
Normal file
6
.npmignore
Normal file
@ -0,0 +1,6 @@
|
||||
node_modules/
|
||||
test/
|
||||
.project
|
||||
.gitmodules
|
||||
.travis.yml
|
||||
Dockerfile
|
||||
18
.travis.yml
Normal file
18
.travis.yml
Normal file
@ -0,0 +1,18 @@
|
||||
# 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
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
before_script:
|
||||
- git submodule update --init
|
||||
- docker build -t node-bitcoin .
|
||||
|
||||
script:
|
||||
- docker run node-bitcoin
|
||||
134
Changelog.md
134
Changelog.md
@ -1,14 +1,142 @@
|
||||
# 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
|
||||
* update devDependencies
|
||||
* add commands for bitcoind v0.10
|
||||
* `estimateFee`
|
||||
* `estimatePriority`
|
||||
* `getChainTips`
|
||||
* `importAddress`
|
||||
|
||||
## v2.2.0 (2014/08/29)
|
||||
* add commands for bitcoind v0.9.x
|
||||
* `decodeScript`
|
||||
* `dumpWallet`
|
||||
* `getBestBlockHash`
|
||||
* `getBlockchainInfo`
|
||||
* `getNetTotals`
|
||||
* `getNetworkInfo`
|
||||
* `getNetworkHashPs`
|
||||
* `getRawChangeAddress`
|
||||
* `getUnconfirmedBalance`
|
||||
* `getWalletInfo`
|
||||
* `ping`
|
||||
* `verifyChain`
|
||||
|
||||
## v2.1.2 (2014/04/16)
|
||||
* lazy load `http`/`https` module
|
||||
|
||||
## v2.1.1 (2014/03/25)
|
||||
* change default request timeout from `5000`ms to `30000`ms
|
||||
|
||||
## v2.1.0 (2014/03/12)
|
||||
* remove `deprecate` dependency
|
||||
* add request timeout option (defaults to 5000ms)
|
||||
* add 3rd parameter to callbacks: response headers
|
||||
|
||||
## v2.0.1 (2014/01/08)
|
||||
* default `host` to 'localhost'; `port` to '8332'
|
||||
|
||||
## v2.0.0 (2013/10/14)
|
||||
* remove deprecated commands
|
||||
* `getMemoryPool`
|
||||
* `getMemorypool`
|
||||
* remove deprecated functionality
|
||||
* creating `bitcoin.Client` with more than one argument
|
||||
|
||||
## v1.7.0 (2013/05/05)
|
||||
* add missing commands from bitcoind v0.7.0
|
||||
* `createMultiSig`
|
||||
* `getBlockTemplate`
|
||||
* `getTxOut`
|
||||
* `getTxOutSetInfo`
|
||||
* `listAddressGroupings`
|
||||
* `submitBlock`
|
||||
* deprecate commands
|
||||
* `getMemoryPool`
|
||||
* `getMemorypool`
|
||||
|
||||
## v1.6.2 (2013/03/21)
|
||||
* shrink package size via .npmignore
|
||||
|
||||
## v1.6.1 (2013/03/13)
|
||||
* add node v0.10.x support (rejectUnauthorized defaults to true in 0.10.x)
|
||||
|
||||
## v1.6.0 (2013/03/08)
|
||||
* drop node v0.6.x support
|
||||
* change test runner from `vows` to `mocha`
|
||||
* upgrade testnet-box
|
||||
* add commands for bitcoind v0.8.0
|
||||
* `addNode`
|
||||
* `getAddedNodeInfo`
|
||||
* `listLockUnspent`
|
||||
* `lockUnspent`
|
||||
* deprecate creating `bitcoin.Client` with more than one argument
|
||||
* add SSL support
|
||||
|
||||
## v1.5.0 (2012/10/22)
|
||||
* remove `getBlockNumber` test
|
||||
* upgrade testnet-box
|
||||
* add RPC call batching (multiple RPC calls within one HTTP request)
|
||||
|
||||
## v1.4.0 (2012/09/09)
|
||||
* add commands for bitcoind v0.7.0
|
||||
* `createRawTransaction`
|
||||
* `decodeRawTransaction`
|
||||
* `getPeerInfo`
|
||||
* `getRawMemPool`
|
||||
* `getRawTransaction`
|
||||
* `listUnspent`
|
||||
* `sendRawTransaction`
|
||||
* `signRawTransaction`
|
||||
* remove deprecated `getBlockNumber`
|
||||
|
||||
## v1.3.1 (2012/08/19)
|
||||
Remove `underscore` dependency
|
||||
|
||||
## v1.3.0 (2012/07/03)
|
||||
Change use of http.createClient() (deprecated in node v0.8.x) to http.request()
|
||||
|
||||
## v1.2.2 (2012/04/26)
|
||||
Fix callback being called twice when a client and request error
|
||||
occur on the same command call.
|
||||
|
||||
## v1.2.1 (2012/04/26)
|
||||
* Add missing `getBlock` command
|
||||
* add missing `getBlock` command
|
||||
|
||||
## v1.2.0 (2012/04/25)
|
||||
* Submoduled testnet-box for running tests
|
||||
* submodule testnet-box for running tests
|
||||
* err objects should all now be an instance of Error
|
||||
|
||||
## v1.1.6 (2012/04/11)
|
||||
* New commands for bitcoin v0.6.0
|
||||
* add commands for bitcoind v0.6.0
|
||||
* `addMultiSigAddress` (only available in testnet)
|
||||
* `dumpPrivKey`
|
||||
* `getBlockHash`
|
||||
|
||||
21
Dockerfile
Normal file
21
Dockerfile
Normal file
@ -0,0 +1,21 @@
|
||||
# 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
Normal file
24
LICENSE
Normal file
@ -0,0 +1,24 @@
|
||||
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/>
|
||||
28
Makefile
28
Makefile
@ -1,20 +1,42 @@
|
||||
VOWS=./node_modules/.bin/vows
|
||||
MOCHA=./node_modules/.bin/mocha
|
||||
BOX=test/testnet-box
|
||||
|
||||
test:
|
||||
$(MAKE) test-ssl-no
|
||||
sleep 20
|
||||
$(MAKE) clean
|
||||
$(MAKE) test-ssl
|
||||
|
||||
test-ssl-no:
|
||||
$(MAKE) start
|
||||
sleep 15
|
||||
sleep 20
|
||||
$(MAKE) run-test
|
||||
$(MAKE) stop
|
||||
|
||||
test-ssl:
|
||||
$(MAKE) start-ssl
|
||||
sleep 20
|
||||
$(MAKE) run-test-ssl
|
||||
$(MAKE) stop-ssl
|
||||
|
||||
start:
|
||||
$(MAKE) -C $(BOX) start
|
||||
|
||||
start-ssl:
|
||||
$(MAKE) -C $(BOX) start B1_FLAGS=-rpcssl=1 B2_FLAGS=-rpcssl=1
|
||||
|
||||
stop:
|
||||
$(MAKE) -C $(BOX) stop
|
||||
@while ps -C bitcoind > /dev/null; do sleep 1; done
|
||||
|
||||
stop-ssl:
|
||||
$(MAKE) -C $(BOX) stop B1_FLAGS=-rpcssl=1 B2_FLAGS=-rpcssl=1
|
||||
|
||||
run-test:
|
||||
$(VOWS) test/api.js
|
||||
$(MOCHA) --invert --grep SSL
|
||||
|
||||
run-test-ssl:
|
||||
$(MOCHA) --grep SSL
|
||||
|
||||
clean:
|
||||
$(MAKE) -C $(BOX) clean
|
||||
|
||||
91
Readme.md
91
Readme.md
@ -1,7 +1,25 @@
|
||||
# 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.
|
||||
|
||||
**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.
|
||||
@ -10,46 +28,24 @@ object, or you may call the API directly using the `cmd` method.
|
||||
|
||||
`npm install bitcoin`
|
||||
|
||||
## Setup
|
||||
|
||||
1. Traverse to `~/.bitcoin` or `~/Library/Application Support/Bitcoin` and add a
|
||||
file called `bitcoin.conf` if it doesn't already exist.
|
||||
|
||||
2. Add these lines to the file:
|
||||
|
||||
rpcuser=username
|
||||
|
||||
rpcpassword=password
|
||||
|
||||
You will use these to login to the server.
|
||||
|
||||
3. Start your Bitcoin client with the `-server` argument or run `bitcoind`
|
||||
|
||||
4. You should now be able to communicate with Bitcoin JSON-RPC API using the
|
||||
node-bitcoin library, try it out!
|
||||
|
||||
## Examples
|
||||
|
||||
### Create client
|
||||
```js
|
||||
var bitcoin = require('bitcoin');
|
||||
var client = new bitcoin.Client('localhost', 8332, 'username', 'password');
|
||||
```
|
||||
|
||||
### Create client with single object
|
||||
```js
|
||||
// all config options are optional
|
||||
var client = new bitcoin.Client({
|
||||
host: 'localhost',
|
||||
port: 8332,
|
||||
user: 'username',
|
||||
pass: 'password'
|
||||
pass: 'password',
|
||||
timeout: 30000
|
||||
});
|
||||
```
|
||||
|
||||
### Get balance across all accounts with minimum confirmations of 6
|
||||
|
||||
```js
|
||||
client.getBalance('*', 6, function(err, balance) {
|
||||
client.getBalance('*', 6, function(err, balance, resHeaders) {
|
||||
if (err) return console.log(err);
|
||||
console.log('Balance:', balance);
|
||||
});
|
||||
@ -57,8 +53,49 @@ client.getBalance('*', 6, function(err, balance) {
|
||||
### Getting the balance directly using `cmd`
|
||||
|
||||
```js
|
||||
client.cmd('getbalance', '*', 6, function(err, balance){
|
||||
client.cmd('getbalance', '*', 6, function(err, balance, resHeaders){
|
||||
if (err) return console.log(err);
|
||||
console.log('Balance:', balance);
|
||||
});
|
||||
```
|
||||
|
||||
### Batch multiple RPC calls into single HTTP request
|
||||
|
||||
```js
|
||||
var batch = [];
|
||||
for (var i = 0; i < 10; ++i) {
|
||||
batch.push({
|
||||
method: 'getnewaddress',
|
||||
params: ['myaccount']
|
||||
});
|
||||
}
|
||||
client.cmd(batch, function(err, address, resHeaders) {
|
||||
if (err) return console.log(err);
|
||||
console.log('Address:', address);
|
||||
});
|
||||
```
|
||||
|
||||
## SSL
|
||||
See [Enabling SSL on original client](https://en.bitcoin.it/wiki/Enabling_SSL_on_original_client_daemon).
|
||||
|
||||
If you're using this to connect to bitcoind across a network it is highly
|
||||
recommended to enable `ssl`, otherwise an attacker may intercept your RPC credentials
|
||||
resulting in theft of your bitcoins.
|
||||
|
||||
When enabling `ssl` by setting the configuration option to `true`, the `sslStrict`
|
||||
option (verifies the server certificate) will also be enabled by default. It is
|
||||
highly recommended to specify the `sslCa` as well, even if your bitcoind has
|
||||
a certificate signed by an actual CA, to ensure you are connecting
|
||||
to your own bitcoind.
|
||||
|
||||
```js
|
||||
var client = new bitcoin.Client({
|
||||
host: 'localhost',
|
||||
port: 8332,
|
||||
user: 'username',
|
||||
pass: 'password',
|
||||
ssl: true,
|
||||
sslStrict: true,
|
||||
sslCa: fs.readFileSync(__dirname + '/myca.cert')
|
||||
});
|
||||
```
|
||||
|
||||
@ -1,124 +0,0 @@
|
||||
|
||||
var rpc = require('../jsonrpc')
|
||||
, _ = require('underscore')._;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// jsonrpc wrappers
|
||||
//===----------------------------------------------------------------------===//
|
||||
var bitcoinAPI = {
|
||||
addMultiSigAddress: 'addmultisigaddress',
|
||||
backupWallet: 'backupwallet',
|
||||
dumpPrivKey: 'dumpprivkey',
|
||||
encryptWallet: 'encryptwallet',
|
||||
getAccount: 'getaccount',
|
||||
getAccountAddress: 'getaccountaddress',
|
||||
getAddressesByAccount: 'getaddressesbyaccount',
|
||||
getBalance: 'getbalance',
|
||||
getBlock: 'getblock',
|
||||
getBlockCount: 'getblockcount',
|
||||
getBlockHash: 'getblockhash',
|
||||
getBlockNumber: 'getblockcount', // getblocknumber deprecated since Bitcoin v0.5.1
|
||||
getConnectionCount: 'getconnectioncount',
|
||||
getDifficulty: 'getdifficulty',
|
||||
getGenerate: 'getgenerate',
|
||||
getHashesPerSecond: 'gethashespersec',
|
||||
getHashesPerSec: 'gethashespersec',
|
||||
getInfo: 'getinfo',
|
||||
getMemorypool: 'getmemorypool',
|
||||
getMemoryPool: 'getmemorypool',
|
||||
getMiningInfo: 'getmininginfo',
|
||||
getNewAddress: 'getnewaddress',
|
||||
getReceivedByAccount: 'getreceivedbyaccount',
|
||||
getReceivedByAddress: 'getreceivedbyaddress',
|
||||
getTransaction: 'gettransaction',
|
||||
getWork: 'getwork',
|
||||
help: 'help',
|
||||
importPrivKey: 'importprivkey',
|
||||
keypoolRefill: 'keypoolrefill',
|
||||
keyPoolRefill: 'keypoolrefill',
|
||||
listAccounts: 'listaccounts',
|
||||
listReceivedByAccount: 'listreceivedbyaccount',
|
||||
listReceivedByAddress: 'listreceivedbyaddress',
|
||||
listSinceBlock: 'listsinceblock',
|
||||
listTransactions: 'listtransactions',
|
||||
move: 'move',
|
||||
sendFrom: 'sendfrom',
|
||||
sendMany: 'sendmany',
|
||||
sendToAddress: 'sendtoaddress',
|
||||
setAccount: 'setaccount',
|
||||
setGenerate: 'setgenerate',
|
||||
setTxFee: 'settxfee',
|
||||
signMessage: 'signmessage',
|
||||
stop: 'stop',
|
||||
validateAddress: 'validateaddress',
|
||||
verifyMessage: 'verifymessage',
|
||||
walletLock: 'walletlock',
|
||||
walletPassphrase: 'walletpassphrase',
|
||||
walletPassphraseChange: 'walletpassphrasechange'
|
||||
};
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Client
|
||||
// Either pass in 4 arguments, or a single object with host, port, user, pass
|
||||
//===----------------------------------------------------------------------===//
|
||||
function Client() {
|
||||
var args = [].slice.call(arguments);
|
||||
this.host = args[0].host || args[0];
|
||||
this.port = args[0].port || args[1];
|
||||
this.user = args[0].user || args[2];
|
||||
this.pass = args[0].pass || args[3];
|
||||
|
||||
this.rpc = new rpc.Client(this.port, this.host, this.user, this.pass);
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// cmd
|
||||
// Call custom jsonrpc commands
|
||||
//===----------------------------------------------------------------------===//
|
||||
Client.prototype.cmd = function() {
|
||||
var args = [].slice.call(arguments);
|
||||
var cmd = args.shift();
|
||||
|
||||
callRpc(cmd, args, this.rpc);
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// callRpc
|
||||
//===----------------------------------------------------------------------===//
|
||||
function callRpc(cmd, args, rpc) {
|
||||
var fn = args[args.length-1];
|
||||
|
||||
// If the last function is a callback, pop it from the args list
|
||||
if(_.isFunction(fn)) {
|
||||
args.pop();
|
||||
} else {
|
||||
fn = function () {};
|
||||
}
|
||||
|
||||
rpc.call(cmd, args, function(){
|
||||
var args = [].slice.call(arguments);
|
||||
args.unshift(null);
|
||||
fn.apply(this, args);
|
||||
}, function(err){
|
||||
fn(err);
|
||||
});
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Initialize wrappers
|
||||
//===----------------------------------------------------------------------===//
|
||||
(function() {
|
||||
_.each(bitcoinAPI, function(jsonFn, protoFn) {
|
||||
Client.prototype[protoFn] = function() {
|
||||
var args = [].slice.call(arguments);
|
||||
callRpc(jsonFn, args, this.rpc);
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
// Export!
|
||||
module.exports = Client;
|
||||
@ -1,2 +0,0 @@
|
||||
|
||||
module.exports.Client = require('./client');
|
||||
92
lib/commands.js
Normal file
92
lib/commands.js
Normal file
@ -0,0 +1,92 @@
|
||||
module.exports = {
|
||||
addMultiSigAddress: 'addmultisigaddress',
|
||||
addNode: 'addnode', // bitcoind v0.8.0+
|
||||
backupWallet: 'backupwallet',
|
||||
createMultiSig: 'createmultisig',
|
||||
createRawTransaction: 'createrawtransaction', // bitcoind v0.7.0+
|
||||
decodeRawTransaction: 'decoderawtransaction', // bitcoind v0.7.0+
|
||||
decodeScript: 'decodescript',
|
||||
dumpPrivKey: 'dumpprivkey',
|
||||
dumpWallet: 'dumpwallet', // bitcoind v0.9.0+
|
||||
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+
|
||||
getAddressesByAccount: 'getaddressesbyaccount',
|
||||
getBalance: 'getbalance',
|
||||
getBestBlockHash: 'getbestblockhash', // bitcoind v0.9.0+
|
||||
getBlock: 'getblock',
|
||||
getBlockStats: 'getblockstats',
|
||||
getBlockFilter: 'getblockfilter',
|
||||
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',
|
||||
getInfo: 'getinfo',
|
||||
getMempoolAncestors: 'getmempoolancestors',
|
||||
getMempoolDescendants: 'getmempooldescendants',
|
||||
getMempoolEntry: 'getmempoolentry',
|
||||
getMempoolInfo: 'getmempoolinfo', // bitcoind v0.10+
|
||||
getMiningInfo: 'getmininginfo',
|
||||
getNetTotals: 'getnettotals',
|
||||
getNetworkInfo: 'getnetworkinfo', // bitcoind v0.9.2+
|
||||
getNetworkHashPs: 'getnetworkhashps', // bitcoind v0.9.0+
|
||||
getNewAddress: 'getnewaddress',
|
||||
getPeerInfo: 'getpeerinfo', // bitcoind v0.7.0+
|
||||
getRawChangeAddress: 'getrawchangeaddress', // bitcoin v0.9+
|
||||
getRawMemPool: 'getrawmempool', // bitcoind v0.7.0+
|
||||
getRawTransaction: 'getrawtransaction', // bitcoind v0.7.0+
|
||||
getReceivedByAccount: 'getreceivedbyaccount',
|
||||
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+
|
||||
help: 'help',
|
||||
importAddress: 'importaddress', // bitcoind v0.10.0+
|
||||
importPrivKey: 'importprivkey',
|
||||
importWallet: 'importwallet', // bitcoind v0.9.0+
|
||||
keypoolRefill: 'keypoolrefill',
|
||||
keyPoolRefill: 'keypoolrefill',
|
||||
listAccounts: 'listaccounts',
|
||||
listAddressGroupings: 'listaddressgroupings', // bitcoind v0.7.0+
|
||||
listLockUnspent: 'listlockunspent', // bitcoind v0.8.0+
|
||||
listReceivedByAccount: 'listreceivedbyaccount',
|
||||
listReceivedByAddress: 'listreceivedbyaddress',
|
||||
listSinceBlock: 'listsinceblock',
|
||||
listTransactions: 'listtransactions',
|
||||
listUnspent: 'listunspent', // bitcoind v0.7.0+
|
||||
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+
|
||||
sendToAddress: 'sendtoaddress',
|
||||
setAccount: 'setaccount',
|
||||
setGenerate: 'setgenerate',
|
||||
setTxFee: 'settxfee',
|
||||
signMessage: 'signmessage',
|
||||
signRawTransaction: 'signrawtransaction', // bitcoind v0.7.0+
|
||||
stop: 'stop',
|
||||
submitBlock: 'submitblock', // bitcoind v0.7.0+
|
||||
validateAddress: 'validateaddress',
|
||||
verifyChain: 'verifychain', // bitcoind v0.9.0+
|
||||
verifyMessage: 'verifymessage',
|
||||
verifyTxOutProof: 'verifytxoutproof', // bitcoind v0.11.0+
|
||||
walletLock: 'walletlock',
|
||||
walletPassphrase: 'walletpassphrase',
|
||||
walletPassphraseChange: 'walletpassphrasechange'
|
||||
}
|
||||
58
lib/index.js
Normal file
58
lib/index.js
Normal file
@ -0,0 +1,58 @@
|
||||
var commands = require('./commands')
|
||||
var rpc = require('./jsonrpc')
|
||||
|
||||
// ===----------------------------------------------------------------------===//
|
||||
// Client
|
||||
// ===----------------------------------------------------------------------===//
|
||||
function Client (opts) {
|
||||
this.rpc = new rpc.Client(opts)
|
||||
}
|
||||
|
||||
// ===----------------------------------------------------------------------===//
|
||||
// cmd
|
||||
// ===----------------------------------------------------------------------===//
|
||||
Client.prototype.cmd = function () {
|
||||
var args = [].slice.call(arguments)
|
||||
var cmd = args.shift()
|
||||
|
||||
callRpc(cmd, args, this.rpc)
|
||||
}
|
||||
|
||||
// ===----------------------------------------------------------------------===//
|
||||
// callRpc
|
||||
// ===----------------------------------------------------------------------===//
|
||||
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()
|
||||
} else {
|
||||
fn = function () {}
|
||||
}
|
||||
|
||||
return rpc.call(cmd, args, function () {
|
||||
var args = [].slice.call(arguments)
|
||||
args.unshift(null)
|
||||
fn.apply(this, args)
|
||||
}, function (err) {
|
||||
fn(err)
|
||||
})
|
||||
}
|
||||
|
||||
// ===----------------------------------------------------------------------===//
|
||||
// Initialize wrappers
|
||||
// ===----------------------------------------------------------------------===//
|
||||
(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)
|
||||
}
|
||||
})()
|
||||
|
||||
// Export!
|
||||
module.exports.Client = Client
|
||||
375
lib/jsonrpc.js
375
lib/jsonrpc.js
@ -1,272 +1,155 @@
|
||||
var util = require('util');
|
||||
var http = require('http');
|
||||
var METHOD_NOT_ALLOWED = "Method Not Allowed\n";
|
||||
var INVALID_REQUEST = "Invalid Request\n";
|
||||
var http = require('http')
|
||||
var https = require('https')
|
||||
|
||||
var Client = function (opts) {
|
||||
this.opts = opts || {}
|
||||
this.http = this.opts.ssl ? https : http
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Server Client
|
||||
//===----------------------------------------------------------------------===//
|
||||
var Client = function(port, host, user, password) {
|
||||
this.port = port;
|
||||
this.host = host;
|
||||
this.user = user;
|
||||
this.password = password;
|
||||
Client.prototype.call = function (method, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var time = Date.now()
|
||||
var requestJSON
|
||||
|
||||
this.call = function(method, params, callback, errback, path) {
|
||||
var client = http.createClient(port, host);
|
||||
|
||||
// First we encode the request into JSON
|
||||
var requestJSON = JSON.stringify({
|
||||
'id': '' + (new Date()).getTime(),
|
||||
'method': method,
|
||||
'params': params
|
||||
});
|
||||
|
||||
var headers = {};
|
||||
|
||||
if (user && password) {
|
||||
var buff = new Buffer(this.user + ":" + this.password)
|
||||
.toString('base64');
|
||||
var auth = 'Basic ' + buff;
|
||||
headers['Authorization'] = auth;
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// Then we build some basic headers.
|
||||
headers['Host'] = host;
|
||||
headers['Content-Length'] = requestJSON.length;
|
||||
// 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: '/',
|
||||
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
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
var request = client.request('POST', path || '/', headers);
|
||||
request.write(requestJSON);
|
||||
// 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)
|
||||
|
||||
client.on('error', function(e){
|
||||
errback(e);
|
||||
});
|
||||
// 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(e){
|
||||
errback(e);
|
||||
});
|
||||
request.on('error', function (err) {
|
||||
if (cbCalled) return
|
||||
cbCalled = true
|
||||
clearTimeout(reqTimeout)
|
||||
reject(err)
|
||||
})
|
||||
|
||||
request.on('response', function (response) {
|
||||
clearTimeout(reqTimeout)
|
||||
|
||||
request.on('response', function(response) {
|
||||
// We need to buffer the response chunks in a nonblocking way.
|
||||
var buffer = '';
|
||||
response.on('data', function(chunk) {
|
||||
buffer = buffer + chunk;
|
||||
});
|
||||
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;
|
||||
|
||||
response.on('end', function () {
|
||||
var err
|
||||
|
||||
if (cbCalled) return
|
||||
cbCalled = true
|
||||
|
||||
try {
|
||||
var decoded = JSON.parse(buffer);
|
||||
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);
|
||||
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;
|
||||
errback(err);
|
||||
err = new Error('Problem parsing JSON response from server')
|
||||
err.code = -32603
|
||||
reject(err)
|
||||
}
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
if (decoded.hasOwnProperty('error') && decoded.error != null) {
|
||||
if (errback) {
|
||||
err = new Error(decoded.error.message || '');
|
||||
if (decoded.error.code) {
|
||||
err.code = decoded.error.code;
|
||||
}
|
||||
errback(err);
|
||||
}
|
||||
} else if (decoded.hasOwnProperty('result')) {
|
||||
if (callback) {
|
||||
callback(decoded.result);
|
||||
}
|
||||
} else {
|
||||
if (errback) {
|
||||
err = new Error(decoded.error.message || '');
|
||||
if (decoded.error.code) {
|
||||
err.code = decoded.error.code;
|
||||
}
|
||||
errback(err);
|
||||
}
|
||||
|
||||
if (!Array.isArray(decoded)) {
|
||||
decoded = [decoded]
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Server
|
||||
//===----------------------------------------------------------------------===//
|
||||
function Server() {
|
||||
var self = this;
|
||||
this.functions = {};
|
||||
this.server = http.createServer(function(req, res) {
|
||||
Server.trace('<--', 'accepted request');
|
||||
if(req.method === 'POST') {
|
||||
self.handlePOST(req, res);
|
||||
}
|
||||
else {
|
||||
Server.handleNonPOST(req, res);
|
||||
}
|
||||
// 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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// exposeModule
|
||||
//===----------------------------------------------------------------------===//
|
||||
Server.prototype.exposeModule = function(mod, object) {
|
||||
var funcs = [];
|
||||
for(var funcName in object) {
|
||||
var funcObj = object[funcName];
|
||||
if(typeof(funcObj) == 'function') {
|
||||
this.functions[mod + '.' + funcName] = funcObj;
|
||||
funcs.push(funcName);
|
||||
}
|
||||
}
|
||||
Server.trace('***', 'exposing module: ' + mod + ' [funs: ' + funcs.join(', ')
|
||||
+ ']');
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// expose
|
||||
//===----------------------------------------------------------------------===//
|
||||
Server.prototype.expose = function(name, func) {
|
||||
Server.trace('***', 'exposing: ' + name);
|
||||
this.functions[name] = func;
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// trace
|
||||
//===----------------------------------------------------------------------===//
|
||||
Server.trace = function(direction, message) {
|
||||
util.puts(' ' + direction + ' ' + message);
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// listen
|
||||
//===----------------------------------------------------------------------===//
|
||||
Server.prototype.listen = function(port, host) {
|
||||
this.server.listen(port, host);
|
||||
Server.trace('***', 'Server listening on http://' + (host || '127.0.0.1') +
|
||||
':' + port + '/');
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// handleInvalidRequest
|
||||
//===----------------------------------------------------------------------===//
|
||||
Server.handleInvalidRequest = function(req, res) {
|
||||
res.writeHead(400, {'Content-Type': 'text/plain',
|
||||
'Content-Length': INVALID_REQUEST.length});
|
||||
res.write(INVALID_REQUEST);
|
||||
res.end();
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// handlePOST
|
||||
//===----------------------------------------------------------------------===//
|
||||
Server.prototype.handlePOST = function(req, res) {
|
||||
var buffer = '';
|
||||
var self = this;
|
||||
var handle = function (buf) {
|
||||
var decoded = JSON.parse(buf);
|
||||
|
||||
// Check for the required fields, and if they aren't there, then
|
||||
// dispatch to the handleInvalidRequest function.
|
||||
if(!(decoded.method && decoded.params)) {
|
||||
return Server.handleInvalidRequest(req, res);
|
||||
}
|
||||
|
||||
if(!self.functions.hasOwnProperty(decoded.method)) {
|
||||
return Server.handleInvalidRequest(req, res);
|
||||
}
|
||||
|
||||
// Build our success handler
|
||||
var onSuccess = function(funcResp) {
|
||||
Server.trace('-->', 'response (id ' + decoded.id + '): ' +
|
||||
JSON.stringify(funcResp));
|
||||
|
||||
var encoded = JSON.stringify({
|
||||
'result': funcResp,
|
||||
'error': null,
|
||||
'id': decoded.id
|
||||
});
|
||||
|
||||
res.writeHead(200, {'Content-Type': 'application/json',
|
||||
'Content-Length': encoded.length});
|
||||
res.write(encoded);
|
||||
res.end();
|
||||
};
|
||||
|
||||
// Build our failure handler (note that error must not be null)
|
||||
var onFailure = function(failure) {
|
||||
Server.trace('-->', 'failure: ' + JSON.stringify(failure));
|
||||
var encoded = JSON.stringify({
|
||||
'result': null,
|
||||
'error': failure || 'Unspecified Failure',
|
||||
'id': decoded.id
|
||||
});
|
||||
res.writeHead(200, {'Content-Type': 'application/json',
|
||||
'Content-Length': encoded.length});
|
||||
res.write(encoded);
|
||||
res.end();
|
||||
};
|
||||
|
||||
Server.trace('<--', 'request (id ' + decoded.id + '): ' +
|
||||
decoded.method + '(' + decoded.params.join(', ') + ')');
|
||||
|
||||
// Try to call the method, but intercept errors and call our
|
||||
// onFailure handler.
|
||||
var method = self.functions[decoded.method];
|
||||
var args = decoded.params.unshift(function(resp) {
|
||||
onSuccess(resp);
|
||||
});
|
||||
|
||||
try {
|
||||
method.apply(null, decoded.params);
|
||||
}
|
||||
catch(err) {
|
||||
return onFailure(err);
|
||||
}
|
||||
|
||||
} // function handle(buf)
|
||||
|
||||
req.addListener('data', function(chunk) {
|
||||
buffer = buffer + chunk;
|
||||
});
|
||||
|
||||
req.addListener('end', function() {
|
||||
handle(buffer);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// handleNonPOST
|
||||
//===----------------------------------------------------------------------===//
|
||||
Server.handleNonPOST = function(req, res) {
|
||||
res.writeHead(405, {'Content-Type': 'text/plain',
|
||||
'Content-Length': METHOD_NOT_ALLOWED.length,
|
||||
'Allow': 'POST'});
|
||||
res.write(METHOD_NOT_ALLOWED);
|
||||
res.end();
|
||||
}
|
||||
|
||||
|
||||
module.exports.Server = Server;
|
||||
module.exports.Client = Client;
|
||||
module.exports.Client = Client
|
||||
|
||||
36
package.json
36
package.json
@ -1,28 +1,40 @@
|
||||
{
|
||||
"name": "bitcoin",
|
||||
"name": "@mempool/bitcoin",
|
||||
"description": "Communicate with bitcoind via JSON-RPC",
|
||||
"version": "1.2.1",
|
||||
"main": "./lib/bitcoin",
|
||||
"version": "3.0.3",
|
||||
"main": "lib/index.js",
|
||||
"keywords": [
|
||||
"bitcoin",
|
||||
"rpc"
|
||||
],
|
||||
"author": "Bill Casarin <bill@casarin.ca> (jb55.com)",
|
||||
"dependencies": {
|
||||
"underscore": "1.3.x"
|
||||
"contributors": [
|
||||
"Sean Lavine <sean@eternalrise.com>"
|
||||
],
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"clone": "^1.0.2",
|
||||
"mocha": "^2.3.3",
|
||||
"standard": "^5.3.1"
|
||||
},
|
||||
"optionalDependencies": {},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/jb55/node-bitcoin.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vows": "0.6.x"
|
||||
"url": "git://github.com/mempool/node-bitcoin.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.2.6"
|
||||
"node": ">= 0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"pretest": "standard --verbose",
|
||||
"test": "make test"
|
||||
},
|
||||
"optionalDependencies": {}
|
||||
}
|
||||
"bugs": {
|
||||
"url": "https://github.com/mempool/node-bitcoin/issues"
|
||||
},
|
||||
"homepage": "https://github.com/mempool/node-bitcoin#readme",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"license": "Unlicense"
|
||||
}
|
||||
|
||||
14
test.js
14
test.js
@ -1,14 +0,0 @@
|
||||
|
||||
var bitcoin = require('./lib/bitcoin');
|
||||
var client = new bitcoin.Client('localhost', 8332, 'jb55', 'thisisthepassword');
|
||||
|
||||
function doCmd(cmd) {
|
||||
client[cmd](function(err, data) {
|
||||
console.log(cmd);
|
||||
console.log(data);
|
||||
console.log("err: ", err);
|
||||
console.log('');
|
||||
});
|
||||
}
|
||||
|
||||
doCmd('getWork');
|
||||
178
test/api.js
178
test/api.js
@ -1,178 +0,0 @@
|
||||
var path = require('path');
|
||||
|
||||
// test variables
|
||||
|
||||
var test = {
|
||||
account: 'test'
|
||||
};
|
||||
|
||||
var config = require('./config');
|
||||
|
||||
// end test variables
|
||||
|
||||
var vows = require('vows'),
|
||||
assert = require('assert');
|
||||
|
||||
var bitcoin = require('../lib/bitcoin');
|
||||
|
||||
function makeClient() {
|
||||
return new bitcoin.Client(config.host, config.port, config.user, config.pass);
|
||||
}
|
||||
|
||||
function notEmpty(data) {
|
||||
if (data === 0)
|
||||
return;
|
||||
assert.ok(data);
|
||||
}
|
||||
|
||||
vows.describe('api').addBatch({
|
||||
'': {
|
||||
topic: makeClient,
|
||||
'an account address': {
|
||||
topic: function(client){
|
||||
client.getAccountAddress(test.account, this.callback);
|
||||
},
|
||||
'is valid': function(address){
|
||||
assert.ok(address);
|
||||
},
|
||||
'after getting the account name again': {
|
||||
topic: function(address, client) {
|
||||
client.getAccount(address, this.callback);
|
||||
},
|
||||
'should be the same as the original': function(account) {
|
||||
assert.equal(account, test.account);
|
||||
}
|
||||
},
|
||||
},
|
||||
'listTransactions with specific amount': {
|
||||
topic: function(client){
|
||||
client.listTransactions(test.account, 15, this.callback);
|
||||
},
|
||||
'should not be empty': function(txs){ assert.ok(txs); },
|
||||
'is an array': function(txs) { assert.isTrue(txs instanceof Array); }
|
||||
},
|
||||
'listTransactions without specific amount': {
|
||||
topic: function(client){
|
||||
client.listTransactions(test.account, this.callback);
|
||||
},
|
||||
'should not be empty': function(txs){ assert.ok(txs); },
|
||||
'is an array': function(txs) { assert.isTrue(txs instanceof Array); }
|
||||
},
|
||||
'account addresses': {
|
||||
topic: function(client){
|
||||
client.getAddressesByAccount(test.account, this.callback);
|
||||
},
|
||||
'is not empty': function(addresses) {
|
||||
assert.isTrue(addresses && addresses.length > 0);
|
||||
}
|
||||
},
|
||||
'getDifficulty': {
|
||||
topic: function(client) { client.getDifficulty(this.callback); },
|
||||
'should not be empty': notEmpty,
|
||||
'is a number': function (data) {
|
||||
assert.isNumber(data);
|
||||
},
|
||||
'is greater than 0': function (data) { assert.isTrue(data > 0); }
|
||||
},
|
||||
'getInfo': {
|
||||
topic: function(client) { client.getInfo(this.callback); },
|
||||
'should not be empty': notEmpty,
|
||||
'info.errors should be empty': function (info) {
|
||||
assert.isEmpty(info.errors);
|
||||
},
|
||||
},
|
||||
'getHashesPerSec': {
|
||||
topic: function(client) { client.getHashesPerSec(this.callback); },
|
||||
'should not be empty': notEmpty,
|
||||
'is a number': function (data) { assert.isNumber(data) },
|
||||
},
|
||||
'help': {
|
||||
topic: function(client) { client.help(this.callback); },
|
||||
'should not be empty': notEmpty,
|
||||
},
|
||||
'getWork': {
|
||||
topic: function(client) { client.getWork(this.callback); },
|
||||
'should not be empty': notEmpty,
|
||||
},
|
||||
'getTransaction': {
|
||||
topic: "TODO: get valid transaction",
|
||||
'should not be empty': notEmpty,
|
||||
},
|
||||
'client creation with single object': {
|
||||
topic: function(client){
|
||||
var client2 = new bitcoin.Client(config);
|
||||
var self = this;
|
||||
client2.getWork(function(err, work) {
|
||||
self.callback(err, work, client2, client);
|
||||
});
|
||||
},
|
||||
'should have same params': function(err, work, client2, client) {
|
||||
assert.isNull(err);
|
||||
assert.equal(client2.host, client.host);
|
||||
assert.equal(client2.port, client.port);
|
||||
assert.equal(client2.user, client.user);
|
||||
assert.equal(client2.pass, client.pass);
|
||||
},
|
||||
'getWork should be an object': function(work) {
|
||||
assert.isObject(work);
|
||||
}
|
||||
},
|
||||
'getblocknumber is deprecated': {
|
||||
topic: function(client) {
|
||||
client.cmd('getblocknumber', this.callback);
|
||||
},
|
||||
'and has been replaced by getblockcount': {
|
||||
topic: function(number, client) {
|
||||
client.cmd('getblockcount', this.callback);
|
||||
},
|
||||
'getBlockNumber uses getblockcount': {
|
||||
topic: function(count, number, client) {
|
||||
var self = this;
|
||||
client.getBlockNumber(function(err, number2) {
|
||||
self.callback(err, number2, count, number);
|
||||
});
|
||||
},
|
||||
'and should match both': function(err, number2, count, number) {
|
||||
assert.equal(number2, count);
|
||||
assert.equal(number2, number);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'creating a bitcoin related error': {
|
||||
topic: function(client) {
|
||||
client.cmd('nomethod', this.callback);
|
||||
},
|
||||
'should pass Error object in callback': function(err, expectedValue) {
|
||||
assert.instanceOf(err, Error);
|
||||
assert.equal(err.message, 'Method not found');
|
||||
assert.equal(err.code, -32601);
|
||||
assert.equal(expectedValue, undefined);
|
||||
},
|
||||
},
|
||||
},
|
||||
'invalid credentials': {
|
||||
topic: function() {
|
||||
return new bitcoin.Client(config.host, config.port, 'baduser', 'badpwd');
|
||||
},
|
||||
'should still return client object': function(client) {
|
||||
assert.equal(typeof client, 'object');
|
||||
assert.equal(client.host, config.host);
|
||||
assert.equal(client.port, config.port);
|
||||
assert.equal(client.user, 'baduser');
|
||||
assert.equal(client.pass, 'badpwd');
|
||||
},
|
||||
'will return status 401 with html': {
|
||||
topic: function(client) {
|
||||
client.getDifficulty(this.callback);
|
||||
},
|
||||
'and should be able to handle it': function(err, difficulty) {
|
||||
assert.instanceOf(err, Error);
|
||||
assert.equal(err.message, 'Invalid params, response status code: 401');
|
||||
assert.equal(err.code, -32602);
|
||||
assert.equal(difficulty, undefined);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
}).export(module);
|
||||
@ -1,6 +1,6 @@
|
||||
module.exports = {
|
||||
host: 'localhost',
|
||||
port: 8332,
|
||||
port: 19001,
|
||||
user: 'admin1',
|
||||
pass: '123'
|
||||
};
|
||||
292
test/index.js
Normal file
292
test/index.js
Normal file
@ -0,0 +1,292 @@
|
||||
/* global describe, it */
|
||||
|
||||
var assert = require('assert')
|
||||
var clone = require('clone')
|
||||
var http = require('http')
|
||||
var bitcoin = require('../')
|
||||
var config = require('./config')
|
||||
|
||||
var test = {
|
||||
account: 'test'
|
||||
}
|
||||
|
||||
var makeClient = function makeClient () {
|
||||
return new bitcoin.Client(config)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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 () {
|
||||
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()
|
||||
})
|
||||
})
|
||||
|
||||
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('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('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('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('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('help()', function () {
|
||||
it('should return help', function (done) {
|
||||
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) {
|
||||
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()
|
||||
})
|
||||
})
|
||||
|
||||
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 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)
|
||||
|
||||
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()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
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
|
||||
})
|
||||
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()
|
||||
})
|
||||
})
|
||||
|
||||
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
|
||||
})
|
||||
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()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
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()
|
||||
})
|
||||
|
||||
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()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
75
test/missing-commands.js
Normal file
75
test/missing-commands.js
Normal file
@ -0,0 +1,75 @@
|
||||
/* 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 = []
|
||||
|
||||
// split up the command list by newlines
|
||||
var commandListLines = commandList.split('\n')
|
||||
var result
|
||||
for (var i in commandListLines) {
|
||||
result = commandRegex.exec(commandListLines[i])
|
||||
if (!result) continue
|
||||
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)
|
||||
|
||||
for (var i in helpCommands) {
|
||||
var found = false
|
||||
for (var j in commands) {
|
||||
if (commands[j] === helpCommands[i]) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
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)
|
||||
|
||||
for (var i in commands) {
|
||||
var found = false
|
||||
for (var j in helpCommands) {
|
||||
if (commands[i] === helpCommands[j]) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// ignore commands not found in help because they are hidden
|
||||
// if the wallet isn't encrypted
|
||||
var ignore = ['walletlock', 'walletpassphrase', 'walletpassphrasechange']
|
||||
if (~ignore.indexOf(commands[i])) {
|
||||
assert.ok(!found, 'command found in `help`: ' + commands[i])
|
||||
} else {
|
||||
assert.ok(found, 'command not found in `help`: ' + commands[i])
|
||||
}
|
||||
}
|
||||
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
1
test/mocha.opts
Normal file
1
test/mocha.opts
Normal file
@ -0,0 +1 @@
|
||||
--reporter spec
|
||||
63
test/ssl.js
Normal file
63
test/ssl.js
Normal file
@ -0,0 +1,63 @@
|
||||
/* global describe, it */
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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()
|
||||
})
|
||||
})
|
||||
|
||||
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()
|
||||
})
|
||||
})
|
||||
|
||||
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()
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -1 +1 @@
|
||||
Subproject commit 4536d383493c3a20c58ecd3760b8303640833d7a
|
||||
Subproject commit 24f5214acfddfec498cca21dd96dac480e9b9013
|
||||
Loading…
Reference in New Issue
Block a user