Public security notice: This documentation is intentionally redacted. Sensitive server paths, private keys, secret tokens, and origin network details are removed.
Core Engine & Workflow¶
This page describes how the engine orchestrates a full DeFi token risk assessment, from command-line entrypoint to final reports.
The reference implementation lives primarily in:
scripts/engine/defi_complete_risk_assessment_clean.py
Dashboard helpers plug into the same data directories and report outputs.
High-level flow¶
At a high level, a full run does the following:
- Initializes environment and paths
- Determines
PROJECT_ROOT,DATA_DIR,LOGS_DIR. - Ensures these directories exist.
-
Sets timestamped paths such as:
RISK_REPORT_DIREXCEL_REPORT_PATH,RISK_REPORT_JSON,RISK_REPORT_CSV*_LATESTaliases for dashboards.
-
Initializes shared services
- Optional
cache_managerfromcache_manager.get_cache_manager(DATA_DIR) - Optional
error_handlerfromapi_error_handler.get_error_handler(DATA_DIR) SharedAPISchedulerwith a global worker pool (per-API caps live inAPIErrorHandler)-
HTTP request state and rate-limit tracking structures.
-
Loads configuration and datasets
- Token universe from
DATA_DIR/tokens.csv. - Fallback definitions from
DATA_DIR/fallbacks/fallbacks.json. - Token Data Viewer snapshot from
DATA_DIR/token_data_viewer.csv. - EU-mode configuration and regulated stablecoin allow-list.
-
Caching and request policy from
DATA_DIR/settings.json. -
Processes tokens in batches
-
For each token (address + symbol + chain), the engine:
- Builds a per-token context (chain, symbol, tags, maybe allow-list status).
- Submits many data-fetch tasks through the shared scheduler.
- Applies caching and rate-limit-aware HTTP logic.
- Normalizes responses into an internal
token_entrystructure.
-
Calculates scores and red flags
- Derives component quality scores (1–10) for behavioral categories.
- Converts them into risk contributions (0–10) using weights.
- Applies red-flag boosts and market-structure penalties.
-
Aggregates into a final risk score and credibility signals.
-
Persists reports
- Writes JSON, CSV and XLSX reports to timestamped files.
- Updates
*_latestaliases for dashboards and downstream tooling. - Optionally generates a social score analysis report.
SharedAPIScheduler & concurrency model¶
The engine avoids per-token thread pools and instead uses a shared scheduler so that concurrency limits are enforced globally.
Key object, SharedAPIScheduler in
scripts/engine/defi_complete_risk_assessment_clean.py (simplified):
```python class SharedAPIScheduler: def init(self, max_workers: int = 12, api_caps: Optional[Dict[str, int]] = None) -> None: self.max_workers = max(1, int(max_workers)) self.executor = ThreadPoolExecutor(max_workers=self.max_workers) self.api_caps: Dict[str, int] = dict(api_caps or {}) self._semaphores = { str(api).lower(): threading.BoundedSemaphore(max(1, int(cap))) for api, cap in self.api_caps.items() }
def submit(self, api_name: str, fn: Callable[..., Any], *args, **kwargs):
...
return self.executor.submit(wrapped)
```
Usage pattern:
- Heavy data-fetch tasks call
get_shared_api_scheduler().submit("service_name", fn, ...). - The scheduler enforces a global thread limit (
max_workers). It can also hold per-service semaphores in_semaphores, butget_shared_api_scheduler()builds the shared instance with an emptyAPI_CONCURRENCY_CAPS: per-API concurrency caps are enforced centrally byAPIErrorHandlerinscripts/engine/api_error_handler.pyinstead.
Why this matters¶
- Prevents nested executors from oversubscribing CPU/network.
- Keeps per-API concurrency caps in one place, so providers that throttle aggressively stay capped even when many tokens are processed at once.
- Keeps CPU and I/O usage more predictable in production environments.
Token processing lifecycle¶
Conceptually, each token goes through the following stages:
- Discovery: read from
tokens.csv(address, symbol, chain, labels). - Bootstrap: attach cached viewer/fallback data if available.
- Data fetch: schedule multiple API calls through the scheduler.
- Normalization: consolidate raw responses into a uniform internal model.
- Scoring: compute behavioral component scores and overall risk.
- Persistence: write to JSON/CSV/XLSX and, optionally, social reports.
The implementation is structured so that the scoring pipeline can be reused with different data sources (e.g. live-only vs. cache-heavy modes) without changing the core model.
Cache manager and error handler integration¶
Two plug-in style components enhance the core script:
- cache_manager – centralizes cache operations and policies.
- error_handler – manages per-service health, cooldowns and error logging.
When available, cache_manager is preferred over the legacy JSON cache helpers.
The engine module initializes it once the data and log directories exist:
python
try:
from cache_manager import get_cache_manager
cache_manager = get_cache_manager(DATA_DIR)
print("✅ Enhanced cache manager initialized")
except ImportError:
print("⚠️ Enhanced cache manager not available, using basic cache")
cache_manager = None
Similarly, the enhanced API error handler is loaded right after it, if present:
python
try:
from api_error_handler import get_error_handler
error_handler = get_error_handler(DATA_DIR)
print("✅ Enhanced API error handler initialized")
except ImportError:
print("⚠️ Enhanced API error handler not available, using basic error handling")
error_handler = None
If these modules are not importable, the engine falls back to embedded basic cache and error-handling logic.
Where to go next¶
- See Data Fetching & Caching for a deep dive into HTTP handling, rate limits and cache layout.
- See Scoring Model & Categories for how token entries are turned into numeric scores and red flags.