electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit c02daa56b0f48f8fd2e110e7d0ed6e434ff696e8
parent d69551f723f5b9ee94a6b5f3af7cf69aec1a78e0
Author: Neil Booth <kyuupichan@gmail.com>
Date:   Sun, 27 Dec 2015 15:00:58 +0900

Finish merging keepkey / trezor implementations

Diffstat:
Mplugins/keepkey/qt.py | 100++++---------------------------------------------------------------------------
Mplugins/trezor/plugin.py | 2+-
Mplugins/trezor/qt.py | 114+++----------------------------------------------------------------------------
Mplugins/trezor/qt_generic.py | 125++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
4 files changed, 126 insertions(+), 215 deletions(-)

diff --git a/plugins/keepkey/qt.py b/plugins/keepkey/qt.py @@ -1,98 +1,6 @@ -from PyQt4.Qt import QVBoxLayout, QLabel, SIGNAL, QGridLayout, QInputDialog, QPushButton -import PyQt4.QtCore as QtCore -from electrum_gui.qt.util import * -from electrum_gui.qt.main_window import StatusBarButton, ElectrumWindow - -from functools import partial -import unicodedata - -from electrum.i18n import _ -from electrum.plugins import hook - -from plugins.trezor.qt_generic import QtHandler +from plugins.trezor.qt_generic import QtPlugin from keepkeylib.qt.pinmatrix import PinMatrixWidget -from keepkey import KeepKeyPlugin, KeepKeyWallet - -class KeepKeyQtHandler(QtHandler): - device = 'KeepKey' - pin_matrix_widget_class = PinMatrixWidget - -class Plugin(KeepKeyPlugin): - - @hook - def load_wallet(self, wallet, window): - self.print_error("load_wallet") - self.wallet = wallet - self.wallet.plugin = self - self.keepkey_button = StatusBarButton(QIcon(":icons/keepkey.png"), _("KeepKey"), partial(self.settings_dialog, window)) - if type(window) is ElectrumWindow: - window.statusBar().addPermanentWidget(self.keepkey_button) - if self.handler is None: - self.handler = KeepKeyQtHandler(window) - msg = self.wallet.sanity_check() - if msg: - window.show_error(msg) - - @hook - def installwizard_load_wallet(self, wallet, window): - if type(wallet) != KeepKeyWallet: - return - self.load_wallet(wallet, window) - - @hook - def installwizard_restore(self, wizard, storage): - if storage.get('wallet_type') != 'keepkey': - return - seed = wizard.enter_seed_dialog("Enter your KeepKey seed", None, func=lambda x:True) - if not seed: - return - wallet = KeepKeyWallet(storage) - self.wallet = wallet - handler = KeepKeyQtHandler(wizard) - passphrase = handler.get_passphrase(_("Please enter your KeepKey passphrase.") + '\n' + _("Press OK if you do not use one.")) - if passphrase is None: - return - password = wizard.password_dialog() - wallet.add_seed(seed, password) - wallet.add_cosigner_seed(seed, 'x/', password, passphrase) - wallet.create_main_account(password) - # disable keepkey plugin - self.set_enabled(False) - return wallet - - @hook - def receive_menu(self, menu, addrs): - if not self.wallet.is_watching_only() and self.atleast_version(1, 3) and len(addrs) == 1: - menu.addAction(_("Show on TREZOR"), lambda: self.show_address(addrs[0])) - - def settings_dialog(self, window): - try: - device_id = self.get_client().get_device_id() - except BaseException as e: - window.show_message(str(e)) - return - get_label = lambda: self.get_client().features.label - update_label = lambda: current_label_label.setText("Label: %s" % get_label()) - d = WindowModalDialog(window, _("KeepKey Settings")) - layout = QGridLayout(d) - layout.addWidget(QLabel("KeepKey Options"),0,0) - layout.addWidget(QLabel("ID:"),1,0) - layout.addWidget(QLabel(" %s" % device_id),1,1) - - def modify_label(): - response = QInputDialog().getText(None, "Set New KeepKey Label", "New KeepKey Label: (upon submission confirm on KeepKey)") - if not response[1]: - return - new_label = str(response[0]) - self.handler.show_message("Please confirm label change on KeepKey") - status = self.get_client().apply_settings(label=new_label) - self.handler.stop() - update_label() - current_label_label = QLabel() - update_label() - change_label_button = QPushButton("Modify") - change_label_button.clicked.connect(modify_label) - layout.addWidget(current_label_label,3,0) - layout.addWidget(change_label_button,3,1) - d.exec_() +class Plugin(QtPlugin): + handler_class = KeepKeyQtHandler + icon_file = ":icons/keepkey.png" diff --git a/plugins/trezor/plugin.py b/plugins/trezor/plugin.py @@ -9,7 +9,7 @@ from electrum.transaction import deserialize, is_extended_pubkey class TrezorCompatiblePlugin(BasePlugin): # Derived classes provide: # - # class-static variables: client_class, firmware_URL, + # class-static variables: client_class, firmware_URL, handler_class, # libraries_available, libraries_URL, minimum_firmware, # wallet_class, ckd_public, types, HidTransport diff --git a/plugins/trezor/qt.py b/plugins/trezor/qt.py @@ -1,114 +1,6 @@ -from PyQt4.Qt import QVBoxLayout, QLabel, SIGNAL, QGridLayout, QInputDialog, QPushButton -import PyQt4.QtCore as QtCore -from electrum_gui.qt.util import * -from electrum_gui.qt.main_window import StatusBarButton, ElectrumWindow - -from functools import partial -import unicodedata - -from electrum.i18n import _ -from electrum.plugins import hook - -from plugins.trezor.qt_generic import QtHandler -from trezor import TrezorPlugin, TrezorWallet +from plugins.trezor.qt_generic import QtPlugin from trezorlib.qt.pinmatrix import PinMatrixWidget -class TrezorQtHandler(QtHandler): - device = 'Trezor' +class Plugin(QtPlugin): pin_matrix_widget_class = PinMatrixWidget - -class Plugin(TrezorPlugin): - - @hook - def load_wallet(self, wallet, window): - self.print_error("load_wallet") - self.wallet = wallet - self.wallet.plugin = self - self.trezor_button = StatusBarButton(QIcon(":icons/trezor.png"), _("Trezor"), partial(self.settings_dialog, window)) - if type(window) is ElectrumWindow: - window.statusBar().addPermanentWidget(self.trezor_button) - if self.handler is None: - self.handler = TrezorQtHandler(window) - msg = self.wallet.sanity_check() - if msg: - window.show_error(msg) - - @hook - def installwizard_load_wallet(self, wallet, window): - if type(wallet) != TrezorWallet: - return - self.load_wallet(wallet, window) - - @hook - def installwizard_restore(self, wizard, storage): - if storage.get('wallet_type') != 'trezor': - return - seed = wizard.enter_seed_dialog("Enter your Trezor seed", None, func=lambda x:True) - if not seed: - return - wallet = TrezorWallet(storage) - self.wallet = wallet - handler = TrezorQtHandler(wizard) - passphrase = handler.get_passphrase(_("Please enter your Trezor passphrase.") + '\n' + _("Press OK if you do not use one.")) - if passphrase is None: - return - password = wizard.password_dialog() - wallet.add_seed(seed, password) - wallet.add_cosigner_seed(seed, 'x/', password, passphrase) - wallet.create_main_account(password) - # disable trezor plugin - self.set_enabled(False) - return wallet - - @hook - def receive_menu(self, menu, addrs): - if not self.wallet.is_watching_only() and self.atleast_version(1, 3) and len(addrs) == 1: - menu.addAction(_("Show on TREZOR"), lambda: self.show_address(addrs[0])) - - def show_address(self, address): - if not self.wallet.check_proper_device(): - give_error('Wrong device or password') - try: - address_path = self.wallet.address_id(address) - address_n = self.get_client().expand_path(address_path) - except Exception, e: - give_error(e) - try: - self.get_client().get_address('Bitcoin', address_n, True) - except Exception, e: - give_error(e) - finally: - self.handler.stop() - - - def settings_dialog(self, window): - try: - device_id = self.get_client().get_device_id() - except BaseException as e: - window.show_message(str(e)) - return - get_label = lambda: self.get_client().features.label - update_label = lambda: current_label_label.setText("Label: %s" % get_label()) - d = WindowModalDialog(window, _("Trezor Settings")) - layout = QGridLayout(d) - layout.addWidget(QLabel("Trezor Options"),0,0) - layout.addWidget(QLabel("ID:"),1,0) - layout.addWidget(QLabel(" %s" % device_id),1,1) - - def modify_label(): - response = QInputDialog().getText(None, "Set New Trezor Label", "New Trezor Label: (upon submission confirm on Trezor)") - if not response[1]: - return - new_label = str(response[0]) - self.handler.show_message("Please confirm label change on Trezor") - status = self.get_client().apply_settings(label=new_label) - self.handler.stop() - update_label() - - current_label_label = QLabel() - update_label() - change_label_button = QPushButton("Modify") - change_label_button.clicked.connect(modify_label) - layout.addWidget(current_label_label,3,0) - layout.addWidget(change_label_button,3,1) - d.exec_() + icon_file = ":icons/trezor.png" diff --git a/plugins/trezor/qt_generic.py b/plugins/trezor/qt_generic.py @@ -1,30 +1,31 @@ +from functools import partial from unicodedata import normalize import threading +from PyQt4.Qt import QGridLayout, QInputDialog, QPushButton from PyQt4.Qt import QVBoxLayout, QLabel, SIGNAL -import PyQt4.QtCore as QtCore -from electrum_gui.qt.main_window import ElectrumWindow +from trezor import TrezorPlugin +from electrum_gui.qt.main_window import ElectrumWindow, StatusBarButton from electrum_gui.qt.installwizard import InstallWizard from electrum_gui.qt.password_dialog import PasswordDialog from electrum_gui.qt.util import * from electrum.i18n import _ +from electrum.plugins import hook class QtHandler: '''An interface between the GUI (here, QT) and the device handling logic for handling I/O. This is a generic implementation of the Trezor protocol; derived classes can customize it.''' - # Derived classes must provide: - # device a string, e.g. "Trezor" - # pin_matrix_widget_class - - def __init__(self, win): + def __init__(self, win, pin_matrix_widget_class, device): win.connect(win, SIGNAL('message_done'), self.dialog_stop) win.connect(win, SIGNAL('message_dialog'), self.message_dialog) win.connect(win, SIGNAL('pin_dialog'), self.pin_dialog) win.connect(win, SIGNAL('passphrase_dialog'), self.passphrase_dialog) self.win = win + self.pin_matrix_widget_class = pin_matrix_widget_class + self.device = device self.done = threading.Event() self.dialog = None @@ -92,3 +93,113 @@ class QtHandler: if self.dialog: self.dialog.hide() self.dialog = None + + +class QtPlugin(TrezorPlugin): + # Derived classes must provide the following class-static variables: + # icon_file + # pin_matrix_widget_class + + def create_handler(self, window): + return QtHandler(window, self.pin_matrix_widget_class, self.device) + + @hook + def load_wallet(self, wallet, window): + self.print_error("load_wallet") + self.wallet = wallet + self.wallet.plugin = self + self.button = StatusBarButton(QIcon(self.icon_file), self.device, + partial(self.settings_dialog, window)) + if type(window) is ElectrumWindow: + window.statusBar().addPermanentWidget(self.button) + if self.handler is None: + self.handler = self.create_handler(window) + msg = self.wallet.sanity_check() + if msg: + window.show_error(msg) + + @hook + def installwizard_load_wallet(self, wallet, window): + if type(wallet) != self.wallet_class: + return + self.load_wallet(wallet, window) + + @hook + def installwizard_restore(self, wizard, storage): + if storage.get('wallet_type') != self.wallet_class.wallet_type: + return + seed = wizard.enter_seed_dialog(_("Enter your %s seed") % self.device, + None, func=lambda x:True) + if not seed: + return + wallet = self.wallet_class(storage) + self.wallet = wallet + handler = self.create_handler(wizard) + msg = "\n".join([_("Please enter your %s passphrase.") % self.device, + _("Press OK if you do not use one.")]) + passphrase = handler.get_passphrase(msg) + if passphrase is None: + return + password = wizard.password_dialog() + wallet.add_seed(seed, password) + wallet.add_cosigner_seed(seed, 'x/', password, passphrase) + wallet.create_main_account(password) + # disable plugin as this is a free-standing wallet + self.set_enabled(False) + return wallet + + @hook + def receive_menu(self, menu, addrs): + if (not self.wallet.is_watching_only() and self.atleast_version(1, 3) + and len(addrs) == 1): + menu.addAction(_("Show on %s") % self.device, + lambda: self.show_address(addrs[0])) + + def show_address(self, address): + self.wallet.check_proper_device() + try: + address_path = self.wallet.address_id(address) + address_n = self.get_client().expand_path(address_path) + except Exception, e: + self.give_error(e) + try: + self.get_client().get_address('Bitcoin', address_n, True) + except Exception, e: + self.give_error(e) + finally: + self.handler.stop() + + def settings_dialog(self, window): + try: + device_id = self.get_client().get_device_id() + except BaseException as e: + window.show_error(str(e)) + return + get_label = lambda: self.get_client().features.label + update_label = lambda: current_label.setText("Label: %s" % get_label()) + d = WindowModalDialog(window, _("%s Settings") % self.device) + layout = QGridLayout(d) + layout.addWidget(QLabel(_("%s Options") % self.device), 0, 0) + layout.addWidget(QLabel("ID:"), 1, 0) + layout.addWidget(QLabel(" %s" % device_id), 1, 1) + + def modify_label(): + title = _("Set New %s Label") % self.device + msg = _("New Label: (upon submission confirm on %s)") % self.device + response = QInputDialog().getText(None, title, msg) + if not response[1]: + return + new_label = str(response[0]) + msg = _("Please confirm label change on %s") % self.device + self.handler.show_message(msg) + status = self.get_client().apply_settings(label=new_label) + self.handler.stop() + update_label() + + current_label = QLabel() + update_label() + change_label_button = QPushButton("Modify") + change_label_button.clicked.connect(modify_label) + layout.addWidget(current_label,3,0) + layout.addWidget(change_label_button,3,1) + d.exec_()