From e42fdde2acad6b442d48b8a595f4c61b2447e00d Mon Sep 17 00:00:00 2001 From: Tiago vasconcelos Date: Tue, 28 Dec 2021 14:47:44 +0000 Subject: [PATCH 01/10] fix wallet key permission for create --- lnbits/extensions/satspay/views_api.py | 28 +++++++++++++++++--------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/lnbits/extensions/satspay/views_api.py b/lnbits/extensions/satspay/views_api.py index a207113b..8b5f7b9a 100644 --- a/lnbits/extensions/satspay/views_api.py +++ b/lnbits/extensions/satspay/views_api.py @@ -5,7 +5,13 @@ from fastapi import Query from fastapi.params import Depends from starlette.exceptions import HTTPException -from lnbits.decorators import WalletTypeInfo, get_key_type, require_admin_key +from lnbits.decorators import ( + WalletAdminKeyChecker, + WalletInvoiceKeyChecker, + WalletTypeInfo, + get_key_type, + require_admin_key, +) from lnbits.extensions.satspay import satspay_ext from .crud import ( @@ -20,20 +26,22 @@ from .models import CreateCharge #############################CHARGES########################## +@satspay_ext.post("/api/v1/charge", dependencies=[Depends(WalletInvoiceKeyChecker())]) +async def api_charge_create( + data: CreateCharge, + wallet: WalletTypeInfo = Depends(get_key_type) +): + charge = await create_charge(user=wallet.wallet.user, data=data) + return charge.dict() -@satspay_ext.post("/api/v1/charge") -@satspay_ext.put("/api/v1/charge/{charge_id}") -async def api_charge_create_or_update( +@satspay_ext.put("/api/v1/charge/{charge_id}", dependencies=[Depends(WalletAdminKeyChecker())]) +async def api_charge_update( data: CreateCharge, wallet: WalletTypeInfo = Depends(require_admin_key), charge_id=None, ): - if not charge_id: - charge = await create_charge(user=wallet.wallet.user, data=data) - return charge.dict() - else: - charge = await update_charge(charge_id=charge_id, data=data) - return charge.dict() + charge = await update_charge(charge_id=charge_id, data=data) + return charge.dict() @satspay_ext.get("/api/v1/charges") From 0ef0188462e8ac16ebc31a969bbf15d3a1e48226 Mon Sep 17 00:00:00 2001 From: Tiago vasconcelos Date: Tue, 28 Dec 2021 15:16:45 +0000 Subject: [PATCH 02/10] index --- lnbits/extensions/satspay/templates/satspay/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lnbits/extensions/satspay/templates/satspay/index.html b/lnbits/extensions/satspay/templates/satspay/index.html index 7c5b2114..5be38cf6 100644 --- a/lnbits/extensions/satspay/templates/satspay/index.html +++ b/lnbits/extensions/satspay/templates/satspay/index.html @@ -475,7 +475,7 @@ }, sendFormDataCharge: function () { var self = this - var wallet = this.g.user.wallets[0].adminkey + var wallet = this.g.user.wallets[0].inkey var data = this.formDialogCharge.data data.amount = parseInt(data.amount) data.time = parseInt(data.time) From aa58775c90ee9c7e9bf1b5783d714d4287e89a24 Mon Sep 17 00:00:00 2001 From: Tiago vasconcelos Date: Tue, 28 Dec 2021 15:17:08 +0000 Subject: [PATCH 03/10] added require_invoice_key --- lnbits/decorators.py | 18 ++++++++++++++++++ lnbits/extensions/satspay/views_api.py | 7 ++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lnbits/decorators.py b/lnbits/decorators.py index 04f0e220..f7cf86ec 100644 --- a/lnbits/decorators.py +++ b/lnbits/decorators.py @@ -171,6 +171,24 @@ async def require_admin_key( else: return wallet +async def require_invoice_key( + r: Request, + api_key_header: str = Security(api_key_header), + api_key_query: str = Security(api_key_query), +): + token = api_key_header if api_key_header else api_key_query + + wallet = await get_key_type(r, token) + + if wallet.wallet_type > 1: + # If wallet type is not invoice then return the unauthorized status + # This also covers when the user passes an invalid key type + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="Invoice (or Admin) key required." + ) + else: + return wallet + async def check_user_exists(usr: UUID4) -> User: g().user = await get_user(usr.hex) diff --git a/lnbits/extensions/satspay/views_api.py b/lnbits/extensions/satspay/views_api.py index 8b5f7b9a..c2f85ca4 100644 --- a/lnbits/extensions/satspay/views_api.py +++ b/lnbits/extensions/satspay/views_api.py @@ -11,6 +11,7 @@ from lnbits.decorators import ( WalletTypeInfo, get_key_type, require_admin_key, + require_invoice_key, ) from lnbits.extensions.satspay import satspay_ext @@ -26,15 +27,15 @@ from .models import CreateCharge #############################CHARGES########################## -@satspay_ext.post("/api/v1/charge", dependencies=[Depends(WalletInvoiceKeyChecker())]) +@satspay_ext.post("/api/v1/charge") async def api_charge_create( data: CreateCharge, - wallet: WalletTypeInfo = Depends(get_key_type) + wallet: WalletTypeInfo = Depends(require_invoice_key) ): charge = await create_charge(user=wallet.wallet.user, data=data) return charge.dict() -@satspay_ext.put("/api/v1/charge/{charge_id}", dependencies=[Depends(WalletAdminKeyChecker())]) +@satspay_ext.put("/api/v1/charge/{charge_id}") async def api_charge_update( data: CreateCharge, wallet: WalletTypeInfo = Depends(require_admin_key), From adcfc43f56899e63b26d4b795e34201adf100b2a Mon Sep 17 00:00:00 2001 From: Tiago vasconcelos Date: Tue, 28 Dec 2021 15:22:08 +0000 Subject: [PATCH 04/10] clean up --- lnbits/extensions/satspay/views_api.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/lnbits/extensions/satspay/views_api.py b/lnbits/extensions/satspay/views_api.py index c2f85ca4..428f2ef6 100644 --- a/lnbits/extensions/satspay/views_api.py +++ b/lnbits/extensions/satspay/views_api.py @@ -6,8 +6,6 @@ from fastapi.params import Depends from starlette.exceptions import HTTPException from lnbits.decorators import ( - WalletAdminKeyChecker, - WalletInvoiceKeyChecker, WalletTypeInfo, get_key_type, require_admin_key, From df2345bda90638e0ca9c2895256c055e78607a0d Mon Sep 17 00:00:00 2001 From: Tiago vasconcelos Date: Tue, 28 Dec 2021 15:22:45 +0000 Subject: [PATCH 05/10] added require_invoice_key clean up --- lnbits/decorators.py | 18 ++++++++++++++++++ lnbits/extensions/satspay/views_api.py | 9 ++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lnbits/decorators.py b/lnbits/decorators.py index 04f0e220..f7cf86ec 100644 --- a/lnbits/decorators.py +++ b/lnbits/decorators.py @@ -171,6 +171,24 @@ async def require_admin_key( else: return wallet +async def require_invoice_key( + r: Request, + api_key_header: str = Security(api_key_header), + api_key_query: str = Security(api_key_query), +): + token = api_key_header if api_key_header else api_key_query + + wallet = await get_key_type(r, token) + + if wallet.wallet_type > 1: + # If wallet type is not invoice then return the unauthorized status + # This also covers when the user passes an invalid key type + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="Invoice (or Admin) key required." + ) + else: + return wallet + async def check_user_exists(usr: UUID4) -> User: g().user = await get_user(usr.hex) diff --git a/lnbits/extensions/satspay/views_api.py b/lnbits/extensions/satspay/views_api.py index 8b5f7b9a..428f2ef6 100644 --- a/lnbits/extensions/satspay/views_api.py +++ b/lnbits/extensions/satspay/views_api.py @@ -6,11 +6,10 @@ from fastapi.params import Depends from starlette.exceptions import HTTPException from lnbits.decorators import ( - WalletAdminKeyChecker, - WalletInvoiceKeyChecker, WalletTypeInfo, get_key_type, require_admin_key, + require_invoice_key, ) from lnbits.extensions.satspay import satspay_ext @@ -26,15 +25,15 @@ from .models import CreateCharge #############################CHARGES########################## -@satspay_ext.post("/api/v1/charge", dependencies=[Depends(WalletInvoiceKeyChecker())]) +@satspay_ext.post("/api/v1/charge") async def api_charge_create( data: CreateCharge, - wallet: WalletTypeInfo = Depends(get_key_type) + wallet: WalletTypeInfo = Depends(require_invoice_key) ): charge = await create_charge(user=wallet.wallet.user, data=data) return charge.dict() -@satspay_ext.put("/api/v1/charge/{charge_id}", dependencies=[Depends(WalletAdminKeyChecker())]) +@satspay_ext.put("/api/v1/charge/{charge_id}") async def api_charge_update( data: CreateCharge, wallet: WalletTypeInfo = Depends(require_admin_key), From 2991cbce1f67149e2243e7c080cbc7f8d218a08a Mon Sep 17 00:00:00 2001 From: Tiago vasconcelos Date: Wed, 29 Dec 2021 12:57:43 +0000 Subject: [PATCH 06/10] add listener to invoice --- lnbits/extensions/satspay/__init__.py | 10 +++++- lnbits/extensions/satspay/crud.py | 7 +++-- lnbits/extensions/satspay/tasks.py | 31 +++++++++++++++++++ .../satspay/templates/satspay/display.html | 18 ++++++++++- lnbits/extensions/satspay/views.py | 4 ++- 5 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 lnbits/extensions/satspay/tasks.py diff --git a/lnbits/extensions/satspay/__init__.py b/lnbits/extensions/satspay/__init__.py index 7cc5f64c..ddbd1bb9 100644 --- a/lnbits/extensions/satspay/__init__.py +++ b/lnbits/extensions/satspay/__init__.py @@ -1,7 +1,10 @@ +import asyncio + from fastapi import APIRouter from lnbits.db import Database from lnbits.helpers import template_renderer +from lnbits.tasks import catch_everything_and_restart db = Database("ext_satspay") @@ -12,6 +15,11 @@ satspay_ext: APIRouter = APIRouter(prefix="/satspay", tags=["satspay"]) def satspay_renderer(): return template_renderer(["lnbits/extensions/satspay/templates"]) - +from .tasks import wait_for_paid_invoices from .views import * # noqa from .views_api import * # noqa + + +def satspay_start(): + loop = asyncio.get_event_loop() + loop.create_task(catch_everything_and_restart(wait_for_paid_invoices)) diff --git a/lnbits/extensions/satspay/crud.py b/lnbits/extensions/satspay/crud.py index edbd39e7..a4fe5f14 100644 --- a/lnbits/extensions/satspay/crud.py +++ b/lnbits/extensions/satspay/crud.py @@ -25,7 +25,10 @@ async def create_charge(user: str, data: CreateCharge) -> Charges: onchainaddress = None if data.lnbitswallet: payment_hash, payment_request = await create_invoice( - wallet_id=data.lnbitswallet, amount=data.amount, memo=charge_id + wallet_id=data.lnbitswallet, + amount=data.amount, + memo=charge_id, + extra={"tag": "charge"}, ) else: payment_hash = None @@ -112,7 +115,7 @@ async def check_address_balance(charge_id: str) -> List[Charges]: pass if charge.lnbitswallet: invoice_status = await api_payment(charge.payment_hash) - + if invoice_status["paid"]: return await update_charge(charge_id=charge_id, balance=charge.amount) row = await db.fetchone("SELECT * FROM satspay.charges WHERE id = ?", (charge_id,)) diff --git a/lnbits/extensions/satspay/tasks.py b/lnbits/extensions/satspay/tasks.py new file mode 100644 index 00000000..bddd4ab2 --- /dev/null +++ b/lnbits/extensions/satspay/tasks.py @@ -0,0 +1,31 @@ +import asyncio + +from lnbits.core.models import Payment +from lnbits.extensions.satspay.crud import check_address_balance, get_charge +from lnbits.tasks import register_invoice_listener + +# from .crud import get_ticket, set_ticket_paid + + +async def wait_for_paid_invoices(): + invoice_queue = asyncio.Queue() + register_invoice_listener(invoice_queue) + + while True: + payment = await invoice_queue.get() + await on_invoice_paid(payment) + + +async def on_invoice_paid(payment: Payment) -> None: + if "charge" != payment.extra.get("tag"): + # not a charge invoice + return + + charge = await get_charge(payment.memo) + if not charge: + print("this should never happen", payment) + return + + await payment.set_pending(False) + await check_address_balance(charge_id=charge.id) + diff --git a/lnbits/extensions/satspay/templates/satspay/display.html b/lnbits/extensions/satspay/templates/satspay/display.html index 5b0282b6..9f42e88f 100644 --- a/lnbits/extensions/satspay/templates/satspay/display.html +++ b/lnbits/extensions/satspay/templates/satspay/display.html @@ -235,10 +235,24 @@ charge_time_elapsed: '{{charge.time_elapsed}}', charge_amount: '{{charge.amount}}', charge_balance: '{{charge.balance}}', - charge_paid: '{{charge.paid}}' + charge_paid: '{{charge.paid}}', + wallet: { + inkey: '' + }, + cancelListener: () => {} } }, methods: { + startPaymentNotifier(){ + this.cancelListener() + + this.cancelListener = LNbits.event.onInvoicePaid( + this.wallet, + payment => { + this.checkBalance() + } + ) + }, checkBalance: function () { var self = this LNbits.api @@ -307,12 +321,14 @@ this.lnbtc = false this.onbtc = true } + this.wallet.inkey = '{{ wallet_inkey }}' this.getTheTime() this.getThePercentage() var timerCount = this.timerCount if ('{{ charge.paid }}' == 'False') { timerCount() } + this.startPaymentNotifier() } }) diff --git a/lnbits/extensions/satspay/views.py b/lnbits/extensions/satspay/views.py index 500f0212..07ed71ef 100644 --- a/lnbits/extensions/satspay/views.py +++ b/lnbits/extensions/satspay/views.py @@ -6,6 +6,7 @@ from starlette.exceptions import HTTPException from starlette.requests import Request from starlette.responses import HTMLResponse +from lnbits.core.crud import get_wallet from lnbits.core.models import User from lnbits.decorators import check_user_exists @@ -29,6 +30,7 @@ async def display(request: Request, charge_id): raise HTTPException( status_code=HTTPStatus.NOT_FOUND, detail="Charge link does not exist." ) + wallet = await get_wallet(charge.lnbitswallet) return satspay_renderer().TemplateResponse( - "satspay/display.html", {"request": request, "charge": charge} + "satspay/display.html", {"request": request, "charge": charge, "wallet_key": wallet.inkey} ) From aa8557ada1a0fd4d529120e3eeb1e95982fe2b51 Mon Sep 17 00:00:00 2001 From: Tiago vasconcelos Date: Wed, 29 Dec 2021 15:12:10 +0000 Subject: [PATCH 07/10] fix lightning:// --- lnbits/extensions/withdraw/templates/withdraw/display.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lnbits/extensions/withdraw/templates/withdraw/display.html b/lnbits/extensions/withdraw/templates/withdraw/display.html index 245b3ed1..5552c77f 100644 --- a/lnbits/extensions/withdraw/templates/withdraw/display.html +++ b/lnbits/extensions/withdraw/templates/withdraw/display.html @@ -7,7 +7,7 @@ {% if link.is_spent %} Withdraw is spent. {% endif %} - + Date: Wed, 29 Dec 2021 15:12:37 +0000 Subject: [PATCH 08/10] fix lightning:// --- lnbits/extensions/satspay/templates/satspay/display.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lnbits/extensions/satspay/templates/satspay/display.html b/lnbits/extensions/satspay/templates/satspay/display.html index 9f42e88f..e60bdf7d 100644 --- a/lnbits/extensions/satspay/templates/satspay/display.html +++ b/lnbits/extensions/satspay/templates/satspay/display.html @@ -132,7 +132,7 @@ lightning-network invoice - + Date: Wed, 29 Dec 2021 15:15:49 +0000 Subject: [PATCH 09/10] fix lightning:// fix lightning:// --- lnbits/extensions/satspay/templates/satspay/display.html | 2 +- lnbits/extensions/withdraw/templates/withdraw/display.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lnbits/extensions/satspay/templates/satspay/display.html b/lnbits/extensions/satspay/templates/satspay/display.html index 9f42e88f..e60bdf7d 100644 --- a/lnbits/extensions/satspay/templates/satspay/display.html +++ b/lnbits/extensions/satspay/templates/satspay/display.html @@ -132,7 +132,7 @@ lightning-network invoice - + Withdraw is spent. {% endif %} - + Date: Wed, 29 Dec 2021 15:19:09 +0000 Subject: [PATCH 10/10] fix :// in bitcoin --- lnbits/extensions/satspay/templates/satspay/display.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lnbits/extensions/satspay/templates/satspay/display.html b/lnbits/extensions/satspay/templates/satspay/display.html index e60bdf7d..7d7f2ab4 100644 --- a/lnbits/extensions/satspay/templates/satspay/display.html +++ b/lnbits/extensions/satspay/templates/satspay/display.html @@ -182,7 +182,7 @@ to this onchain address - +