added simple lnurl

This commit is contained in:
arcbtc 2023-12-08 20:39:27 +00:00
parent 2261bb8452
commit c87ccf7107
11 changed files with 154 additions and 39 deletions

View file

@ -18,7 +18,9 @@ async def create_temp(wallet_id: str, data: CreateTempData) -> Temp:
temp_id, temp_id,
wallet_id, wallet_id,
data.name, data.name,
data.total data.total,
data.lnurlpayamount,
data.lnurlwithdrawamount
), ),
) )
temp = await get_temp(temp_id) temp = await get_temp(temp_id)

115
lnurl.py
View file

@ -1 +1,114 @@
# Maybe your extensions needs some LNURL stuff, for anything LNURL always make sure you are on spec https://github.com/lnurl/luds # Maybe your extensions needs some LNURL stuff, if so checkout LNURLp/LNURLw extensions/lnurl library in LNbits (to keep things simple the below examples are raw LNURLs)
from http import HTTPStatus
from fastapi import Depends, Query, Request
from . import temp_ext
from .crud import get_temp
from lnbits.core.services import create_invoice
#################################################
########### A very simple LNURLpay ##############
# https://github.com/lnurl/luds/blob/luds/06.md #
#################################################
#################################################
@temp_ext.get(
"/api/v1/lnurl/pay/{temp_id}", status_code=HTTPStatus.OK
)
async def api_lnurl_pay(
request: Request,
temp_id: str,
):
temp = await get_temp(temp_id)
if not temp:
return {"status": "ERROR", "reason": "No temp found"}
return {
"callback": str(request.url_for("temp.api_lnurl_pay_callback", temp_id=temp_id)),
"maxSendable": temp.lnurlpayamount,
"minSendable": temp.lnurlpayamount,
"metadata":"[[\"text/plain\", \"" + temp.name + "\"]]",
"tag": "payRequest"
}
@temp_ext.get(
"/api/v1/lnurl/pay/cb/{temp_id}",
status_code=HTTPStatus.OK,
name="temp.api_lnurl_pay_callback",
)
async def api_lnurl_pay_cb(
request: Request,
temp_id: str,
amount: int = Query(...),
):
temp = await get_temp(temp_id)
if not temp:
return {"status": "ERROR", "reason": "No temp found"}
payment_request = await create_invoice(
wallet_id=temp.wallet,
amount=int(amount / 1000),
memo=temp.name,
unhashed_description="[[\"text/plain\", \"" + temp.name + "\"]]".encode(),
extra= {
"tag": "temp",
"link": temp_id,
"extra": request.query_params.get("amount"),
},
)
return { "pr": payment_request, "routes": []}
#################################################
######## A very simple LNURLwithdraw ############
# https://github.com/lnurl/luds/blob/luds/03.md #
#################################################
#################################################
@temp_ext.get(
"/api/v1/lnurl/withdraw/{temp_id}", status_code=HTTPStatus.OK
)
async def api_lnurl_pay(
request: Request,
temp_id: str,
):
temp = await get_temp(temp_id)
if not temp:
return {"status": "ERROR", "reason": "No temp found"}
return {
"callback": str(request.url_for("temp.api_lnurl_pay_callback", temp_id=temp_id)),
"maxSendable": temp.lnurlwithdrawamount,
"minSendable": temp.lnurlwithdrawamount,
"k1": "",
"defaultDescription": temp.name,
"metadata":"[[\"text/plain\", \"" + temp.name + "\"]]",
"tag": "withdrawRequest"
}
@temp_ext.get(
"/api/v1/lnurl/pay/cb/{temp_id}",
status_code=HTTPStatus.OK,
name="temp.api_lnurl_pay_callback",
)
async def api_lnurl_pay_cb(
request: Request,
temp_id: str,
amount: int = Query(...),
):
temp = await get_temp(temp_id)
if not temp:
return {"status": "ERROR", "reason": "No temp found"}
payment_request = await create_invoice(
wallet_id=temp.wallet,
amount=int(amount / 1000),
memo=temp.name,
unhashed_description="[[\"text/plain\", \"" + temp.name + "\"]]".encode(),
extra= {
"tag": "temp",
"link": temp_id,
"extra": request.query_params.get("amount"),
},
)
return { "pr": payment_request, "routes": []}

View file

@ -9,7 +9,10 @@ async def m001_initial(db):
CREATE TABLE temp.temp ( CREATE TABLE temp.temp (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
wallet TEXT NOT NULL, wallet TEXT NOT NULL,
name TEXT NOT NULL name TEXT NOT NULL,
total INTEGER DEFAULT 0,
lnurlpayamount INTEGER DEFAULT 0,
lnurlwithdrawamount INTEGER DEFAULT 0,
); );
""" """
) )
@ -23,6 +26,6 @@ async def m002_addtip_wallet(db):
""" """
await db.execute( await db.execute(
""" """
ALTER TABLE temp.temp ADD total withdrawlimit INTEGER DEFAULT 0,; ALTER TABLE temp.temp ADD lnurlwithdrawamount withdrawlimit INTEGER DEFAULT 0,;
""" """
) )

View file

@ -2,23 +2,26 @@ from sqlite3 import Row
from typing import Optional, List from typing import Optional, List
from pydantic import BaseModel from pydantic import BaseModel
from lnbits.lnurl import encode as lnurl_encode
class CreateTempData(BaseModel): class CreateTempData(BaseModel):
wallet: Optional[str] wallet: Optional[str]
name: Optional[str] name: Optional[str]
total: Optional[int] total: Optional[int]
lnurlpayamount: Optional[int]
lnurlwithdrawamount: Optional[int]
class Temp(BaseModel): class Temp(BaseModel):
id: str id: str
wallet: str wallet: str
name: str name: str
total: Optional[int] total: Optional[int]
lnurlpayamount: Optional[int]
lnurlwithdrawamount: Optional[int]
@classmethod @classmethod
def from_row(cls, row: Row) -> "Temp": def from_row(cls, row: Row) -> "Temp":
return cls(**dict(row)) return cls(**dict(row))
class CreateUpdateItemData(BaseModel): class CreateUpdateItemData(BaseModel):
items: List[Item] items: List[Item]
# add something lnurly

18
templates/temp/_temp.html Normal file
View file

@ -0,0 +1,18 @@
<q-expansion-item group="extras" icon="info" label="About Temp">
<q-card>
<q-card-section>
<p>
Temp extension is a basic extension that you can use to get started building your own extension
</p>
<small
>Created by
<a
class="text-secondary"
href="https://github.com/benarc"
target="_blank"
>Ben Arc</a
>.</small
>
</q-card-section>
</q-card>
</q-expansion-item>

View file

@ -1,21 +0,0 @@
<q-expansion-item group="extras" icon="info" label="About Temp">
<q-card>
<q-card-section>
<p>
Thiago's Point of Sale is a secure, mobile-ready, instant and shareable
point of sale terminal (PoS) for merchants. The PoS is linked to your
LNbits wallet but completely air-gapped so users can ONLY create
invoices. To share the Temp hit the hash on the terminal.
</p>
<small
>Created by
<a
class="text-secondary"
href="https://github.com/talvasconcelos"
target="_blank"
>Tiago Vasconcelos</a
>.</small
>
</q-card-section>
</q-card>
</q-expansion-item>

View file

@ -49,11 +49,11 @@ async def temp(request: Request, temp_id):
) )
# Customise a manifest, or remove manifest completely # Manifest, customise or remove manifest completely
@temp_ext.get("/manifest/{temp_id}.webmanifest") @temp_ext.get("/manifest/{temp_id}.webmanifest")
async def manifest(temp_id: str): async def manifest(temp_id: str):
remp= await get_temp(temp_id) temp= await get_temp(temp_id)
if not temp: if not temp:
raise HTTPException( raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Temp does not exist." status_code=HTTPStatus.NOT_FOUND, detail="Temp does not exist."

View file

@ -34,10 +34,7 @@ from .models import CreateTempData, PayLnurlWData, LNURLCharge, CreateUpdateItem
##### ADD YOUR API ENDPOINTS HERE ##### ##### ADD YOUR API ENDPOINTS HERE #####
####################################### #######################################
## Get all the records belonging to the user
# TYPICAL ENDPOINTS
# get all the records belonging to the user
@temp_ext.get("/api/v1/temps", status_code=HTTPStatus.OK) @temp_ext.get("/api/v1/temps", status_code=HTTPStatus.OK)
async def api_temps( async def api_temps(
@ -50,7 +47,7 @@ async def api_temps(
return [temp.dict() for temp in await get_temps(wallet_ids)] return [temp.dict() for temp in await get_temps(wallet_ids)]
# get a specific record belonging to a user ## Get a specific record belonging to a user
@temp_ext.put("/api/v1/temps/{temp_id}") @temp_ext.put("/api/v1/temps/{temp_id}")
async def api_temp_update( async def api_temp_update(
@ -71,7 +68,7 @@ async def api_temp_update(
return temp.dict() return temp.dict()
# Create a new record ## Create a new record
@temp_ext.post("/api/v1/temps", status_code=HTTPStatus.CREATED) @temp_ext.post("/api/v1/temps", status_code=HTTPStatus.CREATED)
async def api_temp_create( async def api_temp_create(
@ -81,7 +78,7 @@ async def api_temp_create(
return temp.dict() return temp.dict()
# Delete a record ## Delete a record
@temp_ext.delete("/api/v1/temps/{temp_id}") @temp_ext.delete("/api/v1/temps/{temp_id}")
async def api_temp_delete( async def api_temp_delete(
@ -103,7 +100,7 @@ async def api_temp_delete(
# ANY OTHER ENDPOINTS YOU NEED # ANY OTHER ENDPOINTS YOU NEED
# This endpoint creates a payment ## This endpoint creates a payment
@tpos_ext.post("/api/v1/temps/payment/{temp_id}", status_code=HTTPStatus.CREATED) @tpos_ext.post("/api/v1/temps/payment/{temp_id}", status_code=HTTPStatus.CREATED)
async def api_tpos_create_invoice( async def api_tpos_create_invoice(