URI: 
       timprove requests - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 48e53498dbb94e5e1868d2c790bd5ea8cf09b284
   DIR parent fbc68d94d666b4a214f3f8abf298a42aed44851b
  HTML Author: ThomasV <thomasv@gitorious>
       Date:   Sun,  7 Jun 2015 18:44:33 +0200
       
       improve requests
       
       Diffstat:
         M gui/qt/main_window.py               |      18 ++++++++++--------
         M lib/commands.py                     |      71 +++++++++++++++++++++----------
         M lib/paymentrequest.py               |      34 +++++++++++++++++++++++++++++--
         M lib/wallet.py                       |      50 +++++++++++++------------------
       
       4 files changed, 112 insertions(+), 61 deletions(-)
       ---
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -41,6 +41,7 @@ from electrum import mnemonic
        from electrum import util, bitcoin, commands, Wallet
        from electrum import SimpleConfig, Wallet, WalletStorage
        from electrum import Imported_Wallet
       +from electrum import paymentrequest
        
        from amountedit import AmountEdit, BTCAmountEdit, MyLineEdit
        from network_dialog import NetworkDialog
       t@@ -721,8 +722,8 @@ class ElectrumWindow(QMainWindow):
        
            def export_payment_request(self, addr):
                r = self.wallet.get_payment_request(addr)
       -        pr = self.wallet.make_bip70_request(self.config, r)
       -        name = 'request.bip70'
       +        pr = paymentrequest.make_request(self.config, r)
       +        name = r['key'] + '.bip70'
                fileName = self.getSaveFileName(_("Select where to save your payment request"), name, "*.bip70")
                if fileName:
                    with open(fileName, "wb+") as f:
       t@@ -804,17 +805,18 @@ class ElectrumWindow(QMainWindow):
        
                # clear the list and fill it again
                self.receive_list.clear()
       -        for address, req in self.wallet.receive_requests.viewitems():
       -            timestamp, amount = req['time'], req['amount']
       -            expiration = req.get('expiration', None)
       -            message = self.wallet.labels.get(address, '')
       -            # only show requests for the current account
       +        for req in self.wallet.get_sorted_requests():
       +            address = req['address']
                    if address not in domain:
                        continue
       +            timestamp = req['time']
       +            amount = req.get('amount')
       +            expiration = req.get('expiration', None)
       +            message = req.get('reason', '')
                    date = format_time(timestamp)
       +            status = req.get('status')
                    account = self.wallet.get_account_name(self.wallet.get_account_from_address(address))
                    amount_str = self.format_amount(amount) if amount else ""
       -            status = self.wallet.get_request_status(address, amount, timestamp, expiration)
                    item = QTreeWidgetItem([date, account, address, message, amount_str, pr_tooltips.get(status,'')])
                    if status is not PR_UNKNOWN:
                        item.setIcon(5, QIcon(pr_icons.get(status)))
   DIR diff --git a/lib/commands.py b/lib/commands.py
       t@@ -16,6 +16,7 @@
        # You should have received a copy of the GNU General Public License
        # along with this program. If not, see <http://www.gnu.org/licenses/>.
        
       +import os
        import sys
        import datetime
        import time
       t@@ -31,7 +32,7 @@ from util import print_msg, format_satoshis, print_stderr
        import bitcoin
        from bitcoin import is_address, hash_160_to_bc_address, hash_160, COIN
        from transaction import Transaction
       -
       +import paymentrequest
        
        known_commands = {}
        
       t@@ -516,7 +517,7 @@ class Commands:
                """Decrypt a message encrypted with a public key."""
                return self.wallet.decrypt_message(pubkey, encrypted, self.password)
        
       -    def _format_request(self, v, show_status=False):
       +    def _format_request(self, v):
                from paymentrequest import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED
                pr_str = {
                    PR_UNKNOWN: 'Unknown',
       t@@ -524,42 +525,66 @@ class Commands:
                    PR_PAID: 'Paid',
                    PR_EXPIRED: 'Expired',
                }
       +        key = v['key']
                addr = v.get('address')
                amount = v.get('amount')
                timestamp = v.get('time')
                expiration = v.get('expiration')
                out = {
       +            'key': key,
                    'address': addr,
                    'amount': format_satoshis(amount),
       -            'time': timestamp,
       -            'reason': self.wallet.get_label(addr)[0],
       +            'timestamp': timestamp,
       +            'reason': v.get('reason'),
                    'expiration': expiration,
       +            'URI':'bitcoin:' + addr + '?amount=' + format_satoshis(amount),
       +            'status': pr_str[v.get('status', PR_UNKNOWN)]
                }
       -        if v.get('path'):
       -            url = 'file://' + v.get('path')
       -            r = self.config.get('url_rewrite')
       -            if r:
       -                a, b = r
       -                url = url.replace(a, b)
       -            URI = 'bitcoin:?r=' + url
       -            out['URI'] = URI
       -        if show_status:
       -            status = self.wallet.get_request_status(addr, amount, timestamp, expiration)
       -            out['status'] = pr_str[status]
       +        # check if bip70 file exists
       +        rdir = self.config.get('requests_dir')
       +        if rdir:
       +            path = os.path.join(rdir, key + '.bip70')
       +            if os.path.exists(path):
       +                out['path'] = path
       +                url = 'file://' + path
       +                r = self.config.get('url_rewrite')
       +                if r:
       +                    a, b = r
       +                    url = url.replace(a, b)
       +                out['request_url'] = url
       +                out['URI'] += '&r=' + url
       +
                return out
        
       +    @command('wn')
       +    def getrequest(self, key):
       +        """Return a payment request"""
       +        r = self.wallet.get_payment_request(key)
       +        if not r:
       +            raise BaseException("Request not found")
       +        return self._format_request(r)
       +
            @command('w')
       -    def listrequests(self, status=False):
       +    def ackrequest(self, serialized):
       +        """<Not implemented>"""
       +        pass
       +
       +    @command('w')
       +    def listrequests(self):
                """List the payment requests you made, and their status"""
       -        return map(lambda x: self._format_request(x, status), self.wallet.receive_requests.values())
       +        return map(self._format_request, self.wallet.get_sorted_requests())
        
            @command('w')
       -    def addrequest(self, requested_amount, reason='', expiration=60*60):
       -        """Create a payment request.
       -        """
       +    def addrequest(self, requested_amount, reason='', expiration=None):
       +        """Create a payment request."""
                amount = int(Decimal(requested_amount)*COIN)
       -        key = self.wallet.add_payment_request(self.config, amount, reason, expiration)
       -        return self._format_request(self.wallet.get_payment_request(key)) if key else False
       +        key = self.wallet.add_payment_request(amount, reason, expiration)
       +        if key is None:
       +            return
       +        # create file
       +        req = self.wallet.get_payment_request(key)
       +        paymentrequest.publish_request(self.config, key, req)
       +        return self._format_request(req)
        
            @command('w')
            def rmrequest(self, address):
       t@@ -659,6 +684,8 @@ def set_default_subparser(self, name, args=None):
        
        argparse.ArgumentParser.set_default_subparser = set_default_subparser
        
       +
       +
        def add_network_options(parser):
            parser.add_argument("-1", "--oneserver", action="store_true", dest="oneserver", default=False, help="connect to one server only")
            parser.add_argument("-s", "--server", dest="server", default=None, help="set server host:port:protocol, where protocol is either t (tcp) or s (ssl)")
   DIR diff --git a/lib/paymentrequest.py b/lib/paymentrequest.py
       t@@ -262,13 +262,12 @@ class PaymentRequest:
        
        
        
       -
        def make_payment_request(outputs, memo, time, expires, key_path, cert_path):
            pd = pb2.PaymentDetails()
            for script, amount in outputs:
                pd.outputs.add(amount=amount, script=script)
            pd.time = time
       -    pd.expires = expires
       +    pd.expires = expires if expires else 0
            pd.memo = memo
            pr = pb2.PaymentRequest()
            pr.serialized_payment_details = pd.SerializeToString()
       t@@ -294,6 +293,37 @@ def make_payment_request(outputs, memo, time, expires, key_path, cert_path):
            return pr.SerializeToString()
        
        
       +def make_request(config, req):
       +    from transaction import Transaction
       +    addr = req['address']
       +    time = req['time']
       +    amount = req['amount']
       +    expiration = req['expiration']
       +    message = req['reason']
       +    script = Transaction.pay_script('address', addr).decode('hex')
       +    outputs = [(script, amount)]
       +    key_path = config.get('ssl_privkey')
       +    cert_path = config.get('ssl_chain')
       +    return make_payment_request(outputs, message, time, time + expiration if expiration else None, key_path, cert_path)
       +
       +
       +def publish_request(config, key, req):
       +    import shutil, os
       +    rdir = config.get('requests_dir')
       +    if not rdir:
       +        return
       +    if not os.path.exists(rdir):
       +        os.mkdir(rdir)
       +    index = os.path.join(rdir, 'index.html')
       +    if not os.path.exists(index):
       +        src = os.path.join(os.path.dirname(__file__), 'payrequest.html')
       +        shutil.copy(src, index)
       +    pr = make_request(config, req)
       +    path = os.path.join(rdir, key + '.bip70')
       +    with open(path, 'w') as f:
       +        f.write(pr)
       +    return path
       +
        
        
        class InvoiceStore(object):
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -1231,25 +1231,22 @@ class Abstract_Wallet(object):
                    if not self.history.get(addr) and addr not in self.receive_requests.keys():
                        return addr
        
       -
       -    def make_bip70_request(self, config, req):
       -        from paymentrequest import make_payment_request
       -        addr = req['address']
       -        time = req['time']
       -        amount = req['amount']
       -        expiration = req['expiration']
       -        message = self.labels.get(addr, '')
       -        script = Transaction.pay_script('address', addr).decode('hex')
       -        outputs = [(script, amount)]
       -        key_path = config.get('ssl_privkey')
       -        cert_path = config.get('ssl_chain')
       -        return make_payment_request(outputs, message, time, time + expiration, key_path, cert_path)
       -
            def get_payment_request(self, key):
       -        return self.receive_requests.get(key)
       +        r = self.receive_requests.get(key)
       +        if not r:
       +            return
       +        r['reason'] = self.labels.get(key, '')
       +        r['status'] = self.get_request_status(key)
       +        r['key'] = key
       +        return r
        
       -    def get_request_status(self, address, amount, timestamp, expiration):
       +    def get_request_status(self, key):
                from paymentrequest import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED
       +        r = self.receive_requests[key]
       +        address = r['address']
       +        amount = r.get('amount')
       +        timestamp = r.get('time')
       +        expiration = r.get('expiration')
                if amount:
                    paid = amount <= self.get_addr_received(address)
                    status = PR_PAID if paid else PR_UNPAID
       t@@ -1259,27 +1256,18 @@ class Abstract_Wallet(object):
                    status = PR_UNKNOWN
                return status
        
       -    def save_payment_request(self, config, addr, amount, message, expiration):
       -        #if addr in self.receive_requests:
       -        #    self.receive_requests[addr]['amount'] = amount
       +    def save_payment_request(self, addr, amount, message, expiration):
                self.set_label(addr, message)
                now = int(time.time())
                r = {'time':now, 'amount':amount, 'expiration':expiration, 'address':addr}
       -        rdir = config.get('requests_dir')
       -        if rdir:
       -            pr = self.make_bip70_request(config, r)
       -            path = os.path.join(rdir, addr + '.bip70')
       -            with open(path, 'w') as f:
       -                f.write(pr)
       -            r['path'] = path
                self.receive_requests[addr] = r
                self.storage.put('receive_requests2', self.receive_requests)
        
       -    def add_payment_request(self, config, amount, message, expiration):
       +    def add_payment_request(self, amount, message, expiration):
                addr = self.get_unused_address(None)
                if addr is None:
       -            return False
       -        self.save_payment_request(config, addr, amount, message, expiration)
       +            return
       +        self.save_payment_request(addr, amount, message, expiration)
                return addr
        
            def remove_payment_request(self, addr):
       t@@ -1289,6 +1277,10 @@ class Abstract_Wallet(object):
                self.storage.put('receive_requests2', self.receive_requests)
                return True
        
       +    def get_sorted_requests(self):
       +        return sorted(map(self.get_payment_request, self.receive_requests.keys()), key=itemgetter('time'))
       +
       +
        
        class Imported_Wallet(Abstract_Wallet):
            wallet_type = 'imported'