RIP Lntxbot, thank you for all your help building LN, you will be missed :(

This commit is contained in:
Ben Arc 2023-02-23 11:41:44 +00:00
parent a154ff3175
commit cbde5744aa
7 changed files with 11 additions and 194 deletions

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -43,7 +43,7 @@
<p>
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!
</p>
<p>
You can run LNbits for yourself, or easily offer a custodian
@ -135,24 +135,6 @@
</div>
</div>
<div class="row">
<div class="col">
<a href="https://github.com/shesek/spark-wallet">
<q-img
contain
:src="($q.dark.isActive) ? '/static/images/spark.png' : '/static/images/sparkl.png'"
></q-img>
</a>
</div>
<div class="col q-pl-md">
<a href="https://t.me/lntxbot">
<q-img
contain
:src="($q.dark.isActive) ? '/static/images/lntxbot.png' : '/static/images/lntxbotl.png'"
></q-img>
</a>
</div>
</div>
<div class="row">
<div class="col">
<a href="https://github.com/rootzoll/raspiblitz">
@ -182,6 +164,14 @@
</div>
<div class="col q-pl-md">&nbsp;</div>
</div>
<div class="col">
<a href="https://github.com/shesek/spark-wallet">
<q-img
contain
:src="($q.dark.isActive) ? '/static/images/spark.png' : '/static/images/sparkl.png'"
></q-img>
</a>
</div>
</div>
{% if AD_SPACE %} {% for ADS in AD_SPACE %} {% set AD = ADS.split(';') %}

View File

@ -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)

View File

@ -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

View File

@ -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)