예제 #1
0
class PasswordDialog(AbstractPasswordDialog):
    enter_pw_message = _('Enter your password')
    enter_new_pw_message = _('Enter new password')
    confirm_new_pw_message = _('Confirm new password')
    wrong_password_message = _('Wrong password')
    allow_disable = False

    def __init__(self, app, **kwargs):
        AbstractPasswordDialog.__init__(self, app, **kwargs)

    def clear_password(self):
        self.ids.textinput_generic_password.text = ''

    def on_password(self, pw: str):
        #
        if not self.require_password:
            self.success = True
            self.message = _('Please wait...')
            self.dismiss()
            return
        # if setting new generic password, enforce min length
        if self.level > 0:
            if len(pw) < 6:
                self.app.show_error(
                    _('Password is too short (min {} characters)').format(6))
                return
        # don't enforce minimum length on existing
        self.do_check(pw)
예제 #2
0
 def update_item(self, item):
     chan = item._chan
     item.status = chan.get_state_for_GUI()
     item.short_channel_id = chan.short_id_for_GUI()
     l, r = self.format_fields(chan)
     item.local_balance = _('Local') + ':' + l
     item.remote_balance = _('Remote') + ': ' + r
     self.update_can_send()
예제 #3
0
 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)
예제 #4
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
예제 #5
0
 def _close(self, b):
     if not b:
         return
     loop = self.app.wallet.network.asyncio_loop
     coro = asyncio.run_coroutine_threadsafe(
         self.app.wallet.lnworker.close_channel(self.chan.channel_id), loop)
     try:
         coro.result(5)
         self.app.show_info(_('Channel closed'))
     except Exception as e:
         self.logger.exception("Could not close channel")
         self.app.show_info(_('Could not close channel: ') +
                            repr(e))  # repr because str(Exception()) == ''
예제 #6
0
 def __init__(self,
              msg,
              callback,
              *,
              yes_str: str = None,
              no_str: str = None,
              title: str = None):
     Factory.Popup.__init__(self)
     self.yes_str = yes_str or _('Yes')
     self.no_str = no_str or _('No')
     self.title = title or _('Question')
     self.message = msg
     self.callback = callback
예제 #7
0
 def export_backup(self):
     text = self.app.wallet.lnworker.export_channel_backup(
         self.chan.channel_id)
     # TODO: some messages are duplicated between Kivy and Qt.
     help_text = ' '.join([
         _("Channel backups can be imported in another instance of the same wallet, by scanning this QR code."
           ),
         _("Please note that channel backups cannot be used to restore your channels."
           ),
         _("If you lose your wallet file, the only thing you can do with a backup is to request your channel to be closed, so that your funds will be sent on-chain."
           ),
     ])
     self.app.qr_dialog(_("Channel Backup " + self.chan.short_id_for_GUI()),
                        text,
                        help_text=help_text)
예제 #8
0
 def on_password(self, pw: str):
     #
     if not self.require_password:
         self.success = True
         self.message = _('Please wait...')
         self.dismiss()
         return
     # if setting new generic password, enforce min length
     if self.level > 0:
         if len(pw) < 6:
             self.app.show_error(
                 _('Password is too short (min {} characters)').format(6))
             return
     # don't enforce minimum length on existing
     self.do_check(pw)
예제 #9
0
 def get_card(self, req: Invoice) -> Dict[str, Any]:
     is_lightning = req.is_lightning()
     if not is_lightning:
         assert isinstance(req, OnchainInvoice)
         address = req.get_address()
         key = address
     else:
         assert isinstance(req, LNInvoice)
         key = req.rhash
         address = req.invoice
     amount = req.get_amount_sat()
     description = req.message
     status = self.app.wallet.get_request_status(key)
     status_str = req.get_status_str(status)
     ci = {}
     ci['screen'] = self
     ci['address'] = address
     ci['is_lightning'] = is_lightning
     ci['key'] = key
     ci['amount'] = self.app.format_amount_and_units(
         amount) if amount else ''
     ci['memo'] = description or _('No Description')
     ci['status'] = status
     ci['status_str'] = status_str
     return ci
예제 #10
0
 def new_request(self, lightning):
     amount = self.amount
     amount = self.app.get_amount(amount) if amount else 0
     message = self.message
     if lightning:
         key = self.app.wallet.lnworker.add_request(amount, message,
                                                    self.expiry())
     else:
         addr = self.address or self.app.wallet.get_unused_address()
         if not addr:
             if not self.app.wallet.is_deterministic():
                 addr = self.app.wallet.get_receiving_address()
             else:
                 self.app.show_info(
                     _('No address available. Please remove some of your pending requests.'
                       ))
                 return
         self.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)
예제 #11
0
 def do_pay_invoice(self, invoice):
     if invoice.is_lightning():
         if self.app.wallet.lnworker:
             self.app.protected(_('Pay lightning invoice?'),
                                self._do_pay_lightning, (invoice, ))
         else:
             self.app.show_error(
                 _("Lightning payments are not available for this wallet"))
     else:
         do_pay = lambda rbf: self._do_pay_onchain(invoice, rbf)
         if self.app.electrum_config.get('use_rbf'):
             d = Question(_('Should this transaction be replaceable?'),
                          do_pay)
             d.open()
         else:
             do_pay(False)
예제 #12
0
 def get_card(self, item: Invoice):
     status = self.app.wallet.get_invoice_status(item)
     status_str = item.get_status_str(status)
     is_lightning = item.type == PR_TYPE_LN
     if is_lightning:
         assert isinstance(item, LNInvoice)
         key = item.rhash
         address = key
         if self.app.wallet.lnworker:
             log = self.app.wallet.lnworker.logs.get(key)
             if status == PR_INFLIGHT and log:
                 status_str += '... (%d)' % len(log)
         is_bip70 = False
     else:
         assert isinstance(item, OnchainInvoice)
         key = item.id
         address = item.get_address()
         is_bip70 = bool(item.bip70)
     return {
         'is_lightning': is_lightning,
         'is_bip70': is_bip70,
         'screen': self,
         'status': status,
         'status_str': status_str,
         'key': key,
         'memo': item.message or _('No Description'),
         'address': address,
         'amount': self.app.format_amount_and_units(item.get_amount_sat()
                                                    or 0),
     }
예제 #13
0
 def __init__(self, chan: Channel, app: 'ElectrumWindow', **kwargs):
     Popup.__init__(self, **kwargs)
     Logger.__init__(self)
     self.is_closed = chan.is_closed()
     self.is_redeemed = chan.is_redeemed()
     self.app = app
     self.chan = chan
     self.title = _('Channel details')
     self.node_id = bh2u(chan.node_id)
     self.channel_id = bh2u(chan.channel_id)
     self.funding_txid = chan.funding_outpoint.txid
     self.short_id = format_short_channel_id(chan.short_channel_id)
     self.capacity = self.app.format_amount_and_units(
         chan.constraints.capacity)
     self.state = chan.get_state_for_GUI()
     self.local_ctn = chan.get_latest_ctn(LOCAL)
     self.remote_ctn = chan.get_latest_ctn(REMOTE)
     self.local_csv = chan.config[LOCAL].to_self_delay
     self.remote_csv = chan.config[REMOTE].to_self_delay
     self.initiator = 'Local' if chan.constraints.is_initiator else 'Remote'
     self.feerate = chan.get_latest_feerate(LOCAL)
     self.can_send = self.app.format_amount_and_units(
         chan.available_to_spend(LOCAL) // 1000)
     self.can_receive = self.app.format_amount_and_units(
         chan.available_to_spend(REMOTE) // 1000)
     self.is_open = chan.is_open()
     closed = chan.get_closing_height()
     if closed:
         self.closing_txid, closing_height, closing_timestamp = closed
예제 #14
0
 def update_status(self):
     req = self.app.wallet.get_request(self.key)
     self.status = self.app.wallet.get_request_status(self.key)
     self.status_str = req.get_status_str(self.status)
     self.status_color = pr_color[self.status]
     if self.status == PR_UNPAID and self.is_lightning and self.app.wallet.lnworker:
         if self.amount_sat and self.amount_sat > self.app.wallet.lnworker.num_sats_can_receive(
         ):
             self.warning = _('Warning') + ': ' + _(
                 'This amount exceeds the maximum you can currently receive with your channels'
             )
     if self.status == PR_UNPAID and not self.is_lightning:
         address = req.get_address()
         if self.app.wallet.is_used(address):
             self.warning = _('Warning') + ': ' + _(
                 'This address is being reused')
예제 #15
0
    def ipport_dialog(self):
        def callback(text):
            self.ipport = text

        d = LabelDialog(_('IP/port in format:\n[host]:[port]'), self.ipport,
                        callback)
        d.open()
예제 #16
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')
예제 #17
0
 def __init__(self, chan: AbstractChannel, app: 'ElectrumWindow', **kwargs):
     Popup.__init__(self, **kwargs)
     Logger.__init__(self)
     self.chan = chan
     self.app = app
     self.short_id = format_short_channel_id(chan.short_channel_id)
     self.state = chan.get_state_for_GUI()
     self.title = _('Channel Backup')
예제 #18
0
class PincodeDialog(AbstractPasswordDialog):
    enter_pw_message = _('Enter your PIN')
    enter_new_pw_message = _('Enter new PIN')
    confirm_new_pw_message = _('Confirm new PIN')
    wrong_password_message = _('Wrong PIN')
    allow_disable = True

    def __init__(self, app, **kwargs):
        AbstractPasswordDialog.__init__(self, app, **kwargs)

    def clear_password(self):
        self.ids.kb.password = ''

    def on_password(self, pw: str):
        # PIN codes are exactly 6 chars
        if len(pw) >= 6:
            self.do_check(pw)
예제 #19
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()
예제 #20
0
 def on_address(self, addr):
     req = self.app.wallet.get_request(addr)
     self.status = ''
     if req:
         self.message = req.get('memo', '')
         amount = req.get('amount')
         self.amount = self.app.format_amount_and_units(
             amount) if amount else ''
         status = req.get('status', PR_UNKNOWN)
         self.status = _('Payment received') if status == PR_PAID else ''
예제 #21
0
 def _force_close(self, b):
     if not b:
         return
     if self.chan.is_closed():
         self.app.show_error(_('Channel already closed'))
         return
     loop = self.app.wallet.network.asyncio_loop
     coro = asyncio.run_coroutine_threadsafe(
         self.app.wallet.lnworker.force_close_channel(self.chan.channel_id),
         loop)
     try:
         coro.result(1)
         self.app.show_info(
             _('Channel closed, you may need to wait at least {} blocks, because of CSV delays'
               .format(self.chan.config[REMOTE].to_self_delay)))
     except Exception as e:
         self.logger.exception("Could not force close channel")
         self.app.show_info(_('Could not force close channel: ') +
                            repr(e))  # repr because str(Exception()) == ''
예제 #22
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())
예제 #23
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.save_db()
                self.app._trigger_update_wallet()  # FIXME private...
                self.dismiss()

        d = Question(question, on_prompt)
        d.open()
예제 #24
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()
예제 #25
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 = '!' if self.is_max else self.app.get_amount(self.amount)
     self.app.protected('Create a new channel?', self.do_open_channel,
                        (conn_str, amount))
     self.dismiss()
예제 #26
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()
예제 #27
0
    def do_delete(self, obj):
        from .question import Question

        def cb(result):
            if result:
                self.app.wallet.invoices.remove(obj.key)
            self.hide_menu()
            self.update()

        d = Question(_('Delete invoice?'), cb)
        d.open()
예제 #28
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)
     self.address_color, self.address_background_color = address_colors(
         self.app.wallet, address)
예제 #29
0
    def do_delete(self, req):
        from .question import Question

        def cb(result):
            if result:
                self.app.wallet.remove_payment_request(
                    req.address, self.app.electrum_config)
                self.hide_menu()
                self.update()

        d = Question(_('Delete request'), cb)
        d.open()
예제 #30
0
    def label_dialog(self):
        from .label_dialog import LabelDialog
        key = self.tx.txid()
        text = self.app.wallet.get_label_for_txid(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()