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)
94 lines
3.5 KiB
Python
94 lines
3.5 KiB
Python
"""Repository - async data fetch for token info via Databus."""
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from app.core.logging import get_logger
|
|
from app.domains.token.models import (
|
|
TokenDetail,
|
|
TokenHolder,
|
|
TokenLiquidity,
|
|
)
|
|
|
|
log = get_logger(__name__)
|
|
|
|
|
|
class TokenRepository:
|
|
"""Async data access for token info via Databus."""
|
|
|
|
async def get_detail(self, address: str, chain: str) -> TokenDetail:
|
|
"""Fetch token metadata + supply."""
|
|
try:
|
|
from app.databus.client import get_databus_client
|
|
|
|
client = get_databus_client()
|
|
raw = await client.get_token_info(address, chain=chain)
|
|
return self._parse_detail(address, chain, raw or {})
|
|
except Exception as e:
|
|
log.warning("token_detail_fetch_failed", address=address[:12], error=str(e))
|
|
return TokenDetail(address=address, chain=chain)
|
|
|
|
async def get_holders(
|
|
self,
|
|
address: str,
|
|
chain: str,
|
|
limit: int = 100,
|
|
) -> list[TokenHolder]:
|
|
"""Fetch top holders."""
|
|
try:
|
|
from app.databus.client import get_databus_client
|
|
|
|
client = get_databus_client()
|
|
raw = await client.get_token_holders(address, chain=chain, limit=limit)
|
|
return [self._parse_holder(h) for h in (raw or [])]
|
|
except Exception as e:
|
|
log.warning("token_holders_fetch_failed", address=address[:12], error=str(e))
|
|
return []
|
|
|
|
async def get_liquidity(self, address: str, chain: str) -> TokenLiquidity:
|
|
"""Fetch liquidity + pool info."""
|
|
try:
|
|
from app.databus.client import get_databus_client
|
|
|
|
client = get_databus_client()
|
|
raw = await client.get_token_liquidity(address, chain=chain)
|
|
return self._parse_liquidity(address, chain, raw or {})
|
|
except Exception as e:
|
|
log.warning("token_liquidity_fetch_failed", address=address[:12], error=str(e))
|
|
return TokenLiquidity(address=address, chain=chain)
|
|
|
|
@staticmethod
|
|
def _parse_detail(address: str, chain: str, raw: dict[str, Any]) -> TokenDetail:
|
|
return TokenDetail(
|
|
address=address,
|
|
chain=chain,
|
|
name=raw.get("name", ""),
|
|
symbol=raw.get("symbol", ""),
|
|
decimals=int(raw.get("decimals", 9) or 9),
|
|
total_supply=float(raw.get("total_supply", 0) or 0),
|
|
circulating_supply=float(raw.get("circulating_supply", 0) or 0),
|
|
holders=int(raw.get("holders", 0) or 0),
|
|
verified=bool(raw.get("verified", False)),
|
|
metadata=raw.get("metadata", {}) or {},
|
|
)
|
|
|
|
@staticmethod
|
|
def _parse_holder(raw: dict[str, Any]) -> TokenHolder:
|
|
return TokenHolder(
|
|
address=raw.get("address", ""),
|
|
balance=float(raw.get("balance", 0) or 0),
|
|
percentage=float(raw.get("percentage", raw.get("pct", 0)) or 0),
|
|
label=raw.get("label"),
|
|
is_contract=bool(raw.get("is_contract", False)),
|
|
is_locked=bool(raw.get("is_locked", False)),
|
|
)
|
|
|
|
@staticmethod
|
|
def _parse_liquidity(address: str, chain: str, raw: dict[str, Any]) -> TokenLiquidity:
|
|
return TokenLiquidity(
|
|
address=address,
|
|
chain=chain,
|
|
total_liquidity_usd=float(raw.get("total_usd", 0) or 0),
|
|
pools=raw.get("pools", []) or [],
|
|
locked_percentage=float(raw.get("locked_percentage", 0) or 0),
|
|
)
|