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.
- data/.rvmrc +1 -1
- data/Gemfile.lock +56 -4
- data/Guardfile +38 -0
- data/README.markdown +21 -2
- data/bin/rbcoin +8 -1
- data/bitcoin.gemspec +17 -5
- data/config/cucumber.yml +3 -3
- data/config/darcs.boring +121 -0
- data/doc/DEFINITION_OF_DONE.markdown +12 -0
- data/doc/HISTORY.markdown +19 -0
- data/{LICENCE.markdown → doc/LICENCE.markdown} +1 -1
- data/doc/TODO.markdown +31 -0
- data/doc/UBIQUITOUS_LANGUAGE.markdown +15 -0
- data/features/descriptions/command_help.feature +31 -0
- data/features/descriptions/satoshi_wallet/add_address.feature +49 -0
- data/features/descriptions/satoshi_wallet/show_addresses.feature +18 -0
- data/features/descriptions/satoshi_wallet/show_version.feature +17 -0
- data/features/descriptions/satoshi_wallet/subcommand_help.feature +20 -0
- data/features/fixtures/ABOUT_FIXTURES.markdown +6 -0
- data/features/fixtures/addressbook_wallet.dat +0 -0
- data/features/fixtures/new_wallet.dat +0 -0
- data/features/step_definitions/command_steps.rb +3 -0
- data/features/step_definitions/wallet_steps.rb +11 -0
- data/features/support/env.rb +8 -1
- data/lib/bitcoin/cli.rb +35 -0
- data/lib/bitcoin/commands.rb +3 -0
- data/lib/bitcoin/commands/help_command.rb +32 -0
- data/lib/bitcoin/commands/satoshi_wallet.rb +11 -0
- data/lib/bitcoin/commands/satoshi_wallet/add_address_command.rb +61 -0
- data/lib/bitcoin/commands/satoshi_wallet/show_addresses_command.rb +16 -0
- data/lib/bitcoin/commands/satoshi_wallet/show_version_command.rb +15 -0
- data/lib/bitcoin/commands/satoshi_wallet_command.rb +37 -0
- data/lib/bitcoin/commands/satoshi_wallet_command_environment.rb +28 -0
- data/lib/bitcoin/console/capturing_stream_bundle.rb +42 -0
- data/lib/bitcoin/console/stream_bundle.rb +21 -0
- data/lib/bitcoin/data_access/satoshi/bdb_satoshi_wallet_repository.rb +155 -0
- data/lib/bitcoin/data_access/satoshi/satoshi_version.rb +58 -0
- data/lib/bitcoin/data_access/satoshi/satoshi_wallet.rb +39 -0
- data/lib/bitcoin/domain/address_book.rb +19 -0
- data/lib/bitcoin/domain/bitcoin_address.rb +33 -0
- data/lib/bitcoin/filesystem/empty_temp_dir.rb +74 -0
- data/lib/bitcoin/rspec/argument_matchers.rb +1 -0
- data/lib/bitcoin/rspec/argument_matchers/block_evaluating_to_matcher.rb +23 -0
- data/lib/bitcoin/rspec/directory_helpers.rb +22 -0
- data/lib/bitcoin/version.rb +1 -1
- data/spec/bitcoin/cli_spec.rb +128 -0
- data/spec/bitcoin/commands/help_command_spec.rb +53 -0
- data/spec/bitcoin/commands/satoshi_wallet/add_address_command_spec.rb +149 -0
- data/spec/bitcoin/commands/satoshi_wallet/show_addresses_command_spec.rb +26 -0
- data/spec/bitcoin/commands/satoshi_wallet/show_version_command_spec.rb +26 -0
- data/spec/bitcoin/commands/satoshi_wallet_command_environment_spec.rb +76 -0
- data/spec/bitcoin/commands/satoshi_wallet_command_spec.rb +73 -0
- data/spec/bitcoin/console/_contracts/stream_bundle_contract.rb +29 -0
- data/spec/bitcoin/console/capturing_stream_bundle_spec.rb +74 -0
- data/spec/bitcoin/console/stream_bundle_spec.rb +13 -0
- data/spec/bitcoin/data_access/satoshi/bdb_satoshi_wallet_repository_spec.rb +78 -0
- data/spec/bitcoin/data_access/satoshi/satoshi_version_spec.rb +112 -0
- data/spec/bitcoin/data_access/satoshi/satoshi_wallet_spec.rb +102 -0
- data/spec/bitcoin/domain/address_book_spec.rb +63 -0
- data/spec/bitcoin/domain/bitcoin_address_spec.rb +52 -0
- data/spec/bitcoin/filesystem/empty_temp_dir_spec.rb +170 -0
- data/spec/bitcoin/rspec/argument_matchers/block_evaluating_to_matcher_spec.rb +36 -0
- data/spec/spec_helper.rb +29 -1
- 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,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
|