More keepkey / trezor commonizing and cleanup
This commit is contained in:
parent
33e57fe5a7
commit
f3329988b2
|
@ -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
|
||||
|
@ -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
|
||||
|
|
|
@ -3,10 +3,7 @@ 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)
|
||||
# Requires: self.proto, self.device
|
||||
|
||||
def callback_ButtonRequest(self, msg):
|
||||
if msg.code == 3:
|
||||
|
@ -26,7 +23,7 @@ class GuiMixin(object):
|
|||
cancel_callback = None
|
||||
|
||||
self.handler.show_message(message % self.device, cancel_callback)
|
||||
return self.protocol.ButtonAck()
|
||||
return self.proto.ButtonAck()
|
||||
|
||||
def callback_PinMatrixRequest(self, msg):
|
||||
if msg.type == 1:
|
||||
|
@ -39,19 +36,39 @@ class GuiMixin(object):
|
|||
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)
|
||||
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.protocol.Cancel()
|
||||
return self.protocol.PassphraseAck(passphrase=passphrase)
|
||||
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.protocol.WordAck(word=word)
|
||||
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
|
|
@ -8,39 +8,32 @@ from electrum.transaction import deserialize, is_extended_pubkey
|
|||
|
||||
class TrezorCompatiblePlugin(BasePlugin):
|
||||
# Derived classes provide:
|
||||
|
||||
# libraries_available()
|
||||
# constructor()
|
||||
# ckd_public
|
||||
# types
|
||||
# wallet_type
|
||||
#
|
||||
# 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
|
||||
self.transport = None
|
||||
|
||||
def constructor(self, s):
|
||||
raise NotImplementedError
|
||||
|
||||
@staticmethod
|
||||
def libraries_available():
|
||||
raise NotImplementedError
|
||||
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():
|
||||
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
|
||||
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)
|
||||
|
@ -52,9 +45,32 @@ class TrezorCompatiblePlugin(BasePlugin):
|
|||
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):
|
||||
features = self.get_client().features
|
||||
v = [features.major_version, features.minor_version, features.patch_version]
|
||||
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])
|
||||
|
|
@ -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
|
||||
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue