format
This commit is contained in:
parent
66d44f95fb
commit
2cac36be17
12 changed files with 272 additions and 311 deletions
|
|
@ -8,9 +8,7 @@ from lnbits.tasks import catch_everything_and_restart
|
|||
|
||||
db = Database("ext_myextension")
|
||||
|
||||
myextension_ext: APIRouter = APIRouter(
|
||||
prefix="/myextension", tags=["MyExtension"]
|
||||
)
|
||||
myextension_ext: APIRouter = APIRouter(prefix="/myextension", tags=["MyExtension"])
|
||||
|
||||
temp_static_files = [
|
||||
{
|
||||
|
|
@ -19,14 +17,17 @@ temp_static_files = [
|
|||
}
|
||||
]
|
||||
|
||||
|
||||
def myextension_renderer():
|
||||
return template_renderer(["myextension/templates"])
|
||||
|
||||
|
||||
from .lnurl import *
|
||||
from .tasks import wait_for_paid_invoices
|
||||
from .views import *
|
||||
from .views_api import *
|
||||
|
||||
|
||||
def myextension_start():
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.create_task(catch_everything_and_restart(wait_for_paid_invoices))
|
||||
53
crud.py
53
crud.py
|
|
@ -9,7 +9,10 @@ from fastapi import Request
|
|||
from lnurl import encode as lnurl_encode
|
||||
import shortuuid
|
||||
|
||||
async def create_myextension(wallet_id: str, data: CreateMyExtensionData, req: Request) -> MyExtension:
|
||||
|
||||
async def create_myextension(
|
||||
wallet_id: str, data: CreateMyExtensionData, req: Request
|
||||
) -> MyExtension:
|
||||
myextension_id = urlsafe_short_hash()
|
||||
await db.execute(
|
||||
"""
|
||||
|
|
@ -21,7 +24,7 @@ async def create_myextension(wallet_id: str, data: CreateMyExtensionData, req: R
|
|||
wallet_id,
|
||||
data.name,
|
||||
data.lnurlpayamount,
|
||||
data.lnurlwithdrawamount
|
||||
data.lnurlwithdrawamount,
|
||||
),
|
||||
)
|
||||
myextension = await get_myextension(myextension_id, req)
|
||||
|
|
@ -29,25 +32,33 @@ async def create_myextension(wallet_id: str, data: CreateMyExtensionData, req: R
|
|||
return myextension
|
||||
|
||||
|
||||
async def get_myextension(myextension_id: str, req: Optional[Request] = None) -> Optional[MyExtension]:
|
||||
async def get_myextension(
|
||||
myextension_id: str, req: Optional[Request] = None
|
||||
) -> Optional[MyExtension]:
|
||||
logger.debug(myextension_id)
|
||||
row = await db.fetchone("SELECT * FROM myextension.maintable WHERE id = ?", (myextension_id,))
|
||||
row = await db.fetchone(
|
||||
"SELECT * FROM myextension.maintable WHERE id = ?", (myextension_id,)
|
||||
)
|
||||
if not row:
|
||||
return None
|
||||
rowAmended = MyExtension(**row)
|
||||
if req:
|
||||
rowAmended.lnurlpay = lnurl_encode(
|
||||
req.url_for("myextension.api_lnurl_pay",
|
||||
myextension_id=row.id)._url
|
||||
req.url_for("myextension.api_lnurl_pay", myextension_id=row.id)._url
|
||||
)
|
||||
rowAmended.lnurlwithdraw = lnurl_encode(
|
||||
req.url_for("myextension.api_lnurl_withdraw",
|
||||
req.url_for(
|
||||
"myextension.api_lnurl_withdraw",
|
||||
myextension_id=row.id,
|
||||
tickerhash=shortuuid.uuid(name=rowAmended.id + str(rowAmended.ticker)))._url
|
||||
tickerhash=shortuuid.uuid(name=rowAmended.id + str(rowAmended.ticker)),
|
||||
)._url
|
||||
)
|
||||
return rowAmended
|
||||
|
||||
async def get_myextensions(wallet_ids: Union[str, List[str]], req: Optional[Request] = None) -> List[MyExtension]:
|
||||
|
||||
async def get_myextensions(
|
||||
wallet_ids: Union[str, List[str]], req: Optional[Request] = None
|
||||
) -> List[MyExtension]:
|
||||
if isinstance(wallet_ids, str):
|
||||
wallet_ids = [wallet_ids]
|
||||
|
||||
|
|
@ -59,25 +70,33 @@ async def get_myextensions(wallet_ids: Union[str, List[str]], req: Optional[Requ
|
|||
if req:
|
||||
for row in tempRows:
|
||||
row.lnurlpay = lnurl_encode(
|
||||
req.url_for("myextension.api_lnurl_pay",
|
||||
myextension_id=row.id)._url
|
||||
req.url_for("myextension.api_lnurl_pay", myextension_id=row.id)._url
|
||||
)
|
||||
row.lnurlwithdraw = lnurl_encode(
|
||||
req.url_for("myextension.api_lnurl_withdraw",
|
||||
req.url_for(
|
||||
"myextension.api_lnurl_withdraw",
|
||||
myextension_id=row.id,
|
||||
tickerhash=shortuuid.uuid(name=row.id + str(row.ticker)))._url
|
||||
tickerhash=shortuuid.uuid(name=row.id + str(row.ticker)),
|
||||
)._url
|
||||
)
|
||||
return tempRows
|
||||
|
||||
async def update_myextension(myextension_id: str, req: Optional[Request] = None, **kwargs) -> MyExtension:
|
||||
|
||||
async def update_myextension(
|
||||
myextension_id: str, req: Optional[Request] = None, **kwargs
|
||||
) -> MyExtension:
|
||||
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
|
||||
logger.debug( kwargs.items())
|
||||
logger.debug(kwargs.items())
|
||||
await db.execute(
|
||||
f"UPDATE myextension.maintable SET {q} WHERE id = ?", (*kwargs.values(), myextension_id)
|
||||
f"UPDATE myextension.maintable SET {q} WHERE id = ?",
|
||||
(*kwargs.values(), myextension_id),
|
||||
)
|
||||
myextension = await get_myextension(myextension_id, req)
|
||||
assert myextension, "Newly updated myextension couldn't be retrieved"
|
||||
return myextension
|
||||
|
||||
|
||||
async def delete_myextension(myextension_id: str) -> None:
|
||||
await db.execute("DELETE FROM myextension.maintable WHERE id = ?", (myextension_id,))
|
||||
await db.execute(
|
||||
"DELETE FROM myextension.maintable WHERE id = ?", (myextension_id,)
|
||||
)
|
||||
|
|
|
|||
41
lnurl.py
41
lnurl.py
|
|
@ -19,6 +19,7 @@ import shortuuid
|
|||
#################################################
|
||||
#################################################
|
||||
|
||||
|
||||
@myextension_ext.get(
|
||||
"/api/v1/lnurl/pay/{myextension_id}",
|
||||
status_code=HTTPStatus.OK,
|
||||
|
|
@ -32,13 +33,18 @@ async def api_lnurl_pay(
|
|||
if not myextension:
|
||||
return {"status": "ERROR", "reason": "No myextension found"}
|
||||
return {
|
||||
"callback": str(request.url_for("myextension.api_lnurl_pay_callback", myextension_id=myextension_id)),
|
||||
"callback": str(
|
||||
request.url_for(
|
||||
"myextension.api_lnurl_pay_callback", myextension_id=myextension_id
|
||||
)
|
||||
),
|
||||
"maxSendable": myextension.lnurlpayamount * 1000,
|
||||
"minSendable": myextension.lnurlpayamount * 1000,
|
||||
"metadata":"[[\"text/plain\", \"" + myextension.name + "\"]]",
|
||||
"tag": "payRequest"
|
||||
"metadata": '[["text/plain", "' + myextension.name + '"]]',
|
||||
"tag": "payRequest",
|
||||
}
|
||||
|
||||
|
||||
@myextension_ext.get(
|
||||
"/api/v1/lnurl/pay/cb/{myextension_id}",
|
||||
status_code=HTTPStatus.OK,
|
||||
|
|
@ -58,8 +64,8 @@ async def api_lnurl_pay_cb(
|
|||
wallet_id=myextension.wallet,
|
||||
amount=int(amount / 1000),
|
||||
memo=myextension.name,
|
||||
unhashed_description=f"[[\"text/plain\", \"{myextension.name}\"]]".encode(),
|
||||
extra= {
|
||||
unhashed_description=f'[["text/plain", "{myextension.name}"]]'.encode(),
|
||||
extra={
|
||||
"tag": "MyExtension",
|
||||
"myextensionId": myextension_id,
|
||||
"extra": request.query_params.get("amount"),
|
||||
|
|
@ -68,12 +74,10 @@ async def api_lnurl_pay_cb(
|
|||
return {
|
||||
"pr": payment_request,
|
||||
"routes": [],
|
||||
"successAction": {
|
||||
"tag": "message",
|
||||
"message": f"Paid {myextension.name}"
|
||||
}
|
||||
"successAction": {"tag": "message", "message": f"Paid {myextension.name}"},
|
||||
}
|
||||
|
||||
|
||||
#################################################
|
||||
######## A very simple LNURLwithdraw ############
|
||||
# https://github.com/lnurl/luds/blob/luds/03.md #
|
||||
|
|
@ -100,13 +104,18 @@ async def api_lnurl_withdraw(
|
|||
|
||||
return {
|
||||
"tag": "withdrawRequest",
|
||||
"callback": str(request.url_for("myextension.api_lnurl_withdraw_callback", myextension_id=myextension_id)),
|
||||
"callback": str(
|
||||
request.url_for(
|
||||
"myextension.api_lnurl_withdraw_callback", myextension_id=myextension_id
|
||||
)
|
||||
),
|
||||
"k1": k1,
|
||||
"defaultDescription": myextension.name,
|
||||
"maxWithdrawable": myextension.lnurlwithdrawamount * 1000,
|
||||
"minWithdrawable": myextension.lnurlwithdrawamount * 1000
|
||||
"minWithdrawable": myextension.lnurlwithdrawamount * 1000,
|
||||
}
|
||||
|
||||
|
||||
@myextension_ext.get(
|
||||
"/api/v1/lnurl/withdraw/cb/{myextension_id}",
|
||||
status_code=HTTPStatus.OK,
|
||||
|
|
@ -130,7 +139,9 @@ async def api_lnurl_withdraw_cb(
|
|||
if k1Check != k1:
|
||||
return {"status": "ERROR", "reason": "Wrong k1 check provided"}
|
||||
|
||||
await update_myextension(myextension_id=myextension_id, ticker=myextension.ticker + 1)
|
||||
await update_myextension(
|
||||
myextension_id=myextension_id, ticker=myextension.ticker + 1
|
||||
)
|
||||
logger.debug(myextension.wallet)
|
||||
logger.debug(pr)
|
||||
logger.debug(int(myextension.lnurlwithdrawamount * 1000))
|
||||
|
|
@ -138,6 +149,10 @@ async def api_lnurl_withdraw_cb(
|
|||
wallet_id=myextension.wallet,
|
||||
payment_request=pr,
|
||||
max_sat=int(myextension.lnurlwithdrawamount * 1000),
|
||||
extra={"tag": "MyExtension", "myextensionId": myextension_id, "lnurlwithdraw": True}
|
||||
extra={
|
||||
"tag": "MyExtension",
|
||||
"myextensionId": myextension_id,
|
||||
"lnurlwithdraw": True,
|
||||
},
|
||||
)
|
||||
return {"status": "OK"}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
# The migration file is like a blockchain, never edit only add!
|
||||
|
||||
|
||||
async def m001_initial(db):
|
||||
"""
|
||||
Initial templates table.
|
||||
|
|
@ -19,8 +20,10 @@ async def m001_initial(db):
|
|||
"""
|
||||
)
|
||||
|
||||
|
||||
# Here we add another field to the database
|
||||
|
||||
|
||||
async def m002_addtip_wallet(db):
|
||||
"""
|
||||
Add total to templates table
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ from fastapi import Request
|
|||
from lnbits.lnurl import encode as lnurl_encode
|
||||
from urllib.parse import urlparse
|
||||
|
||||
|
||||
class CreateMyExtensionData(BaseModel):
|
||||
wallet: Optional[str]
|
||||
name: Optional[str]
|
||||
|
|
@ -17,6 +18,7 @@ class CreateMyExtensionData(BaseModel):
|
|||
lnurlwithdrawamount: Optional[int]
|
||||
ticker: Optional[int]
|
||||
|
||||
|
||||
class MyExtension(BaseModel):
|
||||
id: str
|
||||
wallet: Optional[str]
|
||||
|
|
|
|||
7
tasks.py
7
tasks.py
|
|
@ -29,6 +29,7 @@ async def wait_for_paid_invoices():
|
|||
|
||||
# do somethhing when an invoice related top this extension is paid
|
||||
|
||||
|
||||
async def on_invoice_paid(payment: Payment) -> None:
|
||||
logger.debug("payment received for myextension extension")
|
||||
if payment.extra.get("tag") != "MyExtension":
|
||||
|
|
@ -42,9 +43,7 @@ async def on_invoice_paid(payment: Payment) -> None:
|
|||
total = myextension.total - payment.amount
|
||||
else:
|
||||
total = myextension.total + payment.amount
|
||||
data_to_update = {
|
||||
"total": total
|
||||
}
|
||||
data_to_update = {"total": total}
|
||||
|
||||
await update_myextension(myextension_id=myextension_id, **data_to_update)
|
||||
|
||||
|
|
@ -55,7 +54,7 @@ async def on_invoice_paid(payment: Payment) -> None:
|
|||
"name": myextension.name,
|
||||
"amount": payment.amount,
|
||||
"fee": payment.fee,
|
||||
"checking_id": payment.checking_id
|
||||
"checking_id": payment.checking_id,
|
||||
}
|
||||
|
||||
await websocketUpdater(myextension_id, str(some_payment_data))
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
<q-expansion-item
|
||||
group="extras"
|
||||
icon="swap_vertical_circle"
|
||||
label="API info"
|
||||
:content-inset-level="0.5"
|
||||
>
|
||||
<q-expansion-item group="extras" icon="swap_vertical_circle" label="API info" :content-inset-level="0.5">
|
||||
<q-btn flat label="Swagger API" type="a" href="../docs#/MyExtension"></q-btn>
|
||||
</q-expansion-item>
|
||||
|
|
@ -4,24 +4,10 @@
|
|||
<p>
|
||||
Some more info about my excellent extension.
|
||||
</p>
|
||||
<small
|
||||
>Created by
|
||||
<a
|
||||
class="text-secondary"
|
||||
href="https://github.com/benarc"
|
||||
target="_blank"
|
||||
>Ben Arc</a
|
||||
>.</small
|
||||
>
|
||||
<small
|
||||
>Repo
|
||||
<a
|
||||
class="text-secondary"
|
||||
href="https://github.com/lnbits/myextension"
|
||||
target="_blank"
|
||||
>MyExtension</a
|
||||
>.</small
|
||||
>
|
||||
<small>Created by
|
||||
<a class="text-secondary" href="https://github.com/benarc" target="_blank">Ben Arc</a>.</small>
|
||||
<small>Repo
|
||||
<a class="text-secondary" href="https://github.com/lnbits/myextension" target="_blank">MyExtension</a>.</small>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-expansion-item>
|
||||
|
|
@ -4,9 +4,7 @@
|
|||
<div class="col-12 col-md-8 col-lg-7 q-gutter-y-md">
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
<q-btn unelevated color="primary" @click="formDialog.show = true"
|
||||
>New MyExtension</q-btn
|
||||
>
|
||||
<q-btn unelevated color="primary" @click="formDialog.show = true">New MyExtension</q-btn>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
|
||||
|
|
@ -20,14 +18,8 @@
|
|||
<q-btn flat color="grey" @click="exportCSV">Export to CSV</q-btn>
|
||||
</div>
|
||||
</div>
|
||||
<q-table
|
||||
dense
|
||||
flat
|
||||
:data="temps"
|
||||
row-key="id"
|
||||
:columns="tempsTable.columns"
|
||||
:pagination.sync="tempsTable.pagination"
|
||||
>
|
||||
<q-table dense flat :data="temps" row-key="id" :columns="tempsTable.columns"
|
||||
:pagination.sync="tempsTable.pagination">
|
||||
<myextension v-slot:header="props">
|
||||
<q-tr :props="props">
|
||||
<q-th v-for="col in props.cols" :key="col.name" :props="props">
|
||||
|
|
@ -38,59 +30,26 @@
|
|||
|
||||
<template v-slot:body="props">
|
||||
<q-tr :props="props">
|
||||
<q-td
|
||||
v-for="col in props.cols"
|
||||
:key="col.name"
|
||||
:props="props"
|
||||
>
|
||||
<q-td v-for="col in props.cols" :key="col.name" :props="props">
|
||||
<div v-if="col.field == 'total'">${ col.value / 1000} sats</div>
|
||||
<div v-else>${ col.value }</div>
|
||||
</q-td>
|
||||
<q-td auto-width>
|
||||
<q-btn
|
||||
unelevated
|
||||
dense
|
||||
size="sm"
|
||||
icon="qr_code"
|
||||
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
|
||||
class="q-mr-sm"
|
||||
@click="openUrlDialog(props.row.id)"
|
||||
></q-btn></q-td>
|
||||
<q-btn unelevated dense size="sm" icon="qr_code" :color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
|
||||
class="q-mr-sm" @click="openUrlDialog(props.row.id)"></q-btn></q-td>
|
||||
<q-td auto-width>
|
||||
<q-btn
|
||||
unelevated
|
||||
dense
|
||||
size="sm"
|
||||
icon="launch"
|
||||
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
|
||||
type="a"
|
||||
:href="props.row.myextension"
|
||||
target="_blank"
|
||||
><q-tooltip>Open public page</q-tooltip></q-btn
|
||||
></q-td>
|
||||
<q-btn unelevated dense size="sm" icon="launch" :color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
|
||||
type="a" :href="props.row.myextension" target="_blank"><q-tooltip>Open public
|
||||
page</q-tooltip></q-btn></q-td>
|
||||
|
||||
<q-td>
|
||||
<q-btn
|
||||
flat
|
||||
dense
|
||||
size="xs"
|
||||
@click="updateMyExtensionForm(props.row.id)"
|
||||
icon="edit"
|
||||
color="light-blue"
|
||||
>
|
||||
<q-btn flat dense size="xs" @click="updateMyExtensionForm(props.row.id)" icon="edit" color="light-blue">
|
||||
<q-tooltip> Edit copilot </q-tooltip>
|
||||
</q-btn>
|
||||
</q-td>
|
||||
|
||||
<q-td>
|
||||
<q-btn
|
||||
flat
|
||||
dense
|
||||
size="xs"
|
||||
@click="deleteMyExtension(props.row.id)"
|
||||
icon="cancel"
|
||||
color="pink"
|
||||
>
|
||||
<q-btn flat dense size="xs" @click="deleteMyExtension(props.row.id)" icon="cancel" color="pink">
|
||||
<q-tooltip> Delete copilot </q-tooltip>
|
||||
</q-btn>
|
||||
</q-td>
|
||||
|
|
@ -107,7 +66,8 @@
|
|||
<q-card>
|
||||
<q-card-section>
|
||||
<h6 class="text-subtitle1 q-my-none">{{SITE_TITLE}} MyExtension extension</h6>
|
||||
<p>Simple extension you can use as a base for your own extension. <br/> Includes very simple LNURL-pay and LNURL-withdraw example.</p>
|
||||
<p>Simple extension you can use as a base for your own extension. <br /> Includes very simple LNURL-pay and
|
||||
LNURL-withdraw example.</p>
|
||||
</q-card-section>
|
||||
<q-card-section class="q-pa-none">
|
||||
<q-separator></q-separator>
|
||||
|
|
@ -123,54 +83,20 @@
|
|||
<q-dialog v-model="formDialog.show" position="top" @hide="closeFormDialog">
|
||||
<q-card class="q-pa-lg q-pt-xl" style="width: 500px">
|
||||
<q-form @submit="sendMyExtensionData" class="q-gutter-md">
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
v-model.trim="formDialog.data.name"
|
||||
label="Name"
|
||||
placeholder="Name for your record"
|
||||
></q-input>
|
||||
<q-select
|
||||
filled
|
||||
dense
|
||||
emit-value
|
||||
v-model="formDialog.data.wallet"
|
||||
:options="g.user.walletOptions"
|
||||
label="Wallet *"
|
||||
></q-select>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
type="number"
|
||||
v-model.trim="formDialog.data.lnurlwithdrawamount"
|
||||
label="LNURL-withdraw amount"
|
||||
></q-input>
|
||||
<q-input
|
||||
filled
|
||||
dense
|
||||
type="number"
|
||||
v-model.trim="formDialog.data.lnurlpayamount"
|
||||
label="LNURL-pay amount"
|
||||
></q-input>
|
||||
<q-input filled dense v-model.trim="formDialog.data.name" label="Name"
|
||||
placeholder="Name for your record"></q-input>
|
||||
<q-select filled dense emit-value v-model="formDialog.data.wallet" :options="g.user.walletOptions"
|
||||
label="Wallet *"></q-select>
|
||||
<q-input filled dense type="number" v-model.trim="formDialog.data.lnurlwithdrawamount"
|
||||
label="LNURL-withdraw amount"></q-input>
|
||||
<q-input filled dense type="number" v-model.trim="formDialog.data.lnurlpayamount"
|
||||
label="LNURL-pay amount"></q-input>
|
||||
<div class="row q-mt-lg">
|
||||
<q-btn
|
||||
v-if="formDialog.data.id"
|
||||
unelevated
|
||||
color="primary"
|
||||
type="submit"
|
||||
>Update MyExtension</q-btn
|
||||
>
|
||||
<q-btn
|
||||
v-else
|
||||
unelevated
|
||||
color="primary"
|
||||
<q-btn v-if="formDialog.data.id" unelevated color="primary" type="submit">Update MyExtension</q-btn>
|
||||
<q-btn v-else unelevated color="primary"
|
||||
:disable="formDialog.data.name == null || formDialog.data.wallet == null || formDialog.data.lnurlwithdrawamount == null || formDialog.data.lnurlpayamount == null"
|
||||
type="submit"
|
||||
>Create MyExtension</q-btn
|
||||
>
|
||||
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
|
||||
>Cancel</q-btn
|
||||
>
|
||||
type="submit">Create MyExtension</q-btn>
|
||||
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Cancel</q-btn>
|
||||
</div>
|
||||
</q-form>
|
||||
</q-card>
|
||||
|
|
@ -181,9 +107,7 @@
|
|||
|
||||
|
||||
<q-responsive :ratio="1" class="q-mx-xl q-mb-md">
|
||||
<lnbits-qrcode
|
||||
:value="qrValue"
|
||||
></lnbits-qrcode>
|
||||
<lnbits-qrcode :value="qrValue"></lnbits-qrcode>
|
||||
</q-responsive>
|
||||
<center><q-btn label="copy" @click="copyText(qrValue)"></q-btn>
|
||||
</center>
|
||||
|
|
@ -202,7 +126,8 @@
|
|||
<div class="col q-pl-md">
|
||||
<q-input filled bottom-slots dense v-model="invoiceAmount">
|
||||
<template v-slot:append>
|
||||
<q-btn round @click="createInvoice(urlDialog.data.wallet, urlDialog.data.id)" color="primary" flat icon="add_circle" />
|
||||
<q-btn round @click="createInvoice(urlDialog.data.wallet, urlDialog.data.id)" color="primary" flat
|
||||
icon="add_circle" />
|
||||
</template>
|
||||
<template v-slot:hint>
|
||||
Create an invoice
|
||||
|
|
@ -242,15 +167,15 @@
|
|||
temps: [],
|
||||
tempsTable: {
|
||||
columns: [
|
||||
{name: 'id', align: 'left', label: 'ID', field: 'id'},
|
||||
{name: 'name', align: 'left', label: 'Name', field: 'name'},
|
||||
{ name: 'id', align: 'left', label: 'ID', field: 'id' },
|
||||
{ name: 'name', align: 'left', label: 'Name', field: 'name' },
|
||||
{
|
||||
name: 'wallet',
|
||||
align: 'left',
|
||||
label: 'Wallet',
|
||||
field: 'wallet'
|
||||
},
|
||||
{name: 'total', align: 'left', label: 'Total sent/received', field: 'total'},
|
||||
{ name: 'total', align: 'left', label: 'Total sent/received', field: 'total' },
|
||||
],
|
||||
pagination: {
|
||||
rowsPerPage: 10
|
||||
|
|
@ -317,7 +242,7 @@
|
|||
}
|
||||
},
|
||||
updateMyExtensionForm(tempId) {
|
||||
const myextension = _.findWhere(this.temps, {id: tempId})
|
||||
const myextension = _.findWhere(this.temps, { id: tempId })
|
||||
this.formDialog.data = {
|
||||
...myextension
|
||||
}
|
||||
|
|
@ -361,7 +286,7 @@
|
|||
},
|
||||
deleteMyExtension: function (tempId) {
|
||||
var self = this
|
||||
var myextension = _.findWhere(this.temps, {id: tempId})
|
||||
var myextension = _.findWhere(this.temps, { id: tempId })
|
||||
|
||||
LNbits.utils
|
||||
.confirmDialog('Are you sure you want to delete this MyExtension?')
|
||||
|
|
@ -370,7 +295,7 @@
|
|||
.request(
|
||||
'DELETE',
|
||||
'/myextension/api/v1/temps/' + tempId,
|
||||
_.findWhere(self.g.user.wallets, {id: myextension.wallet}).adminkey
|
||||
_.findWhere(self.g.user.wallets, { id: myextension.wallet }).adminkey
|
||||
)
|
||||
.then(function (response) {
|
||||
self.temps = _.reject(self.temps, function (obj) {
|
||||
|
|
@ -386,17 +311,17 @@
|
|||
LNbits.utils.exportCSV(this.tempsTable.columns, this.temps)
|
||||
},
|
||||
itemsArray(tempId) {
|
||||
const myextension = _.findWhere(this.temps, {id: tempId})
|
||||
const myextension = _.findWhere(this.temps, { id: tempId })
|
||||
return [...myextension.itemsMap.values()]
|
||||
},
|
||||
itemFormatPrice(price, id) {
|
||||
const myextension = id.split(':')[0]
|
||||
const currency = _.findWhere(this.temps, {id: myextension}).currency
|
||||
const currency = _.findWhere(this.temps, { id: myextension }).currency
|
||||
return LNbits.utils.formatCurrency(Number(price).toFixed(2), currency)
|
||||
},
|
||||
openformDialog(id) {
|
||||
const [tempId, itemId] = id.split(':')
|
||||
const myextension = _.findWhere(this.temps, {id: tempId})
|
||||
const myextension = _.findWhere(this.temps, { id: tempId })
|
||||
if (itemId) {
|
||||
const item = myextension.itemsMap.get(id)
|
||||
this.formDialog.data = {
|
||||
|
|
@ -419,7 +344,7 @@
|
|||
}
|
||||
},
|
||||
openUrlDialog(id) {
|
||||
this.urlDialog.data = _.findWhere(this.temps, {id})
|
||||
this.urlDialog.data = _.findWhere(this.temps, { id })
|
||||
this.qrValue = this.urlDialog.data.lnurlpay
|
||||
console.log(this.urlDialog.data.id)
|
||||
this.connectWebocket(this.urlDialog.data.id)
|
||||
|
|
@ -486,7 +411,7 @@
|
|||
}
|
||||
frame()
|
||||
},
|
||||
connectWebocket(id){
|
||||
connectWebocket(id) {
|
||||
//////////////////////////////////////////////////
|
||||
///wait for pay action to happen and do a thing////
|
||||
///////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -6,18 +6,12 @@
|
|||
<div class="text-center">
|
||||
<a class="text-secondary" href="lightning:{{ lnurl }}">
|
||||
<q-responsive :ratio="1" class="q-mx-md">
|
||||
<qrcode
|
||||
:value="qrValue"
|
||||
:options="{width: 800}"
|
||||
class="rounded-borders"
|
||||
></qrcode>
|
||||
<qrcode :value="qrValue" :options="{width: 800}" class="rounded-borders"></qrcode>
|
||||
</q-responsive>
|
||||
</a>
|
||||
</div>
|
||||
<div class="row q-mt-lg q-gutter-sm">
|
||||
<q-btn outline color="grey" @click="copyText(qrValue)"
|
||||
>Copy LNURL </q-btn
|
||||
>
|
||||
<q-btn outline color="grey" @click="copyText(qrValue)">Copy LNURL </q-btn>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
|
|
@ -42,7 +36,7 @@
|
|||
Moat extensions have a public page that can be shared
|
||||
(this page will still be accessible even if you have restricted
|
||||
access to your LNbits install).
|
||||
<br/>
|
||||
<br />
|
||||
In this example when a user pays the LNURLpay it triggers an event via a websocket waiting for the payment.
|
||||
</p>.</p>
|
||||
</q-card-section>
|
||||
|
|
@ -102,7 +96,7 @@
|
|||
}
|
||||
frame()
|
||||
},
|
||||
connectWebocket(id){
|
||||
connectWebocket(id) {
|
||||
//////////////////////////////////////////////////
|
||||
///wait for pay action to happen and do a thing////
|
||||
///////////////////////////////////////////////////
|
||||
|
|
|
|||
5
views.py
5
views.py
|
|
@ -22,6 +22,7 @@ temps = Jinja2Templates(directory="temps")
|
|||
|
||||
# Backend admin page
|
||||
|
||||
|
||||
@myextension_ext.get("/", response_class=HTMLResponse)
|
||||
async def index(request: Request, user: User = Depends(check_user_exists)):
|
||||
return myextension_renderer().TemplateResponse(
|
||||
|
|
@ -31,6 +32,7 @@ async def index(request: Request, user: User = Depends(check_user_exists)):
|
|||
|
||||
# Frontend shareable page
|
||||
|
||||
|
||||
@myextension_ext.get("/{myextension_id}")
|
||||
async def myextension(request: Request, myextension_id):
|
||||
myextension = await get_myextension(myextension_id, request)
|
||||
|
|
@ -52,9 +54,10 @@ async def myextension(request: Request, myextension_id):
|
|||
|
||||
# Manifest for public page, customise or remove manifest completely
|
||||
|
||||
|
||||
@myextension_ext.get("/manifest/{myextension_id}.webmanifest")
|
||||
async def manifest(myextension_id: str):
|
||||
myextension= await get_myextension(myextension_id)
|
||||
myextension = await get_myextension(myextension_id)
|
||||
if not myextension:
|
||||
raise HTTPException(
|
||||
status_code=HTTPStatus.NOT_FOUND, detail="MyExtension does not exist."
|
||||
|
|
|
|||
47
views_api.py
47
views_api.py
|
|
@ -25,7 +25,7 @@ from .crud import (
|
|||
update_myextension,
|
||||
delete_myextension,
|
||||
get_myextension,
|
||||
get_myextensions
|
||||
get_myextensions,
|
||||
)
|
||||
from .models import CreateMyExtensionData
|
||||
|
||||
|
|
@ -36,25 +36,29 @@ from .models import CreateMyExtensionData
|
|||
|
||||
## Get all the records belonging to the user
|
||||
|
||||
|
||||
@myextension_ext.get("/api/v1/temps", status_code=HTTPStatus.OK)
|
||||
async def api_myextensions(
|
||||
req: Request, all_wallets:
|
||||
bool = Query(False),
|
||||
wallet: WalletTypeInfo = Depends(get_key_type)
|
||||
req: Request,
|
||||
all_wallets: bool = Query(False),
|
||||
wallet: WalletTypeInfo = Depends(get_key_type),
|
||||
):
|
||||
wallet_ids = [wallet.wallet.id]
|
||||
if all_wallets:
|
||||
user = await get_user(wallet.wallet.user)
|
||||
wallet_ids = user.wallet_ids if user else []
|
||||
return [myextension.dict() for myextension in await get_myextensions(wallet_ids, req)]
|
||||
return [
|
||||
myextension.dict() for myextension in await get_myextensions(wallet_ids, req)
|
||||
]
|
||||
|
||||
|
||||
## Get a single record
|
||||
|
||||
|
||||
@myextension_ext.get("/api/v1/temps/{myextension_id}", status_code=HTTPStatus.OK)
|
||||
async def api_myextension(
|
||||
req: Request,
|
||||
myextension_id: str,
|
||||
WalletTypeInfo = Depends(get_key_type)):
|
||||
req: Request, myextension_id: str, WalletTypeInfo=Depends(get_key_type)
|
||||
):
|
||||
myextension = await get_myextension(myextension_id, req)
|
||||
if not myextension:
|
||||
raise HTTPException(
|
||||
|
|
@ -62,8 +66,10 @@ async def api_myextension(
|
|||
)
|
||||
return myextension.dict()
|
||||
|
||||
|
||||
## update a record
|
||||
|
||||
|
||||
@myextension_ext.put("/api/v1/temps/{myextension_id}")
|
||||
async def api_myextension_update(
|
||||
req: Request,
|
||||
|
|
@ -79,25 +85,33 @@ async def api_myextension_update(
|
|||
assert myextension, "MyExtension couldn't be retrieved"
|
||||
|
||||
if wallet.wallet.id != myextension.wallet:
|
||||
raise HTTPException(status_code=HTTPStatus.FORBIDDEN, detail="Not your MyExtension.")
|
||||
myextension = await update_myextension(myextension_id=myextension_id, **data.dict(), req=req)
|
||||
raise HTTPException(
|
||||
status_code=HTTPStatus.FORBIDDEN, detail="Not your MyExtension."
|
||||
)
|
||||
myextension = await update_myextension(
|
||||
myextension_id=myextension_id, **data.dict(), req=req
|
||||
)
|
||||
return myextension.dict()
|
||||
|
||||
|
||||
## Create a new record
|
||||
|
||||
|
||||
@myextension_ext.post("/api/v1/temps", status_code=HTTPStatus.CREATED)
|
||||
async def api_myextension_create(
|
||||
req: Request,
|
||||
data: CreateMyExtensionData,
|
||||
wallet: WalletTypeInfo = Depends(get_key_type)
|
||||
wallet: WalletTypeInfo = Depends(get_key_type),
|
||||
):
|
||||
myextension = await create_myextension(wallet_id=wallet.wallet.id, data=data, req=req)
|
||||
myextension = await create_myextension(
|
||||
wallet_id=wallet.wallet.id, data=data, req=req
|
||||
)
|
||||
return myextension.dict()
|
||||
|
||||
|
||||
## Delete a record
|
||||
|
||||
|
||||
@myextension_ext.delete("/api/v1/temps/{myextension_id}")
|
||||
async def api_myextension_delete(
|
||||
myextension_id: str, wallet: WalletTypeInfo = Depends(require_admin_key)
|
||||
|
|
@ -110,7 +124,9 @@ async def api_myextension_delete(
|
|||
)
|
||||
|
||||
if myextension.wallet != wallet.wallet.id:
|
||||
raise HTTPException(status_code=HTTPStatus.FORBIDDEN, detail="Not your MyExtension.")
|
||||
raise HTTPException(
|
||||
status_code=HTTPStatus.FORBIDDEN, detail="Not your MyExtension."
|
||||
)
|
||||
|
||||
await delete_myextension(myextension_id)
|
||||
return "", HTTPStatus.NO_CONTENT
|
||||
|
|
@ -120,7 +136,10 @@ async def api_myextension_delete(
|
|||
|
||||
## This endpoint creates a payment
|
||||
|
||||
@myextension_ext.post("/api/v1/temps/payment/{myextension_id}", status_code=HTTPStatus.CREATED)
|
||||
|
||||
@myextension_ext.post(
|
||||
"/api/v1/temps/payment/{myextension_id}", status_code=HTTPStatus.CREATED
|
||||
)
|
||||
async def api_tpos_create_invoice(
|
||||
myextension_id: str, amount: int = Query(..., ge=1), memo: str = ""
|
||||
) -> dict:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue