ramontayag-bitcoin-client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.gitignore +4 -0
  2. data/.travis.yml +8 -0
  3. data/Gemfile +13 -0
  4. data/README.rdoc +88 -0
  5. data/Rakefile +8 -0
  6. data/bitcoind-client.gemspec +28 -0
  7. data/lib/bitcoin-client.rb +1 -0
  8. data/lib/bitcoin.rb +19 -0
  9. data/lib/bitcoin/api.rb +33 -0
  10. data/lib/bitcoin/client.rb +244 -0
  11. data/lib/bitcoin/dsl.rb +259 -0
  12. data/lib/bitcoin/errors.rb +4 -0
  13. data/lib/bitcoin/request.rb +35 -0
  14. data/lib/bitcoin/rpc.rb +50 -0
  15. data/lib/bitcoin/version.rb +12 -0
  16. data/spec/fixtures/backupwallet_without_params.json +8 -0
  17. data/spec/fixtures/build_fixture.rb +19 -0
  18. data/spec/fixtures/getbalance.json +8 -0
  19. data/spec/fixtures/getblockcount.json +8 -0
  20. data/spec/fixtures/getblocknumber.json +8 -0
  21. data/spec/fixtures/getconnectioncount.json +8 -0
  22. data/spec/fixtures/getdifficulty.json +8 -0
  23. data/spec/fixtures/getgenerate.json +8 -0
  24. data/spec/fixtures/gethashespersec.json +8 -0
  25. data/spec/fixtures/getinfo.json +8 -0
  26. data/spec/fixtures/help.json +8 -0
  27. data/spec/fixtures/listreceivedbyaddress_with_minconf_0.json +8 -0
  28. data/spec/fixtures/listreceivedbyaddress_with_minconf_0_and_includeempty_true.json +7 -0
  29. data/spec/fixtures/listreceivedbyaddress_without_params.json +7 -0
  30. data/spec/fixtures/signmessage_invalid_address.json +8 -0
  31. data/spec/fixtures/signmessage_success.json +8 -0
  32. data/spec/fixtures/verifymessage_failure.json +8 -0
  33. data/spec/fixtures/verifymessage_success.json +8 -0
  34. data/spec/lib/bitcoin/api_spec.rb +28 -0
  35. data/spec/lib/bitcoin/client_spec.rb +137 -0
  36. data/spec/lib/bitcoin/request_spec.rb +19 -0
  37. data/spec/lib/bitcoin_spec.rb +34 -0
  38. data/spec/spec_helper.rb +15 -0
  39. data/spec/support/fixtures_helper.rb +5 -0
  40. data/spec/support/rpc_service_helper.rb +34 -0
  41. metadata +182 -0
@@ -0,0 +1,259 @@
1
+ module Bitcoin::DSL
2
+ def bitcoin
3
+ if self.class.respond_to?(:bitcoin)
4
+ @client ||= Bitcoin::Client.new(self.class.bitcoin.user, self.class.bitcoin.pass, self.class.bitcoin.options)
5
+ else
6
+ @client ||= Bitcoin::Client.new(nil, nil)
7
+ end
8
+ end
9
+
10
+ def username=(value)
11
+ bitcoin.user = value
12
+ end
13
+
14
+ def password=(value)
15
+ bitcoin.pass = value
16
+ end
17
+
18
+ def host=(value)
19
+ bitcoin.host = value
20
+ end
21
+
22
+ def port=(value)
23
+ bitcoin.port = value
24
+ end
25
+
26
+ def ssl=(value)
27
+ bitcoin.ssl = value
28
+ end
29
+
30
+ def username(value = nil)
31
+ value ? bitcoin.user = value : bitcoin.user
32
+ end
33
+
34
+ def password(value = nil)
35
+ value ? bitcoin.pass = value : bitcoin.pass
36
+ end
37
+
38
+ def host(value = nil)
39
+ value ? bitcoin.host = value : bitcoin.host
40
+ end
41
+
42
+ def port(value = nil)
43
+ value ? bitcoin.port = value : bitcoin.port
44
+ end
45
+
46
+ def ssl(value = nil)
47
+ value.nil? ? bitcoin.ssl : bitcoin.ssl = value
48
+ end
49
+
50
+ def ssl?
51
+ bitcoin.ssl?
52
+ end
53
+
54
+
55
+ # Safely copies wallet.dat to destination, which can be a directory or a path with filename.
56
+ def backupwallet(destination)
57
+ bitcoin.backupwallet destination
58
+ end
59
+
60
+ # Returns the account associated with the given address.
61
+ def getaccount(bitcoinaddress)
62
+ bitcoin.getaccount bitcoinaddress
63
+ end
64
+
65
+ # Returns the current bitcoin address for receiving payments to this account.
66
+ def getaccountaddress(account)
67
+ bitcoin.getaccountaddress account
68
+ end
69
+
70
+ # Returns the list of addresses for the given account.
71
+ def getaddressesbyaccount(account)
72
+ bitcoin.getaddressesbyaccount account
73
+ end
74
+
75
+ # If +account+ is not specified, returns the server's total available balance.
76
+ # If +account+ is specified, returns the balance in the account.
77
+ def getbalance(account = nil, minconf = 1)
78
+ bitcoin.getbalance account, minconf
79
+ end
80
+
81
+ # Dumps the block existing at specified height.
82
+ # Note: this is not available in the official release
83
+ def getblockbycount(height)
84
+ bitcoin.getblockbycount height
85
+ end
86
+
87
+ # Returns the number of blocks in the longest block chain.
88
+ def getblockcount
89
+ bitcoin.getblockcount
90
+ end
91
+
92
+ # Returns the block number of the latest block in the longest block chain.
93
+ def getblocknumber
94
+ bitcoin.getblocknumber
95
+ end
96
+
97
+ # Returns the number of connections to other nodes.
98
+ def getconnectioncount
99
+ bitcoin.getconnectioncount
100
+ end
101
+
102
+ # Returns the proof-of-work difficulty as a multiple of the minimum difficulty.
103
+ def getdifficulty
104
+ bitcoin.getdifficulty
105
+ end
106
+
107
+ # Returns true or false whether bitcoind is currently generating hashes
108
+ def getgenerate
109
+ bitcoin.getgenerate
110
+ end
111
+
112
+ # Returns a recent hashes per second performance measurement while generating.
113
+ def gethashespersec
114
+ bitcoin.gethashespersec
115
+ end
116
+
117
+ # Returns an object containing various state info.
118
+ def getinfo
119
+ bitcoin.getinfo
120
+ end
121
+
122
+ # Returns a new bitcoin address for receiving payments. If +account+ is specified (recommended),
123
+ # it is added to the address book so payments received with the address will be credited to +account+.
124
+ def getnewaddress(account = nil)
125
+ bitcoin.getnewaddress account
126
+ end
127
+
128
+ # Returns the total amount received by addresses with +account+ in transactions
129
+ # with at least +minconf+ confirmations.
130
+ def getreceivedbyaccount(account, minconf = 1)
131
+ bitcoin.getreceivedbyaccount account, minconf
132
+ end
133
+
134
+ # Returns the total amount received by +bitcoinaddress+ in transactions with at least +minconf+ confirmations.
135
+ def getreceivedbyaddress(bitcoinaddress, minconf = 1)
136
+ bitcoin.getreceivedbyaddress bitcoinaddress, minconf
137
+ end
138
+
139
+ # Get detailed information about +txid+
140
+ def gettransaction(txid)
141
+ bitcoin.gettransaction txid
142
+ end
143
+
144
+ # If +data+ is not specified, returns formatted hash data to work on:
145
+ #
146
+ # :midstate => precomputed hash state after hashing the first half of the data
147
+ # :data => block data
148
+ # :hash1 => formatted hash buffer for second hash
149
+ # :target => little endian hash target
150
+ #
151
+ # If +data+ is specified, tries to solve the block and returns true if it was successful.
152
+ def getwork(data = nil)
153
+ bitcoin.getwork data
154
+ end
155
+
156
+ # List commands, or get help for a command.
157
+ def help(command = nil)
158
+ bitcoin.help command
159
+ end
160
+
161
+ # Returns Object that has account names as keys, account balances as values.
162
+ def listaccounts(minconf = 1)
163
+ bitcoin.listaccounts minconf
164
+ end
165
+
166
+ # Returns an array of objects containing:
167
+ #
168
+ # :account => the account of the receiving addresses
169
+ # :amount => total amount received by addresses with this account
170
+ # :confirmations => number of confirmations of the most recent transaction included
171
+ #
172
+ def listreceivedbyaccount(minconf = 1, includeempty = false)
173
+ bitcoin.listreceivedbyaccount minconf, includeempty
174
+ end
175
+
176
+ # Returns an array of objects containing:
177
+ #
178
+ # :address => receiving address
179
+ # :account => the account of the receiving address
180
+ # :amount => total amount received by the address
181
+ # :confirmations => number of confirmations of the most recent transaction included
182
+ #
183
+ # To get a list of accounts on the system, execute bitcoind listreceivedbyaddress 0 true
184
+ def listreceivedbyaddress(minconf = 1, includeempty = false)
185
+ bitcoin.listreceivedbyaddress minconf, includeempty
186
+ end
187
+
188
+ # Returns up to +count+ most recent transactions for account +account+.
189
+ def listtransactions(account, count = 10)
190
+ bitcoin.listtransactions account, count
191
+ end
192
+
193
+ # Move from one account in your wallet to another.
194
+ def move(fromaccount, toaccount, amount, minconf = 1, comment = nil)
195
+ bitcoin.move fromaccount, toaccount, amount, minconf, comment
196
+ end
197
+
198
+ # +amount+ is a real and is rounded to 8 decimal places. Returns the transaction ID if successful.
199
+ def sendfrom(fromaccount, tobitcoinaddress, amount, minconf = 1, comment = nil, comment_to = nil)
200
+ bitcoin.sendfrom fromaccount, tobitcoinaddress, amount, minconf, comment, comment_to
201
+ end
202
+
203
+ # +amount+ is a real and is rounded to 8 decimal places
204
+ def sendtoaddress(bitcoinaddress, amount, comment = nil, comment_to = nil)
205
+ bitcoin.sendtoaddress bitcoinaddress, amount, comment, comment_to
206
+ end
207
+
208
+ # Sets the account associated with the given address.
209
+ def setaccount(bitcoinaddress, account)
210
+ bitcoin.setaccount bitcoinaddress, account
211
+ end
212
+
213
+ # +generate+ is true or false to turn generation on or off.
214
+ # Generation is limited to +genproclimit+ processors, -1 is unlimited.
215
+ def setgenerate(generate, genproclimit = -1)
216
+ bitcoin.setgenerate generate, genproclimit
217
+ end
218
+
219
+ # Stop bitcoin server.
220
+ def stop
221
+ bitcoin.stop
222
+ end
223
+
224
+ # Return information about +bitcoinaddress+.
225
+ def validateaddress(bitcoinaddress)
226
+ bitcoin.validateaddress
227
+ end
228
+
229
+ alias account getaccount
230
+ alias account_address getaccountaddress
231
+ alias addresses_by_account getaddressesbyaccount
232
+ alias balance getbalance
233
+ alias block_by_count getblockbycount
234
+ alias block_count getblockcount
235
+ alias block_number getblocknumber
236
+ alias connection_count getconnectioncount
237
+ alias difficulty getdifficulty
238
+ alias generate? getgenerate
239
+ alias hashes_per_sec gethashespersec
240
+ alias info getinfo
241
+ alias new_address getnewaddress
242
+ alias received_by_account getreceivedbyaccount
243
+ alias received_by_address getreceivedbyaddress
244
+ alias transaction gettransaction
245
+ alias work getwork
246
+ alias get_work getwork
247
+ alias accounts listaccounts
248
+ alias list_received_by_account listreceivedbyaccount
249
+ alias list_received_by_address listreceivedbyaddress
250
+ alias transactions listtransactions
251
+ alias list_transactions listtransactions
252
+ alias send_from sendfrom
253
+ alias send_to_address sendtoaddress
254
+ alias account= setaccount
255
+ alias set_account setaccount
256
+ alias generate= setgenerate
257
+ alias set_generate setgenerate
258
+ alias validate_address validateaddress
259
+ end
@@ -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 = 1
5
+ PATCH = 0
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 LovleOdnu:NajOij6DriWokEjEinaw --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"}