7 from StringIO import StringIO
8 from lib.wallet import WalletStorage, NewWallet
11 class FakeConfig(object):
12 """A stub config file to be used in tests"""
13 def __init__(self, path):
17 def set(self, key, value):
18 self.store[key] = value
20 def get(self, key, default=None):
21 return self.store.get(key, default)
24 class FakeSynchronizer(object):
29 def add(self, address):
30 self.store.append(address)
33 class WalletTestCase(unittest.TestCase):
36 super(WalletTestCase, self).setUp()
37 self.user_dir = tempfile.mkdtemp()
39 self.fake_config = FakeConfig(self.user_dir)
41 self._saved_stdout = sys.stdout
42 self._stdout_buffer = StringIO()
43 sys.stdout = self._stdout_buffer
46 super(WalletTestCase, self).tearDown()
47 shutil.rmtree(self.user_dir)
48 # Restore the "real" stdout
49 sys.stdout = self._saved_stdout
52 class TestWalletStorage(WalletTestCase):
54 def test_init_wallet_default_path(self):
55 storage = WalletStorage(self.fake_config)
56 expected = os.path.join(self.user_dir, "wallets", "default_wallet")
57 self.assertEqual(expected, storage.path)
59 def test_init_wallet_explicit_path(self):
60 path = os.path.join(self.user_dir, "somewallet")
61 self.fake_config.set("wallet_path", path)
63 storage = WalletStorage(self.fake_config)
64 self.assertEqual(path, storage.path)
66 def test_init_wallet_default_wallet_path(self):
67 path = os.path.join(self.user_dir, "somewallet")
68 self.fake_config.set("default_wallet_path", path)
70 storage = WalletStorage(self.fake_config)
71 self.assertEqual(path, storage.path)
73 def test_read_dictionnary_from_file(self):
74 path = os.path.join(self.user_dir, "somewallet")
75 self.fake_config.set("wallet_path", path)
77 some_dict = {"a":"b", "c":"d"}
78 contents = repr(some_dict)
79 with open(path, "w") as f:
80 contents = f.write(contents)
82 storage = WalletStorage(self.fake_config)
83 self.assertEqual("b", storage.get("a"))
84 self.assertEqual("d", storage.get("c"))
86 def test_write_dictionnary_to_file(self):
87 path = os.path.join(self.user_dir, "somewallet")
88 self.fake_config.set("wallet_path", path)
90 storage = WalletStorage(self.fake_config)
92 some_dict = {"a":"b", "c":"d"}
93 storage.data = some_dict
98 with open(path, "r") as f:
100 self.assertEqual(repr(some_dict), contents)
103 class TestNewWallet(WalletTestCase):
105 seed_text = "The seed will sprout and grow up tall."
108 master_xpub = "xpub661MyMwAqRbcGEop5Rnp68oX1ikeFNVMtx1utwXZGRKMmeXVxwBM5UzkwU9nGB1EofZekLDRfi1w5F9P7Vac3PEuWdWHr2gHLW8vp5YyKJ1"
109 master_xpriv = "xprv9s21ZrQH143K3kjLyQFoizrnTgv9qumWXj6K6Z7wi5nNtrCMRPs6XggH6Bbgz9CUgPJnZnV74yUdRSr8qWVELr9QQTgU5aNL33ViMyD9nhs"
111 first_account_name = "account1"
112 first_account_first_address = "1Jv9pLCJ4Sqr7aDYLGX5QhET4ps5qRcB9V"
113 first_account_second_address = "14n9EsZsgTTc4eC4TxeP1ccP8bXgwxPMmL"
115 import_private_key = "L52XzL2cMkHxqxBXRyEpnPQZGUs3uKiL3R11XbAdHigRzDozKZeW"
116 import_key_address = "15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma"
119 super(TestNewWallet, self).setUp()
120 self.storage = WalletStorage(self.fake_config)
121 self.wallet = NewWallet(self.storage)
122 # This cannot be constructed by electrum at random, it should be safe
123 # from eventual collisions.
124 self.wallet.add_seed(self.seed_text, self.password)
126 def test_wallet_with_seed_is_not_watching_only(self):
127 self.assertFalse(self.wallet.is_watching_only())
129 def test_wallet_without_seed_is_watching_only(self):
130 # We need a new storage , since the default storage was already seeded
132 new_dir = tempfile.mkdtemp()
133 config = FakeConfig(new_dir)
134 wallet = NewWallet(config)
135 self.assertTrue(wallet.is_watching_only())
136 shutil.rmtree(new_dir) # Don't leave useless stuff in /tmp
138 def test_new_wallet_is_deterministic(self):
139 self.assertTrue(self.wallet.is_deterministic())
141 def test_get_seed_returns_correct_seed(self):
142 self.assertEqual(self.wallet.get_seed(self.password), self.seed_text)
143 self.assertEqual(0, len(self.wallet.addresses()))
145 def test_add_account(self):
146 self.wallet.create_account(self.first_account_name, self.password)
147 self.assertEqual(1, len(self.wallet.addresses()))
148 self.assertIn(self.first_account_first_address,
149 self.wallet.addresses())
151 def test_add_account_add_address(self):
152 self.wallet.create_account(self.first_account_name, self.password)
153 self.wallet.synchronizer = FakeSynchronizer()
155 self.wallet.create_new_address()
156 self.assertEqual(2, len(self.wallet.addresses()))
157 self.assertIn(self.first_account_first_address,
158 self.wallet.addresses())
159 self.assertIn(self.first_account_second_address,
160 self.wallet.addresses())
162 def test_key_import(self):
163 # Wallets have no imported keys by default.
164 self.wallet.create_account(self.first_account_name, self.password)
165 self.assertFalse(self.wallet.has_imported_keys())
167 # Importing a key works.
168 self.wallet.import_key(self.import_private_key, "")
169 self.assertEqual(2, len(self.wallet.addresses()))
170 self.assertIn(self.import_key_address, self.wallet.addresses())
172 self.assertTrue(self.wallet.has_imported_keys())
174 # Deleting the key works.
175 self.wallet.delete_imported_key(self.import_key_address)
176 self.assertFalse(self.wallet.has_imported_keys())
177 self.assertEqual(1, len(self.wallet.addresses()))
178 self.assertNotIn(self.import_key_address, self.wallet.addresses())
180 def test_update_password(self):
181 new_password = "secret2"
182 self.wallet.update_password(self.password, new_password)
183 self.wallet.create_account(self.first_account_name, new_password)
184 self.assertEqual(1, len(self.wallet.addresses()))