commit 4781df9d2107ec65181e99073aaac4bbf18ade91
parent 0520eda628eab626b8e698e8166a9d72798d92ce
Author: ThomasV <thomasv@electrum.org>
Date: Tue, 23 Aug 2016 13:40:11 +0200
wizard: scan hardware devices directly
Diffstat:
5 files changed, 62 insertions(+), 44 deletions(-)
diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py
@@ -338,13 +338,13 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
self.show_message(msg)
@wizard_dialog
- def confirm_dialog(self, msg, run_next):
- self.confirm(msg)
+ def confirm_dialog(self, title, message, run_next):
+ self.confirm(message, title)
- def confirm(self, msg):
+ def confirm(self, message, title):
vbox = QVBoxLayout()
- vbox.addWidget(WWLabel(msg))
- self.set_main_layout(vbox)
+ vbox.addWidget(WWLabel(message))
+ self.set_main_layout(vbox, title)
@wizard_dialog
def action_dialog(self, action, run_next):
@@ -379,6 +379,13 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
self.set_main_layout(vbox, '')
return clayout.selected_index()
+ def get_passphrase(self, msg, confirm):
+ phrase = self.pw_layout(msg, PW_PASSPHRASE)
+ if phrase is None:
+ raise UserCancelled
+ return phrase
+
+
@wizard_dialog
def account_id_dialog(self, run_next):
message = '\n'.join([
diff --git a/lib/base_wizard.py b/lib/base_wizard.py
@@ -117,12 +117,12 @@ class BaseWizard(object):
('create_seed', _('Create a new seed')),
('restore_seed', _('I already have a seed')),
('restore_from_key', _('Import keys')),
- ('choose_hw', _('Use hardware device')),
+ ('choose_device', _('Use hardware device')),
]
else:
choices = [
('restore_from_key', _('Import cosigner key')),
- ('choose_hw', _('Cosign with hardware device')),
+ ('choose_device', _('Cosign with hardware device')),
]
self.choice_dialog(title=title, message=message, choices=choices, run_next=self.run)
@@ -165,46 +165,59 @@ class BaseWizard(object):
])
self.restore_keys_dialog(title=title, message=message, run_next=self.on_restore, is_valid=v)
- def choose_hw(self):
- hw_wallet_types, choices = self.plugins.hardware_wallets('create')
- choices = zip(hw_wallet_types, choices)
+ def choose_device(self):
title = _('Hardware Keystore')
- if choices:
- msg = _('Select the type of device') + ':'
- else:
- msg = ' '.join([
+ # check available plugins
+ support = self.plugins.get_hardware_support()
+ if not support:
+ msg = '\n'.join([
_('No hardware wallet support found on your system.'),
_('Please install the relevant libraries (eg python-trezor for Trezor).'),
])
- self.choice_dialog(title=title, message=msg, choices=choices, run_next=self.on_hardware)
-
- def on_hardware(self, hw_type):
- self.hw_type = hw_type
- title = _('Hardware wallet') + ' [%s]' % hw_type
- message = _('Do you have a device, or do you want to restore a wallet using an existing seed?')
- choices = [
- ('on_hardware_device', _('I have a %s device')%hw_type),
- ('on_hardware_seed', _('I have a %s seed')%hw_type),
- ]
- self.choice_dialog(title=title, message=message, choices=choices, run_next=self.run)
-
- def on_hardware_device(self):
- f = lambda x: self.run('on_hardware_account_id', x)
+ self.confirm_dialog(title=title, message=msg, run_next= lambda x: self.choose_device())
+ return
+ # scan devices
+ devices = []
+ for name, description, plugin in support:
+ devmgr = plugin.device_manager()
+ try:
+ u = devmgr.unpaired_device_infos(self, plugin)
+ except:
+ print "error", name
+ continue
+ devices += map(lambda x: (name, x), u)
+ if not devices:
+ msg = '\n'.join([
+ _('No hardware device detected.'),
+ _('To trigger a rescan, press \'next\'.'),
+ ])
+ self.confirm_dialog(title=title, message=msg, run_next= lambda x: self.choose_device())
+ return
+ # select device
+ self.devices = devices
+ choices = []
+ for name, device_info in devices:
+ choices.append( ((name, device_info), device_info.description) )
+ msg = _('Select a device') + ':'
+ self.choice_dialog(title=title, message=msg, choices=choices, run_next=self.on_device)
+
+ def on_device(self, name, device_info):
+ f = lambda x: self.run('on_hardware_account_id', name, device_info, x)
self.account_id_dialog(run_next=f)
- def on_hardware_account_id(self, account_id):
+ def on_hardware_account_id(self, hw_type, device_info, account_id):
from keystore import hardware_keystore, bip44_derivation
derivation = bip44_derivation(int(account_id))
- plugin = self.plugins.get_plugin(self.hw_type)
- xpub = plugin.setup_device(derivation, self)
+ plugin = self.plugins.get_plugin(hw_type)
+ xpub = plugin.setup_device(device_info, derivation, self)
# create keystore
d = {
'type': 'hardware',
- 'hw_type': self.hw_type,
+ 'hw_type': hw_type,
'derivation': derivation,
'xpub': xpub,
}
- k = hardware_keystore(self.hw_type, d)
+ k = hardware_keystore(hw_type, d)
self.on_keystore(k, None)
def on_hardware_seed(self):
diff --git a/lib/plugins.py b/lib/plugins.py
@@ -139,19 +139,18 @@ class Plugins(DaemonThread):
requires = d.get('requires_wallet_type', [])
return not requires or w.wallet_type in requires
- def hardware_wallets(self, action):
- wallet_types, descs = [], []
+ def get_hardware_support(self):
+ out = []
for name, (gui_good, details) in self.hw_wallets.items():
if gui_good:
try:
p = self.get_plugin(name)
- if action == 'restore' or p.is_enabled():
- wallet_types.append(details[1])
- descs.append(details[2])
+ if p.is_enabled():
+ out.append([name, details[2], p])
except:
traceback.print_exc()
self.print_error("cannot load plugin for:", name)
- return wallet_types, descs
+ return out
def register_wallet_type(self, name, gui_good, wallet_type):
from wallet import register_wallet_type, register_constructor
diff --git a/plugins/trezor/plugin.py b/plugins/trezor/plugin.py
@@ -199,13 +199,12 @@ class TrezorCompatiblePlugin(HW_PluginBase):
client.load_device_by_xprv(item, pin, passphrase_protection,
label, language)
- def setup_device(self, derivation, wizard):
+ def setup_device(self, device_info, derivation, wizard):
'''Called when creating a new wallet. Select the device to use. If
the device is uninitialized, go through the intialization
process.'''
- handler = self.create_handler(wizard)
+ handler = wizard
devmgr = self.device_manager()
- device_info = devmgr.select_device(handler, self)
device_id = device_info.device.id_
if not device_info.initialized:
self.initialize_device(device_id, wizard, handler)
diff --git a/plugins/trustedcoin/trustedcoin.py b/plugins/trustedcoin/trustedcoin.py
@@ -337,7 +337,7 @@ class TrustedCoinPlugin(BasePlugin):
def show_disclaimer(self, wizard):
wizard.set_icon(':icons/trustedcoin.png')
wizard.stack = []
- wizard.confirm_dialog('\n\n'.join(DISCLAIMER), run_next = lambda x: wizard.run('choose_seed'))
+ wizard.confirm_dialog(title='Disclaimer', message='\n\n'.join(DISCLAIMER), run_next = lambda x: wizard.run('choose_seed'))
def choose_seed(self, wizard):
title = _('Create or restore')
@@ -372,7 +372,7 @@ class TrustedCoinPlugin(BasePlugin):
]
msg = '\n\n'.join(msg)
wizard.stack = []
- wizard.confirm_dialog(msg, run_next = lambda x: wizard.run('create_remote_key'))
+ wizard.confirm_dialog(title='', message=msg, run_next = lambda x: wizard.run('create_remote_key'))
def restore_wallet(self, wizard):
title = _("Restore two-factor Wallet")