refactor(mcp-common): centralize base_url defaults in resolve_environment

Aggiunti kwargs opzionali default_base_url_live / default_base_url_testnet
a resolve_environment. Rimosse 8 chiamate creds.setdefault duplicate dai
4 servizi (alpaca, bybit, deribit, hyperliquid) ora passano gli URL
canonici direttamente al resolver.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
AdrianoDev
2026-04-27 22:28:18 +02:00
parent 81fb5e8c29
commit 21da74e8a1
6 changed files with 50 additions and 14 deletions
+11 -1
View File
@@ -29,13 +29,18 @@ def resolve_environment(
env_var: str, env_var: str,
flag_key: str, flag_key: str,
exchange: str, exchange: str,
default_base_url_live: str | None = None,
default_base_url_testnet: str | None = None,
) -> EnvironmentInfo: ) -> EnvironmentInfo:
"""Risolvi l'ambiente per un MCP exchange. """Risolvi l'ambiente per un MCP exchange.
creds: dict letto dal secret JSON. Deve contenere base_url_live e base_url_testnet. creds: dict letto dal secret JSON. Può contenere base_url_live/base_url_testnet
per override; in assenza vengono usati i default kwargs.
env_var: nome della env var di override (es. DERIBIT_TESTNET). env_var: nome della env var di override (es. DERIBIT_TESTNET).
flag_key: chiave booleana nel secret JSON (es. "testnet" o "paper" per alpaca). flag_key: chiave booleana nel secret JSON (es. "testnet" o "paper" per alpaca).
exchange: nome exchange per logging/info. exchange: nome exchange per logging/info.
default_base_url_live / default_base_url_testnet: URL canonici dell'exchange,
applicati se non presenti in creds.
""" """
env_value = os.environ.get(env_var) env_value = os.environ.get(env_var)
if env_value is not None: if env_value is not None:
@@ -49,6 +54,11 @@ def resolve_environment(
environment = "testnet" environment = "testnet"
source = "default" source = "default"
if default_base_url_live is not None:
creds.setdefault("base_url_live", default_base_url_live)
if default_base_url_testnet is not None:
creds.setdefault("base_url_testnet", default_base_url_testnet)
base_url = creds["base_url_testnet"] if environment == "testnet" else creds["base_url_live"] base_url = creds["base_url_testnet"] if environment == "testnet" else creds["base_url_live"]
return EnvironmentInfo( return EnvironmentInfo(
exchange=exchange, exchange=exchange,
+31
View File
@@ -74,6 +74,37 @@ def test_env_value_truthy_parsing(monkeypatch, raw, expected):
assert info.environment == expected assert info.environment == expected
def test_default_base_urls_applied_when_creds_missing(monkeypatch):
monkeypatch.delenv("X_TESTNET", raising=False)
creds: dict = {}
info = resolve_environment(
creds,
env_var="X_TESTNET",
flag_key="testnet",
exchange="x",
default_base_url_live="https://live.example",
default_base_url_testnet="https://test.example",
)
assert info.base_url == "https://test.example"
assert creds["base_url_live"] == "https://live.example"
assert creds["base_url_testnet"] == "https://test.example"
def test_creds_base_urls_override_defaults(monkeypatch):
monkeypatch.delenv("X_TESTNET", raising=False)
creds = {"base_url_live": "L", "base_url_testnet": "T"}
info = resolve_environment(
creds,
env_var="X_TESTNET",
flag_key="testnet",
exchange="x",
default_base_url_live="https://live.example",
default_base_url_testnet="https://test.example",
)
assert info.base_url == "T"
assert creds["base_url_live"] == "L"
def test_alpaca_paper_flag_key(monkeypatch): def test_alpaca_paper_flag_key(monkeypatch):
"""Alpaca usa 'paper' invece di 'testnet' nel secret.""" """Alpaca usa 'paper' invece di 'testnet' nel secret."""
monkeypatch.delenv("ALPACA_PAPER", raising=False) monkeypatch.delenv("ALPACA_PAPER", raising=False)
@@ -20,14 +20,13 @@ def main():
with open(creds_file) as f: with open(creds_file) as f:
creds = json.load(f) creds = json.load(f)
creds.setdefault("base_url_live", "https://api.alpaca.markets")
creds.setdefault("base_url_testnet", "https://paper-api.alpaca.markets")
env_info = resolve_environment( env_info = resolve_environment(
creds, creds,
env_var="ALPACA_PAPER", env_var="ALPACA_PAPER",
flag_key="paper", flag_key="paper",
exchange="alpaca", exchange="alpaca",
default_base_url_live="https://api.alpaca.markets",
default_base_url_testnet="https://paper-api.alpaca.markets",
) )
client = AlpacaClient( client = AlpacaClient(
+2 -3
View File
@@ -20,14 +20,13 @@ def main():
with open(creds_file) as f: with open(creds_file) as f:
creds = json.load(f) creds = json.load(f)
creds.setdefault("base_url_live", "https://api.bybit.com")
creds.setdefault("base_url_testnet", "https://api-testnet.bybit.com")
env_info = resolve_environment( env_info = resolve_environment(
creds, creds,
env_var="BYBIT_TESTNET", env_var="BYBIT_TESTNET",
flag_key="testnet", flag_key="testnet",
exchange="bybit", exchange="bybit",
default_base_url_live="https://api.bybit.com",
default_base_url_testnet="https://api-testnet.bybit.com",
) )
client = BybitClient( client = BybitClient(
@@ -27,15 +27,13 @@ def main():
with open(creds_file) as f: with open(creds_file) as f:
creds = json.load(f) creds = json.load(f)
# Default base URLs per backward-compat con secret schema legacy
creds.setdefault("base_url_live", "https://www.deribit.com/api/v2")
creds.setdefault("base_url_testnet", "https://test.deribit.com/api/v2")
env_info = resolve_environment( env_info = resolve_environment(
creds, creds,
env_var="DERIBIT_TESTNET", env_var="DERIBIT_TESTNET",
flag_key="testnet", flag_key="testnet",
exchange="deribit", exchange="deribit",
default_base_url_live="https://www.deribit.com/api/v2",
default_base_url_testnet="https://test.deribit.com/api/v2",
) )
client = DeribitClient( client = DeribitClient(
@@ -19,14 +19,13 @@ def main():
with open(wallet_file) as f: with open(wallet_file) as f:
creds = json.load(f) creds = json.load(f)
creds.setdefault("base_url_live", "https://api.hyperliquid.xyz")
creds.setdefault("base_url_testnet", "https://api.hyperliquid-testnet.xyz")
env_info = resolve_environment( env_info = resolve_environment(
creds, creds,
env_var="HYPERLIQUID_TESTNET", env_var="HYPERLIQUID_TESTNET",
flag_key="testnet", flag_key="testnet",
exchange="hyperliquid", exchange="hyperliquid",
default_base_url_live="https://api.hyperliquid.xyz",
default_base_url_testnet="https://api.hyperliquid-testnet.xyz",
) )
client = HyperliquidClient( client = HyperliquidClient(