def handle_chunk_tx(self, tx, chunk_index): try: data = parseOpreturnToChunks(tx.outputs()[0][1].to_script(), allow_op_0=False, allow_op_number=False) except Exception as e: raise e return self.fail_metadata_info( _("This chunk does not contain any data")) if len(data) != 1: return self.fail_metadata_info( _("This chunk does not contain any data")) self.progress.setValue(self.progress.value() + 1) self.progress.setVisible(True) self.txn_downloads[chunk_index]['data'] = data[0] if chunk_index < self.chunk_count - 1: self.txn_downloads.append({ 'txid': tx.inputs()[0]['prevout_hash'], 'data': None }) assert tx.inputs()[0]['prevout_n'] == 1 index = len(self.txn_downloads) - 1 self.download_chunk_data(self.txn_downloads[index]['txid'], index) else: self.build_file()
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): 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 __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 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: 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 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 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) # Trigger a pairing keystore.thread.add(partial(self.get_client, keystore))
def __init__(self, seed=None, title=None, icon=True, msg=None, options=None, is_seed=None, passphrase=None, parent=None): QVBoxLayout.__init__(self) self.parent = parent self.options = options self.is_bip39 = True # Hard-coded for SLP self.is_bip39_145 = False # Hard-coded for SLP self.is_seed = is_seed = lambda x: bool(x) # Hard-coded for SLP if title: self.addWidget(WWLabel(title)) self.seed_e = CompletionTextEdit() if seed: self.seed_e.setText(seed) else: self.seed_e.setTabChangesFocus(True) 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, 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) 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 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: 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, 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 warn_if_no_network(self, parent): if not self.daemon.network: self.warning(message=_( 'You are using Electrum-ZSLP in offline mode; restart Electrum-ZSLP if you want to get connected' ), title=_('Offline'), parent=parent) return True return False
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 __init__(self, main_window, exctype, value, tb): self.exc_args = (exctype, value, tb) self.main_window = main_window QWidget.__init__(self) self.setWindowTitle('Electrum-Zclassic - ' + _('An Error Occurred')) self.setMinimumSize(600, 300) main_box = QVBoxLayout() heading = QLabel('<h2>' + _('Sorry!') + '</h2>') main_box.addWidget(heading) main_box.addWidget( QLabel( _('Something went wrong while executing Electrum-Zclassic.'))) main_box.addWidget( QLabel( _('To help us diagnose and fix the problem, you can send us a bug report that contains useful debug ' 'information:'))) collapse_info = QPushButton(_("Show report contents")) collapse_info.clicked.connect( lambda: self.msg_box(QMessageBox.NoIcon, self, "Report contents", self.get_report_string())) main_box.addWidget(collapse_info) main_box.addWidget( QLabel( _("Please briefly describe what led to the error (optional):")) ) self.description_textfield = QTextEdit() self.description_textfield.setFixedHeight(50) main_box.addWidget(self.description_textfield) main_box.addWidget(QLabel(_("Do you want to send this report?"))) buttons = QHBoxLayout() report_button = QPushButton(_('Send Bug Report')) report_button.clicked.connect(self.send_report) report_button.setIcon(QIcon(":icons/tab_send.png")) buttons.addWidget(report_button) never_button = QPushButton(_('Never')) never_button.clicked.connect(self.show_never) buttons.addWidget(never_button) close_button = QPushButton(_('Not Now')) close_button.clicked.connect(self.close) buttons.addWidget(close_button) main_box.addLayout(buttons) self.setLayout(main_box) self.show()
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 Zclassic coins in it!") if not self.question(msg, title=title, icon=QMessageBox.Critical): return invoke_client('wipe_device', unpair_after=True)
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 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 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 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 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) vbox.addLayout(layout.layout()) self.exec_layout(vbox, _('Master Public Key')) return None
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 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 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]) for i in range(6): if i > 2: address_item.setTextAlignment(i, Qt.AlignRight) address_item.setFont(i, QFont(MONOSPACE_FONT)) else: address_item = SortableTreeWidgetItem(['', address, label, balance_text, "%d"%num]) for i in range(5): if i > 2: address_item.setTextAlignment(i, Qt.AlignRight) address_item.setFont(i, 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 plot_history_dialog(self): if plot_history is None: self.parent.show_message( _("Can't plot history.") + '\n' + _("Perhaps some dependencies are missing...") + " (matplotlib?)") return try: plt = plot_history(self.transactions) plt.show() except NothingToPlotException as e: self.parent.show_message(str(e))
def __init__(self, parent, seed, passphrase): WindowModalDialog.__init__(self, parent, ('Electrum ZSLP - ' + _('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) vbox.addLayout(Buttons(CloseButton(self)))
def dbb_erase(self): self.handler.show_message( _("Are you sure you want to erase the Digital Bitbox?") + "\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.")) hid_reply = self.hid_send_encrypt(b'{"reset":"__ERASE__"}') self.handler.finished() if 'error' in hid_reply: raise Exception(hid_reply['error']['message']) else: self.password = None raise Exception('Device erased')
def create_menu(self, position): menu = QMenu() selected = self.selectedItems() if len(selected) == 1: keys = [item.text(0) for item in selected] if self.parent.wallet.token_types[keys[0]]['decimals'] == "?": menu.addAction( _("Add this token"), lambda: SlpAddTokenDialog(self.parent, token_id_hex=keys[0], allow_overwrite=True)) menu.addAction(_("Remove this token"), lambda: self.parent.delete_slp_token(keys)) else: if self.parent.wallet.token_types[ keys[0]]['class'] == 'SLP129': menu.addAction( _("Create new NFT"), lambda: SlpCreateTokenGenesisDialog( self.parent, nft_parent_id=keys[0])) menu.addSeparator() try: self.parent.wallet.get_slp_token_baton(keys[0]) menu.addAction( _("Mint Tool"), lambda: SlpCreateTokenMintDialog(self.parent, keys[0])) except SlpNoMintingBatonFound: pass column = self.currentColumn() column_title = self.headerItem().text(column) column_data = '\n'.join( [item.text(column) for item in selected]) menu.addAction( _("Copy {}").format(column_title), lambda: self.parent.app.clipboard().setText(column_data)) menu.addAction(_("Remove this token"), lambda: self.parent.delete_slp_token(keys)) if self.currentItem(): menu.addAction(_("View Token Details"), lambda: self.onViewTokenDetails()) menu.addSeparator() menu.addAction(_("Burn Tool"), lambda: self.onBurnDialog()) menu.addSeparator() menu.addAction(_("Add existing token"), lambda: SlpAddTokenDialog(self.parent, )) menu.addAction(_("Create a new token"), lambda: SlpCreateTokenGenesisDialog(self.parent, )) run_hook('create_contact_menu', menu, selected) menu.exec_(self.viewport().mapToGlobal(position))
def create_menu(self, position): menu = QMenu() selected = self.selectedItems() if not selected: menu.addAction(_("New contact"), lambda: self.parent.new_contact_dialog()) menu.addAction(_("Import file"), lambda: self.import_contacts()) menu.addAction(_("Export file"), lambda: self.export_contacts()) else: names = [item.text(0) for item in selected] keys = [item.text(1) for item in selected] column = self.currentColumn() column_title = self.headerItem().text(column) column_data = '\n'.join([item.text(column) for item in selected]) menu.addAction(_("Copy {}").format(column_title), lambda: self.parent.app.clipboard().setText(column_data)) if column in self.editable_columns: item = self.currentItem() menu.addAction(_("Edit {}").format(column_title), lambda: self.editItem(item, column)) menu.addAction(_("Pay to"), lambda: self.parent.payto_contacts(keys)) menu.addAction(_("Delete"), lambda: self.parent.delete_contacts(keys)) URLs = [block_explorer_URL(self.config, 'addr', Address.from_string(key)) for key in keys if Address.is_valid(key)] if URLs: menu.addAction(_("View on block explorer"), lambda: [webbrowser.open(URL) for URL in URLs]) run_hook('create_contact_menu', menu, selected) menu.exec_(self.viewport().mapToGlobal(position))