Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
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)