Exemplo n.º 1
0
 def on_otp(self, wallet, tx, otp, on_success, on_failure):
     try:
         wallet.on_otp(tx, otp)
     except TrustedCoinException as e:
         if e.status_code == 400:  # invalid OTP
             Clock.schedule_once(
                 lambda dt: on_failure(_('Invalid one-time password.')))
         else:
             Clock.schedule_once(lambda dt, bound_e=e: on_failure(
                 _('Error') + ':\n' + str(bound_e)))
     except Exception as e:
         Clock.schedule_once(lambda dt, bound_e=e: on_failure(
             _('Error') + ':\n' + str(bound_e)))
     else:
         on_success(tx)
Exemplo n.º 2
0
 def create_menu(self, position):
     item = self.currentItem()
     if not item:
         return
     is_server = not bool(item.data(0, Qt.UserRole))
     menu = QMenu()
     if is_server:
         server = item.data(1, Qt.UserRole)
         menu.addAction(_("Use as server"),
                        lambda: self.parent.follow_server(server))
     else:
         chain_id = item.data(1, Qt.UserRole)
         menu.addAction(_("Follow this branch"),
                        lambda: self.parent.follow_branch(chain_id))
     menu.exec_(self.viewport().mapToGlobal(position))
Exemplo n.º 3
0
 def purge_transaction(self):
     mods = ['_pick', '_signed', '_lock', '_shutdown']
     if not self.window.question(
             _("Purging you transactions will erase the current transaction"
               ) + '\n' +
             _("Are you sure you want to purge your transaction?")):
         return
     for mod in mods:
         for key, _hash, window in self.keys:
             server.delete(_hash)
             server.delete(_hash + mod)
         for window, xpub, K, _hash in self.cosigner_list:
             server.delete(_hash)
             server.delete(_hash + mod)
     self.window.show_message(_("Your transactions have been purged."))
Exemplo n.º 4
0
 def __init__(self, parent=None, msg=None):
     msg = msg or _('Please enter your password')
     WindowModalDialog.__init__(self, parent, _("Enter Password"))
     self.pw = pw = QLineEdit()
     pw.setEchoMode(2)
     vbox = QVBoxLayout()
     vbox.addWidget(QLabel(msg))
     grid = QGridLayout()
     grid.setSpacing(8)
     grid.addWidget(QLabel(_('Password')), 1, 0)
     grid.addWidget(pw, 1, 1)
     vbox.addLayout(grid)
     vbox.addLayout(Buttons(CancelButton(self), OkButton(self)))
     self.setLayout(vbox)
     run_hook('password_dialog', pw, grid, 1)
Exemplo n.º 5
0
 def update(self):
     inv_list = self.parent.invoices.unpaid_invoices()
     self.model().clear()
     self.update_headers(self.__class__.headers)
     self.header().setSectionResizeMode(self.Columns.REQUESTOR, QHeaderView.Interactive)
     for idx, pr in enumerate(inv_list):
         key = pr.get_id()
         status = self.parent.invoices.get_status(key)
         if status is None:
             continue
         requestor = pr.get_requestor()
         exp = pr.get_expiration_date()
         date_str = format_time(exp) if exp else _('Never')
         labels = [date_str, requestor, pr.memo, self.parent.format_amount(pr.get_amount(), whitespaces=True), pr_tooltips.get(status,'')]
         items = [QStandardItem(e) for e in labels]
         self.set_editability(items)
         items[self.Columns.STATUS].setIcon(read_QIcon(pr_icons.get(status)))
         items[self.Columns.DATE].setData(key, role=Qt.UserRole)
         items[self.Columns.REQUESTOR].setFont(QFont(MONOSPACE_FONT))
         items[self.Columns.AMOUNT].setFont(QFont(MONOSPACE_FONT))
         self.model().insertRow(idx, items)
     self.selectionModel().select(self.model().index(0,0), QItemSelectionModel.SelectCurrent)
     if self.parent.isVisible():
         b = len(inv_list) > 0
         self.setVisible(b)
         self.parent.invoices_label.setVisible(b)
     self.filter()
Exemplo n.º 6
0
    def accept_terms_of_use(self, wizard):
        def handle_error(msg, e):
            wizard.show_error(msg + ':\n' + str(e))
            wizard.terminate()

        try:
            tos = server.get_terms_of_service()
        except ErrorConnectingServer as e:
            Clock.schedule_once(lambda dt, bound_e=e: handle_error(
                _('Error connecting to server'), bound_e))
        except Exception as e:
            Clock.schedule_once(
                lambda dt, bound_e=e: handle_error(_('Error'), bound_e))
        else:
            f = lambda x: self.read_email(wizard)
            wizard.tos_dialog(tos=tos, run_next=f)
Exemplo n.º 7
0
 def prompt_user_for_otp(self, wallet, tx, on_success, on_failure):
     from ...gui.kivy.uix.dialogs.label_dialog import LabelDialog
     msg = _('Please enter your Google Authenticator code')
     d = LabelDialog(
         msg, '',
         lambda otp: self.on_otp(wallet, tx, otp, on_success, on_failure))
     d.open()
Exemplo n.º 8
0
 def get_pin(self, code=None):
     if code == 2:
         msg = _("Enter a new PIN for your {}:")
     elif code == 3:
         msg = (_("Re-enter the new PIN for your {}.\n\n"
                  "NOTE: the positions of the numbers have changed!"))
     else:
         msg = _("Enter your current {} PIN:")
     pin = self.handler.get_pin(msg.format(self.device))
     if not pin:
         raise Cancelled
     if len(pin) > 9:
         self.handler.show_error(
             _('The PIN cannot be longer than 9 characters.'))
         raise Cancelled
     return pin
Exemplo n.º 9
0
 def send(self, window, addr):
     from electrum_exos import paymentrequest
     r = window.wallet.receive_requests.get(addr)
     message = r.get('memo', '')
     if r.get('signature'):
         pr = paymentrequest.serialize_request(r)
     else:
         pr = paymentrequest.make_request(self.config, r)
     if not pr:
         return
     recipient, ok = QInputDialog.getText(window, 'Send request',
                                          'Email invoice to:')
     if not ok:
         return
     recipient = str(recipient)
     payload = pr.SerializeToString()
     self.print_error('sending mail to', recipient)
     try:
         # FIXME this runs in the GUI thread and blocks it...
         self.processor.send(recipient, message, payload)
     except BaseException as e:
         traceback.print_exc(file=sys.stderr)
         window.show_message(str(e))
     else:
         window.show_message(_('Request sent.'))
Exemplo n.º 10
0
 def callback_WordRequest(self, msg):
     self.step += 1
     msg = _("Step {}/24.  Enter seed word as explained on "
             "your {}:").format(self.step, self.device)
     word = self.handler.get_word(msg)
     # Unfortunately the device can't handle self.proto.Cancel()
     return self.proto.WordAck(word=word)
Exemplo n.º 11
0
 def restore_wallet(self, wizard):
     wizard.opt_bip39 = False
     wizard.opt_ext = True
     title = _("Restore two-factor Wallet")
     f = lambda seed, is_bip39, is_ext: wizard.run('on_restore_seed', seed,
                                                   is_ext)
     wizard.restore_seed_dialog(run_next=f, test=self.is_valid_seed)
Exemplo n.º 12
0
    def _initialize_device(self, settings, method, device_id, wizard, handler):
        item, label, pin_protection, passphrase_protection = settings

        language = 'english'
        devmgr = self.device_manager()
        client = devmgr.client_by_id(device_id)
        if not client:
            raise Exception(_("The device was disconnected."))

        if method == TIM_NEW:
            strength = 64 * (item + 2)  # 128, 192 or 256
            client.reset_device(True, strength, passphrase_protection,
                                pin_protection, label, language)
        elif method == TIM_RECOVER:
            word_count = 6 * (item + 2)  # 12, 18 or 24
            client.step = 0
            client.recovery_device(word_count, passphrase_protection,
                                       pin_protection, label, language)
        elif method == TIM_MNEMONIC:
            pin = pin_protection  # It's the pin, not a boolean
            client.load_device_by_mnemonic(str(item), pin,
                                           passphrase_protection,
                                           label, language)
        else:
            pin = pin_protection  # It's the pin, not a boolean
            client.load_device_by_xprv(item, pin, passphrase_protection,
                                       label, language)
Exemplo n.º 13
0
 def show_address(self, wallet, address, keystore=None):
     if keystore is None:
         keystore = wallet.get_keystore()
     if not self.show_address_helper(wallet, address, keystore):
         return
     client = self.get_client(keystore)
     if not client.atleast_version(1, 3):
         keystore.handler.show_error(_("Your device firmware is too old"))
         return
     change, index = wallet.get_address_index(address)
     derivation = keystore.derivation
     address_path = "%s/%d/%d"%(derivation, change, index)
     address_n = client.expand_path(address_path)
     xpubs = wallet.get_master_public_keys()
     if len(xpubs) == 1:
         script_type = self.get_keepkey_input_script_type(wallet.txin_type)
         client.get_address(self.get_coin_name(), address_n, True, script_type=script_type)
     else:
         def f(xpub):
             return self._make_node_path(xpub, [change, index])
         pubkeys = wallet.get_public_keys(address)
         # sort xpubs using the order of pubkeys
         sorted_pubkeys, sorted_xpubs = zip(*sorted(zip(pubkeys, xpubs)))
         pubkeys = list(map(f, sorted_xpubs))
         multisig = self.types.MultisigRedeemScriptType(
            pubkeys=pubkeys,
            signatures=[b''] * wallet.n,
            m=wallet.m,
         )
         script_type = self.get_keepkey_input_script_type(wallet.txin_type)
         client.get_address(self.get_coin_name(), address_n, True, multisig=multisig, script_type=script_type)
Exemplo n.º 14
0
    def create_client(self, device, handler):
        try:
            self.print_error("connecting to device at", device.path)
            transport = self.transport_handler.get_transport(device.path)
        except BaseException as e:
            self.print_error("cannot connect at", device.path, str(e))
            return None

        if not transport:
            self.print_error("cannot connect at", device.path)
            return

        self.print_error("connected to device at", device.path)
        client = self.client_class(transport, handler, self)

        # Try a ping for device sanity
        try:
            client.ping('t')
        except BaseException as e:
            self.print_error("ping failed", str(e))
            return None

        if not client.atleast_version(*self.minimum_firmware):
            msg = (_('Outdated {} firmware for device labelled {}. Please '
                     'download the updated firmware from {}').format(
                         self.device, client.label(), self.firmware_URL))
            self.print_error(msg)
            if handler:
                handler.show_error(msg)
            else:
                raise UserFacingException(msg)
            return None

        return client
Exemplo n.º 15
0
    def create_client(self, device, handler):
        if device.product_key[1] == 2:
            transport = self._try_webusb(device)
        else:
            transport = self._try_hid(device)

        if not transport:
            self.logger.info("cannot connect to device")
            return

        self.logger.info(f"connected to device at {device.path}")

        client = self.client_class(transport, handler, self)

        # Try a ping for device sanity
        try:
            client.ping('t')
        except BaseException as e:
            self.logger.info(f"ping failed {e}")
            return None

        if not client.atleast_version(*self.minimum_firmware):
            msg = (_('Outdated {} firmware for device labelled {}. Please '
                     'download the updated firmware from {}')
                   .format(self.device, client.label(), self.firmware_URL))
            self.logger.info(msg)
            if handler:
                handler.show_error(msg)
            else:
                raise UserFacingException(msg)
            return None

        return client
Exemplo n.º 16
0
 def passphrase_dialog(self, msg, confirm):
     # If confirm is true, require the user to enter the passphrase twice
     parent = self.top_level_window()
     d = WindowModalDialog(parent, _("Enter Passphrase"))
     if confirm:
         OK_button = OkButton(d)
         playout = PasswordLayout(msg=msg,
                                  kind=PW_PASSPHRASE,
                                  OK_button=OK_button)
         vbox = QVBoxLayout()
         vbox.addLayout(playout.layout())
         vbox.addLayout(Buttons(CancelButton(d), OK_button))
         d.setLayout(vbox)
         passphrase = playout.new_password() if d.exec_() else None
     else:
         pw = QLineEdit()
         pw.setEchoMode(2)
         pw.setMinimumWidth(200)
         vbox = QVBoxLayout()
         vbox.addWidget(WWLabel(msg))
         vbox.addWidget(pw)
         vbox.addLayout(Buttons(CancelButton(d), OkButton(d)))
         d.setLayout(vbox)
         passphrase = pw.text() if d.exec_() else None
     self.passphrase = passphrase
     self.done.set()
Exemplo n.º 17
0
    def __init__(self, text=None):
        ButtonsTextEdit.__init__(self, text)
        self.setReadOnly(1)
        icon = "qrcode_white.png" if ColorScheme.dark_scheme else "qrcode.png"
        self.addButton(icon, self.qr_show, _("Show as QR code"))

        run_hook('show_text_edit', self)
Exemplo n.º 18
0
 def dbb_has_password(self):
     reply = self.hid_send_plain(b'{"ping":""}')
     if 'ping' not in reply:
         raise UserFacingException(_('Device communication error. Please unplug and replug your Digital Bitbox.'))
     if reply['ping'] == 'password':
         return True
     return False
Exemplo n.º 19
0
 def seed_device_dialog(self):
     msg = _("Choose how to initialize your Digital Bitbox:") + "\n"
     choices = [
         (_("Generate a new random wallet")),
         (_("Load a wallet from the micro SD card"))
     ]
     try:
         reply = self.handler.win.query_choice(msg, choices)
     except Exception:
         return # Back button pushed
     if reply == 0:
         self.dbb_generate_wallet()
     else:
         if not self.dbb_load_backup(show_msg=False):
             return
     self.isInitialized = True
Exemplo n.º 20
0
 def callback_PinMatrixRequest(self, msg):
     if msg.type == 2:
         msg = _("Enter a new PIN for your {}:")
     elif msg.type == 3:
         msg = (_("Re-enter the new PIN for your {}.\n\n"
                  "NOTE: the positions of the numbers have changed!"))
     else:
         msg = _("Enter your current {} PIN:")
     pin = self.handler.get_pin(msg.format(self.device))
     if len(pin) > 9:
         self.handler.show_error(
             _('The PIN cannot be longer than 9 characters.'))
         pin = ''  # to cancel below
     if not pin:
         return self.proto.Cancel()
     return self.proto.PinMatrixAck(pin=pin)
Exemplo n.º 21
0
    def _initialize_device(self, settings, method, device_id, wizard, handler):
        item, label, pin_protection, passphrase_protection, recovery_type = settings

        if method == TIM_RECOVER and recovery_type == RECOVERY_TYPE_SCRAMBLED_WORDS:
            handler.show_error(_(
                "You will be asked to enter 24 words regardless of your "
                "seed's actual length.  If you enter a word incorrectly or "
                "misspell it, you cannot change it or go back - you will need "
                "to start again from the beginning.\n\nSo please enter "
                "the words carefully!"),
                               blocking=True)

        devmgr = self.device_manager()
        client = devmgr.client_by_id(device_id)

        if method == TIM_NEW:
            client.reset_device(
                strength=64 * (item + 2),  # 128, 192 or 256
                passphrase_protection=passphrase_protection,
                pin_protection=pin_protection,
                label=label)
        elif method == TIM_RECOVER:
            client.recover_device(
                recovery_type=recovery_type,
                word_count=6 * (item + 2),  # 12, 18 or 24
                passphrase_protection=passphrase_protection,
                pin_protection=pin_protection,
                label=label)
            if recovery_type == RECOVERY_TYPE_MATRIX:
                handler.close_matrix_dialog()
        else:
            raise RuntimeError("Unsupported recovery method")
Exemplo n.º 22
0
    def check_libraries_available(self) -> bool:
        def version_str(t):
            return ".".join(str(i) for i in t)

        try:
            # this might raise ImportError or LibraryFoundButUnusable
            library_version = self.get_library_version()
            # if no exception so far, we might still raise LibraryFoundButUnusable
            if (library_version == 'unknown'
                    or versiontuple(library_version) < self.minimum_library
                    or hasattr(self, "maximum_library") and versiontuple(library_version) >= self.maximum_library):
                raise LibraryFoundButUnusable(library_version=library_version)
        except ImportError:
            return False
        except LibraryFoundButUnusable as e:
            library_version = e.library_version
            max_version_str = version_str(self.maximum_library) if hasattr(self, "maximum_library") else "inf"
            self.libraries_available_message = (
                    _("Library version for '{}' is incompatible.").format(self.name)
                    + '\nInstalled: {}, Needed: {} <= x < {}'
                    .format(library_version, version_str(self.minimum_library), max_version_str))
            self.print_stderr(self.libraries_available_message)
            return False

        return True
Exemplo n.º 23
0
        def change_homescreen():
            dialog = QFileDialog(self, _("Choose Homescreen"))
            filename, __ = dialog.getOpenFileName()
            if not filename:
                return  # user cancelled

            if filename.endswith('.toif'):
                img = open(filename, 'rb').read()
                if img[:8] != b'TOIf\x90\x00\x90\x00':
                    handler.show_error(
                        'File is not a TOIF file with size of 144x144')
                    return
            else:
                from PIL import Image  # FIXME
                im = Image.open(filename)
                if im.size != (128, 64):
                    handler.show_error('Image must be 128 x 64 pixels')
                    return
                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)
Exemplo n.º 24
0
 def message_dialog(self, msg):
     self.clear_dialog()
     self.dialog = dialog = WindowModalDialog(self.top_level_window(), _("Ledger Status"))
     l = QLabel(msg)
     vbox = QVBoxLayout(dialog)
     vbox.addWidget(l)
     dialog.show()
Exemplo n.º 25
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
Exemplo n.º 26
0
    def send_report(self):
        def on_success(response):
            # note: 'response' coming from (remote) crash reporter server.
            # It contains a URL to the GitHub issue, so we allow rich text.
            self.show_message(parent=self,
                              title=_("Crash report"),
                              msg=response,
                              rich_text=True)
            self.close()

        def on_failure(exc_info):
            e = exc_info[1]
            self.logger.error(
                'There was a problem with the automatic reporting',
                exc_info=exc_info)
            self.show_critical(
                parent=self,
                msg=(
                    _('There was a problem with the automatic reporting:') +
                    '<br/>' + repr(e)[:120] + '<br/>' +
                    _("Please report this issue manually") +
                    f' <a href="{constants.GIT_REPO_ISSUES_URL}">on GitHub</a>.'
                ),
                rich_text=True)

        proxy = self.main_window.network.proxy
        task = lambda: BaseCrashReporter.send_report(
            self, self.main_window.network.asyncio_loop, proxy)
        msg = _('Sending crash report...')
        WaitingDialog(self, msg, task, on_success, on_failure)
Exemplo n.º 27
0
    def settings_dialog(self, window):
        d = WindowModalDialog(window, _("Email settings"))
        d.setMinimumSize(500, 200)

        vbox = QVBoxLayout(d)
        vbox.addWidget(QLabel(_('Server hosting your email account')))
        grid = QGridLayout()
        vbox.addLayout(grid)
        grid.addWidget(QLabel('Server (IMAP)'), 0, 0)
        server_e = QLineEdit()
        server_e.setText(self.imap_server)
        grid.addWidget(server_e, 0, 1)

        grid.addWidget(QLabel('Username'), 1, 0)
        username_e = QLineEdit()
        username_e.setText(self.username)
        grid.addWidget(username_e, 1, 1)

        grid.addWidget(QLabel('Password'), 2, 0)
        password_e = QLineEdit()
        password_e.setText(self.password)
        grid.addWidget(password_e, 2, 1)

        vbox.addStretch()
        vbox.addLayout(Buttons(CloseButton(d), OkButton(d)))

        if not d.exec_():
            return

        server = str(server_e.text())
        self.config.set_key('email_server', server)
        self.imap_server = server

        username = str(username_e.text())
        self.config.set_key('email_username', username)
        self.username = username

        password = str(password_e.text())
        self.config.set_key('email_password', password)
        self.password = password

        check_connection = CheckConnectionThread(server, username, password)
        check_connection.connection_error_signal.connect(
            lambda e: window.show_message(
                _("Unable to connect to mail server:\n {}").format(e) + "\n" +
                _("Please check your connection and credentials.")))
        check_connection.start()
Exemplo n.º 28
0
 def sign_message(self, sequence, message, password):
     message = message.encode('utf8')
     message_hash = hashlib.sha256(message).hexdigest().upper()
     # prompt for the PIN before displaying the dialog if necessary
     client = self.get_client()
     address_path = self.get_derivation()[2:] + "/%d/%d" % sequence
     self.handler.show_message("Signing message ...\r\nMessage hash: " +
                               message_hash)
     try:
         info = self.get_client().signMessagePrepare(address_path, message)
         pin = ""
         if info['confirmationNeeded']:
             pin = self.handler.get_auth(
                 info)  # does the authenticate dialog and returns pin
             if not pin:
                 raise UserWarning(_('Cancelled by user'))
             pin = str(pin).encode()
         signature = self.get_client().signMessageSign(pin)
     except BTChipException as e:
         if e.sw == 0x6a80:
             self.give_error(
                 "Unfortunately, this message cannot be signed by the Ledger wallet. Only alphanumerical messages shorter than 140 characters are supported. Please remove any extra characters (tab, carriage return) and retry."
             )
         elif e.sw == 0x6985:  # cancelled by user
             return b''
         elif e.sw == 0x6982:
             raise  # pin lock. decorator will catch it
         else:
             self.give_error(e, True)
     except UserWarning:
         self.handler.show_error(_('Cancelled by user'))
         return b''
     except Exception as e:
         self.give_error(e, True)
     finally:
         self.handler.finished()
     # Parse the ASN.1 signature
     rLength = signature[3]
     r = signature[4:4 + rLength]
     sLength = signature[4 + rLength + 1]
     s = signature[4 + rLength + 2:]
     if rLength == 33:
         r = r[1:]
     if sLength == 33:
         s = s[1:]
     # And convert it
     return bytes([27 + 4 + (signature[0] & 0x01)]) + r + s
Exemplo n.º 29
0
    def add_show_address_on_hw_device_button_for_receive_addr(self, wallet, keystore, main_window):
        plugin = keystore.plugin
        receive_address_e = main_window.receive_address_e

        def show_address():
            addr = receive_address_e.text()
            keystore.thread.add(partial(plugin.show_address, wallet, addr, keystore))
        receive_address_e.addButton("eye1.png", show_address, _("Show on {}").format(plugin.device))
Exemplo n.º 30
0
 def create_menu(self, position):
     item = self.currentItem()
     if not item:
         return
     menu = QMenu()
     server = item.data(self.Columns.HOST, self.SERVER_STR_ROLE)
     menu.addAction(_("Use as server"), lambda: self.set_server(server))
     menu.exec_(self.viewport().mapToGlobal(position))