def _change_password(self, cb, old_password): if self.wallet.has_password(): if old_password is None: return try: self.wallet.check_password(old_password) except InvalidPassword: self.show_error("Invalid PIN") return self.password_dialog(_('Enter new PIN'), self._change_password2, (cb, old_password,))
def do_delete(self, obj): from dialogs.question import Question def cb(result): if result: self.app.invoices.remove(obj.key) self.app.update_tab('invoices') d = Question(_('Delete invoice?'), cb) d.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 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 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 do_delete(self, obj): from dialogs.question import Question def cb(result): if result: self.app.wallet.remove_payment_request( obj.address, self.app.electrum_config) self.update() d = Question(_('Delete request?'), cb) d.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 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 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 update_status(self, *dt): if not self.wallet: self.status = _("No Wallet") return if self.network is None or not self.network.is_running(): 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: status = _("Synchronizing...") elif server_lag > 1: status = _("Server lagging (%d blocks)"%server_lag) else: c, u, x = self.wallet.get_balance() text = self.format_amount(c+x+u) status = str(text.strip() + ' ' + self.base_unit) else: status = _("Not connected") n = self.wallet.basename() self.status = '[size=15dp]%s[/size]\n%s' %(n, status) if n !='default_wallet' else status
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 Stratis address or a payment request')) return if not stratis.is_address(address): self.app.show_error( _('Invalid Stratis 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 = [(stratis.TYPE_ADDRESS, address, amount)] message = unicode(self.screen.message) amount = sum(map(lambda x: x[2], outputs)) if self.app.electrum_config.get('use_rbf'): from dialogs.question import Question d = Question(_('Should this transaction be replaceable?'), lambda b: self._do_send(amount, message, outputs, b)) d.open() else: self._do_send(amount, message, outputs, False)
def _do_send(self, amount, message, outputs, rbf): # 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 if rbf: tx.set_sequence(0) 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', 1000000): 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 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 scan_qr(self, on_complete): if platform != 'android': return from jnius import autoclass from android import activity PythonActivity = autoclass('org.kivy.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 __init__(self, obj, action_list): Bubble.__init__(self) self.obj = obj for k, v in action_list: l = MenuItem() l.text = _(k) def func(f=v): Clock.schedule_once(lambda dt: self.hide(), 0.1) Clock.schedule_once(lambda dt: f(obj), 0.15) l.on_release = func self.ids.buttons.add_widget(l)
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: ci = self.get_card(req) 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 set_URI(self, text): import electrum_stratis as electrum try: uri = electrum.util.parse_URI(text, self.app.on_pr) except: self.app.show_info(_("Not a Stratis URI")) return amount = uri.get('amount') self.screen.address = uri.get('address', '') self.screen.message = uri.get('message', '') self.screen.amount = self.app.format_amount_and_units( amount) if amount else '' self.payment_request = None self.screen.is_pr = False
def get_card(self, pr): key = pr.get_id() ci = self.cards.get(key) if ci is None: ci = Factory.InvoiceItem() ci.key = key ci.screen = self self.cards[key] = ci 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') return ci
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 = self.get_card(pr) 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, see_all=False): if self.app.wallet is None: return history = reversed(self.app.wallet.get_history()) history_card = self.screen.ids.history_container history_card.clear_widgets() count = 0 for item in history: ri = self.get_card(*item) count += 1 history_card.add_widget(ri) if count == 0: msg = _( 'This screen shows your list of transactions. It is currently empty.' ) history_card.add_widget(EmptyLabel(text=msg))
def on_pr(self, pr): if pr.verify(self.contacts): key = self.invoices.add(pr) if self.invoices_screen: self.invoices_screen.update() status = self.invoices.get_status(key) if status == PR_PAID: self.show_error("invoice already paid") self.send_screen.do_clear() else: if pr.has_expired(): self.show_error(_('Payment request has expired')) else: self.switch_to('send') self.send_screen.set_request(pr) else: self.show_error("invoice error:" + pr.error) self.send_screen.do_clear()
def do_save(self): if not self.screen.address: return if self.screen.is_pr: # it sould be already saved return # save address as invoice from electrum_stratis.paymentrequest import make_unsigned_request, PaymentRequest req = {'address': self.screen.address, 'memo': self.screen.message} amount = self.app.get_amount( self.screen.amount) if self.screen.amount else 0 req['amount'] = amount pr = make_unsigned_request(req).SerializeToString() pr = PaymentRequest(pr) self.app.invoices.add(pr) self.app.update_tab('invoices') self.app.show_info(_("Invoice saved")) if pr.is_pr(): self.screen.is_pr = True self.payment_request = pr else: self.screen.is_pr = False self.payment_request = None
class ShowSeedDialog(WizardDialog): seed_text = StringProperty('') message = _( "If you forget your PIN or lose your device, your seed phrase will be the only way to recover your funds." ) ext = False def on_parent(self, instance, value): if value: app = App.get_running_app() self._back = _back = partial(self.ids.back.dispatch, 'on_release') def options_dialog(self): from seed_options import SeedOptionsDialog def callback(status): self.ext = status d = SeedOptionsDialog(self.ext, callback) d.open() def get_params(self, b): return (self.ext, )
def _change_password2(self, cb, old_password, new_password): self.password_dialog(_('Confirm new PIN'), self._change_password3, (cb, old_password, new_password))
def __init__(self, msg, callback): Factory.Popup.__init__(self) self.title = _('Question') self.message = msg self.callback = callback
def show_seed(self, label): self.protected(_("Enter your PIN code in order to decrypt your seed"), self._show_seed, (label, ))
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 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 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)
class InfoBubble(Factory.Bubble): '''Bubble to be used to display short Help Information''' message = StringProperty(_('Nothing set !')) '''Message to be displayed; defaults to "nothing set"''' icon = StringProperty('') ''' Icon to be displayed along with the message defaults to '' :attr:`icon` is a `StringProperty` defaults to `''` ''' fs = BooleanProperty(False) ''' Show Bubble in half screen mode :attr:`fs` is a `BooleanProperty` defaults to `False` ''' modal = BooleanProperty(False) ''' Allow bubble to be hidden on touch. :attr:`modal` is a `BooleanProperty` defauult to `False`. ''' exit = BooleanProperty(False) '''Indicates whether to exit app after bubble is closed. :attr:`exit` is a `BooleanProperty` defaults to False. ''' dim_background = BooleanProperty(False) ''' Indicates Whether to draw a background on the windows behind the bubble. :attr:`dim` is a `BooleanProperty` defaults to `False`. ''' def on_touch_down(self, touch): if self.modal: return True self.hide() if self.collide_point(*touch.pos): return True def show(self, pos, duration, width=None, modal=False, exit=False): '''Animate the bubble into position''' self.modal, self.exit = modal, exit if width: self.width = width if self.modal: from kivy.uix.modalview import ModalView self._modal_view = m = ModalView(background_color=[.5, .5, .5, .2]) Window.add_widget(m) m.add_widget(self) else: Window.add_widget(self) # wait for the bubble to adjust it's size according to text then animate Clock.schedule_once(lambda dt: self._show(pos, duration)) def _show(self, pos, duration): def on_stop(*l): if duration: Clock.schedule_once(self.hide, duration + .5) self.opacity = 0 arrow_pos = self.arrow_pos if arrow_pos[0] in ('l', 'r'): pos = pos[0], pos[1] - (self.height / 2) else: pos = pos[0] - (self.width / 2), pos[1] self.limit_to = Window anim = Factory.Animation(opacity=1, pos=pos, d=.32) anim.bind(on_complete=on_stop) anim.cancel_all(self) anim.start(self) def hide(self, now=False): ''' Auto fade out the Bubble ''' def on_stop(*l): if self.modal: m = self._modal_view m.remove_widget(self) Window.remove_widget(m) Window.remove_widget(self) if self.exit: App.get_running_app().stop() import sys sys.exit() else: App.get_running_app().is_exit = False if now: return on_stop() anim = Factory.Animation(opacity=0, d=.25) anim.bind(on_complete=on_stop) anim.cancel_all(self) anim.start(self)