Пример #1
0
    def check_text(self):
        self.errors = []
        if self.is_pr:
            return
        # filter out empty lines
        lines = [i for i in self.lines() if i]
        outputs = []
        total = 0
        self.payto_address = None
        if len(lines) == 1:
            data = lines[0]
            if ':' in data and '?' in data and len(data) > 35:
                try: 
                    self.scan_f(data)
                except AddressError as e:
                    self.errors.append((0, str(e)))
                else:
                    return
            elif ':' not in data and len(data) > 35:
                self.setText(Address.prefix_from_address_string(data) + ':' + data)
                return
            try:
                self.parse_address(data)
            except Exception as e:
                self.errors.append((0, str(e)))
            try:
                self.payto_address = self.parse_output(data)
                self.address_string_for_slp_check = data
            except:
                self.address_string_for_slp_check = ''
            if self.payto_address:
                self.win.lock_amount(False)
                return

        is_max = False
        for i, line in enumerate(lines):
            try:
                _type, to_address, amount = self.parse_address_and_amount(line)
            except Exception as e:
                if len(self.errors) < 1:
                    self.errors.append((i, line.strip()))
                continue

            outputs.append((_type, to_address, amount))
            if amount == '!':
                is_max = True
            else:
                total += amount

        self.win.max_button.setChecked(is_max)
        self.outputs = outputs
        self.payto_address = None

        if self.win.max_button.isChecked():
            self.win.do_update_fee()
        else:
            """
            The following line is commented out for SLP.
            If this line is not commented out then the amount field will
            always be reset to 0 when the address text is edited.
            For SLP, an amount of 546 sat should be left in the amount_e field.
            """
            #self.amount_edit.setAmount(total if outputs else None)
            self.win.lock_amount(total or len(lines)>1)
    def check_text(self):
        self.errors = []
        if self.is_pr:
            return
        # filter out empty lines
        lines = [i for i in self.lines() if i]
        outputs = []
        total = 0
        self.payto_address = None
        self.cointext = None
        if len(lines) == 1:
            data = lines[0]
            if ':' in data and '?' in data and len(data) > 35:
                try:
                    self.scan_f(data)
                except AddressError as e:
                    self.errors.append((0, str(e)))
                else:
                    return
            elif ':' not in data and len(data) > 35:
                self.setText(
                    Address.prefix_from_address_string(data) + ':' + data)
                return
            try:
                self.parse_address(data)
            except Exception as e:
                self.errors.append((0, str(e)))
            try:
                self.payto_address = self.parse_output(data)
                self.address_string_for_slp_check = data
            except:
                self.address_string_for_slp_check = ''
                try:
                    self.cointext = self.parse_cointext(data)
                except:
                    pass
            if self.payto_address or self.cointext:
                self.win.lock_amount(False)
                return

        is_max = False
        for i, line in enumerate(lines):
            try:
                _type, to_address, amount = self.parse_address_and_amount(line)
            except Exception as e:
                if len(self.errors) < 1:
                    self.errors.append((i, line.strip()))
                continue

            outputs.append((_type, to_address, amount))
            if amount == '!':
                is_max = True
            else:
                total += amount

        self.win.max_button.setChecked(is_max)
        self.outputs = outputs
        self.payto_address = None

        if self.win.max_button.isChecked():
            self.win.do_update_fee()
        else:
            if not self.win.slp_token_id:
                self.amount_edit.setAmount(total if outputs else None)
            self.win.lock_amount(total or len(lines) > 1)
    def __init__(self, main_window, *, nft_parent_id=None):
        #self.provided_token_name = token_name
        # We want to be a top-level window
        QDialog.__init__(self, parent=None)
        from .main_window import ElectrumWindow

        assert isinstance(main_window, ElectrumWindow)
        main_window._slp_dialogs.add(self)
        finalization_print_error(self)  # track object lifecycle

        self.main_window = main_window
        self.wallet = main_window.wallet
        self.config = main_window.config
        self.network = main_window.network
        self.app = main_window.app
        self.nft_parent_id = nft_parent_id
        if nft_parent_id != None:
            self.token_type = 65
        else:
            self.token_type = 1

        if self.main_window.gui_object.warn_if_no_network(self.main_window):
            return

        self.setWindowTitle(_("Create a New Token"))

        vbox = QVBoxLayout()
        self.setLayout(vbox)

        grid = QGridLayout()
        grid.setColumnStretch(1, 1)
        vbox.addLayout(grid)
        row = 0

        msg = _(
            'An optional name string embedded in the token genesis transaction.'
        )
        grid.addWidget(HelpLabel(_('Token Name (optional):'), msg), row, 0)
        self.token_name_e = QLineEdit()
        grid.addWidget(self.token_name_e, row, 1)
        row += 1

        msg = _(
            'An optional ticker symbol string embedded into the token genesis transaction.'
        )
        grid.addWidget(HelpLabel(_('Ticker Symbol (optional):'), msg), row, 0)
        self.token_ticker_e = QLineEdit()
        self.token_ticker_e.setFixedWidth(110)
        self.token_ticker_e.textChanged.connect(self.upd_token)
        grid.addWidget(self.token_ticker_e, row, 1)
        row += 1

        msg = _(
            'An optional URL string embedded into the token genesis transaction.'
        )
        grid.addWidget(HelpLabel(_('Document URL (optional):'), msg), row, 0)
        self.token_url_e = QLineEdit()
        self.token_url_e.setFixedWidth(560)
        self.token_url_e.textChanged.connect(self.upd_token)
        grid.addWidget(self.token_url_e, row, 1)
        row += 1

        msg = _('An optional hash hexidecimal bytes embedded into the token genesis transaction for hashing') \
                                                    + 'the document file contents at the URL provided above.'
        grid.addWidget(HelpLabel(_('Document Hash (optional):'), msg), row, 0)
        self.token_dochash_e = QLineEdit()
        self.token_dochash_e.setInputMask(
            "HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH")
        self.token_dochash_e.setFixedWidth(560)
        self.token_dochash_e.textChanged.connect(self.upd_token)
        grid.addWidget(self.token_dochash_e, row, 1)
        row += 1

        msg = _('Sets the number of decimals of divisibility for this token (embedded into genesis).') \
                + '\n\n' \
                + _('Each 1 token is divisible into 10^(decimals) base units, and internally in the protocol') \
                + _('the token amounts are represented as 64-bit integers measured in these base units.')
        grid.addWidget(HelpLabel(_('Decimal Places:'), msg), row, 0)
        self.token_ds_e = QDoubleSpinBox()
        self.token_ds_e.setRange(0, 9)
        self.token_ds_e.setDecimals(0)
        self.token_ds_e.setFixedWidth(50)
        self.token_ds_e.valueChanged.connect(self.upd_token)
        grid.addWidget(self.token_ds_e, row, 1)
        row += 1

        msg = _('The number of tokens created during token genesis transaction,') \
                                    + _('send to the receiver address provided below.')
        if nft_parent_id == None:
            self.token_qty_label = HelpLabel(_('Token Quantity:'), msg)
        else:
            self.token_qty_label = HelpLabel(_('Number of Child NFTs:'), msg)
        grid.addWidget(self.token_qty_label, row, 0)
        self.token_qty_e = SLPAmountEdit('', 0)
        self.token_qty_e.setFixedWidth(200)
        self.token_qty_e.textChanged.connect(self.check_token_qty)
        grid.addWidget(self.token_qty_e, row, 1)
        row += 1

        msg = _(
            'The \'simpleledger:\' formatted bitcoin address for the genesis receiver of all genesis tokens.'
        )
        grid.addWidget(HelpLabel(_('Token Receiver Address:'), msg), row, 0)
        self.token_pay_to_e = ButtonsLineEdit()
        self.token_pay_to_e.setFixedWidth(560)
        grid.addWidget(self.token_pay_to_e, row, 1)
        row += 1

        self.token_fixed_supply_cb = cb = QCheckBox(_('Fixed Supply'))
        self.token_fixed_supply_cb.setChecked(True)
        grid.addWidget(self.token_fixed_supply_cb, row, 1)
        cb.clicked.connect(self.show_mint_baton_address)
        row += 1

        self.token_nft_parent_cb = cb = QCheckBox(_('Is NFT Parent?'))
        self.token_nft_parent_cb.setChecked(False)
        grid.addWidget(self.token_nft_parent_cb, row, 1)
        cb.clicked.connect(self.token_nft_parent_cb_update)
        row += 1

        if self.nft_parent_id:
            self.token_nft_parent_cb.setDisabled(True)
            self.token_fixed_supply_cb.setDisabled(True)
            self.token_qty_e.setAmount(1)
            self.token_qty_e.setDisabled(True)
            self.token_ds_e.setDisabled(True)

        msg = _('The \'simpleledger:\' formatted bitcoin address for the "minting baton" receiver.') + '\n\n' \
                + _('After the genesis transaction, further unlimited minting operations can be performed by the owner of') \
                + ' the "minting baton" transaction output. This baton can be repeatedly used for minting operations but' \
                + ' it cannot be duplicated.'
        self.token_baton_label = HelpLabel(_('Address for Baton:'), msg)
        self.token_baton_label.setHidden(True)
        grid.addWidget(self.token_baton_label, row, 0)
        self.token_baton_to_e = ButtonsLineEdit()
        self.token_baton_to_e.setFixedWidth(560)
        self.token_baton_to_e.setHidden(True)
        grid.addWidget(self.token_baton_to_e, row, 1)
        row += 1

        try:
            slpAddr = self.wallet.get_unused_address().to_slpaddr()
            self.token_pay_to_e.setText(
                Address.prefix_from_address_string(slpAddr) + ":" + slpAddr)
            self.token_baton_to_e.setText(
                Address.prefix_from_address_string(slpAddr) + ":" + slpAddr)
        except Exception as e:
            pass

        if nft_parent_id:
            nft_parent_coin = get_nft_parent_coin(nft_parent_id, main_window)
            if not get_nft_parent_coin(nft_parent_id, main_window):
                hbox2 = QHBoxLayout()
                vbox.addLayout(hbox2)
                warnpm = QIcon(":icons/warning.png").pixmap(20, 20)
                self.warn1 = l = QLabel()
                l.setPixmap(warnpm)
                hbox2.addWidget(l)
                self.warn_msg = msg = QLabel(
                    _("     NOTE: The parent token needs to be split before a new NFT can be created, click 'Prepare Group Parent'."
                      ))
                hbox2.addWidget(msg)
                self.warn2 = l = QLabel()
                l.setPixmap(warnpm)
                hbox2.addStretch(1)
                hbox2.addWidget(l)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)

        self.cancel_button = b = QPushButton(_("Cancel"))
        self.cancel_button.setAutoDefault(False)
        self.cancel_button.setDefault(False)
        b.clicked.connect(self.close)
        hbox.addWidget(self.cancel_button)

        hbox.addStretch(1)

        # self.hash_button = b = QPushButton(_("Compute Document Hash..."))
        # self.hash_button.setAutoDefault(False)
        # self.hash_button.setDefault(False)
        # b.clicked.connect(self.hash_file)
        # b.setDefault(True)
        # hbox.addWidget(self.hash_button)

        self.tok_doc_button = b = QPushButton(_("Upload a Token Document..."))
        self.tok_doc_button.setAutoDefault(False)
        self.tok_doc_button.setDefault(False)
        b.clicked.connect(self.show_upload)
        b.setDefault(True)
        hbox.addWidget(self.tok_doc_button)

        if nft_parent_id:
            self.import_burn_tx_file_button = EnterButton(
                _("Import file..."), self.do_process_from_file)
            self.import_burn_tx_text_button = EnterButton(
                _("Import hex..."), self.do_process_from_text)
            hbox.addWidget(self.import_burn_tx_file_button)
            hbox.addWidget(self.import_burn_tx_text_button)

        self.preview_button = EnterButton(_("Preview"), self.do_preview)
        hbox.addWidget(self.preview_button)

        self.create_button = b = QPushButton(
            _("Create New Token"
              ))  #if self.provided_token_name is None else _("Change"))
        b.clicked.connect(self.create_token)
        self.create_button.setAutoDefault(True)
        self.create_button.setDefault(True)
        hbox.addWidget(self.create_button)

        if nft_parent_id:
            self.create_button.setText("Create NFT")
            if not nft_parent_coin:
                self.create_button.setHidden(True)
                self.prepare_parent_bttn = QPushButton(
                    _("Prepare Group Parent"))
                self.prepare_parent_bttn.clicked.connect(
                    self.prepare_nft_parent)
                self.prepare_parent_bttn.setAutoDefault(True)
                self.prepare_parent_bttn.setDefault(True)
                hbox.addWidget(self.prepare_parent_bttn)
                self.token_name_e.setDisabled(True)
                self.token_ticker_e.setDisabled(True)
                self.token_url_e.setDisabled(True)
                self.token_dochash_e.setDisabled(True)
                self.token_pay_to_e.setDisabled(True)
                self.token_baton_to_e.setDisabled(True)

        dialogs.append(self)
        self.show()
        self.token_name_e.setFocus()
    def __init__(self, main_window, token_id_hex):
        # We want to be a top-level window
        QDialog.__init__(self, parent=None)
        from .main_window import ElectrumWindow

        assert isinstance(main_window, ElectrumWindow)
        main_window._slp_dialogs.add(self)
        finalization_print_error(self)  # Track object lifecycle

        self.main_window = main_window
        self.wallet = main_window.wallet
        self.network = main_window.network
        self.app = main_window.app

        if self.main_window.gui_object.warn_if_no_network(self.main_window):
            return

        self.setWindowTitle(_("Mint Additional Tokens"))

        vbox = QVBoxLayout()
        self.setLayout(vbox)

        grid = QGridLayout()
        grid.setColumnStretch(1, 1)
        vbox.addLayout(grid)
        row = 0

        msg = _('Unique identifier for the token.')
        grid.addWidget(HelpLabel(_('Token ID:'), msg), row, 0)

        self.token_id_e = QLineEdit()
        self.token_id_e.setFixedWidth(490)
        self.token_id_e.setText(token_id_hex)
        self.token_id_e.setDisabled(True)
        grid.addWidget(self.token_id_e, row, 1)
        row += 1

        msg = _('The number of decimal places used in the token quantity.')
        grid.addWidget(HelpLabel(_('Decimals:'), msg), row, 0)
        self.token_dec = QDoubleSpinBox()
        decimals = self.main_window.wallet.token_types.get(
            token_id_hex)['decimals']
        self.token_dec.setRange(0, 9)
        self.token_dec.setValue(decimals)
        self.token_dec.setDecimals(0)
        self.token_dec.setFixedWidth(50)
        self.token_dec.setDisabled(True)
        grid.addWidget(self.token_dec, row, 1)
        row += 1

        msg = _(
            'The number of tokens created during token minting transaction, send to the receiver address provided below.'
        )
        grid.addWidget(HelpLabel(_('Additional Token Quantity:'), msg), row, 0)
        name = self.main_window.wallet.token_types.get(token_id_hex)['name']
        self.token_qty_e = SLPAmountEdit(name, int(decimals))
        self.token_qty_e.setFixedWidth(200)
        self.token_qty_e.textChanged.connect(self.check_token_qty)
        grid.addWidget(self.token_qty_e, row, 1)
        row += 1

        msg = _(
            'The simpleledger formatted bitcoin address for the genesis receiver of all genesis tokens.'
        )
        grid.addWidget(HelpLabel(_('Token Receiver Address:'), msg), row, 0)
        self.token_pay_to_e = ButtonsLineEdit()
        self.token_pay_to_e.setFixedWidth(490)
        grid.addWidget(self.token_pay_to_e, row, 1)
        row += 1

        msg = _(
            'The simpleledger formatted bitcoin address for the genesis baton receiver.'
        )
        self.token_baton_label = HelpLabel(_('Mint Baton Address:'), msg)
        grid.addWidget(self.token_baton_label, row, 0)
        self.token_baton_to_e = ButtonsLineEdit()
        self.token_baton_to_e.setFixedWidth(490)
        grid.addWidget(self.token_baton_to_e, row, 1)
        row += 1

        try:
            slpAddr = self.wallet.get_unused_address().to_slpaddr()
            self.token_pay_to_e.setText(
                Address.prefix_from_address_string(slpAddr) + ":" + slpAddr)
            self.token_baton_to_e.setText(
                Address.prefix_from_address_string(slpAddr) + ":" + slpAddr)
        except Exception as e:
            pass

        self.token_fixed_supply_cb = cb = QCheckBox(
            _('Permanently end issuance'))
        self.token_fixed_supply_cb.setChecked(False)
        grid.addWidget(self.token_fixed_supply_cb, row, 0)
        cb.clicked.connect(self.show_mint_baton_address)
        row += 1

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)

        self.cancel_button = b = QPushButton(_("Cancel"))
        self.cancel_button.setAutoDefault(False)
        self.cancel_button.setDefault(False)
        b.clicked.connect(self.close)
        b.setDefault(True)
        hbox.addWidget(self.cancel_button)

        hbox.addStretch(1)

        self.preview_button = EnterButton(_("Preview"), self.do_preview)
        self.mint_button = b = QPushButton(_("Create Additional Tokens"))
        b.clicked.connect(self.mint_token)
        self.mint_button.setAutoDefault(True)
        self.mint_button.setDefault(True)
        hbox.addWidget(self.preview_button)
        hbox.addWidget(self.mint_button)

        dialogs.append(self)
        self.show()
        self.token_qty_e.setFocus()
    def __init__(self, main_window):
        #self.provided_token_name = token_name
        # We want to be a top-level window
        QDialog.__init__(self, parent=main_window)

        self.main_window = main_window
        self.wallet = main_window.wallet
        self.config = main_window.config
        self.network = main_window.network
        self.app = main_window.app

        self.setWindowTitle(_("Create a New Token"))

        vbox = QVBoxLayout()
        self.setLayout(vbox)

        grid = QGridLayout()
        grid.setColumnStretch(1, 1)
        vbox.addLayout(grid)
        row = 0

        msg = _(
            'An optional name string embedded in the token genesis transaction.'
        )
        grid.addWidget(HelpLabel(_('Token Name (optional):'), msg), row, 0)
        self.token_name_e = QLineEdit()
        grid.addWidget(self.token_name_e, row, 1)
        row += 1

        msg = _(
            'An optional ticker symbol string embedded into the token genesis transaction.'
        )
        grid.addWidget(HelpLabel(_('Ticker Symbol (optional):'), msg), row, 0)
        self.token_ticker_e = QLineEdit()
        self.token_ticker_e.setFixedWidth(110)
        self.token_ticker_e.textChanged.connect(self.upd_token)
        grid.addWidget(self.token_ticker_e, row, 1)
        row += 1

        msg = _(
            'An optional URL string embedded into the token genesis transaction.'
        )
        grid.addWidget(HelpLabel(_('Document URL (optional):'), msg), row, 0)
        self.token_url_e = QLineEdit()
        self.token_url_e.setFixedWidth(560)
        self.token_url_e.textChanged.connect(self.upd_token)
        grid.addWidget(self.token_url_e, row, 1)
        row += 1

        msg = _(
            'An optional hash hexidecimal bytes embedded into the token genesis transaction for hashing the document file contents at the URL provided above.'
        )
        grid.addWidget(HelpLabel(_('Document Hash (optional):'), msg), row, 0)
        self.token_dochash_e = QLineEdit()
        self.token_dochash_e.setInputMask(
            "HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH")
        self.token_dochash_e.setFixedWidth(560)
        self.token_dochash_e.textChanged.connect(self.upd_token)
        grid.addWidget(self.token_dochash_e, row, 1)
        row += 1

        msg = _('Sets the number of decimals of divisibility for this token (embedded into genesis).') + '\n\n'\
              + _('Each 1 token is divisible into 10^(decimals) base units, and internally in the protocol the token amounts are represented as 64-bit integers measured in these base units.')
        grid.addWidget(HelpLabel(_('Decimal Places:'), msg), row, 0)
        self.token_ds_e = QDoubleSpinBox()
        self.token_ds_e.setRange(0, 9)
        self.token_ds_e.setDecimals(0)
        self.token_ds_e.setFixedWidth(50)
        self.token_ds_e.valueChanged.connect(self.upd_token)
        grid.addWidget(self.token_ds_e, row, 1)
        row += 1

        msg = _(
            'The number of tokens created during token genesis transaction, send to the receiver address provided below.'
        )
        grid.addWidget(HelpLabel(_('Token Quantity:'), msg), row, 0)
        self.token_qty_e = SLPAmountEdit('', 0)
        self.token_qty_e.setFixedWidth(200)
        self.token_qty_e.textChanged.connect(self.check_token_qty)
        grid.addWidget(self.token_qty_e, row, 1)
        row += 1

        msg = _(
            'The \'simpleledger:\' formatted bitcoin address for the genesis receiver of all genesis tokens.'
        )
        grid.addWidget(HelpLabel(_('Token Receiver Address:'), msg), row, 0)
        self.token_pay_to_e = ButtonsLineEdit()
        self.token_pay_to_e.setFixedWidth(560)
        grid.addWidget(self.token_pay_to_e, row, 1)
        try:
            slpAddr = self.wallet.get_unused_address().to_slpaddr()
            self.token_pay_to_e.setText(
                Address.prefix_from_address_string(slpAddr) + ":" + slpAddr)
        except:
            pass
        row += 1

        self.token_fixed_supply_cb = cb = QCheckBox(_('Fixed Supply'))
        self.token_fixed_supply_cb.setChecked(True)
        grid.addWidget(self.token_fixed_supply_cb, row, 1)
        cb.clicked.connect(self.show_mint_baton_address)
        row += 1

        msg = _('The \'simpleledger:\' formatted bitcoin address for the "minting baton" receiver.') + '\n\n'\
              + _('After the genesis transaction, further unlimited minting operations can be performed by the owner of the "minting baton" transaction output. This baton can be repeatedly used for minting operations but it cannot be duplicated.')
        self.token_baton_label = HelpLabel(_('Address for Baton:'), msg)
        self.token_baton_label.setHidden(True)
        grid.addWidget(self.token_baton_label, row, 0)
        self.token_baton_to_e = ButtonsLineEdit()
        self.token_baton_to_e.setFixedWidth(560)
        self.token_baton_to_e.setHidden(True)
        grid.addWidget(self.token_baton_to_e, row, 1)
        row += 1

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)

        self.cancel_button = b = QPushButton(_("Cancel"))
        self.cancel_button.setAutoDefault(False)
        self.cancel_button.setDefault(False)
        b.clicked.connect(self.close)
        hbox.addWidget(self.cancel_button)

        hbox.addStretch(1)

        # self.hash_button = b = QPushButton(_("Compute Document Hash..."))
        # self.hash_button.setAutoDefault(False)
        # self.hash_button.setDefault(False)
        # b.clicked.connect(self.hash_file)
        # b.setDefault(True)
        # hbox.addWidget(self.hash_button)

        self.tok_doc_button = b = QPushButton(_("Upload a Token Document..."))
        self.tok_doc_button.setAutoDefault(False)
        self.tok_doc_button.setDefault(False)
        b.clicked.connect(self.show_upload)
        b.setDefault(True)
        hbox.addWidget(self.tok_doc_button)

        self.preview_button = EnterButton(_("Preview"), self.do_preview)
        self.create_button = b = QPushButton(
            _("Create New Token"
              ))  #if self.provided_token_name is None else _("Change"))
        b.clicked.connect(self.create_token)
        self.create_button.setAutoDefault(True)
        self.create_button.setDefault(True)
        hbox.addWidget(self.preview_button)
        hbox.addWidget(self.create_button)

        dialogs.append(self)
        self.show()
        self.token_name_e.setFocus()