URI: 
       tMore keepkey / trezor commonizing and cleanup - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit f3329988b28ba89ff2e27b03a98a88e45d9bddd7
   DIR parent 33e57fe5a79c1b83aa0f21087eab9d69f36b09e7
  HTML Author: Neil Booth <kyuupichan@gmail.com>
       Date:   Sun, 27 Dec 2015 13:56:50 +0900
       
       More keepkey / trezor commonizing and cleanup
       
       Diffstat:
         M plugins/keepkey/keepkey.py          |      50 +++++--------------------------
         A plugins/trezor/client.py            |      74 +++++++++++++++++++++++++++++++
         D plugins/trezor/gui_mixin.py         |      57 -------------------------------
         A plugins/trezor/plugin.py            |     222 ++++++++++++++++++++++++++++++
         D plugins/trezor/plugin_generic.py    |     206 -------------------------------
         M plugins/trezor/trezor.py            |      54 ++++++-------------------------
       
       6 files changed, 313 insertions(+), 350 deletions(-)
       ---
   DIR diff --git a/plugins/keepkey/keepkey.py b/plugins/keepkey/keepkey.py
       t@@ -5,8 +5,6 @@ from plugins.trezor.plugin_generic import TrezorCompatiblePlugin
        
        try:
            from keepkeylib.client import proto, BaseClient, ProtocolMixin
       -    from keepkeylib.transport import ConnectionError
       -    from keepkeylib.transport_hid import HidTransport
            KEEPKEY = True
        except ImportError:
            KEEPKEY = False
       t@@ -19,46 +17,12 @@ class KeepKeyWallet(BIP32_Hardware_Wallet):
        
        
        class KeepKeyPlugin(TrezorCompatiblePlugin):
       -    wallet_type = 'keepkey'
       +    client_class = trezor_client_class(ProtocolMixin, BaseClient, proto)
       +    firmware_URL = 'https://www.keepkey.com'
       +    libraries_URL = 'https://github.com/keepkey/python-keepkey'
       +    libraries_available = KEEPKEY
       +    minimum_firmware = (1, 0, 0)
       +    wallet_class = KeepKeyWallet
            import keepkeylib.ckd_public as ckd_public
            from keepkeylib.client import types
       -
       -    @staticmethod
       -    def libraries_available():
       -        return KEEPKEY
       -
       -    def constructor(self, s):
       -        return KeepKeyWallet(s)
       -
       -    def get_client(self):
       -        if not KEEPKEY:
       -            give_error('please install github.com/keepkey/python-keepkey')
       -
       -        if not self.client or self.client.bad:
       -            d = HidTransport.enumerate()
       -            if not d:
       -                give_error('Could not connect to your KeepKey. Please verify the cable is connected and that no other app is using it.')
       -            self.transport = HidTransport(d[0])
       -            self.client = QtGuiKeepKeyClient(self.transport)
       -            self.client.handler = self.handler
       -            self.client.set_tx_api(self)
       -            self.client.bad = False
       -            if not self.atleast_version(1, 0, 0):
       -                self.client = None
       -                give_error('Outdated KeepKey firmware. Please update the firmware from https://www.keepkey.com')
       -        return self.client
       -
       -
       -if KEEPKEY:
       -    class QtGuiKeepKeyClient(ProtocolMixin, GuiMixin, BaseClient):
       -        protocol = proto
       -        device = 'KeepKey'
       -
       -        def call_raw(self, msg):
       -            try:
       -                resp = BaseClient.call_raw(self, msg)
       -            except ConnectionError:
       -                self.bad = True
       -                raise
       -
       -            return resp
       +    from keepkeylib.transport_hid import HidTransport
   DIR diff --git a/plugins/trezor/client.py b/plugins/trezor/client.py
       t@@ -0,0 +1,74 @@
       +from sys import stderr
       +
       +from electrum.i18n import _
       +
       +class GuiMixin(object):
       +    # Requires: self.proto, self.device
       +
       +    def callback_ButtonRequest(self, msg):
       +        if msg.code == 3:
       +            message = _("Confirm transaction outputs on %s device to continue")
       +        elif msg.code == 8:
       +            message = _("Confirm transaction fee on %s device to continue")
       +        elif msg.code == 7:
       +            message = _("Confirm message to sign on %s device to continue")
       +        elif msg.code == 10:
       +            message = _("Confirm address on %s device to continue")
       +        else:
       +            message = _("Check %s device to continue")
       +
       +        if msg.code in [3, 8] and hasattr(self, 'cancel'):
       +            cancel_callback = self.cancel
       +        else:
       +            cancel_callback = None
       +
       +        self.handler.show_message(message % self.device, cancel_callback)
       +        return self.proto.ButtonAck()
       +
       +    def callback_PinMatrixRequest(self, msg):
       +        if msg.type == 1:
       +            msg = _("Please enter %s current PIN")
       +        elif msg.type == 2:
       +            msg = _("Please enter %s new PIN")
       +        elif msg.type == 3:
       +            msg = _("Please enter %s new PIN again")
       +        else:
       +            msg = _("Please enter %s PIN")
       +        pin = self.handler.get_pin(msg % self.device)
       +        if not pin:
       +            return self.proto.Cancel()
       +        return self.proto.PinMatrixAck(pin=pin)
       +
       +    def callback_PassphraseRequest(self, req):
       +        msg = _("Please enter your %s passphrase")
       +        passphrase = self.handler.get_passphrase(msg % self.device)
       +        if passphrase is None:
       +            return self.proto.Cancel()
       +        return self.proto.PassphraseAck(passphrase=passphrase)
       +
       +    def callback_WordRequest(self, msg):
       +        #TODO
       +        stderr.write("Enter one word of mnemonic:\n")
       +        stderr.flush()
       +        word = raw_input()
       +        return self.proto.WordAck(word=word)
       +
       +def trezor_client_class(protocol_mixin, base_client, proto):
       +    '''Returns a class dynamically.'''
       +
       +    class TrezorClient(protocol_mixin, GuiMixin, base_client):
       +
       +        def __init__(self, transport, device):
       +            base_client.__init__(self, transport)
       +            protocol_mixin.__init__(self, transport)
       +            self.proto = proto
       +            self.device = device
       +
       +        def call_raw(self, msg):
       +            try:
       +                return base_client.call_raw(self, msg)
       +            except:
       +                self.bad = True
       +                raise
       +
       +    return TrezorClient
   DIR diff --git a/plugins/trezor/gui_mixin.py b/plugins/trezor/gui_mixin.py
       t@@ -1,57 +0,0 @@
       -from sys import stderr
       -
       -from electrum.i18n import _
       -
       -class GuiMixin(object):
       -    # Requires: self.protcol, self.device
       -
       -    def __init__(self, *args, **kwargs):
       -        super(GuiMixin, self).__init__(*args, **kwargs)
       -
       -    def callback_ButtonRequest(self, msg):
       -        if msg.code == 3:
       -            message = _("Confirm transaction outputs on %s device to continue")
       -        elif msg.code == 8:
       -            message = _("Confirm transaction fee on %s device to continue")
       -        elif msg.code == 7:
       -            message = _("Confirm message to sign on %s device to continue")
       -        elif msg.code == 10:
       -            message = _("Confirm address on %s device to continue")
       -        else:
       -            message = _("Check %s device to continue")
       -
       -        if msg.code in [3, 8] and hasattr(self, 'cancel'):
       -            cancel_callback = self.cancel
       -        else:
       -            cancel_callback = None
       -
       -        self.handler.show_message(message % self.device, cancel_callback)
       -        return self.protocol.ButtonAck()
       -
       -    def callback_PinMatrixRequest(self, msg):
       -        if msg.type == 1:
       -            msg = _("Please enter %s current PIN")
       -        elif msg.type == 2:
       -            msg = _("Please enter %s new PIN")
       -        elif msg.type == 3:
       -            msg = _("Please enter %s new PIN again")
       -        else:
       -            msg = _("Please enter %s PIN")
       -        pin = self.handler.get_pin(msg % self.device)
       -        if not pin:
       -            return self.protocol.Cancel()
       -        return self.protocol.PinMatrixAck(pin=pin)
       -
       -    def callback_PassphraseRequest(self, req):
       -        msg = _("Please enter your %s passphrase")
       -        passphrase = self.handler.get_passphrase(msg % self.device)
       -        if passphrase is None:
       -            return self.protocol.Cancel()
       -        return self.protocol.PassphraseAck(passphrase=passphrase)
       -
       -    def callback_WordRequest(self, msg):
       -        #TODO
       -        stderr.write("Enter one word of mnemonic:\n")
       -        stderr.flush()
       -        word = raw_input()
       -        return self.protocol.WordAck(word=word)
   DIR diff --git a/plugins/trezor/plugin.py b/plugins/trezor/plugin.py
       t@@ -0,0 +1,222 @@
       +from binascii import unhexlify
       +
       +from electrum.account import BIP32_Account
       +from electrum.bitcoin import bc_address_to_hash_160, xpub_from_pubkey
       +from electrum.i18n import _
       +from electrum.plugins import BasePlugin, hook
       +from electrum.transaction import deserialize, is_extended_pubkey
       +
       +class TrezorCompatiblePlugin(BasePlugin):
       +    # Derived classes provide:
       +    #
       +    #  class-static variables: client_class, firmware_URL,
       +    #     libraries_available, libraries_URL, minimum_firmware,
       +    #     wallet_class, ckd_public, types, HidTransport
       +
       +    def __init__(self, parent, config, name):
       +        BasePlugin.__init__(self, parent, config, name)
       +        self.device = self.wallet_class.device
       +        self.wallet = None
       +        self.handler = None
       +        self.client = None
       +
       +    def constructor(self, s):
       +        return self.wallet_class(s)
       +
       +    def give_error(self, message):
       +        self.print_error(message)
       +        raise Exception(message)
       +
       +    def is_available(self):
       +        if not self.libraries_available:
       +            return False
       +        if not self.wallet:
       +            return False
       +        wallet_type = self.wallet.storage.get('wallet_type')
       +        return wallet_type == self.wallet_class.wallet_type
       +
       +    def set_enabled(self, enabled):
       +        self.wallet.storage.put('use_' + self.name, enabled)
       +
       +    def is_enabled(self):
       +        if not self.is_available():
       +            return False
       +        if self.wallet.has_seed():
       +            return False
       +        return True
       +
       +    def get_client(self):
       +        if not self.libraries_available:
       +            self.give_error(_('please install the %s libraries from %s')
       +                            % (self.device, self.libraries_URL))
       +
       +        if not self.client or self.client.bad:
       +            d = self.HidTransport.enumerate()
       +            if not d:
       +                self.give_error(_('Could not connect to your %s. Please '
       +                                  'verify the cable is connected and that no '
       +                                  'other app is using it.' % self.device))
       +            transport = self.HidTransport(d[0])
       +            self.client = self.client_class(transport, self.device)
       +            self.client.handler = self.handler
       +            self.client.set_tx_api(self)
       +            self.client.bad = False
       +            if not self.atleast_version(*self.minimum_firmware):
       +                self.client = None
       +                self.give_error(_('Outdated %s firmware. Please update the '
       +                                  'firmware from %s') % (self.device,
       +                                                         self.firmware_URL))
       +        return self.client
       +
       +    def compare_version(self, major, minor=0, patch=0):
       +        f = self.get_client().features
       +        v = [f.major_version, f.minor_version, f.patch_version]
       +        self.print_error('firmware version', v)
       +        return cmp(v, [major, minor, patch])
       +
       +    def atleast_version(self, major, minor=0, patch=0):
       +        return self.compare_version(major, minor, patch) >= 0
       +
       +    @hook
       +    def close_wallet(self):
       +        self.print_error("clear session")
       +        if self.client:
       +            self.client.clear_session()
       +            self.client.transport.close()
       +            self.client = None
       +        self.wallet = None
       +
       +    def sign_transaction(self, tx, prev_tx, xpub_path):
       +        self.prev_tx = prev_tx
       +        self.xpub_path = xpub_path
       +        client = self.get_client()
       +        inputs = self.tx_inputs(tx, True)
       +        outputs = self.tx_outputs(tx)
       +        try:
       +            signed_tx = client.sign_tx('Bitcoin', inputs, outputs)[1]
       +        except Exception as e:
       +            self.give_error(e)
       +        finally:
       +            self.handler.stop()
       +        raw = signed_tx.encode('hex')
       +        tx.update_signatures(raw)
       +
       +    def show_address(self, address):
       +        client = self.get_client()
       +        self.wallet.check_proper_device()
       +        try:
       +            address_path = self.wallet.address_id(address)
       +            address_n = client.expand_path(address_path)
       +        except Exception as e:
       +            self.give_error(e)
       +        try:
       +            client.get_address('Bitcoin', address_n, True)
       +        except Exception as e:
       +            self.give_error(e)
       +        finally:
       +            self.handler.stop()
       +
       +    def tx_inputs(self, tx, for_sig=False):
       +        client = self.get_client()
       +        inputs = []
       +        for txin in tx.inputs:
       +            txinputtype = self.types.TxInputType()
       +            if txin.get('is_coinbase'):
       +                prev_hash = "\0"*32
       +                prev_index = 0xffffffff # signed int -1
       +            else:
       +                if for_sig:
       +                    x_pubkeys = txin['x_pubkeys']
       +                    if len(x_pubkeys) == 1:
       +                        x_pubkey = x_pubkeys[0]
       +                        xpub, s = BIP32_Account.parse_xpubkey(x_pubkey)
       +                        xpub_n = client.expand_path(self.xpub_path[xpub])
       +                        txinputtype.address_n.extend(xpub_n + s)
       +                    else:
       +                        def f(x_pubkey):
       +                            if is_extended_pubkey(x_pubkey):
       +                                xpub, s = BIP32_Account.parse_xpubkey(x_pubkey)
       +                            else:
       +                                xpub = xpub_from_pubkey(x_pubkey.decode('hex'))
       +                                s = []
       +                            node = ckd_public.deserialize(xpub)
       +                            return self.types.HDNodePathType(node=node, address_n=s)
       +                        pubkeys = map(f, x_pubkeys)
       +                        multisig = self.types.MultisigRedeemScriptType(
       +                            pubkeys=pubkeys,
       +                            signatures=map(lambda x: x.decode('hex') if x else '', txin.get('signatures')),
       +                            m=txin.get('num_sig'),
       +                        )
       +                        txinputtype = self.types.TxInputType(
       +                            script_type=self.types.SPENDMULTISIG,
       +                            multisig= multisig
       +                        )
       +                        # find which key is mine
       +                        for x_pubkey in x_pubkeys:
       +                            if is_extended_pubkey(x_pubkey):
       +                                xpub, s = BIP32_Account.parse_xpubkey(x_pubkey)
       +                                if xpub in self.xpub_path:
       +                                    xpub_n = client.expand_path(self.xpub_path[xpub])
       +                                    txinputtype.address_n.extend(xpub_n + s)
       +                                    break
       +
       +                prev_hash = unhexlify(txin['prevout_hash'])
       +                prev_index = txin['prevout_n']
       +
       +            txinputtype.prev_hash = prev_hash
       +            txinputtype.prev_index = prev_index
       +
       +            if 'scriptSig' in txin:
       +                script_sig = txin['scriptSig'].decode('hex')
       +                txinputtype.script_sig = script_sig
       +
       +            if 'sequence' in txin:
       +                sequence = txin['sequence']
       +                txinputtype.sequence = sequence
       +
       +            inputs.append(txinputtype)
       +
       +        return inputs
       +
       +    def tx_outputs(self, tx):
       +        client = self.get_client()
       +        outputs = []
       +
       +        for type, address, amount in tx.outputs:
       +            assert type == 'address'
       +            txoutputtype = self.types.TxOutputType()
       +            if self.wallet.is_change(address):
       +                address_path = self.wallet.address_id(address)
       +                address_n = client.expand_path(address_path)
       +                txoutputtype.address_n.extend(address_n)
       +            else:
       +                txoutputtype.address = address
       +            txoutputtype.amount = amount
       +            addrtype, hash_160 = bc_address_to_hash_160(address)
       +            if addrtype == 0:
       +                txoutputtype.script_type = self.types.PAYTOADDRESS
       +            elif addrtype == 5:
       +                txoutputtype.script_type = self.types.PAYTOSCRIPTHASH
       +            else:
       +                raise BaseException('addrtype')
       +            outputs.append(txoutputtype)
       +
       +        return outputs
       +
       +    def electrum_tx_to_txtype(self, tx):
       +        t = self.types.TransactionType()
       +        d = deserialize(tx.raw)
       +        t.version = d['version']
       +        t.lock_time = d['lockTime']
       +        inputs = self.tx_inputs(tx)
       +        t.inputs.extend(inputs)
       +        for vout in d['outputs']:
       +            o = t.bin_outputs.add()
       +            o.amount = vout['value']
       +            o.script_pubkey = vout['scriptPubKey'].decode('hex')
       +        return t
       +
       +    def get_tx(self, tx_hash):
       +        tx = self.prev_tx[tx_hash]
       +        tx.deserialize()
       +        return self.electrum_tx_to_txtype(tx)
   DIR diff --git a/plugins/trezor/plugin_generic.py b/plugins/trezor/plugin_generic.py
       t@@ -1,206 +0,0 @@
       -from binascii import unhexlify
       -
       -from electrum.account import BIP32_Account
       -from electrum.bitcoin import bc_address_to_hash_160, xpub_from_pubkey
       -from electrum.i18n import _
       -from electrum.plugins import BasePlugin, hook
       -from electrum.transaction import deserialize, is_extended_pubkey
       -
       -class TrezorCompatiblePlugin(BasePlugin):
       -    # Derived classes provide:
       -
       -    #  libraries_available()
       -    #  constructor()
       -    #  ckd_public
       -    #  types
       -    #  wallet_type
       -
       -    def __init__(self, parent, config, name):
       -        BasePlugin.__init__(self, parent, config, name)
       -        self.wallet = None
       -        self.handler = None
       -        self.client = None
       -        self.transport = None
       -
       -    def constructor(self, s):
       -        raise NotImplementedError
       -
       -    @staticmethod
       -    def libraries_available():
       -        raise NotImplementedError
       -
       -    def give_error(self, message):
       -        self.print_error(message)
       -        raise Exception(message)
       -
       -    def is_available(self):
       -        if not self.libraries_available():
       -            return False
       -        if not self.wallet:
       -            return False
       -        if self.wallet.storage.get('wallet_type') != self.wallet_type:
       -            return False
       -        return True
       -
       -    def set_enabled(self, enabled):
       -        self.wallet.storage.put('use_' + self.name, enabled)
       -
       -    def is_enabled(self):
       -        if not self.is_available():
       -            return False
       -        if self.wallet.has_seed():
       -            return False
       -        return True
       -
       -    def compare_version(self, major, minor=0, patch=0):
       -        features = self.get_client().features
       -        v = [features.major_version, features.minor_version, features.patch_version]
       -        self.print_error('firmware version', v)
       -        return cmp(v, [major, minor, patch])
       -
       -    def atleast_version(self, major, minor=0, patch=0):
       -        return self.compare_version(major, minor, patch) >= 0
       -
       -    @hook
       -    def close_wallet(self):
       -        self.print_error("clear session")
       -        if self.client:
       -            self.client.clear_session()
       -            self.client.transport.close()
       -            self.client = None
       -        self.wallet = None
       -
       -    def sign_transaction(self, tx, prev_tx, xpub_path):
       -        self.prev_tx = prev_tx
       -        self.xpub_path = xpub_path
       -        client = self.get_client()
       -        inputs = self.tx_inputs(tx, True)
       -        outputs = self.tx_outputs(tx)
       -        try:
       -            signed_tx = client.sign_tx('Bitcoin', inputs, outputs)[1]
       -        except Exception as e:
       -            self.give_error(e)
       -        finally:
       -            self.handler.stop()
       -        raw = signed_tx.encode('hex')
       -        tx.update_signatures(raw)
       -
       -    def show_address(self, address):
       -        client = self.get_client()
       -        self.wallet.check_proper_device()
       -        try:
       -            address_path = self.wallet.address_id(address)
       -            address_n = client.expand_path(address_path)
       -        except Exception as e:
       -            self.give_error(e)
       -        try:
       -            client.get_address('Bitcoin', address_n, True)
       -        except Exception as e:
       -            self.give_error(e)
       -        finally:
       -            self.handler.stop()
       -
       -    def tx_inputs(self, tx, for_sig=False):
       -        client = self.get_client()
       -        inputs = []
       -        for txin in tx.inputs:
       -            txinputtype = self.types.TxInputType()
       -            if txin.get('is_coinbase'):
       -                prev_hash = "\0"*32
       -                prev_index = 0xffffffff # signed int -1
       -            else:
       -                if for_sig:
       -                    x_pubkeys = txin['x_pubkeys']
       -                    if len(x_pubkeys) == 1:
       -                        x_pubkey = x_pubkeys[0]
       -                        xpub, s = BIP32_Account.parse_xpubkey(x_pubkey)
       -                        xpub_n = client.expand_path(self.xpub_path[xpub])
       -                        txinputtype.address_n.extend(xpub_n + s)
       -                    else:
       -                        def f(x_pubkey):
       -                            if is_extended_pubkey(x_pubkey):
       -                                xpub, s = BIP32_Account.parse_xpubkey(x_pubkey)
       -                            else:
       -                                xpub = xpub_from_pubkey(x_pubkey.decode('hex'))
       -                                s = []
       -                            node = ckd_public.deserialize(xpub)
       -                            return self.types.HDNodePathType(node=node, address_n=s)
       -                        pubkeys = map(f, x_pubkeys)
       -                        multisig = self.types.MultisigRedeemScriptType(
       -                            pubkeys=pubkeys,
       -                            signatures=map(lambda x: x.decode('hex') if x else '', txin.get('signatures')),
       -                            m=txin.get('num_sig'),
       -                        )
       -                        txinputtype = self.types.TxInputType(
       -                            script_type=self.types.SPENDMULTISIG,
       -                            multisig= multisig
       -                        )
       -                        # find which key is mine
       -                        for x_pubkey in x_pubkeys:
       -                            if is_extended_pubkey(x_pubkey):
       -                                xpub, s = BIP32_Account.parse_xpubkey(x_pubkey)
       -                                if xpub in self.xpub_path:
       -                                    xpub_n = client.expand_path(self.xpub_path[xpub])
       -                                    txinputtype.address_n.extend(xpub_n + s)
       -                                    break
       -
       -                prev_hash = unhexlify(txin['prevout_hash'])
       -                prev_index = txin['prevout_n']
       -
       -            txinputtype.prev_hash = prev_hash
       -            txinputtype.prev_index = prev_index
       -
       -            if 'scriptSig' in txin:
       -                script_sig = txin['scriptSig'].decode('hex')
       -                txinputtype.script_sig = script_sig
       -
       -            if 'sequence' in txin:
       -                sequence = txin['sequence']
       -                txinputtype.sequence = sequence
       -
       -            inputs.append(txinputtype)
       -
       -        return inputs
       -
       -    def tx_outputs(self, tx):
       -        client = self.get_client()
       -        outputs = []
       -
       -        for type, address, amount in tx.outputs:
       -            assert type == 'address'
       -            txoutputtype = self.types.TxOutputType()
       -            if self.wallet.is_change(address):
       -                address_path = self.wallet.address_id(address)
       -                address_n = client.expand_path(address_path)
       -                txoutputtype.address_n.extend(address_n)
       -            else:
       -                txoutputtype.address = address
       -            txoutputtype.amount = amount
       -            addrtype, hash_160 = bc_address_to_hash_160(address)
       -            if addrtype == 0:
       -                txoutputtype.script_type = self.types.PAYTOADDRESS
       -            elif addrtype == 5:
       -                txoutputtype.script_type = self.types.PAYTOSCRIPTHASH
       -            else:
       -                raise BaseException('addrtype')
       -            outputs.append(txoutputtype)
       -
       -        return outputs
       -
       -    def electrum_tx_to_txtype(self, tx):
       -        t = self.types.TransactionType()
       -        d = deserialize(tx.raw)
       -        t.version = d['version']
       -        t.lock_time = d['lockTime']
       -        inputs = self.tx_inputs(tx)
       -        t.inputs.extend(inputs)
       -        for vout in d['outputs']:
       -            o = t.bin_outputs.add()
       -            o.amount = vout['value']
       -            o.script_pubkey = vout['scriptPubKey'].decode('hex')
       -        return t
       -
       -    def get_tx(self, tx_hash):
       -        tx = self.prev_tx[tx_hash]
       -        tx.deserialize()
       -        return self.electrum_tx_to_txtype(tx)
   DIR diff --git a/plugins/trezor/trezor.py b/plugins/trezor/trezor.py
       t@@ -1,12 +1,10 @@
        from electrum.wallet import BIP32_Hardware_Wallet
        
       -from plugins.trezor.gui_mixin import GuiMixin
       -from plugins.trezor.plugin_generic import TrezorCompatiblePlugin
       +from plugins.trezor.client import trezor_client_class
       +from plugins.trezor.plugin import TrezorCompatiblePlugin
        
        try:
            from trezorlib.client import proto, BaseClient, ProtocolMixin
       -    from trezorlib.transport import ConnectionError
       -    from trezorlib.transport_hid import HidTransport
            TREZOR = True
        except ImportError:
            TREZOR = False
       t@@ -17,46 +15,14 @@ class TrezorWallet(BIP32_Hardware_Wallet):
            root_derivation = "m/44'/0'"
            device = 'Trezor'
        
       +
        class TrezorPlugin(TrezorCompatiblePlugin):
       -    wallet_type = 'trezor'
       +    client_class = trezor_client_class(ProtocolMixin, BaseClient, proto)
       +    firmware_URL = 'https://www.mytrezor.com'
       +    libraries_URL = 'https://github.com/trezor/python-trezor'
       +    libraries_available = TREZOR
       +    minimum_firmware = (1, 2, 1)
       +    wallet_class = TrezorWallet
            import trezorlib.ckd_public as ckd_public
            from trezorlib.client import types
       -
       -    @staticmethod
       -    def libraries_available():
       -        return TREZOR
       -
       -    def constructor(self, s):
       -        return TrezorWallet(s)
       -
       -    def get_client(self):
       -        if not TREZOR:
       -            self.give_error('please install github.com/trezor/python-trezor')
       -
       -        if not self.client or self.client.bad:
       -            d = HidTransport.enumerate()
       -            if not d:
       -                self.give_error('Could not connect to your Trezor. Please verify the cable is connected and that no other app is using it.')
       -            self.transport = HidTransport(d[0])
       -            self.client = QtGuiTrezorClient(self.transport)
       -            self.client.handler = self.handler
       -            self.client.set_tx_api(self)
       -            self.client.bad = False
       -            if not self.atleast_version(1, 2, 1):
       -                self.client = None
       -                self.give_error('Outdated Trezor firmware. Please update the firmware from https://www.mytrezor.com')
       -        return self.client
       -
       -if TREZOR:
       -    class QtGuiTrezorClient(ProtocolMixin, GuiMixin, BaseClient):
       -        protocol = proto
       -        device = 'Trezor'
       -
       -        def call_raw(self, msg):
       -            try:
       -                resp = BaseClient.call_raw(self, msg)
       -            except ConnectionError:
       -                self.bad = True
       -                raise
       -
       -            return resp
       +    from trezorlib.transport_hid import HidTransport