def __init__(self, parent): super(MatrixDialog, self).__init__(parent) self.setWindowTitle(_("Trezor Matrix Recovery")) self.num = 9 self.loop = QEventLoop() vbox = QVBoxLayout(self) vbox.addWidget(WWLabel(MATRIX_RECOVERY)) grid = QGridLayout() grid.setSpacing(0) self.char_buttons = [] for y in range(3): for x in range(3): button = QPushButton('?') button.clicked.connect( partial(self.process_key, ord('1') + y * 3 + x)) grid.addWidget(button, 3 - y, x) self.char_buttons.append(button) vbox.addLayout(grid) self.backspace_button = QPushButton("<=") self.backspace_button.clicked.connect( partial(self.process_key, Qt.Key_Backspace)) self.cancel_button = QPushButton(_("Cancel")) self.cancel_button.clicked.connect( partial(self.process_key, Qt.Key_Escape)) buttons = Buttons(self.backspace_button, self.cancel_button) vbox.addSpacing(40) vbox.addLayout(buttons) self.refresh() self.show()
def load_wallet(self, wallet, window): for keystore in wallet.get_keystores(): if not isinstance(keystore, self.keystore_class): continue if not self.libraries_available: if hasattr(self, 'libraries_available_message'): message = self.libraries_available_message + '\n' else: message = _("Cannot find python library for" ) + " '%s'.\n" % self.name message += _("Make sure you install it with python3") window.show_error(message) return tooltip = self.device + '\n' + (keystore.label or 'unnamed') cb = partial(self.show_settings_dialog, window, keystore) button = StatusBarButton(QIcon(self.icon_unpaired), tooltip, cb) button.icon_paired = self.icon_paired button.icon_unpaired = self.icon_unpaired window.statusBar().addPermanentWidget(button) handler = self.create_handler(window) handler.button = button keystore.handler = handler keystore.thread = TaskThread(window, window.on_error) self.add_show_address_on_hw_device_button_for_receive_addr( wallet, keystore, window) # Trigger a pairing keystore.thread.add(partial(self.get_client, keystore))
def seed_options(self): dialog = QDialog() vbox = QVBoxLayout(dialog) if 'ext' in self.options: cb_ext = QCheckBox(_('Extend this seed with custom words')) cb_ext.setChecked(self.is_ext) vbox.addWidget(cb_ext) if 'bip39' in self.options: def f(b): self.is_seed = (lambda x: bool(x)) if b else self.saved_is_seed self.is_bip39 = b self.on_edit() if b: msg = ' '.join([ '<b>' + _('Warning') + ':</b> ', _('BIP39 seeds can be imported in Electrum, so that users can access funds locked in other wallets.'), _('However, we do not generate BIP39 seeds, because they do not meet our safety standard.'), _('BIP39 seeds do not include a version number, which compromises compatibility with future software.'), _('We do not guarantee that BIP39 imports will always be supported in Electrum.'), ]) else: msg = '' self.seed_warning.setText(msg) cb_bip39 = QCheckBox(_('BIP39 seed (e.g. Android)')) cb_bip39.toggled.connect(f) cb_bip39.setChecked(self.is_bip39) vbox.addWidget(cb_bip39) vbox.addLayout(Buttons(OkButton(dialog))) if not dialog.exec_(): return None self.is_ext = cb_ext.isChecked() if 'ext' in self.options else False self.is_bip39 = cb_bip39.isChecked() if 'bip39' in self.options else False
def show_address(self, wallet, address, keystore=None): if keystore is None: keystore = wallet.get_keystore() if not self.show_address_helper(wallet, address, keystore): return if type(wallet) is not Standard_Wallet: keystore.handler.show_error( _('This function is only available for standard wallets when using {}.' ).format(self.device)) return client = self.get_client(wallet.keystore) if not client.atleast_version(1, 3): wallet.keystore.handler.show_error( _("Your device firmware is too old")) return change, index = wallet.get_address_index(address) derivation = wallet.keystore.derivation address_path = "%s/%d/%d" % (derivation, change, index) address_n = client.expand_path(address_path) segwit = wallet.keystore.is_segwit() script_type = self.types.SPENDP2SHWITNESS if segwit else self.types.SPENDADDRESS client.get_address(self.get_coin_name(), address_n, True, script_type=script_type)
def create_menu(self, position): item = self.itemAt(position) if not item: return addr = str(item.text(1)) req = self.wallet.receive_requests.get(addr) if req is None: self.update() return column = self.currentColumn() column_title = self.headerItem().text(column) column_data = item.text(column) menu = QMenu(self) menu.addAction( _("Copy {}").format(column_title), lambda: self.parent.app.clipboard().setText(column_data)) menu.addAction( _("Copy URI"), lambda: self.parent.view_and_paste( 'URI', '', self.parent.get_request_URI(addr))) menu.addAction(_("Save as BIP70 file"), lambda: self.parent.export_payment_request(addr)) menu.addAction(_("Delete"), lambda: self.parent.delete_payment_request(addr)) run_hook('receive_list_menu', menu, addr) menu.exec_(self.viewport().mapToGlobal(position))
def make_cypherseed(self, img, rawnoise, calibration=False, is_seed=True): img = img.convertToFormat(QImage.Format_Mono) p = QPainter() p.begin(img) p.setCompositionMode(26) #xor p.drawImage(0, 0, rawnoise) p.end() cypherseed = self.pixelcode_2x2(img) cypherseed = QBitmap.fromImage(cypherseed) cypherseed = cypherseed.scaled(self.f_size, Qt.KeepAspectRatio) cypherseed = self.overlay_marks(cypherseed, True, calibration) if not is_seed: self.filename = _('custom_secret') + '_' self.was = _('Custom secret') else: self.filename = self.wallet_name + '_' + _('seed') + '_' self.was = self.wallet_name + ' ' + _('seed') if not calibration: self.toPdf(QImage(cypherseed)) QDesktopServices.openUrl( QUrl.fromLocalFile( os.path.abspath(self.base_dir + self.filename + self.version + '_' + self.code_id + '.pdf'))) cypherseed.save(self.base_dir + self.filename + self.version + '_' + self.code_id + '.png') self.bcrypt(self.c_dialog) return cypherseed
def dbb_load_backup(self, show_msg=True): backups = self.hid_send_encrypt(b'{"backup":"list"}') if 'error' in backups: raise Exception(backups['error']['message']) try: f = self.handler.win.query_choice(_("Choose a backup file:"), backups['backup']) except Exception: return False # Back button pushed key = self.backup_password_dialog() if key is None: raise Exception('Canceled by user') key = self.stretch_key(key) if show_msg: self.handler.show_message( _("Loading backup...") + "\n\n" + _("To continue, touch the Digital Bitbox's light for 3 seconds." ) + "\n\n" + _("To cancel, briefly touch the light or wait for the timeout." )) msg = ('{"seed":{"source": "backup", "key": "%s", "filename": "%s"}}' % (key, backups['backup'][f])).encode('utf8') hid_reply = self.hid_send_encrypt(msg) self.handler.finished() if 'error' in hid_reply: raise Exception(hid_reply['error']['message']) return True
def task(): wallet.wait_until_synchronized() if wallet.is_found(): msg = _("Recovery successful") else: msg = _("No transactions found for this seed") self.synchronized_signal.emit(msg)
def __init__(self, parent): super(CharacterDialog, self).__init__(parent) self.setWindowTitle(_("KeepKey Seed Recovery")) self.character_pos = 0 self.word_pos = 0 self.loop = QEventLoop() self.word_help = QLabel() self.char_buttons = [] vbox = QVBoxLayout(self) vbox.addWidget(WWLabel(CHARACTER_RECOVERY)) hbox = QHBoxLayout() hbox.addWidget(self.word_help) for i in range(4): char_button = CharacterButton('*') char_button.setMaximumWidth(36) self.char_buttons.append(char_button) hbox.addWidget(char_button) self.accept_button = CharacterButton(_("Accept Word")) self.accept_button.clicked.connect(partial(self.process_key, 32)) self.rejected.connect(partial(self.loop.exit, 1)) hbox.addWidget(self.accept_button) hbox.addStretch(1) vbox.addLayout(hbox) self.finished_button = QPushButton(_("Seed Entered")) self.cancel_button = QPushButton(_("Cancel")) self.finished_button.clicked.connect( partial(self.process_key, Qt.Key_Return)) self.cancel_button.clicked.connect(self.rejected) buttons = Buttons(self.finished_button, self.cancel_button) vbox.addSpacing(40) vbox.addLayout(buttons) self.refresh() self.show()
def show_address(self, wallet, address, keystore=None): if keystore is None: keystore = wallet.get_keystore() if not self.show_address_helper(wallet, address, keystore): return if type(wallet) is not Standard_Wallet: keystore.handler.show_error( _('This function is only available for standard wallets when using {}.' ).format(self.device)) return if not self.is_mobile_paired(): keystore.handler.show_error( _('This function is only available after pairing your {} with a mobile device.' ).format(self.device)) return if not keystore.is_p2pkh(): keystore.handler.show_error( _('This function is only available for p2pkh keystores when using {}.' ).format(self.device)) return change, index = wallet.get_address_index(address) keypath = '%s/%d/%d' % (keystore.derivation, change, index) xpub = self.get_client(keystore)._get_xpub(keypath) verify_request_payload = { "type": 'p2pkh', "echo": xpub['echo'], } self.comserver_post_notification(verify_request_payload)
def get_tooltip(self, pos, fee_rate): mempool = self.config.use_mempool_fees() target, estimate = self.config.get_fee_text(pos, self.dyn, mempool, fee_rate) if self.dyn: return _('Target') + ': ' + target + '\n' + _('Current rate') + ': ' + estimate else: return _('Fixed rate') + ': ' + target + '\n' + _('Estimate') + ': ' + estimate
def show_address(self, sequence, txin_type): client = self.get_client() address_path = self.get_derivation()[2:] + "/%d/%d" % sequence self.handler.show_message(_("Showing address ...")) segwit = Transaction.is_segwit_inputtype(txin_type) segwitNative = txin_type == 'p2wpkh' try: client.getWalletPublicKey(address_path, showOnScreen=True, segwit=segwit, segwitNative=segwitNative) except BTChipException as e: if e.sw == 0x6985: # cancelled by user pass elif e.sw == 0x6982: raise # pin lock. decorator will catch it elif e.sw == 0x6b00: # hw.1 raises this self.handler.show_error('{}\n{}\n{}'.format( _('Error showing address') + ':', e, _('Your device might not have support for this functionality.' ))) else: traceback.print_exc(file=sys.stderr) self.handler.show_error(e) except BaseException as e: traceback.print_exc(file=sys.stderr) self.handler.show_error(e) finally: self.handler.finished()
def toggle_passphrase(self): if self.features.passphrase_protection: self.msg = _("Confirm on your {} device to disable passphrases") else: self.msg = _("Confirm on your {} device to enable passphrases") enabled = not self.features.passphrase_protection self.apply_settings(use_passphrase=enabled)
def add_cosigner_dialog(self, run_next, index, is_valid): title = _("Add Cosigner") + " %d" % index message = ' '.join([ _('Please enter the master public key (xpub) of your cosigner.'), _('Enter their master private key (xprv) if you want to be able to sign for them.' ) ]) return self.text_input(title, message, is_valid)
def __init__(self, text="", allow_multi=False): ButtonsTextEdit.__init__(self, text) self.allow_multi = allow_multi self.setReadOnly(0) self.addButton(":icons/file.png", self.file_input, _("Read file")) icon = ":icons/qrcode_white.png" if ColorScheme.dark_scheme else ":icons/qrcode.png" self.addButton(icon, self.qr_input, _("Read QR code")) run_hook('scan_text_edit', self)
def set_pin(self, remove): if remove: self.msg = _("Confirm on your {} device to disable PIN protection") elif self.features.pin_protection: self.msg = _("Confirm on your {} device to change your PIN") else: self.msg = _("Confirm on your {} device to set a PIN") self.change_pin(remove)
def __init__(self, seed=None, title=None, icon=True, msg=None, options=None, is_seed=None, passphrase=None, parent=None, for_seed_words=True): QVBoxLayout.__init__(self) self.parent = parent self.options = options if title: self.addWidget(WWLabel(title)) if seed: # "read only", we already have the text if for_seed_words: self.seed_e = ButtonsTextEdit() else: # e.g. xpub self.seed_e = ShowQRTextEdit() self.seed_e.setReadOnly(True) self.seed_e.setText(seed) else: # we expect user to enter text assert for_seed_words self.seed_e = CompletionTextEdit() self.seed_e.setTabChangesFocus(False) # so that tab auto-completes self.is_seed = is_seed self.saved_is_seed = self.is_seed self.seed_e.textChanged.connect(self.on_edit) self.initialize_completer() self.seed_e.setMaximumHeight(75) hbox = QHBoxLayout() if icon: logo = QLabel() logo.setPixmap(QPixmap(":icons/seed.png").scaledToWidth(64, mode=Qt.SmoothTransformation)) logo.setMaximumWidth(60) hbox.addWidget(logo) hbox.addWidget(self.seed_e) self.addLayout(hbox) hbox = QHBoxLayout() hbox.addStretch(1) self.seed_type_label = QLabel('') hbox.addWidget(self.seed_type_label) # options self.is_bip39 = False self.is_ext = False if options: opt_button = EnterButton(_('Options'), self.seed_options) hbox.addWidget(opt_button) self.addLayout(hbox) if passphrase: hbox = QHBoxLayout() passphrase_e = QLineEdit() passphrase_e.setText(passphrase) passphrase_e.setReadOnly(True) hbox.addWidget(QLabel(_("Your seed extension is") + ':')) hbox.addWidget(passphrase_e) self.addLayout(hbox) self.addStretch(1) self.seed_warning = WWLabel('') if msg: self.seed_warning.setText(seed_warning_msg(seed)) self.addWidget(self.seed_warning)
def __init__(self, parent, seed, passphrase): WindowModalDialog.__init__(self, parent, ('Electrum-XSH - ' + _('Seed'))) self.setMinimumWidth(400) vbox = QVBoxLayout(self) title = _("Your wallet generation seed is:") slayout = SeedLayout(title=title, seed=seed, msg=True, passphrase=passphrase) vbox.addLayout(slayout) run_hook('set_seed', seed, slayout.seed_e) vbox.addLayout(Buttons(CloseButton(self)))
def __init__(self, parent=None): MyTreeWidget.__init__(self, parent, self.create_menu, [ _('Address'), _('Label'), _('Amount'), _('Height'), _('Output point') ], 1) self.setSelectionMode(QAbstractItemView.ExtendedSelection) self.setSortingEnabled(True)
def wipe_device(): wallet = window.wallet if wallet and sum(wallet.get_balance()): title = _("Confirm Device Wipe") msg = _("Are you SURE you want to wipe the device?\n" "Your wallet still has SHIELD in it!") if not self.question( msg, title=title, icon=QMessageBox.Critical): return invoke_client('wipe_device', unpair_after=True)
def show_xpub_dialog(self, xpub, run_next): msg = ' '.join([ _("Here is your master public key."), _("Please share it with your cosigners.") ]) vbox = QVBoxLayout() layout = SeedLayout(xpub, title=msg, icon=False, for_seed_words=False) vbox.addLayout(layout.layout()) self.exec_layout(vbox, _('Master Public Key')) return None
def create_password_layout(self, wallet, is_encrypted, OK_button): if not is_encrypted: msg = _('Your wallet file is NOT encrypted.') else: msg = _('Your wallet file is encrypted.') msg += '\n' + _( 'Note: If you enable this setting, you will need your hardware device to open your wallet.' ) msg += '\n' + _('Use this dialog to toggle encryption.') self.playout = PasswordLayoutForHW(wallet, msg, PW_CHANGE, OK_button)
def export(self): name = 'signed_%s.txn' % ( self.tx.txid()[0:8]) if self.tx.is_complete() else 'unsigned.txn' fileName = self.main_window.getSaveFileName( _("Select where to save your signed transaction"), name, "*.txn") if fileName: with open(fileName, "w+") as f: f.write(json.dumps(self.tx.as_dict(), indent=4) + '\n') self.show_message(_("Transaction exported successfully")) self.saved = True
def __init__(self, parent): MyTreeWidget.__init__(self, parent, self.create_menu, [ _('Expires'), _('Requestor'), _('Description'), _('Amount'), _('Status') ], 2) self.setSortingEnabled(True) self.header().setSectionResizeMode(1, QHeaderView.Interactive) self.setColumnWidth(1, 200)
def send_report(self): try: response = BaseCrashReporter.send_report(self) except BaseException as e: traceback.print_exc(file=sys.stderr) self.main_window.show_critical( _('There was a problem with the automatic reporting:') + '\n' + str(e) + '\n' + _("Please report this issue manually.")) return QMessageBox.about(self, _("Crash report"), response.text) self.close()
def restore_seed_dialog(self, run_next, test): options = [] if self.opt_ext: options.append('ext') if self.opt_bip39: options.append('bip39') title = _('Enter Seed') message = _( 'Please enter your seed phrase in order to restore your wallet.\nAndroid wallet users should enable "Options > BIP39 seed" below.' ) return self.seed_input(title, message, test, options)
def confirm_seed_dialog(self, run_next, test): self.app.clipboard().clear() title = _('Confirm Seed') message = ' '.join([ _('Your seed is important!'), _('If you lose your seed, your money will be permanently lost.'), _('To make sure that you have properly saved your seed, please retype it here.' ) ]) seed, is_bip39, is_ext = self.seed_input(title, message, test, None) return seed
def closeEvent(self, event): if (self.prompt_if_unsaved and not self.saved and not self.question( _('This transaction is not saved. Close anyway?'), title=_("Warning"))): event.ignore() else: event.accept() try: dialogs.remove(self) except ValueError: pass # was not in list already
def send_report(self): try: response = BaseCrashReporter.send_report(self, "/crash.json").json() except requests.exceptions.RequestException: self.show_popup(_('Unable to send report'), _("Please check your network connection.")) else: self.show_popup(_('Report sent'), response["text"]) if response["location"]: self.open_url(response["location"]) self.dismiss()
def setup_device(self, device_info, wizard, purpose): devmgr = self.device_manager() device_id = device_info.device.id_ client = devmgr.client_by_id(device_id) if client is None: raise Exception( _('Failed to create a client for this device.') + '\n' + _('Make sure it is in the correct state.')) client.handler = self.create_handler(wizard) if purpose == HWD_SETUP_NEW_WALLET: client.setupRunning = True client.get_xpub("m/44'/2'", 'standard')