bitcoin 0.1.0 → 0.1.2

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 (64) hide show
  1. data/.rvmrc +1 -1
  2. data/Gemfile.lock +56 -4
  3. data/Guardfile +38 -0
  4. data/README.markdown +21 -2
  5. data/bin/rbcoin +8 -1
  6. data/bitcoin.gemspec +17 -5
  7. data/config/cucumber.yml +3 -3
  8. data/config/darcs.boring +121 -0
  9. data/doc/DEFINITION_OF_DONE.markdown +12 -0
  10. data/doc/HISTORY.markdown +19 -0
  11. data/{LICENCE.markdown → doc/LICENCE.markdown} +1 -1
  12. data/doc/TODO.markdown +31 -0
  13. data/doc/UBIQUITOUS_LANGUAGE.markdown +15 -0
  14. data/features/descriptions/command_help.feature +31 -0
  15. data/features/descriptions/satoshi_wallet/add_address.feature +49 -0
  16. data/features/descriptions/satoshi_wallet/show_addresses.feature +18 -0
  17. data/features/descriptions/satoshi_wallet/show_version.feature +17 -0
  18. data/features/descriptions/satoshi_wallet/subcommand_help.feature +20 -0
  19. data/features/fixtures/ABOUT_FIXTURES.markdown +6 -0
  20. data/features/fixtures/addressbook_wallet.dat +0 -0
  21. data/features/fixtures/new_wallet.dat +0 -0
  22. data/features/step_definitions/command_steps.rb +3 -0
  23. data/features/step_definitions/wallet_steps.rb +11 -0
  24. data/features/support/env.rb +8 -1
  25. data/lib/bitcoin/cli.rb +35 -0
  26. data/lib/bitcoin/commands.rb +3 -0
  27. data/lib/bitcoin/commands/help_command.rb +32 -0
  28. data/lib/bitcoin/commands/satoshi_wallet.rb +11 -0
  29. data/lib/bitcoin/commands/satoshi_wallet/add_address_command.rb +61 -0
  30. data/lib/bitcoin/commands/satoshi_wallet/show_addresses_command.rb +16 -0
  31. data/lib/bitcoin/commands/satoshi_wallet/show_version_command.rb +15 -0
  32. data/lib/bitcoin/commands/satoshi_wallet_command.rb +37 -0
  33. data/lib/bitcoin/commands/satoshi_wallet_command_environment.rb +28 -0
  34. data/lib/bitcoin/console/capturing_stream_bundle.rb +42 -0
  35. data/lib/bitcoin/console/stream_bundle.rb +21 -0
  36. data/lib/bitcoin/data_access/satoshi/bdb_satoshi_wallet_repository.rb +155 -0
  37. data/lib/bitcoin/data_access/satoshi/satoshi_version.rb +58 -0
  38. data/lib/bitcoin/data_access/satoshi/satoshi_wallet.rb +39 -0
  39. data/lib/bitcoin/domain/address_book.rb +19 -0
  40. data/lib/bitcoin/domain/bitcoin_address.rb +33 -0
  41. data/lib/bitcoin/filesystem/empty_temp_dir.rb +74 -0
  42. data/lib/bitcoin/rspec/argument_matchers.rb +1 -0
  43. data/lib/bitcoin/rspec/argument_matchers/block_evaluating_to_matcher.rb +23 -0
  44. data/lib/bitcoin/rspec/directory_helpers.rb +22 -0
  45. data/lib/bitcoin/version.rb +1 -1
  46. data/spec/bitcoin/cli_spec.rb +128 -0
  47. data/spec/bitcoin/commands/help_command_spec.rb +53 -0
  48. data/spec/bitcoin/commands/satoshi_wallet/add_address_command_spec.rb +149 -0
  49. data/spec/bitcoin/commands/satoshi_wallet/show_addresses_command_spec.rb +26 -0
  50. data/spec/bitcoin/commands/satoshi_wallet/show_version_command_spec.rb +26 -0
  51. data/spec/bitcoin/commands/satoshi_wallet_command_environment_spec.rb +76 -0
  52. data/spec/bitcoin/commands/satoshi_wallet_command_spec.rb +73 -0
  53. data/spec/bitcoin/console/_contracts/stream_bundle_contract.rb +29 -0
  54. data/spec/bitcoin/console/capturing_stream_bundle_spec.rb +74 -0
  55. data/spec/bitcoin/console/stream_bundle_spec.rb +13 -0
  56. data/spec/bitcoin/data_access/satoshi/bdb_satoshi_wallet_repository_spec.rb +78 -0
  57. data/spec/bitcoin/data_access/satoshi/satoshi_version_spec.rb +112 -0
  58. data/spec/bitcoin/data_access/satoshi/satoshi_wallet_spec.rb +102 -0
  59. data/spec/bitcoin/domain/address_book_spec.rb +63 -0
  60. data/spec/bitcoin/domain/bitcoin_address_spec.rb +52 -0
  61. data/spec/bitcoin/filesystem/empty_temp_dir_spec.rb +170 -0
  62. data/spec/bitcoin/rspec/argument_matchers/block_evaluating_to_matcher_spec.rb +36 -0
  63. data/spec/spec_helper.rb +29 -1
  64. metadata +221 -18
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ require 'bitcoin/commands/satoshi_wallet_command'
4
+
5
+ # Dependencies only used in the spec
6
+ require 'bitcoin/domain/address_book'
7
+ require 'bitcoin/console/capturing_stream_bundle'
8
+ require 'bitcoin/commands/satoshi_wallet_command_environment'
9
+
10
+ module Bitcoin
11
+ module Commands
12
+ describe SatoshiWalletCommand do
13
+ let(:stream_bundle) { Console::CapturingStreamBundle.test_bundle }
14
+ let(:command_environment) { mock(SatoshiWalletCommandEnvironment, run_command: nil) }
15
+
16
+ subject { SatoshiWalletCommand.new(stream_bundle, command_environment) }
17
+
18
+ describe "#run" do
19
+ shared_examples_for "SatoshiWalletCommand#run" do |options|
20
+ let(:command) { mock(options[:command_class]) }
21
+
22
+ before(:each) do
23
+ options[:command_class].stub(new: command)
24
+ end
25
+
26
+ it "makes a command" do
27
+ options[:command_class].should_receive(:new).with(stream_bundle)
28
+ subject.run([ options[:command_name], "wallet.dat", "foo", "bar" ])
29
+ end
30
+
31
+ it "runs the command" do
32
+ command_environment.should_receive(:run_command).with(command, %w[ wallet.dat foo bar ])
33
+ subject.run([ options[:command_name], "wallet.dat", "foo", "bar" ])
34
+ end
35
+ end
36
+
37
+ context "show-version" do
38
+ it_behaves_like "SatoshiWalletCommand#run",
39
+ command_name: "show-version",
40
+ command_class: Commands::SatoshiWallet::ShowVersionCommand
41
+ end
42
+
43
+ context "show-addresses" do
44
+ it_behaves_like "SatoshiWalletCommand#run",
45
+ command_name: "show-addresses",
46
+ command_class: Commands::SatoshiWallet::ShowAddressesCommand
47
+ end
48
+
49
+ context "add-address" do
50
+ it_behaves_like "SatoshiWalletCommand#run",
51
+ command_name: "add-address",
52
+ command_class: Commands::SatoshiWallet::AddAddressCommand
53
+ end
54
+
55
+ context "<unknown subcommand>" do
56
+ it "prints an error" do
57
+ expect {
58
+ subject.run(%w[ unknown-subcommand wallet.dat foo bar ])
59
+ }.to raise_error
60
+
61
+ stream_bundle.captured_error.should eq %'Unknown satoshi-wallet subcommand: "unknown-subcommand"\n'
62
+ end
63
+
64
+ it "raises an error" do
65
+ expect {
66
+ subject.run(%w[ unknown-subcommand wallet.dat foo bar ])
67
+ }.to raise_error(CLI::CommandError)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,29 @@
1
+ contract "StreamBundle" do
2
+ let(:input) { StringIO.new }
3
+ let(:output) { StringIO.new }
4
+ let(:error) { StringIO.new }
5
+
6
+ let(:subject) { described_class.new(input, output, error) }
7
+
8
+ describe "#puts_output" do
9
+ it "writes a line to the output" do
10
+ subject.puts_output("foo")
11
+ subject.puts_output("bar")
12
+ subject.puts_output("baz")
13
+
14
+ output.rewind
15
+ output.read.should eq "foo\nbar\nbaz\n"
16
+ end
17
+ end
18
+
19
+ describe "#puts_error" do
20
+ it "writes a line to the output" do
21
+ subject.puts_error("foo")
22
+ subject.puts_error("bar")
23
+ subject.puts_error("baz")
24
+
25
+ error.rewind
26
+ error.read.should eq "foo\nbar\nbaz\n"
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ require 'bitcoin/console/capturing_stream_bundle'
4
+
5
+ require_relative '_contracts/stream_bundle_contract'
6
+
7
+ module Bitcoin
8
+ module Console
9
+ describe CapturingStreamBundle do
10
+ it_satisfies_contract "StreamBundle"
11
+
12
+ let(:input) { StringIO.new }
13
+ let(:output) { StringIO.new }
14
+ let(:error) { StringIO.new }
15
+
16
+ let(:subject) { CapturingStreamBundle.new(input, output, error) }
17
+
18
+ describe ".test_bundle" do
19
+ it "creates a CapturingStreamBundle with three StringIO streams", because: "we only care about captured output" do
20
+ # Really should be a separate factory object, but not for the sake of one method
21
+ CapturingStreamBundle.should_receive(:new).with(
22
+ an_instance_of(StringIO), an_instance_of(StringIO), an_instance_of(StringIO)
23
+ ).and_return(:stream_bundle)
24
+ CapturingStreamBundle.test_bundle.should eq :stream_bundle
25
+ end
26
+ end
27
+
28
+ # The output and error streams are effectively the same with different names,
29
+ # but the duplication is only textual and I don't see a neat way to remove it yet
30
+
31
+ describe "#captured_output" do
32
+ before(:each) do
33
+ subject.puts_output("foo")
34
+ subject.puts_output("bar")
35
+ subject.puts_output("baz")
36
+ end
37
+
38
+ its(:captured_output) { should eq "foo\nbar\nbaz\n" }
39
+
40
+ it "doesn't manipulate the output stream" do
41
+ output.stub(:rewind).and_raise(RuntimeError.new)
42
+ expect { subject.captured_output }.to_not raise_error
43
+ end
44
+
45
+ it "accumulates output across reads" do
46
+ subject.captured_output
47
+ subject.puts_output("quux")
48
+ subject.captured_output.should eq "foo\nbar\nbaz\nquux\n"
49
+ end
50
+ end
51
+
52
+ describe "#captured_error" do
53
+ before(:each) do
54
+ subject.puts_error("foo")
55
+ subject.puts_error("bar")
56
+ subject.puts_error("baz")
57
+ end
58
+
59
+ its(:captured_error) { should eq "foo\nbar\nbaz\n" }
60
+
61
+ it "doesn't manipulate the error stream" do
62
+ error.stub(:rewind).and_raise(RuntimeError.new)
63
+ expect { subject.captured_error }.to_not raise_error
64
+ end
65
+
66
+ it "accumulates output across reads" do
67
+ subject.captured_error
68
+ subject.puts_error("quux")
69
+ subject.captured_error.should eq "foo\nbar\nbaz\nquux\n"
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ require 'bitcoin/console/stream_bundle'
4
+
5
+ require_relative '_contracts/stream_bundle_contract'
6
+
7
+ module Bitcoin
8
+ module Console
9
+ describe StreamBundle do
10
+ it_satisfies_contract "StreamBundle"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+
3
+ require 'bitcoin/data_access/satoshi/bdb_satoshi_wallet_repository'
4
+ require 'bitcoin/rspec/directory_helpers'
5
+
6
+ module Bitcoin
7
+ module DataAccess
8
+ module Satoshi
9
+ describe BDBSatoshiWalletRepository, adapter: :slow do
10
+ include Bitcoin::RSpec::DirectoryHelpers
11
+
12
+ TEMP_DB_DIR = File.join(PROJECT_ROOT, "tmp", "db").freeze
13
+ ensure_empty_test_dir(TEMP_DB_DIR)
14
+
15
+ # Temporary means to get a copy of the fixture file
16
+ before(:each) do
17
+ FileUtils.cp(File.join(PROJECT_ROOT, "features", "fixtures", wallet_fixture_filename), TEMP_DB_DIR)
18
+ end
19
+
20
+ def wallet_filename
21
+ File.join(PROJECT_ROOT, "tmp", "db", wallet_fixture_filename)
22
+ end
23
+
24
+ let(:wallet_fixture_filename) { "addressbook_wallet.dat" }
25
+
26
+ subject { BDBSatoshiWalletRepository.new(wallet_filename, db_dirname: TEMP_DB_DIR) }
27
+
28
+ it "has a less naive write_compact_size"
29
+
30
+ describe "4-byte unsigned little endian integers stored immediately (no compact length in the value)" do
31
+ specify {
32
+ subject.get_value_immediate_uint32le("version").should eq 32400
33
+ }
34
+
35
+ specify {
36
+ expect {
37
+ subject.set_value_immediate_uint32le("version", 32500)
38
+ }.to change {
39
+ subject.get_value_immediate_uint32le("version")
40
+ }.from(32400).to(32500)
41
+ }
42
+ end
43
+
44
+ describe "string key data, string value data" do
45
+ it "lets you read all values" do
46
+ subject.get_key_and_value_data_string_utf8("name").should eq [
47
+ [ "13f2t2WKnCZh1rZbDhdUKB6fY1rZNWZVzd", "Receiving address 2" ],
48
+ [ "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz", "Bitcoin Monitor" ],
49
+ [ "16kzGRdP8LToECecna3EynghiApUM9duLw", "Receiving address 1" ],
50
+ [ "1Nqr3MqVyUp6k3o3QPePAdn4Yg4tzgB9kw", "Bitcoincharts" ]
51
+ ]
52
+ end
53
+
54
+ it "lets you read individual values" do
55
+ subject.get_value_with_key_data_string_utf8("name", "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz").should eq "Bitcoin Monitor"
56
+ end
57
+
58
+ it "lets you create" do
59
+ expect {
60
+ subject.set_value_with_key_data_string_utf8("name", "1ThisIsAMadeUpKeyKudFr63EwHqQT2njz", "New Value")
61
+ }.to change {
62
+ subject.get_value_with_key_data_string_utf8("name", "1ThisIsAMadeUpKeyKudFr63EwHqQT2njz")
63
+ }.from(nil).to("New Value")
64
+ end
65
+
66
+ it "lets you update" do
67
+ expect {
68
+ subject.set_value_with_key_data_string_utf8("name", "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz", "Really is Bitcoin Monitor")
69
+ }.to change {
70
+ subject.get_value_with_key_data_string_utf8("name", "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz")
71
+ }.from("Bitcoin Monitor").to("Really is Bitcoin Monitor")
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+
@@ -0,0 +1,112 @@
1
+ require 'spec_helper'
2
+
3
+ require 'bitcoin/data_access/satoshi/satoshi_version'
4
+
5
+ module Bitcoin
6
+ module DataAccess
7
+ module Satoshi
8
+ describe SatoshiVersion do
9
+ describe ".from_wallet_bytes" do
10
+ it "supports the data format as extracted from the BDB database" do
11
+ SatoshiVersion.from_wallet_bytes([144, 126, 0, 0]).should eq SatoshiVersion.new(0, 3, 24)
12
+ end
13
+ end
14
+
15
+ describe ".from_wallet_int" do
16
+ it "supports the data format as extracted from the BDB database" do
17
+ SatoshiVersion.from_wallet_int(32400).should eq SatoshiVersion.new(0, 3, 24)
18
+ end
19
+ end
20
+
21
+ describe "three-part form" do
22
+ it "compares equality" do
23
+ SatoshiVersion.new(0, 3, 24).should eq SatoshiVersion.new(0, 3, 24)
24
+
25
+ SatoshiVersion.new(0, 3, 24).should_not eq SatoshiVersion.new(0, 3, 25)
26
+ SatoshiVersion.new(0, 3, 24).should_not eq SatoshiVersion.new(0, 4, 24)
27
+ SatoshiVersion.new(0, 3, 24).should_not eq SatoshiVersion.new(1, 3, 24)
28
+ end
29
+
30
+ it "has a total ordering" do
31
+ SatoshiVersion.new(0, 3, 24).should be < SatoshiVersion.new(0, 3, 25)
32
+ SatoshiVersion.new(0, 3, 24).should be > SatoshiVersion.new(0, 3, 23)
33
+
34
+ SatoshiVersion.new(0, 3, 24).should be < SatoshiVersion.new(0, 4, 23)
35
+ SatoshiVersion.new(0, 3, 24).should be > SatoshiVersion.new(0, 2, 25)
36
+
37
+ SatoshiVersion.new(1, 3, 24).should be < SatoshiVersion.new(2, 2, 23)
38
+ SatoshiVersion.new(1, 3, 24).should be > SatoshiVersion.new(0, 4, 25)
39
+ end
40
+ end
41
+
42
+ describe "four-part form" do
43
+ # We cheat slightly here and make assumptions about the implementation
44
+ # (by not re-specifying every conceivable possibility)
45
+
46
+ it "compares equality" do
47
+ SatoshiVersion.new(0, 3, 24, 0).should eq SatoshiVersion.new(0, 3, 24, 0)
48
+ SatoshiVersion.new(0, 3, 24, 0).should_not eq SatoshiVersion.new(0, 3, 24, 1)
49
+ end
50
+
51
+ it "has a total ordering" do
52
+ SatoshiVersion.new(0, 3, 24, 1).should be < SatoshiVersion.new(0, 3, 25, 2)
53
+ SatoshiVersion.new(0, 3, 24, 1).should be > SatoshiVersion.new(0, 3, 23, 0)
54
+
55
+ SatoshiVersion.new(0, 3, 24, 1).should be < SatoshiVersion.new(0, 3, 25, 0)
56
+ SatoshiVersion.new(0, 3, 24, 1).should be > SatoshiVersion.new(0, 3, 23, 2)
57
+
58
+ # etc, for the rest of the components...
59
+ end
60
+ end
61
+
62
+ describe "-beta version suffixes" do
63
+ it "are not supported", because: "this is hardcoded into the Satoshi client" do
64
+ # As of 0.3.24, the "beta" status is determined in the C++ code with this value:
65
+ # static const bool VERSION_IS_BETA = true;
66
+ false.should be_false
67
+ end
68
+ end
69
+
70
+ describe "comparing three- and four-part forms" do
71
+ # This is not explicit in the Satoshi code, but seems a reasonable assumption for now,
72
+ # until it breaks...
73
+ it "assumes an implicit 0 at the end of the three-part form" do
74
+ SatoshiVersion.new(0, 3, 24).should eq SatoshiVersion.new(0, 3, 24, 0)
75
+ SatoshiVersion.new(0, 3, 24, 0).should eq SatoshiVersion.new(0, 3, 24)
76
+ # it seems safe to assume the rest of the comparisons work by induction
77
+ end
78
+ end
79
+
80
+ describe "conversion" do
81
+ describe "to strings" do
82
+ it "supports #to_s", because: "we need to be usable with IO#<<" do
83
+ SatoshiVersion.new(0, 3, 24).to_s.should eq "0.3.24"
84
+ SatoshiVersion.new(0, 3, 24, 1).to_s.should eq "0.3.24.1"
85
+ end
86
+
87
+ it "truncates a fourth zero", because: "the standard client does this (semantic versioning?)" do
88
+ SatoshiVersion.new(0, 3, 24, 0).to_s.should eq "0.3.24"
89
+ end
90
+
91
+ it "does not truncate a third version", because: "the standard client does this (semantic versioning?)" do
92
+ SatoshiVersion.new(0, 4, 0).to_s.should eq "0.4.0"
93
+ end
94
+
95
+ it "supports #to_str as an alias of :to_s" do
96
+ version = SatoshiVersion.new(0, 3, 24)
97
+ to_s_method = version.method(:to_s)
98
+ to_str_method = version.method(:to_str)
99
+ to_str_method.should eq to_s_method
100
+ end
101
+ end
102
+
103
+ describe "to Satoshi-format wallet bytes" do
104
+ it "creates the same bytes as came from the BDB database" do
105
+ SatoshiVersion.new(0, 3, 24).to_wallet_bytes.should eq [144, 126, 0, 0]
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ require 'bitcoin/data_access/satoshi/satoshi_wallet'
4
+
5
+ module Bitcoin
6
+ module DataAccess
7
+ module Satoshi
8
+ describe SatoshiWallet do
9
+ describe ".open" do
10
+ let(:satoshi_wallet_repository) { mock(BDBSatoshiWalletRepository) }
11
+ let(:satoshi_wallet) { mock(SatoshiWallet) }
12
+
13
+ before(:each) do
14
+ BDBSatoshiWalletRepository.stub(new: satoshi_wallet_repository)
15
+ SatoshiWallet.stub(new: satoshi_wallet)
16
+ end
17
+
18
+ it "makes a BDBSatoshiWalletRepository" do
19
+ BDBSatoshiWalletRepository.should_receive(:new).with("wallet.dat", db_dirname: "/db/dir")
20
+ SatoshiWallet.open(wallet_filename: "wallet.dat", db_dirname: "/db/dir", & ->(wallet) { :noop })
21
+ end
22
+
23
+ it "makes a SatoshiWallet with the BDBSatoshiWalletRepository" do
24
+ SatoshiWallet.should_receive(:new).with(satoshi_wallet_repository)
25
+ SatoshiWallet.open(wallet_filename: "wallet.dat", db_dirname: "/db/dir", & ->(wallet) { :noop })
26
+ end
27
+
28
+ it "yields the wallet" do
29
+ SatoshiWallet.open(wallet_filename: "wallet.dat", db_dirname: "/db/dir") do |wallet|
30
+ wallet.should eq satoshi_wallet
31
+ end
32
+ end
33
+
34
+ it "returns the value of the block" do
35
+ SatoshiWallet.open(wallet_filename: "wallet.dat", db_dirname: "/db/dir") { |wallet|
36
+ :block_value
37
+ }.should eq :block_value
38
+ end
39
+
40
+ it "raises an error if no block is given", because: "we use blocks to manage the opening and closing of the BDB database" do
41
+ expect {
42
+ SatoshiWallet.open(wallet_filename: "wallet.dat", db_dirname: "/db/dir")
43
+ }.to raise_error(ArgumentError) { |error|
44
+ error.message.should =~ /you must provide a block to SatoshiWallet\.new/i
45
+ }
46
+ end
47
+ end
48
+
49
+ describe "instance methods" do
50
+ let(:satoshi_wallet_repository) { mock(BDBSatoshiWalletRepository) }
51
+
52
+ before(:each) do
53
+ BDBSatoshiWalletRepository.stub(new: satoshi_wallet_repository)
54
+ end
55
+
56
+ subject { SatoshiWallet.new(satoshi_wallet_repository) }
57
+
58
+ describe "#version" do
59
+ it "returns the version from the wallet" do
60
+ satoshi_wallet_repository.should_receive(:get_value_immediate_uint32le).with("version").and_return(32400)
61
+ subject.version.should eq SatoshiVersion.new(0, 3, 24)
62
+ end
63
+ end
64
+
65
+ describe "#addresses" do
66
+ before(:each) do
67
+ satoshi_wallet_repository.stub(
68
+ get_key_and_value_data_string_utf8: [
69
+ [ "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz", "Bitcoin Monitor" ],
70
+ [ "1Nqr3MqVyUp6k3o3QPePAdn4Yg4tzgB9kw", "Bitcoincharts" ]
71
+ ]
72
+ )
73
+ end
74
+
75
+ it "fetches the data" do
76
+ satoshi_wallet_repository.should_receive(:get_key_and_value_data_string_utf8).with("name")
77
+ subject.addresses
78
+ end
79
+
80
+ it "returns an AddressBook with the wallet addresses" do
81
+ subject.addresses.should be_a Domain::AddressBook
82
+ expected_addresses = Domain::AddressBook.new([
83
+ { address: Domain::BitcoinAddress.new("14Z1mazY4HfysZyMaKudFr63EwHqQT2njz"), name: "Bitcoin Monitor" },
84
+ { address: Domain::BitcoinAddress.new("1Nqr3MqVyUp6k3o3QPePAdn4Yg4tzgB9kw"), name: "Bitcoincharts" }
85
+ ]).to_a
86
+ subject.addresses.to_a.should =~ expected_addresses
87
+ end
88
+ end
89
+
90
+ describe "#add_address" do
91
+ it "adds the BitcoinAddress to the Wallet" do
92
+ satoshi_wallet_repository.should_receive(:set_value_with_key_data_string_utf8).with(
93
+ "name", "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz", "Bitcoin Monitor"
94
+ )
95
+ subject.add_address(Domain::BitcoinAddress.new("14Z1mazY4HfysZyMaKudFr63EwHqQT2njz"), name: "Bitcoin Monitor")
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end