|
|
|
@ -12,10 +12,10 @@ from electrum.util import UserCancelled |
|
|
|
from electrum.base_wizard import BaseWizard |
|
|
|
from electrum.base_wizard import BaseWizard |
|
|
|
from electrum.i18n import _ |
|
|
|
from electrum.i18n import _ |
|
|
|
|
|
|
|
|
|
|
|
from seed_dialog import SeedDisplayLayout, SeedWarningLayout, SeedInputLayout |
|
|
|
from seed_dialog import SeedDisplayLayout, CreateSeedLayout, SeedInputLayout, TextInputLayout |
|
|
|
from network_dialog import NetworkChoiceLayout |
|
|
|
from network_dialog import NetworkChoiceLayout |
|
|
|
from util import * |
|
|
|
from util import * |
|
|
|
from password_dialog import PasswordLayout, PW_NEW, PW_PASSPHRASE |
|
|
|
from password_dialog import PasswordLayout, PW_NEW |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class GoBack(Exception): |
|
|
|
class GoBack(Exception): |
|
|
|
@ -28,15 +28,11 @@ MSG_ENTER_SEED_OR_MPK = _("Please enter a seed phrase or a master key (xpub or x |
|
|
|
MSG_COSIGNER = _("Please enter the master public key of cosigner #%d:") |
|
|
|
MSG_COSIGNER = _("Please enter the master public key of cosigner #%d:") |
|
|
|
MSG_ENTER_PASSWORD = _("Choose a password to encrypt your wallet keys.") + '\n'\ |
|
|
|
MSG_ENTER_PASSWORD = _("Choose a password to encrypt your wallet keys.") + '\n'\ |
|
|
|
+ _("Leave this field empty if you want to disable encryption.") |
|
|
|
+ _("Leave this field empty if you want to disable encryption.") |
|
|
|
MSG_PASSPHRASE = \ |
|
|
|
MSG_RESTORE_PASSPHRASE = \ |
|
|
|
_("Please enter your seed derivation passphrase. " |
|
|
|
_("Please enter your seed derivation passphrase. " |
|
|
|
"Note: this is NOT your encryption password. " |
|
|
|
"Note: this is NOT your encryption password. " |
|
|
|
"Leave this field empty if you did not use one or are unsure.") |
|
|
|
"Leave this field empty if you did not use one or are unsure.") |
|
|
|
|
|
|
|
|
|
|
|
def clean_text(seed_e): |
|
|
|
|
|
|
|
text = unicode(seed_e.toPlainText()).strip() |
|
|
|
|
|
|
|
text = ' '.join(text.split()) |
|
|
|
|
|
|
|
return text |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CosignWidget(QWidget): |
|
|
|
class CosignWidget(QWidget): |
|
|
|
size = 120 |
|
|
|
size = 120 |
|
|
|
@ -248,31 +244,18 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard): |
|
|
|
def remove_from_recently_open(self, filename): |
|
|
|
def remove_from_recently_open(self, filename): |
|
|
|
self.config.remove_from_recently_open(filename) |
|
|
|
self.config.remove_from_recently_open(filename) |
|
|
|
|
|
|
|
|
|
|
|
def text_input_layout(self, title, message, is_valid): |
|
|
|
|
|
|
|
slayout = SeedInputLayout(title=message) |
|
|
|
|
|
|
|
slayout.is_valid = is_valid |
|
|
|
|
|
|
|
slayout.sanitized_text = lambda: clean_text(slayout.seed_edit()) |
|
|
|
|
|
|
|
slayout.set_enabled = lambda: self.next_button.setEnabled(slayout.is_valid(slayout.sanitized_text())) |
|
|
|
|
|
|
|
slayout.seed_edit().textChanged.connect(slayout.set_enabled) |
|
|
|
|
|
|
|
return slayout |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def text_input(self, title, message, is_valid): |
|
|
|
def text_input(self, title, message, is_valid): |
|
|
|
slayout = self.text_input_layout(title, message, is_valid) |
|
|
|
slayout = TextInputLayout(self, message, is_valid) |
|
|
|
self.set_main_layout(slayout.layout(), title, next_enabled=False) |
|
|
|
self.set_main_layout(slayout.layout(), title, next_enabled=False) |
|
|
|
seed = slayout.sanitized_text() |
|
|
|
return slayout.get_text() |
|
|
|
return seed |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def seed_input(self, title, message, is_valid): |
|
|
|
def seed_input(self, title, message, is_seed, is_passphrase): |
|
|
|
slayout = self.text_input_layout(title, message, is_valid) |
|
|
|
slayout = SeedInputLayout(self, message, is_seed, is_passphrase) |
|
|
|
vbox = QVBoxLayout() |
|
|
|
vbox = QVBoxLayout() |
|
|
|
vbox.addLayout(slayout.layout()) |
|
|
|
vbox.addLayout(slayout.layout()) |
|
|
|
if self.opt_ext or self.opt_bip39: |
|
|
|
if self.opt_bip39: |
|
|
|
vbox.addStretch(1) |
|
|
|
vbox.addStretch(1) |
|
|
|
vbox.addWidget(QLabel(_('Options') + ':')) |
|
|
|
vbox.addWidget(QLabel(_('Options') + ':')) |
|
|
|
if self.opt_ext: |
|
|
|
|
|
|
|
cb_ext = QCheckBox(_('Extend this seed with a passphrase')) |
|
|
|
|
|
|
|
vbox.addWidget(cb_ext) |
|
|
|
|
|
|
|
if self.opt_bip39: |
|
|
|
|
|
|
|
def f(b): |
|
|
|
def f(b): |
|
|
|
slayout.is_valid = (lambda x: bool(x)) if b else is_valid |
|
|
|
slayout.is_valid = (lambda x: bool(x)) if b else is_valid |
|
|
|
slayout.set_enabled() |
|
|
|
slayout.set_enabled() |
|
|
|
@ -280,10 +263,10 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard): |
|
|
|
cb_bip39.toggled.connect(f) |
|
|
|
cb_bip39.toggled.connect(f) |
|
|
|
vbox.addWidget(cb_bip39) |
|
|
|
vbox.addWidget(cb_bip39) |
|
|
|
self.set_main_layout(vbox, title, next_enabled=False) |
|
|
|
self.set_main_layout(vbox, title, next_enabled=False) |
|
|
|
seed = slayout.sanitized_text() |
|
|
|
seed = slayout.get_seed() |
|
|
|
is_ext = cb_ext.isChecked() if self.opt_ext else False |
|
|
|
passphrase = slayout.get_passphrase() |
|
|
|
is_bip39 = cb_bip39.isChecked() if self.opt_bip39 else False |
|
|
|
is_bip39 = cb_bip39.isChecked() if self.opt_bip39 else False |
|
|
|
return seed, is_ext, is_bip39 |
|
|
|
return seed, passphrase, is_bip39 |
|
|
|
|
|
|
|
|
|
|
|
@wizard_dialog |
|
|
|
@wizard_dialog |
|
|
|
def restore_keys_dialog(self, title, message, is_valid, run_next): |
|
|
|
def restore_keys_dialog(self, title, message, is_valid, run_next): |
|
|
|
@ -299,13 +282,14 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard): |
|
|
|
return self.text_input(title, message, is_valid) |
|
|
|
return self.text_input(title, message, is_valid) |
|
|
|
|
|
|
|
|
|
|
|
@wizard_dialog |
|
|
|
@wizard_dialog |
|
|
|
def restore_seed_dialog(self, run_next, is_valid): |
|
|
|
def restore_seed_dialog(self, run_next, is_seed): |
|
|
|
title = _('Enter Seed') |
|
|
|
title = _('Enter Seed') |
|
|
|
message = _('Please enter your seed phrase in order to restore your wallet.') |
|
|
|
message = _('Please enter your seed phrase in order to restore your wallet.') |
|
|
|
return self.seed_input(title, message, is_valid) |
|
|
|
is_passphrase = lambda x: True |
|
|
|
|
|
|
|
return self.seed_input(title, message, is_seed, is_passphrase) |
|
|
|
|
|
|
|
|
|
|
|
@wizard_dialog |
|
|
|
@wizard_dialog |
|
|
|
def confirm_seed_dialog(self, run_next, is_valid): |
|
|
|
def confirm_seed_dialog(self, run_next, is_seed, is_passphrase): |
|
|
|
self.app.clipboard().clear() |
|
|
|
self.app.clipboard().clear() |
|
|
|
title = _('Confirm Seed') |
|
|
|
title = _('Confirm Seed') |
|
|
|
message = ' '.join([ |
|
|
|
message = ' '.join([ |
|
|
|
@ -313,29 +297,19 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard): |
|
|
|
_('If you lose your seed, your money will be permanently lost.'), |
|
|
|
_('If you lose your seed, your money will be permanently lost.'), |
|
|
|
_('To make sure that you have properly saved your seed, please retype it here.') |
|
|
|
_('To make sure that you have properly saved your seed, please retype it here.') |
|
|
|
]) |
|
|
|
]) |
|
|
|
return self.seed_input(title, message, is_valid) |
|
|
|
return self.seed_input(title, message, is_seed, is_passphrase) |
|
|
|
|
|
|
|
|
|
|
|
@wizard_dialog |
|
|
|
@wizard_dialog |
|
|
|
def show_seed_dialog(self, run_next, seed_text): |
|
|
|
def show_seed_dialog(self, run_next, seed_text): |
|
|
|
slayout = SeedWarningLayout(seed_text) |
|
|
|
slayout = CreateSeedLayout(seed_text) |
|
|
|
self.set_main_layout(slayout.layout()) |
|
|
|
self.set_main_layout(slayout.layout()) |
|
|
|
return seed_text |
|
|
|
return seed_text, slayout.passphrase() |
|
|
|
|
|
|
|
|
|
|
|
def pw_layout(self, msg, kind): |
|
|
|
def pw_layout(self, msg, kind): |
|
|
|
playout = PasswordLayout(None, msg, kind, self.next_button) |
|
|
|
playout = PasswordLayout(None, msg, kind, self.next_button) |
|
|
|
self.set_main_layout(playout.layout()) |
|
|
|
self.set_main_layout(playout.layout()) |
|
|
|
return playout.new_password() |
|
|
|
return playout.new_password() |
|
|
|
|
|
|
|
|
|
|
|
@wizard_dialog |
|
|
|
|
|
|
|
def request_passphrase(self, run_next): |
|
|
|
|
|
|
|
"""When restoring a wallet, request the passphrase that was used for |
|
|
|
|
|
|
|
the wallet on the given device and confirm it. Should return |
|
|
|
|
|
|
|
a unicode string.""" |
|
|
|
|
|
|
|
phrase = self.pw_layout(MSG_PASSPHRASE, PW_PASSPHRASE) |
|
|
|
|
|
|
|
if phrase is None: |
|
|
|
|
|
|
|
raise UserCancelled |
|
|
|
|
|
|
|
return phrase |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@wizard_dialog |
|
|
|
@wizard_dialog |
|
|
|
def request_password(self, run_next): |
|
|
|
def request_password(self, run_next): |
|
|
|
"""Request the user enter a new password and confirm it. Return |
|
|
|
"""Request the user enter a new password and confirm it. Return |
|
|
|
@ -405,13 +379,6 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard): |
|
|
|
self.set_main_layout(vbox, '') |
|
|
|
self.set_main_layout(vbox, '') |
|
|
|
return clayout.selected_index() |
|
|
|
return clayout.selected_index() |
|
|
|
|
|
|
|
|
|
|
|
def get_passphrase(self, msg, confirm): |
|
|
|
|
|
|
|
phrase = self.pw_layout(msg, PW_PASSPHRASE) |
|
|
|
|
|
|
|
if phrase is None: |
|
|
|
|
|
|
|
raise UserCancelled |
|
|
|
|
|
|
|
return phrase |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@wizard_dialog |
|
|
|
@wizard_dialog |
|
|
|
def account_id_dialog(self, run_next): |
|
|
|
def account_id_dialog(self, run_next): |
|
|
|
message = '\n'.join([ |
|
|
|
message = '\n'.join([ |
|
|
|
|