save invoices
authorThomasV <thomasv@gitorious>
Fri, 6 Jun 2014 14:16:14 +0000 (16:16 +0200)
committerThomasV <thomasv@gitorious>
Fri, 6 Jun 2014 14:16:14 +0000 (16:16 +0200)
gui/qt/__init__.py
gui/qt/main_window.py
gui/qt/paytoedit.py
lib/paymentrequest.py

index 26cff8b..b318b5f 100644 (file)
@@ -181,7 +181,8 @@ class ElectrumGui:
             return
 
         def payment_request():
-            self.payment_request = paymentrequest.PaymentRequest(request_url)
+            self.payment_request = paymentrequest.PaymentRequest(self.config)
+            self.payment_request.read(request_url)
             if self.payment_request.verify():
                 self.main_window.emit(SIGNAL('payment_request_ok'))
             else:
index 9620b6c..dae8c32 100644 (file)
@@ -129,6 +129,7 @@ class ElectrumWindow(QMainWindow):
         tabs.addTab(self.create_send_tab(), _('Send') )
         tabs.addTab(self.create_receive_tab(), _('Receive') )
         tabs.addTab(self.create_contacts_tab(), _('Contacts') )
+        tabs.addTab(self.create_invoices_tab(), _('Invoices') )
         tabs.addTab(self.create_console_tab(), _('Console') )
         tabs.setMinimumSize(600, 400)
         tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
@@ -468,6 +469,7 @@ class ElectrumWindow(QMainWindow):
             self.update_receive_tab()
             self.update_contacts_tab()
             self.update_completions()
+            self.update_invoices_tab()
 
 
     def create_history_tab(self):
@@ -808,7 +810,7 @@ class ElectrumWindow(QMainWindow):
             if addr is None or not bitcoin.is_address(addr):
                 QMessageBox.warning(self, _('Error'), _('Invalid Bitcoin Address'), _('OK'))
                 return
-            if type(x) is not int:
+            if x is None:
                 QMessageBox.warning(self, _('Error'), _('Invalid Amount'), _('OK'))
                 return
 
@@ -912,6 +914,7 @@ class ElectrumWindow(QMainWindow):
 
     def prepare_for_payment_request(self):
         self.tabs.setCurrentIndex(1)
+        self.payto_e.is_pr = True
         for e in [self.payto_e, self.amount_e, self.message_e]:
             e.setFrozen(True)
         for h in [self.payto_help, self.amount_help, self.message_help]:
@@ -921,6 +924,13 @@ class ElectrumWindow(QMainWindow):
 
     def payment_request_ok(self):
         pr = self.gui_object.payment_request
+        pr_id = pr.get_id()
+        # save it
+        invoices = self.wallet.storage.get('invoices', {})
+        invoices[pr_id] = (pr.get_domain(), pr.get_amount())
+        invoices = self.wallet.storage.put('invoices', invoices)
+        self.update_invoices_tab()
+
         self.payto_help.show()
         self.payto_help.set_alt(pr.status)
         self.payto_e.setGreen()
@@ -952,6 +962,7 @@ class ElectrumWindow(QMainWindow):
 
 
     def do_clear(self):
+        self.payto_e.is_pr = False
         self.payto_sig.setVisible(False)
         for e in [self.payto_e, self.message_e, self.amount_e, self.fee_e]:
             e.setText('')
@@ -1049,6 +1060,30 @@ class ElectrumWindow(QMainWindow):
         return w
 
 
+    def create_invoices_tab(self):
+        l,w,hbox = self.create_list_tab([_('Recipient'), _('Amount'), _('Status')])
+        l.setContextMenuPolicy(Qt.CustomContextMenu)
+        #l.customContextMenuRequested.connect(self.create_contact_menu)
+        #self.connect(l, SIGNAL('itemDoubleClicked(QTreeWidgetItem*, int)'), lambda a, b: self.address_label_clicked(a,b,l,0,1))
+        #self.connect(l, SIGNAL('itemChanged(QTreeWidgetItem*, int)'), lambda a,b: self.address_label_changed(a,b,l,0,1))
+        self.invoices_list = l
+        hbox.addStretch(1)
+        return w
+
+    def update_invoices_tab(self):
+        invoices = self.wallet.storage.get('invoices', {})
+        l = self.invoices_list
+        l.clear()
+
+        for item, value in invoices.items():
+            domain, amount = value
+            item = QTreeWidgetItem( [ domain, self.format_amount(amount), ""] )
+            l.addTopLevelItem(item)
+
+        l.setCurrentItem(l.topLevelItem(0))
+
+
+
     def delete_imported_key(self, addr):
         if self.question(_("Do you want to remove")+" %s "%addr +_("from your wallet?")):
             self.wallet.delete_imported_key(addr)
index 890cee9..aa26f9d 100644 (file)
@@ -42,6 +42,7 @@ class PayToEdit(QTextEdit):
         self.c = None
         self.textChanged.connect(self.check_text)
         self.outputs = []
+        self.is_pr = False
 
     def lock_amount(self):
         self.amount_edit.setFrozen(True)
@@ -54,8 +55,10 @@ class PayToEdit(QTextEdit):
         self.setStyleSheet(frozen_style if b else normal_style)
 
     def setGreen(self):
+        self.is_pr = True
         self.setStyleSheet("QWidget { background-color:#00ff00;}")
 
+
     def parse_address_and_amount(self, line):
         x, y = line.split(',')
         address = self.parse_address(x)
@@ -77,6 +80,9 @@ class PayToEdit(QTextEdit):
 
 
     def check_text(self):
+        if self.is_pr:
+            return
+
         # filter out empty lines
         lines = filter( lambda x: x, self.lines())
         outputs = []
index d970d49..5a377d8 100644 (file)
@@ -18,6 +18,7 @@ import urlparse
 import requests
 from M2Crypto import X509
 
+import bitcoin
 from bitcoin import is_valid
 import urlparse
 
@@ -29,6 +30,15 @@ import transaction
 REQUEST_HEADERS = {'Accept': 'application/bitcoin-paymentrequest', 'User-Agent': 'Electrum'}
 ACK_HEADERS = {'Content-Type':'application/bitcoin-payment','Accept':'application/bitcoin-paymentack','User-Agent':'Electrum'}
 
+# status can be:
+PR_UNPAID  = 0
+PR_EXPIRED = 1
+PR_SENT    = 2     # sent but not propagated
+PR_PAID    = 3     # send and propagated
+
+
+
+
 ca_path = os.path.expanduser("~/.electrum/ca/ca-bundle.crt")
 ca_list = {}
 try:
@@ -52,32 +62,52 @@ except Exception:
 
 class PaymentRequest:
 
-    def __init__(self, url):
-        self.url = url
+    def __init__(self, config):
+        self.config = config
         self.outputs = []
         self.error = ""
 
+    def read(self, url):
+        self.url = url
 
-    def verify(self):
-        u = urlparse.urlparse(self.url)
+        u = urlparse.urlparse(url)
         self.domain = u.netloc
 
         try:
             connection = httplib.HTTPConnection(u.netloc) if u.scheme == 'http' else httplib.HTTPSConnection(u.netloc)
             connection.request("GET",u.geturl(), headers=REQUEST_HEADERS)
-            resp = connection.getresponse()
+            response = connection.getresponse()
         except:
             self.error = "cannot read url"
             return
 
-        paymntreq = paymentrequest_pb2.PaymentRequest()
         try:
-            r = resp.read()
-            paymntreq.ParseFromString(r)
+            r = response.read()
+        except:
+            self.error = "cannot read"
+            return
+
+        try:
+            self.data = paymentrequest_pb2.PaymentRequest()
+            self.data.ParseFromString(r)
         except:
             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):
+        paymntreq = self.data
         sig = paymntreq.signature
         if not sig:
             self.error = "No signature"
@@ -187,6 +217,14 @@ class PaymentRequest:
         return True
 
 
+    def get_amount(self):
+        return sum(map(lambda x:x[1], self.outputs))
+
+    def get_domain(self):
+        return self.domain
+
+    def get_id(self):
+        return self.id
 
     def send_ack(self, raw_tx, refund_addr):
 
@@ -228,7 +266,6 @@ class PaymentRequest:
 
 
 
-
 if __name__ == "__main__":
 
     try: