From 6646fce549fe0123bd1fbf0e6adb8ea9e3676b8a Mon Sep 17 00:00:00 2001
From: calle <93376500+callebtc@users.noreply.github.com>
Date: Sun, 17 Jul 2022 14:34:25 +0200
Subject: [PATCH] Core: add internal flag for invoice creation to use
FakeWallet (#646)
* add internal flag for invoice creation to use FakeWallet
---
lnbits/core/services.py | 10 ++++---
lnbits/core/templates/core/_api_docs.html | 3 ++-
lnbits/core/views/api.py | 2 ++
lnbits/settings.py | 1 +
lnbits/wallets/fake.py | 8 +++++-
tests/core/views/test_api.py | 33 ++++++++++++++++++-----
6 files changed, 45 insertions(+), 12 deletions(-)
diff --git a/lnbits/core/services.py b/lnbits/core/services.py
index 84bc98e3b..da0e5a446 100644
--- a/lnbits/core/services.py
+++ b/lnbits/core/services.py
@@ -14,7 +14,7 @@ from lnbits import bolt11
from lnbits.db import Connection
from lnbits.helpers import url_for, urlsafe_short_hash
from lnbits.requestvars import g
-from lnbits.settings import WALLET
+from lnbits.settings import FAKE_WALLET, WALLET
from lnbits.wallets.base import PaymentResponse, PaymentStatus
from . import db
@@ -49,15 +49,19 @@ async def create_invoice(
description_hash: Optional[bytes] = None,
extra: Optional[Dict] = None,
webhook: Optional[str] = None,
+ internal: Optional[bool] = False,
conn: Optional[Connection] = None,
) -> Tuple[str, str]:
invoice_memo = None if description_hash else memo
- ok, checking_id, payment_request, error_message = await WALLET.create_invoice(
+ # use the fake wallet if the invoice is for internal use only
+ wallet = FAKE_WALLET if internal else WALLET
+
+ ok, checking_id, payment_request, error_message = await wallet.create_invoice(
amount=amount, memo=invoice_memo, description_hash=description_hash
)
if not ok:
- raise InvoiceFailure(error_message or "Unexpected backend error.")
+ raise InvoiceFailure(error_message or "unexpected backend error.")
invoice = bolt11.decode(payment_request)
diff --git a/lnbits/core/templates/core/_api_docs.html b/lnbits/core/templates/core/_api_docs.html
index 271568d44..383f2b121 100644
--- a/lnbits/core/templates/core/_api_docs.html
+++ b/lnbits/core/templates/core/_api_docs.html
@@ -49,7 +49,8 @@
Body (application/json)
{"out": false, "amount": <int>, "memo": <string>, "unit":
- <string>, "webhook": <url:string>}
Returns 201 CREATED (application/json)
diff --git a/lnbits/core/views/api.py b/lnbits/core/views/api.py
index f5b580414..198b00098 100644
--- a/lnbits/core/views/api.py
+++ b/lnbits/core/views/api.py
@@ -147,6 +147,7 @@ class CreateInvoiceData(BaseModel):
lnurl_balance_check: Optional[str] = None
extra: Optional[dict] = None
webhook: Optional[str] = None
+ internal: Optional[bool] = False
bolt11: Optional[str] = None
@@ -173,6 +174,7 @@ async def api_payments_create_invoice(data: CreateInvoiceData, wallet: Wallet):
description_hash=description_hash,
extra=data.extra,
webhook=data.webhook,
+ internal=data.internal,
conn=conn,
)
except InvoiceFailure as e:
diff --git a/lnbits/settings.py b/lnbits/settings.py
index efa0b8d50..5778b9e23 100644
--- a/lnbits/settings.py
+++ b/lnbits/settings.py
@@ -51,6 +51,7 @@ LNBITS_THEME_OPTIONS: List[str] = env.list(
LNBITS_CUSTOM_LOGO = env.str("LNBITS_CUSTOM_LOGO", default="")
WALLET = wallet_class()
+FAKE_WALLET = getattr(wallets_module, "FakeWallet")()
DEFAULT_WALLET_NAME = env.str("LNBITS_DEFAULT_WALLET_NAME", default="LNbits wallet")
PREFER_SECURE_URLS = env.bool("LNBITS_FORCE_HTTPS", default=True)
diff --git a/lnbits/wallets/fake.py b/lnbits/wallets/fake.py
index ff64bd613..9dd5556bd 100644
--- a/lnbits/wallets/fake.py
+++ b/lnbits/wallets/fake.py
@@ -5,6 +5,7 @@ from datetime import datetime
from os import getenv
from typing import AsyncGenerator, Dict, Optional
+from environs import Env # type: ignore
from loguru import logger
from lnbits.helpers import urlsafe_short_hash
@@ -18,6 +19,9 @@ from .base import (
Wallet,
)
+env = Env()
+env.read_env()
+
class FakeWallet(Wallet):
async def status(self) -> StatusResponse:
@@ -32,7 +36,9 @@ class FakeWallet(Wallet):
memo: Optional[str] = None,
description_hash: Optional[bytes] = None,
) -> InvoiceResponse:
- secret = getenv("FAKE_WALLET_SECRET")
+ # we set a default secret since FakeWallet is used for internal=True invoices
+ # and the user might not have configured a secret yet
+ secret = env.str("FAKE_WALLET_SECTRET", default="ToTheMoon1")
data: Dict = {
"out": False,
"amount": amount,
diff --git a/tests/core/views/test_api.py b/tests/core/views/test_api.py
index 726709022..10e659aa4 100644
--- a/tests/core/views/test_api.py
+++ b/tests/core/views/test_api.py
@@ -25,13 +25,32 @@ async def test_create_invoice(client, inkey_headers_to):
response = await client.post(
"/api/v1/payments", json=data, headers=inkey_headers_to
)
- assert response.status_code < 300
- assert "payment_hash" in response.json()
- assert len(response.json()["payment_hash"]) == 64
- assert "payment_request" in response.json()
- assert "checking_id" in response.json()
- assert len(response.json()["checking_id"])
- return response.json()
+ assert response.status_code == 201
+ invoice = response.json()
+ assert "payment_hash" in invoice
+ assert len(invoice["payment_hash"]) == 64
+ assert "payment_request" in invoice
+ assert "checking_id" in invoice
+ assert len(invoice["checking_id"])
+ return invoice
+
+
+# check POST /api/v1/payments: invoice creation for internal payments only
+@pytest.mark.asyncio
+async def test_create_internal_invoice(client, inkey_headers_to):
+ data = await get_random_invoice_data()
+ data["internal"] = True
+ response = await client.post(
+ "/api/v1/payments", json=data, headers=inkey_headers_to
+ )
+ invoice = response.json()
+ assert response.status_code == 201
+ assert "payment_hash" in invoice
+ assert len(invoice["payment_hash"]) == 64
+ assert "payment_request" in invoice
+ assert "checking_id" in invoice
+ assert len(invoice["checking_id"])
+ return invoice
# check POST /api/v1/payments: make payment