Compare commits

..

167 Commits

Author SHA1 Message Date
softsimon
b6eaefd223
Adding new methods. 2021-07-13 18:40:05 +03:00
softsimon
c097b9c81e * adding new mempool methods
* promisify
2020-12-20 17:40:55 +07:00
Sean Lavine
cb6e5c811b
readme: update link to bitcoin-core 2018-05-13 13:35:57 -07:00
Sean Lavine
e969b3844f
readme: make unmaintained explicit 2018-05-13 13:35:11 -07:00
Sean Lavine
07d320d630 readme: new features in bitcoin-core 2016-03-19 17:48:52 -07:00
Sean Lavine
7b739e8eb9 readme: recommend bitcoin-core 2016-03-16 20:00:27 -07:00
Sean Lavine
e956310d43 3.0.1 2015-10-25 21:32:10 -07:00
Sean Lavine
b444d23f00 update changelog 2015-10-25 21:32:02 -07:00
Sean Lavine
fe1ab3fc52 coding style: standard 2015-10-25 21:26:44 -07:00
Sean Lavine
33d4ff9079 readme: add mention of bitcoin-promise module 2015-10-25 20:38:42 -07:00
Sean Lavine
b9a2a749d8 3.0.0 2015-10-18 21:15:53 -07:00
Sean Lavine
b136254de9 update changelog 2015-10-18 21:15:44 -07:00
Sean Lavine
bfedefd8c4 upgrade dev dependencies 2015-10-18 21:07:25 -07:00
Sean Lavine
12860e83de add public domain license
See jb55/node-bitcoin#4
2015-10-18 21:01:07 -07:00
Sean Lavine
2a067655c5 add bitcoind v0.11 command: generate 2015-10-18 20:51:26 -07:00
Sean Lavine
b93026db3a travis: specify node_js as language 2015-10-18 20:48:53 -07:00
Sean Lavine
1d76ea1e14 new command in bitcoind v0.11: verifyTxOutProof 2015-10-18 20:45:26 -07:00
Sean Lavine
16f07d9a7a gethashespersec removed in bitcoind v0.11 2015-10-18 20:43:10 -07:00
Sean Lavine
990d5c472a travis: use docker to run tests 2015-10-18 20:32:22 -07:00
Sean Lavine
41818121ae upgrade testnet-box 2015-10-18 20:15:23 -07:00
Sean Lavine
67e6545d88 2.4.0 2015-07-16 09:18:18 -07:00
Sean Lavine
43e1412066 prepare changelog for release 2015-07-16 09:18:13 -07:00
Sean Lavine
12d8fd898a update changelog 2015-07-12 09:44:26 -07:00
Sean Lavine
a245166a65 don't lazy-load http/https modules 2015-07-12 09:40:43 -07:00
Sean Lavine
d25098240b add command getTxOutProof 2015-07-12 09:39:50 -07:00
Sean Lavine
0ef43d8555 clean up Dockerfile 2015-06-26 17:51:29 -07:00
Sean Lavine
a83c454525 2.3.2 2015-06-26 14:41:55 -07:00
Sean Lavine
bd63966e43 update changelog 2015-06-26 14:27:16 -07:00
Sean Lavine
6973183179 add Dockerfile for running tests 2015-06-26 14:26:50 -07:00
Sean Lavine
4328a49b63 add missing commands 2015-06-26 14:26:36 -07:00
Sean Lavine
2e56677ab9 fix missing cmds not being found in tests 2015-06-26 14:12:56 -07:00
Sean Lavine
69393ae38c 2.3.1 2015-06-24 08:56:35 -07:00
Sean Lavine
4e0851d859 update changelog 2015-06-24 08:56:29 -07:00
Sean Lavine
4f47030c53 Merge pull request #27 from challengerdeep/mempoolinfo
Add getmempoolinfo command
2015-06-24 08:53:42 -07:00
Vincent de Lagabbe
2e4c46cc41 Add getmempoolinfo command
added in bitcoind v0.10
2015-06-24 14:57:49 +02:00
Sean Lavine
00047173d5 travis: add node v0.12 and iojs 2015-03-24 18:39:50 -07:00
Sean Lavine
cb95f56e9c skip non-cmd lines in help output 2015-03-24 18:39:50 -07:00
Sean Lavine
bb8d05e556 remove test for getWork()
This was removed in bitcoind v0.10.0
2015-03-24 18:39:49 -07:00
Sean Lavine
b2900f01b9 2.3.0 2015-02-04 11:11:29 -08:00
Sean Lavine
75c204c109 changelog: v2.3.0 2015-02-04 11:11:12 -08:00
Sean Lavine
fff3333c6c travis: remove node v0.11 testing 2015-02-04 11:06:04 -08:00
Sean Lavine
ce29b1d74e update changelog 2015-02-04 11:04:23 -08:00
Sean Lavine
b9a3043de6 Merge pull request #24 from kaipila/master
Added support for new bitcoind v0.10.0 JSON-RPC calls
2015-02-04 10:58:41 -08:00
Antti Kaipila
c8e5a1dda5 Update commands.js 2015-02-04 13:51:09 +02:00
Sean Lavine
3cbf41caad Merge pull request #23 from dcousens/patch-1
package: update mocha to 2.1.0
2015-01-20 21:26:50 -08:00
Daniel Cousens
db518ff059 package: update mocha to 2.1.0 2015-01-21 14:28:34 +11:00
Sean Lavine
af727e9f91 update changelog 2014-10-18 14:28:07 -07:00
Sean Lavine
5e7df878ce update testnet-box 2014-10-18 14:25:31 -07:00
Sean Lavine
ee52f9ef5a drop node v0.8.x support 2014-10-18 14:24:36 -07:00
Sean Lavine
15819275f5 update devDependencies 2014-10-18 14:09:58 -07:00
Sean Lavine
25aaeee5af readme: travis badge for master 2014-10-18 03:27:59 -07:00
Sean Lavine
b8aeff8750 update testnet-box 2014-10-18 03:27:59 -07:00
freewil
1aea9f2006 fix .travis.tml error 2014-08-29 13:41:43 -07:00
freewil
8d02a1e7e6 2.2.0 2014-08-29 13:30:17 -07:00
freewil
d716cf99ef changelog: v2.2.0 2014-08-29 13:30:11 -07:00
freewil
b75262f501 getBlockChainInfo -> getBlockchainInfo 2014-08-29 13:29:26 -07:00
freewil
03f16394db allow node.js v0.11 to fail 2014-08-29 13:23:49 -07:00
Sean Lavine
d9352f0cc5 Merge pull request #20 from devlo/master
Added some new RPC commands v0.9.0 - v0.9.3
2014-08-21 18:04:11 -07:00
devlo
654b4a675b Added some new RPC commands v0.9.0 - v0.9.3 2014-08-22 01:22:40 +02:00
freewil
cd6382afca 2.1.2 2014-04-16 23:45:14 -07:00
freewil
347df714c4 lazy load http/https module 2014-04-16 23:44:57 -07:00
Sean Lavine
66a132ccfb readme: move badge to header line
[ci skip]
2014-04-10 13:44:40 -07:00
freewil
0d5fb299af use new travis svg badge 2014-04-07 14:23:22 -07:00
freewil
1377f69351 fix ssl self-signed tests for node v0.11 2014-03-26 00:30:29 -07:00
freewil
a26112a640 2.1.1 2014-03-25 23:00:48 -07:00
freewil
c964c962c4 add v2.1.1 to changelog 2014-03-25 23:00:45 -07:00
freewil
4623696d6b increase default request timeout to 30000ms
bitcoind has been known to be slow to respond to requests
while processing blocks. Best to be safe and set this high.
2014-03-25 22:54:58 -07:00
freewil
1e5fae327d 2.1.0 2014-03-12 16:19:22 -07:00
freewil
af7cd16428 update changelog 2014-03-12 16:18:00 -07:00
freewil
8512417889 add node 0.11 for travis 2014-03-12 16:11:47 -07:00
freewil
4324d1c177 update readme and changelog with new features 2014-03-12 15:55:40 -07:00
freewil
491fc3576d add tests for response headers to callback 2014-03-12 15:20:19 -07:00
freewil
145cef5885 Merge branch 'patch-1' of https://github.com/shimondoodkin/node-bitcoin into shimondoodkin-patch-1 2014-03-12 14:43:22 -07:00
freewil
f68721c0ca remove unused deprecated commands module 2014-03-12 14:20:11 -07:00
Sean Lavine
7e578b43d7 Merge pull request #13 from freewil/timeout
add request timeout
2014-03-12 13:49:51 -07:00
freewil
5d83f0e43a add request timeout
fix GH-12
2014-03-12 13:37:20 -07:00
freewil
b490f03e1c add getBalance() test without any args
close GH-11
2014-03-09 00:22:58 -08:00
Shimon Doodkin
50825e3a11 callback with server headers for wallet coin name
client.rpc.call('getinfo', [], console.log,function(){});
result : {}, {server: 'nexuscoin-json-rpc/v0.8.6-12-g4d83b6e-dirty-beta'}
2014-01-23 10:52:31 +02:00
freewil
6b237fe61e 2.0.1 2014-01-08 16:09:46 -08:00
freewil
0fca45ecad update changelog 2014-01-08 16:09:40 -08:00
freewil
8f4f522b47 default host to 'localhost'; port to '8332'
fix GH-6
2014-01-08 16:06:34 -08:00
freewil
39c4ebb0b7 quick fix for bitcoind start/stop race condition 2013-10-14 21:12:55 -07:00
freewil
788ae6a41b 2.0.0 2013-10-14 16:59:36 -07:00
freewil
820d79adff add v2.0.0 to changelog 2013-10-14 16:59:20 -07:00
freewil
3b307a27d0 upgrade dev dependencies 2013-10-14 16:58:20 -07:00
freewil
6f44193d4b remove deprecated functionality
closes GH-4
2013-10-14 16:42:41 -07:00
freewil
e2f755d313 fix bitcoins capitalization in readme
[ci skip]
2013-05-13 12:49:25 -03:00
freewil
915742cd17 fix short circuit if line from help fails regex 2013-05-12 14:13:28 -04:00
freewil
8f1a886dc7 check commands against help more thoroughly 2013-05-06 01:46:43 -04:00
freewil
88457b5eed 1.7.0 2013-05-05 14:08:40 -04:00
freewil
70742c87e4 add v1.7.0 to changelog 2013-05-05 14:08:34 -04:00
freewil
2f05ad1107 deprecate getMemoryPool 2013-05-05 14:02:14 -04:00
freewil
13e1a46a86 reorganize directory structure by adding lib/ 2013-05-05 00:32:19 -04:00
freewil
596a828f07 add missing commands added in bitcoind v0.7.0 2013-05-05 00:28:03 -04:00
freewil
3c20e34d1a 1.6.2 2013-03-21 19:10:41 -04:00
freewil
03f124363c add v1.6.2 to changelog 2013-03-21 19:10:25 -04:00
freewil
7e14ede5ca add .npmignore 2013-03-21 19:05:59 -04:00
freewil
07edb0c4f5 pass bitcoin.Client options through to rpc.Client 2013-03-13 16:42:15 -04:00
freewil
0c1389612f 1.6.1 2013-03-13 09:54:02 -04:00
freewil
1c2aba3c20 add v1.6.1 to changelog
[ci skip]
2013-03-13 09:53:03 -04:00
freewil
76873d1743 rejectUnauthorized defaults to true in node v0.10 2013-03-13 09:46:10 -04:00
freewil
aec981d0fe flatten out directory structure 2013-03-13 00:50:06 -04:00
freewil
a91b3474e9 add node v0.10 to travis 2013-03-13 00:16:25 -04:00
freewil
2412d014d0 fix readme typos
[ci skip]
2013-03-08 15:56:40 -05:00
freewil
3619e6f038 1.6.0
[ci skip]
2013-03-08 15:29:53 -05:00
freewil
106b922e82 drop support for node v0.6.x 2013-03-08 15:24:27 -05:00
freewil
8daa9085b3 add v1.6.0 to changelog
[ci skip]
2013-03-08 09:23:31 -05:00
freewil
1ac9e7d201 add SSL support
closes #2
2013-03-08 08:53:08 -05:00
freewil
36417a5657 remove json-rpc server 2013-03-08 08:50:33 -05:00
freewil
beeee58631 reformat json-rpc client 2013-03-08 08:50:33 -05:00
freewil
7d8269bc6d upgrade testnet-box 2013-03-08 08:50:33 -05:00
freewil
0a19d625c5 update travis URIs in readme
[ci skip]
2013-03-07 05:54:59 -05:00
freewil
fb79db9b06 add new commands for bitcoind v0.8.0 2013-03-07 05:44:30 -05:00
freewil
d11e048188 upgrade testnet-box for bitcoind v0.8.0 2013-03-07 04:26:28 -05:00
freewil
e6ac2d313b change tests from vows to mocha
closes #3
2013-03-05 08:22:47 -05:00
freewil
bcd0afbdf5 remove setup section from readme 2013-03-04 18:36:20 -05:00
freewil
456477cedc ignore .project 2013-03-04 18:35:19 -05:00
freewil
a649d14852 add v1.5.0 to changelog 2012-11-26 03:26:25 -05:00
freewil
bf4c75cc0c 1.5.0 2012-10-22 16:15:24 -04:00
freewil
c989985b2c add rpc call batching 2012-10-18 14:38:15 -04:00
freewil
2127609f4c upgrade testnet-box 2012-10-18 04:11:56 -04:00
freewil
8b78279472 remove getBlockNumber() test 2012-09-09 23:24:22 -04:00
freewil
cb6c39dcf5 1.4.0 2012-09-09 23:21:37 -04:00
freewil
eb35da94d7 update changelog 2012-09-09 23:21:25 -04:00
freewil
f1c94aab43 remove deprecated getBlockNumber() 2012-09-09 23:17:39 -04:00
freewil
20a563f047 Merge pull request #1 from sebicas/master
Add New Bitcoin v0.7 API Methods
2012-09-09 20:11:26 -07:00
Sebastian Castro
d012b9b315 Adding New Bitcoin v0.7 API Methods: createrawtransaction, decoderawtransaction, getpeerinfo, getrawmempool, getrawtransaction, listunspent, sendrawtransaction, signrawtransaction 2012-09-05 14:13:25 -04:00
freewil
1aee0ec091 1.3.1 2012-08-19 18:36:09 -04:00
freewil
e9e9b9f4e5 update changelog; use secure travis link 2012-08-19 18:35:32 -04:00
freewil
f29440b2da remove underscore dependency 2012-08-19 18:30:48 -04:00
freewil
1077753fbf point to freewil/node-bitcoin repo 2012-07-30 06:36:54 -04:00
freewil
024e40dad8 Merge branch 'travis' 2012-07-30 06:33:07 -04:00
freewil
7940a86028 use present tense for v1.3.0 in changelog 2012-07-03 18:17:36 -04:00
freewil
24480cecec add v1.3.0 changelog entry 2012-07-03 15:26:00 -04:00
freewil
1cfefb82c7 1.3.0 2012-07-03 15:22:05 -04:00
freewil
c4be38158c don't use http.createClient; deprecated in 0.8.x 2012-07-03 15:21:08 -04:00
freewil
c28f78c983 add travis ci 2012-06-27 05:55:15 -04:00
freewil
1a2947d9aa make tests runnable "out of the box" 2012-05-15 16:00:59 -04:00
freewil
d7d4684918 remove unused test file 2012-05-15 15:58:38 -04:00
freewil
637bc2ee65 update testnet-box 2012-05-15 15:57:58 -04:00
freewil
292637c16e 1.2.2 2012-04-26 20:57:15 -04:00
freewil
ff2ea67a7f fix callback called twice for client/request
This fixes the errback being called twice when both a client and
request error occur on the same command call.
2012-04-26 20:57:00 -04:00
freewil
a8d6f646a7 1.2.1 2012-04-26 01:13:38 -04:00
freewil
0d123f7792 add missing getBlock command 2012-04-26 01:12:45 -04:00
freewil
e1f631ef26 1.2.0 2012-04-25 21:07:41 -04:00
freewil
c3e0747a70 update changelog for v1.2.0 2012-04-25 21:07:27 -04:00
freewil
6faf577332 use Error object for errors
Fixes GH-11
2012-04-25 21:03:53 -04:00
freewil
8f1ef895fa use testnet-box for tests 2012-04-25 20:22:28 -04:00
freewil
85e57b994a 1.1.6 2012-04-11 17:18:20 -04:00
freewil
3f5cbb7f89 add new commands for bitcoin v0.6.0 2012-04-11 17:17:59 -04:00
freewil
107bb99d44 fix client creation with object example
Fixes GH-10
2012-02-28 16:05:25 -05:00
freewil
7121708a5f 1.1.5 2012-02-25 12:45:25 -05:00
freewil
d7ab0c6e4d handle cases where bitcoin client returns html
Fixes GH-9
2012-02-25 12:44:58 -05:00
freewil
79ab65759a bitcoin errors should pass err object in callback 2012-02-23 01:02:34 -05:00
freewil
53d0381984 1.1.4 2012-02-22 23:32:46 -05:00
freewil
5b3233164c add test for getblocknumber deprecation 2012-02-22 23:28:54 -05:00
freewil
9d35fd5811 update dependencies 2012-02-22 23:27:11 -05:00
freewil
e7a941a2bc sys module was replaced with util 2012-02-22 23:26:09 -05:00
freewil
c09425b955 deprecate getBlockNumber 2012-02-20 00:46:44 -05:00
Bill Casarin
062443ec65 Fixed tests 2012-02-02 16:51:53 -05:00
Bill Casarin
61a9e28f98 Added documentation on client.cmd 2012-01-03 09:22:46 -05:00
freewil
ac6afe2d30 version 1.1.3 2011-11-19 18:32:38 -05:00
freewil
6a31d38099 Merge branch 'commands-0.5.0' 2011-11-19 18:27:26 -05:00
freewil
be85571e68 add additional alias for 'keypoolrefill' 2011-10-11 02:33:49 -04:00
freewil
7eeb7d343c add additonal alias for 2011-10-11 02:16:59 -04:00
freewil
498f184817 add four new commands in bitcoind v0.5.0rc1 2011-10-10 13:14:11 -04:00
freewil
f91e6d7cac updated examples 2011-10-09 14:05:41 -03:00
24 changed files with 1113 additions and 538 deletions

5
.gitignore vendored
View File

@ -1 +1,4 @@
node_modules
node_modules/
test/config.js
.project

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "test/testnet-box"]
path = test/testnet-box
url = https://github.com/freewil/bitcoin-testnet-box

6
.npmignore Normal file
View File

@ -0,0 +1,6 @@
node_modules/
test/
.project
.gitmodules
.travis.yml
Dockerfile

18
.travis.yml Normal file
View 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

144
Changelog.md Normal file
View File

@ -0,0 +1,144 @@
# 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
## v1.2.0 (2012/04/25)
* submodule testnet-box for running tests
* err objects should all now be an instance of Error
## v1.1.6 (2012/04/11)
* add commands for bitcoind v0.6.0
* `addMultiSigAddress` (only available in testnet)
* `dumpPrivKey`
* `getBlockHash`
* `getMiningInfo`
* `importPrivKey`

21
Dockerfile Normal file
View 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
View 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/>

44
Makefile Normal file
View File

@ -0,0 +1,44 @@
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 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:
$(MOCHA) --invert --grep SSL
run-test-ssl:
$(MOCHA) --grep SSL
clean:
$(MAKE) -C $(BOX) clean
.PHONY: test

View File

@ -1,40 +0,0 @@
# node-bitcoin
node-bitcoin is a simple wrapper for the Bitcoin client's JSON-RPC API.
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.
## Install
`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!
## Example
```js
var bitcoin = require('bitcoin');
var client = new bitcoin.Client('localhost', 8332, 'username', 'password');
client.getBalance(function(err, balance) {
if (err) return console.log(err);
console.log("Balance:", balance);
});
```

101
Readme.md Normal file
View File

@ -0,0 +1,101 @@
# 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.
## Install
`npm install bitcoin`
## Examples
### Create client
```js
// all config options are optional
var client = new bitcoin.Client({
host: 'localhost',
port: 8332,
user: 'username',
pass: 'password',
timeout: 30000
});
```
### Get balance across all accounts with minimum confirmations of 6
```js
client.getBalance('*', 6, function(err, balance, resHeaders) {
if (err) return console.log(err);
console.log('Balance:', balance);
});
```
### Getting the balance directly using `cmd`
```js
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')
});
```

View File

@ -1,112 +0,0 @@
var rpc = require('../jsonrpc')
, _ = require('underscore')._;
//===----------------------------------------------------------------------===//
// jsonrpc wrappers
//===----------------------------------------------------------------------===//
var bitcoinAPI = {
backupWallet: 'backupwallet',
encryptWallet: 'encryptwallet',
getAccount: 'getaccount',
getAccountAddress: 'getaccountaddress',
getAddressesByAccount: 'getaddressesbyaccount',
getBalance: 'getbalance',
getBlockCount: 'getblockcount',
getBlockNumber: 'getblocknumber',
getConnectionCount: 'getconnectioncount',
getDifficulty: 'getdifficulty',
getGenerate: 'getgenerate',
getHashesPerSecond: 'gethashespersec',
getHashesPerSec: 'gethashespersec',
getInfo: 'getinfo',
getNewAddress: 'getnewaddress',
getReceivedByAccount: 'getreceivedbyaccount',
getReceivedByAddress: 'getreceivedbyaddress',
getTransaction: 'gettransaction',
getWork: 'getwork',
help: 'help',
keypoolRefill: 'keypoolrefill',
listAccounts: 'listaccounts',
listReceivedByAccount: 'listreceivedbyaccount',
listReceivedByAddress: 'listreceivedbyaddress',
listTransactions: 'listtransactions',
move: 'move',
sendFrom: 'sendfrom',
sendMany: 'sendmany',
sendToAddress: 'sendtoaddress',
setAccount: 'setaccount',
setGenerate: 'setgenerate',
setTxFee: 'settxfee',
stop: 'stop',
validateAddress: 'validateaddress',
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;

View File

@ -1,2 +0,0 @@
module.exports.Client = require('./client');

92
lib/commands.js Normal file
View 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
View 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

View File

@ -1,247 +1,155 @@
var sys = require('sys');
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 decoded = JSON.parse(buffer);
if(decoded.hasOwnProperty('error') && decoded.error != null) {
if (errback)
errback(decoded.error)
} else if(decoded.hasOwnProperty('result')) {
if (callback)
callback(decoded.result);
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
}
else {
if (errback)
errback(decoded.error);
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) {
sys.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);
console.log(decoded);
// 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

View File

@ -1,27 +1,40 @@
{
"name": "bitcoin",
"name": "@mempool/bitcoin",
"description": "Communicate with bitcoind via JSON-RPC",
"version": "1.1.2",
"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.0.3"
"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": "*"
"url": "git://github.com/mempool/node-bitcoin.git"
},
"engines": {
"node": "*"
"node": ">= 0.10.0"
},
"scripts": {
"test": "node test/api.js"
}
}
"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"
}

14
test.js
View File

@ -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');

View File

@ -1,130 +0,0 @@
var path = require('path');
require.paths.unshift(path.join(__dirname, '..'));
// test variables
var test = {
account: "test"
};
var config = {
host: 'localhost',
port: 8332,
user: 'jb55',
pass: 'thisisthepassword'
};
// 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);
}
},
},
}).export(module);

6
test/config.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
host: 'localhost',
port: 19001,
user: 'admin1',
pass: '123'
};

292
test/index.js Normal file
View 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
View 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
View File

@ -0,0 +1 @@
--reporter spec

63
test/ssl.js Normal file
View 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
test/testnet-box Submodule

@ -0,0 +1 @@
Subproject commit 24f5214acfddfec498cca21dd96dac480e9b9013