Esempio n. 1
0
    def update_amounts(self, ):
        # Update the other two dependent amounts based on user-provided ones.
        # This uses floats.

        wbyprice = self.want_price_cb.isChecked()
        gbyprice = self.give_price_cb.isChecked()
        if wbyprice or gbyprice:
            if self.primaryprice is self.price1_e:
                try:
                    price = float(self.price1_e.text())
                    iprice = invert(price)
                except:
                    self.price2_e.setText('')
                    price = None
                else:
                    self.price2_e.setText(self.format_price(iprice))
            else:
                try:
                    iprice = float(self.price2_e.text())
                    price = invert(iprice)
                except:
                    self.price1_e.setText('')
                    price = None
                else:
                    self.price1_e.setText(self.format_price(price))
            if wbyprice:
                try:
                    a = price * 1e8 * float(self.give_amount_e.text())
                    self.want_amount_e.setText(
                        format_satoshis_plain_nofloat(a))
                except:
                    self.want_amount_e.setText('')
            else:
                try:
                    a = iprice * 1e8 * float(self.want_amount_e.text())
                    self.give_amount_e.setText(
                        format_satoshis_plain_nofloat(a))
                except:
                    self.give_amount_e.setText('')
        else:
            try:
                wa = float(self.want_amount_e.text())
                ga = float(self.give_amount_e.text())
            except:
                self.price1_e.setText('')
                self.price2_e.setText('')
            else:
                self.price1_e.setText(self.format_price(wa * invert(ga)))
                self.price2_e.setText(self.format_price(ga * invert(wa)))
Esempio n. 2
0
    def read_from_offerinfo(self, offerinfo):
        tick1 = offerinfo.want_ticker
        tick2 = offerinfo.give_ticker
        self.pi.want_crypto_cb.setCurrentIndex(
            crypto_list_by_bytes.index(tick1))
        self.pi.give_crypto_cb.setCurrentIndex(
            crypto_list_by_bytes.index(tick2))
        if offerinfo.want_amount is not None:
            self.pi.want_amount_e.setText(
                format_satoshis_plain_nofloat(offerinfo.want_amount))
        if offerinfo.give_amount is not None:
            self.pi.give_amount_e.setText(
                format_satoshis_plain_nofloat(offerinfo.give_amount))
        self.want_rtime = offerinfo.want_rtime
        self.give_rtime = offerinfo.give_rtime
        self.salt = offerinfo.salt

        self.pi.update_amounts()
Esempio n. 3
0
    def on_update(self):
        self.clear()
        self.coins, self.spent = self.halfswapcon.get_coins()
        self.unspent = self.coins.copy()
        for c in self.spent:
            self.unspent.pop(c)

        wallet = self.halfswapcon.wallet

        def conf_info(tx_hash):
            height, conf, timestamp = wallet.get_tx_height(tx_hash)
            status, status_str = wallet.get_tx_status(tx_hash, height, conf,
                                                      timestamp)
            if status not in self.statusIcons:
                self.statusIcons[status] = QIcon(":icons/" + TX_ICONS[status])
            return self.statusIcons[status], status, conf

        for c, (height, v) in self.coins.items():
            amount = format_satoshis_plain_nofloat(v)
            item = SortableTreeWidgetItem(['', amount, c, ''])
            icon, status, conf = conf_info(c.split(':')[0])

            item.setData(0, SortableTreeWidgetItem.DataRole, (status, conf))
            item.setToolTip(
                0,
                str(conf) + " confirmation" + ("s" if conf != 1 else ""))
            item.setIcon(0, icon)
            item.setFont(1, QFont(MONOSPACE_FONT))
            item.setFont(2, QFont(MONOSPACE_FONT))
            item.setData(0, Qt.UserRole, c)

            tx_hash_spent = self.spent.get(c)
            item.setData(3, Qt.UserRole, tx_hash_spent)

            if tx_hash_spent:
                icon, status, conf = conf_info(tx_hash_spent)
                item.setIcon(3, icon)
                item.setToolTip(
                    3,
                    str(conf) + " confirmation" + ("s" if conf != 1 else ""))

            self.addTopLevelItem(item)
Esempio n. 4
0
    def on_update(self):
        item = self.currentItem()
        current_tx = item.data(0, Qt.UserRole) if item else None
        self.clear()

        cmw = self.parent.cmw
        wallet = self.wallet
        chanaddress = cmw.address
        pmw = self.parent.pmw
        if pmw:
            mypubkey = pmw.key.pubkey
        else:
            mypubkey = None

        # internal function to be called within loop below
        def putitem(i, datastr):
            item = SortableTreeWidgetItem([
                '',
                status_str,
                'me' if from_me else from_pubkey[-3:].hex(),
                datastr,
            ])

            if status not in self.statusIcons:
                self.statusIcons[status] = QIcon(":icons/" + TX_ICONS[status])
            icon = self.statusIcons[status]
            item.setIcon(0, icon)
            item.setData(0, SortableTreeWidgetItem.DataRole, (status, conf))
            item.setToolTip(
                0,
                str(conf) + " confirmation" + ("s" if conf != 1 else ""))

            item.setData(0, Qt.UserRole, tx_hash)
            item.setData(2, Qt.UserRole, from_pubkey)
            item.setToolTip(3, '<p>%s</p>' % (escape(datastr), ))
            self.insertTopLevelItem(0, item)
            if current_tx == tx_hash:
                self.setCurrentItem(item)
            return item

        for tx_hash, height in wallet.get_address_history(chanaddress):
            info = cmw.messageinfo.get(tx_hash)
            if not info:
                continue
            height, conf, timestamp = wallet.get_tx_height(tx_hash)
            status, status_str = wallet.get_tx_status(tx_hash, height, conf,
                                                      timestamp)

            from_pubkey = info['src']
            from_me = (from_pubkey == mypubkey)

            if info['status'] == 'processing':
                # tx needs to be verified
                putitem(0, 'verifying')
                continue

            messagebytes = info.get('message')

            if messagebytes is None:
                putitem(0, '?')
                continue

            try:
                tag = messagebytes[:2]
                assert len(messagebytes) == 18
                if tag == b'\0\0':
                    amtw = int.from_bytes(messagebytes[2:10], 'big')
                    amtg = int.from_bytes(messagebytes[10:18], 'big')
                    nw = self.parent.n1
                    ng = self.parent.n2
                    data = (False, amtw, amtg)
                elif tag == b'\0\1':
                    amtg = int.from_bytes(messagebytes[2:10], 'big')
                    amtw = int.from_bytes(messagebytes[10:18], 'big')
                    ng = self.parent.n1
                    nw = self.parent.n2
                    data = (True, amtw, amtg)
                item = putitem(
                    0, 'Wants %s %s for %s %s' % (
                        format_satoshis_plain_nofloat(amtw),
                        nw,
                        format_satoshis_plain_nofloat(amtg),
                        ng,
                    ))
                item.setData(3, Qt.UserRole, data)
            except:
                item = putitem(0, 'raw:' + messagebytes.hex())
Esempio n. 5
0
 def setAmount(self, amount):
     if amount is None:
         self.setText(" ") # Space forces repaint in case units changed
     else:
         self.setText(format_satoshis_plain_nofloat(amount, self.decimal_point()))
    def mint_token(self, preview=False):
        decimals = int(self.token_dec.value())
        mint_baton_vout = 2 if self.token_baton_to_e.text(
        ) != '' and not self.token_fixed_supply_cb.isChecked() else None
        init_mint_qty = self.token_qty_e.get_amount()
        if init_mint_qty is None:
            self.show_message(_("Invalid token quantity entered."))
            return
        if init_mint_qty > (2**64) - 1:
            maxqty = format_satoshis_plain_nofloat((2**64) - 1, decimals)
            self.show_message(
                _("Token output quantity is too large. Maximum %s.") %
                (maxqty, ))
            return

        outputs = []
        try:
            token_id_hex = self.token_id_e.text()
            token_type = self.wallet.token_types[token_id_hex]['class']
            slp_op_return_msg = buildMintOpReturnOutput_V1(
                token_id_hex, mint_baton_vout, init_mint_qty, token_type)
            outputs.append(slp_op_return_msg)
        except OPReturnTooLarge:
            self.show_message(
                _("Optional string text causiing OP_RETURN greater than 223 bytes."
                  ))
            return
        except Exception as e:
            traceback.print_exc(file=sys.stdout)
            self.show_message(str(e))
            return

        try:
            addr = self.parse_address(self.token_pay_to_e.text())
            outputs.append((TYPE_ADDRESS, addr, 546))
        except:
            self.show_message(
                _("Enter a Mint Receiver Address in SLP address format."))
            return

        if not self.token_fixed_supply_cb.isChecked():
            try:
                addr = self.parse_address(self.token_baton_to_e.text())
                outputs.append((TYPE_ADDRESS, addr, 546))
            except:
                self.show_message(
                    _("Enter a Baton Address in SLP address format."))
                return

        # IMPORTANT: set wallet.sedn_slpTokenId to None to guard tokens during this transaction
        self.main_window.token_type_combo.setCurrentIndex(0)
        assert self.main_window.slp_token_id == None

        coins = self.main_window.get_coins()
        fee = None

        try:
            baton_input = self.main_window.wallet.get_slp_token_baton(
                self.token_id_e.text())
        except SlpNoMintingBatonFound as e:
            self.show_message(_("No baton exists for this token."))
            return

        desired_fee_rate = 1.0  # sats/B, just init this value for paranoia
        try:
            tx = self.main_window.wallet.make_unsigned_transaction(
                coins, outputs, self.main_window.config, fee, None)
            desired_fee_rate = tx.get_fee() / tx.estimated_size(
            )  # remember the fee coin chooser & wallet gave us as a fee rate so we may use it below after adding baton to adjust fee downward to this rate.
        except NotEnoughFunds:
            self.show_message(_("Insufficient funds"))
            return
        except ExcessiveFee:
            self.show_message(_("Your fee is too high.  Max is 50 sat/byte."))
            return
        except BaseException as e:
            traceback.print_exc(file=sys.stdout)
            self.show_message(str(e))
            return

        # Find & Add baton to tx inputs
        try:
            baton_utxo = self.main_window.wallet.get_slp_token_baton(
                self.token_id_e.text())
        except SlpNoMintingBatonFound:
            self.show_message(
                _("There is no minting baton found for this token."))
            return

        tx.add_inputs([baton_utxo])
        for txin in tx._inputs:
            self.main_window.wallet.add_input_info(txin)

        def tx_adjust_change_amount_based_on_baton_amount(
                tx, desired_fee_rate):
            ''' adjust change amount (based on amount added from baton) '''
            if len(tx._outputs) not in (3, 4):
                # no change, or a tx shape we don't know about
                self.print_error(f"Unkown tx shape, not adjusting fee!")
                return
            chg = tx._outputs[
                -1]  # change is always the last output due to BIP_LI01 sorting
            assert len(chg) == 3, "Expected tx output to be of length 3"
            if not self.main_window.wallet.is_mine(chg[1]):
                self.print_error(
                    f"Unkown change address {chg[1]}, not adjusting fee!")
                return
            chg_amt = chg[2]
            if chg_amt <= 546:
                # if change is 546, then the BIP_LI01 sorting doesn't guarantee
                # change output is at the end.. so we don't know which was
                # changed based on the heuristics this code relies on.. so..
                # Abort! Abort!
                self.print_error(
                    "Could not determine change output, not adjusting fee!")
                return
            curr_fee, curr_size = tx.get_fee(), tx.estimated_size()
            fee_rate = curr_fee / curr_size
            diff = math.ceil((fee_rate - desired_fee_rate) * curr_size)
            if diff > 0:
                tx._outputs[-1] = (chg[0], chg[1], chg[2] + diff
                                   )  # adjust the output
                self.print_error(
                    f"Added {diff} sats to change to maintain fee rate of {desired_fee_rate:0.2f}, new fee: {tx.get_fee()}"
                )

        tx_adjust_change_amount_based_on_baton_amount(tx, desired_fee_rate)

        if preview:
            show_transaction(tx, self.main_window, None, False, self)
            return

        msg = []

        if self.main_window.wallet.has_password():
            msg.append("")
            msg.append(_("Enter your password to proceed"))
            password = self.main_window.password_dialog('\n'.join(msg))
            if not password:
                return
        else:
            password = None

        tx_desc = None

        def sign_done(success):
            if success:
                if not tx.is_complete():
                    show_transaction(tx, self.main_window, None, False, self)
                    self.main_window.do_clear()
                else:
                    self.main_window.broadcast_transaction(tx, tx_desc)

        self.main_window.sign_tx_with_password(tx, sign_done, password)

        self.mint_button.setDisabled(True)
        self.close()
Esempio n. 7
0
    def mint_token(self, preview=False):
        decimals = int(self.token_dec.value())
        mint_baton_vout = 2 if self.token_baton_to_e.text(
        ) != '' and not self.token_fixed_supply_cb.isChecked() else None
        init_mint_qty = self.token_qty_e.get_amount()
        if init_mint_qty is None:
            self.show_message(_("Invalid token quantity entered."))
            return
        if init_mint_qty > (2**64) - 1:
            maxqty = format_satoshis_plain_nofloat((2**64) - 1, decimals)
            self.show_message(
                _("Token output quantity is too large. Maximum %s.") %
                (maxqty, ))
            return

        outputs = []
        try:
            token_id_hex = self.token_id_e.text()
            slp_op_return_msg = buildMintOpReturnOutput_V1(
                token_id_hex, mint_baton_vout, init_mint_qty)
            outputs.append(slp_op_return_msg)
        except OPReturnTooLarge:
            self.show_message(
                _("Optional string text causiing OP_RETURN greater than 223 bytes."
                  ))
            return
        except Exception as e:
            traceback.print_exc(file=sys.stdout)
            self.show_message(str(e))
            return

        try:
            addr = self.parse_address(self.token_pay_to_e.text())
            outputs.append((TYPE_ADDRESS, addr, 546))
        except:
            self.show_message(
                _("Enter a Mint Receiver Address in SLP address format."))
            return

        if not self.token_fixed_supply_cb.isChecked():
            try:
                addr = self.parse_address(self.token_baton_to_e.text())
                outputs.append((TYPE_ADDRESS, addr, 546))
            except:
                self.show_message(
                    _("Enter a Baton Address in SLP address format."))
                return

        # IMPORTANT: set wallet.sedn_slpTokenId to None to guard tokens during this transaction
        self.main_window.token_type_combo.setCurrentIndex(0)
        assert self.main_window.slp_token_id == None

        coins = self.main_window.get_coins()
        fee = None

        try:
            baton_input = self.main_window.wallet.get_slp_token_baton(
                self.token_id_e.text())
        except SlpNoMintingBatonFound as e:
            self.show_message(_("No baton exists for this token."))
            return

        try:
            tx = self.main_window.wallet.make_unsigned_transaction(
                coins, outputs, self.main_window.config, fee, None)
        except NotEnoughFunds:
            self.show_message(_("Insufficient funds"))
            return
        except ExcessiveFee:
            self.show_message(_("Your fee is too high.  Max is 50 sat/byte."))
            return
        except BaseException as e:
            traceback.print_exc(file=sys.stdout)
            self.show_message(str(e))
            return

        # Find & Add baton to tx inputs
        try:
            baton_utxo = self.main_window.wallet.get_slp_token_baton(
                self.token_id_e.text())
        except SlpNoMintingBatonFound:
            self.show_message(
                _("There is no minting baton found for this token."))
            return

        tx.add_inputs([baton_utxo])
        for txin in tx._inputs:
            self.main_window.wallet.add_input_info(txin)

        # TODO: adjust change amount (based on amount added from baton)

        if preview:
            show_transaction(tx, self.main_window, None, False, self)
            return

        msg = []

        if self.main_window.wallet.has_password():
            msg.append("")
            msg.append(_("Enter your password to proceed"))
            password = self.main_window.password_dialog('\n'.join(msg))
            if not password:
                return
        else:
            password = None

        tx_desc = None

        def sign_done(success):
            if success:
                if not tx.is_complete():
                    show_transaction(tx, self.main_window, None, False, self)
                    self.main_window.do_clear()
                else:
                    self.main_window.broadcast_transaction(tx, tx_desc)

        self.main_window.sign_tx_with_password(tx, sign_done, password)

        self.mint_button.setDisabled(True)
        self.close()
    def create_token(self, preview=False, multisig_tx_to_sign=None):
        token_name = self.token_name_e.text(
        ) if self.token_name_e.text() != '' else None
        ticker = self.token_ticker_e.text(
        ) if self.token_ticker_e.text() != '' else None
        token_document_url = self.token_url_e.text(
        ) if self.token_url_e.text() != '' else None
        token_document_hash_hex = self.token_dochash_e.text(
        ) if self.token_dochash_e.text() != '' else None
        decimals = int(self.token_ds_e.value())
        mint_baton_vout = 2 if self.token_baton_to_e.text(
        ) != '' and not self.token_fixed_supply_cb.isChecked() else None

        init_mint_qty = self.token_qty_e.get_amount()
        if init_mint_qty is None:
            self.show_message(_("Invalid token quantity entered."))
            return
        if init_mint_qty > (2**64) - 1:
            maxqty = format_satoshis_plain_nofloat((2**64) - 1, decimals)
            self.show_message(
                _("Token output quantity is too large. Maximum %s.") %
                (maxqty, ))
            return

        if token_document_hash_hex != None:
            if len(token_document_hash_hex) != 64:
                self.show_message(
                    _("Token document hash must be a 32 byte hexidecimal string or left empty."
                      ))
                return

        outputs = []
        try:
            slp_op_return_msg = buildGenesisOpReturnOutput_V1(
                ticker,
                token_name,
                token_document_url,
                token_document_hash_hex,
                decimals,
                mint_baton_vout,
                init_mint_qty,
                token_type=self.token_type)
            outputs.append(slp_op_return_msg)
        except OPReturnTooLarge:
            self.show_message(
                _("Optional string text causiing OP_RETURN greater than 223 bytes."
                  ))
            return
        except Exception as e:
            traceback.print_exc(file=sys.stdout)
            self.show_message(str(e))
            return

        try:
            addr = self.parse_address(self.token_pay_to_e.text())
            outputs.append((TYPE_ADDRESS, addr, 546))
        except:
            self.show_message(
                _("Must have Receiver Address in simpleledger format."))
            return

        if not self.token_fixed_supply_cb.isChecked(
        ) and not self.nft_parent_id:
            try:
                addr = self.parse_address(self.token_baton_to_e.text())
                outputs.append((TYPE_ADDRESS, addr, 546))
            except:
                self.show_message(
                    _("Must have Baton Address in simpleledger format."))
                return

        # IMPORTANT: set wallet.sedn_slpTokenId to None to guard tokens during this transaction
        self.main_window.token_type_combo.setCurrentIndex(0)
        assert self.main_window.slp_token_id == None

        coins = self.main_window.get_coins()
        fee = None

        try:
            selected_coin = None
            if self.nft_parent_id and multisig_tx_to_sign:
                tx = multisig_tx_to_sign
                parent_txo_hash = multisig_tx_to_sign.inputs(
                )[0]['prevout_hash']
                parent_txo_n = multisig_tx_to_sign.inputs()[0]['prevout_n']
                slp_coins = self.wallet.get_slp_utxos(
                    self.nft_parent_id,
                    domain=None,
                    exclude_frozen=True,
                    confirmed_only=self.main_window.config.get(
                        'confirmed_only', False),
                    slp_include_invalid=False,
                    slp_include_baton=False)
                try:
                    for coin in slp_coins:
                        if coin['prevout_hash'] == parent_txo_hash \
                            and coin['prevout_n'] == parent_txo_n \
                            and coin['token_value'] != "MINT_BATON":
                            selected_coin = coin
                            # total_burn_amt += coin['token_value']
                except KeyError:
                    pass
            elif self.nft_parent_id:
                selected_coin = get_nft_parent_coin(self.nft_parent_id,
                                                    self.main_window)
                if selected_coin:
                    tx = self.main_window.wallet.make_unsigned_transaction(
                        coins,
                        outputs,
                        self.main_window.config,
                        fee,
                        None,
                        mandatory_coins=[selected_coin])
                else:
                    raise Exception(
                        'Must have a parent NFT coin with value of 1 first.')
            else:
                tx = self.main_window.wallet.make_unsigned_transaction(
                    coins, outputs, self.main_window.config, fee, None)
        except NotEnoughFunds:
            self.show_message(_("Insufficient funds"))
            return
        except ExcessiveFee:
            self.show_message(_("Your fee is too high.  Max is 50 sat/byte."))
            return
        except BaseException as e:
            traceback.print_exc(file=sys.stdout)
            self.show_message(str(e))
            return

        if preview:
            if self.nft_parent_id:
                show_transaction(tx,
                                 self.main_window,
                                 None,
                                 False,
                                 self,
                                 slp_coins_to_burn=[selected_coin],
                                 slp_amt_to_burn=1)
            else:
                show_transaction(tx, self.main_window, None, False, self)
            return

        msg = []

        if self.main_window.wallet.has_password():
            msg.append("")
            msg.append(_("Enter your password to proceed"))
            password = self.main_window.password_dialog('\n'.join(msg))
            if not password:
                return
        else:
            password = None
        tx_desc = None

        def sign_done(success):
            if success:
                if not tx.is_complete():
                    show_transaction(tx, self.main_window, None, False, self)
                    self.main_window.do_clear()
                else:
                    token_id = tx.txid()
                    if self.token_name_e.text() == '':
                        wallet_name = tx.txid()[0:5]
                    else:
                        wallet_name = self.token_name_e.text()[0:20]
                    # Check for duplication error
                    d = self.wallet.token_types.get(token_id)
                    for tid, d in self.wallet.token_types.items():
                        if d['name'] == wallet_name and tid != token_id:
                            wallet_name = wallet_name + "-" + token_id[:3]
                            break
                    self.broadcast_transaction(tx, self.token_name_e.text(),
                                               wallet_name)

        if self.nft_parent_id:
            self.sign_tx_with_password(tx,
                                       sign_done,
                                       password,
                                       slp_coins_to_burn=[selected_coin],
                                       slp_amt_to_burn=1)
        else:
            self.sign_tx_with_password(tx, sign_done, password)
Esempio n. 9
0
    def __init__(self, app, config, swapper, amount1, amount2):
        # probably need config
        # top level window
        QDialog.__init__(self, parent=None)
        #        self.wallet = parent.wallet

        self.app = app
        self.config = config
        self.swapper = swapper

        currency1 = swapper.network1.currency
        currency2 = swapper.network2.currency

        shownamount1 = format_satoshis_plain_nofloat(amount1) + " " + currency1
        shownamount2 = format_satoshis_plain_nofloat(amount2) + " " + currency2
        youstr = _("You agreed to offer %s at this address:")
        themstr = _("They agreed to offer %s at this address:")

        self.setWindowTitle(_("Atomic Swap"))

        self.setMinimumWidth(800)
        vbox = QVBoxLayout()
        self.setLayout(vbox)
        self.party_info_label = QLabel(
            _("You are party A.") if swapper.
            i_am_party_A else _("You are party B."))
        self.party_info_label.setAlignment(Qt.AlignCenter)
        self.party_info_label.setTextFormat(Qt.RichText)
        vbox.addWidget(self.party_info_label)
        self.phase_info_label = QLabel("")
        self.phase_info_label.setAlignment(Qt.AlignCenter)
        self.phase_info_label.setTextFormat(Qt.RichText)
        vbox.addWidget(self.phase_info_label)
        self.instruction_label = QLabel("")
        self.instruction_label.setAlignment(Qt.AlignCenter)
        self.instruction_label.setTextFormat(Qt.RichText)
        vbox.addWidget(self.instruction_label)

        ##
        # Split parts below
        ##

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)

        vboxleft = QVBoxLayout()
        hbox.addLayout(vboxleft)
        vboxright = QVBoxLayout()
        hbox.addLayout(vboxright)

        vboxleft.addWidget(
            QLabel(
                (youstr if swapper.i_am_party_A else themstr) % shownamount1))
        addr_e = QLineEdit(str(self.swapper.contract1.address))
        addr_e.setReadOnly(True)
        vboxleft.addWidget(addr_e)

        vboxleft.addWidget(QLabel(_("Coins at this address") + ':'))
        self.leftutxolist = SwapUTXOList(self, swapper.sc1)
        vboxleft.addWidget(self.leftutxolist)

        self.time_remaining_1_e = QLabel()
        vboxleft.addWidget(self.time_remaining_1_e)

        hbox = QHBoxLayout()
        vboxleft.addLayout(hbox)

        if swapper.i_am_party_A:
            b = QPushButton(_("Refund"))
            b.clicked.connect(self.refund)
            hbox.addWidget(b)
        else:
            self.redeem_button = QPushButton(_("Redeem"))
            self.redeem_button.clicked.connect(self.redeem)
            hbox.addWidget(self.redeem_button)

        vboxright.addWidget(
            QLabel(
                (themstr if swapper.i_am_party_A else youstr) % shownamount2))
        addr_e = QLineEdit(str(self.swapper.contract2.address))
        addr_e.setReadOnly(True)
        vboxright.addWidget(addr_e)

        vboxright.addWidget(QLabel(_("Coins at this address") + ':'))
        self.rightutxolist = SwapUTXOList(self, swapper.sc2)
        vboxright.addWidget(self.rightutxolist)

        self.time_remaining_2_e = QLabel()
        vboxright.addWidget(self.time_remaining_2_e)

        hbox = QHBoxLayout()
        vboxright.addLayout(hbox)

        if swapper.i_am_party_A:
            self.redeem_button = QPushButton(_("Redeem"))
            self.redeem_button.clicked.connect(self.redeem)
            hbox.addWidget(self.redeem_button)
        else:
            b = QPushButton(_("Refund"))
            b.clicked.connect(self.refund)
            hbox.addWidget(b)

        swapper.network1.register_callback(self.leftutxolist.on_network,
                                           ['updated', 'verified'])
        swapper.network2.register_callback(self.rightutxolist.on_network,
                                           ['updated', 'verified'])

        self.timer = QTimer()
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.timed_update)
        self.timer.start()

        self.timed_update()  # call once to start
Esempio n. 10
0
    def on_update(self):
        item = self.currentItem()
        current_tx, current_i = item.data(0, Qt.UserRole) if item else (None,
                                                                        None)
        self.clear()

        wallet = self.parent.wallet
        pmw = self.parent.pmw
        key = self.parent.key
        mypubkey = key.pubkey
        myaddress = key.address

        # internal function to be called within loop below
        def putitem(i, typ, datastr):
            if to_me:
                to_str = 'me'
            elif to_pubkey:
                to_str = to_pubkey[-3:].hex()
            else:
                to_str = 'unk'
            item = SortableTreeWidgetItem([
                '',
                status_str,
                'me' if from_me else from_pubkey[-3:].hex(),
                to_str,
                typ,
                datastr,
            ])

            if status not in self.statusIcons:
                self.statusIcons[status] = QIcon(":icons/" + TX_ICONS[status])
            icon = self.statusIcons[status]
            item.setIcon(0, icon)
            item.setData(0, SortableTreeWidgetItem.DataRole, (status, conf))
            item.setToolTip(
                0,
                str(conf) + " confirmation" + ("s" if conf != 1 else ""))

            item.setData(0, Qt.UserRole, (tx_hash, i))
            item.setData(2, Qt.UserRole, from_pubkey)
            item.setData(3, Qt.UserRole, to_pubkey)
            item.setToolTip(5, '<p>%s</p>' % (escape(datastr), ))
            self.insertTopLevelItem(0, item)
            if current_tx == tx_hash and current_i == i:
                self.setCurrentItem(item)
            return item

        for tx_hash, height in wallet.get_address_history(myaddress):
            info = pmw.messageinfo.get(tx_hash)
            if not info:
                continue
            height, conf, timestamp = wallet.get_tx_height(tx_hash)
            status, status_str = wallet.get_tx_status(tx_hash, height, conf,
                                                      timestamp)

            from_pubkey = info['src']
            dest_addr = info['dst']
            from_me = (from_pubkey == mypubkey)
            to_me = (dest_addr == myaddress)

            if to_me:
                to_pubkey = mypubkey
            else:
                to_pubkey = pmw.known_pubkeys.get(dest_addr)

            if info['status'] == 'processing':
                # tx needs to be verified
                putitem(0, '-', 'verifying')
                continue

            messagebytes = info.get('message')

            if messagebytes is None:
                putitem(0, '?', '')
                continue

            try:
                osm = openswap.OpenSwapMessage.from_bytes(messagebytes)
            except Exception as e:
                try:
                    message = repr(messagebytes.decode('utf8'))
                except:
                    message = messagebytes.hex()
                putitem(0, 'raw', "raw: " + message)
                continue
            for i, pak in enumerate(osm.packets):
                if isinstance(pak, openswap.PacketPad):  # skip padding
                    continue
                if isinstance(pak, openswap.PacketOffer) and not from_me:
                    # save incoming offer packets
                    self.incoming_offers[(from_pubkey, pak.offer_info)] = pak
                try:
                    datastr = pak.to_ui_string()
                except Exception as e:
                    print(e)
                    datastr = str(pak)
                if isinstance(pak, openswap.PacketOffer):
                    remain = pak.expire_time - time.time()
                    if remain > 0:
                        expstr = _("%d minutes remain") % (round(remain / 60.))
                    else:
                        expstr = _("expired")
                    if from_me:
                        fmtstr = _('You offer %s%s to get %s%s (%s)')
                    else:
                        fmtstr = _('They offer %s%s to get %s%s (%s)')
                    datastr = fmtstr % (
                        format_satoshis_plain_nofloat(
                            pak.offer_info.give_amount),
                        pak.offer_info.give_ticker.decode('utf8'),
                        format_satoshis_plain_nofloat(
                            pak.offer_info.want_amount),
                        pak.offer_info.want_ticker.decode('utf8'),
                        expstr,
                    )

                item = putitem(i, 'OS', datastr)
                item.setData(5, Qt.UserRole, pak)