feat: set sidecar mnemonic if missing (#3839)

This commit is contained in:
Vlad Stan
2026-03-04 16:13:46 +02:00
committed by GitHub
parent f93efbfb3a
commit 04ec643c93
4 changed files with 42 additions and 2 deletions
+1
View File
@@ -610,6 +610,7 @@ class SparkL2FundingSource(LNbitsSettings):
spark_l2_network: str = Field(default="MAINNET")
spark_l2_external_endpoint: str | None = Field(default="http://localhost:8765")
spark_l2_external_api_key: str | None = Field(default=None)
spark_l2_mnemonic: str | None = Field(default=None)
spark_l2_pay_wait_ms: int = Field(default=4000, ge=0)
spark_l2_pay_poll_ms: int = Field(default=500, ge=0)
spark_l2_stream_keepalive_ms: int = Field(default=15000, ge=0)
File diff suppressed because one or more lines are too long
@@ -237,6 +237,11 @@ window.app.component('lnbits-admin-funding-sources', {
hint: 'If specified then this endpoint will be used instead of the internal sidecar. Make sure to also specify the API key if your sidecar requires authentication.',
value: ''
},
spark_l2_mnemonic: {
label: 'External Sidecar Mnemonic',
hint: 'Mnemonic for the Spark wallet on the external sidecar. Required if the side car does not have its own mnemonic.',
value: ''
},
spark_l2_external_api_key: {
label: 'External Sidecar API Key',
hint: 'API key for authenticating with the external sidecar if it requires authentication.',
+35 -1
View File
@@ -8,6 +8,8 @@ from typing import Any, cast
import httpx
from bolt11 import decode as bolt11_decode
from coincurve.keys import PrivateKey
from embit.bip39 import mnemonic_from_bytes, mnemonic_is_valid
from loguru import logger
from lnbits.helpers import normalize_endpoint
@@ -79,6 +81,11 @@ class SparkL2Wallet(Wallet):
async def status(self) -> StatusResponse:
try:
res = await self._request("POST", "/v1/balance")
status = res.get("status")
if status == "missing_mnemonic":
await self._check_sidecar_mnemonic()
return StatusResponse("Spark sidecar mnemonic not set", 0)
balance_msat = res.get("balance_msat")
if balance_msat is not None:
return StatusResponse(None, int(balance_msat))
@@ -237,7 +244,7 @@ class SparkL2Wallet(Wallet):
) -> dict[str, Any]:
error_message = None
try:
r = await self.client.request(method, path, json=json_data)
r = await self.client.request(method, path, json=json_data, timeout=30)
r.raise_for_status()
j = r.json()
except (httpx.RequestError, httpx.HTTPStatusError, json.JSONDecodeError) as exc:
@@ -319,3 +326,30 @@ class SparkL2Wallet(Wallet):
if mapped.failed:
return False
return None
async def _check_sidecar_mnemonic(self):
if settings.spark_l2_mnemonic:
valid = mnemonic_is_valid(settings.spark_l2_mnemonic)
if not valid:
logger.warning("SPARK_L2_MNEMONIC is set but invalid. Please recheck!")
return
await self._set_sidecar_mnemonic(settings.spark_l2_mnemonic)
return
logger.info("SPARK_L2_MNEMONIC is not set, one will be generated for you.")
mnemonic = mnemonic_from_bytes(PrivateKey().secret)
await self._set_sidecar_mnemonic(mnemonic)
async def _set_sidecar_mnemonic(self, mnemonic: str):
logger.info("Checking 'SPARK_L2_MNEMONIC' on the Spark sidecar.")
payload = {"mnemonic": mnemonic}
resp = await self._request("POST", "/v1/mnemonic", payload)
status = resp.get("status")
logger.info(f"Spark sidecar mnemonic status: {status}")
if status == "set":
logger.info("Updating 'SPARK_L2_MNEMONIC' mnemonic settings.")
from lnbits.core.crud.settings import set_settings_field
await set_settings_field("spark_l2_mnemonic", mnemonic)
else:
logger.info("Nothing to do for 'SPARK_L2_MNEMONIC' on the Spark sidecar.")