ramontayag-bitcoin-client 0.1.0

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.
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"}