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)
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, '')
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,'')
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()
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)
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
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()
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)
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