diff --git a/lnbits/__main__.py b/lnbits/__main__.py index 186b2901..e9c43cda 100644 --- a/lnbits/__main__.py +++ b/lnbits/__main__.py @@ -27,4 +27,3 @@ print( - service fee: {SERVICE_FEE} """ ) - diff --git a/lnbits/extensions/amilk/README.md b/lnbits/extensions/amilk/README.md deleted file mode 100644 index 27729459..00000000 --- a/lnbits/extensions/amilk/README.md +++ /dev/null @@ -1,11 +0,0 @@ -
-
-
-curl -H "Content-type: application/json" -X POST https://YOUR-LNBITS/YOUR-EXTENSION/api/v1/EXAMPLE -d '{"amount":"100","memo":"example"}' -H "X-Api-Key: YOUR_WALLET-ADMIN/INVOICE-KEY"
diff --git a/lnbits/extensions/amilk/__init__.py b/lnbits/extensions/amilk/__init__.py
deleted file mode 100644
index 0cdd8727..00000000
--- a/lnbits/extensions/amilk/__init__.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from quart import Blueprint
-from lnbits.db import Database
-
-db = Database("ext_amilk")
-
-amilk_ext: Blueprint = Blueprint(
- "amilk", __name__, static_folder="static", template_folder="templates"
-)
-
-
-from .views_api import * # noqa
-from .views import * # noqa
diff --git a/lnbits/extensions/amilk/config.json b/lnbits/extensions/amilk/config.json
deleted file mode 100644
index 09faf8af..00000000
--- a/lnbits/extensions/amilk/config.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "AMilk",
- "short_description": "Assistant Faucet Milker",
- "icon": "room_service",
- "contributors": ["arcbtc"]
-}
diff --git a/lnbits/extensions/amilk/crud.py b/lnbits/extensions/amilk/crud.py
deleted file mode 100644
index 859d2fa8..00000000
--- a/lnbits/extensions/amilk/crud.py
+++ /dev/null
@@ -1,42 +0,0 @@
-from base64 import urlsafe_b64encode
-from uuid import uuid4
-from typing import List, Optional, Union
-
-from . import db
-from .models import AMilk
-
-
-async def create_amilk(*, wallet_id: str, lnurl: str, atime: int, amount: int) -> AMilk:
- amilk_id = urlsafe_b64encode(uuid4().bytes_le).decode("utf-8")
- await db.execute(
- """
- INSERT INTO amilk.amilks (id, wallet, lnurl, atime, amount)
- VALUES (?, ?, ?, ?, ?)
- """,
- (amilk_id, wallet_id, lnurl, atime, amount),
- )
-
- amilk = await get_amilk(amilk_id)
- assert amilk, "Newly created amilk_id couldn't be retrieved"
- return amilk
-
-
-async def get_amilk(amilk_id: str) -> Optional[AMilk]:
- row = await db.fetchone("SELECT * FROM amilk.amilks WHERE id = ?", (amilk_id,))
- return AMilk(**row) if row else None
-
-
-async def get_amilks(wallet_ids: Union[str, List[str]]) -> List[AMilk]:
- if isinstance(wallet_ids, str):
- wallet_ids = [wallet_ids]
-
- q = ",".join(["?"] * len(wallet_ids))
- rows = await db.fetchall(
- f"SELECT * FROM amilk.amilks WHERE wallet IN ({q})", (*wallet_ids,)
- )
-
- return [AMilk(**row) for row in rows]
-
-
-async def delete_amilk(amilk_id: str) -> None:
- await db.execute("DELETE FROM amilk.amilks WHERE id = ?", (amilk_id,))
diff --git a/lnbits/extensions/amilk/migrations.py b/lnbits/extensions/amilk/migrations.py
deleted file mode 100644
index 596a8633..00000000
--- a/lnbits/extensions/amilk/migrations.py
+++ /dev/null
@@ -1,15 +0,0 @@
-async def m001_initial(db):
- """
- Initial amilks table.
- """
- await db.execute(
- """
- CREATE TABLE amilk.amilks (
- id TEXT PRIMARY KEY,
- wallet TEXT NOT NULL,
- lnurl TEXT NOT NULL,
- atime INTEGER NOT NULL,
- amount INTEGER NOT NULL
- );
- """
- )
diff --git a/lnbits/extensions/amilk/models.py b/lnbits/extensions/amilk/models.py
deleted file mode 100644
index 647cc530..00000000
--- a/lnbits/extensions/amilk/models.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from pydantic import BaseModel
-
-
-class AMilk(BaseModel):
- id: str
- wallet: str
- lnurl: str
- atime: int
- amount: int
diff --git a/lnbits/extensions/amilk/templates/amilk/_api_docs.html b/lnbits/extensions/amilk/templates/amilk/_api_docs.html
deleted file mode 100644
index f1c27a1b..00000000
--- a/lnbits/extensions/amilk/templates/amilk/_api_docs.html
+++ /dev/null
@@ -1,24 +0,0 @@
-
- Milking faucets with software, known as "assmilking", seems at first to
- be black-hat, although in fact there might be some unexplored use cases.
- An LNURL withdraw gives someone the right to pull funds, which can be
- done over time. An LNURL withdraw could be used outside of just faucets,
- to provide money streaming and repeat payments.
Paste or scan an
- LNURL withdraw, enter the amount for the AMilk to pull and the frequency
- for it to be pulled.
-
- Created by, Ben Arc
-
- This extension allows you to connect a Bleskomat ATM to an lnbits - wallet. It will work with both the - open-source DIY Bleskomat ATM project - as well as the - commercial Bleskomat ATM. -
-- Since the Bleskomat ATMs are designed to be offline, a cryptographic - signing scheme is used to verify that the URL was generated by an - authorized device. When one of your customers inserts fiat money into - the device, a signed URL (lnurl-withdraw) is created and displayed as a - QR code. Your customer scans the QR code with their lnurl-supporting - mobile app, their mobile app communicates with the web API of lnbits to - verify the signature, the fiat currency amount is converted to sats, the - customer accepts the withdrawal, and finally lnbits will pay the - customer from your lnbits wallet. -
-
-
-
-curl -H "Content-type: application/json" -X POST https://YOUR-LNBITS/YOUR-EXTENSION/api/v1/EXAMPLE -d '{"amount":"100","memo":"example"}' -H "X-Api-Key: YOUR_WALLET-ADMIN/INVOICE-KEY"
diff --git a/lnbits/extensions/captcha/__init__.py b/lnbits/extensions/captcha/__init__.py
deleted file mode 100644
index f25dccce..00000000
--- a/lnbits/extensions/captcha/__init__.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from quart import Blueprint
-from lnbits.db import Database
-
-db = Database("ext_captcha")
-
-captcha_ext: Blueprint = Blueprint(
- "captcha", __name__, static_folder="static", template_folder="templates"
-)
-
-
-from .views_api import * # noqa
-from .views import * # noqa
diff --git a/lnbits/extensions/captcha/config.json b/lnbits/extensions/captcha/config.json
deleted file mode 100644
index 4ef7c43f..00000000
--- a/lnbits/extensions/captcha/config.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "Captcha",
- "short_description": "Create captcha to stop spam",
- "icon": "block",
- "contributors": ["pseudozach"]
-}
diff --git a/lnbits/extensions/captcha/crud.py b/lnbits/extensions/captcha/crud.py
deleted file mode 100644
index 43a0374e..00000000
--- a/lnbits/extensions/captcha/crud.py
+++ /dev/null
@@ -1,53 +0,0 @@
-from typing import List, Optional, Union
-
-from lnbits.helpers import urlsafe_short_hash
-
-from . import db
-from .models import Captcha
-
-
-async def create_captcha(
- *,
- wallet_id: str,
- url: str,
- memo: str,
- description: Optional[str] = None,
- amount: int = 0,
- remembers: bool = True,
-) -> Captcha:
- captcha_id = urlsafe_short_hash()
- await db.execute(
- """
- INSERT INTO captcha.captchas (id, wallet, url, memo, description, amount, remembers)
- VALUES (?, ?, ?, ?, ?, ?, ?)
- """,
- (captcha_id, wallet_id, url, memo, description, amount, int(remembers)),
- )
-
- captcha = await get_captcha(captcha_id)
- assert captcha, "Newly created captcha couldn't be retrieved"
- return captcha
-
-
-async def get_captcha(captcha_id: str) -> Optional[Captcha]:
- row = await db.fetchone(
- "SELECT * FROM captcha.captchas WHERE id = ?", (captcha_id,)
- )
-
- return Captcha.from_row(row) if row else None
-
-
-async def get_captchas(wallet_ids: Union[str, List[str]]) -> List[Captcha]:
- if isinstance(wallet_ids, str):
- wallet_ids = [wallet_ids]
-
- q = ",".join(["?"] * len(wallet_ids))
- rows = await db.fetchall(
- f"SELECT * FROM captcha.captchas WHERE wallet IN ({q})", (*wallet_ids,)
- )
-
- return [Captcha.from_row(row) for row in rows]
-
-
-async def delete_captcha(captcha_id: str) -> None:
- await db.execute("DELETE FROM captcha.captchas WHERE id = ?", (captcha_id,))
diff --git a/lnbits/extensions/captcha/migrations.py b/lnbits/extensions/captcha/migrations.py
deleted file mode 100644
index 744fc506..00000000
--- a/lnbits/extensions/captcha/migrations.py
+++ /dev/null
@@ -1,63 +0,0 @@
-async def m001_initial(db):
- """
- Initial captchas table.
- """
- await db.execute(
- """
- CREATE TABLE captcha.captchas (
- id TEXT PRIMARY KEY,
- wallet TEXT NOT NULL,
- secret TEXT NOT NULL,
- url TEXT NOT NULL,
- memo TEXT NOT NULL,
- amount INTEGER NOT NULL,
- time TIMESTAMP NOT NULL DEFAULT """
- + db.timestamp_now
- + """
- );
- """
- )
-
-
-async def m002_redux(db):
- """
- Creates an improved captchas table and migrates the existing data.
- """
- await db.execute("ALTER TABLE captcha.captchas RENAME TO captchas_old")
- await db.execute(
- """
- CREATE TABLE captcha.captchas (
- id TEXT PRIMARY KEY,
- wallet TEXT NOT NULL,
- url TEXT NOT NULL,
- memo TEXT NOT NULL,
- description TEXT NULL,
- amount INTEGER DEFAULT 0,
- time TIMESTAMP NOT NULL DEFAULT """
- + db.timestamp_now
- + """,
- remembers INTEGER DEFAULT 0,
- extras TEXT NULL
- );
- """
- )
-
- for row in [
- list(row) for row in await db.fetchall("SELECT * FROM captcha.captchas_old")
- ]:
- await db.execute(
- """
- INSERT INTO captcha.captchas (
- id,
- wallet,
- url,
- memo,
- amount,
- time
- )
- VALUES (?, ?, ?, ?, ?, ?)
- """,
- (row[0], row[1], row[3], row[4], row[5], row[6]),
- )
-
- await db.execute("DROP TABLE captcha.captchas_old")
diff --git a/lnbits/extensions/captcha/models.py b/lnbits/extensions/captcha/models.py
deleted file mode 100644
index 2b98a91e..00000000
--- a/lnbits/extensions/captcha/models.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import json
-
-from sqlite3 import Row
-from pydantic import BaseModel
-from typing import Optional
-
-
-class Captcha(BaseModel):
- id: str
- wallet: str
- url: str
- memo: str
- description: str
- amount: int
- time: int
- remembers: bool
- extras: Optional[dict]
-
- @classmethod
- def from_row(cls, row: Row) -> "Captcha":
- data = dict(row)
- data["remembers"] = bool(data["remembers"])
- data["extras"] = json.loads(data["extras"]) if data["extras"] else None
- return cls(**data)
diff --git a/lnbits/extensions/captcha/static/js/captcha.js b/lnbits/extensions/captcha/static/js/captcha.js
deleted file mode 100644
index 1da24f57..00000000
--- a/lnbits/extensions/captcha/static/js/captcha.js
+++ /dev/null
@@ -1,82 +0,0 @@
-var ciframeLoaded = !1,
- captchaStyleAdded = !1
-
-function ccreateIframeElement(t = {}) {
- const e = document.createElement('iframe')
- // e.style.marginLeft = "25px",
- ;(e.style.border = 'none'),
- (e.style.width = '100%'),
- (e.style.height = '100%'),
- (e.scrolling = 'no'),
- (e.id = 'captcha-iframe')
- t.dest, t.amount, t.currency, t.label, t.opReturn
- var captchaid = document
- .getElementById('captchascript')
- .getAttribute('data-captchaid')
- var lnbhostsrc = document.getElementById('captchascript').getAttribute('src')
- var lnbhost = lnbhostsrc.split('/captcha/static/js/captcha.js')[0]
- return (e.src = lnbhost + '/captcha/' + captchaid), e
-}
-document.addEventListener('DOMContentLoaded', function () {
- if (captchaStyleAdded) console.log('Captcha already added!')
- else {
- console.log('Adding captcha'), (captchaStyleAdded = !0)
- var t = document.createElement('style')
- t.innerHTML =
- "\t/*Button*/\t\t.button-captcha-filled\t\t\t{\t\t\tdisplay: flex;\t\t\talign-items: center;\t\t\tjustify-content: center;\t\t\twidth: 120px;\t\t\tmin-width: 30px;\t\t\theight: 40px;\t\t\tline-height: 2.5;\t\t\ttext-align: center;\t\t\tcursor: pointer;\t\t\t/* Rectangle 2: */\t\t\tbackground: #FF7979;\t\t\tbox-shadow: 0 2px 4px 0 rgba(0,0,0,0.20);\t\t\tborder-radius: 20px;\t\t\t/* Sign up: */\t\t\tfont-family: 'Avenir-Heavy', Futura, Helvetica, Arial;\t\t\tfont-size: 16px;\t\t\tcolor: #FFFFFF;\t\t}\t\t.button-captcha-filled:hover\t\t{\t\t\tbackground:#FFFFFF;\t\t\tcolor: #FF7979;\t\t\tbox-shadow: 0 0 4px 0 rgba(0,0,0,0.20);\t\t}\t\t.button-captcha-filled:active\t\t{\t\t\tbackground:#FFFFFF;\t\t\tcolor: #FF7979;\t\t\t/*Move it down a little bit*/\t\t\tposition: relative;\t\t\ttop: 1px;\t\t}\t\t.button-captcha-filled-dark\t\t\t{\t\t\tdisplay: flex;\t\t\talign-items: center;\t\t\tjustify-content: center;\t\t\twidth: 120px;\t\t\tmin-width: 30px;\t\t\theight: 40px;\t\t\tline-height: 2.5;\t\t\ttext-align: center;\t\t\tcursor: pointer;\t\t\t/* Rectangle 2: */\t\t\tbackground: #161C38;\t\t\tbox-shadow: 0 0px 4px 0 rgba(0,0,0,0.20);\t\t\tborder-radius: 20px;\t\t\t/* Sign up: */\t\t\tfont-family: 'Avenir-Heavy', Futura, Helvetica, Arial;\t\t\tfont-size: 16px;\t\t\tcolor: #FFFFFF;\t\t}\t\t.button-captcha-filled-dark:hover\t\t{\t\t\tbackground:#FFFFFF;\t\t\tcolor: #161C38;\t\t\tbox-shadow: 0 0px 4px 0 rgba(0,0,0,0.20);\t\t}\t\t.button-captcha-filled-dark:active\t\t{\t\t\tbackground:#FFFFFF;\t\t\tcolor: #161C38;\t\t\t/*Move it down a little bit*/\t\t\tposition: relative;\t\t\ttop: 1px;\t\t}\t\t.modal-captcha-container {\t\t position: fixed;\t\t z-index: 1000;\t\t text-align: left;/*Si no añado esto, a veces hereda el text-align:center del body, y entonces el popup queda movido a la derecha, por center + margin left que aplico*/\t\t left: 0;\t\t top: 0;\t\t width: 100%;\t\t height: 100%;\t\t background-color: rgba(0, 0, 0, 0.5);\t\t opacity: 0;\t\t visibility: hidden;\t\t transform: scale(1.1);\t\t transition: visibility 0s linear 0.25s, opacity 0.25s 0s, transform 0.25s;\t\t}\t\t.modal-captcha-content {\t\t position: absolute;\t\t top: 50%;\t\t left: 50%;\t\t transform: translate(-50%, -50%);\t\t background-color: white;\t\t width: 100%;\t\t height: 100%;\t\t border-radius: 0.5rem;\t\t /*Rounded shadowed borders*/\t\t\tbox-shadow: 2px 2px 4px 0 rgba(0,0,0,0.15);\t\t\tborder-radius: 5px;\t\t}\t\t.close-button-captcha {\t\t float: right;\t\t width: 1.5rem;\t\t line-height: 1.5rem;\t\t text-align: center;\t\t cursor: pointer;\t\t margin-right:20px;\t\t margin-top:10px;\t\t border-radius: 0.25rem;\t\t background-color: lightgray;\t\t}\t\t.close-button-captcha:hover {\t\t background-color: darkgray;\t\t}\t\t.show-modal-captcha {\t\t opacity: 1;\t\t visibility: visible;\t\t transform: scale(1.0);\t\t transition: visibility 0s linear 0s, opacity 0.25s 0s, transform 0.25s;\t\t}\t\t/* Mobile */\t\t@media screen and (min-device-width: 160px) and ( max-width: 1077px ) /*No tendria ni por que poner un min-device, porq abarca todo lo humano...*/\t\t{\t\t}"
- var e = document.querySelector('script')
- e.parentNode.insertBefore(t, e)
- var i = document.getElementById('captchacheckbox'),
- n = i.dataset,
- o = 'true' === n.dark
- var a = document.createElement('div')
- ;(a.className += ' modal-captcha-container'),
- (a.innerHTML =
- '\t\tGET /captcha/api/v1/captchas
- {"X-Api-Key": <invoice_key>}[<captcha_object>, ...]
- curl -X GET {{ request.url_root }}captcha/api/v1/captchas -H
- "X-Api-Key: {{ g.user.wallets[0].inkey }}"
-
- POST /captcha/api/v1/captchas
- {"X-Api-Key": <admin_key>}{"amount": <integer>, "description": <string>, "memo":
- <string>, "remembers": <boolean>, "url":
- <string>}
- {"amount": <integer>, "description": <string>, "id":
- <string>, "memo": <string>, "remembers": <boolean>,
- "time": <int>, "url": <string>, "wallet":
- <string>}
- curl -X POST {{ request.url_root }}captcha/api/v1/captchas -d
- '{"url": <string>, "memo": <string>, "description":
- <string>, "amount": <integer>, "remembers":
- <boolean>}' -H "Content-type: application/json" -H "X-Api-Key:
- {{ g.user.wallets[0].adminkey }}"
-
- POST
- /captcha/api/v1/captchas/<captcha_id>/invoice
- {"amount": <integer>}
- {"payment_hash": <string>, "payment_request":
- <string>}
- curl -X POST {{ request.url_root
- }}captcha/api/v1/captchas/<captcha_id>/invoice -d '{"amount":
- <integer>}' -H "Content-type: application/json"
-
- POST
- /captcha/api/v1/captchas/<captcha_id>/check_invoice
- {"payment_hash": <string>}
- {"paid": false}{"paid": true, "url": <string>, "remembers":
- <boolean>}
- curl -X POST {{ request.url_root
- }}captcha/api/v1/captchas/<captcha_id>/check_invoice -d
- '{"payment_hash": <string>}' -H "Content-type: application/json"
-
- DELETE
- /captcha/api/v1/captchas/<captcha_id>
- {"X-Api-Key": <admin_key>}
- curl -X DELETE {{ request.url_root
- }}captcha/api/v1/captchas/<captcha_id> -H "X-Api-Key: {{
- g.user.wallets[0].adminkey }}"
-
- {{ captcha.description }}
- {% endif %} -
- Captcha accepted. You are probably human.
-
-
- {{ qrCodeDialog.data.snippet }}
-
- - Copy the snippet above and paste into your website/form. The checkbox - can be in checked state only after user pays. -
-
- ID: {{ qrCodeDialog.data.id }}
- Amount: {{ qrCodeDialog.data.amount }}
-
-
- StreamerCopilot: get tips via static QR (lnurl-pay) and show an
- animation
-
- Created by, Ben Arc
-
POST /copilot/api/v1/copilot
- {"X-Api-Key": <admin_key>}[<copilot_object>, ...]
- curl -X POST {{ request.url_root }}api/v1/copilot -d '{"title":
- <string>, "animation": <string>,
- "show_message":<string>, "amount": <integer>,
- "lnurl_title": <string>}' -H "Content-type: application/json"
- -H "X-Api-Key: {{g.user.wallets[0].adminkey }}"
-
- PUT
- /copilot/api/v1/copilot/<copilot_id>
- {"X-Api-Key": <admin_key>}[<copilot_object>, ...]
- curl -X POST {{ request.url_root
- }}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:
- {{g.user.wallets[0].adminkey }}"
-
- GET
- /copilot/api/v1/copilot/<copilot_id>
- {"X-Api-Key": <invoice_key>}[<copilot_object>, ...]
- curl -X GET {{ request.url_root }}api/v1/copilot/<copilot_id>
- -H "X-Api-Key: {{ g.user.wallets[0].inkey }}"
-
- GET /copilot/api/v1/copilots
- {"X-Api-Key": <invoice_key>}[<copilot_object>, ...]
- curl -X GET {{ request.url_root }}api/v1/copilots -H "X-Api-Key: {{
- g.user.wallets[0].inkey }}"
-
- DELETE
- /copilot/api/v1/copilot/<copilot_id>
- {"X-Api-Key": <admin_key>}
- curl -X DELETE {{ request.url_root
- }}api/v1/copilot/<copilot_id> -H "X-Api-Key: {{
- g.user.wallets[0].adminkey }}"
-
- GET
- /api/v1/copilot/ws/<copilot_id>/<comment>/<data>
- {"X-Api-Key": <admin_key>}
- curl -X GET {{ request.url_root }}/api/v1/copilot/ws/<string,
- copilot_id>/<string, comment>/<string, gif name> -H
- "X-Api-Key: {{ g.user.wallets[0].adminkey }}"
-
- - Powered by LNbits/StreamerCopilot -
-
-
-
-curl -X GET http://YOUR-TOR-ADDRESS
diff --git a/lnbits/extensions/diagonalley/__init__.py b/lnbits/extensions/diagonalley/__init__.py
deleted file mode 100644
index ac907f5c..00000000
--- a/lnbits/extensions/diagonalley/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from quart import Blueprint
-
-
-diagonalley_ext: Blueprint = Blueprint(
- "diagonalley", __name__, static_folder="static", template_folder="templates"
-)
-
-
-from .views_api import * # noqa
-from .views import * # noqa
diff --git a/lnbits/extensions/diagonalley/config.json.example b/lnbits/extensions/diagonalley/config.json.example
deleted file mode 100644
index 057d0f23..00000000
--- a/lnbits/extensions/diagonalley/config.json.example
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "Diagon Alley",
- "short_description": "Movable anonymous market stand",
- "icon": "add_shopping_cart",
- "contributors": ["benarc"]
-}
diff --git a/lnbits/extensions/diagonalley/crud.py b/lnbits/extensions/diagonalley/crud.py
deleted file mode 100644
index 971cd449..00000000
--- a/lnbits/extensions/diagonalley/crud.py
+++ /dev/null
@@ -1,308 +0,0 @@
-from base64 import urlsafe_b64encode
-from uuid import uuid4
-from typing import List, Optional, Union
-import httpx
-from lnbits.db import open_ext_db
-from lnbits.settings import WALLET
-from .models import Products, Orders, Indexers
-import re
-
-regex = re.compile(
- r"^(?:http|ftp)s?://" # http:// or https://
- r"(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|"
- r"localhost|"
- r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})"
- r"(?::\d+)?"
- r"(?:/?|[/?]\S+)$",
- re.IGNORECASE,
-)
-
-###Products
-
-
-def create_diagonalleys_product(
- *,
- wallet_id: str,
- product: str,
- categories: str,
- description: str,
- image: str,
- price: int,
- quantity: int,
-) -> Products:
- with open_ext_db("diagonalley") as db:
- product_id = urlsafe_b64encode(uuid4().bytes_le).decode("utf-8")
- db.execute(
- """
- INSERT INTO diagonalley.products (id, wallet, product, categories, description, image, price, quantity)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
- """,
- (
- product_id,
- wallet_id,
- product,
- categories,
- description,
- image,
- price,
- quantity,
- ),
- )
-
- return get_diagonalleys_product(product_id)
-
-
-def update_diagonalleys_product(product_id: str, **kwargs) -> Optional[Indexers]:
- q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
-
- with open_ext_db("diagonalley") as db:
- db.execute(
- f"UPDATE diagonalley.products SET {q} WHERE id = ?",
- (*kwargs.values(), product_id),
- )
- row = db.fetchone(
- "SELECT * FROM diagonalley.products WHERE id = ?", (product_id,)
- )
-
- return get_diagonalleys_indexer(product_id)
-
-
-def get_diagonalleys_product(product_id: str) -> Optional[Products]:
- with open_ext_db("diagonalley") as db:
- row = db.fetchone(
- "SELECT * FROM diagonalley.products WHERE id = ?", (product_id,)
- )
-
- return Products(**row) if row else None
-
-
-def get_diagonalleys_products(wallet_ids: Union[str, List[str]]) -> List[Products]:
- if isinstance(wallet_ids, str):
- wallet_ids = [wallet_ids]
-
- with open_ext_db("diagonalley") as db:
- q = ",".join(["?"] * len(wallet_ids))
- rows = db.fetchall(
- f"SELECT * FROM diagonalley.products WHERE wallet IN ({q})", (*wallet_ids,)
- )
-
- return [Products(**row) for row in rows]
-
-
-def delete_diagonalleys_product(product_id: str) -> None:
- with open_ext_db("diagonalley") as db:
- db.execute("DELETE FROM diagonalley.products WHERE id = ?", (product_id,))
-
-
-###Indexers
-
-
-def create_diagonalleys_indexer(
- wallet_id: str,
- shopname: str,
- indexeraddress: str,
- shippingzone1: str,
- shippingzone2: str,
- zone1cost: int,
- zone2cost: int,
- email: str,
-) -> Indexers:
- with open_ext_db("diagonalley") as db:
- indexer_id = urlsafe_b64encode(uuid4().bytes_le).decode("utf-8")
- db.execute(
- """
- INSERT INTO diagonalley.indexers (id, wallet, shopname, indexeraddress, online, rating, shippingzone1, shippingzone2, zone1cost, zone2cost, email)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- """,
- (
- indexer_id,
- wallet_id,
- shopname,
- indexeraddress,
- False,
- 0,
- shippingzone1,
- shippingzone2,
- zone1cost,
- zone2cost,
- email,
- ),
- )
- return get_diagonalleys_indexer(indexer_id)
-
-
-def update_diagonalleys_indexer(indexer_id: str, **kwargs) -> Optional[Indexers]:
- q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
-
- with open_ext_db("diagonalley") as db:
- db.execute(
- f"UPDATE diagonalley.indexers SET {q} WHERE id = ?",
- (*kwargs.values(), indexer_id),
- )
- row = db.fetchone(
- "SELECT * FROM diagonalley.indexers WHERE id = ?", (indexer_id,)
- )
-
- return get_diagonalleys_indexer(indexer_id)
-
-
-def get_diagonalleys_indexer(indexer_id: str) -> Optional[Indexers]:
- with open_ext_db("diagonalley") as db:
- roww = db.fetchone(
- "SELECT * FROM diagonalley.indexers WHERE id = ?", (indexer_id,)
- )
- try:
- x = httpx.get(roww["indexeraddress"] + "/" + roww["ratingkey"])
- if x.status_code == 200:
- print(x)
- print("poo")
- with open_ext_db("diagonalley") as db:
- db.execute(
- "UPDATE diagonalley.indexers SET online = ? WHERE id = ?",
- (
- True,
- indexer_id,
- ),
- )
- else:
- with open_ext_db("diagonalley") as db:
- db.execute(
- "UPDATE diagonalley.indexers SET online = ? WHERE id = ?",
- (
- False,
- indexer_id,
- ),
- )
- except:
- print("An exception occurred")
- with open_ext_db("diagonalley") as db:
- row = db.fetchone(
- "SELECT * FROM diagonalley.indexers WHERE id = ?", (indexer_id,)
- )
- return Indexers(**row) if row else None
-
-
-def get_diagonalleys_indexers(wallet_ids: Union[str, List[str]]) -> List[Indexers]:
- if isinstance(wallet_ids, str):
- wallet_ids = [wallet_ids]
-
- with open_ext_db("diagonalley") as db:
- q = ",".join(["?"] * len(wallet_ids))
- rows = db.fetchall(
- f"SELECT * FROM diagonalley.indexers WHERE wallet IN ({q})", (*wallet_ids,)
- )
-
- for r in rows:
- try:
- x = httpx.get(r["indexeraddress"] + "/" + r["ratingkey"])
- if x.status_code == 200:
- with open_ext_db("diagonalley") as db:
- db.execute(
- "UPDATE diagonalley.indexers SET online = ? WHERE id = ?",
- (
- True,
- r["id"],
- ),
- )
- else:
- with open_ext_db("diagonalley") as db:
- db.execute(
- "UPDATE diagonalley.indexers SET online = ? WHERE id = ?",
- (
- False,
- r["id"],
- ),
- )
- except:
- print("An exception occurred")
- with open_ext_db("diagonalley") as db:
- q = ",".join(["?"] * len(wallet_ids))
- rows = db.fetchall(
- f"SELECT * FROM diagonalley.indexers WHERE wallet IN ({q})", (*wallet_ids,)
- )
- return [Indexers(**row) for row in rows]
-
-
-def delete_diagonalleys_indexer(indexer_id: str) -> None:
- with open_ext_db("diagonalley") as db:
- db.execute("DELETE FROM diagonalley.indexers WHERE id = ?", (indexer_id,))
-
-
-###Orders
-
-
-def create_diagonalleys_order(
- *,
- productid: str,
- wallet: str,
- product: str,
- quantity: int,
- shippingzone: str,
- address: str,
- email: str,
- invoiceid: str,
- paid: bool,
- shipped: bool,
-) -> Indexers:
- with open_ext_db("diagonalley") as db:
- order_id = urlsafe_b64encode(uuid4().bytes_le).decode("utf-8")
- db.execute(
- """
- INSERT INTO diagonalley.orders (id, productid, wallet, product, quantity, shippingzone, address, email, invoiceid, paid, shipped)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- """,
- (
- order_id,
- productid,
- wallet,
- product,
- quantity,
- shippingzone,
- address,
- email,
- invoiceid,
- False,
- False,
- ),
- )
-
- return get_diagonalleys_order(order_id)
-
-
-def get_diagonalleys_order(order_id: str) -> Optional[Orders]:
- with open_ext_db("diagonalley") as db:
- row = db.fetchone("SELECT * FROM diagonalley.orders WHERE id = ?", (order_id,))
-
- return Orders(**row) if row else None
-
-
-def get_diagonalleys_orders(wallet_ids: Union[str, List[str]]) -> List[Orders]:
- if isinstance(wallet_ids, str):
- wallet_ids = [wallet_ids]
-
- with open_ext_db("diagonalley") as db:
- q = ",".join(["?"] * len(wallet_ids))
- rows = db.fetchall(
- f"SELECT * FROM diagonalley.orders WHERE wallet IN ({q})", (*wallet_ids,)
- )
- for r in rows:
- PAID = (await WALLET.get_invoice_status(r["invoiceid"])).paid
- if PAID:
- with open_ext_db("diagonalley") as db:
- db.execute(
- "UPDATE diagonalley.orders SET paid = ? WHERE id = ?",
- (
- True,
- r["id"],
- ),
- )
- rows = db.fetchall(
- f"SELECT * FROM diagonalley.orders WHERE wallet IN ({q})",
- (*wallet_ids,),
- )
- return [Orders(**row) for row in rows]
-
-
-def delete_diagonalleys_order(order_id: str) -> None:
- with open_ext_db("diagonalley") as db:
- db.execute("DELETE FROM diagonalley.orders WHERE id = ?", (order_id,))
diff --git a/lnbits/extensions/diagonalley/migrations.py b/lnbits/extensions/diagonalley/migrations.py
deleted file mode 100644
index 9f2b787f..00000000
--- a/lnbits/extensions/diagonalley/migrations.py
+++ /dev/null
@@ -1,60 +0,0 @@
-async def m001_initial(db):
- """
- Initial products table.
- """
- await db.execute(
- """
- CREATE TABLE diagonalley.products (
- id TEXT PRIMARY KEY,
- wallet TEXT NOT NULL,
- product TEXT NOT NULL,
- categories TEXT NOT NULL,
- description TEXT NOT NULL,
- image TEXT NOT NULL,
- price INTEGER NOT NULL,
- quantity INTEGER NOT NULL
- );
- """
- )
-
- """
- Initial indexers table.
- """
- await db.execute(
- """
- CREATE TABLE diagonalley.indexers (
- id TEXT PRIMARY KEY,
- wallet TEXT NOT NULL,
- shopname TEXT NOT NULL,
- indexeraddress TEXT NOT NULL,
- online BOOLEAN NOT NULL,
- rating INTEGER NOT NULL,
- shippingzone1 TEXT NOT NULL,
- shippingzone2 TEXT NOT NULL,
- zone1cost INTEGER NOT NULL,
- zone2cost INTEGER NOT NULL,
- email TEXT NOT NULL
- );
- """
- )
-
- """
- Initial orders table.
- """
- await db.execute(
- """
- CREATE TABLE diagonalley.orders (
- id TEXT PRIMARY KEY,
- productid TEXT NOT NULL,
- wallet TEXT NOT NULL,
- product TEXT NOT NULL,
- quantity INTEGER NOT NULL,
- shippingzone INTEGER NOT NULL,
- address TEXT NOT NULL,
- email TEXT NOT NULL,
- invoiceid TEXT NOT NULL,
- paid BOOLEAN NOT NULL,
- shipped BOOLEAN NOT NULL
- );
- """
- )
diff --git a/lnbits/extensions/diagonalley/models.py b/lnbits/extensions/diagonalley/models.py
deleted file mode 100644
index ab1c592d..00000000
--- a/lnbits/extensions/diagonalley/models.py
+++ /dev/null
@@ -1,41 +0,0 @@
-from typing import NamedTuple
-from sqlite3 import Row
-from pydantic import BaseModel
-
-class Indexers(BaseModel):
- id: str
- wallet: str
- shopname: str
- indexeraddress: str
- online: bool
- rating: str
- shippingzone1: str
- shippingzone2: str
- zone1cost: int
- zone2cost: int
- email: str
-
-
-class Products(BaseModel):
- id: str
- wallet: str
- product: str
- categories: str
- description: str
- image: str
- price: int
- quantity: int
-
-
-class Orders(BaseModel):
- id: str
- productid: str
- wallet: str
- product: str
- quantity: int
- shippingzone: int
- address: str
- email: str
- invoiceid: str
- paid: bool
- shipped: bool
diff --git a/lnbits/extensions/diagonalley/templates/diagonalley/_api_docs.html b/lnbits/extensions/diagonalley/templates/diagonalley/_api_docs.html
deleted file mode 100644
index 585e8d7c..00000000
--- a/lnbits/extensions/diagonalley/templates/diagonalley/_api_docs.html
+++ /dev/null
@@ -1,122 +0,0 @@
-
- Make a list of products to sell, point your list of products at a public
- indexer. Buyers browse your products on the indexer, and pay you
- directly. Ratings are managed by the indexer. Your stall can be listed
- in multiple indexers, even over TOR, if you wish to be anonymous.
- More information on the
- Diagon Alley Protocol
-
- Created by, Ben Arc
-
GET
- /api/v1/diagonalley/stall/products/<indexer_id>
- Product JSON list
- curl -X GET {{ request.url_root
- }}diagonalley/api/v1/diagonalley/stall/products/<indexer_id>
- POST
- /api/v1/diagonalley/stall/order/<indexer_id>
- {"id": <string>, "address": <string>, "shippingzone":
- <integer>, "email": <string>, "quantity":
- <integer>}
- {"checking_id": <string>,"payment_request":
- <string>}
- curl -X POST {{ request.url_root
- }}diagonalley/api/v1/diagonalley/stall/order/<indexer_id> -d
- '{"id": <product_id&>, "email": <customer_email>,
- "address": <customer_address>, "quantity": 2, "shippingzone":
- 1}' -H "Content-type: application/json"
-
- GET
- /diagonalley/api/v1/diagonalley/stall/checkshipped/<checking_id>
- {"shipped": <boolean>}
- curl -X GET {{ request.url_root
- }}diagonalley/api/v1/diagonalley/stall/checkshipped/<checking_id>
- -H "Content-type: application/json"
-
- Events alows you to make a wave of tickets for an event, each ticket is
- in the form of a unqiue QRcode, which the user presents at registration.
- Events comes with a shareable ticket scanner, which can be used to
- register attendees.
-
- Created by, Ben Arc
-
-
You'll be redirected in a few moments...
-
-
-
-curl -H "Content-type: application/json" -X POST https://YOUR-LNBITS/YOUR-EXTENSION/api/v1/EXAMPLE -d '{"amount":"100","memo":"example"}' -H "X-Api-Key: YOUR_WALLET-ADMIN/INVOICE-KEY"
diff --git a/lnbits/extensions/example/__init__.py b/lnbits/extensions/example/__init__.py
deleted file mode 100644
index e16e0372..00000000
--- a/lnbits/extensions/example/__init__.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from quart import Blueprint
-from lnbits.db import Database
-
-db = Database("ext_example")
-
-example_ext: Blueprint = Blueprint(
- "example", __name__, static_folder="static", template_folder="templates"
-)
-
-
-from .views_api import * # noqa
-from .views import * # noqa
diff --git a/lnbits/extensions/example/config.json b/lnbits/extensions/example/config.json
deleted file mode 100644
index 55389373..00000000
--- a/lnbits/extensions/example/config.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "Build your own!",
- "short_description": "Join us, make an extension",
- "icon": "info",
- "contributors": ["github_username"]
-}
diff --git a/lnbits/extensions/example/migrations.py b/lnbits/extensions/example/migrations.py
deleted file mode 100644
index 99d7c362..00000000
--- a/lnbits/extensions/example/migrations.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# async def m001_initial(db):
-# await db.execute(
-# f"""
-# CREATE TABLE example.example (
-# id TEXT PRIMARY KEY,
-# wallet TEXT NOT NULL,
-# time TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}
-# );
-# """
-# )
diff --git a/lnbits/extensions/example/models.py b/lnbits/extensions/example/models.py
deleted file mode 100644
index be523233..00000000
--- a/lnbits/extensions/example/models.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# from sqlite3 import Row
-# from typing import NamedTuple
-
-
-# class Example(NamedTuple):
-# id: str
-# wallet: str
-#
-# @classmethod
-# def from_row(cls, row: Row) -> "Example":
-# return cls(**dict(row))
diff --git a/lnbits/extensions/example/templates/example/index.html b/lnbits/extensions/example/templates/example/index.html
deleted file mode 100644
index d732ef37..00000000
--- a/lnbits/extensions/example/templates/example/index.html
+++ /dev/null
@@ -1,59 +0,0 @@
-{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
-%} {% block page %}
-- A magical "g" is always available, with info about the user, wallets and - extensions: -
-{% raw %}{{ g }}{% endraw %}
- - Hivemind is a Bitcoin sidechain - project for a peer-to-peer oracle protocol that absorbs accurate data into - a blockchain so that Bitcoin users can speculate in prediction markets. -
-- These markets have the potential to revolutionize the emergence of - diffusion of knowledge in society and fix all sorts of problems in the - world. -
-- This extension will become fully operative when the - BIP300 soft-fork gets activated and - Bitcoin Hivemind is launched. -
-GET /jukebox/api/v1/jukebox
- {"X-Api-Key": <admin_key>}[<jukebox_object>, ...]
- curl -X GET {{ request.url_root }}api/v1/jukebox -H "X-Api-Key: {{
- g.user.wallets[0].adminkey }}"
-
- GET
- /jukebox/api/v1/jukebox/<juke_id>
- {"X-Api-Key": <admin_key>}<jukebox_object>
- curl -X GET {{ request.url_root }}api/v1/jukebox/<juke_id> -H
- "X-Api-Key: {{ g.user.wallets[0].adminkey }}"
-
- POST/PUT
- /jukebox/api/v1/jukebox/
- {"X-Api-Key": <admin_key>}<jukbox_object>
- curl -X POST {{ request.url_root }}api/v1/jukebox/ -d '{"user":
- <string, user_id>, "title": <string>,
- "wallet":<string>, "sp_user": <string,
- spotify_user_account>, "sp_secret": <string,
- spotify_user_secret>, "sp_access_token": <string,
- not_required>, "sp_refresh_token": <string, not_required>,
- "sp_device": <string, spotify_user_secret>, "sp_playlists":
- <string, not_required>, "price": <integer, not_required>}'
- -H "Content-type: application/json" -H "X-Api-Key:
- {{g.user.wallets[0].adminkey }}"
-
- DELETE
- /jukebox/api/v1/jukebox/<juke_id>
- {"X-Api-Key": <admin_key>}<jukebox_object>
- curl -X DELETE {{ request.url_root }}api/v1/jukebox/<juke_id>
- -H "X-Api-Key: {{ g.user.wallets[0].adminkey }}"
-
-
- To use this extension you need a Spotify client ID and client secret.
- You get these by creating an app in the Spotify developers dashboard
- here.
-
- In the app go to edit-settings, set the redirect URI to this link
- Currently playing
-Pick a song
-Add tracks, profit.
-GET
- /livestream/api/v1/livestream
- {"X-Api-Key": <invoice_key>}[<livestream_object>, ...]
- curl -X GET {{ request.url_root }}api/v1/livestream -H "X-Api-Key: {{
- g.user.wallets[0].inkey }}"
-
- PUT
- /livestream/api/v1/livestream/track/<track_id>
- {"X-Api-Key": <invoice_key>}curl -X PUT {{ request.url_root
- }}api/v1/livestream/track/<track_id> -H "X-Api-Key: {{
- g.user.wallets[0].inkey }}"
-
- PUT
- /livestream/api/v1/livestream/fee/<fee_pct>
- {"X-Api-Key": <invoice_key>}curl -X PUT {{ request.url_root
- }}api/v1/livestream/fee/<fee_pct> -H "X-Api-Key: {{
- g.user.wallets[0].inkey }}"
-
- POST
- /livestream/api/v1/livestream/tracks
- {"X-Api-Key": <invoice_key>}{"name": <string>, "download_url": <string>,
- "price_msat": <integer>, "producer_id": <integer>,
- "producer_name": <string>}
- curl -X POST {{ request.url_root }}api/v1/livestream/tracks -d
- '{"name": <string>, "download_url": <string>,
- "price_msat": <integer>, "producer_id": <integer>,
- "producer_name": <string>}' -H "Content-type: application/json"
- -H "X-Api-Key: {{ g.user.wallets[0].adminkey }}"
-
- DELETE
- /livestream/api/v1/livestream/tracks/<track_id>
- {"X-Api-Key": <invoice_key>}
- curl -X DELETE {{ request.url_root
- }}api/v1/livestream/tracks/<track_id> -H "X-Api-Key: {{
- g.user.wallets[0].inkey }}"
-
- - Standalone QR Code for this track -
- -Add a wallet / Import wallet on BlueWallet or
- Settings / Add a new node on Zeus.
- - LndHub is a protocol invented by - BlueWallet that allows mobile - wallets to query payments and balances, generate invoices and make - payments from accounts that exist on a server. The protocol is a - collection of HTTP endpoints exposed through the internet. -
-- For a wallet that supports it, reading a QR code that contains the URL - along with secret access credentials should enable access. Currently it - is supported by Zeus and - BlueWallet. -
-curl -X GET {{ request.url_root }}api/v1/links -H "X-Api-Key: {{
- g.user.wallets[0].inkey }}"
+ user.wallets[0].inkey }}"
@@ -27,7 +27,8 @@
GET /lnurlp/api/v1/links/<pay_id>GET
+ /lnurlp/api/v1/links/<pay_id>
{"X-Api-Key": <invoice_key>}curl -X GET {{ request.url_root }}api/v1/links/<pay_id> -H
- "X-Api-Key: {{ g.user.wallets[0].inkey }}"
+ "X-Api-Key: {{ user.wallets[0].inkey }}"
{"X-Api-Key": <admin_key>}{"description": <string> "amount": <integer> "max": <integer> "min": <integer> "comment_chars": <integer>}
+ {"description": <string> "amount": <integer> "max":
+ <integer> "min": <integer> "comment_chars":
+ <integer>}
curl -X POST {{ request.url_root }}api/v1/links -d '{"description":
- <string>, "amount": <integer>, "max": <integer>, "min": <integer>, "comment_chars": <integer>}' -H "Content-type:
- application/json" -H "X-Api-Key: {{ g.user.wallets[0].adminkey }}"
+ <string>, "amount": <integer>, "max": <integer>,
+ "min": <integer>, "comment_chars": <integer>}' -H
+ "Content-type: application/json" -H "X-Api-Key: {{
+ user.wallets[0].adminkey }}"
@@ -95,7 +102,7 @@
>curl -X PUT {{ request.url_root }}api/v1/links/<pay_id> -d
'{"description": <string>, "amount": <integer>}' -H
"Content-type: application/json" -H "X-Api-Key: {{
- g.user.wallets[0].adminkey }}"
+ user.wallets[0].adminkey }}"
@@ -120,7 +127,7 @@
curl -X DELETE {{ request.url_root }}api/v1/links/<pay_id> -H
- "X-Api-Key: {{ g.user.wallets[0].adminkey }}"
+ "X-Api-Key: {{ user.wallets[0].adminkey }}"
diff --git a/lnbits/extensions/lnurlp/templates/lnurlp/display.html b/lnbits/extensions/lnurlp/templates/lnurlp/display.html
index a2e0389c..08e4de15 100644
--- a/lnbits/extensions/lnurlp/templates/lnurlp/display.html
+++ b/lnbits/extensions/lnurlp/templates/lnurlp/display.html
@@ -4,10 +4,10 @@
-
-- Note that if you restart your device, your device will generate a - new url. If anyone is using your old one for wallets, lnurls, - etc., whatever they are doing will stop working. -
- Created by - Supertestnet. -GET /paywall/api/v1/paywalls
- {"X-Api-Key": <invoice_key>}[<paywall_object>, ...]
- curl -X GET {{ request.url_root }}api/v1/paywalls -H "X-Api-Key: {{
- g.user.wallets[0].inkey }}"
-
- POST /paywall/api/v1/paywalls
- {"X-Api-Key": <admin_key>}{"amount": <integer>, "description": <string>, "memo":
- <string>, "remembers": <boolean>, "url":
- <string>}
- {"amount": <integer>, "description": <string>, "id":
- <string>, "memo": <string>, "remembers": <boolean>,
- "time": <int>, "url": <string>, "wallet":
- <string>}
- curl -X POST {{ request.url_root }}api/v1/paywalls -d '{"url":
- <string>, "memo": <string>, "description": <string>,
- "amount": <integer>, "remembers": <boolean>}' -H
- "Content-type: application/json" -H "X-Api-Key: {{
- g.user.wallets[0].adminkey }}"
-
- POST
- /paywall/api/v1/paywalls/<paywall_id>/invoice
- {"amount": <integer>}
- {"payment_hash": <string>, "payment_request":
- <string>}
- curl -X POST {{ request.url_root
- }}api/v1/paywalls/<paywall_id>/invoice -d '{"amount":
- <integer>}' -H "Content-type: application/json"
-
- POST
- /paywall/api/v1/paywalls/<paywall_id>/check_invoice
- {"payment_hash": <string>}
- {"paid": false}{"paid": true, "url": <string>, "remembers":
- <boolean>}
- curl -X POST {{ request.url_root
- }}api/v1/paywalls/<paywall_id>/check_invoice -d
- '{"payment_hash": <string>}' -H "Content-type: application/json"
-
- DELETE
- /paywall/api/v1/paywalls/<paywall_id>
- {"X-Api-Key": <admin_key>}
- curl -X DELETE {{ request.url_root
- }}api/v1/paywalls/<paywall_id> -H "X-Api-Key: {{
- g.user.wallets[0].adminkey }}"
-
- {{ paywall.description }}
- {% endif %} -
- You can access the URL behind this paywall:
- {% raw %}{{ redirectUrl }}{% endraw %}
-
- SatsPayServer, create Onchain/LN charges.
WARNING: If using with the
- WatchOnly extension, we highly reccomend using a fresh extended public Key
- specifically for SatsPayServer!
-
- Created by, Ben Arc
-
POST /satspay/api/v1/charge
- {"X-Api-Key": <admin_key>}[<charge_object>, ...]
- curl -X POST {{ request.url_root }}api/v1/charge -d
- '{"onchainwallet": <string, watchonly_wallet_id>,
- "description": <string>, "webhook":<string>, "time":
- <integer>, "amount": <integer>, "lnbitswallet":
- <string, lnbits_wallet_id>}' -H "Content-type:
- application/json" -H "X-Api-Key: {{g.user.wallets[0].adminkey }}"
-
- PUT
- /satspay/api/v1/charge/<charge_id>
- {"X-Api-Key": <admin_key>}[<charge_object>, ...]
- curl -X POST {{ request.url_root }}api/v1/charge/<charge_id>
- -d '{"onchainwallet": <string, watchonly_wallet_id>,
- "description": <string>, "webhook":<string>, "time":
- <integer>, "amount": <integer>, "lnbitswallet":
- <string, lnbits_wallet_id>}' -H "Content-type:
- application/json" -H "X-Api-Key: {{g.user.wallets[0].adminkey }}"
-
- GET
- /satspay/api/v1/charge/<charge_id>
- {"X-Api-Key": <invoice_key>}[<charge_object>, ...]
- curl -X GET {{ request.url_root }}api/v1/charge/<charge_id>
- -H "X-Api-Key: {{ g.user.wallets[0].inkey }}"
-
- GET /satspay/api/v1/charges
- {"X-Api-Key": <invoice_key>}[<charge_object>, ...]
- curl -X GET {{ request.url_root }}api/v1/charges -H "X-Api-Key: {{
- g.user.wallets[0].inkey }}"
-
- DELETE
- /satspay/api/v1/charge/<charge_id>
- {"X-Api-Key": <admin_key>}
- curl -X DELETE {{ request.url_root
- }}api/v1/charge/<charge_id> -H "X-Api-Key: {{
- g.user.wallets[0].adminkey }}"
-
- GET
- /satspay/api/v1/charges/balance/<charge_id>
- [<charge_object>, ...]
- curl -X GET {{ request.url_root
- }}api/v1/charges/balance/<charge_id> -H "X-Api-Key: {{
- g.user.wallets[0].inkey }}"
-
- - Add some wallets to the list of "Target Wallets", each with an - associated percent. After saving, every time any payment - arrives at the "Source Wallet" that payment will be split with the - target wallets according to their percent. -
-This is valid for every payment, doesn't matter how it was created.
-Target wallets can be any wallet from this same LNbits instance.
-- To remove a wallet from the targets list, just erase its fields and - save. To remove all, click "Clear" then save. -
-GET
- /splitpayments/api/v1/targets
- {"X-Api-Key": <admin_key>}[{"wallet": <wallet id>, "alias": <chosen name for this
- wallet>, "percent": <number between 1 and 100>}, ...]
- curl -X GET {{ request.url_root }}api/v1/livestream -H "X-Api-Key: {{
- g.user.wallets[0].inkey }}"
-
- PUT
- /splitpayments/api/v1/targets
- {"X-Api-Key": <admin_key>}curl -X PUT {{ request.url_root }}api/v1/splitpayments/targets -H
- "X-Api-Key: {{ g.user.wallets[0].adminkey }}" -H 'Content-Type:
- application/json' -d '{"targets": [{"wallet": <wallet id or invoice
- key>, "alias": <name to identify this>, "percent": <number
- between 1 and 100>}, ...]}'
-
-
- Accept Bitcoin donations on Twitch, and integrate them into your alerts.
- Present your viewers with a simple donation page, and add those donations
- to Streamlabs to play alerts on your stream!
- For detailed setup instructions, check out
- this guide!
-
- Created by, Fitti
-
-4. Get Cloudflare API TOKEN
-
-
-5. Open the LNBits subdomains extension and register your domain
-6. Click on the button in the table to open the public form that was generated for your domain
-
- - Extension also supports webhooks so you can get notified when someone buys a new subdomain\
-
-
-## API Endpoints
-
-- **Domains**
- - GET /api/v1/domains
- - POST /api/v1/domains
- - PUT /api/v1/domains/
- Charge people for using your subdomain name...
-
- More details
-
-
- Created by, Kris
-
- Cost per day: {{ domain_cost }} sats
- {% raw %} Total cost: {{amountSats}} sats {% endraw %}
-
- To help developers use LNbits to manage their users, the User Manager
- extension allows the creation and management of users and wallets.
-
For example, a games developer may be developing a game that needs
- each user to have their own wallet, LNbits can be included in the
- develpoers stack as the user and wallet manager.
-
- Created by, Ben Arc
-
GET
- /usermanager/api/v1/users
- JSON list of users
- curl -X GET {{ request.url_root }}usermanager/api/v1/users -H "X-Api-Key: {{
- g.user.wallets[0].inkey }}"
-
- GET
- /usermanager/api/v1/users/<user_id>
- JSON list of users
- curl -X GET {{ request.url_root }}usermanager/api/v1/users/<user_id> -H
- "X-Api-Key: {{ g.user.wallets[0].inkey }}"
-
- GET
- /usermanager/api/v1/wallets/<user_id>
- {"X-Api-Key": <string>}
- JSON wallet data
- curl -X GET {{ request.url_root }}usermanager/api/v1/wallets/<user_id> -H
- "X-Api-Key: {{ g.user.wallets[0].inkey }}"
-
- GET
- /usermanager/api/v1/wallets<wallet_id>
- {"X-Api-Key": <string>}
- JSON a wallets transactions
- curl -X GET {{ request.url_root }}usermanager/api/v1/wallets<wallet_id> -H
- "X-Api-Key: {{ g.user.wallets[0].inkey }}"
-
- POST
- /usermanager/api/v1/users
- {"X-Api-Key": <string>, "Content-type":
- "application/json"}
- {"admin_id": <string>, "user_name": <string>,
- "wallet_name": <string>,"email": <Optional string>
- ,"password": <Optional string>}
- {"id": <string>, "name": <string>, "admin":
- <string>, "email": <string>, "password":
- <string>}
- curl -X POST {{ request.url_root }}usermanager/api/v1/users -d '{"admin_id": "{{
- g.user.id }}", "wallet_name": <string>, "user_name":
- <string>, "email": <Optional string>, "password": <
- Optional string>}' -H "X-Api-Key: {{ g.user.wallets[0].inkey }}" -H
- "Content-type: application/json"
-
- POST
- /usermanager/api/v1/wallets
- {"X-Api-Key": <string>, "Content-type":
- "application/json"}
- {"user_id": <string>, "wallet_name": <string>,
- "admin_id": <string>}
- {"id": <string>, "admin": <string>, "name":
- <string>, "user": <string>, "adminkey": <string>,
- "inkey": <string>}
- curl -X POST {{ request.url_root }}usermanager/api/v1/wallets -d '{"user_id":
- <string>, "wallet_name": <string>, "admin_id": "{{
- g.user.id }}"}' -H "X-Api-Key: {{ g.user.wallets[0].inkey }}" -H
- "Content-type: application/json"
-
- DELETE
- /usermanager/api/v1/users/<user_id>
- {"X-Api-Key": <string>}
- curl -X DELETE {{ request.url_root }}usermanager/api/v1/users/<user_id> -H
- "X-Api-Key: {{ g.user.wallets[0].inkey }}"
-
- DELETE
- /usermanager/api/v1/wallets/<wallet_id>
- {"X-Api-Key": <string>}
- curl -X DELETE {{ request.url_root }}usermanager/api/v1/wallets/<wallet_id>
- -H "X-Api-Key: {{ g.user.wallets[0].inkey }}"
-
- POST
- /usermanager/api/v1/extensions
- {"X-Api-Key": <string>}
- curl -X POST {{ request.url_root }}usermanager/api/v1/extensions -d '{"userid":
- <string>, "extension": <string>, "active":
- <integer>}' -H "X-Api-Key: {{ g.user.wallets[0].inkey }}" -H
- "Content-type: application/json"
-
-
- Watch Only extension uses mempool.space
- For use with "account Extended Public Key"
- https://iancoleman.io/bip39/
-
-
Created by,
- Ben Arc (using,
- Embit)
-
GET /watchonly/api/v1/wallet
- {"X-Api-Key": <invoice_key>}[<wallets_object>, ...]
- curl -X GET {{ request.url_root }}api/v1/wallet -H "X-Api-Key: {{
- g.user.wallets[0].inkey }}"
-
- GET
- /watchonly/api/v1/wallet/<wallet_id>
- {"X-Api-Key": <invoice_key>}[<wallet_object>, ...]
- curl -X GET {{ request.url_root }}api/v1/wallet/<wallet_id>
- -H "X-Api-Key: {{ g.user.wallets[0].inkey }}"
-
- POST /watchonly/api/v1/wallet
- {"X-Api-Key": <admin_key>}[<wallet_object>, ...]
- curl -X POST {{ request.url_root }}api/v1/wallet -d '{"title":
- <string>, "masterpub": <string>}' -H "Content-type:
- application/json" -H "X-Api-Key: {{ g.user.wallets[0].adminkey }}"
-
- DELETE
- /watchonly/api/v1/wallet/<wallet_id>
- {"X-Api-Key": <admin_key>}
- curl -X DELETE {{ request.url_root
- }}api/v1/wallet/<wallet_id> -H "X-Api-Key: {{
- g.user.wallets[0].adminkey }}"
-
- GET
- /watchonly/api/v1/addresses/<wallet_id>
- {"X-Api-Key": <invoice_key>}[<address_object>, ...]
- curl -X GET {{ request.url_root
- }}api/v1/addresses/<wallet_id> -H "X-Api-Key: {{
- g.user.wallets[0].inkey }}"
-
- GET
- /watchonly/api/v1/address/<wallet_id>
- {"X-Api-Key": <invoice_key>}[<address_object>, ...]
- curl -X GET {{ request.url_root }}api/v1/address/<wallet_id>
- -H "X-Api-Key: {{ g.user.wallets[0].inkey }}"
-
- GET /watchonly/api/v1/mempool
- {"X-Api-Key": <admin_key>}[<mempool_object>, ...]
- curl -X GET {{ request.url_root }}api/v1/mempool -H "X-Api-Key: {{
- g.user.wallets[0].adminkey }}"
-
- POST
- /watchonly/api/v1/mempool
- {"X-Api-Key": <admin_key>}[<mempool_object>, ...]
- curl -X PUT {{ request.url_root }}api/v1/mempool -d '{"endpoint":
- <string>}' -H "Content-type: application/json" -H "X-Api-Key:
- {{ g.user.wallets[0].adminkey }}"
-
-
- Current:
- {{ currentaddress }}
-
-
curl -X GET {{ request.url_root }}api/v1/links -H "X-Api-Key: {{
- g.user.wallets[0].inkey }}"
+ user.wallets[0].inkey }}"
curl -X GET {{ request.url_root }}api/v1/links/<withdraw_id> -H
- "X-Api-Key: {{ g.user.wallets[0].inkey }}"
+ "X-Api-Key: {{ user.wallets[0].inkey }}"
@@ -83,7 +83,7 @@
"max_withdrawable": <integer>, "uses": <integer>,
"wait_time": <integer>, "is_unique": <boolean>}' -H
"Content-type: application/json" -H "X-Api-Key: {{
- g.user.wallets[0].adminkey }}"
+ user.wallets[0].adminkey }}"
@@ -119,7 +119,7 @@
"max_withdrawable": <integer>, "uses": <integer>,
"wait_time": <integer>, "is_unique": <boolean>}' -H
"Content-type: application/json" -H "X-Api-Key: {{
- g.user.wallets[0].adminkey }}"
+ user.wallets[0].adminkey }}"
@@ -143,7 +143,7 @@
curl -X DELETE {{ request.url_root }}api/v1/links/<withdraw_id>
- -H "X-Api-Key: {{ g.user.wallets[0].adminkey }}"
+ -H "X-Api-Key: {{ user.wallets[0].adminkey }}"
@@ -171,7 +171,7 @@
curl -X GET {{ request.url_root
}}api/v1/links/<the_hash>/<lnurl_id> -H "X-Api-Key: {{
- g.user.wallets[0].inkey }}"
+ user.wallets[0].inkey }}"
diff --git a/lnbits/extensions/withdraw/views.py b/lnbits/extensions/withdraw/views.py
index dc1b6e31..9bdaee45 100644
--- a/lnbits/extensions/withdraw/views.py
+++ b/lnbits/extensions/withdraw/views.py
@@ -1,40 +1,53 @@
-from quart import g, abort, render_template
from http import HTTPStatus
import pyqrcode
from io import BytesIO
-from lnbits.decorators import check_user_exists, validate_uuids
+from lnbits.decorators import check_user_exists
-from . import withdraw_ext
+from . import withdraw_ext, withdraw_renderer
from .crud import get_withdraw_link, chunks
-from fastapi import FastAPI, Request, Response
-
+from fastapi import FastAPI, Request
+from fastapi.params import Depends
from fastapi.templating import Jinja2Templates
+from starlette.exceptions import HTTPException
+from starlette.responses import HTMLResponse
+from lnbits.core.models import User
+
templates = Jinja2Templates(directory="templates")
-@withdraw_ext.get("/", status_code=HTTPStatus.OK)
-@validate_uuids(["usr"], required=True)
-@check_user_exists()
-async def index(request: Request):
- return await templates.TemplateResponse("withdraw/index.html", {"request":request,"user":g.user})
+@withdraw_ext.get("/", response_class=HTMLResponse)
+# @validate_uuids(["usr"], required=True)
+# @check_user_exists()
+async def index(request: Request, user: User = Depends(check_user_exists)):
+ return withdraw_renderer().TemplateResponse("withdraw/index.html", {"request":request,"user": user.dict()})
-@withdraw_ext.get("/{link_id}", status_code=HTTPStatus.OK)
-async def display(request: Request, link_id, response: Response):
+@withdraw_ext.get("/{link_id}", response_class=HTMLResponse)
+async def display(request: Request, link_id):
+ link = await get_withdraw_link(link_id, 0)
+
+ if not link:
+ raise HTTPException(
+ status_code=HTTPStatus.NOT_FOUND,
+ detail="Withdraw link does not exist."
+ )
+ # response.status_code = HTTPStatus.NOT_FOUND
+ # return "Withdraw link does not exist." #probably here is where we should return the 404??
+ return withdraw_renderer().TemplateResponse("withdraw/display.html", {"request":request,"link":{**link.dict(), "lnurl": link.lnurl(request)}, "unique":True})
+
+
+@withdraw_ext.get("/img/{link_id}", response_class=HTMLResponse)
+async def img(request: Request, link_id):
link = await get_withdraw_link(link_id, 0)
if not link:
- response.status_code = HTTPStatus.NOT_FOUND
- return "Withdraw link does not exist." #probably here is where we should return the 404??
- return await templates.TemplateResponse("withdraw/display.html", {"request":request,"link":link, "unique":True})
-
-
-@withdraw_ext.get("/img/{link_id}", status_code=HTTPStatus.OK)
-async def img(request: Request, link_id, response: Response):
- link = await get_withdraw_link(link_id, 0)
- if not link:
- response.status_code = HTTPStatus.NOT_FOUND
- return "Withdraw link does not exist."
- qr = pyqrcode.create(link.lnurl)
+ raise HTTPException(
+ status_code=HTTPStatus.NOT_FOUND,
+ detail="Withdraw link does not exist."
+ )
+ # response.status_code = HTTPStatus.NOT_FOUND
+ # return "Withdraw link does not exist."
+ qr = pyqrcode.create(link.lnurl(request))
+ print(qr)
stream = BytesIO()
qr.svg(stream, scale=3)
return (
@@ -49,23 +62,35 @@ async def img(request: Request, link_id, response: Response):
)
-@withdraw_ext.get("/print/{link_id}", status_code=HTTPStatus.OK)
-async def print_qr(request: Request, link_id, response: Response):
+@withdraw_ext.get("/print/{link_id}", response_class=HTMLResponse)
+async def print_qr(request: Request, link_id):
link = await get_withdraw_link(link_id)
if not link:
- response.status_code = HTTPStatus.NOT_FOUND
- return "Withdraw link does not exist."
+ raise HTTPException(
+ status_code=HTTPStatus.NOT_FOUND,
+ detail="Withdraw link does not exist."
+ )
+ # response.status_code = HTTPStatus.NOT_FOUND
+ # return "Withdraw link does not exist."
+
if link.uses == 0:
- return await templates.TemplateResponse("withdraw/print_qr.html", {"request":request,link:link, unique:False})
+
+ return withdraw_renderer().TemplateResponse("withdraw/print_qr.html", {"request":request,"link":link.dict(), unique:False})
links = []
count = 0
+
for x in link.usescsv.split(","):
linkk = await get_withdraw_link(link_id, count)
if not linkk:
- response.status_code = HTTPStatus.NOT_FOUND
- return "Withdraw link does not exist."
- links.append(str(linkk.lnurl))
+ raise HTTPException(
+ status_code=HTTPStatus.NOT_FOUND,
+ detail="Withdraw link does not exist."
+ )
+ # response.status_code = HTTPStatus.NOT_FOUND
+ # return "Withdraw link does not exist."
+ links.append(str(linkk.lnurl(request)))
count = count + 1
page_link = list(chunks(links, 2))
linked = list(chunks(page_link, 5))
- return await templates.TemplateResponse("withdraw/print_qr.html", {"request":request,"link":linked, "unique":True})
+ print("LINKED", linked)
+ return withdraw_renderer().TemplateResponse("withdraw/print_qr.html", {"request":request,"link":linked, "unique":True})
diff --git a/lnbits/extensions/withdraw/views_api.py b/lnbits/extensions/withdraw/views_api.py
index d0ad0656..93b498ef 100644
--- a/lnbits/extensions/withdraw/views_api.py
+++ b/lnbits/extensions/withdraw/views_api.py
@@ -1,11 +1,18 @@
-from quart import g, jsonify, request
+from fastapi.params import Depends
+from fastapi.param_functions import Query
+from pydantic.main import BaseModel
+
from http import HTTPStatus
from lnurl.exceptions import InvalidUrl as LnurlInvalidUrl # type: ignore
+from starlette.exceptions import HTTPException
+from starlette.requests import Request
+from starlette.responses import HTMLResponse, JSONResponse # type: ignore
from lnbits.core.crud import get_user
-from lnbits.decorators import api_check_wallet_key, api_validate_post_request
-from pydantic import BaseModel
-from fastapi import FastAPI, Query, Response
+from lnbits.decorators import WalletTypeInfo, get_key_type
+from .models import CreateWithdrawData
+
+# from fastapi import FastAPI, Query, Response
from . import withdraw_ext
from .crud import (
@@ -19,59 +26,75 @@ from .crud import (
)
-@withdraw_ext.get("/api/v1/links", status_code=200)
-@api_check_wallet_key("invoice")
-async def api_links(response: Response):
- wallet_ids = [g.wallet.id]
+@withdraw_ext.get("/api/v1/links", status_code=HTTPStatus.OK)
+# @api_check_wallet_key("invoice")
+async def api_links(req: Request, wallet: WalletTypeInfo = Depends(get_key_type), all_wallets: bool = Query(False)):
+ wallet_ids = [wallet.wallet.id]
+
+ if all_wallets:
+ wallet_ids = (await get_user(wallet.wallet.user)).wallet_ids
- if "all_wallets" in request.args:
- wallet_ids = (await get_user(g.wallet.user)).wallet_ids
try:
return [
{
- **link._asdict(),
- **{"lnurl": link.lnurl},
+ **link.dict(),
+ **{"lnurl": link.lnurl(req)},
}
for link in await get_withdraw_links(wallet_ids)
]
-
+
except LnurlInvalidUrl:
- response.status_code = HTTPStatus.UPGRADE_REQUIRED
- return { "message": "LNURLs need to be delivered over a publically accessible `https` domain or Tor." }
+ raise HTTPException(
+ status_code=HTTPStatus.UPGRADE_REQUIRED,
+ detail="LNURLs need to be delivered over a publically accessible `https` domain or Tor.",
+ )
+ # response.status_code = HTTPStatus.UPGRADE_REQUIRED
+ # return { "message": "LNURLs need to be delivered over a publically accessible `https` domain or Tor." }
-@withdraw_ext.get("/api/v1/links/{link_id}", status_code=200)
-@api_check_wallet_key("invoice")
-async def api_link_retrieve(link_id, response: Response):
+@withdraw_ext.get("/api/v1/links/{link_id}", status_code=HTTPStatus.OK)
+# @api_check_wallet_key("invoice")
+async def api_link_retrieve(link_id, wallet: WalletTypeInfo = Depends(get_key_type)):
link = await get_withdraw_link(link_id, 0)
if not link:
- response.status_code = HTTPStatus.NOT_FOUND
- return {"message": "Withdraw link does not exist."}
+ raise HTTPException(
+ detail="Withdraw link does not exist.",
+ status_code=HTTPStatus.NOT_FOUND
+ )
+ # response.status_code = HTTPStatus.NOT_FOUND
+ # return {"message": "Withdraw link does not exist."}
- if link.wallet != g.wallet.id:
- response.status_code = HTTPStatus.FORBIDDEN
- return {"message": "Not your withdraw link."}
+ if link.wallet != wallet.wallet.id:
+ raise HTTPException(
+ detail="Not your withdraw link.",
+ status_code=HTTPStatus.FORBIDDEN
+ )
+ # response.status_code = HTTPStatus.FORBIDDEN
+ # return {"message": "Not your withdraw link."}
+ return {**link, **{"lnurl": link.lnurl(request)}}
- return {**link, **{"lnurl": link.lnurl}}
-
-class CreateData(BaseModel):
- title: str = Query(...)
- min_withdrawable: int = Query(..., ge=1)
- max_withdrawable: int = Query(..., ge=1)
- uses: int = Query(..., ge=1)
- wait_time: int = Query(..., ge=1)
- is_unique: bool
+# class CreateData(BaseModel):
+# title: str = Query(...)
+# min_withdrawable: int = Query(..., ge=1)
+# max_withdrawable: int = Query(..., ge=1)
+# uses: int = Query(..., ge=1)
+# wait_time: int = Query(..., ge=1)
+# is_unique: bool
@withdraw_ext.post("/api/v1/links", status_code=HTTPStatus.CREATED)
-@withdraw_ext.put("/api/v1/links/{link_id}")
-@api_check_wallet_key("admin")
-async def api_link_create_or_update(data: CreateData, link_id: str = None, response: Response):
+@withdraw_ext.put("/api/v1/links/{link_id}", status_code=HTTPStatus.OK)
+# @api_check_wallet_key("admin")
+async def api_link_create_or_update(req: Request, data: CreateWithdrawData, link_id: str = None, wallet: WalletTypeInfo = Depends(get_key_type)):
if data.max_withdrawable < data.min_withdrawable:
- response.status_code = HTTPStatus.BAD_REQUEST
- return {
- "message": "`max_withdrawable` needs to be at least `min_withdrawable`."
- }
+ raise HTTPException(
+ detail="`max_withdrawable` needs to be at least `min_withdrawable`.",
+ status_code=HTTPStatus.BAD_REQUEST
+ )
+ # response.status_code = HTTPStatus.BAD_REQUEST
+ # return {
+ # "message": "`max_withdrawable` needs to be at least `min_withdrawable`."
+ # }
usescsv = ""
for i in range(data.uses):
@@ -84,41 +107,57 @@ async def api_link_create_or_update(data: CreateData, link_id: str = None, respo
if link_id:
link = await get_withdraw_link(link_id, 0)
if not link:
- response.status_code = HTTPStatus.NOT_FOUND
- return {"message": "Withdraw link does not exist."}
- if link.wallet != g.wallet.id:
- response.status_code = HTTPStatus.FORBIDDEN
- return {"message": "Not your withdraw link."}
- link = await update_withdraw_link(link_id, **data, usescsv=usescsv, used=0)
+ raise HTTPException(
+ detail="Withdraw link does not exist.",
+ status_code=HTTPStatus.NOT_FOUND
+ )
+ # response.status_code = HTTPStatus.NOT_FOUND
+ # return {"message": "Withdraw link does not exist."}
+ if link.wallet != wallet.wallet.id:
+ raise HTTPException(
+ detail="Not your withdraw link.",
+ status_code=HTTPStatus.FORBIDDEN
+ )
+ # response.status_code = HTTPStatus.FORBIDDEN
+ # return {"message": "Not your withdraw link."}
+ link = await update_withdraw_link(link_id, data=data, usescsv=usescsv, used=0)
else:
link = await create_withdraw_link(
- wallet_id=g.wallet.id, **data, usescsv=usescsv
+ wallet_id=wallet.wallet.id, data=data, usescsv=usescsv
)
- if link_id:
- response.status_code = HTTPStatus.OK
- return {**link, **{"lnurl": link.lnurl}}
+ # if link_id:
+ # response.status_code = HTTPStatus.OK
+ return {**link.dict(), **{"lnurl": link.lnurl(req)}}
-@withdraw_ext.delete("/api/v1/links/{link_id}", status_code=HTTPStatus.NO_CONTENT)
-@api_check_wallet_key("admin")
-async def api_link_delete(link_id, response: Response):
+@withdraw_ext.delete("/api/v1/links/{link_id}")
+# @api_check_wallet_key("admin")
+async def api_link_delete(link_id, wallet: WalletTypeInfo = Depends(get_key_type)):
link = await get_withdraw_link(link_id)
if not link:
- response.status_code = HTTPStatus.NOT_FOUND
- return {"message": "Withdraw link does not exist."}
+ raise HTTPException(
+ detail="Withdraw link does not exist.",
+ status_code=HTTPStatus.NOT_FOUND
+ )
+ # response.status_code = HTTPStatus.NOT_FOUND
+ # return {"message": "Withdraw link does not exist."}
- if link.wallet != g.wallet.id:
- response.status_code = HTTPStatus.FORBIDDEN
- return {"message": "Not your withdraw link."}
+ if link.wallet != wallet.wallet.id:
+ raise HTTPException(
+ detail="Not your withdraw link.",
+ status_code=HTTPStatus.FORBIDDEN
+ )
+ # response.status_code = HTTPStatus.FORBIDDEN
+ # return {"message": "Not your withdraw link."}
await delete_withdraw_link(link_id)
-
- return ""
+ raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
+ # return ""
@withdraw_ext.get("/api/v1/links/{the_hash}/{lnurl_id}", status_code=HTTPStatus.OK)
-@api_check_wallet_key("invoice")
-async def api_hash_retrieve(the_hash, lnurl_id):
+# @api_check_wallet_key("invoice")
+async def api_hash_retrieve(the_hash, lnurl_id, wallet: WalletTypeInfo = Depends(get_key_type)):
hashCheck = await get_hash_check(the_hash, lnurl_id)
return hashCheck