feat: update to v1.0.0

This commit is contained in:
dni ⚡ 2024-10-21 14:38:03 +02:00
parent 42b5edaf5d
commit 48b1069a9f
12 changed files with 1447 additions and 1370 deletions

View file

@ -2,7 +2,7 @@
"name": "MyExtension", "name": "MyExtension",
"short_description": "Minimal extension to build on", "short_description": "Minimal extension to build on",
"tile": "/myextension/static/image/myextension.png", "tile": "/myextension/static/image/myextension.png",
"min_lnbits_version": "0.12.5", "min_lnbits_version": "1.0.0",
"contributors": [ "contributors": [
{ {
"name": "Alan Bits", "name": "Alan Bits",

33
crud.py
View file

@ -1,7 +1,6 @@
from typing import Optional, Union from typing import Optional, Union
from lnbits.db import Database from lnbits.db import Database
from lnbits.helpers import insert_query, update_query
from .models import MyExtension from .models import MyExtension
@ -10,10 +9,7 @@ table_name = "myextension.maintable"
async def create_myextension(data: MyExtension) -> MyExtension: async def create_myextension(data: MyExtension) -> MyExtension:
await db.execute( await db.insert(table_name, data)
insert_query(table_name, data),
(*data.dict().values(),),
)
return data return data
# this is how we used to do it # this is how we used to do it
@ -38,34 +34,27 @@ async def create_myextension(data: MyExtension) -> MyExtension:
async def get_myextension(myextension_id: str) -> Optional[MyExtension]: async def get_myextension(myextension_id: str) -> Optional[MyExtension]:
row = await db.fetchone( return await db.fetchone(
f"SELECT * FROM {table_name} WHERE id = ?", (myextension_id,) f"SELECT * FROM {table_name} WHERE id = :id",
{"id": myextension_id},
MyExtension,
) )
return MyExtension(**row) if row else None
async def get_myextensions(wallet_ids: Union[str, list[str]]) -> list[MyExtension]: async def get_myextensions(wallet_ids: Union[str, list[str]]) -> list[MyExtension]:
if isinstance(wallet_ids, str): if isinstance(wallet_ids, str):
wallet_ids = [wallet_ids] wallet_ids = [wallet_ids]
q = ",".join([f"'{wallet_id}'" for wallet_id in wallet_ids])
q = ",".join(["?"] * len(wallet_ids)) return await db.fetchall(
rows = await db.fetchall( f"SELECT * FROM {table_name} WHERE wallet IN ({q})", model=MyExtension
f"SELECT * FROM {table_name} WHERE wallet IN ({q})", (*wallet_ids,)
) )
return [MyExtension(**row) for row in rows]
async def update_myextension(data: MyExtension) -> MyExtension: async def update_myextension(data: MyExtension) -> MyExtension:
await db.execute( await db.update(table_name, data)
update_query(table_name, data),
(
*data.dict().values(),
data.id,
),
)
return data return data
# this is how we used to do it
# this is how we used to do it
# q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) # q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
# await db.execute( # await db.execute(
# f"UPDATE myextension.maintable SET {q} WHERE id = ?", # f"UPDATE myextension.maintable SET {q} WHERE id = ?",
@ -74,4 +63,4 @@ async def update_myextension(data: MyExtension) -> MyExtension:
async def delete_myextension(myextension_id: str) -> None: async def delete_myextension(myextension_id: str) -> None:
await db.execute(f"DELETE FROM {table_name} WHERE id = ?", (myextension_id,)) await db.execute(f"DELETE FROM {table_name} WHERE id = :id", {"id": myextension_id})

View file

@ -21,3 +21,15 @@ async def m001_initial(db):
); );
""" """
) )
async def m002_add_timestamp(db):
"""
Add timestamp to templates table.
"""
await db.execute(
f"""
ALTER TABLE myextension.maintable
ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT {db.timestamp_now};
"""
)

View file

@ -1,5 +1,6 @@
# Data models for your extension # Data models for your extension
from datetime import datetime, timezone
from typing import Optional from typing import Optional
from pydantic import BaseModel from pydantic import BaseModel
@ -22,3 +23,4 @@ class MyExtension(BaseModel):
total: int total: int
lnurlpay: Optional[str] lnurlpay: Optional[str]
lnurlwithdraw: Optional[str] lnurlwithdraw: Optional[str]
created_at: datetime = datetime.now(timezone.utc)

2115
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,7 @@ authors = ["benarc", "dni <dni@lnbits.com>"]
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.10 | ^3.9" python = "^3.10 | ^3.9"
lnbits = "*" lnbits = {version = "*", allow-prereleases = true}
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
black = "^24.3.0" black = "^24.3.0"

280
static/js/index.js Normal file
View file

@ -0,0 +1,280 @@
///////////////////////////////////////////////////
//////////an object we can update with data////////
///////////////////////////////////////////////////
const mapMyExtension = obj => {
obj.date = Quasar.date.formatDate(
new Date(obj.created_at),
'YYYY-MM-DD HH:mm'
)
obj.myextension = ['/myextension/', obj.id].join('')
return obj
}
window.app = Vue.createApp({
el: '#vue',
mixins: [windowMixin],
delimiters: ['${', '}'],
data() {
return {
invoiceAmount: 10,
qrValue: 'lnurlpay',
myex: [],
myexTable: {
columns: [
{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'
}
],
pagination: {
rowsPerPage: 10
}
},
formDialog: {
show: false,
data: {},
advanced: {}
},
urlDialog: {
show: false,
data: {}
}
}
},
///////////////////////////////////////////////////
////////////////METHODS FUNCTIONS//////////////////
///////////////////////////////////////////////////
methods: {
closeFormDialog() {
this.formDialog.show = false
this.formDialog.data = {}
},
getMyExtensions() {
LNbits.api
.request(
'GET',
'/myextension/api/v1/myex?all_wallets=true',
this.g.user.wallets[0].inkey
)
.then(response => {
this.myex = response.data.map(obj => {
return mapMyExtension(obj)
})
})
},
sendMyExtensionData() {
const data = {
name: this.formDialog.data.name,
lnurlwithdrawamount: this.formDialog.data.lnurlwithdrawamount,
lnurlpayamount: this.formDialog.data.lnurlpayamount
}
const wallet = _.findWhere(this.g.user.wallets, {
id: this.formDialog.data.wallet
})
if (this.formDialog.data.id) {
data.id = this.formDialog.data.id
data.wallet = wallet.id
data.total = this.formDialog.data.total
this.updateMyExtension(wallet, data)
} else {
this.createMyExtension(wallet, data)
}
},
updateMyExtensionForm(tempId) {
const myextension = _.findWhere(this.myex, {id: tempId})
this.formDialog.data = {
...myextension
}
if (this.formDialog.data.tip_wallet != '') {
this.formDialog.advanced.tips = true
}
if (this.formDialog.data.withdrawlimit >= 1) {
this.formDialog.advanced.otc = true
}
this.formDialog.show = true
},
createMyExtension(wallet, data) {
LNbits.api
.request('POST', '/myextension/api/v1/myex', wallet.adminkey, data)
.then(response => {
this.myex.push(mapMyExtension(response.data))
this.closeFormDialog()
})
.catch(error => {
LNbits.utils.notifyApiError(error)
})
},
updateMyExtension(wallet, data) {
LNbits.api
.request(
'PUT',
`/myextension/api/v1/myex/${data.id}`,
wallet.adminkey,
data
)
.then(response => {
this.myex = _.reject(this.myex, obj => {
return obj.id == data.id
})
this.myex.push(mapMyExtension(response.data))
this.closeFormDialog()
})
.catch(error => {
LNbits.utils.notifyApiError(error)
})
},
deleteMyExtension(tempId) {
const myextension = _.findWhere(this.myex, {id: tempId})
LNbits.utils
.confirmDialog('Are you sure you want to delete this MyExtension?')
.onOk(() => {
LNbits.api
.request(
'DELETE',
'/myextension/api/v1/myex/' + tempId,
_.findWhere(this.g.user.wallets, {id: myextension.wallet})
.adminkey
)
.then(response => {
this.myex = _.reject(this.myex, obj => {
return obj.id == tempId
})
})
.catch(LNbits.utils.notifyApiError)
})
},
exportCSV() {
LNbits.utils.exportCSV(this.myexTable.columns, this.myex)
},
itemsArray(tempId) {
const myextension = _.findWhere(this.myex, {id: tempId})
return [...myextension.itemsMap.values()]
},
openformDialog(id) {
const [tempId, itemId] = id.split(':')
const myextension = _.findWhere(this.myex, {id: tempId})
if (itemId) {
const item = myextension.itemsMap.get(id)
this.formDialog.data = {
...item,
myextension: tempId
}
} else {
this.formDialog.data.myextension = tempId
}
this.formDialog.data.currency = myextension.currency
this.formDialog.show = true
},
closeformDialog() {
this.formDialog.show = false
this.formDialog.data = {}
},
openUrlDialog(id) {
this.urlDialog.data = _.findWhere(this.myex, {id})
this.qrValue = this.urlDialog.data.lnurlpay
console.log(this.urlDialog.data.id)
this.connectWebocket(this.urlDialog.data.id)
this.urlDialog.show = true
},
createInvoice(walletId, myextensionId) {
///////////////////////////////////////////////////
///Simple call to the api to create an invoice/////
///////////////////////////////////////////////////
console.log(walletId)
const wallet = _.findWhere(this.g.user.wallets, {
id: walletId
})
const dataToSend = {
out: false,
amount: this.invoiceAmount,
memo: 'Invoice created by MyExtension',
extra: {
tag: 'MyExtension',
myextensionId: myextensionId
}
}
LNbits.api
.request('POST', `/api/v1/payments`, wallet.inkey, dataToSend)
.then(response => {
this.qrValue = response.data.payment_request
})
.catch(error => {
LNbits.utils.notifyApiError(error)
})
},
makeItRain() {
document.getElementById('vue').disabled = true
const end = Date.now() + 2 * 1000
const colors = ['#FFD700', '#ffffff']
confetti({
particleCount: 2,
angle: 60,
spread: 55,
origin: {x: 0},
colors: colors,
zIndex: 999999
})
confetti({
particleCount: 2,
angle: 120,
spread: 55,
origin: {x: 1},
colors: colors,
zIndex: 999999
})
if (Date.now() < end) {
requestAnimationFrame(frame)
} else {
document.getElementById('vue').disabled = false
}
},
connectWebocket(wallet_id) {
//////////////////////////////////////////////////
///wait for pay action to happen and do a thing////
///////////////////////////////////////////////////
if (location.protocol !== 'http:') {
localUrl =
'wss://' +
document.domain +
':' +
location.port +
'/api/v1/ws/' +
wallet_id
} else {
localUrl =
'ws://' +
document.domain +
':' +
location.port +
'/api/v1/ws/' +
wallet_id
}
this.connection = new WebSocket(localUrl)
this.connection.onmessage = e => {
this.makeItRain()
}
}
},
///////////////////////////////////////////////////
//////LIFECYCLE FUNCTIONS RUNNING ON PAGE LOAD/////
///////////////////////////////////////////////////
created() {
if (this.g.user.wallets.length) {
this.getMyExtensions()
}
}
})

View file

@ -2,7 +2,6 @@ import asyncio
from lnbits.core.models import Payment from lnbits.core.models import Payment
from lnbits.core.services import websocket_updater from lnbits.core.services import websocket_updater
from lnbits.helpers import get_current_extension_name
from lnbits.tasks import register_invoice_listener from lnbits.tasks import register_invoice_listener
from .crud import get_myextension, update_myextension from .crud import get_myextension, update_myextension
@ -16,7 +15,7 @@ from .crud import get_myextension, update_myextension
async def wait_for_paid_invoices(): async def wait_for_paid_invoices():
invoice_queue = asyncio.Queue() invoice_queue = asyncio.Queue()
register_invoice_listener(invoice_queue, get_current_extension_name()) register_invoice_listener(invoice_queue, "ext_myextension_invoice_listener")
while True: while True:
payment = await invoice_queue.get() payment = await invoice_queue.get()
await on_invoice_paid(payment) await on_invoice_paid(payment)

View file

@ -3,7 +3,9 @@
<!--/////////////////////////////////////////////////--> <!--/////////////////////////////////////////////////-->
{% extends "base.html" %} {% from "macros.jinja" import window_vars with context {% extends "base.html" %} {% from "macros.jinja" import window_vars with context
%} {% block page %} %} {% block scripts %} {{ window_vars(user) }}
<script src="{{ static_url_for('myextension/static', path='js/index.js') }}"></script>
{% endblock %} {% block page %}
<div class="row q-col-gutter-md" id="makeItRain"> <div class="row q-col-gutter-md" id="makeItRain">
<div class="col-12 col-md-8 col-lg-7 q-gutter-y-md"> <div class="col-12 col-md-8 col-lg-7 q-gutter-y-md">
<q-card> <q-card>
@ -27,10 +29,10 @@
<q-table <q-table
dense dense
flat flat
:data="myex" :rows="myex"
row-key="id" row-key="id"
:columns="myexTable.columns" :columns="myexTable.columns"
:pagination.sync="myexTable.pagination" v-model:pagination="myexTable.pagination"
> >
<myextension v-slot:header="props"> <myextension v-slot:header="props">
<q-tr :props="props"> <q-tr :props="props">
@ -236,296 +238,4 @@
</q-card> </q-card>
</q-dialog> </q-dialog>
</div> </div>
{% endblock %} {% block scripts %} {{ window_vars(user) }}
<script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.4.0/dist/confetti.browser.min.js"></script>
<script>
///////////////////////////////////////////////////
//////////an object we can update with data////////
///////////////////////////////////////////////////
const mapMyExtension = obj => {
obj.date = Quasar.utils.date.formatDate(
new Date(obj.time * 1000),
'YYYY-MM-DD HH:mm'
)
obj.myextension = ['/myextension/', obj.id].join('')
return obj
}
new Vue({
el: '#vue',
mixins: [windowMixin],
delimiters: ['${', '}'],
data: function () {
return {
invoiceAmount: 10,
qrValue: 'lnurlpay',
myex: [],
myexTable: {
columns: [
{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'
}
],
pagination: {
rowsPerPage: 10
}
},
formDialog: {
show: false,
data: {},
advanced: {}
},
urlDialog: {
show: false,
data: {}
}
}
},
///////////////////////////////////////////////////
////////////////METHODS FUNCTIONS//////////////////
///////////////////////////////////////////////////
methods: {
closeFormDialog() {
this.formDialog.show = false
this.formDialog.data = {}
},
getMyExtensions: function () {
var self = this
LNbits.api
.request(
'GET',
'/myextension/api/v1/myex?all_wallets=true',
this.g.user.wallets[0].inkey
)
.then(function (response) {
self.myex = response.data.map(function (obj) {
return mapMyExtension(obj)
})
})
},
sendMyExtensionData() {
const data = {
name: this.formDialog.data.name,
lnurlwithdrawamount: this.formDialog.data.lnurlwithdrawamount,
lnurlpayamount: this.formDialog.data.lnurlpayamount
}
const wallet = _.findWhere(this.g.user.wallets, {
id: this.formDialog.data.wallet
})
if (this.formDialog.data.id) {
data.id = this.formDialog.data.id
data.wallet = wallet.id
data.total = this.formDialog.data.total
this.updateMyExtension(wallet, data)
} else {
this.createMyExtension(wallet, data)
}
},
updateMyExtensionForm(tempId) {
const myextension = _.findWhere(this.myex, {id: tempId})
this.formDialog.data = {
...myextension
}
if (this.formDialog.data.tip_wallet != '') {
this.formDialog.advanced.tips = true
}
if (this.formDialog.data.withdrawlimit >= 1) {
this.formDialog.advanced.otc = true
}
this.formDialog.show = true
},
createMyExtension(wallet, data) {
LNbits.api
.request('POST', '/myextension/api/v1/myex', wallet.adminkey, data)
.then(response => {
this.myex.push(mapMyExtension(response.data))
this.closeFormDialog()
})
.catch(error => {
LNbits.utils.notifyApiError(error)
})
},
updateMyExtension(wallet, data) {
LNbits.api
.request(
'PUT',
`/myextension/api/v1/myex/${data.id}`,
wallet.adminkey,
data
)
.then(response => {
this.myex = _.reject(this.myex, obj => {
return obj.id == data.id
})
this.myex.push(mapMyExtension(response.data))
this.closeFormDialog()
})
.catch(error => {
LNbits.utils.notifyApiError(error)
})
},
deleteMyExtension: function (tempId) {
var self = this
var myextension = _.findWhere(this.myex, {id: tempId})
LNbits.utils
.confirmDialog('Are you sure you want to delete this MyExtension?')
.onOk(function () {
LNbits.api
.request(
'DELETE',
'/myextension/api/v1/myex/' + tempId,
_.findWhere(self.g.user.wallets, {id: myextension.wallet})
.adminkey
)
.then(function (response) {
self.myex = _.reject(self.myex, function (obj) {
return obj.id == tempId
})
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
})
})
},
exportCSV: function () {
LNbits.utils.exportCSV(this.myexTable.columns, this.myex)
},
itemsArray(tempId) {
const myextension = _.findWhere(this.myex, {id: tempId})
return [...myextension.itemsMap.values()]
},
openformDialog(id) {
const [tempId, itemId] = id.split(':')
const myextension = _.findWhere(this.myex, {id: tempId})
if (itemId) {
const item = myextension.itemsMap.get(id)
this.formDialog.data = {
...item,
myextension: tempId
}
} else {
this.formDialog.data.myextension = tempId
}
this.formDialog.data.currency = myextension.currency
this.formDialog.show = true
},
closeformDialog() {
this.formDialog.show = false
this.formDialog.data = {}
},
openUrlDialog(id) {
this.urlDialog.data = _.findWhere(this.myex, {id})
this.qrValue = this.urlDialog.data.lnurlpay
console.log(this.urlDialog.data.id)
this.connectWebocket(this.urlDialog.data.id)
this.urlDialog.show = true
},
createInvoice(walletId, myextensionId) {
///////////////////////////////////////////////////
///Simple call to the api to create an invoice/////
///////////////////////////////////////////////////
console.log(walletId)
const wallet = _.findWhere(this.g.user.wallets, {
id: walletId
})
const dataToSend = {
out: false,
amount: this.invoiceAmount,
memo: 'Invoice created by MyExtension',
extra: {
tag: 'MyExtension',
myextensionId: myextensionId
}
}
LNbits.api
.request('POST', `/api/v1/payments`, wallet.inkey, dataToSend)
.then(response => {
this.qrValue = response.data.payment_request
})
.catch(error => {
LNbits.utils.notifyApiError(error)
})
},
makeItRain() {
document.getElementById('vue').disabled = true
var end = Date.now() + 2 * 1000
var colors = ['#FFD700', '#ffffff']
function frame() {
confetti({
particleCount: 2,
angle: 60,
spread: 55,
origin: {x: 0},
colors: colors,
zIndex: 999999
})
confetti({
particleCount: 2,
angle: 120,
spread: 55,
origin: {x: 1},
colors: colors,
zIndex: 999999
})
if (Date.now() < end) {
requestAnimationFrame(frame)
} else {
document.getElementById('vue').disabled = false
}
}
frame()
},
connectWebocket(wallet_id) {
//////////////////////////////////////////////////
///wait for pay action to happen and do a thing////
///////////////////////////////////////////////////
self = this
if (location.protocol !== 'http:') {
localUrl =
'wss://' +
document.domain +
':' +
location.port +
'/api/v1/ws/' +
wallet_id
} else {
localUrl =
'ws://' +
document.domain +
':' +
location.port +
'/api/v1/ws/' +
wallet_id
}
this.connection = new WebSocket(localUrl)
this.connection.onmessage = function (e) {
self.makeItRain()
}
}
},
///////////////////////////////////////////////////
//////LIFECYCLE FUNCTIONS RUNNING ON PAGE LOAD/////
///////////////////////////////////////////////////
created: function () {
if (this.g.user.wallets.length) {
this.getMyExtensions()
}
}
})
</script>
{% endblock %} {% endblock %}

View file

@ -1,12 +1,11 @@
from http import HTTPStatus from http import HTTPStatus
from fastapi import APIRouter, Depends, Request from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import HTMLResponse
from lnbits.core.models import User from lnbits.core.models import User
from lnbits.decorators import check_user_exists from lnbits.decorators import check_user_exists
from lnbits.helpers import template_renderer from lnbits.helpers import template_renderer
from lnbits.settings import settings from lnbits.settings import settings
from starlette.exceptions import HTTPException
from starlette.responses import HTMLResponse
from .crud import get_myextension from .crud import get_myextension
@ -28,7 +27,7 @@ def myextension_renderer():
@myextension_generic_router.get("/", response_class=HTMLResponse) @myextension_generic_router.get("/", response_class=HTMLResponse)
async def index(request: Request, user: User = Depends(check_user_exists)): async def index(request: Request, user: User = Depends(check_user_exists)):
return myextension_renderer().TemplateResponse( return myextension_renderer().TemplateResponse(
"myextension/index.html", {"request": request, "user": user.dict()} "myextension/index.html", {"request": request, "user": user.json()}
) )

View file

@ -5,7 +5,6 @@ from lnbits.core.crud import get_user
from lnbits.core.models import WalletTypeInfo from lnbits.core.models import WalletTypeInfo
from lnbits.core.services import create_invoice from lnbits.core.services import create_invoice
from lnbits.decorators import ( from lnbits.decorators import (
get_key_type,
require_admin_key, require_admin_key,
require_invoice_key, require_invoice_key,
) )
@ -32,16 +31,16 @@ myextension_api_router = APIRouter()
## Get all the records belonging to the user ## Get all the records belonging to the user
@myextension_api_router.get("/api/v1/myex", status_code=HTTPStatus.OK) @myextension_api_router.get("/api/v1/myex")
async def api_myextensions( async def api_myextensions(
all_wallets: bool = Query(False), all_wallets: bool = Query(False),
wallet: WalletTypeInfo = Depends(get_key_type), key_info: WalletTypeInfo = Depends(require_invoice_key),
): ) -> list[MyExtension]:
wallet_ids = [wallet.wallet.id] wallet_ids = [key_info.wallet.id]
if all_wallets: if all_wallets:
user = await get_user(wallet.wallet.user) user = await get_user(key_info.wallet.user)
wallet_ids = user.wallet_ids if user else [] wallet_ids = user.wallet_ids if user else []
return [myextension.dict() for myextension in await get_myextensions(wallet_ids)] return await get_myextensions(wallet_ids)
## Get a single record ## Get a single record
@ -49,16 +48,15 @@ async def api_myextensions(
@myextension_api_router.get( @myextension_api_router.get(
"/api/v1/myex/{myextension_id}", "/api/v1/myex/{myextension_id}",
status_code=HTTPStatus.OK,
dependencies=[Depends(require_invoice_key)], dependencies=[Depends(require_invoice_key)],
) )
async def api_myextension(myextension_id: str): async def api_myextension(myextension_id: str) -> MyExtension:
myextension = await get_myextension(myextension_id) myextension = await get_myextension(myextension_id)
if not myextension: if not myextension:
raise HTTPException( raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="MyExtension does not exist." status_code=HTTPStatus.NOT_FOUND, detail="MyExtension does not exist."
) )
return myextension.dict() return myextension
## update a record ## update a record
@ -68,16 +66,15 @@ async def api_myextension(myextension_id: str):
async def api_myextension_update( async def api_myextension_update(
data: CreateMyExtensionData, data: CreateMyExtensionData,
myextension_id: str, myextension_id: str,
wallet: WalletTypeInfo = Depends(get_key_type), key_info: WalletTypeInfo = Depends(require_invoice_key),
) -> MyExtension: ) -> MyExtension:
if not myextension_id: myextension = await get_myextension(myextension_id)
if not myextension:
raise HTTPException( raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="MyExtension does not exist." status_code=HTTPStatus.NOT_FOUND, detail="MyExtension does not exist."
) )
myextension = await get_myextension(myextension_id)
assert myextension, "MyExtension couldn't be retrieved"
if wallet.wallet.id != myextension.wallet: if key_info.wallet.id != myextension.wallet:
raise HTTPException( raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="Not your MyExtension." status_code=HTTPStatus.FORBIDDEN, detail="Not your MyExtension."
) )
@ -123,7 +120,7 @@ async def api_myextension_create(
@myextension_api_router.delete("/api/v1/myex/{myextension_id}") @myextension_api_router.delete("/api/v1/myex/{myextension_id}")
async def api_myextension_delete( async def api_myextension_delete(
myextension_id: str, wallet: WalletTypeInfo = Depends(require_admin_key) myextension_id: str, key_info: WalletTypeInfo = Depends(require_admin_key)
): ):
myextension = await get_myextension(myextension_id) myextension = await get_myextension(myextension_id)
@ -132,13 +129,12 @@ async def api_myextension_delete(
status_code=HTTPStatus.NOT_FOUND, detail="MyExtension does not exist." status_code=HTTPStatus.NOT_FOUND, detail="MyExtension does not exist."
) )
if myextension.wallet != wallet.wallet.id: if myextension.wallet != key_info.wallet.id:
raise HTTPException( raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="Not your MyExtension." status_code=HTTPStatus.FORBIDDEN, detail="Not your MyExtension."
) )
await delete_myextension(myextension_id) await delete_myextension(myextension_id)
return "", HTTPStatus.NO_CONTENT
# ANY OTHER ENDPOINTS YOU NEED # ANY OTHER ENDPOINTS YOU NEED
@ -162,19 +158,14 @@ async def api_myextension_create_invoice(
# we create a payment and add some tags, # we create a payment and add some tags,
# so tasks.py can grab the payment once its paid # so tasks.py can grab the payment once its paid
try: payment = await create_invoice(
payment_hash, payment_request = await create_invoice( wallet_id=myextension.wallet,
wallet_id=myextension.wallet, amount=amount,
amount=amount, memo=f"{memo} to {myextension.name}" if memo else f"{myextension.name}",
memo=f"{memo} to {myextension.name}" if memo else f"{myextension.name}", extra={
extra={ "tag": "myextension",
"tag": "myextension", "amount": amount,
"amount": amount, },
}, )
)
except Exception as exc:
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(exc)
) from exc
return {"payment_hash": payment_hash, "payment_request": payment_request} return {"payment_hash": payment.payment_hash, "payment_request": payment.bolt11}

View file

@ -61,7 +61,7 @@ async def api_lnurl_pay_cb(
if not myextension: if not myextension:
return {"status": "ERROR", "reason": "No myextension found"} return {"status": "ERROR", "reason": "No myextension found"}
_, payment_request = await create_invoice( payment = await create_invoice(
wallet_id=myextension.wallet, wallet_id=myextension.wallet,
amount=int(amount / 1000), amount=int(amount / 1000),
memo=myextension.name, memo=myextension.name,
@ -73,7 +73,7 @@ async def api_lnurl_pay_cb(
}, },
) )
return { return {
"pr": payment_request, "pr": payment.bolt11,
"routes": [], "routes": [],
"successAction": {"tag": "message", "message": f"Paid {myextension.name}"}, "successAction": {"tag": "message", "message": f"Paid {myextension.name}"},
} }