commit 3e8598c245c55aaa408199bc56800224639bd892
parent 54cdd551fead951b8c04624ea0b97090b3b10668
Author: Neil Booth <kyuupichan@gmail.com>
Date: Sat, 9 Jan 2016 15:20:31 +0900
Move trezor-specific install wizard code to plugin
Diffstat:
4 files changed, 107 insertions(+), 116 deletions(-)
diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py
@@ -418,88 +418,3 @@ class InstallWizard(WindowModalDialog, WizardBase):
self.set_layout(vbox)
if not self.exec_():
raise UserCancelled
-
- def request_trezor_init_settings(self, method, device):
- vbox = QVBoxLayout()
-
- main_label = QLabel(_("Initialization settings for your %s:") % device)
- vbox.addWidget(main_label)
-
- OK_button = OkButton(self, _('Next'))
-
- if method in [self.TIM_NEW, self.TIM_RECOVER]:
- gb = QGroupBox()
- vbox1 = QVBoxLayout()
- gb.setLayout(vbox1)
- vbox.addWidget(gb)
- gb.setTitle(_("Select your seed length:"))
- choices = [
- _("12 words"),
- _("18 words"),
- _("24 words"),
- ]
- bg = QButtonGroup()
- for i, choice in enumerate(choices):
- rb = QRadioButton(gb)
- rb.setText(choice)
- bg.addButton(rb)
- bg.setId(rb, i)
- vbox1.addWidget(rb)
- rb.setChecked(True)
- cb_pin = QCheckBox(_('Enable PIN protection'))
- cb_pin.setChecked(True)
- else:
- text = QTextEdit()
- text.setMaximumHeight(60)
- if method == self.TIM_MNEMONIC:
- msg = _("Enter your BIP39 mnemonic:")
- else:
- msg = _("Enter the master private key beginning with xprv:")
- def set_enabled():
- OK_button.setEnabled(Wallet.is_xprv(
- self.get_seed_text(text)))
- text.textChanged.connect(set_enabled)
- OK_button.setEnabled(False)
-
- vbox.addWidget(QLabel(msg))
- vbox.addWidget(text)
- pin = QLineEdit()
- pin.setValidator(QRegExpValidator(QRegExp('[1-9]{0,10}')))
- pin.setMaximumWidth(100)
- hbox_pin = QHBoxLayout()
- hbox_pin.addWidget(QLabel(_("Enter your PIN (digits 1-9):")))
- hbox_pin.addWidget(pin)
- hbox_pin.addStretch(1)
-
- label = QLabel(_("Enter a label to name your device:"))
- name = QLineEdit()
- hl = QHBoxLayout()
- hl.addWidget(label)
- hl.addWidget(name)
- hl.addStretch(1)
- vbox.addLayout(hl)
-
- if method in [self.TIM_NEW, self.TIM_RECOVER]:
- vbox.addWidget(cb_pin)
- else:
- vbox.addLayout(hbox_pin)
-
- cb_phrase = QCheckBox(_('Enable Passphrase protection'))
- cb_phrase.setChecked(False)
- vbox.addWidget(cb_phrase)
-
- vbox.addStretch(1)
- vbox.addLayout(Buttons(CancelButton(self), OK_button))
- self.set_layout(vbox)
-
- if not self.exec_():
- raise UserCancelled
-
- if method in [self.TIM_NEW, self.TIM_RECOVER]:
- item = bg.checkedId()
- pin = cb_pin.isChecked()
- else:
- item = ' '.join(str(self.get_seed_text(text)).split())
- pin = str(pin.text())
-
- return (item, unicode(name.text()), pin, cb_phrase.isChecked())
diff --git a/lib/wizard.py b/lib/wizard.py
@@ -48,7 +48,6 @@ class WizardBase(PrintError):
('multisig', _("Multi-signature wallet")),
('hardware', _("Hardware wallet")),
]
- TIM_NEW, TIM_RECOVER, TIM_MNEMONIC, TIM_PRIVKEY = range(0, 4)
# Derived classes must set:
# self.language_for_seed
@@ -103,23 +102,6 @@ class WizardBase(PrintError):
dynamic feedback. If not provided, Wallet.is_any is used."""
raise NotImplementedError
- def request_trezor_init_settings(self, method, device):
- """Ask the user for the information needed to initialize a trezor-
- compatible device. Method is one of the TIM_ trezor init
- method constants. TIM_NEW and TIM_RECOVER should ask how many
- seed words to use, and return 0, 1 or 2 for a 12, 18 or 24
- word seed respectively. TIM_MNEMONIC should ask for a
- mnemonic. TIM_PRIVKEY should ask for a master private key.
- All four methods should additionally ask for a name to label
- the device, PIN information and whether passphrase protection is
- to be enabled (True/False, default to False). For TIM_NEW and
- TIM_RECOVER, the pin information is whether pin protection
- is required (True/False, default to True); for TIM_MNEMONIC and
- TIM_PRIVKEY is is the pin as a string of digits 1-9.
- The result is a 4-tuple: (TIM specific data, label, pininfo,
- passphraseprotection)."""
- raise NotImplementedError
-
def request_many(self, n, xpub_hot=None):
"""If xpub_hot is provided, a new wallet is being created. Request N
master public keys for cosigners; xpub_hot is the master xpub
diff --git a/plugins/trezor/plugin.py b/plugins/trezor/plugin.py
@@ -14,7 +14,9 @@ from electrum.transaction import (deserialize, is_extended_pubkey,
from electrum.wallet import BIP32_HD_Wallet, BIP44_Wallet
from electrum.util import ThreadJob
from electrum.plugins import DeviceMgr
-from electrum.wizard import WizardBase
+
+# Trezor initialization methods
+TIM_NEW, TIM_RECOVER, TIM_MNEMONIC, TIM_PRIVKEY = range(0, 4)
class DeviceDisconnectedError(Exception):
pass
@@ -247,7 +249,7 @@ class TrezorCompatiblePlugin(BasePlugin, ThreadJob):
if isinstance(wallet, self.wallet_class):
self.device_manager().close_wallet(wallet)
- def initialize_device(self, wallet, wizard):
+ def initialize_device(self, wallet):
# Prevent timeouts during initialization
wallet.last_operation = self.prevent_timeout
@@ -268,22 +270,22 @@ class TrezorCompatiblePlugin(BasePlugin, ThreadJob):
_("Upload a master private key")
]
- method = wizard.query_choice(msg, methods)
+ method = wallet.handler.query_choice(msg, methods)
(item, label, pin_protection, passphrase_protection) \
- = wizard.request_trezor_init_settings(method, self.device)
+ = wallet.handler.request_trezor_init_settings(method, self.device)
client = self.get_client(wallet)
language = 'english'
- if method == WizardBase.TIM_NEW:
+ if method == TIM_NEW:
strength = 64 * (item + 2) # 128, 192 or 256
client.reset_device(True, strength, passphrase_protection,
pin_protection, label, language)
- elif method == WizardBase.TIM_RECOVER:
+ elif method == TIM_RECOVER:
word_count = 6 * (item + 2) # 12, 18 or 24
client.recovery_device(word_count, passphrase_protection,
pin_protection, label, language)
- elif method == WizardBase.TIM_MNEMONIC:
+ elif method == TIM_MNEMONIC:
pin = pin_protection # It's the pin, not a boolean
client.load_device_by_mnemonic(str(item), pin,
passphrase_protection,
@@ -293,7 +295,7 @@ class TrezorCompatiblePlugin(BasePlugin, ThreadJob):
client.load_device_by_xprv(item, pin, passphrase_protection,
label, language)
- def select_device(self, wallet, wizard):
+ def select_device(self, wallet):
'''Called when creating a new wallet. Select the device to use. If
the device is uninitialized, go through the intialization
process.'''
@@ -306,10 +308,10 @@ class TrezorCompatiblePlugin(BasePlugin, ThreadJob):
labels = list(map(client_desc, clients))
msg = _("Please select which %s device to use:") % self.device
- client = clients[wizard.query_choice(msg, labels)]
+ client = clients[wallet.handler.query_choice(msg, labels)]
self.device_manager().pair_wallet(wallet, client)
if not client.is_initialized():
- self.initialize_device(wallet, wizard)
+ self.initialize_device(wallet)
def on_restore_wallet(self, wallet, wizard):
assert isinstance(wallet, self.wallet_class)
diff --git a/plugins/trezor/qt_generic.py b/plugins/trezor/qt_generic.py
@@ -8,12 +8,13 @@ from PyQt4.Qt import QVBoxLayout, QLabel, SIGNAL
from electrum_gui.qt.main_window import StatusBarButton
from electrum_gui.qt.password_dialog import PasswordDialog
from electrum_gui.qt.util import *
-from plugin import TrezorCompatiblePlugin
+from .plugin import TrezorCompatiblePlugin, TIM_NEW, TIM_RECOVER, TIM_MNEMONIC
from electrum.i18n import _
from electrum.plugins import hook, DeviceMgr
from electrum.util import PrintError
-from electrum.wallet import BIP44_Wallet
+from electrum.wallet import Wallet, BIP44_Wallet
+from electrum.wizard import UserCancelled
# By far the trickiest thing about this handler is the window stack;
@@ -134,6 +135,97 @@ class QtHandler(PrintError):
finally:
assert dialog == self.window_stack.pop()
+ def query_choice(self, msg, labels):
+ return self.win.query_choice(msg, labels)
+
+ def request_trezor_init_settings(self, method, device):
+ wizard = self.win
+
+ vbox = QVBoxLayout()
+ main_label = QLabel(_("Initialization settings for your %s:") % device)
+ vbox.addWidget(main_label)
+ OK_button = OkButton(wizard, _('Next'))
+
+ def clean_text(widget):
+ text = unicode(widget.toPlainText()).strip()
+ return ' '.join(text.split())
+
+ if method in [TIM_NEW, TIM_RECOVER]:
+ gb = QGroupBox()
+ vbox1 = QVBoxLayout()
+ gb.setLayout(vbox1)
+ vbox.addWidget(gb)
+ gb.setTitle(_("Select your seed length:"))
+ choices = [
+ _("12 words"),
+ _("18 words"),
+ _("24 words"),
+ ]
+ bg = QButtonGroup()
+ for i, choice in enumerate(choices):
+ rb = QRadioButton(gb)
+ rb.setText(choice)
+ bg.addButton(rb)
+ bg.setId(rb, i)
+ vbox1.addWidget(rb)
+ rb.setChecked(True)
+ cb_pin = QCheckBox(_('Enable PIN protection'))
+ cb_pin.setChecked(True)
+ else:
+ text = QTextEdit()
+ text.setMaximumHeight(60)
+ if method == TIM_MNEMONIC:
+ msg = _("Enter your BIP39 mnemonic:")
+ else:
+ msg = _("Enter the master private key beginning with xprv:")
+ def set_enabled():
+ OK_button.setEnabled(Wallet.is_xprv(clean_text(text)))
+ text.textChanged.connect(set_enabled)
+ OK_button.setEnabled(False)
+
+ vbox.addWidget(QLabel(msg))
+ vbox.addWidget(text)
+ pin = QLineEdit()
+ pin.setValidator(QRegExpValidator(QRegExp('[1-9]{0,10}')))
+ pin.setMaximumWidth(100)
+ hbox_pin = QHBoxLayout()
+ hbox_pin.addWidget(QLabel(_("Enter your PIN (digits 1-9):")))
+ hbox_pin.addWidget(pin)
+ hbox_pin.addStretch(1)
+
+ label = QLabel(_("Enter a label to name your device:"))
+ name = QLineEdit()
+ hl = QHBoxLayout()
+ hl.addWidget(label)
+ hl.addWidget(name)
+ hl.addStretch(1)
+ vbox.addLayout(hl)
+
+ if method in [TIM_NEW, TIM_RECOVER]:
+ vbox.addWidget(cb_pin)
+ else:
+ vbox.addLayout(hbox_pin)
+
+ cb_phrase = QCheckBox(_('Enable Passphrase protection'))
+ cb_phrase.setChecked(False)
+ vbox.addWidget(cb_phrase)
+
+ vbox.addStretch(1)
+ vbox.addLayout(Buttons(CancelButton(wizard), OK_button))
+
+ wizard.set_layout(vbox)
+ if not wizard.exec_():
+ raise UserCancelled
+
+ if method in [TIM_NEW, TIM_RECOVER]:
+ item = bg.checkedId()
+ pin = cb_pin.isChecked()
+ else:
+ item = ' '.join(str(clean_text(text)).split())
+ pin = str(pin.text())
+
+ return (item, unicode(name.text()), pin, cb_phrase.isChecked())
+
def qt_plugin_class(base_plugin_class):
@@ -159,7 +251,7 @@ def qt_plugin_class(base_plugin_class):
def on_create_wallet(self, wallet, wizard):
assert type(wallet) == self.wallet_class
wallet.handler = self.create_handler(wizard)
- self.select_device(wallet, wizard)
+ self.select_device(wallet)
wallet.create_hd_account(None)
@hook