Logging with loguru (#708)

* logging

* requirements

* add loguru dependency

* restore it

* add loguru

* set log level in .env file

* remove service fee print

* set log level

* more logging

* more logging

* more logging

* pyament.checking_id

* fix
This commit is contained in:
calle 2022-07-07 14:30:16 +02:00 committed by GitHub
parent 847fd18796
commit 089313f613
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 202 additions and 81 deletions

View File

@ -1,10 +1,8 @@
QUART_APP=lnbits.app:create_app()
QUART_ENV=development
QUART_DEBUG=true
HOST=127.0.0.1
PORT=5000
DEBUG=true
LNBITS_ALLOWED_USERS=""
LNBITS_ADMIN_USERS=""
# Extensions only admin can access

View File

@ -12,6 +12,7 @@ cerberus = "*"
ecdsa = "*"
environs = "*"
lnurl = "==0.3.6"
loguru = "*"
pyscss = "*"
shortuuid = "*"
typing-extensions = "*"

View File

@ -3,15 +3,19 @@ import asyncio
import uvloop
from starlette.requests import Request
from loguru import logger
from .commands import bundle_vendored, migrate_databases, transpile_scss
from .settings import (
DEBUG,
LNBITS_COMMIT,
LNBITS_DATA_FOLDER,
LNBITS_SITE_TITLE,
HOST,
PORT,
SERVICE_FEE,
WALLET,
LNBITS_DATABASE_URL,
LNBITS_DATA_FOLDER,
)
uvloop.install()
@ -24,13 +28,15 @@ from .app import create_app
app = create_app()
print(
f"""Starting LNbits with
- git version: {LNBITS_COMMIT}
- site title: {LNBITS_SITE_TITLE}
- debug: {DEBUG}
- data folder: {LNBITS_DATA_FOLDER}
- funding source: {WALLET.__class__.__name__}
- service fee: {SERVICE_FEE}
"""
logger.info("Starting LNbits")
logger.info(f"Host: {HOST}")
logger.info(f"Port: {PORT}")
logger.info(f"Debug: {DEBUG}")
logger.info(f"Site title: {LNBITS_SITE_TITLE}")
logger.info(f"Funding source: {WALLET.__class__.__name__}")
logger.info(
f"Database: {'PostgreSQL' if LNBITS_DATABASE_URL.startswith('postgres://') else 'CockroachDB' if LNBITS_DATABASE_URL.startswith('cockroachdb://') else 'SQLite'}"
)
logger.info(f"Data folder: {LNBITS_DATA_FOLDER}")
logger.info(f"Git version: {LNBITS_COMMIT}")
# logger.info(f"Service fee: {SERVICE_FEE}")

View File

@ -3,6 +3,9 @@ import importlib
import sys
import traceback
import warnings
from loguru import logger
from http import HTTPStatus
from fastapi import FastAPI, Request
@ -41,6 +44,8 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
"""Create application factory.
:param config_object: The configuration object to use.
"""
set_logging_level()
app = FastAPI()
app.mount("/static", StaticFiles(directory="lnbits/static"), name="static")
app.mount(
@ -94,14 +99,14 @@ def check_funding_source(app: FastAPI) -> None:
error_message, balance = await WALLET.status()
if not error_message:
break
warnings.warn(
f" × The backend for {WALLET.__class__.__name__} isn't working properly: '{error_message}'",
logger.error(
f"The backend for {WALLET.__class__.__name__} isn't working properly: '{error_message}'",
RuntimeWarning,
)
print("Retrying connection to backend in 5 seconds...")
logger.info("Retrying connection to backend in 5 seconds...")
await asyncio.sleep(5)
print(
f" ✔️ {WALLET.__class__.__name__} seems to be connected and with a balance of {balance} msat."
logger.info(
f"✔️ Backend {WALLET.__class__.__name__} connected and with a balance of {balance} msat."
)
@ -124,9 +129,10 @@ def register_routes(app: FastAPI) -> None:
for s in ext_statics:
app.mount(s["path"], s["app"], s["name"])
logger.trace(f"adding route for extension {ext_module}")
app.include_router(ext_route)
except Exception as e:
print(str(e))
logger.error(str(e))
raise ImportError(
f"Please make sure that the extension `{ext.code}` follows conventions."
)
@ -173,8 +179,8 @@ def register_async_tasks(app):
def register_exception_handlers(app: FastAPI):
@app.exception_handler(Exception)
async def basic_error(request: Request, err):
print("handled error", traceback.format_exc())
print("ERROR:", err)
logger.error("handled error", traceback.format_exc())
logger.error("ERROR:", err)
etype, _, tb = sys.exc_info()
traceback.print_exception(etype, err, tb)
exc = traceback.format_exc()
@ -188,3 +194,10 @@ def register_exception_handlers(app: FastAPI):
status_code=HTTPStatus.NO_CONTENT,
content={"detail": err},
)
def set_logging_level() -> None:
"""Set the logging level for the application."""
logger.remove()
log_level: str = "DEBUG" if lnbits.settings.DEBUG else "INFO"
logger.add(sys.stderr, level=log_level)

View File

@ -5,6 +5,8 @@ import importlib
import re
import os
from loguru import logger
from .db import SQLITE, POSTGRES, COCKROACH
from .core import db as core_db, migrations as core_migrations
from .helpers import (
@ -69,7 +71,7 @@ async def migrate_databases():
if match:
version = int(match.group(1))
if version > current_versions.get(db_name, 0):
print(f"running migration {db_name}.{version}")
logger.debug(f"running migration {db_name}.{version}")
await migrate(db)
if db.schema == None:
@ -110,4 +112,4 @@ async def migrate_databases():
async with ext_db.connect() as ext_conn:
await run_migration(ext_conn, ext_migrations)
print(" ✔️ All migrations done.")
logger.info("✔️ All migrations done.")

View File

@ -7,6 +7,9 @@ from lnurl import encode as lnurl_encode # type: ignore
from typing import List, NamedTuple, Optional, Dict
from sqlite3 import Row
from pydantic import BaseModel
from loguru import logger
from lnbits.settings import WALLET
@ -142,10 +145,12 @@ class Payment(BaseModel):
status = await WALLET.get_invoice_status(self.checking_id)
if self.is_out and status.failed:
print(f" - deleting outgoing failed payment {self.checking_id}: {status}")
logger.info(
f" - deleting outgoing failed payment {self.checking_id}: {status}"
)
await self.delete()
elif not status.pending:
print(
logger.info(
f" - marking '{'in' if self.is_in else 'out'}' {self.checking_id} as not pending anymore: {status}"
)
await self.set_pending(status.pending)

View File

@ -3,6 +3,9 @@ import json
from binascii import unhexlify
from io import BytesIO
from typing import Dict, Optional, Tuple
from loguru import logger
from urllib.parse import parse_qs, urlparse
import httpx
@ -120,6 +123,7 @@ async def pay_invoice(
# check_internal() returns the checking_id of the invoice we're waiting for
internal_checking_id = await check_internal(invoice.payment_hash, conn=conn)
if internal_checking_id:
logger.debug(f"creating temporary internal payment with id {internal_id}")
# create a new payment from this wallet
await create_payment(
checking_id=internal_id,
@ -129,6 +133,7 @@ async def pay_invoice(
**payment_kwargs,
)
else:
logger.debug(f"creating temporary payment with id {temp_id}")
# create a temporary payment here so we can check if
# the balance is enough in the next step
await create_payment(
@ -142,6 +147,7 @@ async def pay_invoice(
wallet = await get_wallet(wallet_id, conn=conn)
assert wallet
if wallet.balance_msat < 0:
logger.debug("balance is too low, deleting temporary payment")
if not internal_checking_id and wallet.balance_msat > -fee_reserve_msat:
raise PaymentFailure(
f"You must reserve at least 1% ({round(fee_reserve_msat/1000)} sat) to cover potential routing fees."
@ -149,6 +155,7 @@ async def pay_invoice(
raise PermissionError("Insufficient balance.")
if internal_checking_id:
logger.debug(f"marking temporary payment as not pending {internal_checking_id}")
# mark the invoice from the other side as not pending anymore
# so the other side only has access to his new money when we are sure
# the payer has enough to deduct from
@ -163,11 +170,14 @@ async def pay_invoice(
await internal_invoice_queue.put(internal_checking_id)
else:
logger.debug(f"backend: sending payment {temp_id}")
# actually pay the external invoice
payment: PaymentResponse = await WALLET.pay_invoice(
payment_request, fee_reserve_msat
)
logger.debug(f"backend: pay_invoice finished {temp_id}")
if payment.checking_id:
logger.debug(f"creating final payment {payment.checking_id}")
async with db.connect() as conn:
await create_payment(
checking_id=payment.checking_id,
@ -177,15 +187,18 @@ async def pay_invoice(
conn=conn,
**payment_kwargs,
)
logger.debug(f"deleting temporary payment {temp_id}")
await delete_payment(temp_id, conn=conn)
else:
logger.debug(f"backend payment failed, no checking_id {temp_id}")
async with db.connect() as conn:
logger.debug(f"deleting temporary payment {temp_id}")
await delete_payment(temp_id, conn=conn)
raise PaymentFailure(
payment.error_message
or "Payment failed, but backend didn't give us an error message."
)
logger.debug(f"payment successful {payment.checking_id}")
return invoice.payment_hash
@ -216,7 +229,7 @@ async def redeem_lnurl_withdraw(
conn=conn,
)
except:
print(
logger.warn(
f"failed to create invoice on redeem_lnurl_withdraw from {lnurl}. params: {res}"
)
return None
@ -325,11 +338,11 @@ async def check_invoice_status(
if not payment.pending:
return status
if payment.is_out and status.failed:
print(f" - deleting outgoing failed payment {payment.checking_id}: {status}")
logger.info(f"deleting outgoing failed payment {payment.checking_id}: {status}")
await payment.delete()
elif not status.pending:
print(
f" - marking '{'in' if payment.is_in else 'out'}' {payment.checking_id} as not pending anymore: {status}"
logger.info(
f"marking '{'in' if payment.is_in else 'out'}' {payment.checking_id} as not pending anymore: {status}"
)
await payment.set_pending(status.pending)
return status

View File

@ -2,6 +2,8 @@ import asyncio
import httpx
from typing import List
from loguru import logger
from lnbits.tasks import register_invoice_listener
from . import db
@ -20,7 +22,7 @@ async def register_task_listeners():
async def wait_for_paid_invoices(invoice_paid_queue: asyncio.Queue):
while True:
payment = await invoice_paid_queue.get()
logger.debug("received invoice paid event")
# send information to sse channel
await dispatch_invoice_listener(payment)
@ -44,7 +46,7 @@ async def dispatch_invoice_listener(payment: Payment):
try:
send_channel.put_nowait(payment)
except asyncio.QueueFull:
print("removing sse listener", send_channel)
logger.debug("removing sse listener", send_channel)
api_invoice_listeners.remove(send_channel)
@ -52,6 +54,7 @@ async def dispatch_webhook(payment: Payment):
async with httpx.AsyncClient() as client:
data = payment.dict()
try:
logger.debug("sending webhook", payment.webhook)
r = await client.post(payment.webhook, json=data, timeout=40)
await mark_webhook_sent(payment, r.status_code)
except (httpx.ConnectError, httpx.RequestError):

View File

@ -7,6 +7,9 @@ from typing import Dict, List, Optional, Union
from urllib.parse import ParseResult, parse_qs, urlencode, urlparse, urlunparse
import httpx
from loguru import logger
from fastapi import Header, Query, Request
from fastapi.exceptions import HTTPException
from fastapi.param_functions import Depends
@ -347,7 +350,7 @@ async def subscribe(request: Request, wallet: Wallet):
payment_queue: asyncio.Queue[Payment] = asyncio.Queue(0)
print("adding sse listener", payment_queue)
logger.debug("adding sse listener", payment_queue)
api_invoice_listeners.append(payment_queue)
send_queue: asyncio.Queue[tuple[str, Payment]] = asyncio.Queue(0)
@ -356,6 +359,7 @@ async def subscribe(request: Request, wallet: Wallet):
while True:
payment: Payment = await payment_queue.get()
if payment.wallet_id == this_wallet_id:
logger.debug("payment receieved", payment)
await send_queue.put(("payment-received", payment))
asyncio.create_task(payment_received())
@ -391,7 +395,7 @@ async def api_payment(payment_hash, X_Api_Key: Optional[str] = Header(None)):
wallet = None
try:
if X_Api_Key.extra:
print("No key")
logger.warn("No key")
except:
wallet = await get_wallet_for_key(X_Api_Key)
payment = await get_standalone_payment(payment_hash)

View File

@ -10,6 +10,8 @@ from fastapi.routing import APIRouter
from pydantic.types import UUID4
from starlette.responses import HTMLResponse, JSONResponse
from loguru import logger
from lnbits.core import db
from lnbits.core.models import User
from lnbits.decorators import check_user_exists
@ -66,10 +68,12 @@ async def extensions(
)
if extension_to_enable:
logger.info(f"Enabling extension: {extension_to_enable} for user {user.id}")
await update_user_extension(
user_id=user.id, extension=extension_to_enable, active=True
)
elif extension_to_disable:
logger.info(f"Disabling extension: {extension_to_disable} for user {user.id}")
await update_user_extension(
user_id=user.id, extension=extension_to_disable, active=False
)
@ -109,6 +113,7 @@ async def wallet(
if not user_id:
user = await get_user((await create_account()).id)
logger.info(f"Created new account for user {user.id}")
else:
user = await get_user(user_id)
if not user:
@ -126,12 +131,16 @@ async def wallet(
wallet = user.wallets[0]
else:
wallet = await create_wallet(user_id=user.id, wallet_name=wallet_name)
logger.info(
f"Created new wallet {wallet_name if wallet_name else '(no name)'} for user {user.id}"
)
return RedirectResponse(
f"/wallet?usr={user.id}&wal={wallet.id}",
status_code=status.HTTP_307_TEMPORARY_REDIRECT,
)
logger.info(f"Access wallet {wallet_name} of user {user.id}")
wallet = user.get_wallet(wallet_id)
if not wallet:
return template_renderer().TemplateResponse(
@ -202,13 +211,13 @@ async def lnurl_full_withdraw_callback(request: Request):
async def deletewallet(request: Request, wal: str = Query(...), usr: str = Query(...)):
user = await get_user(usr)
user_wallet_ids = [u.id for u in user.wallets]
print("USR", user_wallet_ids)
if wal not in user_wallet_ids:
raise HTTPException(HTTPStatus.FORBIDDEN, "Not your wallet.")
else:
await delete_wallet(user_id=user.id, wallet_id=wal)
user_wallet_ids.remove(wal)
logger.debug("Deleted wallet {wal} of user {user.id}")
if user_wallet_ids:
return RedirectResponse(

View File

@ -7,6 +7,8 @@ from fastapi import HTTPException
from starlette.requests import Request
from starlette.responses import HTMLResponse
from loguru import logger
from lnbits import bolt11
from .. import core_app
@ -45,7 +47,7 @@ async def api_public_payment_longpolling(payment_hash):
payment_queue = asyncio.Queue(0)
print("adding standalone invoice listener", payment_hash, payment_queue)
logger.debug("adding standalone invoice listener", payment_hash, payment_queue)
api_invoice_listeners.append(payment_queue)
response = None

View File

@ -5,6 +5,8 @@ import time
from contextlib import asynccontextmanager
from typing import Optional
from loguru import logger
from sqlalchemy import create_engine
from sqlalchemy_aio.base import AsyncConnection
from sqlalchemy_aio.strategy import ASYNCIO_STRATEGY # type: ignore
@ -139,7 +141,7 @@ class Database(Compat):
f"LNBITS_DATA_FOLDER named {LNBITS_DATA_FOLDER} was not created"
f" - please 'mkdir {LNBITS_DATA_FOLDER}' and try again"
)
logger.trace(f"database {self.type} added for {self.name}")
self.schema = self.name
if self.name.startswith("ext_"):
self.schema = self.name[4:]

View File

@ -5,6 +5,8 @@ from http import HTTPStatus
from starlette.requests import Request
from loguru import logger
from . import bleskomat_ext
from .crud import (
create_bleskomat_lnurl,
@ -122,7 +124,7 @@ async def api_bleskomat_lnurl(req: Request):
except LnurlHttpError as e:
return {"status": "ERROR", "reason": str(e)}
except Exception as e:
print(str(e))
logger.error(str(e))
return {"status": "ERROR", "reason": "Unexpected error"}
return {"status": "OK"}

View File

@ -6,6 +6,8 @@ from fastapi.params import Query
from pydantic import BaseModel, validator
from starlette.requests import Request
from loguru import logger
from lnbits import bolt11
from lnbits.core.services import pay_invoice, PaymentFailure
@ -125,7 +127,7 @@ class BleskomatLnurl(BaseModel):
except (ValueError, PermissionError, PaymentFailure) as e:
raise LnurlValidationError("Failed to pay invoice: " + str(e))
except Exception as e:
print(str(e))
logger.error(str(e))
raise LnurlValidationError("Unexpected error")
async def use(self, conn) -> bool:

View File

@ -3,6 +3,8 @@ from http import HTTPStatus
from fastapi import Depends, Query
from starlette.exceptions import HTTPException
from loguru import logger
from lnbits.core.crud import get_user
from lnbits.decorators import WalletTypeInfo, require_admin_key
from lnbits.extensions.bleskomat.models import CreateBleskomat
@ -60,7 +62,7 @@ async def api_bleskomat_create_or_update(
currency=fiat_currency, provider=exchange_rate_provider
)
except Exception as e:
print(e)
logger.error(e)
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail=f'Failed to fetch BTC/{fiat_currency} currency pair from "{exchange_rate_provider}"',

View File

@ -1,6 +1,8 @@
import asyncio
import json
from loguru import logger
from lnbits.core import db as core_db
from lnbits.core.crud import create_payment
from lnbits.core.models import Payment
@ -26,11 +28,11 @@ async def on_invoice_paid(payment: Payment) -> None:
track = await get_track(payment.extra.get("track", -1))
if not track:
print("this should never happen", payment)
logger.error("this should never happen", payment)
return
if payment.extra.get("shared_with"):
print("payment was shared already", payment)
logger.error("payment was shared already", payment)
return
producer = await get_producer(track.producer)

View File

@ -1,6 +1,8 @@
from datetime import datetime, timedelta
from typing import List, Optional, Union
from loguru import logger
from lnbits.helpers import urlsafe_short_hash
from . import db
@ -186,9 +188,9 @@ async def purge_addresses(domain_id: str):
) # give user 1 day to topup is address
if not paid and pay_expire:
print("DELETE UNP_PAY_EXP", r["username"])
logger.debug("DELETE UNP_PAY_EXP", r["username"])
await delete_address(r["id"])
if paid and expired:
print("DELETE PAID_EXP", r["username"])
logger.debug("DELETE PAID_EXP", r["username"])
await delete_address(r["id"])

View File

@ -3,6 +3,9 @@ import json
from datetime import datetime, timedelta
import httpx
from loguru import logger
from fastapi.params import Query
from lnurl import ( # type: ignore
LnurlErrorResponse,
@ -38,13 +41,12 @@ async def lnurl_response(username: str, domain: str, request: Request):
"maxSendable": 1000000000,
}
print("RESP", resp)
logger.debug("RESP", resp)
return resp
@lnaddress_ext.get("/lnurl/cb/{address_id}", name="lnaddress.lnurl_callback")
async def lnurl_callback(address_id, amount: int = Query(...)):
print("PING")
address = await get_address(address_id)
if not address:
return LnurlErrorResponse(reason=f"Address not found").dict()

View File

@ -1,5 +1,7 @@
import asyncio
from loguru import logger
from lnbits.core.models import Payment
from lnbits.tasks import register_invoice_listener
@ -22,7 +24,7 @@ async def on_invoice_paid(payment: Payment) -> None:
ticket = await get_ticket(payment.checking_id)
if not ticket:
print("this should never happen", payment)
logger.error("this should never happen", payment)
return
await payment.set_pending(False)

View File

@ -150,7 +150,7 @@ async def lnurl_v1_params(
"defaultDescription": device.title,
}
price_msat = int(price_msat * ((device.profit / 100) + 1) / 1000)
print(price_msat)
lnurldevicepayment = await create_lnurldevicepayment(
deviceid=device.id,
payload=p,
@ -204,7 +204,7 @@ async def lnurl_callback(
extra={"tag": "withdraw"},
)
return {"status": "OK"}
print(lnurldevicepayment.sats)
payment_hash, payment_request = await create_invoice(
wallet_id=device.wallet,
amount=lnurldevicepayment.sats / 1000,

View File

@ -2,6 +2,9 @@ import asyncio
from http import HTTPStatus
import httpx
from loguru import logger
from starlette.exceptions import HTTPException
from lnbits.core import db as core_db
@ -27,7 +30,7 @@ async def on_invoice_paid(payment: Payment) -> None:
try:
# Check its got a payout associated with it
lnurlpayout_link = await get_lnurlpayout_from_wallet(payment.wallet_id)
print("LNURLpayout", lnurlpayout_link)
logger.debug("LNURLpayout", lnurlpayout_link)
if lnurlpayout_link:
# Check the wallet balance is more than the threshold

View File

@ -1,5 +1,7 @@
import asyncio
from loguru import logger
from lnbits.core.models import Payment
from lnbits.extensions.satspay.crud import check_address_balance, get_charge
from lnbits.tasks import register_invoice_listener
@ -23,7 +25,7 @@ async def on_invoice_paid(payment: Payment) -> None:
charge = await get_charge(payment.memo)
if not charge:
print("this should never happen", payment)
logger.error("this should never happen", payment)
return
await payment.set_pending(False)

View File

@ -1,6 +1,8 @@
import asyncio
import json
from loguru import logger
from lnbits.core import db as core_db
from lnbits.core.crud import create_payment
from lnbits.core.models import Payment
@ -34,7 +36,9 @@ async def on_invoice_paid(payment: Payment) -> None:
amount_left = payment.amount - sum([amount for _, amount in transfers])
if amount_left < 0:
print("splitpayments failure: amount_left is negative.", payment.payment_hash)
logger.error(
"splitpayments failure: amount_left is negative.", payment.payment_hash
)
return
if not targets:

View File

@ -4,6 +4,8 @@ from fastapi import Query
from fastapi.params import Depends
from starlette.exceptions import HTTPException
from loguru import logger
from lnbits.core.crud import get_user
from lnbits.core.services import create_invoice
from lnbits.core.views.api import api_payment
@ -88,6 +90,6 @@ async def api_tpos_check_invoice(tpos_id: str, payment_hash: str):
status = await api_payment(payment_hash)
except Exception as exc:
print(exc)
logger.error(exc)
return {"paid": False}
return status

View File

@ -5,6 +5,8 @@ import httpx
from datetime import datetime
from http import HTTPStatus
from loguru import logger
import shortuuid # type: ignore
from fastapi import HTTPException
from fastapi.param_functions import Query
@ -136,13 +138,13 @@ async def api_lnurl_callback(
)
except Exception as exc:
# webhook fails shouldn't cause the lnurlw to fail since invoice is already paid
print("Caught exception when dispatching webhook url:", exc)
logger.error("Caught exception when dispatching webhook url:", exc)
return {"status": "OK"}
except Exception as e:
await update_withdraw_link(link.id, **changesback)
print(traceback.format_exc())
logger.error(traceback.format_exc())
return {"status": "ERROR", "reason": "Link not working"}

View File

@ -13,8 +13,8 @@ wallet_class = getattr(
wallets_module, env.str("LNBITS_BACKEND_WALLET_CLASS", default="VoidWallet")
)
ENV = env.str("QUART_ENV", default="production")
DEBUG = env.bool("QUART_DEBUG", default=False) or ENV == "development"
DEBUG = env.bool("DEBUG", default=False)
HOST = env.str("HOST", default="127.0.0.1")
PORT = env.int("PORT", default=5000)

View File

@ -4,6 +4,8 @@ import traceback
from http import HTTPStatus
from typing import List, Callable
from loguru import logger
from fastapi.exceptions import HTTPException
from lnbits.settings import WALLET
@ -37,9 +39,9 @@ async def catch_everything_and_restart(func):
except asyncio.CancelledError:
raise # because we must pass this up
except Exception as exc:
print("caught exception in background task:", exc)
print(traceback.format_exc())
print("will restart the task in 5 seconds.")
logger.error("caught exception in background task:", exc)
logger.error(traceback.format_exc())
logger.error("will restart the task in 5 seconds.")
await asyncio.sleep(5)
await catch_everything_and_restart(func)
@ -77,7 +79,7 @@ async def internal_invoice_listener():
async def invoice_listener():
async for checking_id in WALLET.paid_invoices_stream():
print("> got a payment notification", checking_id)
logger.info("> got a payment notification", checking_id)
asyncio.create_task(invoice_callback_dispatcher(checking_id))
@ -117,6 +119,7 @@ async def perform_balance_checks():
async def invoice_callback_dispatcher(checking_id: str):
payment = await get_standalone_payment(checking_id, incoming=True)
if payment and payment.is_in:
logger.trace("sending invoice callback for payment", checking_id)
await payment.set_pending(False)
for send_chan in invoice_listeners:
await send_chan.put(payment)

View File

@ -1,6 +1,8 @@
import asyncio
from typing import Callable, NamedTuple
from loguru import logger
import httpx
currencies = {
@ -280,7 +282,7 @@ async def btc_price(currency: str) -> float:
if not rates:
return 9999999999
elif len(rates) == 1:
print("Warning could only fetch one Bitcoin price.")
logger.warn("Could only fetch one Bitcoin price.")
return sum([rate for rate in rates]) / len(rates)

View File

@ -5,6 +5,8 @@ import urllib.parse
from os import getenv
from typing import AsyncGenerator, Dict, Optional
from loguru import logger
import httpx
from websockets import connect
from websockets.exceptions import (
@ -193,8 +195,8 @@ class EclairWallet(Wallet):
ConnectionClosedError,
ConnectionClosed,
) as ose:
print("OSE", ose)
logger.error("OSE", ose)
pass
print("lost connection to eclair's websocket, retrying in 5 seconds")
logger.error("lost connection to eclair's websocket, retrying in 5 seconds")
await asyncio.sleep(5)

View File

@ -1,11 +1,12 @@
import asyncio
import json
import httpx
from os import getenv
from datetime import datetime, timedelta
from datetime import datetime
from typing import Optional, Dict, AsyncGenerator
import random
import string
from loguru import logger
from lnbits.helpers import urlsafe_short_hash
import hashlib
from ..bolt11 import encode, decode
@ -20,7 +21,7 @@ from .base import (
class FakeWallet(Wallet):
async def status(self) -> StatusResponse:
print(
logger.info(
"FakeWallet funding source is for using LNbits as a centralised, stand-alone payment system with brrrrrr."
)
return StatusResponse(None, float("inf"))

View File

@ -4,6 +4,8 @@ import httpx
from os import getenv
from typing import Optional, Dict, AsyncGenerator
from loguru import logger
from .base import (
StatusResponse,
InvoiceResponse,
@ -144,5 +146,7 @@ class LNbitsWallet(Wallet):
except (OSError, httpx.ReadError, httpx.ConnectError, httpx.ReadTimeout):
pass
print("lost connection to lnbits /payments/sse, retrying in 5 seconds")
logger.error(
"lost connection to lnbits /payments/sse, retrying in 5 seconds"
)
await asyncio.sleep(5)

View File

@ -11,6 +11,9 @@ import base64
import hashlib
from os import environ, error, getenv
from typing import Optional, Dict, AsyncGenerator
from loguru import logger
from .macaroon import load_macaroon, AESCipher
if imports_ok:
@ -187,6 +190,8 @@ class LndWallet(Wallet):
checking_id = stringify_checking_id(i.r_hash)
yield checking_id
except error:
print(error)
logger.error(error)
print("lost connection to lnd InvoiceSubscription, please restart lnbits.")
logger.error(
"lost connection to lnd InvoiceSubscription, please restart lnbits."
)

View File

@ -6,6 +6,8 @@ import base64
from os import getenv
from typing import Optional, Dict, AsyncGenerator
from loguru import logger
from lnbits import bolt11 as lnbits_bolt11
from .macaroon import load_macaroon, AESCipher
@ -191,5 +193,7 @@ class LndRestWallet(Wallet):
except (OSError, httpx.ConnectError, httpx.ReadError):
pass
print("lost connection to lnd invoices stream, retrying in 5 seconds")
logger.error(
"lost connection to lnd invoices stream, retrying in 5 seconds"
)
await asyncio.sleep(5)

View File

@ -6,6 +6,8 @@ from os import getenv
from http import HTTPStatus
from typing import Optional, Dict, AsyncGenerator
from loguru import logger
from .base import (
StatusResponse,
InvoiceResponse,
@ -127,7 +129,7 @@ class LNPayWallet(Wallet):
try:
data = json.loads(text)
except json.decoder.JSONDecodeError:
print(f"got something wrong on lnpay webhook endpoint: {text[:200]}")
logger.error(f"got something wrong on lnpay webhook endpoint: {text[:200]}")
data = None
if (
type(data) is not dict

View File

@ -4,6 +4,8 @@ import httpx
from os import getenv
from typing import Optional, Dict, AsyncGenerator
from loguru import logger
from .base import (
StatusResponse,
InvoiceResponse,
@ -143,5 +145,7 @@ class LntxbotWallet(Wallet):
except (OSError, httpx.ReadError, httpx.ReadTimeout, httpx.ConnectError):
pass
print("lost connection to lntxbot /payments/stream, retrying in 5 seconds")
logger.error(
"lost connection to lntxbot /payments/stream, retrying in 5 seconds"
)
await asyncio.sleep(5)

View File

@ -4,6 +4,8 @@ import base64
from hashlib import md5
import getpass
from loguru import logger
BLOCK_SIZE = 16
import getpass
@ -103,5 +105,5 @@ if __name__ == "__main__":
macaroon = input("Enter macaroon: ")
macaroon = load_macaroon(macaroon)
macaroon = AESCipher(description="encryption").encrypt(macaroon.encode())
print("Encrypted macaroon:")
print(macaroon)
logger.info("Encrypted macaroon:")
logger.info(macaroon)

View File

@ -8,6 +8,8 @@ from http import HTTPStatus
from os import getenv
from typing import Optional, AsyncGenerator
from loguru import logger
from .base import (
StatusResponse,
InvoiceResponse,
@ -139,7 +141,7 @@ class OpenNodeWallet(Wallet):
x = hmac.new(self.auth["Authorization"].encode("ascii"), digestmod="sha256")
x.update(charge_id.encode("ascii"))
if x.hexdigest() != data["hashed_order"]:
print("invalid webhook, not from opennode")
logger.error("invalid webhook, not from opennode")
raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
await self.queue.put(charge_id)

View File

@ -5,6 +5,8 @@ import random
from os import getenv
from typing import Optional, AsyncGenerator
from loguru import logger
from .base import (
StatusResponse,
InvoiceResponse,
@ -204,5 +206,5 @@ class SparkWallet(Wallet):
except (OSError, httpx.ReadError, httpx.ConnectError, httpx.ReadTimeout):
pass
print("lost connection to spark /stream, retrying in 5 seconds")
logger.error("lost connection to spark /stream, retrying in 5 seconds")
await asyncio.sleep(5)

View File

@ -1,5 +1,7 @@
from typing import AsyncGenerator, Optional
from loguru import logger
from .base import (
InvoiceResponse,
PaymentResponse,
@ -20,7 +22,7 @@ class VoidWallet(Wallet):
raise Unsupported("")
async def status(self) -> StatusResponse:
print(
logger.info(
"This backend does nothing, it is here just as a placeholder, you must configure an actual backend before being able to do anything useful with LNbits."
)
return StatusResponse(None, 0)

View File

@ -21,6 +21,7 @@ idna==3.2
importlib-metadata==4.8.1
jinja2==3.0.1
lnurl==0.3.6
loguru==0.6.0
markupsafe==2.0.1
marshmallow==3.13.0
outcome==1.1.0