From 7cd3487bc9cfee4730708f6e4fc58071148a4172 Mon Sep 17 00:00:00 2001
From: benarc
Date: Wed, 17 Mar 2021 15:38:32 +0000
Subject: [PATCH 01/11] Added hash check to db
---
lnbits/extensions/withdraw/migrations.py | 13 +++++++++++++
lnbits/extensions/withdraw/models.py | 8 ++++++++
2 files changed, 21 insertions(+)
diff --git a/lnbits/extensions/withdraw/migrations.py b/lnbits/extensions/withdraw/migrations.py
index 4af24f8f..b0cf0b8f 100644
--- a/lnbits/extensions/withdraw/migrations.py
+++ b/lnbits/extensions/withdraw/migrations.py
@@ -94,3 +94,16 @@ async def m002_change_withdraw_table(db):
),
)
await db.execute("DROP TABLE withdraw_links")
+
+async def m003_make_hash_check(db):
+ """
+ Creates a hash check table.
+ """
+ await db.execute(
+ """
+ CREATE TABLE IF NOT EXISTS hash_check (
+ id TEXT PRIMARY KEY,
+ lnurl_id TEXT
+ );
+ """
+ )
\ No newline at end of file
diff --git a/lnbits/extensions/withdraw/models.py b/lnbits/extensions/withdraw/models.py
index 9a4dfb7c..1903dba6 100644
--- a/lnbits/extensions/withdraw/models.py
+++ b/lnbits/extensions/withdraw/models.py
@@ -59,3 +59,11 @@ class WithdrawLink(NamedTuple):
max_withdrawable=self.max_withdrawable * 1000,
default_description=self.title,
)
+
+class HashCheck(NamedTuple):
+ id: str
+ lnurl_id: str
+
+ @classmethod
+ def from_row(cls, row: Row) -> "Hash":
+ return cls(**dict(row))
\ No newline at end of file
From 514329045f2cf9ab570b250e460542dd61562fd4 Mon Sep 17 00:00:00 2001
From: benarc
Date: Wed, 17 Mar 2021 16:33:12 +0000
Subject: [PATCH 02/11] Should work
---
lnbits/extensions/withdraw/crud.py | 25 +++++++++++++++++++++++++
lnbits/extensions/withdraw/models.py | 1 -
lnbits/extensions/withdraw/views_api.py | 16 ++++++++++++++++
3 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/lnbits/extensions/withdraw/crud.py b/lnbits/extensions/withdraw/crud.py
index 78fd7f56..64d4373e 100644
--- a/lnbits/extensions/withdraw/crud.py
+++ b/lnbits/extensions/withdraw/crud.py
@@ -98,3 +98,28 @@ async def delete_withdraw_link(link_id: str) -> None:
def chunks(lst, n):
for i in range(0, len(lst), n):
yield lst[i : i + n]
+
+async def create_hash_check(
+ the_hash: str,
+ lnurl_id: str,
+) -> HashCheck:
+ await db.execute(
+ """
+ INSERT INTO hash_check (
+ id,
+ lnurl_id
+ )
+ VALUES (?, ?)
+ """,
+ (
+ the_hash,
+ lnurl_id,
+ ),
+ )
+ hashCheck = await get_hash_check(the_hash, lnurl_id)
+ row = await db.fetchone("SELECT * FROM hash_check WHERE id = ?", (the_hash,))
+ return HashCheck.from_row(row) if row else None
+
+async def get_hash_check(the_hash: str, lnurl_id: str) -> Optional[HashCheck]:
+ row = await db.fetchone("SELECT * FROM hash_check WHERE id = ?", (the_hash,))
+ return HashCheck.from_row(row) if row else None
\ No newline at end of file
diff --git a/lnbits/extensions/withdraw/models.py b/lnbits/extensions/withdraw/models.py
index 1903dba6..4d147f25 100644
--- a/lnbits/extensions/withdraw/models.py
+++ b/lnbits/extensions/withdraw/models.py
@@ -63,7 +63,6 @@ class WithdrawLink(NamedTuple):
class HashCheck(NamedTuple):
id: str
lnurl_id: str
-
@classmethod
def from_row(cls, row: Row) -> "Hash":
return cls(**dict(row))
\ No newline at end of file
diff --git a/lnbits/extensions/withdraw/views_api.py b/lnbits/extensions/withdraw/views_api.py
index cb8b7f0a..d34422ba 100644
--- a/lnbits/extensions/withdraw/views_api.py
+++ b/lnbits/extensions/withdraw/views_api.py
@@ -12,6 +12,8 @@ from .crud import (
get_withdraw_links,
update_withdraw_link,
delete_withdraw_link,
+ create_hash_check,
+ get_hash_check,
)
@@ -111,3 +113,17 @@ async def api_link_delete(link_id):
await delete_withdraw_link(link_id)
return "", HTTPStatus.NO_CONTENT
+
+@withdraw_ext.route("/api/v1/links//", methods=["GET"])
+@api_check_wallet_key("invoice")
+async def api_hash_retrieve(the_hash, lnurl_id):
+ hashCheck = await get_hash_check(the_hash, lnurl_id)
+
+ if not hashCheck:
+ hashCheck = await create_hash_check(the_hash, lnurl_id)
+ return jsonify({"status": False}), HTTPStatus.OK
+
+ if link.wallet != g.wallet.id:
+ return jsonify({"status": True}), HTTPStatus.OK
+
+ return jsonify({"status": True}), HTTPStatus.OK
From 86744ebcedadca6c54619c3c73ac8267b24efbc3 Mon Sep 17 00:00:00 2001
From: benarc
Date: Wed, 17 Mar 2021 16:56:23 +0000
Subject: [PATCH 03/11] Bug
---
lnbits/extensions/withdraw/crud.py | 2 +-
.../templates/withdraw/_api_docs.html | 27 +++++++++++++++++++
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/lnbits/extensions/withdraw/crud.py b/lnbits/extensions/withdraw/crud.py
index 64d4373e..cc7fe387 100644
--- a/lnbits/extensions/withdraw/crud.py
+++ b/lnbits/extensions/withdraw/crud.py
@@ -3,7 +3,7 @@ from typing import List, Optional, Union
from lnbits.helpers import urlsafe_short_hash
from . import db
-from .models import WithdrawLink
+from .models import WithdrawLink, HashCheck
async def create_withdraw_link(
diff --git a/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html b/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
index 18a0a542..75ed9e02 100644
--- a/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
+++ b/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
@@ -150,3 +150,30 @@
+
+
+
+ GET
+ /withdraw/api/v1/links/<the_hash>/<lnurl_id>
+ Headers
+ {"X-Api-Key": <invoice_key>}
+ Body (application/json)
+
+ Returns 201 CREATED (application/json)
+
+ {"status": <bool>}
+ Curl example
+ curl -X GET {{ request.url_root }}api/v1/links/<the_hash>/<lnurl_id> -H
+ "X-Api-Key: {{ g.user.wallets[0].inkey }}"
+
+
+
+
From f42dab5e309c5e3d90e597492d7063035705f816 Mon Sep 17 00:00:00 2001
From: benarc
Date: Wed, 17 Mar 2021 17:55:00 +0000
Subject: [PATCH 04/11] Added api docs
---
.../templates/withdraw/_api_docs.html | 30 +++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html b/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
index 75ed9e02..13d2c1d3 100644
--- a/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
+++ b/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
@@ -149,8 +149,7 @@
-
-
+
+
+
+ GET
+ /withdraw/img/<lnurl_id>
+ Body (application/json)
+
+ Returns 201 CREATED (application/json)
+
+ {"status": <bool>}
+ Curl example
+ curl -X GET {{ request.url_root }}/withdraw/img/<lnurl_id>"
+
+
+
+
+
+
+
From 09f89d07dd32fd0b0a75f3e09674e38593ea4120 Mon Sep 17 00:00:00 2001
From: benarc
Date: Wed, 17 Mar 2021 17:57:12 +0000
Subject: [PATCH 05/11] API docs
---
.../extensions/withdraw/templates/withdraw/_api_docs.html | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html b/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
index 13d2c1d3..e15355c3 100644
--- a/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
+++ b/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
@@ -129,7 +129,7 @@
dense
expand-separator
label="Delete a withdraw link"
- class="q-pb-md"
+
>
@@ -181,6 +181,7 @@ group="api"
dense
expand-separator
label="Get image to embed"
+class="q-pb-md"
>
@@ -188,10 +189,6 @@ label="Get image to embed"
>GET
/withdraw/img/<lnurl_id>
- Body (application/json)
-
- Returns 201 CREATED (application/json)
-
{"status": <bool>}
Curl example
Date: Wed, 17 Mar 2021 17:58:03 +0000
Subject: [PATCH 06/11] api doc
---
lnbits/extensions/withdraw/templates/withdraw/_api_docs.html | 1 -
1 file changed, 1 deletion(-)
diff --git a/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html b/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
index e15355c3..b8fa8231 100644
--- a/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
+++ b/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
@@ -189,7 +189,6 @@ class="q-pb-md"
>GET
/withdraw/img/<lnurl_id>
- {"status": <bool>}
Curl example
curl -X GET {{ request.url_root }}/withdraw/img/<lnurl_id>"
From 66cde0154b591fcfeaffc71796cb046f8862d2cf Mon Sep 17 00:00:00 2001
From: benarc
Date: Wed, 17 Mar 2021 18:02:52 +0000
Subject: [PATCH 07/11] api docs
---
lnbits/extensions/withdraw/views_api.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/lnbits/extensions/withdraw/views_api.py b/lnbits/extensions/withdraw/views_api.py
index d34422ba..757603c6 100644
--- a/lnbits/extensions/withdraw/views_api.py
+++ b/lnbits/extensions/withdraw/views_api.py
@@ -122,8 +122,5 @@ async def api_hash_retrieve(the_hash, lnurl_id):
if not hashCheck:
hashCheck = await create_hash_check(the_hash, lnurl_id)
return jsonify({"status": False}), HTTPStatus.OK
-
- if link.wallet != g.wallet.id:
- return jsonify({"status": True}), HTTPStatus.OK
return jsonify({"status": True}), HTTPStatus.OK
From ad545e7fe13e3b9dc94cfd39e745acd960f7e49a Mon Sep 17 00:00:00 2001
From: benarc
Date: Wed, 17 Mar 2021 19:27:52 +0000
Subject: [PATCH 08/11] prettier/black
---
lnbits/extensions/withdraw/crud.py | 2 +
lnbits/extensions/withdraw/migrations.py | 1 +
lnbits/extensions/withdraw/models.py | 2 +
.../templates/withdraw/_api_docs.html | 91 +++++++++----------
lnbits/extensions/withdraw/views_api.py | 1 +
5 files changed, 48 insertions(+), 49 deletions(-)
diff --git a/lnbits/extensions/withdraw/crud.py b/lnbits/extensions/withdraw/crud.py
index cc7fe387..11f7d949 100644
--- a/lnbits/extensions/withdraw/crud.py
+++ b/lnbits/extensions/withdraw/crud.py
@@ -99,6 +99,7 @@ def chunks(lst, n):
for i in range(0, len(lst), n):
yield lst[i : i + n]
+
async def create_hash_check(
the_hash: str,
lnurl_id: str,
@@ -120,6 +121,7 @@ async def create_hash_check(
row = await db.fetchone("SELECT * FROM hash_check WHERE id = ?", (the_hash,))
return HashCheck.from_row(row) if row else None
+
async def get_hash_check(the_hash: str, lnurl_id: str) -> Optional[HashCheck]:
row = await db.fetchone("SELECT * FROM hash_check WHERE id = ?", (the_hash,))
return HashCheck.from_row(row) if row else None
\ No newline at end of file
diff --git a/lnbits/extensions/withdraw/migrations.py b/lnbits/extensions/withdraw/migrations.py
index b0cf0b8f..2cb802d4 100644
--- a/lnbits/extensions/withdraw/migrations.py
+++ b/lnbits/extensions/withdraw/migrations.py
@@ -95,6 +95,7 @@ async def m002_change_withdraw_table(db):
)
await db.execute("DROP TABLE withdraw_links")
+
async def m003_make_hash_check(db):
"""
Creates a hash check table.
diff --git a/lnbits/extensions/withdraw/models.py b/lnbits/extensions/withdraw/models.py
index 4d147f25..4c485ea3 100644
--- a/lnbits/extensions/withdraw/models.py
+++ b/lnbits/extensions/withdraw/models.py
@@ -60,9 +60,11 @@ class WithdrawLink(NamedTuple):
default_description=self.title,
)
+
class HashCheck(NamedTuple):
id: str
lnurl_id: str
+
@classmethod
def from_row(cls, row: Row) -> "Hash":
return cls(**dict(row))
\ No newline at end of file
diff --git a/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html b/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
index b8fa8231..c303b091 100644
--- a/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
+++ b/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
@@ -129,7 +129,6 @@
dense
expand-separator
label="Delete a withdraw link"
-
>
@@ -149,53 +148,47 @@
+
+
+
+ GET
+ /withdraw/api/v1/links/<the_hash>/<lnurl_id>
+ Headers
+ {"X-Api-Key": <invoice_key>}
+ Body (application/json)
+
+ Returns 201 CREATED (application/json)
+
+ {"status": <bool>}
+ Curl example
+ curl -X GET {{ request.url_root
+ }}api/v1/links/<the_hash>/<lnurl_id> -H "X-Api-Key: {{
+ g.user.wallets[0].inkey }}"
+
+
+
+
-
-
- GET
- /withdraw/api/v1/links/<the_hash>/<lnurl_id>
- Headers
- {"X-Api-Key": <invoice_key>}
- Body (application/json)
-
- Returns 201 CREATED (application/json)
-
- {"status": <bool>}
- Curl example
- curl -X GET {{ request.url_root }}api/v1/links/<the_hash>/<lnurl_id> -H
- "X-Api-Key: {{ g.user.wallets[0].inkey }}"
-
-
-
+ group="api"
+ dense
+ expand-separator
+ label="Get image to embed"
+ class="q-pb-md"
+ >
+
+
+ GET
+ /withdraw/img/<lnurl_id>
+ Curl example
+ curl -X GET {{ request.url_root }}/withdraw/img/<lnurl_id>"
+
+
+
+
-
-
-
- GET
- /withdraw/img/<lnurl_id>
- Curl example
- curl -X GET {{ request.url_root }}/withdraw/img/<lnurl_id>"
-
-
-
-
-
-
-
diff --git a/lnbits/extensions/withdraw/views_api.py b/lnbits/extensions/withdraw/views_api.py
index 757603c6..2f80aab5 100644
--- a/lnbits/extensions/withdraw/views_api.py
+++ b/lnbits/extensions/withdraw/views_api.py
@@ -114,6 +114,7 @@ async def api_link_delete(link_id):
return "", HTTPStatus.NO_CONTENT
+
@withdraw_ext.route("/api/v1/links//", methods=["GET"])
@api_check_wallet_key("invoice")
async def api_hash_retrieve(the_hash, lnurl_id):
From c86bd74506c054e8a0f6c271918d15d81c4cbdf3 Mon Sep 17 00:00:00 2001
From: benarc
Date: Wed, 17 Mar 2021 19:32:37 +0000
Subject: [PATCH 09/11] edited api
---
.../extensions/withdraw/templates/withdraw/_api_docs.html | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html b/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
index c303b091..484464ba 100644
--- a/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
+++ b/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
@@ -148,7 +148,12 @@
-
+
Date: Wed, 17 Mar 2021 19:54:17 +0000
Subject: [PATCH 10/11] Ran black on bleskomat
---
lnbits/extensions/bleskomat/crud.py | 29 +++++++++--
lnbits/extensions/bleskomat/exchange_rates.py | 23 ++++----
lnbits/extensions/bleskomat/helpers.py | 52 ++++++-------------
lnbits/extensions/bleskomat/lnurl_api.py | 13 ++---
lnbits/extensions/bleskomat/models.py | 14 ++---
lnbits/extensions/bleskomat/views.py | 3 +-
lnbits/extensions/bleskomat/views_api.py | 10 ++--
lnbits/extensions/withdraw/crud.py | 1 +
8 files changed, 70 insertions(+), 75 deletions(-)
diff --git a/lnbits/extensions/bleskomat/crud.py b/lnbits/extensions/bleskomat/crud.py
index 470d87cb..69079350 100644
--- a/lnbits/extensions/bleskomat/crud.py
+++ b/lnbits/extensions/bleskomat/crud.py
@@ -6,19 +6,30 @@ from . import db
from .models import Bleskomat, BleskomatLnurl
from .helpers import generate_bleskomat_lnurl_hash
+
async def create_bleskomat(
*, wallet_id: str, name: str, fiat_currency: str, exchange_rate_provider: str, fee: str
) -> Bleskomat:
bleskomat_id = uuid4().hex
api_key_id = secrets.token_hex(8)
api_key_secret = secrets.token_hex(32)
- api_key_encoding = "hex";
+ api_key_encoding = "hex"
await db.execute(
"""
INSERT INTO bleskomats (id, wallet, api_key_id, api_key_secret, api_key_encoding, name, fiat_currency, exchange_rate_provider, fee)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
- (bleskomat_id, wallet_id, api_key_id, api_key_secret, api_key_encoding, name, fiat_currency, exchange_rate_provider, fee),
+ (
+ bleskomat_id,
+ wallet_id,
+ api_key_id,
+ api_key_secret,
+ api_key_encoding,
+ name,
+ fiat_currency,
+ exchange_rate_provider,
+ fee,
+ ),
)
bleskomat = await get_bleskomat(bleskomat_id)
assert bleskomat, "Newly created bleskomat couldn't be retrieved"
@@ -65,7 +76,19 @@ async def create_bleskomat_lnurl(
INSERT INTO bleskomat_lnurls (id, bleskomat, wallet, hash, tag, params, api_key_id, initial_uses, remaining_uses, created_time, updated_time)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
- (bleskomat_lnurl_id, bleskomat.id, bleskomat.wallet, hash, tag, params, bleskomat.api_key_id, uses, uses, now, now),
+ (
+ bleskomat_lnurl_id,
+ bleskomat.id,
+ bleskomat.wallet,
+ hash,
+ tag,
+ params,
+ bleskomat.api_key_id,
+ uses,
+ uses,
+ now,
+ now,
+ ),
)
bleskomat_lnurl = await get_bleskomat_lnurl(secret)
assert bleskomat_lnurl, "Newly created bleskomat LNURL couldn't be retrieved"
diff --git a/lnbits/extensions/bleskomat/exchange_rates.py b/lnbits/extensions/bleskomat/exchange_rates.py
index 15547370..6d9297c6 100644
--- a/lnbits/extensions/bleskomat/exchange_rates.py
+++ b/lnbits/extensions/bleskomat/exchange_rates.py
@@ -2,39 +2,41 @@ import httpx
import json
import os
-fiat_currencies = json.load(open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'fiat_currencies.json'), 'r'))
+fiat_currencies = json.load(
+ open(os.path.join(os.path.dirname(os.path.realpath(__file__)), "fiat_currencies.json"), "r")
+)
exchange_rate_providers = {
"bitfinex": {
"name": "Bitfinex",
"domain": "bitfinex.com",
"api_url": "https://api.bitfinex.com/v1/pubticker/{from}{to}",
- "getter": lambda data, replacements: data["last_price"]
+ "getter": lambda data, replacements: data["last_price"],
},
"bitstamp": {
"name": "Bitstamp",
"domain": "bitstamp.net",
"api_url": "https://www.bitstamp.net/api/v2/ticker/{from}{to}/",
- "getter": lambda data, replacements: data["last"]
+ "getter": lambda data, replacements: data["last"],
},
"coinbase": {
"name": "Coinbase",
"domain": "coinbase.com",
"api_url": "https://api.coinbase.com/v2/exchange-rates?currency={FROM}",
- "getter": lambda data, replacements: data["data"]["rates"][replacements["TO"]]
+ "getter": lambda data, replacements: data["data"]["rates"][replacements["TO"]],
},
"coinmate": {
"name": "CoinMate",
"domain": "coinmate.io",
"api_url": "https://coinmate.io/api/ticker?currencyPair={FROM}_{TO}",
- "getter": lambda data, replacements: data["data"]["last"]
+ "getter": lambda data, replacements: data["data"]["last"],
},
"kraken": {
"name": "Kraken",
"domain": "kraken.com",
"api_url": "https://api.kraken.com/0/public/Ticker?pair=XBT{TO}",
- "getter": lambda data, replacements: data["result"]["XXBTZ" + replacements["TO"]]["c"][0]
- }
+ "getter": lambda data, replacements: data["result"]["XXBTZ" + replacements["TO"]]["c"][0],
+ },
}
exchange_rate_providers_serializable = {}
@@ -48,12 +50,7 @@ for ref, exchange_rate_provider in exchange_rate_providers.items():
async def fetch_fiat_exchange_rate(currency: str, provider: str):
- replacements = {
- "FROM" : "BTC",
- "from" : "btc",
- "TO" : currency.upper(),
- "to" : currency.lower()
- }
+ replacements = {"FROM": "BTC", "from": "btc", "TO": currency.upper(), "to": currency.lower()}
url = exchange_rate_providers[provider]["api_url"]
for key in replacements.keys():
diff --git a/lnbits/extensions/bleskomat/helpers.py b/lnbits/extensions/bleskomat/helpers.py
index 439795be..9b745c79 100644
--- a/lnbits/extensions/bleskomat/helpers.py
+++ b/lnbits/extensions/bleskomat/helpers.py
@@ -21,11 +21,7 @@ def generate_bleskomat_lnurl_signature(payload: str, api_key_secret: str, api_ke
key = base64.b64decode(api_key_secret)
else:
key = bytes(f"{api_key_secret}")
- return hmac.new(
- key=key,
- msg=payload.encode(),
- digestmod=hashlib.sha256
- ).hexdigest()
+ return hmac.new(key=key, msg=payload.encode(), digestmod=hashlib.sha256).hexdigest()
def generate_bleskomat_lnurl_secret(api_key_id: str, signature: str):
@@ -58,19 +54,21 @@ class LnurlValidationError(Exception):
def prepare_lnurl_params(tag: str, query: Dict[str, str]):
params = {}
if not is_supported_lnurl_subprotocol(tag):
- raise LnurlValidationError(f"Unsupported subprotocol: \"{tag}\"")
+ raise LnurlValidationError(f'Unsupported subprotocol: "{tag}"')
if tag == "withdrawRequest":
params["minWithdrawable"] = float(query["minWithdrawable"])
params["maxWithdrawable"] = float(query["maxWithdrawable"])
params["defaultDescription"] = query["defaultDescription"]
if not params["minWithdrawable"] > 0:
- raise LnurlValidationError("\"minWithdrawable\" must be greater than zero")
+ raise LnurlValidationError('"minWithdrawable" must be greater than zero')
if not params["maxWithdrawable"] >= params["minWithdrawable"]:
- raise LnurlValidationError("\"maxWithdrawable\" must be greater than or equal to \"minWithdrawable\"")
+ raise LnurlValidationError('"maxWithdrawable" must be greater than or equal to "minWithdrawable"')
return params
encode_uri_component_safe_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()"
+
+
def query_to_signing_payload(query: Dict[str, str]) -> str:
# Sort the query by key, then stringify it to create the payload.
sorted_keys = sorted(query.keys(), key=str.lower)
@@ -84,35 +82,17 @@ def query_to_signing_payload(query: Dict[str, str]) -> str:
unshorten_rules = {
- "query": {
- "n": "nonce",
- "s": "signature",
- "t": "tag"
- },
- "tags": {
- "c": "channelRequest",
- "l": "login",
- "p": "payRequest",
- "w": "withdrawRequest"
- },
+ "query": {"n": "nonce", "s": "signature", "t": "tag"},
+ "tags": {"c": "channelRequest", "l": "login", "p": "payRequest", "w": "withdrawRequest"},
"params": {
- "channelRequest": {
- "pl": "localAmt",
- "pp": "pushAmt"
- },
+ "channelRequest": {"pl": "localAmt", "pp": "pushAmt"},
"login": {},
- "payRequest": {
- "pn": "minSendable",
- "px": "maxSendable",
- "pm": "metadata"
- },
- "withdrawRequest": {
- "pn": "minWithdrawable",
- "px": "maxWithdrawable",
- "pd": "defaultDescription"
- }
- }
+ "payRequest": {"pn": "minSendable", "px": "maxSendable", "pm": "metadata"},
+ "withdrawRequest": {"pn": "minWithdrawable", "px": "maxWithdrawable", "pd": "defaultDescription"},
+ },
}
+
+
def unshorten_lnurl_query(query: Dict[str, str]) -> Dict[str, str]:
new_query = {}
rules = unshorten_rules
@@ -121,14 +101,14 @@ def unshorten_lnurl_query(query: Dict[str, str]) -> Dict[str, str]:
elif "t" in query:
tag = query["t"]
else:
- raise LnurlValidationError("Missing required query parameter: \"tag\"")
+ raise LnurlValidationError('Missing required query parameter: "tag"')
# Unshorten tag:
if tag in rules["tags"]:
long_tag = rules["tags"][tag]
new_query["tag"] = long_tag
tag = long_tag
if not tag in rules["params"]:
- raise LnurlValidationError(f"Unknown tag: \"{tag}\"")
+ raise LnurlValidationError(f'Unknown tag: "{tag}"')
for key in query:
if key in rules["params"][tag]:
short_param_key = key
diff --git a/lnbits/extensions/bleskomat/lnurl_api.py b/lnbits/extensions/bleskomat/lnurl_api.py
index 35d93032..c7df81d1 100644
--- a/lnbits/extensions/bleskomat/lnurl_api.py
+++ b/lnbits/extensions/bleskomat/lnurl_api.py
@@ -47,7 +47,7 @@ async def api_bleskomat_lnurl():
# The API key ID, nonce, and tag should be present in the query string.
for field in ["id", "nonce", "tag"]:
if not field in query:
- raise LnurlHttpError(f"Failed API key signature check: Missing \"{field}\"", HTTPStatus.BAD_REQUEST)
+ raise LnurlHttpError(f'Failed API key signature check: Missing "{field}"', HTTPStatus.BAD_REQUEST)
# URL signing scheme is described here:
# https://github.com/chill117/lnurl-node#how-to-implement-url-signing-scheme
@@ -72,8 +72,7 @@ async def api_bleskomat_lnurl():
params = prepare_lnurl_params(tag, query)
if "f" in query:
rate = await fetch_fiat_exchange_rate(
- currency=query["f"],
- provider=bleskomat.exchange_rate_provider
+ currency=query["f"], provider=bleskomat.exchange_rate_provider
)
# Convert fee (%) to decimal:
fee = float(bleskomat.fee) / 100
@@ -88,13 +87,7 @@ async def api_bleskomat_lnurl():
raise LnurlHttpError(e.message, HTTPStatus.BAD_REQUEST)
# Create a new LNURL using the query parameters provided in the signed URL.
params = json.JSONEncoder().encode(params)
- lnurl = await create_bleskomat_lnurl(
- bleskomat=bleskomat,
- secret=secret,
- tag=tag,
- params=params,
- uses=1
- )
+ lnurl = await create_bleskomat_lnurl(bleskomat=bleskomat, secret=secret, tag=tag, params=params, uses=1)
# Reply with LNURL response object.
return jsonify(lnurl.get_info_response_object(secret)), HTTPStatus.OK
diff --git a/lnbits/extensions/bleskomat/models.py b/lnbits/extensions/bleskomat/models.py
index 8a671a71..8ea97338 100644
--- a/lnbits/extensions/bleskomat/models.py
+++ b/lnbits/extensions/bleskomat/models.py
@@ -39,7 +39,7 @@ class BleskomatLnurl(NamedTuple):
def get_info_response_object(self, secret: str) -> Dict[str, str]:
tag = self.tag
params = json.loads(self.params)
- response = { "tag": tag }
+ response = {"tag": tag}
if tag == "withdrawRequest":
for key in ["minWithdrawable", "maxWithdrawable", "defaultDescription"]:
response[key] = params[key]
@@ -54,7 +54,7 @@ class BleskomatLnurl(NamedTuple):
if tag == "withdrawRequest":
for field in ["pr"]:
if not field in query:
- raise LnurlValidationError(f"Missing required parameter: \"{field}\"")
+ raise LnurlValidationError(f'Missing required parameter: "{field}"')
# Check the bolt11 invoice(s) provided.
pr = query["pr"]
if "," in pr:
@@ -62,13 +62,13 @@ class BleskomatLnurl(NamedTuple):
try:
invoice = bolt11.decode(pr)
except ValueError as e:
- raise LnurlValidationError("Invalid parameter (\"pr\"): Lightning payment request expected")
+ raise LnurlValidationError('Invalid parameter ("pr"): Lightning payment request expected')
if invoice.amount_msat < params["minWithdrawable"]:
- raise LnurlValidationError("Amount in invoice must be greater than or equal to \"minWithdrawable\"")
+ raise LnurlValidationError('Amount in invoice must be greater than or equal to "minWithdrawable"')
if invoice.amount_msat > params["maxWithdrawable"]:
- raise LnurlValidationError("Amount in invoice must be less than or equal to \"maxWithdrawable\"")
+ raise LnurlValidationError('Amount in invoice must be less than or equal to "maxWithdrawable"')
else:
- raise LnurlValidationError(f"Unknown subprotocol: \"{tag}\"")
+ raise LnurlValidationError(f'Unknown subprotocol: "{tag}"')
async def execute_action(self, query: Dict[str, str]):
self.validate_action(query)
@@ -105,6 +105,6 @@ class BleskomatLnurl(NamedTuple):
WHERE id = ?
AND remaining_uses > 0
""",
- (now, self.id)
+ (now, self.id),
)
return result.rowcount > 0
diff --git a/lnbits/extensions/bleskomat/views.py b/lnbits/extensions/bleskomat/views.py
index 16e986ee..52f63499 100644
--- a/lnbits/extensions/bleskomat/views.py
+++ b/lnbits/extensions/bleskomat/views.py
@@ -7,6 +7,7 @@ from . import bleskomat_ext
from .exchange_rates import exchange_rate_providers_serializable, fiat_currencies
from .helpers import get_callback_url
+
@bleskomat_ext.route("/")
@validate_uuids(["usr"], required=True)
@check_user_exists()
@@ -14,6 +15,6 @@ async def index():
bleskomat_vars = {
"callback_url": get_callback_url(),
"exchange_rate_providers": exchange_rate_providers_serializable,
- "fiat_currencies": fiat_currencies
+ "fiat_currencies": fiat_currencies,
}
return await render_template("bleskomat/index.html", user=g.user, bleskomat_vars=bleskomat_vars)
diff --git a/lnbits/extensions/bleskomat/views_api.py b/lnbits/extensions/bleskomat/views_api.py
index aed4d02e..8256ece8 100644
--- a/lnbits/extensions/bleskomat/views_api.py
+++ b/lnbits/extensions/bleskomat/views_api.py
@@ -58,13 +58,13 @@ async def api_bleskomat_create_or_update(bleskomat_id=None):
try:
fiat_currency = g.data["fiat_currency"]
exchange_rate_provider = g.data["exchange_rate_provider"]
- rate = await fetch_fiat_exchange_rate(
- currency=fiat_currency,
- provider=exchange_rate_provider
- )
+ rate = await fetch_fiat_exchange_rate(currency=fiat_currency, provider=exchange_rate_provider)
except Exception as e:
print(e)
- return jsonify({"message": f"Failed to fetch BTC/{fiat_currency} currency pair from \"{exchange_rate_provider}\""}), HTTPStatus.INTERNAL_SERVER_ERROR
+ return (
+ jsonify({"message": f'Failed to fetch BTC/{fiat_currency} currency pair from "{exchange_rate_provider}"'}),
+ HTTPStatus.INTERNAL_SERVER_ERROR,
+ )
if bleskomat_id:
bleskomat = await get_bleskomat(bleskomat_id)
diff --git a/lnbits/extensions/withdraw/crud.py b/lnbits/extensions/withdraw/crud.py
index 11f7d949..18f77db0 100644
--- a/lnbits/extensions/withdraw/crud.py
+++ b/lnbits/extensions/withdraw/crud.py
@@ -124,4 +124,5 @@ async def create_hash_check(
async def get_hash_check(the_hash: str, lnurl_id: str) -> Optional[HashCheck]:
row = await db.fetchone("SELECT * FROM hash_check WHERE id = ?", (the_hash,))
+
return HashCheck.from_row(row) if row else None
\ No newline at end of file
From 1e9151cedcae72fd768d998230ba88dea5c87bdc Mon Sep 17 00:00:00 2001
From: benarc
Date: Wed, 17 Mar 2021 19:59:00 +0000
Subject: [PATCH 11/11] ran prettier on captcha
---
.../extensions/captcha/static/js/captcha.js | 131 ++++++++++--------
.../captcha/templates/captcha/display.html | 8 +-
.../captcha/templates/captcha/index.html | 45 +++---
3 files changed, 106 insertions(+), 78 deletions(-)
diff --git a/lnbits/extensions/captcha/static/js/captcha.js b/lnbits/extensions/captcha/static/js/captcha.js
index 6d86e865..b2387289 100644
--- a/lnbits/extensions/captcha/static/js/captcha.js
+++ b/lnbits/extensions/captcha/static/js/captcha.js
@@ -1,65 +1,80 @@
var ciframeLoaded = !1,
- captchaStyleAdded = !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");
- return e.src = "http://localhost:5000/captcha/" + captchaid, e
+ 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')
+ return (e.src = 'http://localhost:5000/captcha/' + captchaid), e
}
-document.addEventListener("DOMContentLoaded", function() {
- if (captchaStyleAdded) console.log("Captcha stuff already added!");
- else {
- console.log("Adding captcha stuff"), 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\t \t×\t\t
\t', document.getElementsByTagName("body")[0].appendChild(a);
- var r = document.getElementsByClassName("modal-captcha-content").item(0);
- document.getElementsByClassName("close-button-captcha").item(0).addEventListener("click", d), window.addEventListener("click", function(t) {
- t.target === a && d()
- }), i.addEventListener("change", function() {
- if(this.checked){
- // console.log("checkbox checked");
- if (0 == ciframeLoaded) {
- // console.log("n: ", n);
- var t = ccreateIframeElement(n);
- r.appendChild(t), ciframeLoaded = !0
- }
- d()
- }
- })
- }
+document.addEventListener('DOMContentLoaded', function () {
+ if (captchaStyleAdded) console.log('Captcha stuff already added!')
+ else {
+ console.log('Adding captcha stuff'), (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\t \t×\t\t
\t'),
+ document.getElementsByTagName('body')[0].appendChild(a)
+ var r = document.getElementsByClassName('modal-captcha-content').item(0)
+ document
+ .getElementsByClassName('close-button-captcha')
+ .item(0)
+ .addEventListener('click', d),
+ window.addEventListener('click', function (t) {
+ t.target === a && d()
+ }),
+ i.addEventListener('change', function () {
+ if (this.checked) {
+ // console.log("checkbox checked");
+ if (0 == ciframeLoaded) {
+ // console.log("n: ", n);
+ var t = ccreateIframeElement(n)
+ r.appendChild(t), (ciframeLoaded = !0)
+ }
+ d()
+ }
+ })
+ }
- function d() {
- a.classList.toggle("show-modal-captcha")
- }
-});
+ function d() {
+ a.classList.toggle('show-modal-captcha')
+ }
+})
-function receiveMessage(event){
- if (event.data.includes("paymenthash")){
- // console.log("paymenthash received: ", event.data);
- document.getElementById("captchapayhash").value = event.data.split("_")[1];
- }
- if (event.data.includes("removetheiframe")){
- if (event.data.includes("nok")){
- //invoice was NOT paid
- // console.log("receiveMessage not paid")
- document.getElementById("captchacheckbox").checked = false;
- }
- ciframeLoaded = !1;
- var element = document.getElementById('captcha-iframe');
- document.getElementsByClassName("modal-captcha-container")[0].classList.toggle("show-modal-captcha");
- element.parentNode.removeChild(element);
- }
+function receiveMessage(event) {
+ if (event.data.includes('paymenthash')) {
+ // console.log("paymenthash received: ", event.data);
+ document.getElementById('captchapayhash').value = event.data.split('_')[1]
+ }
+ if (event.data.includes('removetheiframe')) {
+ if (event.data.includes('nok')) {
+ //invoice was NOT paid
+ // console.log("receiveMessage not paid")
+ document.getElementById('captchacheckbox').checked = false
+ }
+ ciframeLoaded = !1
+ var element = document.getElementById('captcha-iframe')
+ document
+ .getElementsByClassName('modal-captcha-container')[0]
+ .classList.toggle('show-modal-captcha')
+ element.parentNode.removeChild(element)
+ }
}
-window.addEventListener("message", receiveMessage, false);
-
-
+window.addEventListener('message', receiveMessage, false)
diff --git a/lnbits/extensions/captcha/templates/captcha/display.html b/lnbits/extensions/captcha/templates/captcha/display.html
index af40ff4a..80e59e63 100644
--- a/lnbits/extensions/captcha/templates/captcha/display.html
+++ b/lnbits/extensions/captcha/templates/captcha/display.html
@@ -46,7 +46,11 @@
Copy invoice
- Cancel
@@ -58,7 +62,7 @@
Captcha accepted. You are probably human.
-
diff --git a/lnbits/extensions/captcha/templates/captcha/index.html b/lnbits/extensions/captcha/templates/captcha/index.html
index a83e1029..2250bced 100644
--- a/lnbits/extensions/captcha/templates/captcha/index.html
+++ b/lnbits/extensions/captcha/templates/captcha/index.html
@@ -106,7 +106,7 @@
label="Wallet *"
>
-\n'
- + '\n'
- + '
\n'
- + '\n'
- + '