Merge branch 'main' into fix/mypy
This commit is contained in:
commit
817472c036
61 changed files with 1824 additions and 102 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -35,3 +35,6 @@ coverage.xml
|
||||||
node_modules
|
node_modules
|
||||||
lnbits/static/bundle.*
|
lnbits/static/bundle.*
|
||||||
docker
|
docker
|
||||||
|
|
||||||
|
# Nix
|
||||||
|
*result*
|
||||||
|
|
|
||||||
110
build.py
Normal file
110
build.py
Normal file
|
|
@ -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"])
|
||||||
|
|
@ -8,13 +8,32 @@ nav_order: 2
|
||||||
|
|
||||||
# Basic installation
|
# 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).
|
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
|
```sh
|
||||||
git clone https://github.com/lnbits/lnbits-legend.git
|
git clone https://github.com/lnbits/lnbits-legend.git
|
||||||
|
|
@ -44,9 +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).
|
Add the flag `--reload` for development (includes hot-reload).
|
||||||
|
|
||||||
|
|
||||||
## Option 2: venv
|
## Option 3: venv
|
||||||
|
|
||||||
Download this repo and install the dependencies:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/lnbits/lnbits-legend.git
|
git clone https://github.com/lnbits/lnbits-legend.git
|
||||||
|
|
@ -67,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`.
|
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
|
### Troubleshooting
|
||||||
|
|
||||||
Problems installing? These commands have helped us install LNbits.
|
Problems installing? These commands have helped us install LNbits.
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ A backend wallet can be configured using the following LNbits environment variab
|
||||||
### CLightning
|
### CLightning
|
||||||
|
|
||||||
Using this wallet requires the installation of the `pylightning` Python package.
|
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**
|
- `LNBITS_BACKEND_WALLET_CLASS`: **CLightningWallet**
|
||||||
- `CLIGHTNING_RPC`: /file/path/lightning-rpc
|
- `CLIGHTNING_RPC`: /file/path/lightning-rpc
|
||||||
|
|
|
||||||
77
flake.lock
generated
Normal file
77
flake.lock
generated
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
55
flake.nix
Normal file
55
flake.nix
Normal file
|
|
@ -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 = {
|
||||||
|
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...
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ import uvloop
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from starlette.requests import Request
|
from starlette.requests import Request
|
||||||
|
|
||||||
from .commands import bundle_vendored, migrate_databases, transpile_scss
|
from .commands import migrate_databases
|
||||||
from .settings import (
|
from .settings import (
|
||||||
DEBUG,
|
DEBUG,
|
||||||
HOST,
|
HOST,
|
||||||
|
|
@ -19,8 +19,6 @@ from .settings import (
|
||||||
uvloop.install()
|
uvloop.install()
|
||||||
|
|
||||||
asyncio.create_task(migrate_databases())
|
asyncio.create_task(migrate_databases())
|
||||||
transpile_scss()
|
|
||||||
bundle_vendored()
|
|
||||||
|
|
||||||
from .app import create_app
|
from .app import create_app
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,19 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
|
||||||
"""
|
"""
|
||||||
configure_logger()
|
configure_logger()
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI(
|
||||||
app.mount("/static", StaticFiles(directory="lnbits/static"), name="static")
|
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(
|
app.mount(
|
||||||
"/core/static", StaticFiles(directory="lnbits/core/static"), name="core_static"
|
"/core/static",
|
||||||
|
StaticFiles(packages=[("lnbits.core", "static")]),
|
||||||
|
name="core_static",
|
||||||
)
|
)
|
||||||
|
|
||||||
origins = ["*"]
|
origins = ["*"]
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ db = Database("ext_bleskomat")
|
||||||
bleskomat_static_files = [
|
bleskomat_static_files = [
|
||||||
{
|
{
|
||||||
"path": "/bleskomat/static",
|
"path": "/bleskomat/static",
|
||||||
"app": StaticFiles(directory="lnbits/extensions/bleskomat/static"),
|
"app": StaticFiles(packages=[("lnbits", "extensions/bleskomat/static")]),
|
||||||
"name": "bleskomat_static",
|
"name": "bleskomat_static",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -62,4 +62,5 @@
|
||||||
</p>
|
</p>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/Bleskomat"></q-btn>
|
||||||
</q-expansion-item>
|
</q-expansion-item>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ db = Database("ext_copilot")
|
||||||
copilot_static_files = [
|
copilot_static_files = [
|
||||||
{
|
{
|
||||||
"path": "/copilot/static",
|
"path": "/copilot/static",
|
||||||
"app": StaticFiles(directory="lnbits/extensions/copilot/static"),
|
"app": StaticFiles(packages=[("lnbits", "extensions/copilot/static")]),
|
||||||
"name": "copilot_static",
|
"name": "copilot_static",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/copilot"></q-btn>
|
||||||
<q-expansion-item group="api" dense expand-separator label="Create copilot">
|
<q-expansion-item group="api" dense expand-separator label="Create copilot">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ db = Database("ext_discordbot")
|
||||||
discordbot_static_files = [
|
discordbot_static_files = [
|
||||||
{
|
{
|
||||||
"path": "/discordbot/static",
|
"path": "/discordbot/static",
|
||||||
"app": StaticFiles(directory="lnbits/extensions/discordbot/static"),
|
"app": StaticFiles(packages=[("lnbits", "extensions/discordbot/static")]),
|
||||||
"name": "discordbot_static",
|
"name": "discordbot_static",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/discordbot"></q-btn>
|
||||||
<q-expansion-item group="api" dense expand-separator label="GET users">
|
<q-expansion-item group="api" dense expand-separator label="GET users">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ async def create_ticket(
|
||||||
INSERT INTO events.ticket (id, wallet, event, name, email, registered, paid)
|
INSERT INTO events.ticket (id, wallet, event, name, email, registered, paid)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(payment_hash, wallet, event, name, email, False, False),
|
(payment_hash, wallet, event, name, email, False, True),
|
||||||
)
|
)
|
||||||
|
|
||||||
ticket = await get_ticket(payment_hash)
|
ticket = await get_ticket(payment_hash)
|
||||||
|
|
|
||||||
|
|
@ -20,4 +20,5 @@
|
||||||
</p>
|
</p>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/events"></q-btn>
|
||||||
</q-expansion-item>
|
</q-expansion-item>
|
||||||
|
|
|
||||||
|
|
@ -135,15 +135,7 @@
|
||||||
var self = this
|
var self = this
|
||||||
axios
|
axios
|
||||||
|
|
||||||
.post(
|
.get('/events/api/v1/tickets/' + '{{ event_id }}')
|
||||||
'/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
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
self.paymentReq = response.data.payment_request
|
self.paymentReq = response.data.payment_request
|
||||||
self.paymentCheck = response.data.payment_hash
|
self.paymentCheck = response.data.payment_hash
|
||||||
|
|
@ -161,7 +153,17 @@
|
||||||
|
|
||||||
paymentChecker = setInterval(function () {
|
paymentChecker = setInterval(function () {
|
||||||
axios
|
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) {
|
.then(function (res) {
|
||||||
if (res.data.paid) {
|
if (res.data.paid) {
|
||||||
clearInterval(paymentChecker)
|
clearInterval(paymentChecker)
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,10 @@
|
||||||
var self = this
|
var self = this
|
||||||
|
|
||||||
LNbits.api
|
LNbits.api
|
||||||
.request('GET', '/events/api/v1/register/ticket/' + res)
|
.request(
|
||||||
|
'GET',
|
||||||
|
'/events/api/v1/register/ticket/' + res.split('//')[1]
|
||||||
|
)
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
self.$q.notify({
|
self.$q.notify({
|
||||||
type: 'positive',
|
type: 'positive',
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,8 @@
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<qrcode
|
<qrcode
|
||||||
:value="'{{ ticket_id }}'"
|
:value="'ticket://{{ ticket_id }}'"
|
||||||
:options="{width: 340}"
|
:options="{width: 500}"
|
||||||
class="rounded-borders"
|
|
||||||
></qrcode>
|
></qrcode>
|
||||||
<br />
|
<br />
|
||||||
<q-btn @click="printWindow" color="grey" class="q-ml-auto">
|
<q-btn @click="printWindow" color="grey" class="q-ml-auto">
|
||||||
|
|
|
||||||
|
|
@ -97,8 +97,8 @@ async def api_tickets(
|
||||||
return [ticket.dict() for ticket in await get_tickets(wallet_ids)]
|
return [ticket.dict() for ticket in await get_tickets(wallet_ids)]
|
||||||
|
|
||||||
|
|
||||||
@events_ext.post("/api/v1/tickets/{event_id}/{sats}")
|
@events_ext.get("/api/v1/tickets/{event_id}")
|
||||||
async def api_ticket_make_ticket(event_id, sats, data: CreateTicket):
|
async def api_ticket_make_ticket(event_id):
|
||||||
event = await get_event(event_id)
|
event = await get_event(event_id)
|
||||||
if not event:
|
if not event:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -107,37 +107,35 @@ async def api_ticket_make_ticket(event_id, sats, data: CreateTicket):
|
||||||
try:
|
try:
|
||||||
payment_hash, payment_request = await create_invoice(
|
payment_hash, payment_request = await create_invoice(
|
||||||
wallet_id=event.wallet,
|
wallet_id=event.wallet,
|
||||||
amount=int(sats),
|
amount=event.price_per_ticket,
|
||||||
memo=f"{event_id}",
|
memo=f"{event_id}",
|
||||||
extra={"tag": "events"},
|
extra={"tag": "events"},
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(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}
|
return {"payment_hash": payment_hash, "payment_request": payment_request}
|
||||||
|
|
||||||
|
|
||||||
@events_ext.get("/api/v1/tickets/{payment_hash}")
|
@events_ext.post("/api/v1/tickets/{event_id}/{payment_hash}")
|
||||||
async def api_ticket_send_ticket(payment_hash):
|
async def api_ticket_send_ticket(event_id, payment_hash, data: CreateTicket):
|
||||||
ticket = await get_ticket(payment_hash)
|
event = await get_event(event_id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
status = await api_payment(payment_hash)
|
status = await api_payment(payment_hash)
|
||||||
if status["paid"]:
|
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}
|
return {"paid": True, "ticket_id": ticket.id}
|
||||||
except Exception:
|
except Exception:
|
||||||
raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail="Not paid")
|
raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail="Not paid")
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ db = Database("ext_jukebox")
|
||||||
jukebox_static_files = [
|
jukebox_static_files = [
|
||||||
{
|
{
|
||||||
"path": "/jukebox/static",
|
"path": "/jukebox/static",
|
||||||
"app": StaticFiles(directory="lnbits/extensions/jukebox/static"),
|
"app": StaticFiles(packages=[("lnbits", "extensions/jukebox/static")]),
|
||||||
"name": "jukebox_static",
|
"name": "jukebox_static",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/jukebox"></q-btn>
|
||||||
|
|
||||||
<q-expansion-item group="api" dense expand-separator label="List jukeboxes">
|
<q-expansion-item group="api" dense expand-separator label="List jukeboxes">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ db = Database("ext_livestream")
|
||||||
livestream_static_files = [
|
livestream_static_files = [
|
||||||
{
|
{
|
||||||
"path": "/livestream/static",
|
"path": "/livestream/static",
|
||||||
"app": StaticFiles(directory="lnbits/extensions/livestream/static"),
|
"app": StaticFiles(packages=[("lnbits", "extensions/livestream/static")]),
|
||||||
"name": "livestream_static",
|
"name": "livestream_static",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/livestream"></q-btn>
|
||||||
|
|
||||||
<q-expansion-item
|
<q-expansion-item
|
||||||
group="api"
|
group="api"
|
||||||
dense
|
dense
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/lnaddress"></q-btn>
|
||||||
<q-expansion-item group="api" dense expand-separator label="GET domains">
|
<q-expansion-item group="api" dense expand-separator label="GET domains">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
|
|
|
||||||
|
|
@ -31,5 +31,6 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/lndhub"></q-btn>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-expansion-item>
|
</q-expansion-item>
|
||||||
|
|
|
||||||
|
|
@ -19,4 +19,5 @@
|
||||||
</p>
|
</p>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/lnticket"></q-btn>
|
||||||
</q-expansion-item>
|
</q-expansion-item>
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,12 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
label="Swagger API"
|
||||||
|
type="a"
|
||||||
|
href="../docs#/lnurldevice"
|
||||||
|
></q-btn>
|
||||||
<q-expansion-item
|
<q-expansion-item
|
||||||
group="api"
|
group="api"
|
||||||
dense
|
dense
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ db = Database("ext_lnurlp")
|
||||||
lnurlp_static_files = [
|
lnurlp_static_files = [
|
||||||
{
|
{
|
||||||
"path": "/lnurlp/static",
|
"path": "/lnurlp/static",
|
||||||
"app": StaticFiles(directory="lnbits/extensions/lnurlp/static"),
|
"app": StaticFiles(packages=[("lnbits", "extensions/lnurlp/static")]),
|
||||||
"name": "lnurlp_static",
|
"name": "lnurlp_static",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/lnurlp"></q-btn>
|
||||||
<q-expansion-item group="api" dense expand-separator label="List pay links">
|
<q-expansion-item group="api" dense expand-separator label="List pay links">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
|
|
@ -51,6 +52,7 @@
|
||||||
expand-separator
|
expand-separator
|
||||||
label="Create a pay link"
|
label="Create a pay link"
|
||||||
>
|
>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/lnurlp"></q-btn>
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<code><span class="text-green">POST</span> /lnurlp/api/v1/links</code>
|
<code><span class="text-green">POST</span> /lnurlp/api/v1/links</code>
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,5 @@
|
||||||
"name": "LNURLPayout",
|
"name": "LNURLPayout",
|
||||||
"short_description": "Autodump wallet funds to LNURLpay",
|
"short_description": "Autodump wallet funds to LNURLpay",
|
||||||
"icon": "exit_to_app",
|
"icon": "exit_to_app",
|
||||||
"contributors": ["arcbtc"]
|
"contributors": ["arcbtc","talvasconcelos"]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,12 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
label="Swagger API"
|
||||||
|
type="a"
|
||||||
|
href="../docs#/lnurlpayout"
|
||||||
|
></q-btn>
|
||||||
<q-expansion-item group="api" dense expand-separator label="List lnurlpayout">
|
<q-expansion-item group="api" dense expand-separator label="List lnurlpayout">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
|
|
@ -32,6 +38,7 @@
|
||||||
expand-separator
|
expand-separator
|
||||||
label="Create a lnurlpayout"
|
label="Create a lnurlpayout"
|
||||||
>
|
>
|
||||||
|
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<code
|
<code
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ db = Database("ext_offlineshop")
|
||||||
offlineshop_static_files = [
|
offlineshop_static_files = [
|
||||||
{
|
{
|
||||||
"path": "/offlineshop/static",
|
"path": "/offlineshop/static",
|
||||||
"app": StaticFiles(directory="lnbits/extensions/offlineshop/static"),
|
"app": StaticFiles(packages=[("lnbits", "extensions/offlineshop/static")]),
|
||||||
"name": "offlineshop_static",
|
"name": "offlineshop_static",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/offlineshop"></q-btn>
|
||||||
<q-expansion-item
|
<q-expansion-item
|
||||||
group="api"
|
group="api"
|
||||||
dense
|
dense
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/paywall"></q-btn>
|
||||||
<q-expansion-item group="api" dense expand-separator label="List paywalls">
|
<q-expansion-item group="api" dense expand-separator label="List paywalls">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/satsdice"></q-btn>
|
||||||
<q-expansion-item group="api" dense expand-separator label="List satsdices">
|
<q-expansion-item group="api" dense expand-separator label="List satsdices">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/satspay"></q-btn>
|
||||||
<q-expansion-item group="api" dense expand-separator label="Create charge">
|
<q-expansion-item group="api" dense expand-separator label="Create charge">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ db = Database("ext_splitpayments")
|
||||||
splitpayments_static_files = [
|
splitpayments_static_files = [
|
||||||
{
|
{
|
||||||
"path": "/splitpayments/static",
|
"path": "/splitpayments/static",
|
||||||
"app": StaticFiles(directory="lnbits/extensions/splitpayments/static"),
|
"app": StaticFiles(packages=[("lnbits", "extensions/splitpayments/static")]),
|
||||||
"name": "splitpayments_static",
|
"name": "splitpayments_static",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,12 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
label="Swagger API"
|
||||||
|
type="a"
|
||||||
|
href="../docs#/splitpayments"
|
||||||
|
></q-btn>
|
||||||
<q-expansion-item
|
<q-expansion-item
|
||||||
group="api"
|
group="api"
|
||||||
dense
|
dense
|
||||||
|
|
|
||||||
|
|
@ -15,4 +15,5 @@
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/streamalerts"></q-btn>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
|
|
||||||
|
|
@ -22,5 +22,6 @@
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/subdomains"></q-btn>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-expansion-item>
|
</q-expansion-item>
|
||||||
|
|
|
||||||
|
|
@ -12,4 +12,5 @@
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/tipjar"></q-btn>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/tpos"></q-btn>
|
||||||
<q-expansion-item group="api" dense expand-separator label="List TPoS">
|
<q-expansion-item group="api" dense expand-separator label="List TPoS">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
|
|
|
||||||
|
|
@ -308,7 +308,9 @@
|
||||||
},
|
},
|
||||||
sat: function () {
|
sat: function () {
|
||||||
if (!this.exchangeRate) return 0
|
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 () {
|
tipAmountSat: function () {
|
||||||
if (!this.exchangeRate) return 0
|
if (!this.exchangeRate) return 0
|
||||||
|
|
@ -423,10 +425,9 @@
|
||||||
'{{ tpos.tip_options | tojson }}' == 'null'
|
'{{ tpos.tip_options | tojson }}' == 'null'
|
||||||
? null
|
? null
|
||||||
: JSON.parse('{{ tpos.tip_options }}')
|
: JSON.parse('{{ tpos.tip_options }}')
|
||||||
console.log(typeof this.tip_options, this.tip_options)
|
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
getRates()
|
getRates()
|
||||||
}, 20000)
|
}, 120000)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/usermanager"></q-btn>
|
||||||
<q-expansion-item group="api" dense expand-separator label="GET users">
|
<q-expansion-item group="api" dense expand-separator label="GET users">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/watchonly"></q-btn>
|
||||||
<q-expansion-item group="api" dense expand-separator label="List wallets">
|
<q-expansion-item group="api" dense expand-separator label="List wallets">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ db = Database("ext_withdraw")
|
||||||
withdraw_static_files = [
|
withdraw_static_files = [
|
||||||
{
|
{
|
||||||
"path": "/withdraw/static",
|
"path": "/withdraw/static",
|
||||||
"app": StaticFiles(directory="lnbits/extensions/withdraw/static"),
|
"app": StaticFiles(packages=[("lnbits", "extensions/withdraw/static")]),
|
||||||
"name": "withdraw_static",
|
"name": "withdraw_static",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
label="API info"
|
label="API info"
|
||||||
:content-inset-level="0.5"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
|
<q-btn flat label="Swagger API" type="a" href="../docs#/withdraw"></q-btn>
|
||||||
<q-expansion-item
|
<q-expansion-item
|
||||||
group="api"
|
group="api"
|
||||||
dense
|
dense
|
||||||
|
|
|
||||||
18
lnbits/server.py
Normal file
18
lnbits/server.py
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import click
|
||||||
|
import uvicorn
|
||||||
|
|
||||||
|
|
||||||
|
@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")
|
||||||
|
|
@ -100,7 +100,7 @@ class EclairWallet(Wallet):
|
||||||
f"{self.url}/payinvoice",
|
f"{self.url}/payinvoice",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
data={"invoice": bolt11, "blocking": True},
|
data={"invoice": bolt11, "blocking": True},
|
||||||
timeout=40,
|
timeout=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
if "error" in r.json():
|
if "error" in r.json():
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ class LNbitsWallet(Wallet):
|
||||||
url=f"{self.endpoint}/api/v1/payments",
|
url=f"{self.endpoint}/api/v1/payments",
|
||||||
headers=self.key,
|
headers=self.key,
|
||||||
json={"out": True, "bolt11": bolt11},
|
json={"out": True, "bolt11": bolt11},
|
||||||
timeout=100,
|
timeout=None,
|
||||||
)
|
)
|
||||||
ok, checking_id, fee_msat, error_message = not r.is_error, None, 0, None
|
ok, checking_id, fee_msat, error_message = not r.is_error, None, 0, None
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ class LndRestWallet(Wallet):
|
||||||
url=f"{self.endpoint}/v1/channels/transactions",
|
url=f"{self.endpoint}/v1/channels/transactions",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
json={"payment_request": bolt11, "fee_limit": lnrpcFeeLimit},
|
json={"payment_request": bolt11, "fee_limit": lnrpcFeeLimit},
|
||||||
timeout=180,
|
timeout=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
if r.is_error or r.json().get("payment_error"):
|
if r.is_error or r.json().get("payment_error"):
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ class LNPayWallet(Wallet):
|
||||||
f"{self.endpoint}/wallet/{self.wallet_key}/withdraw",
|
f"{self.endpoint}/wallet/{self.wallet_key}/withdraw",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
json={"payment_request": bolt11},
|
json={"payment_request": bolt11},
|
||||||
timeout=180,
|
timeout=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ class LntxbotWallet(Wallet):
|
||||||
f"{self.endpoint}/payinvoice",
|
f"{self.endpoint}/payinvoice",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
json={"invoice": bolt11},
|
json={"invoice": bolt11},
|
||||||
timeout=100,
|
timeout=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
if "error" in r.json():
|
if "error" in r.json():
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ class OpenNodeWallet(Wallet):
|
||||||
f"{self.endpoint}/v2/withdrawals",
|
f"{self.endpoint}/v2/withdrawals",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
json={"type": "ln", "address": bolt11},
|
json={"type": "ln", "address": bolt11},
|
||||||
timeout=180,
|
timeout=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
if r.is_error:
|
if r.is_error:
|
||||||
|
|
|
||||||
106
nix/modules/lnbits-service.nix
Normal file
106
nix/modules/lnbits-service.nix
Normal file
|
|
@ -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 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
4
nix/tests/default.nix
Normal file
4
nix/tests/default.nix
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{ pkgs, makeTest, inputs }:
|
||||||
|
{
|
||||||
|
vmTest = import ./nixos-module { inherit pkgs makeTest inputs; };
|
||||||
|
}
|
||||||
25
nix/tests/nixos-module/default.nix
Normal file
25
nix/tests/nixos-module/default.nix
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
{ pkgs, makeTest, inputs }:
|
||||||
|
makeTest {
|
||||||
|
nodes = {
|
||||||
|
client = { config, pkgs, ... }: {
|
||||||
|
environment.systemPackages = [ pkgs.curl ];
|
||||||
|
};
|
||||||
|
lnbits = { ... }: {
|
||||||
|
imports = [ inputs.self.nixosModules.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 "<title>LNbits</title>" in client.succeed(
|
||||||
|
"curl -sSf http:/lnbits:8231/ | grep title"
|
||||||
|
)
|
||||||
|
'';
|
||||||
|
}
|
||||||
1165
poetry.lock
generated
Normal file
1165
poetry.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
70
pyproject.toml
Normal file
70
pyproject.toml
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
[tool.poetry]
|
||||||
|
name = "lnbits"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = ""
|
||||||
|
authors = ["matthewcroughan <matt@croughan.sh>"]
|
||||||
|
|
||||||
|
[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"
|
||||||
|
|
@ -1,52 +1,52 @@
|
||||||
aiofiles==0.7.0
|
aiofiles==0.8.0
|
||||||
anyio==3.3.1
|
anyio==3.6.1
|
||||||
asgiref==3.4.1
|
|
||||||
asyncio==3.4.3
|
asyncio==3.4.3
|
||||||
attrs==21.2.0
|
attrs==21.4.0
|
||||||
bech32==1.2.0
|
bech32==1.2.0
|
||||||
bitstring==3.1.9
|
bitstring==3.1.9
|
||||||
cerberus==1.3.4
|
cerberus==1.3.4
|
||||||
certifi==2021.5.30
|
certifi==2022.6.15
|
||||||
charset-normalizer==2.0.6
|
cffi==1.15.0
|
||||||
click==8.0.1
|
click==8.1.3
|
||||||
ecdsa==0.17.0
|
ecdsa==0.18.0
|
||||||
embit==0.4.9
|
embit==0.5.0
|
||||||
environs==9.3.3
|
environs==9.5.0
|
||||||
fastapi==0.68.1
|
fastapi==0.79.0
|
||||||
h11==0.12.0
|
h11==0.12.0
|
||||||
httpcore==0.15.0
|
httpcore==0.15.0
|
||||||
httptools==0.2.0
|
httptools==0.4.0
|
||||||
httpx==0.23.0
|
httpx==0.23.0
|
||||||
idna==3.2
|
idna==3.3
|
||||||
importlib-metadata==4.8.1
|
|
||||||
jinja2==3.0.1
|
jinja2==3.0.1
|
||||||
lnurl==0.3.6
|
lnurl==0.3.6
|
||||||
loguru==0.6.0
|
loguru==0.6.0
|
||||||
markupsafe==2.0.1
|
markupsafe==2.1.1
|
||||||
marshmallow==3.13.0
|
marshmallow==3.17.0
|
||||||
outcome==1.1.0
|
outcome==1.2.0
|
||||||
psycopg2-binary==2.9.1
|
packaging==21.3
|
||||||
pycryptodomex==3.14.1
|
psycopg2-binary==2.9.3
|
||||||
pydantic==1.8.2
|
pycparser==2.21
|
||||||
pypng==0.0.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
|
pyqrcode==1.2.1
|
||||||
pyscss==1.3.7
|
pyscss==1.4.0
|
||||||
python-dotenv==0.19.0
|
python-dotenv==0.20.0
|
||||||
pyyaml==5.4.1
|
pyyaml==6.0
|
||||||
represent==1.6.0.post0
|
represent==1.6.0.post0
|
||||||
rfc3986==1.5.0
|
rfc3986==1.5.0
|
||||||
secp256k1==0.14.0
|
secp256k1==0.14.0
|
||||||
cffi==1.15.0
|
shortuuid==1.0.9
|
||||||
shortuuid==1.0.1
|
|
||||||
six==1.16.0
|
six==1.16.0
|
||||||
sniffio==1.2.0
|
sniffio==1.2.0
|
||||||
|
sqlalchemy-aio==0.17.0
|
||||||
sqlalchemy==1.3.23
|
sqlalchemy==1.3.23
|
||||||
sqlalchemy-aio==0.16.0
|
sse-starlette==0.10.3
|
||||||
sse-starlette==0.6.2
|
starlette==0.19.1
|
||||||
starlette==0.14.2
|
typing-extensions==4.3.0
|
||||||
typing-extensions==3.10.0.2
|
uvicorn==0.18.2
|
||||||
uvicorn==0.15.0
|
|
||||||
uvloop==0.16.0
|
uvloop==0.16.0
|
||||||
watchgod==0.7
|
watchfiles==0.16.0
|
||||||
websockets==10.0
|
websockets==10.3
|
||||||
zipp==3.5.0
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue