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 on_complete(ok, msg): if ok: self.show_info(_('Payment sent.')) if self.send_screen: self.send_screen.do_clear() if pr: self.wallet.invoices.set_paid(pr, tx.txid()) self.wallet.invoices.save() self.update_tab('invoices') else: self.show_error(msg)
def broadcast(self, tx, pr=None): def on_complete(ok, msg): if ok: self.show_info(_('Payment sent.')) if self.send_screen: self.send_screen.do_clear() if pr: self.wallet.invoices.set_paid(pr, tx.txid()) self.wallet.invoices.save() self.update_tab('invoices') else: self.show_error(msg) 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 __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: f(obj), 0.15) l.on_release = func self.ids.buttons.add_widget(l)
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 _do_send(self, amount, message, outputs): # make unsigned transaction config = self.app.electrum_config coins = self.app.wallet.get_spendable_coins(None, 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 choose_blockchain_dialog(self, dt): from .uix.dialogs.choice_dialog import ChoiceDialog chains = self.network.get_blockchains() def cb(name): for index, b in self.network.blockchains.items(): if name == self.network.get_blockchain_name(b): self.network.follow_chain(index) #self.block names = [self.network.blockchains[b].get_name() for b in chains] if len(names) > 1: ChoiceDialog(_('Choose your chain'), names, '', cb).open()
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 try: key = self.wallet.export_private_key(addr, password) pk_label.data = key except InvalidPassword: self.show_error("Invalid PIN") return self.protected( _("Enter your PIN code in order to decrypt your private key"), show_private_key, (addr, pk_label))
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 = 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 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.wallet.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 choose_server_dialog(self, popup): from .uix.dialogs.choice_dialog import ChoiceDialog protocol = 's' def cb2(host): from electrum_zclassic import constants pp = servers.get(host, constants.net.DEFAULT_PORTS) port = pp.get(protocol, '') popup.ids.host.text = host popup.ids.port.text = port servers = self.network.get_servers() ChoiceDialog(_('Choose a server'), sorted(servers), popup.ids.host.text, cb2).open()
def set_URI(self, text): import electrum_zclassic try: uri = electrum_zclassic.util.parse_URI(text, self.app.on_pr) except: self.app.show_info(_("Not a Zclassic 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 on_password(self, pw): if len(pw) == 6: if self.check_password(pw): if self.is_change == 0: self.success = True self.pw = pw self.message = _('Please wait...') self.dismiss() elif self.is_change == 1: self.pw = pw self.message = _('Enter new PIN') self.ids.kb.password = '' self.is_change = 2 elif self.is_change == 2: self.new_password = pw self.message = _('Confirm new PIN') self.ids.kb.password = '' self.is_change = 3 elif self.is_change == 3: self.success = pw == self.new_password self.dismiss() else: self.app.show_error(_('Wrong PIN')) self.ids.kb.password = ''
def __init__(self, **kwargs): # initialize variables self._clipboard = Clipboard self.info_bubble = None self.nfcscanner = None self.tabs = None self.is_exit = False self.wallet = None self.pause_time = 0 App.__init__(self) #, **kwargs) title = _('Electrum-Zclassic App') self.electrum_config = config = kwargs.get('config', None) self.language = config.get('language', 'en') self.network = network = kwargs.get('network', None) if self.network: self.num_blocks = self.network.get_local_height() self.num_nodes = len(self.network.get_interfaces()) host, port, protocol, proxy_config, auto_connect = self.network.get_parameters( ) self.server_host = host self.server_port = port self.auto_connect = auto_connect self.proxy_config = proxy_config if proxy_config else {} self.plugins = kwargs.get('plugins', []) self.gui_object = kwargs.get('gui_object', None) self.daemon = self.gui_object.daemon self.fx = self.daemon.fx self.use_change = config.get('use_change', True) self.use_unconfirmed = not config.get('confirmed_only', False) # create triggers so as to minimize updating 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_update_history = Clock.create_trigger( self.update_history, .5) self._trigger_update_interfaces = Clock.create_trigger( self.update_interfaces, .5) # cached dialogs self._settings_dialog = None self._password_dialog = None self.fee_status = self.electrum_config.get_fee_status()
def save_request(self): addr = self.screen.address if not addr: return False amount = self.screen.amount message = self.screen.message amount = self.app.get_amount(amount) if amount else 0 req = self.app.wallet.make_payment_request(addr, amount, message, None) try: self.app.wallet.add_payment_request(req, self.app.electrum_config) added_request = True except Exception as e: self.app.show_error( _('Error adding payment request') + ':\n' + str(e)) added_request = False finally: self.app.update_tab('requests') return added_request
def on_pr(self, pr): if pr.verify(self.wallet.contacts): key = self.wallet.invoices.add(pr) if self.invoices_screen: self.invoices_screen.update() status = self.wallet.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 should be already saved return # save address as invoice from electrum_zclassic.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.wallet.invoices.add(pr) 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
def load_wallet_by_name(self, path): 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-Zclassic: Wallet not found. Launching install wizard' ) storage = WalletStorage(path) wizard = Factory.InstallWizard(self.electrum_config, storage) wizard.bind(on_wizard_complete=self.on_wizard_complete) action = wizard.storage.get_action() wizard.run(action)
def do_sign(self): self.app.protected( _("Enter your PIN code in order to sign this transaction"), self._do_sign, ())
cols: 1 id: invoices_container size_hint: 1, None height: self.minimum_height spacing: '2dp' padding: '12dp' ''') from kivy.properties import BooleanProperty from electrum_zclassic_gui.kivy.i18n import _ from electrum_zclassic.util import format_time from electrum_zclassic.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED from electrum_zclassic_gui.kivy.uix.context_menu import ContextMenu invoice_text = { PR_UNPAID: _('Pending'), PR_UNKNOWN: _('Unknown'), PR_PAID: _('Paid'), 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' } class InvoicesDialog(Factory.Popup): def __init__(self, app, screen, callback): Factory.Popup.__init__(self)
def __init__(self, msg, callback): Factory.Popup.__init__(self) self.title = _('Question') self.message = msg self.callback = callback
def do_save(self): if self.save_request(): self.app.show_info(_('Request was saved.'))
def do_new(self): addr = self.get_new_address() if not addr: self.app.show_info(_('Please use the existing requests first.'))
def show_qr(self): from electrum_zclassic.bitcoin import base_encode, bfh text = bfh(str(self.tx)) text = base_encode(text, base=43) self.app.qr_dialog(_("Raw Transaction"), text)
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()
class ContextMenu(Bubble): buttons = ListProperty([_('ok'), _('cancel')]) '''List of Buttons to be displayed at the bottom''' __events__ = ('on_press', 'on_release') def __init__(self, **kwargs): self._old_buttons = self.buttons super(ContextMenu, self).__init__(**kwargs) self.on_buttons(self, self.buttons) def on_touch_down(self, touch): if not self.collide_point(*touch.pos): self.hide() return return super(ContextMenu, self).on_touch_down(touch) def on_buttons(self, _menu, value): if 'menu_content' not in self.ids.keys(): return if value == self._old_buttons: return blayout = self.ids.menu_content blayout.clear_widgets() for btn in value: ib = ContextButton(text=btn) ib.bind(on_press=partial(self.dispatch, 'on_press')) ib.bind(on_release=partial(self.dispatch, 'on_release')) blayout.add_widget(ib) self._old_buttons = value def on_press(self, instance): pass def on_release(self, instance): pass def show(self, pos, duration=0): 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 = Animation(opacity=1, pos=pos, d=.32) anim.bind(on_complete=on_stop) anim.cancel_all(self) anim.start(self) def hide(self, *dt): def on_stop(*l): Window.remove_widget(self) anim = Animation(opacity=0, d=.25) anim.bind(on_complete=on_stop) anim.cancel_all(self) anim.start(self) def add_widget(self, widget, index=0): if not isinstance(widget, ContextMenuItem): super(ContextMenu, self).add_widget(widget, index) return menu_content.add_widget(widget, index)
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 its 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)
def do_copy(self): uri = self.get_URI() self.app._clipboard.copy(uri) self.app.show_info(_('Request copied to clipboard'))