URI: 
       tsign and save to file bip70 payment request; redo receive tab layout - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 30bed4c5a937e94bec1f45aaad091c5566554b35
   DIR parent 2f729c25053a4102a0fd1b5dcf8e35b2f1944863
  HTML Author: ThomasV <thomasv@gitorious>
       Date:   Tue, 21 Apr 2015 08:45:51 +0200
       
       sign and save to file bip70 payment request; redo receive tab layout
       
       Diffstat:
         M gui/qt/main_window.py               |      55 +++++++++++++++++++++----------
         M lib/paymentrequest.py               |      26 ++++++++++++++++++--------
       
       2 files changed, 56 insertions(+), 25 deletions(-)
       ---
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -79,7 +79,7 @@ class StatusBarButton(QPushButton):
        
        
        from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_EXPIRED
       -from electrum.paymentrequest import PaymentRequest, InvoiceStore, get_payment_request
       +from electrum.paymentrequest import PaymentRequest, InvoiceStore, get_payment_request, make_payment_request
        
        pr_icons = {
            PR_UNPAID:":icons/unpaid.png",
       t@@ -604,23 +604,18 @@ class ElectrumWindow(QMainWindow):
                grid.addWidget(self.expires_combo, 3, 1)
        
                self.save_request_button = QPushButton(_('Save'))
       -        self.save_request_button.clicked.connect(self.save_payment_request)
       +        self.save_request_button.clicked.connect(self.add_payment_request)
        
                self.new_request_button = QPushButton(_('New'))
                self.new_request_button.clicked.connect(self.new_receive_address)
        
       -        self.qr_button = QPushButton()
       -        self.qr_button.setIcon(QIcon(":icons/qrcode.png"))
       -        self.qr_button.setToolTip(_("Show/Hide QR code window"))
       -        self.qr_button.clicked.connect(lambda x: self.toggle_qr_window())
       +        self.receive_qr = QRCodeWidget(fixedSize=200)
       +        self.receive_qr.mouseReleaseEvent = lambda x: self.toggle_qr_window()
        
                buttons = QHBoxLayout()
       -        buttons.addWidget(self.qr_button)
       +        buttons.addStretch(1)
                buttons.addWidget(self.save_request_button)
                buttons.addWidget(self.new_request_button)
       -        buttons.addStretch(1)
       -        grid.addLayout(buttons, 4, 1, 1, 3)
       -        grid.setRowStretch(5, 1)
        
                self.receive_requests_label = QLabel(_('My Requests'))
                self.receive_list = MyTreeWidget(self, self.receive_list_menu, [_('Date'), _('Account'), _('Address'), _('Description'), _('Amount'), _('Status')], [])
       t@@ -636,9 +631,14 @@ class ElectrumWindow(QMainWindow):
                h.setResizeMode(3, QHeaderView.Stretch)
        
                # layout
       +        vbox_g = QVBoxLayout()
       +        vbox_g.addLayout(grid)
       +        vbox_g.addLayout(buttons)
       +
                hbox = QHBoxLayout()
       -        hbox.addLayout(grid)
       +        hbox.addLayout(vbox_g)
                hbox.addStretch()
       +        hbox.addWidget(self.receive_qr)
        
                w = QWidget()
                vbox = QVBoxLayout(w)
       t@@ -661,7 +661,7 @@ class ElectrumWindow(QMainWindow):
                self.receive_amount_e.setAmount(amount)
                self.new_request_button.setEnabled(True)
        
       -    def receive_list_delete(self, item):
       +    def delete_payment_request(self, item):
                addr = str(item.text(2))
                self.receive_requests.pop(addr)
                self.wallet.storage.put('receive_requests2', self.receive_requests)
       t@@ -685,11 +685,12 @@ class ElectrumWindow(QMainWindow):
                menu = QMenu()
                menu.addAction(_("Copy Address"), lambda: self.app.clipboard().setText(addr))
                menu.addAction(_("Copy URI"), lambda: self.app.clipboard().setText(str(URI)))
       -        menu.addAction(_("Delete"), lambda: self.receive_list_delete(item))
       +        menu.addAction(_("Save as BIP70 file"), lambda: self.export_payment_request(addr))
       +        menu.addAction(_("Delete"), lambda: self.delete_payment_request(item))
                menu.exec_(self.receive_list.viewport().mapToGlobal(position))
        
       -    def save_payment_request(self):
       -        timestamp = int(time.time())
       +    def add_payment_request(self):
       +        now = int(time.time())
                addr = str(self.receive_address_e.text())
                amount = self.receive_amount_e.get_amount()
                message = unicode(self.receive_message_e.text())
       t@@ -699,13 +700,32 @@ class ElectrumWindow(QMainWindow):
                    QMessageBox.warning(self, _('Error'), _('No message or amount'), _('OK'))
                    return
                self.receive_requests = self.wallet.storage.get('receive_requests2',{})
       -        self.receive_requests[addr] = {'time':timestamp, 'amount':amount, 'expiration':expiration}
       +        self.receive_requests[addr] = {'time':now, 'amount':amount, 'expiration':expiration}
                self.wallet.storage.put('receive_requests2', self.receive_requests)
                self.wallet.set_label(addr, message)
                self.update_receive_tab()
                self.update_address_tab()
                self.save_request_button.setEnabled(False)
        
       +    def export_payment_request(self, addr):
       +        req = self.receive_requests[addr]
       +        time = req['time']
       +        amount = req['amount']
       +        expiration = req['expiration']
       +        message = self.wallet.labels.get(addr, '')
       +        script = Transaction.pay_script('address', addr).decode('hex')
       +        outputs = [(script, amount)]
       +        cert_path = self.config.get('cert_path')
       +        chain_path = self.config.get('chain_path')
       +        pr = make_payment_request(outputs, message, time, time + expiration, cert_path, chain_path)
       +        name = 'request.bip70'
       +        fileName = self.getSaveFileName(_("Select where to save your payment request"), name, "*.bip70")
       +        if fileName:
       +            with open(fileName, "wb+") as f:
       +                f.write(str(pr))
       +            self.show_message(_("Request saved successfully"))
       +            self.saved = True
       +
            def get_receive_address(self):
                domain = self.wallet.get_account_addresses(self.current_account, include_change=False)
                for addr in domain:
       t@@ -813,8 +833,9 @@ class ElectrumWindow(QMainWindow):
                amount = self.receive_amount_e.get_amount()
                message = unicode(self.receive_message_e.text()).encode('utf8')
                self.save_request_button.setEnabled((amount is not None) or (message != ""))
       +        uri = util.create_URI(addr, amount, message)
       +        self.receive_qr.setData(uri)
                if self.qr_window and self.qr_window.isVisible():
       -            uri = util.create_URI(addr, amount, message)
                    self.qr_window.set_content(addr, amount, message, uri)
        
        
   DIR diff --git a/lib/paymentrequest.py b/lib/paymentrequest.py
       t@@ -263,19 +263,29 @@ class PaymentRequest:
        
        
        
       -def make_payment_request(amount, script, memo, rsakey=None):
       -    """Generates a http PaymentRequest object"""
       +
       +def make_payment_request(outputs, memo, time, expires, cert_path, chain_path):
            pd = pb2.PaymentDetails()
       -    pd.outputs.add(amount=amount, script=script)
       -    now = int(time.time())
       -    pd.time = now
       -    pd.expires = now + 15*60
       +    for script, amount in outputs:
       +        pd.outputs.add(amount=amount, script=script)
       +    pd.time = time
       +    pd.expires = expires
            pd.memo = memo
       -    #pd.payment_url = 'http://payment_ack.url'
            pr = pb2.PaymentRequest()
            pr.serialized_payment_details = pd.SerializeToString()
            pr.signature = ''
       -    if rsakey:
       +    pr = pb2.PaymentRequest()
       +    pr.serialized_payment_details = pd.SerializeToString()
       +    pr.signature = ''
       +    if cert_path and chain_path:
       +        import tlslite
       +        with open(cert_path, 'r') as f:
       +            rsakey = tlslite.utils.python_rsakey.Python_RSAKey.parsePEM(f.read())
       +        with open(chain_path, 'r') as f:
       +            chain = tlslite.X509CertChain()
       +            chain.parsePemList(f.read())
       +        certificates = pb2.X509Certificates()
       +        certificates.certificate.extend(map(lambda x: str(x.bytes), chain.x509List))
                pr.pki_type = 'x509+sha256'
                pr.pki_data = certificates.SerializeToString()
                msgBytes = bytearray(pr.SerializeToString())