sign and save to file bip70 payment request; redo receive tab layout
This commit is contained in:
parent
2f729c2505
commit
30bed4c5a9
|
@ -79,7 +79,7 @@ class StatusBarButton(QPushButton):
|
||||||
|
|
||||||
|
|
||||||
from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_EXPIRED
|
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_icons = {
|
||||||
PR_UNPAID:":icons/unpaid.png",
|
PR_UNPAID:":icons/unpaid.png",
|
||||||
|
@ -604,23 +604,18 @@ class ElectrumWindow(QMainWindow):
|
||||||
grid.addWidget(self.expires_combo, 3, 1)
|
grid.addWidget(self.expires_combo, 3, 1)
|
||||||
|
|
||||||
self.save_request_button = QPushButton(_('Save'))
|
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 = QPushButton(_('New'))
|
||||||
self.new_request_button.clicked.connect(self.new_receive_address)
|
self.new_request_button.clicked.connect(self.new_receive_address)
|
||||||
|
|
||||||
self.qr_button = QPushButton()
|
self.receive_qr = QRCodeWidget(fixedSize=200)
|
||||||
self.qr_button.setIcon(QIcon(":icons/qrcode.png"))
|
self.receive_qr.mouseReleaseEvent = lambda x: self.toggle_qr_window()
|
||||||
self.qr_button.setToolTip(_("Show/Hide QR code window"))
|
|
||||||
self.qr_button.clicked.connect(lambda x: self.toggle_qr_window())
|
|
||||||
|
|
||||||
buttons = QHBoxLayout()
|
buttons = QHBoxLayout()
|
||||||
buttons.addWidget(self.qr_button)
|
buttons.addStretch(1)
|
||||||
buttons.addWidget(self.save_request_button)
|
buttons.addWidget(self.save_request_button)
|
||||||
buttons.addWidget(self.new_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_requests_label = QLabel(_('My Requests'))
|
||||||
self.receive_list = MyTreeWidget(self, self.receive_list_menu, [_('Date'), _('Account'), _('Address'), _('Description'), _('Amount'), _('Status')], [])
|
self.receive_list = MyTreeWidget(self, self.receive_list_menu, [_('Date'), _('Account'), _('Address'), _('Description'), _('Amount'), _('Status')], [])
|
||||||
|
@ -636,9 +631,14 @@ class ElectrumWindow(QMainWindow):
|
||||||
h.setResizeMode(3, QHeaderView.Stretch)
|
h.setResizeMode(3, QHeaderView.Stretch)
|
||||||
|
|
||||||
# layout
|
# layout
|
||||||
|
vbox_g = QVBoxLayout()
|
||||||
|
vbox_g.addLayout(grid)
|
||||||
|
vbox_g.addLayout(buttons)
|
||||||
|
|
||||||
hbox = QHBoxLayout()
|
hbox = QHBoxLayout()
|
||||||
hbox.addLayout(grid)
|
hbox.addLayout(vbox_g)
|
||||||
hbox.addStretch()
|
hbox.addStretch()
|
||||||
|
hbox.addWidget(self.receive_qr)
|
||||||
|
|
||||||
w = QWidget()
|
w = QWidget()
|
||||||
vbox = QVBoxLayout(w)
|
vbox = QVBoxLayout(w)
|
||||||
|
@ -661,7 +661,7 @@ class ElectrumWindow(QMainWindow):
|
||||||
self.receive_amount_e.setAmount(amount)
|
self.receive_amount_e.setAmount(amount)
|
||||||
self.new_request_button.setEnabled(True)
|
self.new_request_button.setEnabled(True)
|
||||||
|
|
||||||
def receive_list_delete(self, item):
|
def delete_payment_request(self, item):
|
||||||
addr = str(item.text(2))
|
addr = str(item.text(2))
|
||||||
self.receive_requests.pop(addr)
|
self.receive_requests.pop(addr)
|
||||||
self.wallet.storage.put('receive_requests2', self.receive_requests)
|
self.wallet.storage.put('receive_requests2', self.receive_requests)
|
||||||
|
@ -685,11 +685,12 @@ class ElectrumWindow(QMainWindow):
|
||||||
menu = QMenu()
|
menu = QMenu()
|
||||||
menu.addAction(_("Copy Address"), lambda: self.app.clipboard().setText(addr))
|
menu.addAction(_("Copy Address"), lambda: self.app.clipboard().setText(addr))
|
||||||
menu.addAction(_("Copy URI"), lambda: self.app.clipboard().setText(str(URI)))
|
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))
|
menu.exec_(self.receive_list.viewport().mapToGlobal(position))
|
||||||
|
|
||||||
def save_payment_request(self):
|
def add_payment_request(self):
|
||||||
timestamp = int(time.time())
|
now = int(time.time())
|
||||||
addr = str(self.receive_address_e.text())
|
addr = str(self.receive_address_e.text())
|
||||||
amount = self.receive_amount_e.get_amount()
|
amount = self.receive_amount_e.get_amount()
|
||||||
message = unicode(self.receive_message_e.text())
|
message = unicode(self.receive_message_e.text())
|
||||||
|
@ -699,13 +700,32 @@ class ElectrumWindow(QMainWindow):
|
||||||
QMessageBox.warning(self, _('Error'), _('No message or amount'), _('OK'))
|
QMessageBox.warning(self, _('Error'), _('No message or amount'), _('OK'))
|
||||||
return
|
return
|
||||||
self.receive_requests = self.wallet.storage.get('receive_requests2',{})
|
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.storage.put('receive_requests2', self.receive_requests)
|
||||||
self.wallet.set_label(addr, message)
|
self.wallet.set_label(addr, message)
|
||||||
self.update_receive_tab()
|
self.update_receive_tab()
|
||||||
self.update_address_tab()
|
self.update_address_tab()
|
||||||
self.save_request_button.setEnabled(False)
|
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):
|
def get_receive_address(self):
|
||||||
domain = self.wallet.get_account_addresses(self.current_account, include_change=False)
|
domain = self.wallet.get_account_addresses(self.current_account, include_change=False)
|
||||||
for addr in domain:
|
for addr in domain:
|
||||||
|
@ -813,8 +833,9 @@ class ElectrumWindow(QMainWindow):
|
||||||
amount = self.receive_amount_e.get_amount()
|
amount = self.receive_amount_e.get_amount()
|
||||||
message = unicode(self.receive_message_e.text()).encode('utf8')
|
message = unicode(self.receive_message_e.text()).encode('utf8')
|
||||||
self.save_request_button.setEnabled((amount is not None) or (message != ""))
|
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():
|
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)
|
self.qr_window.set_content(addr, amount, message, uri)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 = pb2.PaymentDetails()
|
||||||
pd.outputs.add(amount=amount, script=script)
|
for script, amount in outputs:
|
||||||
now = int(time.time())
|
pd.outputs.add(amount=amount, script=script)
|
||||||
pd.time = now
|
pd.time = time
|
||||||
pd.expires = now + 15*60
|
pd.expires = expires
|
||||||
pd.memo = memo
|
pd.memo = memo
|
||||||
#pd.payment_url = 'http://payment_ack.url'
|
|
||||||
pr = pb2.PaymentRequest()
|
pr = pb2.PaymentRequest()
|
||||||
pr.serialized_payment_details = pd.SerializeToString()
|
pr.serialized_payment_details = pd.SerializeToString()
|
||||||
pr.signature = ''
|
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_type = 'x509+sha256'
|
||||||
pr.pki_data = certificates.SerializeToString()
|
pr.pki_data = certificates.SerializeToString()
|
||||||
msgBytes = bytearray(pr.SerializeToString())
|
msgBytes = bytearray(pr.SerializeToString())
|
||||||
|
|
Loading…
Reference in New Issue