"""Configuration for the BigCoin block explorer. All settings are read from environment variables so the explorer can be pointed at any bigcoind instance without editing code. """ import os def _env_bool(name: str, default: bool) -> bool: val = os.environ.get(name) if val is None: return default return val.strip().lower() in ("1", "true", "yes", "on") # --- RPC connection settings (Bitcoin/Litecoin-Core style JSON-RPC) --- RPC_HOST = os.environ.get("BIGCOIN_RPC_HOST", "127.0.0.1") RPC_PORT = int(os.environ.get("BIGCOIN_RPC_PORT", "9445")) RPC_USER = os.environ.get("BIGCOIN_RPC_USER", "") RPC_PASSWORD = os.environ.get("BIGCOIN_RPC_PASSWORD", "") # Full RPC URL override. When set (e.g. an HTTPS Cloudflare-tunnel host that # fronts the read-only proxy), it takes precedence over HOST/PORT so the # explorer can reach a remote node over https without editing code. RPC_URL = os.environ.get("BIGCOIN_RPC_URL", "") # Timeout (seconds) for RPC HTTP calls. RPC_TIMEOUT = float(os.environ.get("BIGCOIN_RPC_TIMEOUT", "8")) # --- Explorer / display settings --- COIN_NAME = os.environ.get("BIGCOIN_NAME", "BigCoin") COIN_TICKER = os.environ.get("BIGCOIN_TICKER", "BIG") # Explorer web server port (chosen to avoid common collisions). EXPLORER_PORT = int(os.environ.get("EXPLORER_PORT", "5055")) # How many recent blocks to show on the home page. LATEST_BLOCKS = int(os.environ.get("EXPLORER_LATEST_BLOCKS", "15")) # --- Demo mode --- # When DEMO_MODE=1 the explorer serves realistic fake sample data and never # needs a running chain. When DEMO_MODE is unset, it defaults to ON only if # the RPC node cannot be reached (handled in rpc.py). DEMO_MODE = _env_bool("DEMO_MODE", default=False) # Whether DEMO_MODE was explicitly requested by the user. DEMO_MODE_EXPLICIT = os.environ.get("DEMO_MODE") is not None # --- Browser-miner endpoint (POST /api/mine) --- # Lets the Spark web page trigger real mining on the node (the node does the # proof-of-work via generatetoaddress). Off unless MINING_ENABLED is truthy so a # public explorer never mines unless the operator opts in. MINING_ENABLED = _env_bool("MINING_ENABLED", default=False) # PoW attempts the node makes per /api/mine call before returning (keep modest so # the HTTP request returns promptly whether or not a block is found). MINING_MAXTRIES = int(os.environ.get("MINING_MAXTRIES", "500000")) # Cross-origin allow-list for the browser miner (the site is a different origin # from the explorer). Comma-separated; "*" allows any origin. MINING_CORS_ORIGINS = os.environ.get( "MINING_CORS_ORIGINS", "https://moonbite.org,https://www.moonbite.org,https://moonbitecoin.github.io", ) # --- Phase 2b HTLC settlement verifier (read-only chain observer) --- # When enabled, the operator's node is polled to confirm atomic-swap HTLCs and # advance settled trades (the only path that lets last_price move). Off by # default: a swap never settles unless the operator opts into on-chain # verification against a node they trust. VERIFIER_ENABLED = _env_bool("VERIFIER_ENABLED", default=False) # Confirmation depth required before the verifier trusts a funding/redeem tx. VERIFIER_MIN_CONFS_BASE = int(os.environ.get("VERIFIER_MIN_CONFS_BASE", "6")) VERIFIER_MIN_CONFS_QUOTE = int(os.environ.get("VERIFIER_MIN_CONFS_QUOTE", "6")) # --- Webhooks (POST /api/webhooks) --- # A background poller watches the chain tip and delivers signed callbacks for # 'new_block' and per-'address' activity. Registration requires an API key so a # public explorer is never turned into an open relay; leave WEBHOOK_API_KEY # unset to disable registration entirely. WEBHOOKS_ENABLED = _env_bool("WEBHOOKS_ENABLED", default=True) WEBHOOK_API_KEY = os.environ.get("WEBHOOK_API_KEY", "") # Where the SQLite store lives (ephemeral on Railway's dyno disk by default). WEBHOOK_DB_PATH = os.environ.get("WEBHOOK_DB_PATH", "webhooks.db") # Seconds between chain-tip polls. WEBHOOK_POLL_INTERVAL = float(os.environ.get("WEBHOOK_POLL_INTERVAL", "10")) # Safety caps. WEBHOOK_MAX = int(os.environ.get("WEBHOOK_MAX", "200")) WEBHOOK_MAX_FAILURES = int(os.environ.get("WEBHOOK_MAX_FAILURES", "10")) WEBHOOK_TIMEOUT = float(os.environ.get("WEBHOOK_TIMEOUT", "8")) # Most blocks to walk forward in a single poll (bounds catch-up work after a # long outage; older gaps are skipped rather than replayed). WEBHOOK_MAX_CATCHUP = int(os.environ.get("WEBHOOK_MAX_CATCHUP", "50")) # SSRF guard. By default callback URLs must be https and must not resolve to a # private/loopback/link-local address. Set WEBHOOK_ALLOW_PRIVATE=1 for local # testing (permits http + private IPs). WEBHOOK_ALLOW_PRIVATE = _env_bool("WEBHOOK_ALLOW_PRIVATE", default=False) def rpc_url() -> str: return RPC_URL if RPC_URL else f"http://{RPC_HOST}:{RPC_PORT}/"