ThomasV
12 years ago
5 changed files with 439 additions and 312 deletions
@ -0,0 +1,183 @@ |
|||||
|
from PyQt4.QtGui import * |
||||
|
from PyQt4.QtCore import * |
||||
|
import PyQt4.QtCore as QtCore |
||||
|
from i18n import _ |
||||
|
|
||||
|
from electrum import Wallet, mnemonic |
||||
|
from seed_dialog import SeedDialog |
||||
|
from network_dialog import NetworkDialog |
||||
|
from qt_util import * |
||||
|
|
||||
|
class InstallWizard(QDialog): |
||||
|
|
||||
|
def __init__(self, config, interface): |
||||
|
QDialog.__init__(self) |
||||
|
self.config = config |
||||
|
self.interface = interface |
||||
|
|
||||
|
|
||||
|
def restore_or_create(self): |
||||
|
msg = _("Wallet file not found.")+"\n"+_("Do you want to create a new wallet, or to restore an existing one?") |
||||
|
r = QMessageBox.question(None, _('Message'), msg, _('Create'), _('Restore'), _('Cancel'), 0, 2) |
||||
|
if r==2: return None |
||||
|
return 'restore' if r==1 else 'create' |
||||
|
|
||||
|
|
||||
|
def verify_seed(self, wallet): |
||||
|
r = self.seed_dialog(False) |
||||
|
if r != wallet.seed: |
||||
|
QMessageBox.warning(None, _('Error'), 'incorrect seed', 'OK') |
||||
|
return False |
||||
|
else: |
||||
|
return True |
||||
|
|
||||
|
|
||||
|
def seed_dialog(self, is_restore=True): |
||||
|
d = QDialog() |
||||
|
d.setModal(1) |
||||
|
|
||||
|
vbox = QVBoxLayout() |
||||
|
if is_restore: |
||||
|
msg = _("Please enter your wallet seed (or your master public key if you want to create a watching-only wallet)." + ' ') |
||||
|
else: |
||||
|
msg = _("Your seed is important! To make sure that you have properly saved your seed, please type it here." + ' ') |
||||
|
|
||||
|
msg += _("Your seed can be entered as a sequence of words, or as a hexadecimal string."+ '\n') |
||||
|
|
||||
|
label=QLabel(msg) |
||||
|
label.setWordWrap(True) |
||||
|
vbox.addWidget(label) |
||||
|
|
||||
|
seed_e = QTextEdit() |
||||
|
seed_e.setMaximumHeight(100) |
||||
|
vbox.addWidget(seed_e) |
||||
|
|
||||
|
if is_restore: |
||||
|
grid = QGridLayout() |
||||
|
grid.setSpacing(8) |
||||
|
gap_e = AmountEdit(None, True) |
||||
|
gap_e.setText("5") |
||||
|
grid.addWidget(QLabel(_('Gap limit')), 2, 0) |
||||
|
grid.addWidget(gap_e, 2, 1) |
||||
|
grid.addWidget(HelpButton(_('Keep the default value unless you modified this parameter in your wallet.')), 2, 3) |
||||
|
vbox.addLayout(grid) |
||||
|
|
||||
|
vbox.addLayout(ok_cancel_buttons(d)) |
||||
|
d.setLayout(vbox) |
||||
|
|
||||
|
if not d.exec_(): return |
||||
|
|
||||
|
try: |
||||
|
seed = str(seed_e.toPlainText()) |
||||
|
seed.decode('hex') |
||||
|
except: |
||||
|
try: |
||||
|
seed = mnemonic.mn_decode( seed.split() ) |
||||
|
except: |
||||
|
QMessageBox.warning(None, _('Error'), _('I cannot decode this'), _('OK')) |
||||
|
return |
||||
|
|
||||
|
if not seed: |
||||
|
QMessageBox.warning(None, _('Error'), _('No seed'), _('OK')) |
||||
|
return |
||||
|
|
||||
|
if not is_restore: |
||||
|
return seed |
||||
|
else: |
||||
|
try: |
||||
|
gap = int(unicode(gap_e.text())) |
||||
|
except: |
||||
|
QMessageBox.warning(None, _('Error'), 'error', 'OK') |
||||
|
return |
||||
|
return seed, gap |
||||
|
|
||||
|
|
||||
|
def network_dialog(self): |
||||
|
return NetworkDialog(self.interface, self.config, None).do_exec() |
||||
|
|
||||
|
|
||||
|
def show_seed(self, wallet): |
||||
|
d = SeedDialog() |
||||
|
d.show_seed(wallet.seed, wallet.imported_keys) |
||||
|
|
||||
|
|
||||
|
def password_dialog(self, wallet): |
||||
|
from password_dialog import PasswordDialog |
||||
|
d = PasswordDialog(wallet) |
||||
|
d.run() |
||||
|
|
||||
|
|
||||
|
def restore_wallet(self): |
||||
|
wallet = self.wallet |
||||
|
# wait until we are connected, because the user might have selected another server |
||||
|
if not wallet.interface.is_connected: |
||||
|
waiting = lambda: False if wallet.interface.is_connected else "%s \n" % (_("Connecting...")) |
||||
|
waiting_dialog(waiting) |
||||
|
|
||||
|
waiting = lambda: False if wallet.is_up_to_date() else "%s\n%s %d\n%s %.1f"\ |
||||
|
%(_("Please wait..."),_("Addresses generated:"),len(wallet.addresses(True)),_("Kilobytes received:"), wallet.interface.bytes_received/1024.) |
||||
|
|
||||
|
wallet.set_up_to_date(False) |
||||
|
wallet.interface.poke('synchronizer') |
||||
|
waiting_dialog(waiting) |
||||
|
if wallet.is_found(): |
||||
|
print_error( "Recovery successful" ) |
||||
|
else: |
||||
|
QMessageBox.information(None, _('Error'), _("No transactions found for this seed"), _('OK')) |
||||
|
|
||||
|
return True |
||||
|
|
||||
|
|
||||
|
def run(self): |
||||
|
|
||||
|
a = self.restore_or_create() |
||||
|
if not a: exit() |
||||
|
|
||||
|
wallet = Wallet(self.config) |
||||
|
wallet.interface = self.interface |
||||
|
|
||||
|
if a =='create': |
||||
|
wallet.init_seed(None) |
||||
|
self.show_seed(wallet) |
||||
|
if self.verify_seed(wallet): |
||||
|
wallet.save_seed() |
||||
|
else: |
||||
|
exit() |
||||
|
else: |
||||
|
# ask for seed and gap. |
||||
|
sg = gui.seed_dialog() |
||||
|
if not sg: exit() |
||||
|
seed, gap = sg |
||||
|
if not seed: exit() |
||||
|
wallet.gap_limit = gap |
||||
|
if len(seed) == 128: |
||||
|
wallet.seed = '' |
||||
|
wallet.init_sequence(str(seed)) |
||||
|
else: |
||||
|
wallet.init_seed(str(seed)) |
||||
|
wallet.save_seed() |
||||
|
|
||||
|
# select a server. |
||||
|
s = self.network_dialog() |
||||
|
if s is None: |
||||
|
self.config.set_key("server", None, True) |
||||
|
self.config.set_key('auto_cycle', False, True) |
||||
|
|
||||
|
# generate the first addresses, in case we are offline |
||||
|
if s is None or a == 'create': |
||||
|
wallet.synchronize() |
||||
|
|
||||
|
|
||||
|
if a == 'restore' and s is not None: |
||||
|
try: |
||||
|
keep_it = gui.restore_wallet() |
||||
|
wallet.fill_addressbook() |
||||
|
except: |
||||
|
import traceback |
||||
|
traceback.print_exc(file=sys.stdout) |
||||
|
exit() |
||||
|
|
||||
|
if not keep_it: exit() |
||||
|
|
||||
|
|
||||
|
self.password_dialog(wallet) |
@ -0,0 +1,104 @@ |
|||||
|
#!/usr/bin/env python |
||||
|
# |
||||
|
# Electrum - lightweight Bitcoin client |
||||
|
# Copyright (C) 2013 ecdsa@github |
||||
|
# |
||||
|
# This program is free software: you can redistribute it and/or modify |
||||
|
# it under the terms of the GNU General Public License as published by |
||||
|
# the Free Software Foundation, either version 3 of the License, or |
||||
|
# (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU General Public License |
||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
|
|
||||
|
from PyQt4.QtGui import * |
||||
|
from PyQt4.QtCore import * |
||||
|
from i18n import _ |
||||
|
from qt_util import * |
||||
|
|
||||
|
|
||||
|
class PasswordDialog(QDialog): |
||||
|
|
||||
|
def __init__(self, wallet, parent=None): |
||||
|
QDialog.__init__(self, parent) |
||||
|
self.setModal(1) |
||||
|
self.wallet = wallet |
||||
|
self.parent = parent |
||||
|
|
||||
|
self.pw = QLineEdit() |
||||
|
self.pw.setEchoMode(2) |
||||
|
self.new_pw = QLineEdit() |
||||
|
self.new_pw.setEchoMode(2) |
||||
|
self.conf_pw = QLineEdit() |
||||
|
self.conf_pw.setEchoMode(2) |
||||
|
|
||||
|
vbox = QVBoxLayout() |
||||
|
if parent: |
||||
|
msg = (_('Your wallet is encrypted. Use this dialog to change your password.')+'\n'\ |
||||
|
+_('To disable wallet encryption, enter an empty new password.')) \ |
||||
|
if wallet.use_encryption else _('Your wallet keys are not encrypted') |
||||
|
else: |
||||
|
msg = _("Please choose a password to encrypt your wallet keys.")+'\n'\ |
||||
|
+_("Leave these fields empty if you want to disable encryption.") |
||||
|
vbox.addWidget(QLabel(msg)) |
||||
|
|
||||
|
grid = QGridLayout() |
||||
|
grid.setSpacing(8) |
||||
|
|
||||
|
if wallet.use_encryption: |
||||
|
grid.addWidget(QLabel(_('Password')), 1, 0) |
||||
|
grid.addWidget(self.pw, 1, 1) |
||||
|
|
||||
|
grid.addWidget(QLabel(_('New Password')), 2, 0) |
||||
|
grid.addWidget(self.new_pw, 2, 1) |
||||
|
|
||||
|
grid.addWidget(QLabel(_('Confirm Password')), 3, 0) |
||||
|
grid.addWidget(self.conf_pw, 3, 1) |
||||
|
vbox.addLayout(grid) |
||||
|
|
||||
|
vbox.addLayout(ok_cancel_buttons(self)) |
||||
|
self.setLayout(vbox) |
||||
|
|
||||
|
|
||||
|
def run(self): |
||||
|
wallet = self.wallet |
||||
|
|
||||
|
if not wallet.seed: |
||||
|
QMessageBox.information(parent, _('Error'), _('No seed'), _('OK')) |
||||
|
return |
||||
|
|
||||
|
if not self.exec_(): return |
||||
|
|
||||
|
password = unicode(self.pw.text()) if wallet.use_encryption else None |
||||
|
new_password = unicode(self.new_pw.text()) |
||||
|
new_password2 = unicode(self.conf_pw.text()) |
||||
|
|
||||
|
try: |
||||
|
seed = wallet.decode_seed(password) |
||||
|
except: |
||||
|
QMessageBox.warning(self.parent, _('Error'), _('Incorrect Password'), _('OK')) |
||||
|
return |
||||
|
|
||||
|
if new_password != new_password2: |
||||
|
QMessageBox.warning(self.parent, _('Error'), _('Passwords do not match'), _('OK')) |
||||
|
self.run() # Retry |
||||
|
|
||||
|
try: |
||||
|
wallet.update_password(seed, password, new_password) |
||||
|
except: |
||||
|
QMessageBox.warning(self.parent, _('Error'), _('Failed to update password'), _('OK')) |
||||
|
return |
||||
|
|
||||
|
QMessageBox.information(self.parent, _('Success'), _('Password was updated successfully'), _('OK')) |
||||
|
|
||||
|
if self.parent: |
||||
|
icon = QIcon(":icons/lock.png") if wallet.use_encryption else QIcon(":icons/unlock.png") |
||||
|
self.parent.password_button.setIcon( icon ) |
||||
|
|
||||
|
|
||||
|
|
@ -0,0 +1,82 @@ |
|||||
|
#!/usr/bin/env python |
||||
|
# |
||||
|
# Electrum - lightweight Bitcoin client |
||||
|
# Copyright (C) 2013 ecdsa@github |
||||
|
# |
||||
|
# This program is free software: you can redistribute it and/or modify |
||||
|
# it under the terms of the GNU General Public License as published by |
||||
|
# the Free Software Foundation, either version 3 of the License, or |
||||
|
# (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU General Public License |
||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
|
|
||||
|
from PyQt4.QtGui import * |
||||
|
from PyQt4.QtCore import * |
||||
|
import PyQt4.QtCore as QtCore |
||||
|
from i18n import _ |
||||
|
from electrum import mnemonic |
||||
|
from qrcodewidget import QRCodeWidget |
||||
|
|
||||
|
class SeedDialog(QDialog): |
||||
|
def __init__(self, parent=None): |
||||
|
QDialog.__init__(self, parent) |
||||
|
self.setModal(1) |
||||
|
self.setWindowTitle('Electrum' + ' - ' + _('Seed')) |
||||
|
|
||||
|
|
||||
|
def show_seed(self, seed, imported_keys, parent=None): |
||||
|
|
||||
|
brainwallet = ' '.join(mnemonic.mn_encode(seed)) |
||||
|
|
||||
|
label1 = QLabel(_("Your wallet generation seed is")+ ":") |
||||
|
|
||||
|
seed_text = QTextEdit(brainwallet) |
||||
|
seed_text.setReadOnly(True) |
||||
|
seed_text.setMaximumHeight(130) |
||||
|
|
||||
|
msg2 = _("Please write down or memorize these 12 words (order is important).") + " " \ |
||||
|
+ _("This seed will allow you to recover your wallet in case of computer failure.") + " " \ |
||||
|
+ _("Your seed is also displayed as QR code, in case you want to transfer it to a mobile phone.") + "<p>" \ |
||||
|
+ "<b>"+_("WARNING")+":</b> " + _("Never disclose your seed. Never type it on a website.") + "</b><p>" |
||||
|
if imported_keys: |
||||
|
msg2 += "<b>"+_("WARNING")+":</b> " + _("Your wallet contains imported keys. These keys cannot be recovered from seed.") + "</b><p>" |
||||
|
label2 = QLabel(msg2) |
||||
|
label2.setWordWrap(True) |
||||
|
|
||||
|
logo = QLabel() |
||||
|
logo.setPixmap(QPixmap(":icons/seed.png").scaledToWidth(56)) |
||||
|
logo.setMaximumWidth(60) |
||||
|
|
||||
|
qrw = QRCodeWidget(seed) |
||||
|
|
||||
|
ok_button = QPushButton(_("OK")) |
||||
|
ok_button.setDefault(True) |
||||
|
ok_button.clicked.connect(self.accept) |
||||
|
|
||||
|
grid = QGridLayout() |
||||
|
#main_layout.addWidget(logo, 0, 0) |
||||
|
|
||||
|
grid.addWidget(logo, 0, 0) |
||||
|
grid.addWidget(label1, 0, 1) |
||||
|
|
||||
|
grid.addWidget(seed_text, 1, 0, 1, 2) |
||||
|
|
||||
|
grid.addWidget(qrw, 0, 2, 2, 1) |
||||
|
|
||||
|
vbox = QVBoxLayout() |
||||
|
vbox.addLayout(grid) |
||||
|
vbox.addWidget(label2) |
||||
|
|
||||
|
hbox = QHBoxLayout() |
||||
|
hbox.addStretch(1) |
||||
|
hbox.addWidget(ok_button) |
||||
|
vbox.addLayout(hbox) |
||||
|
|
||||
|
self.setLayout(vbox) |
||||
|
self.exec_() |
Loading…
Reference in new issue