From c4924bcf24f1c6e9edcbea1ef0ac164a25417481 Mon Sep 17 00:00:00 2001
From: matthewcroughan
Date: Fri, 8 Jul 2022 09:20:38 +0100
Subject: [PATCH 01/18] gitignore: add Nix ignores
---
.gitignore | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.gitignore b/.gitignore
index 07ee15b8..b70f620d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,3 +34,6 @@ __bundle__
node_modules
lnbits/static/bundle.*
docker
+
+# Nix
+*result*
From 50a5f47308ccce2f367b5e2b350b043480a9468d Mon Sep 17 00:00:00 2001
From: matthewcroughan
Date: Fri, 8 Jul 2022 09:22:35 +0100
Subject: [PATCH 02/18] Add Poetry as a build system
---
build.py | 110 +++++
poetry.lock | 1165 ++++++++++++++++++++++++++++++++++++++++++++++++
pyproject.toml | 70 +++
3 files changed, 1345 insertions(+)
create mode 100644 build.py
create mode 100644 poetry.lock
create mode 100644 pyproject.toml
diff --git a/build.py b/build.py
new file mode 100644
index 00000000..5cc8b7de
--- /dev/null
+++ b/build.py
@@ -0,0 +1,110 @@
+import warnings
+import subprocess
+import glob
+import os
+from os import path
+from typing import Any, List, NamedTuple, Optional
+from pathlib import Path
+
+LNBITS_PATH = path.dirname(path.realpath(__file__)) + "/lnbits"
+
+def get_js_vendored(prefer_minified: bool = False) -> List[str]:
+ paths = get_vendored(".js", prefer_minified)
+
+ def sorter(key: str):
+ if "moment@" in key:
+ return 1
+ if "vue@" in key:
+ return 2
+ if "vue-router@" in key:
+ return 3
+ if "polyfills" in key:
+ return 4
+ return 9
+
+ return sorted(paths, key=sorter)
+
+
+def get_css_vendored(prefer_minified: bool = False) -> List[str]:
+ paths = get_vendored(".css", prefer_minified)
+
+ def sorter(key: str):
+ if "quasar@" in key:
+ return 1
+ if "vue@" in key:
+ return 2
+ if "chart.js@" in key:
+ return 100
+ return 9
+
+ return sorted(paths, key=sorter)
+
+
+def get_vendored(ext: str, prefer_minified: bool = False) -> List[str]:
+ paths: List[str] = []
+ for path in glob.glob(
+ os.path.join(LNBITS_PATH, "static/vendor/**"), recursive=True
+ ):
+ if path.endswith(".min" + ext):
+ # path is minified
+ unminified = path.replace(".min" + ext, ext)
+ if prefer_minified:
+ paths.append(path)
+ if unminified in paths:
+ paths.remove(unminified)
+ elif unminified not in paths:
+ paths.append(path)
+
+ elif path.endswith(ext):
+ # path is not minified
+ minified = path.replace(ext, ".min" + ext)
+ if not prefer_minified:
+ paths.append(path)
+ if minified in paths:
+ paths.remove(minified)
+ elif minified not in paths:
+ paths.append(path)
+
+ return sorted(paths)
+
+
+def url_for_vendored(abspath: str) -> str:
+ return "/" + os.path.relpath(abspath, LNBITS_PATH)
+
+def transpile_scss():
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ from scss.compiler import compile_string # type: ignore
+
+ with open(os.path.join(LNBITS_PATH, "static/scss/base.scss")) as scss:
+ with open(os.path.join(LNBITS_PATH, "static/css/base.css"), "w") as css:
+ css.write(compile_string(scss.read()))
+
+def bundle_vendored():
+ for getfiles, outputpath in [
+ (get_js_vendored, os.path.join(LNBITS_PATH, "static/bundle.js")),
+ (get_css_vendored, os.path.join(LNBITS_PATH, "static/bundle.css")),
+ ]:
+ output = ""
+ for path in getfiles():
+ with open(path) as f:
+ output += "/* " + url_for_vendored(path) + " */\n" + f.read() + ";\n"
+ with open(outputpath, "w") as f:
+ f.write(output)
+
+
+def build():
+ transpile_scss()
+ bundle_vendored()
+# root = Path("lnbits/static/foo")
+# root.mkdir(parents=True)
+# root.joinpath("example.css").write_text("")
+
+if __name__ == "__main__":
+ build()
+
+#def build(setup_kwargs):
+# """Build """
+# transpile_scss()
+# bundle_vendored()
+# subprocess.run(["ls", "-la", "./lnbits/static"])
diff --git a/poetry.lock b/poetry.lock
new file mode 100644
index 00000000..48c508ce
--- /dev/null
+++ b/poetry.lock
@@ -0,0 +1,1165 @@
+[[package]]
+name = "aiofiles"
+version = "0.7.0"
+description = "File support for asyncio."
+category = "main"
+optional = false
+python-versions = ">=3.6,<4.0"
+
+[[package]]
+name = "anyio"
+version = "3.6.1"
+description = "High level compatibility layer for multiple asynchronous event loop implementations"
+category = "main"
+optional = false
+python-versions = ">=3.6.2"
+
+[package.dependencies]
+idna = ">=2.8"
+sniffio = ">=1.1"
+
+[package.extras]
+doc = ["packaging", "sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"]
+test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"]
+trio = ["trio (>=0.16)"]
+
+[[package]]
+name = "asgiref"
+version = "3.4.1"
+description = "ASGI specs, helper code, and adapters"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.extras]
+tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"]
+
+[[package]]
+name = "attrs"
+version = "21.2.0"
+description = "Classes Without Boilerplate"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[package.extras]
+dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"]
+docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
+tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"]
+tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"]
+
+[[package]]
+name = "bech32"
+version = "1.2.0"
+description = "Reference implementation for Bech32 and segwit addresses."
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
+[[package]]
+name = "bitstring"
+version = "3.1.9"
+description = "Simple construction, analysis and modification of binary data."
+category = "main"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "cerberus"
+version = "1.3.4"
+description = "Lightweight, extensible schema and data validation tool for Python dictionaries."
+category = "main"
+optional = false
+python-versions = ">=2.7"
+
+[[package]]
+name = "certifi"
+version = "2021.5.30"
+description = "Python package for providing Mozilla's CA Bundle."
+category = "main"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "cffi"
+version = "1.15.0"
+description = "Foreign Function Interface for Python calling C code."
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+pycparser = "*"
+
+[[package]]
+name = "charset-normalizer"
+version = "2.0.6"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
+category = "main"
+optional = false
+python-versions = ">=3.5.0"
+
+[package.extras]
+unicode_backport = ["unicodedata2"]
+
+[[package]]
+name = "click"
+version = "8.0.1"
+description = "Composable command line interface toolkit"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "colorama"
+version = "0.4.5"
+description = "Cross-platform colored terminal text."
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[[package]]
+name = "ecdsa"
+version = "0.17.0"
+description = "ECDSA cryptographic signature library (pure python)"
+category = "main"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+
+[package.dependencies]
+six = ">=1.9.0"
+
+[package.extras]
+gmpy = ["gmpy"]
+gmpy2 = ["gmpy2"]
+
+[[package]]
+name = "embit"
+version = "0.4.9"
+description = "yet another bitcoin library"
+category = "main"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "environs"
+version = "9.3.3"
+description = "simplified environment variable parsing"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+marshmallow = ">=3.0.0"
+python-dotenv = "*"
+
+[package.extras]
+dev = ["pytest", "dj-database-url", "dj-email-url", "django-cache-url", "flake8 (==3.9.2)", "flake8-bugbear (==21.4.3)", "mypy (==0.910)", "pre-commit (>=2.4,<3.0)", "tox"]
+django = ["dj-database-url", "dj-email-url", "django-cache-url"]
+lint = ["flake8 (==3.9.2)", "flake8-bugbear (==21.4.3)", "mypy (==0.910)", "pre-commit (>=2.4,<3.0)"]
+tests = ["pytest", "dj-database-url", "dj-email-url", "django-cache-url"]
+
+[[package]]
+name = "fastapi"
+version = "0.78.0"
+description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
+category = "main"
+optional = false
+python-versions = ">=3.6.1"
+
+[package.dependencies]
+pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0"
+starlette = "0.19.1"
+
+[package.extras]
+all = ["requests (>=2.24.0,<3.0.0)", "jinja2 (>=2.11.2,<4.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "itsdangerous (>=1.1.0,<3.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)", "orjson (>=3.2.1,<4.0.0)", "email_validator (>=1.1.1,<2.0.0)", "uvicorn[standard] (>=0.12.0,<0.18.0)"]
+dev = ["python-jose[cryptography] (>=3.3.0,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "autoflake (>=1.4.0,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "uvicorn[standard] (>=0.12.0,<0.18.0)", "pre-commit (>=2.17.0,<3.0.0)"]
+doc = ["mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "typer (>=0.4.1,<0.5.0)", "pyyaml (>=5.3.1,<7.0.0)"]
+test = ["pytest (>=6.2.4,<7.0.0)", "pytest-cov (>=2.12.0,<4.0.0)", "mypy (==0.910)", "flake8 (>=3.8.3,<4.0.0)", "black (==22.3.0)", "isort (>=5.0.6,<6.0.0)", "requests (>=2.24.0,<3.0.0)", "httpx (>=0.14.0,<0.19.0)", "email_validator (>=1.1.1,<2.0.0)", "sqlalchemy (>=1.3.18,<1.5.0)", "peewee (>=3.13.3,<4.0.0)", "databases[sqlite] (>=0.3.2,<0.6.0)", "orjson (>=3.2.1,<4.0.0)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "flask (>=1.1.2,<3.0.0)", "anyio[trio] (>=3.2.1,<4.0.0)", "types-ujson (==4.2.1)", "types-orjson (==3.6.2)", "types-dataclasses (==0.6.5)"]
+
+[[package]]
+name = "h11"
+version = "0.12.0"
+description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[[package]]
+name = "httpcore"
+version = "0.13.7"
+description = "A minimal low-level HTTP client."
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+anyio = ">=3.0.0,<4.0.0"
+h11 = ">=0.11,<0.13"
+sniffio = ">=1.0.0,<2.0.0"
+
+[package.extras]
+http2 = ["h2 (>=3,<5)"]
+
+[[package]]
+name = "httptools"
+version = "0.2.0"
+description = "A collection of framework independent HTTP protocol utils."
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.extras]
+test = ["Cython (==0.29.22)"]
+
+[[package]]
+name = "httpx"
+version = "0.19.0"
+description = "The next generation HTTP client."
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+certifi = "*"
+charset-normalizer = "*"
+httpcore = ">=0.13.3,<0.14.0"
+rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]}
+sniffio = "*"
+
+[package.extras]
+brotli = ["brotlicffi", "brotli"]
+http2 = ["h2 (>=3,<5)"]
+
+[[package]]
+name = "idna"
+version = "3.2"
+description = "Internationalized Domain Names in Applications (IDNA)"
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
+[[package]]
+name = "importlib-metadata"
+version = "4.8.1"
+description = "Read metadata from Python packages"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+zipp = ">=0.5"
+
+[package.extras]
+docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
+perf = ["ipython"]
+testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"]
+
+[[package]]
+name = "jinja2"
+version = "3.0.1"
+description = "A very fast and expressive template engine."
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+MarkupSafe = ">=2.0"
+
+[package.extras]
+i18n = ["Babel (>=2.7)"]
+
+[[package]]
+name = "lnurl"
+version = "0.3.6"
+description = "LNURL implementation for Python."
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+bech32 = "*"
+pydantic = "*"
+
+[[package]]
+name = "loguru"
+version = "0.5.3"
+description = "Python logging made (stupidly) simple"
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
+[package.dependencies]
+colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""}
+win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""}
+
+[package.extras]
+dev = ["codecov (>=2.0.15)", "colorama (>=0.3.4)", "flake8 (>=3.7.7)", "tox (>=3.9.0)", "tox-travis (>=0.12)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "Sphinx (>=2.2.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "black (>=19.10b0)", "isort (>=5.1.1)"]
+
+[[package]]
+name = "markupsafe"
+version = "2.0.1"
+description = "Safely add untrusted strings to HTML/XML markup."
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[[package]]
+name = "marshmallow"
+version = "3.13.0"
+description = "A lightweight library for converting complex datatypes to and from native Python datatypes."
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
+[package.extras]
+dev = ["pytest", "pytz", "simplejson", "mypy (==0.910)", "flake8 (==3.9.2)", "flake8-bugbear (==21.4.3)", "pre-commit (>=2.4,<3.0)", "tox"]
+docs = ["sphinx (==4.1.1)", "sphinx-issues (==1.2.0)", "alabaster (==0.7.12)", "sphinx-version-warning (==1.1.2)", "autodocsumm (==0.2.6)"]
+lint = ["mypy (==0.910)", "flake8 (==3.9.2)", "flake8-bugbear (==21.4.3)", "pre-commit (>=2.4,<3.0)"]
+tests = ["pytest", "pytz", "simplejson"]
+
+[[package]]
+name = "outcome"
+version = "1.1.0"
+description = "Capture the outcome of Python function calls."
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+attrs = ">=19.2.0"
+
+[[package]]
+name = "psycopg2-binary"
+version = "2.9.1"
+description = "psycopg2 - Python-PostgreSQL Database Adapter"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[[package]]
+name = "pycparser"
+version = "2.21"
+description = "C parser in Python"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[[package]]
+name = "pycryptodomex"
+version = "3.14.1"
+description = "Cryptographic library for Python"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[[package]]
+name = "pydantic"
+version = "1.8.2"
+description = "Data validation and settings management using python 3.6 type hinting"
+category = "main"
+optional = false
+python-versions = ">=3.6.1"
+
+[package.dependencies]
+typing-extensions = ">=3.7.4.3"
+
+[package.extras]
+dotenv = ["python-dotenv (>=0.10.4)"]
+email = ["email-validator (>=1.0.3)"]
+
+[[package]]
+name = "pypng"
+version = "0.0.21"
+description = "Pure Python library for saving and loading PNG images"
+category = "main"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "pyqrcode"
+version = "1.2.1"
+description = "A QR code generator written purely in Python with SVG, EPS, PNG and terminal output."
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.extras]
+PNG = ["pypng (>=0.0.13)"]
+
+[[package]]
+name = "pyscss"
+version = "1.3.7"
+description = "pyScss, a Scss compiler for Python"
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+six = "*"
+
+[[package]]
+name = "python-dotenv"
+version = "0.19.0"
+description = "Read key-value pairs from a .env file and set them as environment variables"
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
+[package.extras]
+cli = ["click (>=5.0)"]
+
+[[package]]
+name = "pyyaml"
+version = "5.4.1"
+description = "YAML parser and emitter for Python"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
+
+[[package]]
+name = "represent"
+version = "1.6.0.post0"
+description = "Create __repr__ automatically or declaratively."
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[package.dependencies]
+six = ">=1.8.0"
+
+[package.extras]
+test = ["ipython", "pytest (>=3.0.5)", "mock"]
+
+[[package]]
+name = "rfc3986"
+version = "1.5.0"
+description = "Validating URI References per RFC 3986"
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+idna = {version = "*", optional = true, markers = "extra == \"idna2008\""}
+
+[package.extras]
+idna2008 = ["idna"]
+
+[[package]]
+name = "secp256k1"
+version = "0.14.0"
+description = "FFI bindings to libsecp256k1"
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+cffi = ">=1.3.0"
+
+[[package]]
+name = "shortuuid"
+version = "1.0.1"
+description = "A generator library for concise, unambiguous and URL-safe UUIDs."
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
+[[package]]
+name = "six"
+version = "1.16.0"
+description = "Python 2 and 3 compatibility utilities"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+
+[[package]]
+name = "sniffio"
+version = "1.2.0"
+description = "Sniff out which async library your code is running under"
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
+[[package]]
+name = "sqlalchemy"
+version = "1.3.23"
+description = "Database Abstraction Library"
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[package.extras]
+mssql = ["pyodbc"]
+mssql_pymssql = ["pymssql"]
+mssql_pyodbc = ["pyodbc"]
+mysql = ["mysqlclient"]
+oracle = ["cx-oracle"]
+postgresql = ["psycopg2"]
+postgresql_pg8000 = ["pg8000 (<1.16.6)"]
+postgresql_psycopg2binary = ["psycopg2-binary"]
+postgresql_psycopg2cffi = ["psycopg2cffi"]
+pymysql = ["pymysql (<1)", "pymysql"]
+
+[[package]]
+name = "sqlalchemy-aio"
+version = "0.16.0"
+description = "Async support for SQLAlchemy."
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+outcome = "*"
+represent = ">=1.4"
+sqlalchemy = "*"
+
+[package.extras]
+test = ["pytest (>=5.4)", "pytest-asyncio (>=0.14)", "pytest-trio (>=0.6)"]
+test-noextras = ["pytest (>=5.4)", "pytest-asyncio (>=0.14)"]
+trio = ["trio (>=0.15)"]
+
+[[package]]
+name = "sse-starlette"
+version = "0.6.2"
+description = "SSE plugin for Starlette"
+category = "main"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "starlette"
+version = "0.19.1"
+description = "The little ASGI library that shines."
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+anyio = ">=3.4.0,<5"
+typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""}
+
+[package.extras]
+full = ["itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"]
+
+[[package]]
+name = "typing-extensions"
+version = "3.10.0.2"
+description = "Backported and Experimental Type Hints for Python 3.5+"
+category = "main"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "uvicorn"
+version = "0.18.1"
+description = "The lightning-fast ASGI server."
+category = "main"
+optional = false
+python-versions = ">=3.7"
+
+[package.dependencies]
+click = ">=7.0"
+h11 = ">=0.8"
+
+[package.extras]
+standard = ["websockets (>=10.0)", "httptools (>=0.4.0)", "watchfiles (>=0.13)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "colorama (>=0.4)"]
+
+[[package]]
+name = "uvloop"
+version = "0.16.0"
+description = "Fast implementation of asyncio event loop on top of libuv"
+category = "main"
+optional = false
+python-versions = ">=3.7"
+
+[package.extras]
+dev = ["Cython (>=0.29.24,<0.30.0)", "pytest (>=3.6.0)", "Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,<2.8.0)", "pyOpenSSL (>=19.0.0,<19.1.0)", "mypy (>=0.800)"]
+docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)"]
+test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,<2.8.0)", "pyOpenSSL (>=19.0.0,<19.1.0)", "mypy (>=0.800)"]
+
+[[package]]
+name = "watchgod"
+version = "0.7"
+description = "Simple, modern file watching and code reload in python."
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
+[[package]]
+name = "websockets"
+version = "10.0"
+description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
+category = "main"
+optional = false
+python-versions = ">=3.7"
+
+[[package]]
+name = "win32-setctime"
+version = "1.1.0"
+description = "A small Python utility to set file creation time on Windows"
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
+[package.extras]
+dev = ["pytest (>=4.6.2)", "black (>=19.3b0)"]
+
+[[package]]
+name = "zipp"
+version = "3.5.0"
+description = "Backport of pathlib-compatible object wrapper for zip files"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.extras]
+docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
+testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"]
+
+[metadata]
+lock-version = "1.1"
+python-versions = "^3.9"
+content-hash = "921a5f4fe1a4d1a4c3b490f8631ed4bdd0d8af1f1992f1a4f74eaed986c4eb0b"
+
+[metadata.files]
+aiofiles = [
+ {file = "aiofiles-0.7.0-py3-none-any.whl", hash = "sha256:c67a6823b5f23fcab0a2595a289cec7d8c863ffcb4322fb8cd6b90400aedfdbc"},
+ {file = "aiofiles-0.7.0.tar.gz", hash = "sha256:a1c4fc9b2ff81568c83e21392a82f344ea9d23da906e4f6a52662764545e19d4"},
+]
+anyio = [
+ {file = "anyio-3.6.1-py3-none-any.whl", hash = "sha256:cb29b9c70620506a9a8f87a309591713446953302d7d995344d0d7c6c0c9a7be"},
+ {file = "anyio-3.6.1.tar.gz", hash = "sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b"},
+]
+asgiref = [
+ {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"},
+ {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"},
+]
+attrs = [
+ {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"},
+ {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"},
+]
+bech32 = [
+ {file = "bech32-1.2.0-py3-none-any.whl", hash = "sha256:990dc8e5a5e4feabbdf55207b5315fdd9b73db40be294a19b3752cde9e79d981"},
+ {file = "bech32-1.2.0.tar.gz", hash = "sha256:7d6db8214603bd7871fcfa6c0826ef68b85b0abd90fa21c285a9c5e21d2bd899"},
+]
+bitstring = [
+ {file = "bitstring-3.1.9-py2-none-any.whl", hash = "sha256:e3e340e58900a948787a05e8c08772f1ccbe133f6f41fe3f0fa19a18a22bbf4f"},
+ {file = "bitstring-3.1.9-py3-none-any.whl", hash = "sha256:0de167daa6a00c9386255a7cac931b45e6e24e0ad7ea64f1f92a64ac23ad4578"},
+ {file = "bitstring-3.1.9.tar.gz", hash = "sha256:a5848a3f63111785224dca8bb4c0a75b62ecdef56a042c8d6be74b16f7e860e7"},
+]
+cerberus = [
+ {file = "Cerberus-1.3.4.tar.gz", hash = "sha256:d1b21b3954b2498d9a79edf16b3170a3ac1021df88d197dc2ce5928ba519237c"},
+]
+certifi = [
+ {file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"},
+ {file = "certifi-2021.5.30.tar.gz", hash = "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee"},
+]
+cffi = [
+ {file = "cffi-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962"},
+ {file = "cffi-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0"},
+ {file = "cffi-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14"},
+ {file = "cffi-1.15.0-cp27-cp27m-win32.whl", hash = "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474"},
+ {file = "cffi-1.15.0-cp27-cp27m-win_amd64.whl", hash = "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6"},
+ {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27"},
+ {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023"},
+ {file = "cffi-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2"},
+ {file = "cffi-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e"},
+ {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7"},
+ {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3"},
+ {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c"},
+ {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962"},
+ {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382"},
+ {file = "cffi-1.15.0-cp310-cp310-win32.whl", hash = "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55"},
+ {file = "cffi-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0"},
+ {file = "cffi-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e"},
+ {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39"},
+ {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc"},
+ {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032"},
+ {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8"},
+ {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605"},
+ {file = "cffi-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e"},
+ {file = "cffi-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc"},
+ {file = "cffi-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636"},
+ {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4"},
+ {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997"},
+ {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b"},
+ {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2"},
+ {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7"},
+ {file = "cffi-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66"},
+ {file = "cffi-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029"},
+ {file = "cffi-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880"},
+ {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20"},
+ {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024"},
+ {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e"},
+ {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728"},
+ {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6"},
+ {file = "cffi-1.15.0-cp38-cp38-win32.whl", hash = "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c"},
+ {file = "cffi-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443"},
+ {file = "cffi-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a"},
+ {file = "cffi-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37"},
+ {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a"},
+ {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e"},
+ {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796"},
+ {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df"},
+ {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8"},
+ {file = "cffi-1.15.0-cp39-cp39-win32.whl", hash = "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a"},
+ {file = "cffi-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139"},
+ {file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"},
+]
+charset-normalizer = [
+ {file = "charset-normalizer-2.0.6.tar.gz", hash = "sha256:5ec46d183433dcbd0ab716f2d7f29d8dee50505b3fdb40c6b985c7c4f5a3591f"},
+ {file = "charset_normalizer-2.0.6-py3-none-any.whl", hash = "sha256:5d209c0a931f215cee683b6445e2d77677e7e75e159f78def0db09d68fafcaa6"},
+]
+click = [
+ {file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"},
+ {file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"},
+]
+colorama = [
+ {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"},
+ {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
+]
+ecdsa = [
+ {file = "ecdsa-0.17.0-py2.py3-none-any.whl", hash = "sha256:5cf31d5b33743abe0dfc28999036c849a69d548f994b535e527ee3cb7f3ef676"},
+ {file = "ecdsa-0.17.0.tar.gz", hash = "sha256:b9f500bb439e4153d0330610f5d26baaf18d17b8ced1bc54410d189385ea68aa"},
+]
+embit = [
+ {file = "embit-0.4.9.tar.gz", hash = "sha256:992332bd89af6e2d027e26fe437eb14aa33997db08c882c49064d49c3e6f4ab9"},
+]
+environs = [
+ {file = "environs-9.3.3-py2.py3-none-any.whl", hash = "sha256:ee5466156b50fe03aa9fec6e720feea577b5bf515d7f21b2c46608272557ba26"},
+ {file = "environs-9.3.3.tar.gz", hash = "sha256:72b867ff7b553076cdd90f3ee01ecc1cf854987639c9c459f0ed0d3d44ae490c"},
+]
+fastapi = [
+ {file = "fastapi-0.78.0-py3-none-any.whl", hash = "sha256:15fcabd5c78c266fa7ae7d8de9b384bfc2375ee0503463a6febbe3bab69d6f65"},
+ {file = "fastapi-0.78.0.tar.gz", hash = "sha256:3233d4a789ba018578658e2af1a4bb5e38bdd122ff722b313666a9b2c6786a83"},
+]
+h11 = [
+ {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"},
+ {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"},
+]
+httpcore = [
+ {file = "httpcore-0.13.7-py3-none-any.whl", hash = "sha256:369aa481b014cf046f7067fddd67d00560f2f00426e79569d99cb11245134af0"},
+ {file = "httpcore-0.13.7.tar.gz", hash = "sha256:036f960468759e633574d7c121afba48af6419615d36ab8ede979f1ad6276fa3"},
+]
+httptools = [
+ {file = "httptools-0.2.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:79dbc21f3612a78b28384e989b21872e2e3cf3968532601544696e4ed0007ce5"},
+ {file = "httptools-0.2.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:78d03dd39b09c99ec917d50189e6743adbfd18c15d5944392d2eabda688bf149"},
+ {file = "httptools-0.2.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:a23166e5ae2775709cf4f7ad4c2048755ebfb272767d244e1a96d55ac775cca7"},
+ {file = "httptools-0.2.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3ab1f390d8867f74b3b5ee2a7ecc9b8d7f53750bd45714bf1cb72a953d7dfa77"},
+ {file = "httptools-0.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a7594f9a010cdf1e16a58b3bf26c9da39bbf663e3b8d46d39176999d71816658"},
+ {file = "httptools-0.2.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:01b392a166adcc8bc2f526a939a8aabf89fe079243e1543fd0e7dc1b58d737cb"},
+ {file = "httptools-0.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:80ffa04fe8c8dfacf6e4cef8277347d35b0442c581f5814f3b0cf41b65c43c6e"},
+ {file = "httptools-0.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d5682eeb10cca0606c4a8286a3391d4c3c5a36f0c448e71b8bd05be4e1694bfb"},
+ {file = "httptools-0.2.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:a289c27ccae399a70eacf32df9a44059ca2ba4ac444604b00a19a6c1f0809943"},
+ {file = "httptools-0.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:813871f961edea6cb2fe312f2d9b27d12a51ba92545380126f80d0de1917ea15"},
+ {file = "httptools-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:cc9be041e428c10f8b6ab358c6b393648f9457094e1dcc11b4906026d43cd380"},
+ {file = "httptools-0.2.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b08d00d889a118f68f37f3c43e359aab24ee29eb2e3fe96d64c6a2ba8b9d6557"},
+ {file = "httptools-0.2.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:fd3b8905e21431ad306eeaf56644a68fdd621bf8f3097eff54d0f6bdf7262065"},
+ {file = "httptools-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:200fc1cdf733a9ff554c0bb97a4047785cfaad9875307d6087001db3eb2b417f"},
+ {file = "httptools-0.2.0.tar.gz", hash = "sha256:94505026be56652d7a530ab03d89474dc6021019d6b8682281977163b3471ea0"},
+]
+httpx = [
+ {file = "httpx-0.19.0-py3-none-any.whl", hash = "sha256:9bd728a6c5ec0a9e243932a9983d57d3cc4a87bb4f554e1360fce407f78f9435"},
+ {file = "httpx-0.19.0.tar.gz", hash = "sha256:92ecd2c00c688b529eda11cedb15161eaf02dee9116712f621c70d9a40b2cdd0"},
+]
+idna = [
+ {file = "idna-3.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"},
+ {file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"},
+]
+importlib-metadata = [
+ {file = "importlib_metadata-4.8.1-py3-none-any.whl", hash = "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15"},
+ {file = "importlib_metadata-4.8.1.tar.gz", hash = "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1"},
+]
+jinja2 = [
+ {file = "Jinja2-3.0.1-py3-none-any.whl", hash = "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4"},
+ {file = "Jinja2-3.0.1.tar.gz", hash = "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"},
+]
+lnurl = [
+ {file = "lnurl-0.3.6-py3-none-any.whl", hash = "sha256:579982fd8c4d25bc84c61c74ec45cb7999fa1fa2426f5d5aeb0160ba333b9c92"},
+ {file = "lnurl-0.3.6.tar.gz", hash = "sha256:8af07460115a48f3122a5a9c9a6062bee3897d5f6ab4c9a60f6561a83a8234f6"},
+]
+loguru = [
+ {file = "loguru-0.5.3-py3-none-any.whl", hash = "sha256:f8087ac396b5ee5f67c963b495d615ebbceac2796379599820e324419d53667c"},
+ {file = "loguru-0.5.3.tar.gz", hash = "sha256:b28e72ac7a98be3d28ad28570299a393dfcd32e5e3f6a353dec94675767b6319"},
+]
+markupsafe = [
+ {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"},
+ {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"},
+ {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"},
+ {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"},
+ {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"},
+ {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
+ {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
+]
+marshmallow = [
+ {file = "marshmallow-3.13.0-py2.py3-none-any.whl", hash = "sha256:dd4724335d3c2b870b641ffe4a2f8728a1380cd2e7e2312756715ffeaa82b842"},
+ {file = "marshmallow-3.13.0.tar.gz", hash = "sha256:c67929438fd73a2be92128caa0325b1b5ed8b626d91a094d2f7f2771bf1f1c0e"},
+]
+outcome = [
+ {file = "outcome-1.1.0-py2.py3-none-any.whl", hash = "sha256:c7dd9375cfd3c12db9801d080a3b63d4b0a261aa996c4c13152380587288d958"},
+ {file = "outcome-1.1.0.tar.gz", hash = "sha256:e862f01d4e626e63e8f92c38d1f8d5546d3f9cce989263c521b2e7990d186967"},
+]
+psycopg2-binary = [
+ {file = "psycopg2-binary-2.9.1.tar.gz", hash = "sha256:b0221ca5a9837e040ebf61f48899926b5783668b7807419e4adae8175a31f773"},
+ {file = "psycopg2_binary-2.9.1-cp310-cp310-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:24b0b6688b9f31a911f2361fe818492650795c9e5d3a1bc647acbd7440142a4f"},
+ {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:542875f62bc56e91c6eac05a0deadeae20e1730be4c6334d8f04c944fcd99759"},
+ {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:661509f51531ec125e52357a489ea3806640d0ca37d9dada461ffc69ee1e7b6e"},
+ {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:d92272c7c16e105788efe2cfa5d680f07e34e0c29b03c1908f8636f55d5f915a"},
+ {file = "psycopg2_binary-2.9.1-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:736b8797b58febabb85494142c627bd182b50d2a7ec65322983e71065ad3034c"},
+ {file = "psycopg2_binary-2.9.1-cp310-cp310-win32.whl", hash = "sha256:ebccf1123e7ef66efc615a68295bf6fdba875a75d5bba10a05073202598085fc"},
+ {file = "psycopg2_binary-2.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:1f6ca4a9068f5c5c57e744b4baa79f40e83e3746875cac3c45467b16326bab45"},
+ {file = "psycopg2_binary-2.9.1-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:c250a7ec489b652c892e4f0a5d122cc14c3780f9f643e1a326754aedf82d9a76"},
+ {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aef9aee84ec78af51107181d02fe8773b100b01c5dfde351184ad9223eab3698"},
+ {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:123c3fb684e9abfc47218d3784c7b4c47c8587951ea4dd5bc38b6636ac57f616"},
+ {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_24_aarch64.whl", hash = "sha256:995fc41ebda5a7a663a254a1dcac52638c3e847f48307b5416ee373da15075d7"},
+ {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_24_ppc64le.whl", hash = "sha256:fbb42a541b1093385a2d8c7eec94d26d30437d0e77c1d25dae1dcc46741a385e"},
+ {file = "psycopg2_binary-2.9.1-cp36-cp36m-win32.whl", hash = "sha256:20f1ab44d8c352074e2d7ca67dc00843067788791be373e67a0911998787ce7d"},
+ {file = "psycopg2_binary-2.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f6fac64a38f6768e7bc7b035b9e10d8a538a9fadce06b983fb3e6fa55ac5f5ce"},
+ {file = "psycopg2_binary-2.9.1-cp37-cp37m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:1e3a362790edc0a365385b1ac4cc0acc429a0c0d662d829a50b6ce743ae61b5a"},
+ {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f8559617b1fcf59a9aedba2c9838b5b6aa211ffedecabca412b92a1ff75aac1a"},
+ {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a36c7eb6152ba5467fb264d73844877be8b0847874d4822b7cf2d3c0cb8cdcb0"},
+ {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:2f62c207d1740b0bde5c4e949f857b044818f734a3d57f1d0d0edc65050532ed"},
+ {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:cfc523edecddaef56f6740d7de1ce24a2fdf94fd5e704091856a201872e37f9f"},
+ {file = "psycopg2_binary-2.9.1-cp37-cp37m-win32.whl", hash = "sha256:1e85b74cbbb3056e3656f1cc4781294df03383127a8114cbc6531e8b8367bf1e"},
+ {file = "psycopg2_binary-2.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:1473c0215b0613dd938db54a653f68251a45a78b05f6fc21af4326f40e8360a2"},
+ {file = "psycopg2_binary-2.9.1-cp38-cp38-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:35c4310f8febe41f442d3c65066ca93cccefd75013df3d8c736c5b93ec288140"},
+ {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c13d72ed6af7fd2c8acbd95661cf9477f94e381fce0792c04981a8283b52917"},
+ {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14db1752acdd2187d99cb2ca0a1a6dfe57fc65c3281e0f20e597aac8d2a5bd90"},
+ {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:aed4a9a7e3221b3e252c39d0bf794c438dc5453bc2963e8befe9d4cd324dff72"},
+ {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:da113b70f6ec40e7d81b43d1b139b9db6a05727ab8be1ee559f3a69854a69d34"},
+ {file = "psycopg2_binary-2.9.1-cp38-cp38-win32.whl", hash = "sha256:4235f9d5ddcab0b8dbd723dca56ea2922b485ea00e1dafacf33b0c7e840b3d32"},
+ {file = "psycopg2_binary-2.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:988b47ac70d204aed01589ed342303da7c4d84b56c2f4c4b8b00deda123372bf"},
+ {file = "psycopg2_binary-2.9.1-cp39-cp39-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:7360647ea04db2e7dff1648d1da825c8cf68dc5fbd80b8fb5b3ee9f068dcd21a"},
+ {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca86db5b561b894f9e5f115d6a159fff2a2570a652e07889d8a383b5fae66eb4"},
+ {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ced67f1e34e1a450cdb48eb53ca73b60aa0af21c46b9b35ac3e581cf9f00e31"},
+ {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:0f2e04bd2a2ab54fa44ee67fe2d002bb90cee1c0f1cc0ebc3148af7b02034cbd"},
+ {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:3242b9619de955ab44581a03a64bdd7d5e470cc4183e8fcadd85ab9d3756ce7a"},
+ {file = "psycopg2_binary-2.9.1-cp39-cp39-win32.whl", hash = "sha256:0b7dae87f0b729922e06f85f667de7bf16455d411971b2043bbd9577af9d1975"},
+ {file = "psycopg2_binary-2.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:b4d7679a08fea64573c969f6994a2631908bb2c0e69a7235648642f3d2e39a68"},
+]
+pycparser = [
+ {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
+ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
+]
+pycryptodomex = [
+ {file = "pycryptodomex-3.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca88f2f7020002638276439a01ffbb0355634907d1aa5ca91f3dc0c2e44e8f3b"},
+ {file = "pycryptodomex-3.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:8536bc08d130cae6dcba1ea689f2913dfd332d06113904d171f2f56da6228e89"},
+ {file = "pycryptodomex-3.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:406ec8cfe0c098fadb18d597dc2ee6de4428d640c0ccafa453f3d9b2e58d29e2"},
+ {file = "pycryptodomex-3.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:da8db8374295fb532b4b0c467e66800ef17d100e4d5faa2bbbd6df35502da125"},
+ {file = "pycryptodomex-3.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:d709572d64825d8d59ea112e11cc7faf6007f294e9951324b7574af4251e4de8"},
+ {file = "pycryptodomex-3.14.1-cp27-cp27m-win32.whl", hash = "sha256:3da13c2535b7aea94cc2a6d1b1b37746814c74b6e80790daddd55ca5c120a489"},
+ {file = "pycryptodomex-3.14.1-cp27-cp27m-win_amd64.whl", hash = "sha256:298c00ea41a81a491d5b244d295d18369e5aac4b61b77b2de5b249ca61cd6659"},
+ {file = "pycryptodomex-3.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:77931df40bb5ce5e13f4de2bfc982b2ddc0198971fbd947776c8bb5050896eb2"},
+ {file = "pycryptodomex-3.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:c5dd3ffa663c982d7f1be9eb494a8924f6d40e2e2f7d1d27384cfab1b2ac0662"},
+ {file = "pycryptodomex-3.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:2aa887683eee493e015545bd69d3d21ac8d5ad582674ec98f4af84511e353e45"},
+ {file = "pycryptodomex-3.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:8085bd0ad2034352eee4d4f3e2da985c2749cb7344b939f4d95ead38c2520859"},
+ {file = "pycryptodomex-3.14.1-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:e95a4a6c54d27a84a4624d2af8bb9ee178111604653194ca6880c98dcad92f48"},
+ {file = "pycryptodomex-3.14.1-cp35-abi3-manylinux1_i686.whl", hash = "sha256:a4d412eba5679ede84b41dbe48b1bed8f33131ab9db06c238a235334733acc5e"},
+ {file = "pycryptodomex-3.14.1-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:d2cce1c82a7845d7e2e8a0956c6b7ed3f1661c9acf18eb120fc71e098ab5c6fe"},
+ {file = "pycryptodomex-3.14.1-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:f75009715dcf4a3d680c2338ab19dac5498f8121173a929872950f4fb3a48fbf"},
+ {file = "pycryptodomex-3.14.1-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:1ca8e1b4c62038bb2da55451385246f51f412c5f5eabd64812c01766a5989b4a"},
+ {file = "pycryptodomex-3.14.1-cp35-abi3-win32.whl", hash = "sha256:ee835def05622e0c8b1435a906491760a43d0c462f065ec9143ec4b8d79f8bff"},
+ {file = "pycryptodomex-3.14.1-cp35-abi3-win_amd64.whl", hash = "sha256:b5a185ae79f899b01ca49f365bdf15a45d78d9856f09b0de1a41b92afce1a07f"},
+ {file = "pycryptodomex-3.14.1-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:797a36bd1f69df9e2798e33edb4bd04e5a30478efc08f9428c087f17f65a7045"},
+ {file = "pycryptodomex-3.14.1-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:aebecde2adc4a6847094d3bd6a8a9538ef3438a5ea84ac1983fcb167db614461"},
+ {file = "pycryptodomex-3.14.1-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:f8524b8bc89470cec7ac51734907818d3620fb1637f8f8b542d650ebec42a126"},
+ {file = "pycryptodomex-3.14.1-pp27-pypy_73-win32.whl", hash = "sha256:4d0db8df9ffae36f416897ad184608d9d7a8c2b46c4612c6bc759b26c073f750"},
+ {file = "pycryptodomex-3.14.1-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b276cc4deb4a80f9dfd47a41ebb464b1fe91efd8b1b8620cf5ccf8b824b850d6"},
+ {file = "pycryptodomex-3.14.1-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:e36c7e3b5382cd5669cf199c4a04a0279a43b2a3bdd77627e9b89778ac9ec08c"},
+ {file = "pycryptodomex-3.14.1-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:c4d8977ccda886d88dc3ca789de2f1adc714df912ff3934b3d0a3f3d777deafb"},
+ {file = "pycryptodomex-3.14.1-pp36-pypy36_pp73-win32.whl", hash = "sha256:530756d2faa40af4c1f74123e1d889bd07feae45bac2fd32f259a35f7aa74151"},
+ {file = "pycryptodomex-3.14.1.tar.gz", hash = "sha256:2ce76ed0081fd6ac8c74edc75b9d14eca2064173af79843c24fa62573263c1f2"},
+]
+pydantic = [
+ {file = "pydantic-1.8.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:05ddfd37c1720c392f4e0d43c484217b7521558302e7069ce8d318438d297739"},
+ {file = "pydantic-1.8.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a7c6002203fe2c5a1b5cbb141bb85060cbff88c2d78eccbc72d97eb7022c43e4"},
+ {file = "pydantic-1.8.2-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:589eb6cd6361e8ac341db97602eb7f354551482368a37f4fd086c0733548308e"},
+ {file = "pydantic-1.8.2-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:10e5622224245941efc193ad1d159887872776df7a8fd592ed746aa25d071840"},
+ {file = "pydantic-1.8.2-cp36-cp36m-win_amd64.whl", hash = "sha256:99a9fc39470010c45c161a1dc584997f1feb13f689ecf645f59bb4ba623e586b"},
+ {file = "pydantic-1.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a83db7205f60c6a86f2c44a61791d993dff4b73135df1973ecd9eed5ea0bda20"},
+ {file = "pydantic-1.8.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:41b542c0b3c42dc17da70554bc6f38cbc30d7066d2c2815a94499b5684582ecb"},
+ {file = "pydantic-1.8.2-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:ea5cb40a3b23b3265f6325727ddfc45141b08ed665458be8c6285e7b85bd73a1"},
+ {file = "pydantic-1.8.2-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:18b5ea242dd3e62dbf89b2b0ec9ba6c7b5abaf6af85b95a97b00279f65845a23"},
+ {file = "pydantic-1.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:234a6c19f1c14e25e362cb05c68afb7f183eb931dd3cd4605eafff055ebbf287"},
+ {file = "pydantic-1.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:021ea0e4133e8c824775a0cfe098677acf6fa5a3cbf9206a376eed3fc09302cd"},
+ {file = "pydantic-1.8.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e710876437bc07bd414ff453ac8ec63d219e7690128d925c6e82889d674bb505"},
+ {file = "pydantic-1.8.2-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:ac8eed4ca3bd3aadc58a13c2aa93cd8a884bcf21cb019f8cfecaae3b6ce3746e"},
+ {file = "pydantic-1.8.2-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:4a03cbbe743e9c7247ceae6f0d8898f7a64bb65800a45cbdc52d65e370570820"},
+ {file = "pydantic-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:8621559dcf5afacf0069ed194278f35c255dc1a1385c28b32dd6c110fd6531b3"},
+ {file = "pydantic-1.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8b223557f9510cf0bfd8b01316bf6dd281cf41826607eada99662f5e4963f316"},
+ {file = "pydantic-1.8.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:244ad78eeb388a43b0c927e74d3af78008e944074b7d0f4f696ddd5b2af43c62"},
+ {file = "pydantic-1.8.2-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:05ef5246a7ffd2ce12a619cbb29f3307b7c4509307b1b49f456657b43529dc6f"},
+ {file = "pydantic-1.8.2-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:54cd5121383f4a461ff7644c7ca20c0419d58052db70d8791eacbbe31528916b"},
+ {file = "pydantic-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:4be75bebf676a5f0f87937c6ddb061fa39cbea067240d98e298508c1bda6f3f3"},
+ {file = "pydantic-1.8.2-py3-none-any.whl", hash = "sha256:fec866a0b59f372b7e776f2d7308511784dace622e0992a0b59ea3ccee0ae833"},
+ {file = "pydantic-1.8.2.tar.gz", hash = "sha256:26464e57ccaafe72b7ad156fdaa4e9b9ef051f69e175dbbb463283000c05ab7b"},
+]
+pypng = [
+ {file = "pypng-0.0.21-py3-none-any.whl", hash = "sha256:76f8a1539ec56451da7ab7121f12a361969fe0f2d48d703d198ce2a99d6c5afd"},
+]
+pyqrcode = [
+ {file = "PyQRCode-1.2.1.tar.gz", hash = "sha256:fdbf7634733e56b72e27f9bce46e4550b75a3a2c420414035cae9d9d26b234d5"},
+ {file = "PyQRCode-1.2.1.zip", hash = "sha256:1b2812775fa6ff5c527977c4cd2ccb07051ca7d0bc0aecf937a43864abe5eff6"},
+]
+pyscss = [
+ {file = "pyScss-1.3.7.tar.gz", hash = "sha256:f1df571569021a23941a538eb154405dde80bed35dc1ea7c5f3e18e0144746bf"},
+]
+python-dotenv = [
+ {file = "python-dotenv-0.19.0.tar.gz", hash = "sha256:f521bc2ac9a8e03c736f62911605c5d83970021e3fa95b37d769e2bbbe9b6172"},
+ {file = "python_dotenv-0.19.0-py2.py3-none-any.whl", hash = "sha256:aae25dc1ebe97c420f50b81fb0e5c949659af713f31fdb63c749ca68748f34b1"},
+]
+pyyaml = [
+ {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"},
+ {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"},
+ {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"},
+ {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"},
+ {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"},
+ {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"},
+ {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"},
+ {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"},
+ {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"},
+ {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"},
+ {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"},
+ {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"},
+ {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"},
+ {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"},
+ {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"},
+ {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"},
+ {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"},
+ {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"},
+ {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"},
+ {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"},
+ {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"},
+ {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"},
+ {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"},
+ {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"},
+ {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"},
+ {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"},
+ {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"},
+ {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"},
+ {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"},
+]
+represent = [
+ {file = "Represent-1.6.0.post0-py2.py3-none-any.whl", hash = "sha256:99142650756ef1998ce0661568f54a47dac8c638fb27e3816c02536575dbba8c"},
+ {file = "Represent-1.6.0.post0.tar.gz", hash = "sha256:026c0de2ee8385d1255b9c2426cd4f03fe9177ac94c09979bc601946c8493aa0"},
+]
+rfc3986 = [
+ {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"},
+ {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"},
+]
+secp256k1 = [
+ {file = "secp256k1-0.14.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f666c67dcf1dc69e1448b2ede5e12aaf382b600204a61dbc65e4f82cea444405"},
+ {file = "secp256k1-0.14.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fcabb3c3497a902fb61eec72d1b69bf72747d7bcc2a732d56d9319a1e8322262"},
+ {file = "secp256k1-0.14.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7a27c479ab60571502516a1506a562d0a9df062de8ad645313fabfcc97252816"},
+ {file = "secp256k1-0.14.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f4b9306bff6dde020444dfee9ca9b9f5b20ca53a2c0b04898361a3f43d5daf2e"},
+ {file = "secp256k1-0.14.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:72735da6cb28273e924431cd40aa607e7f80ef09608c8c9300be2e0e1d2417b4"},
+ {file = "secp256k1-0.14.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:87f4ad42a370f768910585989a301d1d65de17dcd86f6e8def9b021364b34d5c"},
+ {file = "secp256k1-0.14.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:130f119b06142e597c10eb4470b5a38eae865362d01aaef06b113478d77f728d"},
+ {file = "secp256k1-0.14.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:3aedcfe6eb1c5fa7c6be25b7cc91c76d8eb984271920ba0f7a934ae41ed56f51"},
+ {file = "secp256k1-0.14.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c91dd3154f6c46ac798d9a41166120e1751222587f54516cc3f378f56ce4ac82"},
+ {file = "secp256k1-0.14.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fec790cb6d0d37129ca0ce5b3f8e85692d5fb618d1c440f189453d18694035df"},
+ {file = "secp256k1-0.14.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:63eb148196b8f646922d4be6739b17fbbf50ebb3a020078c823e2445d88b7a81"},
+ {file = "secp256k1-0.14.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:adc23a4c5d24c95191638eb2ca313097827f07db102e77b59faed15d50c98cae"},
+ {file = "secp256k1-0.14.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ce0314788d3248b275426501228969fd32f6501c9d1837902ee0e7bd8264a36f"},
+ {file = "secp256k1-0.14.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bc761894b3634021686714278fc62b73395fa3eded33453eadfd8a00a6c44ef3"},
+ {file = "secp256k1-0.14.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:373dc8bca735f3c2d73259aa2711a9ecea2f3c7edbb663555fe3422e3dd76102"},
+ {file = "secp256k1-0.14.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fe3f503c9dfdf663b500d3e0688ad842e116c2907ad3f1e1d685812df3f56290"},
+ {file = "secp256k1-0.14.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4b1bf09953cde181132cf5e9033065615e5c2694e803165e2db763efa47695e5"},
+ {file = "secp256k1-0.14.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6af07be5f8612628c3638dc7b208f6cc78d0abae3e25797eadb13890c7d5da81"},
+ {file = "secp256k1-0.14.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a8dbd75a9fb6f42de307f3c5e24573fe59c3374637cbf39136edc66c200a4029"},
+ {file = "secp256k1-0.14.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:97a30c8dae633cb18135c76b6517ae99dc59106818e8985be70dbc05dcc06c0d"},
+ {file = "secp256k1-0.14.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f4062d8c101aa63b9ecb3709f1f075ad9c01b6672869bbaa1bd77271816936a7"},
+ {file = "secp256k1-0.14.0-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c9e7c024ff17e9b9d7c392bb2a917da231d6cb40ab119389ff1f51dca10339a4"},
+ {file = "secp256k1-0.14.0.tar.gz", hash = "sha256:82c06712d69ef945220c8b53c1a0d424c2ff6a1f64aee609030df79ad8383397"},
+]
+shortuuid = [
+ {file = "shortuuid-1.0.1-py3-none-any.whl", hash = "sha256:492c7402ff91beb1342a5898bd61ea953985bf24a41cd9f247409aa2e03c8f77"},
+ {file = "shortuuid-1.0.1.tar.gz", hash = "sha256:3c11d2007b915c43bee3e10625f068d8a349e04f0d81f08f5fa08507427ebf1f"},
+]
+six = [
+ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
+ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
+]
+sniffio = [
+ {file = "sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"},
+ {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"},
+]
+sqlalchemy = [
+ {file = "SQLAlchemy-1.3.23-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:fd3b96f8c705af8e938eaa99cbd8fd1450f632d38cad55e7367c33b263bf98ec"},
+ {file = "SQLAlchemy-1.3.23-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:29cccc9606750fe10c5d0e8bd847f17a97f3850b8682aef1f56f5d5e1a5a64b1"},
+ {file = "SQLAlchemy-1.3.23-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:927ce09e49bff3104459e1451ce82983b0a3062437a07d883a4c66f0b344c9b5"},
+ {file = "SQLAlchemy-1.3.23-cp27-cp27m-win32.whl", hash = "sha256:b4b0e44d586cd64b65b507fa116a3814a1a53d55dce4836d7c1a6eb2823ff8d1"},
+ {file = "SQLAlchemy-1.3.23-cp27-cp27m-win_amd64.whl", hash = "sha256:6b8b8c80c7f384f06825612dd078e4a31f0185e8f1f6b8c19e188ff246334205"},
+ {file = "SQLAlchemy-1.3.23-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:9e9c25522933e569e8b53ccc644dc993cab87e922fb7e142894653880fdd419d"},
+ {file = "SQLAlchemy-1.3.23-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:a0e306e9bb76fd93b29ae3a5155298e4c1b504c7cbc620c09c20858d32d16234"},
+ {file = "SQLAlchemy-1.3.23-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:6c9e6cc9237de5660bcddea63f332428bb83c8e2015c26777281f7ffbd2efb84"},
+ {file = "SQLAlchemy-1.3.23-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:94f667d86be82dd4cb17d08de0c3622e77ca865320e0b95eae6153faa7b4ecaf"},
+ {file = "SQLAlchemy-1.3.23-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:751934967f5336a3e26fc5993ccad1e4fee982029f9317eb6153bc0bc3d2d2da"},
+ {file = "SQLAlchemy-1.3.23-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:63677d0c08524af4c5893c18dbe42141de7178001360b3de0b86217502ed3601"},
+ {file = "SQLAlchemy-1.3.23-cp35-cp35m-win32.whl", hash = "sha256:ddfb511e76d016c3a160910642d57f4587dc542ce5ee823b0d415134790eeeb9"},
+ {file = "SQLAlchemy-1.3.23-cp35-cp35m-win_amd64.whl", hash = "sha256:040bdfc1d76a9074717a3f43455685f781c581f94472b010cd6c4754754e1862"},
+ {file = "SQLAlchemy-1.3.23-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:d1a85dfc5dee741bf49cb9b6b6b8d2725a268e4992507cf151cba26b17d97c37"},
+ {file = "SQLAlchemy-1.3.23-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:639940bbe1108ac667dcffc79925db2966826c270112e9159439ab6bb14f8d80"},
+ {file = "SQLAlchemy-1.3.23-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:e8a1750b44ad6422ace82bf3466638f1aa0862dbb9689690d5f2f48cce3476c8"},
+ {file = "SQLAlchemy-1.3.23-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:e5bb3463df697279e5459a7316ad5a60b04b0107f9392e88674d0ece70e9cf70"},
+ {file = "SQLAlchemy-1.3.23-cp36-cp36m-win32.whl", hash = "sha256:e273367f4076bd7b9a8dc2e771978ef2bfd6b82526e80775a7db52bff8ca01dd"},
+ {file = "SQLAlchemy-1.3.23-cp36-cp36m-win_amd64.whl", hash = "sha256:ac2244e64485c3778f012951fdc869969a736cd61375fde6096d08850d8be729"},
+ {file = "SQLAlchemy-1.3.23-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:23927c3981d1ec6b4ea71eb99d28424b874d9c696a21e5fbd9fa322718be3708"},
+ {file = "SQLAlchemy-1.3.23-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d90010304abb4102123d10cbad2cdf2c25a9f2e66a50974199b24b468509bad5"},
+ {file = "SQLAlchemy-1.3.23-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:a8bfc1e1afe523e94974132d7230b82ca7fa2511aedde1f537ec54db0399541a"},
+ {file = "SQLAlchemy-1.3.23-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:269990b3ab53cb035d662dcde51df0943c1417bdab707dc4a7e4114a710504b4"},
+ {file = "SQLAlchemy-1.3.23-cp37-cp37m-win32.whl", hash = "sha256:fdd2ed7395df8ac2dbb10cefc44737b66c6a5cd7755c92524733d7a443e5b7e2"},
+ {file = "SQLAlchemy-1.3.23-cp37-cp37m-win_amd64.whl", hash = "sha256:6a939a868fdaa4b504e8b9d4a61f21aac11e3fecc8a8214455e144939e3d2aea"},
+ {file = "SQLAlchemy-1.3.23-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:24f9569e82a009a09ce2d263559acb3466eba2617203170e4a0af91e75b4f075"},
+ {file = "SQLAlchemy-1.3.23-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:2578dbdbe4dbb0e5126fb37ffcd9793a25dcad769a95f171a2161030bea850ff"},
+ {file = "SQLAlchemy-1.3.23-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:1fe5d8d39118c2b018c215c37b73fd6893c3e1d4895be745ca8ff6eb83333ed3"},
+ {file = "SQLAlchemy-1.3.23-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:c7dc052432cd5d060d7437e217dd33c97025287f99a69a50e2dc1478dd610d64"},
+ {file = "SQLAlchemy-1.3.23-cp38-cp38-win32.whl", hash = "sha256:ecce8c021894a77d89808222b1ff9687ad84db54d18e4bd0500ca766737faaf6"},
+ {file = "SQLAlchemy-1.3.23-cp38-cp38-win_amd64.whl", hash = "sha256:37b83bf81b4b85dda273aaaed5f35ea20ad80606f672d94d2218afc565fb0173"},
+ {file = "SQLAlchemy-1.3.23-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:8be835aac18ec85351385e17b8665bd4d63083a7160a017bef3d640e8e65cadb"},
+ {file = "SQLAlchemy-1.3.23-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:6ec1044908414013ebfe363450c22f14698803ce97fbb47e53284d55c5165848"},
+ {file = "SQLAlchemy-1.3.23-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:eab063a70cca4a587c28824e18be41d8ecc4457f8f15b2933584c6c6cccd30f0"},
+ {file = "SQLAlchemy-1.3.23-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:baeb451ee23e264de3f577fee5283c73d9bbaa8cb921d0305c0bbf700094b65b"},
+ {file = "SQLAlchemy-1.3.23-cp39-cp39-win32.whl", hash = "sha256:94208867f34e60f54a33a37f1c117251be91a47e3bfdb9ab8a7847f20886ad06"},
+ {file = "SQLAlchemy-1.3.23-cp39-cp39-win_amd64.whl", hash = "sha256:f4d972139d5000105fcda9539a76452039434013570d6059993120dc2a65e447"},
+ {file = "SQLAlchemy-1.3.23.tar.gz", hash = "sha256:6fca33672578666f657c131552c4ef8979c1606e494f78cd5199742dfb26918b"},
+]
+sqlalchemy-aio = [
+ {file = "sqlalchemy_aio-0.16.0-py2.py3-none-any.whl", hash = "sha256:f767320427c22c66fa5840a1f17f3261110a8ddc8560558f4fbf12d31a66b17b"},
+ {file = "sqlalchemy_aio-0.16.0.tar.gz", hash = "sha256:7f77366f55d34891c87386dd0962a28b948b684e8ea5edb7daae4187c0b291bf"},
+]
+sse-starlette = [
+ {file = "sse-starlette-0.6.2.tar.gz", hash = "sha256:1c0cc62cc7d021a386dc06a16a9ddc3e2861d19da6bc2e654e65cc111e820456"},
+]
+starlette = [
+ {file = "starlette-0.19.1-py3-none-any.whl", hash = "sha256:5a60c5c2d051f3a8eb546136aa0c9399773a689595e099e0877704d5888279bf"},
+ {file = "starlette-0.19.1.tar.gz", hash = "sha256:c6d21096774ecb9639acad41b86b7706e52ba3bf1dc13ea4ed9ad593d47e24c7"},
+]
+typing-extensions = [
+ {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"},
+ {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"},
+ {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"},
+]
+uvicorn = [
+ {file = "uvicorn-0.18.1-py3-none-any.whl", hash = "sha256:013c4ea0787cc2dc456ef4368e18c01982e6be57903e4d3183218e543eb889b7"},
+ {file = "uvicorn-0.18.1.tar.gz", hash = "sha256:35703e6518105cfe53f16a5a9435db3e2e227d0784f1fd8fbc1214b1fdc108df"},
+]
+uvloop = [
+ {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"},
+ {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30ba9dcbd0965f5c812b7c2112a1ddf60cf904c1c160f398e7eed3a6b82dcd9c"},
+ {file = "uvloop-0.16.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bd53f7f5db562f37cd64a3af5012df8cac2c464c97e732ed556800129505bd64"},
+ {file = "uvloop-0.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:772206116b9b57cd625c8a88f2413df2fcfd0b496eb188b82a43bed7af2c2ec9"},
+ {file = "uvloop-0.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b572256409f194521a9895aef274cea88731d14732343da3ecdb175228881638"},
+ {file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:04ff57aa137230d8cc968f03481176041ae789308b4d5079118331ab01112450"},
+ {file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a19828c4f15687675ea912cc28bbcb48e9bb907c801873bd1519b96b04fb805"},
+ {file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e814ac2c6f9daf4c36eb8e85266859f42174a4ff0d71b99405ed559257750382"},
+ {file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bd8f42ea1ea8f4e84d265769089964ddda95eb2bb38b5cbe26712b0616c3edee"},
+ {file = "uvloop-0.16.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:647e481940379eebd314c00440314c81ea547aa636056f554d491e40503c8464"},
+ {file = "uvloop-0.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e0d26fa5875d43ddbb0d9d79a447d2ace4180d9e3239788208527c4784f7cab"},
+ {file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6ccd57ae8db17d677e9e06192e9c9ec4bd2066b77790f9aa7dede2cc4008ee8f"},
+ {file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:089b4834fd299d82d83a25e3335372f12117a7d38525217c2258e9b9f4578897"},
+ {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98d117332cc9e5ea8dfdc2b28b0a23f60370d02e1395f88f40d1effd2cb86c4f"},
+ {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e5f2e2ff51aefe6c19ee98af12b4ae61f5be456cd24396953244a30880ad861"},
+ {file = "uvloop-0.16.0.tar.gz", hash = "sha256:f74bc20c7b67d1c27c72601c78cf95be99d5c2cdd4514502b4f3eb0933ff1228"},
+]
+watchgod = [
+ {file = "watchgod-0.7-py3-none-any.whl", hash = "sha256:d6c1ea21df37847ac0537ca0d6c2f4cdf513562e95f77bb93abbcf05573407b7"},
+ {file = "watchgod-0.7.tar.gz", hash = "sha256:48140d62b0ebe9dd9cf8381337f06351e1f2e70b2203fa9c6eff4e572ca84f29"},
+]
+websockets = [
+ {file = "websockets-10.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cd8c6f2ec24aedace251017bc7a414525171d4e6578f914acab9349362def4da"},
+ {file = "websockets-10.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1f6b814cff6aadc4288297cb3a248614829c6e4ff5556593c44a115e9dd49939"},
+ {file = "websockets-10.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:01db0ecd1a0ca6702d02a5ed40413e18b7d22f94afb3bbe0d323bac86c42c1c8"},
+ {file = "websockets-10.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:82b17524b1ce6ae7f7dd93e4d18e9b9474071e28b65dbf1dfe9b5767778db379"},
+ {file = "websockets-10.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:8bbf8660c3f833ddc8b1afab90213f2e672a9ddac6eecb3cde968e6b2807c1c7"},
+ {file = "websockets-10.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b8176deb6be540a46695960a765a77c28ac8b2e3ef2ec95d50a4f5df901edb1c"},
+ {file = "websockets-10.0-cp37-cp37m-win32.whl", hash = "sha256:706e200fc7f03bed99ad0574cd1ea8b0951477dd18cc978ccb190683c69dba76"},
+ {file = "websockets-10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5b2600e01c7ca6f840c42c747ffbe0254f319594ed108db847eb3d75f4aacb80"},
+ {file = "websockets-10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:085bb8a6e780d30eaa1ba48ac7f3a6707f925edea787cfb761ce5a39e77ac09b"},
+ {file = "websockets-10.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:9a4d889162bd48588e80950e07fa5e039eee9deb76a58092e8c3ece96d7ef537"},
+ {file = "websockets-10.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b4ade7569b6fd17912452f9c3757d96f8e4044016b6d22b3b8391e641ca50456"},
+ {file = "websockets-10.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:2a43072e434c041a99f2e1eb9b692df0232a38c37c61d00e9f24db79474329e4"},
+ {file = "websockets-10.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:7f79f02c7f9a8320aff7d3321cd1c7e3a7dbc15d922ac996cca827301ee75238"},
+ {file = "websockets-10.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:1ac35426fe3e7d3d0fac3d63c8965c76ed67a8fd713937be072bf0ce22808539"},
+ {file = "websockets-10.0-cp38-cp38-win32.whl", hash = "sha256:ff59c6bdb87b31f7e2d596f09353d5a38c8c8ff571b0e2238e8ee2d55ad68465"},
+ {file = "websockets-10.0-cp38-cp38-win_amd64.whl", hash = "sha256:d67646ddd17a86117ae21c27005d83c1895c0cef5d7be548b7549646372f868a"},
+ {file = "websockets-10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:82bd921885231f4a30d9bc550552495b3fc36b1235add6d374e7c65c3babd805"},
+ {file = "websockets-10.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:7d2e12e4f901f1bc062dfdf91831712c4106ed18a9a4cdb65e2e5f502124ca37"},
+ {file = "websockets-10.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:71358c7816e2762f3e4af3adf0040f268e219f5a38cb3487a9d0fc2e554fef6a"},
+ {file = "websockets-10.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:fe83b3ec9ef34063d86dfe1029160a85f24a5a94271036e5714a57acfdd089a1"},
+ {file = "websockets-10.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:eb282127e9c136f860c6068a4fba5756eb25e755baffb5940b6f1eae071928b2"},
+ {file = "websockets-10.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:62160772314920397f9d219147f958b33fa27a12c662d4455c9ccbba9a07e474"},
+ {file = "websockets-10.0-cp39-cp39-win32.whl", hash = "sha256:e42a1f1e03437b017af341e9bbfdc09252cd48ef32a8c3c3ead769eab3b17368"},
+ {file = "websockets-10.0-cp39-cp39-win_amd64.whl", hash = "sha256:c5880442f5fc268f1ef6d37b2c152c114deccca73f48e3a8c48004d2f16f4567"},
+ {file = "websockets-10.0.tar.gz", hash = "sha256:c4fc9a1d242317892590abe5b61a9127f1a61740477bfb121743f290b8054002"},
+]
+win32-setctime = []
+zipp = [
+ {file = "zipp-3.5.0-py3-none-any.whl", hash = "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3"},
+ {file = "zipp-3.5.0.tar.gz", hash = "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"},
+]
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 00000000..5c4bc7a0
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,70 @@
+[tool.poetry]
+name = "lnbits"
+version = "0.1.0"
+description = ""
+authors = ["matthewcroughan "]
+
+[tool.poetry.build]
+generate-setup-file = false
+script = "build.py"
+
+[tool.poetry.dependencies]
+python = "^3.9"
+aiofiles = "0.7.0"
+asgiref = "3.4.1"
+attrs = "21.2.0"
+bech32 = "1.2.0"
+bitstring = "3.1.9"
+cerberus = "1.3.4"
+certifi = "2021.5.30"
+charset-normalizer = "2.0.6"
+click = "8.0.1"
+ecdsa = "0.17.0"
+embit = "0.4.9"
+environs = "9.3.3"
+fastapi = "0.78.0"
+h11 = "0.12.0"
+httpcore = "0.13.7"
+httptools = "0.2.0"
+httpx = "0.19.0"
+idna = "3.2"
+importlib-metadata = "4.8.1"
+jinja2 = "3.0.1"
+lnurl = "0.3.6"
+markupsafe = "2.0.1"
+marshmallow = "3.13.0"
+outcome = "1.1.0"
+psycopg2-binary = "2.9.1"
+pycryptodomex = "3.14.1"
+pydantic = "1.8.2"
+pypng = "0.0.21"
+pyqrcode = "1.2.1"
+pyscss = "1.3.7"
+python-dotenv = "0.19.0"
+pyyaml = "5.4.1"
+represent = "1.6.0.post0"
+rfc3986 = "1.5.0"
+secp256k1 = "0.14.0"
+shortuuid = "1.0.1"
+six = "1.16.0"
+sniffio = "1.2.0"
+sqlalchemy = "1.3.23"
+sqlalchemy-aio = "0.16.0"
+sse-starlette = "0.6.2"
+typing-extensions = "3.10.0.2"
+uvicorn = "0.18.1"
+uvloop = "0.16.0"
+watchgod = "0.7"
+websockets = "10.0"
+zipp = "3.5.0"
+loguru = "0.5.3"
+cffi = "1.15.0"
+
+[tool.poetry.dev-dependencies]
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
+
+[tool.poetry.scripts]
+lnbits = "lnbits.server:main"
From 49bd5ad26bffa5f4cce8ce6a9f2bbeb4e874140d Mon Sep 17 00:00:00 2001
From: matthewcroughan
Date: Fri, 8 Jul 2022 09:24:54 +0100
Subject: [PATCH 03/18] lnbits/server.py: init
This adds a wrapper around uvicorn using Python. This is so the
entrypoint lnbits.server can be called on the command line, and passed
arguments like port and host. This makes lnbits feel more like a real
CLI application, and lends well to running as a service in systemd
---
lnbits/server.py | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 lnbits/server.py
diff --git a/lnbits/server.py b/lnbits/server.py
new file mode 100644
index 00000000..c0efb895
--- /dev/null
+++ b/lnbits/server.py
@@ -0,0 +1,17 @@
+import uvicorn
+
+import click
+
+@click.command()
+@click.option('--port', default="5000", help='Port to run LNBits on')
+@click.option('--host', default="127.0.0.1", help='Host to run LNBits on')
+def main(port, host):
+ """Launched with `poetry run lnbits` at root level"""
+ uvicorn.run("lnbits.__main__:app", port=port, host=host)
+
+if __name__ == '__main__':
+ main()
+
+#def main():
+# """Launched with `poetry run start` at root level"""
+# uvicorn.run("lnbits.__main__:app")
From 36e92765d3e76bc50543c6a96829f09cbb4c5b2e Mon Sep 17 00:00:00 2001
From: matthewcroughan
Date: Fri, 8 Jul 2022 09:49:38 +0100
Subject: [PATCH 04/18] treewide: use StaticFiles() rather than rel path
This commit is not exhaustive, and it is a trend in this codebase to not
use StaticFiles() and instead use relative paths. This means the code
cannot run anywhere other than the source code directory, as it will not
find the files it is looking for
---
lnbits/__main__.py | 4 +---
lnbits/app.py | 4 ++--
lnbits/extensions/bleskomat/__init__.py | 4 ++--
lnbits/extensions/copilot/__init__.py | 4 ++--
lnbits/extensions/discordbot/__init__.py | 4 ++--
lnbits/extensions/jukebox/__init__.py | 4 ++--
lnbits/extensions/livestream/__init__.py | 4 ++--
lnbits/extensions/lnurlp/__init__.py | 4 ++--
lnbits/extensions/offlineshop/__init__.py | 4 ++--
lnbits/extensions/splitpayments/__init__.py | 4 ++--
lnbits/extensions/withdraw/__init__.py | 4 ++--
11 files changed, 21 insertions(+), 23 deletions(-)
diff --git a/lnbits/__main__.py b/lnbits/__main__.py
index 93e2181c..aa652899 100644
--- a/lnbits/__main__.py
+++ b/lnbits/__main__.py
@@ -5,7 +5,7 @@ from starlette.requests import Request
from loguru import logger
-from .commands import bundle_vendored, migrate_databases, transpile_scss
+from .commands import migrate_databases
from .settings import (
DEBUG,
LNBITS_COMMIT,
@@ -21,8 +21,6 @@ from .settings import (
uvloop.install()
asyncio.create_task(migrate_databases())
-transpile_scss()
-bundle_vendored()
from .app import create_app
diff --git a/lnbits/app.py b/lnbits/app.py
index 9ab7c75d..84df250f 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -47,9 +47,9 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
configure_logger()
app = FastAPI()
- app.mount("/static", StaticFiles(directory="lnbits/static"), name="static")
+ app.mount("/static", StaticFiles(packages=[("lnbits", "static")]), name="static")
app.mount(
- "/core/static", StaticFiles(directory="lnbits/core/static"), name="core_static"
+ "/core/static", StaticFiles(packages=[("lnbits.core", "static")]), name="core_static"
)
origins = ["*"]
diff --git a/lnbits/extensions/bleskomat/__init__.py b/lnbits/extensions/bleskomat/__init__.py
index cc89760e..06b4a441 100644
--- a/lnbits/extensions/bleskomat/__init__.py
+++ b/lnbits/extensions/bleskomat/__init__.py
@@ -9,7 +9,7 @@ db = Database("ext_bleskomat")
bleskomat_static_files = [
{
"path": "/bleskomat/static",
- "app": StaticFiles(directory="lnbits/extensions/bleskomat/static"),
+ "app": StaticFiles(packages=[("lnbits", "extensions/bleskomat/static")]),
"name": "bleskomat_static",
}
]
@@ -18,7 +18,7 @@ bleskomat_ext: APIRouter = APIRouter(prefix="/bleskomat", tags=["Bleskomat"])
def bleskomat_renderer():
- return template_renderer(["lnbits/extensions/bleskomat/templates"])
+ return template_renderer([StaticFiles(packages=[("lnbits", "extensions/bleskomat/static/templates")])])
from .lnurl_api import * # noqa
diff --git a/lnbits/extensions/copilot/__init__.py b/lnbits/extensions/copilot/__init__.py
index 8a634267..8634505f 100644
--- a/lnbits/extensions/copilot/__init__.py
+++ b/lnbits/extensions/copilot/__init__.py
@@ -12,7 +12,7 @@ db = Database("ext_copilot")
copilot_static_files = [
{
"path": "/copilot/static",
- "app": StaticFiles(directory="lnbits/extensions/copilot/static"),
+ "app": StaticFiles(packages=[("lnbits", "extensions/copilot/static")]),
"name": "copilot_static",
}
]
@@ -20,7 +20,7 @@ copilot_ext: APIRouter = APIRouter(prefix="/copilot", tags=["copilot"])
def copilot_renderer():
- return template_renderer(["lnbits/extensions/copilot/templates"])
+ return template_renderer([StaticFiles(packages=[("lnbits", "extensions/copilot/static/templates")])])
from .lnurl import * # noqa
diff --git a/lnbits/extensions/discordbot/__init__.py b/lnbits/extensions/discordbot/__init__.py
index ff60dd62..eb755bd1 100644
--- a/lnbits/extensions/discordbot/__init__.py
+++ b/lnbits/extensions/discordbot/__init__.py
@@ -9,7 +9,7 @@ db = Database("ext_discordbot")
discordbot_static_files = [
{
"path": "/discordbot/static",
- "app": StaticFiles(directory="lnbits/extensions/discordbot/static"),
+ "app": StaticFiles(packages=[("lnbits", "extensions/discordbot/static")]),
"name": "discordbot_static",
}
]
@@ -18,7 +18,7 @@ discordbot_ext: APIRouter = APIRouter(prefix="/discordbot", tags=["discordbot"])
def discordbot_renderer():
- return template_renderer(["lnbits/extensions/discordbot/templates"])
+ return template_renderer([StaticFiles(packages=[("lnbits", "extensions/discordbot/static/templates")])])
from .views import * # noqa
diff --git a/lnbits/extensions/jukebox/__init__.py b/lnbits/extensions/jukebox/__init__.py
index 702a6c67..ee92ec6a 100644
--- a/lnbits/extensions/jukebox/__init__.py
+++ b/lnbits/extensions/jukebox/__init__.py
@@ -12,7 +12,7 @@ db = Database("ext_jukebox")
jukebox_static_files = [
{
"path": "/jukebox/static",
- "app": StaticFiles(directory="lnbits/extensions/jukebox/static"),
+ "app": StaticFiles(packages=[("lnbits", "extensions/jukebox/static")]),
"name": "jukebox_static",
}
]
@@ -21,7 +21,7 @@ jukebox_ext: APIRouter = APIRouter(prefix="/jukebox", tags=["jukebox"])
def jukebox_renderer():
- return template_renderer(["lnbits/extensions/jukebox/templates"])
+ return template_renderer([StaticFiles(packages=[("lnbits", "extensions/jukebox/static/templates")])])
from .tasks import wait_for_paid_invoices
diff --git a/lnbits/extensions/livestream/__init__.py b/lnbits/extensions/livestream/__init__.py
index 17fc2d3b..fbfcf22a 100644
--- a/lnbits/extensions/livestream/__init__.py
+++ b/lnbits/extensions/livestream/__init__.py
@@ -12,7 +12,7 @@ db = Database("ext_livestream")
livestream_static_files = [
{
"path": "/livestream/static",
- "app": StaticFiles(directory="lnbits/extensions/livestream/static"),
+ "app": StaticFiles(packages=[("lnbits", "extensions/livestream/static")]),
"name": "livestream_static",
}
]
@@ -21,7 +21,7 @@ livestream_ext: APIRouter = APIRouter(prefix="/livestream", tags=["livestream"])
def livestream_renderer():
- return template_renderer(["lnbits/extensions/livestream/templates"])
+ return template_renderer([StaticFiles(packages=[("lnbits", "extensions/livestream/static/templates")])])
from .lnurl import * # noqa
diff --git a/lnbits/extensions/lnurlp/__init__.py b/lnbits/extensions/lnurlp/__init__.py
index 40981748..02dbf2ce 100644
--- a/lnbits/extensions/lnurlp/__init__.py
+++ b/lnbits/extensions/lnurlp/__init__.py
@@ -12,7 +12,7 @@ db = Database("ext_lnurlp")
lnurlp_static_files = [
{
"path": "/lnurlp/static",
- "app": StaticFiles(directory="lnbits/extensions/lnurlp/static"),
+ "app": StaticFiles(packages=[("lnbits", "extensions/lnurlp/static")]),
"name": "lnurlp_static",
}
]
@@ -21,7 +21,7 @@ lnurlp_ext: APIRouter = APIRouter(prefix="/lnurlp", tags=["lnurlp"])
def lnurlp_renderer():
- return template_renderer(["lnbits/extensions/lnurlp/templates"])
+ return template_renderer([StaticFiles(packages=[("lnbits", "extensions/lnurlp/static/templates")])])
from .lnurl import * # noqa
diff --git a/lnbits/extensions/offlineshop/__init__.py b/lnbits/extensions/offlineshop/__init__.py
index a601c1b8..bacbf339 100644
--- a/lnbits/extensions/offlineshop/__init__.py
+++ b/lnbits/extensions/offlineshop/__init__.py
@@ -9,7 +9,7 @@ db = Database("ext_offlineshop")
offlineshop_static_files = [
{
"path": "/offlineshop/static",
- "app": StaticFiles(directory="lnbits/extensions/offlineshop/static"),
+ "app": StaticFiles(packages=[("lnbits", "extensions/offlineshop/static")]),
"name": "offlineshop_static",
}
]
@@ -18,7 +18,7 @@ offlineshop_ext: APIRouter = APIRouter(prefix="/offlineshop", tags=["Offlineshop
def offlineshop_renderer():
- return template_renderer(["lnbits/extensions/offlineshop/templates"])
+ return template_renderer([StaticFiles(packages=[("lnbits", "extensions/offlineshop/static/templates")])])
from .lnurl import * # noqa
diff --git a/lnbits/extensions/splitpayments/__init__.py b/lnbits/extensions/splitpayments/__init__.py
index df6feb94..3edac442 100644
--- a/lnbits/extensions/splitpayments/__init__.py
+++ b/lnbits/extensions/splitpayments/__init__.py
@@ -12,7 +12,7 @@ db = Database("ext_splitpayments")
splitpayments_static_files = [
{
"path": "/splitpayments/static",
- "app": StaticFiles(directory="lnbits/extensions/splitpayments/static"),
+ "app": StaticFiles(packages=[("lnbits", "extensions/splitpayments/static")]),
"name": "splitpayments_static",
}
]
@@ -22,7 +22,7 @@ splitpayments_ext: APIRouter = APIRouter(
def splitpayments_renderer():
- return template_renderer(["lnbits/extensions/splitpayments/templates"])
+ return template_renderer([StaticFiles(packages=[("lnbits", "extensions/splitpayments/static/templates")])])
from .tasks import wait_for_paid_invoices
diff --git a/lnbits/extensions/withdraw/__init__.py b/lnbits/extensions/withdraw/__init__.py
index 58ccfe7e..187ee7c0 100644
--- a/lnbits/extensions/withdraw/__init__.py
+++ b/lnbits/extensions/withdraw/__init__.py
@@ -9,7 +9,7 @@ db = Database("ext_withdraw")
withdraw_static_files = [
{
"path": "/withdraw/static",
- "app": StaticFiles(directory="lnbits/extensions/withdraw/static"),
+ "app": StaticFiles(packages=[("lnbits", "extensions/withdraw/static")]),
"name": "withdraw_static",
}
]
@@ -19,7 +19,7 @@ withdraw_ext: APIRouter = APIRouter(prefix="/withdraw", tags=["withdraw"])
def withdraw_renderer():
- return template_renderer(["lnbits/extensions/withdraw/templates"])
+ return template_renderer([StaticFiles(packages=[("lnbits", "extensions/withdraw/static/templates")])])
from .lnurl import * # noqa
From 6aa8330dc331c94fdfb2f8427948c0daa4abac61 Mon Sep 17 00:00:00 2001
From: matthewcroughan
Date: Fri, 8 Jul 2022 09:51:21 +0100
Subject: [PATCH 05/18] Start using Nix as a reproducible build tool
---
flake.lock | 77 +++++++++++++++++++++
flake.nix | 55 +++++++++++++++
nix/modules/lnbits-service.nix | 106 +++++++++++++++++++++++++++++
nix/tests/default.nix | 4 ++
nix/tests/nixos-module/default.nix | 25 +++++++
5 files changed, 267 insertions(+)
create mode 100644 flake.lock
create mode 100644 flake.nix
create mode 100644 nix/modules/lnbits-service.nix
create mode 100644 nix/tests/default.nix
create mode 100644 nix/tests/nixos-module/default.nix
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 00000000..0ca2db01
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,77 @@
+{
+ "nodes": {
+ "flake-utils": {
+ "locked": {
+ "lastModified": 1656928814,
+ "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=",
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "type": "github"
+ }
+ },
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1657114324,
+ "narHash": "sha256-fWuaUNXrHcz/ciHRHlcSO92dvV3EVS0GJQUSBO5JIB4=",
+ "owner": "nixos",
+ "repo": "nixpkgs",
+ "rev": "a5c867d9fe9e4380452628e8f171c26b69fa9d3d",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nixos",
+ "ref": "nixos-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs_2": {
+ "locked": {
+ "lastModified": 1657261001,
+ "narHash": "sha256-sUZeuRYfhG59uD6xafM07bc7bAIkpcGq84Vj4B+cyms=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "0be91cefefde5701f8fa957904618a13e3bb51d8",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "poetry2nix": {
+ "inputs": {
+ "flake-utils": "flake-utils",
+ "nixpkgs": "nixpkgs_2"
+ },
+ "locked": {
+ "lastModified": 1657149754,
+ "narHash": "sha256-iSnZoqwNDDVoO175whSuvl4sS9lAb/2zZ3Sa4ywo970=",
+ "owner": "nix-community",
+ "repo": "poetry2nix",
+ "rev": "fc1930e011dea149db81863aac22fe701f36f1b5",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-community",
+ "repo": "poetry2nix",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "nixpkgs": "nixpkgs",
+ "poetry2nix": "poetry2nix"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 00000000..77522866
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,55 @@
+{
+ inputs = {
+ nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
+ poetry2nix.url = "github:nix-community/poetry2nix";
+ };
+ outputs = { self, nixpkgs, poetry2nix }@inputs:
+ let
+ supportedSystems = [ "x86_64-linux" "aarch64-linux" ];
+ forSystems = systems: f:
+ nixpkgs.lib.genAttrs systems
+ (system: f system (import nixpkgs { inherit system; overlays = [ poetry2nix.overlay self.overlays.default ]; }));
+ forAllSystems = forSystems supportedSystems;
+ projectName = "lnbits";
+ in
+ {
+ devShells = forAllSystems (system: pkgs: {
+ default = pkgs.mkShell {
+ buildInputs = with pkgs; [
+ nodePackages.prettier
+ ];
+ };
+ });
+ overlays = {
+ default = final: prev: {
+ ${projectName} = self.packages.${final.hostPlatform.system}.${projectName};
+ };
+ };
+ packages = forAllSystems (system: pkgs: {
+ default = self.packages.${system}.${projectName};
+ ${projectName} = pkgs.poetry2nix.mkPoetryApplication {
+ projectDir = ./.;
+ python = pkgs.python39;
+ };
+ });
+ nixosModules = forAllSystems (system: pkgs: {
+ default = { pkgs, lib, config, ... }: {
+ imports = [ "${./nix/modules/${projectName}-service.nix}" ];
+ nixpkgs.overlays = [ self.overlays.default ];
+ };
+ });
+ checks = forAllSystems (system: pkgs:
+ let
+ vmTests = import ./nix/tests {
+ makeTest = (import (nixpkgs + "/nixos/lib/testing-python.nix") { inherit system; }).makeTest;
+ inherit inputs pkgs;
+ };
+ in
+ pkgs.lib.optionalAttrs pkgs.stdenv.isLinux vmTests # vmTests can only be ran on Linux, so append them only if on Linux.
+ //
+ {
+ # Other checks here...
+ }
+ );
+ };
+}
diff --git a/nix/modules/lnbits-service.nix b/nix/modules/lnbits-service.nix
new file mode 100644
index 00000000..5d8e0640
--- /dev/null
+++ b/nix/modules/lnbits-service.nix
@@ -0,0 +1,106 @@
+{ config, pkgs, lib, ... }:
+
+let
+ defaultUser = "lnbits";
+ cfg = config.services.lnbits;
+ inherit (lib) mkOption mkIf types optionalAttrs;
+in
+
+{
+ options = {
+ services.lnbits = {
+ enable = mkOption {
+ default = false;
+ type = types.bool;
+ description = ''
+ Whether to enable the lnbits service
+ '';
+ };
+ openFirewall = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to open the ports used by lnbits in the firewall for the server
+ '';
+ };
+ package = mkOption {
+ type = types.package;
+ default = pkgs.lnbits;
+ description = ''
+ The lnbits package to use.
+ '';
+ };
+ stateDir = mkOption {
+ type = types.path;
+ default = "/var/lib/lnbits";
+ description = ''
+ The lnbits state directory which LNBITS_DATA_FOLDER will be set to
+ '';
+ };
+ host = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = ''
+ The host to bind to
+ '';
+ };
+ port = mkOption {
+ type = types.port;
+ default = 8231;
+ description = ''
+ The port to run on
+ '';
+ };
+ user = mkOption {
+ type = types.str;
+ default = "lnbits";
+ description = "user to run lnbits as";
+ };
+ group = mkOption {
+ type = types.str;
+ default = "lnbits";
+ description = "group to run lnbits as";
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ users.users = optionalAttrs (cfg.user == defaultUser) {
+ ${defaultUser} = {
+ isSystemUser = true;
+ group = defaultUser;
+ };
+ };
+
+ users.groups = optionalAttrs (cfg.group == defaultUser) {
+ ${defaultUser} = { };
+ };
+
+ systemd.tmpfiles.rules = [
+ "d ${cfg.stateDir} 0700 ${cfg.user} ${cfg.group} - -"
+ ];
+
+ systemd.services.lnbits = {
+ enable = true;
+ description = "lnbits";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network-online.target" ];
+ environment = {
+ LNBITS_DATA_FOLDER = "${cfg.stateDir}";
+ };
+ serviceConfig = {
+ User = cfg.user;
+ Group = cfg.group;
+ WorkingDirectory = "${cfg.package.src}";
+ StateDirectory = "${cfg.stateDir}";
+ ExecStart = "${lib.getExe cfg.package} --port ${toString cfg.port} --host ${cfg.host}";
+ Restart = "always";
+ PrivateTmp = true;
+ };
+ };
+ networking.firewall = mkIf cfg.openFirewall {
+ allowedTCPPorts = [ cfg.port ];
+ };
+ };
+}
+
diff --git a/nix/tests/default.nix b/nix/tests/default.nix
new file mode 100644
index 00000000..7b8513ac
--- /dev/null
+++ b/nix/tests/default.nix
@@ -0,0 +1,4 @@
+{ pkgs, makeTest, inputs }:
+{
+ vmTest = import ./nixos-module { inherit pkgs makeTest inputs; };
+}
diff --git a/nix/tests/nixos-module/default.nix b/nix/tests/nixos-module/default.nix
new file mode 100644
index 00000000..5649ae59
--- /dev/null
+++ b/nix/tests/nixos-module/default.nix
@@ -0,0 +1,25 @@
+{ pkgs, makeTest, inputs }:
+makeTest {
+ nodes = {
+ client = { config, pkgs, ... }: {
+ environment.systemPackages = [ pkgs.curl ];
+ };
+ lnbits = { ... }: {
+ imports = [ inputs.self.nixosModules.${pkgs.hostPlatform.system}.default ];
+ services.lnbits = {
+ enable = true;
+ openFirewall = true;
+ host = "0.0.0.0";
+ };
+ };
+ };
+ testScript = { nodes, ... }: ''
+ start_all()
+ lnbits.wait_for_open_port(${toString nodes.lnbits.config.services.lnbits.port})
+ client.wait_for_unit("multi-user.target")
+ with subtest("Check that the lnbits webserver can be reached."):
+ assert "LNbits" in client.succeed(
+ "curl -sSf http:/lnbits:8231/ | grep title"
+ )
+ '';
+}
From 984f06239f0fed969a25be903cf35be4d788dd1d Mon Sep 17 00:00:00 2001
From: matthewcroughan
Date: Thu, 14 Jul 2022 05:27:38 +0100
Subject: [PATCH 06/18] nix: remove forAllSystems from nixosModule
This causes lnbits.nixosModules.default to exist, rather than
lnbits.nixosModules.aarch64-linux.default. The latter was a mistake.
---
flake.nix | 4 ++--
nix/tests/nixos-module/default.nix | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/flake.nix b/flake.nix
index 77522866..af25ba5c 100644
--- a/flake.nix
+++ b/flake.nix
@@ -32,12 +32,12 @@
python = pkgs.python39;
};
});
- nixosModules = forAllSystems (system: pkgs: {
+ nixosModules = {
default = { pkgs, lib, config, ... }: {
imports = [ "${./nix/modules/${projectName}-service.nix}" ];
nixpkgs.overlays = [ self.overlays.default ];
};
- });
+ };
checks = forAllSystems (system: pkgs:
let
vmTests = import ./nix/tests {
diff --git a/nix/tests/nixos-module/default.nix b/nix/tests/nixos-module/default.nix
index 5649ae59..86857912 100644
--- a/nix/tests/nixos-module/default.nix
+++ b/nix/tests/nixos-module/default.nix
@@ -5,7 +5,7 @@ makeTest {
environment.systemPackages = [ pkgs.curl ];
};
lnbits = { ... }: {
- imports = [ inputs.self.nixosModules.${pkgs.hostPlatform.system}.default ];
+ imports = [ inputs.self.nixosModules.default ];
services.lnbits = {
enable = true;
openFirewall = true;
From 0e8da3c368389c369a0723bec9edf520d2fdd130 Mon Sep 17 00:00:00 2001
From: ben
Date: Sat, 23 Jul 2022 20:08:59 +0100
Subject: [PATCH 07/18] Fixed path for extension templates
---
lnbits/extensions/bleskomat/__init__.py | 2 +-
lnbits/extensions/copilot/__init__.py | 2 +-
lnbits/extensions/discordbot/__init__.py | 2 +-
lnbits/extensions/jukebox/__init__.py | 2 +-
lnbits/extensions/livestream/__init__.py | 2 +-
lnbits/extensions/lnurlp/__init__.py | 2 +-
lnbits/extensions/offlineshop/__init__.py | 3 ++-
lnbits/extensions/splitpayments/__init__.py | 2 +-
lnbits/extensions/withdraw/__init__.py | 2 +-
9 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/lnbits/extensions/bleskomat/__init__.py b/lnbits/extensions/bleskomat/__init__.py
index 06b4a441..bef362dc 100644
--- a/lnbits/extensions/bleskomat/__init__.py
+++ b/lnbits/extensions/bleskomat/__init__.py
@@ -18,7 +18,7 @@ bleskomat_ext: APIRouter = APIRouter(prefix="/bleskomat", tags=["Bleskomat"])
def bleskomat_renderer():
- return template_renderer([StaticFiles(packages=[("lnbits", "extensions/bleskomat/static/templates")])])
+ return template_renderer(["lnbits/extensions/bleskomat/templates"])
from .lnurl_api import * # noqa
diff --git a/lnbits/extensions/copilot/__init__.py b/lnbits/extensions/copilot/__init__.py
index 8634505f..806801ce 100644
--- a/lnbits/extensions/copilot/__init__.py
+++ b/lnbits/extensions/copilot/__init__.py
@@ -20,7 +20,7 @@ copilot_ext: APIRouter = APIRouter(prefix="/copilot", tags=["copilot"])
def copilot_renderer():
- return template_renderer([StaticFiles(packages=[("lnbits", "extensions/copilot/static/templates")])])
+ return template_renderer(["lnbits/extensions/copilot/templates"])
from .lnurl import * # noqa
diff --git a/lnbits/extensions/discordbot/__init__.py b/lnbits/extensions/discordbot/__init__.py
index eb755bd1..21989b24 100644
--- a/lnbits/extensions/discordbot/__init__.py
+++ b/lnbits/extensions/discordbot/__init__.py
@@ -18,7 +18,7 @@ discordbot_ext: APIRouter = APIRouter(prefix="/discordbot", tags=["discordbot"])
def discordbot_renderer():
- return template_renderer([StaticFiles(packages=[("lnbits", "extensions/discordbot/static/templates")])])
+ return template_renderer(["lnbits/extensions/discordbot/templates"])
from .views import * # noqa
diff --git a/lnbits/extensions/jukebox/__init__.py b/lnbits/extensions/jukebox/__init__.py
index ee92ec6a..4559dccf 100644
--- a/lnbits/extensions/jukebox/__init__.py
+++ b/lnbits/extensions/jukebox/__init__.py
@@ -21,7 +21,7 @@ jukebox_ext: APIRouter = APIRouter(prefix="/jukebox", tags=["jukebox"])
def jukebox_renderer():
- return template_renderer([StaticFiles(packages=[("lnbits", "extensions/jukebox/static/templates")])])
+ return template_renderer(["lnbits/extensions/jukebox/templates"])
from .tasks import wait_for_paid_invoices
diff --git a/lnbits/extensions/livestream/__init__.py b/lnbits/extensions/livestream/__init__.py
index fbfcf22a..e5f2987c 100644
--- a/lnbits/extensions/livestream/__init__.py
+++ b/lnbits/extensions/livestream/__init__.py
@@ -21,7 +21,7 @@ livestream_ext: APIRouter = APIRouter(prefix="/livestream", tags=["livestream"])
def livestream_renderer():
- return template_renderer([StaticFiles(packages=[("lnbits", "extensions/livestream/static/templates")])])
+ return template_renderer(["lnbits/extensions/livestream/templates"])
from .lnurl import * # noqa
diff --git a/lnbits/extensions/lnurlp/__init__.py b/lnbits/extensions/lnurlp/__init__.py
index 02dbf2ce..e2486df0 100644
--- a/lnbits/extensions/lnurlp/__init__.py
+++ b/lnbits/extensions/lnurlp/__init__.py
@@ -21,7 +21,7 @@ lnurlp_ext: APIRouter = APIRouter(prefix="/lnurlp", tags=["lnurlp"])
def lnurlp_renderer():
- return template_renderer([StaticFiles(packages=[("lnbits", "extensions/lnurlp/static/templates")])])
+ return template_renderer(["lnbits/extensions/lnurlp/templates"])
from .lnurl import * # noqa
diff --git a/lnbits/extensions/offlineshop/__init__.py b/lnbits/extensions/offlineshop/__init__.py
index bacbf339..2dbaa7d0 100644
--- a/lnbits/extensions/offlineshop/__init__.py
+++ b/lnbits/extensions/offlineshop/__init__.py
@@ -18,7 +18,8 @@ offlineshop_ext: APIRouter = APIRouter(prefix="/offlineshop", tags=["Offlineshop
def offlineshop_renderer():
- return template_renderer([StaticFiles(packages=[("lnbits", "extensions/offlineshop/static/templates")])])
+ return template_renderer(["lnbits/extensions/offlineshop/templates"])
+
from .lnurl import * # noqa
diff --git a/lnbits/extensions/splitpayments/__init__.py b/lnbits/extensions/splitpayments/__init__.py
index 3edac442..9989728e 100644
--- a/lnbits/extensions/splitpayments/__init__.py
+++ b/lnbits/extensions/splitpayments/__init__.py
@@ -22,7 +22,7 @@ splitpayments_ext: APIRouter = APIRouter(
def splitpayments_renderer():
- return template_renderer([StaticFiles(packages=[("lnbits", "extensions/splitpayments/static/templates")])])
+ return template_renderer(["lnbits/extensions/splitpayments/templates"])
from .tasks import wait_for_paid_invoices
diff --git a/lnbits/extensions/withdraw/__init__.py b/lnbits/extensions/withdraw/__init__.py
index 187ee7c0..a0f4b606 100644
--- a/lnbits/extensions/withdraw/__init__.py
+++ b/lnbits/extensions/withdraw/__init__.py
@@ -19,7 +19,7 @@ withdraw_ext: APIRouter = APIRouter(prefix="/withdraw", tags=["withdraw"])
def withdraw_renderer():
- return template_renderer([StaticFiles(packages=[("lnbits", "extensions/withdraw/static/templates")])])
+ return template_renderer(["lnbits/extensions/withdraw/templates"])
from .lnurl import * # noqa
From 0c5cb8cb9ead067144cd60af05596429afac04bd Mon Sep 17 00:00:00 2001
From: calle <93376500+callebtc@users.noreply.github.com>
Date: Wed, 27 Jul 2022 15:29:44 +0200
Subject: [PATCH 08/18] Wallets: increase timeouts (#787)
* increase pay timeouts to infinite
---
lnbits/wallets/eclair.py | 2 +-
lnbits/wallets/lnbits.py | 2 +-
lnbits/wallets/lndrest.py | 2 +-
lnbits/wallets/lnpay.py | 2 +-
lnbits/wallets/lntxbot.py | 2 +-
lnbits/wallets/opennode.py | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/lnbits/wallets/eclair.py b/lnbits/wallets/eclair.py
index 0ac3fd2a..c878d0d1 100644
--- a/lnbits/wallets/eclair.py
+++ b/lnbits/wallets/eclair.py
@@ -97,7 +97,7 @@ class EclairWallet(Wallet):
f"{self.url}/payinvoice",
headers=self.auth,
data={"invoice": bolt11, "blocking": True},
- timeout=40,
+ timeout=None,
)
if "error" in r.json():
diff --git a/lnbits/wallets/lnbits.py b/lnbits/wallets/lnbits.py
index 55186196..d2ddb7ff 100644
--- a/lnbits/wallets/lnbits.py
+++ b/lnbits/wallets/lnbits.py
@@ -88,7 +88,7 @@ class LNbitsWallet(Wallet):
url=f"{self.endpoint}/api/v1/payments",
headers=self.key,
json={"out": True, "bolt11": bolt11},
- timeout=100,
+ timeout=None,
)
ok, checking_id, fee_msat, error_message = not r.is_error, None, 0, None
diff --git a/lnbits/wallets/lndrest.py b/lnbits/wallets/lndrest.py
index 56d18dc4..575db64d 100644
--- a/lnbits/wallets/lndrest.py
+++ b/lnbits/wallets/lndrest.py
@@ -111,7 +111,7 @@ class LndRestWallet(Wallet):
url=f"{self.endpoint}/v1/channels/transactions",
headers=self.auth,
json={"payment_request": bolt11, "fee_limit": lnrpcFeeLimit},
- timeout=180,
+ timeout=None,
)
if r.is_error or r.json().get("payment_error"):
diff --git a/lnbits/wallets/lnpay.py b/lnbits/wallets/lnpay.py
index 807d7253..7171ec3f 100644
--- a/lnbits/wallets/lnpay.py
+++ b/lnbits/wallets/lnpay.py
@@ -84,7 +84,7 @@ class LNPayWallet(Wallet):
f"{self.endpoint}/wallet/{self.wallet_key}/withdraw",
headers=self.auth,
json={"payment_request": bolt11},
- timeout=180,
+ timeout=None,
)
try:
diff --git a/lnbits/wallets/lntxbot.py b/lnbits/wallets/lntxbot.py
index 47a1f6c1..3c758e6c 100644
--- a/lnbits/wallets/lntxbot.py
+++ b/lnbits/wallets/lntxbot.py
@@ -82,7 +82,7 @@ class LntxbotWallet(Wallet):
f"{self.endpoint}/payinvoice",
headers=self.auth,
json={"invoice": bolt11},
- timeout=100,
+ timeout=None,
)
if "error" in r.json():
diff --git a/lnbits/wallets/opennode.py b/lnbits/wallets/opennode.py
index 6d3fb02c..d503b4dd 100644
--- a/lnbits/wallets/opennode.py
+++ b/lnbits/wallets/opennode.py
@@ -85,7 +85,7 @@ class OpenNodeWallet(Wallet):
f"{self.endpoint}/v2/withdrawals",
headers=self.auth,
json={"type": "ln", "address": bolt11},
- timeout=180,
+ timeout=None,
)
if r.is_error:
From 6e344561e391fa647882edc9f011f53c6c733ad1 Mon Sep 17 00:00:00 2001
From: ben
Date: Wed, 27 Jul 2022 14:49:13 +0100
Subject: [PATCH 09/18] Updated requirements
---
requirements.txt | 68 ++++++++++++++++++++++++------------------------
1 file changed, 34 insertions(+), 34 deletions(-)
diff --git a/requirements.txt b/requirements.txt
index f8ccf47c..23d428e5 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,52 +1,52 @@
-aiofiles==0.7.0
-anyio==3.3.1
-asgiref==3.4.1
+aiofiles==0.8.0
+anyio==3.6.1
asyncio==3.4.3
-attrs==21.2.0
+attrs==21.4.0
bech32==1.2.0
bitstring==3.1.9
cerberus==1.3.4
-certifi==2021.5.30
-charset-normalizer==2.0.6
-click==8.0.1
-ecdsa==0.17.0
-embit==0.4.9
-environs==9.3.3
-fastapi==0.68.1
+certifi==2022.6.15
+cffi==1.15.0
+click==8.1.3
+ecdsa==0.18.0
+embit==0.5.0
+environs==9.5.0
+fastapi==0.79.0
h11==0.12.0
httpcore==0.15.0
-httptools==0.2.0
+httptools==0.4.0
httpx==0.23.0
-idna==3.2
-importlib-metadata==4.8.1
+idna==3.3
jinja2==3.0.1
lnurl==0.3.6
loguru==0.6.0
-markupsafe==2.0.1
-marshmallow==3.13.0
-outcome==1.1.0
-psycopg2-binary==2.9.1
-pycryptodomex==3.14.1
-pydantic==1.8.2
-pypng==0.0.21
+markupsafe==2.1.1
+marshmallow==3.17.0
+outcome==1.2.0
+packaging==21.3
+psycopg2-binary==2.9.3
+pycparser==2.21
+pycryptodomex==3.15.0
+pydantic==1.9.1
+pyngrok==5.1.0
+pyparsing==3.0.9
+pypng==0.20220715.0
pyqrcode==1.2.1
-pyscss==1.3.7
-python-dotenv==0.19.0
-pyyaml==5.4.1
+pyscss==1.4.0
+python-dotenv==0.20.0
+pyyaml==6.0
represent==1.6.0.post0
rfc3986==1.5.0
secp256k1==0.14.0
-cffi==1.15.0
-shortuuid==1.0.1
+shortuuid==1.0.9
six==1.16.0
sniffio==1.2.0
+sqlalchemy-aio==0.17.0
sqlalchemy==1.3.23
-sqlalchemy-aio==0.16.0
-sse-starlette==0.6.2
-starlette==0.14.2
-typing-extensions==3.10.0.2
-uvicorn==0.15.0
+sse-starlette==0.10.3
+starlette==0.19.1
+typing-extensions==4.3.0
+uvicorn==0.18.2
uvloop==0.16.0
-watchgod==0.7
-websockets==10.0
-zipp==3.5.0
+watchfiles==0.16.0
+websockets==10.3
From ee1cc28187848aa2e3f833260005d9ab6a137537 Mon Sep 17 00:00:00 2001
From: Arc <33088785+arcbtc@users.noreply.github.com>
Date: Wed, 27 Jul 2022 15:01:23 +0100
Subject: [PATCH 10/18] Update installation.md
---
docs/guide/installation.md | 25 ++++++++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/docs/guide/installation.md b/docs/guide/installation.md
index 591516f1..380c756d 100644
--- a/docs/guide/installation.md
+++ b/docs/guide/installation.md
@@ -12,9 +12,28 @@ You can choose between two python package managers, `venv` and `pipenv`. Both ar
By default, LNbits will use SQLite as its database. You can also use PostgreSQL which is recommended for applications with a high load (see guide below).
-## Option 1: pipenv
+## Option 1: poetry
-You can also use Pipenv to manage your python packages.
+```sh
+git clone https://github.com/lnbits/lnbits-legend.git
+cd lnbits-legend/
+
+curl -sSL https://install.python-poetry.org | python3 -
+poetry install
+
+# You may need to install python 3.9, update your python following this guide https://linuxize.com/post/how-to-install-python-3-9-on-ubuntu-20-04/
+
+ mkdir data && cp .env.example .env
+```
+
+#### Running the server
+
+```sh
+poetry run lnbits
+# To change port/host pass 'poetry run lnbits --port 9000 --host 0.0.0.0'
+```
+
+## Option 2: pipenv
```sh
git clone https://github.com/lnbits/lnbits-legend.git
@@ -44,7 +63,7 @@ pipenv run python -m uvicorn lnbits.__main__:app --port 5000 --host 0.0.0.0
Add the flag `--reload` for development (includes hot-reload).
-## Option 2: venv
+## Option 3: venv
Download this repo and install the dependencies:
From 2b811ec1bbdf38ac321c0fef3d3c355ab33923b4 Mon Sep 17 00:00:00 2001
From: Arc <33088785+arcbtc@users.noreply.github.com>
Date: Wed, 27 Jul 2022 15:07:16 +0100
Subject: [PATCH 11/18] Update installation.md
---
docs/guide/installation.md | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/docs/guide/installation.md b/docs/guide/installation.md
index 380c756d..0b28f803 100644
--- a/docs/guide/installation.md
+++ b/docs/guide/installation.md
@@ -65,8 +65,6 @@ Add the flag `--reload` for development (includes hot-reload).
## Option 3: venv
-Download this repo and install the dependencies:
-
```sh
git clone https://github.com/lnbits/lnbits-legend.git
cd lnbits-legend/
@@ -86,6 +84,26 @@ mkdir data && cp .env.example .env
If you want to host LNbits on the internet, run with the option `--host 0.0.0.0`.
+## Option 4: Nix
+
+```sh
+git clone https://github.com/lnbits/lnbits-legend.git
+cd lnbits-legend/
+# Install nix, modern debian distros usually already include
+sh <(curl -L https://nixos.org/nix/install) --daemon
+
+nix build .#lnbits
+mkdir data
+
+```
+
+#### Running the server
+
+```sh
+# .env variables are currently passed when running
+LNBITS_DATA_FOLDER=data LNBITS_BACKEND_WALLET_CLASS=LNbitsWallet LNBITS_ENDPOINT=https://legend.lnbits.com LNBITS_KEY=7b1a78d6c78f48b09a202f2dcb2d22eb ./result/bin/lnbits --port 9000
+```
+
### Troubleshooting
Problems installing? These commands have helped us install LNbits.
From 8cac577f2f912abd829ad44809f598723bb4b862 Mon Sep 17 00:00:00 2001
From: Arc <33088785+arcbtc@users.noreply.github.com>
Date: Wed, 27 Jul 2022 15:09:41 +0100
Subject: [PATCH 12/18] Update installation.md
---
docs/guide/installation.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/guide/installation.md b/docs/guide/installation.md
index 0b28f803..f38f606d 100644
--- a/docs/guide/installation.md
+++ b/docs/guide/installation.md
@@ -8,7 +8,7 @@ nav_order: 2
# Basic installation
-You can choose between two python package managers, `venv` and `pipenv`. Both are fine but if you don't know what you're doing, just go for the first option.
+You can choose between four package managers, `poetry`, `pipenv`, `venv` and `nix`.
By default, LNbits will use SQLite as its database. You can also use PostgreSQL which is recommended for applications with a high load (see guide below).
From 41dc1b05125700f906920e352e77967c2c74791c Mon Sep 17 00:00:00 2001
From: Tiago Vasconcelos
Date: Wed, 27 Jul 2022 15:45:17 +0100
Subject: [PATCH 13/18] Fix/hotfix tpos 2 (#783)
* fix older tpos without tips
* bad math requesting invoice
* make format
---
lnbits/app.py | 4 +++-
lnbits/extensions/offlineshop/__init__.py | 1 -
lnbits/extensions/tpos/templates/tpos/tpos.html | 7 ++++---
lnbits/server.py | 11 ++++++-----
4 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 83a9749b..8e32e38b 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -48,7 +48,9 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
app = FastAPI()
app.mount("/static", StaticFiles(packages=[("lnbits", "static")]), name="static")
app.mount(
- "/core/static", StaticFiles(packages=[("lnbits.core", "static")]), name="core_static"
+ "/core/static",
+ StaticFiles(packages=[("lnbits.core", "static")]),
+ name="core_static",
)
origins = ["*"]
diff --git a/lnbits/extensions/offlineshop/__init__.py b/lnbits/extensions/offlineshop/__init__.py
index 2dbaa7d0..0b776a8c 100644
--- a/lnbits/extensions/offlineshop/__init__.py
+++ b/lnbits/extensions/offlineshop/__init__.py
@@ -21,7 +21,6 @@ def offlineshop_renderer():
return template_renderer(["lnbits/extensions/offlineshop/templates"])
-
from .lnurl import * # noqa
from .views import * # noqa
from .views_api import * # noqa
diff --git a/lnbits/extensions/tpos/templates/tpos/tpos.html b/lnbits/extensions/tpos/templates/tpos/tpos.html
index e11f6079..ebc6595e 100644
--- a/lnbits/extensions/tpos/templates/tpos/tpos.html
+++ b/lnbits/extensions/tpos/templates/tpos/tpos.html
@@ -308,7 +308,9 @@
},
sat: function () {
if (!this.exchangeRate) return 0
- return Math.ceil((this.amount / this.exchangeRate) * 100000000)
+ return Math.ceil(
+ ((this.amount - this.tipAmount) / this.exchangeRate) * 100000000
+ )
},
tipAmountSat: function () {
if (!this.exchangeRate) return 0
@@ -423,10 +425,9 @@
'{{ tpos.tip_options | tojson }}' == 'null'
? null
: JSON.parse('{{ tpos.tip_options }}')
- console.log(typeof this.tip_options, this.tip_options)
setInterval(function () {
getRates()
- }, 20000)
+ }, 120000)
}
})
diff --git a/lnbits/server.py b/lnbits/server.py
index c0efb895..4a63b3b7 100644
--- a/lnbits/server.py
+++ b/lnbits/server.py
@@ -1,17 +1,18 @@
+import click
import uvicorn
-import click
@click.command()
-@click.option('--port', default="5000", help='Port to run LNBits on')
-@click.option('--host', default="127.0.0.1", help='Host to run LNBits on')
+@click.option("--port", default="5000", help="Port to run LNBits on")
+@click.option("--host", default="127.0.0.1", help="Host to run LNBits on")
def main(port, host):
"""Launched with `poetry run lnbits` at root level"""
uvicorn.run("lnbits.__main__:app", port=port, host=host)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
main()
-#def main():
+# def main():
# """Launched with `poetry run start` at root level"""
# uvicorn.run("lnbits.__main__:app")
From 1c77d165e27921c58fa06cbf46d3d98fb6b62d50 Mon Sep 17 00:00:00 2001
From: ben
Date: Wed, 27 Jul 2022 17:32:03 +0100
Subject: [PATCH 14/18] Made reliable
Fixed issue scanning tickets by adding "ticket://" prefix
---
lnbits/extensions/events/crud.py | 2 +-
.../events/templates/events/display.html | 18 ++++-----
.../events/templates/events/register.html | 2 +-
.../events/templates/events/ticket.html | 5 +--
lnbits/extensions/events/views_api.py | 40 +++++++++----------
5 files changed, 32 insertions(+), 35 deletions(-)
diff --git a/lnbits/extensions/events/crud.py b/lnbits/extensions/events/crud.py
index 9e04476d..4cc86ac4 100644
--- a/lnbits/extensions/events/crud.py
+++ b/lnbits/extensions/events/crud.py
@@ -16,7 +16,7 @@ async def create_ticket(
INSERT INTO events.ticket (id, wallet, event, name, email, registered, paid)
VALUES (?, ?, ?, ?, ?, ?, ?)
""",
- (payment_hash, wallet, event, name, email, False, False),
+ (payment_hash, wallet, event, name, email, False, True),
)
ticket = await get_ticket(payment_hash)
diff --git a/lnbits/extensions/events/templates/events/display.html b/lnbits/extensions/events/templates/events/display.html
index 4c1f557f..7e62b7a7 100644
--- a/lnbits/extensions/events/templates/events/display.html
+++ b/lnbits/extensions/events/templates/events/display.html
@@ -135,14 +135,8 @@
var self = this
axios
- .post(
- '/events/api/v1/tickets/' + '{{ event_id }}/{{ event_price }}',
- {
- event: '{{ event_id }}',
- event_name: '{{ event_name }}',
- name: self.formDialog.data.name,
- email: self.formDialog.data.email
- }
+ .get(
+ '/events/api/v1/tickets/' + '{{ event_id }}'
)
.then(function (response) {
self.paymentReq = response.data.payment_request
@@ -161,7 +155,13 @@
paymentChecker = setInterval(function () {
axios
- .get('/events/api/v1/tickets/' + self.paymentCheck)
+ .post('/events/api/v1/tickets/' + '{{ event_id }}/' + self.paymentCheck,
+ {
+ event: '{{ event_id }}',
+ event_name: '{{ event_name }}',
+ name: self.formDialog.data.name,
+ email: self.formDialog.data.email
+ })
.then(function (res) {
if (res.data.paid) {
clearInterval(paymentChecker)
diff --git a/lnbits/extensions/events/templates/events/register.html b/lnbits/extensions/events/templates/events/register.html
index 4dff9afb..3913cc0c 100644
--- a/lnbits/extensions/events/templates/events/register.html
+++ b/lnbits/extensions/events/templates/events/register.html
@@ -133,7 +133,7 @@
var self = this
LNbits.api
- .request('GET', '/events/api/v1/register/ticket/' + res)
+ .request('GET', '/events/api/v1/register/ticket/' + res.split("//")[1])
.then(function (response) {
self.$q.notify({
type: 'positive',
diff --git a/lnbits/extensions/events/templates/events/ticket.html b/lnbits/extensions/events/templates/events/ticket.html
index a53f834f..21b7cfa8 100644
--- a/lnbits/extensions/events/templates/events/ticket.html
+++ b/lnbits/extensions/events/templates/events/ticket.html
@@ -13,9 +13,8 @@
diff --git a/lnbits/extensions/events/views_api.py b/lnbits/extensions/events/views_api.py
index 87edb07d..45ee4de0 100644
--- a/lnbits/extensions/events/views_api.py
+++ b/lnbits/extensions/events/views_api.py
@@ -97,8 +97,8 @@ async def api_tickets(
return [ticket.dict() for ticket in await get_tickets(wallet_ids)]
-@events_ext.post("/api/v1/tickets/{event_id}/{sats}")
-async def api_ticket_make_ticket(event_id, sats, data: CreateTicket):
+@events_ext.get("/api/v1/tickets/{event_id}")
+async def api_ticket_make_ticket(event_id):
event = await get_event(event_id)
if not event:
raise HTTPException(
@@ -107,37 +107,35 @@ async def api_ticket_make_ticket(event_id, sats, data: CreateTicket):
try:
payment_hash, payment_request = await create_invoice(
wallet_id=event.wallet,
- amount=int(sats),
+ amount=event.price_per_ticket,
memo=f"{event_id}",
extra={"tag": "events"},
)
except Exception as e:
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e))
- ticket = await create_ticket(
- payment_hash=payment_hash,
- wallet=event.wallet,
- event=event_id,
- name=data.name,
- email=data.email,
- )
-
- if not ticket:
- raise HTTPException(
- status_code=HTTPStatus.NOT_FOUND, detail=f"Event could not be fetched."
- )
-
return {"payment_hash": payment_hash, "payment_request": payment_request}
-@events_ext.get("/api/v1/tickets/{payment_hash}")
-async def api_ticket_send_ticket(payment_hash):
- ticket = await get_ticket(payment_hash)
-
+@events_ext.post("/api/v1/tickets/{event_id}/{payment_hash}")
+async def api_ticket_send_ticket(event_id, payment_hash, data: CreateTicket):
+ event = await get_event(event_id)
try:
status = await api_payment(payment_hash)
if status["paid"]:
- await set_ticket_paid(payment_hash=payment_hash)
+ ticket = await create_ticket(
+ payment_hash=payment_hash,
+ wallet=event.wallet,
+ event=event_id,
+ name=data.name,
+ email=data.email,
+ )
+
+ if not ticket:
+ raise HTTPException(
+ status_code=HTTPStatus.NOT_FOUND, detail=f"Event could not be fetched."
+ )
+
return {"paid": True, "ticket_id": ticket.id}
except Exception:
raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail="Not paid")
From bb002c6d4091056132483802a256ebb8c01af4df Mon Sep 17 00:00:00 2001
From: Arc <33088785+arcbtc@users.noreply.github.com>
Date: Wed, 27 Jul 2022 17:57:59 +0100
Subject: [PATCH 15/18] Update wallets.md
---
docs/guide/wallets.md | 1 -
1 file changed, 1 deletion(-)
diff --git a/docs/guide/wallets.md b/docs/guide/wallets.md
index 7a3b6a27..dfea66aa 100644
--- a/docs/guide/wallets.md
+++ b/docs/guide/wallets.md
@@ -17,7 +17,6 @@ A backend wallet can be configured using the following LNbits environment variab
### CLightning
Using this wallet requires the installation of the `pylightning` Python package.
-If you want to use LNURLp you should use SparkWallet because of an issue with description_hash and CLightning.
- `LNBITS_BACKEND_WALLET_CLASS`: **CLightningWallet**
- `CLIGHTNING_RPC`: /file/path/lightning-rpc
From 58659d2f47be25c30620576186374e79e20ab926 Mon Sep 17 00:00:00 2001
From: ben
Date: Wed, 27 Jul 2022 18:20:36 +0100
Subject: [PATCH 16/18] Added meta for api /docs
---
lnbits/app.py | 9 +++++++-
.../events/templates/events/display.html | 22 ++++++++++---------
.../events/templates/events/register.html | 5 ++++-
3 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 8e32e38b..19482b06 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -45,7 +45,14 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
"""
configure_logger()
- app = FastAPI()
+ app = FastAPI(
+ title="LNbits API",
+ description="API for LNbits, the free and open source bitcoin wallet and accounts system with plugins.",
+ license_info={
+ "name": "MIT License",
+ "url": "https://raw.githubusercontent.com/lnbits/lnbits-legend/main/LICENSE",
+ },
+ )
app.mount("/static", StaticFiles(packages=[("lnbits", "static")]), name="static")
app.mount(
"/core/static",
diff --git a/lnbits/extensions/events/templates/events/display.html b/lnbits/extensions/events/templates/events/display.html
index 7e62b7a7..4589c578 100644
--- a/lnbits/extensions/events/templates/events/display.html
+++ b/lnbits/extensions/events/templates/events/display.html
@@ -135,9 +135,7 @@
var self = this
axios
- .get(
- '/events/api/v1/tickets/' + '{{ event_id }}'
- )
+ .get('/events/api/v1/tickets/' + '{{ event_id }}')
.then(function (response) {
self.paymentReq = response.data.payment_request
self.paymentCheck = response.data.payment_hash
@@ -155,13 +153,17 @@
paymentChecker = setInterval(function () {
axios
- .post('/events/api/v1/tickets/' + '{{ event_id }}/' + self.paymentCheck,
- {
- event: '{{ event_id }}',
- event_name: '{{ event_name }}',
- name: self.formDialog.data.name,
- email: self.formDialog.data.email
- })
+ .post(
+ '/events/api/v1/tickets/' +
+ '{{ event_id }}/' +
+ self.paymentCheck,
+ {
+ event: '{{ event_id }}',
+ event_name: '{{ event_name }}',
+ name: self.formDialog.data.name,
+ email: self.formDialog.data.email
+ }
+ )
.then(function (res) {
if (res.data.paid) {
clearInterval(paymentChecker)
diff --git a/lnbits/extensions/events/templates/events/register.html b/lnbits/extensions/events/templates/events/register.html
index 3913cc0c..43d43070 100644
--- a/lnbits/extensions/events/templates/events/register.html
+++ b/lnbits/extensions/events/templates/events/register.html
@@ -133,7 +133,10 @@
var self = this
LNbits.api
- .request('GET', '/events/api/v1/register/ticket/' + res.split("//")[1])
+ .request(
+ 'GET',
+ '/events/api/v1/register/ticket/' + res.split('//')[1]
+ )
.then(function (response) {
self.$q.notify({
type: 'positive',
From 3a28ff1020bae2ef4a91ca573dcffff06652a896 Mon Sep 17 00:00:00 2001
From: ben
Date: Wed, 27 Jul 2022 19:21:04 +0100
Subject: [PATCH 17/18] added swagger to extensions
---
.../bleskomat/templates/bleskomat/_api_docs.html | 1 +
lnbits/extensions/copilot/templates/copilot/_api_docs.html | 1 +
.../discordbot/templates/discordbot/_api_docs.html | 1 +
lnbits/extensions/events/templates/events/_api_docs.html | 1 +
lnbits/extensions/jukebox/templates/jukebox/_api_docs.html | 2 ++
.../livestream/templates/livestream/_api_docs.html | 2 ++
.../lnaddress/templates/lnaddress/_api_docs.html | 1 +
.../extensions/lndhub/templates/lndhub/_instructions.html | 1 +
.../extensions/lnticket/templates/lnticket/_api_docs.html | 1 +
.../lnurldevice/templates/lnurldevice/_api_docs.html | 6 ++++++
lnbits/extensions/lnurlp/templates/lnurlp/_api_docs.html | 2 ++
.../lnurlpayout/{config.json.example => config.json} | 2 +-
.../lnurlpayout/templates/lnurlpayout/_api_docs.html | 7 +++++++
.../offlineshop/templates/offlineshop/_api_docs.html | 1 +
lnbits/extensions/paywall/templates/paywall/_api_docs.html | 1 +
.../extensions/satsdice/templates/satsdice/_api_docs.html | 1 +
lnbits/extensions/satspay/templates/satspay/_api_docs.html | 1 +
.../splitpayments/templates/splitpayments/_api_docs.html | 6 ++++++
.../streamalerts/templates/streamalerts/_api_docs.html | 1 +
.../subdomains/templates/subdomains/_api_docs.html | 1 +
lnbits/extensions/tipjar/templates/tipjar/_api_docs.html | 1 +
lnbits/extensions/tpos/templates/tpos/_api_docs.html | 1 +
.../usermanager/templates/usermanager/_api_docs.html | 1 +
.../watchonly/templates/watchonly/_api_docs.html | 1 +
.../extensions/withdraw/templates/withdraw/_api_docs.html | 1 +
25 files changed, 44 insertions(+), 1 deletion(-)
rename lnbits/extensions/lnurlpayout/{config.json.example => config.json} (71%)
diff --git a/lnbits/extensions/bleskomat/templates/bleskomat/_api_docs.html b/lnbits/extensions/bleskomat/templates/bleskomat/_api_docs.html
index 210d534c..2a7160bd 100644
--- a/lnbits/extensions/bleskomat/templates/bleskomat/_api_docs.html
+++ b/lnbits/extensions/bleskomat/templates/bleskomat/_api_docs.html
@@ -62,4 +62,5 @@
+
diff --git a/lnbits/extensions/copilot/templates/copilot/_api_docs.html b/lnbits/extensions/copilot/templates/copilot/_api_docs.html
index eed25169..6105d169 100644
--- a/lnbits/extensions/copilot/templates/copilot/_api_docs.html
+++ b/lnbits/extensions/copilot/templates/copilot/_api_docs.html
@@ -14,6 +14,7 @@
label="API info"
:content-inset-level="0.5"
>
+
diff --git a/lnbits/extensions/discordbot/templates/discordbot/_api_docs.html b/lnbits/extensions/discordbot/templates/discordbot/_api_docs.html
index fcda086a..b57e4ab1 100644
--- a/lnbits/extensions/discordbot/templates/discordbot/_api_docs.html
+++ b/lnbits/extensions/discordbot/templates/discordbot/_api_docs.html
@@ -34,6 +34,7 @@
label="API info"
:content-inset-level="0.5"
>
+
diff --git a/lnbits/extensions/events/templates/events/_api_docs.html b/lnbits/extensions/events/templates/events/_api_docs.html
index a5c82174..d2fa890e 100644
--- a/lnbits/extensions/events/templates/events/_api_docs.html
+++ b/lnbits/extensions/events/templates/events/_api_docs.html
@@ -20,4 +20,5 @@
+
diff --git a/lnbits/extensions/jukebox/templates/jukebox/_api_docs.html b/lnbits/extensions/jukebox/templates/jukebox/_api_docs.html
index f4daaf39..4bae4965 100644
--- a/lnbits/extensions/jukebox/templates/jukebox/_api_docs.html
+++ b/lnbits/extensions/jukebox/templates/jukebox/_api_docs.html
@@ -24,6 +24,8 @@
label="API info"
:content-inset-level="0.5"
>
+
+
diff --git a/lnbits/extensions/livestream/templates/livestream/_api_docs.html b/lnbits/extensions/livestream/templates/livestream/_api_docs.html
index fb4853ce..34b6518d 100644
--- a/lnbits/extensions/livestream/templates/livestream/_api_docs.html
+++ b/lnbits/extensions/livestream/templates/livestream/_api_docs.html
@@ -17,6 +17,8 @@
label="API info"
:content-inset-level="0.5"
>
+
+
+
diff --git a/lnbits/extensions/lndhub/templates/lndhub/_instructions.html b/lnbits/extensions/lndhub/templates/lndhub/_instructions.html
index 4db79aba..005bced5 100644
--- a/lnbits/extensions/lndhub/templates/lndhub/_instructions.html
+++ b/lnbits/extensions/lndhub/templates/lndhub/_instructions.html
@@ -31,5 +31,6 @@
+
diff --git a/lnbits/extensions/lnticket/templates/lnticket/_api_docs.html b/lnbits/extensions/lnticket/templates/lnticket/_api_docs.html
index 69328f38..e9340924 100644
--- a/lnbits/extensions/lnticket/templates/lnticket/_api_docs.html
+++ b/lnbits/extensions/lnticket/templates/lnticket/_api_docs.html
@@ -19,4 +19,5 @@
+
diff --git a/lnbits/extensions/lnurldevice/templates/lnurldevice/_api_docs.html b/lnbits/extensions/lnurldevice/templates/lnurldevice/_api_docs.html
index 940d4691..7f9afa27 100644
--- a/lnbits/extensions/lnurldevice/templates/lnurldevice/_api_docs.html
+++ b/lnbits/extensions/lnurldevice/templates/lnurldevice/_api_docs.html
@@ -17,6 +17,12 @@
label="API info"
:content-inset-level="0.5"
>
+
+
@@ -51,6 +52,7 @@
expand-separator
label="Create a pay link"
>
+
POST /lnurlp/api/v1/links
diff --git a/lnbits/extensions/lnurlpayout/config.json.example b/lnbits/extensions/lnurlpayout/config.json
similarity index 71%
rename from lnbits/extensions/lnurlpayout/config.json.example
rename to lnbits/extensions/lnurlpayout/config.json
index 1e72c0c1..b4160d7b 100644
--- a/lnbits/extensions/lnurlpayout/config.json.example
+++ b/lnbits/extensions/lnurlpayout/config.json
@@ -2,5 +2,5 @@
"name": "LNURLPayout",
"short_description": "Autodump wallet funds to LNURLpay",
"icon": "exit_to_app",
- "contributors": ["arcbtc"]
+ "contributors": ["arcbtc","talvasconcelos"]
}
diff --git a/lnbits/extensions/lnurlpayout/templates/lnurlpayout/_api_docs.html b/lnbits/extensions/lnurlpayout/templates/lnurlpayout/_api_docs.html
index 7febea44..4f921bb5 100644
--- a/lnbits/extensions/lnurlpayout/templates/lnurlpayout/_api_docs.html
+++ b/lnbits/extensions/lnurlpayout/templates/lnurlpayout/_api_docs.html
@@ -4,6 +4,12 @@
label="API info"
:content-inset-level="0.5"
>
+
@@ -32,6 +38,7 @@
expand-separator
label="Create a lnurlpayout"
>
+
+
+
diff --git a/lnbits/extensions/satsdice/templates/satsdice/_api_docs.html b/lnbits/extensions/satsdice/templates/satsdice/_api_docs.html
index a80fd37a..e85e9586 100644
--- a/lnbits/extensions/satsdice/templates/satsdice/_api_docs.html
+++ b/lnbits/extensions/satsdice/templates/satsdice/_api_docs.html
@@ -4,6 +4,7 @@
label="API info"
:content-inset-level="0.5"
>
+
diff --git a/lnbits/extensions/satspay/templates/satspay/_api_docs.html b/lnbits/extensions/satspay/templates/satspay/_api_docs.html
index 77451ae5..336ab899 100644
--- a/lnbits/extensions/satspay/templates/satspay/_api_docs.html
+++ b/lnbits/extensions/satspay/templates/satspay/_api_docs.html
@@ -15,6 +15,7 @@
label="API info"
:content-inset-level="0.5"
>
+
diff --git a/lnbits/extensions/splitpayments/templates/splitpayments/_api_docs.html b/lnbits/extensions/splitpayments/templates/splitpayments/_api_docs.html
index 4cf7190c..4b5ed979 100644
--- a/lnbits/extensions/splitpayments/templates/splitpayments/_api_docs.html
+++ b/lnbits/extensions/splitpayments/templates/splitpayments/_api_docs.html
@@ -28,6 +28,12 @@
label="API info"
:content-inset-level="0.5"
>
+
+
diff --git a/lnbits/extensions/subdomains/templates/subdomains/_api_docs.html b/lnbits/extensions/subdomains/templates/subdomains/_api_docs.html
index b839c641..db3b2477 100644
--- a/lnbits/extensions/subdomains/templates/subdomains/_api_docs.html
+++ b/lnbits/extensions/subdomains/templates/subdomains/_api_docs.html
@@ -22,5 +22,6 @@
>
+
diff --git a/lnbits/extensions/tipjar/templates/tipjar/_api_docs.html b/lnbits/extensions/tipjar/templates/tipjar/_api_docs.html
index 95ba6e06..cfb8136b 100644
--- a/lnbits/extensions/tipjar/templates/tipjar/_api_docs.html
+++ b/lnbits/extensions/tipjar/templates/tipjar/_api_docs.html
@@ -12,4 +12,5 @@
>
+
diff --git a/lnbits/extensions/tpos/templates/tpos/_api_docs.html b/lnbits/extensions/tpos/templates/tpos/_api_docs.html
index 8930d990..cbb21be1 100644
--- a/lnbits/extensions/tpos/templates/tpos/_api_docs.html
+++ b/lnbits/extensions/tpos/templates/tpos/_api_docs.html
@@ -4,6 +4,7 @@
label="API info"
:content-inset-level="0.5"
>
+
diff --git a/lnbits/extensions/usermanager/templates/usermanager/_api_docs.html b/lnbits/extensions/usermanager/templates/usermanager/_api_docs.html
index 34b3c39b..886589e6 100644
--- a/lnbits/extensions/usermanager/templates/usermanager/_api_docs.html
+++ b/lnbits/extensions/usermanager/templates/usermanager/_api_docs.html
@@ -28,6 +28,7 @@
label="API info"
:content-inset-level="0.5"
>
+
diff --git a/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html b/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html
index b421186a..94b44a44 100644
--- a/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html
+++ b/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html
@@ -20,6 +20,7 @@
label="API info"
:content-inset-level="0.5"
>
+
diff --git a/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html b/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
index 095aad3a..ff88189d 100644
--- a/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
+++ b/lnbits/extensions/withdraw/templates/withdraw/_api_docs.html
@@ -4,6 +4,7 @@
label="API info"
:content-inset-level="0.5"
>
+
Date: Wed, 27 Jul 2022 19:36:32 +0100
Subject: [PATCH 18/18] disabled lnurlpayout again
---
.../extensions/lnurlpayout/{config.json => config.json.example} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename lnbits/extensions/lnurlpayout/{config.json => config.json.example} (100%)
diff --git a/lnbits/extensions/lnurlpayout/config.json b/lnbits/extensions/lnurlpayout/config.json.example
similarity index 100%
rename from lnbits/extensions/lnurlpayout/config.json
rename to lnbits/extensions/lnurlpayout/config.json.example