diff --git a/lnbits/__init__.py b/lnbits/__init__.py index ca6081821..463471bf7 100644 --- a/lnbits/__init__.py +++ b/lnbits/__init__.py @@ -282,7 +282,7 @@ def api_transactions(): # insert the payment db.execute( - "INSERT INTO apipayments (payhash, amount, fee, wallet, pending, memo) VALUES (?, ?, ?, ?, 1, ?)", + "INSERT OR IGNORE INTO apipayments (payhash, amount, fee, wallet, pending, memo) VALUES (?, ?, ?, ?, 1, ?)", ( invoice.payment_hash, -int(invoice.amount_msat), @@ -305,26 +305,14 @@ def api_transactions(): else: # actually send the payment r = WALLET.pay_invoice(data["payment_request"]) - print(r) - - if not r.raw_response: + + if not r.raw_response.ok or r.failed: return jsonify({"ERROR": "UNEXPECTED PAYMENT ERROR"}), 500 - data = r.raw_response.json() - - print(data) - - - if r.raw_response and "error" in data: - # payment didn't went through, delete it here - # (these guarantees specific to lntxbot) - db.execute("DELETE FROM apipayments WHERE payhash = ?", (invoice.payment_hash,)) - return jsonify({"PAID": "FALSE"}), 200 - # payment went through, not pending anymore, save actual fees db.execute( "UPDATE apipayments SET pending = 0, fee = ? WHERE payhash = ? AND wallet = ?", - (invoice.amount_msat, invoice.payment_hash, wallet["id"]), + (r.fee_msat, invoice.payment_hash, wallet["id"]), ) return jsonify({"PAID": "TRUE", "payment_hash": invoice.payment_hash}), 200 diff --git a/lnbits/wallets/base.py b/lnbits/wallets/base.py index c854589db..b708ec0e9 100644 --- a/lnbits/wallets/base.py +++ b/lnbits/wallets/base.py @@ -9,12 +9,15 @@ class InvoiceResponse(NamedTuple): payment_request: Optional[str] = None +class PaymentResponse(NamedTuple): + raw_response: Response + failed: bool = False + fee_msat: int = 0 + + class TxStatus(NamedTuple): raw_response: Response settled: Optional[bool] = None - -class PaymentResponse(NamedTuple): - raw_response: Response class Wallet(ABC): diff --git a/lnbits/wallets/lnd.py b/lnbits/wallets/lnd.py index 8f36a6cb4..9aa8099f7 100644 --- a/lnbits/wallets/lnd.py +++ b/lnbits/wallets/lnd.py @@ -1,7 +1,5 @@ -from requests import Response, get, post -from flask import jsonify -from .base import InvoiceResponse, TxStatus, Wallet, PaymentResponse -import json +from requests import get, post +from .base import InvoiceResponse, PaymentResponse, TxStatus, Wallet class LndWallet(Wallet): @@ -26,28 +24,23 @@ class LndWallet(Wallet): payment_request = data["payment_request"] rr = get(url=f"{self.endpoint}/v1/payreq/{payment_request}", headers=self.auth_read) - print(rr.json()) + if rr.ok: dataa = rr.json() payment_hash = dataa["payment_hash"] - return InvoiceResponse(r, payment_hash, payment_request) - - def pay_invoice(self, bolt11: str) -> PaymentResponse: - fee_msat = None - r = post(url=f"{self.endpoint}/v1/channels/transactions", headers=self.auth_admin, json={"payment_request": bolt11}) - return PaymentResponse(r) - - + r = post( + url=f"{self.endpoint}/v1/channels/transactions", headers=self.auth_admin, json={"payment_request": bolt11} + ) + return PaymentResponse(r, not r.ok) def get_invoice_status(self, payment_hash: str, wait: bool = True) -> TxStatus: r = get(url=f"{self.endpoint}/v1/invoice/{payment_hash}", headers=self.auth_read) - # print(payment_hash) - print(r.json()) - if not r.ok: + + if not r.ok or "settled" not in r.json(): return TxStatus(r, None) return TxStatus(r, r.json()["settled"]) @@ -64,5 +57,3 @@ class LndWallet(Wallet): # check payment.status: https://api.lightning.community/rest/index.html?python#peersynctype statuses = {"UNKNOWN": None, "IN_FLIGHT": None, "SUCCEEDED": True, "FAILED": False} return TxStatus(r, statuses[payment["status"]] if payment else None) - - diff --git a/lnbits/wallets/lntxbot.py b/lnbits/wallets/lntxbot.py index 37ce601dc..d5da1d026 100644 --- a/lnbits/wallets/lntxbot.py +++ b/lnbits/wallets/lntxbot.py @@ -1,7 +1,6 @@ -from requests import Response, get, post -from flask import jsonify -from .base import InvoiceResponse, TxStatus, Wallet, PaymentResponse -import json +from requests import post + +from .base import InvoiceResponse, PaymentResponse, TxStatus, Wallet class LntxbotWallet(Wallet): @@ -23,11 +22,17 @@ class LntxbotWallet(Wallet): return InvoiceResponse(r, payment_hash, payment_request) def pay_invoice(self, bolt11: str) -> PaymentResponse: - fee_msat = None r = post(url=f"{self.endpoint}/payinvoice", headers=self.auth_admin, json={"invoice": bolt11}) - return PaymentResponse(r) + failed, fee_msat = not r.ok, 0 + if r.ok: + data = r.json() + if "error" in data and data["error"]: + failed = True + elif "fee_msat" in data: + fee_msat = data["fee_msat"] + return PaymentResponse(r, failed, fee_msat) def get_invoice_status(self, payment_hash: str, wait: bool = True) -> TxStatus: wait = "true" if wait else "false" @@ -42,7 +47,6 @@ class LntxbotWallet(Wallet): return TxStatus(r, True) - def get_payment_status(self, payment_hash: str) -> TxStatus: r = post(url=f"{self.endpoint}/paymentstatus/{payment_hash}", headers=self.auth_invoice) data = r.json() @@ -51,5 +55,3 @@ class LntxbotWallet(Wallet): return TxStatus(r, None) return TxStatus(r, {"complete": True, "failed": False, "unknown": None}[data.get("status", "unknown")]) - - diff --git a/lnbits/wallets/opennode.py b/lnbits/wallets/opennode.py index aa02f44e1..50443e66e 100644 --- a/lnbits/wallets/opennode.py +++ b/lnbits/wallets/opennode.py @@ -1,7 +1,7 @@ -from requests import Response, get, post -from flask import jsonify -from .base import InvoiceResponse, TxStatus, Wallet, PaymentResponse -import json +from requests import get, post + +from .base import InvoiceResponse, PaymentResponse, TxStatus, Wallet + class OpenNodeWallet(Wallet): """https://api.lightning.community/rest/index.html#lnd-rest-api-reference""" @@ -20,33 +20,24 @@ class OpenNodeWallet(Wallet): ) if r.ok: data = r.json() - payment_hash, payment_request = data['data']['id'], data["data"]["lightning_invoice"]["payreq"] + payment_hash, payment_request = data["data"]["id"], data["data"]["lightning_invoice"]["payreq"] return InvoiceResponse(r, payment_hash, payment_request) def pay_invoice(self, bolt11: str) -> PaymentResponse: - - r = post(url=f"{self.endpoint}/v2/withdrawals", headers=self.auth_admin, json={"type": "ln","address": bolt11}) - - return PaymentResponse(r) - + r = post(url=f"{self.endpoint}/v2/withdrawals", headers=self.auth_admin, json={"type": "ln", "address": bolt11}) + return PaymentResponse(r, not r.ok) def get_invoice_status(self, payment_hash: str) -> TxStatus: - r = get(url=f"{self.endpoint}/v1/charge/{payment_hash}", headers=self.auth_invoice) - data = r.json() - print(data) - print(f"{self.endpoint}/v1/charge/{payment_hash} {self.auth_invoice}") if not r.ok: return TxStatus(r, None) - - + statuses = {"processing": None, "paid": True, "unpaid": False} return TxStatus(r, statuses[r.json()["data"]["status"]]) def get_payment_status(self, payment_hash: str) -> TxStatus: - r = get(url=f"{self.endpoint}/v1/withdrawal/{payment_hash}", headers=self.auth_admin) if not r.ok: @@ -54,6 +45,3 @@ class OpenNodeWallet(Wallet): statuses = {"pending": None, "confirmed": True, "error": False, "failed": False} return TxStatus(r, statuses[r.json()["data"]["status"]]) - - -