store and display signatures of own requests
This commit is contained in:
parent
affd64125c
commit
cb2bc54f96
|
@ -629,17 +629,17 @@ class ElectrumWindow(QMainWindow):
|
||||||
buttons.addWidget(self.new_request_button)
|
buttons.addWidget(self.new_request_button)
|
||||||
|
|
||||||
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')], 3)
|
self.receive_list = MyTreeWidget(self, self.receive_list_menu, [_('Date'), _('Account'), _('Address'), _('Requestor'), _('Description'), _('Amount'), _('Status')], 4)
|
||||||
self.receive_list.currentItemChanged.connect(self.receive_item_changed)
|
self.receive_list.currentItemChanged.connect(self.receive_item_changed)
|
||||||
self.receive_list.itemClicked.connect(self.receive_item_changed)
|
self.receive_list.itemClicked.connect(self.receive_item_changed)
|
||||||
self.receive_list.setSortingEnabled(True)
|
self.receive_list.setSortingEnabled(True)
|
||||||
self.receive_list.setColumnWidth(0, 180)
|
self.receive_list.setColumnWidth(0, 180)
|
||||||
self.receive_list.hideColumn(1) # the update will show it if necessary
|
self.receive_list.hideColumn(1)
|
||||||
self.receive_list.hideColumn(2) # don't show address
|
self.receive_list.hideColumn(2)
|
||||||
self.receive_list.setColumnWidth(2, 340)
|
#self.receive_list.setColumnWidth(2, 340)
|
||||||
h = self.receive_list.header()
|
h = self.receive_list.header()
|
||||||
h.setStretchLastSection(False)
|
h.setStretchLastSection(False)
|
||||||
h.setResizeMode(3, QHeaderView.Stretch)
|
h.setResizeMode(4, QHeaderView.Stretch)
|
||||||
|
|
||||||
# layout
|
# layout
|
||||||
vbox_g = QVBoxLayout()
|
vbox_g = QVBoxLayout()
|
||||||
|
@ -714,28 +714,34 @@ class ElectrumWindow(QMainWindow):
|
||||||
return False
|
return False
|
||||||
i = self.expires_combo.currentIndex()
|
i = self.expires_combo.currentIndex()
|
||||||
expiration = map(lambda x: x[1], expiration_values)[i]
|
expiration = map(lambda x: x[1], expiration_values)[i]
|
||||||
self.wallet.add_payment_request(addr, amount, message, expiration, self.config)
|
req = self.wallet.make_payment_request(addr, amount, message, expiration)
|
||||||
|
pr, requestor = self.make_bip70_request(req)
|
||||||
|
if requestor:
|
||||||
|
req['requestor'] = requestor
|
||||||
|
req['signature'] = pr.signature.encode('hex')
|
||||||
|
self.wallet.add_payment_request(req, self.config)
|
||||||
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)
|
||||||
return True
|
return pr
|
||||||
|
|
||||||
def make_payment_request(self, addr):
|
def make_bip70_request(self, req):
|
||||||
alias = str(self.config.get('alias'))
|
alias = str(self.config.get('alias'))
|
||||||
alias_privkey = None
|
alias_privkey = None
|
||||||
if alias:
|
if alias:
|
||||||
alias_info = self.contacts.resolve_openalias(alias)
|
alias_info = self.contacts.resolve_openalias(alias)
|
||||||
if alias_info:
|
if alias_info:
|
||||||
alias_addr, alias_name = alias_info
|
alias_addr, alias_name, validated = alias_info
|
||||||
if alias_addr and self.wallet.is_mine(alias_addr):
|
if alias_addr and self.wallet.is_mine(alias_addr):
|
||||||
password = self.password_dialog()
|
password = self.password_dialog(_('Please enter your password in order to sign your payment request.'))
|
||||||
|
if password:
|
||||||
alias_privkey = self.wallet.get_private_key(alias_addr, password)[0]
|
alias_privkey = self.wallet.get_private_key(alias_addr, password)[0]
|
||||||
r = self.wallet.get_payment_request(addr, self.config)
|
return paymentrequest.make_request(self.config, req, alias, alias_privkey)
|
||||||
pr = paymentrequest.make_request(self.config, r, alias, alias_privkey)
|
|
||||||
return pr
|
|
||||||
|
|
||||||
def export_payment_request(self, addr):
|
def export_payment_request(self, addr):
|
||||||
pr = self.make_payment_request(addr)
|
r = self.wallet.receive_requests.get(addr)
|
||||||
|
pr, requestor = paymentrequest.make_request(self.config, r)
|
||||||
|
pr = pr.SerializeToString()
|
||||||
name = r['id'] + '.bip70'
|
name = r['id'] + '.bip70'
|
||||||
fileName = self.getSaveFileName(_("Select where to save your payment request"), name, "*.bip70")
|
fileName = self.getSaveFileName(_("Select where to save your payment request"), name, "*.bip70")
|
||||||
if fileName:
|
if fileName:
|
||||||
|
@ -828,9 +834,13 @@ class ElectrumWindow(QMainWindow):
|
||||||
message = req.get('memo', '')
|
message = req.get('memo', '')
|
||||||
date = format_time(timestamp)
|
date = format_time(timestamp)
|
||||||
status = req.get('status')
|
status = req.get('status')
|
||||||
account = self.wallet.get_account_name(self.wallet.get_account_from_address(address))
|
signature = req.get('signature')
|
||||||
|
requestor = req.get('requestor', '')
|
||||||
amount_str = self.format_amount(amount) if amount else ""
|
amount_str = self.format_amount(amount) if amount else ""
|
||||||
item = QTreeWidgetItem([date, account, address, message, amount_str, pr_tooltips.get(status,'')])
|
account = ''
|
||||||
|
item = QTreeWidgetItem([date, account, address, requestor, message, amount_str, pr_tooltips.get(status,'')])
|
||||||
|
if signature is not None:
|
||||||
|
item.setIcon(3, QIcon(":icons/confirmed.png"))
|
||||||
if status is not PR_UNKNOWN:
|
if status is not PR_UNKNOWN:
|
||||||
item.setIcon(5, QIcon(pr_icons.get(status)))
|
item.setIcon(5, QIcon(pr_icons.get(status)))
|
||||||
self.receive_list.addTopLevelItem(item)
|
self.receive_list.addTopLevelItem(item)
|
||||||
|
|
|
@ -297,6 +297,7 @@ def make_payment_request(outputs, memo, time, expires, key_path, cert_path, alia
|
||||||
pr = pb2.PaymentRequest()
|
pr = pb2.PaymentRequest()
|
||||||
pr.serialized_payment_details = pd.SerializeToString()
|
pr.serialized_payment_details = pd.SerializeToString()
|
||||||
pr.signature = ''
|
pr.signature = ''
|
||||||
|
requestor = None
|
||||||
|
|
||||||
if alias and alias_privkey:
|
if alias and alias_privkey:
|
||||||
pr.pki_type = 'dnssec+btc'
|
pr.pki_type = 'dnssec+btc'
|
||||||
|
@ -306,6 +307,7 @@ def make_payment_request(outputs, memo, time, expires, key_path, cert_path, alia
|
||||||
address = bitcoin.address_from_private_key(alias_privkey)
|
address = bitcoin.address_from_private_key(alias_privkey)
|
||||||
compressed = bitcoin.is_compressed(alias_privkey)
|
compressed = bitcoin.is_compressed(alias_privkey)
|
||||||
pr.signature = ec_key.sign_message(message, compressed, address)
|
pr.signature = ec_key.sign_message(message, compressed, address)
|
||||||
|
requestor = alias
|
||||||
|
|
||||||
if key_path and cert_path:
|
if key_path and cert_path:
|
||||||
import tlslite
|
import tlslite
|
||||||
|
@ -322,7 +324,9 @@ def make_payment_request(outputs, memo, time, expires, key_path, cert_path, alia
|
||||||
hashBytes = bytearray(hashlib.sha256(msgBytes).digest())
|
hashBytes = bytearray(hashlib.sha256(msgBytes).digest())
|
||||||
sig = rsakey.sign(x509.PREFIX_RSA_SHA256 + hashBytes)
|
sig = rsakey.sign(x509.PREFIX_RSA_SHA256 + hashBytes)
|
||||||
pr.signature = bytes(sig)
|
pr.signature = bytes(sig)
|
||||||
return pr.SerializeToString()
|
requestor = 'x'
|
||||||
|
|
||||||
|
return pr, requestor
|
||||||
|
|
||||||
|
|
||||||
def make_request(config, req, alias=None, alias_privkey=None):
|
def make_request(config, req, alias=None, alias_privkey=None):
|
||||||
|
|
|
@ -1256,16 +1256,22 @@ class Abstract_Wallet(object):
|
||||||
status = PR_UNKNOWN
|
status = PR_UNKNOWN
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def add_payment_request(self, addr, amount, message, expiration, config):
|
def make_payment_request(self, addr, amount, message, expiration):
|
||||||
import paymentrequest, shutil, os
|
|
||||||
timestamp = int(time.time())
|
timestamp = int(time.time())
|
||||||
_id = Hash(addr + "%d"%timestamp).encode('hex')[0:10]
|
_id = Hash(addr + "%d"%timestamp).encode('hex')[0:10]
|
||||||
r = {'timestamp':timestamp, 'amount':amount, 'expiration':expiration, 'address':addr, 'memo':message, 'id':_id}
|
r = {'timestamp':timestamp, 'amount':amount, 'expiration':expiration, 'address':addr, 'memo':message, 'id':_id}
|
||||||
self.receive_requests[addr] = r
|
return r
|
||||||
|
|
||||||
|
def add_payment_request(self, req, config):
|
||||||
|
import paymentrequest, shutil, os
|
||||||
|
addr = req['address']
|
||||||
|
amount = req.get('amount')
|
||||||
|
message = req.get('memo')
|
||||||
|
self.receive_requests[addr] = req
|
||||||
self.storage.put('payment_requests', self.receive_requests)
|
self.storage.put('payment_requests', self.receive_requests)
|
||||||
self.set_label(addr, message) # should be a default label
|
self.set_label(addr, message) # should be a default label
|
||||||
|
|
||||||
rdir = config.get('requests_dir')
|
rdir = config.get('requests_dir')
|
||||||
req = self.get_payment_request(addr, config)
|
|
||||||
if rdir and amount is not None:
|
if rdir and amount is not None:
|
||||||
if not os.path.exists(rdir):
|
if not os.path.exists(rdir):
|
||||||
os.mkdir(rdir)
|
os.mkdir(rdir)
|
||||||
|
|
|
@ -146,19 +146,17 @@ class Plugin(BasePlugin):
|
||||||
def send(self):
|
def send(self):
|
||||||
addr = str(self.win.receive_address_e.text())
|
addr = str(self.win.receive_address_e.text())
|
||||||
message = unicode(self.win.receive_message_e.text())
|
message = unicode(self.win.receive_message_e.text())
|
||||||
payment_request = self.win.make_payment_request(addr)
|
payment_request = self.win.save_payment_request()
|
||||||
|
if not payment_request:
|
||||||
if not self.win.save_payment_request():
|
|
||||||
return
|
return
|
||||||
|
|
||||||
recipient, ok = QtGui.QInputDialog.getText(self.win, 'Send request', 'Send request to:')
|
recipient, ok = QtGui.QInputDialog.getText(self.win, 'Send request', 'Send request to:')
|
||||||
if not ok:
|
if not ok:
|
||||||
return
|
return
|
||||||
|
|
||||||
recipient = str(recipient)
|
recipient = str(recipient)
|
||||||
|
payload = payment_request.SerializeToString()
|
||||||
self.print_error('sending mail to', recipient)
|
self.print_error('sending mail to', recipient)
|
||||||
try:
|
try:
|
||||||
self.processor.send(recipient, message, payment_request)
|
self.processor.send(recipient, message, payload)
|
||||||
except BaseException as e:
|
except BaseException as e:
|
||||||
self.win.show_message(str(e))
|
self.win.show_message(str(e))
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue