common wallet.restore() method for GUIs
This commit is contained in:
parent
3d4a16b5c8
commit
ecfe5e2590
7
electrum
7
electrum
|
@ -215,12 +215,13 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
wallet.init_seed( str(seed) )
|
wallet.init_seed( str(seed) )
|
||||||
wallet.save_seed()
|
wallet.save_seed()
|
||||||
wallet.create_accounts()
|
|
||||||
print_msg("Recovering wallet...")
|
|
||||||
network = Network(config)
|
network = Network(config)
|
||||||
network.start()
|
network.start()
|
||||||
wallet.start_threads(network)
|
wallet.start_threads(network)
|
||||||
wallet.update()
|
|
||||||
|
print_msg("Recovering wallet...")
|
||||||
|
wallet.restore(lambda x: x)
|
||||||
|
|
||||||
if wallet.is_found():
|
if wallet.is_found():
|
||||||
print_msg("Recovery successful")
|
print_msg("Recovery successful")
|
||||||
else:
|
else:
|
||||||
|
|
105
gui/gtk.py
105
gui/gtk.py
|
@ -82,7 +82,7 @@ def show_seed_dialog(wallet, password, parent):
|
||||||
dialog.run()
|
dialog.run()
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
|
|
||||||
def restore_create_dialog(wallet):
|
def restore_create_dialog():
|
||||||
|
|
||||||
# ask if the user wants to create a new wallet, or recover from a seed.
|
# ask if the user wants to create a new wallet, or recover from a seed.
|
||||||
# if he wants to recover, and nothing is found, do not create wallet
|
# if he wants to recover, and nothing is found, do not create wallet
|
||||||
|
@ -102,7 +102,7 @@ def restore_create_dialog(wallet):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def run_recovery_dialog(wallet):
|
def run_recovery_dialog():
|
||||||
message = "Please enter your wallet seed or the corresponding mnemonic list of words, and the gap limit of your wallet."
|
message = "Please enter your wallet seed or the corresponding mnemonic list of words, and the gap limit of your wallet."
|
||||||
dialog = gtk.MessageDialog(
|
dialog = gtk.MessageDialog(
|
||||||
parent = None,
|
parent = None,
|
||||||
|
@ -127,35 +127,14 @@ def run_recovery_dialog(wallet):
|
||||||
seed_box.show()
|
seed_box.show()
|
||||||
vbox.pack_start(seed_box, False, False, 5)
|
vbox.pack_start(seed_box, False, False, 5)
|
||||||
|
|
||||||
gap = gtk.HBox()
|
|
||||||
gap_label = gtk.Label('Gap limit:')
|
|
||||||
gap_label.set_size_request(150,10)
|
|
||||||
gap_label.show()
|
|
||||||
gap.pack_start(gap_label,False, False, 10)
|
|
||||||
gap_entry = gtk.Entry()
|
|
||||||
gap_entry.set_text("%d"%wallet.gap_limit)
|
|
||||||
gap_entry.connect('changed', numbify, True)
|
|
||||||
gap_entry.show()
|
|
||||||
gap.pack_start(gap_entry,False,False, 10)
|
|
||||||
add_help_button(gap, 'The maximum gap that is allowed between unused addresses in your wallet. During wallet recovery, this parameter is used to decide when to stop the recovery process. If you increase this value, you will need to remember it in order to be able to recover your wallet from seed.')
|
|
||||||
gap.show()
|
|
||||||
vbox.pack_start(gap, False,False, 5)
|
|
||||||
|
|
||||||
dialog.show()
|
dialog.show()
|
||||||
r = dialog.run()
|
r = dialog.run()
|
||||||
gap = gap_entry.get_text()
|
|
||||||
seed = seed_entry.get_text()
|
seed = seed_entry.get_text()
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
|
|
||||||
if r==gtk.RESPONSE_CANCEL:
|
if r==gtk.RESPONSE_CANCEL:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
|
||||||
gap = int(gap)
|
|
||||||
except:
|
|
||||||
show_message("error")
|
|
||||||
return False
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
seed.decode('hex')
|
seed.decode('hex')
|
||||||
except:
|
except:
|
||||||
|
@ -165,7 +144,7 @@ def run_recovery_dialog(wallet):
|
||||||
show_message("no seed")
|
show_message("no seed")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return seed, gap
|
return seed
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -265,13 +244,13 @@ def run_settings_dialog(wallet, parent):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def run_network_dialog( wallet, parent ):
|
def run_network_dialog( network, parent ):
|
||||||
image = gtk.Image()
|
image = gtk.Image()
|
||||||
image.set_from_stock(gtk.STOCK_NETWORK, gtk.ICON_SIZE_DIALOG)
|
image.set_from_stock(gtk.STOCK_NETWORK, gtk.ICON_SIZE_DIALOG)
|
||||||
interface = wallet.network.interface
|
interface = network.interface
|
||||||
if parent:
|
if parent:
|
||||||
if interface.is_connected:
|
if interface.is_connected:
|
||||||
status = "Connected to %s:%d\n%d blocks"%(interface.host, interface.port, wallet.network.blockchain.height)
|
status = "Connected to %s:%d\n%d blocks"%(interface.host, interface.port, network.blockchain.height)
|
||||||
else:
|
else:
|
||||||
status = "Not connected"
|
status = "Not connected"
|
||||||
else:
|
else:
|
||||||
|
@ -279,7 +258,7 @@ def run_network_dialog( wallet, parent ):
|
||||||
status = "Please choose a server.\nSelect cancel if you are offline."
|
status = "Please choose a server.\nSelect cancel if you are offline."
|
||||||
|
|
||||||
server = interface.server
|
server = interface.server
|
||||||
servers = wallet.network.get_servers()
|
servers = network.get_servers()
|
||||||
|
|
||||||
dialog = gtk.MessageDialog( parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
|
dialog = gtk.MessageDialog( parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||||
gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, status)
|
gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, status)
|
||||||
|
@ -510,9 +489,10 @@ class ElectrumWindow:
|
||||||
def show_message(self, msg):
|
def show_message(self, msg):
|
||||||
show_message(msg, self.window)
|
show_message(msg, self.window)
|
||||||
|
|
||||||
def __init__(self, wallet, config):
|
def __init__(self, wallet, config, network):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.wallet = wallet
|
self.wallet = wallet
|
||||||
|
self.network = network
|
||||||
self.funds_error = False # True if not enough funds
|
self.funds_error = False # True if not enough funds
|
||||||
self.num_zeros = int(self.config.get('num_zeros',0))
|
self.num_zeros = int(self.config.get('num_zeros',0))
|
||||||
|
|
||||||
|
@ -547,7 +527,7 @@ class ElectrumWindow:
|
||||||
self.status_image.show()
|
self.status_image.show()
|
||||||
|
|
||||||
self.network_button = gtk.Button()
|
self.network_button = gtk.Button()
|
||||||
self.network_button.connect("clicked", lambda x: run_network_dialog(self.wallet, self.window) )
|
self.network_button.connect("clicked", lambda x: run_network_dialog(self.network, self.window) )
|
||||||
self.network_button.add(self.status_image)
|
self.network_button.add(self.status_image)
|
||||||
self.network_button.set_relief(gtk.RELIEF_NONE)
|
self.network_button.set_relief(gtk.RELIEF_NONE)
|
||||||
self.network_button.show()
|
self.network_button.show()
|
||||||
|
@ -601,7 +581,7 @@ class ElectrumWindow:
|
||||||
self.context_id = self.status_bar.get_context_id("statusbar")
|
self.context_id = self.status_bar.get_context_id("statusbar")
|
||||||
self.update_status_bar()
|
self.update_status_bar()
|
||||||
|
|
||||||
self.wallet.network.register_callback('updated', self.update_callback)
|
self.network.register_callback('updated', self.update_callback)
|
||||||
|
|
||||||
|
|
||||||
def update_status_bar_thread():
|
def update_status_bar_thread():
|
||||||
|
@ -1107,17 +1087,17 @@ class ElectrumWindow:
|
||||||
return vbox
|
return vbox
|
||||||
|
|
||||||
def update_status_bar(self):
|
def update_status_bar(self):
|
||||||
interface = self.wallet.network.interface
|
interface = self.network.interface
|
||||||
if self.funds_error:
|
if self.funds_error:
|
||||||
text = "Not enough funds"
|
text = "Not enough funds"
|
||||||
elif interface and interface.is_connected:
|
elif interface and interface.is_connected:
|
||||||
self.network_button.set_tooltip_text("Connected to %s:%d.\n%d blocks"%(interface.host, interface.port, self.wallet.network.blockchain.height))
|
self.network_button.set_tooltip_text("Connected to %s:%d.\n%d blocks"%(interface.host, interface.port, self.network.blockchain.height))
|
||||||
if not self.wallet.up_to_date:
|
if not self.wallet.up_to_date:
|
||||||
self.status_image.set_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_MENU)
|
self.status_image.set_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_MENU)
|
||||||
text = "Synchronizing..."
|
text = "Synchronizing..."
|
||||||
else:
|
else:
|
||||||
self.status_image.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_MENU)
|
self.status_image.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_MENU)
|
||||||
self.network_button.set_tooltip_text("Connected to %s:%d.\n%d blocks"%(interface.host, interface.port, self.wallet.network.blockchain.height))
|
self.network_button.set_tooltip_text("Connected to %s:%d.\n%d blocks"%(interface.host, interface.port, self.network.blockchain.height))
|
||||||
c, u = self.wallet.get_balance()
|
c, u = self.wallet.get_balance()
|
||||||
text = "Balance: %s "%( format_satoshis(c,False,self.num_zeros) )
|
text = "Balance: %s "%( format_satoshis(c,False,self.num_zeros) )
|
||||||
if u: text += "[%s unconfirmed]"%( format_satoshis(u,True,self.num_zeros).strip() )
|
if u: text += "[%s unconfirmed]"%( format_satoshis(u,True,self.num_zeros).strip() )
|
||||||
|
@ -1133,7 +1113,7 @@ class ElectrumWindow:
|
||||||
self.update_history_tab()
|
self.update_history_tab()
|
||||||
self.update_receiving_tab()
|
self.update_receiving_tab()
|
||||||
# addressbook too...
|
# addressbook too...
|
||||||
self.info.set_text( self.wallet.network.banner )
|
self.info.set_text( self.network.banner )
|
||||||
self.wallet_updated = False
|
self.wallet_updated = False
|
||||||
|
|
||||||
def update_receiving_tab(self):
|
def update_receiving_tab(self):
|
||||||
|
@ -1279,32 +1259,56 @@ class ElectrumGui():
|
||||||
def __init__(self, config, network):
|
def __init__(self, config, network):
|
||||||
self.network = network
|
self.network = network
|
||||||
self.config = config
|
self.config = config
|
||||||
storage = WalletStorage(config)
|
|
||||||
if not storage.file_exists:
|
|
||||||
print "Wallet not found. try 'electrum create'"
|
|
||||||
exit()
|
|
||||||
|
|
||||||
self.wallet = Wallet(storage)
|
|
||||||
self.wallet.start_threads(network)
|
|
||||||
|
|
||||||
|
|
||||||
def main(self, url=None):
|
def main(self, url=None):
|
||||||
ew = ElectrumWindow(self.wallet, self.config)
|
|
||||||
if url: ew.set_url(url)
|
storage = WalletStorage(self.config)
|
||||||
|
if not storage.file_exists:
|
||||||
|
action = self.restore_or_create()
|
||||||
|
if not action:
|
||||||
|
exit()
|
||||||
|
self.wallet = wallet = Wallet(storage)
|
||||||
|
gap = self.config.get('gap_limit', 5)
|
||||||
|
if gap != 5:
|
||||||
|
wallet.gap_limit = gap
|
||||||
|
wallet.storage.put('gap_limit', gap, True)
|
||||||
|
|
||||||
|
self.wallet.start_threads(self.network)
|
||||||
|
|
||||||
|
if action == 'create':
|
||||||
|
wallet.init_seed(None)
|
||||||
|
wallet.save_seed()
|
||||||
|
wallet.create_accounts()
|
||||||
|
wallet.synchronize() # generate first addresses offline
|
||||||
|
elif action == 'restore':
|
||||||
|
seed = self.seed_dialog()
|
||||||
|
wallet.init_seed(seed)
|
||||||
|
wallet.save_seed()
|
||||||
|
self.restore_wallet(wallet)
|
||||||
|
|
||||||
|
else:
|
||||||
|
exit()
|
||||||
|
else:
|
||||||
|
self.wallet = Wallet(storage)
|
||||||
|
self.wallet.start_threads(self.network)
|
||||||
|
|
||||||
|
w = ElectrumWindow(self.wallet, self.config, self.network)
|
||||||
|
if url: w.set_url(url)
|
||||||
gtk.main()
|
gtk.main()
|
||||||
|
|
||||||
def restore_or_create(self):
|
def restore_or_create(self):
|
||||||
return restore_create_dialog(self.wallet)
|
return restore_create_dialog()
|
||||||
|
|
||||||
def seed_dialog(self):
|
def seed_dialog(self):
|
||||||
return run_recovery_dialog( self.wallet )
|
return run_recovery_dialog()
|
||||||
|
|
||||||
def verify_seed(self):
|
def verify_seed(self):
|
||||||
self.wallet.save_seed()
|
self.wallet.save_seed()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def network_dialog(self):
|
def network_dialog(self):
|
||||||
return run_network_dialog( self.wallet, parent=None )
|
return run_network_dialog( self.network, parent=None )
|
||||||
|
|
||||||
def show_seed(self):
|
def show_seed(self):
|
||||||
show_seed_dialog(self.wallet, None, None)
|
show_seed_dialog(self.wallet, None, None)
|
||||||
|
@ -1312,8 +1316,7 @@ class ElectrumGui():
|
||||||
def password_dialog(self):
|
def password_dialog(self):
|
||||||
change_password_dialog(self.wallet, None, None)
|
change_password_dialog(self.wallet, None, None)
|
||||||
|
|
||||||
def restore_wallet(self):
|
def restore_wallet(self, wallet):
|
||||||
wallet = self.wallet
|
|
||||||
|
|
||||||
dialog = gtk.MessageDialog(
|
dialog = gtk.MessageDialog(
|
||||||
parent = None,
|
parent = None,
|
||||||
|
@ -1323,8 +1326,7 @@ class ElectrumGui():
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
|
||||||
def recover_thread( wallet, dialog ):
|
def recover_thread( wallet, dialog ):
|
||||||
while not wallet.is_up_to_date():
|
wallet.restore(lambda x:x)
|
||||||
time.sleep(0.1)
|
|
||||||
gobject.idle_add( dialog.destroy )
|
gobject.idle_add( dialog.destroy )
|
||||||
|
|
||||||
thread.start_new_thread( recover_thread, ( wallet, dialog ) )
|
thread.start_new_thread( recover_thread, ( wallet, dialog ) )
|
||||||
|
@ -1334,5 +1336,4 @@ class ElectrumGui():
|
||||||
if not wallet.is_found():
|
if not wallet.is_found():
|
||||||
show_message("No transactions found for this seed")
|
show_message("No transactions found for this seed")
|
||||||
|
|
||||||
wallet.save()
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -90,8 +90,7 @@ class ElectrumGui:
|
||||||
exit()
|
exit()
|
||||||
else:
|
else:
|
||||||
wallet = Wallet(storage)
|
wallet = Wallet(storage)
|
||||||
|
wallet.start_threads(self.network)
|
||||||
wallet.start_threads(self.network)
|
|
||||||
|
|
||||||
self.main_window = w = ElectrumWindow(self.config, self.network)
|
self.main_window = w = ElectrumWindow(self.config, self.network)
|
||||||
|
|
||||||
|
|
|
@ -303,36 +303,7 @@ class InstallWizard(QDialog):
|
||||||
|
|
||||||
if action == 'restore':
|
if action == 'restore':
|
||||||
|
|
||||||
def wait_for_wallet():
|
self.waiting_dialog(lambda: wallet.restore(self.waiting_label.setText))
|
||||||
wallet.set_up_to_date(False)
|
|
||||||
while not wallet.is_up_to_date():
|
|
||||||
msg = "%s\n%s %d\n%s %.1f"%(_("Please wait..."),_("Addresses generated:"),len(wallet.addresses(True)),_("Kilobytes received:"), self.network.interface.bytes_received/1024.)
|
|
||||||
self.waiting_label.setText(msg)
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
def wait_for_network():
|
|
||||||
while not self.network.interface.is_connected:
|
|
||||||
msg = "%s \n" % (_("Connecting..."))
|
|
||||||
self.waiting_label.setText(msg)
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
def restore():
|
|
||||||
# wait until we are connected, because the user might have selected another server
|
|
||||||
wait_for_network()
|
|
||||||
|
|
||||||
# try to restore old account
|
|
||||||
wallet.create_old_account()
|
|
||||||
wait_for_wallet()
|
|
||||||
|
|
||||||
if wallet.is_found():
|
|
||||||
wallet.seed_version = 4
|
|
||||||
wallet.storage.put('seed_version', wallet.seed_version, True)
|
|
||||||
else:
|
|
||||||
wallet.accounts.pop(0)
|
|
||||||
wallet.create_accounts()
|
|
||||||
wait_for_wallet()
|
|
||||||
|
|
||||||
self.waiting_dialog(restore)
|
|
||||||
|
|
||||||
if wallet.is_found():
|
if wallet.is_found():
|
||||||
QMessageBox.information(None, _('Information'), _("Recovery successful"), _('OK'))
|
QMessageBox.information(None, _('Information'), _("Recovery successful"), _('OK'))
|
||||||
|
|
|
@ -1409,6 +1409,42 @@ class Wallet:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def restore(self, callback):
|
||||||
|
from i18n import _
|
||||||
|
def wait_for_wallet():
|
||||||
|
self.set_up_to_date(False)
|
||||||
|
while not self.is_up_to_date():
|
||||||
|
msg = "%s\n%s %d\n%s %.1f"%(
|
||||||
|
_("Please wait..."),
|
||||||
|
_("Addresses generated:"),
|
||||||
|
len(self.addresses(True)),_("Kilobytes received:"),
|
||||||
|
self.network.interface.bytes_received/1024.)
|
||||||
|
|
||||||
|
apply(callback, (msg,))
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
def wait_for_network():
|
||||||
|
while not self.network.interface.is_connected:
|
||||||
|
msg = "%s \n" % (_("Connecting..."))
|
||||||
|
apply(callback, (msg,))
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
# wait until we are connected, because the user might have selected another server
|
||||||
|
wait_for_network()
|
||||||
|
|
||||||
|
# try to restore old account
|
||||||
|
self.create_old_account()
|
||||||
|
wait_for_wallet()
|
||||||
|
|
||||||
|
if self.is_found():
|
||||||
|
self.seed_version = 4
|
||||||
|
self.storage.put('seed_version', wallet.seed_version, True)
|
||||||
|
else:
|
||||||
|
self.accounts.pop(0)
|
||||||
|
self.create_accounts()
|
||||||
|
wait_for_wallet()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WalletSynchronizer(threading.Thread):
|
class WalletSynchronizer(threading.Thread):
|
||||||
|
|
Loading…
Reference in New Issue