feat: adds blockexplorer api, frontend via electrum
- settings - frontend page component - api - models models
This commit is contained in:
@@ -3,6 +3,7 @@ from fastapi import APIRouter, FastAPI
|
||||
from .db import core_app_extra, db
|
||||
from .views.admin_api import admin_router
|
||||
from .views.api import api_router
|
||||
from .views.blockexplorer_api import blockexplorer_router
|
||||
from .views.asset_api import asset_router
|
||||
from .views.audit_api import audit_router
|
||||
from .views.auth_api import auth_router
|
||||
@@ -48,6 +49,7 @@ def init_core_routers(app: FastAPI):
|
||||
app.include_router(asset_router)
|
||||
app.include_router(fiat_router)
|
||||
app.include_router(lnurl_router)
|
||||
app.include_router(blockexplorer_router)
|
||||
|
||||
|
||||
__all__ = ["core_app", "core_app_extra", "db"]
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
import asyncio
|
||||
from http import HTTPStatus
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from lnbits.settings import settings
|
||||
from lnbits.utils.electrum import (
|
||||
AddressResponse,
|
||||
BlockHeader,
|
||||
ElectrumClient,
|
||||
ElectrumError,
|
||||
FeeResponse,
|
||||
Transaction,
|
||||
parse_raw_tx,
|
||||
scripthash_from_address,
|
||||
)
|
||||
|
||||
blockexplorer_router = APIRouter(
|
||||
tags=["Block Explorer"],
|
||||
prefix="/blockexplorer/api/v1",
|
||||
)
|
||||
|
||||
|
||||
def _check_enabled() -> None:
|
||||
if not settings.lnbits_blockexplorer_enabled:
|
||||
raise HTTPException(
|
||||
status_code=HTTPStatus.SERVICE_UNAVAILABLE,
|
||||
detail="Block explorer is not enabled.",
|
||||
)
|
||||
|
||||
|
||||
def _client() -> ElectrumClient:
|
||||
return ElectrumClient(settings.lnbits_blockexplorer_electrum_url)
|
||||
|
||||
|
||||
@blockexplorer_router.get("/tip")
|
||||
async def api_tip() -> BlockHeader:
|
||||
_check_enabled()
|
||||
try:
|
||||
async with _client() as c:
|
||||
return await c.get_tip()
|
||||
except ElectrumError as e:
|
||||
raise HTTPException(HTTPStatus.SERVICE_UNAVAILABLE, detail=str(e))
|
||||
|
||||
|
||||
@blockexplorer_router.get("/fees")
|
||||
async def api_fees() -> FeeResponse:
|
||||
_check_enabled()
|
||||
try:
|
||||
async with _client() as c:
|
||||
estimates_raw = await asyncio.gather(
|
||||
c.estimate_fee(1),
|
||||
c.estimate_fee(3),
|
||||
c.estimate_fee(6),
|
||||
c.estimate_fee(144),
|
||||
)
|
||||
histogram = await c.fee_histogram()
|
||||
estimates = {
|
||||
str(blocks): fee
|
||||
for blocks, fee in zip([1, 3, 6, 144], estimates_raw)
|
||||
if fee >= 0
|
||||
}
|
||||
return FeeResponse(estimates=estimates, histogram=histogram)
|
||||
except ElectrumError as e:
|
||||
raise HTTPException(HTTPStatus.SERVICE_UNAVAILABLE, detail=str(e))
|
||||
|
||||
|
||||
@blockexplorer_router.get("/tx/{txid}")
|
||||
async def api_tx(txid: str) -> Transaction:
|
||||
_check_enabled()
|
||||
try:
|
||||
async with _client() as c:
|
||||
raw_hex = await c.get_transaction(txid, verbose=False)
|
||||
return parse_raw_tx(raw_hex)
|
||||
except ElectrumError as e:
|
||||
raise HTTPException(HTTPStatus.SERVICE_UNAVAILABLE, detail=str(e))
|
||||
|
||||
|
||||
@blockexplorer_router.get("/address/{address}")
|
||||
async def api_address(address: str) -> AddressResponse:
|
||||
_check_enabled()
|
||||
try:
|
||||
scripthash = scripthash_from_address(address)
|
||||
except ValueError as e:
|
||||
raise HTTPException(HTTPStatus.BAD_REQUEST, detail=str(e))
|
||||
try:
|
||||
async with _client() as c:
|
||||
balance, history = await asyncio.gather(
|
||||
c.get_balance(scripthash),
|
||||
c.get_history(scripthash),
|
||||
)
|
||||
return AddressResponse(balance=balance, history=history)
|
||||
except ElectrumError as e:
|
||||
raise HTTPException(HTTPStatus.SERVICE_UNAVAILABLE, detail=str(e))
|
||||
@@ -209,6 +209,7 @@ async def index(
|
||||
|
||||
@generic_router.get("/")
|
||||
@generic_router.get("/node/public")
|
||||
@generic_router.get("/blockexplorer")
|
||||
@generic_router.get("/first_install", dependencies=[Depends(check_first_install)])
|
||||
async def index_public(request: Request) -> HTMLResponse:
|
||||
return template_renderer().TemplateResponse(request, "base.html", {"public": True})
|
||||
|
||||
Reference in New Issue
Block a user