예제 #1
0
 def build_tray_menu(self):
     m = QMenu()
     m.addAction(_("Show/Hide"), self.show_or_hide)
     m.addAction(_("Dark/Light"), self.toggle_tray_icon)
     m.addSeparator()
     m.addAction(_("Exit Electrum"), self.close)
     self.tray.setContextMenu(m)
예제 #2
0
    def __init__(self, address, parent):
        self.address = address
        self.parent = parent
        self.config = parent.config
        self.wallet = parent.wallet
        self.app = parent.app
        self.saved = True

        QDialog.__init__(self)
        self.setMinimumWidth(700)
        self.setWindowTitle(_("Address"))
        self.setModal(1)
        vbox = QVBoxLayout()
        self.setLayout(vbox)

        vbox.addWidget(QLabel(_("Address:")))
        self.addr_e = ButtonsLineEdit(self.address)
        self.addr_e.addCopyButton(self.app)
        self.addr_e.addButton(":icons/qrcode.png", self.show_qr, _("Show QR Code"))
        self.addr_e.setReadOnly(True)
        vbox.addWidget(self.addr_e)

        vbox.addWidget(QLabel(_("History")))
        self.hw = HistoryWidget(self.parent)
        vbox.addWidget(self.hw)

        vbox.addStretch(1)
        vbox.addLayout(Buttons(CloseButton(self)))
        self.format_amount = self.parent.format_amount

        h = self.wallet.get_history([self.address])
        self.hw.update(h)
예제 #3
0
 def qr_input(self):
     from electrum_grs import qrscanner, get_config
     try:
         data = qrscanner.scan_qr(get_config())
     except BaseException, e:
         QMessageBox.warning(self, _('Error'), _(e), _('OK'))
         return ""
예제 #4
0
    def mouseReleaseEvent(self, event):
        dialog = QDialog(self)
        dialog.setWindowTitle(_('Electrum update'))
        dialog.setModal(1)

        main_layout = QGridLayout()
        main_layout.addWidget(QLabel(_("A new version of Electrum is available:")+" " + self.latest_version), 0,0,1,3)

        ignore_version = QPushButton(_("Ignore this version"))
        ignore_version.clicked.connect(self.ignore_this_version)

        ignore_all_versions = QPushButton(_("Ignore all versions"))
        ignore_all_versions.clicked.connect(self.ignore_all_version)

        open_website = QPushButton(_("Goto download page"))
        open_website.clicked.connect(self.open_website)

        main_layout.addWidget(ignore_version, 1, 0)
        main_layout.addWidget(ignore_all_versions, 1, 1)
        main_layout.addWidget(open_website, 1, 2)

        dialog.setLayout(main_layout)

        self.dialog = dialog

        if not dialog.exec_(): return
예제 #5
0
    def multi_mpk_dialog(self, xpub_hot, n):
        vbox = QVBoxLayout()
        scroll = QScrollArea()
        scroll.setEnabled(True)
        scroll.setWidgetResizable(True)
        vbox.addWidget(scroll)

        w = QWidget()
        scroll.setWidget(w)

        innerVbox = QVBoxLayout()
        w.setLayout(innerVbox)

        vbox0 = seed_dialog.show_seed_box(MSG_SHOW_MPK, xpub_hot, 'hot')
        innerVbox.addLayout(vbox0)
        entries = []
        for i in range(n):
            msg = _("Please enter the master public key of cosigner") + ' %d'%(i+1)
            vbox2, seed_e2 = seed_dialog.enter_seed_box(msg, self, 'cold')
            innerVbox.addLayout(vbox2)
            entries.append(seed_e2)
        vbox.addStretch(1)
        button = OkButton(self, _('Next'))
        vbox.addLayout(Buttons(CancelButton(self), button))
        button.setEnabled(False)
        f = lambda: button.setEnabled( map(lambda e: Wallet.is_xpub(self.get_seed_text(e)), entries) == [True]*len(entries))
        for e in entries:
            e.textChanged.connect(f)
        self.set_layout(vbox)
        if not self.exec_():
            return
        return map(lambda e: self.get_seed_text(e), entries)
예제 #6
0
    def __init__(self, transaction_id, parent):
        super(TransactionWindow, self).__init__()

        self.tx_id = str(transaction_id)
        self.parent = parent

        self.setModal(True)
        self.resize(200, 100)
        self.setWindowTitle(_("Transaction successfully sent"))

        self.layout = QGridLayout(self)
        history_label = "%s\n%s" % (
            _("Your transaction has been sent."),
            _("Please enter a label for this transaction for future reference."),
        )
        self.layout.addWidget(QLabel(history_label))

        self.label_edit = QLineEdit()
        self.label_edit.setPlaceholderText(_("Transaction label"))
        self.label_edit.setObjectName("label_input")
        self.label_edit.setAttribute(Qt.WA_MacShowFocusRect, 0)
        self.label_edit.setFocusPolicy(Qt.ClickFocus)
        self.layout.addWidget(self.label_edit)

        self.save_button = QPushButton(_("Save"))
        self.layout.addWidget(self.save_button)
        self.save_button.clicked.connect(self.set_label)

        self.exec_()
예제 #7
0
    def network_dialog(self):
        grid = QGridLayout()
        grid.setSpacing(5)

        label = QLabel(_("Electrum-GRS communicates with remote servers to get information about your transactions and addresses. The servers all fulfil the same purpose only differing in hardware. In most cases you simply want to let Electrum-GRS pick one at random if you have a preference though feel free to select a server manually.") + "\n\n" \
                      + _("How do you want to connect to a server:")+" ")
        label.setWordWrap(True)
        grid.addWidget(label, 0, 0)
        gb = QGroupBox()
        b1 = QRadioButton(gb)
        b1.setText(_("Auto connect"))
        b1.setChecked(True)
        b2 = QRadioButton(gb)
        b2.setText(_("Select server manually"))
        grid.addWidget(b1,1,0)
        grid.addWidget(b2,2,0)
        vbox = QVBoxLayout()
        vbox.addLayout(grid)
        vbox.addStretch(1)
        vbox.addLayout(Buttons(CancelButton(self), OkButton(self, _('Next'))))

        self.set_layout(vbox)
        if not self.exec_():
            return

        if b2.isChecked():
            return NetworkDialog(self.network, self.config, None).do_exec()
        else:
            self.config.set_key('auto_connect', True, True)
            return
예제 #8
0
 def value_str(self, satoshis, rate):
     if satoshis is None:  # Can happen with incomplete history
         return _("Unknown")
     if rate:
         value = Decimal(satoshis) / COIN * Decimal(rate)
         return "%s" % (self.ccy_amount_str(value, True))
     return _("No data")
 def save(self):
     name = 'signed_%s.txn' % (self.tx.hash()[0:8]) if self.tx.is_complete() else 'unsigned.txn'
     fileName = self.parent.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
예제 #10
0
 def verify_seed(self, seed, sid, func=None):
     r = self.enter_seed_dialog(MSG_VERIFY_SEED, sid, func)
     if not r:
         return
     if prepare_seed(r) != prepare_seed(seed):
         QMessageBox.warning(None, _('Error'), _('Incorrect seed'), _('OK'))
         return False
     else:
         return True
    def add_io(self, vbox):

        if self.tx.locktime > 0:
            vbox.addWidget(QLabel("LockTime: %d\n" % self.tx.locktime))

        vbox.addWidget(QLabel(_("Inputs") + ' (%d)'%len(self.tx.inputs)))

        ext = QTextCharFormat()
        rec = QTextCharFormat()
        rec.setBackground(QBrush(QColor("lightgreen")))
        rec.setToolTip(_("Wallet receive address"))
        chg = QTextCharFormat()
        chg.setBackground(QBrush(QColor("yellow")))
        chg.setToolTip(_("Wallet change address"))

        def text_format(addr):
            if self.wallet.is_mine(addr):
                return chg if self.wallet.is_change(addr) else rec
            return ext

        i_text = QTextEdit()
        i_text.setFont(QFont(MONOSPACE_FONT))
        i_text.setReadOnly(True)
        i_text.setMaximumHeight(100)
        cursor = i_text.textCursor()
        for x in self.tx.inputs:
            if x.get('is_coinbase'):
                cursor.insertText('coinbase')
            else:
                prevout_hash = x.get('prevout_hash')
                prevout_n = x.get('prevout_n')
                cursor.insertText(prevout_hash[0:8] + '...', ext)
                cursor.insertText(prevout_hash[-8:] + ":%-4d " % prevout_n, ext)
                addr = x.get('address')
                if addr == "(pubkey)":
                    _addr = self.wallet.find_pay_to_pubkey_address(prevout_hash, prevout_n)
                    if _addr:
                        addr = _addr
                if addr is None:
                    addr = _('unknown')
                cursor.insertText(addr, text_format(addr))
            cursor.insertBlock()

        vbox.addWidget(i_text)
        vbox.addWidget(QLabel(_("Outputs") + ' (%d)'%len(self.tx.outputs)))
        o_text = QTextEdit()
        o_text.setFont(QFont(MONOSPACE_FONT))
        o_text.setReadOnly(True)
        o_text.setMaximumHeight(100)
        cursor = o_text.textCursor()
        for addr, v in self.tx.get_outputs():
            cursor.insertText(addr, text_format(addr))
            if v is not None:
                cursor.insertText('\t', ext)
                cursor.insertText(self.parent.format_amount(v, whitespaces = True), ext)
            cursor.insertBlock()
        vbox.addWidget(o_text)
예제 #12
0
 def export_history_dialog(self, d,hbox):
     self.wallet = d.wallet
     history = self.wallet.get_history()
     if len(history) > 0:
         b = QPushButton(_("Preview plot"))
         hbox.addWidget(b)
         b.clicked.connect(lambda: self.do_plot(self.wallet, history))
     else:
         b = QPushButton(_("No history to plot"))
         hbox.addWidget(b)
예제 #13
0
 def installwizard_restore(self, wizard, storage):
     if storage.get('wallet_type') != 'btchip':
         return
     wallet = BTChipWallet(storage)
     try:
         wallet.create_main_account(None)
     except BaseException as e:
         QMessageBox.information(None, _('Error'), str(e), _('OK'))
         return
     return wallet
예제 #14
0
def ok_cancel_buttons(dialog):
    row_layout = QHBoxLayout()
    row_layout.addStretch(1)
    ok_button = QPushButton(_("OK"))
    row_layout.addWidget(ok_button)
    ok_button.clicked.connect(dialog.accept)
    cancel_button = QPushButton(_("Cancel"))
    row_layout.addWidget(cancel_button)
    cancel_button.clicked.connect(dialog.reject)
    return row_layout
예제 #15
0
 def give_error(self, message, clear_client = False):
     print_error(message)
     if not self.signing:
         QMessageBox.warning(QDialog(), _('Warning'), _(message), _('OK'))
     else:
         self.signing = False
     if clear_client and self.client is not None:
         self.client.bad = True
         self.device_checked = False
     raise Exception(message)
예제 #16
0
 def __init__(self, parent, seed, imported_keys):
     QDialog.__init__(self, parent)
     self.setModal(1)
     self.setMinimumWidth(400)
     self.setWindowTitle('Electrum' + ' - ' + _('Seed'))
     vbox = show_seed_box_msg(seed)
     if imported_keys:
         vbox.addWidget(QLabel("<b>"+_("WARNING")+":</b> " + _("Your wallet contains imported keys. These keys cannot be recovered from seed.") + "</b><p>"))
     vbox.addLayout(Buttons(CloseButton(self)))
     self.setLayout(vbox)
 def closeEvent(self, event):
     if (self.prompt_if_unsaved and not self.saved and not self.broadcast
         and QMessageBox.question(
             self, _('Warning'),
             _('This transaction is not saved. Close anyway?'),
             QMessageBox.Yes | QMessageBox.No) == QMessageBox.No):
         event.ignore()
     else:
         event.accept()
         dialogs.remove(self)
예제 #18
0
 def append(self, address, amount, date):
     if address is None:
         address = _("Unknown")
     if amount is None:
         amount = _("Unknown")
     if date is None:
         date = _("Unknown")
     item = QTreeWidgetItem([amount, address, date])
     if amount.find("-") != -1:
         item.setForeground(0, QBrush(QColor("#BC1E1E")))
     self.insertTopLevelItem(0, item)
예제 #19
0
    def __init__(self, owner=None):
        self.owner = owner
        self.editing = False

        QTreeWidget.__init__(self, owner)
        self.setColumnCount(3)
        self.setHeaderLabels([_("Address"), _("Label"), _("Used")])
        self.setIndentation(0)

        self.hide_used = True
        self.setColumnHidden(2, True)
예제 #20
0
    def restore_or_create(self):
        vbox = QVBoxLayout()
        main_label = QLabel(_("Electrum-GRS could not find an existing wallet."))
        vbox.addWidget(main_label)
        grid = QGridLayout()
        grid.setSpacing(5)
        gb1 = QGroupBox(_("What do you want to do?"))
        vbox.addWidget(gb1)
        b1 = QRadioButton(gb1)
        b1.setText(_("Create new wallet"))
        b1.setChecked(True)
        b2 = QRadioButton(gb1)
        b2.setText(_("Restore a wallet or import keys"))
        group1 = QButtonGroup()
        group1.addButton(b1)
        group1.addButton(b2)
        vbox.addWidget(b1)
        vbox.addWidget(b2)

        gb2 = QGroupBox(_("Wallet type:"))
        vbox.addWidget(gb2)
        group2 = QButtonGroup()

        self.wallet_types = [
            ('standard',  _("Standard wallet")),
            ('twofactor', _("Wallet with two-factor authentication")),
            ('multisig',  _("Multi-signature wallet")),
            ('hardware',  _("Hardware wallet")),
        ]

        for i, (wtype,name) in enumerate(self.wallet_types):
            if not filter(lambda x:x[0]==wtype, electrum_grs.wallet.wallet_types):
                continue
            button = QRadioButton(gb2)
            button.setText(name)
            vbox.addWidget(button)
            group2.addButton(button)
            group2.setId(button, i)
            if i==0:
                button.setChecked(True)

        vbox.addStretch(1)
        self.set_layout(vbox)
        vbox.addLayout(Buttons(CancelButton(self), OkButton(self, _('Next'))))
        self.show()
        self.raise_()

        if not self.exec_():
            return None, None

        action = 'create' if b1.isChecked() else 'restore'
        wallet_type = self.wallet_types[group2.checkedId()][0]
        return action, wallet_type
예제 #21
0
    def close(self):
        self.d.accept()
        if self.error:
            QMessageBox.warning(self.parent, _('Error'), self.error, _('OK'))
        else:
            if self.on_success:
                if type(self.result) is not tuple:
                    self.result = (self.result,)
                self.on_success(*self.result)

        if self.on_complete:
            self.on_complete()
예제 #22
0
def show_seed_box_msg(seedphrase, sid=None):
    msg =  _("Your wallet generation seed is") + ":"
    vbox = show_seed_box(msg, seedphrase, sid)
    save_msg = _("Please save these %d words on paper (order is important).")%len(seedphrase.split()) + " "
    msg2 = save_msg + " " \
           + _("This seed will allow you to recover your wallet in case of computer failure.") + "<br/>" \
           + "<b>"+_("WARNING")+":</b> " + _("Never disclose your seed. Never type it on a website.") + "</b><p>"
    label2 = QLabel(msg2)
    label2.setWordWrap(True)
    vbox.addWidget(label2)
    vbox.addStretch(1)
    return vbox
예제 #23
0
    def settings_dialog(self):
        d = QDialog()
        d.setWindowTitle("Settings")
        layout = QGridLayout(d)
        layout.addWidget(QLabel(_('Exchange rate API: ')), 0, 0)
        layout.addWidget(QLabel(_('Currency: ')), 1, 0)
        # Disabled.
        # layout.addWidget(QLabel(_('History Rates: ')), 2, 0)

        # Currency list
        self.ccy_combo = QComboBox()
        self.ccy_combo.currentIndexChanged.connect(self.on_ccy_combo_change)
        self.populate_ccy_combo()

        def on_change_ex(idx):
            exchange = str(combo_ex.currentText())
            if exchange != self.exchange.name():
                self.set_exchange(exchange)
                self.hist_checkbox_update()

        def on_change_hist(checked):
            if checked:
                self.config.set_key('history_rates', 'checked')
                self.get_historical_rates()
            else:
                self.config.set_key('history_rates', 'unchecked')
            self.refresh_headers()

        def ok_clicked():
            self.timeout = 0
            self.ccy_combo = None
            d.accept()

        combo_ex = QComboBox()
        combo_ex.addItems(sorted(self.exchanges.keys()))
        combo_ex.setCurrentIndex(combo_ex.findText(self.config_exchange()))
        combo_ex.currentIndexChanged.connect(on_change_ex)

        self.hist_checkbox = QCheckBox()
        self.hist_checkbox.stateChanged.connect(on_change_hist)
        self.hist_checkbox_update()

        ok_button = QPushButton(_("OK"))
        ok_button.clicked.connect(lambda: ok_clicked())

        layout.addWidget(self.ccy_combo,1,1)
        layout.addWidget(combo_ex,0,1)
        # Disabled.
        # layout.addWidget(self.hist_checkbox,2,1)
        layout.addWidget(ok_button,3,1)

        return d.exec_()
예제 #24
0
 def load_wallet(self, wallet, window):
     self.wallet = wallet
     self.wallet.plugin = self
     self.window = window
     if self.handler is None:
         self.handler = BTChipQTHandler(self.window.app)
     if self.btchip_is_connected():
         if not self.wallet.check_proper_device():
             QMessageBox.information(self.window, _('Error'), _("This wallet does not match your Ledger device"), _('OK'))
             self.wallet.force_watching_only = True
     else:
         QMessageBox.information(self.window, _('Error'), _("Ledger device not detected.\nContinuing in watching-only mode."), _('OK'))
         self.wallet.force_watching_only = True
예제 #25
0
    def setup(self, address):
        label = QLabel(_("Copied your Groestlcoin address to the clipboard!"))
        address_display = QLineEdit(address)
        address_display.setReadOnly(True)
        resize_line_edit_width(address_display, address)

        main_layout = QVBoxLayout(self)
        main_layout.addWidget(label)
        main_layout.addWidget(address_display)

        self.setMouseTracking(True)
        self.setWindowTitle("Electrum-GRS - " + _("Receive Groestlcoin payment"))
        self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint | Qt.MSWindowsFixedSizeDialogHint)
        self.layout().setSizeConstraint(QLayout.SetFixedSize)
예제 #26
0
 def question(self, msg, yes_label=_('OK'), no_label=_('Cancel'), icon=None):
     vbox = QVBoxLayout()
     self.set_layout(vbox)
     if icon:
         logo = QLabel()
         logo.setPixmap(icon)
         vbox.addWidget(logo)
     label = QLabel(msg)
     label.setWordWrap(True)
     vbox.addWidget(label)
     vbox.addStretch(1)
     vbox.addLayout(Buttons(CancelButton(self, no_label), OkButton(self, yes_label)))
     if not self.exec_():
         return None
     return True
예제 #27
0
 def __init__(self, change_quote_currency, parent=None):
     super(QLabel, self).__init__(_("Connecting..."), parent)
     self.change_quote_currency = change_quote_currency
     self.state = self.SHOW_CONNECTING
     self.balance_text = ""
     self.amount_text = ""
     self.parent = parent
예제 #28
0
    def multi_seed_dialog(self, n):
        vbox = QVBoxLayout()
        scroll = QScrollArea()
        scroll.setEnabled(True)
        scroll.setWidgetResizable(True)
        vbox.addWidget(scroll)

        w = QWidget()
        scroll.setWidget(w)

        innerVbox = QVBoxLayout()
        w.setLayout(innerVbox)

        vbox1, seed_e1 = seed_dialog.enter_seed_box(MSG_ENTER_SEED_OR_MPK, self, 'hot')
        innerVbox.addLayout(vbox1)
        entries = [seed_e1]
        for i in range(n):
            vbox2, seed_e2 = seed_dialog.enter_seed_box(MSG_ENTER_SEED_OR_MPK, self, 'cold')
            innerVbox.addLayout(vbox2)
            entries.append(seed_e2)
        vbox.addStretch(1)
        button = OkButton(self, _('Next'))
        vbox.addLayout(Buttons(CancelButton(self), button))
        button.setEnabled(False)
        f = lambda: button.setEnabled( map(lambda e: self.is_any(self.get_seed_text(e)), entries) == [True]*len(entries))
        for e in entries:
            e.textChanged.connect(f)
        self.set_layout(vbox)
        if not self.exec_():
            return
        return map(lambda e: self.get_seed_text(e), entries)
예제 #29
0
    def choice(self, title, msg, choices):
        vbox = QVBoxLayout()
        self.set_layout(vbox)
        vbox.addWidget(QLabel(title))
        gb2 = QGroupBox(msg)
        vbox.addWidget(gb2)

        vbox2 = QVBoxLayout()
        gb2.setLayout(vbox2)

        group2 = QButtonGroup()
        for i,c in enumerate(choices):
            button = QRadioButton(gb2)
            button.setText(c[1])
            vbox2.addWidget(button)
            group2.addButton(button)
            group2.setId(button, i)
            if i==0:
                button.setChecked(True)
        vbox.addStretch(1)
        vbox.addLayout(Buttons(CancelButton(self), OkButton(self, _('Next'))))
        if not self.exec_():
            return
        wallet_type = choices[group2.checkedId()][0]
        return wallet_type
예제 #30
0
 def password_dialog(self, pw, grid, pos):
     vkb_button = QPushButton(_("+"))
     vkb_button.setFixedWidth(20)
     vkb_button.clicked.connect(lambda: self.toggle_vkb(grid, pw))
     grid.addWidget(vkb_button, pos, 2)
     self.kb_pos = 2
     self.vkb = None
예제 #31
0
from electrum_grs.i18n import _

fullname = _('Revealer')
description = ''.join(["<br/>",
    "<b>"+_("Do you have something to hide ?")+"</b>", '<br/>', '<br/>',
    _("Revealer is a seed phrase back-up solution. It allows you to create a cold, analog, multi-factor backup of your wallet seeds, or of any arbitrary secret."), '<br/>', '<br/>',
    _("Using a Revealer is better than writing your seed phrases on paper: a revealer is invulnerable to physical access and allows creation of trustless redundancy."), '<br/>', '<br/>',
    _("This plug-in allows you to generate a pdf file of your secret phrase encrypted visually for your physical Revealer. You can print it trustlessly - it can only be decrypted optically with your Revealer."), '<br/>', '<br/>',
    _("The plug-in also allows you to generate a digital Revealer file and print it yourself on a transparent overhead foil."), '<br/>', '<br/>',
    _("Once activated you can access the plug-in through the icon at the seed dialog."), '<br/>', '<br/>',
    _("For more information, visit"),
    " <a href=\"https://revealer.cc\">https://revealer.cc</a>", '<br/>', '<br/>',
])
available_for = ['qt']


예제 #32
0
    def __init__(self, window, plugin, keystore, device_id):
        title = _("{} Settings").format(plugin.device)
        super(CKCCSettingsDialog, self).__init__(window, title)
        self.setMaximumWidth(540)

        devmgr = plugin.device_manager()
        config = devmgr.config
        handler = keystore.handler
        self.thread = thread = keystore.thread

        def connect_and_doit():
            client = devmgr.client_by_id(device_id)
            if not client:
                raise RuntimeError("Device not connected")
            return client

        body = QWidget()
        body_layout = QVBoxLayout(body)
        grid = QGridLayout()
        grid.setColumnStretch(2, 1)

        # see <http://doc.qt.io/archives/qt-4.8/richtext-html-subset.html>
        title = QLabel('''<center>
<span style="font-size: x-large">Coldcard Wallet</span>
<br><span style="font-size: medium">from Coinkite Inc.</span>
<br><a href="https://coldcardwallet.com">coldcardwallet.com</a>''')
        title.setTextInteractionFlags(Qt.LinksAccessibleByMouse)

        grid.addWidget(title, 0, 0, 1, 2, Qt.AlignHCenter)
        y = 3

        rows = [
            ('fw_version', _("Firmware Version")),
            ('fw_built', _("Build Date")),
            ('bl_version', _("Bootloader")),
            ('xfp', _("Master Fingerprint")),
            ('serial', _("USB Serial")),
        ]
        for row_num, (member_name, label) in enumerate(rows):
            widget = QLabel('<tt>000000000000')
            widget.setTextInteractionFlags(Qt.TextSelectableByMouse
                                           | Qt.TextSelectableByKeyboard)

            grid.addWidget(QLabel(label), y, 0, 1, 1, Qt.AlignRight)
            grid.addWidget(widget, y, 1, 1, 1, Qt.AlignLeft)
            setattr(self, member_name, widget)
            y += 1
        body_layout.addLayout(grid)

        upg_btn = QPushButton('Upgrade')

        #upg_btn.setDefault(False)
        def _start_upgrade():
            thread.add(connect_and_doit, on_success=self.start_upgrade)

        upg_btn.clicked.connect(_start_upgrade)

        y += 3
        grid.addWidget(upg_btn, y, 0)
        grid.addWidget(CloseButton(self), y, 1)

        dialog_vbox = QVBoxLayout(self)
        dialog_vbox.addWidget(body)

        # Fetch values and show them
        thread.add(connect_and_doit, on_success=self.show_values)
예제 #33
0
    def __init__(self, tx, parent, desc, prompt_if_unsaved):
        '''Transactions in the wallet will show their description.
        Pass desc to give a description for txs not yet in the wallet.
        '''
        # We want to be a top-level window
        QDialog.__init__(self, parent=None)
        # Take a copy; it might get updated in the main window by
        # e.g. the FX plugin.  If this happens during or after a long
        # sign operation the signatures are lost.
        self.tx = tx = copy.deepcopy(tx)
        try:
            self.tx.deserialize()
        except BaseException as e:
            raise SerializationError(e)
        self.main_window = parent
        self.wallet = parent.wallet
        self.prompt_if_unsaved = prompt_if_unsaved
        self.saved = False
        self.desc = desc

        # if the wallet can populate the inputs with more info, do it now.
        # as a result, e.g. we might learn an imported address tx is segwit,
        # in which case it's ok to display txid
        self.wallet.add_input_info_to_all_inputs(tx)

        self.setMinimumWidth(950)
        self.setWindowTitle(_("Transaction"))

        vbox = QVBoxLayout()
        self.setLayout(vbox)

        vbox.addWidget(QLabel(_("Transaction ID:")))
        self.tx_hash_e = ButtonsLineEdit()
        qr_show = lambda: parent.show_qrcode(
            str(self.tx_hash_e.text()), 'Transaction ID', parent=self)
        self.tx_hash_e.addButton(":icons/qrcode.png", qr_show,
                                 _("Show as QR code"))
        self.tx_hash_e.setReadOnly(True)
        vbox.addWidget(self.tx_hash_e)
        self.tx_desc = QLabel()
        vbox.addWidget(self.tx_desc)
        self.status_label = QLabel()
        vbox.addWidget(self.status_label)
        self.date_label = QLabel()
        vbox.addWidget(self.date_label)
        self.amount_label = QLabel()
        vbox.addWidget(self.amount_label)
        self.size_label = QLabel()
        vbox.addWidget(self.size_label)
        self.fee_label = QLabel()
        vbox.addWidget(self.fee_label)

        self.add_io(vbox)

        vbox.addStretch(1)

        self.sign_button = b = QPushButton(_("Sign"))
        b.clicked.connect(self.sign)

        self.broadcast_button = b = QPushButton(_("Broadcast"))
        b.clicked.connect(self.do_broadcast)

        self.save_button = b = QPushButton(_("Save"))
        save_button_disabled = not tx.is_complete()
        b.setDisabled(save_button_disabled)
        if save_button_disabled:
            b.setToolTip(SAVE_BUTTON_DISABLED_TOOLTIP)
        else:
            b.setToolTip(SAVE_BUTTON_ENABLED_TOOLTIP)
        b.clicked.connect(self.save)

        self.export_button = b = QPushButton(_("Export"))
        b.clicked.connect(self.export)

        self.cancel_button = b = QPushButton(_("Close"))
        b.clicked.connect(self.close)
        b.setDefault(True)

        self.qr_button = b = QPushButton()
        b.setIcon(QIcon(":icons/qrcode.png"))
        b.clicked.connect(self.show_qr)

        self.copy_button = CopyButton(lambda: str(self.tx), parent.app)

        # Action buttons
        self.buttons = [
            self.sign_button, self.broadcast_button, self.cancel_button
        ]
        # Transaction sharing buttons
        self.sharing_buttons = [
            self.copy_button, self.qr_button, self.export_button,
            self.save_button
        ]

        run_hook('transaction_dialog', self)

        hbox = QHBoxLayout()
        hbox.addLayout(Buttons(*self.sharing_buttons))
        hbox.addStretch(1)
        hbox.addLayout(Buttons(*self.buttons))
        vbox.addLayout(hbox)
        self.update()
예제 #34
0
 def done_processing_error(self, dialog, result):
     traceback.print_exception(*result, file=sys.stderr)
     dialog.show_error(_("Error synchronising labels") + ':\n' + str(result[:2]))
예제 #35
0
from electrum_grs.i18n import _

fullname = _('Audio MODEM')
description = _('Provides support for air-gapped transaction signing.')
requires = [('amodem', 'http://github.com/romanz/amodem/')]
available_for = []
예제 #36
0
 def contextMenuEvent(self, e):
     m = self.createStandardContextMenu()
     m.addAction(_("Read QR code"), self.qr_input)
     m.exec_(e.globalPos())
예제 #37
0
 def __init__(self, text=""):
     ButtonsTextEdit.__init__(self, text)
     self.setReadOnly(0)
     self.addButton(":icons/file.png", self.file_input, _("Read file"))
     self.addButton(":icons/qrcode.png", self.qr_input, _("Read QR code"))
     run_hook('scan_text_edit', self)
예제 #38
0
 def copy_to_clipboard():
     p = qscreen.grabWindow(qrw.winId())
     QApplication.clipboard().setPixmap(p)
     self.show_message(_("QR code copied to clipboard"))
예제 #39
0
 def print_qr():
     p = qscreen.grabWindow(qrw.winId())
     p.save(filename, 'png')
     self.show_message(_("QR code saved to file") + " " + filename)
예제 #40
0
    def __init__(self, network, config, wizard=False):
        self.network = network
        self.config = config
        self.protocol = None
        self.tor_proxy = None

        self.tabs = tabs = QTabWidget()
        server_tab = QWidget()
        proxy_tab = QWidget()
        blockchain_tab = QWidget()
        tabs.addTab(blockchain_tab, _('Overview'))
        tabs.addTab(server_tab, _('Server'))
        tabs.addTab(proxy_tab, _('Proxy'))

        # server tab
        grid = QGridLayout(server_tab)
        grid.setSpacing(8)

        self.server_host = QLineEdit()
        self.server_host.setFixedWidth(200)
        self.server_port = QLineEdit()
        self.server_port.setFixedWidth(60)
        self.autoconnect_cb = QCheckBox(_('Select server automatically'))
        self.autoconnect_cb.setEnabled(
            self.config.is_modifiable('auto_connect'))

        self.server_host.editingFinished.connect(self.set_server)
        self.server_port.editingFinished.connect(self.set_server)
        self.autoconnect_cb.clicked.connect(self.set_server)
        self.autoconnect_cb.clicked.connect(self.update)

        msg = ' '.join([
            _("If auto-connect is enabled, Electrum-GRS will always use a server that is on the longest blockchain."
              ),
            _("If it is disabled, you have to choose a server you want to use. Electrum-GRS will warn you if your server is lagging."
              )
        ])
        grid.addWidget(self.autoconnect_cb, 0, 0, 1, 3)
        grid.addWidget(HelpButton(msg), 0, 4)

        grid.addWidget(QLabel(_('Server') + ':'), 1, 0)
        grid.addWidget(self.server_host, 1, 1, 1, 2)
        grid.addWidget(self.server_port, 1, 3)

        label = _('Server peers') if network.is_connected() else _(
            'Default Servers')
        grid.addWidget(QLabel(label), 2, 0, 1, 5)
        self.servers_list = ServerListWidget(self)
        grid.addWidget(self.servers_list, 3, 0, 1, 5)

        # Proxy tab
        grid = QGridLayout(proxy_tab)
        grid.setSpacing(8)

        # proxy setting
        self.proxy_cb = QCheckBox(_('Use proxy'))
        self.proxy_cb.clicked.connect(self.check_disable_proxy)
        self.proxy_cb.clicked.connect(self.set_proxy)

        self.proxy_mode = QComboBox()
        self.proxy_mode.addItems(['SOCKS4', 'SOCKS5', 'HTTP'])
        self.proxy_host = QLineEdit()
        self.proxy_host.setFixedWidth(200)
        self.proxy_port = QLineEdit()
        self.proxy_port.setFixedWidth(60)
        self.proxy_user = QLineEdit()
        self.proxy_user.setPlaceholderText(_("Proxy user"))
        self.proxy_password = QLineEdit()
        self.proxy_password.setPlaceholderText(_("Password"))
        self.proxy_password.setEchoMode(QLineEdit.Password)
        self.proxy_password.setFixedWidth(60)

        self.proxy_mode.currentIndexChanged.connect(self.set_proxy)
        self.proxy_host.editingFinished.connect(self.set_proxy)
        self.proxy_port.editingFinished.connect(self.set_proxy)
        self.proxy_user.editingFinished.connect(self.set_proxy)
        self.proxy_password.editingFinished.connect(self.set_proxy)

        self.proxy_mode.currentIndexChanged.connect(
            self.proxy_settings_changed)
        self.proxy_host.textEdited.connect(self.proxy_settings_changed)
        self.proxy_port.textEdited.connect(self.proxy_settings_changed)
        self.proxy_user.textEdited.connect(self.proxy_settings_changed)
        self.proxy_password.textEdited.connect(self.proxy_settings_changed)

        self.tor_cb = QCheckBox(_("Use Tor Proxy"))
        self.tor_cb.setIcon(QIcon(":icons/tor_logo.png"))
        self.tor_cb.hide()
        self.tor_cb.clicked.connect(self.use_tor_proxy)

        grid.addWidget(self.tor_cb, 1, 0, 1, 3)
        grid.addWidget(self.proxy_cb, 2, 0, 1, 3)
        grid.addWidget(
            HelpButton(
                _('Proxy settings apply to all connections: with Electrum-GRS servers, but also with third-party services.'
                  )), 2, 4)
        grid.addWidget(self.proxy_mode, 4, 1)
        grid.addWidget(self.proxy_host, 4, 2)
        grid.addWidget(self.proxy_port, 4, 3)
        grid.addWidget(self.proxy_user, 5, 2)
        grid.addWidget(self.proxy_password, 5, 3)
        grid.setRowStretch(7, 1)

        # Blockchain Tab
        grid = QGridLayout(blockchain_tab)
        msg = ' '.join([
            _("Electrum-GRS connects to several nodes in order to download block headers and find out the longest blockchain."
              ),
            _("This blockchain is used to verify the transactions sent by your transaction server."
              )
        ])
        self.status_label = QLabel('')
        grid.addWidget(QLabel(_('Status') + ':'), 0, 0)
        grid.addWidget(self.status_label, 0, 1, 1, 3)
        grid.addWidget(HelpButton(msg), 0, 4)

        self.server_label = QLabel('')
        msg = _(
            "Electrum-GRS sends your wallet addresses to a single server, in order to receive your transaction history."
        )
        grid.addWidget(QLabel(_('Server') + ':'), 1, 0)
        grid.addWidget(self.server_label, 1, 1, 1, 3)
        grid.addWidget(HelpButton(msg), 1, 4)

        self.height_label = QLabel('')
        msg = _('This is the height of your local copy of the blockchain.')
        grid.addWidget(QLabel(_('Blockchain') + ':'), 2, 0)
        grid.addWidget(self.height_label, 2, 1)
        grid.addWidget(HelpButton(msg), 2, 4)

        self.split_label = QLabel('')
        grid.addWidget(self.split_label, 3, 0, 1, 3)

        self.nodes_list_widget = NodesListWidget(self)
        grid.addWidget(self.nodes_list_widget, 5, 0, 1, 5)

        vbox = QVBoxLayout()
        vbox.addWidget(tabs)
        self.layout_ = vbox
        # tor detector
        self.td = td = TorDetector()
        td.found_proxy.connect(self.suggest_proxy)
        td.start()

        self.fill_in_proxy_settings()
        self.update()
예제 #41
0
 def import_invoices(self):
     import_meta_gui(self.parent, _('invoices'),
                     self.parent.invoices.import_file, self.on_update)
예제 #42
0
 def decrypt_message(self, pubkey, message, password):
     raise BaseException(_('Decrypt method is not implemented in Trezor'))
예제 #43
0
 def receive_menu(self, menu, addrs):
     if not self.wallet.is_watching_only() and self.atleast_version(
             1, 3) and len(addrs) == 1:
         menu.addAction(_("Show on TREZOR"),
                        lambda: self.show_address(addrs[0]))
예제 #44
0
    def __init__(self, text=None):
        ButtonsTextEdit.__init__(self, text)
        self.setReadOnly(1)
        self.addButton(":icons/qrcode.png", self.qr_show, _("Show as QR code"))

        run_hook('show_text_edit', self)
예제 #45
0
    def show_settings_dialog(self, window, success):
        if not success:
            window.show_message(_('Server not reachable.'))
            return

        wallet = window.wallet
        d = WindowModalDialog(window, _("TrustedCoin Information"))
        d.setMinimumSize(500, 200)
        vbox = QVBoxLayout(d)
        hbox = QHBoxLayout()

        logo = QLabel()
        logo.setPixmap(QPixmap(":icons/trustedcoin-status.png"))
        msg = _('This wallet is protected by TrustedCoin\'s two-factor authentication.') + '<br/>'\
              + _("For more information, visit") + " <a href=\"https://api.trustedcoin.com/#/electrum-help\">https://api.trustedcoin.com/#/electrum-help</a>"
        label = QLabel(msg)
        label.setOpenExternalLinks(1)

        hbox.addStretch(10)
        hbox.addWidget(logo)
        hbox.addStretch(10)
        hbox.addWidget(label)
        hbox.addStretch(10)

        vbox.addLayout(hbox)
        vbox.addStretch(10)

        msg = _(
            'TrustedCoin charges a small fee to co-sign transactions. The fee depends on how many prepaid transactions you buy. An extra output is added to your transaction every time you run out of prepaid transactions.'
        ) + '<br/>'
        label = QLabel(msg)
        label.setWordWrap(1)
        vbox.addWidget(label)

        vbox.addStretch(10)
        grid = QGridLayout()
        vbox.addLayout(grid)

        price_per_tx = wallet.price_per_tx
        n_prepay = wallet.num_prepay(self.config)
        i = 0
        for k, v in sorted(price_per_tx.items()):
            if k == 1:
                continue
            grid.addWidget(QLabel("Pay every %d transactions:" % k), i, 0)
            grid.addWidget(
                QLabel(
                    window.format_amount(v / k) + ' ' + window.base_unit() +
                    "/tx"), i, 1)
            b = QRadioButton()
            b.setChecked(k == n_prepay)
            b.clicked.connect(lambda b, k=k: self.config.set_key(
                'trustedcoin_prepay', k, True))
            grid.addWidget(b, i, 2)
            i += 1

        n = wallet.billing_info.get('tx_remaining', 0)
        grid.addWidget(
            QLabel(_("Your wallet has {} prepaid transactions.").format(n)), i,
            0)
        vbox.addLayout(Buttons(CloseButton(d)))
        d.exec_()
예제 #46
0
from electrum_grs.i18n import _

fullname = _('Two Factor Authentication')
description = ''.join([
    _("This plugin adds two-factor authentication to your wallet."), '<br/>',
    _("For more information, visit"),
    " <a href=\"https://api.trustedcoin.com/#/electrum-help\">https://api.trustedcoin.com/#/electrum-help</a>"
])
requires_wallet_type = ['2fa']
registers_wallet_type = '2fa'
available_for = []  # Disabled
예제 #47
0
 def done_processing_success(self, dialog, result):
     dialog.show_message(_("Your labels have been synchronised."))
예제 #48
0
from electrum_grs.i18n import _

fullname = _('Email')
description = _("Send and receive payment request with an email account")
available_for = ['qt']
예제 #49
0
    def add_io(self, vbox):
        if self.tx.locktime > 0:
            vbox.addWidget(QLabel("LockTime: %d\n" % self.tx.locktime))

        vbox.addWidget(QLabel(_("Inputs") + ' (%d)' % len(self.tx.inputs())))
        ext = QTextCharFormat()
        rec = QTextCharFormat()
        rec.setBackground(QBrush(ColorScheme.GREEN.as_color(background=True)))
        rec.setToolTip(_("Wallet receive address"))
        chg = QTextCharFormat()
        chg.setBackground(QBrush(ColorScheme.YELLOW.as_color(background=True)))
        chg.setToolTip(_("Wallet change address"))
        twofactor = QTextCharFormat()
        twofactor.setBackground(
            QBrush(ColorScheme.BLUE.as_color(background=True)))
        twofactor.setToolTip(
            _("TrustedCoin (2FA) fee for the next batch of transactions"))

        def text_format(addr):
            if self.wallet.is_mine(addr):
                return chg if self.wallet.is_change(addr) else rec
            elif self.wallet.is_billing_address(addr):
                return twofactor
            return ext

        def format_amount(amt):
            return self.main_window.format_amount(amt, whitespaces=True)

        i_text = QTextEdit()
        i_text.setFont(QFont(MONOSPACE_FONT))
        i_text.setReadOnly(True)
        i_text.setMaximumHeight(100)
        cursor = i_text.textCursor()
        for x in self.tx.inputs():
            if x['type'] == 'coinbase':
                cursor.insertText('coinbase')
            else:
                prevout_hash = x.get('prevout_hash')
                prevout_n = x.get('prevout_n')
                cursor.insertText(prevout_hash + ":%-4d " % prevout_n, ext)
                addr = self.wallet.get_txin_address(x)
                if addr is None:
                    addr = ''
                cursor.insertText(addr, text_format(addr))
                if x.get('value'):
                    cursor.insertText(format_amount(x['value']), ext)
            cursor.insertBlock()

        vbox.addWidget(i_text)
        vbox.addWidget(QLabel(_("Outputs") + ' (%d)' % len(self.tx.outputs())))
        o_text = QTextEdit()
        o_text.setFont(QFont(MONOSPACE_FONT))
        o_text.setReadOnly(True)
        o_text.setMaximumHeight(100)
        cursor = o_text.textCursor()
        for addr, v in self.tx.get_outputs():
            cursor.insertText(addr, text_format(addr))
            if v is not None:
                cursor.insertText('\t', ext)
                cursor.insertText(format_amount(v), ext)
            cursor.insertBlock()
        vbox.addWidget(o_text)
예제 #50
0
 def addCopyButton(self, app):
     self.app = app
     f = lambda: self.app.clipboard().setText(str(self.text()))
     self.addButton(":icons/copy.png", f, _("Copy to Clipboard"))
예제 #51
0
    def update(self):
        desc = self.desc
        base_unit = self.main_window.base_unit()
        format_amount = self.main_window.format_amount
        tx_hash, status, label, can_broadcast, can_rbf, amount, fee, height, conf, timestamp, exp_n = self.wallet.get_tx_info(
            self.tx)
        size = self.tx.estimated_size()
        self.broadcast_button.setEnabled(can_broadcast)
        can_sign = not self.tx.is_complete() and \
            (self.wallet.can_sign(self.tx) or bool(self.main_window.tx_external_keypairs))
        self.sign_button.setEnabled(can_sign)
        self.tx_hash_e.setText(tx_hash or _('Unknown'))
        if desc is None:
            self.tx_desc.hide()
        else:
            self.tx_desc.setText(_("Description") + ': ' + desc)
            self.tx_desc.show()
        self.status_label.setText(_('Status:') + ' ' + status)

        if timestamp:
            time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(
                ' ')[:-3]
            self.date_label.setText(_("Date: {}").format(time_str))
            self.date_label.show()
        elif exp_n:
            text = '%.2f MB' % (exp_n / 1000000)
            self.date_label.setText(
                _('Position in mempool: {} from tip').format(text))
            self.date_label.show()
        else:
            self.date_label.hide()
        if amount is None:
            amount_str = _("Transaction unrelated to your wallet")
        elif amount > 0:
            amount_str = _("Amount received:"
                           ) + ' %s' % format_amount(amount) + ' ' + base_unit
        else:
            amount_str = _("Amount sent:"
                           ) + ' %s' % format_amount(-amount) + ' ' + base_unit
        size_str = _("Size:") + ' %d bytes' % size
        fee_str = _("Fee") + ': %s' % (format_amount(fee) + ' ' + base_unit
                                       if fee is not None else _('unknown'))
        if fee is not None:
            fee_rate = fee / size * 1000
            fee_str += '  ( %s ) ' % self.main_window.format_fee_rate(fee_rate)
            confirm_rate = simple_config.FEERATE_WARNING_HIGH_FEE
            if fee_rate > confirm_rate:
                fee_str += ' - ' + _('Warning') + ': ' + _("high fee") + '!'
        self.amount_label.setText(amount_str)
        self.fee_label.setText(fee_str)
        self.size_label.setText(size_str)
        run_hook('transaction_dialog_update', self)
예제 #52
0
from PyQt5.QtWidgets import *

import qrcode
from qrcode import exceptions

from electrum_grs.bitcoin import base_encode
from electrum_grs.i18n import _
from electrum_grs.plugin import run_hook
from electrum_grs import simple_config

from electrum_grs.util import bfh
from electrum_grs.transaction import SerializationError

from .util import *

SAVE_BUTTON_ENABLED_TOOLTIP = _("Save transaction offline")
SAVE_BUTTON_DISABLED_TOOLTIP = _(
    "Please sign this transaction in order to save it")

dialogs = []  # Otherwise python randomly garbage collects the dialogs...


def show_transaction(tx, parent, desc=None, prompt_if_unsaved=False):
    try:
        d = TxDialog(tx, parent, desc, prompt_if_unsaved)
    except SerializationError as e:
        traceback.print_exc(file=sys.stderr)
        parent.show_critical(
            _("Electrum-GRS was unable to deserialize the transaction:") +
            "\n" + str(e))
    else:
예제 #53
0
 def settings_widget(self, window):
     return EnterButton(_('Settings'),
                        partial(self.settings_dialog, window))
예제 #54
0
 def setup_dialog(self):
     self.show_error(
         _('Please initialization your Coldcard while disconnected.'))
     return
예제 #55
0
 def new_electrum_version(self):
     if self.new_version:
         self.setText(
             _("New version available") + ": " + self.latest_version)
         self.sb.insertPermanentWidget(1, self)
예제 #56
0
 def callback_PassphraseRequest(self, req):
     msg = _("Please enter your Trezor passphrase.")
     passphrase = self.handler.get_passphrase(msg)
     if passphrase is None:
         return proto.Cancel()
     return proto.PassphraseAck(passphrase=passphrase)
예제 #57
0
 def contextMenuEvent(self, e):
     m = self.createStandardContextMenu()
     m.addAction(_("Show as QR code"), self.qr_show)
     m.exec_(e.globalPos())
예제 #58
0
 def __init__(self, parent):
     QTreeWidget.__init__(self)
     self.parent = parent
     self.setHeaderLabels([_('Connected node'), _('Height')])
     self.setContextMenuPolicy(Qt.CustomContextMenu)
     self.customContextMenuRequested.connect(self.create_menu)
예제 #59
0
 def export_invoices(self):
     export_meta_gui(self.parent, _('invoices'),
                     self.parent.invoices.export_file)
예제 #60
0
 def decrypt_message(self, sequence, message, password):
     raise RuntimeError(
         _('Encryption and decryption are not implemented by {}').format(
             self.device))