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 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 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 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 __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 __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 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." ) ]), rich_text=True) self.user_input = False return False
def save_current_masternode(self, as_new=False): """Save the masternode that is being viewed. If as_new is True, a new masternode will be created. """ delegate_privkey = str(self.masternode_editor.delegate_key_edit.text()) if not delegate_privkey: QMessageBox.warning(self, _('Warning'), _('Delegate private key is empty.')) return try: delegate_pubkey = self.manager.import_masternode_delegate( delegate_privkey) except Exception: # Show an error if the private key is invalid and not an empty string. if delegate_privkey: QMessageBox.warning( self, _('Warning'), _('Ignoring invalid delegate private key.')) delegate_pubkey = '' alias = str(self.masternode_editor.alias_edit.text()) # Construct a new masternode. if as_new: kwargs = self.masternode_editor.get_masternode_args() kwargs['delegate_key'] = delegate_pubkey del kwargs['vin'] self.mapper.revert() self.masternodes_widget.add_masternode( MasternodeAnnounce(**kwargs)) else: self.mapper.submit() self.manager.save() self.masternodes_widget.select_masternode(alias)
def sign_announce(self, alias): """Sign an announce for alias. This is called by SignAnnounceWidget.""" pw = None if self.manager.wallet.has_password(): pw = self.gui.password_dialog(msg=_( 'Please enter your password to activate masternode "%s".' % alias)) if pw is None: return self.sign_announce_widget.sign_button.setEnabled(False) def sign_thread(): return self.manager.sign_announce(alias, pw) def on_sign_successful(mn): self.print_msg('Successfully signed Masternode Announce.') self.send_announce(alias) # Proceed to broadcasting the announcement, or re-enable the button. def on_sign_error(err): self.print_error('Error signing MasternodeAnnounce:') # Print traceback information to error log. self.print_error(''.join(traceback.format_tb(err[2]))) self.print_error(''.join( traceback.format_exception_only(err[0], err[1]))) self.sign_announce_widget.sign_button.setEnabled(True) util.WaitingDialog(self, _('Signing Masternode Announce...'), sign_thread, on_sign_successful, on_sign_error)
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 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 create_proposal(self): manager = self.parent.masternode_manager try: proposal = self.create_proposal_from_widgets() except Exception as e: return QMessageBox.critical(self, _('Error'), _(str(e))) pw = None if manager.wallet.has_password(): pw = self.parent.password_dialog(msg=_( 'Please enter your password to create a budget proposal.')) if pw is None: return manager.add_proposal(proposal) def sign_done(proposal, tx): print_error('proposal tx sign done: %s' % proposal.proposal_name) if tx: label = _('Budget Proposal Tx: ') + proposal.proposal_name self.parent.broadcast_transaction(tx, label) self.parent.masternode_manager.save() self.create_proposal_tx(proposal, pw, sign_done)
def update(self, proposals, main_window): item = self.currentItem() current_proposal = item.data(ProposalsModel.TXID, Qt.UserRole).toString() if item else None self.model.set_proposals(proposals) self.clear() row_count = self.model.rowCount() if row_count < 1: return for r in range(row_count): get_data = lambda col, row=r: self.model.data( self.model.index(row, col)) name = _(str(get_data(ProposalsModel.NAME).toString())) url = _(str(get_data(ProposalsModel.URL).toString())) yes_count = str(get_data(ProposalsModel.YES_COUNT).toString()) no_count = str(get_data(ProposalsModel.NO_COUNT).toString()) start_block = str(get_data(ProposalsModel.START_BLOCK).toString()) end_block = str(get_data(ProposalsModel.END_BLOCK).toString()) amount = str(get_data(ProposalsModel.AMOUNT).toString()) address = str(get_data(ProposalsModel.ADDRESS).toString()) txid = str(get_data(ProposalsModel.TXID).toString()) display_txid = '%s...%s' % (txid[0:8], txid[-8:]) item = QTreeWidgetItem([ name, url, yes_count, no_count, start_block, end_block, amount, address, display_txid ]) item.setFont(ProposalsModel.START_BLOCK, QFont(util.MONOSPACE_FONT)) item.setFont(ProposalsModel.END_BLOCK, QFont(util.MONOSPACE_FONT)) item.setFont(ProposalsModel.ADDRESS, QFont(util.MONOSPACE_FONT)) item.setFont(ProposalsModel.TXID, QFont(util.MONOSPACE_FONT)) if name: item.setData(ProposalsModel.NAME, Qt.UserRole, name) if txid: item.setData(ProposalsModel.TXID, Qt.UserRole, txid) is_my_proposal = False if main_window.masternode_manager.get_proposal(name) is not None: is_my_proposal = True if is_my_proposal: item.setBackground(ProposalsModel.NAME, QBrush(QColor(MY_PROPOSAL_COLOR))) item.setToolTip(ProposalsModel.NAME, _('You created this proposal.')) is_my_address = main_window.wallet.is_mine(address) if is_my_address: item.setBackground(ProposalsModel.ADDRESS, QBrush(QColor(MY_ADDRESS_COLOR))) item.setToolTip(ProposalsModel.ADDRESS, _('You own this address.')) self.addTopLevelItem(item) if current_proposal == name: self.setCurrentItem(item)
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.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 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 on_vote_successful(result): errmsg, res = result if res: QMessageBox.information(self, _('Success'), _('Successfully voted')) else: QMessageBox.critical(self, _('Error Voting'), _(errmsg)) self.proposals_widget.editor.vote_button.setEnabled(True)
def ext_warning(self, dialog): dialog.show_message(''.join([ "<b>", _("Warning: "), "</b>", _("your seed extension will not be included in the encrypted backup." ) ]), rich_text=True) dialog.close()
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'/5'", 'standard') # TODO replace by direct derivation once Nano S > 1.1
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() fx = self.parent.fx for address in addr_list: num = self.wallet.get_address_history_len(address) label = self.wallet.labels.get(address, '') c, u, x = self.wallet.get_addr_balance(address) balance = c + u + x is_used_and_empty = self.wallet.is_used(address) and balance == 0 if self.show_used == 1 and (balance or is_used_and_empty): continue if self.show_used == 2 and balance == 0: continue if self.show_used == 3 and not is_used_and_empty: continue balance_text = self.parent.format_amount(balance, whitespaces=True) # create item 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]) else: address_item = SortableTreeWidgetItem(['', address, label, balance_text, "%d"%num]) # align text and set fonts for i in range(address_item.columnCount()): address_item.setTextAlignment(i, Qt.AlignVCenter) if i not in (0, 2): address_item.setFont(i, QFont(MONOSPACE_FONT)) if fx and fx.get_fiat_address_config(): address_item.setTextAlignment(4, Qt.AlignRight | Qt.AlignVCenter) # setup column 0 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.setData(0, Qt.UserRole, address) # column 0; independent from address column # setup column 1 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)) # add item self.addChild(address_item) if address == current_address: self.setCurrentItem(address_item)
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 __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 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 delete_current_masternode(self): """Delete the masternode that is being viewed.""" mn = self.selected_masternode() if QMessageBox.question( self, _('Delete'), _('Do you want to remove the masternode configuration for') + ' %s?' % mn.alias, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.Yes: self.masternodes_widget.remove_masternode(mn.alias) self.masternodes_widget.view.selectRow(0)
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 Cadex coins in it!") if not self.question( msg, title=title, icon=QMessageBox.Critical): return invoke_client('wipe_device', unpair_after=True)
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 __init__(self, parent=None): super(ProposalsTreeWidget, self).__init__(parent, self.create_menu, [ _('Name'), _('URL'), _('Yes Votes'), _('No Votes'), _('Start Block'), _('End Block'), _('Amount'), _('Address'), _('Fee Tx') ], 0) header = self.header() header.setResizeMode(ProposalsModel.NAME, QHeaderView.ResizeToContents) header.setResizeMode(ProposalsModel.URL, QHeaderView.Stretch) header.setResizeMode(ProposalsModel.YES_COUNT, QHeaderView.ResizeToContents) header.setResizeMode(ProposalsModel.NO_COUNT, QHeaderView.ResizeToContents) header.setResizeMode(ProposalsModel.ADDRESS, QHeaderView.ResizeToContents) header.setResizeMode(ProposalsModel.TXID, QHeaderView.ResizeToContents) self.model = ProposalsModel()
def __init__(self, parent=None): super(ProposalsModel, self).__init__(parent) self.proposals = [] headers = [ { Qt.DisplayRole: _('Name'), }, { Qt.DisplayRole: _('URL'), }, { Qt.DisplayRole: _('Yes Votes'), }, { Qt.DisplayRole: _('No Votes'), }, { Qt.DisplayRole: _('Start Block'), }, { Qt.DisplayRole: _('End Block'), }, { Qt.DisplayRole: _('Amount'), }, { Qt.DisplayRole: _('Address'), }, { Qt.DisplayRole: _('Fee Tx'), }, ] for d in headers: d[Qt.EditRole] = d[Qt.DisplayRole] self.headers = headers
def __init__(self, parent=None): super(MasternodeEditor, self).__init__(parent) self.alias_edit = QLineEdit() self.alias_edit.setPlaceholderText( _('Enter a name for this masternode')) self.vin_edit = PrevOutWidget() self.addr_edit = NetworkAddressWidget() self.delegate_key_edit = QLineEdit() self.delegate_key_edit.setFont(QFont(util.MONOSPACE_FONT)) self.delegate_key_edit.setPlaceholderText( _('Your masternode\'s private key')) self.protocol_version_edit = QLineEdit() self.protocol_version_edit.setText('70201') self.status_edit = QLineEdit() self.status_edit.setPlaceholderText(_('Masternode status')) self.status_edit.setReadOnly(True) form = QFormLayout() form.addRow(_('Alias:'), self.alias_edit) form.addRow(_('Status:'), self.status_edit) form.addRow(_('Collateral KDX Output:'), self.vin_edit) form.addRow(_('Masternode Private Key:'), self.delegate_key_edit) form.addRow(_('Address:'), self.addr_edit) form.addRow(_('Protocol Version:'), self.protocol_version_edit) self.setLayout(form)
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 + ":%-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)