feat: set sidecar mnemonic if missing (#3839)
This commit is contained in:
@@ -610,6 +610,7 @@ class SparkL2FundingSource(LNbitsSettings):
|
|||||||
spark_l2_network: str = Field(default="MAINNET")
|
spark_l2_network: str = Field(default="MAINNET")
|
||||||
spark_l2_external_endpoint: str | None = Field(default="http://localhost:8765")
|
spark_l2_external_endpoint: str | None = Field(default="http://localhost:8765")
|
||||||
spark_l2_external_api_key: str | None = Field(default=None)
|
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_wait_ms: int = Field(default=4000, ge=0)
|
||||||
spark_l2_pay_poll_ms: int = Field(default=500, ge=0)
|
spark_l2_pay_poll_ms: int = Field(default=500, ge=0)
|
||||||
spark_l2_stream_keepalive_ms: int = Field(default=15000, ge=0)
|
spark_l2_stream_keepalive_ms: int = Field(default=15000, ge=0)
|
||||||
|
|||||||
+1
-1
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.',
|
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: ''
|
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: {
|
spark_l2_external_api_key: {
|
||||||
label: 'External Sidecar API Key',
|
label: 'External Sidecar API Key',
|
||||||
hint: 'API key for authenticating with the external sidecar if it requires authentication.',
|
hint: 'API key for authenticating with the external sidecar if it requires authentication.',
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ from typing import Any, cast
|
|||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
from bolt11 import decode as bolt11_decode
|
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 loguru import logger
|
||||||
|
|
||||||
from lnbits.helpers import normalize_endpoint
|
from lnbits.helpers import normalize_endpoint
|
||||||
@@ -79,6 +81,11 @@ class SparkL2Wallet(Wallet):
|
|||||||
async def status(self) -> StatusResponse:
|
async def status(self) -> StatusResponse:
|
||||||
try:
|
try:
|
||||||
res = await self._request("POST", "/v1/balance")
|
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")
|
balance_msat = res.get("balance_msat")
|
||||||
if balance_msat is not None:
|
if balance_msat is not None:
|
||||||
return StatusResponse(None, int(balance_msat))
|
return StatusResponse(None, int(balance_msat))
|
||||||
@@ -237,7 +244,7 @@ class SparkL2Wallet(Wallet):
|
|||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
error_message = None
|
error_message = None
|
||||||
try:
|
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()
|
r.raise_for_status()
|
||||||
j = r.json()
|
j = r.json()
|
||||||
except (httpx.RequestError, httpx.HTTPStatusError, json.JSONDecodeError) as exc:
|
except (httpx.RequestError, httpx.HTTPStatusError, json.JSONDecodeError) as exc:
|
||||||
@@ -319,3 +326,30 @@ class SparkL2Wallet(Wallet):
|
|||||||
if mapped.failed:
|
if mapped.failed:
|
||||||
return False
|
return False
|
||||||
return None
|
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.")
|
||||||
|
|||||||
Reference in New Issue
Block a user