Restructure invoices and requests (WIP)
- Terminology: use 'invoices' for outgoing payments, 'requests' for incoming payments - At the GUI level, try to handle invoices in a generic way. - Display ongoing payments in send tab.
This commit is contained in:
@@ -41,6 +41,7 @@ except ImportError:
|
||||
from . import bitcoin, ecc, util, transaction, x509, rsakey
|
||||
from .util import bh2u, bfh, export_meta, import_meta, make_aiohttp_session
|
||||
from .util import PR_UNPAID, PR_EXPIRED, PR_PAID, PR_UNKNOWN, PR_INFLIGHT
|
||||
from .util import PR_TYPE_BIP70
|
||||
from .crypto import sha256
|
||||
from .bitcoin import TYPE_ADDRESS
|
||||
from .transaction import TxOutput
|
||||
@@ -270,13 +271,15 @@ class PaymentRequest:
|
||||
|
||||
def get_dict(self):
|
||||
return {
|
||||
'type': PR_TYPE_BIP70,
|
||||
'id': self.get_id(),
|
||||
'requestor': self.get_requestor(),
|
||||
'memo':self.get_memo(),
|
||||
'exp': self.get_expiration_date(),
|
||||
'message': self.get_memo(),
|
||||
'time': self.get_time(),
|
||||
'exp': self.get_expiration_date() - self.get_time(),
|
||||
'amount': self.get_amount(),
|
||||
'signature': self.get_verify_status(),
|
||||
'txid': self.tx,
|
||||
'outputs': self.get_outputs()
|
||||
'outputs': self.get_outputs(),
|
||||
'hex': self.raw.hex(),
|
||||
}
|
||||
|
||||
def get_id(self):
|
||||
@@ -475,94 +478,3 @@ def make_request(config, req):
|
||||
if key_path and cert_path:
|
||||
sign_request_with_x509(pr, key_path, cert_path)
|
||||
return pr
|
||||
|
||||
|
||||
|
||||
class InvoiceStore(Logger):
|
||||
|
||||
def __init__(self, storage):
|
||||
Logger.__init__(self)
|
||||
self.storage = storage
|
||||
self.invoices = {}
|
||||
self.paid = {}
|
||||
d = self.storage.get('invoices', {})
|
||||
self.load(d)
|
||||
|
||||
def set_paid(self, pr, txid):
|
||||
pr.tx = txid
|
||||
pr_id = pr.get_id()
|
||||
self.paid[txid] = pr_id
|
||||
if pr_id not in self.invoices:
|
||||
# in case the user had deleted it previously
|
||||
self.add(pr)
|
||||
|
||||
def load(self, d):
|
||||
for k, v in d.items():
|
||||
try:
|
||||
pr = PaymentRequest(bfh(v.get('hex')))
|
||||
pr.tx = v.get('txid')
|
||||
pr.requestor = v.get('requestor')
|
||||
self.invoices[k] = pr
|
||||
if pr.tx:
|
||||
self.paid[pr.tx] = k
|
||||
except:
|
||||
continue
|
||||
|
||||
def import_file(self, path):
|
||||
def validate(data):
|
||||
return data # TODO
|
||||
import_meta(path, validate, self.on_import)
|
||||
|
||||
def on_import(self, data):
|
||||
self.load(data)
|
||||
self.save()
|
||||
|
||||
def export_file(self, filename):
|
||||
export_meta(self.dump(), filename)
|
||||
|
||||
def dump(self):
|
||||
d = {}
|
||||
for k, pr in self.invoices.items():
|
||||
d[k] = {
|
||||
'hex': bh2u(pr.raw),
|
||||
'requestor': pr.requestor,
|
||||
'txid': pr.tx
|
||||
}
|
||||
return d
|
||||
|
||||
def save(self):
|
||||
self.storage.put('invoices', self.dump())
|
||||
|
||||
def get_status(self, key):
|
||||
pr = self.get(key)
|
||||
if pr is None:
|
||||
self.logger.info(f"get_status() can't find pr for {key}")
|
||||
return
|
||||
if pr.tx is not None:
|
||||
return PR_PAID
|
||||
if pr.has_expired():
|
||||
return PR_EXPIRED
|
||||
return PR_UNPAID
|
||||
|
||||
def add(self, pr):
|
||||
key = pr.get_id()
|
||||
self.invoices[key] = pr
|
||||
self.save()
|
||||
return key
|
||||
|
||||
def remove(self, key):
|
||||
self.invoices.pop(key)
|
||||
self.save()
|
||||
|
||||
def get(self, k):
|
||||
return self.invoices.get(k)
|
||||
|
||||
def sorted_list(self):
|
||||
# sort
|
||||
return self.invoices.values()
|
||||
|
||||
def unpaid_invoices(self):
|
||||
return [self.invoices[k] for k in
|
||||
filter(lambda x: self.get_status(x) not in (PR_PAID, None),
|
||||
self.invoices.keys())
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user