Spaces:
Sleeping
Sleeping
| import os | |
| import sys | |
| import time | |
| import json | |
| import unittest | |
| from unittest.mock import patch | |
| from pathlib import Path | |
| ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) | |
| if ROOT not in sys.path: | |
| sys.path.insert(0, ROOT) | |
| from src.agents.strategy import live_data | |
| class _FakeCache: | |
| def __init__(self): | |
| self.store = {} | |
| self.exp = {} | |
| def _alive(self, key: str) -> bool: | |
| exp = self.exp.get(key) | |
| if exp is None: | |
| return key in self.store | |
| if time.time() > exp: | |
| self.store.pop(key, None) | |
| self.exp.pop(key, None) | |
| return False | |
| return True | |
| def get_json(self, key: str): | |
| return self.store.get(key) if self._alive(key) else None | |
| def set_json(self, key: str, value, ttl: int): | |
| self.store[key] = value | |
| self.exp[key] = time.time() + ttl | |
| def set_error(self, key: str, payload, ttl: int): | |
| self.set_json(key, {"__error__": True, "payload": payload}, ttl=ttl) | |
| def incr(self, key: str, ttl: int): | |
| value = int(self.store.get(key, 0) or 0) + 1 | |
| self.store[key] = value | |
| self.exp[key] = time.time() + ttl | |
| return value | |
| def exists(self, key: str): | |
| return self._alive(key) | |
| class LiveDataTest(unittest.TestCase): | |
| def setUp(self): | |
| self.cache = _FakeCache() | |
| live_data._CACHE = self.cache | |
| live_data._MICRO_CACHE.clear() | |
| def test_slug_mapping_known_protocol(self): | |
| self.assertEqual(live_data._defillama_protocol_slug("Euler V2"), "euler-v2") | |
| def test_alias_matching_variants(self): | |
| self.assertTrue(live_data._project_matches_protocol("spark-savings", "Spark")) | |
| self.assertTrue(live_data._project_matches_protocol("joe-v2.1", "LFJ")) | |
| self.assertTrue(live_data._project_matches_protocol("blackhole-clmm", "Blackhole")) | |
| def test_fresh_cache_hit(self): | |
| key = live_data._build_cache_key("lending", ["Spark"]) | |
| self.cache.set_json( | |
| key, | |
| {"payload": {"apy": 0.09, "freshness": "fresh", "source": "defillama"}, "_cached_at": time.time()}, | |
| ttl=live_data._STALE_TTL, | |
| ) | |
| with patch("src.agents.strategy.live_data.lending_adapter", side_effect=RuntimeError("should not fetch")): | |
| result = live_data.enrich_live_data("lending", ["Spark"]) | |
| self.assertEqual(result["apy"], 0.09) | |
| self.assertEqual(result["freshness"], "fresh") | |
| def test_stale_cache_used_on_fetch_failure(self): | |
| key = live_data._build_cache_key("lending", ["Spark"]) | |
| self.cache.set_json( | |
| key, | |
| {"payload": {"apy": 0.08, "freshness": "fresh", "source": "defillama"}, "_cached_at": time.time() - 240}, | |
| ttl=live_data._STALE_TTL, | |
| ) | |
| with patch("src.agents.strategy.live_data.lending_adapter", side_effect=RuntimeError("network")): | |
| result = live_data.enrich_live_data("lending", ["Spark"]) | |
| self.assertEqual(result["apy"], 0.08) | |
| self.assertEqual(result["freshness"], "stale") | |
| def test_negative_cache_triggers_static_fallback(self): | |
| key = live_data._build_cache_key("lending", ["Spark"]) | |
| self.cache.set_error(f"{key}:error", {"err": "timeout"}, ttl=live_data._ERROR_TTL) | |
| result = live_data.enrich_live_data("lending", ["Spark"]) | |
| self.assertEqual(result["source"], "static_assumption") | |
| self.assertEqual(result["confidence"], "low") | |
| self.assertIsNotNone(result.get("apy")) | |
| def test_source_failover_to_static_when_no_pool_and_no_protocol_stats(self): | |
| with patch("src.agents.strategy.live_data._fetch_pool_apy", return_value=None), patch( | |
| "src.agents.strategy.live_data._fetch_protocol_stats", side_effect=RuntimeError("boom") | |
| ): | |
| result = live_data.enrich_live_data("lending", ["Spark"]) | |
| self.assertEqual(result["source"], "static_assumption") | |
| self.assertEqual(result["confidence"], "low") | |
| def test_protocol_adapter_map_covers_all_registry_protocols(self): | |
| registry_protocols = set() | |
| for registry_name in ("strategy_registry.avalanche.json", "strategy_registry.base.json"): | |
| registry = json.loads( | |
| Path( | |
| f"/home/inteli/Área de trabalho/projects/panorama/zico_agent/new_zico/src/agents/strategy/{registry_name}" | |
| ).read_text(encoding="utf-8") | |
| ) | |
| registry_protocols.update({p for s in registry for p in s.get("protocols", [])}) | |
| adapter_protocols = set(live_data._PROTOCOL_ADAPTERS.keys()) | |
| self.assertTrue(registry_protocols.issubset(adapter_protocols)) | |
| def test_multi_protocol_strategy_selects_best_apy(self): | |
| with patch( | |
| "src.agents.strategy.live_data._PROTOCOL_ADAPTERS", | |
| { | |
| "Hypha": lambda _network: { | |
| "apy": 0.07, | |
| "tvl": 1000.0, | |
| "capacity": "ok", | |
| "risk_flags": [], | |
| "as_of": "now", | |
| "source": "defillama", | |
| "freshness": "fresh", | |
| "warning": None, | |
| "confidence": "high", | |
| }, | |
| "Euler V2": lambda _network: { | |
| "apy": 0.05, | |
| "tvl": 2000.0, | |
| "capacity": "ok", | |
| "risk_flags": [], | |
| "as_of": "now", | |
| "source": "defillama", | |
| "freshness": "fresh", | |
| "warning": None, | |
| "confidence": "high", | |
| }, | |
| }, | |
| ): | |
| result = live_data.enrich_live_data("structured", ["Hypha", "Euler V2"]) | |
| self.assertEqual(result["protocol"], "Hypha") | |
| self.assertEqual(result["apy"], 0.07) | |
| if __name__ == "__main__": | |
| unittest.main() | |