Merge pull request #1542 from lnbits/pullntxbot

RIP Lntxbot, thank you for all your help building LN, you will be missed :(
This commit is contained in:
Arc 2023-03-07 12:48:44 +00:00 committed by GitHub
commit 2787d5c6b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 13 additions and 197 deletions

View File

@ -62,7 +62,7 @@ LNBITS_SITE_DESCRIPTION="Some description about your service, will display if ti
LNBITS_THEME_OPTIONS="classic, bitcoin, flamingo, freedom, mint, autumn, monochrome, salvador, cyber"
# LNBITS_CUSTOM_LOGO="https://lnbits.com/assets/images/logo/logo.svg"
# Choose from LNPayWallet, OpenNodeWallet, LntxbotWallet, ClicheWallet,
# Choose from LNPayWallet, OpenNodeWallet, ClicheWallet,
# LndWallet, LndRestWallet, CoreLightningWallet, EclairWallet,
# LnTipsWallet, LNbitsWallet, SparkWallet, FakeWallet,
LNBITS_BACKEND_WALLET_CLASS=VoidWallet
@ -110,10 +110,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 [LNbits Wiki](github.com/lnbits/lnbits/wiki/) for more detailed documentation.

View File

@ -169,7 +169,7 @@ allow-self-payment=1
<ul> <p>LNbits has all sorts of open APIs and tools to program and connect to a lot of different devices for a gazillion of use-cases. Let us know what you did with it ! Come to the <a href="https://t.me/makerbits">Makerbits Telegram Group</a> if you are interested in building or if you need help with a project - we got you!</p>
<details><summary>ATM - deposit and withdraw in your shop or at your meetup</summary>
<p>This is a do-it-yourself project consisting of a mini-computer (Raspberry Pi Zero), a coin acceptor, a display, a 3D printed case, and a Bitcoin Lightning wallet as a funding source. It exchanges fiat coins for valuable Bitcoin Lightning ⚡ Satoshis. The user can pick up the Satoshis via QR code (LNURL-withdraw) on a mobile phone wallet. It works based on BTCPayer server, LNTXBOT is not longer an option. You can get the components as individual parts and build the case yourself e.g. from <a href="https://www.Fulmo.org">Fulmo</a> who also made a <a href="https://blog.fulmo.org/the-lightningatm-pocket-edition/">guide</a> on it. The shop offers payments in Bitcoin and Lightning ⚡. The code can be found on <a href="https://github.com/21isenough/LightningATM">the ATM github project page></a>.</p>
<p>This is a do-it-yourself project consisting of a mini-computer (Raspberry Pi Zero), a coin acceptor, a display, a 3D printed case, and a Bitcoin Lightning wallet as a funding source. It exchanges fiat coins for valuable Bitcoin Lightning ⚡ Satoshis. The user can pick up the Satoshis via QR code (LNURL-withdraw) on a mobile phone wallet. You can get the components as individual parts and build the case yourself e.g. from <a href="https://www.Fulmo.org">Fulmo</a> who also made a <a href="https://blog.fulmo.org/the-lightningatm-pocket-edition/">guide</a> on it. The shop offers payments in Bitcoin and Lightning ⚡. The code can be found on <a href="https://github.com/21isenough/LightningATM">the ATM github project page></a>.</p>
</details>
<details><summary>POS Terminal - an offline terminal for merchants</summary>

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)
@ -190,7 +185,6 @@ class FundingSourcesSettings(
LndRestFundingSource,
LndGrpcFundingSource,
LnPayFundingSource,
LnTxtBotFundingSource,
OpenNodeFundingSource,
SparkFundingSource,
LnTipsFundingSource,

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)