feat: use uv instead of poetry for CI, docker and development (#3325)
Co-authored-by: arcbtc <ben@arc.wales>
This commit is contained in:
+2
-2
@@ -5,9 +5,9 @@ import os
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
from collections.abc import Callable
|
||||
from contextlib import asynccontextmanager
|
||||
from pathlib import Path
|
||||
from typing import Callable, Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
@@ -280,7 +280,7 @@ async def check_installed_extensions(app: FastAPI):
|
||||
|
||||
|
||||
async def build_all_installed_extensions_list( # noqa: C901
|
||||
include_deactivated: Optional[bool] = True,
|
||||
include_deactivated: bool | None = True,
|
||||
) -> list[InstallableExtension]:
|
||||
"""
|
||||
Returns a list of all the installed extensions plus the extensions that
|
||||
|
||||
+32
-33
@@ -5,7 +5,6 @@ import time
|
||||
from functools import wraps
|
||||
from getpass import getpass
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from uuid import uuid4
|
||||
|
||||
import click
|
||||
@@ -96,7 +95,7 @@ def decrypt():
|
||||
"""
|
||||
|
||||
|
||||
def get_super_user() -> Optional[str]:
|
||||
def get_super_user() -> str | None:
|
||||
"""Get the superuser"""
|
||||
superuser_file = Path(settings.lnbits_data_folder, ".super_user")
|
||||
if not superuser_file.exists() or not superuser_file.is_file():
|
||||
@@ -155,7 +154,7 @@ async def db_versions():
|
||||
@db.command("cleanup-wallets")
|
||||
@click.argument("days", type=int, required=False)
|
||||
@coro
|
||||
async def database_cleanup_wallets(days: Optional[int] = None):
|
||||
async def database_cleanup_wallets(days: int | None = None):
|
||||
"""Delete all wallets that never had any transaction"""
|
||||
async with core_db.connect() as conn:
|
||||
delta = days or settings.cleanup_wallets_days
|
||||
@@ -212,10 +211,10 @@ async def database_revert_payment(checking_id: str):
|
||||
@click.option("-v", "--verbose", is_flag=True, help="Detailed log.")
|
||||
@coro
|
||||
async def check_invalid_payments(
|
||||
days: Optional[int] = None,
|
||||
limit: Optional[int] = None,
|
||||
wallet: Optional[str] = None,
|
||||
verbose: Optional[bool] = False,
|
||||
days: int | None = None,
|
||||
limit: int | None = None,
|
||||
wallet: str | None = None,
|
||||
verbose: bool | None = False,
|
||||
):
|
||||
"""Check payments that are settled in the DB but pending on the Funding Source"""
|
||||
await check_admin_settings()
|
||||
@@ -303,7 +302,7 @@ async def create_user(username: str, password: str):
|
||||
@users.command("cleanup-accounts")
|
||||
@click.argument("days", type=int, required=False)
|
||||
@coro
|
||||
async def database_cleanup_accounts(days: Optional[int] = None):
|
||||
async def database_cleanup_accounts(days: int | None = None):
|
||||
"""Delete all accounts that have no wallets"""
|
||||
async with core_db.connect() as conn:
|
||||
delta = days or settings.cleanup_wallets_days
|
||||
@@ -353,12 +352,12 @@ async def extensions_list():
|
||||
)
|
||||
@coro
|
||||
async def extensions_update( # noqa: C901
|
||||
extension: Optional[str] = None,
|
||||
all_extensions: Optional[bool] = False,
|
||||
repo_index: Optional[str] = None,
|
||||
source_repo: Optional[str] = None,
|
||||
url: Optional[str] = None,
|
||||
admin_user: Optional[str] = None,
|
||||
extension: str | None = None,
|
||||
all_extensions: bool | None = False,
|
||||
repo_index: str | None = None,
|
||||
source_repo: str | None = None,
|
||||
url: str | None = None,
|
||||
admin_user: str | None = None,
|
||||
):
|
||||
"""
|
||||
Update extension to the latest version.
|
||||
@@ -443,10 +442,10 @@ async def extensions_update( # noqa: C901
|
||||
@coro
|
||||
async def extensions_install(
|
||||
extension: str,
|
||||
repo_index: Optional[str] = None,
|
||||
source_repo: Optional[str] = None,
|
||||
url: Optional[str] = None,
|
||||
admin_user: Optional[str] = None,
|
||||
repo_index: str | None = None,
|
||||
source_repo: str | None = None,
|
||||
url: str | None = None,
|
||||
admin_user: str | None = None,
|
||||
):
|
||||
"""Install a extension"""
|
||||
click.echo(f"Installing {extension}... {repo_index}")
|
||||
@@ -473,7 +472,7 @@ async def extensions_install(
|
||||
)
|
||||
@coro
|
||||
async def extensions_uninstall(
|
||||
extension: str, url: Optional[str] = None, admin_user: Optional[str] = None
|
||||
extension: str, url: str | None = None, admin_user: str | None = None
|
||||
):
|
||||
"""Uninstall a extension"""
|
||||
click.echo(f"Uninstalling '{extension}'...")
|
||||
@@ -562,10 +561,10 @@ if __name__ == "__main__":
|
||||
|
||||
async def install_extension(
|
||||
extension: str,
|
||||
repo_index: Optional[str] = None,
|
||||
source_repo: Optional[str] = None,
|
||||
url: Optional[str] = None,
|
||||
admin_user: Optional[str] = None,
|
||||
repo_index: str | None = None,
|
||||
source_repo: str | None = None,
|
||||
url: str | None = None,
|
||||
admin_user: str | None = None,
|
||||
) -> tuple[bool, str]:
|
||||
try:
|
||||
release = await _select_release(extension, repo_index, source_repo)
|
||||
@@ -591,10 +590,10 @@ async def install_extension(
|
||||
|
||||
async def update_extension(
|
||||
extension: str,
|
||||
repo_index: Optional[str] = None,
|
||||
source_repo: Optional[str] = None,
|
||||
url: Optional[str] = None,
|
||||
admin_user: Optional[str] = None,
|
||||
repo_index: str | None = None,
|
||||
source_repo: str | None = None,
|
||||
url: str | None = None,
|
||||
admin_user: str | None = None,
|
||||
) -> tuple[bool, str]:
|
||||
try:
|
||||
click.echo(f"Updating '{extension}' extension.")
|
||||
@@ -644,9 +643,9 @@ async def update_extension(
|
||||
|
||||
async def _select_release(
|
||||
extension: str,
|
||||
repo_index: Optional[str] = None,
|
||||
source_repo: Optional[str] = None,
|
||||
) -> Optional[ExtensionRelease]:
|
||||
repo_index: str | None = None,
|
||||
source_repo: str | None = None,
|
||||
) -> ExtensionRelease | None:
|
||||
all_releases = await InstallableExtension.get_extension_releases(extension)
|
||||
if len(all_releases) == 0:
|
||||
click.echo(f"No repository found for extension '{extension}'.")
|
||||
@@ -706,7 +705,7 @@ def _get_latest_release_per_repo(all_releases):
|
||||
|
||||
|
||||
async def _call_install_extension(
|
||||
data: CreateExtension, url: Optional[str], user_id: Optional[str] = None
|
||||
data: CreateExtension, url: str | None, user_id: str | None = None
|
||||
):
|
||||
if url:
|
||||
user_id = user_id or get_super_user()
|
||||
@@ -720,7 +719,7 @@ async def _call_install_extension(
|
||||
|
||||
|
||||
async def _call_uninstall_extension(
|
||||
extension: str, url: Optional[str], user_id: Optional[str] = None
|
||||
extension: str, url: str | None, user_id: str | None = None
|
||||
):
|
||||
if url:
|
||||
user_id = user_id or get_super_user()
|
||||
@@ -756,7 +755,7 @@ async def _can_run_operation(url) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
async def _is_lnbits_started(url: Optional[str]):
|
||||
async def _is_lnbits_started(url: str | None):
|
||||
try:
|
||||
url = url or f"http://{settings.host}:{settings.port}/api/v1/health"
|
||||
async with httpx.AsyncClient() as client:
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Optional
|
||||
|
||||
from lnbits.core.db import db
|
||||
from lnbits.core.models import AuditEntry, AuditFilters
|
||||
from lnbits.core.models.audit import AuditCountStat
|
||||
@@ -8,14 +6,14 @@ from lnbits.db import Connection, Filters, Page
|
||||
|
||||
async def create_audit_entry(
|
||||
entry: AuditEntry,
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
) -> None:
|
||||
await (conn or db).insert("audit", entry)
|
||||
|
||||
|
||||
async def get_audit_entries(
|
||||
filters: Optional[Filters[AuditFilters]] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
filters: Filters[AuditFilters] | None = None,
|
||||
conn: Connection | None = None,
|
||||
) -> Page[AuditEntry]:
|
||||
return await (conn or db).fetch_page(
|
||||
"SELECT * from audit",
|
||||
@@ -27,7 +25,7 @@ async def get_audit_entries(
|
||||
|
||||
|
||||
async def delete_expired_audit_entries(
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
):
|
||||
await (conn or db).execute(
|
||||
# Timestamp placeholder is safe from SQL injection (not user input)
|
||||
@@ -40,8 +38,8 @@ async def delete_expired_audit_entries(
|
||||
|
||||
async def get_count_stats(
|
||||
field: str,
|
||||
filters: Optional[Filters[AuditFilters]] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
filters: Filters[AuditFilters] | None = None,
|
||||
conn: Connection | None = None,
|
||||
) -> list[AuditCountStat]:
|
||||
if field not in ["request_method", "component", "response_code"]:
|
||||
return []
|
||||
@@ -67,8 +65,8 @@ async def get_count_stats(
|
||||
|
||||
|
||||
async def get_long_duration_stats(
|
||||
filters: Optional[Filters[AuditFilters]] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
filters: Filters[AuditFilters] | None = None,
|
||||
conn: Connection | None = None,
|
||||
) -> list[AuditCountStat]:
|
||||
if not filters:
|
||||
filters = Filters()
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Optional
|
||||
|
||||
from lnbits.core.db import db
|
||||
from lnbits.db import Connection
|
||||
|
||||
@@ -7,8 +5,8 @@ from ..models import DbVersion
|
||||
|
||||
|
||||
async def get_db_version(
|
||||
ext_id: str, conn: Optional[Connection] = None
|
||||
) -> Optional[DbVersion]:
|
||||
ext_id: str, conn: Connection | None = None
|
||||
) -> DbVersion | None:
|
||||
return await (conn or db).fetchone(
|
||||
"SELECT * FROM dbversions WHERE db = :ext_id",
|
||||
{"ext_id": ext_id},
|
||||
@@ -16,7 +14,7 @@ async def get_db_version(
|
||||
)
|
||||
|
||||
|
||||
async def get_db_versions(conn: Optional[Connection] = None) -> list[DbVersion]:
|
||||
async def get_db_versions(conn: Connection | None = None) -> list[DbVersion]:
|
||||
return await (conn or db).fetchall("SELECT * FROM dbversions", model=DbVersion)
|
||||
|
||||
|
||||
@@ -30,7 +28,7 @@ async def update_migration_version(conn, db_name, version):
|
||||
)
|
||||
|
||||
|
||||
async def delete_dbversion(*, ext_id: str, conn: Optional[Connection] = None) -> None:
|
||||
async def delete_dbversion(*, ext_id: str, conn: Connection | None = None) -> None:
|
||||
await (conn or db).execute(
|
||||
"""
|
||||
DELETE FROM dbversions WHERE db = :ext
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Optional
|
||||
|
||||
from lnbits.core.db import db
|
||||
from lnbits.core.models.extensions import (
|
||||
InstallableExtension,
|
||||
@@ -10,20 +8,20 @@ from lnbits.db import Connection, Database
|
||||
|
||||
async def create_installed_extension(
|
||||
ext: InstallableExtension,
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
) -> None:
|
||||
await (conn or db).insert("installed_extensions", ext)
|
||||
|
||||
|
||||
async def update_installed_extension(
|
||||
ext: InstallableExtension,
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
) -> None:
|
||||
await (conn or db).update("installed_extensions", ext)
|
||||
|
||||
|
||||
async def update_installed_extension_state(
|
||||
*, ext_id: str, active: bool, conn: Optional[Connection] = None
|
||||
*, ext_id: str, active: bool, conn: Connection | None = None
|
||||
) -> None:
|
||||
await (conn or db).execute(
|
||||
"""
|
||||
@@ -34,7 +32,7 @@ async def update_installed_extension_state(
|
||||
|
||||
|
||||
async def delete_installed_extension(
|
||||
*, ext_id: str, conn: Optional[Connection] = None
|
||||
*, ext_id: str, conn: Connection | None = None
|
||||
) -> None:
|
||||
await (conn or db).execute(
|
||||
"""
|
||||
@@ -44,7 +42,7 @@ async def delete_installed_extension(
|
||||
)
|
||||
|
||||
|
||||
async def drop_extension_db(ext_id: str, conn: Optional[Connection] = None) -> None:
|
||||
async def drop_extension_db(ext_id: str, conn: Connection | None = None) -> None:
|
||||
row: dict = await (conn or db).fetchone(
|
||||
"SELECT * FROM dbversions WHERE db = :id",
|
||||
{"id": ext_id},
|
||||
@@ -65,8 +63,8 @@ async def drop_extension_db(ext_id: str, conn: Optional[Connection] = None) -> N
|
||||
|
||||
|
||||
async def get_installed_extension(
|
||||
ext_id: str, conn: Optional[Connection] = None
|
||||
) -> Optional[InstallableExtension]:
|
||||
ext_id: str, conn: Connection | None = None
|
||||
) -> InstallableExtension | None:
|
||||
extension = await (conn or db).fetchone(
|
||||
"SELECT * FROM installed_extensions WHERE id = :id",
|
||||
{"id": ext_id},
|
||||
@@ -76,8 +74,8 @@ async def get_installed_extension(
|
||||
|
||||
|
||||
async def get_installed_extensions(
|
||||
active: Optional[bool] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
active: bool | None = None,
|
||||
conn: Connection | None = None,
|
||||
) -> list[InstallableExtension]:
|
||||
query = "SELECT * FROM installed_extensions"
|
||||
if active is not None:
|
||||
@@ -93,8 +91,8 @@ async def get_installed_extensions(
|
||||
|
||||
|
||||
async def get_user_extension(
|
||||
user_id: str, extension: str, conn: Optional[Connection] = None
|
||||
) -> Optional[UserExtension]:
|
||||
user_id: str, extension: str, conn: Connection | None = None
|
||||
) -> UserExtension | None:
|
||||
return await (conn or db).fetchone(
|
||||
"""
|
||||
SELECT * FROM extensions
|
||||
@@ -106,7 +104,7 @@ async def get_user_extension(
|
||||
|
||||
|
||||
async def get_user_extensions(
|
||||
user_id: str, conn: Optional[Connection] = None
|
||||
user_id: str, conn: Connection | None = None
|
||||
) -> list[UserExtension]:
|
||||
return await (conn or db).fetchall(
|
||||
"""SELECT * FROM extensions WHERE "user" = :user""",
|
||||
@@ -116,20 +114,20 @@ async def get_user_extensions(
|
||||
|
||||
|
||||
async def create_user_extension(
|
||||
user_extension: UserExtension, conn: Optional[Connection] = None
|
||||
user_extension: UserExtension, conn: Connection | None = None
|
||||
) -> None:
|
||||
await (conn or db).insert("extensions", user_extension)
|
||||
|
||||
|
||||
async def update_user_extension(
|
||||
user_extension: UserExtension, conn: Optional[Connection] = None
|
||||
user_extension: UserExtension, conn: Connection | None = None
|
||||
) -> None:
|
||||
where = """WHERE extension = :extension AND "user" = :user"""
|
||||
await (conn or db).update("extensions", user_extension, where)
|
||||
|
||||
|
||||
async def get_user_active_extensions_ids(
|
||||
user_id: str, conn: Optional[Connection] = None
|
||||
user_id: str, conn: Connection | None = None
|
||||
) -> list[str]:
|
||||
exts = await (conn or db).fetchall(
|
||||
"""
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from time import time
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
from lnbits.core.crud.wallets import get_total_balance, get_wallet, get_wallets_ids
|
||||
from lnbits.core.db import db
|
||||
@@ -23,7 +23,7 @@ def update_payment_extra():
|
||||
pass
|
||||
|
||||
|
||||
async def get_payment(checking_id: str, conn: Optional[Connection] = None) -> Payment:
|
||||
async def get_payment(checking_id: str, conn: Connection | None = None) -> Payment:
|
||||
return await (conn or db).fetchone(
|
||||
"SELECT * FROM apipayments WHERE checking_id = :checking_id",
|
||||
{"checking_id": checking_id},
|
||||
@@ -33,10 +33,10 @@ async def get_payment(checking_id: str, conn: Optional[Connection] = None) -> Pa
|
||||
|
||||
async def get_standalone_payment(
|
||||
checking_id_or_hash: str,
|
||||
conn: Optional[Connection] = None,
|
||||
incoming: Optional[bool] = False,
|
||||
wallet_id: Optional[str] = None,
|
||||
) -> Optional[Payment]:
|
||||
conn: Connection | None = None,
|
||||
incoming: bool | None = False,
|
||||
wallet_id: str | None = None,
|
||||
) -> Payment | None:
|
||||
clause: str = "checking_id = :checking_id OR payment_hash = :hash"
|
||||
values = {
|
||||
"wallet_id": wallet_id,
|
||||
@@ -64,8 +64,8 @@ async def get_standalone_payment(
|
||||
|
||||
|
||||
async def get_wallet_payment(
|
||||
wallet_id: str, payment_hash: str, conn: Optional[Connection] = None
|
||||
) -> Optional[Payment]:
|
||||
wallet_id: str, payment_hash: str, conn: Connection | None = None
|
||||
) -> Payment | None:
|
||||
payment = await (conn or db).fetchone(
|
||||
"""
|
||||
SELECT *
|
||||
@@ -102,17 +102,17 @@ async def get_latest_payments_by_extension(
|
||||
|
||||
async def get_payments_paginated( # noqa: C901
|
||||
*,
|
||||
wallet_id: Optional[str] = None,
|
||||
user_id: Optional[str] = None,
|
||||
wallet_id: str | None = None,
|
||||
user_id: str | None = None,
|
||||
complete: bool = False,
|
||||
pending: bool = False,
|
||||
failed: bool = False,
|
||||
outgoing: bool = False,
|
||||
incoming: bool = False,
|
||||
since: Optional[int] = None,
|
||||
since: int | None = None,
|
||||
exclude_uncheckable: bool = False,
|
||||
filters: Optional[Filters[PaymentFilters]] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
filters: Filters[PaymentFilters] | None = None,
|
||||
conn: Connection | None = None,
|
||||
) -> Page[Payment]:
|
||||
"""
|
||||
Filters payments to be returned by:
|
||||
@@ -176,17 +176,17 @@ async def get_payments_paginated( # noqa: C901
|
||||
|
||||
async def get_payments(
|
||||
*,
|
||||
wallet_id: Optional[str] = None,
|
||||
wallet_id: str | None = None,
|
||||
complete: bool = False,
|
||||
pending: bool = False,
|
||||
outgoing: bool = False,
|
||||
incoming: bool = False,
|
||||
since: Optional[int] = None,
|
||||
since: int | None = None,
|
||||
exclude_uncheckable: bool = False,
|
||||
filters: Optional[Filters[PaymentFilters]] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
limit: Optional[int] = None,
|
||||
offset: Optional[int] = None,
|
||||
filters: Filters[PaymentFilters] | None = None,
|
||||
conn: Connection | None = None,
|
||||
limit: int | None = None,
|
||||
offset: int | None = None,
|
||||
) -> list[Payment]:
|
||||
"""
|
||||
Filters payments to be returned by complete | pending | outgoing | incoming.
|
||||
@@ -230,7 +230,7 @@ async def get_payments_status_count() -> PaymentsStatusCount:
|
||||
|
||||
|
||||
async def delete_expired_invoices(
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
) -> None:
|
||||
# first we delete all invoices older than one month
|
||||
|
||||
@@ -259,7 +259,7 @@ async def create_payment(
|
||||
checking_id: str,
|
||||
data: CreatePayment,
|
||||
status: PaymentState = PaymentState.PENDING,
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
) -> Payment:
|
||||
# we don't allow the creation of the same invoice twice
|
||||
# note: this can be removed if the db uniqueness constraints are set appropriately
|
||||
@@ -290,7 +290,7 @@ async def create_payment(
|
||||
|
||||
|
||||
async def update_payment_checking_id(
|
||||
checking_id: str, new_checking_id: str, conn: Optional[Connection] = None
|
||||
checking_id: str, new_checking_id: str, conn: Connection | None = None
|
||||
) -> None:
|
||||
await (conn or db).execute(
|
||||
"UPDATE apipayments SET checking_id = :new_id WHERE checking_id = :old_id",
|
||||
@@ -300,8 +300,8 @@ async def update_payment_checking_id(
|
||||
|
||||
async def update_payment(
|
||||
payment: Payment,
|
||||
new_checking_id: Optional[str] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
new_checking_id: str | None = None,
|
||||
conn: Connection | None = None,
|
||||
) -> None:
|
||||
await (conn or db).update(
|
||||
"apipayments", payment, "WHERE checking_id = :checking_id"
|
||||
@@ -311,9 +311,9 @@ async def update_payment(
|
||||
|
||||
|
||||
async def get_payments_history(
|
||||
wallet_id: Optional[str] = None,
|
||||
wallet_id: str | None = None,
|
||||
group: DateTrunc = "day",
|
||||
filters: Optional[Filters] = None,
|
||||
filters: Filters | None = None,
|
||||
) -> list[PaymentHistoryPoint]:
|
||||
if not filters:
|
||||
filters = Filters()
|
||||
@@ -376,9 +376,9 @@ async def get_payments_history(
|
||||
|
||||
async def get_payment_count_stats(
|
||||
field: PaymentCountField,
|
||||
filters: Optional[Filters[PaymentFilters]] = None,
|
||||
user_id: Optional[str] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
filters: Filters[PaymentFilters] | None = None,
|
||||
user_id: str | None = None,
|
||||
conn: Connection | None = None,
|
||||
) -> list[PaymentCountStat]:
|
||||
|
||||
if not filters:
|
||||
@@ -409,9 +409,9 @@ async def get_payment_count_stats(
|
||||
|
||||
|
||||
async def get_daily_stats(
|
||||
filters: Optional[Filters[PaymentFilters]] = None,
|
||||
user_id: Optional[str] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
filters: Filters[PaymentFilters] | None = None,
|
||||
user_id: str | None = None,
|
||||
conn: Connection | None = None,
|
||||
) -> tuple[list[PaymentDailyStats], list[PaymentDailyStats]]:
|
||||
|
||||
if not filters:
|
||||
@@ -459,9 +459,9 @@ async def get_daily_stats(
|
||||
|
||||
|
||||
async def get_wallets_stats(
|
||||
filters: Optional[Filters[PaymentFilters]] = None,
|
||||
user_id: Optional[str] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
filters: Filters[PaymentFilters] | None = None,
|
||||
user_id: str | None = None,
|
||||
conn: Connection | None = None,
|
||||
) -> list[PaymentWalletStats]:
|
||||
|
||||
if not filters:
|
||||
@@ -508,7 +508,7 @@ async def get_wallets_stats(
|
||||
|
||||
|
||||
async def delete_wallet_payment(
|
||||
checking_id: str, wallet_id: str, conn: Optional[Connection] = None
|
||||
checking_id: str, wallet_id: str, conn: Connection | None = None
|
||||
) -> None:
|
||||
await (conn or db).execute(
|
||||
"DELETE FROM apipayments WHERE checking_id = :checking_id AND wallet = :wallet",
|
||||
@@ -517,8 +517,8 @@ async def delete_wallet_payment(
|
||||
|
||||
|
||||
async def check_internal(
|
||||
payment_hash: str, conn: Optional[Connection] = None
|
||||
) -> Optional[Payment]:
|
||||
payment_hash: str, conn: Connection | None = None
|
||||
) -> Payment | None:
|
||||
"""
|
||||
Returns the checking_id of the internal payment if it exists,
|
||||
otherwise None
|
||||
@@ -534,7 +534,7 @@ async def check_internal(
|
||||
|
||||
|
||||
async def is_internal_status_success(
|
||||
payment_hash: str, conn: Optional[Connection] = None
|
||||
payment_hash: str, conn: Connection | None = None
|
||||
) -> bool:
|
||||
"""
|
||||
Returns True if the internal payment was found and is successful,
|
||||
@@ -563,7 +563,7 @@ async def mark_webhook_sent(payment_hash: str, status: str) -> None:
|
||||
|
||||
|
||||
async def _only_user_wallets_statement(
|
||||
user_id: str, conn: Optional[Connection] = None
|
||||
user_id: str, conn: Connection | None = None
|
||||
) -> str:
|
||||
wallet_ids = await get_wallets_ids(user_id=user_id, conn=conn) or [
|
||||
"no-wallets-for-user"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import json
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
from loguru import logger
|
||||
|
||||
@@ -14,7 +14,7 @@ from lnbits.settings import (
|
||||
)
|
||||
|
||||
|
||||
async def get_super_settings() -> Optional[SuperSettings]:
|
||||
async def get_super_settings() -> SuperSettings | None:
|
||||
data = await get_settings_by_tag("core")
|
||||
if data:
|
||||
super_user = await get_settings_field("super_user")
|
||||
@@ -24,7 +24,7 @@ async def get_super_settings() -> Optional[SuperSettings]:
|
||||
return None
|
||||
|
||||
|
||||
async def get_admin_settings(is_super_user: bool = False) -> Optional[AdminSettings]:
|
||||
async def get_admin_settings(is_super_user: bool = False) -> AdminSettings | None:
|
||||
sets = await get_super_settings()
|
||||
if not sets:
|
||||
return None
|
||||
@@ -41,7 +41,7 @@ async def get_admin_settings(is_super_user: bool = False) -> Optional[AdminSetti
|
||||
|
||||
|
||||
async def update_admin_settings(
|
||||
data: EditableSettings, tag: Optional[str] = "core"
|
||||
data: EditableSettings, tag: str | None = "core"
|
||||
) -> None:
|
||||
editable_settings = await get_settings_by_tag("core") or {}
|
||||
editable_settings.update(data.dict(exclude_unset=True))
|
||||
@@ -61,7 +61,7 @@ async def update_super_user(super_user: str) -> SuperSettings:
|
||||
return settings
|
||||
|
||||
|
||||
async def delete_admin_settings(tag: Optional[str] = "core") -> None:
|
||||
async def delete_admin_settings(tag: str | None = "core") -> None:
|
||||
await db.execute(
|
||||
"DELETE FROM system_settings WHERE tag = :tag",
|
||||
{"tag": tag},
|
||||
@@ -93,8 +93,8 @@ async def create_admin_settings(super_user: str, new_settings: dict) -> SuperSet
|
||||
|
||||
|
||||
async def get_settings_field(
|
||||
id_: str, tag: Optional[str] = "core"
|
||||
) -> Optional[SettingsField]:
|
||||
id_: str, tag: str | None = "core"
|
||||
) -> SettingsField | None:
|
||||
|
||||
row: dict = await db.fetchone(
|
||||
"""
|
||||
@@ -108,9 +108,7 @@ async def get_settings_field(
|
||||
return SettingsField(id=row["id"], value=json.loads(row["value"]), tag=row["tag"])
|
||||
|
||||
|
||||
async def set_settings_field(
|
||||
id_: str, value: Optional[Any], tag: Optional[str] = "core"
|
||||
):
|
||||
async def set_settings_field(id_: str, value: Any | None, tag: str | None = "core"):
|
||||
value = json.dumps(value) if value is not None else None
|
||||
await db.execute(
|
||||
"""
|
||||
@@ -122,7 +120,7 @@ async def set_settings_field(
|
||||
)
|
||||
|
||||
|
||||
async def get_settings_by_tag(tag: str) -> Optional[dict[str, Any]]:
|
||||
async def get_settings_by_tag(tag: str) -> dict[str, Any] | None:
|
||||
rows: list[dict] = await db.fetchall(
|
||||
"SELECT * FROM system_settings WHERE tag = :tag", {"tag": tag}
|
||||
)
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Optional
|
||||
|
||||
import shortuuid
|
||||
|
||||
from lnbits.core.db import db
|
||||
@@ -19,7 +17,7 @@ async def create_tinyurl(domain: str, endless: bool, wallet: str):
|
||||
return await get_tinyurl(tinyurl_id)
|
||||
|
||||
|
||||
async def get_tinyurl(tinyurl_id: str) -> Optional[TinyURL]:
|
||||
async def get_tinyurl(tinyurl_id: str) -> TinyURL | None:
|
||||
return await db.fetchone(
|
||||
"SELECT * FROM tiny_url WHERE id = :tinyurl",
|
||||
{"tinyurl": tinyurl_id},
|
||||
|
||||
+20
-22
@@ -1,6 +1,6 @@
|
||||
from datetime import datetime, timezone
|
||||
from time import time
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
from uuid import uuid4
|
||||
|
||||
from lnbits.core.crud.extensions import get_user_active_extensions_ids
|
||||
@@ -18,8 +18,8 @@ from ..models import (
|
||||
|
||||
|
||||
async def create_account(
|
||||
account: Optional[Account] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
account: Account | None = None,
|
||||
conn: Connection | None = None,
|
||||
) -> Account:
|
||||
if account:
|
||||
account.validate_fields()
|
||||
@@ -36,7 +36,7 @@ async def update_account(account: Account) -> Account:
|
||||
return account
|
||||
|
||||
|
||||
async def delete_account(user_id: str, conn: Optional[Connection] = None) -> None:
|
||||
async def delete_account(user_id: str, conn: Connection | None = None) -> None:
|
||||
await (conn or db).execute(
|
||||
"DELETE from accounts WHERE id = :user",
|
||||
{"user": user_id},
|
||||
@@ -44,8 +44,8 @@ async def delete_account(user_id: str, conn: Optional[Connection] = None) -> Non
|
||||
|
||||
|
||||
async def get_accounts(
|
||||
filters: Optional[Filters[AccountFilters]] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
filters: Filters[AccountFilters] | None = None,
|
||||
conn: Connection | None = None,
|
||||
) -> Page[AccountOverview]:
|
||||
where_clauses = []
|
||||
values: dict[str, Any] = {}
|
||||
@@ -92,9 +92,7 @@ async def get_accounts(
|
||||
)
|
||||
|
||||
|
||||
async def get_account(
|
||||
user_id: str, conn: Optional[Connection] = None
|
||||
) -> Optional[Account]:
|
||||
async def get_account(user_id: str, conn: Connection | None = None) -> Account | None:
|
||||
if len(user_id) == 0:
|
||||
return None
|
||||
return await (conn or db).fetchone(
|
||||
@@ -106,7 +104,7 @@ async def get_account(
|
||||
|
||||
async def delete_accounts_no_wallets(
|
||||
time_delta: int,
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
) -> None:
|
||||
delta = int(time()) - time_delta
|
||||
await (conn or db).execute(
|
||||
@@ -125,8 +123,8 @@ async def delete_accounts_no_wallets(
|
||||
|
||||
|
||||
async def get_account_by_username(
|
||||
username: str, conn: Optional[Connection] = None
|
||||
) -> Optional[Account]:
|
||||
username: str, conn: Connection | None = None
|
||||
) -> Account | None:
|
||||
if len(username) == 0:
|
||||
return None
|
||||
return await (conn or db).fetchone(
|
||||
@@ -137,8 +135,8 @@ async def get_account_by_username(
|
||||
|
||||
|
||||
async def get_account_by_pubkey(
|
||||
pubkey: str, conn: Optional[Connection] = None
|
||||
) -> Optional[Account]:
|
||||
pubkey: str, conn: Connection | None = None
|
||||
) -> Account | None:
|
||||
return await (conn or db).fetchone(
|
||||
"SELECT * FROM accounts WHERE LOWER(pubkey) = :pubkey",
|
||||
{"pubkey": pubkey.lower()},
|
||||
@@ -147,8 +145,8 @@ async def get_account_by_pubkey(
|
||||
|
||||
|
||||
async def get_account_by_email(
|
||||
email: str, conn: Optional[Connection] = None
|
||||
) -> Optional[Account]:
|
||||
email: str, conn: Connection | None = None
|
||||
) -> Account | None:
|
||||
if len(email) == 0:
|
||||
return None
|
||||
return await (conn or db).fetchone(
|
||||
@@ -159,8 +157,8 @@ async def get_account_by_email(
|
||||
|
||||
|
||||
async def get_account_by_username_or_email(
|
||||
username_or_email: str, conn: Optional[Connection] = None
|
||||
) -> Optional[Account]:
|
||||
username_or_email: str, conn: Connection | None = None
|
||||
) -> Account | None:
|
||||
return await (conn or db).fetchone(
|
||||
"""
|
||||
SELECT * FROM accounts
|
||||
@@ -171,7 +169,7 @@ async def get_account_by_username_or_email(
|
||||
)
|
||||
|
||||
|
||||
async def get_user(user_id: str, conn: Optional[Connection] = None) -> Optional[User]:
|
||||
async def get_user(user_id: str, conn: Connection | None = None) -> User | None:
|
||||
account = await get_account(user_id, conn)
|
||||
if not account:
|
||||
return None
|
||||
@@ -179,8 +177,8 @@ async def get_user(user_id: str, conn: Optional[Connection] = None) -> Optional[
|
||||
|
||||
|
||||
async def get_user_from_account(
|
||||
account: Account, conn: Optional[Connection] = None
|
||||
) -> Optional[User]:
|
||||
account: Account, conn: Connection | None = None
|
||||
) -> User | None:
|
||||
extensions = await get_user_active_extensions_ids(account.id, conn)
|
||||
wallets = await get_wallets(account.id, False, conn=conn)
|
||||
return User(
|
||||
@@ -207,7 +205,7 @@ async def update_user_access_control_list(user_acls: UserAcls):
|
||||
|
||||
|
||||
async def get_user_access_control_lists(
|
||||
user_id: str, conn: Optional[Connection] = None
|
||||
user_id: str, conn: Connection | None = None
|
||||
) -> UserAcls:
|
||||
user_acls = await (conn or db).fetchone(
|
||||
"SELECT id, access_control_list FROM accounts WHERE id = :id",
|
||||
|
||||
+19
-22
@@ -1,6 +1,5 @@
|
||||
from datetime import datetime, timezone
|
||||
from time import time
|
||||
from typing import Optional
|
||||
from uuid import uuid4
|
||||
|
||||
from lnbits.core.db import db
|
||||
@@ -14,8 +13,8 @@ from ..models import Wallet
|
||||
async def create_wallet(
|
||||
*,
|
||||
user_id: str,
|
||||
wallet_name: Optional[str] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
wallet_name: str | None = None,
|
||||
conn: Connection | None = None,
|
||||
) -> Wallet:
|
||||
wallet_id = uuid4().hex
|
||||
wallet = Wallet(
|
||||
@@ -32,7 +31,7 @@ async def create_wallet(
|
||||
|
||||
async def update_wallet(
|
||||
wallet: Wallet,
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
) -> Wallet:
|
||||
wallet.updated_at = datetime.now(timezone.utc)
|
||||
await (conn or db).update("wallets", wallet)
|
||||
@@ -44,7 +43,7 @@ async def delete_wallet(
|
||||
user_id: str,
|
||||
wallet_id: str,
|
||||
deleted: bool = True,
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
) -> None:
|
||||
now = int(time())
|
||||
await (conn or db).execute(
|
||||
@@ -58,9 +57,7 @@ async def delete_wallet(
|
||||
)
|
||||
|
||||
|
||||
async def force_delete_wallet(
|
||||
wallet_id: str, conn: Optional[Connection] = None
|
||||
) -> None:
|
||||
async def force_delete_wallet(wallet_id: str, conn: Connection | None = None) -> None:
|
||||
await (conn or db).execute(
|
||||
"DELETE FROM wallets WHERE id = :wallet",
|
||||
{"wallet": wallet_id},
|
||||
@@ -68,8 +65,8 @@ async def force_delete_wallet(
|
||||
|
||||
|
||||
async def delete_wallet_by_id(
|
||||
wallet_id: str, conn: Optional[Connection] = None
|
||||
) -> Optional[int]:
|
||||
wallet_id: str, conn: Connection | None = None
|
||||
) -> int | None:
|
||||
now = int(time())
|
||||
result = await (conn or db).execute(
|
||||
# Timestamp placeholder is safe from SQL injection (not user input)
|
||||
@@ -83,13 +80,13 @@ async def delete_wallet_by_id(
|
||||
return result.rowcount
|
||||
|
||||
|
||||
async def remove_deleted_wallets(conn: Optional[Connection] = None) -> None:
|
||||
async def remove_deleted_wallets(conn: Connection | None = None) -> None:
|
||||
await (conn or db).execute("DELETE FROM wallets WHERE deleted = true")
|
||||
|
||||
|
||||
async def delete_unused_wallets(
|
||||
time_delta: int,
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
) -> None:
|
||||
delta = int(time()) - time_delta
|
||||
await (conn or db).execute(
|
||||
@@ -107,8 +104,8 @@ async def delete_unused_wallets(
|
||||
|
||||
|
||||
async def get_wallet(
|
||||
wallet_id: str, deleted: Optional[bool] = None, conn: Optional[Connection] = None
|
||||
) -> Optional[Wallet]:
|
||||
wallet_id: str, deleted: bool | None = None, conn: Connection | None = None
|
||||
) -> Wallet | None:
|
||||
query = """
|
||||
SELECT *, COALESCE((
|
||||
SELECT balance FROM balances WHERE wallet_id = wallets.id
|
||||
@@ -125,7 +122,7 @@ async def get_wallet(
|
||||
|
||||
|
||||
async def get_wallets(
|
||||
user_id: str, deleted: Optional[bool] = None, conn: Optional[Connection] = None
|
||||
user_id: str, deleted: bool | None = None, conn: Connection | None = None
|
||||
) -> list[Wallet]:
|
||||
query = """
|
||||
SELECT *, COALESCE((
|
||||
@@ -144,9 +141,9 @@ async def get_wallets(
|
||||
|
||||
async def get_wallets_paginated(
|
||||
user_id: str,
|
||||
deleted: Optional[bool] = None,
|
||||
filters: Optional[Filters[WalletsFilters]] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
deleted: bool | None = None,
|
||||
filters: Filters[WalletsFilters] | None = None,
|
||||
conn: Connection | None = None,
|
||||
) -> Page[Wallet]:
|
||||
if deleted is None:
|
||||
deleted = False
|
||||
@@ -166,7 +163,7 @@ async def get_wallets_paginated(
|
||||
|
||||
|
||||
async def get_wallets_ids(
|
||||
user_id: str, deleted: Optional[bool] = None, conn: Optional[Connection] = None
|
||||
user_id: str, deleted: bool | None = None, conn: Connection | None = None
|
||||
) -> list[str]:
|
||||
query = """SELECT id FROM wallets WHERE "user" = :user"""
|
||||
if deleted is not None:
|
||||
@@ -186,8 +183,8 @@ async def get_wallets_count():
|
||||
|
||||
async def get_wallet_for_key(
|
||||
key: str,
|
||||
conn: Optional[Connection] = None,
|
||||
) -> Optional[Wallet]:
|
||||
conn: Connection | None = None,
|
||||
) -> Wallet | None:
|
||||
return await (conn or db).fetchone(
|
||||
"""
|
||||
SELECT *, COALESCE((
|
||||
@@ -201,7 +198,7 @@ async def get_wallet_for_key(
|
||||
)
|
||||
|
||||
|
||||
async def get_total_balance(conn: Optional[Connection] = None):
|
||||
async def get_total_balance(conn: Connection | None = None):
|
||||
result = await (conn or db).execute("SELECT SUM(balance) as balance FROM balances")
|
||||
row = result.mappings().first()
|
||||
return row.get("balance", 0) or 0
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Optional
|
||||
|
||||
from lnbits.core.db import db
|
||||
|
||||
from ..models import WebPushSubscription
|
||||
@@ -7,7 +5,7 @@ from ..models import WebPushSubscription
|
||||
|
||||
async def get_webpush_subscription(
|
||||
endpoint: str, user: str
|
||||
) -> Optional[WebPushSubscription]:
|
||||
) -> WebPushSubscription | None:
|
||||
return await db.fetchone(
|
||||
"""
|
||||
SELECT * FROM webpush_subscriptions
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import importlib
|
||||
import re
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
from urllib.parse import urlparse
|
||||
from uuid import UUID
|
||||
|
||||
@@ -20,7 +20,7 @@ from lnbits.settings import settings
|
||||
|
||||
|
||||
async def migrate_extension_database(
|
||||
ext: InstallableExtension, current_version: Optional[DbVersion] = None
|
||||
ext: InstallableExtension, current_version: DbVersion | None = None
|
||||
):
|
||||
|
||||
try:
|
||||
@@ -38,7 +38,7 @@ async def run_migration(
|
||||
db: Connection,
|
||||
migrations_module: Any,
|
||||
db_name: str,
|
||||
current_version: Optional[DbVersion] = None,
|
||||
current_version: DbVersion | None = None,
|
||||
):
|
||||
matcher = re.compile(r"^m(\d\d\d)_")
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from time import time
|
||||
from typing import Optional
|
||||
|
||||
from lnurl import LnAddress, Lnurl, LnurlPayResponse
|
||||
from pydantic import BaseModel, Field
|
||||
@@ -9,9 +8,9 @@ class CreateLnurlPayment(BaseModel):
|
||||
res: LnurlPayResponse | None = None
|
||||
lnurl: Lnurl | LnAddress | None = None
|
||||
amount: int
|
||||
comment: Optional[str] = None
|
||||
unit: Optional[str] = None
|
||||
internal_memo: Optional[str] = None
|
||||
comment: str | None = None
|
||||
unit: str | None = None
|
||||
internal_memo: str | None = None
|
||||
|
||||
|
||||
class CreateLnurlWithdraw(BaseModel):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Callable
|
||||
from collections.abc import Callable
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import asyncio
|
||||
import importlib
|
||||
from typing import Optional
|
||||
|
||||
from loguru import logger
|
||||
|
||||
@@ -145,7 +144,7 @@ async def start_extension_background_work(ext_id: str) -> bool:
|
||||
|
||||
|
||||
async def get_valid_extensions(
|
||||
include_deactivated: Optional[bool] = True,
|
||||
include_deactivated: bool | None = True,
|
||||
) -> list[Extension]:
|
||||
installed_extensions = await get_installed_extensions()
|
||||
valid_extensions = [Extension.from_installable_ext(e) for e in installed_extensions]
|
||||
@@ -164,8 +163,8 @@ async def get_valid_extensions(
|
||||
|
||||
|
||||
async def get_valid_extension(
|
||||
ext_id: str, include_deactivated: Optional[bool] = True
|
||||
) -> Optional[Extension]:
|
||||
ext_id: str, include_deactivated: bool | None = True
|
||||
) -> Extension | None:
|
||||
ext = await get_installed_extension(ext_id)
|
||||
if not ext:
|
||||
return None
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import hashlib
|
||||
import hmac
|
||||
import time
|
||||
from typing import Optional
|
||||
|
||||
from loguru import logger
|
||||
|
||||
@@ -15,7 +14,7 @@ from lnbits.settings import settings
|
||||
|
||||
|
||||
async def handle_fiat_payment_confirmation(
|
||||
payment: Payment, conn: Optional[Connection] = None
|
||||
payment: Payment, conn: Connection | None = None
|
||||
):
|
||||
try:
|
||||
await _credit_fiat_service_fee_wallet(payment, conn=conn)
|
||||
@@ -29,7 +28,7 @@ async def handle_fiat_payment_confirmation(
|
||||
|
||||
|
||||
async def _credit_fiat_service_fee_wallet(
|
||||
payment: Payment, conn: Optional[Connection] = None
|
||||
payment: Payment, conn: Connection | None = None
|
||||
):
|
||||
fiat_provider_name = payment.fiat_provider
|
||||
if not fiat_provider_name:
|
||||
@@ -66,7 +65,7 @@ async def _credit_fiat_service_fee_wallet(
|
||||
|
||||
|
||||
async def _debit_fiat_service_faucet_wallet(
|
||||
payment: Payment, conn: Optional[Connection] = None
|
||||
payment: Payment, conn: Connection | None = None
|
||||
):
|
||||
fiat_provider_name = payment.fiat_provider
|
||||
if not fiat_provider_name:
|
||||
@@ -129,8 +128,8 @@ async def handle_stripe_event(event: dict):
|
||||
|
||||
def check_stripe_signature(
|
||||
payload: bytes,
|
||||
sig_header: Optional[str],
|
||||
secret: Optional[str],
|
||||
sig_header: str | None,
|
||||
secret: str | None,
|
||||
tolerance_seconds=300,
|
||||
):
|
||||
if not sig_header:
|
||||
|
||||
@@ -4,7 +4,6 @@ import smtplib
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from http import HTTPStatus
|
||||
from typing import Optional
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
@@ -71,7 +70,7 @@ async def process_next_notification() -> None:
|
||||
|
||||
async def send_admin_notification(
|
||||
message: str,
|
||||
message_type: Optional[str] = None,
|
||||
message_type: str | None = None,
|
||||
) -> None:
|
||||
return await send_notification(
|
||||
settings.lnbits_telegram_notifications_chat_id,
|
||||
@@ -85,7 +84,7 @@ async def send_admin_notification(
|
||||
async def send_user_notification(
|
||||
user_notifications: UserNotifications,
|
||||
message: str,
|
||||
message_type: Optional[str] = None,
|
||||
message_type: str | None = None,
|
||||
) -> None:
|
||||
|
||||
email_address = (
|
||||
@@ -110,7 +109,7 @@ async def send_notification(
|
||||
nostr_identifiers: list[str] | None,
|
||||
email_addresses: list[str] | None,
|
||||
message: str,
|
||||
message_type: Optional[str] = None,
|
||||
message_type: str | None = None,
|
||||
) -> None:
|
||||
try:
|
||||
if telegram_chat_id and settings.is_telegram_notifications_configured():
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import asyncio
|
||||
import time
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Optional
|
||||
|
||||
from bolt11 import Bolt11, MilliSatoshi, Tags
|
||||
from bolt11 import decode as bolt11_decode
|
||||
@@ -58,11 +57,11 @@ async def pay_invoice(
|
||||
*,
|
||||
wallet_id: str,
|
||||
payment_request: str,
|
||||
max_sat: Optional[int] = None,
|
||||
extra: Optional[dict] = None,
|
||||
max_sat: int | None = None,
|
||||
extra: dict | None = None,
|
||||
description: str = "",
|
||||
tag: str = "",
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
) -> Payment:
|
||||
if settings.lnbits_only_allow_incoming_payments:
|
||||
raise PaymentError("Only incoming payments allowed.", status="failed")
|
||||
@@ -110,7 +109,7 @@ async def create_payment_request(
|
||||
|
||||
|
||||
async def create_fiat_invoice(
|
||||
wallet_id: str, invoice_data: CreateInvoice, conn: Optional[Connection] = None
|
||||
wallet_id: str, invoice_data: CreateInvoice, conn: Connection | None = None
|
||||
):
|
||||
fiat_provider_name = invoice_data.fiat_provider
|
||||
if not fiat_provider_name:
|
||||
@@ -231,16 +230,16 @@ async def create_invoice(
|
||||
*,
|
||||
wallet_id: str,
|
||||
amount: float,
|
||||
currency: Optional[str] = "sat",
|
||||
currency: str | None = "sat",
|
||||
memo: str,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
expiry: Optional[int] = None,
|
||||
extra: Optional[dict] = None,
|
||||
webhook: Optional[str] = None,
|
||||
internal: Optional[bool] = False,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
expiry: int | None = None,
|
||||
extra: dict | None = None,
|
||||
webhook: str | None = None,
|
||||
internal: bool | None = False,
|
||||
payment_hash: str | None = None,
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
) -> Payment:
|
||||
if not amount > 0:
|
||||
raise InvoiceError("Amountless invoices not supported.", status="failed")
|
||||
@@ -427,7 +426,7 @@ def service_fee_fiat(amount_msat: int, fiat_provider_name: str) -> int:
|
||||
async def update_wallet_balance(
|
||||
wallet: Wallet,
|
||||
amount: int,
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
):
|
||||
if amount == 0:
|
||||
raise ValueError("Amount cannot be 0.")
|
||||
@@ -486,14 +485,14 @@ async def update_wallet_balance(
|
||||
|
||||
|
||||
async def check_wallet_limits(
|
||||
wallet_id: str, amount_msat: int, conn: Optional[Connection] = None
|
||||
wallet_id: str, amount_msat: int, conn: Connection | None = None
|
||||
):
|
||||
await check_time_limit_between_transactions(wallet_id, conn)
|
||||
await check_wallet_daily_withdraw_limit(wallet_id, amount_msat, conn)
|
||||
|
||||
|
||||
async def check_time_limit_between_transactions(
|
||||
wallet_id: str, conn: Optional[Connection] = None
|
||||
wallet_id: str, conn: Connection | None = None
|
||||
):
|
||||
limit = settings.lnbits_wallet_limit_secs_between_trans
|
||||
if not limit or limit <= 0:
|
||||
@@ -513,7 +512,7 @@ async def check_time_limit_between_transactions(
|
||||
|
||||
|
||||
async def check_wallet_daily_withdraw_limit(
|
||||
wallet_id: str, amount_msat: int, conn: Optional[Connection] = None
|
||||
wallet_id: str, amount_msat: int, conn: Connection | None = None
|
||||
):
|
||||
limit = settings.lnbits_wallet_limit_daily_max_withdraw
|
||||
if not limit:
|
||||
@@ -546,8 +545,8 @@ async def check_wallet_daily_withdraw_limit(
|
||||
async def calculate_fiat_amounts(
|
||||
amount: float,
|
||||
wallet: Wallet,
|
||||
currency: Optional[str] = None,
|
||||
extra: Optional[dict] = None,
|
||||
currency: str | None = None,
|
||||
extra: dict | None = None,
|
||||
) -> tuple[int, dict]:
|
||||
wallet_currency = wallet.currency or settings.lnbits_default_accounting_currency
|
||||
fiat_amounts: dict = extra or {}
|
||||
@@ -582,9 +581,9 @@ async def calculate_fiat_amounts(
|
||||
|
||||
|
||||
async def check_transaction_status(
|
||||
wallet_id: str, payment_hash: str, conn: Optional[Connection] = None
|
||||
wallet_id: str, payment_hash: str, conn: Connection | None = None
|
||||
) -> PaymentStatus:
|
||||
payment: Optional[Payment] = await get_wallet_payment(
|
||||
payment: Payment | None = await get_wallet_payment(
|
||||
wallet_id, payment_hash, conn=conn
|
||||
)
|
||||
if not payment:
|
||||
@@ -598,7 +597,7 @@ async def check_transaction_status(
|
||||
|
||||
async def get_payments_daily_stats(
|
||||
filters: Filters[PaymentFilters],
|
||||
user_id: Optional[str] = None,
|
||||
user_id: str | None = None,
|
||||
) -> list[PaymentDailyStats]:
|
||||
data_in, data_out = await get_daily_stats(filters, user_id=user_id)
|
||||
balance_total: float = 0
|
||||
@@ -647,7 +646,7 @@ async def get_payments_daily_stats(
|
||||
async def _pay_invoice(
|
||||
wallet_id: str,
|
||||
create_payment_model: CreatePayment,
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
):
|
||||
async with payment_lock:
|
||||
if wallet_id not in wallets_payments_lock:
|
||||
@@ -670,8 +669,8 @@ async def _pay_invoice(
|
||||
async def _pay_internal_invoice(
|
||||
wallet: Wallet,
|
||||
create_payment_model: CreatePayment,
|
||||
conn: Optional[Connection] = None,
|
||||
) -> Optional[Payment]:
|
||||
conn: Connection | None = None,
|
||||
) -> Payment | None:
|
||||
"""
|
||||
Pay an internal payment.
|
||||
returns None if the payment is not internal.
|
||||
@@ -738,7 +737,7 @@ async def _pay_internal_invoice(
|
||||
async def _pay_external_invoice(
|
||||
wallet: Wallet,
|
||||
create_payment_model: CreatePayment,
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
) -> Payment:
|
||||
checking_id = create_payment_model.payment_hash
|
||||
amount_msat = create_payment_model.amount_msat
|
||||
@@ -807,7 +806,7 @@ async def _pay_external_invoice(
|
||||
async def update_payment_success_status(
|
||||
payment: Payment,
|
||||
status: PaymentStatus,
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
) -> Payment:
|
||||
if status.success:
|
||||
service_fee_msat = service_fee(payment.amount, internal=False)
|
||||
@@ -831,7 +830,7 @@ async def _fundingsource_pay_invoice(
|
||||
|
||||
|
||||
async def _verify_external_payment(
|
||||
payment: Payment, conn: Optional[Connection] = None
|
||||
payment: Payment, conn: Connection | None = None
|
||||
) -> Payment:
|
||||
# fail on pending payments
|
||||
if payment.pending:
|
||||
@@ -862,7 +861,7 @@ async def _check_wallet_for_payment(
|
||||
wallet_id: str,
|
||||
tag: str,
|
||||
amount_msat: int,
|
||||
conn: Optional[Connection] = None,
|
||||
conn: Connection | None = None,
|
||||
):
|
||||
wallet = await get_wallet(wallet_id, conn=conn)
|
||||
if not wallet:
|
||||
@@ -878,7 +877,7 @@ async def _check_wallet_for_payment(
|
||||
|
||||
|
||||
def _validate_payment_request(
|
||||
payment_request: str, max_sat: Optional[int] = None
|
||||
payment_request: str, max_sat: int | None = None
|
||||
) -> Bolt11:
|
||||
try:
|
||||
invoice = bolt11_decode(payment_request)
|
||||
@@ -901,7 +900,7 @@ def _validate_payment_request(
|
||||
|
||||
|
||||
async def _credit_service_fee_wallet(
|
||||
wallet: Wallet, payment: Payment, conn: Optional[Connection] = None
|
||||
wallet: Wallet, payment: Payment, conn: Connection | None = None
|
||||
):
|
||||
service_fee_msat = service_fee(payment.amount, internal=payment.is_internal)
|
||||
if not settings.lnbits_service_fee_wallet or not service_fee_msat:
|
||||
@@ -927,7 +926,7 @@ async def _credit_service_fee_wallet(
|
||||
|
||||
|
||||
async def _check_fiat_invoice_limits(
|
||||
amount_sat: int, fiat_provider_name: str, conn: Optional[Connection] = None
|
||||
amount_sat: int, fiat_provider_name: str, conn: Connection | None = None
|
||||
):
|
||||
limits = settings.get_fiat_provider_limits(fiat_provider_name)
|
||||
if not limits:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from uuid import uuid4
|
||||
|
||||
from loguru import logger
|
||||
@@ -37,7 +36,7 @@ from .settings import update_cached_settings
|
||||
|
||||
|
||||
async def create_user_account(
|
||||
account: Optional[Account] = None, wallet_name: Optional[str] = None
|
||||
account: Account | None = None, wallet_name: str | None = None
|
||||
) -> User:
|
||||
if not settings.new_accounts_allowed:
|
||||
raise ValueError("Account creation is disabled.")
|
||||
@@ -46,9 +45,9 @@ async def create_user_account(
|
||||
|
||||
|
||||
async def create_user_account_no_ckeck(
|
||||
account: Optional[Account] = None,
|
||||
wallet_name: Optional[str] = None,
|
||||
default_exts: Optional[list[str]] = None,
|
||||
account: Account | None = None,
|
||||
wallet_name: str | None = None,
|
||||
default_exts: list[str] | None = None,
|
||||
) -> User:
|
||||
|
||||
if account:
|
||||
@@ -165,12 +164,12 @@ async def check_admin_settings():
|
||||
settings.first_install = True
|
||||
|
||||
logger.success(
|
||||
"✔️ Admin UI is enabled. run `poetry run lnbits-cli superuser` "
|
||||
"✔️ Admin UI is enabled. run `uv run lnbits-cli superuser` "
|
||||
"to get the superuser."
|
||||
)
|
||||
|
||||
|
||||
async def init_admin_settings(super_user: Optional[str] = None) -> SuperSettings:
|
||||
async def init_admin_settings(super_user: str | None = None) -> SuperSettings:
|
||||
account = None
|
||||
if super_user:
|
||||
account = await get_account(super_user)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import asyncio
|
||||
import traceback
|
||||
from collections.abc import Coroutine
|
||||
from typing import Callable
|
||||
from collections.abc import Callable, Coroutine
|
||||
|
||||
from loguru import logger
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ from pathlib import Path
|
||||
from shutil import make_archive, move
|
||||
from subprocess import Popen
|
||||
from tempfile import NamedTemporaryFile
|
||||
from typing import IO, Optional
|
||||
from typing import IO
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import filetype
|
||||
@@ -71,10 +71,10 @@ async def api_test_email():
|
||||
)
|
||||
|
||||
|
||||
@admin_router.get("/api/v1/settings", response_model=Optional[AdminSettings])
|
||||
@admin_router.get("/api/v1/settings")
|
||||
async def api_get_settings(
|
||||
user: User = Depends(check_admin),
|
||||
) -> Optional[AdminSettings]:
|
||||
) -> AdminSettings | None:
|
||||
admin_settings = await get_admin_settings(user.super_user)
|
||||
return admin_settings
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import base64
|
||||
import importlib
|
||||
import json
|
||||
from collections.abc import Callable
|
||||
from http import HTTPStatus
|
||||
from time import time
|
||||
from typing import Callable, Optional
|
||||
from uuid import uuid4
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
@@ -238,7 +238,7 @@ async def api_delete_user_api_token(
|
||||
|
||||
@auth_router.get("/{provider}", description="SSO Provider")
|
||||
async def login_with_sso_provider(
|
||||
request: Request, provider: str, user_id: Optional[str] = None
|
||||
request: Request, provider: str, user_id: str | None = None
|
||||
):
|
||||
provider_sso = _new_sso(provider)
|
||||
if not provider_sso:
|
||||
@@ -319,7 +319,7 @@ async def update_pubkey(
|
||||
data: UpdateUserPubkey,
|
||||
user: User = Depends(check_user_exists),
|
||||
payload: AccessTokenPayload = Depends(access_token_payload),
|
||||
) -> Optional[User]:
|
||||
) -> User | None:
|
||||
if data.user_id != user.id:
|
||||
raise ValueError("Invalid user ID.")
|
||||
|
||||
@@ -345,7 +345,7 @@ async def update_password(
|
||||
data: UpdateUserPassword,
|
||||
user: User = Depends(check_user_exists),
|
||||
payload: AccessTokenPayload = Depends(access_token_payload),
|
||||
) -> Optional[User]:
|
||||
) -> User | None:
|
||||
_validate_auth_timeout(payload.auth_time)
|
||||
if data.user_id != user.id:
|
||||
raise ValueError("Invalid user ID.")
|
||||
@@ -419,7 +419,7 @@ async def reset_password(data: ResetUserPassword) -> JSONResponse:
|
||||
@auth_router.put("/update")
|
||||
async def update(
|
||||
data: UpdateUser, user: User = Depends(check_user_exists)
|
||||
) -> Optional[User]:
|
||||
) -> User | None:
|
||||
if data.user_id != user.id:
|
||||
raise HTTPException(HTTPStatus.BAD_REQUEST, "Invalid user ID.")
|
||||
if data.username and not is_valid_username(data.username):
|
||||
@@ -461,7 +461,7 @@ async def first_install(data: UpdateSuperuserPassword) -> JSONResponse:
|
||||
return _auth_success_response(account.username, account.id, account.email)
|
||||
|
||||
|
||||
async def _handle_sso_login(userinfo: OpenID, verified_user_id: Optional[str] = None):
|
||||
async def _handle_sso_login(userinfo: OpenID, verified_user_id: str | None = None):
|
||||
email = userinfo.email
|
||||
if not email or not is_valid_email_address(email):
|
||||
raise HTTPException(HTTPStatus.BAD_REQUEST, "Invalid email.")
|
||||
@@ -490,9 +490,9 @@ async def _handle_sso_login(userinfo: OpenID, verified_user_id: Optional[str] =
|
||||
|
||||
|
||||
def _auth_success_response(
|
||||
username: Optional[str] = None,
|
||||
user_id: Optional[str] = None,
|
||||
email: Optional[str] = None,
|
||||
username: str | None = None,
|
||||
user_id: str | None = None,
|
||||
email: str | None = None,
|
||||
) -> JSONResponse:
|
||||
payload = AccessTokenPayload(
|
||||
sub=username or "", usr=user_id, email=email, auth_time=int(time())
|
||||
@@ -533,7 +533,7 @@ def _auth_redirect_response(path: str, email: str) -> RedirectResponse:
|
||||
return response
|
||||
|
||||
|
||||
def _new_sso(provider: str) -> Optional[SSOBase]:
|
||||
def _new_sso(provider: str) -> SSOBase | None:
|
||||
try:
|
||||
if not settings.is_auth_method_allowed(AuthMethods(f"{provider}-auth")):
|
||||
return None
|
||||
@@ -610,7 +610,7 @@ def _nostr_nip98_event(request: Request) -> dict:
|
||||
|
||||
|
||||
def _check_nostr_event_tags(event: dict):
|
||||
method: Optional[str] = next((v for k, v in event["tags"] if k == "method"), None)
|
||||
method: str | None = next((v for k, v in event["tags"] if k == "method"), None)
|
||||
if not method:
|
||||
raise ValueError("Tag 'method' is missing.")
|
||||
if not method.upper() == "POST":
|
||||
@@ -625,7 +625,7 @@ def _check_nostr_event_tags(event: dict):
|
||||
raise ValueError(f"Invalid value for tag 'u': '{url}'.")
|
||||
|
||||
|
||||
def _validate_auth_timeout(auth_time: Optional[int] = 0):
|
||||
def _validate_auth_timeout(auth_time: int | None = 0):
|
||||
if abs(time() - (auth_time or 0)) > settings.auth_credetials_update_threshold:
|
||||
raise HTTPException(
|
||||
HTTPStatus.BAD_REQUEST,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from http import HTTPStatus
|
||||
from typing import Annotated, Optional, Union
|
||||
from typing import Annotated
|
||||
from urllib.parse import urlencode, urlparse
|
||||
|
||||
import httpx
|
||||
@@ -161,9 +161,9 @@ async def extensions(request: Request, user: User = Depends(check_user_exists)):
|
||||
)
|
||||
async def wallet(
|
||||
request: Request,
|
||||
lnbits_last_active_wallet: Annotated[Union[str, None], Cookie()] = None,
|
||||
lnbits_last_active_wallet: Annotated[str | None, Cookie()] = None,
|
||||
user: User = Depends(check_user_exists),
|
||||
wal: Optional[UUID4] = Query(None),
|
||||
wal: UUID4 | None = Query(None),
|
||||
):
|
||||
if wal:
|
||||
wallet = await get_wallet(wal.hex)
|
||||
|
||||
@@ -60,7 +60,7 @@ async def _handle(lnurl: str) -> LnurlResponseModel:
|
||||
)
|
||||
async def api_lnurlscan(code: str) -> LnurlResponseModel:
|
||||
res = await _handle(code)
|
||||
if isinstance(res, (LnurlPayResponse, LnurlWithdrawResponse, LnurlAuthResponse)):
|
||||
if isinstance(res, LnurlPayResponse | LnurlWithdrawResponse | LnurlAuthResponse):
|
||||
check_callback_url(res.callback)
|
||||
return res
|
||||
|
||||
@@ -169,7 +169,7 @@ async def api_payment_pay_with_nfc(
|
||||
except (LnurlResponseException, Exception) as exc:
|
||||
logger.warning(exc)
|
||||
return LnurlErrorResponse(reason=str(exc))
|
||||
if not isinstance(res2, (LnurlSuccessResponse, LnurlErrorResponse)):
|
||||
if not isinstance(res2, LnurlSuccessResponse | LnurlErrorResponse):
|
||||
return LnurlErrorResponse(reason="Invalid LNURL-withdraw response.")
|
||||
|
||||
return res2
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from http import HTTPStatus
|
||||
from typing import Optional
|
||||
|
||||
import httpx
|
||||
from fastapi import APIRouter, Body, Depends, HTTPException
|
||||
@@ -89,14 +88,14 @@ async def api_get_public_info(node: Node = Depends(require_node)) -> PublicNodeI
|
||||
@node_router.get("/info")
|
||||
async def api_get_info(
|
||||
node: Node = Depends(require_node),
|
||||
) -> Optional[NodeInfoResponse]:
|
||||
) -> NodeInfoResponse | None:
|
||||
return await node.get_info()
|
||||
|
||||
|
||||
@node_router.get("/channels")
|
||||
async def api_get_channels(
|
||||
node: Node = Depends(require_node),
|
||||
) -> Optional[list[NodeChannel]]:
|
||||
) -> list[NodeChannel] | None:
|
||||
return await node.get_channels()
|
||||
|
||||
|
||||
@@ -104,7 +103,7 @@ async def api_get_channels(
|
||||
async def api_get_channel(
|
||||
channel_id: str,
|
||||
node: Node = Depends(require_node),
|
||||
) -> Optional[NodeChannel]:
|
||||
) -> NodeChannel | None:
|
||||
return await node.get_channel(channel_id)
|
||||
|
||||
|
||||
@@ -113,20 +112,20 @@ async def api_create_channel(
|
||||
node: Node = Depends(require_node),
|
||||
peer_id: str = Body(),
|
||||
funding_amount: int = Body(),
|
||||
push_amount: Optional[int] = Body(None),
|
||||
fee_rate: Optional[int] = Body(None),
|
||||
push_amount: int | None = Body(None),
|
||||
fee_rate: int | None = Body(None),
|
||||
):
|
||||
return await node.open_channel(peer_id, funding_amount, push_amount, fee_rate)
|
||||
|
||||
|
||||
@super_node_router.delete("/channels")
|
||||
async def api_delete_channel(
|
||||
short_id: Optional[str],
|
||||
funding_txid: Optional[str],
|
||||
output_index: Optional[int],
|
||||
short_id: str | None,
|
||||
funding_txid: str | None,
|
||||
output_index: int | None,
|
||||
force: bool = False,
|
||||
node: Node = Depends(require_node),
|
||||
) -> Optional[list[NodeChannel]]:
|
||||
) -> list[NodeChannel] | None:
|
||||
return await node.close_channel(
|
||||
short_id,
|
||||
(
|
||||
@@ -152,7 +151,7 @@ async def api_set_channel_fees(
|
||||
async def api_get_payments(
|
||||
node: Node = Depends(require_node),
|
||||
filters: Filters = Depends(parse_filters(NodePaymentsFilters)),
|
||||
) -> Optional[Page[NodePayment]]:
|
||||
) -> Page[NodePayment] | None:
|
||||
if not settings.lnbits_node_ui_transactions:
|
||||
raise HTTPException(
|
||||
HTTP_503_SERVICE_UNAVAILABLE,
|
||||
@@ -165,7 +164,7 @@ async def api_get_payments(
|
||||
async def api_get_invoices(
|
||||
node: Node = Depends(require_node),
|
||||
filters: Filters = Depends(parse_filters(NodeInvoiceFilters)),
|
||||
) -> Optional[Page[NodeInvoice]]:
|
||||
) -> Page[NodeInvoice] | None:
|
||||
if not settings.lnbits_node_ui_transactions:
|
||||
raise HTTPException(
|
||||
HTTP_503_SERVICE_UNAVAILABLE,
|
||||
@@ -192,25 +191,25 @@ async def api_disconnect_peer(peer_id: str, node: Node = Depends(require_node)):
|
||||
|
||||
|
||||
class NodeRank(BaseModel):
|
||||
capacity: Optional[int]
|
||||
channelcount: Optional[int]
|
||||
age: Optional[int]
|
||||
growth: Optional[int]
|
||||
availability: Optional[int]
|
||||
capacity: int | None
|
||||
channelcount: int | None
|
||||
age: int | None
|
||||
growth: int | None
|
||||
availability: int | None
|
||||
|
||||
|
||||
# Same for public and private api
|
||||
@node_router.get(
|
||||
"/rank",
|
||||
description="Retrieve node ranks from https://1ml.com",
|
||||
response_model=Optional[NodeRank],
|
||||
response_model=NodeRank | None,
|
||||
)
|
||||
@public_node_router.get(
|
||||
"/rank",
|
||||
description="Retrieve node ranks from https://1ml.com",
|
||||
response_model=Optional[NodeRank],
|
||||
response_model=NodeRank | None,
|
||||
)
|
||||
async def api_get_1ml_stats(node: Node = Depends(require_node)) -> Optional[NodeRank]:
|
||||
async def api_get_1ml_stats(node: Node = Depends(require_node)) -> NodeRank | None:
|
||||
node_id = await node.get_id()
|
||||
headers = {"User-Agent": settings.user_agent}
|
||||
async with httpx.AsyncClient(headers=headers) as client:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from hashlib import sha256
|
||||
from http import HTTPStatus
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import (
|
||||
APIRouter,
|
||||
@@ -275,7 +274,7 @@ async def api_payments_fee_reserve(invoice: str = Query("invoice")) -> JSONRespo
|
||||
|
||||
# TODO: refactor this route into a public and admin one
|
||||
@payment_router.get("/{payment_hash}")
|
||||
async def api_payment(payment_hash, x_api_key: Optional[str] = Header(None)):
|
||||
async def api_payment(payment_hash, x_api_key: str | None = Header(None)):
|
||||
# We use X_Api_Key here because we want this call to work with and without keys
|
||||
# If a valid key is given, we also return the field "details", otherwise not
|
||||
wallet = await get_wallet_for_key(x_api_key) if isinstance(x_api_key, str) else None
|
||||
|
||||
@@ -2,7 +2,6 @@ import base64
|
||||
import json
|
||||
import time
|
||||
from http import HTTPStatus
|
||||
from typing import Optional
|
||||
from uuid import uuid4
|
||||
|
||||
import shortuuid
|
||||
@@ -223,7 +222,7 @@ async def api_users_get_user_wallet(user_id: str) -> list[Wallet]:
|
||||
|
||||
@users_router.post("/user/{user_id}/wallet", name="Create a new wallet for user")
|
||||
async def api_users_create_user_wallet(
|
||||
user_id: str, name: Optional[str] = Body(None), currency: Optional[str] = Body(None)
|
||||
user_id: str, name: str | None = Body(None), currency: str | None = Body(None)
|
||||
):
|
||||
if currency and currency not in allowed_currencies():
|
||||
raise ValueError(f"Currency '{currency}' not allowed.")
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from http import HTTPStatus
|
||||
from typing import Optional
|
||||
from uuid import uuid4
|
||||
|
||||
from fastapi import (
|
||||
@@ -110,11 +109,11 @@ async def api_put_stored_paylinks(
|
||||
|
||||
@wallet_router.patch("")
|
||||
async def api_update_wallet(
|
||||
name: Optional[str] = Body(None),
|
||||
icon: Optional[str] = Body(None),
|
||||
color: Optional[str] = Body(None),
|
||||
currency: Optional[str] = Body(None),
|
||||
pinned: Optional[bool] = Body(None),
|
||||
name: str | None = Body(None),
|
||||
icon: str | None = Body(None),
|
||||
color: str | None = Body(None),
|
||||
currency: str | None = Body(None),
|
||||
pinned: bool | None = Body(None),
|
||||
key_info: WalletTypeInfo = Depends(require_admin_key),
|
||||
) -> Wallet:
|
||||
wallet = await get_wallet(key_info.wallet.id)
|
||||
|
||||
+21
-21
@@ -1,5 +1,5 @@
|
||||
from http import HTTPStatus
|
||||
from typing import Annotated, Literal, Optional, Union
|
||||
from typing import Annotated, Literal
|
||||
|
||||
import jwt
|
||||
from fastapi import Cookie, Depends, Query, Request, Security
|
||||
@@ -55,8 +55,8 @@ api_key_query = APIKeyQuery(
|
||||
class KeyChecker(SecurityBase):
|
||||
def __init__(
|
||||
self,
|
||||
api_key: Optional[str] = None,
|
||||
expected_key_type: Optional[KeyType] = None,
|
||||
api_key: str | None = None,
|
||||
expected_key_type: KeyType | None = None,
|
||||
):
|
||||
self.auto_error: bool = True
|
||||
self.expected_key_type = expected_key_type
|
||||
@@ -137,17 +137,17 @@ async def require_invoice_key(
|
||||
|
||||
|
||||
async def check_access_token(
|
||||
header_access_token: Annotated[Union[str, None], Depends(oauth2_scheme)],
|
||||
cookie_access_token: Annotated[Union[str, None], Cookie()] = None,
|
||||
bearer_access_token: Annotated[Union[str, None], Depends(http_bearer)] = None,
|
||||
) -> Optional[str]:
|
||||
header_access_token: Annotated[str | None, Depends(oauth2_scheme)],
|
||||
cookie_access_token: Annotated[str | None, Cookie()] = None,
|
||||
bearer_access_token: Annotated[str | None, Depends(http_bearer)] = None,
|
||||
) -> str | None:
|
||||
return header_access_token or cookie_access_token or bearer_access_token
|
||||
|
||||
|
||||
async def check_user_exists(
|
||||
r: Request,
|
||||
access_token: Annotated[Optional[str], Depends(check_access_token)],
|
||||
usr: Optional[UUID4] = None,
|
||||
access_token: Annotated[str | None, Depends(check_access_token)],
|
||||
usr: UUID4 | None = None,
|
||||
) -> User:
|
||||
if access_token:
|
||||
account = await _get_account_from_token(access_token, r["path"], r["method"])
|
||||
@@ -176,9 +176,9 @@ async def check_user_exists(
|
||||
|
||||
async def optional_user_id(
|
||||
r: Request,
|
||||
access_token: Annotated[Optional[str], Depends(check_access_token)],
|
||||
usr: Optional[UUID4] = None,
|
||||
) -> Optional[str]:
|
||||
access_token: Annotated[str | None, Depends(check_access_token)],
|
||||
usr: UUID4 | None = None,
|
||||
) -> str | None:
|
||||
if usr and settings.is_auth_method_allowed(AuthMethods.user_id_only):
|
||||
return usr.hex
|
||||
if access_token:
|
||||
@@ -189,7 +189,7 @@ async def optional_user_id(
|
||||
|
||||
|
||||
async def access_token_payload(
|
||||
access_token: Annotated[Optional[str], Depends(check_access_token)],
|
||||
access_token: Annotated[str | None, Depends(check_access_token)],
|
||||
) -> AccessTokenPayload:
|
||||
if not access_token:
|
||||
raise HTTPException(HTTPStatus.UNAUTHORIZED, "Missing access token.")
|
||||
@@ -231,11 +231,11 @@ def parse_filters(model: type[TFilterModel]):
|
||||
|
||||
def dependency(
|
||||
request: Request,
|
||||
limit: Optional[int] = None,
|
||||
offset: Optional[int] = None,
|
||||
sortby: Optional[str] = None,
|
||||
direction: Optional[Literal["asc", "desc"]] = None,
|
||||
search: Optional[str] = Query(None, description="Text based search"),
|
||||
limit: int | None = None,
|
||||
offset: int | None = None,
|
||||
sortby: str | None = None,
|
||||
direction: Literal["asc", "desc"] | None = None,
|
||||
search: str | None = Query(None, description="Text based search"),
|
||||
):
|
||||
params = request.query_params
|
||||
filters = []
|
||||
@@ -259,7 +259,7 @@ def parse_filters(model: type[TFilterModel]):
|
||||
|
||||
|
||||
async def check_user_extension_access(
|
||||
user_id: str, ext_id: str, conn: Optional[Connection] = None
|
||||
user_id: str, ext_id: str, conn: Connection | None = None
|
||||
) -> SimpleStatus:
|
||||
"""
|
||||
Check if the user has access to a particular extension.
|
||||
@@ -292,7 +292,7 @@ async def _check_user_extension_access(user_id: str, path: str):
|
||||
|
||||
async def _get_account_from_token(
|
||||
access_token: str, path: str, method: str
|
||||
) -> Optional[Account]:
|
||||
) -> Account | None:
|
||||
try:
|
||||
payload: dict = jwt.decode(access_token, settings.auth_secret_key, ["HS256"])
|
||||
return await _get_account_from_jwt_payload(
|
||||
@@ -310,7 +310,7 @@ async def _get_account_from_token(
|
||||
|
||||
async def _get_account_from_jwt_payload(
|
||||
payload: AccessTokenPayload, path: str, method: str
|
||||
) -> Optional[Account]:
|
||||
) -> Account | None:
|
||||
account = None
|
||||
if payload.sub:
|
||||
account = await get_account_by_username(payload.sub)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import sys
|
||||
import traceback
|
||||
from http import HTTPStatus
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI, HTTPException, Request
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
@@ -30,7 +29,7 @@ class UnsupportedError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def render_html_error(request: Request, exc: Exception) -> Optional[Response]:
|
||||
def render_html_error(request: Request, exc: Exception) -> Response | None:
|
||||
# Only the browser sends "text/html" request
|
||||
# not fail proof, but everything else get's a JSON response
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import asyncio
|
||||
import json
|
||||
from collections.abc import AsyncGenerator
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Optional
|
||||
from urllib.parse import urlencode
|
||||
|
||||
import httpx
|
||||
@@ -49,7 +48,7 @@ class StripeWallet(FiatProvider):
|
||||
logger.warning(f"Error closing stripe wallet connection: {e}")
|
||||
|
||||
async def status(
|
||||
self, only_check_settings: Optional[bool] = False
|
||||
self, only_check_settings: bool | None = False
|
||||
) -> FiatStatusResponse:
|
||||
if only_check_settings:
|
||||
if self._settings_fields != self._settings_connection_fields():
|
||||
@@ -76,7 +75,7 @@ class StripeWallet(FiatProvider):
|
||||
amount: float,
|
||||
payment_hash: str,
|
||||
currency: str,
|
||||
memo: Optional[str] = None,
|
||||
memo: str | None = None,
|
||||
**kwargs,
|
||||
) -> FiatInvoiceResponse:
|
||||
amount_cents = int(amount * 100)
|
||||
|
||||
+9
-13
@@ -3,7 +3,7 @@ import json
|
||||
import re
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
from urllib import request
|
||||
from urllib.parse import urlparse
|
||||
|
||||
@@ -39,7 +39,7 @@ def urlsafe_short_hash() -> str:
|
||||
return shortuuid.uuid()
|
||||
|
||||
|
||||
def url_for(endpoint: str, external: Optional[bool] = False, **params: Any) -> str:
|
||||
def url_for(endpoint: str, external: bool | None = False, **params: Any) -> str:
|
||||
base = f"http://{settings.host}:{settings.port}" if external else ""
|
||||
url_params = "?"
|
||||
for key, value in params.items():
|
||||
@@ -52,7 +52,7 @@ def static_url_for(static: str, path: str) -> str:
|
||||
return f"/{static}/{path}?v={settings.server_startup_time}"
|
||||
|
||||
|
||||
def template_renderer(additional_folders: Optional[list] = None) -> Jinja2Templates:
|
||||
def template_renderer(additional_folders: list | None = None) -> Jinja2Templates:
|
||||
folders = ["lnbits/templates", "lnbits/core/templates"]
|
||||
if additional_folders:
|
||||
additional_folders += [
|
||||
@@ -211,7 +211,7 @@ def is_valid_pubkey(pubkey: str) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def create_access_token(data: dict, token_expire_minutes: Optional[int] = None) -> str:
|
||||
def create_access_token(data: dict, token_expire_minutes: int | None = None) -> str:
|
||||
minutes = token_expire_minutes or settings.auth_token_expire_minutes
|
||||
expire = datetime.now(timezone.utc) + timedelta(minutes=minutes)
|
||||
to_encode = {k: v for k, v in data.items() if v is not None}
|
||||
@@ -219,9 +219,7 @@ def create_access_token(data: dict, token_expire_minutes: Optional[int] = None)
|
||||
return jwt.encode(to_encode, settings.auth_secret_key, "HS256")
|
||||
|
||||
|
||||
def encrypt_internal_message(
|
||||
m: Optional[str] = None, urlsafe: bool = False
|
||||
) -> Optional[str]:
|
||||
def encrypt_internal_message(m: str | None = None, urlsafe: bool = False) -> str | None:
|
||||
"""
|
||||
Encrypt message with the internal secret key
|
||||
|
||||
@@ -234,9 +232,7 @@ def encrypt_internal_message(
|
||||
return AESCipher(key=settings.auth_secret_key).encrypt(m.encode(), urlsafe=urlsafe)
|
||||
|
||||
|
||||
def decrypt_internal_message(
|
||||
m: Optional[str] = None, urlsafe: bool = False
|
||||
) -> Optional[str]:
|
||||
def decrypt_internal_message(m: str | None = None, urlsafe: bool = False) -> str | None:
|
||||
"""
|
||||
Decrypt message with the internal secret key
|
||||
|
||||
@@ -249,7 +245,7 @@ def decrypt_internal_message(
|
||||
return AESCipher(key=settings.auth_secret_key).decrypt(m, urlsafe=urlsafe)
|
||||
|
||||
|
||||
def filter_dict_keys(data: dict, filter_keys: Optional[list[str]]) -> dict:
|
||||
def filter_dict_keys(data: dict, filter_keys: list[str] | None) -> dict:
|
||||
if not filter_keys:
|
||||
# return shallow clone of the dict even if there are no filters
|
||||
return {**data}
|
||||
@@ -270,7 +266,7 @@ def version_parse(v: str):
|
||||
|
||||
|
||||
def is_lnbits_version_ok(
|
||||
min_lnbits_version: Optional[str], max_lnbits_version: Optional[str]
|
||||
min_lnbits_version: str | None, max_lnbits_version: str | None
|
||||
) -> bool:
|
||||
if min_lnbits_version and (
|
||||
version_parse(min_lnbits_version) > version_parse(settings.version)
|
||||
@@ -347,7 +343,7 @@ def path_segments(path: str) -> list[str]:
|
||||
return segments[0:]
|
||||
|
||||
|
||||
def normalize_path(path: Optional[str]) -> str:
|
||||
def normalize_path(path: str | None) -> str:
|
||||
path = path or ""
|
||||
return "/" + "/".join(path_segments(path))
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import asyncio
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
from http import HTTPStatus
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any
|
||||
|
||||
from fastapi import FastAPI, Request, Response
|
||||
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse
|
||||
@@ -62,7 +62,7 @@ class InstalledExtensionMiddleware:
|
||||
|
||||
def _response_by_accepted_type(
|
||||
self, scope: Scope, headers: list[Any], msg: str, status_code: HTTPStatus
|
||||
) -> Union[HTMLResponse, JSONResponse]:
|
||||
) -> HTMLResponse | JSONResponse:
|
||||
"""
|
||||
Build an HTTP response containing the `msg` as HTTP body and the `status_code`
|
||||
as HTTP code. If the `accept` HTTP header is present int the request and
|
||||
@@ -127,7 +127,7 @@ class AuditMiddleware(BaseHTTPMiddleware):
|
||||
async def dispatch(self, request: Request, call_next) -> Response:
|
||||
start_time = datetime.now(timezone.utc)
|
||||
request_details = await self._request_details(request)
|
||||
response: Optional[Response] = None
|
||||
response: Response | None = None
|
||||
|
||||
try:
|
||||
response = await call_next(request)
|
||||
@@ -140,13 +140,13 @@ class AuditMiddleware(BaseHTTPMiddleware):
|
||||
async def _log_audit(
|
||||
self,
|
||||
request: Request,
|
||||
response: Optional[Response],
|
||||
response: Response | None,
|
||||
duration: float,
|
||||
request_details: Optional[str],
|
||||
request_details: str | None,
|
||||
):
|
||||
try:
|
||||
http_method = request.scope.get("method", None)
|
||||
path: Optional[str] = getattr(request.scope.get("route", {}), "path", None)
|
||||
path: str | None = getattr(request.scope.get("route", {}), "path", None)
|
||||
response_code = str(response.status_code) if response else None
|
||||
if not settings.audit_http_request(http_method, path, response_code):
|
||||
return None
|
||||
@@ -178,7 +178,7 @@ class AuditMiddleware(BaseHTTPMiddleware):
|
||||
except Exception as ex:
|
||||
logger.warning(ex)
|
||||
|
||||
async def _request_details(self, request: Request) -> Optional[str]:
|
||||
async def _request_details(self, request: Request) -> str | None:
|
||||
if not settings.audit_http_request_details():
|
||||
return None
|
||||
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ def main(
|
||||
ssl_certfile: str,
|
||||
reload: bool,
|
||||
):
|
||||
"""Launched with `poetry run lnbits` at root level"""
|
||||
"""Launched with `uv run lnbits` at root level"""
|
||||
|
||||
# create data dir if it does not exist
|
||||
Path(settings.lnbits_data_folder).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
+2
-6
@@ -1,11 +1,7 @@
|
||||
import asyncio
|
||||
import traceback
|
||||
import uuid
|
||||
from collections.abc import Coroutine
|
||||
from typing import (
|
||||
Callable,
|
||||
Optional,
|
||||
)
|
||||
from collections.abc import Callable, Coroutine
|
||||
|
||||
from loguru import logger
|
||||
|
||||
@@ -84,7 +80,7 @@ invoice_listeners: dict[str, asyncio.Queue] = {}
|
||||
|
||||
# TODO: name should not be optional
|
||||
# some extensions still dont use a name, but they should
|
||||
def register_invoice_listener(send_chan: asyncio.Queue, name: Optional[str] = None):
|
||||
def register_invoice_listener(send_chan: asyncio.Queue, name: str | None = None):
|
||||
"""
|
||||
A method intended for extensions (and core/tasks.py) to call when they want to be
|
||||
notified about new invoice payments incoming. Will emit all incoming payments.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from base64 import b64decode, b64encode, urlsafe_b64decode, urlsafe_b64encode
|
||||
from hashlib import md5, pbkdf2_hmac, sha256
|
||||
from typing import Union
|
||||
|
||||
from Cryptodome import Random
|
||||
from Cryptodome.Cipher import AES
|
||||
@@ -40,7 +39,7 @@ class AESCipher:
|
||||
AES.decrypt(encrypted, password).toString(Utf8);
|
||||
"""
|
||||
|
||||
def __init__(self, key: Union[bytes, str], block_size: int = 16):
|
||||
def __init__(self, key: bytes | str, block_size: int = 16):
|
||||
self.block_size = block_size
|
||||
if isinstance(key, bytes):
|
||||
self.key = key
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import asyncio
|
||||
import statistics
|
||||
from typing import Optional
|
||||
|
||||
import httpx
|
||||
import jsonpath_ng.ext as jpx
|
||||
@@ -250,7 +249,7 @@ async def btc_rates(currency: str) -> list[tuple[str, float]]:
|
||||
|
||||
async def fetch_price(
|
||||
provider: ExchangeRateProvider,
|
||||
) -> Optional[tuple[str, float]]:
|
||||
) -> tuple[str, float] | None:
|
||||
if currency.lower() in provider.exclude_to:
|
||||
logger.warning(f"Provider {provider.name} does not support {currency}.")
|
||||
return None
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import asyncio
|
||||
import logging
|
||||
import sys
|
||||
from collections.abc import Callable
|
||||
from hashlib import sha256
|
||||
from pathlib import Path
|
||||
from typing import Callable
|
||||
|
||||
from loguru import logger
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import base64
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
from typing import Union
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import secp256k1
|
||||
@@ -149,7 +148,7 @@ def sign_event(
|
||||
return event
|
||||
|
||||
|
||||
def json_dumps(data: Union[dict, list]) -> str:
|
||||
def json_dumps(data: dict | list) -> str:
|
||||
"""
|
||||
Converts a Python dictionary to a JSON string with compact encoding.
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import asyncio
|
||||
import hashlib
|
||||
import json
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Optional
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
@@ -71,9 +70,9 @@ class AlbyWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**_,
|
||||
) -> InvoiceResponse:
|
||||
# https://api.getalby.com/invoices
|
||||
|
||||
@@ -2,7 +2,6 @@ import asyncio
|
||||
import hashlib
|
||||
import json
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Optional
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
@@ -102,9 +101,9 @@ class BlinkWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**kwargs,
|
||||
) -> InvoiceResponse:
|
||||
# https://dev.blink.sv/api/btc-ln-receive
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import asyncio
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Optional
|
||||
|
||||
from bolt11.decode import decode
|
||||
from grpc.aio import AioRpcError
|
||||
@@ -107,9 +106,9 @@ class BoltzWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**_,
|
||||
) -> InvoiceResponse:
|
||||
pair = boltzrpc_pb2.Pair(to=boltzrpc_pb2.LBTC)
|
||||
@@ -254,7 +253,7 @@ class BoltzWallet(Wallet):
|
||||
)
|
||||
await asyncio.sleep(5)
|
||||
|
||||
async def _fetch_wallet(self, wallet_name: str) -> Optional[str]:
|
||||
async def _fetch_wallet(self, wallet_name: str) -> str | None:
|
||||
try:
|
||||
request = boltzrpc_pb2.GetWalletRequest(name=wallet_name)
|
||||
response = await self.rpc.GetWallet(request, metadata=self.metadata)
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
|
||||
wget https://raw.githubusercontent.com/BoltzExchange/boltz-client/refs/heads/master/pkg/boltzrpc/boltzrpc.proto -O boltz_grpc_files/boltzrpc.proto
|
||||
poetry run python -m grpc_tools.protoc -I . --python_out=. --grpc_python_out=. --pyi_out=. boltz_grpc_files/boltzrpc.proto
|
||||
uv run python -m grpc_tools.protoc -I . --python_out=. --grpc_python_out=. --pyi_out=. boltz_grpc_files/boltzrpc.proto
|
||||
|
||||
@@ -9,14 +9,13 @@ if not find_spec("breez_sdk"):
|
||||
def __init__(self):
|
||||
raise RuntimeError(
|
||||
"Breez SDK is not installed. "
|
||||
"Ask admin to run `poetry install -E breez` to install it."
|
||||
"Ask admin to run `uv sync --extra breez` to install it."
|
||||
)
|
||||
|
||||
else:
|
||||
import asyncio
|
||||
from collections.abc import AsyncGenerator
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from bolt11 import Bolt11Exception
|
||||
from bolt11 import decode as bolt11_decode
|
||||
@@ -66,7 +65,7 @@ else:
|
||||
):
|
||||
breez_incoming_queue.put_nowait(e.details)
|
||||
|
||||
def load_bytes(source: str, extension: str) -> Optional[bytes]:
|
||||
def load_bytes(source: str, extension: str) -> bytes | None:
|
||||
# first check if it can be read from a file
|
||||
if source.split(".")[-1] == extension:
|
||||
with open(source, "rb") as f:
|
||||
@@ -85,7 +84,7 @@ else:
|
||||
logger.debug(exc)
|
||||
return None
|
||||
|
||||
def load_greenlight_credentials() -> Optional[GreenlightCredentials]:
|
||||
def load_greenlight_credentials() -> GreenlightCredentials | None:
|
||||
if (
|
||||
settings.breez_greenlight_device_key
|
||||
and settings.breez_greenlight_device_cert
|
||||
@@ -168,9 +167,9 @@ else:
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**kwargs,
|
||||
) -> InvoiceResponse:
|
||||
# if description_hash or unhashed_description:
|
||||
|
||||
@@ -8,7 +8,7 @@ if not find_spec("breez_sdk_liquid"):
|
||||
def __init__(self):
|
||||
raise RuntimeError(
|
||||
"Breez Liquid SDK is not installed. "
|
||||
"Ask admin to run `poetry add -E breez` to install it."
|
||||
"Ask admin to run `uv sync --extra breez` to install it."
|
||||
)
|
||||
|
||||
else:
|
||||
@@ -16,7 +16,6 @@ else:
|
||||
from asyncio import Queue
|
||||
from collections.abc import AsyncGenerator
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from bolt11 import decode as bolt11_decode
|
||||
from breez_sdk_liquid import (
|
||||
@@ -128,9 +127,9 @@ else:
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**_,
|
||||
) -> InvoiceResponse:
|
||||
try:
|
||||
|
||||
@@ -2,7 +2,6 @@ import asyncio
|
||||
import hashlib
|
||||
import json
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Optional
|
||||
|
||||
from loguru import logger
|
||||
from websocket import create_connection
|
||||
@@ -53,9 +52,9 @@ class ClicheWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**_,
|
||||
) -> InvoiceResponse:
|
||||
if unhashed_description or description_hash:
|
||||
|
||||
@@ -5,7 +5,6 @@ import os
|
||||
import ssl
|
||||
import uuid
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Optional
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import httpx
|
||||
@@ -174,9 +173,9 @@ class CLNRestWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**kwargs,
|
||||
) -> InvoiceResponse:
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import asyncio
|
||||
from collections.abc import AsyncGenerator
|
||||
from secrets import token_urlsafe
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
from bolt11.decode import decode as bolt11_decode
|
||||
from bolt11.exceptions import Bolt11Exception
|
||||
@@ -92,9 +92,9 @@ class CoreLightningWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**kwargs,
|
||||
) -> InvoiceResponse:
|
||||
label = kwargs.get("label", f"lbl{token_urlsafe(16)}")
|
||||
|
||||
@@ -2,7 +2,6 @@ import asyncio
|
||||
import json
|
||||
from collections.abc import AsyncGenerator
|
||||
from secrets import token_urlsafe
|
||||
from typing import Optional
|
||||
|
||||
import httpx
|
||||
from bolt11 import Bolt11Exception
|
||||
@@ -106,9 +105,9 @@ class CoreLightningRestWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**kwargs,
|
||||
) -> InvoiceResponse:
|
||||
label = kwargs.get("label", f"lbl{token_urlsafe(16)}")
|
||||
|
||||
@@ -5,7 +5,7 @@ import json
|
||||
import urllib.parse
|
||||
from collections.abc import AsyncGenerator
|
||||
from decimal import Decimal
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
@@ -84,9 +84,9 @@ class EclairWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**kwargs,
|
||||
) -> InvoiceResponse:
|
||||
data: dict[str, Any] = {
|
||||
|
||||
@@ -3,7 +3,6 @@ from collections.abc import AsyncGenerator
|
||||
from datetime import datetime
|
||||
from hashlib import sha256
|
||||
from os import urandom
|
||||
from typing import Optional
|
||||
|
||||
from bolt11 import (
|
||||
Bolt11,
|
||||
@@ -53,11 +52,11 @@ class FakeWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
expiry: Optional[int] = None,
|
||||
payment_secret: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
expiry: int | None = None,
|
||||
payment_secret: bytes | None = None,
|
||||
**_,
|
||||
) -> InvoiceResponse:
|
||||
tags = Tags()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import asyncio
|
||||
import json
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Optional
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
@@ -71,9 +70,9 @@ class LNbitsWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**kwargs,
|
||||
) -> InvoiceResponse:
|
||||
data: dict = {"out": False, "amount": amount, "memo": memo or ""}
|
||||
|
||||
@@ -3,7 +3,6 @@ import base64
|
||||
from collections.abc import AsyncGenerator
|
||||
from hashlib import sha256
|
||||
from os import environ
|
||||
from typing import Optional
|
||||
|
||||
import grpc
|
||||
from loguru import logger
|
||||
@@ -123,9 +122,9 @@ class LndWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**kwargs,
|
||||
) -> InvoiceResponse:
|
||||
data: dict = {
|
||||
@@ -312,9 +311,9 @@ class LndWallet(Wallet):
|
||||
self,
|
||||
amount: int,
|
||||
payment_hash: str,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**kwargs,
|
||||
) -> InvoiceResponse:
|
||||
data: dict = {
|
||||
|
||||
@@ -3,7 +3,7 @@ import base64
|
||||
import hashlib
|
||||
import json
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
@@ -103,9 +103,9 @@ class LndRestWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**kwargs,
|
||||
) -> InvoiceResponse:
|
||||
_data: dict = {
|
||||
@@ -327,9 +327,9 @@ class LndRestWallet(Wallet):
|
||||
self,
|
||||
amount: int,
|
||||
payment_hash: str,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**_,
|
||||
) -> InvoiceResponse:
|
||||
data: dict = {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import asyncio
|
||||
import hashlib
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Optional
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
@@ -75,9 +74,9 @@ class LNPayWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**_,
|
||||
) -> InvoiceResponse:
|
||||
data: dict = {"num_satoshis": f"{amount}"}
|
||||
|
||||
@@ -3,7 +3,6 @@ import hashlib
|
||||
import json
|
||||
import time
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Optional
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
@@ -69,9 +68,9 @@ class LnTipsWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**_,
|
||||
) -> InvoiceResponse:
|
||||
data: dict = {"amount": amount, "description_hash": "", "memo": memo or ""}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import base64
|
||||
from getpass import getpass
|
||||
from typing import Optional
|
||||
|
||||
from loguru import logger
|
||||
|
||||
@@ -8,8 +7,8 @@ from lnbits.utils.crypto import AESCipher
|
||||
|
||||
|
||||
def load_macaroon(
|
||||
macaroon: Optional[str] = None,
|
||||
encrypted_macaroon: Optional[str] = None,
|
||||
macaroon: str | None = None,
|
||||
encrypted_macaroon: str | None = None,
|
||||
) -> str:
|
||||
"""Returns hex version of a macaroon encoded in base64 or the file path."""
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import json
|
||||
import random
|
||||
import time
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Optional, Union, cast
|
||||
from typing import cast
|
||||
from urllib.parse import parse_qs, unquote, urlparse
|
||||
|
||||
import secp256k1
|
||||
@@ -130,9 +130,9 @@ class NWCWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**_,
|
||||
) -> InvoiceResponse:
|
||||
desc = ""
|
||||
@@ -360,7 +360,7 @@ class NWCConnection:
|
||||
"""
|
||||
return self.shutdown or not settings.lnbits_running
|
||||
|
||||
async def _send(self, data: list[Union[str, dict]]):
|
||||
async def _send(self, data: list[str | dict]):
|
||||
"""
|
||||
Sends data to the NWC relay.
|
||||
|
||||
@@ -396,7 +396,7 @@ class NWCConnection:
|
||||
|
||||
async def _close_subscription_by_subid(
|
||||
self, sub_id: str, send_event: bool = True
|
||||
) -> Optional[dict]:
|
||||
) -> dict | None:
|
||||
"""
|
||||
Closes a subscription by its sub_id.
|
||||
|
||||
@@ -427,7 +427,7 @@ class NWCConnection:
|
||||
|
||||
async def _close_subscription_by_eventid(
|
||||
self, event_id, send_event=True
|
||||
) -> Optional[dict]:
|
||||
) -> dict | None:
|
||||
"""
|
||||
Closes a subscription associated to an event_id.
|
||||
|
||||
@@ -514,7 +514,7 @@ class NWCConnection:
|
||||
if subscription: # Check if the subscription exists first
|
||||
subscription["future"].set_exception(Exception(info))
|
||||
|
||||
async def _on_event_message(self, msg: list[Union[str, dict]]): # noqa: C901
|
||||
async def _on_event_message(self, msg: list[str | dict]): # noqa: C901
|
||||
"""
|
||||
Handles EVENT messages from the relay.
|
||||
"""
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import asyncio
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Optional
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
@@ -71,9 +70,9 @@ class OpenNodeWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**_,
|
||||
) -> InvoiceResponse:
|
||||
if description_hash or unhashed_description:
|
||||
|
||||
@@ -4,7 +4,7 @@ import hashlib
|
||||
import json
|
||||
import urllib.parse
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
from httpx import RequestError, TimeoutException
|
||||
@@ -96,9 +96,9 @@ class PhoenixdWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**kwargs,
|
||||
) -> InvoiceResponse:
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ import hashlib
|
||||
import json
|
||||
from collections.abc import AsyncGenerator
|
||||
from secrets import token_urlsafe
|
||||
from typing import Optional
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
@@ -111,9 +110,9 @@ class SparkWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**kwargs,
|
||||
) -> InvoiceResponse:
|
||||
label = f"lbs{token_urlsafe(16)}"
|
||||
|
||||
@@ -2,7 +2,7 @@ import asyncio
|
||||
import time
|
||||
from collections.abc import AsyncGenerator
|
||||
from decimal import Decimal
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
@@ -116,7 +116,7 @@ class StrikeWallet(Wallet):
|
||||
self.failed_payments: dict[str, str] = {}
|
||||
|
||||
# balance cache
|
||||
self._cached_balance: Optional[int] = None
|
||||
self._cached_balance: int | None = None
|
||||
self._cached_balance_ts: float = 0.0
|
||||
self._cache_ttl = 30 # seconds
|
||||
|
||||
@@ -199,8 +199,8 @@ class StrikeWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None, # Add this parameter
|
||||
**kwargs,
|
||||
) -> InvoiceResponse:
|
||||
@@ -424,10 +424,10 @@ class StrikeWallet(Wallet):
|
||||
|
||||
async def get_invoices(
|
||||
self,
|
||||
filters: Optional[str] = None,
|
||||
orderby: Optional[str] = None,
|
||||
skip: Optional[int] = None,
|
||||
top: Optional[int] = None,
|
||||
filters: str | None = None,
|
||||
orderby: str | None = None,
|
||||
skip: int | None = None,
|
||||
top: int | None = None,
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
params: dict[str, Any] = {}
|
||||
@@ -450,7 +450,7 @@ class StrikeWallet(Wallet):
|
||||
|
||||
async def _get_payment_status_by_quote_id(
|
||||
self, checking_id: str, quote_id: str
|
||||
) -> Optional[PaymentStatus]:
|
||||
) -> PaymentStatus | None:
|
||||
resp = await self._get(f"/payment-quotes/{quote_id}")
|
||||
resp.raise_for_status()
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import asyncio
|
||||
import hashlib
|
||||
from collections.abc import AsyncGenerator
|
||||
from typing import Optional
|
||||
|
||||
import httpx
|
||||
from bolt11 import decode as bolt11_decode
|
||||
@@ -60,9 +59,9 @@ class ZBDWallet(Wallet):
|
||||
async def create_invoice(
|
||||
self,
|
||||
amount: int,
|
||||
memo: Optional[str] = None,
|
||||
description_hash: Optional[bytes] = None,
|
||||
unhashed_description: Optional[bytes] = None,
|
||||
memo: str | None = None,
|
||||
description_hash: bytes | None = None,
|
||||
unhashed_description: bytes | None = None,
|
||||
**_,
|
||||
) -> InvoiceResponse:
|
||||
# https://api.zebedee.io/v0/charges
|
||||
|
||||
Reference in New Issue
Block a user