bitcoind 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
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in bitcoind.gemspec
4
+ gemspec
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'test' do
5
+ watch(%r{lib/bitcoind/(.*)\.rb}) { |m| "test/#{m[1]}_test.rb" }
6
+ watch(%r{test/.*_test\.rb})
7
+ watch('lib/bitcoind.rb') { 'test' }
8
+ watch('test/test_helper.rb') { "test" }
9
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Bryce Kerley
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,63 @@
1
+ # Bitcoind
2
+
3
+ Automate your [Bitcoin](http://bitcoin.org/) transactions with this Ruby interface to the `bitcoind` JSON-RPC API.
4
+
5
+ ## Connecting
6
+
7
+ Before connecting, you will need to configure a username and password for `bitcoind`, and start
8
+ `bitcoind`. Once that's done:
9
+
10
+ client = Bitcoind.new 'username', 'password'
11
+ # => #<Bitcoind::Client "http://username:password@localhost:8332" >
12
+
13
+ ## Account Balances
14
+
15
+ You can get the balance of all addresses controlled by the client:
16
+
17
+ client.balance
18
+ # => 12.34
19
+
20
+ You can also get a hash of all accounts the client controls:
21
+
22
+ client.accounts
23
+ # => {"Your Address"=>#<Bitcoind::Account "Your Address" >, "eve-online ransoms"=>#<Bitcoind::Account "eve-online ransoms" >}
24
+
25
+ And of course each account has its own balance too:
26
+
27
+ ransom = client.accounts['eve-online ransoms']
28
+ # => #<Bitcoind::Account "eve-online ransoms" >
29
+ ransom.balance
30
+ # => 2.19
31
+
32
+ ## Transactions
33
+
34
+ You can get all the transactions in an account:
35
+
36
+ ransom.transactions
37
+ # => [#<Bitcoind::Transaction abadbabe123deadbeef 2.19 to eve-online ransoms at 2011-02-19 16:21:09 -0500>]
38
+
39
+ You can send money from an account too:
40
+
41
+ ransom.send_to 'destinationaddress', 2
42
+ # => #<Bitcoind::Account deadbeef888abadbeef UNCONFIRMED>
43
+
44
+ ## Making Accounts
45
+
46
+ Creating an account with an associated address is done through the accounts interface:
47
+
48
+ tiny_wings = client.accounts.new 'tiny wings ransoms'
49
+ # => #<Bitcoind::Account "tiny wings ransoms" >
50
+ tiny_wings.address
51
+ # => "1KV5khnHbbHF2nNQkk7Pe5nPndEj43U27r"
52
+
53
+ # Contributing
54
+
55
+ * [Fork the project on GitHub](https://github.com/bkerley/bitcoind)
56
+ * Write tests for your changes locally
57
+ * Make the tests pass by implementing the changes
58
+ * Push your changes to GitHub.
59
+ * Send a pull request.
60
+
61
+ # Copyright
62
+
63
+ Copyright (c) 2011 Bryce Kerley. See LICENSE.txt for further details.
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/*_test.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "bitcoind/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "bitcoind"
7
+ s.version = Bitcoind::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Bryce Kerley"]
10
+ s.email = ["bkerley@brycekerley.net"]
11
+ s.homepage = ""
12
+ s.summary = %q{Control the bitcoin nework client over JSON-RPC.}
13
+ s.description = %q{Automate your Bitcoin transactions with this Ruby interface to the bitcoind JSON-RPC API.}
14
+
15
+ s.rubyforge_project = "bitcoind"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency 'rest-client', ['~> 1.6.1']
23
+ s.add_dependency 'activesupport', ['~> 3.0.6']
24
+
25
+ s.add_development_dependency 'guard-test', ['~> 0.1.6']
26
+ s.add_development_dependency 'shoulda', ['~> 2.11.3']
27
+ s.add_development_dependency 'mocha', ['~> 0.9.12']
28
+ s.add_development_dependency 'bundler', ['~> 1.0.12']
29
+ end
@@ -0,0 +1,13 @@
1
+ require 'json'
2
+ require 'rest_client'
3
+ require 'active_support/memoizable'
4
+
5
+ %w{ client account account_hash transaction }.each do |f|
6
+ require File.join(File.dirname(__FILE__), 'bitcoind', f)
7
+ end
8
+
9
+ module Bitcoind
10
+ def self.new(user, pass)
11
+ return Client.new user, pass
12
+ end
13
+ end
@@ -0,0 +1,38 @@
1
+ module Bitcoind
2
+ class Account
3
+ extend ActiveSupport::Memoizable
4
+ attr_accessor :name, :balance
5
+
6
+ def initialize(client, name)
7
+ @client = client
8
+ self.name = name
9
+ end
10
+
11
+ def inspect
12
+ "#<Bitcoind::Account #{self.name.inspect} >"
13
+ end
14
+
15
+ def send_to(destination, amount)
16
+ txn_id = @client.request 'sendfrom', self.name, destination, amount
17
+ Transaction.new @clientm, self, txn_id
18
+ end
19
+
20
+ def balance
21
+ @client.request 'getbalance', self.name
22
+ end
23
+ memoize :balance
24
+
25
+ def address
26
+ @client.request 'getaccountaddress', self.name
27
+ end
28
+ memoize :address
29
+
30
+ def transactions
31
+ txn_array = @client.request 'listtransactions', self.name
32
+
33
+ txn_array.map do |h|
34
+ Transaction.new @client, self, h['txid']
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,18 @@
1
+ module Bitcoind
2
+ class AccountHash < Hash
3
+ def initialize(client, balance_hash)
4
+ @client = client
5
+ balance_hash.each do |name,b|
6
+ self[name] = Account.new client, name
7
+ end
8
+ end
9
+
10
+ def new(name)
11
+ addr = @client.request 'getnewaddress', name
12
+
13
+ self[name] = Account.new @client, name
14
+
15
+ self[name]
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,28 @@
1
+ module Bitcoind
2
+ class Client
3
+ def initialize(user, pass)
4
+ @endpoint = "http://#{user}:#{pass}@localhost:8332"
5
+ end
6
+
7
+ def balance
8
+ request 'getbalance'
9
+ end
10
+
11
+ def accounts
12
+ balance_hash = request 'listaccounts'
13
+ AccountHash.new self, balance_hash
14
+ end
15
+
16
+ def request(method, *args)
17
+ body = { 'id'=>'jsonrpc', 'method'=>method}
18
+ body['params'] = args unless args.empty?
19
+ response_json = RestClient.post @endpoint, body.to_json
20
+ response = JSON.parse response_json
21
+ return response['result']
22
+ end
23
+
24
+ def inspect
25
+ "#<Bitcoind::Client #{@endpoint.inspect} >"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,39 @@
1
+ module Bitcoind
2
+ class Transaction
3
+ extend ActiveSupport::Memoizable
4
+ attr_accessor :id, :account
5
+ def initialize(client, account, id)
6
+ @client = client
7
+ self.account = account
8
+ self.id = id
9
+ end
10
+
11
+ def detail_hash
12
+ @client.request 'gettransaction', self.id
13
+ end
14
+ memoize :detail_hash
15
+
16
+ def inspect
17
+ "#<Bitcoind::Transaction #{id} #{amount} to #{account.name} at #{time}>"
18
+ rescue RestClient::InternalServerError
19
+ "#<Bitcoind::Transaction #{id} UNCONFIRMED>"
20
+ end
21
+
22
+ def amount
23
+ detail_hash['amount']
24
+ end
25
+
26
+ def confirmations
27
+ detail_hash['confirmations'] rescue 0
28
+ end
29
+
30
+ def time
31
+ Time.at detail_hash['time']
32
+ end
33
+ memoize :time
34
+
35
+ def confirmed?
36
+ confirmations > 6
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ module Bitcoind
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,27 @@
1
+ require 'helper'
2
+
3
+ class AccountHashTest < Test::Unit::TestCase
4
+ context 'an AccountHash' do
5
+ setup do
6
+ @client = stub
7
+ @ach = Bitcoind::AccountHash.new @client, ""=>0.0, "pi"=>3.14, "benjamin"=>100.0
8
+ end
9
+
10
+ should 'access accounts like a normal hash' do
11
+ assert_equal 'pi', @ach['pi'].name
12
+ assert_equal 'benjamin', @ach['benjamin'].name
13
+ end
14
+
15
+ context 'new method' do
16
+ should 'make a new account with a given name' do
17
+ @client.expects(:request).
18
+ once.
19
+ with('getnewaddress', 'new test account').
20
+ returns('xxxnewtestaddress')
21
+
22
+ @act = @ach.new 'new test account'
23
+ assert_equal 'new test account', @act.name
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,95 @@
1
+ require 'helper'
2
+
3
+ class AccountTest < Test::Unit::TestCase
4
+ context 'an Account' do
5
+ setup do
6
+ @client = stub
7
+ @acc = Bitcoind::Account.new @client, 'pi'
8
+ end
9
+
10
+ should 'have name' do
11
+ assert_equal 'pi', @acc.name
12
+ end
13
+
14
+ should 'have a short but useful inspect' do
15
+ assert_equal "#<Bitcoind::Account \"pi\" >", @acc.inspect
16
+ end
17
+
18
+ should 'ask the client for a balance' do
19
+ @client.expects(:request).
20
+ once.
21
+ with('getbalance', 'pi').
22
+ returns(3.14)
23
+
24
+ @balance = @acc.balance
25
+
26
+ assert_equal 3.14, @balance
27
+ end
28
+
29
+ should 'ask the client for an address' do
30
+ @client.expects(:request).
31
+ once.
32
+ with('getaccountaddress', 'pi').
33
+ returns('testaddress')
34
+
35
+ @address = @acc.address
36
+
37
+ assert_equal 'testaddress', @address
38
+ end
39
+
40
+ should 'have a list of transactions' do
41
+ @client.expects(:request).
42
+ once.
43
+ with('listtransactions', 'pi').
44
+ returns [
45
+ {
46
+ 'account'=>'pi',
47
+ 'address'=>'testaddress',
48
+ 'category'=>'receive',
49
+ 'amount'=>3.10,
50
+ 'confirmations'=>310,
51
+ 'txid'=>'310',
52
+ 'time'=>1234567310
53
+ },
54
+ {
55
+ 'account'=>'pi',
56
+ 'address'=>'testaddress',
57
+ 'category'=>'receive',
58
+ 'amount'=>3.11,
59
+ 'confirmations'=>311,
60
+ 'txid'=>'311',
61
+ 'time'=>1234567311
62
+ },
63
+ {
64
+ 'account'=>'pi',
65
+ 'address'=>'testaddress',
66
+ 'category'=>'receive',
67
+ 'amount'=>3.12,
68
+ 'confirmations'=>312,
69
+ 'txid'=>'312',
70
+ 'time'=>1234567312
71
+ },
72
+ ]
73
+
74
+ @txns = @acc.transactions
75
+
76
+ @txns.each do |t|
77
+ assert_kind_of Bitcoind::Transaction, t
78
+ end
79
+ assert_equal ['310', '311', '312'], @txns.map(&:id)
80
+ end
81
+
82
+ context 'transactions' do
83
+ should 'send money' do
84
+ @client.expects(:request).
85
+ once.
86
+ with('sendfrom', @acc.name, 'testdestinationaddress', 5).
87
+ returns('sentmoneytransactionid')
88
+
89
+ @txn = @acc.send_to('testdestinationaddress', 5)
90
+
91
+ assert_equal 'sentmoneytransactionid', @txn.id
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,51 @@
1
+ require 'helper'
2
+
3
+ class ClientTest < Test::Unit::TestCase
4
+ context 'a Bitcoind client' do
5
+ setup do
6
+ @bcd = Bitcoind.new 'testuser', 'testpass'
7
+ end
8
+
9
+ should 'have a simple and useful inspect' do
10
+ assert_equal "#<Bitcoind::Client \"http://testuser:testpass@localhost:8332\" >", @bcd.inspect
11
+ end
12
+
13
+ context 'balance operation' do
14
+ setup do
15
+ RestClient.expects(:post).
16
+ returns("{\"result\":12.34000000,\"error\":null,\"id\":\"jsonrpc\"}\n").
17
+ with do |e, a|
18
+ e == 'http://testuser:testpass@localhost:8332' &&
19
+ JSON.parse(a) == {'method'=>'getbalance', 'id'=>'jsonrpc'}
20
+ end
21
+ end
22
+
23
+ should 'get the balance' do
24
+ @result = @bcd.balance
25
+ assert_equal 12.34, @result
26
+ end
27
+ end
28
+
29
+ context 'accounts operation' do
30
+ setup do
31
+ RestClient.expects(:post).
32
+ returns("{\"result\":{\"\":0.0,\"Your Address\":0.0,\"pi\":3.14,\"ben\":100.00},\"error\":null,\"id\":\"jsonrpc\"}\n").
33
+ with do |e, a|
34
+ e == 'http://testuser:testpass@localhost:8332' &&
35
+ JSON.parse(a) == {'method'=>'listaccounts', 'id'=>'jsonrpc'}
36
+ end
37
+ end
38
+
39
+ should 'return a hash of Account objects' do
40
+ @result = @bcd.accounts
41
+ assert_kind_of Hash, @result
42
+ @result.each do |k, a|
43
+ assert_kind_of Bitcoind::Account, a
44
+ assert_equal k, a.name
45
+ end
46
+
47
+ assert_equal 'pi', @result['pi'].name
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,3 @@
1
+ require 'shoulda'
2
+ require 'mocha'
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'bitcoind')
@@ -0,0 +1,54 @@
1
+ require 'helper'
2
+
3
+ class TransactionTest < Test::Unit::TestCase
4
+ context 'a transaction' do
5
+ setup do
6
+ @client = stub
7
+ @acc = Bitcoind::Account.new @client, 'pi'
8
+ @txn = Bitcoind::Transaction.new @client, @acc, 'testtxnid'
9
+ end
10
+
11
+ context 'with a detail_hash' do
12
+ setup do
13
+ @client.expects(:request).
14
+ once.
15
+ with('gettransaction', 'testtxnid').
16
+ returns('amount'=>3.14, 'confirmations'=>420, 'txid'=>'testtxnid',
17
+ 'time'=>1234567890, 'details'=>{
18
+ 'account'=> 'pi',
19
+ 'address'=>'testaddress',
20
+ 'category'=>'receive',
21
+ 'amount'=>3.14
22
+ })
23
+ end
24
+
25
+ should 'have an amount and time' do
26
+ assert_equal 3.14, @txn.amount
27
+ assert_equal Time.at(1234567890), @txn.time
28
+ end
29
+
30
+ should 'have confirmations and be confirmed' do
31
+ assert_equal 420, @txn.confirmations
32
+ assert @txn.confirmed?
33
+ end
34
+ end
35
+
36
+ context 'without a detail_hash' do
37
+ setup do
38
+ @client.expects(:request).
39
+ at_least_once.
40
+ with('gettransaction', 'testtxnid').
41
+ raises(RestClient::InternalServerError)
42
+ end
43
+
44
+ should 'have a sane inspect' do
45
+ assert_equal "#<Bitcoind::Transaction testtxnid UNCONFIRMED>", @txn.inspect
46
+ end
47
+
48
+ should 'have zero confirmations and be unconfirmed' do
49
+ assert_equal 0, @txn.confirmations
50
+ assert !@txn.confirmed?
51
+ end
52
+ end
53
+ end
54
+ end
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bitcoind
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Bryce Kerley
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-04-18 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rest-client
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 6
31
+ - 1
32
+ version: 1.6.1
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: activesupport
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ segments:
44
+ - 3
45
+ - 0
46
+ - 6
47
+ version: 3.0.6
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: guard-test
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ~>
57
+ - !ruby/object:Gem::Version
58
+ segments:
59
+ - 0
60
+ - 1
61
+ - 6
62
+ version: 0.1.6
63
+ type: :development
64
+ version_requirements: *id003
65
+ - !ruby/object:Gem::Dependency
66
+ name: shoulda
67
+ prerelease: false
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ~>
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 2
75
+ - 11
76
+ - 3
77
+ version: 2.11.3
78
+ type: :development
79
+ version_requirements: *id004
80
+ - !ruby/object:Gem::Dependency
81
+ name: mocha
82
+ prerelease: false
83
+ requirement: &id005 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ~>
87
+ - !ruby/object:Gem::Version
88
+ segments:
89
+ - 0
90
+ - 9
91
+ - 12
92
+ version: 0.9.12
93
+ type: :development
94
+ version_requirements: *id005
95
+ - !ruby/object:Gem::Dependency
96
+ name: bundler
97
+ prerelease: false
98
+ requirement: &id006 !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ segments:
104
+ - 1
105
+ - 0
106
+ - 12
107
+ version: 1.0.12
108
+ type: :development
109
+ version_requirements: *id006
110
+ description: Automate your Bitcoin transactions with this Ruby interface to the bitcoind JSON-RPC API.
111
+ email:
112
+ - bkerley@brycekerley.net
113
+ executables: []
114
+
115
+ extensions: []
116
+
117
+ extra_rdoc_files: []
118
+
119
+ files:
120
+ - .gitignore
121
+ - Gemfile
122
+ - Guardfile
123
+ - LICENSE.txt
124
+ - README.md
125
+ - Rakefile
126
+ - bitcoind.gemspec
127
+ - lib/bitcoind.rb
128
+ - lib/bitcoind/account.rb
129
+ - lib/bitcoind/account_hash.rb
130
+ - lib/bitcoind/client.rb
131
+ - lib/bitcoind/transaction.rb
132
+ - lib/bitcoind/version.rb
133
+ - test/account_hash_test.rb
134
+ - test/account_test.rb
135
+ - test/client_test.rb
136
+ - test/helper.rb
137
+ - test/transaction_test.rb
138
+ has_rdoc: true
139
+ homepage: ""
140
+ licenses: []
141
+
142
+ post_install_message:
143
+ rdoc_options: []
144
+
145
+ require_paths:
146
+ - lib
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ none: false
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ segments:
153
+ - 0
154
+ version: "0"
155
+ required_rubygems_version: !ruby/object:Gem::Requirement
156
+ none: false
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ segments:
161
+ - 0
162
+ version: "0"
163
+ requirements: []
164
+
165
+ rubyforge_project: bitcoind
166
+ rubygems_version: 1.3.7
167
+ signing_key:
168
+ specification_version: 3
169
+ summary: Control the bitcoin nework client over JSON-RPC.
170
+ test_files:
171
+ - test/account_hash_test.rb
172
+ - test/account_test.rb
173
+ - test/client_test.rb
174
+ - test/helper.rb
175
+ - test/transaction_test.rb