def update_and_broadcast(self, identifier, value, transfer_to): if transfer_to.toPlainText() == "": # User left the recipient blank, so this isn't a transfer. recipient_address = None else: # The user entered something into the recipient text box. recipient = transfer_to.get_recipient() if recipient is None: recipient_type, recipient_address = None, transfer_to.toPlainText( ) else: recipient_type, recipient_address = recipient if recipient_type != TYPE_ADDRESS: self.main_window.show_error( _("Invalid address ") + recipient_address) return name_update = self.main_window.console.namespace.get('name_update') broadcast = self.main_window.console.namespace.get('broadcast') try: # TODO: support non-ASCII encodings tx = name_update(identifier.decode('ascii'), value.decode('ascii'), destination=recipient_address, wallet=self.wallet) except (NotEnoughFunds, NoDynamicFeeEstimates) as e: formatted_name = format_name_identifier(identifier) self.main_window.show_message( _("Error creating update for ") + formatted_name + ": " + str(e)) return except InternalAddressCorruption as e: formatted_name = format_name_identifier(identifier) self.main_window.show_error( _("Error creating update for ") + formatted_name + ": " + str(e)) raise except BaseException as e: traceback.print_exc(file=sys.stdout) formatted_name = format_name_identifier(identifier) self.main_window.show_message( _("Error creating update for ") + formatted_name + ": " + str(e)) return try: broadcast(tx) except Exception as e: formatted_name = format_name_identifier(identifier) self.main_window.show_error( _("Error broadcasting update for ") + formatted_name + ": " + str(e)) return
def register_and_broadcast(self, identifier, value, transfer_to): if transfer_to.toPlainText() == "": # User left the recipient blank, so this isn't a transfer. recipient_address = None else: # The user entered something into the recipient text box. recipient = transfer_to.get_recipient() if recipient is None: recipient_type, recipient_address = None, transfer_to.toPlainText( ) else: recipient_type, recipient_address = recipient if recipient_type != TYPE_ADDRESS: self.main_window.show_error( _("Invalid address ") + recipient_address) return name_autoregister = self.main_window.console.namespace.get( 'name_autoregister') try: # TODO: support non-ASCII encodings name_autoregister(identifier.decode('ascii'), value.decode('ascii'), destination=recipient_address, wallet=self.wallet) except NameAlreadyExistsError as e: formatted_name = format_name_identifier(identifier) self.main_window.show_message( _("Error registering ") + formatted_name + ": " + str(e)) return except (NotEnoughFunds, NoDynamicFeeEstimates) as e: formatted_name = format_name_identifier(identifier) self.main_window.show_message( _("Error registering ") + formatted_name + ": " + str(e)) return except InternalAddressCorruption as e: formatted_name = format_name_identifier(identifier) self.main_window.show_error( _("Error registering ") + formatted_name + ": " + str(e)) raise except TxBroadcastError as e: msg = e.get_message_for_gui() self.main_window.show_error(msg) except BestEffortRequestFailed as e: msg = repr(e) self.main_window.show_error(msg) except BaseException as e: traceback.print_exc(file=sys.stdout) formatted_name = format_name_identifier(identifier) self.main_window.show_message( _("Error registering ") + formatted_name + ": " + str(e)) return
def renew_selected_items(self): selected = self.selected_in_column(0) if not selected: return name_update = self.parent.console.namespace.get('name_update') broadcast = self.parent.console.namespace.get('broadcast') addtransaction = self.parent.console.namespace.get('addtransaction') for item in selected: identifier = item.data(Qt.UserRole + USER_ROLE_NAME) try: # TODO: support non-ASCII encodings tx = name_update(identifier.decode('ascii'), wallet=self.wallet) except NameUpdatedTooRecentlyError: # The name was recently updated, so skip it and don't renew. continue except (NotEnoughFunds, NoDynamicFeeEstimates) as e: self.parent.show_message(str(e)) return except InternalAddressCorruption as e: self.parent.show_error(str(e)) raise except BaseException as e: traceback.print_exc(file=sys.stdout) self.parent.show_message(str(e)) return try: broadcast(tx) except Exception as e: formatted_name = format_name_identifier(identifier) self.parent.show_error( _("Error broadcasting renewal for ") + formatted_name + ": " + str(e)) continue # We add the transaction to the wallet explicitly because # otherwise, the wallet will only learn that the transaction's # inputs are spent once the ElectrumX server sends us a copy of the # transaction, which is several seconds later, which will cause us # to double-spend those inputs in subsequent renewals during this # loop. status = addtransaction(tx) if not status: formatted_name = format_name_identifier(identifier) self.parent.show_error( _("Error adding renewal for ") + formatted_name + _(" to wallet")) continue
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 insert_utxo(self, idx, utxo: PartialTxInput): txid = utxo.prevout.txid.hex() vout = utxo.prevout.out_idx name_op = utxo.name_op if name_op is None: return height = utxo.block_height header_at_tip = self.network.blockchain().header_at_tip() if height is None or height <= 0: # TODO: Namecoin: Take into account the fact that transactions may # not be mined in the next block. blocks_until_mined = 1 height_estimated = header_at_tip[ 'block_height'] + blocks_until_mined else: height_estimated = height if 'name' not in name_op: # Upstream handles a name_new here, which doesn't exist in Xaya. assert False else: if height is not None and height > 0: # utxo is confirmed status = '' else: # utxo is name_update status = _('Update Pending') if 'name' in name_op: # utxo is name_anyupdate or a name_new that we've queued a name_firstupdate for name = name_op['name'] formatted_name = format_name_identifier(name) value = name_op['value'] formatted_value = format_name_value(value) else: # utxo is a name_new that we haven't queued a name_firstupdate for name = None formatted_name = '' value = None formatted_value = '' txout = txid + ":%d" % vout self._utxo_dict[txout] = utxo labels = [formatted_name, formatted_value, 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 = utxo.address if self.wallet.is_frozen_address( address) or self.wallet.is_frozen_coin(utxo): utxo_item[self.Columns.NAME].setBackground( ColorScheme.BLUE.as_color(True)) if self.wallet.is_frozen_address( address) and self.wallet.is_frozen_coin(utxo): 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(utxo): utxo_item[self.Columns.NAME].setToolTip(_('Coin is frozen')) self.model().appendRow(utxo_item)
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.wallet = self.main_window.wallet 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() self.set_value(value) self.namespace = identifier_to_namespace(identifier) self.namespace_is_dns = self.namespace in ["d", "dd"] if self.namespace_is_dns: self.dnsButton = QPushButton(_('DNS Editor...')) self.dnsButton.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.dnsButton.setMinimumSize(150, 0) # TODO: tooltip? self.dnsButton.clicked.connect(lambda: show_configure_dns( self.dataEdit.text().encode('ascii'), self)) data_layout = QHBoxLayout() data_layout.setContentsMargins(0, 0, 0, 0) data_layout.addWidget(self.dataEdit) if self.namespace_is_dns: data_layout.addWidget(self.dnsButton) self.data = QWidget() self.data.setLayout(data_layout) form_layout.addRow(_("Data:"), self.data) 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 insert_utxo(self, idx, utxo: PartialTxInput): txid = utxo.prevout.txid.hex() vout = utxo.prevout.out_idx name_op = utxo.name_op if name_op is None: return height = utxo.block_height header_at_tip = self.network.blockchain().header_at_tip() if height is None or height <= 0: # TODO: Doichain: Take into account the fact that transactions may # not be mined in the next block. blocks_until_mined = 1 height_estimated = header_at_tip[ 'block_height'] + blocks_until_mined else: height_estimated = height if 'name' not in name_op: # utxo is name_new queue_item, firstupdate_output = get_queued_firstupdate_from_new( self.wallet, txid, vout) if firstupdate_output is not None: if firstupdate_output.name_op is not None: name_op = firstupdate_output.name_op expires_in, expires_datetime = None, None if height is not None and header_at_tip is not None and queue_item is not None: sendwhen_depth = queue_item["sendWhen"]["confirmations"] blocks_until_firstupdate_sent = blocks_remaining_until_confirmations( height_estimated, header_at_tip['block_height'], sendwhen_depth) # TODO: Doichain: Take into account the fact that transactions # may not be mined in the next block. blocks_until_firstupdate_confirmed = blocks_until_firstupdate_sent + 1 minutes_remaining_until_firstupdate_confirmed = 10 * blocks_until_firstupdate_confirmed status = _('Registration Pending, ETA ') + str( minutes_remaining_until_firstupdate_confirmed) + _("min") else: status = _('Registration Pending') else: # utxo is name_anyupdate if header_at_tip is not None: expires_in, expires_datetime = name_expiration_datetime_estimate( height_estimated, header_at_tip['block_height'], header_at_tip['timestamp']) else: expires_in, expires_datetime = None, None if height is not None and height > 0: # utxo is confirmed status = '' else: # utxo is unconfirmed if name_op['op'] == OP_NAME_UPDATE: # utxo is name_update status = _('Update Pending') else: # utxo is name_firstupdate # TODO: Doichain: Take into account the fact that # transactions may not be mined in the next block. status = _('Registration Pending, ETA 10min') if 'name' in name_op: # utxo is name_anyupdate or a name_new that we've queued a name_firstupdate for name = name_op['name'] formatted_name = format_name_identifier(name) value = name_op['value'] formatted_value = format_name_value(value) else: # utxo is a name_new that we haven't queued a name_firstupdate for name = None formatted_name = '' value = None formatted_value = '' formatted_expires_in = (_( 'Expires in %d blocks\nDate/time is only an estimate; do not rely on it!' ) % expires_in) if expires_in is not None else '' formatted_expires_datetime = expires_datetime.isoformat( ' ') if expires_datetime is not None else '' txout = txid + ":%d" % vout self._utxo_dict[txout] = utxo labels = [ formatted_name, formatted_value, formatted_expires_datetime, 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) utxo_item[self.Columns.EXPIRES_IN].setToolTip(formatted_expires_in) address = utxo.address if self.wallet.is_frozen_address( address) or self.wallet.is_frozen_coin(utxo): utxo_item[self.Columns.NAME].setBackground( ColorScheme.BLUE.as_color(True)) if self.wallet.is_frozen_address( address) and self.wallet.is_frozen_coin(utxo): 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(utxo): utxo_item[self.Columns.NAME].setToolTip(_('Coin is frozen')) self.model().appendRow(utxo_item)
def insert_utxo(self, idx, x): txid = x.get('prevout_hash') vout = x.get('prevout_n') output = self.wallet.db.transactions[txid].outputs()[vout] name_op = output.name_op if name_op is None: return if 'name' not in name_op: # Upstream handles a name_new here, which doesn't exist in Xaya. assert False else: # utxo is name_anyupdate height = x.get('height') header_at_tip = self.network.blockchain().header_at_tip() #chain_height = self.network.blockchain().height() pending = (height <= 0) status = '' if not pending else _('Update Pending') if 'name' in name_op: # utxo is name_anyupdate or a name_new that we've queued a name_firstupdate for name = name_op['name'] formatted_name = format_name_identifier(name) value = name_op['value'] formatted_value = format_name_value(value) else: # utxo is a name_new that we haven't queued a name_firstupdate for name = None formatted_name = '' value = None formatted_value = '' txout = txid + ":%d" % vout self.utxo_dict[txout] = x labels = [formatted_name, formatted_value, 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 insert_utxo(self, idx, x): txid = x.get('prevout_hash') vout = x.get('prevout_n') output = self.wallet.db.transactions[txid].outputs()[vout] name_op = output.name_op if name_op is None: return if 'name' not in name_op: # utxo is name_new firstupdate_output = get_queued_firstupdate_from_new( self.wallet, txid, vout) if firstupdate_output is not None: if firstupdate_output.name_op is not None: name_op = firstupdate_output.name_op expires_in, expires_datetime = None, None status = _('Registration Pending') else: # utxo is name_anyupdate height = x.get('height') header_at_tip = self.network.blockchain().header_at_tip() #chain_height = self.network.blockchain().height() expires_in, expires_datetime = name_expiration_datetime_estimate( height, header_at_tip['block_height'], header_at_tip['timestamp']) status = '' if expires_in is not None else _('Update Pending') if 'name' in name_op: # utxo is name_anyupdate or a name_new that we've queued a name_firstupdate for name = name_op['name'] formatted_name = format_name_identifier(name) value = name_op['value'] formatted_value = format_name_value(value) else: # utxo is a name_new that we haven't queued a name_firstupdate for name = None formatted_name = '' value = None formatted_value = '' formatted_expires_in = (_( 'Expires in %d blocks\nDate/time is only an estimate; do not rely on it!' ) % expires_in) if expires_in is not None else '' formatted_expires_datetime = expires_datetime.isoformat( ' ') if expires_datetime is not None else '' txout = txid + ":%d" % vout self.utxo_dict[txout] = x labels = [ formatted_name, formatted_value, formatted_expires_datetime, 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) utxo_item[self.Columns.EXPIRES_IN].setToolTip(formatted_expires_in) 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)