electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 0cef063ee231cc9459dff6829dc33ffc2ed499e2
parent 2a1fbf01fe63dee9f950f7ba7b4d68d456799262
Author: ThomasV <thomasv@electrum.org>
Date:   Fri, 11 Dec 2015 15:21:21 +0100

add payment requests to kivy

Diffstat:
Mgui/kivy/main_window.py | 24+++++++++++++++++-------
Mgui/kivy/uix/screens.py | 37+++++++++++++++++++++++++++----------
Mgui/kivy/uix/ui_screens/send.kv | 2+-
Mgui/qt/main_window.py | 28+++++++++-------------------
Mlib/util.py | 18+++++++++++++++++-
5 files changed, 71 insertions(+), 38 deletions(-)

diff --git a/gui/kivy/main_window.py b/gui/kivy/main_window.py @@ -193,9 +193,24 @@ class ElectrumWindow(App): self._trigger_notify_transactions = \ Clock.create_trigger(self.notify_transactions, 5) + def on_pr(self, pr): + from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED + if pr.verify(self.contacts): + key = self.invoices.add(pr) + status = self.invoices.get_status(key) + #self.invoices_screen.update() + if status == PR_PAID: + self.show_message("invoice already paid") + self.send_screen.do_clear() + else: + self.send_screen.set_request(pr) + else: + self.show_message("invoice error:" + pr.error) + self.send_screen.do_clear() + def set_URI(self, url): try: - url = electrum.util.parse_URI(url) + url = electrum.util.parse_URI(url, self.on_pr) except: self.show_info("Invalid URI", url) return @@ -214,12 +229,7 @@ class ElectrumWindow(App): if resultCode == -1: # RESULT_OK: contents = intent.getStringExtra("SCAN_RESULT") if intent.getStringExtra("SCAN_RESULT_FORMAT") == 'QR_CODE': - try: - uri = electrum.util.parse_URI(contents) - except: - self.show_info("Invalid URI", url) - return - on_complete(uri) + on_complete(contents) activity.bind(on_activity_result=on_qr_result) PythonActivity.mActivity.startActivityForResult(intent, 0) diff --git a/gui/kivy/uix/screens.py b/gui/kivy/uix/screens.py @@ -181,6 +181,7 @@ class ScreenPassword(Factory.Screen): class SendScreen(CScreen): kvname = 'send' + payment_request = None def set_URI(self, uri): print "set uri", uri @@ -195,6 +196,16 @@ class SendScreen(CScreen): self.screen.amount = '' self.screen.message = '' self.screen.address = '' + self.payment_request = None + + def set_request(self, pr): + if pr.has_expired(): + self.app.show_error(_('Payment request has expired')) + return + self.payment_request = pr + self.screen.address = pr.get_requestor() + self.screen.amount = self.app.format_amount(pr.get_amount()) + self.screen.message = pr.get_memo() def do_paste(self): contents = unicode(self.app._clipboard.get()) @@ -206,18 +217,24 @@ class SendScreen(CScreen): self.set_URI(uri) def do_send(self): - address = str(self.screen.address) - if not bitcoin.is_address(address): - self.app.show_error(_('Invalid Bitcoin 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 + if self.payment_request: + 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 bitcoin.is_address(address): + self.app.show_error(_('Invalid Bitcoin 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 = [('address', address, amount)] message = unicode(self.screen.message) fee = None - outputs = [('address', address, amount)] self.app.protected(self.send_tx, (outputs, fee, message)) def send_tx(self, *args): diff --git a/gui/kivy/uix/ui_screens/send.kv b/gui/kivy/uix/ui_screens/send.kv @@ -78,7 +78,7 @@ SendScreen: id: qr text: _('QR Code') on_release: - app.scan_qr(on_complete=s.parent.set_URI) + app.scan_qr(on_complete=app.set_URI) Button: id: paste_button text: _('Paste') diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py @@ -83,7 +83,6 @@ class StatusBarButton(QPushButton): from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED -from electrum.paymentrequest import PaymentRequest, get_payment_request pr_icons = { PR_UNPAID:":icons/unpaid.png", @@ -1346,37 +1345,28 @@ class ElectrumWindow(QMainWindow, PrintError): self.payment_request = None self.do_clear() + def on_pr(self, request): + self.payment_request = request + if self.payment_request.verify(self.contacts): + self.emit(SIGNAL('payment_request_ok')) + else: + self.emit(SIGNAL('payment_request_error')) + def pay_to_URI(self, URI): if not URI: return try: - out = util.parse_URI(unicode(URI)) - except Exception as e: + out = util.parse_URI(unicode(URI), self.on_pr) + except BaseException as e: QMessageBox.warning(self, _('Error'), _('Invalid bitcoin URI:') + '\n' + str(e), _('OK')) return self.tabs.setCurrentIndex(1) - r = out.get('r') sig = out.get('sig') name = out.get('name') if r or (name and sig): - def get_payment_request_thread(): - if name and sig: - from electrum import paymentrequest - pr = paymentrequest.serialize_request(out).SerializeToString() - self.payment_request = paymentrequest.PaymentRequest(pr) - else: - self.payment_request = get_payment_request(r) - if self.payment_request.verify(self.contacts): - self.emit(SIGNAL('payment_request_ok')) - else: - self.emit(SIGNAL('payment_request_error')) - t = threading.Thread(target=get_payment_request_thread) - t.setDaemon(True) - t.start() self.prepare_for_payment_request() return - address = out.get('address') amount = out.get('amount') label = out.get('label') diff --git a/lib/util.py b/lib/util.py @@ -317,7 +317,7 @@ def block_explorer_URL(config, kind, item): #_ud = re.compile('%([0-9a-hA-H]{2})', re.MULTILINE) #urldecode = lambda x: _ud.sub(lambda m: chr(int(m.group(1), 16)), x) -def parse_URI(uri): +def parse_URI(uri, on_pr=None): import bitcoin from bitcoin import COIN @@ -364,6 +364,22 @@ def parse_URI(uri): if 'sig' in out: out['sig'] = bitcoin.base_decode(out['sig'], None, base=58).encode('hex') + r = out.get('r') + sig = out.get('sig') + name = out.get('name') + if r or (name and sig): + def get_payment_request_thread(): + import paymentrequest as pr + if name and sig: + s = pr.serialize_request(out).SerializeToString() + request = pr.PaymentRequest(s) + else: + request = pr.get_payment_request(r) + on_pr(request) + t = threading.Thread(target=get_payment_request_thread) + t.setDaemon(True) + t.start() + return out