From cbde5744aa43d1848c98d48e3a13c66d71c7f58b Mon Sep 17 00:00:00 2001 From: Ben Arc Date: Thu, 23 Feb 2023 11:41:44 +0000 Subject: [PATCH] RIP Lntxbot, thank you for all your help building LN, you will be missed :( --- .env.example | 4 - README.md | 2 +- docs/guide/wallets.md | 9 +- lnbits/core/templates/core/index.html | 28 ++--- lnbits/settings.py | 5 - lnbits/wallets/__init__.py | 1 - lnbits/wallets/lntxbot.py | 156 -------------------------- 7 files changed, 11 insertions(+), 194 deletions(-) delete mode 100644 lnbits/wallets/lntxbot.py diff --git a/.env.example b/.env.example index dd85b655c..4b7cfabfe 100644 --- a/.env.example +++ b/.env.example @@ -111,10 +111,6 @@ LNPAY_API_KEY=LNPAY_API_KEY # Wallet Admin in Wallet Access Keys LNPAY_WALLET_KEY=LNPAY_ADMIN_KEY -# LntxbotWallet -LNTXBOT_API_ENDPOINT=https://lntxbot.com/ -LNTXBOT_KEY=LNTXBOT_ADMIN_KEY - # OpenNodeWallet OPENNODE_API_ENDPOINT=https://api.opennode.com/ OPENNODE_KEY=OPENNODE_ADMIN_KEY diff --git a/README.md b/README.md index 0f81b99f2..4727cad49 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ LNbits is a Python server that sits on top of any funding source. It can be used * Fallback wallet for the LNURL scheme * Instant wallet for LN demonstrations -LNbits can run on top of any Lightning funding source. It supports LND, CLN, Eclair, Spark, LNpay, OpenNode, lntxbot, LightningTipBot, and with more being added regularly. +LNbits can run on top of any Lightning funding source. It supports LND, CLN, Eclair, Spark, LNpay, OpenNode, LightningTipBot, and with more being added regularly. See [docs.lnbits.org](https://docs.lnbits.org) for more detailed documentation. diff --git a/docs/guide/wallets.md b/docs/guide/wallets.md index 10724f34b..a10e09a9a 100644 --- a/docs/guide/wallets.md +++ b/docs/guide/wallets.md @@ -8,7 +8,7 @@ nav_order: 3 Backend wallets =============== -LNbits can run on top of many lightning-network funding sources. Currently there is support for CoreLightning, LND, LNbits, LNPay, lntxbot and OpenNode, with more being added regularly. +LNbits can run on top of many lightning-network funding sources. Currently there is support for CoreLightning, LND, LNbits, LNPay and OpenNode, with more being added regularly. A backend wallet can be configured using the following LNbits environment variables: @@ -65,13 +65,6 @@ For the invoice listener to work you have a publicly accessible URL in your LNbi - `LNPAY_WALLET_KEY`: waka_apiKey -### lntxbot - -- `LNBITS_BACKEND_WALLET_CLASS`: **LntxbotWallet** -- `LNTXBOT_API_ENDPOINT`: https://lntxbot.com/ -- `LNTXBOT_KEY`: lntxbotAdminApiKey - - ### OpenNode For the invoice to work you must have a publicly accessible URL in your LNbits. No manual webhook setting is necessary. diff --git a/lnbits/core/templates/core/index.html b/lnbits/core/templates/core/index.html index 104dccd94..e23f5ca44 100644 --- a/lnbits/core/templates/core/index.html +++ b/lnbits/core/templates/core/index.html @@ -43,7 +43,7 @@

Easy to set up and lightweight, LNbits can run on any lightning-network funding source, currently supporting LND, - c-lightning, OpenNode, lntxbot, LNPay and even LNbits itself! + c-lightning, OpenNode, LNPay and even LNbits itself!

You can run LNbits for yourself, or easily offer a custodian @@ -135,24 +135,6 @@ -

-
- - - -
-
- - - -
-
 
+
+ + + +
{% if AD_SPACE %} {% for ADS in AD_SPACE %} {% set AD = ADS.split(';') %} diff --git a/lnbits/settings.py b/lnbits/settings.py index 0f1036825..3934c18e2 100644 --- a/lnbits/settings.py +++ b/lnbits/settings.py @@ -147,11 +147,6 @@ class LnPayFundingSource(LNbitsSettings): lnpay_wallet_key: Optional[str] = Field(default=None) -class LnTxtBotFundingSource(LNbitsSettings): - lntxbot_api_endpoint: Optional[str] = Field(default=None) - lntxbot_key: Optional[str] = Field(default=None) - - class OpenNodeFundingSource(LNbitsSettings): opennode_api_endpoint: Optional[str] = Field(default=None) opennode_key: Optional[str] = Field(default=None) diff --git a/lnbits/wallets/__init__.py b/lnbits/wallets/__init__.py index 76c47c048..c16fb42e3 100644 --- a/lnbits/wallets/__init__.py +++ b/lnbits/wallets/__init__.py @@ -11,7 +11,6 @@ from .lndgrpc import LndWallet from .lndrest import LndRestWallet from .lnpay import LNPayWallet from .lntips import LnTipsWallet -from .lntxbot import LntxbotWallet from .opennode import OpenNodeWallet from .spark import SparkWallet from .void import VoidWallet diff --git a/lnbits/wallets/lntxbot.py b/lnbits/wallets/lntxbot.py deleted file mode 100644 index a1e41bd22..000000000 --- a/lnbits/wallets/lntxbot.py +++ /dev/null @@ -1,156 +0,0 @@ -import asyncio -import hashlib -import json -from typing import AsyncGenerator, Dict, Optional - -import httpx -from loguru import logger - -from lnbits.settings import settings - -from .base import ( - InvoiceResponse, - PaymentResponse, - PaymentStatus, - StatusResponse, - Wallet, -) - - -class LntxbotWallet(Wallet): - """https://github.com/fiatjaf/lntxbot/blob/master/api.go""" - - def __init__(self): - endpoint = settings.lntxbot_api_endpoint - self.endpoint = endpoint[:-1] if endpoint.endswith("/") else endpoint - - key = ( - settings.lntxbot_key - or settings.lntxbot_admin_key - or settings.lntxbot_invoice_key - ) - self.auth = {"Authorization": f"Basic {key}"} - - async def status(self) -> StatusResponse: - async with httpx.AsyncClient() as client: - r = await client.get( - f"{self.endpoint}/balance", headers=self.auth, timeout=40 - ) - try: - data = r.json() - except: - return StatusResponse( - f"Failed to connect to {self.endpoint}, got: '{r.text[:200]}...'", 0 - ) - - if data.get("error"): - return StatusResponse(data["message"], 0) - - return StatusResponse(None, data["BTC"]["AvailableBalance"] * 1000) - - async def create_invoice( - self, - amount: int, - memo: Optional[str] = None, - description_hash: Optional[bytes] = None, - unhashed_description: Optional[bytes] = None, - **kwargs, - ) -> InvoiceResponse: - data: Dict = {"amt": str(amount)} - if description_hash: - data["description_hash"] = description_hash.hex() - elif unhashed_description: - data["description_hash"] = hashlib.sha256(unhashed_description).hexdigest() - else: - data["memo"] = memo or "" - - async with httpx.AsyncClient() as client: - r = await client.post( - f"{self.endpoint}/addinvoice", headers=self.auth, json=data, timeout=40 - ) - - if r.is_error: - try: - data = r.json() - error_message = data["message"] - except: - error_message = r.text - - return InvoiceResponse(False, None, None, error_message) - - data = r.json() - return InvoiceResponse(True, data["payment_hash"], data["pay_req"], None) - - async def pay_invoice(self, bolt11: str, fee_limit_msat: int) -> PaymentResponse: - async with httpx.AsyncClient() as client: - r = await client.post( - f"{self.endpoint}/payinvoice", - headers=self.auth, - json={"invoice": bolt11}, - timeout=None, - ) - - if "error" in r.json(): - try: - data = r.json() - error_message = data["message"] - except: - error_message = r.text - return PaymentResponse(False, None, None, None, error_message) - - data = r.json() - if data.get("type") != "paid_invoice": - return PaymentResponse(None) - checking_id = data["payment_hash"] - fee_msat = -data["fee_msat"] - preimage = data["payment_preimage"] - return PaymentResponse(True, checking_id, fee_msat, preimage, None) - - async def get_invoice_status(self, checking_id: str) -> PaymentStatus: - async with httpx.AsyncClient() as client: - r = await client.post( - f"{self.endpoint}/invoicestatus/{checking_id}?wait=false", - headers=self.auth, - ) - - data = r.json() - if r.is_error or "error" in data: - return PaymentStatus(None) - - if "preimage" not in data: - return PaymentStatus(False) - - return PaymentStatus(True) - - async def get_payment_status(self, checking_id: str) -> PaymentStatus: - async with httpx.AsyncClient() as client: - r = await client.post( - url=f"{self.endpoint}/paymentstatus/{checking_id}", headers=self.auth - ) - - data = r.json() - if r.is_error or "error" in data: - return PaymentStatus(None) - - statuses = {"complete": True, "failed": False, "pending": None, "unknown": None} - return PaymentStatus(statuses[data.get("status", "unknown")]) - - async def paid_invoices_stream(self) -> AsyncGenerator[str, None]: - url = f"{self.endpoint}/payments/stream" - - while True: - try: - async with httpx.AsyncClient(timeout=None, headers=self.auth) as client: - async with client.stream("GET", url) as r: - async for line in r.aiter_lines(): - if line.startswith("data:"): - data = json.loads(line[5:]) - if "payment_hash" in data and data.get("msatoshi") > 0: - yield data["payment_hash"] - except (OSError, httpx.ReadError, httpx.ReadTimeout, httpx.ConnectError): - pass - - logger.error( - "lost connection to lntxbot /payments/stream, retrying in 5 seconds" - ) - await asyncio.sleep(5)