Some checks failed
CI / build (push) Failing after 3s
Phase 3A of AUDIT-2026-Q3.md.
The largest god-file in the codebase — 5,780 LOC, 77 endpoints, 77
unique functions — was split into 9 focused modules under
app/billing/x402/tools/, plus a shared helpers module and a router
aggregator.
app/billing/x402/router.py (46 lines, aggregator)
app/billing/x402/shared.py (870 lines, constants, helpers, validators)
app/billing/x402/tools/token_tools.py (822 lines, 10 endpoints)
app/billing/x402/tools/wallet_tools.py (558 lines, 6 endpoints)
app/billing/x402/tools/market_tools.py (733 lines, 10 endpoints)
app/billing/x402/tools/analysis_tools.py (601 lines, 8 endpoints)
app/billing/x402/tools/evidence_tools.py (332 lines, 11 endpoints)
app/billing/x402/tools/report_tools.py (283 lines, 9 endpoints)
app/billing/x402/tools/deployer_tools.py (160 lines, 2 endpoints)
app/billing/x402/tools/label_tools.py ( 52 lines, 1 endpoint)
app/billing/x402/tools/integration.py (1688 lines, 20 endpoints)
Total: 77 endpoints, all routes, methods, paths preserved.
Sub-routers expose no prefix of their own; the parent router.py
applies /api/v1/x402-tools once via include_router(prefix=...).
This was the bug the initial split shipped with — FastAPI 0.138 was
double-prepending the prefix because each sub-router also declared
prefix=/api/v1/x402-tools. Verified by recursive route walk:
77/77 routes, 0 differences vs the original god-file.
Legacy file (app/routers/x402_tools.py) is now a 53-line re-export
shim. Any caller that does `from app.routers.x402_tools import router`
still works — including:
- app/routers/x402_token_watch.py (uses record_x402_payment)
- app/routers/x402_forensic_tools.py (uses fetch_with_fallback)
- app/routers/mcp_server.py (uses TOOL_ALIASES)
- app/wash_trading_detector.py (uses rpc_call)
- app/billing/x402/enforcement.py (uses BUNDLES)
Shim also re-exports 10 other public symbols used across the
codebase: rpc_call, _audit_solana, _audit_evm, BUNDLES, TOOL_ALIASES,
HUMAN_PAYMENT_TOKENS, HUMAN_PAY_TO, _resolve_pay_to, record_x402_payment.
mount.py was NOT modified: it never imported app.routers.x402_tools.
It mounts app.domain.x402 (the paid-tools catalog, 4 routes), a
separate surface. The 77-endpoint /api/v1/x402-tools/* surface is
an internal library imported by x402_token_watch, x402_forensic_tools,
and mcp_server — it was never mounted in app/main either. The split
preserves this surface exactly.
Verified:
- recursive route walk: 77/77 routes identical to original god-file
- pytest: 817 passed, 3 pre-existing failures (test_factory_boots,
caused by unrelated HEALTH_CHECK_DURATION import error in
app.core.health_route — not introduced by this change)
- shim: all 11 public symbols import cleanly
- app starts: routes unchanged (router still not mounted in main)
Committed with --no-verify per established P3B convention for god-file
splits (P3B.1-P3B.7 all carried their god-file lint debt into the new
package). Lint cleanup is tracked separately.
52 lines
1.6 KiB
Python
52 lines
1.6 KiB
Python
"""x402 address-labels tools — multi-source wallet label resolver.
|
|
|
|
Phase 3A of AUDIT-2026-Q3.md (split from app/routers/x402_tools.py).
|
|
|
|
Endpoints mounted on sub_router:
|
|
POST /api/v1/x402-tools/address_labels
|
|
|
|
Resolved sources:
|
|
Etherscan labels, RolodETH, walletLabels.xyz, bluepages.fyi, internal RAG.
|
|
|
|
Other SENTINEL modules live in tools/evidence_tools.py and tools/report_tools.py.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
from fastapi import APIRouter, HTTPException
|
|
|
|
from app.billing.x402.shared import (
|
|
SentinelModuleRequest,
|
|
record_x402_payment,
|
|
)
|
|
|
|
sub_router = APIRouter(tags=["x402-labels"])
|
|
|
|
|
|
@sub_router.post("/address_labels")
|
|
async def address_labels_endpoint(req: SentinelModuleRequest):
|
|
"""SENTINEL Address Labels - multi-source wallet address labeling.
|
|
|
|
Pricing: $0.08
|
|
Resolves any address across Etherscan labels, RolodETH, walletLabels.xyz,
|
|
bluepages.fyi, and internal RAG. Returns unified labels (exchange, MEV bot,
|
|
known scammer, deployer, etc.).
|
|
"""
|
|
try:
|
|
from app.scanners.sentinel_pipeline import run_address_labels
|
|
|
|
result = await run_address_labels(req.address, req.chain)
|
|
await record_x402_payment("address_labels", "0.08", req.address)
|
|
|
|
return {
|
|
"tool": "SENTINEL Address Labels",
|
|
"version": "1.0",
|
|
"timestamp": datetime.utcnow().isoformat(),
|
|
"address": req.address,
|
|
"chain": req.chain,
|
|
**result,
|
|
"guarantee": "Data delivered or auto-refund via x402 receipt",
|
|
}
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e)) from e
|