def restore(self, t):
     if t == 'standard':
         text = self.enter_seed_dialog(MSG_ENTER_ANYTHING, None)
         if not text:
             return
         password = self.password_dialog() if Wallet.is_seed(text) or Wallet.is_xprv(text) or Wallet.is_private_key(text) else None
         wallet = Wallet.from_text(text, password, self.storage)
     elif re.match('(\d+)of(\d+)', t):
         n = int(re.match('(\d+)of(\d+)', t).group(2))
         key_list = self.multi_seed_dialog(n - 1)
         if not key_list:
             return
         password = self.password_dialog() if any(map(lambda x: Wallet.is_seed(x) or Wallet.is_xprv(x), key_list)) else None
         wallet = Wallet.from_multisig(key_list, password, self.storage, t)
     else:
         self.storage.put('wallet_type', t, False)
         # call the constructor to load the plugin (side effect)
         Wallet(self.storage)
         wallet = always_hook('installwizard_restore', self, self.storage)
         if not wallet:
             util.print_error("no wallet")
             return
     # create first keys offline
     self.waiting_dialog(wallet.synchronize)
     return wallet
Esempio n. 2
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. 3
0
 def restore(self, t):
     if t == 'standard':
         text = self.enter_seed_dialog(MSG_ENTER_ANYTHING, None)
         if not text:
             return
         password = self.password_dialog(
         ) if Wallet.is_seed(text) or Wallet.is_xprv(
             text) or Wallet.is_private_key(text) else None
         wallet = Wallet.from_text(text, password, self.storage)
     elif re.match('(\d+)of(\d+)', t):
         n = int(re.match('(\d+)of(\d+)', t).group(2))
         key_list = self.multi_seed_dialog(n - 1)
         if not key_list:
             return
         password = self.password_dialog() if any(
             map(lambda x: Wallet.is_seed(x) or Wallet.is_xprv(x),
                 key_list)) else None
         wallet = Wallet.from_multisig(key_list, password, self.storage, t)
     else:
         self.storage.put('wallet_type', t, False)
         # call the constructor to load the plugin (side effect)
         Wallet(self.storage)
         wallet = always_hook('installwizard_restore', self, self.storage)
         if not wallet:
             util.print_error("no wallet")
             return
     # create first keys offline
     self.waiting_dialog(wallet.synchronize)
     return wallet
Esempio n. 4
0
    def __init__(self, config, network, plugins):

        self.config = config
        self.network = network
        storage = WalletStorage(config.get_wallet_path())
        if not storage.file_exists:
            print "Wallet not found. try 'electrum-gmc create'"
            exit()

        self.wallet = Wallet(storage)
        self.wallet.start_threads(self.network)
        self.contacts = StoreDict(self.config, 'contacts')

        locale.setlocale(locale.LC_ALL, '')
        self.encoding = locale.getpreferredencoding()

        self.stdscr = curses.initscr()
        curses.noecho()
        curses.cbreak()
        curses.start_color()
        curses.use_default_colors()
        curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
        curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_CYAN)
        self.stdscr.keypad(1)
        self.stdscr.border(0)
        self.maxy, self.maxx = self.stdscr.getmaxyx()
        self.set_cursor(0)
        self.w = curses.newwin(10, 50, 5, 5)

        set_verbosity(False)
        self.tab = 0
        self.pos = 0
        self.popup_pos = 0

        self.str_recipient = ""
        self.str_description = ""
        self.str_amount = ""
        self.str_fee = ""
        self.history = None

        if self.network:
            self.network.register_callback('updated', self.update)
            self.network.register_callback('connected', self.refresh)
            self.network.register_callback('disconnected', self.refresh)
            self.network.register_callback('disconnecting', self.refresh)

        self.tab_names = [_("History"), _("Send"), _("Receive"), _("Addresses"), _("Contacts"), _("Banner")]
        self.num_tabs = len(self.tab_names)
    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. 6
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)
    def on_start(self):
        ''' This is the start point of the kivy ui
        '''
        Logger.info("dpi: {} {}".format(metrics.dpi, metrics.dpi_rounded))
        win = Window
        win.bind(size=self.on_size,
                    on_keyboard=self.on_keyboard)
        win.bind(on_key_down=self.on_key_down)

        # Register fonts without this you won't be able to use bold/italic...
        # inside markup.
        from kivy.core.text import Label
        Label.register('Roboto',
                   'data/fonts/Roboto.ttf',
                   'data/fonts/Roboto.ttf',
                   'data/fonts/Roboto-Bold.ttf',
                   'data/fonts/Roboto-Bold.ttf')

        if platform == 'android':
            # bind to keyboard height so we can get the window contents to
            # behave the way we want when the keyboard appears.
            win.bind(keyboard_height=self.on_keyboard_height)

        self.on_size(win, win.size)
        config = self.electrum_config
        storage = WalletStorage(config.get_wallet_path())

        Logger.info('Electrum: Check for existing wallet')

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

        if action is not None:
            # start installation wizard
            Logger.debug('Electrum: Wallet not found. Launching install wizard')
            wizard = Factory.InstallWizard(config, self.network, storage)
            wizard.bind(on_wizard_complete=self.on_wizard_complete)
            wizard.run(action)
        else:
            wallet.start_threads(self.network)
            self.on_wizard_complete(None, wallet)

        self.on_resume()
Esempio n. 8
0
    def on_verify_restore_ok(self, wallet, _dlg, btn, restore=False):
        if btn in (_dlg.ids.back, _dlg.ids.but_close):
            _dlg.close()
            Factory.CreateRestoreDialog(
                on_release=self.on_creatrestore_complete).open()
            return

        seed = self.get_seed_text(_dlg.ids.text_input_seed)
        if not seed:
            return app.show_error(_("No seed!"), duration=.5)

        _dlg.close()

        if Wallet.is_seed(seed):
            return self.password_dialog(wallet=wallet,
                                        mode='restore',
                                        seed=seed)
        elif Wallet.is_mpk(seed):
            wallet = Wallet.from_mpk(seed, self.storage)
        elif Wallet.is_address(seed):
            wallet = Wallet.from_address(seed, self.storage)
        elif Wallet.is_private_key(seed):
            wallet = Wallet.from_private_key(seed, self.storage)
        else:
            return app.show_error(_('Not a valid seed. App will now exit'),
                                  exit=True,
                                  modal=True,
                                  duration=.5)
        return
    def on_verify_restore_ok(self, wallet, _dlg, btn, restore=False):
        if btn in (_dlg.ids.back, _dlg.ids.but_close) :
            _dlg.close()
            Factory.CreateRestoreDialog(
                on_release=self.on_creatrestore_complete).open()
            return

        seed = self.get_seed_text(_dlg.ids.text_input_seed)
        if not seed:
            return app.show_error(_("No seed!"), duration=.5)

        _dlg.close()

        if Wallet.is_seed(seed):
            return self.password_dialog(wallet=wallet, mode='restore',
                                        seed=seed)
        elif Wallet.is_mpk(seed):
            wallet = Wallet.from_mpk(seed, self.storage)
        elif Wallet.is_address(seed):
            wallet = Wallet.from_address(seed, self.storage)
        elif Wallet.is_private_key(seed):
            wallet = Wallet.from_private_key(seed, self.storage)
        else:
            return app.show_error(_('Not a valid seed. App will now exit'),
                                  exit=True, modal=True, duration=.5)
        return
Esempio n. 10
0
    def on_start(self):
        ''' This is the start point of the kivy ui
        '''
        Logger.info("dpi: {} {}".format(metrics.dpi, metrics.dpi_rounded))
        win = Window
        win.bind(size=self.on_size, on_keyboard=self.on_keyboard)
        win.bind(on_key_down=self.on_key_down)

        # Register fonts without this you won't be able to use bold/italic...
        # inside markup.
        from kivy.core.text import Label
        Label.register('Roboto', 'data/fonts/Roboto.ttf',
                       'data/fonts/Roboto.ttf', 'data/fonts/Roboto-Bold.ttf',
                       'data/fonts/Roboto-Bold.ttf')

        if platform == 'android':
            # bind to keyboard height so we can get the window contents to
            # behave the way we want when the keyboard appears.
            win.bind(keyboard_height=self.on_keyboard_height)

        self.on_size(win, win.size)
        config = self.electrum_config
        storage = WalletStorage(config.get_wallet_path())

        Logger.info('Electrum: Check for existing wallet')

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

        if action is not None:
            # start installation wizard
            Logger.debug(
                'Electrum: Wallet not found. Launching install wizard')
            wizard = Factory.InstallWizard(config, self.network, storage)
            wizard.bind(on_wizard_complete=self.on_wizard_complete)
            wizard.run(action)
        else:
            wallet.start_threads(self.network)
            self.on_wizard_complete(None, wallet)

        self.on_resume()
    def main(self):

        storage = WalletStorage(self.config.get_wallet_path())
        if not storage.file_exists:
            action = self.restore_or_create()
            if not action:
                exit()
            self.wallet = wallet = Wallet(storage)
            gap = self.config.get('gap_limit', 5)
            if gap != 5:
                wallet.gap_limit = gap
                wallet.storage.put('gap_limit', gap, True)

            if action == 'create':
                seed = wallet.make_seed()
                show_seed_dialog(seed, None)
                r = change_password_dialog(False, None)
                password = r[2] if r else None
                wallet.add_seed(seed, password)
                wallet.create_master_keys(password)
                wallet.create_main_account(password)
                wallet.synchronize()  # generate first addresses offline

            elif action == 'restore':
                seed = self.seed_dialog()
                if not seed:
                    exit()
                r = change_password_dialog(False, None)
                password = r[2] if r else None
                wallet.add_seed(seed, password)
                wallet.create_master_keys(password)
                wallet.create_main_account(password)

            else:
                exit()
        else:
            self.wallet = Wallet(storage)
            action = None

        self.wallet.start_threads(self.network)

        if action == 'restore':
            self.restore_wallet(wallet)

        w = ElectrumWindow(self.wallet, self.config, self.network)
        #if url: w.set_url(url)
        Gtk.main()
Esempio n. 12
0
    def on_creatrestore_complete(self, dialog, button):
        if not button:
            # soft back or escape button pressed
            return self.dispatch('on_wizard_complete', None)
        dialog.close()

        action = dialog.action
        if button == dialog.ids.create:
            wallet = Wallet(self.storage)
            self.password_dialog(wallet=wallet, mode='create')

        elif button == dialog.ids.restore:
            wallet = None
            self.restore_seed_dialog(wallet)

        else:
            self.dispatch('on_wizard_complete', None)
def run_recovery_dialog():
    message = "Please enter your wallet seed or the corresponding mnemonic list of words, and the gap limit of your wallet."
    dialog = Gtk.MessageDialog(
        parent = None,
        flags = Gtk.DialogFlags.MODAL,
        buttons = Gtk.ButtonsType.OK_CANCEL,
        message_format = message)

    vbox = dialog.vbox
    dialog.set_default_response(Gtk.ResponseType.OK)

    # ask seed, server and gap in the same dialog
    seed_box = Gtk.HBox()
    seed_label = Gtk.Label(label='Seed or mnemonic:')
    seed_label.set_size_request(150,-1)
    seed_box.pack_start(seed_label, False, False, 10)
    seed_label.show()
    seed_entry = Gtk.Entry()
    seed_entry.show()
    seed_entry.set_size_request(450,-1)
    seed_box.pack_start(seed_entry, False, False, 10)
    add_help_button(seed_box, '.')
    seed_box.show()
    vbox.pack_start(seed_box, False, False, 5)

    dialog.show()
    r = dialog.run()
    seed = seed_entry.get_text()
    dialog.destroy()

    if r==Gtk.ResponseType.CANCEL:
        return False

    if Wallet.is_seed(seed):
        return seed

    show_message("no seed")
    return False
Esempio n. 14
0
    def __init__(self, _config, _network, plugins):
        global wallet, network, contacts, config
        network = _network
        config = _config
        network.register_callback('updated', update_callback)
        network.register_callback('connected', update_callback)
        network.register_callback('disconnected', update_callback)
        network.register_callback('disconnecting', update_callback)

        contacts = util.StoreDict(config, 'contacts')

        storage = WalletStorage(config.get_wallet_path())
        if not storage.file_exists:
            action = self.restore_or_create()
            if not action:
                exit()

            password = droid.dialogGetPassword('Choose a password').result
            if password:
                password2 = droid.dialogGetPassword('Confirm password').result
                if password != password2:
                    modal_dialog('Error', 'passwords do not match')
                    exit()
            else:
                # set to None if it's an empty string
                password = None

            if action == 'create':
                wallet = Wallet(storage)
                seed = wallet.make_seed()
                modal_dialog('Your seed is:', seed)
                wallet.add_seed(seed, password)
                wallet.create_master_keys(password)
                wallet.create_main_account(password)
            elif action == 'restore':
                seed = self.seed_dialog()
                if not seed:
                    exit()
                if not Wallet.is_seed(seed):
                    exit()
                wallet = Wallet.from_seed(seed, password, storage)
            else:
                exit()

            msg = "Creating wallet" if action == 'create' else "Restoring wallet"
            droid.dialogCreateSpinnerProgress("Electrum-GMC", msg)
            droid.dialogShow()
            wallet.start_threads(network)
            if action == 'restore':
                wallet.wait_until_synchronized()
            else:
                wallet.synchronize()
            droid.dialogDismiss()
            droid.vibrate()

        else:
            wallet = Wallet(storage)
            wallet.start_threads(network)
 def is_any(self, seed_e):
     text = self.get_seed_text(seed_e)
     return (Wallet.is_seed(text) or
             Wallet.is_mpk(text) or
             Wallet.is_address(text) or
             Wallet.is_private_key(text))
        def on_release(wallet, seed, _dlg, _btn):
            ti_password = _dlg.ids.ti_password
            ti_new_password = _dlg.ids.ti_new_password
            ti_confirm_password = _dlg.ids.ti_confirm_password
            if _btn != _dlg.ids.next:
                if mode == 'restore':
                    # back is disabled cause seed is already set
                    return
                _dlg.close()
                if not instance:
                    # back on create
                    Factory.CreateRestoreDialog(
                        on_release=self.on_creatrestore_complete).open()
                return

            # Confirm
            wallet_name = _dlg.ids.ti_wallet_name.text
            new_password = unicode(ti_new_password.text)
            new_password2 = unicode(ti_confirm_password.text)

            if new_password != new_password2:
                # passwords don't match
                ti_password.text = ""
                ti_new_password.text = ""
                ti_confirm_password.text = ""
                if ti_password.disabled:
                    ti_new_password.focus = True
                else:
                    ti_password.focus = True
                return app.show_error(_('Passwords do not match'), duration=.5)

            if not new_password:
                new_password = None

            if mode == 'restore':
                wallet = Wallet.from_seed(seed, self.storage)
                password = (unicode(ti_password.text)
                            if wallet and wallet.use_encryption else
                            None)

                def on_complete(*l):
                    wallet.create_accounts(new_password)
                    self.load_network(wallet, mode='restore')
                    _dlg.close()

                self.waiting_dialog(lambda: wallet.add_seed(seed, new_password),
                                    msg=_("saving seed"),
                                    on_complete=on_complete)
                return

            if not instance:
                # create mode
                _dlg.close()
                seed = wallet.make_seed()

                return self.show_seed(password=new_password, wallet=wallet,
                                      wallet_name=wallet_name, mode=mode,
                                      seed=seed)

            # change password mode
            try:
                seed = wallet.decode_seed(password)
            except BaseException:
                return app.show_error(_('Incorrect Password'), duration=.5)

            # test carefully
            try:
                wallet.update_password(seed, password, new_password)
            except BaseException:
                return app.show_error(_('Failed to update password'), exit=True)
            else:
                app.show_info_bubble(
                    text=_('Password successfully updated'), duration=1,
                    pos=_btn.pos)
            _dlg.close()

            if instance is None:  # in initial phase
                self.load_wallet()
            self.app.update_wallet()
Esempio n. 17
0
    def __init__(self):
        global wallet
        self.qr_data = None
        storage = WalletStorage('/sdcard/electrum-gmc/authenticator')
        if not storage.file_exists:

            action = self.restore_or_create()
            if not action:
                exit()
            password = droid.dialogGetPassword('Choose a password').result
            if password:
                password2 = droid.dialogGetPassword('Confirm password').result
                if password != password2:
                    modal_dialog('Error', 'Passwords do not match')
                    exit()
            else:
                password = None
            if action == 'create':
                wallet = Wallet(storage)
                seed = wallet.make_seed()
                modal_dialog('Your seed is:', seed)
            elif action == 'import':
                seed = self.seed_dialog()
                if not seed:
                    exit()
                if not Wallet.is_seed(seed):
                    exit()
                wallet = Wallet.from_seed(seed, password, storage)
            else:
                exit()

            wallet.add_seed(seed, password)
            wallet.create_master_keys(password)
            wallet.create_main_account(password)
        else:
            wallet = Wallet(storage)
Esempio n. 18
0
class ElectrumGui:

    def __init__(self, config, network, plugins):

        self.config = config
        self.network = network
        storage = WalletStorage(config.get_wallet_path())
        if not storage.file_exists:
            print "Wallet not found. try 'electrum-gmc create'"
            exit()

        self.wallet = Wallet(storage)
        self.wallet.start_threads(self.network)
        self.contacts = StoreDict(self.config, 'contacts')

        locale.setlocale(locale.LC_ALL, '')
        self.encoding = locale.getpreferredencoding()

        self.stdscr = curses.initscr()
        curses.noecho()
        curses.cbreak()
        curses.start_color()
        curses.use_default_colors()
        curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
        curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_CYAN)
        self.stdscr.keypad(1)
        self.stdscr.border(0)
        self.maxy, self.maxx = self.stdscr.getmaxyx()
        self.set_cursor(0)
        self.w = curses.newwin(10, 50, 5, 5)

        set_verbosity(False)
        self.tab = 0
        self.pos = 0
        self.popup_pos = 0

        self.str_recipient = ""
        self.str_description = ""
        self.str_amount = ""
        self.str_fee = ""
        self.history = None

        if self.network:
            self.network.register_callback('updated', self.update)
            self.network.register_callback('connected', self.refresh)
            self.network.register_callback('disconnected', self.refresh)
            self.network.register_callback('disconnecting', self.refresh)

        self.tab_names = [_("History"), _("Send"), _("Receive"), _("Addresses"), _("Contacts"), _("Banner")]
        self.num_tabs = len(self.tab_names)


    def set_cursor(self, x):
        try:
            curses.curs_set(x)
        except Exception:
            pass

    def restore_or_create(self):
        pass

    def verify_seed(self):
        pass

    def get_string(self, y, x):
        self.set_cursor(1)
        curses.echo()
        self.stdscr.addstr( y, x, " "*20, curses.A_REVERSE)
        s = self.stdscr.getstr(y,x)
        curses.noecho()
        self.set_cursor(0)
        return s

    def update(self):
        self.update_history()
        if self.tab == 0:
            self.print_history()
        self.refresh()

    def print_history(self):

        width = [20, 40, 14, 14]
        delta = (self.maxx - sum(width) - 4)/3
        format_str = "%"+"%d"%width[0]+"s"+"%"+"%d"%(width[1]+delta)+"s"+"%"+"%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s"

        if self.history is None:
            self.update_history()

        self.print_list(self.history[::-1], format_str%( _("Date"), _("Description"), _("Amount"), _("Balance")))

    def update_history(self):
        width = [20, 40, 14, 14]
        delta = (self.maxx - sum(width) - 4)/3
        format_str = "%"+"%d"%width[0]+"s"+"%"+"%d"%(width[1]+delta)+"s"+"%"+"%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s"

        b = 0
        self.history = []

        for item in self.wallet.get_history():
            tx_hash, conf, value, timestamp, balance = item
            if conf:
                try:
                    time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3]
                except Exception:
                    time_str = "------"
            else:
                time_str = 'pending'

            label, is_default_label = self.wallet.get_label(tx_hash)
            if len(label) > 40:
                label = label[0:37] + '...'
            self.history.append( format_str%( time_str, label, format_satoshis(value, whitespaces=True), format_satoshis(balance, whitespaces=True) ) )


    def print_balance(self):
        if not self.network:
            msg = _("Offline")
        elif self.network.is_connected():
            if not self.wallet.up_to_date:
                msg = _("Synchronizing...")
            else:
                c, u, x =  self.wallet.get_balance()
                msg = _("Balance")+": %f  "%(Decimal(c) / COIN)
                if u:
                    msg += "  [%f unconfirmed]"%(Decimal(u) / COIN)
                if x:
                    msg += "  [%f unmatured]"%(Decimal(x) / COIN)
        else:
            msg = _("Not connected")

        self.stdscr.addstr( self.maxy -1, 3, msg)

        for i in range(self.num_tabs):
            self.stdscr.addstr( 0, 2 + 2*i + len(''.join(self.tab_names[0:i])), ' '+self.tab_names[i]+' ', curses.A_BOLD if self.tab == i else 0)

        self.stdscr.addstr(self.maxy -1, self.maxx-30, ' '.join([_("Settings"), _("Network"), _("Quit")]))

    def print_receive(self):
        addr = self.wallet.get_unused_address(None)
        self.stdscr.addstr(2, 1, "Address: "+addr)
        self.print_qr(addr)

    def print_contacts(self):
        messages = map(lambda x: "%20s   %45s "%(x[0], x[1][1]), self.contacts.items())
        self.print_list(messages, "%19s  %15s "%("Key", "Value"))

    def print_addresses(self):
        fmt = "%-35s  %-30s"
        messages = map(lambda addr: fmt % (addr, self.wallet.labels.get(addr,"")), self.wallet.addresses())
        self.print_list(messages,   fmt % ("Address", "Label"))

    def print_edit_line(self, y, label, text, index, size):
        text += " "*(size - len(text) )
        self.stdscr.addstr( y, 2, label)
        self.stdscr.addstr( y, 15, text, curses.A_REVERSE if self.pos%6==index else curses.color_pair(1))

    def print_send_tab(self):
        self.stdscr.clear()
        self.print_edit_line(3, _("Pay to"), self.str_recipient, 0, 40)
        self.print_edit_line(5, _("Description"), self.str_description, 1, 40)
        self.print_edit_line(7, _("Amount"), self.str_amount, 2, 15)
        self.print_edit_line(9, _("Fee"), self.str_fee, 3, 15)
        self.stdscr.addstr( 12, 15, _("[Send]"), curses.A_REVERSE if self.pos%6==4 else curses.color_pair(2))
        self.stdscr.addstr( 12, 25, _("[Clear]"), curses.A_REVERSE if self.pos%6==5 else curses.color_pair(2))

    def print_banner(self):
        if self.network:
            self.print_list( self.network.banner.split('\n'))

    def print_qr(self, data):
        import qrcode, StringIO
        s = StringIO.StringIO()
        self.qr = qrcode.QRCode()
        self.qr.add_data(data)
        self.qr.print_ascii(out=s, invert=True)
        msg = s.getvalue()
        lines = msg.split('\n')
        for i, l in enumerate(lines):
            l = l.encode("utf-8")
            self.stdscr.addstr(i+5, 5, l)

    def print_list(self, list, firstline = None):
        self.maxpos = len(list)
        if not self.maxpos: return
        if firstline:
            firstline += " "*(self.maxx -2 - len(firstline))
            self.stdscr.addstr( 1, 1, firstline )
        for i in range(self.maxy-4):
            msg = list[i] if i < len(list) else ""
            msg += " "*(self.maxx - 2 - len(msg))
            m = msg[0:self.maxx - 2]
            m = m.encode(self.encoding)
            self.stdscr.addstr( i+2, 1, m, curses.A_REVERSE if i == (self.pos % self.maxpos) else 0)

    def refresh(self):
        if self.tab == -1: return
        self.stdscr.border(0)
        self.print_balance()
        self.stdscr.refresh()

    def main_command(self):
        c = self.stdscr.getch()
        print c
        if   c == curses.KEY_RIGHT: self.tab = (self.tab + 1)%self.num_tabs
        elif c == curses.KEY_LEFT: self.tab = (self.tab - 1)%self.num_tabs
        elif c == curses.KEY_DOWN: self.pos +=1
        elif c == curses.KEY_UP: self.pos -= 1
        elif c == 9: self.pos +=1 # tab
        elif curses.unctrl(c) in ['^W', '^C', '^X', '^Q']: self.tab = -1
        elif curses.unctrl(c) in ['^N']: self.network_dialog()
        elif curses.unctrl(c) == '^S': self.settings_dialog()
        else: return c
        if self.pos<0: self.pos=0
        if self.pos>=self.maxpos: self.pos=self.maxpos - 1

    def run_tab(self, i, print_func, exec_func):
        while self.tab == i:
            self.stdscr.clear()
            print_func()
            self.refresh()
            c = self.main_command()
            if c: exec_func(c)


    def run_history_tab(self, c):
        if c == 10:
            out = self.run_popup('',["blah","foo"])


    def edit_str(self, target, c, is_num=False):
        # detect backspace
        if c in [8, 127, 263] and target:
            target = target[:-1]
        elif not is_num or curses.unctrl(c) in '0123456789.':
            target += curses.unctrl(c)
        return target


    def run_send_tab(self, c):
        if self.pos%6 == 0:
            self.str_recipient = self.edit_str(self.str_recipient, c)
        if self.pos%6 == 1:
            self.str_description = self.edit_str(self.str_description, c)
        if self.pos%6 == 2:
            self.str_amount = self.edit_str(self.str_amount, c, True)
        elif self.pos%6 == 3:
            self.str_fee = self.edit_str(self.str_fee, c, True)
        elif self.pos%6==4:
            if c == 10: self.do_send()
        elif self.pos%6==5:
            if c == 10: self.do_clear()


    def run_receive_tab(self, c):
        if c == 10:
            out = self.run_popup('Address', ["Edit label", "Freeze", "Prioritize"])

    def run_contacts_tab(self, c):
        if c == 10 and self.contacts:
            out = self.run_popup('Adress', ["Copy", "Pay to", "Edit label", "Delete"]).get('button')
            key = self.contacts.keys()[self.pos%len(self.contacts.keys())]
            if out == "Pay to":
                self.tab = 1
                self.str_recipient = key
                self.pos = 2
            elif out == "Edit label":
                s = self.get_string(6 + self.pos, 18)
                if s:
                    self.wallet.labels[address] = s

    def run_banner_tab(self, c):
        self.show_message(repr(c))
        pass

    def main(self):

        tty.setraw(sys.stdin)
        while self.tab != -1:
            self.run_tab(0, self.print_history, self.run_history_tab)
            self.run_tab(1, self.print_send_tab, self.run_send_tab)
            self.run_tab(2, self.print_receive, self.run_receive_tab)
            self.run_tab(3, self.print_addresses, self.run_banner_tab)
            self.run_tab(4, self.print_contacts, self.run_contacts_tab)
            self.run_tab(5, self.print_banner, self.run_banner_tab)

        tty.setcbreak(sys.stdin)
        curses.nocbreak()
        self.stdscr.keypad(0)
        curses.echo()
        curses.endwin()


    def do_clear(self):
        self.str_amount = ''
        self.str_recipient = ''
        self.str_fee = ''
        self.str_description = ''

    def do_send(self):
        if not is_valid(self.str_recipient):
            self.show_message(_('Invalid Gamecredits address'))
            return
        try:
            amount = int(Decimal(self.str_amount) * COIN)
        except Exception:
            self.show_message(_('Invalid Amount'))
            return
        try:
            fee = int(Decimal(self.str_fee) * COIN)
        except Exception:
            self.show_message(_('Invalid Fee'))
            return

        if self.wallet.use_encryption:
            password = self.password_dialog()
            if not password:
                return
        else:
            password = None

        try:
            tx = self.wallet.mktx( [("address", self.str_recipient, amount)], password, self.config, fee)
        except Exception as e:
            self.show_message(str(e))
            return

        if self.str_description:
            self.wallet.labels[tx.hash()] = self.str_description

        h = self.wallet.send_tx(tx)
        self.show_message(_("Please wait..."), getchar=False)
        self.wallet.tx_event.wait()
        status, msg = self.wallet.receive_tx( h, tx )

        if status:
            self.show_message(_('Payment sent.'))
            self.do_clear()
            #self.update_contacts_tab()
        else:
            self.show_message(_('Error'))


    def show_message(self, message, getchar = True):
        w = self.w
        w.clear()
        w.border(0)
        for i, line in enumerate(message.split('\n')):
            w.addstr(2+i,2,line)
        w.refresh()
        if getchar: c = self.stdscr.getch()


    def run_popup(self, title, items):
        return self.run_dialog(title, map(lambda x: {'type':'button','label':x}, items), interval=1, y_pos = self.pos+3)


    def network_dialog(self):
        if not self.network: return
        host, port, protocol, proxy_config, auto_connect = self.network.get_parameters()
        srv = 'auto-connect' if auto_connect else self.network.default_server

        out = self.run_dialog('Network', [
            {'label':'server', 'type':'str', 'value':srv},
            {'label':'proxy', 'type':'str', 'value':self.config.get('proxy', '')},
            ], buttons = 1)
        if out:
            if out.get('server'):
                server = out.get('server')
                auto_connect = server == 'auto-connect'
                if not auto_connect:
                    try:
                        host, port, protocol = server.split(':')
                    except Exception:
                        self.show_message("Error:" + server + "\nIn doubt, type \"auto-connect\"")
                        return False

                if out.get('proxy'):
                    proxy = self.parse_proxy_options(out.get('proxy'))
                else:
                    proxy = None

                self.network.set_parameters(host, port, protocol, proxy, auto_connect)



    def settings_dialog(self):
        out = self.run_dialog('Settings', [
            {'label':'Default GUI', 'type':'list', 'choices':['classic','lite','gtk','text'], 'value':self.config.get('gui')},
            {'label':'Default fee', 'type':'satoshis', 'value': format_satoshis(self.wallet.fee_per_kb).strip() }
            ], buttons = 1)
        if out:
            if out.get('Default GUI'):
                self.config.set_key('gui', out['Default GUI'], True)
            if out.get('Default fee'):
                fee = int(Decimal(out['Default fee']) * COIN)
                self.config.set_key('fee_per_kb', fee, True)


    def password_dialog(self):
        out = self.run_dialog('Password', [
            {'label':'Password', 'type':'password', 'value':''}
            ], buttons = 1)
        return out.get('Password')


    def run_dialog(self, title, items, interval=2, buttons=None, y_pos=3):
        self.popup_pos = 0

        self.w = curses.newwin( 5 + len(items)*interval + (2 if buttons else 0), 50, y_pos, 5)
        w = self.w
        out = {}
        while True:
            w.clear()
            w.border(0)
            w.addstr( 0, 2, title)

            num = len(items)

            numpos = num
            if buttons: numpos += 2

            for i in range(num):
                item = items[i]
                label = item.get('label')
                if item.get('type') == 'list':
                    value = item.get('value','')
                elif item.get('type') == 'satoshis':
                    value = item.get('value','')
                elif item.get('type') == 'str':
                    value = item.get('value','')
                elif item.get('type') == 'password':
                    value = '*'*len(item.get('value',''))
                else:
                    value = ''
                if value is None:
                    value = ''
                if len(value)<20:
                    value += ' '*(20-len(value))

                if item.has_key('value'):
                    w.addstr( 2+interval*i, 2, label)
                    w.addstr( 2+interval*i, 15, value, curses.A_REVERSE if self.popup_pos%numpos==i else curses.color_pair(1) )
                else:
                    w.addstr( 2+interval*i, 2, label, curses.A_REVERSE if self.popup_pos%numpos==i else 0)

            if buttons:
                w.addstr( 5+interval*i, 10, "[  ok  ]",     curses.A_REVERSE if self.popup_pos%numpos==(numpos-2) else curses.color_pair(2))
                w.addstr( 5+interval*i, 25, "[cancel]", curses.A_REVERSE if self.popup_pos%numpos==(numpos-1) else curses.color_pair(2))

            w.refresh()

            c = self.stdscr.getch()
            if c in [ord('q'), 27]: break
            elif c in [curses.KEY_LEFT, curses.KEY_UP]: self.popup_pos -= 1
            elif c in [curses.KEY_RIGHT, curses.KEY_DOWN]: self.popup_pos +=1
            else:
                i = self.popup_pos%numpos
                if buttons and c==10:
                    if i == numpos-2:
                        return out
                    elif i == numpos -1:
                        return {}

                item = items[i]
                _type = item.get('type')

                if _type == 'str':
                    item['value'] = self.edit_str(item['value'], c)
                    out[item.get('label')] = item.get('value')

                elif _type == 'password':
                    item['value'] = self.edit_str(item['value'], c)
                    out[item.get('label')] = item ['value']

                elif _type == 'satoshis':
                    item['value'] = self.edit_str(item['value'], c, True)
                    out[item.get('label')] = item.get('value')

                elif _type == 'list':
                    choices = item.get('choices')
                    try:
                        j = choices.index(item.get('value'))
                    except Exception:
                        j = 0
                    new_choice = choices[(j + 1)% len(choices)]
                    item['value'] = new_choice
                    out[item.get('label')] = item.get('value')

                elif _type == 'button':
                    out['button'] = item.get('label')
                    break

        return out
    def run_wallet_type(self, action, wallet_type):
        if action in ['create', 'restore']:
            if wallet_type == 'multisig':
                wallet_type = self.multisig_choice()
                if not wallet_type:
                    return
            elif wallet_type == 'hardware':
                hardware_wallets = []
                for item in electrum.wallet.wallet_types:
                    t, name, description, loader = item
                    if t == 'hardware':
                        try:
                            p = loader()
                        except:
                            util.print_error("cannot load plugin for:", name)
                            continue
                        if p:
                            hardware_wallets.append((name, description))
                wallet_type = self.choice(_("Hardware Wallet"), 'Select your hardware wallet', hardware_wallets)

                if not wallet_type:
                    return
            elif wallet_type == 'twofactor':
                wallet_type = '2fa'
            if action == '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

        # load wallet in plugins
        always_hook('installwizard_load_wallet', wallet, self)

        while action is not None:
            util.print_error("installwizard:", wallet, action)

            if action == 'create_seed':
                lang = self.config.get('language')
                seed = wallet.make_seed(lang)
                if not self.show_seed(seed, None):
                    return
                self.app.clipboard().clear()
                if not self.verify_seed(seed, None):
                    return
                password = self.password_dialog()
                wallet.add_seed(seed, password)
                wallet.create_master_keys(password)

            elif action == 'add_cosigners':
                n = int(re.match('(\d+)of(\d+)', wallet.wallet_type).group(2))
                xpub1 = wallet.master_public_keys.get("x1/")
                r = self.multi_mpk_dialog(xpub1, n - 1)
                if not r:
                    return
                for i, xpub in enumerate(r):
                    wallet.add_master_public_key("x%d/"%(i+2), xpub)

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

            else:
                f = always_hook('get_wizard_action', self, wallet, action)
                if not f:
                    raise BaseException('unknown wizard action', action)
                r = f(wallet, self)
                if not r:
                    return

            # next action
            action = wallet.get_action()


        if self.network:
            # show network dialog if config does not exist
            if self.config.get('server') is None:
                self.network_dialog()
        else:
            QMessageBox.information(None, _('Warning'), _('You are offline'), _('OK'))


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

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

        return wallet
class ElectrumGui():

    def __init__(self, config, network, plugins):
        self.network = network
        self.config = config


    def main(self):

        storage = WalletStorage(self.config.get_wallet_path())
        if not storage.file_exists:
            action = self.restore_or_create()
            if not action:
                exit()
            self.wallet = wallet = Wallet(storage)
            gap = self.config.get('gap_limit', 5)
            if gap != 5:
                wallet.gap_limit = gap
                wallet.storage.put('gap_limit', gap, True)

            if action == 'create':
                seed = wallet.make_seed()
                show_seed_dialog(seed, None)
                r = change_password_dialog(False, None)
                password = r[2] if r else None
                wallet.add_seed(seed, password)
                wallet.create_master_keys(password)
                wallet.create_main_account(password)
                wallet.synchronize()  # generate first addresses offline

            elif action == 'restore':
                seed = self.seed_dialog()
                if not seed:
                    exit()
                r = change_password_dialog(False, None)
                password = r[2] if r else None
                wallet.add_seed(seed, password)
                wallet.create_master_keys(password)
                wallet.create_main_account(password)

            else:
                exit()
        else:
            self.wallet = Wallet(storage)
            action = None

        self.wallet.start_threads(self.network)

        if action == 'restore':
            self.restore_wallet(wallet)

        w = ElectrumWindow(self.wallet, self.config, self.network)
        #if url: w.set_url(url)
        Gtk.main()

    def restore_or_create(self):
        return restore_create_dialog()

    def seed_dialog(self):
        return run_recovery_dialog()

    def network_dialog(self):
        return run_network_dialog( self.network, parent=None )


    def restore_wallet(self, wallet):

        dialog = Gtk.MessageDialog(
            parent = None,
            flags = Gtk.DialogFlags.MODAL,
            buttons = Gtk.ButtonsType.CANCEL,
            message_format = "Please wait..."  )
        dialog.show()

        def recover_thread( wallet, dialog ):
            wallet.wait_until_synchronized()
            GObject.idle_add(dialog.destroy)

        thread.start_new_thread( recover_thread, ( wallet, dialog ) )
        r = dialog.run()
        dialog.destroy()
        if r==Gtk.ResponseType.CANCEL: return False
        if not wallet.is_found():
            show_message("No transactions found for this seed")

        return True
 def is_mpk(self, text):
     return Wallet.is_xpub(text) or Wallet.is_old_mpk(text)
Esempio n. 22
0
 def is_any(self, seed_e):
     text = self.get_seed_text(seed_e)
     return (Wallet.is_seed(text) or Wallet.is_mpk(text)
             or Wallet.is_address(text) or Wallet.is_private_key(text))
    def __init__(self, _config, _network, plugins):
        global wallet, network, contacts, config
        network = _network
        config = _config
        network.register_callback('updated', update_callback)
        network.register_callback('connected', update_callback)
        network.register_callback('disconnected', update_callback)
        network.register_callback('disconnecting', update_callback)

        contacts = util.StoreDict(config, 'contacts')

        storage = WalletStorage(config.get_wallet_path())
        if not storage.file_exists:
            action = self.restore_or_create()
            if not action:
                exit()

            password  = droid.dialogGetPassword('Choose a password').result
            if password:
                password2  = droid.dialogGetPassword('Confirm password').result
                if password != password2:
                    modal_dialog('Error','passwords do not match')
                    exit()
            else:
                # set to None if it's an empty string
                password = None

            if action == 'create':
                wallet = Wallet(storage)
                seed = wallet.make_seed()
                modal_dialog('Your seed is:', seed)
                wallet.add_seed(seed, password)
                wallet.create_master_keys(password)
                wallet.create_main_account(password)
            elif action == 'restore':
                seed = self.seed_dialog()
                if not seed:
                    exit()
                if not Wallet.is_seed(seed):
                    exit()
                wallet = Wallet.from_seed(seed, password, storage)
            else:
                exit()

            msg = "Creating wallet" if action == 'create' else "Restoring wallet"
            droid.dialogCreateSpinnerProgress("Electrum-GMC", msg)
            droid.dialogShow()
            wallet.start_threads(network)
            if action == 'restore':
                wallet.wait_until_synchronized()
            else:
                wallet.synchronize()
            droid.dialogDismiss()
            droid.vibrate()

        else:
            wallet = Wallet(storage)
            wallet.start_threads(network)
Esempio n. 24
0
    def run_wallet_type(self, action, wallet_type):
        if action in ['create', 'restore']:
            if wallet_type == 'multisig':
                wallet_type = self.multisig_choice()
                if not wallet_type:
                    return
            elif wallet_type == 'hardware':
                hardware_wallets = []
                for item in electrum.wallet.wallet_types:
                    t, name, description, loader = item
                    if t == 'hardware':
                        try:
                            p = loader()
                        except:
                            util.print_error("cannot load plugin for:", name)
                            continue
                        if p:
                            hardware_wallets.append((name, description))
                wallet_type = self.choice(_("Hardware Wallet"),
                                          'Select your hardware wallet',
                                          hardware_wallets)

                if not wallet_type:
                    return
            elif wallet_type == 'twofactor':
                wallet_type = '2fa'
            if action == '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

        # load wallet in plugins
        always_hook('installwizard_load_wallet', wallet, self)

        while action is not None:
            util.print_error("installwizard:", wallet, action)

            if action == 'create_seed':
                lang = self.config.get('language')
                seed = wallet.make_seed(lang)
                if not self.show_seed(seed, None):
                    return
                self.app.clipboard().clear()
                if not self.verify_seed(seed, None):
                    return
                password = self.password_dialog()
                wallet.add_seed(seed, password)
                wallet.create_master_keys(password)

            elif action == 'add_cosigners':
                n = int(re.match('(\d+)of(\d+)', wallet.wallet_type).group(2))
                xpub1 = wallet.master_public_keys.get("x1/")
                r = self.multi_mpk_dialog(xpub1, n - 1)
                if not r:
                    return
                for i, xpub in enumerate(r):
                    wallet.add_master_public_key("x%d/" % (i + 2), xpub)

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

            else:
                f = always_hook('get_wizard_action', self, wallet, action)
                if not f:
                    raise BaseException('unknown wizard action', action)
                r = f(wallet, self)
                if not r:
                    return

            # next action
            action = wallet.get_action()

        if self.network:
            # show network dialog if config does not exist
            if self.config.get('server') is None:
                self.network_dialog()
        else:
            QMessageBox.information(None, _('Warning'), _('You are offline'),
                                    _('OK'))

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

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

        return wallet
Esempio n. 25
0
 def is_mpk(self, text):
     return Wallet.is_xpub(text) or Wallet.is_old_mpk(text)
Esempio n. 26
0
 def is_any(self, text):
     return Wallet.is_seed(text) or Wallet.is_old_mpk(
         text) or Wallet.is_xpub(text) or Wallet.is_xprv(
             text) or Wallet.is_address(text) or Wallet.is_private_key(text)
 def is_any(self, text):
     return Wallet.is_seed(text) or Wallet.is_old_mpk(text) or Wallet.is_xpub(text) or Wallet.is_xprv(text) or Wallet.is_address(text) or Wallet.is_private_key(text)
Esempio n. 28
0
        def on_release(wallet, seed, _dlg, _btn):
            ti_password = _dlg.ids.ti_password
            ti_new_password = _dlg.ids.ti_new_password
            ti_confirm_password = _dlg.ids.ti_confirm_password
            if _btn != _dlg.ids.next:
                if mode == 'restore':
                    # back is disabled cause seed is already set
                    return
                _dlg.close()
                if not instance:
                    # back on create
                    Factory.CreateRestoreDialog(
                        on_release=self.on_creatrestore_complete).open()
                return

            # Confirm
            wallet_name = _dlg.ids.ti_wallet_name.text
            new_password = unicode(ti_new_password.text)
            new_password2 = unicode(ti_confirm_password.text)

            if new_password != new_password2:
                # passwords don't match
                ti_password.text = ""
                ti_new_password.text = ""
                ti_confirm_password.text = ""
                if ti_password.disabled:
                    ti_new_password.focus = True
                else:
                    ti_password.focus = True
                return app.show_error(_('Passwords do not match'), duration=.5)

            if not new_password:
                new_password = None

            if mode == 'restore':
                wallet = Wallet.from_seed(seed, self.storage)
                password = (unicode(ti_password.text)
                            if wallet and wallet.use_encryption else None)

                def on_complete(*l):
                    wallet.create_accounts(new_password)
                    self.load_network(wallet, mode='restore')
                    _dlg.close()

                self.waiting_dialog(
                    lambda: wallet.add_seed(seed, new_password),
                    msg=_("saving seed"),
                    on_complete=on_complete)
                return

            if not instance:
                # create mode
                _dlg.close()
                seed = wallet.make_seed()

                return self.show_seed(password=new_password,
                                      wallet=wallet,
                                      wallet_name=wallet_name,
                                      mode=mode,
                                      seed=seed)

            # change password mode
            try:
                seed = wallet.decode_seed(password)
            except BaseException:
                return app.show_error(_('Incorrect Password'), duration=.5)

            # test carefully
            try:
                wallet.update_password(seed, password, new_password)
            except BaseException:
                return app.show_error(_('Failed to update password'),
                                      exit=True)
            else:
                app.show_info_bubble(text=_('Password successfully updated'),
                                     duration=1,
                                     pos=_btn.pos)
            _dlg.close()

            if instance is None:  # in initial phase
                self.load_wallet()
            self.app.update_wallet()