diff --git a/lnbits/core/services.py b/lnbits/core/services.py index d3665d5..8bdb73a 100644 --- a/lnbits/core/services.py +++ b/lnbits/core/services.py @@ -11,7 +11,7 @@ except ImportError: # pragma: nocover from lnbits import bolt11 from lnbits.helpers import urlsafe_short_hash from lnbits.settings import WALLET -from lnbits.wallets.base import PaymentStatus +from lnbits.wallets.base import PaymentStatus, PaymentResponse from .crud import get_wallet, create_payment, delete_payment, check_internal, update_payment_status, get_wallet_payment @@ -110,12 +110,17 @@ def pay_invoice( update_payment_status(checking_id=internal, pending=False) else: # actually pay the external invoice - ok, checking_id, fee_msat, error_message = WALLET.pay_invoice(payment_request) - if ok: - create_payment(checking_id=checking_id, fee=fee_msat, **payment_kwargs) + payment: PaymentResponse = WALLET.pay_invoice(payment_request) + if payment.ok: + create_payment( + checking_id=payment.checking_id, + fee=payment.fee_msat, + preimage=payment.preimage, + **payment_kwargs, + ) delete_payment(temp_id) else: - raise Exception(error_message or "Failed to pay_invoice on backend.") + raise Exception(payment.error_message or "Failed to pay_invoice on backend.") g.db.commit() return invoice.payment_hash diff --git a/lnbits/static/js/components.js b/lnbits/static/js/components.js index d8048e3..3d8c554 100644 --- a/lnbits/static/js/components.js +++ b/lnbits/static/js/components.js @@ -199,6 +199,10 @@ Vue.component('lnbits-payment-details', {
Payment hash:
{{ payment.payment_hash }}
+
+
Payment proof:
+
{{ payment.preimage }}
+
` }) diff --git a/lnbits/wallets/base.py b/lnbits/wallets/base.py index d4484f3..98f9137 100644 --- a/lnbits/wallets/base.py +++ b/lnbits/wallets/base.py @@ -18,6 +18,7 @@ class PaymentResponse(NamedTuple): ok: bool checking_id: Optional[str] = None # payment_hash, rcp_id fee_msat: int = 0 + preimage: Optional[str] = None error_message: Optional[str] = None diff --git a/lnbits/wallets/clightning.py b/lnbits/wallets/clightning.py index e51455b..48d304b 100644 --- a/lnbits/wallets/clightning.py +++ b/lnbits/wallets/clightning.py @@ -73,8 +73,14 @@ class CLightningWallet(Wallet): return InvoiceResponse(False, label, None, error_message) def pay_invoice(self, bolt11: str) -> PaymentResponse: - r = self.ln.pay(bolt11) - return PaymentResponse(True, r["payment_hash"], r["msatoshi_sent"] - r["msatoshi"], None) + try: + r = self.ln.pay(bolt11) + except RpcError as exc: + return PaymentResponse(False, None, 0, None, str(exc)) + + fee_msat = r["msatoshi_sent"] - r["msatoshi"] + preimage = r["payment_preimage"] + return PaymentResponse(True, r["payment_hash"], fee_msat, preimage, None) def get_invoice_status(self, checking_id: str) -> PaymentStatus: r = self.ln.listinvoices(checking_id) diff --git a/lnbits/wallets/lndgrpc.py b/lnbits/wallets/lndgrpc.py index 6dc6721..d92b568 100644 --- a/lnbits/wallets/lndgrpc.py +++ b/lnbits/wallets/lndgrpc.py @@ -135,11 +135,13 @@ class LndWallet(Wallet): resp = self.rpc.send_payment(payment_request=bolt11) if resp.payment_error: - return PaymentResponse(False, "", 0, resp.payment_error) + return PaymentResponse(False, "", 0, None, resp.payment_error) r_hash = hashlib.sha256(resp.payment_preimage).digest() checking_id = stringify_checking_id(r_hash) - return PaymentResponse(True, checking_id, 0, None) + fee_msat = resp.payment_route.total_fees_msat + preimage = resp.payment_preimage.hex() + return PaymentResponse(True, checking_id, fee_msat, preimage, None) def get_invoice_status(self, checking_id: str) -> PaymentStatus: try: diff --git a/lnbits/wallets/lndrest.py b/lnbits/wallets/lndrest.py index 2013a33..6257dde 100644 --- a/lnbits/wallets/lndrest.py +++ b/lnbits/wallets/lndrest.py @@ -94,12 +94,13 @@ class LndRestWallet(Wallet): error_message = r.json()["error"] except: pass - return PaymentResponse(False, None, 0, error_message) + return PaymentResponse(False, None, 0, None, error_message) - payment_hash = r.json()["payment_hash"] + data = r.json() + payment_hash = data["payment_hash"] checking_id = payment_hash - - return PaymentResponse(True, checking_id, 0, None) + preimage = base64.b64decode(data["payment_preimage"]).hex() + return PaymentResponse(True, checking_id, 0, preimage, None) def get_invoice_status(self, checking_id: str) -> PaymentStatus: checking_id = checking_id.replace("_", "/") diff --git a/lnbits/wallets/lnpay.py b/lnbits/wallets/lnpay.py index 5073318..8b7daf5 100644 --- a/lnbits/wallets/lnpay.py +++ b/lnbits/wallets/lnpay.py @@ -72,12 +72,19 @@ class LNPayWallet(Wallet): headers=self.auth, json={"payment_request": bolt11}, ) - ok, checking_id, fee_msat, error_message = r.status_code == 201, None, 0, None - if ok: - checking_id = r.json()["lnTx"]["id"] + try: + data = r.json() + except: + return PaymentResponse(False, None, 0, None, f"Got invalid JSON: {r.text[:200]}") + + if r.is_error: + return PaymentResponse(False, None, 0, None, data["message"]) - return PaymentResponse(ok, checking_id, fee_msat, error_message) + checking_id = data["lnTx"]["id"] + fee_msat = 0 + preimage = data["lnTx"]["payment_preimage"] + return PaymentResponse(True, checking_id, fee_msat, preimage, None) def get_invoice_status(self, checking_id: str) -> PaymentStatus: return self.get_payment_status(checking_id) diff --git a/lnbits/wallets/lntxbot.py b/lnbits/wallets/lntxbot.py index c4ad534..eec5e02 100644 --- a/lnbits/wallets/lntxbot.py +++ b/lnbits/wallets/lntxbot.py @@ -67,10 +67,13 @@ class LntxbotWallet(Wallet): error_message = r.text pass - return PaymentResponse(False, None, 0, error_message) + return PaymentResponse(False, None, 0, None, error_message) data = r.json() - return PaymentResponse(True, data["decoded"]["payment_hash"], data["fee_msat"], None) + checking_id = data["payment_hash"] + fee_msat = data["fee_msat"] + preimage = data["payment_preimage"] + return PaymentResponse(True, checking_id, fee_msat, preimage, None) def get_invoice_status(self, checking_id: str) -> PaymentStatus: r = httpx.post(url=f"{self.endpoint}/invoicestatus/{checking_id}?wait=false", headers=self.auth) diff --git a/lnbits/wallets/opennode.py b/lnbits/wallets/opennode.py index 592adee..8b772e7 100644 --- a/lnbits/wallets/opennode.py +++ b/lnbits/wallets/opennode.py @@ -62,12 +62,12 @@ class OpenNodeWallet(Wallet): if r.is_error: error_message = r.json()["message"] - return PaymentResponse(False, None, 0, error_message) + return PaymentResponse(False, None, 0, None, error_message) data = r.json()["data"] checking_id = data["id"] fee_msat = data["fee"] * 1000 - return PaymentResponse(True, checking_id, fee_msat, None) + return PaymentResponse(True, checking_id, fee_msat, None, None) def get_invoice_status(self, checking_id: str) -> PaymentStatus: r = httpx.get(f"{self.endpoint}/v1/charge/{checking_id}", headers=self.auth) diff --git a/lnbits/wallets/spark.py b/lnbits/wallets/spark.py index ea821ec..bce53cd 100644 --- a/lnbits/wallets/spark.py +++ b/lnbits/wallets/spark.py @@ -85,11 +85,12 @@ class SparkWallet(Wallet): def pay_invoice(self, bolt11: str) -> PaymentResponse: try: r = self.pay(bolt11) - ok, checking_id, fee_msat, error_message = True, r["payment_hash"], r["msatoshi_sent"] - r["msatoshi"], None - except (SparkError, UnknownError) as e: - ok, checking_id, fee_msat, error_message = False, None, None, str(e) + except (SparkError, UnknownError) as exc: + return PaymentResponse(False, None, 0, None, str(exc)) - return PaymentResponse(ok, checking_id, fee_msat, error_message) + fee_msat = r["msatoshi_sent"] - r["msatoshi"] + preimage = r["payment_preimage"] + return PaymentResponse(True, r["payment_hash"], fee_msat, preimage, None) def get_invoice_status(self, checking_id: str) -> PaymentStatus: r = self.listinvoices(label=checking_id)