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")) twofactor = QTextCharFormat() twofactor.setBackground(QBrush(ColorScheme.BLUE.as_color(background=True))) twofactor.setToolTip(_("TrustedCoin (2FA) fee for the next batch of transactions")) def text_format(addr): if self.wallet.is_mine(addr): return chg if self.wallet.is_change(addr) else rec elif self.wallet.is_billing_address(addr): return twofactor 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 + ":%-4d " % prevout_n, ext) addr = self.wallet.get_txin_address(x) if addr is None: addr = '' 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 __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 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 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 __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 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 self.has_extension: self.ext_warning(self.c_dialog) 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 is_noise(self, txt): if (len(txt) >= 34): try: int(txt, 16) except: self.user_input = False return False else: id = self.code_hashid(txt[:-3]) if (txt[-3:].upper() == id.upper()): self.code_id = id self.user_input = True return True else: return False else: if (len(txt) > 0 and txt[0] == '0'): self.d.show_message(''.join([ "<b>", _("Warning: "), "</b>", _("Revealers starting with 0 had a vulnerability and are not supported." ) ])) self.user_input = False return False
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 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 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 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 ext_warning(self, dialog): dialog.show_message(''.join([ "<b>", _("Warning: "), "</b>", _("your seed extension will not be included in the encrypted backup." ) ])) dialog.close()
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 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 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) client.get_xpub("m/44'/2'", 'standard') # TODO replace by direct derivation once Nano S > 1.1
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)
def show_qr(self): text = bfh(str(self.tx)) text = base_encode(text, base=43) try: self.main_window.show_qrcode(text, 'Transaction', parent=self) except qrcode.exceptions.DataOverflowError: self.show_error(_('Failed to display QR code.') + '\n' + _('Transaction is too large in size.')) except Exception as e: self.show_error(_('Failed to display QR code.') + '\n' + str(e))
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 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.') return self.seed_input(title, message, test, options)
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_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_toolbar_buttons(self): self.period_combo = QComboBox() self.start_button = QPushButton('-') self.start_button.pressed.connect(self.select_start_date) self.start_button.setEnabled(False) self.end_button = QPushButton('-') self.end_button.pressed.connect(self.select_end_date) self.end_button.setEnabled(False) self.period_combo.addItems([_('All'), _('Custom')]) self.period_combo.activated.connect(self.on_combo)
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 bitcoreds in it!") if not self.question(msg, title=title, icon=QMessageBox.Critical): return invoke_client('wipe_device', unpair_after=True)
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 populate_modes(self): self.modes.blockSignals(True) self.modes.clear() self.modes.addItem(_("Summary Text PIN (requires dongle replugging)") if self.txdata['confirmationType'] == 1 else _("Summary Text PIN is Disabled")) if self.txdata['confirmationType'] > 1: self.modes.addItem(_("Security Card Challenge")) if not self.cfg['pair']: self.modes.addItem(_("Mobile - Not paired")) else: self.modes.addItem(_("Mobile - {}").format(self.cfg['pair'][1])) self.modes.blockSignals(False)
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 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 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')