add payment requests to kivy
This commit is contained in:
parent
2a1fbf01fe
commit
0cef063ee2
|
@ -193,9 +193,24 @@ class ElectrumWindow(App):
|
||||||
self._trigger_notify_transactions = \
|
self._trigger_notify_transactions = \
|
||||||
Clock.create_trigger(self.notify_transactions, 5)
|
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):
|
def set_URI(self, url):
|
||||||
try:
|
try:
|
||||||
url = electrum.util.parse_URI(url)
|
url = electrum.util.parse_URI(url, self.on_pr)
|
||||||
except:
|
except:
|
||||||
self.show_info("Invalid URI", url)
|
self.show_info("Invalid URI", url)
|
||||||
return
|
return
|
||||||
|
@ -214,12 +229,7 @@ class ElectrumWindow(App):
|
||||||
if resultCode == -1: # RESULT_OK:
|
if resultCode == -1: # RESULT_OK:
|
||||||
contents = intent.getStringExtra("SCAN_RESULT")
|
contents = intent.getStringExtra("SCAN_RESULT")
|
||||||
if intent.getStringExtra("SCAN_RESULT_FORMAT") == 'QR_CODE':
|
if intent.getStringExtra("SCAN_RESULT_FORMAT") == 'QR_CODE':
|
||||||
try:
|
on_complete(contents)
|
||||||
uri = electrum.util.parse_URI(contents)
|
|
||||||
except:
|
|
||||||
self.show_info("Invalid URI", url)
|
|
||||||
return
|
|
||||||
on_complete(uri)
|
|
||||||
activity.bind(on_activity_result=on_qr_result)
|
activity.bind(on_activity_result=on_qr_result)
|
||||||
PythonActivity.mActivity.startActivityForResult(intent, 0)
|
PythonActivity.mActivity.startActivityForResult(intent, 0)
|
||||||
|
|
||||||
|
|
|
@ -181,6 +181,7 @@ class ScreenPassword(Factory.Screen):
|
||||||
class SendScreen(CScreen):
|
class SendScreen(CScreen):
|
||||||
|
|
||||||
kvname = 'send'
|
kvname = 'send'
|
||||||
|
payment_request = None
|
||||||
|
|
||||||
def set_URI(self, uri):
|
def set_URI(self, uri):
|
||||||
print "set uri", uri
|
print "set uri", uri
|
||||||
|
@ -195,6 +196,16 @@ class SendScreen(CScreen):
|
||||||
self.screen.amount = ''
|
self.screen.amount = ''
|
||||||
self.screen.message = ''
|
self.screen.message = ''
|
||||||
self.screen.address = ''
|
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):
|
def do_paste(self):
|
||||||
contents = unicode(self.app._clipboard.get())
|
contents = unicode(self.app._clipboard.get())
|
||||||
|
@ -206,6 +217,12 @@ class SendScreen(CScreen):
|
||||||
self.set_URI(uri)
|
self.set_URI(uri)
|
||||||
|
|
||||||
def do_send(self):
|
def do_send(self):
|
||||||
|
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)
|
address = str(self.screen.address)
|
||||||
if not bitcoin.is_address(address):
|
if not bitcoin.is_address(address):
|
||||||
self.app.show_error(_('Invalid Bitcoin Address') + ':\n' + address)
|
self.app.show_error(_('Invalid Bitcoin Address') + ':\n' + address)
|
||||||
|
@ -215,9 +232,9 @@ class SendScreen(CScreen):
|
||||||
except:
|
except:
|
||||||
self.app.show_error(_('Invalid amount') + ':\n' + self.screen.amount)
|
self.app.show_error(_('Invalid amount') + ':\n' + self.screen.amount)
|
||||||
return
|
return
|
||||||
|
outputs = [('address', address, amount)]
|
||||||
message = unicode(self.screen.message)
|
message = unicode(self.screen.message)
|
||||||
fee = None
|
fee = None
|
||||||
outputs = [('address', address, amount)]
|
|
||||||
self.app.protected(self.send_tx, (outputs, fee, message))
|
self.app.protected(self.send_tx, (outputs, fee, message))
|
||||||
|
|
||||||
def send_tx(self, *args):
|
def send_tx(self, *args):
|
||||||
|
|
|
@ -78,7 +78,7 @@ SendScreen:
|
||||||
id: qr
|
id: qr
|
||||||
text: _('QR Code')
|
text: _('QR Code')
|
||||||
on_release:
|
on_release:
|
||||||
app.scan_qr(on_complete=s.parent.set_URI)
|
app.scan_qr(on_complete=app.set_URI)
|
||||||
Button:
|
Button:
|
||||||
id: paste_button
|
id: paste_button
|
||||||
text: _('Paste')
|
text: _('Paste')
|
||||||
|
|
|
@ -83,7 +83,6 @@ class StatusBarButton(QPushButton):
|
||||||
|
|
||||||
|
|
||||||
from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED
|
from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED
|
||||||
from electrum.paymentrequest import PaymentRequest, get_payment_request
|
|
||||||
|
|
||||||
pr_icons = {
|
pr_icons = {
|
||||||
PR_UNPAID:":icons/unpaid.png",
|
PR_UNPAID:":icons/unpaid.png",
|
||||||
|
@ -1346,37 +1345,28 @@ class ElectrumWindow(QMainWindow, PrintError):
|
||||||
self.payment_request = None
|
self.payment_request = None
|
||||||
self.do_clear()
|
self.do_clear()
|
||||||
|
|
||||||
def pay_to_URI(self, URI):
|
def on_pr(self, request):
|
||||||
if not URI:
|
self.payment_request = request
|
||||||
return
|
|
||||||
try:
|
|
||||||
out = util.parse_URI(unicode(URI))
|
|
||||||
except Exception 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):
|
if self.payment_request.verify(self.contacts):
|
||||||
self.emit(SIGNAL('payment_request_ok'))
|
self.emit(SIGNAL('payment_request_ok'))
|
||||||
else:
|
else:
|
||||||
self.emit(SIGNAL('payment_request_error'))
|
self.emit(SIGNAL('payment_request_error'))
|
||||||
t = threading.Thread(target=get_payment_request_thread)
|
|
||||||
t.setDaemon(True)
|
def pay_to_URI(self, URI):
|
||||||
t.start()
|
if not URI:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
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):
|
||||||
self.prepare_for_payment_request()
|
self.prepare_for_payment_request()
|
||||||
return
|
return
|
||||||
|
|
||||||
address = out.get('address')
|
address = out.get('address')
|
||||||
amount = out.get('amount')
|
amount = out.get('amount')
|
||||||
label = out.get('label')
|
label = out.get('label')
|
||||||
|
|
18
lib/util.py
18
lib/util.py
|
@ -317,7 +317,7 @@ def block_explorer_URL(config, kind, item):
|
||||||
#_ud = re.compile('%([0-9a-hA-H]{2})', re.MULTILINE)
|
#_ud = re.compile('%([0-9a-hA-H]{2})', re.MULTILINE)
|
||||||
#urldecode = lambda x: _ud.sub(lambda m: chr(int(m.group(1), 16)), x)
|
#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
|
import bitcoin
|
||||||
from bitcoin import COIN
|
from bitcoin import COIN
|
||||||
|
|
||||||
|
@ -364,6 +364,22 @@ def parse_URI(uri):
|
||||||
if 'sig' in out:
|
if 'sig' in out:
|
||||||
out['sig'] = bitcoin.base_decode(out['sig'], None, base=58).encode('hex')
|
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
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue