|
|
@ -31,6 +31,7 @@ from kivy.clock import Clock |
|
|
|
from kivy.factory import Factory |
|
|
|
from kivy.metrics import inch |
|
|
|
from kivy.lang import Builder |
|
|
|
from .uix.dialogs.password_dialog import PasswordDialog |
|
|
|
|
|
|
|
## lazy imports for factory so that widgets can be used in kv |
|
|
|
#Factory.register('InstallWizard', module='electrum.gui.kivy.uix.dialogs.installwizard') |
|
|
@ -326,7 +327,7 @@ class ElectrumWindow(App): |
|
|
|
self.wallet = None # type: Optional[Abstract_Wallet] |
|
|
|
self.pause_time = 0 |
|
|
|
self.asyncio_loop = asyncio.get_event_loop() |
|
|
|
self.pin_code = None |
|
|
|
self.password = None |
|
|
|
|
|
|
|
App.__init__(self)#, **kwargs) |
|
|
|
|
|
|
@ -623,10 +624,12 @@ class ElectrumWindow(App): |
|
|
|
if wallet.has_password(): |
|
|
|
def on_success(x): |
|
|
|
# save pin_code so that we can create backups |
|
|
|
self.pin_code = x |
|
|
|
self.password = x |
|
|
|
self.load_wallet(wallet) |
|
|
|
self.password_dialog(wallet=wallet, msg=_('Enter PIN code'), |
|
|
|
on_success=on_success, on_failure=self.stop) |
|
|
|
self.password_dialog( |
|
|
|
check_password=wallet.check_password, |
|
|
|
on_success=on_success, |
|
|
|
on_failure=self.stop) |
|
|
|
else: |
|
|
|
self.load_wallet(wallet) |
|
|
|
else: |
|
|
@ -642,11 +645,13 @@ class ElectrumWindow(App): |
|
|
|
if not storage.is_encrypted_with_user_pw(): |
|
|
|
raise Exception("Kivy GUI does not support this type of encrypted wallet files.") |
|
|
|
def on_password(pw): |
|
|
|
self.pin_code = pw |
|
|
|
self.password = pw |
|
|
|
storage.decrypt(pw) |
|
|
|
self._on_decrypted_storage(storage) |
|
|
|
self.password_dialog(wallet=storage, msg=_('Enter PIN code'), |
|
|
|
on_success=on_password, on_failure=self.stop) |
|
|
|
self.password_dialog( |
|
|
|
check_password=storage.check_password, |
|
|
|
on_success=on_password, |
|
|
|
on_failure=self.stop) |
|
|
|
return |
|
|
|
self._on_decrypted_storage(storage) |
|
|
|
if not ask_if_wizard: |
|
|
@ -940,7 +945,7 @@ class ElectrumWindow(App): |
|
|
|
def on_resume(self): |
|
|
|
now = time.time() |
|
|
|
if self.wallet and self.wallet.has_password() and now - self.pause_time > 60: |
|
|
|
self.password_dialog(wallet=self.wallet, msg=_('Enter PIN'), on_success=None, on_failure=self.stop) |
|
|
|
self.password_dialog(check_password=self.check_pin_code, on_success=None, on_failure=self.stop, is_password=False) |
|
|
|
if self.nfcscanner: |
|
|
|
self.nfcscanner.nfc_enable() |
|
|
|
|
|
|
@ -1102,12 +1107,12 @@ class ElectrumWindow(App): |
|
|
|
def on_fee(self, event, *arg): |
|
|
|
self.fee_status = self.electrum_config.get_fee_status() |
|
|
|
|
|
|
|
def protected(self, msg, f, args): |
|
|
|
if self.wallet.has_password(): |
|
|
|
on_success = lambda pw: f(*(args + (pw,))) |
|
|
|
self.password_dialog(wallet=self.wallet, msg=msg, on_success=on_success, on_failure=lambda: None) |
|
|
|
def protected(self, f, args): |
|
|
|
if self.electrum_config.get('pin_code'): |
|
|
|
on_success = lambda pw: f(*(args + (self.password,))) |
|
|
|
self.password_dialog(check_password=self.check_pin_code, on_success=on_success, on_failure=lambda: None, is_password=False) |
|
|
|
else: |
|
|
|
f(*(args + (None,))) |
|
|
|
f(*(args + (self.password,))) |
|
|
|
|
|
|
|
def toggle_lightning(self): |
|
|
|
if self.wallet.has_lightning(): |
|
|
@ -1167,59 +1172,64 @@ class ElectrumWindow(App): |
|
|
|
self.load_wallet_by_name(new_path) |
|
|
|
|
|
|
|
def show_seed(self, label): |
|
|
|
self.protected(_("Enter your PIN code in order to decrypt your seed"), self._show_seed, (label,)) |
|
|
|
self.protected(self._show_seed, (label,)) |
|
|
|
|
|
|
|
def _show_seed(self, label, password): |
|
|
|
if self.wallet.has_password() and password is None: |
|
|
|
return |
|
|
|
keystore = self.wallet.keystore |
|
|
|
try: |
|
|
|
seed = keystore.get_seed(password) |
|
|
|
passphrase = keystore.get_passphrase(password) |
|
|
|
except: |
|
|
|
self.show_error("Invalid PIN") |
|
|
|
return |
|
|
|
seed = keystore.get_seed(password) |
|
|
|
passphrase = keystore.get_passphrase(password) |
|
|
|
label.data = seed |
|
|
|
if passphrase: |
|
|
|
label.data += '\n\n' + _('Passphrase') + ': ' + passphrase |
|
|
|
|
|
|
|
def password_dialog(self, *, wallet: Union[Abstract_Wallet, WalletStorage], |
|
|
|
msg: str, on_success: Callable = None, on_failure: Callable = None): |
|
|
|
from .uix.dialogs.password_dialog import PasswordDialog |
|
|
|
def has_pin_code(self): |
|
|
|
return bool(self.electrum_config.get('pin_code')) |
|
|
|
|
|
|
|
def check_pin_code(self, pin): |
|
|
|
if pin != self.electrum_config.get('pin_code'): |
|
|
|
raise InvalidPassword |
|
|
|
|
|
|
|
def password_dialog(self, *, check_password: Callable = None, |
|
|
|
on_success: Callable = None, on_failure: Callable = None, |
|
|
|
is_password=True): |
|
|
|
if self._password_dialog is None: |
|
|
|
self._password_dialog = PasswordDialog() |
|
|
|
self._password_dialog.init(self, wallet=wallet, msg=msg, |
|
|
|
on_success=on_success, on_failure=on_failure) |
|
|
|
self._password_dialog.init( |
|
|
|
self, check_password = check_password, |
|
|
|
on_success=on_success, on_failure=on_failure, |
|
|
|
is_password=is_password) |
|
|
|
self._password_dialog.open() |
|
|
|
|
|
|
|
def change_password(self, cb): |
|
|
|
from .uix.dialogs.password_dialog import PasswordDialog |
|
|
|
if self._password_dialog is None: |
|
|
|
self._password_dialog = PasswordDialog() |
|
|
|
message = _("Changing PIN code.") + '\n' + _("Enter your current PIN:") |
|
|
|
def on_success(old_password, new_password): |
|
|
|
self.wallet.update_password(old_password, new_password) |
|
|
|
self.show_info(_("Your PIN code was updated")) |
|
|
|
on_failure = lambda: self.show_error(_("PIN codes do not match")) |
|
|
|
self._password_dialog.init(self, wallet=self.wallet, msg=message, |
|
|
|
on_success=on_success, on_failure=on_failure, is_change=True) |
|
|
|
self.password = new_password |
|
|
|
self.show_info(_("Your password was updated")) |
|
|
|
on_failure = lambda: self.show_error(_("Password not updated")) |
|
|
|
self._password_dialog.init( |
|
|
|
self, check_password = self.wallet.check_password, |
|
|
|
on_success=on_success, on_failure=on_failure, |
|
|
|
is_change=True, is_password=True, |
|
|
|
has_password=self.wallet.has_password()) |
|
|
|
self._password_dialog.open() |
|
|
|
|
|
|
|
def change_backup_password(self): |
|
|
|
from .uix.dialogs.password_dialog import PasswordDialog |
|
|
|
from electrum.util import get_backup_dir |
|
|
|
from electrum.storage import WalletStorage |
|
|
|
def change_pin_code(self, cb): |
|
|
|
if self._password_dialog is None: |
|
|
|
self._password_dialog = PasswordDialog() |
|
|
|
message = _("Create backup.") + '\n' + _("Enter your current PIN:") |
|
|
|
def on_success(old_password, new_password): |
|
|
|
backup_pubkey = WalletStorage.get_eckey_from_password(new_password).get_public_key_hex() |
|
|
|
# TODO: use a unique PIN for all wallets |
|
|
|
self.electrum_config.set_key('backup_pubkey', backup_pubkey) |
|
|
|
self.show_info(_("Backup password set")) |
|
|
|
on_failure = lambda: self.show_error(_("Passwords do not match")) |
|
|
|
self._password_dialog.init(self, wallet=self.wallet, msg=message, |
|
|
|
on_success=on_success, on_failure=on_failure, is_change=True, is_backup=True) |
|
|
|
self.electrum_config.set_key('pin_code', new_password) |
|
|
|
cb() |
|
|
|
self.show_info(_("PIN updated") if new_password else _('PIN disabled')) |
|
|
|
on_failure = lambda: self.show_error(_("PIN not updated")) |
|
|
|
self._password_dialog.init( |
|
|
|
self, check_password=self.check_pin_code, |
|
|
|
on_success=on_success, on_failure=on_failure, |
|
|
|
is_change=True, is_password=False, |
|
|
|
has_password = self.has_pin_code()) |
|
|
|
self._password_dialog.open() |
|
|
|
|
|
|
|
def save_backup(self): |
|
|
@ -1238,7 +1248,7 @@ class ElectrumWindow(App): |
|
|
|
request_permissions([Permission.WRITE_EXTERNAL_STORAGE], cb) |
|
|
|
|
|
|
|
def _save_backup(self): |
|
|
|
new_path = self.wallet.save_backup(pin_code=self.pin_code) |
|
|
|
new_path = self.wallet.save_backup() |
|
|
|
if new_path: |
|
|
|
self.show_info(_("Backup saved:") + f"\n{new_path}") |
|
|
|
else: |
|
|
|