multi-account synchronization
This commit is contained in:
parent
04e53281f6
commit
d2f4eed1f7
|
@ -99,12 +99,7 @@ class PendingAccount(Account):
|
||||||
self.pending_address = v['pending']
|
self.pending_address = v['pending']
|
||||||
|
|
||||||
def synchronize(self, wallet):
|
def synchronize(self, wallet):
|
||||||
if wallet.address_is_old(self.pending_address):
|
return
|
||||||
print_error( "creating account", account_id )
|
|
||||||
xpub = wallet.master_public_keys[account_id]
|
|
||||||
account = BIP32_Account({'xpub':xpub})
|
|
||||||
wallet.add_account(account_id, account)
|
|
||||||
#self.next_addresses.pop(account_id)
|
|
||||||
|
|
||||||
def get_addresses(self, is_change):
|
def get_addresses(self, is_change):
|
||||||
return [self.pending_address]
|
return [self.pending_address]
|
||||||
|
|
|
@ -303,7 +303,7 @@ class Abstract_Wallet(object):
|
||||||
self.save_accounts()
|
self.save_accounts()
|
||||||
|
|
||||||
if self.synchronizer:
|
if self.synchronizer:
|
||||||
self.synchronizer.subscribe_to_addresses([address])
|
self.synchronizer.add(address)
|
||||||
return address
|
return address
|
||||||
|
|
||||||
def delete_imported_key(self, addr):
|
def delete_imported_key(self, addr):
|
||||||
|
@ -1153,7 +1153,8 @@ class Deterministic_Wallet(Abstract_Wallet):
|
||||||
return address
|
return address
|
||||||
|
|
||||||
def add_address(self, address):
|
def add_address(self, address):
|
||||||
self.history[address] = []
|
if address not in self.history:
|
||||||
|
self.history[address] = []
|
||||||
if self.synchronizer:
|
if self.synchronizer:
|
||||||
self.synchronizer.add(address)
|
self.synchronizer.add(address)
|
||||||
self.save_accounts()
|
self.save_accounts()
|
||||||
|
@ -1327,10 +1328,21 @@ class BIP32_Simple_Wallet(BIP32_Wallet):
|
||||||
|
|
||||||
class BIP32_HD_Wallet(BIP32_Wallet):
|
class BIP32_HD_Wallet(BIP32_Wallet):
|
||||||
# wallet that can create accounts
|
# wallet that can create accounts
|
||||||
|
def __init__(self, storage):
|
||||||
|
self.next_account = storage.get('next_account', None)
|
||||||
|
BIP32_Wallet.__init__(self, storage)
|
||||||
|
|
||||||
def can_create_accounts(self):
|
def can_create_accounts(self):
|
||||||
return self.root_name in self.master_private_keys.keys()
|
return self.root_name in self.master_private_keys.keys()
|
||||||
|
|
||||||
|
def addresses(self, b):
|
||||||
|
l = BIP32_Wallet.addresses(self, b)
|
||||||
|
if self.next_account:
|
||||||
|
next_address = self.next_account[2]
|
||||||
|
if next_address not in l:
|
||||||
|
l.append(next_address)
|
||||||
|
return l
|
||||||
|
|
||||||
def num_accounts(self):
|
def num_accounts(self):
|
||||||
keys = []
|
keys = []
|
||||||
for k, v in self.accounts.items():
|
for k, v in self.accounts.items():
|
||||||
|
@ -1345,51 +1357,67 @@ class BIP32_HD_Wallet(BIP32_Wallet):
|
||||||
i += 1
|
i += 1
|
||||||
return i
|
return i
|
||||||
|
|
||||||
def next_account_address(self, password):
|
def get_next_account(self, password):
|
||||||
account_id = '%d'%self.num_accounts()
|
account_id = '%d'%self.num_accounts()
|
||||||
account = self.make_account(account_id, password)
|
|
||||||
addr = account.first_address()
|
|
||||||
return account_id, addr
|
|
||||||
|
|
||||||
def make_account(self, account_id, password):
|
|
||||||
"""Creates and saves the master keys, but does not save the account"""
|
|
||||||
derivation = self.root_name + "%d'"%int(account_id)
|
derivation = self.root_name + "%d'"%int(account_id)
|
||||||
xpub, xprv = self.derive_xkeys(self.root_name, derivation, password)
|
xpub, xprv = self.derive_xkeys(self.root_name, derivation, password)
|
||||||
self.add_master_public_key(derivation, xpub)
|
self.add_master_public_key(derivation, xpub)
|
||||||
self.add_master_private_key(derivation, xprv, password)
|
if xprv:
|
||||||
|
self.add_master_private_key(derivation, xprv, password)
|
||||||
account = BIP32_Account({'xpub':xpub})
|
account = BIP32_Account({'xpub':xpub})
|
||||||
return account
|
addr = account.first_address()
|
||||||
|
return account_id, xpub, addr
|
||||||
def create_account(self, name, password):
|
|
||||||
account_id = "%d"%self.num_accounts()
|
|
||||||
account = self.make_account(account_id, password)
|
|
||||||
self.add_account(account_id, account)
|
|
||||||
if name:
|
|
||||||
self.set_label(account_id, name)
|
|
||||||
# add address of the next account
|
|
||||||
account_id, addr = self.next_account_address(password)
|
|
||||||
self.storage.put('next_address',(account_id, addr))
|
|
||||||
|
|
||||||
def create_main_account(self, password):
|
def create_main_account(self, password):
|
||||||
# First check the password is valid (this raises if it isn't).
|
# First check the password is valid (this raises if it isn't).
|
||||||
if not self.is_watching_only():
|
self.check_password(password)
|
||||||
self.check_password(password)
|
assert self.num_accounts() == 0
|
||||||
self.create_account('Main account', password)
|
self.create_account('Main account', password)
|
||||||
|
|
||||||
|
def create_account(self, name, password):
|
||||||
|
account_id, xpub, addr = self.get_next_account(password)
|
||||||
|
account = BIP32_Account({'xpub':xpub})
|
||||||
|
self.add_account(account_id, account)
|
||||||
|
self.set_label(account_id, name)
|
||||||
|
# add address of the next account
|
||||||
|
self.next_account = self.get_next_account(password)
|
||||||
|
self.storage.put('next_account', self.next_account)
|
||||||
|
|
||||||
def account_is_pending(self, k):
|
def account_is_pending(self, k):
|
||||||
return type(self.accounts.get(k)) == PendingAccount
|
return type(self.accounts.get(k)) == PendingAccount
|
||||||
|
|
||||||
def delete_pending_account(self, k):
|
def delete_pending_account(self, k):
|
||||||
assert self.account_is_pending(k)
|
assert type(self.accounts.get(k)) == PendingAccount
|
||||||
self.accounts.pop(k)
|
self.accounts.pop(k)
|
||||||
self.save_accounts()
|
self.save_accounts()
|
||||||
|
|
||||||
def create_pending_account(self, name, password):
|
def create_pending_account(self, name, password):
|
||||||
account_id, addr = self.next_account_address(password)
|
next_id, next_xpub, next_address = self.next_account if self.next_account else self.get_next_account_address(password)
|
||||||
self.set_label(account_id, name)
|
self.set_label(next_id, name)
|
||||||
self.accounts[account_id] = PendingAccount({'pending':addr})
|
self.accounts[next_id] = PendingAccount({'pending':next_address})
|
||||||
self.save_accounts()
|
self.save_accounts()
|
||||||
|
# prepare the next account
|
||||||
|
self.next_account = self.get_next_account(password)
|
||||||
|
self.storage.put('next_account', self.next_account)
|
||||||
|
|
||||||
|
def synchronize(self):
|
||||||
|
# synchronize existing accounts
|
||||||
|
BIP32_Wallet.synchronize(self)
|
||||||
|
|
||||||
|
if self.next_account is None:
|
||||||
|
try:
|
||||||
|
self.next_account = self.get_next_account(None)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# check pending account
|
||||||
|
if self.next_account is not None:
|
||||||
|
next_id, next_xpub, next_address = self.next_account
|
||||||
|
if self.address_is_old(next_address):
|
||||||
|
print_error("creating account", next_id)
|
||||||
|
self.add_account(next_id, BIP32_Account({'xpub':next_xpub}))
|
||||||
|
# here the user should get a notification
|
||||||
|
self.next_account = None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue