commit 0cef063ee231cc9459dff6829dc33ffc2ed499e2
parent 2a1fbf01fe63dee9f950f7ba7b4d68d456799262
Author: ThomasV <thomasv@electrum.org>
Date: Fri, 11 Dec 2015 15:21:21 +0100
add payment requests to kivy
Diffstat:
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