electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit cf1f533613549e918bae5c73ae8a8d243fe8b933
parent 2385cc3ad8f1a72cafca42137272735bd1fdc2a1
Author: thomasv <thomasv@gitorious>
Date:   Tue, 20 Nov 2012 15:30:46 +0100

allow offline creation/recovery within the gui

Diffstat:
Melectrum | 49+++++++++++++++++++++++++++++++------------------
Mlib/gui.py | 118+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mlib/gui_qt.py | 73++++++++++++++++++++++++++++++++++++++-----------------------------------
Mlib/interface.py | 2++
4 files changed, 133 insertions(+), 109 deletions(-)

diff --git a/electrum b/electrum @@ -197,36 +197,49 @@ if __name__ == '__main__': else: sys.exit("Error: Unknown GUI: " + pref_gui ) + gui = gui.ElectrumGui(wallet, config) + interface = Interface(config, True) + wallet.interface = interface interface.start() interface.send([('server.peers.subscribe',[])]) - wallet.interface = interface - - gui = gui.ElectrumGui(wallet, config) + found = config.wallet_file_exists + if not found: + a = gui.restore_or_create() + if not a: exit() + + if a =='create': + wallet.new_seed(None) + wallet.init_mpk( wallet.seed ) + else: + # ask for seed and gap. + if not gui.seed_dialog(): exit() + wallet.init_mpk( wallet.seed ) + + # select a server. + s = gui.network_dialog() + if s is None: + gui.create_wallet() + + interface.register_callback('peers', gui.server_list_changed) verifier = WalletVerifier(interface, config) wallet.set_verifier(verifier) - WalletSynchronizer(wallet, config).start() - try: - found = config.wallet_file_exists - if not found: - found = gui.restore_or_create() - except SystemExit(e): - exit(e) - except BaseException(e): - import traceback - traceback.print_exc(file=sys.stdout) - #gui.show_message(e.message) - exit(1) - if not found: - exit(1) + if not found and a == 'restore' and s is not None: + try: + ok = gui.restore_wallet() + except: + import traceback + traceback.print_exc(file=sys.stdout) + exit() - verifier.start() + if not ok: exit() + verifier.start() gui.main(url) wallet.save() sys.exit(0) diff --git a/lib/gui.py b/lib/gui.py @@ -97,58 +97,8 @@ def restore_create_dialog(wallet): dialog.destroy() if r==2: return False - - is_recovery = (r==1) - - # ask for the server. - if not run_network_dialog( wallet, parent=None ): return False - - if not is_recovery: - - wallet.new_seed(None) - # generate first key - wallet.init_mpk( wallet.seed ) - wallet.up_to_date_event.clear() - wallet.update() + return 'restore' if r==1 else 'create' - # run a dialog indicating the seed, ask the user to remember it - show_seed_dialog(wallet, None, None) - - #ask for password - change_password_dialog(wallet, None, None) - else: - # ask for seed and gap. - run_recovery_dialog( wallet ) - - dialog = gtk.MessageDialog( - parent = None, - flags = gtk.DIALOG_MODAL, - buttons = gtk.BUTTONS_CANCEL, - message_format = "Please wait..." ) - dialog.show() - - def recover_thread( wallet, dialog ): - wallet.init_mpk( wallet.seed ) # not encrypted at this point - wallet.up_to_date_event.clear() - wallet.update() - - if wallet.is_found(): - # history and addressbook - wallet.update_tx_history() - wallet.fill_addressbook() - print "Recovery successful" - - gobject.idle_add( dialog.destroy ) - - thread.start_new_thread( recover_thread, ( wallet, dialog ) ) - r = dialog.run() - dialog.destroy() - if r==gtk.RESPONSE_CANCEL: return False - if not wallet.is_found: - show_message("No transactions found for this seed") - - wallet.save() - return True def run_recovery_dialog(wallet): @@ -197,12 +147,13 @@ def run_recovery_dialog(wallet): dialog.destroy() if r==gtk.RESPONSE_CANCEL: - sys.exit(1) + return False + try: gap = int(gap) except: show_message("error") - sys.exit(1) + return False try: seed.decode('hex') @@ -211,11 +162,12 @@ def run_recovery_dialog(wallet): seed = mnemonic.mn_decode( seed.split(' ') ) if not seed: show_message("no seed") - sys.exit(1) + return False wallet.seed = seed wallet.gap_limit = gap wallet.save() + return True @@ -328,7 +280,7 @@ def run_network_dialog( wallet, parent ): status = "Not connected" else: import random - status = "Please choose a server." + status = "Please choose a server.\nSelect cancel if you are offline." server = interface.server plist, servers_list = interface.get_servers_list() @@ -575,6 +527,7 @@ class ElectrumWindow: self.window.set_border_width(0) self.window.connect('mykeypress', gtk.main_quit) self.window.set_default_size(720, 350) + self.wallet_updated = False vbox = gtk.VBox() @@ -651,7 +604,6 @@ class ElectrumWindow: self.context_id = self.status_bar.get_context_id("statusbar") self.update_status_bar() - self.wallet_updated = False self.wallet.interface.register_callback('updated', self.update_callback) @@ -1302,3 +1254,57 @@ class ElectrumGui(): def server_list_changed(self): pass + + def seed_dialog(self): + # ask for seed and gap. + return run_recovery_dialog( self.wallet ) + + def network_dialog(self): + return run_network_dialog( self.wallet, parent=None ) + + def create_wallet(self): + wallet = self.wallet + wallet.new_seed(None) + # generate first key + wallet.init_mpk( wallet.seed ) + wallet.synchronize() + #wallet.up_to_date_event.clear() + #wallet.update() + # run a dialog indicating the seed, ask the user to remember it + show_seed_dialog(wallet, None, None) + #ask for password + change_password_dialog(wallet, None, None) + + def restore_wallet(self): + wallet = self.wallet + + dialog = gtk.MessageDialog( + parent = None, + flags = gtk.DIALOG_MODAL, + buttons = gtk.BUTTONS_CANCEL, + message_format = "Please wait..." ) + dialog.show() + wallet.save() + + def recover_thread( wallet, dialog ): + wallet.init_mpk( wallet.seed ) # not encrypted at this point + wallet.up_to_date_event.clear() + wallet.update() + + if wallet.is_found(): + # history and addressbook + wallet.update_tx_history() + wallet.fill_addressbook() + print "Recovery successful" + + gobject.idle_add( dialog.destroy ) + + thread.start_new_thread( recover_thread, ( wallet, dialog ) ) + r = dialog.run() + dialog.destroy() + if r==gtk.RESPONSE_CANCEL: return False + if not wallet.is_found: + show_message("No transactions found for this seed") + + wallet.save() + return True diff --git a/lib/gui_qt.py b/lib/gui_qt.py @@ -1367,11 +1367,13 @@ class ElectrumWindow(QMainWindow): status = _("Connected to")+" %s\n%d blocks"%(interface.host, wallet.verifier.height) else: status = _("Not connected") + server = interface.server else: import random - status = _("Please choose a server.") + status = _("Please choose a server.") + "\n" + _("Select 'Cancel' if you are offline.") + server = None + interface.proxy = None - server = interface.server plist, servers_list = interface.get_servers_list() d = QDialog(parent) @@ -1414,8 +1416,6 @@ class ElectrumWindow(QMainWindow): grid.addWidget(server_host, 0, 2) grid.addWidget(server_port, 0, 3) - host, port, protocol = server.split(':') - def change_protocol(p): protocol = protocol_letters[p] host = unicode(server_host.text()) @@ -1465,7 +1465,10 @@ class ElectrumWindow(QMainWindow): server_protocol.model().setData(j, QtCore.QVariant(0,False), QtCore.Qt.UserRole-1) - change_server(host,protocol) + if server: + host, port, protocol = server.split(':') + change_server(host,protocol) + servers_list_widget.connect(servers_list_widget, SIGNAL('itemClicked(QTreeWidgetItem*, int)'), lambda x: change_server(unicode(x.text(0)))) grid.addWidget(servers_list_widget, 1, 1, 1, 3) @@ -1541,16 +1544,30 @@ class ElectrumGui: def restore_or_create(self): - msg = _("Wallet file not found.")+"\n"+_("Do you want to create a new wallet, or to restore an existing one?") r = QMessageBox.question(None, _('Message'), msg, _('Create'), _('Restore'), _('Cancel'), 0, 2) - if r==2: return False + if r==2: return None + return 'restore' if r==1 else 'create' + + def seed_dialog(self): + return ElectrumWindow.seed_dialog( self.wallet ) + + def network_dialog(self): + return ElectrumWindow.network_dialog( self.wallet, parent=None ) - is_recovery = (r==1) + def create_wallet(self): wallet = self.wallet - # ask for the server. - if not ElectrumWindow.network_dialog( wallet, parent=None ): return False + # generate the first addresses + wallet.synchronize() + # run a dialog indicating the seed, ask the user to remember it + ElectrumWindow.show_seed_dialog(wallet) + # ask for password + ElectrumWindow.change_password_dialog(wallet) + wallet.save() + + def restore_wallet(self): + wallet = self.wallet # wait until we are connected, because the user might have selected another server if not wallet.interface.is_connected: waiting = lambda: False if wallet.interface.is_connected else "connecting...\n" @@ -1559,32 +1576,18 @@ class ElectrumGui: waiting = lambda: False if wallet.up_to_date else "Please wait...\nAddresses generated: %d\nKilobytes received: %.1f"\ %(len(wallet.all_addresses()), wallet.interface.bytes_received/1024.) - if not is_recovery: - wallet.new_seed(None) - wallet.init_mpk( wallet.seed ) - wallet.up_to_date_event.clear() - wallet.up_to_date = False - wallet.interface.poke('synchronizer') - waiting_dialog(waiting) - # run a dialog indicating the seed, ask the user to remember it - ElectrumWindow.show_seed_dialog(wallet) - #ask for password - ElectrumWindow.change_password_dialog(wallet) + wallet.up_to_date_event.clear() + wallet.up_to_date = False + wallet.interface.poke('synchronizer') + waiting_dialog(waiting) + if wallet.is_found(): + # history and addressbook + wallet.fill_addressbook() + print "Recovery successful" + wallet.save() else: - # ask for seed and gap. - if not ElectrumWindow.seed_dialog( wallet ): return False - wallet.init_mpk( wallet.seed ) - wallet.up_to_date_event.clear() - wallet.up_to_date = False - wallet.interface.poke('synchronizer') - waiting_dialog(waiting) - if wallet.is_found(): - # history and addressbook - wallet.fill_addressbook() - print "Recovery successful" - wallet.save() - else: - QMessageBox.information(None, _('Error'), _("No transactions found for this seed"), _('OK')) + QMessageBox.information(None, _('Error'), _("No transactions found for this seed"), _('OK')) + return False wallet.save() return True diff --git a/lib/interface.py b/lib/interface.py @@ -352,6 +352,8 @@ class Interface(threading.Thread): def __init__(self, config=None, loop=False): + self.server = None + self.proxy = None if config is None: from simple_config import SimpleConfig