diff --git a/lnbits/core/services.py b/lnbits/core/services.py
index d3665d55b..8bdb73aca 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 d8048e3ca..3d8c55474 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 d4484f37f..98f91378c 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 e51455bf3..48d304bb6 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 6dc672183..d92b568f9 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 2013a3364..6257ddec9 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 5073318a0..8b7daf5ea 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]}")
- return PaymentResponse(ok, checking_id, fee_msat, error_message)
+ if r.is_error:
+ return PaymentResponse(False, None, 0, None, data["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 c4ad534df..eec5e028d 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 592adee14..8b772e7e4 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 ea821ec87..bce53cd41 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)