예제 #1
0
    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))
예제 #2
0
 def _add_addr_to_io_menu_lists_for_widget(self, addr, show_list, copy_list,
                                           widget):
     if hasattr(addr, 'to_ui_string'):
         addr_text = addr.to_ui_string()
         if isinstance(addr, Address) and self.wallet.is_mine(addr):
             show_list += [(_("Address Details"),
                            lambda: self._open_internal_link(addr_text))]
             addr_URL = web.BE_URL(self.main_window.config,
                                   web.ExplorerUrlParts.ADDR, addr)
             if addr_URL:
                 show_list += [(_("View on block explorer"),
                                lambda: webopen(addr_URL))]
         if isinstance(addr, ScriptOutput):
             action_text = _("Copy Script Text")
         elif isinstance(addr, PublicKey):
             action_text = _("Copy Public Key")
         else:
             action_text = _("Copy Address")
         copy_list += [(action_text,
                        lambda: self._copy_to_clipboard(addr_text, widget))]
         # also add script hex copy to clipboard
         if isinstance(addr, ScriptOutput):
             hex_text = addr.to_script().hex() or ''
             if hex_text:
                 copy_list += [
                     (_("Copy Script Hex"),
                      lambda: self._copy_to_clipboard(hex_text, widget))
                 ]
예제 #3
0
    def create_menu(self, position):
        item = self.currentItem()
        if not item:
            return
        column = self.currentColumn()
        tx_hash = item.data(0, Qt.UserRole)
        token_id = item.data(4, Qt.UserRole)
        if not tx_hash:
            return
        if column == 0:
            column_title = "ID"
            column_data = tx_hash
        else:
            column_title = self.headerItem().text(column)
            column_data = item.text(column)

        tx_URL = web.BE_URL(self.config, 'tx', tx_hash)
        height, conf, timestamp = self.wallet.get_tx_height(tx_hash)
        tx = self.wallet.transactions.get(tx_hash)
        is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(tx)
        is_unconfirmed = height <= 0
        pr_key = self.wallet.invoices.paid.get(tx_hash)

        menu = QMenu()

        if not self.wallet.token_types.get(token_id):
            menu.addAction(
                _("Add this token"),
                lambda: SlpAddTokenDialog(self.parent, token_id_hex=token_id))
        elif self.wallet.token_types.get(token_id)['decimals'] == '?':
            menu.addAction(
                _("Add this token"), lambda: SlpAddTokenDialog(
                    self.parent, token_id_hex=token_id, allow_overwrite=True))

        menu.addAction(
            _("Copy {}").format(column_title),
            lambda: self.parent.app.clipboard().setText(column_data))
        if column in self.editable_columns:
            # We grab a fresh reference to the current item, as it has been deleted in a reported issue.
            menu.addAction(
                _("Edit {}").format(column_title),
                lambda: self.currentItem() and self.editItem(
                    self.currentItem(), column))

        menu.addAction(_("Details"), lambda: self.parent.show_transaction(tx))
        if is_unconfirmed and tx:
            child_tx = self.wallet.cpfp(tx, 0)
            if child_tx:
                menu.addAction(_("Child pays for parent"),
                               lambda: self.parent.cpfp(tx, child_tx))
        if pr_key:
            menu.addAction(QIcon(":icons/seal.svg"), _("View invoice"),
                           lambda: self.parent.show_invoice(pr_key))
        if tx_URL:
            menu.addAction(_("View on block explorer"),
                           lambda: webbrowser.open(tx_URL))
        if self.wallet.get_slp_token_info(tx_hash)['validity'] == 2:
            menu.addAction(_("Revalidate"),
                           lambda: self.wallet.revalidate(tx_hash, tx))
        menu.exec_(self.viewport().mapToGlobal(position))
예제 #4
0
    def create_menu(self, position):
        from electroncash.wallet import Multisig_Wallet
        is_multisig = isinstance(self.wallet, Multisig_Wallet)
        can_delete = self.wallet.can_delete_address()
        selected = self.selectedItems()
        multi_select = len(selected) > 1
        addrs = [item.data(0, Qt.UserRole) for item in selected]
        if not addrs:
            return
        addrs = [addr for addr in addrs if isinstance(addr, Address)]

        menu = QMenu()

        if not multi_select:
            item = self.itemAt(position)
            col = self.currentColumn()
            if not item:
                return
            if not addrs:
                item.setExpanded(not item.isExpanded())
                return
            addr = addrs[0]

            column_title = self.headerItem().text(col)
            if col == 0:
                copy_text = addr.to_full_ui_string()
            else:
                copy_text = item.text(col)
            menu.addAction(_("Copy {}").format(column_title), lambda: self.parent.app.clipboard().setText(copy_text))
            menu.addAction(_('Details'), lambda: self.parent.show_address(addr))
            if col in self.editable_columns:
                menu.addAction(_("Edit {}").format(column_title), lambda: self.editItem(self.itemAt(position), # NB: C++ item may go away if this widget is refreshed while menu is up -- so need to re-grab and not store in lamba. See #953
                                                                                        col))
            menu.addAction(_("Request payment"), lambda: self.parent.receive_at(addr))
            if self.wallet.can_export():
                menu.addAction(_("Private key"), lambda: self.parent.show_private_key(addr))
            if not is_multisig and not self.wallet.is_watching_only():
                menu.addAction(_("Sign/verify message"), lambda: self.parent.sign_verify_message(addr))
                menu.addAction(_("Encrypt/decrypt message"), lambda: self.parent.encrypt_message(addr))
            if can_delete:
                menu.addAction(_("Remove from wallet"), lambda: self.parent.remove_address(addr))
            addr_URL = web.BE_URL(self.config, 'addr', addr)
            if addr_URL:
                menu.addAction(_("View on block explorer"), lambda: webbrowser.open(addr_URL))

        freeze = self.parent.set_frozen_state
        if any(self.wallet.is_frozen(addr) for addr in addrs):
            menu.addAction(_("Unfreeze"), partial(freeze, addrs, False))
        if not all(self.wallet.is_frozen(addr) for addr in addrs):
            menu.addAction(_("Freeze"), partial(freeze, addrs, True))

        coins = self.wallet.get_spendable_coins(domain = addrs, config = self.config)
        if coins:
            menu.addAction(_("Spend from"),
                           partial(self.parent.spend_coins, coins))

        run_hook('receive_menu', menu, addrs, self.wallet)
        menu.exec_(self.viewport().mapToGlobal(position))
예제 #5
0
    def create_menu(self, position):
        item = self.currentItem()
        if not item:
            return
        column = self.currentColumn()
        tx_hash = item.data(0, Qt.UserRole)
        if not tx_hash:
            return
        if column is 0:
            column_title = "ID"
            column_data = tx_hash
        else:
            column_title = self.headerItem().text(column)
            column_data = item.text(column)

        tx_URL = web.BE_URL(self.config, 'tx', tx_hash)
        height, conf, timestamp = self.wallet.get_tx_height(tx_hash)
        tx = self.wallet.transactions.get(tx_hash)
        if not tx:
            return  # this happens sometimes on wallet synch when first starting up.
        is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(tx)
        is_unconfirmed = height <= 0
        pr_key = self.wallet.invoices.paid.get(tx_hash)

        menu = QMenu()

        menu.addAction(
            _("Copy {}").format(column_title),
            lambda: self.parent.app.clipboard().setText(column_data))
        if column in self.editable_columns:
            # We grab a fresh reference to the current item, as it has been deleted in a reported issue.
            menu.addAction(
                _("Edit {}").format(column_title),
                lambda: self.currentItem() and self.editItem(
                    self.currentItem(), column))
        label = self.wallet.get_label(tx_hash) or None
        menu.addAction(_("Details"),
                       lambda: self.parent.show_transaction(tx, label))
        if is_unconfirmed and tx:
            child_tx = self.wallet.cpfp(tx, 0)
            if child_tx:
                menu.addAction(_("Child pays for parent"),
                               lambda: self.parent.cpfp(tx, child_tx))
        if pr_key:
            menu.addAction(self.invoiceIcon, _("View invoice"),
                           lambda: self.parent.show_invoice(pr_key))
        if tx_URL:
            menu.addAction(_("View on block explorer"),
                           lambda: webbrowser.open(tx_URL))

        run_hook("history_list_context_menu_setup", self, menu, item,
                 tx_hash)  # Plugins can modify menu

        menu.exec_(self.viewport().mapToGlobal(position))
예제 #6
0
 def open_be_url(link):
     if link:
         try:
             kind, thing = link.split(':')
             url = web.BE_URL(self.main_window.config, kind, thing)
         except:
             url = None
         if url:
             webopen( url )
         else:
             self.show_error(_('Unable to open in block explorer. Please be sure your block explorer is configured correctly in preferences.'))
예제 #7
0
 def open_be_url(link):
     if link:
         try:
             _, txid = link.split(':')
             url = web.BE_URL(self.main_window.config, web.ExplorerUrlParts.TX, txid)
         except:
             raise
             url = None
         if url:
             webopen( url )
         else:
             self.show_error(_('Unable to open in block explorer. Please be sure your block explorer is configured correctly in preferences.'))
예제 #8
0
 def open_link(link):
     if Address.is_valid(link):
         addr = Address.from_string(link)
         if wallet.is_mine(addr):
             parent.show_address(addr)
         else:
             addr_URL = web.BE_URL(parent.config, 'addr', addr)
             if addr_URL:
                 webopen(addr_URL)
         return
     if link.startswith('http'):
         webopen(link)
예제 #9
0
    def create_menu(self, position):
        self.selectedIndexes()
        item = self.currentItem()
        if not item:
            return
        column = self.currentColumn()
        tx_hash = item.data(0, Qt.UserRole)
        if not tx_hash:
            return
        if column is 0:
            column_title = "ID"
            column_data = tx_hash
        else:
            column_title = self.headerItem().text(column)
            column_data = item.text(column)

        tx_URL = web.BE_URL(self.config, 'tx', tx_hash)
        height, conf, timestamp = self.wallet.get_tx_height(tx_hash)
        tx = self.wallet.transactions.get(tx_hash)
        is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(tx)
        is_unconfirmed = height <= 0
        pr_key = self.wallet.invoices.paid.get(tx_hash)

        menu = QMenu()

        menu.addAction(
            _("Copy {}").format(column_title),
            lambda: self.parent.app.clipboard().setText(column_data))
        if column in self.editable_columns:
            # We grab a fresh reference to the current item, as it has been deleted in a reported issue.
            menu.addAction(
                _("Edit {}").format(column_title),
                lambda: self.currentItem() and self.editItem(
                    self.currentItem(), column))

        menu.addAction(_("Details"), lambda: self.parent.show_transaction(tx))
        if is_unconfirmed and tx:
            child_tx = self.wallet.cpfp(tx, 0)
            if child_tx:
                menu.addAction(_("Child pays for parent"),
                               lambda: self.parent.cpfp(tx, child_tx))
        if pr_key:
            menu.addAction(QIcon(":icons/seal"), _("View invoice"),
                           lambda: self.parent.show_invoice(pr_key))
        if tx_URL:
            menu.addAction(_("View on block explorer"),
                           lambda: webbrowser.open(tx_URL))
        menu.exec_(self.viewport().mapToGlobal(position))
예제 #10
0
 def open_link(link):
     if Address.is_valid(link):
         addr = Address.from_string(link)
         if wallet.is_mine(addr):
             parent.show_address(addr)
         else:
             addr_URL = web.BE_URL(parent.config, web.ExplorerUrlParts.ADDR, addr)
             if addr_URL:
                 webopen(addr_URL)
         return
     if link.startswith('http'):
         webopen(link)
     elif len(link) == 64:  # 64 character txid
         tx = wallet.transactions.get(link)
         if tx:
             parent.show_transaction(tx, tx_desc=wallet.get_label(link))
         else:
             parent.do_process_from_txid(txid=link, tx_desc=wallet.get_label(link))
         return
예제 #11
0
    def create_menu(self, position):
        self.selectedIndexes()
        item = self.currentItem()
        if not item:
            return
        column = self.currentColumn()
        tx_hash = item.data(0, Qt.UserRole)
        if not tx_hash:
            return
        if column is 0:
            column_title = "ID"
            column_data = tx_hash
        else:
            column_title = self.headerItem().text(column)
            column_data = item.text(column)

        tx_URL = web.BE_URL(self.config, 'tx', tx_hash)
        height, conf, timestamp = self.wallet.get_tx_height(tx_hash)
        tx = self.wallet.transactions.get(tx_hash)

        otherpubkey = item.data(1, Qt.UserRole)

        menu = QMenu()

        if otherpubkey:
            menu.addAction(_("Reply"), lambda: self.parent.write_message(otherpubkey.hex()))

        menu.addAction(_("Copy {}").format(column_title), lambda: self.parent.parent.app.clipboard().setText(column_data))
        if column in self.editable_columns:
            # We grab a fresh reference to the current item, as it has been deleted in a reported issue.
            menu.addAction(_("Edit {}").format(column_title),
                lambda: self.currentItem() and self.editItem(self.currentItem(), column))

        menu.addAction(_("Details"), lambda: self.parent.parent.show_transaction(tx))
        if tx_URL:
            menu.addAction(_("View on block explorer"), lambda: webbrowser.open(tx_URL))
        menu.exec_(self.viewport().mapToGlobal(position))
예제 #12
0
		def doOpenBlockExplorerTX(txid: str):
			URL = web.BE_URL(self.config, 'tx', txid)
			webopen(URL)
예제 #13
0
    def create_menu(self, position):
        menu = QMenu()
        selected = self.selectedItems()
        i2c = self._i2c
        ca_unverified = self._get_ca_unverified(include_temp=False)
        if selected:
            names = [item.text(1) for item in selected]
            keys = [i2c(item) for item in selected]
            payable_keys = [k for k in keys if k.type != 'cashacct_T']
            deletable_keys = [k for k in keys if k.type in contact_types]
            needs_verif_keys = [k for k in keys if k in ca_unverified]
            column = self.currentColumn()
            column_title = self.headerItem().text(column)
            column_data = '\n'.join([item.text(column) for item in selected])
            item = self.currentItem()
            typ = i2c(item).type if item else 'unknown'
            ca_info = None
            if item and typ in ('cashacct', 'cashacct_W'):
                ca_info = self.wallet.cashacct.get_verified(i2c(item).name)
                if column == 1 and len(selected) == 1:
                    # hack .. for Cash Accounts just say "Copy Cash Account"
                    column_title = _('Cash Account')
                    if ca_info:
                        column_data = self.wallet.cashacct.fmt_info(ca_info, emoji=True)
            menu.addAction(_("Copy {}").format(column_title), lambda: self.parent.app.clipboard().setText(column_data))
            if item and column in self.editable_columns and self.on_permit_edit(item, column):
                key = item.data(0, self.DataRoles.Contact)
                # this key & find_item business is so we don't hold a reference
                # to the ephemeral item, which may be deleted while the
                # context menu is up.  Accessing the item after on_update runs
                # means the item is deleted and you get a C++ object deleted
                # runtime error.
                menu.addAction(_("Edit {}").format(column_title), lambda: self._on_edit_item(key, column))
            a = menu.addAction(_("Pay to"), lambda: self.parent.payto_contacts(payable_keys))
            if needs_verif_keys or not payable_keys:
                a.setDisabled(True)
            a = menu.addAction(_("Delete"), lambda: self.parent.delete_contacts(deletable_keys))
            if not deletable_keys:
                a.setDisabled(True)
            # Add sign/verify and encrypt/decrypt menu - but only if just 1 thing selected
            if len(keys) == 1 and Address.is_valid(keys[0]):
                signAddr = Address.from_string(keys[0])
                a = menu.addAction(_("Sign/verify message") + "...", lambda: self.parent.sign_verify_message(signAddr))
                if signAddr.kind != Address.ADDR_P2PKH:
                    a.setDisabled(True)  # We only allow this for P2PKH since it makes no sense for P2SH (ambiguous public key)
            URLs = [web.BE_URL(self.config, 'addr', Address.from_string(key.address))
                    for key in keys if Address.is_valid(key.address)]
            a = menu.addAction(_("View on block explorer"), lambda: [URL and webopen(URL) for URL in URLs])
            if not any(URLs):
                a.setDisabled(True)
            if ca_info:
                menu.addAction(_("View registration tx..."), lambda: self.parent.do_process_from_txid(txid=ca_info.txid, tx_desc=self.wallet.get_label(ca_info.txid)))
                if typ in ('cashacct_W', 'cashacct'):
                    _contact_d = i2c(item)
                    menu.addAction(_("Details..."), lambda: cashacctqt.cash_account_detail_dialog(self.parent, _contact_d.name))
            menu.addSeparator()

        menu.addAction(self.icon_cashacct,
                       _("Add Contact") + " - " + _("Cash Account"), self.new_cash_account_contact_dialog)
        menu.addAction(self.icon_contacts, _("Add Contact") + " - " + _("Address"), self.parent.new_contact_dialog)
        menu.addSeparator()
        menu.addAction(self.icon_cashacct,
                       _("Register Cash Account..."), self.parent.register_new_cash_account)
        menu.addSeparator()
        menu.addAction(QIcon(":icons/import.svg" if not ColorScheme.dark_scheme else ":icons/import_dark_theme.svg"),
                       _("Import file"), self.import_contacts)
        if not self.parent.contacts.empty:
            menu.addAction(QIcon(":icons/save.svg" if not ColorScheme.dark_scheme else ":icons/save_dark_theme.svg"),
                           _("Export file"), self.export_contacts)

        menu.addSeparator()
        a = menu.addAction(_("Show My Cash Accounts"), self.toggle_show_my_cashaccts)
        a.setCheckable(True)
        a.setChecked(self.show_my_cashaccts)

        if ca_unverified:
            def kick_off_verify():
                bnums = set()
                for contact in ca_unverified:
                    tup = self.wallet.cashacct.parse_string(contact.name)
                    if not tup:
                        continue
                    bnums.add(tup[1])  # number
                ret = cashacctqt.verify_multiple_blocks(bnums, self.parent, self.wallet)
                if ret is None:
                    # user cancel
                    return
                verified = ca_unverified - self._get_ca_unverified()
                if not verified:
                    self.parent.show_error(_("Cash Account verification failure"))

            menu.addSeparator()
            num = len(ca_unverified)
            a = menu.addAction(self.icon_unverif,
                               ngettext("Verify {count} Cash Account",
                                        "Verify {count} Cash Accounts",
                                        num).format(count=num), kick_off_verify)
            if not self.wallet.network:
                a.setDisabled(True)

        run_hook('create_contact_menu', menu, selected)
        menu.exec_(self.viewport().mapToGlobal(position))
예제 #14
0
		def doOpenBlockExplorerAddress(address: Address):
			URL = web.BE_URL(self.config, 'addr', address)
			webopen(URL)
예제 #15
0
    def create_menu(self, position):
        from electroncash.wallet import Multisig_Wallet
        is_multisig = isinstance(self.wallet, Multisig_Wallet)
        can_delete = self.wallet.can_delete_address()
        selected = self.selectedItems()
        multi_select = len(selected) > 1
        addrs = [item.data(0, self.DataRoles.address) for item in selected]
        if not addrs:
            return
        addrs = [addr for addr in addrs if isinstance(addr, Address)]

        menu = QMenu()

        where_to_insert_dupe_copy_cash_account = None

        if not multi_select:
            item = self.itemAt(position)
            col = self.currentColumn()
            if not item:
                return
            if not addrs:
                item.setExpanded(not item.isExpanded())
                return
            addr = addrs[0]

            column_title = self.headerItem().text(col)
            alt_copy_text, alt_column_title = None, None
            if col == 0:
                copy_text = addr.to_full_ui_string()
                if Address.FMT_UI == Address.FMT_LEGACY:
                    alt_copy_text, alt_column_title = addr.to_full_string(
                        Address.FMT_CASHADDR), _('Cash Address')
                else:
                    alt_copy_text, alt_column_title = addr.to_full_string(
                        Address.FMT_LEGACY), _('Legacy Address')
            else:
                copy_text = item.text(col)

            def doCopy(txt):
                txt = txt.strip()
                self.parent.copy_to_clipboard(txt)

            menu.addAction(
                _("Copy {}").format(column_title), lambda: doCopy(copy_text))
            if alt_copy_text and alt_column_title:
                # Add 'Copy Legacy Address' and 'Copy Cash Address' alternates if right-click is on column 0
                menu.addAction(
                    _("Copy {}").format(alt_column_title),
                    lambda: doCopy(alt_copy_text))
            a = menu.addAction(
                _('Details') + "...", lambda: self.parent.show_address(addr))
            if col == 0:
                where_to_insert_dupe_copy_cash_account = a
            if col in self.editable_columns:
                menu.addAction(
                    _("Edit {}").format(column_title),
                    lambda: self.editItem(
                        self.itemAt(
                            position
                        ),  # NB: C++ item may go away if this widget is refreshed while menu is up -- so need to re-grab and not store in lamba. See #953
                        col))
            menu.addAction(_("Request payment"),
                           lambda: self.parent.receive_at(addr))
            if self.wallet.can_export():
                menu.addAction(_("Private key"),
                               lambda: self.parent.show_private_key(addr))
            if not is_multisig and not self.wallet.is_watching_only():
                menu.addAction(_("Sign/verify message"),
                               lambda: self.parent.sign_verify_message(addr))
                menu.addAction(_("Encrypt/decrypt message"),
                               lambda: self.parent.encrypt_message(addr))
            if can_delete:
                menu.addAction(_("Remove from wallet"),
                               lambda: self.parent.remove_address(addr))
            addr_URL = web.BE_URL(self.config, 'addr', addr)
            if addr_URL:
                menu.addAction(_("View on block explorer"),
                               lambda: webopen(addr_URL))

        freeze = self.parent.set_frozen_state
        if any(self.wallet.is_frozen(addr) for addr in addrs):
            menu.addAction(_("Unfreeze"), partial(freeze, addrs, False))
        if not all(self.wallet.is_frozen(addr) for addr in addrs):
            menu.addAction(_("Freeze"), partial(freeze, addrs, True))

        coins = self.wallet.get_spendable_coins(domain=addrs,
                                                config=self.config)
        if coins:
            menu.addAction(_("Spend from"),
                           partial(self.parent.spend_coins, coins))

        # Add Cash Accounts section at the end, if relevant
        if not multi_select:
            ca_list = item.data(0, self.DataRoles.cash_accounts)
            menu.addSeparator()
            a1 = menu.addAction(_("Cash Accounts"), lambda: None)
            a1.setDisabled(True)
            if ca_list:
                ca_default = self._ca_get_default(ca_list)
                for ca_info in ca_list:
                    ca_text = self.wallet.cashacct.fmt_info(
                        ca_info, ca_info.minimal_chash)
                    ca_text_em = self.wallet.cashacct.fmt_info(
                        ca_info, ca_info.minimal_chash, emoji=True)
                    m = menu.addMenu(ca_info.emoji + " " + ca_text)
                    a_ca_copy = m.addAction(
                        _("Copy Cash Account"),
                        lambda x=None, text=ca_text_em: doCopy(text))
                    a = m.addAction(
                        _("Details") + "...",
                        lambda x=None, ca_text=ca_text: cashacctqt.
                        cash_account_detail_dialog(self.parent, ca_text))
                    a = m.addAction(_("View registration tx") + "...",
                                    lambda x=None, ca=ca_info: self.parent.
                                    do_process_from_txid(txid=ca.txid))
                    a = a_def = m.addAction(_("Make default for address"),
                                            lambda x=None, ca=ca_info: self.
                                            _ca_set_default(ca, True))
                    if ca_info == ca_default:
                        if where_to_insert_dupe_copy_cash_account and a_ca_copy:
                            # insert a dupe of "Copy Cash Account" for the default cash account for this address in the top-level menu
                            menu.insertAction(
                                where_to_insert_dupe_copy_cash_account,
                                a_ca_copy)
                        m.setTitle(m.title() + "    " + "★")
                        a_def.setDisabled(True)
                        a_def.setCheckable(True)
                        a_def.setChecked(True)
                        a_def.setText(_("Is default for address"))
            else:
                a1.setText(_("No Cash Accounts"))
            a_new = menu.addAction(_("Register new..."),
                                   lambda x=None, addr=addr: self.parent.
                                   register_new_cash_account(addr))
            if not ca_list and __class__._cashacct_icon:
                # we only add an icon if there are no cashaccounts
                # for this address. This is because the icon alongside the emojis
                # made the ui look too "busy"...
                a_new.setIcon(__class__._cashacct_icon)

        run_hook('receive_menu', menu, addrs, self.wallet)
        menu.exec_(self.viewport().mapToGlobal(position))
예제 #16
0
    def create_menu(self, position):
        from electroncash.wallet import Multisig_Wallet
        is_multisig = isinstance(self.wallet, Multisig_Wallet)
        can_delete = self.wallet.can_delete_address()
        selected = self.selectedItems()
        multi_select = len(selected) > 1
        addrs = [item.data(0, self.DataRoles.address) for item in selected]
        if not addrs:
            return
        addrs = [addr for addr in addrs if isinstance(addr, Address)]

        menu = QMenu()

        where_to_insert_dupe_copy_cash_account = None

        def doCopy(txt):
            txt = txt.strip()
            self.parent.copy_to_clipboard(txt)

        col = self.currentColumn()
        column_title = self.headerItem().text(col)

        if not multi_select:
            item = self.itemAt(position)
            if not item:
                return
            if not addrs:
                item.setExpanded(not item.isExpanded())
                return
            addr = addrs[0]

            alt_copy_text, alt_column_title = None, None
            if col == 0:
                copy_text = addr.to_full_ui_string()
                if Address.FMT_UI == Address.FMT_LEGACY:
                    alt_copy_text, alt_column_title = addr.to_full_string(
                        Address.FMT_CASHADDR), _('Cash Address')
                else:
                    alt_copy_text, alt_column_title = addr.to_full_string(
                        Address.FMT_LEGACY), _('Legacy Address')
            else:
                copy_text = item.text(col)
            menu.addAction(
                _("Copy {}").format(column_title), lambda: doCopy(copy_text))
            a = menu.addAction(
                _('Details') + "...", lambda: self.parent.show_address(addr))
            if col == 0:
                where_to_insert_dupe_copy_cash_account = a
            if col in self.editable_columns:
                menu.addAction(
                    _("Edit {}").format(column_title),
                    lambda: self.editItem(
                        self.itemAt(
                            position
                        ),  # NB: C++ item may go away if this widget is refreshed while menu is up -- so need to re-grab and not store in lamba. See #953
                        col))
            menu.addAction(_("Request payment"),
                           lambda: self.parent.receive_at(addr))
            if self.wallet.can_export():
                menu.addAction(_("Private key"),
                               lambda: self.parent.show_private_key(addr))
            if not is_multisig and not self.wallet.is_watching_only():
                menu.addAction(_("Sign/verify message"),
                               lambda: self.parent.sign_verify_message(addr))
                menu.addAction(_("Encrypt/decrypt message"),
                               lambda: self.parent.encrypt_message(addr))
            if can_delete:
                menu.addAction(_("Remove from wallet"),
                               lambda: self.parent.remove_address(addr))
            addr_URL = web.BE_URL(self.config, 'addr', addr)
            if addr_URL:
                menu.addAction(_("View on block explorer"),
                               lambda: webopen(addr_URL))
        else:
            # multi-select
            if col > -1:
                texts, alt_copy, alt_copy_text = None, None, None
                if col == 0:  # address column
                    texts = [a.to_ui_string() for a in addrs]
                    # Add additional copy option: "Address, Balance (n)"
                    alt_copy = _("Copy {}").format(
                        _("Address") + ", " +
                        _("Balance")) + f" ({len(addrs)})"
                    alt_copy_text = "\n".join([
                        a.to_ui_string() + ", " + self.parent.format_amount(
                            sum(self.wallet.get_addr_balance(a)))
                        for a in addrs
                    ])
                else:
                    texts = [i.text(col).strip() for i in selected]
                    texts = [t for t in texts if t]  # omit empty items
                if texts:
                    copy_text = '\n'.join(texts)
                    menu.addAction(
                        _("Copy {}").format(column_title) + f" ({len(texts)})",
                        lambda: doCopy(copy_text))
                if alt_copy and alt_copy_text:
                    menu.addAction(alt_copy, lambda: doCopy(alt_copy_text))

        freeze = self.parent.set_frozen_state
        if any(self.wallet.is_frozen(addr) for addr in addrs):
            menu.addAction(_("Unfreeze"), partial(freeze, addrs, False))
        if not all(self.wallet.is_frozen(addr) for addr in addrs):
            menu.addAction(_("Freeze"), partial(freeze, addrs, True))

        coins = self.wallet.get_spendable_coins(domain=addrs,
                                                config=self.config)
        if coins:
            menu.addAction(_("Spend from"),
                           partial(self.parent.spend_coins, coins))

        # Add Cash Accounts section at the end, if relevant

        run_hook('receive_menu', menu, addrs, self.wallet)
        menu.exec_(self.viewport().mapToGlobal(position))
예제 #17
0
    def __init__(self, main_window, address, password):
        QDialog.__init__(self, parent=main_window)

        self.main_window = main_window
        self.wallet = main_window.wallet
        self.config = main_window.config

        #self.address = address  # address to spend from
        self.password = password # save for funding

        if address:
            self.fund_domain = [address]
            self.fund_change_address = address
            self.default_redeem_address = address
            self.entropy_address = address
        else:
            self.fund_domain = None
            self.fund_change_address = None
            self.default_redeem_address = self.wallet.get_unused_address()
            self.entropy_address = self.wallet.get_addresses()[0]

        # Extract private key
        index = self.wallet.get_address_index(self.entropy_address)
        key = self.wallet.keystore.get_private_key(index, password)
        privkey = int.from_bytes(key[0],'big')

        # Create contract derived from private key
        self.contract = SplitContract(privkey)

        self.setWindowTitle(_("OP_CHECKDATASIG Coin Splitting"))

        vbox = QVBoxLayout()
        self.setLayout(vbox)
        l = QLabel(_("Master address") + ": " + self.entropy_address.to_ui_string())
        l.setTextInteractionFlags(Qt.TextSelectableByMouse)
        vbox.addWidget(l)

        l = QLabel(_("Split contract") + ": " + self.contract.address.to_ui_string())
        l.setTextInteractionFlags(Qt.TextSelectableByMouse)
        vbox.addWidget(l)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)

        addr_URL = web.BE_URL(self.config, 'addr', self.contract.address)
        b = QPushButton(_("View on block explorer"))
        b.clicked.connect(lambda: webbrowser.open(addr_URL))
        hbox.addWidget(b)
        if not addr_URL:
            b.setDisabled(True)

        b = QPushButton(_("View redeem script..."))
        b.clicked.connect(self.showscript)
        hbox.addWidget(b)

        hbox.addStretch(1)


        l = QLabel("<b>%s</b>"%(_("Splittable coin creation/finding:")))
        vbox.addWidget(l)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)

        b = QPushButton(_("Create splittable coin"))
        b.clicked.connect(self.fund)
        hbox.addWidget(b)
        self.fund_button = b

        b = QPushButton("x")
        b.clicked.connect(self.search)
        hbox.addWidget(b)
        self.search_button = b

        hbox.addStretch(1)


        grid = QGridLayout()
        vbox.addLayout(grid)

        l = QLabel(_("TXID"))
        grid.addWidget(l, 0, 0)

        l = QLabel(_("Out#"))
        grid.addWidget(l, 0, 1)

        l = QLabel(_("Value (sats)"))
        grid.addWidget(l, 0, 2)

        self.fund_txid_e = QLineEdit()
        self.fund_txid_e.textEdited.connect(self.changed_coin)
        grid.addWidget(self.fund_txid_e, 1, 0)

        self.fund_txout_e = QLineEdit()
        self.fund_txout_e.setMaximumWidth(40)
        self.fund_txout_e.setAlignment(Qt.AlignRight)
        self.fund_txout_e.textEdited.connect(self.changed_coin)
        grid.addWidget(self.fund_txout_e, 1, 1)

        self.fund_value_e = QLineEdit()
        self.fund_value_e.setMaximumWidth(70)
        self.fund_value_e.setAlignment(Qt.AlignRight)
        self.fund_value_e.textEdited.connect(self.changed_coin)
        grid.addWidget(self.fund_value_e, 1, 2)


        l = QLabel("<b>%s</b>"%(_("Splittable coin spending:")))
        vbox.addWidget(l)

        self.option1_rb = QRadioButton(_("Only spend splittable coin"))
        self.option2_rb = QRadioButton()
        self.option3_rb = QRadioButton(_("Combine with all coins from wallet") + ' "%s"'%(self.wallet.basename()))
        vbox.addWidget(self.option1_rb)
        vbox.addWidget(self.option2_rb)
        vbox.addWidget(self.option3_rb)
        if self.fund_change_address:
            self.option2_rb.setText(_("Combine with all coins from address") + " %.10s..."%(self.fund_change_address.to_ui_string()))
            self.option2_rb.setChecked(True)
        else:
            self.option3_rb.setChecked(True)
            self.option2_rb.setHidden(True)


        hbox = QHBoxLayout()
        vbox.addLayout(hbox)
        l = QLabel(_("Output to:"))
        hbox.addWidget(l)
        self.redeem_address_e = QLineEdit()
        self.redeem_address_e.setText(self.default_redeem_address.to_full_ui_string())
        hbox.addWidget(self.redeem_address_e)


        hbox = QHBoxLayout()
        vbox.addLayout(hbox)

        b = QPushButton(_("Redeem with split (CDS chain only)"))
        b.clicked.connect(lambda: self.spend('redeem'))
        hbox.addWidget(b)
        self.redeem_button = b

        b = QPushButton(_("Refund (any chain)"))
        b.clicked.connect(lambda: self.spend('refund'))
        hbox.addWidget(b)
        self.refund_button = b

        self.changed_coin()

        self.search_done_signal.connect(self.search_done)
        self.search()
예제 #18
0
    def __init__(self, parent, plugin, wallet_name, address):
        QDialog.__init__(self, parent)
        self.main_window = parent
        self.wallet = parent.wallet
        self.plugin = plugin
        self.wallet_name = wallet_name
        self.config = parent.config
        self.password = None
        if self.wallet.has_password():
            self.main_window.show_error(
                _("Coinsplitter Plugin requires password. It will get access to your private keys."
                  ))
            self.password = parent.password_dialog()
            if not self.password:
                return

        if address:
            self.fund_domain = [address]
            self.fund_change_address = address
            self.default_redeem_address = address
            self.entropy_address = address
        else:
            self.fund_domain = None
            self.fund_change_address = None
            self.default_redeem_address = self.wallet.get_unused_address()
            self.entropy_address = self.wallet.get_addresses()[0]
        if not self.default_redeem_address:
            # self.wallet.get_unused_address() returns None for imported privkey wallets.
            self.main_window.show_error(
                _("For imported private key wallets, please open the coin splitter from the Addresses tab by right clicking on an address, instead of via the Tools menu."
                  ))
            return

        # Extract private key
        index = self.wallet.get_address_index(self.entropy_address)

        key = self.wallet.keystore.get_private_key(index, self.password)
        privkey = int.from_bytes(key[0], 'big')

        if isinstance(self.wallet, Multisig_Wallet):
            self.main_window.show_error(
                "Multi-sig wallet support is partial.\nThe splitter coin itself is *not* multisig and belongs to you alone (it cannot be redeemed by other parties)."
            )
        self.contract = SplitContract(privkey)

        self.setWindowTitle(_("OP_CHECKDATASIG Coin Splitting"))

        vbox = QVBoxLayout()
        self.setLayout(vbox)
        l = QLabel(
            _("Master address") + ": " + self.entropy_address.to_ui_string())
        l.setTextInteractionFlags(Qt.TextSelectableByMouse)
        vbox.addWidget(l)

        l = QLabel(
            _("Split contract") + ": " + self.contract.address.to_ui_string())
        l.setTextInteractionFlags(Qt.TextSelectableByMouse)
        vbox.addWidget(l)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)

        addr_URL = web.BE_URL(self.config, 'addr', self.contract.address)
        b = QPushButton(_("View on block explorer"))
        b.clicked.connect(lambda: webbrowser.open(addr_URL))
        hbox.addWidget(b)
        if not addr_URL:
            b.setDisabled(True)

        b = QPushButton(_("View redeem script..."))
        b.clicked.connect(self.showscript)
        hbox.addWidget(b)

        hbox.addStretch(1)

        l = QLabel("<b>%s</b>" % (_("Splittable coin creation/finding:")))
        vbox.addWidget(l)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)

        b = QPushButton(_("Create splittable coin"))
        b.clicked.connect(self.fund)
        hbox.addWidget(b)
        self.fund_button = b

        b = QPushButton("x")
        b.clicked.connect(self.search)
        hbox.addWidget(b)
        self.search_button = b

        hbox.addStretch(1)

        grid = QGridLayout()
        vbox.addLayout(grid)

        l = QLabel(_("TXID"))
        grid.addWidget(l, 0, 0)

        l = QLabel(_("Out#"))
        grid.addWidget(l, 0, 1)

        l = QLabel(_("Value (sats)"))
        grid.addWidget(l, 0, 2)

        self.fund_txid_e = QLineEdit()
        self.fund_txid_e.textEdited.connect(self.changed_coin)
        grid.addWidget(self.fund_txid_e, 1, 0)

        self.fund_txout_e = QLineEdit()
        self.fund_txout_e.setMaximumWidth(40)
        self.fund_txout_e.setAlignment(Qt.AlignRight)
        self.fund_txout_e.textEdited.connect(self.changed_coin)
        grid.addWidget(self.fund_txout_e, 1, 1)

        self.fund_value_e = QLineEdit()
        self.fund_value_e.setMaximumWidth(70)
        self.fund_value_e.setAlignment(Qt.AlignRight)
        self.fund_value_e.textEdited.connect(self.changed_coin)
        grid.addWidget(self.fund_value_e, 1, 2)

        l = QLabel("<b>%s</b>" % (_("Splittable coin spending:")))
        vbox.addWidget(l)

        self.option1_rb = QRadioButton(_("Only spend splittable coin"))
        self.option2_rb = QRadioButton()
        self.option3_rb = QRadioButton(
            _("Combine with all coins from wallet") + ' "%s"' %
            (self.wallet.basename()))
        vbox.addWidget(self.option1_rb)
        vbox.addWidget(self.option2_rb)
        vbox.addWidget(self.option3_rb)
        if self.fund_change_address:
            self.option2_rb.setText(
                _("Combine with all coins from address") + " %.10s..." %
                (self.fund_change_address.to_ui_string()))
            self.option2_rb.setChecked(True)
        else:
            self.option3_rb.setChecked(True)
            self.option2_rb.setHidden(True)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)
        l = QLabel(_("Output to:"))
        hbox.addWidget(l)
        self.redeem_address_e = QLineEdit()
        self.redeem_address_e.setText(
            self.default_redeem_address.to_full_ui_string())
        hbox.addWidget(self.redeem_address_e)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)

        b = QPushButton(_("Redeem with split (CDS chain only)"))
        b.clicked.connect(lambda: self.spend('redeem'))
        hbox.addWidget(b)
        self.redeem_button = b

        b = QPushButton(_("Refund (any chain)"))
        b.clicked.connect(lambda: self.spend('refund'))
        hbox.addWidget(b)
        self.refund_button = b

        self.changed_coin()

        self.search_done_signal.connect(self.search_done)
        self.search()

        self.show()
예제 #19
0
    def create_menu(self, position):
        if self.picker:
            # picker mode has no menu
            return
        from electroncash.wallet import Multisig_Wallet
        is_multisig = isinstance(self.wallet, Multisig_Wallet)
        can_delete = self.wallet.can_delete_address()
        selected = self.selectedItems()
        multi_select = len(selected) > 1
        addrs = [item.data(0, self.DataRoles.address) for item in selected]
        if not addrs:
            return
        addrs = [addr for addr in addrs if isinstance(addr, Address)]

        menu = QMenu()

        where_to_insert_dupe_copy_cash_account = None

        def doCopy(txt):
            txt = txt.strip()
            self.parent.copy_to_clipboard(txt)

        col = self.currentColumn()
        column_title = self.headerItem().text(col)

        if not multi_select:
            item = self.itemAt(position)
            if not item:
                return
            if not addrs:
                item.setExpanded(not item.isExpanded())
                return
            addr = addrs[0]

            alt_copy_text, alt_column_title = None, None
            if col == 0:
                copy_text = addr.to_full_ui_string()
                if Address.FMT_UI == Address.FMT_LEGACY:
                    alt_copy_text, alt_column_title = addr.to_full_string(Address.FMT_CASHADDR), _('Cash Address')
                else:
                    alt_copy_text, alt_column_title = addr.to_full_string(Address.FMT_LEGACY), _('Legacy Address')
            else:
                copy_text = item.text(col)
            menu.addAction(_("Copy {}").format(column_title), lambda: doCopy(copy_text))
            if alt_copy_text and alt_column_title:
                # Add 'Copy Legacy Address' and 'Copy Cash Address' alternates if right-click is on column 0
                menu.addAction(_("Copy {}").format(alt_column_title), lambda: doCopy(alt_copy_text))
            a = menu.addAction(_('Details') + "...", lambda: self.parent.show_address(addr))
            if col == 0:
                where_to_insert_dupe_copy_cash_account = a
            if col in self.editable_columns:
                menu.addAction(_("Edit {}").format(column_title), lambda: self.editItem(self.itemAt(position), # NB: C++ item may go away if this widget is refreshed while menu is up -- so need to re-grab and not store in lamba. See #953
                                                                                        col))
            a = menu.addAction(_("Request payment"), lambda: self.parent.receive_at(addr))
            if self.wallet.get_num_tx(addr) or self.wallet.has_payment_request(addr):
                # This address cannot be used for a payment request because
                # the receive tab will refuse to display it and will instead
                # create a request with a new address, if we were to call
                # self.parent.receive_at(addr). This is because the recieve tab
                # now strongly enforces no-address-reuse. See #1552.
                a.setDisabled(True)
            if self.wallet.can_export():
                menu.addAction(_("Private key"), lambda: self.parent.show_private_key(addr))
            if not is_multisig and not self.wallet.is_watching_only():
                menu.addAction(_("Sign/verify message") + "...", lambda: self.parent.sign_verify_message(addr))
                menu.addAction(_("Encrypt/decrypt message") + "...", lambda: self.parent.encrypt_message(addr))
            if can_delete:
                menu.addAction(_("Remove from wallet"), lambda: self.parent.remove_address(addr))
            addr_URL = web.BE_URL(self.config, web.ExplorerUrlParts.ADDR, addr)
            if addr_URL:
                menu.addAction(_("View on block explorer"), lambda: webopen(addr_URL))
        else:
            # multi-select
            if col > -1:
                texts, alt_copy, alt_copy_text = None, None, None
                if col == 0: # address column
                    texts = [a.to_full_ui_string() for a in addrs]
                    # Add additional copy option: "Address, Balance (n)"
                    alt_copy = _("Copy {}").format(_("Address") + ", " + _("Balance")) + f" ({len(addrs)})"
                    alt_copy_text = "\n".join([a.to_full_ui_string() + ", " + self.parent.format_amount(sum(self.wallet.get_addr_balance(a)))
                                              for a in addrs])
                else:
                    texts = [i.text(col).strip() for i in selected]
                    texts = [t for t in texts if t]  # omit empty items
                if texts:
                    copy_text = '\n'.join(texts)
                    menu.addAction(_("Copy {}").format(column_title) + f" ({len(texts)})", lambda: doCopy(copy_text))
                if alt_copy and alt_copy_text:
                    menu.addAction(alt_copy, lambda: doCopy(alt_copy_text))

        freeze = self.parent.set_frozen_state
        if any(self.wallet.is_frozen(addr) for addr in addrs):
            menu.addAction(_("Unfreeze"), partial(freeze, addrs, False))
        if not all(self.wallet.is_frozen(addr) for addr in addrs):
            menu.addAction(_("Freeze"), partial(freeze, addrs, True))

        coins = self.wallet.get_spendable_coins(domain = addrs, config = self.config)
        if coins:
            menu.addAction(_("Spend from"),
                           partial(self.parent.spend_coins, coins))

        run_hook('address_list_context_menu_setup', self, menu, addrs)

        # Add Cash Accounts section at the end, if relevant
        if not multi_select:
            ca_list = item.data(0, self.DataRoles.cash_accounts)
            menu.addSeparator()
            a1 = menu.addAction(_("Cash Accounts"), lambda: None)
            a1.setDisabled(True)
            if ca_list:
                ca_default = self._ca_get_default(ca_list)
                for ca_info in ca_list:
                    ca_text = self.wallet.cashacct.fmt_info(ca_info, ca_info.minimal_chash)
                    ca_text_em = self.wallet.cashacct.fmt_info(ca_info, ca_info.minimal_chash, emoji=True)
                    m = menu.addMenu(ca_info.emoji + " " + ca_text)
                    a_ca_copy = m.addAction(_("Copy Cash Account"), lambda x=None, text=ca_text_em: doCopy(text))
                    a = m.addAction(_("Details") + "...", lambda x=None,ca_text=ca_text: cashacctqt.cash_account_detail_dialog(self.parent, ca_text))
                    a = m.addAction(_("View registration tx") + "...", lambda x=None, ca=ca_info: self.parent.do_process_from_txid(txid=ca.txid))
                    a = a_def = m.addAction(_("Make default for address"), lambda x=None, ca=ca_info: self._ca_set_default(ca, True))
                    if ca_info == ca_default:
                        if where_to_insert_dupe_copy_cash_account and a_ca_copy:
                            # insert a dupe of "Copy Cash Account" for the default cash account for this address in the top-level menu
                            menu.insertAction(where_to_insert_dupe_copy_cash_account, a_ca_copy)
                        m.setTitle(m.title() + "    " + "★")
                        a_def.setDisabled(True)
                        a_def.setCheckable(True)
                        a_def.setChecked(True)
                        a_def.setText(_("Is default for address"))
            else:
                a1.setText(_("No Cash Accounts"))
            a_new = menu.addAction(_("Register new..."), lambda x=None, addr=addr: self.parent.register_new_cash_account(addr))
            a_new.setIcon(__class__._cashacct_icon)


        run_hook('receive_menu', menu, addrs, self.wallet)
        menu.exec_(self.viewport().mapToGlobal(position))
예제 #20
0
    def __init__(self, main_window, address, password):
        QDialog.__init__(self, parent=main_window)

        self.main_window = main_window
        self.wallet = main_window.wallet
        self.config = main_window.config

        #self.address = address  # address to spend from
        self.password = password  # save for funding

        if address:
            self.fund_domain = [address]
            self.fund_change_address = address
            self.default_redeem_address = address
            self.entropy_address = address
        else:
            self.fund_domain = None
            self.fund_change_address = None
            self.default_redeem_address = self.wallet.get_unused_address()
            self.entropy_address = self.wallet.get_addresses()[0]

        if not self.default_redeem_address:
            # self.wallet.get_unused_address() returns None for imported privkey wallets.
            self.close()
            self.main_window.show_error(
                _("For imported private key wallets, please open the coin splitter from the Addresses tab by right clicking on an address, instead of via the Tools menu."
                  ))
            return

        # Extract private key
        index = self.wallet.get_address_index(self.entropy_address)
        try:
            key = self.wallet.keystore.get_private_key(index, password)
        except:
            self.close()
            self.main_window.show_error(
                _("Coin splitter only works with wallets possessing private keys. See the User Guide for details on how to split other wallets' coins, at:"
                  ) +
                "\nhttps://github.com/markblundeberg/coinsplitter_checkdatasig/blob/master/doc/coinsplitter_user_guide.md"
            )
            return
        privkey = int.from_bytes(key[0], 'big')

        if isinstance(self.wallet, Multisig_Wallet):
            self.main_window.show_error(
                "Multi-sig wallet support is partial.\nThe splitter coin itself is *not* multisig and belongs to you alone (it cannot be redeemed by other parties)."
            )

        # Create contract derived from private key
        self.contract = SplitContract(privkey)

        self.setWindowTitle(_("OP_MUL Coin Splitting"))

        vbox = QVBoxLayout()
        self.setLayout(vbox)
        l = QLabel(
            _("Master address") + ": " + self.entropy_address.to_ui_string())
        l.setTextInteractionFlags(Qt.TextSelectableByMouse)
        vbox.addWidget(l)

        l = QLabel(
            _("Split contract") + ": " + self.contract.address.to_ui_string())
        l.setTextInteractionFlags(Qt.TextSelectableByMouse)
        vbox.addWidget(l)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)
        l1 = QLabel()
        l1.setPixmap(QIcon(":icons/warning").pixmap(QSize(40, 40)))
        hbox.addWidget(l1)
        l2 = QLabel(
            _("<b>EXPERTS ONLY!</b><br/>Coins sent to split contract cannot be recovered<br/>on chains that do not support OP_MUL."
              ))
        hbox.addWidget(l2)
        hbox.addStretch(1)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)

        addr_URL = web.BE_URL(self.config, 'addr', self.contract.address)
        b = QPushButton(_("View on block explorer"))
        b.clicked.connect(lambda: webbrowser.open(addr_URL))
        hbox.addWidget(b)
        if not addr_URL:
            b.setDisabled(True)

        b = QPushButton(_("View redeem script..."))
        b.clicked.connect(self.showscript)
        hbox.addWidget(b)

        hbox.addStretch(1)

        l = QLabel("<b>%s</b>" % (_("Splittable coin creation/finding:")))
        vbox.addWidget(l)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)

        b = QPushButton(_("Create splittable coin"))
        b.clicked.connect(self.fund)
        hbox.addWidget(b)
        self.fund_button = b

        b = QPushButton("x")
        b.clicked.connect(self.search)
        hbox.addWidget(b)
        self.search_button = b

        hbox.addStretch(1)

        grid = QGridLayout()
        vbox.addLayout(grid)

        l = QLabel(_("TXID"))
        grid.addWidget(l, 0, 0)

        l = QLabel(_("Out#"))
        grid.addWidget(l, 0, 1)

        l = QLabel(_("Value (sats)"))
        grid.addWidget(l, 0, 2)

        self.fund_txid_e = QLineEdit()
        self.fund_txid_e.textEdited.connect(self.changed_coin)
        grid.addWidget(self.fund_txid_e, 1, 0)

        self.fund_txout_e = QLineEdit()
        self.fund_txout_e.setMaximumWidth(40)
        self.fund_txout_e.setAlignment(Qt.AlignRight)
        self.fund_txout_e.textEdited.connect(self.changed_coin)
        grid.addWidget(self.fund_txout_e, 1, 1)

        self.fund_value_e = QLineEdit()
        self.fund_value_e.setMaximumWidth(70)
        self.fund_value_e.setAlignment(Qt.AlignRight)
        self.fund_value_e.textEdited.connect(self.changed_coin)
        grid.addWidget(self.fund_value_e, 1, 2)

        l = QLabel("<b>%s</b>" % (_("Splittable coin spending:")))
        vbox.addWidget(l)

        self.option1_rb = QRadioButton(_("Only spend splittable coin"))
        self.option2_rb = QRadioButton()
        self.option3_rb = QRadioButton(
            _("Combine with all coins from wallet") + ' "%s"' %
            (self.wallet.basename()))
        vbox.addWidget(self.option1_rb)
        vbox.addWidget(self.option2_rb)
        vbox.addWidget(self.option3_rb)
        if self.fund_change_address:
            self.option2_rb.setText(
                _("Combine with all coins from address") + " %.10s..." %
                (self.fund_change_address.to_ui_string()))
            self.option2_rb.setChecked(True)
        else:
            self.option3_rb.setChecked(True)
            self.option2_rb.setHidden(True)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)
        l = QLabel(_("Output to:"))
        hbox.addWidget(l)
        self.redeem_address_e = QLineEdit()
        self.redeem_address_e.setText(
            self.default_redeem_address.to_full_ui_string())
        hbox.addWidget(self.redeem_address_e)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)

        b = QPushButton(_("Redeem (MUL chain only)"))
        b.clicked.connect(self.spend)
        hbox.addWidget(b)
        self.redeem_button = b

        self.changed_coin()

        self.search_done_signal.connect(self.search_done)
        self.search()
        self.show()