spb/coinexplorer Public MIT
Self-hosted, zero-API-key explorer for stablecoins and major crypto.
Python 60.3%
HTML 23.6%
JavaScript 8.1%
CSS 6.8%
SQL 1%
1# Author: Simon-Pierre Boucher2# Mail: contact@spboucher.ai3"""Central config loading — YAML files + environment overrides.45Env vars (see .env.example):6 EXPLORER_DB path to the SQLite DB (default ./explorer.db)7 (PostgreSQL via DATABASE_URL lands in Deliverable 5)8 EXPLORER_CHAINS comma-separated subset of chains to index (default all)9 EXPLORER_CONFIG directory holding chains.yaml / tokens.yaml10"""1112import os13import pathlib1415import yaml1617ROOT = pathlib.Path(__file__).parent.parent18CONFIG_DIR = pathlib.Path(os.environ.get("EXPLORER_CONFIG", ROOT / "config"))192021def db_path():22 return os.environ.get("EXPLORER_DB", str(ROOT / "explorer.db"))232425def load_chains():26 return yaml.safe_load((CONFIG_DIR / "chains.yaml").read_text())["chains"]272829def load_tokens():30 return yaml.safe_load((CONFIG_DIR / "tokens.yaml").read_text())["tokens"]313233def backfill_blocks(chain_cfg):34 """How many blocks of history to grow backwards. Per-chain35 `backfill_days` wins; else EXPLORER_BACKFILL_DAYS env; else 0 (off)."""36 days = chain_cfg.get("backfill_days")37 if days is None:38 days = float(os.environ.get("EXPLORER_BACKFILL_DAYS", 0) or 0)39 if not days:40 return 041 return int(days * 86400 / float(chain_cfg.get("block_time", 12)))424344def selected_chains(chains, tokens, cli_arg=None, families=("evm",)):45 """Chains to run: CLI arg > EXPLORER_CHAINS env > every chain that has46 both a chain config and a token list. Chains whose family has no47 adapter yet are skipped with a warning."""48 env = os.environ.get("EXPLORER_CHAINS", "").strip()49 if cli_arg:50 wanted = list(cli_arg)51 elif env:52 wanted = [c.strip() for c in env.split(",") if c.strip()]53 else:54 wanted = [c for c in chains if c in tokens]55 unknown = [c for c in wanted if c not in chains or c not in tokens]56 if unknown:57 raise SystemExit(f"unknown chains (need entries in both YAML files): {unknown}")58 skipped = [c for c in wanted if chains[c].get("family", "evm") not in families]59 if skipped:60 import logging61 logging.warning("skipping chains with no adapter yet: %s", skipped)62 return [c for c in wanted if chains[c].get("family", "evm") in families]63