From e2f6e37ebe021aace1340d8f65acab52cb65ba19 Mon Sep 17 00:00:00 2001 From: redshift <213178690+1ftredsh@users.noreply.github.com> Date: Mon, 21 Sep 2026 16:51:33 +0300 Subject: [PATCH] feat: ship fresh nodes with default trusted Cashu mints cashu_mints previously defaulted to an empty list, leaving a new node in a half-working state: it silently trusted the hardcoded minibits primary mint but advertised no mints in /v1/info or its NIP-91 listing, so clients discovering the node had no way to know where to pay. - default cashu_mints to minibits + cubabitcoin via shared DEFAULT_CASHU_MINTS - reuse the constant for the primary_mint fallback (removes duplicate literal) - CASHU_MINTS env or dashboard edits still replace the list entirely; an explicitly empty value keeps only the primary mint trusted - document the defaults in configuration.md, dashboard.md, .env.example Existing nodes are unaffected: the settings-blob merge skips persisted empty lists, so unconfigured nodes pick up the defaults on restart while nodes with explicit mints keep theirs. --- .env.example | 1 + docs/provider/configuration.md | 11 ++++++++++- docs/provider/dashboard.md | 4 +++- routstr/core/settings.py | 17 +++++++++++++++-- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/.env.example b/.env.example index 265ca2c4..d540fce2 100644 --- a/.env.example +++ b/.env.example @@ -45,6 +45,7 @@ ROUTSTR_SECRET_KEY= # ONION_URL=http://mynode.onion (auto fetched from compose) # RELAYS="wss://relay.damus.io,wss://relay.nostr.band,wss://eden.nostr.land,wss://relay.routstr.com" # ENABLE_ANALYTICS_SHARING=true +# CASHU_MINTS="https://mint.minibits.cash/Bitcoin,https://mint.cubabitcoin.org" # this is the default # CASHU_MINTS="https://mint.minibits.cash/Bitcoin,https://mint.cubabitcoin.org,https://ecashmint.otrta.me" # MINT_OPERATION_CONCURRENCY=4 # MINT_OPERATION_TIMEOUT_SECONDS=30 diff --git a/docs/provider/configuration.md b/docs/provider/configuration.md index 68433cc1..6954480c 100644 --- a/docs/provider/configuration.md +++ b/docs/provider/configuration.md @@ -139,6 +139,15 @@ Which mints to accept payments from: | --------- | ------------------------------- | | **Mints** | List of trusted Cashu mint URLs | +A fresh node ships with two mints preconfigured: + +- `https://mint.minibits.cash/Bitcoin` +- `https://mint.cubabitcoin.org` + +Setting `CASHU_MINTS` (env) or editing the list in the dashboard replaces this +default entirely. An explicitly empty value leaves only the primary mint +trusted. + ### Lightning Withdrawals Automatic profit withdrawal: @@ -197,7 +206,7 @@ Use environment variables for: | `NPUB` | Nostr public key (bech32) | — | | `NSEC` | Legacy seed for the Nostr private key (otherwise set from the admin UI) | — | | `ENABLE_ANALYTICS_SHARING` | Enable usage analytics sharing to Nostr | `true` | -| `CASHU_MINTS` | Comma-separated mint URLs | `https://mint.minibits.cash/Bitcoin` | +| `CASHU_MINTS` | Comma-separated mint URLs | `https://mint.minibits.cash/Bitcoin,https://mint.cubabitcoin.org` | | `MINT_OPERATION_CONCURRENCY` | Concurrent mint/unit balance reads | `4` | | `MINT_OPERATION_TIMEOUT_SECONDS` | Per-attempt timeout for mint network calls | `30` | | `MINT_MAX_CONCURRENCY` | Concurrent operations allowed per mint (`0` disables the limit) | `4` | diff --git a/docs/provider/dashboard.md b/docs/provider/dashboard.md index 66852845..7e3db598 100644 --- a/docs/provider/dashboard.md +++ b/docs/provider/dashboard.md @@ -132,7 +132,9 @@ Connect to your AI provider: ### Cashu Mints -Manage which mints you accept payments from: +Manage which mints you accept payments from. A fresh node comes with two +default mints preconfigured (`https://mint.minibits.cash/Bitcoin` and +`https://mint.cubabitcoin.org`): - **Add Mint** — Enter a mint URL - **Remove Mint** — Stop accepting from a mint diff --git a/routstr/core/settings.py b/routstr/core/settings.py index 2104aeb3..b98da94b 100644 --- a/routstr/core/settings.py +++ b/routstr/core/settings.py @@ -11,6 +11,14 @@ from typing import Any from pydantic.v1 import BaseModel, BaseSettings, Field from sqlmodel.ext.asyncio.session import AsyncSession +# Mints a fresh node trusts out of the box, shared by the settings default and +# the primary-mint fallback. Defined before the Settings class because the +# default_factory lambda resolves it at class-definition time. +DEFAULT_CASHU_MINTS: list[str] = [ + "https://mint.minibits.cash/Bitcoin", + "https://mint.cubabitcoin.org", +] + class Settings(BaseSettings): class Config: @@ -37,7 +45,12 @@ class Settings(BaseSettings): onion_url: str = Field(default="", env="ONION_URL") # Cashu - cashu_mints: list[str] = Field(default_factory=list, env="CASHU_MINTS") + # Mints a fresh node trusts out of the box. Setting CASHU_MINTS (env or + # dashboard) replaces this list entirely; an explicitly empty value yields + # an empty list (no trusted mints beyond primary_mint). + cashu_mints: list[str] = Field( + default_factory=lambda: list(DEFAULT_CASHU_MINTS), env="CASHU_MINTS" + ) receive_ln_address: str = Field(default="", env="RECEIVE_LN_ADDRESS") primary_mint: str = Field(default="", env="PRIMARY_MINT_URL") primary_mint_unit: str = Field(default="sat", env="PRIMARY_MINT_UNIT") @@ -256,7 +269,7 @@ def _apply_to_live_settings(data: dict[str, Any]) -> None: def _compute_primary_mint(cashu_mints: list[str]) -> str: - return cashu_mints[0] if cashu_mints else "https://mint.minibits.cash/Bitcoin" + return cashu_mints[0] if cashu_mints else DEFAULT_CASHU_MINTS[0] def derive_npub_from_nsec(nsec: str) -> str | None: