bitcoin-client 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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