refactor payment requests
This commit is contained in:
parent
572a463806
commit
9bd94e5062
@ -681,7 +681,7 @@ class ElectrumWindow(QMainWindow):
|
|||||||
|
|
||||||
def delete_payment_request(self, item):
|
def delete_payment_request(self, item):
|
||||||
addr = str(item.text(2))
|
addr = str(item.text(2))
|
||||||
self.wallet.remove_payment_request(addr)
|
self.wallet.remove_payment_request(addr, self.config)
|
||||||
self.update_receive_tab()
|
self.update_receive_tab()
|
||||||
self.clear_receive_tab()
|
self.clear_receive_tab()
|
||||||
|
|
||||||
@ -715,13 +715,13 @@ class ElectrumWindow(QMainWindow):
|
|||||||
return
|
return
|
||||||
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.save_payment_request(self.config, addr, amount, message, expiration)
|
self.wallet.add_payment_request(addr, amount, message, expiration, 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)
|
||||||
|
|
||||||
def export_payment_request(self, addr):
|
def export_payment_request(self, addr):
|
||||||
r = self.wallet.get_payment_request(addr)
|
r = self.wallet.get_payment_request(addr, self.config)
|
||||||
pr = paymentrequest.make_request(self.config, r)
|
pr = paymentrequest.make_request(self.config, r)
|
||||||
name = r['key'] + '.bip70'
|
name = r['key'] + '.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")
|
||||||
@ -805,7 +805,7 @@ class ElectrumWindow(QMainWindow):
|
|||||||
|
|
||||||
# clear the list and fill it again
|
# clear the list and fill it again
|
||||||
self.receive_list.clear()
|
self.receive_list.clear()
|
||||||
for req in self.wallet.get_sorted_requests():
|
for req in self.wallet.get_sorted_requests(self.config):
|
||||||
address = req['address']
|
address = req['address']
|
||||||
if address not in domain:
|
if address not in domain:
|
||||||
continue
|
continue
|
||||||
|
|||||||
@ -491,7 +491,7 @@ class Commands:
|
|||||||
if show_balance:
|
if show_balance:
|
||||||
item += ", "+ format_satoshis(sum(self.wallet.get_addr_balance(addr)))
|
item += ", "+ format_satoshis(sum(self.wallet.get_addr_balance(addr)))
|
||||||
if show_labels:
|
if show_labels:
|
||||||
item += ', ' + self.wallet.labels.get(addr,'')
|
item += ', ' + repr(self.wallet.labels.get(addr, ''))
|
||||||
out.append(item)
|
out.append(item)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
@ -517,7 +517,7 @@ class Commands:
|
|||||||
"""Decrypt a message encrypted with a public key."""
|
"""Decrypt a message encrypted with a public key."""
|
||||||
return self.wallet.decrypt_message(pubkey, encrypted, self.password)
|
return self.wallet.decrypt_message(pubkey, encrypted, self.password)
|
||||||
|
|
||||||
def _format_request(self, v):
|
def _format_request(self, out):
|
||||||
from paymentrequest import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED
|
from paymentrequest import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED
|
||||||
pr_str = {
|
pr_str = {
|
||||||
PR_UNKNOWN: 'Unknown',
|
PR_UNKNOWN: 'Unknown',
|
||||||
@ -525,40 +525,14 @@ class Commands:
|
|||||||
PR_PAID: 'Paid',
|
PR_PAID: 'Paid',
|
||||||
PR_EXPIRED: 'Expired',
|
PR_EXPIRED: 'Expired',
|
||||||
}
|
}
|
||||||
key = v['key']
|
out['amount'] = format_satoshis(out.get('amount'))
|
||||||
addr = v.get('address')
|
out['status'] = pr_str[out.get('status', PR_UNKNOWN)]
|
||||||
amount = v.get('amount')
|
|
||||||
timestamp = v.get('time')
|
|
||||||
expiration = v.get('expiration')
|
|
||||||
out = {
|
|
||||||
'key': key,
|
|
||||||
'address': addr,
|
|
||||||
'amount': format_satoshis(amount),
|
|
||||||
'timestamp': timestamp,
|
|
||||||
'memo': v.get('memo', ''),
|
|
||||||
'expiration': expiration,
|
|
||||||
'URI':'bitcoin:' + addr + '?amount=' + format_satoshis(amount),
|
|
||||||
'status': pr_str[v.get('status', PR_UNKNOWN)]
|
|
||||||
}
|
|
||||||
# check if bip70 file exists
|
|
||||||
rdir = self.config.get('requests_dir')
|
|
||||||
path = os.path.join(rdir, key + '.bip70')
|
|
||||||
if rdir and os.path.exists(path):
|
|
||||||
out['path'] = path
|
|
||||||
baseurl = 'file://' + rdir
|
|
||||||
rewrite = self.config.get('url_rewrite')
|
|
||||||
if rewrite:
|
|
||||||
baseurl = baseurl.replace(*rewrite)
|
|
||||||
out['request_url'] = os.path.join(baseurl, key + '.bip70')
|
|
||||||
out['URI'] += '&r=' + out['request_url']
|
|
||||||
out['index_url'] = os.path.join(baseurl, 'index.html') + '?id=' + key
|
|
||||||
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
@command('wn')
|
@command('wn')
|
||||||
def getrequest(self, key):
|
def getrequest(self, key):
|
||||||
"""Return a payment request"""
|
"""Return a payment request"""
|
||||||
r = self.wallet.get_payment_request(key)
|
r = self.wallet.get_payment_request(key, self.config)
|
||||||
if not r:
|
if not r:
|
||||||
raise BaseException("Request not found")
|
raise BaseException("Request not found")
|
||||||
return self._format_request(r)
|
return self._format_request(r)
|
||||||
@ -571,30 +545,22 @@ class Commands:
|
|||||||
@command('w')
|
@command('w')
|
||||||
def listrequests(self):
|
def listrequests(self):
|
||||||
"""List the payment requests you made, and their status"""
|
"""List the payment requests you made, and their status"""
|
||||||
return map(self._format_request, self.wallet.get_sorted_requests())
|
return map(self._format_request, self.wallet.get_sorted_requests(self.config))
|
||||||
|
|
||||||
@command('w')
|
@command('w')
|
||||||
def addrequest(self, requested_amount, memo='', expiration=60*60):
|
def addrequest(self, requested_amount, memo='', expiration=60*60):
|
||||||
"""Create a payment request."""
|
"""Create a payment request."""
|
||||||
|
addr = self.wallet.get_unused_address(None)
|
||||||
|
if addr is None:
|
||||||
|
return False
|
||||||
amount = int(Decimal(requested_amount)*COIN)
|
amount = int(Decimal(requested_amount)*COIN)
|
||||||
key = self.wallet.add_payment_request(amount, memo, expiration)
|
req = self.wallet.add_payment_request(addr, amount, memo, expiration, self.config)
|
||||||
if key is None:
|
return self._format_request(req)
|
||||||
return
|
|
||||||
req = self.wallet.get_payment_request(key)
|
|
||||||
rdir = self.config.get('requests_dir')
|
|
||||||
if rdir:
|
|
||||||
path = paymentrequest.publish_request(self.config, key, req)
|
|
||||||
req['path'] = path
|
|
||||||
req = self._format_request(req)
|
|
||||||
if rdir:
|
|
||||||
with open(os.path.join(rdir, key + '.json'), 'w') as f:
|
|
||||||
f.write(json.dumps(req))
|
|
||||||
return req
|
|
||||||
|
|
||||||
@command('w')
|
@command('w')
|
||||||
def rmrequest(self, address):
|
def rmrequest(self, key):
|
||||||
"""Remove a payment request"""
|
"""Remove a payment request"""
|
||||||
return self.wallet.remove_payment_request(address)
|
return self.wallet.remove_payment_request(key, self.config)
|
||||||
|
|
||||||
param_descriptions = {
|
param_descriptions = {
|
||||||
'privkey': 'Private key. Type \'?\' to get a prompt.',
|
'privkey': 'Private key. Type \'?\' to get a prompt.',
|
||||||
|
|||||||
@ -299,7 +299,7 @@ def make_request(config, req):
|
|||||||
time = req['time']
|
time = req['time']
|
||||||
amount = req['amount']
|
amount = req['amount']
|
||||||
expiration = req['expiration']
|
expiration = req['expiration']
|
||||||
message = req['reason']
|
message = req['memo']
|
||||||
script = Transaction.pay_script('address', addr).decode('hex')
|
script = Transaction.pay_script('address', addr).decode('hex')
|
||||||
outputs = [(script, amount)]
|
outputs = [(script, amount)]
|
||||||
key_path = config.get('ssl_privkey')
|
key_path = config.get('ssl_privkey')
|
||||||
@ -307,7 +307,7 @@ def make_request(config, req):
|
|||||||
return make_payment_request(outputs, message, time, time + expiration if expiration else None, key_path, cert_path)
|
return make_payment_request(outputs, message, time, time + expiration if expiration else None, key_path, cert_path)
|
||||||
|
|
||||||
|
|
||||||
def publish_request(config, key, req):
|
def publish_request(config, addr, req):
|
||||||
import shutil, os
|
import shutil, os
|
||||||
rdir = config.get('requests_dir')
|
rdir = config.get('requests_dir')
|
||||||
if not rdir:
|
if not rdir:
|
||||||
@ -316,13 +316,17 @@ def publish_request(config, key, req):
|
|||||||
os.mkdir(rdir)
|
os.mkdir(rdir)
|
||||||
index = os.path.join(rdir, 'index.html')
|
index = os.path.join(rdir, 'index.html')
|
||||||
if not os.path.exists(index):
|
if not os.path.exists(index):
|
||||||
src = os.path.join(os.path.dirname(__file__), 'payrequest.html')
|
src = os.path.join(os.path.dirname(__file__), 'www', 'index.html')
|
||||||
shutil.copy(src, index)
|
shutil.copy(src, index)
|
||||||
|
key = req.get('id', addr)
|
||||||
pr = make_request(config, req)
|
pr = make_request(config, req)
|
||||||
path = os.path.join(rdir, key + '.bip70')
|
path = os.path.join(rdir, key + '.bip70')
|
||||||
with open(path, 'w') as f:
|
with open(path, 'w') as f:
|
||||||
f.write(pr)
|
f.write(pr)
|
||||||
return path
|
with open(os.path.join(rdir, key + '.json'), 'w') as f:
|
||||||
|
f.write(json.dumps(req))
|
||||||
|
req['path'] = path
|
||||||
|
return req
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1231,14 +1231,27 @@ class Abstract_Wallet(object):
|
|||||||
if not self.history.get(addr) and addr not in self.receive_requests.keys():
|
if not self.history.get(addr) and addr not in self.receive_requests.keys():
|
||||||
return addr
|
return addr
|
||||||
|
|
||||||
def get_payment_request(self, key):
|
def get_payment_request(self, addr, config):
|
||||||
r = self.receive_requests.get(key)
|
import util
|
||||||
|
r = self.receive_requests.get(addr)
|
||||||
if not r:
|
if not r:
|
||||||
return
|
return
|
||||||
r['reason'] = self.labels.get(key, '')
|
out = copy.copy(r)
|
||||||
r['status'] = self.get_request_status(key)
|
out['URI'] = 'bitcoin:' + addr + '?amount=' + util.format_satoshis(out.get('amount'))
|
||||||
r['key'] = key
|
out['status'] = self.get_request_status(addr)
|
||||||
return r
|
# check if bip70 file exists
|
||||||
|
rdir = config.get('requests_dir')
|
||||||
|
key = out.get('id', addr)
|
||||||
|
path = os.path.join(rdir, key + '.bip70')
|
||||||
|
if rdir and os.path.exists(path):
|
||||||
|
baseurl = 'file://' + rdir
|
||||||
|
rewrite = config.get('url_rewrite')
|
||||||
|
if rewrite:
|
||||||
|
baseurl = baseurl.replace(*rewrite)
|
||||||
|
out['request_url'] = os.path.join(baseurl, key + '.bip70')
|
||||||
|
out['URI'] += '&r=' + out['request_url']
|
||||||
|
out['index_url'] = os.path.join(baseurl, 'index.html') + '?id=' + key
|
||||||
|
return out
|
||||||
|
|
||||||
def get_request_status(self, key):
|
def get_request_status(self, key):
|
||||||
from paymentrequest import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED
|
from paymentrequest import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED
|
||||||
@ -1256,29 +1269,34 @@ class Abstract_Wallet(object):
|
|||||||
status = PR_UNKNOWN
|
status = PR_UNKNOWN
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def save_payment_request(self, addr, amount, message, expiration):
|
def add_payment_request(self, addr, amount, message, expiration, config):
|
||||||
self.set_label(addr, message)
|
import paymentrequest
|
||||||
now = int(time.time())
|
timestamp = int(time.time())
|
||||||
r = {'time':now, 'amount':amount, 'expiration':expiration, 'address':addr}
|
_id = Hash(addr + "%d"%timestamp).encode('hex')[0:10]
|
||||||
|
r = {'time':timestamp, 'amount':amount, 'expiration':expiration, 'address':addr, 'memo':message, 'id':_id}
|
||||||
self.receive_requests[addr] = r
|
self.receive_requests[addr] = r
|
||||||
|
self.set_label(addr, message) # should be a default label
|
||||||
|
if config.get('requests_dir'):
|
||||||
|
paymentrequest.publish_request(config, addr, r)
|
||||||
self.storage.put('receive_requests2', self.receive_requests)
|
self.storage.put('receive_requests2', self.receive_requests)
|
||||||
|
return self.get_payment_request(addr, config)
|
||||||
|
|
||||||
def add_payment_request(self, amount, message, expiration):
|
def remove_payment_request(self, addr, config):
|
||||||
addr = self.get_unused_address(None)
|
|
||||||
if addr is None:
|
|
||||||
return
|
|
||||||
self.save_payment_request(addr, amount, message, expiration)
|
|
||||||
return addr
|
|
||||||
|
|
||||||
def remove_payment_request(self, addr):
|
|
||||||
if addr not in self.receive_requests:
|
if addr not in self.receive_requests:
|
||||||
return False
|
return False
|
||||||
self.receive_requests.pop(addr)
|
r = self.receive_requests.pop(addr)
|
||||||
|
rdir = config.get('requests_dir')
|
||||||
|
if rdir:
|
||||||
|
key = r.get('id', addr)
|
||||||
|
for s in ['.json', '.bip70']:
|
||||||
|
n = os.path.join(rdir, key + s)
|
||||||
|
if os.path.exists(n):
|
||||||
|
os.unlink(n)
|
||||||
self.storage.put('receive_requests2', self.receive_requests)
|
self.storage.put('receive_requests2', self.receive_requests)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_sorted_requests(self):
|
def get_sorted_requests(self, config):
|
||||||
return sorted(map(self.get_payment_request, self.receive_requests.keys()), key=itemgetter('time'))
|
return sorted(map(lambda x: self.get_payment_request(x, config), self.receive_requests.keys()), key=itemgetter('time'))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user