Browse Source

refactor payment requests

283
ThomasV 10 years ago
parent
commit
9bd94e5062
  1. 8
      gui/qt/main_window.py
  2. 60
      lib/commands.py
  3. 12
      lib/paymentrequest.py
  4. 60
      lib/wallet.py
  5. 0
      lib/www/index.html

8
gui/qt/main_window.py

@ -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

60
lib/commands.py

@ -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.',

12
lib/paymentrequest.py

@ -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

60
lib/wallet.py

@ -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'))

0
lib/payrequest.html → lib/www/index.html

Loading…
Cancel
Save