def update(self):

        is_relevant, is_mine, v, fee = self.wallet.get_tx_value(self.tx)
        if self.wallet.can_sign(self.tx):
            self.sign_button.show()
        else:
            self.sign_button.hide()

        if self.tx.is_complete():
            status = _("Signed")
            tx_hash = self.tx.hash()

            if tx_hash in self.wallet.transactions.keys():
                conf, timestamp = self.wallet.verifier.get_confirmations(tx_hash)
                if timestamp:
                    time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3]
                else:
                    time_str = 'pending'
                status = _("%d confirmations")%conf
                self.broadcast_button.hide()
            else:
                time_str = None
                conf = 0
                self.broadcast_button.show()
        else:
            s, r = self.tx.signature_count()
            status = _("Unsigned") if s == 0 else _('Partially signed (%d/%d)'%(s,r))
            time_str = None
            self.broadcast_button.hide()
            tx_hash = 'unknown'

        self.tx_hash_e.setText(tx_hash)
        self.status_label.setText(_('Status:') + ' ' + status)

        if time_str is not None:
            self.date_label.setText(_("Date: %s")%time_str)
            self.date_label.show()
        else:
            self.date_label.hide()

        # if we are not synchronized, we cannot tell
        if self.parent.network is None or not self.parent.network.is_running() or not self.parent.network.is_connected():
            return
        if not self.wallet.up_to_date:
            return

        if is_relevant:    
            if is_mine:
                if fee is not None: 
                    self.amount_label.setText(_("Amount sent:")+' %s'% self.parent.format_amount(v-fee) + ' ' + self.parent.base_unit())
                    self.fee_label.setText(_("Transaction fee")+': %s'% self.parent.format_amount(fee) + ' ' + self.parent.base_unit())
                else:
                    self.amount_label.setText(_("Amount sent:")+' %s'% self.parent.format_amount(v) + ' ' + self.parent.base_unit())
                    self.fee_label.setText(_("Transaction fee")+': '+ _("unknown"))
            else:
                self.amount_label.setText(_("Amount received:")+' %s'% self.parent.format_amount(v) + ' ' + self.parent.base_unit())
        else:
            self.amount_label.setText(_("Transaction unrelated to your wallet"))

        run_hook('transaction_dialog_update', self)
Example #2
0
 def create_quote_text(self, btc_balance):
     """Return a string copy of the amount fiat currency the 
     user has in bitcoins."""
     from electrum_nvc.plugins import run_hook
     r = {}
     run_hook('get_fiat_balance_text', btc_balance, r)
     return r.get(0, '')
Example #3
0
 def create_quote_text(self, btc_balance):
     """Return a string copy of the amount fiat currency the 
     user has in bitcoins."""
     from electrum_nvc.plugins import run_hook
     r = {}
     run_hook('get_fiat_balance_text', btc_balance, r)
     return r.get(0,'')
Example #4
0
    def __init__(self, tx, parent):
        self.tx = tx
        tx_dict = tx.as_dict()
        self.parent = parent
        self.wallet = parent.wallet

        QDialog.__init__(self)
        self.setMinimumWidth(600)
        self.setWindowTitle(_("Transaction"))
        self.setModal(1)

        vbox = QVBoxLayout()
        self.setLayout(vbox)

        vbox.addWidget(QLabel(_("Transaction ID:")))
        self.tx_hash_e = QLineEdit()
        self.tx_hash_e.setReadOnly(True)
        vbox.addWidget(self.tx_hash_e)
        self.status_label = QLabel()
        vbox.addWidget(self.status_label)

        self.date_label = QLabel()
        vbox.addWidget(self.date_label)
        self.amount_label = QLabel()
        vbox.addWidget(self.amount_label)
        self.fee_label = QLabel()
        vbox.addWidget(self.fee_label)

        self.add_io(vbox)

        vbox.addStretch(1)

        self.buttons = buttons = QHBoxLayout()
        vbox.addLayout(buttons)

        buttons.addStretch(1)

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

        self.broadcast_button = b = QPushButton(_("Broadcast"))
        b.clicked.connect(lambda: self.parent.broadcast_transaction(self.tx))

        b.hide()
        buttons.addWidget(b)

        self.save_button = b = QPushButton(_("Save"))
        b.clicked.connect(self.save)
        buttons.addWidget(b)

        cancelButton = QPushButton(_("Close"))
        cancelButton.clicked.connect(lambda: self.done(0))
        buttons.addWidget(cancelButton)
        cancelButton.setDefault(True)

        b = QPushButton()
        b.setIcon(QIcon(":icons/qrcode.png"))
        b.clicked.connect(self.show_qr)
        buttons.insertWidget(1, b)

        run_hook('transaction_dialog', self)

        self.update()
Example #5
0
    def update(self):

        is_relevant, is_mine, v, fee = self.wallet.get_tx_value(self.tx)
        if self.wallet.can_sign(self.tx):
            self.sign_button.show()
        else:
            self.sign_button.hide()

        if self.tx.is_complete():
            status = _("Signed")
            tx_hash = self.tx.hash()

            if tx_hash in self.wallet.transactions.keys():
                conf, timestamp = self.wallet.verifier.get_confirmations(
                    tx_hash)
                if timestamp:
                    time_str = datetime.datetime.fromtimestamp(
                        timestamp).isoformat(' ')[:-3]
                else:
                    time_str = 'pending'
                status = _("%d confirmations") % conf
                self.broadcast_button.hide()
            else:
                time_str = None
                conf = 0
                self.broadcast_button.show()
        else:
            s, r = self.tx.signature_count()
            status = _("Unsigned") if s == 0 else _(
                'Partially signed (%d/%d)' % (s, r))
            time_str = None
            self.broadcast_button.hide()
            tx_hash = 'unknown'

        self.tx_hash_e.setText(tx_hash)
        self.status_label.setText(_('Status:') + ' ' + status)

        if time_str is not None:
            self.date_label.setText(_("Date: %s") % time_str)
            self.date_label.show()
        else:
            self.date_label.hide()

        # if we are not synchronized, we cannot tell
        if self.parent.network is None or not self.parent.network.is_running(
        ) or not self.parent.network.is_connected():
            return
        if not self.wallet.up_to_date:
            return

        if is_relevant:
            if is_mine:
                if fee is not None:
                    self.amount_label.setText(
                        _("Amount sent:") +
                        ' %s' % self.parent.format_amount(v - fee) + ' ' +
                        self.parent.base_unit())
                    self.fee_label.setText(
                        _("Transaction fee") +
                        ': %s' % self.parent.format_amount(fee) + ' ' +
                        self.parent.base_unit())
                else:
                    self.amount_label.setText(
                        _("Amount sent:") +
                        ' %s' % self.parent.format_amount(v) + ' ' +
                        self.parent.base_unit())
                    self.fee_label.setText(
                        _("Transaction fee") + ': ' + _("unknown"))
            else:
                self.amount_label.setText(
                    _("Amount received:") +
                    ' %s' % self.parent.format_amount(v) + ' ' +
                    self.parent.base_unit())
        else:
            self.amount_label.setText(
                _("Transaction unrelated to your wallet"))

        run_hook('transaction_dialog_update', self)
Example #6
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)

        label = QLabel(_("What do you want to do?"))
        label.setWordWrap(True)
        grid.addWidget(label, 0, 0)

        gb1 = QGroupBox()
        grid.addWidget(gb1, 0, 0)

        group1 = QButtonGroup()

        b1 = QRadioButton(gb1)
        b1.setText(_("Create new wallet"))
        b1.setChecked(True)

        b2 = QRadioButton(gb1)
        b2.setText(_("Restore an existing wallet"))

        group1.addButton(b1)
        group1.addButton(b2)

        grid.addWidget(b1, 1, 0)
        grid.addWidget(b2, 2, 0)
        vbox.addLayout(grid)

        grid2 = QGridLayout()
        grid2.setSpacing(5)

        class ClickableLabel(QLabel):
            def mouseReleaseEvent(self, ev):
                self.emit(SIGNAL('clicked()'))

        label2 = ClickableLabel(_("Wallet type:") + " [+]")
        hbox = QHBoxLayout()
        hbox.addWidget(label2)
        grid2.addLayout(hbox, 0, 0)

        gb2 = QGroupBox()
        grid.addWidget(gb2, 3, 0)
        group2 = QButtonGroup()

        self.wallet_types = [
            ('standard', _("Standard wallet"), Wallet),
            ('2of2', _("Multisig wallet (2 of 2)"), Wallet_2of2),
            ('2of3', _("Multisig wallet (2 of 3)"), Wallet_2of3)
        ]
        run_hook('add_wallet_types', self.wallet_types)

        for i, (t, l, c) in enumerate(self.wallet_types):
            button = QRadioButton(gb2)
            button.setText(l)
            grid2.addWidget(button, i + 1, 0)
            group2.addButton(button)
            group2.setId(button, i)
            if i == 0:
                button.setChecked(True)
            #else:
            #    button.setHidden(True)

        def toggle():
            buttons = group2.buttons()
            x = buttons[1].isHidden()
            label2.setText(_("Wallet type:") + (' [+]' if x else ' [-]'))
            for b in buttons[1:]:
                b.setHidden(not x)

        self.connect(label2, SIGNAL('clicked()'), toggle)
        grid2.addWidget(label2)

        vbox.addLayout(grid2)
        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
Example #7
0
    def restore(self, t):

        if t == 'standard':
            text = self.enter_seed_dialog(MSG_ENTER_ANYTHING, None)
            if not text:
                return
            if Wallet.is_seed(text):
                password = self.password_dialog()
                wallet = Wallet.from_seed(text, self.storage)
                wallet.add_seed(text, password)
                wallet.create_accounts(password)
            elif Wallet.is_xprv(text):
                password = self.password_dialog()
                wallet = Wallet.from_xprv(text, password, self.storage)
            elif Wallet.is_old_mpk(text):
                wallet = Wallet.from_old_mpk(text, self.storage)
            elif Wallet.is_xpub(text):
                wallet = Wallet.from_xpub(text, self.storage)
            elif Wallet.is_address(text):
                wallet = Wallet.from_address(text, self.storage)
            elif Wallet.is_private_key(text):
                wallet = Wallet.from_private_key(text, self.storage)
            else:
                raise

        elif t in ['2of2']:
            r = self.multi_seed_dialog(1)
            if not r:
                return
            text1, text2 = r
            wallet = Wallet_2of2(self.storage)
            if Wallet.is_seed(text1) or Wallet.is_seed(text2):
                password = self.password_dialog()
            else:
                password = None

            if Wallet.is_seed(text1):
                wallet.add_seed(text1, password)
                if Wallet.is_seed(text2):
                    wallet.add_cold_seed(text2, password)
                else:
                    wallet.add_master_public_key("cold/", text2)
            else:
                assert Wallet.is_xpub(text1)
                if Wallet.is_seed(text2):
                    wallet.add_seed(text2, password)
                    wallet.add_master_public_key("cold/", text1)
                else:
                    wallet.add_master_public_key("m/", text1)
                    wallet.add_master_public_key("cold/", text2)

            wallet.create_accounts(password)

        elif t in ['2of3']:
            r = self.multi_seed_dialog(2)
            if not r:
                return
            text1, text2, text3 = r
            wallet = Wallet_2of3(self.storage)
            if Wallet.is_seed(text1) or Wallet.is_seed(
                    text2) or Wallet.is_seed(text3):
                password = self.password_dialog()
            else:
                password = None

            if Wallet.is_seed(text1):
                wallet.add_seed(text1, password)
                if Wallet.is_seed(text2):
                    wallet.add_cold_seed(text2, password)
                else:
                    wallet.add_master_public_key("cold/", text2)

            elif Wallet.is_xpub(text1):
                if Wallet.is_seed(text2):
                    wallet.add_seed(text2, password)
                    wallet.add_master_public_key("cold/", text1)
                else:
                    wallet.add_master_public_key("m/", text1)
                    wallet.add_master_public_key("cold/", text2)

            wallet.create_accounts(password)

        else:
            wallet = run_hook('installwizard_restore', self, self.storage)
            if not wallet:
                return

        # create first keys offline
        self.waiting_dialog(wallet.synchronize)

        return wallet
Example #8
0
    def run(self, action):

        if action == 'new':
            action, wallet_type = self.restore_or_create()
            self.storage.put('wallet_type', wallet_type, False)

        if action is None:
            return

        if action == 'restore':
            wallet = self.restore(wallet_type)
            if not wallet:
                return
            action = None

        else:
            wallet = Wallet(self.storage)
            action = wallet.get_action()
            # fixme: password is only needed for multiple accounts
            password = None

        while action is not None:

            util.print_error("installwizard:", wallet, action)

            if action == 'create_seed':
                seed = wallet.make_seed()
                if not self.show_seed(seed, None):
                    return
                if not self.verify_seed(seed, None):
                    return
                password = self.password_dialog()
                wallet.add_seed(seed, password)

            elif action == 'add_cosigner':
                xpub_hot = wallet.master_public_keys.get("m/")
                r = self.multi_mpk_dialog(xpub_hot, 1)
                if not r:
                    return
                xpub_cold = r[0]
                wallet.add_master_public_key("cold/", xpub_cold)

            elif action == 'add_two_cosigners':
                xpub_hot = wallet.master_public_keys.get("m/")
                r = self.multi_mpk_dialog(xpub_hot, 2)
                if not r:
                    return
                xpub1, xpub2 = r
                wallet.add_master_public_key("cold/", xpub1)
                wallet.add_master_public_key("remote/", xpub2)

            elif action == 'create_accounts':
                wallet.create_accounts(password)
                self.waiting_dialog(wallet.synchronize)

            elif action == 'create_cold_seed':
                self.create_cold_seed(wallet)
                return

            else:
                r = run_hook('install_wizard_action', self, wallet, action)
                if not r:
                    raise BaseException('unknown wizard action', action)

            # next action
            action = wallet.get_action()

        if self.network:
            if self.network.interfaces:
                self.network_dialog()
            else:
                QMessageBox.information(None, _('Warning'),
                                        _('You are offline'), _('OK'))
                self.network.stop()
                self.network = None

        # start wallet threads
        wallet.start_threads(self.network)

        if action == 'restore':
            self.waiting_dialog(
                lambda: wallet.restore(self.waiting_label.setText))
            if self.network:
                if wallet.is_found():
                    QMessageBox.information(None, _('Information'),
                                            _("Recovery successful"), _('OK'))
                else:
                    QMessageBox.information(
                        None, _('Information'),
                        _("No transactions found for this seed"), _('OK'))
            else:
                QMessageBox.information(
                    None, _('Information'),
                    _("This wallet was restored offline. It may contain more addresses than displayed."
                      ), _('OK'))

        return wallet
    def __init__(self, tx, parent):
        self.tx = tx
        tx_dict = tx.as_dict()
        self.parent = parent
        self.wallet = parent.wallet
            
        QDialog.__init__(self)
        self.setMinimumWidth(600)
        self.setWindowTitle(_("Transaction"))
        self.setModal(1)

        vbox = QVBoxLayout()
        self.setLayout(vbox)

        vbox.addWidget(QLabel(_("Transaction ID:")))
        self.tx_hash_e  = QLineEdit()
        self.tx_hash_e.setReadOnly(True)
        vbox.addWidget(self.tx_hash_e)
        self.status_label = QLabel()
        vbox.addWidget(self.status_label)

        self.date_label = QLabel()
        vbox.addWidget(self.date_label)
        self.amount_label = QLabel()
        vbox.addWidget(self.amount_label)
        self.fee_label = QLabel()
        vbox.addWidget(self.fee_label)

        self.add_io(vbox)

        vbox.addStretch(1)

        self.buttons = buttons = QHBoxLayout()
        vbox.addLayout( buttons )

        buttons.addStretch(1)

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

        self.broadcast_button = b = QPushButton(_("Broadcast"))
        b.clicked.connect(lambda: self.parent.broadcast_transaction(self.tx))

        b.hide()
        buttons.addWidget(b)

        self.save_button = b = QPushButton(_("Save"))
        b.clicked.connect(self.save)
        buttons.addWidget(b)

        cancelButton = QPushButton(_("Close"))
        cancelButton.clicked.connect(lambda: self.done(0))
        buttons.addWidget(cancelButton)
        cancelButton.setDefault(True)

        b = QPushButton()
        b.setIcon(QIcon(":icons/qrcode.png"))
        b.clicked.connect(self.show_qr)
        buttons.insertWidget(1,b)

        run_hook('transaction_dialog', self)
        
        self.update()
Example #10
0
 def qr_input(self):
     from electrum_nvc.plugins import run_hook
     data = run_hook('scan_qr_hook')
     if type(data) != str:
         return
     self.setText(data)
Example #11
0
    def main(self, url):

        storage = WalletStorage(self.config)
        if storage.file_exists:
            wallet = Wallet(storage)
            action = wallet.get_action()
        else:
            action = 'new'

        if action is not None:
            import installwizard
            wizard = installwizard.InstallWizard(self.config, self.network, storage)
            wallet = wizard.run(action)
            if not wallet: 
                exit()
        else:
            wallet.start_threads(self.network)

        # init tray
        self.dark_icon = self.config.get("dark_icon", False)
        icon = QIcon(":icons/electrum_dark_icon.png") if self.dark_icon else QIcon(':icons/electrum_light_icon.png')
        self.tray = QSystemTrayIcon(icon, None)
        self.tray.setToolTip('Electrum')
        self.tray.activated.connect(self.tray_activated)
        self.build_tray_menu()
        self.tray.show()

        # main window
        self.main_window = w = ElectrumWindow(self.config, self.network, self)
        self.current_window = self.main_window

        #lite window
        self.init_lite()

        # initial configuration
        if self.config.get('hide_gui') is True and self.tray.isVisible():
            self.main_window.hide()
            self.lite_window.hide()
        else:
            if self.config.get('lite_mode') is True:
                self.go_lite()
            else:
                self.go_full()

        # plugins that need to change the GUI do it here
        run_hook('init')

        w.load_wallet(wallet)

        s = Timer()
        s.start()

        self.windows.append(w)
        if url: 
            self.set_url(url)

        w.app = self.app
        w.connect_slots(s)
        w.update_wallet()

        self.app.exec_()

        # clipboard persistence
        # see http://www.mail-archive.com/[email protected]/msg17328.html
        event = QtCore.QEvent(QtCore.QEvent.Clipboard)
        self.app.sendEvent(self.app.clipboard(), event)

        wallet.stop_threads()
    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)

        label = QLabel(_("What do you want to do?"))
        label.setWordWrap(True)
        grid.addWidget(label, 0, 0)

        gb1 = QGroupBox()
        grid.addWidget(gb1, 0, 0)

        group1 = QButtonGroup()

        b1 = QRadioButton(gb1)
        b1.setText(_("Create new wallet"))
        b1.setChecked(True)

        b2 = QRadioButton(gb1)
        b2.setText(_("Restore an existing wallet"))

        group1.addButton(b1)
        group1.addButton(b2)

        grid.addWidget(b1, 1, 0)
        grid.addWidget(b2, 2, 0)
        vbox.addLayout(grid)

        grid2 = QGridLayout()
        grid2.setSpacing(5)

        class ClickableLabel(QLabel):
            def mouseReleaseEvent(self, ev):
                self.emit(SIGNAL('clicked()'))

        label2 = ClickableLabel(_("Wallet type:") + " [+]")
        hbox = QHBoxLayout()
        hbox.addWidget(label2)
        grid2.addLayout(hbox, 0, 0)
        
        gb2 = QGroupBox()
        grid.addWidget(gb2, 3, 0)
        group2 = QButtonGroup()

        self.wallet_types = [ 
            ('standard', _("Standard wallet"),          Wallet), 
            ('2of2',     _("Multisig wallet (2 of 2)"), Wallet_2of2),
            ('2of3',     _("Multisig wallet (2 of 3)"), Wallet_2of3)
        ]
        run_hook('add_wallet_types', self.wallet_types)

        for i, (t,l,c) in enumerate(self.wallet_types):
            button = QRadioButton(gb2)
            button.setText(l)
            grid2.addWidget(button, i+1, 0)
            group2.addButton(button)
            group2.setId(button, i)
            if i==0:
                button.setChecked(True)
            #else:
            #    button.setHidden(True)


        def toggle():
            buttons = group2.buttons()
            x = buttons[1].isHidden()
            label2.setText(_("Wallet type:") + (' [+]' if x else ' [-]'))
            for b in buttons[1:]:
                b.setHidden(not x)

        self.connect(label2, SIGNAL('clicked()'), toggle)
        grid2.addWidget(label2)
 
        vbox.addLayout(grid2)
        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
    def restore(self, t):

            if t == 'standard':
                text = self.enter_seed_dialog(MSG_ENTER_ANYTHING, None)
                if not text:
                    return
                if Wallet.is_seed(text):
                    password = self.password_dialog()
                    wallet = Wallet.from_seed(text, self.storage)
                    wallet.add_seed(text, password)
                    wallet.create_accounts(password)
                elif Wallet.is_xprv(text):
                    password = self.password_dialog()
                    wallet = Wallet.from_xprv(text, password, self.storage)
                elif Wallet.is_old_mpk(text):
                    wallet = Wallet.from_old_mpk(text, self.storage)
                elif Wallet.is_xpub(text):
                    wallet = Wallet.from_xpub(text, self.storage)
                elif Wallet.is_address(text):
                    wallet = Wallet.from_address(text, self.storage)
                elif Wallet.is_private_key(text):
                    wallet = Wallet.from_private_key(text, self.storage)
                else:
                    raise

            elif t in ['2of2']:
                r = self.multi_seed_dialog(1)
                if not r: 
                    return
                text1, text2 = r
                wallet = Wallet_2of2(self.storage)
                if Wallet.is_seed(text1) or Wallet.is_seed(text2):
                    password = self.password_dialog()
                else:
                    password = None

                if Wallet.is_seed(text1):
                    wallet.add_seed(text1, password)
                    if Wallet.is_seed(text2):
                        wallet.add_cold_seed(text2, password)
                    else:
                        wallet.add_master_public_key("cold/", text2)
                else:
                    assert Wallet.is_xpub(text1)
                    if Wallet.is_seed(text2):
                        wallet.add_seed(text2, password)
                        wallet.add_master_public_key("cold/", text1)
                    else:
                        wallet.add_master_public_key("m/", text1)
                        wallet.add_master_public_key("cold/", text2)

                wallet.create_accounts(password)


            elif t in ['2of3']:
                r = self.multi_seed_dialog(2)
                if not r: 
                    return
                text1, text2, text3 = r
                wallet = Wallet_2of3(self.storage)
                if Wallet.is_seed(text1) or Wallet.is_seed(text2) or Wallet.is_seed(text3):
                    password = self.password_dialog()
                else:
                    password = None

                if Wallet.is_seed(text1):
                    wallet.add_seed(text1, password)
                    if Wallet.is_seed(text2):
                        wallet.add_cold_seed(text2, password)
                    else:
                        wallet.add_master_public_key("cold/", text2)

                elif Wallet.is_xpub(text1):
                    if Wallet.is_seed(text2):
                        wallet.add_seed(text2, password)
                        wallet.add_master_public_key("cold/", text1)
                    else:
                        wallet.add_master_public_key("m/", text1)
                        wallet.add_master_public_key("cold/", text2)

                wallet.create_accounts(password)

            else:
                wallet = run_hook('installwizard_restore', self, self.storage)
                if not wallet:
                    return

            # create first keys offline
            self.waiting_dialog(wallet.synchronize)
                
            return wallet
    def run(self, action):

        if action == 'new':
            action, wallet_type = self.restore_or_create()
            self.storage.put('wallet_type', wallet_type, False)

        if action is None:
            return

        if action == 'restore':
            wallet = self.restore(wallet_type)
            if not wallet:
                return
            action = None

        else:
            wallet = Wallet(self.storage)
            action = wallet.get_action()
            # fixme: password is only needed for multiple accounts
            password = None

        while action is not None:

            util.print_error("installwizard:", wallet, action)

            if action == 'create_seed':
                seed = wallet.make_seed()
                if not self.show_seed(seed, None):
                    return
                if not self.verify_seed(seed, None):
                    return
                password = self.password_dialog()
                wallet.add_seed(seed, password)

            elif action == 'add_cosigner':
                xpub_hot = wallet.master_public_keys.get("m/")
                r = self.multi_mpk_dialog(xpub_hot, 1)
                if not r:
                    return
                xpub_cold = r[0]
                wallet.add_master_public_key("cold/", xpub_cold)

            elif action == 'add_two_cosigners':
                xpub_hot = wallet.master_public_keys.get("m/")
                r = self.multi_mpk_dialog(xpub_hot, 2)
                if not r:
                    return
                xpub1, xpub2 = r
                wallet.add_master_public_key("cold/", xpub1)
                wallet.add_master_public_key("remote/", xpub2)

            elif action == 'create_accounts':
                wallet.create_accounts(password)
                self.waiting_dialog(wallet.synchronize)

            elif action == 'create_cold_seed':
                self.create_cold_seed(wallet)
                return

            else:
                 r = run_hook('install_wizard_action', self, wallet, action)
                 if not r: 
                     raise BaseException('unknown wizard action', action)

            # next action
            action = wallet.get_action()


        if self.network:
            if self.network.interfaces:
                self.network_dialog()
            else:
                QMessageBox.information(None, _('Warning'), _('You are offline'), _('OK'))
                self.network.stop()
                self.network = None

        # start wallet threads
        wallet.start_threads(self.network)

        if action == 'restore':
            self.waiting_dialog(lambda: wallet.restore(self.waiting_label.setText))
            if self.network:
                if wallet.is_found():
                    QMessageBox.information(None, _('Information'), _("Recovery successful"), _('OK'))
                else:
                    QMessageBox.information(None, _('Information'), _("No transactions found for this seed"), _('OK'))
            else:
                QMessageBox.information(None, _('Information'), _("This wallet was restored offline. It may contain more addresses than displayed."), _('OK'))

        return wallet