URI: 
       tLedger: move get_client() to the plugin - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 986e198e87f80153b3c1c4bdda3bdd93c1e60769
   DIR parent deccca1827e027739b6ac32787aeee2578e5c8d1
  HTML Author: Neil Booth <kyuupichan@gmail.com>
       Date:   Mon, 11 Jan 2016 15:08:12 +0900
       
       Ledger: move get_client() to the plugin
       
       Mirrors the trezor code
       
       Diffstat:
         M plugins/ledger/ledger.py            |     159 ++++++++++++++++---------------
         M plugins/ledger/qt.py                |       9 +++++----
       
       2 files changed, 86 insertions(+), 82 deletions(-)
       ---
   DIR diff --git a/plugins/ledger/ledger.py b/plugins/ledger/ledger.py
       t@@ -42,8 +42,6 @@ class BTChipWallet(BIP44_Wallet):
                self.handler = None
                self.force_watching_only = False
        
       -        self.transport = None
       -        self.client = None
                self.device_checked = False
                self.signing = False
        
       t@@ -53,8 +51,8 @@ class BTChipWallet(BIP44_Wallet):
                    QMessageBox.warning(QDialog(), _('Warning'), _(message), _('OK'))
                else:
                    self.signing = False
       -        if clear_client and self.client is not None:
       -            self.client.bad = True
       +        if clear_client:
       +            self.plugin.client = None
                    self.device_checked = False
                raise Exception(message)
        
       t@@ -76,75 +74,7 @@ class BTChipWallet(BIP44_Wallet):
                return BIP44_Wallet.address_id(self, address)[2:]
        
            def get_client(self, noPin=False):
       -        if not BTCHIP:
       -            self.give_error('please install github.com/btchip/btchip-python')
       -
       -        aborted = False
       -        if not self.client or self.client.bad:
       -            try:
       -                d = getDongle(BTCHIP_DEBUG)
       -                self.client = btchip(d)
       -                firmware = self.client.getFirmwareVersion()['version'].split(".")
       -                if not checkFirmware(firmware):
       -                    d.close()
       -                    try:
       -                        updateFirmware()
       -                    except Exception, e:
       -                        aborted = True
       -                        raise e
       -                    d = getDongle(BTCHIP_DEBUG)
       -                    self.client = btchip(d)
       -                try:
       -                    self.client.getOperationMode()
       -                except BTChipException, e:
       -                    if (e.sw == 0x6985):
       -                        d.close()
       -                        dialog = StartBTChipPersoDialog()
       -                        dialog.exec_()
       -                        # Then fetch the reference again  as it was invalidated
       -                        d = getDongle(BTCHIP_DEBUG)
       -                        self.client = btchip(d)
       -                    else:
       -                        raise e
       -                if not noPin:
       -                    # Immediately prompts for the PIN
       -                    remaining_attempts = self.client.getVerifyPinRemainingAttempts()
       -                    if remaining_attempts <> 1:
       -                        msg = "Enter your Ledger PIN - remaining attempts : " + str(remaining_attempts)
       -                    else:
       -                        msg = "Enter your Ledger PIN - WARNING : LAST ATTEMPT. If the PIN is not correct, the dongle will be wiped."
       -                    confirmed, p, pin = self.password_dialog(msg)
       -                    if not confirmed:
       -                        aborted = True
       -                        raise Exception('Aborted by user - please unplug the dongle and plug it again before retrying')
       -                    pin = pin.encode()
       -                    self.client.verifyPin(pin)
       -
       -            except BTChipException, e:
       -                try:
       -                    self.client.dongle.close()
       -                except:
       -                    pass
       -                self.client = None
       -                if (e.sw == 0x6faa):
       -                    raise Exception("Dongle is temporarily locked - please unplug it and replug it again")
       -                if ((e.sw & 0xFFF0) == 0x63c0):
       -                    raise Exception("Invalid PIN - please unplug the dongle and plug it again before retrying")
       -                raise e
       -            except Exception, e:
       -                try:
       -                    self.client.dongle.close()
       -                except:
       -                    pass
       -                self.client = None
       -                if not aborted:
       -                    raise Exception("Could not connect to your Ledger wallet. Please verify access permissions, PIN, or unplug the dongle and plug it again")
       -                else:
       -                    raise e
       -            self.client.bad = False
       -            self.device_checked = False
       -            self.proper_device = False
       -        return self.client
       +        return self.plugin.get_client(self, noPin=noPin)
        
            def derive_xkeys(self, root, derivation, password):
                derivation = '/'.join(derivation.split('/')[1:])
       t@@ -193,7 +123,8 @@ class BTChipWallet(BIP44_Wallet):
            def sign_message(self, address, message, password):
                use2FA = False
                self.signing = True
       -        self.get_client() # prompt for the PIN before displaying the dialog if necessary
       +        # prompt for the PIN before displaying the dialog if necessary
       +        client = self.get_client()
                if not self.check_proper_device():
                    self.give_error('Wrong device or password')
                address_path = self.address_id(address)
       t@@ -208,7 +139,7 @@ class BTChipWallet(BIP44_Wallet):
                        if not confirmed:
                            raise Exception('Aborted by user')
                        pin = pin.encode()
       -                self.client.bad = True
       +                client.bad = True
                        self.device_checked = False
                        self.get_client(True)
                    signature = self.get_client().signMessageSign(pin)
       t@@ -221,7 +152,7 @@ class BTChipWallet(BIP44_Wallet):
                    self.give_error(e, True)
                finally:
                    self.handler.stop()
       -        self.client.bad = use2FA
       +        client.bad = use2FA
                self.signing = False
        
                # Parse the ASN.1 signature
       t@@ -334,7 +265,7 @@ class BTChipWallet(BIP44_Wallet):
                                if not confirmed:
                                    raise Exception('Aborted by user')
                                pin = pin.encode()
       -                        self.client.bad = True
       +                        client.bad = True
                                self.device_checked = False
                                self.get_client(True)
                            self.handler.show_message("Signing ...")
       t@@ -361,7 +292,7 @@ class BTChipWallet(BIP44_Wallet):
                updatedTransaction = format_transaction(transactionOutput, preparedTrustedInputs)
                updatedTransaction = hexlify(updatedTransaction)
                tx.update(updatedTransaction)
       -        self.client.bad = use2FA
       +        client.bad = use2FA
                self.signing = False
        
            def check_proper_device(self):
       t@@ -404,6 +335,7 @@ class LedgerPlugin(BasePlugin):
                BasePlugin.__init__(self, parent, config, name)
                self.wallet_class.plugin = self
                self.device = self.wallet_class.device
       +        self.client = None
        
            def is_enabled(self):
                return BTCHIP
       t@@ -441,3 +373,74 @@ class LedgerPlugin(BasePlugin):
            @hook
            def close_wallet(self, wallet):
                self.client = None
       +
       +    def get_client(self, wallet, noPin=False):
       +        aborted = False
       +        client = self.client
       +        if not client or client.bad:
       +            try:
       +                d = getDongle(BTCHIP_DEBUG)
       +                client = btchip(d)
       +                firmware = client.getFirmwareVersion()['version'].split(".")
       +                if not checkFirmware(firmware):
       +                    d.close()
       +                    try:
       +                        updateFirmware()
       +                    except Exception, e:
       +                        aborted = True
       +                        raise e
       +                    d = getDongle(BTCHIP_DEBUG)
       +                    client = btchip(d)
       +                try:
       +                    client.getOperationMode()
       +                except BTChipException, e:
       +                    if (e.sw == 0x6985):
       +                        d.close()
       +                        dialog = StartBTChipPersoDialog()
       +                        dialog.exec_()
       +                        # Then fetch the reference again  as it was invalidated
       +                        d = getDongle(BTCHIP_DEBUG)
       +                        client = btchip(d)
       +                    else:
       +                        raise e
       +                if not noPin:
       +                    # Immediately prompts for the PIN
       +                    remaining_attempts = client.getVerifyPinRemainingAttempts()
       +                    if remaining_attempts <> 1:
       +                        msg = "Enter your Ledger PIN - remaining attempts : " + str(remaining_attempts)
       +                    else:
       +                        msg = "Enter your Ledger PIN - WARNING : LAST ATTEMPT. If the PIN is not correct, the dongle will be wiped."
       +                    confirmed, p, pin = wallet.password_dialog(msg)
       +                    if not confirmed:
       +                        aborted = True
       +                        raise Exception('Aborted by user - please unplug the dongle and plug it again before retrying')
       +                    pin = pin.encode()
       +                    client.verifyPin(pin)
       +
       +            except BTChipException, e:
       +                try:
       +                    client.dongle.close()
       +                except:
       +                    pass
       +                client = None
       +                if (e.sw == 0x6faa):
       +                    raise Exception("Dongle is temporarily locked - please unplug it and replug it again")
       +                if ((e.sw & 0xFFF0) == 0x63c0):
       +                    raise Exception("Invalid PIN - please unplug the dongle and plug it again before retrying")
       +                raise e
       +            except Exception, e:
       +                try:
       +                    client.dongle.close()
       +                except:
       +                    pass
       +                client = None
       +                if not aborted:
       +                    raise Exception("Could not connect to your Ledger wallet. Please verify access permissions, PIN, or unplug the dongle and plug it again")
       +                else:
       +                    raise e
       +            client.bad = False
       +            wallet.device_checked = False
       +            wallet.proper_device = False
       +            self.client = client
       +
       +        return self.client
   DIR diff --git a/plugins/ledger/qt.py b/plugins/ledger/qt.py
       t@@ -1,11 +1,12 @@
       +import threading
       +
        from PyQt4.Qt import (QDialog, QInputDialog, QLineEdit,
                              QVBoxLayout, QLabel, SIGNAL)
        import PyQt4.QtCore as QtCore
       -import threading
       -
       -from electrum.plugins import BasePlugin, hook
        
       -from ledger import LedgerPlugin, BTChipWallet
       +from electrum.i18n import _
       +from electrum.plugins import hook
       +from .ledger import LedgerPlugin, BTChipWallet
        
        class Plugin(LedgerPlugin):