URI: 
       tsave invoices - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 513f9c2d89e9a530710bb163ea713f6948185fbc
   DIR parent 2bbcae449c0b71fa74d61384888c72a5e437296a
  HTML Author: ThomasV <thomasv@gitorious>
       Date:   Fri,  6 Jun 2014 16:16:14 +0200
       
       save invoices
       
       Diffstat:
         M gui/qt/__init__.py                  |       3 ++-
         M gui/qt/main_window.py               |      37 ++++++++++++++++++++++++++++++-
         M gui/qt/paytoedit.py                 |       6 ++++++
         M lib/paymentrequest.py               |      55 ++++++++++++++++++++++++++-----
       
       4 files changed, 90 insertions(+), 11 deletions(-)
       ---
   DIR diff --git a/gui/qt/__init__.py b/gui/qt/__init__.py
       t@@ -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:
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -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)
       t@@ -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):
       t@@ -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
        
       t@@ -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]:
       t@@ -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()
       t@@ -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('')
       t@@ -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)
   DIR diff --git a/gui/qt/paytoedit.py b/gui/qt/paytoedit.py
       t@@ -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)
       t@@ -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)
       t@@ -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 = []
   DIR diff --git a/lib/paymentrequest.py b/lib/paymentrequest.py
       t@@ -18,6 +18,7 @@ import urlparse
        import requests
        from M2Crypto import X509
        
       +import bitcoin
        from bitcoin import is_valid
        import urlparse
        
       t@@ -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:
       t@@ -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"
       t@@ -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):
        
       t@@ -228,7 +266,6 @@ class PaymentRequest:
        
        
        
       -
        if __name__ == "__main__":
        
            try: