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) if self.app.wallet else [] 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 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 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 = [('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 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'))
def change_password(self, cb): if self.wallet.use_encryption: self.protected( _("Changing PIN code.") + '\n' + _("Enter your current PIN:"), self._change_password, (cb, )) else: self._change_password(cb, None)
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 _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 __init__(self, **kwargs): # initialize variables self._clipboard = Clipboard self.info_bubble = 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) # cached dialogs self._settings_dialog = None self._password_dialog = None
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 update(self, see_all=False): if self.app.wallet is None: return history = self.parse_history(reversed( self.app.wallet.get_history(self.app.current_account))) # repopulate History Card history_card = self.screen.ids.history_container history_card.clear_widgets() count = 0 for item in history: count += 1 conf, icon, date_time, message, value, tx, quote_text = item ri = Factory.HistoryItem() ri.icon = icon ri.date = date_time ri.message = message ri.value = value or 0 ri.value_known = value is not None ri.quote_text = quote_text ri.confirmations = conf ri.tx_hash = tx ri.screen = self history_card.add_widget(ri) if count == 8 and not see_all: break if count == 0: msg = _('This screen shows your list of transactions. It is currently empty.') history_card.add_widget(EmptyLabel(text=msg))
def add_seed(self, text, password): def task(): self.wallet = Wallet.from_text(text, password, self.storage) self.wallet.create_main_account() self.wallet.synchronize() msg= _("Electrum is generating your addresses, please wait.") self.waiting_dialog(task, msg, self.terminate)
def update(self): self.can_broadcast = False if self.tx.is_complete(): self.tx_hash = self.tx.hash() self.description = self.wallet.get_label(self.tx_hash) if self.tx_hash in self.wallet.transactions.keys(): conf, timestamp = self.wallet.get_confirmations(self.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) self.ids.output_list.update(self.tx.outputs())
def label_dialog(self, obj): from dialogs.label_dialog import LabelDialog key = obj.tx_hash text = self.app.wallet.get_label(key) def callback(text): self.app.wallet.set_label(key, text) self.update() d = LabelDialog(_('Enter Transaction Label'), text, callback) d.open()
def _show_seed(self, label, password): if self.wallet.use_encryption and password is None: return try: seed = self.wallet.get_seed(password) except: self.show_error("Invalid PIN") return label.text = _('Seed') + ':\n' + seed
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 new_wallet(self, app, dirname): def cb(text): if text: app.load_wallet_by_name(os.path.join(dirname, text)) if self.ids.wallet_selector.selection: app.load_wallet_by_name(self.ids.wallet_selector.selection[0]) else: d = LabelDialog(_('Enter wallet name'), '', cb) d.open()
def on_keyboard(self, instance, key, keycode, codepoint, modifiers): if key == 27 and self.is_exit is False: self.is_exit = True self.show_info(_('Press again to exit')) return True self.is_exit = False # override settings button if key in (319, 282): #f1/settings button on android #self.gui.main_gui.toggle_settings(self) return True
def update_status(self, *dt): if not self.wallet: self.status = _("No Wallet") return if self.network is None or not self.network.is_running(): self.status = _("Offline") elif self.network.is_connected(): server_height = self.network.get_server_height() server_lag = self.network.get_local_height() - server_height if not self.wallet.up_to_date or server_height == 0: self.status = _("Synchronizing...") elif server_lag > 1: self.status = _("Server lagging (%d blocks)" % server_lag) else: c, u, x = self.wallet.get_account_balance(self.current_account) text = self.format_amount(c + x + u) self.status = str(text.strip() + ' ' + self.base_unit) else: self.status = _("Not connected")
def on_address(self, addr): req = self.app.wallet.get_payment_request(addr, self.app.electrum_config) self.screen.status = '' if req: self.screen.message = unicode(req.get('memo', '')) amount = req.get('amount') self.screen.amount = self.app.format_amount_and_units(amount) if amount else '' status = req.get('status', PR_UNKNOWN) self.screen.status = _('Payment received') if status == PR_PAID else '' Clock.schedule_once(lambda dt: self.update_qr())
def on_ref_label(self, label, touch): if label.touched: label.touched = False self.qr_dialog(label.name, label.data, True) else: label.touched = True self._clipboard.copy(label.data) Clock.schedule_once(lambda dt: self.show_info( _('Text copied to clipboard.\nTap again to display it as QR code.' )))
def restore_seed(self): def on_seed(_dlg, btn): _dlg.close() if btn is _dlg.ids.back: self.run('new') return text = _dlg.get_text() self.run('enter_pin', (text,)) msg = _('Please type your seed phrase using the virtual keyboard.') RestoreSeedDialog(test=Wallet.is_seed, message=msg, on_release=on_seed).open()
def show_info_bubble(self, text=_('Hello World'), pos=None, duration=0, arrow_pos='bottom_mid', width=None, icon='', modal=False, exit=False): '''Method to show a Information Bubble .. parameters:: text: Message to be displayed pos: position for the bubble duration: duration the bubble remains on screen. 0 = click to hide width: width of the Bubble arrow_pos: arrow position for the bubble ''' info_bubble = self.info_bubble if not info_bubble: info_bubble = self.info_bubble = Factory.InfoBubble() win = Window if info_bubble.parent: win.remove_widget(info_bubble if not info_bubble.modal else info_bubble._modal_view) if not arrow_pos: info_bubble.show_arrow = False else: info_bubble.show_arrow = True info_bubble.arrow_pos = arrow_pos img = info_bubble.ids.img if text == 'texture': # icon holds a texture not a source image # display the texture in full screen text = '' img.texture = icon info_bubble.fs = True info_bubble.show_arrow = False img.allow_stretch = True info_bubble.dim_background = True info_bubble.background_image = 'atlas://gui/kivy/theming/light/card' else: info_bubble.fs = False info_bubble.icon = icon #if img.texture and img._coreimage: # img.reload() img.allow_stretch = False info_bubble.dim_background = False info_bubble.background_image = 'atlas://data/images/defaulttheme/bubble' info_bubble.message = text if not pos: pos = (win.center[0], win.center[1] - (info_bubble.height / 2)) info_bubble.show(pos, duration, width, modal=modal, exit=exit)
def restore_xpub(self): def on_xpub(_dlg, btn): _dlg.close() if btn is _dlg.ids.back: self.run('new') return text = _dlg.get_text() self.run('add_seed', (text, None)) msg = _('To create a watching-only wallet, paste your master public key, or scan it using the camera button.') RestoreXpubDialog(test=Wallet.is_mpk, message=msg, on_release=on_xpub).open()
def confirm_seed(self, seed): assert Wallet.is_seed(seed) def on_seed(_dlg, btn): if btn is _dlg.ids.back: _dlg.close() self.run('create') return _dlg.close() self.run('enter_pin', (seed,)) msg = _('Please retype your seed phrase, to confirm that you properly saved it') RestoreSeedDialog(test=lambda x: x==seed, message=msg, on_release=on_seed).open()
def unit_dialog(self, item, dt): if self._unit_dialog is None: def cb(text): self.app._set_bu(text) item.bu = self.app.base_unit self._unit_dialog = ChoiceDialog(_('Denomination'), base_units.keys(), self.app.base_unit, cb) self._unit_dialog.open()
def coinselect_dialog(self, item, dt): if self._coinselect_dialog is None: choosers = sorted(coinchooser.COIN_CHOOSERS.keys()) chooser_name = coinchooser.get_name(self.config) def cb(text): self.config.set_key('coin_chooser', text) item.status = text self._coinselect_dialog = ChoiceDialog(_('Coin selection'), choosers, chooser_name, cb) self._coinselect_dialog.open()
def language_dialog(self, item, dt): if self._language_dialog is None: l = self.config.get('language', 'en_UK') def cb(key): self.config.set_key("language", key, True) item.lang = self.get_language_name() self.app.language = key self._language_dialog = ChoiceDialog(_('Language'), languages, l, cb) self._language_dialog.open()
def create(self): from electrum_sib.wallet import BIP32_Wallet seed = BIP32_Wallet.make_seed() msg = _("If you forget your PIN or lose your device, your seed phrase will be the " "only way to recover your funds.") def on_ok(_dlg, _btn): _dlg.close() if _btn == _dlg.ids.confirm: self.run('confirm_seed', (seed,)) else: self.run('new') ShowSeedDialog(message=msg, seed_text=seed, on_release=on_ok).open()