diff --git a/lnbits/decorators.py b/lnbits/decorators.py
index 04f0e2206..f7cf86ec9 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/__init__.py b/lnbits/extensions/satspay/__init__.py
index 7cc5f64cd..ddbd1bb97 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 edbd39e7f..a4fe5f14d 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 000000000..bddd4ab2c
--- /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 5b0282b61..7d7f2ab44 100644
--- a/lnbits/extensions/satspay/templates/satspay/display.html
+++ b/lnbits/extensions/satspay/templates/satspay/display.html
@@ -132,7 +132,7 @@
lightning-network invoice
-
+
-
+
{}
}
},
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/templates/satspay/index.html b/lnbits/extensions/satspay/templates/satspay/index.html
index 7c5b21140..5be38cf6b 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)
diff --git a/lnbits/extensions/satspay/views.py b/lnbits/extensions/satspay/views.py
index 500f02123..07ed71ef8 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}
)
diff --git a/lnbits/extensions/satspay/views_api.py b/lnbits/extensions/satspay/views_api.py
index a207113b6..428f2ef69 100644
--- a/lnbits/extensions/satspay/views_api.py
+++ b/lnbits/extensions/satspay/views_api.py
@@ -5,7 +5,12 @@ 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 (
+ WalletTypeInfo,
+ get_key_type,
+ require_admin_key,
+ require_invoice_key,
+)
from lnbits.extensions.satspay import satspay_ext
from .crud import (
@@ -20,20 +25,22 @@ from .models import CreateCharge
#############################CHARGES##########################
-
@satspay_ext.post("/api/v1/charge")
+async def api_charge_create(
+ data: CreateCharge,
+ 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}")
-async def api_charge_create_or_update(
+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")
diff --git a/lnbits/extensions/withdraw/templates/withdraw/display.html b/lnbits/extensions/withdraw/templates/withdraw/display.html
index 245b3ed1a..5552c77ff 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 %}
-
+