def _initialize_device(self, settings: TrezorInitSettings, method, device_id, wizard, handler): if method == TIM_RECOVER and settings.recovery_type == RECOVERY_TYPE_SCRAMBLED_WORDS: handler.show_error(_( "You will be asked to enter 24 words regardless of your " "seed's actual length. If you enter a word incorrectly or " "misspell it, you cannot change it or go back - you will need " "to start again from the beginning.\n\nSo please enter " "the words carefully!"), blocking=True) devmgr = self.device_manager() client = devmgr.client_by_id(device_id) if not client: raise Exception(_("The device was disconnected.")) if method == TIM_NEW: strength_from_word_count = {12: 128, 18: 192, 24: 256} client.reset_device( strength=strength_from_word_count[settings.word_count], passphrase_protection=settings.passphrase_enabled, pin_protection=settings.pin_enabled, label=settings.label, no_backup=settings.no_backup) elif method == TIM_RECOVER: client.recover_device( recovery_type=settings.recovery_type, word_count=settings.word_count, passphrase_protection=settings.passphrase_enabled, pin_protection=settings.pin_enabled, label=settings.label) if settings.recovery_type == RECOVERY_TYPE_MATRIX: handler.close_matrix_dialog() else: raise RuntimeError("Unsupported recovery method")
def _start_wizard_to_select_or_create_wallet( self, path) -> Optional[Abstract_Wallet]: wizard = InstallWizard(self.config, self.app, self.plugins) try: path, storage = wizard.select_storage(path, self.daemon.get_wallet) # storage is None if file does not exist if storage is None: wizard.path = path # needed by trustedcoin plugin wizard.run('new') storage = wizard.create_storage(path) else: wizard.run_upgrades(storage) except (UserCancelled, GoBack): return except WalletAlreadyOpenInMemory as e: return e.wallet except (WalletFileException, BitcoinException) as e: traceback.print_exc(file=sys.stderr) QMessageBox.warning(None, _('Error'), _('Cannot load wallet') + ' (2):\n' + str(e)) return finally: wizard.terminate() # return if wallet creation is not complete if storage is None or storage.get_action(): return wallet = Wallet(storage) wallet.start_network(self.daemon.network) self.daemon.add_wallet(wallet) return wallet
def __init__(self, parent): MyTreeWidget.__init__(self, parent, self.create_menu, [_('Date'), _('Address'), '', _('Description'), _('Amount'), _('Status')], 3) self.currentItemChanged.connect(self.item_changed) self.itemClicked.connect(self.item_changed) self.setSortingEnabled(True) self.setColumnWidth(0, 180) self.hideColumn(1)
def refresh_headers(self): headers = [_('Address'), _('Label'), _('Balance')] fx = self.parent.fx if fx and fx.get_fiat_address_config(): headers.extend([_(fx.get_currency() + ' Balance')]) headers.extend([_('Tx')]) self.update_headers(headers)
def export_psbt(self, dia): # Called from hook in transaction dialog tx = dia.tx if tx.is_complete(): # if they sign while dialog is open, it can transition from unsigned to signed, # which we don't support here, so do nothing return # can only expect Coldcard wallets to work with these files (right now) keystore = dia.wallet.get_keystore() assert type(keystore) == self.keystore_class # convert to PSBT raw_psbt = keystore.build_psbt(tx, wallet=dia.wallet) name = (dia.wallet.basename() + time.strftime('-%y%m%d-%H%M.psbt')).replace(' ', '-') fileName = dia.main_window.getSaveFileName( _("Select where to save the PSBT file"), name, "*.psbt") if fileName: with open(fileName, "wb+") as f: f.write(raw_psbt) dia.show_message(_("Transaction exported successfully")) dia.saved = True
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 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_prefix = 'custom_secret_' self.was = _('Custom secret') else: self.filename_prefix = self.wallet_name + '_seed_' self.was = self.wallet_name + ' ' + _('seed') if self.extension: self.ext_warning(self.c_dialog) if not calibration: self.toPdf(QImage(cypherseed)) QDesktopServices.openUrl( QUrl.fromLocalFile(self.get_path_to_revealer_file('.pdf'))) cypherseed.save(self.get_path_to_revealer_file('.png')) self.bcrypt(self.c_dialog) return cypherseed
def get_library_not_available_message(self) -> str: if hasattr(self, 'libraries_available_message'): message = self.libraries_available_message else: message = _("Missing libraries for {}.").format(self.name) message += '\n' + _("Make sure you install it with python3") return message
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 add_io(self, vbox): if self.tx.locktime > 0: vbox.addWidget(QLabel("LockTime: %d\n" % self.tx.locktime)) vbox.addWidget(QLabel(_("Inputs") + ' (%d)'%len(self.tx.inputs()))) ext = QTextCharFormat() rec = QTextCharFormat() rec.setBackground(QBrush(ColorScheme.GREEN.as_color(background=True))) rec.setToolTip(_("Wallet receive address")) chg = QTextCharFormat() chg.setBackground(QBrush(ColorScheme.YELLOW.as_color(background=True))) chg.setToolTip(_("Wallet change address")) def text_format(addr): if self.wallet.is_mine(addr): return chg if self.wallet.is_change(addr) else rec return ext def format_amount(amt): return self.main_window.format_amount(amt, whitespaces=True) i_text = QTextEdit() i_text.setFont(QFont(MONOSPACE_FONT)) i_text.setReadOnly(True) i_text.setMaximumHeight(100) cursor = i_text.textCursor() for x in self.tx.inputs(): if x['type'] == 'coinbase': cursor.insertText('coinbase') else: prevout_hash = x.get('prevout_hash') prevout_n = x.get('prevout_n') cursor.insertText(prevout_hash[0:8] + '...', ext) cursor.insertText(prevout_hash[-8:] + ":%-4d " % prevout_n, ext) addr = x.get('address') if addr == "(pubkey)": _addr = self.wallet.get_txin_address(x) if _addr: addr = _addr if addr is None: addr = _('unknown') cursor.insertText(addr, text_format(addr)) if x.get('value'): cursor.insertText(format_amount(x['value']), ext) cursor.insertBlock() vbox.addWidget(i_text) vbox.addWidget(QLabel(_("Outputs") + ' (%d)'%len(self.tx.outputs()))) o_text = QTextEdit() o_text.setFont(QFont(MONOSPACE_FONT)) o_text.setReadOnly(True) o_text.setMaximumHeight(100) cursor = o_text.textCursor() for addr, v in self.tx.get_outputs(): cursor.insertText(addr, text_format(addr)) if v is not None: cursor.insertText('\t', ext) cursor.insertText(format_amount(v), ext) cursor.insertBlock() vbox.addWidget(o_text)
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(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 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 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 __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 insert_utxo(self, idx, x): txid = x.get('prevout_hash') vout = x.get('prevout_n') name_op = self.wallet.db.transactions[txid].outputs()[vout].name_op if name_op is None: return # TODO: Support name_new if 'name' in name_op: name = name_op['name'] formatted_name = format_name_identifier(name) value = name_op['value'] formatted_value = format_name_value(value) else: name = None formatted_name = '' value = None formatted_value = '' height = x.get('height') chain_height = self.network.blockchain().height() expires_in = name_expires_in(height, chain_height) formatted_expires_in = '%d' % expires_in if expires_in is not None else '' status = '' if expires_in is not None else _('Update Pending') txout = txid + ":%d" % vout self.utxo_dict[txout] = x labels = [ formatted_name, formatted_value, formatted_expires_in, status ] utxo_item = [QStandardItem(x) for x in labels] self.set_editability(utxo_item) utxo_item[self.Columns.NAME].setFont(QFont(MONOSPACE_FONT)) utxo_item[self.Columns.VALUE].setFont(QFont(MONOSPACE_FONT)) utxo_item[self.Columns.NAME].setData(txout, Qt.UserRole) utxo_item[self.Columns.NAME].setData(name, Qt.UserRole + USER_ROLE_NAME) utxo_item[self.Columns.NAME].setData(value, Qt.UserRole + USER_ROLE_VALUE) address = x.get('address') if self.wallet.is_frozen_address( address) or self.wallet.is_frozen_coin(x): utxo_item[self.Columns.NAME].setBackground( ColorScheme.BLUE.as_color(True)) if self.wallet.is_frozen_address( address) and self.wallet.is_frozen_coin(x): utxo_item[self.Columns.NAME].setToolTip( _('Address and coin are frozen')) elif self.wallet.is_frozen_address(address): utxo_item[self.Columns.NAME].setToolTip(_('Address is frozen')) elif self.wallet.is_frozen_coin(x): utxo_item[self.Columns.NAME].setToolTip(_('Coin is frozen')) self.model().appendRow(utxo_item)
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 toggle_passphrase(self): if self.features.passphrase_protection: msg = _("Confirm on your {} device to disable passphrases") else: msg = _("Confirm on your {} device to enable passphrases") enabled = not self.features.passphrase_protection with self.run_flow(msg): trezorlib.device.apply_settings(self.client, use_passphrase=enabled)
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 __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 on_error(exc_info): e = exc_info[1] window.show_error("{header}\n{exc}\n\n{tor}".format( header=_('Error getting TrustedCoin account info.'), exc=str(e), tor= _('If you keep experiencing network problems, try using a Tor proxy.' )))
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 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 UserFacingException(_('Failed to create a client for this device.') + '\n' + _('Make sure it is in the correct state.')) client.handler = self.create_handler(wizard)
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 set_pin(self, remove): if remove: msg = _("Confirm on your {} device to disable PIN protection") elif self.features.pin_protection: msg = _("Confirm on your {} device to change your PIN") else: msg = _("Confirm on your {} device to set a PIN") with self.run_flow(msg): trezorlib.device.change_pin(self.client, remove)
def __init__(self, parent=None): MyTreeWidget.__init__(self, parent, self.create_menu, [ _('Address'), _('Label'), _('Amount'), _('Height'), _('Output point') ], 1) self.setSelectionMode(QAbstractItemView.ExtendedSelection)
def __init__(self, identifier, value, parent, is_new): # We want to be a top-level window QDialog.__init__(self, parent=None) self.main_window = parent self.setMinimumWidth(545) self.setMinimumHeight(245) if is_new: self.setWindowTitle(_("Configure New Name")) else: self.setWindowTitle(_("Reconfigure Name")) form_layout = QFormLayout() self.identifier = identifier formatted_name = format_name_identifier(identifier) form_layout.addRow(QLabel(formatted_name)) self.dataEdit = QLineEdit() # TODO: support non-ASCII encodings self.dataEdit.setText(value.decode('ascii')) form_layout.addRow(_("Data:"), self.dataEdit) self.transferTo = PayToEdit(self.main_window) form_layout.addRow(_("Transfer to:"), self.transferTo) form = QWidget() form.setLayout(form_layout) self.buttons_box = QDialogButtonBox() self.buttons_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) buttons_hbox = QHBoxLayout() buttons_hbox.addStretch() buttons_hbox.addWidget(self.buttons_box) buttons = QWidget() buttons.setLayout(buttons_hbox) vbox = QVBoxLayout() vbox.addWidget(form) vbox.addWidget(buttons) self.setLayout(vbox) self.buttons_box.accepted.connect(self.accept) self.buttons_box.rejected.connect(self.reject) if is_new: self.accepted.connect(lambda: self.register_and_broadcast( self.identifier, self.dataEdit.text().encode('ascii'), self.transferTo)) else: # TODO: handle non-ASCII encodings self.accepted.connect(lambda: self.update_and_broadcast( self.identifier, self.dataEdit.text().encode('ascii'), self.transferTo))
def on_update(self): self.wallet = self.parent.wallet item = self.currentItem() current_address = item.data(0, Qt.UserRole) if item else None if self.show_change == 1: addr_list = self.wallet.get_receiving_addresses() elif self.show_change == 2: addr_list = self.wallet.get_change_addresses() else: addr_list = self.wallet.get_addresses() self.clear() for address in addr_list: num = len(self.wallet.get_address_history(address)) is_used = self.wallet.is_used(address) label = self.wallet.labels.get(address, '') c, u, x = self.wallet.get_addr_balance(address) balance = c + u + x if self.show_used == 1 and (balance or is_used): continue if self.show_used == 2 and balance == 0: continue if self.show_used == 3 and not is_used: continue balance_text = self.parent.format_amount(balance, whitespaces=True) fx = self.parent.fx if fx and fx.get_fiat_address_config(): rate = fx.exchange_rate() fiat_balance = fx.value_str(balance, rate) address_item = SortableTreeWidgetItem([ '', address, label, balance_text, fiat_balance, "%d" % num ]) address_item.setTextAlignment(4, Qt.AlignRight) address_item.setFont(4, QFont(MONOSPACE_FONT)) else: address_item = SortableTreeWidgetItem( ['', address, label, balance_text, "%d" % num]) address_item.setFont(3, QFont(MONOSPACE_FONT)) if self.wallet.is_change(address): address_item.setText(0, _('change')) address_item.setBackground(0, ColorScheme.YELLOW.as_color(True)) else: address_item.setText(0, _('receiving')) address_item.setBackground(0, ColorScheme.GREEN.as_color(True)) address_item.setFont(1, QFont(MONOSPACE_FONT)) address_item.setData( 0, Qt.UserRole, address) # column 0; independent from address column if self.wallet.is_frozen(address): address_item.setBackground(1, ColorScheme.BLUE.as_color(True)) if self.wallet.is_beyond_limit(address): address_item.setBackground(1, ColorScheme.RED.as_color(True)) self.addChild(address_item) if address == current_address: self.setCurrentItem(address_item)
def ext_warning(self, dialog): dialog.show_message(''.join([ "<b>", _("Warning"), ": </b>", _("your seed extension will <b>not</b> be included in the encrypted backup." ) ]), rich_text=True) dialog.close()