From d5645b52d7a2b1b34cf3b1bc4fd335c8f8a84378 Mon Sep 17 00:00:00 2001 From: aaron <> Date: Sun, 24 May 2026 12:10:18 +0800 Subject: [PATCH] 1 --- app/config/system_config.py | 46 +++++++++++++++++++++++++++++++++++- tests/test_runtime_config.py | 5 ++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/app/config/system_config.py b/app/config/system_config.py index a43ad5a..5e48ef7 100644 --- a/app/config/system_config.py +++ b/app/config/system_config.py @@ -52,6 +52,10 @@ def _env_list(name, default): return [x.strip().lower() for x in raw.split(",") if x.strip()] or list(default) +def _env_present(name): + return os.getenv(name) is not None + + def default_llm_config(): return { "enabled": _env_bool("ALPHAX_LLM_ENABLED", False), @@ -106,6 +110,45 @@ def default_onchain_config(default_chains=("ethereum", "bsc")): } +def _onchain_env_overrides(default_chains=("ethereum", "bsc")): + """Honor explicit on-chain env vars even when DB runtime config exists.""" + checks = { + "ALPHAX_ONCHAIN_ENABLED": ("enabled", lambda: _env_bool("ALPHAX_ONCHAIN_ENABLED", False)), + "ALPHAX_ONCHAIN_PROVIDER": ("provider", lambda: _env_str("ALPHAX_ONCHAIN_PROVIDER", "nodereal")), + "ALPHAX_ONCHAIN_CHAINS": ("chains", lambda: _env_list("ALPHAX_ONCHAIN_CHAINS", default_chains)), + "ALPHAX_ONCHAIN_TIMEOUT": ("timeout", lambda: _env_int("ALPHAX_ONCHAIN_TIMEOUT", 15)), + "ALPHAX_NODEREAL_ENABLED": ("nodereal_enabled", lambda: _env_bool("ALPHAX_NODEREAL_ENABLED", True)), + "ALPHAX_NODEREAL_CHAINS": ("nodereal_chains", lambda: _env_list("ALPHAX_NODEREAL_CHAINS", ("ethereum", "bsc"))), + "ALPHAX_NODEREAL_LOG_BLOCK_LOOKBACK": ("nodereal_log_block_lookback", lambda: _env_int("ALPHAX_NODEREAL_LOG_BLOCK_LOOKBACK", 120)), + "ALPHAX_NODEREAL_MAX_LOGS_PER_TOKEN": ("nodereal_max_logs_per_token", lambda: _env_int("ALPHAX_NODEREAL_MAX_LOGS_PER_TOKEN", 25)), + "ALPHAX_NODEREAL_RAW_TRANSFER_ENABLED": ("nodereal_raw_transfer_enabled", lambda: _env_bool("ALPHAX_NODEREAL_RAW_TRANSFER_ENABLED", True)), + "ALPHAX_NODEREAL_RAW_BLOCK_LOOKBACK": ("nodereal_raw_block_lookback", lambda: _env_int("ALPHAX_NODEREAL_RAW_BLOCK_LOOKBACK", 1)), + "ALPHAX_NODEREAL_RAW_MAX_LOGS_PER_CHAIN": ("nodereal_raw_max_logs_per_chain", lambda: _env_int("ALPHAX_NODEREAL_RAW_MAX_LOGS_PER_CHAIN", 30)), + "ALPHAX_NODEREAL_AUTO_MAPPING_ENABLED": ("nodereal_auto_mapping_enabled", lambda: _env_bool("ALPHAX_NODEREAL_AUTO_MAPPING_ENABLED", True)), + "ALPHAX_NODEREAL_AUTO_MAPPING_CONFIDENCE": ("nodereal_auto_mapping_confidence", lambda: _env_int("ALPHAX_NODEREAL_AUTO_MAPPING_CONFIDENCE", 82)), + "ALPHAX_ALCHEMY_ENABLED": ("alchemy_enabled", lambda: _env_bool("ALPHAX_ALCHEMY_ENABLED", False)), + "ALPHAX_ALCHEMY_CHAINS": ("alchemy_chains", lambda: _env_list("ALPHAX_ALCHEMY_CHAINS", ("ethereum", "bsc"))), + "ALPHAX_ALCHEMY_LOG_BLOCK_LOOKBACK": ("alchemy_log_block_lookback", lambda: _env_int("ALPHAX_ALCHEMY_LOG_BLOCK_LOOKBACK", 9)), + "ALPHAX_ALCHEMY_MAX_LOGS_PER_TOKEN": ("alchemy_max_logs_per_token", lambda: _env_int("ALPHAX_ALCHEMY_MAX_LOGS_PER_TOKEN", 25)), + "ALPHAX_ALCHEMY_RAW_TRANSFER_ENABLED": ("alchemy_raw_transfer_enabled", lambda: _env_bool("ALPHAX_ALCHEMY_RAW_TRANSFER_ENABLED", True)), + "ALPHAX_ALCHEMY_RAW_CHAINS": ("alchemy_raw_chains", lambda: _env_list("ALPHAX_ALCHEMY_RAW_CHAINS", ("ethereum",))), + "ALPHAX_ALCHEMY_RAW_BLOCK_LOOKBACK": ("alchemy_raw_block_lookback", lambda: _env_int("ALPHAX_ALCHEMY_RAW_BLOCK_LOOKBACK", 1)), + "ALPHAX_ALCHEMY_RAW_MAX_LOGS_PER_CHAIN": ("alchemy_raw_max_logs_per_chain", lambda: _env_int("ALPHAX_ALCHEMY_RAW_MAX_LOGS_PER_CHAIN", 8)), + "ALPHAX_ALCHEMY_AUTO_MAPPING_ENABLED": ("alchemy_auto_mapping_enabled", lambda: _env_bool("ALPHAX_ALCHEMY_AUTO_MAPPING_ENABLED", True)), + "ALPHAX_ALCHEMY_AUTO_MAPPING_CONFIDENCE": ("alchemy_auto_mapping_confidence", lambda: _env_int("ALPHAX_ALCHEMY_AUTO_MAPPING_CONFIDENCE", 82)), + "ALPHAX_ONCHAIN_CANDIDATE_ENABLED": ("candidate_enabled", lambda: _env_bool("ALPHAX_ONCHAIN_CANDIDATE_ENABLED", True)), + "ALPHAX_ONCHAIN_CANDIDATE_MIN_SCORE": ("candidate_min_score", lambda: _env_float("ALPHAX_ONCHAIN_CANDIDATE_MIN_SCORE", 70)), + "ALPHAX_ONCHAIN_CANDIDATE_MIN_CONFIDENCE": ("candidate_min_confidence", lambda: _env_int("ALPHAX_ONCHAIN_CANDIDATE_MIN_CONFIDENCE", 70)), + "ALPHAX_ONCHAIN_CANDIDATE_COOLDOWN_HOURS": ("candidate_cooldown_hours", lambda: _env_float("ALPHAX_ONCHAIN_CANDIDATE_COOLDOWN_HOURS", 6)), + "ALPHAX_ONCHAIN_WHALE_TX_USD": ("whale_tx_usd", lambda: _env_float("ALPHAX_ONCHAIN_WHALE_TX_USD", 250000)), + } + overrides = {} + for env_name, (key, loader) in checks.items(): + if _env_present(env_name): + overrides[key] = loader() + return overrides + + def default_paper_trading_config(): return { "enabled": _env_bool("ALPHAX_PAPER_TRADING_ENABLED", True), @@ -403,7 +446,8 @@ def onchain_config(default_chains=("ethereum", "bsc")): if cfg is None: _seed_one("onchain", default_onchain_config(default_chains), "On-chain provider and signal thresholds; API keys remain in env") cfg = get_onchain_config(default=None) - return cfg or default_onchain_config(default_chains) + merged = deep_merge(default_onchain_config(default_chains), cfg or {}) + return deep_merge(merged, _onchain_env_overrides(default_chains)) def paper_trading_config(): diff --git a/tests/test_runtime_config.py b/tests/test_runtime_config.py index a543e9c..f7c38e6 100644 --- a/tests/test_runtime_config.py +++ b/tests/test_runtime_config.py @@ -215,7 +215,8 @@ def test_llm_system_config_overrides_env_defaults(monkeypatch): def test_onchain_system_config_overrides_env(monkeypatch): - monkeypatch.setenv("ALPHAX_ONCHAIN_ENABLED", "0") + monkeypatch.setenv("ALPHAX_ONCHAIN_ENABLED", "1") + monkeypatch.setenv("ALPHAX_ONCHAIN_PROVIDER", "nodereal,alchemy") monkeypatch.setenv("TEST_NODEREAL_KEY", "nodereal-secret") monkeypatch.setenv("TEST_ALCHEMY_KEY", "alchemy-secret") set_config("system", "onchain", { @@ -240,7 +241,7 @@ def test_onchain_system_config_overrides_env(monkeypatch): assert params["candidate_min_score"] == 88 assert params["nodereal_api_key"] == "nodereal-secret" assert params["nodereal_raw_max_logs_per_chain"] == 12 - assert params["provider"] == "alchemy" + assert params["provider"] == "nodereal,alchemy" assert params["alchemy_api_key"] == "alchemy-secret" assert params["alchemy_chains"] == ["ethereum"] assert params["alchemy_raw_max_logs_per_chain"] == 9