def blockchain_info(self): if len(self.network.blockchains)>1: checkpoint = self.network.get_checkpoint() msg = _('Fork detected at block %d')%checkpoint else: msg = _('The blockchain appears to be one') return msg
def update(self): self.menu_actions = [(_('Use'), self.do_use), (_('Details'), self.do_view)] wallet = self.app.wallet if self.show_change == 0: _list = wallet.get_receiving_addresses() elif self.show_change == 1: _list = wallet.get_change_addresses() else: _list = wallet.get_addresses() search = self.message container = self.ids.search_container container.clear_widgets() n = 0 for address in _list: label = wallet.labels.get(address, '') balance = sum(wallet.get_addr_balance(address)) is_used = wallet.is_used(address) if self.show_used == 1 and (balance or is_used): continue if self.show_used == 2 and balance == 0: continue if self.show_used == 3 and not is_used: continue card = self.get_card(address, balance, is_used, label) if search and not self.ext_search(card, search): continue container.add_widget(card) n += 1 if not n: msg = _('No address matching your search') container.add_widget(EmptyLabel(text=msg))
def load_wallet_by_name(self, path, ask_if_wizard=False): if not path: return if self.wallet and self.wallet.storage.path == path: return wallet = self.daemon.load_wallet(path, None) if wallet: if wallet.has_password(): self.password_dialog(wallet, _('Enter PIN code'), lambda x: self.load_wallet(wallet), self.stop) else: self.load_wallet(wallet) else: Logger.debug('Electrum: Wallet not found or action needed. Launching install wizard') def launch_wizard(): storage = WalletStorage(path, manual_upgrades=True) wizard = Factory.InstallWizard(self.electrum_config, self.plugins, storage) wizard.bind(on_wizard_complete=self.on_wizard_complete) action = wizard.storage.get_action() wizard.run(action) if not ask_if_wizard: launch_wizard() else: from .uix.dialogs.question import Question def handle_answer(b: bool): if b: launch_wizard() else: try: os.unlink(path) except FileNotFoundError: pass self.stop() d = Question(_('Do you want to launch the wizard again?'), handle_answer) d.open()
def update(self): self.menu_actions = [('Pay', self.do_pay), ('Details', self.do_view), ('Delete', self.do_delete)] invoices_list = self.screen.ids.invoices_container invoices_list.clear_widgets() _list = self.app.invoices.sorted_list() for pr in _list: ci = Factory.InvoiceItem() ci.key = pr.get_id() ci.requestor = pr.get_requestor() ci.memo = pr.get_memo() amount = pr.get_amount() if amount: ci.amount = self.app.format_amount_and_units(amount) status = self.app.invoices.get_status(ci.key) ci.status = invoice_text[status] ci.icon = pr_icon[status] else: ci.amount = _('No Amount') ci.status = '' exp = pr.get_expiration_date() ci.date = format_time(exp) if exp else _('Never') ci.screen = self invoices_list.add_widget(ci) if not _list: msg = _('This screen shows the list of payment requests that have been sent to you. You may also use it to store contact addresses.') invoices_list.add_widget(EmptyLabel(text=msg))
def update(self): format_amount = self.app.format_amount_and_units tx_hash, self.status_str, self.description, self.can_broadcast, self.can_rbf, amount, fee, height, conf, timestamp, exp_n = self.wallet.get_tx_info(self.tx) self.tx_hash = tx_hash or '' if timestamp: self.date_label = _('Date') self.date_str = datetime.fromtimestamp(timestamp).isoformat(' ')[:-3] elif exp_n: self.date_label = _('Mempool depth') self.date_str = _('{} from tip').format('%.2f MB'%(exp_n/1000000)) else: self.date_label = '' self.date_str = '' if amount is None: self.amount_str = _("Transaction unrelated to your wallet") elif amount > 0: self.is_mine = False self.amount_str = format_amount(amount) else: self.is_mine = True self.amount_str = format_amount(-amount) self.fee_str = format_amount(fee) if fee is not None else _('unknown') self.can_sign = self.wallet.can_sign(self.tx) self.ids.output_list.update(self.tx.outputs())
def parse_history(self, items): for item in items: tx_hash, conf, value, timestamp, balance = item time_str = _("unknown") if conf > 0: try: time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3] except Exception: time_str = _("error") if conf == -1: time_str = _('Not Verified') icon = "atlas://gui/kivy/theming/light/close" elif conf == 0: time_str = _('Unconfirmed') icon = "atlas://gui/kivy/theming/light/unconfirmed" elif conf < 6: conf = max(1, conf) icon = "atlas://gui/kivy/theming/light/clock{}".format(conf) else: icon = "atlas://gui/kivy/theming/light/confirmed" label = self.app.wallet.get_label(tx_hash) if tx_hash else _('Pruned transaction outputs') date = timestamp_to_datetime(timestamp) quote_text = '' if self.app.fiat_unit and date: rate = run_hook('history_rate', date) if rate: s = run_hook('value_str', value, rate) quote_text = '' if s is None else s + ' ' + self.app.fiat_unit yield (conf, icon, time_str, label, value, tx_hash, quote_text)
def update(self): self.menu_actions = [('Show', self.do_show), ('Details', self.do_view), ('Delete', self.do_delete)] requests_list = self.screen.ids.requests_container requests_list.clear_widgets() _list = self.app.wallet.get_sorted_requests(self.app.electrum_config) for req in _list: address = req['address'] timestamp = req.get('time', 0) amount = req.get('amount') expiration = req.get('exp', None) status = req.get('status') signature = req.get('sig') ci = Factory.RequestItem() ci.address = address ci.memo = self.app.wallet.get_label(address) if amount: status = req.get('status') ci.status = request_text[status] else: received = self.app.wallet.get_addr_received(address) ci.status = self.app.format_amount_and_units(amount) ci.icon = pr_icon[status] ci.amount = self.app.format_amount_and_units(amount) if amount else _('No Amount') ci.date = format_time(timestamp) ci.screen = self requests_list.add_widget(ci) if not _list: msg = _('This screen shows the list of payment requests you made.') requests_list.add_widget(EmptyLabel(text=msg))
def notify_transactions(self, *dt): if not self.network or not self.network.is_connected(): return # temporarily disabled for merge return iface = self.network ptfn = iface.pending_transactions_for_notifications if len(ptfn) > 0: # Combine the transactions if there are more then three tx_amount = len(ptfn) if(tx_amount >= 3): total_amount = 0 for tx in ptfn: is_relevant, is_mine, v, fee = self.wallet.get_tx_value(tx) if(v > 0): total_amount += v self.notify(_("{txs}s new transactions received. Total amount" "received in the new transactions {amount}s" "{unit}s").format(txs=tx_amount, amount=self.format_amount(total_amount), unit=self.base_unit())) iface.pending_transactions_for_notifications = [] else: for tx in iface.pending_transactions_for_notifications: if tx: iface.pending_transactions_for_notifications.remove(tx) is_relevant, is_mine, v, fee = self.wallet.get_tx_value(tx) if(v > 0): self.notify( _("{txs} new transaction received. {amount} {unit}"). format(txs=tx_amount, amount=self.format_amount(v), unit=self.base_unit))
def do_new(self): addr = self.get_new_address() if not addr: self.app.show_info(_('Please use the existing requests first.')) else: self.save_request() self.app.show_info(_('New request added to your list.'))
def update(self): self.menu_actions = [(_('Show'), self.do_show), (_('Delete'), self.do_delete)] requests_list = self.ids.requests_container requests_list.clear_widgets() _list = self.app.wallet.get_sorted_requests(self.app.electrum_config) for pr in _list: ci = self.get_card(pr) requests_list.add_widget(ci)
def __init__(self, wizard, **kwargs): super(RestoreSeedDialog, self).__init__(wizard, **kwargs) self._test = kwargs['is_valid'] from electrum.mnemonic import Mnemonic from electrum.old_mnemonic import words as old_wordlist self.words = set(Mnemonic('en').wordlist).union(set(old_wordlist)) self.ids.text_input_seed.text = test_seed if is_test else '' self.message = _('Please type your seed phrase using the virtual keyboard.') self.title = _('Enter Seed')
def choose_seed(self): msg = ' '.join([ _("Do you want to create a new seed, or to restore a wallet using an existing seed?") ]) choices = [ (_('Create a new seed'), 'create_seed'), (_('I already have a seed'), 'restore_seed'), (_('Watching-only wallet'), 'restore_xpub') ] self.choice_dialog(msg=msg, choices=choices, run_prev=self.new, run_next=self.run)
def change_password(self, cb): from .uix.dialogs.password_dialog import PasswordDialog if self._password_dialog is None: self._password_dialog = PasswordDialog() message = _("Changing PIN code.") + '\n' + _("Enter your current PIN:") def on_success(old_password, new_password): self.wallet.update_password(old_password, new_password) self.show_info(_("Your PIN code was updated")) on_failure = lambda: self.show_error(_("PIN codes do not match")) self._password_dialog.init(self, self.wallet, message, on_success, on_failure, is_change=1) self._password_dialog.open()
def get_card(self, addr, balance, is_used, label): ci = self.cards.get(addr) if ci is None: ci = Factory.AddressItem() ci.screen = self ci.address = addr self.cards[addr] = ci ci.memo = label ci.amount = self.app.format_amount_and_units(balance) ci.status = _('Used') if is_used else _('Funded') if balance > 0 else _('Unused') return ci
def invoices_dialog(self, screen): from .uix.dialogs.invoices import InvoicesDialog if len(self.wallet.invoices.sorted_list()) == 0: self.show_info(' '.join([ _('No saved invoices.'), _('Signed invoices are saved automatically when you scan them.'), _('You may also save unsigned requests or contact addresses using the save button.') ])) return popup = InvoicesDialog(self, screen, None) popup.update() popup.open()
def rbf_dialog(self, label, dt): if self._rbf_dialog is None: from checkbox_dialog import CheckBoxDialog def cb(x): self.config.set_key('use_rbf', x, True) label.status = self.rbf_status() msg = [_('If you check this box, your transactions will be marked as non-final,'), _('and you will have the possiblity, while they are unconfirmed, to replace them with transactions that pays higher fees.'), _('Note that some merchants do not accept non-final transactions until they are confirmed.')] fullname = _('Replace by fee') self._rbf_dialog = CheckBoxDialog(fullname, ' '.join(msg), self.config.get('use_rbf', False), cb) self._rbf_dialog.open()
def new(self): name = os.path.basename(self.storage.path) msg = "\n".join([ _("Welcome to the Electrum installation wizard."), _("The wallet '%s' does not exist.") % name, _("What kind of wallet do you want to create?") ]) choices = [ (_('Standard wallet'), 'create_standard'), (_('Multi-signature wallet'), 'create_multisig'), ] self.choice_dialog(msg=msg, choices=choices, run_prev=self.cancel, run_next=self.run)
def export_private_keys(self, pk_label, addr): if self.wallet.is_watching_only(): self.show_info(_('This is a watching-only wallet. It does not contain private keys.')) return def show_private_key(addr, pk_label, password): if self.wallet.has_password() and password is None: return if not self.wallet.can_export(): return key = str(self.wallet.export_private_key(addr, password)[0]) pk_label.data = key self.protected(_("Enter your PIN code in order to decrypt your private key"), show_private_key, (addr, pk_label))
def broadcast(self, tx, pr=None): def on_complete(ok, txid): self.show_info(txid) if ok and pr: pr.set_paid(tx.hash()) self.invoices.save() self.update_tab('invoices') if self.network and self.network.is_connected(): self.show_info(_('Sending')) threading.Thread(target=self._broadcast_thread, args=(tx, on_complete)).start() else: self.show_info(_('Cannot broadcast transaction') + ':\n' + _('Not connected'))
def _show_seed(self, label, password): if self.wallet.has_password() and password is None: return keystore = self.wallet.keystore try: seed = keystore.get_seed(password) passphrase = keystore.get_passphrase(password) except: self.show_error("Invalid PIN") return label.text = _('Seed') + ':\n' + seed if passphrase: label.text += '\n\n' + _('Passphrase') + ': ' + passphrase
def update(self): self.can_broadcast = False if self.tx.is_complete(): tx_hash = self.tx.hash() self.description = self.wallet.get_label(tx_hash) self.txid_str = _('Transaction ID') + ' :\n' + ' '.join(map(''.join, zip(*[iter(tx_hash)]*4))) if tx_hash in self.wallet.transactions.keys(): conf, timestamp = self.wallet.get_confirmations(tx_hash) self.status_str = _("%d confirmations")%conf if conf else _('Pending') if timestamp: self.date_str = datetime.fromtimestamp(timestamp).isoformat(' ')[:-3] else: self.can_broadcast = self.app.network is not None self.status_str = _('Signed') else: s, r = self.tx.signature_count() self.status_str = _("Unsigned") if s == 0 else _('Partially signed') + ' (%d/%d)'%(s,r) is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(self.tx) self.is_mine = is_mine if is_relevant: if is_mine: if fee is not None: self.amount_str = self.app.format_amount_and_units(-v+fee) self.fee_str = self.app.format_amount_and_units(-fee) else: self.amount_str = self.app.format_amount_and_units(-v) self.fee_str = _("unknown") else: self.amount_str = self.app.format_amount_and_units(v) self.fee_str = '' else: self.amount_str = _("Transaction unrelated to your wallet") self.fee_str = '' self.can_sign = self.wallet.can_sign(self.tx)
def do_save(self): addr = str(self.screen.address) amount = str(self.screen.amount) message = str(self.screen.message) #.ids.message_input.text) if not message and not amount: self.app.show_error(_('No message or amount')) return if amount: amount = self.app.get_amount(amount) else: amount = 0 req = self.app.wallet.make_payment_request(addr, amount, message, None) self.app.wallet.add_payment_request(req, self.app.electrum_config) self.app.show_info(_('Request saved')) self.app.update_tab('requests')
def get_card(self, req): address = req['address'] timestamp = req.get('time', 0) amount = req.get('amount') expiration = req.get('exp', None) status = req.get('status') signature = req.get('sig') ci = self.cards.get(address) if ci is None: ci = Factory.RequestItem() ci.screen = self ci.address = address self.cards[address] = ci ci.memo = self.app.wallet.get_label(address) if amount: status = req.get('status') ci.status = request_text[status] else: received = self.app.wallet.get_addr_received(address) ci.status = self.app.format_amount_and_units(amount) ci.icon = pr_icon[status] ci.amount = self.app.format_amount_and_units(amount) if amount else _('No Amount') ci.date = format_time(timestamp) return ci
def do_delete(self, obj): from dialogs.question import Question def cb(): self.app.invoices.remove(obj.key) self.app.update_tab('invoices') d = Question(_('Delete invoice?'), cb) d.open()
def do_delete(self, obj): from dialogs.question import Question def cb(): self.app.wallet.remove_payment_request(obj.address, self.app.electrum_config) self.update() d = Question(_('Delete request?'), cb) d.open()
def _sign_tx(self, tx, password, on_success, on_failure): try: self.wallet.sign_transaction(tx, password) except InvalidPassword: Clock.schedule_once(lambda dt: on_failure(_("Invalid PIN"))) return Clock.schedule_once(lambda dt: on_success(tx))
def description_dialog(self, screen): from uix.dialogs.label_dialog import LabelDialog text = screen.message def callback(text): screen.message = text d = LabelDialog(_('Enter description'), text, callback) d.open()
def _show_seed(self, label, password): try: seed = self.wallet.get_seed(password) except: self.show_error("Invalid PIN") return label.text = _('Seed') + ':\n' + seed
def __init__(self, **kwargs): # initialize variables self._clipboard = Clipboard self.info_bubble = None self.qrscanner = None self.nfcscanner = None self.tabs = None self.is_exit = False super(ElectrumWindow, self).__init__(**kwargs) title = _('Electrum App') self.electrum_config = config = kwargs.get('config', None) self.language = config.get('language', 'en') self.network = network = kwargs.get('network', None) self.plugins = kwargs.get('plugins', []) self.gui_object = kwargs.get('gui_object', None) #self.config = self.gui_object.config self.contacts = Contacts(self.electrum_config) self.invoices = InvoiceStore(self.electrum_config) # create triggers so as to minimize updation a max of 2 times a sec self._trigger_update_wallet =\ Clock.create_trigger(self.update_wallet, .5) self._trigger_update_status =\ Clock.create_trigger(self.update_status, .5) self._trigger_notify_transactions = \ Clock.create_trigger(self.notify_transactions, 5)
def on_resume(self): now = time.time() if self.wallet.has_password and now - self.pause_time > 60: self.password_dialog(self.wallet, _('Enter PIN'), None, self.stop) if self.nfcscanner: self.nfcscanner.nfc_enable()
def do_send(self): if self.screen.is_pr: if self.payment_request.has_expired(): self.app.show_error(_('Payment request has expired')) return outputs = self.payment_request.get_outputs() else: address = str(self.screen.address) if not address: self.app.show_error( _('Recipient not specified.') + ' ' + _('Please scan a Bitcoin address or a payment request')) return if not bitcoin.is_address(address): self.app.show_error( _('Invalid Bitcoin Address') + ':\n' + address) return try: amount = self.app.get_amount(self.screen.amount) except: self.app.show_error( _('Invalid amount') + ':\n' + self.screen.amount) return outputs = [(bitcoin.TYPE_ADDRESS, address, amount)] message = unicode(self.screen.message) amount = sum(map(lambda x: x[2], outputs)) # make unsigned transaction coins = self.app.wallet.get_spendable_coins() config = self.app.electrum_config try: tx = self.app.wallet.make_unsigned_transaction( coins, outputs, config, None) except NotEnoughFunds: self.app.show_error(_("Not enough funds")) return except Exception as e: traceback.print_exc(file=sys.stdout) self.app.show_error(str(e)) return fee = tx.get_fee() msg = [ _("Amount to be sent") + ": " + self.app.format_amount_and_units(amount), _("Mining fee") + ": " + self.app.format_amount_and_units(fee), ] if fee >= config.get('confirm_fee', 100000): msg.append( _('Warning') + ': ' + _("The fee for this transaction seems unusually high.")) msg.append(_("Enter your PIN code to proceed")) self.app.protected('\n'.join(msg), self.send_tx, (tx, message))
def show_qr(self): from electrum.bitcoin import base_encode text = str(self.tx).decode('hex') text = base_encode(text, base=43) self.app.qr_dialog(_("Raw Transaction"), text)
def _delete_wallet(self, b): if b: basename = os.path.basename(self.wallet.storage.path) self.protected(_("Enter your PIN code to confirm deletion of %s") % basename, self.__delete_wallet, ())
def _change_password2(self, cb, old_password, new_password): self.password_dialog(_('Confirm new PIN'), self._change_password3, (cb, old_password, new_password))
def do_share(self): uri = self.get_URI() self.app.do_share(uri, _("Share Zclassic Request"))
def do_paste(self): contents = self.app._clipboard.paste() if not contents: self.app.show_info(_("Clipboard is empty")) return self.set_URI(contents)
def add_cosigner_dialog(self, **kwargs): kwargs['title'] = _("Add Cosigner") + " %d" % kwargs['index'] kwargs['message'] = _( 'Please paste your cosigners master public key, or scan it using the camera button.' ) AddXpubDialog(self, **kwargs).open()
def do_share(self): uri = self.get_URI() self.app.do_share(uri, _("Share Bitcoin Request"))
def _delete_wallet(self, b): if b: basename = self.wallet.basename() self.protected( _("Enter your PIN code to confirm deletion of {}").format( basename), self.__delete_wallet, ())
def delete_wallet(self): from .uix.dialogs.question import Question basename = os.path.basename(self.wallet.storage.path) d = Question( _('Delete wallet?') + '\n' + basename, self._delete_wallet) d.open()
def show_seed(self, label): self.protected(_("Enter your PIN code in order to decrypt your seed"), self._show_seed, (label, ))
def do_copy(self): uri = self.get_URI() self.app._clipboard.copy(uri) self.app.show_info(_('Request copied to clipboard'))
def change_password(self, cb): if self.wallet.has_password(): self.protected(_("Changing PIN code.") + '\n' + _("Enter your current PIN:"), self._change_password, (cb,)) else: self._change_password(cb, None)
def do_sign(self): self.app.protected(_("Enter your PIN code in order to sign this transaction"), self._do_sign, ())
def change_password(self): self.protected( _("Changing PIN code.") + '\n' + _("Enter your current PIN:"), self._change_password, ())
def _do_sign(self, password): self.status_str = _('Signing') + '...' Clock.schedule_once(lambda dt: self.__do_sign(password), 0.1)
def __do_sign(self, password): try: self.app.wallet.sign_transaction(self.tx, password) except InvalidPassword: self.app.show_error(_("Invalid PIN")) self.update()
def do_save(self): if self.save_request(): self.app.show_info(_('Request was saved.'))
def add_xpub_dialog(self, **kwargs): kwargs['message'] += ' ' + _( 'Use the camera button to scan a QR code.') AddXpubDialog(self, **kwargs).open()
def on_success(old_password, new_password): self.wallet.update_password(old_password, new_password) self.show_info(_("Your PIN code was updated"))
def confirm_seed_dialog(self, **kwargs): kwargs['title'] = _('Confirm Seed') kwargs['message'] = _( 'Please retype your seed phrase, to confirm that you properly saved it' ) ConfirmSeedDialog(self, **kwargs).open()
def do_qr(self): from qr_dialog import QRDialog popup = QRDialog(_("Master Public Key"), self.xpub, True) popup.open()
def do_new(self): addr = self.get_new_address() if not addr: self.app.show_info(_('Please use the existing requests first.'))
def do_share(self): self.app.do_share(self.xpub, _("Master Public Key"))
def update(self): if not self.screen.address: self.get_new_address() else: status = self.app.wallet.get_request_status(self.screen.address) self.screen.status = _('Payment received') if status == PR_PAID else ''
def proxy_status(self): server, port, protocol, proxy, auto_connect = self.app.network.get_parameters( ) return proxy.get('host') + ':' + proxy.get('port') if proxy else _( 'None')
def on_amount_or_message(self): self.save_request() Clock.schedule_once(lambda dt: self.update_qr()) def do_new(self): addr = self.get_new_address() if not addr: self.app.show_info(_('Please use the existing requests first.')) else: self.save_request() self.app.show_info(_('New request added to your list.')) invoice_text = { PR_UNPAID: _('Pending'), PR_UNKNOWN: _('Unknown'), PR_PAID: _('Paid'), PR_EXPIRED: _('Expired') } request_text = { PR_UNPAID: _('Pending'), PR_UNKNOWN: _('Unknown'), PR_PAID: _('Received'), PR_EXPIRED: _('Expired') } pr_icon = { PR_UNPAID: 'atlas://gui/kivy/theming/light/important', PR_UNKNOWN: 'atlas://gui/kivy/theming/light/important', PR_PAID: 'atlas://gui/kivy/theming/light/confirmed', PR_EXPIRED: 'atlas://gui/kivy/theming/light/close'
def do_share(self): uri = self.get_URI() self.app.do_share(uri, _("Share Digital Pandacoin Request"))
def callback(conf): if conf == pin: run_next(pin, False) else: self.show_error(_('PIN mismatch')) self.run('request_password', run_next)
def scan_qr(self, on_complete): if platform != "android": return from jnius import autoclass from android import activity PythonActivity = autoclass("org.renpy.android.PythonActivity") Intent = autoclass("android.content.Intent") intent = Intent("com.google.zxing.client.android.SCAN") intent.putExtra("SCAN_MODE", "QR_CODE_MODE") def on_qr_result(requestCode, resultCode, intent): if requestCode == 0: if resultCode == -1: # RESULT_OK: contents = intent.getStringExtra("SCAN_RESULT") if intent.getStringExtra("SCAN_RESULT_FORMAT") == "QR_CODE": on_complete(contents) else: self.show_error("wrong format " + intent.getStringExtra("SCAN_RESULT_FORMAT")) activity.bind(on_activity_result=on_qr_result) try: PythonActivity.mActivity.startActivityForResult(intent, 0) except: self.show_error( _("Could not start Barcode Scanner.") + " " + _("Please install the Barcode Scanner app from ZXing") )