- Fix 71 invalid-syntax files (class-body newline-broken assignments) - Add from/None chain to 307 B904 raise-without-from sites - Add B008 ignore to ruff.toml (already in pyproject.toml) - Noqa F401 on __init__.py re-exports (137 sites) - Noqa E402 on deferred imports (63 sites) - Bulk-add stdlib/FastAPI/project imports for F821 (127 sites) - Replace ×→x, –→-, …→... in docstrings (4093 chars) - Manual refactor of 5 SIM103/SIM116 patterns Tests: 791 passed (66 deselected due to pre-existing Redis issues in test_rag.py) Co-authored-by: opencode <opencode@rugmunch.io>
317 lines
11 KiB
Python
317 lines
11 KiB
Python
"""Deep Intelligence Router - 12 Unaccounted Features API
|
|
|
|
Endpoints for:
|
|
1. Deployer Reputation Score
|
|
2. Pre-flight Transaction Simulator
|
|
3. Liquidity Lock Authenticity
|
|
4. Volume Authenticity Engine
|
|
5. Slow Rug Detector
|
|
6. Funding Source Tracer
|
|
7. Ownership Theater Detector
|
|
8. Exit Liquidity Calculator
|
|
9. Token Lifespan Predictor
|
|
10. Post-Purchase Monitor
|
|
11. Cross-Chain Identity Resolution
|
|
12. Social-Onchain Correlation
|
|
+ Composite full report
|
|
"""
|
|
|
|
import logging
|
|
|
|
from fastapi import APIRouter, HTTPException, Query
|
|
|
|
from app.services.deep_intelligence import (
|
|
cross_chain_identity,
|
|
deployer_reputation,
|
|
exit_liquidity_calculator,
|
|
full_deep_intel,
|
|
funding_source_tracer,
|
|
liquidity_lock_authenticity,
|
|
ownership_theater_detector,
|
|
post_purchase_monitor,
|
|
preflight_simulate,
|
|
slow_rug_detector,
|
|
social_onchain_correlation,
|
|
token_lifespan_predictor,
|
|
volume_authenticity,
|
|
)
|
|
|
|
logger = logging.getLogger("deep_intel_router")
|
|
|
|
router = APIRouter(prefix="/api/v1/deep-intel", tags=["deep-intelligence"])
|
|
|
|
SUPPORTED_CHAINS = ["sol", "eth", "bsc", "base", "arb", "polygon", "avax"]
|
|
|
|
|
|
# ── Health ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
@router.get("/health")
|
|
async def health():
|
|
return {
|
|
"status": "healthy",
|
|
"service": "deep-intelligence",
|
|
"features": [
|
|
"deployer_reputation",
|
|
"preflight_simulation",
|
|
"liquidity_lock_authenticity",
|
|
"volume_authenticity",
|
|
"slow_rug_detector",
|
|
"funding_source_tracer",
|
|
"ownership_theater",
|
|
"exit_liquidity",
|
|
"lifespan_predictor",
|
|
"post_purchase_monitor",
|
|
"cross_chain_identity",
|
|
"social_onchain_correlation",
|
|
"full_report",
|
|
],
|
|
}
|
|
|
|
|
|
# ── 1. Deployer Reputation Score ──────────────────────────────────────
|
|
|
|
|
|
@router.get("/deployer/{address}")
|
|
async def api_deployer_reputation(
|
|
address: str,
|
|
chain: str = Query("sol", enum=SUPPORTED_CHAINS),
|
|
):
|
|
"""Track EVERY token a deployer wallet has created across ALL chains."""
|
|
try:
|
|
result = await deployer_reputation(address, chain)
|
|
return result
|
|
except Exception as e:
|
|
logger.error(f"Deployer reputation error: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
|
|
|
|
# ── 2. Pre-flight Transaction Simulator ────────────────────────────────
|
|
|
|
|
|
@router.get("/preflight/{token_address}")
|
|
async def api_preflight_simulate(
|
|
token_address: str,
|
|
wallet: str = Query("0x0000000000000000000000000000000000000000"),
|
|
amount_usd: float = Query(100, ge=1, le=1000000),
|
|
chain: str = Query("sol", enum=SUPPORTED_CHAINS),
|
|
):
|
|
"""Simulate buy AND sell to show real costs, slippage, taxes, net P&L."""
|
|
try:
|
|
result = await preflight_simulate(token_address, wallet, amount_usd, chain)
|
|
return result
|
|
except Exception as e:
|
|
logger.error(f"Preflight simulation error: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
|
|
|
|
# ── 3. Liquidity Lock Authenticity ────────────────────────────────────
|
|
|
|
|
|
@router.get("/liquidity-lock/{token_address}")
|
|
async def api_liquidity_lock(
|
|
token_address: str,
|
|
chain: str = Query("sol", enum=SUPPORTED_CHAINS),
|
|
):
|
|
"""Analyze liquidity lock authenticity - not just 'is it locked?' but meaningful analysis."""
|
|
try:
|
|
result = await liquidity_lock_authenticity(token_address, chain)
|
|
return result
|
|
except Exception as e:
|
|
logger.error(f"Liquidity lock error: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
|
|
|
|
# ── 4. Volume Authenticity Engine ──────────────────────────────────────
|
|
|
|
|
|
@router.get("/volume-authenticity/{token_address}")
|
|
async def api_volume_authenticity(
|
|
token_address: str,
|
|
chain: str = Query("sol", enum=SUPPORTED_CHAINS),
|
|
):
|
|
"""Detect wash trading, fake volume, bot vs organic trading."""
|
|
try:
|
|
result = await volume_authenticity(token_address, chain)
|
|
return result
|
|
except Exception as e:
|
|
logger.error(f"Volume authenticity error: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
|
|
|
|
# ── 5. Slow Rug Detector ──────────────────────────────────────────────
|
|
|
|
|
|
@router.get("/slow-rug/{token_address}")
|
|
async def api_slow_rug_detector(
|
|
token_address: str,
|
|
chain: str = Query("sol", enum=SUPPORTED_CHAINS),
|
|
):
|
|
"""Detect gradual LP removal, fee increases, slow ownership transfers."""
|
|
try:
|
|
result = await slow_rug_detector(token_address, chain)
|
|
return result
|
|
except Exception as e:
|
|
logger.error(f"Slow rug detector error: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
|
|
|
|
# ── 6. Funding Source Tracer ──────────────────────────────────────────
|
|
|
|
|
|
@router.get("/funding-source/{address}")
|
|
async def api_funding_source(
|
|
address: str,
|
|
chain: str = Query("sol", enum=SUPPORTED_CHAINS),
|
|
):
|
|
"""Trace where wallets got their initial ETH/SOL. Detect CEX, mixers, fresh wallets."""
|
|
try:
|
|
result = await funding_source_tracer(address, chain)
|
|
return result
|
|
except Exception as e:
|
|
logger.error(f"Funding source error: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
|
|
|
|
# ── 7. Ownership Theater Detector ─────────────────────────────────────
|
|
|
|
|
|
@router.get("/ownership-theater/{token_address}")
|
|
async def api_ownership_theater(
|
|
token_address: str,
|
|
chain: str = Query("sol", enum=SUPPORTED_CHAINS),
|
|
):
|
|
"""Detect fake renunciation: hidden admin roles, upgradeable proxies, remaining privileges."""
|
|
try:
|
|
result = await ownership_theater_detector(token_address, chain)
|
|
return result
|
|
except Exception as e:
|
|
logger.error(f"Ownership theater error: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
|
|
|
|
# ── 8. Exit Liquidity Calculator ──────────────────────────────────────
|
|
|
|
|
|
@router.get("/exit-liquidity/{token_address}")
|
|
async def api_exit_liquidity(
|
|
token_address: str,
|
|
position_usd: float = Query(1000, ge=1, le=10000000),
|
|
chain: str = Query("sol", enum=SUPPORTED_CHAINS),
|
|
):
|
|
"""Can you actually sell? Depth analysis, cascade simulation, recovery rate."""
|
|
try:
|
|
result = await exit_liquidity_calculator(token_address, position_usd, chain)
|
|
return result
|
|
except Exception as e:
|
|
logger.error(f"Exit liquidity error: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
|
|
|
|
# ── 9. Token Lifespan Predictor ────────────────────────────────────────
|
|
|
|
|
|
@router.get("/lifespan/{token_address}")
|
|
async def api_lifespan_predictor(
|
|
token_address: str,
|
|
chain: str = Query("sol", enum=SUPPORTED_CHAINS),
|
|
):
|
|
"""AI-driven survival analysis. Predict 7d/30d/90d survival probability."""
|
|
try:
|
|
result = await token_lifespan_predictor(token_address, chain)
|
|
return result
|
|
except Exception as e:
|
|
logger.error(f"Lifespan predictor error: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
|
|
|
|
# ── 10. Post-Purchase Monitor ─────────────────────────────────────────
|
|
|
|
|
|
@router.get("/post-purchase/{token_address}")
|
|
async def api_post_purchase_monitor(
|
|
token_address: str,
|
|
chain: str = Query("sol", enum=SUPPORTED_CHAINS),
|
|
):
|
|
"""Live risk monitoring - detect contract changes, fee increases, liquidity drops."""
|
|
try:
|
|
result = await post_purchase_monitor(token_address, chain)
|
|
return result
|
|
except Exception as e:
|
|
logger.error(f"Post purchase monitor error: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
|
|
|
|
# ── 11. Cross-Chain Identity Resolution ────────────────────────────────
|
|
|
|
|
|
@router.get("/cross-chain/{address}")
|
|
async def api_cross_chain_identity(
|
|
address: str,
|
|
chain: str = Query("sol", enum=SUPPORTED_CHAINS),
|
|
):
|
|
"""Same entity, multiple chains. Detect deployer patterns across chains."""
|
|
try:
|
|
result = await cross_chain_identity(address, chain)
|
|
return result
|
|
except Exception as e:
|
|
logger.error(f"Cross-chain identity error: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
|
|
|
|
# ── 12. Social-Onchain Correlation ─────────────────────────────────────
|
|
|
|
|
|
@router.get("/social-correlation/{token_address}")
|
|
async def api_social_onchain_correlation(
|
|
token_address: str,
|
|
chain: str = Query("sol", enum=SUPPORTED_CHAINS),
|
|
):
|
|
"""Map hype cycle: wallet activity vs social mentions. Coordinated pump detection."""
|
|
try:
|
|
result = await social_onchain_correlation(token_address, chain)
|
|
return result
|
|
except Exception as e:
|
|
logger.error(f"Social correlation error: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
|
|
|
|
# ── COMPOSITE: Full Deep Intelligence Report ────────────────────────────
|
|
|
|
|
|
@router.get("/full-report/{token_address}")
|
|
async def api_full_report(
|
|
token_address: str,
|
|
chain: str = Query("sol", enum=SUPPORTED_CHAINS),
|
|
wallet: str | None = Query(None),
|
|
):
|
|
"""Run ALL 12 intelligence modules and produce a composite deep intel report."""
|
|
try:
|
|
result = await full_deep_intel(token_address, chain, wallet)
|
|
return result
|
|
except Exception as e:
|
|
logger.error(f"Full deep intel error: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
|
|
|
|
# ── Batch: Multiple tokens at once ────────────────────────────────────
|
|
|
|
|
|
@router.post("/batch-report")
|
|
async def api_batch_report(
|
|
tokens: list[dict],
|
|
chain: str = Query("sol", enum=SUPPORTED_CHAINS),
|
|
):
|
|
"""Run deep intel on multiple tokens. Body: [{"address": "0x..."}, ...]"""
|
|
from app.services.deep_intelligence import full_deep_intel
|
|
|
|
results = []
|
|
for token in tokens[:10]: # Max 10 tokens per batch
|
|
addr = token.get("address", "")
|
|
if addr:
|
|
try:
|
|
report = await full_deep_intel(addr, chain)
|
|
results.append(report)
|
|
except Exception as e:
|
|
results.append({"address": addr, "error": str(e)})
|
|
return {"results": results, "count": len(results)}
|