Esempio n. 1
0
    def _update_transactions_tab_summary(self) -> None:
        local_count = 0
        local_value = 0

        if self._account_id is not None:
            wallet = self._account.get_wallet()
            with wallet.get_transaction_delta_table() as table:
                _account_id, local_value, local_count = table.read_balance(
                    self._account_id, mask=TxFlags.STATE_UNCLEARED_MASK)

        if local_count == 0:
            self._local_summary_label.setVisible(False)
            return

        value_text = app_state.format_amount(
            local_value) + " " + app_state.base_unit()
        if local_count == 1:
            text = _(
                "The Transactions tab has <b>1</b> transaction containing <b>{balance}</b> "
                "in allocated coins.").format(balance=value_text)
        else:
            text = _(
                "The Transactions tab has <b>{count}</b> transactions containing "
                "<b>{balance}</b> in allocated coins.").format(
                    count=local_count, balance=value_text)
        self._local_summary_label.setText(text)
        self._local_summary_label.setVisible(True)
Esempio n. 2
0
 def set_content(self, address_text, amount, message, url):
     self.address_label.setText(address_text)
     if amount:
         amount_text = '{} {}'.format(self.win.format_amount(amount),
                                      app_state.base_unit())
     else:
         amount_text = ''
     self.amount_label.setText(amount_text)
     self.msg_label.setText(message)
     self.qrw.setData(url)
Esempio n. 3
0
 def set_content(self, address_text, amount, message, url):
     self._address_edit.setPlainText(address_text)
     if amount:
         amount_text = '{} {}'.format(app_state.format_amount(amount),
                                      app_state.base_unit())
     else:
         amount_text = ''
     self._amount_edit.setText(amount_text)
     self._message_edit.setPlainText(message)
     self.qrw.setData(url)
Esempio n. 4
0
    def _on_entry_changed(self) -> None:
        text = ""
        if self._not_enough_funds:
            amt_color = ColorScheme.RED
            text = _("Not enough funds")
            c, u, x = self._account.get_frozen_balance()
            if c + u + x:
                text += (' (' + app_state.format_amount(c + u + x).strip() +
                         ' ' + app_state.base_unit() + ' ' + _("are frozen") +
                         ')')

        if self.amount_e.isModified():
            amt_color = ColorScheme.DEFAULT
        else:
            amt_color = ColorScheme.BLUE

        self._main_window.statusBar().showMessage(text)
        self.amount_e.setStyleSheet(amt_color.as_stylesheet())
Esempio n. 5
0
    def update(self):
        desc = self.desc
        base_unit = app_state.base_unit()
        format_amount = self.main_window.format_amount
        tx_info = self.wallet.get_tx_info(self.tx)
        tx_info_fee = tx_info.fee

        size = self.tx.estimated_size()
        self.broadcast_button.setEnabled(tx_info.can_broadcast)
        if self.main_window.network is None:
            self.broadcast_button.setEnabled(False)
            self.broadcast_button.setToolTip(
                _('You are using ElectrumSV in offline mode; restart '
                  'ElectrumSV if you want to get connected'))
        can_sign = not self.tx.is_complete() and \
            (self.wallet.can_sign(self.tx) or bool(self.main_window.tx_external_keypairs))
        self.sign_button.setEnabled(can_sign)
        self._tx_hash = tx_info.hash
        self.tx_hash_e.setText(tx_info.hash or _('Unknown'))
        if tx_info_fee is None:
            try:
                # Try and compute fee. We don't always have 'value' in
                # all the inputs though. :/
                tx_info_fee = self.tx.get_fee()
            except KeyError:  # Value key missing from an input
                pass
        if desc is None:
            self.tx_desc.hide()
        else:
            self.tx_desc.setText(_("Description") + ': ' + desc)
            self.tx_desc.show()
        self.status_label.setText(_('Status:') + ' ' + tx_info.status)

        if tx_info.timestamp:
            time_str = datetime.datetime.fromtimestamp(
                tx_info.timestamp).isoformat(' ')[:-3]
            self.date_label.setText(_("Date: {}").format(time_str))
            self.date_label.show()
        else:
            self.date_label.hide()
        if tx_info.amount is None:
            amount_str = _("Transaction unrelated to your wallet")
        elif tx_info.amount > 0:
            amount_str = '{} {} {}'.format(_("Amount received:"),
                                           format_amount(tx_info.amount),
                                           base_unit)
        else:
            amount_str = '{} {} {}'.format(_("Amount sent:"),
                                           format_amount(-tx_info.amount),
                                           base_unit)
        size_str = _("Size:") + ' %d bytes' % size
        if tx_info_fee is not None:
            fee_amount = '{} {}'.format(format_amount(tx_info_fee), base_unit)
        else:
            fee_amount = _('unknown')
        fee_str = '{}: {}'.format(_("Fee"), fee_amount)
        if tx_info_fee is not None:
            fee_str += '  ( {} ) '.format(
                self.main_window.format_fee_rate(tx_info_fee / size * 1000))
        self.amount_label.setText(amount_str)
        self.fee_label.setText(fee_str)
        self.size_label.setText(size_str)

        # Cosigner button
        visible = app_state.app.cosigner_pool.show_button(self.wallet, self.tx)
        self.cosigner_button.setVisible(visible)
Esempio n. 6
0
    def update(self) -> None:
        base_unit = app_state.base_unit()
        format_amount = app_state.format_amount
        tx_info = self._get_tx_info(self.tx)
        tx_info_fee = tx_info.fee

        self.broadcast_button.setEnabled(tx_info.can_broadcast)
        if self._main_window.network is None:
            self.broadcast_button.setEnabled(False)
            self.broadcast_button.setToolTip(
                _('You are using ElectrumSV in offline mode; restart '
                  'ElectrumSV if you want to get connected'))

        can_sign = not self.tx.is_complete() and self._account.can_sign(
            self.tx)
        self.sign_button.setEnabled(can_sign)

        self._tx_hash = tx_info.hash
        tx_id = hash_to_hex_str(tx_info.hash)
        self.tx_hash_e.setText(tx_id)

        if tx_info_fee is None:
            try:
                # Try and compute fee. We don't always have 'value' in all the inputs though. :/
                tx_info_fee = self.tx.get_fee()
            except TypeError:  # At least one of the XTxInputs does not have an attached value.
                pass
            else:
                if tx_info_fee < 0:
                    tx_info_fee = None

        if self.tx.context.description is None:
            self.tx_desc.hide()
        else:
            self.tx_desc.setText(self.tx.context.description)
            self.tx_desc.show()
        self.status_label.setText(tx_info.status)

        time_str = ""
        if tx_info.date_mined:
            time_str = datetime.datetime.fromtimestamp(
                tx_info.date_mined).isoformat(' ')[:-3]
            time_str += "\n"
        if tx_info.date_created:
            time_str += (datetime.datetime.fromtimestamp(
                tx_info.date_created).isoformat(' ')[:-3] + " (" +
                         _("added to account") + ")")

        self.date_label.setText(time_str)
        self.date_label.show()

        if tx_info.amount is None:
            amount_str = _("Unknown")
        elif math.isclose(tx_info.amount, 0, abs_tol=1e-9):
            amount_str = "No external payment"
        elif tx_info.amount > 0:
            amount_str = _("Received") + " " + format_amount(
                tx_info.amount) + " " + base_unit
        else:
            amount_str = _("Sent") + " " + format_amount(
                -tx_info.amount) + " " + base_unit
        self.amount_label.setText(amount_str)

        size = self.tx.size()
        self.size_label.setText('%d bytes' % size)

        if tx_info_fee is not None:
            fee_amount = '{} {}'.format(format_amount(tx_info_fee), base_unit)
        else:
            fee_amount = _('Unknown')
        fee_str = '{}'.format(fee_amount)
        if tx_info_fee is not None:
            fee_str += ' ({}) '.format(
                self._main_window.format_fee_rate(tx_info_fee / size * 1000))
        self.fee_label.setText(fee_str)

        # Cosigner button
        visible = app_state.app.cosigner_pool.show_send_to_cosigner_button(
            self._main_window, self._account, self.tx)
        self.cosigner_button.setVisible(visible)

        # Copy options.
        self._copy_menu.clear()
        if self.tx.is_complete():
            self._copy_hex_menu = self._copy_menu.addAction(
                _("Transaction (hex)"),
                partial(self._copy_transaction, TxSerialisationFormat.HEX))
            if self._account:
                self._copy_extended_full_menu = self._copy_menu.addAction(
                    _("Transaction with proofs (JSON)"),
                    partial(self._copy_transaction,
                            TxSerialisationFormat.JSON_WITH_PROOFS))
        else:
            self._copy_extended_basic_menu = self._copy_menu.addAction(
                _("Incomplete transaction (JSON)"),
                partial(self._copy_transaction, TxSerialisationFormat.JSON))
            if self._account:
                self._copy_extended_full_menu = self._copy_menu.addAction(
                    _("Incomplete transaction with proofs (JSON)"),
                    partial(self._copy_transaction,
                            TxSerialisationFormat.JSON_WITH_PROOFS))

        # Save options.
        self._save_menu.clear()
        if self.tx.is_complete():
            self._save_raw_menu = self._save_menu.addAction(
                _("Transaction (raw)"),
                partial(self._save_transaction, TxSerialisationFormat.RAW))
            self._save_hex_menu = self._save_menu.addAction(
                _("Transaction (hex)"),
                partial(self._save_transaction, TxSerialisationFormat.HEX))
            if self._account:
                self._save_extended_full_menu = self._save_menu.addAction(
                    _("Transaction with proofs (JSON)"),
                    partial(self._save_transaction,
                            TxSerialisationFormat.JSON_WITH_PROOFS))
        else:
            self._save_extended_basic_menu = self._save_menu.addAction(
                _("Incomplete transaction (JSON)"),
                partial(self._save_transaction, TxSerialisationFormat.JSON))
            if self._account:
                self._save_extended_full_menu = self._save_menu.addAction(
                    _("Incomplete transaction with proofs (JSON)"),
                    partial(self._save_transaction,
                            TxSerialisationFormat.JSON_WITH_PROOFS))
    def update_balances(self):
        wallet = self._main_window._wallet

        self.unfrozen_balance = self._account.get_balance(
            exclude_frozen_coins=True)
        self.frozen_balance = self._account.get_frozen_balance()

        unfrozen_confirmed, unfrozen_unconfirmed, _unfrozen_unmature = self.unfrozen_balance
        _frozen_confirmed, _frozen_unconfirmed, _frozen_unmature = self.frozen_balance

        splittable_amount = unfrozen_confirmed + unfrozen_unconfirmed
        # unsplittable_amount = unfrozen_unmature + frozen_confirmed + frozen_unconfirmed
        # + frozen_unmature

        splittable_amount_text = self._main_window.format_amount(
            splittable_amount)
        unit_text = app_state.base_unit()

        text = [
            "<p>",
            _("As of the November 2018 hard-fork, Bitcoin Cash split into Bitcoin ABC "
              "and Bitcoin SV."),
            " ",
            _("This tab allows you to easily split the available coins in this account "
              "(approximately {} {}) on the Bitcoin SV chain.".format(
                  splittable_amount_text, unit_text)),
            " ",
            _("This will involve the following steps if you choose to proceed:"
              ),
            "</p>",
            "<ol>",
            "<li>",
            _("Your browser will open to a faucet that can provide you with a small amount of SV "
              "coin. Once you have operated the faucet, and obtained it, ElectrumSV will "
              "detect it."),
            "</li>",
            "<li>",
            _("A transaction will be constructed including your entire spendable balance "
              "combined with the new known SV coin from the faucet, to be sent back into "
              "this account."),
            "</li>",
        ]
        text.extend([
            "<li>",
            _("As this account is password protected, you will be prompted to "
              "enter your password to sign the transaction."),
            "</li>",
        ])
        text.extend([
            "<li>",
            _("The transaction will then be broadcast, and immediately added to your "
              "account history so you can see it confirmed. It will be labeled as splitting "
              "related, so you can easily identify it."),
            "</li>",
            "<li>",
            _("You can then open Electron Cash and move your ABC coins to a different address, "
              "in order to finalise the split."),
            "</li>",
            "</ol>",
            "<p>",
            _("<b>This will only split the coins currently available in this account.</b> "
              "While any further coins you send to your account are included in the overall "
              "balance, if they were unsplit before sending, they remain unsplit on arrival. "
              "It it your responsibility to ensure you know if you are sending unsplit coins "
              "and what the repercussions are. If in doubt, click split and be sure."
              ),
            "</p>",
        ])

        self.intro_label.setText("".join(text))
Esempio n. 8
0
    def general_widgets(self):
        # language
        lang_modifiable = app_state.config.is_modifiable('language')
        lang_pairs = sorted(
            (code, language) for language, code in languages.items())
        language_names, language_keys = zip(*lang_pairs)

        lang_label = HelpLabel(
            _('Language') + ':',
            _('Select which language is used in the GUI (after restart).'))
        lang_label.setEnabled(lang_modifiable)

        lang_combo = QComboBox()
        lang_combo.setEnabled(lang_modifiable)
        lang_combo.addItems(language_names)
        try:
            index = language_keys.index(app_state.config.get("language", ''))
        except ValueError:
            index = 0
        lang_combo.setCurrentIndex(index)

        def on_lang(index):
            lang_request = language_keys[index]
            if lang_request != app_state.config.get('language'):
                app_state.config.set_key("language", lang_request, True)

        lang_combo.currentIndexChanged.connect(on_lang)

        nz_modifiable = app_state.config.is_modifiable('num_zeros')
        nz_label = HelpLabel(
            _('Zeros after decimal point') + ':',
            _('Number of zeros displayed after the decimal point.  '
              'For example, if set to 2, "1." will be displayed as "1.00"'))
        nz_label.setEnabled(nz_modifiable)
        nz = QSpinBox()
        nz.setMinimum(0)
        nz.setMaximum(app_state.decimal_point)
        nz.setValue(app_state.num_zeros)
        nz.setEnabled(nz_modifiable)

        def on_nz():
            value = nz.value()
            if app_state.num_zeros != value:
                app_state.num_zeros = value
                app_state.config.set_key('num_zeros', value, True)
                app_state.app.num_zeros_changed.emit()

        nz.valueChanged.connect(on_nz)

        unit_label = HelpLabel(
            _('Base unit') + ':', '\n'.join((
                _('Base unit of display in the application.'),
                '1 BSV = 1,000 mBSV = 1,000,000 bits.',
            )))
        unit_combo = QComboBox()
        unit_combo.addItems(app_state.base_units)
        unit_combo.setCurrentIndex(
            app_state.base_units.index(app_state.base_unit()))

        def on_unit(index):
            app_state.set_base_unit(app_state.base_units[index])
            nz.setMaximum(app_state.decimal_point)

        unit_combo.currentIndexChanged.connect(on_unit)

        msg = _(
            'Choose which online block explorer to use for functions that open a web browser'
        )
        block_ex_label = HelpLabel(_('Online Block Explorer') + ':', msg)
        block_explorers = web.BE_sorted_list()
        block_ex_combo = QComboBox()
        block_ex_combo.addItems(block_explorers)
        block_ex_combo.setCurrentIndex(
            block_ex_combo.findText(web.BE_from_config(app_state.config)))

        def on_be(index):
            app_state.config.set_key('block_explorer', block_explorers[index],
                                     True)

        block_ex_combo.currentIndexChanged.connect(on_be)

        qr_label = HelpLabel(
            _('Video Device') + ':',
            _("Install the zbar package to enable this."))
        qr_combo = QComboBox()
        qr_combo.addItem("Default", "default")
        system_cameras = qrscanner.find_system_cameras()
        for camera, device in system_cameras.items():
            qr_combo.addItem(camera, device)
        qr_combo.setCurrentIndex(
            qr_combo.findData(app_state.config.get("video_device")))
        qr_combo.setEnabled(qrscanner.libzbar is not None)

        def on_video_device(index):
            app_state.config.set_key("video_device", qr_combo.itemData(index),
                                     True)

        qr_combo.currentIndexChanged.connect(on_video_device)

        updatecheck_box = QGroupBox(_("Software Updates"))
        updatecheck_vbox = QVBoxLayout()
        updatecheck_box.setLayout(updatecheck_vbox)
        # The main checkbox, which turns update checking on or off completely.
        updatecheck_cb = QCheckBox(
            _("Automatically check for software updates"))
        updatecheck_cb.setChecked(app_state.config.get('check_updates', True))

        def on_set_updatecheck(v):
            app_state.config.set_key('check_updates',
                                     v == Qt.Checked,
                                     save=True)

        updatecheck_cb.stateChanged.connect(on_set_updatecheck)
        updatecheck_vbox.addWidget(updatecheck_cb)
        # The secondary checkbox, which determines if unstable releases result in notifications.
        updatecheck_unstable_cb = QCheckBox(_("Ignore unstable releases"))
        updatecheck_unstable_cb.setChecked(
            app_state.config.get('check_updates_ignore_unstable', True))

        def on_set_updatecheck_unstable(v):
            app_state.config.set_key('check_updates_ignore_unstable',
                                     v == Qt.Checked,
                                     save=True)

        updatecheck_unstable_cb.stateChanged.connect(
            on_set_updatecheck_unstable)
        updatecheck_vbox.addWidget(updatecheck_unstable_cb)

        return [
            (lang_label, lang_combo),
            (nz_label, nz),
            (unit_label, unit_combo),
            (block_ex_label, block_ex_combo),
            (qr_label, qr_combo),
            (updatecheck_box, ),
        ]
Esempio n. 9
0
 def get_base_unit(self) -> str:
     return app_state.base_unit()
Esempio n. 10
0
    def update_balances(self):
        window = self.window()
        wallet = window.wallet

        self.unfrozen_balance = wallet.get_balance(
            exclude_frozen_coins=True, exclude_frozen_addresses=True)
        self.frozen_balance = wallet.get_frozen_balance()

        unfrozen_confirmed, unfrozen_unconfirmed, _unfrozen_unmature = self.unfrozen_balance
        _frozen_confirmed, _frozen_unconfirmed, _frozen_unmature = self.frozen_balance

        splittable_amount = unfrozen_confirmed + unfrozen_unconfirmed
        # unsplittable_amount = unfrozen_unmature + frozen_confirmed + frozen_unconfirmed
        # + frozen_unmature

        splittable_amount_text = window.format_amount(splittable_amount)
        unit_text = app_state.base_unit()

        text = [
            "<p>",
            _("As of the November 2018 hard-fork, Bitcoin Cash split into Bitcoin ABC "
              "and Bitcoin SV."),
            " ",
            _("This tab allows you to easily split the available coins in this wallet "
              "(approximately {} {}) on the Bitcoin SV chain.".format(
                  splittable_amount_text, unit_text)),
            " ",
            _("This will involve the following steps if you choose to proceed:"
              ),
            "</p>",
            "<ol>",
            "<li>",
            _("A small amount of SV coin will be obtained from a faucet."),
            "</li>",
            "<li>",
            _("A transaction will be constructed including your entire spendable balance "
              "combined with the new known SV coin from the faucet, to be sent back into "
              "this wallet."),
            "</li>",
        ]
        if wallet.has_password():
            text.extend([
                "<li>",
                _("As this wallet is password protected, you will be prompted to "
                  "enter your password to sign the transaction."),
                "</li>",
            ])
        text.extend([
            "<li>",
            _("The transaction will then be broadcast, and immediately added to your "
              "wallet history so you can see it confirmed. It will be labeled as splitting "
              "related, so you can easily identify it."),
            "</li>",
            "<li>",
            _("You can then open Electron Cash and move your ABC coins to a different address, "
              "in order to finalise the split."),
            "</li>",
            "</ol>",
        ])

        self.intro_label.setText("".join(text))
Esempio n. 11
0
    def update(self) -> None:
        base_unit = app_state.base_unit()
        format_amount = self._main_window.format_amount
        tx_info = self.get_tx_info(self.tx)
        tx_info_fee = tx_info.fee

        size = self.tx.size()
        self.broadcast_button.setEnabled(tx_info.can_broadcast)
        if self._main_window.network is None:
            self.broadcast_button.setEnabled(False)
            self.broadcast_button.setToolTip(_('You are using ElectrumSV in offline mode; restart '
                                               'ElectrumSV if you want to get connected'))
        can_sign = not self.tx.is_complete() and self._account.can_sign(self.tx)
        self.sign_button.setEnabled(can_sign)
        self._tx_hash = tx_info.hash
        tx_id = hash_to_hex_str(tx_info.hash)
        self.tx_hash_e.setText(tx_id)
        if tx_info_fee is None:
            try:
                # Try and compute fee. We don't always have 'value' in
                # all the inputs though. :/
                tx_info_fee = self.tx.get_fee()
            except KeyError: # Value key missing from an input
                pass
            if tx_info_fee < 0:
                tx_info_fee = None
        if self.tx.description is None:
            self.tx_desc.hide()
        else:
            self.tx_desc.setText(self.tx.description)
            self.tx_desc.show()
        self.status_label.setText(tx_info.status)

        if tx_info.timestamp:
            time_str = datetime.datetime.fromtimestamp(
                tx_info.timestamp).isoformat(' ')[:-3]
            self.date_label.setText(time_str)
            self.date_label.show()
        else:
            self.date_label.hide()
        if tx_info.amount is None:
            amount_str = _("Transaction unrelated to your wallet")
        elif tx_info.amount > 0:
            amount_str = '{} {} {}'.format(_("Received") +" ",
                                           format_amount(tx_info.amount),
                                           base_unit)
        else:
            amount_str = '{} {} {}'.format(_("Sent") +" ",
                                           format_amount(-tx_info.amount),
                                           base_unit)
        size_str = '%d bytes'% size
        if tx_info_fee is not None:
            fee_amount = '{} {}'.format(format_amount(tx_info_fee), base_unit)
        else:
            fee_amount = _('unknown')
        fee_str = '{}'.format(fee_amount)
        if tx_info_fee is not None:
            fee_str += ' ({}) '.format(self._main_window.format_fee_rate(
                tx_info_fee / size * 1000))
        self.amount_label.setText(amount_str)
        self.fee_label.setText(fee_str)
        self.size_label.setText(size_str)

        # Cosigner button
        visible = app_state.app.cosigner_pool.show_send_to_cosigner_button(self._main_window,
            self._account, self.tx)
        self.cosigner_button.setVisible(visible)
Esempio n. 12
0
    def __init__(self, main_window: 'ElectrumWindow', row: InvoiceRow) -> None:
        super().__init__(main_window, _("Invoice"))

        self.setMinimumWidth(400)

        self._main_window = weakref.proxy(main_window)

        self._pr = pr = PaymentRequest.from_json(row.invoice_data)

        state = row.flags & PaymentFlag.STATE_MASK
        if state & PaymentFlag.UNPAID and has_expired(row.date_expires):
            state = PaymentFlag.EXPIRED

        total_amount = 0
        for output in pr.outputs:
            total_amount += output.amount

        vbox = QVBoxLayout(self)
        form = FormSectionWidget(minimum_label_width=120)
        form.add_row(_('Type'), QLabel(_("BIP270")))
        form.add_row(_("State"), QLabel(pr_tooltips.get(state, _("Unknown"))))
        form.add_row(
            _('Amount'),
            QLabel(
                app_state.format_amount(output.amount) + " " +
                app_state.base_unit()))
        form.add_row(_('Memo'), QLabel(row.description))
        form.add_row(_('Date Created'),
                     QLabel(format_time(pr.creation_timestamp, _("Unknown"))))
        form.add_row(_('Date Received'),
                     QLabel(format_time(row.date_created, _("Unknown"))))
        if row.date_expires:
            form.add_row(_('Date Expires'),
                         QLabel(format_time(row.date_expires, _("Unknown"))))
        vbox.addWidget(form)

        self._table = table = ButtonsTableWidget()
        table.setSelectionBehavior(QAbstractItemView.SelectRows)
        table.setSelectionMode(QAbstractItemView.SingleSelection)

        vh = table.verticalHeader()
        vh.setSectionResizeMode(QHeaderView.ResizeToContents)
        vh.hide()

        table.setColumnCount(3)
        table.setContextMenuPolicy(Qt.CustomContextMenu)
        table.customContextMenuRequested.connect(self._on_table_menu)
        table.setHorizontalHeaderLabels(self._table_column_names)
        table.setRowCount(len(pr.outputs))
        # table.addButton("icons8-copy-to-clipboard-32.png", f,
        #     _("Copy all listed destinations to the clipboard"))
        # table.addButton("icons8-save-as-32-windows.png", f,
        #     _("Save the listed destinations to a file"))
        hh = table.horizontalHeader()
        hh.setStretchLastSection(True)

        for row, output in enumerate(pr.outputs):
            label = QLabel(
                app_state.format_amount(output.amount) + " " +
                app_state.base_unit())
            table.setCellWidget(row, 0, label)

            table.setCellWidget(row, 1, QLabel(output.description))

            kind = classify_output_script(output.script, Net.COIN)
            text = script_to_display_text(output.script, kind)
            table.setCellWidget(row, 2, QLabel(text))

            vbox.addWidget(table, 1)

        def do_export():
            fn = self._main_window.getSaveFileName(_("Export invoice to file"),
                                                   "*.bip270.json")
            if not fn:
                return
            with open(fn, 'w') as f:
                data = f.write(row.invoice_data)
            self._main_window.show_message(_('Invoice saved as' + ' ' + fn))

        exportButton = EnterButton(_('Export'), do_export)

        def do_delete():
            if self.question(
                    _('Are you sure you want to delete this invoice?'),
                    title=_("Delete invoice"),
                    icon=QMessageBox.Warning):
                self._main_window._send_view._invoice_list._delete_invoice(
                    row.invoice_id)
                self.close()

        deleteButton = EnterButton(_('Delete'), do_delete)

        vbox.addLayout(Buttons(exportButton, deleteButton, CloseButton(self)))
Esempio n. 13
0
    def update(self) -> None:
        base_unit = app_state.base_unit()
        format_amount = app_state.format_amount
        tx_info = self._get_tx_info(self.tx)
        tx_info_fee = tx_info.fee

        self.broadcast_button.setEnabled(tx_info.can_broadcast)
        if self._main_window.network is None:
            self.broadcast_button.setEnabled(False)
            self.broadcast_button.setToolTip(
                _('You are using ElectrumSV in offline mode; restart '
                  'ElectrumSV if you want to get connected'))

        can_sign = not self.tx.is_complete() and self._account.can_sign(
            self.tx)
        self.sign_button.setEnabled(can_sign)

        self._tx_hash = tx_info.hash
        tx_id = hash_to_hex_str(tx_info.hash)
        self.tx_hash_e.setText(tx_id)

        if tx_info_fee is None:
            try:
                # Try and compute fee. We don't always have 'value' in all the inputs though. :/
                tx_info_fee = self.tx.get_fee()
            except TypeError:  # At least one of the XTxInputs does not have an attached value.
                pass
            else:
                if tx_info_fee < 0:
                    tx_info_fee = None

        if self.tx.description is None:
            self.tx_desc.hide()
        else:
            self.tx_desc.setText(self.tx.description)
            self.tx_desc.show()
        self.status_label.setText(tx_info.status)

        if tx_info.timestamp:
            time_str = datetime.datetime.fromtimestamp(
                tx_info.timestamp).isoformat(' ')[:-3]
            self.date_label.setText(time_str)
            self.date_label.show()
        else:
            self.date_label.hide()

        if tx_info.amount is None:
            amount_str = _("Unknown")
        elif math.isclose(tx_info.amount, 0, abs_tol=1e-9):
            amount_str = "No external payment"
        elif tx_info.amount > 0:
            amount_str = _("Received") + " " + format_amount(
                tx_info.amount) + " " + base_unit
        else:
            amount_str = _("Sent") + " " + format_amount(
                -tx_info.amount) + " " + base_unit
        self.amount_label.setText(amount_str)

        size = self.tx.size()
        self.size_label.setText('%d bytes' % size)

        if tx_info_fee is not None:
            fee_amount = '{} {}'.format(format_amount(tx_info_fee), base_unit)
        else:
            fee_amount = _('Unknown')
        fee_str = '{}'.format(fee_amount)
        if tx_info_fee is not None:
            fee_str += ' ({}) '.format(
                self._main_window.format_fee_rate(tx_info_fee / size * 1000))
        self.fee_label.setText(fee_str)

        # Cosigner button
        visible = app_state.app.cosigner_pool.show_send_to_cosigner_button(
            self._main_window, self._account, self.tx)
        self.cosigner_button.setVisible(visible)