show payment request details
authorThomasV <thomasv@gitorious>
Sat, 7 Jun 2014 17:53:54 +0000 (19:53 +0200)
committerThomasV <thomasv@gitorious>
Sat, 7 Jun 2014 17:53:54 +0000 (19:53 +0200)
gui/qt/__init__.py
gui/qt/main_window.py
gui/qt/util.py
lib/paymentrequest.py

index b318b5f..169c05f 100644 (file)
@@ -169,11 +169,7 @@ class ElectrumGui:
                 QMessageBox.warning(self.main_window, _('Error'), _('Invalid Amount'), _('OK'))
 
         if request_url:
-            try:
-                from electrum import paymentrequest
-            except:
-                print "cannot import paymentrequest"
-                request_url = None
+            from electrum import paymentrequest
 
         if not request_url:
             self.main_window.set_send(address, amount, label, message)
index 9be738b..cfeac68 100644 (file)
@@ -933,7 +933,8 @@ class ElectrumWindow(QMainWindow):
         self.update_invoices_tab()
 
         self.payto_help.show()
-        self.payto_help.set_alt(pr.status)
+        self.payto_help.set_alt(lambda: self.show_pr_details(pr))
+
         self.payto_e.setGreen()
         self.payto_e.setText(pr.domain)
         self.amount_e.setText(self.format_amount(pr.get_amount()))
@@ -973,7 +974,6 @@ class ElectrumWindow(QMainWindow):
             h.show()
 
         self.payto_help.set_alt(None)
-
         self.set_pay_from([])
         self.update_status()
 
@@ -1211,18 +1211,36 @@ class ElectrumWindow(QMainWindow):
         menu.exec_(self.contacts_list.viewport().mapToGlobal(position))
 
     def delete_invoice(self, item):
-        k = self.invoices_list.indexOfTopLevelItem(item)
-        key = self.invoices.keys()[k]
         self.invoices.pop(key)
         self.wallet.storage.put('invoices', self.invoices)
         self.update_invoices_tab()
 
+    def show_invoice(self, key):
+        from electrum.paymentrequest import PaymentRequest
+        domain, value = self.invoices[key]
+        pr = PaymentRequest(self.config)
+        pr.read_file(key)
+        pr.domain = domain
+        pr.verify()
+        self.show_pr_details(pr)
+
+    def show_pr_details(self, pr):
+        msg = 'Domain: ' + pr.domain
+        msg += '\nStatus: ' + pr.get_status()
+        msg += '\nMemo: ' + pr.memo
+        msg += '\nPayment URL: ' + pr.payment_url
+        msg += '\n\nOutputs:\n' + '\n'.join(map(lambda x: x[0] + ' ' + self.format_amount(x[1])+ self.base_unit(), pr.get_outputs()))
+        QMessageBox.information(self, 'Invoice', msg , 'OK')
+
     def create_invoice_menu(self, position):
         item = self.invoices_list.itemAt(position)
         if not item:
             return
+        k = self.invoices_list.indexOfTopLevelItem(item)
+        key = self.invoices.keys()[k]
         menu = QMenu()
-        menu.addAction(_("Delete"), lambda: self.delete_invoice(item))
+        menu.addAction(_("Details"), lambda: self.show_invoice(key))
+        menu.addAction(_("Delete"), lambda: self.delete_invoice(key))
         menu.exec_(self.invoices_list.viewport().mapToGlobal(position))
 
 
index 99c143f..9842f05 100644 (file)
@@ -56,17 +56,19 @@ class HelpButton(QPushButton):
     def __init__(self, text):
         QPushButton.__init__(self, '?')
         self.help_text = text
-        self.alt_text = None
         self.setFocusPolicy(Qt.NoFocus)
         self.setFixedWidth(20)
-        self.clicked.connect(lambda: QMessageBox.information(self, 'Help', self.get_text(), 'OK') )
+        self.alt = None
+        self.clicked.connect(self.onclick)
 
-    def get_text(self):
-        return self.alt_text if self.alt_text else self.help_text
-
-    def set_alt(self, t):
-        self.alt_text = t
+    def set_alt(self, func):
+        self.alt = func
 
+    def onclick(self):
+        if self.alt:
+            apply(self.alt)
+        else:
+            QMessageBox.information(self, 'Help', self.help_text, 'OK')
 
 
 
index 89d1d5d..8a052f6 100644 (file)
@@ -7,20 +7,19 @@ import threading
 import time
 import traceback
 import urllib2
+import urlparse
+
 
 try:
     import paymentrequest_pb2
 except:
-    print "protoc --proto_path=lib/ --python_out=lib/ lib/paymentrequest.proto"
-    raise Exception()
+    sys.exit("Error: could not find paymentrequest_pb2.py. Create it with 'protoc --proto_path=lib/ --python_out=lib/ lib/paymentrequest.proto'")
 
 try:
     import requests
 except ImportError:
     sys.exit("Error: requests does not seem to be installed. Try 'sudo pip install requests'")
 
-import urlparse
-
 
 import bitcoin
 import util
@@ -35,8 +34,7 @@ PR_UNPAID  = 0
 PR_EXPIRED = 1
 PR_SENT    = 2     # sent but not propagated
 PR_PAID    = 3     # send and propagated
-
-
+PR_ERROR   = 4     # could not parse
 
 
 ca_list = {}
@@ -77,10 +75,12 @@ class PaymentRequest:
         self.config = config
         self.outputs = []
         self.error = ""
+        self.dir_path = os.path.join( self.config.path, 'requests')
+        if not os.path.exists(self.dir_path):
+            os.mkdir(self.dir_path)
 
     def read(self, url):
         self.url = url
-
         u = urlparse.urlparse(url)
         self.domain = u.netloc
         try:
@@ -97,6 +97,30 @@ class PaymentRequest:
             self.error = "cannot read"
             return
 
+        self.id = bitcoin.sha256(r)[0:16].encode('hex')
+        filename = os.path.join(self.dir_path, self.id)
+        with open(filename,'w') as f:
+            f.write(r)
+
+        return self.parse(r)
+
+
+    def get_status(self):
+        if self.error:
+            return self.error
+        else:
+            return self.status
+
+
+    def read_file(self, key):
+        filename = os.path.join(self.dir_path, key)
+        with open(filename,'r') as f:
+            r = f.read()
+
+        self.parse(r)
+
+
+    def parse(self, r):
         try:
             self.data = paymentrequest_pb2.PaymentRequest()
             self.data.ParseFromString(r)
@@ -104,17 +128,6 @@ class PaymentRequest:
             self.error = "cannot parse payment request"
             return
 
-        self.id = bitcoin.sha256(r)[0:16].encode('hex')
-        print self.id
-
-        dir_path = os.path.join( self.config.path, 'requests')
-        if not os.path.exists(dir_path):
-            os.mkdir(dir_path)
-        filename = os.path.join(dir_path, self.id)
-        with open(filename,'w') as f:
-            f.write(r)
-
-
 
     def verify(self):
         try:
@@ -217,25 +230,28 @@ class PaymentRequest:
 
         ### SIG Verified
 
-        self.payment_details = pay_det = paymentrequest_pb2.PaymentDetails()
-        pay_det.ParseFromString(paymntreq.serialized_payment_details)
-
-        if pay_det.expires and pay_det.expires < int(time.time()):
-            self.error = "ERROR: Payment Request has Expired."
-            return False
+        self.details = pay_det = paymentrequest_pb2.PaymentDetails()
+        self.details.ParseFromString(paymntreq.serialized_payment_details)
 
         for o in pay_det.outputs:
             addr = transaction.get_address_from_output_script(o.script)[1]
             self.outputs.append( (addr, o.amount) )
 
-        self.memo = pay_det.memo
+        self.memo = self.details.memo
 
         if CA_match:
             self.status = 'Signed by Trusted CA:\n' + CA_OU
 
-        print "payment url", pay_det.payment_url
+        self.payment_url = self.details.payment_url
+
+        if self.has_expired():
+            self.error = "ERROR: Payment Request has Expired."
+            return False
+
         return True
 
+    def has_expired(self):
+        return self.details.expires and self.details.expires < int(time.time())
 
     def get_amount(self):
         return sum(map(lambda x:x[1], self.outputs))
@@ -246,10 +262,16 @@ class PaymentRequest:
     def get_id(self):
         return self.id
 
+    def get_outputs(self):
+        return self.outputs
+
     def send_ack(self, raw_tx, refund_addr):
 
-        pay_det = self.payment_details
-        if not pay_det.payment_url:
+        if self.has_expired():
+            return False, "has expired"
+
+        pay_det = self.details
+        if not self.details.payment_url:
             return False, "no url"
 
         paymnt = paymentrequest_pb2.Payment()
@@ -302,7 +324,7 @@ if __name__ == "__main__":
 
     print 'Payment Request Verified Domain: ', pr.domain
     print 'outputs', pr.outputs
-    print 'Payment Memo: ', pr.payment_details.memo
+    print 'Payment Memo: ', pr.details.memo
 
     tx = "blah"
     pr.send_ack(tx, refund_addr = "1vXAXUnGitimzinpXrqDWVU4tyAAQ34RA")