import asyncio import datetime from http import HTTPStatus from fastapi import HTTPException from starlette.requests import Request from lnbits import bolt11 from .. import core_app from ..crud import get_standalone_payment from ..tasks import api_invoice_listeners @core_app.get("/.well-known/lnurlp/{username}") async def lnaddress(username: str, request: Request): from lnbits.extensions.lnaddress.lnurl import lnurl_response domain = request.client.host return await lnurl_response(username, domain, request) @core_app.get("/public/v1/payment/{payment_hash}") async def api_public_payment_longpolling(payment_hash): payment = await get_standalone_payment(payment_hash) if not payment: raise HTTPException( status_code=HTTPStatus.NOT_FOUND, detail="Payment does not exist." ) elif not payment.pending: return {"status": "paid"} try: invoice = bolt11.decode(payment.bolt11) expiration = datetime.datetime.fromtimestamp(invoice.date + invoice.expiry) if expiration < datetime.datetime.now(): return {"status": "expired"} except: raise HTTPException( status_code=HTTPStatus.BAD_REQUEST, detail="Invalid bolt11 invoice." ) payment_queue = asyncio.Queue(0) print("adding standalone invoice listener", payment_hash, payment_queue) api_invoice_listeners.append(payment_queue) response = None async def payment_info_receiver(cancel_scope): async for payment in payment_queue.get(): if payment.payment_hash == payment_hash: nonlocal response response = {"status": "paid"} cancel_scope.cancel() async def timeouter(cancel_scope): await asyncio.sleep(45) cancel_scope.cancel() asyncio.create_task(payment_info_receiver()) asyncio.create_task(timeouter()) if response: return response else: raise HTTPException(status_code=HTTPStatus.REQUEST_TIMEOUT, detail="timeout")