fix: several more API calls restored

This commit is contained in:
Stefan Stammberger
2021-08-29 19:38:42 +02:00
parent 5ae124408e
commit fe79709698
5 changed files with 208 additions and 142 deletions
+76 -89
View File
@@ -1,69 +1,59 @@
from lnbits.helpers import url_for
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 fastapi import Query
from http import HTTPStatus
import json
from binascii import unhexlify
from typing import Dict, List, Optional, Union
from http import HTTPStatus
from typing import Dict, Optional, Union
from urllib.parse import ParseResult, parse_qs, urlencode, urlparse, urlunparse
import httpx
import trio
from fastapi import Query, security
from fastapi.exceptions import HTTPException
from fastapi.param_functions import Depends
from fastapi.params import Body
from pydantic import BaseModel
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.core.models import Wallet
from lnbits.decorators import (WalletAdminKeyChecker, WalletInvoiceKeyChecker,
WalletTypeInfo, get_key_type)
from lnbits.helpers import url_for
from lnbits.requestvars import g
from lnbits.utils.exchange_rates import currencies, fiat_amount_as_satoshis
from .. import core_app, db
from ..crud import get_payments, save_balance_check, update_wallet
from ..services import (
PaymentFailure,
InvoiceFailure,
create_invoice,
pay_invoice,
perform_lnurlauth,
)
from ..services import (InvoiceFailure, PaymentFailure, create_invoice,
pay_invoice, perform_lnurlauth)
from ..tasks import api_invoice_listeners
@core_app.get(
"/api/v1/wallet",
# dependencies=[Depends(AuthBearer())]
)
# @api_check_wallet_key("invoice")
async def api_wallet():
@core_app.get("/api/v1/wallet")
async def api_wallet(wallet: WalletTypeInfo = Depends(get_key_type)):
return (
{"id": g().wallet.id, "name": g().wallet.name, "balance": g().wallet.balance_msat},
{"id": wallet.wallet.id, "name": wallet.wallet.name, "balance": wallet.wallet.balance_msat},
HTTPStatus.OK,
)
@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)
async def api_update_wallet(new_name: str, wallet: WalletTypeInfo = Depends(get_key_type)):
await update_wallet(wallet.wallet.id, new_name)
return (
{
"id": g().wallet.id,
"name": g().wallet.name,
"balance": g().wallet.balance_msat,
"id": wallet.wallet.id,
"name": wallet.wallet.name,
"balance": wallet.wallet.balance_msat,
},
HTTPStatus.OK,
)
@core_app.get("/api/v1/payments")
@api_check_wallet_key("invoice")
async def api_payments():
return (
await get_payments(wallet_id=g().wallet.id, pending=True, complete=True),
HTTPStatus.OK,
)
async def api_payments(wallet: WalletTypeInfo = Depends(get_key_type)):
return await get_payments(wallet_id=wallet.wallet.id, pending=True, complete=True)
class CreateInvoiceData(BaseModel):
amount: int = Query(None, ge=1)
@@ -75,9 +65,7 @@ class CreateInvoiceData(BaseModel):
extra: Optional[dict] = None
webhook: Optional[str] = None
@api_check_wallet_key("invoice")
# async def api_payments_create_invoice(amount: List[str] = Query([type: str = Query(None)])):
async def api_payments_create_invoice(data: CreateInvoiceData):
async def api_payments_create_invoice(data: CreateInvoiceData, wallet: Wallet):
if "description_hash" in data:
description_hash = unhexlify(data.description_hash)
memo = ""
@@ -94,7 +82,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=wallet.id,
amount=amount,
memo=memo,
description_hash=description_hash,
@@ -151,10 +139,7 @@ async def api_payments_create_invoice(data: CreateInvoiceData):
)
@api_check_wallet_key("admin")
async def api_payments_pay_invoice(
bolt11: str = Query(...), wallet: Optional[List[str]] = Query(None)
):
async def api_payments_pay_invoice(bolt11: str, wallet: Wallet):
try:
payment_hash = await pay_invoice(
wallet_id=wallet.id,
@@ -179,11 +164,20 @@ async def api_payments_pay_invoice(
)
@core_app.post("/api/v1/payments")
async def api_payments_create(out: bool = True):
if out is True:
return await api_payments_pay_invoice()
return await api_payments_create_invoice()
@core_app.post("/api/v1/payments", deprecated=True,
description="DEPRECATED. Use /api/v2/TBD and /api/v2/TBD instead")
async def api_payments_create(wallet: WalletTypeInfo = Depends(get_key_type), out: bool = True,
invoiceData: Optional[CreateInvoiceData] = Body(None),
bolt11: Optional[str] = Query(None)):
if wallet.wallet_type < 0 or wallet.wallet_type > 2:
raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="Key is invalid")
if out is True and wallet.wallet_type == 0:
if not bolt11:
raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="BOLT11 string is invalid or not given")
return await api_payments_pay_invoice(bolt11, wallet.wallet) # admin key
return await api_payments_create_invoice(invoiceData, wallet.wallet) # invoice key
class CreateLNURLData(BaseModel):
description_hash: str
@@ -192,8 +186,7 @@ class CreateLNURLData(BaseModel):
comment: Optional[str] = None
description: Optional[str] = None
@core_app.post("/api/v1/payments/lnurl")
@api_check_wallet_key("admin")
@core_app.post("/api/v1/payments/lnurl", dependencies=[Depends(WalletAdminKeyChecker())])
async def api_payments_pay_lnurl(data: CreateLNURLData):
domain = urlparse(data.callback).netloc
@@ -258,32 +251,9 @@ async def api_payments_pay_lnurl(data: CreateLNURLData):
HTTPStatus.CREATED,
)
@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)
if not payment:
return {"message": "Payment does not exist."}, HTTPStatus.NOT_FOUND
elif not payment.pending:
return {"paid": True, "preimage": payment.preimage}, HTTPStatus.OK
try:
await payment.check_pending()
except Exception:
return {"paid": False}, HTTPStatus.OK
return (
{"paid": not payment.pending, "preimage": payment.preimage},
HTTPStatus.OK,
)
@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
async def api_payments_sse(wallet: WalletTypeInfo = Depends(get_key_type)):
this_wallet_id = wallet.wallet.id
send_payment, receive_payment = trio.open_memory_channel(0)
@@ -303,9 +273,10 @@ async def api_payments_sse():
await send_event.send(("keepalive", ""))
await trio.sleep(25)
current_app.nursery.start_soon(payment_received)
current_app.nursery.start_soon(repeat_keepalive)
async with trio.open_nursery() as nursery:
nursery.start_soon(payment_received)
nursery.start_soon(repeat_keepalive)
async def send_events():
try:
async for typ, data in event_to_send:
@@ -332,9 +303,26 @@ async def api_payments_sse():
response.timeout = None
return response
@core_app.get("/api/v1/payments/{payment_hash}")
async def api_payment(payment_hash, wallet: WalletTypeInfo = Depends(get_key_type)):
payment = await wallet.wallet.get_payment(payment_hash)
@core_app.get("/api/v1/lnurlscan/{code}")
@api_check_wallet_key("invoice")
if not payment:
return {"message": "Payment does not exist."}, HTTPStatus.NOT_FOUND
elif not payment.pending:
return {"paid": True, "preimage": payment.preimage}, HTTPStatus.OK
try:
await payment.check_pending()
except Exception:
return {"paid": False}, HTTPStatus.OK
return (
{"paid": not payment.pending, "preimage": payment.preimage},
HTTPStatus.OK,
)
@core_app.get("/api/v1/lnurlscan/{code}", dependencies=[Depends(WalletInvoiceKeyChecker())])
async def api_lnurlscan(code: str):
try:
url = lnurl.decode(code)
@@ -443,8 +431,7 @@ async def api_lnurlscan(code: str):
return params
@core_app.post("/api/v1/lnurlauth")
@api_check_wallet_key("admin")
@core_app.post("/api/v1/lnurlauth", dependencies=[Depends(WalletAdminKeyChecker())])
async def api_perform_lnurlauth(callback: str):
err = await perform_lnurlauth(callback)
if err:
@@ -452,6 +439,6 @@ async def api_perform_lnurlauth(callback: str):
return "", HTTPStatus.OK
@core_app.route("/api/v1/currencies", methods=["GET"])
@core_app.get("/api/v1/currencies")
async def api_list_currencies_available():
return list(currencies.keys())
+15 -13
View File
@@ -2,12 +2,14 @@ from http import HTTPStatus
from typing import Optional
from fastapi import Request, status
from fastapi.exceptions import HTTPException
from fastapi.param_functions import Body
from fastapi.params import Depends, Query
from fastapi.responses import FileResponse, RedirectResponse
from fastapi.routing import APIRouter
from pydantic.types import UUID4
from starlette.responses import HTMLResponse
import trio
from lnbits.core import db
from lnbits.helpers import template_renderer, url_for
@@ -40,9 +42,7 @@ async def extensions(request: Request, enable: str, disable: str):
extension_to_disable = disable
if extension_to_enable and extension_to_disable:
abort(
HTTPStatus.BAD_REQUEST, "You can either `enable` or `disable` an extension."
)
raise HTTPException(HTTPStatus.BAD_REQUEST, "You can either `enable` or `disable` an extension.")
if extension_to_enable:
await update_user_extension(
@@ -142,7 +142,8 @@ async def lnurl_full_withdraw_callback(request: Request):
except:
pass
current_app.nursery.start_soon(pay)
async with trio.open_nursery() as n:
n.start_soon(pay)
balance_notify = request.args.get("balanceNotify")
if balance_notify:
@@ -159,7 +160,7 @@ async def deletewallet(request: Request):
user_wallet_ids = g().user.wallet_ids
if wallet_id not in user_wallet_ids:
abort(HTTPStatus.FORBIDDEN, "Not your wallet.")
raise HTTPException(HTTPStatus.FORBIDDEN, "Not your wallet.")
else:
await delete_wallet(user_id=g().user.id, wallet_id=wallet_id)
user_wallet_ids.remove(wallet_id)
@@ -186,16 +187,17 @@ async def lnurlwallet(request: Request):
user = await get_user(account.id, conn=conn)
wallet = await create_wallet(user_id=user.id, conn=conn)
current_app.nursery.start_soon(
redeem_lnurl_withdraw,
wallet.id,
request.args.get("lightning"),
"LNbits initial funding: voucher redeem.",
{"tag": "lnurlwallet"},
5, # wait 5 seconds before sending the invoice to the service
async with trio.open_nursery() as n:
n.start_soon(
redeem_lnurl_withdraw,
wallet.id,
request.args.get("lightning"),
"LNbits initial funding: voucher redeem.",
{"tag": "lnurlwallet"},
5, # wait 5 seconds before sending the invoice to the service
)
return redirect(url_for("core.wallet", usr=user.id, wal=wallet.id))
return RedirectResponse(f"/wallet?usr={user.id}&wal={wallet.id}", status_code=status.HTTP_307_TEMPORARY_REDIRECT)
@core_html_routes.get("/manifest/{usr}.webmanifest")