Exemple #1
0
 def seed_options(self):
     dialog = QDialog()
     vbox = QVBoxLayout(dialog)
     if 'ext' in self.options:
         cb_ext = QCheckBox(_('Extend this seed with custom words'))
         cb_ext.setChecked(self.is_ext)
         vbox.addWidget(cb_ext)
     if 'bip39' in self.options:
         def f(b):
             if b:
                 msg = ' '.join([
                     '<b>' + _('Warning') + '</b>' + ': ',
                     _('BIP39 seeds may not be supported in the future.'),
                     '<br/><br/>',
                     _('As technology matures, MonetaryUnit address generation may change.'),
                     _('However, BIP39 seeds do not include a version number.'),
                     _('As a result, it is not possible to infer your wallet type from a BIP39 seed.'),
                     '<br/><br/>',
                     _('We do not guarantee that BIP39 seeds will be supported in future versions of Electrum-MUE.'),
                     _('We recommend to use seeds generated by Electrum-MUE or compatible wallets.'),
                 ])
                 #self.parent.show_warning(msg)
             self.seed_type_label.setVisible(not b)
             self.is_seed = (lambda x: bool(x)) if b else self.saved_is_seed
             self.on_edit()
         cb_bip39 = QCheckBox(_('BIP39 seed'))
         cb_bip39.toggled.connect(f)
         cb_bip39.setChecked(self.is_bip39)
         vbox.addWidget(cb_bip39)
     vbox.addLayout(Buttons(OkButton(dialog)))
     if not dialog.exec_():
         return None
     self.is_ext = cb_ext.isChecked() if 'ext' in self.options else False
     self.is_bip39 = cb_bip39.isChecked() if 'bip39' in self.options else False
Exemple #2
0
 def toggle_passphrase(self):
     if self.features.passphrase_protection:
         self.msg = _("Confirm on your %s device to disable passphrases")
     else:
         self.msg = _("Confirm on your %s device to enable passphrases")
     enabled = not self.features.passphrase_protection
     self.apply_settings(use_passphrase=enabled)
Exemple #3
0
 def task():
     wallet.wait_until_synchronized()
     if wallet.is_found():
         msg = _("Recovery successful")
     else:
         msg = _("No transactions found for this seed")
     self.emit(QtCore.SIGNAL('synchronized'), msg)
Exemple #4
0
    def __init__(self, parent):
        super(CharacterDialog, self).__init__(parent)
        self.setWindowTitle(_("KeepKey Seed Recovery"))
        self.character_pos = 0
        self.word_pos = 0
        self.loop = QEventLoop()
        self.word_help = QLabel()
        self.char_buttons = []

        vbox = QVBoxLayout(self)
        vbox.addWidget(WWLabel(CHARACTER_RECOVERY))
        hbox = QHBoxLayout()
        hbox.addWidget(self.word_help)
        for i in range(4):
            char_button = CharacterButton('*')
            char_button.setMaximumWidth(36)
            self.char_buttons.append(char_button)
            hbox.addWidget(char_button)
        self.accept_button = CharacterButton(_("Accept Word"))
        self.accept_button.clicked.connect(partial(self.process_key, 32))
        self.rejected.connect(partial(self.loop.exit, 1))
        hbox.addWidget(self.accept_button)
        hbox.addStretch(1)
        vbox.addLayout(hbox)

        self.finished_button = QPushButton(_("Seed Entered"))
        self.cancel_button = QPushButton(_("Cancel"))
        self.finished_button.clicked.connect(partial(self.process_key,
                                                     Qt.Key_Return))
        self.cancel_button.clicked.connect(self.rejected)
        buttons = Buttons(self.finished_button, self.cancel_button)
        vbox.addSpacing(40)
        vbox.addLayout(buttons)
        self.refresh()
        self.show()
Exemple #5
0
    def save_current_masternode(self, as_new=False):
        """Save the masternode that is being viewed.

        If as_new is True, a new masternode will be created.
        """
        delegate_privkey = str(self.masternode_editor.delegate_key_edit.text())
        try:
            self.manager.import_masternode_delegate(delegate_privkey)
            delegate_pubkey = bitcoin.public_key_from_private_key(delegate_privkey)
        except Exception:
            # Show an error if the private key is invalid and not an empty string.
            if delegate_privkey:
                QMessageBox.warning(self, _('Warning'), _('Ignoring invalid delegate private key.'))
            delegate_pubkey = ''

        alias = str(self.masternode_editor.alias_edit.text())
        # Construct a new masternode.
        if as_new:
            kwargs = self.masternode_editor.get_masternode_args()
            kwargs['delegate_key'] = delegate_pubkey
            del kwargs['vin']
            self.mapper.revert()
            self.masternodes_widget.add_masternode(MasternodeAnnounce(**kwargs))
        else:
            self.mapper.submit()
        self.manager.save()
        self.masternodes_widget.select_masternode(alias)
Exemple #6
0
 def delete_current_masternode(self):
     """Delete the masternode that is being viewed."""
     mn = self.selected_masternode()
     if QMessageBox.question(self, _('Delete'), _('Do you want to remove the masternode configuration for') + ' %s?'%mn.alias,
                 QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.Yes:
         self.masternodes_widget.remove_masternode(mn.alias)
         self.masternodes_widget.view.selectRow(0)
Exemple #7
0
    def sign_announce(self, alias):
        """Sign an announce for alias. This is called by SignAnnounceWidget."""
        pw = None
        if self.manager.wallet.use_encryption:
            pw = self.gui.password_dialog(msg=_('Please enter your password to activate masternode "%s".' % alias))
            if pw is None:
                return

        self.sign_announce_widget.sign_button.setEnabled(False)

        def sign_thread():
            return self.manager.sign_announce(alias, pw)

        def on_sign_successful(mn):
            self.print_msg('Successfully signed Masternode Announce.')
            self.send_announce(alias)
        # Proceed to broadcasting the announcement, or re-enable the button.
        def on_sign_error(err):
            self.print_error('Error signing MasternodeAnnounce:')
            # Print traceback information to error log.
            self.print_error(''.join(traceback.format_tb(err[2])))
            self.print_error(''.join(traceback.format_exception_only(err[0], err[1])))
            self.sign_announce_widget.sign_button.setEnabled(True)

        util.WaitingDialog(self, _('Signing Masternode Announce...'), sign_thread, on_sign_successful, on_sign_error)
Exemple #8
0
    def cast_vote(self, proposal_name, vote_yes):
        """Vote for a proposal. This is called by ProposalsWidget."""
        vote_choice = 'yes' if vote_yes else 'no'
        mn = self.selected_masternode()
        if not mn.announced:
            return QMessageBox.critical(self, _('Cannot Vote'), _('Masternode has not been activated.'))
        # Check that we can vote before asking for a password.
        try:
            self.manager.check_can_vote(mn.alias, proposal_name)
        except Exception as e:
            return QMessageBox.critical(self, _('Cannot Vote'), _(str(e)))

        self.proposals_widget.editor.vote_button.setEnabled(False)

        def vote_thread():
            return self.manager.vote(mn.alias, proposal_name, vote_choice)

        # Show the result.
        def on_vote_successful(result):
            errmsg, res = result
            if res:
                QMessageBox.information(self, _('Success'), _('Successfully voted'))
            else:
                QMessageBox.critical(self, _('Error Voting'), _(errmsg))
            self.proposals_widget.editor.vote_button.setEnabled(True)

        def on_vote_failed(err):
            self.print_error('Error sending vote:')
            # Print traceback information to error log.
            self.print_error(''.join(traceback.format_tb(err[2])))
            self.print_error(''.join(traceback.format_exception_only(err[0], err[1])))
            self.proposals_widget.editor.vote_button.setEnabled(True)

        util.WaitingDialog(self, _('Voting...'), vote_thread, on_vote_successful, on_vote_failed)
Exemple #9
0
    def create_proposal(self):
        manager = self.parent.masternode_manager

        try:
            proposal = self.create_proposal_from_widgets()
        except Exception as e:
            return QMessageBox.critical(self, _('Error'), _(str(e)))

        pw = None
        if manager.wallet.use_encryption:
            pw = self.parent.password_dialog(msg=_(
                'Please enter your password to create a budget proposal.'))
            if pw is None:
                return

        manager.add_proposal(proposal)

        def sign_done(proposal, tx):
            print_error('proposal tx sign done: %s' % proposal.proposal_name)
            if tx:
                label = _('Budget Proposal Tx: ') + proposal.proposal_name
                self.parent.broadcast_transaction(tx, label)
                self.parent.masternode_manager.save()

        self.create_proposal_tx(proposal, pw, sign_done)
Exemple #10
0
 def on_vote_successful(result):
     errmsg, res = result
     if res:
         QMessageBox.information(self, _('Success'), _('Successfully voted'))
     else:
         QMessageBox.critical(self, _('Error Voting'), _(errmsg))
     self.proposals_widget.editor.vote_button.setEnabled(True)
Exemple #11
0
    def update(self, proposals, main_window):
        item = self.currentItem()
        current_proposal = item.data(ProposalsModel.TXID,
                                     Qt.UserRole).toString() if item else None

        self.model.set_proposals(proposals)
        self.clear()
        row_count = self.model.rowCount()
        if row_count < 1:
            return
        for r in range(row_count):
            get_data = lambda col, row=r: self.model.data(
                self.model.index(row, col))
            name = _(str(get_data(ProposalsModel.NAME).toString()))
            url = _(str(get_data(ProposalsModel.URL).toString()))
            yes_count = str(get_data(ProposalsModel.YES_COUNT).toString())
            no_count = str(get_data(ProposalsModel.NO_COUNT).toString())
            start_block = str(get_data(ProposalsModel.START_BLOCK).toString())
            end_block = str(get_data(ProposalsModel.END_BLOCK).toString())
            amount = str(get_data(ProposalsModel.AMOUNT).toString())
            address = str(get_data(ProposalsModel.ADDRESS).toString())
            txid = str(get_data(ProposalsModel.TXID).toString())
            display_txid = '%s...%s' % (txid[0:8], txid[-8:])

            item = QTreeWidgetItem([
                name, url, yes_count, no_count, start_block, end_block, amount,
                address, display_txid
            ])
            item.setFont(ProposalsModel.START_BLOCK,
                         QFont(util.MONOSPACE_FONT))
            item.setFont(ProposalsModel.END_BLOCK, QFont(util.MONOSPACE_FONT))
            item.setFont(ProposalsModel.ADDRESS, QFont(util.MONOSPACE_FONT))
            item.setFont(ProposalsModel.TXID, QFont(util.MONOSPACE_FONT))

            if name:
                item.setData(ProposalsModel.NAME, Qt.UserRole, name)
            if txid:
                item.setData(ProposalsModel.TXID, Qt.UserRole, txid)

            is_my_proposal = False
            if main_window.masternode_manager.get_proposal(name) is not None:
                is_my_proposal = True
            if is_my_proposal:
                item.setBackground(ProposalsModel.NAME,
                                   QBrush(QColor(MY_PROPOSAL_COLOR)))
                item.setToolTip(ProposalsModel.NAME,
                                _('You created this proposal.'))

            is_my_address = main_window.wallet.is_mine(address)
            if is_my_address:
                item.setBackground(ProposalsModel.ADDRESS,
                                   QBrush(QColor(MY_ADDRESS_COLOR)))
                item.setToolTip(ProposalsModel.ADDRESS,
                                _('You own this address.'))

            self.addTopLevelItem(item)

            if current_proposal == name:
                self.setCurrentItem(item)
Exemple #12
0
 def __init__(self, parent, seed, passphrase):
     WindowModalDialog.__init__(self, parent, ('Electrum-MUE - ' + _('Seed')))
     self.setMinimumWidth(400)
     vbox = QVBoxLayout(self)
     title =  _("Your wallet generation seed is:")
     slayout = SeedLayout(title=title, seed=seed, msg=True, passphrase=passphrase)
     vbox.addLayout(slayout)
     vbox.addLayout(Buttons(CloseButton(self)))
Exemple #13
0
 def add_cosigner_dialog(self, run_next, index, is_valid):
     title = _("Add Cosigner") + " %d" % index
     message = ' '.join([
         _('Please enter the master public key (xpub) of your cosigner.'),
         _('Enter their master private key (xprv) if you want to be able to sign for them.'
           )
     ])
     return self.text_input(title, message, is_valid)
Exemple #14
0
 def closeEvent(self, event):
     if (self.prompt_if_unsaved and not self.saved and not self.question(
             _('This transaction is not saved. Close anyway?'),
             title=_("Warning"))):
         event.ignore()
     else:
         event.accept()
         dialogs.remove(self)
Exemple #15
0
 def set_pin(self, remove):
     if remove:
         self.msg = _("Confirm on your %s device to disable PIN protection")
     elif self.features.pin_protection:
         self.msg = _("Confirm on your %s device to change your PIN")
     else:
         self.msg = _("Confirm on your %s device to set a PIN")
     self.change_pin(remove)
Exemple #16
0
 def __init__(self, parent=None):
     MyTreeWidget.__init__(self, parent, self.create_menu, [
         _('Address'),
         _('Label'),
         _('Amount'),
         _('Height'),
         _('Output point')
     ], 1)
     self.setSelectionMode(QAbstractItemView.ExtendedSelection)
Exemple #17
0
 def wipe_device():
     wallet = window.wallet
     if wallet and sum(wallet.get_balance()):
         title = _("Confirm Device Wipe")
         msg = _("Are you SURE you want to wipe the device?\n"
                 "Your wallet still has MonetaryUnit in it!")
         if not self.question(msg, title=title,
                              icon=QMessageBox.Critical):
             return
     invoke_client('wipe_device', unpair_after=True)
Exemple #18
0
 def on_send_successful(result):
     errmsg, was_announced = result
     if was_announced:
         self.print_msg('Successfully broadcasted MasternodeAnnounce for "%s"' % alias)
         QMessageBox.information(self, _('Success'), _('Masternode activated successfully.'))
     else:
         self.print_error('Failed to broadcast MasternodeAnnounce: %s' % errmsg)
         QMessageBox.critical(self, _('Error Sending'), _(errmsg))
     self.masternodes_widget.refresh_items()
     self.masternodes_widget.select_masternode(alias)
Exemple #19
0
 def restore_seed_dialog(self, run_next, test):
     options = []
     if self.opt_ext:
         options.append('ext')
     if self.opt_bip39:
         options.append('bip39')
     title = _('Enter Seed')
     message = _(
         'Please enter your seed phrase in order to restore your wallet.')
     return self.seed_input(title, message, test, options)
Exemple #20
0
 def show_xpub_dialog(self, xpub, run_next):
     msg = ' '.join([
         _("Here is your master public key."),
         _("Please share it with your cosigners.")
     ])
     vbox = QVBoxLayout()
     layout = SeedLayout(xpub, title=msg, icon=False)
     vbox.addLayout(layout.layout())
     self.exec_layout(vbox, _('Master Public Key'))
     return None
Exemple #21
0
 def save(self):
     name = 'signed_%s.txn' % (
         self.tx.hash()[0:8]) if self.tx.is_complete() else 'unsigned.txn'
     fileName = self.main_window.getSaveFileName(
         _("Select where to save your signed transaction"), name, "*.txn")
     if fileName:
         with open(fileName, "w+") as f:
             f.write(json.dumps(self.tx.as_dict(), indent=4) + '\n')
         self.show_message(_("Transaction saved successfully"))
         self.saved = True
Exemple #22
0
 def __init__(self, parent=None):
     super(ProposalsModel, self).__init__(parent)
     self.proposals = []
     headers = [
         {
             Qt.DisplayRole: _('Name'),
         },
         {
             Qt.DisplayRole: _('URL'),
         },
         {
             Qt.DisplayRole: _('Yes Votes'),
         },
         {
             Qt.DisplayRole: _('No Votes'),
         },
         {
             Qt.DisplayRole: _('Start Block'),
         },
         {
             Qt.DisplayRole: _('End Block'),
         },
         {
             Qt.DisplayRole: _('Amount'),
         },
         {
             Qt.DisplayRole: _('Address'),
         },
         {
             Qt.DisplayRole: _('Fee Tx'),
         },
     ]
     for d in headers:
         d[Qt.EditRole] = d[Qt.DisplayRole]
     self.headers = headers
Exemple #23
0
    def __init__(self, parent=None):
        super(ProposalsTreeWidget, self).__init__(parent, self.create_menu, [
            _('Name'),
            _('URL'),
            _('Yes Votes'),
            _('No Votes'),
            _('Start Block'),
            _('End Block'),
            _('Amount'),
            _('Address'),
            _('Fee Tx')
        ], 0)

        header = self.header()
        header.setResizeMode(ProposalsModel.NAME, QHeaderView.ResizeToContents)
        header.setResizeMode(ProposalsModel.URL, QHeaderView.Stretch)
        header.setResizeMode(ProposalsModel.YES_COUNT,
                             QHeaderView.ResizeToContents)
        header.setResizeMode(ProposalsModel.NO_COUNT,
                             QHeaderView.ResizeToContents)
        header.setResizeMode(ProposalsModel.ADDRESS,
                             QHeaderView.ResizeToContents)
        header.setResizeMode(ProposalsModel.TXID, QHeaderView.ResizeToContents)

        self.model = ProposalsModel()
Exemple #24
0
    def import_masternode_conf(self, filename):
        """Import a masternode.conf file."""
        pw = None
        if self.manager.wallet.use_encryption:
            pw = self.gui.password_dialog(msg=_('Please enter your password to import Masternode information.'))
            if pw is None:
                return

        if not os.path.exists(filename):
            QMessageBox.critical(self, _('Error'), _('File does not exist'))
            return
        with open(filename, 'r') as f:
            lines = f.readlines()

        # Show an error if the conf file is malformed.
        try:
            conf_lines = parse_masternode_conf(lines)
        except Exception as e:
            QMessageBox.critical(self, _('Error'), _(str(e)))
            return

        num = self.masternodes_widget.import_masternode_conf_lines(conf_lines, pw)
        if not num:
            return QMessageBox.warning(self, _('Failed to Import'), _('Could not import any masternode configurations. Please ensure that they are not already imported.'))
        # Grammar is important.
        configurations = 'configuration' if num == 1 else 'configurations'
        adjective = 'this' if num == 1 else 'these'
        noun = 'masternode' if num == 1 else 'masternodes'
        words = {'adjective': adjective, 'configurations': configurations, 'noun': noun, 'num': num,}
        msg = '{num} {noun} {configurations} imported.\n\nPlease wait for transactions involving {adjective} {configurations} to be retrieved before activating {adjective} {noun}.'.format(**words)
        QMessageBox.information(self, _('Success'), _(msg))
Exemple #25
0
    def __init__(self, parent=None):
        super(MasternodeEditor, self).__init__(parent)

        self.alias_edit = QLineEdit()
        self.alias_edit.setPlaceholderText(_('Enter a name for this masternode'))

        self.vin_edit = PrevOutWidget()

        self.addr_edit = NetworkAddressWidget()
        self.delegate_key_edit = QLineEdit()
        self.delegate_key_edit.setFont(QFont(util.MONOSPACE_FONT))
        self.delegate_key_edit.setPlaceholderText(_('Your masternode\'s private key'))
        self.protocol_version_edit = QLineEdit()
        self.protocol_version_edit.setText('70201')

        self.status_edit = QLineEdit()
        self.status_edit.setPlaceholderText(_('Masternode status'))
        self.status_edit.setReadOnly(True)

        form = QFormLayout()
        form.addRow(_('Alias:'), self.alias_edit)
        form.addRow(_('Status:'), self.status_edit)
        form.addRow(_('Collateral MUE Output:'), self.vin_edit)
        form.addRow(_('Masternode Private Key:'), self.delegate_key_edit)
        form.addRow(_('Address:'), self.addr_edit)
        form.addRow(_('Protocol Version:'), self.protocol_version_edit)

        self.setLayout(form)
Exemple #26
0
 def confirm_seed_dialog(self, run_next, test):
     self.app.clipboard().clear()
     title = _('Confirm Seed')
     message = ' '.join([
         _('Your seed is important!'),
         _('If you lose your seed, your money will be permanently lost.'),
         _('To make sure that you have properly saved your seed, please retype it here.'
           )
     ])
     seed, is_bip39, is_ext = self.seed_input(title, message, test, None)
     return seed
Exemple #27
0
 def __init__(self, parent):
     MyTreeWidget.__init__(self, parent, self.create_menu, [
         _('Expires'),
         _('Requestor'),
         _('Description'),
         _('Amount'),
         _('Status')
     ], 2)
     self.setSortingEnabled(True)
     self.header().setResizeMode(1, QHeaderView.Interactive)
     self.setColumnWidth(1, 200)
Exemple #28
0
    def __init__(self, main_widget, parent=None):
        super(ProposalEditor, self).__init__(parent)
        self.main_widget = main_widget

        self.name_edit = QLineEdit()
        self.url_edit = QLineEdit()
        self.start_block_edit = QLineEdit()
        self.end_block_edit = QLineEdit()
        self.amount_edit = QLineEdit()
        self.address_edit = QLineEdit()
        self.txid_edit = QLineEdit()
        for i in [
                self.name_edit, self.url_edit, self.start_block_edit,
                self.end_block_edit, self.amount_edit, self.address_edit,
                self.txid_edit
        ]:
            i.setReadOnly(True)

        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.main_widget.proxy_model)
        self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)

        self.mapper.addMapping(self.name_edit, ProposalsModel.NAME)
        self.mapper.addMapping(self.url_edit, ProposalsModel.URL)
        self.mapper.addMapping(self.start_block_edit,
                               ProposalsModel.START_BLOCK)
        self.mapper.addMapping(self.end_block_edit, ProposalsModel.END_BLOCK)
        self.mapper.addMapping(self.amount_edit, ProposalsModel.AMOUNT)
        self.mapper.addMapping(self.address_edit, ProposalsModel.ADDRESS)
        self.mapper.addMapping(self.txid_edit, ProposalsModel.TXID)

        block_hbox = QHBoxLayout()
        block_hbox.addWidget(self.start_block_edit)
        block_hbox.addWidget(QLabel(' - '))
        block_hbox.addWidget(self.end_block_edit)

        self.vote_combo = QComboBox()
        self.vote_combo.addItem(_('Yes'))
        self.vote_combo.addItem(_('No'))
        self.vote_button = QPushButton(_('Vote'))
        self.vote_button.clicked.connect(self.cast_vote)

        vote_hbox = util.Buttons(self.vote_combo, self.vote_button)

        form = QFormLayout()
        form.addRow(_('Name:'), self.name_edit)
        form.addRow(_('URL:'), self.url_edit)
        form.addRow(_('Blocks:'), block_hbox)
        form.addRow(_('Monthly Payment:'), self.amount_edit)
        form.addRow(_('Payment Address:'), self.address_edit)
        form.addRow(_('Fee TxID:'), self.txid_edit)

        form.addRow(_('Vote:'), vote_hbox)
        self.setLayout(form)
Exemple #29
0
 def build_tray_menu(self):
     # Avoid immediate GC of old menu when window closed via its action
     self.old_menu = self.tray.contextMenu()
     m = QMenu()
     for window in self.windows:
         submenu = m.addMenu(window.wallet.basename())
         submenu.addAction(_("Show/Hide"), window.show_or_hide)
         submenu.addAction(_("Close"), window.close)
     m.addAction(_("Dark/Light"), self.toggle_tray_icon)
     m.addSeparator()
     m.addAction(_("Exit Electrum-MUE"), self.close)
     self.tray.setContextMenu(m)
Exemple #30
0
 def callback_PinMatrixRequest(self, msg):
     if msg.type == 2:
         msg = _("Enter a new PIN for your %s:")
     elif msg.type == 3:
         msg = (_("Re-enter the new PIN for your %s.\n\n"
                  "NOTE: the positions of the numbers have changed!"))
     else:
         msg = _("Enter your current %s PIN:")
     pin = self.handler.get_pin(msg % self.device)
     if not pin:
         return self.proto.Cancel()
     return self.proto.PinMatrixAck(pin=pin)