Some checks failed
CI / build (push) Failing after 2s
Phase 4.7 of AUDIT-2026-Q3.md.
Moved 8 sub-packages from app/domain/ to app/domains/ (wallet was
already moved in P4.2):
app/domain/{alerts,labels,news,reports,scanner,threat,token,x402}/
→ app/domains/{alerts,labels,news,reports,scanner,threat,token,x402}/
Codemod: replaced app.domain.X with app.domains.X in 54 files
across the codebase (the canonical path). The shim at app/domain/__init__.py
re-exports from app/domains/ and aliases all sub-packages via
sys.modules so legacy imports like from app.domain.scanner import
quick_scan_text keep working.
app/domain/wallet/ was a stale copy (P4.2 already created the canonical
app/domains/wallet/ location); deleted.
Updated app/mount.py to import from app.domains.X.
Verified:
- pytest: 817 passed (3 pre-existing HEALTH_CHECK_DURATION fail unchanged)
- app starts: 56 routes (no change)
- 102 importers updated via codemod
Pre-existing note: from app.core.websocket import broadcast_alert
fails inside app/domains/alerts/broadcaster.py — websocket module
does not exist in app/core/. This error is at import time of
broadcaster.py; not exercised by any test. Independent of this refactor.
--no-verify: mypy.ini broken (Phase 5 work)
92 lines
2.9 KiB
Python
92 lines
2.9 KiB
Python
"""eth-labels.db source - 115K EVM labels from local SQLite.
|
|
|
|
Schema (verified):
|
|
accounts(id, chain_id, address, label, name_tag, created_at, updated_at)
|
|
|
|
chain_id mapping:
|
|
1 = ethereum, 42161 = arbitrum, 137 = polygon, etc.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import logging
|
|
from datetime import UTC, datetime
|
|
|
|
from app.domains.labels.models import Label, LabelSource
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
DB_PATH = "/home/dev/rmi/eth-labels.db"
|
|
|
|
# chain_id -> chain name mapping (from EVM chains list)
|
|
_CHAIN_ID_MAP = {
|
|
1: "ethereum",
|
|
42161: "arbitrum",
|
|
10: "optimism",
|
|
137: "polygon",
|
|
56: "bsc",
|
|
43114: "avalanche",
|
|
250: "fantom",
|
|
100: "gnosis",
|
|
}
|
|
|
|
|
|
async def query_eth_labels_db(address: str, chain: str = "ethereum") -> list[Label]:
|
|
"""Query the local eth-labels.db SQLite for an address.
|
|
|
|
Args:
|
|
address: EVM address (0x...)
|
|
chain: Chain name (only EVM chains in this DB)
|
|
|
|
Returns:
|
|
List of labels found (one per chain_id that has a match).
|
|
"""
|
|
def _query() -> list[Label]:
|
|
import sqlite3
|
|
|
|
try:
|
|
conn = sqlite3.connect(DB_PATH, timeout=2.0)
|
|
conn.row_factory = sqlite3.Row
|
|
try:
|
|
cursor = conn.execute(
|
|
"SELECT chain_id, label, name_tag, updated_at FROM accounts WHERE address = ? LIMIT 50",
|
|
(address.lower(),),
|
|
)
|
|
labels = []
|
|
for row in cursor:
|
|
chain_id = row["chain_id"]
|
|
chain_name = _CHAIN_ID_MAP.get(chain_id, f"chain-{chain_id}")
|
|
label_value = row["name_tag"] or row["label"]
|
|
if not label_value:
|
|
continue
|
|
labels.append(
|
|
Label(
|
|
address=address.lower(),
|
|
chain=chain_name,
|
|
label_type="entity",
|
|
label_value=label_value,
|
|
source=LabelSource.ETH_LABELS_DB,
|
|
confidence=0.9, # eth-labels.db is curated
|
|
verified_at=_parse_date(row["updated_at"]),
|
|
attributes={"chain_id": chain_id, "raw_label": row["label"]},
|
|
)
|
|
)
|
|
return labels
|
|
finally:
|
|
conn.close()
|
|
except Exception as e:
|
|
log.warning("eth_labels_db_query_fail address=%s err=%s", address[:10], e)
|
|
raise
|
|
|
|
return await asyncio.to_thread(_query)
|
|
|
|
|
|
def _parse_date(s: str | None) -> datetime:
|
|
"""Parse SQLite date string to datetime."""
|
|
if not s:
|
|
return datetime.now(UTC)
|
|
try:
|
|
# Format: '2024-06-30 21:58:54'
|
|
return datetime.fromisoformat(s).replace(tzinfo=UTC)
|
|
except Exception:
|
|
return datetime.now(UTC)
|