NEMESIS TRACER v2.0

WebSocket Initialization RealtimeManagerDO

The user configures a target on the UI and executes the trace. The frontend establishes a secure WebSocket connection to the Durable Object and sends the initial trace parameters.

Client Action

The investigator inputs the target address (e.g., 0x3A6JgF...), selects the trace mode (e.g., "Mass Sweep"), and clicks Execute. The UI immediately opens a WS channel.

ws_payload.json
{
  "type": "START_TRACE",
  "seeds": ["0x3A6JgF1JfG7BANTYKizCs2jUCnWrEpd5A8"],
  "network": "ETHEREUM",
  "trace_mode": "mass_sweep",
  "max_depth": 3,
  "trace_direction": "forward"
}

DOM Scraper Engine Cloudflare Browser

Before querying the blockchain, the engine spawns a Headless Puppeteer instance via Cloudflare Browser Rendering to scrape Block Explorers (like OKLink) for undocumented entity tags.

Extraction Logic

The scraper navigates to the OKLink multi-search page, bypassing API rate limits. It explicitly targets the DOM structure looking for the `text-ellipsis` class or the specific XPath requested.


Extracted Label: "Binance 14"
worker.js (excerpt)
const scrapeResult = await env.BROWSER.quickAction("scrape", {
    url: `https://www.oklink.com/multi-search#key=${address}`,
    elements: [
        { selector: ".text-ellipsis" },
        { selector: "/html/body/.../text()[2]" } // User XPath
    ]
});

const targetLabel = scrapeResult.results[0].text.trim();
return targetLabel; // "Binance 14"

Entity Resolution R2 + Cryptologos

Once a raw label like "Binance 14" is scraped, the engine queries the massive R2 Databases bucket to standardize the entity, classify its risk, and attach official high-res UI icons.

Resolution Process

  • Check nemesis-exports/databases/ for matches.
  • Classify "Binance" as EXCHANGE.
  • Generate visual icon URI from Cryptologos API.
  • Dispatch `ENTITY_RESOLVED` event back to user WS.
Entity Object Payload
{
  "type": "ENTITY_RESOLVED",
  "address": "0x3A6Jg...",
  "entityName": "Binance 14",
  "tags": ["CEX", "Custodial"],
  "logoUrl": "https://cryptologos.cc/logos/binance-logo.png",
  "riskScore": 0.2
}

Auto-Ingestion API Waterfall fetchTransactions

The tracing engine must now pull the transaction history. To prevent rate-limits and maximize data depth, it utilizes the Enterprise API Waterfall configuration.

Waterfall Routing Strategy

1. COVALENT API: Attempt deep historical extraction without pagination limits.
2. MORALIS API: If Covalent fails, utilize Moralis for high-speed EVM tracking.
3. EXPLORER API: Fallback to Etherscan/BscScan if enterprise APIs are exhausted.

Routing Logic
if (env.COVALENT_API_KEY) {
    const url = `${env.COVALENT_ENDPOINT}/eth-mainnet/address/${addr}/transactions_v3/`;
    const res = await fetch(url, { headers: { 'Authorization': `Bearer ${env.COVALENT}` }});
    if (res.ok) return formatCovalentData(res);
} 
if (isEvm && env.MORALIS_API_KEY) {
    const url = `${env.MORALIS_ENDPOINT}/${addr}?chain=eth`;
    const res = await fetch(url, { headers: { 'X-API-Key': env.MORALIS }});
    if (res.ok) return formatMoralisData(res);
}

Graph Topology Builder bfsTraverse()

With transactions ingested and entities scraped, the engine recursively loops (Breadth-First Search) up to the target depth, generating the mathematical nodes and edges array.

Graph Generation

The system calculates node sizes (based on txCount) and applies color-coding based on the Risk Score (e.g., Red for Hackers, Green for Clean CEXs). Geometric coordinates (X/Y) are pre-calculated for the frontend canvas.

Output Graph Payload
{
  "nodes": [
    { "id": "eth:0x3A...", "depth": 0, "label": "Victim", "color": "#00cc00" },
    { "id": "eth:0x8B...", "depth": 1, "label": "Binance 14", "color": "#ff6600" }
  ],
  "edges": [
    { "source": "eth:0x3A...", "target": "eth:0x8B...", "value": 45.5 }
  ]
}

AI Rotation Swarm Gemini 2.5 Pro

Before finalizing the trace, the raw graph JSON is sent to the LLM orchestration layer. The rotating API key engine assigns a Gemini model to analyze the topological structure for laundering patterns.

Heuristic Audit

The `getRotatedGeminiAI()` function dynamically swaps between keys and models (Gemini 2.5 Flash vs Pro). It identifies Peel Chains, Wash Trading, and Smurfing behaviors based on edge weights.

AI Orchestration Logic
function getRotatedGeminiAI(env) {
    const keys = env.GEMINI_API_KEYS.split(',');
    const key = keys[Math.floor(Math.random() * keys.length)];
    
    let model = 'gemini-2.5-flash';
    if (env.AI_ROTATION_ENABLED === 'true') {
        model = 'gemini-2.5-pro'; // Heavy analysis
    }
    return { ai: new GoogleGenAI({ apiKey: key }), model };
}

Frontend Delivery WebSockets

The server terminates the Durable Object lifecycle by streaming the final AI Insights, the Graph payload, and the `COMPLETE` event back to the browser UI.

Render Canvas

The frontend D3.js or Force Graph engine intercepts the WebSocket payload, renders the nodes with the Cryptologos icons, and paints the heuristic AML insights onto the side panel.


Trace Completed Successfully.
Final WS Event
try {
    ws.send(JSON.stringify({
        type: "FINAL_GRAPH",
        data: finalGraphData,
        ai_insights: geminiReport
    }));
    
    ws.send(JSON.stringify({ type: "COMPLETE" }));
} catch(e) {
    console.error("Socket disconnected");
}