URI: 
       tadd unconfirmed state for onchain invoices and requests - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 90abfda12bf78ce13332ab0474dcade418a211b1
   DIR parent d50a8d1b843d9f155e58e846ed5fa4ff8d28c929
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Tue, 12 Jan 2021 10:49:46 +0100
       
       add unconfirmed state for onchain invoices and requests
       
       Diffstat:
         M electrum/gui/qt/util.py             |       3 ++-
         M electrum/invoices.py                |       3 +++
         M electrum/wallet.py                  |      30 +++++++++++++++++++++---------
       
       3 files changed, 26 insertions(+), 10 deletions(-)
       ---
   DIR diff --git a/electrum/gui/qt/util.py b/electrum/gui/qt/util.py
       t@@ -26,7 +26,7 @@ from PyQt5.QtWidgets import (QPushButton, QLabel, QMessageBox, QHBoxLayout,
        
        from electrum.i18n import _, languages
        from electrum.util import FileImportFailed, FileExportFailed, make_aiohttp_session, resource_path
       -from electrum.invoices import PR_UNPAID, PR_PAID, PR_EXPIRED, PR_INFLIGHT, PR_UNKNOWN, PR_FAILED, PR_ROUTING
       +from electrum.invoices import PR_UNPAID, PR_PAID, PR_EXPIRED, PR_INFLIGHT, PR_UNKNOWN, PR_FAILED, PR_ROUTING, PR_UNCONFIRMED
        
        if TYPE_CHECKING:
            from .main_window import ElectrumWindow
       t@@ -52,6 +52,7 @@ pr_icons = {
            PR_INFLIGHT:"unconfirmed.png",
            PR_FAILED:"warning.png",
            PR_ROUTING:"unconfirmed.png",
       +    PR_UNCONFIRMED:"unconfirmed.png",
        }
        
        
   DIR diff --git a/electrum/invoices.py b/electrum/invoices.py
       t@@ -29,6 +29,7 @@ PR_PAID     = 3     # send and propagated
        PR_INFLIGHT = 4     # unconfirmed
        PR_FAILED   = 5
        PR_ROUTING  = 6
       +PR_UNCONFIRMED = 7
        
        pr_color = {
            PR_UNPAID:   (.7, .7, .7, 1),
       t@@ -38,6 +39,7 @@ pr_color = {
            PR_INFLIGHT: (.9, .6, .3, 1),
            PR_FAILED:   (.9, .2, .2, 1),
            PR_ROUTING: (.9, .6, .3, 1),
       +    PR_UNCONFIRMED: (.9, .6, .3, 1),
        }
        
        pr_tooltips = {
       t@@ -48,6 +50,7 @@ pr_tooltips = {
            PR_INFLIGHT:_('In progress'),
            PR_FAILED:_('Failed'),
            PR_ROUTING: _('Computing route...'),
       +    PR_UNCONFIRMED: _('Unconfirmed'),
        }
        
        PR_DEFAULT_EXPIRATION_WHEN_CREATING = 24*60*60  # 1 day
   DIR diff --git a/electrum/wallet.py b/electrum/wallet.py
       t@@ -73,7 +73,7 @@ from .plugin import run_hook
        from .address_synchronizer import (AddressSynchronizer, TX_HEIGHT_LOCAL,
                                           TX_HEIGHT_UNCONF_PARENT, TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_FUTURE)
        from .invoices import Invoice, OnchainInvoice, LNInvoice
       -from .invoices import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED, PR_INFLIGHT, PR_TYPE_ONCHAIN, PR_TYPE_LN
       +from .invoices import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED, PR_UNCONFIRMED, PR_TYPE_ONCHAIN, PR_TYPE_LN
        from .contacts import Contacts
        from .interface import NetworkException
        from .mnemonic import Mnemonic
       t@@ -741,7 +741,7 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
                elif invoice_type == PR_TYPE_ONCHAIN:
                    assert isinstance(invoice, OnchainInvoice)
                    key = invoice.id
       -            if self.is_onchain_invoice_paid(invoice):
       +            if self.is_onchain_invoice_paid(invoice, 0):
                        self.logger.info("saving invoice... but it is already paid!")
                    with self.transaction_lock:
                        for txout in invoice.outputs:
       t@@ -813,7 +813,7 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
                        for txout in invoice.outputs:
                            self._invoices_from_scriptpubkey_map[txout.scriptpubkey].add(invoice_key)
        
       -    def _is_onchain_invoice_paid(self, invoice: Invoice) -> Tuple[bool, Sequence[str]]:
       +    def _is_onchain_invoice_paid(self, invoice: Invoice, conf: int) -> Tuple[bool, Sequence[str]]:
                """Returns whether on-chain invoice is satisfied, and list of relevant TXIDs."""
                assert invoice.type == PR_TYPE_ONCHAIN
                assert isinstance(invoice, OnchainInvoice)
       t@@ -827,8 +827,10 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
                        prevouts_and_values = self.db.get_prevouts_by_scripthash(scripthash)
                        total_received = 0
                        for prevout, v in prevouts_and_values:
       -                    height = self.get_tx_height(prevout.txid.hex()).height
       -                    if height > 0 and height <= invoice.height:
       +                    tx_height = self.get_tx_height(prevout.txid.hex())
       +                    if tx_height.height > 0 and tx_height.height <= invoice.height:
       +                        continue
       +                    if tx_height.conf < conf:
                                continue
                            total_received += v
                            relevant_txs.append(prevout.txid.hex())
       t@@ -840,8 +842,8 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
                            return False, []
                return True, relevant_txs
        
       -    def is_onchain_invoice_paid(self, invoice: Invoice) -> bool:
       -        return self._is_onchain_invoice_paid(invoice)[0]
       +    def is_onchain_invoice_paid(self, invoice: Invoice, conf: int) -> bool:
       +        return self._is_onchain_invoice_paid(invoice, conf)[0]
        
            def _maybe_set_tx_label_based_on_invoices(self, tx: Transaction) -> bool:
                # note: this is not done in 'get_default_label' as that would require deserializing each tx
       t@@ -1839,7 +1841,12 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
                if invoice.is_lightning():
                    status = self.lnworker.get_invoice_status(invoice) if self.lnworker else PR_UNKNOWN
                else:
       -            status = PR_PAID if self.is_onchain_invoice_paid(invoice) else PR_UNPAID
       +            if self.is_onchain_invoice_paid(invoice, 1):
       +                status =PR_PAID
       +            elif self.is_onchain_invoice_paid(invoice, 0):
       +                status = PR_UNCONFIRMED
       +            else:
       +                status = PR_UNPAID
                return self.check_expired_status(invoice, status)
        
            def get_request_status(self, key):
       t@@ -1852,7 +1859,12 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
                else:
                    assert isinstance(r, OnchainInvoice)
                    paid, conf = self.get_onchain_request_status(r)
       -            status = PR_PAID if paid else PR_UNPAID
       +            if not paid:
       +                status = PR_UNPAID
       +            elif conf == 0:
       +                status = PR_UNCONFIRMED
       +            else:
       +                status = PR_PAID
                return self.check_expired_status(r, status)
        
            def get_request(self, key):