def are_addresses_identical(addr1: str, addr2: str) -> bool: """Compare 2 addresses. These addresses can be of a different format. :param addr1: :param addr2: :return: """ addr1 = Address.from_string(addr1) addr2 = Address.from_string(addr2) fmt = Address.FMT_LEGACY return addr1.to_string(fmt) == addr2.to_string(fmt)
def set_payment_address(address): self.payto_edit.payto_address = bitcoin.TYPE_ADDRESS, Address.from_string( address) self.value_payto_outputs = self.payto_edit.get_outputs(False) contact_name = None if address in window.wallet.contacts.keys(): contact_type, contact_name = window.wallet.contacts[address] if contact_name is not None: self.payto_edit.setText(contact_name + ' <' + address + '>') else: if Address.is_valid(address): address = Address.from_string(address).to_ui_string() self.payto_edit.setText(address)
def autopay_payments(self, wallet_name, payment_entries): """ For unencrypted wallets, the option is (will be) there to make the payments automatically, rather than simply mark them as unpaid occurrences. """ # payment_entries = [ (payment_data, overdue_payment_times), ... ] wallet_window = self.wallet_windows[wallet_name] wallet = wallet_window.wallet config = wallet_window.config network = wallet_window.network outputs = [] for payment_data, overdue_payment_times in payment_entries: totalSatoshis = len( overdue_payment_times) * payment_data[PAYMENT_AMOUNT] address = Address.from_string(payment_data[PAYMENT_ADDRESS]) outputs.append((TYPE_ADDRESS, address, totalSatoshis)) password = None tx = wallet.mktx(outputs, password, wallet_window.config) status, data = network.broadcast(tx) if status: # data is txid. return data # data is error message # Fallback to remembering the overdue payments. # TODO: Alert the user about the failure - best way is to mark the payment. for payment_data, overdue_payment_times in payment_entries: self.remember_overdue_payment_occurrences(payment_data, overdue_payment_times)
def invoke(firstarg='0.0.0.0', sport='8787', upnp_str=None, addr_str=None): bindhost, *extrahosts = firstarg.split(',') if len(extrahosts) > 1: raise Exception("too many hosts") elif len(extrahosts) == 1: [ announcehost, ] = extrahosts else: announcehost = None port = int(sport) pnp = get_upnp() if upnp_str == 'upnp' else None if not pnp and not addr_str: # third arg may be addr_str, so swap the args addr_str = upnp_str upnp_str = None addr = None if addr_str: assert Address.is_valid( addr_str), "Invalid donation address specified" addr = Address.from_string(addr_str) return self.start_fusion_server(network, bindhost, port, upnp=pnp, announcehost=announcehost, donation_address=addr)
def get_contacts() -> list: ''' Builds a list of ContactsEntry tuples: ContactsEntry = namedtuple("ContactsEntry", "name address address_str hist_entries") ''' t0 = time.time() parent = gui.ElectrumGui.gui wallet = parent.wallet if wallet is None: utils.NSLog("get_contacts: wallent was None, returning early") return list() c = wallet.contacts contacts = list() for addr,tupl in c.items(): typ, name = tupl if typ == 'address' and Address.is_valid(addr): address = Address.from_string(addr) hist_entries = build_contact_tx_list(address) entry = ContactsEntry(name, address, addr, hist_entries) contacts.append(entry) contacts.sort(key=lambda x: [x.name, x.address_str], reverse=False) utils.NSLog("get_contacts: fetched %d contacts in %f ms",len(contacts), (time.time()-t0)*1000.0) return contacts
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()) 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 %s") % column_title, lambda: self.parent.app.clipboard().setText(column_data)) if column in self.editable_columns: item = self.currentItem() menu.addAction( _("Edit %s") % 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 = [ web.BE_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))
def doVerify(self) -> None: addrtf = self.tf address_str = str(addrtf.text).strip() message = str(self.topTvDel.text) signature = str(self.botTvDel.text).strip() if not signature: parent().show_message( _("Please provide both a signature and a message to verify")) return try: address = Address.from_string(address_str) except: parent().show_error(_('Invalid Vitae address.')) return message = message.encode('utf-8') try: # This can raise on invalid base64 sig = base64.b64decode(signature) verified = bitcoin.verify_message( address, sig, message) # this raises too on failure except: verified = False if verified: parent().show_message(_("Signature verified"), title=_("Success")) else: parent().show_error(_("Wrong signature"))
def on_edited(self, item, column, prior_value): contact = item.data(0, self.DataRoles.Contact) if column == 2: # Label label_key = contact.address try: label_key = Address.from_string(label_key).to_storage_string() except: pass self.wallet.set_label(label_key, item.text(2)) self.update() # force refresh in case 2 contacts use the same address return # else.. Name typ = contact.type was_cur, was_sel = bool(self.currentItem()), item.isSelected() name, value = item.text(1), item.text(3) del item # paranoia # On success, parent.set_contact returns the new key (address text) # if 'cashacct'.. or always the same key for all other types. key = self.parent.set_contact(name, value, typ=typ, replace=contact) if key: # Due to deferred updates, on_update will actually be called later. # So, we have to save the edited item's "current" and "selected" # status here. 'on_update' will look at this tuple and clear it # after updating. self._edited_item_cur_sel = (key, was_cur, was_sel)
def do_send(self): if self.screen.is_pr: if self.payment_request.has_expired(): self.app.show_error(_('Payment request has expired')) return outputs = self.payment_request.get_outputs() else: address = str(self.screen.address) if not address: self.app.show_error( _('Recipient not specified.') + ' ' + _('Please scan a Bitcoin address or a payment request')) return if not Address.is_valid(address): self.app.show_error( _('Invalid Bitcoin Address') + ':\n' + address) return try: amount = self.app.get_amount(self.screen.amount) except: self.app.show_error( _('Invalid amount') + ':\n' + self.screen.amount) return outputs = [(bitcoin.TYPE_ADDRESS, Address.from_string(address), amount)] message = self.screen.message amount = sum(map(lambda x: x[2], outputs)) self._do_send(amount, message, outputs)
def view_addr_link_activated(addr): if isinstance(parent, ElectrumWindow): try: address = Address.from_string(addr) parent.show_address(address, parent=parent.top_level_window()) except Exception as e: parent.print_error(repr(e))
def do_sign(self): password = self._get_password() address = self.address_e.text().strip() message = self.message_e.toPlainText().strip() try: addr = Address.from_string(address) except Exception: self.show_message(_(f"Invalid {CURRENCY} address.")) return if addr.kind != addr.ADDR_P2PKH: msg_sign = (_( "Signing with an address actually means signing with the corresponding " "private key, and verifying with the corresponding public key. The " "address you have entered does not have a unique public key, so these " "operations cannot be performed.") + "\n\n" + _(f"The operation is undefined. Not just in " f"{PROJECT_NAME}, but in general.")) self.show_message( _("Cannot sign messages with this type of address.") + "\n\n" + msg_sign) return if self.wallet.is_watching_only(): self.show_message(_("This is a watching-only wallet.")) return if not self.wallet.is_mine(addr): self.show_message(_("Address not in wallet.")) return task = partial(self.wallet.sign_message, addr, message, password, self.get_sigtype()) def show_signed_message(sig): self.signature_e.setText(base64.b64encode(sig).decode("ascii")) self.wallet.thread.add(task, on_success=show_signed_message)
def doConversion_(self, text) -> bool: self.cash.text = "" self.legacy.text = "" self.cpyCashBut.enabled = False self.cpyLegBut.enabled = False self.qrButShowCash.enabled = False self.qrButShowLegacy.enabled = False text = text.strip() addy = None try: addy = Address.from_string(text) except: pass if addy: self.cash.text = addy.to_full_string(Address.FMT_CASHADDR) self.legacy.text = addy.to_full_string(Address.FMT_LEGACY) self.cpyCashBut.enabled = True self.cpyLegBut.enabled = True self.qrButShowCash.enabled = True self.qrButShowLegacy.enabled = True return True return False
def do_view(self, obj): addr = Address.from_string(obj.address) req = self.app.wallet.get_payment_request(addr, self.app.electrum_config) if req: c, u, x = self.app.wallet.get_addr_balance(addr) balance = c + u + x if balance > 0: req['fund'] = balance status = req.get('status') amount = req.get('amount') address = req['address'] if amount: status = req.get('status') status = request_text[status] else: received_amount = self.app.wallet.get_addr_received(address) status = self.app.format_amount_and_units(received_amount) self.app.show_pr_details(req, status, False) else: req = {'address': addr, 'status': obj.status} status = obj.status c, u, x = self.app.wallet.get_addr_balance(addr) balance = c + u + x if balance > 0: req['fund'] = balance self.app.show_addr_details(req, status)
def get_max_amount(self): inputs = self.wallet.get_spendable_coins(None, self.electrum_config) addr = Address.from_string(self.send_screen.screen.address) or self.wallet.dummy_address() outputs = [(TYPE_ADDRESS, addr, '!')] tx = self.wallet.make_unsigned_transaction(inputs, outputs, self.electrum_config) amount = tx.output_value() return format_satoshis_plain(amount, self.decimal_point())
def make_unsigned_transaction(self, amount, fee, all_inputs, outputs, changes): ''' make unsigned transaction ''' dust = self.dust_threshold( ) # always 546 for now, but this call is here in case something more sophisticated happens in the future coins = {} tx_inputs = [] amounts = {} try: for player in all_inputs: inputs_coins = self.get_coins(all_inputs[player]) # if there are no coins on input it terminates the process if inputs_coins: coins[player] = inputs_coins else: return None except BaseException as e: self.print_error('make_unsigned_transaction:', repr(e)) return None for player, pubkey_utxos in coins.items(): amounts[player] = 0 for pubkey, utxos in pubkey_utxos.items(): for utxo in utxos: utxo['type'] = 'p2pkh' utxo['address'] = Address.from_pubkey(pubkey) utxo['pubkeys'] = [pubkey] utxo['x_pubkeys'] = [pubkey] utxo['prevout_hash'] = utxo['tx_hash'] utxo['prevout_n'] = utxo['tx_pos'] utxo['signatures'] = [None] utxo['num_sig'] = 1 tx_inputs.append(utxo) amounts[player] += utxo['value'] tx_inputs.sort(key=lambda x: x['prevout_hash'] + str(x["tx_pos"])) tx_outputs = [(TYPE_ADDRESS, Address.from_string(output), int(amount)) for output in outputs] transaction = Transaction.from_io(tx_inputs, tx_outputs, sign_schnorr=False) tx_changes = [ (TYPE_ADDRESS, Address.from_string(changes[player]), int(amounts[player] - amount - fee)) for player in sorted(changes) if Address.is_valid(changes[player]) and int(amounts[player] - amount - fee) >= dust ] transaction.add_outputs(tx_changes) return transaction
def mecenate_info_changed(self, ): # if any of the txid/out#/value changes try: self.protege_address = Address.from_string( self.protege_address_wid.text()) self.reps = int(self.repetitions.text()) self.rpayment_time = int( self.rpayment_time_wid.text()) * 3600 * 24 // 512 self.rpayment_value = self.rpayment_value_wid.get_amount() total_time = int(self.rpayment_time_wid.text()) * self.reps self.total_time_label.setText("<b>%s</b>" % (str(total_time) + " days")) if self.advanced_wid.option == 2: self.version = 2 self.addresses = [self.protege_address, self.mecenas_address] elif self.advanced_wid.option == 3: self.version = 3 self.escrow_address = Address.from_string( self.advanced_wid.escrow_address.text()) self.addresses = [ self.protege_address, self.mecenas_address, self.escrow_address ] elif self.advanced_wid.option == 1: self.version = 1.1 self.addresses = [self.protege_address, self.mecenas_address] elif self.advanced_wid.option == 4: self.version = 1 self.addresses = [self.protege_address, self.mecenas_address] self.total_value = self.reps * (self.rpayment_value + MecenasContract.fee(self.version)) self.total_label.setText( "<b>%s</b>" % (self.main_window.format_amount(self.total_value) + " " + self.main_window.base_unit())) except Exception as e: self.create_button.setDisabled(True) print(e) else: self.create_button.setDisabled(False) # PROTEGE is 0, MECENAS is 1 self.contract = MecenasContract( self.addresses, v=self.version, data=[self.rpayment_time, self.rpayment_value])
def checkAddress(self): xpub = self.textBox.document().toPlainText() if xpub[:2] != "ff" or len(xpub) < 100: self.textBox.setPlainText( "Please enter your partner's x_pubkey into this textbox before clicking CheckAddress." ) return addrOrig = self.addressBox.text() try: addr = Address.from_string(addrOrig) except: self.addressBox.setText( "Please enter multisig address here before clicking CheckAddress." ) return if addr.kind != Address.ADDR_P2SH: self.addressBox.setText( "The address you entered was not a multisig address.") return currentContract = self.getCurrentContract() if currentContract != None: if "address" in cashrip.contracts[currentContract]: self.textBox.setPlainText( "This contract already has an address. Maybe you selected the wrong contract?" ) return if cashrip.contracts[currentContract]["my_x_pubkey"] == xpub: self.textBox.setPlainText( "You entered your own x_pubkey, not your partner's.") return try: self.textBox.setPlainText("Please wait . . .") self.textBox.repaint() contract = cashrip.create_multisig_addr( currentContract, xpub, False) except: self.textBox.setPlainText( "Something was wrong with the x_pubkey you pasted.") return if contract["address"] == addr: self.textBox.setPlainText( "Success. You and your partner generated the same address. You can now send funds to {}" .format(addrOrig)) cashrip.startSyncMultiWallet(currentContract, self.network) else: self.textBox.setPlainText( "Something went wrong. You and your partner generated different addresses. Please double-check the x_pubkeys that you have sent to each other." ) os.remove(contract['addrWalletFile']) del contract["addrWalletFile"] del contract["address"] del contract["partner_addr"] del contract["partner_x_pubkey"] del contract["partner_pubkey"] del contract["gen_by_me"] del contract["redeemScript"] cashrip.updateContracts() cashrip.multiWallets[currentContract] = None self.parent.update()
def save_request(self): addr = Address.from_string(self.screen.address) amount = self.screen.amount message = self.screen.message amount = self.app.get_amount(amount) if amount else 0 req = self.app.wallet.make_payment_request(addr, amount, message, None) self.app.wallet.add_payment_request(req, self.app.electrum_config) self.app.update_tab('requests')
def get_URI(self): amount = self.screen.amount if amount: a, u = self.screen.amount.split() assert u == self.app.base_unit amount = Decimal(a) * pow(10, self.app.decimal_point()) addr = Address.from_string(self.screen.address) return create_URI(addr, amount, self.screen.message)
def update(self): if not self.screen.address: self.get_new_address() else: addr = Address.from_string(self.screen.address) status = self.app.wallet.get_request_status(addr) self.screen.status = _( 'Payment received') if status == PR_PAID else ''
def onBlkXplo() -> None: print("onBlkXplo") if isInput: data = getData(x, False, True) else: data = getData(x, True, False) data = Address.from_string(data) parent.view_on_block_explorer(data, "tx" if isInput else "addr")
def show_private_key(addr, pk_label, password): if self.wallet.has_password() and password is None: return if not self.wallet.can_export(): return addr = Address.from_string(addr) key = self.wallet.export_private_key(addr, password) pk_label.data = key
def validate_address(self, address_text: str): previous_address = self.output_address try: self.output_address = Address.from_string(address_text) except AddressError: self.output_address = None if self.output_address != previous_address: self.completeChanged.emit()
def make_unsigned_transaction(self, amount, fee, inputs, outputs, changes): coins = {vk : self.get_first_sufficient_utxo(inputs[vk], amount) for vk in inputs} for vk in coins: coins[vk]['type'] = 'p2pkh' coins[vk]['address'] = Address.from_string(self.address(vk)) coins[vk]['pubkeys'] = [vk] coins[vk]['x_pubkeys'] = [vk] coins[vk]['prevout_hash'] = coins[vk]['tx_hash'] coins[vk]['prevout_n'] = coins[vk]['tx_pos'] coins[vk]['signatures'] = [None] coins[vk]['num_sig'] = 1 tx_inputs = [coins[vk] for vk in sorted(coins)] tx_outputs = [(TYPE_ADDRESS, Address.from_string(output), int(amount)) for output in outputs ] tx = Transaction.from_io(tx_inputs, tx_outputs) tx_changes = [(TYPE_ADDRESS, Address.from_string(changes[vk]), int(coins[vk]['value'] - amount - fee)) for vk in changes if Address.is_valid(changes[vk])] tx.add_outputs(tx_changes) return tx
def donation_address(self, window) -> Optional[Tuple[str, Address]]: ''' Plugin API: Returns a tuple of (description, Address) or None. This is the donation address that we as a client got from the remote server (as opposed to the donation address we announce if we are a server). ''' if self.remote_donation_address and Address.is_valid( self.remote_donation_address): return (self.fullname() + " " + _("Server") + ": " + self.get_server()[0], Address.from_string(self.remote_donation_address))
def doCB() -> None: cb = utils.get_callback(self, 'on_ok') if callable(cb): entry = None if name and address_str and Address.is_valid(address_str): address = Address.from_string(address_str) entry = ContactsEntry(name, address, address_str) cb(entry) self.autorelease()
def parse_address(self, line): slp_token_type_index = self.parent.token_type_combo.currentIndex() r = line.strip() m = re.match(RE_ALIAS, r) address = m.group(2) if m else r if slp_token_type_index > 0: if "simpleledger" not in address: address = "simpleledger:" + address return Address.from_string(address)
def decodeAddress(addr: str) -> Address: ret = None if addr: try: # re-encode addr in case they went to/from cashaddr ret = Address.from_string(addr) except BaseException as e: utils.NSLog("Caught exception decoding address %s: %s", addr, str(e)) return ret
def delete_history(self, address: Address) -> None: if isinstance(address, str) and Address.is_valid(address): address = Address.from_string(address) storage = self.parent.wallet.storage if self.parent.wallet else None if storage: with self.lock: addrstr = address.to_storage_string() k = 'contact_history_%s' % (addrstr) storage.put(k, None) self.print_error("Deleted %s" % addrstr)
def new_contract_info_changed(self, ): # if any of the txid/out#/value changes try: self.total_value = self.value_wid.get_amount() self.receiver_address = Address.from_string( self.receiver_address_wid.text()) self.arbiter_address = Address.from_string( self.arbiter_address_wid.text()) addresses = [ self.receiver_address, self.sender_address, self.arbiter_address ] except: self.create_button.setDisabled(True) else: self.create_button.setDisabled(False) self.contract = MultisigContract(addresses, v=self.version, data=None)