Skip to content

Commit ff5103c

Browse files
authored
feat: update to v1.0.0 (#15)
1 parent 5cfd10b commit ff5103c

9 files changed

Lines changed: 1392 additions & 1283 deletions

File tree

__init__.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from fastapi import APIRouter
44
from lnbits.db import Database
5-
from lnbits.tasks import create_permanent_unique_task
65
from loguru import logger
76

87
from .tasks import wait_for_paid_invoices
@@ -34,7 +33,7 @@ def example_stop():
3433

3534

3635
def example_start():
37-
# ignore will be removed in lnbits `0.12.6`
38-
# https://github.com/lnbits/lnbits/pull/2417
39-
task = create_permanent_unique_task("ext_testing", wait_for_paid_invoices) # type: ignore
36+
from lnbits.tasks import create_permanent_unique_task
37+
38+
task = create_permanent_unique_task("ext_testing", wait_for_paid_invoices)
4039
scheduled_tasks.append(task)

config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "Build your own!",
33
"short_description": "Extension building guide",
44
"tile": "https://raw.githubusercontent.com/lnbits/example/main/static/bitcoin-extension.png",
5-
"min_lnbits_version": "0.12.6",
5+
"min_lnbits_version": "1.0.0",
66
"donate": "donate@legend.lnbits.com",
77
"contributors": [
88
{

poetry.lock

Lines changed: 1271 additions & 1150 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ authors = ["Alan Bits <alan@lnbits.com>"]
66

77
[tool.poetry.dependencies]
88
python = "^3.10 | ^3.9"
9-
lnbits = "*"
9+
lnbits = {version = "*", allow-prereleases = true}
1010

1111
[tool.poetry.group.dev.dependencies]
1212
black = "^24.3.0"

static/js/index.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
const mapObject = obj => {
2+
// obj.date = Quasar.date.formatDate(new Date(obj.time), 'YYYY-MM-DD HH:mm')
3+
// here you can do something with the mapped data
4+
return obj
5+
}
6+
7+
window.app = Vue.createApp({
8+
el: '#vue',
9+
mixins: [windowMixin],
10+
// Declare models/variables
11+
data() {
12+
return {
13+
protocol: window.location.protocol,
14+
location: '//' + window.location.hostname,
15+
thingDialog: {
16+
show: false,
17+
data: {}
18+
},
19+
someBool: true,
20+
splitterModel: 20,
21+
exampleData: [],
22+
tab: 'frameworks',
23+
framworktab: 'fastapi',
24+
usefultab: 'magicalg',
25+
vettedData: ''
26+
}
27+
},
28+
// Where functions live
29+
methods: {
30+
exampleFunction(data) {
31+
LNbits.api
32+
.request(
33+
'GET', // Type of request
34+
'/example/api/v1/test/00000000', // URL of the endpoint
35+
this.g.user.wallets[0].inkey, // Often endpoints require a key
36+
data
37+
)
38+
.then(response => {
39+
this.exampleData = response.data.map(mapObject) // Often whats returned is mapped onto some model
40+
})
41+
// Error will be passed to the frontend
42+
.catch(LNbits.utils.notifyApiError)
43+
},
44+
getVettedReadme() {
45+
// This is a function that gets the vetted readme from the LNbits repo and converts it from makrdown to html.
46+
LNbits.api
47+
.request('GET', '/example/api/v1/vetted', this.g.user.wallets[0].inkey)
48+
.then(response => {
49+
this.vettedData = LNbits.utils.convertMarkdown(response.data)
50+
})
51+
.catch(LNbits.utils.notifyApiError)
52+
},
53+
async initWs() {
54+
if (location.protocol !== 'http:') {
55+
localUrl =
56+
'wss://' +
57+
document.domain +
58+
':' +
59+
location.port +
60+
'/api/v1/ws/32872r23g29'
61+
} else {
62+
localUrl =
63+
'ws://' +
64+
document.domain +
65+
':' +
66+
location.port +
67+
'/api/v1/ws/32872r23g29'
68+
}
69+
this.ws = new WebSocket(localUrl)
70+
this.ws.addEventListener('message', async ({data}) => {
71+
const res = data.toString()
72+
document.getElementById('text-to-change').innerHTML = res
73+
})
74+
},
75+
sendThingDialog() {
76+
console.log(this.thingDialog)
77+
}
78+
},
79+
// To run on startup
80+
created() {
81+
this.exampleFunction('lorum')
82+
this.initWs()
83+
this.getVettedReadme()
84+
}
85+
})

tasks.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111

1212
async def wait_for_paid_invoices():
1313
invoice_queue = asyncio.Queue()
14-
register_invoice_listener(invoice_queue, "example")
14+
register_invoice_listener(invoice_queue, "ext_example")
1515

1616
while True:
1717
payment = await invoice_queue.get()
1818
await on_invoice_paid(payment)
1919

2020

2121
async def on_invoice_paid(payment: Payment) -> None:
22-
if (
23-
payment.extra.get("tag") == "example"
24-
): # Will grab any payment with the tag "example"
22+
# Will grab any payment with the tag "example"
23+
if payment.extra.get("tag") == "example":
24+
logger.info("example extension received payment")
2525
logger.debug(payment)

templates/example/index.html

Lines changed: 4 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
2-
%} {% block page %}
3-
2+
%} {% block scripts %} {{ window_vars(user) }}
3+
<script src="{{ static_url_for('example/static', path='js/index.js') }}"></script>
4+
<!-- Do not remove. Test install extension version: 2 -->
5+
{% endblock %} {% block page %}
46
<q-dialog v-model="thingDialog.show" position="top">
57
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
68
<q-form @submit="sendThingDialog" class="q-gutter-md">
@@ -371,105 +373,4 @@
371373
</q-card>
372374
</q-card-section>
373375
</q-card>
374-
{% endblock %} {% block scripts %} {{ window_vars(user) }}
375-
376-
<script>
377-
var someMapObject = obj => {
378-
obj._data = _.clone(obj)
379-
obj.date = Quasar.utils.date.formatDate(
380-
new Date(obj.time * 1000),
381-
'YYYY-MM-DD HH:mm'
382-
)
383-
// here you can do something with the mapped data
384-
return obj
385-
}
386-
new Vue({
387-
el: '#vue',
388-
mixins: [windowMixin],
389-
data: function () {
390-
return {
391-
///// Declare models/variables /////
392-
protocol: window.location.protocol,
393-
location: '//' + window.location.hostname,
394-
thingDialog: {
395-
show: false,
396-
data: {}
397-
},
398-
someBool: true,
399-
splitterModel: 20,
400-
exampleData: [],
401-
tab: 'frameworks',
402-
framworktab: 'fastapi',
403-
usefultab: 'magicalg',
404-
vettedData: ''
405-
}
406-
},
407-
///// Where functions live /////
408-
methods: {
409-
exampleFunction: function (data) {
410-
var theData = data
411-
LNbits.api
412-
.request(
413-
'GET', // Type of request
414-
'/example/api/v1/test/' + theData, // URL of the endpoint
415-
this.g.user.wallets[0].inkey // Often endpoints require a key
416-
)
417-
.then(response => {
418-
this.exampleData = response.data.map(someMapObject) // Often whats returned is mapped onto some model
419-
})
420-
.catch(error => {
421-
LNbits.utils.notifyApiError(error) // Error will be passed to the frontend
422-
})
423-
},
424-
getVettedReadme: function () {
425-
// This is a function that gets the vetted readme from the LNbits repo and converts it from makrdown to html.
426-
LNbits.api
427-
.request(
428-
'GET',
429-
'/example/api/v1/vetted',
430-
this.g.user.wallets[0].inkey
431-
)
432-
.then(response => {
433-
this.vettedData = LNbits.utils.convertMarkdown(response.data)
434-
})
435-
.catch(error => {
436-
LNbits.utils.notifyApiError(error)
437-
})
438-
},
439-
initWs: async function () {
440-
if (location.protocol !== 'http:') {
441-
localUrl =
442-
'wss://' +
443-
document.domain +
444-
':' +
445-
location.port +
446-
'/api/v1/ws/32872r23g29'
447-
} else {
448-
localUrl =
449-
'ws://' +
450-
document.domain +
451-
':' +
452-
location.port +
453-
'/api/v1/ws/32872r23g29'
454-
}
455-
this.ws = new WebSocket(localUrl)
456-
this.ws.addEventListener('message', async ({data}) => {
457-
const res = data.toString()
458-
document.getElementById('text-to-change').innerHTML = res
459-
})
460-
},
461-
sendThingDialog() {
462-
console.log(this.thingDialog)
463-
}
464-
},
465-
///// To run on startup /////
466-
created: function () {
467-
self = this // Often used to run a real object, rather than the event (all a bit confusing really)
468-
self.exampleFunction('lorum')
469-
self.initWs()
470-
self.getVettedReadme()
471-
}
472-
})
473-
</script>
474-
<!-- Do not remove. Test install extension version: 2 -->
475376
{% endblock %}

views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ async def index(
1515
user: User = Depends(check_user_exists),
1616
):
1717
return template_renderer(["example/templates"]).TemplateResponse(
18-
request, "example/index.html", {"user": user.dict()}
18+
request, "example/index.html", {"user": user.json()}
1919
)

views_api.py

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
from http import HTTPStatus
22

33
import httpx
4-
from fastapi import APIRouter, Depends
5-
from fastapi.exceptions import HTTPException
6-
from lnbits.decorators import WalletTypeInfo, get_key_type
4+
from fastapi import APIRouter, Depends, HTTPException
5+
from lnbits.decorators import require_invoice_key
76

87
from .models import Example
98

@@ -16,20 +15,24 @@
1615

1716

1817
@example_ext_api.get("/test/{example_data}", description="Example API endpoint")
19-
async def api_example(example_data: str) -> Example:
20-
# Do some python things and return the data
21-
return Example(id="2", wallet=example_data)
22-
23-
24-
@example_ext_api.get("/vetted", description="Get the vetted extension readme")
25-
async def api_get_vetted(wallet: WalletTypeInfo = Depends(get_key_type)):
26-
try:
27-
async with httpx.AsyncClient() as client:
28-
resp = await client.get(
29-
"https://raw.githubusercontent.com/lnbits/lnbits-extensions/main/README.md"
30-
)
31-
return resp.text
32-
except Exception as e:
18+
async def api_example(example_data: str) -> list[Example]:
19+
if example_data != "00000000":
3320
raise HTTPException(
34-
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e)
35-
) from e
21+
status_code=HTTPStatus.BAD_REQUEST,
22+
detail="Invalid example data",
23+
)
24+
# Do some python things and return the data
25+
return [Example(id="1", wallet=example_data), Example(id="2", wallet=example_data)]
26+
27+
28+
@example_ext_api.get(
29+
"/vetted",
30+
description="Get the vetted extension readme",
31+
dependencies=[Depends(require_invoice_key)],
32+
)
33+
async def api_get_vetted():
34+
async with httpx.AsyncClient() as client:
35+
resp = await client.get(
36+
"https://raw.githubusercontent.com/lnbits/lnbits-extensions/main/README.md"
37+
)
38+
return resp.text

0 commit comments

Comments
 (0)