diff --git a/.gitignore b/.gitignore index c5f1498ce..07ee15b86 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ __bundle__ node_modules lnbits/static/bundle.* +docker diff --git a/Makefile b/Makefile index 63f7eb239..b9418df54 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ all: format check requirements.txt -format: prettier black +format: black check: mypy checkprettier checkblack diff --git a/lnbits/extensions/copilot/templates/copilot/_api_docs.html b/lnbits/extensions/copilot/templates/copilot/_api_docs.html index 64acba148..f0002611a 100644 --- a/lnbits/extensions/copilot/templates/copilot/_api_docs.html +++ b/lnbits/extensions/copilot/templates/copilot/_api_docs.html @@ -31,7 +31,7 @@ [<copilot_object>, ...]
Curl example
curl -X POST {{ request.base_url }}api/v1/copilot -d '{"title": + >curl -X POST {{ request.base_url }}copilot/api/v1/copilot -d '{"title": <string>, "animation": <string>, "show_message":<string>, "amount": <integer>, "lnurl_title": <string>}' -H "Content-type: application/json" @@ -59,7 +59,7 @@
Curl example
curl -X POST {{ request.base_url - }}api/v1/copilot/<copilot_id> -d '{"title": <string>, + }}copilot/api/v1/copilot/<copilot_id> -d '{"title": <string>, "animation": <string>, "show_message":<string>, "amount": <integer>, "lnurl_title": <string>}' -H "Content-type: application/json" -H "X-Api-Key: @@ -87,7 +87,7 @@ [<copilot_object>, ...]
Curl example
curl -X GET {{ request.base_url }}api/v1/copilot/<copilot_id> + >curl -X GET {{ request.base_url }}copilot/api/v1/copilot/<copilot_id> -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -110,7 +110,7 @@ [<copilot_object>, ...]
Curl example
curl -X GET {{ request.base_url }}api/v1/copilots -H "X-Api-Key: {{ + >curl -X GET {{ request.base_url }}copilot/api/v1/copilots -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -136,7 +136,7 @@
Curl example
curl -X DELETE {{ request.base_url - }}api/v1/copilot/<copilot_id> -H "X-Api-Key: {{ + }}copilot/api/v1/copilot/<copilot_id> -H "X-Api-Key: {{ user.wallets[0].adminkey }}" @@ -161,7 +161,7 @@
Curl example
curl -X GET {{ request.base_url }}/api/v1/copilot/ws/<string, + >curl -X GET {{ request.base_url }}copilot/api/v1/copilot/ws/<string, copilot_id>/<string, comment>/<string, gif name> -H "X-Api-Key: {{ user.wallets[0].adminkey }}" diff --git a/lnbits/extensions/jukebox/templates/jukebox/_api_docs.html b/lnbits/extensions/jukebox/templates/jukebox/_api_docs.html index 791a55e71..2a00da008 100644 --- a/lnbits/extensions/jukebox/templates/jukebox/_api_docs.html +++ b/lnbits/extensions/jukebox/templates/jukebox/_api_docs.html @@ -37,7 +37,7 @@ [<jukebox_object>, ...]
Curl example
curl -X GET {{ request.base_url }}api/v1/jukebox -H "X-Api-Key: {{ + >curl -X GET {{ request.base_url }}jukebox/api/v1/jukebox -H "X-Api-Key: {{ user.wallets[0].adminkey }}" @@ -59,7 +59,7 @@ <jukebox_object>
Curl example
curl -X GET {{ request.base_url }}api/v1/jukebox/<juke_id> -H + >curl -X GET {{ request.base_url }}jukebox/api/v1/jukebox/<juke_id> -H "X-Api-Key: {{ user.wallets[0].adminkey }}" @@ -86,7 +86,7 @@ <jukbox_object>
Curl example
curl -X POST {{ request.base_url }}api/v1/jukebox/ -d '{"user": + >curl -X POST {{ request.base_url }}jukebox/api/v1/jukebox/ -d '{"user": <string, user_id>, "title": <string>, "wallet":<string>, "sp_user": <string, spotify_user_account>, "sp_secret": <string, @@ -116,7 +116,7 @@ <jukebox_object>
Curl example
curl -X DELETE {{ request.base_url }}api/v1/jukebox/<juke_id> + >curl -X DELETE {{ request.base_url }}jukebox/api/v1/jukebox/<juke_id> -H "X-Api-Key: {{ user.wallets[0].adminkey }}" diff --git a/lnbits/extensions/livestream/templates/livestream/_api_docs.html b/lnbits/extensions/livestream/templates/livestream/_api_docs.html index 4c497d7f9..629e5d9cf 100644 --- a/lnbits/extensions/livestream/templates/livestream/_api_docs.html +++ b/lnbits/extensions/livestream/templates/livestream/_api_docs.html @@ -38,7 +38,7 @@ [<livestream_object>, ...]
Curl example
curl -X GET {{ request.url_root }}api/v1/livestream -H "X-Api-Key: {{ + >curl -X GET {{ request.base_url }}livestream/api/v1/livestream -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -59,8 +59,8 @@
Curl example
curl -X PUT {{ request.url_root - }}api/v1/livestream/track/<track_id> -H "X-Api-Key: {{ + >curl -X PUT {{ request.base_url }} + livestream/api/v1/livestream/track/<track_id> -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -81,8 +81,8 @@
Curl example
curl -X PUT {{ request.url_root - }}api/v1/livestream/fee/<fee_pct> -H "X-Api-Key: {{ + >curl -X PUT {{ request.base_url }} + livestream/api/v1/livestream/fee/<fee_pct> -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -109,7 +109,8 @@
Curl example
curl -X POST {{ request.url_root }}api/v1/livestream/tracks -d + >curl -X POST {{ request.base_url }} + livestream/api/v1/livestream/tracks -d '{"name": <string>, "download_url": <string>, "price_msat": <integer>, "producer_id": <integer>, "producer_name": <string>}' -H "Content-type: application/json" @@ -123,6 +124,7 @@ dense expand-separator label="Delete a withdraw link" + class="q-pb-md" > @@ -136,8 +138,8 @@
Curl example
curl -X DELETE {{ request.url_root - }}api/v1/livestream/tracks/<track_id> -H "X-Api-Key: {{ + >curl -X DELETE {{ request.base_url }} + livestream/api/v1/livestream/tracks/<track_id> -H "X-Api-Key: {{ user.wallets[0].inkey }}"
diff --git a/lnbits/extensions/lnaddress/templates/lnaddress/_api_docs.html b/lnbits/extensions/lnaddress/templates/lnaddress/_api_docs.html index ab7ab4bd3..dbaa84695 100644 --- a/lnbits/extensions/lnaddress/templates/lnaddress/_api_docs.html +++ b/lnbits/extensions/lnaddress/templates/lnaddress/_api_docs.html @@ -45,7 +45,7 @@ JSON list of users
Curl example
curl -X GET {{ request.url_root }}lnaddress/api/v1/domains -H + >curl -X GET {{ request.base_url }}lnaddress/api/v1/domains -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -81,7 +81,7 @@ >
Curl example
curl -X POST {{ request.url_root }}lnaddress/api/v1/domains -d + >curl -X POST {{ request.base_url }}lnaddress/api/v1/domains -d '{"wallet": "{{ user.wallets[0].id }}", "domain": <string>, "cf_token": <string>,"cf_zone_id": <string>,"webhook": <Optional string> ,"cost": <integer>}' -H "X-Api-Key: {{ @@ -101,7 +101,7 @@ {"X-Api-Key": <string>}
Curl example
curl -X DELETE {{ request.url_root + >curl -X DELETE {{ request.base_url }}lnaddress/api/v1/domains/<domain_id> -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -122,7 +122,7 @@ JSON list of addresses
Curl example
curl -X GET {{ request.url_root }}lnaddress/api/v1/addresses -H + >curl -X GET {{ request.base_url }}lnaddress/api/v1/addresses -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -142,14 +142,14 @@ JSON list of addresses
Curl example
curl -X GET {{ request.url_root + >curl -X GET {{ request.base_url }}lnaddress/api/v1/address/<domain>/<username>/<wallet_key> -H "X-Api-Key: {{ user.wallets[0].inkey }}"
- + {"X-Api-Key": <string>}
Curl example
curl -X POST {{ request.url_root + >curl -X POST {{ request.base_url }}lnaddress/api/v1/address/<domain_id> -d '{"domain": <string>, "username": <string>,"email": <Optional string>, "wallet_endpoint": <string>, "wallet_key": diff --git a/lnbits/extensions/lnurldevice/templates/lnurldevice/_api_docs.html b/lnbits/extensions/lnurldevice/templates/lnurldevice/_api_docs.html index af69b76e3..e255d4a02 100644 --- a/lnbits/extensions/lnurldevice/templates/lnurldevice/_api_docs.html +++ b/lnbits/extensions/lnurldevice/templates/lnurldevice/_api_docs.html @@ -39,7 +39,7 @@ [<lnurldevice_object>, ...]
Curl example
curl -X POST {{ request.base_url }}api/v1/lnurldevice -d '{"title": + >curl -X POST {{ request.base_url }}lnurldevice/api/v1/lnurlpos -d '{"title": <string>, "message":<string>, "currency": <integer>}' -H "Content-type: application/json" -H "X-Api-Key: {{user.wallets[0].adminkey }}" @@ -71,7 +71,7 @@
Curl example
curl -X POST {{ request.base_url - }}api/v1/lnurlpos/<lnurldevice_id> -d ''{"title": + }}lnurldevice/api/v1/lnurlpos/<lnurldevice_id> -d ''{"title": <string>, "message":<string>, "currency": <integer>} -H "Content-type: application/json" -H "X-Api-Key: {{user.wallets[0].adminkey }}" @@ -104,7 +104,7 @@
Curl example
curl -X GET {{ request.base_url - }}api/v1/lnurlpos/<lnurldevice_id> -H "X-Api-Key: {{ + }}lnurldevice/api/v1/lnurlpos/<lnurldevice_id> -H "X-Api-Key: {{ user.wallets[0].inkey }}"
@@ -133,7 +133,7 @@ [<lnurldevice_object>, ...]
Curl example
curl -X GET {{ request.base_url }}api/v1/lnurldevices -H + >curl -X GET {{ request.base_url }}lnurldevice/api/v1/lnurlpos -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -159,7 +159,7 @@
Curl example
curl -X DELETE {{ request.base_url - }}api/v1/lnurlpos/<lnurldevice_id> -H "X-Api-Key: {{ + }}lnurldevice/api/v1/lnurlpos/<lnurldevice_id> -H "X-Api-Key: {{ user.wallets[0].adminkey }}" diff --git a/lnbits/extensions/lnurlp/templates/lnurlp/_api_docs.html b/lnbits/extensions/lnurlp/templates/lnurlp/_api_docs.html index 80d1478d2..bf920558b 100644 --- a/lnbits/extensions/lnurlp/templates/lnurlp/_api_docs.html +++ b/lnbits/extensions/lnurlp/templates/lnurlp/_api_docs.html @@ -17,7 +17,7 @@ [<pay_link_object>, ...]
Curl example
curl -X GET {{ request.base_url }}api/v1/links -H "X-Api-Key: {{ + >curl -X GET {{ request.base_url }}lnurlp/api/v1/links -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -39,7 +39,7 @@ {"lnurl": <string>}
Curl example
curl -X GET {{ request.base_url }}api/v1/links/<pay_id> -H + >curl -X GET {{ request.base_url }}lnurlp/api/v1/links/<pay_id> -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -68,7 +68,7 @@ {"lnurl": <string>}
Curl example
curl -X POST {{ request.base_url }}api/v1/links -d '{"description": + >curl -X POST {{ request.base_url }}lnurlp/api/v1/links -d '{"description": <string>, "amount": <integer>, "max": <integer>, "min": <integer>, "comment_chars": <integer>}' -H "Content-type: application/json" -H "X-Api-Key: {{ @@ -99,7 +99,7 @@ {"lnurl": <string>}
Curl example
curl -X PUT {{ request.base_url }}api/v1/links/<pay_id> -d + >curl -X PUT {{ request.base_url }}lnurlp/api/v1/links/<pay_id> -d '{"description": <string>, "amount": <integer>}' -H "Content-type: application/json" -H "X-Api-Key: {{ user.wallets[0].adminkey }}" @@ -126,7 +126,7 @@
Curl example
curl -X DELETE {{ request.base_url }}api/v1/links/<pay_id> -H + >curl -X DELETE {{ request.base_url }}lnurlp/api/v1/links/<pay_id> -H "X-Api-Key: {{ user.wallets[0].adminkey }}" diff --git a/lnbits/extensions/offlineshop/templates/offlineshop/_api_docs.html b/lnbits/extensions/offlineshop/templates/offlineshop/_api_docs.html index ac655697b..bd68b629e 100644 --- a/lnbits/extensions/offlineshop/templates/offlineshop/_api_docs.html +++ b/lnbits/extensions/offlineshop/templates/offlineshop/_api_docs.html @@ -63,7 +63,7 @@
Curl example
curl -X GET {{ request.base_url - }}/offlineshop/api/v1/offlineshop/items -H "Content-Type: + }}offlineshop/api/v1/offlineshop/items -H "Content-Type: application/json" -H "X-Api-Key: {{ user.wallets[0].inkey }}" -d '{"name": <string>, "description": <string>, "image": <data-uri string>, "price": <integer>, "unit": <"sat" @@ -96,7 +96,7 @@ >
Curl example
curl -X GET {{ request.base_url }}/offlineshop/api/v1/offlineshop -H + >curl -X GET {{ request.base_url }}offlineshop/api/v1/offlineshop -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -118,7 +118,7 @@
Curl example
curl -X GET {{ request.base_url - }}/offlineshop/api/v1/offlineshop/items/<item_id> -H + }}offlineshop/api/v1/offlineshop/items/<item_id> -H "Content-Type: application/json" -H "X-Api-Key: {{ user.wallets[0].inkey }}" -d '{"name": <string>, "description": <string>, "image": <data-uri string>, "price": @@ -127,7 +127,7 @@
- + DELETE @@ -138,7 +138,7 @@
Curl example
curl -X GET {{ request.base_url - }}/offlineshop/api/v1/offlineshop/items/<item_id> -H "X-Api-Key: + }}offlineshop/api/v1/offlineshop/items/<item_id> -H "X-Api-Key: {{ user.wallets[0].inkey }}"
diff --git a/lnbits/extensions/paywall/templates/paywall/_api_docs.html b/lnbits/extensions/paywall/templates/paywall/_api_docs.html index ceadf2f08..664cda0f1 100644 --- a/lnbits/extensions/paywall/templates/paywall/_api_docs.html +++ b/lnbits/extensions/paywall/templates/paywall/_api_docs.html @@ -17,7 +17,7 @@ [<paywall_object>, ...]
Curl example
curl -X GET {{ request.url_root }}api/v1/paywalls -H "X-Api-Key: {{ + >curl -X GET {{ request.base_url }}paywall/api/v1/paywalls -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -48,7 +48,7 @@ >
Curl example
curl -X POST {{ request.url_root }}api/v1/paywalls -d '{"url": + >curl -X POST {{ request.base_url }}paywall/api/v1/paywalls -d '{"url": <string>, "memo": <string>, "description": <string>, "amount": <integer>, "remembers": <boolean>}' -H "Content-type: application/json" -H "X-Api-Key: {{ @@ -80,8 +80,8 @@ >
Curl example
curl -X POST {{ request.url_root - }}api/v1/paywalls/<paywall_id>/invoice -d '{"amount": + >curl -X POST {{ request.base_url + }}paywall/api/v1/paywalls/<paywall_id>/invoice -d '{"amount": <integer>}' -H "Content-type: application/json" @@ -111,8 +111,8 @@ >
Curl example
curl -X POST {{ request.url_root - }}api/v1/paywalls/<paywall_id>/check_invoice -d + >curl -X POST {{ request.base_url + }}paywall/api/v1/paywalls/<paywall_id>/check_invoice -d '{"payment_hash": <string>}' -H "Content-type: application/json" @@ -137,8 +137,8 @@
Curl example
curl -X DELETE {{ request.url_root - }}api/v1/paywalls/<paywall_id> -H "X-Api-Key: {{ + >curl -X DELETE {{ request.base_url + }}paywall/api/v1/paywalls/<paywall_id> -H "X-Api-Key: {{ user.wallets[0].adminkey }}" diff --git a/lnbits/extensions/satsdice/templates/satsdice/_api_docs.html b/lnbits/extensions/satsdice/templates/satsdice/_api_docs.html index fb43b90dc..644bcdfef 100644 --- a/lnbits/extensions/satsdice/templates/satsdice/_api_docs.html +++ b/lnbits/extensions/satsdice/templates/satsdice/_api_docs.html @@ -17,7 +17,7 @@ [<satsdice_link_object>, ...]
Curl example
curl -X GET {{ request.base_url }}api/v1/links -H "X-Api-Key: {{ + >curl -X GET {{ request.base_url }}satsdice/api/v1/links -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -44,7 +44,7 @@ {"lnurl": <string>}
Curl example
curl -X GET {{ request.base_url }}api/v1/links/<satsdice_id> -H + >curl -X GET {{ request.base_url }}satsdice/api/v1/links/<satsdice_id> -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -73,7 +73,7 @@ {"lnurl": <string>}
Curl example
curl -X POST {{ request.base_url }}api/v1/links -d '{"title": + >curl -X POST {{ request.base_url }}satsdice/api/v1/links -d '{"title": <string>, "min_satsdiceable": <integer>, "max_satsdiceable": <integer>, "uses": <integer>, "wait_time": <integer>, "is_unique": <boolean>}' -H @@ -109,7 +109,7 @@ {"lnurl": <string>}
Curl example
curl -X PUT {{ request.base_url }}api/v1/links/<satsdice_id> -d + >curl -X PUT {{ request.base_url }}satsdice/api/v1/links/<satsdice_id> -d '{"title": <string>, "min_satsdiceable": <integer>, "max_satsdiceable": <integer>, "uses": <integer>, "wait_time": <integer>, "is_unique": <boolean>}' -H @@ -137,7 +137,7 @@
Curl example
curl -X DELETE {{ request.base_url }}api/v1/links/<satsdice_id> + >curl -X DELETE {{ request.base_url }}satsdice/api/v1/links/<satsdice_id> -H "X-Api-Key: {{ user.wallets[0].adminkey }}" @@ -165,7 +165,7 @@
Curl example
curl -X GET {{ request.base_url - }}api/v1/links/<the_hash>/<lnurl_id> -H "X-Api-Key: {{ + }}satsdice/api/v1/links/<the_hash>/<lnurl_id> -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -186,7 +186,7 @@ >
Curl example
curl -X GET {{ request.base_url }}/satsdice/img/<lnurl_id>" + >curl -X GET {{ request.base_url }}satsdice/img/<lnurl_id>"
diff --git a/lnbits/extensions/satspay/templates/satspay/_api_docs.html b/lnbits/extensions/satspay/templates/satspay/_api_docs.html index d834db200..89380de00 100644 --- a/lnbits/extensions/satspay/templates/satspay/_api_docs.html +++ b/lnbits/extensions/satspay/templates/satspay/_api_docs.html @@ -32,7 +32,7 @@ [<charge_object>, ...]
Curl example
curl -X POST {{ request.base_url }}api/v1/charge -d + >curl -X POST {{ request.base_url }}satspay/api/v1/charge -d '{"onchainwallet": <string, watchonly_wallet_id>, "description": <string>, "webhook":<string>, "time": <integer>, "amount": <integer>, "lnbitswallet": @@ -60,7 +60,7 @@ [<charge_object>, ...]
Curl example
curl -X POST {{ request.base_url }}api/v1/charge/<charge_id> + >curl -X POST {{ request.base_url }}satspay/api/v1/charge/<charge_id> -d '{"onchainwallet": <string, watchonly_wallet_id>, "description": <string>, "webhook":<string>, "time": <integer>, "amount": <integer>, "lnbitswallet": @@ -89,7 +89,7 @@ [<charge_object>, ...]
Curl example
curl -X GET {{ request.base_url }}api/v1/charge/<charge_id> + >curl -X GET {{ request.base_url }}satspay/api/v1/charge/<charge_id> -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -112,7 +112,7 @@ [<charge_object>, ...]
Curl example
curl -X GET {{ request.base_url }}api/v1/charges -H "X-Api-Key: {{ + >curl -X GET {{ request.base_url }}satspay/api/v1/charges -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -123,7 +123,6 @@ dense expand-separator label="Delete a pay link" - class="q-pb-md" > @@ -138,13 +137,18 @@
Curl example
curl -X DELETE {{ request.base_url - }}api/v1/charge/<charge_id> -H "X-Api-Key: {{ + }}satspay/api/v1/charge/<charge_id> -H "X-Api-Key: {{ user.wallets[0].adminkey }}"
- + Curl example curl -X GET {{ request.base_url - }}api/v1/charges/balance/<charge_id> -H "X-Api-Key: {{ + }}satspay/api/v1/charges/balance/<charge_id> -H "X-Api-Key: {{ user.wallets[0].inkey }}" diff --git a/lnbits/extensions/splitpayments/templates/splitpayments/_api_docs.html b/lnbits/extensions/splitpayments/templates/splitpayments/_api_docs.html index 78b5362cd..7a8a6d07e 100644 --- a/lnbits/extensions/splitpayments/templates/splitpayments/_api_docs.html +++ b/lnbits/extensions/splitpayments/templates/splitpayments/_api_docs.html @@ -52,7 +52,7 @@ >
Curl example
curl -X GET {{ request.base_url }}api/v1/livestream -H "X-Api-Key: {{ + >curl -X GET {{ request.base_url }}splitpayments/api/v1/targets -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -63,6 +63,7 @@ dense expand-separator label="Set Target Wallets" + class="q-pb-md" > @@ -78,7 +79,7 @@
Curl example
curl -X PUT {{ request.base_url }}api/v1/splitpayments/targets -H + >curl -X PUT {{ request.base_url }}splitpayments/api/v1/targets -H "X-Api-Key: {{ user.wallets[0].adminkey }}" -H 'Content-Type: application/json' -d '{"targets": [{"wallet": <wallet id or invoice key>, "alias": <name to identify this>, "percent": <number diff --git a/lnbits/extensions/tpos/__init__.py b/lnbits/extensions/tpos/__init__.py index c62981d72..1aed95bac 100644 --- a/lnbits/extensions/tpos/__init__.py +++ b/lnbits/extensions/tpos/__init__.py @@ -1,7 +1,10 @@ +import asyncio + 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_tpos") @@ -12,5 +15,11 @@ def tpos_renderer(): return template_renderer(["lnbits/extensions/tpos/templates"]) +from .tasks import wait_for_paid_invoices from .views_api import * # noqa from .views import * # noqa + + +def tpos_start(): + loop = asyncio.get_event_loop() + loop.create_task(catch_everything_and_restart(wait_for_paid_invoices)) diff --git a/lnbits/extensions/tpos/config.json b/lnbits/extensions/tpos/config.json index c5789afb7..3bd1a71a4 100644 --- a/lnbits/extensions/tpos/config.json +++ b/lnbits/extensions/tpos/config.json @@ -2,5 +2,5 @@ "name": "TPoS", "short_description": "A shareable PoS terminal!", "icon": "dialpad", - "contributors": ["talvasconcelos", "arcbtc"] + "contributors": ["talvasconcelos", "arcbtc", "leesalminen"] } diff --git a/lnbits/extensions/tpos/crud.py b/lnbits/extensions/tpos/crud.py index 1a1987696..8f071d8cc 100644 --- a/lnbits/extensions/tpos/crud.py +++ b/lnbits/extensions/tpos/crud.py @@ -10,10 +10,17 @@ async def create_tpos(wallet_id: str, data: CreateTposData) -> TPoS: tpos_id = urlsafe_short_hash() await db.execute( """ - INSERT INTO tpos.tposs (id, wallet, name, currency) - VALUES (?, ?, ?, ?) + INSERT INTO tpos.tposs (id, wallet, name, currency, tip_options, tip_wallet) + VALUES (?, ?, ?, ?, ?, ?) """, - (tpos_id, wallet_id, data.name, data.currency), + ( + tpos_id, + wallet_id, + data.name, + data.currency, + data.tip_options, + data.tip_wallet, + ), ) tpos = await get_tpos(tpos_id) diff --git a/lnbits/extensions/tpos/migrations.py b/lnbits/extensions/tpos/migrations.py index 7a7fff0d5..565c05abf 100644 --- a/lnbits/extensions/tpos/migrations.py +++ b/lnbits/extensions/tpos/migrations.py @@ -12,3 +12,25 @@ async def m001_initial(db): ); """ ) + + +async def m002_addtip_wallet(db): + """ + Add tips to tposs table + """ + await db.execute( + """ + ALTER TABLE tpos.tposs ADD tip_wallet TEXT NULL; + """ + ) + + +async def m003_addtip_options(db): + """ + Add tips to tposs table + """ + await db.execute( + """ + ALTER TABLE tpos.tposs ADD tip_options TEXT NULL; + """ + ) diff --git a/lnbits/extensions/tpos/models.py b/lnbits/extensions/tpos/models.py index 653a055ca..6a2ff1d2c 100644 --- a/lnbits/extensions/tpos/models.py +++ b/lnbits/extensions/tpos/models.py @@ -6,6 +6,8 @@ from pydantic import BaseModel class CreateTposData(BaseModel): name: str currency: str + tip_options: str + tip_wallet: str class TPoS(BaseModel): @@ -13,6 +15,8 @@ class TPoS(BaseModel): wallet: str name: str currency: str + tip_options: str + tip_wallet: str @classmethod def from_row(cls, row: Row) -> "TPoS": diff --git a/lnbits/extensions/tpos/tasks.py b/lnbits/extensions/tpos/tasks.py new file mode 100644 index 000000000..0bb8dff92 --- /dev/null +++ b/lnbits/extensions/tpos/tasks.py @@ -0,0 +1,70 @@ +import asyncio +import json + +from lnbits.core import db as core_db +from lnbits.core.crud import create_payment +from lnbits.core.models import Payment +from lnbits.helpers import urlsafe_short_hash +from lnbits.tasks import internal_invoice_queue, register_invoice_listener + +from .crud import get_tpos + + +async def wait_for_paid_invoices(): + invoice_queue = asyncio.Queue() + register_invoice_listener(invoice_queue) + + while True: + payment = await invoice_queue.get() + await on_invoice_paid(payment) + + +async def on_invoice_paid(payment: Payment) -> None: + if "tpos" == payment.extra.get("tag") and payment.extra.get("tipSplitted"): + # already splitted, ignore + return + + # now we make some special internal transfers (from no one to the receiver) + tpos = await get_tpos(payment.extra.get("tposId")) + + tipAmount = payment.extra.get("tipAmount") + + if tipAmount is None: + # no tip amount + return + + tipAmount = tipAmount * 1000 + + # mark the original payment with one extra key, "splitted" + # (this prevents us from doing this process again and it's informative) + # and reduce it by the amount we're going to send to the producer + await core_db.execute( + """ + UPDATE apipayments + SET extra = ?, amount = amount - ? + WHERE hash = ? + AND checking_id NOT LIKE 'internal_%' + """, + ( + json.dumps(dict(**payment.extra, tipSplitted=True)), + tipAmount, + payment.payment_hash, + ), + ) + + # perform the internal transfer using the same payment_hash + internal_checking_id = f"internal_{urlsafe_short_hash()}" + await create_payment( + wallet_id=tpos.tip_wallet, + checking_id=internal_checking_id, + payment_request="", + payment_hash=payment.payment_hash, + amount=tipAmount, + memo=payment.memo, + pending=False, + extra={"tipSplitted": True}, + ) + + # manually send this for now + await internal_invoice_queue.put(internal_checking_id) + return diff --git a/lnbits/extensions/tpos/templates/tpos/_api_docs.html b/lnbits/extensions/tpos/templates/tpos/_api_docs.html index 7897383d0..42160cce2 100644 --- a/lnbits/extensions/tpos/templates/tpos/_api_docs.html +++ b/lnbits/extensions/tpos/templates/tpos/_api_docs.html @@ -17,7 +17,7 @@ [<tpos_object>, ...]
Curl example
curl -X GET {{ request.base_url }}api/v1/tposs -H "X-Api-Key: + >curl -X GET {{ request.base_url }}tpos/api/v1/tposs -H "X-Api-Key: <invoice_key>"
@@ -42,7 +42,7 @@ >
Curl example
curl -X POST {{ request.base_url }}api/v1/tposs -d '{"name": + >curl -X POST {{ request.base_url }}tpos/api/v1/tposs -d '{"name": <string>, "currency": <string>}' -H "Content-type: application/json" -H "X-Api-Key: <admin_key>" @@ -69,7 +69,7 @@
Curl example
curl -X DELETE {{ request.base_url }}api/v1/tposs/<tpos_id> -H + >curl -X DELETE {{ request.base_url }}tpos/api/v1/tposs/<tpos_id> -H "X-Api-Key: <admin_key>" diff --git a/lnbits/extensions/tpos/templates/tpos/index.html b/lnbits/extensions/tpos/templates/tpos/index.html index a8971211a..af3b0573f 100644 --- a/lnbits/extensions/tpos/templates/tpos/index.html +++ b/lnbits/extensions/tpos/templates/tpos/index.html @@ -54,7 +54,7 @@ > - {{ col.value }} + {{ (col.name == 'tip_options' ? JSON.parse(col.value).join(", ") : col.value) }} + +
parseInt(str))) : JSON.stringify([])), + tip_wallet: this.formDialog.data.tip_wallet || "", } var self = this diff --git a/lnbits/extensions/tpos/templates/tpos/tpos.html b/lnbits/extensions/tpos/templates/tpos/tpos.html index 49d88140f..e4ea14992 100644 --- a/lnbits/extensions/tpos/templates/tpos/tpos.html +++ b/lnbits/extensions/tpos/templates/tpos/tpos.html @@ -1,5 +1,17 @@ -{% extends "public.html" %} {% block toolbar_title %}{{ tpos.name }}{% endblock -%} {% block footer %}{% endblock %} {% block page_container %} + +{% extends "public.html" %} +{% block toolbar_title %} +{{ tpos.name }} + +{% endblock %} +{% block footer %}{% endblock %} {% block page_container %} @@ -43,16 +55,6 @@ color="primary" >3 - C 9 - OK #C + OK
@@ -176,6 +179,38 @@
+ + + +
+ Would you like to leave a tip? +
+
+ {% raw %}{{ tip }}{% endraw %}% +
+ +
+ Close +
+
+
+ @@ -214,6 +249,10 @@ {% endblock %} {% block styles %} {% endblock %} {% block scripts %} @@ -241,14 +279,19 @@ return { tposId: '{{ tpos.id }}', currency: '{{ tpos.currency }}', + tip_options: JSON.parse('{{ tpos.tip_options }}'), exchangeRate: null, stack: [], + tipAmount: 0.00, invoiceDialog: { show: false, data: null, dismissMsg: null, paymentChecker: null }, + tipDialog: { + show: false, + }, urlDialog: { show: false }, @@ -269,6 +312,10 @@ if (!this.exchangeRate) return 0 return Math.ceil((this.amount / this.exchangeRate) * 100000000) }, + tipAmountSat: function () { + if (!this.exchangeRate) return 0 + return Math.ceil((this.tipAmount / this.exchangeRate) * 100000000) + }, fsat: function () { console.log('sat', this.sat, LNbits.utils.formatSat(this.sat)) return LNbits.utils.formatSat(this.sat) @@ -277,12 +324,46 @@ methods: { closeInvoiceDialog: function () { this.stack = [] + this.tipAmount = 0.00 var dialog = this.invoiceDialog setTimeout(function () { clearInterval(dialog.paymentChecker) dialog.dismissMsg() }, 3000) }, + processTipSelection: function (selectedTipOption) { + this.tipDialog.show = false + + if(selectedTipOption) { + const tipAmount = parseFloat(parseFloat((selectedTipOption / 100) * this.amount)) + const subtotal = parseFloat(this.amount) + const grandTotal = parseFloat((tipAmount + subtotal).toFixed(2)) + const totalString = grandTotal.toFixed(2).toString() + + this.stack = [] + for (var i = 0; i < totalString.length; i++) { + const char = totalString[i] + + if(char !== ".") { + this.stack.push(char) + } + } + + this.tipAmount = tipAmount + } + + this.showInvoice() + }, + submitForm: function() { + if(this.tip_options.length) { + this.showTipModal() + } else { + this.showInvoice() + } + }, + showTipModal: function() { + this.tipDialog.show = true + }, showInvoice: function () { var self = this var dialog = this.invoiceDialog @@ -290,7 +371,8 @@ axios .post('/tpos/api/v1/tposs/' + this.tposId + '/invoices', null, { params: { - amount: this.sat + amount: this.sat, + tipAmount: this.tipAmountSat, } }) .then(function (response) { diff --git a/lnbits/extensions/tpos/views.py b/lnbits/extensions/tpos/views.py index 2d78ecce1..a94564d57 100644 --- a/lnbits/extensions/tpos/views.py +++ b/lnbits/extensions/tpos/views.py @@ -8,6 +8,10 @@ from starlette.responses import HTMLResponse from lnbits.core.models import User from lnbits.decorators import check_user_exists +from lnbits.settings import ( + LNBITS_CUSTOM_LOGO, + LNBITS_SITE_TITLE, +) from . import tpos_ext, tpos_renderer from .crud import get_tpos @@ -33,3 +37,40 @@ async def tpos(request: Request, tpos_id): return tpos_renderer().TemplateResponse( "tpos/tpos.html", {"request": request, "tpos": tpos} ) + + +@tpos_ext.get("/manifest/{tpos_id}.webmanifest") +async def manifest(tpos_id: str): + tpos = await get_tpos(tpos_id) + if not tpos: + raise HTTPException( + status_code=HTTPStatus.NOT_FOUND, detail="TPoS does not exist." + ) + + return { + "short_name": LNBITS_SITE_TITLE, + "name": tpos.name + " - " + LNBITS_SITE_TITLE, + "icons": [ + { + "src": LNBITS_CUSTOM_LOGO + if LNBITS_CUSTOM_LOGO + else "https://cdn.jsdelivr.net/gh/lnbits/lnbits@0.3.0/docs/logos/lnbits.png", + "type": "image/png", + "sizes": "900x900", + } + ], + "start_url": "/tpos/" + tpos_id, + "background_color": "#1F2234", + "description": "Bitcoin Lightning tPOS", + "display": "standalone", + "scope": "/tpos/" + tpos_id, + "theme_color": "#1F2234", + "shortcuts": [ + { + "name": tpos.name + " - " + LNBITS_SITE_TITLE, + "short_name": tpos.name, + "description": tpos.name + " - " + LNBITS_SITE_TITLE, + "url": "/tpos/" + tpos_id, + } + ], + } diff --git a/lnbits/extensions/tpos/views_api.py b/lnbits/extensions/tpos/views_api.py index ae457b61a..fb4bd0ab1 100644 --- a/lnbits/extensions/tpos/views_api.py +++ b/lnbits/extensions/tpos/views_api.py @@ -52,7 +52,9 @@ async def api_tpos_delete( @tpos_ext.post("/api/v1/tposs/{tpos_id}/invoices", status_code=HTTPStatus.CREATED) -async def api_tpos_create_invoice(amount: int = Query(..., ge=1), tpos_id: str = None): +async def api_tpos_create_invoice( + amount: int = Query(..., ge=1), tipAmount: int = None, tpos_id: str = None +): tpos = await get_tpos(tpos_id) if not tpos: @@ -65,7 +67,7 @@ async def api_tpos_create_invoice(amount: int = Query(..., ge=1), tpos_id: str = wallet_id=tpos.wallet, amount=amount, memo=f"{tpos.name}", - extra={"tag": "tpos"}, + extra={"tag": "tpos", "tipAmount": tipAmount, "tposId": tpos_id}, ) except Exception as e: raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e)) @@ -84,6 +86,7 @@ async def api_tpos_check_invoice(tpos_id: str, payment_hash: str): ) try: status = await api_payment(payment_hash) + except Exception as exc: print(exc) return {"paid": False} diff --git a/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html b/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html index e82171920..bff663833 100644 --- a/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html +++ b/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html @@ -37,7 +37,7 @@ [<wallets_object>, ...]
Curl example
curl -X GET {{ request.base_url }}api/v1/wallet -H "X-Api-Key: {{ + >curl -X GET {{ request.base_url }}watchonly/api/v1/wallet -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -66,7 +66,7 @@ [<wallet_object>, ...]
Curl example
curl -X GET {{ request.base_url }}api/v1/wallet/<wallet_id> + >curl -X GET {{ request.base_url }}watchonly/api/v1/wallet/<wallet_id> -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -89,7 +89,7 @@ [<wallet_object>, ...]
Curl example
curl -X POST {{ request.base_url }}api/v1/wallet -d '{"title": + >curl -X POST {{ request.base_url }}watchonly/api/v1/wallet -d '{"title": <string>, "masterpub": <string>}' -H "Content-type: application/json" -H "X-Api-Key: {{ user.wallets[0].adminkey }}" @@ -116,7 +116,7 @@
Curl example
curl -X DELETE {{ request.base_url - }}api/v1/wallet/<wallet_id> -H "X-Api-Key: {{ + }}watchonly/api/v1/wallet/<wallet_id> -H "X-Api-Key: {{ user.wallets[0].adminkey }}" @@ -142,7 +142,7 @@
Curl example
curl -X GET {{ request.base_url - }}api/v1/addresses/<wallet_id> -H "X-Api-Key: {{ + }}watchonly/api/v1/addresses/<wallet_id> -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -173,7 +173,7 @@ [<address_object>, ...]
Curl example
curl -X GET {{ request.base_url }}api/v1/address/<wallet_id> + >curl -X GET {{ request.base_url }}watchonly/api/v1/address/<wallet_id> -H "X-Api-Key: {{ user.wallets[0].inkey }}" @@ -202,7 +202,7 @@ [<mempool_object>, ...]
Curl example
curl -X GET {{ request.base_url }}api/v1/mempool -H "X-Api-Key: {{ + >curl -X GET {{ request.base_url }}watchonly/api/v1/mempool -H "X-Api-Key: {{ user.wallets[0].adminkey }}" @@ -233,7 +233,7 @@ [<mempool_object>, ...]
Curl example
curl -X PUT {{ request.base_url }}api/v1/mempool -d '{"endpoint": + >curl -X PUT {{ request.base_url }}watchonly/api/v1/mempool -d '{"endpoint": <string>}' -H "Content-type: application/json" -H "X-Api-Key: {{ user.wallets[0].adminkey }}" diff --git a/lnbits/static/scss/base.scss b/lnbits/static/scss/base.scss index 3668e7736..672a85b61 100644 --- a/lnbits/static/scss/base.scss +++ b/lnbits/static/scss/base.scss @@ -140,4 +140,10 @@ video { // text-wrap .text-wrap { word-break: break-word; +} + +.q-card { + code { + overflow-wrap: break-word; + } } \ No newline at end of file