mirror of
https://github.com/lnbits/lnbits.git
synced 2025-09-28 21:02:31 +02:00
Adding bitcoinswitch to lnurldevices
This commit is contained in:
@@ -2,6 +2,7 @@ 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_lnurldevice")
|
||||
|
||||
@@ -11,7 +12,11 @@ lnurldevice_ext: APIRouter = APIRouter(prefix="/lnurldevice", tags=["lnurldevice
|
||||
def lnurldevice_renderer():
|
||||
return template_renderer(["lnbits/extensions/lnurldevice/templates"])
|
||||
|
||||
|
||||
from .tasks import wait_for_paid_invoices
|
||||
from .lnurl import * # noqa
|
||||
from .views import * # noqa
|
||||
from .views_api import * # noqa
|
||||
|
||||
def lnurldevice_start():
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.create_task(catch_everything_and_restart(wait_for_paid_invoices))
|
||||
|
@@ -102,7 +102,22 @@ async def lnurl_v1_params(
|
||||
if device.device == "atm":
|
||||
if paymentcheck:
|
||||
return {"status": "ERROR", "reason": f"Payment already claimed"}
|
||||
|
||||
if device.device == "switch":
|
||||
lnurldevicepayment = await create_lnurldevicepayment(
|
||||
deviceid=device.id,
|
||||
sats=device.profit,
|
||||
)
|
||||
if not lnurldevicepayment:
|
||||
return {"status": "ERROR", "reason": "Could not create payment."}
|
||||
return {
|
||||
"tag": "payRequest",
|
||||
"callback": request.url_for(
|
||||
"lnurldevice.lnurl_callback", paymentid=lnurldevicepayment.id
|
||||
),
|
||||
"minSendable": device.profit * 1000,
|
||||
"maxSendable": device.profit * 1000,
|
||||
"metadata": await device.lnurlpay_metadata(),
|
||||
}
|
||||
if len(p) % 4 > 0:
|
||||
p += "=" * (4 - (len(p) % 4))
|
||||
|
||||
@@ -205,6 +220,27 @@ async def lnurl_callback(
|
||||
extra={"tag": "withdraw"},
|
||||
)
|
||||
return {"status": "OK"}
|
||||
if device.device == "switch":
|
||||
payment_hash, payment_request = await create_invoice(
|
||||
wallet_id=device.wallet,
|
||||
amount=lnurldevicepayment.sats / 1000,
|
||||
memo=device.title,
|
||||
unhashed_description=(await device.lnurlpay_metadata()).encode("utf-8"),
|
||||
extra={"tag": "Switch", "id": device.paymentid, "time": device.amount},
|
||||
)
|
||||
lnurldevicepayment = await update_lnurldevicepayment(
|
||||
lnurldevicepayment_id=paymentid, payhash=payment_hash
|
||||
)
|
||||
|
||||
return {
|
||||
"pr": payment_request,
|
||||
"successAction": {
|
||||
"tag": "url",
|
||||
"description": "Check the attached link",
|
||||
"url": request.url_for("lnurldevice.displaypin", paymentid=paymentid),
|
||||
},
|
||||
"routes": [],
|
||||
}
|
||||
|
||||
payment_hash, payment_request = await create_invoice(
|
||||
wallet_id=device.wallet,
|
||||
@@ -226,5 +262,3 @@ async def lnurl_callback(
|
||||
},
|
||||
"routes": [],
|
||||
}
|
||||
|
||||
return resp.dict()
|
||||
|
@@ -79,3 +79,9 @@ async def m002_redux(db):
|
||||
)
|
||||
except:
|
||||
return
|
||||
|
||||
async def m003_redux(db):
|
||||
"""
|
||||
Add 'meta' for storing various metadata about the wallet
|
||||
"""
|
||||
await db.execute("ALTER TABLE lnurldevice.lnurldevices ADD COLUMN amount INT DEFAULT 0;")
|
@@ -17,6 +17,7 @@ class createLnurldevice(BaseModel):
|
||||
currency: str
|
||||
device: str
|
||||
profit: float
|
||||
amount: int
|
||||
|
||||
|
||||
class lnurldevices(BaseModel):
|
||||
@@ -27,6 +28,7 @@ class lnurldevices(BaseModel):
|
||||
currency: str
|
||||
device: str
|
||||
profit: float
|
||||
amount: int
|
||||
timestamp: str
|
||||
|
||||
def from_row(cls, row: Row) -> "lnurldevices":
|
||||
|
39
lnbits/extensions/lnurldevice/tasks.py
Normal file
39
lnbits/extensions/lnurldevice/tasks.py
Normal file
@@ -0,0 +1,39 @@
|
||||
import asyncio
|
||||
import json
|
||||
from http import HTTPStatus
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import httpx
|
||||
from fastapi import HTTPException
|
||||
|
||||
from lnbits import bolt11
|
||||
from lnbits.core.models import Payment
|
||||
from lnbits.core.services import pay_invoice
|
||||
from lnbits.helpers import get_current_extension_name
|
||||
from lnbits.tasks import register_invoice_listener
|
||||
|
||||
from .crud import get_lnurldevice
|
||||
from .views import updater
|
||||
|
||||
async def wait_for_paid_invoices():
|
||||
invoice_queue = asyncio.Queue()
|
||||
register_invoice_listener(invoice_queue, get_current_extension_name())
|
||||
|
||||
while True:
|
||||
payment = await invoice_queue.get()
|
||||
await on_invoice_paid(payment)
|
||||
|
||||
|
||||
async def on_invoice_paid(payment: Payment) -> None:
|
||||
# (avoid loops)
|
||||
if "switch" == payment.extra.get("tag"):
|
||||
lnurldevicepayment = await get_lnurldevicepayment(payment.extra.get("id"))
|
||||
if not lnurldevicepayment:
|
||||
return
|
||||
if lnurldevicepayment.payhash == "used":
|
||||
return
|
||||
lnurldevicepayment = await update_lnurldevicepayment(
|
||||
lnurldevicepayment_id=paymentid, payhash="used"
|
||||
)
|
||||
return await updater(lnurldevicepayment.deviceid)
|
||||
return
|
@@ -51,3 +51,48 @@ async def displaypin(request: Request, paymentid: str = Query(None)):
|
||||
"lnurldevice/error.html",
|
||||
{"request": request, "pin": "filler", "not_paid": True},
|
||||
)
|
||||
|
||||
|
||||
##################WEBSOCKET ROUTES########################
|
||||
|
||||
|
||||
class ConnectionManager:
|
||||
def __init__(self):
|
||||
self.active_connections: List[WebSocket] = []
|
||||
|
||||
async def connect(self, websocket: WebSocket, lnurldevice_id: str):
|
||||
await websocket.accept()
|
||||
websocket.id = lnurldevice_id
|
||||
self.active_connections.append(websocket)
|
||||
|
||||
def disconnect(self, websocket: WebSocket):
|
||||
self.active_connections.remove(websocket)
|
||||
|
||||
async def send_personal_message(self, message: str, lnurldevice_id: str):
|
||||
for connection in self.active_connections:
|
||||
if connection.id == lnurldevice_id:
|
||||
await connection.send_text(message)
|
||||
|
||||
async def broadcast(self, message: str):
|
||||
for connection in self.active_connections:
|
||||
await connection.send_text(message)
|
||||
|
||||
|
||||
manager = ConnectionManager()
|
||||
|
||||
|
||||
@lnurldevice_ext.websocket("/ws/{lnurldevice_id}", name="lnurldevice.lnurldevice_by_id")
|
||||
async def websocket_endpoint(websocket: WebSocket, lnurldevice_id: str):
|
||||
await manager.connect(websocket, lnurldevice_id)
|
||||
try:
|
||||
while True:
|
||||
data = await websocket.receive_text()
|
||||
except WebSocketDisconnect:
|
||||
manager.disconnect(websocket)
|
||||
|
||||
|
||||
async def updater(lnurldevice_id):
|
||||
lnurldevice = await get_lnurldevice(lnurldevice_id)
|
||||
if not lnurldevice:
|
||||
return
|
||||
await manager.send_personal_message(f"{lnurldevice.amount}", lnurldevice_id)
|
Reference in New Issue
Block a user