Esempio n. 1
0
    def do_full_pull(self, force = False):
        try:
            connection = httplib.HTTPConnection(self.target_host)
            connection.request("GET", ("/api/wallets/%s/labels.json?auth_token=%s" % (self.wallet_id, self.auth_token())),"", {'Content-Type': 'application/json'})
            response = connection.getresponse()
            if response.reason == httplib.responses[httplib.NOT_FOUND]:
                return
            try:
                response = json.loads(response.read())
            except ValueError as e:
                return False

            if "error" in response:
                QMessageBox.warning(None, _("Error"),_("Could not sync labels: %s" % response["error"]))
                return False

            for label in response:
                 decoded_key = self.decode(label["external_id"]) 
                 decoded_label = self.decode(label["text"]) 
                 if force or not self.wallet.labels.get(decoded_key):
                     self.wallet.labels[decoded_key] = decoded_label 
            return True
        except socket.gaierror as e:
            print_error('Error connecting to service: %s ' %  e)
            return False
Esempio n. 2
0
 def contextMenuEvent(self, e):
     m = self.createStandardContextMenu()
     if self.isReadOnly():
         m.addAction(_("Show as QR code"), self.qr_show)
     else:
         m.addAction(_("Read QR code"), self.qr_input)
     m.exec_(e.globalPos())
Esempio n. 3
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)
Esempio n. 4
0
 def seed_options(self):
     dialog = QDialog()
     vbox = QVBoxLayout(dialog)
     if 'ext' in self.options:
         cb_ext = QCheckBox(_('Extend this seed with custom words'))
         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, Litecoin 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.'),
                     _('We recommend to use seeds generated by Electrum 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)
         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
Esempio n. 5
0
    def network_dialog(self):
        grid = QGridLayout()
        grid.setSpacing(5)
        label = QLabel(_("Electrum 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 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
Esempio n. 6
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(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

        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.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))
                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)
def enter_seed_box(is_restore, sid=None):

    vbox = QVBoxLayout()
    if is_restore:
        msg = _("Please enter your wallet seed, or master public key") + "\n"
    else:
        msg = _("Your seed is important!") \
              + "\n" + _("To make sure that you have properly saved your seed, please retype it here.")
        
    logo = QLabel()
    logo.setPixmap(QPixmap(icon_filename(sid)).scaledToWidth(56))
    logo.setMaximumWidth(60)

    label = QLabel(msg)
    label.setWordWrap(True)

    seed_e = QTextEdit()
    seed_e.setMaximumHeight(100)

    vbox.addWidget(label)

    grid = QGridLayout()
    grid.addWidget(logo, 0, 0)
    grid.addWidget(seed_e, 0, 1)

    vbox.addLayout(grid)
    return vbox, seed_e
Esempio n. 8
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()
Esempio n. 9
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)
    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)
Esempio n. 11
0
    def create_menu(self, position):
        self.selectedIndexes()
        item = self.currentItem()
        if not item:
            return
        column = self.currentColumn()
        tx_hash = str(item.data(0, Qt.UserRole).toString())
        if not tx_hash:
            return
        if column is 0:
            column_title = "ID"
            column_data = tx_hash
        else:
            column_title = self.headerItem().text(column)
            column_data = item.text(column)

        tx_URL = block_explorer_URL(self.config, 'tx', tx_hash)
        height, conf, timestamp = self.wallet.get_tx_height(tx_hash)
        tx = self.wallet.transactions.get(tx_hash)
        is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(tx)
        rbf = is_mine and height <=0 and tx and not tx.is_final()
        menu = QMenu()

        menu.addAction(_("Copy %s")%column_title, lambda: self.parent.app.clipboard().setText(column_data))
        if column in self.editable_columns:
            menu.addAction(_("Edit %s")%column_title, lambda: self.editItem(item, column))

        menu.addAction(_("Details"), lambda: self.parent.show_transaction(tx))
        if rbf:
            menu.addAction(_("Increase fee"), lambda: self.parent.bump_fee_dialog(tx))
        if tx_URL:
            menu.addAction(_("View on block explorer"), lambda: webbrowser.open(tx_URL))
        menu.exec_(self.viewport().mapToGlobal(position))
Esempio n. 12
0
    def load_wallet_file(self, filename):
        try:
            storage = WalletStorage(filename)
        except Exception as e:
            QMessageBox.information(None, _('Error'), str(e), _('OK'))
            return
        if not storage.file_exists:
            recent = self.config.get('recently_open', [])
            if filename in recent:
                recent.remove(filename)
                self.config.set_key('recently_open', recent)
            action = 'new'
        else:
            try:
                wallet = Wallet(storage)
            except BaseException as e:
                traceback.print_exc(file=sys.stdout)
                QMessageBox.warning(None, _('Warning'), str(e), _('OK'))
                return
            action = wallet.get_action()
        # run wizard
        if action is not None:
            wizard = InstallWizard(self.app, self.config, self.network, storage)
            wallet = wizard.run(action)
            # keep current wallet
            if not wallet:
                return
        else:
            wallet.start_threads(self.network)

        return wallet
Esempio n. 13
0
 def qr_input(self):
     from electrum_ltc import qrscanner, get_config
     try:
         data = qrscanner.scan_qr(get_config())
     except BaseException, e:
         QMessageBox.warning(self, _('Error'), _(e), _('OK'))
         return ""
Esempio n. 14
0
    def add_io(self, vbox):

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

        vbox.addWidget(QLabel(_("Inputs")))
        def format_input(x):
            if x.get('is_coinbase'):
                return 'coinbase'
            else:
                _hash = x.get('prevout_hash')
                return _hash[0:16] + '...' + _hash[-8:] + ":%d"%x.get('prevout_n') + u'\t' + "%s"%x.get('address')
        lines = map(format_input, self.tx.inputs )
        i_text = QTextEdit()
        i_text.setText('\n'.join(lines))
        i_text.setReadOnly(True)
        i_text.setMaximumHeight(100)
        vbox.addWidget(i_text)

        vbox.addWidget(QLabel(_("Outputs")))
        lines = map(lambda x: x[0] + u'\t\t' + self.parent.format_amount(x[1]) if x[1] else x[0], self.tx.get_outputs())
        o_text = QTextEdit()
        o_text.setText('\n'.join(lines))
        o_text.setReadOnly(True)
        o_text.setMaximumHeight(100)
        vbox.addWidget(o_text)
Esempio n. 15
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)
Esempio n. 16
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_()
Esempio n. 17
0
 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"))
Esempio n. 18
0
    def make_cypherseed(self, img, rawnoise, calibration=False, is_seed = True):
        img = img.convertToFormat(QImage.Format_Mono)
        p = QPainter()
        p.begin(img)
        p.setCompositionMode(26) #xor
        p.drawImage(0, 0, rawnoise)
        p.end()
        cypherseed = self.pixelcode_2x2(img)
        cypherseed = QBitmap.fromImage(cypherseed)
        cypherseed = cypherseed.scaled(self.f_size, Qt.KeepAspectRatio)
        cypherseed = self.overlay_marks(cypherseed, True, calibration)

        if not is_seed:
            self.filename_prefix = 'custom_secret_'
            self.was = _('Custom secret')
        else:
            self.filename_prefix = self.wallet_name + '_seed_'
            self.was = self.wallet_name + ' ' + _('seed')
            if self.extension:
                self.ext_warning(self.c_dialog)


        if not calibration:
            self.toPdf(QImage(cypherseed))
            QDesktopServices.openUrl(QUrl.fromLocalFile(self.get_path_to_revealer_file('.pdf')))
            cypherseed.save(self.get_path_to_revealer_file('.png'))
            self.bcrypt(self.c_dialog)
        return cypherseed
Esempio n. 19
0
    def context_menu(self):
        view_menu = QMenu()
        themes_menu = view_menu.addMenu(_("&Themes"))
        selected_theme = self.actuator.selected_theme()
        theme_group = QActionGroup(self)
        for theme_name in self.actuator.theme_names():
            theme_action = themes_menu.addAction(theme_name)
            theme_action.setCheckable(True)
            if selected_theme == theme_name:
                theme_action.setChecked(True)
            class SelectThemeFunctor:
                def __init__(self, theme_name, toggle_theme):
                    self.theme_name = theme_name
                    self.toggle_theme = toggle_theme
                def __call__(self, checked):
                    if checked:
                        self.toggle_theme(self.theme_name)
            delegate = SelectThemeFunctor(theme_name, self.toggle_theme)
            theme_action.toggled.connect(delegate)
            theme_group.addAction(theme_action)
        view_menu.addSeparator()

        show_receiving = view_menu.addAction(_("Show Receiving addresses"))
        show_receiving.setCheckable(True)
        show_receiving.toggled.connect(self.toggle_receiving_layout)
        show_receiving.setChecked(self.config.get("gui_show_receiving",False))

        show_history = view_menu.addAction(_("Show History"))
        show_history.setCheckable(True)
        show_history.toggled.connect(self.show_history)
        show_history.setChecked(self.config.get("gui_show_history",False))

        return view_menu
Esempio n. 20
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)
Esempio n. 21
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-LTC"), self.close)
     self.tray.setContextMenu(m)
Esempio n. 22
0
 def get_library_not_available_message(self) -> str:
     if hasattr(self, 'libraries_available_message'):
         message = self.libraries_available_message
     else:
         message = _("Missing libraries for {}.").format(self.name)
     message += '\n' + _("Make sure you install it with python3")
     return message
Esempio n. 23
0
    def query_multisig(self, action):
        cw = CosignWidget(2, 2)
        m_edit = QSpinBox()
        n_edit = QSpinBox()
        m_edit.setValue(2)
        n_edit.setValue(2)
        n_edit.setMinimum(2)
        n_edit.setMaximum(15)
        m_edit.setMinimum(1)
        m_edit.setMaximum(2)
        n_edit.valueChanged.connect(m_edit.setMaximum)

        n_edit.valueChanged.connect(cw.set_n)
        m_edit.valueChanged.connect(cw.set_m)

        hbox = QHBoxLayout()
        hbox.addWidget(QLabel(_('Require')))
        hbox.addWidget(m_edit)
        hbox.addWidget(QLabel(_('of')))
        hbox.addWidget(n_edit)
        hbox.addWidget(QLabel(_('signatures')))
        hbox.addStretch(1)

        vbox = QVBoxLayout()
        vbox.addWidget(cw)
        vbox.addWidget(WWLabel(_("Choose the number of signatures needed "
                          "to unlock funds in your wallet:")))
        vbox.addLayout(hbox)
        self.set_main_layout(vbox, _("Multi-Signature Wallet"))
        m = int(m_edit.value())
        n = int(n_edit.value())
        wallet_type = '%dof%d'%(m,n)
        return wallet_type
    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
Esempio n. 25
0
 def get_tooltip(self, pos, fee_rate):
     mempool = self.config.use_mempool_fees()
     target, estimate = self.config.get_fee_text(pos, self.dyn, mempool, fee_rate)
     if self.dyn:
         return _('Target') + ': ' + target + '\n' + _('Current rate') + ': ' + estimate
     else:
         return _('Fixed rate') + ': ' + target + '\n' + _('Estimate') + ': ' + estimate
Esempio n. 26
0
    def before_send(self):
        '''
        Change URL to address before making a send.
        IMPORTANT:
            return False to continue execution of the send
            return True to stop execution of the send
        '''

        if self.win.payto_e.is_multiline():  # only supports single line entries atm
            return False
        if self.win.payto_e.is_pr:
            return
        payto_e = str(self.win.payto_e.toPlainText())
        regex = re.compile(r'^([^\s]+) <([A-Za-z0-9]+)>')  # only do that for converted addresses
        try:
            (url, address) = regex.search(payto_e).groups()
        except AttributeError:
            return False

        if not self.validated:
            msgBox = QMessageBox()
            msgBox.setText(_('WARNING: the address ' + address + ' could not be validated via an additional security check, DNSSEC, and thus may not be correct.'))
            msgBox.setInformativeText(_('Do you wish to continue?'))
            msgBox.setStandardButtons(QMessageBox.Cancel | QMessageBox.Ok)
            msgBox.setDefaultButton(QMessageBox.Cancel)
            reply = msgBox.exec_()
            if reply != QMessageBox.Ok:
                return True

        return False
Esempio n. 27
0
    def __init__(self, parent):
        super(MatrixDialog, self).__init__(parent)
        self.setWindowTitle(_("Trezor Matrix Recovery"))
        self.num = 9
        self.loop = QEventLoop()

        vbox = QVBoxLayout(self)
        vbox.addWidget(WWLabel(MATRIX_RECOVERY))

        grid = QGridLayout()
        grid.setSpacing(0)
        self.char_buttons = []
        for y in range(3):
            for x in range(3):
                button = QPushButton('?')
                button.clicked.connect(partial(self.process_key, ord('1') + y * 3 + x))
                grid.addWidget(button, 3 - y, x)
                self.char_buttons.append(button)
        vbox.addLayout(grid)

        self.backspace_button = QPushButton("<=")
        self.backspace_button.clicked.connect(partial(self.process_key, Qt.Key_Backspace))
        self.cancel_button = QPushButton(_("Cancel"))
        self.cancel_button.clicked.connect(partial(self.process_key, Qt.Key_Escape))
        buttons = Buttons(self.backspace_button, self.cancel_button)
        vbox.addSpacing(40)
        vbox.addLayout(buttons)
        self.refresh()
        self.show()
Esempio n. 28
0
 def qr_input(self):
     from electrum_ltc import qrscanner
     try:
         data = qrscanner.scan_qr(self.win.config)
     except BaseException, e:
         QMessageBox.warning(self.win, _('Error'), _(e), _('OK'))
         return
Esempio n. 29
0
    def restore_or_create(self):

        vbox = QVBoxLayout()

        main_label = QLabel(_("Electrum 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 an existing wallet"))
        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.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)
        hbox, button = ok_cancel_buttons2(self, _('Next'))
        vbox.addLayout(hbox)
        self.set_layout(vbox)
        self.show()
        self.raise_()
        button.setDefault(True)

        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
Esempio n. 30
0
    def notify_transactions(self, *dt):
        '''
        '''
        if not self.network or not self.network.is_connected():
            return
        # temporarily disabled for merge
        return
        iface = self.network
        ptfn = iface.pending_transactions_for_notifications
        if len(ptfn) > 0:
            # Combine the transactions if there are more then three
            tx_amount = len(ptfn)
            if(tx_amount >= 3):
                total_amount = 0
                for tx in ptfn:
                    is_relevant, is_mine, v, fee = self.wallet.get_tx_value(tx)
                    if(v > 0):
                        total_amount += v
                self.notify(_("{txs}s new transactions received. Total amount"
                              "received in the new transactions {amount}s"
                              "{unit}s").format(txs=tx_amount,
                                    amount=self.format_amount(total_amount),
                                    unit=self.base_unit()))

                iface.pending_transactions_for_notifications = []
            else:
              for tx in iface.pending_transactions_for_notifications:
                  if tx:
                      iface.pending_transactions_for_notifications.remove(tx)
                      is_relevant, is_mine, v, fee = self.wallet.get_tx_value(tx)
                      if(v > 0):
                          self.notify(
                              _("{txs} new transaction received. {amount} {unit}").
                              format(txs=tx_amount, amount=self.format_amount(v),
                                     unit=self.base_unit))
Esempio n. 31
0
 def slider_moved():
     mins = timeout_slider.sliderPosition()
     timeout_minutes.setText(_("%2d minutes") % mins)
Esempio n. 32
0
 def decrypt_message(self, sequence, message, password):
     raise RuntimeError(
         _('Encryption and decryption are not implemented by %s') %
         self.device)
Esempio n. 33
0
 def settings_widget(self, window):
     return EnterButton(_('Settings'), partial(self.settings_dialog,
                                               window))
Esempio n. 34
0
 def receive_list_menu(self, menu, addr):
     window = get_parent_main_window(menu)
     menu.addAction(_("Send via e-mail"), lambda: self.send(window, addr))
Esempio n. 35
0
 def description(self):
     return _("Send and receive payment requests via email")
Esempio n. 36
0
 def __str__(self):
     header = _("Error connecting to {} server").format('Labels')
     reason = self.reason
     if isinstance(reason, BaseException):
         reason = repr(reason)
     return f"{header}: {reason}" if reason else header
Esempio n. 37
0
 def push(self, wallet: 'Abstract_Wallet'):
     if not wallet.network: raise Exception(_('You are offline.'))
     return asyncio.run_coroutine_threadsafe(self.push_thread(wallet), wallet.network.asyncio_loop).result()
Esempio n. 38
0
    def request_trezor_init_settings(self, wizard, method, device):
        vbox = QVBoxLayout()
        next_enabled = True
        label = QLabel(_("Enter a label to name your device:"))
        name = QLineEdit()
        hl = QHBoxLayout()
        hl.addWidget(label)
        hl.addWidget(name)
        hl.addStretch(1)
        vbox.addLayout(hl)

        def clean_text(widget):
            text = widget.toPlainText().strip()
            return ' '.join(text.split())

        if method in [TIM_NEW, TIM_RECOVER]:
            gb = QGroupBox()
            hbox1 = QHBoxLayout()
            gb.setLayout(hbox1)
            # KeepKey recovery doesn't need a word count
            if method == TIM_NEW or self.device == 'TREZOR':
                vbox.addWidget(gb)
            gb.setTitle(_("Select your seed length:"))
            bg = QButtonGroup()
            for i, count in enumerate([12, 18, 24]):
                rb = QRadioButton(gb)
                rb.setText(_("%d words") % count)
                bg.addButton(rb)
                bg.setId(rb, i)
                hbox1.addWidget(rb)
                rb.setChecked(True)
            cb_pin = QCheckBox(_('Enable PIN protection'))
            cb_pin.setChecked(True)
        else:
            text = QTextEdit()
            text.setMaximumHeight(60)
            if method == TIM_MNEMONIC:
                msg = _("Enter your BIP39 mnemonic:")
            else:
                msg = _("Enter the master private key beginning with xprv:")
                def set_enabled():
                    from electrum_ltc.keystore import is_xprv
                    wizard.next_button.setEnabled(is_xprv(clean_text(text)))
                text.textChanged.connect(set_enabled)
                next_enabled = False

            vbox.addWidget(QLabel(msg))
            vbox.addWidget(text)
            pin = QLineEdit()
            pin.setValidator(QRegExpValidator(QRegExp('[1-9]{0,9}')))
            pin.setMaximumWidth(100)
            hbox_pin = QHBoxLayout()
            hbox_pin.addWidget(QLabel(_("Enter your PIN (digits 1-9):")))
            hbox_pin.addWidget(pin)
            hbox_pin.addStretch(1)

        if method in [TIM_NEW, TIM_RECOVER]:
            vbox.addWidget(WWLabel(RECOMMEND_PIN))
            vbox.addWidget(cb_pin)
        else:
            vbox.addLayout(hbox_pin)

        passphrase_msg = WWLabel(PASSPHRASE_HELP_SHORT)
        passphrase_warning = WWLabel(PASSPHRASE_NOT_PIN)
        passphrase_warning.setStyleSheet("color: red")
        cb_phrase = QCheckBox(_('Enable passphrases'))
        cb_phrase.setChecked(False)
        vbox.addWidget(passphrase_msg)
        vbox.addWidget(passphrase_warning)
        vbox.addWidget(cb_phrase)

        wizard.exec_layout(vbox, next_enabled=next_enabled)

        if method in [TIM_NEW, TIM_RECOVER]:
            item = bg.checkedId()
            pin = cb_pin.isChecked()
        else:
            item = ' '.join(str(clean_text(text)).split())
            pin = str(pin.text())

        return (item, name.text(), pin, cb_phrase.isChecked())
Esempio n. 39
0
    def sign_transaction(self, tx, password):
        if tx.is_complete():
            return
        client = self.get_client()
        inputs = []
        inputsPaths = []
        pubKeys = []
        chipInputs = []
        redeemScripts = []
        signatures = []
        changePath = ""
        output = None
        p2shTransaction = False
        segwitTransaction = False
        pin = ""
        self.get_client(
        )  # prompt for the PIN before displaying the dialog if necessary

        # Fetch inputs of the transaction to sign
        derivations = self.get_tx_derivations(tx)
        for txin in tx.inputs():
            if txin['type'] == 'coinbase':
                self.give_error(
                    "Coinbase not supported")  # should never happen

            if txin['type'] in ['p2sh']:
                p2shTransaction = True

            if txin['type'] in ['p2wpkh-p2sh', 'p2wsh-p2sh']:
                if not self.get_client_electrum().supports_segwit():
                    self.give_error(MSG_NEEDS_FW_UPDATE_SEGWIT)
                segwitTransaction = True

            if txin['type'] in ['p2wpkh', 'p2wsh']:
                if not self.get_client_electrum().supports_native_segwit():
                    self.give_error(MSG_NEEDS_FW_UPDATE_SEGWIT)
                segwitTransaction = True

            pubkeys, x_pubkeys = tx.get_sorted_pubkeys(txin)
            for i, x_pubkey in enumerate(x_pubkeys):
                if x_pubkey in derivations:
                    signingPos = i
                    s = derivations.get(x_pubkey)
                    hwAddress = "%s/%d/%d" % (self.get_derivation()[2:], s[0],
                                              s[1])
                    break
            else:
                self.give_error("No matching x_key for sign_transaction"
                                )  # should never happen

            redeemScript = Transaction.get_preimage_script(txin)
            txin_prev_tx = txin.get('prev_tx')
            if txin_prev_tx is None and not Transaction.is_segwit_input(txin):
                raise UserFacingException(
                    _('Offline signing with {} is not supported for legacy inputs.'
                      ).format(self.device))
            txin_prev_tx_raw = txin_prev_tx.raw if txin_prev_tx else None
            inputs.append([
                txin_prev_tx_raw, txin['prevout_n'], redeemScript,
                txin['prevout_hash'], signingPos,
                txin.get('sequence', 0xffffffff - 1),
                txin.get('value')
            ])
            inputsPaths.append(hwAddress)
            pubKeys.append(pubkeys)

        # Sanity check
        if p2shTransaction:
            for txin in tx.inputs():
                if txin['type'] != 'p2sh':
                    self.give_error(
                        "P2SH / regular input mixed in same transaction not supported"
                    )  # should never happen

        txOutput = var_int(len(tx.outputs()))
        for o in tx.outputs():
            output_type, addr, amount = o.type, o.address, o.value
            txOutput += int_to_hex(amount, 8)
            script = tx.pay_script(output_type, addr)
            txOutput += var_int(len(script) // 2)
            txOutput += script
        txOutput = bfh(txOutput)

        # Recognize outputs
        # - only one output and one change is authorized (for hw.1 and nano)
        # - at most one output can bypass confirmation (~change) (for all)
        if not p2shTransaction:
            if not self.get_client_electrum().supports_multi_output():
                if len(tx.outputs()) > 2:
                    self.give_error(
                        "Transaction with more than 2 outputs not supported")
            has_change = False
            any_output_on_change_branch = is_any_tx_output_on_change_branch(tx)
            for o in tx.outputs():
                assert o.type == TYPE_ADDRESS
                info = tx.output_info.get(o.address)
                if (info is not None) and len(tx.outputs()) > 1 \
                        and not has_change:
                    index = info.address_index
                    on_change_branch = index[0] == 1
                    # prioritise hiding outputs on the 'change' branch from user
                    # because no more than one change address allowed
                    if on_change_branch == any_output_on_change_branch:
                        changePath = self.get_derivation(
                        )[2:] + "/%d/%d" % index
                        has_change = True
                    else:
                        output = o.address
                else:
                    output = o.address

        self.handler.show_message(
            _("Confirm Transaction on your Ledger device..."))
        try:
            # Get trusted inputs from the original transactions
            for utxo in inputs:
                sequence = int_to_hex(utxo[5], 4)
                if segwitTransaction:
                    tmp = bfh(utxo[3])[::-1]
                    tmp += bfh(int_to_hex(utxo[1], 4))
                    tmp += bfh(int_to_hex(utxo[6], 8))  # txin['value']
                    chipInputs.append({
                        'value': tmp,
                        'witness': True,
                        'sequence': sequence
                    })
                    redeemScripts.append(bfh(utxo[2]))
                elif not p2shTransaction:
                    txtmp = bitcoinTransaction(bfh(utxo[0]))
                    trustedInput = self.get_client().getTrustedInput(
                        txtmp, utxo[1])
                    trustedInput['sequence'] = sequence
                    chipInputs.append(trustedInput)
                    redeemScripts.append(txtmp.outputs[utxo[1]].script)
                else:
                    tmp = bfh(utxo[3])[::-1]
                    tmp += bfh(int_to_hex(utxo[1], 4))
                    chipInputs.append({'value': tmp, 'sequence': sequence})
                    redeemScripts.append(bfh(utxo[2]))

            # Sign all inputs
            firstTransaction = True
            inputIndex = 0
            rawTx = tx.serialize_to_network()
            self.get_client().enableAlternate2fa(False)
            if segwitTransaction:
                self.get_client().startUntrustedTransaction(
                    True,
                    inputIndex,
                    chipInputs,
                    redeemScripts[inputIndex],
                    version=tx.version)
                # we don't set meaningful outputAddress, amount and fees
                # as we only care about the alternateEncoding==True branch
                outputData = self.get_client().finalizeInput(
                    b'', 0, 0, changePath, bfh(rawTx))
                outputData['outputData'] = txOutput
                if outputData['confirmationNeeded']:
                    outputData['address'] = output
                    self.handler.finished()
                    pin = self.handler.get_auth(
                        outputData
                    )  # does the authenticate dialog and returns pin
                    if not pin:
                        raise UserWarning()
                    self.handler.show_message(
                        _("Confirmed. Signing Transaction..."))
                while inputIndex < len(inputs):
                    singleInput = [chipInputs[inputIndex]]
                    self.get_client().startUntrustedTransaction(
                        False,
                        0,
                        singleInput,
                        redeemScripts[inputIndex],
                        version=tx.version)
                    inputSignature = self.get_client().untrustedHashSign(
                        inputsPaths[inputIndex], pin, lockTime=tx.locktime)
                    inputSignature[0] = 0x30  # force for 1.4.9+
                    signatures.append(inputSignature)
                    inputIndex = inputIndex + 1
            else:
                while inputIndex < len(inputs):
                    self.get_client().startUntrustedTransaction(
                        firstTransaction,
                        inputIndex,
                        chipInputs,
                        redeemScripts[inputIndex],
                        version=tx.version)
                    # we don't set meaningful outputAddress, amount and fees
                    # as we only care about the alternateEncoding==True branch
                    outputData = self.get_client().finalizeInput(
                        b'', 0, 0, changePath, bfh(rawTx))
                    outputData['outputData'] = txOutput
                    if outputData['confirmationNeeded']:
                        outputData['address'] = output
                        self.handler.finished()
                        pin = self.handler.get_auth(
                            outputData
                        )  # does the authenticate dialog and returns pin
                        if not pin:
                            raise UserWarning()
                        self.handler.show_message(
                            _("Confirmed. Signing Transaction..."))
                    else:
                        # Sign input with the provided PIN
                        inputSignature = self.get_client().untrustedHashSign(
                            inputsPaths[inputIndex], pin, lockTime=tx.locktime)
                        inputSignature[0] = 0x30  # force for 1.4.9+
                        signatures.append(inputSignature)
                        inputIndex = inputIndex + 1
                    firstTransaction = False
        except UserWarning:
            self.handler.show_error(_('Cancelled by user'))
            return
        except BTChipException as e:
            if e.sw in (0x6985, 0x6d00):  # cancelled by user
                return
            elif e.sw == 0x6982:
                raise  # pin lock. decorator will catch it
            else:
                self.logger.exception('')
                self.give_error(e, True)
        except BaseException as e:
            self.logger.exception('')
            self.give_error(e, True)
        finally:
            self.handler.finished()

        for i, txin in enumerate(tx.inputs()):
            signingPos = inputs[i][4]
            tx.add_signature_to_txin(i, signingPos, bh2u(signatures[i]))
        tx.raw = tx.serialize()
Esempio n. 40
0
    def __init__(self, window, plugin, keystore, device_id):
        title = _("{} Settings").format(plugin.device)
        super(SettingsDialog, self).__init__(window, title)
        self.setMaximumWidth(540)

        devmgr = plugin.device_manager()
        config = devmgr.config
        handler = keystore.handler
        thread = keystore.thread
        hs_rows, hs_cols = (64, 128)

        def invoke_client(method, *args, **kw_args):
            unpair_after = kw_args.pop('unpair_after', False)

            def task():
                client = devmgr.client_by_id(device_id)
                if not client:
                    raise RuntimeError("Device not connected")
                if method:
                    getattr(client, method)(*args, **kw_args)
                if unpair_after:
                    devmgr.unpair_id(device_id)
                return client.features

            thread.add(task, on_success=update)

        def update(features):
            self.features = features
            set_label_enabled()
            if features.bootloader_hash:
                bl_hash = bh2u(features.bootloader_hash)
                bl_hash = "\n".join([bl_hash[:32], bl_hash[32:]])
            else:
                bl_hash = "N/A"
            noyes = [_("No"), _("Yes")]
            endis = [_("Enable Passphrases"), _("Disable Passphrases")]
            disen = [_("Disabled"), _("Enabled")]
            setchange = [_("Set a PIN"), _("Change PIN")]

            version = "%d.%d.%d" % (features.major_version,
                                    features.minor_version,
                                    features.patch_version)
            coins = ", ".join(coin.coin_name for coin in features.coins)

            device_label.setText(features.label)
            pin_set_label.setText(noyes[features.pin_protection])
            passphrases_label.setText(disen[features.passphrase_protection])
            bl_hash_label.setText(bl_hash)
            label_edit.setText(features.label)
            device_id_label.setText(features.device_id)
            initialized_label.setText(noyes[features.initialized])
            version_label.setText(version)
            coins_label.setText(coins)
            clear_pin_button.setVisible(features.pin_protection)
            clear_pin_warning.setVisible(features.pin_protection)
            pin_button.setText(setchange[features.pin_protection])
            pin_msg.setVisible(not features.pin_protection)
            passphrase_button.setText(endis[features.passphrase_protection])
            language_label.setText(features.language)

        def set_label_enabled():
            label_apply.setEnabled(label_edit.text() != self.features.label)

        def rename():
            invoke_client('change_label', label_edit.text())

        def toggle_passphrase():
            title = _("Confirm Toggle Passphrase Protection")
            currently_enabled = self.features.passphrase_protection
            if currently_enabled:
                msg = _("After disabling passphrases, you can only pair this "
                        "Electrum wallet if it had an empty passphrase.  "
                        "If its passphrase was not empty, you will need to "
                        "create a new wallet with the install wizard.  You "
                        "can use this wallet again at any time by re-enabling "
                        "passphrases and entering its passphrase.")
            else:
                msg = _("Your current Electrum wallet can only be used with "
                        "an empty passphrase.  You must create a separate "
                        "wallet with the install wizard for other passphrases "
                        "as each one generates a new set of addresses.")
            msg += "\n\n" + _("Are you sure you want to proceed?")
            if not self.question(msg, title=title):
                return
            invoke_client('toggle_passphrase', unpair_after=currently_enabled)

        def change_homescreen():
            dialog = QFileDialog(self, _("Choose Homescreen"))
            filename, __ = dialog.getOpenFileName()

            if filename.endswith('.toif'):
                img = open(filename, 'rb').read()
                if img[:8] != b'TOIf\x90\x00\x90\x00':
                    raise Exception('File is not a TOIF file with size of 144x144')
            else:
                from PIL import Image # FIXME
                im = Image.open(filename)
                if im.size != (128, 64):
                    raise Exception('Image must be 128 x 64 pixels')
                im = im.convert('1')
                pix = im.load()
                img = bytearray(1024)
                for j in range(64):
                    for i in range(128):
                        if pix[i, j]:
                            o = (i + j * 128)
                            img[o // 8] |= (1 << (7 - o % 8))
                img = bytes(img)
                invoke_client('change_homescreen', img)

        def clear_homescreen():
            invoke_client('change_homescreen', b'\x00')

        def set_pin():
            invoke_client('set_pin', remove=False)

        def clear_pin():
            invoke_client('set_pin', remove=True)

        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 litecoins in it!")
                if not self.question(msg, title=title,
                                     icon=QMessageBox.Critical):
                    return
            invoke_client('wipe_device', unpair_after=True)

        def slider_moved():
            mins = timeout_slider.sliderPosition()
            timeout_minutes.setText(_("%2d minutes") % mins)

        def slider_released():
            config.set_session_timeout(timeout_slider.sliderPosition() * 60)

        # Information tab
        info_tab = QWidget()
        info_layout = QVBoxLayout(info_tab)
        info_glayout = QGridLayout()
        info_glayout.setColumnStretch(2, 1)
        device_label = QLabel()
        pin_set_label = QLabel()
        passphrases_label = QLabel()
        version_label = QLabel()
        device_id_label = QLabel()
        bl_hash_label = QLabel()
        bl_hash_label.setWordWrap(True)
        coins_label = QLabel()
        coins_label.setWordWrap(True)
        language_label = QLabel()
        initialized_label = QLabel()
        rows = [
            (_("Device Label"), device_label),
            (_("PIN set"), pin_set_label),
            (_("Passphrases"), passphrases_label),
            (_("Firmware Version"), version_label),
            (_("Device ID"), device_id_label),
            (_("Bootloader Hash"), bl_hash_label),
            (_("Supported Coins"), coins_label),
            (_("Language"), language_label),
            (_("Initialized"), initialized_label),
        ]
        for row_num, (label, widget) in enumerate(rows):
            info_glayout.addWidget(QLabel(label), row_num, 0)
            info_glayout.addWidget(widget, row_num, 1)
        info_layout.addLayout(info_glayout)

        # Settings tab
        settings_tab = QWidget()
        settings_layout = QVBoxLayout(settings_tab)
        settings_glayout = QGridLayout()

        # Settings tab - Label
        label_msg = QLabel(_("Name this {}.  If you have mutiple devices "
                             "their labels help distinguish them.")
                           .format(plugin.device))
        label_msg.setWordWrap(True)
        label_label = QLabel(_("Device Label"))
        label_edit = QLineEdit()
        label_edit.setMinimumWidth(150)
        label_edit.setMaxLength(plugin.MAX_LABEL_LEN)
        label_apply = QPushButton(_("Apply"))
        label_apply.clicked.connect(rename)
        label_edit.textChanged.connect(set_label_enabled)
        settings_glayout.addWidget(label_label, 0, 0)
        settings_glayout.addWidget(label_edit, 0, 1, 1, 2)
        settings_glayout.addWidget(label_apply, 0, 3)
        settings_glayout.addWidget(label_msg, 1, 1, 1, -1)

        # Settings tab - PIN
        pin_label = QLabel(_("PIN Protection"))
        pin_button = QPushButton()
        pin_button.clicked.connect(set_pin)
        settings_glayout.addWidget(pin_label, 2, 0)
        settings_glayout.addWidget(pin_button, 2, 1)
        pin_msg = QLabel(_("PIN protection is strongly recommended.  "
                           "A PIN is your only protection against someone "
                           "stealing your litecoins if they obtain physical "
                           "access to your {}.").format(plugin.device))
        pin_msg.setWordWrap(True)
        pin_msg.setStyleSheet("color: red")
        settings_glayout.addWidget(pin_msg, 3, 1, 1, -1)

        # Settings tab - Homescreen
        if plugin.device != 'KeepKey':   # Not yet supported by KK firmware
            homescreen_layout = QHBoxLayout()
            homescreen_label = QLabel(_("Homescreen"))
            homescreen_change_button = QPushButton(_("Change..."))
            homescreen_clear_button = QPushButton(_("Reset"))
            homescreen_change_button.clicked.connect(change_homescreen)
            homescreen_clear_button.clicked.connect(clear_homescreen)
            homescreen_msg = QLabel(_("You can set the homescreen on your "
                                      "device to personalize it.  You must "
                                      "choose a {} x {} monochrome black and "
                                      "white image.").format(hs_rows, hs_cols))
            homescreen_msg.setWordWrap(True)
            settings_glayout.addWidget(homescreen_label, 4, 0)
            settings_glayout.addWidget(homescreen_change_button, 4, 1)
            settings_glayout.addWidget(homescreen_clear_button, 4, 2)
            settings_glayout.addWidget(homescreen_msg, 5, 1, 1, -1)

        # Settings tab - Session Timeout
        timeout_label = QLabel(_("Session Timeout"))
        timeout_minutes = QLabel()
        timeout_slider = QSlider(Qt.Horizontal)
        timeout_slider.setRange(1, 60)
        timeout_slider.setSingleStep(1)
        timeout_slider.setTickInterval(5)
        timeout_slider.setTickPosition(QSlider.TicksBelow)
        timeout_slider.setTracking(True)
        timeout_msg = QLabel(
            _("Clear the session after the specified period "
              "of inactivity.  Once a session has timed out, "
              "your PIN and passphrase (if enabled) must be "
              "re-entered to use the device."))
        timeout_msg.setWordWrap(True)
        timeout_slider.setSliderPosition(config.get_session_timeout() // 60)
        slider_moved()
        timeout_slider.valueChanged.connect(slider_moved)
        timeout_slider.sliderReleased.connect(slider_released)
        settings_glayout.addWidget(timeout_label, 6, 0)
        settings_glayout.addWidget(timeout_slider, 6, 1, 1, 3)
        settings_glayout.addWidget(timeout_minutes, 6, 4)
        settings_glayout.addWidget(timeout_msg, 7, 1, 1, -1)
        settings_layout.addLayout(settings_glayout)
        settings_layout.addStretch(1)

        # Advanced tab
        advanced_tab = QWidget()
        advanced_layout = QVBoxLayout(advanced_tab)
        advanced_glayout = QGridLayout()

        # Advanced tab - clear PIN
        clear_pin_button = QPushButton(_("Disable PIN"))
        clear_pin_button.clicked.connect(clear_pin)
        clear_pin_warning = QLabel(
            _("If you disable your PIN, anyone with physical access to your "
              "{} device can spend your litecoins.").format(plugin.device))
        clear_pin_warning.setWordWrap(True)
        clear_pin_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(clear_pin_button, 0, 2)
        advanced_glayout.addWidget(clear_pin_warning, 1, 0, 1, 5)

        # Advanced tab - toggle passphrase protection
        passphrase_button = QPushButton()
        passphrase_button.clicked.connect(toggle_passphrase)
        passphrase_msg = WWLabel(PASSPHRASE_HELP)
        passphrase_warning = WWLabel(PASSPHRASE_NOT_PIN)
        passphrase_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(passphrase_button, 3, 2)
        advanced_glayout.addWidget(passphrase_msg, 4, 0, 1, 5)
        advanced_glayout.addWidget(passphrase_warning, 5, 0, 1, 5)

        # Advanced tab - wipe device
        wipe_device_button = QPushButton(_("Wipe Device"))
        wipe_device_button.clicked.connect(wipe_device)
        wipe_device_msg = QLabel(
            _("Wipe the device, removing all data from it.  The firmware "
              "is left unchanged."))
        wipe_device_msg.setWordWrap(True)
        wipe_device_warning = QLabel(
            _("Only wipe a device if you have the recovery seed written down "
              "and the device wallet(s) are empty, otherwise the litecoins "
              "will be lost forever."))
        wipe_device_warning.setWordWrap(True)
        wipe_device_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(wipe_device_button, 6, 2)
        advanced_glayout.addWidget(wipe_device_msg, 7, 0, 1, 5)
        advanced_glayout.addWidget(wipe_device_warning, 8, 0, 1, 5)
        advanced_layout.addLayout(advanced_glayout)
        advanced_layout.addStretch(1)

        tabs = QTabWidget(self)
        tabs.addTab(info_tab, _("Information"))
        tabs.addTab(settings_tab, _("Settings"))
        tabs.addTab(advanced_tab, _("Advanced"))
        dialog_vbox = QVBoxLayout(self)
        dialog_vbox.addWidget(tabs)
        dialog_vbox.addLayout(Buttons(CloseButton(self)))

        # Update information
        invoke_client(None)
 def ignore_this_version(self):
     self.setText("")
     self.config.set_key("last_seen_version", self.latest_version, True)
     QMessageBox.information(self, _("Preference saved"), _("Notifications about this update will not be shown again."))
     self.dialog.done(0)
Esempio n. 42
0
import threading

from PyQt5.Qt import Qt
from PyQt5.Qt import QGridLayout, QInputDialog, QPushButton
from PyQt5.Qt import QVBoxLayout, QLabel
from electrum_ltc_gui.qt.util import *
from .trezor import TIM_NEW, TIM_RECOVER, TIM_MNEMONIC
from ..hw_wallet.qt import QtHandlerBase, QtPluginBase

from electrum_ltc.i18n import _
from electrum_ltc.plugins import hook, DeviceMgr
from electrum_ltc.util import PrintError, UserCancelled, bh2u
from electrum_ltc.wallet import Wallet, Standard_Wallet

PASSPHRASE_HELP_SHORT =_(
    "Passphrases allow you to access new wallets, each "
    "hidden behind a particular case-sensitive passphrase.")
PASSPHRASE_HELP = PASSPHRASE_HELP_SHORT + "  " + _(
    "You need to create a separate Electrum wallet for each passphrase "
    "you use as they each generate different addresses.  Changing "
    "your passphrase does not lose other wallets, each is still "
    "accessible behind its own passphrase.")
RECOMMEND_PIN = _(
    "You should enable PIN protection.  Your PIN is the only protection "
    "for your litecoins if your device is lost or stolen.")
PASSPHRASE_NOT_PIN = _(
    "If you forget a passphrase you will be unable to access any "
    "litecoins in the wallet behind it.  A passphrase is not a PIN. "
    "Only change this if you are sure you understand it.")
CHARACTER_RECOVERY = (
    "Use the recovery cipher shown on your device to input your seed words.  "
Esempio n. 43
0
 def on_copy(self):
     self.app.clipboard().setText(self.text())
     QToolTip.showText(QCursor.pos(), _("Text copied to clipboard"), self)
 def ignore_all_version(self):
     self.setText("")
     self.config.set_key("last_seen_version", "9.9.9", True)
     QMessageBox.information(self, _("Preference saved"), _("No more notifications about version updates will be shown."))
     self.dialog.done(0)
Esempio n. 45
0
 def show_message(self, msg, parent=None, title=None):
     return self.msg_box(QMessageBox.Information, parent, title
                         or _('Information'), msg)
 def new_electrum_version(self):
     if self.new_version:
         self.setText(_("New version available") + ": " + self.latest_version)
         self.sb.insertPermanentWidget(1, self)
Esempio n. 47
0
 def show_error(self, msg, parent=None):
     return self.msg_box(QMessageBox.Warning, parent, _('Error'), msg)
Esempio n. 48
0
 def addCopyButton(self, app):
     self.app = app
     self.addButton(":icons/copy.png", self.on_copy, _("Copy to clipboard"))
Esempio n. 49
0
 def __init__(self, dialog, label=None):
     QPushButton.__init__(self, label or _("Cancel"))
     self.clicked.connect(dialog.reject)
Esempio n. 50
0
 def show_critical(self, msg, parent=None, title=None):
     return self.msg_box(QMessageBox.Critical, parent, title
                         or _('Critical Error'), msg)
Esempio n. 51
0
 def __init__(self, text_getter, app, dialog):
     QPushButton.__init__(self, _("Copy and Close"))
     self.clicked.connect(lambda: app.clipboard().setText(text_getter()))
     self.clicked.connect(dialog.close)
     self.setDefault(True)
Esempio n. 52
0
 def show_warning(self, msg, parent=None, title=None):
     return self.msg_box(QMessageBox.Warning, parent, title or _('Warning'),
                         msg)
Esempio n. 53
0
 def __init__(self, dialog):
     QPushButton.__init__(self, _("Close"))
     self.clicked.connect(dialog.close)
     self.setDefault(True)
Esempio n. 54
0
 def __init__(self, dialog, label=None):
     QPushButton.__init__(self, label or _("OK"))
     self.clicked.connect(dialog.accept)
     self.setDefault(True)
Esempio n. 55
0
 def verify_seed(self, seed, is_valid=None):
     while True:
         r = self.request_seed(MSG_VERIFY_SEED, is_valid)
         if prepare_seed(r) == prepare_seed(seed):
             return
         self.show_error(_('Incorrect seed'))
Esempio n. 56
0
 def __init__(self, text_getter, app):
     QPushButton.__init__(self, _("Copy"))
     self.clicked.connect(lambda: app.clipboard().setText(text_getter()))
Esempio n. 57
0
 def done_processing(self, dialog, result):
     dialog.show_message(_("Your labels have been synchronised."))
Esempio n. 58
0
    MONOSPACE_FONT = 'Monaco'
else:
    MONOSPACE_FONT = 'monospace'

dialogs = []

from electrum_ltc.paymentrequest import PR_UNPAID, PR_PAID, PR_EXPIRED

pr_icons = {
    PR_UNPAID: ":icons/unpaid.png",
    PR_PAID: ":icons/confirmed.png",
    PR_EXPIRED: ":icons/expired.png"
}

pr_tooltips = {
    PR_UNPAID: _('Pending'),
    PR_PAID: _('Paid'),
    PR_EXPIRED: _('Expired')
}

expiration_values = [(_('1 hour'), 60 * 60), (_('1 day'), 24 * 60 * 60),
                     (_('1 week'), 7 * 24 * 60 * 60), (_('Never'), None)]


class Timer(QThread):
    stopped = False
    timer_signal = pyqtSignal()

    def run(self):
        while not self.stopped:
            self.timer_signal.emit()
Esempio n. 59
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"))
Esempio n. 60
0
    def __init__(self, window: 'ElectrumWindow', chan_id: bytes):
        super().__init__(window)

        # initialize instance fields
        self.window = window
        self.wallet = window.wallet
        chan = self.chan = window.wallet.lnworker.channels[chan_id]
        self.format_msat = lambda msat: window.format_amount_and_units(msat /
                                                                       1000)

        # connect signals with slots
        self.htlc_fulfilled.connect(self.on_htlc_fulfilled)
        self.htlc_failed.connect(self.on_htlc_failed)
        self.state_changed.connect(self.do_state_changed)
        self.htlc_added.connect(self.on_htlc_added)

        # register callbacks for updating
        util.register_callback(self.htlc_fulfilled.emit, ['htlc_fulfilled'])
        util.register_callback(self.htlc_failed.emit, ['htlc_failed'])
        util.register_callback(self.htlc_added.emit, ['htlc_added'])
        util.register_callback(self.state_changed.emit, ['channel'])

        # set attributes of QDialog
        self.setWindowTitle(_('Channel Details'))
        self.setMinimumSize(800, 400)

        # add layouts
        vbox = QtWidgets.QVBoxLayout(self)
        vbox.addWidget(QLabel(_('Remote Node ID:')))
        remote_id_e = ButtonsLineEdit(bh2u(chan.node_id))
        remote_id_e.addCopyButton(self.window.app)
        remote_id_e.setReadOnly(True)
        vbox.addWidget(remote_id_e)
        funding_label_text = f'<a href=click_destination>{chan.funding_outpoint.txid}</a>:{chan.funding_outpoint.output_index}'
        vbox.addWidget(QLabel(_('Funding Outpoint:')))
        vbox.addWidget(LinkedLabel(funding_label_text, self.show_tx))

        form_layout = QtWidgets.QFormLayout(None)
        # add form content
        form_layout.addRow(
            _('Channel ID:'),
            SelectableLabel(
                f"{chan.channel_id.hex()} (Short: {chan.short_channel_id})"))
        form_layout.addRow(_('State:'),
                           SelectableLabel(chan.get_state_for_GUI()))
        self.initiator = 'Local' if chan.constraints.is_initiator else 'Remote'
        form_layout.addRow(_('Initiator:'), SelectableLabel(self.initiator))
        self.capacity = self.window.format_amount_and_units(
            chan.get_capacity())
        form_layout.addRow(_('Capacity:'), SelectableLabel(self.capacity))
        self.can_send_label = SelectableLabel()
        self.can_receive_label = SelectableLabel()
        form_layout.addRow(_('Can send:'), self.can_send_label)
        form_layout.addRow(_('Can receive:'), self.can_receive_label)
        self.received_label = SelectableLabel()
        form_layout.addRow(_('Received:'), self.received_label)
        self.sent_label = SelectableLabel()
        form_layout.addRow(_('Sent:'), self.sent_label)
        #self.htlc_minimum_msat = SelectableLabel(str(chan.config[REMOTE].htlc_minimum_msat))
        #form_layout.addRow(_('Minimum HTLC value accepted by peer (mSAT):'), self.htlc_minimum_msat)
        #self.max_htlcs = SelectableLabel(str(chan.config[REMOTE].max_accepted_htlcs))
        #form_layout.addRow(_('Maximum number of concurrent HTLCs accepted by peer:'), self.max_htlcs)
        #self.max_htlc_value = SelectableLabel(self.window.format_amount_and_units(chan.config[REMOTE].max_htlc_value_in_flight_msat / 1000))
        #form_layout.addRow(_('Maximum value of in-flight HTLCs accepted by peer:'), self.max_htlc_value)
        self.dust_limit = SelectableLabel(
            self.window.format_amount_and_units(
                chan.config[REMOTE].dust_limit_sat))
        form_layout.addRow(_('Remote dust limit:'), self.dust_limit)
        self.remote_reserve = self.window.format_amount_and_units(
            chan.config[REMOTE].reserve_sat)
        form_layout.addRow(_('Remote reserve:'),
                           SelectableLabel(self.remote_reserve))
        vbox.addLayout(form_layout)

        # add htlc tree view to vbox (wouldn't scale correctly in QFormLayout)
        vbox.addWidget(QLabel(_('Payments (HTLCs):')))
        w = QtWidgets.QTreeView(self)
        htlc_dict = chan.get_payments()
        htlc_list = []
        for rhash, _list in htlc_dict.items():
            for _tuple in _list:
                htlc_list.append((rhash.hex(), ) + _tuple)
        w.setModel(self.make_model(htlc_list))
        w.header().setSectionResizeMode(0,
                                        QtWidgets.QHeaderView.ResizeToContents)
        vbox.addWidget(w)
        vbox.addLayout(Buttons(CloseButton(self)))
        # initialize sent/received fields
        self.update()