URI: 
       tMerge pull request #4490 from SomberNight/trustedcoin_color_outputs - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 83974cd0a80faddd172b6e9d04fafdf5d1c9b492
   DIR parent 0ad013f144480d8349422608013c26992b565dc9
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Tue,  3 Jul 2018 08:47:15 +0200
       
       Merge pull request #4490 from SomberNight/trustedcoin_color_outputs
       
       colour 2fa billing outputs in Qt tx dialog
       Diffstat:
         M gui/qt/transaction_dialog.py        |       5 +++++
         M lib/wallet.py                       |       4 ++++
         M plugins/trustedcoin/trustedcoin.py  |      48 +++++++++++++++++++++++++------
       
       3 files changed, 48 insertions(+), 9 deletions(-)
       ---
   DIR diff --git a/gui/qt/transaction_dialog.py b/gui/qt/transaction_dialog.py
       t@@ -278,10 +278,15 @@ class TxDialog(QDialog, MessageBoxMixin):
                chg = QTextCharFormat()
                chg.setBackground(QBrush(ColorScheme.YELLOW.as_color(background=True)))
                chg.setToolTip(_("Wallet change address"))
       +        twofactor = QTextCharFormat()
       +        twofactor.setBackground(QBrush(ColorScheme.BLUE.as_color(background=True)))
       +        twofactor.setToolTip(_("TrustedCoin (2FA) fee for the next batch of transactions"))
        
                def text_format(addr):
                    if self.wallet.is_mine(addr):
                        return chg if self.wallet.is_change(addr) else rec
       +            elif self.wallet.is_billing_address(addr):
       +                return twofactor
                    return ext
        
                def format_amount(amt):
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -1849,6 +1849,10 @@ class Abstract_Wallet(PrintError):
                        p = self.price_at_timestamp(txid, price_func)
                        return p * txin_value/Decimal(COIN)
        
       +    def is_billing_address(self, addr):
       +        # overloaded for TrustedCoin wallets
       +        return False
       +
        
        class Simple_Wallet(Abstract_Wallet):
            # wallet with a single keystore
   DIR diff --git a/plugins/trustedcoin/trustedcoin.py b/plugins/trustedcoin/trustedcoin.py
       t@@ -228,6 +228,15 @@ class Wallet_2fa(Multisig_Wallet):
                Deterministic_Wallet.__init__(self, storage)
                self.is_billing = False
                self.billing_info = None
       +        self._load_billing_addresses()
       +
       +    def _load_billing_addresses(self):
       +        billing_addresses = self.storage.get('trustedcoin_billing_addresses', {})
       +        self._billing_addresses = {}  # index -> addr
       +        # convert keys from str to int
       +        for index, addr in list(billing_addresses.items()):
       +            self._billing_addresses[int(index)] = addr
       +        self._billing_addresses_set = set(self._billing_addresses.values())  # set of addrs
        
            def can_sign_without_server(self):
                return not self.keystores['x2/'].is_watching_only()
       t@@ -298,6 +307,31 @@ class Wallet_2fa(Multisig_Wallet):
                self.billing_info = None
                self.plugin.start_request_thread(self)
        
       +    def add_new_billing_address(self, billing_index: int, address: str):
       +        saved_addr = self._billing_addresses.get(billing_index)
       +        if saved_addr is not None:
       +            if saved_addr == address:
       +                return  # already saved this address
       +            else:
       +                raise Exception('trustedcoin billing address inconsistency.. '
       +                                'for index {}, already saved {}, now got {}'
       +                                .format(billing_index, saved_addr, address))
       +        # do we have all prior indices? (are we synced?)
       +        largest_index_we_have = max(self._billing_addresses) if self._billing_addresses else -1
       +        if largest_index_we_have + 1 < billing_index:  # need to sync
       +            for i in range(largest_index_we_have + 1, billing_index):
       +                addr = make_billing_address(self, i)
       +                self._billing_addresses[i] = addr
       +                self._billing_addresses_set.add(addr)
       +        # save this address; and persist to disk
       +        self._billing_addresses[billing_index] = address
       +        self._billing_addresses_set.add(address)
       +        self.storage.put('trustedcoin_billing_addresses', self._billing_addresses)
       +        # FIXME this often runs in a daemon thread, where storage.write will fail
       +        self.storage.write()
       +
       +    def is_billing_address(self, addr: str) -> bool:
       +        return addr in self._billing_addresses_set
        
        
        # Utility functions
       t@@ -365,15 +399,9 @@ class TrustedCoinPlugin(BasePlugin):
            def get_tx_extra_fee(self, wallet, tx):
                if type(wallet) != Wallet_2fa:
                    return
       -        if wallet.billing_info is None:
       -            if not wallet.can_sign_without_server():
       -                self.start_request_thread(wallet)
       -                raise Exception('missing trustedcoin billing info')
       -            return None
       -        address = wallet.billing_info['billing_address']
                for _type, addr, amount in tx.outputs():
       -            if _type == TYPE_ADDRESS and addr == address:
       -                return address, amount
       +            if _type == TYPE_ADDRESS and wallet.is_billing_address(addr):
       +                return addr, amount
        
            def finish_requesting(func):
                def f(self, *args, **kwargs):
       t@@ -393,10 +421,12 @@ class TrustedCoinPlugin(BasePlugin):
                except ErrorConnectingServer as e:
                    self.print_error('cannot connect to TrustedCoin server: {}'.format(e))
                    return
       -        billing_address = make_billing_address(wallet, billing_info['billing_index'])
       +        billing_index = billing_info['billing_index']
       +        billing_address = make_billing_address(wallet, billing_index)
                if billing_address != billing_info['billing_address']:
                    raise Exception('unexpected trustedcoin billing address: expected {}, received {}'
                                    .format(billing_address, billing_info['billing_address']))
       +        wallet.add_new_billing_address(billing_index, billing_address)
                wallet.billing_info = billing_info
                wallet.price_per_tx = dict(billing_info['price_per_tx'])
                wallet.price_per_tx.pop(1, None)