Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] LN Gateway #553

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions cashu/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ def from_row(cls, row: Row):
quote=row["quote"],
method=row["method"],
request=row["request"],
expiry=row["expiry"],
checking_id=row["checking_id"],
unit=row["unit"],
amount=row["amount"],
Expand Down
15 changes: 15 additions & 0 deletions cashu/core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,19 @@ class MintSettings(CashuSettings):
mint_input_fee_ppk: int = Field(default=0)


class GatewaySettings(CashuSettings):
gateway_private_key: str = Field(default=None)
gateway_listen_host: str = Field(default="127.0.0.1")
gateway_listen_port: int = Field(default=3838)
gateway_database: str = Field(default="data/gateway")

gateway_backend_bolt11_sat: str = Field(default="")
gateway_bolt11_sat_fee_ppm: int = Field(default=1000)
gateway_bolt11_sat_base_fee: int = Field(default=2)

gateway_mint_urls: List[str] = Field(default=[])


class MintBackends(MintSettings):
mint_lightning_backend: str = Field(default="") # deprecated
mint_backend_bolt11_sat: str = Field(default="")
Expand Down Expand Up @@ -172,6 +185,7 @@ class WalletSettings(CashuSettings):

locktime_delta_seconds: int = Field(default=86400) # 1 day
proofs_batch_size: int = Field(default=1000)
wallet_gateways: List[str] = Field(default=[])

wallet_target_amount_count: int = Field(default=3)

Expand Down Expand Up @@ -201,6 +215,7 @@ class Settings(
MintSettings,
MintInformation,
WalletSettings,
GatewaySettings,
CashuSettings,
):
version: str = Field(default=VERSION)
Expand Down
3 changes: 3 additions & 0 deletions cashu/gateway/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .main import main

main()
91 changes: 91 additions & 0 deletions cashu/gateway/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import sys
from traceback import print_exception

from fastapi import FastAPI, status
from fastapi.responses import JSONResponse
from loguru import logger
from starlette.requests import Request

from ..core.errors import CashuError
from ..core.logging import configure_logger
from ..core.settings import settings
from .router import router
from .startup import start_gateway_init

if settings.debug_profiling:
pass

if settings.mint_rate_limit:
pass

# this errors with the tests but is the appropriate way to handle startup and shutdown
# until then, we use @app.on_event("startup")
# @asynccontextmanager
# async def lifespan(app: FastAPI):
# # startup routines here
# await start_mint_init()
# yield
# # shutdown routines here


def create_app(config_object="core.settings") -> FastAPI:
configure_logger()

app = FastAPI(
title="Nutshell Cashu Mint",
description="Ecash wallet and mint based on the Cashu protocol.",
version=settings.version,
license_info={
"name": "MIT License",
"url": "https://raw.githubusercontent.com/cashubtc/cashu/main/LICENSE",
},
)

return app


app = create_app()


@app.middleware("http")
async def catch_exceptions(request: Request, call_next):
CORS_HEADERS = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "*",
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Credentials": "true",
}
try:
return await call_next(request)
except Exception as e:
try:
err_message = str(e)
except Exception:
err_message = e.args[0] if e.args else "Unknown error"

if isinstance(e, CashuError) or isinstance(e.args[0], CashuError):
logger.error(f"CashuError: {err_message}")
code = e.code if isinstance(e, CashuError) else e.args[0].code
# return with cors headers
return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST,
content={"detail": err_message, "code": code},
headers=CORS_HEADERS,
)
logger.error(f"Exception: {err_message}")
if settings.debug:
print_exception(*sys.exc_info())
return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST,
content={"detail": err_message, "code": 0},
headers=CORS_HEADERS,
)


# Add exception handlers
app.include_router(router=router, tags=["Gateway"])


@app.on_event("startup")
async def startup_gateway():
await start_gateway_init()
Loading
Loading