bitcoin-client 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ module Bitcoin::Errors
2
+ class RPCError < StandardError
3
+ end
4
+ end
@@ -0,0 +1,35 @@
1
+ require 'json'
2
+
3
+ class Bitcoin::Request
4
+ attr_reader :service_name, :params
5
+
6
+ def initialize(service_name, params = [])
7
+ @service_name = service_name
8
+ @params = params.dup
9
+
10
+ # bitcoin rejects null values even for optional params. Since
11
+ # even params following those may have default non-nil values,
12
+ # we'll assume the first non-nil value marks a set of optional
13
+ # params, and drop it and everything following it.
14
+ #
15
+ # ex:
16
+ # [nil] => []
17
+ # [1,nil,nil] => [1]
18
+ # [1,nil,nil,1] => [1]
19
+ if index = @params.index(nil)
20
+ @params = @params[0...index]
21
+ end
22
+ end
23
+
24
+ def to_hash
25
+ {
26
+ :method => service_name,
27
+ :params => params,
28
+ :id => "jsonrpc"
29
+ }
30
+ end
31
+
32
+ def to_post_data
33
+ to_hash.to_json
34
+ end
35
+ end
@@ -0,0 +1,50 @@
1
+ require 'rest_client'
2
+
3
+ class Bitcoin::RPC
4
+ def initialize(options)
5
+ @user, @pass = options[:user], options[:pass]
6
+ @host, @port = options[:host], options[:port]
7
+ @ssl = options[:ssl]
8
+ end
9
+
10
+ def credentials
11
+ if @user
12
+ "#{@user}:#{@pass}"
13
+ else
14
+ nil
15
+ end
16
+ end
17
+
18
+ def service_url
19
+ url = @ssl ? "https://" : "http://"
20
+ url.concat "#{credentials}@" if c = credentials
21
+ url.concat "#{@host}:#{@port}"
22
+ url
23
+ end
24
+
25
+ def dispatch(request)
26
+ respdata = RestClient.post service_url, request.to_post_data
27
+ response = JSON.parse(respdata)
28
+ raise Bitcoin::Errors::RPCError, response['error'] if response['error']
29
+ response['result']
30
+ end
31
+
32
+ private
33
+ def symbolize_keys(hash)
34
+ case hash
35
+ when Hash
36
+ hash.inject({}) do |result, (key, value)|
37
+ key = key.to_sym if key.kind_of?(String)
38
+ value = symbolize_keys(value)
39
+ result[key] = value
40
+ result
41
+ end
42
+ when Array
43
+ hash.collect do |ele|
44
+ symbolize_keys(ele)
45
+ end
46
+ else
47
+ hash
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,12 @@
1
+ module Bitcoin
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ PATCH = 1
6
+ REL = nil
7
+
8
+ STRING = REL ? [MAJOR, MINOR, PATCH, REL].join('.') : [MAJOR, MINOR, PATCH].join('.')
9
+ end
10
+
11
+ VERSION = Version::STRING
12
+ end
@@ -0,0 +1,8 @@
1
+ HTTP/1.1 500 Internal Server Error
2
+ Date: Sun, 21 Aug 2011 22:53:05 +0000
3
+ Connection: close
4
+ Content-Length: 183
5
+ Content-Type: application/json
6
+ Server: bitcoin-json-rpc/0.3.24-beta
7
+
8
+ {"result":null,"error":{"code":-1,"message":"backupwallet <destination>\nSafely copies wallet.dat to destination, which can be a directory or a path with filename."},"id":"curltest"}
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yaml'
4
+ require 'json'
5
+
6
+ service_name = ARGV[0]
7
+ file_name = (ARGV[1] || service_name).dup
8
+ params = ARGV[2..-1].collect { |y| y == '_nil' ? nil : YAML::load(y) }
9
+
10
+ file_name << ".json" unless file_name =~ /\.json$/
11
+
12
+ data = { 'jsonrpc' => '1.0', 'id' => 'curltest', 'method' => service_name, 'params' => params }
13
+ command = "curl --user cm4:H2na-92D --data-binary '#{data.to_json}' -H 'content-type: text/plain;' http://127.0.0.1:8332/ -i"
14
+
15
+ puts command, nil
16
+ result = %x[#{command}]
17
+ puts result, nil
18
+ File.open(file_name, "w") { |f| f.print result }
19
+
@@ -0,0 +1,8 @@
1
+ HTTP/1.1 200 OK
2
+ Date: Mon, 22 Aug 2011 00:22:27 +0000
3
+ Connection: close
4
+ Content-Length: 51
5
+ Content-Type: application/json
6
+ Server: bitcoin-json-rpc/0.3.24-beta
7
+
8
+ {"result":0.00100000,"error":null,"id":"curltest"}
@@ -0,0 +1,8 @@
1
+ HTTP/1.1 200 OK
2
+ Date: Sun, 21 Aug 2011 22:01:17 +0000
3
+ Connection: close
4
+ Content-Length: 47
5
+ Content-Type: application/json
6
+ Server: bitcoin-json-rpc/0.3.24-beta
7
+
8
+ {"result":141972,"error":null,"id":"curltest"}
@@ -0,0 +1,8 @@
1
+ HTTP/1.1 200 OK
2
+ Date: Sun, 21 Aug 2011 22:02:32 +0000
3
+ Connection: close
4
+ Content-Length: 47
5
+ Content-Type: application/json
6
+ Server: bitcoin-json-rpc/0.3.24-beta
7
+
8
+ {"result":141972,"error":null,"id":"curltest"}
@@ -0,0 +1,8 @@
1
+ HTTP/1.1 200 OK
2
+ Date: Sun, 21 Aug 2011 22:21:22 +0000
3
+ Connection: close
4
+ Content-Length: 42
5
+ Content-Type: application/json
6
+ Server: bitcoin-json-rpc/0.3.24-beta
7
+
8
+ {"result":8,"error":null,"id":"curltest"}
@@ -0,0 +1,8 @@
1
+ HTTP/1.1 200 OK
2
+ Date: Sun, 21 Aug 2011 22:23:42 +0000
3
+ Connection: close
4
+ Content-Length: 57
5
+ Content-Type: application/json
6
+ Server: bitcoin-json-rpc/0.3.24-beta
7
+
8
+ {"result":1805700.83619367,"error":null,"id":"curltest"}
@@ -0,0 +1,8 @@
1
+ HTTP/1.1 200 OK
2
+ Date: Sun, 21 Aug 2011 22:24:10 +0000
3
+ Connection: close
4
+ Content-Length: 46
5
+ Content-Type: application/json
6
+ Server: bitcoin-json-rpc/0.3.24-beta
7
+
8
+ {"result":false,"error":null,"id":"curltest"}
@@ -0,0 +1,8 @@
1
+ HTTP/1.1 200 OK
2
+ Date: Sun, 21 Aug 2011 22:25:42 +0000
3
+ Connection: close
4
+ Content-Length: 42
5
+ Content-Type: application/json
6
+ Server: bitcoin-json-rpc/0.3.24-beta
7
+
8
+ {"result":0,"error":null,"id":"curltest"}
@@ -0,0 +1,8 @@
1
+ HTTP/1.1 200 OK
2
+ Date: Sun, 21 Aug 2011 20:24:03 +0000
3
+ Connection: close
4
+ Content-Length: 281
5
+ Content-Type: application/json
6
+ Server: bitcoin-json-rpc/0.3.24-beta
7
+
8
+ {"result":{"version":32400,"balance":0.00100000,"blocks":141957,"connections":8,"proxy":"","generate":false,"genproclimit":-1,"difficulty":1805700.83619367,"hashespersec":0,"testnet":false,"keypoololdest":1313766189,"paytxfee":0.00000000,"errors":""},"error":null,"id":"curltest"}
@@ -0,0 +1,8 @@
1
+ HTTP/1.1 200 OK
2
+ Date: Sun, 21 Aug 2011 23:20:10 +0000
3
+ Connection: close
4
+ Content-Length: 1078
5
+ Content-Type: application/json
6
+ Server: bitcoin-json-rpc/0.3.24-beta
7
+
8
+ {"result":"backupwallet <destination>\ngetaccount <bitcoinaddress>\ngetaccountaddress <account>\ngetaddressesbyaccount <account>\ngetbalance [account] [minconf=1]\ngetblockcount\ngetblocknumber\ngetconnectioncount\ngetdifficulty\ngetgenerate\ngethashespersec\ngetinfo\ngetnewaddress [account]\ngetreceivedbyaccount <account> [minconf=1]\ngetreceivedbyaddress <bitcoinaddress> [minconf=1]\ngettransaction <txid>\ngetwork [data]\nhelp [command]\nlistaccounts [minconf=1]\nlistreceivedbyaccount [minconf=1] [includeempty=false]\nlistreceivedbyaddress [minconf=1] [includeempty=false]\nlisttransactions [account] [count=10] [from=0]\nmove <fromaccount> <toaccount> <amount> [minconf=1] [comment]\nsendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\nsendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\nsendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\nsetaccount <bitcoinaddress> <account>\nsetgenerate <generate> [genproclimit]\nsettxfee <amount>\nstop\nvalidateaddress <bitcoinaddress>","error":null,"id":"curltest"}
@@ -0,0 +1,8 @@
1
+ HTTP/1.1 200 OK
2
+ Date: Sun, 21 Aug 2011 23:04:42 +0000
3
+ Connection: close
4
+ Content-Length: 155
5
+ Content-Type: application/json
6
+ Server: bitcoin-json-rpc/0.3.24-beta
7
+
8
+ {"result":[{"address":"1234","account":"","label":"","amount":0.00100000,"confirmations":180}],"error":null,"id":"curltest"}
@@ -0,0 +1,7 @@
1
+ HTTP/1.1 200 OK
2
+ Date: Sun, 21 Aug 2011 23:15:11 +0000
3
+ Connection: close
4
+ Content-Type: application/json
5
+ Server: bitcoin-json-rpc/0.3.24-beta
6
+
7
+ {"result":[{"address":"1234","account":"","label":"","amount":0.00100000,"confirmations":180}],"error":null,"id":"curltest"}
@@ -0,0 +1,7 @@
1
+ HTTP/1.1 200 OK
2
+ Date: Sun, 21 Aug 2011 22:54:36 +0000
3
+ Connection: close
4
+ Content-Type: application/json
5
+ Server: bitcoin-json-rpc/0.3.24-beta
6
+
7
+ {"result":[{"address":"1234","account":"","label":"","amount":0.00100000,"confirmations":180}],"error":null,"id":"curltest"}
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bitcoin::API do
4
+ subject { Bitcoin::API.new(:user => $user, :pass => $pass) }
5
+
6
+ it "should have default host, port, ssl" do
7
+ subject.host.should == 'localhost'
8
+ subject.port.should == 8332
9
+ subject.ssl?.should be_false
10
+ end
11
+
12
+ it "should accept host, port, ssl options" do
13
+ req = Bitcoin::API.new(:user => $user, :pass => $pass, :host => 'example.com', :port => 1234, :ssl => true)
14
+ req.host.should == 'example.com'
15
+ req.port.should == 1234
16
+ req.ssl?.should be_true
17
+ end
18
+
19
+ it "should build an options hash" do
20
+ subject.to_hash.should == {
21
+ :user => $user,
22
+ :pass => $pass,
23
+ :host => 'localhost',
24
+ :port => 8332,
25
+ :ssl => false,
26
+ }
27
+ end
28
+ end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bitcoin::Client do
4
+ subject { Bitcoin::Client.new($user, $pass) }
5
+
6
+ it "defaults" do
7
+ subject.user.should == $user
8
+ subject.pass.should == $pass
9
+ subject.host.should == 'localhost'
10
+ subject.port.should == 8332
11
+ subject.ssl?.should_not be_true
12
+ end
13
+
14
+ context "RPC" do
15
+ extend RPCServiceHelper
16
+
17
+ service 'getinfo' do
18
+ it "should produce the expected result" do
19
+ result.should == {
20
+ 'version' => 32400,
21
+ 'balance' => 0.001,
22
+ 'blocks' => 141957,
23
+ 'connections' => 8,
24
+ 'proxy' => "",
25
+ 'generate' => false,
26
+ 'genproclimit' => -1,
27
+ 'difficulty' => 1805700.83619367,
28
+ 'hashespersec' => 0,
29
+ 'testnet' => false,
30
+ 'keypoololdest' => 1313766189,
31
+ 'paytxfee' => 0.0,
32
+ 'errors' => ""
33
+ }
34
+ end
35
+ end
36
+
37
+ service 'getblockcount' do
38
+ it "should produce the expected result" do
39
+ result.should == 141972
40
+ end
41
+ end
42
+
43
+ service 'getblocknumber' do
44
+ it "should produce the expected result" do
45
+ result.should == 141972
46
+ end
47
+ end
48
+
49
+ service 'getconnectioncount' do
50
+ it "should produce the expected result" do
51
+ result.should == 8
52
+ end
53
+ end
54
+
55
+ service 'getdifficulty' do
56
+ it "should produce the expected result" do
57
+ result.should == 1805700.83619367
58
+ end
59
+ end
60
+
61
+ service 'getgenerate' do
62
+ it "should produce the expected result" do
63
+ result.should be_false
64
+ end
65
+ end
66
+
67
+ service 'gethashespersec' do
68
+ it "should produce the expected result" do
69
+ result.should == 0
70
+ end
71
+ end
72
+
73
+ service 'listreceivedbyaddress' do
74
+ context 'without params' do
75
+ it "should produce the expected result" do
76
+ result.should == [{
77
+ 'address' => "1234",
78
+ 'account' => "",
79
+ 'label' => "",
80
+ 'amount' => 0.001,
81
+ 'confirmations' => 180}]
82
+ end
83
+ end
84
+
85
+ context 'with minconf 0' do
86
+ it "should produce the expected result" do
87
+ result(0).should == [{
88
+ 'address' => "1234",
89
+ 'account' => "",
90
+ 'label' => "",
91
+ 'amount' => 0.001,
92
+ 'confirmations' => 180}]
93
+ end
94
+ end
95
+
96
+ context 'with minconf 0 and includeempty true' do
97
+ it "should produce the expected result" do
98
+ result(0, true).should == [{
99
+ 'address' => "1234",
100
+ 'account' => "",
101
+ 'label' => "",
102
+ 'amount' => 0.001,
103
+ 'confirmations' => 180}]
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bitcoin::Request do
4
+ it "should omit null arguments and everything after them" do
5
+ # bitcoin rejects null values even for optional params. Since
6
+ # even params following those may have default non-nil values,
7
+ # we'll assume the first non-nil value marks a set of optional
8
+ # params, and drop it and everything following it.
9
+
10
+ req = Bitcoin::Request.new('svc', [1, nil, nil, nil])
11
+ req.params.should == [1]
12
+
13
+ req = Bitcoin::Request.new('svc', [nil])
14
+ req.params.should == []
15
+
16
+ req = Bitcoin::Request.new('svc', [1, nil, nil, 1, nil])
17
+ req.params.should == [1]
18
+ end
19
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bitcoin do
4
+ before :each do
5
+ FakeWeb.register_uri(:post, "http://user:pass@localhost:8332", :response => fixture('getbalance'))
6
+ end
7
+
8
+ it "as a function" do
9
+ cli = Bitcoin($user, $pass)
10
+ cli.balance.should == 0.001
11
+ end
12
+
13
+ it "DSL, included" do
14
+ class << self
15
+ include Bitcoin
16
+ end
17
+
18
+ username $user
19
+ password $pass
20
+
21
+ balance.should == 0.001
22
+ end
23
+
24
+ it "DSL, extended" do
25
+ class << self
26
+ include Bitcoin
27
+
28
+ username $user
29
+ password $pass
30
+
31
+ balance.should == 0.001
32
+ end
33
+ end
34
+ end