diff --git a/lnbits/core/utils.py b/lnbits/core/utils.py new file mode 100644 index 00000000..b8ff96a9 --- /dev/null +++ b/lnbits/core/utils.py @@ -0,0 +1,44 @@ +from typing import Tuple + +from lnbits.bolt11 import decode as bolt11_decode +from lnbits.settings import WALLET, FEE_RESERVE + +from .crud import create_payment + + +def create_invoice(*, wallet_id: str, amount: int, memo: str) -> Tuple[str, str]: + try: + ok, checking_id, payment_request, error_message = WALLET.create_invoice(amount=amount, memo=memo) + except Exception as e: + ok, error_message = False, str(e) + + if not ok: + raise Exception(error_message or "Unexpected backend error.") + + amount_msat = amount * 1000 + create_payment(wallet_id=wallet_id, checking_id=checking_id, amount=amount_msat, memo=memo) + + return checking_id, payment_request + + +def pay_invoice(*, wallet_id: str, bolt11: str) -> str: + try: + invoice = bolt11_decode(bolt11) + ok, checking_id, fee_msat, error_message = WALLET.pay_invoice(bolt11) + + if ok: + create_payment( + wallet_id=wallet_id, + checking_id=checking_id, + amount=-invoice.amount_msat, + memo=invoice.description, + fee=-invoice.amount_msat * FEE_RESERVE, + ) + + except Exception as e: + ok, error_message = False, str(e) + + if not ok: + raise Exception(error_message or "Unexpected backend error.") + + return checking_id diff --git a/lnbits/core/views/api.py b/lnbits/core/views/api.py index d23a9e1f..2693e7ff 100644 --- a/lnbits/core/views/api.py +++ b/lnbits/core/views/api.py @@ -1,12 +1,12 @@ from flask import g, jsonify, request -from lnbits import bolt11 +from lnbits.bolt11 import decode as bolt11_decode from lnbits.core import core_app from lnbits.decorators import api_check_wallet_macaroon, api_validate_post_request from lnbits.helpers import Status -from lnbits.settings import FEE_RESERVE, WALLET +from lnbits.settings import WALLET -from ..crud import create_payment +from ..utils import create_invoice, pay_invoice @core_app.route("/api/v1/payments", methods=["GET"]) @@ -31,15 +31,11 @@ def api_payments(): ) def api_payments_create_invoice(): try: - ok, checking_id, payment_request, error_message = WALLET.create_invoice(g.data["amount"], g.data["memo"]) + checking_id, payment_request = create_invoice( + wallet_id=g.wallet.id, amount=g.data["amount"], memo=g.data["memo"] + ) except Exception as e: - ok, error_message = False, str(e) - - if not ok: - return jsonify({"message": error_message or "Unexpected backend error."}), Status.INTERNAL_SERVER_ERROR - - amount_msat = g.data["amount"] * 1000 - create_payment(wallet_id=g.wallet.id, checking_id=checking_id, amount=amount_msat, memo=g.data["memo"]) + return jsonify({"message": str(e)}), Status.INTERNAL_SERVER_ERROR return jsonify({"checking_id": checking_id, "payment_request": payment_request}), Status.CREATED @@ -48,7 +44,7 @@ def api_payments_create_invoice(): @api_validate_post_request(schema={"bolt11": {"type": "string", "empty": False, "required": True}}) def api_payments_pay_invoice(): try: - invoice = bolt11.decode(g.data["bolt11"]) + invoice = bolt11_decode(g.data["bolt11"]) if invoice.amount_msat == 0: return jsonify({"message": "Amountless invoices not supported."}), Status.BAD_REQUEST @@ -56,22 +52,10 @@ def api_payments_pay_invoice(): if invoice.amount_msat > g.wallet.balance_msat: return jsonify({"message": "Insufficient balance."}), Status.FORBIDDEN - ok, checking_id, fee_msat, error_message = WALLET.pay_invoice(g.data["bolt11"]) - - if ok: - create_payment( - wallet_id=g.wallet.id, - checking_id=checking_id, - amount=-invoice.amount_msat, - memo=invoice.description, - fee=-invoice.amount_msat * FEE_RESERVE, - ) + checking_id = pay_invoice(wallet_id=g.wallet.id, bolt11=g.data["bolt11"]) except Exception as e: - ok, error_message = False, str(e) - - if not ok: - return jsonify({"message": error_message or "Unexpected backend error."}), Status.INTERNAL_SERVER_ERROR + return jsonify({"message": str(e)}), Status.INTERNAL_SERVER_ERROR return jsonify({"checking_id": checking_id}), Status.CREATED diff --git a/lnbits/extensions/tpos/views_api.py b/lnbits/extensions/tpos/views_api.py index 5bbe9cdf..6c46acdb 100644 --- a/lnbits/extensions/tpos/views_api.py +++ b/lnbits/extensions/tpos/views_api.py @@ -1,6 +1,7 @@ from flask import g, jsonify, request from lnbits.core.crud import get_user +from lnbits.core.utils import create_invoice from lnbits.decorators import api_check_wallet_macaroon, api_validate_post_request from lnbits.helpers import Status @@ -11,7 +12,6 @@ from .crud import create_tpos, get_tpos, get_tposs, delete_tpos @tpos_ext.route("/api/v1/tposs", methods=["GET"]) @api_check_wallet_macaroon(key_type="invoice") def api_tposs(): - wallet_ids = [g.wallet.id] if "all_wallets" in request.args: @@ -35,6 +35,7 @@ def api_tpos_create(): return jsonify(tpos._asdict()), Status.CREATED + @tpos_ext.route("/api/v1/tposs/", methods=["DELETE"]) @api_check_wallet_macaroon(key_type="invoice") def api_tpos_delete(tpos_id): @@ -44,19 +45,29 @@ def api_tpos_delete(tpos_id): return jsonify({"message": "TPoS does not exist."}), Status.NOT_FOUND if tpos.wallet != g.wallet.id: - return jsonify({"message": "Not your tpos."}), Status.FORBIDDEN + return jsonify({"message": "Not your TPoS."}), Status.FORBIDDEN delete_tpos(tpos_id) return '', Status.NO_CONTENT + @tpos_ext.route("/api/v1/tposs/invoice/", methods=["POST"]) +@api_check_wallet_macaroon(key_type="invoice") @api_validate_post_request(schema={"amount": {"type": "integer", "min": 1, "required": True}}) def api_tpos_create_invoice(tpos_id): - r = get_tpos(tpos_id) - print(r) - rr = get_wallet(tpos_id.id) - print(rr) - # api_payments_create_invoice(memo=tpos_id.id, amount=amount, ) + tpos = get_tpos(tpos_id) - return jsonify(rr), Status.CREATED + if not tpos: + return jsonify({"message": "TPoS does not exist."}), Status.NOT_FOUND + + if tpos.wallet != g.wallet.id: + return jsonify({"message": "Not your TPoS."}), Status.FORBIDDEN + + try: + memo = f"TPoS {tpos_id}" + checking_id, payment_request = create_invoice(wallet_id=g.wallet.id, amount=g.data["amount"], memo=memo) + except Exception as e: + return jsonify({"message": str(e)}), Status.INTERNAL_SERVER_ERROR + + return jsonify({"checking_id": checking_id, "payment_request": payment_request}), Status.CREATED