//! Shared Bitcoin RPC credential management. //! Reads credentials from the per-installation secrets file, falling back to //! environment variables, then a dev-only default. use tokio::sync::OnceCell; use tracing::debug; const SECRETS_PATH: &str = "/var/lib/archipelago/secrets/bitcoin-rpc-password"; const DEFAULT_USER: &str = "archipelago"; static CACHED_PASSWORD: OnceCell = OnceCell::const_new(); /// Read the Bitcoin RPC password from the secrets file, env var, or dev fallback. async fn read_password() -> String { // 1. Try secrets file (production path) if let Ok(pass) = tokio::fs::read_to_string(SECRETS_PATH).await { let pass = pass.trim().to_string(); if !pass.is_empty() { debug!("Bitcoin RPC password loaded from secrets file"); return pass; } } // 2. Try environment variable if let Ok(pass) = std::env::var("BITCOIN_RPC_PASSWORD") { if !pass.is_empty() { debug!("Bitcoin RPC password loaded from env var"); return pass; } } // 3. Dev fallback (will only work on dev machines with default config) debug!("Bitcoin RPC password: using dev fallback"); "archipelago123".to_string() } /// Get Bitcoin RPC credentials (user, password). Cached after first call. pub async fn bitcoin_rpc_credentials() -> (String, String) { let pass = CACHED_PASSWORD .get_or_init(|| async { read_password().await }) .await; (DEFAULT_USER.to_string(), pass.clone()) } /// Get the Bitcoin RPC password as a plain string (for config generation). pub async fn bitcoin_rpc_password() -> String { let (_, pass) = bitcoin_rpc_credentials().await; pass }