def run_offline_command(config, config_options): cmdname = config.get('cmd') cmd = known_commands[cmdname] password = config_options.get('password') if cmd.requires_wallet: wallet_path = config.get_cmdline_wallet_filepath() if not WalletStorage.files_are_matched_by_path(wallet_path): print("Error: wallet does not exist at given path") sys.exit(1) storage = WalletStorage(wallet_path) wallet = Wallet(storage) else: wallet = None if cmd.requires_password: try: wallet.check_password(password) except InvalidPassword: print( "Error: This password cannot access the wallet's private data." ) sys.exit(1) if cmd.requires_network: print("Warning: running command offline") # arguments passed to function args = [config.get(x) for x in cmd.params] # decode json arguments if cmdname not in ('setconfig', ): args = [json_decode(arg) for arg in args] # options kwargs = {} for x in cmd.options: kwargs[x] = (config_options.get(x) if x in ['password', 'new_password'] else config.get(x)) cmd_runner = Commands(config, wallet, None) func = getattr(cmd_runner, cmd.name) result = func(*args, **kwargs) # save wallet if wallet: wallet.save_storage() return result
def init_daemon(config_options): config = SimpleConfig(config_options) wallet_path = config.get_wallet_path() if not WalletStorage.files_are_matched_by_path(wallet_path): print("Error: Wallet file not found.") print("Type 'electrum-sv create' to create a new wallet, " "or provide a path to a wallet with the -w option") sys.exit(0) storage = WalletStorage(wallet_path) if 'wallet_password' in config_options: print( 'Warning: unlocking wallet with commandline argument \"--walletpassword\"' ) password = config_options['wallet_password'] elif config.get('password'): password = config.get('password') else: password = prompt_password('Password:'******'password'] = password
def select_storage(self, initial_path: str, is_startup=False): if is_startup: self._copy_electron_cash_wallets() vbox = QVBoxLayout() hbox = QHBoxLayout() hbox.addWidget(QLabel(_('Wallet') + ':')) self.name_e = QLineEdit() hbox.addWidget(self.name_e) button = QPushButton(_('Choose...')) hbox.addWidget(button) vbox.addLayout(hbox) self.msg_label = QLabel('') vbox.addWidget(self.msg_label) hbox2 = QHBoxLayout() self.pw_e = PasswordLineEdit() self.pw_e.setMinimumWidth(200) self.pw_label = QLabel(_('Password') + ':') self.pw_label.setAlignment(Qt.AlignTop) hbox2.addWidget(self.pw_label) hbox2.addWidget(self.pw_e) hbox2.addStretch() vbox.addLayout(hbox2) self._set_standard_layout(vbox, title=_('ElectrumSV wallet'), back_text=_(MSG_BUTTON_CANCEL)) esv_wallets_dir = os.path.join(app_state.config.electrum_path(), "wallets") if is_startup: def _show_copy_electron_cash_wallets_dialog(*args): nonlocal esv_wallets_dir, ec_wallets_dir d = WindowModalDialog(self, _("Copy Electron Cash Wallets")) d.setMinimumWidth(400) vbox, file_list = self._create_copy_electron_cash_wallets_layout( ec_wallets_dir) bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bbox.rejected.connect(d.reject) bbox.accepted.connect(d.accept) vbox.addWidget(bbox) d.setLayout(vbox) result = d.exec() if result == QDialog.Accepted: self._do_copy_electron_cash_wallets( file_list, esv_wallets_dir, ec_wallets_dir) _update_selected_wallet() ec_import_text = ("<p>" + _( "You have previously run Electron Cash and created at " + "least one wallet with it. ElectrumSV should not be used to open these wallets " + "directly using the 'Choose' button, and you should instead use the 'Import' " + "button to help you copy them." ) + "</p>" + "<p>" + _( "There are many reasons for this, and the simplest is that if Electron Cash " + "and ElectrumSV were to operate on the same wallet at the same time, then the " + "wallet will most likely become corrupted. It's simpler in every way to just " + "copy the wallet over to ElectrumSV and use a separate wallet file for each." ) + "</p>") ec_import_icon = HelpLabel("label text", ec_import_text) ec_import_icon.setPixmap( QPixmap(icon_path("icons8-info.svg")).scaledToWidth( 16, Qt.SmoothTransformation)) ec_import_label = QLabel( _("Existing Electron Cash wallets detected")) ec_import_button = QPushButton(_("Import...")) ec_import_button.clicked.connect( _show_copy_electron_cash_wallets_dialog) self.template_hbox.addWidget(ec_import_icon) self.template_hbox.addWidget(ec_import_label) self.template_hbox.addWidget(ec_import_button) self.template_hbox.addStretch(1) ec_wallets_dir = get_electron_cash_user_dir(esv_wallets_dir) if len(self._list_user_wallets(ec_wallets_dir)) == 0: ec_import_icon.set_help_text("<p>" + _( "This feature is aimed at users who were " + "already using Electron Cash and have existing wallets associated with it. " + "None were detected on this computer, but if you do have some stored in " + "places ElectrumSV does not know about you may need to copy them " + "yourself." ) + "</p>" + "<p>" + _( "You should never open your existing Electron Cash wallets directly in " + "ElectrumSV as this can lead to them being opened in both applications at " + "the same time, and can result in corruption.") + "</p>") ec_import_button.setEnabled(False) ec_import_button.setToolTip(_("Nothing to import")) ec_import_label.setText(_("No Electron Cash wallets detected")) if WalletStorage.files_are_matched_by_path(initial_path): self._storage_existing = WalletStorage(initial_path, manual_upgrades=True) wallet_folder = os.path.dirname(initial_path) def _on_choose() -> None: path, __ = QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder) if path: self.name_e.setText(path) def _on_filename(filename: str) -> None: pw = False self._storage_existing = None # A relative path will be relative to the folder we offered in the choose dialog. # An absolute path will not get joined to the dialog folder (no-op). path = os.path.join(wallet_folder, filename) if WalletStorage.files_are_matched_by_path(path): try: self._storage_existing = WalletStorage( path, manual_upgrades=True) except IOError: self.next_button.setEnabled(False) msg = _('Cannot read file') else: self.next_button.setEnabled(True) if self._storage_existing.is_encrypted(): msg = '\n'.join([ _("This file is encrypted."), _('Enter your password or choose another file.'), ]) pw = True else: msg = _("Press 'Next' to open this wallet.") else: msg = _("This file does not exist.") if os.access(wallet_folder, os.W_OK): self.next_button.setEnabled(True) msg += "\n" + _( "Press 'Next' to create this wallet, or choose another file." ) self._path_new = path else: self.next_button.setEnabled(False) msg += "\n" + _("You do not have write access " + "to this folder to create a new wallet.") self.msg_label.setText(msg) if pw: self.pw_label.show() self.pw_e.show() self.pw_e.setFocus() else: self.pw_label.hide() self.pw_e.hide() def _update_selected_wallet( skip_pick_most_recent: bool = False) -> None: wallet_filename = None if is_startup and not skip_pick_most_recent and self._storage_existing is None: esv_wallet_names = self._list_user_wallets(esv_wallets_dir) if len(esv_wallet_names): wallet_filename = esv_wallet_names[0] if wallet_filename is None: if self._storage_existing is not None: wallet_filename = os.path.basename( self._storage_existing.get_path()) else: wallet_filename = os.path.basename(initial_path) self.name_e.setText(wallet_filename) button.clicked.connect(_on_choose) self.name_e.textChanged.connect(_on_filename) # We do not pick the most recent when first displaying the wizard because we want to # treat the preselected wallet as the user's explicit choice. So a non-existent name # should be a possible wallet creation. _update_selected_wallet(skip_pick_most_recent=True) while True: if self._storage_existing is not None and not self._storage_existing.is_encrypted( ): break if self.loop.exec_() != 2: # 2 = next return if self._storage_existing is None: break if self._storage_existing is not None and self._storage_existing.is_encrypted( ): password = self.pw_e.text() try: self._storage_existing.decrypt(password) self.pw_e.setText('') break except DecryptionError: QMessageBox.information(None, _('Error'), _("Incorrect password")) continue except Exception as e: logger.exception("decrypting storage") QMessageBox.information(None, _('Error'), str(e)) return return True
def run_non_RPC(config): cmdname = config.get('cmd') wallet_path = config.get_wallet_path() if WalletStorage.files_are_matched_by_path(wallet_path): sys.exit("Error: wallet name in use at given path") storage = WalletStorage(wallet_path) def password_dialog(): return prompt_password( "Password (hit return if you do not wish to encrypt your wallet):") if cmdname == 'restore': text = config.get('text').strip() passphrase = config.get('passphrase', '') password = password_dialog() if keystore.is_private(text) else None parent_wallet = ParentWallet.as_legacy_wallet_container(storage) if keystore.is_address_list(text): legacy_wallet = ImportedAddressWallet.from_text( parent_wallet, text) elif keystore.is_private_key_list(text): legacy_wallet = ImportedPrivkeyWallet.from_text( parent_wallet, text) else: if keystore.is_seed(text): k = keystore.from_seed(text, passphrase, False) elif keystore.is_master_key(text): k = keystore.from_master_key(text) else: sys.exit("Error: Seed or key not recognized") keystore_usage = parent_wallet.add_keystore(k.dump()) Standard_Wallet.create_within_parent( parent_wallet, keystore_usage=[keystore_usage]) if password: parent_wallet.update_password(None, password) if not config.get('offline'): network = Network() network.add_wallet(parent_wallet) print("Recovering wallet...") parent_wallet.synchronize() msg = ("Recovery successful" if parent_wallet.has_usage() else "Found no history for this wallet") else: msg = ("This wallet was restored offline. " "It may contain more addresses than displayed.") print(msg) elif cmdname == 'create': password = password_dialog() passphrase = config.get('passphrase', '') seed_type = 'standard' seed = Mnemonic('en').make_seed(seed_type) k = keystore.from_seed(seed, passphrase, False) parent_wallet = ParentWallet.as_legacy_wallet_container(storage) keystore_usage = parent_wallet.add_keystore(k.dump()) Standard_Wallet.create_within_parent(parent_wallet, keystore_usage=[keystore_usage]) parent_wallet.update_password(None, password) parent_wallet.synchronize() print("Your wallet generation seed is:\n\"%s\"" % seed) print("Please keep it in a safe place; if you lose it, " "you will not be able to restore your wallet.") parent_wallet.save_storage() print(f"Wallet saved in '{parent_wallet.get_storage_path()}'") sys.exit(0)