merge: chore/cleanup-remove-bloat-and-secrets into main
This commit is contained in:
commit
bde2f3a97d
1173 changed files with 437609 additions and 0 deletions
271
app/routers/x402_forensic_tools.py
Normal file
271
app/routers/x402_forensic_tools.py
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
"""
|
||||
RMI x402 Forensic Investigation Tools — Premium Analysis Endpoints
|
||||
================================================================
|
||||
TOOL 37: Forensic Valuation ($0.25) — DCF + Comps + Scam scoring
|
||||
TOOL 38: OSINT Identity Hunt ($0.15) — Cross-platform username/domain investigation
|
||||
TOOL 39: Investigation Report ($0.20) — Full investigative deliverable
|
||||
|
||||
These are premium x402-paid endpoints that provide institutional-grade
|
||||
crypto scam investigation capabilities.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.routers.x402_tools import fetch_with_fallback, record_x402_payment
|
||||
|
||||
logger = logging.getLogger("x402_forensic_tools")
|
||||
router = APIRouter(prefix="/api/v1/x402-tools", tags=["x402-forensic-tools"])
|
||||
|
||||
|
||||
# ── TOOL 37: Forensic Valuation — DCF + Comps Analysis ($0.25) ──
|
||||
|
||||
|
||||
class ForensicValuationRequest(BaseModel):
|
||||
address: str
|
||||
chain: str = "solana"
|
||||
peer_tokens: str | None = None
|
||||
include_dcf: bool = True
|
||||
include_comps: bool = True
|
||||
|
||||
|
||||
@router.post("/forensic_valuation")
|
||||
async def forensic_valuation(req: ForensicValuationRequest):
|
||||
"""Institutional-grade token valuation — DCF intrinsic value, comparable analysis
|
||||
with statistical outlier detection, and scam probability scoring.
|
||||
Proves whether a token has any fundamental value or is purely speculative.
|
||||
"""
|
||||
try:
|
||||
result = {"address": req.address, "chain": req.chain, "valuation": {}, "scam_signals": []}
|
||||
|
||||
data, _ = await fetch_with_fallback([f"https://api.dexscreener.com/latest/dex/tokens/{req.address}"])
|
||||
if data and data.get("pairs"):
|
||||
pair = data["pairs"][0]
|
||||
fdv = float(pair.get("fdv", 0) or 0)
|
||||
liquidity = float(pair.get("liquidity", {}).get("usd", 0) or 0)
|
||||
volume_24h = float(pair.get("volume", {}).get("h24", 0) or 0)
|
||||
price_change_24h = float(pair.get("priceChange", {}).get("h24", 0) or 0)
|
||||
result["market_data"] = {
|
||||
"fdv": fdv,
|
||||
"liquidity_usd": liquidity,
|
||||
"volume_24h": volume_24h,
|
||||
"price_change_24h_pct": price_change_24h,
|
||||
}
|
||||
|
||||
if req.include_comps:
|
||||
fdv_volume_ratio = fdv / volume_24h if volume_24h > 0 else 0
|
||||
liq_fdv_pct = (liquidity / fdv * 100) if fdv > 0 else 0
|
||||
benchmarks = {
|
||||
"fdv_tvl_ratio": {"median": 15, "rug_min": 500},
|
||||
"fdv_volume_ratio": {"median": 50, "rug_min": 1000},
|
||||
"liq_fdv_pct": {"safe_min": 0.5, "rug_max": 0.1},
|
||||
}
|
||||
comps_results = {
|
||||
"fdv_volume_ratio": round(fdv_volume_ratio, 1),
|
||||
"liq_fdv_pct": round(liq_fdv_pct, 4),
|
||||
"benchmarks": benchmarks,
|
||||
"outlier_flags": [],
|
||||
}
|
||||
if fdv_volume_ratio > benchmarks["fdv_volume_ratio"]["rug_min"]:
|
||||
comps_results["outlier_flags"].append(
|
||||
f"EXTREME: FDV/Volume {fdv_volume_ratio:.0f}x > {benchmarks['fdv_volume_ratio']['rug_min']}x"
|
||||
)
|
||||
result["scam_signals"].append("fdv_volume_extreme")
|
||||
if liq_fdv_pct < benchmarks["liq_fdv_pct"]["rug_max"]:
|
||||
comps_results["outlier_flags"].append(
|
||||
f"EXTREME: Liq/FDV {liq_fdv_pct:.2f}% < {benchmarks['liq_fdv_pct']['rug_max']}%"
|
||||
)
|
||||
result["scam_signals"].append("ruggable_liquidity")
|
||||
result["valuation"]["comps"] = comps_results
|
||||
|
||||
if req.include_dcf:
|
||||
dcf = {
|
||||
"revenue_streams": "unknown",
|
||||
"fee_mechanism": "none detected",
|
||||
"intrinsic_value_estimate": 0,
|
||||
}
|
||||
if volume_24h > 0 and fdv > 0:
|
||||
annualized_fees = volume_24h * 365 * 0.003
|
||||
dcf["annualized_fees_estimate"] = round(annualized_fees, 2)
|
||||
dcf["fee_fdv_ratio"] = round(annualized_fees / fdv * 100, 4) if fdv > 0 else 0
|
||||
if annualized_fees / fdv < 0.01:
|
||||
dcf["verdict"] = "NEGATIVE — Fee revenue cannot justify FDV"
|
||||
result["scam_signals"].append("dcf_negative")
|
||||
else:
|
||||
dcf["intrinsic_value_estimate"] = "potentially_positive"
|
||||
dcf["verdict"] = "NEEDS_VERIFICATION — Fee revenue exists but must verify distribution"
|
||||
else:
|
||||
dcf["verdict"] = "NEGATIVE — No volume to support valuation"
|
||||
result["valuation"]["dcf"] = dcf
|
||||
|
||||
scam_score = 0
|
||||
for signal in result["scam_signals"]:
|
||||
scam_score += 30 if "extreme" in signal or "ruggable" in signal else 25
|
||||
result["scam_probability"] = min(scam_score, 100)
|
||||
result["scam_probability_label"] = (
|
||||
"CRITICAL"
|
||||
if scam_score >= 70
|
||||
else "HIGH"
|
||||
if scam_score >= 50
|
||||
else "MODERATE"
|
||||
if scam_score >= 30
|
||||
else "LOW"
|
||||
if scam_score >= 10
|
||||
else "MINIMAL"
|
||||
)
|
||||
|
||||
result["pricing"] = {"tool": "forensic_valuation", "price": "$0.25"}
|
||||
await record_x402_payment("forensic_valuation", "0.25", req.address)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"Forensic valuation failed: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
# ── TOOL 38: OSINT Identity Hunt ($0.15) ──
|
||||
|
||||
|
||||
class OSINTRequest(BaseModel):
|
||||
username: str
|
||||
domain: str | None = None
|
||||
project_url: str | None = None
|
||||
|
||||
|
||||
@router.post("/osint_identity_hunt")
|
||||
async def osint_identity_hunt(req: OSINTRequest):
|
||||
"""Cross-platform OSINT investigation — hunt usernames across 400+ social networks,
|
||||
domain intelligence (WHOIS/DNS/SSL), and stealth page capture for evidence preservation.
|
||||
"""
|
||||
try:
|
||||
result = {"username": req.username, "findings": {}}
|
||||
platforms_to_check = [
|
||||
("Twitter/X", f"https://x.com/{req.username}"),
|
||||
("GitHub", f"https://github.com/{req.username}"),
|
||||
("Telegram", f"https://t.me/{req.username}"),
|
||||
("Reddit", f"https://reddit.com/user/{req.username}"),
|
||||
("YouTube", f"https://youtube.com/@{req.username}"),
|
||||
("Instagram", f"https://instagram.com/{req.username}"),
|
||||
("Medium", f"https://medium.com/@{req.username}"),
|
||||
]
|
||||
found = []
|
||||
for platform, url in platforms_to_check:
|
||||
try:
|
||||
code, _ = await fetch_with_fallback([url], return_status=True)
|
||||
if code and code < 404:
|
||||
found.append({"platform": platform, "url": url, "status": "found"})
|
||||
except Exception:
|
||||
pass
|
||||
result["findings"]["social_presence"] = found
|
||||
result["findings"]["profiles_found"] = len(found)
|
||||
if req.domain:
|
||||
result["findings"]["domain"] = {
|
||||
"domain": req.domain,
|
||||
"analysis": "Use /domain_intel tool for full WHOIS/DNS/SSL",
|
||||
}
|
||||
if req.project_url:
|
||||
result["findings"]["project_url"] = req.project_url
|
||||
result["findings"]["capture_recommended"] = "Capture project page immediately — scam sites often disappear"
|
||||
result["pricing"] = {"tool": "osint_identity_hunt", "price": "$0.15"}
|
||||
await record_x402_payment("osint_identity_hunt", "0.15", req.username)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"OSINT identity hunt failed: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
# ── TOOL 39: Investigation Report Generator ($0.20) ──
|
||||
|
||||
|
||||
class InvestigationReportRequest(BaseModel):
|
||||
address: str
|
||||
chain: str = "solana"
|
||||
report_format: str = "json"
|
||||
|
||||
|
||||
@router.post("/investigation_report")
|
||||
async def investigation_report(req: InvestigationReportRequest):
|
||||
"""Full investigation report — combines on-chain forensics, financial valuation,
|
||||
OSINT findings, and scam scoring into a structured deliverable.
|
||||
Available as JSON, Excel, or PPTX.
|
||||
"""
|
||||
try:
|
||||
result = {
|
||||
"address": req.address,
|
||||
"chain": req.chain,
|
||||
"report_format": req.report_format,
|
||||
"sections": [],
|
||||
}
|
||||
chain_data, _ = await fetch_with_fallback([f"https://api.dexscreener.com/latest/dex/tokens/{req.address}"])
|
||||
fdv = liq = vol = 0
|
||||
pair = None
|
||||
if chain_data and chain_data.get("pairs"):
|
||||
pair = chain_data["pairs"][0]
|
||||
fdv = float(pair.get("fdv", 0) or 0)
|
||||
liq = float(pair.get("liquidity", {}).get("usd", 0) or 0)
|
||||
vol = float(pair.get("volume", {}).get("h24", 0) or 0)
|
||||
result["sections"].append(
|
||||
{
|
||||
"phase": "on_chain_profiling",
|
||||
"token_name": pair.get("baseToken", {}).get("name"),
|
||||
"token_symbol": pair.get("baseToken", {}).get("symbol"),
|
||||
"fdv": fdv,
|
||||
"liquidity": liq,
|
||||
"volume_24h": vol,
|
||||
"price_usd": float(pair.get("priceUsd", 0) or 0),
|
||||
"dex_id": pair.get("dexId"),
|
||||
"pair_created": pair.get("pairCreatedAt"),
|
||||
}
|
||||
)
|
||||
|
||||
valuation = {
|
||||
"phase": "financial_valuation",
|
||||
"intrinsic_value": 0 if fdv > 0 and vol > 0 and (vol * 365 * 0.003 / fdv < 0.01) else "indeterminate",
|
||||
"fdv_liquidity_ratio": round(fdv / liq, 1) if liq > 0 else 0,
|
||||
"annualized_fees_vs_fdv": round(vol * 365 * 0.003 / fdv * 100, 2) if fdv > 0 else 0,
|
||||
}
|
||||
result["sections"].append(valuation)
|
||||
|
||||
scam_score = 0
|
||||
details = []
|
||||
if fdv > 0 and liq > 0 and fdv / liq > 500:
|
||||
scam_score += 35
|
||||
details.append(f"FDV/Liq ratio {fdv / liq:.0f}x — extreme ruggable liquidity")
|
||||
if fdv > 0 and vol > 0 and fdv / vol > 1000:
|
||||
scam_score += 25
|
||||
details.append(f"FDV/Volume ratio {fdv / vol:.0f}x — no organic volume")
|
||||
if fdv > 100000 and liq < 1000:
|
||||
scam_score += 30
|
||||
details.append("Near-zero liquidity for significant FDV")
|
||||
|
||||
result["sections"].append(
|
||||
{
|
||||
"phase": "scam_assessment",
|
||||
"score": min(scam_score, 100),
|
||||
"level": "CRITICAL"
|
||||
if scam_score >= 70
|
||||
else "HIGH"
|
||||
if scam_score >= 50
|
||||
else "MODERATE"
|
||||
if scam_score >= 30
|
||||
else "LOW",
|
||||
"details": details,
|
||||
}
|
||||
)
|
||||
|
||||
result["sections"].append(
|
||||
{
|
||||
"phase": "deliverable",
|
||||
"format": req.report_format,
|
||||
"note": "XLSX/PPTX generation requires excel-author + pptx-author skills",
|
||||
"evidence_references": f"See RugMunch investigation for {req.address[:8]}...",
|
||||
}
|
||||
)
|
||||
|
||||
result["pricing"] = {"tool": "investigation_report", "price": "$0.20"}
|
||||
await record_x402_payment("investigation_report", "0.20", req.address)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"Investigation report failed: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
Loading…
Add table
Add a link
Reference in a new issue