Exemplo n.º 1
0
 def read_invoice(self):
     address = str(self.screen.address)
     if not address:
         self.app.show_error(
             _('Recipient not specified.') + ' ' +
             _('Please scan a Gravity address or a payment request'))
         return
     if not self.screen.amount:
         self.app.show_error(_('Please enter an amount'))
         return
     try:
         amount = self.app.get_amount(self.screen.amount)
     except:
         self.app.show_error(
             _('Invalid amount') + ':\n' + self.screen.amount)
         return
     message = self.screen.message
     if self.screen.is_lightning:
         return self.app.wallet.lnworker.parse_bech32_invoice(address)
     else:
         if not bitcoin.is_address(address):
             self.app.show_error(
                 _('Invalid Gravity Address') + ':\n' + address)
             return
         outputs = [TxOutput(TYPE_ADDRESS, address, amount)]
         return self.app.wallet.create_invoice(outputs, message,
                                               self.payment_request,
                                               self.parsed_URI)
Exemplo n.º 2
0
 def get_card(self, addr, balance, is_used, label):
     ci = {}
     ci['screen'] = self
     ci['address'] = addr
     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
Exemplo n.º 3
0
 def do_open_channel(self, conn_str, amount, password):
     try:
         chan = self.app.wallet.lnworker.open_channel(conn_str, amount, 0, password=password)
     except Exception as e:
         self.app.show_error(_('Problem opening channel: ') + '\n' + repr(e))
         return
     n = chan.constraints.funding_txn_minimum_depth
     message = '\n'.join([
         _('Channel established.'),
         _('Remote peer ID') + ':' + chan.node_id.hex(),
         _('This channel will be usable after {} confirmations').format(n)
     ])
     self.app.show_info(message)
Exemplo n.º 4
0
 def new_request(self, lightning):
     amount = self.screen.amount
     amount = self.app.get_amount(amount) if amount else 0
     message = self.screen.message
     if lightning:
         payment_hash = self.app.wallet.lnworker.add_invoice(
             amount, message, self.expiry())
         request, direction, is_paid = self.app.wallet.lnworker.invoices.get(
             payment_hash.hex())
         key = payment_hash.hex()
     else:
         addr = self.screen.address or self.app.wallet.get_unused_address()
         if not addr:
             self.app.show_info(
                 _('No address available. Please remove some of your pending requests.'
                   ))
             return
         self.screen.address = addr
         req = self.app.wallet.make_payment_request(addr, amount, message,
                                                    self.expiry())
         self.app.wallet.add_payment_request(req)
         key = addr
     self.clear()
     self.update()
     self.app.show_request(lightning, key)
Exemplo n.º 5
0
 def show_qr(self):
     from electrum_gzro.bitcoin import base_encode, bfh
     raw_tx = str(self.tx)
     text = bfh(raw_tx)
     text = base_encode(text, base=43)
     self.app.qr_dialog(_("Raw Transaction"),
                        text,
                        text_for_clipboard=raw_tx)
Exemplo n.º 6
0
 def fx_status(self):
     fx = self.app.fx
     if fx.is_enabled():
         source = fx.exchange.name()
         ccy = fx.get_currency()
         return '%s [%s]' % (ccy, source)
     else:
         return _('None')
Exemplo n.º 7
0
    def _do_send_onchain(self, amount, message, outputs, rbf):
        # make unsigned transaction
        coins = self.app.wallet.get_spendable_coins(None)
        try:
            tx = self.app.wallet.make_unsigned_transaction(
                coins, outputs, 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(repr(e))
            return
        if rbf:
            tx.set_rbf(True)
        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),
        ]
        x_fee = run_hook('get_tx_extra_fee', self.app.wallet, tx)
        if x_fee:
            x_fee_address, x_fee_amount = x_fee
            msg.append(
                _("Additional fees") + ": " +
                self.app.format_amount_and_units(x_fee_amount))

        feerate_warning = simple_config.FEERATE_WARNING_HIGH_FEE
        if fee > feerate_warning * tx.estimated_size() / 1000:
            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))
Exemplo n.º 8
0
    def expiration_dialog(self, obj):
        from .dialogs.choice_dialog import ChoiceDialog

        def callback(c):
            self.app.electrum_config.set_key('request_expiry', c)

        d = ChoiceDialog(_('Expiration date'), pr_expiration_values,
                         self.expiry(), callback)
        d.open()
Exemplo n.º 9
0
 def __init__(self, parent, address, balance, status, **kwargs):
     super(AddressPopup, self).__init__(**kwargs)
     self.title = _('Address Details')
     self.parent_dialog = parent
     self.app = parent.app
     self.address = address
     self.status = status
     self.script_type = self.app.wallet.get_txin_type(self.address)
     self.balance = self.app.format_amount_and_units(balance)
Exemplo n.º 10
0
    def update_action_button(self):
        action_button = self.ids.action_button
        options = (
            ActionButtonOption(text=_('Sign'),
                               func=lambda btn: self.do_sign(),
                               enabled=self.can_sign),
            ActionButtonOption(text=_('Broadcast'),
                               func=lambda btn: self.do_broadcast(),
                               enabled=self.can_broadcast),
            ActionButtonOption(text=_('Bump fee'),
                               func=lambda btn: self.do_rbf(),
                               enabled=self.can_rbf),
            ActionButtonOption(text=_('Remove'),
                               func=lambda btn: self.remove_local_tx(),
                               enabled=self.is_local_tx),
        )
        num_options = sum(map(lambda o: bool(o.enabled), options))
        # if no options available, hide button
        if num_options == 0:
            action_button.disabled = True
            action_button.opacity = 0
            return
        action_button.disabled = False
        action_button.opacity = 1

        if num_options == 1:
            # only one option, button will correspond to that
            for option in options:
                if option.enabled:
                    action_button.text = option.text
                    self._action_button_fn = option.func
        else:
            # multiple options. button opens dropdown which has one sub-button for each
            dropdown = DropDown()
            action_button.text = _('Options')
            self._action_button_fn = dropdown.open
            for option in options:
                if option.enabled:
                    btn = Button(text=option.text,
                                 size_hint_y=None,
                                 height='48dp')
                    btn.bind(on_release=option.func)
                    dropdown.add_widget(btn)
Exemplo n.º 11
0
 def do_rbf(self):
     from .bump_fee_dialog import BumpFeeDialog
     is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(self.tx)
     if fee is None:
         self.app.show_error(
             _("Can't bump fee: unknown fee for original transaction."))
         return
     size = self.tx.estimated_size()
     d = BumpFeeDialog(self.app, fee, size, self._do_rbf)
     d.open()
Exemplo n.º 12
0
 def on_currency(self, ccy):
     b = (ccy != _('None'))
     self.fx.set_enabled(b)
     if b:
         if ccy != self.fx.get_currency():
             self.fx.set_currency(ccy)
         self.app.fiat_unit = ccy
     else:
         self.app.is_fiat = False
     Clock.schedule_once(lambda dt: self.add_exchanges())
Exemplo n.º 13
0
 def open_channel(self):
     if not self.pubkey or not self.amount:
         self.app.show_info(_('All fields must be filled out'))
         return
     conn_str = self.pubkey
     if self.ipport:
         conn_str += '@' + self.ipport.strip()
     amount = self.app.get_amount(self.amount)
     self.app.protected('Enter PIN to create a new channel', self.do_open_channel, (conn_str, amount))
     self.dismiss()
Exemplo n.º 14
0
 def on_address(self, addr):
     req = self.app.wallet.get_request(addr)
     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 ''
Exemplo n.º 15
0
    def delete_dialog(self):
        from .question import Question

        def cb(result):
            if result:
                self.app.wallet.delete_invoice(self.key)
                self.dismiss()
                self.app.send_screen.update()

        d = Question(_('Delete invoice?'), cb)
        d.open()
Exemplo n.º 16
0
 def send_report(self):
     try:
         loop = self.main_window.network.asyncio_loop
         proxy = self.main_window.network.proxy
         # FIXME network request in GUI thread...
         response = json.loads(
             BaseCrashReporter.send_report(self,
                                           loop,
                                           proxy,
                                           "/crash.json",
                                           timeout=10))
     except (ValueError, ClientError):
         #self.logger.debug("", exc_info=True)
         self.show_popup(_('Unable to send report'),
                         _("Please check your network connection."))
     else:
         self.show_popup(_('Report sent'), response["text"])
         if response["location"]:
             self.open_url(response["location"])
     self.dismiss()
Exemplo n.º 17
0
    def delete_dialog(self):
        from .question import Question

        def cb(result):
            if result:
                self.app.wallet.delete_request(self.key)
                self.dismiss()
                self.app.receive_screen.update()

        d = Question(_('Delete request?'), cb)
        d.open()
Exemplo n.º 18
0
    def remove_local_tx(self):
        txid = self.tx.txid()
        to_delete = {txid}
        to_delete |= self.wallet.get_depending_transactions(txid)
        question = _("Are you sure you want to remove this transaction?")
        if len(to_delete) > 1:
            question = (_(
                "Are you sure you want to remove this transaction and {} child transactions?"
            ).format(len(to_delete) - 1))

        def on_prompt(b):
            if b:
                for tx in to_delete:
                    self.wallet.remove_transaction(tx)
                self.wallet.storage.write()
                self.app._trigger_update_wallet()  # FIXME private...
                self.dismiss()

        d = Question(question, on_prompt)
        d.open()
Exemplo n.º 19
0
    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()
Exemplo n.º 20
0
    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()
Exemplo n.º 21
0
    def label_dialog(self):
        from .label_dialog import LabelDialog
        key = self.tx.txid()
        text = self.app.wallet.get_label(key)

        def callback(text):
            self.app.wallet.set_label(key, text)
            self.update()
            self.app.history_screen.update()

        d = LabelDialog(_('Enter Transaction Label'), text, callback)
        d.open()
Exemplo n.º 22
0
    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_list,
                                             self.app.base_unit,
                                             cb,
                                             keep_choice_order=True)
        self._unit_dialog.open()
Exemplo n.º 23
0
 def set_ln_invoice(self, invoice):
     try:
         lnaddr = lndecode(invoice, expected_hrp=constants.net.SEGWIT_HRP)
     except Exception as e:
         self.app.show_info(invoice +
                            _(" is not a valid Lightning invoice: ") +
                            repr(e))  # repr because str(Exception()) == ''
         return
     self.screen.address = invoice
     self.screen.message = dict(lnaddr.tags).get('d', None)
     self.screen.amount = self.app.format_amount_and_units(
         lnaddr.amount * bitcoin.COIN) if lnaddr.amount else ''
     self.payment_request = None
     self.screen.is_lightning = True
Exemplo n.º 24
0
 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 = ''
Exemplo n.º 25
0
 def set_URI(self, text):
     if not self.app.wallet:
         self.payment_request_queued = text
         return
     try:
         uri = parse_URI(text, self.app.on_pr, loop=self.app.asyncio_loop)
     except InvalidBitcoinURI as e:
         self.app.show_info(_("Error parsing URI") + f":\n{e}")
         return
     self.parsed_URI = uri
     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_lightning = False
Exemplo n.º 26
0
 def do_pay_invoice(self, invoice):
     if invoice['type'] == PR_TYPE_LN:
         self._do_send_lightning(invoice['invoice'], invoice['amount'])
         return
     elif invoice['type'] == PR_TYPE_ONCHAIN:
         message = invoice['message']
         outputs = invoice['outputs']  # type: List[TxOutput]
         amount = sum(map(lambda x: x.value, outputs))
         do_pay = lambda rbf: self._do_send_onchain(amount, message,
                                                    outputs, rbf)
         if self.app.electrum_config.get('use_rbf'):
             d = Question(_('Should this transaction be replaceable?'),
                          do_pay)
             d.open()
         else:
             do_pay(False)
     else:
         raise Exception('unknown invoice type')
Exemplo n.º 27
0
    def clear_requests_dialog(self):
        expired = [
            req for req in self.app.wallet.get_sorted_requests()
            if req['status'] == PR_EXPIRED
        ]
        if len(expired) == 0:
            return

        def callback(c):
            if c:
                for req in expired:
                    is_lightning = req.get('lightning', False)
                    key = req['rhash'] if is_lightning else req['address']
                    self.app.wallet.delete_request(key)
                self.update()

        d = Question(_('Delete expired requests?'), callback)
        d.open()
Exemplo n.º 28
0
 def do_paste(self):
     data = self.app._clipboard.paste().strip()
     if not data:
         self.app.show_info(_("Clipboard is empty"))
         return
     # try to decode as transaction
     try:
         raw_tx = tx_from_str(data)
         tx = Transaction(raw_tx)
         tx.deserialize()
     except:
         tx = None
     if tx:
         self.app.tx_dialog(tx)
         return
     lower = data.lower()
     if lower.startswith('lightning:ln'):
         lower = lower[10:]
     # try to decode as URI/address
     if lower.startswith('ln'):
         self.set_ln_invoice(lower)
     else:
         self.set_URI(data)
Exemplo n.º 29
0
    def update(self):
        format_amount = self.app.format_amount_and_units
        tx_details = self.wallet.get_tx_info(self.tx)
        tx_mined_status = tx_details.tx_mined_status
        exp_n = tx_details.mempool_depth_bytes
        amount, fee = tx_details.amount, tx_details.fee
        self.status_str = tx_details.status
        self.description = tx_details.label
        self.can_broadcast = tx_details.can_broadcast
        self.can_rbf = tx_details.can_bump
        self.tx_hash = tx_details.txid or ''
        if tx_mined_status.timestamp:
            self.date_label = _('Date')
            self.date_str = datetime.fromtimestamp(
                tx_mined_status.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)
        if fee is not None:
            self.fee_str = format_amount(fee)
            fee_per_kb = fee / self.tx.estimated_size() * 1000
            self.feerate_str = self.app.format_fee_rate(fee_per_kb)
        else:
            self.fee_str = _('unknown')
            self.feerate_str = _('unknown')
        self.can_sign = self.wallet.can_sign(self.tx)
        self.ids.output_list.update(self.tx.get_outputs_for_UI())
        self.is_local_tx = tx_mined_status.height == TX_HEIGHT_LOCAL
        self.update_action_button()
Exemplo n.º 30
0
 def do_share(self):
     self.app.do_share(self.data, _("Share Invoice"))
     self.dismiss()