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