bitcoind 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
+ *.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