allow offline creation/recovery within the gui
This commit is contained in:
parent
2385cc3ad8
commit
cf1f533613
41
electrum
41
electrum
|
@ -197,36 +197,49 @@ if __name__ == '__main__':
|
||||||
else:
|
else:
|
||||||
sys.exit("Error: Unknown GUI: " + pref_gui )
|
sys.exit("Error: Unknown GUI: " + pref_gui )
|
||||||
|
|
||||||
|
gui = gui.ElectrumGui(wallet, config)
|
||||||
|
|
||||||
interface = Interface(config, True)
|
interface = Interface(config, True)
|
||||||
|
wallet.interface = interface
|
||||||
interface.start()
|
interface.start()
|
||||||
interface.send([('server.peers.subscribe',[])])
|
interface.send([('server.peers.subscribe',[])])
|
||||||
|
|
||||||
wallet.interface = interface
|
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()
|
||||||
|
|
||||||
|
|
||||||
gui = gui.ElectrumGui(wallet, config)
|
|
||||||
interface.register_callback('peers', gui.server_list_changed)
|
interface.register_callback('peers', gui.server_list_changed)
|
||||||
|
|
||||||
verifier = WalletVerifier(interface, config)
|
verifier = WalletVerifier(interface, config)
|
||||||
wallet.set_verifier(verifier)
|
wallet.set_verifier(verifier)
|
||||||
|
|
||||||
WalletSynchronizer(wallet, config).start()
|
WalletSynchronizer(wallet, config).start()
|
||||||
|
|
||||||
|
if not found and a == 'restore' and s is not None:
|
||||||
try:
|
try:
|
||||||
found = config.wallet_file_exists
|
ok = gui.restore_wallet()
|
||||||
if not found:
|
except:
|
||||||
found = gui.restore_or_create()
|
|
||||||
except SystemExit(e):
|
|
||||||
exit(e)
|
|
||||||
except BaseException(e):
|
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc(file=sys.stdout)
|
traceback.print_exc(file=sys.stdout)
|
||||||
#gui.show_message(e.message)
|
exit()
|
||||||
exit(1)
|
|
||||||
|
|
||||||
if not found:
|
if not ok: exit()
|
||||||
exit(1)
|
|
||||||
|
|
||||||
verifier.start()
|
verifier.start()
|
||||||
|
|
||||||
gui.main(url)
|
gui.main(url)
|
||||||
wallet.save()
|
wallet.save()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
118
lib/gui.py
118
lib/gui.py
|
@ -97,58 +97,8 @@ def restore_create_dialog(wallet):
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
|
|
||||||
if r==2: return False
|
if r==2: return False
|
||||||
|
return 'restore' if r==1 else 'create'
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
||||||
# 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):
|
def run_recovery_dialog(wallet):
|
||||||
|
@ -197,12 +147,13 @@ def run_recovery_dialog(wallet):
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
|
|
||||||
if r==gtk.RESPONSE_CANCEL:
|
if r==gtk.RESPONSE_CANCEL:
|
||||||
sys.exit(1)
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
gap = int(gap)
|
gap = int(gap)
|
||||||
except:
|
except:
|
||||||
show_message("error")
|
show_message("error")
|
||||||
sys.exit(1)
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
seed.decode('hex')
|
seed.decode('hex')
|
||||||
|
@ -211,11 +162,12 @@ def run_recovery_dialog(wallet):
|
||||||
seed = mnemonic.mn_decode( seed.split(' ') )
|
seed = mnemonic.mn_decode( seed.split(' ') )
|
||||||
if not seed:
|
if not seed:
|
||||||
show_message("no seed")
|
show_message("no seed")
|
||||||
sys.exit(1)
|
return False
|
||||||
|
|
||||||
wallet.seed = seed
|
wallet.seed = seed
|
||||||
wallet.gap_limit = gap
|
wallet.gap_limit = gap
|
||||||
wallet.save()
|
wallet.save()
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -328,7 +280,7 @@ def run_network_dialog( wallet, parent ):
|
||||||
status = "Not connected"
|
status = "Not connected"
|
||||||
else:
|
else:
|
||||||
import random
|
import random
|
||||||
status = "Please choose a server."
|
status = "Please choose a server.\nSelect cancel if you are offline."
|
||||||
|
|
||||||
server = interface.server
|
server = interface.server
|
||||||
plist, servers_list = interface.get_servers_list()
|
plist, servers_list = interface.get_servers_list()
|
||||||
|
@ -575,6 +527,7 @@ class ElectrumWindow:
|
||||||
self.window.set_border_width(0)
|
self.window.set_border_width(0)
|
||||||
self.window.connect('mykeypress', gtk.main_quit)
|
self.window.connect('mykeypress', gtk.main_quit)
|
||||||
self.window.set_default_size(720, 350)
|
self.window.set_default_size(720, 350)
|
||||||
|
self.wallet_updated = False
|
||||||
|
|
||||||
vbox = gtk.VBox()
|
vbox = gtk.VBox()
|
||||||
|
|
||||||
|
@ -651,7 +604,6 @@ 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_updated = False
|
|
||||||
self.wallet.interface.register_callback('updated', self.update_callback)
|
self.wallet.interface.register_callback('updated', self.update_callback)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1302,3 +1254,57 @@ class ElectrumGui():
|
||||||
|
|
||||||
def server_list_changed(self):
|
def server_list_changed(self):
|
||||||
pass
|
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
|
||||||
|
|
|
@ -1367,11 +1367,13 @@ class ElectrumWindow(QMainWindow):
|
||||||
status = _("Connected to")+" %s\n%d blocks"%(interface.host, wallet.verifier.height)
|
status = _("Connected to")+" %s\n%d blocks"%(interface.host, wallet.verifier.height)
|
||||||
else:
|
else:
|
||||||
status = _("Not connected")
|
status = _("Not connected")
|
||||||
|
server = interface.server
|
||||||
else:
|
else:
|
||||||
import random
|
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()
|
plist, servers_list = interface.get_servers_list()
|
||||||
|
|
||||||
d = QDialog(parent)
|
d = QDialog(parent)
|
||||||
|
@ -1414,8 +1416,6 @@ class ElectrumWindow(QMainWindow):
|
||||||
grid.addWidget(server_host, 0, 2)
|
grid.addWidget(server_host, 0, 2)
|
||||||
grid.addWidget(server_port, 0, 3)
|
grid.addWidget(server_port, 0, 3)
|
||||||
|
|
||||||
host, port, protocol = server.split(':')
|
|
||||||
|
|
||||||
def change_protocol(p):
|
def change_protocol(p):
|
||||||
protocol = protocol_letters[p]
|
protocol = protocol_letters[p]
|
||||||
host = unicode(server_host.text())
|
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)
|
server_protocol.model().setData(j, QtCore.QVariant(0,False), QtCore.Qt.UserRole-1)
|
||||||
|
|
||||||
|
|
||||||
|
if server:
|
||||||
|
host, port, protocol = server.split(':')
|
||||||
change_server(host,protocol)
|
change_server(host,protocol)
|
||||||
|
|
||||||
servers_list_widget.connect(servers_list_widget, SIGNAL('itemClicked(QTreeWidgetItem*, int)'), lambda x: change_server(unicode(x.text(0))))
|
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)
|
grid.addWidget(servers_list_widget, 1, 1, 1, 3)
|
||||||
|
|
||||||
|
@ -1541,16 +1544,30 @@ class ElectrumGui:
|
||||||
|
|
||||||
|
|
||||||
def restore_or_create(self):
|
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?")
|
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)
|
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'
|
||||||
|
|
||||||
is_recovery = (r==1)
|
def seed_dialog(self):
|
||||||
|
return ElectrumWindow.seed_dialog( self.wallet )
|
||||||
|
|
||||||
|
def network_dialog(self):
|
||||||
|
return ElectrumWindow.network_dialog( self.wallet, parent=None )
|
||||||
|
|
||||||
|
def create_wallet(self):
|
||||||
wallet = self.wallet
|
wallet = self.wallet
|
||||||
# ask for the server.
|
# generate the first addresses
|
||||||
if not ElectrumWindow.network_dialog( wallet, parent=None ): return False
|
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
|
# wait until we are connected, because the user might have selected another server
|
||||||
if not wallet.interface.is_connected:
|
if not wallet.interface.is_connected:
|
||||||
waiting = lambda: False if wallet.interface.is_connected else "connecting...\n"
|
waiting = lambda: False if wallet.interface.is_connected else "connecting...\n"
|
||||||
|
@ -1559,21 +1576,6 @@ class ElectrumGui:
|
||||||
waiting = lambda: False if wallet.up_to_date else "Please wait...\nAddresses generated: %d\nKilobytes received: %.1f"\
|
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.)
|
%(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)
|
|
||||||
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_event.clear()
|
||||||
wallet.up_to_date = False
|
wallet.up_to_date = False
|
||||||
wallet.interface.poke('synchronizer')
|
wallet.interface.poke('synchronizer')
|
||||||
|
@ -1585,6 +1587,7 @@ class ElectrumGui:
|
||||||
wallet.save()
|
wallet.save()
|
||||||
else:
|
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()
|
wallet.save()
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -352,6 +352,8 @@ class Interface(threading.Thread):
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, config=None, loop=False):
|
def __init__(self, config=None, loop=False):
|
||||||
|
self.server = None
|
||||||
|
self.proxy = None
|
||||||
|
|
||||||
if config is None:
|
if config is None:
|
||||||
from simple_config import SimpleConfig
|
from simple_config import SimpleConfig
|
||||||
|
|
Loading…
Reference in New Issue