def __init__(self, _config, _network, plugins): global wallet, network, contacts, config network = _network config = _config network.register_callback('updated', update_callback) network.register_callback('connected', update_callback) network.register_callback('disconnected', update_callback) network.register_callback('disconnecting', update_callback) contacts = util.StoreDict(config, 'contacts') storage = WalletStorage(config.get_wallet_path()) if not storage.file_exists: action = self.restore_or_create() if not action: exit() password = droid.dialogGetPassword('Choose a password').result if password: password2 = droid.dialogGetPassword('Confirm password').result if password != password2: modal_dialog('Error', 'passwords do not match') exit() else: # set to None if it's an empty string password = None if action == 'create': wallet = Wallet(storage) seed = wallet.make_seed() modal_dialog('Your seed is:', seed) wallet.add_seed(seed, password) wallet.create_master_keys(password) wallet.create_main_account(password) elif action == 'restore': seed = self.seed_dialog() if not seed: exit() if not Wallet.is_seed(seed): exit() wallet = Wallet.from_seed(seed, password, storage) else: exit() msg = "Creating wallet" if action == 'create' else "Restoring wallet" droid.dialogCreateSpinnerProgress("Electrum", msg) droid.dialogShow() wallet.start_threads(network) if action == 'restore': wallet.wait_until_synchronized() else: wallet.synchronize() droid.dialogDismiss() droid.vibrate() else: wallet = Wallet(storage) wallet.start_threads(network)
def __init__(self, _config, _network, plugins): global wallet, network, contacts, config network = _network config = _config network.register_callback('updated', update_callback) network.register_callback('connected', update_callback) network.register_callback('disconnected', update_callback) network.register_callback('disconnecting', update_callback) contacts = util.StoreDict(config, 'contacts') storage = WalletStorage(config.get_wallet_path()) if not storage.file_exists: action = self.restore_or_create() if not action: exit() password = droid.dialogGetPassword('Choose a password').result if password: password2 = droid.dialogGetPassword('Confirm password').result if password != password2: modal_dialog('Error', 'passwords do not match') exit() else: # set to None if it's an empty string password = None if action == 'create': wallet = Wallet(storage) seed = wallet.make_seed() modal_dialog('Your seed is:', seed) wallet.add_seed(seed, password) wallet.create_master_keys(password) wallet.create_main_account(password) elif action == 'restore': seed = self.seed_dialog() if not seed: exit() if not Wallet.is_seed(seed): exit() wallet = Wallet.from_seed(seed, password, storage) else: exit() msg = "Creating wallet" if action == 'create' else "Restoring wallet" droid.dialogCreateSpinnerProgress("Electrum", msg) droid.dialogShow() wallet.start_threads(network) if action == 'restore': wallet.restore(lambda x: None) else: wallet.synchronize() droid.dialogDismiss() droid.vibrate() else: wallet = Wallet(storage) wallet.start_threads(network)
def __init__(self, _config, _network, daemon, plugins): global wallet, network, contacts, config network = _network config = _config network.register_callback(update_callback, ["updated"]) contacts = util.StoreDict(config, "contacts") storage = WalletStorage(config.get_wallet_path()) if not storage.file_exists: action = self.restore_or_create() if not action: exit() password = droid.dialogGetPassword("Choose a password").result if password: password2 = droid.dialogGetPassword("Confirm password").result if password != password2: modal_dialog("Error", "passwords do not match") exit() else: # set to None if it's an empty string password = None if action == "create": wallet = Wallet(storage) seed = wallet.make_seed() modal_dialog("Your seed is:", seed) wallet.add_seed(seed, password) wallet.create_master_keys(password) wallet.create_main_account(password) elif action == "restore": seed = self.seed_dialog() if not seed: exit() if not Wallet.is_seed(seed): exit() wallet = Wallet.from_seed(seed, password, storage) else: exit() msg = "Creating wallet" if action == "create" else "Restoring wallet" droid.dialogCreateSpinnerProgress("Electrum", msg) droid.dialogShow() wallet.start_threads(network) if action == "restore": wallet.wait_until_synchronized() else: wallet.synchronize() droid.dialogDismiss() droid.vibrate() else: wallet = Wallet(storage) wallet.start_threads(network)
def create_or_load_wallet(self): wallet = Wallet(self.storage) if not self.storage.file_exists: try: seed = wallet.make_seed() wallet.init_seed(seed) wallet.save_seed(self.__password__()) wallet.synchronize() config_entry = Configuration.objects.get() config_entry.wallet_seed = str(seed) config_entry.save() except Exception: exc_info = sys.exc_info() message = str(exc_info[0]) + ' - ' + str(exc_info[1]) utils.log_error('btc processor create or load wallet', message) return wallet
def create_or_load_wallet(self): wallet = Wallet(self.storage) if not self.storage.file_exists: try: seed = wallet.make_seed() wallet.init_seed(seed) wallet.save_seed(self.__password__()) wallet.synchronize() config_entry = Configuration.objects.get() config_entry.wallet_seed = str(seed) config_entry.save() except Exception: exc_info = sys.exc_info() message = str(exc_info[0]) + ' - ' + str(exc_info[1]) utils.log_error('btc processor create or load wallet', message) return wallet
def __init__(self): global wallet self.qr_data = None storage = WalletStorage( {'wallet_path': '/sdcard/electrum/authenticator'}) if not storage.file_exists: action = self.restore_or_create() if not action: exit() password = droid.dialogGetPassword('Choose a password').result if password: password2 = droid.dialogGetPassword('Confirm password').result if password != password2: modal_dialog('Error', 'Passwords do not match') exit() else: password = None if action == 'create': wallet = Wallet(storage) seed = wallet.make_seed() modal_dialog('Your seed is:', seed) elif action == 'import': seed = self.seed_dialog() if not seed: exit() if not Wallet.is_seed(seed): exit() wallet = Wallet.from_seed(seed, storage) else: exit() wallet.add_seed(seed, password) wallet.create_master_keys(password) wallet.create_main_account(password) else: wallet = Wallet(storage)
def __init__(self): global wallet self.qr_data = None storage = WalletStorage({'wallet_path':'/sdcard/electrum/authenticator'}) if not storage.file_exists: action = self.restore_or_create() if not action: exit() password = droid.dialogGetPassword('Choose a password').result if password: password2 = droid.dialogGetPassword('Confirm password').result if password != password2: modal_dialog('Error', 'Passwords do not match') exit() else: password = None if action == 'create': wallet = Wallet(storage) seed = wallet.make_seed() modal_dialog('Your seed is:', seed) elif action == 'import': seed = self.seed_dialog() if not seed: exit() if not Wallet.is_seed(seed): exit() wallet = Wallet.from_seed(seed, storage) else: exit() wallet.add_seed(seed, password) wallet.create_master_keys(password) wallet.create_main_account(password) else: wallet = Wallet(storage)
def __init__(self): global wallet self.qr_data = None storage = WalletStorage("/sdcard/electrum/authenticator") if not storage.file_exists: action = self.restore_or_create() if not action: exit() password = droid.dialogGetPassword("Choose a password").result if password: password2 = droid.dialogGetPassword("Confirm password").result if password != password2: modal_dialog("Error", "Passwords do not match") exit() else: password = None if action == "create": wallet = Wallet(storage) seed = wallet.make_seed() modal_dialog("Your seed is:", seed) elif action == "import": seed = self.seed_dialog() if not seed: exit() if not Wallet.is_seed(seed): exit() wallet = Wallet.from_seed(seed, password, storage) else: exit() wallet.add_seed(seed, password) wallet.create_master_keys(password) wallet.create_main_account(password) else: wallet = Wallet(storage)
def run(self, action): if action == 'new': action, wallet_type = self.restore_or_create() if wallet_type == 'multisig': wallet_type = self.choice(_("Multi Signature Wallet"), 'Select wallet type', [('2of2', _("2 of 2")),('2of3',_("2 of 3"))]) if not wallet_type: return elif wallet_type == 'hardware': hardware_wallets = map(lambda x:(x[1],x[2]), filter(lambda x:x[0]=='hardware', electrum.wallet.wallet_types)) wallet_type = self.choice(_("Hardware Wallet"), 'Select your hardware wallet', hardware_wallets) if not wallet_type: return elif wallet_type == 'twofactor': wallet_type = '2fa' if action == 'create': self.storage.put('wallet_type', wallet_type, False) if action is None: return if action == 'restore': wallet = self.restore(wallet_type) if not wallet: return action = None else: wallet = Wallet(self.storage) action = wallet.get_action() # fixme: password is only needed for multiple accounts password = None while action is not None: util.print_error("installwizard:", wallet, action) if action == 'create_seed': seed = wallet.make_seed() if not self.show_seed(seed, None): return if not self.verify_seed(seed, None): return password = self.password_dialog() wallet.add_seed(seed, password) wallet.create_master_keys(password) elif action == 'add_cosigner': xpub1 = wallet.master_public_keys.get("x1/") r = self.multi_mpk_dialog(xpub1, 1) if not r: return xpub2 = r[0] wallet.add_master_public_key("x2/", xpub2) elif action == 'add_two_cosigners': xpub1 = wallet.master_public_keys.get("x1/") r = self.multi_mpk_dialog(xpub1, 2) if not r: return xpub2, xpub3 = r wallet.add_master_public_key("x2/", xpub2) wallet.add_master_public_key("x3/", xpub3) elif action == 'create_accounts': try: wallet.create_main_account(password) except BaseException as e: import traceback traceback.print_exc(file=sys.stdout) QMessageBox.information(None, _('Error'), str(e), _('OK')) return self.waiting_dialog(wallet.synchronize) else: f = run_hook('get_wizard_action', self, wallet, action) if not f: raise BaseException('unknown wizard action', action) r = f(wallet, self) if not r: return # next action action = wallet.get_action() if self.network: if self.network.interfaces: self.network_dialog() else: QMessageBox.information(None, _('Warning'), _('You are offline'), _('OK')) self.network.stop() self.network = None # start wallet threads wallet.start_threads(self.network) if action == 'restore': self.waiting_dialog(lambda: wallet.restore(self.waiting_label.setText)) if self.network: msg = _("Recovery successful") if wallet.is_found() else _("No transactions found for this seed") else: msg = _("This wallet was restored offline. It may contain more addresses than displayed.") QMessageBox.information(None, _('Information'), msg, _('OK')) return wallet
class InstallWizard(Widget): '''Installation Wizard. Responsible for instantiating the creation/restoration of wallets. events:: `on_wizard_complete` Fired when the wizard is done creating/ restoring wallet/s. ''' __events__ = ('on_wizard_complete', ) def __init__(self, config, network, storage): super(InstallWizard, self).__init__() self.config = config self.network = network self.storage = storage self.wallet = Wallet(self.storage) self.is_restore = False def waiting_dialog(self, task, msg, on_complete=None): '''Perform a blocking task in the background by running the passed method in a thread. ''' def target(): # run your threaded function try: task() except Exception as err: Clock.schedule_once(lambda dt: app.show_error(str(err))) # on completion hide message Clock.schedule_once(lambda dt: app.info_bubble.hide(now=True), -1) if on_complete: on_complete() app.show_info_bubble( text=msg, icon='atlas://gui/kivy/theming/light/important', pos=Window.center, width='200sp', arrow_pos=None, modal=True) t = threading.Thread(target = target) t.start() def run(self, action, *args): '''Entry point of our Installation wizard''' if not action: return if hasattr(self, action): f = getattr(self, action) apply(f, *args) else: raise BaseException("unknown action", action) def new(self): def on_release(dialog, button): if not button: # soft back or escape button pressed return self.dispatch('on_wizard_complete', None) dialog.close() action = dialog.action if button == dialog.ids.create: self.run('create') elif button == dialog.ids.restore: self.run('restore') else: self.dispatch('on_wizard_complete', None) CreateRestoreDialog(on_release=on_release).open() def restore(self): self.is_restore = True def on_seed(_dlg, btn): _dlg.close() if btn is _dlg.ids.back: self.run('new') return text = _dlg.get_seed_text() if Wallet.should_encrypt(text): self.run('enter_pin', (text,)) else: self.run('add_seed', (text, None)) # fixme: sync msg = _('You may also enter an extended public key, to create a watching-only wallet') RestoreSeedDialog(test=Wallet.is_any, message=msg, on_release=on_seed).open() def add_seed(self, text, password): def task(): if Wallet.is_seed(text): self.wallet.add_seed(text, password) self.wallet.create_master_keys(password) else: self.wallet = Wallet.from_text(text, None, self.storage) self.wallet.create_main_account() self.wallet.synchronize() msg= _("Electrum is generating your addresses, please wait.") self.waiting_dialog(task, msg, self.terminate) def create(self): self.is_restore = False seed = self.wallet.make_seed() msg = _("If you forget your PIN or lose your device, your seed phrase will be the " "only way to recover your funds.") def on_ok(_dlg, _btn): _dlg.close() if _btn == _dlg.ids.confirm: self.run('confirm_seed', (seed,)) else: self.run('new') ShowSeedDialog(message=msg, seed_text=seed, on_release=on_ok).open() def confirm_seed(self, seed): assert Wallet.is_seed(seed) def on_seed(_dlg, btn): if btn is _dlg.ids.back: _dlg.close() self.run('create') return _dlg.close() self.run('enter_pin', (seed,)) msg = _('Please retype your seed phrase, to confirm that you properly saved it') RestoreSeedDialog(test=lambda x: x==seed, message=msg, on_release=on_seed).open() def enter_pin(self, seed): def callback(pin): self.run('confirm_pin', (seed, pin)) popup = PasswordDialog('Choose a PIN code', callback) popup.open() def confirm_pin(self, seed, pin): def callback(conf): if conf == pin: self.run('add_seed', (seed, pin)) else: app.show_error(_('PIN mismatch'), duration=.5) self.run('enter_pin', (seed,)) popup = PasswordDialog('Confirm your PIN code', callback) popup.open() def terminate(self): self.wallet.start_threads(self.network) #if self.is_restore: # if self.wallet.is_found(): # app.show_info(_("Recovery successful"), duration=.5) # else: # app.show_info(_("No transactions found for this seed"), duration=.5) self.dispatch('on_wizard_complete', self.wallet) def on_wizard_complete(self, wallet): """overriden by main_window""" pass
def run(self, action, wallet_type): if action in ['create', 'restore']: if wallet_type == 'multisig': wallet_type = self.multisig_choice() if not wallet_type: return elif wallet_type == 'hardware': hardware_wallets = map(lambda x:(x[1],x[2]), filter(lambda x:x[0]=='hardware', electrum.wallet.wallet_types)) wallet_type = self.choice(_("Hardware Wallet"), 'Select your hardware wallet', hardware_wallets) if not wallet_type: return elif wallet_type == 'twofactor': wallet_type = '2fa' if action == 'create': self.storage.put('wallet_type', wallet_type, False) if action is None: return if action == 'restore': wallet = self.restore(wallet_type) if not wallet: return action = None else: wallet = Wallet(self.storage) action = wallet.get_action() # fixme: password is only needed for multiple accounts password = None # load wallet in plugins always_hook('installwizard_load_wallet', wallet, self) while action is not None: util.print_error("installwizard:", wallet, action) if action == 'create_seed': lang = self.config.get('language') seed = wallet.make_seed(lang) if not self.show_seed(seed, None): return if not self.verify_seed(seed, None): return password = self.password_dialog() wallet.add_seed(seed, password) wallet.create_master_keys(password) elif action == 'add_cosigners': n = int(re.match('(\d+)of(\d+)', wallet.wallet_type).group(2)) xpub1 = wallet.master_public_keys.get("x1/") r = self.multi_mpk_dialog(xpub1, n - 1) if not r: return for i, xpub in enumerate(r): wallet.add_master_public_key("x%d/"%(i+2), xpub) elif action == 'create_accounts': wallet.create_main_account(password) self.waiting_dialog(wallet.synchronize) else: f = always_hook('get_wizard_action', self, wallet, action) if not f: raise BaseException('unknown wizard action', action) r = f(wallet, self) if not r: return # next action action = wallet.get_action() if self.network: if self.network.interfaces: self.network_dialog() else: QMessageBox.information(None, _('Warning'), _('You are offline'), _('OK')) self.network.stop() self.network = None # start wallet threads wallet.start_threads(self.network) if action == 'restore': self.waiting_dialog(lambda: wallet.restore(self.waiting_label.setText)) if self.network: msg = _("Recovery successful") if wallet.is_found() else _("No transactions found for this seed") else: msg = _("This wallet was restored offline. It may contain more addresses than displayed.") QMessageBox.information(None, _('Information'), msg, _('OK')) return wallet
def run(self, action): if action == 'new': action, wallet_type = self.restore_or_create() self.storage.put('wallet_type', wallet_type, False) if action is None: return if action == 'restore': wallet = self.restore(wallet_type) if not wallet: return action = None else: wallet = Wallet(self.storage) action = wallet.get_action() # fixme: password is only needed for multiple accounts password = None while action is not None: util.print_error("installwizard:", wallet, action) if action == 'create_seed': seed = wallet.make_seed() if not self.show_seed(seed, None): return if not self.verify_seed(seed, None): return password = self.password_dialog() wallet.add_seed(seed, password) elif action == 'add_cosigner': xpub_hot = wallet.master_public_keys.get("m/") r = self.multi_mpk_dialog(xpub_hot, 1) if not r: return xpub_cold = r[0] wallet.add_master_public_key("cold/", xpub_cold) elif action == 'add_two_cosigners': xpub_hot = wallet.master_public_keys.get("m/") r = self.multi_mpk_dialog(xpub_hot, 2) if not r: return xpub1, xpub2 = r wallet.add_master_public_key("cold/", xpub1) wallet.add_master_public_key("remote/", xpub2) elif action == 'create_accounts': wallet.create_accounts(password) self.waiting_dialog(wallet.synchronize) elif action == 'create_cold_seed': self.create_cold_seed(wallet) return else: r = run_hook('install_wizard_action', self, wallet, action) if not r: raise BaseException('unknown wizard action', action) # next action action = wallet.get_action() if self.network: if self.network.interfaces: self.network_dialog() else: QMessageBox.information(None, _('Warning'), _('You are offline'), _('OK')) self.network.stop() self.network = None # start wallet threads wallet.start_threads(self.network) if action == 'restore': self.waiting_dialog(lambda: wallet.restore(self.waiting_label.setText)) if self.network: if wallet.is_found(): QMessageBox.information(None, _('Information'), _("Recovery successful"), _('OK')) else: QMessageBox.information(None, _('Information'), _("No transactions found for this seed"), _('OK')) else: QMessageBox.information(None, _('Information'), _("This wallet was restored offline. It may contain more addresses than displayed."), _('OK')) return wallet
def run(self, action): if action == 'new': action, t = self.restore_or_create() if action is None: return if action == 'create': if t == 'standard': wallet = Wallet(self.storage) elif t == '2fa': wallet = Wallet_2of3(self.storage) run_hook('create_cold_seed', wallet, self) self.create_cold_seed(wallet) return elif t == '2of2': wallet = Wallet_2of2(self.storage) action = 'create_2of2_1' elif t == '2of3': wallet = Wallet_2of3(self.storage) action = 'create_2of3_1' if action in ['create_2fa_2', 'create_2of3_2']: wallet = Wallet_2of3(self.storage) if action in ['create', 'create_2of2_1', 'create_2fa_2', 'create_2of3_1']: seed = wallet.make_seed() sid = None if action == 'create' else 'hot' if not self.show_seed(seed, sid): return if not self.verify_seed(seed, sid): return password = self.password_dialog() wallet.add_seed(seed, password) if action == 'create': wallet.create_accounts(password) self.waiting_dialog(wallet.synchronize) elif action == 'create_2of2_1': action = 'create_2of2_2' elif action == 'create_2of3_1': action = 'create_2of3_2' elif action == 'create_2fa_2': action = 'create_2fa_3' if action == 'create_2of2_2': xpub_hot = wallet.master_public_keys.get("m/") xpub = self.multi_mpk_dialog(xpub_hot, 1) if not xpub: return wallet.add_master_public_key("cold/", xpub) wallet.create_account() self.waiting_dialog(wallet.synchronize) if action == 'create_2of3_2': xpub_hot = wallet.master_public_keys.get("m/") r = self.multi_mpk_dialog(xpub_hot, 2) if not r: return xpub1, xpub2 = r wallet.add_master_public_key("cold/", xpub1) wallet.add_master_public_key("remote/", xpub2) wallet.create_account() self.waiting_dialog(wallet.synchronize) if action == 'create_2fa_3': run_hook('create_remote_key', wallet, self) if not wallet.master_public_keys.get("remote/"): return wallet.create_account() self.waiting_dialog(wallet.synchronize) if action == 'restore': if t == 'standard': text = self.enter_seed_dialog(MSG_ENTER_ANYTHING, None) if not text: return if Wallet.is_seed(text): password = self.password_dialog() wallet = Wallet.from_seed(text, self.storage) wallet.add_seed(text, password) wallet.create_accounts(password) elif Wallet.is_mpk(text): wallet = Wallet.from_mpk(text, self.storage) elif Wallet.is_address(text): wallet = Wallet.from_address(text, self.storage) elif Wallet.is_private_key(text): wallet = Wallet.from_private_key(text, self.storage) else: raise elif t in ['2fa', '2of2']: r = self.multi_seed_dialog(1) if not r: return text1, text2 = r password = self.password_dialog() if t == '2of2': wallet = Wallet_2of2(self.storage) elif t == '2of3': wallet = Wallet_2of3(self.storage) elif t == '2fa': wallet = Wallet_2of3(self.storage) if Wallet.is_seed(text1): wallet.add_seed(text1, password) if Wallet.is_seed(text2): wallet.add_cold_seed(text2, password) else: wallet.add_master_public_key("cold/", text2) elif Wallet.is_mpk(text1): if Wallet.is_seed(text2): wallet.add_seed(text2, password) wallet.add_master_public_key("cold/", text1) else: wallet.add_master_public_key("m/", text1) wallet.add_master_public_key("cold/", text2) if t == '2fa': run_hook('restore_third_key', wallet, self) wallet.create_account() elif t in ['2of3']: r = self.multi_seed_dialog(2) if not r: return text1, text2, text3 = r password = self.password_dialog() wallet = Wallet_2of3(self.storage) if Wallet.is_seed(text1): wallet.add_seed(text1, password) if Wallet.is_seed(text2): wallet.add_cold_seed(text2, password) else: wallet.add_master_public_key("cold/", text2) elif Wallet.is_mpk(text1): if Wallet.is_seed(text2): wallet.add_seed(text2, password) wallet.add_master_public_key("cold/", text1) else: wallet.add_master_public_key("m/", text1) wallet.add_master_public_key("cold/", text2) wallet.create_account() else: raise #if not self.config.get('server'): if self.network: if self.network.interfaces: self.network_dialog() else: QMessageBox.information(None, _('Warning'), _('You are offline'), _('OK')) self.network.stop() self.network = None # start wallet threads wallet.start_threads(self.network) if action == 'restore': self.waiting_dialog(lambda: wallet.restore(self.waiting_label.setText)) if self.network: if wallet.is_found(): QMessageBox.information(None, _('Information'), _("Recovery successful"), _('OK')) else: QMessageBox.information(None, _('Information'), _("No transactions found for this seed"), _('OK')) else: QMessageBox.information(None, _('Information'), _("This wallet was restored offline. It may contain more addresses than displayed."), _('OK')) return wallet
def run_wallet_type(self, action, wallet_type): if action in ['create', 'restore']: if wallet_type == 'multisig': wallet_type = self.multisig_choice() if not wallet_type: return elif wallet_type == 'hardware': hardware_wallets = [] for item in electrum.wallet.wallet_types: t, name, description, loader = item if t == 'hardware': try: p = loader() except: util.print_error("cannot load plugin for:", name) continue if p: hardware_wallets.append((name, description)) wallet_type = self.choice(_("Hardware Wallet"), 'Select your hardware wallet', hardware_wallets) if not wallet_type: return elif wallet_type == 'twofactor': wallet_type = '2fa' if action == 'create': self.storage.put('wallet_type', wallet_type, False) if action is None: return if action == 'restore': wallet = self.restore(wallet_type) if not wallet: return action = None else: wallet = Wallet(self.storage) action = wallet.get_action() # fixme: password is only needed for multiple accounts password = None # load wallet in plugins always_hook('installwizard_load_wallet', wallet, self) while action is not None: util.print_error("installwizard:", wallet, action) if action == 'create_seed': lang = self.config.get('language') seed = wallet.make_seed(lang) if not self.show_seed(seed, None): return if not self.verify_seed(seed, None): return password = self.password_dialog() wallet.add_seed(seed, password) wallet.create_master_keys(password) elif action == 'add_cosigners': n = int(re.match('(\d+)of(\d+)', wallet.wallet_type).group(2)) xpub1 = wallet.master_public_keys.get("x1/") r = self.multi_mpk_dialog(xpub1, n - 1) if not r: return for i, xpub in enumerate(r): wallet.add_master_public_key("x%d/" % (i + 2), xpub) elif action == 'create_accounts': wallet.create_main_account(password) self.waiting_dialog(wallet.synchronize) else: f = always_hook('get_wizard_action', self, wallet, action) if not f: raise BaseException('unknown wizard action', action) r = f(wallet, self) if not r: return # next action action = wallet.get_action() if self.network: if self.network.interfaces: self.network_dialog() else: QMessageBox.information(None, _('Warning'), _('You are offline'), _('OK')) self.network.stop() self.network = None # start wallet threads wallet.start_threads(self.network) if action == 'restore': self.waiting_dialog( lambda: wallet.restore(self.waiting_label.setText)) if self.network: msg = _("Recovery successful") if wallet.is_found() else _( "No transactions found for this seed") else: msg = _( "This wallet was restored offline. It may contain more addresses than displayed." ) QMessageBox.information(None, _('Information'), msg, _('OK')) return wallet
class InstallWizard(Widget): '''Installation Wizard. Responsible for instantiating the creation/restoration of wallets. events:: `on_wizard_complete` Fired when the wizard is done creating/ restoring wallet/s. ''' __events__ = ('on_wizard_complete', ) def __init__(self, config, network, storage): super(InstallWizard, self).__init__() self.config = config self.network = network self.storage = storage self.wallet = Wallet(self.storage) self.is_restore = False def waiting_dialog(self, task, msg, on_complete=None): '''Perform a blocking task in the background by running the passed method in a thread. ''' def target(): # run your threaded function try: task() except Exception as err: Clock.schedule_once(lambda dt: app.show_error(str(err))) # on completion hide message Clock.schedule_once(lambda dt: app.info_bubble.hide(now=True), -1) if on_complete: on_complete() app.show_info_bubble(text=msg, icon='atlas://gui/kivy/theming/light/important', pos=Window.center, width='200sp', arrow_pos=None, modal=True) t = threading.Thread(target=target) t.start() def run(self, action, *args): '''Entry point of our Installation wizard''' if not action: return if hasattr(self, action): f = getattr(self, action) apply(f, *args) else: raise BaseException("unknown action", action) def new(self): def on_release(dialog, button): if not button: # soft back or escape button pressed return self.dispatch('on_wizard_complete', None) dialog.close() action = dialog.action if button == dialog.ids.create: self.run('create') elif button == dialog.ids.restore: self.run('restore') else: self.dispatch('on_wizard_complete', None) CreateRestoreDialog(on_release=on_release).open() def restore(self): self.is_restore = True def on_seed(_dlg, btn): _dlg.close() if btn is _dlg.ids.back: self.run('new') return text = _dlg.get_seed_text() if Wallet.should_encrypt(text): self.run('enter_pin', (text, )) else: self.run('add_seed', (text, None)) # fixme: sync msg = _( 'You may use the camera to scan your seed. To create a watching-only wallet, scan your master public key.' ) RestoreSeedDialog(test=Wallet.is_any, message=msg, on_release=on_seed).open() def add_seed(self, text, password): def task(): if Wallet.is_seed(text): self.wallet.add_seed(text, password) self.wallet.create_master_keys(password) else: self.wallet = Wallet.from_text(text, None, self.storage) self.wallet.create_main_account() self.wallet.synchronize() msg = _("Electrum is generating your addresses, please wait.") self.waiting_dialog(task, msg, self.terminate) def create(self): self.is_restore = False seed = self.wallet.make_seed() msg = _( "If you forget your PIN or lose your device, your seed phrase will be the " "only way to recover your funds.") def on_ok(_dlg, _btn): _dlg.close() if _btn == _dlg.ids.confirm: self.run('confirm_seed', (seed, )) else: self.run('new') ShowSeedDialog(message=msg, seed_text=seed, on_release=on_ok).open() def confirm_seed(self, seed): assert Wallet.is_seed(seed) def on_seed(_dlg, btn): if btn is _dlg.ids.back: _dlg.close() self.run('create') return _dlg.close() self.run('enter_pin', (seed, )) msg = _( 'Please retype your seed phrase, to confirm that you properly saved it' ) RestoreSeedDialog(test=lambda x: x == seed, message=msg, on_release=on_seed).open() def enter_pin(self, seed): def callback(pin): self.run('confirm_pin', (seed, pin)) popup = PasswordDialog('Choose a PIN code', callback) popup.open() def confirm_pin(self, seed, pin): def callback(conf): if conf == pin: self.run('add_seed', (seed, pin)) else: app.show_error(_('PIN mismatch'), duration=.5) self.run('enter_pin', (seed, )) popup = PasswordDialog('Confirm your PIN code', callback) popup.open() def terminate(self): self.wallet.start_threads(self.network) #if self.is_restore: # if self.wallet.is_found(): # app.show_info(_("Recovery successful"), duration=.5) # else: # app.show_info(_("No transactions found for this seed"), duration=.5) self.dispatch('on_wizard_complete', self.wallet) def on_wizard_complete(self, wallet): """overriden by main_window""" pass
def run(self, action): if action == 'new': action, wallet_type = self.restore_or_create() if wallet_type == 'multisig': wallet_type = self.choice(_("Multi Signature Wallet"), 'Select wallet type', [('2of2', _("2 of 2")), ('2of3', _("2 of 3"))]) if not wallet_type: return elif wallet_type == 'hardware': hardware_wallets = map( lambda x: (x[1], x[2]), filter(lambda x: x[0] == 'hardware', electrum.wallet.wallet_types)) wallet_type = self.choice(_("Hardware Wallet"), 'Select your hardware wallet', hardware_wallets) if not wallet_type: return elif wallet_type == 'twofactor': wallet_type = '2fa' if action == 'create': self.storage.put('wallet_type', wallet_type, False) if action is None: return if action == 'restore': wallet = self.restore(wallet_type) if not wallet: return action = None else: wallet = Wallet(self.storage) action = wallet.get_action() # fixme: password is only needed for multiple accounts password = None while action is not None: util.print_error("installwizard:", wallet, action) if action == 'create_seed': seed = wallet.make_seed() if not self.show_seed(seed, None): return if not self.verify_seed(seed, None): return password = self.password_dialog() wallet.add_seed(seed, password) wallet.create_master_keys(password) elif action == 'add_cosigner': xpub1 = wallet.master_public_keys.get("x1/") r = self.multi_mpk_dialog(xpub1, 1) if not r: return xpub2 = r[0] wallet.add_master_public_key("x2/", xpub2) elif action == 'add_two_cosigners': xpub1 = wallet.master_public_keys.get("x1/") r = self.multi_mpk_dialog(xpub1, 2) if not r: return xpub2, xpub3 = r wallet.add_master_public_key("x2/", xpub2) wallet.add_master_public_key("x3/", xpub3) elif action == 'create_accounts': wallet.create_main_account(password) self.waiting_dialog(wallet.synchronize) else: f = run_hook('get_wizard_action', self, wallet, action) if not f: raise BaseException('unknown wizard action', action) r = f(wallet, self) if not r: return # next action action = wallet.get_action() if self.network: if self.network.interfaces: self.network_dialog() else: QMessageBox.information(None, _('Warning'), _('You are offline'), _('OK')) self.network.stop() self.network = None # start wallet threads wallet.start_threads(self.network) if action == 'restore': self.waiting_dialog( lambda: wallet.restore(self.waiting_label.setText)) if self.network: msg = _("Recovery successful") if wallet.is_found() else _( "No transactions found for this seed") else: msg = _( "This wallet was restored offline. It may contain more addresses than displayed." ) QMessageBox.information(None, _('Information'), msg, _('OK')) return wallet
def run_wallet_type(self, action, wallet_type): if action in ["create", "restore"]: if wallet_type == "multisig": wallet_type = self.multisig_choice() if not wallet_type: return elif wallet_type == "hardware": hardware_wallets = [] for item in electrum.wallet.wallet_types: t, name, description, loader = item if t == "hardware": try: p = loader() except: util.print_error("cannot load plugin for:", name) continue if p: hardware_wallets.append((name, description)) wallet_type = self.choice(_("Hardware Wallet"), "Select your hardware wallet", hardware_wallets) if not wallet_type: return elif wallet_type == "twofactor": wallet_type = "2fa" if action == "create": self.storage.put("wallet_type", wallet_type, False) if action is None: return if action == "restore": wallet = self.restore(wallet_type) if not wallet: return action = None else: wallet = Wallet(self.storage) action = wallet.get_action() # fixme: password is only needed for multiple accounts password = None # load wallet in plugins always_hook("installwizard_load_wallet", wallet, self) while action is not None: util.print_error("installwizard:", wallet, action) if action == "create_seed": lang = self.config.get("language") seed = wallet.make_seed(lang) if not self.show_seed(seed, None): return if not self.verify_seed(seed, None): return password = self.password_dialog() wallet.add_seed(seed, password) wallet.create_master_keys(password) elif action == "add_cosigners": n = int(re.match("(\d+)of(\d+)", wallet.wallet_type).group(2)) xpub1 = wallet.master_public_keys.get("x1/") r = self.multi_mpk_dialog(xpub1, n - 1) if not r: return for i, xpub in enumerate(r): wallet.add_master_public_key("x%d/" % (i + 2), xpub) elif action == "create_accounts": wallet.create_main_account(password) self.waiting_dialog(wallet.synchronize) else: f = always_hook("get_wizard_action", self, wallet, action) if not f: raise BaseException("unknown wizard action", action) r = f(wallet, self) if not r: return # next action action = wallet.get_action() if self.network: if self.network.interfaces: self.network_dialog() else: QMessageBox.information(None, _("Warning"), _("You are offline"), _("OK")) self.network.stop() self.network = None # start wallet threads wallet.start_threads(self.network) if action == "restore": self.waiting_dialog(lambda: wallet.restore(self.waiting_label.setText)) if self.network: msg = _("Recovery successful") if wallet.is_found() else _("No transactions found for this seed") else: msg = _("This wallet was restored offline. It may contain more addresses than displayed.") QMessageBox.information(None, _("Information"), msg, _("OK")) return wallet