feat: switch from Quart to FastAPI part I

This commit is contained in:
Stefan Stammberger
2021-08-22 20:07:24 +02:00
parent fc68e0a6da
commit 938fc54af3
12 changed files with 245 additions and 114 deletions
+12 -15
View File
@@ -1,22 +1,19 @@
from quart import Blueprint
from fastapi.routing import APIRouter
from lnbits.db import Database
db = Database("database")
core_app: Blueprint = Blueprint(
"core",
__name__,
template_folder="templates",
static_folder="static",
static_url_path="/core/static",
)
from .views.api import * # noqa
from .views.generic import * # noqa
from .views.public_api import * # noqa
from .tasks import register_listeners
core_app: APIRouter = APIRouter()
from lnbits.tasks import record_async
core_app.record(record_async(register_listeners))
from .tasks import register_listeners
from .views.api import * # noqa
from .views.generic import * # noqa
from .views.public_api import * # noqa
@core_app.on_event("startup")
def do_startup():
record_async(register_listeners)
+26 -20
View File
@@ -1,10 +1,12 @@
from fastapi.param_functions import Depends
from lnbits.auth_bearer import AuthBearer
from pydantic import BaseModel
import trio
import json
import httpx
import hashlib
from urllib.parse import urlparse, urlunparse, urlencode, parse_qs, ParseResult
from quart import g, current_app, make_response, url_for
from quart import current_app, make_response, url_for
from fastapi import Query
@@ -15,6 +17,7 @@ from typing import Dict, List, Optional, Union
from lnbits import bolt11, lnurl
from lnbits.decorators import api_check_wallet_key, api_validate_post_request
from lnbits.utils.exchange_rates import currencies, fiat_amount_as_satoshis
from lnbits.requestvars import g
from .. import core_app, db
from ..crud import get_payments, save_balance_check, update_wallet
@@ -28,11 +31,14 @@ from ..services import (
from ..tasks import api_invoice_listeners
@core_app.get("/api/v1/wallet")
@api_check_wallet_key("invoice")
@core_app.get(
"/api/v1/wallet",
# dependencies=[Depends(AuthBearer())]
)
# @api_check_wallet_key("invoice")
async def api_wallet():
return (
{"id": g.wallet.id, "name": g.wallet.name, "balance": g.wallet.balance_msat},
{"id": g().wallet.id, "name": g().wallet.name, "balance": g().wallet.balance_msat},
HTTPStatus.OK,
)
@@ -40,12 +46,12 @@ async def api_wallet():
@core_app.put("/api/v1/wallet/<new_name>")
@api_check_wallet_key("invoice")
async def api_update_wallet(new_name: str):
await update_wallet(g.wallet.id, new_name)
await update_wallet(g().wallet.id, new_name)
return (
{
"id": g.wallet.id,
"name": g.wallet.name,
"balance": g.wallet.balance_msat,
"id": g().wallet.id,
"name": g().wallet.name,
"balance": g().wallet.balance_msat,
},
HTTPStatus.OK,
)
@@ -55,7 +61,7 @@ async def api_update_wallet(new_name: str):
@api_check_wallet_key("invoice")
async def api_payments():
return (
await get_payments(wallet_id=g.wallet.id, pending=True, complete=True),
await get_payments(wallet_id=g().wallet.id, pending=True, complete=True),
HTTPStatus.OK,
)
@@ -88,7 +94,7 @@ async def api_payments_create_invoice(data: CreateInvoiceData):
async with db.connect() as conn:
try:
payment_hash, payment_request = await create_invoice(
wallet_id=g.wallet.id,
wallet_id=g().wallet.id,
amount=amount,
memo=memo,
description_hash=description_hash,
@@ -105,8 +111,8 @@ async def api_payments_create_invoice(data: CreateInvoiceData):
lnurl_response: Union[None, bool, str] = None
if data.lnurl_callback:
if "lnurl_balance_check" in g.data:
save_balance_check(g.wallet.id, data.lnurl_balance_check)
if "lnurl_balance_check" in g().data:
save_balance_check(g().wallet.id, data.lnurl_balance_check)
async with httpx.AsyncClient() as client:
try:
@@ -117,7 +123,7 @@ async def api_payments_create_invoice(data: CreateInvoiceData):
"balanceNotify": url_for(
"core.lnurl_balance_notify",
service=urlparse(data.lnurl_callback).netloc,
wal=g.wallet.id,
wal=g().wallet.id,
_external=True,
),
},
@@ -217,14 +223,14 @@ async def api_payments_pay_lnurl(data: CreateLNURLData):
if invoice.amount_msat != data.amount:
return (
{
"message": f"{domain} returned an invalid invoice. Expected {g.data['amount']} msat, got {invoice.amount_msat}."
"message": f"{domain} returned an invalid invoice. Expected {g().data['amount']} msat, got {invoice.amount_msat}."
},
HTTPStatus.BAD_REQUEST,
)
if invoice.description_hash != g.data["description_hash"]:
if invoice.description_hash != g().data["description_hash"]:
return (
{
"message": f"{domain} returned an invalid invoice. Expected description_hash == {g.data['description_hash']}, got {invoice.description_hash}."
"message": f"{domain} returned an invalid invoice. Expected description_hash == {g().data['description_hash']}, got {invoice.description_hash}."
},
HTTPStatus.BAD_REQUEST,
)
@@ -237,7 +243,7 @@ async def api_payments_pay_lnurl(data: CreateLNURLData):
extra["comment"] = data.comment
payment_hash = await pay_invoice(
wallet_id=g.wallet.id,
wallet_id=g().wallet.id,
payment_request=params["pr"],
description=data.description,
extra=extra,
@@ -257,7 +263,7 @@ async def api_payments_pay_lnurl(data: CreateLNURLData):
@core_app.get("/api/v1/payments/<payment_hash>")
@api_check_wallet_key("invoice")
async def api_payment(payment_hash):
payment = await g.wallet.get_payment(payment_hash)
payment = await g().wallet.get_payment(payment_hash)
if not payment:
return {"message": "Payment does not exist."}, HTTPStatus.NOT_FOUND
@@ -278,7 +284,7 @@ async def api_payment(payment_hash):
@core_app.get("/api/v1/payments/sse")
@api_check_wallet_key("invoice", accept_querystring=True)
async def api_payments_sse():
this_wallet_id = g.wallet.id
this_wallet_id = g().wallet.id
send_payment, receive_payment = trio.open_memory_channel(0)
@@ -356,7 +362,7 @@ async def api_lnurlscan(code: str):
params.update(kind="auth")
params.update(callback=url) # with k1 already in it
lnurlauth_key = g.wallet.lnurlauth_key(domain)
lnurlauth_key = g().wallet.lnurlauth_key(domain)
params.update(pubkey=lnurlauth_key.verifying_key.to_string("compressed").hex())
else:
async with httpx.AsyncClient() as client:
+11 -18
View File
@@ -1,15 +1,10 @@
from lnbits.requestvars import g
from os import path
from http import HTTPStatus
from quart import (
g,
current_app,
abort,
request,
redirect,
render_template,
send_from_directory,
url_for,
)
from typing import Optional
import jinja2
from starlette.responses import HTMLResponse
from lnbits.core import core_app, db
from lnbits.decorators import check_user_exists, validate_uuids
@@ -26,20 +21,18 @@ from ..crud import (
)
from ..services import redeem_lnurl_withdraw, pay_invoice
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from fastapi.responses import FileResponse
from lnbits.jinja2_templating import Jinja2Templates
templates = Jinja2Templates(directory="templates")
@core_app.get("/favicon.ico")
async def favicon():
return await send_from_directory(
path.join(core_app.root_path, "static"), "favicon.ico"
)
return FileResponse("lnbits/core/static/favicon.ico")
@core_app.get("/")
@core_app.get("/", response_class=HTMLResponse)
async def home(request: Request, lightning: str = None):
return templates.TemplateResponse("core/index.html", {"request": request, "lnurl": lightning})
return g().templates.TemplateResponse("core/index.html", {"request": request, "lnurl": lightning})
@core_app.get("/extensions")