feat: introduce self.features to wallets, refactor feature nodemanager (#3260)
This commit is contained in:
parent
256a8098c6
commit
6e9f451419
9 changed files with 36 additions and 29 deletions
|
|
@ -7,8 +7,9 @@ from pydantic import BaseModel
|
||||||
from starlette.status import HTTP_503_SERVICE_UNAVAILABLE
|
from starlette.status import HTTP_503_SERVICE_UNAVAILABLE
|
||||||
|
|
||||||
from lnbits.decorators import check_admin, check_super_user, parse_filters
|
from lnbits.decorators import check_admin, check_super_user, parse_filters
|
||||||
from lnbits.nodes import get_node_class
|
|
||||||
from lnbits.settings import settings
|
from lnbits.settings import settings
|
||||||
|
from lnbits.wallets import get_funding_source
|
||||||
|
from lnbits.wallets.base import Feature
|
||||||
|
|
||||||
from ...db import Filters, Page
|
from ...db import Filters, Page
|
||||||
from ...nodes.base import (
|
from ...nodes.base import (
|
||||||
|
|
@ -26,9 +27,13 @@ from ...nodes.base import (
|
||||||
from ...utils.cache import cache
|
from ...utils.cache import cache
|
||||||
|
|
||||||
|
|
||||||
def require_node():
|
def require_node() -> Node:
|
||||||
node_class = get_node_class()
|
funding_source = get_funding_source()
|
||||||
if not node_class:
|
if (
|
||||||
|
not funding_source.features
|
||||||
|
or Feature.nodemanager not in funding_source.features
|
||||||
|
or not funding_source.__node_cls__
|
||||||
|
):
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=HTTPStatus.NOT_IMPLEMENTED,
|
status_code=HTTPStatus.NOT_IMPLEMENTED,
|
||||||
detail="Active backend does not implement Node API",
|
detail="Active backend does not implement Node API",
|
||||||
|
|
@ -38,7 +43,7 @@ def require_node():
|
||||||
status_code=HTTPStatus.SERVICE_UNAVAILABLE,
|
status_code=HTTPStatus.SERVICE_UNAVAILABLE,
|
||||||
detail="Not enabled",
|
detail="Not enabled",
|
||||||
)
|
)
|
||||||
return node_class
|
return funding_source.__node_cls__(funding_source)
|
||||||
|
|
||||||
|
|
||||||
def check_public():
|
def check_public():
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ from packaging import version
|
||||||
from pydantic.schema import field_schema
|
from pydantic.schema import field_schema
|
||||||
|
|
||||||
from lnbits.jinja2_templating import Jinja2Templates
|
from lnbits.jinja2_templating import Jinja2Templates
|
||||||
from lnbits.nodes import get_node_class
|
|
||||||
from lnbits.settings import settings
|
from lnbits.settings import settings
|
||||||
from lnbits.utils.crypto import AESCipher
|
from lnbits.utils.crypto import AESCipher
|
||||||
|
|
||||||
|
|
@ -83,8 +82,8 @@ def template_renderer(additional_folders: Optional[list] = None) -> Jinja2Templa
|
||||||
"LNBITS_CUSTOM_BADGE_COLOR": settings.lnbits_custom_badge_color,
|
"LNBITS_CUSTOM_BADGE_COLOR": settings.lnbits_custom_badge_color,
|
||||||
"LNBITS_EXTENSIONS_DEACTIVATE_ALL": settings.lnbits_extensions_deactivate_all,
|
"LNBITS_EXTENSIONS_DEACTIVATE_ALL": settings.lnbits_extensions_deactivate_all,
|
||||||
"LNBITS_NEW_ACCOUNTS_ALLOWED": settings.new_accounts_allowed,
|
"LNBITS_NEW_ACCOUNTS_ALLOWED": settings.new_accounts_allowed,
|
||||||
"LNBITS_NODE_UI": settings.lnbits_node_ui and get_node_class() is not None,
|
"LNBITS_NODE_UI": settings.lnbits_node_ui and settings.has_nodemanager,
|
||||||
"LNBITS_NODE_UI_AVAILABLE": get_node_class() is not None,
|
"LNBITS_NODE_UI_AVAILABLE": settings.has_nodemanager,
|
||||||
"LNBITS_QR_LOGO": settings.lnbits_qr_logo,
|
"LNBITS_QR_LOGO": settings.lnbits_qr_logo,
|
||||||
"LNBITS_SERVICE_FEE": settings.lnbits_service_fee,
|
"LNBITS_SERVICE_FEE": settings.lnbits_service_fee,
|
||||||
"LNBITS_SERVICE_FEE_MAX": settings.lnbits_service_fee_max,
|
"LNBITS_SERVICE_FEE_MAX": settings.lnbits_service_fee_max,
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from .base import Node
|
|
||||||
|
|
||||||
|
|
||||||
def get_node_class() -> Optional[Node]:
|
|
||||||
return NODE
|
|
||||||
|
|
||||||
|
|
||||||
def set_node_class(node: Node):
|
|
||||||
global NODE
|
|
||||||
NODE = node
|
|
||||||
|
|
||||||
|
|
||||||
NODE: Optional[Node] = None
|
|
||||||
|
|
@ -11,12 +11,12 @@ from httpx import HTTPStatusError
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from lnbits.db import Filters, Page
|
from lnbits.db import Filters, Page
|
||||||
from lnbits.nodes import Node
|
|
||||||
from lnbits.nodes.base import (
|
from lnbits.nodes.base import (
|
||||||
ChannelBalance,
|
ChannelBalance,
|
||||||
ChannelPoint,
|
ChannelPoint,
|
||||||
ChannelState,
|
ChannelState,
|
||||||
ChannelStats,
|
ChannelStats,
|
||||||
|
Node,
|
||||||
NodeChannel,
|
NodeChannel,
|
||||||
NodeFees,
|
NodeFees,
|
||||||
NodeInfoResponse,
|
NodeInfoResponse,
|
||||||
|
|
|
||||||
|
|
@ -987,6 +987,8 @@ class TransientSettings(InstalledExtensionsSettings, ExchangeHistorySettings):
|
||||||
|
|
||||||
server_startup_time: int = Field(default=time())
|
server_startup_time: int = Field(default=time())
|
||||||
|
|
||||||
|
has_nodemanager: bool = Field(default=False)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lnbits_server_up_time(self) -> str:
|
def lnbits_server_up_time(self) -> str:
|
||||||
up_time = int(time() - self.server_startup_time)
|
up_time = int(time() - self.server_startup_time)
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,8 @@ from __future__ import annotations
|
||||||
|
|
||||||
import importlib
|
import importlib
|
||||||
|
|
||||||
from lnbits.nodes import set_node_class
|
|
||||||
from lnbits.settings import settings
|
from lnbits.settings import settings
|
||||||
from lnbits.wallets.base import Wallet
|
from lnbits.wallets.base import Feature, Wallet
|
||||||
|
|
||||||
from .alby import AlbyWallet
|
from .alby import AlbyWallet
|
||||||
from .blink import BlinkWallet
|
from .blink import BlinkWallet
|
||||||
|
|
@ -35,13 +34,12 @@ from .void import VoidWallet
|
||||||
from .zbd import ZBDWallet
|
from .zbd import ZBDWallet
|
||||||
|
|
||||||
|
|
||||||
def set_funding_source(class_name: str | None = None):
|
def set_funding_source(class_name: str | None = None) -> None:
|
||||||
backend_wallet_class = class_name or settings.lnbits_backend_wallet_class
|
backend_wallet_class = class_name or settings.lnbits_backend_wallet_class
|
||||||
funding_source_constructor = getattr(wallets_module, backend_wallet_class)
|
funding_source_constructor = getattr(wallets_module, backend_wallet_class)
|
||||||
global funding_source
|
global funding_source
|
||||||
funding_source = funding_source_constructor()
|
funding_source = funding_source_constructor()
|
||||||
if funding_source.__node_cls__:
|
settings.has_nodemanager = funding_source.has_feature(Feature.nodemanager)
|
||||||
set_node_class(funding_source.__node_cls__(funding_source))
|
|
||||||
|
|
||||||
|
|
||||||
def get_funding_source() -> Wallet:
|
def get_funding_source() -> Wallet:
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
||||||
import asyncio
|
import asyncio
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from collections.abc import AsyncGenerator, Coroutine
|
from collections.abc import AsyncGenerator, Coroutine
|
||||||
|
from enum import Enum
|
||||||
from typing import TYPE_CHECKING, NamedTuple
|
from typing import TYPE_CHECKING, NamedTuple
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
@ -13,6 +14,12 @@ if TYPE_CHECKING:
|
||||||
from lnbits.nodes.base import Node
|
from lnbits.nodes.base import Node
|
||||||
|
|
||||||
|
|
||||||
|
class Feature(Enum):
|
||||||
|
nodemanager = "nodemanager"
|
||||||
|
# hold = "hold"
|
||||||
|
# bolt12 = "bolt12"
|
||||||
|
|
||||||
|
|
||||||
class StatusResponse(NamedTuple):
|
class StatusResponse(NamedTuple):
|
||||||
error_message: str | None
|
error_message: str | None
|
||||||
balance_msat: int
|
balance_msat: int
|
||||||
|
|
@ -100,6 +107,10 @@ class PaymentPendingStatus(PaymentStatus):
|
||||||
class Wallet(ABC):
|
class Wallet(ABC):
|
||||||
|
|
||||||
__node_cls__: type[Node] | None = None
|
__node_cls__: type[Node] | None = None
|
||||||
|
features: list[Feature] | None = None
|
||||||
|
|
||||||
|
def has_feature(self, feature: Feature) -> bool:
|
||||||
|
return self.features is not None and feature in self.features
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.pending_invoices: list[str] = []
|
self.pending_invoices: list[str] = []
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ from lnbits.settings import settings
|
||||||
from lnbits.utils.crypto import random_secret_and_hash
|
from lnbits.utils.crypto import random_secret_and_hash
|
||||||
|
|
||||||
from .base import (
|
from .base import (
|
||||||
|
Feature,
|
||||||
InvoiceResponse,
|
InvoiceResponse,
|
||||||
PaymentFailedStatus,
|
PaymentFailedStatus,
|
||||||
PaymentPendingStatus,
|
PaymentPendingStatus,
|
||||||
|
|
@ -31,12 +32,16 @@ async def run_sync(func) -> Any:
|
||||||
|
|
||||||
|
|
||||||
class CoreLightningWallet(Wallet):
|
class CoreLightningWallet(Wallet):
|
||||||
|
"""Core Lightning RPC implementation."""
|
||||||
|
|
||||||
__node_cls__ = CoreLightningNode
|
__node_cls__ = CoreLightningNode
|
||||||
|
features = [Feature.nodemanager]
|
||||||
|
|
||||||
async def cleanup(self):
|
async def cleanup(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
rpc = settings.corelightning_rpc or settings.clightning_rpc
|
rpc = settings.corelightning_rpc or settings.clightning_rpc
|
||||||
if not rpc:
|
if not rpc:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ from lnbits.settings import settings
|
||||||
from lnbits.utils.crypto import random_secret_and_hash
|
from lnbits.utils.crypto import random_secret_and_hash
|
||||||
|
|
||||||
from .base import (
|
from .base import (
|
||||||
|
Feature,
|
||||||
InvoiceResponse,
|
InvoiceResponse,
|
||||||
PaymentFailedStatus,
|
PaymentFailedStatus,
|
||||||
PaymentPendingStatus,
|
PaymentPendingStatus,
|
||||||
|
|
@ -30,6 +31,7 @@ class LndRestWallet(Wallet):
|
||||||
"""https://api.lightning.community/rest/index.html#lnd-rest-api-reference"""
|
"""https://api.lightning.community/rest/index.html#lnd-rest-api-reference"""
|
||||||
|
|
||||||
__node_cls__ = LndRestNode
|
__node_cls__ = LndRestNode
|
||||||
|
features = [Feature.nodemanager]
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
if not settings.lnd_rest_endpoint:
|
if not settings.lnd_rest_endpoint:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue